目的:
WiFi設定(接続先設定、IPアドレス 等)をスケッチには記述せず、スマホ等から設定できる様にする。背景:
これまで WiFI設定をスケッチの中で定義していたが、これだと、WiFi設定変更の度にコンパイルをしなけらばならない。この為、APモード(アクセスポイントモード) で接続してWiFi接続先設定ができる様にし、スケッチに WiFI 環境の SSID や パスワードを書き込まなくて良くしたい。
*APモード : APモードは、ESP32が無線LAN のアクセスポイント(親機)となり、スマホ等から直接接続できるモード。この場合、ESP32 と スマホの間は独立のネットワークとなり、スマホ等からは ESP32 への接続のみとなる。
動作概要:
・softAP で APモードでサーバ起動し、スマホ等から WiFi接続設定を行う。(APモードの時の ESP32 の SSID,パスワードは 固定値)
・設定したWiFi接続情報は、SPIFFS で 設定ファイルに保存する。
・設定ファイルが有り、接続先が設定されている場合は STA(ステーション)モードでサーバー起動する。 ・STAモードで 接続できなかった場合は APモードでサーバー起動する。
・APモードのまま、メインの動作も可能。
接続手順:
- 最初は、接続設定がないため、ESP32 は AP モードで起動。
- スマホ等から、WiFi接続先として
SSID : ESP32_AP
パスワード : password
で接続できる。 - 接続後、ブラウザで "192.168.4.1" にアクセスすると、下記設定画面が表示される。
- WiFi接続設定(SSID, PASSWORD, IPアドレス等) を設定し、STA MODE を選択して "設定"ボタンを押下すると、 ESP32 がリブートして 設定した WiFi 親機に接続する。
- スマホ等から、ブラウザで設定した IPアドレスにアクセスすると、下記 LED調光画面が表示される。
- LED 調光画面から、WiFi 設定画面 ボタンを押下すると再度 WiFiの設定画面に遷移する。
- WiFi 親機に接続できなかった場合は、再度 AP モードで立ち上がる。
- 設定画面で、AP MODE を選択した場合は、AP モードのまま、LED調光画面に遷移する。
例:
LED をPWM で調光する。 をベースに WiFi 設定画面を追加。スケッチは、長くなった来た為、ファイルを .ino の拡張子で
1. メイン用 : 各変数等の設定, setup, loop を記述
2. 設定用 :主にWiFi 設定に使用する処理を記述
3. LED調光用:主にLED調光に使用する処理を記述
の 3つに分割。( ファイル分割 参照 )
各処理の説明等は、コメントで記入。
その他 覚書などを、下部に記載。
< 各画面サンプル >
WiFi 設定画面
接続先の SSID,パスワード, ESP32 の IPアドレス等を設定。
接続モード (AP/STA) を設定
LED調光の画面
ON ボタンを押下する度に LED の明るさが増す。("LED を PWM で調光する" 同様 )
WiFi設定画面への移行用ボタンを追加
< WiFi 設定画面用 HTML >
<!DOCTYPE html><html lang='ja'><head><meta charset='UTF-8'> <style> #base {font-size:16pt; text-align:center; width:600px; border:solid 4px #00000000; background-color:#c0c0c0; } #text_box {height: 25px; font-size:12pt; float:left ; text-align:left; width:45%;} #input_box {height: 25px; font-size:12pt; float:right; text-align:left; width:55%;} #ip_box {height: 25px; font-size:12pt; float:right; text-align:left; width:15%;} #radio_box {font-size:12pt; clear:both; margin : 0% 20% ; width : 60% ;} #button {font-size:12pt; clear:both; width 50%} #foot {font-size:16pt; clear:both;} input.val {width: 90%;} input.ip {width: 20%;} input.button {margin:10px 10% ; width: 25%;} input.radio {margin:10px 0px 0px 15% ; } </style> <title>設定画面</title></head> <body> <div id="base"> <p>設定画面</p> <div id="text_box"> <span> WiFi 接続先 SSID </span> </div> <form method="get"> <div id="input_box"> <input class='val' type='text' name='ssid' id='ssid' value=$ssid> </div> <div id="text_box"> <span> WiFi 接続先 PASSWORD </span> </div> <div id="input_box"> <input class='val' type='text' name='pass' id='pass' value=$pass> </div> <div id="text_box"> <span> WiFi 接続 IP アドレス </span> </div> <div id="input_box"> <input class='ip' type='number' name='ip1' id='ip1' min=0 max=255 value=$ip1 > <input class='ip' type='number' name='ip2' id='ip2' min=0 max=255 value=$ip2 > <input class='ip' type='number' name='ip3' id='ip3' min=0 max=255 value=$ip3 > <input class='ip' type='number' name='ip4' id='ip4' min=0 max=255 value=$ip4 > </div> <div id="text_box"> <span> WiFi 接続 サブネットマスク</span> </div> <div id="input_box"> <input class='ip' type='number' name='sn1' id='sn1' min=0 max=255 value=$sm1 > <input class='ip' type='number' name='sn2' id='sn2' min=0 max=255 value=$sm2 > <input class='ip' type='number' name='sn3' id='sn3' min=0 max=255 value=$sm3 > <input class='ip' type='number' name='sn4' id='sn4' min=0 max=255 value=$sm4 > </div> <div id="text_box"> <span> WiFi 接続 デフォルトゲートウェイ</span> </div> <div id="input_box"> <input class='ip' type='number' name='gw1' id='gw1' min=0 max=255 value=$gw1 > <input class='ip' type='number' name='gw2' id='gw2' min=0 max=255 value=$gw2 > <input class='ip' type='number' name='gw3' id='gw3' min=0 max=255 value=$gw3 > <input class='ip' type='number' name='gw4' id='gw4' min=0 max=255 value=$gw4 > </div> <div id="text_box"> <span> WiFi 接続 DNSアドレス</span> </div> <div id="input_box"> <input class='ip' type='number' name='dns1' id='dns1' min=0 max=255 value=$dns1 > <input class='ip' type='number' name='dns2' id='dns2' min=0 max=255 value=$dns2 > <input class='ip' type='number' name='dns3' id='dns3' min=0 max=255 value=$dns3 > <input class='ip' type='number' name='dns4' id='dns4' min=0 max=255 value=$dns4 > </div> <div id="radio_box"> <input class='radio' type='radio' name='wifi_stamode' id='rad_sta' value='sta' $checked_sta > STA MODE <input class='radio' type='radio' name='wifi_stamode' id='rad_ap' value='ap' $checked_ap > AP MODE </div> <div id="button"> <input class='button' type='submit' name='set' id='set' value='設定'> </div> </form> <div id="foot"> <span>$footer</span> </div> </div> </body> </html>
< LED調光用 HTML >
<!DOCTYPE html><html lang='ja'><head><meta charset='UTF-8'> <style> #base {font-size:16pt; text-align:center; width:400px; border:solid 4px #93ff93; background-color:#f0f0f0; } #text_box {height: 30px; font-size:12pt; float:left ; text-align:left; width:45%;} #button {font-size:12pt; clear:both; width 50%} #foot {font-size:16pt; clear:both;} input {margin:8px;width:100px;} div {font-size:16pt;text-align:center;} </style> <title>Color LED Controller</title></head> <body> <div id="base"> <p>LED ON/OFF</p> <form method='get'> <input type='submit' name='on' value='ON' /> <input type='submit' name='off' value='OFF' /> </form> <form method="get"> <div id="button"> <input class='button' type='submit' name='config' id='config' value='WiFi設定画面'> </div> </form> <div id="foot"> <span>$footer</span> </div> </div> </body> </html>
< スケッチ (メイン) >
#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 ="" ; // リブートメッセージ用 WiFiServer server(80); String html_CONF ; // 設定用 HTML String html_MAIN ; // メイン HTML // 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("/Config.html",html_CONF) ; // html_CONF に Config.html を格納 // 本体 HTML ファイルの読み込み ---------------------------------------------- res = rd_SPIFFS("/main.html",html_MAIN) ; // html_MAIN に main.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 = "" ; // クライアントからの入力用 // HTML クライアント処理 ------------------------------------------------------ if (client) { Serial.println(" +++++++++++++++++ new client! +++++++++++++++++ "); while (client.connected()) { // クライアントから接続されたとき if (client.available()) { // 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 { // メイン用 処理 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 { // 次にメイン画面なら send_MAIN_html(client) ; // メイン HTML 送信 config_exec = false ; // } // } // # ifdef DEBUG_HTML // Serial.println("Send HTML") ; // # endif // break ; // ループ終了 } // //------------------------------------------------------------------- } } // 接続が切れた場合 ------------------------------------------------------ client.stop(); Serial.println("client disonnected"); Serial.println("----------------------------------------------------"); } if (stamode != sta_exec) { // sta_mode が変わった場合 Serial.println("------------------- リブートします------------------- "); delay(500); // ESP.restart() ; // リブート } else { } // -------------------------------------------------------------------------- }
< スケッチ (WiFi設定用) >
// ***************************************************************************** // * 初期設定ファイル をリードし、グローバル変数に値をセットする * // ***************************************************************************** int rd_config() { // File fp ; // 設定ファイル用ファイルポインタ int result = 0 ; // 戻り値 // if (SPIFFS.exists("/config.txt")) { // 設定ファイル存在確認 // ファイルがあった場合 ---------------------// result = rd_SPIFFS("/config.txt",s_config) ; // s_config に config.txt を格納 } else { // // ファイルが無かった場合 -------------------// Serial.println("設定ファイルなし") ; // 無かったら、APモード result = -1 ; // } // // ファイルが読み込めたら、グローバル変数にセットする if (result == 0) // # ifdef DEBUG // デバッグ用表示 Serial.println("--- s_config --- ") ; // Serial.println(s_config ) ; // # endif // set_conf2param() ; // s_config の内容を変数に設定 // 初期設定ファイルの状態で wifiモード, 画面モードを設定 ---------------------- if (result != -1) { // 変数に設定できた場合 if (( strcmp(wifi_ssid,"") ==0) || (strcmp(wifi_pass,"") ==0)) { // ssid,pass 設定なければ stamode = false ; // APモード if ( strcmp(wifi_mode,"ap") == 0) // wifi_mode が "ap" なら config_mode = false ; // メイン画面 else // wifi_mode が "ap" でなければ config_mode = true ; // 初期設定画面 } else { // ssid,pass の設定があれば、 config_mode = false ; // メイン画面 if ( strcmp(wifi_mode,"ap") == 0) // wifi_mode が "ap" なら stamode = false ; // APモード else // "ap" でなければ stamode = true ; // STAモード } } else { // 変数に設定できなかった場合 stamode = false ; // APモード config_mode = true ; // 初期設定画面 } return result ; // } // ---------------------------------------------------------------------------- // - 設定ファイルの内容を グローバル変数に 設定する - // ---------------------------------------------------------------------------- void set_conf2param() { int pos = 0 ; int npos = 0 ; String s_work ; String s_name ; String s_data ; // 記載内容を順次処理 ( 設定情報を取り出し、グローバル変数に設定する ) ------ while(1) { if (s_config.charAt(pos) == '/') { // 先頭が '/' なら 次の行へ npos = s_config.indexOf('\n',pos) ; // pos = npos + 1 ; // } else { // npos = s_config.indexOf(':',pos) ; // ':' までの文字をs_name に取得 if (npos == -1) break ; // 見つからなければ終了 s_name = s_config.substring(pos,npos) ; // s_name.trim() ; // pos = npos+1 ; // ポインタを ':' の次へ npos = s_config.indexOf('\n',pos) ; // '\n' までの文字をs_data に取得 if (npos == -1) npos = s_config.length() ; // s_data = s_config.substring(pos,npos) ; // s_data.trim() ; // pos = npos+1 ; // set_param(s_name,s_data) ; // 取得した内容をグローバル変数に設定 } // } // } // // - 設定内容を判定し、グローバル変数に設定 ------------------------------------ void set_param(String &name, String &data) { // if (name.compareTo("wifi_ssid")==0) { // 'wifi_ssid' の場合 data.toCharArray(wifi_ssid,128) ; // } // if (name.compareTo("wifi_pass")==0) { // 'wifi_pass' の場合 data.toCharArray(wifi_pass,128) ; // } // if (name.compareTo("wifi_ip")==0) { // 'wifi_ip' の場合 wifi_ip = stoip(data) ; // 取得情報(文字列)をIPAddressに変換 } // if (name.compareTo("wifi_gw")==0) { // 'wifi_gw' の場合 wifi_gw = stoip(data) ; // } // if (name.compareTo("wifi_sm")==0) { // 'wifi_sm' の場合 wifi_sm = stoip(data) ; // } // if (name.compareTo("wifi_dns")==0) { // 'wifi_dns' の場合 wifi_dns = stoip(data) ; // } // if (name.compareTo("wifi_mode")==0) { // 'wifi_mode' の場合 data.toCharArray(wifi_mode,16) ; // } // } // // - 文字列 から IPAddress へ変換 ---------------------------------------------- IPAddress stoip(String &data) { // IPAddress ip ; String num = "" ; int pos = 0 ; while(data.charAt(pos) != '.') { // 先頭から '.' までの文字を取得 num += data.charAt(pos++) ; // } // ip[0] = num.toInt() ; // 数値に変換して 第1オクテット に 代入 pos++ ; // '.' の次から num=""; // while(data.charAt(pos) != '.') { // '.' までの文字を取得 num += data.charAt(pos++) ; // } // ip[1] = num.toInt() ; // 数値に変換して 第2オクテットに代入 pos++ ; // '.' の次から num=""; // while(data.charAt(pos) != '.') { // '.' までの文字を取得 num += data.charAt(pos++) ; // } // ip[2] = num.toInt() ; // pos++ ; // '.' の次から num=""; // while(data.charAt(pos) != '.') { // '.' または 最後まで の 文字を取得 num += data.charAt(pos++) ; // if (pos > data.length()) break ; // } // ip[3] = num.toInt() ; // 数値に変換して 第4オクテットに代入 // return ip ; // IPAddress を戻り値とする } // // **************************************************************************** // * アクセスポイント モードで サーバーを起動 * // **************************************************************************** void start_AP_server() { Serial.println(" AP Server exec") ; WiFi.softAP(ssid, pass); // SSIDとパスの設定 delay(100); // delayが必要 WiFi.softAPConfig(ip, ip, subnet); // IP address, gateway, subnetmask の設定 IPAddress myIP = WiFi.softAPIP(); // WiFi.softAPIP()でWiFi起動 server.begin(); // サーバーを起動(htmlを表示させるため) } // **************************************************************************** // * デバッグ表示用 * // **************************************************************************** void disp_mode() { # ifdef DEBUG_HTML // デバッグ用表示 Serial.print("config_mode - exec : ") ; // 設定画面か メイン画面か if (config_mode) // 変数の状態と実行状況を表示 Serial.print("Config MODE - ") ; // else // Serial.print("Main MODE - ") ; // if (config_exec) // Serial.println("Config MODE") ; // else // Serial.println("Main MODE") ; // // Serial.print("wifi_mode - exec : ") ; // Wifi モードを if (stamode) // 変数の状態と実行状況を表示 Serial.print("STA - ") ; // else // Serial.print("AP - ") ; // if (sta_exec) // Serial.println("STA") ; // else // Serial.println("AP") ; // # endif // } // **************************************************************************** // * クライアントからのフォームデータを変数にセットし、設定ファイルに書き出す * // **************************************************************************** void set_form2param(String &line) { String s_work ="" ; // クライアントからのデータを グローバル変数にセットする。 ------------------ if (line.indexOf("GET /?ssid=") != -1) { // wifi_ssid s_work = getvalue_s(line,"?ssid=") ; // ssid に続く文字列を取得 s_work.toCharArray(wifi_ssid,128) ; // 変数にセット } if (line.indexOf("pass=") != -1) { // wifi_pass s_work = getvalue_s(line,"pass=") ; // pass に続く文字列を取得 s_work.toCharArray(wifi_pass,128) ; // 変数にセット } if (line.indexOf("ip1=") != -1) { // wifi_ip wifi_ip[0] = getvalue_i(line,"ip1=") ; // ip1 に続く数値を変数にセット } if (line.indexOf("ip2=") != -1) { // wifi_ip[1] = getvalue_i(line,"ip2=") ; // ip2 に続く数値を変数にセット } if (line.indexOf("ip3=") != -1) { // wifi_ip[2] = getvalue_i(line,"ip3=") ; // ip3 に続く数値を変数にセット } if (line.indexOf("ip4=") != -1) { // wifi_ip[3] = getvalue_i(line,"ip4=") ; // ip4 に続く数値を変数にセット } if (line.indexOf("gw1=") != -1) { // wifi_gw wifi_gw[0] = getvalue_i(line,"gw1=") ; // gw1 に続く数値を変数にセット } if (line.indexOf("gw2=") != -1) { // wifi_gw[1] = getvalue_i(line,"gw2=") ; // gw2 に続く数値を変数にセット } if (line.indexOf("gw3=") != -1) { // wifi_gw[2] = getvalue_i(line,"gw3=") ; // gw3 に続く数値を変数にセット } if (line.indexOf("gw4=") != -1) { // wifi_gw[3] = getvalue_i(line,"gw4=") ; // gw4 に続く数値を変数にセット } if (line.indexOf("sm1=") != -1) { // wifi_sm wifi_sm[0] = getvalue_i(line,"sm1=") ; // sm1 に続く数値を変数にセット } if (line.indexOf("sm2=") != -1) { // wifi_sm[1] = getvalue_i(line,"sm2=") ; // sm2 に続く数値を変数にセット } if (line.indexOf("sm3=") != -1) { // wifi_sm[2] = getvalue_i(line,"sm3=") ; // sm3 に続く数値を変数にセット } if (line.indexOf("sm4=") != -1) { // wifi_sm[3] = getvalue_i(line,"sm4=") ; // sm4 に続く数値を変数にセット } if (line.indexOf("dns1=") != -1) { // wifi_dns wifi_dns[0] = getvalue_i(line,"dns1=") ; // dns1 に続く数値を変数にセット } if (line.indexOf("dns2=") != -1) { // wifi_dns[1] = getvalue_i(line,"dns2=") ; // dns2 に続く数値を変数にセット } if (line.indexOf("dns3=") != -1) { // wifi_dns[2] = getvalue_i(line,"dns3=") ; // dns3 に続く数値を変数にセット } if (line.indexOf("dns4=") != -1) { // wifi_dns[3] = getvalue_i(line,"dns4=") ; // dns4 に続く数値を変数にセット } if (line.indexOf("stamode=") != -1) { // stamode set s_work = getvalue_s(line,"stamode=") ; // ssid に続く文字列を取得 s_work.toCharArray(wifi_mode,16) ; // 変数にセット if (s_work == "sta") { // 設定値により、モードをセット stamode = true ; // config_mode = false ; // } else { // stamode = false ; // config_mode = false ; // } } // グローバル変数を 設定ファイルに書き出す ----------------------------------- wr_config() ; // 設定を初期設定ファイルに書き出し } // 要素名に続く値(文字列)を取得する -------------------------------------------- String getvalue_s(String &line,String param) { String val="" ; int pos = 0 ; if ((pos=line.indexOf(param)) != -1) { // 要素名の位置を取得 pos += param.length() ; // while((line.charAt(pos) != '&') & (line.charAt(pos) != '\n')) { val += line.charAt(pos++) ; // '&' か 行末 まで文字を取得 } // } // return val ; // 取得した文字列を返す } // 要素名に続く値(数値)を取得する --------------------------------------------- int getvalue_i(String &line,String param) { String val="" ; int pos = 0 ; if ((pos=line.indexOf(param)) != -1) { // 要素名の位置を取得 pos += param.length() ; // while((line.charAt(pos) >= '0') & (line.charAt(pos) <= '9')) { val += line.charAt(pos++) ; // 数値でなくなるまで文字を } // 取得 } // return val.toInt() ; // 数値に変換して返す } // ----------------------------------------------------------------------------- // - グローバル変数の内容を設定ファイルに書き出す - // ----------------------------------------------------------------------------- void wr_config() { char s_work[128] ; File fp ; // String に 変数の内容を書き込む ------------------------------------------- sprintf(s_work,"wifi_ssid : %s\n",wifi_ssid) ; // s_config = String(s_work) ; // sprintf(s_work,"wifi_pass : %s\n",wifi_pass) ; // s_config += String(s_work) ; // sprintf(s_work,"wifi_ip : %3d.%3d.%3d.%3d\n",wifi_ip[0],wifi_ip[1],wifi_ip[2],wifi_ip[3]) ; s_config += String(s_work) ; // sprintf(s_work,"wifi_sm : %3d.%3d.%3d.%3d\n",wifi_sm[0],wifi_sm[1],wifi_sm[2],wifi_sm[3]) ; s_config += String(s_work) ; // sprintf(s_work,"wifi_gw : %3d.%3d.%3d.%3d\n",wifi_gw[0],wifi_gw[1],wifi_gw[2],wifi_gw[3]) ; s_config += String(s_work) ; // sprintf(s_work,"wifi_dns : %3d.%3d.%3d.%3d\n",wifi_dns[0],wifi_dns[1],wifi_dns[2],wifi_dns[3]) ; s_config += String(s_work) ; // sprintf(s_work,"wifi_mode : %s\n",wifi_mode) ; // s_config += String(s_work) ; // // 設定ファイルに書き込む ---------------------------------------------------- fp = SPIFFS.open("/config.txt",FILE_WRITE) ; // 設定ファイルを開く if (!fp) { Serial.println(" 設定ファイル オープンエラー !!") ; } else { // 初期設定ファイル書き込み ------------------------------------------------- if(fp.print(s_config)) { // ファイルに書き込み Serial.println("s_config written") ; // 終了メッセージ } else { // Serial.println("s_config write error !!") ; // 失敗メッセージ } // fp.close() ; // ファイルクローズ } // // } // // ***************************************************************************** // * HTML 送信処理 * // ***************************************************************************** // ---------------------------------------------------------------------------- // - CONF_HTML 送信 ----------------------------------------------------------- // ---------------------------------------------------------------------------- void send_CONF_html(WiFiClient client) { String htmlwk ; // 変数置換え処理 ------------------------------------------------------------ htmlwk = html_CONF ; htmlwk.replace("$ssid",String(wifi_ssid)) ; htmlwk.replace("$pass",String(wifi_pass)) ; htmlwk.replace("$ip1",String(wifi_ip[0])) ; htmlwk.replace("$ip2",String(wifi_ip[1])) ; htmlwk.replace("$ip3",String(wifi_ip[2])) ; htmlwk.replace("$ip4",String(wifi_ip[3])) ; htmlwk.replace("$sm1",String(wifi_sm[0])) ; htmlwk.replace("$sm2",String(wifi_sm[1])) ; htmlwk.replace("$sm3",String(wifi_sm[2])) ; htmlwk.replace("$sm4",String(wifi_sm[3])) ; htmlwk.replace("$gw1",String(wifi_gw[0])) ; htmlwk.replace("$gw2",String(wifi_gw[1])) ; htmlwk.replace("$gw3",String(wifi_gw[2])) ; htmlwk.replace("$gw4",String(wifi_gw[3])) ; htmlwk.replace("$dns1",String(wifi_dns[0])) ; htmlwk.replace("$dns2",String(wifi_dns[1])) ; htmlwk.replace("$dns3",String(wifi_dns[2])) ; htmlwk.replace("$dns4",String(wifi_dns[3])) ; if (stamode) { // ステーションモード時 htmlwk.replace("$checked_sta","checked") ; // htmlwk.replace("$checked_ap","") ; // } else { // アクセスポイントモード時 htmlwk.replace("$checked_sta","") ; // htmlwk.replace("$checked_ap","checked") ; // } htmlwk.replace("$footer",foot_msg ) ; // -------------------------------------------------------------------------- send_html(client,htmlwk) ; // HTML 送信処理 }
< スケッチ (LED調光用) >
// ***************************************************************************** // * SPIFFS ファイルを String に読み込む * // ***************************************************************************** int rd_SPIFFS(String fname, String &sname) { // File fp = SPIFFS.open(fname,"r") ; // ファイルをオープンする if (!fp) { // オープン失敗の場合 Serial.print(fname) ; // Serial.println(" : file open error") ; // return -1 ; // 戻り値 -1 }else { // オープン出来たら sname = fp.readString() ; // String変数に読み込む fp.close() ; // } // return 0 ; // オープン出来た時のみ } // 戻り値 0 // // **************************************************************************** // * ステーションモードで サーバーを起動 * // **************************************************************************** void start_STA_server() { int lpcnt = 0 ; // ループカウント int lpcnt2 = 0 ; // ループカウント2 WiFi.config(wifi_ip, wifi_gw, wifi_sm, wifi_dns); // Set fixed IP address delay(10) ; // WiFi.begin(wifi_ssid, wifi_pass); // wifi 開始 lpcnt = 0 ; // lpcnt2 = 0 ; // while (WiFi.status() != WL_CONNECTED) { // 接続確認 lpcnt += 1 ; // if (lpcnt > 4) { // WiFi.begin(wifi_ssid, wifi_pass); // 4回目(2秒) で再度開始指示 lpcnt = 0 ; // lpcnt2 += 1 ; // } // if (lpcnt2 > 5) { // 2秒x5 接続できなければ、 stamode = false ; // APモードにして ESP.restart() ; // 再起動 } // Serial.print("."); // delay(500); // 0.5秒毎にチェック } // server.begin(); // サーバー開始 } // ***************************************************************************** // * HTML 送信処理 * // ***************************************************************************** // ---------------------------------------------------------------------------- // - CONF_HTML 送信 - // ---------------------------------------------------------------------------- void send_MAIN_html(WiFiClient client) { String htmlwk ; htmlwk = html_MAIN ; // htmlwk に HTML をコピー htmlwk.replace("$footer",foot_msg ) ; // 変数を値に置き換える send_html(client,htmlwk) ; // HTML 送信処理 } // ---------------------------------------------------------------------------- // - HTML 送信処理 - // ---------------------------------------------------------------------------- void send_html(WiFiClient client, String &html ) { client.println("HTTP/1.1 200 OK"); // client.println("Content-type:text/html"); // client.println(); // // client.print(html) ; // # ifdef DEBUG // Serial.println( " --- send html --- "); // #endif // } // ***************************************************************************** // * メイン処理 * // ***************************************************************************** void proc_main(String &line) { String s_work ="" ; if (line.indexOf("GET /?config=") != -1) { // config Serial.println(" -- Set config_mode truw--") ; config_mode = true ; } if (line.indexOf("GET /?on") != -1) { // "on"が押下された時 brightness +=25 ; // 明るさを +25 Serial.print("brightness value : "); Serial.println(brightness); // -- for ledc ledcWrite(0, brightness) ; // チャネル#0 に Duty値設定 } if (line.indexOf("GET /?off") != -1) { // "off"が押下された時 brightness = 0 ; // 明るさを "0" Serial.print("brightness value : "); Serial.println(brightness); // -- for ledc ledcWrite(0, brightness) ; // チャネル#0 に Duty値設定 } } // -----------------------------------------------------------------------------
以下、覚書など。
<メイン スケッチ>
(行#8~12)APモード用 WiFi 設定。
APモードで立ち上がった場合 、スマホから、ここに設定した SSID が見える。
パスワードは、この値 ("password") で接続。
接続後、設定した IPアドレス (192.168.4.1) にアクセスすると、設定画面が表示される。
(行#14~18)
接続モード等のフラグ定義
(行#20~29)
WiFi接続設定用変数。
この変数を、SPIFFS で 設定ファイルに保存する。
初期値は、仮の値。
(行#33,34)
HTML 格納用 String変数
(行#36 ~ 39)
LED調光用変数
(行#43~79)
Arduino setup 関数
内容は、コメント参照。
LED調光の ledc の dutyビット数は、8bit とした。
(行# 86~143)
Arfuino loop 関数
内容はコメント参照。
APかSTAか、初期設定がメイン処理かで、処理を選択。
(行#145~159)
WiFi 接続モードが変わった場合、リブートする。
<WiFi 設定用 スケッチ >
(行#1~134)初期設定ファイルをリードして、変数に設定。
初期設定ファイルのリード結果により、WiFi接続モードや画面モードを選択する。
SFPFFS ファイルリードの関数は、LED調光用 のファイルに記述。
(行#135~145)
APモードでサーバー起動
以下の手順で、サーバーを開始する。
WiFi.softAP(ssid,password) : AP としての SSID と パスワードを設定
WiFi.softAPConfig(ip adr, gateway adr, subnetmask) : サーバーのIPアドレスの設定
WiFi.softAPIP() : サーバーをAPモードで起動
server.begin() : サーボー開始
(行#174~319)
クライアントからのフォームデータを解析して変数に設定し、内容を初期設定ファイルに書き込む。
(行#320~361)
WiFI設定用 HTML の変数部分を 値の置換え、送信する。
送信の関数は、LED調光用 のファイルに記述。
<LED調光用 スケッチ >
(行#1~15)SFPFFS ファイルリードの関数。
HTML 初期設定ファイルのリードに使用。
(行#17~45)
STAモードでサーバー起動。
一定時間(約2秒)以内に接続できなければ、再度 WiFi 開始を実行。
(リセット時等、1回置きに接続できない現象 (原因不明) の対策。)
約 10秒以内に接続できなければ、APモードにして再起動。
(行#46~61)
LED調光用 HTML の変数部分を 値の置換え、送信する。
(行#63~76)
HTML 送信処理
(行#78~104)
LED調光処理
クライアントからのフォームデータを解析してLEDの調光を行う。
”LED をPWM で調光する” から少し変更。
1. PWM の DUTY設定を 8bit にし、 0~255 の範囲とした。
2. ON ボタン 押下毎に 明るさを +25づつ加算する様にした。
私にとって、とっても 分かりやすい うまく書かれたソースです。
返信削除公開、ありがとうございます。
ひとつだけ、教えてください。
rd_SPIFFS() は どこに存在している Function なのでしょうか?
すみません、私の 見落としでした。
削除m(__)m
参照ありがとうございます。
削除記事が参考になれば幸いです。