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
This project is part of a Light-Wall using addressable LED strips (WS2801). I have published a few posts on my blog about the construction of the wall and building a game to play on it (PacMan). I have also had a guest post from a friend who has set his children the task of producing some interesting animations. The original post is http://robdobson.com/2015/07/spidey-wall/
So far, however, I hadn't fully connected the physical (and electronic) wall with the web-browser creations to drive it. This project is hopefully the final link. A fast and reliable web server using REST commands to drive the 1686 LEDs in the Spidey Wall from code running in a browser (say on an iPad while you are playing a game).
The approach taken here results in the ability to control the RGB values of all 1686 LEDs at a rate of 20 frames per second.
A blog post describing the whole thing is here:
http://robdobson.com/2015/08/a-reliable-mbed-webserver/
Diff: main.cpp
- Revision:
- 1:362331cec9b7
- Parent:
- 0:887096209439
- Child:
- 2:99eb4c6e9ea4
--- a/main.cpp Tue Aug 18 16:03:29 2015 +0000
+++ b/main.cpp Thu Aug 20 07:41:02 2015 +0000
@@ -1,170 +1,230 @@
-/* main.cpp
- Rob Dobson 2013
- More details at ???
-*/
+//
+// Spidey Wall WebServer
+//
+// Rob Dobson 2015
#include "mbed.h"
#include "EthernetInterface.h"
-#include <stdio.h>
+#include "RdWebServer.h"
+#include "DrawingManager.h"
#include <string.h>
-#include "RdWebServer.h"
-#include "ledstrip.h"
-#include "LedCmdHandler.h"
+
+// Web port
+const int WEBPORT = 80; // Port for web server
-#define PORT 80
-
-Serial pc(USBTX, USBRX);
+// Debugging and status
+RawSerial pc(USBTX, USBRX);
+DigitalOut led1(LED1); // ticking (flashes)
+DigitalOut led2(LED2); //
+DigitalOut led3(LED3); //
+DigitalOut led4(LED4); // web server status
-RdWebServer webServer;
-
-EthernetInterface eth;
+// Drawing Manager
+DrawingManager drawingManager(1686, 780);
-DigitalOut led1(LED1); //server listning status
-DigitalOut led2(LED2); //socket connecting status
-
-Ticker ledTick;
+//int ledsCount = 904;
+//int ledSplitPoint = 448;
+//ledstrip* pLedStrip = NULL;
+//
+//char* indexHtmName = "index.htm";
+//
+//const int TICK_MS = 100;
+//LedCmdHandler* pLedCmdHandler = NULL;
+//int blinkCtr = 0;
+//
+//void ledTickfunc()
+//{
+// if(webServer.isListening())
+// {
+// blinkCtr++;
+// if (blinkCtr > 1)
+// {
+// led1 = !led1;
+// blinkCtr = 0;
+// }
+// }
+// else
+// {
+// led1 = false;
+// }
+//
+// if (pLedCmdHandler != NULL)
+// pLedCmdHandler->NextGen();
+//}
+//
+//void handleCmd_ledControl(char* cmdStr, char* argStr)
+//{
+// printf("LEDS COMMAND %s %s\r\n", cmdStr, argStr);
+// if (argStr == NULL)
+// return;
+// pLedCmdHandler->DoCommand(argStr);
+//
+// // Store last command
+// LocalFileSystem local("local");
+// FILE* fp = fopen("/local/lastcmd.inf", "w");
+// if (fp != NULL)
+// {
+// fwrite(argStr, 1, strlen(argStr)+1, fp);
+// fclose(fp);
+// }
+//}
+//
+//void reRunLastCommand()
+//{
+// // Store last command
+// LocalFileSystem local("local");
+// FILE* fp = fopen("/local/lastcmd.inf", "r");
+// if (fp != NULL)
+// {
+// char buf[501];
+// buf[sizeof(buf)-1] = 0;
+// int nread = fread(buf, 1, sizeof(buf), fp);
+// fclose(fp);
+// if (nread > 0 && nread <= sizeof(buf))
+// {
+// buf[nread] = 0;
+// pLedCmdHandler->DoCommand(buf);
+// }
+// }
+//}
+//
+//#include "colourconverters.h"
+//
+//void BodgeSmooth(ledstrip* pLedStrip)
+//{
+// pLedStrip->Clear();
+// pLedStrip->ShowLeds();
+//
+//
+// RgbColor startRGB(50,0,0);
+// HsvColor curHsv = RgbToHsv(startRGB);
+// while(1)
+// for (int k = 0; k < 1000; k++)
+// for (int j = 0; j < 255; j++)
+// {
+// pLedStrip->Clear();
+// RgbColor colrVal = HsvToRgb(curHsv);
+// pLedStrip->Fill(0,pLedStrip->GetNumLeds(),colrVal.r, colrVal.g, colrVal.b);
+// pLedStrip->ShowLeds();
+// wait_ms(250);
+// curHsv.h++;
+// }
+//}
+//
+//void setLightsConfig()
+//{
+// printf("Rob LightWall - Configured for ");
+// // Check for a config file on the local file system
+// strcpy(nameOfLights, "Spidey");
+// LocalFileSystem local("local");
+// FILE* fp = fopen("/local/spidey.cnf", "r");
+// if (fp != NULL)
+// {
+// char buf[201];
+// buf[sizeof(buf)-1] = 0;
+// int nread = fread(buf, 1, sizeof(buf), fp);
+// if (nread > 0 && nread <= sizeof(buf))
+// {
+// buf[nread] = 0;
+// sscanf(buf, "%s %d %d", nameOfLights, &ledsCount, &ledSplitPoint);
+// }
+// fclose(fp);
+// printf("%s (%d LEDs, Split at %d)", nameOfLights, ledsCount, ledSplitPoint);
+// printf("\n\r");
+// }
+//
+// // Leds setup
+// pLedStrip = new ledstrip(ledsCount, ledSplitPoint);
+// wait_ms(100);
+// pLedStrip->Clear();
+// pLedStrip->ShowLeds();
+//
+// // Cmd handler
+// pLedCmdHandler = new LedCmdHandler(pLedStrip);
+//}
+//
+//int main (void)
+//{
+// pc.baud(115200);
+//
+// setLightsConfig();
+//
+// BodgeSmooth(pLedStrip);
+//
+// ledTick.attach(&ledTickfunc,TICK_MS / 1000.0);
+//
+//// reRunLastCommand();
+//
+// // setup ethernet interface
+// eth.init(); //Use DHCP
+// eth.connect();
+// printf("IP Address is %s\n\r", eth.getIPAddress());
+//
+// webServer.addCommand("", RdWebServerCmdDef::CMD_LOCALFILE, NULL, indexHtmName, true);
+// webServer.addCommand("cmd", RdWebServerCmdDef::CMD_CALLBACK, &handleCmd_ledControl);
+// webServer.init(PORT, &led2);
+// webServer.run();
+//}
-char nameOfLights[50];
-int ledsCount = 904;
-int ledSplitPoint = 448;
-ledstrip* pLedStrip = NULL;
-
-char* indexHtmName = "index.htm";
-
-const int TICK_MS = 100;
-LedCmdHandler* pLedCmdHandler = NULL;
-int blinkCtr = 0;
-
-void ledTickfunc()
+// Handle a command
+char* lightwallCmd(int method, char* cmdStr, char* argStr, char* msgBuf)
{
- if(webServer.isListening())
+ int cmdLen = RdWebServer::getPayloadLengthFromMsg(msgBuf);
+ unsigned char* cmdBuf = RdWebServer::getPayloadDataFromMsg(msgBuf);
+ pc.printf("Command Payload Len %d\r\n", cmdLen);
+ if (cmdLen == 256)
{
- blinkCtr++;
- if (blinkCtr > 1)
- {
- led1 = !led1;
- blinkCtr = 0;
- }
- }
- else
- {
- led1 = false;
+ for (int i = 0; i < cmdLen; i++)
+ if (cmdBuf[i] != i)
+ {
+ printf("Binary content err at %d\r\n", i);
+ break;
+ }
}
-
- if (pLedCmdHandler != NULL)
- pLedCmdHandler->NextGen();
-}
-
-void handleCmd_ledControl(char* cmdStr, char* argStr)
-{
- printf("LEDS COMMAND %s %s\r\n", cmdStr, argStr);
- if (argStr == NULL)
- return;
- pLedCmdHandler->DoCommand(argStr);
-
- // Store last command
- LocalFileSystem local("local");
- FILE* fp = fopen("/local/lastcmd.inf", "w");
- if (fp != NULL)
- {
- fwrite(argStr, 1, strlen(argStr)+1, fp);
- fclose(fp);
- }
+ char* respStr = "";
+ respStr = drawingManager.start(cmdBuf, cmdLen);
+ return respStr;
}
-void reRunLastCommand()
+// Create, configure and run the web server
+void http_thread(void const* arg)
{
- // Store last command
- LocalFileSystem local("local");
- FILE* fp = fopen("/local/lastcmd.inf", "r");
- if (fp != NULL)
- {
- char buf[501];
- buf[sizeof(buf)-1] = 0;
- int nread = fread(buf, 1, sizeof(buf), fp);
- fclose(fp);
- if (nread > 0 && nread <= sizeof(buf))
- {
- buf[nread] = 0;
- pLedCmdHandler->DoCommand(buf);
- }
- }
-}
-
-#include "colourconverters.h"
-
-void BodgeSmooth(ledstrip* pLedStrip)
-{
- pLedStrip->Clear();
- pLedStrip->ShowLeds();
-
-
- RgbColor startRGB(50,0,0);
- HsvColor curHsv = RgbToHsv(startRGB);
- while(1)
- for (int k = 0; k < 1000; k++)
- for (int j = 0; j < 255; j++)
- {
- pLedStrip->Clear();
- RgbColor colrVal = HsvToRgb(curHsv);
- pLedStrip->Fill(0,pLedStrip->GetNumLeds(),colrVal.r, colrVal.g, colrVal.b);
- pLedStrip->ShowLeds();
- wait_ms(250);
- curHsv.h++;
- }
+ pc.printf("Starting web server\r\n");
+ char* baseWebFolder = "/sd/"; // should be /sd/ for SDcard files - not used for local file system
+ RdWebServer webServer;
+ webServer.addCommand("", RdWebServerCmdDef::CMD_LOCALFILE, NULL, "index.htm", true);
+ webServer.addCommand("favicon.ico", RdWebServerCmdDef::CMD_LOCALFILE, NULL, NULL, true);
+ webServer.addCommand("cmd", RdWebServerCmdDef::CMD_CALLBACK, &lightwallCmd);
+ webServer.init(WEBPORT, &led4, baseWebFolder);
+ webServer.run();
}
-void setLightsConfig()
+int main()
{
- printf("Rob LightWall - Configured for ");
- // Check for a config file on the local file system
- strcpy(nameOfLights, "Spidey");
- LocalFileSystem local("local");
- FILE* fp = fopen("/local/spidey.cnf", "r");
- if (fp != NULL)
- {
- char buf[201];
- buf[sizeof(buf)-1] = 0;
- int nread = fread(buf, 1, sizeof(buf), fp);
- if (nread > 0 && nread <= sizeof(buf))
- {
- buf[nread] = 0;
- sscanf(buf, "%s %d %d", nameOfLights, &ledsCount, &ledSplitPoint);
- }
- fclose(fp);
- printf("%s (%d LEDs, Split at %d)", nameOfLights, ledsCount, ledSplitPoint);
- printf("\n\r");
- }
+ // Init
+ pc.baud(115200);
+ pc.printf("Light Wall - Rob Dobson 2015\r\n");
+
+ // Setup ethernet interface
+ char macAddr[6];
+ mbed_mac_address(macAddr);
+ 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]);
+ pc.printf("Connecting to ethernet ...\r\n");
+ EthernetInterface::init();
+ EthernetInterface::connect();
+ pc.printf("IP Address: %s\r\n", EthernetInterface::getIPAddress());
+
+ // Web Server
+ Thread httpServer(&http_thread, NULL, osPriorityNormal, (DEFAULT_STACK_SIZE * 4));
- // Leds setup
- pLedStrip = new ledstrip(ledsCount, ledSplitPoint);
- wait_ms(100);
- pLedStrip->Clear();
- pLedStrip->ShowLeds();
-
- // Cmd handler
- pLedCmdHandler = new LedCmdHandler(pLedStrip);
-}
+ // Home
+ drawingManager.init();
-int main (void)
-{
- pc.baud(115200);
-
- setLightsConfig();
-
- BodgeSmooth(pLedStrip);
-
- ledTick.attach(&ledTickfunc,TICK_MS / 1000.0);
-
-// reRunLastCommand();
-
- // setup ethernet interface
- eth.init(); //Use DHCP
- eth.connect();
- printf("IP Address is %s\n\r", eth.getIPAddress());
-
- webServer.addCommand("", RdWebServerCmdDef::CMD_LOCALFILE, NULL, indexHtmName, true);
- webServer.addCommand("cmd", RdWebServerCmdDef::CMD_CALLBACK, &handleCmd_ledControl);
- webServer.init(PORT, &led2);
- webServer.run();
+ while(true)
+ {
+// led1=!led1;
+ // Service drawing manager
+ drawingManager.service();
+// Thread::wait(500);
+ }
}