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制作,敬请期待。