android+app+wifi+控制+协议,玩转OneNET物联网平台之MQTT服务④ —— 远程控制LED(数量无限制)+ Android App控制...
授人以魚不如授人以漁,目的不是為了教會你具體項目開發,而是學會學習的能力。但愿你們分享給你周邊須要的朋友或者同窗,說不定大神成長之路有博哥的奠定石。。。android
若是以為有用,麻煩點贊收藏,您的支持是博主創做的動力。github
1.理論基礎
參考博主線上博文:web
在前面的博文中,博主主要經過手動方式去建立設備。這種方式的缺點明顯:json
人為手動控制,對于開發者來講極度不友好;
若是設備數量不少,豈不是要手動操做很是屢次;
那么,如何實現設備自注冊呢?所謂自注冊就是設備連入網絡后自動往OneNet云平臺注冊設備信息并獲取設備Id。api
為了區分惟一性,咱們采用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協議)
注意點:app
務必選擇MQTT協議
建立完畢后,咱們點擊查看具體的產品信息:svg
注意點:
須要記錄產品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重連的現象
總結
以上是生活随笔為你收集整理的android+app+wifi+控制+协议,玩转OneNET物联网平台之MQTT服务④ —— 远程控制LED(数量无限制)+ Android App控制...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android获取连接wifi名称,an
- 下一篇: android 优化启动事件,张绍文an