#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <WiFiManager.h>
//oled
#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
//rfm95
#include <SPI.h>
#include <RH_RF95.h>
#include <ArduinoJson.h>

//chosing the right display
U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(/* clock=*/ 2, /* data=*/ 0, /* reset=*/ U8X8_PIN_NONE);

#define NSS_PIN 15
#define DIO0_PIN 5
#define LED D0

RH_RF95 rf95(NSS_PIN, DIO0_PIN);

//access table
//Two Dimensional Array consist of maximum 10 devices and 3 informations and settings of each device
#define maxNumOfDevices 10
#define maxParameters 4
#define indexId  0
#define indexRelay1 1
#define indexRelay2 2
#define indexMode 3

int table[maxNumOfDevices][maxParameters] = {};
bool registerMode = false;
bool registerMode_old = false;
String receivedConfiguration = "";

ESP8266WebServer server(80);

//for interrupt
const byte interruptPin = D2;

//wifi default softAP setup
const char* ssid = "LoRa-GTW-setup";
const char* passphrase = "optiplex";

String urlPrefix = "/PHP";
String st;
String content;
String esid = "";
String epass = "";
String host = "";
bool connection = false;

int id;
bool rqst;
int rssi = 0;
int t = 0;
int h = 0;
int voltage = 0;

byte sendLen = 0;

//setup for millis function
unsigned long previousMillis = 0;
const long interval = 30000;

void setup() {
  Serial.begin(74880);
  delay(10);
  Serial.println();

  pinMode(LED, OUTPUT);
  digitalWrite(LED, HIGH);
  pinMode(interruptPin, INPUT_PULLUP);

  showStartScreen();
  setuppMCU();
  //The setupAP should be called with this interrupt
  attachInterrupt(digitalPinToInterrupt(interruptPin), afterInterrupt, RISING);
  Serial.println("Interrupt: Atached");
  
  eepromRead();

  //try to connect to WiFi
  if (esid.length() > 1) {
    WiFi.begin(esid.c_str(), epass.c_str());
    if (testWifi()) {
      launchWeb(0);
      if (connection) { // if Wifi connection is estabilished, pMCU can download the table from PHP
        downloadTheTable();
      }
      return;
    }
  }
  setupAP();
}

void loop() {
  //Handle LoRa clients
  if (rf95.available() && connection == true) { //RECEIVING - checks if LoRa module received some message
    if (dealWithMessage()) // checks permitions, parse received packet, replyes to LoRa sensor
      forwardDataToServer();
  }
  //Handle WiFi clients
  server.handleClient(); //This function processes HTTP request to pMCU

  //Handle table auto-download
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval && connection == true) {
    previousMillis = currentMillis;
    downloadTheTable();
  }
}

int arrayToInt(int number, int msg[], int length2) { //function takes the integer field with pointer and returns 4byte int number
  //parsing of values
  int value = 0;
  int pointer = number * 4;
  for (int i = pointer; i < pointer + length2; i++) {
    value *= 10;
    value += msg[i];
  }
  return value;
}

bool checkTheTable(int id, bool rqst) {
  // id is declared globally
  //check Table for permissions
  for (int i = 0; i < 10; i++) { //first check if the sensor is in the database
    if (id != table[i][indexId]) {
      continue;
    }
    Serial.println("SENSOR IS IN THE DATABASE.");
    Serial.print("under the index: ");
    Serial.println(i);
    return true;
  }

  if (registerMode == true && rqst == true) {
    Serial.println("Registration permission granted.");
    Serial.println("Making new record");
    for (int i = 0; i < maxNumOfDevices; i++) { //first find empty line
      if (table[i][indexId] == 0) {
        Serial.println("First empty line found.");
        Serial.print("Adress is: [");
        Serial.print(i);
        Serial.println("]");
        Serial.println("Saving device to that adess.");
        table[i][indexId] = id;
        printOutTheTable();
        sendCurrentTable();
        return true;
      }
      else {
        continue;
      }
    }
  }

  //if sensor was not found
  return false;
}

