Browse Source

www: automatically update the status page content periodically

Get updated status information periodically.
TODO: make this event-driven.
H. Peter Anvin 2 years ago
parent
commit
52945884b7
8 changed files with 67 additions and 32 deletions
  1. 39 11
      esp32/max80/httpd.c
  2. BIN
      esp32/output/max80.ino.bin
  3. 2 0
      esp32/www/lang/sv
  4. 1 1
      esp32/www/max80.css
  5. 6 1
      esp32/www/max80.js
  6. 19 19
      esp32/www/status.html
  7. BIN
      fpga/output/v1.fw
  8. BIN
      fpga/output/v2.fw

+ 39 - 11
esp32/max80/httpd.c

@@ -357,6 +357,41 @@ static esp_err_t httpd_set_config(httpd_req_t *req, const char *query)
     return httpd_update_done(req, "Configuration", rv1 ? rv1 : rv2);
 }
 
+#define MIN_STATUS_REF 2	/* Minimum refresh time in ms */
+
+static void httpd_get_status_extra(FILE *f, httpd_req_t *req)
+{
+    static const char refresh_time_config[] = "http.status.refresh";
+    const unsigned long min_status_ref = 5;
+    char timebuf[64];
+    size_t len;
+    struct timeval tv;
+
+    unsigned long statref;
+    statref = Max(getenv_ul(refresh_time_config, 0), min_status_ref);
+
+    if (httpd_req_get_url_query_str(req, timebuf, sizeof timebuf) == ESP_OK &&
+	*timebuf) {
+	char *ep;
+	unsigned long newstatref = strtoul(timebuf, &ep, 10);
+	if (!*ep && newstatref >= min_status_ref && newstatref != statref) {
+	    statref = newstatref;
+	    setenv_config(refresh_time_config, timebuf);
+	    read_config(NULL, true); /* Save changed config */
+	}
+    }
+    fprintf(f, "%s=%lu\n", refresh_time_config, statref);
+
+    gettimeofday(&tv,NULL);
+    const struct tm *tm = localtime(&tv.tv_sec);
+    len = strftime(timebuf, sizeof timebuf, "localtime=%Y-%m-%d %H:%M:%S.", tm);
+    snprintf(timebuf+len, sizeof timebuf - len, "%06u",
+	     (unsigned long)tv.tv_usec);
+    len += 3;
+    len += strftime(timebuf+len, sizeof timebuf - len, " %z (%Z)\n", tm);
+    fwrite(timebuf, 1, len, f);
+}
+
 static esp_err_t httpd_get_config_status(httpd_req_t *req, bool status)
 {
     FILE *f = httpd_fopen_write(req);
@@ -366,21 +401,14 @@ static esp_err_t httpd_get_config_status(httpd_req_t *req, bool status)
     httpd_resp_set_type(req, text_plain);
     httpd_resp_set_hdr(req, "Cache-Control", "no-cache");
 
+    if (status)
+	httpd_get_status_extra(f, req);
+
     int rv = write_env(f, status);
     fclose(f);
     return rv ? ESP_FAIL : ESP_OK;
 }
 
