Merge branch 'display-task-improvements'
This commit is contained in:
commit
71a5e96994
@ -49,7 +49,7 @@ namespace Devices {
|
|||||||
Number* displayTimerMqtt = Builder<Number>::instance(new Number{ "Timer duration", "timer_duration",
|
Number* displayTimerMqtt = Builder<Number>::instance(new Number{ "Timer duration", "timer_duration",
|
||||||
[](const char* msg) {
|
[](const char* msg) {
|
||||||
auto value = String{ msg }.toInt();
|
auto value = String{ msg }.toInt();
|
||||||
Display::Timer::timer = value;
|
timer = value;
|
||||||
displayTimerMqtt->updateState(value);
|
displayTimerMqtt->updateState(value);
|
||||||
}
|
}
|
||||||
}).withMin(0).withMax(90).withStep(5).restoreStateFromCommand().build();
|
}).withMin(0).withMax(90).withStep(5).restoreStateFromCommand().build();
|
||||||
@ -58,10 +58,10 @@ namespace Devices {
|
|||||||
Switch* timerMqtt = Builder<Switch>::instance(new Switch{"Timer", "timer",
|
Switch* timerMqtt = Builder<Switch>::instance(new Switch{"Timer", "timer",
|
||||||
[](const char* msg) {
|
[](const char* msg) {
|
||||||
if (strcmp("ON", msg) == 0) {
|
if (strcmp("ON", msg) == 0) {
|
||||||
Display::Timer::start();
|
Display::tTimer.restart();
|
||||||
timerMqtt->updateState(true);
|
timerMqtt->updateState(true);
|
||||||
} else {
|
} else {
|
||||||
Display::Timer::stop();
|
Display::tTimer.disable();
|
||||||
timerMqtt->updateState(false);
|
timerMqtt->updateState(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,10 +77,9 @@ namespace Devices {
|
|||||||
.addSecondary(
|
.addSecondary(
|
||||||
Builder<Button>::instance(new Button{"Display sensor data", "display_sensor_data",
|
Builder<Button>::instance(new Button{"Display sensor data", "display_sensor_data",
|
||||||
[](const char* msg) {
|
[](const char* msg) {
|
||||||
if (strcmp("PRESS", msg) == 0 && !Display::tDisplaySensor.isEnabled()) {
|
if (strcmp("PRESS", msg) == 0) {
|
||||||
Bme::data.readAll();
|
Bme::data.readAll();
|
||||||
Display::tDisplaySensor.setIterations(DISPLAY_SENSOR_ITERATIONS);
|
Display::displayTask.activate(Display::tDisplaySensor);
|
||||||
Display::tDisplaySensor.restart();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}).build()
|
}).build()
|
||||||
@ -88,8 +87,8 @@ namespace Devices {
|
|||||||
.addSecondary(
|
.addSecondary(
|
||||||
Builder<Button>::instance(new Button{"Display date", "display_date",
|
Builder<Button>::instance(new Button{"Display date", "display_date",
|
||||||
[](const char* msg) {
|
[](const char* msg) {
|
||||||
if (strcmp("PRESS", msg) == 0 && !Display::tDisplayDate.isEnabled()) {
|
if (strcmp("PRESS", msg) == 0) {
|
||||||
Display::tDisplayDate.restart();
|
Display::displayTask.activate(Display::tDisplayDate);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}).build()
|
}).build()
|
||||||
@ -97,8 +96,8 @@ namespace Devices {
|
|||||||
.addSecondary(
|
.addSecondary(
|
||||||
Builder<Button>::instance(new Button{"Display remaining timer", "display_remaining_timer",
|
Builder<Button>::instance(new Button{"Display remaining timer", "display_remaining_timer",
|
||||||
[](const char* msg) {
|
[](const char* msg) {
|
||||||
if (strcmp("PRESS", msg) == 0 && !Display::Timer::tDisplayTimer.isEnabled()) {
|
if (strcmp("PRESS", msg) == 0) {
|
||||||
Display::Timer::tDisplayTimer.restart();
|
Display::displayTask.activate(Display::tDisplayTimer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).build()
|
}).build()
|
||||||
@ -137,7 +136,7 @@ namespace Devices {
|
|||||||
Display::brightness.registerCallback([]{
|
Display::brightness.registerCallback([]{
|
||||||
brightnessMqtt->updateState(Display::brightness);
|
brightnessMqtt->updateState(Display::brightness);
|
||||||
});
|
});
|
||||||
Display::Timer::timer.registerCallback([](int8 current){
|
timer.registerCallback([](int8 current){
|
||||||
timerRemainingMqtt->updateState(to_string(current).c_str());
|
timerRemainingMqtt->updateState(to_string(current).c_str());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include "ntp_time.h"
|
#include "ntp_time.h"
|
||||||
#include "bme.h"
|
#include "bme.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
#define DISPLAY_ADDRESS 0x70
|
#define DISPLAY_ADDRESS 0x70
|
||||||
#define MILLISECONDS(value) value*TASK_MILLISECOND
|
#define MILLISECONDS(value) value*TASK_MILLISECOND
|
||||||
@ -14,19 +15,41 @@
|
|||||||
#define DISPLAY_SENSOR_ITERATIONS 2+1
|
#define DISPLAY_SENSOR_ITERATIONS 2+1
|
||||||
#define DISPLAY_DELAY (SECONDS(2))
|
#define DISPLAY_DELAY (SECONDS(2))
|
||||||
|
|
||||||
typedef void (*callback_t)();
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct CallbackAware {
|
|
||||||
void registerCallback(T f) {
|
|
||||||
callback = f;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
T callback;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace Display {
|
namespace Display {
|
||||||
|
|
||||||
|
// Create display object
|
||||||
|
Adafruit_7segment clockDisplay = Adafruit_7segment();
|
||||||
|
|
||||||
|
struct {
|
||||||
|
operator Task&() {
|
||||||
|
return *perm;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool activate(Task& task) {
|
||||||
|
if (task.isEnabled()) return false;
|
||||||
|
if (temp) temp->cancel();
|
||||||
|
if (perm) perm->cancel();
|
||||||
|
if (task.getIterations() == TASK_FOREVER) {
|
||||||
|
perm = &task;
|
||||||
|
return task.enable();
|
||||||
|
} else {
|
||||||
|
temp = &task;
|
||||||
|
return task.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void restorePerm() {
|
||||||
|
if (temp && temp->isEnabled()) return; // don't enable perm when triggered by another temp on top of exsting temp
|
||||||
|
if (perm) perm->enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isPerm(Task& task) {
|
||||||
|
return perm == &task;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Task *temp = nullptr, *perm = nullptr;
|
||||||
|
} displayTask;
|
||||||
|
|
||||||
void displayTime();
|
void displayTime();
|
||||||
void displayDate();
|
void displayDate();
|
||||||
void displayTemp();
|
void displayTemp();
|
||||||
@ -43,23 +66,46 @@ namespace Display {
|
|||||||
});
|
});
|
||||||
Task tDisplaySensor(SECONDS(5), DISPLAY_SENSOR_ITERATIONS, nullptr, &ts, false,
|
Task tDisplaySensor(SECONDS(5), DISPLAY_SENSOR_ITERATIONS, nullptr, &ts, false,
|
||||||
[]() {
|
[]() {
|
||||||
if (!tDisplayTime.isEnabled()) return false;
|
|
||||||
tDisplayTime.disable();
|
|
||||||
tDisplaySensor.setCallback(displayTemp);
|
tDisplaySensor.setCallback(displayTemp);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
[]() {
|
[]() {
|
||||||
tDisplaySensor.setIterations((DISPLAY_SENSOR_ITERATIONS - 1) * 2 + 1);
|
tDisplaySensor.setIterations(DISPLAY_SENSOR_ITERATIONS);
|
||||||
tDisplayTime.enable();
|
displayTask.restorePerm();
|
||||||
});
|
});
|
||||||
Task tDisplayDate(SECONDS(5), TASK_ONCE + 1, displayDate, &ts, false,
|
Task tDisplayDate(SECONDS(5), TASK_ONCE + 1, displayDate, &ts, false, nullptr,
|
||||||
[]() {
|
[]() {
|
||||||
if (!tDisplayTime.isEnabled()) return false;
|
displayTask.restorePerm();
|
||||||
tDisplayTime.disable();
|
});
|
||||||
|
Task tDisplayTimer(SECONDS(10), TASK_ONCE + 1,
|
||||||
|
[]{
|
||||||
|
if (timer >= 0) {
|
||||||
|
clockDisplay.print(timer, DEC);
|
||||||
|
clockDisplay.writeDisplay();
|
||||||
|
}
|
||||||
|
}, &ts, false, nullptr,
|
||||||
|
[]{
|
||||||
|
tDisplayTimer.setIterations(TASK_ONCE + 1);
|
||||||
|
if (!displayTask.isPerm(tDisplayTimer)) displayTask.restorePerm();
|
||||||
|
});
|
||||||
|
Task tTimer(MINUTES(1), TASK_FOREVER,
|
||||||
|
[]{
|
||||||
|
static constexpr uint8 threshold = 16;
|
||||||
|
timer.decrease();
|
||||||
|
if (timer.atBeginning()) {
|
||||||
|
if (timer <= threshold) tDisplayTimer.setIterations(TASK_FOREVER);
|
||||||
|
displayTask.activate(tDisplayTimer);
|
||||||
|
} else if (timer == threshold) {
|
||||||
|
tDisplayTimer.setIterations(TASK_FOREVER);
|
||||||
|
displayTask.activate(tDisplayTimer);
|
||||||
|
}
|
||||||
|
}, &ts, false,
|
||||||
|
[]{
|
||||||
|
timer.start();
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
[]() {
|
[]{
|
||||||
tDisplayTime.enable();
|
displayTask.activate(tDisplayTime);
|
||||||
});
|
});
|
||||||
|
|
||||||
struct HourFormat : public CallbackAware<callback_t> {
|
struct HourFormat : public CallbackAware<callback_t> {
|
||||||
@ -70,16 +116,13 @@ namespace Display {
|
|||||||
|
|
||||||
void operator=(bool value) {
|
void operator=(bool value) {
|
||||||
format24 = value;
|
format24 = value;
|
||||||
tDisplayTime.restart();
|
if (displayTask.isPerm(tDisplayTime)) drawTime();
|
||||||
if (callback) callback();
|
if (callback) callback();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
bool format24 = false;
|
bool format24 = false;
|
||||||
} hourFormat24;
|
} hourFormat24;
|
||||||
|
|
||||||
// Create display object
|
|
||||||
Adafruit_7segment clockDisplay = Adafruit_7segment();
|
|
||||||
|
|
||||||
struct Brightness : public CallbackAware<callback_t> {
|
struct Brightness : public CallbackAware<callback_t> {
|
||||||
static constexpr uint8 MIN = 0;
|
static constexpr uint8 MIN = 0;
|
||||||
static constexpr uint8 MAX = 15;
|
static constexpr uint8 MAX = 15;
|
||||||
@ -100,80 +143,6 @@ namespace Display {
|
|||||||
uint8 current = NIGHT;
|
uint8 current = NIGHT;
|
||||||
} brightness;
|
} brightness;
|
||||||
|
|
||||||
namespace Timer {
|
|
||||||
typedef void (*remaining_callback_t)(int8);
|
|
||||||
struct : public CallbackAware<remaining_callback_t> {
|
|
||||||
|
|
||||||
void operator=(int8 value) {
|
|
||||||
initial = remaining = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator int8() {
|
|
||||||
return remaining;
|
|
||||||
}
|
|
||||||
|
|
||||||
void start() {
|
|
||||||
remaining = initial + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void decrease() {
|
|
||||||
remaining--;
|
|
||||||
if (callback) callback(remaining);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool atBeginning() {
|
|
||||||
return initial == remaining;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int8 initial = 0, remaining = 0;
|
|
||||||
} timer;
|
|
||||||
|
|
||||||
Task tDisplayTimer(SECONDS(10), TASK_ONCE + 1,
|
|
||||||
[]{
|
|
||||||
if (timer >= 0) {
|
|
||||||
clockDisplay.print(timer, DEC);
|
|
||||||
clockDisplay.writeDisplay();
|
|
||||||
}
|
|
||||||
}, &ts, false,
|
|
||||||
[]{
|
|
||||||
if (!tDisplayTime.isEnabled()) return false;
|
|
||||||
tDisplayTime.disable();
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
[]{
|
|
||||||
tDisplayTimer.setIterations(TASK_ONCE + 1);
|
|
||||||
tDisplayTime.enable();
|
|
||||||
});
|
|
||||||
Task tTimer(MINUTES(1), TASK_FOREVER,
|
|
||||||
[]{
|
|
||||||
static constexpr uint8 threshold = 16;
|
|
||||||
timer.decrease();
|
|
||||||
if (timer.atBeginning()) {
|
|
||||||
if (timer <= threshold) tDisplayTimer.setIterations(TASK_FOREVER);
|
|
||||||
tDisplayTimer.restart();
|
|
||||||
} else if (timer == threshold) {
|
|
||||||
tDisplayTimer.setIterations(TASK_FOREVER);
|
|
||||||
tDisplayTimer.restart();
|
|
||||||
}
|
|
||||||
}, &ts, false,
|
|
||||||
[]{
|
|
||||||
timer.start();
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
[]{
|
|
||||||
tDisplayTimer.disable();
|
|
||||||
});
|
|
||||||
|
|
||||||
void start() {
|
|
||||||
tTimer.restart();
|
|
||||||
}
|
|
||||||
|
|
||||||
void stop() {
|
|
||||||
tTimer.disable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawTime() {
|
void drawTime() {
|
||||||
int displayHour = hourFormat24 ? hour() : hourFormat12();
|
int displayHour = hourFormat24 ? hour() : hourFormat12();
|
||||||
int displayMinute = minute();
|
int displayMinute = minute();
|
||||||
@ -274,6 +243,6 @@ namespace Display {
|
|||||||
void setup() {
|
void setup() {
|
||||||
clockDisplay.begin(DISPLAY_ADDRESS);
|
clockDisplay.begin(DISPLAY_ADDRESS);
|
||||||
clockDisplay.setBrightness(brightness);
|
clockDisplay.setBrightness(brightness);
|
||||||
tDisplayTime.enable();
|
displayTask.activate(tDisplayTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
include/helper.h
Normal file
12
include/helper.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef void (*callback_t)();
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct CallbackAware {
|
||||||
|
void registerCallback(T f) {
|
||||||
|
callback = f;
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
T callback;
|
||||||
|
};
|
||||||
31
include/timer.h
Normal file
31
include/timer.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "helper.h"
|
||||||
|
|
||||||
|
typedef void (*remaining_callback_t)(int8);
|
||||||
|
struct : public CallbackAware<remaining_callback_t> {
|
||||||
|
|
||||||
|
void operator=(int8 value) {
|
||||||
|
initial = remaining = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator int8() {
|
||||||
|
return remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
void start() {
|
||||||
|
remaining = initial + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void decrease() {
|
||||||
|
remaining--;
|
||||||
|
if (callback) callback(remaining);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool atBeginning() {
|
||||||
|
return initial == remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int8 initial = 0, remaining = 0;
|
||||||
|
} timer;
|
||||||
@ -28,10 +28,7 @@ void turnLed(bool on = true) {
|
|||||||
|
|
||||||
Task tButton(TASK_IMMEDIATE, TASK_ONCE,
|
Task tButton(TASK_IMMEDIATE, TASK_ONCE,
|
||||||
[]() {
|
[]() {
|
||||||
if (Display::tDisplaySensor.isEnabled()) return;
|
if (Display::displayTask.activate(Display::tDisplaySensor)) Bme::data.readAll();
|
||||||
Bme::data.readAll();
|
|
||||||
Display::tDisplaySensor.setIterations(DISPLAY_SENSOR_ITERATIONS);
|
|
||||||
Display::tDisplaySensor.restart();
|
|
||||||
}, &ts);
|
}, &ts);
|
||||||
Task tLed(TASK_IMMEDIATE, TASK_ONCE,
|
Task tLed(TASK_IMMEDIATE, TASK_ONCE,
|
||||||
[]() {
|
[]() {
|
||||||
@ -46,7 +43,8 @@ Task tReadBme(TASK_MINUTE, TASK_FOREVER, []() {
|
|||||||
Devices::publishBme280();
|
Devices::publishBme280();
|
||||||
if (abs(lastTemp - Bme::data.temp) > 0.2) {
|
if (abs(lastTemp - Bme::data.temp) > 0.2) {
|
||||||
lastTemp = Bme::data.temp;
|
lastTemp = Bme::data.temp;
|
||||||
Display::tDisplaySensor.restart();
|
Display::tDisplaySensor.setIterations((DISPLAY_SENSOR_ITERATIONS - 1) * 2 + 1);
|
||||||
|
Display::displayTask.activate(Display::tDisplaySensor);
|
||||||
}
|
}
|
||||||
}, &ts);
|
}, &ts);
|
||||||
|
|
||||||
@ -89,7 +87,8 @@ void setup() {
|
|||||||
attachInterrupt(digitalPinToInterrupt(BUTTON), onButtonPressed, FALLING);
|
attachInterrupt(digitalPinToInterrupt(BUTTON), onButtonPressed, FALLING);
|
||||||
attachInterrupt(digitalPinToInterrupt(LED_BUILTIN), onLed, CHANGE);
|
attachInterrupt(digitalPinToInterrupt(LED_BUILTIN), onLed, CHANGE);
|
||||||
|
|
||||||
tReadBme.enable();
|
tReadBme.enableDelayed();
|
||||||
|
tButton.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user