void printOutTheTable() {
  Serial.println("printing out the table:");
  for (int i = 0; i < maxNumOfDevices; i++) {
    for (int b = 0; b < maxParameters; b++) {
      Serial.print("[");
      Serial.print(table[i][b]);
      Serial.print("]");
    }
    Serial.println();
  }
}


int findElement() {
  for (int i = 0; i < maxNumOfDevices; i++) {
    if (id == table[i][indexId]) {
      Serial.println("FindElement = id found");
      return i;
    }
  }
  return 9999;
}

void sendCurrentTable() {
  //this function serves as an connection opener a sends the whole table after add a new record command
  //in registration mode
  Serial.println("[WiFi]: Sending current table to server.");

  String data = "[";
  //[{"sensor_id":"1233","relay_1":"0","relay_2":"0","commode":"0"}]
  for (int i = 0; i < maxNumOfDevices; i++) {
    data += "{\"sensor_id\":\"";
    data += table[i][indexId];
    data += "\",\"relay_1\":\"";
    data += table[i][indexRelay1];
    data += "\",\"relay_2\":\"";
    data += table[i][indexRelay2];
    data += "\",\"commode\":\"";
    data += table[i][indexMode];
    data += "\"}";
    if (i + 1 != maxNumOfDevices)
    {
      data += ",";
    }
  }
  data += "]";
  Serial.println(data);

  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host.c_str(), httpPort)) {
    Serial.println("[WiFi]: connection to server failed ");
    return;
  }

  String url = urlPrefix;
        url += "/receivetable";

  client.println("POST " + url + " HTTP/1.1");
  client.println("Host: 192.168.100.100");
  client.println("Cache-Control: no-cache");
  client.println("Content-Type: application/json");
  client.print("Content-Length: ");
  client.println(data.length());
  client.println();
  client.println(data);

  Serial.println("POST " + url + " HTTP/1.1");
  Serial.println("Host: 192.168.100.100");
  Serial.println("Cache-Control: no-cache");
  Serial.println("Content-Type: application/json");
  Serial.print("Content-Length: ");
  Serial.println(data.length());
  Serial.println();
  Serial.println(data);
  Serial.println("\n");

  //wait for server to replay to our request
  unsigned long timeout = millis();
  while (client.available() == 0) {
    if (millis() - timeout > 5000) {
      Serial.println("[WiFi]: >>> Client Timeout !");
      client.stop();
      return;
    }
  }
  String line = "";
  while (client.available()) {
    line = client.readStringUntil('\r');
    Serial.print(line);
  }
  Serial.println("[WiFi]: Server received data.");
}

void showStartScreen() {
  //Show start screen
  u8x8.begin();
  u8x8.setFont(u8x8_font_chroma48medium8_r);
  u8x8.clear();
  //u8x8.setCursor(0, 0);
  u8x8.draw2x2String(2, 1, "pMCU");
  u8x8.drawString(2, 3, "..wait..");
}

void setuppMCU() {
  //Just in case disconnect WiFi from
  //previous connections and set client mode
  WiFi.disconnect();
  WiFi.mode(WIFI_STA);

  Serial.println("pMcu is starting");
  delay(3000);

  if (!rf95.init())
    Serial.println("init failed");   // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on

  rf95.setFrequency(868.0);
  //rf95.printRegisters();

  delay(10);
}

void eepromRead() {
  EEPROM.begin(512);
  delay(10);
  //Serial.println("Reading EEPROM ssid");
  esid = "";
  for (int i = 0; i < 32; ++i) {
    esid += char(EEPROM.read(i));
  }
  //Serial.println("Reading EEPROM pass");
  epass = "";
  for (int i = 32; i < 64; ++i) {
    epass += char(EEPROM.read(i));
  }
  //Serial.println("Reading EEPROM host");
  host = "";
  for (int i = 64; i < 96; ++i) {
    host += char(EEPROM.read(i));
  }

  //print out all the stuff
  /*
    Serial.print("SSID: ");
    Serial.println(esid);
    Serial.print("PASS: ");
    Serial.println(epass);
    Serial.print("HOST: ");
    Serial.println(host);
  */
}

