前言

做了一个物联网的项目,基本内容是GPS+MQTT+微信小程序,GPS获取经纬度通过ESP8266上传到云服务器,然后微信小程序获取经纬度信息,在小程序里显示出当前位置的地图。

环境准备

说到物联网,首先必须得提到两个东西。第一个是无线通信模块这里我用的是国产的ESP8266-01S,01好像是得加一个上拉电阻才能用,这里无线通信还有比如NB-IoT等,无线通信模块的作用是接入互联网。第二个就是通信协议,最熟知的网络协议应该是TCP/IP协议。而在我们物联网中,最常用的是MQTT协议MQTT协议是一个基于应用层的TCP/IP协议具体什么意思可以去了解一下网络协议,而MQTT协议就是我们物联网通信的规范。我们只需要知道这两个东西就行。想具体了解MQTT协议可以去看这篇博客 博客地址

基础工作

这里的准备工作是指完成STM32基础的开发,比如OLED屏幕外设驱动的移植,DHT11温湿度传感器等等,由于需求不同,我就不再赘述。

MQTT相关内容的移植

MQTT的代码我们不可能自己去写,咱也没那个能力。其实这些东西早就有大佬给我们写好了,我们找到这些东西就行。
首先我们搜索OneNET,进入网页的论坛,在搜索框找到OneNET开发板代码、资料,点这里,然后打开百度网盘,下载OneNET标准版3.2的裸机-基础教程的代码,如下图
1

解压后我们打开MQTT-例程,里面的esp8266.c文件esp8266.h文件MQTTKit.c文件MQTTKit.h文件onenet.c文件onenet.h文件就是我们所需要的文件,移植到我们自己的工程里,怎么移植我也不赘述了,移植好后工程文件如下
1
在这里我们也感谢一下这些白嫖代码的作者:张继瑞同志

配置程序实现数据上传至MQTT服务器

Topic配置及订阅

我们首先需要加两个东西,订阅命令的Topic以及上行数据的Topic

1
2
const char *devSubTopic[] = {"/mysmarthome1/sub"};  #设备上行数据Topic
const char devPubTopic[] = "/mysmarthome1/pub"; #设备订阅的Topic

在初始化结束加上这个函数

1
OneNet_Subscribe(devSubTopic, 1);

我们打开这个函数,可以看到这个函数的作用就是订阅我们在前面配置的Topic

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void OneNet_Subscribe(const char *topics[], unsigned char topic_cnt)
{

unsigned char i = 0;

MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0}; //协议包

for(; i < topic_cnt; i++)
UsartPrintf(USART_DEBUG, "Subscribe Topic: %s\r\n", topics[i]);

if(MQTT_PacketSubscribe(MQTT_SUBSCRIBE_ID, MQTT_QOS_LEVEL0, topics, topic_cnt, &mqttPacket) == 0)
{
ESP8266_SendData(mqttPacket._data, mqttPacket._len); //向平台发送订阅请求

MQTT_DeleteBuffer(&mqttPacket); //删包
}

}

esp8266接入互联网

在这一步,我们需要配置两个东西,第一个是我们WIFI的名称以及密码,注意WIFI必须为2.4GHZ,并且连接过程中不需要登录操作,校园网就不行。
esp8266.c中修改

1
#define ESP8266_WIFI_INFO		"AT+CWJAP=\" 这里填你的WIFI名称 \",\" 你的WIFI密码 \"\r\n"

第二个是配置我们订阅的MQTT服务器的IP地址以及端口号,这里如果想用自己的服务器,得买一个域名,配置ssl证书,最重要的是得进行ICP备案,整个过程有点复杂,后续可能会专门写一篇教程。这里我们其实用免费的就好,不过你后续微信小程序要发布的话,必须得用自己的服务器并且备案。
这里我们大陆MQTT的官网,找到MQTT下面的公共MQTT服务器,如图
1
这个Broker就是域名,我们在esp8266.c中修改
1
#define ESP8266_ONENET_INFO		"AT+CIPSTART=\"TCP\",\"域名\",端口号\r\n"

这里端口号填1883

单片机控制esp8266是通过串口发送AT指令,这里我们看一下ESP8266的初始化代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
void ESP8266_Init(void)
{

GPIO_InitTypeDef GPIO_Initure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //ESP8266复位引脚配置
GPIO_Initure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Initure.GPIO_Pin = GPIO_Pin_14; //GPIOC14-复位
GPIO_Initure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_Initure);

GPIO_WriteBit(GPIOC, GPIO_Pin_14, Bit_RESET);
delay_ms(250);
GPIO_WriteBit(GPIOC, GPIO_Pin_14, Bit_SET);
delay_ms(500);

ESP8266_Clear();

UsartPrintf(USART_DEBUG, "0. AT\r\n"); //测试AT指令
while(ESP8266_SendCmd("AT\r\n", "OK"))
delay_ms(500);

UsartPrintf(USART_DEBUG, "1. RST\r\n"); //ESP8266模块进行重启
ESP8266_SendCmd("AT+RST\r\n", "");
delay_ms(500);
ESP8266_SendCmd("AT+CIPCLOSE\r\n", ""); //关闭单连接模式下的 TCP/UDP/SSL 连接
delay_ms(500);
UsartPrintf(USART_DEBUG, "2. CWMODE\r\n"); //进入station模式
while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK"))
delay_ms(500);

UsartPrintf(USART_DEBUG, "3. AT+CWDHCP\r\n"); //启用DHCP(动态主机配置协议)
while(ESP8266_SendCmd("AT+CWDHCP=1,1\r\n", "OK"))
delay_ms(500);

UsartPrintf(USART_DEBUG, "4. CWJAP\r\n"); //连接设定的WIFI
while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "GOT IP"))
delay_ms(500);

UsartPrintf(USART_DEBUG, "5. CIPSTART\r\n"); //连接服务器
while(ESP8266_SendCmd(ESP8266_ONENET_INFO, "CONNECT"))
delay_ms(500);

UsartPrintf(USART_DEBUG, "6. ESP8266 Init OK\r\n");

}

所有配置完成后,我们打开串口助手查看ESP8266的连接
1
这样则连接成功,失败的话可以重新上电或者长按复位按键

我们在main函数的循环里加入OneNet_Publish(devPubTopic, PUB_BUF);函数,PUB_BUF为上传的内容数组

使用MQTT.fx软件查看发布内容

我们下载一个MQTT.fx软件,进行调试
新建一个项目
1
在Broker.address中填入公共服务器的地址,进行连接
在Subscribe中填入之前配置的订阅topic进行订阅
1
能看到我们单片机上采集的数据,这部分配置程序实现数据上传至MQTT服务器就到这