WIFI模块-ESP芯片开发框架(ESP32/ESP8266)

开发工具

  • Arduino IDE 2.3.5

支持设备

  • ESP32 | ESP8266

功能列表

  • 联网配置
  • MQ通信
  • OTA升级
  • WatchDog

联网流程

  • 程序启动后,查找本地文件存储的wifi账号和密码,如果文件为空,或者wifi连不上则进入入ap模式,在网页界面上输入账户和密码,保存到本地文件并进行连接,连接成功后重启ESP;超时5分钟未连上wifi则重启ESP

开发板选择

  • ESP32开发板
  • ESP8266开发板

第三方库

  • ArduinoJson
  • NTPClient
  • PubSubClient

代码结构

  • image

 

代码入口

#include <HTTPClient.h>        // 添加 ESP32 的 HTTP 客户端
#include <HTTPUpdate.h>        // 使用 ESP32 版本的 HTTPUpdate
#include <ArduinoJson.h>
#include "GlobalVar.h"
#include "WebConfig.h"
#include "Common.h"
#include "KeyValueStore.h"
#include "MQClient.h"
#include "JsonGenerator.h"
#include "soc/rtc_wdt.h"

MQClient mqttClient; 
String deviceId; 
bool firstLoad = true;

void setup() { 
  // 配置调试串口 
  Serial.begin(9600);  // 先初始化串口
  Serial.println("");
  Serial.printf("MCU RUN,Version:%s\n", MCU_Version.c_str());
  //
  // 配置看门狗
  rtc_wdt_protect_off();
  rtc_wdt_disable();
  rtc_wdt_enable();
  rtc_wdt_set_time(RTC_WDT_STAGE0, 10000);
  rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_RESET_RTC);
  //
  SPIFFS.begin(true);
  // 
  WebConfig::initWifi();

  if (KeyValueStore::exists(DeviceId)) {
    // 初始化时间
    Common::initTime();

   // 获取完整日期时间 
    Serial.println("CurrentTime: " + Common::getCurrentTime()); 
    
    deviceId = KeyValueStore::get(DeviceId);
    SubTopic.concat(deviceId);  
    PubTopic.concat(deviceId);  
  
    Serial.printf("DeviceId:%s\n", deviceId.c_str()); 

    // MQTT初始化
    mqttClient.init(KeyValueStore::get(MQServer),
                    KeyValueStore::getLong(MQPort),
                    KeyValueStore::get(MQUid),
                    KeyValueStore::get(MQPwd),
                    SubTopic,
                    PubTopic,
                    "mqclient_" + deviceId,
                    subCallBack);
  }
}

void loop() {
  rtc_wdt_feed();           // 喂狗

  WebConfig::checkWifi();
  mqttClient.loop();  // 保持MQTT连接

  // OTA发送
  if (firstLoad && WiFi.status() == WL_CONNECTED && mqttClient.isConnected()) {
    firstLoad = false; 
    String ota = JsonGenerator::generateOTA(deviceId, MCU_Version, MCU_Type);
    mqttClient.publish(ota.c_str());
  } 
} 
 
/**
 * MQ回调函数 
 */
void subCallBack(char* topic, byte* payload, unsigned int length) {
  // 转换payload为字符串
  payload[length] = '\0';
  String message = String((char*)payload);
  
  Serial.print("Received [");
  Serial.print(topic);
  Serial.print("]: ");
  Serial.println(message);

  // 解析JSON数据
  DynamicJsonDocument doc(256);
  DeserializationError error = deserializeJson(doc, message);
  
  if (error) {
    Serial.print("JSON解析失败: ");
    Serial.println(error.c_str());
    return;
  }

  // 处理指令类型
  int command = doc["c"];
  switch(command) {
    case 1:  // 固件升级指令
      if (doc["m"]["errcode"] == 0) {
        String url = doc["m"]["url"].as<String>();
        if (!url.equals("")) {
          Serial.println("开始固件升级: " + url);
          updateBin(url);
        } 
      }
      break;
    case 2:
      // 重启
      Serial.println("远程升级,即将重启");
      delay(1000);
      ESP.restart();
      break;
    default:
      Serial.println("未知指令类型");
      break;
  }
}

/**
 * 固件升级函数 (ESP32专用)
 */
void updateBin(String upUrl) {
  WiFiClient client;
  
  // 创建 HTTPUpdate 对象
  HTTPUpdate httpUpdate;
  httpUpdate.rebootOnUpdate(false); // 禁用自动重启
  
  for(int i = 0; i < 3; i++) {
    t_httpUpdate_return ret = httpUpdate.update(client, upUrl);
    
    switch(ret) {
      case HTTP_UPDATE_FAILED:
        Serial.printf("升级失败原因: %s\n", httpUpdate.getLastErrorString().c_str());
        delay(5000);
        break;
      case HTTP_UPDATE_NO_UPDATES:
        Serial.println("无可用更新");
        return;
      case HTTP_UPDATE_OK:
        Serial.println("升级成功,即将重启");
        delay(1000);
        ESP.restart();
        return;
    }
  }
}

 

功能测试

1. wifi配置

image image image

image  image

image

 2. OTA升级

image

 3. 远程升级

image

 

posted @ 2025-07-28 10:42  CHHC  阅读(116)  评论(0)    收藏  举报