Package: denonavr
denonavrAutomation Library for Denon AVR receiversTCP monitoringIn addition to retrieving the current device status via HTTP calls, this version also adds the ability to setup a task that will connect to the receiver on TCP port 23 and listen for real-time events to notify of status changes. This provides instant updates via a callback when the device status changes.Important changes for version 0.10.0 and aboveasyncAs of version 0.10.0 and newer, thedenonavrlibrary has switched to usingasyncmethods to interact with Denon receivers.Legacy synchronous methods are still available to avoid breaking existing implementations, but may be deprecated in the future.  Switching toasyncmethods is recommended.  The existing sync methods are inefficient because they use the corresponding async methods by starting and stopping its ownasyncioloop for each command.Other changes:When creating a new instance ofDenonAVRthere are no longer any API calls to avoid blocking the event loop. To initialize setup of your receiver you would use(async_)setup()and(async_)update()methods to populate the attributes. Calling(async_)update()invokes a call ofasync_setup()if the instance was not setup yet.Methods do not returnTrueorFalseanymore. If successful,Noneis returned. Otherwise an exception is raised from a class indenonavr/exceptions.py.It is no longer assumed that a command was successful even when the receiver returns anHTTP 200 OK. This is because the receiver can return anHTTP 200 OKfrom some endpoints even when the API call has failed. As an example, you now have to call(async_)update()after you call(async_)power_off()to see thepowerattribute change.InstallationUse pip:$ pip install denonavror$ pip install --use-wheel denonavrUsage withasyncWritingasyncandawaitmethods are outside the scope of the documentation.  You can testasyncusage from the Python REPL.  In a terminal run:python3 -m asyncioTheasynciolibrary should automatically be imported in the REPL.  Import thedenonavrlibrary and set up your receiver.  If you know the  IP address, enter it below replacing192.168.1.119.>>> import asyncio
>>> import denonavr
>>> d = denonavr.DenonAVR("192.168.1.119")
>>> await d.async_setup()
>>> await d.async_update()
>>> print(d.volume)
-36.5Monitoring with TCP>>> import asyncio
>>> import denonavr
>>> d = denonavr.DenonAVR("192.168.1.119")
>>> await d.async_setup()
>>> await d.async_telnet_connect()
>>> await d.async_update()
>>> async def update_callback(zone, event, parameter):
>>>>>> print("Zone: " + zone + " Event: " + event + " Parameter: " + parameter)
>>> d.register_callback("ALL", update_callback)Power & Input>>> await d.async_power_on()
>>> await d.async_update()
>>> d.power
'ON'

>>> await d.async_power_off()
>>> await d.async_update()
>>> d.power
'OFF'

