From 08ff0ba36762e170715fbb54741e6ace9e6387be Mon Sep 17 00:00:00 2001 From: Nicu Hodos Date: Sat, 8 Jul 2023 00:34:43 +0200 Subject: [PATCH 1/9] unify sensor config --- include/ha.h | 102 ++++++++++++++++++++++++------------------------- include/mqtt.h | 6 +-- 2 files changed, 52 insertions(+), 56 deletions(-) diff --git a/include/ha.h b/include/ha.h index 9b628c1..6961230 100644 --- a/include/ha.h +++ b/include/ha.h @@ -4,48 +4,6 @@ namespace Ha { - struct SensorConfig { - const char* name; - const char* uniqueId; - const char* stateTopic; - const char* deviceClass; - const char* unitMeasure; - const char* valueTemplate; - }; - - struct TemperatureConfig : SensorConfig { - TemperatureConfig(const char* name, const char* uniqueId, const char* stateTopic) { - this->name = name; - this->uniqueId = uniqueId; - this->stateTopic = stateTopic; - this->deviceClass = "temperature"; - this->unitMeasure = "°C"; - this->valueTemplate = "{{ value_json.temperature }}"; - } - }; - - struct PressureConfig : SensorConfig { - PressureConfig(const char* name, const char* uniqueId, const char* stateTopic) { - this->name = name; - this->uniqueId = uniqueId; - this->stateTopic = stateTopic; - this->deviceClass = "pressure"; - this->unitMeasure = "hPa"; - this->valueTemplate = "{{ value_json.pressure }}"; - } - }; - - struct AltitudeConfig : SensorConfig { - AltitudeConfig(const char* name, const char* uniqueId, const char* stateTopic) { - this->name = name; - this->uniqueId = uniqueId; - this->stateTopic = stateTopic; - this->deviceClass = "distance"; - this->unitMeasure = "m"; - this->valueTemplate = "{{ value_json.altitude }}"; - } - }; - void buildDeviceConfig(JsonDocument& jsonDoc) { JsonObject device = jsonDoc.createNestedObject("device"); device["name"] = "ESP Clock"; @@ -56,17 +14,55 @@ namespace Ha { mac.add(WiFi.macAddress()); } - void buildSensorConfig(char(&output)[JSON_SIZE], SensorConfig config) { - StaticJsonDocument jsonDoc; - buildDeviceConfig(jsonDoc); - jsonDoc["device_class"] = config.deviceClass; - jsonDoc["name"] = config.name; - jsonDoc["unique_id"] = config.uniqueId; - jsonDoc["unit_of_measurement"] = config.unitMeasure; - jsonDoc["state_topic"] = config.stateTopic; - jsonDoc["value_template"] = config.valueTemplate; - serializeJson(jsonDoc, output); - } + struct SensorConfig { + const char* name; + const char* uniqueId; + const char* deviceClass; + const char* unitMeasure; + const char* valueTemplate; + void buildConfig(char(&output)[JSON_SIZE], const char* stateTopic) { + StaticJsonDocument jsonDoc; + buildDeviceConfig(jsonDoc); + jsonDoc["device_class"] = deviceClass; + jsonDoc["name"] = name; + jsonDoc["unique_id"] = uniqueId; + jsonDoc["unit_of_measurement"] = unitMeasure; + jsonDoc["state_topic"] = stateTopic; + jsonDoc["value_template"] = valueTemplate; + serializeJson(jsonDoc, output); + } + + }; + + struct TemperatureConfig : SensorConfig { + TemperatureConfig(const char* name, const char* uniqueId) { + this->name = name; + this->uniqueId = uniqueId; + deviceClass = "temperature"; + unitMeasure = "°C"; + valueTemplate = "{{ value_json.temperature }}"; + } + }; + + struct PressureConfig : SensorConfig { + PressureConfig(const char* name, const char* uniqueId) { + this->name = name; + this->uniqueId = uniqueId; + this->deviceClass = "pressure"; + this->unitMeasure = "hPa"; + this->valueTemplate = "{{ value_json.pressure }}"; + } + }; + + struct AltitudeConfig : SensorConfig { + AltitudeConfig(const char* name, const char* uniqueId) { + this->name = name; + this->uniqueId = uniqueId; + this->deviceClass = "distance"; + this->unitMeasure = "m"; + this->valueTemplate = "{{ value_json.altitude }}"; + } + }; void buildRestartConfig(char(&output)[JSON_SIZE], const char* topic) { StaticJsonDocument jsonDoc; diff --git a/include/mqtt.h b/include/mqtt.h index b0c4b9f..0359bb7 100644 --- a/include/mqtt.h +++ b/include/mqtt.h @@ -51,19 +51,19 @@ namespace Mqtt { void publishTempConfig() { char message[JSON_SIZE]; - Ha::buildSensorConfig(message, Ha::TemperatureConfig{ "Living room Temperature", "living_room_temperature", bmpTopic }); + Ha::TemperatureConfig{ "Living room Temperature", "living_room_temperature" }.buildConfig(message, bmpTopic); client.publish("homeassistant/sensor/esp_clock/temperature/config", 0, true, message); } void publishPressureConfig() { char message[JSON_SIZE]; - Ha::buildSensorConfig(message, Ha::PressureConfig{ "Living room Pressure", "living_room_pressure", bmpTopic }); + Ha::PressureConfig{ "Living room Pressure", "living_room_pressure" }.buildConfig(message, bmpTopic); client.publish("homeassistant/sensor/esp_clock/pressure/config", 0, true, message); } void publishAltitudeConfig() { char message[JSON_SIZE]; - Ha::buildSensorConfig(message, Ha::AltitudeConfig{ "Living room Altitude", "living_room_altitude", bmpTopic }); + Ha::AltitudeConfig{ "Living room Altitude", "living_room_altitude" }.buildConfig(message, bmpTopic); client.publish("homeassistant/sensor/esp_clock/altitude/config", 0, true, message); } From 7412029272f795b00b52df9e5841d5e33863bee9 Mon Sep 17 00:00:00 2001 From: Nicu Hodos Date: Sat, 8 Jul 2023 00:46:40 +0200 Subject: [PATCH 2/9] unify command components --- include/ha.h | 26 ++++---------------------- include/mqtt.h | 6 +++--- 2 files changed, 7 insertions(+), 25 deletions(-) diff --git a/include/ha.h b/include/ha.h index 6961230..d7f9ed6 100644 --- a/include/ha.h +++ b/include/ha.h @@ -64,30 +64,12 @@ namespace Ha { } }; - void buildRestartConfig(char(&output)[JSON_SIZE], const char* topic) { + void buildCommandConfig(char(&output)[JSON_SIZE], const char* name, const char* uniqueId, const char* commandTopic) { StaticJsonDocument jsonDoc; buildDeviceConfig(jsonDoc); - jsonDoc["name"] = "Restart"; - jsonDoc["unique_id"] = "esp_clock_restart"; - jsonDoc["command_topic"] = topic; - serializeJson(jsonDoc, output); - } - - void buildLedConfig(char(&output)[JSON_SIZE], const char* topic) { - StaticJsonDocument jsonDoc; - buildDeviceConfig(jsonDoc); - jsonDoc["name"] = "ESP Clock Led"; - jsonDoc["unique_id"] = "esp_clock_led"; - jsonDoc["command_topic"] = topic; - serializeJson(jsonDoc, output); - } - - void buildHourFormatConfig(char(&output)[JSON_SIZE], const char* topic) { - StaticJsonDocument jsonDoc; - buildDeviceConfig(jsonDoc); - jsonDoc["name"] = "ESP Clock Format 24h"; - jsonDoc["unique_id"] = "esp_clock_format_24h"; - jsonDoc["command_topic"] = topic; + jsonDoc["name"] = name; + jsonDoc["unique_id"] = uniqueId; + jsonDoc["command_topic"] = commandTopic; serializeJson(jsonDoc, output); } } diff --git a/include/mqtt.h b/include/mqtt.h index 0359bb7..c033754 100644 --- a/include/mqtt.h +++ b/include/mqtt.h @@ -69,19 +69,19 @@ namespace Mqtt { void publishRestartConfig() { char message[JSON_SIZE]; - Ha::buildRestartConfig(message, restartTopic); + Ha::buildCommandConfig(message, "Restart", "esp_clock_restart", restartTopic); client.publish("homeassistant/button/esp_clock/restart/config", 0, true, message); } void publishLedConfig() { char message[JSON_SIZE]; - Ha::buildLedConfig(message, ledTopic); + Ha::buildCommandConfig(message, "ESP Clock Led", "esp_clock_led", ledTopic); client.publish("homeassistant/switch/esp_clock/led/config", 0, true, message); } void publishHourFormatConfig() { char message[JSON_SIZE]; - Ha::buildHourFormatConfig(message, hourFormatTopic); + Ha::buildCommandConfig(message, "ESP Clock Format 24h", "esp_clock_format_24h", hourFormatTopic); client.publish("homeassistant/switch/esp_clock/hour_format/config", 0, true, message); } From b2e049f93037c99b93d9cb0586d4e2b9d4c6ea54 Mon Sep 17 00:00:00 2001 From: Nicu Hodos Date: Sat, 8 Jul 2023 01:01:11 +0200 Subject: [PATCH 3/9] make build configuration consistent --- include/ha.h | 93 +++++++++++++++++++++++--------------------------- include/mqtt.h | 6 ++-- 2 files changed, 46 insertions(+), 53 deletions(-) diff --git a/include/ha.h b/include/ha.h index d7f9ed6..9f3a5fa 100644 --- a/include/ha.h +++ b/include/ha.h @@ -14,56 +14,6 @@ namespace Ha { mac.add(WiFi.macAddress()); } - struct SensorConfig { - const char* name; - const char* uniqueId; - const char* deviceClass; - const char* unitMeasure; - const char* valueTemplate; - void buildConfig(char(&output)[JSON_SIZE], const char* stateTopic) { - StaticJsonDocument jsonDoc; - buildDeviceConfig(jsonDoc); - jsonDoc["device_class"] = deviceClass; - jsonDoc["name"] = name; - jsonDoc["unique_id"] = uniqueId; - jsonDoc["unit_of_measurement"] = unitMeasure; - jsonDoc["state_topic"] = stateTopic; - jsonDoc["value_template"] = valueTemplate; - serializeJson(jsonDoc, output); - } - - }; - - struct TemperatureConfig : SensorConfig { - TemperatureConfig(const char* name, const char* uniqueId) { - this->name = name; - this->uniqueId = uniqueId; - deviceClass = "temperature"; - unitMeasure = "°C"; - valueTemplate = "{{ value_json.temperature }}"; - } - }; - - struct PressureConfig : SensorConfig { - PressureConfig(const char* name, const char* uniqueId) { - this->name = name; - this->uniqueId = uniqueId; - this->deviceClass = "pressure"; - this->unitMeasure = "hPa"; - this->valueTemplate = "{{ value_json.pressure }}"; - } - }; - - struct AltitudeConfig : SensorConfig { - AltitudeConfig(const char* name, const char* uniqueId) { - this->name = name; - this->uniqueId = uniqueId; - this->deviceClass = "distance"; - this->unitMeasure = "m"; - this->valueTemplate = "{{ value_json.altitude }}"; - } - }; - void buildCommandConfig(char(&output)[JSON_SIZE], const char* name, const char* uniqueId, const char* commandTopic) { StaticJsonDocument jsonDoc; buildDeviceConfig(jsonDoc); @@ -72,4 +22,47 @@ namespace Ha { jsonDoc["command_topic"] = commandTopic; serializeJson(jsonDoc, output); } + + struct SensorConfig { + const char* deviceClass; + const char* unitMeasure; + const char* valueTemplate; + + void buildConfig(char(&output)[JSON_SIZE], const char* name, const char* uniqueId, const char* stateTopic) { + StaticJsonDocument jsonDoc; + buildDeviceConfig(jsonDoc); + jsonDoc["name"] = name; + jsonDoc["unique_id"] = uniqueId; + jsonDoc["state_topic"] = stateTopic; + jsonDoc["device_class"] = deviceClass; + jsonDoc["unit_of_measurement"] = unitMeasure; + jsonDoc["value_template"] = valueTemplate; + serializeJson(jsonDoc, output); + } + + }; + + struct TemperatureConfig : SensorConfig { + TemperatureConfig() { + deviceClass = "temperature"; + unitMeasure = "°C"; + valueTemplate = "{{ value_json.temperature }}"; + } + }; + + struct PressureConfig : SensorConfig { + PressureConfig() { + deviceClass = "pressure"; + unitMeasure = "hPa"; + valueTemplate = "{{ value_json.pressure }}"; + } + }; + + struct AltitudeConfig : SensorConfig { + AltitudeConfig() { + deviceClass = "distance"; + unitMeasure = "m"; + valueTemplate = "{{ value_json.altitude }}"; + } + }; } diff --git a/include/mqtt.h b/include/mqtt.h index c033754..5d2c8f4 100644 --- a/include/mqtt.h +++ b/include/mqtt.h @@ -51,19 +51,19 @@ namespace Mqtt { void publishTempConfig() { char message[JSON_SIZE]; - Ha::TemperatureConfig{ "Living room Temperature", "living_room_temperature" }.buildConfig(message, bmpTopic); + Ha::TemperatureConfig{}.buildConfig(message, "Living room Temperature", "living_room_temperature", bmpTopic); client.publish("homeassistant/sensor/esp_clock/temperature/config", 0, true, message); } void publishPressureConfig() { char message[JSON_SIZE]; - Ha::PressureConfig{ "Living room Pressure", "living_room_pressure" }.buildConfig(message, bmpTopic); + Ha::PressureConfig{}.buildConfig(message, "Living room Pressure", "living_room_pressure", bmpTopic); client.publish("homeassistant/sensor/esp_clock/pressure/config", 0, true, message); } void publishAltitudeConfig() { char message[JSON_SIZE]; - Ha::AltitudeConfig{ "Living room Altitude", "living_room_altitude" }.buildConfig(message, bmpTopic); + Ha::AltitudeConfig{}.buildConfig(message, "Living room Altitude", "living_room_altitude", bmpTopic); client.publish("homeassistant/sensor/esp_clock/altitude/config", 0, true, message); } From 04e4c6531bb6988acb7707455eb66b2b2e36068c Mon Sep 17 00:00:00 2001 From: Nicu Hodos Date: Sat, 8 Jul 2023 09:43:53 +0200 Subject: [PATCH 4/9] refactor building components' configuration --- .gitignore | 7 ++-- include/ha.h | 94 +++++++++++++++++++++++++++++++------------------- include/mqtt.h | 52 +++++++++------------------- 3 files changed, 77 insertions(+), 76 deletions(-) diff --git a/.gitignore b/.gitignore index d7ee03c..2cb2faa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,3 @@ -.pio -.vscode/.browse.c_cpp.db* -.vscode/c_cpp_properties.json -.vscode/launch.json -.vscode/ipch +.pio/ +.vscode/ credentials.h diff --git a/include/ha.h b/include/ha.h index 9f3a5fa..3b46d0d 100644 --- a/include/ha.h +++ b/include/ha.h @@ -4,62 +4,86 @@ namespace Ha { - void buildDeviceConfig(JsonDocument& jsonDoc) { - JsonObject device = jsonDoc.createNestedObject("device"); - device["name"] = "ESP Clock"; - device["suggested_area"] = "Living room"; - JsonArray connections = device.createNestedArray("connections"); - JsonArray mac = connections.createNestedArray(); - mac.add("mac"); - mac.add(WiFi.macAddress()); - } + struct Component { + const char* name; + const char* uniqueId; + const char* configTopic; - void buildCommandConfig(char(&output)[JSON_SIZE], const char* name, const char* uniqueId, const char* commandTopic) { - StaticJsonDocument jsonDoc; - buildDeviceConfig(jsonDoc); - jsonDoc["name"] = name; - jsonDoc["unique_id"] = uniqueId; - jsonDoc["command_topic"] = commandTopic; - serializeJson(jsonDoc, output); - } + Component(const char* name, const char* uniqueId, const char* configTopic) { + this->name = name; + this->uniqueId = uniqueId; + this->configTopic = configTopic; + } - struct SensorConfig { - const char* deviceClass; - const char* unitMeasure; - const char* valueTemplate; - - void buildConfig(char(&output)[JSON_SIZE], const char* name, const char* uniqueId, const char* stateTopic) { - StaticJsonDocument jsonDoc; + virtual void buildConfig(JsonDocument& jsonDoc) { buildDeviceConfig(jsonDoc); jsonDoc["name"] = name; jsonDoc["unique_id"] = uniqueId; - jsonDoc["state_topic"] = stateTopic; - jsonDoc["device_class"] = deviceClass; - jsonDoc["unit_of_measurement"] = unitMeasure; - jsonDoc["value_template"] = valueTemplate; - serializeJson(jsonDoc, output); + } + + void buildDeviceConfig(JsonDocument& jsonDoc) { + JsonObject device = jsonDoc.createNestedObject("device"); + device["name"] = "ESP Clock"; + device["suggested_area"] = "Living room"; + JsonArray connections = device.createNestedArray("connections"); + JsonArray mac = connections.createNestedArray(); + mac.add("mac"); + mac.add(WiFi.macAddress()); + } + }; + + struct Command : Component { + const char* commandTopic; + + Command(const char* name, const char* uniqueId, const char* configTopic, const char* commandTopic) : Component(name, uniqueId, configTopic) { + this->commandTopic = commandTopic; + } + + void buildConfig(JsonDocument& jsonDoc) { + Component::buildConfig(jsonDoc); + jsonDoc["command_topic"] = commandTopic; } }; - struct TemperatureConfig : SensorConfig { - TemperatureConfig() { + struct Sensor : Component { + const char* deviceClass; + const char* unitMeasure; + const char* valueTemplate; + const char* stateTopic; + + Sensor(const char* name, const char* uniqueId, const char* configTopic, const char* stateTopic) : Component(name, uniqueId, configTopic) { + this->stateTopic = stateTopic; + } + + void buildConfig(JsonDocument& jsonDoc) { + Component::buildConfig(jsonDoc); + jsonDoc["device_class"] = deviceClass; + jsonDoc["unit_of_measurement"] = unitMeasure; + jsonDoc["value_template"] = valueTemplate; + jsonDoc["state_topic"] = stateTopic; + } + + }; + + struct TemperatureSensor : Sensor { + TemperatureSensor(const char* name, const char* uniqueId, const char* configTopic, const char* stateTopic) : Sensor(name, uniqueId, configTopic, stateTopic) { deviceClass = "temperature"; unitMeasure = "°C"; valueTemplate = "{{ value_json.temperature }}"; } }; - struct PressureConfig : SensorConfig { - PressureConfig() { + struct PressureSensor : Sensor { + PressureSensor(const char* name, const char* uniqueId, const char* configTopic, const char* stateTopic) : Sensor(name, uniqueId, configTopic, stateTopic) { deviceClass = "pressure"; unitMeasure = "hPa"; valueTemplate = "{{ value_json.pressure }}"; } }; - struct AltitudeConfig : SensorConfig { - AltitudeConfig() { + struct AltitudeSensor : Sensor { + AltitudeSensor(const char* name, const char* uniqueId, const char* configTopic, const char* stateTopic) : Sensor(name, uniqueId, configTopic, stateTopic) { deviceClass = "distance"; unitMeasure = "m"; valueTemplate = "{{ value_json.altitude }}"; diff --git a/include/mqtt.h b/include/mqtt.h index 5d2c8f4..6ef9cd6 100644 --- a/include/mqtt.h +++ b/include/mqtt.h @@ -49,49 +49,29 @@ namespace Mqtt { client.disconnect(); } - void publishTempConfig() { - char message[JSON_SIZE]; - Ha::TemperatureConfig{}.buildConfig(message, "Living room Temperature", "living_room_temperature", bmpTopic); - client.publish("homeassistant/sensor/esp_clock/temperature/config", 0, true, message); - } + Ha::Component components[] = { + Ha::TemperatureSensor{"Living room Temperature", "living_room_temperature", "homeassistant/sensor/esp_clock/temperature/config", bmpTopic}, + Ha::PressureSensor{"Living room Pressure", "living_room_pressure", "homeassistant/sensor/esp_clock/pressure/config", bmpTopic}, + Ha::AltitudeSensor{"Living room Altitude", "living_room_altitude", "homeassistant/sensor/esp_clock/altitude/config", bmpTopic}, + Ha::Command{"Restart", "esp_clock_restart", "homeassistant/button/esp_clock/restart/config", restartTopic}, + Ha::Command{"ESP Clock Led", "esp_clock_led", "homeassistant/switch/esp_clock/led/config", ledTopic}, + Ha::Command{"ESP Clock Format 24h", "esp_clock_format_24h", "homeassistant/switch/esp_clock/hour_format/config", hourFormatTopic} + }; - void publishPressureConfig() { - char message[JSON_SIZE]; - Ha::PressureConfig{}.buildConfig(message, "Living room Pressure", "living_room_pressure", bmpTopic); - client.publish("homeassistant/sensor/esp_clock/pressure/config", 0, true, message); - } + void publishComponentConfig(Ha::Component& component) { + StaticJsonDocument jsonDoc; + component.buildConfig(jsonDoc); - void publishAltitudeConfig() { char message[JSON_SIZE]; - Ha::AltitudeConfig{}.buildConfig(message, "Living room Altitude", "living_room_altitude", bmpTopic); - client.publish("homeassistant/sensor/esp_clock/altitude/config", 0, true, message); - } + serializeJson(jsonDoc, message); - void publishRestartConfig() { - char message[JSON_SIZE]; - Ha::buildCommandConfig(message, "Restart", "esp_clock_restart", restartTopic); - client.publish("homeassistant/button/esp_clock/restart/config", 0, true, message); - } - - void publishLedConfig() { - char message[JSON_SIZE]; - Ha::buildCommandConfig(message, "ESP Clock Led", "esp_clock_led", ledTopic); - client.publish("homeassistant/switch/esp_clock/led/config", 0, true, message); - } - - void publishHourFormatConfig() { - char message[JSON_SIZE]; - Ha::buildCommandConfig(message, "ESP Clock Format 24h", "esp_clock_format_24h", hourFormatTopic); - client.publish("homeassistant/switch/esp_clock/hour_format/config", 0, true, message); + client.publish(component.configTopic, 0, true, message); } void publishConfig() { - publishTempConfig(); - publishPressureConfig(); - publishAltitudeConfig(); - publishRestartConfig(); - publishLedConfig(); - publishHourFormatConfig(); + for (Ha::Component cmp : components) { + publishComponentConfig(cmp); + } ts.deleteTask(tPublishConfig); } From 294eef45c6eb5242f8737b93c054f5ed4e70e149 Mon Sep 17 00:00:00 2001 From: Nicu Hodos Date: Sat, 8 Jul 2023 11:20:39 +0200 Subject: [PATCH 5/9] generalize components configuration --- include/ha.h | 4 +++- include/mqtt.h | 60 ++++++++++++++++++++++++++++---------------------- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/include/ha.h b/include/ha.h index 3b46d0d..4490d96 100644 --- a/include/ha.h +++ b/include/ha.h @@ -34,9 +34,11 @@ namespace Ha { struct Command : Component { const char* commandTopic; + void (*f)(const char* msg); - Command(const char* name, const char* uniqueId, const char* configTopic, const char* commandTopic) : Component(name, uniqueId, configTopic) { + Command(const char* name, const char* uniqueId, const char* configTopic, const char* commandTopic, void (*f)(const char* msg)) : Component(name, uniqueId, configTopic) { this->commandTopic = commandTopic; + this->f = f; } void buildConfig(JsonDocument& jsonDoc) { diff --git a/include/mqtt.h b/include/mqtt.h index 6ef9cd6..d151276 100644 --- a/include/mqtt.h +++ b/include/mqtt.h @@ -35,9 +35,6 @@ namespace Mqtt { } commands; const char* bmpTopic = "homeassistant/sensor/esp_clock/state"; - const char* restartTopic = "homeassistant/button/esp_clock/restart"; - const char* ledTopic = "homeassistant/switch/esp_clock/led/set"; - const char* hourFormatTopic = "homeassistant/switch/esp_clock/hour_format/set"; const char* espClockTopic = "homeassistant/+/esp_clock/#"; void connect() { @@ -49,13 +46,34 @@ namespace Mqtt { client.disconnect(); } - Ha::Component components[] = { + Ha::Sensor sensors[] = { Ha::TemperatureSensor{"Living room Temperature", "living_room_temperature", "homeassistant/sensor/esp_clock/temperature/config", bmpTopic}, Ha::PressureSensor{"Living room Pressure", "living_room_pressure", "homeassistant/sensor/esp_clock/pressure/config", bmpTopic}, - Ha::AltitudeSensor{"Living room Altitude", "living_room_altitude", "homeassistant/sensor/esp_clock/altitude/config", bmpTopic}, - Ha::Command{"Restart", "esp_clock_restart", "homeassistant/button/esp_clock/restart/config", restartTopic}, - Ha::Command{"ESP Clock Led", "esp_clock_led", "homeassistant/switch/esp_clock/led/config", ledTopic}, - Ha::Command{"ESP Clock Format 24h", "esp_clock_format_24h", "homeassistant/switch/esp_clock/hour_format/config", hourFormatTopic} + Ha::AltitudeSensor{"Living room Altitude", "living_room_altitude", "homeassistant/sensor/esp_clock/altitude/config", bmpTopic} + }; + + Ha::Command switches[] = { + Ha::Command{"Restart", "esp_clock_restart", "homeassistant/button/esp_clock/restart/config", "homeassistant/button/esp_clock/restart", + [](const char* msg) { + if (String { "PRESS" }.equals(msg)) ESP.restart(); + } + }, + Ha::Command{"ESP Clock Led", "esp_clock_led", "homeassistant/switch/esp_clock/led/config", "homeassistant/switch/esp_clock/led/set", + [](const char* msg) { + String{ "ON" }.equals(msg) ? digitalWrite(LED_BUILTIN, LOW) : digitalWrite(LED_BUILTIN, HIGH); + } + }, + Ha::Command{"ESP Clock Format 24h", "esp_clock_format_24h", "homeassistant/switch/esp_clock/hour_format/config", "homeassistant/switch/esp_clock/hour_format/set", + [](const char* msg) { + if (String{ "ON" }.equals(msg)) { + Display::hourFormat24 = true; + Display::drawTime(); + } else { + Display::hourFormat24 = false; + Display::drawTime(); + } + } + } }; void publishComponentConfig(Ha::Component& component) { @@ -69,7 +87,10 @@ namespace Mqtt { } void publishConfig() { - for (Ha::Component cmp : components) { + for (Ha::Component cmp : sensors) { + publishComponentConfig(cmp); + } + for (Ha::Component cmp : switches) { publishComponentConfig(cmp); } ts.deleteTask(tPublishConfig); @@ -102,23 +123,10 @@ namespace Mqtt { char msg[len + 1]; memcpy(msg, payload, len); msg[len] = 0; - if (String{ restartTopic }.equals(topic) && String { "PRESS" }.equals(msg)) { - ESP.restart(); - } - if (String{ ledTopic }.equals(topic)) { - if (String{ "ON" }.equals(msg)) { - digitalWrite(LED_BUILTIN, LOW); - } else { - digitalWrite(LED_BUILTIN, HIGH); - } - } - if (String{ hourFormatTopic }.equals(topic)) { - if (String{ "ON" }.equals(msg)) { - Display::hourFormat24 = true; - Display::drawTime(); - } else { - Display::hourFormat24 = false; - Display::drawTime(); + for (Ha::Command cmd : switches) { + if (String{ cmd.commandTopic }.equals(topic)) { + cmd.f(msg); + return; } } } From 7e99bafff91f01f02e4b0e4012831e5632a14957 Mon Sep 17 00:00:00 2001 From: Nicu Hodos Date: Sat, 8 Jul 2023 11:52:43 +0200 Subject: [PATCH 6/9] use typedef for function --- include/ha.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/ha.h b/include/ha.h index 4490d96..c577006 100644 --- a/include/ha.h +++ b/include/ha.h @@ -32,11 +32,12 @@ namespace Ha { } }; + typedef void (*onMessage)(const char* msg); struct Command : Component { const char* commandTopic; - void (*f)(const char* msg); + onMessage f; - Command(const char* name, const char* uniqueId, const char* configTopic, const char* commandTopic, void (*f)(const char* msg)) : Component(name, uniqueId, configTopic) { + Command(const char* name, const char* uniqueId, const char* configTopic, const char* commandTopic, onMessage f) : Component(name, uniqueId, configTopic) { this->commandTopic = commandTopic; this->f = f; } From 65f7919ed9306822054f9785d2afd29de6ea98c2 Mon Sep 17 00:00:00 2001 From: Nicu Hodos Date: Sat, 8 Jul 2023 14:21:07 +0200 Subject: [PATCH 7/9] standardize components configuration --- include/ha.h | 41 +++++++++++++++++++++++++++++------------ include/mqtt.h | 15 +++++++-------- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/include/ha.h b/include/ha.h index c577006..e4345bb 100644 --- a/include/ha.h +++ b/include/ha.h @@ -1,18 +1,19 @@ #include #define JSON_SIZE 512 +#define TOPIC_SIZE 255 namespace Ha { struct Component { const char* name; const char* uniqueId; - const char* configTopic; + char configTopic[TOPIC_SIZE]; - Component(const char* name, const char* uniqueId, const char* configTopic) { + Component(const char* name, const char* uniqueId, const char* topic, const char* type) { this->name = name; this->uniqueId = uniqueId; - this->configTopic = configTopic; + sprintf(configTopic, "homeassistant/%s/esp_clock/%s/config", type, topic); } virtual void buildConfig(JsonDocument& jsonDoc) { @@ -34,11 +35,10 @@ namespace Ha { typedef void (*onMessage)(const char* msg); struct Command : Component { - const char* commandTopic; + char commandTopic[TOPIC_SIZE]; onMessage f; - Command(const char* name, const char* uniqueId, const char* configTopic, const char* commandTopic, onMessage f) : Component(name, uniqueId, configTopic) { - this->commandTopic = commandTopic; + Command(const char* name, const char* uniqueId, const char* topic, const char* type, onMessage f) : Component(name, uniqueId, topic, type) { this->f = f; } @@ -49,14 +49,31 @@ namespace Ha { }; + struct Button : Command { + static constexpr const char* type = "button"; + + Button(const char* name, const char* uniqueId, const char* topic, onMessage f) : Command(name, uniqueId, topic, type, f) { + sprintf(commandTopic, "homeassistant/%s/esp_clock/%s", type, topic); + } + + }; + + struct Switch : Command { + static constexpr const char* type = "switch"; + + Switch(const char* name, const char* uniqueId, const char* topic, onMessage f) : Command(name, uniqueId, topic, type, f) { + sprintf(commandTopic, "homeassistant/%s/esp_clock/%s/set", type, topic); + } + + }; + struct Sensor : Component { const char* deviceClass; const char* unitMeasure; const char* valueTemplate; - const char* stateTopic; + static constexpr const char* stateTopic = "homeassistant/sensor/esp_clock/state"; - Sensor(const char* name, const char* uniqueId, const char* configTopic, const char* stateTopic) : Component(name, uniqueId, configTopic) { - this->stateTopic = stateTopic; + Sensor(const char* name, const char* uniqueId, const char* topic) : Component(name, uniqueId, topic, "sensor") { } void buildConfig(JsonDocument& jsonDoc) { @@ -70,7 +87,7 @@ namespace Ha { }; struct TemperatureSensor : Sensor { - TemperatureSensor(const char* name, const char* uniqueId, const char* configTopic, const char* stateTopic) : Sensor(name, uniqueId, configTopic, stateTopic) { + TemperatureSensor(const char* name, const char* uniqueId, const char* topic) : Sensor(name, uniqueId, topic) { deviceClass = "temperature"; unitMeasure = "°C"; valueTemplate = "{{ value_json.temperature }}"; @@ -78,7 +95,7 @@ namespace Ha { }; struct PressureSensor : Sensor { - PressureSensor(const char* name, const char* uniqueId, const char* configTopic, const char* stateTopic) : Sensor(name, uniqueId, configTopic, stateTopic) { + PressureSensor(const char* name, const char* uniqueId, const char* topic) : Sensor(name, uniqueId, topic) { deviceClass = "pressure"; unitMeasure = "hPa"; valueTemplate = "{{ value_json.pressure }}"; @@ -86,7 +103,7 @@ namespace Ha { }; struct AltitudeSensor : Sensor { - AltitudeSensor(const char* name, const char* uniqueId, const char* configTopic, const char* stateTopic) : Sensor(name, uniqueId, configTopic, stateTopic) { + AltitudeSensor(const char* name, const char* uniqueId, const char* topic) : Sensor(name, uniqueId, topic) { deviceClass = "distance"; unitMeasure = "m"; valueTemplate = "{{ value_json.altitude }}"; diff --git a/include/mqtt.h b/include/mqtt.h index d151276..8848560 100644 --- a/include/mqtt.h +++ b/include/mqtt.h @@ -34,7 +34,6 @@ namespace Mqtt { } } commands; - const char* bmpTopic = "homeassistant/sensor/esp_clock/state"; const char* espClockTopic = "homeassistant/+/esp_clock/#"; void connect() { @@ -47,23 +46,23 @@ namespace Mqtt { } Ha::Sensor sensors[] = { - Ha::TemperatureSensor{"Living room Temperature", "living_room_temperature", "homeassistant/sensor/esp_clock/temperature/config", bmpTopic}, - Ha::PressureSensor{"Living room Pressure", "living_room_pressure", "homeassistant/sensor/esp_clock/pressure/config", bmpTopic}, - Ha::AltitudeSensor{"Living room Altitude", "living_room_altitude", "homeassistant/sensor/esp_clock/altitude/config", bmpTopic} + Ha::TemperatureSensor{"Living room Temperature", "living_room_temperature", "temperature"}, + Ha::PressureSensor{"Living room Pressure", "living_room_pressure", "pressure"}, + Ha::AltitudeSensor{"Living room Altitude", "living_room_altitude", "altitude"} }; Ha::Command switches[] = { - Ha::Command{"Restart", "esp_clock_restart", "homeassistant/button/esp_clock/restart/config", "homeassistant/button/esp_clock/restart", + Ha::Button{"ESP Clock Restart", "esp_clock_restart", "restart", [](const char* msg) { if (String { "PRESS" }.equals(msg)) ESP.restart(); } }, - Ha::Command{"ESP Clock Led", "esp_clock_led", "homeassistant/switch/esp_clock/led/config", "homeassistant/switch/esp_clock/led/set", + Ha::Switch{"ESP Clock Led", "esp_clock_led", "led", [](const char* msg) { String{ "ON" }.equals(msg) ? digitalWrite(LED_BUILTIN, LOW) : digitalWrite(LED_BUILTIN, HIGH); } }, - Ha::Command{"ESP Clock Format 24h", "esp_clock_format_24h", "homeassistant/switch/esp_clock/hour_format/config", "homeassistant/switch/esp_clock/hour_format/set", + Ha::Switch{"ESP Clock Format 24h", "esp_clock_format_24h", "hour_format", [](const char* msg) { if (String{ "ON" }.equals(msg)) { Display::hourFormat24 = true; @@ -104,7 +103,7 @@ namespace Mqtt { jsonDoc["altitude"] = Bmp::data.altitude; char message[255]; serializeJson(jsonDoc, message); - client.publish(bmpTopic, 0, true, message); + client.publish(Ha::Sensor::stateTopic, 0, true, message); } void publishCommand() { From acf009dbe820aa811d1ee5e06a4aed906ffd0230 Mon Sep 17 00:00:00 2001 From: Nicu Hodos Date: Sat, 8 Jul 2023 14:52:46 +0200 Subject: [PATCH 8/9] fix virtual function not being called --- include/ha.h | 4 ++-- include/mqtt.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/ha.h b/include/ha.h index e4345bb..3fd5cfb 100644 --- a/include/ha.h +++ b/include/ha.h @@ -42,7 +42,7 @@ namespace Ha { this->f = f; } - void buildConfig(JsonDocument& jsonDoc) { + void buildConfig(JsonDocument& jsonDoc) override { Component::buildConfig(jsonDoc); jsonDoc["command_topic"] = commandTopic; } @@ -76,7 +76,7 @@ namespace Ha { Sensor(const char* name, const char* uniqueId, const char* topic) : Component(name, uniqueId, topic, "sensor") { } - void buildConfig(JsonDocument& jsonDoc) { + void buildConfig(JsonDocument& jsonDoc) override { Component::buildConfig(jsonDoc); jsonDoc["device_class"] = deviceClass; jsonDoc["unit_of_measurement"] = unitMeasure; diff --git a/include/mqtt.h b/include/mqtt.h index 8848560..900506c 100644 --- a/include/mqtt.h +++ b/include/mqtt.h @@ -86,10 +86,10 @@ namespace Mqtt { } void publishConfig() { - for (Ha::Component cmp : sensors) { + for (Ha::Component& cmp : sensors) { publishComponentConfig(cmp); } - for (Ha::Component cmp : switches) { + for (Ha::Component& cmp : switches) { publishComponentConfig(cmp); } ts.deleteTask(tPublishConfig); From d3d04721e98e47d23ff34771f4b047f0f0747d01 Mon Sep 17 00:00:00 2001 From: Nicu Hodos Date: Sat, 8 Jul 2023 15:41:44 +0200 Subject: [PATCH 9/9] generate uniqueId from id --- include/ha.h | 38 +++++++++++++++++++++++++------------- include/mqtt.h | 12 ++++++------ 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/include/ha.h b/include/ha.h index 3fd5cfb..3b72509 100644 --- a/include/ha.h +++ b/include/ha.h @@ -7,18 +7,22 @@ namespace Ha { struct Component { const char* name; - const char* uniqueId; + const char* id; char configTopic[TOPIC_SIZE]; - Component(const char* name, const char* uniqueId, const char* topic, const char* type) { + Component(const char* name, const char* id, const char* type) { this->name = name; - this->uniqueId = uniqueId; - sprintf(configTopic, "homeassistant/%s/esp_clock/%s/config", type, topic); + this->id = id; + sprintf(configTopic, "homeassistant/%s/esp_clock/%s/config", type, id); } + virtual void buildUniqueId(char* uniqueId) = 0; + virtual void buildConfig(JsonDocument& jsonDoc) { buildDeviceConfig(jsonDoc); jsonDoc["name"] = name; + char uniqueId[50]; + buildUniqueId(uniqueId); jsonDoc["unique_id"] = uniqueId; } @@ -38,10 +42,14 @@ namespace Ha { char commandTopic[TOPIC_SIZE]; onMessage f; - Command(const char* name, const char* uniqueId, const char* topic, const char* type, onMessage f) : Component(name, uniqueId, topic, type) { + Command(const char* name, const char* id, const char* type, onMessage f) : Component(name, id, type) { this->f = f; } + void buildUniqueId(char* uniqueId) override { + sprintf(uniqueId, "esp_clock_%s", id); + } + void buildConfig(JsonDocument& jsonDoc) override { Component::buildConfig(jsonDoc); jsonDoc["command_topic"] = commandTopic; @@ -52,8 +60,8 @@ namespace Ha { struct Button : Command { static constexpr const char* type = "button"; - Button(const char* name, const char* uniqueId, const char* topic, onMessage f) : Command(name, uniqueId, topic, type, f) { - sprintf(commandTopic, "homeassistant/%s/esp_clock/%s", type, topic); + Button(const char* name, const char* id, onMessage f) : Command(name, id, type, f) { + sprintf(commandTopic, "homeassistant/%s/esp_clock/%s", type, id); } }; @@ -61,8 +69,8 @@ namespace Ha { struct Switch : Command { static constexpr const char* type = "switch"; - Switch(const char* name, const char* uniqueId, const char* topic, onMessage f) : Command(name, uniqueId, topic, type, f) { - sprintf(commandTopic, "homeassistant/%s/esp_clock/%s/set", type, topic); + Switch(const char* name, const char* id, onMessage f) : Command(name, id, type, f) { + sprintf(commandTopic, "homeassistant/%s/esp_clock/%s/set", type, id); } }; @@ -73,7 +81,11 @@ namespace Ha { const char* valueTemplate; static constexpr const char* stateTopic = "homeassistant/sensor/esp_clock/state"; - Sensor(const char* name, const char* uniqueId, const char* topic) : Component(name, uniqueId, topic, "sensor") { + Sensor(const char* name, const char* id) : Component(name, id, "sensor") { + } + + void buildUniqueId(char* uniqueId) override { + sprintf(uniqueId, "living_room_%s", id); } void buildConfig(JsonDocument& jsonDoc) override { @@ -87,7 +99,7 @@ namespace Ha { }; struct TemperatureSensor : Sensor { - TemperatureSensor(const char* name, const char* uniqueId, const char* topic) : Sensor(name, uniqueId, topic) { + TemperatureSensor(const char* name, const char* id) : Sensor(name, id) { deviceClass = "temperature"; unitMeasure = "°C"; valueTemplate = "{{ value_json.temperature }}"; @@ -95,7 +107,7 @@ namespace Ha { }; struct PressureSensor : Sensor { - PressureSensor(const char* name, const char* uniqueId, const char* topic) : Sensor(name, uniqueId, topic) { + PressureSensor(const char* name, const char* id) : Sensor(name, id) { deviceClass = "pressure"; unitMeasure = "hPa"; valueTemplate = "{{ value_json.pressure }}"; @@ -103,7 +115,7 @@ namespace Ha { }; struct AltitudeSensor : Sensor { - AltitudeSensor(const char* name, const char* uniqueId, const char* topic) : Sensor(name, uniqueId, topic) { + AltitudeSensor(const char* name, const char* id) : Sensor(name, id) { deviceClass = "distance"; unitMeasure = "m"; valueTemplate = "{{ value_json.altitude }}"; diff --git a/include/mqtt.h b/include/mqtt.h index 900506c..b8f8e4b 100644 --- a/include/mqtt.h +++ b/include/mqtt.h @@ -46,23 +46,23 @@ namespace Mqtt { } Ha::Sensor sensors[] = { - Ha::TemperatureSensor{"Living room Temperature", "living_room_temperature", "temperature"}, - Ha::PressureSensor{"Living room Pressure", "living_room_pressure", "pressure"}, - Ha::AltitudeSensor{"Living room Altitude", "living_room_altitude", "altitude"} + Ha::TemperatureSensor{"Living room Temperature", "temperature"}, + Ha::PressureSensor{"Living room Pressure", "pressure"}, + Ha::AltitudeSensor{"Living room Altitude", "altitude"} }; Ha::Command switches[] = { - Ha::Button{"ESP Clock Restart", "esp_clock_restart", "restart", + Ha::Button{"ESP Clock Restart", "restart", [](const char* msg) { if (String { "PRESS" }.equals(msg)) ESP.restart(); } }, - Ha::Switch{"ESP Clock Led", "esp_clock_led", "led", + Ha::Switch{"ESP Clock Led", "led", [](const char* msg) { String{ "ON" }.equals(msg) ? digitalWrite(LED_BUILTIN, LOW) : digitalWrite(LED_BUILTIN, HIGH); } }, - Ha::Switch{"ESP Clock Format 24h", "esp_clock_format_24h", "hour_format", + Ha::Switch{"ESP Clock Format 24h", "format_24h", [](const char* msg) { if (String{ "ON" }.equals(msg)) { Display::hourFormat24 = true;