/*
 Basic ESP8266 MQTT example

 This sketch demonstrates the capabilities of the pubsub library in combination
 with the ESP8266 board/library.

 It connects to an MQTT server then:
  - publishes "hello world" to the topic "outTopic" every two seconds
  - subscribes to the topic "inTopic", printing out any messages
    it receives. NB - it assumes the received payloads are strings not binary
  - If the first character of the topic "inTopic" is an 1, switch ON the ESP Led,
    else switch it off

 It will reconnect to the server if the connection is lost using a blocking
 reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to
 achieve the same result without blocking the main loop.

 To install the ESP8266 board, (using Arduino 1.6.4+):
  - Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs":
       http://arduino.esp8266.com/stable/package_esp8266com_index.json
  - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266"
  - Select your ESP8266 in "Tools -> Board"

*/
//#include <EEPROM.h>

#include <ESP8266WiFi.h>

//#include <ESP8266HTTPClient.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Nextion.h>

#include <X10ir.h>

#define BUZZER_PIN D2

// X10 Infrared Receiver Library
void infraredEvent(char house, byte unit, byte command, bool isRepeat);

X10ir x10ir = X10ir(
  5, // Receive Interrupt Number (1 = Standard Arduino External Interrupt)
  5, // Receive Interrupt Pin (Pin 3 must be used with interrupt 1)
  'A', // Default House Code
//  *infraredEvent // Event triggered when IR message is received
infraredEvent // Event triggered when IR message is received .  //In example zonder * !!!!
);


// Update these with values suitable for your network.

const char* ssid = "FrankHilde";
const char* password = "HildeFrank";
const char* mqtt_server = "192.168.2.202";

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[100];
int value = 0;

#define idx_staandelamp       1252
#define idx_hanglamp          1326
#define idx_haardverlichting  628
#define idx_tuinverlichting   695
#define idx_rooster           148
#define idx_deurbel           906
#define idx_deurbel_stil      917
#define idx_rooster           922

//NexButton b0 = NexButton(0, 1, "b0");

NexText txt_header = NexText(0, 14, "txt_header");
//NexText txt_weer = NexText(0, 12, "txt_weer");

NexPicture pic_weer = NexPicture(0, 13, "pic_weer");

NexDSButton btn_1 = NexDSButton(0, 5, "btn_1");
NexDSButton btn_2 = NexDSButton(0, 2, "btn_2");
NexDSButton btn_3 = NexDSButton(0, 4, "btn_3");
NexDSButton btn_4 = NexDSButton(0, 6, "btn_4");
NexDSButton btn_5 = NexDSButton(0, 7, "btn_5");

//NexText txt_temp_binnen = NexText(0, 9, "txt_temp_in");
//NexText txt_temp_buiten = NexText(0, 10, "txt_temp_out");
//NexText txt_regen = NexText(0, 11, "t2");

//page1
//NexText txt_1_temp_binnen = NexText(1, 3, "txt_temp_in");
//NexText txt_1_temp_buiten = NexText(1, 4, "txt_temp_out");

//NexText txt_1_header = NexText(1, 1, "txt_header");
//NexText txt_1_weer = NexText(0, 15, "txt_weer");


char buffer[100] = {0};

NexTouch *nex_listen_list[] = 
{
    &btn_1, &btn_2, &btn_3, &btn_4, &btn_5,
    NULL
};


void btn_1_PopCallback(void *ptr)
{
    uint32_t dual_state;
    
    btn_1.getValue(&dual_state);
    if(dual_state) 
    {
      send_nvalue(idx_hanglamp,1);
    }
    else
    {
      send_nvalue(idx_hanglamp,0);
    } 
}


void btn_2_PopCallback(void *ptr)
{
    uint32_t dual_state;

    btn_2.getValue(&dual_state);
    if(dual_state) 
    {
      send_nvalue(idx_staandelamp,1);
    }
    else
    {
      send_nvalue(idx_staandelamp,0);
    }
}


