目的
みなさん、毎日生きづらいですか?ちゃんと懊悩してますか?この世の悩みごとの多くは対人関係から生まれると言いますが、他人との距離感の取り方って難しいですよね。私個人としては他人と距離を置き気味で迷惑をかけることもあるのではと思っているのですが、その自己認識すらずれているかもしれません。悩ましい。
というわけで、友人知人に対して、自分が心地よいと思っている距離感が、果たして客観的に見てどれぐらいなのかをセンサーで図り教えてくれるLINEBotを作ろうと思います。
こちらの42カ国、9000人を対象にしたパーソナルスペースの調査によると、ルーマニアやハンガリーなどは、130センチ以上距離を取り、アルゼンチンやペルーは80センチを下回る超情熱系のインファイターと、国によってもパーソナルスペースにかなり変動があるようです。こちらのデータをもとに、ざっくりと下記のような5つの分類に分けて診断していくことにします。
「人見知り、人間嫌い系」
150cm〜
「クールな東欧系」
120〜149cm
「バランス型の中華・米英系」
90〜119cm
「情熱的な南米系」
70〜89cm
「セクハラパワハラ?系」
〜69cm
実装目標
超音波センサーを積んだオブナイズを、知人や友人に持ってもらい、心地よい距離だと思う位置まで移動し、オーキードーキー博士BOTに「距離感どう?」とLINEで送ると、上記の5分類と距離を教えてくれる、LINEBotの作成を目指します。
環境・デバイス
Node.js v17.6.0
obniz v3.19.1
超音波距離センサー HC−SR04
未完成品
センサーが拾ってくれない…#protoout #obniz pic.twitter.com/4LBV0Vo7GK
— yoshio333 (@yoshio333333) April 14, 2022
ここの分岐でエラーが… pic.twitter.com/HJNfG6XPyR
— yoshio333 (@yoshio333333) April 14, 2022
暫定コード全体 (注:エラーあり)
// ########################################
// obniz処理部分
// Obniz_ID:自分のobniz ID(XXXX-XXXX)
// ########################################
const Obniz = require('obniz');
const obniz = new Obniz('');
// 温度センサから値を取得して返す
const getObnizDistance = async () => {
// 超音波測距センサを利用する
const hcsr04 = obniz.wired('HC-SR04', { gnd: 0, echo: 1, trigger: 2, vcc: 3 });
// 非同期で取得
const distance = await hcsr04.measureWait();
// そのままだと小数点以下の桁数がやたら多いので整数に丸めてもよい
distance = Math.floor(distance);
// ターミナル表示
console.log('obniz distance:', distance);
// obnizディスプレイ表示
obniz.display.clear();
obniz.display.print(distance/10 + 'cm');
// 距離を返す
return distance;
}
// ########################################
// LINEBot イベント処理部分
// channelSecret:LINE Developers → チャネル基本設定 → チャネルシークレット
// channelAccessToken:LINE Developers → Messaging API設定 → チャネルアクセストークン(長期)
// ターミナルで `ngrok http 3000` 実行後、発行されたURLをWebhook URLとして設定するのを忘れずに
// 「検証」ボタンをクリックするとターミナルにエラーが出ますがここでは問題ありません(検証イベントのハンドリングをしていないため)
// ########################################
const config = {
channelSecret: '',
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);
}
// テキストメッセージを受信したとき
if (event.message.text === '距離感教えて') {
// 待ってねというメッセージを「リプライ」で先に返す
await client.replyMessage(event.replyToken, {
type: 'text',
text: 'しばし待つのじゃ'
});
// obnizの温度センサから値をとってくる(ブロッキング・時間のかかる処理で一旦ここで止まる)
const distance = await getObnizDistance();
// tempが取得できたらそれを含めたメッセージを「プッシュ」で送信する
client.pushMessage(event.source.userId, {
type: 'text',
text: '今の距離は' + distance/10 + 'センチじゃ。',
});
} 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);
つまずいたポイント
①LINEBotとのつなぎこみはできたが、距離センサーの数値をうまく拾えない。
エラー表示はこちら、
TypeError: Assignment to constant variable.
at getObnizDistance
getObnizDistanceの関数がちゃんと書けていないのか。
const getObnizDistance = async () => {
// 超音波測距センサを利用する
const hcsr04 = obniz.wired('HC-SR04', { gnd: 0, echo: 1, trigger: 2, vcc: 3 });
// 非同期で取得
const distance = await hcsr04.measureWait();
// そのままだと小数点以下の桁数がやたら多いので整数に丸めてもよい
distance = Math.floor(distance);
// ターミナル表示
console.log('obniz distance:', distance);
// obnizディスプレイ表示
obniz.display.clear();
obniz.display.print(distance/10 + 'cm');
// 距離を返す
return distance;
}
定例のタイムアップ…。エラーで詰まると無限に時間が溶けてしまう。
まとめ
if文と、関数が整理しきれておらず、Progateで復習をしていたら、時間をだいぶ取られてしまいました…。コードも長くなり、複数の関数が走っているので、エラー後の修正箇所の切り出しが、なかなか難しいです。もう少し手を加えます。