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 60a53b0..a560284 100644 --- a/include/display.h +++ b/include/display.h @@ -7,18 +7,19 @@ #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 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; @@ -26,6 +27,25 @@ 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 drawTime() { int displayHour = hourFormat24 ? hour() : hourFormat12(); int displayMinute = minute(); @@ -45,25 +65,17 @@ namespace Display { } } - void changeBrightness(bool increase) { - increase ? brightness = (brightness + BRIGHTNESS_STEP) % 15 : brightness = (brightness - BRIGHTNESS_STEP) % 15; - clockDisplay.setBrightness(brightness); - } - - void adjustBrightness() { - if (currentHour > 8 && currentHour < 17) { - brightness = BRIGHTNESS_DAY; - } else { - brightness = BRIGHTNESS_NIGHT; - } - clockDisplay.setBrightness(brightness); - } - void drawColon(bool colonOn) { if (colonOn) { if (currentHour != hour()) { currentHour = hour(); - 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(); @@ -73,7 +85,7 @@ namespace Display { clockDisplay.drawColon(colonOn); } - void displayColon() { + void display() { static bool colonOn = false; drawColon(colonOn); @@ -111,8 +123,8 @@ namespace Display { void setup() { clockDisplay.begin(DISPLAY_ADDRESS); - clockDisplay.setBrightness(brightness); + clockDisplay.setBrightness(Brightness::current); drawTime(); - displayColon(); + display(); } } diff --git a/include/ha.h b/include/ha.h index 3b72509..3e7a7b7 100644 --- a/include/ha.h +++ b/include/ha.h @@ -1,4 +1,7 @@ +#pragma once + #include +#include "display.h" #define JSON_SIZE 512 #define TOPIC_SIZE 255 @@ -8,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); } @@ -40,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) { @@ -53,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; } }; @@ -75,6 +87,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..b8fb634 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 @@ -45,24 +49,30 @@ 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* brightnessMqtt = (new Ha::Brightness{ "ESP Clock Brightness", "brightness", + [](const char* msg) { + Display::Brightness::set(String{ msg }.toInt()); + } + })->withStateTopic(); + + 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,9 +82,14 @@ namespace Mqtt { Display::drawTime(); } } - } + }, + 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); @@ -82,16 +97,24 @@ 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() { - 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); } + publishBrightness(); ts.deleteTask(tPublishConfig); } @@ -103,14 +126,14 @@ namespace Mqtt { jsonDoc["altitude"] = Bmp::data.altitude; char message[255]; serializeJson(jsonDoc, message); - client.publish(Ha::Sensor::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(); @@ -122,15 +145,16 @@ 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; } } } void setup() { + Display::Brightness::onChanged(publishBrightness); client.onConnect([](bool sessionPresent) { tPublishConfig.enable(); tPublishBmp.enableIfNot(); 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"