void btn_3_PopCallback(void *ptr)
{
    uint32_t dual_state;

    /* Get the state value of dual state button component . */
    btn_3.getValue(&dual_state);
    if(dual_state) 
    {
      send_nvalue(idx_haardverlichting,1);
    }
    else
    {
      send_nvalue(idx_haardverlichting,0);
    } 
}


void btn_4_PopCallback(void *ptr)
{
    uint32_t dual_state;

    /* Get the state value of dual state button component . */
    btn_4.getValue(&dual_state);
    if(dual_state) 
    {
      send_nvalue(idx_tuinverlichting,1);
    }
    else
    {
      send_nvalue(idx_tuinverlichting,0);
    } 
}


void btn_5_PopCallback(void *ptr)
{
    uint32_t dual_state;

    /* Get the state value of dual state button component . */
    btn_5.getValue(&dual_state);
    if(dual_state) 
    {
      send_nvalue(idx_rooster,1);
    }
    else
    {
      send_nvalue(idx_rooster,0); 
    } 
}

void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
    int svalue1, loc, StepperTarget;
    String sub, devicename;

 StaticJsonDocument<256> doc;

  sendCommand("p0.pic=55");
  sendCommand("tm1.en=1");
  
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

 // Deserialize the JSON document
  DeserializationError error = deserializeJson(doc, payload);


 // Test if parsing succeeds.
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.c_str());
    return;
  }

  //Show Status WIFI icon
  sendCommand("p0.pic=55");

 // Get the root object in the document
  JsonObject root = doc.as<JsonObject>();

  int idx = root["idx"];
  const char* idx_name = root["name"];
  const char* idx_svalue1 = root["svalue1"];
  const char* idx_svalue2 = root["svalue2"];
  const char* idx_svalue4 = root["svalue4"];

  int idx_nvalue = root["nvalue"];  
 
  Serial.println(idx);
  Serial.println(idx_name);
  Serial.println(idx_svalue1);
  Serial.println(idx_nvalue);
  
    if(idx == idx_hanglamp) 
    {
        btn_1.setValue(idx_nvalue);
    }

    if(idx == idx_staandelamp) 
    {
        btn_2.setValue(idx_nvalue);
    }

    if(idx == idx_haardverlichting) 
    {
        btn_3.setValue(idx_nvalue);
    }
    
    if(idx == idx_tuinverlichting) 
    {
        btn_4.setValue(idx_nvalue);
    }
    
    if(idx == idx_rooster) 
    {
        btn_5.setValue(idx_nvalue);
    }

    //Tijd
    if(idx == 1513)
    {
       Serial.println(idx_svalue1);
       txt_header.setText(idx_svalue1);
     //  txt_1_header.setText(idx_svalue1);
    }  

    //Weer
    if(idx == 1459)
    {
       nextion_send("txt_weer.txt", idx_svalue1);  
    }

      if(idx==450)
      {
        nextion_send("txt_temp_in.txt", idx_svalue1);  
        nextion_send("t0.txt", idx_svalue2);  
        nextion_send("t2.txt", idx_svalue4);    

    
//        int length = sizeof(idx_svalue4);

//        Serial.println("Barometer");
//        Serial.println(length);
        
//        char subbuff[5];
//        memcpy( subbuff, &idx_svalue4[0], (length-2) );
//        subbuff[5] = '\0';          
//        nextion_send("t2.txt", subbuff);    

      }
      
      //Min temperatuur
      if(idx==1562)
      {
        nextion_send("t10.txt", idx_svalue1);  
      }
      //Max Temperatuur
      if(idx==1563)
      {
        nextion_send("t11.txt", idx_svalue1);  
      }
      //Rain
      if(idx==1564)
      {
        nextion_send("t3.txt", idx_svalue1);  
        nextion_send("t4.txt", idx_svalue2);        
      }
      
      if(idx==453)
      {
          nextion_send("txt_temp_out.txt", idx_svalue1);
          nextion_send("t1.txt", idx_svalue2);
      }

      //Set weer icoon
      if(idx==1522)
      {
           pic_weer.setPic(idx_nvalue);
      }

      if(idx==idx_deurbel)
      {
          if(idx_nvalue==1)
          {
            Serial.println("Show doorbell");
            sendCommand("vis pic_doorbell,1");
            //delay(200);
            for (int i=0; i<10; i++) 
            {   
                tone(BUZZER_PIN,1000,200);    
                delay(500); 
            }    
            sendCommand("vis pic_doorbell,0");
          }
      }

      //Show Deurbel stil icon
      if(idx==idx_deurbel_stil)
      {
          if(idx_nvalue==1)
              sendCommand("p1.pic=56");
          else
              sendCommand("p1.pic=53");   
      }
}


