Spidey Wall is the name for a physical wall lit up by multiple addressable LED strips. This program is an LPC1768 web server to control the wall from a browser.

Dependencies:   EthernetInterfacePlusHostname RdWebServer mbed-rtos mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 // 
00002 // LightWall WebServer
00003 // 
00004 // Rob Dobson (C) 2015
00005 // 
00006 // See http://robdobson.com/2015/07/spidey-wall/ and http://robdobson.com/2015/08/a-reliable-mbed-webserver/
00007 //
00008 
00009 #include "mbed.h"
00010 #include "EthernetInterface.h"
00011 #include "RdWebServer.h"
00012 #include "DrawingManager.h"
00013 #include "Idler.h"
00014 #include <string.h>
00015 
00016 // Web port
00017 const int WEBPORT = 80; // Port for web server
00018 
00019 // Debugging and status
00020 RawSerial pc(USBTX, USBRX);
00021 DigitalOut led1(LED1); // flashes on command received
00022 DigitalOut led2(LED2); //
00023 DigitalOut led3(LED3); //
00024 DigitalOut led4(LED4); // web server status
00025 
00026 // System configuration
00027 char systemName[20] = "LightWall";
00028 int systemNumLEDS = 20;
00029 int systemLEDSSplitPoint = systemNumLEDS;
00030 
00031 // Drawing Manager
00032 DrawingManager drawingManager;
00033 
00034 // Idler - to display something when not being driven by the web interface
00035 Idler idler(&led2, &drawingManager);
00036 
00037 // General response string for REST requests
00038 char* generalRespStr = "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Methods: POST, GET, OPTIONS\r\nAccess-Control-Allow-Headers:accept, content-type\r\nContent-Length: 0\r\nContent-Type: application/octet-stream\r\n\r\n";
00039 
00040 // Get system name - No arguments required
00041 char* lightwallGetSystemName(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen, 
00042                 int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
00043 {
00044     // Return the system name
00045     return systemName;
00046 }
00047 
00048 // Clear LEDS - No arguments required
00049 char* lightwallClear(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen, 
00050                 int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
00051 {
00052     idler.notIdle();
00053     drawingManager.Clear();
00054     return generalRespStr;
00055 }
00056 
00057 // RawFill - arguments for start LED (e.g. /rawfill?start=0)
00058 //         - payload of message contains binary data for RGB (1 byte for each) for each LED to be set
00059 char* lightwallRawFill(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen, 
00060                 int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
00061 {
00062     idler.notIdle();
00063     drawingManager.RawFill(argStr, pPayload, payloadLen, splitPayloadPos);
00064     return generalRespStr;
00065 }
00066 
00067 // Fill - arguments for start, numLeds, initial-R/G/B and ending-R/G/B (optional)
00068 //      - e.g. /fill?start=0&len=100&r1=20&g1=30&b1=50
00069 //      - e.g. /fill?start=0&len=100&r1=20&g1=30&b1=50&r2=50&g2=100&b2=23
00070 char* lightwallFill(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen, 
00071                 int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
00072 {
00073     idler.notIdle();
00074     drawingManager.Fill(argStr);
00075     return generalRespStr;
00076 }
00077 
00078 // ShowLeds - no arguments
00079 char* lightwallShowLeds(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen, 
00080                 int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
00081 {
00082     // Blink LED
00083     led1 = !led1;
00084     // Show LEDS
00085     idler.notIdle();
00086     drawingManager.ShowLeds();
00087     return generalRespStr;
00088 }
00089 
00090 // Create, configure and run the web server
00091 void http_server(void const* arg)
00092 {
00093     // Init the web server
00094     pc.printf("Starting web server\r\n");
00095     char* baseWebFolder = "/sd/";  // should be /sd/ for SDcard files - not used for local file system
00096     RdWebServer webServer;
00097     
00098     // Add commands to handle the home page and favicon
00099     webServer.addCommand("", RdWebServerCmdDef::CMD_LOCALFILE, NULL, "index.htm", true);
00100     webServer.addCommand("favicon.ico", RdWebServerCmdDef::CMD_LOCALFILE, NULL, NULL, true);
00101     
00102     // Add the lightwall control commands
00103     webServer.addCommand("name", RdWebServerCmdDef::CMD_CALLBACK, &lightwallGetSystemName);
00104     webServer.addCommand("clear", RdWebServerCmdDef::CMD_CALLBACK, &lightwallClear);
00105     webServer.addCommand("rawfill", RdWebServerCmdDef::CMD_CALLBACK, &lightwallRawFill);
00106     webServer.addCommand("fill", RdWebServerCmdDef::CMD_CALLBACK, &lightwallFill);
00107     webServer.addCommand("showleds", RdWebServerCmdDef::CMD_CALLBACK, &lightwallShowLeds);
00108     
00109     // Start the server
00110     webServer.init(WEBPORT, &led4, baseWebFolder);
00111     webServer.run();
00112 }
00113 
00114 void getSystemConfig()
00115 {
00116     printf("LightWall - Configured for ");
00117     // Check for a config file on the local file system
00118     LocalFileSystem local("local");
00119     FILE* fp = fopen("/local/lights.txt", "r");
00120     if (fp != NULL)
00121     {
00122         char buf[201];
00123         buf[sizeof(buf)-1] = 0;
00124         int nread = fread(buf, 1, sizeof(buf), fp);
00125         if (nread > 0 && nread <= sizeof(buf))
00126         {
00127             buf[nread] = 0;
00128             // Read config details from the file
00129             sscanf(buf, "%s %d %d", systemName, &systemNumLEDS, &systemLEDSSplitPoint);
00130         }
00131         fclose(fp);
00132         printf("%s (%d LEDs, Split at %d)", systemName, systemNumLEDS, systemLEDSSplitPoint);
00133         printf("\r\n");
00134     }
00135 }
00136 
00137 int main() 
00138 {
00139     // Init
00140     pc.baud(115200);
00141     pc.printf("Light Wall - Rob Dobson 2015\r\n");
00142     
00143     // Wait for a moment
00144     wait(1);
00145 
00146     // Get the configuration of the system
00147     getSystemConfig();
00148     
00149     // Drawing manager controls the LEDs
00150     drawingManager.Init(systemNumLEDS, systemLEDSSplitPoint);
00151 
00152     // Start idler
00153     idler.start();
00154         
00155     // Setup ethernet interface
00156     char macAddr[6];
00157     mbed_mac_address(macAddr);
00158     pc.printf("Ethernet MAC address: %02x:%02x:%02x:%02x:%02x:%02x\r\n", macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]); 
00159     pc.printf("Connecting to ethernet ...\r\n");
00160 
00161     // Init ethernet
00162     EthernetInterface::init();
00163 
00164     // Using code described here https://developer.mbed.org/questions/1602/How-to-set-the-TCPIP-stack-s-hostname-pr/
00165     // to setName on the ethernet interface
00166     EthernetInterface::setName(systemName);
00167 
00168     // Connect ethernet
00169     EthernetInterface::connect();
00170     pc.printf("IP Address: %s HostName %s\r\n", EthernetInterface::getIPAddress(), EthernetInterface::getName());
00171 
00172     // Web Server used to run in a thread - but I've found this slows performance a lot as described here:
00173     // http://robdobson.com/2015/08/a-reliable-mbed-webserver/
00174     // Fortunately it doesn't matter as the LED code is all interrupt driven
00175     // This is the previous code...
00176     // Thread httpServer(&http_server, NULL, osPriorityNormal, (DEFAULT_STACK_SIZE * 3));
00177     http_server("");
00178 
00179     // Forever - actually it won't even get here as the server has a forever loop in it too
00180     while(true)
00181     {
00182     }
00183 }