Resi: checks keep quiet while a Resi event starts or stops (weekly schedule + PCO special services)

User 2026-10-26: three services each have a Resi event that starts and stops on its own; the cloud,
decoder and Resi audio checks threw false alarms then. resi_events (weekly, from studio.resi.io) and the
special services' times from PCO; checks marked quiet resi_events show OK (EVENT CHANGE) within 10 min of
an event's start or end. The encoder's ping and web checks still alarm.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-26 12:37:00 -04:00
co-authored by Claude Opus 5.5
parent 8b9a71eba0
commit aa90f7e03c
5 changed files with 149 additions and 7 deletions
+39
View File
@@ -1860,6 +1860,11 @@ def look(cfg, now=None, data_dir=None, sources=None):
lines["start"] = eval_start(rc, services, src["start"](services), now)
except Exception as e: # noqa: BLE001
failed(["start"], e)
if ((cfg.get("resi_events") or {}).get("pco_specials")) and not sources:
try:
LAST["resi_specials"] = resi_specials(rc, now)
except Exception as e: # noqa: BLE001 - only the quiet windows miss the special services
log.warning("READY resi specials: %s", e)
if rc.get("resi_vox"):
try:
try:
@@ -2038,6 +2043,40 @@ def upcoming_services(rc, now, fresh=False):
return out
RESI_SPECIALS = {}
def resi_specials(rc, now):
"""(start, end) of the special services' service times (First Tuesday, Flourish...) in the next 8 days, from
PCO's plan times - Resi streams those too, and the status page keeps quiet while they start and stop."""
if RESI_SPECIALS.get("key") == int(now // 1800):
return RESI_SPECIALS["list"]
auth, home = pco_login(rc)
types, _ = pco_get(auth, "/service_types?per_page=100", pages=3)
by_id = {x["id"]: x for x in types}
parent_of = lambda x: ((((x or {}).get("relationships") or {}).get("parent") or {}).get("data") or {}).get("id")
name_of = lambda x: ((x or {}).get("attributes") or {}).get("name") or ""
want = re.compile(rc.get("start_types", START_TYPES), re.I)
skip = re.compile(rc.get("start_skip_types", START_SKIP), re.I)
out = []
for x in types:
if x["id"] == home or parent_of(x) != parent_of(by_id.get(home)) or not want.search(name_of(x)) or skip.search(name_of(x)):
continue
plans, _ = pco_get(auth, "/service_types/%s/plans?filter=future&order=sort_date&per_page=3" % x["id"], pages=1)
for p in plans:
t = parse_iso((p.get("attributes") or {}).get("sort_date"))
if t is None or t > now + 8 * 86400:
continue
times, _ = pco_get(auth, "/service_types/%s/plans/%s/plan_times" % (x["id"], p["id"]), pages=1)
for pt in times:
a = pt.get("attributes") or {}
s, e = parse_iso(a.get("starts_at")), parse_iso(a.get("ends_at"))
if a.get("time_type") == "service" and s and e:
out.append((s, e))
RESI_SPECIALS.update(key=int(now // 1800), list=out)
return out
def start_params(rc, services, mode):
projects = rc.get("projects", "")
return {"mode": mode, "projects": projects, "site_folder": rc.get("site_folder", ""),