Skip to main content

Local Ecobee Control (HomeKit)

Control your Ecobee thermostat from Python over your local network, with no cloud, no OAuth, no ecobee developer key, and no Home Assistant. It talks to the thermostat directly using Apple's HomeKit Accessory Protocol (HAP) via aiohomekit.

Pair once, then read and control the thermostat from a small control-panel GUI, a command line, or as a Python library you drop into your own project.

Works with any HomeKit-capable Ecobee. Developed and tested against an Ecobee3 lite and an Ecobee Smart Premium (including its remote SmartSensor).

What it can do

  • Read current temperature, target, mode, running state, humidity, and fan state
  • Set target temperature, mode (heat / cool / auto / off), heat/cool thresholds, and fan (auto / on)
  • Read remote SmartSensors and the built-in occupancy sensor (temperature, occupancy, battery)
  • Set target humidity on models that have a humidifier/dehumidifier (e.g. Smart Premium)
  • Read and switch comfort profiles (Home / Sleep / Away) locally on supported models (off by default; see notes, the ecobee3 lite does not support this correctly)
  • Fahrenheit or Celsius display, with exact half-degree Celsius setting
  • A live GUI that auto-updates, or a scriptable CLI, or an importable library

Requirements

  • Python 3.9+
  • pip install -r requirements.txt (installs aiohomekit and zeroconf)
  • Tkinter for the GUI. It ships with Python on Windows and macOS. On some Linux distros it's a separate package: sudo apt install python3-tk.

Setup

1. Free the thermostat for pairing

HomeKit accessories can only be paired to one "home" at a time. If your Ecobee is already added to Apple Home, it won't be discoverable for pairing until you reset its HomeKit info. On the thermostat: Menu → Settings → HomeKit → Reset HomeKit. (This removes it from Apple Home. If you don't use Apple Home, there's nothing to do.)

2. Pair

python pair_ecobee.py

The wizard will:

  • scan your network and show a numbered list of HomeKit devices (or filter by name),
  • let you pick the thermostat, give it a short label and a friendly name,
  • ask for the 8-digit HomeKit setup code shown on the thermostat screen (type it any way — 12345678, 1234 5678, or 123-45-678 all work),
  • save the credentials to a file.

Run it again for each additional thermostat. Files are saved to a per-user folder (%LOCALAPPDATA%\ecobee-local on Windows, ~/ecobee-local on macOS/Linux) by default; use --folder PATH to change it.

Keep your pairing files private. Each one contains long-term keys that grant full control of that thermostat on your network. Don't commit or share them. The included .gitignore already excludes them.

3. Run

python ecobee_controller.py

With no arguments this opens the control window (one card per thermostat). On a headless machine with no display it automatically falls back to a background service instead.

Command line

Everything the GUI does is also scriptable. All --set-* actions require --label.

python ecobee_controller.py                         # open the GUI
python ecobee_controller.py --dump                  # list every characteristic each thermostat exposes
python ecobee_controller.py --dump --raw            # same, without truncating long values
python ecobee_controller.py --label main --set-temp 72
python ecobee_controller.py --label main --set-mode 2       # 0=off 1=heat 2=cool 3=auto
python ecobee_controller.py --label main --set-heat 68 --set-cool 75   # auto-mode range
python ecobee_controller.py --label main --set-fan on
python ecobee_controller.py --label main --set-comfort away      # home/sleep/away/hold (Premium/Smart)
python ecobee_controller.py --headless              # run as a background service (no GUI)
python ecobee_controller.py --debug                 # print connection/subscription events
python ecobee_controller.py --folder PATH           # use a different credentials folder

--dump is the tool for discovering what your specific model exposes: it prints every accessory, service, and characteristic with its UUID, current value, permissions, and range.

Use it as a library

from ecobee_controller import EcobeeController

ec = EcobeeController.from_folder()   # auto-discovers every pairing file
ec.start()

print(ec.get_status("main"))
# {'current_temp': 78, 'target_temp': 75, 'mode': 2, 'humidity': 57,
#  'setpoint_kind': 'single', 'display_target': 75, 'sensors': [...], ...}

ec.set_temp("main", 72)                       # Fahrenheit
ec.set_temp_c("main", 22.5)                   # Celsius, exact half-degree
ec.set_mode("main", EcobeeController.MODE_COOL)
ec.set_heat_threshold("main", 68)             # auto mode
ec.set_cool_threshold("main", 75)
ec.set_fan("main", auto=True)

# comfort profiles (see notes; works on some models, not the ecobee3 lite)
print(ec.get_comfort_mode("main"))            # "home" / "sleep" / "away" / "hold"
ec.set_comfort_mode("main", "away")           # switch to Away locally
# the first comfort call prints a one-time firmware-caveat note to stderr;
# construct with EcobeeController(..., comfort_warning=False) to silence it

