### Install pytradfri with async support Source: https://github.com/home-assistant-libs/pytradfri/blob/master/README.md Install the pytradfri library with asynchronous support using pip. This may take a considerable amount of time on slower devices. ```shell pip install pytradfri[async] ``` -------------------------------- ### Install pytradfri Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Install pytradfri using pip. Include the async extras for asynchronous applications. ```bash pip install pytradfri ``` ```bash pip install pytradfri[async] ``` -------------------------------- ### Initialize Async API Factory Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Creates and initializes an async API factory for Tradfri gateway communication. Handles DTLS authentication and CoAP setup. For first-time setup, generate a PSK using the security code from the gateway. For subsequent connections, use saved credentials. ```python import asyncio import uuid from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory async def main(): # First time setup: generate PSK from security code identity = uuid.uuid4().hex api_factory = await APIFactory.init(host="192.168.1.100", psk_id=identity) # Security code is on the back of your gateway (16 characters) security_code = "abcd1234efgh5678" psk = await api_factory.generate_psk(security_code) print(f"Save these credentials - Identity: {identity}, PSK: {psk}") # Subsequent connections: use saved credentials api_factory = await APIFactory.init( host="192.168.1.100", psk_id=identity, psk=psk ) # Get the request function for making API calls api = api_factory.request # Use the API... gateway = Gateway() devices_command = gateway.get_devices() device_commands = await api(devices_command) devices = await api(device_commands) print(f"Found {len(devices)} devices") # Always shutdown when done await api_factory.shutdown() asyncio.run(main()) ``` -------------------------------- ### Control Smart Sockets with PyTradfri Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Shows how to turn smart wall plugs (sockets) on and off using the pytradfri library. This example iterates through found sockets, prints their current state and reachability, and toggles them. ```python import asyncio from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory async def control_sockets(): api_factory = await APIFactory.init( host="192.168.1.100", psk_id="my_identity", psk="my_saved_psk" ) api = api_factory.request gateway = Gateway() device_commands = await api(gateway.get_devices()) devices = await api(device_commands) sockets = [d for d in devices if d.has_socket_control] print(f"Found {len(sockets)} wall plugs") for socket_device in sockets: socket_control = socket_device.socket_control socket_obj = socket_control.sockets[0] print(f"\nSocket: {socket_device.name}") print(f" Current state: {'on' if socket_obj.state else 'off'}") print(f" Reachable: {socket_device.reachable}") # Turn socket on on_command = socket_control.set_state(True) await api(on_command) print(" Turned ON") await asyncio.sleep(3) # Turn socket off off_command = socket_control.set_state(False) await api(off_command) print(" Turned OFF") await api_factory.shutdown() asyncio.run(control_sockets()) ``` -------------------------------- ### APIFactory.init (Async) Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Creates and initializes an async API factory for communicating with the Tradfri gateway. This is the entry point for all async operations, handling DTLS authentication and CoAP protocol setup. ```APIDOC ## APIFactory.init (Async) ### Description Creates and initializes an async API factory for communicating with the Tradfri gateway. This is the entry point for all async operations, handling DTLS authentication and CoAP protocol setup. ### Method Async Function ### Endpoint N/A (Library Function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python import asyncio import uuid from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory async def main(): # First time setup: generate PSK from security code identity = uuid.uuid4().hex api_factory = await APIFactory.init(host="192.168.1.100", psk_id=identity) # Security code is on the back of your gateway (16 characters) security_code = "abcd1234efgh5678" psk = await api_factory.generate_psk(security_code) print(f"Save these credentials - Identity: {identity}, PSK: {psk}") # Subsequent connections: use saved credentials api_factory = await APIFactory.init( host="192.168.1.100", psk_id=identity, psk=psk ) # Get the request function for making API calls api = api_factory.request # Use the API... gateway = Gateway() devices_command = gateway.get_devices() device_commands = await api(devices_command) devices = await api(device_commands) print(f"Found {len(devices)} devices") # Always shutdown when done await api_factory.shutdown() asyncio.run(main()) ``` ### Response #### Success Response (200) N/A (Function returns API factory object or PSK) #### Response Example ```json { "example": "Save these credentials - Identity: , PSK: " } ``` ``` -------------------------------- ### Control Blinds with PyTradfri Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Provides an example of controlling window blinds by setting their position from 0% (fully closed) to 100% (fully open). It demonstrates setting specific positions and toggling between open and closed states. ```python import asyncio from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory async def control_blinds(): api_factory = await APIFactory.init( host="192.168.1.100", psk_id="my_identity", psk="my_saved_psk" ) api = api_factory.request gateway = Gateway() device_commands = await api(gateway.get_devices()) devices = await api(device_commands) blinds = [d for d in devices if d.has_blind_control] print(f"Found {len(blinds)} window blinds") for blind_device in blinds: blind_control = blind_device.blind_control blind_obj = blind_control.blinds[0] print(f"\nBlind: {blind_device.name}") print(f" Current position: {blind_obj.current_cover_position}%") print(f" Battery level: {blind_device.device_info.battery_level}%") # Set to 50% open position_command = blind_control.set_state(50) await api(position_command) print(" Set to 50% open") await asyncio.sleep(5) # Fully open open_command = blind_control.set_state(100) await api(open_command) print(" Fully opened") await asyncio.sleep(5) # Fully close close_command = blind_control.set_state(0) await api(close_command) print(" Fully closed") await api_factory.shutdown() asyncio.run(control_blinds()) ``` -------------------------------- ### APIFactory (Sync) Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Creates a synchronous API factory for communicating with the Tradfri gateway using libcoap. Requires the coap-client binary to be installed on the system. ```APIDOC ## APIFactory (Sync) ### Description Creates a synchronous API factory for communicating with the Tradfri gateway using libcoap. Requires the coap-client binary to be installed on the system. ### Method Synchronous Function ### Endpoint N/A (Library Function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python import uuid from pytradfri import Gateway from pytradfri.api.libcoap_api import APIFactory def main(): # First time setup identity = uuid.uuid4().hex api_factory = APIFactory(host="192.168.1.100", psk_id=identity) # Generate PSK from security code (on back of gateway) security_code = "abcd1234efgh5678" psk = api_factory.generate_psk(security_code) print(f"Save credentials - Identity: {identity}, PSK: {psk}") # For subsequent connections, use saved credentials api_factory = APIFactory( host="192.168.1.100", psk_id=identity, psk=psk, timeout=10 # Request timeout in seconds ) api = api_factory.request gateway = Gateway() devices_command = gateway.get_devices() device_commands = api(devices_command) devices = api(device_commands) print(f"Found {len(devices)} devices") for device in devices: print(f" - {device.name} ({device.device_info.model_number})") main() ``` ### Response #### Success Response (200) N/A (Function returns API factory object or PSK) #### Response Example ```json { "example": "Save credentials - Identity: , PSK: " } ``` ``` -------------------------------- ### Start pytradfri in stand-alone CLI mode Source: https://github.com/home-assistant-libs/pytradfri/blob/master/README.md Launch the pytradfri library in an interactive command-line interface. Replace IP with your gateway's IP address. You will be prompted for the gateway's security code on first use. ```shell python3 -i -m pytradfri IP ``` -------------------------------- ### Initialize Sync API Factory Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Creates a synchronous API factory for Tradfri gateway communication using libcoap. Requires coap-client. For first-time setup, generate a PSK using the security code from the gateway. For subsequent connections, use saved credentials. ```python import uuid from pytradfri import Gateway from pytradfri.api.libcoap_api import APIFactory def main(): # First time setup identity = uuid.uuid4().hex api_factory = APIFactory(host="192.168.1.100", psk_id=identity) # Generate PSK from security code (on back of gateway) security_code = "abcd1234efgh5678" psk = api_factory.generate_psk(security_code) print(f"Save credentials - Identity: {identity}, PSK: {psk}") # For subsequent connections, use saved credentials api_factory = APIFactory( host="192.168.1.100", psk_id=identity, psk=psk, timeout=10 # Request timeout in seconds ) api = api_factory.request gateway = Gateway() devices_command = gateway.get_devices() device_commands = api(devices_command) devices = api(device_commands) print(f"Found {len(devices)} devices") for device in devices: print(f" - {device.name} ({device.device_info.model_number})") main() ``` -------------------------------- ### Control Air Purifier with PyTradfri Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt This example shows how to control an IKEA Starkvind air purifier, including setting fan speed, enabling auto mode, locking controls, and turning off LEDs. It also prints the current status of the purifier. Requires valid API credentials. ```python import asyncio from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory async def control_air_purifier(): api_factory = await APIFactory.init( host="192.168.1.100", psk_id="my_identity", psk="my_saved_psk" ) api = api_factory.request gateway = Gateway() device_commands = await api(gateway.get_devices()) devices = await api(device_commands) purifiers = [d for d in devices if d.has_air_purifier_control] for purifier_device in purifiers: control = purifier_device.air_purifier_control purifier = control.air_purifiers[0] print(f"Air Purifier: {purifier_device.name}") print(f" State: {'on' if purifier.state else 'off'}") print(f" Auto mode: {purifier.is_auto_mode}") print(f" Fan speed: {purifier.fan_speed} (0=off, 2-50=speed)") print(f" Air quality: {purifier.air_quality}") # Air quality: 0-35 Good, 36-85 OK, 86+ Not Good, 65535 Measuring print(f" Controls locked: {purifier.controls_locked}") print(f" LEDs off: {purifier.leds_off}") print(f" Filter runtime: {purifier.filter_runtime} mins") print(f" Filter remaining: {purifier.filter_lifetime_remaining} mins") print(f" Filter needs replacing: {purifier.filter_status}") print(f" Motor runtime: {purifier.motor_runtime_total} mins") # Turn on auto mode auto_command = control.turn_on_auto_mode() await api(auto_command) print(" Enabled auto mode") await asyncio.sleep(3) # Set specific fan speed (2-50) speed_command = control.set_fan_speed(25) await api(speed_command) print(" Set fan speed to 25") # Lock physical controls lock_command = control.set_controls_locked(True) await api(lock_command) print(" Locked physical controls") # Turn off LEDs led_command = control.set_leds_off(True) await api(led_command) print(" Turned off LEDs") await asyncio.sleep(3) # Turn off purifier off_command = control.turn_off() await api(off_command) print(" Turned off") await api_factory.shutdown() asyncio.run(control_air_purifier()) ``` -------------------------------- ### GET Gateway.get_groups Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Retrieves all device groups configured on the gateway and provides methods to control group state, brightness, and color. ```APIDOC ## GET Gateway.get_groups ### Description Returns all device groups configured on the gateway. Groups allow controlling multiple devices together. ### Method GET ### Endpoint Gateway.get_groups() ### Response #### Success Response (200) - **groups** (list) - A list of group objects containing properties like name, id, state, dimmer, hex_color, member_ids, and mood_id. ``` -------------------------------- ### Manage Gateway Smart Tasks Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Retrieves and manages scheduled smart tasks (automations) configured on the gateway. Allows enabling/disabling tasks, modifying start times, and adjusting device settings within tasks. Requires API initialization with host, PSK ID, and PSK. ```python import asyncio from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory async def manage_smart_tasks(): api_factory = await APIFactory.init( host="192.168.1.100", psk_id="my_identity", psk="my_saved_psk" ) api = api_factory.request gateway = Gateway() tasks_command = gateway.get_smart_tasks() task_commands = await api(tasks_command) tasks = await api(task_commands) print(f"Found {len(tasks)} smart tasks") for task in tasks: print(f"\nTask: {task.name} (ID: {task.id})") print(f" Type: {task.task_type_name}") print(f" Type ID: {task.task_type_id}") print(f" State: {'enabled' if task.state else 'disabled'}") print(f" Start time: {task.task_start_time}") print(f" Repeat days: {task.repeat_days_list}") # Access task control task_control = task.task_control # Get task items (devices in this task) task_items = task_control.tasks print(f" Devices in task: {len(task_items)}") for item in task_items: print(f" Device ID: {item.id}") print(f" Dimmer target: {item.dimmer}") print(f" Transition time: {item.transition_time} mins") # Modify task settings controller = item.item_controller # Set final dimmer value dimmer_command = controller.set_dimmer(200) await api(dimmer_command) print(f" Set target dimmer to 200") # Set transition time (in minutes) time_command = controller.set_transition_time(30) await api(time_command) print(f" Set transition time to 30 minutes") # Enable/disable task enable_command = task_control.set_state(True) await api(enable_command) print(f" Task enabled") # Set start time (hour, minute) time_command = task_control.set_dimmer_start_time(7, 30) await api(time_command) print(f" Set start time to 07:30") await api_factory.shutdown() asyncio.run(manage_smart_tasks()) ``` -------------------------------- ### GET Group.moods Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Retrieves the available moods (scenes) for a specific group and provides functionality to activate them. ```APIDOC ## GET Group.moods ### Description Returns the moods (scenes) available in a group. Moods define preset light configurations. ### Method GET ### Endpoint Group.moods() ### Response #### Success Response (200) - **moods** (list) - A list of mood objects containing properties like name and id. ``` -------------------------------- ### Initialize and Control Tradfri Gateway Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Demonstrates full lifecycle management including credential storage, device discovery, light control, and event observation. ```python import asyncio import uuid import json from pathlib import Path from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory from pytradfri.error import PytradfriError, RequestTimeout from pytradfri.device import Device from pytradfri.resource import ApiResource CONFIG_FILE = Path("tradfri_config.json") def load_config(): """Load saved configuration.""" if CONFIG_FILE.exists(): return json.loads(CONFIG_FILE.read_text()) return {} def save_config(config): """Save configuration.""" CONFIG_FILE.write_text(json.dumps(config, indent=2)) async def main(): gateway_ip = "192.168.1.100" security_code = None # Set this on first run config = load_config() # Initialize API factory if gateway_ip in config: # Use saved credentials identity = config[gateway_ip]["identity"] psk = config[gateway_ip]["psk"] api_factory = await APIFactory.init( host=gateway_ip, psk_id=identity, psk=psk ) else: # First time setup if not security_code: security_code = input("Enter security code from gateway: ").strip() identity = uuid.uuid4().hex api_factory = await APIFactory.init(host=gateway_ip, psk_id=identity) psk = await api_factory.generate_psk(security_code) config[gateway_ip] = {"identity": identity, "psk": psk} save_config(config) print(f"Saved credentials for {gateway_ip}") api = api_factory.request gateway = Gateway() try: # Get gateway info info = await api(Gateway.get_gateway_info()) print(f"Connected to gateway {info.id} (firmware {info.firmware_version})") # Get all devices device_commands = await api(gateway.get_devices()) devices = await api(device_commands) lights = [d for d in devices if d.has_light_control] sockets = [d for d in devices if d.has_socket_control] blinds = [d for d in devices if d.has_blind_control] print(f"\nDevices: {len(lights)} lights, {len(sockets)} plugs, {len(blinds)} blinds") # Control a light if lights: light = lights[0] control = light.light_control print(f"\nControlling light: {light.name}") # Turn on and set brightness await api(control.set_state(True)) await api(control.set_dimmer(200)) if control.lights[0].supports_color_temp: await api(control.set_color_temp(350)) print("Light configured") # Set up observation def on_update(device: ApiResource): if isinstance(device, Device) and device.has_light_control: state = device.light_control.lights[0] print(f"[{device.name}] state={state.state}, dimmer={state.dimmer}") for light in lights[:2]: # Observe first 2 lights observe_cmd = light.observe(on_update, lambda e: print(f"Error: {e}"), duration=30) asyncio.create_task(api(observe_cmd)) print("\nObserving for 30 seconds...") await asyncio.sleep(30) except RequestTimeout: print("Gateway timeout - check network connection") except PytradfriError as e: print(f"Error: {e}") finally: await api_factory.shutdown() print("Disconnected") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### List all lights in CLI Source: https://github.com/home-assistant-libs/pytradfri/blob/master/README.md In the pytradfri interactive prompt, use the 'lights' command to list all connected lights. ```python lights ``` -------------------------------- ### Combine Light Commands with PyTradfri Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Demonstrates how to combine multiple light control commands (state, brightness, color) into a single request for devices that support it, like Philips Hue bulbs. Ensure you have the necessary API credentials and host information. ```python import asyncio from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory async def combine_light_commands(): api_factory = await APIFactory.init( host="192.168.1.100", psk_id="my_identity", psk="my_saved_psk" ) api = api_factory.request gateway = Gateway() device_commands = await api(gateway.get_devices()) devices = await api(device_commands) lights = [d for d in devices if d.has_light_control] for light in lights: light_control = light.light_control # Check if this bulb can combine commands # (Philips Hue bulbs support this) if light_control.can_combine_commands: print(f"Light '{light.name}' supports combined commands") # Create individual commands state_cmd = light_control.set_state(True) dimmer_cmd = light_control.set_dimmer(200) color_cmd = light_control.set_hex_color("efd275") # Combine into single command combined = light_control.combine_commands([ state_cmd, dimmer_cmd, color_cmd ]) # Execute single combined command await api(combined) print(" Applied state, brightness, and color in one request") else: print(f"Light '{light.name}' requires separate commands") # Execute commands individually await api(light_control.set_state(True)) await api(light_control.set_dimmer(200)) await api_factory.shutdown() asyncio.run(combine_light_commands()) ``` -------------------------------- ### Retrieve and categorize all devices Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Fetches all connected devices from the gateway and categorizes them by their control capabilities. ```python import asyncio from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory async def list_all_devices(): api_factory = await APIFactory.init( host="192.168.1.100", psk_id="my_identity", psk="my_saved_psk" ) api = api_factory.request gateway = Gateway() # Step 1: Get list of device IDs devices_command = gateway.get_devices() device_commands = await api(devices_command) # Step 2: Fetch each device's details devices = await api(device_commands) # Categorize devices by type lights = [d for d in devices if d.has_light_control] sockets = [d for d in devices if d.has_socket_control] blinds = [d for d in devices if d.has_blind_control] air_purifiers = [d for d in devices if d.has_air_purifier_control] repeaters = [d for d in devices if d.has_signal_repeater_control] print(f"Lights: {len(lights)}") for light in lights: print(f" - {light.name} (ID: {light.id})") print(f" Model: {light.device_info.model_number}") print(f" Firmware: {light.device_info.firmware_version}") print(f" Reachable: {light.reachable}") print(f"\nWall Plugs: {len(sockets)}") print(f"Blinds: {len(blinds)}") print(f"Air Purifiers: {len(air_purifiers)}") print(f"Signal Repeaters: {len(repeaters)}") await api_factory.shutdown() asyncio.run(list_all_devices()) ``` -------------------------------- ### Observe light for state changes in CLI Source: https://github.com/home-assistant-libs/pytradfri/blob/master/README.md In the pytradfri interactive prompt, use the 'observe' method on a light to register a callback function that will be executed when the light's state changes. The callback receives the device object as an argument. ```python def change_listener(device): print(device.name + " is now " + str(device.light_control.lights[0].state)) api(lights[0].observe(change_listener)) ``` -------------------------------- ### Observe Device State Changes Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Observes a device for real-time state changes. Callbacks are invoked whenever the device state updates. Requires specifying host, PSK ID, and PSK for API initialization. The observation duration is set to 120 seconds. ```python import asyncio from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory from pytradfri.device import Device from pytradfri.resource import ApiResource async def observe_devices(): api_factory = await APIFactory.init( host="192.168.1.100", psk_id="my_identity", psk="my_saved_psk" ) api = api_factory.request gateway = Gateway() device_commands = await api(gateway.get_devices()) devices = await api(device_commands) lights = [d for d in devices if d.has_light_control] def on_update(updated_device: ApiResource) -> None: """Called when device state changes.""" assert isinstance(updated_device, Device) if updated_device.has_light_control: light = updated_device.light_control.lights[0] print(f"[UPDATE] {updated_device.name}:") print(f" State: {'on' if light.state else 'off'}") print(f" Dimmer: {light.dimmer}") print(f" Color: {light.hex_color}") def on_error(err: Exception) -> None: """Called when observation fails.""" print(f"[ERROR] Observation error: {err}") # Start observing all lights for light in lights: observe_command = light.observe( callback=on_update, err_callback=on_error, duration=120 # Observe for 120 seconds ) # Start observation as background task asyncio.create_task(api(observe_command)) print(f"Started observing: {light.name}") # Allow observations to start await asyncio.sleep(0.1) print("\nObserving for 2 minutes...") print("Try changing lights via the IKEA app to see updates!\n") # Keep running for observation period await asyncio.sleep(120) await api_factory.shutdown() asyncio.run(observe_devices()) ``` -------------------------------- ### Toggle light power state Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Demonstrates how to identify a light device and toggle its power state using the LightControl interface. ```python import asyncio from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory async def toggle_lights(): api_factory = await APIFactory.init( host="192.168.1.100", psk_id="my_identity", psk="my_saved_psk" ) api = api_factory.request gateway = Gateway() # Get all devices device_commands = await api(gateway.get_devices()) devices = await api(device_commands) # Filter for lights lights = [d for d in devices if d.has_light_control] if lights: light = lights[0] light_control = light.light_control current_state = light_control.lights[0].state print(f"Light '{light.name}' is currently {'on' if current_state else 'off'}") # Toggle the light new_state = not current_state state_command = light_control.set_state(new_state) await api(state_command) print(f"Light is now {'on' if new_state else 'off'}") await api_factory.shutdown() asyncio.run(toggle_lights()) ``` -------------------------------- ### Set Tradfri Light Color using RGB to XYZ Conversion Source: https://github.com/home-assistant-libs/pytradfri/wiki/Example-script-for-using-different-color-models This script demonstrates setting a light's color by converting an RGB value to the CIE XYZ color space, which is used by the Tradfri gateway. It requires the colormath library for conversions and pytradfri for device communication. Ensure you have the gateway's IP address and security code. ```python #!/usr/bin/env python3 """Color examples. This is a file to give examples on how to work with colors The gateway supports _some_ hex values, otherwise colors stored as XY A guess is that IKEA uses the CIE XYZ space To run the script, do the following: $ pip3 install pytradfri $ Download this file (example_color.py) $ python3 example_color.py Where is the address to your IKEA gateway. The first time running you will be asked to input the 'Security Code' found on the back of your IKEA gateway. The gateway returns: Hue (a guess) Saturation (a guess) Brignthess X Y Hex (for some colors) """ import os # Hack to allow relative import above top level package import sys folder = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, os.path.normpath("%s/.." % folder)) import argparse import asyncio import uuid from colormath.color_conversions import convert_color from colormath.color_objects import XYZColor, sRGBColor from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory from pytradfri.error import PytradfriError from pytradfri.util import load_json, save_json CONFIG_FILE = "tradfri_standalone_psk.conf" parser = argparse.ArgumentParser() parser.add_argument( "host", metavar="IP", type=str, help="IP Address of your Tradfri gateway" ) parser.add_argument( "-K", "--key", dest="key", required=False, help="Key found on your Tradfri gateway" ) args = parser.parse_args() if args.host not in load_json(CONFIG_FILE) and args.key is None: print( "Please provide the 'Security Code' on the back of your " "Tradfri gateway:", end=" ", ) key = input().strip() if len(key) != 16: raise PytradfriError("Invalid 'Security Code' provided.") else: args.key = key async def run(): """Run.""" # Assign configuration variables. # The configuration check takes care they are present. conf = load_json(CONFIG_FILE) try: identity = conf[args.host].get("identity") psk = conf[args.host].get("key") api_factory = await APIFactory.init(host=args.host, psk_id=identity, psk=psk) except KeyError: identity = uuid.uuid4().hex api_factory = await APIFactory.init(host=args.host, psk_id=identity) try: psk = await api_factory.generate_psk(args.key) print("Generated PSK: ", psk) conf[args.host] = {"identity": identity, "key": psk} save_json(CONFIG_FILE, conf) except AttributeError: raise PytradfriError( "Please provide the 'Security Code' on the " "back of your Tradfri gateway using the " "-K flag." ) api = api_factory.request gateway = Gateway() devices_command = gateway.get_devices() devices_commands = await api(devices_command) devices = await api(devices_commands) lights = [dev for dev in devices if dev.has_light_control] rgb = (0, 0, 102) # Convert RGB to XYZ using a D50 illuminant. xyz = convert_color( sRGBColor(rgb[0], rgb[1], rgb[2]), XYZColor, observer="2", target_illuminant="d65", ) xy = int(xyz.xyz_x), int(xyz.xyz_y) light = None # Find a bulb that can set color for dev in lights: if dev.light_control.lights[0].supports_hsb_xy_color: light = dev break if not light: print("No color bulbs found") return xy_command = light.light_control.set_xy_color(xy[0], xy[1]) await api(xy_command) xy = light.light_control.lights[0].xy_color # Normalize Z Z = int(light.light_control.lights[0].dimmer / 254 * 65535) xyZ = xy + (Z,) rgb = convert_color( XYZColor(xyZ[0], xyZ[1], xyZ[2]), sRGBColor, observer="2", target_illuminant="d65", ) rgb = (int(rgb.rgb_r), int(rgb.rgb_g), int(rgb.rgb_b)) print(rgb) await asyncio.sleep(120) await api_factory.shutdown() asyncio.get_event_loop().run_until_complete(run()) ``` -------------------------------- ### Enable Gateway Pairing Mode Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Puts the gateway into pairing mode for a specified duration to allow new device discovery. ```python import asyncio from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory async def enable_pairing_mode(): api_factory = await APIFactory.init( host="192.168.1.100", psk_id="my_identity", psk="my_saved_psk" ) api = api_factory.request # Enable pairing mode for 60 seconds pairing_command = Gateway.set_commissioning_timeout(60) await api(pairing_command) print("Gateway is now in pairing mode for 60 seconds") print("Press the pairing button on your device now...") await api_factory.shutdown() asyncio.run(enable_pairing_mode()) ``` -------------------------------- ### Retrieve gateway system information Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Fetches metadata about the gateway, including firmware version, pairing status, and update progress. ```python import asyncio from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory async def get_gateway_details(): api_factory = await APIFactory.init( host="192.168.1.100", psk_id="my_identity", psk="my_saved_psk" ) api = api_factory.request gateway = Gateway() info_command = Gateway.get_gateway_info() info = await api(info_command) print(f"Gateway ID: {info.id}") print(f"Firmware Version: {info.firmware_version}") print(f"Current Time: {info.current_time}") print(f"Current Time (ISO): {info.current_time_iso8601}") print(f"NTP Server: {info.ntp_server}") print(f"First Setup: {info.first_setup}") print(f"HomeKit ID: {info.homekit_id}") print(f"Alexa Paired: {info.pair_status_alexa}") print(f"Google Home Paired: {info.pair_status_google_home}") print(f"OTA Update State: {info.ota_update_state}") print(f"Update Progress: {info.update_progress}%") print(f"Commissioning Mode: {info.commissioning_mode}") await api_factory.shutdown() asyncio.run(get_gateway_details()) ``` -------------------------------- ### Gateway.get_devices Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Retrieves a list of all devices connected to the gateway. This involves two steps: first fetching device IDs, then fetching the details for each device. ```APIDOC ## Gateway.get_devices ### Description Returns a command to retrieve all devices connected to the gateway. The result is a list of device commands that must be executed to get the actual Device objects. ### Method GET (conceptual, actual implementation uses async API calls) ### Endpoint N/A (Library function) ### Request Example ```python # This is a conceptual representation of the call within the library # Actual execution is handled by the APIFactory gateway.get_devices() ``` ### Response #### Success Response (200) - **device_commands** (list) - A list of commands to fetch individual device details. - **devices** (list) - A list of Device objects after executing the commands. ### Response Example ```json # Example of a Device object (structure may vary) [ { "id": "device_id_1", "name": "Living Room Light", "type": "light", "reachable": true, "device_info": { "model_number": "TRADFRI bulb E27 CWS opal 600lm", "firmware_version": "2.3.0099" }, "has_light_control": true } ] ``` ``` -------------------------------- ### Handle pytradfri Exceptions Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Demonstrates catching specific library exceptions to manage network timeouts, client errors, and server-side issues. ```python import asyncio from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory from pytradfri.error import ( PytradfriError, RequestError, RequestTimeout, ClientError, ServerError, ColorError ) async def handle_errors(): try: api_factory = await APIFactory.init( host="192.168.1.100", psk_id="my_identity", psk="my_saved_psk" ) api = api_factory.request gateway = Gateway() device_commands = await api(gateway.get_devices()) devices = await api(device_commands) except RequestTimeout as e: # Request timed out - gateway may be unreachable print(f"Timeout: Gateway did not respond. Check network connection.") print(f"Details: {e}") except ClientError as e: # Client-side error (4.xx CoAP codes) print(f"Client error: Invalid request or authentication failed.") print(f"Details: {e}") except ServerError as e: # Server-side error (5.xx CoAP codes) print(f"Server error: Gateway encountered an internal error.") print(f"Details: {e}") except RequestError as e: # General request error print(f"Request failed: {e}") except PytradfriError as e: # Base exception for all pytradfri errors print(f"Pytradfri error: {e}") except Exception as e: # Unexpected error print(f"Unexpected error: {type(e).__name__}: {e}") finally: if 'api_factory' in locals(): await api_factory.shutdown() asyncio.run(handle_errors()) ``` -------------------------------- ### Group bulbs by name pattern Source: https://github.com/home-assistant-libs/pytradfri/wiki/Access-your-bulbs-through-their-names-instead-of-ID Filters available devices by light control capability and assigns them to groups based on partial name matches. ```Python # Like we know en love from the examples lampList = [dev for dev in devices if dev.has_light_control] # Define the different group names groupNameList = ['Alpha', 'Beta'] # Make an empty dict to store our groups groups = {} # Iterate all group names for groupName in groupNameList: groups[groupName] = [] # Iterate all lamps on the network for lamp in lampList: # Check if the group name is a partial of the lamp name. By forcing both to be lowercase the check is case insensitive. if groupName.lower() in lamp.name.lower(): groups[groupName].append(lamp) # Output the group hierarchy print(groups) ``` -------------------------------- ### Set light color using predefined names with LightControl Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Use set_predefined_color to apply a color by name. Requires handling ColorError for invalid color names. ```python import asyncio from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory from pytradfri.error import ColorError async def use_predefined_colors(): api_factory = await APIFactory.init( host="192.168.1.100", psk_id="my_identity", psk="my_saved_psk" ) api = api_factory.request gateway = Gateway() device_commands = await api(gateway.get_devices()) devices = await api(device_commands) lights = [d for d in devices if d.has_light_control] for light in lights: light_control = light.light_control if light_control.lights[0].supports_hex_color: # Cycle through some colors color_names = ["warm_glow", "candlelight", "cool_white", "light_blue"] for color_name in color_names: try: color_command = light_control.set_predefined_color(color_name) await api(color_command) print(f"Set '{light.name}' to {color_name}") await asyncio.sleep(2) except ColorError as e: print(f"Invalid color: {e}") await api_factory.shutdown() asyncio.run(use_predefined_colors()) ``` -------------------------------- ### Manage Gateway Groups with PyTradfri Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt Use this snippet to retrieve all configured groups on a TRÅDFRI gateway, display their properties, and control their states. Ensure you have initialized the APIFactory with your gateway's host, PSK ID, and PSK. ```python import asyncio from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory async def manage_groups(): api_factory = await APIFactory.init( host="192.168.1.100", psk_id="my_identity", psk="my_saved_psk" ) api = api_factory.request gateway = Gateway() # Get all groups groups_command = gateway.get_groups() group_commands = await api(groups_command) groups = await api(group_commands) print(f"Found {len(groups)} groups") for group in groups: print(f"\nGroup: {group.name} (ID: {group.id})") print(f" State: {'on' if group.state else 'off'}") print(f" Dimmer: {group.dimmer}/254") print(f" Color: {group.hex_color}") print(f" Member IDs: {group.member_ids}") print(f" Active mood ID: {group.mood_id}") # Get member device details member_commands = group.members() if member_commands: members = await api(member_commands) print(" Members:") for member in members: print(f" - {member.name}") # Control the entire group # Turn group on state_command = group.set_state(True) await api(state_command) print(" Group turned ON") # Set group dimmer dim_command = group.set_dimmer(180) await api(dim_command) print(" Group dimmer set to 180") # Set group color (for color-capable lights) color_command = group.set_hex_color("efd275") await api(color_command) print(" Group color set to warm glow") await api_factory.shutdown() asyncio.run(manage_groups()) ``` -------------------------------- ### Manage Group Moods with PyTradfri Source: https://context7.com/home-assistant-libs/pytradfri/llms.txt This snippet demonstrates how to retrieve available moods (scenes) for a group and activate a specific mood. It requires prior initialization of the APIFactory and retrieval of group objects. ```python import asyncio from pytradfri import Gateway from pytradfri.api.aiocoap_api import APIFactory async def manage_moods(): api_factory = await APIFactory.init( host="192.168.1.100", psk_id="my_identity", psk="my_saved_psk" ) api = api_factory.request gateway = Gateway() groups_command = gateway.get_groups() group_commands = await api(groups_command) groups = await api(group_commands) for group in groups: print(f"\nGroup: {group.name}") print(f" Current mood ID: {group.mood_id}") # Get available moods moods_command = group.moods() mood_commands = await api(moods_command) moods = await api(mood_commands) print(f" Available moods:") for mood in moods: print(f" - {mood.name} (ID: {mood.id})") # Activate a mood if moods: mood_to_activate = moods[0] activate_command = group.activate_mood(mood_to_activate.id) await api(activate_command) print(f" Activated mood: {mood_to_activate.name}") await api_factory.shutdown() asyncio.run(manage_moods()) ```