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/
Revision 4:b521815f2657, committed 2015-08-31
- Comitter:
- Bobty
- Date:
- Mon Aug 31 15:21:47 2015 +0000
- Parent:
- 3:e5ea80fae61d
- Child:
- 5:910909f34907
- Commit message:
- Tidied up and removed unnecessary code
Changed in this revision
--- a/DrawingManager.cpp Mon Aug 31 09:03:15 2015 +0000
+++ b/DrawingManager.cpp Mon Aug 31 15:21:47 2015 +0000
@@ -1,5 +1,5 @@
//
-// Drawing Manager for Pancake Drawbot
+// Drawing Manager for LightWall
// Rob Dobson 2015
//
@@ -12,7 +12,7 @@
isBusy = false;
}
-void DrawingManager::init(int numLeds, int splitPoint)
+void DrawingManager::Init(int numLeds, int splitPoint)
{
pLedStrip = new ledstrip(numLeds, splitPoint);
Thread::wait(100);
@@ -21,18 +21,58 @@
}
-char* DrawingManager::start(const unsigned char* cmdBuf, int cmdLen)
+void DrawingManager::Clear()
+{
+// printf("CLEAR\r\n");
+ if (pLedStrip)
+ pLedStrip->Clear();
+}
+
+void DrawingManager::RawFill(char* args, unsigned char* payload, int payloadLen, int payloadOffset)
{
- if (!pLedStrip)
- return "NOINIT";
- if (isBusy)
- return "BUSY";
- isBusy = true;
- char* respStr = cmdmsg::Interpret(cmdBuf, cmdLen, pLedStrip);
- isBusy = false;
- return respStr;
+// printf("RAWFILL %s payloadLen %d, payloadOffset %d\r\n", args, payloadLen, payloadOffset);
+ int startLed = GetIntFromNameValPair(args, "start=", -1);
+ if (startLed != -1 && payloadLen > 0)
+ {
+ int numLeds = payloadLen / 3;
+ int fromLed = startLed + (payloadOffset / 3);
+// printf("RAWFILL fromLed %d numLeds %d\r\n", fromLed, numLeds);
+ pLedStrip->RawFill(fromLed, numLeds, payload);
+ }
}
-void DrawingManager::service()
+void DrawingManager::Fill(char* args)
{
+// printf("FILL %s\r\n", args);
+ int startLed = GetIntFromNameValPair(args, "start=", -1);
+ int numLeds = GetIntFromNameValPair(args, "len=", -1);
+ int r1 = GetIntFromNameValPair(args, "r1=", -1);
+ int g1 = GetIntFromNameValPair(args, "g1=", -1);
+ int b1 = GetIntFromNameValPair(args, "b1=", -1);
+ int r2 = GetIntFromNameValPair(args, "r2=", -1);
+ int g2 = GetIntFromNameValPair(args, "g2=", -1);
+ int b2 = GetIntFromNameValPair(args, "b2=", -1);
+ if (startLed != -1 && numLeds != -1 && r1 != -1 && g1 != -1 && b1 != -1)
+ {
+ if (r2 == -1 || g2 == -1 || b2 == -1)
+ pLedStrip->Fill(startLed, numLeds, r1, g1, b1);
+ else
+ pLedStrip->Fill(startLed, numLeds, r1, g1, b1, r2, g2, b2);
+ }
}
+
+void DrawingManager::ShowLeds()
+{
+// printf("SHOWLEDS\r\n");
+ if (pLedStrip)
+ pLedStrip->ShowLeds();
+}
+
+int DrawingManager::GetIntFromNameValPair(char* buf, char* name, int invalidVal)
+{
+ int val = invalidVal;
+ char* pFnd = strstr(buf, name);
+ if (pFnd)
+ val = atoi(pFnd + strlen(name));
+ return val;
+}
--- a/DrawingManager.h Mon Aug 31 09:03:15 2015 +0000
+++ b/DrawingManager.h Mon Aug 31 15:21:47 2015 +0000
@@ -1,21 +1,29 @@
#ifndef DRAWING_MANAGER
#define DRAWING_MANAGER
+//
+// Drawing Manager for LightWall
+// Rob Dobson 2015
+//
+
#include "mbed.h"
#include "ledstrip.h"
-#include "cmdmsg.h"
class DrawingManager
{
public:
DrawingManager();
- void init(int numLeds, int splitPoint);
- void service();
- char* start(const unsigned char* cmdBuf, int cmdLen);
+ void Init(int numLeds, int splitPoint);
+ void Clear();
+ void RawFill(char* args, unsigned char* payload, int payloadLen, int payloadOffset);
+ void Fill(char* args);
+ void ShowLeds();
+
private:
ledstrip* pLedStrip;
bool isBusy;
+ int GetIntFromNameValPair(char* buf, char* name, int invalidVal);
};
#endif
--- a/EthernetInterface.lib Mon Aug 31 09:03:15 2015 +0000 +++ b/EthernetInterface.lib Mon Aug 31 15:21:47 2015 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/mbed_official/code/EthernetInterface/#8e692841213c +https://developer.mbed.org/users/Bobty/code/EthernetInterfacePlusHostname/#8e692841213c
--- a/RdWebServer.lib Mon Aug 31 09:03:15 2015 +0000 +++ b/RdWebServer.lib Mon Aug 31 15:21:47 2015 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/Bobty/code/RdWebServer/#0fc3d7b5e596 +http://mbed.org/users/Bobty/code/RdWebServer/#27800de38eab
--- a/cmdmsg.cpp Mon Aug 31 09:03:15 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,361 +0,0 @@
-#include "mbed.h"
-#include "cmdmsg.h"
-#include "ledstrip.h"
-//#define DETECT_LEDS
-#ifdef DETECT_LEDS
-#include "detectled.h"
-#endif
-//#define USE_SPIDEY_GEOM
-#ifdef USE_SPIDEY_GEOM
-#include "spideyGeometry.h"
-#endif
-/*
-
-Message format is:
- <SEQ><CMD><CMD><CMD> ... <ZERO>
-
-Where:
- <SEQ> is a two byte sequence count
- <CMD> is a series of bytes as follows:
- <LEN><COD><PARAMS>
-
-Where:
- <LEN> is a two byte with value 1..65535 depicting msg len
- <COD> is a one byte command code - see below
- <PARAMS> are a series of bytes containing the parameters for the command
-
-<COD> values:
-
- NOTE MSB of COD is used to indicate that no response is required on success
- i.e. if MSB of COD is 1 then no response is required on success
-
- (COD & 0x7f) ....
- 0x01:
- Clear the entire strip
- There are no parameters
- 0x02:
- Fill a series of leds with RGB values
- <PARAMS> := <START><NUM><RGB1><RGB2>
- Where:
- <START> is a two byte value (bigendian) for led to start series
- <NUM> is a two byte (bigendian) number of leds to set
- <RGB1> is the starting RGB value (24bits)
- <RGB2> is the ending RGB value (24bits) - OPTIONAL
- The RGB2 value is optional - the LEN value determines whether it is present or not
- - if present the colour values are interpolated (HSV) between RGB1 and RGB2
- - if not present all leds are set to colour RGB1
- 0x03:
- Detect LED with opto-sensor (put opto-sensor on LED and run command)
- Sensor must be attached to p20 - currently using BPX65 with 470K pullup
- Returns string with LED number
- 0x04:
- Set number of leds and split point
- <PARAMS> := <NUMLEDS><SPLITPOINT>
- Where:
- <NUMLEDS> is a two byte (bigendian) value for number of leds in strip
- <SPLITPOINT> is a two byte (bigendian) value for point at which DigitalOut(p10) is used instead of p12 for data
- (this is because the spidey wall is two parallel chains of LEDS)
- 0x05:
- Raw RGB values for a series of leds
- <PARAMS> := <START><NUM><RGB1><RGB2><RGB2>....<RGBn>
- Where:
- <START> is a two byte value (bigendian) for led to start series
- <NUM> is a two byte (bigendian) number of leds to set
- <RGB1> is the RGB value for 1st LED (24bits)
- <RGB2> is the RGB value for 2nd LED (24bits)
- <RGBn> is the RGB value for nth LED (24bits)
- 0x06:
- Set colour for leds on a pad
- <PARAMS> := <PAD><RGB1><RGB2>
- Where:
- <PAD> is the pad number (1 byte)
- <RGB1> is the starting RGB value (24bits)
- <RGB2> is the ending RGB value (24bits) - OPTIONAL
- The RGB2 value is optional - the LEN value determines whether it is present or not
- - if present the colour values are interpolated (HSV) between RGB1 and RGB2
- - if not present all leds are set to colour RGB1
- 0x07:
- Set node and link info
- <PARAMS> := <NODE><NODEFLAGS><NODERGB><LINKIDX><LINKLEDSTART><LINKNUMLEDS><LINKRGB>
- Where:
- <NODE> is the node number (1 byte)
- <NODEFLAGS> LSB is 0 if the RGB value for the node is not to be changed, or 1 otherwise (1 byte)
- <NODERGB> is the RBG value for the leds in the node itself (3 bytes)
- <LINKIDX> is the index of the link (edge) from this node to control (1 byte)
- <LINKLEDSTART> is the LED along the link to start controlling (1 byte)
- <LINKNUMLEDS> is the number of LEDs to control (1 byte)
- <LINKRGB> is the colour to make the link LEDs (3 bytes)
-
- 0x08:
- Raw HSV values for a series of leds
- <PARAMS> := <START><NUM><HSV1><HSV2><HSV3>....<HSVn>
- Where:
- <START> is a two byte value (bigendian) for led to start series
- <NUM> is a two byte (bigendian) number of leds to set
- <HSV1> is the RGB value for 1st LED (16bits) - first 8 bits = H, upper 4 (bigendian) = S / 16, lower 4 = V / 16
- <HSV2> is the RGB value for 2nd LED
- <HSVn> is the RGB value for nth LED
-
- 0x09:
- ShowLeds
- Until this command is sent all other commands simply "paint" into the buffer and don't actually change the LEDs
- There are no parameters
-
-*/
-
-#ifdef USE_SPIDEY_GEOM
-int cmdmsg::getLedNumFromSeq(const int* edgeLeds, int numLedsInSeq, int seqIdx)
-{
- if (seqIdx >= numLedsInSeq)
- return -1;
- int curSeqPos = 0;
- bool reverseSeq = false;
- for (int i = 0; i < MAX_SPIDEY_LINK_ELS/2; i++)
- {
- int startLedIdx = edgeLeds[i * 2];
- int endLedIdx = edgeLeds[i * 2 + 1];
- int nLeds = endLedIdx - startLedIdx + 1;
- if (startLedIdx > endLedIdx)
- {
- reverseSeq = true;
- nLeds = startLedIdx - endLedIdx + 1;
- }
- if (seqIdx - curSeqPos < nLeds)
- {
- if (reverseSeq)
- return startLedIdx - seqIdx;
- return startLedIdx + seqIdx;
- }
- curSeqPos = nLeds;
- }
- return -1;
-}
-#endif
-
-char* cmdmsg::Interpret(const unsigned char* msg, int msgLen, ledstrip* pLedStrip)
-{
- // Get message details
- static char responseStr[50];
- unsigned char* ledStrip = pLedStrip->GetBuffer();
- int nBytesLeft = msgLen - 2;
- int seqCount = (msg[0] * 256) + msg[1];
- msg += 2;
- while (nBytesLeft > 0)
- {
- // Length of chunk
- int chunkLen = (msg[0] * 256) + msg[1];
- if (chunkLen == 0)
- break;
-
- // Params length
- int paramsLen = chunkLen - 1;
-// printf("Chunklen = %d, Paramslen = %d\r\n", chunkLen, paramsLen);
-
- // Command and whether response required on success
- int cmdCode = msg[2];
- if ((cmdCode & 0x80) == 0)
- sprintf(responseStr, "%04x OK", seqCount);
- else
- strcpy(responseStr, "");
-
- // Move message pointer to assist in decoding the payload
- msg += 3;
- switch(cmdCode & 0x7f)
- {
- case 0x01: // Clear
- {
-// printf("Clear - nextbyte %d\r\n", msg[0]);
- pLedStrip->Clear();
- break;
- }
- case 0x02: // Fill
- {
-// printf("Fill\r\n");
-
- int startLed = (msg[0] * 256) + msg[1];
- int numLeds = (msg[2] * 256) + msg[3];
-// printf("F Q%04x S%d N%d Pa%d Ln%d\r\n", seqCount, startLed, numLeds, paramsLen, msgLen);
- if (paramsLen == 10) // RGB2 is provided
- {
- pLedStrip->Fill(startLed, numLeds, msg[4], msg[5], msg[6], msg[7], msg[8], msg[9]);
- } else if (paramsLen == 7) // only RGB1 - so solid colour fill
- {
- pLedStrip->Fill(startLed, numLeds, msg[4], msg[5], msg[6]);
- }
- break;
- }
- case 0x03: // Detect LED
- {
-#ifdef DETECT_LEDS
- detectled ledDetector(p20);
- int selectedLed = ledDetector.DetectSelectedLed(pLedStrip);
- sprintf(responseStr, "%02x OK LED %d", seqCount, selectedLed);
-#endif
- break;
- }
- case 0x04: // Set numleds and splitpoint
- {
-// printf("Set numleds and splitpoint\r\n");
-
- if (paramsLen == 4)
- {
- int numLeds = (msg[0] * 256) + msg[1];
- int splitPoint = (msg[2] * 256) + msg[3];
- pLedStrip->Resize(numLeds, splitPoint);
- }
- sprintf(responseStr, "%04x OK Resized", seqCount);
- break;
- }
- case 0x05: // Raw - set LEDs to RGB values from buffer
- {
- if (paramsLen > 4)
- {
- int startLed = (msg[0] * 256) + msg[1];
- int numLeds = (msg[2] * 256) + msg[3];
- if (paramsLen >= numLeds * 3 + 4)
- {
- pLedStrip->RawFill(startLed, numLeds, msg+4);
-// printf("R Q%04x S%d N%d Pa%d Ln%d\r\n", seqCount, startLed, numLeds, paramsLen, mMsgLen);
- }
- else
- {
- sprintf(responseStr, "%04x RAW FILL - BufLengthMismatch %d", seqCount, paramsLen);
- }
- }
- else
- {
- sprintf(responseStr, "%04x RAW FILL - ParamsLen Error %d", seqCount, paramsLen);
- }
- break;
- }
- case 0x06: // Set pad leds to a colour
- {
-#ifdef USE_SPIDEY_GEOM
- printf("Pad\r\n");
-
- if (paramsLen > 2)
- {
- int padIdx = msg[0];
- if (padIdx < sizeof(_spideyPads)/sizeof(SpideyPadInfo))
- {
- int firstLed = _spideyPads[padIdx].padLeds[0];
- int numLeds = _spideyPads[padIdx].padLeds[1] - _spideyPads[padIdx].padLeds[0] + 1;
- if (paramsLen == 4) // Only 1 RGB value
- pLedStrip->Fill(firstLed, numLeds, msg[1], msg[2], msg[3]);
- else if (paramsLen == 7) // Two RGB values
- pLedStrip->Fill(firstLed, numLeds, msg[1], msg[2], msg[3], msg[4], msg[5], msg[6]);
- }
- }
-#endif
- break;
- }
- case 0x07: // Control node
- {
-#ifdef USE_SPIDEY_GEOM
- printf("Node\r\n");
-
- if (paramsLen == 11)
- {
- int nodeIdx = msg[0];
- if (nodeIdx < sizeof(_spideyNodes)/sizeof(SpideyNodeInfo))
- {
- const SpideyNodeInfo& sni = _spideyNodes[nodeIdx];
-
- // Handle the node leds
- printf("Node %d leds %d colour %d,%d,%d ... ", nodeIdx, sni.numNodeLeds, msg[2], msg[3], msg[4]);
- bool setNodeRGB = ((msg[1] & 0x01) != 0);
- if (setNodeRGB)
- {
- for (int i = 0; (i < sni.numNodeLeds) && (i < MAX_SPIDEY_NODE_LEDS); i++)
- {
- pLedStrip->Fill(sni.nodeLeds[i], 1, msg[2], msg[3], msg[4]);
- printf("Led %d", sni.nodeLeds[i]);
- }
- }
- printf("\r\n");
-
- // Handle the link leds
- int linkIdx = msg[5];
- int linkLedStart = msg[6];
- int linkNumLeds = msg[7];
- printf("Link %d st %d num %d colour %d,%d,%d ... ", linkIdx, linkLedStart, linkNumLeds, msg[8], msg[9], msg[10]);
- if ((linkIdx < sni.numLinks) && (linkIdx < MAX_SPIDEY_NODE_LINKS))
- {
- const SpideyLinkInfo* pSli = sni.nodeLinks[linkIdx];
- for (int i = 0; i < linkNumLeds; i++)
- {
- int ledIdx = linkLedStart + i;
- int ledNumA = getLedNumFromSeq(pSli->edgeLedsA, pSli->edgeLengthA, ledIdx);
- if (ledNumA >= 0)
- {
- pLedStrip->Fill(ledNumA, 1, msg[8], msg[9], msg[10]);
- printf("A=%d/", ledNumA);
- }
- int ledNumB = getLedNumFromSeq(pSli->edgeLedsB, pSli->edgeLengthB, ledIdx);
- if (ledNumB >= 0)
- {
- pLedStrip->Fill(ledNumB, 1, msg[8], msg[9], msg[10]);
- printf("B=%d, ", ledNumB);
- }
- }
- }
- else
- {
- sprintf(responseStr, "%04x NODE - linkInvalid %d", seqCount, linkIdx);
- }
- printf("\r\n");
- }
- else
- {
- sprintf(responseStr, "%04x NODE - nodeInvalid %d", seqCount, nodeIdx);
- }
- }
- else
- {
- sprintf(responseStr, "%04x NODE - BufLengthMismatch %d", seqCount, paramsLen);
- }
-#endif
- break;
- }
- case 0x08: // Raw HSV
- {
- if (paramsLen > 4)
- {
- int startLed = (msg[0] * 256) + msg[1];
- int numLeds = (msg[2] * 256) + msg[3];
- if (paramsLen >= numLeds * 2 + 4)
- {
- pLedStrip->HsvFill(startLed, numLeds, msg+4);
-// printf("R Q%04x S%d N%d Pa%d\r\n", seqCount, startLed, numLeds, paramsLen);
- }
- else
- {
- sprintf(responseStr, "%04x HSV FILL - BufLengthMismatch %d", seqCount, paramsLen);
- }
- }
- else
- {
- sprintf(responseStr, "%04x HSV FILL - ParamsLen Error %d", seqCount, paramsLen);
- }
- break;
- }
- case 0x09: // ShowLeds
- {
-// printf("ShowLeds - nextbyte %d\r\n", msg[0]);
- pLedStrip->ShowLeds();
- break;
- }
- default:
- {
- sprintf(responseStr, "%04x CMD %02x UNKNOWN", seqCount, cmdCode);
- break;
- }
- }
-
- // Move to next chunk
- nBytesLeft = nBytesLeft - chunkLen - 2;
- msg += paramsLen;
-// printf("Bytesleft = %d, msg[0] = %d\r\n", nBytesLeft, msg[0]);
- }
- return responseStr;
-}
--- a/cmdmsg.h Mon Aug 31 09:03:15 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-
-class ledstrip;
-
-class cmdmsg
-{
- private:
-// static char responseStr[50];
-// unsigned char* mpMsgBuf;
-// int mMaxMsgLen;
-// int mMsgLen;
- int getLedNumFromSeq(const int* edgeLeds, int numLedsInSeq, int seqIdx);
-
- public:
- cmdmsg()
- {
-// mMsgLen = 0;
-// mMaxMsgLen = 5200;
-// mpMsgBuf = new unsigned char [mMaxMsgLen]();
-// responseStr[0] = 0;
- }
-
-// ~cmdmsg()
-// {
-// delete mpMsgBuf;
-// }
-//
-// char* GetBuffer()
-// {
-// return (char*)mpMsgBuf;
-// }
-// int GetMaxMsgLen()
-// {
-// return mMaxMsgLen;
-// }
-//
-// void SetMsgLen(int n)
-// {
-// mMsgLen = n;
-// }
-// char* Interpret(ledstrip* pLedStrip);
-//
- static char* Interpret(const unsigned char* msgBuf, int msgLen, ledstrip* pLedStrip);
-};
-
--- a/ledstrip.cpp Mon Aug 31 09:03:15 2015 +0000 +++ b/ledstrip.cpp Mon Aug 31 15:21:47 2015 +0000 @@ -1,3 +1,4 @@ + // LED Strip using WS2801 with two ISRs for two SPI connected // LED strips running in parallel // Rob Dobson 2013-2014
--- a/ledstrip.h Mon Aug 31 09:03:15 2015 +0000 +++ b/ledstrip.h Mon Aug 31 15:21:47 2015 +0000 @@ -1,6 +1,10 @@ #ifndef LEDSTRIP__H #define LEDSTRIP__H +// LED Strip using WS2801 with two ISRs for two SPI connected +// LED strips running in parallel +// Rob Dobson 2013-2014 + #include "mbed.h" class ledstrip
--- a/main.cpp Mon Aug 31 09:03:15 2015 +0000
+++ b/main.cpp Mon Aug 31 15:21:47 2015 +0000
@@ -1,7 +1,10 @@
//
// LightWall WebServer
//
-// Rob Dobson 2015
+// Rob Dobson (C) 2015
+//
+// See http://robdobson.com/2015/07/spidey-wall/ and http://robdobson.com/2015/08/a-reliable-mbed-webserver/
+//
#include "mbed.h"
#include "EthernetInterface.h"
@@ -27,180 +30,57 @@
// Drawing Manager
DrawingManager drawingManager;
-//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);
-//}
+// General response string for REST requests
+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";
-//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();
-//}
-
-// Handle a command
-char* lightwallCmd(int method, char* cmdStr, char* argStr, char* msgBuf)
-{
- // Blink LED
- led1 = !led1;
-
- // Get message payload
- int cmdLen = RdWebServer::getPayloadLengthFromMsg(msgBuf);
- unsigned char* cmdBuf = RdWebServer::getPayloadDataFromMsg(msgBuf);
-
- // Check if the command length is 0 - in this case respond ok as it might be a
- // pre-flight check on a Cross Domain request - https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
- char* respStr = "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";
- if (cmdLen != 0)
- {
- // Process command
- drawingManager.start(cmdBuf, cmdLen);
- }
- return respStr;
-}
-
-// Get system name
-char* lightwallGetSystemName(int method, char* cmdStr, char* argStr, char* msgBuf)
+// Get system name - No arguments required
+char* lightwallGetSystemName(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen,
+ int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
{
// Return the system name
return systemName;
}
+// Clear LEDS - No arguments required
+char* lightwallClear(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen,
+ int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
+{
+ drawingManager.Clear();
+ return generalRespStr;
+}
+
+// RawFill - arguments for start LED (e.g. /rawfill?start=0)
+// - payload of message contains binary data for RGB (1 byte for each) for each LED to be set
+char* lightwallRawFill(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen,
+ int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
+{
+ drawingManager.RawFill(argStr, pPayload, payloadLen, splitPayloadPos);
+ return generalRespStr;
+}
+
+// Fill - arguments for start, numLeds, initial-R/G/B and ending-R/G/B (optional)
+// - e.g. /fill?start=0&len=100&r1=20&g1=30&b1=50
+// - e.g. /fill?start=0&len=100&r1=20&g1=30&b1=50&r2=50&g2=100&b2=23
+char* lightwallFill(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen,
+ int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
+{
+ drawingManager.Fill(argStr);
+ return generalRespStr;
+}
+
+// ShowLeds - no arguments
+char* lightwallShowLeds(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen,
+ int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
+{
+ // Blink LED
+ led1 = !led1;
+ // Show LEDS
+ drawingManager.ShowLeds();
+ return generalRespStr;
+}
+
// Create, configure and run the web server
-void http_thread(void const* arg)
+void http_server(void const* arg)
{
// Init the web server
pc.printf("Starting web server\r\n");
@@ -212,8 +92,11 @@
webServer.addCommand("favicon.ico", RdWebServerCmdDef::CMD_LOCALFILE, NULL, NULL, true);
// Add the lightwall control commands
- webServer.addCommand("cmd", RdWebServerCmdDef::CMD_CALLBACK, &lightwallCmd);
webServer.addCommand("name", RdWebServerCmdDef::CMD_CALLBACK, &lightwallGetSystemName);
+ webServer.addCommand("clear", RdWebServerCmdDef::CMD_CALLBACK, &lightwallClear);
+ webServer.addCommand("rawfill", RdWebServerCmdDef::CMD_CALLBACK, &lightwallRawFill);
+ webServer.addCommand("fill", RdWebServerCmdDef::CMD_CALLBACK, &lightwallFill);
+ webServer.addCommand("showleds", RdWebServerCmdDef::CMD_CALLBACK, &lightwallShowLeds);
// Start the server
webServer.init(WEBPORT, &led4, baseWebFolder);
@@ -253,7 +136,7 @@
getSystemConfig();
// Drawing manager controls the LEDs
- drawingManager.init(systemNumLEDS, systemLEDSSplitPoint);
+ drawingManager.Init(systemNumLEDS, systemLEDSSplitPoint);
// Setup ethernet interface
char macAddr[6];
@@ -276,8 +159,8 @@
// http://robdobson.com/2015/08/a-reliable-mbed-webserver/
// Fortunately it doesn't matter as the LED code is all interrupt driven
// This is the previous code...
- // Thread httpServer(&http_thread, NULL, osPriorityNormal, (DEFAULT_STACK_SIZE * 3));
- http_thread("");
+ // Thread httpServer(&http_server, NULL, osPriorityNormal, (DEFAULT_STACK_SIZE * 3));
+ http_server("");
// Forever - actually it won't even get here as the server has a forever loop in it too
while(true)