ESP8266を使った音声認識Wifiスイッチのさらなる改良の続きです。
前回は、複数あるESP8266の一つをメインサーバとして、そこから他のESP8266へもHTTPリクエストを送る仕組みにしていましたが、今回はAjaxのXMLHttpRequestを使って、それぞれのESP8266へリクエストを送る仕組みに変更しました。
そもそも、XMLHttpRequestは同ドメイン内でしか使えないと思っていたので、前回のようなやり方になってしまったのですが、よく調べてみたらChromeやFireFoxでは異なるドメインへのリクエストも問題ないということでした。結局かなり遠回りしていましたが、クエリもサーバ同士の通信も不要で元の単純なアイデアに戻ってきた感じです。
これは↑、左側のESP8266(server A)がメインサーバとなり、ここに音声認識を含んだJavaScript、ならびにHTML+CSSファイルをアップロードしておき、ブラウザからこのIPアドレスにアクセスします。ブラウザ上では音声認識によるスイッチのON/OFF、そしてボタンでも操作できます。右側のもう一つのESP8266には、speech.html内に記述されたJavaScript(XMLHttpRequest)でON/OFFのリクエストを出します。
要は、画面遷移せずに複数あるESP8266に割り振った静的IPアドレスにリクエストを出しているだけです。一応XMLHttpRequestでリクエストを出したら、onreadystatechangeで反応の確認をとってから、画面内表示をアップデートするようにしています。以下の部分が今回のリクエストの仕方です(ほぼサンプル通りですが)。
前回は、複数あるESP8266の一つをメインサーバとして、そこから他のESP8266へもHTTPリクエストを送る仕組みにしていましたが、今回はAjaxのXMLHttpRequestを使って、それぞれのESP8266へリクエストを送る仕組みに変更しました。
そもそも、XMLHttpRequestは同ドメイン内でしか使えないと思っていたので、前回のようなやり方になってしまったのですが、よく調べてみたらChromeやFireFoxでは異なるドメインへのリクエストも問題ないということでした。結局かなり遠回りしていましたが、クエリもサーバ同士の通信も不要で元の単純なアイデアに戻ってきた感じです。
これは↑、左側のESP8266(server A)がメインサーバとなり、ここに音声認識を含んだJavaScript、ならびにHTML+CSSファイルをアップロードしておき、ブラウザからこのIPアドレスにアクセスします。ブラウザ上では音声認識によるスイッチのON/OFF、そしてボタンでも操作できます。右側のもう一つのESP8266には、speech.html内に記述されたJavaScript(XMLHttpRequest)でON/OFFのリクエストを出します。
要は、画面遷移せずに複数あるESP8266に割り振った静的IPアドレスにリクエストを出しているだけです。一応XMLHttpRequestでリクエストを出したら、onreadystatechangeで反応の確認をとってから、画面内表示をアップデートするようにしています。以下の部分が今回のリクエストの仕方です(ほぼサンプル通りですが)。
function request(url){ var index = html_id.indexOf(url); var req_url = ip_address[index] + url; var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ if(xhr.readyState === 4 && xhr.status === 200){ updateHtml(); console.log(xhr.response); } } xhr.open("GET", req_url, true); xhr.send(); }
それぞれのスイッチをON/OFFするにはそれに対応したURL("/fluo_on"や"/fluo_off"など)へリクエストをすればいいのですが、画面表示上ボタンもあることから、どれがONになっていて、どれがOFFになっているか分かるようにボタンの色を変える(この場合updateHtmlという関数)必要もあります。今回のようなやり方の場合は、onreadystatechangeで確認したのちにupdateHtmlで画面表示内容を変更するので、もしリクエスト先のESP8266から返事がなければボタンを押しても色が変わらないということになります。
これ↑は、前々回クエリをつかってやりとりしていた画面です(ボタンなどに表示画面自体は今回も同じ)。URLのあとに長々とクエリをつけて異なるサーバへ表示用変数を渡す面倒なやり方になっていましたが、今回は画面表示に関してはメインサーバとのやりとりだけなので、メインサーバ内のJavaScriptの変数に記憶させているだけでクエリは不要となりました。
もうひとつの方法として、ESP8266をメインサーバとして使わず、外部にある普通のWebサーバに音声認識も含むJavaScriptならびにHTML+CSSファイルをアップロードしておき、そこをメインサーバにしてしまうというのもあります。
この場合、ESP8266には簡単なボタン操作するだけのHTMLデータ(音声認識なし、画面表示も単純)を書いておき、万が一中央のメインサーバと通信不能になっても、一応それぞれのESP8266へアクセスすればON/OFFだけはできるようにしておきます。
こんな感じ↑の臨時用ボタンくらいは表示できるようにしておく。
ESP8266にはわざわざHTMLファイルをアップロードしなくてもいいので、その分手間が省けそうです。外部サーバをメインサーバとすれば、ファイルが巨大になってもなんとかなりそうです。あるいは、ローカルで使うのであれば、Raspberry Piでサーバを立ち上げていてもいいかもしれません。
あと改良しなければいけない点は、メインサーバと再接続したときに、現状だとすべてがリセット(すべてOFF)になってしまうので、再接続の際にそれぞれのスイッチのON/OFF状態を確認するプログラムが必要という感じです。そのためには、それぞれのESP8266にON/OFF状態の変数を用意しておき、再接続の際に状態チェック用のURLにアクセスして、それぞれのESP8266からそのデータを受け取る仕組みにすればいいかなと考えています。
追記:
音声認識Wifiスイッチ/ESP8266使用(まとめ)についてはこちら。