Main

How to Test a Smart Plug’s Local Fallback Without Cutting the Whole Network

The premise is wrong, and the fix is more useful than the test

“Unplug the router and see if the plug still works” sounds like a clean experiment. It isn’t. Pulling the router tests your entire household network at once, and it conflates two failures that behave very differently: losing the internet and losing the local network. A plug can pass a router-unplug test and still be cloud-dependent, because the router keeps serving the LAN even when the WAN link is gone. Conversely, a router unplug can break local control that would have survived an internet-only outage.

If you already run Home Assistant with Zigbee2MQTT, Z-Wave JS, ESPHome, or MQTT, the useful question isn’t “does the plug work?” It’s “which chain failed?” A smart plug has at least four separate control paths, and each one can fail independently:

  1. The physical button on the plug.
  2. A command from your local controller (Home Assistant) over the local network.
  3. A schedule or automation running on the controller.
  4. The state the controller reports back to you in the UI.

Record those four observations separately. A plug that toggles from its button but shows unavailable in Home Assistant is a different failure than one that ignores local commands entirely, and you can’t tell them apart from a whole-home outage.

Before you touch anything: establish a baseline

Pick one noncritical plug. A lamp, a fan, a holiday-light string. Not the freezer, not the sump pump, not anything on a medical device. The Home Resilience Hub’s offline-control audit is blunt about this: do not disconnect household internet, the router, hub, or a shared network when cameras, monitoring, access control, medical connectivity, or another important service depends on it. That warning applies to your test too, which is why we’re scoping it to one plug.

In Home Assistant, open the plug’s entity and record:

  • The exact entity ID and whether it’s exposed as a switch or an outlet. The device class tells Home Assistant whether a switch controls a power outlet, and the integration that provides the switch sets the device class. If your plug shows up as a generic switch when it should be an outlet, note that now — it affects how you read the UI later.
  • The current state: on, off, unavailable, or unknown. Home Assistant documents these four states for switch entities, and unavailable means the entity is currently unavailable — not that the plug is dead.
  • Which integration owns it: ZHA, Zigbee2MQTT, Z-Wave JS, an ESPHome node, or a cloud integration.
  • Whether the plug has a physical button and what it does (toggle, reset, pairing).

Write these down. You’ll compare against them after the test.

Know your availability timeout before you start the clock

This is the step most people skip, and it produces false readings. A plug that loses power or drops off its radio doesn’t flip to unavailable instantly. The controller waits for a timeout.

ZHA documents a setting called “Consider mains-powered devices unavailable after,” defaulting to 7200 seconds — two hours. You can lower it (the docs suggest 3600 for faster detection when a plug or bulb loses power), but if you leave it at the default, a short test window will show the plug’s last known state for up to two hours. That looks like “still working” when it isn’t.

Zigbee2MQTT has its own availability mechanism. Active devices — routers and mains-powered end devices — check in on an interval and get pinged if they miss it; passive devices check in far less often. The exact defaults should be confirmed from Zigbee2MQTT’s own documentation for your version before you rely on them, but the principle is the same: the timeout is longer than your patience.

For MQTT-backed plugs, the broker’s Last Will and Testament message is the signal. Home Assistant’s MQTT integration documents that the LWT is sent both on a clean disconnect and on an unclean one, such as losing a network connection. That’s useful, but it tells you about the client’s connection to the broker, not whether the plug itself is reachable.

So: either lower the timeout for the duration of the test, or make the test window longer than the timeout. Don’t do a five-minute test against a two-hour timeout and call it a result.

Isolate the cloud path, not the whole network

Here’s where I have to be honest about the limits of what’s documented. The clean way to test a single plug’s cloud dependency is to block only that plug’s outbound traffic — a per-device firewall rule, a dedicated VLAN, or a vendor-documented offline mode. I haven’t found primary documentation that gives a universal, supported procedure for this across plug brands, and I’m not going to invent one. What I can tell you is what the sources support and where the uncertainty sits.

One published guide suggests disconnecting the router from the internet while keeping the home network powered on, then checking the physical button, the app, and a scheduled event. That’s a reasonable approximation of an internet-only outage — but it still affects every device in the house, and it doesn’t isolate one plug. If you have cameras, monitoring, or anything else that depends on that router, don’t do it.

The safer options, in order of preference:

  1. A separate test network. Put the plug and a controller on an isolated access point or a spare router with no WAN connection. This tests the plug without touching the household network. It’s more setup, but it’s the only approach that doesn’t risk unrelated services.
  2. A per-device firewall rule. If your router supports blocking outbound traffic for a single MAC or IP, block just the plug. This is the closest thing to a true cloud-path isolation, but support varies by router and I can’t point to a universal procedure.
  3. Documentation and manufacturer support. If you can’t isolate the plug safely, read the manual for your exact model and firmware. Search for “internet outage,” “local control,” “cloud,” and “offline.” If the manual is silent, leave the result as unknown rather than guessing.

What I would not do is pull the household router and infer one plug’s behavior from the resulting mess. That’s the premise the original question got wrong.

The four observations, and what each one tells you

With the plug isolated (or with the internet path blocked), run each check separately and write down the result.

1. Physical button

Press the button on the plug. Does the relay click and the load change state? This path doesn’t depend on any network. If it fails, you have a hardware or firmware problem, not a connectivity problem, and the rest of the test is moot.

2. Local controller command

From Home Assistant on the local network, call switch.turn_on or switch.turn_off on the entity. Home Assistant documents these actions as part of the switch building block. Does the plug respond? If yes, the local controller path works and the cloud path is irrelevant to this command. If no, check whether the entity is unavailable — that tells you the controller lost the device, which is a different problem from the plug ignoring a command.

3. Schedule or automation

If you have a schedule that runs on the controller, wait for it to fire (or trigger it manually) and see whether the plug responds. A schedule stored in the vendor’s cloud will fail when the cloud is unreachable; a schedule running in Home Assistant’s automation engine will fire as long as the controller and the local network are up. The distinction matters: the plug can be perfectly local and still fail a schedule test because the schedule lived in the cloud.

4. UI state reporting

This is the one that fools people. After the test, look at the entity state in Home Assistant. Is it on, off, unavailable, or unknown? A plug that still toggles locally but shows unavailable in the UI means the controller lost the device’s availability signal — not that the plug stopped working. Check the availability mechanism (ZHA timeout, Zigbee2MQTT last-seen, MQTT LWT) before concluding anything.

For Zigbee2MQTT users, the Last Seen value is brought into Home Assistant as a diagnostic entity that is disabled by default. Enable it before the test if you want a timestamp to compare against. Without it, you’re reading tea leaves.

Reading the result correctly

Here’s the part where a short test window lies to you. Suppose you have a Zigbee plug on ZHA with the default two-hour unavailable timeout. You block its cloud path, wait ten minutes, and the entity still shows on. You conclude the plug is local. But the controller hasn’t yet decided the device is gone — it’s still showing the last known state. The plug might be unreachable and you wouldn’t know for two hours.

This is why the test duration has to exceed the configured timeout, or the timeout has to be lowered for the test. There’s no way around it. A five-minute test against a two-hour timeout is not a test; it’s a hope.

Record each chain as one of four values, following the Home Resilience Hub’s framing: works locally, needs internet, needs confirmation, or not tested. “App works” is not a useful single status, because the app might connect locally to one hub but depend on the cloud for a different feature. The same logic applies to your plug: the button, the controller command, the schedule, and the UI state are four separate results.

Restore and verify

Undo whatever you did to isolate the plug. Re-enable the firewall rule, reconnect the test network, or restore the router. Then confirm:

  • The entity returns to its expected state within the availability timeout.
  • The physical button still works.
  • Any schedule you paused resumes.
  • No entity is stuck in unavailable or unknown after a reasonable wait.

If something doesn’t recover automatically, note it. A plug that needs a manual re-pair after an outage is a different reliability problem than one that recovers on its own, and you want that in your record before you depend on it.

Turn the result into a record you’ll actually use

One line per plug, kept somewhere you’ll find it during an outage. Something like:

Living room lamp plug — Zigbee, ZHA, entity switch.living_room_lamp. Button: works locally. Controller command: works locally. Schedule: runs in HA, works locally. UI state during test: unavailable after 2h timeout, recovered on restore. Cloud path: not isolated, needs confirmation.

That record tells you what to do when the internet is down: use the button, or use Home Assistant on the local network, and don’t trust the UI state until the timeout has passed. It also tells you what you haven’t verified, which is just as important.

If you’re auditing more than one plug, the same approach scales. The small-systems audit covers the broader question of which quiet systems in your week deserve this kind of record; this procedure is the plug-specific version of it.

When a mechanical timer is the smarter choice

Not every plug needs this test. If the plug controls a lamp on a fixed schedule and nothing else depends on it, a $10 mechanical timer does the job with no network, no controller, and no availability timeout to reason about. It won’t integrate with Home Assistant, and it won’t give you energy monitoring, but it also won’t fail in a way you have to diagnose at 11 p.m.

The same goes for a plug on a circuit where a plain switch would do. Local fallback testing is worth the effort when the plug is part of an automation you rely on, or when you’ve already built a local-first stack and want to know which parts of it actually hold up. For a single lamp on a timer, the honest answer is that the mechanical timer wins on reliability per dollar, and no amount of Zigbee mesh routing changes that.

FAQ

Can I just unplug the router for ten minutes and see what happens?

You can, but it tests the whole household, not one plug, and it can disturb cameras, monitoring, or anything else on that router. The Home Resilience Hub’s guidance is explicit: don’t disconnect a shared network when important services depend on it. If you have nothing else on the router and you accept the disruption, it’s a rough approximation of an internet-only outage — but it won’t tell you which chain failed for a specific plug.

My plug shows unavailable in Home Assistant but the button still works. Is the plug broken?

No. unavailable means the entity is currently unavailable to Home Assistant — the controller lost the device’s availability signal. The plug itself may be fine. Check the availability timeout for your integration before concluding anything; ZHA’s default is two hours, so a short test can show the last known state rather than the current one.

Does a Zigbee or Z-Wave plug always work without internet?

No. The protocol doesn’t guarantee it. A Zigbee plug paired to a local coordinator will typically keep responding to local commands as long as the coordinator and the local network are up, but the exact behavior depends on the plug, the firmware, and the integration. The sources describe tendencies and dependencies, not guarantees. Test your specific plug rather than assuming.

How long should the test run?

Longer than your integration’s availability timeout. If you’re on ZHA with the default 7200 seconds, either lower the timeout for the test or run it for more than two hours. For Zigbee2MQTT, confirm the check-in interval for your device type from its documentation before setting the window. A test shorter than the timeout can produce a false “still working” reading.

What if I can’t isolate the plug’s cloud path safely?

Then don’t guess. Read the manual for your exact model and firmware, search for “local control” and “offline,” and if it’s silent, leave the result as unknown. A record that says “needs confirmation” is more useful than one that says “works” based on a test that didn’t actually isolate anything.