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

char ssid[] = "Wokwi-GUEST"; //SSID vašeho Wifi routeru
char pass[] = ""; //heslo na Wifi
//server MQTT brokeru, na kteý se budeme připojovoat
char server[] = "broker.mqttdashboard.com";
int port = 1883;

//nastavení názvů topiců, na které budeme posílat ze zařízení eventy (evtTopic) 
//a ze kterých budeme poslouchat commandy (cmdTopic)
const char evtTopic[] = "jakblikam_JA";
const char cmdTopic[] = "bliknipls_JA";
//název klienta - našeho zařízení, který potřebujeme podle knihovny k připojení 
//https://pubsubclient.knolleary.net/api
const char clientName[] = "mojeblikatko_JA";

//proměnná pro uložení stavu ledky na WEMOS desce
String stav;


//tyto dvě proměnné použijeme v časové 'if' smyčce
int publishInterval = 2000; //udává jak často bude mikrokontroler posílat stav (2s)
long lastPublishMillis;
long lastBlinkMillis;

//proměnná, kam budeme ukládat stav led na desce (zda svítí nebo ne)
int reading;

/*
 * FUNKCE CALLBACKU S ČEKÁNÍM NA PŘÍKAZ K ROZSVĚCENÍ LED
 * budeme do zařízení posílat jednopísmenný txt 't' jako true a 'f' jako false
 * na základě přijatého písmenka WEMOS rozsvítí nebo zhasne ledku
 */
 
void cmdCallback(char* topic, byte* payload, unsigned int len) {

  char cmd = (char)payload[0];
    Serial.println("Publish-Topic-Message -> bliknipls T/F (ON/OFF)");
    Serial.println(cmd);

  if (cmd == 't' || cmd == 'T') { 
    digitalWrite(LED_BUILTIN, LOW);
    Serial.println("LED svítí");
    stav = "ON";
    return;
  }

  if (cmd == 'f' || cmd == 'F') { 
    digitalWrite(LED_BUILTIN, HIGH);
    Serial.println("LED NEsvítí");
    stav = "OFF";
    return;
  }
}

WiFiClient wClient; //instance wifi
PubSubClient pubSubClient(server, port, cmdCallback, wClient); //instance PubSub klienta

void connectCloud(){
  
  if (pubSubClient.connect(clientName)) {
    Serial.println("Connection to MQTT Broker Successfull");
    if (pubSubClient.subscribe(cmdTopic)){
      Serial.println("Subcription OK");
    } else {
      Serial.println("Subcription FAILED");
    }

  } else {
    Serial.println("Connection to MQTT Broker Failed");
  }
}

void setup() {
  Serial.begin(9600); //inicializace seriove linky pro vypis do konzole
  pinMode(LED_BUILTIN, OUTPUT);
    //vypneme led ma descea nastavíme a do proměnné stav si zapíšeme 'off'
  digitalWrite(LED_BUILTIN, HIGH);
  stav = "OFF";
  Serial.println("Led nastavena na OFF");
  
  // připojíme se na wifi
  Serial.print("Connecting to...");
  Serial.println(ssid);

  WiFi.begin(ssid, pass);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("Wi-Fi connected successfully");
}

void loop() {
/*
//budeme zapínat a vypínat led na desce vždy po 15s
if (millis() - lastBlinkMillis > publishInterval/20){
  Serial.println("Čas změnit LED");
  reading = digitalRead(LED_BUILTIN);
  Serial.println(reading);
  if (reading == HIGH) {
    digitalWrite(LED_BUILTIN, LOW);
    stav = "on";
  } else {
    digitalWrite(LED_BUILTIN, HIGH);
    stav = "off";
  }
  
lastBlinkMillis = millis();
}
*/

//ověříme, zda již uplynul stanovený čas, pokud ano provedeme zaslání zprávy
  if (millis() - lastPublishMillis > publishInterval){
  Serial.print("STAV LED: ");
  Serial.println(stav);
  
 //Voláme funkci createJSONMessage() na vytváření JSON zprávy, posílanou na server
//funkci najdete na konci kódu
    String json = createJSONMessage();

//zde udáváme počet znaků ve zprávě 
//pozor ať nemáte zprávu delší než počet, který si zde stanovíte !!!
    char jsonStr[100]; 
    json.toCharArray(jsonStr,100);

//poslání zprávy na server
    if (pubSubClient.connected()){
           
        boolean pubresult = pubSubClient.publish(evtTopic,jsonStr);
        Serial.print("Sending ");
        Serial.print(jsonStr);
        Serial.print(" to ");
        Serial.println(evtTopic);
        if (pubresult) {
          Serial.println("SUCCESS\n");
        } else {
          Serial.println("NOT SUCCESSFULL\n");
        }
    }

//nastavíme lastPublishMillis na soušasné millis - tj. zresetujeme odpočet
//do dalšího vyslání zpráv     
    lastPublishMillis = millis();
 }
 
 //Toto by mělo být voláno pravidelně, aby klient mohl zpracovávat příchozí zprávy 
 //a udržovat jeho připojení k serveru.
  if (!pubSubClient.loop()) {
    connectCloud();
  }

  if (WiFi.status() != WL_CONNECTED) { 
    Serial.println("Pripojeni selhalo.");
 
  } 
}

String createJSONMessage() { 
  String data = "{\"d\":{\"wemosled\":\"";
  data += stav +"\"";
  data += "}}";
  return data;
}