WIP: accept flaschentaschen protocol

master
informatic 2019-04-07 14:39:04 +02:00
parent dbe39193a7
commit f19441985e
1 changed files with 138 additions and 29 deletions

View File

@ -8,7 +8,7 @@ extern "C" {
#include "ws2812_i2s.h"
}
#define LEDS_CNT 150
#define LEDS_CNT 20
enum LEDMode {
IDLE,
@ -17,17 +17,35 @@ enum LEDMode {
STROBE,
BRIGHT,
TEST,
REMOTE,
};
typedef struct __attribute__((packed)) {
uint8_t r;
uint8_t g;
uint8_t b;
} led_t;
class LEDEndpoint;
class FlaschenTaschenHandler {
public:
void init(LEDEndpoint* _ep) {
ep = _ep;
socket = new UdpConnection(UdpConnectionDataDelegate(&FlaschenTaschenHandler::onReceive, this));
socket->listen(1337);
}
protected:
LEDEndpoint* ep;
UdpConnection* socket;
void onReceive(UdpConnection& connection, char* data, int size, IPAddress remoteIP, uint16_t remotePort);
};
class LEDEndpoint : public Endpoint {
private:
struct __attribute__((packed)) {
uint8_t g;
uint8_t r;
uint8_t b;
} leds[LEDS_CNT];
enum LEDMode currentMode = LEDMode::IDLE;
led_t leds[LEDS_CNT];
Timer animationTimer;
void animate() {
@ -36,6 +54,11 @@ private:
static int frameCounter = 0;
frameCounter++;
if (overrideTime && millis() - overrideTime > 5000) {
overrideTime = 0;
currentMode = LEDMode::IDLE;
}
for(int i = 0; i < LEDS_CNT; i++) {
switch(currentMode) {
case LEDMode::IDLE:
@ -68,37 +91,123 @@ private:
ws2812_push((uint8_t*) leds, sizeof(leds));
}
FlaschenTaschenHandler ft;
public:
LEDEndpoint() : Endpoint("leds", {
{"mode", "enum", true, "idle,off,white,strobe,bright,test", "Current LED mode"},
}) {
animationTimer.initializeMs(50, TimerDelegate(&LEDEndpoint::animate, this)).start();
ws2812_init();
}
int crateWidth = 5;
int crateHeight = 4;
EndpointResult onValue(String property, String value) {
if (property != "mode") {
return 400;
enum LEDMode currentMode = LEDMode::IDLE;
long overrideTime = 0;
LEDEndpoint();
EndpointResult onValue(String property, String value);
void set(uint8_t x, uint8_t y, uint8_t r, uint8_t g, uint8_t b) {
int k;
if (y % 2 == 1) {
k = (y+1)*crateWidth - x - 1;
} else {
k = y*crateWidth + x;
}
if (value == "idle") currentMode = LEDMode::IDLE;
else if (value == "off") currentMode = LEDMode::OFF;
else if (value == "white") currentMode = LEDMode::WHITE;
else if (value == "strobe") currentMode = LEDMode::STROBE;
else if (value == "bright") currentMode = LEDMode::BRIGHT;
else if (value == "test") currentMode = LEDMode::TEST;
else {
return 400;
}
notify("mode", value);
return 200;
leds[k].r = r;
leds[k].g = g;
leds[k].b = b;
}
};
LEDEndpoint::LEDEndpoint() : Endpoint("leds", {
{"mode", "enum", true, "idle,off,white,strobe,bright,test", "Current LED mode"},
}) {
animationTimer.initializeMs(50, TimerDelegate(&LEDEndpoint::animate, this)).start();
ft.init(this);
ws2812_init();
}
EndpointResult LEDEndpoint::onValue(String property, String value) {
if (property != "mode") {
return 400;
}
if (value == "idle") currentMode = LEDMode::IDLE;
else if (value == "off") currentMode = LEDMode::OFF;
else if (value == "white") currentMode = LEDMode::WHITE;
else if (value == "strobe") currentMode = LEDMode::STROBE;
else if (value == "bright") currentMode = LEDMode::BRIGHT;
else if (value == "test") currentMode = LEDMode::TEST;
else {
return 400;
}
notify("mode", value);
return 200;
}
SpejsNode node("ledcontroller");
#define debug(s) node.notify("$debug", s)
void FlaschenTaschenHandler::onReceive(UdpConnection& connection, char* data, int size, IPAddress remoteIP, uint16_t remotePort) {
ep->currentMode = LEDMode::REMOTE;
ep->overrideTime = millis();
int bufW, bufH;
int bufleft = size;
int linecnt = 0;
char* linestart = data;
char* lineend;
while (linecnt < 3 && bufleft > 0) {
lineend = (char*) memchr(linestart, '\n', bufleft);
String line = String(linestart, lineend-linestart);
if (linecnt == 0 && !line.equals("P6")) {
// invalid frame
ep->currentMode = LEDMode::WHITE;
return;
} else if (line.startsWith("#")) {
// comment
} else {
if (linecnt == 1) {
// buffer size
bufW = line.substring(0, line.indexOf(" ")).toInt();
bufH = line.substring(line.indexOf(" ")).toInt();
} else if (linecnt == 2) {
if (!line.equals("255")) {
// this should be 255 ;_;
ep->currentMode = LEDMode::STROBE;
return;
}
}
linecnt++;
}
bufleft -= lineend-linestart+1;
linestart = lineend+1;
}
if (bufW*bufH*3 > bufleft) {
ep->currentMode = LEDMode::STROBE;
return;
}
for (int x = 0; x < bufW; x++) {
for (int y = 0; y < bufH; y++) {
int b = (y*bufW + x) * 3;
ep->set(x, y, linestart[b], linestart[b+1], linestart[b+2]);
}
}
//debug(String(bufW));
//debug(String(bufH));
//debug(String());
//debug(String(bufleft));
//node.notify("$debug", String(linestart, lineend-linestart));
}
void init()
{
node.init();