Skip to main content

Ecobee Thermostat (Cloud)

GEM controls Ecobee smart thermostats through Ecobee's cloud REST API at api.ecobee.com. One GEM device represents one Ecobee homeowner account; every thermostat registered to that account becomes a Climate zone underneath it. The link is established once, through Ecobee's PIN authorization, after which GEM keeps itself signed in automatically — there is nothing to re-enter on a server restart unless the pairing is revoked.

This is a cloud integration: there is no LAN/local path. The GEM server needs outbound internet access to reach Ecobee.

What's controlled

  • Per-thermostat heat and cool setpoints, with an automatic gap (deadband) kept between them.
  • System modeauto / cool / heat / off.
  • Fan modeauto / on.
  • Live feedback published back onto each zone: current temperature, relative humidity, the active heat/cool setpoints, the running system and fan mode, and the thermostat's online/offline state.

Prerequisites

  • An Ecobee homeowner account with at least one thermostat already commissioned in the Ecobee app (if it shows up in the app, GEM can reach it).
  • A developer API key. Register a developer application at https://www.ecobee.com/developers and set its Authorization Method to ecobee PIN. The application's API key is what you paste into GEM.
  • Access to the homeowner account during setup, to type the pairing PIN into Ecobee's web portal.
  • Outbound HTTPS (port 443) from the GEM server to api.ecobee.com.

Setup

1. Add the device

  1. Open Devices and add a new device of type Ecobee Thermostat.
  2. In the API Key field, paste the developer API key from your Ecobee developer application. This is stored encrypted.
  3. Save the device.

2. Pair with the homeowner account (one time)

The first link uses Ecobee's PIN flow. You start it from GEM, then approve it in Ecobee's web portal.

  1. Run the authorize command against the device — from the device's command list, the Commands screen, or the Script Console.
  2. GEM generates a pairing PIN and shows it to you. The same value also lands in the device's read-only Authorization PIN attribute and is emailed to the site's mail recipient.
  3. Within about three minutes, sign in to the Ecobee web portal, open My Apps → Add Application, enter the PIN, and confirm/add the application.
  4. GEM polls Ecobee every few seconds in the background. As soon as you approve the PIN, it fills in the read-only Access Token and Refresh Token attributes and begins syncing. The PIN is single-use — if you miss the three-minute window, run authorize again for a fresh one.
tip

After the first successful pairing, GEM only needs the Refresh Token to reconnect. You do not run authorize again on reboots or reloads. Re-authorize only if you removed GEM's application from the Ecobee account, or re-paired the same account elsewhere (which revokes the old refresh token).

3. Create one zone per thermostat

Zones are not created automatically — you add one Climate zone for each thermostat.

  1. Run get_thermostats against the device to list everything on the account. The response is keyed by both the thermostat's identifier and its name.
  2. Open Zones and create a zone under the Climate subsystem for each thermostat.
  3. Set the zone Address to that thermostat's identifier or its name exactly as it appears in the get_thermostats output. Either works; the name must match character-for-character.

Once a zone's address matches, GEM starts populating its temperature, humidity, setpoints, mode and fan attributes on the next poll (within ~3 minutes), and the standard climate controls light up in the UI.

Attribute reference

Device attributes

AttributeRequiredTypeDefaultNotes
api_keyyesstring (secure)Developer API key from the Ecobee developer portal.
pinautostring (read-only)Pairing PIN produced by authorize; you type this into Ecobee's web portal.
tokenautostring (secure, read-only)OAuth access token. Filled in and rotated automatically.
refresh_tokenautostring (secure, read-only)OAuth refresh token. This is what lets GEM reconnect without re-pairing — do not clear it.
hold_typenostringindefiniteHow long a setpoint hold lasts. One of indefinite, nextTransition, dateTime, holdHours.

Zone attributes

AttributeRequiredTypeNotes
addressyesstringThermostat identifier or name on the Ecobee account. Run get_thermostats to list valid values.
deadbandnoint (°F)Minimum gap GEM enforces between the heat and cool setpoints. If unset, the Climate subsystem's deadband default is used.

