ESP8266 (Wemos D1 Mini)阿里雲IOT入門教程(二)--- 如何測試Mqtt數據的發送和接收
概述
之前已經有兩篇相關的文章講述了開發平臺的搭建以及開發板的上雲,這個實驗二是在前兩個實驗的基礎上,測試Wemos D1 Mini與阿里雲Mqtt服務器之間數據的收發。
前兩個教程的電梯:
VSCode+PlatformIo IDE實現Wemos D1 Mini(ESP8266)接入阿里雲物聯網平臺
VSCode+PlatformIo IDE實現arduino IOT嵌入式編程—Wemos D1 Mini點亮板載LED燈
這個部分主要在之前上雲代碼的基礎上增加兩個函數,一個實現開發板端採集的數據的上報工作,一個實現對訂閱的Mqtt主題進行監聽和響應。
上報數據
開發板端代碼編寫
上報數據的處理由mqttIntervalPost()
函數實現。該函數中下面這句非常關鍵。它將LED這個板載燈的狀態(0/1
)寫入"Switch_State"
這個變量中,從而實現板載燈狀態的上報。那麼這個"Switch_State"
是什麼呢?它是當初我們定義產品、增加產品屬性時,爲屬性定義的英文標識符(詳情見下圖)。如果你當初和我實驗裏用的不是同一個字符,替換成你的相應標識符就好。由此我們可以get到關於阿里雲Mqtt上傳數據時的一個重點:我們可以通過對產品增加更多的屬性並定義不同的標識符,來實現多組不同數據的上傳。比如增加溫度、溼度等其他參數。(實驗三或者四會增加溫溼度採集,敬請期待 哈哈哈)
sprintf(param, “{“Switch_State”:%d}”, digitalRead(LED));
/**
* 上報數據
*/
void mqttIntervalPost()
{
char param[128];//存儲上報數據的數組
char jsonBuf[256];//matt的數據傳輸是json的,這個是用來存儲轉化爲json格式的上傳數據
//數據的數組
//“Switch_State”:阿里雲端創建的產品屬性的標識符
//digitalRead(LED):將讀取到的LED燈的引腳狀態
//LED: 在整段程序的最開始預定義的變量 #define LED D4 其中D4是板載燈
sprintf(param, "{\"Switch_State\":%d}", digitalRead(LED));
//按照阿里雲平臺要求的json格式方式上報數據
//這段話照抄就行,沒有需要求改的地方
sprintf(jsonBuf, ALINK_BODY_FORMAT, ALINK_METHOD_PROP_POST, param);
Serial.println(jsonBuf);//串口輸出jsonBuf裏的內容用作調試
mqttClient.publish(ALINK_TOPIC_PROP_POST, jsonBuf); // 上報屬性Topic數據
}
在loop()
循環中增加數據上報函數後,編譯上傳程序至開發板。
阿里雲IOT端驗證
點擊上述圖片中的按鈕就會自動跳轉到下面這個界面。仔細觀察會發現,現在產品的在線調試功能遷移到了“監控運維”標籤下的“在線調試”頁面。以後可以直接點擊這裏進入調試頁面。如下圖所示,上報的數據會顯示在右側。劃紅線的位置就是我們剛剛剛板載寫入的那個LED燈狀態變量。
開發板監聽數據
開發板端監聽雲端指令並處理
這個對Mqtt雲端指令的監聽,是通過在mqtt服務中增加相應的callback()
函數實現的。整段函數中下面這句是關鍵。我們燈的狀態是通過產品屬性的Switch_State
標識符來控制的。1:開燈;0:關燈
。
int redLedState = root[“params”][“Switch_State”];
callback()
函數通過下述語句添加在setup()
//監聽雲端下發的指令
void callback(char *topic, byte *payload, unsigned int length)
{
//串口輸出從阿里雲接收到的原始數據
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
payload[length] = '\0';
Serial.println((char *)payload);
if (strstr(topic, ALINK_TOPIC_PROP_SET))
{
StaticJsonBuffer<200> jsonBuffer;
JsonObject &root = jsonBuffer.parseObject(payload);
if (!root.success())
{ //接收阿里雲Mqtt訂閱主題數據失敗
Serial.println("parseObject() failed");
} else {
//接收阿里雲Mqtt訂閱主題數據成功
Serial.println("parseObject() success");
//下一步對收到的雲端指令進行處理
int redLedState = root["params"]["Switch_State"];
//串口輸出方便調試
Serial.print("LED State: ");
Serial.println(redLedState);
//根據接收到的Mqtt參數改變板載燈的亮滅
digitalWrite(LED, redLedState);
}
}
}
阿里雲IOT平臺端發送測試數據
當然也可以通過將測試代碼中的Switch_State
編程1。來測試打開板載LED燈。
{
“Switch_State”: 1
}
PS:當完成上述全部操作後你可能發現那裏有點問題。。。是不是你發送“1”時,開發板的燈是滅的;但是發送“0”的時候燈是點亮的?不要着急,這是因爲wemosD1Mini的板載燈內部有做電路上的邏輯變換。你自己外接一個LED在D4就是正常邏輯咯。
完整源代碼
// Example testing sketch for various DHT humidity/temperature sensors
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include <aliyun_mqtt.h>
// Wifi名稱和密碼,你WemosD1Mini上網時需要接入的Wifi賬號和密碼
#define WIFI_SSID "xxxxxxxx" //WiFi賬號
#define WIFI_PASSWD "xxxxxxxxx"//WiFi密碼
//定義板載燈常量 wemosD1Mini板載燈的管腳號是D4.
#define LED D4
// LP的設備三元組(PK/DN/DS)根據你雲端創建的設備三碼進行更改
#define PRODUCT_KEY "xxxxxx"
#define DEVICE_NAME "xxxxxxxxx"
#define DEVICE_SECRET "xxxxxxxxxxx"
// Alink協議格式和Topic定義 這個部分是固定格式不用進行修改
//id:自定義的,隨便寫
#define ALINK_BODY_FORMAT "
{\"id\":\"123\",\"version\":\"1.0\",\"method\":\"%s\",\"params\":%s}"
#define ALINK_TOPIC_PROP_POST "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/post"
#define ALINK_TOPIC_PROP_SET "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/service/property/set"
#define ALINK_METHOD_PROP_POST "thing.event.property.post"
// 創建WiFiClient實例
WiFiClient espClient;
//創建MqttClient實例
PubSubClient mqttClient(espClient);
//連接Wifi
void initWifi(const char *ssid, const char *password)
{
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
Serial.println("WiFi does not connect, try again ...");
delay(3000);
}
Serial.println("Wifi is connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
//監聽雲端下發的指令
void callback(char *topic, byte *payload, unsigned int length)
{
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
payload[length] = '\0';
Serial.println((char *)payload);
if (strstr(topic, ALINK_TOPIC_PROP_SET))
{
StaticJsonBuffer<200> jsonBuffer;
JsonObject &root = jsonBuffer.parseObject(payload);
if (!root.success())
{
Serial.println("parseObject() failed");
} else {
Serial.println("parseObject() success");
//下一步對收到的雲端指令進行處理
int redLedState = root["params"]["Switch_State"];
Serial.print("LED State: ");
Serial.println(redLedState);
digitalWrite(LED, redLedState);
}
}
}
//連接Mqtt
void mqttCheckConnect()
{
bool connected = connectAliyunMQTT(mqttClient, PRODUCT_KEY, DEVICE_NAME, DEVICE_SECRET);
if (connected) {
Serial.println("MQTT connect succeed!");
mqttClient.subscribe(ALINK_TOPIC_PROP_SET); // 訂閱屬性設置Topic
Serial.println("subscribe done");
}
}
/**
* 上報數據
*/
void mqttIntervalPost()
{
char param[128];
char jsonBuf[256]
sprintf(param, "{\"Switch_State\":%d}", digitalRead(LED));
sprintf(jsonBuf, ALINK_BODY_FORMAT, ALINK_METHOD_PROP_POST, param);
Serial.println(jsonBuf);
mqttClient.publish(ALINK_TOPIC_PROP_POST, jsonBuf); // 上報屬性Topic數據
}
void setup() {
Serial.begin(115200);
pinMode(LED, OUTPUT); //將LED燈的引腳設置爲輸出
digitalWrite(LED, 0); //讓燈的狀態在程序初次上電運行時保持關閉
initWifi(WIFI_SSID, WIFI_PASSWD); // 連接Wifi
mqttClient.setCallback(callback); // 設置回調監聽雲端下發的指令
}
void loop() {
mqttCheckConnect(); // MQTT上雲
mqttIntervalPost(); //上報數據
mqttClient.loop();
delay(1000); // 每1秒連接一次
}
小結
全文通過對Wemos D1 Mini和阿里雲IOT平臺兩部分,詳細較少了阿里雲IOT平臺上雲設備的一般上傳和監聽控制功能的調試流程。下次課程將詳細講述阿里雲IOT平臺中IOT Studio
服務中提供的App製作,敬請期待。