← All posts Deutsch

Test an MQTT Payload Filter in Home Assistant Before Using It for an Alert

An MQTT automation can receive messages on the expected topic and still do the wrong thing. The payload filter might accept more than you intended, a template might compare the wrong field, or a retained value might look like a new event. The opposite happens too. A message can look right in an MQTT listener but never reach the action because the filter rejects it.

The question is whether one specific rule accepts the fictional message it should accept and rejects a similar message it should ignore. Knowing that Home Assistant can subscribe to MQTT isn't enough. A short, isolated test lets you check the rule without using a network observation, a NAS status, or a real alert as test data.

If you need to know which clients are actually present, establish that separately before designing an alert. How to See Every Device on Your Network and Find Its IP Address explains how to compare a scan with router information without treating a name, address, or single automation result as proof of identity.

The rule in plain language

Before opening the automation editor, write the intended rule as a sentence. For example: “Accept a message on lab/filter-check/2026-11-07/event only when its JSON field kind is exactly fictional_device_seen; then create one laboratory notification.” That gives you the topic, field, accepted value, and harmless result.

MQTT topic matching and payload matching answer different questions. An exact topic tells Home Assistant where to listen; a payload constraint tells it which messages on that topic matter to this automation. A message can pass one check and fail the other. Write them down separately. Otherwise, it's easy to change both at once and lose track of why the test result changed.

Keep the test topic separate from anything a real exporter, device, or service uses. A dated laboratory path such as lab/filter-check/2026-11-07/event reduces the chance of accidental overlap and makes the test easier to find later in a trace or broker log. Don't put a real hostname, MAC address, private address, customer name, password, or token in the topic or fixture.

Choose a result with no outside effect. A persistent notification with a fresh identifier can show that the accepted message reached an action. A dedicated helper or logbook entry can do the same. Don't start with a switch, lock, reboot, external message, or notification that someone is expected to act on. Even if the filter test succeeds, that isn't a reason to give the first action real consequences.

An accepted fixture and a control fixture

Use JSON only if the actual rule is supposed to read JSON. For this fictional test, the accepted fixture can be this small:

~~~json { "kind": "fictional_device_seen", "label": "Tutorial sensor", "test_id": "filter-check-2026-11-07" } ~~~

The label and identifier are invented examples, not device observations. The filter evaluates kind. The other fields are present but irrelevant, so a later reader won't mistake a label, device-like name, or identifier for the field that caused the match.

Prepare a control fixture on the same topic, changing only the field that decides the match:

~~~json { "kind": "fictional_device_ignored", "label": "Tutorial sensor", "test_id": "filter-check-2026-11-07" } ~~~

Don't skip the control. A notification from the accepted message shows that a path may have run, but it doesn't tell you whether the filter was selective. If both fixtures produce the same result, the rule accepts more than the written claim allows. If neither produces a result, check the subscription, topic spelling, enabled state, and payload parsing before changing the value you're testing.

Give every test result a unique identifier. A notification ID such as lab_filter_check_2026_11_07_accept is easier to distinguish from an old test than a generic title such as “MQTT alert.” Before testing, remove any older result with that ID or use a new ID. An old notification still on screen proves only that something created it earlier.

The filtering mechanism

Home Assistant MQTT triggers can constrain a payload directly. Templates can evaluate more detailed payload data. Pick the simplest mechanism that expresses the actual rule: an exact text payload may be enough for a simple message, while a JSON template can inspect a named field. Several fields in a fixture aren't a reason to write a complex template. This procedure tests filtering inside the MQTT trigger using payload and, for JSON, value_template. It does not test filtering in an automation condition, which can correctly reject a message after a run has started and leave a trace stopping at that condition.

For the fictional JSON above, test the value of kind. Don't just check whether fictional_device_seen appears somewhere in the raw payload. A substring can match text in an unrelated field, making a future message look as though it passed for the right reason when it didn't. Formatting changes can also make that check fragile. Comparing a named field leaves the intended condition easy to inspect.

Types matter. In JSON, 1, "1", true, and "true" are different values. If a real publisher sometimes sends a number and sometimes a string, document the inconsistency and decide which form is valid. Don't quietly accept both to get a passing test. Be just as careful with case and whitespace in text comparisons.

A template that renders without an error hasn't passed an automation test. Rendering checks the syntax and a supplied input. It doesn't show that the MQTT integration received a live message or that the topic matched. Nor does it show that the automation was enabled or an action ran. If you use this check, record it as a template-only check.

