玩转OneNET物联网平台之MQTT服务③ —— 远程控制LED(设备自注册)
授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力。希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石。。。
QQ技术互动交流群:ESP8266&32 物联网开发 群号622368884,不喜勿喷
一、你如果想学基于Arduino的ESP8266开发技术
一、基础篇
二、网络篇
- ESP8266开发之旅 网络篇① 认识一下Arduino Core For ESP8266
- ESP8266开发之旅 网络篇② ESP8266 工作模式与ESP8266WiFi库
- ESP8266开发之旅 网络篇③ Soft-AP——ESP8266WiFiAP库的使用
- ESP8266开发之旅 网络篇④ Station——ESP8266WiFiSTA库的使用
- ESP8266开发之旅 网络篇⑤ Scan WiFi——ESP8266WiFiScan库的使用
- ESP8266开发之旅 网络篇⑥ ESP8266WiFiGeneric——基础库
- ESP8266开发之旅 网络篇⑦ TCP Server & TCP Client
- ESP8266开发之旅 网络篇⑧ SmartConfig——一键配网
- ESP8266开发之旅 网络篇⑨ HttpClient——ESP8266HTTPClient库的使用
- ESP8266开发之旅 网络篇⑩ UDP服务
- ESP8266开发之旅 网络篇⑪ WebServer——ESP8266WebServer库的使用
- ESP8266开发之旅 网络篇⑫ 域名服务——ESP8266mDNS库
- ESP8266开发之旅 网络篇⑬ SPIFFS——ESP8266 Flash文件系统
- ESP8266开发之旅 网络篇⑭ web配网
- ESP8266开发之旅 网络篇⑮ 真正的域名服务——DNSServer
- ESP8266开发之旅 网络篇⑯ 无线更新——OTA固件更新
三、应用篇
四、高级篇
1.理论基础
参考博主线上博文:
- 玩转PubSubClient MQTT库
- 玩转OneNET物联网平台之简介
- 玩转OneNET物联网平台之MQTT服务①
- 玩转OneNET物联网平台之MQTT服务②
在前面的博文中,博主主要通过手动方式去创建设备。这种方式的缺点明显:
- 人为手动控制,对于开发者来说极度不友好;
- 如果设备数量很多,岂不是要手动操作非常多次;
那么,如何实现设备自注册呢?所谓自注册就是设备连入网络后自动往OneNet云平台注册设备信息并获取设备Id。
- 为了区分唯一性,我们采用ESP-Mac地址的组合形式
2.远程控制LED,实现设备自注册
2.1 实验材料
- ESP8266 NodeMcu
- OneNet Mqtt调试工具
- OneNet平台
2.2 实验步骤
2.2.1 创建 ESP8266智能灯系统 产品(MQTT协议)

注意点:
- 务必选择MQTT协议
创建完毕后,我们点击查看具体的产品信息:

