From d03bb8e58b32ed6ed8a0c153b47038ef75e08986 Mon Sep 17 00:00:00 2001 From: Michel van de Wetering Date: Sat, 21 Sep 2024 14:09:46 +0200 Subject: [PATCH 01/14] Fix printing of branchname --- release.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release.py b/release.py index 1e749be..813c46a 100755 --- a/release.py +++ b/release.py @@ -356,7 +356,7 @@ def main(args): 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() From da45d466eeddc06768953d14d12b0b15bc9b06d0 Mon Sep 17 00:00:00 2001 From: Michel van de Wetering Date: Sat, 21 Sep 2024 14:32:15 +0200 Subject: [PATCH 02/14] Fix push of master --- release.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/release.py b/release.py index 813c46a..9d6b10c 100755 --- a/release.py +++ b/release.py @@ -348,10 +348,11 @@ def main(args): Git.commit_changes(f"Update version to {bump_version_after_release}") if input("Push to origin? [Y/n]: ") != "n": - if Git.get_current_branch() == MASTER: + if Git.get_current_branch().name == MASTER: 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!") From f2eedee31b211de46afb4970f25e5f9b5e5d33f8 Mon Sep 17 00:00:00 2001 From: Michel van de Wetering Date: Sat, 21 Sep 2024 14:34:16 +0200 Subject: [PATCH 03/14] Add comment about using PR --- release.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/release.py b/release.py index 9d6b10c..845969b 100755 --- a/release.py +++ b/release.py @@ -323,7 +323,8 @@ def main(args): Git.commit_changes(f"Update version to {next_version}") if not next_version.modifier: - # Merge to master + # Merge to master, ideally this would be done with a PR + # but I don't know how to specify the merge strategy Git.checkout(MASTER) Git.pull() subprocess.run( From 415546445f9ee883c6010d4f48fd2d3d015d9fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Rupe=CC=81rez?= Date: Thu, 21 Nov 2024 17:30:40 +0100 Subject: [PATCH 04/14] Remove entity_category=EntityCategory.CONFIG to allow entertainment area as a control. --- custom_components/huesyncbox/select.py | 1 - 1 file changed, 1 deletion(-) 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, From 21f344fe6175f370c3bd02f3d26885ae8adc7156 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Rupe=CC=81rez?= Date: Thu, 21 Nov 2024 17:52:42 +0100 Subject: [PATCH 05/14] Add Spanish (Spain) translation for Philips Hue Play HDMI Syncbox integration --- .../huesyncbox/translations/es.json | 236 ++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 custom_components/huesyncbox/translations/es.json 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_." + } + } + } + } +} From 21d51336b9dd39a279d4ec575bc42dda2c136dd5 Mon Sep 17 00:00:00 2001 From: Michel van de Wetering Date: Mon, 25 Nov 2024 20:20:52 +0100 Subject: [PATCH 06/14] Misc fixes for release script, check cmd line output, fix numbering for beta releases --- release.py | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/release.py b/release.py index 845969b..bb79b27 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 @@ -323,8 +321,7 @@ def main(args): Git.commit_changes(f"Update version to {next_version}") if not next_version.modifier: - # Merge to master, ideally this would be done with a PR - # but I don't know how to specify the merge strategy + # Merge to master Git.checkout(MASTER) Git.pull() subprocess.run( @@ -349,14 +346,13 @@ def main(args): Git.commit_changes(f"Update version to {bump_version_after_release}") if input("Push to origin? [Y/n]: ") != "n": - if Git.get_current_branch().name == MASTER: + if Git.get_current_branch() == MASTER: 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().name}") From 46c7485c4d298380a2a3935a82545baab8776ad4 Mon Sep 17 00:00:00 2001 From: Michel van de Wetering Date: Mon, 25 Nov 2024 20:36:10 +0100 Subject: [PATCH 07/14] Also check merge command --- release.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/release.py b/release.py index bb79b27..6a2c465 100755 --- a/release.py +++ b/release.py @@ -334,7 +334,8 @@ def main(args): "theirs", "-m", f"Release v{next_version}", - ] + ], + check=True, ) Git.create_tag(tag_name) From 84f7dd1d0371e3f4403588494eab28132fc8c525 Mon Sep 17 00:00:00 2001 From: Michel van de Wetering Date: Fri, 20 Sep 2024 16:40:06 +0200 Subject: [PATCH 08/14] Bump min HA version --- hacs.json | 2 +- requirements_dev.txt | 2 +- requirements_test.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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/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. From 87afb921c6ef6a08806e51b662dd22566374c33b Mon Sep 17 00:00:00 2001 From: Michel van de Wetering Date: Fri, 20 Sep 2024 16:40:21 +0200 Subject: [PATCH 09/14] Show modelnames --- custom_components/huesyncbox/helpers.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/custom_components/huesyncbox/helpers.py b/custom_components/huesyncbox/helpers.py index 83e8ba6..6f2252a 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), + 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 From d4ed8ded039654f8671e2ed2cc2b4240486cd74e Mon Sep 17 00:00:00 2001 From: Michel van de Wetering Date: Fri, 20 Sep 2024 16:40:43 +0200 Subject: [PATCH 10/14] Update tests (part 1, still failing) --- tests/conftest.py | 4 ++-- tests/test_config_flow.py | 9 ++++----- tests/test_init.py | 3 ++- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 93e01a3..7d07f24 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,7 +4,7 @@ from typing import Type from typing_extensions import Generator -from unittest.mock import Mock, patch +from unittest.mock import AsyncMock, Mock, patch import pytest from homeassistant.const import ( @@ -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..e877dc3 100644 --- a/tests/test_config_flow.py +++ b/tests/test_config_flow.py @@ -351,9 +351,8 @@ 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 + # # Confirming will start link phase which tries to connect to the API so setup upfront with patch("aiohuesyncbox.HueSyncBox.__aenter__", return_value=mock_api): - # First attempt button not pressed yet, second try return value mock_api.register.return_value = { "registration_id": "NewRegistrationId", @@ -373,17 +372,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")} From 19ac41ceece0048a74d1b681cfc994d09a16d5c3 Mon Sep 17 00:00:00 2001 From: Michel van de Wetering Date: Mon, 25 Nov 2024 21:35:19 +0100 Subject: [PATCH 11/14] Fix mock setup in tests --- tests/test_config_flow.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_config_flow.py b/tests/test_config_flow.py index e877dc3..30c3560 100644 --- a/tests/test_config_flow.py +++ b/tests/test_config_flow.py @@ -351,8 +351,10 @@ 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 upfront - 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 = { "registration_id": "NewRegistrationId", From cf9fa1a31036cfba0881cfcd7022aa0f5b18ef81 Mon Sep 17 00:00:00 2001 From: Michel van de Wetering Date: Mon, 25 Nov 2024 21:35:50 +0100 Subject: [PATCH 12/14] Don't show a modelname for unknown modelids --- custom_components/huesyncbox/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/huesyncbox/helpers.py b/custom_components/huesyncbox/helpers.py index 6f2252a..7ccd7f2 100644 --- a/custom_components/huesyncbox/helpers.py +++ b/custom_components/huesyncbox/helpers.py @@ -26,7 +26,7 @@ async def update_device_registry( model={ "HSB1": "Philips Hue Play HDMI sync box 4K", "HSB2": "Philips Hue Play HDMI sync box 8K", - }.get(api.device.device_type), + }.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 From 7796cdb830b3083af41c4c5aa6ffc1506276978d Mon Sep 17 00:00:00 2001 From: Michel van de Wetering Date: Mon, 25 Nov 2024 21:47:32 +0100 Subject: [PATCH 13/14] Remove unused import --- tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 7d07f24..e645251 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,7 +4,7 @@ from typing import Type from typing_extensions import Generator -from unittest.mock import AsyncMock, Mock, patch +from unittest.mock import Mock, patch import pytest from homeassistant.const import ( From 46702ff695d6958a6fda819364114f4da75031f9 Mon Sep 17 00:00:00 2001 From: Michel van de Wetering Date: Mon, 25 Nov 2024 21:54:45 +0100 Subject: [PATCH 14/14] Update version to 2.4.0 --- custom_components/huesyncbox/manifest.json | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/custom_components/huesyncbox/manifest.json b/custom_components/huesyncbox/manifest.json index 6e8dcf7..85e0035 100644 --- a/custom_components/huesyncbox/manifest.json +++ b/custom_components/huesyncbox/manifest.json @@ -1,7 +1,6 @@ { "domain": "huesyncbox", "name": "Philips Hue Play HDMI Sync Box", - "codeowners": [ "@mvdwetering" ], @@ -11,8 +10,14 @@ "integration_type": "device", "iot_class": "local_polling", "issue_tracker": "https://github.com/mvdwetering/huesyncbox/issues", - "loggers": ["aiohuesyncbox"], - "requirements": ["aiohuesyncbox==0.0.30"], - "version": "0.0.0", - "zeroconf": ["_huesync._tcp.local."] -} + "loggers": [ + "aiohuesyncbox" + ], + "requirements": [ + "aiohuesyncbox==0.0.30" + ], + "version": "2.4.0", + "zeroconf": [ + "_huesync._tcp.local." + ] +} \ No newline at end of file