presenting current time on ESP hosted page

I’m building a watering system for my small vegetable garden. the goal is to

  • Keep the system time updated
  • Host a page which allows start/endtime to be set
  • Page should ideally present the current time, and the current status of the system
  • future scope:scrape openweather API to determine if it will rain soon

So far I’ve got most of this working my smashing together some found code, as well as some of my own, I can pull the current time for comparison, but i can’t it to show on the page.
I can show the current start, and end times, so i suspect the page doesn’t have access to the variable i’m passing in

(forgive ugly code, i had it broken into methods to compare times and then to trigger relay etc, but was struggling with variables not being available to all, this is just an intermediary step)


#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <Hash.h>
#include <FS.h>
#include <ESPAsyncWebServer.h>
#include <NTPClient.h>
#include <WiFiUdp.h>

AsyncWebServer server(80);

// REPLACE WITH YOUR NETWORK CREDENTIALS
const char* ssid = "bears beets battlestar-galactica";
const char* password = "*****";

const char* PARAM_START = "startTime";
const char* PARAM_END = "endTime";

int nuTime;

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "au.pool.ntp.org", 39600);
//timeClient(ntpUDP, [NTP Server], [offset in seconds], [update frequency])


// HTML web page to handle 2 input fields and a switch
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html><head>
  <title>Auto Water-o</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script>
    function submitMessage() {
      alert("Saved value to ESP SPIFFS");
      setTimeout(function(){ document.location.reload(false); }, 500);   
    }
    </script></head><body>
    <h1><center>&#127811;Auto Water-o&#127793;</center></h1>
    currently %curTime%
    

    

    <form action="/get" target="hidden-form">
    Start Time: <input type="number" name="startTime">
    <input type="submit" value="Submit" onclick="submitMessage()">
    
(current value %startTime%)
  </form>

  

  <form action="/get" target="hidden-form">
    End Time: <input type="number" name="endTime">
    <input type="submit" value="Submit" onclick="submitMessage()">
    
(current value %endTime%)
  </form>
  <iframe style="display:none" name="hidden-form"></iframe>
</body></html>)rawliteral";


void setup() {
  pinMode(5, OUTPUT);
  Serial.begin(115200);
  if (!SPIFFS.begin()) {
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  if (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("WiFi Failed!");
    return;
  }
  Serial.println();
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());
  timeClient.begin();
  timeClient.update();
  String curTime = timeClient.getFormattedTime();
  // Send web page with input fields to client
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send_P(200, "text/html", index_html, processor);
  });

  server.on("/get", HTTP_GET, [] (AsyncWebServerRequest * request) {
    String inputMessage;
    if (request->hasParam(PARAM_START)) {
      inputMessage = request->getParam(PARAM_START)->value();
      writeFile(SPIFFS, "/startTime.txt", inputMessage.c_str());
    }
    else if (request->hasParam(PARAM_END)) {
      inputMessage = request->getParam(PARAM_END)->value();
      writeFile(SPIFFS, "/endTime.txt", inputMessage.c_str());
    }
    else {
      inputMessage = "No message sent";
    }
    Serial.println(inputMessage);
    request->send(200, "text/text", inputMessage);
  });
  server.onNotFound(notFound);
  server.begin();
  timeClient.begin();
}

void loop() {
  int yourstartTime = readFile(SPIFFS, "/startTime.txt").toInt();
  int yourendTime = readFile(SPIFFS, "/endTime.txt").toInt();
  timeClient.update();
  nuTime = (timeClient.getFormattedTime().substring(0, 2) + timeClient.getFormattedTime().substring(3, 5)).toInt();
  delay(400);
  Serial.print("Time is ");
  Serial.println(nuTime);
  Serial.print("yourstartTime is ");
  Serial.println(yourstartTime);
  Serial.print("yourendTime is ");
  Serial.println(yourendTime);
  delay(400);

  if (nuTime < yourstartTime || nuTime >= yourendTime) {
    Serial.print(nuTime);
    Serial.print(" less than ");
    Serial.print(yourstartTime);
    Serial.print(" or greater than ");
    Serial.print(yourendTime);
    Serial.print(", pinoff");
    Serial.println();
    digitalWrite(5, LOW); // de-energise the relay
  }
  if (nuTime > yourstartTime && nuTime < yourendTime) {
    Serial.print(nuTime);
    Serial.print(" greater than ");
    Serial.print(yourstartTime);
    Serial.print(" and less than ");
    Serial.print(yourendTime);
    Serial.print(", pinon");
    Serial.println();

    digitalWrite(5, HIGH); // Energise the relay
  }
  delay(5000);
  //  }
}

void notFound(AsyncWebServerRequest *request) {
  request->send(404, "text/plain", "Not found");
}

String readFile(fs::FS &fs, const char * path) {
  Serial.printf("Reading file: %s\r\n", path);
  File file = fs.open(path, "r");
  if (!file || file.isDirectory()) {
    Serial.println("- empty file or failed to open file");
    return String();
  }
  Serial.print("- read from file:");
  String fileContent;
  while (file.available()) {
    fileContent += String((char)file.read());
  }
  Serial.println(fileContent);
  return fileContent;
}

void writeFile(fs::FS &fs, const char * path, const char * message) {
  Serial.printf("Writing file: %s\r\n", path);
  File file = fs.open(path, "w");
  if (!file) {
    Serial.println("- failed to open file for writing");
    return;
  }
  if (file.print(message)) {
    Serial.println("- file written");
  } else {
    Serial.println("- write failed");
  }
}

// Replaces placeholder with stored values
String processor(const String& var) {
  //Serial.println(var);
  if (var == "startTime") {
    return readFile(SPIFFS, "/startTime.txt");
  }
  else if (var == "endTime") {
    return readFile(SPIFFS, "/endTime.txt");
  }
  return String();
}

Why are you posting code in quotes? :roll_eyes:

(See the instructions, point 7)


Much better! :sunglasses:

my bad, i didn't see the code tag in the edit controls

Smashing code does not work unless you understand what you are smashing. I do not think you googled “arduino sprinkler controller”, I got 475,000 hits. I googled “arduino plant watering” and got 695,000 hits. These have drawings, software, pictures and instructions depending on which one you use.

gilshultz:
Smashing code does not work unless you understand what you are smashing. I do not think you googled "arduino sprinkler controller", I got 475,000 hits. I googled "arduino plant watering" and got 695,000 hits. These have drawings, software, pictures and instructions depending on which one you use.

thanks for your insightful and helpful post.
to be clear, the code i smashed was only
this to get a time update from an NTP server. which i understand, and which works
this to host a page accepting text input, and save to spiffs which works, and i largely understand

i added the above into my existing code, and restructured the received NTP time, to compare it to saved, user entered tim which works, and drives a relay to trigger the 24vDC solenoid

or are you suggesting i should, instead of coding/learning myself, and asking one question on a forum specifically around this platform, i should instead google, arduino sprinkler controller or arduino plant watering

because neither of these are going to cover passing a time value captured in the loop method into a page generated outside of the setup or loop method.

I figured out a solution to this.
Hopefully as others on this forum couldn’t help me, this might people looking at the same in future.

in the below (hosted page component), i defined a couple of extra variables %curTime% and %water% to show th current time, and status of whether it’s watering or not.

// HTML web page to handle 2 input fields and a switch
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html><head>
  <title>Auto Water-o</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script>
    function submitMessage() {
      alert("Saved value to ESP SPIFFS");
      setTimeout(function(){ document.location.reload(false); }, 500);   
    }
    </script></head><body>
    <h1><center>&#127811;Auto Water-o&#127793;</center></h1>
    

    <center>Current Time is %curTime%
    
    
    Watering is %water%</center>
    

    <form action="/get" target="hidden-form">
    Start Time: <input type="number" name="startTime">
    <input type="submit" value="Submit" onclick="submitMessage()">
    
(current value %startTime%)
  </form>

  

  <form action="/get" target="hidden-form">
    End Time: <input type="number" name="endTime">
    <input type="submit" value="Submit" onclick="submitMessage()">
    
(current value %endTime%)
  </form>
  <iframe style="display:none" name="hidden-form"></iframe>
</body></html>)rawliteral";

then added these the processor method, which gets sent above, when server.on is called

String processor(const String& var) {
  String curTime = timeClient.getFormattedTime().substring(0, 2) + timeClient.getFormattedTime().substring(3, 5);
  //Serial.println(var);
  if (var == "startTime") {
    return readFile(SPIFFS, "/startTime.txt");
  }
  else if (var == "endTime") {
    return readFile(SPIFFS, "/endTime.txt");
  }
  else if (var == "curTime") {
    return curTime;
  }
  else if (var == "water") {
  return Watering;
  }
  return String();
}

you’ll also need to set the value of Watering, ideally where you turn on and off the relay

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.