/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/ttgo-lora32-sx1276-arduino-ide/
*********/
#define WIFI
//Libraries for LoRa
#include <SPI.h>
#include <LoRa.h>

//Libraries for OLED Display
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <PubSubClient.h>

#include <WiFiClient.h>

//define the pins used by the LoRa transceiver module
#define SCK 5
#define MISO 19
#define MOSI 27
#define SS 18
#define RST 14
#define DIO0 26

//433E6 for Asia
//866E6 for Europe
//915E6 for North America
#define BAND 866E6

//OLED pins
#define OLED_SDA 4
#define OLED_SCL 15 
#define OLED_RST 16
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RST);

#include <WiFiClientSecure.h>
const char* ssid     = "Home";          // WiFi SSID
const char* password = "2Drittel%13579";              // WiFi Password

const char* mqttServer = "192.168.2.71";
const int mqttPort = 1883;
const char* clientID = "lora_esp_32";
const char* channelName = "/Drive/CMD/#";

long interval = 1000;       // Sende-Intervall in ms

WiFiClient MQTTclient;
PubSubClient client(MQTTclient);

const int relay = 22;
const int check = 23;

void callback(char* topic, byte* payload, unsigned int length) {
  //String payload_buff;
  //for (int i=0;i<length;i++) {
    //payload_buff = payload_buff+String((char)payload[i]);
  //}
  //Serial.println(payload_buff); // Print out messages.
  String line0;
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.println("] ");
  line0=topic;
 
  if (line0.endsWith("licht")) {   
    int x = payload[0]-'0';
    if (x==1){
      Serial.print("on ");
      digitalWrite(relay, LOW);
    }
    if (x==0){
      Serial.print("off ");
      digitalWrite(relay, HIGH);
    }
    Serial.println(x);
   }
  if (line0.endsWith("check")){
    int state = digitalRead(check);
    if (state==LOW){
      client.publish("/drive/check","ON");
      Serial.println("ON");
    } else{
      client.publish("/drive/check","OFF");
      Serial.println("OFF");
       
    }
  }
}
long lastReconnectAttempt = 0;

boolean reconnect() {
  if (client.connect(clientID)) {
    client.subscribe(channelName); // Subscribe to channel.
  }
  return client.connected();
}


char buffer[10];
int count = 0;
String LoRaData;

void setup() { 
  Serial.begin(115200);
  // relay
  pinMode(relay,OUTPUT);
  digitalWrite(relay,HIGH);
  // check
  pinMode(check,INPUT);
  
  //reset OLED display via software
  pinMode(OLED_RST, OUTPUT);
  digitalWrite(OLED_RST, LOW);
  delay(20);
  digitalWrite(OLED_RST, HIGH);
   //initialize OLED
  Wire.begin(OLED_SDA, OLED_SCL);
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c, false, false)) { // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
 //initialize Serial Monitor
  display.clearDisplay();
  display.setRotation(2);
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(0,0);
  display.print("LORA low power sender ");
  display.display();
  

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    
    display.clearDisplay();
    display.setCursor(0,0);
    display.print("Wifi search ");
    display.setCursor(30,10);
    int i = count % 2;
    if (i == 0){
      display.print("/");
    } 
    else {
      display.print("\\");
    }
    count += 1;
    
    display.display();
    delay(100);
  }

  Serial.println();
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.println( WiFi.localIP().toString());
  
  
 
 
  //SPI LoRa pins
  SPI.begin(SCK, MISO, MOSI, SS);
  //setup LoRa transceiver module
  LoRa.setPins(SS, RST, DIO0);

  if (!LoRa.begin(BAND)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
  Serial.println("LoRa Initializing OK!");
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(0,0);
  display.print("LORA low power sender ");
  display.display();
  client.setServer(mqttServer, mqttPort); // Connect to PubNub.
  client.setCallback(callback);
  
}


void loop() {

  if (!client.connected()) {
    long now = millis();
    if (now - lastReconnectAttempt > 5000) { // Try to reconnect.
      lastReconnectAttempt = now;
      if (reconnect()) { // Attempt to reconnect.
        lastReconnectAttempt = 0;
      }
    }
  } else { // Connected.
    client.loop();
  }

  //try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    //received a packet
    Serial.print("Received packet ");

    //read packet
    while (LoRa.available()) {
      LoRaData = LoRa.readString();
      Serial.print(LoRaData);
      if (LoRaData.startsWith("!") == true)
      {
         client.publish("/drive/find","detect");
      } else
      {
        LoRaData.toCharArray(buffer,LoRaData.length());
        client.publish("/drive/volt",buffer);
      }
     
    }

    //print RSSI of packet
    int rssi = LoRa.packetRssi();
    Serial.print(" with RSSI ");    
    Serial.println(rssi);
    String b;
    b = String(rssi);
    b.toCharArray(buffer,b.length()+1);
    client.publish("/drive/rssi",buffer);
    
    
   // Dsiplay information
   display.clearDisplay();
   display.setCursor(0,0);
   display.print("LORA  ");
   display.setCursor(30,0);
   display.print(WiFi.localIP().toString());
   display.setCursor(0,20);
   display.print("Received packet:");
   display.setCursor(0,30);
   display.print(LoRaData);
   display.setCursor(0,40);
   display.print("RSSI:");
   display.setCursor(30,40);
   display.print(rssi);
   display.display();   
  }

 
}
