タイトルの通り、サザンを聴きながらobnizで製作を行なっていたところ、奇妙な挙動を示すようになってしまいました。ちょっと行き詰まってしまったのでご意見いただけると助かります。
IoTセンサーを活用してLINE Botの機能を拡張しようとしています。
#環境・デバイス
obniz Board 1Y
圧電スピーカー
高精度IC温度センサ LM60BIZ
超音波距離センサー HC-SR04
Node.js v16.10.0
Visual Studio Code 1.60.2
#温度と時刻の確認
LINE Bot上で温度と時間をとれるようにしたいと考えましたが、時間を取得する際に挙動がおかしいようです。
#見つめあうと素直におしゃべりできないし、離れるとエボシラインが離れる
また、通常であれば問題なく温度を取得できていましたが、距離によっては挙動がおかしくなるようです。
#あれは?
#サンプルコード
いくつかに分割します。
変数部分
//全体で使う部分
let blnDist = false;
const scData = {
"C4":261.6,
"D4":293.7,
"E4":329.6,
"F4":349.2,
"G4":392.0,
"A4":440.0,
"A#4":466.2,
"B4":493.9,
"C5":523.3,
"C#5":554.4,
"D5":587.3,
"D#5":622.3,
"E5":659.3,
"F5":698.5,
"F#5":740.0,
"G5":784.0,
"A5":880.0,
"B5":987.8
};
obniz処理部分
// ########################################
// obniz処理部分
// ########################################
const Obniz = require('obniz');
const obniz = new Obniz('XXXX-XXXX');
// obnizと接続確立したとき
obniz.onconnect = async () => {
obniz.display.clear();
obniz.display.print('obniz Ready');
}
// 温度センサから値を取得して返す
const getObnizTemp = async () => {
// 温度センサの利用
const tempsens = obniz.wired('LM60', { gnd: 9, output: 10, vcc: 11 });
// 非同期で取得
const temp = await tempsens.getWait();
// ターミナル表示
console.log('obniz temp:', temp);
// 温度値を返す
return temp;
}
//距離センサーから値を取得して返す
const getObnizDist = async () => {
const hcsr04 = obniz.wired('HC-SR04', { gnd: 3, echo: 2, trigger: 1, vcc: 0 });
let distance = await hcsr04.measureWait();
// 整数に丸め
distance = Math.floor(distance);
// 距離(mm)をターミナルに表示
console.log(distance + ' mm');
// 距離を返す
return distance;
}
// 勝手にシンドバッド
const sindibaad = async () => {
const speaker = obniz.wired('Speaker', { signal: 5, gnd: 6 });
speaker.play(scData.E5);await obniz.wait(300);speaker.stop();await obniz.wait(50);
speaker.play(scData.B4);await obniz.wait(150);speaker.stop();await obniz.wait(50);
speaker.play(scData.D5);await obniz.wait(250);speaker.stop();await obniz.wait(50);
speaker.play(scData.D5);await obniz.wait(250);speaker.stop();await obniz.wait(50);
speaker.play(scData.E5);await obniz.wait(700);speaker.stop();await obniz.wait(50);
}
// 希望の轍
const hope = async () => {
const speaker = obniz.wired('Speaker', { signal: 5, gnd: 6 });
speaker.play(scData.B4);await obniz.wait(200);speaker.stop();await obniz.wait(50);
speaker.play(scData['C#5']);await obniz.wait(200);speaker.stop();await obniz.wait(50);
speaker.play(scData.D5);await obniz.wait(1100);speaker.stop();await obniz.wait(50);
speaker.play(scData.E5);await obniz.wait(200);speaker.stop();await obniz.wait(50);
speaker.play(scData['F#5']);await obniz.wait(200);speaker.stop();await obniz.wait(50);
speaker.play(scData.G5);await obniz.wait(1100);speaker.stop();await obniz.wait(50);
speaker.play(scData.B4);await obniz.wait(200);speaker.stop();await obniz.wait(50);
speaker.play(scData.D5);await obniz.wait(200);speaker.stop();await obniz.wait(50);
speaker.play(scData['C#5']);await obniz.wait(1100);speaker.stop();await obniz.wait(50);
speaker.play(scData.D5);await obniz.wait(200);speaker.stop();await obniz.wait(50);
speaker.play(scData.E5);await obniz.wait(200);speaker.stop();await obniz.wait(50);
speaker.play(scData.G5);await obniz.wait(350);speaker.stop();await obniz.wait(50);
speaker.play(scData['F#5']);await obniz.wait(200);speaker.stop();await obniz.wait(50);
speaker.play(scData.E5);await obniz.wait(200);speaker.stop();await obniz.wait(50);
speaker.play(scData['F#5']);await obniz.wait(700);speaker.stop();await obniz.wait(50);
}
// gspot
const gspot = async () => {
const speaker = obniz.wired('Speaker', { signal: 5, gnd: 6 });
speaker.play(scData.B4);await obniz.wait(100);speaker.stop();await obniz.wait(75);
speaker.play(scData.D5);await obniz.wait(100);speaker.stop();await obniz.wait(75);
speaker.play(scData.E5);await obniz.wait(150);speaker.stop();await obniz.wait(400);
speaker.play(scData.G5);await obniz.wait(375);speaker.stop();await obniz.wait(50);
speaker.play(scData.G4);await obniz.wait(375);speaker.stop();await obniz.wait(50);
speaker.play(scData.E4);await obniz.wait(325);speaker.stop();await obniz.wait(50);
speaker.play(scData.G4);await obniz.wait(600);speaker.stop();await obniz.wait(50);
speaker.play(scData.G4);await obniz.wait(200);speaker.stop();await obniz.wait(650);
speaker.play(scData.A4);await obniz.wait(600);speaker.stop();await obniz.wait(50);
speaker.play(scData.A4);await obniz.wait(200);speaker.stop();await obniz.wait(650);
speaker.play(scData.B4);await obniz.wait(600);speaker.stop();await obniz.wait(50);
speaker.play(scData.B4);await obniz.wait(200);speaker.stop();await obniz.wait(600);
}
LINE Bot部分
// ########################################
// LINEBot イベント処理部分
// ########################################
const config = {
channelSecret: 'channelSecret',
channelAccessToken: 'channelAccessToken'
};
const line = require('@line/bot-sdk');
const client = new line.Client(config);
// ExpressからMessaging APIイベントを渡されて処理するところ
const handleEvent = async (event) => {
// テキストメッセージ以外を受信したときは何も行わずresolveを返す
if (event.type !== 'message' || event.message.type !== 'text') {
return Promise.resolve(null);
} else {
if(blnDist){
let dist = await getObnizDist();
if(dist > 200){
hope();
blnDist = false;//距離が前回200以下で、今回離れた場合、希望の轍を長してblnDistをfalseに戻す
} else {
await client.replyMessage(event.replyToken, {
type: 'text',
text: 'べっ、別にあんたのために歌ってるわけじゃないんだからね///'//距離が200以下では見つめあっているので素直におしゃべりできない
});
}
} else {
let dist = await getObnizDist();
if( dist < 200 ){
await client.replyMessage(event.replyToken, {
type: 'text',
text: 'べっ、別にあんたのために歌ってるわけじゃないんだからね///'
});
blnDist = true;//距離が200以下では見つめあっているので素直におしゃべりできない。近づいたフラグをblnDistで立てる。
} else if (event.message.text === '温度教えて') {
// 待ってねというメッセージを「リプライ」で先に返す
await client.replyMessage(event.replyToken, {
type: 'text',
text: '.oO(ちょっと調べてきますねー。)'
});
// obnizの温度センサから値をとってくる(ブロッキング・時間のかかる処理で一旦ここで止まる)
const temp = await getObnizTemp();
// tempが取得できたらそれを含めたメッセージを「プッシュ」で送信する
client.pushMessage(event.source.userId, {
type: 'text',
text: '今の温度は' + temp + '度ですねー。',
});
//距離センサー確認用
} else if (event.message.text === '距離教えて') {
await client.replyMessage(event.replyToken, {
type: 'text',
text: '.oO(ちょっと調べてきますねー。)'
});
// obnizの距離センサから値をとってくる(ブロッキング・時間のかかる処理で一旦ここで止まる)
let dist = await getObnizDist();
// distが取得できたらそれを含めたメッセージを「プッシュ」で送信する
client.pushMessage(event.source.userId, {
type: 'text',
text: '今の距離は' + dist + 'mmですねー。',
});
} else if (event.message.text === '今何時?') {
sindibaad();
} else if (event.message.text === 'あれは?') {
client.replyMessage(event.replyToken, {
type: 'text',
text: 'あれは?'
});
gspot();
} else {
// メッセージの中身が「温度教えて」以外だったとき
client.replyMessage(event.replyToken, {
type: 'text',
text: '温度聞いて!'
});
}
}
}
// resolveを返す
return Promise.resolve(null);
}
// ########################################
// Expressサーバー部分
// ########################################
const express = require('express');
const PORT = process.env.PORT || 3000;
const app = express();
// 「(サーバーURL)/webhook」にアクセス(LINEサーバーからのWebhook)があったとき
app.post('/webhook', line.middleware(config), (req, res) => {
// 受信したイベントをターミナルに表示
console.log(req.body.events);
// イベントをhandleEventに渡して1つずつ処理
Promise.all(
req.body.events.map(handleEvent)
).then(
result => res.json(result)
);
});
// PORT番号のポートでサーバーを開始
app.listen(PORT);
console.log('express runnning: PORT =', PORT);
スピーカー部分のコードについて、何度も同じコードを描くのが嫌だったので、
const sound = async (scale, volume, pose) => {
speaker.play(scale);
await obniz.wait(volume);
speaker.stop();
await obniz.wait(pose);
}
と関数にしてみましたが、うまく動きません。関数の中のawaitに命令が行く前に次の関数に命令が行ってしまうような挙動をとっていました。面倒ですが、一つ一つ記載しましょう。もし、関数にまとめてうまく行く方法あればご教示いただけるとありがたいです。
#結局何ができるのか
温度がわかります。