void afterInterrupt(void) {
  detachInterrupt(digitalPinToInterrupt(interruptPin));
  detachInterrupt(digitalPinToInterrupt(5));
  connection == false;
  Serial.println("Interrupt was called.");
  u8x8.clear();
  u8x8.draw2x2String(2, 1, "CONFIG");
  u8x8.drawString(0, 4, "click");
  u8x8.drawString(0, 5, "for reset");
  delay(500);

  //check button hold status
  //waits for second button push as a approval
  //Otherwise watchdog resets the pMCU
  while (digitalRead(interruptPin) == LOW) {
    delay(10);
  }
  while (digitalRead(interruptPin) == HIGH) {
    delay(10);
  }
  Serial.println("Settings reset was approved by user");
  Serial.println("Removing stored credentials.");
  for (int i = 0; i < 96; ++i) {
    EEPROM.write(i, 0);
  }

  EEPROM.commit();

  Serial.println("WiFi disconnect");
  WiFi.disconnect();
  delay(1000);

  Serial.println("Configuration erase.");
  Serial.println("ESP: AutoRestart");
  //ESP.restart();
  ESP.eraseConfig();
  ESP.reset();
}

bool testWifi(void) {
  int c = 0;
  Serial.println("Waiting for Gateway to connect to your home AP");
  Serial.println("--Credentials--");
  Serial.print("SSID: ");
  Serial.println(esid);
  Serial.print("PASS: ");
  Serial.println(epass);
  Serial.print("HOST: ");
  Serial.println(host);

  /* this values equals this status
    WL_NO_SHIELD = 255,
    WL_IDLE_STATUS = 0,
    WL_NO_SSID_AVAIL = 1
    WL_SCAN_COMPLETED = 2
    WL_CONNECTED = 3
    WL_CONNECT_FAILED = 4
    WL_CONNECTION_LOST = 5
    WL_DISCONNECTED = 6
  */
  //This methow was already called
  //WiFi.begin(esid.c_str(), epass.c_str());

  if (WiFi.status() != 0) {
    while ( c < 10 ) {
      if (WiFi.status() == 3) {
        u8x8.clear();
        u8x8.draw2x2String(3, 1, "pMCU");
        u8x8.drawString(2, 4, "..WAITING..");
        u8x8.drawString(3, 5, "for sensor");
        connection = true;
        return true;
      }
      Serial.print(WiFi.status());
      delay(1500);
      c++;
    }
    Serial.println("Calling for SoftAP");
  }
  return false;
}

void downloadTheTable() {
  String JsonStream = "";
  String url = urlPrefix;
        url += "/getconfiguration";

  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host.c_str(), httpPort)) {
    Serial.println("[WiFi]: connection to server failed ");
    delay(2000);
    ESP.reset();
  }
  //just send empty header
  client.println("POST " + url + " HTTP/1.1");
  client.println("Host: 192.168.100.100");
  client.println("Cache-Control: no-cache");
  client.println("Content-Type: application/json");
  client.print("Content-Length: ");
  client.println(JsonStream.length());
  client.println();
  client.println(JsonStream);

  String line = "";
  while (client.available()) {
    line = client.readStringUntil('\r');
  }
  //----------------------------------------------
  //comparsion of two strings
  if (receivedConfiguration != line) {
    receivedConfiguration = line;
    Serial.println("[WiFi]: Received data from server:");
    Serial.print(line);

    DynamicJsonBuffer jsonBuffer;
    JsonArray& array = jsonBuffer.parseArray(line);

    //first mesage is register mode information
    registerMode = array[0]["registermode"];
    if (registerMode != registerMode_old) {
      Serial.print("\nRegister mode: ");
      Serial.println(registerMode);
      registerMode_old = registerMode;
    }

    for (int i = 0; i < 10; i++) {

      table[i][indexId] = array[i + 1]["sensor_id"];
      table[i][indexRelay1] = array[i + 1]["relay_1"];
      table[i][indexRelay2] = array[i + 1]["relay_2"];
      table[i][indexMode] = array[i + 1]["commode"];
    }

    Serial.println("\n[WiFi]: Table downloaded from server");
    printOutTheTable();
    Serial.println("[pMCU]: Gateway setup complete.");
  }
  else {
    Serial.println("[pMCU]: Table checked for latest update.");
    return;
  }
}

