#include <ESP8266WiFi.h>            // Library for WiFi
#include <ESP8266WebServer.h>       // Library for the web server
#include <ArduinoJson.h>            // Library for JSON processing
#include <OneWire.h>                // Library for DS18B20 sensor
#include <DallasTemperature.h>      // Library for DS18B20 sensor
#include "credentials.h"            // File with WiFi credentials

// Network Configurations
IPAddress ip(192,168,0,102);        // Set the board's IP configuration
IPAddress gateway(192,168,0,1);
IPAddress subnet(255,255,255,0);
 
// Web Server Configuration
ESP8266WebServer server(80);         //Define web-server on port 80

// DS18B20 Sensor Libraries Configuration
OneWire ourWire(4);                  //Set D2(GPIO-4) pin as OneWire bus
DallasTemperature sensors(&ourWire); 

// Global variables definition
float temp0;                         //Define variables to store temp readings
float temp1;
float temp2;
unsigned long previousMillis = 0;    //Temporal variable 
const long interval = 2000;          //Set minimal interval between readings

void setup() {
    Serial.begin(115200);
    delay(10);
    
    // Connect to WiFi network
    Serial.println(); Serial.println();
    Serial.print("Connecting to ");
    Serial.println(WLAN_SSID);
    
    WiFi.config(ip, gateway, subnet);
    WiFi.mode(WIFI_STA);
    WiFi.begin(WLAN_SSID, WLAN_PASSWORD);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    
    Serial.println();
    Serial.println("WiFi connected");
    Serial.println("IP address: "); 
    Serial.println(WiFi.localIP());
    
    sensors.begin();                      // Initialize DS18B20 sensors
    
    // Define server responses
    server.on("/reading", HTTP_GET, [](){
        read_sensor();
        
        char buff0[9];                    //Define character buffer variables to store converted values
        char buff1[9];
        char buff2[9];    
        dtostrf(temp0, 8, 4, buff0);      //Convert float values to string for printing 7 character + sign + NULL
        dtostrf(temp1, 8, 4, buff1);
        dtostrf(temp2, 8, 4, buff2);
        
        char webString[600];              //Define character variable for storing the HTML page
        snprintf(webString, 600,          //Write HTML page
"\
<html>\
  <head>\
    <meta http-equiv='refresh' content='5'/>\
    <title>DS18B20 Server</title>\
    <style>\
      body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }\
    </style>\
  </head>\
  <body>\
    <h1>Sensor Data</h1>\
    <p>Temperature 01: %s &#176;C</p>\
    <p>Temperature 02: %s &#176;C</p>\
    <p>Temperature 03: %s &#176;C</p>\
  </body>\
</html>\
", buff0, buff1, buff2);
        // Log to serial monitor
        Serial.println();
        Serial.println("Reporting Temp(0) " + String((int)temp0) + F(" °C"));
        Serial.println("Reporting Temp(1) " + String((int)temp1) + F(" °C"));
        Serial.println("Reporting Temp(2) " + String((int)temp2) + F(" °C"));
        // Send response
        server.send(200, "text/html", webString);
    });
    
    server.on("/reading.json", [](){
        read_sensor();
        
        StaticJsonDocument<500> jsonBuffer;             //Create JSON document
        JsonObject root = jsonBuffer.to<JsonObject>();  //Create JSON object
        root["temperature-probe0"] = temp0;             //Add values to elements
        root["temperature-probe1"] = temp1;
        root["temperature-probe2"] = temp2;
        
        String jsonString;                              
        serializeJson(jsonBuffer, jsonString);          //Serialize JSON for printing

        // Log to serial monitor
        Serial.println();
        Serial.println(jsonString);
        // Send response
        server.send(200, "application/json", jsonString);
    });

    server.begin();   //Start server
    Serial.println("Temp server started! Waiting for clients!");
    digitalWrite(LED_BUILTIN, HIGH);    //Turn the LED off
}

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

// Get sensor readings
void read_sensor() {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
        previousMillis = currentMillis;

        sensors.requestTemperatures();         //Request temp readings
        temp0 = sensors.getTempCByIndex(0);    //Request temp in C by index
        temp1 = sensors.getTempCByIndex(1);
        temp2 = sensors.getTempCByIndex(2);

        if (isnan(temp0) | isnan(temp1) | isnan(temp2)) {
            Serial.println("Failed to read from DS18B20 sensors!");
            return;
        }
    }
}