目的:
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のテキストファイルをダウンロードする 」を参照 )
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 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | #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 件のコメント:
コメントを投稿