Compare commits

..

9 Commits

24 changed files with 147 additions and 46 deletions

3
data/config.json Normal file
View File

@ -0,0 +1,3 @@
{
"version": 3
}

View File

@ -0,0 +1,18 @@
{
"version": 1,
"strides": [
{"x": 0, "y": 6, "pixels": 6},
{"x": 1, "y": 6, "pixels": 6},
{"x": 2, "y": 6, "pixels": 6},
{"x": 3, "y": 4, "pixels": 9},
{"x": 4, "y": 4, "pixels": 14},
{"x": 5, "y": 0, "pixels": 17},
{"x": 6, "y": 2, "pixels": 12},
{"x": 7, "y": 0, "pixels": 18},
{"x": 8, "y": 4, "pixels": 14},
{"x": 9, "y": 5, "pixels": 9},
{"x": 10, "y": 4, "pixels": 7},
{"x": 11, "y": 5, "pixels": 6},
{"x": 12, "y": 5, "pixels": 6}
]
}

6
data/maps/default.json Normal file
View File

@ -0,0 +1,6 @@
{
"version": 1,
"strides": [
{"x": 0, "y": 0, "pixels": 255}
]
}

View File

@ -0,0 +1,16 @@
{
"version": 1,
"tasks": [
"Renderer",
"SerialInput",
"BPM",
"Bluetooth"
],
"scenes": {
"Idle": ["Solid", "MPU5060", "Pulse", "IdleColors", "CircadianRhythm"],
"Acid": ["Chimes", "Pulse", "MPU5060", "IdleColors", "Rainbow"],
"Flashlight": ["Flashlight"]
},
"surfaceMap": "cyberplague"
}

View File

@ -0,0 +1,15 @@
{
"version": 1,
"tasks": [
"Renderer",
"MQTT",
"WiFi",
"ArduinoOTA",
"UpdateStatusAnimation"
],
"scenes": {
"Idle": ["Solid", "MPU5060", "Pulse", "IdleColors", "CircadianRhythm"],
"Flashlight": ["Flashlight"]
}
"surfaceMap": "default"
}

View File

@ -0,0 +1,17 @@
{
"version": 1,
"tasks": [
"Bluetooth",
"Renderer",
"WiFi",
"MQTT",
"ArduinoOTA",
"UpdateStatusAnimation"
],
"scenes": {
"Idle": ["Solid", "MPU5060", "Pulse", "IdleColors", "CircadianRhythm"],
"Acid": ["Chimes", "Pulse", "MPU5060", "IdleColors", "Rainbow"],
"Flashlight": ["Flashlight"]
}
"surfaceMap": "default"
}

View File

