diff --git a/gateway/README.md b/gateway/README.md index 40206bc..be137bd 100644 --- a/gateway/README.md +++ b/gateway/README.md @@ -44,7 +44,7 @@ enum SensorId : unsigned short { }; ``` #### Stairs temperature -##### Value and volatage +##### Value and voltage ```json { "sensor": { @@ -66,7 +66,7 @@ enum SensorId : unsigned short { } ``` #### Oil sensor -##### Value and volatage +##### Value and voltage ```json { "sensor": { diff --git a/gateway/include/devices.h b/gateway/include/devices.h index eeecfcf..27f0983 100644 --- a/gateway/include/devices.h +++ b/gateway/include/devices.h @@ -1,16 +1,20 @@ #pragma once +#define MAIN_DEVICE_ID "rc-gateway" + #include "ha.h" using namespace Ha; +DeviceConfig* gatewayConfig = (new DeviceConfig{MAIN_DEVICE_ID, "RC Gateway"})->withManufacturer("Adafruit")->withModel("Huzzah Esp8266"); + struct PollinSwitch : Switch { const char* group; unsigned char channel; PollinSwitch(const char* name, const char* group, const unsigned char channel) : Switch(name, Protocol_1::buildId(group, channel)), group(group), channel(channel) { - sprintf(commandTopic, "homeassistant/%s/rc-gateway/%s/set", type, id); + asDevice((new DeviceConfig{id, name})->withManufacturer("Pollin")->withParent(gatewayConfig)); } void onCommand(const char* msg) override { @@ -18,12 +22,6 @@ struct PollinSwitch : Switch { publisher(stateTopic, msg); } - void buildConfig(JsonDocument& jsonDoc) override { - Switch::buildConfig(jsonDoc); - JsonObject device = jsonDoc["device"]; - device["manufacturer"] = "Pollin"; - } - void addToMap() override { p1Switches.insert({ string(id), this }); } @@ -38,7 +36,7 @@ struct EasyHomeSwitch : Switch { : Switch(name, id) { memcpy(&this->on[4], on, 4 * sizeof(unsigned long)); memcpy(&this->off[4], off, 4 * sizeof(unsigned long)); - sprintf(commandTopic, "homeassistant/%s/rc-gateway/%s/set", type, id); + asDevice((new DeviceConfig{id, name})->withManufacturer("Intertek")->withModel("Easy Home")->withParent(gatewayConfig)); } void onCommand(const char* msg) override { @@ -47,13 +45,6 @@ struct EasyHomeSwitch : Switch { publisher(stateTopic, msg); } - void buildConfig(JsonDocument& jsonDoc) override { - Switch::buildConfig(jsonDoc); - JsonObject device = jsonDoc["device"]; - device["manufacturer"] = "Intertek"; - device["model"] = "Easy Home"; - } - void addToMap() override { for (int i = 0; i < 8; i++) { onSwitches.insert({ on[i], this }); 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