这里写目录标题
- 项目介绍
- mqtt服务器相关知识![在这里插入图片描述](https://img-blog.csdnimg.cn/9ad065fb8fac48b1b975fc3a48b99763.png)
- 下位机代码
- 项目需要的一些开发工具
项目介绍
本项目芯片使用STM32F103ZET6,微信小程序开发使用微信开发者工具。
stm32作为下位机,功能是每过一段时间上传温湿度以及光照度给mqtt服务器,然后微信小程序从mqtt服务器订阅对应的主题来接收下位机发过来的数据并进行处理,并在微信小程序中设置LED开关,以及蜂鸣器开关。
mqtt服务器相关知识
如图,汽车上有联网芯片,可以充当客户端,汽车采集到的数据可以发送到mqtt服务器,然后再搭建其他mqtt客户端(电脑,手机等设备),这些设备就可以从mqtt服务器获取汽车的数据。
这里的单片机和微信小程序都是客服端,他们连接上同一个服务器,然后通过订阅/发布对应的主题,来进行信息的交互。
主题:
用来区别接收的数据。比如汽车采集的速度,要传给mqtt服务器,就要给数据打上一个标签,即主题,然后其他mqtt客户端可以根据主题来获取数据。
发布:
客服端发布数据给服务端,并标上主题。
订阅:
客户端订阅主题,然后获取主题对应的数据。
每一个客户端都可以订阅/发布数据,即数据可以互相发送。
下位机代码
main.c
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"
#include "beep.h"
#include "adc.h"
#include "lsens.h"
#include "esp8266.h"
#include "MqttKit.h"
#include "onenet.h"
uint8_t Usart_String[50];
uint8_t * dataPtr;
uint8_t tem_light_string[50];
const char *subtopics[] = {"/iot/2462/sub/wsy"};
const char pubtopics[] = {"/iot/2462/pub/wsy"};
void dht11_exit()
{
while(DHT11_Init())
{
LCD_ShowString(30,130,200,16,16,"DHT11 Error");
delay_ms(200);
LCD_Fill(30,130,239,130+16,WHITE);
delay_ms(200);
}
}
void Hardware_Init(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Usart1_Init(115200);
Usart2_Init(115200);
BEEP_Init();
UsartPrintf(USART_DEBUG, " Hardware init OK\r\n");
}
int main(void)
{
u8 timeCount=0;
u8 temperature;
u8 humidity;
u8 adcx;
LED_Init();
delay_init();
Hardware_Init();
LCD_Init();
LCD_Clear(WHITE);
Lsens_Init();
LCD_ShowString(30,130,200,16,16,"DHT11 OK");
POINT_COLOR=BLUE;
LCD_ShowString(30,150,200,16,16,"Temp: C");
LCD_ShowString(30,170,200,16,16,"Humi: %");
LCD_ShowString(30,190,200,16,16,"LSENS_VAL:");
dht11_exit();
ESP8266_Init();
while(OneNet_DevLink())
delay_ms(500);
OneNet_Subscribe(subtopics, 1);
while(1)
{
if(timeCount%40==0)
{
DHT11_Read_Data(&temperature,&humidity);
adcx=Lsens_Get_Val();
LCD_ShowNum(30+40,150,temperature,2,16);
LCD_ShowNum(30+40,170,humidity,2,16);
LCD_ShowNum(30+10*8,190,adcx,3,16);
}
if(++timeCount >= 200)
{
UsartPrintf(USART_DEBUG, "OneNet_Publish\r\n");
sprintf((char *)tem_light_string,"{\"tem\":%02d,\"hum\":%02d,\"light\":%d}",temperature,humidity,adcx);
OneNet_Publish((char *)pubtopics, tem_light_string);
timeCount = 0;
ESP8266_Clear();
}
dataPtr = ESP8266_GetIPD(3);
if(dataPtr != NULL)
OneNet_RevPro(dataPtr);
delay_ms(10);
}
}
这里移植了Onenet平台的stm32芯片esp8266连接服务器的代码。
有需要的小伙伴可进入连接获取添加链接描述
esp8266.c
#include "stm32f10x.h"
#include "esp8266.h"
#include "delay.h"
#include "usart.h"
#include <string.h>
#include <stdio.h>
#define ESP8266_WIFI_INFO "AT+CWJAP=\"xxx\",\"xxxxxx\"\r\n"
#define ESP8266_ONENET_INFO "AT+CIPSTART=\"TCP\",\"xxxxxxx\",xxxxx\r\n"
unsigned char esp8266_buf[128];
unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;
void ESP8266_Clear(void)
{
memset(esp8266_buf, 0, sizeof(esp8266_buf));
esp8266_cnt = 0;
}
_Bool ESP8266_WaitRecive(void)
{
if(esp8266_cnt == 0)
return REV_WAIT;
if(esp8266_cnt == esp8266_cntPre)
{
esp8266_cnt = 0;
return REV_OK;
}
esp8266_cntPre = esp8266_cnt;
return REV_WAIT;
}
_Bool ESP8266_SendCmd(char *cmd, char *res)
{
unsigned char timeOut = 200;
Usart_SendString(USART2, (unsigned char *)cmd, strlen((const char *)cmd));
while(timeOut--)
{
if(ESP8266_WaitRecive() == REV_OK)
{
if(strstr((const char *)esp8266_buf, res) != NULL)
{
ESP8266_Clear();
return 0;
}
}
delay_ms(10);
}
return 1;
}
void ESP8266_SendData(unsigned char *data, unsigned short len)
{
char cmdBuf[32];
ESP8266_Clear();
sprintf(cmdBuf, "AT+CIPSEND=%d\r\n", len);
if(!ESP8266_SendCmd(cmdBuf, ">"))
{
Usart_SendString(USART2, data, len);
}
}
unsigned char *ESP8266_GetIPD(unsigned short timeOut)
{
char *ptrIPD = NULL;
do
{
if(ESP8266_WaitRecive() == REV_OK)
{
ptrIPD = strstr((char *)esp8266_buf, "IPD,");
if(ptrIPD == NULL)
{
}
else
{
ptrIPD = strchr(ptrIPD, ':');
if(ptrIPD != NULL)
{
ptrIPD++;
return (unsigned char *)(ptrIPD);
}
else
return NULL;
}
}
delay_ms(5);
} while(timeOut--);
return NULL;
}
void ESP8266_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_Initure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Initure.GPIO_Pin = GPIO_Pin_14;
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");
while(ESP8266_SendCmd("AT\r\n", "OK"))
delay_ms(500);
UsartPrintf(USART_DEBUG, "1. RST\r\n");
ESP8266_SendCmd("AT+RST\r\n", "");
delay_ms(500);
ESP8266_SendCmd("AT+CIPCLOSE\r\n", "");
delay_ms(500);
UsartPrintf(USART_DEBUG, "2. CWMODE\r\n");
while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK"))
delay_ms(500);
UsartPrintf(USART_DEBUG, "3. AT+CWDHCP\r\n");
while(ESP8266_SendCmd("AT+CWDHCP=1,1\r\n", "OK"))
delay_ms(500);
UsartPrintf(USART_DEBUG, "4. CWJAP\r\n");
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");
}
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
if(esp8266_cnt >= sizeof(esp8266_buf)) esp8266_cnt = 0;
esp8266_buf[esp8266_cnt++] = USART2->DR;
USART_ClearFlag(USART2, USART_FLAG_RXNE);
}
}
#define ESP8266_WIFI_INFO “AT+CWJAP=“xxx”,“xxxxxx”\r\n” //填入你要连接的wifi名字和密码
#define ESP8266_ONENET_INFO “AT+CIPSTART=“TCP”,“xxxxxxx”,xxxxx\r\n”//填入你要连接的服务器域名和端口号
onenet.c
#include "stm32f10x.h"
#include "esp8266.h"
#include "onenet.h"
#include "mqttkit.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "beep.h"
#include <string.h>
#include <stdio.h>
#include "cJSON.h"
#define PROID "0a15a6464f0fee359eadb8992ebb72d7"
#define AUTH_INFO "123456"
#define DEVID "11"
extern unsigned char esp8266_buf[128];
_Bool OneNet_DevLink(void)
{
MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0};
unsigned char *dataPtr;
_Bool status = 1;
UsartPrintf(USART_DEBUG, "OneNet_DevLink\r\n"
"PROID: %s, AUIF: %s, DEVID:%s\r\n"
, PROID, AUTH_INFO, DEVID);
if(MQTT_PacketConnect(PROID, AUTH_INFO, DEVID, 256, 0, MQTT_QOS_LEVEL0, NULL, NULL, 0, &mqttPacket) == 0)
{
ESP8266_SendData(mqttPacket._data, mqttPacket._len);
dataPtr = ESP8266_GetIPD(250);
if(dataPtr != NULL)
{
if(MQTT_UnPacketRecv(dataPtr) == MQTT_PKT_CONNACK)
{
switch(MQTT_UnPacketConnectAck(dataPtr))
{
case 0:UsartPrintf(USART_DEBUG, "Tips: 连接成功\r\n");status = 0;break;
case 1:UsartPrintf(USART_DEBUG, "WARN: 连接失败:协议错误\r\n");break;
case 2:UsartPrintf(USART_DEBUG, "WARN: 连接失败:非法的clientid\r\n");break;
case 3:UsartPrintf(USART_DEBUG, "WARN: 连接失败:服务器失败\r\n");break;
case 4:UsartPrintf(USART_DEBUG, "WARN: 连接失败:用户名或密码错误\r\n");break;
case 5:UsartPrintf(USART_DEBUG, "WARN: 连接失败:非法链接(比如token非法)\r\n");break;
default:UsartPrintf(USART_DEBUG, "ERR: 连接失败:未知错误\r\n");break;
}
}
}
MQTT_DeleteBuffer(&mqttPacket);
}
else
UsartPrintf(USART_DEBUG, "WARN: MQTT_PacketConnect Failed\r\n");
return status;
}
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_LEVEL2, topics, topic_cnt, &mqttPacket) == 0)
{
ESP8266_SendData(mqttPacket._data, mqttPacket._len);
MQTT_DeleteBuffer(&mqttPacket);
}
}
void OneNet_Publish(const char *topic, const char *msg)
{
MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0};
UsartPrintf(USART_DEBUG, "Publish Topic: %s, Msg: %s\r\n", topic, msg);
if(MQTT_PacketPublish(MQTT_PUBLISH_ID, topic, msg, strlen(msg), MQTT_QOS_LEVEL2, 0, 1, &mqttPacket) == 0)
{
ESP8266_SendData(mqttPacket._data, mqttPacket._len);
MQTT_DeleteBuffer(&mqttPacket);
}
}
void OneNet_RevPro(unsigned char *cmd)
{
MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0};
char *req_payload = NULL;
char *cmdid_topic = NULL;
unsigned short topic_len = 0;
unsigned short req_len = 0;
unsigned char type = 0;
unsigned char qos = 0;
static unsigned short pkt_id = 0;
short result = 0;
char *dataPtr = NULL;
char numBuf[10];
int num = 0;
cJSON * json,*json_value;
type = MQTT_UnPacketRecv(cmd);
switch(type)
{
case MQTT_PKT_CMD:
result = MQTT_UnPacketCmd(cmd, &cmdid_topic, &req_payload, &req_len);
if(result == 0)
{
UsartPrintf(USART_DEBUG, "cmdid: %s, req: %s, req_len: %d\r\n", cmdid_topic, req_payload, req_len);
MQTT_DeleteBuffer(&mqttPacket);
}
break;
case MQTT_PKT_PUBLISH:
result = MQTT_UnPacketPublish(cmd, &cmdid_topic, &topic_len, &req_payload, &req_len, &qos, &pkt_id);
if(result == 0)
{
UsartPrintf(USART_DEBUG, "topic: %s, topic_len: %d, payload: %s, payload_len: %d\r\n",
cmdid_topic, topic_len, req_payload, req_len);
json = cJSON_Parse(req_payload);
if(!json)UsartPrintf(USART_DEBUG,"Error before: [%s]\n",cJSON_GetErrorPtr());
else
{
json_value=cJSON_GetObjectItem(json,"target");
UsartPrintf(USART_DEBUG,"json_value= %d\r\n",json_value->string);
UsartPrintf(USART_DEBUG,"json_value= %d\r\n",json_value->valuestring);
if(strstr(json_value->valuestring,"led")!=NULL)
{
json_value=cJSON_GetObjectItem(json,"value");
if(json_value->valueint)
LED1=0;
else
LED1=1;
}
else
{
json_value=cJSON_GetObjectItem(json,"value");
if(json_value->valueint)
BEEP=1;
else
BEEP=0;
}
}
cJSON_Delete(json);
switch(qos)
{
case 1:
if(MQTT_PacketPublishAck(pkt_id, &mqttPacket) == 0)
{
UsartPrintf(USART_DEBUG, "Tips: Send PublishAck\r\n");
ESP8266_SendData(mqttPacket._data, mqttPacket._len);
MQTT_DeleteBuffer(&mqttPacket);
}
break;
case 2:
if(MQTT_PacketPublishRec(pkt_id, &mqttPacket) == 0)
{
UsartPrintf(USART_DEBUG, "Tips: Send PublishRec\r\n");
ESP8266_SendData(mqttPacket._data, mqttPacket._len);
MQTT_DeleteBuffer(&mqttPacket);
}
break;
default:
break;
}
}
break;
case MQTT_PKT_PUBACK:
if(MQTT_UnPacketPublishAck(cmd) == 0)
UsartPrintf(USART_DEBUG, "Tips: MQTT Publish Send OK\r\n");
break;
case MQTT_PKT_PUBREC:
if(MQTT_UnPacketPublishRec(cmd) == 0)
{
UsartPrintf(USART_DEBUG, "Tips: Rev PublishRec\r\n");
if(MQTT_PacketPublishRel(MQTT_PUBLISH_ID, &mqttPacket) == 0)
{
UsartPrintf(USART_DEBUG, "Tips: Send PublishRel\r\n");
ESP8266_SendData(mqttPacket._data, mqttPacket._len);
MQTT_DeleteBuffer(&mqttPacket);
}
}
break;
case MQTT_PKT_PUBREL:
if(MQTT_UnPacketPublishRel(cmd, pkt_id) == 0)
{
UsartPrintf(USART_DEBUG, "Tips: Rev PublishRel\r\n");
if(MQTT_PacketPublishComp(MQTT_PUBLISH_ID, &mqttPacket) == 0)
{
UsartPrintf(USART_DEBUG, "Tips: Send PublishComp\r\n");
ESP8266_SendData(mqttPacket._data, mqttPacket._len);
MQTT_DeleteBuffer(&mqttPacket);
}
}
break;
case MQTT_PKT_PUBCOMP:
if(MQTT_UnPacketPublishComp(cmd) == 0)
{
UsartPrintf(USART_DEBUG, "Tips: Rev PublishComp\r\n");
}
break;
case MQTT_PKT_SUBACK:
if(MQTT_UnPacketSubscribe(cmd) == 0)
UsartPrintf(USART_DEBUG, "Tips: MQTT Subscribe OK\r\n");
else
UsartPrintf(USART_DEBUG, "Tips: MQTT Subscribe Err\r\n");
break;
case MQTT_PKT_UNSUBACK:
if(MQTT_UnPacketUnSubscribe(cmd) == 0)
UsartPrintf(USART_DEBUG, "Tips: MQTT UnSubscribe OK\r\n");
else
UsartPrintf(USART_DEBUG, "Tips: MQTT UnSubscribe Err\r\n");
break;
default:
result = -1;
break;
}
ESP8266_Clear();
if(result == -1)
return;
dataPtr = strchr(req_payload, '}');
if(dataPtr != NULL && result != -1)
{
dataPtr++;
while(*dataPtr >= '0' && *dataPtr <= '9')
{
numBuf[num++] = *dataPtr++;
}
num = atoi((const char *)numBuf);
}
if(type == MQTT_PKT_CMD || type == MQTT_PKT_PUBLISH)
{
MQTT_FreeBuffer(cmdid_topic);
MQTT_FreeBuffer(req_payload);
}
}
#define PROID “0a15a6464f0fee359eadb8992ebb72d7”//一些私人的服务器需要设备号ID
#define AUTH_INFO “123456”//密码
#define DEVID “11”//随便写,这里没有要求
项目需要的一些开发工具
1.微信开发者工具添加链接描述
2.mqtt.js插件 密码6666
3.onenet移植代码用来给下位机连接服务器使用
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)