Add Do Not Disturb feature
All checks were successful
BTClock CI / build (push) Successful in 21m1s
BTClock CI / merge (map[name:btclock_rev_b version:esp32s3], 213epd) (push) Successful in 31s
BTClock CI / merge (map[name:btclock_v8 version:esp32s3], 213epd) (push) Successful in 21s
BTClock CI / merge (map[name:lolin_s3_mini version:esp32s3], 213epd) (push) Successful in 28s
BTClock CI / merge (map[name:lolin_s3_mini version:esp32s3], 29epd) (push) Successful in 19s
BTClock CI / release (push) Successful in 11s
All checks were successful
BTClock CI / build (push) Successful in 21m1s
BTClock CI / merge (map[name:btclock_rev_b version:esp32s3], 213epd) (push) Successful in 31s
BTClock CI / merge (map[name:btclock_v8 version:esp32s3], 213epd) (push) Successful in 21s
BTClock CI / merge (map[name:lolin_s3_mini version:esp32s3], 213epd) (push) Successful in 28s
BTClock CI / merge (map[name:lolin_s3_mini version:esp32s3], 29epd) (push) Successful in 19s
BTClock CI / release (push) Successful in 11s
This commit is contained in:
parent
13c8e67b4c
commit
2e1b15e688
5 changed files with 189 additions and 13 deletions
2
data
2
data
|
@ -1 +1 @@
|
||||||
Subproject commit 0041ec3d9a174955383836bba02caf79f3961072
|
Subproject commit 033fe098295ab6da6568d6298b4380e51bec0b98
|
|
@ -50,6 +50,9 @@ void frontlightFadeOut(uint num)
|
||||||
|
|
||||||
void frontlightSetBrightness(uint brightness)
|
void frontlightSetBrightness(uint brightness)
|
||||||
{
|
{
|
||||||
|
if (isDNDActive()) {
|
||||||
|
return; // Don't change brightness during DND mode
|
||||||
|
}
|
||||||
if (brightness > 4096)
|
if (brightness > 4096)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -183,6 +186,9 @@ bool frontlightIsOn()
|
||||||
|
|
||||||
void frontlightFadeIn(uint num, int flDelayTime)
|
void frontlightFadeIn(uint num, int flDelayTime)
|
||||||
{
|
{
|
||||||
|
if (isDNDActive()) {
|
||||||
|
return; // Don't change brightness during DND mode
|
||||||
|
}
|
||||||
if (preferences.getBool("flDisable"))
|
if (preferences.getBool("flDisable"))
|
||||||
return;
|
return;
|
||||||
for (int dutyCycle = 0; dutyCycle <= preferences.getUInt("flMaxBrightness"); dutyCycle += 5)
|
for (int dutyCycle = 0; dutyCycle <= preferences.getUInt("flMaxBrightness"); dutyCycle += 5)
|
||||||
|
@ -194,6 +200,9 @@ void frontlightFadeIn(uint num, int flDelayTime)
|
||||||
|
|
||||||
void frontlightFadeOut(uint num, int flDelayTime)
|
void frontlightFadeOut(uint num, int flDelayTime)
|
||||||
{
|
{
|
||||||
|
if (isDNDActive()) {
|
||||||
|
return; // Don't change brightness during DND mode
|
||||||
|
}
|
||||||
if (preferences.getBool("flDisable"))
|
if (preferences.getBool("flDisable"))
|
||||||
return;
|
return;
|
||||||
if (!frontlightIsOn())
|
if (!frontlightIsOn())
|
||||||
|
@ -207,6 +216,85 @@ void frontlightFadeOut(uint num, int flDelayTime)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Do Not Disturb mode variables
|
||||||
|
bool dndEnabled = false;
|
||||||
|
bool dndTimeBasedEnabled = false;
|
||||||
|
DNDTimeRange dndTimeRange = {23, 0, 7, 0}; // Default: 23:00 to 07:00
|
||||||
|
|
||||||
|
void loadDNDSettings() {
|
||||||
|
dndEnabled = preferences.getBool("dndEnabled", false);
|
||||||
|
dndTimeBasedEnabled = preferences.getBool("dndTimeEnabled", false);
|
||||||
|
|
||||||
|
dndTimeRange.startHour = preferences.getUChar("dndStartHour", 23);
|
||||||
|
dndTimeRange.startMinute = preferences.getUChar("dndStartMin", 0);
|
||||||
|
dndTimeRange.endHour = preferences.getUChar("dndEndHour", 7);
|
||||||
|
dndTimeRange.endMinute = preferences.getUChar("dndEndMin", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDNDEnabled(bool enabled) {
|
||||||
|
dndEnabled = enabled;
|
||||||
|
preferences.putBool("dndEnabled", enabled);
|
||||||
|
if (enabled && isDNDActive()) {
|
||||||
|
clearLeds();
|
||||||
|
#ifdef HAS_FRONTLIGHT
|
||||||
|
frontlightFadeOutAll();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDNDTimeBasedEnabled(bool enabled) {
|
||||||
|
dndTimeBasedEnabled = enabled;
|
||||||
|
preferences.putBool("dndTimeEnabled", enabled);
|
||||||
|
if (enabled && isDNDActive()) {
|
||||||
|
clearLeds();
|
||||||
|
#ifdef HAS_FRONTLIGHT
|
||||||
|
frontlightFadeOutAll();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDNDTimeRange(uint8_t startHour, uint8_t startMinute, uint8_t endHour, uint8_t endMinute) {
|
||||||
|
dndTimeRange.startHour = startHour;
|
||||||
|
dndTimeRange.startMinute = startMinute;
|
||||||
|
dndTimeRange.endHour = endHour;
|
||||||
|
dndTimeRange.endMinute = endMinute;
|
||||||
|
|
||||||
|
preferences.putUChar("dndStartHour", startHour);
|
||||||
|
preferences.putUChar("dndStartMin", startMinute);
|
||||||
|
preferences.putUChar("dndEndHour", endHour);
|
||||||
|
preferences.putUChar("dndEndMin", endMinute);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isTimeInDNDRange(uint8_t hour, uint8_t minute) {
|
||||||
|
uint16_t currentTime = hour * 60 + minute;
|
||||||
|
uint16_t startTime = dndTimeRange.startHour * 60 + dndTimeRange.startMinute;
|
||||||
|
uint16_t endTime = dndTimeRange.endHour * 60 + dndTimeRange.endMinute;
|
||||||
|
|
||||||
|
if (startTime <= endTime) {
|
||||||
|
// Simple case: start time is before end time (e.g., 09:00 to 17:00)
|
||||||
|
return currentTime >= startTime && currentTime < endTime;
|
||||||
|
} else {
|
||||||
|
// Complex case: start time is after end time (e.g., 23:00 to 07:00)
|
||||||
|
return currentTime >= startTime || currentTime < endTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDNDActive() {
|
||||||
|
if (dndEnabled) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dndTimeBasedEnabled) {
|
||||||
|
time_t now;
|
||||||
|
struct tm timeinfo;
|
||||||
|
time(&now);
|
||||||
|
localtime_r(&now, &timeinfo);
|
||||||
|
return isTimeInDNDRange(timeinfo.tm_hour, timeinfo.tm_min);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void ledTask(void *parameter)
|
void ledTask(void *parameter)
|
||||||
{
|
{
|
||||||
while (1)
|
while (1)
|
||||||
|
@ -450,6 +538,7 @@ void ledTask(void *parameter)
|
||||||
|
|
||||||
void setupLeds()
|
void setupLeds()
|
||||||
{
|
{
|
||||||
|
loadDNDSettings();
|
||||||
pixels.begin();
|
pixels.begin();
|
||||||
pixels.setBrightness(preferences.getUInt("ledBrightness", DEFAULT_LED_BRIGHTNESS));
|
pixels.setBrightness(preferences.getUInt("ledBrightness", DEFAULT_LED_BRIGHTNESS));
|
||||||
pixels.clear();
|
pixels.clear();
|
||||||
|
@ -595,15 +684,18 @@ void restoreLedState()
|
||||||
|
|
||||||
QueueHandle_t getLedTaskQueue() { return ledTaskQueue; }
|
QueueHandle_t getLedTaskQueue() { return ledTaskQueue; }
|
||||||
|
|
||||||
bool queueLedEffect(uint effect)
|
bool queueLedEffect(uint effect) {
|
||||||
{
|
if (isDNDActive()) {
|
||||||
if (ledTaskQueue == NULL)
|
return false; // Don't queue any effects during DND mode
|
||||||
{
|
}
|
||||||
return false;
|
if (ledTaskQueue == NULL)
|
||||||
}
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
uint flashType = effect;
|
uint flashType = effect;
|
||||||
xQueueSend(ledTaskQueue, &flashType, portMAX_DELAY);
|
xQueueSend(ledTaskQueue, &flashType, portMAX_DELAY);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ledRainbow(int wait)
|
void ledRainbow(int wait)
|
||||||
|
|
|
@ -28,7 +28,6 @@ const int LED_EFFECT_WIFI_CONNECT_ERROR = 102;
|
||||||
const int LED_EFFECT_WIFI_CONNECT_SUCCESS = 103;
|
const int LED_EFFECT_WIFI_CONNECT_SUCCESS = 103;
|
||||||
const int LED_EFFECT_WIFI_ERASE_SETTINGS = 104;
|
const int LED_EFFECT_WIFI_ERASE_SETTINGS = 104;
|
||||||
|
|
||||||
|
|
||||||
const int LED_PROGRESS_25 = 200;
|
const int LED_PROGRESS_25 = 200;
|
||||||
const int LED_PROGRESS_50 = 201;
|
const int LED_PROGRESS_50 = 201;
|
||||||
const int LED_PROGRESS_75 = 202;
|
const int LED_PROGRESS_75 = 202;
|
||||||
|
@ -82,4 +81,22 @@ void frontlightFadeOutAll(int flDelayTime, bool staggered);
|
||||||
|
|
||||||
void frontlightFadeIn(uint num, int flDelayTime);
|
void frontlightFadeIn(uint num, int flDelayTime);
|
||||||
void frontlightFadeOut(uint num, int flDelayTime);
|
void frontlightFadeOut(uint num, int flDelayTime);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Do Not Disturb mode settings
|
||||||
|
struct DNDTimeRange {
|
||||||
|
uint8_t startHour;
|
||||||
|
uint8_t startMinute;
|
||||||
|
uint8_t endHour;
|
||||||
|
uint8_t endMinute;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern bool dndEnabled;
|
||||||
|
extern bool dndTimeBasedEnabled;
|
||||||
|
extern DNDTimeRange dndTimeRange;
|
||||||
|
|
||||||
|
void setDNDEnabled(bool enabled);
|
||||||
|
void setDNDTimeBasedEnabled(bool enabled);
|
||||||
|
void setDNDTimeRange(uint8_t startHour, uint8_t startMinute, uint8_t endHour, uint8_t endMinute);
|
||||||
|
bool isDNDActive();
|
||||||
|
bool isTimeInDNDRange(uint8_t hour, uint8_t minute);
|
|
@ -16,7 +16,7 @@ static const char *const PROGMEM boolSettings[] = {"ledTestOnPower", "ledFlashOn
|
||||||
"mempoolSecure", "bitaxeEnabled",
|
"mempoolSecure", "bitaxeEnabled",
|
||||||
"miningPoolStats", "verticalDesc",
|
"miningPoolStats", "verticalDesc",
|
||||||
"nostrZapNotify", "httpAuthEnabled",
|
"nostrZapNotify", "httpAuthEnabled",
|
||||||
"enableDebugLog", "ceDisableSSL"};
|
"enableDebugLog", "ceDisableSSL", "dndEnabled", "dndTimeBasedEnabled"};
|
||||||
|
|
||||||
AsyncWebServer server(80);
|
AsyncWebServer server(80);
|
||||||
AsyncEventSource events("/events");
|
AsyncEventSource events("/events");
|
||||||
|
@ -116,6 +116,10 @@ void setupWebserver()
|
||||||
server.addRewrite(new OneParamRewrite("/api/show/number/{number}",
|
server.addRewrite(new OneParamRewrite("/api/show/number/{number}",
|
||||||
"/api/show/text?t={text}"));
|
"/api/show/text?t={text}"));
|
||||||
|
|
||||||
|
server.on("/api/dnd/status", HTTP_GET, onApiDNDStatus);
|
||||||
|
server.on("/api/dnd/enable", HTTP_POST, onApiDNDEnable);
|
||||||
|
server.on("/api/dnd/disable", HTTP_POST, onApiDNDDisable);
|
||||||
|
|
||||||
server.onNotFound(onNotFound);
|
server.onNotFound(onNotFound);
|
||||||
|
|
||||||
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
|
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
@ -265,6 +269,15 @@ JsonDocument getStatusObject()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Add DND status
|
||||||
|
root["dnd"]["enabled"] = dndEnabled;
|
||||||
|
root["dnd"]["timeBasedEnabled"] = dndTimeBasedEnabled;
|
||||||
|
root["dnd"]["startTime"] = String(dndTimeRange.startHour) + ":" +
|
||||||
|
(dndTimeRange.startMinute < 10 ? "0" : "") + String(dndTimeRange.startMinute);
|
||||||
|
root["dnd"]["endTime"] = String(dndTimeRange.endHour) + ":" +
|
||||||
|
(dndTimeRange.endMinute < 10 ? "0" : "") + String(dndTimeRange.endMinute);
|
||||||
|
root["dnd"]["active"] = isDNDActive();
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,6 +618,23 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle DND settings
|
||||||
|
if (settings.containsKey("dnd")) {
|
||||||
|
JsonObject dndObj = settings["dnd"];
|
||||||
|
if (dndObj.containsKey("timeBasedEnabled")) {
|
||||||
|
setDNDTimeBasedEnabled(dndObj["timeBasedEnabled"].as<bool>());
|
||||||
|
}
|
||||||
|
if (dndObj.containsKey("startHour") && dndObj.containsKey("startMinute") &&
|
||||||
|
dndObj.containsKey("endHour") && dndObj.containsKey("endMinute")) {
|
||||||
|
setDNDTimeRange(
|
||||||
|
dndObj["startHour"].as<uint8_t>(),
|
||||||
|
dndObj["startMinute"].as<uint8_t>(),
|
||||||
|
dndObj["endHour"].as<uint8_t>(),
|
||||||
|
dndObj["endMinute"].as<uint8_t>()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
request->send(HTTP_OK);
|
request->send(HTTP_OK);
|
||||||
if (settingsChanged)
|
if (settingsChanged)
|
||||||
{
|
{
|
||||||
|
@ -766,6 +796,14 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
|
||||||
root["ceEndpoint"] = preferences.getString("ceEndpoint", DEFAULT_CUSTOM_ENDPOINT);
|
root["ceEndpoint"] = preferences.getString("ceEndpoint", DEFAULT_CUSTOM_ENDPOINT);
|
||||||
root["ceDisableSSL"] = preferences.getBool("ceDisableSSL", DEFAULT_CUSTOM_ENDPOINT_DISABLE_SSL);
|
root["ceDisableSSL"] = preferences.getBool("ceDisableSSL", DEFAULT_CUSTOM_ENDPOINT_DISABLE_SSL);
|
||||||
|
|
||||||
|
// Add DND settings
|
||||||
|
root["dnd"]["enabled"] = dndEnabled;
|
||||||
|
root["dnd"]["timeBasedEnabled"] = dndTimeBasedEnabled;
|
||||||
|
root["dnd"]["startHour"] = dndTimeRange.startHour;
|
||||||
|
root["dnd"]["startMinute"] = dndTimeRange.startMinute;
|
||||||
|
root["dnd"]["endHour"] = dndTimeRange.endHour;
|
||||||
|
root["dnd"]["endMinute"] = dndTimeRange.endMinute;
|
||||||
|
|
||||||
AsyncResponseStream *response =
|
AsyncResponseStream *response =
|
||||||
request->beginResponseStream(JSON_CONTENT);
|
request->beginResponseStream(JSON_CONTENT);
|
||||||
serializeJson(root, *response);
|
serializeJson(root, *response);
|
||||||
|
@ -1091,4 +1129,29 @@ void onApiFrontlightOff(AsyncWebServerRequest *request)
|
||||||
|
|
||||||
request->send(HTTP_OK);
|
request->send(HTTP_OK);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void onApiDNDStatus(AsyncWebServerRequest *request) {
|
||||||
|
JsonDocument doc;
|
||||||
|
doc["enabled"] = dndEnabled;
|
||||||
|
doc["timeBasedEnabled"] = dndTimeBasedEnabled;
|
||||||
|
doc["startTime"] = String(dndTimeRange.startHour) + ":" +
|
||||||
|
(dndTimeRange.startMinute < 10 ? "0" : "") + String(dndTimeRange.startMinute);
|
||||||
|
doc["endTime"] = String(dndTimeRange.endHour) + ":" +
|
||||||
|
(dndTimeRange.endMinute < 10 ? "0" : "") + String(dndTimeRange.endMinute);
|
||||||
|
doc["active"] = isDNDActive();
|
||||||
|
|
||||||
|
String response;
|
||||||
|
serializeJson(doc, response);
|
||||||
|
request->send(200, "application/json", response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onApiDNDEnable(AsyncWebServerRequest *request) {
|
||||||
|
setDNDEnabled(true);
|
||||||
|
request->send(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onApiDNDDisable(AsyncWebServerRequest *request) {
|
||||||
|
setDNDEnabled(false);
|
||||||
|
request->send(200);
|
||||||
|
}
|
|
@ -67,6 +67,10 @@ void eventSourceTask(void *pvParameters);
|
||||||
void onApiStopDataSources(AsyncWebServerRequest *request);
|
void onApiStopDataSources(AsyncWebServerRequest *request);
|
||||||
void onApiRestartDataSources(AsyncWebServerRequest *request);
|
void onApiRestartDataSources(AsyncWebServerRequest *request);
|
||||||
|
|
||||||
|
void onApiDNDStatus(AsyncWebServerRequest *request);
|
||||||
|
void onApiDNDEnable(AsyncWebServerRequest *request);
|
||||||
|
void onApiDNDDisable(AsyncWebServerRequest *request);
|
||||||
|
|
||||||
#ifdef HAS_FRONTLIGHT
|
#ifdef HAS_FRONTLIGHT
|
||||||
void onApiFrontlightOn(AsyncWebServerRequest *request);
|
void onApiFrontlightOn(AsyncWebServerRequest *request);
|
||||||
void onApiFrontlightFlash(AsyncWebServerRequest *request);
|
void onApiFrontlightFlash(AsyncWebServerRequest *request);
|
||||||
|
|
Loading…
Reference in a new issue