Skip to main content

TP-Link Kasa

Local control of TP-Link Kasa smart plugs and power strips (HS-series, KP-series) over the device's own LAN API. No Kasa cloud account and no hub sit in the middle — GEM talks straight to the device's IP address on port 9999, and no username or password is required.

This is an on/off power switch integration. A Kasa outlet either passes power or it doesn't; the driver does not dim, and it does not read the energy metering that some strips report. Use it to switch lights, appliances, and other loads, to power-cycle gear, or — wired to a momentary trigger — to pulse a gate or garage operator.

The standout feature is auto-discovery: when you add a multi-outlet Kasa device and enable it, GEM reads the strip's outlet list and creates one zone per outlet automatically, under the Power subsystem. You normally do not add zones by hand.

One device, many zones

One Kasa device in GEM is one physical unit (a plug or a strip). On a multi-outlet strip — HS300, KP303, KP400, EP40 — each outlet becomes its own zone, so a 6-outlet HS300 gives you six independent on/off zones.

Prerequisites

  • Pair the Kasa device in the Kasa mobile app first and put it on the same LAN the GEM controller can reach.
  • Give the device a static IP or a DHCP reservation. The integration addresses the device by IP, so a moving lease takes it offline.
  • Name each outlet in the Kasa app before you add it to GEM (e.g. "Patio Lights", "Christmas Tree"). GEM uses each outlet's Kasa alias as the new zone's label, so naming them first saves you renaming zones afterward.
  • Confirm the unit still exposes its local LAN API. Some 2024-and-newer Kasa and Tapo firmware silently disables the legacy local API in favor of a cloud-only protocol — see Troubleshooting.

Setup

  1. Open Devices and add a new device. Pick the TP-Link Kasa driver.
  2. In Kasa IP Address enter the device's LAN IP (e.g. 192.168.1.50). No credentials are needed.
  3. Enable the device. On connect, the driver reads the strip's outlet list and creates one zone per outlet under the Power subsystem, named after the outlet aliases you set in the Kasa app.
  4. Open Zones to confirm the new zones appeared. Each one is a Light Switch-style power control with on/off. Rename, re-home to a different subsystem, or assign them to UIs as you would any other zone.
Single-outlet plugs aren't auto-provisioned

The driver discovers outlets from the device's child-outlet list, which only multi-outlet strips report. A single-outlet plug (HS100/HS103/HS110, KP105/KP115, EP10, and similar) has no child list, so no zone is created and the plug can't be controlled through this driver. Use a multi-outlet Kasa device, or switch that single load through a different relay/plug integration.

How outlets become zones

Each auto-created zone carries an address equal to the outlet's Kasa child id — a long hexadecimal string the driver fills in for you. You don't type it; the address field's hint ("Kasa child outlet id (auto-populated on discovery)") reflects that it's populated during discovery.

The outlet list is read only at connect time. If you add or re-map outlets, or upgrade firmware, reload the device so the driver re-enumerates and binds any new outlets — see Troubleshooting.

Subsystem and control type

New zones land on the Power subsystem with a standard on/off power control. That's the right home for switched lights and appliances. The driver also suggests Lights and Garage as subsystems if a particular outlet fits better there:

  • A switched light or appliance — leave it on Power (or move it to Lights). on / off energize and de-energize the outlet.
  • A gate or garage operator wired to a Kasa outlet's trigger — move the zone to the Garage (or Gates) subsystem and mark it momentary so open/close become a pulse. See Momentary and garage outlets.

There is no dimmer control type for Kasa — these are on/off outlets. A level command is treated as on/off (any level above 0 turns the outlet on, 0 turns it off).

State polling

While the device is enabled, the driver polls each of its zones in turn and writes the result back to the zone's state (on / off). Outlets are queried about 500 ms apart so a multi-outlet strip isn't hit all at once, and the whole sweep repeats on the device's Status Poll Interval (status_interval, default 1000 ms). If a busy device or network struggles, raise status_interval.

A zone can also mirror another zone's state instead of polling its own outlet: set the zone's status_zone attribute to another zone's id and it follows that zone's state. This is the same status-mirroring pattern used elsewhere in GEM (for example, a relay zone that reports position from a separate sensor zone).

