A remote timer, equipped with a scheduling Web interface, controls a "DigitalOut".

Dependencies:   Timezone NTPClient

WebTimer

The WebTimer is an Mbed device enabling to remotely control a DigitalOut. It has a "calendar-like" user interface to edit the schedule - a table you can click on (or tap on a touch-screen device).
The program was ported to Mbed from the Tuxgraphics site. Thank you Guido for sharing!

  • When starting, it will print it's IP address over the USB serial link to the terminal screen. However, you can set a different static IP address if you modify the code in the main.cpp.
  • To connect to the WebTimer, type the IP address into the web browser edit box and hit ENTER.
  • When a cell is green then the timer keeps it's output ON during that period of time. If a cell is not green it means the output is OFF.
  • To select or deselect multiple cells you can click (keep down the button) and move the mouse over more cells.
  • The smallest time interval on this 24h timer is 15minutes.
  • To save the changes type in the password and hit ENTER or click on the Save button.
  • The default password is "secret". But you can change it by editing the source code in main.cpp.
OnDesktopOnPhone
Revision:
0:f78e57015038
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/websrv_help_functions.c	Wed Nov 11 16:56:02 2020 +0000
@@ -0,0 +1,234 @@
+/*********************************************
+ * vim:sw=8:ts=8:si:et
+ * To use the above modeline in vim you must have "set modeline" in your .vimrc
+ * Author: Guido Socher
+ * Copyright:LGPL V2
+ * See http://www.gnu.org/licenses/old-licenses/lgpl-2.0.html
+ *
+ * Some common utilities needed for IP and web applications.
+ * The defines below are controlled via ip_config.h. By choosing
+ * the right defines for your application in ip_config.h you can
+ * significantly reduce the size of the resulting code.
+ *********************************************/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "websrv_help_functions.h"
+
+#ifdef FROMDECODE_websrv_help
+// search for a string of the form key=value in
+// a string that looks like q?xyz=abc&uvw=defgh HTTP/1.1\r\n
+// The returned value is stored in strbuf. You must allocate
+// enough storage for strbuf, maxlen is the size of strbuf.
+
+// I.e the value it is declared with: strbuf[5]-> maxlen=5
+uint8_t find_key_val(char* str, char* strbuf, uint8_t maxlen, char* key)
+{
+    uint8_t found = 0;
+    uint8_t i = 0;
+    char*   kp;
+    kp = key;
+    while (*str && *str != ' ' && *str != '\r' && found == 0) {
+        if (*str == *kp) {
+
+            // At the beginning of the key we must check
+            // if this is the start of the key otherwise we will
+            // match on 'foobar' when only looking for 'bar', by andras tucsni
+            if (kp == key && !(*(str - 1) == '?' || *(str - 1) == '&'))
+                goto NEXT;
+            kp++;
+            if (*kp == '\0') {
+                str++;
+                kp = key;
+                if (*str == '=') {
+                    found = 1;
+                }
+            }
+        }
+        else {
+            kp = key;
+        }
+
+NEXT:
+        str++;
+    }
+
+    if (found == 1) {
+
+        // copy the value to a buffer and terminate it with '\0'
+        while (*str && *str != ' ' && *str != '\r' && *str != '&' && i < maxlen - 1) {
+            *strbuf = *str;
+            i++;
+            str++;
+            strbuf++;
+        }
+
+        *strbuf = '\0';
+    }
+
+    // return 1 if found (the string in strbuf might still be an empty string)
+    // otherwise return 0
+    return(found);
+}
+
+// convert a single hex digit character to its integer value
+unsigned char h2int(char c)
+{
+    if (c >= '0' && c <= '9') {
+        return((unsigned char)c - '0');
+    }
+
+    if (c >= 'a' && c <= 'f') {
+        return((unsigned char)c - 'a' + 10);
+    }
+
+    if (c >= 'A' && c <= 'F') {
+        return((unsigned char)c - 'A' + 10);
+    }
+
+    return(0);
+}
+
+// decode a url string e.g "hello%20joe" or "hello+joe" becomes "hello joe"
+void urldecode(char* urlbuf)
+{
+    char    c;
+    char*   dst;
+    dst = urlbuf;
+    while ((c = *urlbuf)) {
+        if (c == '+')
+            c = ' ';
+        if (c == '%') {
+            urlbuf++;
+            c = *urlbuf;
+            urlbuf++;
+            c = (h2int(c) << 4) | h2int(*urlbuf);
+        }
+
+        *dst = c;
+        dst++;
+        urlbuf++;
+    }
+
+    *dst = '\0';
+}
+#endif //  FROMDECODE_websrv_help
+
+#ifdef URLENCODE_websrv_help
+// convert a single character to a 2 digit hex str
+
+// a terminating '\0' is added
+void int2h(char c, char* hstr)
+{
+    hstr[1] = (c & 0xf) + '0';
+    if ((c & 0xf) > 9) {
+        hstr[1] = (c & 0xf) - 10 + 'a';
+    }
+
+    c = (c >> 4) & 0xf;
+    hstr[0] = c + '0';
+    if (c > 9) {
+        hstr[0] = c - 10 + 'a';
+    }
+
+    hstr[2] = '\0';
+}
+
+// There must be enough space in urlbuf. In the worst case that would be
+
+// 3 times the length of str
+void urlencode(const char* str, char* urlbuf)
+{
+    char    c;
+    while ((c = *str)) {
+        if (c == ' ' || isalnum(c)) {
+            if (c == ' ') {
+                c = '+';
+            }
+
+            *urlbuf = c;
+            str++;
+            urlbuf++;
+            continue;
+        }
+
+        *urlbuf = '%';
+        urlbuf++;
+        int2h(c, urlbuf);
+        urlbuf++;
+        urlbuf++;
+        str++;
+    }
+
+    *urlbuf = '\0';
+}
+#endif // URLENCODE_websrv_help
+
+// parse a string that is an IP address and extract the IP to ip_byte_str
+uint8_t parse_ip(uint8_t* ip_byte_str, const char* str)
+{
+    char    strbuf[4];
+    uint8_t bufpos = 0;
+    uint8_t i = 0;
+    while (i < 4) {
+        ip_byte_str[i] = 0;
+        i++;
+    }
+
+    i = 0;
+    while (*str && i < 4) {
+
+        // if a number then start
+        if (bufpos < 3 && isdigit(*str)) {
+            strbuf[bufpos] = *str;  // copy
+            bufpos++;
+        }
+
+        if (bufpos && *str == '.') {
+            strbuf[bufpos] = '\0';
+            ip_byte_str[i] = (atoi(strbuf) & 0xff);
+            i++;
+            bufpos = 0;
+        }
+
+        str++;
+    }
+
+    if (i == 3) {
+
+        // must have read the first componets of the IP
+        strbuf[bufpos] = '\0';
+        ip_byte_str[i] = (atoi(strbuf) & 0xff);
+        return(0);
+    }
+
+    return(1);
+}
+
+// take a byte string and convert it to a human readable display string  (base is 10 for ip and 16 for mac addr), len is 4 for IP addr and 6 for mac.
+void mk_net_str(char* resultstr, uint8_t* ip_byte_str, uint8_t len, char separator, uint8_t base)
+{
+    uint8_t i = 0;
+    uint8_t j = 0;
+    while (i < len) {
+        sprintf(resultstr, base == 10 ? "%i" : "%x", (int)ip_byte_str[i]);
+
+        // search end of str:
+        while (resultstr[j]) {
+            j++;
+        }
+
+        if (separator) {
+
+            // no separator, separator==NULL is as well possible, suggested by andras tucsni
+            resultstr[j] = separator;
+            j++;
+        }
+
+        i++;
+    }
+
+    j--;
+    resultstr[j] = '\0';
+}