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:
1:ec4170739967

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
iva2k 0:886e4b3119ad 1 // Written by IVA2K
iva2k 0:886e4b3119ad 2 //
iva2k 0:886e4b3119ad 3 // Example of HTTPServer with additional features:
iva2k 0:886e4b3119ad 4 // * SNTP Client (Simple NTP)
iva2k 0:886e4b3119ad 5 // * Link status indication (LED4 or RJ45 socket LED on MBED-BoB2-mod)
iva2k 0:886e4b3119ad 6 // * Local file system (create index.htm page on MBED!)
iva2k 0:886e4b3119ad 7 // * SD-based WebServer
iva2k 0:886e4b3119ad 8 // * RPC-able class (myrpc, allows remote function call that blinks LED1 N times)
iva2k 0:886e4b3119ad 9 // * Static HTML page
iva2k 0:886e4b3119ad 10 // * Dynamic HTML page
iva2k 0:886e4b3119ad 11 //
iva2k 0:886e4b3119ad 12 // Instructions:
iva2k 0:886e4b3119ad 13 // 1 Plug MBED into MBED-BoB2 (or other ETH connector breakout)
iva2k 0:886e4b3119ad 14 // 2 Plug ETH connector into your network (needs DHCP to get IP address and Internet connection)
iva2k 0:886e4b3119ad 15 // 3 Power up MBED using USB cable
iva2k 0:886e4b3119ad 16 // 4 Install MBED serial driver (http://mbed.org/handbook/SerialPC)
iva2k 0:886e4b3119ad 17 // 5 Copy compiled .bin to your MBED (make sure target device selected in the compiler is correct)
iva2k 0:886e4b3119ad 18 // 6 Open terminal on the mbed serial port
iva2k 0:886e4b3119ad 19 // 7 Push MBED reset button
iva2k 0:886e4b3119ad 20 // 8 Terminal will display info message with mac address, followed by IP address (if connection succeeds)
iva2k 0:886e4b3119ad 21 // in the following items, replace 10.0.0.321 with actual MBED IP address from the terminal
iva2k 0:886e4b3119ad 22 // 9 Open browser and enter the following URL:
iva2k 0:886e4b3119ad 23 // http://10.0.0.321/rpc/myrpc1/blink,10
iva2k 0:886e4b3119ad 24 // 10 MBED will blink the LED 10 times
iva2k 0:886e4b3119ad 25 // 11 Open browser and enter the following URL:
iva2k 0:886e4b3119ad 26 // http://10.0.0.321/rpc/myrpc1/gettime
iva2k 0:886e4b3119ad 27 // 12 The browser will show date and time from the MBED synchronized to NTP server
iva2k 0:886e4b3119ad 28 // 13 Open browser and enter the following URL:
iva2k 0:886e4b3119ad 29 // http://10.0.0.321/static.htm
iva2k 0:886e4b3119ad 30 // 14 The browser will show static HTML page
iva2k 0:886e4b3119ad 31 // 15 Open browser and enter the following URL:
iva2k 0:886e4b3119ad 32 // http://10.0.0.321/dynamic.htm
iva2k 0:886e4b3119ad 33 // 16 The browser will show dynamic HTML page
iva2k 0:886e4b3119ad 34 // 17 Create a simple index.htm page on the MBED
iva2k 0:886e4b3119ad 35 // 18 Open browser and enter the following URL:
iva2k 0:886e4b3119ad 36 // http://10.0.0.321
iva2k 0:886e4b3119ad 37 // 19 The browser will show index HTML page
iva2k 0:886e4b3119ad 38 // 20 Create a simple index.htm page on a micro SD card, plug the card into MBED-BoB2
iva2k 0:886e4b3119ad 39 // 21 Open browser and enter the following URL:
iva2k 0:886e4b3119ad 40 // http://10.0.0.321
iva2k 0:886e4b3119ad 41 // 22 The browser will show index HTML page from SD card
iva2k 0:886e4b3119ad 42 // 23 Optionally, create file "sntp.ini" on MBED or SD card. Copy-paste SNTP configuration from the terminal into this file and modify to your needs.
iva2k 0:886e4b3119ad 43 //
iva2k 0:886e4b3119ad 44 // Notes: there are still some bugs in HTTPServer code.
iva2k 0:886e4b3119ad 45 // To help fight some of them, copy a valid favicon.ico (a 16x16 icon) file to MBED.
iva2k 0:886e4b3119ad 46 //
iva2k 0:886e4b3119ad 47
iva2k 0:886e4b3119ad 48 #include "mbed.h"
iva2k 0:886e4b3119ad 49 #include "SDFileSystem.h"
iva2k 0:886e4b3119ad 50 #include "HTTPServer.h"
iva2k 0:886e4b3119ad 51 #include "HTTPRPC.h"
iva2k 0:886e4b3119ad 52 #include "HTTPFS.h"
iva2k 0:886e4b3119ad 53 #include "HTTPStaticPage.h"
iva2k 0:886e4b3119ad 54 #include "HTTPDynamicPage.h"
iva2k 0:886e4b3119ad 55 #include "HTTPLinkStatus.h"
iva2k 0:886e4b3119ad 56 #include "SNTPClient.h"
iva2k 0:886e4b3119ad 57
iva2k 0:886e4b3119ad 58 #define CLS "\033[2J"
iva2k 0:886e4b3119ad 59
iva2k 0:886e4b3119ad 60 const char content[] =
iva2k 0:886e4b3119ad 61 "<HTML>"
iva2k 0:886e4b3119ad 62 "<HEAD>"
iva2k 0:886e4b3119ad 63 "<title>Static Page</title>"
iva2k 0:886e4b3119ad 64 "</HEAD>"
iva2k 0:886e4b3119ad 65 "<BODY>"
iva2k 0:886e4b3119ad 66 "<H1>Hello World</H1>"
iva2k 0:886e4b3119ad 67 "<p>Page generated statically from code.</p>"
iva2k 0:886e4b3119ad 68 "</BODY></HTML>"
iva2k 0:886e4b3119ad 69 ;
iva2k 0:886e4b3119ad 70
iva2k 0:886e4b3119ad 71 #define MAX_DYNAMIC_CONTENT_LEN 2048
iva2k 0:886e4b3119ad 72 char dynamic_content[MAX_DYNAMIC_CONTENT_LEN];
iva2k 0:886e4b3119ad 73
iva2k 0:886e4b3119ad 74 const char content_fmt[] =
iva2k 0:886e4b3119ad 75 "<HTML>"
iva2k 0:886e4b3119ad 76 "<HEAD>"
iva2k 0:886e4b3119ad 77 "<title>Dynamic Page</title>"
iva2k 0:886e4b3119ad 78 "</HEAD>"
iva2k 0:886e4b3119ad 79 "<BODY>"
iva2k 0:886e4b3119ad 80 "<H1>Hello World</H1>"
iva2k 0:886e4b3119ad 81 "<p>Page generated dynamically from code.</p>"
iva2k 0:886e4b3119ad 82 "<p>URL=%s</p>"
iva2k 0:886e4b3119ad 83 "<p>Header Fields=%s</p>"
iva2k 0:886e4b3119ad 84 "</BODY></HTML>"
iva2k 0:886e4b3119ad 85 ;
iva2k 0:886e4b3119ad 86
iva2k 0:886e4b3119ad 87 DigitalOut led1(LED1, "led1");
iva2k 0:886e4b3119ad 88 DigitalOut led2(LED2, "led2");
iva2k 0:886e4b3119ad 89 DigitalOut led3(LED3, "led3");
iva2k 0:886e4b3119ad 90 DigitalOut led4(LED4, "led4");
iva2k 0:886e4b3119ad 91 DigitalIn sw1(p9, "sw1");
iva2k 0:886e4b3119ad 92 DigitalIn sw2(p10, "sw2");
iva2k 0:886e4b3119ad 93 LocalFileSystem local("local");
iva2k 0:886e4b3119ad 94 SDFileSystem sd(p5, p6, p7, p8, "sd"); // MBED-BoB2
iva2k 0:886e4b3119ad 95
iva2k 0:886e4b3119ad 96 #include "myrpc.h"
iva2k 0:886e4b3119ad 97 myrpc myrpc1(LED1, "myrpc1");
iva2k 0:886e4b3119ad 98
iva2k 0:886e4b3119ad 99 extern Ethernet eth; // eth is defined elsewhere, avoid compiler error.
iva2k 0:886e4b3119ad 100 Serial pc(USBTX, USBRX);
iva2k 0:886e4b3119ad 101 int gDebug=1;
iva2k 0:886e4b3119ad 102 float gWait = 0.005; // Main loop wait timeout
iva2k 0:886e4b3119ad 103
iva2k 0:886e4b3119ad 104 HTTPStatus myDynamicPage(HTTPConnection *con, HTTPDynamicPageData *pd) {
iva2k 0:886e4b3119ad 105 #if 0
iva2k 0:886e4b3119ad 106 // Static example. With this, we don't really need HTTPStaticPage
iva2k 0:886e4b3119ad 107 pd->size = 0; // let it measure our page
iva2k 0:886e4b3119ad 108 pd->page = (char*)content; // Nothing dynamic about that yet, but we can now get loose here.
iva2k 0:886e4b3119ad 109 pd->page_free = NULL; // No mem free() needed
iva2k 0:886e4b3119ad 110 #elif 0
iva2k 0:886e4b3119ad 111 // Dynamic example, static buffer
iva2k 0:886e4b3119ad 112 pd->size = sprintf(dynamic_content, content_fmt, con->getURL(), con->getHeaderFields());
iva2k 0:886e4b3119ad 113 pd->page = (char*)dynamic_content;
iva2k 0:886e4b3119ad 114 pd->page_free = NULL; // No mem free() needed
iva2k 0:886e4b3119ad 115 if(pd->size > sizeof(dynamic_content)) printf("ASSERTION FAILED: %s:%d\r\n", __FILE__, __LINE__); // Buffer overrun
iva2k 0:886e4b3119ad 116 #else
iva2k 0:886e4b3119ad 117 // Dynamic example, dynamic buffer
iva2k 0:886e4b3119ad 118 int size = sizeof(content_fmt) + 512; // Just guess how much the data will expand
iva2k 0:886e4b3119ad 119 char *buf = (char *)malloc(size);
iva2k 0:886e4b3119ad 120 if (buf) {
iva2k 0:886e4b3119ad 121 pd->size = sprintf(buf, content_fmt, con->getURL(), con->getHeaderFields());
iva2k 0:886e4b3119ad 122 pd->page = buf;
iva2k 0:886e4b3119ad 123 pd->page_free = &free; // Use free() when done
iva2k 0:886e4b3119ad 124 if(pd->size > size) printf("ASSERTION FAILED: %s:%d\r\n", __FILE__, __LINE__); // Buffer overrun
iva2k 0:886e4b3119ad 125 #endif
iva2k 0:886e4b3119ad 126 }
iva2k 0:886e4b3119ad 127 return HTTP_OK;
iva2k 0:886e4b3119ad 128 }
iva2k 0:886e4b3119ad 129
iva2k 0:886e4b3119ad 130 int main(void) {
iva2k 0:886e4b3119ad 131 char mac[6];
iva2k 0:886e4b3119ad 132 int sw1_old=0, sw2_old=0;
iva2k 0:886e4b3119ad 133 bool use_sd = false;
iva2k 0:886e4b3119ad 134
iva2k 0:886e4b3119ad 135 led1=1;
iva2k 0:886e4b3119ad 136 led2=1;
iva2k 0:886e4b3119ad 137 led3=1;
iva2k 0:886e4b3119ad 138 led4=1;
iva2k 0:886e4b3119ad 139
iva2k 0:886e4b3119ad 140 // Start RTC
iva2k 0:886e4b3119ad 141 time_t seconds = time(NULL);
iva2k 0:886e4b3119ad 142 if (seconds == (unsigned)-1 || seconds == 0) {
iva2k 0:886e4b3119ad 143 seconds = 1256729737; // Set RTC time to Wed, 28 Oct 2009 11:35:37
iva2k 0:886e4b3119ad 144 set_time(seconds);
iva2k 0:886e4b3119ad 145 printf("RTC initialized, start time %d seconds\r\n", seconds);
iva2k 0:886e4b3119ad 146 }
iva2k 0:886e4b3119ad 147
iva2k 0:886e4b3119ad 148 char *hostname = "mbed";
iva2k 0:886e4b3119ad 149 HTTPServer http(hostname); // Use DHCP
iva2k 0:886e4b3119ad 150 http.timeout(10000); // Sets the timout for a HTTP request. The timout is the time which is allowed to spent between two incomming TCP packets. If the time is passed the connection will be closed.
iva2k 0:886e4b3119ad 151
iva2k 0:886e4b3119ad 152 eth.address(mac);
iva2k 0:886e4b3119ad 153 pc.printf(CLS "\r\n\r\nHTTPServer \"%s\" started\r\nMAC %02X:%02X:%02X:%02X:%02X:%02X\r\n%s",
iva2k 0:886e4b3119ad 154 hostname, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
iva2k 0:886e4b3119ad 155 gDebug?"Debug is ON\r\n":""
iva2k 0:886e4b3119ad 156 );
iva2k 0:886e4b3119ad 157
iva2k 0:886e4b3119ad 158 Base::add_rpc_class<AnalogIn>();
iva2k 0:886e4b3119ad 159 Base::add_rpc_class<AnalogOut>();
iva2k 0:886e4b3119ad 160 Base::add_rpc_class<DigitalIn>();
iva2k 0:886e4b3119ad 161 Base::add_rpc_class<DigitalOut>();
iva2k 0:886e4b3119ad 162 Base::add_rpc_class<PwmOut>();
iva2k 0:886e4b3119ad 163 Base::add_rpc_class<Timer>();
iva2k 0:886e4b3119ad 164 Base::add_rpc_class<SPI>();
iva2k 0:886e4b3119ad 165 Base::add_rpc_class<BusOut>();
iva2k 0:886e4b3119ad 166 Base::add_rpc_class<BusIn>();
iva2k 0:886e4b3119ad 167 Base::add_rpc_class<myrpc>();
iva2k 0:886e4b3119ad 168 led1=0;
iva2k 0:886e4b3119ad 169
iva2k 0:886e4b3119ad 170 // Check if we can use SD card for the web server
iva2k 0:886e4b3119ad 171 FILE *fp = fopen("/sd/index.htm", "r");
iva2k 0:886e4b3119ad 172 if (fp == NULL) {
iva2k 0:886e4b3119ad 173 if (gDebug) printf("DEBUG: No SD card found or no index.htm file - using LocalFilesystem for WebServer.\r\n");
iva2k 0:886e4b3119ad 174 } else {
iva2k 0:886e4b3119ad 175 use_sd = true;
iva2k 0:886e4b3119ad 176 fclose(fp);
iva2k 0:886e4b3119ad 177 if (gDebug) printf("DEBUG: Found SD card with index.htm file - using SD for WebServer.\r\n");
iva2k 0:886e4b3119ad 178 }
iva2k 0:886e4b3119ad 179
iva2k 0:886e4b3119ad 180 if (0 != SNTPReadIniFile("/sd/sntp.ini") )
iva2k 0:886e4b3119ad 181 SNTPReadIniFile("/local/sntp.ini");
iva2k 0:886e4b3119ad 182 SNTPWriteIniFile(stdout);
iva2k 0:886e4b3119ad 183
iva2k 0:886e4b3119ad 184
iva2k 0:886e4b3119ad 185 http.addHandler(new HTTPLinkStatus("/",
iva2k 1:ec4170739967 186 #if MBED_BOB2
iva2k 0:886e4b3119ad 187 p25, p26, // MBED-BoB2-mods
iva2k 0:886e4b3119ad 188 #else
iva2k 0:886e4b3119ad 189 LED3, LED4,
iva2k 0:886e4b3119ad 190 #endif
iva2k 0:886e4b3119ad 191 0.1,
iva2k 0:886e4b3119ad 192 /*do_urlfile*/ true, /*do_link_printf*/ true, /*do_log_printf*/ false,
iva2k 0:886e4b3119ad 193 /*log_file*/ ( (gDebug>1) ? (use_sd ? "/sd/httpd.log" : "/local/httpd.log") : NULL)
iva2k 0:886e4b3119ad 194 )); // Should be the first handler to get a preview of all requests
iva2k 0:886e4b3119ad 195 http.addHandler(new HTTPRPC());
iva2k 0:886e4b3119ad 196 led2=0;
iva2k 0:886e4b3119ad 197
iva2k 0:886e4b3119ad 198 // Static/Dynamic pages must be installed before FileSystem on /
iva2k 0:886e4b3119ad 199 http.addHandler(new HTTPStaticPage("/static.htm", content, strlen(content)));
iva2k 0:886e4b3119ad 200 http.addHandler(new HTTPDynamicPage("/dynamic.htm", &myDynamicPage));
iva2k 0:886e4b3119ad 201 http.addHandler(new HTTPFileSystemHandler("/", use_sd ? "/sd/" : "/local/"));
iva2k 0:886e4b3119ad 202 led3=0;
iva2k 0:886e4b3119ad 203
iva2k 0:886e4b3119ad 204 // FIXME: BUG If eth is not plugged, http.bind() hangs!
iva2k 0:886e4b3119ad 205 http.bind();
iva2k 0:886e4b3119ad 206
iva2k 0:886e4b3119ad 207 SNTPClientInit();
iva2k 0:886e4b3119ad 208 led4 = 0;
iva2k 0:886e4b3119ad 209
iva2k 0:886e4b3119ad 210 pc.printf("\r"); // Add linefeed for stupid Hyperterminal
iva2k 0:886e4b3119ad 211 while(1) {
iva2k 0:886e4b3119ad 212 http.poll(); // Have to call this method at least every 250ms to let the http server run.
iva2k 0:886e4b3119ad 213 if (sw1 & !sw1_old) {
iva2k 0:886e4b3119ad 214 printf("SW1\r\n");
iva2k 0:886e4b3119ad 215 }
iva2k 0:886e4b3119ad 216 if (sw2 && !sw2_old) {
iva2k 0:886e4b3119ad 217 printf(CLS "SW2\r\n");
iva2k 0:886e4b3119ad 218 }
iva2k 0:886e4b3119ad 219 sw1_old = sw1;
iva2k 0:886e4b3119ad 220 sw2_old = sw2;
iva2k 0:886e4b3119ad 221 wait(gWait);
iva2k 0:886e4b3119ad 222 }
iva2k 0:886e4b3119ad 223 }
iva2k 0:886e4b3119ad 224
iva2k 0:886e4b3119ad 225 //END