Summary
Fixes #111 — the school time switch in HA (switch.<child>_school_time) and the companion services familylink.enable_school_time / familylink.disable_school_time appeared to succeed but did not actually lock or unlock the child device.
Root cause
The previous implementation only flipped the weekly school time policy via:
PUT /timeLimit:updateThat call is what the web app sends when you toggle the big switch in the "Schedules" page — it's correct, but on its own it's not enough.
If the current weekday has no slot in the weekly schedule (e.g. a Saturday on a Mon–Fri schedule), the child device sees no state change, because nothing in the weekly rule applies right now.
The official Family Link web app gets around this by always layering a daily override on top of the weekly policy whenever the user toggles "Today" in the schedules screen.
That override is what actually makes the device react. Our code never sent it.
What changed
async_enable_school_time / async_disable_school_time (and the corresponding services) now replicate the behavior of the official web app.
Enable flow
Creates a daily override:
POST /people/{id}/timeLimitOverrides:batchCreatewith:
type=9action=2- time window:
now → 23:59 - today's ISO weekday
- reference to the school time rule UUID
Disable flow
- Fetch existing overrides:
GET /timeLimit- Remove any existing school time override matching:
- today's weekday
- the school time rule UUID
using:
POST /timeLimitOverride/{uuid}?$httpMethod=DELETE- Recreate the override with:
action=1
via:
POST /timeLimitOverrides:batchCreateThis mirrors the Family Link web app behavior (DELETE → CREATE) and avoids stacking conflicting overrides on the same day.
Important behavior change
The weekly policy:
PUT /timeLimit:updateis no longer modified by these switch/service calls.
The daily override alone is sufficient and better matches user expectations:
"I toggled it, it should lock/unlock right now."
The switch now controls only today's active state, not the persistent weekly schedule.
Reverse engineering notes
The payload format was captured directly from the official Family Link web app (Flutter Web) by intercepting XMLHttpRequest calls.
Override structure:
[
null, null, 9, null, null, null, null, null, null, null, null, null,
[
action,
[now_h, now_m],
[23, 59],
null,
[iso_weekday, ""]
]
]Where:
action=2→ enable school timeaction=1→ disable school timeiso_weekday1 = Monday7 = Sunday
The full payload and a new section:
School time daily override pattern
were added to:
GOOGLE_FAMILY_LINK_API_ANALYSIS.md
Risk assessment
- Bedtime is untouched — same code path as before.
- Daily limits are untouched — separate implementation.
- The weekly school time policy is intentionally left unchanged.
Users relying on the switch to persist weekly state will see a behavior change:
- before → modified the weekly schedule
- now → controls only today's effective state
This matches the expected behavior reported in issue #111.
Test plan
-
switch.turn_ononswitch.<child>_school_timelocks the child device immediately, even outside any configured weekly slot (e.g. Saturday with a Mon–Fri schedule). -
switch.turn_offunlocks the child device immediately, even during an active weekly slot. - Rapid off/on toggling does not leave duplicate overrides.
- Family Link app reflects only the latest "Today" action.
- Bedtime switch still works (regression check).
- Daily limit services still work (regression check).
Version
Bumps to:
1.2.7
Released initially as:
1.2.7 pre-release
for early validation.