查看: 1322|回复: 5

[项目教程] 【阿里云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信息,如下图所示:

0_2.png

订阅Topic
       通过它,会检测并接收到阿里云IoT向ESP32发送的指令,再通过数据格式解析从而操作ESP32上的某个设备。
       获取方式:进入某个设备的设备详情页,选择Topic列表,,即可找到订阅TOPIC信息,如下图所示:

0_1.png
平台数据交互
      ESP32通过上报Topic将设备信息传送给阿里云IoT平台,通过订阅Topic接收来自阿里云IoT平台的指令。
      而阿里云IoT可通过真实设备调试,设置并获取ESP32上设备的状态,可通过运行状态实时检测ESP32上报的数据。
例:通过阿里云IoT平台点亮或熄灭LED灯,在阿里云IoT平台上实时检测真实设备按钮是否被按下。

准备工作
      1.打开浏览器,输入网址iot.aliyun.com;
      2.进入物联网平台控制台;
      3.在产品栏创建一个名为智能家居(名字自取)的产品,如下图所示:

1.png

      4.为ESP32产品,定义一个名为LED开关的属性,标识符为LightSwitch,0代表关灯,1代表开灯,如下图所示:

2.png

       5.智能家居产品下挂载一个设备名为ESP32(名字自取或不填)的设备,如下图所示:

3.png

        得到ESP32设备的设备证书信息,如下图所示:

4.png

      7.将LED灯连接到插有FireBeetle扩展板的ESP32的D2口,将按钮连接到扩展版的D3口,连接如下图所示:

5.png

      8.向ESP32主控烧录程序。
      由此准备工作即完成,接下来就是如何用搭建好的平台来实现物理设备同阿里云IOT平台上的通信。


如何通过阿里云IoT平台点亮一颗LED灯?
         在产品栏找到上面创建的智能家居产品,单击其后的查看按钮,如下图所示:

6.png

         在弹出的产品详情页页面,点击在线调试,如下图所示:

7.png

          点击前往查看,进入如下所示页面

8.png

        选择ESP32设备,进入在线调试页面,选择调试真实设备,如下图所示

9.png

        如果真实设备没有连接上阿里云平台,其功能,方法框都是灰色的,无法使用,如下图所示:

10.png

     当真实设备上线后(即连接到阿里云平台上的某个虚拟设备后),即可调试真实设备了,选择LED开关功能,选择设置,如下图所示:

11.png
        点亮LED灯,将标识符LightSwitch1的值变为1,再单击发送指令,即可点亮LED灯,如下图所示:

12.png

           关LED灯,将标识符LightSwitch1的值变为0,再单击发送指令,即可熄灭LED灯,如下图所示:

13.png


如何在阿里云IoT平台上实时检测按钮是否被按下?
      在设备列表栏,找到创建的ESP32设备,点击其后的查看按钮,如下图所示:

17.png

           进入设备详情页,点击运行状态,开启实时刷新,如下图所示:

18.png

       当按钮按下时,会发现LED开关数据变为1,如下图所示:

19.png

        当按钮按松开时,会发现LED开关数据变为0,如下图所示:

20.png

注:虽然阿里云平台上,设备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检测到按钮或灯的状态发生改变后,才上报数据给阿里云平台。

详细代码如下:
[C++] 纯文本查看 复制代码
#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[i]);
  }
  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();
}

刁雷  高级技师

发表于 2019-4-28 15:59:18

阿里云物联网平台花钱么 。。。。
回复 支持 反对

使用道具 举报

wuji  中级技师
 楼主|

发表于 2019-4-29 09:08:35

刁雷 发表于 2019-4-28 15:59
阿里云物联网平台花钱么 。。。。

套件用的是免费的
回复 支持 反对

使用道具 举报

刁雷  高级技师

发表于 2019-4-29 13:12:39

wuji 发表于 2019-4-29 09:08
套件用的是免费的

好的  谢谢
回复 支持 反对

使用道具 举报

DFlc  见习技师

发表于 2019-5-23 22:23:48

这咋搞?
截图201905232223247153.png
回复 支持 反对

使用道具 举报

RiesenQiao  学徒

发表于 2019-10-10 11:05:39

如果不需要写死WiFi SSID和密码,要怎么写呢?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
wifi气象站

硬件清单

btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2019 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail