授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力。希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石。。。

QQ技术互动交流群:ESP8266&32 物联网开发 群号622368884,不喜勿喷

一、你如果想学基于Arduino的ESP8266开发技术

一、基础篇

  1. ESP8266开发之旅 基础篇① 走进ESP8266的世界
  2. ESP8266开发之旅 基础篇② 如何安装ESP8266的Arduino开发环境
  3. ESP8266开发之旅 基础篇③ ESP8266与Arduino的开发说明
  4. ESP8266开发之旅 基础篇④ ESP8266与EEPROM
  5. ESP8266开发之旅 基础篇⑤ ESP8266 SPI通信和I2C通信
  6. ESP8266开发之旅 基础篇⑥ Ticker——ESP8266定时库

二、网络篇

  1. ESP8266开发之旅 网络篇① 认识一下Arduino Core For ESP8266
  2. ESP8266开发之旅 网络篇② ESP8266 工作模式与ESP8266WiFi库
  3. ESP8266开发之旅 网络篇③ Soft-AP——ESP8266WiFiAP库的使用
  4. ESP8266开发之旅 网络篇④ Station——ESP8266WiFiSTA库的使用
  5. ESP8266开发之旅 网络篇⑤ Scan WiFi——ESP8266WiFiScan库的使用
  6. ESP8266开发之旅 网络篇⑥ ESP8266WiFiGeneric——基础库
  7. ESP8266开发之旅 网络篇⑦ TCP Server & TCP Client
  8. ESP8266开发之旅 网络篇⑧ SmartConfig——一键配网
  9. ESP8266开发之旅 网络篇⑨ HttpClient——ESP8266HTTPClient库的使用
  10. ESP8266开发之旅 网络篇⑩ UDP服务
  11. ESP8266开发之旅 网络篇⑪ WebServer——ESP8266WebServer库的使用
  12. ESP8266开发之旅 网络篇⑫ 域名服务——ESP8266mDNS库
  13. ESP8266开发之旅 网络篇⑬ SPIFFS——ESP8266 Flash文件系统
  14. ESP8266开发之旅 网络篇⑭ web配网
  15. ESP8266开发之旅 网络篇⑮ 真正的域名服务——DNSServer
  16. ESP8266开发之旅 网络篇⑯ 无线更新——OTA固件更新

三、应用篇

  1. ESP8266开发之旅 应用篇① 局域网应用 ——炫酷RGB彩灯
  2. ESP8266开发之旅 应用篇② OLED显示天气屏
  3. ESP8266开发之旅 应用篇③ 简易版WiFi小车

四、高级篇

  1. ESP8266开发之旅 进阶篇① 代码优化 —— ESP8266内存管理
  2. ESP8266开发之旅 进阶篇② 闲聊Arduino IDE For ESP8266配置
  3. ESP8266开发之旅 进阶篇③ 闲聊 ESP8266 Flash
  4. ESP8266开发之旅 进阶篇④ 常见问题 —— 解决困扰
  5. ESP8266开发之旅 进阶篇⑤ 代码规范 —— 像写文章一样优美
  6. ESP8266开发之旅 进阶篇⑥ ESP-specific APIs说明

1.理论基础

    参考博主线上博文:

    在前面的博文中,博主主要通过手动方式去创建设备。这种方式的缺点明显:

  • 人为手动控制,对于开发者来说极度不友好;
  • 如果设备数量很多,岂不是要手动操作非常多次;

    那么,如何实现设备自注册呢?所谓自注册就是设备连入网络后自动往OneNet云平台注册设备信息并获取设备Id。

  • 为了区分唯一性,我们采用ESP-Mac地址的组合形式
  • 同时为了操作方便,博主花了个周末的时间做了一个对应的app,理论上不限制ESP8266接入点的数量

    本篇博文的目的就在于教会大家如何和app通信,完成MQTT协议下的App远程控制LED灯,并且LED灯的数量可以随意接入,用户可以在app端修改设备名字以便方便操作。

  • 博主极度建议大家从第一篇看起,有个大概了解,因为本系列教程都是有相联系的

    先上个概念图:

2.远程控制LED,实现设备自注册

2.1 实验材料

  • ESP8266 NodeMcu
  • Android手机
  • OneNet平台

2.2 实验步骤

2.2.1 创建 ESP8266智能灯系统 产品(MQTT协议)

注意点:

  • 务必选择MQTT协议

    创建完毕后,我们点击查看具体的产品信息:

注意点:

  • 需要记录产品ID,其用来区分产品唯一标识符,这个ID待会需要填入App
  • Master-APIkey,网络请求鉴权信息,接口调用需要带入,这个ID待会需要填入App

2.2.2 NodeMcu烧录代码 —— MQTT设备端

    为了明确区分代码功能,博哥命名工程名为P_OneNet_Exam05:

  • P_OneNet_Exam05.ino文件:
/**
 *  功能:ESP8266 Mqtt客户端自注冊功能,通过配套App控制Led消息,理论上可以接入无数个esp8266
 *  作者:单片机菜鸟
 *  时间:2019-10-27
 *  描述:
 *      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 parseOneNetMqttResponse(char* payload);

/**
 * 初始化
 */
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();
  parseOneNetMqttResponse((char *)payload);
}

/*
 * 保存参数到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("-------------------");
}

/**
 * 解析mqtt数据
 */
