HTTP Server serving a simple webpage which enables to remotely turn a digital output on/off. Compile, download, run and type 'IP_address/secret/' (don't forget the last '/') into your web browser and hit ENTER.

Dependencies:   UIPEthernet

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include <string>
00003 #include "UipEthernet.h"
00004 #include "TcpServer.h"
00005 #include "TcpClient.h"
00006 
00007 //#define DEBUG
00008 // Static IP address must be unique and compatible with your network.
00009 #define IP      "192.168.1.35"
00010 #define GATEWAY "192.168.1.1"
00011 #define NETMASK "255.255.255.0"
00012 #define PORT    80
00013 const uint8_t   MAC[6] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x06 };
00014 UipEthernet     net(MAC, D11, D12, D13, D10);   // mosi, miso, sck, cs
00015 TcpServer       server;                         // Ethernet server
00016 TcpClient*      client;
00017 char            httpBuf[1500];
00018 char            httpHeader[256];
00019 const int       OFF = 0;
00020 const int       ON = 1;
00021 DigitalOut      output(D3);                     // A digital output to be switched on/off
00022 float           roomTemp = 21.8f;               // A temperature sensor output
00023 const char      PASSWORD[] = "secret";          // Change as you like
00024 
00025 /**
00026  * @brief   Analyses the received URL
00027  * @note    The string passed to this function will look like this:
00028  *          GET /HTTP/1.....
00029  *          GET /password HTTP/1.....
00030  *          GET /password/ HTTP/1.....
00031  *          GET /password/?sw=1 HTTP/1.....
00032  *          GET /password/?sw=0 HTTP/1.....
00033  * @param   url URL string
00034  * @retval -3 just refresh page
00035  *         -2 no command given but password valid
00036  *         -1 invalid password
00037  *          0 switch off
00038  *          1 switch on
00039  */
00040 int8_t analyseURL(char* url)
00041 {
00042     if (strlen(url) < (5 + strlen(PASSWORD) + 1))
00043         return(-1);
00044 
00045     //if (url.substr(5, PASSWORD.size()) != PASSWORD)
00046     if (strncmp(url + 5, PASSWORD, strlen(PASSWORD)) != 0)
00047         return(-1);
00048 
00049     uint8_t pos = 5 + strlen(PASSWORD);
00050 
00051     //if (url.substr(pos, 1) != "/")
00052 
00053     if (*(url + pos) != '/')
00054         return(-1);
00055 
00056     //if (url.substr(pos++, 1) == " ")
00057     if (*(url + pos++) == ' ')
00058         return(-2);
00059 
00060     //string  cmd(url.substr(pos, 5));
00061     *(url + pos + 5) = '\0';    // terminate the cmd string
00062     char*   cmd = ((url + pos));
00063     if (strcmp(cmd, "?sw=0") == 0)
00064         return(0);
00065     if (strcmp(cmd, "?sw=1") == 0)
00066         return(1);
00067     return(-3);
00068 }
00069 
00070 /**
00071  * @brief
00072  * @note
00073  * @param
00074  * @retval
00075  */
00076 char* movedPermanently(uint8_t flag)
00077 {
00078     memset(httpBuf, 0, sizeof(httpBuf));
00079     if (flag == 1) {
00080         strcpy(httpBuf, "/");
00081         strcat(httpBuf, PASSWORD);
00082         strcat(httpBuf, "/");
00083     }
00084 
00085     strcat(httpBuf, "<h1>301 Moved Permanently</h1>\r\n");
00086     return(httpBuf);
00087 }
00088 
00089 /**
00090  * @brief
00091  * @note
00092  * @param
00093  * @retval
00094  */
00095 char* showWebPage(int status)
00096 {
00097     char    roomTempStr[10] = { };
00098 
00099     //roomTemp = ds1820.read();
00100 
00101     sprintf(roomTempStr, "%3.1f", roomTemp);
00102     memset(httpBuf, 0, sizeof(httpBuf));
00103     /*$off*/
00104     strcat
00105     (
00106         httpBuf,
00107         "<head>"
00108             "<meta charset=\"utf-8\">"
00109             "<meta name=\"viewport\" content=\" initial-scale=1.0; maximum-scale=1.0; minimum-scale=1.0; user-scalable=0;\"/>"
00110             "<title>Smart Home</title>"
00111             "<link href='http://fonts.googleapis.com/css?family=Droid+Sans&v1' rel='stylesheet' type='text/css'>"
00112             "<style>"
00113             ".switch {"
00114                 "position: relative;"
00115                 "display: inline-block;"
00116                 "width: 60px;"
00117                 "height: 34px;"
00118             "}"
00119             ".switch input {display:none;}"
00120             ".slider {"
00121                 "position: absolute;"
00122                 "cursor: pointer;"
00123                 "top: 0;"
00124                 "left: 0;"
00125                 "right: 0;"
00126                 "bottom: 0;"
00127                 "border-radius: 34px;"
00128                 "background-color: #ccc;"
00129                 "-webkit-transition: .4s;"
00130                 "transition: .4s;"
00131             "}"
00132             ".slider:before {"
00133                 "position: absolute;"
00134                 "content: \"\";"
00135                 "height: 26px;"
00136                 "width: 26px;"
00137                 "left: 4px;"
00138                 "bottom: 4px;"
00139                 "border-radius: 50%;"
00140                 "background-color: white;"
00141                 "-webkit-transition: .4s;"
00142                 "transition: .4s;"
00143             "}"
00144             "input:checked + .slider {"
00145                 "background-color: #8ce196;"
00146             "}"
00147             "input:focus + .slider {"
00148                 "box-shadow: 0 0 1px #8ce196;"
00149             "}"
00150             "input:checked + .slider:before {"
00151                 "-webkit-transform: translateX(26px);"
00152                 "-ms-transform: translateX(26px);"
00153                 "transform: translateX(26px);"
00154             "}"
00155             "</style>"
00156         "</head>"
00157 
00158         "<body>"
00159             "<h2><a href=\".\" title=\"Click to refresh the page\">Smart Home</a></h2>"
00160             "<pre>Temperature:\t"
00161     );
00162     strcat(httpBuf, roomTempStr);
00163     strcat(httpBuf, "&deg;C</pre>");
00164     strcat
00165     (
00166        httpBuf,
00167        "<pre>Heating:\t"
00168     );
00169     if(status == ON) {
00170        strcat
00171        (
00172            httpBuf,
00173            "<a href=\"./?sw=0\" class=\"switch\"> "
00174            "<input type=\"checkbox\" checked>"
00175        );
00176     }
00177     else {
00178        strcat
00179        (
00180            httpBuf,
00181            "<a href=\"./?sw=1\" class=\"switch\"> "
00182            "<input type=\"checkbox\">"
00183        );
00184     }
00185     strcat
00186     (
00187        httpBuf,
00188            "<div class=\"slider\"></div>"
00189            "</a>"
00190            "</pre>"
00191            "<hr>"
00192            "<pre>2017 ARMmbed</pre>"
00193        "</body>"
00194     );
00195     /*$on*/
00196     return httpBuf;
00197 }
00198 
00199 /**
00200  * @brief
00201  * @note
00202  * @param
00203  * @retval
00204  */
00205 void sendHTTP(TcpClient* client, char* header, char* content)
00206 {
00207     char    content_length[10] = { };
00208 
00209     sprintf(content_length, "%u\r\n", strlen(content));
00210 
00211     strcat(header, "\r\nContent-Type: text/html\r\n");
00212     strcat(header, "Content-Length: ");
00213     strcat(header, content_length);
00214     strcat(header, "Pragma: no-cache\r\n");
00215     strcat(header, "Connection: About to close\r\n\r\n");
00216 
00217     char c = content[0];
00218     memmove(httpBuf + strlen(header), httpBuf, strlen(content)); // make room for the header
00219     strcpy(httpBuf, header); // copy the header on front of the content
00220     httpBuf[strlen(header)] = c;
00221     client->send((uint8_t*)httpBuf, strlen(httpBuf));
00222 }
00223 
00224 /**
00225  * @brief
00226  * @note
00227  * @param
00228  * @retval
00229  */
00230 int main(void)
00231 {
00232     printf("Starting ...\r\n");
00233 
00234     //net.set_network(IP, NETMASK, GATEWAY);  // include this for using static IP address
00235     if (net.connect(30) != 0) {
00236 
00237         // 'connect' timeout in seconds (defaults to 60 sec)
00238         printf("Unable to connet.\r\n");
00239         return -1;
00240     }
00241 
00242     // Show the network address
00243     SocketAddress   addr;
00244     net.get_ip_address(&addr);
00245     printf("IP address: %s\n", addr.get_ip_address() ? addr.get_ip_address() : "None");
00246     net.get_netmask(&addr);
00247     printf("Netmask: %s\n", addr.get_ip_address() ? addr.get_ip_address() : "None");
00248     net.get_gateway(&addr);
00249     printf("Gateway: %s\n", addr.get_ip_address() ? addr.get_ip_address() : "None");
00250 
00251     /* Open the server on ethernet stack */
00252     server.open(&net);
00253 
00254     /* Bind the HTTP port (TCP 80) to the server */
00255     server.bind(PORT);
00256 
00257     /* Can handle 4 simultaneous connections */
00258     server.listen(4);
00259 
00260     while (true) {
00261         client = server.accept();
00262         if (client) {
00263             switch (client->recv((uint8_t*)httpBuf, client->available())) {
00264                 case 0:
00265                     printf("recieved buffer is empty.\n\r");
00266                     break;
00267 
00268                 case -1:
00269                     printf("failed to read data from client.\n\r");
00270                     break;
00271 
00272                 default:
00273     #ifdef DEBUG
00274                     printf("Client with IP address %s connected.\r\n\r\n", client->getpeername());
00275                     printf("Data received:\r\n%s\n\r", receiveBuf);
00276     #endif
00277                     if (strncmp(httpBuf, "GET", 3) != 0) {
00278                         strcpy(httpHeader, "HTTP/1.0 200 OK");
00279                         strcpy(httpBuf, "<h1>200 OK</h1>");
00280                         sendHTTP(client, httpHeader, httpBuf);
00281                     }
00282                     else
00283                     if ((strncmp(httpBuf, "GET", 3) == 0) && (strncmp(httpBuf + 3, " / ", 3 == 0))) {
00284                         strcpy(httpHeader, "HTTP/1.0 200 OK");
00285                         strcpy(httpBuf, "<p>Usage: http://host_or_ip/password</p>\r\n");
00286                         sendHTTP(client, httpHeader, httpBuf);
00287                     }
00288                     else {
00289                         int cmd = analyseURL(httpBuf);
00290                         switch (cmd) {
00291                             case -3:
00292                                 // update webpage
00293                                 strcpy(httpHeader, "HTTP/1.0 200 OK");
00294                                 sendHTTP(client, httpHeader, showWebPage(output));
00295                                 break;
00296 
00297                             case -2:
00298                                 // redirect to the right base url
00299                                 strcpy(httpHeader, "HTTP/1.0 301 Moved Permanently\r\nLocation: ");
00300                                 sendHTTP(client, httpHeader, movedPermanently(1));
00301                                 break;
00302 
00303                             case -1:
00304                                 strcpy(httpHeader, "HTTP/1.0 401 Unauthorized");
00305                                 strcpy(httpBuf, "<h1>401 Unauthorized</h1>");
00306                                 sendHTTP(client, httpHeader, httpBuf);
00307                                 break;
00308 
00309                             case 0:
00310                                 output = OFF;   // output off
00311                                 strcpy(httpHeader, "HTTP/1.0 200 OK");
00312                                 sendHTTP(client, httpHeader, showWebPage(output));
00313                                 break;
00314 
00315                             case 1:
00316                                 output = ON;    // output on
00317                                 strcpy(httpHeader, "HTTP/1.0 200 OK");
00318                                 sendHTTP(client, httpHeader, showWebPage(output));
00319                                 break;
00320                         }
00321                     }
00322             }
00323 
00324             client->close();
00325         }
00326     }
00327 }