目的:
WEBブラウザからの文字列受信にタイムアウト処理を追加する。問題点:
「SPIFFSのテキストファイルをダウンロードする 」等 WEBサーバー動作で、クライアント接続後 に client.connected() のまま何も文字列を受信しなかった場合に while 文のループを抜けなくなってしまう。文字列受信開始後に 最終行(空行) を受信せずに client.available() == 0 となった場合も同様。( clientclient.connected() のまま で )
対策:
一定時間 client.available() == 0 の状態が続いた場合、タイムアウトとして、ループを抜けて client.stop() を行う。タイムアウト時間は状況に応じて設定。start_time = millis() ; // 開始前の時刻を取得
while (client.connected()) {
if (client.available()) {
start_time = millis() ; // 文字列受信時の時刻に更新
|
} else {
if ( (millis() - start_time) > 3000 ) {
break ; // 3000 mS 受信がなければループを抜ける
}
}
例:
「SPIFFSのテキストファイルをダウンロードする 」の メインスケッチにタイムアウト処理を追加した例を示す。(メインスケッチ以外のファイルは 「SPIFFSのテキストファイルをダウンロードする 」を参照 )
#include <WiFi.h> // WiFi 使用の為 #include "FS.h" // SPIFFS 使用の為 #include "SPIFFS.h" // SPIFFS 使用の為 #define DEBUG_HTML // Debug用 Serial 表示制御用 #define DEBUG // Debug用 Serial 表示制御用 // AP モード用 WIFI 設定 --------------------------------------------- const char ssid[] = "ESP32_AP"; // SSID for softAP const char pass[] = "password"; // password for softAP const IPAddress ip(192, 168, 4, 1); // IPアドレス for softAP const IPAddress subnet(255, 255, 255, 0); // サブネットマスク for softAP // 動作モードフラグ --------------------------------------------------- bool stamode = true ; // WiFi STA 接続モード : true bool sta_exec = false ; // WiFi STA接続モード実行中フラグ bool config_mode = false ; // 初期設定モード ; true bool config_exec = false ; // 初期設定実行中フラグ // 設定ファイル用 ----------------------------------------------------- String s_config ; // 設定ファイル用 String char wifi_ssid[128] = "" ; // SSID for WiFi STA char wifi_pass[128] = "" ; // password for WiFi STA IPAddress wifi_ip(192,168,1,66) ; // IP Address for WiFi STA IPAddress wifi_gw(192,168,1,1) ; // gate way for WiFi STA IPAddress wifi_sm(255,255,255,0) ; // subnet mask for WiFi STA IPAddress wifi_dns(192,168,1,1) ; // dns address for WiFi STA char wifi_mode[16] = "" ; // wifi mode String foot_msg ="" ; // リブートメッセージ用 #define CLIENT_TIMEOUT 3000 // クライアントタイムアウト (mS) WiFiServer server(80); String html_CONF ; // 設定用 HTML String html_MAIN ; // メイン HTML String html_resp ; // LED 調光処理用 ---------------------------------------------------------------- // -- for ledc byte brightness = 0 ; // LED 明るさ設定 (0-255) // ----------------------------------------------------------------------------- // arduino 初期化処理 -- // ----------------------------------------------------------------------------- void setup() { int res = 0 ; // 結果格納用 (ワーク) Serial.begin(115200); // シリアル 開始 SPIFFS.begin(true) ; // SPIFFS 開始 // 初期設定用 HTML ファイルの読み込み --------------------------------------- res = rd_SPIFFS("/WiFi_Config.html",html_CONF) ; // html_CONF に Config.html を格納 // 本体 HTML ファイルの読み込み ---------------------------------------------- res = rd_SPIFFS("/main.html",html_MAIN) ; // html_MAIN に main.html を格納 // レスポンス用HTML ファイルの読み込み ---------------------------------------- res = rd_SPIFFS("/resp_cnfld.html",html_resp) ; // html_resp に resp_confld.html を格納 // 初期設定ファイルを読み込み、グローバル変数に設定し、wifi,画面モードを決定 --- res = rd_config() ; // // wifiモード(stamode) に応じて AP か STA かを選択してサーバー起動 ------------- if (stamode == false) { // APモードの場合 softAP WiFi 開始 start_AP_server() ; // APモードでサーバー起動 sta_exec = false ; // } else { // STAモードの場合 Wifi 開始 start_STA_server() ; // APモードでサーバー起動 sta_exec = true ; // } // // 実行中のモード (設定かメインか) を設定 ------------------------------------- if (config_mode) config_exec = true ; // config_mode なら config_exec を '1' else config_exec = false ; // Serial.println("Server start!"); // メイン処理用 初期化 ------------------------------------------------------ ledcSetup(0, 5000, 8); // channel 0 周波数 5000 Hz, 8 bit ledcAttachPin(2,0); // attach pin 2 to channel 0 ledcWrite(0, 0); // initialize channel 0 to off } // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // arduino メインループ処理 -- // ----------------------------------------------------------------------------- void loop() { WiFiClient client = server.available(); String htmlwk = "" ; // html 用 ワーク変数 String line = "" ; // クライアントからの入力用 int xhr = 0 ; // xhr 要求フラグ unsigned long start_time = 0 ; // タイムアウト監視開始時間 unsigned long wait_time = 0 ; // 開始/前回受信からの経過時間 // HTML クライアント処理 ------------------------------------------------------ if (client) { start_time = millis() ; // タイムアウト監視開始時間を更新 Serial.println(" +++++++++++++++++ new client! +++++++++++++++++ "); while (client.connected()) { // クライアントから接続されたとき if (client.available()) { // 受信文字列がある事 start_time = millis() ; // タイムアウト監視開始時間を更新 line = client.readStringUntil('\n'); // 1行分取得 # ifdef DEBUG_HTML // Serial.println(line) ; // # endif // if (line.indexOf("GET /?") != -1) { // GET 処理 if (config_mode) // 初期設定用 フォームデータ処理 set_form2param(line) ; // フォームデータを変数に格納 else { // メイン用 処理 xhr = proc_main(line) ; // フォームデータのメイン処理 } // } // // 最終行(空行)を受信した時 ------------------------------------------- if (line.length() == 1 && line[0] == '\r'){ // 最終行判定 if (stamode != sta_exec) { // sta_mode が変わった場合 if (strcmp(wifi_mode,"ap") == 0){ // リブートメッセージを設定 foot_msg = "アクセスポイントモードに移行します。<br> " ; foot_msg += "この画面を閉じてアクセスポイントに接続して下さい。" ; }else{ foot_msg = "ステーションモードに移行します。<br>"; foot_msg += "この画面を閉じて 設定したアドレスに接続して下さい。" ; } if (config_exec) { // 初期設定中なら send_CONF_html(client) ; // 初期設定 HTML 送信 } else { // メイン画面なら send_MAIN_html(client) ; // メイン HTML 送信 } // ( その後 リブート) } else { // sta_mode が変わらない場合 if (config_mode) { // 次に初期設定を表示するなら send_CONF_html(client) ; // 初期設定 HTML 送信 config_exec = true ; // } else { // 次にメイン画面なら if (xhr) { // XHR 応答の場合 send_resp_html(client) ; // XHR 応答 送信 } else { // HTML 送信なら send_MAIN_html(client) ; // メイン HTML 送信 config_exec = false ; // } // } // } // # ifdef DEBUG_HTML // Serial.println("Send HTML") ; // # endif // break ; // ループ終了 } // //------------------------------------------------------------------- } else { // 文字列受信していない時 wait_time = millis() - start_time ; // 前回受信からの時間を取得 if ((wait_time) > CLIENT_TIMEOUT) { // 文字列受信タイムアウト判定 Serial.print("タイムアウト :") ; // Serial.print(wait_time) ; // Serial.println(" mS") ; // break ; // ループ終了 } // } // } // 接続が切れた場合 ------------------------------------------------------ client.stop(); Serial.println("client disonnected"); Serial.println("----------------------------------------------------"); } if (stamode != sta_exec) { // sta_mode が変わった場合 Serial.println("------------------- リブートします------------------- "); delay(500); // ESP.restart() ; // リブート } else { } // -------------------------------------------------------------------------- }
(行#31)
タイムアウト時間 の define 文
(行#96,97)
タイムアウト処理用ローカル変数
(行#101,105)
開始時、文字列受信時の 監視開始時間を取得
(行#151~158)
client.available() == 0 時の処理。
タイムアウト時間を超えていたら break ;を実行
0 件のコメント:
コメントを投稿