ESP32のWi-Fi設定について #2

以前にESP32のWi-Fi設定について、SmartConfigを中心に記載しました。

その後、記載したコードではWi-Fi設定が記録されておらず、起動するたびにSmartConfigの設定を求められるとのご指摘をいただきました。

確認したところ、確かにSmartConfigで設定後に電源を再投入しても、Wi-Fiの接続が行われないことを確認しました。今となっては記憶があいまいですが、以前に記載した時は動作確認も行ったはずなのですが…。現実としてダメなようです。

そこでSmartConfigで設定した内容を不揮発性メモリに記録し、次回に起動したときは不揮発性メモリからSSIDとパスワードを読み出し、接続するようにしたいと思います。

設定したSSIDとパスワードを読み出せれば、後はpreferencesへPUTするだけなのですが、SSIDはWiFi.ssid()のコマンドで得られることは直ぐに分かったのですが、パスワードを得るコマンドが分からない。そこでソースを眺めながら調べ漸くにWiFi.psk()であることが分かりました。ここは実は結構、苦労しました…が、分かってしまえば後は楽ちん。

ArduinoIDEを用いたプログラムは次の通りです。

#include <WiFi.h>
#include   // 不揮発性メモリへの記録(Wi-Fi情報)

#define SW  39                                // スイッチのPIN番号
#define LED 33                                // LEDのPIN番号

uint32_t startTime = 0;
 enum BTN_STATUS { Release, ON_start, MomentPress_Determined, LongPress_Determined, Continuous_Press }
 btnStatus = Release;
 // SSID storage
 Preferences preferences;  // declare class object
 void setWiFi() {
   WiFi.mode(WIFI_AP);                         // APモードで動作…
   WiFi.beginSmartConfig();                    // SmartConfigを有効化
   Serial.println("Waiting for SmartConfig."); // 設定待ち
   while (!WiFi.smartConfigDone()) {
     digitalWrite(LED, HIGH);
     delay(250);
     Serial.print(".");
     digitalWrite(LED, LOW);
     delay(250);
   }
   // ここで不揮発性メモリへの書き込み…
   preferences.begin("wifi", false);
   preferences.putString( "ssid", WiFi.SSID());
   preferences.putString( "password", WiFi.psk());
   preferences.end();
 WiFi.mode(WIFI_STA);                        // STAモードで動作…
   WiFi.begin();
 }
 //=========================================================================
 //! 以下、URL情報からソースをいただいています。
 //! https://www.mgo-tec.com/blog-entry-m5stack-button-arduino-esp32.html/4
 //=========================================================================
 uint8_t My_Button(const uint8_t gpio, BTN_STATUS *button_status, uint32_t *start_time, boolean continuous_set, uint32_t chatter_time, uint32_t long_press_time) {
   uint8_t ret_state = Release;
   switch ( digitalRead(gpio) ) {
     case LOW: // LOW = 0
       switch ( *button_status ) {
         case Release:
           *button_status = ON_start;
           start_time = millis();  //reset start_time
           break;
         case ON_start:
           if ( continuous_set ) {
             if ( Time_Mesure(start_time) > long_press_time ) {
               button_status = Continuous_Press;
             }
           } else {
             if ( Time_Mesure(start_time) > long_press_time ) {
               button_status = LongPress_Determined;
               ret_state = LongPress_Determined;
             }
           }
           break;
         case Continuous_Press:
           if ( Time_Mesure(start_time) > long_press_time ) {
             *start_time = millis(); //reset start_time
             return Continuous_Press;
           }
           break;
         default:
           break;
       }
       break;
     case HIGH: // HIGH = 1
       if ( *button_status == ON_start ) {
         if ( Time_Mesure(*start_time) > chatter_time ) {
           ret_state = MomentPress_Determined;
         }
       }
       *button_status = Release;
       break;
     default:
       break;
   }
   return ret_state;
 }

 uint32_t Time_Mesure( uint32_t st_time ) {
   return millis() - st_time;
 }

 void setup() {
   String PrefSSID, PrefPass;
   Serial.begin(9600);                         // シリアルモニタの設定
   Serial.println("");
   pinMode(SW, INPUT);                         // INPUTモードの設定
   pinMode(LED, OUTPUT);                       // INPUTモードの設定
   // WiFi開始(前回情報を不揮発メモリから読み出し)
   WiFi.mode(WIFI_STA);
   preferences.begin("wifi", false);
   PrefSSID = preferences.getString("ssid", "none");      //NVS key ssid
   PrefPass = preferences.getString("password", "none");  //NVS key password
   preferences.end();
   WiFi.begin(PrefSSID.c_str() , PrefPass.c_str());
   unsigned long ftm = millis() + 10 * 1000;   //! 起動時のWiFi接続のタイムアウト(10秒)
   Serial.println("WiFi connecting…");
   while ((WiFi.status() != WL_CONNECTED) & (millis() < ftm)) {
     Serial.print('*');
     delay(500);
   }
   Serial.println("");
   // 前回情報で接続できなければ、SmartConfigで設定…
   if (WiFi.status() != WL_CONNECTED) setWiFi();
   Serial.printf("Connected, IP address: ");
   Serial.println(WiFi.localIP());
   Serial.println("WiFi connected!");
 }

 void loop() {
   // ボタンが長押し(2秒)されているか確認…
   uint8_t btnState = My_Button(SW, &btnStatus, &startTime, false, 10, 2000);
   // 長押しされたらWiFiを設定する
   if (btnState == LongPress_Determined) setWiFi();
   // WiFiに接続されていれば点灯…
   digitalWrite(LED, (WiFi.status() == WL_CONNECTED));
   Serial.println("do something...");
   delay(1000);
 }

他に探したところ、こちらの情報ソースがヒットしました。電波強度やMACアドレス、IPアドレス情報も取得できます。なおESP32の量産化による個別識別を考えた場合、MACアドレスをキーとしたら活用できそうです。