Webserver controller with url trimming for value controls
Dependencies: LCD_DISCO_F746NG BSP_DISCO_F746NG
main.cpp
- Committer:
- jonasnimb7992
- Date:
- 2019-08-26
- Revision:
- 10:f941e0750773
- Parent:
- 9:161bed13b17e
File content as of revision 10:f941e0750773:
#include "mbed.h" #include "EthernetInterface.h" #include "TCPSocket.h" #include "LCD_DISCO_F746NG.h" #include <stdio.h> #include <vector> #include <sstream> #include <iostream> // std::cout #include <string> // std::string using namespace std; #define IP "192.168.137.200" #define GATEWAY "192.168.137.1" #define NETMASK "255.255.255.0" #define PORT 80 Serial pc(USBTX, USBRX); EthernetInterface* net; TCPSocket server; TCPSocket* clientSocket; SocketAddress clientAddress; LCD_DISCO_F746NG displayLCD; Thread tempUpdater; // Multithreaded temp updater Thread urlManager; // Thread for url management char receiveBuf[1024]; const int OFF = 0; // Switch off const int ON = 1; // Switch on DigitalOut sw(LED1); // A digital output to be switched on/off PwmOut PwrLED(D3); // Simulation of motor control AnalogIn tempSensor(A0); // Temperature sensor float roomTemp = 0.0; // A temperature sensor output float units; // Final variable to contain temp value unsigned int a, beta = 3975; // Unsigned int's to use for temperature calculations float resistance; // LE PIECE OF RESISTAAAANCE float temperature; // Temperature variable to use for calculations int sliderVal // Value of the slider const string PASSWORD = "daddyshark"; // 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 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 -3 just refresh page * -2 no command given but password valid * -1 invalid password * 0 switch off * 1 switch on */ 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) != "/") return(-1); if (url.substr(pos++, 1) == " ") return(-2); string cmd(url.substr(pos, 5)); if (cmd == "?sw=0") return(0); if (cmd == "?sw=1") return(1); return(-3); } /** * @brief * @note * @param * @retval */ 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(int status) { char roomTempStr[5]; //roomTemp = ds1820.read(); sprintf(roomTempStr, "%3.1f", roomTemp); /*$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'>" "<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js\"></script>" "<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>" "<script>" "$(document).ready(function(){" "setInterval(function() {" "$(\"#readTemp\").load(\" #readTemp\");" "}, 10000);" "$(\"#click\").click(function(){" "$(\"#readTemp\").load(\" #readTemp\");" "});" "});" "</script>" "</head>" "<body>" "<h2><a href=\".\" title=\"Click to refresh the page\">Smart Home</a></h2>" "<button id=\"click\">Click on this.</button>" "<div id=\"readTemp\">" "<pre>Temperature:\t" + string(roomTempStr) + "°C</pre>" "<pre>Temperature:\t" + string(roomTempStr) + "°C</pre>" "</div>" "<pre>Heating:\t"; if(status == ON) { httpContent += "<a href=\"./?sw=0\" class=\"switch\"> " "<input type=\"checkbox\" checked>"; } else { httpContent += "<a href=\"./?sw=1\" class=\"switch\"> " "<input type=\"checkbox\">"; } httpContent += "<div class=\"slider\"></div>" "</body>"; return httpContent; /*$on*/ } /** * @brief * @note * @param * @retval */ void sendHTTP(TCPSocket& client, string& header, string& content) { /*$off*/ char content_length[5] = { }; header += "\r\nContent-Type: text/html\r\n" "Content-Length: "; sprintf(content_length, "%d", content.length()); 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()); pc.printf("HTTP message sent to client.\n\r"); /*$on*/ } void clearLineLCD(int line) { displayLCD.DisplayStringAt(0, LINE(line),(uint8_t *)(" "), CENTER_MODE); } int findURL(string mainString,string stringToFind) { int foundAt; int number; //printf("String to search in: %s\r\n", mainString); //printf("String to search for: %s\r\n", stringToFind); std::size_t found = mainString.find(stringToFind); if (found != string::npos) { foundAt = found; //printf("Found at %i\r\n", foundAt); string getString = mainString.substr(foundAt, 7); string trimString = getString.substr(stringToFind.length(), 3); std::istringstream iss (trimString); iss >> number; //printf("%s found: %s\r\n", stringToFind, getString); //printf("Converting: %s\r\n", trimString); //printf("Final Number = %i\r\n", number); } else { number = -1; } return number; } void tempReader() { while (true) { a = tempSensor.read_u16(); /* Read analog value */ // Calculate the resistance of the thermistor from analog voltage read. resistance= (float) 10000.0 * ((65536.0 / a) - 1.0); // Convert the resistance to temperature using Steinhart's Hart equation temperature=(1/((log(resistance/10000.0)/beta) + (1.0/298.15)))-273.15; units = (float) temperature; roomTemp = units; if (sw == ON) { if (roomTemp >= 30) { PwrLED = 0.80; } else { PwrLED = 0.20; } } if (sw == OFF) { PwrLED = 0; } char tempStr[20]; sprintf(tempStr, "Temperature is: %3.1f C", roomTemp); displayLCD.DisplayStringAt(0, LINE(6),(uint8_t *)(tempStr), CENTER_MODE); Thread::wait(1000); } } /** * @brief * @note * @param * @retval */ int main(void) { displayLCD.Clear(LCD_COLOR_BLACK); displayLCD.SetBackColor(LCD_COLOR_BLACK); displayLCD.SetTextColor(LCD_COLOR_WHITE); pc.printf("Starting.. \r\n\r\n"); net = new EthernetInterface(); if (!net) { 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(); if (r != 0) { 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(); displayLCD.DisplayStringAt(0, LINE(2),(uint8_t *)("IP Address"), CENTER_MODE); displayLCD.DisplayStringAt(0, LINE(4),(uint8_t *)( ip ? ip : "None"), CENTER_MODE); 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()); tempUpdater.start(tempReader); // Starting the multithreaded workload so it won't affect main program /* Open the server on ethernet stack */ server.open(net); /* Bind the HTTP port (TCP 80) to the server */ server.bind(ip, PORT); /* Can handle 5 simultaneous connections */ server.listen(5); //listening for http GET request 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") { httpHeader = HTTP_OK; httpContent = "<h1>200 OK</h1>"; sendHTTP(*clientSocket, httpHeader, httpContent); clientSocket->close(); continue; } 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); clientSocket->close(); continue; } int cmd = analyseURL(received); int testFind = findURL(received, "val="); if (testFind == -1) { printf("--------------Couldn't find 'val='\r\n"); } if (testFind >= 0) { printf("--------------Found 'val=': %i\r\n", testFind); } 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 PwrLED = 0; // turn the "motor" led off clearLineLCD(8); displayLCD.DisplayStringAt(0, LINE(8),(uint8_t *)("Heating OFF"), CENTER_MODE); httpHeader = HTTP_OK; sendHTTP(*clientSocket, httpHeader, showWebPage(sw)); break; case 1: sw = ON; // turn the switch on clearLineLCD(8); displayLCD.DisplayStringAt(0, LINE(8),(uint8_t *)("Heating ON"), CENTER_MODE); httpHeader = HTTP_OK; sendHTTP(*clientSocket, httpHeader, showWebPage(sw)); break; } clientSocket->close(); } }