pyfenixcontrol
Asynchronous Python client for the FENIX Control cloud, used by FENIX TFT WiFi thermostats. It powers the FENIX integration for Home Assistant, but has no Home Assistant dependency and can be used from any asyncio code.
- Fully typed (
py.typed),asyncio+aiohttp, Python 3.12+ - Read thermostats, rooms and installations; set target temperature and operating mode
- Installation-wide holiday schedules
- Room energy consumption at hourly … yearly aggregation
- Pluggable authentication: bundled e-mail/password login, or bring your own OAuth2 tokens
- Automatic token refresh, single retry on HTTP 401, backoff on HTTP 5xx
Installation
pip install pyfenixcontrol
Quick start
import asyncio
import aiohttp
from pyfenixcontrol import FenixControlClient, PasswordAuth, PresetMode
async def main() -> None:
async with aiohttp.ClientSession() as session:
auth = PasswordAuth(session, "you@example.com", "password")
client = FenixControlClient(auth)
for device in await client.get_devices():
print(device.name, device.room_temperature, device.target_temperature)
await client.set_target_temperature(device.id, 21.5)
await client.set_preset_mode(device.id, PresetMode.PROGRAM)
asyncio.run(main())
Authentication
The client never sees credentials. It asks an AbstractAuth for a bearer token:
from pyfenixcontrol import AbstractAuth
class MyAuth(AbstractAuth):
async def async_get_access_token(self) -> str:
return await my_token_store.get_valid_token()
async def async_invalidate_access_token(self) -> None:
# Called after an HTTP 401; optional.
await my_token_store.mark_expired()
PasswordAuth performs the OAuth2 authorization-code + PKCE login used by the
FENIX Control app and keeps tokens in memory. await auth.async_login() validates
credentials up front (e.g. in a setup wizard).
PasswordAuth needs an aiohttp session with a working cookie jar, because the
identity server tracks its login form with cookies. Cookies of the identity host
are cleared before each full login.
API overview
| Method | Description |
|---|---|
get_user_id() |
Account subject id (cached on the client) |
get_installations() |
Installations (homes) with their rooms and device ids |
get_devices(installations=None) |
Device state of every thermostat |
get_device_properties(device_id) |
Raw device twin properties |
trigger_installation_update(installation_id) |
Ask thermostats to report fresh values |
set_target_temperature(device_id, celsius) |
Set target °C (switches to manual) |
set_preset_mode(device_id, mode) |
PresetMode.OFF / PROGRAM / MANUAL / DEFROST / BOOST / HOLIDAYS |
set_holiday_schedule(installation_id, start, end, mode) |
Holiday for the whole installation |
cancel_holiday_schedule(installation_id) |
Remove the holiday schedule |
get_room_energy(installation_id, room_id, start, end, period) |
EnergyMetric buckets in Wh |
Errors
| Exception | Meaning |
|---|---|
FenixControlAuthError |
Credentials or tokens rejected – user action needed |
FenixControlConnectionError |
Network error or timeout – retry later |
FenixControlResponseError |
Unexpected status or body (.status holds the HTTP code) |
All inherit from FenixControlError.
Units and conventions
- Temperatures are °C. The API transports °F ×
divFactor;decode_temperature()/encode_temperature()convert. - Holiday
start/endare wall-clock times of the installation (no time zone conversion). Energy queries convert to UTC; naive datetimes are taken as UTC. - Every model keeps the original payload in
.rawfor fields not yet modelled.
Development
uv sync
uv run pytest --cov
uv run ruff check . && uv run ruff format --check . && uv run mypy
Tests run against a local fake of the cloud and identity server; no account is needed.
Releases: bump __version__, update CHANGELOG.md, publish a GitHub release
tagged vX.Y.Z. The release workflow publishes to PyPI via trusted publishing.
License
MIT – see LICENSE. Not an official product of FENIX Trading s.r.o. unless stated otherwise in the project metadata.
Metadata
Release files for pyfenixcontrol 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pyfenixcontrol-0.1.0.tar.gz | 22.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyfenixcontrol-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 39.7 kB
Release files / pyfenixcontrol-0.1.0.tar.gz
| Download URL | pyfenixcontrol-0.1.0.tar.gz |
|---|---|
| Size | 22.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
23814ad2e4367d6d7dee63a15337d3b96e637d4f78161b3382f25b67711bd58a
|
|
BLAKE2b-256 checksum How to use checksums |
28a6e0bbd720a74e7100da66dce0de9eb0611dcd7c9a7bfa2c4604765e0fc895
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 15, 2026.
Transparency logRelease files / pyfenixcontrol-0.1.0-py3-none-any.whl
| Download URL | pyfenixcontrol-0.1.0-py3-none-any.whl |
|---|---|
| Size | 17.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4c98d5c7573632de65b05968ba8e4b042c3bcbde4276441781e9de1edf3ca4a3
|
|
BLAKE2b-256 checksum How to use checksums |
e41882e7aeb1d84e8334b3f59097c27f612c75aa5ee1499feb59840b7202bab3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 15, 2026.
Transparency log