Schedule pages and rotation rules can be skipped in slow mode

Each page in a schedule block, and each rule that adds its page to the
rotation, has a "skip in slow mode" checkbox. While slow mode is on those
pages are left out of the rotation; when none of the block's pages are
left, the chosen page is shown. The rotation keeps its own timers.

Schedule format version 5; version 4 is converted when read and stored
again in version 5 on the next save.

Version 2.18.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mangavalkandClaude Opus 5.5 committed 2026-10-20 21:14:14 +02:00
1 parent a91d2550d7
commit e9f3c16c78
13 files changed
+177 -13

No files matched your search

+2
View File
@@ -25,6 +25,7 @@ struct ScheduleItem
{
char page[PAGE_NAME_SIZE] = "";
uint16_t seconds = 30;
bool skip_slow_mode = false; // left out of the rotation while slow mode is on
};
// From `start` (minutes since midnight) until the next block
@@ -66,6 +67,7 @@ struct TriggerRule
uint8_t blocks = 0; // bit i: active during block i; 0: always (also without a schedule)
bool over_manual = true; // also over a page picked by hand (false: it waits until the pick ends)
bool over_slow_mode = false; // while its page is shown the display works normally (slow mode waits)
bool skip_slow_mode = false; // AddToRotation: left out of the rotation while slow mode is on
};
struct PageSchedule
+4 -3
View File
@@ -131,15 +131,16 @@ PageChoice PageSelector::update(int minute, uint32_t now)
const ScheduleBlock &b = _schedule->blocks[_block];
effect = b.effect;
for (int i = 0; i < b.item_count; i++)
items[count++] = {b.items[i].page, b.items[i].seconds * 1000UL, ShowReason::Schedule, -1};
if (!_slow || !b.items[i].skip_slow_mode)
items[count++] = {b.items[i].page, b.items[i].seconds * 1000UL, ShowReason::Schedule, -1};
}
else
if (count == 0) // no schedule, a manual pick, or slow mode skips all the block's pages
items[count++] = {_chosen, CHOSEN_PAGE_SECONDS * 1000UL, ShowReason::Chosen, -1};
for (int i = 0; i < rule_count; i++)
{
const TriggerRule &r = _schedule->rules[i];
if (r.mode == TriggerMode::AddToRotation && _rule_active[i] && ruleInBlock(r, _block) &&
(r.over_manual || !_picked))
(r.over_manual || !_picked) && (!_slow || !r.skip_slow_mode))
items[count++] = {r.page, r.seconds * 1000UL, ShowReason::Rotation, i};
}
+6
View File
@@ -12,6 +12,8 @@
// 3. the schedule: the pages of the current block rotate, plus the pages of active
// AddToRotation rules
// 4. without a schedule (none, or switched off): the chosen page, plus AddToRotation pages
// In slow mode the items and AddToRotation rules with skip_slow_mode are left out of the
// rotation; when that leaves none of the block's pages, the chosen page is shown instead.
// Pure logic, tested in test/test_esp32. Times are millis().
enum class ShowReason : uint8_t
@@ -53,6 +55,9 @@ public:
// Start of the block that ends a manual pick (minutes since midnight), -1 when none
int pickedUntil() const;
// Slow mode is switched on (SlowModeSettings::enabled): leave out the skip_slow_mode pages
void setSlowMode(bool on) { _slow = on; }
// Whether a rule's condition is true now (from Home Assistant)
void setRuleState(int rule, bool active, uint32_t now);
bool ruleActive(int rule) const;
@@ -63,6 +68,7 @@ private:
const PageSchedule *_schedule = nullptr;
char _chosen[PAGE_NAME_SIZE] = "";
bool _picked = false;
bool _slow = false;
int _block = -1;
int _last_minute = -1;
int _item = 0;