admin管理员组

文章数量:1794759

自制APP连接OneNET

自制APP连接OneNET

文章目录
  • 前言
  • 一、前期准备
  • 二、功能介绍
    • 1、自制APP页面展示
    • 2、串口助手界面
    • 3、OneNET平台显示
  • 三、单片机端功能实现
    • 1、修改OneNET官方提供的例程
    • 2、主函数代码
    • 3、上传数据到APP
    • 4、命令处理
  • 四、APP端功能实现
    • 1、连接MQTT服务器
    • 2、实现订阅与发布
    • 3、APP显示数据
    • 4、APP下发命令
  • 总结


前言

本案例主要实现的功能是自制手机APP连接OneNET的MQTT服务器,同时接收和显示单片机的数据,对单片机上LED灯进行远程控制。 虽说OneNET上有应用管理,可以实现手机端控制单片机,但是这样做有点简单,达不到毕设水平,课设勉强可以及格。如果是自己做一款APP来控制单片机,顿时高大上很多。


一、前期准备

1、STM32F103C8T6最小系统板 2、ESP8266-01S模块 3、在OneNET平台上创建MQTT协议的产品和创建两个设备 4、安装E4A软件,软件不大几百兆下载链接

二、功能介绍 1、自制APP页面展示

由于是连接OneNET的MQTT服务器,故地址端口是固定不变的。 产品ID、设备ID、鉴权信可以在OneNET平台上获取,这个不必多说。 订阅按钮:订阅主题为EndTopic的主题 发布按钮:发布主题为AppToic的消,消内容是123456 三个绿色框分别是光照值、温度值、湿度值。这里的温湿度做了自增处理,不是实际温湿度。 第一个开关:发布主题为AppToic的消,消内容是KEY:1或KEY:0 第二个开关:发布主题为AppToic的消,消内容是LED1:1或LED1:0

2、串口助手界面

1、EndTopic是单片机端发布消的主题 2、{“Light”:152.7,“Temp”:104,“Humi”:104}是消的内容 3、AppTopic是来自APP端发布的消主题 4、KEY:1是消内容

3、OneNET平台显示

APP端和单片机端的设备都显示在线。

三、单片机端功能实现 1、修改OneNET官方提供的例程

(1)将芯片型号由原先的STM32F103RC更改为STM32F103C8 (2)在全局宏定义中将STM32F10X_HD更改为STM32F10X_MD (3)将原先的startup_stm32f10x_hd.s的启动文件移除,添加startup_stm32f10x_md.s的 启动文件 (4)在stm32f10x.h文件中,将HSE_VALUE宏的值由原先的12M改为8M (5)在onenet.c文件上方的三个宏定义分别填入连接平台的三要素 (6)在esp8266.c中,定义了系统需要连接热点名称和密码 (7)从其他例程中移植OneNet_SendData();函数 (8)移植传感器采集数据和LED(PC13)的初始化代码

