grbl1.1+Arduino CNCシールドV3.5+bCNCを使用中。
BluetoothモジュールおよびbCNCのPendant機能でスマホからもワイヤレス操作可能。
その他、電子工作・プログラミング、機械学習などもやっています。
MacとUbuntuを使用。

CNCマシン全般について:
国内レーザー加工機と中国製レーザー加工機の比較
中国製レーザーダイオードについて
CNCミリングマシンとCNCルーターマシンいろいろ
その他:
利用例や付加機能など:
CNCルーター関係:



*CNCマシンの制作記録は2016/04/10〜の投稿に書いてあります。


2017年4月23日日曜日

ESP8266:WebサーバからHttpリクエスト

前回までの複数のESP8266を用いた音声認識Wifiスイッチの続きです。
複数の部屋(リビング、寝室、トイレなど)に異なるIPアドレスを割り振ったESP8266があるので、リビングの電源をON/OFFするには、リビングに設置したESP8266のIPアドレスにリクエストしていましたが、リビングから寝室の電源をON/OFFするには、寝室のIPアドレスへ画面遷移してリクエストを送るというややこしい仕組みになってました。


仕組みとしてはこんな感じで、電源をON/OFFさせたい場所のESP8266へ直接リクエストを送って、それぞれのサーバからレスポンスを受け取っていたという感じです。画面遷移しないで、AからBあるいはBからAへリクエストできないものかと、以下のようなシステムに変更してみました。


この場合は、serverAがメインサーバとなり、端末からもこのIPアドレスにアクセスして、Aの電源をON/OFFする場合は従来通りAへリクエストを送り、Bの電源をON/OFFするには、Aにリクエストを送り、Aが内部的にBへHTTPリクエストを送ることになります。
逆にBのIPアドレスへアクセスしても、同様にAに対してリクエストを送ることができるので、AであれBであれ、どちらにアクセスしようと画面遷移せずに両方の電源を制御できます。

今までは、サーバはクライアントからのリクエストを待ち、リクエストがあるときだけレスポンスするのだと思っていたので、サーバから別のURLへHTTPリクエストを送ることはできないと思っていました。しかし、サーバからも普通にHTTPリクエストできるということでした(もっと早く気づけば)。

以下がサンプルコード。今回は音声認識の部分は外しています。単にサーバAを介してサーバBを制御するという仕組みの部分だけです。

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WiFiClient.h>

#define ledPin 2

const char* ssid = "******";
const char* password = "******";
const char* reqHost = "192.168.3.13";

String webPage = "";

ESP8266WebServer server(80);

void setup(void){
  webPage="<http><head><meta charset='utf-8'><title>WIFI SWITCH</title></head><body>";
  webPage+="<div style='text-align:center; font-size:30px;'>";
  webPage+="<a href='/this_on'><button>THIS: ON</button></a><br/>";
  webPage+="<a href='/this_off'><button>THIS: OFF</button></a><br/>";
  webPage+="<a href='/other_on'><button>OTHER: ON</button></a><br/>";
  webPage+="<a href='/other_off'><button>OTHER: OFF</button></a><br/>";
  webPage+="</div></body></html>";
  
  pinMode(ledPin, OUTPUT);
  
  Serial.begin(115200); 
  delay(500);
  WiFi.begin(ssid, password);
  Serial.println("");

  while (WiFi.status() != WL_CONNECTED) {
    delay(5000);
    Serial.print(".");
  }
  WiFi.config(IPAddress(192,168,3,12),IPAddress(192,168,3,1),IPAddress(255,255,255,0));

  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
    
  server.on("/", [](){
    server.send(200, "text/html", webPage);
  });
  
  server.on("/this_on", [](){
    server.send(200, "text/html", webPage);
    digitalWrite(ledPin, HIGH);
    delay(1000);
  });
  
  server.on("/this_off", [](){
    server.send(200, "text/html", webPage);
    digitalWrite(ledPin, LOW);
    delay(1000); 
  });
  
  server.on("/other_on", [](){
    server.send(200, "text/html", webPage);
    http_request(reqHost,"/this_on");
    delay(1000);
  });
  
  server.on("/other_off", [](){
    server.send(200, "text/html", webPage);
    http_request(reqHost,"/this_off");
    delay(1000); 
  });

  server.begin();
  Serial.println("HTTP server started"); 
}

void http_request(const char* host, String url){
  //host="192.168.3.13";
  //url="/this_on";
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  unsigned long timeout = millis();
  while (client.available() == 0) {
    if (millis() - timeout > 5000) {
      Serial.println("Client Timeout!");
      client.stop();
      return;
    }
  }
}

void loop(void){
  server.handleClient();
}


ということで、http_request()という関数をつくり、他のIPアドレスのボタンを押したら、レスポンスとしてHTMLデータ(webPage:ボタン画面)を返しつつ、リクエストをもう一方のESP8266へ送るということにしました。setup()内にある以下の部分です。

  server.on("/other_on", [](){
    server.send(200, "text/html", webPage);
    http_request(reqHost,"/this_on");
    delay(1000);
  });
  
  server.on("/other_off", [](){
    server.send(200, "text/html", webPage);
    http_request(reqHost,"/this_off");
    delay(1000); 
  });

少しずつ曖昧な部分の理解が深まってきたので、徐々にまともなシステムになりつつあります。
Raspberry Pi上にNode-REDで全体を管理するサーバを立ち上げようと思いましたが、今回のやり方で大丈夫そうなので、Node-REDやMQTTなどは使わずいけそうです。
電気的な制御は単純なON/OFFですが、Wifiが絡んでくると、サーバだとかクライアントだとか、通信の仕組みで手間がかかります。ということで、またもやRaspberry Pi(サーバ利用)は不要となってしまいました。もっと複雑なことをしない限り、しばらくは中枢的なサーバはいらなさそうです。
このシステムは近々完成させて、次は再度IPカメラに戻りたいと思います。

追記:
改良案はこちら(XMLHttpRequestを使ったサンプル)
音声認識Wifiスイッチ/ESP8266使用(まとめ)についてはこちら

0 件のコメント:

コメントを投稿