Skip to main content

Enphase Envoy / IQ Gateway

The Enphase Envoy driver polls a local Envoy / IQ Gateway over its LAN HTTPS API and surfaces production, consumption, and (where present) Encharge battery telemetry as device attributes. All telemetry traffic stays on the LAN; the only cloud round-trip is the one-time JWT mint at install time.

Status

Built against the public D7 firmware endpoints. Read paths (/info, /production.json, /api/v1/production, /api/v1/production/inverters, /ivp/ensemble/*) are implemented. Encharge storage-mode writes are stubbed (set_storage_mode returns not yet implemented). Older D5 session-cookie firmware is out of scope — upgrade in Enlighten.

Prerequisites

  • Envoy / IQ Gateway on D7+ firmware. Verify in the Enlighten installer view under the gateway's Software tab.
  • The gateway and the GEM controller share a LAN; TCP/443 reachable from the controller to the gateway IP.
  • An Enlighten account (homeowner is fine for production-only telemetry; installer is required for per-inverter and battery endpoints).
  • Gateway serial number — printed on the unit and visible in Enlighten under System > Devices > Gateway.

Setup

  1. Find the Envoy LAN IP. Easiest paths:
    • Enlighten app → System > Devices > Gateway.
    • The router's DHCP table (look for Envoy- or the gateway serial).
    • arp -a | grep <first 6 of MAC> from the controller.
  2. Mint a JWT bearer token.
    • Sign in at https://entrez.enphaseenergy.com.
    • Paste the gateway serial number when prompted.
    • Click Generate Token and copy the long opaque JWT.
    • Tokens are valid ~12 months for installer accounts; homeowner tokens are shorter-lived. Note the expiry — when polling starts logging auth rejected (401), mint a fresh one.
  3. Create the device under System > Devices with driver enphase_envoy. Set:
    • ip — the Envoy LAN IP (e.g., 192.168.1.50)
    • token — the JWT pasted from Entrez
  4. Verify. From the Script Console:
    await gem.command({device: <device_id>, action: 'get_status'});
    You should see a JSON response with a production array. After ~30 s the device picks up production_now_w, production_today_wh, and friends as attributes.
  5. (Optional) Per-microinverter zones. Run:
    await gem.command({device: <device_id>, action: 'get_inverters'});
    Create one zone per inverter you care about; set zone.address to the inverter serialNumber. The driver writes last_w and max_w zone attributes on each poll, and surfaces last_w as the zone state.

Attribute Reference

Required device attributes

NameTypeDescription
ipstringEnvoy LAN IP.
tokenstringJWT bearer minted from Entrez (stored encrypted).

Optional device attributes

NameTypeDefaultDescription
portint443HTTPS port. Override only on non-standard installs.
serial_numberstrGateway serial. Auto-populated from /info on first connect.
polling_intervalint30000Telemetry poll interval (ms). Hard floor 5000 ms.
request_timeoutint10000Per-request HTTPS timeout (ms).

Runtime device attributes (driver-populated)

NameTypeNotes
production_now_wintInstantaneous PV production. Prefers EIM (CT-meter) value, falls back to inverter summary.
production_today_whintToday's production.
production_lifetime_whintLifetime production.
consumption_now_wintWhole-home load (CT meter required).
consumption_today_whintToday's consumption (CT meter required).
consumption_lifetime_whintLifetime consumption (CT meter required).
net_power_wintNet power; positive = export to grid, negative = import. (CT meter required.)
inverter_countintActive microinverters reporting.
last_report_timestringISO timestamp of the last EIM/inverter reading.
battery_now_wintEncharge instantaneous power. Positive = discharging.
battery_soc_percentfloatEncharge state-of-charge %.
battery_capacity_whintEncharge stored energy.
battery_statestringEncharge controller state (e.g., idle, charging, discharging).

Per-zone attributes (optional)

NameTypeNotes
last_wintInverter's last-reported wattage.
max_wintInverter's lifetime max wattage.
statestrMirrors last_w so dashboard widgets render the value.

Zone Address Format

zone.address is the inverter serial number as reported by /api/v1/production/inverters (e.g., 122412345678). Leave blank to treat the Envoy as a single telemetry endpoint with no per-inverter breakdown.

Commands

CommandArgsNotes
get_statusReads /production.json and refreshes device attributes.
get_productionRaw /api/v1/production response.
get_invertersPer-microinverter wattage. Requires installer JWT.
get_batteryEncharge inventory + storage controller state. Installer JWT.
get_infoXML /info (firmware, model, MAC, serial).
set_storage_modemodeTODO — returns not yet implemented.

Known Limitations

  • D5 firmware is not supported. The D5 line uses installer / <password-from-serial> HTTP basic + session cookies; this driver only speaks the D7+ JWT flow.
  • set_storage_mode is stubbed. Reverse-engineered Encharge profile payloads exist in the community but we have not validated them against a live battery — leaving the call to return an error rather than guess at the wire format.
  • Stream / live-data subscriptions are not used. Telemetry is polled every polling_interval ms; the /stream/meter and /ivp/livedata/stream SSE endpoints are not subscribed. Polling at 30 s is enough for graphing and most automation; sub-second telemetry would need the stream.
  • No automatic JWT renewal. When the token expires, mint a fresh one in Enlighten and update the token attribute. (A future revision could automate this with stored Enlighten credentials, similar to ecobee.js.)

Troubleshooting

  • auth rejected (401) on every poll — JWT expired, was minted for a different gateway serial, or is a homeowner token hitting an installer-only endpoint. Mint a fresh installer JWT in Entrez.
  • auth rejected (403) — Token is valid but lacks the scope for that endpoint. /api/v1/production/inverters and /ivp/ensemble/* need installer-tier; /production.json works with homeowner.
  • Connection refused on 443, works on 80 — Almost certainly D5 firmware. Upgrade in Enlighten or use a generic HTTP poller for now.
  • Production reports 0 W during the day — Envoy lost contact with the inverters. Check /info in a browser and verify the gateway's network/cellular backhaul is up.
  • No consumption_now_w attribute appears — System has no CT (current transformer) consumption meters. This is normal on production-only installs.