#include <ETH.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <Ticker.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT
#define ETH_PHY_POWER 12

const char* wifi_ssid = "ssid";
const char* wifi_password = "passord";

static bool eth_connected = false;

volatile float temperature = 0;
volatile float pressure = 0;
volatile float humidity = 0;

boolean BME280_Sensor_State = false;

String website = "";

Ticker Ticker_ReadSensors;
Ticker Ticker_Service;

WebServer WebServer_Server(80);

Adafruit_BME280 BME280_Sensor;

void setup() {
  Serial.begin(115200); // RS232
  Wire.begin (13, 16);  // I²C Init
  pinMode (34, INPUT);  // User Button
  Ticker_ReadSensors.attach(15, ReadSensors);
  Ticker_Service.attach(1, Service);

  Serial.println("Starting...");

/*  WiFi.begin(wifi_ssid, wifi_password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP()); */

  WiFi.onEvent(EthEvent);
  ETH.begin();

  WebServer_Server.on("/", handleRoot);
  WebServer_Server.on("/metrics", handleMetrics);
  WebServer_Server.onNotFound(handleNotFound);
  WebServer_Server.begin();
  Serial.println("HTTP server started");

  if (! BME280_Sensor.begin(0x76)) {
      Serial.println("Could not find a valid BME280 sensor, check wiring!");
      while (1);
  }
  
  BME280_Sensor.setSampling(Adafruit_BME280::MODE_FORCED,
                            Adafruit_BME280::SAMPLING_X1, // temperature
                            Adafruit_BME280::SAMPLING_X1, // pressure
                            Adafruit_BME280::SAMPLING_X1, // humidity
                            Adafruit_BME280::FILTER_OFF);
}

/* Main Loop */

void loop() {
  WebServer_Server.handleClient();
}

/* Timer Events */

void Service() {
  Serial.print(".");
}

void ReadSensors() {
  BME280_Sensor.takeForcedMeasurement(); 
  temperature = BME280_Sensor.readTemperature();
  pressure = (BME280_Sensor.readPressure() / 100.0F);
  humidity = BME280_Sensor.readHumidity();
  Serial.print("\nTemperature: ");
  Serial.print(temperature);
  Serial.print(", Pressure: ");
  Serial.print(pressure);
  Serial.print(", Humidity: ");
  Serial.println(humidity);
}

/* Eth Interface */

void EthEvent(WiFiEvent_t event)
{
  switch (event) {
    case SYSTEM_EVENT_ETH_START:
      Serial.println("ETH Started");
      //set eth hostname here
      ETH.setHostname("esp32-poe-sensor");
      break;
    case SYSTEM_EVENT_ETH_CONNECTED:
      Serial.println("ETH Connected");
      break;
    case SYSTEM_EVENT_ETH_GOT_IP:
      Serial.print("ETH MAC: ");
      Serial.print(ETH.macAddress());
      Serial.print(", IPv4: ");
      Serial.print(ETH.localIP());
      if (ETH.fullDuplex()) {
        Serial.print(", FULL_DUPLEX");
      }
      Serial.print(", ");
      Serial.print(ETH.linkSpeed());
      Serial.println("Mbps");
      eth_connected = true;
      break;
    case SYSTEM_EVENT_ETH_DISCONNECTED:
      Serial.println("ETH Disconnected");
      eth_connected = false;
      break;
    case SYSTEM_EVENT_ETH_STOP:
      Serial.println("ETH Stopped");
      eth_connected = false;
      break;
    default:
      break;
  }
}

/* Webserver */
void handleRoot() {
  website = "";
  website += "<html><body><h1>Temperatur: ";
  website += temperature;
  website += " °C</h1><h1>Luftdruck: ";
  website += pressure;
  website += " hPa</h1><h1>rel. Luftfeuchte: ";
  website += humidity;
  website += " %</h1></body></html>";
  WebServer_Server.send(200, "text/html", website);
}

void handleNotFound() {
  WebServer_Server.send(404, "text/plain", "Not found!");
}

void handleMetrics() {
  website = "";
  website += "# HELP temperature The temperature measured in degree Celcius by the specified sensor.\n# TYPE temperature gauge\ntemperature{sensor=\"BME280\",address=\"0x76\"} ";
  website += temperature;
  website += "\n\n# HELP humidity The relative humidity measured in percent by the specified sensor.\n# TYPE humidity gauge\nhumidity{sensor=\"BME280\",address=\"0x76\"} ";
  website += humidity;
  website += "\n\n# HELP pressure The air pressure measured in hPa by the specified sensor.\n# TYPE pressure gauge\npressure{sensor=\"BME280\",address=\"0x76\"} ";
  website += pressure;
  website += "\n"; 
  WebServer_Server.send(200, "text/plain", website);
}