2、主函数代码 int main(void) { unsigned short timeCount = 0; //发送间隔变量 unsigned char *dataPtr = NULL; Hardware_Init(); //初始化外围硬件 ESP8266_Init(); //初始化ESP8266 while(OneNet_DevLink()) //接入OneNET DelayXms(500); Beep_Set(BEEP_ON); //鸣叫提示接入成功 DelayXms(250); Beep_Set(BEEP_OFF); OneNet_Subscribe(SubTopics, 1); while(1) { if(++timeCount >= 300) //发送间隔3s { //UsartPrintf(USART_DEBUG, "OneNet_Publish\\r\\n"); light = LIght_Intensity(); //读取光照强度的值 //可以在这读取温湿度值 OneNet_SendData();//发送数据到手机APP timeCount = 0; ESP8266_Clear(); } dataPtr = ESP8266_GetIPD(0); if(dataPtr != NULL) OneNet_RevPro(dataPtr); //下发命令处理 DelayXms(10); } } 3、上传数据到APP

上传数据相关代码如下:

void OneNet_SendData(void) { char buf[256]; memset(buf, 0, sizeof(buf)); OneNet_FillBuf(buf); //封装数据流 //ESP8266_SendData((unsigned char *)buf, strlen(buf)); //上传数据 OneNet_Publish(PubTopics, buf); //发布消 }

数据封装函数 这个函数的功能是将需要上传的数据打包成JSON格式。

extern u8 temp,humi; extern float light; extern const char PubTopics[] ; //发布主题 unsigned char OneNet_FillBuf(char *buf) { char text[16]; memset(text, 0, sizeof(text)); strcpy(buf, "{"); memset(text, 0, sizeof(text)); sprintf(text, "\\"Light\\":%.1f,",light); strcat(buf, text); memset(text, 0, sizeof(text)); sprintf(text, "\\"Temp\\":%d,", temp++); strcat(buf, text); memset(text, 0, sizeof(text)); sprintf(text, "\\"Humi\\":%d", humi++); strcat(buf, text); strcat(buf, "}"); return strlen(buf); } 4、命令处理

当接收到来自APP端下发的命令后,会调用下发命令处理函数OneNet_RevPro(),在该函数内根据消内容对单片机进行控制。 函数内部的部分代码如下:

dataPtr = strchr(req_payload, ':'); //搜索':' if(dataPtr != NULL && result != -1) //如果找到了 { dataPtr++; while(*dataPtr >= '0' && *dataPtr <= '9') //判断是否是下发的命令控制数据 { numBuf[num++] = *dataPtr++; } num = atoi((const char *)numBuf); //转为数值形式 if(strstr((char *)req_payload, "LED1")) //搜索"LED1" { UsartPrintf(USART_DEBUG,"LED1 = %d\\r\\n", num); //num就是LED1:V 中V的值 LED1 = !num; //控制LED灯,低电平点亮 } else if(strstr((char *)req_payload, "KEY")) //搜索"KEY" { UsartPrintf(USART_DEBUG,"KEY = %d\\r\\n", num); } //继续else if添加其他命令 } 四、APP端功能实现

这部分主要讲如何制作手机APP连接OneNET平台,并且获取数据和下发命令控制LED灯。APP是使用E4A中文安卓编程开发的,编程思维和C语言很相似,并且是中文编程,只需一天就能基本掌握。

1、连接MQTT服务器

接入云平台主要依靠的是E4A上面的mqtt通讯组件,这个组件命令有八个方法,七个事件。从单片机编程的角度来看,方法相当于函数,可以人为的去调用,事件相当于中断,不需人为调用。而连接OneNET的MQTT服务器就使用了连接服务器方法。 连接服务器方法的调用需要传入七个参数,参数一是服务器地址端口,即OneNET的MQTT服务器地址和端口;参数二填入产品ID;参数三填入鉴权信;参数四填入设备ID;通过点击连接按钮,就可以调用连接服务器方法,实现接入云平台的功能。

事件 连接按钮.被单击() 如果 连接按钮.标题 = "连接" 则 ' 产品ID框.内容为空会闪退 连接按钮.标题 = "断开" mqtt通讯1.连接服务器(地址端口框.内容,产品ID框.内容,鉴权信框.内容,设备ID框.内容,真,假,5) 否则 连接按钮.标题 = "连接" mqtt通讯1.断开连接() 结束 如果 结束 事件 2、实现订阅与发布

订阅和发布分别使用mqtt通讯组件中的订阅消和发布消的方法,通过对应的按钮单击事件分别调用这两个方法。 订阅与发布程序编写如下所示。

事件 订阅按钮.被单击() mqtt通讯1.订阅消(订阅主题框.内容,0) 结束 事件 事件 发布按钮.被单击() mqtt通讯1.发送消(发布主题框.内容,文本到字节(发布消框.内容,"UTF-8"),1,真) 结束 事件

订阅消方法的调用要传入两个参数,参数一是订阅的主题,为了接收单片机端发布的主题消,这里订阅的是“EndTopic”;参数二是消策略,可以填入0、1、2,这里填入0,表示只会发送一次推送消,收不收都不关心,这是因为单片机端会多次发布主题消,故不需要每次都要接收到。 发布消方法的调用要传入四个参数,参数一是消主题,这里填“AppTopic”;参数二是消内容,参数三是消策略,这里填入1

3、APP显示数据

由于单片机端发布的消不只有光照值,还有温湿度等内容,为了方便解读出数据,在单片机端将这些数据打包为JSON格式,然后再发布出去。 当APP端收到消后,就会触发mqtt通讯里面的收到消事件,在这事件里面,我们利用E4A中的JSON操作组件对消内容进行解析,将解析处理的内容存放在JSON对象里面,然后使用JSON操作组件里面的取文本值方法获取JSON对象里指定数据成员的值,最后将这个值赋值给对应的显示标签。 收到消事件程序编写如下所示

事件 mqtt通讯1.收到消(消主题 为 文本型, 消内容 为 字节型(), 消策略 为 整数型) 接收框.内容 = 接收框.内容 & "\\n" & "主题:" & 消主题 & "\\n内容:" & 字节到文本(消内容,"UTF-8") & "\\n策略:" & 消策略 接收框.置光标位置(取文本长度(接收框.内容)) '开始json解析 变量 JSON对象 为 对象 JSON对象 = JSON操作1.解析(字节到文本(消内容,"UTF-8")) 调试输出("JSON成员数:" & JSON操作1.取成员数(JSON对象)) 光照值标签.标题 = "Light:" & JSON操作1.取文本值(JSON对象 , "Light") 温度值标签.标题 = "Temp:" & JSON操作1.取文本值(JSON对象 , "Temp") 湿度值标签.标题 = "Humi:" & JSON操作1.取文本值(JSON对象 , "Humi") 结束 事件 4、APP下发命令

这里以灯光开关的控制为例子,其他控制功能类似。灯光开关组件状态被改变事件程序如下所示。

事件 开灯按钮.被单击() 如果 连接按钮.标题 = "连接" 则 '未连接时退出事件 退出 结束 如果 如果 开灯按钮.标题 = "开灯" 则 开灯按钮.标题 = "关灯" mqtt通讯1.发送消(发布主题框.内容,文本到字节("LED1:1","UTF-8"),1,真) 否则 开灯按钮.标题 = "开灯" mqtt通讯1.发送消(发布主题框.内容,文本到字节("LED1:0","UTF-8"),1,真) 结束 如果 结束 事件

单片机端接收到由APP端发布出来的消后,会通过消解包函数取出数据包的主题、消内容、消策略,如果消策略是1就先回复Ack给服务器,然后再判断消内容里面有没有程序设计好的命令字符串,如果有就执行相应的程序。


总结

有需要的话,可以问我拿源码,我有空就会回复。 代码下载链接放这里了:github/J-CHUN/OneNET-MQTT-APP.git

本文标签: appOneNET