OMRON HVC-F Human Vision CompoをNode-REDで活用する

OMRON HVC-Fは、人の“位置”と“人数”を検出する画像型人感センサです。
本製品は、PoEにより電源供給/ネットワーク接続され、TCP/IPもしくはmodbus/TCPでのデータ取得をサポートしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316451/412b1257-3246-19ba-4afc-0450e6385151.png)

https://www.omron.co.jp/ecb/product-detail?partId=43062

今回は、本センサーからTCP/IPによりデータ取得を行う方法についてNode-REDによる実装を行ってみました。
なお、本記事はOpenBlocks IoT(debian9)上で検証を行っていますが、debian9はもとより、Node-REDの動作環境があれば利用できるはずです。
ただ、OpenBlocksの場合は標準のmodbus/Etherクライアント機能にて対応可能ですので今回の場合はIPC-in接続に置き換えて可視化すればいいだけとなります。

## 初期設定について

今回はお借りした機器の設定のまま利用しましたので、
HVC-F IP address : 192.168.167.100/24  port : 9600
としてネットワーク回りの設定を行っています。
## Node-REDによるセンサーデータの取得例

Node-REDのTCP Requestノードを使用し、データ取得コマンドの発行と検出データの受信を行っています。
受信したデータは、上記ページよりリンクされている、コマンド仕様書に基づいて、JSON形式にパースしています。
https://omronfs.omron.com/ja_JP/ecb/products/pdf/CDSC-030A.pdf
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316451/aa045a0f-937b-ef4c-1a3d-3a2c24cecc9f.png)

Node-RED によるサンプルフロー

```
[{"id":"7f2fcebf.3e059","type":"tcp request","z":"5bd9ba38.7e1224","server":"192.168.167.100","port":"9600","out":"time","splitc":"0","name":"HVC-F","x":650,"y":180,"wires":[["775273a7.11070c","44848fa5.55e06"]]},{"id":"775273a7.11070c","type":"function","z":"5bd9ba38.7e1224","name":"to JSON","func":"if ( msg.payload[0]==0xfe && msg.payload[5]==0x90 && msg.payload[6]==0x04 ){\n    data = msg.payload\n    msg.payload=\n    {\n        time : global.get(\"TimeStump\"),\n        count: msg.payload.readInt8(8)\n    }\n\n    var arr = Array();\n    \n    for( i=0; i<msg.payload.count; i++ ) {\n        arr[i*2] = data.readInt16BE(i*4+10);\n        arr[i*2+1] = data.readInt16BE(i*4+12);\n    }\n    \n    msg.payload.pos = arr;\n    return msg;\n}","outputs":"1","noerr":0,"x":440,"y":260,"wires":[["f3750ff6.1df88","5f58c0a3.ac864"]]},{"id":"f3750ff6.1df88","type":"debug","z":"5bd9ba38.7e1224","name":"","active":true,"console":"false","complete":"false","x":690,"y":260,"wires":[]},{"id":"ba5e1a7d.37e9e8","type":"inject","z":"5bd9ba38.7e1224","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":180,"y":100,"wires":[["7f934e0.ccce1b4"]]},{"id":"2c97eccc.4d2404","type":"function","z":"5bd9ba38.7e1224","name":"検出コマンド・計測時間保存","func":"global.set(\"TimeStump\", msg.payload );\n\nvar buf = new Buffer([0xFE,0x60,0x00,0x00]);\nmsg.payload = buf;\nreturn msg;","outputs":1,"noerr":0,"x":400,"y":180,"wires":[["7f2fcebf.3e059"]]},{"id":"44848fa5.55e06","type":"debug","z":"5bd9ba38.7e1224","name":"","active":false,"console":"false","complete":"false","x":850,"y":100,"wires":[]},{"id":"7f934e0.ccce1b4","type":"function","z":"5bd9ba38.7e1224","name":"TimeStump","func":"var date = new Date();\ndate.setTime(msg.payload);\nmsg.payload = date.toISOString();\nreturn msg;","outputs":1,"noerr":0,"x":390,"y":100,"wires":[["2c97eccc.4d2404"]]},{"id":"9241c95.a9e8838","type":"ui_gauge","z":"5bd9ba38.7e1224","name":"","group":"fb4887ca.b32508","order":1,"width":"0","height":"0","gtype":"gage","title":"Gauge","label":"units","format":"{{value}}","min":0,"max":"35","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":530,"y":360,"wires":[]},{"id":"5f58c0a3.ac864","type":"function","z":"5bd9ba38.7e1224","name":"value","func":"msg.payload = msg.payload.count;\nreturn msg;","outputs":1,"noerr":0,"x":350,"y":360,"wires":[["9241c95.a9e8838","fbd5415b.57974","9964c27c.38bf3"]]},{"id":"fbd5415b.57974","type":"ui_chart","z":"5bd9ba38.7e1224","name":"","group":"fb4887ca.b32508","order":4,"width":"0","height":"0","label":"chart","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"x":530,"y":400,"wires":[[],[]]},{"id":"9964c27c.38bf3","type":"debug","z":"5bd9ba38.7e1224","name":"","active":false,"console":"false","complete":"false","x":630,"y":320,"wires":[]},{"id":"fb4887ca.b32508","type":"ui_group","z":"","name":"OMRON HVC-F Human Vision Compo","tab":"db39c3ca.e8f54","disp":true,"width":"6"},{"id":"db39c3ca.e8f54","type":"ui_tab","z":"","name":"OMRON Sensors","icon":"dashboard"}]
```

injectボタンを押すとコマンドが発行され、レスポンスをJSON形式でパースしたものが、debugノードで確認できます。
JSONの形式で、count(人数)および最大35人分の位置座標データを配列posに格納します。

また、ダッシュボードへGaugeとchartで出力していますので、
http://Node-REDのURL/ui
でダッシュボード出力されます。下記のダッシュボードではOMRON社のCTセンサKM-N1からmodbus/RTU接続で取得したデータを合わせて表示させています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316451/eb284590-e300-b1eb-138b-912b12a243f7.png)

起動時より自動的に一定時間毎のデータ計測を行いたい場合は、injectノードを編集し、「Node-RED起動時に実行」「繰り返し」等の設定を行ってください。
JSON形式にしていますので、Node-REDで利用できるノードを用いて、サーバやクラウドのIoT Hubへ送信したり、データベースへの書き込みを行うことも容易かと思います。
また、OpenBlocks IoTシリーズの場合、ユーザーデバイス登録を行い、IPC Outへパスを設定することで、パースしたJSONデータをPD repeaterで扱うことにより、各種クラウドやAzure IoT Edgeのコンテナモジュールへの送信について、WebUIで設定/リモート管理出来ます。

## 最後に
検出座標のデータを整数値の配列posに変更しました。

--
(ご)　　Toshiya Goto
　　　　goto@plathome.co.jp