Python library for Airobot thermostat TE1 local REST API
Project description
pyairobotrest
Python library for controlling Airobot TE1 thermostats via local REST API.
This library is used by the Airobot Home Assistant integration.
Features
- 🔌 Async/await support using asyncio with comprehensive error handling
- 🌡️ Temperature control for HOME and AWAY modes (5-35°C range)
- 🏠 Mode management (HOME/AWAY mode switching)
- ⚙️ Hysteresis control (0.0-0.5°C range)
- 💨 Boost mode for temporary heating (1 hour duration)
- 🔒 Child lock control for safety
- 💡 Sensor monitoring (temperature, humidity, CO2, AQI)
- 🛡️ Type hints for better IDE support and development experience
- ✅ Input validation with range checking for all settings
- 📊 Comprehensive data model with optional sensor support
Installation
pip install pyairobotrest
Prerequisites
Before using this library, ensure your Airobot thermostat is properly configured:
- Network Connection: Connect the thermostat to your local WiFi/Ethernet network
- Initial Registration: Connect to the internet at least once to register with the server and obtain credentials (Device ID and password)
- Enable Local API: In thermostat settings, navigate to "Connectivity → Local API → Enable"
- Get Credentials: Find your Device ID (username) and password in the thermostat menu under "Mobile app" screen
Note: After initial setup, internet connectivity is not required for local API access.
Quick Start
import asyncio
from pyairobotrest import AirobotClient, AirobotConnectionError
async def main():
# Create client - replace with your thermostat's IP and credentials
client = AirobotClient(
host="192.168.1.100", # or "airobot-thermostat-t01xxxxxx.local"
username="T01XXXXXX", # Your thermostat Device ID
password="your_password" # Password from "Mobile app" screen
)
try:
# Read current status
status = await client.get_statuses()
print(f"Device: {status.device_id}")
print(f"Hardware: v{status.hw_version_string}")
print(f"Firmware: v{status.fw_version_string}")
print(f"Current temperature: {status.temp_air:.1f}°C")
print(f"Target temperature: {status.setpoint_temp:.1f}°C")
print(f"Humidity: {status.hum_air:.1f}%")
print(f"Heating: {'ON' if status.is_heating else 'OFF'}")
# Check optional sensors
if status.has_floor_sensor:
print(f"Floor temperature: {status.temp_floor:.1f}°C")
if status.has_co2_sensor:
print(f"CO2: {status.co2} ppm (AQI: {status.aqi})")
# Read current settings
settings = await client.get_settings()
print(f"Mode: {'HOME' if settings.mode == 1 else 'AWAY'}")
print(f"HOME temp: {settings.setpoint_temp}°C")
print(f"AWAY temp: {settings.setpoint_temp_away}°C")
# Control the thermostat
await client.set_home_temperature(23.0) # Set HOME temperature
await client.set_mode(1) # Switch to HOME mode
await client.set_boost_mode(True) # Enable boost for 1 hour
except AirobotConnectionError as err:
print(f"Connection error: {err}")
finally:
await client.close()
asyncio.run(main())
Context Manager Usage (Recommended)
import asyncio
from pyairobotrest import AirobotClient
async def main():
try:
# Using async context manager automatically handles connection cleanup
async with AirobotClient(
host="192.168.1.100",
username="T01XXXXXX",
password="your_password"
) as client:
# Read status
status = await client.get_statuses()
print(f"Temperature: {status.temp_air:.1f}°C")
print(f"Heating: {status.is_heating}")
# Configure thermostat
await client.set_home_temperature(22.5)
await client.set_hysteresis_band(0.3)
await client.set_child_lock(True)
except Exception as err:
print(f"Error: {err}")
asyncio.run(main())
Factory Method (Recommended for Home Assistant)
For explicit session initialization, use the factory method pattern:
import asyncio
from pyairobotrest import AirobotClient
async def main():
# Factory method ensures session is initialized before use
client = await AirobotClient.create(
host="192.168.1.100",
username="T01XXXXXX",
password="your_password"
)
try:
status = await client.get_statuses()
print(f"Temperature: {status.temp_air:.1f}°C")
finally:
await client.close()
asyncio.run(main())
API Reference
Client Initialization
| Method | Description | Returns |
|---|---|---|
AirobotClient() |
Standard constructor | AirobotClient |
AirobotClient.create() |
Factory method with session pre-initialized | AirobotClient |
Main Client Methods
| Method | Description | Parameters |
|---|---|---|
get_statuses() |
Read all current measurements | None |
get_settings() |
Read all thermostat settings | None |
set_mode(mode) |
Set HOME/AWAY mode | mode: int (1=HOME, 2=AWAY) |
set_home_temperature(temp) |
Set HOME temperature | temp: float (5.0-35.0°C) |
set_away_temperature(temp) |
Set AWAY temperature | temp: float (5.0-35.0°C) |
set_hysteresis_band(hyst) |
Set temperature hysteresis | hyst: float (0.0-0.5°C) |
set_device_name(name) |
Set device name | name: str (1-20 chars) |
set_child_lock(enabled) |
Enable/disable child lock | enabled: bool |
set_boost_mode(enabled) |
Enable/disable boost mode | enabled: bool |
reboot_thermostat() |
Reboot the thermostat | None |
recalibrate_co2_sensor() |
Recalibrate CO2 sensor | None |
toggle_actuator_exercise(disabled) |
Enable/disable actuator test | disabled: bool |
Data Model (ThermostatStatus)
@dataclass
class ThermostatStatus:
# Device identification
device_id: str # Unique device ID
hw_version: int # Hardware version (raw)
fw_version: int # Firmware version (raw)
# Temperature measurements
temp_air: float # Air temperature in °C
temp_floor: float | None # Floor temperature in °C (None if not attached)
setpoint_temp: float # Target temperature in °C
# Environmental sensors
hum_air: float # Relative humidity in %
co2: int | None # CO2 in ppm (None if not equipped)
aqi: int | None # Air quality index 0-5 (None if no CO2)
# Status
is_heating: bool # True if actively heating
has_error: bool # True if error present
error_code: int # Error code (0 = no error)
uptime: int # Device uptime in seconds
# Sensor availability
has_floor_sensor: bool # True if floor sensor attached
has_co2_sensor: bool # True if CO2 sensor equipped
# Version properties (human-readable)
hw_version_string: str # Hardware version (e.g., "1.11")
fw_version_string: str # Firmware version (e.g., "1.11")
Data Model (ThermostatSettings)
@dataclass
class ThermostatSettings:
device_id: str # Unique device ID
mode: int # 1=HOME, 2=AWAY
setpoint_temp: float # HOME temperature in °C
setpoint_temp_away: float # AWAY temperature in °C
hysteresis_band: float # Temperature hysteresis in °C
device_name: str # Device name (1-20 characters)
# Setting flags
setting_flags: SettingFlags
childlock_enabled: bool # Child lock status
boost_enabled: bool # Boost mode status (1 hour)
reboot: bool # Reboot flag
recalibrate_co2: bool # CO2 calibration flag
actuator_exercise_disabled: bool # Actuator exercise status
Exception Handling
from pyairobotrest import (
AirobotConnectionError, # Connection issues
AirobotAuthError, # Authentication failures
AirobotTimeoutError, # Timeout errors
AirobotError, # General API errors
)
try:
async with AirobotClient("192.168.1.100", "T01XXXXXX", "password") as client:
status = await client.get_statuses()
except AirobotAuthError:
print("Authentication failed - check username/password")
except AirobotConnectionError:
print("Failed to connect to thermostat")
except AirobotTimeoutError:
print("Operation timed out")
except AirobotError as err:
print(f"API error: {err}")
Development
Setup
# Clone the repository
git clone https://github.com/mettolen/pyairobotrest.git
cd pyairobotrest
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install in development mode with dev dependencies
pip install -e ".[dev]"
Testing & Quality
# Run all tests with coverage
pytest --cov=pyairobotrest --cov-report=term-missing
# Run type checking
mypy src/pyairobotrest
# Run linting and formatting
ruff check src/pyairobotrest
ruff format src/pyairobotrest
# Run pre-commit hooks (if installed)
pre-commit run --all-files
Requirements
- Python 3.11+
- Dependencies:
aiohttp>= 3.9.0 (HTTP client for REST API communication)asyncio(built-in, async/await support)
Compatibility
This library is tested and compatible with:
- Airobot TE1 thermostats with local REST API enabled
- Tested with hardware v1.1 (257) and firmware v1.11 (267)
- Home Assistant integration
- Python 3.11, 3.12, 3.13+
Advanced Usage
Firmware and Hardware Version Decoding
The thermostat reports firmware and hardware versions as encoded integers. The library automatically decodes these to human-readable strings:
status = await client.get_statuses()
# Raw version numbers (as stored in device)
print(f"Raw HW version: {status.hw_version}") # e.g., 267
print(f"Raw FW version: {status.fw_version}") # e.g., 257
# Human-readable version strings (automatically decoded)
print(f"HW version: v{status.hw_version_string}") # e.g., v1.11
print(f"FW version: v{status.fw_version_string}") # e.g., v1.1
# Version encoding: value = major * 256 + minor
# Example: 267 = 1 * 256 + 11 = v1.11
# 257 = 1 * 256 + 1 = v1.1
Input Validation
All setter methods validate input values before sending to the API:
# These will raise AirobotError before making API calls
await client.set_home_temperature(40.0) # Error: outside 5-35°C range
await client.set_hysteresis_band(1.0) # Error: outside 0-0.5°C range
await client.set_device_name("x" * 25) # Error: name too long (max 20 chars)
await client.set_mode(3) # Error: invalid mode (must be 1 or 2)
Strict Validation Mode
For testing or strict data validation scenarios, enable strict mode to raise exceptions for out-of-range sensor values:
from pyairobotrest.models import ThermostatStatus
# Normal mode (default): logs warnings for out-of-range values
status = ThermostatStatus.from_dict(api_response_data)
# Strict mode: raises ValueError for out-of-range values
try:
status = ThermostatStatus.from_dict(api_response_data, strict=True)
except ValueError as e:
print(f"Invalid sensor data: {e}")
Use cases for strict mode:
- Unit testing with known good data
- Development and debugging
- Data quality validation pipelines
Default mode (strict=False) is recommended for production as it handles edge cases gracefully by logging warnings.
Polling Best Practices
The thermostat measures air every 30 seconds, which is the minimum recommended polling interval:
import asyncio
async def monitor_temperature():
async with AirobotClient("192.168.1.100", "T01XXXXXX", "password") as client:
while True:
status = await client.get_statuses()
print(f"Temperature: {status.temp_air:.1f}°C")
await asyncio.sleep(30) # Poll every 30 seconds
Troubleshooting
Connection Issues
- Check IP address: Ensure the thermostat IP is correct
- Local API enabled: Verify "Connectivity - Local API – Enable" is turned on
- Network connectivity: Ensure the thermostat is on the same network
- Credentials: Check username (Device ID) and password from "Mobile app" screen
Common Error Patterns
# Handle specific error types
try:
await client.get_statuses()
except AirobotAuthError:
print("Authentication failed - check credentials")
except AirobotTimeoutError:
print("Request timed out - thermostat may be offline")
except AirobotConnectionError as err:
if "refused" in str(err).lower():
print("Connection refused - check IP and ensure local API is enabled")
else:
print(f"Connection error: {err}")
License
MIT License - see LICENSE file for details.
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for detailed guidelines on:
- Setting up your development environment
- Code style and testing requirements
- Submitting pull requests
- Reporting bugs and requesting features
For major changes, please open an issue first to discuss what you would like to change.
Credits
This library is designed to work with Airobot TE1 thermostats and is used by the Home Assistant Airobot integration.
Key Features Developed:
- Complete REST API implementation for Airobot thermostats
- Comprehensive error handling and input validation
- Type-safe API with full asyncio support
- Individual setter methods for granular control
- Production-ready reliability and performance
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyairobotrest-0.3.0.tar.gz.
File metadata
- Download URL: pyairobotrest-0.3.0.tar.gz
- Upload date:
- Size: 30.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f26903543c54ea8a26514ff1af3f1cee6ff2c5972692c948c84ab4621182550
|
|
| MD5 |
105460580ff65da65ade5358fd35998a
|
|
| BLAKE2b-256 |
7b8e5d064509a4a8d3a8467255bb6bb975bbf5343ec63d3ccdd9e782d566dca3
|
Provenance
The following attestation bundles were made for pyairobotrest-0.3.0.tar.gz:
Publisher:
publish.yml on mettolen/pyairobotrest
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyairobotrest-0.3.0.tar.gz -
Subject digest:
2f26903543c54ea8a26514ff1af3f1cee6ff2c5972692c948c84ab4621182550 - Sigstore transparency entry: 849073392
- Sigstore integration time:
-
Permalink:
mettolen/pyairobotrest@9b67ba9510effc705204e9044c8d840d8991dd62 -
Branch / Tag:
refs/tags/0.3.0 - Owner: https://github.com/mettolen
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9b67ba9510effc705204e9044c8d840d8991dd62 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyairobotrest-0.3.0-py3-none-any.whl.
File metadata
- Download URL: pyairobotrest-0.3.0-py3-none-any.whl
- Upload date:
- Size: 17.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
00cb9709a6c225fd97e42d39157a35dd97c7d99b4f5732a67d759a32ec96c17b
|
|
| MD5 |
20868b3410616ad47960ea729bed26a4
|
|
| BLAKE2b-256 |
74fc3b10c04b0a845c9929a7bca6fc2f4aa72f80b1c00e603ee48e4c7366a35a
|
Provenance
The following attestation bundles were made for pyairobotrest-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on mettolen/pyairobotrest
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyairobotrest-0.3.0-py3-none-any.whl -
Subject digest:
00cb9709a6c225fd97e42d39157a35dd97c7d99b4f5732a67d759a32ec96c17b - Sigstore transparency entry: 849073400
- Sigstore integration time:
-
Permalink:
mettolen/pyairobotrest@9b67ba9510effc705204e9044c8d840d8991dd62 -
Branch / Tag:
refs/tags/0.3.0 - Owner: https://github.com/mettolen
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9b67ba9510effc705204e9044c8d840d8991dd62 -
Trigger Event:
release
-
Statement type: