Webserver controller with url trimming for value controls

Dependencies:   LCD_DISCO_F746NG BSP_DISCO_F746NG

Committer:
hudakz
Date:
Tue Oct 30 16:41:15 2018 +0000
Revision:
8:47b0cb4b5b7d
Parent:
7:02a0635aeeac
Child:
9:161bed13b17e
Updated.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 0:e455fdb56bc8 1 #include "mbed.h"
hudakz 0:e455fdb56bc8 2 #include "EthernetInterface.h"
hudakz 0:e455fdb56bc8 3 #include "TCPServer.h"
hudakz 0:e455fdb56bc8 4 #include "TCPSocket.h"
hudakz 0:e455fdb56bc8 5 #include <stdio.h>
hudakz 0:e455fdb56bc8 6 #include <string>
hudakz 8:47b0cb4b5b7d 7
hudakz 0:e455fdb56bc8 8 using namespace std;
hudakz 8:47b0cb4b5b7d 9
hudakz 7:02a0635aeeac 10 #define IP "192.168.1.181"
hudakz 7:02a0635aeeac 11 #define GATEWAY "192.168.1.1"
hudakz 8:47b0cb4b5b7d 12 #define NETMASK "255.255.255.0"
hudakz 8:47b0cb4b5b7d 13
hudakz 8:47b0cb4b5b7d 14
hudakz 8:47b0cb4b5b7d 15 #define PORT 80
hudakz 8:47b0cb4b5b7d 16
hudakz 8:47b0cb4b5b7d 17 EthernetInterface* net;
hudakz 7:02a0635aeeac 18
hudakz 0:e455fdb56bc8 19 TCPServer server;
hudakz 0:e455fdb56bc8 20 TCPSocket clientSocket;
hudakz 0:e455fdb56bc8 21 SocketAddress clientAddress;
hudakz 0:e455fdb56bc8 22 char receiveBuf[1024] = { };
hudakz 8:47b0cb4b5b7d 23
hudakz 0:e455fdb56bc8 24 const int OFF = 0;
hudakz 0:e455fdb56bc8 25 const int ON = 1;
hudakz 8:47b0cb4b5b7d 26
hudakz 0:e455fdb56bc8 27 DigitalOut sw(LED1);
hudakz 2:33e8bb5615a6 28 float roomTemp = 21.8; // A temperature sensor output
hudakz 8:47b0cb4b5b7d 29
hudakz 0:e455fdb56bc8 30 const string PASSWORD = "secret"; // change as you like
hudakz 0:e455fdb56bc8 31 const string HTTP_OK = "HTTP/1.0 200 OK";
hudakz 0:e455fdb56bc8 32 const string MOVED_PERM = "HTTP/1.0 301 Moved Permanently\r\nLocation: ";
hudakz 0:e455fdb56bc8 33 const string UNAUTHORIZED = "HTTP/1.0 401 Unauthorized";
hudakz 0:e455fdb56bc8 34 string httpHeader; // HTTP header
hudakz 0:e455fdb56bc8 35 string httpContent; // HTTP content
hudakz 8:47b0cb4b5b7d 36
hudakz 2:33e8bb5615a6 37 /**
hudakz 2:33e8bb5615a6 38 * @brief Defines a custom MAC address
hudakz 2:33e8bb5615a6 39 * @note Uncomment the code below to define a unique MAC address.
hudakz 2:33e8bb5615a6 40 * Modify the mac array items as needed.
hudakz 2:33e8bb5615a6 41 * @param
hudakz 2:33e8bb5615a6 42 * @retval
hudakz 2:33e8bb5615a6 43 */
hudakz 2:33e8bb5615a6 44 //extern "C" void mbed_mac_address(char* mac) {
hudakz 2:33e8bb5615a6 45 // mac[0] = 0x00;
hudakz 2:33e8bb5615a6 46 // mac[1] = 0x01;
hudakz 2:33e8bb5615a6 47 // mac[2] = 0x02;
hudakz 2:33e8bb5615a6 48 // mac[3] = 0x03;
hudakz 2:33e8bb5615a6 49 // mac[4] = 0x04;
hudakz 2:33e8bb5615a6 50 // mac[5] = 0x05;
hudakz 2:33e8bb5615a6 51 //};
hudakz 8:47b0cb4b5b7d 52
hudakz 2:33e8bb5615a6 53 /**
hudakz 2:33e8bb5615a6 54 * @brief Analyses the received URL
hudakz 2:33e8bb5615a6 55 * @note The string passed to this function will look like this:
hudakz 2:33e8bb5615a6 56 * GET /password HTTP/1.....
hudakz 2:33e8bb5615a6 57 * GET /password/ HTTP/1.....
hudakz 2:33e8bb5615a6 58 * GET /password/?sw=1 HTTP/1.....
hudakz 2:33e8bb5615a6 59 * GET /password/?sw=0 HTTP/1.....
hudakz 2:33e8bb5615a6 60 * @param url URL string
hudakz 2:33e8bb5615a6 61 * @retval -1 invalid password
hudakz 2:33e8bb5615a6 62 * -2 no command given but password valid
hudakz 2:33e8bb5615a6 63 * -3 just refresh page
hudakz 2:33e8bb5615a6 64 * 0 switch off
hudakz 2:33e8bb5615a6 65 * 1 switch on
hudakz 2:33e8bb5615a6 66 */
hudakz 2:33e8bb5615a6 67 int8_t analyseURL(string& url) {
hudakz 2:33e8bb5615a6 68 if(url.substr(5, PASSWORD.size()) != PASSWORD)
hudakz 0:e455fdb56bc8 69 return(-1);
hudakz 8:47b0cb4b5b7d 70
hudakz 0:e455fdb56bc8 71 uint8_t pos = 5 + PASSWORD.size();
hudakz 8:47b0cb4b5b7d 72
hudakz 2:33e8bb5615a6 73 if(url.substr(pos, 1) == " ")
hudakz 0:e455fdb56bc8 74 return(-2);
hudakz 8:47b0cb4b5b7d 75
hudakz 2:33e8bb5615a6 76 if(url.substr(pos++, 1) != "/")
hudakz 0:e455fdb56bc8 77 return(-1);
hudakz 8:47b0cb4b5b7d 78
hudakz 2:33e8bb5615a6 79 string cmd(url.substr(pos, 5));
hudakz 8:47b0cb4b5b7d 80
hudakz 0:e455fdb56bc8 81 if(cmd == "?sw=0")
hudakz 2:33e8bb5615a6 82 return(0);
hudakz 8:47b0cb4b5b7d 83
hudakz 0:e455fdb56bc8 84 if(cmd == "?sw=1")
hudakz 2:33e8bb5615a6 85 return(1);
hudakz 8:47b0cb4b5b7d 86
hudakz 0:e455fdb56bc8 87 return(-3);
hudakz 0:e455fdb56bc8 88 }
hudakz 8:47b0cb4b5b7d 89
hudakz 0:e455fdb56bc8 90 /**
hudakz 0:e455fdb56bc8 91 * @brief
hudakz 0:e455fdb56bc8 92 * @note
hudakz 0:e455fdb56bc8 93 * @param
hudakz 0:e455fdb56bc8 94 * @retval
hudakz 0:e455fdb56bc8 95 */
hudakz 0:e455fdb56bc8 96 string& movedPermanently(uint8_t flag) {
hudakz 0:e455fdb56bc8 97 if(flag == 1)
hudakz 0:e455fdb56bc8 98 httpContent = "/" + PASSWORD + "/";
hudakz 0:e455fdb56bc8 99 else
hudakz 0:e455fdb56bc8 100 httpContent = "";
hudakz 8:47b0cb4b5b7d 101
hudakz 0:e455fdb56bc8 102 httpContent += "<h1>301 Moved Permanently</h1>\r\n";
hudakz 8:47b0cb4b5b7d 103
hudakz 0:e455fdb56bc8 104 return(httpContent);
hudakz 0:e455fdb56bc8 105 }
hudakz 8:47b0cb4b5b7d 106
hudakz 0:e455fdb56bc8 107 /**
hudakz 0:e455fdb56bc8 108 * @brief
hudakz 0:e455fdb56bc8 109 * @note
hudakz 0:e455fdb56bc8 110 * @param
hudakz 0:e455fdb56bc8 111 * @retval
hudakz 0:e455fdb56bc8 112 */
hudakz 0:e455fdb56bc8 113 string& showWebPage(uint8_t status) {
hudakz 2:33e8bb5615a6 114 char roomTempStr[5];
hudakz 8:47b0cb4b5b7d 115
hudakz 2:33e8bb5615a6 116 //roomTemp = ds1820.read();
hudakz 2:33e8bb5615a6 117 sprintf(roomTempStr, "%3.1f", roomTemp);
hudakz 8:47b0cb4b5b7d 118
hudakz 5:e1218721aefd 119 // CSS toggle switch
hudakz 5:e1218721aefd 120 httpContent = "<head>";
hudakz 5:e1218721aefd 121 httpContent += "<style>";
hudakz 8:47b0cb4b5b7d 122
hudakz 5:e1218721aefd 123 httpContent += ".switch {";
hudakz 5:e1218721aefd 124 httpContent += "position: relative;";
hudakz 5:e1218721aefd 125 httpContent += "display: inline-block;";
hudakz 5:e1218721aefd 126 httpContent += "width: 60px;";
hudakz 5:e1218721aefd 127 httpContent += "height: 34px;";
hudakz 5:e1218721aefd 128 httpContent += "}";
hudakz 8:47b0cb4b5b7d 129
hudakz 5:e1218721aefd 130 httpContent += ".switch input {display:none;}";
hudakz 8:47b0cb4b5b7d 131
hudakz 5:e1218721aefd 132 httpContent += ".slider {";
hudakz 5:e1218721aefd 133 httpContent += "position: absolute;";
hudakz 5:e1218721aefd 134 httpContent += "cursor: pointer;";
hudakz 5:e1218721aefd 135 httpContent += "top: 0;";
hudakz 5:e1218721aefd 136 httpContent += "left: 0;";
hudakz 5:e1218721aefd 137 httpContent += "right: 0;";
hudakz 5:e1218721aefd 138 httpContent += "bottom: 0;";
hudakz 6:e2d251d535f0 139 httpContent += "border-radius: 34px;";
hudakz 5:e1218721aefd 140 httpContent += "background-color: #ccc;";
hudakz 5:e1218721aefd 141 httpContent += "-webkit-transition: .4s;";
hudakz 5:e1218721aefd 142 httpContent += "transition: .4s;";
hudakz 5:e1218721aefd 143 httpContent += "}";
hudakz 8:47b0cb4b5b7d 144
hudakz 5:e1218721aefd 145 httpContent += ".slider:before {";
hudakz 5:e1218721aefd 146 httpContent += "position: absolute;";
hudakz 5:e1218721aefd 147 httpContent += "content: \"\";";
hudakz 5:e1218721aefd 148 httpContent += "height: 26px;";
hudakz 5:e1218721aefd 149 httpContent += "width: 26px;";
hudakz 5:e1218721aefd 150 httpContent += "left: 4px;";
hudakz 5:e1218721aefd 151 httpContent += "bottom: 4px;";
hudakz 6:e2d251d535f0 152 httpContent += "border-radius: 50%;";
hudakz 5:e1218721aefd 153 httpContent += "background-color: white;";
hudakz 5:e1218721aefd 154 httpContent += "-webkit-transition: .4s;";
hudakz 5:e1218721aefd 155 httpContent += "transition: .4s;";
hudakz 5:e1218721aefd 156 httpContent += "}";
hudakz 8:47b0cb4b5b7d 157
hudakz 5:e1218721aefd 158 httpContent += "input:checked + .slider {";
hudakz 5:e1218721aefd 159 httpContent += "background-color: #8ce196;";
hudakz 5:e1218721aefd 160 httpContent += "}";
hudakz 8:47b0cb4b5b7d 161
hudakz 5:e1218721aefd 162 httpContent += "input:focus + .slider {";
hudakz 5:e1218721aefd 163 httpContent += "box-shadow: 0 0 1px #8ce196;";
hudakz 5:e1218721aefd 164 httpContent += "}";
hudakz 8:47b0cb4b5b7d 165
hudakz 5:e1218721aefd 166 httpContent += "input:checked + .slider:before {";
hudakz 5:e1218721aefd 167 httpContent += "-webkit-transform: translateX(26px);";
hudakz 5:e1218721aefd 168 httpContent += "-ms-transform: translateX(26px);";
hudakz 5:e1218721aefd 169 httpContent += "transform: translateX(26px);";
hudakz 5:e1218721aefd 170 httpContent += "}";
hudakz 8:47b0cb4b5b7d 171
hudakz 5:e1218721aefd 172 httpContent += "</style>";
hudakz 5:e1218721aefd 173 httpContent += "</head>";
hudakz 8:47b0cb4b5b7d 174
hudakz 5:e1218721aefd 175 httpContent += "<body>";
hudakz 7:02a0635aeeac 176 httpContent += "<h2><a href=\".\" title=\"Click to refresh the page\">Smart Home</a></h2>";
hudakz 5:e1218721aefd 177 httpContent += "<pre>Temperature:\t" + string(roomTempStr) + "&deg;C</pre>";
hudakz 6:e2d251d535f0 178 httpContent += "<pre>Heating:\t";
hudakz 8:47b0cb4b5b7d 179
hudakz 0:e455fdb56bc8 180 if(status == ON) {
hudakz 6:e2d251d535f0 181 httpContent += "<a href=\"./?sw=0\" class=\"switch\"> ";
hudakz 5:e1218721aefd 182 httpContent += "<input type=\"checkbox\" checked>";
hudakz 0:e455fdb56bc8 183 }
hudakz 0:e455fdb56bc8 184 else {
hudakz 6:e2d251d535f0 185 httpContent += "<a href=\"./?sw=1\" class=\"switch\"> ";
hudakz 5:e1218721aefd 186 httpContent += "<input type=\"checkbox\">";
hudakz 5:e1218721aefd 187 }
hudakz 8:47b0cb4b5b7d 188
hudakz 5:e1218721aefd 189 httpContent += "<div class=\"slider\"></div>";
hudakz 6:e2d251d535f0 190 httpContent += "</a></pre>";
hudakz 5:e1218721aefd 191 httpContent += "<hr>";
hudakz 7:02a0635aeeac 192 httpContent += "<pre>2017 armMBED</pre>";
hudakz 5:e1218721aefd 193 httpContent += "</body>";
hudakz 8:47b0cb4b5b7d 194
hudakz 0:e455fdb56bc8 195 return httpContent;
hudakz 0:e455fdb56bc8 196 }
hudakz 8:47b0cb4b5b7d 197
hudakz 0:e455fdb56bc8 198 /**
hudakz 0:e455fdb56bc8 199 * @brief
hudakz 0:e455fdb56bc8 200 * @note
hudakz 0:e455fdb56bc8 201 * @param
hudakz 0:e455fdb56bc8 202 * @retval
hudakz 0:e455fdb56bc8 203 */
hudakz 0:e455fdb56bc8 204 void sendHTTP(TCPSocket& client, string& header, string& content) {
hudakz 0:e455fdb56bc8 205 char content_length[5] = { };
hudakz 8:47b0cb4b5b7d 206
hudakz 0:e455fdb56bc8 207 header += "\r\nContent-Type: text/html\r\n";
hudakz 0:e455fdb56bc8 208 header += "Content-Length: ";
hudakz 0:e455fdb56bc8 209 sprintf(content_length, "%d", content.length());
hudakz 0:e455fdb56bc8 210 header += string(content_length) + "\r\n";
hudakz 0:e455fdb56bc8 211 header += "Pragma: no-cache\r\n";
hudakz 0:e455fdb56bc8 212 header += "Connection: About to close\r\n";
hudakz 0:e455fdb56bc8 213 header += "\r\n";
hudakz 8:47b0cb4b5b7d 214
hudakz 0:e455fdb56bc8 215 string webpage = header + content;
hudakz 0:e455fdb56bc8 216 client.send((char*)webpage.c_str(), webpage.length());
hudakz 0:e455fdb56bc8 217 printf("HTTP sent.\n\r");
hudakz 0:e455fdb56bc8 218 }
hudakz 8:47b0cb4b5b7d 219
hudakz 0:e455fdb56bc8 220 /**
hudakz 0:e455fdb56bc8 221 * @brief
hudakz 0:e455fdb56bc8 222 * @note
hudakz 0:e455fdb56bc8 223 * @param
hudakz 0:e455fdb56bc8 224 * @retval
hudakz 0:e455fdb56bc8 225 */
hudakz 0:e455fdb56bc8 226 int main(void) {
hudakz 8:47b0cb4b5b7d 227 printf("Starting\r\n");
hudakz 8:47b0cb4b5b7d 228
hudakz 8:47b0cb4b5b7d 229 //net = NetworkInterface::get_default_instance();
hudakz 8:47b0cb4b5b7d 230
hudakz 8:47b0cb4b5b7d 231 net = new EthernetInterface();
hudakz 8:47b0cb4b5b7d 232
hudakz 8:47b0cb4b5b7d 233 if (!net) {
hudakz 8:47b0cb4b5b7d 234 printf("Error! No network inteface found.\n");
hudakz 8:47b0cb4b5b7d 235 return 0;
hudakz 8:47b0cb4b5b7d 236 }
hudakz 0:e455fdb56bc8 237
hudakz 8:47b0cb4b5b7d 238 //net->set_network (IP, NETMASK, GATEWAY); // include this for using static IP address
hudakz 8:47b0cb4b5b7d 239
hudakz 8:47b0cb4b5b7d 240 nsapi_size_or_error_t r = net->connect();
hudakz 8:47b0cb4b5b7d 241 if (r != 0) {
hudakz 8:47b0cb4b5b7d 242 printf("Error! net->connect() returned: %d\n", r);
hudakz 8:47b0cb4b5b7d 243 return r;
hudakz 8:47b0cb4b5b7d 244 }
hudakz 7:02a0635aeeac 245
hudakz 8:47b0cb4b5b7d 246 // Show the network address
hudakz 8:47b0cb4b5b7d 247 const char *ip = net->get_ip_address();
hudakz 8:47b0cb4b5b7d 248 const char *netmask = net->get_netmask();
hudakz 8:47b0cb4b5b7d 249 const char *gateway = net->get_gateway();
hudakz 8:47b0cb4b5b7d 250 printf("IP address: %s\n", ip ? ip : "None");
hudakz 8:47b0cb4b5b7d 251 printf("Netmask: %s\n", netmask ? netmask : "None");
hudakz 8:47b0cb4b5b7d 252 printf("Gateway: %s\n", gateway ? gateway : "None");
hudakz 8:47b0cb4b5b7d 253 printf("Usage: Type %s/%s/ into your web browser and hit ENTER\r\n", ip, PASSWORD.c_str());
hudakz 8:47b0cb4b5b7d 254
hudakz 8:47b0cb4b5b7d 255 /* Open the server on ethernet stack */
hudakz 8:47b0cb4b5b7d 256 server.open(net);
hudakz 8:47b0cb4b5b7d 257
hudakz 0:e455fdb56bc8 258 /* Bind the HTTP port (TCP 80) to the server */
hudakz 8:47b0cb4b5b7d 259 server.bind(ip, 80);
hudakz 8:47b0cb4b5b7d 260
hudakz 0:e455fdb56bc8 261 /* Can handle 5 simultaneous connections */
hudakz 0:e455fdb56bc8 262 server.listen(5);
hudakz 8:47b0cb4b5b7d 263
hudakz 0:e455fdb56bc8 264 //listening for http GET request
hudakz 0:e455fdb56bc8 265 while(true) {
hudakz 7:02a0635aeeac 266 printf("=========================================\r\n");
hudakz 2:33e8bb5615a6 267 printf("Ready to serve clients.\r\n");
hudakz 0:e455fdb56bc8 268 server.accept(&clientSocket, &clientAddress);
hudakz 0:e455fdb56bc8 269 printf("Connection succeeded!\n\rIP: %s\n\r", clientAddress.get_ip_address());
hudakz 0:e455fdb56bc8 270 clientSocket.recv(receiveBuf, 1023);
hudakz 0:e455fdb56bc8 271 printf("Recieved Data: %d\n\r\n\r%.*s\n\r", strlen(receiveBuf), strlen(receiveBuf), receiveBuf);
hudakz 8:47b0cb4b5b7d 272
hudakz 0:e455fdb56bc8 273 string received(receiveBuf);
hudakz 8:47b0cb4b5b7d 274
hudakz 0:e455fdb56bc8 275 if(received.substr(0, 3) != "GET") {
hudakz 0:e455fdb56bc8 276 httpHeader = HTTP_OK;
hudakz 0:e455fdb56bc8 277 httpContent = "<h1>200 OK</h1>";
hudakz 0:e455fdb56bc8 278 sendHTTP(clientSocket, httpHeader, httpContent);
hudakz 0:e455fdb56bc8 279 continue;
hudakz 0:e455fdb56bc8 280 }
hudakz 8:47b0cb4b5b7d 281
hudakz 0:e455fdb56bc8 282 if(received.substr(0, 6) == "GET / ") {
hudakz 0:e455fdb56bc8 283 httpHeader = HTTP_OK;
hudakz 0:e455fdb56bc8 284 httpContent = "<p>Usage: Type http://ip_address/password/ into your web browser and hit ENTER</p>\r\n";
hudakz 0:e455fdb56bc8 285 sendHTTP(clientSocket, httpHeader, httpContent);
hudakz 0:e455fdb56bc8 286 continue;
hudakz 0:e455fdb56bc8 287 }
hudakz 8:47b0cb4b5b7d 288
hudakz 0:e455fdb56bc8 289 int cmd = analyseURL(received);
hudakz 8:47b0cb4b5b7d 290
hudakz 0:e455fdb56bc8 291 if(cmd == -2) {
hudakz 8:47b0cb4b5b7d 292
hudakz 0:e455fdb56bc8 293 // redirect to the right base url
hudakz 0:e455fdb56bc8 294 httpHeader = MOVED_PERM;
hudakz 0:e455fdb56bc8 295 sendHTTP(clientSocket, httpHeader, movedPermanently(1));
hudakz 0:e455fdb56bc8 296 continue;
hudakz 0:e455fdb56bc8 297 }
hudakz 8:47b0cb4b5b7d 298
hudakz 0:e455fdb56bc8 299 if(cmd == -1) {
hudakz 0:e455fdb56bc8 300 httpHeader = UNAUTHORIZED;
hudakz 0:e455fdb56bc8 301 httpContent = "<h1>401 Unauthorized</h1>";
hudakz 0:e455fdb56bc8 302 sendHTTP(clientSocket, httpHeader, httpContent);
hudakz 0:e455fdb56bc8 303 continue;
hudakz 0:e455fdb56bc8 304 }
hudakz 8:47b0cb4b5b7d 305
hudakz 0:e455fdb56bc8 306 if(cmd == ON) {
hudakz 0:e455fdb56bc8 307 sw = ON; // turn the switch on
hudakz 0:e455fdb56bc8 308 }
hudakz 8:47b0cb4b5b7d 309
hudakz 0:e455fdb56bc8 310 if(cmd == OFF) {
hudakz 0:e455fdb56bc8 311 sw = OFF; // turn the switch off
hudakz 0:e455fdb56bc8 312 }
hudakz 8:47b0cb4b5b7d 313
hudakz 0:e455fdb56bc8 314 httpHeader = HTTP_OK;
hudakz 0:e455fdb56bc8 315 sendHTTP(clientSocket, httpHeader, showWebPage(sw));
hudakz 0:e455fdb56bc8 316 }
hudakz 8:47b0cb4b5b7d 317 }