本文主要涉及,c语言基础知识,嵌入式技术,STM32开发,Java全栈,Maven,应用小程序等技术。
第1章 物联网介绍
物联网(英语:Internet of Things,缩写:IoT)它起源于媒体领域,是信息技术产业的第三次革命。物联网是指通过信息传感设备将任何物体与网络连接,并通过信息传输媒体进行信息交换和通信,以实现智能识别、定位、跟踪、监督等功能。
物联网技术只是将各种数据上传到应用层的技术。根据物联网的四层结构,物联网项目可分为物理层、传输层、平台层和应用层。三层结构分为:感知层、网络层和应用层。本文介绍了各层的解决方案。本文从使用的角度介绍了各层技术,并完成了一个简单的温湿度监督系统。
根据四层模型,各层描述了一些应用技术。架构图如1.1所示。
图1.1 四层物联网模型
第2章 物理层
2.1 物理层介绍
物理层主要作用是数据获取,然后通过传输层将数据上传给物联网平台,供应用层使用。即物理层是数据的主要来源。
物理层通常是由MCU、构成感知节点和执行节点。MCU相当于大脑,负责与每个节点互动,MCU可以是STM32、Arduino、ESP8266、ESP32、51单片机等控制器。感知节点和一些传感器用于获取所需数据,感知节点根据需要确定。一般来说,执行节点是继电器、风扇等设备。
2.2 MCU介绍
这里只对STM32和Arduino进行介绍。
STM32是一款拥有ADC、PWM、中断、UART微控制器等功能,主要采用C语言开发,入门推荐观看野火教程、视频版、图书。B站视频资源可观看【单片机】野火STM32F103教学视频(配套霸道/指南/MINI)【全】(刘火良老师生产)(无字幕)_哔哩哔哩_bilibili】。书《零死角玩转》STM32—F103指南者可与视频配合使用。入门主要掌握各引脚的配置,如配置引脚的输入输出模式、输出高低电平等等。要获取传感器的数据,可以在网上查阅。大多数传感器都有现成的程序,需要移植到相应的开发板上。当然,程序也可以根据芯片手册自己编写,这需要一定的基础,初期不能去成都。然后学习一些外设,PWM、UART等等。
Arduino与STM32外设差不多,也拥有ADC、PWM、UART然而,这些外设Arduino相对来说比较简单,C 开发,即使用面向对象的开发理念,很多传感器都有写好的库,使用非常方便。
下面用代码对比两种MCU获取DHT11温湿度传感器值的差异。
STM32:
这是DHT11的头文件定义了一些函数和常量
#ifndef __DHT11_H #define __DHT11_H #include "system.h" #define BOOL unsigned char #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif //定义DHT11 GPIOD 0 #define DHT11_PORT_RCC RCC_APB2Periph_GPIOD #define DHT11_PIN GPIO_Pin_0 #define DHT11_PORT GPIOD static void DHT11_DataPin_Configure_Output(void); static void DHT11_DataPin_Configure_Input(void);
BOOL DHT11_get_databit(void);
void DHT11_set_databit(BOOL level);
void mdelay(u16 ms);
void udelay(u16 us);
static uint8_t DHT11_read_byte(void);
static uint8_t DHT11_start_sampling(void);
void DHT11_get_data(u32 *buf);
#endif
这里是获取DHT11数据的具体的实现:
#include "dht11.h"
#include "SysTick.h"
/*数据定义: ---以下变量均为全局变量-------- //----温度高8位== U8T_data_H------ //----温度低8位== U8T_data_L------ //----湿度高8位== U8RH_data_H----- //----湿度低8位== U8RH_data_L----- //-----校验 8位 == U8checkdata----- */
u8 U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;
u8 U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;
static void DHT11_DataPin_Configure_Output(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(DHT11_PORT_RCC, ENABLE); //使能PD端口时钟
GPIO_InitStructure.GPIO_Pin = DHT11_PIN; //PD.0 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_PORT, &GPIO_InitStructure);
}
static void DHT11_DataPin_Configure_Input(void)
{
GPIO_InitTypeDef DataPin;
DataPin.GPIO_Pin = DHT11_PIN;
DataPin.GPIO_Mode = GPIO_Mode_IN_FLOATING; //悬空 输入
DataPin.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_PORT, &DataPin);
}
BOOL DHT11_get_databit(void)
{
uint8_t val;
val = GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN);
if(val == Bit_RESET)
{
return FALSE;
}
else
{
return TRUE;
}
}
void DHT11_set_databit(BOOL level)
{
if(level == TRUE)
{
GPIO_SetBits(DHT11_PORT, DHT11_PIN);
}
else
{
GPIO_ResetBits(DHT11_PORT, DHT11_PIN);
}
}
void mdelay(u16 ms)
{
if(ms != 0)
{
delay_ms(ms);
}
}
void udelay(u16 us)
{
if(us != 0)
{
delay_us(us);
}
}
static uint8_t DHT11_read_byte(void)
{
uint8_t i;
uint8_t data = 0;
for(i = 0; i < 8; i++)
{
data <<= 1;
while((!DHT11_get_databit()));
udelay(10);
udelay(10);
udelay(10);
if(DHT11_get_databit())
{
data |= 0x1;
while(DHT11_get_databit());
}
else
{
}
}
return data;
}
static uint8_t DHT11_start_sampling(void)
{
DHT11_DataPin_Configure_Output();
//主机拉低18ms
DHT11_set_databit(FALSE);
mdelay(18);
DHT11_set_databit(TRUE);
//总线由上拉电阻拉高 主机延时20us
udelay(10);
udelay(10);
//主机设为输入 判断从机响应信号
DHT11_set_databit(TRUE);
DHT11_DataPin_Configure_Input();
//判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行
if(!DHT11_get_databit()) //T !
{
//判断从机是否发出 80us 的低电平响应信号是否结束
while((!DHT11_get_databit()));
// printf("DHT11 answers.\r\n");
//判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
while((DHT11_get_databit()))
{
}
return 1;
}
return 0;
}
void DHT11_get_data(u32 *buf)
{
u8 temp;
if(DHT11_start_sampling())
{
//printf("DHT11 is ready to transmit data\r\n");
//数据接收状态
U8RH_data_H_temp = DHT11_read_byte();
U8RH_data_L_temp = DHT11_read_byte();
U8T_data_H_temp = DHT11_read_byte();
U8T_data_L_temp = DHT11_read_byte();
U8checkdata_temp = DHT11_read_byte();
/* Data transmission finishes, pull the bus high */
DHT11_DataPin_Configure_Output();
DHT11_set_databit(TRUE);
//数据校验
temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);
if(temp==U8checkdata_temp)
{
U8RH_data_H=U8RH_data_H_temp; //湿度
U8RH_data_L=U8RH_data_L_temp;
U8T_data_H=U8T_data_H_temp; //温湿
U8T_data_L=U8T_data_L_temp;
U8checkdata=U8checkdata_temp;
buf[0] = U8T_data_H; //温度的高低
buf[1] = U8T_data_L;
buf[2] = U8RH_data_H; //湿度高低
buf[3] = U8RH_data_L;
}
}
}
主函数调用:
#include "system.h"
#include "SysTick.h" //延时
#include "oled.h"
#include "dht11.h"
void dht11_show(u32 *buf); //oled显示
int main()
{
//显示温度和湿度的数组 元素0 为温度高 元素1 为温度低
// 元素2 为湿度高 元素3 为湿度的低
u32 DTH11_data[4]={
0};
//时钟源获取 配置
SysTick_Init(72); //精确延时
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示
while(1)
{
DHT11_get_data(DTH11_data); //获取到温湿度
dht11_show(DTH11_data);
delay_ms(5000);
OLED_ShowString(70,20," ",16,1);
OLED_ShowString(70,40," ",16,1);
OLED_Refresh();
}
}
再看Arduino获取DTH11的值。
#include <DHT.h> //调用DHT库
DHT dht(D1,DHT11); //设置Data引脚所接IO口和传感器类型
void setup(){
//初始化函数,只在程序开始时运行一次
Serial.begin(115200); //设置串口波特率
dht.begin();
}
//https://blog.zeruns.tech
void loop() {
delay(1000); //延时1000毫秒
float RH = dht.readHumidity(); //读取湿度数据
float T = dht.readTemperature();//读取温度数据
Serial.print("Humidity:"); //向串口打印 Humidity:
Serial.print(RH); //向串口打印湿度数据
Serial.print("%");
Serial.print(" Temperature:");
Serial.print(T); //向串口打印温度数据
Serial.println("C");
Serial.println("https://blog.zeruns.tech");
}
可见Arduino使用库后是多么的简介。其实STM32使用DHT11.C和DHT11.H也相当于是库了,所以从使用的角度他们差距也不大。
2.3 感知节点
感知节点是获取数据的传感器,要使传感器与MCU通信并且获取到数据,一般有两种做法,一是自己根据对应传感器的数据手册直接实现,二是在网上获取。一般来说,常见的传感器都是可直接找到资源的,这里推荐【GITEE】搜索,以DHT11为例,STM32版如图1.1所示。
图1.1 STM32获取DHT11搜索
使用GITEE搜索Arduino DTH11的结果如图1.2所示。
图1.2 Arduino获取DHT11搜索
2.4 执行节点
执行节点通常是一些继电器,通过简单的输出高低电平来控制继电器的开关。也就是MCU通过控制引脚输出来实现控制。
第3章 传输层
传输层主要负责将数据传送至平台层,一般可将数据通过网络传输的模块都可以算作传输层的设备。数据通信方式如图3.1所示。
图3.1 物联网通信方式
使用移动网络技术的模块为NB-IOT,使用Wi-Fi技术的模块有ESP8266、ESP32等,使用以太网的模块W5500。这里只做简单介绍,根据不同的应用场景可自行了解相关技术。
在众多通信模块中,下面对使用Wi-Fi技术的ESP8266作简要介绍。
3.1 ESP8266模块介绍
ESP8266是一个完整且自成体系的Wi-Fi网络解决方案,能够搭载软件应用,或通过另一个应用处理器卸载所有Wi-Fi网络功能。ESP8266在搭载应用并作为设备中唯一的应用处理器时,能够直接从外接闪存中启动。内置的高速缓冲存储器有利于提高系统性能,并减少内存需求
ESP8266 系列的特性:
-
32-bit MCU & 2.4 GHz Wi-Fi
-
单核 CPU 时钟频率高达 160 MHz
-
+19.5 dBm 天线端输出功率,确保良好的覆盖范围
-
睡眠电流小于 20 μA,适用于电池供电的可穿戴电子设备
-
外设包括 UART,GPIO,I2S,I2C,SDIO,PWM,ADC 和 SPI
ESP8266也有不同版本,这里选择安信可的ESP8266NODEMCU做介绍,NODEMCU版相当于物理层加传输层,适用于小型项目,这里只使用他的通信功能。
ESP8266作为一个MCU也有很多的开发方式,如基于官方SDK二次开发、AT固件、Lua、ArduinoIDE等等。从只使用其通信功能来讲,推荐使用AT固件方式开发。
AT指令是应用于终端设备与PC应用之间的连接与通信的指令。AT 即Attention。每个AT命令行中只能包含一条AT指令;对于AT指令的发送,除AT两个字符外,最多可以接收1056个字符的长度(包括最后的空字符)。
既然选择了AT固件方式开发,则需要让ESP8266支持AT功能,下面讲解一些烧录AT固件至ESP8266。
3.2 AT固件烧录
要使用AT固件则需要先获取,AT固件获取地址【ESP8266 SDK发布 | 安信可科技 (ai-thinker.com)】。推荐使用第4个,它支持MQTT。固件下载如图3.2所示。
在写本文时,在实际测试中发现现在该固件支持的是ESP-12S,而如果你是安信可NODEMCU版本则是ESP-12F,它们不兼容。所固件获取需要换个思路,不使用安信可提供的而是直接使用该芯片的设计商,乐鑫【提供 Wi-Fi、蓝牙芯片和 AIoT 解决方案 I 乐鑫科技 (espressif.com)】。以下内容可以略读,成功操作在本节重新烧录固件处,点击跳转->[1]。
3.2 AT固件下载
固件有了得需要烧录工具将它烧录到ESP8266,固件烧录工具下载地址【开发工具清单 |安信可科技(ai-thinker.com),同时也可将串口调试工具下载下来。烧录工具及串口调试工具下载如图3.3所示。
3.3 烧录工具及串口调试工具下载
固件和烧录工具都准备好了,接下来就是烧录了。首先准备好ESP8266、CH340模块、母对母杜邦线若干。根据ESP8266用户手册,查询下载模式接线方式。启动模式如图3.4所示。
图3.4 ESP8266启动模式
下载模式实际连线方式如3.5所示。
图3.5 实际连线图
连接好后将CH340与电脑相连接,可能会识别出来,需要安装CH340驱动,安装驱动可以看到如3.6图所示。
图3.6 识别到CH340
万事俱备了,打开烧录工具,打开如图3.7所示。
图3.7 打开烧录工具
打开烧录工具后,选择固件,如图3.8所示。
图3.8 选择固件
然后填写填上烧录地址填0,选中固件,SPI更改为DIO,FLASHSIZE改为32mbit,选择对应的串口,选择波特率为115200,点击开始。如果连线正确就可以会开始,等待完成即可,如果没有识别,则大概率是连线错误,请检查连线。烧录完成后如图3.9所示。
3.9 烧录完成
烧录完成后将启动模式更改为运行模式。拔掉IO0的杜邦线即可。如图3.10所示。
图3.10 运行模式连线图
断开杜邦线后,拔下CH340重新连接。接下来测试固件是否烧录成功。打开串口调试工具,选中对应串口,波特率115200,输入AT,选中自动换行,点击发送。如果成功会返回OK,如果失败会不显示,或显示乱码,按复位键也会显示乱码,失败如图3.11所示。
图3.11 烧录失败
第一遍烧录失败是较为正常的,解决方法是按照刚刚的步骤重新烧录一遍,特别注意IO0的杜邦线连接方式,并且重新烧录前需要关闭串口调试助手,不然会占用串口。
- 重新烧录
在几次实验后发现固件与芯片不符,不符合是因为安信可所提供的固件是他们个性化开发的,所以适配性不好。所以需要换个思路,直接找该芯片的提供商,也就是乐鑫,下面开始介绍。
首先是获取固件,获取地址【https://www.espressif.com/zh-hans/support/download/at】,选择ESP8266,点击即会跳转,如图3.12所示。
图3.12 乐鑫ESP8266 AT固件
选择ESP8266 AT binaries,如图3.13所示。
图3.13 ESP8266 AT Binaries
然后点击推荐的固件,点击下载,如图3.14所示。
图3.14 下载AT固件
解压后可以看到两个文件,其中ESP8266-IDF-AT Release Note 是新版本的一些说明,文件夹中factory的bin文件就是固件。解压后如图3.15所示。
图3.15 解压
下面进行烧录,CH340与ESP8266的连接方式可完全按上面来,这里还有一种简便方式,简单来说就是如果给ESP8266通电后大部分引脚默认就是高电平,所以根据下载模式只需要将IO0拉低就行了,这样三根杜邦线就可以完成。连接示意图如图3.16所示。
图3.16 连接示意图
连接好后打开下载工具,选择factory中的bin文件,地址填0,SPI模式选DIO,FLASH SIZE根据实际芯片大小选择,ESP-12F选择32Mbit,具体选择如图3.17所示。
图3.17 烧录配置
点击Start后正常就会开始烧录了,如果没有可以按一下ESP8266的RST键。烧录完成后拔掉IO0,根据刚刚下载的压缩包中的手册如图3.18所示,可以知道得通过IO13和1O15来通讯。
图3.18 使用手册
运行模式连接示意图如图3.19所示。
图3.19 运行模式连接示意图
按以上连接方式连接后,打开串口调试工具,波特率选择115200,按下复位键,如果收到ready,这表示固件烧录完成。可以发送一些测试指令来测试固件是否能正常使用。正常运行如图3.20所示。
图3.20 正常运行效果
3.3 使用串口连接云平台
3.3.1 平台及数据准备
完成以上操作后,说明固件已经成功烧录完成。下面进行云平台连接,云平台有很多,目前有阿里云物联网平台,ONENET,百度物联网平台,还有开源物联网平台,还可以自己搭建平台,他们共性是都支持以MQTT协议为通信协议的平台,所以也可以自己搭建MQTT服务器。
对于MQTT协议可以自行查阅文档,它是一种发布/订阅模型,典型的应用有两种模式,一是,物理层控制传输层向平台的某个MQTT主题发布消息,这个消息可以是任意内容,一般是发送JSON格式串,这样平台层就获取到了物理层的数据了,然后可交由上层使用;二是,物联网层控制传输层订阅平台的某个主题,上层应用向这个主题发送指令,那么物理层就可解析这个指令做出相应的操作。这样就完成了数据的上传和指令的接受了。
这里选择阿里云物联网平台,阿里云物联网平台相对来说是更加麻烦的,不过学会它的连接后,使用其他平台也就没有问题了。
首先登陆阿里云物理平台,登录网址【https://iot.console.aliyun.com/】,登录后点击【公共实例】,点击产品,点击【创建产品】,名称随意,选择自定义产品,选择透传,选择免校验,选择设备密钥。然后点击完成。产品创建配置如图3.21所示。
图3.21 产品创建配置图
创建完成后点击查看产品详请,可以自定义一些topic。然后在该产品下创建设备,点击设备,添加设备,产品选择刚刚创建的产品,名称随意,备注随意,点击确定。配置如图3.22所示。
图3.22 设备配置
确定后,点击查看设备详情,可以看到如图3.23所示的信息。
图3.23 设备详情
点击如图DeviceSecret,可以获取到设备的三元组如图3.24所示。保持好三元组的信息。
图3.24 三元组
设备的接入可以查看官方文档,如图3.25所示。
图3.25 官方文档
查看MQTT接入方式,网址如下,如果过期了可以自行按如图3.26所示查找。
【https://help.aliyun.com/document_detail/73742.html?spm=a2c4g.11186623.6.614.77e53d57dlMcmh】
图3.26 MQTT方式接入文档
公共实例的接入域名:
${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com:1883。
其中:
-
${YourProductKey}:请替换为设备所属产品的ProductKey。
- ${YourRegionId}:请替换为您的物联网平台设备所在地域代码。
按照刚刚保存的三元组中的ProductKey替换字符串中的内容,地域查询如图3.27所示。
图3.27 地域查询
所以接入域名为:a1Wp5KdjrwG.iot-as-mqtt.cn-shanghai.aliyuncs.com:1883
接下来要拼接以下内容:
mqttClientId: clientId+"|securemode=3,signmethod=hmacsha1,timestamp=132323232|"
mqttUsername: deviceName+"&"+productKey
mqttPassword: sign_hmac(deviceSecret,content)
mqttClientId:格式中| |内为扩展参数。
clientId:表示客户端ID,可自定义,长度不可超过64个字符。建议使用设备的MAC地址或SN码,方便您识别区分不同的客户端。
securemode:表示目前安全模式,可选值有2(TLS直连模式)和3(TCP直连模式)。
signmethod:表示签名算法类型。支持hmacmd5,hmacsha1和hmacsha256,默认为hmacmd5。
timestamp:表示当前时间毫秒值,可以不传递。
mqttPassword:sign签名需把提交给服务器的参数按字典排序后,根据signmethod加签。
content的值为提交给服务器的参数(ProductKey、DeviceName、timestamp和clientId),按照字母顺序排序, 然后将参数值依次拼接。通过源码分析得知,他是按clientId, deviceName, productKey,timestamp这个顺序拼接的,并且是key+value的形式,具体实例见下文。
该设备的信息如下:
-
clientId = 2017519216(按推荐方式提供,也可自定义)
-
deviceName = the_device(来自于三元组),
-
productKey = a1Wp5KdjrwG(来自于三元组)
-
timestamp (不用)
-
signmethod=hmacsha1,(加密方式)
-
deviceSecret= a0634c8e595544fa38652287cc981bf9,(来自于三元组)
-
使用TCP方式提交
则对应的信息为:
mqttClientId: ”2017519216|securemode=3,signmethod=hmacsha1|”
mqttUsername: ”the_device& a1Wp5KdjrwG”
这里对于密码获取简单介绍一下,密码应该使用一个加密函数通过 deviceSecert与Content进行加密,加密函数有很多种(支持hmacmd5,hmacsha1和hmacsha256,),可以使用在线工具的方式进行加密,也可以使用单片机实现加密算法,阿里云提供了加密函数的C语言实现。这里先使用在线加密的方式进行加密。
拼接Content: ”clientId2017519216deviceNamethe_deviceproductKeya1Wp5KdjrwG”,没有时间戳不写,这是要加密的内容,加密过程如图3.28所示。
图3.28 在线加密
加密结果:1c1ea606f217a89fa1cc1ac9f97802b009a993db
至此需要的数据都准备好了。汇总一下:
接入域名 | a1Wp5KdjrwG.iot-as-mqtt.cn-shanghai.aliyuncs.com:1883 |
---|---|
mqttClientId | 2017519216|securemode=3,signmethod=hmacsha1| |
mqttUsername | the_device&a1Wp5KdjrwG |
mqttPassword | 1c1ea606f217a89fa1cc1ac9f97802b009a993db |
3.3.2 ESP8266连接阿里云平台
经过上面数据准备,可以进行连接云平台了,连接平台大致为以下步骤,连接wifi,配置MQTT信息,连接云平台,发送就收消息,具体流程如图3.29所示。
图3.29 SP8266使用流程图
根据流程图的描述,首先是连接Wi-Fi,所以需要查阅与连接Wi-Fi有关的AT指令,AT指令文档在乐鑫官网文档中可以看到。【https://docs.espressif.com/projects/esp-at/zh_CN/latest/AT_Command_Set/index.html】。也可在提供的文件夹中找到。
与Wi-Fi相关的AT指令
• AT+CWMODE:查询/设置 Wi-Fi 模式 (Station/SoftAP/Station+SoftAP)
• AT+CWJAP:连接 AP
• AT+CWRECONNCFG:查询/设置 Wi-Fi 重连配置
• AT+CWLAPOPT:设置AT+CWLAP 命令扫描结果的属性
• AT+CWLAP:扫描当前可用的 AP
• AT+CWQAP:断开与 AP 的连接
• AT+CWSAP:配置 ESP32 SoftAP 参数
• AT+CWLIF:查询连接到 ESP SoftAP 的 station 信息
• AT+CWQIF:断开 station 与 ESP SoftAP 的连接
• AT+CWDHCP:启用/禁用 DHCP
• AT+CWDHCPS:查询/设置 ESP SoftAP DHCP 分配的 IP 地址范围
• AT+CWAUTOCONN:上电是否自动连接 AP
…
连接Wi-Fi步骤:
- 设置为Station模式
AT+CWMODE=1 |
---|
- 连接Wi-Fi,第一个参数为Wi-Fi名,第二个参数为密码
AT+CWJAP=“FAST”,“12345789rg” |
---|
Wi-Fi连接成功如图3.30所示。
图3.30 连接Wi-Fi成功
与MQTT相关的AT指令:
• AT+MQTTUSERCFG:设置 MQTT 用户属性
•AT+MQTTCONNCFG:设置 MQTT 连接属性
•AT+MQTTPUB:发布 MQTT 消息(字符串)
•AT+MQTTSUB:订阅 MQTT Topic
•AT+MQTTCONN:连接 MQTT Broker
•AT+MQTTUNSUB:取消订阅 MQTT Topic
•AT+MQTTCLEAN:断开 MQTT 连接
命令说明请查阅文档。
MQTT使用:
- 配置MQTT用户属性,根据3.3.1节获取到的数据填充,其中clientId的逗号得转义。
AT+MQTTUSERCFG=0,1,"2017519216\|securemode=3\\,signmethod=hmacsha1\|","the_device&a1Wp5KdjrwG","1c1ea606f217a89fa1cc1ac9f97802b009a993db",0,0,""
- 配置MQTT连接属性,超时设置为300
AT+MQTTCONNCFG=0,300,0,"","",0,0
-
连接服务器
AT+MQTTCONN=0,"a1Wp5KdjrwG.iot-as-mqtt.cn-shanghai.aliyuncs.com",1883,0
连接成功如图3.31,3.32所示。
图3.31 连接服务器成功
图3.32 连接服务器成功
如果没有连接成功,就是参数有错误,所有的符号都应该为英文符号。以上过程,在做下一步前每一步都是成功的,即返回的是OK。
- 发送数据
发送数据需要对某个topic发送,产品中可以创建topic,设备中可以查看有哪些topic。这里找一个topic。topic如图3.33所示。
图3.33 topic列表
Topic:/a1Wp5KdjrwG/the_device/user/update
Data:”{
\\“temperature\\”:36.5\\,
\\“humidity\\”:50
}”
AT+MQTTPUB=0,"/a1Wp5KdjrwG/the_device/user/update","{\\"temperature\\":36.5\\,\\"humidity\\":50}",0,0
发送成功串口助手打印ok,如图3.34所示。在阿里云物联网平台的日志服务中可以查看该条数据。
图3.34 串口发布消息成功
图3.35 云平台收到数据
- 接收数据
接收数据前得订阅一个有订阅权限的topic。
Topic:a1Wp5KdjrwG/the_device/user/get
AT+MQTTSUB=0,"a1Wp5KdjrwG/the\_device/user/get",0
订阅成功串口助手显示OK,在平台设备中可以看到订阅的Topic,向该Topic发送消息,ESP8266可接收到数据,如图3.36所示。
图3.36 订阅主题成功
点击发布消息发布{“operation”:“close”},ESP8266收到后使用串口打印该条消息,如图3.37所示。
图3.37 ESP8266 接收到消息
至此使用串口连接平台就完成了,下面将介绍STM32控制ESP8266连接平台。
3.4 使用STM32连接云平台
有了上面通过串口连接平台的经验,使用STM32连接就较为容易了,与使用串口连接的区别就在于,发送各种指令的不再是我们手动发送了,而是使用STM32来依次发送。根据这个原理,找一个STM32 UART工程,在它的基础上就可实现使用STM32连接云平台,安信可提供了现成的AT STM32工程【https://docs.ai-thinker.com/esp8266/examples/at_demo】,当然也可以自己手动封装。下载工程项目如图3.38所示。
图3.38 STM32 AT工程
打开ESP8266->Project 中的项目文件,打开工程后,需要与自己的开发板做一个适配,由于本项目使用的是STM32F103ZET6,所以得删除原先的启动文件然后添加新的启动文件如图3.39所示,修改芯片型号如图3.40所示。
图3.39 修改启动文件
图3.40 修改芯片型号
修改宏定义STM32F10X_MD为STM32F10X_HD,具体操作如图3.41所示。
图3.41 修改宏定义
简单分析工程可知,该工程使用UART2与ESP8266交互,使用UART3作为串口打印,UART2收到的数据都会转发给UART3。也可根据需求自己修改对应的UART。STM32与ESP8266按照工程默认的连接方式如表3.1所示。
表3.1 STM32与ESP8266连接表
STM32引脚 | ESP8266引脚 |
---|---|
A2 | IO13 |
A3 | IO15 |
STM32与CH340默认连接方式如表3.2所示。
表3.2 STM32与CH340连接表
STM32引脚 | CH340引脚 |
---|---|
B10 | RXD |
B11 | TXD |
连接完成后需要对连接信息进行一个配置,主要修改mqtt.h这个文件,根据上节的串口连接云平台生成的连接信息配置。配置如图3.42所示。
图3.42 连接信息配置
需要注意的是User_ESP8266_client_id中“,”需要在前面加两个反斜杠,这是通过测试得到的结论。Main函数做如图3.43所示的修改。
图3.43 main函数修改
完成上述修改后即可编译代码,将程序下载到开发板了。打开串口调试助手发现卡在了配置MQTT信息,如图3.44所示
图3.44 配置MQTT信息
经过分析发现是因为安信可所提供代码有点问题,在esp8266.c中cmd数组给得太小了,所以出了问题,解决方法就是增大数组,将120改为300,不止该函数,下面的几个函数中的cmd都得增加。如图3.45所示。
图3.45 增加cmd数组大小
其中ESP8266_SendString()函数中数组大小只有20,应该它是问题所在,改它的大小为200.如图3.46所示。
图3.46 修改数组大小
为了能发送和接收消息,需要提供两个topic。在mqtt.h中添加User_ESP8266_MQTTServer_Topic_Send和User_ESP8266_MQTTServer_Topic_Recv两个topic,如图3.47所示。
图3.47 添加TOPIC
修改完后还需要修改mqtt.c中订阅和发布的主题,修改如图3.48所示。
图3.48 修改发布和订阅的主题
重新下载重新后,通过串口可以看到正常发送了,在物联网平台日志服务中可以看到上传的消息,如图3.49所示。
图3.49 STM32上传数据
至此就完成了STM32连接物联网平台,当然后续还有一些需要完善的地方,比如接收到的数据解析,如何给ESP8266配网等问题。
第4章 平台层
4.1 平台层种类
云平台种类十分多;仅国内就有如下平台:
- 运营商平台
中国电信的天翼物联 https://www.ctwing.cn/
中国联通的物联网平台 https://www.10646.cn/
中国移动的ONENet https://open.iot.10086.cn/
- 互联网大厂平台
百度天工 https://cloud.baidu.com/solution/iot/index.html
阿里云物联网 https://iot.aliyun.com/
腾讯IoT Explorer https://cloud.tencent.com/product/iotexplorer
腾讯QQ物联 https://iot.open.qq.com/
京东微联 https://smartcloud.jd.com/
京东小京鱼 https://jdwhale.jd.com/
京东智联云 https://www.jdcloud.com/cn/iot/all
小米IoT开发者平台 https://iot.mi.com/
- 设备商平台
华为云IoT https://www.huaweicloud.com/product/iot.html
浪潮云IoT https://cloud.inspur.com/product/iotdm/
新华三绿洲平台 https://iot-developer.h3c.com/
庆科云FogCloud https://v2.fogcloud.io/
中消云 http://www.zxycloud.com/
- 创业型公司平台
涂鸦智能 https://www.tuya.com/cn/
机智云 https://www.gizwits.com/
云智易 http://www.xlink.cn/
青云 https://sw.qingcloud.com/internet_of_things
智城云 https://www.zcyun.cn/
氦氪云 https://www.hekr.me/
Ablecloud http://www.ablecloud.com/
Yeelink http://www.yeelink.net/
艾拉物联 https://www.ayla.com.cn/