diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..20623b5 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: [Mr-Groch] +custom: ["https://paypal.me/MrGroch", "https://www.buymeacoffee.com/MrGroch"] diff --git a/.github/workflows/hassfest.yaml b/.github/workflows/hassfest.yaml new file mode 100644 index 0000000..18c7d19 --- /dev/null +++ b/.github/workflows/hassfest.yaml @@ -0,0 +1,14 @@ +name: Validate with hassfest + +on: + push: + pull_request: + schedule: + - cron: "0 0 * * *" + +jobs: + validate: + runs-on: "ubuntu-latest" + steps: + - uses: "actions/checkout@v2" + - uses: home-assistant/actions/hassfest@master diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml new file mode 100644 index 0000000..fc1b5f9 --- /dev/null +++ b/.github/workflows/validate.yaml @@ -0,0 +1,17 @@ +name: Validate + +on: + push: + pull_request: + schedule: + - cron: "0 0 * * *" + +jobs: + validate: + runs-on: "ubuntu-latest" + steps: + - uses: "actions/checkout@v2" + - name: HACS validation + uses: "hacs/action@main" + with: + category: "integration" diff --git a/README.md b/README.md index 5eeb905..613fccd 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,40 @@ +[![hacs_badge](https://img.shields.io/badge/HACS-Default-orange.svg)](https://github.com/hacs/integration) +[![paypalme_badge](https://img.shields.io/badge/Donate-PayPal-0070ba)](https://paypal.me/MrGroch) +[![Buy me a coffee](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/MrGroch) + # Philips TV Ambilight+Hue (Switch) Component A Switch component for automating the control of the Ambilight+hue setting on a Philips TV, this reveals the current status of the menu setting to Home Assistant, and allows for remote or automated toggling. + +Forked from not maintained for a long time jomwell's repo: +https://github.com/jomwells/ambihue + ## Installation -#### Option 1: (recommended) -This repository is compatible with the Home Assistant Community Store ([HACS](https://community.home-assistant.io/t/custom-component-hacs/121727)). +### Using [HACS](https://hacs.xyz/) (recommended) + +This integration can be installed using HACS. To do it search for `Philips Ambilight+Hue Switch` in Integrations section. + +### Manual + +1. Using the tool of choice open the directory (folder) for your HA configuration (where you find `configuration.yaml`). +2. If you do not have a `custom_components` directory (folder) there, you need to create it. +3. In the `custom_components` directory (folder) create a new folder called `philips_ambilight_hue`. +4. Download _all_ the files from the `custom_components/philips_ambilight_hue/` directory (folder) in this repository. +5. Place the files you downloaded in the new directory (folder) you created. +6. Restart Home Assistant. +7. [Configure](#Configuration) custom component using Config Flow UI. + + +## Configuration -After installing HACS, install 'Philips Ambilight+Hue' from the store, and use the ```configuration.yaml``` example below. +After installation of the custom component, it needs to be added using **Config Flow UI**. -#### Option 2: (manual) -If you have already set up the [Ambilight (Light) component](https://github.com/jomwells/ambilights), installing this component is very simple, copy the ```philips_ambilight+hue``` directory into your ```config/custom_components/``` directory, -enter the same username and password as for the ambilight component in the configuration.yaml, along with the IP of the TV, and restart home assistant: +To configure this integration go to: _Configuration_ -> _Integrations_ -> _Add integration_ -> _Philips TV Ambilight+Hue_. -If you have not setup any other Philips TV components, use the tool linked in the Ambilight (Light) component docs to obtain your username and password. -``` -switch: - - platform: philips_ambilight+hue - name: Ambilight+Hue - host: 192.168.1.XXX - username: !secret philips_username - password: !secret philips_password - id: 2131230774 # ambilight_hue_off node id. Default is 2131230774, but some newer TVs use 2131230778 instead. - scan_interval: 5 -``` +You can also use following [My Home Assistant](http://my.home-assistant.io/) link -If the component is not working, try setting `2131230778` as the `id` in the config +[![Open your Home Assistant instance and start setting up a new integration.](https://my.home-assistant.io/badges/config_flow_start.svg)](https://my.home-assistant.io/redirect/config_flow_start/?domain=philips_ambilight_hue) -*note:* there is often a noticeable lag between Home Assistant sending the request to toggle the setting, and receiving a status update from the API, for this reason, it is advised that you reduce your `scan_interval` (in seconds) to suit your needs. +Configuration steps are similar to official Philips TV integration, so if you need help look [here](https://www.home-assistant.io/integrations/philips_js/). +*note:* there is often a noticeable lag between Home Assistant sending the request to toggle the setting, and receiving a status update from the API. diff --git a/custom_components/philips_ambilight+hue/manifest.json b/custom_components/philips_ambilight+hue/manifest.json deleted file mode 100755 index 9f7a768..0000000 --- a/custom_components/philips_ambilight+hue/manifest.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "domain": "philips_ambilight+hue", - "name": "Philips Ambilight+Hue", - "documentation": "https://github.com/jomwells/ambihue", - "dependencies": [], - "codeowners": ["@jomwells"], - "requirements": [] -} diff --git a/custom_components/philips_ambilight+hue/switch.py b/custom_components/philips_ambilight+hue/switch.py deleted file mode 100755 index cd7c51d..0000000 --- a/custom_components/philips_ambilight+hue/switch.py +++ /dev/null @@ -1,117 +0,0 @@ -import json -import string -import requests -import homeassistant.helpers.config_validation as cv -import voluptuous as vol -from homeassistant.components.switch import ( - DOMAIN, PLATFORM_SCHEMA, SwitchEntity, ENTITY_ID_FORMAT) -from homeassistant.const import (CONF_HOST, CONF_NAME, CONF_USERNAME, CONF_PASSWORD, CONF_ID, STATE_OFF, STATE_STANDBY, STATE_ON) -from requests.auth import HTTPDigestAuth -from requests.adapters import HTTPAdapter - -DEFAULT_DEVICE = 'default' -DEFAULT_HOST = '127.0.0.1' -DEFAULT_USER = 'user' -DEFAULT_PASS = 'pass' -DEFAULT_NAME = 'Ambilight+Hue' -DEFAULT_ID = '2131230774' -BASE_URL = 'https://{0}:1926/6/{1}' # for older philps tv's, try changing this to 'http://{0}:1925/1/{1}' -TIMEOUT = 5.0 -CONNFAILCOUNT = 5 - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_HOST, default=DEFAULT_HOST): cv.string, - vol.Required(CONF_USERNAME, default=DEFAULT_USER): cv.string, - vol.Required(CONF_PASSWORD, default=DEFAULT_PASS): cv.string, - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_ID, default=DEFAULT_ID): cv.string -}) - -def setup_platform(hass, config, add_devices, discovery_info=None): - name = config.get(CONF_NAME) - host = config.get(CONF_HOST) - user = config.get(CONF_USERNAME) - password = config.get(CONF_PASSWORD) - nodeId = config.get(CONF_ID) - add_devices([AmbiHue(name, host, user, password, nodeId)]) - -class AmbiHue(SwitchEntity): - - def __init__(self, name, host, user, password, nodeId): - self._name = name - self._host = host - self._user = user - self._password = password - self._nodeId = int(nodeId) - self._state = False - self._connfail = 0 - self._available = False - self._session = requests.Session() - self._session.mount('https://', HTTPAdapter(pool_connections=1)) - - @property - def name(self): - return self._name - - @property - def is_on(self): - return self._state - - @property - def available(self): - return self._available - - @property - def should_poll(self): - return True - - - def turn_on(self, **kwargs): - self._postReq('menuitems/settings/update', {"values":[{"value":{"Nodeid":self._nodeId,"Controllable":"true","Available":"true","data":{"value":"true"}}}]} ) - self._state = True - - def turn_off(self, **kwargs): - self._postReq('menuitems/settings/update', {"values":[{"value":{"Nodeid":self._nodeId,"Controllable":"true","Available":"true","data":{"value":"false"}}}]} ) - self._state = False - - def getState(self): - fullstate = self._postReq('menuitems/settings/current', {'nodes':[{'nodeid':self._nodeId}]}) - if fullstate: - self._available = True - ahstat = fullstate['values'][0]['value']['data']['value'] - if ahstat == True: - self._state = True - else: - self._state = False - else: - self._available = False - self._state = False - - def update(self): - self.getState() - - def _getReq(self, path): - try: - if self._connfail: - self._connfail -= 1 - return None - resp = self._session.get(BASE_URL.format(self._host, path), verify=False, auth=HTTPDigestAuth(self._user, self._password), timeout=TIMEOUT) - self.on = True - return json.loads(resp.text) - except requests.exceptions.RequestException as err: - self._connfail = CONNFAILCOUNT - self.on = False - return None - - def _postReq(self, path, data): - try: - if self._connfail: - self._connfail -= 1 - return False - resp = self._session.post(BASE_URL.format(self._host, path), data=json.dumps(data), verify=False, auth=HTTPDigestAuth(self._user, self._password), timeout=TIMEOUT) - self.on = True - return json.loads(resp.text) - except requests.exceptions.RequestException as err: - self._connfail = CONNFAILCOUNT - self.on = False - return False diff --git a/custom_components/philips_ambilight_hue/__init__.py b/custom_components/philips_ambilight_hue/__init__.py new file mode 100644 index 0000000..0f16d4a --- /dev/null +++ b/custom_components/philips_ambilight_hue/__init__.py @@ -0,0 +1,142 @@ +"""The Philips Ambilight+Hue integration.""" +from __future__ import annotations + +from typing import cast, Optional +import asyncio +from collections.abc import Mapping +from datetime import timedelta +import logging + +from haphilipsjs import ConnectionFailure, PhilipsTV +from haphilipsjs.typing import SystemType + +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import ( + CONF_API_VERSION, + CONF_HOST, + CONF_PASSWORD, + CONF_USERNAME, + Platform, +) +from homeassistant.core import ( + HomeAssistant, + callback, +) +from homeassistant.helpers.debounce import Debouncer +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator + +from .const import CONF_SYSTEM, DOMAIN + +PLATFORMS = [ + Platform.SWITCH, +] + +LOGGER = logging.getLogger(__name__) + + +async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: + """Set up Philips TV from a config entry.""" + + tvapi = PhilipsTV( + entry.data[CONF_HOST], + entry.data[CONF_API_VERSION], + username=entry.data.get(CONF_USERNAME), + password=entry.data.get(CONF_PASSWORD), + ) + coordinator = PhilipsTVDataUpdateCoordinator(hass, tvapi, entry.options) + + await coordinator.async_refresh() + hass.data.setdefault(DOMAIN, {}) + hass.data[DOMAIN][entry.entry_id] = coordinator + + for component in PLATFORMS: + hass.async_create_task( + hass.config_entries.async_forward_entry_setup(entry, component) + ) + + entry.async_on_unload(entry.add_update_listener(async_update_entry)) + + return True + + +async def async_update_entry(hass: HomeAssistant, entry: ConfigEntry) -> None: + """Update options.""" + await hass.config_entries.async_reload(entry.entry_id) + + +async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: + """Unload a config entry.""" + unload_ok = all( + await asyncio.gather( + *[ + hass.config_entries.async_forward_entry_unload(entry, component) + for component in PLATFORMS + ] + ) + ) + if unload_ok: + hass.data[DOMAIN].pop(entry.entry_id) + + return unload_ok + + +class PhilipsTVDataUpdateCoordinator(DataUpdateCoordinator[None]): + """Coordinator to update data.""" + + def __init__(self, hass, api: PhilipsTV, options: Mapping) -> None: + """Set up the coordinator.""" + self.api = api + self.options = options + + self.huelampstate: Optional[str] = None + + super().__init__( + hass, + LOGGER, + name=DOMAIN, + update_interval=timedelta(seconds=30), + request_refresh_debouncer=Debouncer( + hass, LOGGER, cooldown=2.0, immediate=False + ), + ) + + @property + def system(self) -> SystemType: + """Return the system descriptor.""" + if self.api.system: + return self.api.system + return self.config_entry.data[CONF_SYSTEM] + + @property + def unique_id(self) -> str: + """Return the system descriptor.""" + entry: ConfigEntry = self.config_entry + assert entry + if entry.unique_id: + return entry.unique_id + assert entry.entry_id + return entry.entry_id + + async def getHueLampState(self): + r = await self.api.getReq("HueLamp/power") + if r: + self.huelampstate = cast(str, r["power"]) + else: + self.huelampstate = None + return r + + + async def setHueLampState(self, state): + data = {"power": state} + if await self.api.postReq("HueLamp/power", data) is not None: + self.huelampstate = state + return True + + @callback + async def _async_update_data(self): + """Fetch the latest data from the source.""" + try: + await self.getHueLampState() + await self.api.update() + except ConnectionFailure: + pass diff --git a/custom_components/philips_ambilight_hue/config_flow.py b/custom_components/philips_ambilight_hue/config_flow.py new file mode 100644 index 0000000..e4142c2 --- /dev/null +++ b/custom_components/philips_ambilight_hue/config_flow.py @@ -0,0 +1,145 @@ +"""Config flow for Philips Ambilight+Hue integration.""" +from __future__ import annotations + +import platform +from typing import Any + +from haphilipsjs import ConnectionFailure, PairingFailure, PhilipsTV +import voluptuous as vol + +from homeassistant import config_entries, core +from homeassistant.const import ( + CONF_API_VERSION, + CONF_HOST, + CONF_PASSWORD, + CONF_PIN, + CONF_USERNAME, +) + +from . import LOGGER +from .const import CONF_SYSTEM, CONST_APP_ID, CONST_APP_NAME, DOMAIN + + +async def validate_input( + hass: core.HomeAssistant, host: str, api_version: int +) -> tuple[dict, PhilipsTV]: + """Validate the user input allows us to connect.""" + hub = PhilipsTV(host, api_version) + + await hub.getSystem() + await hub.setTransport(hub.secured_transport) + + if not hub.system: + raise ConnectionFailure("System data is empty") + + return hub + + +class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): + """Handle a config flow for Philips TV.""" + + VERSION = 1 + + def __init__(self) -> None: + """Initialize flow.""" + super().__init__() + self._current = {} + self._hub: PhilipsTV | None = None + self._pair_state: Any = None + + async def _async_create_current(self): + + system = self._current[CONF_SYSTEM] + return self.async_create_entry( + title=f"{system['name']}", + data=self._current, + ) + + async def async_step_pair(self, user_input: dict | None = None) -> dict: + """Attempt to pair with device.""" + assert self._hub + + errors = {} + schema = vol.Schema( + { + vol.Required(CONF_PIN): str, + } + ) + + if not user_input: + try: + self._pair_state = await self._hub.pairRequest( + CONST_APP_ID, + CONST_APP_NAME, + platform.node(), + platform.system(), + "native", + ) + except PairingFailure as exc: + LOGGER.debug(exc) + return self.async_abort( + reason="pairing_failure", + description_placeholders={"error_id": exc.data.get("error_id")}, + ) + return self.async_show_form( + step_id="pair", data_schema=schema, errors=errors + ) + + try: + username, password = await self._hub.pairGrant( + self._pair_state, user_input[CONF_PIN] + ) + except PairingFailure as exc: + LOGGER.debug(exc) + if exc.data.get("error_id") == "INVALID_PIN": + errors[CONF_PIN] = "invalid_pin" + return self.async_show_form( + step_id="pair", data_schema=schema, errors=errors + ) + + return self.async_abort( + reason="pairing_failure", + description_placeholders={"error_id": exc.data.get("error_id")}, + ) + + self._current[CONF_USERNAME] = username + self._current[CONF_PASSWORD] = password + return await self._async_create_current() + + async def async_step_user(self, user_input: dict | None = None) -> dict: + """Handle the initial step.""" + errors = {} + if user_input: + self._current = user_input + try: + hub = await validate_input( + self.hass, user_input[CONF_HOST], user_input[CONF_API_VERSION] + ) + except ConnectionFailure as exc: + LOGGER.error(exc) + errors["base"] = "cannot_connect" + except Exception: # pylint: disable=broad-except + LOGGER.exception("Unexpected exception") + errors["base"] = "unknown" + else: + if serialnumber := hub.system.get("serialnumber"): + await self.async_set_unique_id(serialnumber) + self._abort_if_unique_id_configured() + + self._current[CONF_SYSTEM] = hub.system + self._current[CONF_API_VERSION] = hub.api_version + self._hub = hub + + if hub.pairing_type == "digest_auth_pairing": + return await self.async_step_pair() + return await self._async_create_current() + + schema = vol.Schema( + { + vol.Required(CONF_HOST, default=self._current.get(CONF_HOST)): str, + vol.Required( + CONF_API_VERSION, default=self._current.get(CONF_API_VERSION, 1) + ): vol.In([1, 5, 6]), + } + ) + return self.async_show_form(step_id="user", data_schema=schema, errors=errors) diff --git a/custom_components/philips_ambilight_hue/const.py b/custom_components/philips_ambilight_hue/const.py new file mode 100644 index 0000000..89561fc --- /dev/null +++ b/custom_components/philips_ambilight_hue/const.py @@ -0,0 +1,7 @@ +"""The Philips Ambilight+Hue constants.""" + +DOMAIN = "philips_ambilight_hue" +CONF_SYSTEM = "system" + +CONST_APP_ID = "homeassistant.io" +CONST_APP_NAME = "Home Assistant" \ No newline at end of file diff --git a/custom_components/philips_ambilight_hue/manifest.json b/custom_components/philips_ambilight_hue/manifest.json new file mode 100644 index 0000000..3a653a3 --- /dev/null +++ b/custom_components/philips_ambilight_hue/manifest.json @@ -0,0 +1,11 @@ +{ + "domain": "philips_ambilight_hue", + "name": "Philips TV Ambilight+Hue", + "codeowners": ["@jomwells","@Mr-Groch"], + "config_flow": true, + "documentation": "https://github.com/Mr-Groch/ambihue", + "iot_class": "local_polling", + "issue_tracker": "https://github.com/Mr-Groch/ambihue/issues", + "requirements": ["ha-philipsjs==2.7.6"], + "version": "1.0.3" +} diff --git a/custom_components/philips_ambilight_hue/strings.json b/custom_components/philips_ambilight_hue/strings.json new file mode 100644 index 0000000..c2d7f9a --- /dev/null +++ b/custom_components/philips_ambilight_hue/strings.json @@ -0,0 +1,28 @@ +{ + "config": { + "step": { + "user": { + "data": { + "host": "[%key:common::config_flow::data::host%]", + "api_version": "API Version" + } + }, + "pair": { + "title": "Pair", + "description": "Enter the PIN displayed on your TV", + "data":{ + "pin": "[%key:common::config_flow::data::pin%]" + } + } + }, + "error": { + "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", + "unknown": "[%key:common::config_flow::error::unknown%]", + "pairing_failure": "Unable to pair: {error_id}", + "invalid_pin": "Invalid PIN" + }, + "abort": { + "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" + } + } +} \ No newline at end of file diff --git a/custom_components/philips_ambilight_hue/switch.py b/custom_components/philips_ambilight_hue/switch.py new file mode 100644 index 0000000..6b72064 --- /dev/null +++ b/custom_components/philips_ambilight_hue/switch.py @@ -0,0 +1,84 @@ +"""Philips Ambilight+Hue switch""" +from __future__ import annotations + +from typing import Any + +from homeassistant.components.switch import SwitchEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers.entity import DeviceInfo +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.update_coordinator import CoordinatorEntity + +from . import PhilipsTVDataUpdateCoordinator +from .const import DOMAIN + + +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up the configuration entry.""" + coordinator: PhilipsTVDataUpdateCoordinator = hass.data[DOMAIN][ + config_entry.entry_id + ] + + async_add_entities([PhilipsTVAmbiHueSwitch(coordinator)]) + + +class PhilipsTVAmbiHueSwitch(CoordinatorEntity, SwitchEntity): + """A Philips TV Ambilight+Hue state switch.""" + + coordinator: PhilipsTVDataUpdateCoordinator + + def __init__( + self, + coordinator: PhilipsTVDataUpdateCoordinator, + ) -> None: + """Initialize entity.""" + + super().__init__(coordinator) + + self._attr_name = f"{coordinator.system['name']} Ambilight+Hue" + self._attr_icon = "mdi:television-ambient-light" + self._attr_unique_id = coordinator.unique_id + self._attr_device_info = DeviceInfo( + identifiers={ + (DOMAIN, self._attr_unique_id), + }, + manufacturer="Philips", + model=coordinator.system.get("model"), + name=coordinator.system["name"], + sw_version=coordinator.system.get("softwareversion"), + ) + + @property + def available(self) -> bool: + """Return true if entity is available.""" + if not super().available: + return False + if not self.coordinator.api.on: + return False + return self.coordinator.api.powerstate == "On" + + @property + def is_on(self) -> bool: + """Return True if entity is on.""" + return self.coordinator.huelampstate == "On" + + async def async_turn_on(self, **kwargs: Any) -> None: + """Turn the entity on.""" + await self.coordinator.setHueLampState("On") + await self.coordinator.async_request_refresh() + + async def async_turn_off(self, **kwargs: Any) -> None: + """Turn the entity off.""" + await self.coordinator.setHueLampState("Off") + await self.coordinator.async_request_refresh() + + @callback + def _handle_coordinator_update(self) -> None: + """Handle updated data from the coordinator.""" + self._attr_is_on = self.coordinator.huelampstate == "On" + self.async_write_ha_state() diff --git a/custom_components/philips_ambilight_hue/translations/en.json b/custom_components/philips_ambilight_hue/translations/en.json new file mode 100644 index 0000000..98dadb9 --- /dev/null +++ b/custom_components/philips_ambilight_hue/translations/en.json @@ -0,0 +1,28 @@ +{ + "config": { + "abort": { + "already_configured": "Device is already configured" + }, + "error": { + "cannot_connect": "Failed to connect", + "invalid_pin": "Invalid PIN", + "pairing_failure": "Unable to pair: {error_id}", + "unknown": "Unexpected error" + }, + "step": { + "pair": { + "data": { + "pin": "PIN Code" + }, + "description": "Enter the PIN displayed on your TV", + "title": "Pair" + }, + "user": { + "data": { + "api_version": "API Version", + "host": "Host" + } + } + } + } +} \ No newline at end of file diff --git a/custom_components/philips_ambilight_hue/translations/pl.json b/custom_components/philips_ambilight_hue/translations/pl.json new file mode 100644 index 0000000..23b30de --- /dev/null +++ b/custom_components/philips_ambilight_hue/translations/pl.json @@ -0,0 +1,28 @@ +{ + "config": { + "abort": { + "already_configured": "Urz\u0105dzenie jest ju\u017c skonfigurowane" + }, + "error": { + "cannot_connect": "Nie mo\u017cna nawi\u0105za\u0107 po\u0142\u0105czenia", + "invalid_pin": "Nieprawid\u0142owy kod PIN", + "pairing_failure": "Nie mo\u017cna sparowa\u0107: {error_id}", + "unknown": "Nieoczekiwany b\u0142\u0105d" + }, + "step": { + "pair": { + "data": { + "pin": "Kod PIN" + }, + "description": "Wprowad\u017a kod PIN wy\u015bwietlony na Twoim telewizorze", + "title": "Paruj" + }, + "user": { + "data": { + "api_version": "Wersja API", + "host": "Nazwa hosta lub adres IP" + } + } + } + } +} \ No newline at end of file diff --git a/custom_components/philips_ambilight_hue/translations/pt-BR.json b/custom_components/philips_ambilight_hue/translations/pt-BR.json new file mode 100644 index 0000000..b34945b --- /dev/null +++ b/custom_components/philips_ambilight_hue/translations/pt-BR.json @@ -0,0 +1,28 @@ +{ + "config": { + "abort": { + "already_configured": "O dispositivo já está configurado" + }, + "error": { + "cannot_connect": "Falhou ao conectar", + "invalid_pin": "PIN invalido", + "pairing_failure": "Não foi possível parear: {error_id}", + "unknown": "Erro inesperado" + }, + "step": { + "pair": { + "data": { + "pin": "Código PIN" + }, + "description": "Digite o PIN exibido na sua TV", + "title": "Parear" + }, + "user": { + "data": { + "api_version": "Versão da API", + "host": "Host" + } + } + } + } +} \ No newline at end of file diff --git a/hacs.json b/hacs.json new file mode 100644 index 0000000..c6c3032 --- /dev/null +++ b/hacs.json @@ -0,0 +1,4 @@ +{ + "name": "Philips Ambilight+Hue Switch", + "render_readme": true +} diff --git a/info.md b/info.md deleted file mode 100644 index 8871305..0000000 --- a/info.md +++ /dev/null @@ -1,18 +0,0 @@ -# Philips TV Ambilight+Hue (Switch) Component -A Switch component for automating the control of the Ambilight+hue setting on a Philips TV, this reveals the current status of the menu setting to Home Assistant, and allows for remote or automated toggling. -## Configuration - -If you have already set up the Ambilight (Light) component, configuring this component is very simple, enter the same username and password as for the ambilight component in the configuration.yaml, along with the IP of the TV, and restart home assistant: - -If you have not configured any other Philips TV components, use the tool linked in the [Ambilight (Light) component](https://github.com/jomwells/ambilights) GitHub docs to obtain your username and password. -``` -switch: - - platform: philips_ambilight+hue - name: Ambilight+Hue - host: 192.168.1.XXX - username: !secret philips_username - password: !secret philips_password - scan_interval: 5 -``` - -*note:* there is often a noticeable lag between Home Assistant sending the request to toggle the setting, and receiving a status update from the API, for this reason, it is advised that you reduce your `scan_interval` (in seconds) to suit your needs.