void nextion_send(const char* idx, const char* val)
{

              char buf[50];

        char* part1 = "=\"";
          char* part2 = "\"";

          strcpy(buf, idx);
          strcpy(buf + strlen(idx), part1);
          strcpy(buf + strlen(idx) +strlen(part1), val);
          strcpy(buf + strlen(idx) +strlen(part1) + strlen(val), part2);
          Serial.println(buf);
          
         sendCommand(buf); 

} 


void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic", "hello world");
      // ... and resubscribe
      client.subscribe("domoticz/out/example/display");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {

  pinMode(BUZZER_PIN, OUTPUT); 
  digitalWrite(BUZZER_PIN, 0);
  
  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

    nexInit();
    /* Register the pop event callback function of the dual state button component. */
    btn_1.attachPop(btn_1_PopCallback, &btn_1);
    btn_2.attachPop(btn_2_PopCallback, &btn_2);
    btn_3.attachPop(btn_3_PopCallback, &btn_3);
    btn_4.attachPop(btn_4_PopCallback, &btn_4);    
    btn_5.attachPop(btn_5_PopCallback, &btn_5);

    //X10 IR Receiver
    x10ir.begin();



}

void loop() {

  nexLoop(nex_listen_list);

  if (!client.connected()) 
  {
    reconnect();
  }
  
  client.loop();

  long now = millis();
  if (now - lastMsg > 20000) 
  {
    lastMsg = now;
    ++value;    
  }
}


void send_nvalue(int idx, int nvalue)
{
    StaticJsonDocument<200> doc;

    Serial.println("Sending nvalue");
    Serial.println(idx);
    Serial.println(nvalue);

    // Make our document be an object
    JsonObject root = doc.to<JsonObject>();

    root["command"] = "switchlight";
    root["idx"] = idx;
    if(nvalue == 1)
    {
      root["switchcmd"] = "On";
    }
    else
    {
      root["switchcmd"] = "Off";
    }
    serializeJson(root, msg);
    Serial.println(msg);
    client.publish("domoticz/in", msg);        
}


// Process commands received from X10 compatible IR remote
void infraredEvent(char house, byte unit, byte command, bool isRepeat)
{

    //Show Status IR icon
    sendCommand("p0.pic=54");
    sendCommand("tm1.en=1");

      Serial.println("!! IR Received !!");
    if(!isRepeat)
    {

      Serial.println(command);
      // Handle Address Command (House + Unit)
      if(command == CMD_ADDRESS)
      {
        Serial.println("cmd == CMD_ADDRESS");
        Serial.println(house);
        Serial.println(unit);
        Serial.println(command);
        
        if(unit <= 16)
        {
           Serial.println("Switch...");

            if(unit==1)     //Staandelamp
              btn_2_PopCallback(0);
            if(unit==2)     //Haard
              btn_3_PopCallback(0);
            if(unit==4)     //Rooster      
            {
              send_nvalue(idx_rooster,1); 
            }
              //btn_2_PopCallback(0);
            if(unit==4)     //Hanglamp
              btn_1_PopCallback(0);
            if(unit==3)     //Tuin
              btn_4_PopCallback(0);
        }      
      }
    }
}
