// convert epochtime to JavaScripte Date object
function epochToJsDate(epochTime) {
  return new Date(epochTime * 1000);
}

// convert time to human-readable format YYYY/MM/DD HH:MM:SS
function epochToDateTime(epochTime) {
  const epochDate = new Date(epochToJsDate(epochTime));
  const dateTime =
    epochDate.getFullYear() +
    "/" +
    ("00" + (epochDate.getMonth() + 1)).slice(-2) +
    "/" +
    ("00" + epochDate.getDate()).slice(-2) +
    " " +
    ("00" + epochDate.getHours()).slice(-2) +
    ":" +
    ("00" + epochDate.getMinutes()).slice(-2) +
    ":" +
    ("00" + epochDate.getSeconds()).slice(-2);

  return dateTime;
}

// function to plot values on charts
function plotValues(chart, timestamp, value) {
  const x = epochToJsDate(timestamp).getTime();
  const y = Number(value);
  if (chart.series[0].data.length > 40) {
    chart.series[0].addPoint([x, y], true, true, true);
  } else {
    chart.series[0].addPoint([x, y], true, false, true);
  }
}

// DOM elements
const loginElement = document.querySelector("#login-form");
const contentElement = document.querySelector("#content-sign-in");
const userDetailsElement = document.querySelector("#user-details");
const authBarElement = document.querySelector("#authentication-bar");
const deleteButtonElement = document.getElementById("delete-button");
const deleteModalElement = document.getElementById("delete-modal");
const deleteDataFormElement = document.querySelector("#delete-data-form");
const viewDataButtonElement = document.getElementById("view-data-button");
const hideDataButtonElement = document.getElementById("hide-data-button");
const tableContainerElement = document.querySelector("#table-container");
const chartsRangeInputElement = document.getElementById("charts-range");
const loadDataButtonElement = document.getElementById("load-data");
const cardsCheckboxElement = document.querySelector(
  "input[name=cards-checkbox]"
);
const gaugesCheckboxElement = document.querySelector(
  "input[name=gauges-checkbox]"
);
const chartsCheckboxElement = document.querySelector(
  "input[name=charts-checkbox]"
);

var downloadBtn = document.querySelector("#download");

// DOM elements for sensor readings
const cardsReadingsElement = document.querySelector("#cards-div");
const gaugesReadingsElement = document.querySelector("#gauges-div");
const chartsDivElement = document.querySelector("#charts-div");
const tempElement0 = document.getElementById("temperature0");
const tempElement1 = document.getElementById("Lux");
const tempHumidity = document.getElementById("humidity"); //n
const updateElement = document.getElementById("lastUpdate");

