Skip to main content

Leviton Load Center (LWHEM / LDATA)

GEM driver for Leviton's smart electrical panel platform: the Whole Home Energy Monitor (LWHEM-2 / LWHEM-2R data hub) and the earlier LDATA hub, both reached through the MyLeviton (my.leviton.com) cloud REST API. It reads per-breaker electrical telemetry out of a Leviton Load Center and, on 2nd-generation smart breakers, switches circuits on and off.

Feature coverage:

  • Discovery of panels (get_panels), breakers (get_breakers) and whole-panel CT channels (get_cts)
  • Per-breaker polling → zone state, instant_power_w, rms_current_a, rms_voltage_v, consumed_energy_wh, produced_energy_wh, operational_state
  • Panel rollup on the device → total_power_w, breaker_count, rms_voltage_a / rms_voltage_b, panel_model, panel_status, and ct1_power_wct3_power_w for installed current transformers
  • Remote on / off / toggle on 2nd-gen smart breakers, plus blink_led to physically locate a breaker in the panel
  • refresh to ask the hub for an immediate cloud upload instead of waiting for the next scheduled one
note

This is not the same integration as Leviton Decora Smart. That driver controls Decora Smart Wi-Fi switches and dimmers; it shares the MyLeviton cloud and nothing else. A site with both products needs both devices configured.

Prerequisites

  • A commissioned load center. The LWHEM or LDATA hub must be installed in the Leviton Load Center, joined to Wi-Fi, and showing live data in the My Leviton mobile app. If the app shows no energy data, GEM will not either — the driver reads exactly what the hub has uploaded.
  • A MyLeviton account with 2FA disabled. The login endpoint rejects credentials on a two-factor account with an InsufficientData error and there is no inline way to answer the challenge. Use a dedicated automation account with the residence shared to it rather than embedding the homeowner's personal credentials in a controller.
  • 2nd-gen smart breakers for control. Monitoring works on any breaker the hub can see. Remote switching requires Leviton's 2nd-generation smart breakers, which report canRemoteOn: true. 1st-gen breakers and bare CT channels are read-only.
  • Outbound HTTPS. The controller needs to reach my.leviton.com on 443. There is no documented local API on the hub.

Setup steps

  1. Add the device. Devices → New Device, driver leviton_lwhem. Enter:
    • MyLeviton Account Email — the account the load center is enrolled under.
    • MyLeviton Account Password — stored encrypted.
  2. Confirm the panel is visible. From the Script Console, run the get_panels command on the device. You should get one entry per hub, each carrying an id, a model, and type (whem for LWHEM, ldata for the older hub). An empty list usually means the hub is enrolled under a different residence — run get_residences and set Residence ID.
  3. Enumerate breakers. Run get_breakers. Each row pairs a numeric id with the breaker's position in the panel, its current_rating, and can_remote_on. Print this list before you start creating zones — panel position is what lets you match an id to a physical circuit.
  4. Create a zone per circuit. For each breaker you want in the UI, create a zone in the power (or energy) subsystem with the device set to this controller and Address set to the numeric breaker id.
  5. Pin the panel if needed. On a site with more than one load center, set Panel ID so the device-level rollup attributes describe one panel rather than mixing two. Add a second GEM device for the second panel.
  6. Verify a control action. On a 2nd-gen breaker, run blink_led with state=1 and confirm the right breaker's locator LED starts flashing before you ever send off to it.
danger

off physically trips a live circuit. Confirm which breaker an address maps to with blink_led before wiring off into a macro, and never put a life-safety, sump, refrigeration, or network-infrastructure circuit on an automated trip.

Attribute reference

Device attributes

AttributeRequiredTypePurpose
emailyesstringMyLeviton account email.
passwordyesstring (encrypted)MyLeviton account password. Used only to mint session tokens.
api_basenostringAPI endpoint. Defaults to https://my.leviton.com/api.
residence_idnostringPin to one residence on a multi-home account. Blank = every residence the account can see.
panel_idnostringPin to one load center. Blank = all discovered panels; the first supplies the device rollup.
status_intervalnointPoll period in ms. Default 60000, floor 15000.
power_scalenofloatMultiplier applied to raw power before storing as watts. Default 1.
energy_scalenofloatMultiplier applied to raw energy counters before storing as watt-hours. Default 1.
request_timeoutnointHTTP timeout in ms. Default 15000.

The scale factors exist because Leviton does not publish the units on the breaker telemetry fields. The driver stores them unscaled and assumes watts and watt-hours. If the panel and the My Leviton app disagree with GEM by a constant factor, correct it here rather than editing the driver.

Attributes the driver writes

Device (panel rollup, from the pinned or first-discovered panel):

AttributeUnitMeaning
total_power_wWSum of instantaneous power across every breaker on the panel.
breaker_countNumber of breakers the hub reports.
rms_voltage_a / rms_voltage_bVLine voltage per leg.
panel_modelHub model code as reported by the cloud.
panel_statusonline, offline, or the hub's own status string.
ct1_power_wct3_power_wWActive power per installed CT pair (LWHEM only — up to three pairs).

Zone (one per breaker):

AttributeUnitMeaning
stateon or off.
instant_power_wWLive real power, both poles summed.
rms_current_aALive current, both poles summed.
rms_voltage_vVLine voltage at the breaker.
consumed_energy_whWhCumulative consumption counter.
produced_energy_whWhCumulative backfeed counter — non-zero only on circuits that push power back into the panel, such as a solar or generator feed.
operational_stateRaw vendor state string, which is where a trip shows up.

Telemetry is rounded before it is stored (1 W, 0.1 A, 0.1 V, 1 Wh) so that meter jitter does not flood attribute history with movement that isn't real, and a reading the hub does not supply — a breaker reporting no voltage, for example — is skipped rather than stored as an empty value.

Zone address format

The zone address is the numeric MyLeviton breaker id — an opaque cloud id, not the panel position:

482913

Run get_breakers to map ids to positions and labels. Ids are stable for the life of the enrollment but are reassigned if a breaker is removed and re-paired, so re-run get_breakers after any panel work.

Which breakers a user may operate

Every addressed command from a UI, the REST API, or voice — including blink_led, which skips the driver's own breaker lookup entirely — is confined to breakers that have a zone on this device. The rule is enforced centrally at the command dispatch layer, so no per-command list in this driver can miss a verb. A breaker id with no matching zone returns not authorized: address is not mapped to a zone on this device.

The driver's breaker lookup scans every panel across every residence the MyLeviton account can see, which is a much wider set than the breakers a site exposed as zones. The unmapped ones are the ones that must not be user-switchable — the alarm panel, the network rack, the controller. Leviton's canRemoteOn flag describes the breaker's hardware generation, not who GEM allows.

Administrators are unaffected, and so are macros, triggers, schedules and other drivers.

Known limitations

  • Cloud-only. Leviton publishes no local API for the LWHEM hub. A WAN outage stops telemetry and control; the controller cannot fall back to the LAN.
  • Minute-scale resolution. The hub uploads roughly once a minute. Polling faster costs API quota without gaining resolution, which is why the floor is 15 s and the default is 60 s.
  • Two-factor accounts are unusable. There is no inline TOTP path.
  • Breaker state strings are unverified. Leviton does not document the currentState vocabulary. The driver maps on/closedon and off/open/anything containing tripoff, and deliberately leaves the zone state unchanged (logging once) on a value it does not recognize rather than guessing whether a breaker is live.
  • Trips surface in operational_state, not state. Zone state stays on/off so power-subsystem controls stay predictable; use operational_state in a condition if you want to alarm on a trip.
  • No scheduling or load-shedding passthrough. Leviton's own breaker schedules and load-shed rules live in the app and are not read or written here. Build those as GEM macros instead.
  • CT usage types are surfaced but not interpreted. get_cts returns each channel's usage_type verbatim; the driver does not try to decide which CT is the mains.
  • Not yet in the metric registry. The zone attribute names deliberately match the SPAN panel driver's (instant_power_w, consumed_energy_wh, produced_energy_wh) so the Power dashboard picks them up as soon as registry rows carrying metric_role exist for the leviton_lwhem context. Until then the values are stored and trended but not aggregated into the energy-flow view.

Troubleshooting

SymptomCheck
Login fails immediately, error mentions InsufficientData or two factor2FA is enabled on the account. Disable it, or move the residence to a dedicated automation account.
get_panels returns []The hub is on a residence the driver isn't looking at. Run get_residences, then set residence_id.
Breakers list, but every telemetry field is nullThe hub has not uploaded yet (wait two poll cycles), or those circuits have no CT installed. Confirm the My Leviton app shows data for the same breaker.
on / off returns breaker does not support remote controlThe breaker reports canRemoteOn: false — it is a 1st-gen breaker. Monitoring still works.
not authorized: address is not mapped to a zone on this deviceThe breaker has no zone on this device. Create one, or run the command as an administrator. See Which breakers a user may operate.
Connect fails with a certificate errormy.leviton.com is verified against the public CA set — a failure here means something is intercepting the connection (a TLS-inspecting firewall or proxy). The account email, password and session token ride these calls, so the driver will not fall back to an unverified connection.
on / off returns 200 but nothing happensThe hub is offline or the breaker was tripped mechanically. A mechanically tripped breaker must be reset by hand at the panel; remoteOn will not re-close it.
Repeated http 401 in the logThe session token expired and re-login is failing. Confirm the password still works in the app; run refresh_token to force a fresh login.
http 429Too many calls. Raise status_interval — one panel of 20 breakers at 60 s is already several thousand calls a day.
Device shows connected but values are frozenThe cloud is serving a stale cache. Run refresh, which sends the hub a bandwidth nudge and re-polls.
Unrecognized breaker state warnings in the logReport the exact string. It means Leviton uses a currentState value the mapping doesn't cover; the driver is holding the last known state rather than guessing.