//This demonstrates MQTT publishing

//WiFi
#include <WiFiMulti.h>
WiFiMulti wifiMulti;
WiFiClient wifiClient;

//MQTT
#include <PubSubClient.h>
const char* mqttBroker = "broker.hivemq.com";
const int mqttPort = 1883;
void mqttCallback(char* topic, byte* payload, unsigned int length);
PubSubClient mqttClient(mqttBroker, mqttPort, mqttCallback, wifiClient);

char* subTopic = "apu/cs452/s2021/yeh/led";
char* clientID = "yeh-esp32-1gsdfhfgdhsdfgsdfg";

long t_lastPub = 0;
long T_pub = 5*1000;
char* pubTopic = "apu/cs452/s2021/yeh/light";

//LED
const int pinLED = 2;

//Light Sensor
const int pinLight = 34;

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.println("CS452 MQTT client");

  //from previous code
  //LED
  pinMode(pinLED, OUTPUT);
  digitalWrite(pinLED, LOW);

  //WiFi setup
  WiFi.mode(WIFI_MODE_STA);
  wifiMulti.addAP("Wokwi-GUEST");
  wifiMulti.addAP("APU-MYDEVICES");
  wifiMulti.addAP("JamesPhone", "jamesphone");
  wifiMulti.addAP("Amped_TAPR2_guest", "blue3dog");

  Serial.println("Connecting...");
  connectWiFi();
}

void loop() {
  //connect MQTT if not connected
  if (!mqttClient.connected()) {
    mqttConnect();
  }
  //check if a subscribed message came in, call Callback if so
  mqttClient.loop();

  long t_now = millis();

  if (t_now - t_lastPub >= T_pub) {
    int lightLevel = analogRead(pinLight);

    char message[256];
    snprintf(message, 255, "L=%d", lightLevel);
    mqttClient.publish(pubTopic, message);
    
    t_lastPub = t_now;
  }
}

//call back if MQTT message came in
void mqttCallback(char* topic, byte* payload, unsigned int length) {
  //print topic
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  //print payload
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  
  //process message if topic matches
  if (strcmp(topic, subTopic) == 0) {
    changeLED(payload, length); 
  }
}

//process LED message
void changeLED(byte* payload, unsigned int length) {
  //make sure payload contains at least 1 character 
  if (length > 0) {
    //change LED accordingly
    switch (payload[0]) {
      case '0':
        digitalWrite(pinLED, LOW);
        break;
      case '1':
        digitalWrite(pinLED, HIGH);
        break;
      default:
        digitalWrite(pinLED, !digitalRead(pinLED));
    }
  }
}

//connect to mqtt
void mqttConnect() {
  //keep going until connected
  while (!mqttClient.connected()) {
    Serial.print("Connecting to MQTT...");
    if (mqttClient.connect(clientID)) {
      //connected!
      Serial.println("Connected");
      //resubscribe topics
      mqttClient.subscribe(subTopic, 1);
    } else {
      //print error code if not connected
      Serial.print("failed, err=");
      Serial.print(mqttClient.state());
      Serial.print("  wating 5 sec to retry...");
      delay(5000);
    }
  }
}

//Connect to WiFI
void connectWiFi() {
  Serial.print("MAC: ");
  Serial.println(WiFi.macAddress());

  while (wifiMulti.run() != WL_CONNECTED) {
    delay(250);
    Serial.print(".");
    digitalWrite(pinLED, !digitalRead(pinLED));
  }

  digitalWrite(pinLED, HIGH);

  Serial.println();
  Serial.println();
  Serial.print("Connected to ");
  Serial.println(WiFi.SSID());
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}