#include <ArduinoMqttClient.h>
// For ESP32:
#include <WiFi.h>
// For Arduino:
//#include <WiFiNINA.h>

char ssid[] = "RETITLC";
char pass[] = "rdclab2024";

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);

const char broker[] = "192.168.10.24";
int port = 1883;
const char topic_ping[] = "lab/A/0/ping";
const char topic_temperature[] = "lab/A/0/temperature";
const char topic_temperature_status[] = "lab/A/0/temperature_status";
const char topic_plc_status[] = "lab/PLC/1/temperature_status";
const char sub_topic[] = "lab/A/1/temperature";
const char sub_topic_status[] = "lab/A/1/temperature_status";

void setup() {
  // initialize serial and wait for port to open:
  Serial.begin(115200);
  delay(10);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // set the LED pins as output
  pinMode(2, OUTPUT); // for ESP32
  //WiFiDrv::pinMode(25, OUTPUT); // for Arduino, define RED LED
  //WiFiDrv::pinMode(26, OUTPUT); // for Arduino, define GREEN LED
  //WiFiDrv::pinMode(27, OUTPUT); // for Arduino, define BLUE LED


  // attempt to connect to Wifi network:
  Serial.print("Attempting to connect to WPA SSID: ");
  Serial.println(ssid);
  // For Arduino:
  /*while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
    // failed, retry
    Serial.print(".");
    delay(5000);
  }*/
  // For ESP32:
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED) {
    // failed, retry
    Serial.print(".");
    delay(5000);
  }

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

  // attempt to connect to the MQTT broker:
  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();

  // subscribe to the topics from the other device
  Serial.print("Subscribing to topic: ");
  Serial.println(sub_topic);
  mqttClient.subscribe(sub_topic);
  Serial.print("Subscribing to topic: ");
  Serial.println(sub_topic_status);
  mqttClient.subscribe(sub_topic_status);
}

void loop() {
  // call poll() regularly to allow the library to send MQTT keep alive which
  // avoids being disconnected by the broker
  mqttClient.poll();

  mqttClient.beginMessage(topic_ping);
  mqttClient.print("Hello");
  mqttClient.endMessage();

  // read the temperature sensor analog output:
  int sensorValue = analogRead(37); // Replace with A1 for Arduino
  // convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 3.3V):
  // For Arduino:
  //float voltage = sensorValue * (3.3 / 1023.0);
  // For ESP32:
  float voltage = sensorValue * (3.9 / 4095.0);
  // convert the voltage to temperature in degrees Celsius:
  float temperature = (voltage - 0.4) / 0.0195;

  // send the temperature via MQTT
  Serial.print("Sending message ");
  Serial.print(temperature);
  Serial.print(" to topic ");
  Serial.println(topic_temperature);
  mqttClient.beginMessage(topic_temperature);
  mqttClient.print(temperature);
  mqttClient.endMessage();

  // receive messages
  int messageSize = mqttClient.parseMessage();
  while (messageSize) {
    // we received a message, print out the topic and contents
    Serial.print("Received a message with topic '");
    String topic=mqttClient.messageTopic();
    Serial.print(topic);
    Serial.print("', length ");
    Serial.print(messageSize);
    Serial.println(" bytes:");
    String msg=mqttClient.readString();
    Serial.println(msg);

    // check if it is a temperature message
    if(topic==sub_topic) {
      // generate and send the temperature status via MQTT to the other device
      mqttClient.beginMessage(topic_temperature_status);
      if(msg.toFloat()>25) {
        mqttClient.print(1);
        Serial.println("Sending status 1 to other device");
      }
      else {
        mqttClient.print(0);
        Serial.println("Sending status 0 to other device");
      }
      mqttClient.endMessage();

      // generate and send the temperature status via MQTT to the PLC
      mqttClient.beginMessage(topic_plc_status);
      if(msg.toFloat()>25) {
        mqttClient.print(1);
        Serial.println("Sending status 1 to PLC");
      }
      else {
        mqttClient.print(0);
        Serial.println("Sending status 0 to PLC");
      }
      mqttClient.endMessage();
    }

    // check if it is a temperature status message
    if(topic==sub_topic_status) {
      // check how we have to act on the LED
      if(msg=="0") {
        digitalWrite(2,LOW); // for ESP32
        //digitalWrite(25,LOW); // for Arduino
        Serial.println("LED off");
      }
      else {
        digitalWrite(2,HIGH); // for ESP32
        //digitalWrite(25,HIGH); // for Arduino
        Serial.println("LED on");
      }
    }

    // check if there are other incoming messages
    messageSize = mqttClient.parseMessage();
  }
  
  delay(2000);
}