-static esp_err_t httpd_get_status(httpd_req_t *req)
-{
-    char timebuf[64];
-    time_t now = time(NULL);
-    const struct tm *tm = localtime(&now);
-    strftime(timebuf, sizeof timebuf, "%Y-%m-%d %H:%M:%S %z (%Z)", tm);
-    setenv("status.localtime", timebuf, 1);
-    return httpd_get_config_status(req, true);
-}
-
 static esp_err_t httpd_set_lang(httpd_req_t *req, const char *query)
 {
     if (query) {
@@ -439,7 +467,7 @@ static esp_err_t httpd_sys_handler(httpd_req_t *req)
 	return httpd_lang_redirect(req);
 
     if (STRING_MATCHES(file, filelen, "getstatus"))
-	return httpd_get_status(req);
+	return httpd_get_config_status(req, true);
 
     if (STRING_MATCHES(file, filelen, "getconfig"))
 	return httpd_get_config_status(req, false);

BIN
esp32/output/max80.ino.bin


+ 2 - 0
esp32/www/lang/sv

@@ -39,3 +39,5 @@ button .hide=Göm
 .net-ip4-gw span=Router:
 .sntp-sync span=Klockan i synk med NTP:
 .localtime span=Systemklocka:
+.refresh legend=Statusuppdatering
+.refresh label span:first-child=Intervall:

+ 1 - 1
esp32/www/max80.css

@@ -147,7 +147,7 @@ output {
     font-weight: bold;
     text-decoration: underline;
 }
-.getstatus input:not(.noinit) {
+.getstatus :disabled {
     font-family: inherit;
     font-size: inherit;
     background: inherit;

+ 6 - 1
esp32/www/max80.js

@@ -43,6 +43,11 @@ function fetchconfig(url) {
 	});
 }
 
+// Get the value from an input field if valid, otherwise its default
+function valval(ie) {
+    return ie.checkValidity() ? ie.value : ie.defaultValue;
+}
+
 // Parse a string for a valid boolean truth value
 function cfgbool(str) {
     return str && !str.match(/^(0*|[fnd].*|of.*)$/i);
@@ -58,7 +63,7 @@ function initform(form,map,ro = false) {
 	if (e.classList.contains('noinit') ||
 	    e instanceof HTMLFieldSetElement)
 	    continue;
-	if (ro && e.disabled != undefined)
+	if (ro && e.disabled != undefined && !e.classList.contains('noro'))
 	    e.disabled = true;
 	if (e instanceof HTMLInputElement ||
 	    e instanceof HTMLSelectElement) {

+ 19 - 19
esp32/www/status.html

@@ -4,6 +4,21 @@
     <link rel="stylesheet" href="max80.css" />
     <title class="status">MAX80</title>
     <script src="max80.js"></script>
+    <script>
+      var ref_tmr = 0;
+      function ref_status(seti) {
+	  clearTimeout(ref_tmr);
+	  var rt = document.getElementById('refresh_time');
+	  const setintv = (seti && rt.checkValidity()) ? '?'+rt.value : '';
+	  fetchconfig('sys/getstatus' + setintv)
+	      .then((map) => initform('getstatus',map,true))
+	      .catch(err => {})
+	      .finally (() => {
+		  const when = parseInt(valval(rt)) * 1000;
+		  ref_tmr = setTimeout(ref_status, when);
+	      });
+      }
+    </script>
   </head>
   <body>
     <script>inc("head.html")</script>
@@ -97,27 +112,12 @@
 	<legend>Status refresh</legend>
 	<label class="refresh">
 	  <span>Refresh interval:</span>
-	  <input class="noinit" id="refresh_time" type="number"
-		 name="refresh" value="10" step="5" min="5"
-		 onchange="ref_status()" />
-	  &nbsp;<span class="unit">s</span>
+	  <input class="noro" id="refresh_time" type="number"
+		 name="http.status.refresh" value="10" step="5" min="5"
+		 onchange="ref_status(true)" />&nbsp;s
 	</label>
       </fieldset>
     </form>
-    <script>
-      var ref_tmr = 0;
-      function ref_status() {
-	  clearTimeout(ref_tmr);
-	  fetchconfig('sys/getstatus')
-	      .then((map) => initform('getstatus',map,true))
-	      .catch(err => {})
-	      .finally (() => {
-		  const when = document.getElementById('refresh_time').value
-			* 1000;
-		  ref_tmr = setTimeout(ref_status, when);
-	      });
-      }
-      ref_status();
-    </script>
+    <script>ref_status(false)</script>
   </body>
 </html>

BIN
fpga/output/v1.fw


BIN
fpga/output/v2.fw