diff --git a/src/ha.h b/src/ha.h index df756bc..8465741 100644 --- a/src/ha.h +++ b/src/ha.h @@ -12,7 +12,9 @@ namespace Ha { uint16_t(*publisher)(const char* topic, const char* message); typedef void (*onMessage)(const char* msg); + struct Component; struct DeviceConfig { + friend struct Component; const char* id = nullptr; const char* name = nullptr; const char* model = nullptr; @@ -24,17 +26,6 @@ namespace Ha { return *(new DeviceConfig{ id }); } - void buildConfig(JsonDocument& jsonDoc) { - JsonObject device = jsonDoc.createNestedObject("device"); - if (name) device["name"] = name; - if (model) device["model"] = model; - if (manufacturer) device["manufacturer"] = manufacturer; - if (area) device["suggested_area"] = area; - if (parent) device["via_device"] = parent->id; - JsonArray identifiers = device.createNestedArray("identifiers"); - identifiers.add(id); - } - DeviceConfig& withName(const char* value) { name = value; return *this; @@ -62,6 +53,17 @@ namespace Ha { protected: DeviceConfig(const char* id) : id(id) {} + + void buildConfig(JsonDocument& jsonDoc) { + JsonObject device = jsonDoc.createNestedObject("device"); + if (name) device["name"] = name; + if (model) device["model"] = model; + if (manufacturer) device["manufacturer"] = manufacturer; + if (area) device["suggested_area"] = area; + if (parent) device["via_device"] = parent->id; + JsonArray identifiers = device.createNestedArray("identifiers"); + identifiers.add(id); + } }; struct Component { @@ -99,6 +101,21 @@ namespace Ha { components.add(this); } + void publishConfig() { + StaticJsonDocument jsonDoc; + buildConfig(jsonDoc); + + char message[JSON_SIZE]; + serializeJson(jsonDoc, message); + + publisher(configTopic, message); + } + + void publishCleanupConfig() { + publisher(configTopic, ""); + } + + protected: virtual void buildUniqueId(char* uniqueId) { sprintf(uniqueId, "%s_%s", MAIN_DEVICE_ID, id); } @@ -125,33 +142,20 @@ namespace Ha { jsonNumbers.addToJson(jsonDoc); jsonStrings.addToJson(jsonDoc); } - - void publishConfig() { - StaticJsonDocument jsonDoc; - buildConfig(jsonDoc); - - char message[JSON_SIZE]; - serializeJson(jsonDoc, message); - - publisher(configTopic, message); - } - - void publishCleanupConfig() { - publisher(configTopic, ""); - } }; struct AbstractBuilder { static List builders; - AbstractBuilder() { - builders.add(this); - } - static void deleteAll() { builders.forEach([](AbstractBuilder* builder) { delete builder; }); builders.empty(); } + + protected: + AbstractBuilder() { + builders.add(this); + } }; template @@ -255,8 +259,6 @@ namespace Ha { struct Command : Component { bool retain = false; - char commandTopic[TOPIC_SIZE]; - onMessage f; static unordered_map mapCommands; Command(const char* name, const char* id, const char* type, onMessage f) : Component(name, id, type), f(f) { @@ -268,6 +270,9 @@ namespace Ha { if (f) f(msg); } + protected: + char commandTopic[TOPIC_SIZE]; + onMessage f; virtual void buildCommandConfig(JsonDocument& jsonDoc) = 0; void buildComponentConfig(JsonDocument& jsonDoc) override { @@ -275,21 +280,19 @@ namespace Ha { if (retain) jsonDoc["retain"] = true; buildCommandConfig(jsonDoc); } - }; struct Button : Command { Button(const char* name, const char* id, onMessage f = nullptr) : Command(name, id, "button", f) {} + protected: void buildCommandConfig(JsonDocument& jsonDoc) override {} }; struct StateConfig { - char stateTopic[TOPIC_SIZE]; static unordered_map mapStateTopics; - Component* cmp; StateConfig(Component* cmp) : cmp(cmp) {} @@ -297,23 +300,22 @@ namespace Ha { sprintf(stateTopic, "homeassistant/%s/%s/%s/state", cmp->type, MAIN_DEVICE_ID, cmp->id); } - void buildConfig(JsonDocument& jsonDoc) { - if (stateTopic[0]) jsonDoc["state_topic"] = stateTopic; - } - void updateState(const char* message) { if (stateTopic[0]) publisher(stateTopic, message); } + + protected: + char stateTopic[TOPIC_SIZE]; + Component* cmp; + void buildConfig(JsonDocument& jsonDoc) { + if (stateTopic[0]) jsonDoc["state_topic"] = stateTopic; + } }; struct Switch : Command, StateConfig { Switch(const char* name, const char* id, onMessage f = nullptr) : Command(name, id, "switch", f), StateConfig(this) {} - void buildCommandConfig(JsonDocument& jsonDoc) override { - StateConfig::buildConfig(jsonDoc); - } - void updateState(bool state) { StateConfig::updateState(state ? "ON" : "OFF"); } @@ -321,6 +323,11 @@ namespace Ha { void restoreFromState() { mapStateTopics.insert({stateTopic, this}); } + + protected: + void buildCommandConfig(JsonDocument& jsonDoc) override { + StateConfig::buildConfig(jsonDoc); + } }; struct Number : Command, StateConfig { @@ -329,13 +336,6 @@ namespace Ha { 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 buildCommandConfig(JsonDocument& jsonDoc) override { - StateConfig::buildConfig(jsonDoc); - jsonDoc["min"] = min; - jsonDoc["max"] = max; - jsonDoc["step"] = step; - } - void updateState(unsigned int value) { char message[32]; sprintf(message, "%u", value); @@ -346,6 +346,13 @@ namespace Ha { mapStateTopics.insert({stateTopic, this}); } + protected: + void buildCommandConfig(JsonDocument& jsonDoc) override { + StateConfig::buildConfig(jsonDoc); + jsonDoc["min"] = min; + jsonDoc["max"] = max; + jsonDoc["step"] = step; + } }; struct Sensor : Component, StateConfig { @@ -359,6 +366,7 @@ namespace Ha { mapSensors.insert({ id, this }); } + protected: void buildUniqueId(char* uniqueId) override { if (multiValueComponent && deviceClass) { sprintf(uniqueId, "%s_%s_%s", MAIN_DEVICE_ID, deviceClass, id);