// MANAGE LOGIN/LOGOUT UI
const setupUI = (user) => {
  if (user) {
    //toggle UI elements
    loginElement.style.display = "none";
    contentElement.style.display = "block";
    authBarElement.style.display = "block";
    userDetailsElement.style.display = "block";
    userDetailsElement.innerHTML = user.email;

    // get user UID to get data from database
    const uid = user.uid;
    console.log(uid);

    // Database paths (with user UID)
    const dbPath = "UsersData/" + uid.toString() + "/readings";
    const chartPath = "UsersData/" + uid.toString() + "/charts/range";
    const namePath = "UsersData/" + uid.toString() + "/email";

    // Database references
    const dbRef = firebase.database().ref(dbPath);
    const chartRef = firebase.database().ref(chartPath);
    const nameRef = firebase.database().ref(namePath);

    nameRef.set(user.email);

    // CHARTS
    // Number of readings to plot on charts
    var chartRange = 0;
    // Get number of readings to plot saved on database (runs when the page first loads and whenever there's a change in the database)
    chartRef.on("value", (snapshot) => {
      chartRange = Number(snapshot.val());
      console.log(chartRange);
      // Delete all data from charts to update with new values when a new range is selected
      chartT0.destroy();
      chartH.destroy();
      chartT1.destroy();
      // Render new charts to display new range of data
      chartT0 = createDryTemperatureChart();
      chartH = createHumidityChart();
      chartT1 = createLuxChart(); //yet to create
      // Update the charts with the new range
      // Get the latest readings and plot them on charts (the number of plotted readings corresponds to the chartRange value)
      dbRef
        .orderByKey()
        .limitToLast(chartRange)
        .on("child_added", (snapshot) => {
          const jsonData = snapshot.toJSON(); // example: {temperature: 25.02, humidity: 50.20, pressure: 1008.48, timestamp:1641317355}
          // Save values on variables
          const temperature0 = jsonData.temperature0;
          const Lux = jsonData.temperature1;
          const humidity = jsonData.humidity; //n
          const timestamp = jsonData.timestamp;
          // Plot the values on the charts
          plotValues(chartT0, timestamp, temperature0);
          plotValues(chartH, timestamp, humidity);
          plotValues(chartT1, timestamp, Lux);
          //n chart a regarder
        });
    });

    // Update database with new range (input field)
    chartsRangeInputElement.onchange = () => {
      chartRef.set(chartsRangeInputElement.value);
    };

    //CHECKBOXES
    // Checbox (cards for sensor readings)
    cardsCheckboxElement.addEventListener("change", (e) => {
      if (cardsCheckboxElement.checked) {
        cardsReadingsElement.style.display = "block";
      } else {
        cardsReadingsElement.style.display = "none";
      }
    });
    // Checbox (gauges for sensor readings)
    gaugesCheckboxElement.addEventListener("change", (e) => {
      if (gaugesCheckboxElement.checked) {
        gaugesReadingsElement.style.display = "block";
      } else {
        gaugesReadingsElement.style.display = "none";
      }
    });
    // Checbox (charta for sensor readings)
    chartsCheckboxElement.addEventListener("change", (e) => {
      if (chartsCheckboxElement.checked) {
        chartsDivElement.style.display = "block";
      } else {
        chartsDivElement.style.display = "none";
      }
    });

    // CARDS
    // Get the latest readings and display on cards
    dbRef
      .orderByKey()
      .limitToLast(1)
      .on("child_added", (snapshot) => {
        const jsonData = snapshot.toJSON(); // example: {temperature: 25.02, humidity: 50.20, pressure: 1008.48, timestamp:1641317355}
        const temperature0 = jsonData.temperature0;
        const Lux = jsonData.temperature1;
        const humidity = jsonData.humidity; //n
        const timestamp = jsonData.timestamp;
        // Update DOM elements
        tempElement0.innerHTML = temperature0;
        tempElement1.innerHTML = Lux;
        tempHumidity.innerHTML = humidity; //n

        updateElement.innerHTML = epochToDateTime(timestamp);
      });

    // GAUGES
    // Get the latest readings and display on gauges
    dbRef
      .orderByKey()
      .limitToLast(1)
      .on("child_added", (snapshot) => {
        const jsonData = snapshot.toJSON(); // example: {temperature: 25.02, humidity: 50.20, pressure: 1008.48, timestamp:1641317355}
        const temperature0 = jsonData.temperature0;

        const humidity = jsonData.humidity;
        const Lux = jsonData.temperature1;

        const timestamp = jsonData.timestamp;
        // Update DOM elements
        const gaugeT0 = createDryTemperatureGauge();
        const gaugeLux = createLuxGauge();
        const gaugeH = createHumidityGauge();

        gaugeT0.value = temperature0;
        gaugeLux.value = Lux;
        gaugeH.value = humidity;

        updateElement.innerHTML = epochToDateTime(timestamp);
      });

    // DELETE DATA
    // Add event listener to open modal when click on "Delete Data" button
    deleteButtonElement.addEventListener("click", (e) => {
      console.log("Remove data");
      e.preventDefault;
      deleteModalElement.style.display = "block";
    });

    // Add event listener when delete form is submited
    deleteDataFormElement.addEventListener("submit", (e) => {
      // delete data (readings)
      dbRef.remove();
    });

    // TABLE
    var lastReadingTimestamp; //saves last timestamp displayed on the table
    // Function that creates the table with the first 100 readings
    function createTable() {
      // append all data to the table
      var firstRun = true;
      dbRef
        .orderByKey()
        .limitToLast(100)
        .on("child_added", function (snapshot) {
          if (snapshot.exists()) {
            const jsonData = snapshot.toJSON();
            console.log(jsonData);
            /* var temperature = jsonData.temperature;
            var humidity = jsonData.humidity;
            var pressure = jsonData.pressure; */
            const temperature0 = jsonData.temperature0;
            const Lux = jsonData.temperature1;
            const humidity = jsonData.humidity;
            const timestamp = jsonData.timestamp;
            var content = "";
            content += "<tr>";
            content += "<td>" + epochToDateTime(timestamp) + "</td>";
            /* content += '<td>' + temperature + '</td>';
            content += '<td>' + humidity + '</td>';
            content += '<td>' + pressure + '</td>'; */
            content += "<td>" + temperature0 + "</td>";
            content += "<td>" + humidity + "</td>";
            content += "<td>" + Lux + "</td>";
            content += "</tr>";
            $("#tbody").prepend(content);
            // Save lastReadingTimestamp --> corresponds to the first timestamp on the returned snapshot data
            if (firstRun) {
              lastReadingTimestamp = timestamp;
              firstRun = false;
              console.log(lastReadingTimestamp);
            }
          }
        });
    }

    // append readings to table (after pressing More results... button)
    function appendToTable() {
      const dataList = []; // saves list of readings returned by the snapshot (oldest-->newest)
      const reversedList = []; // the same as previous, but reversed (newest--> oldest)
      console.log("APEND");
      dbRef
        .orderByKey()
        .limitToLast(100)
        .endAt(lastReadingTimestamp)
        .once("value", function (snapshot) {
          // convert the snapshot to JSON
          if (snapshot.exists()) {
            snapshot.forEach((element) => {
              const jsonData = element.toJSON();
              dataList.push(jsonData); // create a list with all data
            });
            lastReadingTimestamp = dataList[0].timestamp; //oldest timestamp corresponds to the first on the list (oldest --> newest)
            reversedList = dataList.reverse(); // reverse the order of the list (newest data --> oldest data)

            var firstTime = true;
            // loop through all elements of the list and append to table (newest elements first)
            reversedList.forEach((element) => {
              if (firstTime) {
                // ignore first reading (it's already on the table from the previous query)
                firstTime = false;
              } else {
                //var temperature = element.temperature;
                const temperature0 = element.temperature0;
                const Lux = element.Lux;
                const humidity = element.humidity;
                const timestamp = element.timestamp;
                var content = "";
                content += "<tr>";
                content += "<td>" + epochToDateTime(timestamp) + "</td>";
                content += "<td>" + temperature0 + "</td>";
                content += "<td>" + Lux + "</td>";
                content += "<td>" + humidity + "</td>";
                content += "</tr>";
                $("#tbody").append(content);
              }
            });
          }
        });
    }

    viewDataButtonElement.addEventListener("click", (e) => {
      // Toggle DOM elements
      tableContainerElement.style.display = "block";
      viewDataButtonElement.style.display = "none";
      hideDataButtonElement.style.display = "inline-block";
      loadDataButtonElement.style.display = "inline-block";
      createTable();
    });

    //***************DOWNLOAD BUTTON*******************

    function tableToCSV() {
      // Variable to store the final csv data
      var csv_data = [];
      csv_data.push("sep=,");
      // Get each row data
      const rows = document.getElementsByTagName("tr");
      for (var i = 0; i < rows.length; i++) {
        // Get each column data
        const cols = rows[i].querySelectorAll("td,th");

        // Stores each csv row data
        var csvrow = [];
        for (var j = 0; j < cols.length; j++) {
          // Get the text data of each cell of
          // a row and push it to csvrow
          csvrow.push(cols[j].innerHTML);
        }

        // Combine each column value with comma
        csv_data.push(csvrow.join(","));
      }
      // combine each row data with new line character
      csv_data = csv_data.join("\n");

      downloadCSVFile(csv_data);
      /* We will use this function later to download
        the data in a csv file downloadCSVFile(csv_data);
        */
    }

    function downloadCSVFile(csv_data) {
      // Create CSV file object and feed our csv_data into it
      const CSVFile = new Blob([csv_data], {
        type: "text/csv",
      });

      // Create to temporary link to initiate
      // download process
      const temp_link = document.createElement("a");

      // Download csv file
      temp_link.download = "measurement_history_solar_dryer.csv";
      const url = window.URL.createObjectURL(CSVFile);
      temp_link.href = url;

      // This link should not be displayed
      temp_link.style.display = "none";
      document.body.appendChild(temp_link);

      // Automatically click the link to trigger download
      temp_link.click();
      document.body.removeChild(temp_link);
    }

    downloadBtn.addEventListener("click", tableToCSV);

    //***************DOWNLOAD BUTTON*******************

    loadDataButtonElement.addEventListener("click", (e) => {
      appendToTable();
    });

    hideDataButtonElement.addEventListener("click", (e) => {
      tableContainerElement.style.display = "none";
      viewDataButtonElement.style.display = "inline-block";
      hideDataButtonElement.style.display = "none";
    });

    // IF USER IS LOGGED OUT
  } else {
    // toggle UI elements
    loginElement.style.display = "block";
    authBarElement.style.display = "none";
    userDetailsElement.style.display = "none";
    contentElement.style.display = "none";
  }
};

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>ESP Datalogging Firebase App</title>

    <!-- include Firebase SDK -->
    <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/8.8.1/firebase-auth.js"></script>
    <script src="https://www.gstatic.com/firebasejs/8.8.1/firebase-database.js"></script>

    <script>
      // Your web app's Firebase configuration
      const firebaseConfig = {
     apiKey: "AIzaSyD5QY8FTrFuZa6U6g4u7xTYLE1Tm4PCO_Q",
     authDomain: "thn-sensor.firebaseapp.com",
     databaseURL: "https://thn-sensor-default-rtdb.asia-southeast1.firebasedatabase.app",
     projectId: "thn-sensor",
     storageBucket: "thn-sensor.appspot.com",
     messagingSenderId: "555617789996",
     appId: "1:555617789996:web:83ffa25dc12f5861fbc989"
     };



      // Initialize firebase
      firebase.initializeApp(firebaseConfig);

      // Make auth and database references
      const auth = firebase.auth();
      const db = firebase.database();

    </script>

    <!-- include highchartsjs to build the charts-->
    <script src="https://code.highcharts.com/highcharts.js"></script>
    <!-- include to use jquery-->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <!--include icons from fontawesome-->
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
    <!-- include Gauges Javascript library-->
    <script src="https://cdn.rawgit.com/Mikhus/canvas-gauges/gh-pages/download/2.1.7/all/gauge.min.js"></script>

    <!--reference for favicon-->
    <link rel="icon" type="image/png" href="favicon.png">
    <!--reference a stylesheet-->
    <link rel="stylesheet" type="text/css" href="style.css">

  </head>

  <body>

    <!--TOP BAR-->
    <div class="topnav">
      <img src="img/valogo.jpg" alt="logo" />
      <h1> DRYER UNIT_5<i class="fas fa-clipboard-list"></i></h1>
    </div>

        <!--AUTHENTICATION BAR (USER DETAILS/LOGOUT BUTTON)-->
        <div id="authentication-bar" style="display: none;">
          <p><span id="authentication-status">User logged in</span>
            <span id="user-details">USEREMAIL</span>
            <a href="/" id="logout-link">(logout)</a>
          </p>
        </div>
    
        <!--LOGIN FORM-->
        <form id="login-form" style="display: none;">
          <div class="form-elements-container">
            <label for="input-email"><b>Email</b></label>
            <input type="text" placeholder="Enter Username" id="input-email" required>
    
            <label for="input-password"><b>Password</b></label>
            <input type="password" placeholder="Enter Password" id="input-password" required>
    
            <button type="submit" id="login-button">Login</button>
            <p id="error-message" style="color:red;"></p>
          </div>
        </form>
    
        <!--CONTENT (SENSOR READINGS)-->
        <div class="content-sign-in" id="content-sign-in" style="display: none;">
    
          <!--LAST UPDATE-->
          <p><span class ="date-time">Last update: <span id="lastUpdate"></span></span></p>
          <p>
          <p><span class ="informations"> Temperature has a precision of ±1°C and humidity has a ±5% precision </span></p>
          <p>
            Card: <input type="checkbox" id="cards-checkbox" name="cards-checkbox" checked>
            Gauge: <input type="checkbox" id="gauges-checkbox" name="gauges-checkbox" checked>
            Chart: <input type="checkbox" id="charts-checkbox" name="charts-checkbox" unchecked>
          </p>
          <div id="cards-div">
            <div class="cards">
              <!--TEMPERATURE-->
              <div class="card">
                <p><i class="fas fa-thermometer-half" style="color:#fff200;"></i> TEMPERATURE</p>
                <p><span class="reading"><span id="temperature0"></span> &deg;C</span></p>
              </div>
              <!--HUMIDITY-->
              <div class="card">
                <p><i class="fas fa-tint" style="color:#00add6;"></i> HUMIDITY</p>
                <p><span class="reading"><span id="humidity"></span> &percnt;</span></p>
              </div>
              <!--LIGHT INTENSITY-->
              <div class="card">
                <p><i class="fas fa-lightbulb" style="color:#ff9100;"></i> LIGHT INTENSITY</p>
                <p><span class="reading"><span id="Lux"></span>lx</span></p>
              </div>
            </div>
          </div>
          <!--GAUGES-->
          <div id ="gauges-div">
            <div class="cards">
              <!--TEMPERATURE-->
              <div class="card">
                <canvas id="gauge-dry-temperature"></canvas>
              </div>
              <!--HUMIDITY-->
              <div class="card">
                <canvas id="gauge-humidity"></canvas>
              </div>
              <!--LIGHT INTENSITY-->
              <div class="card">
                <canvas id="gauge-Lux"></canvas>
              </div>
            </div>
          </div>
    
          <!--CHARTS-->
          <div id="charts-div" style="display:none">
            <!--SET NUMBER OF READINGS INPUT FIELD-->
            <div>
              <p> Number of readings: <input type="number" id="charts-range"></p>
            </div>
            <!--TEMPERATURE-CHART-->
            <div class="cards">
              <div class="card">
                <p><i class="fas fa-thermometer-half" style="color:#fff200;"></i> TEMPERATURE CHART</p>
                <div id="chart-dry-temperature" class="chart-container"></div>
              </div>
            </div>
            <!--HUMIDITY-CHART-->
            <div class="cards">
              <div class="card">
                <p><i class="fas fa-tint" style="color:#00add6;"></i> HUMIDITY CHART</p>
                <div id="chart-humidity" class="chart-container"></div>
              </div>
            </div>
            <!--LUX-CHART-->
            <div class="cards">
              <div class="card">
                <p><i class="fas fa-lightbulb" style="color:#ff9100;"></i> LUX CHART</p>
                <div id="chart-lux" class="chart-container"></div>
              </div>
            </div>
          </div>
    
        <!--BUTTONS TO HANDLE DATA-->
        <p>
          <!--View data button-->
          <button id="view-data-button">View all data</button>
          <!--Hide data button-->
          <button id="hide-data-button" style= "display:none;">Hide data</button>
          <!--Delete data button-->
          <button id="delete-button" class="deletebtn">Delete data</button>
        </p>
        <!--Modal to delete data-->
        <div id="delete-modal" class="modal" sytle="display:none">
          <span onclick = "document.getElementById('delete-modal').style.display='none'" class="close" title="Close Modal">×</span>
          <form id= "delete-data-form" class="modal-content" action="/">
            <div class="container">
              <h1>Delete Data</h1>
              <p>Are you sure you want to delete all data from database?</p>
              <div class="clearfix">
                <button type="button" onclick="document.getElementById('delete-modal').style.display='none'" class="cancelbtn">Cancel</button>
                <button type="submit" onclick="document.getElementById('delete-modal').style.display='none'" class="deletebtn">Delete</button>
              </div>
            </div>
          </form>
        </div>
    
        <!--TABLE WITH ALL DATA-->
        <div class ="cards">
          <div class="card" id="table-container" style= "display:none;">
            <table id="readings-table">
                <tr id="theader">
                  <th>Timestamp</th>
                  <th>Temperature (ºC)</th>
                  <th>Hum (%)</th>
            <th>Light Intensity</th>  
                </tr>
                <tbody id="tbody">
                </tbody>
            </table>
            <p>
              <button id="load-data" style= "display:none;">More results...</button>
              <button id="download" >Download CSV</button>
            </p>
          </div>
        </div>
    
      </div>
    
        <!--INCLUDE JS FILES-->
        <script src="scripts/auth.js"></script>
        <script src="scripts/charts-definition.js"></script>
        <script src="scripts/gauge-defination.js"></script>
        <script src="scripts/index.js"></script>
    
      </body>
    
    </html>
html {
    font-family: Verdana, Geneva, Tahoma, sans-serif;
    display: inline-block;
    text-align: center;
}

body {
    margin: 0;
    width: 100%;
}

.topnav {
    overflow: hidden;
    background-color: white;
    color: blue;
    font-size: 1rem;
    padding: 5px;
}

.topnav img {
    height: 150px;
}

#authentication-bar{
    background-color:#FFD1DC;
    padding-top: 10px;
    padding-bottom: 10px;
}

#user-details{
    color: cadetblue;
}

.content {
    padding: 20px;
}

.card {
    background-color: white;
    box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
    padding: 5%;
}

.cards {
    max-width: 800px;
    margin: 0 auto;
    margin-bottom: 10px;
    display: grid;
    grid-gap: 2rem;
    grid-template-columns: repeat(auto-fit, minmax(200px, 2fr));
}

.reading {
    color: #193036;
}

.date-time{
    font-size: 0.8rem;
    color: #1282A2;
}

.informations{
    font-size: 1rem;
    color: #ff0000;
}

button {
    background-color: #049faa;
    color: white;
    padding: 14px 20px;
    margin: 8px 0;
    border: none;
    cursor: pointer;
    border-radius: 4px;
}
button:hover {
   opacity: 0.8;
}
.deletebtn{
    background-color: #c52c2c;
}

.form-elements-container{
    padding: 16px;
    width: 250px;
    margin: 0 auto;
}

input[type=text], input[type=password] {
    width: 100%;
    padding: 12px 20px;
    margin: 8px 0;
    display: inline-block;
    border: 1px solid #ccc;
    box-sizing: border-box;
}

table {
    width: 100%;
    text-align: center;
    font-size: 0.8rem;
}   
tr, td {
    padding: 0.25rem;
}
tr:nth-child(even) {
    background-color: #f2f2f2
}
tr:hover {
    background-color: #ddd;
}
th {
    position: sticky;
    top: 0;
    background-color: #50b8b4;
    color: white;
}

/* The Modal (background) */
.modal {
    display: none; /* Hidden by default */
    position: fixed; /* Stay in place */
    z-index: 1; /* Sit on top */
    left: 0;
    top: 0;
    width: 100%; /* Full width */
    height: 100%; /* Full height */
    overflow: auto; /* Enable scroll if needed */
    background-color: #474e5d;
    padding-top: 50px;
}
  
/* Modal Content/Box */
.modal-content {
    background-color: #FFFFFF;
    margin: 5% auto 15% auto; /* 5% from the top, 15% from the bottom and centered */
    border: 1px solid #888;
    width: 80%; /* Could be more or less, depending on screen size */
}
  
/* Style the horizontal ruler */
hr {
    border: 1px solid #f1f1f1;
    margin-bottom: 25px;
}

/* The Modal Close Button (x) */
.close {
    position: absolute;
    right: 35px;
    top: 15px;
    font-size: 40px;
    font-weight: bold;
    color: #f1f1f1;
}

.close:hover,
.close:focus {
    color: #f44336;
    cursor: pointer;
}

/* Clear floats */
.clearfix::after {
    content: "";
    clear: both;
    display: table;
}

/* Change styles for cancel button and delete button on extra small screens */
@media screen and (max-width: 300px) {
    .cancelbtn, .deletebtn {
        width: 100%;
    }
}
// Create DRY Temperature Gauge
function createDryTemperatureGauge() {
  var gauge = new LinearGauge({
      renderTo: 'gauge-dry-temperature',
      width: 120,
      height: 400,
      units: "Temperature °C",
      minValue: 0,
      startAngle: 90,
      ticksAngle: 180,
      maxValue: 150,
      colorValueBoxRect: "#049faa",
      colorValueBoxRectEnd: "#049faa",
      colorValueBoxBackground: "#f1fbfc",
      valueDec: 2,
      valueInt: 2,
      majorTicks: [
          "0",
          "10",
          "20",
          "30",
          "40",
          "50",
          "60",
          "70",
          "80",
          "90",
          "100",
          "110",
          "120",
          "130",
          "140",
          "150"
      ],
      minorTicks: 4,
      strokeTicks: true,
      highlights: [
          {
              "from": 100,
              "to": 150,
              "color": "rgba(200, 50, 50, .75)"
          }
      ],
      colorPlate: "#fff",
      colorBarProgress: "#CC2936",
      colorBarProgressEnd: "#049faa",
      borderShadowWidth: 0,
      borders: false,
      needleType: "arrow",
      needleWidth: 2,
      needleCircleSize: 7,
      needleCircleOuter: true,
      needleCircleInner: false,
      animationDuration: 1500,
      animationRule: "linear",
      barWidth: 10,
  });
  return gauge;
}
  // Create Humidity Gauge
function createHumidityGauge(){
  var gauge = new RadialGauge({
      renderTo: 'gauge-humidity',
      width: 250,
      height: 250,
      units: "Humidity (%)",
      minValue: 0,
      maxValue: 100,
      colorValueBoxRect: "#049faa",
      colorValueBoxRectEnd: "#049faa",
      colorValueBoxBackground: "#f1fbfc",
      valueInt: 2,
      majorTicks: [
          "0",
          "20",
          "40",
          "60",
          "80",
          "100"
  
      ],
      minorTicks: 4,
      strokeTicks: true,
      highlights: [
          {
              "from": 0,
              "to": 30,
              "color": "#FF4500" //orangered
          },
          {
              "from": 30,
              "to": 60,
              "color": "#FDDA0D" //cadmium yellow
          },
          {
              "from": 60,
              "to": 70,
              "color": "#7CFC00" //lawngreen
          },
          {
              "from": 70,
              "to": 100,
              "color": "#03C0C1"
          }
      ],
      colorPlate: "#fff",
      borderShadowWidth: 0,
      borders: false,
      needleType: "line",
      colorNeedle: "#007F80",
      colorNeedleEnd: "#007F80",
      needleWidth: 2,
      needleCircleSize: 3,
      colorNeedleCircleOuter: "#007F80",
      needleCircleOuter: true,
      needleCircleInner: false,
      animationDuration: 1500,
      animationRule: "linear"
  });
  return gauge;
}


function createLuxGauge(){
  var gauge = new RadialGauge({
      renderTo: 'gauge-Lux',
      width: 250,
      height: 250,
      units: "Lux (lx)",
      minValue: 0,
      maxValue: 200000,
      colorValueBoxRect: "#049faa",
      colorValueBoxRectEnd: "#049faa",
      colorValueBoxBackground: "#f1fbfc",
      valueInt: 2,
      majorTicks: [
          "0",
          "40000",
          "80000",
          "120000",
          "160000",
          "200000"
  
      ],
      minorTicks: 4,
      strokeTicks: true,
      highlights: [
          {
              "from": 0,
              "to": 20000,
              "color": "#FF4500" //orangered
          },
          {
              "from": 20000,
              "to": 40000,
              "color": "#FDDA0D" //cadmium yellow
          },
          {
              "from": 40000,
              "to": 120000,
              "color": "#7CFC00" //lawngreen
          },
          {
              "from": 120000,
              "to": 200000,
              "color": "#03C0C1"
          }
      ],
      colorPlate: "#fff",
      borderShadowWidth: 0,
      borders: false,
      needleType: "line",
      colorNeedle: "#007F80",
      colorNeedleEnd: "#007F80",
      needleWidth: 2,
      needleCircleSize: 3,
      colorNeedleCircleOuter: "#007F80",
      needleCircleOuter: true,
      needleCircleInner: false,
      animationDuration: 1500,
      animationRule: "linear"
  });
  return gauge;
}
// Create the charts when the web page loads
window.addEventListener('load', onload);

function onload(event){
  chartT0 = createDryTemperatureChart();
  chartH = createHumidityChart();
  chartT1 = createLuxChart();
}

// Create DRY Temperature Chart
function createDryTemperatureChart() {
  var chart = new Highcharts.Chart({
    chart:{ 
      renderTo:'chart-dry-temperature',
      type: 'spline' 
    },
    series: [
      {
        name: 'SENSOR 0'
      }
    ],
    title: { 
      text: undefined
    },
    plotOptions: {
      line: { 
        animation: false,
        dataLabels: { 
          enabled: true 
        }
      }
    },
    xAxis: {
      type: 'datetime',
      dateTimeLabelFormats: { second: '%H:%M:%S' }
    },
    yAxis: {
      title: { 
        text: 'Temperature Celsius Degrees' 
      }
    },
    credits: { 
      enabled: false 
    }
  });
  return chart;
}
// Create Humidity Chart
function createHumidityChart(){
  var chart = new Highcharts.Chart({
    chart:{ 
      renderTo:'chart-humidity',
      type: 'spline'  
    },
    series: [{
      name: 'HUMIDITY CALCULATION'
    }],
    title: { 
      text: undefined
    },    
    plotOptions: {
      line: { 
        animation: false,
        dataLabels: { 
          enabled: true 
        }
      },
      series: { 
        color: '#50b8b4' 
      }
    },
    xAxis: {
      type: 'datetime',
      dateTimeLabelFormats: { second: '%H:%M:%S' }
    },
    yAxis: {
      title: { 
        text: 'Humidity (%)' 
      }
    },
    credits: { 
      enabled: false 
    }
  });
  return chart;
}
function createLuxChart(){
  var chart = new Highcharts.Chart({
    chart:{ 
      renderTo:'chart-lux',
      type: 'spline'  
    },
    series: [{
      name: 'LUX CALCULATION'
    }],
    title: { 
      text: undefined
    },    
    plotOptions: {
      line: { 
        animation: false,
        dataLabels: { 
          enabled: true 
        }
      },
      series: { 
        color: '#ff9100' 
      }
    },
    xAxis: {
      type: 'datetime',
      dateTimeLabelFormats: { second: '%H:%M:%S' }
    },
    yAxis: {
      title: { 
        text: 'LUX (lx)' 
      }
    },
    credits: { 
      enabled: false 
    }
  });
  return chart;
}

#define WIFI_JIO
//#include 
#if defined(ESP32)
  #include 
#elif defined(ESP8266)
  #include 
#endif
#include 

#include 
#include "time.h"

//AHT temperature sensors:
#include 
#include 
#include 

BH1750 lightMeter(0x23);
#define SDA_2 33
#define SCL_2 32 
TwoWire I2C_2 = TwoWire(1);
//#include 
//Adafruit_AHTX0 aht; // I2C
AHTxx aht20(AHTXX_ADDRESS_X38, AHT2x_SENSOR);

//include the following for the Firebase library to work.
// Provide the token generation process info.
#include "addons/TokenHelper.h"
// Provide the RTDB payload printing info and other helper functions.
#include "addons/RTDBHelper.h"

// Insert your network credentials and make sure the define at the beginning of the document is correct
#if defined(WIFI_JIO)
  //#define WIFI_SSID "JioFi_10C2184"
  //#define WIFI_PASSWORD "2ycrszvn8p"
  //#define WIFI_SSID "JioFi_10C2184"
  //#define WIFI_PASSWORD "2ycrszvn8p"
  #define WIFI_SSID "wifi name"
  #define WIFI_PASSWORD "wifi password"
  #define WIFI_NAME "WS"
#endif

// Insert Firebase project API Key
#define API_KEY "ENTER YOUR API KEY" //"va-black-soldier-flies" firebase project

// Insert Authorized Email and Corresponding Password
#define USER_EMAIL "ENTER EMAIL linked to firebase" //you can also choose: va_esp32_test@gmail.com
#define USER_PASSWORD "enter password"

// Insert RTDB URLefine the RTDB URL
#define DATABASE_URL "https://thn-sensor-default-rtdb.asia-southeast1.firebasedatabase.app/"

// Define Firebase objects
FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig config;

// Variable to save USER UID
String uid;

// Data wire is plugged TO GPIO 4
/* #define ONE_WIRE_BUS 4
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&amp;oneWire); */
float temp=0;
float rh=0;
int hours;
int minutes;

