android http onenet,玩转OneNET物联网平台之MQTT服务④ —— 远程控制LED(设备自注册) Android App控制...

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

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

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

一、基础篇

二、网络篇

三、应用篇

四、高级篇

1.理论基础

参考博主线上博文:

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

人为手动控制,对于开发者来说极度不友好;

如果设备数量很多,岂不是要手动操作非常多次;

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

为了区分唯一性,我们采用ESP-Mac地址的组合形式

同时为了操作方便,博主花了个周末的时间做了一个对应的app,理论上不限制ESP8266接入点的数量

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

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

先上个概念图:

174302224_1_20191028045331221

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

#include

#include

#include

#include

#include

#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,请参考博哥上线博文

我们这里使用到了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重连的现象

理论上设备接入数是无限制的,基本上能满足普通需求。

来源:https://www.icode9.com/content-4-530601.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值