目的:
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
参照ありがとうございます。
削除記事が参考になれば幸いです。