MeranoWhat went wrong?Security and accessGetting started and running it

Both came home — and the automation said nothing

Unlocking the door was supposed to produce a photo. None appeared. The trigger was waiting for a state change this lock never makes.

A black ten-key keypad stuck to a marble wall beside the door.
A black ten-key keypad stuck to a marble wall beside the door.

On the flat door in Merano hangs a Tedee lock, integrated through its local bridge. An automation hangs off it: whoever unlocks triggers a camera snapshot, and the notification goes out.

It worked. The first image appeared on 9 August at 15:49:33, 65 kilobytes.

On 13 August both residents came home, at 18:12 and at 18:18. No image, no notification. Over its entire lifetime the automation had zero traces — the last entry came from the previous day’s manual test.

First, the storage location was wrong

That was the harmless part, and it still matters. The images initially landed in the folder for static files:

Location retrievable?
/config/www/… → /local/… HTTP 404 — measured
/media/schnappschuesse/… immediately visible in the media browser

The folder is registered at start-up. Files added later are not served by Home Assistant — hence the 404.

And even after a restart a second problem would remain:

/local is unauthenticated. Anyone who can reach the instance could fetch door images without logging in.

A picture of your own front door is not decoration. One line was changed — the target path — and since then the images sit behind the login, visible under Media → My Media.

And then the silent failure

The automation listened for the change from locked to unlocked. That sounds like the only sensible condition.

The recorded history of the lock says otherwise:

10:22:18  locked
18:12:45  unlocking        18:18:41  opening
18:12:52  opening          18:18:42  open
18:12:53  open             18:18:45  unlocked
18:12:55  unlocked

The jump from locked to unlocked does not exist. This lock goes through unlocking → opening → open and only reaches unlocked out of open.

So the condition could never fire. And it fails in the most unpleasant way:

No error message, no trace, no red dot. Just silence. Exactly the kind of fault you do not notice for months — because “nothing happened” looks like “there was nothing”.

The proof came from the sister automation

This is the part that turned the diagnosis from a guess into evidence.

A second automation hangs off the same lock; it arms a camera when the door is shut. Same entity, same moment — with one difference: it listens for to: unlocked without stating where from.

It fired cleanly at 18:18:45.348. In the same millisecond the other one stayed silent.

Two automations, one entity, one event, two different outcomes. The difference lay solely in the statement about the previous state.

A from: in a state trigger is not a refinement. It is a silent assumption about a device’s intermediate states — and you do not know those until you have looked them up.

Looking them up takes one line: query the history of that single entity through the interface and read the sequence of states.

The correction, and two subtleties in it

The trigger now has two cases and no origin:

triggers:
  - trigger: state
    entity_id: lock.<door>
    to: open        # somebody actually comes in
  - trigger: state
    entity_id: lock.<door>
    to: unlocked    # unlocked without opening, remotely for instance
mode: single
max_exceeded: silent

Two triggers, because there are two events. Somebody opens the door — or somebody unlocks it without opening, for a tradesperson say.

And exactly one notification, although both fire. In the sequence open → unlocked within two seconds, both triggers go off. The second is dropped because the first is still running — that is what mode: single is there for. And max_exceeded: silent keeps that intended drop out of the log as a warning.

The latter sounds cosmetic and is not: a log full of warnings that are all fine is a log nobody reads any more.

One decision about the camera I consider important

The door camera runs on battery. The first grab at an image can fail because the device is still waking up.

Both snapshot steps therefore carry a “continue on error”:

Better a notification without an image than no image and no notification.

A step that aborts an entire automation because a by-product failed is weighted wrongly. The notification is the point; the image is the bonus.

What I’d suggest

  1. Look at the real state history before you build a from: trigger. Devices have intermediate states that appear in no documentation.
  2. Measure whether your automation has ever fired. The number of triggerings is the cheapest check there is — and here it would have said “zero” immediately.
  3. Put door images behind the login. The static-file folder is open and does not serve later additions anyway.
  4. Use two triggers when there are two events — and deliberately turn the duplication into a single notification.
  5. Do not let an automation fail on its bonus. A failed snapshot must not prevent the notification.
  6. Keep your log clean. An intended drop does not belong in it as a warning.

So what?

For four days the door was unobserved, and nobody would have noticed. The difference from a loud failure is that a loud failure sends a message. Here there was nothing — the system considered everything to be in order, because from its point of view there had never been anything to do.

That is the same pattern as the umlaut that killed my frost alarm and the watchdog waiting for the wrong state. Three times the same construction: a condition containing an assumption about the device, and a device that behaves differently.

I only found it because a second automation happened to hang off the same entity and fired cleanly. Without that control I would have suspected the lock, the camera, the notification path — everything except the one parameter that was the problem.