本文参考了 B 站 U P 主 [ 画卿师兄 ] : \textcolor{red}{本文参考了B站UP主[画卿师兄]:} 本文参考了B站UP主[画卿师兄]:https://space.bilibili.com/382542366 的【挽救小白第一季】视频进行学习制作和开发。 \textcolor{red}{的【挽救小白第一季】视频进行学习制作和开发。} 的【挽救小白第一季】视频进行学习制作和开发。
随着物联网技术的发展,物联网技术在各个领域均起到作用。其中实现智慧家庭不在是什么难题,通过物联网技术可以很容易的对家庭各种系统进行远程控制和调节,以达到改善和提高人们家庭生活质量的需求。而智慧家庭系统通过各种传感器将采集到的数据经整合后上传至智能云平台经其分析处理后再传输给手机端等移动设备,就可以实现对家庭灯光照明、温度控制、自动开启换气等家庭系统进行远程实时监测和控制
系统框架如下图:
该设计的功能如下:
STM32C8T6(最小核心板)
温湿度模块:DHT11
光照值模块:BH1750
蜂鸣器模块:MH-FMD(低电平触发)
OLED显示模块:(GND开头)
小风扇:LED代替(一个LED+一个10k上拉电阻)
WIFI模块:ESP8266-01S/ATK-ESP8266正点原子官方
烧录模块:ST-LINK V2
串口模块:TTL转USB(CH340G)
阿里云服务器[物联网平台]:https://iot.console.aliyun.com/和微信小程序
元器件 | VCC | GND | 与STM32端 | 其他 |
---|---|---|---|---|
DHT11 | 3.3V | GND | DATA-PA8 | 无 |
BH1750 | 3.3V | GND | SCL-PB6、SDA-PB7 | 无 |
BEEP | 3.3V | GND | I/O-PA0 | 无 |
OLED | 3.3V | GND | SCK-PA5、SDA-PA7 | 无 |
LED | 正极-3.3V(10K的上拉电阻) | 无 | 无 | 负极-PA1 |
ESPB266 | 3.3V | GND | TXD-PA3、RXD-PA2 | 无 |
CH340G | 5.0V | GND | TXD-PA10、RXD-PA9 | 无 |
ST-LINK V2 | 3.3V | GND | SWCLK-SWCLK、SWIO-SWDIO | 无 |
(1)设备数据上传微信端运行图
(2)微信下发数据控制设备端运行图
蜂鸣器在温度大于30℃时开始报警,在微信端下发命令关闭蜂鸣器报警
微信端下发命令打开小风扇(用LED亮灯代替)
(3)成功实现对小风扇(LED亮)的控制实物效果图
(1)dht11.c(移植现有模板后稍作修改)
#include "dht11.h" //DHT11头文件引用
#include "delay.h" //延时函数头文件引用
//复位DHT11
void DHT11_Rst(void)
{
DHT11_IO_OUT();
DHT11_DQ_OUT=0;
delay_ms(20);
DHT11_DQ_OUT=1;
delay_us(30);
}
//等待DHT11回应
//返回1:未检测到DHT11
//返回0:存在
u8 DHT11_Check(void)
{
u8 retry=0;
DHT11_IO_IN();
while (DHT11_DQ_IN&&retry<100)
{
retry++;
delay_us(1);
};
if(retry>=100)return 1;
else retry=0;
while (!DHT11_DQ_IN&&retry<100)
{
retry++;
delay_us(1);
};
if(retry>=100)return 1;
return 0;
}
//从DHT11读取一个值
//返回值:1/0
u8 DHT11_Read_Bit(void)
{
u8 retry=0;
while(DHT11_DQ_IN&&retry<100)
{
retry++;
delay_us(1);
}
retry=0;
while(!DHT11_DQ_IN&&retry<100)
{
retry++;
delay_us(1);
}
delay_us(40);
if(DHT11_DQ_IN)return 1;
else return 0;
}
//从DHT11读取一个字节
//返回值:读到的数据
u8 DHT11_Read_Byte(void)
{
u8 i,dat;
dat=0;
for (i=0;i<8;i++)
{
dat<<=1;
dat|=DHT11_Read_Bit();
}
return dat;
}
//*********从DHT11读取一次数据***************//
//*********temp:温度值(范围:0~50℃)********//
//*********humi:湿度值(范围:20%~90%)********//
//*********返回值:0,正常;1,读取失败********//
u8 DHT11_Read_Data(u8 *humiH,u8 *humiL,u8 *tempH,u8 *tempL)
{
u8 buf[5];
u8 i;
DHT11_Rst();
if(DHT11_Check()==0)
{
for(i=0;i<5;i++)//读取40位数据
{
buf[i]=DHT11_Read_Byte();
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
{
*humiH=buf[0];
*humiL=buf[1];
*tempH=buf[2];
*tempL=buf[3];
}
}else return 1;
return 0;
}
//初始化DHT11的IO口,DQ同时监测DHT11的存在
//返回1:不存在
//返回0:存在
u8 DHT11_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //PA8端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IO口
GPIO_SetBits(GPIOA,GPIO_Pin_8); //PA8输出高
DHT11_Rst(); //复位DHT11
return DHT11_Check(); //等待DHT11的回应
}
(2)dht11.h
#ifndef __DHT11_H
#define __DHT11_H
#include "sys.h"
//IO方向设置
#define DHT11_IO_IN() {GPIOA->CRH&=0XFFFFFFF0;GPIOA->CRH|=8;}
#define DHT11_IO_OUT() {GPIOA->CRH&=0XFFFFFFF0;GPIOA->CRH|=3;}
//IO操作函数
#define DHT11_DQ_OUT PAout(8) //数据端口 PA8输出方向
#define DHT11_DQ_IN PAin(8) //数据端口 PA8输入方向
u8 DHT11_Init(void);//初始化DHT11
u8 DHT11_Read_Data(u8 *humiH,u8 *humiL,u8 *tempH,u8 *tempL);//读取温湿度
u8 DHT11_Read_Byte(void);//读出一个字节
u8 DHT11_Read_Bit(void);//读出一个位
u8 DHT11_Check(void);//监测是否存在DHT11
void DHT11_Rst(void);//复位
#endif
(3)在main.c中添加
//添加全局变量//
u8 humidityH; //湿度整数
u8 humidityL; //湿度小数
u8 temperatureH; //温度整数
u8 temperatureL; //温度小数
int main(void)
{
DHT11_Init(); //DHT11初始化
DEBUG_LOG("DHT11初始化 OK"); //串口显示初始化成功消息
OLED_Refresh_Line("DHT11");
while(1)
{
DHT11_Read_Data(&humidityH,&humidityL,&temperatureH,&temperatureL); //读取温湿度信息
}
}
相应的串口输出等函数在 u s a r t . c 中 \textcolor{red}{相应的串口输出等函数在usart.c中} 相应的串口输出等函数在usart.c中
(1)bh1750.c和bh1750.h
移植链接如下:
提取码: hm83
(2)main.c中添加
#include "bh1750.h"
int Light = 0;//添加全局变量光照值
int main(void)
{
BH1750_Init();//函数初始化
while(1)
{
if (!i2c_CheckDevice(BH1750_Addr)) //光照值传感器获取数据
{
Light = LIght_Intensity();
}
}
}
(1)Beep.c(初始化PA0端口)
#include "beep.h"
//BEEP IO初始化
void BEEP_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //BEEP-->PA.0 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHZ
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA.0
GPIO_SetBits(GPIOA,GPIO_Pin_0); //PA.0 初始化为高电平
}
(2)Beep.h
#ifndef __BEEP_H
#define __BEEP_H
#include "sys.h"
#define BEEP PAout(0) // PA0
void BEEP_Init(void);//初始化
#endif
(3)main.c
#include "beep.h"
#include "timer.h" //中断函数头文件
#include "onenet.h"//阿里云数据发布和接受头文件
#include "delay.h" //延迟函数
int main(void)
{
u8 alarmFlag = 0; //是否报警的标志
BEEP_Init();//蜂鸣器初始化
TIM3_Int_Init(2499,7199);//TIM3中断函数
//蜂鸣器提示接入成功
BEEP = 0;
delay_ms(250);
BEEP = 1;
if((humidityH < 80)&&(temperatureH < 30) && (Light < 2000))
alarmFlag = 0;
else alarmFlag = 1;//如果温湿度光照值超过阈值,蜂鸣器报警(中断3)
}
(4)timer.c(中断)
#include "timer.h"
#include "stdio.h"
extern u8 alarmFlag;//是否报警标志
//通用定时器中断初始化
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到5000为500ms
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMX时钟频率除数的预分频值 10khz的技术频率
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS=TCK_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct重指定的参数初始化TIMX的时间基数单位
TIM_ITConfig( //使能或者失能指定的TIM中断
TIM3, //TIM3
TIM_IT_Update ,
ENABLE //使能
);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIMX外设
}
void TIM3_IRQHandler(void) //TIM3中断
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM中断源
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMX的中断处理位:TIM中断源
if(alarmFlag)//如果alarmFlag=1就执行报警
{
BEEP=0;
}
else
{
BEEP=1;
}
}
}
(1)oled.c与oled.h
移植地址:[正点原子OLED]:http://www.openedv.com/docs/modules/lcd/0.96-OLED-12864.html
(2)main.c
#include "oled.h"
#include "timer.h"
#include "delay.h"
extern char oledBuf[20];
int main(void)
{
OLED_Init(); //OLED初始化
OLED_ColorTurn(0); //0正常显示,1反色显示
OLED_DisplayTurn(0); //0正常显示,1屏幕翻转显示
OLED_Clear();
TIM2_Int_Init(2499,7199);//定时器中断2
}
(3)timer.c
#include "timer.h"
#include "stdio.h"
char oledBuf[20];
extern u8 humidityH;
extern u8 humidityL;
extern u8 temperatureH;
extern u8 temperatureL;
extern int Light; //光照值
//通用定时器中断初始化
void TIM2_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到5000为500ms
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMX时钟频率除数的预分频值 10khz的技术频率
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS=TCK_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct重指定的参数初始化TIMX的时间基数单位
TIM_ITConfig( //使能或者失能指定的TIM中断
TIM2, //TIM2
TIM_IT_Update ,
ENABLE //使能
);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
TIM_Cmd(TIM2, ENABLE); //使能TIMX外设
}
void TIM2_IRQHandler(void) //TIM2中断
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM中断源´
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update ); //清除TIMX的中断处理位:TIM中断源
sprintf(oledBuf,"Welcome");
OLED_ShowString(32,0,(u8*)oledBuf,16);//8*16 "ABC"
sprintf(oledBuf,"wendu:%d.%d %%",humidityH,humidityL);
OLED_ShowString(0,16,(u8*)oledBuf,16);//8*16 "ABC"
sprintf(oledBuf,"shidu:%d.%d C",temperatureH,temperatureL);
OLED_ShowString(0,32,(u8*)oledBuf,16);//8*16 "ABC"
sprintf(oledBuf,"Light:%d Lx",Light);
OLED_ShowString(0,48,(u8*)oledBuf,16);//8*16 "ABC"
OLED_Refresh();
}
}
(1)led.c
#include "led.h"
//初始化PA1、PC13为输出口,并使能这三个口的时钟
//LEDIO口初始化
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC, ENABLE); //使能PA端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //LED2-->PA1端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHZ
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA.1
GPIO_SetBits(GPIOA,GPIO_Pin_1);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //PC13端口配置
GPIO_Init(GPIOC, &GPIO_InitStructure); //推挽输出,IO口速度为50MHZ
GPIO_SetBits(GPIOC,GPIO_Pin_13); //PC.13输出高
}
(2)led.h
#ifndef __LED_H
#define __LED_H
#include "sys.h"
#define LED2 PAout(1) // PA1
#define LED1 PCout(13) // PC13
void LED_Init(void);//初始化
#endif
(3)main.c
#include "led.h"
int main(void)
{
LED_Init(); //LED初始化
}
(1)esp8266.c
[程序移植地址]:http://www.openedv.com/docs/modules/iot/atk-esp.html?highlight=esp8266
做如下修改:
#define WIFI_SSID "nova4" // WIFI密码名称,必须为2.4G,名称中不能含有空格、中文
#define WIFI_PSWD "66666666"//WIFI密码
#define SERVER_HOST "broker.emqx.io" // MQTT服务器域名或IP
#define SERVER_PORT "1883" // MQTT服务器端口
#define ESP8266_WIFI_INFO "AT+CWJAP=\"" WIFI_SSID "\",\"" WIFI_PSWD "\"\r\n"//WIFI配置
#define ESP8266_ONENET_INFO "AT+CIPSTART=\"TCP\",\"a1aFm68O8XC.iot-as-mqtt.cn-shanghai.aliyuncs.com\",1883\r\n" //阿里云连接域名及端口号
unsigned char esp8266_buf[256];
unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;
extern u8 ESP8266_INIT_OK;
在void ESP8266_Init(void)函数中添加8266复位指令:
由于STM32再重新烧录程序后会自动进行复位操作,然而ESP8266不会复位,此前处于连接状态,烧录后再次连接则会出现问题,无法连接,故必须先进行复位操作。
ESP8266_SendCmd("AT+RST\r\n","");
delay_ms(500);
ESP8266_SendCmd("AT+CIPCLOSE\r\n","");
delay_ms(500);
Mqttkit.c的源码移植于如下链接:
提取码:l00d
https://pan.baidu.com/s/1x4HmJWm-JkJkEftLBHs72g
char PUB_BUF[256]; //上传数据的BUF
const char *devSubTopic[] ={"/a1aFm68O8XC/home/user/get"}; //订阅主题
const char devPubTopic[] = "/a1aFm68O8XC/home/user/update/error"; //发布主题
u8 ESP8266_INIT_OK = 0; //ESP8266初始化完成标志
int main(void)
{
unsigned short timeCount = 0;//发送间隔变量
Usart1_Init(115200); //串口初始化
ESP8266_Init(); //ESP8266初始化
while(OneNet_DevLink())
{ //接入阿里云
delay_ms(500);
}
BEEP = 0; //蜂鸣器提示连接成功
delay_ms(250);
BEEP = 1;
OneNet_Subscribe(devSubTopic, 1); //订阅主题
}
在onenet.c中修改自己相应的三元组
#define PROID "home&a1aFm68O8XC" //Username
#define AUTH_INFO "9c54332a63ea97a799d94844f38d5617e4ba46b8628453b1aa1cf7e01abc01cc" //Password
#define DEVID "a1aFm68O8XC.home|securemode=2,signmethod=hmacsha256,timestamp=1660806540188|" //ClientId
while(1)
{
if(timeCount % 40 == 0) //1000ms/25=40 一秒执行一次
{
DHT11_Read_Data(&humidityH,&humidityL,&temperatureH,&temperatureL); //获取温湿度数据
if (!i2c_CheckDevice(BH1750_Addr)) //获取光照值数据
{
Light = LIght_Intensity();
}
Led_Status = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1);//读取PA1端口(小风扇的状态)
/********** 报警逻辑 **************/
if((humidityH < 80)&&(temperatureH < 30) && (Light < 2000))alarmFlag = 0;
else alarmFlag = 1; //其中之一超过阈值即报警
/**********串口输出调试信息**************/
DEBUG_LOG(" | 温度 %d.%d d | 湿度 %d.%d %% | 光照值 %d lx |小风扇 %s | 报警器 %s |",temperatureH,temperatureL,humidityH,humidityL,Light,Led_Status?"关闭":"启动",alarmFlag?"启动":"停止");//此处用了条件运算符(Exp1 ? Exp2 : Exp3),Exp1为真,则返回Exp2,否则返回Exp3
}
/***************上传发布数据**************/
if(++timeCount >= 200) //5000ms/25=200 每五秒上传一次数据
{
Led_Status = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1);//读取PA1端口(小风扇的状态)
DEBUG_LOG("====================================================================");
DEBUG_LOG("发布数据 ----- aliyun_Publish");
sprintf(PUB_BUF,"{\"Temp\":%d,\"Hum\":%d,\"Light\":%d,\"Led\":%d,\"Beep\":%d}"
,temperatureH,humidityH,Light,Led_Status?0:1,alarmFlag);//缓存数据
OneNet_Publish(devPubTopic, PUB_BUF); //发布消息上传数据
DEBUG_LOG("====================================================================");
timeCount = 0;
ESP8266_Clear(); //清空缓存
}
#include "onenet.h"
int main(void)
{
dataPtr = ESP8266_GetIPD(3); //获取下发数据
if(dataPtr != NULL) //若收到数据,开始进行数据处理--->数据解析
OneNet_RevPro(dataPtr);
delay_ms(10);
}
void OneNet_RevPro(unsigned char *cmd)
{
MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0}; //协议包
char *req_payload = NULL; //消息体
char *cmdid_topic = NULL; //主题topic
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,*json_value2; //用来存放解析的数据
type = MQTT_UnPacketRecv(cmd);
switch(type)
{
case MQTT_PKT_PUBLISH: //阿里云向设备发送的消息类型属于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); //对消息体进行c.json解析
}
if (!json)
UsartPrintf(USART_DEBUG,"Error before: [%s]\n",cJSON_GetErrorPtr());//解析失败,打印错误提示
else//解析成功
{
json_value = cJSON_GetObjectItem(json , "Led"); //解析消息体中的"Led",使json_value来存放"Led"的真值
if(!json_value);
else//解析"Led"成功
{
if(json_value->valueint) //若json_value为整型且大于0
LED2 = 0; //LED2点亮,代表小风扇启动(PA1输出低电平)
else
LED2 = 1; //LED2熄灭,代表小风扇关闭(PA1输出高电平)
}
json_value2 = cJSON_GetObjectItem(json , "Beep");//解析消息体中的"Beep",使json_value2来存放"Led"的value值
if(!json_value2) ;//解析失败
else//解析成功
{
if(json_value2->valueint) alarmFlag=1; //是否警报标志alarmFlag为1,则打开蜂鸣器报警
else {
alarmFlag=0;
}
}
cJSON_Delete(json); //删包(不然会导致缓存不足,无法继续运行)
MQTT_DeleteBuffer(&mqttPacket);
}
break;
存在的问题:
由于我使用的是自定义主题,其消息格式为{“Led”:value,“Beep”:value},故只需要解析一层;如果使用物模型主题,存在嵌套解析的问题,此处需要注意!至于如何进行嵌套解析,请百度搜索,此处不过多阐述。当使用自定义topic时,不能使用阿里云提供的物理模型,只能自定义数据结构的类型,可以使消息体的数据结构变得更加简洁,更加方便地进行Json数据解析,因此我的程序在接下来都将使用自定义topic进行数据通信
设备一(home) 订阅:/a1aFm68O8XC/home/user/get 发布:/a1aFm68O8XC/home/user/update/error
设备二(weixin) 订阅:/a1aFm68O8XC/weixin/user/get 发布:/a1aFm68O8XC/weixin/user/update/error
微信小程序使用老师提供的模板,并参考CSDN博主Stdonald对其进行开发和修改。
页面效果图如下:
当进入小程序页面后,会自动与阿里云服务器连接,并提示连接成功,此时就可以读取上传至云平台经云流转后的温湿度以及光照值信息,并且也可以实现指令的下发。所有的操作都会在数据面板显示相应的提示信息。
微信端的程序设计:index.js
aliyunInfo:
{
productKey: 'a1aFm68O8XC', //阿里云连接的三元组 ,请自己替代为自己的产品信息!!
deviceName: 'weixin', //阿里云连接的三元组 ,请自己替代为自己的产品信息!!
deviceSecret: 'dd51bbc32a9b397e4f7ac2e40fa4323b', //阿里云连接的三元组 ,请自己替代为自己的产品信息!!
regionId: 'cn-shanghai', //阿里云连接的三元组 ,请自己替代为自己的产品信息!!
pubTopic: '/a1aFm68O8XC/weixin/user/update/error', //发布消息的主题
subTopic: '/a1aFm68O8XC/weixin/user/get', //订阅消息的主题
},
that.data.client.on("message", function (topic, payload)
{
console.log(" 收到 topic:" + topic + " , payload :" + payload)
let json_payload = JSON.parse(payload)
if (payload.indexOf("Temp") !== -1) { //温度 湿度 光照值
console.log("温度 " + json_payload.Temp)
that.setData({
temp: json_payload.Temp,
})
}
if (payload.indexOf("Hum") !== -1){
console.log("湿度 " + json_payload.Hum)
that.setData({
humi: json_payload.Hum,
})
}
if (payload.indexOf("Light") !== -1){
console.log("光照值 " + json_payload.Light)
that.setData({
light: json_payload.Light,
})
}
if (payload.indexOf("Led") !== -1) { //小风扇状态
console.log("小风扇 " + json_payload.Led)
that.setData({
light_status1: json_payload.Led,
})
}
if (payload.indexOf("Beep") !== -1) { //报警器状态
console.log("报警器 " + json_payload.Beep)
that.setData({
light_status2: json_payload.Beep,
})
}
onClickOpen1()
{
that.sendCommond(1, 'light1');
},
sendCommond(data, light) {
let sendData = null;
if (light === 'light1') {
console.log(1)
sendData =
{
"Led": data,
};
}
<!-- button -->
<view class="button_wrap">
<view class="button1">
<button class="button1_open" type="primary" size="mini" bindtap="onClickOpen1">开小风扇</button>
<button class="button1_close" type="warn" size="mini" bindtap="onClickOff1">关小风扇</button>
<text class="button1_text">状态:</text>
<switch class="button1_state" checked="{{light_status1}}" disabled/>
</view>
<view class="button2">
<button class="button2_open" type="primary" size="mini" bindtap="onClickOpen2">开报警器</button>
<button class="button2_close" type="warn" size="mini" bindtap="onClickOff2">关报警器</button>
<text class="button2_text">状态:</text>
<switch class="button2_state" checked="{{light_status2}}" disabled/>
</view>
</view>
<!-- temp humi -->
<view class="temp_humi_wrap">
<view class="temp_wrap">
<text class="temp_tag">温度:</text>
<text class="temp_value">{{temp}}</text>
</view>
<view class="humi_wrap">
<text class="humi_tag">湿度:</text>
<text class="humi_value">{{humi}}</text>
</view>
<view class="temp_wrap">
<text class="humi_tag">光照值:</text>
<text class="humi_value">{{light}}</text>
</view>
</view>
会报连接错误,无法下载。
解决方法:
然后打开旁边的Settings,添加如下图所示,其次返回点击OK退出。连接上ST-LINK点击Download进行下载即可。
分析:应该是设备端对数据包的接收和解析部分出现了问题
解决方法:
由于模板文件其发布接收消息的主题为自定义主题,消息体较为简单,故设置的缓存消息的BUF为128,然而如果使用平台的物模型主题格式,缓存消息的BUF太小,导致无法正常接收和处理下发消息,故做如下修改:
(1)在esp8266.c中将esp8266_buf由128改为256;
(2)在startup_stm32f103x_md.c中将Stack_Size EQU改为0X00000800;
问题分析: