Example of HTTPServer with additional features: * SNTPClient, DST rules * Link status indication * Local or SDCard-based WebServer * RPC-able class * Static and Dynamic HTML page
HTTPLinkStatus.h@2:360fda42fefd, 2010-01-12 (annotated)
- Committer:
- iva2k
- Date:
- Tue Jan 12 07:41:55 2010 +0000
- Revision:
- 2:360fda42fefd
- Parent:
- 0:886e4b3119ad
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
iva2k | 0:886e4b3119ad | 1 | // HTTPLinkStatus.h |
iva2k | 0:886e4b3119ad | 2 | // HTTP Server Logger class |
iva2k | 0:886e4b3119ad | 3 | // |
iva2k | 0:886e4b3119ad | 4 | // Provides: |
iva2k | 0:886e4b3119ad | 5 | // 1. ETH port link state monitor |
iva2k | 0:886e4b3119ad | 6 | // - lights LED for link |
iva2k | 0:886e4b3119ad | 7 | // - default: logs link state to stdout; |
iva2k | 0:886e4b3119ad | 8 | // - default: creates URL file on local filesystem (can be used to open browser to URL address) |
iva2k | 0:886e4b3119ad | 9 | // 2. HTTP activity monitor (does not react to non-http traffic) |
iva2k | 0:886e4b3119ad | 10 | // - blinks LED for activity / HTTP requests |
iva2k | 0:886e4b3119ad | 11 | // - optional: log activity to stdout |
iva2k | 0:886e4b3119ad | 12 | // - optional: log activity to file (file is opened for each log entry, so local file system can still be accessed via USB) |
iva2k | 0:886e4b3119ad | 13 | // |
iva2k | 0:886e4b3119ad | 14 | |
iva2k | 0:886e4b3119ad | 15 | #ifndef HTTPLINKSTATUS_H |
iva2k | 0:886e4b3119ad | 16 | #define HTTPLINKSTATUS_H |
iva2k | 0:886e4b3119ad | 17 | |
iva2k | 0:886e4b3119ad | 18 | #include "HTTPServer.h" |
iva2k | 0:886e4b3119ad | 19 | |
iva2k | 0:886e4b3119ad | 20 | // FIXME: should we be able to get this from *con? |
iva2k | 0:886e4b3119ad | 21 | extern Ethernet eth; // eth is defined elsewhere, avoid compiler error. |
iva2k | 0:886e4b3119ad | 22 | |
iva2k | 0:886e4b3119ad | 23 | namespace mbed { |
iva2k | 0:886e4b3119ad | 24 | |
iva2k | 0:886e4b3119ad | 25 | class DigitalOutDelayed : public DigitalOut { |
iva2k | 0:886e4b3119ad | 26 | public: |
iva2k | 0:886e4b3119ad | 27 | DigitalOutDelayed(PinName pin, const char* name = NULL) : DigitalOut(pin, name) {} |
iva2k | 0:886e4b3119ad | 28 | void write(int value, float delay=0.0) { |
iva2k | 0:886e4b3119ad | 29 | _timeout.detach(); |
iva2k | 0:886e4b3119ad | 30 | if (delay > 0.0) { |
iva2k | 0:886e4b3119ad | 31 | _delay_value = value; |
iva2k | 0:886e4b3119ad | 32 | _timeout.attach(this, &DigitalOutDelayed::_write_delayed, delay); |
iva2k | 0:886e4b3119ad | 33 | } else { |
iva2k | 0:886e4b3119ad | 34 | DigitalOut::write(value); |
iva2k | 0:886e4b3119ad | 35 | } |
iva2k | 0:886e4b3119ad | 36 | } |
iva2k | 0:886e4b3119ad | 37 | void write_us(int value, unsigned int delay_us=0) { |
iva2k | 0:886e4b3119ad | 38 | _timeout.detach(); |
iva2k | 0:886e4b3119ad | 39 | if (delay_us > 0) { |
iva2k | 0:886e4b3119ad | 40 | _delay_value = value; |
iva2k | 0:886e4b3119ad | 41 | _timeout.attach_us(this, &DigitalOutDelayed::_write_delayed, delay_us); |
iva2k | 0:886e4b3119ad | 42 | } else { |
iva2k | 0:886e4b3119ad | 43 | DigitalOut::write(value); |
iva2k | 0:886e4b3119ad | 44 | } |
iva2k | 0:886e4b3119ad | 45 | } |
iva2k | 0:886e4b3119ad | 46 | #ifdef MBED_OPERATORS |
iva2k | 0:886e4b3119ad | 47 | using DigitalOut::operator = ; |
iva2k | 0:886e4b3119ad | 48 | using DigitalOut::operator int; |
iva2k | 0:886e4b3119ad | 49 | #endif |
iva2k | 0:886e4b3119ad | 50 | |
iva2k | 0:886e4b3119ad | 51 | protected: |
iva2k | 0:886e4b3119ad | 52 | void _write_delayed(void) { DigitalOut::write(_delay_value); } |
iva2k | 0:886e4b3119ad | 53 | Timeout _timeout; |
iva2k | 0:886e4b3119ad | 54 | int _delay_value; |
iva2k | 0:886e4b3119ad | 55 | }; |
iva2k | 0:886e4b3119ad | 56 | |
iva2k | 0:886e4b3119ad | 57 | } // namespace mbed |
iva2k | 0:886e4b3119ad | 58 | |
iva2k | 0:886e4b3119ad | 59 | class HTTPLinkStatus : public HTTPHandler { |
iva2k | 0:886e4b3119ad | 60 | public: |
iva2k | 0:886e4b3119ad | 61 | HTTPLinkStatus(const char *prefix, PinName link_led=NC, PinName act_led=NC, float poll_t = 0.1, |
iva2k | 0:886e4b3119ad | 62 | bool do_urlfile = true, bool do_link_printf = true, bool do_log_printf = false, const char* log_file = NULL |
iva2k | 0:886e4b3119ad | 63 | ) : |
iva2k | 0:886e4b3119ad | 64 | HTTPHandler(prefix), |
iva2k | 0:886e4b3119ad | 65 | _link_led(link_led), |
iva2k | 0:886e4b3119ad | 66 | _act_led(act_led), |
iva2k | 0:886e4b3119ad | 67 | _linkstate(-1), |
iva2k | 0:886e4b3119ad | 68 | _first(true), |
iva2k | 0:886e4b3119ad | 69 | _our_ip(0), |
iva2k | 0:886e4b3119ad | 70 | _do_urlfile(do_urlfile), |
iva2k | 0:886e4b3119ad | 71 | _do_link_printf(do_link_printf), |
iva2k | 0:886e4b3119ad | 72 | _do_log_printf(do_log_printf), |
iva2k | 0:886e4b3119ad | 73 | _log_file(log_file) |
iva2k | 0:886e4b3119ad | 74 | { |
iva2k | 0:886e4b3119ad | 75 | if (poll_t > 0) _ticker.attach(this, &HTTPLinkStatus::_link_poll, poll_t); |
iva2k | 0:886e4b3119ad | 76 | } |
iva2k | 0:886e4b3119ad | 77 | HTTPLinkStatus(HTTPServer *server, const char *prefix, PinName link_led=NC, PinName act_led=NC, float poll_t = 0.1, |
iva2k | 0:886e4b3119ad | 78 | bool do_urlfile = true, bool do_link_printf = true, bool do_log_printf = false, const char* log_file = NULL |
iva2k | 0:886e4b3119ad | 79 | ) : |
iva2k | 0:886e4b3119ad | 80 | HTTPHandler(prefix), |
iva2k | 0:886e4b3119ad | 81 | _link_led(link_led), |
iva2k | 0:886e4b3119ad | 82 | _act_led(act_led), |
iva2k | 0:886e4b3119ad | 83 | _linkstate(-1), |
iva2k | 0:886e4b3119ad | 84 | _first(true), |
iva2k | 0:886e4b3119ad | 85 | _our_ip(0), |
iva2k | 0:886e4b3119ad | 86 | _do_urlfile(do_urlfile), |
iva2k | 0:886e4b3119ad | 87 | _do_link_printf(do_link_printf), |
iva2k | 0:886e4b3119ad | 88 | _do_log_printf(do_log_printf), |
iva2k | 0:886e4b3119ad | 89 | _log_file(log_file) |
iva2k | 0:886e4b3119ad | 90 | { |
iva2k | 0:886e4b3119ad | 91 | server->addHandler(this); |
iva2k | 0:886e4b3119ad | 92 | if (poll_t > 0) _ticker.attach(this, &HTTPLinkStatus::_link_poll, poll_t); |
iva2k | 0:886e4b3119ad | 93 | } |
iva2k | 0:886e4b3119ad | 94 | virtual ~HTTPLinkStatus() { |
iva2k | 0:886e4b3119ad | 95 | _ticker.detach(); // Needeed? |
iva2k | 0:886e4b3119ad | 96 | } |
iva2k | 0:886e4b3119ad | 97 | void set_do_urlfile(bool val) { _do_urlfile = val; } |
iva2k | 0:886e4b3119ad | 98 | void set_link_stdout(bool val) { _do_link_printf = val; } |
iva2k | 0:886e4b3119ad | 99 | void set_log_stdout(bool val) { _do_log_printf = val; } |
iva2k | 0:886e4b3119ad | 100 | void set_log_file(const char *file) { |
iva2k | 0:886e4b3119ad | 101 | _log_file = file; |
iva2k | 0:886e4b3119ad | 102 | if (_log_file) { |
iva2k | 0:886e4b3119ad | 103 | FILE *fp = fopen(_log_file, "a"); |
iva2k | 0:886e4b3119ad | 104 | if (fp) { |
iva2k | 0:886e4b3119ad | 105 | fprintf(fp, "======== HTTPLinkStatus NEW LOG OPENED ========\r\n"); |
iva2k | 0:886e4b3119ad | 106 | fclose(fp); |
iva2k | 0:886e4b3119ad | 107 | } else { |
iva2k | 0:886e4b3119ad | 108 | _log_file = NULL; // Error opening file. Reset file name so we won't waste our time trying to log to it. |
iva2k | 0:886e4b3119ad | 109 | } |
iva2k | 0:886e4b3119ad | 110 | } |
iva2k | 0:886e4b3119ad | 111 | } |
iva2k | 0:886e4b3119ad | 112 | private: |
iva2k | 0:886e4b3119ad | 113 | void _link_poll() { |
iva2k | 0:886e4b3119ad | 114 | int new_linkstate = eth.link(); |
iva2k | 0:886e4b3119ad | 115 | if (new_linkstate) { |
iva2k | 0:886e4b3119ad | 116 | // From http://mbed.org/forum/post/909/ |
iva2k | 0:886e4b3119ad | 117 | NetServer *net = NetServer::get(); |
iva2k | 0:886e4b3119ad | 118 | struct ip_addr ip = net->getIPAddr(); |
iva2k | 0:886e4b3119ad | 119 | // struct ip_addr gw = net->getGateway(); |
iva2k | 0:886e4b3119ad | 120 | // struct ip_addr nm = net->getNetmask(); |
iva2k | 0:886e4b3119ad | 121 | // struct ip_addr dns = net->getDNS1(); |
iva2k | 0:886e4b3119ad | 122 | if (ip.addr != _our_ip) { |
iva2k | 0:886e4b3119ad | 123 | if (!_first &&_do_link_printf) { |
iva2k | 0:886e4b3119ad | 124 | printf("IP: %hhu.%hhu.%hhu.%hhu\r\n", |
iva2k | 0:886e4b3119ad | 125 | (ip.addr)&0xFF, (ip.addr>>8)&0xFF, (ip.addr>>16)&0xFF, (ip.addr>>24)&0xFF); |
iva2k | 0:886e4b3119ad | 126 | } |
iva2k | 0:886e4b3119ad | 127 | _first = false; |
iva2k | 0:886e4b3119ad | 128 | if (_do_urlfile) { |
iva2k | 0:886e4b3119ad | 129 | // Create a link file to our IP. |
iva2k | 0:886e4b3119ad | 130 | FILE *fp = fopen("/local/Start.url", "w"); // Create a link to own IP |
iva2k | 0:886e4b3119ad | 131 | if (fp) { |
iva2k | 0:886e4b3119ad | 132 | fprintf(fp, "[InternetShortcut]\r\nURL=http://%hhu.%hhu.%hhu.%hhu/\r\n", |
iva2k | 0:886e4b3119ad | 133 | (ip.addr)&0xFF, (ip.addr>>8)&0xFF, (ip.addr>>16)&0xFF, (ip.addr>>24)&0xFF); |
iva2k | 0:886e4b3119ad | 134 | fclose(fp); |
iva2k | 0:886e4b3119ad | 135 | } |
iva2k | 0:886e4b3119ad | 136 | } |
iva2k | 0:886e4b3119ad | 137 | _our_ip = ip.addr; |
iva2k | 0:886e4b3119ad | 138 | } |
iva2k | 0:886e4b3119ad | 139 | } |
iva2k | 0:886e4b3119ad | 140 | else { |
iva2k | 0:886e4b3119ad | 141 | if (_do_link_printf && _linkstate != new_linkstate) { |
iva2k | 0:886e4b3119ad | 142 | printf("IP: <link down>\r\n"); |
iva2k | 0:886e4b3119ad | 143 | } |
iva2k | 0:886e4b3119ad | 144 | } |
iva2k | 0:886e4b3119ad | 145 | _link_led = new_linkstate; |
iva2k | 0:886e4b3119ad | 146 | _linkstate = new_linkstate; |
iva2k | 0:886e4b3119ad | 147 | } |
iva2k | 0:886e4b3119ad | 148 | |
iva2k | 0:886e4b3119ad | 149 | virtual HTTPHandle action(HTTPConnection *con) const { |
iva2k | 0:886e4b3119ad | 150 | _act_led = 1; |
iva2k | 0:886e4b3119ad | 151 | // struct ip_addr ip = con->_pcb()->remote_ip; |
iva2k | 0:886e4b3119ad | 152 | struct ip_addr ip = con->get_remote_ip(); // This requires a patch to TCPConnection.h file in lwip/Core |
iva2k | 0:886e4b3119ad | 153 | if (_do_log_printf) { |
iva2k | 0:886e4b3119ad | 154 | printf("HTTPStatus IP: %hhu.%hhu.%hhu.%hhu %s %s\r\n", |
iva2k | 0:886e4b3119ad | 155 | (ip.addr)&0xFF, (ip.addr>>8)&0xFF, (ip.addr>>16)&0xFF, (ip.addr>>24)&0xFF, |
iva2k | 0:886e4b3119ad | 156 | (con->getType() == POST? "POST" : "GET "), con->getURL() |
iva2k | 0:886e4b3119ad | 157 | ); |
iva2k | 0:886e4b3119ad | 158 | } |
iva2k | 0:886e4b3119ad | 159 | if (_log_file) { |
iva2k | 0:886e4b3119ad | 160 | FILE *fp = fopen(_log_file, "a"); |
iva2k | 0:886e4b3119ad | 161 | if (fp) { |
iva2k | 0:886e4b3119ad | 162 | fprintf(fp, "HTTPStatus IP: %hhu.%hhu.%hhu.%hhu %s %s\r\n", |
iva2k | 0:886e4b3119ad | 163 | (ip.addr)&0xFF, (ip.addr>>8)&0xFF, (ip.addr>>16)&0xFF, (ip.addr>>24)&0xFF, |
iva2k | 0:886e4b3119ad | 164 | (con->getType() == POST? "POST" : "GET "), con->getURL() |
iva2k | 0:886e4b3119ad | 165 | ); |
iva2k | 0:886e4b3119ad | 166 | fclose(fp); |
iva2k | 0:886e4b3119ad | 167 | } |
iva2k | 0:886e4b3119ad | 168 | } |
iva2k | 0:886e4b3119ad | 169 | _act_led.write(0, 0.050); // Delayed write |
iva2k | 0:886e4b3119ad | 170 | return HTTP_AddFields; |
iva2k | 0:886e4b3119ad | 171 | } |
iva2k | 0:886e4b3119ad | 172 | |
iva2k | 0:886e4b3119ad | 173 | DigitalOut _link_led; // Link status LED |
iva2k | 0:886e4b3119ad | 174 | mutable DigitalOutDelayed _act_led; // Link activity LED. Need "mutable" keyword to let it be changed from within action() const function. |
iva2k | 0:886e4b3119ad | 175 | Ticker _ticker; // State polling timer |
iva2k | 0:886e4b3119ad | 176 | int _linkstate; // Last state of eth link |
iva2k | 0:886e4b3119ad | 177 | bool _first; // Avoid duplicate IP report on the very first pass |
iva2k | 0:886e4b3119ad | 178 | unsigned int _our_ip; // Our last IP address (used for _do_urlfile) |
iva2k | 0:886e4b3119ad | 179 | bool _do_urlfile; // True for creating url (link) to self on local file system /local/Start.url |
iva2k | 0:886e4b3119ad | 180 | bool _do_link_printf; // True for printing to stdout |
iva2k | 0:886e4b3119ad | 181 | bool _do_log_printf; // True for printing activity log to stdout |
iva2k | 0:886e4b3119ad | 182 | const char *_log_file; // Optional file for activity logging |
iva2k | 0:886e4b3119ad | 183 | }; |
iva2k | 0:886e4b3119ad | 184 | |
iva2k | 0:886e4b3119ad | 185 | #endif |