void setupAP(void) {
  u8x8.clear();
  u8x8.draw2x2String(3, 1, "pMCU");
  u8x8.drawString(1, 4, "..WiFi-SetUP..");
  delay(1500);
  u8x8.setFont(u8x8_font_chroma48medium8_r);
  u8x8.clear();
  u8x8.setCursor(0, 0);
  u8x8.println(" ..WiFi config..");
  u8x8.println("     SSID:");
  u8x8.println("LoRa-GTW-setup");
  u8x8.println("     PASS:");
  u8x8.println("optiplex");
  u8x8.println("     IP:");
  u8x8.println("192.168.4.1");

  Serial.println("Opening AP");
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  int n = WiFi.scanNetworks();
  Serial.println("scan done");
  if (n == 0)
    Serial.println("no networks found");
  else {
    Serial.print(n);
    Serial.println(" networks found");
    for (int i = 0; i < n; ++i) {
      // Print SSID and RSSI for each network found
      Serial.print(i + 1);
      Serial.print(": ");
      Serial.print(WiFi.SSID(i));
      Serial.print(" (");
      Serial.print(WiFi.RSSI(i));
      Serial.print(")");
      Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*");
      delay(10);
    }
  }
  Serial.println("");
  st = "<ol>";
  for (int i = 0; i < n; ++i) {
    // Print SSID and RSSI for each network found
    st += "<li>";
    st += WiFi.SSID(i);
    st += " (";
    st += WiFi.RSSI(i);
    st += ")";
    st += (WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*";
    st += "</li>";
  }
  st += "</ol>";
  delay(100);
  WiFi.softAP(ssid, passphrase, 6);
  Serial.println("softap");
  launchWeb(1);

  Serial.println("over");
}
void launchWeb(int webtype) {
  Serial.println("");
  Serial.println("Gateway connected to your home WiFi AP");
  Serial.print("Local IP: ");
  Serial.println(WiFi.localIP());
  Serial.print("SoftAP IP: ");
  Serial.println(WiFi.softAPIP());

  createWebServer(webtype);
  // Start the server
  server.begin();
  Serial.println("Server started");
}

void createWebServer(int webtype) {
  //In softAP mode the purpose is to fill in the SSID and PASS
  if ( webtype == 1 ) {
    server.on("/", []() {
      IPAddress ip = WiFi.softAPIP();
      String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
      content = "<!DOCTYPE HTML>\r\n<html>Hello from ESP8266 at ";
      content += ipStr;
      content += "<p>";
      content += st;
      content += "</p><form method='get' action='setting'><br><br><table border='0'><tr><td>SSID: </td><td><input name='ssid' length=32></td></tr><tr><td>PASS: </td><td><input type='password' name='pass' length=32></td></tr><tr><td>Server IP: </td><td><input name='host' length=32></td></tr><tr><td></td><td><input type='submit'></td></tr></table></form>";
      content += "</html>";
      server.send(200, "text/html", content);
    });
    server.on("/setting", []() {
      String qsid = server.arg("ssid");
      String qpass = server.arg("pass");
      String host = server.arg("host");
      if (qsid.length() > 0 && qpass.length() > 0 && host.length()) {
        Serial.println("clearing eeprom");
        for (int i = 0; i < 96; ++i) {
          EEPROM.write(i, 0);
        }
        Serial.println(qsid);
        Serial.println("");
        Serial.println(qpass);
        Serial.println("");
        Serial.println(host);
        Serial.println("");

        Serial.println("writing eeprom ssid:");
        for (int i = 0; i < qsid.length(); ++i) {
          EEPROM.write(i, qsid[i]);
          Serial.print("Wrote: ");
          Serial.println(qsid[i]);
        }
        Serial.println("writing eeprom pass:");
        for (int i = 0; i < qpass.length(); ++i) {
          EEPROM.write(32 + i, qpass[i]);
          Serial.print("Wrote: ");
          Serial.println(qpass[i]);
        }
        Serial.println("writing eeprom host:");
        for (int i = 0; i < host.length(); ++i) {
          EEPROM.write(64 + i, host[i]);
          Serial.print("Wrote: ");
          Serial.println(host[i]);
        }
        EEPROM.commit();
        content = "<!DOCTYPE HTML>\r\n<html>";
        content += "<p>saved to eeprom... Gateway now provides an autoreset. </p><p>And will turn off the AP mode if the connection to your home router is successful.</p></html>";

      }
      else {
        content = "Error";
        Serial.println("Sending 404");
      }

      server.send(200, "text/html", content);
      Serial.println("Auto REBOOT");
      ESP.restart();
    });
  }

  //In Client mode after successful connection
  else if (webtype == 0) {
    /*
      server.on("/all", HTTP_GET, [](){
      String json = "{";
      json += "\"heap\":"+String(ESP.getFreeHeap());
      json += ", \"analog\":"+String(analogRead(A0));
      json += ", \"gpio\":"+String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16)));
      json += "}";
      server.send(200, "text/json", json);
      json = String();
      });
    */
    server.on("/", []() {
      // String JsonMsg = server.arg("plain")
      server.send(200, "text/plain", "this works ");
    });

    server.on("/json", receiveJson);
    server.on("/registermode", registermode);
    server.on("/configuration", configuration);
    server.on("/cleareeprom", cleareeprom);
    /*
      server.on("/setting", []() {
      server.send(200, "text/plain", "setting.");
      });
    */
  }
}

void cleareeprom() {
  content = "<!DOCTYPE HTML>\r\n<html>";
  content += "<p>Clearing the EEPROM</p></html>";
  server.send(200, "text/html", content);
  Serial.println("clearing eeprom");
  for (int i = 0; i < 96; ++i) {
    EEPROM.write(i, 0);
  }
  EEPROM.commit();
}

void configuration() { //for saving new table from server
  //[{\"sensor_id\":\"1234\",\"relay1\":\"0\",\"relay2\":\"0\",\"commode\":\"0\"}]
  String data = server.arg("plain");
  //String mojedata = "";
  DynamicJsonBuffer jsonBuffer;

  //JsonObject& jObject = jBuffer.parseObject(data);
  JsonArray& array = jsonBuffer.parseArray(data);
  for (int i = 0; i < 10; i++) {
    int sensor_id = array[i]["sensor_id"];
    bool relay_1 = array[i]["relay_1"];
    bool relay_2 = array[i]["relay_2"];
    bool commode = array[i]["commode"];


    table[i][indexId] = array[i]["sensor_id"];
    table[i][indexRelay1] = array[i]["relay_1"];
    table[i][indexRelay2] = array[i]["relay_2"];
    table[i][indexMode] = array[i]["commode"];

    Serial.print("cycle [");
    Serial.print(i);
    Serial.print("]\n");
    Serial.print("Sensonr_id: ");
    Serial.println(sensor_id);
    Serial.print("relay_1: ");
    Serial.println(relay_1);
    Serial.print("relay_2: ");
    Serial.println(relay_2);
    Serial.print("commode: ");
    Serial.println(commode);
    Serial.println();
  }

  server.send(200, "text/plain", data);

  Serial.print("[WiFi][PAYLOAD]: ");
  Serial.println(data);
  printOutTheTable();
}

void receiveJson() { //just for single recor changes
  //{"id":1234,"pin1":0,"pin2":0 "commode": 0}
  String data = server.arg("plain");
  String mojedata = "";
  StaticJsonBuffer<200> jBuffer;
  JsonObject& jObject = jBuffer.parseObject(data);

  id   = jObject["id"];
  int index = findElement();
  Serial.print("index:");
  Serial.println(index);
  if (index != 9999) {
    table[index][indexRelay1] = jObject["pin1"];
    table[index][indexRelay2] = jObject["pin2"];
    table[index][indexMode] = jObject["commode"];
    Serial.println("Data in the table CHANGED.");
    printOutTheTable();

    mojedata += "   ID: ";
    mojedata += id;
    mojedata += "   pin1: ";
    mojedata += table[index][indexRelay1];
    mojedata += "   pin2: ";
    mojedata += table[index][indexRelay2];
    mojedata += "   comMode: ";
    mojedata += table[index][indexMode];
  }
  else {
    Serial.print("\nID: ");
    Serial.print(id);
    Serial.println(" was not found in the table.");
  }
  data += mojedata;
  server.send(200, "text/plain", data);

  Serial.println("[WiFi]: Received PAYLOAD");
  Serial.println();
  Serial.println(data);
}

void registermode() { //receives sets the pMCU into register mode
  //{"registermode":0}
  String data = server.arg("plain");
  String mojedata = "";
  StaticJsonBuffer<200> jBuffer;
  JsonObject& jObject = jBuffer.parseObject(data);

  registerMode = jObject["registermode"];

  mojedata += "   registerMode: ";
  mojedata += registerMode;
  data += mojedata;
  server.send(200, "text/plain", data);

  Serial.println("[WiFi]: Received PAYLOAD");
  Serial.println();
  Serial.println(data);

  if (registerMode == true) {
    Serial.println("[LoRa]: Register mode ENTERED");
  }
  else {
    Serial.println("[LoRa]: Register mode END");
  }
}

bool dealWithMessage() {
  if (h == 0) {
    u8x8.clear();
  }
  char buffer[RH_RF95_MAX_MESSAGE_LEN];  //Buffer for replying to LoRa sensor message
  uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];  //Buffer for incoming LoRa messages
  uint8_t len = sizeof(buf);
  memset(buf, '\0', sizeof(buf));        //clear the buffer

  if (rf95.recv(buf, &len)) {
    digitalWrite(LED, LOW);
    Serial.print("[LoRa]: MsgRcvd: [");
    for(int i=0; i<len; i++)
      {
        Serial.print(buf[i]);
        Serial.print(" ");
      }
    Serial.print("]  ");
    //-----------------------------------
    Serial.print("Length: ");
    Serial.println(len);

    //---------------------------------------------------------------

     id = buf[0] << 6 | (buf[1] >> 2);
     rqst = buf[1] & B0000010;
    int offset = 30;//30
    int tmpWhole = ((buf[1] & B00000001) << 6) | (buf[2] >> 2) - offset; 
    int tmpDec = buf[2] & B00000011;
    int tmpDecField[4] = {0, 25, 50, 75};
     t = tmpWhole*100 + tmpDecField[tmpDec];
  
    int humWhole = buf[3] >> 1;
    int humDec = buf[3] & B00000001;
     h = humWhole*100 + humDec*50;
    int vltgWhole = buf[4] >> 5;
    int vltgDec = (buf[4] & B00011111)*40;
     voltage = vltgWhole*1000+vltgDec; 
    
    //---------------------------------------------------------------
    
      Serial.println();
      Serial.print("id: ");
      Serial.println(id);
      Serial.print("rqst: ");
      Serial.println(rqst);
      Serial.print("temp: ");
      Serial.println(t);
      Serial.print("hum: ");
      Serial.println(h);
      Serial.print("vltg: ");
      Serial.println(voltage);
    
    
    
    /*
    int msg[len]; //new field of int values
    for (int i = 0; i < len; i++) { //convert the message from char field to int field
      msg[i] = buf[i] - 48;
    }
*/
    rssi = rf95.lastRssi();
/*
    int pointer = 0;   //cannot swith the rows now, coz of message structure
    id = arrayToInt(pointer++, msg, 4);
    h = arrayToInt(pointer++, msg, 4);
    t = arrayToInt(pointer++, msg, 4);
    voltage = arrayToInt(pointer++, msg, 4);
    rqst = arrayToInt(pointer++, msg, 1);
    */
    
    if (checkTheTable(id, rqst)) {
      Serial.println("[pMCU]:Access granted.");
    }
    else {
      Serial.print("[pMCU]: ID: ");
      Serial.print(id);
      Serial.println(" not on the white list.");
      return false;
    }

    Serial.print("\nRssi: ");
    Serial.println(rssi);
    Serial.print("Rtr: ");
    Serial.println(rqst);
    Serial.print("Id:  ");
    Serial.println(id);
    Serial.print("Hum: ");
    Serial.println(h);
    Serial.print("Tmp: ");
    Serial.println(t);
    Serial.print("Vlt: ");
    Serial.println(voltage);

    //-------------------------------------------------------------------------------------
    //Show on OLED

    u8x8.setFont(u8x8_font_chroma48medium8_r);
    u8x8.setCursor(0, 2);
    //u8x8.drawString(0,1,"Hello World!");
    u8x8.print("Hum: ");
    u8x8.print(h);
    u8x8.println(" %");
    u8x8.print("Tmp: ");
    u8x8.print(t);
    u8x8.println(" C");
    u8x8.print("Vlt: ");
    u8x8.print(voltage);
    u8x8.print(" mV");

    //-----------------------------------------------------------------------------
    //SENDING back

    int index = findElement();
    int pin1 = table[index][indexRelay1];
    int pin2 = table[index][indexRelay2];
    int comMode = table[index][indexMode];

    sprintf(buffer, "%d%d%d%d", pin1, pin2, comMode, index + 1);
    sendLen = strlen(buffer);  //get the length of buffer

    rf95.send((uint8_t *) buffer, sendLen); //send back the message
    Serial.print("MsgSent: [");
    Serial.print(buffer);
    Serial.print("]\n\n");

    memset(buffer, '\0', sizeof(buffer));  //properly terminate the buffer (clear it)
    Serial.println("[LoRa]: Wait relay seetings sent to sensor");
    rf95.waitPacketSent();
    Serial.println("[LoRa]: Successful");
    //-------------------------------------------------------------------------------------

    sendLen = 0;
    digitalWrite(LED, HIGH);
  }
  return true;
}

