まずは事件が
最近WiFiの基地局を変更した時の事なのですが、基地局にログインできなくなった
GoogleHomeとNatureRemoと動作確認中のESP8266に再設定を行う事態に陥りました。
3つの対応は以下のとうり
GoogleHome : 端末名.o のSSIDの局が出来て再設定を促している
再設定=> 設定ソフトを呼び出し、端末名.o の局に繋いで再設定
NatureRemo : なにやら表示灯が点滅している
再設定=> 設定ソフトを呼び出し、端末のリセットボタンを押し
端末固有名の局に繋いで再設定
ESP8266 : ぽか~~~ん(表示無し)
再設定=> 端末の強制AP接続モードボタンを押し、
端末固有名の局に繋いで再設定
正直NatureRemoとESP8266の再設定は、本体を触る必要があり面倒でした。
ESP8266はWiFi基地局との接続が1度切れると?
折角なので今回ESP8266の接続した基地局が電源OFF・ONとなると接続はどうなる
か確認してみました。 結果は高い頻度で未接続状態に陥る様です。
※我が家の運用実績はもっと良いので、接続復帰しても良いのですが・・・・
当然未接続に落ちても報告機能は無いので何も判りませんwww
そこで欲しい機能を考えた
現在作っているESP8266のソフトは絶対WiFiに接続できる前提で作っているが
WiFiがダウンしている状況でも動作して、WiFi復帰後は再接続を行えて、
WiFi未接続時は基地局モードになり、WebServerに接続してWiFiの再設定が
できるべきではないか?
今回の実験
・ソフト起動時はWiFi_AP_STAモードで、自分が基地局として立ち上がりつつ
設定にあるWiFi基地局への接続を試す。 並走のAPモードでは、後日追記
予定のWebserverでWiFi接続設定の変更画面を提供する。
・WiFi基地局への接続が確認できたら WiFi_AP_STAモードをWiFi_STAモードに
変更して、WiFi基地局へ再度接続を行う。(目的:リソース利用量の削減
・WiFi基地局の接続が累積で1時間接続できなかったらESP8266をリセット。
原因不明の基地局検知不良を想定したリセットです。
・WiFi基地局へ接続できない時は複数のESP8266がWiFiに繋がらないのを想定。
APモードの基地局名の重複を防ぐ為にMacアドレス末尾6桁を使う。
・とりあえず今回はWebServerの実装は無し。
これで基本機能は達成できそうな気がする。
でESP32の移植性はどうなのよ?
include文の変更で動作すると思います。(今回はESP32で作成してESP8266に移植)
APSTAモードも同様の挙動をしてくれるので、基本設計の方に感謝であります。
※ESP32の方が若干挙動不安定で、頻繁に基地局の接続が出来ない症状を確認して
います。(この実験コードが役に立っている)
そして出来たコード
思ったより少ないコードで出来た感じです。
このコードに以前作成した、WebServerソフトをセットしたら良い感じになるかな?
後はNTPでの時刻合わせ完了も待つコードを足すと、良い感じになりそうです。
#include <ESP8266WiFi.h>
const char* ssid = "guest";
const char* password = "guest";
char AP_SSID[13]; // アクセスポイントのSSID(自動生成)
bool WiFi_AP_STA_mode; // 現在の接続モード
bool WiFi_ConnectOnce; // WiFi接続時の最初の初期処理
int WiFi_TickCount; // ESP8266起動からのカウント(10秒)
int WiFi_LostCount = 0; // WiFi未接続のカウント
// 初期処理
// WIFI_AP_STAモードで起動します。
void setup() {
Serial.begin(115200);
delay(10);
WiFi_AP_STA_mode = true;
WiFi.mode(WIFI_AP_STA);
WiFi.disconnect(true);
uint8_t mac1[6];
WiFi.softAPmacAddress(mac1);
sprintf( AP_SSID, "ESPAP_%02X%02X%02X", mac1[3], mac1[4], mac1[5] );
WiFi.softAP( AP_SSID, "" );
Serial.print( "AP SSID name :" );
Serial.println( AP_SSID );
IPAddress myIP = WiFi.softAPIP();
WiFi.begin(ssid, password);
delay(100);
Serial.print("AP IP address: ");
Serial.println(myIP);
}
// WiFi接続チェック
int WiFi_ConnectCheck( ){
int WiFiStatus;
WiFiStatus = WiFi.status();
if( WiFiStatus==WL_CONNECTED ){
if( WiFi_AP_STA_mode==true ){
Serial.print("WiFi Reconnect[");
Serial.print(ssid);
Serial.println("]");
WiFi.disconnect(true);
WiFi.mode(WIFI_STA);
WiFi_AP_STA_mode = false;
WiFi.begin(ssid, password);
WiFi_ConnectOnce = false;
delay(1000);
return WL_DISCONNECTED;
}
if( WiFi_ConnectOnce!=true ){
Serial.print("WiFi Connect[");
Serial.print(ssid);
Serial.println("]");
WiFi_ConnectOnce = true;
WiFi_LostCount = 0;
}
return WiFiStatus;
}
// WiFi未接続時の処理
// 10秒毎にメッセージを表示します。
// WiFi未接続が360カウント蓄積すると、ESP8266をリセットします。
if( WiFi_TickCount==(millis()/10000) ) return WiFiStatus;
WiFi_TickCount = millis()/10000;
WiFi_LostCount++;
if( WiFi_LostCount>(6*60) ){
Serial.println("Can't connect WiFi network");
Serial.println("ESP8266 reset");
delay(1000);
ESP.reset();
delay(4000);
return WiFiStatus;
}
Serial.print("WiFi Start[");
Serial.print(WiFi_timeCount);
Serial.print(":");
Serial.print(ssid);
Serial.print(":");
switch( WiFiStatus ){
// case WL_CONNECTED: Serial.print("assigned when connected to a WiFi network;"); break; // ココは来ない
case WL_NO_SHIELD: Serial.print("assigned when no WiFi shield is present;"); break;
case WL_IDLE_STATUS: Serial.print("WL_IDLE_STATUS"); break;
case WL_NO_SSID_AVAIL: Serial.print("assigned when no SSID are available;"); break;
case WL_SCAN_COMPLETED: Serial.print("assigned when the scan networks is completed;"); break;
case WL_CONNECT_FAILED: Serial.print("assigned when the connection fails for all the attempts;");break;
case WL_CONNECTION_LOST: Serial.print("assigned when the connection is lost;"); break;
case WL_DISCONNECTED: Serial.print("assigned when disconnected from a network;"); break;
default: Serial.print("unknown:"); Serial.print( WiFiStatus ); break;
}
Serial.println("]");
return WiFiStatus;
}
// メインループ
void loop() {
if( WiFi_ConnectCheck()!=WL_CONNECTED ) return;
// WiFi接続中に行う処理を記述します
}```