Miyp が 2021年05月13日23時36分31秒 に編集
コメント無し
本文の変更
## やりたいこと コロナで自宅にいる時間が増えているので自宅のスマートホーム化を計画しました。 いきなり難しいことはできないため、まずはそれぞれの部屋の温度・湿度を取得して履歴の取得と 携帯からそれぞれの部屋の状態を確認できるシステムを構築しました。 ## デモ画面 @[Youtube](https://youtu.be/Hzoxv2gYD9w) ## システム構成


## ハードウェア 今回は買い物だけではんだ付けは不要です。 |No|名称|機能|入手先| |:--|:--|:--|:--| |1|obniz|BLE通信を使いGoveeから温湿度情報を取得、Ambientにデータを出力します|[Amazon](https://www.amazon.co.jp/dp/B07DD6FK8G/)やSWITCHSCIENSなど| |2|Govee|BLE温湿度計|[Amazon](https://www.amazon.co.jp/dp/B083348J3X/)など| |3|Raspberrypi4|ダッシュボード表示用のWebサーバ|[Amazon]()など| No.3のRaspberrypiはHtml+Javascriptファイルを公開するためのWebサーバです。
obnizIDを書いたファイルを公開したくなかったので自宅内にWebサーバを立てましたが、上手く管理する方法があればCloud上にあるサービスを使って公開するのもよいかと思います。
obnizIDを書いたファイルを公開したくなかったので自宅内にWebサーバを立てましたが、毎回obnizIDを入力していいのであればCloud上にあるサービスを使って公開するのもよいかと思います。
## ソフトウェア
## 事前準備:Ambientのユーザ登録とチャンネル登録 [Ambient](https://ambidata.io/)はIoTデータの可視化サービスです。8チャンネルまでなら無料で使用できるため、個人のIoT用途にいいサービスです。ユーザ登録をして、今回のプロダクト用にチャンネルの作成をしてください。
### 事前準備:Ambientのユーザ登録とチャンネル登録 [Ambient](https://ambidata.io/)はIoTデータの可視化サービスです。8チャンネルまでなら無料で使用できるため、個人のIoT用途にぴったりです。 ユーザ登録をして、今回のプロダクト用にチャンネルの作成をしてください。