void forwardDataToServer() {

  Serial.print("[WiFi]: connecting to ");
  Serial.println(host.c_str());

  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host.c_str(), httpPort)) {
    Serial.println("[WiFi]: connection to server failed ");
    return;
  }

  //JSON style------------------------------------
  DynamicJsonBuffer jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  root["sensor_id"] = id;
  root["tmp"] = t;
  root["hum"] = h;
  root["vltg"] = voltage;
  root["rssi"] = rssi;

  //root.printTo(stream);

  String JsonStream = "";
  root.printTo(JsonStream);
  String url = urlPrefix; 
        url += "/receiverecord";

  client.println("POST " + url + " HTTP/1.1");
  client.println("Host: 192.168.100.100");
  client.println("Cache-Control: no-cache");
  client.println("Content-Type: application/json");
  client.print("Content-Length: ");
  client.println(JsonStream.length());
  client.println();
  client.println(JsonStream);

  root.prettyPrintTo(JsonStream);
  Serial.println("POST " + url + " HTTP/1.1");
  Serial.println("Host: 192.168.100.100");
  Serial.println("Cache-Control: no-cache");
  Serial.println("Content-Type: application/json");
  Serial.print("Content-Length: ");
  Serial.println(JsonStream.length());
  Serial.println();
  Serial.println(JsonStream);
  Serial.println("\n");

  unsigned long timeout = millis();
  while (client.available() == 0) {
    if (millis() - timeout > 5000) {
      Serial.println("[WiFi]: >>> Client Timeout !");
      client.stop();
      return;
    }
  }

  // Read all the lines of the reply from server and print them to Serial
  //JSON is in the last line, so its enough to save only last line
  String line = "";
  while (client.available())
  {
    line = client.readStringUntil('\r');
    Serial.print(line);
  }
  /*  //  Serial.print(line);
      JsonObject& sendd = jsonBuffer.parseObject(line);
      //{"pin1":1,"pin2":0}
      pin1 = sendd["pin1"];
      pin2 = sendd["pin2"];
      Serial.print("\nDecoded_Msg:\n");
      Serial.print(pin1);
      Serial.print(pin2);
      Serial.print("\nEndOfMsg\n");

      Serial.println();
      Serial.println("closing connection");
  */
}


