#include <WiFi.h>
#include <ESP32WebServer.h>
#include "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
// jfs Wemos lolin32
// jfs Heltec WiFi kit 32 (weisses Board)
// #define HELTEC
//#define DEBUG
//#define _DS1631
//#define _SHT3x
#define _ADS1115
//#define _NTC
//#define SERVER

#ifdef _NTC
  #include "ntc_support.h"
#endif
#ifdef _DS1631
#include <DS1631.h>
  DS1631 Temp1(0); 
#endif  
#ifdef _SHT3x
#include <SHT3x.h>
  SHT3x Sensor(0x44); 
#endif    
#ifdef _ADS1115
  // 0x48 addr to gnd
  // 0x49 addr to vdd
  // 0x4A addr to sda
  // 0x4B addr to scl
  #include <Adafruit_ADS1015.h>
  Adafruit_ADS1115 ads(0x48);
  float Voltage = 0.0;
#endif

#ifdef SERVER
ESP32WebServer server(80);
#endif

// Initialize the OLED display using Wire library
#ifdef HELTEC
SSD1306  display(0x3c, 4, 15);
#else
SSD1306  display(0x3c, 5, 4);
#endif

//SSD1306  display(0x3c, 5, 4);  //vorher 5,4 für wemos | Heltec WiFi Kit 32 4,15

const int mxSize=4;
String ssids[mxSize] ={"GAST","pipanet","FRITZ!Box Gastzugang","WLAN-DE8245"};
String ssidp[mxSize] = {"passatvr6","passatvr6","praxis123","4955065570896956"};
boolean conok =false;

void netfound(int i){
     display.clear();
     display.setColor(BLACK);
     display.fillRect(0, 0, 128, 10);
     display.setColor(WHITE);
     display.drawString(0,0,String(i));
     display.drawString(20,0,"networks found");
     display.display(); 
}

boolean init_wifi(){
    boolean ok = false;
    WiFi.mode(WIFI_STA);
    WiFi.disconnect();
    delay(100);
    int n = WiFi.scanNetworks();
    Serial.println("scan done");
    if (n == 0) {
        Serial.println("no networks found");
        netfound(0);
    } else {
        Serial.print(n);
        Serial.println(" networks found");
        netfound(n);        
        for (int i = 0; i < n; ++i) {
            for (int p=0;p<mxSize;p++){
              if (WiFi.SSID(i).equals(ssids[p])){
                String pp = ssidp[p];
                String ss = WiFi.SSID(i);
                WiFi.begin(ss.c_str(), pp.c_str());
                i=n;
                ok = true;
              }
            }
            delay(10);
        }
    }     
    return ok;
}

#ifdef _DS1631
void init_ds1631(){
int config = Temp1.readConfig();
  Temp1.writeConfig(13);  // Set to 12-bit, 1-shot mode
  config = Temp1.readConfig();    
}
#endif




void setup() {
  //für Wiufi Kit 32
#ifdef HELTEC
  pinMode(16,OUTPUT); digitalWrite(16, LOW); delay(50); digitalWrite(16, HIGH);
#endif 
#ifdef _NTC
    ThermistorPin = 34;
    adcMax = 4095.0; // ADC resolution 12-bit (0-4095)
    Vs = 3.3;        // supply voltage
#endif
  Serial.begin(115200); 
  Serial.println("Starting");

  display.flipScreenVertically();
  display.clear();
  display.drawString(0, 0, "Starting...");
  display.display();
  while (!init_wifi()){
    delay(200);  
  }
  display.drawString(0, 10, "Connecting to WiFi...");
  display.display();
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
  }
  display.drawString(0, 20, "\nWiFi connected, IP address: "); 
  display.drawString(0, 30, WiFi.localIP().toString());
  display.display();

#ifdef SERVER
  server.onNotFound(handleNotFound);
  server.on("/", menu);
  server.on("/print", sendToPrinter);
#endif
#ifdef DEBUG  
  i2c_scanner();
  delay(2000);
