目的:
クライアントからの POST 要求で LED ON/OFF できるようにする。POST 受信処理:
クライアントからのメッセージは、リクエスト行 (GET / POST 等 )
リクエストヘッダ
空行
メッセージボディ (POST のデータ等)
の順に送られ、GET要求の場合は メッセージボディが無く、POST要求ではメッセージボディに送信データが入る。
POST受信処理では、空行の後のメッセージボディを受信して解析する必要がある。
リクエスト行から空行の間は、行単位(最後が '\r\n'で終了) の為、GET要求の受信処理では行単位で処理 ( readStringUntil('\n') で 行末('\n') までを種付く) していたが、メッセージボディの最後は ('\r\n') になるとは限らない為、readStringUntil('\n')で データを取得すると、('\n') が見つからずに タイムアウト (Default 1秒) まで待たされる。この為、受信バイト数分を取得 (メッセージボディ全てを一度に取得) して処理することとした。
例:
LED ON/OFF (固定 IPアドレス) の スケッチ に POST 受信処理を追加した例を以下に示す。WEB画面:
GET 用の ON, OFF ボタン と
POST 用 の ON, OFF ボタン を 設置
POST 用 の ON, OFF ボタン を 設置
POST_ON, POST_OFF 押下時、POST要求を発行
スケッチ:
// +==========================================================================+ // | WiFi LED ON/OFF TEST ( GET / POST ) | // +==========================================================================+ // #include <WiFi.h> // WiFi 用 // // ---------------------------------------------------------------------------- // 各種設定 -- // ---------------------------------------------------------------------------- const char* ssid = "hogehoge" ; // WiFi AP SSID const char* password = "hogehogepassy"; // WiFi AP パスワード // String html; // HTML 格納用 // IPAddress ip(192, 168, 1, 32); // ESP32 IPアドレス IPAddress gateway(192,168, 1, 1); // ゲートウェイアドレス IPAddress subnet(255, 255, 255, 0); // サブネットマスク IPAddress DNS(192, 168, 1, 90); // DNS アドレス // WiFiServer server(80); // // // ---------------------------------------------------------------------------- // 初期設定 -- // ---------------------------------------------------------------------------- void setup() // { // Serial.begin(115200); // シリアル出力開始 pinMode(2, OUTPUT); // LED 用 PIN 設定 // WiFi.config(ip, gateway, subnet, DNS); // ESP32 WiFi 設定 delay(10); // // Serial.println(); // デバッグ用出力 Serial.print("Connecting to "); // Serial.println(ssid); // // WiFi.begin(ssid, password); // WiFi 開始 // while (WiFi.status() != WL_CONNECTED) { // delay(500); // Serial.print("."); // } // // Serial.println(""); // デバッグ用出力 Serial.println("WiFi connected."); // Serial.println("IP address: "); // Serial.println(WiFi.localIP()); // // server.begin(); // WiFi サーバ 開始 // } // // // ---------------------------------------------------------------------------- // メインループ -- // ---------------------------------------------------------------------------- void loop(){ // String line = "" ; // データ格納用 char buf[257] ; // int n ; bool post_req = false ; // ポスト要求フラグ WiFiClient client = server.available(); // listen for incoming clients // if (client) { // if you get a client, Serial.println("***** Client access start *****"); // デバッグ用出力 while (client.connected()) { // client が接続されている間 if (client.available()) { // client からのデータがある間 line = client.readStringUntil('\n'); // データを1行分取得 Serial.println(line); // デバッグ用出力 if (line.indexOf("POST /") != -1) { // "POST /" 受信の場合 post_req = true ; // LED on } // if (line.indexOf("GET /?on") != -1) { // "GET /?on" 受信の場合 digitalWrite(2, HIGH); // LED on } // if (line.indexOf("GET /?off") != -1) { // "GET /?off" 受信の場合 digitalWrite(2, LOW); // LED off } // // 空行を受信した場合 --------------- // if (line.length() == 1 && line[0] == '\r'){ // 空行の場合 if (post_req) { // POST 要求の場合 line = "" ; // データ格納用変数初期化 while (n=client.available()) { // 残りデータを全て受信 if (n<256){ // client.readBytes(buf,n) ; // buf[n] = 0 ; // } else { // client.readBytes(buf,256) ; // buf[256] = 0 ; // } // line += buf ; // } // // POST データ処理 ------------- // Serial.println(line); // デバッグ用出力 if (line.indexOf("post_on") != -1) { // "on" の場合 digitalWrite(2, HIGH); // LED on } // if (line.indexOf("post_off") != -1) { // "off" の場合 digitalWrite(2, LOW); // LED off } // } // // 終了処理 ---------------------------// send_response(client) ; // Serial.println("Send HTML !!"); // break; // break while loop } // } // } // delay(1); // give the web browser time to receive the data // close the connection: --------------------// client.stop(); // Serial.println("Client Disconnected."); // Serial.println("--------------------------------------------------"); } // } // // ------------------------------------------------------------------ void send_response(WiFiClient client) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println(); // the content of the HTTP response follows the header: client.print("<!DOCTYPE html><html lang='ja'><head><meta charset='UTF-8'>" ) ; client.print("<style>input {margin:8px;width:100px;}div {font-size:16pt;text-align:center;width:250px;border:solid 4px #93ff93;}</style>" ) ; client.print("<title>Color LED Controller</title></head>" ) ; client.print("<body><div><p>LED ON/OFF</p>" ) ; client.print("<form method='get'>" ) ; client.print("<input type='submit' name='on' value='GET_ON' /><input type='submit' name='off' value='GET_OFF' />" ) ; client.print("</form>" ) ; client.print("<form method='post'>" ) ; client.print("<input type='submit' name='post_on' value='POST_ON' /><input type='submit' name='post_off' value='POST_OFF' />" ) ; client.print("</form>" ) ; client.print("</div></body></html>" ) ; client.println(); Serial.println( " --- send responce --- "); }
以下、メモ
・詳細は コメント参照。
(行#58~60)
POST処理用 変数定義。
(行#69~71)
リクエスト行が POST の場合に POST処理フラグを立てる。
(行#80~100)
POST 処理フラグが 立っていた場合のPOST処理。
(行#81~91) で メッセージボディのデータを取得。
readStringUntil('\n') や readString() を使用すると、タイムアウト(Default 1000mS) まで待ってしまい、ボタンを押下してから LED の ON/OFF まで 1秒かかる。
この為、残りデータ数 (client.available() の戻り値) 分を client.readBytes() で取得している。
(行#92~98) で メッセージボディのデータを処理。
処理内容は、GET と同様。
0 件のコメント:
コメントを投稿