呈上篇
在此教學使用手機來連入 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!");
}