自己做的網(wǎng)站如何讓別人訪問深圳網(wǎng)站優(yōu)化網(wǎng)站
前言
最近在做一個物聯(lián)網(wǎng)項目,涉及到智能開關(guān)的開發(fā)。目前已經(jīng)實現(xiàn)簡單的TCP通信遠(yuǎn)程控制,但是考慮到后期的設(shè)備管理以及設(shè)備通信所需要的技術(shù)和服務(wù)器的維護(hù)成本,我決定將設(shè)備接入云平臺。本文將詳細(xì)闡述如何利用華為云的物聯(lián)網(wǎng)平臺(IoTDA)實現(xiàn)設(shè)備的云上管理與通信。
前提條件
- 搭建Arduino+ESP8266的開發(fā)環(huán)境。可以參考: 軟件開發(fā)人員從0到1實現(xiàn)物聯(lián)網(wǎng)項目:初步實現(xiàn)智能開關(guān)
- 開通華為云物聯(lián)網(wǎng)平臺服務(wù),并注冊一個設(shè)備。可以參考官網(wǎng)文檔。
準(zhǔn)備工作
設(shè)備側(cè)選擇用MQTT協(xié)議,因為對(IoTDA)SDK的編譯環(huán)境不太了解,這里通過API的方式接入華為云的物聯(lián)網(wǎng)平臺。
獲取IoTDA接入信息
首先需要拿到兩個信息:
-
華為云物聯(lián)網(wǎng)平臺的接入信息,也就是URL和PORT。接入信息通過下圖可以看到。
-
華為云物聯(lián)網(wǎng)平臺的設(shè)備連接鑒權(quán)信息。可以參考設(shè)備連接鑒權(quán) 。簡單來講,就是通過注冊設(shè)備時的設(shè)備ID和密鑰生成設(shè)備連接鑒權(quán)所需的參數(shù)(ClientId、Username、Password)。生成參數(shù)的鏈接
安裝代碼庫
其次,設(shè)備側(cè)作為MQTT的客戶端,需要編寫相關(guān)代碼?;贏rduino IDE開發(fā),可以使用現(xiàn)成的庫減少工作量。
- 安裝
PubSubClient
庫,用于連接和交互MQTT代理服務(wù)器(IoTDA)。 - 安裝
ArduinoJson
庫,用于解析和生成 JSON 數(shù)據(jù)。
功能實現(xiàn)
基于IoTDA平臺實現(xiàn)智能開關(guān),代碼要實現(xiàn)以下功能:
- 設(shè)備進(jìn)行WiFi連接與網(wǎng)絡(luò)通信。
- 設(shè)備通過MQTT協(xié)議接入IoTDA平臺。
- 設(shè)備接收IoTDA平臺下發(fā)的消息。
- 設(shè)備根據(jù)消息執(zhí)行相應(yīng)的控制操作。
WiFi連接
#include <ESP8266WiFi.h> const char* ssid = "xxx"; //wifi名稱
const char* password = "xxx"; //wifi密碼void setup_wifi() { delay(10); // We start by connecting to WiFi Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.print("IP address: "); Serial.println(WiFi.localIP());
}
對以上的代碼進(jìn)行解釋:
ESP8266WiFi.h
庫提供了與 WiFi 網(wǎng)絡(luò)連接相關(guān)的功能,WiFi.begin(ssid, password);
這行代碼就可以自動連接WiFi。
接入IoTDA
設(shè)備要接入IoTDA,就需要上面準(zhǔn)備的接入信息。在代碼中定義如下:
const char* mqttServer = "xxx.myhuaweicloud.com";
const int mqttPort = 1883;
const char* mqttClientId = "xxx";
const char* mqttUser ="xxx";
const char* mqttPassword = "xxx";#define deviceId "xxx"#define mqttTopic "$oc/devices/" deviceId "/sys/messages/down"
mqttTopic
是在接入成功后,設(shè)備側(cè)訂閱的Topic,用來接收平臺下發(fā)的消息。更多的topic定義參考IoTDA平臺預(yù)置的topic。
接下來就需要通過PubSubClient
庫進(jìn)行接入IoTDA平臺了
WiFiClient espClient;
PubSubClient client(espClient); void reconnect() { client.setServer(mqttServer, mqttPort); client.setCallback(callback); while (!client.connected()) { Serial.println("Attempting MQTT connection..."); if (client.connect(mqttClientId, mqttUser, mqttPassword)) { Serial.println("connected"); client.subscribe(mqttTopic); } else { Serial.print(client.state());delay(5000); } }
}
接收IoTDA消息&控制開關(guān)
client.connect
成功后會訂閱Topic,當(dāng)在IoTDA平臺下發(fā)消息時,就會在 callback
函數(shù)進(jìn)行 digitalWrite(RELAY_PIN, state);
控制開關(guān)了。
void callback(char* topic, byte* payload, unsigned int length) { StaticJsonDocument<128> doc; DeserializationError error = deserializeJson(doc, payload); if (error) { Serial.print(F("deserializeJson() failed: ")); Serial.println(error.c_str()); return; } const char* stateKey = "state"; if (doc.containsKey(stateKey)) { bool state = doc[stateKey]; digitalWrite(RELAY_PIN, state); Serial.print("Switch state: "); Serial.println(state ? "ON" : "OFF"); }
}
完整代碼
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h> const char* ssid = "xxx";
const char* password = "xxx.";
const char* mqttServer = "xxx.myhuaweicloud.com";
const int mqttPort = 1883;
const char* mqttClientId = "xxx";
const char* mqttUser ="xxx";
const char* mqttPassword = "xxx";#define RELAY_PIN 0#define deviceId "xxx"#define mqttTopic "$oc/devices/" deviceId "/sys/messages/down"WiFiClient espClient;
PubSubClient client(espClient); void callback(char* topic, byte* payload, unsigned int length) { StaticJsonDocument<128> doc; DeserializationError error = deserializeJson(doc, payload); if (error) { Serial.print(F("deserializeJson() failed: ")); Serial.println(error.c_str()); return; } const char* stateKey = "state"; if (doc.containsKey(stateKey)) { bool state = doc[stateKey]; digitalWrite(RELAY_PIN, state); Serial.print("Switch state: "); Serial.println(state ? "ON" : "OFF"); }
} void reconnect() { while (!client.connected()) { Serial.println("Attempting MQTT connection..."); if (client.connect(mqttClientId, mqttUser, mqttPassword)) { Serial.println("connected"); client.subscribe(mqttTopic); } else { Serial.print(client.state());delay(5000); } }
} void setup_wifi() { delay(10); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.print("IP address: "); Serial.println(WiFi.localIP());
} void setup() { Serial.begin(115200); pinMode(RELAY_PIN, OUTPUT); digitalWrite(RELAY_PIN, HIGH); setup_wifi(); client.setServer(mqttServer, mqttPort); client.setCallback(callback);
} void loop() { if (!client.connected()) { reconnect(); } client.loop();
}
IoTDA平臺下發(fā)消息
將編寫完成的代碼燒錄到ESP-01S模塊后,就可以通過IoTDA平臺進(jìn)行消息下發(fā)了。消息下發(fā)位置見下圖
消息下發(fā)格式:
{"state":true
}
當(dāng)state
為true
時,表示電平狀態(tài)為HIGH
,電路呈開啟狀態(tài),此時電路不通電。
而當(dāng)state
為false
時,電平狀態(tài)則為LOW
,電路閉合,此時電路處于通電狀態(tài)。
通過state
數(shù)值的變化,從而達(dá)到遠(yuǎn)程控制開關(guān)。
問題記錄
在串口調(diào)試時,如果mqtt連接返回-1狀態(tài)碼,意味著連接失敗。
那么需要將 PubSubClient.h
庫中的兩個宏定義MQTT_KEEPALIVE
、MQTT_MAX_PACKET_SIZE
的數(shù)值調(diào)大。本文中的代碼已分別調(diào)整為60和2048。
總結(jié)
借助華為云的物聯(lián)網(wǎng)平臺IoTDA,可以幫助物聯(lián)網(wǎng)行業(yè)的用戶快速完成設(shè)備聯(lián)網(wǎng)及行業(yè)應(yīng)用集成,大大提高了開發(fā)人員的工作效率。而且按需計費每月前一百萬條消息是免費的,很大程度上降低了設(shè)備上云的成本。