Webserver controller with url trimming for value controls
Dependencies: LCD_DISCO_F746NG BSP_DISCO_F746NG
Diff: main.cpp
- Revision:
- 9:161bed13b17e
- Parent:
- 8:47b0cb4b5b7d
- Child:
- 10:f941e0750773
--- a/main.cpp Tue Oct 30 16:41:15 2018 +0000 +++ b/main.cpp Mon Jul 01 17:23:49 2019 +0000 @@ -1,317 +1,327 @@ #include "mbed.h" #include "EthernetInterface.h" -#include "TCPServer.h" #include "TCPSocket.h" #include <stdio.h> #include <string> - -using namespace std; - -#define IP "192.168.1.181" -#define GATEWAY "192.168.1.1" -#define NETMASK "255.255.255.0" - - -#define PORT 80 - + +using namespace std; + +#define IP "192.168.1.181" +#define GATEWAY "192.168.1.1" +#define NETMASK "255.255.255.0" +#define PORT 80 + +Serial pc(USBTX, USBRX); EthernetInterface* net; - -TCPServer server; -TCPSocket clientSocket; +TCPSocket server; +TCPSocket* clientSocket; SocketAddress clientAddress; -char receiveBuf[1024] = { }; - +char receiveBuf[1024]; const int OFF = 0; const int ON = 1; - -DigitalOut sw(LED1); -float roomTemp = 21.8; // A temperature sensor output - -const string PASSWORD = "secret"; // change as you like -const string HTTP_OK = "HTTP/1.0 200 OK"; -const string MOVED_PERM = "HTTP/1.0 301 Moved Permanently\r\nLocation: "; +DigitalOut sw(LED1); // A digital output to be switched on/off +float roomTemp = 21.8; // A temperature sensor output +const string PASSWORD = "secret"; // Change as you like +const string HTTP_OK = "HTTP/1.0 200 OK"; +const string MOVED_PERM = "HTTP/1.0 301 Moved Permanently\r\nLocation: "; const string UNAUTHORIZED = "HTTP/1.0 401 Unauthorized"; -string httpHeader; // HTTP header -string httpContent; // HTTP content - -/** - * @brief Defines a custom MAC address - * @note Uncomment the code below to define a unique MAC address. - * Modify the mac array items as needed. - * @param - * @retval - */ -//extern "C" void mbed_mac_address(char* mac) { -// mac[0] = 0x00; -// mac[1] = 0x01; -// mac[2] = 0x02; -// mac[3] = 0x03; -// mac[4] = 0x04; -// mac[5] = 0x05; -//}; - +string httpHeader; // HTTP header +string httpContent; // HTTP content + /** * @brief Analyses the received URL * @note The string passed to this function will look like this: + * GET /HTTP/1..... * GET /password HTTP/1..... * GET /password/ HTTP/1..... * GET /password/?sw=1 HTTP/1..... * GET /password/?sw=0 HTTP/1..... * @param url URL string - * @retval -1 invalid password + * @retval -3 just refresh page * -2 no command given but password valid - * -3 just refresh page + * -1 invalid password * 0 switch off * 1 switch on */ -int8_t analyseURL(string& url) { - if(url.substr(5, PASSWORD.size()) != PASSWORD) +int8_t analyseURL(string& url) +{ + if (url.length() < 5 + PASSWORD.size() + 1) + return(-1); + + if (url.substr(5, PASSWORD.size()) != PASSWORD) return(-1); - + uint8_t pos = 5 + PASSWORD.size(); - - if(url.substr(pos, 1) == " ") + + if (url.substr(pos, 1) != "/") + return(-1); + + if (url.substr(pos++, 1) == " ") return(-2); - - if(url.substr(pos++, 1) != "/") - return(-1); - + string cmd(url.substr(pos, 5)); - - if(cmd == "?sw=0") + + if (cmd == "?sw=0") return(0); - - if(cmd == "?sw=1") + + if (cmd == "?sw=1") return(1); - + return(-3); } - + /** * @brief * @note * @param * @retval */ -string& movedPermanently(uint8_t flag) { - if(flag == 1) +string& movedPermanently(uint8_t flag) +{ + if (flag == 1) httpContent = "/" + PASSWORD + "/"; else httpContent = ""; - + httpContent += "<h1>301 Moved Permanently</h1>\r\n"; - + return(httpContent); } - + /** * @brief * @note * @param * @retval */ -string& showWebPage(uint8_t status) { - char roomTempStr[5]; - +string& showWebPage(int status) +{ + char roomTempStr[5]; + //roomTemp = ds1820.read(); sprintf(roomTempStr, "%3.1f", roomTemp); - - // CSS toggle switch - httpContent = "<head>"; - httpContent += "<style>"; - - httpContent += ".switch {"; - httpContent += "position: relative;"; - httpContent += "display: inline-block;"; - httpContent += "width: 60px;"; - httpContent += "height: 34px;"; - httpContent += "}"; - - httpContent += ".switch input {display:none;}"; - - httpContent += ".slider {"; - httpContent += "position: absolute;"; - httpContent += "cursor: pointer;"; - httpContent += "top: 0;"; - httpContent += "left: 0;"; - httpContent += "right: 0;"; - httpContent += "bottom: 0;"; - httpContent += "border-radius: 34px;"; - httpContent += "background-color: #ccc;"; - httpContent += "-webkit-transition: .4s;"; - httpContent += "transition: .4s;"; - httpContent += "}"; - - httpContent += ".slider:before {"; - httpContent += "position: absolute;"; - httpContent += "content: \"\";"; - httpContent += "height: 26px;"; - httpContent += "width: 26px;"; - httpContent += "left: 4px;"; - httpContent += "bottom: 4px;"; - httpContent += "border-radius: 50%;"; - httpContent += "background-color: white;"; - httpContent += "-webkit-transition: .4s;"; - httpContent += "transition: .4s;"; - httpContent += "}"; - - httpContent += "input:checked + .slider {"; - httpContent += "background-color: #8ce196;"; - httpContent += "}"; - - httpContent += "input:focus + .slider {"; - httpContent += "box-shadow: 0 0 1px #8ce196;"; - httpContent += "}"; - - httpContent += "input:checked + .slider:before {"; - httpContent += "-webkit-transform: translateX(26px);"; - httpContent += "-ms-transform: translateX(26px);"; - httpContent += "transform: translateX(26px);"; - httpContent += "}"; - - httpContent += "</style>"; - httpContent += "</head>"; - - httpContent += "<body>"; - httpContent += "<h2><a href=\".\" title=\"Click to refresh the page\">Smart Home</a></h2>"; - httpContent += "<pre>Temperature:\t" + string(roomTempStr) + "°C</pre>"; - httpContent += "<pre>Heating:\t"; - + + /*$off*/ + httpContent = + "<head>" + "<meta charset=\"utf-8\">" + "<meta name=\"viewport\" content=\" initial-scale=1.0; maximum-scale=1.0; minimum-scale=1.0; user-scalable=0;\"/>" + "<title>Smart Home</title>" + "<link href='http://fonts.googleapis.com/css?family=Droid+Sans&v1' rel='stylesheet' type='text/css'>" + "<style>" + ".switch {" + "position: relative;" + "display: inline-block;" + "width: 60px;" + "height: 34px;" + "}" + ".switch input {display:none;}" + ".slider {" + "position: absolute;" + "cursor: pointer;" + "top: 0;" + "left: 0;" + "right: 0;" + "bottom: 0;" + "border-radius: 34px;" + "background-color: #ccc;" + "-webkit-transition: .4s;" + "transition: .4s;" + "}" + ".slider:before {" + "position: absolute;" + "content: \"\";" + "height: 26px;" + "width: 26px;" + "left: 4px;" + "bottom: 4px;" + "border-radius: 50%;" + "background-color: white;" + "-webkit-transition: .4s;" + "transition: .4s;" + "}" + "input:checked + .slider {" + "background-color: #8ce196;" + "}" + "input:focus + .slider {" + "box-shadow: 0 0 1px #8ce196;" + "}" + "input:checked + .slider:before {" + "-webkit-transform: translateX(26px);" + "-ms-transform: translateX(26px);" + "transform: translateX(26px);" + "}" + "</style>" + "</head>" + + "<body>" + "<h2><a href=\".\" title=\"Click to refresh the page\">Smart Home</a></h2>" + "<pre>Temperature:\t" + string(roomTempStr) + "°C</pre>" + "<pre>Heating:\t"; + if(status == ON) { - httpContent += "<a href=\"./?sw=0\" class=\"switch\"> "; - httpContent += "<input type=\"checkbox\" checked>"; + httpContent += + "<a href=\"./?sw=0\" class=\"switch\"> " + "<input type=\"checkbox\" checked>"; } else { - httpContent += "<a href=\"./?sw=1\" class=\"switch\"> "; - httpContent += "<input type=\"checkbox\">"; - } - - httpContent += "<div class=\"slider\"></div>"; - httpContent += "</a></pre>"; - httpContent += "<hr>"; - httpContent += "<pre>2017 armMBED</pre>"; - httpContent += "</body>"; - + httpContent += + "<a href=\"./?sw=1\" class=\"switch\"> " + "<input type=\"checkbox\">"; + } + + httpContent += + "<div class=\"slider\"></div>" + "</a>" + "</pre>" + "<hr>" + "<pre>2017 ARMmbed</pre>" + "</body>"; + return httpContent; + /*$on*/ } - + /** * @brief * @note * @param * @retval */ -void sendHTTP(TCPSocket& client, string& header, string& content) { +void sendHTTP(TCPSocket& client, string& header, string& content) +{ + /*$off*/ char content_length[5] = { }; - - header += "\r\nContent-Type: text/html\r\n"; - header += "Content-Length: "; + + header += + "\r\nContent-Type: text/html\r\n" + "Content-Length: "; sprintf(content_length, "%d", content.length()); - header += string(content_length) + "\r\n"; - header += "Pragma: no-cache\r\n"; - header += "Connection: About to close\r\n"; - header += "\r\n"; - + header += + string(content_length) + "\r\n" + "Pragma: no-cache\r\n" + "Connection: About to close\r\n\r\n"; + string webpage = header + content; client.send((char*)webpage.c_str(), webpage.length()); - printf("HTTP sent.\n\r"); + pc.printf("HTTP message sent to client.\n\r"); + /*$on*/ } - + /** * @brief * @note * @param * @retval */ -int main(void) { - printf("Starting\r\n"); - - //net = NetworkInterface::get_default_instance(); - +int main(void) +{ + pc.printf("Starting.. \r\n\r\n"); + net = new EthernetInterface(); if (!net) { - printf("Error! No network inteface found.\n"); + pc.printf("Error! No network inteface found.\n"); return 0; } //net->set_network (IP, NETMASK, GATEWAY); // include this for using static IP address - - nsapi_size_or_error_t r = net->connect(); + nsapi_size_or_error_t r = net->connect(); + if (r != 0) { - printf("Error! net->connect() returned: %d\n", r); + pc.printf("Error! net->connect() returned: %d\n", r); return r; } - // Show the network address - const char *ip = net->get_ip_address(); - const char *netmask = net->get_netmask(); - const char *gateway = net->get_gateway(); - printf("IP address: %s\n", ip ? ip : "None"); - printf("Netmask: %s\n", netmask ? netmask : "None"); - printf("Gateway: %s\n", gateway ? gateway : "None"); - printf("Usage: Type %s/%s/ into your web browser and hit ENTER\r\n", ip, PASSWORD.c_str()); - + // Show the network address + const char* ip = net->get_ip_address(); + const char* netmask = net->get_netmask(); + const char* gateway = net->get_gateway(); + + pc.printf("IP address: %s\r\n", ip ? ip : "None"); + pc.printf("Netmask: %s\r\n", netmask ? netmask : "None"); + pc.printf("Gateway: %s\r\n\r\n", gateway ? gateway : "None"); + pc.printf("Usage: Type %s/%s/ into your web browser and hit ENTER\r\n\r\n", ip, PASSWORD.c_str()); + /* Open the server on ethernet stack */ server.open(net); - + /* Bind the HTTP port (TCP 80) to the server */ - server.bind(ip, 80); - + server.bind(ip, PORT); + /* Can handle 5 simultaneous connections */ server.listen(5); - + //listening for http GET request - while(true) { - printf("=========================================\r\n"); - printf("Ready to serve clients.\r\n"); - server.accept(&clientSocket, &clientAddress); - printf("Connection succeeded!\n\rIP: %s\n\r", clientAddress.get_ip_address()); - clientSocket.recv(receiveBuf, 1023); - printf("Recieved Data: %d\n\r\n\r%.*s\n\r", strlen(receiveBuf), strlen(receiveBuf), receiveBuf); - + while (true) { + pc.printf("=========================================\r\n"); + + nsapi_error_t error; + + clientSocket = server.accept(&error); + if (error != 0) { + pc.printf("Connection failed!\r\n"); + clientSocket->close(); + continue; + } + + clientSocket->getpeername(&clientAddress); + pc.printf("Client with IP address %s connected.\r\n\r\n", clientAddress.get_ip_address()); + clientSocket->recv(receiveBuf, 1023); + pc.printf("Data received:\r\n%s\n\r", receiveBuf); + string received(receiveBuf); - - if(received.substr(0, 3) != "GET") { + + if (received.substr(0, 3) != "GET") { httpHeader = HTTP_OK; httpContent = "<h1>200 OK</h1>"; - sendHTTP(clientSocket, httpHeader, httpContent); + sendHTTP(*clientSocket, httpHeader, httpContent); + clientSocket->close(); continue; } - - if(received.substr(0, 6) == "GET / ") { + + if (received.substr(0, 6) == "GET / ") { httpHeader = HTTP_OK; httpContent = "<p>Usage: Type http://ip_address/password/ into your web browser and hit ENTER</p>\r\n"; - sendHTTP(clientSocket, httpHeader, httpContent); - continue; - } - - int cmd = analyseURL(received); - - if(cmd == -2) { - - // redirect to the right base url - httpHeader = MOVED_PERM; - sendHTTP(clientSocket, httpHeader, movedPermanently(1)); + sendHTTP(*clientSocket, httpHeader, httpContent); + clientSocket->close(); continue; } - - if(cmd == -1) { - httpHeader = UNAUTHORIZED; - httpContent = "<h1>401 Unauthorized</h1>"; - sendHTTP(clientSocket, httpHeader, httpContent); - continue; + + int cmd = analyseURL(received); + + switch (cmd) { + case -3: + // update webpage + httpHeader = HTTP_OK; + sendHTTP(*clientSocket, httpHeader, showWebPage(sw)); + break; + + case -2: + // redirect to the right base url + httpHeader = MOVED_PERM; + sendHTTP(*clientSocket, httpHeader, movedPermanently(1)); + break; + + case -1: + httpHeader = UNAUTHORIZED; + httpContent = "<h1>401 Unauthorized</h1>"; + sendHTTP(*clientSocket, httpHeader, httpContent); + break; + + case 0: + sw = OFF; // turn the switch off + httpHeader = HTTP_OK; + sendHTTP(*clientSocket, httpHeader, showWebPage(sw)); + break; + + case 1: + sw = ON; // turn the switch on + httpHeader = HTTP_OK; + sendHTTP(*clientSocket, httpHeader, showWebPage(sw)); + break; } - - if(cmd == ON) { - sw = ON; // turn the switch on - } - - if(cmd == OFF) { - sw = OFF; // turn the switch off - } - - httpHeader = HTTP_OK; - sendHTTP(clientSocket, httpHeader, showWebPage(sw)); + + clientSocket->close(); } -} \ No newline at end of file +}