denonavr 1.1.2__py3-none-any.whl → 1.2.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 -1
- denonavr/api.py +145 -112
- denonavr/audyssey.py +2 -6
- denonavr/const.py +109 -0
- denonavr/denonavr.py +64 -5
- denonavr/dirac.py +2 -6
- denonavr/foundation.py +221 -85
- denonavr/input.py +56 -48
- denonavr/soundmode.py +126 -42
- denonavr/ssdp.py +12 -11
- denonavr/tonecontrol.py +2 -6
- denonavr/volume.py +14 -30
- {denonavr-1.1.2.dist-info → denonavr-1.2.0.dist-info}/METADATA +2 -1
- denonavr-1.2.0.dist-info/RECORD +20 -0
- denonavr-1.1.2.dist-info/RECORD +0 -20
- {denonavr-1.1.2.dist-info → denonavr-1.2.0.dist-info}/WHEEL +0 -0
- {denonavr-1.1.2.dist-info → denonavr-1.2.0.dist-info}/licenses/LICENSE +0 -0
- {denonavr-1.1.2.dist-info → denonavr-1.2.0.dist-info}/top_level.txt +0 -0
denonavr/denonavr.py
CHANGED
|
@@ -10,7 +10,7 @@ This module implements the interface to Denon AVR receivers.
|
|
|
10
10
|
import asyncio
|
|
11
11
|
import logging
|
|
12
12
|
import time
|
|
13
|
-
from typing import
|
|
13
|
+
from typing import Callable, Dict, List, Literal, Optional, Union
|
|
14
14
|
|
|
15
15
|
import attr
|
|
16
16
|
import httpx
|
|
@@ -27,6 +27,7 @@ from .const import (
|
|
|
27
27
|
EcoModes,
|
|
28
28
|
HDMIAudioDecodes,
|
|
29
29
|
HDMIOutputs,
|
|
30
|
+
Illuminations,
|
|
30
31
|
PanelLocks,
|
|
31
32
|
RoomSizes,
|
|
32
33
|
TransducerLPFs,
|
|
@@ -232,14 +233,12 @@ class DenonAVR(DenonAVRFoundation):
|
|
|
232
233
|
"""Send telnet commands to the receiver."""
|
|
233
234
|
self._device.telnet_api.send_commands(*commands)
|
|
234
235
|
|
|
235
|
-
def register_callback(
|
|
236
|
-
self, event: str, callback: Callable[[str, str, str], Awaitable[None]]
|
|
237
|
-
):
|
|
236
|
+
def register_callback(self, event: str, callback: Callable[[str, str, str], None]):
|
|
238
237
|
"""Register a callback for telnet events."""
|
|
239
238
|
self._device.telnet_api.register_callback(event, callback=callback)
|
|
240
239
|
|
|
241
240
|
def unregister_callback(
|
|
242
|
-
self, event: str, callback: Callable[[str, str, str],
|
|
241
|
+
self, event: str, callback: Callable[[str, str, str], None]
|
|
243
242
|
):
|
|
244
243
|
"""Unregister a callback for telnet events."""
|
|
245
244
|
self._device.telnet_api.unregister_callback(event, callback=callback)
|
|
@@ -738,6 +737,26 @@ class DenonAVR(DenonAVRFoundation):
|
|
|
738
737
|
"""
|
|
739
738
|
return self._device.headphone_eq
|
|
740
739
|
|
|
740
|
+
@property
|
|
741
|
+
def illumination(self) -> Optional[str]:
|
|
742
|
+
"""
|
|
743
|
+
Return the illumination status for the device.
|
|
744
|
+
|
|
745
|
+
Only available on Marantz devices and when using Telnet.
|
|
746
|
+
|
|
747
|
+
Possible values are: "Auto", "Bright", "Dim", "Dark", "Off"
|
|
748
|
+
"""
|
|
749
|
+
return self.illumination
|
|
750
|
+
|
|
751
|
+
@property
|
|
752
|
+
def auto_lip_sync(self) -> Optional[bool]:
|
|
753
|
+
"""
|
|
754
|
+
Return the auto lip sync status for the device.
|
|
755
|
+
|
|
756
|
+
Only available on Marantz devices and when using Telnet.
|
|
757
|
+
"""
|
|
758
|
+
return self.auto_lip_sync
|
|
759
|
+
|
|
741
760
|
##########
|
|
742
761
|
# Getter #
|
|
743
762
|
##########
|
|
@@ -1210,3 +1229,43 @@ class DenonAVR(DenonAVRFoundation):
|
|
|
1210
1229
|
:param quick_select_number: Quick select number to set. Valid values are 1-5.
|
|
1211
1230
|
"""
|
|
1212
1231
|
await self._device.async_quick_select_memory(quick_select_number)
|
|
1232
|
+
|
|
1233
|
+
async def async_hdmi_cec_on(self) -> None:
|
|
1234
|
+
"""Turn on HDMI CEC on receiver via HTTP get command."""
|
|
1235
|
+
await self._device.async_hdmi_cec_on()
|
|
1236
|
+
|
|
1237
|
+
async def async_hdmi_cec_off(self) -> None:
|
|
1238
|
+
"""Turn off HDMI CEC on receiver via HTTP get command."""
|
|
1239
|
+
await self._device.async_hdmi_cec_off()
|
|
1240
|
+
|
|
1241
|
+
async def async_illumination(self, mode: Illuminations):
|
|
1242
|
+
"""
|
|
1243
|
+
Set illumination mode on receiver via HTTP get command.
|
|
1244
|
+
|
|
1245
|
+
Only available for Marantz devices.
|
|
1246
|
+
"""
|
|
1247
|
+
await self._device.async_illumination(mode)
|
|
1248
|
+
|
|
1249
|
+
async def async_auto_lip_sync_on(self) -> None:
|
|
1250
|
+
"""
|
|
1251
|
+
Turn on auto lip sync on receiver via HTTP get command.
|
|
1252
|
+
|
|
1253
|
+
Only available on Marantz devices.
|
|
1254
|
+
"""
|
|
1255
|
+
await self._device.async_auto_lip_sync_on()
|
|
1256
|
+
|
|
1257
|
+
async def async_auto_lip_sync_off(self) -> None:
|
|
1258
|
+
"""
|
|
1259
|
+
Turn off auto lip sync on receiver via HTTP get command.
|
|
1260
|
+
|
|
1261
|
+
Only available on Marantz devices.
|
|
1262
|
+
"""
|
|
1263
|
+
await self._device.async_auto_lip_sync_off()
|
|
1264
|
+
|
|
1265
|
+
async def async_auto_lip_sync_toggle(self) -> None:
|
|
1266
|
+
"""
|
|
1267
|
+
Toggle auto lip sync on receiver via HTTP get command.
|
|
1268
|
+
|
|
1269
|
+
Only available on Marantz devices and when using Telnet.
|
|
1270
|
+
"""
|
|
1271
|
+
await self._device.async_auto_lip_sync_toggle()
|
denonavr/dirac.py
CHANGED
|
@@ -35,14 +35,10 @@ class DenonAVRDirac(DenonAVRFoundation):
|
|
|
35
35
|
|
|
36
36
|
def setup(self) -> None:
|
|
37
37
|
"""Ensure that the instance is initialized."""
|
|
38
|
-
self._device.telnet_api.register_callback(
|
|
39
|
-
"PS", self._async_dirac_filter_callback
|
|
40
|
-
)
|
|
38
|
+
self._device.telnet_api.register_callback("PS", self._dirac_filter_callback)
|
|
41
39
|
self._is_setup = True
|
|
42
40
|
|
|
43
|
-
|
|
44
|
-
self, zone: str, event: str, parameter: str
|
|
45
|
-
) -> None:
|
|
41
|
+
def _dirac_filter_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
46
42
|
"""Handle Dirac filter change event."""
|
|
47
43
|
if event == "PS" and parameter[0:5] == "DIRAC":
|
|
48
44
|
self._dirac_filter = DIRAC_FILTER_MAP_LABELS[parameter[6:]]
|
denonavr/foundation.py
CHANGED
|
@@ -41,6 +41,8 @@ from .const import (
|
|
|
41
41
|
ECO_MODE_MAP_LABELS,
|
|
42
42
|
HDMI_OUTPUT_MAP,
|
|
43
43
|
HDMI_OUTPUT_MAP_LABELS,
|
|
44
|
+
ILLUMINATION_MAP,
|
|
45
|
+
ILLUMINATION_MAP_LABELS,
|
|
44
46
|
MAIN_ZONE,
|
|
45
47
|
POWER_STATES,
|
|
46
48
|
SETTINGS_MENU_STATES,
|
|
@@ -61,6 +63,7 @@ from .const import (
|
|
|
61
63
|
EcoModes,
|
|
62
64
|
HDMIAudioDecodes,
|
|
63
65
|
HDMIOutputs,
|
|
66
|
+
Illuminations,
|
|
64
67
|
PanelLocks,
|
|
65
68
|
ReceiverType,
|
|
66
69
|
ReceiverURLs,
|
|
@@ -220,6 +223,13 @@ class DenonAVRDeviceInfo:
|
|
|
220
223
|
_headphone_eq: Optional[bool] = attr.ib(
|
|
221
224
|
converter=attr.converters.optional(convert_on_off_bool), default=None
|
|
222
225
|
)
|
|
226
|
+
_illumination: Optional[str] = attr.ib(
|
|
227
|
+
converter=attr.converters.optional(str), default=None
|
|
228
|
+
)
|
|
229
|
+
_illuminations = get_args(Illuminations)
|
|
230
|
+
_auto_lip_sync: Optional[bool] = attr.ib(
|
|
231
|
+
converter=attr.converters.optional(convert_on_off_bool), default=None
|
|
232
|
+
)
|
|
223
233
|
_is_setup: bool = attr.ib(converter=bool, default=False, init=False)
|
|
224
234
|
_allow_recovery: bool = attr.ib(converter=bool, default=True, init=True)
|
|
225
235
|
_setup_lock: asyncio.Lock = attr.ib(default=attr.Factory(asyncio.Lock))
|
|
@@ -239,16 +249,12 @@ class DenonAVRDeviceInfo:
|
|
|
239
249
|
else:
|
|
240
250
|
raise ValueError(f"Invalid zone {self.zone}")
|
|
241
251
|
|
|
242
|
-
|
|
243
|
-
self, zone: str, event: str, parameter: str
|
|
244
|
-
) -> None:
|
|
252
|
+
def _power_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
245
253
|
"""Handle a power change event."""
|
|
246
254
|
if self.zone == zone and parameter in POWER_STATES:
|
|
247
255
|
self._power = parameter
|
|
248
256
|
|
|
249
|
-
|
|
250
|
-
self, zone: str, event: str, parameter: str
|
|
251
|
-
) -> None:
|
|
257
|
+
def _settings_menu_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
252
258
|
"""Handle a settings menu event."""
|
|
253
259
|
if (
|
|
254
260
|
event == "MN"
|
|
@@ -257,23 +263,17 @@ class DenonAVRDeviceInfo:
|
|
|
257
263
|
):
|
|
258
264
|
self._settings_menu = parameter[4:]
|
|
259
265
|
|
|
260
|
-
|
|
261
|
-
self, zone: str, event: str, parameter: str
|
|
262
|
-
) -> None:
|
|
266
|
+
def _dimmer_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
263
267
|
"""Handle a dimmer change event."""
|
|
264
268
|
if event == "DIM" and parameter[1:] in DIMMER_MODE_MAP_LABELS:
|
|
265
269
|
self._dimmer = DIMMER_MODE_MAP_LABELS[parameter[1:]]
|
|
266
270
|
|
|
267
|
-
|
|
268
|
-
self, zone: str, event: str, parameter: str
|
|
269
|
-
) -> None:
|
|
271
|
+
def _auto_standby_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
270
272
|
"""Handle a auto standby change event."""
|
|
271
273
|
if zone == "Main" and event == "STBY":
|
|
272
274
|
self._auto_standby = parameter
|
|
273
275
|
|
|
274
|
-
|
|
275
|
-
self, zone: str, event: str, parameter: str
|
|
276
|
-
) -> None:
|
|
276
|
+
def _auto_sleep_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
277
277
|
"""Handle a sleep change event."""
|
|
278
278
|
if event != "SLP":
|
|
279
279
|
return
|
|
@@ -283,18 +283,14 @@ class DenonAVRDeviceInfo:
|
|
|
283
283
|
else:
|
|
284
284
|
self._sleep = int(parameter)
|
|
285
285
|
|
|
286
|
-
|
|
287
|
-
self, zone: str, event: str, parameter: str
|
|
288
|
-
) -> None:
|
|
286
|
+
def _room_size_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
289
287
|
"""Handle a room size change event."""
|
|
290
288
|
if parameter[:3] != "RSZ":
|
|
291
289
|
return
|
|
292
290
|
|
|
293
291
|
self._room_size = parameter[4:]
|
|
294
292
|
|
|
295
|
-
|
|
296
|
-
self, zone: str, event: str, parameter: str
|
|
297
|
-
) -> None:
|
|
293
|
+
def _trigger_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
298
294
|
"""Handle a trigger change event."""
|
|
299
295
|
if event != "TR":
|
|
300
296
|
return
|
|
@@ -308,35 +304,29 @@ class DenonAVRDeviceInfo:
|
|
|
308
304
|
|
|
309
305
|
self._triggers[int(values[0])] = values[1]
|
|
310
306
|
|
|
311
|
-
|
|
312
|
-
self, zone: str, event: str, parameter: str
|
|
313
|
-
) -> None:
|
|
307
|
+
def _delay_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
314
308
|
"""Handle a delay change event."""
|
|
315
309
|
if event == "PS" and parameter[0:5] == "DELAY":
|
|
316
310
|
self._delay = int(parameter[6:])
|
|
317
311
|
|
|
318
|
-
|
|
319
|
-
self, zone: str, event: str, parameter: str
|
|
320
|
-
) -> None:
|
|
312
|
+
def _eco_mode_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
321
313
|
"""Handle an Eco-mode change event."""
|
|
322
314
|
if event == "ECO" and parameter in ECO_MODE_MAP_LABELS:
|
|
323
315
|
self._eco_mode = ECO_MODE_MAP_LABELS[parameter]
|
|
324
316
|
|
|
325
|
-
|
|
326
|
-
self, zone: str, event: str, parameter: str
|
|
327
|
-
) -> None:
|
|
317
|
+
def _hdmi_output_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
328
318
|
"""Handle a HDMI output change event."""
|
|
329
319
|
if event == "VS" and parameter[0:4] == "MONI":
|
|
330
320
|
self._hdmi_output = HDMI_OUTPUT_MAP_LABELS[parameter]
|
|
331
321
|
|
|
332
|
-
|
|
322
|
+
def _hdmi_audio_decode_callback(
|
|
333
323
|
self, zone: str, event: str, parameter: str
|
|
334
324
|
) -> None:
|
|
335
325
|
"""Handle a HDMI Audio Decode mode change event."""
|
|
336
326
|
if event == "VS" and parameter[0:5] == "AUDIO":
|
|
337
327
|
self._hdmi_audio_decode = parameter[6:]
|
|
338
328
|
|
|
339
|
-
|
|
329
|
+
def _video_processing_mode_callback(
|
|
340
330
|
self, zone: str, event: str, parameter: str
|
|
341
331
|
) -> None:
|
|
342
332
|
"""Handle a Video Processing Mode change event."""
|
|
@@ -345,7 +335,7 @@ class DenonAVRDeviceInfo:
|
|
|
345
335
|
parameter[3:]
|
|
346
336
|
]
|
|
347
337
|
|
|
348
|
-
|
|
338
|
+
def _tactile_transducer_callback(
|
|
349
339
|
self, zone: str, event: str, parameter: str
|
|
350
340
|
) -> None:
|
|
351
341
|
"""Handle a tactile transducer change event."""
|
|
@@ -365,9 +355,7 @@ class DenonAVRDeviceInfo:
|
|
|
365
355
|
elif key == "TTRLPF":
|
|
366
356
|
self._tactile_transducer_lpf = f"{int(value)} Hz"
|
|
367
357
|
|
|
368
|
-
|
|
369
|
-
self, zone: str, event: str, parameter: str
|
|
370
|
-
) -> None:
|
|
358
|
+
def _speaker_preset_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
371
359
|
"""Handle a speaker preset change event."""
|
|
372
360
|
if event != "SP":
|
|
373
361
|
return
|
|
@@ -375,7 +363,7 @@ class DenonAVRDeviceInfo:
|
|
|
375
363
|
if parameter[0:2] == "PR":
|
|
376
364
|
self._speaker_preset = int(parameter[3:])
|
|
377
365
|
|
|
378
|
-
|
|
366
|
+
def _bt_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
379
367
|
"""Handle a Bluetooth change event."""
|
|
380
368
|
if event != "BT" or parameter[0:2] != "TX":
|
|
381
369
|
return
|
|
@@ -385,9 +373,7 @@ class DenonAVRDeviceInfo:
|
|
|
385
373
|
else:
|
|
386
374
|
self._bt_output_mode = BLUETOOTH_OUTPUT_MAP_LABELS[parameter[3:]]
|
|
387
375
|
|
|
388
|
-
|
|
389
|
-
self, zone: str, event: str, parameter: str
|
|
390
|
-
) -> None:
|
|
376
|
+
def _delay_time_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
391
377
|
"""Handle a delay time change event."""
|
|
392
378
|
# do not match "DELAY" as it's another event
|
|
393
379
|
if event != "PS" or parameter[0:3] != "DEL" or parameter[0:5] == "DELAY":
|
|
@@ -395,33 +381,48 @@ class DenonAVRDeviceInfo:
|
|
|
395
381
|
|
|
396
382
|
self._delay_time = int(parameter[4:])
|
|
397
383
|
|
|
398
|
-
|
|
399
|
-
self, zone: str, event: str, parameter: str
|
|
400
|
-
) -> None:
|
|
384
|
+
def _audio_restorer_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
401
385
|
"""Handle an audio restorer change event."""
|
|
402
386
|
if event != "PS" or parameter[0:4] != "RSTR":
|
|
403
387
|
return
|
|
404
388
|
|
|
405
389
|
self._audio_restorer = AUDIO_RESTORER_MAP_LABELS[parameter[5:]]
|
|
406
390
|
|
|
407
|
-
|
|
408
|
-
self, zone: str, event: str, parameter: str
|
|
409
|
-
) -> None:
|
|
391
|
+
def _graphic_eq_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
410
392
|
"""Handle a Graphic EQ change event."""
|
|
411
393
|
if parameter[0:3] != "GEQ":
|
|
412
394
|
return
|
|
413
395
|
|
|
414
396
|
self._graphic_eq = parameter[4:]
|
|
415
397
|
|
|
416
|
-
|
|
417
|
-
self, zone: str, event: str, parameter: str
|
|
418
|
-
) -> None:
|
|
398
|
+
def _headphone_eq_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
419
399
|
"""Handle a Headphone EQ change event."""
|
|
420
400
|
if parameter[0:3] != "HEQ":
|
|
421
401
|
return
|
|
422
402
|
|
|
423
403
|
self._headphone_eq = parameter[4:]
|
|
424
404
|
|
|
405
|
+
def _illumination_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
406
|
+
"""Handle an illumination change event."""
|
|
407
|
+
if event != "ILB" or parameter[0:3] != "ILL":
|
|
408
|
+
return
|
|
409
|
+
|
|
410
|
+
self._illumination = ILLUMINATION_MAP_LABELS[parameter[4:]]
|
|
411
|
+
|
|
412
|
+
def _auto_lip_sync_callback(self, zone: str, event: str, parameter: str) -> None:
|
|
413
|
+
"""Handle a auto lip sync change event."""
|
|
414
|
+
if event != "PS" or parameter[0:3] != "HOS":
|
|
415
|
+
return
|
|
416
|
+
|
|
417
|
+
if parameter[6:] == "HOSALS":
|
|
418
|
+
auto_lip_sync = parameter[5:]
|
|
419
|
+
elif parameter[3:] == "HOS":
|
|
420
|
+
auto_lip_sync = parameter[4:]
|
|
421
|
+
else:
|
|
422
|
+
return
|
|
423
|
+
|
|
424
|
+
self._auto_lip_sync = auto_lip_sync
|
|
425
|
+
|
|
425
426
|
def get_own_zone(self) -> str:
|
|
426
427
|
"""
|
|
427
428
|
Get zone from actual instance.
|
|
@@ -459,32 +460,32 @@ class DenonAVRDeviceInfo:
|
|
|
459
460
|
power_event = "Z2"
|
|
460
461
|
elif self.zone == ZONE3:
|
|
461
462
|
power_event = "Z3"
|
|
462
|
-
self.telnet_api.register_callback(power_event, self.
|
|
463
|
-
|
|
464
|
-
self.telnet_api.register_callback("MN", self.
|
|
465
|
-
self.telnet_api.register_callback("DIM", self.
|
|
466
|
-
self.telnet_api.register_callback("PS", self.
|
|
467
|
-
self.telnet_api.register_callback("ECO", self.
|
|
468
|
-
self.telnet_api.register_callback("VS", self.
|
|
469
|
-
self.telnet_api.register_callback(
|
|
470
|
-
"VS", self._async_hdmi_audio_decode_callback
|
|
471
|
-
)
|
|
472
|
-
self.telnet_api.register_callback(
|
|
473
|
-
"VS", self._async_video_processing_mode_callback
|
|
474
|
-
)
|
|
463
|
+
self.telnet_api.register_callback(power_event, self._power_callback)
|
|
464
|
+
|
|
465
|
+
self.telnet_api.register_callback("MN", self._settings_menu_callback)
|
|
466
|
+
self.telnet_api.register_callback("DIM", self._dimmer_callback)
|
|
467
|
+
self.telnet_api.register_callback("PS", self._delay_callback)
|
|
468
|
+
self.telnet_api.register_callback("ECO", self._eco_mode_callback)
|
|
469
|
+
self.telnet_api.register_callback("VS", self._hdmi_output_callback)
|
|
470
|
+
self.telnet_api.register_callback("VS", self._hdmi_audio_decode_callback)
|
|
475
471
|
self.telnet_api.register_callback(
|
|
476
|
-
"
|
|
477
|
-
)
|
|
478
|
-
self.telnet_api.register_callback("
|
|
479
|
-
self.telnet_api.register_callback("
|
|
480
|
-
self.telnet_api.register_callback("
|
|
481
|
-
self.telnet_api.register_callback("
|
|
482
|
-
self.telnet_api.register_callback("
|
|
483
|
-
self.telnet_api.register_callback("
|
|
484
|
-
self.telnet_api.register_callback("
|
|
485
|
-
self.telnet_api.register_callback("PS", self.
|
|
486
|
-
self.telnet_api.register_callback("PS", self.
|
|
487
|
-
self.telnet_api.register_callback("PS", self.
|
|
472
|
+
"VS", self._video_processing_mode_callback
|
|
473
|
+
)
|
|
474
|
+
self.telnet_api.register_callback("SS", self._tactile_transducer_callback)
|
|
475
|
+
self.telnet_api.register_callback("STBY", self._auto_standby_callback)
|
|
476
|
+
self.telnet_api.register_callback("SLP", self._auto_sleep_callback)
|
|
477
|
+
self.telnet_api.register_callback("PS", self._room_size_callback)
|
|
478
|
+
self.telnet_api.register_callback("TR", self._trigger_callback)
|
|
479
|
+
self.telnet_api.register_callback("SP", self._speaker_preset_callback)
|
|
480
|
+
self.telnet_api.register_callback("BT", self._bt_callback)
|
|
481
|
+
self.telnet_api.register_callback("PS", self._delay_time_callback)
|
|
482
|
+
self.telnet_api.register_callback("PS", self._audio_restorer_callback)
|
|
483
|
+
self.telnet_api.register_callback("PS", self._graphic_eq_callback)
|
|
484
|
+
self.telnet_api.register_callback("PS", self._headphone_eq_callback)
|
|
485
|
+
|
|
486
|
+
if not self.is_denon:
|
|
487
|
+
self.telnet_api.register_callback("ILB", self._illumination_callback)
|
|
488
|
+
self.telnet_api.register_callback("SS", self._auto_lip_sync_callback)
|
|
488
489
|
|
|
489
490
|
self._is_setup = True
|
|
490
491
|
_LOGGER.debug("Finished device setup")
|
|
@@ -729,6 +730,7 @@ class DenonAVRDeviceInfo:
|
|
|
729
730
|
|
|
730
731
|
if device_info is None:
|
|
731
732
|
self.manufacturer = "Denon"
|
|
733
|
+
self.telnet_api.is_denon = self.is_denon
|
|
732
734
|
self.model_name = "Unknown"
|
|
733
735
|
self.serial_number = None
|
|
734
736
|
_LOGGER.warning(
|
|
@@ -744,6 +746,7 @@ class DenonAVRDeviceInfo:
|
|
|
744
746
|
if self.friendly_name is None and "friendlyName" in device_info:
|
|
745
747
|
self.friendly_name = device_info["friendlyName"]
|
|
746
748
|
self.manufacturer = device_info["manufacturer"]
|
|
749
|
+
self.telnet_api.is_denon = self.is_denon
|
|
747
750
|
self.model_name = device_info["modelName"]
|
|
748
751
|
self.serial_number = device_info["serialNumber"]
|
|
749
752
|
|
|
@@ -1051,11 +1054,36 @@ class DenonAVRDeviceInfo:
|
|
|
1051
1054
|
"""
|
|
1052
1055
|
return self._headphone_eq
|
|
1053
1056
|
|
|
1057
|
+
@property
|
|
1058
|
+
def illumination(self) -> Optional[str]:
|
|
1059
|
+
"""
|
|
1060
|
+
Return the illumination status for the device.
|
|
1061
|
+
|
|
1062
|
+
Only available on Marantz devices and when using Telnet.
|
|
1063
|
+
|
|
1064
|
+
Possible values are: "Auto", "Bright", "Dim", "Dark", "Off"
|
|
1065
|
+
"""
|
|
1066
|
+
return self._illumination
|
|
1067
|
+
|
|
1068
|
+
@property
|
|
1069
|
+
def auto_lip_sync(self) -> Optional[bool]:
|
|
1070
|
+
"""
|
|
1071
|
+
Return the auto lip sync status for the device.
|
|
1072
|
+
|
|
1073
|
+
Only available on Marantz devices and when using Telnet.
|
|
1074
|
+
"""
|
|
1075
|
+
return self._auto_lip_sync
|
|
1076
|
+
|
|
1054
1077
|
@property
|
|
1055
1078
|
def telnet_available(self) -> bool:
|
|
1056
1079
|
"""Return true if telnet is connected and healthy."""
|
|
1057
1080
|
return self.telnet_api.connected and self.telnet_api.healthy
|
|
1058
1081
|
|
|
1082
|
+
@property
|
|
1083
|
+
def is_denon(self) -> bool:
|
|
1084
|
+
"""Return true if the receiver is a Denon device."""
|
|
1085
|
+
return "denon" in self.manufacturer.lower()
|
|
1086
|
+
|
|
1059
1087
|
##########
|
|
1060
1088
|
# Getter #
|
|
1061
1089
|
##########
|
|
@@ -1402,15 +1430,15 @@ class DenonAVRDeviceInfo:
|
|
|
1402
1430
|
raise AvrCommandError("Quick select number must be between 1 and 5")
|
|
1403
1431
|
|
|
1404
1432
|
if self.telnet_available:
|
|
1405
|
-
if
|
|
1406
|
-
command = self.telnet_commands.
|
|
1433
|
+
if self.is_denon:
|
|
1434
|
+
command = self.telnet_commands.command_quick_select_mode
|
|
1407
1435
|
else:
|
|
1408
|
-
command = self.telnet_commands.
|
|
1436
|
+
command = self.telnet_commands.command_smart_select_mode
|
|
1409
1437
|
await self.telnet_api.async_send_commands(
|
|
1410
1438
|
command.format(number=quick_select_number)
|
|
1411
1439
|
)
|
|
1412
1440
|
else:
|
|
1413
|
-
if
|
|
1441
|
+
if self.is_denon:
|
|
1414
1442
|
command = self.urls.command_quick_select_mode
|
|
1415
1443
|
else:
|
|
1416
1444
|
command = self.urls.command_smart_select_mode
|
|
@@ -1426,15 +1454,15 @@ class DenonAVRDeviceInfo:
|
|
|
1426
1454
|
raise AvrCommandError("Quick select number must be between 1 and 5")
|
|
1427
1455
|
|
|
1428
1456
|
if self.telnet_available:
|
|
1429
|
-
if
|
|
1430
|
-
command = self.telnet_commands.
|
|
1457
|
+
if self.is_denon:
|
|
1458
|
+
command = self.telnet_commands.command_quick_select_memory
|
|
1431
1459
|
else:
|
|
1432
|
-
command = self.telnet_commands.
|
|
1460
|
+
command = self.telnet_commands.command_smart_select_memory
|
|
1433
1461
|
await self.telnet_api.async_send_commands(
|
|
1434
1462
|
command.format(number=quick_select_number)
|
|
1435
1463
|
)
|
|
1436
1464
|
else:
|
|
1437
|
-
if
|
|
1465
|
+
if self.is_denon:
|
|
1438
1466
|
command = self.urls.command_quick_select_memory
|
|
1439
1467
|
else:
|
|
1440
1468
|
command = self.urls.command_smart_select_memory
|
|
@@ -1518,11 +1546,17 @@ class DenonAVRDeviceInfo:
|
|
|
1518
1546
|
self.urls.command_video_processing_mode.format(mode=processing_mode)
|
|
1519
1547
|
)
|
|
1520
1548
|
|
|
1521
|
-
async def async_status(self) ->
|
|
1549
|
+
async def async_status(self) -> None:
|
|
1522
1550
|
"""Get status of receiver via HTTP get command."""
|
|
1523
|
-
if
|
|
1551
|
+
if not self.is_denon:
|
|
1524
1552
|
raise AvrCommandError("Status command is only supported for Denon devices")
|
|
1525
|
-
|
|
1553
|
+
|
|
1554
|
+
if self.telnet_available:
|
|
1555
|
+
await self.telnet_api.async_send_commands(
|
|
1556
|
+
self.telnet_commands.command_status
|
|
1557
|
+
)
|
|
1558
|
+
else:
|
|
1559
|
+
await self.api.async_get_command(self.urls.command_status)
|
|
1526
1560
|
|
|
1527
1561
|
async def async_system_reset(self) -> None:
|
|
1528
1562
|
"""DANGER! Reset the receiver via HTTP get command."""
|
|
@@ -1812,6 +1846,108 @@ class DenonAVRDeviceInfo:
|
|
|
1812
1846
|
else:
|
|
1813
1847
|
await self.async_headphone_eq_on()
|
|
1814
1848
|
|
|
1849
|
+
async def async_hdmi_cec_on(self) -> None:
|
|
1850
|
+
"""Turn on HDMI CEC on receiver via HTTP get command."""
|
|
1851
|
+
if self.telnet_available:
|
|
1852
|
+
await self.telnet_api.async_send_commands(
|
|
1853
|
+
self.telnet_commands.command_denon_hdmi_cec_on
|
|
1854
|
+
if self.is_denon
|
|
1855
|
+
else self.urls.command_marantz_hdmi_cec_on
|
|
1856
|
+
)
|
|
1857
|
+
else:
|
|
1858
|
+
await self.api.async_get_command(
|
|
1859
|
+
self.urls.command_denon_hdmi_cec_on
|
|
1860
|
+
if self.is_denon
|
|
1861
|
+
else self.urls.command_marantz_hdmi_cec_on
|
|
1862
|
+
)
|
|
1863
|
+
|
|
1864
|
+
async def async_hdmi_cec_off(self) -> None:
|
|
1865
|
+
"""Turn off HDMI CEC on receiver via HTTP get command."""
|
|
1866
|
+
if self.telnet_available:
|
|
1867
|
+
await self.telnet_api.async_send_commands(
|
|
1868
|
+
self.telnet_commands.command_denon_hdmi_cec_off
|
|
1869
|
+
if self.is_denon
|
|
1870
|
+
else self.urls.command_marantz_hdmi_cec_off
|
|
1871
|
+
)
|
|
1872
|
+
else:
|
|
1873
|
+
await self.api.async_get_command(
|
|
1874
|
+
self.urls.command_denon_hdmi_cec_off
|
|
1875
|
+
if self.is_denon
|
|
1876
|
+
else self.urls.command_marantz_hdmi_cec_off
|
|
1877
|
+
)
|
|
1878
|
+
|
|
1879
|
+
async def async_illumination(self, mode: Illuminations):
|
|
1880
|
+
"""
|
|
1881
|
+
Set illumination mode on receiver via HTTP get command.
|
|
1882
|
+
|
|
1883
|
+
Only available on Marantz devices.
|
|
1884
|
+
"""
|
|
1885
|
+
if self.is_denon:
|
|
1886
|
+
raise AvrCommandError("Illumination is only available for Marantz devices")
|
|
1887
|
+
|
|
1888
|
+
if mode not in self._illuminations:
|
|
1889
|
+
raise AvrCommandError("Invalid illumination mode")
|
|
1890
|
+
|
|
1891
|
+
mapped_mode = ILLUMINATION_MAP[mode]
|
|
1892
|
+
if self.telnet_available:
|
|
1893
|
+
await self.telnet_api.async_send_commands(
|
|
1894
|
+
self.telnet_commands.command_illumination.format(mode=mapped_mode)
|
|
1895
|
+
)
|
|
1896
|
+
else:
|
|
1897
|
+
await self.api.async_get_command(
|
|
1898
|
+
self.urls.command_illumination.format(mode=mapped_mode)
|
|
1899
|
+
)
|
|
1900
|
+
|
|
1901
|
+
async def async_auto_lip_sync_on(self) -> None:
|
|
1902
|
+
"""
|
|
1903
|
+
Turn on auto lip sync on receiver via HTTP get command.
|
|
1904
|
+
|
|
1905
|
+
Only available on Marantz devices.
|
|
1906
|
+
"""
|
|
1907
|
+
if self.is_denon:
|
|
1908
|
+
raise AvrCommandError("Auto lip sync is only available for Marantz devices")
|
|
1909
|
+
|
|
1910
|
+
if self.telnet_available:
|
|
1911
|
+
await self.telnet_api.async_send_commands(
|
|
1912
|
+
self.telnet_commands.command_auto_lip_sync.format(mode="ON")
|
|
1913
|
+
)
|
|
1914
|
+
else:
|
|
1915
|
+
await self.api.async_get_command(
|
|
1916
|
+
self.urls.command_auto_lip_sync.format(mode="ON")
|
|
1917
|
+
)
|
|
1918
|
+
|
|
1919
|
+
async def async_auto_lip_sync_off(self) -> None:
|
|
1920
|
+
"""
|
|
1921
|
+
Turn off auto lip sync on receiver via HTTP get command.
|
|
1922
|
+
|
|
1923
|
+
Only available on Marantz devices.
|
|
1924
|
+
"""
|
|
1925
|
+
if self.is_denon:
|
|
1926
|
+
raise AvrCommandError("Auto lip sync is only available for Marantz devices")
|
|
1927
|
+
|
|
1928
|
+
if self.telnet_available:
|
|
1929
|
+
await self.telnet_api.async_send_commands(
|
|
1930
|
+
self.telnet_commands.command_auto_lip_sync.format(mode="OFF")
|
|
1931
|
+
)
|
|
1932
|
+
else:
|
|
1933
|
+
await self.api.async_get_command(
|
|
1934
|
+
self.urls.command_auto_lip_sync.format(mode="OFF")
|
|
1935
|
+
)
|
|
1936
|
+
|
|
1937
|
+
async def async_auto_lip_sync_toggle(self) -> None:
|
|
1938
|
+
"""
|
|
1939
|
+
Toggle auto lip sync on receiver via HTTP get command.
|
|
1940
|
+
|
|
1941
|
+
Only available on Marantz devices and when using Telnet.
|
|
1942
|
+
"""
|
|
1943
|
+
if self.is_denon:
|
|
1944
|
+
raise AvrCommandError("Auto lip sync is only available for Marantz devices")
|
|
1945
|
+
|
|
1946
|
+
if self._auto_lip_sync:
|
|
1947
|
+
await self.async_auto_lip_sync_off()
|
|
1948
|
+
else:
|
|
1949
|
+
await self.async_auto_lip_sync_on()
|
|
1950
|
+
|
|
1815
1951
|
|
|
1816
1952
|
@attr.s(auto_attribs=True, on_setattr=DENON_ATTR_SETATTR)
|
|
1817
1953
|
class DenonAVRFoundation:
|