diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index fb67e578e0..efb818f87e 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -694,37 +694,71 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { CJSON(macroCountdown, cntdwn["macro"]); setCountdown(); + // Load timers into new vector-based system + clearTimers(); + + // Load regular timers from "ins" array JsonArray timers = tm["ins"]; - uint8_t it = 0; for (JsonObject timer : timers) { - if (it > 9) break; - if (it<8 && timer[F("hour")]==255) it=8; // hour==255 -> sunrise/sunset - CJSON(timerHours[it], timer[F("hour")]); - CJSON(timerMinutes[it], timer["min"]); - CJSON(timerMacro[it], timer["macro"]); - - byte dowPrev = timerWeekday[it]; - //note: act is currently only 0 or 1. - //the reason we are not using bool is that the on-disk type in 0.11.0 was already int - int actPrev = timerWeekday[it] & 0x01; - CJSON(timerWeekday[it], timer[F("dow")]); - if (timerWeekday[it] != dowPrev) { //present in JSON - timerWeekday[it] <<= 1; //add active bit - int act = timer["en"] | actPrev; - if (act) timerWeekday[it]++; + // Extract timer data from JSON + uint8_t hour = timer[F("hour")] | 0; + int8_t minute = timer["min"] | 0; + uint8_t preset = timer["macro"] | 0; + + // Handle weekdays and enabled state + uint8_t weekdays = (timer[F("dow")] | 0) << 1; // shift weekdays to upper 7 bits + if (timer["en"] | false) weekdays |= 0x01; // set enabled bit if timer is enabled + + // Handle date range for regular timers + JsonObject start = timer["start"]; + JsonObject end = timer["end"]; + uint8_t monthStart = start["mon"] | 1; + uint8_t dayStart = start["day"] | 1; + uint8_t monthEnd = end["mon"] | 12; + uint8_t dayEnd = end["day"] | 31; + + // Add regular timer to vector system + addTimer(preset, hour, minute, weekdays, monthStart, monthEnd, dayStart, dayEnd); + } + + // Load sunrise/sunset timers from separate "sunrise_sunset" object + JsonObject sunriseSunset = tm["sunrise_sunset"]; + if (!sunriseSunset.isNull()) { + // Load sunrise timer + JsonObject sunrise = sunriseSunset["sunrise"]; + if (!sunrise.isNull()) { + uint8_t preset = sunrise["macro"] | 0; + int8_t offset = sunrise["offset"] | 0; + uint8_t weekdays = (sunrise[F("dow")] | 0) << 1; + if (sunrise["en"] | false) weekdays |= 0x01; + + JsonObject start = sunrise["start"]; + JsonObject end = sunrise["end"]; + uint8_t monthStart = start["mon"] | 1; + uint8_t dayStart = start["day"] | 1; + uint8_t monthEnd = end["mon"] | 12; + uint8_t dayEnd = end["day"] | 31; + + addTimer(preset, TIMER_HOUR_SUNRISE, offset, weekdays, monthStart, monthEnd, dayStart, dayEnd); } - if (it<8) { - JsonObject start = timer["start"]; - byte startm = start["mon"]; - if (startm) timerMonth[it] = (startm << 4); - CJSON(timerDay[it], start["day"]); - JsonObject end = timer["end"]; - CJSON(timerDayEnd[it], end["day"]); - byte endm = end["mon"]; - if (startm) timerMonth[it] += endm & 0x0F; - if (!(timerMonth[it] & 0x0F)) timerMonth[it] += 12; //default end month to 12 + + // Load sunset timer + JsonObject sunset = sunriseSunset["sunset"]; + if (!sunset.isNull()) { + uint8_t preset = sunset["macro"] | 0; + int8_t offset = sunset["offset"] | 0; + uint8_t weekdays = (sunset[F("dow")] | 0) << 1; + if (sunset["en"] | false) weekdays |= 0x01; + + JsonObject start = sunset["start"]; + JsonObject end = sunset["end"]; + uint8_t monthStart = start["mon"] | 1; + uint8_t dayStart = start["day"] | 1; + uint8_t monthEnd = end["mon"] | 12; + uint8_t dayEnd = end["day"] | 31; + + addTimer(preset, TIMER_HOUR_SUNSET, offset, weekdays, monthStart, monthEnd, dayStart, dayEnd); } - it++; } JsonObject ota = doc["ota"]; @@ -1192,25 +1226,70 @@ void serializeConfig(JsonObject root) { goal.add(countdownHour); goal.add(countdownMin); goal.add(countdownSec); cntdwn["macro"] = macroCountdown; + // Separate regular timers and sunrise/sunset timers JsonArray timers_ins = timers.createNestedArray("ins"); - - for (unsigned i = 0; i < 10; i++) { - if (timerMacro[i] == 0 && timerHours[i] == 0 && timerMinutes[i] == 0) continue; // sunrise/sunset get saved always (timerHours=255) - JsonObject timers_ins0 = timers_ins.createNestedObject(); - timers_ins0["en"] = (timerWeekday[i] & 0x01); - timers_ins0[F("hour")] = timerHours[i]; - timers_ins0["min"] = timerMinutes[i]; - timers_ins0["macro"] = timerMacro[i]; - timers_ins0[F("dow")] = timerWeekday[i] >> 1; - if (i<8) { + JsonObject sunrise_sunset = timers.createNestedObject("sunrise_sunset"); + + Timer sunriseTimer, sunsetTimer; + bool hasSunrise = false, hasSunset = false; + + // Access the global timers vector from ntp.cpp + for (const auto& timer : ::timers) { + if (timer.isSunrise()) { + sunriseTimer = timer; + hasSunrise = true; + } else if (timer.isSunset()) { + sunsetTimer = timer; + hasSunset = true; + } else if (timer.isRegular()) { + // Skip completely empty regular timers + if (timer.preset == 0 && timer.minute == 0) continue; + + JsonObject timers_ins0 = timers_ins.createNestedObject(); + timers_ins0["en"] = timer.isEnabled(); + timers_ins0[F("hour")] = timer.hour; + timers_ins0["min"] = timer.minute; + timers_ins0["macro"] = timer.preset; + timers_ins0[F("dow")] = timer.weekdays >> 1; // remove enabled bit + JsonObject start = timers_ins0.createNestedObject("start"); - start["mon"] = (timerMonth[i] >> 4) & 0xF; - start["day"] = timerDay[i]; + start["mon"] = timer.monthStart; + start["day"] = timer.dayStart; JsonObject end = timers_ins0.createNestedObject("end"); - end["mon"] = timerMonth[i] & 0xF; - end["day"] = timerDayEnd[i]; + end["mon"] = timer.monthEnd; + end["day"] = timer.dayEnd; } } + + // Save sunrise timer if it exists + if (hasSunrise) { + JsonObject sunrise = sunrise_sunset.createNestedObject("sunrise"); + sunrise["en"] = sunriseTimer.isEnabled(); + sunrise["offset"] = sunriseTimer.minute; // offset in minutes + sunrise["macro"] = sunriseTimer.preset; + sunrise[F("dow")] = sunriseTimer.weekdays >> 1; // remove enabled bit + JsonObject start = sunrise.createNestedObject("start"); + start["mon"] = sunriseTimer.monthStart; + start["day"] = sunriseTimer.dayStart; + JsonObject end = sunrise.createNestedObject("end"); + end["mon"] = sunriseTimer.monthEnd; + end["day"] = sunriseTimer.dayEnd; + } + + // Save sunset timer if it exists + if (hasSunset) { + JsonObject sunset = sunrise_sunset.createNestedObject("sunset"); + sunset["en"] = sunsetTimer.isEnabled(); + sunset["offset"] = sunsetTimer.minute; // offset in minutes + sunset["macro"] = sunsetTimer.preset; + sunset[F("dow")] = sunsetTimer.weekdays >> 1; // remove enabled bit + JsonObject start = sunset.createNestedObject("start"); + start["mon"] = sunsetTimer.monthStart; + start["day"] = sunsetTimer.dayStart; + JsonObject end = sunset.createNestedObject("end"); + end["mon"] = sunsetTimer.monthEnd; + end["day"] = sunsetTimer.dayEnd; + } JsonObject ota = root.createNestedObject("ota"); ota[F("lock")] = otaLock; diff --git a/wled00/data/settings_time.htm b/wled00/data/settings_time.htm index ae29065ead..df7c855160 100644 --- a/wled00/data/settings_time.htm +++ b/wled00/data/settings_time.htm @@ -8,13 +8,25 @@
-