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

Dependencies:   mbed

Committer:
iva2k
Date:
Tue Jan 12 07:41:55 2010 +0000
Revision:
2:360fda42fefd
Parent:
0:886e4b3119ad

        

Who changed what in which revision?

UserRevisionLine numberNew 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