代码
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// 状态define
#define STATE_INIT 0
#define STATE_WIFI_CONNECTING 1
#define STATE_MQTT_CONNECTING 2
#define STATE_WORKING 3
#define STATE_MQTT_ERROR 4
#define STATE_WIFI_ERROR 5
//参数定义
//TODO:read from serial config
const char* ssid = "Xiaomi_53C8";
const char* password = "dka123456@";
const char* mqttServer = "emqx.start6.com";
const int mqttPort = 1883;
const char* mqttClient = "test123123";
const char* mqttUser = "mqtt";
const char* mqttPassword = "667f245d912a42139f285b0a0eba2df5";
//wifi client
WiFiClient espClient;
//mqtt client
PubSubClient client(espClient);
//状态参数
int workstate = STATE_INIT;
void setup() {
// pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output
Serial.begin(115200);
}
/*
主要根据状态进行各种操作:
INIT状态:检查参数配置,如果配置有错误,卡死,等待配置
wifi连接状态:connectwifi,如果连接失败,到wifi error状态(进行wifi断开或其他清理工作),
再回到init状态进行参数load和检查
mqtt连接状态:connectmqtt,如果连接失败,到mqtt error状态(进行mqtt断开或其他清理工作),
5次以后wifi重连,wifi失败后重新init
working状态:mqtt连接成功,errtimes清零,loop查看是否有mqtt下发消息,检测mqtt状态
wifi状态进行状态跳转。
*/
void loop() {
int ret = 0;
int mqtt_err_times = 0;
serial_data_handle();
switch(workstate){
case STATE_INIT:
if((ssid== "")||(password=="")){
//error wifi args
break;
}
if((mqttServer =="")||(mqttPort == 0)||(mqttUser=="")||(mqttPassword == "")){
//error mqtt args
break;
}
workstate = STATE_WIFI_CONNECTING;
break;
case STATE_WIFI_CONNECTING:
ret = wifi_connect();
if(ret == 0){
//connect success
workstate = STATE_MQTT_CONNECTING;
}else{
//connect error
workstate = STATE_WIFI_ERROR;
}
break;
case STATE_MQTT_CONNECTING:
ret = mqtt_connect();
if(ret == 0){
// control temp
client.subscribe("closeValue");
mqtt_err_times = 0;
workstate = STATE_WORKING;
}else{
//connect error
workstate = STATE_MQTT_ERROR;
}
break;
case STATE_WORKING:
client.loop();
if (!client.connected()) {
if(WiFi.status() != WL_CONNECTED){
workstate = STATE_WIFI_ERROR;
}else{
workstate = STATE_MQTT_ERROR;
}
}
//Serial.println("state:%d",client.state());
break;
case STATE_MQTT_ERROR:
mqtt_err_times++;
if(mqtt_err_times>=5){
//reconnect wifi
mqtt_err_times = 0;
workstate = STATE_WIFI_ERROR;
}else{
workstate = STATE_MQTT_CONNECTING;
}
break;
case STATE_WIFI_ERROR:
//wifi disconnect
workstate = STATE_INIT;
break;
default:
workstate = STATE_INIT;
break;
}
}
int wifi_connect(void)
{
int retry_times = 0;
WiFi.begin(ssid,password);
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
retry_times++;
if(retry_times>=10){
Serial.print("Wifi Connect timeout");
Serial.println();
return -1;
}
}
Serial.println();
Serial.print("Connected, IP address: ");
Serial.println(WiFi.localIP());
return 0;
}
int mqtt_connect()
{
int retry_times = 0;
client.setServer(mqttServer,mqttPort);
client.setCallback(callback);
while (!client.connected()) {
Serial.println("Connecting to MQTT...");
if (client.connect(mqttClient, mqttUser, mqttPassword)) {
Serial.println("connected");
break;
} else {
Serial.print("failed with state ");
Serial.print(client.state());
retry_times++;
if(retry_times>=10){
return -1;
}
delay(500);
}
}
return 0;
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived in topic: ");
Serial.println(topic);
Serial.print("Message:");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println("-----------------------");
}
void serial_data_handle()
{
//todo:read serial datas config or send to server
//Serial read
}
参考
🎯 拓展阅读提示
本文涉及的内容已同步至公众号后台,我会在那里分享更多深度内容和实用技巧
→ 点击关注:一行梦境
文章评论