前言
由于工作關(guān)系,我接觸到相關(guān)嵌入式開發(fā)睹耐。來公司3年糊探,天天耳濡目染,我覺得自己至少也得寫點嵌入式相關(guān)
目標
實現(xiàn)一個家庭溫濕度計的小工具扣汪。 直接上理想的結(jié)果
配件
esp8266開發(fā)板
溫濕度傳感器
杜邦線
usb線
image.png
淘寶搜一下.
接線
如果你和我的同款断楷,則接線應(yīng)該相同。
傳感器的GND 接 esp8266的GND
傳感器的DATA接 esp8266的 D4
傳感器的VCC 接 esp8266的 3V
image.png
image.png
平臺配置
創(chuàng)建產(chǎn)品
記得選中 密鑰認證
image.png
image.png
定義數(shù)據(jù)模型
image.png
面板設(shè)置
image.png
添加設(shè)備
image.png
用騰訊連連小程序掃描即可崭别。
編碼
編碼的邏輯
1冬筒、先連接wifi
2、再連接mqtt茅主,連接后訂閱消息舞痰,接收控制指令。
3诀姚、不斷檢查時間間隔响牛,時間到了則讀取溫度、濕度赫段。提交數(shù)據(jù)
/**
連接wifi
連接mqtt
讀取溫濕度
DHT11的濕度測量分辨率是1%娃善,溫度測量分辨率是1攝氏度。
*/
#include <SimpleDHT.h>
#include <Arduino_JSON.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <PubSubClient.h>
#ifndef STASSID
#define STASSID "wifi名稱"
#define STAPSK "wifi密碼"
#endif
const char* ssid = STASSID;
const char* password = STAPSK;
/* 產(chǎn)品的三元組信息瑞佩,*/
#define PRODUCT_KEY "產(chǎn)品id"
#define DEVICE_NAME "設(shè)備id"
#define DEVICE_SECRET "設(shè)備密鑰"
/**
mqtt 服務(wù)器信息
*/
#define MQTT_SERVER PRODUCT_KEY".iotcloud.tencentdevices.com"
#define MQTT_PORT 1883
/**
過期時間
2021-11-11 11:09:16
${productid}${devicename};${sdkappid};${connid};${expiry}
11:16:52.842 -> S6UF3TTS5Resp8266living;12010126;fthome;1636600156
*/
#define MQTT_USRNAME PRODUCT_KEY DEVICE_NAME";12010126;fthome;1636600156"
#define MQTT_CLIENT_ID PRODUCT_KEY DEVICE_NAME
/**
密碼規(guī)則
row_key = base64(key)
token = hmacsh1(username,row_key)
4c60988b98fe88af7211ef4baad57efc75d679c1f012100335c798ef566bedda
${token};hmac 簽名方法
*/
#define MQTT_PASSWD "4c60988b98fe88af7211ef4baad57efc75d679c1f012100335c798ef566bedda;hmacsha256"
#define POST_TOPIC "$thing/up/property/" PRODUCT_KEY "/" DEVICE_NAME
#define BODY_FORMAT "{\"method\":\"report\",\"clientToken\":\"msg-id-%d\",\"params\":{\"temperature\":%s,\"humidity\":%s,\"upmin\":%d}}"
#define DOWN_TOPIC "$thing/down/property/" PRODUCT_KEY "/" DEVICE_NAME
/**
設(shè)備對服務(wù)器下發(fā)消息的回應(yīng)
*/
#define REPLY_FORMAT "{\"method\":\"control_reply\",\"clientToken\":\"%s\",\"code\":0,\"status\":\"success\"}"
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
ESP8266WiFiMulti WiFiMulti;
WiFiClient espClient;
PubSubClient client(espClient);
int pinDHT11 = 2;
/**
默認的上報時間
*/
int upmin = 1;
unsigned long lastMs = 0;
SimpleDHT11 dht11(pinDHT11);
void callback(char *topic, byte *payload, unsigned int length)
{
char input[length];
for (int i = 0; i < length; i++) {
//Serial.print((char)payload[i]);
input[i] = (char)payload[i];
}
if (strstr(topic, DOWN_TOPIC))
{
JSONVar myObject = JSON.parse(input);
if (JSON.typeof(myObject) == "undefined")
{
return ;
}
//消息類型
if (myObject.hasOwnProperty("method")) {
Serial.print("myObject[\"method\"] = ");
Serial.println(myObject["method"]);
//是否控制下發(fā)指令
if (strstr(myObject["method"], "control")) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
Serial.println(input);
/**
{
"method": "control",
"clientToken": "clientToken-0a9dc8ef-1b3b-45f0-af55-a10988431f00",
"params": {
"upmin": 1
}
}
*/
//先應(yīng)答
char jsonBuf[128];
sprintf(jsonBuf, REPLY_FORMAT, (const char*)myObject["clientToken"]);
Serial.println(jsonBuf);
boolean d = client.publish(POST_TOPIC, jsonBuf);
if (d) {
Serial.println("reply control msg ok ");
} else {
Serial.println("reply control error ");
}
if (myObject.hasOwnProperty("params")) {
Serial.println(myObject["params"]["upmin"]);
Serial.println(JSON.typeof(myObject["params"]["upmin"]));
if (JSON.typeof(myObject["params"]["upmin"]) == "number") {
upmin = myObject["params"]["upmin"];
}
}
}
}
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect(MQTT_CLIENT_ID, MQTT_USRNAME, MQTT_PASSWD)) {
Serial.println("connected");
// 訂閱消息
client.subscribe(DOWN_TOPIC);
Serial.println("subscribe done");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFiMulti.addAP(ssid, password);
Serial.println();
Serial.println();
Serial.print("Wait for WiFi... ");
while (WiFiMulti.run() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
delay(500);
timeClient.begin();
/**
連接服務(wù)器
*/
client.setServer(MQTT_SERVER, MQTT_PORT);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) {
reconnect();
}
//符合間隔數(shù)據(jù)聚磺,上報一次
if (millis() - lastMs >= upmin * 1000 ) {
lastMs = millis();
Serial.println("start up msg ");
//上報1次。
float temperature = 0.0;
float humidity = 0.0;
int err = SimpleDHTErrSuccess;
if ((err = dht11.read2(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
return;
}
char jsonBuf[128];
int timestamp = millis();
char ts[6] = "";
char hs[6] = "";
dtostrf(temperature, 2, 2, ts);
dtostrf(humidity, 2, 2, hs);
sprintf(jsonBuf, BODY_FORMAT, timestamp, ts, hs,upmin);
boolean d = client.publish(POST_TOPIC, jsonBuf);
if (d) {
Serial.print("up msg ok ");
} else {
Serial.print("up msg error ");
}
}
client.loop();
delay(5000);
}
代碼中的參數(shù)的獲取位置
image.png
注意事項
讀取的溫度和濕度沒有小數(shù)
雖然我代碼寫的是 浮點數(shù)炬丸,但是實際讀取結(jié)果只能整數(shù)瘫寝。這是因為我買的傳感器只支持整數(shù)蜒蕾。精度不夠。騰訊mqtt的文檔地址
https://github.com/tencentyun/qcloud-iot-esp-wifi
其他地方完全看不懂焕阿。尤其其中topic
- Mqtt參數(shù)的密碼問題
密碼我不會代碼生成咪啡,所以選中在線計算。
這里要注意暮屡,記得勾選 我圖中的base64格式密鑰撤摸。
image.png
-
最后的結(jié)果
image.png
image.png
- 后續(xù)