A classic motion sensor only knows two things: motion right now, or none right now. What it doesn’t answer out of the box is the far more useful question — when was someone last in this room? That single piece of information is the foundation for any presence heuristic: “house empty for two hours”, “nobody in the hallway since breakfast”, “has anyone even been in the garage today”.
My first instinct was to buy expensive mmWave presence sensors for this. But the plain PIR detectors already on the wall are enough — you just have to store their last on-moment somewhere. In Home Assistant that’s an input_datetime helper per room plus a trivial automation. This isn’t a light-switching tutorial; it’s a pure data pattern that I’ve since rolled out across the whole house.
Fair objection: every sensor already has a last_changed attribute. The problem is that last_changed flips on every state change — including the switch from on back to off. So you get the time of the last change, not the last motion. And it doesn’t survive a Home Assistant restart cleanly: after a reboot the sensor sits freshly at off, last_changed is the boot time, and your history is gone.
An input_datetime helper fixes both. We write the timestamp only on the transition to on, the value is persistent (it survives restarts), and it’s a real, queryable entity you can use in templates, conditions and on the dashboard just like any other sensor.
Step 1 — create one helper per room
Under Settings → Devices & Services → Helpers, create an input_datetime for each room with both date and time enabled. I keep the naming strictly consistent — letzte_bewegung_<room> (last_motion_<room>) — because that makes later scaling trivial: new entity, same schema. If you prefer YAML, the same thing goes into configuration.yaml.
The only thing that matters is that both flags are set — without has_time you lose the time of day and the whole pattern goes blunt.
Step 2 — write the timestamp on every motion
Now the actual logic, and it’s pleasantly short: an automation that, on the motion sensor’s transition to on, writes the current time into the matching helper via input_datetime.set_datetime. I deliberately trigger only on to: ‘on’ — the off event doesn’t interest us, we want to capture the start of the last motion.
The now().strftime(…) formats the local time into exactly the format set_datetime expects. mode: single is plenty: the action takes milliseconds, parallel runs are irrelevant.
Step 3 — the same pattern across rooms
The real charm is repeatability. For every additional room you copy the automation and swap only two things: the entity_id of the motion sensor and the entity_id of the helper. Same shape, different room.
I run about a dozen of these automations in parallel — one per PIR. If you prefer something more compact you can build a single automation with multiple triggers and a template over trigger.to_state; I prefer the one-per-room variant because it stays instantly readable in the UI and lets you disable individual rooms on purpose.
Step 4 — relative time on the dashboard
The raw timestamp “2026–07–17 14:32:10” is awkward on a dashboard — what’s interesting is “12 minutes ago”. For that Home Assistant has the template function relative_time(), which turns a datetime into a human-readable span. In a Markdown card it looks like this:
The as_datetime converts the string state into a real datetime object that relative_time can process. The result is a compact overview — “Hallway: 3 minutes ago, Garage: 6 hours ago” — that tells you at a glance where there was life most recently.
What the data is good for
Once the timestamps exist, the interesting automations open up. A “house empty” heuristic: if the most recent of all letzte_bewegung_* times is older than, say, 30 minutes, the house counts as unoccupied — cheap presence detection without an mmWave sensor. Or room-scoped triggers: only ramp up the heating in a room if there’s been motion there in the last hour. If you like the Modbus/sensor-data way of thinking, you’ll find the same “data first, logic second” stance in my post on PV string fault detection.
Frequently asked questions
Why not just use the sensor’s last_changed attribute?
Because last_changed flips on every state change — including the switch from on to off — and doesn’t survive a restart: after a reboot the sensor sits freshly at off and last_changed is the boot time. The input_datetime helper, by contrast, stores only the last on-moment, is persistent, and survives restarts.
Does the value survive a Home Assistant restart?
Yes. input_datetime helpers are persistent — their last set value is stored and restored after a reboot. That’s one of the main advantages over raw sensor attributes, which start from scratch after a restart.
Do I need a separate automation per room?
No, but it’s the most readable option. You can also build a single automation with multiple triggers and pick the matching helper from a mapping via trigger.to_state. I deliberately use one automation per room because it stays instantly understandable in the UI and can be disabled individually.
Does this work with any motion sensor?
With any that shows up in Home Assistant as a binary_sensor with on/off states — Zigbee PIR, KNX presence detector or Wi-Fi sensor alike. The pattern doesn’t know the hardware, it only reacts to the on transition. On KNX detectors that I also use for light switching, the same timestamp automation runs alongside without issue.
Originally published at https://www.cloudapp.dev.
A ‘Last Motion’ Sensor in Home Assistant was originally published in Stackademic on Medium, where people are continuing the conversation by highlighting and responding to this story.
PakarPBN
A Private Blog Network (PBN) is a collection of websites that are controlled by a single individual or organization and used primarily to build backlinks to a “money site” in order to influence its ranking in search engines such as Google. The core idea behind a PBN is based on the importance of backlinks in Google’s ranking algorithm. Since Google views backlinks as signals of authority and trust, some website owners attempt to artificially create these signals through a controlled network of sites.
In a typical PBN setup, the owner acquires expired or aged domains that already have existing authority, backlinks, and history. These domains are rebuilt with new content and hosted separately, often using different IP addresses, hosting providers, themes, and ownership details to make them appear unrelated. Within the content published on these sites, links are strategically placed that point to the main website the owner wants to rank higher. By doing this, the owner attempts to pass link equity (also known as “link juice”) from the PBN sites to the target website.
The purpose of a PBN is to give the impression that the target website is naturally earning links from multiple independent sources. If done effectively, this can temporarily improve keyword rankings, increase organic visibility, and drive more traffic from search results.