概述
ESP8266端和APP端均提供源码,包含在文章各部分结尾。
先看效果
app端(可远程显示温湿度、控制继电器开关)
ESP8266端:(IO0口控制继电器,IO2口读取温湿度传感器数值)
ESP8266端开发:
一、需要的材料(网上都能买到)
- Esp8266(系列产品,本项目使用ESP8266-01s)
- ESP LINK下载器(TTL也可以)
- DHT11温湿度传感器
- 继电器模块
- 杜邦线若干
二、OneNet平台相关操作
- 进入开发者中心
- 左上角选择全部产品,选择多协议接入,然后创建产品
- 联网方式:WiFi,操作系统:无,协议:MQTT(旧版),网络运营商:全选,其它随便填
- 然后在该产品下添加两个设备,鉴权信息可以随便填,名字可以随便起,我取的是APP和ESP8266
- 程序中需要用到:产品ID,Master-Apikey和设备ID(产品页面有前两个,设备ID可以从设备列表中看到)
三、MQTT简述
MQTT是基于发布/订阅范式的消息协议。你发布了一个Topic,只要别人订阅了这个Topic,那么他就能收到信息。同样你要收到别人发布的消息,首先你要订阅别人。(就好比抖音你关注了某个人,当这个人发布视频的时候,系统就会通知你)。假如说好几个人都订阅了一个Topic,那么这几个人都将收到信息。
四、安装开发环境
在安装开发环境之前,要确保你已经安装了JDK
五、创建项目
- 下载ESP8266 NONOS SDK V3.00
- 解压该压缩包,将driver_lib重命名为app(其它名字也可以)
- 打开根目录下的Makefile,将倒数第三行的driver_lib改为app
- 将examples文件夹中的esp_mqtt_proj中的所有文件复制到app文件加下,并覆盖。
- 打开third_party文件夹下,将Makefile重命名为Makefile.bak,或者直接将third_party这个文件夹删除。
- 给根文件夹重新命一个名字(比如ESP8266_OneNet)
- 将项目导入AiThink_IDE中(该环境当你编译后会显示错误,但并不是真正的错误,只要编译的时候出现第六条图片中类似的地址说明编译成功,官方建议关闭Problems 窗口,因为它的提示信息并不准确,以Console打印出来的信息为准)
- File–>Import—>C/C+±–>Existing Code as Makefile Project点击Finish(直接Browse,上面的名字会自动填充),C++选项去除。
- 找到mqtt_config.h文件,找到下面的代码片段,此时MQTT_HOST后面的ip改为183.230.40.39,MQTT_PORT更改为6002.(这些可以在OneNet开发文档中看到),Device_ID改为设备ID,Device_Name改为产品ID,Device_Passwd改为Master-Apikey(这些都是先前在OneNet创建产品和设备时候的内容),STA_SSID为WIFI名字,STA_PASS为WIFI密码,除此之外还要看onenet平台用的协议版本,协议版本要与平台一致
PROTOCOL_NAMEv311
。 - 还有重要的一个,当你更改了这些内容之后,一定要更改上面的CFG_HOLDER,随便更改几个数字(不改的话设备连接不上平台)。
/***********************************************************************************************************************/
#define CFG_HOLDER 0x00FF55A4 /* Change this value to load default configurations */
/*DEFAULT CONFIGURATIONS*/
#define MQTT_HOST "192.168.1.100" // the IP address or domain name of your MQTT server or MQTT broker ,such as "mqtt.yourdomain.com"
#define MQTT_PORT 1883 // the listening port of your MQTT server or MQTT broker
#define MQTT_CLIENT_ID "Device_ID" // the ID of yourself, any string is OK,client would use this ID register itself to MQTT server
#define MQTT_USER "Device_Name" // your MQTT login name, if MQTT server allow anonymous login,any string is OK, otherwise, please input valid login name which you had registered
#define MQTT_PASS "Device_Passwd" // you MQTT login password, same as above
#define STA_SSID "AP_SSID" // your AP/router SSID to config your device networking
#define STA_PASS "AP_Passwd" // your AP/router password
- 找到根目录下的Makefile文件,将其中的
SPI_SIZE_MAP?=0
改为SPI_SIZE_MAP?=1,但是mqtt的这个项目要是2MB以上,Esp8266-01s只有1MB所以只能改为2.
(如果是32Mbit的Flash改为SPI_SIZE_MAP?=4`). - 此时 ,build project(六程序编译)然后烧录(烧录请跳到七)成功之后,你会看到平台上你的设备已经在线。
- 如何控制开关灯呢?打开user_main.c文件,其中user_init(void)就相当于主函数,你可以按照其中的顺序读写程序。找到如下函数,这个函数就是用来完成订阅和发布的,我们只需要订阅开关灯的Topic,所以要做一下更改。topic名字没有改,用的是原始的,你可以自行更改。
void mqttConnectedCb(uint32_t *args)
{
MQTT_Client* client = (MQTT_Client*)args;
INFO("MQTT: Connectedrn");
MQTT_Subscribe(client, "/mqtt/topic/0", 0);
/* MQTT_Subscribe(client, "/mqtt/topic/1", 1);
MQTT_Subscribe(client, "/mqtt/topic/2", 2);
MQTT_Publish(client, "/mqtt/topic/0", "hello0", 6, 0, 0);
MQTT_Publish(client, "/mqtt/topic/1", "hello1", 6, 1, 0);
MQTT_Publish(client, "/mqtt/topic/2", "hello2", 6, 2, 0);*/
}
- 这样就成功的订阅了一个开关灯的Topic,此时你用模拟器发送一个/mqtt/topic/0的Topic,串口调试助手(第七条)就会打印收到的信息,通过这条信息你就能找到打印此语句的函数,很明显该函数就是完成开关灯指令的地方。就是下面的函数。在仔细看data就是我们收到的Topic的内容。我们只需要判断获取到的内容是啥然后控制IO0口的高低电平就能控制开关灯了。
void mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t data_len)
{
char *topicBuf = (char*)os_zalloc(topic_len+1),
*dataBuf = (char*)os_zalloc(data_len+1);
MQTT_Client* client = (MQTT_Client*)args;
os_memcpy(topicBuf, topic, topic_len);
topicBuf[topic_len] = 0;
os_memcpy(dataBuf, data, data_len);
dataBuf[data_len] = 0;
INFO("Receive topic: %s, data: %s rn", topicBuf, dataBuf);
os_free(topicBuf);
os_free(dataBuf);
}
- 在上面的打印语句( INFO(“Receive topic: %s, data: %s rn”, topicBuf, dataBuf);)之后加上下面的语句就能用来控制继电器从而实现开关灯的功能,除此之外,我们开关灯之后,灯是开是关我们不清楚,在这里我们应该发布一个Topic告诉手机我们的灯已开启或者关闭。
if( os_strcmp(topicBuf,"/mqtt/topic/0") == 0 )
{
if( os_strcmp(dataBuf,"1") == 0 ) // 有效载荷是"LED_ON"
{
//这里开灯的操作
INFO("LED--ON");
GPIO_OUTPUT_SET(GPIO_ID_PIN(0),1);
MQTT_Publish(&mqttClient, "LED_STATUS","1",1, 0, 0);
}
else if( os_strcmp(dataBuf,"0") == 0 ) // 有效载荷 == "LED_OFF"
{
//这里灭灯的操作
INFO("LED--OFF");
GPIO_OUTPUT_SET(GPIO_ID_PIN(0),0);
MQTT_Publish(&mqttClient, "LED_STATUS","0",1, 0, 0);
}
}
- 此时开关灯的功能已经实现,可以自行烧录,用模拟器发布相应的Topic来观察现象。下面就来完成温湿度采集与上传的功能。
- 将dht11.h放在app—>driver文件加下,将dht11.c文件放在user文件夹下。在 user_main.c中引用库文件。并将下面两个函数复制到user_main.c文件中。
#include "driver/dht11.h"
void ICACHE_FLASH_ATTR OS_Timer_1_Init_JX(u32 time_ms, u8 time_repetitive)
{
os_timer_disarm(&OS_Timer_1);
os_timer_setfn(&OS_Timer_1,(os_timer_func_t *)OS_Timer_1_cb, NULL);
os_timer_arm(&OS_Timer_1, time_ms, time_repetitive);
}
void ICACHE_FLASH_ATTR OS_Timer_1_cb(void)
{
DHT11_Data Data;
if(DHT11_Read_Data(&Data,PERIPHS_IO_MUX_GPIO2_U,2) == 0)
{
os_printf("n read ok n");
os_printf("n Humi: %dt Temp: %dn",Data.Humi,Data.Temp);
}
else
os_printf("nntt read failed nn");
}
- 在主函数(user_init(void))中调用下面的函数,第一个参数表示多少ms采集一次
OS_Timer_1_Init_JX(10000,1);
- 此时,再次烧录,你会看到串口中打印的温湿度信息,表明信息已经采集完成,下面就是温湿度的上传了。那么在哪里上传呢?还要保证温湿度每隔一段时间上传一次。很明显在打印温湿度的函数中。也就是上面的 ICACHE_FLASH_ATTR OS_Timer_1_cb(void)这个函数。看一下程序中原始是怎么发布消息的
MQTT_Publish(client, "hellow", "hello1", 6, 1, 0);
- 第一个参数是Client客户端,找找发现程序上面定义了一个全局的Client(MQTT_Client mqttClient),第二个参数是啥?点击ctrl鼠标选中MQTT_PUBLISH,我们会看到如下:说明第二个参数是Topic名称,第三个参数是要发布的内容,第四个参数是内容长度,第五个参数 是Qos,第六个参数是Retain。这几个参数都是干嘛的我们不用管,想了解的点击这里选择MQTT。
MQTT_Publish(MQTT_Client *client, const char* topic, const char* data, int data_length, int qos, int retain)
- 上面说了发布的内容为char*类型,我们可以直接把数据装进插入数组中去一次发布出去。首先全局定义一个char temp_humi[4];前两位用来存放温度的高位和低位,后两位存放湿度的高位和低位。(DHT11的温度范围为0-50℃,湿度范围20-90%RH)。
temp_humi[0]=Data.Temp/10+'0';//除以10获得温度高位,并转化为char型
temp_humi[1]=Data.Temp%10+'0';//对10取模获得个位,也转为char型
temp_humi[2]=Data.Humi/10+'0';
temp_humi[3]=Data.Humi%10+'0';
MQTT_Publish(&mqttClient, "temp_humi",temp_humi,4, 0, 0);
- 到此程序书写就结束了。
六、程序编译
- 选中项目,鼠标右键Build project,如果出现下面的画面就表示编译成功(后面带有烧录地址),编译完就能烧录了。
- Clean Project(清空项目,官方建议在Build Project之前要先Clean Project防止编译出错,我自己实验几次发现并没有错(可能是小概率事件))
- 提醒:Eclipse默认不会自动报存,你每次更改过之后要先保存一下。
七、为ESP8266烧写固件
- 这里选择不支持云端升级的(看自己情况而定)
- 需要烧录四个程序,前两个为程序编译时生成的(就在该项目的文件夹下),后两个在官方提供的ESP NONOS SDK项目的文件夹下,烧录地址如下(前两个地址如果给build project之后不一样,以程序生成的地址为主),同时还要看你的flash的大小,ESP8266-01s为8Mbit(其他型号flash大小可在乐鑫官网查到)。
- 烧写固件用到的软件(第五条连接已经提供了网址,名字为ESP FLASH TOOL)。
- 观察好自己模块的Flash(我的为8Mbit)进行烧写,波特率可以选大一点,烧写速度快。(将下面模块插上烧写)
- 烧写参考图
七、串口调试
- 串口调试助手下载链接
- 选择你所插入的com口,选择波特率115200,打开串口,此时你会看到ESP8266打印的一系列信息(包括一些连接信息,订阅和发布信息,也可以打印出此时从DHT11中读取到的温湿度数据)。
- 此时,你可以使用OneNet平台提供的MQTT设备模拟器来模拟一台设备。模拟器发送ESP8266已经订阅的Topic,观察串口调试助手打印的信息;模拟器也可以订阅ESP8266发布的Topic,观察 模拟器收到的温湿度信息。
- 串口调试助手信息
- 模拟器端(temp_humi为订阅的温湿度Topic,LED_STATUS为执行过开关灯之后返回的灯状态Topic,用来判断开关灯是否成功)
- 此时ESP8266端开发就完成了。
八、Esp8266端源代码,可以导入后改一下信息进行烧写。
APP端开发
一、开发环境(AndroidStudio3.6,可自行百度安装)
二、导入Jar包
- 将Jar包方在你项目下的libs文件夹下
- 右键该文件选择As APP Library
三、AndroidManFest中添加网络权限
<uses-permission android:name="android.permission.INTERNET"/>
四、AndroidManFest的application标签下添加服务
<service android:name="com.chinamobile.iot.onenet.mqtt.MqttService"/>
五、在onCreate()方法中调用init_MQtt()方法连接OneNet
/**
* MQTT连接服务器
*/
private void init_MQtt(){
//初始化sdk
MqttClient.initialize(this,"183.230.40.39",6002,"设备ID","产品ID","Master APIkey");
//设置接受响应回调
MqttClient.getInstance().setCallBack(callBack);
//设置连接属性
MqttConnectOptions connectOptions = new MqttConnectOptions();
connectOptions.setCleanSession(true);
connectOptions.setKeepAlive(121);
connectOptions.setWill(false);
connectOptions.setWillQoS(QoS.AT_MOST_ONCE);
connectOptions.setWillRetain(false);
//建立TCP连接
MqttClient.getInstance().connect(connectOptions);
}
/**
* MQTT回调函数
*/
private MqttCallBack callBack =new MqttCallBack() {
@Override
public void messageArrived(MqttMessage mqttMessage) {
switch (mqttMessage.getMqttHeader().getType()){
case CONNACK:
MqttConnAck mqttConnAck = (MqttConnAck)
break;
case PUBLISH:
break;
case SUBSCRIBE:
MqttSubscribe mqttSubscribe=(MqttSubscribe)mqttMessage;
break;
case SUBACK:
MqttSubAck mqttSubAck = (MqttSubAck) mqttMessage;
break;
case PINGRESP:
break;
case PUBACK:
MqttPubAck mqttPubAck=(MqttPubAck) mqttMessage;
break;
case PUBCOMP:
break;
}
}
@Override
public void connectionLost(Exception e) {
}
@Override
public void disconnect() {
}
};
六、此时手机设备已经连接上OneNet,可以在平台上看到
七、订阅Topic
MqttSubscribe mqttSubscribe = new MqttSubscribe("你要发布的Topic名字", QoS.AT_LEAST_ONCE);
MqttClient.getInstance().subscribe(mqttSubscribe);
八、发布Topic
//data中写入你想要发送的数据
byte[] data = {'1'};
MqttPublish mqttPublish=new MqttPublish("你要发布的Topic名称",data,QoS.AT_LEAST_ONCE);
MqttClient.getInstance().sendMsg(mqttPublish);
九、接收已订阅Topic的信息,在回调函数的相应项下修改
case PUBLISH:
MqttPublish mqttPublish = (MqttPublish) mqttMessage;
byte[] data = mqttPublish.getData();
String topic= mqttPublish.getTopicName();
String s=new String(data);
textview.setText(topic+" "+new String(data));
break;
十、本项目是用两个按键来发布一个Topic,一个的内容为1,另一个为0,ESP8266订阅了这个Topic,接收到1/0表示开/关灯。
手机订阅一个ESP8266发布的温湿度Topic和一个判断灯开关是否成功的Topic(LED_STATUS),实现温湿度在手机端显示和开关灯。
十一、你可以使用MQtt实现多人聊天。
十二、Android源码地址
十三、小白菜一个,大神勿喷,感谢onenet大哥提供的jar包。
最后
以上就是冷酷诺言为你收集整理的ESP8266+OneNet(MQTT)+APP温湿度采集与继电器控制的全部内容,希望文章能够帮你解决ESP8266+OneNet(MQTT)+APP温湿度采集与继电器控制所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复