#endif  
#ifdef _DS1631
  init_ds1631();
#endif  
#ifdef _ADS1115
  ads.begin();
  //ads.setGain(GAIN_FOUR); +- 1.024
#endif  


  delay(2000);
#ifdef SERVER
  server.begin();
  display.drawString(0, 40, "HTTP started on port 80");
  display.display();
#endif
}



void loop() {
#ifdef SERVER  
  // deals with the Wifi clients and responds, calls the callbacks, etc. ...
  server.handleClient();
#endif
  delay(1);

#ifdef _DS1631  
  float tist=0;
  tist = Temp1.readTempOneShot();
  Serial.print("Temp: ");
  Serial.print(tist);
#endif  
#ifdef _SHT3x
  Sensor.UpdateData();
  Serial.print(Sensor.GetTemperature()); //Celsius
  Serial.write("\xC2\xB0"); //The Degree symbol
  Serial.print("C");
  Serial.print(" | "); 
  Serial.print(Sensor.GetRelHumidity());
  Serial.print("%");
  Serial.print(" | ");
  Serial.print(Sensor.GetAbsHumidity()); //Torr by default
  Serial.print(" Torr");
  Serial.print(" | ");
  Serial.print(Sensor.GetAbsHumidity(SHT3x::psi)); //Torr by default
  Serial.print(" psi");
  Serial.print(" | ");
  Serial.print(Sensor.GetAbsHumidity(SHT3x::Pa)); //Torr by default
  Serial.println(" Pa");
  //And other...
  //Serial.print(" Tolerance: ±");
  //Serial.print(Sensor.GetAbsHumTolerance(SHT3x::mH2O));
  //Serial.print(" mH2O");  
#endif  

#ifdef _ADS1115
  String s;
  
  int16_t adc0;
  int16_t adc1;
  int16_t adc2;
  int16_t adc3;  
  int16_t d1;

  adc0 = ads.readADC_SingleEnded(0);
  adc1 = ads.readADC_SingleEnded(1);
  adc2 = ads.readADC_SingleEnded(2);
  adc3 = ads.readADC_SingleEnded(3);
  d1 = ads.readADC_Differential_0_1();
  
  s="<";
  display.clear();
  Voltage = (adc0 * 0.1875)/1000;
  display.drawString(0,10," "+String(Voltage,3));
  s+= String(Voltage,3);
   Voltage = (adc1 * 0.1875)/1000;
  s+= '|';
  s+= String(Voltage,3);
  display.drawString(0,20," "+String(Voltage,3));
   Voltage = (adc2 * 0.1875)/1000;
   s+= '|';
  s+= String(Voltage,3);
  display.drawString(0,30," "+String(Voltage,3));
   Voltage = (adc3 * 0.1875)/1000;
    s+= '|';
  s+= String(Voltage,3);
  display.drawString(0,40," "+String(Voltage,3));
    Voltage = (d1 * 0.1875)/1000;
   s+= '|';
  s+= String(Voltage,3);
  display.drawString(0,50," "+String(Voltage,3));
   s+= '|';
  s+= String(Voltage,3);
  s+='|>';
  Serial.println(s);
  delay(10);
  display.display();
  
 #ifdef DEBUG      
  Voltage = (adc0 * 0.1875)/1000;
  Serial.print("AIN0: "); 
  Serial.print(adc0);
  Serial.print("\tVoltage: ");
  Serial.println(Voltage, 7); 
  Voltage = (adc1 * 0.1875)/1000;
  Serial.print("AIN1: "); 
  Serial.print(adc1);
  Serial.print("\tVoltage: ");
  Serial.println(Voltage, 7); 
  Voltage = (adc2 * 0.1875)/1000;
  Serial.print("AIN2: "); 
  Serial.print(adc2);
  Serial.print("\tVoltage: ");
  Serial.println(Voltage, 7); 
  Voltage = (adc3 * 0.1875)/1000;
  Serial.print("AIN3: "); 
  Serial.print(adc3);
  Serial.print("\tVoltage: ");
  Serial.println(Voltage, 7);  
 #endif
#endif

#ifdef _NTC
  double Vout, Rt = 0;
  double T, Tc, Tf = 0;
  double adc = 0;
  adc = analogRead(ThermistorPin);
  adc = ADC_LUT[(int)adc];
  Vout = adc * Vs/adcMax;
  Rt = R1 * Vout / (Vs - Vout);

  T = 1/(1/To + log(Rt/Ro)/Beta);    // Temperature in Kelvin
  Tc = T - 273.15;                   // Celsius
  Tf = Tc * 9 / 5 + 32;              // Fahrenheit
  Serial.println(Tc);
  //Serial.print(" Thermistor: ");
  //Serial.println(get_thermistor());
#endif

  delay(1);
  
}



