どうしてクーラーつけないの?!
ある夏の日に実家に帰った時のこと。
うだるような暑さの中、リビングでクーラーもつけずにテレビを見る父がいた。
かろうじてシーリングファンは回っていたものの、父の隣で寝そべっている猫もぐったりしている。驚いて「どうしてクーラーつけないの?!」と聞いたら、「窓開けてれば、涼しいよ」と、ニコニコしながら父は言った。
人は老化が進むにつれ、温度に対する感覚が弱くなる
人は老化が進むと熱放射能力が低くなり、深部体温が上昇しやすい。また、温度に対する感覚も弱くなり「暑い」と感じにくくなったり、喉の渇きを感じにくくなったりすることで、熱中症にかかりやすいと言われている。
【参考文献】
・熱中症ゼロへ
熱中症、こんな人は特に注意!
熱中症の約4割は室内で発生している
消防庁の統計によると、熱中症の約4割が室内で発生しており、熱中症死亡者数で見ると65歳以上の高齢者が8割を占めている。
屋内で熱中症により亡くなった高齢者の約9割は、エアコンがあるのに使用していなかったとのことだ。
【参考文献】
・weathernews
15年で3倍以上 死者数の8割を占める高齢者の熱中症対策
・消防庁
全国の熱中症による救急搬送状況 令和5年7月24日~7月30日(速報値)
LINE Botを活用して家族を守る仕組みを考える
どうしたら離れて暮らす家族を守ることができるのか考えてみた。
考えた仕組みは以下2点である。
LINEのあて先 : 両親、離れて暮らしている家族を想定
・温度センサー
一定の時間ごとに自動で室内の温度を測り、LINE Botでお知らせして注意喚起する
・超音波距離センサー
一定の時間ごとに室内で人の動きがあるか検知し、LINE Botでお知らせする
人の動きがない場合は家族に安否確認するよう促す
活用ツール
・obniz(OSのひとつで、瞬時に動作が始まるIoTを実現)
・温度センサー(LM60)
・超音波距離センサー(HCSR04)
望むものができた。温度を測って、超音波センサーで動きを検知し、LINE Botでお知らせする。ただ、obnizひとつで実行しようとすると、動作のタイミングが一緒になってしまう。#protoout #obniz #安否確認 #NodeRED #JavaScript #温度センサー #超音波センサー https://t.co/XJ307aMjqA pic.twitter.com/Si70T9n3sP
— chihirot134 (@chihirot_kate) June 4, 2024
・Node-RED
・JavaScript
・LINEmessagingAPI
フロー
・上段・・処理停止用ノード(説明は省略)
・下段・・処理実行用ノード
ソースコード(処理実行用ノード)
[{"id":"c61534fcfc6e08b2","type":"obniz-repeat","z":"19f26d722b829ed2","obniz":"2a612d9a43b88fcd","name":"センサーデータ取得","interval":"3600000","code":"const LM60Value = await obnizParts.LM60.getWait();\nconst HCSR04Value = await obnizParts.HCSR04.measureWait();\nmsg.payload = { temperature: LM60Value, distance: HCSR04Value };\nreturn msg;","x":270,"y":200,"wires":[["c7e273cea974653f"]]},{"id":"c7e273cea974653f","type":"function","z":"19f26d722b829ed2","name":"メッセージ生成","func":"let temperature = msg.payload.temperature;\nlet distance = msg.payload.distance;\n\nif (temperature < 28) {\n msg.payload = '【熱中症注意!窓を開けて!】現在の気温は' + temperature + '度です。';\n} else {\n msg.payload = '【熱中症警告!エアコンをつけて!】現在の気温は' + temperature + '度です。';\n}\n\nif (distance >= 1000) {\n msg.payload += '\\n【安否確認】動きが検出されませんでした。確認してください。';\n} else {\n msg.payload += '\\n動きが検出されました。';\n}\n\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":460,"y":200,"wires":[["be193680201d4aae"]]},{"id":"be193680201d4aae","type":"BloadcastMessage","z":"19f26d722b829ed2","name":"LINEメッセージ送信","x":660,"y":200,"wires":[[]]},{"id":"2a612d9a43b88fcd","type":"obniz","obnizId":"****-****","deviceType":"obnizboard1y","name":"","accessToken":"","autoConnectOnDeploy":true,"code":"// 画面を消去\r\nobniz.display.clear();\r\n\r\n// LM60温度センサーの設定\r\nobnizParts.LM60 = obniz.wired(\"LM60\", {\r\n gnd: 0, // GNDピンの接続\r\n output: 1, // アナログ出力ピンの接続\r\n vcc: 2 // VCCピンの接続\r\n});\r\n\r\n// HC-SR04超音波センサーの設定\r\nobnizParts.HCSR04 = obniz.wired(\"HC-SR04\", {\r\n gnd: 3, // GNDピンの接続\r\n echo: 4, // Echoピンの接続\r\n trigger: 5, // Triggerピンの接続\r\n vcc: 6 // VCCピンの接続\r\n});\r\n"}]
①センサーデータ取得
・温度センサー(LM60)と、超音波距離センサー(HCSR04)のデータを取得し、msg.payloadに"temperature"と"distance"を代入する
・"interval":"3600000"=1時間ごとに稼働するよう設定
②メッセージ生成
msg.payloadに代入されたそれぞれのデータを呼び出し、メッセージを生成する
・温度(temperature)
28℃未満だった場合
・・【熱中症注意!窓を開けて!】現在の気温は⚫︎度です。
その他(28℃以上)だった場合
・・【熱中症警告!エアコンをつけて!】現在の気温は⚫︎度です。
・距離(distance)
1m以内で動きがあるか確認
動きなし・・【安否確認】動きが検出されませんでした。確認してください。
動きあり・・動きが検出されました。
③Broadcastノード
LINE Botにメッセージを送信する
結果
考察
今回はobniz1台で粘ったので、稼働時間を分けることが出来なかった。
できれば動きの検出については、6時間に1回などに回数を減らしたい。
メッセージを受け取る対象を誰にするかによっても、稼働のタイミングは変えた方が良さそうだ。
取得したデータを活かして、自動でエアコンをON、OFFする仕組みも作ることができそう。
家族が離れて暮らしていても、見守り・フォローする体制ができていれば、安心して過ごせるのではないだろうか。親世代はとにかくクーラーをつけたがらない。それを認識しておくだけでも防げる事故があるはずだ。
おまけ
前回作成したLINE Botに部屋の温度を測る機能をプラスした。
これでいつでも温度を確認することができる。
全体フローを紹介
[{"id":"97811561ee3a6b19","type":"Webhook","z":"9ef9e62fc4a4dae4","name":"","url":"/webhook","x":120,"y":340,"wires":[["bc574decf74c8274"]]},{"id":"2fb4f5b04158148f","type":"ReplyMessage","z":"9ef9e62fc4a4dae4","name":"","replyMessage":"","x":800,"y":340,"wires":[]},{"id":"bc574decf74c8274","type":"switch","z":"9ef9e62fc4a4dae4","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"朝食","vt":"str"},{"t":"eq","v":"朝ごはん","vt":"str"},{"t":"eq","v":"昼食","vt":"str"},{"t":"eq","v":"ランチ","vt":"str"},{"t":"eq","v":"昼ごはん","vt":"str"},{"t":"eq","v":"気温教えて","vt":"str"},{"t":"eq","v":"温度教えて","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":8,"x":290,"y":340,"wires":[["2a93e82fe561e35d"],["2a93e82fe561e35d"],["9f0c3636c6dc4d9a"],["9f0c3636c6dc4d9a"],["9f0c3636c6dc4d9a"],["be0cd555c1d96a7e"],["be0cd555c1d96a7e"],["117eda19e0f3da20"]]},{"id":"2a93e82fe561e35d","type":"function","z":"9ef9e62fc4a4dae4","name":"朝食","func":"function getRandomElement(array) {\n return array[Math.floor(Math.random() * array.length)];\n}\n\nconst categories = {\n onigiri: [\"鮭おにぎり\", \"梅おにぎり\", \"昆布おにぎり\"],\n sandwich: [\"ハムサンド\", \"卵サンド\", \"ツナサンド\"],\n salad: [\"チキンサラダ\", \"ツナサラダ\", \"シーザーサラダ\"],\n yogurt: [\"プレーンヨーグルト\", \"フルーツ入りヨーグルト\", \"ギリシャヨーグルト\"],\n fruit: [\"カットフルーツ(メロン、パイナップルなど)\", \"バナナ\", \"りんご\"],\n smoothie: [\"野菜スムージー\", \"フルーツスムージー\", \"プロテインスムージー\"],\n cerealBar: [\"グラノーラバー\", \"ナッツ&シードバー\", \"フルーツバー\"],\n hotMenu: [\"おでん\", \"中華まん\", \"焼き芋\"],\n bread: [\"クロワッサン\", \"ベーグル\", \"ブランパン\"],\n others: [\"サバの塩焼き\", \"枝豆\", \"ゆで卵\"],\n drink: [\"豆乳\", \"プロテインドリンク\", \"ミルク\"]\n};\n\nconst randomSelection = {\n onigiri: getRandomElement(categories.onigiri),\n sandwich: getRandomElement(categories.sandwich),\n salad: getRandomElement(categories.salad),\n yogurt: getRandomElement(categories.yogurt),\n fruit: getRandomElement(categories.fruit),\n smoothie: getRandomElement(categories.smoothie),\n cerealBar: getRandomElement(categories.cerealBar),\n hotMenu: getRandomElement(categories.hotMenu),\n bread: getRandomElement(categories.bread),\n others: getRandomElement(categories.others),\n drink: getRandomElement(categories.drink)\n};\n\n// 結果を整形してメッセージとして設定\nmsg.payload = `\n今日のおすすめ朝食メニュー:\nおにぎり: ${randomSelection.onigiri}\nサンドイッチ: ${randomSelection.sandwich}\nサラダ: ${randomSelection.salad}\nヨーグルト: ${randomSelection.yogurt}\nフルーツ: ${randomSelection.fruit}\nスムージー: ${randomSelection.smoothie}\nシリアルバー: ${randomSelection.cerealBar}\nホットメニュー: ${randomSelection.hotMenu}\nパン: ${randomSelection.bread}\nその他: ${randomSelection.others}\n飲み物: ${randomSelection.drink}\n`;\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":470,"y":300,"wires":[["2fb4f5b04158148f"]]},{"id":"9f0c3636c6dc4d9a","type":"function","z":"9ef9e62fc4a4dae4","name":"昼食","func":"function getRandomElement(array) {\n return array[Math.floor(Math.random() * array.length)];\n}\n\nconst categories = {\n bento: [\"チキン南蛮弁当\", \"焼肉弁当\", \"鮭弁当\", \"鯖の塩焼き弁当\", \"牛丼弁当\"],\n sandwich: [\"ローストビーフサンドイッチ\", \"クラブハウスサンドイッチ\", \"カツサンド\", \"エッグサラダサンドイッチ\", \"ツナサラダサンドイッチ\"],\n salad: [\"シーザーサラダ\", \"チキンサラダ\", \"豆腐サラダ\", \"海藻サラダ\", \"ミックスサラダ(チーズ、ナッツ入り)\"],\n pasta: [\"ペペロンチーノ\", \"カルボナーラ\", \"ミートソーススパゲッティ\", \"バジルソースパスタ\", \"シーフードパスタ\"],\n donburi: [\"親子丼\", \"牛丼\", \"海鮮丼\", \"豚丼\", \"天丼\"],\n soup: [\"ミネストローネ\", \"コーンスープ\", \"わかめスープ\", \"チキンスープ\", \"野菜たっぷりスープ\"]\n};\n\nconst randomSelection = {\n bento: getRandomElement(categories.bento),\n sandwich: getRandomElement(categories.sandwich),\n salad: getRandomElement(categories.salad),\n pasta: getRandomElement(categories.pasta),\n donburi: getRandomElement(categories.donburi),\n soup: getRandomElement(categories.soup)\n};\n\n// 結果を整形してメッセージとして設定\nmsg.payload = `\n今日のおすすめ昼食メニュー:\nお弁当: ${randomSelection.bento}\nサンドイッチ: ${randomSelection.sandwich}\nサラダ: ${randomSelection.salad}\nパスタ: ${randomSelection.pasta}\n丼もの: ${randomSelection.donburi}\nスープ: ${randomSelection.soup}\n`;\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":470,"y":340,"wires":[["2fb4f5b04158148f"]]},{"id":"117eda19e0f3da20","type":"template","z":"9ef9e62fc4a4dae4","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"朝食・朝ごはん\n昼食・昼ごはん・ランチ\nと入力してね!\n\n栄養バランスのポイント\n【たんぱく質】 肉、魚、豆腐、卵などのたんぱく質が豊富な食材を選びましょう。\n【野菜】 サラダやスープに野菜を取り入れて、ビタミンやミネラルを摂取しましょう。\n【炭水化物】 主食としてご飯やパン、パスタなどをバランスよく摂取します。\n【健康的な脂肪】 ドレッシングやナッツ、魚の脂など、健康的な脂肪を適量取り入れます。\n\nおすすめメニューは、栄養バランスを考慮して選んでおり、コンビニや食堂で手軽に手に入るものを中心にしています。","output":"str","x":480,"y":420,"wires":[["2fb4f5b04158148f"]]},{"id":"16f127f2c22e4a7b","type":"template","z":"9ef9e62fc4a4dae4","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"今の温度は {{payload}} 度です!","output":"str","x":680,"y":420,"wires":[["2fb4f5b04158148f"]]},{"id":"be0cd555c1d96a7e","type":"obniz-function","z":"9ef9e62fc4a4dae4","obniz":"2a612d9a43b88fcd","name":"","code":"msg.payload = await obnizParts.LM60.getWait();\nreturn msg;","x":500,"y":380,"wires":[["16f127f2c22e4a7b"]]},{"id":"2a612d9a43b88fcd","type":"obniz","obnizId":"****-****","deviceType":"obnizboard1y","name":"","accessToken":"","autoConnectOnDeploy":true,"code":"// 画面を消去\r\nobniz.display.clear();\r\n\r\n// LM60温度センサーの設定\r\nobnizParts.LM60 = obniz.wired(\"LM60\", {\r\n gnd: 0, // GNDピンの接続\r\n output: 1, // アナログ出力ピンの接続\r\n vcc: 2 // VCCピンの接続\r\n});\r\n\r\n// HC-SR04超音波センサーの設定\r\nobnizParts.HCSR04 = obniz.wired(\"HC-SR04\", {\r\n gnd: 3, // GNDピンの接続\r\n echo: 4, // Echoピンの接続\r\n trigger: 5, // Triggerピンの接続\r\n vcc: 6 // VCCピンの接続\r\n});\r\n"}]
・参考(過去の記事)
栄養を気にしてくれる人(Bot)を作りました!