From c2cc10c2cd86d1c3fe346d09a68c900e4897832b Mon Sep 17 00:00:00 2001 From: Nicu Hodos Date: Sun, 9 Jul 2023 19:48:00 +0200 Subject: [PATCH 1/5] change brightness over MQTT --- include/display.h | 19 ++++++++++++------- include/ha.h | 17 +++++++++++++++++ include/mqtt.h | 35 ++++++++++++++++++++--------------- 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/include/display.h b/include/display.h index 60a53b0..c61e68a 100644 --- a/include/display.h +++ b/include/display.h @@ -7,9 +7,11 @@ #include "ntp_time.h" #define DISPLAY_ADDRESS 0x70 -#define BRIGHTNESS_NIGHT 0 -#define BRIGHTNESS_DAY 11 +#define BRIGHTNESS_MIN 0 +#define BRIGHTNESS_MAX 15 #define BRIGHTNESS_STEP 1 +#define BRIGHTNESS_NIGHT BRIGHTNESS_MIN +#define BRIGHTNESS_DAY 11 #define DISPLAY_TIME 2000 #define DISPLAY_TEMP_TIME 5000 @@ -45,18 +47,21 @@ namespace Display { } } - void changeBrightness(bool increase) { - increase ? brightness = (brightness + BRIGHTNESS_STEP) % 15 : brightness = (brightness - BRIGHTNESS_STEP) % 15; + void setBrightness(unsigned int value) { + brightness = value % (BRIGHTNESS_MAX+1); clockDisplay.setBrightness(brightness); } + void changeBrightness(bool increase) { + increase ? setBrightness(brightness + BRIGHTNESS_STEP) : setBrightness(brightness - BRIGHTNESS_STEP); + } + void adjustBrightness() { if (currentHour > 8 && currentHour < 17) { - brightness = BRIGHTNESS_DAY; + setBrightness(BRIGHTNESS_DAY); } else { - brightness = BRIGHTNESS_NIGHT; + setBrightness(BRIGHTNESS_NIGHT); } - clockDisplay.setBrightness(brightness); } void drawColon(bool colonOn) { diff --git a/include/ha.h b/include/ha.h index 3b72509..0adaf5e 100644 --- a/include/ha.h +++ b/include/ha.h @@ -1,4 +1,5 @@ #include +#include "display.h" #define JSON_SIZE 512 #define TOPIC_SIZE 255 @@ -75,6 +76,22 @@ namespace Ha { }; + struct Brightness : Command { + static constexpr const char* type = "number"; + + Brightness(const char* name, const char* id, onMessage f) : Command(name, id, type, f) { + sprintf(commandTopic, "homeassistant/%s/esp_clock/%s", type, id); + } + + void buildConfig(JsonDocument& jsonDoc) override { + Command::buildConfig(jsonDoc); + jsonDoc["min"] = BRIGHTNESS_MIN; + jsonDoc["max"] = BRIGHTNESS_MAX; + jsonDoc["step"] = BRIGHTNESS_STEP; + } + + }; + struct Sensor : Component { const char* deviceClass; const char* unitMeasure; diff --git a/include/mqtt.h b/include/mqtt.h index b8f8e4b..09c36dc 100644 --- a/include/mqtt.h +++ b/include/mqtt.h @@ -45,24 +45,24 @@ namespace Mqtt { client.disconnect(); } - Ha::Sensor sensors[] = { - Ha::TemperatureSensor{"Living room Temperature", "temperature"}, - Ha::PressureSensor{"Living room Pressure", "pressure"}, - Ha::AltitudeSensor{"Living room Altitude", "altitude"} + Ha::Sensor* sensors[] = { + new Ha::TemperatureSensor{"Living room Temperature", "temperature"}, + new Ha::PressureSensor{"Living room Pressure", "pressure"}, + new Ha::AltitudeSensor{"Living room Altitude", "altitude"} }; - Ha::Command switches[] = { - Ha::Button{"ESP Clock Restart", "restart", + Ha::Command* switches[] = { + new Ha::Button{"ESP Clock Restart", "restart", [](const char* msg) { if (String { "PRESS" }.equals(msg)) ESP.restart(); } }, - Ha::Switch{"ESP Clock Led", "led", + new 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", "format_24h", + new Ha::Switch{"ESP Clock Format 24h", "format_24h", [](const char* msg) { if (String{ "ON" }.equals(msg)) { Display::hourFormat24 = true; @@ -72,6 +72,11 @@ namespace Mqtt { Display::drawTime(); } } + }, + new Ha::Brightness{"ESP Clock Brightness", "brightness", + [](const char* msg) { + Display::setBrightness(String{ msg }.toInt()); + } } }; @@ -86,11 +91,11 @@ namespace Mqtt { } void publishConfig() { - for (Ha::Component& cmp : sensors) { - publishComponentConfig(cmp); + for (Ha::Component* cmp : sensors) { + publishComponentConfig(*cmp); } - for (Ha::Component& cmp : switches) { - publishComponentConfig(cmp); + for (Ha::Component* cmp : switches) { + publishComponentConfig(*cmp); } ts.deleteTask(tPublishConfig); } @@ -122,9 +127,9 @@ namespace Mqtt { char msg[len + 1]; memcpy(msg, payload, len); msg[len] = 0; - for (Ha::Command cmd : switches) { - if (String{ cmd.commandTopic }.equals(topic)) { - cmd.f(msg); + for (Ha::Command* cmd : switches) { + if (String{ cmd->commandTopic }.equals(topic)) { + cmd->f(msg); return; } } From ad955e5a7dcec6b6fc5e587e79320c9f805afb89 Mon Sep 17 00:00:00 2001 From: Nicu Hodos Date: Mon, 10 Jul 2023 00:01:40 +0200 Subject: [PATCH 2/5] publish brightness changes on MQTT --- include/bmp.h | 2 ++ include/display.h | 14 ++++++++++++-- include/ha.h | 11 +++++++++++ include/mqtt.h | 29 ++++++++++++++++++++++++----- src/esp_clock.cpp | 2 +- 5 files changed, 50 insertions(+), 8 deletions(-) diff --git a/include/bmp.h b/include/bmp.h index 5ce8f40..95c4ade 100644 --- a/include/bmp.h +++ b/include/bmp.h @@ -1,3 +1,5 @@ +#pragma once + #include namespace Bmp { diff --git a/include/display.h b/include/display.h index c61e68a..c193fff 100644 --- a/include/display.h +++ b/include/display.h @@ -5,6 +5,7 @@ #include #include #include "ntp_time.h" +#include "mqtt.h" #define DISPLAY_ADDRESS 0x70 #define BRIGHTNESS_MIN 0 @@ -15,6 +16,13 @@ #define DISPLAY_TIME 2000 #define DISPLAY_TEMP_TIME 5000 +namespace Mqtt { + void publishBrightness(); + bool connected(); +} + +Task tPublishBrightness(TASK_IMMEDIATE, TASK_ONCE, Mqtt::publishBrightness, &ts, false, Mqtt::connected); + namespace Display { void displayColon(); @@ -47,16 +55,17 @@ namespace Display { } } - void setBrightness(unsigned int value) { + void setBrightness(uint8_t value) { brightness = value % (BRIGHTNESS_MAX+1); clockDisplay.setBrightness(brightness); + tPublishBrightness.restart(); } void changeBrightness(bool increase) { increase ? setBrightness(brightness + BRIGHTNESS_STEP) : setBrightness(brightness - BRIGHTNESS_STEP); } - void adjustBrightness() { + void updateBrightness() { if (currentHour > 8 && currentHour < 17) { setBrightness(BRIGHTNESS_DAY); } else { @@ -68,6 +77,7 @@ namespace Display { if (colonOn) { if (currentHour != hour()) { currentHour = hour(); + updateBrightness(); if (currentHour == 8) Wifi::reconnect(); } if (currentMin != minute()) { diff --git a/include/ha.h b/include/ha.h index 0adaf5e..3e7a7b7 100644 --- a/include/ha.h +++ b/include/ha.h @@ -1,3 +1,5 @@ +#pragma once + #include #include "display.h" @@ -9,11 +11,13 @@ namespace Ha { struct Component { const char* name; const char* id; + const char* type; char configTopic[TOPIC_SIZE]; Component(const char* name, const char* id, const char* type) { this->name = name; this->id = id; + this->type = type; sprintf(configTopic, "homeassistant/%s/esp_clock/%s/config", type, id); } @@ -41,6 +45,7 @@ namespace Ha { typedef void (*onMessage)(const char* msg); struct Command : Component { char commandTopic[TOPIC_SIZE]; + char stateTopic[TOPIC_SIZE]; onMessage f; Command(const char* name, const char* id, const char* type, onMessage f) : Component(name, id, type) { @@ -54,6 +59,12 @@ namespace Ha { void buildConfig(JsonDocument& jsonDoc) override { Component::buildConfig(jsonDoc); jsonDoc["command_topic"] = commandTopic; + if (stateTopic[0]) jsonDoc["state_topic"] = stateTopic; + } + + Command* withStateTopic() { + sprintf(stateTopic, "homeassistant/%s/esp_clock/%s/state", type, id); + return this; } }; diff --git a/include/mqtt.h b/include/mqtt.h index 09c36dc..f4a8190 100644 --- a/include/mqtt.h +++ b/include/mqtt.h @@ -1,7 +1,11 @@ +#pragma once + #include #include #include #include "ha.h" +#include "bmp.h" +#include "display.h" #define MQTT_HOST IPAddress(192, 168, 5, 11) #define MQTT_PORT 1883 @@ -36,6 +40,10 @@ namespace Mqtt { const char* espClockTopic = "homeassistant/+/esp_clock/#"; + bool connected() { + return client.connected(); + } + void connect() { client.connect(); } @@ -51,6 +59,12 @@ namespace Mqtt { new Ha::AltitudeSensor{"Living room Altitude", "altitude"} }; + Ha::Command* brightnessMqtt = (new Ha::Brightness{ "ESP Clock Brightness", "brightness", + [](const char* msg) { + Display::setBrightness(String{ msg }.toInt()); + } + })->withStateTopic(); + Ha::Command* switches[] = { new Ha::Button{"ESP Clock Restart", "restart", [](const char* msg) { @@ -73,11 +87,7 @@ namespace Mqtt { } } }, - new Ha::Brightness{"ESP Clock Brightness", "brightness", - [](const char* msg) { - Display::setBrightness(String{ msg }.toInt()); - } - } + brightnessMqtt }; void publishComponentConfig(Ha::Component& component) { @@ -97,6 +107,7 @@ namespace Mqtt { for (Ha::Component* cmp : switches) { publishComponentConfig(*cmp); } + // publishBrightness(Display::brightness); ts.deleteTask(tPublishConfig); } @@ -111,6 +122,12 @@ namespace Mqtt { client.publish(Ha::Sensor::stateTopic, 0, true, message); } + void publishBrightness() { + char message[32]; + sprintf(message, "%X", Display::brightness); + client.publish(brightnessMqtt->stateTopic, 0, true, message); + } + void publishCommand() { if (uint8_t cmd = commands.getCurrent()) { char message[32]; @@ -140,6 +157,7 @@ namespace Mqtt { tPublishConfig.enable(); tPublishBmp.enableIfNot(); tPublishCommand.enableDelayed(); + tPublishBrightness.enable(); client.subscribe(espClockTopic, 0); tReConnect.disable(); Serial.println("Connected to MQTT"); @@ -148,6 +166,7 @@ namespace Mqtt { tReConnect.enableDelayed(); tPublishCommand.disable(); tPublishBmp.disable(); + tPublishBrightness.disable(); Serial.println("Disconnected from MQTT"); }); client.onMessage(onMessage); diff --git a/src/esp_clock.cpp b/src/esp_clock.cpp index b8708af..da8f654 100644 --- a/src/esp_clock.cpp +++ b/src/esp_clock.cpp @@ -12,10 +12,10 @@ Task tWifiConnected(TASK_IMMEDIATE, TASK_ONCE, onWifiConnected, &ts); Task tButton(TASK_IMMEDIATE, TASK_ONCE, onButtonCallback, &ts); #include "wifi.h" +#include "mqtt.h" #include "display.h" #include "bmp.h" #include "ntp_time.h" -#include "mqtt.h" #include "ota.h" #include "ir.h" From b2952cb6a29091820d5317675bd4ad8fec1a4894 Mon Sep 17 00:00:00 2001 From: Nicu Hodos Date: Mon, 10 Jul 2023 13:28:27 +0200 Subject: [PATCH 3/5] rename displayColumn --- include/display.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/include/display.h b/include/display.h index c193fff..e4344d6 100644 --- a/include/display.h +++ b/include/display.h @@ -25,10 +25,9 @@ Task tPublishBrightness(TASK_IMMEDIATE, TASK_ONCE, Mqtt::publishBrightness, &ts, namespace Display { - void displayColon(); - Task tDisplay(500, TASK_FOREVER, displayColon, &ts, true); + void display(); + Task tDisplay(500, TASK_FOREVER, display, &ts, true); - uint8_t brightness = BRIGHTNESS_NIGHT; int currentHour = -1; int currentMin = -1; bool hourFormat24 = false; @@ -88,7 +87,7 @@ namespace Display { clockDisplay.drawColon(colonOn); } - void displayColon() { + void display() { static bool colonOn = false; drawColon(colonOn); @@ -128,6 +127,6 @@ namespace Display { clockDisplay.begin(DISPLAY_ADDRESS); clockDisplay.setBrightness(brightness); drawTime(); - displayColon(); + display(); } } From 58d60c02b8379d1b6f3408d2ca6fd260fbe4e98e Mon Sep 17 00:00:00 2001 From: Nicu Hodos Date: Mon, 10 Jul 2023 13:30:59 +0200 Subject: [PATCH 4/5] brightness: - use callback for when brightness is updated - avoid dependency on mqtt - encapsulate brigthness in its own namespace - improve readability --- include/display.h | 53 ++++++++++++++++++++++------------------------- include/mqtt.h | 34 +++++++++++++++--------------- 2 files changed, 42 insertions(+), 45 deletions(-) diff --git a/include/display.h b/include/display.h index e4344d6..d10b8ca 100644 --- a/include/display.h +++ b/include/display.h @@ -5,7 +5,6 @@ #include #include #include "ntp_time.h" -#include "mqtt.h" #define DISPLAY_ADDRESS 0x70 #define BRIGHTNESS_MIN 0 @@ -16,13 +15,6 @@ #define DISPLAY_TIME 2000 #define DISPLAY_TEMP_TIME 5000 -namespace Mqtt { - void publishBrightness(); - bool connected(); -} - -Task tPublishBrightness(TASK_IMMEDIATE, TASK_ONCE, Mqtt::publishBrightness, &ts, false, Mqtt::connected); - namespace Display { void display(); @@ -35,6 +27,29 @@ namespace Display { // Create display object Adafruit_7segment clockDisplay = Adafruit_7segment(); + namespace Brightness { + uint8_t current = BRIGHTNESS_NIGHT; + void (*brightnessChangedCallback)(); + + void set(uint8_t value) { + current = value % (BRIGHTNESS_MAX + 1); + clockDisplay.setBrightness(current); + brightnessChangedCallback(); + } + + void onChanged(void (*f)()) { + brightnessChangedCallback = f; + } + + void change(bool increase) { + increase ? set(current + BRIGHTNESS_STEP) : set(current - BRIGHTNESS_STEP); + } + + void update() { + currentHour > 8 && currentHour < 17 ? set(BRIGHTNESS_DAY) : set(BRIGHTNESS_NIGHT); + } + } + void drawTime() { int displayHour = hourFormat24 ? hour() : hourFormat12(); int displayMinute = minute(); @@ -54,29 +69,11 @@ namespace Display { } } - void setBrightness(uint8_t value) { - brightness = value % (BRIGHTNESS_MAX+1); - clockDisplay.setBrightness(brightness); - tPublishBrightness.restart(); - } - - void changeBrightness(bool increase) { - increase ? setBrightness(brightness + BRIGHTNESS_STEP) : setBrightness(brightness - BRIGHTNESS_STEP); - } - - void updateBrightness() { - if (currentHour > 8 && currentHour < 17) { - setBrightness(BRIGHTNESS_DAY); - } else { - setBrightness(BRIGHTNESS_NIGHT); - } - } - void drawColon(bool colonOn) { if (colonOn) { if (currentHour != hour()) { currentHour = hour(); - updateBrightness(); + Brightness::update(); if (currentHour == 8) Wifi::reconnect(); } if (currentMin != minute()) { @@ -125,7 +122,7 @@ namespace Display { void setup() { clockDisplay.begin(DISPLAY_ADDRESS); - clockDisplay.setBrightness(brightness); + clockDisplay.setBrightness(Brightness::current); drawTime(); display(); } diff --git a/include/mqtt.h b/include/mqtt.h index f4a8190..b8fb634 100644 --- a/include/mqtt.h +++ b/include/mqtt.h @@ -40,10 +40,6 @@ namespace Mqtt { const char* espClockTopic = "homeassistant/+/esp_clock/#"; - bool connected() { - return client.connected(); - } - void connect() { client.connect(); } @@ -61,7 +57,7 @@ namespace Mqtt { Ha::Command* brightnessMqtt = (new Ha::Brightness{ "ESP Clock Brightness", "brightness", [](const char* msg) { - Display::setBrightness(String{ msg }.toInt()); + Display::Brightness::set(String{ msg }.toInt()); } })->withStateTopic(); @@ -90,6 +86,10 @@ namespace Mqtt { brightnessMqtt }; + uint16_t publish(const char* topic, const char* message) { + return client.publish(topic, 0, true, message); + } + void publishComponentConfig(Ha::Component& component) { StaticJsonDocument jsonDoc; component.buildConfig(jsonDoc); @@ -97,7 +97,14 @@ namespace Mqtt { char message[JSON_SIZE]; serializeJson(jsonDoc, message); - client.publish(component.configTopic, 0, true, message); + publish(component.configTopic, message); + } + + void publishBrightness() { + if (!client.connected()) return ; + char message[32]; + sprintf(message, "%u", Display::Brightness::current); + publish(brightnessMqtt->stateTopic, message); } void publishConfig() { @@ -107,7 +114,7 @@ namespace Mqtt { for (Ha::Component* cmp : switches) { publishComponentConfig(*cmp); } - // publishBrightness(Display::brightness); + publishBrightness(); ts.deleteTask(tPublishConfig); } @@ -119,20 +126,14 @@ namespace Mqtt { jsonDoc["altitude"] = Bmp::data.altitude; char message[255]; serializeJson(jsonDoc, message); - client.publish(Ha::Sensor::stateTopic, 0, true, message); - } - - void publishBrightness() { - char message[32]; - sprintf(message, "%X", Display::brightness); - client.publish(brightnessMqtt->stateTopic, 0, true, message); + publish(Ha::Sensor::stateTopic, message); } void publishCommand() { if (uint8_t cmd = commands.getCurrent()) { char message[32]; sprintf(message, "%X", cmd); - if (client.publish(commands.topic, 0, true, message) != 0) { + if (publish(commands.topic, message) != 0) { Serial.print(cmd, HEX); Serial.println(); commands.queue.pop(); @@ -153,11 +154,11 @@ namespace Mqtt { } void setup() { + Display::Brightness::onChanged(publishBrightness); client.onConnect([](bool sessionPresent) { tPublishConfig.enable(); tPublishBmp.enableIfNot(); tPublishCommand.enableDelayed(); - tPublishBrightness.enable(); client.subscribe(espClockTopic, 0); tReConnect.disable(); Serial.println("Connected to MQTT"); @@ -166,7 +167,6 @@ namespace Mqtt { tReConnect.enableDelayed(); tPublishCommand.disable(); tPublishBmp.disable(); - tPublishBrightness.disable(); Serial.println("Disconnected from MQTT"); }); client.onMessage(onMessage); From 3272afcef2ebc0eb9f59af9aa032fb3f1b80f264 Mon Sep 17 00:00:00 2001 From: Nicu Hodos Date: Tue, 11 Jul 2023 11:52:42 +0200 Subject: [PATCH 5/5] update brightness at specific hour instead of interval --- include/display.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/display.h b/include/display.h index d10b8ca..a560284 100644 --- a/include/display.h +++ b/include/display.h @@ -44,10 +44,6 @@ namespace Display { void change(bool increase) { increase ? set(current + BRIGHTNESS_STEP) : set(current - BRIGHTNESS_STEP); } - - void update() { - currentHour > 8 && currentHour < 17 ? set(BRIGHTNESS_DAY) : set(BRIGHTNESS_NIGHT); - } } void drawTime() { @@ -73,8 +69,13 @@ namespace Display { if (colonOn) { if (currentHour != hour()) { currentHour = hour(); - Brightness::update(); - if (currentHour == 8) Wifi::reconnect(); + if (currentHour == 8) { + Brightness::set(BRIGHTNESS_DAY); + Wifi::reconnect(); + } + if (currentHour == 17) { + Brightness::set(BRIGHTNESS_NIGHT); + } } if (currentMin != minute()) { currentMin = minute();