#ifdef SERVER
void menu() {
  Serial.println("Menu...");
  String message = "<h1>Thermal Printer</h1>";
  message += "<form action=\"/print\" id=\"frm\"><input type=\"submit\" value=\"Send to printer\"  style=\"height:200px;width:200px\"> </form>";
  message += "<textarea rows=\"10\" cols=\"50\" name=\"text\" form=\"frm\"> Enter text here...</textarea>";
  server.send(200, "text/html", message);
}
void sendToPrinter() {
  // we expect one and only 1 var which is the text to print
  String var = server.argName(0);
  String value = server.arg(0);
  if (var == "text") {
    Serial.print("Received to print: "); Serial.println(value);
    //serialPrinter.println(value);
    cutPaper();   
  } 
  else Serial.println("UNKNOWN var " + var );
  menu();
}

void cutPaper() {
  //extra empty rows to cut below the latest text
  //serialPrinter.println("\n\n\n");
  byte cutCmd[] = {0x1B, 0x69, 0x0A};
  //serialPrinter.write(cutCmd, sizeof(cutCmd));
}

void handleNotFound() {
  String message = "File Not Found\n\n";
  message += "URI: " + server.uri();
  message += "\nMethod: " + (server.method() == HTTP_GET)?" GET":" POST";
  message += "\nArguments: " + server.args();
  message += "\n";
  for (uint8_t i=0; i<server.args(); i++){
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
}
#endif

#ifdef _NTC
double get_thermistor(){
int sensorPin =36;
int bitwertNTC = 0;
long widerstand1 = 100000;
int bWert =3950;                           // B- Wert vom NTC 3950
double widerstandNTC = 0;
double kelvintemp = 273.15;
double umgebungstemp = 17.5;
double Tn = kelvintemp +umgebungstemp;
double TKelvin = 0;
double T = 0;

    bitwertNTC = analogRead(sensorPin);
    widerstandNTC = widerstand1*(((double)bitwertNTC/4096)/(1-((double)bitwertNTC/4096)));
    TKelvin = 1/((1/Tn)+((double)1/bWert)*log((double)widerstandNTC/widerstand1));
    T=TKelvin-kelvintemp;

 
 #ifdef DEBUG    
    Serial.println("Sensormessung: ");
    Serial.print("Analog: ");              //
    Serial.println(bitwertNTC);              //
    Serial.print("NTC- Widerstand: ");     //Gebe die ermittelten Werte aus
    Serial.println(widerstandNTC);           //
    Serial.print("Temperatur: ");          //Gebe die ermittelten Werte aus
    Serial.println(T);                       //
  #endif    
    return(T);
}
#endif

void i2c_scanner(){
   byte error, address;
   int nDevices;
  for(address = 1; address < 127; address++ ) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0) {
      nDevices++;
      Serial.print("Device found @ 0x");
      if (address<16) Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");
      }
    else if (error==4) 
    {
      Serial.print("Unknow error @ 0x");
      if (address<16) Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0) {
    Serial.println("No I2C devices found\n");    
    #if OLED_DISPLAY
        display.drawString(0, 23 , "No I2C devices found");
        display.display();
    #endif
  } else {
    Serial.println("done\n");
}


}
