ATOM Echo のための定時発話システム構築 -Node-RED の利用-
前回はATOM Echo を用いてTTSのストリーミング再生を堪能させていただきました。
ここでは、日々の生活のなかで目覚ましなどの定時発話を目指しシステム構築いたしました。
目次
システム概要
以下が本システムの概要図です。
自宅サーバのラズパイ2のNode-REDから定時で発話のmp3 URLをUDPで
ATOM Echoに送信し、ストリーミング再生します。
Node-RED
以下が今回の定時発話システムの Node-RED フローです。
① injectノード (発話群)
発話内容を入力し次段に送信します。
曜日と時間を指定して繰り返し起動させています。
ここで定時発話させたい内容をノードの追加によって指定します。
我が家では朝の目覚ましや歯磨きや宿題を促すようにしています。
② google-ttsノード
Google Text to Speech APIを呼び出すgoogle-ttsノードを使用しました。
https://flows.nodered.org/node/node-red-contrib-google-tts
前段からの発話内容を入力して発話のmp3 URLを返します。
言語は日本語(ja-JP)を指定しています。
③ UDP送信ノード
前段からのmp3 URLをUDP送信します。
ポートと送信先ATOM EchoのIPアドレスを指定します。
ATOM Echo用 Arduinoコード
Node-REDからのmp3 URLをUDPで受信してストリーミング再生しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
#include <M5Atom.h> #include <WiFi.h> #include <WiFiClient.h> #include "AsyncUDP.h" #include "AudioFileSourceICYStream.h" #include "AudioFileSourceBuffer.h" #include "AudioGeneratorMP3.h" #include "AudioOutputI2S.h" String http; const char * ssid = "WiFi SSID"; const char * password = "WiFi PASS"; AsyncUDP udp; int prayState = 0; IPAddress ip(192, 168, AAA, BBB); // for fixed IP Address IPAddress gateway(192,168, AAA, CCC); // IPAddress subnet(255, 255, DDD, EEE); // IPAddress DNS(192, 168, AAA, CCC); AudioGeneratorMP3 *mp3; AudioFileSourceICYStream *file; AudioFileSourceBuffer *buff; AudioOutputI2S *out; #define CONFIG_I2S_BCK_PIN 19 #define CONFIG_I2S_LRCK_PIN 33 #define CONFIG_I2S_DATA_PIN 22 // Called when a metadata event occurs (i.e. an ID3 tag, an ICY block, etc. void MDCallback(void *cbData, const char *type, bool isUnicode, const char *string) { const char *ptr = reinterpret_cast<const char *>(cbData); (void) isUnicode; // Punt this ball for now // Note that the type and string may be in PROGMEM, so copy them to RAM for printf char s1[32], s2[64]; strncpy_P(s1, type, sizeof(s1)); s1[sizeof(s1)-1]=0; strncpy_P(s2, string, sizeof(s2)); s2[sizeof(s2)-1]=0; Serial.printf("METADATA(%s) '%s' = '%s'\n", ptr, s1, s2); Serial.flush(); } // Called when there's a warning or error (like a buffer underflow or decode hiccup) void StatusCallback(void *cbData, int code, const char *string) { const char *ptr = reinterpret_cast<const char *>(cbData); // Note that the string may be in PROGMEM, so copy it to RAM for printf char s1[64]; strncpy_P(s1, string, sizeof(s1)); s1[sizeof(s1)-1]=0; Serial.printf("STATUS(%s) '%d' = '%s'\n", ptr, code, s1); Serial.flush(); } void setup(){ M5.begin(true, false, true); Serial.begin(115200); WiFi.config(ip, gateway, subnet,DNS); // Set fixed IP address delay(1000); M5.update(); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); if (WiFi.waitForConnectResult() != WL_CONNECTED) { Serial.println("WiFi Failed"); while(1) { delay(1000); } } if(udp.listen(XXXX)) { //XXXX:UDPポート番号 Serial.print("UDP Listening on IP: "); Serial.println(WiFi.localIP()); udp.onPacket([](AsyncUDPPacket packet) { int length = packet.length(); char https[length]; memcpy(https, packet.data(), length); http = "http" + String(https).substring(5, length); Serial.println(http); prayState = 1; }); } } void loop(){ if(prayState){ audioLogger = &Serial; file = new AudioFileSourceICYStream( (const char *)http.c_str() ); file->RegisterMetadataCB(MDCallback, (void*)"ICY"); buff = new AudioFileSourceBuffer(file, 10240); buff->RegisterStatusCB(StatusCallback, (void*)"buffer"); out = new AudioOutputI2S(); out->SetPinout(CONFIG_I2S_BCK_PIN, CONFIG_I2S_LRCK_PIN, CONFIG_I2S_DATA_PIN); out->SetChannels(1); out->SetGain(0.4); mp3 = new AudioGeneratorMP3(); mp3->RegisterStatusCB(StatusCallback, (void*)"mp3"); mp3->begin(buff, out); while(mp3->isRunning()) { Serial.println("playing"); if (!mp3->loop()) { mp3->stop(); prayState = 0; break; } } } M5.update(); } |
google-ttsノードはhttpsのURLを返すので
L. 87 でhttpに変更しています。
httpsのままだと再生できなかったので変更しました。
動作
おわりに
定時発話システムが実現できましたので、
次回はATOM Echo にセンサをつないで測定値を発話させてみたいと思います。
何卒宜しくお願い致します。