diff --git a/gateway/include/ha.h b/gateway/include/ha.h index 54e41e0..864119d 100644 --- a/gateway/include/ha.h +++ b/gateway/include/ha.h @@ -5,73 +5,123 @@ #define JSON_SIZE 512 #define TOPIC_SIZE 255 -#define DEVICE_ID "rc-gateway" namespace Ha { uint16_t (*publisher)(const char* topic, const char* message); + struct DeviceConfig { + const char* id; + const char* name; + const char* model; + const char* manufacturer; + const char* area; + DeviceConfig* parent = nullptr; + + DeviceConfig(const char* id, const char* name) : id(id), name(name) {} + + void buildConfig(JsonDocument& jsonDoc) { + JsonObject device = jsonDoc.createNestedObject("device"); + device["name"] = name; + // JsonArray connections = device.createNestedArray("connections"); + // JsonArray mac = connections.createNestedArray(); + // mac.add("mac"); + // mac.add(WiFi.macAddress()); + JsonArray identifiers = device.createNestedArray("identifiers"); + identifiers.add(id); + if (model) device["model"] = model; + if (manufacturer) device["manufacturer"] = manufacturer; + if (area) device["suggested_area"] = area; + if (parent) device["via_device"] = parent->id; + } + + DeviceConfig* withModel(const char* value) { + model = value; + return this; + } + + DeviceConfig* withManufacturer(const char* value) { + manufacturer = value; + return this; + } + + DeviceConfig* withArea(const char* value) { + area = value; + return this; + } + + DeviceConfig* withParent(DeviceConfig* deviceConfig) { + parent = deviceConfig; + return this; + } + }; + struct Component { const char* name; char* id; const char* type; char configTopic[TOPIC_SIZE]; - static List configs; + DeviceConfig* mainDevice; + static List components; Component(const char* name, const char* id, const char* type) : name(name), id((char*)id), type(type) { - sprintf(configTopic, "homeassistant/%s/rc-gateway/%s/config", type, id); - configs.add(this); + sprintf(configTopic, "homeassistant/%s/%s/%s/config", type, MAIN_DEVICE_ID, id); + components.add(this); } virtual void buildUniqueId(char* uniqueId) = 0; virtual void buildConfig(JsonDocument& jsonDoc) { - buildDeviceConfig(jsonDoc); + if (mainDevice) mainDevice->buildConfig(jsonDoc); jsonDoc["name"] = name; char uniqueId[50]; buildUniqueId(uniqueId); jsonDoc["unique_id"] = uniqueId; } + }; - virtual void buildDeviceConfig(JsonDocument& jsonDoc) { - JsonObject device = jsonDoc.createNestedObject("device"); - device["name"] = "RC Gateway"; - device["model"] = "Huzzah Esp8266"; - device["manufacturer"] = "Adafruit"; - JsonArray connections = device.createNestedArray("connections"); - JsonArray mac = connections.createNestedArray(); - mac.add("mac"); - mac.add(WiFi.macAddress()); - JsonArray identifiers = device.createNestedArray("identifiers"); - identifiers.add(DEVICE_ID); + template + struct EntityConfig : Component { + + EntityConfig(const char* name, const char* id, const char* type) : Component(name, id, type) { + } + + T* withArea(const char* value) { + if (mainDevice) mainDevice->withArea(value); + return static_cast(this); + } + + T* asDevice(DeviceConfig* deviceConfig) { + mainDevice = deviceConfig; + return static_cast(this); } }; - List Component::configs; + + List Component::components; - struct Command : Component { + template + struct Command : EntityConfig { char commandTopic[TOPIC_SIZE]; - Command(const char* name, const char* id, const char* type) : Component(name, id, type) { + Command(const char* name, const char* id, const char* type) : EntityConfig(name, id, type) { } void buildUniqueId(char* uniqueId) override { - sprintf(uniqueId, "rc_gateway_%s", id); + sprintf(uniqueId, "%s_%s", MAIN_DEVICE_ID, this->id); } void buildConfig(JsonDocument& jsonDoc) override { - Component::buildConfig(jsonDoc); + EntityConfig::buildConfig(jsonDoc); jsonDoc["command_topic"] = commandTopic; } }; typedef void (*onMessage)(const char* msg); - struct Button : Command { + struct Button : Command