Application example of upgrading related functions based on ESP32 development board using MiSiQi application WIFI (key/advanced)+EEPROM+MQTT+OTA

I am an amateur electronics enthusiast and can use Chinese programming such as Yi Language and e4a. I have recently played with several microcontroller development boards and used MiSiQi for programming. I found that MiSiQi is good at simple programming but has more complex functions. Programming is difficult to use, especially for friends like me who have a poor foundation in C language. Here I share the cases and analysis notes I studied with my novice friends. My analysis may not be completely correct, but the relevant functions have been tested and OK. Yes, novice friends can refer to it and learn from it.

Function explanation:

  1. WIFI: The key point is that if you use ESP32 to build a hotspot, then use your mobile phone to send the SSID and PSK of the network to be connected to ESP32, and then ESP32 calls the obtained SSID and PSK to connect to the specified WIFI network
  2. EEPROM: How to store the obtained SSID and PSK into ROM without losing them when the power is off
  3. MQTT + OTA: Use OTA for remote firmware upgrade

notes:
1. You must apply for a memory area before using eeprom.
2. The address variable must be of integer type, and the saved content can be of any type, but the variable types for writing and reading must be consistent, otherwise the read value will be incorrect.
3. After the write operation, the write overwrite operation must be performed. The write address needs to be offset according to the character length.
4. Each eeprom operation needs to add a delay
5. Add a delay at the end of initialization to help solve the instability of the pin level value at the beginning
6. The variable type corresponding to the WIFI name and password must be set to char or char*

Method to convert string type to char type (c + language)
char WIFI[20]; //Declare the variable type first; [20] is a subscript and must be
strcpy(WIFI, string.c_str()); //First use the c_str() function and then use strcpy to assign the value to WIFI
The reason why the variable used in the WIFI name needs to be converted is that the function of WIFI.h is written in C language and does not support the new string variables in the C + language, so it needs to be converted.
This case does not use the c_str solution, but uses a string variable to save it to eeprom and then uses a char variable to read it.

In the module initialized using WIFI, the code cannot be compiled because it is in front of the variable assignment. You can copy the corresponding code and put it in the specified location.

Usage plan:
1. First build an AP and enable udp
2. Connect the mobile phone to the AP, and then use the udp debugging tool to send the string with SSIID and PSK to the ESP32
3. After ESP32 receives the data, it decomposes it and stores the SSID and PSK to the specified eeprom address.
4. Restart ESP32. During the restart process, the SSID and PSK in the eeprom address will be read first, and then the WIFI connection will be made.

#include <EEPROM.h>
#include <TimeLib.h>
#include <NtpClientLib.h>
#include <WiFi.h>
#include <WiFiUDP.h>
#include <WiFi.h>
#include <WiFi.h>
#include <PubSubClient.h>
WiFiClient espClient;
PubSubClient client(espClient);
#ifndef AP_CONFIG
String UID = "e8f1fc8f8344d464a2bd5e89a8a718ed";
#endif

const char* UserName = "";
const char* PassWord = "";
bool subTopicCenterFlag = false;
void reConnect() {
 if (!client.connected()) {
  while (!client.connected()) {
   Serial.print("Attempting MQTT connection...");
   if(client.connect(UID.c_str(),UserName,PassWord)){
     Serial.println("connected");
     subTopicCenterFlag = true;
    } else {
    Serial.print("failed, rc=");
    Serial.print(client.state());
    Serial.println(" try again in 1 seconds");
    if(!WiFi.isConnected()) {WiFi.begin();}
    delay(1000);
    }
  }
 }
}

#include <SimpleTimer.h>

