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
- Committer:
- iva2k
- Date:
- 2010-01-12
- Revision:
- 2:360fda42fefd
- Parent:
- 0:886e4b3119ad
File content as of revision 2:360fda42fefd:
// HTTPLinkStatus.h
// HTTP Server Logger class
//
// Provides:
// 1. ETH port link state monitor
// - lights LED for link
// - default: logs link state to stdout;
// - default: creates URL file on local filesystem (can be used to open browser to URL address)
// 2. HTTP activity monitor (does not react to non-http traffic)
// - blinks LED for activity / HTTP requests
// - optional: log activity to stdout
// - optional: log activity to file (file is opened for each log entry, so local file system can still be accessed via USB)
//
#ifndef HTTPLINKSTATUS_H
#define HTTPLINKSTATUS_H
#include "HTTPServer.h"
// FIXME: should we be able to get this from *con?
extern Ethernet eth; // eth is defined elsewhere, avoid compiler error.
namespace mbed {
class DigitalOutDelayed : public DigitalOut {
public:
DigitalOutDelayed(PinName pin, const char* name = NULL) : DigitalOut(pin, name) {}
void write(int value, float delay=0.0) {
_timeout.detach();
if (delay > 0.0) {
_delay_value = value;
_timeout.attach(this, &DigitalOutDelayed::_write_delayed, delay);
} else {
DigitalOut::write(value);
}
}
void write_us(int value, unsigned int delay_us=0) {
_timeout.detach();
if (delay_us > 0) {
_delay_value = value;
_timeout.attach_us(this, &DigitalOutDelayed::_write_delayed, delay_us);
} else {
DigitalOut::write(value);
}
}
#ifdef MBED_OPERATORS
using DigitalOut::operator = ;
using DigitalOut::operator int;
#endif
protected:
void _write_delayed(void) { DigitalOut::write(_delay_value); }
Timeout _timeout;
int _delay_value;
};
} // namespace mbed
class HTTPLinkStatus : public HTTPHandler {
public:
HTTPLinkStatus(const char *prefix, PinName link_led=NC, PinName act_led=NC, float poll_t = 0.1,
bool do_urlfile = true, bool do_link_printf = true, bool do_log_printf = false, const char* log_file = NULL
) :
HTTPHandler(prefix),
_link_led(link_led),
_act_led(act_led),
_linkstate(-1),
_first(true),
_our_ip(0),
_do_urlfile(do_urlfile),
_do_link_printf(do_link_printf),
_do_log_printf(do_log_printf),
_log_file(log_file)
{
if (poll_t > 0) _ticker.attach(this, &HTTPLinkStatus::_link_poll, poll_t);
}
HTTPLinkStatus(HTTPServer *server, const char *prefix, PinName link_led=NC, PinName act_led=NC, float poll_t = 0.1,
bool do_urlfile = true, bool do_link_printf = true, bool do_log_printf = false, const char* log_file = NULL
) :
HTTPHandler(prefix),
_link_led(link_led),
_act_led(act_led),
_linkstate(-1),
_first(true),
_our_ip(0),
_do_urlfile(do_urlfile),
_do_link_printf(do_link_printf),
_do_log_printf(do_log_printf),
_log_file(log_file)
{
server->addHandler(this);
if (poll_t > 0) _ticker.attach(this, &HTTPLinkStatus::_link_poll, poll_t);
}
virtual ~HTTPLinkStatus() {
_ticker.detach(); // Needeed?
}
void set_do_urlfile(bool val) { _do_urlfile = val; }
void set_link_stdout(bool val) { _do_link_printf = val; }
void set_log_stdout(bool val) { _do_log_printf = val; }
void set_log_file(const char *file) {
_log_file = file;
if (_log_file) {
FILE *fp = fopen(_log_file, "a");
if (fp) {
fprintf(fp, "======== HTTPLinkStatus NEW LOG OPENED ========\r\n");
fclose(fp);
} else {
_log_file = NULL; // Error opening file. Reset file name so we won't waste our time trying to log to it.
}
}
}
private:
void _link_poll() {
int new_linkstate = eth.link();
if (new_linkstate) {
// From http://mbed.org/forum/post/909/
NetServer *net = NetServer::get();
struct ip_addr ip = net->getIPAddr();
// struct ip_addr gw = net->getGateway();
// struct ip_addr nm = net->getNetmask();
// struct ip_addr dns = net->getDNS1();
if (ip.addr != _our_ip) {
if (!_first &&_do_link_printf) {
printf("IP: %hhu.%hhu.%hhu.%hhu\r\n",
(ip.addr)&0xFF, (ip.addr>>8)&0xFF, (ip.addr>>16)&0xFF, (ip.addr>>24)&0xFF);
}
_first = false;
if (_do_urlfile) {
// Create a link file to our IP.
FILE *fp = fopen("/local/Start.url", "w"); // Create a link to own IP
if (fp) {
fprintf(fp, "[InternetShortcut]\r\nURL=http://%hhu.%hhu.%hhu.%hhu/\r\n",
(ip.addr)&0xFF, (ip.addr>>8)&0xFF, (ip.addr>>16)&0xFF, (ip.addr>>24)&0xFF);
fclose(fp);
}
}
_our_ip = ip.addr;
}
}
else {
if (_do_link_printf && _linkstate != new_linkstate) {
printf("IP: <link down>\r\n");
}
}
_link_led = new_linkstate;
_linkstate = new_linkstate;
}
virtual HTTPHandle action(HTTPConnection *con) const {
_act_led = 1;
// struct ip_addr ip = con->_pcb()->remote_ip;
struct ip_addr ip = con->get_remote_ip(); // This requires a patch to TCPConnection.h file in lwip/Core
if (_do_log_printf) {
printf("HTTPStatus IP: %hhu.%hhu.%hhu.%hhu %s %s\r\n",
(ip.addr)&0xFF, (ip.addr>>8)&0xFF, (ip.addr>>16)&0xFF, (ip.addr>>24)&0xFF,
(con->getType() == POST? "POST" : "GET "), con->getURL()
);
}
if (_log_file) {
FILE *fp = fopen(_log_file, "a");
if (fp) {
fprintf(fp, "HTTPStatus IP: %hhu.%hhu.%hhu.%hhu %s %s\r\n",
(ip.addr)&0xFF, (ip.addr>>8)&0xFF, (ip.addr>>16)&0xFF, (ip.addr>>24)&0xFF,
(con->getType() == POST? "POST" : "GET "), con->getURL()
);
fclose(fp);
}
}
_act_led.write(0, 0.050); // Delayed write
return HTTP_AddFields;
}
DigitalOut _link_led; // Link status LED
mutable DigitalOutDelayed _act_led; // Link activity LED. Need "mutable" keyword to let it be changed from within action() const function.
Ticker _ticker; // State polling timer
int _linkstate; // Last state of eth link
bool _first; // Avoid duplicate IP report on the very first pass
unsigned int _our_ip; // Our last IP address (used for _do_urlfile)
bool _do_urlfile; // True for creating url (link) to self on local file system /local/Start.url
bool _do_link_printf; // True for printing to stdout
bool _do_log_printf; // True for printing activity log to stdout
const char *_log_file; // Optional file for activity logging
};
#endif