|
25 | 25 | DOMAIN, |
26 | 26 | ) |
27 | 27 | from .coordinator import GoveeCoordinator |
28 | | -from .models import DIYSceneCommand, GoveeDevice, SceneCommand |
| 28 | +from .models import DIYSceneCommand, GoveeDevice, ModeCommand, SceneCommand |
| 29 | +from .models.device import INSTANCE_HDMI_SOURCE |
29 | 30 |
|
30 | 31 | # DIY Style options for select entity |
31 | 32 | DIY_STYLE_OPTIONS = list(DIY_STYLE_NAMES.keys()) |
@@ -103,6 +104,19 @@ async def async_setup_entry( |
103 | 104 | ) |
104 | 105 | _LOGGER.debug("Created DIY style select entity for %s", device.name) |
105 | 106 |
|
| 107 | + # HDMI source selector (for devices like AI Sync Box H6604) |
| 108 | + if device.supports_hdmi_source: |
| 109 | + hdmi_options = device.get_hdmi_source_options() |
| 110 | + if hdmi_options: |
| 111 | + entities.append( |
| 112 | + GoveeHdmiSourceSelectEntity( |
| 113 | + coordinator=coordinator, |
| 114 | + device=device, |
| 115 | + options=hdmi_options, |
| 116 | + ) |
| 117 | + ) |
| 118 | + _LOGGER.debug("Created HDMI source select entity for %s", device.name) |
| 119 | + |
106 | 120 | async_add_entities(entities) |
107 | 121 | _LOGGER.debug("Set up %d Govee scene select entities", len(entities)) |
108 | 122 |
|
@@ -436,3 +450,114 @@ async def async_select_option(self, option: str) -> None: |
436 | 450 | option, |
437 | 451 | self._device.name, |
438 | 452 | ) |
| 453 | + |
| 454 | + |
| 455 | +class GoveeHdmiSourceSelectEntity(CoordinatorEntity["GoveeCoordinator"], SelectEntity): |
| 456 | + """Govee HDMI source select entity. |
| 457 | +
|
| 458 | + Provides a dropdown to select HDMI input source on devices like |
| 459 | + the Govee AI Sync Box (H6604). |
| 460 | + """ |
| 461 | + |
| 462 | + _attr_has_entity_name = True |
| 463 | + _attr_translation_key = "govee_hdmi_source_select" |
| 464 | + _attr_icon = "mdi:hdmi-port" |
| 465 | + |
| 466 | + def __init__( |
| 467 | + self, |
| 468 | + coordinator: GoveeCoordinator, |
| 469 | + device: GoveeDevice, |
| 470 | + options: list[dict[str, Any]], |
| 471 | + ) -> None: |
| 472 | + """Initialize the HDMI source select entity. |
| 473 | +
|
| 474 | + Args: |
| 475 | + coordinator: Govee data coordinator. |
| 476 | + device: Device this select belongs to. |
| 477 | + options: List of HDMI source options from capability parameters. |
| 478 | + """ |
| 479 | + super().__init__(coordinator) |
| 480 | + |
| 481 | + self._device = device |
| 482 | + self._device_id = device.device_id |
| 483 | + |
| 484 | + # Build option mapping: display name -> value |
| 485 | + self._option_map: dict[str, int] = {} |
| 486 | + option_names: list[str] = [] |
| 487 | + |
| 488 | + for opt in options: |
| 489 | + name = opt.get("name", "") |
| 490 | + value = opt.get("value") |
| 491 | + if name and value is not None: |
| 492 | + self._option_map[name] = value |
| 493 | + option_names.append(name) |
| 494 | + |
| 495 | + self._attr_options = option_names |
| 496 | + |
| 497 | + # Unique ID |
| 498 | + self._attr_unique_id = f"{device.device_id}_hdmi_source_select" |
| 499 | + |
| 500 | + # Entity name |
| 501 | + self._attr_name = "HDMI Source" |
| 502 | + |
| 503 | + @property |
| 504 | + def device_info(self) -> DeviceInfo: |
| 505 | + """Return device information.""" |
| 506 | + return DeviceInfo( |
| 507 | + identifiers={(DOMAIN, self._device.device_id)}, |
| 508 | + name=self._device.name, |
| 509 | + manufacturer="Govee", |
| 510 | + model=self._device.sku, |
| 511 | + ) |
| 512 | + |
| 513 | + @property |
| 514 | + def available(self) -> bool: |
| 515 | + """Return True if entity is available.""" |
| 516 | + state = self.coordinator.get_state(self._device_id) |
| 517 | + if state is None: |
| 518 | + return False |
| 519 | + return state.online or self._device.is_group |
| 520 | + |
| 521 | + @property |
| 522 | + def current_option(self) -> str | None: |
| 523 | + """Return current selected option from state.""" |
| 524 | + state = self.coordinator.get_state(self._device_id) |
| 525 | + if state and state.hdmi_source is not None: |
| 526 | + # Find option name matching the current value |
| 527 | + for name, value in self._option_map.items(): |
| 528 | + if value == state.hdmi_source: |
| 529 | + return name |
| 530 | + # Return first option as default if available |
| 531 | + return self._attr_options[0] if self._attr_options else None |
| 532 | + |
| 533 | + async def async_select_option(self, option: str) -> None: |
| 534 | + """Handle HDMI source selection.""" |
| 535 | + value = self._option_map.get(option) |
| 536 | + if value is None: |
| 537 | + _LOGGER.warning("Unknown HDMI source option: %s", option) |
| 538 | + return |
| 539 | + |
| 540 | + command = ModeCommand( |
| 541 | + mode_instance=INSTANCE_HDMI_SOURCE, |
| 542 | + value=value, |
| 543 | + ) |
| 544 | + |
| 545 | + success = await self.coordinator.async_control_device( |
| 546 | + self._device_id, |
| 547 | + command, |
| 548 | + ) |
| 549 | + |
| 550 | + if success: |
| 551 | + self.async_write_ha_state() |
| 552 | + _LOGGER.debug( |
| 553 | + "Set HDMI source '%s' (value=%d) on %s", |
| 554 | + option, |
| 555 | + value, |
| 556 | + self._device.name, |
| 557 | + ) |
| 558 | + else: |
| 559 | + _LOGGER.warning( |
| 560 | + "Failed to set HDMI source '%s' on %s", |
| 561 | + option, |
| 562 | + self._device.name, |
| 563 | + ) |
0 commit comments