//When the upgrade starts, print the log
void update_started() {
  Serial.println("CALLBACK: HTTP update process started");
}
//When the upgrade is completed, print the log
void update_finished() {
  Serial.println("CALLBACK: HTTP update process finished");
}
//When the upgrade is in progress, print the log
void update_progress(int cur, int total) {
  Serial.printf("CALLBACK: HTTP update process at %d of %d bytes...\\
", cur, total);
}
//When the upgrade fails, print the log
void update_error(int err) {
  Serial.printf("CALLBACK: HTTP update fatal error code %d\\
", err);
 }

#include <HTTPUpdate.h>

String WIFI_SSID;
String WIFI_PSK;
int8_t timeZone = 8;
const PROGMEM char *ntpServer = "ntp1.aliyun.com";
const char AP_NameChar[] = "ESP32-8080";
const char WiFiAPPSK[] = "12345678";
IPAddress ESP8266ip1(192,168,4,2);
IPAddress ESP8266ip2(192,168,4,3);
IPAddress ESP8266ip(192,168,4,255);
unsigned int localPort =8080;
unsigned int remotePort=8080;
char incomingPacket[537];
charA;
WiFiUDP Udp;
SimpleTimer timer;

char SSID[20];
char PSK[20];
void WiFiGotIP(WiFiEvent_t event, WiFiEventInfo_t info){
  Serial.println(WiFi.localIP());
  Serial.println(String(NTP.getDateYear()) + String("year") + String(NTP.getDateMonth()) + String("month") + String(NTP.getDateDay()) + String ("Day") + String(NTP.getTimeHour24()) + String("hour") + String(NTP.getTimeMinute()) + String("minute") + String(NTP.getTimeSecond( )));
}

void Simple_timer_1() {
  if (NTP.getDateYear() != 1970) {
    Serial.print(WiFi.localIP());
    Serial.println("Connected to the Internet successfully");
    reConnect();
    client.loop();
  } else {
    Serial.println("Error: The network failed to connect to the Internet");

  }
}

void subMqttTopicCenter() {
  if(subTopicCenterFlag == true){
      subTopicCenterFlag = false;

    Serial.print("sub topic:");Serial.println(String("OTA"));
    client.subscribe(String("OTA").c_str());delay(15);

}}

void callback(char* rtopic, byte* payload, unsigned int length) {
 String msg = "";
 String topic = rtopic;
 for (int i = 0; i < length; i + + ) {
    msg + = (char)payload[i];
 }
  Serial.println(topic);
  Serial.println(msg);
  client.publish( String("MAC").c_str() , String(String(WiFi.macAddress()) + String(":") + String(msg)).c_str());
  Serial.println("A message has been published");
  if (String(msg).equals(String("OTA upgrade"))) {
    client.publish( String("MAC").c_str() , String(String(WiFi.macAddress()) + String(":") + String("Start OTA upgrade")).c_str ());
    Serial.println("A message has been published");
    WiFiClient OTAUpdateClient;
    Serial.println("start update");
    httpUpdate.onStart(update_started);//When the upgrade starts
    httpUpdate.onEnd(update_finished); //When the upgrade ends
    httpUpdate.onProgress(update_progress); //When upgrading is in progress
    httpUpdate.onError(update_error); //When the upgrade fails
    t_httpUpdate_return ret = httpUpdate.update(OTAUpdateClient, "http://bin.bemfa.com/b/1BcZThmMWZjOGY4MzQ0ZDQ2NGEyYmQ1ZTg5YThhNzE4ZWQ=OTA.bin");
    switch(ret) {
      case HTTP_UPDATE_FAILED: //When the upgrade fails
        Serial.println("[update] Update failed.");
        break;
      case HTTP_UPDATE_NO_UPDATES: //When there is no upgrade
        Serial.println("[update] Update no Update.");
        break;
      case HTTP_UPDATE_OK: //When the upgrade is successful
        Serial.println("[update] Update ok.");
        break;
      }

  }
 msg = "";
 topic = "";
 }

void setup(){
  Serial.begin(9600);
  WiFi.mode(WIFI_AP);
  WiFi.softAP(AP_NameChar, WiFiAPPSK);
  Udp.begin(localPort);
  Serial.println();
  Serial.println("Started ap. Local ip: " + WiFi.softAPIP().toString());
  WIFI_SSID = "";
  WIFI_PSK = "";
  Serial.begin(9600);
  NTP.setInterval (600);
  NTP.setNTPTimeout (1500);
  NTP.begin (ntpServer, timeZone, false);
  // You must apply for a memory area before using eeprom
  EEPROM.begin(128);
  // Manual code to add SSID to a variable of type char
  // Manual code adds PSK as a variable of type char
  //The address variable must be of integer type
  // The saved content can be of any type, but the variable types for writing and reading must be consistent, otherwise the read value will be incorrect.
  EEPROM.get(0, SSID);
  delay(100);
  //The address variable must be of integer type
  // The saved content can be of any type, but the variable types for writing and reading must be consistent, otherwise the read value will be incorrect.
  EEPROM.get(20, PSK);
  delay(100);
  Serial.println(String(String("WIFI setting SSID is:") + String(SSID)) + String(String(">>PSK is:") + String(PSK)));
  // Add a delay in initialization to help solve the instability of the pin level value when it first starts.
  delay(500);
  //The original code here is to set the SSID and PSK for WIFI
  // Because the placement is wrong, copy the code and put it in the appropriate location.
  Serial.begin(9600);
    WiFi.mode(WIFI_AP_STA);
    WiFi.softAP(AP_NameChar, WiFiAPPSK);
    WiFi.begin(SSID, PSK);
    Udp.begin(localPort);
    Serial.println();
    Serial.println("Started ap. Local ip: " + WiFi.localIP().toString());
  WiFi.onEvent(WiFiGotIP, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
  client.setServer("bemfa.com", 9501);
  timer.setInterval(10000L, Simple_timer_1);

  client.setCallback(callback);
}

void loop(){
  timer.run();

  int packetSize = Udp.parsePacket();
  if(packetSize)
  {
  Serial.printf("Received %d bytes from %s, port %d\\
", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
  int len = Udp.read(incomingPacket, 536);
  if (len > 0)
  {
  incomingPacket[len] = 0;
  Serial.printf("UDP packet contents: %s\\
", incomingPacket);
  String COM=incomingPacket;
    Serial.println(COM);
    if (String(COM).indexOf(String("*")) == 0 & amp; & amp; String(COM).indexOf(String("#")) > 1) {
      WIFI_SSID = String(COM).substring((String(COM).indexOf(String("*")) + 1),String(COM).indexOf(String("#")));
      WIFI_PSK = String(COM).substring((String(COM).indexOf(String("#")) + 1),String(COM).length());
      Udp.beginPacket("192,168,4,255",remotePort);
      Udp.print(String(String("Received WIFI setting SSID is:") + String(WIFI_SSID)) + String(String(">>PSK is:") + String(WIFI_PSK)));
      Udp.endPacket();
      EEPROM.put(0, WIFI_SSID);
      delay(100);
      EEPROM.put(20, WIFI_PSK);
      delay(100);
      // After the write operation, the write overwrite operation must be performed. Each eeprom operation requires a delay.
      EEPROM.end();
      delay(100);

    } else {
      Udp.beginPacket("192,168,4,255",remotePort);
      Udp.print("Error! Format example: *SSID#12345678");
      Udp.endPacket();

    }
  }
  }
     subMqttTopicCenter();
}