Power-cycling and momentary outlets

The driver turns two real-world actions into outlet sequences:

  • Reboot (power-cycle)reboot turns the outlet off, waits, then turns it back on. The default gap is 5000 ms. Use it to hard-restart a modem, AP, or other load that's hung. Pass a delay arg (in ms) to change the off-time; raise it for loads sensitive to fast cycling.
  • Momentary pulse — a pulse turns the outlet on, waits, then turns it back off. The default pulse is 1000 ms. This is what a gate or garage operator's trigger input expects.

Momentary and garage outlets

If a zone sits on the Garage subsystem (or the Garage subsystem itself is set momentary) and that zone is marked momentary, the driver rewrites open and close commands into a pulse automatically — one press fires the operator and the outlet returns to off. To override the pulse length for a specific command, pass a delay arg (ms); the per-zone Pulse Delay (delay) attribute records the intended momentary pulse length for the outlet.

Because a switched outlet can't tell you whether the door actually opened, point the outlet zone's status_zone attribute at a separate input zone wired to a reed/limit switch so the zone reports real open/closed position.

Attributes

Add these in the Attribute editor for the device or zone; the labeled ones also have fields in the device/zone forms.

Device

AttributeTypeRequiredDefaultDescription
ipstringyesLAN IP of the Kasa plug or strip. Shown as Kasa IP Address.
status_intervalintno1000Status Poll Interval (ms) — how often the full outlet sweep repeats.

Zone

AttributeTypeRequiredDefaultDescription
addressstringyesautoKasa child outlet id. Auto-populated on discovery — you don't normally type it.
delayintnoPulse Delay (ms) — intended pulse length for a momentary/garage outlet.
status_zoneintnoId of another zone whose state this zone should mirror instead of polling its own outlet.

Commands

These are the commands the driver writes and keeps current, so they appear automatically on the device's Commands page and can be tested there.

CommandArgsWhat it does
onaddressTurn the outlet on.
offaddressTurn the outlet off.
levellevel, addressOn/off only — any level above 0 turns the outlet on, 0 turns it off. Kasa outlets don't dim.
rebootdelay, addressPower-cycle: turn the outlet off, wait delay ms (default 5000), then on.
get_stateaddressRead the outlet's current state now and reconcile the zone.
Driver-managed commands

The rows above are rewritten by the driver every time the system starts. Add your own commands if you need them, but don't hand-edit the templates or args of these — your changes are overwritten on the next restart.

On a momentary zone on the Garage (or Gates) subsystem, open and close are converted to a pulse (on → wait → off, default 1000 ms) before they run — see Momentary and garage outlets.

Troubleshooting

SymptomCheck
Device never connects; log shows tplink kasa missing ipThe Kasa IP Address (ip) attribute is blank. Set it to the device's LAN IP.
Connect timeout on a known-good IPThe unit's firmware may have migrated to the cloud-only Tapo protocol and dropped the local LAN API. Test from the host with a Kasa LAN tool (e.g. kasa --host <ip>). If the local API is gone, downgrade the firmware or replace the unit.
No zones appeared after enablingIt's a single-outlet plug (no child-outlet list) — see the note under Setup — or the device never connected. Confirm the IP is reachable and that it's a multi-outlet strip.
Some outlets on a strip are missingThe outlet list is enumerated only at connect time. After firmware upgrades or outlet changes, reload the device so the driver re-enumerates the outlets.
A command returns invalid address / invalid plug addressThe zone's address doesn't match a discovered outlet. Reload the device to re-bind; don't hand-edit the auto-populated child id.
Outlet cycles too fast for a sensitive load on rebootPass a larger delay (ms) on the reboot command, or raise it on the zone.
  • Devices — add the Kasa device and set its IP.
  • Zones — the per-outlet zones the driver auto-creates.
  • Subsystems — Power (default), Lights, or Garage/Gates; set momentary for a gate/garage outlet.
  • Commands — where on / off / reboot / level / get_state appear and can be tested.
  • Relay semantics — how on/off and open/closed states map across subsystems.