diff --git a/gateway/include/devices.h b/gateway/include/devices.h index 6ae8b46..4a1451f 100644 --- a/gateway/include/devices.h +++ b/gateway/include/devices.h @@ -7,16 +7,20 @@ using namespace Ha; DeviceConfig* gatewayDevice = (new DeviceConfig{MAIN_DEVICE_ID})->withName("RC Gateway")->withManufacturer("Adafruit")->withModel("Huzzah Esp8266"); -DeviceConfig* atTinyDevice = (new DeviceConfig{})->withManufacturer("Atmel")->withModel("AtTiny85")->withParent(gatewayDevice); struct OilTankRoomSensorBuilder { static Sensor* build(const char* id) { - auto device = (new DeviceConfig{*atTinyDevice})->withName("Oil tank room")->withArea("Basement"); - device->id = id; - Sensor* sensor = (new Ha::TemperatureSensor(id))->asDevice(device); - (new VoltageSensor{sensor->id, "Battery voltage", "{{ value_json.sensor.diagnostic.voltage }}"})->ofDevice((id)); - (new BatterySensor{sensor->id, "Battery level", "{{ ((states('sensor.oil_tank_room_battery_voltage')|float-2.5)|round(2)*100/2)|int }}"})->ofDevice(id); - return sensor; + auto device = (new DeviceConfig{ id }) + ->withName("Oil tank room") + ->withManufacturer("Atmel") + ->withModel("AtTiny85") + ->withArea("Basement") + ->withParent(gatewayDevice); + return Builder::instance(id) + .asDevice(device) + .withDiagnostic(new VoltageSensor{id, "Battery voltage", "{{ value_json.sensor.diagnostic.voltage }}"}) + .withDiagnostic(new BatterySensor{id, "Battery level", "{{ ((states('sensor.oil_tank_room_battery_voltage')|float-2.5)|round(2)*100/2)|int }}"}) + .build(); } }; @@ -45,13 +49,18 @@ struct OilTankLevelSensor : Sensor { struct OilSensorBuilder { static Sensor* build(const char* id) { - auto device = (new DeviceConfig{*atTinyDevice})->withName("Oil tank")->withArea("Basement"); - device->id = id; - Sensor* sensor = (new OilTankSensor(id))->asDevice(device); - (new OilTankLevelSensor(sensor->id))->ofDevice(id); - (new VoltageSensor{id, "Battery voltage", "{{ value_json.sensor.diagnostic.voltage }}"})->ofDevice(id); - (new BatterySensor{id, "Battery level", "{{ ((states('sensor.oil_tank_battery_voltage')|float-3.6)|round(2)*100/1.6)|int }}"})->ofDevice(id); - return sensor; + auto device = (new DeviceConfig{ id }) + ->withName("Oil tank") + ->withManufacturer("Arduino") + ->withModel("Pro Mini") + ->withArea("Basement") + ->withParent(gatewayDevice); + return Builder::instance(id) + .asDevice(device) + .withSecondary(new OilTankLevelSensor(id)) + .withDiagnostic(new VoltageSensor{id, "Battery voltage", "{{ value_json.sensor.diagnostic.voltage }}"}) + .withDiagnostic(new BatterySensor{id, "Battery level", "{{ ((states('sensor.oil_tank_battery_voltage')|float-3.6)|round(2)*100/1.6)|int }}"}) + .build(); } }; @@ -61,7 +70,7 @@ struct PollinSwitch : Switch { PollinSwitch(const char* name, const char* group, const unsigned char channel, const char* area = nullptr) : Switch(name, Protocol_1::buildId(group, channel)), group(group), channel(channel) { - asDevice((new DeviceConfig{id})->withName(name)->withManufacturer("Pollin")->withArea(area)->withParent(gatewayDevice)); + mainDevice = (new DeviceConfig{id})->withName(name)->withManufacturer("Pollin")->withArea(area)->withParent(gatewayDevice); p1Switches.insert({ string(id), this }); } @@ -80,7 +89,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)); - asDevice((new DeviceConfig{id})->withName(name)->withManufacturer("Intertek")->withModel("Easy Home")->withArea(area)->withParent(gatewayDevice)); + mainDevice = (new DeviceConfig{id})->withName(name)->withManufacturer("Intertek")->withModel("Easy Home")->withArea(area)->withParent(gatewayDevice); for (int i = 0; i < 8; i++) { onSwitches.insert({ this->on[i], this }); offSwitches.insert({ this->off[i], this }); diff --git a/gateway/include/ha.h b/gateway/include/ha.h index 61515cc..904f254 100644 --- a/gateway/include/ha.h +++ b/gateway/include/ha.h @@ -93,31 +93,56 @@ namespace Ha { jsonDoc["unique_id"] = uniqueId; } }; - - template - struct EntityConfig : Component { - - EntityConfig(const char* name, const char* id, const char* type) : Component(name, id, type) { - } - - T* asDevice(DeviceConfig* deviceConfig) { - mainDevice = deviceConfig; - return static_cast(this); - } - - T* ofDevice(const char* id) { - mainDevice = new DeviceConfig{id}; - return static_cast(this); - } - }; List Component::components; template - struct Command : EntityConfig { + struct Builder { + T* cmp; + + Builder() {} + Builder(T* cmp) : cmp(cmp) {} + Builder(const char* id) { + cmp = new T{id}; + } + + static Builder& instance() { + return *(new Builder()); + } + + static Builder& instance(T* c) { + return *(new Builder(c)); + } + + static Builder& instance(const char* id) { + return *(new Builder(id)); + } + + T* build() { + return static_cast(cmp); + } + + Builder& withSecondary(Component* c) { + c->mainDevice = new DeviceConfig{ cmp->id }; + return *this; + } + + Builder& withDiagnostic(Component* c) { + c->entityCategory = "diagnostic"; + c->mainDevice = new DeviceConfig{ cmp->id }; + return *this; + } + + Builder& asDevice(DeviceConfig* deviceConfig) { + cmp->mainDevice = deviceConfig; + return *this; + } + }; + + struct Command : Component { char commandTopic[TOPIC_SIZE]; - Command(const char* name, const char* id, const char* type) : EntityConfig(name, id, type) { + Command(const char* name, const char* id, const char* type) : Component(name, id, type) { sprintf(commandTopic, "homeassistant/%s/%s/%s", type, MAIN_DEVICE_ID, id); } @@ -126,17 +151,17 @@ namespace Ha { } void buildConfig(JsonDocument& jsonDoc) override { - EntityConfig::buildConfig(jsonDoc); + Component::buildConfig(jsonDoc); jsonDoc["command_topic"] = commandTopic; } }; typedef void (*onMessage)(const char* msg); - struct Button : Command