>>> d.input_func
'Tuner'
>>> await d.async_set_input_func("Phono")
>>> d.input_func
'Phono'Sound>>> await d.async_mute(True)
>>> await d.async_mute(False)Other methodsOtherasyncmethods available include:d.async_bass_downd.async_bass_upd.async_treble_downd.async_treble_upd.async_volume_downd.async_volume_upd.async_set_volume(50)Legacy UsageNote: Legacy sync methods are still available, but may be deprecated in the future.  It is recommended to use theasyncmethods described above.  The existing sync methods in versions 0.9.10 and below are inefficient as they use the corresponding async methods by starting and stopping its own asyncio loop for each command.For creation of a device you could use the following lines of codesimport denonavr
d = denonavr.DenonAVR("192.168.0.250", "Name of device (Optional)")Library is not polling the Denon device. Thus you need to update device information using the update method.d.update()Some basic automatic discovery functions for uPnP devices using SSDP broadcast are available.
It is either possible to just discover the Denon AVR devices in the LAN zone or to create instances for each discovered device directly.discovered_devices = denonavr.discover()
instanced_devices = denonavr.init_all_receivers()In addition to the Main Zone which is always started, Zone2 and Zone3 of the receiver can be started assigning a dictionary to the add_zones parameter when creating the instance of the receiver.import denonavr
zones = {"Zone2": "Name of Zone2", "Zone3": "Name of Zone 3"}
d = denonavr.DenonAVR("192.168.0.250", name="Name of Main Zone", add_zones=zones)Each Zone is represented by an own instance which is assigned to the device instance by the zones attribute with type dictionary.d.zones
{'Zone2': <denonavr.denonavr.DenonAVRZones object at 0x000001F893EB7630>, 'Main': <denonavr.denonavr.DenonAVR object at 0x000001F8964155F8>, 'Zone3': <denonavr.denonavr.DenonAVRZones object at 0x000001F896415320>}Some code examples for the Main Zone:>>> import denonavr
>>> d = denonavr.DenonAVR("192.168.0.250")
>>> d.update()
>>> d.power
'STANDBY'
>>> d.power_on()
>>> d.update()
>>> d.power
'ON'
>>> d.name
'Denon AVR-X4100W'
>>> d.artist
'Wynton Marsalis'
>>> d.title
"When It's Sleepytime Down South"
>>> d.image_url
'http://192.168.0.250/NetAudio/art.asp-jpg?1480031583'
>>> d.next_track()
>>> d.previous_track()
>>> d.volume
-43.5
>>> d.volume_up()
>>> d.update()
>>> d.volume
-43.0
>>> d.volume_down()
>>> d.set_volume(-40.0)
>>> d.update()
>>> d.volume
-40.0
>>> d.mute(True)
>>> d.mute(False)
>>> d.toggle_play_pause()
>>> d.toggle_play_pause()
>>> d.input_func
'Online Music'
>>> d.input_func_list
['AUX', 'AUX2', 'Blu-ray', 'Bluetooth', 'CBL/SAT', 'CD', 'DVD', 'Game', 'Internet Radio', 'Media Player', 'Media Server', 'Online Music', 'Phono', 'TV Audio', 'Tuner', 'iPod/USB']
>>> d.set_input_func("Tuner")
>>> d.update()
>>> d.input_func
'Tuner'
>>> d.power_off()

>>> discovered_devices = denonavr.discover()
discovered_devices
[{'friendlyName': 'Denon AVR-X4100W', 'host': '192.168.0.250', 'modelName': '*AVR-X4100W', 'presentationURL': 'http://192.168.0.250'}]
>>> discovered_denon = denonavr.DenonAVR(discovered_devices[0]['host'])
>>> discovered_denon.power
'STANDBY'

>>> instanced_devices = denonavr.init_all_receivers()
>>> instanced_devices
[<denonavr.denonavr.DenonAVR object at 0x000001AF8EA63E10>]
>>> instanced_devices[0].update()
>>> instanced_devices[0].power
'STANDBY'
>>> instanced_devices[0].power_on()
>>> instanced_devices[0].update()
>>> instanced_devices[0].power
'ON'
>>> instanced_devices[0].power_off()
>>> instanced_devices[0].update()
>>> instanced_devices[0].power
'STANDBY'The code examples for the Main Zone instance d from above are working for all zones. The other zones (and Main Zone as well) could be accessed via zones attribute.d.zones['Zone2'].power
'OFF'
d.zones['Zone2'].power_on()
d.zones['Zone2'].update()
d.zones['Zone2'].power
'ON'
d.zones['Zone2'].power_off()
d.zones['Zone2'].update()
d.zones['Zone2'].power
'OFFCollection of HTTP callsFor a collection of HTTP calls for Denon receivers please have a look at thedocfolder.LicenseMITAuthor@ol-iver:https://github.com/ol-iverContributors@soldag:https://github.com/soldag@shapiromatron:https://github.com/shapiromatron@glance-:https://github.com/glance-@p3dda:https://github.com/p3dda@russel:https://github.com/russell@starkillerOG:https://github.com/starkillerOG@andrewsayre:https://github.com/andrewsayre@JPHutchins:https://github.com/JPHutchins@MarBra:https://github.com/MarBra@dcmeglio:https://github.com/dcmeglio@bdraco:https://github.com/bdracoUsersHome Assistant:https://github.com/home-assistant/home-assistant/denonavr-cli:https://pypi.org/project/denonavr-cli/