@ -22,16 +22,14 @@ struct Task : public virtual Loopable {
};
Task() {}
explicit Task(State initialState) : Task(0, initialState) {}
explicit Task(const char* name) : Task(name, Running) {}
Task(const char* name, State initialState) : name(name), state(initialState) {}
explicit Task(const char* name) : name(name) {}
void start() { state = Running; onStart(); }
void stop() { onStop(); state = Stopped; }
virtual bool isFigment() const { return false; }
const char* name = "";
State state = Running;
State state = Stopped;
};
struct TaskFunc: public Task {
@ -42,9 +40,7 @@ struct TaskFunc: public Task {
struct Figment: public Task {
Figment() : Task() {}
explicit Figment(State initialState) : Task(initialState) {}
explicit Figment(const char* name) : Task(name) {}
Figment(const char* name, State initialState) : Task(name, initialState) {}
virtual void render(Display* dpy) const = 0;
bool isFigment() const override { return true; }
};

View File

@ -114,8 +114,6 @@ class InputSource: public Task {
public:
InputSource() : Task() {init();}
explicit InputSource(const char* name) : Task(name) {init();}
explicit InputSource(Task::State initialState) : Task(initialState) {init();}
InputSource(const char* name, Task::State initialState) : Task(name, initialState) {init();}
void loop() override;
void onStart() override;
virtual InputEvent read() = 0;
@ -134,7 +132,6 @@ class InputFunc : public InputSource {
public:
InputFunc(std::function<InputEvent(void)> f) : InputSource(), m_func(f) {}
InputFunc(std::function<InputEvent(void)> f, const char* name) : InputSource(name), m_func(f) {}
InputFunc(std::function<InputEvent(void)> f, const char* name, Task::State initialState) : InputSource(name, initialState), m_func(f) {}
InputEvent read() override {
return m_func();

View File

@ -30,7 +30,7 @@ private:
// Particle. This allows for multiple devices with wildly different displays to
// run the same code
struct ConfigService: public Task {
ConfigService() : Task("Configuration") {}
ConfigService() : Task("Configuration") {state = Task::Running;}
void onStart();
void loop() override;
void handleEvent(const InputEvent &evt) override;

View File

@ -2,7 +2,7 @@
class LogService : public Task {
public:
LogService() : Task("Logging") {}
LogService() : Task("Logging") {state = Task::Running;}
void handleEvent(const InputEvent& event) override;
void loop() override {}

View File

@ -96,6 +96,7 @@ Platform::preSetup()
#else
#ifdef CONFIG_MQTT
Log.begin(LOG_LEVEL_TRACE, Static<MQTTTelemetry>::instance()->logPrinter());
Static<MQTTTelemetry>::instance()->setSequencer(Static<Sequencer>::instance());
#else
Log.begin(LOG_LEVEL_TRACE, &Serial);
#endif

View File

@ -7,7 +7,7 @@ class Platform : public Task {
static int s_timezone;
static char s_deviceID[15];
public:
Platform() : Task("Platform") {}
Platform() : Task("Platform") {state = Task::Running;}
static BootOptions bootopts;
static void setTimezone(int tz) { s_timezone = tz; }
static int getTimezone() { return s_timezone; }

View File

@ -6,6 +6,7 @@ Sequencer::Sequencer() :
Task("SceneSequencer"),
m_idx(0)
{
state = Task::Running;
}
void

View File

@ -1,7 +1,7 @@
#include "Chimes.h"
#include "../Static.h"
ChimesAnimation::ChimesAnimation() : Figment("Chimes", Task::Stopped) {
ChimesAnimation::ChimesAnimation() : Figment("Chimes") {
}
void ChimesAnimation::randomize() {

View File

@ -1,7 +1,7 @@
#include "Drain.h"
#include "../Static.h"
DrainAnimation::DrainAnimation() : Figment("Drain", Task::Stopped) {}
DrainAnimation::DrainAnimation() : Figment("Drain") {}
void DrainAnimation::loop() {
EVERY_N_MILLISECONDS(8) {

View File

@ -1,7 +1,7 @@
#include "Flashlight.h"
#include "../Static.h"
Flashlight::Flashlight() : Figment("Flashlight", Task::Stopped) {
Flashlight::Flashlight() : Figment("Flashlight") {
m_blobs.forEach([](Blob &blob) {
blob.setHue(random(255));
blob.setSaturation(10);

View File

@ -4,7 +4,7 @@
template<uint8_t MaxBrightness = 255, uint32_t MaxMilliAmps = 500, uint32_t Voltage = 5>
class Power: public Figment {
public:
Power() : Figment("Power") {}
Power() : Figment("Power") {state = Task::Running;}
void handleEvent(const InputEvent& evt) override {
switch (evt.intent) {

View File

@ -1,7 +1,7 @@
#include "SolidAnimation.h"
#include "../Static.h"
SolidAnimation::SolidAnimation() : Figment("Solid", Task::Stopped) {
SolidAnimation::SolidAnimation() : Figment("Solid") {
}
void SolidAnimation::randomize() {

View File

@ -4,8 +4,8 @@
template<int Period>
class ColorSequenceInput: public InputSource {
public:
ColorSequenceInput(const std::vector<CRGB> &colors, const char* name, Task::State initialState)
: InputSource(name, initialState), m_colors(colors) {}
ColorSequenceInput(const std::vector<CRGB> &colors, const char* name)
: InputSource(name), m_colors(colors) {}
InputEvent read() override {
EVERY_N_SECONDS(Period) {

34
src/inputs/Serial.cpp Normal file
View File

@ -0,0 +1,34 @@
#include "Serial.h"
InputEvent
Serial::read()
{
while (Serial.available() > 0) {
char nextChar = Serial.read();
if (nextChar == '\n') {
doCommand();
m_buf = "";
} else {
m_buf += nextChar;
}
}
}
void
Serial::doCommand() {
if (command == "tasks") {
Serial.println("Tasks:");
auto sched = MainLoop::instance()->scheduler;
for(auto task : sched.tasks) {
bool isFigment = task->isFigment();
if (isFigment) {
Serial.println("F " + task->name);
} else {
Serial.println("T " + task->name);
}
}
}
}
STATIC_ALLOC(SerialInput);
STATIC_TASK(SerialInput);

View File

@ -1,12 +1,17 @@
#pragma once
#include "Particle.h"
#include "../Figments/Figments.h"
class SerialInput: public InputSource {
public:
void onAttach() override {
void onStart() override {
//Serial.begin();
}
InputEvent read() {
}
InputEvent read();
private:
String m_buf;
void doCommand();
}

View File

@ -3,10 +3,7 @@
#include <FastLED.h>
#include <Figments.h>
#ifndef PLATFORM_PHOTON
#include <ArduinoLog.h>
#endif // !PLATFORM_PHOTON
#include "Platform.h"
#include "Static.h"
@ -23,13 +20,6 @@
#include "inputs/ColorCycle.h"
#include "inputs/Buttons.h"
#ifdef PLATFORM_PHOTON
#include "platform/particle/inputs/Photon.h"
#include "platform/particle/inputs/CloudStatus.h"
#endif // PLATFORM_PHOTON
//SerialLogHandler logHandler;
#define MAX_BRIGHTNESS 255
//#define PSU_MILLIAMPS 4800
//#define PSU_MILLIAMPS 500
@ -75,7 +65,7 @@ InputFunc randomPulse([]() {
}
}
return InputEvent{};
}, "Pulse", Task::Stopped);
}, "Pulse");
REGISTER_TASK(randomPulse);
@ -167,7 +157,7 @@ ColorSequenceInput<9> idleCycle{{
CRGB(128, 0, 128), // Purple
CRGB(255, 255, 255), // White
CRGB(0, 255, 255), // Cyan
}, "IdleColors", Task::Stopped};
}, "IdleColors"};
REGISTER_TASK(idleCycle);
@ -177,7 +167,7 @@ ColorSequenceInput<7> rainbowCycle{{
CRGB(0, 255, 0), // Green
CRGB(0, 0, 255), // Blue
CRGB(128, 0, 128), // Purple
}, "Rainbow", Task::Stopped};
}, "Rainbow"};
REGISTER_TASK(rainbowCycle);
@ -428,17 +418,15 @@ MainLoop* runner = &safeModeApp;
void setup() {
// Turn on,
Platform::preSetup();
#ifdef CONFIG_MQTT
Static<MQTTTelemetry>::instance()->setSequencer(&sequencer);
#endif // CONFIG_MQTT
Log.notice(u8"🐛 Booting Renderbug!");
Log.notice(u8"🐞 I am built for %d LEDs running on %dmA", HardwareConfig::MAX_LED_NUM, PSU_MILLIAMPS);
Log.notice(u8"📡 Platform %s version %s", Platform::name(), Platform::version());
Log.notice(u8"Setting timezone to -7 (PST)");
Platform::setTimezone(-7);
Log.notice(u8"Setting timezone to +2 (CEST)");
Platform::setTimezone(+2);
Log.notice(u8"Setting up platform...");
Platform::setup();
Platform::bootSplash();
@ -453,6 +441,7 @@ void setup() {
FastLED.show();
} else if (Platform::bootopts.isSetup) {
Log.notice(u8"🔧 Starting Figment in configuration mode...");
FastLED.showColor(CRGB(0, 5, 0));
//runner = &configApp;
} else {
Log.notice(u8"🌌 Starting Figment...");

View File

@ -6,6 +6,8 @@
#include "../../Config.h"
#include "../../Platform.h"
StaticJsonDocument<1024> m_json;
struct MQTTDevice {
const String id;
const String name;
@ -234,14 +236,13 @@ MQTTTelemetry::loopOnline()
m_json["os_version"] = ESP.getSdkVersion();
m_json["localip"] = WiFi.localIP().toString();
m_json["pixelCount"] = Static<ConfigService>::instance()->coordMap()->physicalPixelCount();
//m_json["startPixel"] = Static<ConfigService>::instance()->coordMap()->startPixel;
m_json["loadedProfile"] = Static<ConfigService>::instance()->loadedProfile();
m_json["RSSI"] = WiFi.RSSI();
m_json["free_ram"] = ESP.getFreeHeap();
m_json["fps"] = FastLED.getFPS();
String availTopic = m_rootTopic + "/available";
publishDoc(Lightswitch.heartbeatTopic().c_str());
m_mqtt.publish(Device.availabilityTopic.c_str(), "online");
//Log.trace("Heartbeat: %s", buf);
String fpsCounter = String(FastLED.getFPS());
m_mqtt.publish(FPSSensor.statTopic().c_str(), fpsCounter.c_str());
@ -302,6 +303,11 @@ MQTTTelemetry::callback(char* topic, const char* payload)
setEvent(InputEvent{InputEvent::SetDisplayOffset, m_json["startPixel"].as<int>()});
}
if (m_json.containsKey("loadConfig")) {
Log.notice("Loading new config");
setEvent(InputEvent{InputEvent::LoadConfigurationByName, m_json["loadConfig"].as<const char*>()});
}
if (m_json.containsKey("save")) {
setEvent(InputEvent{InputEvent::SaveConfigurationRequest});
}

View File

@ -12,8 +12,6 @@
#include <WiFi.h>
#endif
#include <ArduinoJson.h>
class MQTTTelemetry : public BufferedInputSource, OnlineTaskMixin {
public:
MQTTTelemetry();
@ -75,5 +73,4 @@ class MQTTTelemetry : public BufferedInputSource, OnlineTaskMixin {
WiFiClient m_wifi;
PubSubClient m_mqtt;
LogPrinter m_logPrinter;
StaticJsonDocument<1024> m_json;
};