build for esp32 mask project
This commit is contained in:
86
src/platform/arduino/BluetoothSerialTelemetry.cpp
Normal file
86
src/platform/arduino/BluetoothSerialTelemetry.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
#include "BluetoothSerialTelemetry.h"
|
||||
#include "../../Static.h"
|
||||
#include "../../Platform.h"
|
||||
#include <ArduinoLog.h>
|
||||
#include "../../inputs/Buttons.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
BluetoothSerialTelemetry::BluetoothSerialTelemetry() : InputSource("Bluetooth")
|
||||
{
|
||||
//m_serial.setPin("0000");
|
||||
m_serial.enableSSP();
|
||||
}
|
||||
|
||||
InputEvent
|
||||
BluetoothSerialTelemetry::read()
|
||||
{
|
||||
bool didRead = false;
|
||||
while (m_serial.available()) {
|
||||
didRead = true;
|
||||
char charRead = m_serial.read();
|
||||
m_ringbuf.insert(charRead);
|
||||
if (charRead == '*') {
|
||||
static char commandBuf[32];
|
||||
size_t cmdSize = m_ringbuf.write(commandBuf);
|
||||
// Overwrite the '*' character, to leave us with a complete command
|
||||
commandBuf[cmdSize-1] = 0;
|
||||
|
||||
//Log.notice("Bluetooth read %s", commandBuf);
|
||||
|
||||
if (commandBuf[0] == 'R') {
|
||||
m_color = CRGB(std::atoi(&commandBuf[1]), m_color.g, m_color.b);
|
||||
return InputEvent{InputEvent::SetColor, m_color};
|
||||
} else if (commandBuf[0] == 'G') {
|
||||
m_color = CRGB(m_color.r, std::atoi(&commandBuf[1]), m_color.b);
|
||||
return InputEvent{InputEvent::SetColor, m_color};
|
||||
} else if (commandBuf[0] == 'B') {
|
||||
m_color = CRGB(m_color.r, m_color.g, std::atoi(&commandBuf[1]));
|
||||
return InputEvent{InputEvent::SetColor, m_color};
|
||||
} else if (commandBuf[0] == 'O') {
|
||||
return InputEvent{InputEvent::UserInput, Buttons::Circle};
|
||||
} else if (commandBuf[0] == 'S') {
|
||||
return InputEvent{InputEvent::UserInput, Buttons::Triangle};
|
||||
} else if (commandBuf[0] == 'X') {
|
||||
return InputEvent{InputEvent::UserInput, Buttons::Cross};
|
||||
} else if (commandBuf[0] == '+') {
|
||||
return InputEvent{InputEvent::SetPower, 1};
|
||||
} else if (commandBuf[0] == '-') {
|
||||
return InputEvent{InputEvent::SetPower, 0};
|
||||
} else if (commandBuf[0] == 'p') {
|
||||
return InputEvent{InputEvent::SetPattern, &commandBuf[1]};
|
||||
} else if (commandBuf[0] == 'A') {
|
||||
char* axisVal = strtok(&commandBuf[1], ",");
|
||||
const uint8_t accelX = std::atof(axisVal) * 10;
|
||||
axisVal = strtok(NULL, ",");
|
||||
const uint8_t accelY = std::atof(axisVal) * 10;
|
||||
axisVal = strtok(NULL, ",");
|
||||
const uint8_t accelZ = std::atof(axisVal) * 10;
|
||||
const uint16_t accelSum = abs(accelX) + abs(accelY) + abs(accelZ);
|
||||
const uint16_t delta = abs(m_value.value() - accelSum);
|
||||
m_value.add(accelSum);
|
||||
if (delta > 32) {
|
||||
return InputEvent{InputEvent::Acceleration, delta};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (didRead) {
|
||||
return InputEvent::NetworkActivity;
|
||||
} else {
|
||||
return InputEvent{};
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothSerialTelemetry::onStart()
|
||||
{
|
||||
Log.notice("Starting up Bluetooth...");
|
||||
if (m_serial.begin(Platform::deviceName())) {
|
||||
Log.notice("Bluetooth started!");
|
||||
} else {
|
||||
Log.warning("Bluetooth could not be started!");
|
||||
}
|
||||
}
|
||||
|
||||
STATIC_ALLOC(BluetoothSerialTelemetry);
|
41
src/platform/arduino/BluetoothSerialTelemetry.h
Normal file
41
src/platform/arduino/BluetoothSerialTelemetry.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#include <Figments.h>
|
||||
#include <BluetoothSerial.h>
|
||||
#include <Ringbuf.h>
|
||||
|
||||
class BluetoothSerialTelemetry : public InputSource {
|
||||
public:
|
||||
BluetoothSerialTelemetry();
|
||||
void onStart() override;
|
||||
InputEvent read() override;
|
||||
|
||||
template<typename T, uint8_t Size = 8>
|
||||
struct Averager {
|
||||
std::array<T, Size> buf;
|
||||
unsigned int idx = 0;
|
||||
unsigned int count = 0;
|
||||
|
||||
void add(const T &value) {
|
||||
buf[idx] = value;
|
||||
idx = (idx + 1) % Size;
|
||||
if (count < Size) {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
T value() const {
|
||||
if (count == 0) {
|
||||
return T{};
|
||||
}
|
||||
long long int sum = 0;
|
||||
for(unsigned int i = 0; i < count; i++) {
|
||||
sum += buf[i];
|
||||
}
|
||||
return sum / count;
|
||||
}
|
||||
};
|
||||
private:
|
||||
BluetoothSerial m_serial;
|
||||
Ringbuf<char, 32> m_ringbuf;
|
||||
CRGB m_color;
|
||||
Averager<int16_t, 32> m_value;
|
||||
};
|
@@ -1,107 +1,190 @@
|
||||
#include "MQTTTelemetry.h"
|
||||
|
||||
#ifdef BOARD_ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#elif defined(BOARD_ESP32)
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#include "../../Static.h"
|
||||
#include "../../Config.h"
|
||||
#include "../../Platform.h"
|
||||
|
||||
WiFiClient wifiClient;
|
||||
struct MQTTDevice {
|
||||
const String id;
|
||||
const String name;
|
||||
const String model;
|
||||
const String softwareVersion;
|
||||
const String manufacturer;
|
||||
const String availabilityTopic;
|
||||
|
||||
void toJson(const JsonObject& json) const {
|
||||
json["name"] = name;
|
||||
json["mdl"] = model;
|
||||
json["sw"] = softwareVersion;
|
||||
json["mf"] = manufacturer;
|
||||
json["ids"][0] = id;
|
||||
}
|
||||
};
|
||||
|
||||
const String availTopic = String("renderbug/") + Platform::deviceID() + "/availability";
|
||||
|
||||
const MQTTDevice Device{
|
||||
Platform::deviceID(),
|
||||
Platform::deviceName(),
|
||||
Platform::model(),
|
||||
#ifdef BOARD_ESP8266
|
||||
ESP.getSketchMD5(),
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
"Phong Robotics",
|
||||
availTopic
|
||||
};
|
||||
|
||||
struct MQTTEntity {
|
||||
const MQTTDevice& device;
|
||||
String name;
|
||||
String entityId;
|
||||
String rootTopic;
|
||||
|
||||
MQTTEntity(const String& domain, const MQTTDevice& device, const String& name) : device(device), name(Platform::deviceName() + " " + name) {
|
||||
entityId = String(device.id) + "-" + name;
|
||||
rootTopic = String("homeassistant/") + domain + String("/renderbug/") + entityId;
|
||||
}
|
||||
|
||||
String configTopic() const {
|
||||
return rootTopic + "/config";
|
||||
}
|
||||
|
||||
String commandTopic() const {
|
||||
return rootTopic + "/set";
|
||||
}
|
||||
|
||||
String heartbeatTopic() const {
|
||||
return String("renderbug/") + Device.id + "/heartbeat";
|
||||
}
|
||||
|
||||
String statTopic() const {
|
||||
return rootTopic + "/state";
|
||||
}
|
||||
|
||||
bool isCommandTopic(const char* topic) const {
|
||||
if (strncmp(topic, rootTopic.c_str(), rootTopic.length()) == 0) {
|
||||
return strncmp(&topic[rootTopic.length()], "/set", sizeof("/set")) == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void toJson(JsonDocument& jsonBuf, bool isInteractive = true) const {
|
||||
jsonBuf["~"] = rootTopic.c_str();
|
||||
jsonBuf["name"] = name;
|
||||
jsonBuf["unique_id"] = entityId;
|
||||
if (isInteractive) {
|
||||
jsonBuf["cmd_t"] = "~/set";
|
||||
jsonBuf["ret"] = true;
|
||||
jsonBuf["schema"] = "json";
|
||||
} else {
|
||||
}
|
||||
jsonBuf["stat_t"] = "~/state";
|
||||
jsonBuf["json_attr_t"] = heartbeatTopic();
|
||||
jsonBuf["avty_t"] = device.availabilityTopic;
|
||||
device.toJson(jsonBuf.createNestedObject("dev"));
|
||||
}
|
||||
};
|
||||
|
||||
const MQTTEntity Lightswitch {
|
||||
"light", Device, "lightswitch"
|
||||
};
|
||||
|
||||
const MQTTEntity flashlightSwitch {
|
||||
"switch", Device, "flashlight"
|
||||
};
|
||||
|
||||
const MQTTEntity FPSSensor {
|
||||
"sensor", Device, "fps"
|
||||
};
|
||||
|
||||
MQTTTelemetry::MQTTTelemetry() : BufferedInputSource("MQTT"),
|
||||
m_mqtt(PubSubClient(wifiClient)),
|
||||
m_mqtt(m_wifi),
|
||||
m_logPrinter(this)
|
||||
{}
|
||||
{
|
||||
m_debugTopic = String("renderbug/") + Platform::deviceID();
|
||||
}
|
||||
|
||||
void
|
||||
MQTTTelemetry::handleEventOnline(const InputEvent& evt)
|
||||
{
|
||||
if (!m_mqtt.connected()) {
|
||||
Log.notice("Connecting to MQTT...");
|
||||
const IPAddress server(10, 0, 0, 2);
|
||||
const char* deviceID = Platform::deviceID();
|
||||
Log.verbose("Device ID %s", deviceID);
|
||||
m_mqtt.setServer(server, 1883);
|
||||
m_mqtt.setBufferSize(512);
|
||||
m_mqtt.setCallback(&MQTTTelemetry::s_callback);
|
||||
if (m_mqtt.connect(deviceID)) {
|
||||
Log.notice("Connecting to MQTT as %s on %s...", Platform::deviceID(), Device.availabilityTopic.c_str());
|
||||
if (m_mqtt.connect(Platform::deviceID(), NULL, NULL, Device.availabilityTopic.c_str(), 0, true, "offline")) {
|
||||
Log.notice("Connected to MQTT");
|
||||
m_needHeartbeat = true;
|
||||
|
||||
const String deviceName = String("Renderbug ESP8266") + (char*)deviceID;
|
||||
const String rootTopic = String("homeassistant/light/renderbug/") + (char*)deviceID;
|
||||
const String configTopic = rootTopic + "/config";
|
||||
Log.verbose("root topic %s", rootTopic.c_str());
|
||||
Log.verbose("config topic %s", configTopic.c_str());
|
||||
const String statTopic = rootTopic + "/state";
|
||||
const String cmdTopic = rootTopic + "/set";
|
||||
const String attrTopic = rootTopic + "/attributes";
|
||||
const String logTopic = rootTopic + "/log";
|
||||
const String heartbeatTopic = rootTopic + "/heartbeat";
|
||||
strcpy(m_statTopic, statTopic.c_str());
|
||||
strcpy(m_attrTopic, attrTopic.c_str());
|
||||
strcpy(m_cmdTopic, cmdTopic.c_str());
|
||||
strcpy(m_logTopic, logTopic.c_str());
|
||||
strcpy(m_heartbeatTopic, heartbeatTopic.c_str());
|
||||
|
||||
StaticJsonDocument<1024> configJson;
|
||||
configJson["~"] = rootTopic;
|
||||
configJson["name"] = deviceName;
|
||||
configJson["ret"] = true;
|
||||
configJson["unique_id"] = (char*) deviceID;
|
||||
configJson["cmd_t"] = "~/set";
|
||||
configJson["stat_t"] = "~/state";
|
||||
configJson["json_attr_t"] = "~/attributes";
|
||||
configJson["schema"] = "json";
|
||||
configJson["brightness"] = true;
|
||||
configJson["rgb"] = true;
|
||||
|
||||
Lightswitch.toJson(configJson);
|
||||
|
||||
int i = 0;
|
||||
for(const Sequencer::Scene& scene : m_sequencer->scenes()) {
|
||||
configJson["fx_list"][i++] = scene.name;
|
||||
}
|
||||
configJson["brightness"] = true;
|
||||
configJson["rgb"] = true;
|
||||
|
||||
configJson["dev"]["name"] = "Renderbug";
|
||||
#ifdef PLATFORM_PHOTON
|
||||
configJson["dev"]["mdl"] = "Photon";
|
||||
#elif defined(BOARD_ESP32)
|
||||
configJson["dev"]["mdl"] = "ESP32";
|
||||
#elif defined(BOARD_ESP8266)
|
||||
configJson["dev"]["mdl"] = "ESP8266";
|
||||
#else
|
||||
configJson["dev"]["mdl"] = "Unknown";
|
||||
#endif
|
||||
configJson["dev"]["sw"] = RENDERBUG_VERSION;
|
||||
configJson["dev"]["mf"] = "Phong Robotics";
|
||||
configJson["dev"]["ids"][0] = (char*)deviceID;
|
||||
char buf[1024];
|
||||
serializeJson(configJson, buf, sizeof(buf));
|
||||
Log.verbose("Publish %s %s", configTopic.c_str(), buf);
|
||||
m_mqtt.publish(configTopic.c_str(), buf, true);
|
||||
m_mqtt.subscribe(m_cmdTopic);
|
||||
|
||||
Log.verbose("Publish %s %s", Lightswitch.configTopic().c_str(), buf);
|
||||
m_mqtt.publish(Lightswitch.configTopic().c_str(), (uint8_t*)buf, strlen(buf), true);
|
||||
m_mqtt.subscribe(Lightswitch.commandTopic().c_str());
|
||||
|
||||
configJson.clear();
|
||||
flashlightSwitch.toJson(configJson, false);
|
||||
configJson["cmd_t"] = "~/set";
|
||||
configJson["ret"] = true;
|
||||
serializeJson(configJson, buf, sizeof(buf));
|
||||
m_mqtt.publish(flashlightSwitch.configTopic().c_str(), (uint8_t*)buf, strlen(buf), true);
|
||||
m_mqtt.subscribe(flashlightSwitch.commandTopic().c_str());
|
||||
|
||||
configJson.clear();
|
||||
FPSSensor.toJson(configJson, false);
|
||||
configJson["unit_of_meas"] = "Frames/s";
|
||||
serializeJson(configJson, buf, sizeof(buf));
|
||||
|
||||
Log.verbose("Publish %s %s", FPSSensor.configTopic().c_str(), buf);
|
||||
m_mqtt.publish(FPSSensor.configTopic().c_str(), (uint8_t*)buf, strlen(buf), true);
|
||||
m_mqtt.subscribe(FPSSensor.commandTopic().c_str());
|
||||
|
||||
#ifdef BOARD_ESP8266
|
||||
struct rst_info resetInfo = *ESP.getResetInfoPtr();
|
||||
if (resetInfo.reason != 0) {
|
||||
char buff[200];
|
||||
sprintf(&buff[0], "Fatal exception:%d flag:%d (%s) epc1:0x%08x epc2:0x%08x epc3:0x%08x excvaddr:0x%08x depc:0x%08x", resetInfo.exccause, resetInfo.reason, (resetInfo.reason == 0 ? "DEFAULT" : resetInfo.reason == 1 ? "WDT" : resetInfo.reason == 2 ? "EXCEPTION" : resetInfo.reason == 3 ? "SOFT_WDT" : resetInfo.reason == 4 ? "SOFT_RESTART" : resetInfo.reason == 5 ? "DEEP_SLEEP_AWAKE" : resetInfo.reason == 6 ? "EXT_SYS_RST" : "???"), resetInfo.epc1, resetInfo.epc2, resetInfo.epc3, resetInfo.excvaddr, resetInfo.depc);
|
||||
Log.warning("Previous crash detected! %s", buff);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
Log.warning("Could not connect to MQTT");
|
||||
}
|
||||
} else {
|
||||
if (evt.intent == InputEvent::SetPower) {
|
||||
String statTopic = Lightswitch.statTopic();
|
||||
if (evt.intent == InputEvent::StopThing && String(evt.asString()) == "Flashlight") {
|
||||
String flashlightStatTopic = flashlightSwitch.statTopic();
|
||||
m_mqtt.publish(flashlightStatTopic.c_str(), "OFF");
|
||||
} else if (evt.intent == InputEvent::StartThing && String(evt.asString()) == "Flashlight") {
|
||||
String flashlightStatTopic = flashlightSwitch.statTopic();
|
||||
m_mqtt.publish(flashlightStatTopic.c_str(), "ON");
|
||||
} else if (evt.intent == InputEvent::SetPower) {
|
||||
StaticJsonDocument<256> doc;
|
||||
char buf[256];
|
||||
doc["state"] = evt.asInt() ? "ON" : "OFF";
|
||||
m_isOn = evt.asInt() ? true : false;
|
||||
doc["state"] = m_isOn ? "ON" : "OFF";
|
||||
serializeJson(doc, buf, sizeof(buf));
|
||||
m_mqtt.publish(m_statTopic, buf);
|
||||
m_mqtt.publish(statTopic.c_str(), buf);
|
||||
} else if (evt.intent == InputEvent::SetBrightness) {
|
||||
StaticJsonDocument<256> doc;
|
||||
char buf[256];
|
||||
doc["brightness"] = evt.asInt();
|
||||
doc["state"] = "ON";
|
||||
doc["state"] = m_isOn ? "ON" : "OFF";
|
||||
serializeJson(doc, buf, sizeof(buf));
|
||||
m_mqtt.publish(m_statTopic, buf);
|
||||
m_mqtt.publish(statTopic.c_str(), buf);
|
||||
} else if (evt.intent == InputEvent::SetColor) {
|
||||
StaticJsonDocument<256> doc;
|
||||
char buf[256];
|
||||
@@ -109,18 +192,19 @@ MQTTTelemetry::handleEventOnline(const InputEvent& evt)
|
||||
doc["color"]["r"] = color.r;
|
||||
doc["color"]["g"] = color.g;
|
||||
doc["color"]["b"] = color.b;
|
||||
doc["state"] = "ON";
|
||||
doc["state"] = m_isOn ? "ON" : "OFF";
|
||||
serializeJson(doc, buf, sizeof(buf));
|
||||
m_mqtt.publish(m_statTopic, buf);
|
||||
m_mqtt.publish(statTopic.c_str(), buf);
|
||||
} else if (evt.intent == InputEvent::SetPattern) {
|
||||
StaticJsonDocument<256> doc;
|
||||
char buf[256];
|
||||
doc["effect"] = evt.asString();
|
||||
doc["state"] = "ON";
|
||||
doc["state"] = m_isOn ? "ON" : "OFF";
|
||||
serializeJson(doc, buf, sizeof(buf));
|
||||
m_mqtt.publish(m_statTopic, buf);
|
||||
m_mqtt.publish(statTopic.c_str(), buf);
|
||||
} else if (evt.intent == InputEvent::FirmwareUpdate) {
|
||||
m_mqtt.publish("renderbug/debug/firmware", "firmware update!");
|
||||
String updateTopic = m_debugTopic + "/firmware";
|
||||
m_mqtt.publish(updateTopic.c_str(), "firmware update!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,6 +216,23 @@ MQTTTelemetry::loop()
|
||||
OnlineTaskMixin::loop();
|
||||
}
|
||||
|
||||
void
|
||||
MQTTTelemetry::onOnline()
|
||||
{
|
||||
const IPAddress server(10, 0, 0, 2);
|
||||
|
||||
m_needHeartbeat = true;
|
||||
m_mqtt.setServer(server, 1883);
|
||||
m_mqtt.setBufferSize(1024);
|
||||
m_mqtt.setCallback(&MQTTTelemetry::s_callback);
|
||||
}
|
||||
|
||||
void
|
||||
MQTTTelemetry::onOffline()
|
||||
{
|
||||
m_mqtt.disconnect();
|
||||
}
|
||||
|
||||
void
|
||||
MQTTTelemetry::loopOnline()
|
||||
{
|
||||
@@ -142,89 +243,126 @@ MQTTTelemetry::loopOnline()
|
||||
if (m_needHeartbeat) {
|
||||
char buf[512];
|
||||
StaticJsonDocument<512> response;
|
||||
response["fps"] = FastLED.getFPS();
|
||||
response["RSSI"] = WiFi.RSSI();
|
||||
response["localip"] = WiFi.localIP().toString();
|
||||
response["free_ram"] = ESP.getFreeHeap();
|
||||
response["os_version"] = ESP.getSdkVersion();
|
||||
response["device_id"] = Platform::deviceID();
|
||||
response["sketch_version"] = ESP.getSketchMD5();
|
||||
response["os_version"] = ESP.getSdkVersion();
|
||||
response["localip"] = WiFi.localIP().toString();
|
||||
response["pixelCount"] = Static<ConfigService>::instance()->coordMap()->pixelCount;
|
||||
response["startPixel"] = Static<ConfigService>::instance()->coordMap()->startPixel;
|
||||
response["RSSI"] = WiFi.RSSI();
|
||||
response["free_ram"] = ESP.getFreeHeap();
|
||||
response["fps"] = FastLED.getFPS();
|
||||
serializeJson(response, buf, sizeof(buf));
|
||||
m_mqtt.publish(m_attrTopic, buf);
|
||||
m_mqtt.publish(m_heartbeatTopic, buf);
|
||||
Log.notice("Heartbeat: %s", buf);
|
||||
String availTopic = m_rootTopic + "/available";
|
||||
m_mqtt.publish(Lightswitch.heartbeatTopic().c_str(), buf);
|
||||
m_mqtt.publish(Device.availabilityTopic.c_str(), "online");
|
||||
//Log.notice("Heartbeat: %s", buf);
|
||||
|
||||
String fpsCounter = String(FastLED.getFPS());
|
||||
m_mqtt.publish(FPSSensor.statTopic().c_str(), fpsCounter.c_str());
|
||||
|
||||
response.clear();
|
||||
auto sched = MainLoop::instance()->scheduler;
|
||||
for(auto task : sched.tasks) {
|
||||
response[task->name] = task->state == Task::Running;
|
||||
}
|
||||
serializeJson(response, buf, sizeof(buf));
|
||||
m_mqtt.publish(m_heartbeatTopic, buf);
|
||||
m_needHeartbeat = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MQTTTelemetry::callback(char* topic, byte* payload, unsigned int length)
|
||||
MQTTTelemetry::callback(char* topic, const char* payload)
|
||||
{
|
||||
DynamicJsonDocument doc(1024);
|
||||
deserializeJson(doc, payload, length);
|
||||
|
||||
if (doc.containsKey("state")) {
|
||||
if (doc["state"] == "ON") {
|
||||
setEvent(InputEvent{InputEvent::SetPower, true});
|
||||
} else if (doc["state"] == "OFF") {
|
||||
setEvent(InputEvent{InputEvent::SetPower, false});
|
||||
}
|
||||
}
|
||||
|
||||
if (doc.containsKey("start")) {
|
||||
strcpy(m_patternBuf, doc["start"].as<const char*>());
|
||||
setEvent(InputEvent{InputEvent::StartThing, m_patternBuf});
|
||||
}
|
||||
|
||||
if (doc.containsKey("stop")) {
|
||||
if (doc["stop"] == name) {
|
||||
Log.notice("You can't kill an idea, or stop the MQTT Task via MQTT.");
|
||||
} else {
|
||||
strcpy(m_patternBuf, doc["stop"].as<const char*>());
|
||||
setEvent(InputEvent{InputEvent::StopThing, m_patternBuf});
|
||||
setEvent(InputEvent::NetworkActivity);
|
||||
if (flashlightSwitch.isCommandTopic(topic)) {
|
||||
if (!strncmp((char*)payload, "ON", sizeof("ON"))) {
|
||||
Log.notice("Turning on flashlight");
|
||||
setEvent(InputEvent{InputEvent::SetPower, true});
|
||||
setEvent(InputEvent{InputEvent::SetPattern, "Flashlight"});
|
||||
setEvent(InputEvent{InputEvent::SetBrightness, 255});
|
||||
} else if (!strncmp((char*)payload, "OFF", sizeof("OFF"))) {
|
||||
Log.notice("Turning off flashlight");
|
||||
setEvent(InputEvent{InputEvent::SetPattern, "Idle"});
|
||||
}
|
||||
}
|
||||
} else if (Lightswitch.isCommandTopic(topic)) {
|
||||
StaticJsonDocument<512> doc;
|
||||
deserializeJson(doc, payload);
|
||||
|
||||
if (doc.containsKey("pixelCount")) {
|
||||
setEvent(InputEvent{InputEvent::SetDisplayLength, (int)doc["pixelCount"]});
|
||||
}
|
||||
if (doc.containsKey("state")) {
|
||||
if (doc["state"] == "ON") {
|
||||
Log.notice("Turning on power");
|
||||
setEvent(InputEvent{InputEvent::SetPower, true});
|
||||
} else if (doc["state"] == "OFF") {
|
||||
Log.notice("Turning off power");
|
||||
setEvent(InputEvent{InputEvent::SetPattern, "Idle"});
|
||||
setEvent(InputEvent{InputEvent::SetPower, false});
|
||||
}
|
||||
}
|
||||
|
||||
if (doc.containsKey("startPixel")) {
|
||||
setEvent(InputEvent{InputEvent::SetDisplayOffset, (int)doc["startPixel"]});
|
||||
}
|
||||
if (doc.containsKey("start")) {
|
||||
strcpy(m_patternBuf, doc["start"].as<const char*>());
|
||||
setEvent(InputEvent{InputEvent::StartThing, m_patternBuf});
|
||||
}
|
||||
|
||||
if (doc.containsKey("save")) {
|
||||
setEvent(InputEvent{InputEvent::SaveConfigurationRequest});
|
||||
}
|
||||
if (doc.containsKey("stop")) {
|
||||
if (doc["stop"] == name) {
|
||||
Log.notice("You can't kill an idea, or stop the MQTT Task via MQTT.");
|
||||
} else {
|
||||
strcpy(m_patternBuf, doc["stop"].as<const char*>());
|
||||
setEvent(InputEvent{InputEvent::StopThing, m_patternBuf});
|
||||
}
|
||||
}
|
||||
|
||||
if (doc.containsKey("effect")) {
|
||||
strcpy(m_patternBuf, doc["effect"].as<const char*>());
|
||||
setEvent(InputEvent{InputEvent::SetPattern, m_patternBuf});
|
||||
}
|
||||
if (doc.containsKey("pixelCount")) {
|
||||
setEvent(InputEvent{InputEvent::SetDisplayLength, (int)doc["pixelCount"]});
|
||||
}
|
||||
|
||||
if (doc.containsKey("color")) {
|
||||
uint8_t r = doc["color"]["r"];
|
||||
uint8_t g = doc["color"]["g"];
|
||||
uint8_t b = doc["color"]["b"];
|
||||
setEvent(InputEvent{InputEvent::SetColor, CRGB(r, g, b)});
|
||||
}
|
||||
if (doc.containsKey("startPixel")) {
|
||||
setEvent(InputEvent{InputEvent::SetDisplayOffset, (int)doc["startPixel"]});
|
||||
}
|
||||
|
||||
if (doc.containsKey("brightness")) {
|
||||
setEvent(InputEvent{InputEvent::SetBrightness, (int)doc["brightness"]});
|
||||
if (doc.containsKey("save")) {
|
||||
setEvent(InputEvent{InputEvent::SaveConfigurationRequest});
|
||||
}
|
||||
|
||||
if (doc.containsKey("restart")) {
|
||||
#ifdef BOARD_ESP8266
|
||||
ESP.wdtDisable();
|
||||
ESP.restart();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (doc.containsKey("reconnect")) {
|
||||
m_mqtt.disconnect();
|
||||
}
|
||||
|
||||
if (doc.containsKey("ping")) {
|
||||
m_needHeartbeat = true;
|
||||
Log.notice("Queuing up heartbeat");
|
||||
}
|
||||
|
||||
if (doc.containsKey("effect")) {
|
||||
strcpy(m_patternBuf, doc["effect"].as<const char*>());
|
||||
setEvent(InputEvent{InputEvent::SetPattern, m_patternBuf});
|
||||
}
|
||||
|
||||
if (doc.containsKey("color")) {
|
||||
uint8_t r = doc["color"]["r"];
|
||||
uint8_t g = doc["color"]["g"];
|
||||
uint8_t b = doc["color"]["b"];
|
||||
setEvent(InputEvent{InputEvent::SetColor, CRGB(r, g, b)});
|
||||
}
|
||||
|
||||
if (doc.containsKey("brightness")) {
|
||||
setEvent(InputEvent{InputEvent::SetBrightness, (int)doc["brightness"]});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MQTTTelemetry::s_callback(char* topic, byte* payload, unsigned int length)
|
||||
{
|
||||
Static<MQTTTelemetry>::instance()->callback(topic, payload, length);
|
||||
char topicBuf[128];
|
||||
char payloadBuf[512];
|
||||
strcpy(topicBuf, topic);
|
||||
memcpy(payloadBuf, payload, length);
|
||||
payloadBuf[std::min(sizeof(payloadBuf) - 1, length)] = 0;
|
||||
Static<MQTTTelemetry>::instance()->callback(topicBuf, payloadBuf);
|
||||
}
|
||||
|
||||
STATIC_ALLOC(MQTTTelemetry);
|
||||
|
@@ -6,6 +6,13 @@
|
||||
|
||||
#include "../../Sequencer.h"
|
||||
|
||||
#ifdef BOARD_ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#elif defined(BOARD_ESP32)
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
|
||||
|
||||
class MQTTTelemetry : public BufferedInputSource, OnlineTaskMixin {
|
||||
public:
|
||||
MQTTTelemetry();
|
||||
@@ -22,7 +29,9 @@ class MQTTTelemetry : public BufferedInputSource, OnlineTaskMixin {
|
||||
if (byte == '\n') {
|
||||
size_t bufSize = buf.write(outBuf);
|
||||
outBuf[std::min(sizeof(outBuf), bufSize)] = 0;
|
||||
telemetry->m_mqtt.publish(telemetry->m_logTopic, outBuf);
|
||||
Serial.println(outBuf);
|
||||
String logTopic = telemetry->m_debugTopic + "/log";
|
||||
telemetry->m_mqtt.publish(logTopic.c_str(), outBuf);
|
||||
} else {
|
||||
buf.insert(byte);
|
||||
}
|
||||
@@ -39,20 +48,22 @@ class MQTTTelemetry : public BufferedInputSource, OnlineTaskMixin {
|
||||
|
||||
void loopOnline() override;
|
||||
|
||||
private:
|
||||
char m_statTopic[100];
|
||||
char m_attrTopic[100];
|
||||
char m_cmdTopic[100];
|
||||
char m_logTopic[100];
|
||||
char m_heartbeatTopic[100];
|
||||
void onOnline() override;
|
||||
void onOffline() override;
|
||||
|
||||
void callback(char* topic, byte* payload, unsigned int length);
|
||||
private:
|
||||
String m_rootTopic;
|
||||
String m_debugTopic;
|
||||
|
||||
void callback(char* topic, const char* payload);
|
||||
|
||||
static void s_callback(char* topic, byte* payload, unsigned int length);
|
||||
char m_patternBuf[48];
|
||||
bool m_needHeartbeat = false;
|
||||
bool m_isOn = true;
|
||||
|
||||
Sequencer *m_sequencer = 0;
|
||||
WiFiClient m_wifi;
|
||||
PubSubClient m_mqtt;
|
||||
LogPrinter m_logPrinter;
|
||||
};
|
||||
|
Reference in New Issue
Block a user