Forráskód Böngészése

added ajax filling of html

Andrew Tridgell 3 éve
szülő
commit
86219b021e

+ 11 - 1
RemoteIDModule/web/index.html

@@ -7,6 +7,7 @@
     <meta name="description" content="ArduPilot RemoteID Module.">
     <link rel="stylesheet" type="text/css" href="styles/main.css">
     <script src='js/jquery.min.js'></script>
+    <script src='js/tools.js'></script>
 </head>
 
 <body>
@@ -14,6 +15,12 @@
 
   <h2>Status</h2>
 
+  <table class="values">
+    <tr><td>Version</td><td><div id="STATUS:VERSION"></div></td></tr>
+    <tr><td>Up Time</td><td><div id="STATUS:UPTIME"></div></td></tr>
+    <tr><td>Free Memory</td><td><div id="STATUS:FREEMEM"></div></td></tr>
+  </table>
+
   <h2>Firmware Update</h2>
 
   <form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>
@@ -50,7 +57,10 @@
             }
         });
     });
-  </script>
 
+    // poll status information at 1Hz (900ms to cope with some lag)
+    ajax_json_poll_fill("/ajax/status.json", 900);
+    </script>
+  
 </body>
 </html>

+ 132 - 0
RemoteIDModule/web/js/tools.js

@@ -0,0 +1,132 @@
+/*
+  helper functions for RemoteID javascript
+*/
+
+// helper function for cross-origin requests
+function createCORSRequest(method, url) {
+    var xhr = new XMLHttpRequest();
+    if ("withCredentials" in xhr) {
+        // XHR for Chrome/Firefox/Opera/Safari.
+        xhr.open(method, url, true);
+    } else if (typeof XDomainRequest != "undefined") {
+        // XDomainRequest for IE.
+        xhr = new XDomainRequest();
+        xhr.open(method, url);
+    } else {
+        // CORS not supported.
+        xhr = null;
+    }
+    return xhr;
+}
+
+
+/*
+  fill variables in a page from json
+*/
+function page_fill_json_value(json) {
+    for (var v in json) {
+        var element = document.getElementById(v);
+        if (element) {
+            element.value = json[v];
+        }
+    }
+}
+
+/*
+  fill html in a page from json
+*/
+function page_fill_json_html(json) {
+    for (var v in json) {
+        var element = document.getElementById(v);
+        if (element) {
+            element.innerHTML = json[v];
+        }
+    }
+}
+
+/*
+  fetch a URL, calling a callback
+*/
+function ajax_get_callback(url, callback) {
+    var xhr = createCORSRequest("GET", url);
+    xhr.onload = function() {
+        callback(xhr.responseText);
+    }
+    xhr.send();
+}
+
+/*
+  fetch a URL, calling a callback for binary data
+*/
+function ajax_get_callback_binary(url, callback) {
+    var xhr = createCORSRequest("GET", url);
+    xhr.onload = function() {
+        console.log("got response length " + xhr.response.byteLength);
+        callback(xhr.response);
+    }
+    xhr.responseType = "arraybuffer";
+    xhr.send();
+}
+
+/*
+  poll a URL, calling a callback
+*/
+function ajax_poll(url, callback, refresh_ms=1000) {
+    function again() {
+        setTimeout(function() { ajax_poll(url, callback, refresh_ms); }, refresh_ms);
+    }
+    var xhr = createCORSRequest("GET", url);
+    xhr.onload = function() {
+        if (callback(xhr.responseText)) {
+            again();
+        }
+    }
+    xhr.onerror = function() {
+        again();
+    }
+    xhr.timeout = 3000;
+    xhr.ontimeout = function() {
+        again();
+    }
+    xhr.send();
+}
+
+
+/*
+  poll a json file and fill document IDs at the given rate
+*/
+function ajax_json_poll(url, callback, refresh_ms=1000) {
+    function do_callback(responseText) {
+        try {
+            var json = JSON.parse(responseText);
+            return callback(json);
+        } catch(e) {
+            return true;
+        }
+        /* on bad json keep going */
+        return true;
+    }
+    ajax_poll(url, do_callback, refresh_ms);
+}
+
+/*
+  poll a json file and fill document IDs at the given rate
+*/
+function ajax_json_poll_fill(url, refresh_ms=1000) {
+    function callback(json) {
+        page_fill_json_html(json);
+        return true;
+    }
+    ajax_json_poll(url, callback, refresh_ms);
+}
+
+
+/*
+  set a message in a div by id, with given color
+*/
+function set_message_color(id, color, message) {
+    var element = document.getElementById(id);
+    if (element) {
+        element.innerHTML = '<b style="color:' + color + '">' + message + '</b>';
+    }
+}

+ 55 - 0
RemoteIDModule/webinterface.cpp

@@ -64,6 +64,60 @@ class ROMFS_Handler : public RequestHandler
 
 } ROMFS_Handler;
 
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+typedef struct {
+    String name;
+    String value;
+} json_table_t;
+
+/*
+  create a json string from a table
+ */
+static String json_format(const json_table_t *table, uint8_t n)
+{
+    String s = "{";
+    for (uint8_t i=0; i<n; i++) {
+        const auto &t = table[i];
+        s += "\"" + t.name + "\" : ";
+        s += "\"" + t.value + "\"";
+        if (i != n-1) {
+            s += ",";
+        }
+    }
+    s += "}";
+    return s;
+}
+
+/*
+  serve files from ROMFS
+ */
+class AJAX_Handler : public RequestHandler
+{
+    bool canHandle(HTTPMethod method, String uri) {
+        Serial.printf("ajax check '%s'", uri);
+        return uri == "/ajax/status.json";
+    }
+
+    bool handle(WebServer& server, HTTPMethod requestMethod, String requestUri) {
+        if (requestUri != "/ajax/status.json") {
+            return false;
+        }
+        const uint32_t now_s = millis() / 1000;
+        const uint32_t sec = now_s % 60;
+        const uint32_t min = (now_s / 60) % 60;
+        const uint32_t hr = (now_s / 3600) % 24;
+        const json_table_t table[] = {
+            { "STATUS:VERSION", String(FW_VERSION_MAJOR) + "." + String(FW_VERSION_MINOR) },
+            { "STATUS:UPTIME", String(hr) + ":" + String(min) + ":" + String(sec) },
+            { "STATUS:FREEMEM", String(ESP.getFreeHeap()) },
+        };
+        server.send(200, "application/json", json_format(table, ARRAY_SIZE(table)));
+        return true;
+    }
+
+} AJAX_Handler;
+
 /*
   init web server
  */
@@ -74,6 +128,7 @@ void WebInterface::init(void)
     IPAddress myIP = WiFi.softAPIP();
 
     server.addHandler( &ROMFS_Handler );
+    server.addHandler( &AJAX_Handler );
 
     /*handling uploading firmware file */
     server.on("/update", HTTP_POST, []() {