文章程式碼顯示

2018年7月13日 星期五

一起學 Python 114 : Rapsberry pi 與 NodeMCU (ESP8266) 溝通 基於 MQTT - 1 手機篇



呈上篇

在此教學使用手機來連入 MQTT Server 並且顯示(傳送) Topic 的數值



最後,與上一篇的程式碼不同的地方是我加了一個 timer
每秒會自累加,用以模擬將感測器的數值每秒上傳一次至 MQTT Server

#include "ESP8266WiFi.h" 
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
#include "SimpleTimer.h"

/************************* WiFi Access Point *********************************/ 
#define WLAN_SSID       "wifi名稱" 
#define WLAN_PASS       "wifi密碼" 

// 若你的 NodeMCU 與 Rpi 同個網域,可以使用內網的方式連到 Rpi 的 MQTT Broker
#define MQTT_SERVER      "192.168.0.105" // MQTT Broker 所在的 ip 位置
#define MQTT_PORT         1883 // mosquitto 預設的 port 1883

// 若 NodeMCU 與 Rpi 不同網域,則可以將 Rpi 網域的分享器設置虛擬伺服器
// 從外部的某個 port 連到 Rpi 網域的內部 1883 port 
//#define MQTT_SERVER      "實體ip或網域名稱"
//#define MQTT_PORT         你的外部port             
         
#define MQTT_USERNAME "" // 預設不需使用帳號密碼來登入 MQTT
#define MQTT_PASSWORD "" 

#define LED_PIN     D3               
#define BUTTON_PIN  D2           

uint32_t x=0;
float number = 0.3;
  
void MQTT_connect();

/************ Global State ******************/ 
WiFiClient client;  // Create an  WiFiClient class

// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details. 
Adafruit_MQTT_Client mqtt(&client, MQTT_SERVER, MQTT_PORT, MQTT_USERNAME, MQTT_PASSWORD); 

// 實體化 esp8266_led_P 用以對 '/leds/esp8266' 發布訊息
Adafruit_MQTT_Publish esp8266_led_P = Adafruit_MQTT_Publish(&mqtt, MQTT_USERNAME "/leds/esp8266"); 

// 實體化 esp8266_led 用以對 '/leds/esp8266' 接收訊息
Adafruit_MQTT_Subscribe esp8266_led = Adafruit_MQTT_Subscribe(&mqtt, MQTT_USERNAME "/leds/esp8266"); 

// 實體化 esp8266_number_P 用以對 '/numbers/esp8266' 發布訊息
Adafruit_MQTT_Publish esp8266_number_P = Adafruit_MQTT_Publish(&mqtt, MQTT_USERNAME "/numbers/esp8266"); 

SimpleTimer   timer;

/* =====================*/
// ===== timer_1000 ====
/* =====================*/
void timer_1000(){
  
  number = number + 1.0;
  esp8266_number_P.publish(number); //若目前 LED 滅
}
/*************************** Sketch Code ************************************/ 
// ===== SETUP =====
// =================
void setup() { 
  Serial.begin(115200); 
  delay(10); 
  pinMode(LED_PIN, OUTPUT); 
  digitalWrite(LED_PIN, LOW);
  pinMode(BUTTON_PIN, INPUT); 
  Serial.println(); Serial.println(); 
  Serial.print("Connecting to "); 
  Serial.println(WLAN_SSID); 
  WiFi.begin(WLAN_SSID, WLAN_PASS); 
   while (WiFi.status() != WL_CONNECTED) { 
     delay(500); 
     Serial.print("."); 
   } 
   Serial.println(); 
   Serial.println("WiFi connected"); 
   Serial.println("Local IP address: "); Serial.println(WiFi.localIP()); 
   
   // Setup MQTT subscription for esp8266_led. 
   mqtt.subscribe(&esp8266_led); 
   timer.setInterval(1000L, timer_1000);  
} 

// ===== LOOP =====
// ================
void loop() { 
  timer.run();-
  // 讀取當前 BUTTON 狀態
  int button_first = digitalRead(BUTTON_PIN); 
 
  // 不斷確定有連接到 MQTT Server 若斷線則自動重連 
  MQTT_connect(); 
 
  // 聆聽各種訂閱的主題
  Adafruit_MQTT_Subscribe *subscription; 
  while ((subscription = mqtt.readSubscription())) { 
    if (subscription == &esp8266_led) { //如果有來自 '/leds/esp8266' 的訊息
      char *message = (char *)esp8266_led.lastread; //抓取訊息
      Serial.print("Got: "); 
      Serial.println(message); // 印出接收到的訊息
      
      // 藉由訊息,來使 LED 做相應的動作
      if (strncmp(message, "ON", 2) == 0) { 
        digitalWrite(LED_PIN, HIGH); 
      } 
      else if (strncmp(message, "OFF", 3) == 0) { 
        digitalWrite(LED_PIN, LOW); 
      } 
      else if (strncmp(message, "TOGGLE", 6) == 0) { 
        digitalWrite(LED_PIN, !digitalRead(LED_PIN)); 
      } 
     } 
  }// 聆聽各種訂閱的主題 END
 
  delay(20); 
  int button_second = digitalRead(BUTTON_PIN);  // 讀取當前 BUTTON 狀態
  if ((button_first == HIGH) && (button_second == LOW)) { //代表按鈕被按下
    Serial.println("Button is pressed!");      
    digitalWrite(LED_PIN,!digitalRead(LED_PIN)); //反轉 LED 燈狀態
    //讀取目前 LED 燈狀態
    if (digitalRead(LED_PIN) == HIGH){ 
      esp8266_led_P.publish("Led trun ON by NodeMCU"); //若目前 LED 亮
    }
    else{
      esp8266_led_P.publish("Led trun OFF by NodeMCU"); //若目前 LED 滅
    }
    
  }
}// void loop() END

// =====  MQTT_connect =====
// =========================
void MQTT_connect() { 
  int8_t ret; 
  // 如果目前已經連上 MQTT Server 則直接返回
   if (mqtt.connected()) { 
     return; 
   } 
  Serial.print("Connecting to MQTT... "); 
  uint8_t retries = 3; 
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected 
    Serial.println(mqtt.connectErrorString(ret)); 
    Serial.println("Retrying MQTT connection in 5 seconds..."); 
    mqtt.disconnect(); 
    delay(5000);  // wait 5 seconds 
    retries--; 
    if (retries == 0) { 
      // 連接至 MQTT 失敗三次,則基本上認為版子掛了      
      while (1); // 故意用一個 while(1) 死迴圈來觸發 NodeMCU 的 Watchdog 來重啟版子
      } 
  } 
 Serial.println("MQTT Connected!"); 
}



↓↓↓ 連結到部落格方針與索引 ↓↓↓

Blog 使用方針與索引