微信硬件平臺(十) 1 ESP8266經過mqtt交互消息

 

 

 

//----------------------------------------------------------------------------------------//
//-----------------------------------程序功能-----------------------------------------//
/*
總功能:  製做一個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
    }
    
    }

       

        
相關文章
相關標籤/搜索