Package: aiocomfoconnect
aiocomfoconnectaiocomfoconnectis an asyncio Python 3 library for communicating with a Zehnder ComfoAir Q350/450/600 ventilation system. It's the successor ofcomfoconnect.It's compatible with Python 3.10 and higher.Installationpip3installaiocomfoconnectCLI Usage$python-maiocomfoconnect--help

$python-maiocomfoconnectdiscover

$python-maiocomfoconnectregister--host192.168.1.213

$python-maiocomfoconnectset-speedaway--host192.168.1.213
$python-maiocomfoconnectset-speedlow--host192.168.1.213
$python-maiocomfoconnectset-modeauto--host192.168.1.213
$python-maiocomfoconnectset-speedmedium--host192.168.1.213
$python-maiocomfoconnectset-speedhigh--host192.168.1.213

$python-maiocomfoconnectshow-sensors--host192.168.1.213
$python-maiocomfoconnectshow-sensor276--host192.168.1.213
$python-maiocomfoconnectshow-sensor276--host192.168.1.213-f

$python-maiocomfoconnectget-property--host192.168.1.2131189# Unit 0x01, SubUnit 0x01, Property 0x08, Type STRING. See PROTOCOL-RMI.mdAvailable methodsasync connect(): Connect to the bridge.async disconnect(): Disconnect from the bridge.async register_sensor(sensor): Register a sensor.async deregister_sensor(sensor): Deregister a sensor.async get_mode(): Get the ventilation mode.async set_mode(mode): Set the ventilation mode. (auto / manual)async get_speed(): Get the ventilation speed.async set_speed(speed): Set the ventilation speed. (away / low / medium / high)async get_bypass(): Get the bypass mode.async set_bypass(mode, timeout=-1): Set the bypass mode. (auto / on / off)async get_balance_mode(): Get the balance mode.async set_balance_mode(mode, timeout=-1): Set the balance mode. (balance / supply only / exhaust only)async get_boost(): Get the boost mode.async set_boost(mode, timeout=-1): Set the boost mode. (boolean)async get_away(): Get the away mode.async set_away(mode, timeout=-1): Set the away mode. (boolean)async get_temperature_profile(): Get the temperature profile.async set_temperature_profile(profile): Set the temperature profile. (warm / normal / cool)async get_sensor_ventmode_temperature_passive(): Get the sensor based ventilation passive temperature control setting.async set_sensor_ventmode_temperature_passive(mode): Set the sensor based ventilation passive temperature control setting. (auto / on / off)async get_sensor_ventmode_humidity_comfort(): Get the sensor based ventilation humidity comfort setting.async set_sensor_ventmode_humidity_comfort(mode): Set the sensor based ventilation humidity comfort setting. (auto / on / off)async get_sensor_ventmode_humidity_protection(): Get the sensor based ventilation humidity protection setting.async set_sensor_ventmode_humidity_protection(mode): Set the sensor based ventilation humidity protection setting. (auto / on / off)Low-level APIasync cmd_start_session(): Start a session.async cmd_close_session(): Close a session.async cmd_list_registered_apps(): List registered apps.async cmd_register_app(uuid, device_name, pin): Register an app.async cmd_deregister_app(uuid): Deregister an app.async cmd_version_request(): Request the bridge's version.async cmd_time_request(): Request the bridge's time.async cmd_rmi_request(message, node_id): Send a RMI request.async cmd_rpdo_request(pdid, type, zone, timeout): Send a RPDO request.async cmd_keepalive(): Send a keepalive message.ExamplesDiscovery of ComfoConnect LAN C Bridgesimportasynciofromaiocomfoconnectimportdiscover_bridgesasyncdefmain():""" ComfoConnect LAN C Bridge discovery example."""# Discover all ComfoConnect LAN C Bridges on the subnet.bridges=awaitdiscover_bridges()print(bridges)if__name__=="__main__":asyncio.run(main())Basic ExampleimportasynciofromaiocomfoconnectimportComfoConnectfromaiocomfoconnect.constimportVentilationSpeedfromaiocomfoconnect.sensorsimportSENSORSasyncdefmain(local_uuid,host,uuid):""" Basic example."""defsensor_callback(sensor,value):""" Print sensor updates. """print(f"{sensor.name}={value}")# Connect to the Bridgecomfoconnect=ComfoConnect(host,uuid,sensor_callback=sensor_callback)awaitcomfoconnect.connect(local_uuid)# Register all sensorsforkeyinSENSORS:awaitcomfoconnect.register_sensor(SENSORS[key])# Set speed to LOWawaitcomfoconnect.set_speed(VentilationSpeed.LOW)# Wait 2 minutes so we can see some sensor updatesawaitasyncio.sleep(120)# Disconnect from the bridgeawaitcomfoconnect.disconnect()if__name__=="__main__":asyncio.run(main(local_uuid='00000000000000000000000000001337',host='192.168.1.20',uuid='00000000000000000000000000000055'))# Replace with your bridge's IP and UUIDDevelopment NotesProtocol DocumentationComfoConnect LAN C ProtocolPDO SensorsRMI commandsDecode network trafficYou can use thescripts/decode_pcap.pyfile to decode network traffic between the Mobile App and the ComfoConnect LAN C.
Make sure that the first TCP session in the capture is the connection between the bridge and the app. It's therefore recommended to start the capture before you open the app.$sudotcpdump-iany-s0-w/tmp/capture.pcaptcpandport56747$python3script/decode_pcap.py/tmp/capture.pcapGenerate zehnder_pb2.py filepip3installgrpcio-tools
python3-mgrpc_tools.protoc-Iprotobufprotobuf/nanopb.proto--python_out=aiocomfoconnect/protobuf
python3-mgrpc_tools.protoc-Iprotobufprotobuf/zehnder.proto--python_out=aiocomfoconnect/protobuf