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/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 Awaitable, Callable, Dict, List, Literal, Optional, Union
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], Awaitable[None]]
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
- async def _async_dirac_filter_callback(
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
- async def _async_power_callback(
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
- async def _async_settings_menu_callback(
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
- async def _async_dimmer_callback(
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
- async def _async_auto_standby_callback(
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
- async def _async_auto_sleep_callback(
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
- async def _async_room_size_callback(
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
- async def _async_trigger_callback(
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
- async def _async_delay_callback(
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
- async def _async_eco_mode_callback(
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
- async def _async_hdmi_output_callback(
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
- async def _async_hdmi_audio_decode_callback(
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
- async def _async_video_processing_mode_callback(
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
- async def _async_tactile_transducer_callback(
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
- async def _async_speaker_preset_callback(
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
- async def _async_bt_callback(self, zone: str, event: str, parameter: str) -> None:
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
- async def _async_delay_time_callback(
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
- async def _async_audio_restorer_callback(
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
- async def _async_graphic_eq_callback(
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
- async def _async_headphone_eq_callback(
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._async_power_callback)
463
-
464
- self.telnet_api.register_callback("MN", self._async_settings_menu_callback)
465
- self.telnet_api.register_callback("DIM", self._async_dimmer_callback)
466
- self.telnet_api.register_callback("PS", self._async_delay_callback)
467
- self.telnet_api.register_callback("ECO", self._async_eco_mode_callback)
468
- self.telnet_api.register_callback("VS", self._async_hdmi_output_callback)
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
- "SS", self._async_tactile_transducer_callback
477
- )
478
- self.telnet_api.register_callback("STBY", self._async_auto_standby_callback)
479
- self.telnet_api.register_callback("SLP", self._async_auto_sleep_callback)
480
- self.telnet_api.register_callback("PS", self._async_room_size_callback)
481
- self.telnet_api.register_callback("TR", self._async_trigger_callback)
482
- self.telnet_api.register_callback("SP", self._async_speaker_preset_callback)
483
- self.telnet_api.register_callback("BT", self._async_bt_callback)
484
- self.telnet_api.register_callback("PS", self._async_delay_time_callback)
485
- self.telnet_api.register_callback("PS", self._async_audio_restorer_callback)
486
- self.telnet_api.register_callback("PS", self._async_graphic_eq_callback)
487
- self.telnet_api.register_callback("PS", self._async_headphone_eq_callback)
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 "denon" in self.manufacturer.lower():
1406
- command = self.telnet_commands.command_quick_select_memory
1433
+ if self.is_denon:
1434
+ command = self.telnet_commands.command_quick_select_mode
1407
1435
  else:
1408
- command = self.telnet_commands.command_smart_select_memory
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 "denon" in self.manufacturer.lower():
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 "denon" in self.manufacturer.lower():
1430
- command = self.telnet_commands.command_quick_select_mode
1457
+ if self.is_denon:
1458
+ command = self.telnet_commands.command_quick_select_memory
1431
1459
  else:
1432
- command = self.telnet_commands.command_smart_select_mode
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 "denon" in self.manufacturer.lower():
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) -> str:
1549
+ async def async_status(self) -> None:
1522
1550
  """Get status of receiver via HTTP get command."""
1523
- if "denon" not in self.manufacturer.lower():
1551
+ if not self.is_denon:
1524
1552
  raise AvrCommandError("Status command is only supported for Denon devices")
1525
- return await self.api.async_get_command(self.urls.command_status)
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: