esp32 arduino 支持eeprom保存配置参数

发布时间 2023-06-13 17:19:43作者: larkin-cn

完整代码如下

#include <WiFi.h>
#include <WiFiUdp.h>
#include "WString.h"
#include "EEPROM.h"

void sendSerial1(String str, bool addline = true);
typedef void(*funcSlice)();

#define ROM_STRING_SIZE   16
#define ROM_INT_SIZE      4

enum TaskType
{
  TaskTypeLed,
  TaskTypeParse,
  TaskTypeSerialRecv,
  TaskTypeUDPRecv,
  TaskTypeCount
};

enum Status
{
  LedStatusOff = HIGH,
  LedStatusOn = LOW 
};

enum AddrEEProm
{
  AddressSSID,
  AddressPassword = AddressSSID + ROM_STRING_SIZE,
  AddressPeerHost = AddressPassword + ROM_STRING_SIZE,
  AddressPeerPort = AddressPeerHost + ROM_STRING_SIZE,
  AddressCount = AddressPeerPort + ROM_INT_SIZE
};

struct GlobalParam
{
  uint32_t chipId;
  uint32_t uruntimemsec;
  uint32_t uledPin;
  uint32_t uledValue;
  uint16_t uUdpPort;
  bool bLedBlink;
  bool wifiConnected;

  String udpPeerHost;
  uint16_t udpPeerPort;

  String strCache;
  String strWifissid;
  String strWifiPassword;
};

struct ProgramBlock
{
  uint32_t runLast;
  uint32_t runSlice;
  funcSlice func;
};

int pinsda = GPIO_ID_PIN(0);
int pinscl = GPIO_ID_PIN(4);
ProgramBlock pb[TaskTypeCount] = {0};
GlobalParam param = {0};
//The udp library class
WiFiUDP udp;
EEPROMClass romflash("rom", AddressCount);

void showUsage()
{
  Serial.println("============== menu ==============");
  Serial.println("?: help menu");
  Serial.println("s: status info");
  sendSerial1("reboot: reboot device");
  sendSerial1("ssid=xxxx:save wifi ssid");
  sendSerial1("password=xxxx:save wifi password");  
  sendSerial1("remhost=xxxx:save udp peer host");  
  sendSerial1("remport=xxxx:save udp peer port");  
  Serial.println("==================================");
}

void showStatus()
{
    Serial.println("=============== status =============");
    Serial.printf("chip Id:%d\n", param.chipId);
    Serial.print("wifi connected:");
    Serial.println(param.wifiConnected);
    Serial.print("local ip:");
    Serial.println(WiFi.localIP()); 
    // Serial.printf("has run time(misecs):%d\n", param.uruntimemsec); 
    Serial.print("led blink:");
    Serial.println(param.bLedBlink);
    String str;
    str = "ssid:" + param.strWifissid;
    sendSerial1(str);

    str = "password:" + param.strWifiPassword;
    sendSerial1(str);

    str = "has run:" + timeFormat();
    sendSerial1(str);

    Serial.printf("udp listen port:%d\n", param.uUdpPort);
    Serial.print("udp peer host:");
    Serial.println(param.udpPeerHost);
    Serial.printf("udp peer port:%d\n", param.udpPeerPort);
    Serial.println("====================================");
}

String timeFormat()
{
  int secs = param.uruntimemsec / 1000;
  int nday = 24*3600;
  String str;
  int day = secs / (nday);
  if(day > 0)
  {
    str += day;
    str += "d ";
  }
  int hor = secs % nday;
  int h = hor/3600;
  if(h){
    str += h;
    str += "h ";
  }
  hor = hor % 3600;
  int m = hor /60;
  if(m)
  {
    str += m;
    str += "m ";
  }
  int s = hor % 60;
  if(s)
  {
    str += s;
    str += "s";
  }
  str += "(";
  str += secs;
  str += "secs)";
  return str;
}

void initUDP()
{
  param.uUdpPort = 10888;
  udp.begin(param.uUdpPort);
}

void initEEPRom()
{
    char buf[ROM_STRING_SIZE] = {0};
    if(!romflash.begin(romflash.length()))
    {
      sendSerial1("failed to init eeprom wifissid");
    }else {
      memset(buf, 0, ROM_STRING_SIZE);
      int ret = romflash.readString(AddressSSID, buf, ROM_STRING_SIZE);
      param.strWifissid = buf;

      memset(buf, 0, ROM_STRING_SIZE);
      ret = romflash.readString(AddressPassword, buf, ROM_STRING_SIZE);
      param.strWifiPassword = buf;

      memset(buf, 0, ROM_STRING_SIZE);
      ret = romflash.readString(AddressPeerHost, buf, ROM_STRING_SIZE);
      param.udpPeerHost = buf;

      param.udpPeerPort = romflash.readInt(AddressPeerPort);
    }
}

void sendUDP(String str)
{
  udp.beginPacket(param.udpPeerHost.c_str(), param.udpPeerPort);
    udp.println(str);
    udp.endPacket();
}

void sendSerial1(String str, bool addline)
{
  if(addline)
  {
      Serial.println(str);
  }else {
      Serial.print(str);
  }
    
}

