ESP8266/node MCU网络无线远程烧写(OTA)与MQTT协议配合使用
2017-10-22 18:53
381 查看
序
在Arduino for esp8266中包含一个 OTA的DEMO,但是在使用上有一定的缺陷,首先,每次都要把OTA的代码烧写上去,才能在下次烧写的时候用到OTA。然后OTA代码占据了ESP8266的整条进程,甚至无法再加入自己的一个for循环,这点最为致命。那是不是这段代码根本无法使用呢?方法还是有的,OTA仅仅在烧写的时候有用,在ESP8266上平时可以不运行,只要用一个指令在需要烧写的时候结束其他进程,调出所有CPU资源给OTA进程来实现远程烧写就可以。那怎么触发这个进程呢?当然也可以浪费一个宝贵的引脚使用按键式触发,不过我这里有更好的方法。用esp8266办事情的应该十有八九都会用到MQTT这种协议,所以可以直接通过MQTT发一条JSON数据过去遥控ESP8266使其进入OTA模式即可。
OTA模式下的代码烧写方式:找到网络端口然后最好将上传波特率改为921600(最快)
#include <ArduinoJson.h> #include <ESP8266WiFi.h> #include <ESP8266mDNS.h> #include <WiFiUdp.h> #include <ArduinoOTA.h> #include <ESP8266WiFi.h> #include <PubSubClient.h> const char* ssid = "*******";//路由器ssid const char* password = "*******";//路由器密码 const char* mqtt_server = "********";//服务器的地址 //全局变量区域上界 //全局变量区域下界 WiFiClient espClient; PubSubClient client(espClient); int OTA=0; int OTAS=0; long lastMsg = 0;//存放时间的变量 char msg[200];//存放要发的数据 String load; void setup_wifi() {//自动连WIFI接入网络 delay(10); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); } } void reconnect() {//等待,直到连接上服务器 while (!client.connected()) {//如果没有连接上 int randnum = random(0, 999); if (client.connect("OTADEMO"+randnum)) {//接入时的用户名,尽量取一个很不常用的用户名 client.subscribe("OTAlisten");//接收外来的数据时的intopic } else { Serial.print("failed, rc=");//连接失败 Serial.print(client.state());//重新连接 Serial.println(" try again in 5 seconds");//延时5秒后重新连接 delay(5000); } } } void callback(char* topic, byte* payload, unsigned int length) {//用于接收服务器接收的数据 load=""; for (int i = 0; i < length; i++) { load +=(char)payload[i];//串口打印出接收到的数据 } decodeJson(); } void decodeJson() { DynamicJsonBuffer jsonBuffer; JsonObject& root = jsonBuffer.parseObject(load); OTA = root["OTA"]; OTAS =OTA; //接收数据json处理区上界 //添加其他自己的JSON收听处理方式就像这样 int Activity=root["ACT"]; //接收数据json处理区下界 } void OTAsetup(){ if(OTAS){ ArduinoOTA.onStart([]() { Serial.println("Start"); }); ArduinoOTA.onEnd([]() { Serial.println("\nEnd"); }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }); ArduinoOTA.onError([](ota_error_t error) { Serial.printf("Error[%u]: ", error); if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); else if (error == OTA_END_ERROR) Serial.println("End Failed"); }); ArduinoOTA.begin(); Serial.println("Ready"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); OTAS=0; } } void setup() { //setup代码区域上界 //填写自己的逻辑代码 Serial.begin(9600); //setup代码区域下界 setup_wifi();//自动连WIFI接入网络 client.setServer(mqtt_server, 1883);//1883为端口号 client.setCallback(callback); //用于接收服务器接收的数据 } void loop() { if(OTA){ OTAsetup(); ArduinoOTA.handle(); } else{ reconnect();//确保连上服务器,否则一直等待。 client.loop();//MUC接收数据的主循环函数。 //loop代码上界 //自己的逻辑代码 //loop代码下界 long now = millis();//记录当前时间 if (now - lastMsg > 100) {//每隔100毫秒秒发一次数据 encodeJson(); client.publish("OTAback",msg);//以OTA为TOPIC对外发送MQTT消息 lastMsg = now;//刷新上一次发送数据的时间 } } } void encodeJson(){ DynamicJsonBuffer jsonBuffer; JsonObject& root1 = jsonBuffer.createObject(); //发送数据区上界 //添加其他要发送的JSON包就像这样下面这句代码 root1["back"] = "OTA"; //发送数据区下界 root1.printTo(msg); }
这段代码我已经标注好了loop,setup区域代码添加处,就直接忽略其他杂七杂八的代码,把这两个区域当成一般的loop和setup区域来用即可。当然还有一些其他的区域,比如全局变量定义处,JSON收,发处理的区域等,根据自己的喜好合理利用吧。然后关于MQTT,我这段代码由于是作为DEMO来演示,所以定义esp8266订阅收听的TOPIC为OTAlisten,向外发布的TOPIC为OTAback(当然你可以自由修改),然后你可以用手机订阅OTAback来查看ESP8266发给你的JSON数据包。(demo代码中esp8266返回的应该是{“back”:OTA}字符串)但是当你用手机以OTAlisten发布{“OTA”:1}时,esp8266马上进入OTA待烧写状态,并且不能悔改无法撤销此操作。
几个提示:ArduinoJSON请使用目前最高版本的库,所有库都可以通过Arduino自带的“管理库”功能获得。OTA远程烧写必须在自己的局域网中操作(最简单电脑与esp8266连同一个路由器)。另外如果网络端口迟迟没有跳出,建议先保存你的代码,然后重启Arduino编辑器,还没跳出,建议是时候安装Python环境了,这个功能必须依赖Python.还有如果Esp8266在OTA烧写完的时候迟迟没有进入工作状态,建议按一下板子上的复位键。
关于手机软件 apk安装包:百度盘 http://pan.baidu.com/s/1dEOJHi5
源代码:百度盘 http://pan.baidu.com/s/1hsCc8wW
相关文章推荐
- 使用远程访问和无线网络SSID恢复被盗取笔记本
- 国产优化Linux系统Deepin15.3使用samba配合Xshell5.0搭建在Windows7端SSH远程登录与网络映射驱动器
- 通过改变网络拓扑使用Sniffer Pro监控、分析协议的示意图
- 计算机网络第四次作业——关于无线局域网络协议
- [转]网络协议分析工具Ethereal的使用
- VB自动登陆网络站点详解(二):Inet控件与WebBrowser控件配合使用
- VB自动登陆网络站点详解(二):Inet控件与WebBrowser控件配合使用
- 通过改变网络拓扑使用Sniffer Pro监控、分析协议的示意图
- 通过改变网络拓扑使用Sniffer Pro监控、分析协议的示意图
- 通过改变网络拓扑使用Sniffer Pro监控、分析协议的示意图
- 通过改变网络拓扑使用Sniffer Pro监控、分析协议的示意图
- linux 下无线网络的配置 关键点提示 "加密协议模块"
- 错误信息:通常每个套接字地址(协议/网络地址/端口)只允许使用一次.
- 通过改变网络拓扑使用Sniffer Pro监控、分析协议的示意图
- (OS 10048)通常每个套接字地址(协议/网络地址/端口)只允许使用一次
- 使用协议分析软件查找网络故障慢的原因
- 使用无线网络
- 在vb中使用Iphlpapi.dll获取网络信息 第二章 第七节 获取本机网间控制报文协议(ICMP)信息
- 通过改变网络拓扑使用Sniffer Pro监控、分析协议的示意图
- 解决方法:通常每个套接字地址 (协议/网络地址/端口)只允许使用一次