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_id: <device_id>, command: '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_id: <device_id>, command: '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_numberstr—Gateway 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_status—Reads /production.json and refreshes device attributes.
get_production—Raw /api/v1/production response.
get_inverters—Per-microinverter wattage. Requires installer JWT.
get_battery—Encharge inventory + storage controller state. Installer JWT.
get_info—XML /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.