Skip to content

How Device Sentinel Learns

TheThinkingHome edited this page Aug 8, 2026 · 17 revisions

How Device Sentinel Learns

The feature underneath everything: each home's devices are learned individually. No fixed timeout exists anywhere in Device Sentinel, because no fixed timeout can be right for both a motion sensor that speaks every 30 seconds and a water meter that speaks twice a day.

Watching

Device Sentinel listens passively to Home Assistant's event bus. Every time any entity of a device reports, that device's clock is stamped. Statistics are kept per device, not per entity, so any entity's activity proves the device is alive.

Service entries, cloud connections, and other devices with no hardware behind them are classified out automatically and never watched. You will see these tallied as the Service Devices Ignored count on the device page.

Learning the Rhythm

For each device, each day, Device Sentinel records the longest quiet gap: the worst silence that still turned out to be normal. Those daily maxima build a rolling two-week picture.

The device's rhythm is the trimmed maximum of that window. The single worst day is set aside as a suspected anomaly, and the rhythm is the worst of what remains. This is deliberate: one bad day, like a Zigbee hiccup or an hour of WiFi trouble, moves nothing. A spike that repeats survives the trim and correctly widens the rhythm, because a device that genuinely got slower should be learned as slower.

Completed gaps only: Only completed gaps are learned. A device that goes silent and stays silent never finishes its gap, meaning a freeze can never teach the system that freezing is normal. One exception runs in the safe direction: after a power cut, the silence a device had already accumulated before the lights went out is kept as a completed gap, marked truncated in the episode report. It is a lower bound on the true gap, so it can only move that day's figure toward the truth and never past it.

Bounded learning on recovery: What a gap may teach is also bounded if the device was flagged as frozen. A flagged device that suddenly speaks again might have recovered on its own, or it might have been fixed by a hand the integration cannot see. To prevent one mysterious resurrection from widening a freeze window for two weeks, its gap is learned at most as the rhythm plus a modest allowance, generous for fast devices, small for slow ones. A genuinely slowed device will still teach its new pace within a few detections, but an outlier cannot ruin the statistics. The episode report marks when this happens with a capped label; see The Diagnostic Reports for the vocabulary.

Arming

A device is judged for a freeze only after it has enough learned days to have a trustworthy rhythm, shown in the Devices Learned count. Before that, it is judged only for going unavailable, which needs no rhythm to catch.

Each device arms itself individually; there is no global learning mode. A device added a year from now starts learning the day it arrives without you needing to switch anything. Devices with no natural heartbeat, like buttons and remotes that speak only when pressed, never establish a rhythm and are effectively never judged frozen. This is by design, and it is why your Devices Learned count is not expected to reach your Devices Watched count.

Remembering and Judging Are Different Questions

Every verdict comes from a recent window, and the three detectors use three different ones, because they measure three different shapes.

  • The rhythm: fourteen days. A device's reporting rhythm is the trimmed maximum of the last fourteen daily gaps. Extending it was tested on a real fleet and left seventy-nine of ninety-four devices identical while making the rest less sensitive, so fourteen it stays.
  • The signal floor: thirty days. A floor is a trimmed minimum, so a short window forgets how bad a device really gets. At fourteen days, fifty-one of seventy-eight devices on the same fleet had a worse day sitting just outside the window, and the floor jumped every time one aged out. That jumping is what made signal readings swing wildly from one day to the next.
  • The battery slope: seven days. Battery detection watches for the moment a cell leaves its plateau. A longer window averages the plateau in with the fall and halves the apparent rate, which is exactly the thing it exists to catch.

None of the three is a setting. A threshold that moved with a storage preference would mean two identical systems detecting differently for no reason anyone chose.

How much history is kept is a separate question entirely, and it is yours to answer on the Advanced screen. History is kept far longer because some things cannot be seen in a few weeks at all: a battery barely moves, a signal floor takes a season to settle, and deciding whether these are even the right windows takes months of evidence to study. The long record exists to be studied; the short windows do the deciding. Keeping a year of history detects exactly what keeping thirty days detects.

Knowing When a Device Actually Spoke

Restarts, integration reloads, and radio reconnects all produce bursts of traffic that look like devices reporting when nothing has actually been heard from them. A Zigbee bridge coming back online publishes every device's last known state; Home Assistant starting up re-reads whatever it can. Treating any of that as a device speaking would erase the silence behind it, which is exactly the silence worth noticing.

The protocol clock: Device Sentinel asks a better question than whether a message arrived. Many integrations publish a last-contact time, which is the coordinator's own record of when it genuinely last heard from a device. Where that exists, it is the clock. A replayed message carries the old reading, so it cannot advance anything, and the silence keeps running until the device actually speaks. A device whose last-contact entity is itself unavailable is treated as not heard from, which is precisely the state a stuck device sits in.

When there is no clock: Where an integration publishes no such time, the moment a report arrives is the only evidence there is, and it counts. This includes the report a device makes when the system restarts. A nightly restart is part of a home's rhythm rather than interference to filter out. Treating it as interference had a real cost: a device that is simply quiet overnight ended up with an idea of normal that covered only the hours after the restart, and was then falsely reported for being quiet during the hours before it.

Storms and Polling

For devices without a protocol clock, replay bursts are still caught a direct way. When one integration's devices all report in the same instant, the burst is recognized as a storm, and its stamps are excluded from learning so an integration reload cannot teach a false rhythm.

A storm is also recorded: an opening, a closing, a duration, and how many devices were caught, kept both in the system events log and in a history on disk for as long as your retention setting. The daily brief names it beside restarts and coordinator outages, so an integration reloading is no longer invisible: "The reolink integration reloaded at 4:12 PM." An integration that storms many times over reads as one line rather than two sentences each time, such as "The tplink_router integration reloaded 20 times between 12:50 PM and 1:56 PM, up to 5 device(s) at a time." A burst that happens while Home Assistant is starting up is not recorded separately, because the restart is already recorded and already explains those devices.

Some integrations poll every device they own on a timer, so all of them report inside the same second, over and over. That is indistinguishable from a hub reconnecting, and excluding those stamps from learning would throw away the very rhythm those devices have. Enough storms inside an hour and the integration is read as a poller instead, and its bursts are learned normally.

That count comes from the stored history rather than from what has been seen since the last restart, so a pattern spread across days is visible on a system that reboots nightly. It is recomputed each time rather than written down once, so an integration that settles down stops being treated as a poller.

Time Nothing Was Listening

Time when nothing was listening is never counted against a device. The stretch before a restart, when the integration was not running, is credited to every device rather than held against it. A startup grace also sets aside silences already running across the first moments of a new session, so a restart can never convert an unobserved stretch into a lesson.

Gaps Treated with Care

Some silences cover time that could not be reliably observed or judged, and are set aside from learning:

  • Unavailable stretches: If a device was unavailable only briefly, a passing mesh hiccup, the silence around it is real and is learned. If it was unavailable long enough that its return looks less like a recovery and more like someone fixing it, replacing a battery, re-pairing, power-cycling, the gap is set aside. A hand-fixed outage should not teach the device that being gone for hours is normal. Because the integration cannot see a hand on a device, the length of the unavailable stretch is the only thing that separates the two. Where that line sits is the blip tolerance on the Advanced screen.
  • Coordinator outages: A silence spanning a coordinator outage that ended with the bridge reconnecting is set aside, because the gap measures the outage, not the device's rhythm.
  • Broker outages: Where every MQTT device goes quiet at once because the broker stopped, the outage is recorded and the devices are not blamed for it. A coordinator cannot see this: when the broker stops, nothing delivers the coordinator's own last message, so the bridge goes on reading as running while everything behind it is silent. On a real fleet a sixteen-minute broker outage opened no silence episodes at all, because Home Assistant marked those entities unavailable and the existing handling covered them. What the record gains is that the outage is named rather than left as a crowd of unexplained faults.
  • Pairing windows: A gap ending during a Zigbee pairing window is set aside as a manual re-pair.

The episode report records each of these set-asides with its specific reason. See The Diagnostic Reports for how to read them.

How the Cause Reaches You

When a device goes quiet and comes back, the explanation given is a recorded event that was in effect when the device went quiet and that reaches that device. A restart explains any device, a broker outage explains devices that speak through it, a coordinator explains its own stack, and an integration reload explains only its own devices. Where nothing fits, no cause is named. A group of devices explained by the same event reads as one line in the daily brief rather than one sentence each.

Persistence

Everything survives restarts. The learned statistics, every device's clock, and any flag in progress are stored on disk. A device that is twenty hours into a freeze is still twenty hours frozen after a reboot.

Clone this wiki locally