Https API support, screen off mode, password length update

- Added https support for openweathermap
- Screen can be turn Off with the brightness slider
- Password length has been updated to meet the standard requirements
This commit is contained in:
M-Factory
2025-09-26 17:06:35 +09:00
parent d8bef35766
commit 892afda296
4 changed files with 274 additions and 49 deletions

View File

@@ -33,7 +33,7 @@ const int IP_SCROLL_SPEED = 115; // Default: Adjust this for the IP Address
// WiFi and configuration globals
char ssid[32] = "";
char password[32] = "";
char password[64] = "";
char openWeatherApiKey[64] = "";
char openWeatherCity[64] = "";
char openWeatherCountry[64] = "";
@@ -46,6 +46,7 @@ String detailedDesc = "";
// Timing and display settings
unsigned long clockDuration = 10000;
unsigned long weatherDuration = 5000;
bool displayOff = false;
int brightness = 7;
bool flipDisplay = false;
bool twelveHourToggle = false;
@@ -58,6 +59,8 @@ char ntpServer2[256] = "time.nist.gov";
// Dimming
bool dimmingEnabled = false;
bool displayOffByDimming = false;
bool displayOffByBrightness = false;
int dimStartHour = 18; // 6pm default
int dimStartMinute = 0;
int dimEndHour = 8; // 8am default
@@ -809,11 +812,36 @@ void setupWebServer() {
return;
}
int newBrightness = request->getParam("value", true)->value().toInt();
// Handle "off" request
if (newBrightness == -1) {
P.displayShutdown(true); // Fully shut down display driver
P.displayClear();
displayOff = true;
Serial.println("[WEBSERVER] Display set to OFF (shutdown mode)");
request->send(200, "application/json", "{\"ok\":true, \"display\":\"off\"}");
return;
}
// Clamp brightness to valid range
if (newBrightness < 0) newBrightness = 0;
if (newBrightness > 15) newBrightness = 15;
brightness = newBrightness;
P.setIntensity(brightness);
Serial.printf("[WEBSERVER] Set brightness to %d\n", brightness);
// Only run robust clear/reset when coming from "off"
if (displayOff) {
P.setIntensity(newBrightness);
advanceDisplayModeSafe();
P.displayShutdown(false);
brightness = newBrightness;
displayOff = false;
Serial.println("[WEBSERVER] Display woke from OFF");
} else {
// Display already on, just set brightness
brightness = newBrightness;
P.setIntensity(brightness);
Serial.printf("[WEBSERVER] Set brightness to %d\n", brightness);
}
request->send(200, "application/json", "{\"ok\":true}");
});
@@ -1164,7 +1192,7 @@ bool isFiveDigitZip(const char *str) {
// Weather Fetching and API settings
// -----------------------------------------------------------------------------
String buildWeatherURL() {
String base = "http://api.openweathermap.org/data/2.5/weather?";
String base = "https://api.openweathermap.org/data/2.5/weather?";
float lat = atof(openWeatherCity);
float lon = atof(openWeatherCountry);
@@ -1219,8 +1247,9 @@ void fetchWeather() {
Serial.print(F("[WEATHER] URL: ")); // Use F() with Serial.print
Serial.println(url);
HTTPClient http; // Create an HTTPClient object
WiFiClient client; // Create a WiFiClient object
HTTPClient http; // Create an HTTPClient object
WiFiClientSecure client; // use secure client for HTTPS
client.setInsecure(); // disable certificate validation
http.begin(client, url); // Pass the WiFiClient object and the URL
@@ -1365,7 +1394,8 @@ void advanceDisplayMode() {
} else if (weatherAvailable && (strlen(openWeatherApiKey) == 32) && (strlen(openWeatherCity) > 0) && (strlen(openWeatherCountry) > 0)) {
displayMode = 1;
Serial.println(F("[DISPLAY] Switching to display mode: WEATHER (from Clock)"));
} else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful) {
} else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful &&
countdownTargetTimestamp > 0 && countdownTargetTimestamp > time(nullptr)) {
displayMode = 3;
Serial.println(F("[DISPLAY] Switching to display mode: COUNTDOWN (from Clock, weather skipped)"));
} else if (nightscoutConfigured) {
@@ -1379,7 +1409,8 @@ void advanceDisplayMode() {
if (weatherAvailable && (strlen(openWeatherApiKey) == 32) && (strlen(openWeatherCity) > 0) && (strlen(openWeatherCountry) > 0)) {
displayMode = 1;
Serial.println(F("[DISPLAY] Switching to display mode: WEATHER (from Date)"));
} else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful) {
} else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful &&
countdownTargetTimestamp > 0 && countdownTargetTimestamp > time(nullptr)) {
displayMode = 3;
Serial.println(F("[DISPLAY] Switching to display mode: COUNTDOWN (from Date, weather skipped)"));
} else if (nightscoutConfigured) {
@@ -1393,7 +1424,8 @@ void advanceDisplayMode() {
if (showWeatherDescription && weatherAvailable && weatherDescription.length() > 0) {
displayMode = 2;
Serial.println(F("[DISPLAY] Switching to display mode: DESCRIPTION (from Weather)"));
} else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful) {
} else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful &&
countdownTargetTimestamp > 0 && countdownTargetTimestamp > time(nullptr)) {
displayMode = 3;
Serial.println(F("[DISPLAY] Switching to display mode: COUNTDOWN (from Weather)"));
} else if (nightscoutConfigured) {
@@ -1404,7 +1436,8 @@ void advanceDisplayMode() {
Serial.println(F("[DISPLAY] Switching to display mode: CLOCK (from Weather)"));
}
} else if (displayMode == 2) { // Weather Description
if (countdownEnabled && !countdownFinished && ntpSyncSuccessful) {
if (countdownEnabled && !countdownFinished && ntpSyncSuccessful &&
countdownTargetTimestamp > 0 && countdownTargetTimestamp > time(nullptr)) {
displayMode = 3;
Serial.println(F("[DISPLAY] Switching to display mode: COUNTDOWN (from Description)"));
} else if (nightscoutConfigured) {
@@ -1431,6 +1464,40 @@ void advanceDisplayMode() {
lastSwitch = millis();
}
void advanceDisplayModeSafe() {
int attempts = 0;
const int MAX_ATTEMPTS = 6; // Number of possible modes + 1
int startMode = displayMode;
bool valid = false;
do {
advanceDisplayMode(); // One step advance
attempts++;
// Recalculate validity for the new mode
valid = false;
String ntpField = String(ntpServer2);
bool nightscoutConfigured = ntpField.startsWith("https://");
if (displayMode == 0) valid = true; // Clock always valid
else if (displayMode == 5 && showDate) valid = true;
else if (displayMode == 1 && weatherAvailable && (strlen(openWeatherApiKey) == 32) && (strlen(openWeatherCity) > 0) && (strlen(openWeatherCountry) > 0)) valid = true;
else if (displayMode == 2 && showWeatherDescription && weatherAvailable && weatherDescription.length() > 0) valid = true;
else if (displayMode == 3 && countdownEnabled && !countdownFinished && ntpSyncSuccessful) valid = true;
else if (displayMode == 4 && nightscoutConfigured) valid = true;
// If we've looped back to where we started, break to avoid infinite loop
if (displayMode == startMode) break;
if (valid) break;
} while (attempts < MAX_ATTEMPTS);
// If no valid mode found, fall back to Clock
if (!valid) {
displayMode = 0;
Serial.println(F("[DISPLAY] Safe fallback to CLOCK"));
}
lastSwitch = millis();
}
//config save after countdown finishes
bool saveCountdownConfig(bool enabled, time_t targetTimestamp, const String &label) {
DynamicJsonDocument doc(2048);
@@ -1527,20 +1594,57 @@ void loop() {
bool isDimmingActive = false;
if (dimmingEnabled) {
// Determine if dimming is active (overnight-aware)
if (startTotal < endTotal) {
isDimmingActive = (curTotal >= startTotal && curTotal < endTotal);
} else { // Overnight dimming
} else {
isDimmingActive = (curTotal >= startTotal || curTotal < endTotal);
}
if (isDimmingActive) {
P.setIntensity(dimBrightness);
int targetBrightness = isDimmingActive ? dimBrightness : brightness;
if (targetBrightness == -1) {
if (!displayOff) {
Serial.println(F("[DISPLAY] Turning display OFF (dimming -1)"));
P.displayShutdown(true);
P.displayClear();
displayOff = true;
displayOffByDimming = true;
displayOffByBrightness = false;
}
} else {
P.setIntensity(brightness);
if (displayOff && displayOffByDimming) {
Serial.println(F("[DISPLAY] Waking display (dimming end)"));
P.displayShutdown(false);
displayOff = false;
displayOffByDimming = false;
}
P.setIntensity(targetBrightness);
}
} else {
P.setIntensity(brightness);
// Dimming disabled: just obey brightness slider
if (brightness == -1) {
if (!displayOff) {
Serial.println(F("[DISPLAY] Turning display OFF (brightness -1)"));
P.displayShutdown(true);
P.displayClear();
displayOff = true;
displayOffByBrightness = true;
displayOffByDimming = false;
}
} else {
if (displayOff && displayOffByBrightness) {
Serial.println(F("[DISPLAY] Waking display (brightness changed)"));
P.displayShutdown(false);
displayOff = false;
displayOffByBrightness = false;
}
P.setIntensity(brightness);
}
}
// --- IMMEDIATE COUNTDOWN FINISH TRIGGER ---
if (countdownEnabled && !countdownFinished && ntpSyncSuccessful && countdownTargetTimestamp > 0 && now_time >= countdownTargetTimestamp) {
countdownFinished = true;
@@ -1575,6 +1679,19 @@ void loop() {
// --- BRIGHTNESS/OFF CHECK ---
if (brightness == -1) {
if (!displayOff) {
Serial.println(F("[DISPLAY] Turning display OFF"));
P.displayShutdown(true); // fully off
P.displayClear();
displayOff = true;
}
yield();
}
// --- NTP State Machine ---
switch (ntpState) {
case NTP_IDLE: break;
@@ -1625,7 +1742,7 @@ void loop() {
lastNtpRetryAttempt = millis(); // set baseline on first fail
}
unsigned long ntpRetryInterval = firstRetry ? 30000UL : 300000UL; // first retry after 30s, after that every 5 minutes
unsigned long ntpRetryInterval = firstRetry ? 30000UL : 300000UL; // first retry after 30s, after that every 5 minutes
if (millis() - lastNtpRetryAttempt > ntpRetryInterval) {
lastNtpRetryAttempt = millis();
@@ -1640,7 +1757,6 @@ void loop() {
}
// Only advance mode by timer for clock/weather, not description!
unsigned long displayDuration = (displayMode == 0) ? clockDuration : weatherDuration;
if ((displayMode == 0 || displayMode == 1) && millis() - lastSwitch > displayDuration) {
@@ -1728,6 +1844,7 @@ void loop() {
}
// Persistent variables (declare near top of file or loop)
static int prevDisplayMode = -1;
static bool clockScrollDone = false;
@@ -1898,7 +2015,6 @@ void loop() {
}
// --- Countdown Display Mode ---
if (displayMode == 3 && countdownEnabled && ntpSyncSuccessful) {
static int countdownSegment = 0;

View File

@@ -558,8 +558,8 @@ textarea::placeholder {
</label>
<label style="margin-top: 1.75rem;">Brightness: <span id="brightnessValue">10</span></label>
<input style="width: 100%;" type="range" min="0" max="15" name="brightness" id="brightnessSlider" value="10"
oninput="brightnessValue.textContent = brightnessSlider.value; setBrightnessLive(this.value);">
<input style="width: 100%;" type="range" min="-1" max="15" name="brightness" id="brightnessSlider" value="10"
oninput="brightnessValue.textContent = (this.value == -1 ? 'Off' : this.value); setBrightnessLive(this.value);">
<br><br><br>
<label style="display: flex; align-items: center; justify-content: space-between;">
@@ -583,8 +583,8 @@ textarea::placeholder {
</div>
<label style="margin-top: 1.75rem;" for="dimBrightness">Dimming Brightness: <span id="dimmingBrightnessValue">2</span></label>
<input style="width: 100%;" type="range" min="0" max="15" name="dimming_brightness" id="dimBrightness" value="2"
oninput="dimmingBrightnessValue.textContent = dimBrightness.value; ">
<input style="width: 100%;" type="range" min="-1" max="15" name="dimming_brightness" id="dimBrightness" value="2"
oninput="dimmingBrightnessValue.textContent = (this.value == -1 ? 'off' : this.value);">
<br><br><br>
<div class="form-group">
<label style="display: flex; align-items: center; justify-content: space-between;">
@@ -679,7 +679,7 @@ window.onload = function () {
document.getElementById('language').value = data.language || '';
// Advanced:
document.getElementById('brightnessSlider').value = typeof data.brightness !== "undefined" ? data.brightness : 10;
document.getElementById('brightnessValue').textContent = document.getElementById('brightnessSlider').value;
document.getElementById('brightnessValue').textContent = (document.getElementById('brightnessSlider').value == -1 ? 'off' : document.getElementById('brightnessSlider').value);
document.getElementById('flipDisplay').checked = !!data.flipDisplay;
document.getElementById('ntpServer1').value = data.ntpServer1 || "";
document.getElementById('ntpServer2').value = data.ntpServer2 || "";
@@ -713,7 +713,7 @@ document.getElementById('dimEndTime').value =
document.getElementById('dimBrightness').value = (data.dimBrightness !== undefined ? data.dimBrightness : 2);
// Then update the span's text content with that value
document.getElementById('dimmingBrightnessValue').textContent = document.getElementById('dimBrightness').value;
document.getElementById('dimmingBrightnessValue').textContent = (document.getElementById('dimBrightness').value == -1 ? 'Off' : document.getElementById('dimBrightness').value);
setDimmingFieldsEnabled(!!data.dimmingEnabled);

View File

@@ -33,7 +33,7 @@ const int IP_SCROLL_SPEED = 115; // Default: Adjust this for the IP Address
// WiFi and configuration globals
char ssid[32] = "";
char password[32] = "";
char password[64] = "";
char openWeatherApiKey[64] = "";
char openWeatherCity[64] = "";
char openWeatherCountry[64] = "";
@@ -46,6 +46,7 @@ String detailedDesc = "";
// Timing and display settings
unsigned long clockDuration = 10000;
unsigned long weatherDuration = 5000;
bool displayOff = false;
int brightness = 7;
bool flipDisplay = false;
bool twelveHourToggle = false;
@@ -58,6 +59,8 @@ char ntpServer2[256] = "time.nist.gov";
// Dimming
bool dimmingEnabled = false;
bool displayOffByDimming = false;
bool displayOffByBrightness = false;
int dimStartHour = 18; // 6pm default
int dimStartMinute = 0;
int dimEndHour = 8; // 8am default
@@ -330,7 +333,7 @@ void connectWiFi() {
clearWiFiCredentialsInConfig();
strlcpy(ssid, "", sizeof(ssid));
strlcpy(password, "", sizeof(password));
WiFiMode_t mode = WiFi.getMode();
Serial.printf("[WIFI] WiFi mode after setting AP: %s\n",
mode == WIFI_OFF ? "OFF" : mode == WIFI_STA ? "STA ONLY"
@@ -810,11 +813,36 @@ void setupWebServer() {
return;
}
int newBrightness = request->getParam("value", true)->value().toInt();
// Handle "off" request
if (newBrightness == -1) {
P.displayShutdown(true); // Fully shut down display driver
P.displayClear();
displayOff = true;
Serial.println("[WEBSERVER] Display set to OFF (shutdown mode)");
request->send(200, "application/json", "{\"ok\":true, \"display\":\"off\"}");
return;
}
// Clamp brightness to valid range
if (newBrightness < 0) newBrightness = 0;
if (newBrightness > 15) newBrightness = 15;
brightness = newBrightness;
P.setIntensity(brightness);
Serial.printf("[WEBSERVER] Set brightness to %d\n", brightness);
// Only run robust clear/reset when coming from "off"
if (displayOff) {
P.setIntensity(newBrightness);
advanceDisplayModeSafe();
P.displayShutdown(false);
brightness = newBrightness;
displayOff = false;
Serial.println("[WEBSERVER] Display woke from OFF");
} else {
// Display already on, just set brightness
brightness = newBrightness;
P.setIntensity(brightness);
Serial.printf("[WEBSERVER] Set brightness to %d\n", brightness);
}
request->send(200, "application/json", "{\"ok\":true}");
});
@@ -1163,7 +1191,7 @@ bool isFiveDigitZip(const char *str) {
// Weather Fetching and API settings
// -----------------------------------------------------------------------------
String buildWeatherURL() {
String base = "http://api.openweathermap.org/data/2.5/weather?";
String base = "https://api.openweathermap.org/data/2.5/weather?";
float lat = atof(openWeatherCity);
float lon = atof(openWeatherCountry);
@@ -1217,8 +1245,9 @@ void fetchWeather() {
String url = buildWeatherURL();
Serial.println(F("[WEATHER] URL: ") + url);
HTTPClient http; // Create an HTTPClient object
WiFiClient client; // Create a WiFiClient object
HTTPClient http; // Create an HTTPClient object
WiFiClientSecure client; // use secure client for HTTPS
client.setInsecure(); // disable certificate validation
http.begin(client, url); // Pass the WiFiClient object and the URL
@@ -1361,7 +1390,7 @@ void advanceDisplayMode() {
} else if (weatherAvailable && (strlen(openWeatherApiKey) == 32) && (strlen(openWeatherCity) > 0) && (strlen(openWeatherCountry) > 0)) {
displayMode = 1;
Serial.println(F("[DISPLAY] Switching to display mode: WEATHER (from Clock)"));
} else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful) {
} else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful && countdownTargetTimestamp > 0 && countdownTargetTimestamp > time(nullptr)) {
displayMode = 3;
Serial.println(F("[DISPLAY] Switching to display mode: COUNTDOWN (from Clock, weather skipped)"));
} else if (nightscoutConfigured) {
@@ -1375,7 +1404,7 @@ void advanceDisplayMode() {
if (weatherAvailable && (strlen(openWeatherApiKey) == 32) && (strlen(openWeatherCity) > 0) && (strlen(openWeatherCountry) > 0)) {
displayMode = 1;
Serial.println(F("[DISPLAY] Switching to display mode: WEATHER (from Date)"));
} else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful) {
} else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful && countdownTargetTimestamp > 0 && countdownTargetTimestamp > time(nullptr)) {
displayMode = 3;
Serial.println(F("[DISPLAY] Switching to display mode: COUNTDOWN (from Date, weather skipped)"));
} else if (nightscoutConfigured) {
@@ -1389,7 +1418,7 @@ void advanceDisplayMode() {
if (showWeatherDescription && weatherAvailable && weatherDescription.length() > 0) {
displayMode = 2;
Serial.println(F("[DISPLAY] Switching to display mode: DESCRIPTION (from Weather)"));
} else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful) {
} else if (countdownEnabled && !countdownFinished && ntpSyncSuccessful && countdownTargetTimestamp > 0 && countdownTargetTimestamp > time(nullptr)) {
displayMode = 3;
Serial.println(F("[DISPLAY] Switching to display mode: COUNTDOWN (from Weather)"));
} else if (nightscoutConfigured) {
@@ -1400,7 +1429,7 @@ void advanceDisplayMode() {
Serial.println(F("[DISPLAY] Switching to display mode: CLOCK (from Weather)"));
}
} else if (displayMode == 2) { // Weather Description -> ...
if (countdownEnabled && !countdownFinished && ntpSyncSuccessful) {
if (countdownEnabled && !countdownFinished && ntpSyncSuccessful && countdownTargetTimestamp > 0 && countdownTargetTimestamp > time(nullptr)) {
displayMode = 3;
Serial.println(F("[DISPLAY] Switching to display mode: COUNTDOWN (from Description)"));
} else if (nightscoutConfigured) {
@@ -1427,6 +1456,40 @@ void advanceDisplayMode() {
lastSwitch = millis();
}
void advanceDisplayModeSafe() {
int attempts = 0;
const int MAX_ATTEMPTS = 6; // Number of possible modes + 1
int startMode = displayMode;
bool valid = false;
do {
advanceDisplayMode(); // One step advance
attempts++;
// Recalculate validity for the new mode
valid = false;
String ntpField = String(ntpServer2);
bool nightscoutConfigured = ntpField.startsWith("https://");
if (displayMode == 0) valid = true; // Clock always valid
else if (displayMode == 5 && showDate) valid = true;
else if (displayMode == 1 && weatherAvailable && (strlen(openWeatherApiKey) == 32) && (strlen(openWeatherCity) > 0) && (strlen(openWeatherCountry) > 0)) valid = true;
else if (displayMode == 2 && showWeatherDescription && weatherAvailable && weatherDescription.length() > 0) valid = true;
else if (displayMode == 3 && countdownEnabled && !countdownFinished && ntpSyncSuccessful) valid = true;
else if (displayMode == 4 && nightscoutConfigured) valid = true;
// If we've looped back to where we started, break to avoid infinite loop
if (displayMode == startMode) break;
if (valid) break;
} while (attempts < MAX_ATTEMPTS);
// If no valid mode found, fall back to Clock
if (!valid) {
displayMode = 0;
Serial.println(F("[DISPLAY] Safe fallback to CLOCK"));
}
lastSwitch = millis();
}
//config save after countdown finishes
bool saveCountdownConfig(bool enabled, time_t targetTimestamp, const String &label) {
DynamicJsonDocument doc(2048);
@@ -1523,18 +1586,53 @@ void loop() {
bool isDimmingActive = false;
if (dimmingEnabled) {
// Determine if dimming is active (overnight-aware)
if (startTotal < endTotal) {
isDimmingActive = (curTotal >= startTotal && curTotal < endTotal);
} else { // Overnight dimming
} else {
isDimmingActive = (curTotal >= startTotal || curTotal < endTotal);
}
if (isDimmingActive) {
P.setIntensity(dimBrightness);
int targetBrightness = isDimmingActive ? dimBrightness : brightness;
if (targetBrightness == -1) {
if (!displayOff) {
Serial.println(F("[DISPLAY] Turning display OFF (dimming -1)"));
P.displayShutdown(true);
P.displayClear();
displayOff = true;
displayOffByDimming = true;
displayOffByBrightness = false;
}
} else {
P.setIntensity(brightness);
if (displayOff && displayOffByDimming) {
Serial.println(F("[DISPLAY] Waking display (dimming end)"));
P.displayShutdown(false);
displayOff = false;
displayOffByDimming = false;
}
P.setIntensity(targetBrightness);
}
} else {
P.setIntensity(brightness);
// Dimming disabled: just obey brightness slider
if (brightness == -1) {
if (!displayOff) {
Serial.println(F("[DISPLAY] Turning display OFF (brightness -1)"));
P.displayShutdown(true);
P.displayClear();
displayOff = true;
displayOffByBrightness = true;
displayOffByDimming = false;
}
} else {
if (displayOff && displayOffByBrightness) {
Serial.println(F("[DISPLAY] Waking display (brightness changed)"));
P.displayShutdown(false);
displayOff = false;
displayOffByBrightness = false;
}
P.setIntensity(brightness);
}
}
// --- IMMEDIATE COUNTDOWN FINISH TRIGGER ---
@@ -1570,6 +1668,17 @@ void loop() {
}
// --- BRIGHTNESS/OFF CHECK ---
if (brightness == -1) {
if (!displayOff) {
Serial.println(F("[DISPLAY] Turning display OFF"));
P.displayShutdown(true); // fully off
P.displayClear();
displayOff = true;
}
yield();
}
// --- NTP State Machine ---
switch (ntpState) {
@@ -1621,7 +1730,7 @@ void loop() {
lastNtpRetryAttempt = millis(); // set baseline on first fail
}
unsigned long ntpRetryInterval = firstRetry ? 30000UL : 300000UL; // first retry after 30s, after that every 5 minutes
unsigned long ntpRetryInterval = firstRetry ? 30000UL : 300000UL; // first retry after 30s, after that every 5 minutes
if (millis() - lastNtpRetryAttempt > ntpRetryInterval) {
lastNtpRetryAttempt = millis();

View File

@@ -558,8 +558,8 @@ textarea::placeholder {
</label>
<label style="margin-top: 1.75rem;">Brightness: <span id="brightnessValue">10</span></label>
<input style="width: 100%;" type="range" min="0" max="15" name="brightness" id="brightnessSlider" value="10"
oninput="brightnessValue.textContent = brightnessSlider.value; setBrightnessLive(this.value);">
<input style="width: 100%;" type="range" min="-1" max="15" name="brightness" id="brightnessSlider" value="10"
oninput="brightnessValue.textContent = (this.value == -1 ? 'Off' : this.value); setBrightnessLive(this.value);">
<br><br><br>
<label style="display: flex; align-items: center; justify-content: space-between;">
@@ -583,8 +583,8 @@ textarea::placeholder {
</div>
<label style="margin-top: 1.75rem;" for="dimBrightness">Dimming Brightness: <span id="dimmingBrightnessValue">2</span></label>
<input style="width: 100%;" type="range" min="0" max="15" name="dimming_brightness" id="dimBrightness" value="2"
oninput="dimmingBrightnessValue.textContent = dimBrightness.value; ">
<input style="width: 100%;" type="range" min="-1" max="15" name="dimming_brightness" id="dimBrightness" value="2"
oninput="dimmingBrightnessValue.textContent = (this.value == -1 ? 'off' : this.value);">
<br><br><br>
<div class="form-group">
<label style="display: flex; align-items: center; justify-content: space-between;">
@@ -679,7 +679,7 @@ window.onload = function () {
document.getElementById('language').value = data.language || '';
// Advanced:
document.getElementById('brightnessSlider').value = typeof data.brightness !== "undefined" ? data.brightness : 10;
document.getElementById('brightnessValue').textContent = document.getElementById('brightnessSlider').value;
document.getElementById('brightnessValue').textContent = (document.getElementById('brightnessSlider').value == -1 ? 'off' : document.getElementById('brightnessSlider').value);
document.getElementById('flipDisplay').checked = !!data.flipDisplay;
document.getElementById('ntpServer1').value = data.ntpServer1 || "";
document.getElementById('ntpServer2').value = data.ntpServer2 || "";
@@ -713,7 +713,7 @@ document.getElementById('dimEndTime').value =
document.getElementById('dimBrightness').value = (data.dimBrightness !== undefined ? data.dimBrightness : 2);
// Then update the span's text content with that value
document.getElementById('dimmingBrightnessValue').textContent = document.getElementById('dimBrightness').value;
document.getElementById('dimmingBrightnessValue').textContent = (document.getElementById('dimBrightness').value == -1 ? 'Off' : document.getElementById('dimBrightness').value);
setDimmingFieldsEnabled(!!data.dimmingEnabled);