物联网开发实战-家庭温湿度计的实现

前言

由于工作关系,我接触到相关嵌入式开发。来公司3年,天天耳濡目染,我觉得自己至少也得写点嵌入式相关

目标

实现一个家庭温湿度计的小工具。 直接上理想的结果

配件

esp8266开发板
温湿度传感器
杜邦线
usb线

image.png

淘宝搜一下.

接线

如果你和我的同款,则接线应该相同。

传感器的GND 接 esp8266的GND
传感器的DATA接 esp8266的 D4
传感器的VCC 接 esp8266的 3V

image.png
image.png

平台配置

创建产品
记得选中 密钥认证

image.png
image.png

定义数据模型

image.png

面板设置

image.png

添加设备


image.png

用腾讯连连小程序扫描即可。

编码

编码的逻辑
1、先连接wifi
2、再连接mqtt,连接后订阅消息,接收控制指令。
3、不断检查时间间隔,时间到了则读取温度、湿度。提交数据




/**
   连接wifi
   连接mqtt
   读取温湿度
DHT11的湿度测量分辨率是1%,温度测量分辨率是1摄氏度。
*/
#include 
#include 


#include 
#include 
#include 
#include 
#include 



#ifndef STASSID
#define STASSID "wifi名称"
#define STAPSK  "wifi密码"
#endif

const char* ssid     = STASSID;
const char* password = STAPSK;


/* 产品的三元组信息,*/
#define PRODUCT_KEY       "产品id"
#define DEVICE_NAME       "设备id"
#define DEVICE_SECRET     "设备密钥"
/**
   mqtt 服务器信息
*/
#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
/**
   密码规则
   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

/**
   设备对服务器下发消息的回应

*/
#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"]);

      //是否控制下发指令
      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
          }
          }
        */

        //先应答
            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();

  /**
     连接服务器
  */



  client.setServer(MQTT_SERVER, MQTT_PORT);
  client.setCallback(callback);



}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  //符合间隔数据,上报一次
  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);
}

代码中的参数的获取位置

image.png

注意事项

  • 读取的温度和湿度没有小数
    虽然我代码写的是 浮点数,但是实际读取结果只能整数。这是因为我买的传感器只支持整数。精度不够。

  • 腾讯mqtt的文档地址

https://github.com/tencentyun/qcloud-iot-esp-wifi

其他地方完全看不懂。尤其其中topic

  • Mqtt参数的密码问题

密码我不会代码生成,所以选中在线计算。

这里要注意,记得勾选 我图中的base64格式密钥。

image.png
  • 最后的结果


    image.png
image.png
  • 后续

增加OLED屏幕和空气质量

你可能感兴趣的:(物联网开发实战-家庭温湿度计的实现)