HackLab平台示例代码解析——@NodeMCU篇-(四)连接阿里云物联网平台

注释还算挺多的

hacklab平台

#include 
#include 
#include 

#define WIFI_SSID "Tenda_12E9E0"
#define WIFI_PASSWD "88889999"
//          阿里云三元组
#define PRODUCT_KEY "a1ZJp7eq1cW"
#define DEVICE_NAME "my_flowerpot"
#define DEVICE_SECRET "FKoFPqwLjchgWCguYdXt9dYd7OPzlKRN"

#define ALINK_BODY_FORMAT "{\"id\":\"%u\",\"version\":\"1.0\",\"method\":\"%s\",\"params\":%s}"     //  消息体字符串格式
#define ALINK_TOPIC_PROP_POST "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/post"  //发布,设备属性上报
#define ALINK_TOPIC_PROP_SET "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/service/property/set"  //订阅,设备属性设置
#define ALINK_METHOD_PROP_POST "thing.event.property.post"                                      //设备属性上报,作为上面发布订阅消息体的method参数

const int LED = D2;
const int BUTTON = D6;

int ledState = HIGH; // the current state of the output pin
int previous = LOW; // the previous reading from the input pin  记录开关的上一次状态

// the follow variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounce = 2000; // the debounce time, increase if the output flickers

unsigned long lastMqttConnectMs = 0;

unsigned int postMsgId = 0;

WiFiClient espClient;
PubSubClient mqttClient(espClient);
//              连接WiFi不用多说
void initWifi(const char *ssid, const char *password)
{
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.println("WiFi does not connect, try again ...");
    delay(3000);
  }

  Serial.println("Wifi is connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void mqttCheckConnect()
{
  bool connected = connectAliyunMQTT(mqttClient, PRODUCT_KEY, DEVICE_NAME, DEVICE_SECRET);
  if (connected) {//    如果连接上mqtt则打印
    Serial.println("MQTT connect succeed!");
    if (mqttClient.subscribe(ALINK_TOPIC_PROP_SET)) {//     如果订阅成功,注意上面定义的订阅消息体,则打印
      Serial.println("subscribe done.");
    } else {
      Serial.println("subscribe failed!");
    }
  }
}
//      设备上报函数,里面定义死了要上传LED灯的状态
void mqttPublish()
{
  char param[32];
  char jsonBuf[128];
//      下面sprintf是格式化字符串
  sprintf(param, "{\"LightSwitch\":%d}", ledState);
  postMsgId += 1;
  sprintf(jsonBuf, ALINK_BODY_FORMAT, postMsgId, ALINK_METHOD_PROP_POST, param);

  if (mqttClient.publish(ALINK_TOPIC_PROP_POST, jsonBuf)) {
     Serial.print("Post message to cloud: ");
     Serial.println(jsonBuf);
  } else {
    Serial.println("Publish message to cloud failed!");
  }
}
//              这个函数是用来解析订阅的topic的
// https://pubsubclient.knolleary.net/api.html#callback
void callback(char* topic, byte* payload, unsigned int length)
{
  if (strstr(topic, ALINK_TOPIC_PROP_SET))
  {
    Serial.print("Set message arrived [");
    Serial.print(topic);
    Serial.print("] ");
    payload[length] = '\0';
    Serial.println((char *)payload);

    // Deserialization break change from 5.x to 6.x of ArduinoJson
    DynamicJsonDocument doc(100);
    DeserializationError error = deserializeJson(doc, payload);
    if (error)
    {
      Serial.println("parse json failed");
      return;
    }
    //          将字符串payload转换为json格式的对象
    // {"method":"thing.service.property.set","id":"282860794","params":{"LightSwitch":1},"version":"1.0.0"}
    JsonObject setAlinkMsgObj = doc.as();
    // LightSwitch
    int desiredLedState = setAlinkMsgObj["params"]["LightSwitch"];

    if (desiredLedState == HIGH || desiredLedState == LOW) {
      ledState = desiredLedState;//     修改灯的状态,但是这里没有digitalWrite

      const char* cmdStr = desiredLedState == HIGH ? "on" : "off";
      Serial.print("网络命令: Turn ");
      Serial.print(cmdStr);
      Serial.println(" 这个灯.");
    }
  }
}

// the setup routine runs once when you press reset:
void setup() {
  Serial.begin(115200);
  Serial.println("Hacklab MQTT LED demo starts.");

  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT);

  initWifi(WIFI_SSID, WIFI_PASSWD);
  mqttClient.setCallback(callback);

  lastMqttConnectMs = millis();
  mqttCheckConnect();
  mqttPublish();
}

// the loop routine runs over and over again forever:
void loop() {
  int reading = digitalRead(BUTTON);//读取的开关的高低电平
    //  设置检查mqtt连接周期是五秒
  if (millis() - lastMqttConnectMs >= 5000) {
    lastMqttConnectMs = millis();
    mqttCheckConnect();
  }
    //      如果客户端没有在循环,那么打印disconnected
  // https://pubsubclient.knolleary.net/api.html#loop
  if (!mqttClient.loop()) {
    Serial.println("The MQTT client is disconnected!");
  }
//   Serial.println(reading);
  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (reading == HIGH && previous == LOW && millis() - lastDebounceTime > debounce) {//函数消除抖动,两个时间间隔必须大于0.5秒才能进行改变
    if (ledState == HIGH) {
      ledState = LOW;
      Serial.println("Turn off light locally.");
    } else {
      ledState = HIGH;
      Serial.println("Turn on light locally.");
    }

    lastDebounceTime = millis();
    //      这里修改一下,debounce的参数为2000,让设备两秒再上报一次
    mqttPublish();
    Serial.print("LED state: ");
    Serial.print(ledState);
    Serial.print(", Time: ");
    Serial.println(lastDebounceTime);
  }
  digitalWrite(LED, ledState);
}
//  reading是设备读取本地开关,previous也是读取开关,但是你不按就是低电平,不用管,由低到高便是开关合上的过程,即LED改变的信号,但是必须消除抖动,或许我写的消除抖动不好,但是我的项目不用开关哈哈

HackLab平台示例代码解析——@NodeMCU篇-(四)连接阿里云物联网平台_第1张图片

每过两秒上报一次

HackLab平台示例代码解析——@NodeMCU篇-(四)连接阿里云物联网平台_第2张图片

在运行状态界面也可以看出,实时更新的,(^-^)V

你可能感兴趣的:(物联网学习)