Dirk-Willem van Gulik (NXP/mbed)
/
AmpereMeter
Example self-announcing webserver which controls a servo through a smallHTML userinterface.
main.cpp@0:a259777c45a3, 2010-08-14 (annotated)
- Committer:
- dirkx
- Date:
- Sat Aug 14 15:56:01 2010 +0000
- Revision:
- 0:a259777c45a3
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dirkx | 0:a259777c45a3 | 1 | #include "mbed.h" |
dirkx | 0:a259777c45a3 | 2 | |
dirkx | 0:a259777c45a3 | 3 | #include "Servo.h" |
dirkx | 0:a259777c45a3 | 4 | |
dirkx | 0:a259777c45a3 | 5 | #include "EthernetNetIf.h" |
dirkx | 0:a259777c45a3 | 6 | #include "HTTPServer.h" |
dirkx | 0:a259777c45a3 | 7 | |
dirkx | 0:a259777c45a3 | 8 | #include "mDNSResponder.h" |
dirkx | 0:a259777c45a3 | 9 | |
dirkx | 0:a259777c45a3 | 10 | #include "RestMeterHandler.h" |
dirkx | 0:a259777c45a3 | 11 | |
dirkx | 0:a259777c45a3 | 12 | |
dirkx | 0:a259777c45a3 | 13 | #define __DEBUG |
dirkx | 0:a259777c45a3 | 14 | #include "dbg/dbg.h" |
dirkx | 0:a259777c45a3 | 15 | |
dirkx | 0:a259777c45a3 | 16 | // Hardware I/O |
dirkx | 0:a259777c45a3 | 17 | // |
dirkx | 0:a259777c45a3 | 18 | Servo myservo(p21); |
dirkx | 0:a259777c45a3 | 19 | DigitalOut netPoll(LED1); |
dirkx | 0:a259777c45a3 | 20 | DigitalOut servoChange(LED2); |
dirkx | 0:a259777c45a3 | 21 | |
dirkx | 0:a259777c45a3 | 22 | // Ethernet, webserver and Bonjour responder |
dirkx | 0:a259777c45a3 | 23 | // |
dirkx | 0:a259777c45a3 | 24 | EthernetNetIf eth; |
dirkx | 0:a259777c45a3 | 25 | HTTPServer srv; |
dirkx | 0:a259777c45a3 | 26 | mDNSResponder mdns; // make sure LWIP_IGMP is set in netCfg.h ! |
dirkx | 0:a259777c45a3 | 27 | |
dirkx | 0:a259777c45a3 | 28 | #define MYNAME "Ampere Meter" // Human readable/descriptive name |
dirkx | 0:a259777c45a3 | 29 | #define LUDN "amp-meter" // Local unqualified DNS name |
dirkx | 0:a259777c45a3 | 30 | |
dirkx | 0:a259777c45a3 | 31 | #define RANGE 0.80 // scale of 0 .. 1 -- see Servo |
dirkx | 0:a259777c45a3 | 32 | #define MIN 0.36 // scale of 0 .. 1 |
dirkx | 0:a259777c45a3 | 33 | #define STEP (RANGE / 20) |
dirkx | 0:a259777c45a3 | 34 | |
dirkx | 0:a259777c45a3 | 35 | float pos = MIN + RANGE/2; |
dirkx | 0:a259777c45a3 | 36 | |
dirkx | 0:a259777c45a3 | 37 | const char * restCallback(const char * cmd) |
dirkx | 0:a259777c45a3 | 38 | { |
dirkx | 0:a259777c45a3 | 39 | static char resp[2048]; |
dirkx | 0:a259777c45a3 | 40 | |
dirkx | 0:a259777c45a3 | 41 | if (cmd && (!strcmp(cmd,"min"))) |
dirkx | 0:a259777c45a3 | 42 | pos -= STEP; |
dirkx | 0:a259777c45a3 | 43 | if (cmd && (!strcmp(cmd,"plus"))) |
dirkx | 0:a259777c45a3 | 44 | pos += STEP; |
dirkx | 0:a259777c45a3 | 45 | |
dirkx | 0:a259777c45a3 | 46 | if (pos > MIN+RANGE) pos = MIN + RANGE; |
dirkx | 0:a259777c45a3 | 47 | if (pos < MIN) pos = MIN; |
dirkx | 0:a259777c45a3 | 48 | |
dirkx | 0:a259777c45a3 | 49 | myservo = pos; |
dirkx | 0:a259777c45a3 | 50 | servoChange = !servoChange; |
dirkx | 0:a259777c45a3 | 51 | |
dirkx | 0:a259777c45a3 | 52 | snprintf(resp, sizeof(resp), |
dirkx | 0:a259777c45a3 | 53 | "<head><title>%s</title></head>" |
dirkx | 0:a259777c45a3 | 54 | "<body>" |
dirkx | 0:a259777c45a3 | 55 | "<center><h1><hr/>%s<hr/></h1>", MYNAME, MYNAME); |
dirkx | 0:a259777c45a3 | 56 | |
dirkx | 0:a259777c45a3 | 57 | // small HTML table to give a visual display |
dirkx | 0:a259777c45a3 | 58 | // of the value as a VU style bar. |
dirkx | 0:a259777c45a3 | 59 | snprintf(resp+strlen(resp), sizeof(resp)-strlen(resp), |
dirkx | 0:a259777c45a3 | 60 | "<table cellpadding=2><tr>"); |
dirkx | 0:a259777c45a3 | 61 | |
dirkx | 0:a259777c45a3 | 62 | for(int i = 0; i < 20; i++) |
dirkx | 0:a259777c45a3 | 63 | snprintf(resp+strlen(resp), sizeof(resp)-strlen(resp), |
dirkx | 0:a259777c45a3 | 64 | "<td bgcolor=%s width=10px height=10px> </td>", |
dirkx | 0:a259777c45a3 | 65 | ((pos - MIN) * 20 / RANGE > i) ? "444444" : "dddddd"); |
dirkx | 0:a259777c45a3 | 66 | |
dirkx | 0:a259777c45a3 | 67 | snprintf(resp+strlen(resp), sizeof(resp)-strlen(resp), |
dirkx | 0:a259777c45a3 | 68 | "</tr><table><br>"); |
dirkx | 0:a259777c45a3 | 69 | |
dirkx | 0:a259777c45a3 | 70 | // footer with the 2 plus/minus command options. |
dirkx | 0:a259777c45a3 | 71 | // |
dirkx | 0:a259777c45a3 | 72 | snprintf(resp+strlen(resp), sizeof(resp)-strlen(resp), |
dirkx | 0:a259777c45a3 | 73 | "<a href='?cmd=min'><</a> <font size=+5>[%1.3f]</font> <a href='?cmd=plus'>></a>" |
dirkx | 0:a259777c45a3 | 74 | "</center></body>", pos); |
dirkx | 0:a259777c45a3 | 75 | |
dirkx | 0:a259777c45a3 | 76 | return resp; |
dirkx | 0:a259777c45a3 | 77 | } |
dirkx | 0:a259777c45a3 | 78 | |
dirkx | 0:a259777c45a3 | 79 | int main() { |
dirkx | 0:a259777c45a3 | 80 | DBG("\n\r\n\r" |
dirkx | 0:a259777c45a3 | 81 | "Compiled " MYNAME " (" LUDN ") on " __DATE__ " " __TIME__ |
dirkx | 0:a259777c45a3 | 82 | "\r\n" |
dirkx | 0:a259777c45a3 | 83 | ); |
dirkx | 0:a259777c45a3 | 84 | netPoll = 0; |
dirkx | 0:a259777c45a3 | 85 | |
dirkx | 0:a259777c45a3 | 86 | // middle the servo |
dirkx | 0:a259777c45a3 | 87 | pos = MIN + RANGE/2; |
dirkx | 0:a259777c45a3 | 88 | myservo = pos; |
dirkx | 0:a259777c45a3 | 89 | |
dirkx | 0:a259777c45a3 | 90 | EthernetErr ethErr = eth.setup(); |
dirkx | 0:a259777c45a3 | 91 | if (ethErr) { |
dirkx | 0:a259777c45a3 | 92 | printf("Error %d in setup on DHCP.\r\n", ethErr); |
dirkx | 0:a259777c45a3 | 93 | return -1; |
dirkx | 0:a259777c45a3 | 94 | } |
dirkx | 0:a259777c45a3 | 95 | |
dirkx | 0:a259777c45a3 | 96 | // for general static content. |
dirkx | 0:a259777c45a3 | 97 | FSHandler::mount("/webfs", "/htdocs"); // Mount /webfs path on html docroot |
dirkx | 0:a259777c45a3 | 98 | srv.addHandler<FSHandler>("/icons"); |
dirkx | 0:a259777c45a3 | 99 | |
dirkx | 0:a259777c45a3 | 100 | // handling the commands/dynamic pages |
dirkx | 0:a259777c45a3 | 101 | // |
dirkx | 0:a259777c45a3 | 102 | RestMeterHandler::attach(&restCallback); |
dirkx | 0:a259777c45a3 | 103 | srv.addHandler<RestMeterHandler>("/"); |
dirkx | 0:a259777c45a3 | 104 | |
dirkx | 0:a259777c45a3 | 105 | // start the webserver |
dirkx | 0:a259777c45a3 | 106 | srv.bind(80); |
dirkx | 0:a259777c45a3 | 107 | |
dirkx | 0:a259777c45a3 | 108 | // Announce above web server - and keep doing that every minute or so. |
dirkx | 0:a259777c45a3 | 109 | // |
dirkx | 0:a259777c45a3 | 110 | mdns.announce( |
dirkx | 0:a259777c45a3 | 111 | eth.getIp(), // (My) IP address - where announced service runs. |
dirkx | 0:a259777c45a3 | 112 | LUDN, // DNS name server or service |
dirkx | 0:a259777c45a3 | 113 | "_http._tcp", // protocol |
dirkx | 0:a259777c45a3 | 114 | 80, // Port number |
dirkx | 0:a259777c45a3 | 115 | MYNAME, // User interface name service |
dirkx | 0:a259777c45a3 | 116 | (char *[]) { // NULL terminated list of KV's = see |
dirkx | 0:a259777c45a3 | 117 | "path=/", // http://www.zeroconf.org/Rendezvous/txtrecords.html |
dirkx | 0:a259777c45a3 | 118 | NULL |
dirkx | 0:a259777c45a3 | 119 | } |
dirkx | 0:a259777c45a3 | 120 | ); |
dirkx | 0:a259777c45a3 | 121 | |
dirkx | 0:a259777c45a3 | 122 | #if __DEEBUG |
dirkx | 0:a259777c45a3 | 123 | Ip ip = eth.getIp(); |
dirkx | 0:a259777c45a3 | 124 | DBG("Visible as http://" LUDN ".lcoal/ or http://%d.%d.%d.%d/\r\n", ip[0],ip[1],ip[2],ip[3]); |
dirkx | 0:a259777c45a3 | 125 | #endif |
dirkx | 0:a259777c45a3 | 126 | |
dirkx | 0:a259777c45a3 | 127 | netPoll = 1; |
dirkx | 0:a259777c45a3 | 128 | unsigned char c = 0; |
dirkx | 0:a259777c45a3 | 129 | while(true) { |
dirkx | 0:a259777c45a3 | 130 | netPoll = ! netPoll; // flash net polling LED for geedback. |
dirkx | 0:a259777c45a3 | 131 | Net::poll(); |
dirkx | 0:a259777c45a3 | 132 | } |
dirkx | 0:a259777c45a3 | 133 | } // main |