From e2a56d7c29d6b07c7e8a36e02cd2120bf0081ec7 Mon Sep 17 00:00:00 2001 From: Fabian Schlenz Date: Sat, 21 Dec 2019 14:21:31 +0100 Subject: [PATCH] Added a TimeEffect to show a countdown to a time given via MQTT. --- include/config.sample.h | 1 + include/effect_timer.h | 16 ++++++++++++++++ include/effects.h | 2 ++ include/prototypes.h | 1 + src/effect_timer.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/effects.cpp | 1 + src/mqtt.cpp | 5 +++++ src/pitrix.cpp | 4 ++++ 8 files changed, 67 insertions(+) create mode 100644 include/effect_timer.h create mode 100644 src/effect_timer.cpp diff --git a/include/config.sample.h b/include/config.sample.h index ed837c9..1d9cae4 100644 --- a/include/config.sample.h +++ b/include/config.sample.h @@ -36,6 +36,7 @@ #define MQTT_TOPIC "pitrix/" // MQTT topic to listen to. Must not start with a slash, but must end with one. #define MQTT_REPORT_METRICS // Whether to report metrics via MQTT. Disable if unwanted. #define MQTT_TOPIC_WEATHER "accuweather/pitrix/" // MQTT topic to listen for weather data. Must not start with a slash, but must end with one. +#define MQTT_TOPIC_TIMER "alexa/timer" #define HOSTNAME "pitrix-%08X" // Hostname of the ESP to use for OTA and MQTT client id. %08X will be replaced by the chip id. #define OTA_STARTUP_DELAY 10 // How many seconds to wait at startup. This is useful to prevent being unable to flash OTA by a bug in the code. Set to 0 to disable. diff --git a/include/effect_timer.h b/include/effect_timer.h new file mode 100644 index 0000000..f4f2fed --- /dev/null +++ b/include/effect_timer.h @@ -0,0 +1,16 @@ +#pragma once + +#include "Effect.h" +#include "prototypes.h" +#include "my_fastled.h" +#include "Window.h" + +class TimerEffect : public Effect { +protected: + Window* window = new Window(0, 0, LED_WIDTH, 6); + +public: + ~TimerEffect(); + void loop(uint16_t ms); + String get_name() override { return "timer"; } +}; \ No newline at end of file diff --git a/include/effects.h b/include/effects.h index ba4696d..b44e3e7 100644 --- a/include/effects.h +++ b/include/effects.h @@ -2,6 +2,7 @@ #include "Effect.h" #include "effect_clock.h" +#include "effect_timer.h" struct EffectEntry { const char* name; @@ -13,6 +14,7 @@ extern const uint8_t effects_size; extern Effect* current_effect; extern ClockEffect effect_clock; +extern TimerEffect effect_timer; Effect* select_effect(char* name); Effect* select_effect(uint8_t id); diff --git a/include/prototypes.h b/include/prototypes.h index dfd87af..9788871 100644 --- a/include/prototypes.h +++ b/include/prototypes.h @@ -5,6 +5,7 @@ extern uint8_t baseHue; extern char hostname[30]; extern uint16_t frame; +extern unsigned long timer; typedef struct { uint8_t width; diff --git a/src/effect_timer.cpp b/src/effect_timer.cpp new file mode 100644 index 0000000..66eceeb --- /dev/null +++ b/src/effect_timer.cpp @@ -0,0 +1,37 @@ +#include "effect_timer.h" +#include +#include "functions.h" +#include "fonts.h" +#include "ntp.h" + +void TimerEffect::loop(uint16_t ms) { + if (timer==0) return; + + CRGB bg_color(0x000000); + CRGB fg_color(0xCCCCCC); + unsigned long now = ntpClient.getEpochTime() - NTP_OFFSET; + long diff = timer - now; + window->clear(&bg_color); + if (diff < 0 && (now & 1)==0) return; + if (diff < 0) diff = 0; + int hours = diff / 3600; + int minutes = diff / 60; + int seconds = diff % 60; + if (minutes > 99) { + seconds = minutes % 60; + minutes = hours; + } + //void drawChar(Font f, uint8_t x, uint8_t y, const char c, CRGB* color, bool mask=false); + window->drawChar(&font_numbers3x5, 0<<8, 0<<8, '0' + (minutes / 10), &fg_color); + window->drawChar(&font_numbers3x5, 4<<8, 0<<8, '0' + (minutes % 10), &fg_color); + window->drawChar(&font_numbers3x5, 9<<8, 0<<8, '0' + (seconds / 10), &fg_color); + window->drawChar(&font_numbers3x5, 13<<8, 0<<8, '0' + (seconds % 10), &fg_color); + if (now & 1) { + window->setPixel(7, 1, &fg_color); + window->setPixel(7, 3, &fg_color); + } +} + +TimerEffect::~TimerEffect() { + delete window; +} diff --git a/src/effects.cpp b/src/effects.cpp index 9039755..80d27d7 100644 --- a/src/effects.cpp +++ b/src/effects.cpp @@ -28,6 +28,7 @@ Effect* current_effect; ClockEffect effect_clock; +TimerEffect effect_timer; // We're using 0 instead of false to get a better visual difference between true and false. const EffectEntry effects[] = { diff --git a/src/mqtt.cpp b/src/mqtt.cpp index ffbbc84..947001c 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -50,6 +50,10 @@ void mqtt_callback(char* original_topic, byte* pl, unsigned int length) { LOGln("Set weather_temperatures[%d] to value %d", id, val); } return; + } else if (topic.equals(MQTT_TOPIC_TIMER)) { + timer = payload.toInt(); + LOGln("Set timer to %lu.", timer); + return; } topic.remove(0, strlen(MQTT_TOPIC)); // Strip MQTT_TOPIC from the beginning @@ -102,6 +106,7 @@ boolean mqtt_connect() { mqtt_client.publish(MQTT_TOPIC "status", buffer, true); mqtt_client.subscribe(MQTT_TOPIC "+"); mqtt_client.subscribe(MQTT_TOPIC_WEATHER "#"); + mqtt_client.subscribe(MQTT_TOPIC_TIMER); } return mqtt_client.connected(); } diff --git a/src/pitrix.cpp b/src/pitrix.cpp index 1297a51..f1b778a 100644 --- a/src/pitrix.cpp +++ b/src/pitrix.cpp @@ -19,6 +19,7 @@ uint8_t baseHue = 0; // defined as extern in prototypes.h char hostname[30]; // defined as extern in prototypes.h uint16_t frame = 0; // defined as extern in prototypes.h unsigned long _last_effect_loop_finished_at = 0; +unsigned long timer = 0; #ifdef RECORDER_ENABLE Recorder* recorder; #endif @@ -113,6 +114,9 @@ void loop() { if (current_effect->can_be_shown_with_clock()) { effect_clock.loop_with_invert(current_effect->clock_as_mask()); } + + effect_timer.loop(last_loop_ago); + FastLED.show(); http_server_send_framedata();