node-red経由でAlexaにwio-terminalで取得した室温を喋らせる

 wio-terminalで室温取得出来るようになったので今度は兼ねてから気になっていたAlexaで室温をVUI出来るようにnode-red経由で喋らせてみた。node-red一日生故実装が滅茶苦茶かもしれないがネットの情報を参考にして一応動くので以下に記す。

1.Alexaとnode-red

 Alexaはさまざまなスキルと称するVUI拡張を開示しておりnode-redはIBMに始まるNode.jsを基盤としたサーバ・フレームワークのようなものだと理解している。node-redはフロー形式と称するGUIオブジェクトを接続して処理方法を定義する統合環境のようなものを提供しており今回はhttp://localhost:1880(つまりは自機)でそれを動かしてAlexaとの連携を行う。

f:id:aki_iic:20210509090920p:plain

node-red with alexa

 処理は画面真ん中の左側の「室温」というブロックがAlexaから見たデバイス名で「コンピュータ 室温を教えて」と呪文を唱えれば「○○.○○℃です」と応えてくれる仕掛けになる。ポイントはAmzonはAlexa機器の仕様公開を個人にしている訳でもないしフルスクラッチで作りこむのは大変そうなので安直にAmazon Alexa情報源から温度を通知する機器のインタフェースの真似をすれば良いと考えた。話を戻すとAlexaが呪文を理解すると「室温」デバイスに温度情報を既定のフォーマットで返す事を期待する。その為には

1.Alexaが「室温」デバイスへ温度情報を要求する。

2.wio-terminalのM5Stack ENVUnit(前回構築した物をベースに修正)から温度情報を取得する。

3.取得した温度情報をAlexaが期待するフォーマットに加工する。

4.加工した情報(室温情報)をAlexaにResponseする(右側のAlexa Home Resposeブロック)。

 が必要となる(今の構成では)。

・node-redでAlexaに対応する方法については以下のサイトを参考にさせて頂きました(感謝)

bluefish.orz.hm

2.構築方法

 今回は構成要素として:

 ・Alexa連携:node-red + alexa home/alexa home resp

 ・温度情報取得:wio-terminalを/dev/ttyACM0デバイスでUbuntu16.04/18.04のpython3(pyserial)で取得し温度情報を切り出し・加工。node-redでpythonのプログラムを呼び出し標準出力をmsg.payloadとして取得

  ・wio-terminalのarduinoコード:

/*
20210505 : Wio terminal + M5Stack ENV Unit(DHT12 only)
20210509 : append alexa interface with serial
*/

#include "SPI.h"
#include "TFT_eSPI.h"

// Use hardware SPI
TFT_eSPI tft = TFT_eSPI();

#include "DHT12.h"
#include <Wire.h> //The DHT12 uses I2C comunication.
#include "Adafruit_Sensor.h"

DHT12 dht12; //Preset scale CELSIUS and ID 0x5c.

void setup() {
tft.begin();
tft.setRotation(1);
Wire.begin();

//Serial.println(F("ENV Unit(DHT12 and BMP280) test..."));

tft.fillScreen(TFT_BLUE);
tft.setTextColor(TFT_WHITE, TFT_BLUE);
}

void loop() {

float tmp = dht12.readTemperature();
float hum = dht12.readHumidity();
if (Serial.available() > 0) {
String data = Serial.readStringUntil('\n');
Serial.printf("%2.2f\r\n", tmp);
}

tft.setCursor(0, 0);
tft.setTextColor(TFT_WHITE, TFT_BLUE);
tft.setTextSize(4);
tft.println("V01 20210505");
tft.printf("Temp: %2.1f \r\nHumi: %2.0f%% \r\n", tmp, hum);

delay(1000);
}

  ・それを受けて温度情報を切り出すpythonコード:

import serial

try:
  s=serial.Serial("/dev/ttyACM0","115200",timeout=5)
except:
  print(-273.15)
close(s)
cmd="\01PA00\r".encode()
s.write(cmd)
r=s.readline().decode()
r=r.strip("\r\n")
print(r)

 とんでもなく雑で申し訳ないが動かす事優先で(一日生node-red初心者故)ご容赦。

 ・Alexaが求めるフォーマットに編集:node-redのfunctionを用いてAmazon Alexaガイドで公開されていた温度情報取得のjavascriptコードをmsg.payloadを温度情報に置き換えてコピペ。

  ・functionの中のjavascriptコード:

msg.extra = {
"temperatureReading": {
"value": msg.payload
},
"applianceResponseTimestamp": new Date().toISOString()
};
msg.payload = true;
return msg;

 基本Amazonのパクリだけどvalueのmsg.payloadが前のpythonブロックで取得した温度情報を受けている点が修正点。個人的にはここが最大の難関で何をどうすればさっぱり解らなかったので試行錯誤の繰り返しであった。node-redでは簡単な構造であればブロック繋で構成するのをユーザに期待しておりexecやfunctionは機種依存性も高く已む無き手段かもしれないが動けば勝ちなのでとにかく動かす事優先。

3.まとめ

そんな訳で

「コンピュータ 室温を教えて」:呪文を唱える

「27.4℃です」:Alexaが応えてくれる

のでありました。上記他の善き参考情報に巡り会えたのが幸いであったがarduino,python,node-red,alexa連携と今風のVUIなIoT(笑)が体感出来たのは週末の道楽としては久々に生産的な活動であった。