void parseOneNetMqttResponse(char* payload){
   Serial.println("start parseOneNetMqttResponse");
   StaticJsonBuffer<100> jsonBuffer;
     // StaticJsonBuffer 在栈区分配内存   它也可以被 DynamicJsonBuffer(内存在堆区分配) 代替
     // DynamicJsonBuffer  jsonBuffer;
   JsonObject& root = jsonBuffer.parseObject(payload);

     // Test if parsing succeeds.
   if (!root.success()) {
       Serial.println("parseObject() failed");
       return ;
   }

   String deviceId = root["Did"];
   int status = root["sta"];

   if(strcmp(config.deviceid,deviceId.c_str()) == 0){
        if (status == 1) {
            digitalWrite(LED_BUILTIN, LOW);
        } else {
            digitalWrite(LED_BUILTIN, HIGH);
        }
    }
}

/**
 * 解析注册返回结果
 */
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    "xxxxxx"
#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平台看到设备情况,如下:

    接下来就可以通过App进行远程控制led了。

3.配套android App

3.1 下载App

  • 博主把App放在了个人交流群上以及Github
  • App源码暂不开源,博主也上传到了个人交流群

3.2 配置App

  • 手机App作为一个特殊的设备,需要自行注册一个新的设备,然后填入deviceId,至于如何注册设备,请参考 之前的博文。

3.3 操作App

  • 主页面可以看到当前所有的设备列表(也就是你自注册的所有智能灯),并且标明了设备状态,然后我们就可以远程控制开关灯。

3.4 实验效果



4.总结

需要注意几点:

  • 创建自己的OneNet产品,不要用博哥创建的,不然很容易发生MQTT重连的现象
  • 理论上设备接入数是无限制的,基本上能满足普通需求。

玩转OneNET物联网平台之MQTT服务④ —— 远程控制LED(设备自注册)+ Android App控制的更多相关文章

  1. 玩转OneNET物联网平台之MQTT服务⑦ —— 远程控制LED(数量无限制)+ Android App控制 优化第一版

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  2. 玩转OneNET物联网平台之MQTT服务③ —— 远程控制LED(设备自注册)

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  3. 玩转OneNET物联网平台之MQTT服务② —— 远程控制LED

    1.理论基础     参考博主线上博文: 玩转PubSubClient MQTT库 玩转OneNET物联网平台之简介 玩转OneNET物联网平台之MQTT服务① 2.远程控制LED 2.1 实验材料 ...

  4. 玩转OneNET物联网平台之MQTT服务⑤ —— OneNet智能灯+MVP框架

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  5. 玩转OneNET物联网平台之MQTT服务① —— OneNetMqtt全方位调试

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  6. 玩转OneNET物联网平台之HTTP服务③ —— OneNet智能灯 HTTP版本

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  7. 玩转OneNET物联网平台之HTTP服务① —— 模拟上传温度(TcpClient)

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  8. 玩转OneNET物联网平台之简介

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  9. HelloX操作系统与中国移动OneNET物联网平台成功完成对接

    HelloX成功与中国移动物联网平台对接 经过HelloX项目组同仁的努力,尤其是Tywin(@飓风)的努力下,HelloX最新版本V1.78已成功与中国移动OneNET(open.iot.10086 ...

随机推荐

  1. Alibaba Cloud Toolkit 一键部署插件使用入门

    一.前言 Cloud Toolkit官方介绍文档:https://www.aliyun.com/product/cloudtoolkit Cloud Toolkit 是针对 IDE 平台为开发者提供的 ...

  2. Linux初识之VMWare中Centos7的安装

    Windows平台下VMWare 14安装Centos 7 一.虚拟机硬件配置 1.选择创建新的虚拟机: 2.选择自定义(高级)进行自定义配置,单击下一步: 3.选择虚拟机硬件兼容性为默认,单击下一步 ...

  3. 【linux】【elasticsearch】解决docker pull error pulling image configuration: Get https://d2iks1dkcwqcbx.cloudfront.net/

    网络原因导致的问题: error pulling image configuration: Get https://d2iks1dkcwqcbx.cloudfront.net/docker/regis ...

  4. 【linux】【gitlab】gitlab安装、备份、恢复、升级、内存消耗问题

    前言 GitLab:GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的web服务.功能:Gitlab 是一个提供代码托管.提交审核和问题跟踪的代码管理平 ...

  5. 第六届蓝桥杯java b组第一题

    第一题 三角形面积 图中的所有小方格面积都是1. 那么,图中的三角形面积应该是多少呢? 请填写三角形的面积.不要填写任何多余内容或说明性文字. 填空答案 28 没什么好说的 第一题很水 估计就是为了增 ...

  6. Wordpress设置Pretty Permalink的方法

    设置Wordpress的Pretty Permalink的关键点莫过于下面几点(本文是基于Apache httpd服务器). 1.Apache httpd要有rewrite module 在httpd ...

  7. linux中将video转换成gif

    我使用的机器是Linux mint 17,因为习惯了在linux中开发而有时候在写小demo的时候要带一些演示,虽然可以使用录屏也可以但是视屏演示这些小demo也不是特别的方便.之前一直在linux中 ...

  8. 【ASP.NET基础--MVC】MVC视图基础语法学习

    初步接触.net MVC的视图语法,很多东西都不太熟悉,感觉跟之前的aspx以及html都有一些区别,最近看别人的代码,一边看一边研究,现把学到的东西在这里记录一下,以便日后翻阅. 第一部分:基础知识 ...

  9. 主动降噪技术(ANC)的前生今世–行业分析

    一 原始玩家 1978年,创始人Amar G. Bose博士在从欧洲飞往波士顿的飞机上,发现飞机引擎的噪音扫净了他戴耳机欣赏音乐的兴致.这激发了他在BOSE公司进行一项消噪科技的研究.弹指之间,十年过 ...

  10. ng的显示与隐藏

    显示与隐藏有很多中方法,但是在ng中有自己的显示与隐藏的方法 ng-if 或者[hidden] 在此主要介绍的是[hidden] 在ng中需要摒弃dom操作的方法,使用[hidden] 使用方法: e ...