ec.stop()                                     # cleanly close connections

get_status() returns a dict per thermostat. A few fields are computed for convenience:

  • setpoint_kind is "single" in heat/cool/off and "range" in auto.
  • display_target is the value(s) a UI should show: one number in single-setpoint modes, {"heat": ..., "cool": ...} in auto.
  • In auto mode target_temp is None, because a single target is meaningless there — the thermostat runs off the heat/cool thresholds. Read heat_threshold / cool_threshold (or display_target) instead.
  • Temperatures are in Fahrenheit; the raw Celsius the device reports is also included as *_c (e.g. target_temp_c).
  • Fields a given model doesn't support read as "--" rather than a misleading 0.

How it works

pair_ecobee.py performs the one-time HomeKit handshake and saves credentials. ecobee_controller.py uses those credentials to keep a persistent local connection per thermostat, subscribes for push updates (the device notifies it on change), and caches readings so the GUI/CLI never block on the network. Characteristics are located by their standard HomeKit type inside the thermostat's Thermostat service, so the same code works across different Ecobee models without hardcoding.

Notes and limitations

  • This is local HomeKit control. It reads and controls whatever the thermostat exposes over HomeKit.
  • Air quality is not available. The Smart Premium has an air-quality sensor, but Ecobee does not publish air quality (VOC / CO₂) over HomeKit — only through their cloud. So no local tool, including this one, Apple Home, or Home Assistant, can read it over HomeKit.
  • The Ecobee app and HomeKit can briefly disagree. Ecobee drives its own screen and app from its cloud/comfort-profile system. If you change settings in the ecobee app, the standard HomeKit state this tool reads may show a different or stale value (for example, showing "Auto" with an odd range) until the setting is next changed through HomeKit. Changes made with this tool are always consistent. This is an Ecobee behavior, not a bug in this project.
  • Scheduling isn't a HomeKit feature. HomeKit has no concept of a weekly schedule; Ecobee's comfort schedules live in its own system. You can build time-based automation on top of this library, but it can't read/write Ecobee's schedules over HomeKit.
  • Comfort profiles work on some models, not others. On Premium/Smart models you can read and switch Home, Sleep, and Away locally. This does NOT work on all thermostats, notably the ecobee3 lite, which has a known ecobee firmware bug that always reports the same comfort value no matter the actual setting (so the reading is wrong and a change can't be reflected). For this reason the GUI keeps comfort controls off by default and lets you enable them per-thermostat in Settings, turn them on only for models where they behave. Custom comfort profiles (e.g. a "Gym" profile) aren't individually addressable over HomeKit either; they all report as "hold", and you can't create profiles from here (that's an ecobee-app/cloud action). The comfort UUIDs are vendor-specific and undocumented by ecobee; verified on hardware and corroborated by the Home Assistant project. The library API (get_comfort_mode / set_comfort_mode) is always available regardless of the GUI toggle, use it only if you've confirmed your model reports comfort correctly.

Files

  • pair_ecobee.py — one-time pairing wizard
  • ecobee_controller.py — the library, CLI, and GUI (all in one)
  • requirements.txt — dependencies
  • .gitignore — keeps pairing credentials out of version control

Acknowledgements

Built on aiohomekit, the same HomeKit client that powers Home Assistant's HomeKit Controller integration.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ecobee_local-1.1.0.tar.gz (35.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ecobee_local-1.1.0-py3-none-any.whl (32.9 kB view details)

Uploaded Python 3

File details

Details for the file ecobee_local-1.1.0.tar.gz.

File metadata

  • Download URL: ecobee_local-1.1.0.tar.gz
  • Upload date:
  • Size: 35.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.0

File hashes

Hashes for ecobee_local-1.1.0.tar.gz
Algorithm Hash digest
SHA256 44a2ca4cf1d1a016e97e5ad4d934454d65542397ed59382a254b2f3fb109ca5b
MD5 4505445f25b147359e50d6054ce2b138
BLAKE2b-256 4bf03a4fa20f7201d3c88a5de24428021ef92386eb876e85a514af69027f9cf2

See more details on using hashes here.

File details

Details for the file ecobee_local-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: ecobee_local-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 32.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.0

File hashes

Hashes for ecobee_local-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 eb54703e40b761c3b2a8c2dec3f4b00f8de37e6abd0c12a734f52a7d69382342
MD5 936926d7de99ea9b7d109840a716e513
BLAKE2b-256 7dd679e06ef8e3487de388d11e65dfe507241063029345023b87aefa2eab4ce9

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 files

1.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page