A limited test sequence

Before sending either fixture, note the current time, automation name, isolated topic, exact accepted value, chosen mode, and identifier of the harmless result. Check that the automation is enabled. Any existing trace or notification belongs to an earlier run, not this one. Start an independent MQTT listener subscribed to the exact test topic on the same broker, and keep it running throughout the test. Observe and record both exact fixtures and their receipt times there before interpreting their automation outcomes.

Send the non-matching control fixture once, without retain. First confirm that the independent listener received that exact fixture on the test topic. If it did not, the control test is inconclusive; a later successful accepted fixture cannot establish delivery of the control. Only after confirming receipt, check that the control didn't produce a new run or harmless result. “Nothing happened” isn't enough on its own: look for an unexpected automation trace or a notification with the test identifier. With filtering inside the MQTT trigger, if the automation ran, stop and inspect the filter before sending anything else.

Then send the accepted fixture once, also without retain, and record the publication time. Confirm that the independent listener received this exact fixture on the test topic too; if it did not, its automation outcome is inconclusive. A retained message can be delivered again after a subscription or broker reconnect. That behavior is worth testing separately, but it makes this check of the event path ambiguous. So does repeating the fixture until a notification appears. The result you eventually see may belong to an earlier or later attempt.

After confirming receipt of the accepted fixture, inspect the automation trace or other run record. The trigger data should show the exact laboratory topic and fictional payload. If the automation has conditions, check that the run passed them before reaching the harmless action. Then compare the action data and time with the new notification or helper state.

Keep these outcomes separate:

  • The independent listener received the exact control fixture on the test topic, and the control produced no matching run or result: evidence that this test rejected that one non-matching value at the MQTT trigger. Without confirmed receipt, the control outcome is inconclusive.
  • The independent listener received the exact accepted fixture on the test topic, and it produced a run with trigger data matching the topic and fixture: evidence that the trigger and its payload filter accepted that one message.
  • The run includes the named harmless action, and a fresh matching result is visible: evidence that this run reached that action.
  • A publish service accepted the request: evidence only that Home Assistant accepted a request to publish, not that the subscriber or action completed.

These observations don't prove that a real device is online, offline, owned by a particular person, or correctly identified. They don't guarantee future broker delivery either. They establish one narrow path at one time.

Failure checks at each boundary

If the control fixture triggers the automation, inspect the payload rule before changing the MQTT topic. Find out whether the automation compares a named JSON field, a raw payload string, or a template result. Check for another trigger in the same automation that could have started the run. A temporary automation with one trigger and one action is easier to follow than a production rule with several entry points.

If the accepted fixture doesn't create a run, start by checking the exact topic, broker selection, automation enabled state, and message formatting. MQTT topics are case-sensitive: Lab/filter-check is different from lab/filter-check. If a listener sees the message but the automation stays idle, that points you toward the automation's trigger, filter, conditions, or execution mode. It doesn't prove the action is broken.

If the trace shows the accepted trigger but there's no notification or helper update, check the conditions and action separately. A condition may deliberately stop the run. The action may use the wrong notification ID or service data. Don't edit the filter, condition, and action together. Change one boundary, then run a new dated laboratory test with a new identifier.

Automation mode matters when messages arrive close together. In single mode, a second trigger can be ignored while an earlier run is still active. Queued and parallel modes have different trade-offs. Don't change the mode just to get a result that looks successful. First establish whether a run existed and whether it reached the filter and action you meant to examine.

A small, useful test record

Save a compact record outside the automation: the rule sentence, automation name, isolated topic, accepted fixture, control fixture, retain setting, publication times, independent listener records of both exact fixtures and their receipt times, run times, result IDs, and observed outcomes. Leave out tokens, passwords, private hostnames, real device names, and customer data. That record lets a later check distinguish a rule change from a change in the broker or surrounding setup.

When you're done, dismiss the temporary notification. Reset or remove the dedicated helper if you used one, and disable or delete a purely temporary automation when appropriate. If you created retained laboratory messages for a separate test, remove them too. This cleanup keeps a dated fictional result from looking like a current operational alert.

DeviceShelf Server can publish network observations through MQTT discovery in a Home Assistant installation you administer. A payload filter is one step in verifying those observations. Compare a controlled fixture first, then check timestamps and independent network or service records before drawing a conclusion about a real device.

Network tips and product updates

The occasional guide, new features and release news, straight to your inbox. No spam, unsubscribe anytime.