目的:
クライアントからの 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要求を発行
スケッチ:
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 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | // +==========================================================================+ // | 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 件のコメント:
コメントを投稿