The driver keeps the following feedback attributes in sync on each zone automatically — you do not set them by hand: temperature, humidity, heat_setpoint, cool_setpoint, system_mode, fan_mode, and the connected (online) flag. It also publishes system_modes (auto/cool/heat/off) and fan_modes (auto/on) so the admin UI renders the correct pickers.

All temperatures and setpoints are whole degrees Fahrenheit — Ecobee's API is Fahrenheit-based and the driver does not convert to Celsius.

Commands

These target a Climate zone; GEM supplies the thermostat address from the zone, so in a macro you only provide the values below.

CommandArgsNotes
authorizeStarts the one-time PIN pairing and returns the PIN to enter at Ecobee's web portal.
setpointmode (heat/cool), setpointApplies a hold at the target temperature (whole °F). GEM writes both heat and cool setpoints, keeping them at least the deadband apart, and the hold lasts according to hold_type.
system_modemode (auto/cool/heat/off)Sets the thermostat's HVAC mode.
fan_modemode (auto/on)Sets the fan mode. Speeds beyond auto/on are not supported on all models.
get_thermostatsLists every thermostat on the account; use it to find a zone's Address.
get_system_modeListed for completeness but not currently wired — the live mode is already published to the zone's system_mode attribute, so read it there instead.

How control works

Setpoints and the deadband. When you set a heat (or cool) setpoint, GEM also derives the opposite setpoint so the two stay at least the deadband apart — e.g. with a 3° deadband, setting cool to 72 nudges heat to 69. The pair is applied as a single Ecobee hold. The deadband comes from the zone's deadband attribute, falling back to the Climate subsystem default.

Hold duration. Every setpoint change is sent as a hold whose length is the device's hold_type:

  • indefinite (default) — holds until you clear it on the thermostat or send a new value.
  • nextTransition — holds until the thermostat's next scheduled program change, then resumes the schedule.
  • dateTime / holdHours — Ecobee's timed-hold modes.

If a setpoint "takes" and then reverts a while later, the thermostat's schedule resumed — switch hold_type to indefinite to make manual changes stick.

Polling and tokens. GEM refreshes thermostat state about every 3 minutes, so feedback (temperature, humidity, mode, setpoints) reflects the thermostat within that window. The access token is renewed roughly every 50 minutes using the stored refresh token; this is automatic and invisible to the integrator.

Known limitations

  • Cloud only. No local/LAN control — the integration depends on internet reachability to api.ecobee.com.
  • Holds, not schedules. GEM applies temporary holds; it does not edit the thermostat's comfort schedules, comfort profiles (Home/Away/Sleep), or vacation events.
  • Fan is auto/on. Multi-speed fan control is not exposed and is not supported on all models.
  • No remote-sensor or equipment-runtime detail. Per-room occupancy sensors and stage/equipment runtime data are not surfaced as attributes.
  • Fahrenheit only. Setpoints and readings are whole °F; there is no Celsius mode.
  • get_system_mode is a no-op — use the polled system_mode zone attribute instead.

Troubleshooting

SymptomCheck
authorize returns no PINThe API Key must belong to a developer application whose authorization method is ecobee PIN. Re-check the key and the app's setting in the Ecobee developer portal.
PIN entered but nothing linksThe PIN expires about three minutes after authorize. Run authorize again and enter the fresh PIN promptly.
unmatched ecobee thermostat address in the device logA zone's Address doesn't equal any thermostat identifier or name on the account. Run get_thermostats and copy an exact value.
Zone shows disconnectedThe thermostat is offline to Ecobee's cloud (no Wi-Fi or power). GEM mirrors the thermostat's online state; restore the thermostat's connection.
Setpoint accepted but reverts laterA thermostat schedule resumed. Set hold_type to indefinite, or place the hold on the thermostat itself.
Feedback stopped updating after about an hourToken refresh failed — usually because the refresh token was revoked (the account was re-paired elsewhere, or GEM's app was removed). Reload the device; if it still can't refresh, re-run authorize.

See also

  • Zones — create one Climate zone per thermostat; the zone Address is the thermostat identifier or name.
  • Subsystems — set the Climate subsystem's deadband default used when a zone has none.
  • Devices — where the Ecobee account device is added and authorize is run.
  • Commands — where setpoint, system_mode, and fan_mode are dispatched and wired into macros.