Python library and CLI for controlling Philips air purifiers over the local network using the encrypted CoAP protocol.
Philips air purifiers (AC series) expose a CoAP endpoint on port 5683 of your local network. This library communicates with that endpoint using an AES-128/CBC encryption scheme reverse-engineered from the Philips app. No cloud connection or account is required.
Supported operations:
- Read the current device status (all sensor readings and settings)
- Observe live status updates as the device pushes them
- Send control commands to change settings
Home Assistant integration If you want to control your Philips air purifier from Home Assistant, see the companion integration: kongo09/philips_airpurifier_coap. It is built on top of this library.
- Python 3.12 or newer
- The air purifier must be on the same local network (or otherwise reachable by IP)
pip install aioairctrlAll commands require the -H/--host flag with the IP address of your purifier. Find it in your router's DHCP table or the Philips app.
aioairctrl -H 192.168.1.100 statusAdd --json to get machine-readable output:
aioairctrl -H 192.168.1.100 status --jsonStays connected and prints a new line each time the device reports a change (e.g. sensor readings, mode changes):
aioairctrl -H 192.168.1.100 status-observe
aioairctrl -H 192.168.1.100 status-observe --jsonPress Ctrl+C to stop.
String values:
aioairctrl -H 192.168.1.100 set mode=AGBoolean values (true/false are handled automatically):
aioairctrl -H 192.168.1.100 set pwr=true
aioairctrl -H 192.168.1.100 set pwr=falseInteger values (use -I/--int):
aioairctrl -H 192.168.1.100 set -I om=2Multiple values at once:
aioairctrl -H 192.168.1.100 set -I pwr=true om=2Add -D/--debug to any command to see the raw CoAP traffic:
aioairctrl -H 192.168.1.100 --debug statusimport asyncio
from aioairctrl import CoAPClient
async def main():
client = await CoAPClient.create(host="192.168.1.100")
try:
# Read status once
status, max_age = await client.get_status()
print(status)
# Stream live updates
async for status in client.observe_status():
print(status)
break # stop after first update
# Send a command
await client.set_control_value("pwr", True)
# Send multiple values at once
await client.set_control_values({"om": 2, "rhset": 50})
finally:
await client.shutdown()
asyncio.run(main())MIT