注意点:
- 需要记录产品ID,其用来区分产品唯一标识符
- Master-APIkey,网络请求鉴权信息,接口调用需要带入
2.2.2 NodeMcu烧录代码 —— MQTT设备端
为了明确区分代码功能,博哥命名工程名为P_OneNet_Exam04:
- P_OneNet_Exam04.ino文件:
/**
* 功能:ESP8266 Mqtt客户端自注冊功能,订阅OneNet Mqtt工具发过来的控制Led消息
* 作者:单片机菜鸟
* 时间:2019-06-30
* 描述:
* 1.初始化工作:初始化网络配置,Mqtt客户端自注冊,连接鉴权,订阅主题
* 2.订阅消息:获取发送过来的消息(json格式),解析消息,实现控制亮灭灯
*/
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>
#include <EEPROM.h>
#include <Ticker.h>
#include "H_project.h"
#define MAGIC_NUMBER 0xAA
int state;
WiFiClient espClient;
//声明方法
void initSystem();
void initOneNetMqtt();
void callback(char* topic, byte* payload, unsigned int length);
void saveConfig();
void loadConfig();
bool parseRegisterResponse();
/**
* 初始化
*/
void setup() {
initSystem();
initOneNetMqtt();
}
void loop() {
ESP.wdtFeed();
state = connectToOneNetMqtt();
if(state == ONENET_RECONNECT){
//重连成功 需要重新注册
mqttClient.subscribe(TOPIC,1);
mqttClient.loop();
}else if(state == ONENET_CONNECTED){
mqttClient.loop();
}
delay(2000);
}
void initSystem(){
int cnt = 0;
Serial.begin (115200);
Serial.println("\r\n\r\nStart ESP8266 MQTT");
Serial.print("Firmware Version:");
Serial.println(VER);
Serial.print("SDK Version:");
Serial.println(ESP.getSdkVersion());
wifi_station_set_auto_connect(0);//关闭自动连接
ESP.wdtEnable(5000);
WiFi.disconnect();
delay(100);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
cnt++;
Serial.print(".");
if(cnt>=40){
cnt = 0;
//重启系统
delayRestart(1);
}
}
pinMode(LED_BUILTIN, OUTPUT);
loadConfig();
//还没有注册
if(strcmp(config.deviceid,DEFAULT_ID) == 0){
int tryAgain = 0;
while(!registerDeviceToOneNet()){
Serial.print(".");
delay(500);
tryAgain++;
if(tryAgain == 5){
//尝试5次
tryAgain = 0;
//重启系统
delayRestart(1);
}
}
if(!parseRegisterResponse()){
//重启系统
delayRestart(1);
while(1);
}
}
}
void initOneNetMqtt(){
mqttClient.setServer(mqttServer,mqttPort);
mqttClient.setClient(espClient);
mqttClient.setCallback(callback);
initOneNet(PRODUCT_ID,API_KEY,config.deviceid);
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
if ((char)payload[0] == '1') {
digitalWrite(LED_BUILTIN, LOW);
} else {
digitalWrite(LED_BUILTIN, HIGH);
}
}
/*
* 保存参数到EEPROM
*/
void saveConfig()
{
Serial.println("Save OneNet config!");
Serial.print("deviceId:");
Serial.println(config.deviceid);
EEPROM.begin(150);
uint8_t *p = (uint8_t*)(&config);
for (int i = 0; i < sizeof(config); i++)
{
EEPROM.write(i, *(p + i));
}
EEPROM.commit();
}
/*
* 从EEPROM加载参数
*/
void loadConfig()
{
EEPROM.begin(150);
uint8_t *p = (uint8_t*)(&config);
for (int i = 0; i < sizeof(config); i++)
{
*(p + i) = EEPROM.read(i);
}
EEPROM.commit();
if (config.magic != MAGIC_NUMBER)
{
strcpy(config.deviceid, DEFAULT_ID);
config.magic = MAGIC_NUMBER;
saveConfig();
Serial.println("Restore config!");
}
Serial.println("-----Read config-----");
Serial.print("deviceId:");
Serial.println(config.deviceid);
Serial.println("-------------------");
}
/**
* 解析注册返回结果
*/
bool parseRegisterResponse(){
Serial.println("start parseRegisterResponse");
StaticJsonBuffer<200> jsonBuffer;
// StaticJsonBuffer 在栈区分配内存 它也可以被 DynamicJsonBuffer(内存在堆区分配) 代替
// DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(response);
// Test if parsing succeeds.
if (!root.success()) {
Serial.println("parseObject() failed");
return false;
}
int errno = root["errno"];
if(errno !=0){
Serial.println("register failed!");
return false;
}else{
Serial.println("register sucess!");
strcpy(config.deviceid, root["data"]["device_id"]);
saveConfig();
return true;
}
}
- H_project.h 代码:
#ifndef _MAIN_H__
#define _MAIN_H__
extern "C" {
#include "user_interface.h"
#include "smartconfig.h"
}
struct onenet_config
{
char deviceid[15];
uint8_t magic;
};
/************** ESP8266相关操作 **************************/
void delayRestart(float t);
void delayNs(uint8_t m);
/*********************************************************/
/*************** OneNet MQTT相关操作 ****************************/
void initOneNet(uint8_t *productId,uint8_t *apiKey,uint8_t *deviceId);
int connectToOneNetMqtt();
/*********************************************************/
/**************** OneNet Http相关操作 ***************************/
HTTPClient http;
String response;
const char* host = "api.heclouds.com";
bool registerDeviceToOneNet();
/****************************************************************/
#define ONENET_DISCONNECTED 1 //已经断开
#define ONENET_CONNECTED 2 //已经连接上
#define ONENET_RECONNECT 3 //重连成功
//常量
#define VER "MQTT_LED_V1.0"
const char* ssid = "xxxxxxxx";//wifi账号
const char* password = "xxxxxxx";//wifi秘密
//OneNet相关
PubSubClient mqttClient;
const char* mqttServer = "183.230.40.39";//mqtt服务器
const uint16_t mqttPort = 6002;
#define PRODUCT_ID "253190" //此为博哥自己的产品id 请新建自己的
#define API_KEY "aat9ivuJls3gcAFWnLoxfbwW8bI="
#define DEFAULT_ID "123456"
#define TOPIC "esp8266led"
unsigned long lastWiFiCheckTick = 0;
bool ledState = 0;
onenet_config config;
#endif
全部工程代码,博哥放在个人QQ群里。

注意点:
- 这里用到了JSON,请参考博哥上线博文 玩转ArduinoJson库 V5版本;
- 我们这里使用到了ESP8266 HttpClient来封装Http请求;
将工程分别烧进多个NodeMcu(博哥这里烧录了两个),然后可以看到串口打印内容,如下:



同时,也可以在OneNet平台看到设备情况,如下:

接下来就可以通过mqtt调试工具进行远程控制led了。
3.总结
在理解MQTT协议的基础上,本篇是非常容易操作的,但是也需要注意几点:
- 创建自己的OneNet产品,不要用博哥创建的
- 理解订阅主题含义,尝试去使用onenet提供的api接口。
玩转OneNET物联网平台之MQTT服务③ —— 远程控制LED(设备自注册)的更多相关文章
- 玩转OneNET物联网平台之MQTT服务⑦ —— 远程控制LED(数量无限制)+ Android App控制 优化第一版
授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...
- 玩转OneNET物联网平台之MQTT服务④ —— 远程控制LED(设备自注册)+ Android App控制
授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...
- 玩转OneNET物联网平台之MQTT服务② —— 远程控制LED
1.理论基础 参考博主线上博文: 玩转PubSubClient MQTT库 玩转OneNET物联网平台之简介 玩转OneNET物联网平台之MQTT服务① 2.远程控制LED 2.1 实验材料 ...
- 玩转OneNET物联网平台之MQTT服务⑤ —— OneNet智能灯+MVP框架
授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...
- 玩转OneNET物联网平台之MQTT服务① —— OneNetMqtt全方位调试
授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...
- 玩转OneNET物联网平台之HTTP服务③ —— OneNet智能灯 HTTP版本
授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...
- 玩转OneNET物联网平台之HTTP服务① —— 模拟上传温度(TcpClient)
授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...
- 玩转OneNET物联网平台之简介
授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...
- HelloX操作系统与中国移动OneNET物联网平台成功完成对接
HelloX成功与中国移动物联网平台对接 经过HelloX项目组同仁的努力,尤其是Tywin(@飓风)的努力下,HelloX最新版本V1.78已成功与中国移动OneNET(open.iot.10086 ...
随机推荐
- 30 (OC)* 数据结构和算法
在描述算法时通常用o(1), o(n), o(logn), o(nlogn) 来说明时间复杂度 o(1):是最低的时空复杂度,也就是耗时/耗空间与输入数据大小无关,无论输入数据增大多少倍,耗时/耗空间 ...
- .netCore+Vue 搭建的简捷开发框架 (2)--仓储层实现和EFCore 的使用
书接上文,继续搭建我们基于.netCore 的开发框架.首先是我们的项目分层结构. 这个分层结构,是参考张老师的分层结构,但是实际项目中,我没有去实现仓储模型.因为我使用的是EFCore ,最近也一直 ...
- Python3.7.4入门-0/1To Begin/数据类型与结构
0 To Begin //:向下取整除法 **:乘方 在交互模式下,上一次打印出来的表达式被赋值给变量 _ 如果不希望前置了 \ 的字符转义成特殊字符,可以使用 原始字符串 方式,在引号前添加 r 即 ...
- java数据结构——队列、循环队列(Queue)
每天进步一点点,坚持就是成功. 1.队列 /** * 人无完人,如有bug,还请斧正 * 继续学习Java数据结构————队列(列队) * 队列和栈一样,都是使用数组,但是队列多了一个队头,队头访问数 ...
- Hive安装与简单使用并集成SparkSQL
## Hive环境搭建1. hive下载:http://archive-primary.cloudera.com/cdh5/cdh/5/hive-1.1.0-cdh5.7.0.tar.gzwget h ...
- 通过python代码对域名ssl证书进行监控
根据公司要求,要求用zabbix对域名的ssl证书进行到期监控 直接上代码 #!/usr/bin/env python3 from urllib3.contrib import pyopenssl f ...
- ETL-Kettle学习笔记(入门,简介,简单操作)
KETTLE Kettle:简介 ETL:简介 ETL(Extract-Transform-Load的缩写,即数据抽取.转换.装载的过程),对于企业或行业应用来说,我们经常会遇到各种数据的处理,转换, ...
- Spring 梳理-运行时动态注入bean
动态注入的方法 使用占位符 使用Spring表达式
- Spring Boot 简介与入门(2.1.6版)
Spring Boot 2.1.6 版 与时俱进是每一个程序员都应该有的意识,当一个Java程序员在当代遍布的时候,你就该意识到能多学点什么.可观的是后端的框架是稳定的,它们能够维持更久的 ...
- 浅谈MVC&MTV设计模式
在目前基于Python语言的几十个Web开发框架中,几乎所有的全栈框架都强制或引导开发者使用MVC设计模式.所谓全栈框架,是指除了封装网络和线程操作,还提供HTTP.数据库读写管理.HTML模板引擎等 ...