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)