## ソフトウェア ### ①履歴取得 
### ①履歴取得
obnizのサーバレス機能を使い10分間隔で温湿度の取得します。取得したデータをAmbientへ書き込みを行います。プログラムはAmbientから提供されているJavascriptライブラリ「[Ambient-lib](https://ambidata.io/refs/js/)」を利用してデータの書込みます。 JavascriptプログラムもAmbientの[サンプル](https://ambidata.io/samples/devices/obniz2/)とほぼ一緒です。下記プログラムをobniz開発者コンソールのリポジトリに登録し、サーバレスイベントとして実行させています。 サーバレスイベントの制限が「各イベントの実行は1日に150回まで」となっているので、イベントのトリガーは10分間隔(144回/日)としています。 各自の環境に合わせてプログラム定数を書き換えてください。 ```js:各自の環境に応じて書き換える部分 const ambientID = Your Channel key;//Ambientのユーザチャネルキー const ambientRKey = "Your Read Key";//Ambient読込用のキー const ambientWKey = "Your Write Key";//Ambient書込用のキー const obnizID = "Your obniz ID";//ObnizのID ``` Goveeの温湿度計は温度・湿度情報をBLE通信のAdvertised Dataとして送信します。
仕様は[ここ]()で解説されていますが、
仕様は[ここ](https://github.com/Thrilleratplay/GoveeWatcher)や[ここ](https://qiita.com/hiratarich/items/3f7991d4164e5f0ecc62)で解説されています。 結果的に温度・湿度データのデコーディング部分は下記になります。
```js:アドバタイズドデータから温度・湿度を計算する部分 const buf = peripheral.adv_data[26] * Math.pow(16, 4) + peripheral.adv_data[27] * Math.pow(16, 2) + peripheral.adv_data[28] let temperature = Math.floor(buf / 1000) / 10; let humidity = (buf % 1000) / 10; let power=peripheral.adv_data[29];
```
```html:プログラム全体(サーバレスイベント) <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" /> <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> <script src="https://unpkg.com/obniz@3.x/obniz.js" crossorigin="anonymous" ></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/qs/6.10.1/qs.min.js" integrity="sha512-aTKlYRb1QfU1jlF3k+aS4AqTpnTXci4R79mkdie/bp6Xm51O5O3ESAYhvg6zoicj/PD6VYY0XrYwsWLcvGiKZQ==" crossorigin="anonymous"></script> <script src="https://unpkg.com/ambient-lib@1.0.3/lib/ambient-lib.js"></script> </head> <body> <script> // インストールされたデバイス情報に書き換わる const ambientID=Your Channel key; const ambientRKey="Your Read Key"; const ambientWKey="Your Write Key"; const obnizID="Your obniz ID" var obniz = new Obniz(obnizID); obniz.onconnect = async function () { await obniz.ble.initWait(); var target = { localNamePrefix:"GVH5075" }; var setting = { duration: 60, // 60 sec } obniz.ble.scan.onfind = async function (peripheral) { let name=peripheral.localName; console.log("Name:"+name); const buf = peripheral.adv_data[26] * Math.pow(16, 4) + peripheral.adv_data[27] * Math.pow(16, 2) + peripheral.adv_data[28] let temperature = Math.floor(buf / 1000) / 10; let humidity = (buf % 1000) / 10; let power=peripheral.adv_data[29]; //console.log(buf); //console.log("RSSI:"+peripheral.rssi); console.log("Temp:"+temperature); console.log("Humi:"+humidity); console.log("Power:"+power); am = new Ambient(ambientID,ambientWKey); am.send({d1: temperature, d2: humidity,d3:power}, function(response) { console.log(response.status); }); if (Obniz.App.isCloudRunning()) { Obniz.App.done({ status: 'success', text: `Worked` }) } else { alert("Done.") } }; obniz.ble.scan.onfinish = async function (peripherals, error) { //console.log("scan again") await obniz.ble.scan.startWait(target, setting); }; await obniz.ble.scan.startWait(target, setting); }; obniz.onclose = async function() { }; </script> </body> </html> ``` obnizでサーバレスイベントを設定した手順は以下になります。 - 開発者コンソールにアクセス - リポジトリをクリック
- 新規作成でタイプをBlockProgram、ファイル名入力し作成ボタンをクリック
- 新規作成でタイプをWebApp、ファイル名入力し作成ボタンをクリック
- プログラムを作成 して保存
- 次に、開発者コンソールのサーバレスイベントを選択 - 新規作成で任意の名称、トリガーを「繰返し:10minutes」、実行するアプリケーションに上記で作成したHTMLファイルを指定 - 作成ボタンを押すとサーバレスイベントが出来上がります。

### ②ダッシュボード
30秒間隔で温湿度計のデータを取得。取得したデータをダッシュボードに表示しています。
 次にダッシュボードを作ります。ダッシュボードは30秒間隔で温湿度計のデータを取得。取得したデータを表示しています。
温湿度計は複数個に対応しています。
開発環境にはビジュアルプログラミングツールNoodlを使い、SPAのダッシュボードを作成します。 Noodlプロジェクトを[Github]()にアップしていますので、Noodl2.2.4以上で読込んで使用してください。
開発環境にはビジュアルプログラミングツールNoodlを使い、SPAダッシュボードを作成します。 Noodlプロジェクトを[Github](https://github.com/macole/HomeBoard)にアップしていますので、Noodl2.2.4以上で読込んで使用してください。
### NoodlでUI・アプリの作成
4つのコンポーネントを作成しました。
3つのコンポーネントを作成しました。
|No|名称|機能| |:--|:--|:--|
|1|obniz|BLE通信を使いGoveeから温湿度情報を取得、Ambientにデータを出力します| |2|Govee|BLE温湿度計| |3|Raspberrypi4|ダッシュボード表示用のWebサーバ| |4|XXXX|XXXXXXXXXXXXXXX|
|1|App|ダッシュボード画面アプリ本体| |2|GVH5075|BLE温湿度計GVH5075の表示| |3|Indicator|温度・湿度を表す表示UI部|
Noodl上でのビジュアルプログラミングコードは下記となります。
Javascriptノード内のプログラムは下記となります。

  AppにあるJavascriptノード内のプログラムは下記となります。
```js:Javascriptノードの中身 Node.Inputs = { ObnizID: 'string', } Node.Outputs = { temperature: "number", humidity: "number", power:"number", rssi: "number", name: "string", } Node.Signals.ScriptLoaded = function () { var obniz = new Obniz(Node.Inputs.ObnizID); obniz.onconnect = async function () { await obniz.ble.initWait(); var target = { //localName: "GVH5075_XXXX", localNamePrefix:"GVH5075" }; obniz.ble.scan.onfind = async function (peripheral) { Node.Outputs.name=peripheral.localName; console.log("Name:"+peripheral.localName); const buf = peripheral.adv_data[26] * Math.pow(16, 4) + peripheral.adv_data[27] * Math.pow(16, 2) + peripheral.adv_data[28] Node.Outputs.temperature = Math.floor(buf / 1000) / 10; Node.Outputs.humidity = (buf % 1000) / 10; Node.Outputs.power=peripheral.adv_data[29]; Node.Outputs.rssi=peripheral.rssi; //console.log(buf); //console.log(temperature); //console.log(pressure); //console.log("RSSI:"+peripheral.rssi);
}; obniz.ble.scan.onfinish = async function (peripherals, error) { console.log("scan again") await obniz.ble.scan.startWait(target); }; await obniz.ble.scan.startWait(target); }; } ```
完成したらNoodl上でDeployすることでHTML+Javascriptファイルが生成されます。 このファイルをWebサーバ上に配置することでブラウザからダッシュボードを確認することができます。
## 動作確認 準備ができたので動作確認をしてみました。
①サーバレスイベントが上手く実行されると、実行結果に時間が表示されます。  ②のダッシュボードの確認はファイルを配置したWebサーバにアクセスして確かめてください。
**注 ①②はともに同じobnizに接続しに行くため同時には利用できません。** **そのため②のダッシュボードを表示している間は10分間隔で起動する①の履歴送信ができなくなります。** ## まとめ これで各部屋の温湿度を取得できるようになりました。今回はBLE通信を使ったので半田付けも不要でお手軽にIoTを始められる方法だと思います。 今後はこのデータを使ってLINEへの通知や空いているobnizのIOポートを使った出力を行い、スマートホーム化をさらに進めていきたいです。 ## 参考資料
- [Github:Thrilleratplay/GoveeWatcher](https://github.com/Thrilleratplay/GoveeWatcher)
- [bluetooth 温度・湿度計を読んでインターフェイスする。](https://qiita.com/hiratarich/items/3f7991d4164e5f0ecc62) - [Obnizでセンサデータを取得しAmbientに送る](https://ambidata.io/samples/devices/obniz2/)