#include <ESP8266WiFi.h>
#include <PubSubClient.h>
const char* ssid = "xxx";
const char* password = "xxx";
const char* mqtt_server = "xxx";
const int mqtt_port = 1883;
const char* mqtt_username = "xxx";
const char* mqtt_password = "xxx";
const char* mqtt_topic_prefix = "homeassistant/sensor/kasvihuone";  // MQTT-aiheen alkuosa antureille
const char* plant_names[] = {"kasvi1", "kasvi2", "kasvi3", "kasvi4", "kasvi5", "kasvi6"};  // Kasvien nimet
const char* binary_sensor_topic = "homeassistant/binary_sensor/kasvihuone/vesi/state";  // MQTT-aihe binäärianturille
IPAddress staticIP(x, x, x, x); // Staattinen IP-osoite
IPAddress gateway(x, x, x, x);   // Gateway
IPAddress subnet(x, x, x, x);  // Subnet mask
IPAddress dns(x, x, x, x);       // DNS-palvelin
WiFiClient espClient;
PubSubClient client(espClient);
String currentWaterState = "";  // Nykyinen vesitila
String newWaterState = "";  // Uusi vesitila
bool newWaterStateAvailable = false;  // Lipuke uudelle vesitilalle
unsigned long lastPublishTimes[7] = {0, 0, 0, 0, 0, 0, 0};  // Viimeisimmät julkaisuajat
const long publishInterval = 30000;  // Julkaisuväli 30 sekuntia
void setup() {
  Serial.begin(9600);  // Aloita sarjaviestintä nopeudella 9600 bps
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.config(staticIP, gateway, subnet, dns);  // Aseta staattinen IP-konfiguraatio
  WiFi.begin(ssid, password);  // Yhdistä WiFi-verkkoon
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  client.setServer(mqtt_server, 1883);  // Aseta MQTT-palvelin ja portti
  client.setCallback(callback);  // Aseta callback-funktio MQTT-viestien käsittelyyn
}
void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("kasvihuone_kosteus", mqtt_username, mqtt_password)) {
      Serial.println("connected");
      client.subscribe(binary_sensor_topic);  // Tilaa binäärianturin aihe
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}
void callback(char* topic, byte* payload, unsigned int length) {
  // Käsittele saapuvat MQTT-viestit
  String message;
  for (unsigned int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  if (String(topic) == binary_sensor_topic) {
    // Päivitä nykyinen vesitila
    currentWaterState = message;
    Serial.print("Received current water state: ");
    Serial.println(currentWaterState);
  }
}
void loop() {
  if (!client.connected()) {
    reconnect();  // Yhdistä uudelleen, jos yhteys on katkennut
  }
  client.loop();  // Käsittele MQTT-viestit
  while (Serial.available() > 0) {
    String sensorData = Serial.readStringUntil('\n');  // Lue sarjadata rivi kerrallaan
    Serial.print("Received sensor data: ");
    Serial.println(sensorData);
    unsigned long currentMillis = millis();  // Hae nykyinen aika
    if (sensorData.startsWith("vesi")) {
      // Päivitä uusi vesitila
      newWaterState = (sensorData.indexOf("on") != -1) ? "ON" : "OFF";
      newWaterStateAvailable = true;
      // Lähetä uusi vesitila heti
      if (newWaterState != currentWaterState) {
        Serial.print("Publishing new water state: ");
        Serial.println(newWaterState);
        if (!client.publish(binary_sensor_topic, newWaterState.c_str(), true)) {  // Julkaise vesitilan MQTT-viesti
          Serial.println("Failed to publish MQTT binary sensor message!");
        } else {
          Serial.println("MQTT binary sensor message published successfully.");
          currentWaterState = newWaterState;  // Päivitä nykyinen tila
          lastPublishTimes[0] = currentMillis;  // Päivitä viimeisin lähetysaika
        }
      }
      newWaterStateAvailable = false;  // Nollaa lipuke
    } else {
      // Käsittele analogiset anturidatat
      int colonIndex = sensorData.indexOf(':');
      if (colonIndex != -1) {
        String sensorName = sensorData.substring(0, colonIndex);
        String valueStr = sensorData.substring(colonIndex + 2);
        valueStr.trim();  // Poista ylimääräiset välilyönnit
        int humidityValue = valueStr.toInt();
        for (int i = 0; i < 6; i++) {
          String expectedName = "Sensor A" + String(i);
          if (sensorName.equals(expectedName) && (currentMillis - lastPublishTimes[i + 1] >= publishInterval)) {
            // Julkaise anturidata MQTT:llä
            String mqttMessage = String(humidityValue);
            String mqttTopic = String(mqtt_topic_prefix) + "/" + plant_names[i] + "/moisture";
            Serial.print("Publishing to topic: ");
            Serial.print(mqttTopic);
            Serial.print(" message: ");
            Serial.println(mqttMessage);
            if (!client.publish(mqttTopic.c_str(), mqttMessage.c_str(), true)) {  // Julkaise MQTT-viesti
              Serial.println("Failed to publish MQTT message!");
            } else {
              Serial.println("MQTT message published successfully.");
              lastPublishTimes[i + 1] = currentMillis;  // Päivitä viimeisin lähetysaika
            }
            break;
          }
        }
      }
    }
  }
}