X10 Server - IOT device to leverage a collection of old X10 devices for home automation and lighting control.
Dependencies: IniManager mbed HTTPClient SWUpdate mbed-rtos Watchdog X10 SW_HTTPServer SW_String EthernetInterface TimeInterface SSDP
X10 Server
See the X10 Server Nodebook page
Revision 0:de1dfa2ab813, committed 2018-07-03
- Comitter:
- WiredHome
- Date:
- Tue Jul 03 02:10:23 2018 +0000
- Child:
- 1:016d4400254b
- Commit message:
- An example program demonstrating the SSDP-based discovery and a companion Web Server to interact with the mbed device. Scan the network (e.g. in Windows Explorer) to identify the node. Click to open its web page to interact with it.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EthernetInterface.lib Tue Jul 03 02:10:23 2018 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/WiredHome/code/EthernetInterface/#fc5d4611c70e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SSDP.lib Tue Jul 03 02:10:23 2018 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/WiredHome/code/SSDP/#def15d0b2fae
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SW_HTTPServer.lib Tue Jul 03 02:10:23 2018 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/WiredHome/code/SW_HTTPServer/#238dd90b6fb3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SW_String.lib Tue Jul 03 02:10:23 2018 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/users/WiredHome/code/SW_String/#65bc379d8cd0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TimeInterface.lib Tue Jul 03 02:10:23 2018 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/WiredHome/code/TimeInterface/#a89b319b552c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Watchdog.lib Tue Jul 03 02:10:23 2018 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/WiredHome/code/Watchdog/#e0f547e22dd5
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebPages.cpp Tue Jul 03 02:10:23 2018 +0000 @@ -0,0 +1,249 @@ + +#include "mbed.h" + +#include "EthernetInterface.h" +#include "WebPages.h" + +extern EthernetInterface eth; +extern const char * BUILD_DATE; +extern const char * PROG_NAME; +extern const char * My_Name; +extern const char * My_SerialNum; +const int Server_Port = 80; + + +// ########################################## +// This test version controls the LEDs +// +DigitalOut leds[4] = { LED1, LED2, LED3, LED4 }; + + +static const char hdrTypeHTML_NoCache[] = + "Content-Type: text/html\r\n" + "Cache-Control: no-cache\r\n"; + + +// sprintf(buf, ROOTPAGE, "NodeName", "NodeName", "BuildDate", +static const char * ROOTPAGE = + "<!DOCTYPE html>\r\n" + "<html><head><title>%s</title>\r\n" + "</head>\r\n" + "<body>\r\n" + "<h1>%s</h1>" + "This project demonstrates the Smartware web server and the Smartware SSDP discovery server.\n" + "You should be able to scan the network (e.g. in Windows Explorer) and find this device.\n" + "Then you can click on it to open this web page to interact with it.\n" + "<br/><br/>\n" + "<form method='get'>\n" + "<table>\n" + "<tr><td>Build</td><td>%s</td></tr>\n" + "<tr><td>Set LED</td>\n" + "<td><select name='LED'>\n" + " <option value='1'>1</option>\n" + " <option value='2'>2</option>\n" + " <option value='3'>3</option>\n" + " <option value='4'>4</option>\n" + " </select>\n" + " \n" + " <select name='CMD'>\n" + " <option value='0'>Off</option>\n" + " <option value='1'>On</option>\n" + " </select>\n" + "</td></tr>\n" + "<tr><td> </td><td><input type='submit' value='Apply'></td></tr>\n" + "</table>\n" + "</form>\n" + "</body>\n" + "</html>\n" + ""; + + +// The /setup.xml file +// +// sprintf(buf, SETUP_TEMPLATE, "FriendlyName", "udn_hexstring", "serialNum", "ip.ad.dr", portNum); +static const char * SETUP_TEMPLATE = + "<?xml version=\"1.0\"?>\n" + "<root xmlns=\"urn:Belkin:device-1-0\">\n" + " <specVersion>\n" + " <major>1</major>\n" + " <minor>0</minor>\n" + " </specVersion>\n" + " <device>\n" + " <deviceType>urn:Belkin:device:controllee:1</deviceType>\n" + " <friendlyName>%s</friendlyName>\n" + " <manufacturer>Belkin International Inc.</manufacturer>\n" ///< must be "Belkin..." for Alexa discovery + " <manufacturerURL>http://www.smart-family.net</manufacturerURL>\n" ///< + " <modelDescription>Special thing</modelDescription>\n" ///< + " <modelName>Smart Node</modelName>\n" ///< + " <modelNumber>1.0.0</modelNumber>\n" +#if 0 + " <modelURL>http://www.smart-family.net</modelURL>\n" ///< This causes it to fail to send completely +#endif + " <UDN>uuid:Socket-1_0-%s</UDN>\n" + " <serialNumber>%s</serialNumber>\n" + " <iconList>\n" + " <mimetype>jpg</mimetype>\n" + " <width>100</width>\n" + " <height>100</height>\n" + " <depth>100</depth>\n" + " <url>icon.jpg</url>\n" + " </iconList>\n" + " <presentationURL>http://%s:%d</presentationURL>\n" +#if 0 + " <serviceList>\n" + " <service>\n" + " <serviceType>urn:Belkin:service:WiFiSetup:1</serviceType>\n" + " <serviceId>urn:Belkin:serviceId:WiFiSetup1</serviceId>\n" + " <controlURL>/upnp/control/WiFiSetup1</controlURL>\n" + " <eventSubURL>/upnp/event/WiFiSetup1</eventSubURL>\n" + " <SCPDURL>/setupservice.xml</SCPDURL>\n" + " </service>\n" + " <service>\n" + " <serviceType>urn:Belkin:service:timesync:1</serviceType>\n" + " <serviceId>urn:Belkin:serviceId:timesync1</serviceId>\n" + " <controlURL>/upnp/control/timesync1</controlURL>\n" + " <eventSubURL>/upnp/event/timesync1</eventSubURL>\n" + " <SCPDURL>/timesyncservice.xml</SCPDURL>\n" + " </service>\n" + " <service>\n" + " <serviceType>urn:Belkin:service:basicevent:1</serviceType>\n" + " <serviceId>urn:Belkin:serviceId:basicevent1</serviceId>\n" + " <controlURL>/upnp/control/basicevent1</controlURL>\n" + " <eventSubURL>/upnp/event/basicevent1</eventSubURL>\n" + " <SCPDURL>/eventservice.xml</SCPDURL>\n" + " </service>\n" + " <service>\n" + " <serviceType>urn:Belkin:service:firmwareupdate:1</serviceType>\n" + " <serviceId>urn:Belkin:serviceId:firmwareupdate1</serviceId>\n" + " <controlURL>/upnp/control/firmwareupdate1</controlURL>\n" + " <eventSubURL>/upnp/event/firmwareupdate1</eventSubURL>\n" + " <SCPDURL>/firmwareupdate.xml</SCPDURL>\n" + " </service>\n" + " <service>\n" + " <serviceType>urn:Belkin:service:rules:1</serviceType>\n" + " <serviceId>urn:Belkin:serviceId:rules1</serviceId>\n" + " <controlURL>/upnp/control/rules1</controlURL>\n" + " <eventSubURL>/upnp/event/rules1</eventSubURL>\n" + " <SCPDURL>/rulesservice.xml</SCPDURL>\n" + " </service>\n" + " <service>\n" + " <serviceType>urn:Belkin:service:metainfo:1</serviceType>\n" + " <serviceId>urn:Belkin:serviceId:metainfo1</serviceId>\n" + " <controlURL>/upnp/control/metainfo1</controlURL>\n" + " <eventSubURL>/upnp/event/metainfo1</eventSubURL>\n" + " <SCPDURL>/metainfoservice.xml</SCPDURL>\n" + " </service>\n" + " <service>\n" + " <serviceType>urn:Belkin:service:remoteaccess:1</serviceType>\n" + " <serviceId>urn:Belkin:serviceId:remoteaccess1</serviceId>\n" + " <controlURL>/upnp/control/remoteaccess1</controlURL>\n" + " <eventSubURL>/upnp/event/remoteaccess1</eventSubURL>\n" + " <SCPDURL>/remoteaccess.xml</SCPDURL>\n" + " </service>\n" + " <service>\n" + " <serviceType>urn:Belkin:service:deviceinfo:1</serviceType>\n" + " <serviceId>urn:Belkin:serviceId:deviceinfo1</serviceId>\n" + " <controlURL>/upnp/control/deviceinfo1</controlURL>\n" + " <eventSubURL>/upnp/event/deviceinfo1</eventSubURL>\n" + " <SCPDURL>/deviceinfoservice.xml</SCPDURL>\n" + " </service>\n" + " <service>\n" + " <serviceType>urn:Belkin:service:smartsetup:1</serviceType>\n" + " <serviceId>urn:Belkin:serviceId:smartsetup1</serviceId>\n" + " <controlURL>/upnp/control/smartsetup1</controlURL>\n" + " <eventSubURL>/upnp/event/smartsetup1</eventSubURL>\n" + " <SCPDURL>/smartsetup.xml</SCPDURL>\n" + " </service>\n" + " <service>\n" + " <serviceType>urn:Belkin:service:manufacture:1</serviceType>\n" + " <serviceId>urn:Belkin:serviceId:manufacture1</serviceId>\n" + " <controlURL>/upnp/control/manufacture1</controlURL>\n" + " <eventSubURL>/upnp/event/manufacture1</eventSubURL>\n" + " <SCPDURL>/manufacture.xml</SCPDURL>\n" + " </service>\n" + " </serviceList>\n" +#endif + " </device>\n" + "</root>\n"; + + +HTTPServer::CallBackResults Setup_xml(HTTPServer *svr, HTTPServer::CallBackType type, char * path, + const HTTPServer::namevalue *queryParams, int queryParamCount) +{ + char BigBuffer[1000]; + HTTPServer::CallBackResults ret = HTTPServer::ACCEPT_ERROR; + printf("Setup.xml responder\n"); + switch (type) { + case HTTPServer::SEND_PAGE: + svr->header(HTTPServer::OK, "OK", hdrTypeHTML_NoCache); + sprintf(BigBuffer, SETUP_TEMPLATE, + My_Name, eth.getMACAddress(), My_SerialNum, + eth.getIPAddress(), Server_Port); + svr->send(BigBuffer); + ret = HTTPServer::ACCEPT_COMPLETE; + break; + case HTTPServer::CONTENT_LENGTH_REQUEST: + ret = HTTPServer::ACCEPT_COMPLETE; + break; + case HTTPServer::DATA_TRANSFER: + ret = HTTPServer::ACCEPT_COMPLETE; + break; + default: + ret = HTTPServer::ACCEPT_ERROR; + break; + } + return ret; +} + + + +HTTPServer::CallBackResults RootPage(HTTPServer *svr, HTTPServer::CallBackType type, char * path, + const HTTPServer::namevalue *queryParams, int queryParamCount) +{ + char BigBuffer[1000]; + HTTPServer::CallBackResults ret = HTTPServer::ACCEPT_ERROR; + printf("RootPage responder\n"); + + int led, cmd; + int mask = 0; + for (int i=0; i<queryParamCount; i++) { + if (strcmp(queryParams[i].name, "LED") == 0) { + led = atoi(queryParams[i].value); + mask |= 1; + } else if (strcmp(queryParams[i].name, "CMD") == 0) { + cmd = atoi(queryParams[i].value); + mask |= 2; + } + } + if (mask == 3) { + switch (led) { + case 1: + case 2: + case 3: + case 4: + leds[led - 1] = cmd; + break; + default: + break; + } + } + + switch (type) { + case HTTPServer::SEND_PAGE: + svr->header(HTTPServer::OK, "OK", hdrTypeHTML_NoCache); + sprintf(BigBuffer, ROOTPAGE, PROG_NAME, PROG_NAME, BUILD_DATE); + svr->send(BigBuffer); + ret = HTTPServer::ACCEPT_COMPLETE; + break; + case HTTPServer::CONTENT_LENGTH_REQUEST: + ret = HTTPServer::ACCEPT_COMPLETE; + break; + case HTTPServer::DATA_TRANSFER: + ret = HTTPServer::ACCEPT_COMPLETE; + break; + default: + ret = HTTPServer::ACCEPT_ERROR; + break; + } + return ret; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebPages.h Tue Jul 03 02:10:23 2018 +0000 @@ -0,0 +1,14 @@ + +#ifndef WEBPAGES_H +#define WEBPAGES_H + +#include "SW_HTTPServer.h" + + +HTTPServer::CallBackResults Setup_xml(HTTPServer *svr, HTTPServer::CallBackType type, char * path, + const HTTPServer::namevalue *queryParams, int queryParamCount); + +HTTPServer::CallBackResults RootPage(HTTPServer *svr, HTTPServer::CallBackType type, char * path, + const HTTPServer::namevalue *queryParams, int queryParamCount); + +#endif // WEBPAGES_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue Jul 03 02:10:23 2018 +0000 @@ -0,0 +1,58 @@ +// +// A simple SSDP example +// +#include "mbed.h" // ver 120; mbed-rtos ver 111 +#include "EthernetInterface.h" // ver 55 +#include "SW_HTTPServer.h" // ver 50 +#include "TimeInterface.h" // ver 23 +#include "Watchdog.h" // ver 6 +#include "SW_String.h" // ver 1 +#include "SSDP.h" // ver 0 + +#include "WebPages.h" // Private handler for web queries + +RawSerial pc(USBTX, USBRX); + +EthernetInterface eth; +TimeInterface ntp(ð); +Watchdog wd; +time_t lastboottime; + +//FlashFileSystem flash("flash"); // static files here for reliability and speed +LocalFileSystem local("local"); // some place to hold settings and maybe the static web pages + +const char * Server_Root = "/local"; + +// public for the WebPages handler to see +// +const char * BUILD_DATE = __DATE__ " " __TIME__; +const char * PROG_NAME = "SSDP Server"; +const char * My_Name = "MBED SSDP Node"; +const char * My_SerialNum = "0000001"; +const int Server_Port = 80; +// end public information + + +int main() { + pc.baud(460800); + pc.printf("\r\n%s Build %s\r\n", PROG_NAME, BUILD_DATE); + if (wd.WatchdogCausedReset()) { + pc.printf("**** Watchdog Event caused reset at %s ****\r\n", ntp.ctime(&lastboottime)); + } + wd.Configure(45); // very generous, but this is a network appliance, so a bit less deterministic. + + eth.init(); //Use DHCP + eth.connect(); + printf("IP: %s\n", eth.getIPAddress()); + //Thread thr(SSDPListener, NULL, osPriorityLow); + HTTPServer svr(Server_Port, Server_Root, 15, 30, 20, 50, &pc); + svr.RegisterHandler("/", RootPage); + svr.RegisterHandler("/setup.xml", Setup_xml); + SSDP ssdp("Friendly Node", eth.getMACAddress(), eth.getIPAddress(), Server_Port); + + while (1) { + wd.Service(); + svr.Poll(); // non-blocking, but also not deterministic + Thread::yield(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-rtos.lib Tue Jul 03 02:10:23 2018 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed-rtos/#162b12aea5f2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Tue Jul 03 02:10:23 2018 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/users/mbed_official/code/mbed/builds/7c328cabac7e \ No newline at end of file