【阿里云IoT使用教程4】ESP32与阿里云IoT平台通信
本帖最后由 wuji 于 2019-5-11 10:32 编辑ESP32与阿里云IoT平台通信
本篇主要介绍物理设备与阿里云IOT平台之间的交互通信,如:通过阿里云平台点亮一颗LED灯,通过按钮改变阿里云IoT平台上的某个虚拟灯状态。 所需材料阿里云IoT 入门套件x1 在开始之前,先下载阿里云IoT入门套件库文件及样例代码: 下载页面:https://www.dfrobot.com.cn/goods-1896.html
在开始之前,需要了解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检测到按钮或灯的状态发生改变后,才上报数据给阿里云平台。
详细代码如下:#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include "DFRobot_Aliyun.h"
#define LEDD2
#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"];
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;
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;
strcpy(sendMseg,tempMseg.c_str());
client.publish(pubTopic,sendMseg);
delay(1000);
}
client.loop();
} 阿里云物联网平台花钱么 。。。。 刁雷 发表于 2019-4-28 15:59
阿里云物联网平台花钱么 。。。。
套件用的是免费的 wuji 发表于 2019-4-29 09:08
套件用的是免费的
好的谢谢 这咋搞? 如果不需要写死WiFi SSID和密码,要怎么写呢? 请问楼主物联网的开通是否收费,个人能够负担得起吗? 请问楼主真实设备一直不在线是怎么回事啊 我测试着这个程序灯不能一直亮,在线模拟发一次信号,亮一次就灭了。把这个程序注释掉就没事了,什么原因 Attempting MQTT connection...failed, rc=2 try again in 5 seconds
页:
[1]