/* // Number of temperature devices found
int numberOfDevices;*/
// We'll use this variable to store a found device address
//DeviceAddress tempDeviceAddress;
// Database main path (to be updated in setup with the user UID)
String databasePath;

// Database child nodes
String temppath = "/temperature0";
String prespath = "/temperature1";
String humPath = "/humidity";
String timePath = "/timestamp";

// Parent Node (to be updated in every loop)
String parentPath;

int timestamp;
FirebaseJson json;

const char* ntpServer = "pool.ntp.org";

float humidity;

// Timer variables (send new readings every three minutes)
unsigned long sendDataPrevMillis = 0;
unsigned long timerDelay =1000; //30 minute delay, 1 sec = 1000 for timerDelay




//variables for actuators
unsigned long delayTime;

void start_aht()
{
  while (aht20.begin() != true)
  {
    Serial.println(F("AHT2x not connected or fail to load calibration coefficient")); 
    delay(2000);
  }
  Serial.println(F("AHT20 OK"));
}



// Initialize WiFi
void initWiFi() {
  Serial.print("Connecting to ");
  Serial.println(WIFI_SSID);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
  Serial.print("\nConnected to WiFi!\n");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println();
}

// Function that gets current epoch time
unsigned long getTime() 
{
  time_t now;
  struct tm timeinfo;
  if (!getLocalTime(&amp;timeinfo)) {
    //Serial.println("Failed to obtain time");
    return(0);
  }
  hours = timeinfo.tm_hour;
  minutes = timeinfo.tm_min;
  time(&amp;now);
  return now;
}

/************************************SETUP************************************/

void setup(){
  //relay
  // Initialize WiFi
  initWiFi();
  start_aht();
  Serial.begin(115200);
  Wire.begin();
  I2C_2.begin(SDA_2, SCL_2);
  if (!lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x23, &amp;I2C_2)) {
    Serial.println("Could not find BH1750 sensor!");
    while (1) delay(10);
  }
  Serial.println(F("BH1750 Test begin"));
  bool status;
  // default settings
  configTime(0, 0, ntpServer);

  // Assign the api key (required)
  config.api_key = API_KEY;

  // Assign the user sign in credentials
  auth.user.email = USER_EMAIL;
  auth.user.password = USER_PASSWORD;

  // Assign the RTDB URL (required)
  config.database_url = DATABASE_URL;

  Firebase.reconnectWiFi(true);
  fbdo.setResponseSize(4096);

  // Assign the callback function for the long running token generation task
  config.token_status_callback = tokenStatusCallback; //see addons/TokenHelper.h

  // Assign the maximum retry of token generation
  config.max_token_generation_retry = 5;

  // Initialize the library with the Firebase authen and config
  Firebase.begin(&amp;config, &amp;auth);

  // Getting the user UID might take a few seconds
  Serial.println("Getting User UID");
  while ((auth.token.uid) == "") {
    Serial.print('.');
    delay(1000);
  }
  // Print user UID
  uid = auth.token.uid.c_str();
  Serial.print("User UID: ");
  Serial.print(uid);

  // Update database path
  databasePath = "/UsersData/"+ uid + "/readings";

  Serial.println("\n\nEnd of void setup function");
}

//************************************LOOP************************************

void loop(){

  Serial.println("entering loop...");
  temp = aht20.readTemperature();
  Serial.print("Temperature (ºC): "); Serial.println(temp);
  rh = aht20.readHumidity();
  Serial.print("Humidity (%): ");
  Serial.println(rh);
  delay(1000);
  float lux = lightMeter.readLightLevel();
  Serial.print("Light: ");
  Serial.print(lux);
  Serial.println(" lx");
  delay(1000);
  
  
  timestamp = getTime();
  Serial.print ("current time: ");
  Serial.println (timestamp);
  Serial.println (hours);Serial.println (minutes);
  //Check variables and activate controls
 

  // Send new readings to database
  if (Firebase.ready() &amp;&amp; (millis() - sendDataPrevMillis &gt; timerDelay || sendDataPrevMillis == 0)){
    sendDataPrevMillis = millis();

    //Get current timestamp
    timestamp = getTime();
    Serial.print ("current time: ");
    Serial.println (timestamp);

    parentPath= databasePath + "/" + String(timestamp);

    json.set(temppath.c_str(), String(temp));
    json.set(prespath.c_str(), String(lux));
    json.set(humPath.c_str(), String(rh));
    json.set(timePath, String(timestamp));

    //We can call that instruction inside a Serial.printf() command to print the results in the Serial Monitor at the same time the command runs.
    Serial.printf("Set json... %s\n", Firebase.RTDB.setJSON(&amp;fbdo, parentPath.c_str(), &amp;json) ? "ok" : fbdo.errorReason().c_str());
  }
}