关于#json#的问题:阿里云平台能读取到dht11的温湿度数值和led的开关状态,但是不知道为什么我阿里云平台发送1的控制led信号

我8266连接阿里云,阿里云平台能读取到dht11的温湿度数值和led的开关状态,但是不知道为什么我阿里云平台发送1的控制led信号,他会解析成0。以下是代码

#include <ESP8266WiFi.h>
#include <DFRobot_DHT11.h>
#include <ArduinoJson.h>
//#include <AliyunioTSDK>

DFRobot_DHT11 DHT;
#define DHT11_PIN 5  //D1

char ssid[] = "sssjk";    // your network SSID (name)
char pass[] = "88888888";    // your network password (use for WPA, or use as key for WEP)

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);

const char broker[] = "iot-06z00giq7bii0r9.mqtt.iothub.aliyuncs.com";
int port = 1883;

const char inTopic[] = "/sys/k0469mOKTvh/8266test/thing/service/property/set";
const char outTopic[] = "/sys/k0469mOKTvh/8266test/thing/event/property/post";

const long interval = 10000;
unsigned long previousMillis = 0;

int count = 0;

String inputString = "";

int ledPin = 4;

void setup() {
  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  
  pinMode(ledPin, OUTPUT);

  // Attempt to connect to WiFi network:
  Serial.print("Attempting to connect to WPA SSID: ");
  Serial.println(ssid);
  while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
    // Failed, retry
    Serial.print(".");
    delay(5000);
  }

  Serial.println("You're connected to the network");
  Serial.println();

  mqttClient.setId("k0469mOKTvh.8266test|securemode=2,signmethod=hmacsha256,timestamp=1692836312276|");                    //mqtt 连接客户端id
  mqttClient.setUsernamePassword("8266test&k0469mOKTvh", "2b845e9eab066a43aa768fa2d4ae31118ef5306df057d494776b0031cc7c79aa");        //mqtt 连接用户名、密码

  Serial.print("Attempting to connect to the MQTT broker: ");
  Serial.println(broker);

  if (!mqttClient.connect(broker, port)) {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(mqttClient.connectError());

    while (1);
  }

  Serial.println("You're connected to the MQTT broker!");
  Serial.println();

  // Set the message receive callback
  mqttClient.onMessage(onMqttMessage);

  Serial.print("Subscribing to topic: ");
  Serial.println(inTopic);
  Serial.println();

  int subscribeQos = 1;

  mqttClient.subscribe(inTopic, subscribeQos);

  // Topics can be unsubscribed using:
  // mqttClient.unsubscribe(inTopic);

  Serial.print("Waiting for messages on topic: ");
  Serial.println(inTopic);
  Serial.println();
}

void loop() {

  mqttClient.poll();

  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // Save the last time a message was sent
    previousMillis = currentMillis;

    String payload;

    DHT.read(DHT11_PIN);

    DynamicJsonDocument json_msg(512);
    DynamicJsonDocument json_data(512);

    json_data["temp"] = DHT.temperature;
    json_data["humi"] = DHT.humidity;
    json_data["led"]["value"] = digitalRead(ledPin);

    json_msg["params"] = json_data;
    json_msg["version"] = "1.0.0";

    serializeJson(json_msg, payload);

    Serial.print("Sending message to topic: ");
    Serial.println(outTopic);
    Serial.println(payload);

    bool retained = false;
    int qos = 1;
    bool dup = false;

    mqttClient.beginMessage(outTopic, payload.length(), retained, qos, dup);
    mqttClient.print(payload);
    mqttClient.endMessage();

    Serial.println();

    count++;
  }
}

void onMqttMessage(int messageSize) {
  Serial.print("Received a message with topic '");
  Serial.print(mqttClient.messageTopic());
  Serial.print("', duplicate = ");
  Serial.print(mqttClient.messageDup() ? "true" : "false");
  Serial.print(", QoS = ");
  Serial.print(mqttClient.messageQoS());
  Serial.print(", retained = ");
  Serial.print(mqttClient.messageRetain() ? "true" : "false");
  Serial.print("', length ");
  Serial.print(messageSize);
  Serial.println(" bytes:");

  while (mqttClient.available()) {
    char inChar = (char)mqttClient.read();
    inputString += inChar;
    if (inputString.length() == messageSize) {

      DynamicJsonDocument json_msg(1024);
      DynamicJsonDocument json_item(1024);

      deserializeJson(json_msg, inputString);

      JsonObject params = json_msg["params"].as<JsonObject>();
      bool ledValue = params["led"]["value"].as<bool>();

      if (ledValue == 0) {
        // LED灯关
        Serial.println("LED OFF");
        digitalWrite(ledPin, LOW);
      } else {
        // LED灯开
        Serial.println("LED ON");
        digitalWrite(ledPin, HIGH);
      } 
      inputString = "";
    }
  }
  //Serial.println(inputString);
  Serial.println();
}



下面是发送控制信号后,arduino串口监视器收到的
09:09:19.807 -> Received a message with topic '/sys/k0469mOKTvh/8266test/thing/service/property/set', duplicate = false, QoS = 0, retained = false', length 92 bytes:
09:09:19.943 -> LED OFF

引用 皆我百晓生 小程序回复内容作答:

根据你提供的代码,我注意到在onMqttMessage函数中,当接收到控制信号时,你使用了params['led']['value'].as<bool>()来获取LED的状态值。根据你的描述,当你发送1的控制信号时,它被解析成了0,导致LED灯关闭。

这可能是由于阿里云平台发送的控制信号与你的代码中的数据类型不匹配导致的。你可以尝试修改代码,将params['led']['value'].as<bool>()改为params['led']['value'].as<int>(),然后再进行测试。这样可以将接收到的控制信号作为整数值进行处理,以确保正确解析。

修改后的代码如下:

void onMqttMessage(int messageSize) {
  // ...
  while (mqttClient.available()) {
    // ...
    int ledValue = params['led']['value'].as<int>();
 
    if (ledValue == 0) {
      // LED灯关
      Serial.println('LED OFF');
      digitalWrite(ledPin, LOW);
    } else {
      // LED灯开
      Serial.println('LED ON');
      digitalWrite(ledPin, HIGH);
    } 
    // ...
  }
  // ...
}

请尝试修改代码并重新测试,看看是否能够解决问题。如果问题仍然存在,请检查阿里云平台发送的控制信号的数据类型,并确保与代码中的数据类型匹配。

【以下回答由 GPT 生成】

根据提供的代码,我们可以看到程序中并没有针对收到的控制信号进行处理,而且也没有在程序中设置ledPin的初始状态。因此,我们需要对程序进行修改来解决这个问题。

首先,在setup()函数中,我们需要将ledPin设置为输出模式,并将其初始状态设置为0(关闭状态)。

void setup() {
  // ...
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW); // 初始状态为关闭(0)
  // ...
}

接下来,在loop()函数中,我们需要处理收到的控制信号,并根据信号的值来控制led的状态。

void loop() {
  // ...
  mqttClient.loop();

  // 处理收到的控制信号
  if (mqttClient.available()) {
    char c = mqttClient.read();
    inputString += c;

    if (c == '}') {
      // 解析收到的JSON数据
      DynamicJsonDocument doc(1024);
      deserializeJson(doc, inputString);

      int ledState = doc["params"]["led"].as<int>();

      // 控制led的状态
      digitalWrite(ledPin, ledState);

      inputString = ""; // 清空输入缓冲区
    }
  }

  // ...
}

这样修改后,我们可以根据收到的控制信号来控制led的状态。如果收到的控制信号中led的值为1,那么led将被打开;如果led的值为0,那么led将被关闭。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^