add Number, refactor StateConfig and add support for restoring state at startup
This commit is contained in:
parent
1fe24a5b7f
commit
510a378a5e
@ -67,6 +67,7 @@ struct PollinSwitch : Switch {
|
||||
return uId;
|
||||
}()), group(group), channel(channel) {
|
||||
mainDevice = &DeviceConfig::create(id).withName(name).withManufacturer("Pollin").withArea(area).withParent(gatewayDevice);
|
||||
withStateTopic();
|
||||
deviceClass = "outlet";
|
||||
p1Switches.insert({ string(id), this });
|
||||
}
|
||||
@ -87,6 +88,7 @@ struct EasyHomeSwitch : Switch {
|
||||
memcpy(&this->on[4], on, 4 * sizeof(unsigned long));
|
||||
memcpy(&this->off[4], off, 4 * sizeof(unsigned long));
|
||||
mainDevice = &DeviceConfig::create(id).withName(name).withManufacturer("Intertek").withModel("Easy Home").withArea(area).withParent(gatewayDevice);
|
||||
withStateTopic();
|
||||
deviceClass = "outlet";
|
||||
for (int i = 0; i < 8; i++) {
|
||||
onSwitches.insert({ this->on[i], this });
|
||||
@ -120,12 +122,12 @@ Command* commands[] = {
|
||||
.withParent(gatewayDevice)
|
||||
)
|
||||
.build(),
|
||||
(new EasyHomeSwitch{"FritzBox", "easy_home_a", (unsigned long[4]) { 4483136, 4626800, 4661552, 4819632 }, (unsigned long[4]) { 4326544, 4537104, 4767520, 4972704 }, "Basement"})->withStateTopic(),
|
||||
(new EasyHomeSwitch{"Outside", "easy_home_b", (unsigned long[4]) { 4483140, 4626804, 4661556, 4819636 }, (unsigned long[4]) { 4326548, 4537108, 4767524, 4972708 }, "Basement"})->withStateTopic(),
|
||||
(new PollinSwitch{"Meeting sensor", "00001", 1, "Dining room"})->withStateTopic(),
|
||||
(new PollinSwitch{"Fire Tv", "00001", 2, "Living room"})->withStateTopic(),
|
||||
(new PollinSwitch{"Diningroom player", "00001", 3, "Dining room"})->withStateTopic(),
|
||||
(new PollinSwitch{"Train", "11111", 4, "Playroom"})->withStateTopic()
|
||||
new EasyHomeSwitch{"FritzBox", "easy_home_a", (unsigned long[4]) { 4483136, 4626800, 4661552, 4819632 }, (unsigned long[4]) { 4326544, 4537104, 4767520, 4972704 }, "Basement"},
|
||||
new EasyHomeSwitch{"Outside", "easy_home_b", (unsigned long[4]) { 4483140, 4626804, 4661556, 4819636 }, (unsigned long[4]) { 4326548, 4537108, 4767524, 4972708 }, "Basement"},
|
||||
new PollinSwitch{"Meeting sensor", "00001", 1, "Dining room"},
|
||||
new PollinSwitch{"Fire Tv", "00001", 2, "Living room"},
|
||||
new PollinSwitch{"Diningroom player", "00001", 3, "Dining room"},
|
||||
new PollinSwitch{"Train", "11111", 4, "Playroom"}
|
||||
};
|
||||
|
||||
Sensor* sensors[] = {
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
#include <ArduinoJson.h>
|
||||
#include "utils.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define JSON_SIZE 512
|
||||
#define TOPIC_SIZE 255
|
||||
|
||||
@ -180,11 +182,20 @@ namespace Ha {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Builder& withStateTopic() {
|
||||
cmp->withStateTopic();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Builder& withRetain(bool retain = true) {
|
||||
cmp->retain = retain;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Builder& restoreFromState() {
|
||||
cmp->restoreFromState();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct Command : Component {
|
||||
@ -216,37 +227,76 @@ namespace Ha {
|
||||
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct StateConfig {
|
||||
char stateTopic[TOPIC_SIZE];
|
||||
static unordered_map<string, Command*> mapStateTopics;
|
||||
Component* cmp;
|
||||
|
||||
T* withStateTopic() {
|
||||
sprintf(stateTopic, "homeassistant/%s/%s/%s/state", ((T*)this)->type, MAIN_DEVICE_ID, ((T*)this)->id);
|
||||
return static_cast<T*>(this);
|
||||
StateConfig(Component* cmp) : cmp(cmp) {}
|
||||
|
||||
void withStateTopic() {
|
||||
sprintf(stateTopic, "homeassistant/%s/%s/%s/state", cmp->type, MAIN_DEVICE_ID, cmp->id);
|
||||
}
|
||||
};
|
||||
|
||||
struct Switch : Command, StateConfig<Switch> {
|
||||
|
||||
Switch(const char* name, const char* id, onMessage f = nullptr) : Command(name, id, "switch", f) {}
|
||||
|
||||
void buildConfig(JsonDocument& jsonDoc) override {
|
||||
Command::buildConfig(jsonDoc);
|
||||
// jsonDoc["retain"] = true;
|
||||
void buildConfig(JsonDocument& jsonDoc) {
|
||||
if (stateTopic[0]) jsonDoc["state_topic"] = stateTopic;
|
||||
}
|
||||
|
||||
void updateState(bool state) {
|
||||
publisher(stateTopic, state ? "ON" : "OFF");
|
||||
void updateState(const char* message) {
|
||||
if (stateTopic[0]) publisher(stateTopic, message);
|
||||
}
|
||||
};
|
||||
|
||||
struct Sensor : Component, StateConfig<Sensor> {
|
||||
struct Switch : Command, StateConfig {
|
||||
|
||||
Switch(const char* name, const char* id, onMessage f = nullptr) : Command(name, id, "switch", f), StateConfig(this) {}
|
||||
|
||||
void buildConfig(JsonDocument& jsonDoc) override {
|
||||
Command::buildConfig(jsonDoc);
|
||||
StateConfig::buildConfig(jsonDoc);
|
||||
}
|
||||
|
||||
void updateState(bool state) {
|
||||
StateConfig::updateState(state ? "ON" : "OFF");
|
||||
}
|
||||
|
||||
void restoreFromState() {
|
||||
mapStateTopics.insert({stateTopic, this});
|
||||
}
|
||||
};
|
||||
|
||||
struct Number : Command, StateConfig {
|
||||
unsigned int min, max, step;
|
||||
|
||||
Number(const char* name, const char* id, unsigned int min, unsigned int max, unsigned int step, onMessage f)
|
||||
: Command(name, id, "number", f), StateConfig(this), min(min), max(max), step(step) {}
|
||||
|
||||
void buildConfig(JsonDocument& jsonDoc) override {
|
||||
Command::buildConfig(jsonDoc);
|
||||
StateConfig::buildConfig(jsonDoc);
|
||||
jsonDoc["min"] = min;
|
||||
jsonDoc["max"] = max;
|
||||
jsonDoc["step"] = step;
|
||||
}
|
||||
|
||||
void updateState(unsigned int value) {
|
||||
char message[32];
|
||||
sprintf(message, "%u", value);
|
||||
StateConfig::updateState(message);
|
||||
}
|
||||
|
||||
void restoreFromState() {
|
||||
mapStateTopics.insert({stateTopic, this});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct Sensor : Component, StateConfig {
|
||||
const char* unitMeasure = nullptr;
|
||||
const char* valueTemplate = nullptr;
|
||||
static unordered_map<string, Sensor*> mapSensors;
|
||||
|
||||
Sensor(const char* name, const char* id) : Component(name, id, "sensor") {
|
||||
Sensor(const char* name, const char* id) : Component(name, id, "sensor"), StateConfig(this) {
|
||||
withStateTopic();
|
||||
mapSensors.insert({ id, this });
|
||||
}
|
||||
@ -269,15 +319,11 @@ namespace Ha {
|
||||
|
||||
void buildConfig(JsonDocument& jsonDoc) override {
|
||||
Component::buildConfig(jsonDoc);
|
||||
StateConfig::buildConfig(jsonDoc);
|
||||
if (unitMeasure) jsonDoc["unit_of_measurement"] = unitMeasure;
|
||||
if (valueTemplate) jsonDoc["value_template"] = valueTemplate;
|
||||
jsonDoc["state_topic"] = stateTopic;
|
||||
jsonDoc["suggested_display_precision"] = 2;
|
||||
}
|
||||
|
||||
void updateState(const char* message) {
|
||||
publisher(stateTopic, message);
|
||||
}
|
||||
};
|
||||
|
||||
struct TemperatureSensor : Sensor {
|
||||
@ -307,7 +353,6 @@ namespace Ha {
|
||||
HumiditySensor(const char* id, const char* name = "Humidity") : Sensor(name, id) {
|
||||
deviceClass = "humidity";
|
||||
unitMeasure = "%";
|
||||
// valueTemplate = "{{ value_json.sensor.humidity }}";
|
||||
}
|
||||
};
|
||||
|
||||
@ -315,7 +360,6 @@ namespace Ha {
|
||||
PressureSensor(const char* id, const char* name = "Pressure") : Sensor(name, id) {
|
||||
deviceClass = "pressure";
|
||||
unitMeasure = "hPa";
|
||||
// valueTemplate = "{{ value_json.sensor.pressure }}";
|
||||
}
|
||||
};
|
||||
|
||||
@ -323,4 +367,5 @@ namespace Ha {
|
||||
List<AbstractBuilder> AbstractBuilder::builders;
|
||||
unordered_map<string, Command*> Command::mapCommands;
|
||||
unordered_map<string, Sensor*> Sensor::mapSensors;
|
||||
unordered_map<string, Command*> StateConfig::mapStateTopics;
|
||||
}
|
||||
|
||||
@ -42,8 +42,15 @@ namespace Mqtt {
|
||||
char msg[len + 1];
|
||||
memcpy(msg, payload, len);
|
||||
msg[len] = 0;
|
||||
Command* cmd = Command::mapCommands[string{ topic }];
|
||||
auto strTopic = string{ topic };
|
||||
auto cmd = Command::mapCommands[strTopic];
|
||||
if (cmd) cmd->onCommand(msg);
|
||||
|
||||
cmd = StateConfig::mapStateTopics[strTopic];
|
||||
if (cmd) {
|
||||
cmd->onCommand(msg);
|
||||
StateConfig::mapStateTopics.erase(strTopic);
|
||||
}
|
||||
}
|
||||
|
||||
void setup(Scheduler* ts = nullptr, void(*onConnected)() = nullptr, void(*onDisconnected)() = nullptr) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user