denonavr Automation Library

repository·main·Indexed 42 days ago

https://github.com/ol-iver/denonavr

An asynchronous Python library for controlling Denon AVR receivers via HTTP and Telnet. It provides interfaces for managing power, inputs, sound settings, and real-time status monitoring. Key features include SSDP device discovery, media metadata retrieval via the DenonAVRInput class, and a REST interface through DenonAVRApi. Version 1.4.0-dev supports real-time event callbacks and AppCommand sequences for advanced receiver control.

Tokens
21.3K
Snippets
87
Records
111
Agent score
52%

What's inside denonavr

  1. Monitor real-time events via telnet

    main

    To receive instant updates when the receiver's status changes, you can establish a telnet connection on TCP port 23. This allows you to register a callback that triggers whenever a status change event occurs. Note that receivers typically support only one active telnet connection at a time.

    1. Call await d.async_telnet_connect() after setup.
    2. Define a callback function with the signature callback(zone, event, parameter).
    3. Register the callback using d.register_callback(zone, callback). Use "ALL" as the zone to listen to all events.
    import asyncio
    import denonavr
    
    d = denonavr.DenonAVR("192.168.1.119")
    await d.async_setup()
    await d.async_telnet_connect()
    await d.async_update()
    
    def update_callback(zone, event, parameter):
        print("Zone: " + zone + " Event: " + event + " Parameter: " + parameter)
    
    d.register_callback("ALL", update_callback)
  2. Basic usage with async/await

    main

    The library is designed for asynchronous operation. To use it, instantiate a DenonAVR object with the receiver's IP address, then call await d.async_setup() to initialize the connection. You can use await d.async_update() to refresh the local state of the device before reading properties like volume or power.

    import asyncio
    import denonavr
    
    d = denonavr.DenonAVR("192.168.1.119")
    await d.async_setup()
    await d.async_update()
    print(d.volume)
  3. Use DenonAVRDeviceInfo to manage receiver state

    main

    The DenonAVRDeviceInfo class is the central object for interacting with a Denon AVR receiver. It maintains the current state of the device (power, volume, inputs, etc.) and provides access to both HTTP (api) and Telnet (telnet_api) interfaces.

    Key capabilities include:

    • Automatic Identification: During async_setup(), the class identifies whether the receiver is a standard AVR or an AVR-X model and determines the appropriate update method (AppCommand.xml vs Status XML).
    • State Management: It stores properties like power, dimmer, eco_mode, and room_size.
    • Zone Support: You can initialize it for specific zones (e.g., MAIN_ZONE, ZONE2, ZONE3).
    • Asynchronous Updates: Use async_update() to refresh the device state from the receiver.
    # Conceptual usage of DenonAVRDeviceInfo
    from denonavr.foundation import DenonAVRDeviceInfo
    
    # Note: Actual instantiation depends on the full API implementation
    device = DenonAVRDeviceInfo(
        api=my_denon_api,
        telnet_api=my_telnet_api,
        zone="MAIN_ZONE"
    )
    
    await device.async_update()
    print(f"Power state: {device.power}")
  4. Handle renamed and deleted sources

    main

    Denon receivers allow users to rename or delete input sources. DenonAVRInput handles this through two internal mechanisms depending on the receiver model:

    1. AppCommand.xml (AVR-X and 2016+ models): Uses async_get_changed_sources_appcommand to query the device via HTTP for a list of renamed and deleted functions.
    2. Status.xml (Older AVR models): Uses async_get_changed_sources_status_xml to parse the status XML for RenameSource and SourceDelete tags.

    When async_update is called, these mappings are applied so that _input_func reflects the user's custom names rather than the factory defaults.

  5. Perform asynchronous setup and updates

    main

    Before interacting with the device, you must call async_setup() to load configuration from the receiver. To refresh the current status of all components (input, sound mode, volume, etc.), use async_update(). Both methods are asynchronous and should be awaited.

    import asyncio
    from denonavr import DenonAVR
    
    async def main():
        avr = DenonAVR(host='192.168.1.100')
        
        # Load configuration
        await avr.async_setup()
        
        # Refresh status
        await avr.async_update()
    
    asyncio.run(main())
  6. Initialize the DenonAVR client

    main

    To control a Denon AVR, instantiate the DenonAVR class. You can specify the host (IP or hostname), an optional device name, and configuration for timeouts and rate limiting. You can also create additional zone instances by providing a dictionary of zones via add_zones.

    from denonavr import DenonAVR
    
    # Basic initialization
    avr = DenonAVR(host='192.168.1.100', name='Living Room AVR')
    
    # Initialization with additional zones
    avr = DenonAVR(
        host='192.168.1.100',
        name='Main AVR',
        add_zones={'Zone2': 'Bedroom'}
    )
  7. Control Sound and Volume

    main

    The library provides several methods for adjusting audio parameters:

    Mute

    • await d.async_mute(True): Mutes the audio.
    • await d.async_mute(False): Unmutes the audio.

    Volume

    • await d.async_volume_up(): Increases volume.
    • await d.async_volume_down(): Decreases volume.
    • await d.async_set_volume(value): Sets volume to a specific level.

    Bass and Treble

    • await d.async_bass_up() / await d.async_bass_down()
    • await d.async_treble_up() / await d.async_treble_down()
    # Mute
    await d.async_mute(True)
    
    # Volume
    await d.async_set_volume(50)
    await d.async_volume_up()
    
    # Bass/Treble
    await d.async_bass_up()
    await d.async_treble_down()
  8. Control Power and Input

    main

    Use the following asynchronous methods to control the power state and input selection of the receiver:

    • await d.async_power_on(): Turns the receiver on.
    • await d.async_power_off(): Turns the receiver off.
    • await d.async_set_input_func("InputName"): Sets the input function (e.g., "Phono", "Tuner").

    After sending commands, call await d.async_update() to synchronize the local object state with the device.

    # Power control
    await d.async_power_on()
    await d.async_update()
    print(d.power) # 'ON'
    
    await d.async_power_off()
    await d.async_update()
    print(d.power) # 'OFF'
    
    # Input control
    await d.async_set_input_func("Phono")
    await d.async_update()
    print(d.input_func) # 'Phono'
  9. Configure DenonAVRTelnetApi parameters

    main

    When initializing DenonAVRTelnetApi, you can configure the following attributes:

    ParameterTypeDefaultDescription
    hoststr"localhost"The IP address or hostname of the receiver
    timeoutfloat2.0Connection timeout in seconds
    is_denonboolTrueSet to False for non-Denon compatible devices
    power_query_commandstr"ZM?"Command used to check power state
    _send_confirmation_timeoutfloat2.0How long to wait for command confirmation
  10. Configure DenonAVRApi parameters

    main

    When initializing DenonAVRApi, you can configure the following attributes:

    ParameterTypeDefaultDescription
    hoststr"localhost"The IP address or hostname of the receiver
    portint80The HTTP port
    timeoutfloat2.0Connection timeout in seconds
    read_timeoutfloat15.0Read timeout in seconds
    httpx_async_clientHTTPXAsyncClientHTTPXAsyncClient()Custom HTTPX client instance
  11. Update volume status asynchronously

    main

    To ensure the local state of the DenonAVRVolume object matches the actual state of the receiver, call async_update(). This method handles the underlying communication (AppCommand or Status XML) to refresh all volume-related attributes.

    • async_update(global_update: bool = False, cache_id: Optional[Hashable] = None): The primary method to refresh state.
    • async_update_volume(...): Specifically refreshes volume-related attributes.
    await volume.async_update()