#include <ArduinoJson.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include "DHTesp.h"

// WiFi
const char* ssid = "Wokwi-GUEST";
const char* password = "";
//dht22
const int DHT_PIN = 15;
//led
const int Red_PIN = 25;
const int Green_PIN = 26;
const int Blue_PIN = 27;

//json对象
JsonDocument doc_in;   //json输入
JsonDocument doc_out;  //json输出


DHTesp dhtSensor;

int temp = 23;
int hum = 80;
long time_old = 0;

void wifi_setup() {
  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.println("IP address: ");
  Serial.println(WiFi.localIP());
}

// MQTT Broker
const char *mqtt_broker = "broker.mqttdashboard.com";  //broker.mqttdashboard.com  broker.emqx.io
const int mqtt_port = 1883;
const char *mqtt_username = "";
const char *mqtt_password = "";
///mqtt通信主题
const char *pub_topic = "hhxy/512/08_out";  //hhxy/512/26
const char *sub_topic = "hhxy/512/08_in";

//mqtt客户端id必须唯一
String client_id = "418_08";
WiFiClient espClient;
PubSubClient client(espClient);

//mqtt服务器连接
void mqtt_connect() {
  //connecting to a mqtt broker
  client.setServer(mqtt_broker, mqtt_port);
  client.setCallback(callback);
  while (!client.connected()) {
    //String client_id = "esp32-client-";
    client_id += String(WiFi.macAddress());
    Serial.printf("The client %s connects to the public mqtt broker\n", client_id.c_str());
    if (client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
      Serial.println("Public emqx mqtt broker connected");
    } else {
      Serial.print("failed with state ");
      Serial.print(client.state());
      delay(2000);
    }
  }
  // publish and subscribe
  client.publish(pub_topic, "Hi EMQ X I'm ESP32 ^^");
  //订阅主题
  client.subscribe(sub_topic);
}

//命令处理
void cmd_cl() {
  //命令json格式:例如{"cmd":"Red","val":200}
  String cmd = doc_in["cmd"];
  int val = doc_in["val"];
  if (cmd == "Red") {
    // Serial.print("Red=");
    // Serial.println(val);
    Serial.println("Red=" + String(val));
    digitalWrite(Red_PIN, val); 
  }
  if (cmd == "Green") {
     Serial.println("Green=" + String(val)); 
     digitalWrite(Green_PIN, val);
  }
  if (cmd == "Blue") {
     Serial.println("Blue=" +String(val));
     digitalWrite(Blue_PIN, val);
      }
}

void callback(char *topic, byte *payload, unsigned int length) {
  Serial.print("Message arrived in topic: ");
  Serial.println(topic);
  Serial.print("Message:");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  Serial.println("-----------------------");
  //把mqtt消息转为json对象
  DeserializationError error = deserializeJson(doc_in, payload);
  // Test if parsing succeeds
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    return;
  }
  cmd_cl();  //消息处理
}
  
//mqtt数据输出,json格式:{"type":"Temp","val":23}
void mqttt_pub(String Type, float Val) {
  String data;
  char buf[30];
  doc_out["type"] = Type;
  doc_out["val"] = Val;
  serializeJson(doc_out, data); 
  data.toCharArray(buf, data.length() + 1); 
  Serial.println(String(buf));
  client.publish(pub_topic, buf);
}

void setup() {
  Serial.begin(115200);
  wifi_setup();
  mqtt_connect();
  //dht22初始化
  dhtSensor.setup(DHT_PIN, DHTesp::DHT22);
  //led初始化
  pinMode(Red_PIN, OUTPUT);
  pinMode(Green_PIN, OUTPUT);
  pinMode(Blue_PIN, OUTPUT);
}

//mqtt

void loop() {
  if (!client.connected()) {
    mqtt_connect();
  }
  if (millis() - time_old > 2000) {
    TempAndHumidity  data = dhtSensor.getTempAndHumidity();
    temp=data.temperature;
    hum=data.humidity;
    mqttt_pub("Temp", temp);
    mqttt_pub("Hum",hum);
    time_old = millis();
  }
  client.loop();
}