OneNet使用起来要比lewei50复杂一些,它没有前台须要本身开发。命令下发也和以前介绍的lewei50有一些区别,这里着重介绍一下使用MQTT协议来进行通信。缓存
1、准备服务器
一、Esp8266开发板(+烧写器或者直接用WeMos D1 Wifi之类的就不要烧写器了)网络
二、Arduino IDE for VS函数
三、OneNet注册工具
2、OneNet配置测试
OneNet总体结构上与lewei50不一样,它从产品开始下面能够有若干按APIKEY组织的设备群组(实名认证与否决定了能用多少产品和设备),每一个设备下面能够有若干传感器和控制器(测试过程未发现个数限制)。而其中控制器状态是和传感器一块儿上传的,服务器下发的命令以Qos0进行,即不接收回复。更多的内容就请参考开发文档吧。ui
一、进入开发者中心建立产品编码
接入方式选择公开协议,设备接入协议选择MQTT。建立完成后,会获得一个APIKEY,这个APIKEY能够用于访问产品下的任何一个设备。固然,也能够建立一个新的APIKEY,而后设置该APIKEY关联的设备。spa
二、建立设备3d
其中设备名称和鉴权信息都是自定义,鉴权信息与设备ID是通用的,若是想要用MAC进行绑定那这里鉴权信息就填写设备的MAC地址,我就随便填了一个。固然这是与前台相关的内容,不在此讨论。
三、建立数据流模板
数据流名称最好简明,由于须要ESP8266处理的字符不少,而其资源也不是十分充裕。须要主意的是,每个数据流就是一个传感器或控制器。即控制器也在这里建立。建立完成以后就能够把数据流和产品关联起来,为了直观观察,咱们再在“应用管理”里面建立一个简单的应用:
选择这个开关控件,而后在右面除了关联设备数据流以外,设置一下开关开值和开关关值:
其默认值开为1,关为0。这里说明一下该参数在服务器下发命令时如何被解释(以图中的01和00为例):
把每一个数字解释为1字节进行下发,因此上面00被接收到的是{0,0}这样的,它与0彻底不一样。而右面的按钮我设置的开关之分别为十一、10,因此在后面的代码中前一字节被做为分组标志,后一字节被做为开关值。
3、编码
一、IDE和配置
与前一篇同样,这里使用Arduino IDE(实际上我用的是for vs,操做差很少,有代码提示而已)来进行编写。开发板选择NodeMCU1.0(ESP-12E Module),而不论使用的是WeMos D1 Wifi仍是其余8针、IO全引出啥的(估计魔改串口4针的是玩不了的)。其余配置以下:
二、层次逻辑
a、Esp8266wifi.h负责链接WIFI
b、pubsubclient.h负责MQTT通信(可变头和载体须要自定义,该库只负责Fixed header)
c、ArduinoJson.h负责构建载体中数据部分,具体格式请参考OneNet MQTT开发文档
d、eeprom.h负责将配置写到esp8266模块中和读取,这个的写操做与arduino开发板是不一样的
三、主要代码示例
这里主要说一下MQTT部分,其余部分再也不赘述。
a、pubsubclient总述:
WiFiClient wClient;
PubSubClient mClient(mServerAddress,mServerPort, mCallback,wClient);
其中,mCallback是一个回调函数,该函数用于处理服务器发来的消息,其签名以下:
void mCallback(char* topic, byte* payload, unsigned int length)
其中topic是话题,包含了topicName,Payload是实际下发的内容,例如上面的水泵开关开则有2字节:0 1。length指payload字节数。要处理的服务器数据就在该函数处理就能够了,可是最好别太长,不然影响数据的响应速度。
b、链接MQTT服务器
bool ConnectServer() { int waitConst = 0; if (!mClient.connected()) { //id="设备id",user="产品id",pass="APIkey" mClient.connect(DeviceID, ProductID, APIKey); while (!mClient.connected() && waitConst<20) { delay(100); waitConst++; } Serial.println((String)"ConnectServer " + mClient.connected()); } return mClient.connected();// mClient.state() == MQTT_CONNECTED; }
在Onenet开发者页面的说明后面有一段问答,其中明确说明了上面的参数如何传递,上面注释写的很是清楚了;固然也能够用前面提到的设备鉴权信息代替APIKEY字段做为password传入。
c、发布话题
bool PubTopic(String TopicName,String Json) { memset(msg_buf, 0, MQTT_MAX_PACKET_SIZE); //清理MQTT消息缓存 //设置可变头 msg_buf[0] = char(0x03); //包数据格式标志 msg_buf[1] = char(Json.length() >> 8); //高位在后 msg_buf[2] = char(Json.length() & 0xff); //低位在前 //设置数据 memcpy(msg_buf + 3, Json.c_str(), Json.length()); mClient.publish(TopicName.c_str(), (uint8_t*)msg_buf, Json.length() + 3); //设置发送长度以避免中间的00使得自动断定长度出错。 }
可变头部分指明了使用哪一种数据包格式,设置了Json数据长度。这一部分有若干种数据格式,具体参考开发文档,上面代码中使用的type3格式在说明文档中的说明以下:
数据类型3(type == 3)格式说明:
Byte 1 |
数据点类型指示:type=3 // JSON格式2字符串 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
Byte 2 |
//指示后面字符串长度 固定两字节长度高位字节,值为0x00 |
|
|
|
|
|
|
|
|
Byte 3 |
固定两字节长度低位字节,值为0x46 |
|
|
|
|
|
|
|
|
Byte 4 |
通用格式: { “datastream_id1”:”value1”, “datastream_id2”:”value2”, … }
示例: {“temperature”:22.5,”humidity”:”95.2%”} |
|
|
|
|
|
|
|
|
… … … … |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
||
Byte n |
|
|
|
|
|
|
|
|
看的时候无视这没头没尾的0x00、0x46吧。参考代码上面的代码就能够了。其中Json的构建在上一篇中已经说得很是清楚、十分深刻了,完成这个代码构建是基础中的基础了,这里再也不说明。
4、ESP8266的EEPROM
关于这个问题是看乐鑫的开发文档仍是怎么的才能解决提及来没意义,上你们最喜欢的积木:
void SaveConfig(int cfgidx, String val) { //esp8266的EEPROM与Areduino的使用不一样 //一、申请操做缓存 EEPROM.begin(eBlockSize); //二、写入数据 for (int i = 0; i < eBlockSize; i++) { EEPROM.write(cfgidx*eBlockSize + i, val[i]); } //三、保存数据更改 EEPROM.commit(); }
好了,这篇就介绍到这里,也不把OneNet上面建立的这个设备的应用嵌入到这里了,愿意作的本身作一下就能够看到效果了。我这如今就几块开发板,USB已经插了一堆堆各类东西,不可能长期保持这东西在线的。
5、网络调试工具
这个不像以前的一些WIFI应用调试起来那么简单,有时候代码看着貌似都没问题就是不过,而服务器端没有提供底层的数据调试功能,通常的SOCKET调试工具也不提供MQTT服务器,本身架设一个也须要大篇幅的工做。因此具体WIFI发送了什么仍是要一些其余工具。首先,得让数据从电脑上过去咱们才有机会在电脑上下个钩子把数据呈现出来,因而我安了一个随身WIFI,设置好以后,让ESP8266链接它,至于用什么WIFI软件无所谓,根本别期望他们提供底层数据,也没期望去勾它们,那太麻烦了。开发一个新的东西也得不偿失,仍是用专业工具吧,祭出神器winpcap就解决一切了。使用winpcap的网络封包工具不少,其中作的好的也很多,Ethereal就是其中一个,如今可能叫Wireshark。