ESP8266+OneNet(MQTT)+APP温湿度采集与继电器控制

先看效果

app端(可远程显示温湿度、控制继电器开关)
在这里插入图片描述
ESP8266端:(IO0口控制继电器,IO2口读取温湿度传感器数值)在这里插入图片描述

ESP8266端开发:

一、需要的材料(网上都能买到)

  1. Esp8266(系列产品,本项目使用ESP8266-01s)
  2. ESP LINK下载器(TTL也可以)
  3. DHT11温湿度传感器
  4. 继电器模块
  5. 杜邦线若干

二、OneNet平台相关操作

  1. 进入开发者中心
  2. 左上角选择全部产品,选择多协议接入,然后创建产品
  3. 联网方式:WiFi,操作系统:无,协议:MQTT(旧版),网络运营商:全选,其它随便填
  4. 然后在该产品下添加两个设备,鉴权信息可以随便填,名字可以随便起,我取的是APP和ESP8266
  5. 程序中需要用到:产品ID,Master-Apikey和设备ID(产品页面有前两个,设备ID可以从设备列表中看到)

三、MQTT简述
MQTT是基于发布/订阅范式的消息协议。你发布了一个Topic,只要别人订阅了这个Topic,那么他就能收到信息。同样你要收到别人发布的消息,首先你要订阅别人。(就好比抖音你关注了某个人,当这个人发布视频的时候,系统就会通知你)。假如说好几个人都订阅了一个Topic,那么这几个人都将收到信息。

四、安装开发环境
在安装开发环境之前,要确保你已经安装了JDK
五、创建项目

  1. 下载ESP8266 NONOS SDK V3.00
  2. 解压该压缩包,将driver_lib重命名为app(其它名字也可以)
  3. 打开根目录下的Makefile,将倒数第三行的driver_lib改为app
  4. 将examples文件夹中的esp_mqtt_proj复制到app文件加下。
  5. 打开third_party文件夹下,将Makefile重命名为Makefile.bak
  6. 给根文件夹重新命一个名字(比如ESP8266_OneNet)
  7. 将项目导入AiThink_IDE中(该环境当你编译后会显示错误,但并不是真正的错误,只要编译的时候出现第六条图片中类似的地址说明编译成功,官方建议关闭Project 窗口,因为它的提示信息并不准确,以Console打印出来的信息为准)
  8. File–>Import—>C/C+±–>Existing Code as Makefile Project点击Finish(直接Browse,上面的名字会自动填充)。在这里插入图片描述
  9. 找到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密码。
  10. 还有重要的一个,当你更改了这些内容之后,一定要更改上面的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
  1. 此时 ,build project(六程序编译)然后烧录(烧录请跳到七)成功之后,你会看到平台上你的设备已经在线。在这里插入图片描述
  2. 如何控制开关灯呢?打开user_main.c文件,其中user_init(void)就相当于主函数,你可以按照其中的顺序读写程序。找到如下函数,这个函数就是用来完成订阅和发布的,我们只需要订阅开关灯的Topic,所以要做一下更改。topic名字没有改,用的是原始的,你可以自行更改。
void mqttConnectedCb(uint32_t *args)
{
    MQTT_Client* client = (MQTT_Client*)args;
    INFO("MQTT: Connected\r\n");
    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);*/

}
  1. 这样就成功的订阅了一个开关灯的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 \r\n", topicBuf, dataBuf);
    os_free(topicBuf);
    os_free(dataBuf);
}
  1. 在上面的打印语句( INFO(“Receive topic: %s, data: %s \r\n”, 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);
       	}

       }
  1. 此时开关灯的功能已经实现,可以自行烧录,用模拟器发布相应的Topic来观察现象。下面就来完成温湿度采集与上传的功能。
  2. 将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: %d\t Temp: %d\n",Data.Humi,Data.Temp);
			
	}
	else
		os_printf("\n\n\t\t read failed \n\n");
}
  1. 在主函数(user_init(void))中调用下面的函数,第一个参数表示多少ms采集一次
 OS_Timer_1_Init_JX(10000,1);
  1. 此时,再次烧录,你会看到串口中打印的温湿度信息,表明信息已经采集完成,下面就是温湿度的上传了。那么在哪里上传呢?还要保证温湿度每隔一段时间上传一次。很明显在打印温湿度的函数中。也就是上面的 ICACHE_FLASH_ATTR OS_Timer_1_cb(void)这个函数。看一下程序中原始是怎么发布消息的
MQTT_Publish(client, "hellow", "hello1", 6, 1, 0);
  1. 第一个参数是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)
  1. 上面说了发布的内容为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);
  1. 到此程序书写就结束了。

六、程序编译

  1. 选中项目,鼠标右键Build project,如果出现下面的画面就表示编译成功(后面带有烧录地址),编译完就能烧录了。在这里插入图片描述
  2. Clean Project(清空项目,官方建议在Build Project之前要先Clean Project防止编译出错,我自己实验几次发现并没有错(可能是小概率事件))
  3. 提醒:Eclipse默认不会自动报存,你每次更改过之后要先保存一下。

七、为ESP8266烧写固件

  1. 这里选择不支持云端升级的(看自己情况而定)
  2. 需要烧录四个程序,前两个为程序编译时生成的(就在该项目的文件夹下),后两个在官方提供的ESP NONOS SDK项目的文件夹下,烧录地址如下(前两个地址如果给build project之后不一样,以程序生成的地址为主),同时还要看你的flash的大小,ESP8266-01s为8Mbit(其他型号flash大小可在乐鑫官网查到)。在这里插入图片描述
  3. 烧写固件用到的软件(第五条连接已经提供了网址,名字为ESP FLASH TOOL)。
  4. 观察好自己模块的Flash(我的为8Mbit)进行烧写,波特率可以选大一点,烧写速度快。(将下面模块插上烧写)在这里插入图片描述
  5. 烧写参考图
    在这里插入图片描述

七、串口调试

  1. 串口调试助手下载链接
  2. 选择你所插入的com口,选择波特率115200,打开串口,此时你会看到ESP8266打印的一系列信息(包括一些连接信息,订阅和发布信息,也可以打印出此时从DHT11中读取到的温湿度数据)。
  3. 此时,你可以使用OneNet平台提供的MQTT设备模拟器来模拟一台设备。模拟器发送ESP8266已经订阅的Topic,观察串口调试助手打印的信息;模拟器也可以订阅ESP8266发布的Topic,观察 模拟器收到的温湿度信息。
  4. 串口调试助手信息在这里插入图片描述
  5. 模拟器端(temp_humi为订阅的温湿度Topic,LED_STATUS为执行过开关灯之后返回的灯状态Topic,用来判断开关灯是否成功)在这里插入图片描述
  6. 此时ESP8266端开发就完成了。

八、Esp8266端源代码,可以导入后改一下信息进行烧写。

APP端开发

一、开发环境(AndroidStudio3.6,可自行百度安装)
二、导入Jar包

  1. 将Jar包方在你项目下的libs文件夹下
  2. 右键该文件选择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包。

发布了1 篇原创文章 · 获赞 3 · 访问量 173

猜你喜欢

转载自blog.csdn.net/weixin_42181820/article/details/104598932