//----------------------------------------------------------------------------------------// //-----------------------------------程序功能-----------------------------------------// /* 總功能: 製做一個MQTT服務器和ESP8266串口互相傳輸消息的模塊 如何使用: 1修改每一個芯片的信息 1-1 修改每個產品的ID 1-2 修改對應MQTT服務器配置信息 1-3 修改默認登錄WIFI的消息 2使用步驟 2-1 鏈接WIFI 上電前5S內 若是檢測到超過2S的按鍵長按,進入配網模式,LED慢閃。配網成功後,自動記錄WIFI的帳號和密碼。 若是沒有檢測到超過2S的按鍵動做,5s後自動進入鏈接WIFi模式,,LED快閃,鏈接上次記錄的WIFI。 2-2 鏈接MQTT服務器 鏈接不成功,5S後重連。 鏈接成功,等待服務器發送過來消息,或者將本身的串口收到的消息發送給MQTT服務器 2-3 按鍵功能預留 按下按鍵,led亮 離開按鍵,led滅 */ //----------------------------------------------------------------------------------------// #include <ESP8266WiFi.h> #include <PubSubClient.h> #include <math.h> #include <EEPROM.h> WiFiClient espClient; PubSubClient client(espClient); //----------------------------------------------------------------------------------------// //-----------------------------------配置信息開始-----------------------------------------// //----------------------------------------------------------------------------------------// // 產品惟一ID 微信分配 #define PRODUCT_ID "bowuguan_jiance" // 默認鏈接WIFI帳號密碼 #define DEFAULT_STASSID "dongdong"//默認鏈接的路由器的名字 HUAWEI-H3VBKZ #define DEFAULT_STAPSW "dongdong"//默認鏈接的路由器的名字 13991320168 //通訊服務器消息 #define MQTT_SEVER "www.dongvdong.top" #define MQTT_PORT 1883 #define MQTT_USER "dongdong" #define MQTT_PASS "dongdong" #define MQTT_ID PRODUCT_ID // 使用產品ID充當服務器識別ID #define MQTT_PUB_TOPIC PRODUCT_ID"/s" // 發佈話題 產品ID+/s #define MQTT_REC_TOPIC PRODUCT_ID"/r" // 接受話題 產品ID+/r // led狀態反轉 bool ledState=0; // 配網 #define Smart_KEY D2 //配網按鍵 #define Smart_LED D4 //配網LED指示燈 //led控制按鍵中斷 #define Use_LED D4 //控制LED #define Use_KEY D2 //控制LED的按鍵 //-----------------------------------配置信息結束-----------------------------------------// #define MAGIC_NUMBER 0xAA struct config_type { char stassid[32]; char stapsw[64]; uint8_t magic; }; config_type config; char sendmsg[100];// 發送話題 /***************************(1.1)按鍵LED函數()*****************************/ // LED管腳口初始化 void LED_begin(){ pinMode(Use_LED,OUTPUT); digitalWrite(Use_LED, LOW); pinMode(Use_KEY, INPUT); detachInterrupt(Use_KEY); attachInterrupt(Use_KEY, highInterrupt, RISING); } // 高電平觸發 void highInterrupt(){ digitalWrite(Use_LED, LOW); detachInterrupt(Use_KEY); attachInterrupt(Use_KEY, lowInterrupt,FALLING); } // 低電平觸發 void lowInterrupt(){ digitalWrite(Use_LED, HIGH); detachInterrupt(Use_KEY); attachInterrupt(Use_KEY, highInterrupt, RISING); } /**************************************************************/ /*************************(2) WIFI鏈接設置 *************************************/ /* 1鏈接WIFI 自動連WIFI接入網絡*/ void setup_wifi() { WiFi.begin(config.stassid, config.stapsw); while (WiFi.status() != WL_CONNECTED) { ESP.wdtFeed(); delay(200); ledState = !ledState; digitalWrite(Smart_LED, ledState); Serial.print("..."); } Serial.println("\r\n--------------WIFi CONNECT!-------------\r\n"); Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str()); Serial.printf("PSW:%s\r\n", WiFi.psk().c_str()); } /**************************************************************************/ /*************************(3) 服務器鏈接設置 *************************************/ /* 2鏈接服務器 等待,直到鏈接上服務器*/ void reconnect() {//等待,直到鏈接上服務器 while (!client.connected()) {//若是沒有鏈接上 Serial.println("Connect lost!");//鏈接失敗 if (client.connect(MQTT_ID+random(99999),MQTT_USER,MQTT_PASS)) {//接入時的用戶名,儘可能取一個很不經常使用的用戶名 client.subscribe(MQTT_REC_TOPIC);//接收外來的數據時的intopic client.publish(MQTT_PUB_TOPIC,"hello world "); Serial.println("Connect sever succes!");//鏈接 } else { Serial.println("failed, rc=");//鏈接失敗 Serial.print(client.state());//從新鏈接 Serial.println(" try again in 5 seconds");//延時5秒後從新鏈接 delay(5000); } } } void callback(char* topic, byte* payload, unsigned int length) {//用於接收數據 char recmsg[length+1]; for (int i = length-1; i >=0; i--) { recmsg[i]=(char)payload[i]; } recmsg[length]='\0'; Serial.println(recmsg); // String str(recmsg); // char 轉換String } /**************************************************************************/ /*************************(4) smartConfig配置 *************************************/ void smartConfig() { Serial.println("Start smartConfig module"); pinMode(Smart_LED, OUTPUT); digitalWrite(Smart_LED, 0); WiFi.mode(WIFI_STA); Serial.println("\r\nWait for Smartconfig"); WiFi.stopSmartConfig(); WiFi.beginSmartConfig(); while (1) { Serial.print("."); digitalWrite(Smart_LED, 0); delay(500); digitalWrite(Smart_LED, 1); delay(500); if (WiFi.smartConfigDone()) { Serial.println("SmartConfig Success"); strcpy(config.stassid, WiFi.SSID().c_str()); strcpy(config.stapsw, WiFi.psk().c_str()); Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str()); Serial.printf("PSW:%s\r\n", WiFi.psk().c_str()); saveConfig(); break; } } } /**************************************************************************/ /*******************************5 保存信息**************************************/ /* * 保存參數到EEPROM */ void saveConfig() { Serial.println("Save config!"); Serial.print("stassid:"); Serial.println(config.stassid); Serial.print("stapsw:"); Serial.println(config.stapsw); EEPROM.begin(1024); uint8_t *p = (uint8_t*)(&config); for (int i = 0; i < sizeof(config); i++) { EEPROM.write(i, *(p + i)); } EEPROM.commit(); } /* * 從EEPROM加載參數 */ void loadConfig() { EEPROM.begin(1024); uint8_t *p = (uint8_t*)(&config); for (int i = 0; i < sizeof(config); i++) { *(p + i) = EEPROM.read(i); } EEPROM.commit(); //出廠自帶 if (config.magic != MAGIC_NUMBER) { strcpy(config.stassid, DEFAULT_STASSID); strcpy(config.stapsw, DEFAULT_STAPSW); config.magic = MAGIC_NUMBER; saveConfig(); Serial.println("Restore config!"); } Serial.println(" "); Serial.println("-----Read config-----"); Serial.print("stassid:"); Serial.println(config.stassid); Serial.print("stapsw:"); Serial.println(config.stapsw); Serial.println("-------------------"); } void waitKey() { pinMode (Smart_LED, OUTPUT); pinMode (Smart_KEY, INPUT); digitalWrite(Smart_LED, 0); Serial.println(" press key 2s: smartconfig mode! \r\n press key <2s: connect wifi!"); char keyCnt = 0; unsigned long preTick = millis(); unsigned long preTick2 = millis(); int num = 0; while (1) { ESP.wdtFeed(); if (millis() - preTick < 10 ) continue;//等待10ms preTick = millis(); num++; if (num % 20 == 0) //50*10=500ms=0.5s 反轉一次 { ledState = !ledState; digitalWrite(Smart_LED, ledState); // delay(1); Serial.print("."); } if (keyCnt >= 200 && digitalRead(Smart_KEY) == 1) { //按2S 進入一鍵配置 keyCnt = 0; Serial.println("\r\n try to begin smartConfig! \r\n"); smartConfig();// 手機靈活設置WIFI break; } // 不按按鍵,自動鏈接上傳WIFI if (millis() - preTick2 > 5 * 1000) { Serial.println("\r\n try to connect wifi! \r\n"); setup_wifi(); break; } if (digitalRead(Smart_KEY) == 1){ keyCnt++;} else{keyCnt = 0;} } digitalWrite(Smart_LED, 0); pinMode (Smart_KEY, OUTPUT); } /**************************************************************************/ String serial_read(){ //-------------------Begin----------------------// //功能: 經過串口給MQTT服務器發送數據 if(Serial.available()>0){ delay(100); String comdata = Serial.readString(); Serial.print("Serial.readString:"); //從串口緩存區中讀取的整個字符串,直至檢測到終止字符。 // char terminator = ','; // String comdata =Serial.readStringUntil(terminator); // Serial.print("Serial.readStringUntil: "); Serial.println(comdata); while(Serial.read()>= 0){} /// char charBuf[100]; /// comdata.toCharArray(charBuf, sizechar) ; // client.publish(MQTT_PUB_TOPIC,charBuf); // comdata = ""; return comdata; } else return "fail"; //-------------------End----------------------// } bool serial_mqtt_sendmsg(String comdata){ if(comdata=="fail")return 0; int sise_s=500; char charBuf[sise_s]; comdata.toCharArray(charBuf, sise_s) ; client.publish(MQTT_PUB_TOPIC,charBuf); comdata = ""; return 1; } //初始化函數 void setup() {//初始化程序,只運行一遍 Serial.begin(9600);//設置串口波特率(與燒寫用波特率不是一個概念) loadConfig();// 讀取信息 waitKey(); delay(5000); client.setServer(MQTT_SEVER, MQTT_PORT);//端口號 client.setCallback(callback); //用於接收服務器接收的數據 LED_begin();//設置LED模式 } // 循環主函數 void loop() {//主循環 if(WiFi.status() == WL_CONNECTED){ // 初始化鏈接 if (!client.connected()) { reconnect();//確保連上服務器,不然一直等待。 } // 訂閱話題等待 client.loop();//MUC接收數據的主循環函數。 // 從串口讀數據 String serial_string=serial_read(); // 將串口數據發送給服務器 serial_mqtt_sendmsg(serial_string); serial_string=""; } else { Serial.println("wifi fail!"); setup_wifi() ; // wifi } }