OK. Here you are. But now it’s you turn to extend the code further.
#include "mbed.h"
#include "EthernetInterface.h"
#include "TCPSocket.h"
#define IP "192.168.1.181"
#define GATEWAY "192.168.1.1"
#define NETMASK "255.255.255.0"
#define PORT 80
EthernetInterface* net;
TCPSocket server;
TCPSocket* clientSocket;
SocketAddress clientAddress;
char httpBuf[2000] = { 0 };
char httpHeader[256] = { 0 };
const int OFF = 0;
const int ON = 1;
const char PASSWORD[] = "secret"; // Change as you like
int volume = 0;
PwmOut output(LED1);
DigitalOut relay(LED2);
Thread webServerThread;
void webServerTask();
/**
* @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/?volume=25 HTTP/1.....
* GET /password/?relay=102 HTTP/1.....
* @param url URL string
* @retval -3 just refresh page
* -2 no command given but password valid
* -1 invalid password
* 0:100 value of volume
* 101,102 value of relay
*/
int8_t analyseURL(char* url)
{
if (strlen(url) < (5 + strlen(PASSWORD) + 1))
return(-1);
//if (url.substr(5, PASSWORD.size()) != PASSWORD)
if (strncmp(url + 5, PASSWORD, strlen(PASSWORD)) != 0)
return(-1);
uint8_t pos = 5 + strlen(PASSWORD);
//if (url.substr(pos, 1) != "/")
if (*(url + pos) != '/')
return(-1);
//if (url.substr(pos++, 1) == " ")
if (*(url + pos++) == ' ')
return(-2);
//string cmd(url.substr(pos, 5));
*(url + pos + 11) = '\0'; // terminate the cmd string
char* cmd = ((url + pos));
printf("cmd=%s\r\n", cmd);
if (strcmp(cmd, "?volume=0 H") == 0)
return(0);
if (strcmp(cmd, "?volume=25 ") == 0)
return(25);
if (strcmp(cmd, "?volume=50 ") == 0)
return(50);
if (strcmp(cmd, "?volume=75 ") == 0)
return(75);
if (strcmp(cmd, "?volume=100") == 0)
return(100);
if (strcmp(cmd, "?relay=101 ") == 0)
return(101);
if (strcmp(cmd, "?relay=102 ") == 0)
return(102);
return(-3);
}
/**
* @brief
* @note
* @param
* @retval
*/
char* movedPermanently(uint8_t flag)
{
memset(httpBuf, 0, sizeof(httpBuf));
if (flag == 1) {
strcpy(httpBuf, "/");
strcat(httpBuf, PASSWORD);
strcat(httpBuf, "/");
}
strcat(httpBuf, "<h1>301 Moved Permanently</h1>\r\n");
return(httpBuf);
}
/**
* @brief
* @note
* @param
* @retval
*/
char* showWebPage()
{
char strBuf[16];
memset(httpBuf, 0, sizeof(httpBuf));
/*$off*/
strcat
(
httpBuf,
"<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'>"
);
strcat
(
httpBuf,
"<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>"
);
strcat
(
httpBuf,
"</head>"
"<body>"
"<h2><a href=\".\" title=\"Click to refresh the page\">PWM Control</a></h2>"
"<pre>Volume:</pre>"
);
strcat(httpBuf, "<a href='./?volume=0' id='volume_slider'>");
strcat(httpBuf, "<input type='range' id='volume_range' min='0' max='100' step='25' value=");
memset(strBuf, 0, sizeof(strBuf));
sprintf(strBuf, "'%d'", volume);
strcat(httpBuf, strBuf);
strcat
(
httpBuf,
" oninput='myFunction(this.value);'>"
"</a>"
"<span id='volume_display'>"
);
memset(strBuf, 0, sizeof(strBuf));
sprintf(strBuf, "%d", volume);
strcat(httpBuf, strBuf);
strcat(httpBuf, "</span>");
strcat(httpBuf, "<br><br>");
strcat(httpBuf, "<pre>Relay:\t");
if(relay == 1) {
strcat
(
httpBuf,
"<a href='./?relay=101' class='switch'> "
"<input type='checkbox' checked>"
);
}
else {
strcat
(
httpBuf,
"<a href='./?relay=102' class='switch'> "
"<input type='checkbox'>"
);
}
strcat
(
httpBuf,
"<div class=\"slider\"></div>"
"</a>"
"</pre>"
"<hr>"
);
strcat(httpBuf, "<pre>MbedARM</pre>");
strcat
(
httpBuf,
"<script type='text/javascript'>"
"function myFunction(newVol) {"
"document.getElementById('volume_slider').href = './?volume='+newVol;"
"document.getElementById('volume_display').innerText = newVol;"
"}"
"</script>"
);
strcat(httpBuf, "</body>");
return httpBuf;
/*$on*/
}
/**
* @brief
* @note
* @param
* @retval
*/
void sendHTTP(TCPSocket* client, char* header, char* content)
{
char content_length[10] = { };
sprintf(content_length, "%u\r\n", strlen(content));
strcat(header, "\r\nContent-Type: text/html\r\n");
strcat(header, "Content-Length: ");
strcat(header, content_length);
strcat(header, "Pragma: no-cache\r\n");
strcat(header, "Connection: About to close\r\n\r\n");
char c = content[0];
memmove(httpBuf + strlen(header), httpBuf, strlen(content)); // make room for the header
strcpy(httpBuf, header); // copy the header on front of the content
httpBuf[strlen(header)] = c;
client->send((uint8_t*)httpBuf, strlen(httpBuf));
}
//**
/**
* @brief
* @note
* @param
* @retval
*/
void webServerTask()
{
net = new EthernetInterface;
if (!net) {
printf("Error! No network inteface found.\n");
return;
}
//net->set_network (IP, NETMASK, GATEWAY); // include to use static IP address
nsapi_size_or_error_t r = net->connect();
if (r != 0) {
printf("Error! net->connect() returned: %d\n", r);
return;
}
// Show the network address
SocketAddress ip;
SocketAddress netmask;
SocketAddress gateway;
net->get_ip_address(&ip);
net->get_netmask(&netmask);
net->get_gateway(&gateway);
ip.set_port(PORT);
const char* ipAddr = ip.get_ip_address();
const char* netmaskAddr = netmask.get_ip_address();
const char* gatewayAddr = gateway.get_ip_address();
printf("IP address: %s\r\n", ipAddr ? ipAddr : "None");
printf("Netmask: %s\r\n", netmaskAddr ? netmaskAddr : "None");
printf("Gateway: %s\r\n", gatewayAddr ? gatewayAddr : "None");
/* Open the server on ethernet stack */
server.open(net);
/* Bind the HTTP port (TCP 80) to the server */
server.bind(ip);
/* Can handle 5 simultaneous connections */
server.listen(5);
printf("Usage: Type %s/%s/ into your web browser and hit ENTER\r\n", ipAddr, PASSWORD);
//listening for http GET request
while (true) {
printf("================================================\r\n");
nsapi_error_t error = 0;
clientSocket = server.accept(&error);
if (error != 0) {
printf("Connection failed!\r\n");
}
else {
//clientSocket->set_timeout(200);
clientSocket->getpeername(&clientAddress);
printf("Client with IP address %s connected.\r\n", clientAddress.get_ip_address());
error = clientSocket->recv(httpBuf, sizeof(httpBuf));
switch (error) {
case 0:
printf("Recieved buffer is empty.\r\n");
break;
case -1:
printf("Failed to read data from client.\r\n");
break;
default:
//printf("Recieved Data: %d\n\r\n\r%.*s\r\n\n\r", strlen(httpBuf), httpBuf);
if (strncmp(httpBuf, "GET", 3) != 0) {
strcpy(httpHeader, "HTTP/1.0 200 OK");
strcpy(httpBuf, "<h1>200 OK</h1>");
sendHTTP(clientSocket, httpHeader, httpBuf);
}
else
if ((strncmp(httpBuf, "GET", 3) == 0) && (strncmp(httpBuf + 3, " / ", 3) == 0)) {
strcpy(httpHeader, "HTTP/1.0 200 OK");
strcpy(httpBuf, "<p>Usage: http://host_or_ip/password</p>\r\n");
sendHTTP(clientSocket, httpHeader, httpBuf);
}
else {
int result = analyseURL(httpBuf);
switch (result) {
case -3:
// update webpage
strcpy(httpHeader, "HTTP/1.0 200 OK");
sendHTTP(clientSocket, httpHeader, showWebPage());
break;
case -2:
// redirect to the right base url
strcpy(httpHeader, "HTTP/1.0 301 Moved Permanently\r\nLocation: ");
sendHTTP(clientSocket, httpHeader, movedPermanently(1));
break;
case -1:
strcpy(httpHeader, "HTTP/1.0 401 Unauthorized");
strcpy(httpBuf, "<h1>401 Unauthorized</h1>");
sendHTTP(clientSocket, httpHeader, httpBuf);
break;
case 101:
relay = 0;
strcpy(httpHeader, "HTTP/1.0 200 OK");
sendHTTP(clientSocket, httpHeader, showWebPage());
break;
case 102:
relay = 1;
strcpy(httpHeader, "HTTP/1.0 200 OK");
sendHTTP(clientSocket, httpHeader, showWebPage());
break;
default:
volume = result; // output on
output.write(volume / 100.0f);
strcpy(httpHeader, "HTTP/1.0 200 OK");
sendHTTP(clientSocket, httpHeader, showWebPage());
break;
}
}
break;
}
}
clientSocket->close();
printf("Client socket closed\r\n");
}
}
/**
* @brief
* @note
* @param
* @retval
*/
int main(void)
{
printf("Starting\r\n");
webServerThread.start(callback(webServerTask));
while (true) {
ThisThread::sleep_for(200ms);
}
}