diff --git a/custom_components/huesyncbox/helpers.py b/custom_components/huesyncbox/helpers.py index 83e8ba6..7ccd7f2 100644 --- a/custom_components/huesyncbox/helpers.py +++ b/custom_components/huesyncbox/helpers.py @@ -23,7 +23,11 @@ async def update_device_registry( identifiers={(DOMAIN, api.device.unique_id)}, manufacturer=MANUFACTURER_NAME, name=api.device.name, - model=api.device.device_type, + model={ + "HSB1": "Philips Hue Play HDMI sync box 4K", + "HSB2": "Philips Hue Play HDMI sync box 8K", + }.get(api.device.device_type, None), + model_id=api.device.device_type, sw_version=api.device.firmware_version, # Uniqueid seems to be the mac. Adding the connection allows other integrations # like e.g. Mikrotik Router to link their entities to this device diff --git a/custom_components/huesyncbox/manifest.json b/custom_components/huesyncbox/manifest.json index f574d64..85e0035 100644 --- a/custom_components/huesyncbox/manifest.json +++ b/custom_components/huesyncbox/manifest.json @@ -16,7 +16,7 @@ "requirements": [ "aiohuesyncbox==0.0.30" ], - "version": "2.3.0", + "version": "2.4.0", "zeroconf": [ "_huesync._tcp.local." ] diff --git a/custom_components/huesyncbox/select.py b/custom_components/huesyncbox/select.py index 3efd288..24038e7 100644 --- a/custom_components/huesyncbox/select.py +++ b/custom_components/huesyncbox/select.py @@ -124,7 +124,6 @@ async def select_led_indicator_mode(api: aiohuesyncbox.HueSyncBox, mode): ), HueSyncBoxSelectEntityDescription( # type: ignore key="entertainment_area", # type: ignore - entity_category=EntityCategory.CONFIG, # type: ignore options_fn=available_entertainment_areas, current_option_fn=current_entertainment_area, select_option_fn=select_entertainment_area, diff --git a/custom_components/huesyncbox/translations/es.json b/custom_components/huesyncbox/translations/es.json new file mode 100644 index 0000000..e6fe319 --- /dev/null +++ b/custom_components/huesyncbox/translations/es.json @@ -0,0 +1,236 @@ +{ + "config": { + "abort": { + "already_configured": "El dispositivo ya está configurado", + "reauth_successful": "Se ha vinculado correctamente la Philips Hue Play HDMI Sync Box", + "reconfigure_successful": "Se ha reconfigurado correctamente la Philips Hue Play HDMI Sync Box", + "connection_failed": "La configuración ha fallado" + }, + "error": { + "cannot_connect": "No se pudo conectar", + "invalid_auth": "Autenticación inválida", + "unknown": "Error inesperado" + }, + "step": { + "configure": { + "title": "Introduce la información del dispositivo", + "description": "Selecciona la pestaña Sincronización y asegúrate de que la Philips Hue Play HDMI Syncbox esté seleccionada. Luego, pulsa el menú … en la parte superior, selecciona Dispositivo, luego Información de red para la dirección IP y finalmente Información del dispositivo para el Identificador.", + "data": { + "host": "Dirección IP (p. ej., 192.168.1.123)", + "unique_id": "Identificador (p. ej., C42996000000)" + } + }, + "reauth_confirm": { + "title": "Reautenticar la integración", + "description": "Es necesario volver a vincular la Philips Hue Play HDMI Sync Box" + }, + "zeroconf_confirm": { + "title": "Dispositivo encontrado", + "description": "Es necesario vincular la Philips Hue Play HDMI Sync Box. Pulsa siguiente para iniciar el proceso de vinculación." + } + }, + "progress": { + "wait_for_button": "Mantén pulsado el botón de la Philips Hue Play HDMI Sync Box durante unos segundos hasta que parpadee en verde para vincularlo." + } + }, + "entity": { + "number": { + "brightness": { + "name": "Brillo" + } + }, + "select": { + "hdmi_input": { + "name": "Entrada HDMI" + }, + "entertainment_area": { + "name": "Área de entretenimiento" + }, + "intensity": { + "name": "Intensidad", + "state": { + "subtle": "Sutil", + "moderate": "Moderada", + "high": "Alta", + "intense": "Intensa" + } + }, + "led_indicator_mode": { + "name": "Indicador LED", + "state": { + "normal": "Normal", + "off": "Apagado", + "dimmed": "Atenuado" + } + }, + "sync_mode": { + "name": "Modo de sincronización", + "state": { + "video": "Vídeo", + "music": "Música", + "game": "Juego" + } + } + }, + "sensor": { + "bridge_unique_id": { + "name": "ID del Puente Hue" + }, + "ip_address": { + "name": "Dirección IP" + }, + "bridge_connection_state": { + "name": "Conexión del Puente Hue", + "state": { + "uninitialized": "No inicializado", + "disconnected": "Desconectado", + "connecting": "Conectando", + "unauthorized": "No autorizado", + "connected": "Conectado", + "invalidgroup": "Grupo no válido", + "streaming": "Transmitiendo", + "busy": "Ocupado" + } + }, + "hdmi1_status": { + "name": "Estado de HDMI 1", + "state": { + "unplugged": "Desconectado", + "plugged": "Conectado", + "linked": "Vinculado", + "unknown": "Desconocido" + } + }, + "hdmi2_status": { + "name": "Estado de HDMI 2", + "state": { + "unplugged": "Desconectado", + "plugged": "Conectado", + "linked": "Vinculado", + "unknown": "Desconocido" + } + }, + "hdmi3_status": { + "name": "Estado de HDMI 3", + "state": { + "unplugged": "Desconectado", + "plugged": "Conectado", + "linked": "Vinculado", + "unknown": "Desconocido" + } + }, + "hdmi4_status": { + "name": "Estado de HDMI 4", + "state": { + "unplugged": "Desconectado", + "plugged": "Conectado", + "linked": "Vinculado", + "unknown": "Desconocido" + } + }, + "wifi_strength": { + "name": "Calidad del Wi-Fi", + "state": { + "not_connected": "No conectado", + "weak": "Débil", + "fair": "Aceptable", + "good": "Buena", + "excellent": "Excelente" + } + }, + "content_info": { + "name": "Información del contenido" + } + }, + "switch": { + "power": { + "name": "Encendido" + }, + "light_sync": { + "name": "Sincronización de luces" + }, + "dolby_vision_compatibility": { + "name": "Compatibilidad con Dolby Vision" + } + } + }, + "selector": { + "modes": { + "options": { + "video": "Vídeo", + "music": "Música", + "game": "Juego" + } + }, + "intensities": { + "options": { + "subtle": "Sutil", + "moderate": "Moderada", + "high": "Alta", + "intense": "Intensa" + } + }, + "inputs": { + "options": { + "input1": "HDMI 1", + "input2": "HDMI 2", + "input3": "HDMI 3", + "input4": "HDMI 4" + } + } + }, + "services": { + "set_bridge": { + "name": "Configurar Puente Hue", + "description": "Configura el Puente Hue que será usado por el Philips Hue Play HDMI Syncbox. Ten en cuenta que cambiar el Puente Hue puede tardar un tiempo (aproximadamente 15 segundos). Después de cambiar el Puente Hue, puede que sea necesario seleccionar el `entertainment_area` si el estado de la conexión es `invalidgroup` en lugar de `connected`.", + "fields": { + "bridge_id": { + "name": "ID del Puente Hue", + "description": "ID del Puente Hue. Un código hexadecimal de 16 caracteres." + }, + "bridge_username": { + "name": "Nombre de usuario", + "description": "Nombre de usuario (también conocido como clave de aplicación) válido para el Puente Hue. Un código largo de caracteres aleatorios." + }, + "bridge_clientkey": { + "name": "Clave del cliente", + "description": "Clave del cliente correspondiente al nombre de usuario. Un código hexadecimal de 32 caracteres." + } + } + }, + "set_sync_state": { + "name": "Configurar estado de sincronización de luces", + "description": "Controla el estado completo de sincronización de luces del Philips Hue Play HDMI Syncbox con una única llamada.", + "fields": { + "power": { + "name": "Encendido", + "description": "Encender o apagar el Philips Hue Play HDMI Syncbox." + }, + "sync": { + "name": "Sincronización de luces", + "description": "Configurar el estado de sincronización de luces encendido o apagado. Configurar esta opción también encenderá el Philips Hue Play HDMI Syncbox." + }, + "brightness": { + "name": "Brillo", + "description": "Valor de brillo a configurar." + }, + "mode": { + "name": "Modo", + "description": "Modo a configurar. Configurar el modo también encenderá el Philips Hue Play HDMI Syncbox e iniciará la sincronización de luces." + }, + "intensity": { + "name": "Intensidad", + "description": "Intensidad a configurar." + }, + "input": { + "name": "Entrada", + "description": "Entrada a seleccionar." + }, + "entertainment_area": { + "name": "Área de entretenimiento", + "description": "Área de entretenimiento a seleccionar. El nombre debe coincidir _exactamente_." + } + } + } + } +} diff --git a/hacs.json b/hacs.json index 1303718..7d8fe09 100644 --- a/hacs.json +++ b/hacs.json @@ -1,6 +1,6 @@ { "name": "Philips Hue Play HDMI Sync Box", - "homeassistant": "2024.7.0", + "homeassistant": "2024.8.0", "render_readme": true, "zip_release": true, "filename": "huesyncbox.zip" diff --git a/release.py b/release.py index 1e749be..6a2c465 100755 --- a/release.py +++ b/release.py @@ -57,40 +57,39 @@ def workarea_is_clean() -> bool: @staticmethod def checkout(branch): - subprocess.run(["git", "checkout", branch]) + subprocess.run(["git", "checkout", branch], check=True) @staticmethod def add_changes(): - subprocess.run(["git", "add", "--all"]) + subprocess.run(["git", "add", "--all"], check=True) @staticmethod def commit_changes(message): - subprocess.run(["git", "commit", "-m", message]) + subprocess.run(["git", "commit", "-m", message], check=True) @staticmethod def pull(): - subprocess.run(["git", "pull"]) + subprocess.run(["git", "pull"], check=True) @staticmethod def delete_branch(name): - subprocess.run(["git", "branch", "-D", name]) + subprocess.run(["git", "branch", "-D", name], check=True) @staticmethod def create_branch(name): - subprocess.run(["git", "branch", name]) + subprocess.run(["git", "branch", name], check=True) @staticmethod def create_tag(name): - subprocess.run(["git", "tag", name]) + subprocess.run(["git", "tag", name], check=True) @staticmethod def push_to_origin(name): - subprocess.run(["git", "push", "origin", name]) + subprocess.run(["git", "push", "origin", name], check=True) @staticmethod def fetch_tags(): - subprocess.run(["git", "fetch", "--tags"]) - + subprocess.run(["git", "fetch", "--tags"], check=True) def menu(title, choices): while True: @@ -287,8 +286,7 @@ def main(args): ) # Changing from alpha to beta should bump the version before release - version_diff = next_manifest_version - manifest_version - if version_diff.modifier: + if manifest_version.alpha and next_manifest_version.beta: next_version = next_manifest_version else: next_version = manifest_version @@ -336,7 +334,8 @@ def main(args): "theirs", "-m", f"Release v{next_version}", - ] + ], + check=True, ) Git.create_tag(tag_name) @@ -352,11 +351,11 @@ def main(args): Git.push_to_origin(MASTER) Git.push_to_origin(release_branch_name) Git.push_to_origin(tag_name) + else: print("Don't forget to push later or revert changes!") - print("Done!") - print(f"Currently on branch: {Git.get_current_branch()}") + print(f"Currently on branch: {Git.get_current_branch().name}") if __name__ == "__main__": parser = argparse.ArgumentParser() diff --git a/requirements_dev.txt b/requirements_dev.txt index 6846386..45465ed 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,4 +1,4 @@ -r requirements_test.txt awesomeversion>=24.0.0 -homeassistant-stubs==2024.7.0 +homeassistant-stubs==2024.8.0 diff --git a/requirements_test.txt b/requirements_test.txt index a70c8e6..47ad3b7 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -2,7 +2,7 @@ mypy==1.11.0 -pytest-homeassistant-custom-component==0.13.144 +pytest-homeassistant-custom-component==0.13.152 # Not entirely clear why it is needed as not a requirement for huesyncbox directly # but the tests fail because HA seems to initialize the zeroconf component which fails due to missing lib. diff --git a/tests/conftest.py b/tests/conftest.py index 93e01a3..e645251 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -44,7 +44,7 @@ def entity_registry_enabled_by_default() -> Generator[None]: @pytest.fixture -def mock_api(hass): +def mock_api(): """Create a mocked HueSyncBox instance.""" mock_api = Mock( spec=aiohuesyncbox.HueSyncBox, diff --git a/tests/test_config_flow.py b/tests/test_config_flow.py index 9aba91b..30c3560 100644 --- a/tests/test_config_flow.py +++ b/tests/test_config_flow.py @@ -351,8 +351,9 @@ async def test_reauth_flow(hass: HomeAssistant, mock_api) -> None: assert result["type"] == FlowResultType.FORM assert result["step_id"] == "reauth_confirm" - # Confirming will start link phase which tries to connect to the API so setup up front - with patch("aiohuesyncbox.HueSyncBox.__aenter__", return_value=mock_api): + # Confirming will start link phase which tries to connect to the API so setup upfront + with (patch("aiohuesyncbox.HueSyncBox") as huesyncbox_instance,): + huesyncbox_instance.return_value.__aenter__.return_value = mock_api # First attempt button not pressed yet, second try return value mock_api.register.return_value = { @@ -373,17 +374,17 @@ async def test_reauth_flow(hass: HomeAssistant, mock_api) -> None: result = await hass.config_entries.flow.async_configure( result["flow_id"], ) - await hass.async_block_till_done() + # await hass.async_block_till_done() assert result["type"] == FlowResultType.ABORT assert result["reason"] == "reauth_successful" # Config entry token and registration id should be updated, + assert integration.entry.data["access_token"] == "NewAccessToken" + assert integration.entry.data["registration_id"] == "NewRegistrationId" # rest should still be the same assert integration.entry.data["host"] == "host_value" assert integration.entry.data["port"] == 1234 assert integration.entry.data["unique_id"] == "unique_id_value" assert integration.entry.data["path"] == "/path_value" - assert integration.entry.data["access_token"] == "NewAccessToken" - assert integration.entry.data["registration_id"] == "NewRegistrationId" diff --git a/tests/test_init.py b/tests/test_init.py index 31ef60d..51b68e3 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -30,7 +30,8 @@ async def test_device_info(hass: HomeAssistant, mock_api): assert device is not None assert device.name == "Name" assert device.manufacturer == "Signify" - assert device.model == "HSB1" + assert device.model == "Philips Hue Play HDMI sync box 4K" + assert device.model_id == "HSB1" assert device.sw_version == "firmwareversion" assert device.connections == {("mac", "12:34:56:ab:cd:ef")}