14258| 9
|
[官方案例教程] 【阿里云IoT使用教程4】ESP32与阿里云IoT平台通信 |
本帖最后由 wuji 于 2019-5-11 10:32 编辑 ESP32与阿里云IoT平台通信 本篇主要介绍物理设备与阿里云IOT平台之间的交互通信,如:通过阿里云平台点亮一颗LED灯,通过按钮改变阿里云IoT平台上的某个虚拟灯状态。 所需材料 在开始之前,先下载阿里云IoT入门套件库文件及样例代码: 在开始之前,需要了解a. 产品标识符;b.上报(PubTopic)和订阅(SubTopic)TOPIC等信息。 产品标识符 为产品定义某个功能时,会同时为它定义一个标识符,相当于程序中的变量,通过改变它的值,执行相应的功能。 创建并获取方式:进入某个产品的产品详情页,点击功能定义,在自定义功能栏即可创建新功能或获取被创建的产品标识符。 上报Topic 通过它,ESP32主控可以上报某个设备的属性(即更新阿里云IoT上某个设备的功能状态)到阿里云平台上。 获取方式:进入某个设备的设备详情页,选择Topic列表,即可找到发布(上报)TOPIC信息,如下图所示: 订阅Topic 通过它,会检测并接收到阿里云IoT向ESP32发送的指令,再通过数据格式解析从而操作ESP32上的某个设备。 获取方式:进入某个设备的设备详情页,选择Topic列表,,即可找到订阅TOPIC信息,如下图所示: 平台数据交互: ESP32通过上报Topic将设备信息传送给阿里云IoT平台,通过订阅Topic接收来自阿里云IoT平台的指令。 而阿里云IoT可通过真实设备调试,设置并获取ESP32上设备的状态,可通过运行状态实时检测ESP32上报的数据。 例:通过阿里云IoT平台点亮或熄灭LED灯,在阿里云IoT平台上实时检测真实设备按钮是否被按下。 准备工作 1.打开浏览器,输入网址iot.aliyun.com; 2.进入物联网平台控制台; 3.在产品栏创建一个名为智能家居(名字自取)的产品,如下图所示: 4.为ESP32产品,定义一个名为LED开关的属性,标识符为LightSwitch,0代表关灯,1代表开灯,如下图所示: 5.在智能家居产品下挂载一个设备名为ESP32(名字自取或不填)的设备,如下图所示: 得到ESP32设备的设备证书信息,如下图所示: 7.将LED灯连接到插有FireBeetle扩展板的ESP32的D2口,将按钮连接到扩展版的D3口,连接如下图所示: 8.向ESP32主控烧录程序。 由此准备工作即完成,接下来就是如何用搭建好的平台来实现物理设备同阿里云IOT平台上的通信。如何通过阿里云IoT平台点亮一颗LED灯? 在产品栏找到上面创建的智能家居产品,单击其后的查看按钮,如下图所示: 在弹出的产品详情页页面,点击在线调试,如下图所示: 点击前往查看,进入如下所示页面 选择ESP32设备,进入在线调试页面,选择调试真实设备,如下图所示 如果真实设备没有连接上阿里云平台,其功能,方法框都是灰色的,无法使用,如下图所示: 当真实设备上线后(即连接到阿里云平台上的某个虚拟设备后),即可调试真实设备了,选择LED开关功能,选择设置,如下图所示: 点亮LED灯,将标识符LightSwitch1的值变为1,再单击发送指令,即可点亮LED灯,如下图所示: 关LED灯,将标识符LightSwitch1的值变为0,再单击发送指令,即可熄灭LED灯,如下图所示: 如何在阿里云IoT平台上实时检测按钮是否被按下? 在设备列表栏,找到创建的ESP32设备,点击其后的查看按钮,如下图所示: 进入设备详情页,点击运行状态,开启实时刷新,如下图所示: 当按钮按下时,会发现LED开关数据变为1,如下图所示: 当按钮按松开时,会发现LED开关数据变为0,如下图所示: 注:虽然阿里云平台上,设备ESP32中LED开关的状态值发生了改变,但是物理设备上的LED灯,并不会随着按钮的状态而改变。因为阿里云IoT平台上没有创建当检测到设备状态发生改变后,自动下发指令到ESP32设备上的服务。 以上2个例子(1.调试真实设备;2运行状态实时刷新)简单的实现了真实设备同阿里云IoT平台的交互。下一篇,将会讲述:如何通过阿里云平台,让按钮开关LED灯(需要在阿里云平台上搭建服务)。 扩展: Arduino程序的逻辑: 1. 将D2(LED)设置为IO输出,并输出低电平(默认关LED); 2. 将D3(BUTTON)设置为IO输入,初始状态为低(按钮松开) 3. 连接WiFi; 4. 通过设备证书信息、域名、端口号连接上阿里云平台;(实现MQTT连接) 5. 通过产品表示符、上报和订阅Topic与阿里云平台通信;(实现MQTT通信) 6. 上报LED灯初始状态。 7. 等待订阅和按钮状态改变时间发生。 MQTT通信程序逻辑功能: a.ESP32接收并解析阿里云IoT平台下发的指令,若检测到标识符为0,则执行关灯指令,为1则执行开灯动作,且当LED灯状态发生改变(从亮到灭,或从灭到亮)时才上报LED灯状态; b.当ESP32检测到按钮状态(松开、按下)发生改变时,发送改变LED灯状态的指令给阿里云平台。 按下:LED开关状态值变为1 松开:LED开关状态值变为0 即只有ESP32检测到按钮或灯的状态发生改变后,才上报数据给阿里云平台。 详细代码如下: [mw_shl_code=cpp,true]#include <WiFi.h> #include <PubSubClient.h> #include <ArduinoJson.h> #include "DFRobot_Aliyun.h" #define LED D2 #define BUTTON D3 /*配置WIFI名和密码*/ const char * WIFI_SSID = "host"; const char * WIFI_PASSWORD = "123456789"; /*配置设备证书信息*/ String ProductKey = "**********"; String ClientId = "12345";/*自定义ID*/ String DeviceName = "*************"; String DeviceSecret = "******************"; /*配置域名和端口号*/ String ALIYUN_SERVER = "iot-as-mqtt.cn-shanghai.aliyuncs.com"; uint16_t PORT = 1883; /*需要操作的产品标识符*/ String Identifier = "LightSwitch"; /*需要上报和订阅的两个TOPIC*/ const char * subTopic = "***************************";//****set const char * pubTopic = "**************************";//******post DFRobot_Aliyun myAliyun; WiFiClient espClient; PubSubClient client(espClient); /*ButtonState、LEDState用来存储LED灯同BUTTON按钮的当前值*/ uint8_t ButtonState = 0; uint16_t LEDState = 0; static void openLight(){ digitalWrite(LED, HIGH); } static void closeLight(){ digitalWrite(LED, LOW); } void connectWiFi(){ Serial.print("Connecting to "); Serial.println(WIFI_SSID); WiFi.begin(WIFI_SSID,WIFI_PASSWORD); while(WiFi.status() != WL_CONNECTED){ delay(500); Serial.print("."); } Serial.println(); Serial.println("WiFi connected"); Serial.print("IP Adderss: "); Serial.println(WiFi.localIP()); } void callback(char * topic, byte * payload, unsigned int len){ Serial.print("123"); Serial.print("Recevice ["); Serial.print(topic); Serial.print("] "); for (int i = 0; i < len; i++){ Serial.print((char)payload); } Serial.println(); StaticJsonBuffer<300> jsonBuffer; JsonObject& root = jsonBuffer.parseObject((const char *)payload); if(!root.success()){ Serial.println("parseObject() failed"); return; } const uint16_t LightStatus = root["params"][Identifier]; if(LightStatus == 1){ openLight(); }else{ closeLight(); } /*当LED灯的状态发生改变后,则上报LED灯的当前状态*/ if(LightStatus != LEDState) { LEDState = LightStatus; String tempMseg = "{\"id\":"+ClientId+",\"params\":{\""+Identifier+"\":"+(String)LightStatus+"},\"method\":\"thing.event.property.post\"}"; char sendMseg[tempMseg.length()]; strcpy(sendMseg,tempMseg.c_str()); client.publish(pubTopic,sendMseg); } } void ConnectAliyun(){ while(!client.connected()){ Serial.print("Attempting MQTT connection..."); /*根据自动计算的用户名和密码连接到Alinyun的设备,不需要更改*/ if(client.connect(myAliyun.client_id,myAliyun.username,myAliyun.password)){ Serial.println("connected"); client.subscribe(subTopic); }else{ Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); delay(5000); } } } void setup(){ Serial.begin(115200); /*将LED(D2)设置为IO输出,BUTTON(D3)设置为IO输入*/ pinMode(LED,OUTPUT); pinMode(BUTTON,INPUT); /*连接WIFI*/ connectWiFi(); /*初始化Alinyun的配置,可自动计算用户名和密码*/ myAliyun.init(ALIYUN_SERVER,ProductKey,ClientId,DeviceName,DeviceSecret); client.setServer(myAliyun.mqtt_server,PORT); /*设置回调函数,当收到订阅信息时会执行回调函数*/ client.setCallback(callback); /*连接到Aliyun*/ ConnectAliyun(); /*开机先关灯*/ closeLight(); /*保存BUTTON按钮的初始值状态*/ ButtonState =digitalRead(BUTTON); //Serial.print("ButtonState:"); //Serial.println(ButtonState); /*上报关灯信息*/ client.publish(pubTopic,("{\"id\":"+ClientId+",\"params\":{\""+Identifier+"\":0},\"method\":\"thing.event.property.post\"}").c_str()); } void loop(){ if(!client.connected()){ ConnectAliyun(); } uint8_t ButtonValue = digitalRead(BUTTON); /*如果检测到按钮的状态发生了改变,则发送指令到阿里云平台以更新设备信息*/ if (ButtonValue != ButtonState) { /*保存按钮的当前状态*/ ButtonState = ButtonValue; /*按下:发送开灯指令,阿里云IoT上的相应设备状态变为1;松开:发送关灯指令,阿里云IoT上的相应设备状态值变为0,只需改变Identifier后的值*/ String tempMseg = "{\"id\":"+ClientId+",\"params\":{\""+Identifier+"\":"+(String)ButtonState+"},\"method\":\"thing.event.property.post\"}"; char sendMseg[tempMseg.length()]; strcpy(sendMseg,tempMseg.c_str()); client.publish(pubTopic,sendMseg); delay(1000); } client.loop(); }[/mw_shl_code] |
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed