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)
|
||||
{
|
||||
if (isDNDActive()) {
|
||||
return; // Don't change brightness during DND mode
|
||||
}
|
||||
if (brightness > 4096)
|
||||
{
|
||||
return;
|
||||
|
@ -183,6 +186,9 @@ bool frontlightIsOn()
|
|||
|
||||
void frontlightFadeIn(uint num, int flDelayTime)
|
||||
{
|
||||
if (isDNDActive()) {
|
||||
return; // Don't change brightness during DND mode
|
||||
}
|
||||
if (preferences.getBool("flDisable"))
|
||||
return;
|
||||
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)
|
||||
{
|
||||
if (isDNDActive()) {
|
||||
return; // Don't change brightness during DND mode
|
||||
}
|
||||
if (preferences.getBool("flDisable"))
|
||||
return;
|
||||
if (!frontlightIsOn())
|
||||
|
@ -207,6 +216,85 @@ void frontlightFadeOut(uint num, int flDelayTime)
|
|||
}
|
||||
#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)
|
||||
{
|
||||
while (1)
|
||||
|
@ -450,6 +538,7 @@ void ledTask(void *parameter)
|
|||
|
||||
void setupLeds()
|
||||
{
|
||||
loadDNDSettings();
|
||||
pixels.begin();
|
||||
pixels.setBrightness(preferences.getUInt("ledBrightness", DEFAULT_LED_BRIGHTNESS));
|
||||
pixels.clear();
|
||||
|
@ -595,15 +684,18 @@ void restoreLedState()
|
|||
|
||||
QueueHandle_t getLedTaskQueue() { return ledTaskQueue; }
|
||||
|
||||
bool queueLedEffect(uint effect)
|
||||
{
|
||||
if (ledTaskQueue == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool queueLedEffect(uint effect) {
|
||||
if (isDNDActive()) {
|
||||
return false; // Don't queue any effects during DND mode
|
||||
}
|
||||
if (ledTaskQueue == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint flashType = effect;
|
||||
xQueueSend(ledTaskQueue, &flashType, portMAX_DELAY);
|
||||
uint flashType = effect;
|
||||
xQueueSend(ledTaskQueue, &flashType, portMAX_DELAY);
|
||||
return true;
|
||||
}
|
||||
|
||||
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_ERASE_SETTINGS = 104;
|
||||
|
||||
|
||||
const int LED_PROGRESS_25 = 200;
|
||||
const int LED_PROGRESS_50 = 201;
|
||||
const int LED_PROGRESS_75 = 202;
|
||||
|
@ -82,4 +81,22 @@ void frontlightFadeOutAll(int flDelayTime, bool staggered);
|
|||
|
||||
void frontlightFadeIn(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",
|
||||
"miningPoolStats", "verticalDesc",
|
||||
"nostrZapNotify", "httpAuthEnabled",
|
||||
"enableDebugLog", "ceDisableSSL"};
|
||||
"enableDebugLog", "ceDisableSSL", "dndEnabled", "dndTimeBasedEnabled"};
|
||||
|
||||
AsyncWebServer server(80);
|
||||
AsyncEventSource events("/events");
|
||||
|
@ -116,6 +116,10 @@ void setupWebserver()
|
|||
server.addRewrite(new OneParamRewrite("/api/show/number/{number}",
|
||||
"/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);
|
||||
|
||||
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
|
||||
|
@ -265,6 +269,15 @@ JsonDocument getStatusObject()
|
|||
}
|
||||
#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;
|
||||
}
|
||||
|
||||
|
@ -605,6 +618,23 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
|
|||
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);
|
||||
if (settingsChanged)
|
||||
{
|
||||
|
@ -766,6 +796,14 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
|
|||
root["ceEndpoint"] = preferences.getString("ceEndpoint", DEFAULT_CUSTOM_ENDPOINT);
|
||||
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 =
|
||||
request->beginResponseStream(JSON_CONTENT);
|
||||
serializeJson(root, *response);
|
||||
|
@ -1091,4 +1129,29 @@ void onApiFrontlightOff(AsyncWebServerRequest *request)
|
|||
|
||||
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 onApiRestartDataSources(AsyncWebServerRequest *request);
|
||||
|
||||
void onApiDNDStatus(AsyncWebServerRequest *request);
|
||||
void onApiDNDEnable(AsyncWebServerRequest *request);
|
||||
void onApiDNDDisable(AsyncWebServerRequest *request);
|
||||
|
||||
#ifdef HAS_FRONTLIGHT
|
||||
void onApiFrontlightOn(AsyncWebServerRequest *request);
|
||||
void onApiFrontlightFlash(AsyncWebServerRequest *request);
|
||||
|
|
Loading…
Reference in a new issue