denonavr 0.11.6__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- denonavr/__init__.py +1 -24
- denonavr/api.py +46 -35
- denonavr/audyssey.py +12 -7
- denonavr/const.py +168 -59
- denonavr/decorators.py +6 -46
- denonavr/denonavr.py +46 -186
- denonavr/foundation.py +120 -33
- denonavr/input.py +13 -6
- denonavr/soundmode.py +51 -36
- denonavr/tonecontrol.py +47 -12
- denonavr/volume.py +4 -2
- denonavr-1.0.0.dist-info/METADATA +158 -0
- denonavr-1.0.0.dist-info/RECORD +19 -0
- {denonavr-0.11.6.dist-info → denonavr-1.0.0.dist-info}/WHEEL +1 -1
- denonavr-0.11.6.dist-info/METADATA +0 -290
- denonavr-0.11.6.dist-info/RECORD +0 -19
- {denonavr-0.11.6.dist-info → denonavr-1.0.0.dist-info}/LICENSE +0 -0
- {denonavr-0.11.6.dist-info → denonavr-1.0.0.dist-info}/top_level.txt +0 -0
denonavr/tonecontrol.py
CHANGED
|
@@ -7,6 +7,7 @@ This module implements the handler for state of Denon AVR receivers.
|
|
|
7
7
|
:license: MIT, see LICENSE for more details.
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
+
import asyncio
|
|
10
11
|
import logging
|
|
11
12
|
import time
|
|
12
13
|
from collections.abc import Hashable
|
|
@@ -16,7 +17,7 @@ import attr
|
|
|
16
17
|
|
|
17
18
|
from .appcommand import AppCommandCmdParam, AppCommands
|
|
18
19
|
from .const import DENON_ATTR_SETATTR
|
|
19
|
-
from .exceptions import AvrCommandError, AvrProcessingError
|
|
20
|
+
from .exceptions import AvrCommandError, AvrIncompleteResponseError, AvrProcessingError
|
|
20
21
|
from .foundation import DenonAVRFoundation, convert_string_int_bool
|
|
21
22
|
|
|
22
23
|
_LOGGER = logging.getLogger(__name__)
|
|
@@ -26,6 +27,9 @@ _LOGGER = logging.getLogger(__name__)
|
|
|
26
27
|
class DenonAVRToneControl(DenonAVRFoundation):
|
|
27
28
|
"""This class implements tone control functions of Denon AVR receiver."""
|
|
28
29
|
|
|
30
|
+
_support_tone_control: Optional[bool] = attr.ib(
|
|
31
|
+
converter=attr.converters.optional(bool), default=None
|
|
32
|
+
)
|
|
29
33
|
_tone_control_status: Optional[bool] = attr.ib(
|
|
30
34
|
converter=attr.converters.optional(convert_string_int_bool), default=None
|
|
31
35
|
)
|
|
@@ -44,22 +48,31 @@ class DenonAVRToneControl(DenonAVRFoundation):
|
|
|
44
48
|
_treble_level: Optional[str] = attr.ib(
|
|
45
49
|
converter=attr.converters.optional(str), default=None
|
|
46
50
|
)
|
|
51
|
+
_setup_lock: asyncio.Lock = attr.ib(default=attr.Factory(asyncio.Lock))
|
|
47
52
|
|
|
48
53
|
# Update tags for attributes
|
|
49
54
|
# AppCommand.xml interface
|
|
50
55
|
appcommand_attrs = {AppCommands.GetToneControl: None}
|
|
51
56
|
|
|
52
|
-
def
|
|
57
|
+
async def async_setup(self) -> None:
|
|
53
58
|
"""Ensure that the instance is initialized."""
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
self._device.api.add_appcommand_update_tag(tag)
|
|
59
|
+
async with self._setup_lock:
|
|
60
|
+
_LOGGER.debug("Starting tone control setup")
|
|
57
61
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
)
|
|
62
|
+
# The first update determines if sound mode is supported
|
|
63
|
+
await self.async_update_tone_control()
|
|
61
64
|
|
|
62
|
-
|
|
65
|
+
# Add tags for a potential AppCommand.xml update
|
|
66
|
+
if self.support_tone_control:
|
|
67
|
+
for tag in self.appcommand_attrs:
|
|
68
|
+
self._device.api.add_appcommand_update_tag(tag)
|
|
69
|
+
|
|
70
|
+
self._device.telnet_api.register_callback(
|
|
71
|
+
"PS", self._async_sound_detail_callback
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
self._is_setup = True
|
|
75
|
+
_LOGGER.debug("Finished tone control setup")
|
|
63
76
|
|
|
64
77
|
async def _async_sound_detail_callback(
|
|
65
78
|
self, zone: str, event: str, parameter: str
|
|
@@ -85,14 +98,16 @@ class DenonAVRToneControl(DenonAVRFoundation):
|
|
|
85
98
|
self, global_update: bool = False, cache_id: Optional[Hashable] = None
|
|
86
99
|
) -> None:
|
|
87
100
|
"""Update volume asynchronously."""
|
|
101
|
+
_LOGGER.debug("Starting tone control update")
|
|
88
102
|
# Ensure instance is setup before updating
|
|
89
103
|
if not self._is_setup:
|
|
90
|
-
self.
|
|
104
|
+
await self.async_setup()
|
|
91
105
|
|
|
92
106
|
# Update state
|
|
93
107
|
await self.async_update_tone_control(
|
|
94
108
|
global_update=global_update, cache_id=cache_id
|
|
95
109
|
)
|
|
110
|
+
_LOGGER.debug("Finished tone control update")
|
|
96
111
|
|
|
97
112
|
async def async_update_tone_control(
|
|
98
113
|
self, global_update: bool = False, cache_id: Optional[Hashable] = None
|
|
@@ -103,14 +118,29 @@ class DenonAVRToneControl(DenonAVRFoundation):
|
|
|
103
118
|
"Device is not setup correctly, update method not set"
|
|
104
119
|
)
|
|
105
120
|
|
|
121
|
+
if self._is_setup and not self._support_tone_control:
|
|
122
|
+
return
|
|
123
|
+
|
|
106
124
|
# Tone control is only available for avr 2016 update
|
|
107
|
-
if self._device.use_avr_2016_update:
|
|
125
|
+
if not self._device.use_avr_2016_update:
|
|
126
|
+
self._support_tone_control = False
|
|
127
|
+
_LOGGER.info("Tone control not supported")
|
|
128
|
+
return
|
|
129
|
+
|
|
130
|
+
try:
|
|
108
131
|
await self.async_update_attrs_appcommand(
|
|
109
132
|
self.appcommand_attrs,
|
|
110
133
|
global_update=global_update,
|
|
111
134
|
cache_id=cache_id,
|
|
112
|
-
ignore_missing_response=True,
|
|
113
135
|
)
|
|
136
|
+
except (AvrProcessingError, AvrIncompleteResponseError):
|
|
137
|
+
self._support_tone_control = False
|
|
138
|
+
_LOGGER.info("Tone control not supported")
|
|
139
|
+
return
|
|
140
|
+
|
|
141
|
+
if not self._is_setup:
|
|
142
|
+
self._support_tone_control = True
|
|
143
|
+
_LOGGER.info("Tone control supported")
|
|
114
144
|
|
|
115
145
|
async def async_set_tone_control_command(
|
|
116
146
|
self, parameter_type: str, value: int
|
|
@@ -129,6 +159,11 @@ class DenonAVRToneControl(DenonAVRFoundation):
|
|
|
129
159
|
##############
|
|
130
160
|
# Properties #
|
|
131
161
|
##############
|
|
162
|
+
@property
|
|
163
|
+
def support_tone_control(self) -> Optional[bool]:
|
|
164
|
+
"""Return True if tone control is supported."""
|
|
165
|
+
return self._support_tone_control
|
|
166
|
+
|
|
132
167
|
@property
|
|
133
168
|
def tone_control_status(self) -> Optional[bool]:
|
|
134
169
|
"""Return value of tone control status."""
|
denonavr/volume.py
CHANGED
|
@@ -89,12 +89,14 @@ class DenonAVRVolume(DenonAVRFoundation):
|
|
|
89
89
|
self, global_update: bool = False, cache_id: Optional[Hashable] = None
|
|
90
90
|
) -> None:
|
|
91
91
|
"""Update volume asynchronously."""
|
|
92
|
+
_LOGGER.debug("Starting volume update")
|
|
92
93
|
# Ensure instance is setup before updating
|
|
93
94
|
if not self._is_setup:
|
|
94
95
|
self.setup()
|
|
95
96
|
|
|
96
97
|
# Update state
|
|
97
98
|
await self.async_update_volume(global_update=global_update, cache_id=cache_id)
|
|
99
|
+
_LOGGER.debug("Finished volume update")
|
|
98
100
|
|
|
99
101
|
async def async_update_volume(
|
|
100
102
|
self, global_update: bool = False, cache_id: Optional[Hashable] = None
|
|
@@ -146,7 +148,7 @@ class DenonAVRVolume(DenonAVRFoundation):
|
|
|
146
148
|
"""Volume up receiver via HTTP get command."""
|
|
147
149
|
if self._device.telnet_available:
|
|
148
150
|
await self._device.telnet_api.async_send_commands(
|
|
149
|
-
self._device.telnet_commands.command_volume_up
|
|
151
|
+
self._device.telnet_commands.command_volume_up, skip_confirmation=True
|
|
150
152
|
)
|
|
151
153
|
else:
|
|
152
154
|
await self._device.api.async_get_command(
|
|
@@ -157,7 +159,7 @@ class DenonAVRVolume(DenonAVRFoundation):
|
|
|
157
159
|
"""Volume down receiver via HTTP get command."""
|
|
158
160
|
if self._device.telnet_available:
|
|
159
161
|
await self._device.telnet_api.async_send_commands(
|
|
160
|
-
self._device.telnet_commands.command_volume_down
|
|
162
|
+
self._device.telnet_commands.command_volume_down, skip_confirmation=True
|
|
161
163
|
)
|
|
162
164
|
else:
|
|
163
165
|
await self._device.api.async_get_command(
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: denonavr
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Automation Library for Denon AVR receivers
|
|
5
|
+
Author-email: Oliver Goetz <scarface@mywoh.de>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/ol-iver/denonavr
|
|
8
|
+
Project-URL: Source, https://github.com/ol-iver/denonavr
|
|
9
|
+
Project-URL: Tracker, https://github.com/ol-iver/denonavr/issues
|
|
10
|
+
Platform: any
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
16
|
+
Classifier: Topic :: Home Automation
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Requires-Python: >=3.7
|
|
25
|
+
Description-Content-Type: text/markdown; charset=UTF-8
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: asyncstdlib >=3.10.2
|
|
28
|
+
Requires-Dist: attrs >=21.2.0
|
|
29
|
+
Requires-Dist: defusedxml >=0.7.1
|
|
30
|
+
Requires-Dist: ftfy >=6.1.1
|
|
31
|
+
Requires-Dist: httpx >=0.23.1
|
|
32
|
+
Requires-Dist: netifaces >=0.11.0
|
|
33
|
+
Requires-Dist: async-timeout >=4.0.2 ; python_version < "3.11"
|
|
34
|
+
Provides-Extra: testing
|
|
35
|
+
Requires-Dist: pydocstyle ; extra == 'testing'
|
|
36
|
+
Requires-Dist: pylint ; extra == 'testing'
|
|
37
|
+
Requires-Dist: pytest ; extra == 'testing'
|
|
38
|
+
Requires-Dist: pytest-cov ; extra == 'testing'
|
|
39
|
+
Requires-Dist: pytest-timeout ; extra == 'testing'
|
|
40
|
+
Requires-Dist: pytest-asyncio ; extra == 'testing'
|
|
41
|
+
Requires-Dist: pytest-httpx ; extra == 'testing'
|
|
42
|
+
Requires-Dist: flake8-docstrings ; extra == 'testing'
|
|
43
|
+
Requires-Dist: flake8 ; extra == 'testing'
|
|
44
|
+
|
|
45
|
+
# denonavr
|
|
46
|
+
[](https://github.com/ol-iver/denonavr/releases/latest)
|
|
47
|
+
[](https://github.com/ol-iver/denonavr/actions/workflows/python-tests.yml)
|
|
48
|
+
[](https://pypi.org/project/denonavr)
|
|
49
|
+
[](LICENSE)
|
|
50
|
+
[](https://github.com/psf/black)
|
|
51
|
+
|
|
52
|
+
Automation Library for Denon AVR receivers
|
|
53
|
+
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
Use pip:
|
|
57
|
+
|
|
58
|
+
```$ pip install denonavr```
|
|
59
|
+
|
|
60
|
+
or
|
|
61
|
+
|
|
62
|
+
```$ pip install --use-wheel denonavr```
|
|
63
|
+
|
|
64
|
+
## Usage with `async`
|
|
65
|
+
|
|
66
|
+
Writing `async` and `await` methods are outside the scope of the documentation. You can test `async` usage from the Python REPL. In a terminal run:
|
|
67
|
+
|
|
68
|
+
`python3 -m asyncio`
|
|
69
|
+
|
|
70
|
+
The `asyncio` library should automatically be imported in the REPL. Import the `denonavr` library and set up your receiver. If you know the IP address, enter it below replacing `192.168.1.119`.
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
>>> import asyncio
|
|
74
|
+
>>> import denonavr
|
|
75
|
+
>>> d = denonavr.DenonAVR("192.168.1.119")
|
|
76
|
+
>>> await d.async_setup()
|
|
77
|
+
>>> await d.async_update()
|
|
78
|
+
>>> print(d.volume)
|
|
79
|
+
-36.5
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Monitoring with telnet
|
|
83
|
+
In addition to retrieving the current device status via HTTP calls, `denonavr` library also has the ability to setup a task that will connect to the receiver via telnet on TCP port 23 and listen for real-time events to notify of status changes.
|
|
84
|
+
This provides instant updates via a callback when the device status changes. Receivers support only one active telnet connection.
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
>>> import asyncio
|
|
88
|
+
>>> import denonavr
|
|
89
|
+
>>> d = denonavr.DenonAVR("192.168.1.119")
|
|
90
|
+
>>> await d.async_setup()
|
|
91
|
+
>>> await d.async_telnet_connect()
|
|
92
|
+
>>> await d.async_update()
|
|
93
|
+
>>> async def update_callback(zone, event, parameter):
|
|
94
|
+
>>>>>> print("Zone: " + zone + " Event: " + event + " Parameter: " + parameter)
|
|
95
|
+
>>> d.register_callback("ALL", update_callback)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Power & Input
|
|
99
|
+
```
|
|
100
|
+
>>> await d.async_power_on()
|
|
101
|
+
>>> await d.async_update()
|
|
102
|
+
>>> d.power
|
|
103
|
+
'ON'
|
|
104
|
+
|
|
105
|
+
>>> await d.async_power_off()
|
|
106
|
+
>>> await d.async_update()
|
|
107
|
+
>>> d.power
|
|
108
|
+
'OFF'
|
|
109
|
+
|
|
110
|
+
>>> d.input_func
|
|
111
|
+
'Tuner'
|
|
112
|
+
>>> await d.async_set_input_func("Phono")
|
|
113
|
+
>>> d.input_func
|
|
114
|
+
'Phono'
|
|
115
|
+
```
|
|
116
|
+
### Sound
|
|
117
|
+
```
|
|
118
|
+
>>> await d.async_mute(True)
|
|
119
|
+
>>> await d.async_mute(False)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Other methods
|
|
123
|
+
|
|
124
|
+
Other `async` methods available include:
|
|
125
|
+
|
|
126
|
+
* `d.async_bass_down`
|
|
127
|
+
* `d.async_bass_up`
|
|
128
|
+
* `d.async_treble_down`
|
|
129
|
+
* `d.async_treble_up`
|
|
130
|
+
* `d.async_volume_down`
|
|
131
|
+
* `d.async_volume_up`
|
|
132
|
+
* `d.async_set_volume(50)`
|
|
133
|
+
|
|
134
|
+
## Collection of HTTP calls
|
|
135
|
+
For a collection of HTTP calls for Denon receivers please have a look at the `doc` folder.
|
|
136
|
+
|
|
137
|
+
## License
|
|
138
|
+
MIT
|
|
139
|
+
|
|
140
|
+
## Author
|
|
141
|
+
@ol-iver: https://github.com/ol-iver
|
|
142
|
+
|
|
143
|
+
## Contributors
|
|
144
|
+
@soldag: https://github.com/soldag
|
|
145
|
+
@shapiromatron: https://github.com/shapiromatron
|
|
146
|
+
@glance-: https://github.com/glance-
|
|
147
|
+
@p3dda: https://github.com/p3dda
|
|
148
|
+
@russel: https://github.com/russell
|
|
149
|
+
@starkillerOG: https://github.com/starkillerOG
|
|
150
|
+
@andrewsayre: https://github.com/andrewsayre
|
|
151
|
+
@JPHutchins: https://github.com/JPHutchins
|
|
152
|
+
@MarBra: https://github.com/MarBra
|
|
153
|
+
@dcmeglio: https://github.com/dcmeglio
|
|
154
|
+
@bdraco: https://github.com/bdraco
|
|
155
|
+
|
|
156
|
+
## Users
|
|
157
|
+
Home Assistant: https://github.com/home-assistant/home-assistant/
|
|
158
|
+
denonavr-cli: https://pypi.org/project/denonavr-cli/
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
denonavr/__init__.py,sha256=jkmT2PjmR9ncL4gwegkmN0UMpyA7a2OQn7nU9nbqbZk,1325
|
|
2
|
+
denonavr/api.py,sha256=IL8KMUj6_S_9sFC_DnlmYV0shjfI4lYu7HO3Yb-WjdE,29167
|
|
3
|
+
denonavr/appcommand.py,sha256=H37VK4n-yW0ISvR1hfX8G4udQtGASoY44QNaXtLSidE,7784
|
|
4
|
+
denonavr/audyssey.py,sha256=bHzgFRdUwLQozP2Or59jn6qfYU4WSQxiGKixBx7xxQo,11085
|
|
5
|
+
denonavr/const.py,sha256=lbM3hKYWUd8cto3BUqplKvDpX_uvCr8-7KWWoyohkNE,21464
|
|
6
|
+
denonavr/decorators.py,sha256=yBAMcY3bFJs5DJFZ-7Zvln4_jjcjrux6js4lJoOM59I,3755
|
|
7
|
+
denonavr/denonavr.py,sha256=BUseoHsI4J-ApawMWW_63b61Nn9TasTR0rENiijRW0w,24000
|
|
8
|
+
denonavr/exceptions.py,sha256=naP7MCuNH98rv7y_lDdO7ayyvQGywnsfpHhW-o9tKeo,1725
|
|
9
|
+
denonavr/foundation.py,sha256=fUpOgMO9mgKSq8VW00QSZy75H-mfiIrrKrxqfTiBgfI,31443
|
|
10
|
+
denonavr/input.py,sha256=R9bMCUQYSU02SL3U-uC2bYBKzMd9nVLjRjM4JRvONbo,41408
|
|
11
|
+
denonavr/soundmode.py,sha256=MKyBtSQ-1gtnNyT_qQhbGDlPQuNS3QzBurjUUWNPKeo,12464
|
|
12
|
+
denonavr/ssdp.py,sha256=4gyvN0yo9qSnJ7l6iJmSC_5qW45Fq2Tt2RACpxFMSqg,7839
|
|
13
|
+
denonavr/tonecontrol.py,sha256=DfHzziEeLdYiyTbJKcGk5cCPTvKBgjMqQReYp0qoF0U,12474
|
|
14
|
+
denonavr/volume.py,sha256=S3UeyassnErOSqiaS48Q4Vo9QHJTyG1jnyEDSRFOfdw,7341
|
|
15
|
+
denonavr-1.0.0.dist-info/LICENSE,sha256=hcKXAoZnRee1NRWnxTpKyjKCz4aHhw76sZUZoB3qPTw,1068
|
|
16
|
+
denonavr-1.0.0.dist-info/METADATA,sha256=QsdEw_wHlMK5pthVZU2wP7bJu9eToruOQQgWpYkGFOw,5250
|
|
17
|
+
denonavr-1.0.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
18
|
+
denonavr-1.0.0.dist-info/top_level.txt,sha256=GKwe6bOaw_R68BR7x-C7VD3bDFKKNBf0pRkWywUZWIs,9
|
|
19
|
+
denonavr-1.0.0.dist-info/RECORD,,
|
|
@@ -1,290 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: denonavr
|
|
3
|
-
Version: 0.11.6
|
|
4
|
-
Summary: Automation Library for Denon AVR receivers
|
|
5
|
-
Author-email: Oliver Goetz <scarface@mywoh.de>
|
|
6
|
-
License: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.com/ol-iver/denonavr
|
|
8
|
-
Project-URL: Source, https://github.com/ol-iver/denonavr
|
|
9
|
-
Project-URL: Tracker, https://github.com/ol-iver/denonavr/issues
|
|
10
|
-
Platform: any
|
|
11
|
-
Classifier: Development Status :: 4 - Beta
|
|
12
|
-
Classifier: Intended Audience :: Developers
|
|
13
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
-
Classifier: Operating System :: OS Independent
|
|
15
|
-
Classifier: Topic :: Software Development :: Libraries
|
|
16
|
-
Classifier: Topic :: Home Automation
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
-
Requires-Python: >=3.7
|
|
24
|
-
Description-Content-Type: text/markdown; charset=UTF-8
|
|
25
|
-
License-File: LICENSE
|
|
26
|
-
Requires-Dist: asyncstdlib >=3.10.2
|
|
27
|
-
Requires-Dist: attrs >=21.2.0
|
|
28
|
-
Requires-Dist: defusedxml >=0.7.1
|
|
29
|
-
Requires-Dist: ftfy >=6.1.1
|
|
30
|
-
Requires-Dist: httpx >=0.23.1
|
|
31
|
-
Requires-Dist: netifaces >=0.11.0
|
|
32
|
-
Requires-Dist: async-timeout >=4.0.2 ; python_version < "3.11"
|
|
33
|
-
Provides-Extra: testing
|
|
34
|
-
Requires-Dist: pydocstyle ; extra == 'testing'
|
|
35
|
-
Requires-Dist: pylint ; extra == 'testing'
|
|
36
|
-
Requires-Dist: pytest ; extra == 'testing'
|
|
37
|
-
Requires-Dist: pytest-cov ; extra == 'testing'
|
|
38
|
-
Requires-Dist: pytest-timeout ; extra == 'testing'
|
|
39
|
-
Requires-Dist: pytest-asyncio ; extra == 'testing'
|
|
40
|
-
Requires-Dist: pytest-httpx ; extra == 'testing'
|
|
41
|
-
Requires-Dist: flake8-docstrings ; extra == 'testing'
|
|
42
|
-
Requires-Dist: flake8 ; extra == 'testing'
|
|
43
|
-
|
|
44
|
-
# denonavr
|
|
45
|
-
[](https://github.com/ol-iver/denonavr/releases/latest)
|
|
46
|
-
[](https://github.com/ol-iver/denonavr/actions/workflows/python-tests.yml)
|
|
47
|
-
[](https://pypi.org/project/denonavr)
|
|
48
|
-
[](LICENSE)
|
|
49
|
-
[](https://github.com/psf/black)
|
|
50
|
-
|
|
51
|
-
Automation Library for Denon AVR receivers
|
|
52
|
-
|
|
53
|
-
### TCP monitoring
|
|
54
|
-
|
|
55
|
-
In 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.
|
|
56
|
-
|
|
57
|
-
## Important changes for version 0.10.0 and above
|
|
58
|
-
|
|
59
|
-
### async
|
|
60
|
-
|
|
61
|
-
As of version 0.10.0 and newer, the `denonavr` library has switched to using`async` methods to interact with Denon receivers.
|
|
62
|
-
|
|
63
|
-
Legacy synchronous methods are still available to avoid breaking existing implementations, but may be deprecated in the future. Switching to `async` methods is recommended. The existing sync methods are inefficient because they use the corresponding async methods by starting and stopping its own `asyncio` loop for each command.
|
|
64
|
-
|
|
65
|
-
### Other changes:
|
|
66
|
-
|
|
67
|
-
When creating a new instance of `DenonAVR` there 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 of `async_setup()` if the instance was not setup yet.
|
|
68
|
-
|
|
69
|
-
Methods do not return `True` or `False` anymore. If successful, `None` is returned. Otherwise an exception is raised from a class in [denonavr/exceptions.py](https://github.com/ol-iver/denonavr/blob/master/denonavr/exceptions.py).
|
|
70
|
-
|
|
71
|
-
It is no longer assumed that a command was successful even when the receiver returns an `HTTP 200 OK`. This is because the receiver can return an `HTTP 200 OK` from 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 the `power` attribute change.
|
|
72
|
-
|
|
73
|
-
## Installation
|
|
74
|
-
|
|
75
|
-
Use pip:
|
|
76
|
-
|
|
77
|
-
```$ pip install denonavr```
|
|
78
|
-
|
|
79
|
-
or
|
|
80
|
-
|
|
81
|
-
```$ pip install --use-wheel denonavr```
|
|
82
|
-
|
|
83
|
-
## Usage with `async`
|
|
84
|
-
|
|
85
|
-
Writing `async` and `await` methods are outside the scope of the documentation. You can test `async` usage from the Python REPL. In a terminal run:
|
|
86
|
-
|
|
87
|
-
`python3 -m asyncio`
|
|
88
|
-
|
|
89
|
-
The `asyncio` library should automatically be imported in the REPL. Import the `denonavr` library and set up your receiver. If you know the IP address, enter it below replacing `192.168.1.119`.
|
|
90
|
-
|
|
91
|
-
```
|
|
92
|
-
>>> import asyncio
|
|
93
|
-
>>> import denonavr
|
|
94
|
-
>>> d = denonavr.DenonAVR("192.168.1.119")
|
|
95
|
-
>>> await d.async_setup()
|
|
96
|
-
>>> await d.async_update()
|
|
97
|
-
>>> print(d.volume)
|
|
98
|
-
-36.5
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### Monitoring with TCP
|
|
102
|
-
```
|
|
103
|
-
>>> import asyncio
|
|
104
|
-
>>> import denonavr
|
|
105
|
-
>>> d = denonavr.DenonAVR("192.168.1.119")
|
|
106
|
-
>>> await d.async_setup()
|
|
107
|
-
>>> await d.async_telnet_connect()
|
|
108
|
-
>>> await d.async_update()
|
|
109
|
-
>>> async def update_callback(zone, event, parameter):
|
|
110
|
-
>>>>>> print("Zone: " + zone + " Event: " + event + " Parameter: " + parameter)
|
|
111
|
-
>>> d.register_callback("ALL", update_callback)
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### Power & Input
|
|
115
|
-
```
|
|
116
|
-
>>> await d.async_power_on()
|
|
117
|
-
>>> await d.async_update()
|
|
118
|
-
>>> d.power
|
|
119
|
-
'ON'
|
|
120
|
-
|
|
121
|
-
>>> await d.async_power_off()
|
|
122
|
-
>>> await d.async_update()
|
|
123
|
-
>>> d.power
|
|
124
|
-
'OFF'
|
|
125
|
-
|
|
126
|
-
>>> d.input_func
|
|
127
|
-
'Tuner'
|
|
128
|
-
>>> await d.async_set_input_func("Phono")
|
|
129
|
-
>>> d.input_func
|
|
130
|
-
'Phono'
|
|
131
|
-
```
|
|
132
|
-
### Sound
|
|
133
|
-
```
|
|
134
|
-
>>> await d.async_mute(True)
|
|
135
|
-
>>> await d.async_mute(False)
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### Other methods
|
|
139
|
-
|
|
140
|
-
Other `async` methods available include:
|
|
141
|
-
|
|
142
|
-
* `d.async_bass_down`
|
|
143
|
-
* `d.async_bass_up`
|
|
144
|
-
* `d.async_treble_down`
|
|
145
|
-
* `d.async_treble_up`
|
|
146
|
-
* `d.async_volume_down`
|
|
147
|
-
* `d.async_volume_up`
|
|
148
|
-
* `d.async_set_volume(50)`
|
|
149
|
-
|
|
150
|
-
## Legacy Usage
|
|
151
|
-
|
|
152
|
-
Note: Legacy sync methods are still available, but may be deprecated in the future. It is recommended to use the `async` methods 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.
|
|
153
|
-
|
|
154
|
-
For creation of a device you could use the following lines of codes
|
|
155
|
-
```
|
|
156
|
-
import denonavr
|
|
157
|
-
d = denonavr.DenonAVR("192.168.0.250", "Name of device (Optional)")
|
|
158
|
-
```
|
|
159
|
-
Library is not polling the Denon device. Thus you need to update device information using the update method.
|
|
160
|
-
```
|
|
161
|
-
d.update()
|
|
162
|
-
```
|
|
163
|
-
Some basic automatic discovery functions for uPnP devices using SSDP broadcast are available.
|
|
164
|
-
It is either possible to just discover the Denon AVR devices in the LAN zone or to create instances for each discovered device directly.
|
|
165
|
-
```
|
|
166
|
-
discovered_devices = denonavr.discover()
|
|
167
|
-
instanced_devices = denonavr.init_all_receivers()
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
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.
|
|
171
|
-
```
|
|
172
|
-
import denonavr
|
|
173
|
-
zones = {"Zone2": "Name of Zone2", "Zone3": "Name of Zone 3"}
|
|
174
|
-
d = denonavr.DenonAVR("192.168.0.250", name="Name of Main Zone", add_zones=zones)
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
Each Zone is represented by an own instance which is assigned to the device instance by the zones attribute with type dictionary.
|
|
178
|
-
```
|
|
179
|
-
d.zones
|
|
180
|
-
{'Zone2': <denonavr.denonavr.DenonAVRZones object at 0x000001F893EB7630>, 'Main': <denonavr.denonavr.DenonAVR object at 0x000001F8964155F8>, 'Zone3': <denonavr.denonavr.DenonAVRZones object at 0x000001F896415320>}
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
Some code examples for the Main Zone:
|
|
184
|
-
```
|
|
185
|
-
>>> import denonavr
|
|
186
|
-
>>> d = denonavr.DenonAVR("192.168.0.250")
|
|
187
|
-
>>> d.update()
|
|
188
|
-
>>> d.power
|
|
189
|
-
'STANDBY'
|
|
190
|
-
>>> d.power_on()
|
|
191
|
-
>>> d.update()
|
|
192
|
-
>>> d.power
|
|
193
|
-
'ON'
|
|
194
|
-
>>> d.name
|
|
195
|
-
'Denon AVR-X4100W'
|
|
196
|
-
>>> d.artist
|
|
197
|
-
'Wynton Marsalis'
|
|
198
|
-
>>> d.title
|
|
199
|
-
"When It's Sleepytime Down South"
|
|
200
|
-
>>> d.image_url
|
|
201
|
-
'http://192.168.0.250/NetAudio/art.asp-jpg?1480031583'
|
|
202
|
-
>>> d.next_track()
|
|
203
|
-
>>> d.previous_track()
|
|
204
|
-
>>> d.volume
|
|
205
|
-
-43.5
|
|
206
|
-
>>> d.volume_up()
|
|
207
|
-
>>> d.update()
|
|
208
|
-
>>> d.volume
|
|
209
|
-
-43.0
|
|
210
|
-
>>> d.volume_down()
|
|
211
|
-
>>> d.set_volume(-40.0)
|
|
212
|
-
>>> d.update()
|
|
213
|
-
>>> d.volume
|
|
214
|
-
-40.0
|
|
215
|
-
>>> d.mute(True)
|
|
216
|
-
>>> d.mute(False)
|
|
217
|
-
>>> d.toggle_play_pause()
|
|
218
|
-
>>> d.toggle_play_pause()
|
|
219
|
-
>>> d.input_func
|
|
220
|
-
'Online Music'
|
|
221
|
-
>>> d.input_func_list
|
|
222
|
-
['AUX', 'AUX2', 'Blu-ray', 'Bluetooth', 'CBL/SAT', 'CD', 'DVD', 'Game', 'Internet Radio', 'Media Player', 'Media Server', 'Online Music', 'Phono', 'TV Audio', 'Tuner', 'iPod/USB']
|
|
223
|
-
>>> d.set_input_func("Tuner")
|
|
224
|
-
>>> d.update()
|
|
225
|
-
>>> d.input_func
|
|
226
|
-
'Tuner'
|
|
227
|
-
>>> d.power_off()
|
|
228
|
-
|
|
229
|
-
>>> discovered_devices = denonavr.discover()
|
|
230
|
-
discovered_devices
|
|
231
|
-
[{'friendlyName': 'Denon AVR-X4100W', 'host': '192.168.0.250', 'modelName': '*AVR-X4100W', 'presentationURL': 'http://192.168.0.250'}]
|
|
232
|
-
>>> discovered_denon = denonavr.DenonAVR(discovered_devices[0]['host'])
|
|
233
|
-
>>> discovered_denon.power
|
|
234
|
-
'STANDBY'
|
|
235
|
-
|
|
236
|
-
>>> instanced_devices = denonavr.init_all_receivers()
|
|
237
|
-
>>> instanced_devices
|
|
238
|
-
[<denonavr.denonavr.DenonAVR object at 0x000001AF8EA63E10>]
|
|
239
|
-
>>> instanced_devices[0].update()
|
|
240
|
-
>>> instanced_devices[0].power
|
|
241
|
-
'STANDBY'
|
|
242
|
-
>>> instanced_devices[0].power_on()
|
|
243
|
-
>>> instanced_devices[0].update()
|
|
244
|
-
>>> instanced_devices[0].power
|
|
245
|
-
'ON'
|
|
246
|
-
>>> instanced_devices[0].power_off()
|
|
247
|
-
>>> instanced_devices[0].update()
|
|
248
|
-
>>> instanced_devices[0].power
|
|
249
|
-
'STANDBY'
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
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.
|
|
253
|
-
```
|
|
254
|
-
d.zones['Zone2'].power
|
|
255
|
-
'OFF'
|
|
256
|
-
d.zones['Zone2'].power_on()
|
|
257
|
-
d.zones['Zone2'].update()
|
|
258
|
-
d.zones['Zone2'].power
|
|
259
|
-
'ON'
|
|
260
|
-
d.zones['Zone2'].power_off()
|
|
261
|
-
d.zones['Zone2'].update()
|
|
262
|
-
d.zones['Zone2'].power
|
|
263
|
-
'OFF
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
## Collection of HTTP calls
|
|
267
|
-
For a collection of HTTP calls for Denon receivers please have a look at the `doc` folder.
|
|
268
|
-
|
|
269
|
-
## License
|
|
270
|
-
MIT
|
|
271
|
-
|
|
272
|
-
## Author
|
|
273
|
-
@ol-iver: https://github.com/ol-iver
|
|
274
|
-
|
|
275
|
-
## Contributors
|
|
276
|
-
@soldag: https://github.com/soldag
|
|
277
|
-
@shapiromatron: https://github.com/shapiromatron
|
|
278
|
-
@glance-: https://github.com/glance-
|
|
279
|
-
@p3dda: https://github.com/p3dda
|
|
280
|
-
@russel: https://github.com/russell
|
|
281
|
-
@starkillerOG: https://github.com/starkillerOG
|
|
282
|
-
@andrewsayre: https://github.com/andrewsayre
|
|
283
|
-
@JPHutchins: https://github.com/JPHutchins
|
|
284
|
-
@MarBra: https://github.com/MarBra
|
|
285
|
-
@dcmeglio: https://github.com/dcmeglio
|
|
286
|
-
@bdraco: https://github.com/bdraco
|
|
287
|
-
|
|
288
|
-
## Users
|
|
289
|
-
Home Assistant: https://github.com/home-assistant/home-assistant/
|
|
290
|
-
denonavr-cli: https://pypi.org/project/denonavr-cli/
|
denonavr-0.11.6.dist-info/RECORD
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
denonavr/__init__.py,sha256=-divkN4DxZpILQgRgqab1PE7GszFDjdkCdy7aCI63nw,2035
|
|
2
|
-
denonavr/api.py,sha256=8s_TXeUidCDh4wzgbibOaJjZ1Nba5pcbGmKyLhL1m9s,28671
|
|
3
|
-
denonavr/appcommand.py,sha256=H37VK4n-yW0ISvR1hfX8G4udQtGASoY44QNaXtLSidE,7784
|
|
4
|
-
denonavr/audyssey.py,sha256=tbfOerXxjv6l3TAJ4zMBn08UPNqx-tVJEpDhwyYZ3iw,10797
|
|
5
|
-
denonavr/const.py,sha256=7jXrdTrqSrRJsYf_twqersNtdGx6odiMSsCajIHfsPA,17458
|
|
6
|
-
denonavr/decorators.py,sha256=j1Icyfw64LPLD67H2yd9nbREbTvicqG-kAxawfgvXuE,5062
|
|
7
|
-
denonavr/denonavr.py,sha256=hnsYJiVSXD9qaYr6mjlwkQL3I8NrbXXfAo8uWT35HBU,28159
|
|
8
|
-
denonavr/exceptions.py,sha256=naP7MCuNH98rv7y_lDdO7ayyvQGywnsfpHhW-o9tKeo,1725
|
|
9
|
-
denonavr/foundation.py,sha256=lCPxcbpbjbUCSNquNjaW5RXHQXdSR7Q0O8og2hcPXOY,27911
|
|
10
|
-
denonavr/input.py,sha256=kkswPrMiys1Qq7YWfwrveB-w2aaTgXAkkBa05rolbOA,41085
|
|
11
|
-
denonavr/soundmode.py,sha256=G36Nmf6lTe8Ku6sQ-2nDYHjmSjrnNr9l4wq3-B45I1g,11737
|
|
12
|
-
denonavr/ssdp.py,sha256=4gyvN0yo9qSnJ7l6iJmSC_5qW45Fq2Tt2RACpxFMSqg,7839
|
|
13
|
-
denonavr/tonecontrol.py,sha256=jg3d_OnnXKR5mq7S3mtKHyYhg7Y_qmDloqIm7WRJ71U,11093
|
|
14
|
-
denonavr/volume.py,sha256=bGEOyeNGaI4X-7C7hjEBBH4RlFCYngf4Dl2IM8ooxOo,7197
|
|
15
|
-
denonavr-0.11.6.dist-info/LICENSE,sha256=hcKXAoZnRee1NRWnxTpKyjKCz4aHhw76sZUZoB3qPTw,1068
|
|
16
|
-
denonavr-0.11.6.dist-info/METADATA,sha256=0He0qq32YZidhfW5a5K0NjPhojr5Ul1Q5zXip2SeCDs,10361
|
|
17
|
-
denonavr-0.11.6.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
18
|
-
denonavr-0.11.6.dist-info/top_level.txt,sha256=GKwe6bOaw_R68BR7x-C7VD3bDFKKNBf0pRkWywUZWIs,9
|
|
19
|
-
denonavr-0.11.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|