Konnected Garage Door Opener
The konnected_gdo driver controls a Konnected GDO — an ESPHome-based bridge that wires into a residential garage door opener and exposes it over the LAN. Unlike a single pulse-relay door, the Konnected GDO has discrete open, close, and stop operations plus an on-board garage light and lock. State is read over a live Server-Sent Events (SSE) stream, with a polling fallback for older firmware. The driver also holds an ESPHome native API session (TCP port 6053) open to the unit — without one, stock firmware reboots itself every 15 minutes (see Native API session).
Each Konnected GDO drives a single door. The driver auto-creates one zone per device under the garage subsystem — there is no per-zone address to set.
Prerequisites
- Konnected GDO provisioned onto Wi-Fi via its captive portal.
- A DHCP reservation for the GDO (recommended — the driver addresses it by IP).
- Outbound HTTP from the GEM controller to the GDO, including the
/eventsSSE stream. - Outbound TCP to port 6053 on the GDO (the ESPHome native API). Not strictly required — the door still works without it — but the unit reboots every 15 minutes if nothing is attached there.
- A garage subsystem on the site. A default GEM install ships one named Garages; the driver matches any subsystem whose name contains
garage, so the stock install works as-is. If every garage-type subsystem was deleted, create one under Subsystems before adding the device or no zone will be created.
Firmware and device entities
The driver speaks to the stock Konnected GDO firmware, which is ESPHome and exposes three fixed entities at known names:
| Entity | ESPHome object ID | What it is |
|---|---|---|
| Cover | garage_door | The door itself (open / close / stop / position). |
| Light | garage_light | The opener's on-board light output. |
| Lock | lock | The opener's lock / lock-out output. |
It drives these over the unit's local HTTP API and reads live changes from the /events SSE stream and the native API. ESPHome deprecated the object-ID URL form (/cover/garage_door/…) and removes it in 2026.7, so the driver learns each entity's display name from the unit (the native API entity list, or the name_id field in newer SSE frames) and calls the name form (/cover/Garage%20Door/…, /light/Garage%20Light/…, /lock/Lock/…). Firmware too old to know the name form answers 404 and the driver drops back to the object-ID form for that entity. If you reflash the unit with custom ESPHome firmware, keep those entity object IDs or GEM will not be able to see or drive the door, light, or lock. The light and lock commands only do something if those outputs are actually wired on the unit.
Setup
- Add the device. Go to System → Devices → Add Device on the Devices page and choose the driver
konnected_gdo. Enter the GDO IP Address (use a DHCP reservation), set HTTP Port and Protocol only if they differ from80/http, then enable and save. - Zone is auto-created. On first connect the driver creates a garage zone bound to this device under the garage subsystem and stamps the discrete-verb action attributes (see Discrete openers below). No per-zone address is needed.
- Verify. The driver opens the
/eventsSSE stream and the native API session, and writesstate,position, andoperationonto both the device and the zone as the door moves. If the door state never changes in GEM, the firmware may be too old for SSE — turn Use Server-Sent Events off to fall back to polling.
Native API session
Every ESPHome device with an api: block — which includes the stock Konnected firmware — has a reboot_timeout that defaults to 15 minutes: if no native-API client (normally Home Assistant) has been attached for that long, the firmware assumes its network stack is wedged and restarts. GEM talks to the unit over the web server, so from the firmware's point of view nobody is ever attached, and the unit reboots every 15 minutes. Each reboot shows in GEM as the device going offline for about 10 seconds and coming straight back, on a clean 15-minute cadence.
The driver therefore keeps one plaintext native-API session open on port 6053 (client name gem), pinging every 20 seconds and reconnecting with backoff if the link drops. That is enough for the firmware to count a client as connected, and the same session pushes every door state change, so it is a second live state source alongside SSE. The session never drives the device's connected flag — SSE and polling still own that — so a site where 6053 is unreachable behaves exactly as it did before, reboots included.
Stock Konnected firmware has no native-API encryption key. A unit running custom firmware with api: encryption: key: set cannot be joined by this driver; the session stops with encryption required in the log rather than retrying. On such firmware set api: reboot_timeout: 0s instead.
Attributes
Device
| Attribute | UI label | Required | Type | Default | Notes |
|---|---|---|---|---|---|
ip | GDO IP Address | yes | string | — | GDO LAN IP (DHCP reservation recommended). |
port | HTTP Port | no | int | 80 | HTTP port. |
protocol | Protocol | no | string | http | http or https. |
use_sse | Use Server-Sent Events | no | bool | true | Use the live SSE stream. Turn off to fall back to polling. |
poll_rate | Poll Rate (ms) | no | int (ms) | 2000 | Poll cadence — only used when Use Server-Sent Events is off. |
use_native_api | Hold ESPHome Native API Session | no | bool | true | Keep a native-API client attached so the unit does not reboot every 15 minutes. Turning it off brings the 15-minute outage back. |
api_port | Native API Port | no | int | 6053 | ESPHome native API port. |
state | Door State | readonly | string | — | Door rest state — open or closed. |
position | Door Position | readonly | int | — | Door position as ESPHome reports it, 0 (closed) → 1 (open), fractional during travel. |
operation | Current Operation | readonly | string | — | Current motion — idle / opening / closing. |
last_error | Last Error | readonly | string | — | Most recent driver error (set on a command failure, a poll failure, or an SSE error). Native-API session errors are logged, not written here. |
Zone
The driver binds one auto-created zone per device — no address is required. The state stream writes state, position, and operation onto the zone, and the discrete-verb action attributes (open_action, close_action, stop_action) are stamped on first connect. The zone takes the device's name and label.
Commands
| Name | Args | Description |
|---|---|---|
open | — | Open the door. |
close | — | Close the door. |
stop | — | Stop the door mid-travel. |
toggle | — | Open if the last known state was closed, otherwise close. |
level | level | Drive the door toward a target position 0 (closed) – 1 (open), on the same scale as position (sent verbatim to the opener's set endpoint). Whether the opener honors intermediate positions depends on the hardware — many garage openers only support fully open or fully closed. |
light_on / light_off / light_toggle | — | Control the GDO's garage light output. |
lock / unlock | — | Control the GDO's lock output. |
Discrete openers
A Konnected GDO is not a pulse relay — it has real open, close, and stop verbs. So the driver stamps the per-zone open_action, close_action, and stop_action attributes (string form: open / close / stop) when the zone is created or first seen. The garage control page reads these and dispatches the verbs directly and idempotently — no toggle guard, no pulse — and shows a Stop button because the door supports a real mid-travel stop.
This is a fill-when-empty stamp: if a user or macro has already set one of these action attributes on the zone, the driver leaves it untouched. See Command Overrides for the general per-verb override mechanism.
The garage control page can show a live camera feed beside the door buttons. That feed is sourced from a camera_zone_id attribute set on the garage subsystem, not on this device — the attribute editor offers a camera-zone picker. See Zone Controls.
Known quirks
- One door per GDO — one auto-created zone per device, no per-zone address.
- The zone lands in whichever subsystem matches
garage(the default install's Garages subsystem). - SSE keep-alive frames arrive about every 30 s. On an SSE error the driver marks the device disconnected, then reconnects about 5 s later; the stream also self-recovers if it goes idle for more than ~60 s.
positionis reported0(closed) →1(open), fractional during travel.- Without a native-API client attached the stock firmware reboots every 15 minutes (
api: reboot_timeout). The driver's native-API session is what prevents that. - ESPHome removes object-ID URLs in 2026.7. The driver uses entity-name URLs once it has learned the names and falls back to object IDs on a 404.
Troubleshooting
| Symptom | Check |
|---|---|
| No garage zone is created | Confirm a subsystem whose name contains garage exists (the default Garages). If you deleted the defaults, recreate one under Subsystems, then reload the device. |
| Door state never updates | Verify the SSE stream is reachable: curl -N http://GDO_IP:PORT/events (use the same port as the device). If it 404s the firmware is older — turn Use Server-Sent Events off to fall back to polling. |
| Light or lock command does nothing | That output may not be wired on the unit, or custom firmware renamed the entity. The driver expects the stock garage_light and lock entities. |
"Door is obstructed" / last_error populated | The GDO surfaces the opener's safety-beam state. Clear the obstruction at the door, then close again. |
| Driver flaps connected/disconnected | Wi-Fi RSSI is marginal (the GDO web UI shows RSSI). Below about −75 dBm the link is typically unstable. |
| Device drops for ~10 s exactly every 15 minutes | The unit is rebooting on ESPHome's api: reboot_timeout because no native-API client is attached. Confirm Hold ESPHome Native API Session is on and port 6053 is reachable from the controller (konnected gdo native api connected appears in the log). The unit's Uptime sensor resetting to 0 on each drop confirms the diagnosis. |