void WiFiEvent(WiFiEvent_t event){
    switch(event) {
      case SYSTEM_EVENT_STA_GOT_IP:
          //When connected set 
          Serial.print("WiFi connected! IP address: ");
          Serial.println(WiFi.localIP());  
          //initializes the UDP state
          //This initializes the transfer buffer
          // udp.begin(WiFi.localIP(),udpPort);
          param.wifiConnected = true;
          pb[TaskTypeLed].runSlice = 1000;
          param.bLedBlink = true;
          initUDP();
          break;
      case SYSTEM_EVENT_STA_DISCONNECTED:
          Serial.println("WiFi lost connection");
          param.wifiConnected = false;
          pb[TaskTypeLed].runSlice = 3000;
          param.bLedBlink = false;
          param.uledValue = LedStatusOff;
          break;
      default: break;
    }
}

void connectToWIFI()
{
  WiFi.disconnect(true);
  WiFi.onEvent(WiFiEvent);
  WiFi.begin(param.strWifissid.c_str(), param.strWifiPassword.c_str());
}

void getChipInfo()
{
  param.chipId = 0;
  for(int i=0; i<17; i=i+8) {
	  param.chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
	}
  // Serial.printf("ESP32 Chip model = %s Rev %d\n", ESP.getChipModel(), ESP.getChipRevision());
	// Serial.printf("This chip has %d cores\n", ESP.getChipCores());
  // Serial.print("Chip ID: "); 
  // Serial.println(chipId);
}

void taskLed()
{
  if(param.bLedBlink)
  {
    if(LedStatusOff == param.uledValue){
      param.uledValue = LedStatusOn;
    }else{
      param.uledValue = LedStatusOff;
    }
  }
  digitalWrite(param.uledPin, param.uledValue);
}

void taskParseData()
{
  while(param.strCache.length())
  {
      int index = param.strCache.indexOf('\n');
      if(index < 0){
        return;
      }
      String strwhole = param.strCache.substring(0, index);
      param.strCache.remove(0, index+1);
      strwhole.trim();
      Serial.printf("whole len:%d ", strwhole.length());
      Serial.println(strwhole);
      // Serial.printf("equal ret:%d\n", ret);
      if(strwhole.equalsIgnoreCase(String('s')))
      {
          showStatus();
      }else if(strwhole.equalsIgnoreCase(String("reboot")))
      {
        ESP.restart();
      }
      else if(strwhole.startsWith("ssid="))
      {
        String ssid = strwhole.substring(5, strwhole.length());
        romflash.writeString(AddressSSID, ssid);
        romflash.commit();
        sendSerial1(ssid);
      }else if(strwhole.startsWith("password="))
      {
          String pwd = strwhole.substring(9, strwhole.length());
          romflash.writeString(AddressPassword, pwd);
          romflash.commit();
          sendSerial1(pwd);
      }else if(strwhole.startsWith("remhost="))
      {
        String ssid = strwhole.substring(8, strwhole.length());
        romflash.writeString(AddressPeerHost, ssid);
        romflash.commit();
        sendSerial1(ssid);
      }else if(strwhole.startsWith("remport="))
      {
        String ssid = strwhole.substring(8, strwhole.length());
        romflash.writeInt(AddressPeerPort, ssid.toInt());
        romflash.commit();
        sendSerial1(ssid);
      }
      else {
          showUsage();
      }
  }  
}

void taskSerialRecv()
{  
  while(Serial.available())
  {
      char nch = Serial.read();
      param.strCache += nch;      
  }
}

char buffUdpRecv[255] = {0};

void taskUDPRecv()
{
  if(!param.wifiConnected){
    return;
  }
  int len = udp.parsePacket();
  if(len <= 0){
    return;
  }
  // IPAddress phost = udp.remoteIP();
  // uint16_t pport = udp.remotePort();
  // param.udpPeerHost = phost;
  // param.udpPeerPort = pport;  
  udp.read(buffUdpRecv, len);
  buffUdpRecv[len] = '\n';
  buffUdpRecv[len+1] = 0;
  param.strCache += buffUdpRecv;
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  sendSerial1("system start ...");

  initEEPRom();

  pb[TaskTypeParse].runLast = 0;
  pb[TaskTypeParse].runSlice = 20;
  pb[TaskTypeParse].func = taskParseData;

  pb[TaskTypeLed].runLast = 0;
  pb[TaskTypeLed].runSlice = 1000;
  pb[TaskTypeLed].func = taskLed;

  pb[TaskTypeSerialRecv].runLast = 0;
  pb[TaskTypeSerialRecv].runSlice = 40;
  pb[TaskTypeSerialRecv].func = taskSerialRecv;

  pb[TaskTypeUDPRecv].runLast = 0;
  pb[TaskTypeUDPRecv].runSlice = 40;
  pb[TaskTypeUDPRecv].func = taskUDPRecv;

  getChipInfo();

  param.uledPin = GPIO_ID_PIN(22);
  param.uledValue = LedStatusOff;
  pinMode(param.uledPin, OUTPUT);
  taskLed();
  connectToWIFI();
}

void loop() {
  // put your main code here, to run repeatedly:  
  param.uruntimemsec = millis();
  for(int t = 0; t < TaskTypeCount; t++)
  {
    if(param.uruntimemsec - pb[t].runLast > pb[t].runSlice)
    {
      pb[t].runLast = param.uruntimemsec;
      pb[t].func();
    }
  }
}