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
Committer:
hudakz
Date:
Wed Nov 11 16:56:02 2020 +0000
Revision:
0:f78e57015038
A timer to control a DigitalOut equipped with Web interface for scheduling.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 0:f78e57015038 1 /*********************************************
hudakz 0:f78e57015038 2 * vim:sw=8:ts=8:si:et
hudakz 0:f78e57015038 3 * To use the above modeline in vim you must have "set modeline" in your .vimrc
hudakz 0:f78e57015038 4 * Author: Guido Socher
hudakz 0:f78e57015038 5 * Copyright:LGPL V2
hudakz 0:f78e57015038 6 * See http://www.gnu.org/licenses/old-licenses/lgpl-2.0.html
hudakz 0:f78e57015038 7 *
hudakz 0:f78e57015038 8 * Some common utilities needed for IP and web applications.
hudakz 0:f78e57015038 9 * The defines below are controlled via ip_config.h. By choosing
hudakz 0:f78e57015038 10 * the right defines for your application in ip_config.h you can
hudakz 0:f78e57015038 11 * significantly reduce the size of the resulting code.
hudakz 0:f78e57015038 12 *********************************************/
hudakz 0:f78e57015038 13 #include <stdlib.h>
hudakz 0:f78e57015038 14 #include <stdio.h>
hudakz 0:f78e57015038 15 #include <string.h>
hudakz 0:f78e57015038 16 #include <ctype.h>
hudakz 0:f78e57015038 17 #include "websrv_help_functions.h"
hudakz 0:f78e57015038 18
hudakz 0:f78e57015038 19 #ifdef FROMDECODE_websrv_help
hudakz 0:f78e57015038 20 // search for a string of the form key=value in
hudakz 0:f78e57015038 21 // a string that looks like q?xyz=abc&uvw=defgh HTTP/1.1\r\n
hudakz 0:f78e57015038 22 // The returned value is stored in strbuf. You must allocate
hudakz 0:f78e57015038 23 // enough storage for strbuf, maxlen is the size of strbuf.
hudakz 0:f78e57015038 24
hudakz 0:f78e57015038 25 // I.e the value it is declared with: strbuf[5]-> maxlen=5
hudakz 0:f78e57015038 26 uint8_t find_key_val(char* str, char* strbuf, uint8_t maxlen, char* key)
hudakz 0:f78e57015038 27 {
hudakz 0:f78e57015038 28 uint8_t found = 0;
hudakz 0:f78e57015038 29 uint8_t i = 0;
hudakz 0:f78e57015038 30 char* kp;
hudakz 0:f78e57015038 31 kp = key;
hudakz 0:f78e57015038 32 while (*str && *str != ' ' && *str != '\r' && found == 0) {
hudakz 0:f78e57015038 33 if (*str == *kp) {
hudakz 0:f78e57015038 34
hudakz 0:f78e57015038 35 // At the beginning of the key we must check
hudakz 0:f78e57015038 36 // if this is the start of the key otherwise we will
hudakz 0:f78e57015038 37 // match on 'foobar' when only looking for 'bar', by andras tucsni
hudakz 0:f78e57015038 38 if (kp == key && !(*(str - 1) == '?' || *(str - 1) == '&'))
hudakz 0:f78e57015038 39 goto NEXT;
hudakz 0:f78e57015038 40 kp++;
hudakz 0:f78e57015038 41 if (*kp == '\0') {
hudakz 0:f78e57015038 42 str++;
hudakz 0:f78e57015038 43 kp = key;
hudakz 0:f78e57015038 44 if (*str == '=') {
hudakz 0:f78e57015038 45 found = 1;
hudakz 0:f78e57015038 46 }
hudakz 0:f78e57015038 47 }
hudakz 0:f78e57015038 48 }
hudakz 0:f78e57015038 49 else {
hudakz 0:f78e57015038 50 kp = key;
hudakz 0:f78e57015038 51 }
hudakz 0:f78e57015038 52
hudakz 0:f78e57015038 53 NEXT:
hudakz 0:f78e57015038 54 str++;
hudakz 0:f78e57015038 55 }
hudakz 0:f78e57015038 56
hudakz 0:f78e57015038 57 if (found == 1) {
hudakz 0:f78e57015038 58
hudakz 0:f78e57015038 59 // copy the value to a buffer and terminate it with '\0'
hudakz 0:f78e57015038 60 while (*str && *str != ' ' && *str != '\r' && *str != '&' && i < maxlen - 1) {
hudakz 0:f78e57015038 61 *strbuf = *str;
hudakz 0:f78e57015038 62 i++;
hudakz 0:f78e57015038 63 str++;
hudakz 0:f78e57015038 64 strbuf++;
hudakz 0:f78e57015038 65 }
hudakz 0:f78e57015038 66
hudakz 0:f78e57015038 67 *strbuf = '\0';
hudakz 0:f78e57015038 68 }
hudakz 0:f78e57015038 69
hudakz 0:f78e57015038 70 // return 1 if found (the string in strbuf might still be an empty string)
hudakz 0:f78e57015038 71 // otherwise return 0
hudakz 0:f78e57015038 72 return(found);
hudakz 0:f78e57015038 73 }
hudakz 0:f78e57015038 74
hudakz 0:f78e57015038 75 // convert a single hex digit character to its integer value
hudakz 0:f78e57015038 76 unsigned char h2int(char c)
hudakz 0:f78e57015038 77 {
hudakz 0:f78e57015038 78 if (c >= '0' && c <= '9') {
hudakz 0:f78e57015038 79 return((unsigned char)c - '0');
hudakz 0:f78e57015038 80 }
hudakz 0:f78e57015038 81
hudakz 0:f78e57015038 82 if (c >= 'a' && c <= 'f') {
hudakz 0:f78e57015038 83 return((unsigned char)c - 'a' + 10);
hudakz 0:f78e57015038 84 }
hudakz 0:f78e57015038 85
hudakz 0:f78e57015038 86 if (c >= 'A' && c <= 'F') {
hudakz 0:f78e57015038 87 return((unsigned char)c - 'A' + 10);
hudakz 0:f78e57015038 88 }
hudakz 0:f78e57015038 89
hudakz 0:f78e57015038 90 return(0);
hudakz 0:f78e57015038 91 }
hudakz 0:f78e57015038 92
hudakz 0:f78e57015038 93 // decode a url string e.g "hello%20joe" or "hello+joe" becomes "hello joe"
hudakz 0:f78e57015038 94 void urldecode(char* urlbuf)
hudakz 0:f78e57015038 95 {
hudakz 0:f78e57015038 96 char c;
hudakz 0:f78e57015038 97 char* dst;
hudakz 0:f78e57015038 98 dst = urlbuf;
hudakz 0:f78e57015038 99 while ((c = *urlbuf)) {
hudakz 0:f78e57015038 100 if (c == '+')
hudakz 0:f78e57015038 101 c = ' ';
hudakz 0:f78e57015038 102 if (c == '%') {
hudakz 0:f78e57015038 103 urlbuf++;
hudakz 0:f78e57015038 104 c = *urlbuf;
hudakz 0:f78e57015038 105 urlbuf++;
hudakz 0:f78e57015038 106 c = (h2int(c) << 4) | h2int(*urlbuf);
hudakz 0:f78e57015038 107 }
hudakz 0:f78e57015038 108
hudakz 0:f78e57015038 109 *dst = c;
hudakz 0:f78e57015038 110 dst++;
hudakz 0:f78e57015038 111 urlbuf++;
hudakz 0:f78e57015038 112 }
hudakz 0:f78e57015038 113
hudakz 0:f78e57015038 114 *dst = '\0';
hudakz 0:f78e57015038 115 }
hudakz 0:f78e57015038 116 #endif // FROMDECODE_websrv_help
hudakz 0:f78e57015038 117
hudakz 0:f78e57015038 118 #ifdef URLENCODE_websrv_help
hudakz 0:f78e57015038 119 // convert a single character to a 2 digit hex str
hudakz 0:f78e57015038 120
hudakz 0:f78e57015038 121 // a terminating '\0' is added
hudakz 0:f78e57015038 122 void int2h(char c, char* hstr)
hudakz 0:f78e57015038 123 {
hudakz 0:f78e57015038 124 hstr[1] = (c & 0xf) + '0';
hudakz 0:f78e57015038 125 if ((c & 0xf) > 9) {
hudakz 0:f78e57015038 126 hstr[1] = (c & 0xf) - 10 + 'a';
hudakz 0:f78e57015038 127 }
hudakz 0:f78e57015038 128
hudakz 0:f78e57015038 129 c = (c >> 4) & 0xf;
hudakz 0:f78e57015038 130 hstr[0] = c + '0';
hudakz 0:f78e57015038 131 if (c > 9) {
hudakz 0:f78e57015038 132 hstr[0] = c - 10 + 'a';
hudakz 0:f78e57015038 133 }
hudakz 0:f78e57015038 134
hudakz 0:f78e57015038 135 hstr[2] = '\0';
hudakz 0:f78e57015038 136 }
hudakz 0:f78e57015038 137
hudakz 0:f78e57015038 138 // There must be enough space in urlbuf. In the worst case that would be
hudakz 0:f78e57015038 139
hudakz 0:f78e57015038 140 // 3 times the length of str
hudakz 0:f78e57015038 141 void urlencode(const char* str, char* urlbuf)
hudakz 0:f78e57015038 142 {
hudakz 0:f78e57015038 143 char c;
hudakz 0:f78e57015038 144 while ((c = *str)) {
hudakz 0:f78e57015038 145 if (c == ' ' || isalnum(c)) {
hudakz 0:f78e57015038 146 if (c == ' ') {
hudakz 0:f78e57015038 147 c = '+';
hudakz 0:f78e57015038 148 }
hudakz 0:f78e57015038 149
hudakz 0:f78e57015038 150 *urlbuf = c;
hudakz 0:f78e57015038 151 str++;
hudakz 0:f78e57015038 152 urlbuf++;
hudakz 0:f78e57015038 153 continue;
hudakz 0:f78e57015038 154 }
hudakz 0:f78e57015038 155
hudakz 0:f78e57015038 156 *urlbuf = '%';
hudakz 0:f78e57015038 157 urlbuf++;
hudakz 0:f78e57015038 158 int2h(c, urlbuf);
hudakz 0:f78e57015038 159 urlbuf++;
hudakz 0:f78e57015038 160 urlbuf++;
hudakz 0:f78e57015038 161 str++;
hudakz 0:f78e57015038 162 }
hudakz 0:f78e57015038 163
hudakz 0:f78e57015038 164 *urlbuf = '\0';
hudakz 0:f78e57015038 165 }
hudakz 0:f78e57015038 166 #endif // URLENCODE_websrv_help
hudakz 0:f78e57015038 167
hudakz 0:f78e57015038 168 // parse a string that is an IP address and extract the IP to ip_byte_str
hudakz 0:f78e57015038 169 uint8_t parse_ip(uint8_t* ip_byte_str, const char* str)
hudakz 0:f78e57015038 170 {
hudakz 0:f78e57015038 171 char strbuf[4];
hudakz 0:f78e57015038 172 uint8_t bufpos = 0;
hudakz 0:f78e57015038 173 uint8_t i = 0;
hudakz 0:f78e57015038 174 while (i < 4) {
hudakz 0:f78e57015038 175 ip_byte_str[i] = 0;
hudakz 0:f78e57015038 176 i++;
hudakz 0:f78e57015038 177 }
hudakz 0:f78e57015038 178
hudakz 0:f78e57015038 179 i = 0;
hudakz 0:f78e57015038 180 while (*str && i < 4) {
hudakz 0:f78e57015038 181
hudakz 0:f78e57015038 182 // if a number then start
hudakz 0:f78e57015038 183 if (bufpos < 3 && isdigit(*str)) {
hudakz 0:f78e57015038 184 strbuf[bufpos] = *str; // copy
hudakz 0:f78e57015038 185 bufpos++;
hudakz 0:f78e57015038 186 }
hudakz 0:f78e57015038 187
hudakz 0:f78e57015038 188 if (bufpos && *str == '.') {
hudakz 0:f78e57015038 189 strbuf[bufpos] = '\0';
hudakz 0:f78e57015038 190 ip_byte_str[i] = (atoi(strbuf) & 0xff);
hudakz 0:f78e57015038 191 i++;
hudakz 0:f78e57015038 192 bufpos = 0;
hudakz 0:f78e57015038 193 }
hudakz 0:f78e57015038 194
hudakz 0:f78e57015038 195 str++;
hudakz 0:f78e57015038 196 }
hudakz 0:f78e57015038 197
hudakz 0:f78e57015038 198 if (i == 3) {
hudakz 0:f78e57015038 199
hudakz 0:f78e57015038 200 // must have read the first componets of the IP
hudakz 0:f78e57015038 201 strbuf[bufpos] = '\0';
hudakz 0:f78e57015038 202 ip_byte_str[i] = (atoi(strbuf) & 0xff);
hudakz 0:f78e57015038 203 return(0);
hudakz 0:f78e57015038 204 }
hudakz 0:f78e57015038 205
hudakz 0:f78e57015038 206 return(1);
hudakz 0:f78e57015038 207 }
hudakz 0:f78e57015038 208
hudakz 0:f78e57015038 209 // 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.
hudakz 0:f78e57015038 210 void mk_net_str(char* resultstr, uint8_t* ip_byte_str, uint8_t len, char separator, uint8_t base)
hudakz 0:f78e57015038 211 {
hudakz 0:f78e57015038 212 uint8_t i = 0;
hudakz 0:f78e57015038 213 uint8_t j = 0;
hudakz 0:f78e57015038 214 while (i < len) {
hudakz 0:f78e57015038 215 sprintf(resultstr, base == 10 ? "%i" : "%x", (int)ip_byte_str[i]);
hudakz 0:f78e57015038 216
hudakz 0:f78e57015038 217 // search end of str:
hudakz 0:f78e57015038 218 while (resultstr[j]) {
hudakz 0:f78e57015038 219 j++;
hudakz 0:f78e57015038 220 }
hudakz 0:f78e57015038 221
hudakz 0:f78e57015038 222 if (separator) {
hudakz 0:f78e57015038 223
hudakz 0:f78e57015038 224 // no separator, separator==NULL is as well possible, suggested by andras tucsni
hudakz 0:f78e57015038 225 resultstr[j] = separator;
hudakz 0:f78e57015038 226 j++;
hudakz 0:f78e57015038 227 }
hudakz 0:f78e57015038 228
hudakz 0:f78e57015038 229 i++;
hudakz 0:f78e57015038 230 }
hudakz 0:f78e57015038 231
hudakz 0:f78e57015038 232 j--;
hudakz 0:f78e57015038 233 resultstr[j] = '\0';
hudakz 0:f78e57015038 234 }