diff --git a/.releaserc.json b/.releaserc.json index f9da5eb..bee7b8c 100644 --- a/.releaserc.json +++ b/.releaserc.json @@ -12,9 +12,7 @@ "type": "breaking", "release": "major" }, - { "scope": "ci", - "release": false - } + { "scope": "ci", "release": false } ] } ], diff --git a/README.md b/README.md index c2a532f..9172c4d 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Please help me to complete the [new roadmap](https://github.com/petretiandrea/ho ### Tapo protocol -Tapo is updating it's devices with a new firmware which use a new protocol called KLAP. This integration support it's but if you running older version your devices maybe cannot works. So please keep this integration up to date by using HACS! +Tapo is updating its devices with a new firmware which use a new protocol called KLAP. This integration support it's but if you running older version your devices maybe cannot works. So please keep this integration up to date by using HACS! ### Local Integration @@ -38,24 +38,39 @@ For some unknown reason email with capital letter thrown an "Invalid authenticat The integration now supports native tapo discovery! To enable it you must add at least one tapo device or this line to your tapo configuration file -``` +```yaml tapo: + discovery: true # you can omit "discovery" by default, with "tapo:" it will enable discovery automatically. ``` This will enable tapo device discovery. Not all tapo devices supports tapo discovery, so if you not find it, try adding manually. Also tapo integration discovery filters out not supported devices! +
+ Screenshot + ![Discovery](./docs/discovery-devices.png) + +
+ +You can disable integration discovery by editing `configuration.yaml` in the following way: + +```yaml +tapo: + discovery: false +``` + #### Device IP Tracking -By using DHCP home assistant discovery the feature of mac tracking is now disabled, cause HA can track it automatically now, please be sure -to have DHCP discovery not disable on your `configuration.yaml` (by default is active). +By using DHCP home assistant discovery the feature of mac tracking is now disabled, cause HA can track it automatically now. +Please be sure to have DHCP discovery not disabled on your `configuration.yaml` (by default is active). [BREAKING] Tracking mac address feature is now disabled cause not recommended by HA. The tracking is now performed by HA itself. ### Supported devices - [x] pure async home assistant's method -- [x] support for tapo `H100` hub and siren, `H200` +- [x] support for tapo `H100` hub and siren +- [ ] support for tapo `H100` hub is currently Work In Progress! - [x] support for `T31x` temperature and humidity sensor hub's device - [x] support for `T100` motion sensor hub's device - [x] support for `T110` smart door hub's device @@ -79,31 +94,13 @@ to have DHCP discovery not disable on your `configuration.yaml` (by default is a # How to install -## Simplest and recomended way - This integration is part of HACS store, so you don't need anymore to add this repository as a custom repository. You can find it directly on HACS Store: search for `tapo` and you will find `Tapo Controller`. (**HACS >= 1.6.0 is required**) -## Old way as a custom repository (not recomended, but use if you want to use beta versions) - -1. Install from HACS, add this repository as custom repository -2. Search into HACS store the tapo integration and install -3. Full restart of home assistant is recomended - This video show installation steps: [![Install Steps](http://img.youtube.com/vi/KSYldphgE5A/0.jpg)](https://youtu.be/KSYldphgE5A) -## "Manual" way - -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 `tapo`. -4. Download _all_ the files from the `custom_components/tapo/` directory (folder) in this repository. -5. Place the files you downloaded in the new directory (folder) you created. -6. Restart Home Assistant -7. In the HA UI go to "Configuration" -> "Integrations" click "+" and search for "tapo" - # How to add a Tapo device (after installing the integration) ## Using UI @@ -123,6 +120,14 @@ This video show installation steps: The latest version of this integration remove configuration.yaml device configuration support. This is due to follow home assistant best practices https://developers.home-assistant.io/docs/configuration_yaml_index/ and https://github.com/home-assistant/architecture/blob/master/adr/0010-integration-configuration.md#decision +## Beta versions + +To access to beta version, you must install it as custom + +1. Install from HACS, add this repository as custom repository +2. Search into HACS store the tapo integration and install +3. Full restart of home assistant is recommended + ## Contributions are welcome! Open a pull request, every contribution are welcome. diff --git a/custom_components/tapo/__init__.py b/custom_components/tapo/__init__.py index d53bcbf..2d0c049 100755 --- a/custom_components/tapo/__init__.py +++ b/custom_components/tapo/__init__.py @@ -25,6 +25,7 @@ from .const import CONF_HOST from .const import CONF_MAC from .const import DEFAULT_POLLING_RATE_S +from .const import DISCOVERY_FEATURE_FLAG from .const import DISCOVERY_INTERVAL from .const import DOMAIN from .const import HUB_PLATFORMS @@ -36,15 +37,19 @@ async def async_setup(hass: HomeAssistant, config: dict): """Set up the tapo_p100 component.""" hass.data.setdefault(DOMAIN, {}) + domain_config = config.get(DOMAIN, {}) + discovery_enabled = domain_config.get(DISCOVERY_FEATURE_FLAG, True) + if discovery_enabled: - async def _start_discovery(_: Any = None) -> None: - if device_found := await discovery_tapo_devices(hass): - async_create_discovery_flow(hass, device_found) + async def _start_discovery(_: Any = None) -> None: + if device_found := await discovery_tapo_devices(hass): + async_create_discovery_flow(hass, device_found) + + hass.async_create_background_task(_start_discovery(), "Initial tapo discovery") + async_track_time_interval( + hass, _start_discovery, DISCOVERY_INTERVAL, cancel_on_shutdown=True + ) - hass.async_create_background_task(_start_discovery(), "Initial tapo discovery") - async_track_time_interval( - hass, _start_discovery, DISCOVERY_INTERVAL, cancel_on_shutdown=True - ) return True diff --git a/custom_components/tapo/const.py b/custom_components/tapo/const.py index 1c90cfd..3651b89 100755 --- a/custom_components/tapo/const.py +++ b/custom_components/tapo/const.py @@ -14,6 +14,7 @@ DOMAIN = "tapo" VERSION = "2.13.0" +DISCOVERY_FEATURE_FLAG = "discovery" DISCOVERY_INTERVAL = timedelta(minutes=10) DISCOVERY_TIMEOUT = 5 diff --git a/custom_components/tapo/coordinators.py b/custom_components/tapo/coordinators.py index bb5ccb7..fab22f4 100644 --- a/custom_components/tapo/coordinators.py +++ b/custom_components/tapo/coordinators.py @@ -47,7 +47,7 @@ @dataclass class HassTapoDeviceData: - coordinator: "TapoDataCoordinator" + coordinator: "TapoDeviceCoordinator" config_entry_update_unsub: CALLBACK_TYPE child_coordinators: List["TapoDataCoordinator"] @@ -89,7 +89,7 @@ def __init__( ), ) self._states: StateMap = {} - self.components: Components = None + self.components: Components | None = None async def _negotiate_components_if_needed(self): if self.components is None: @@ -130,19 +130,12 @@ async def _async_update_data(self) -> StateMap: await self._negotiate_components_if_needed() return await self._update_state() except TapoException as error: - self._raise_from_tapo_exception(error) + _raise_from_tapo_exception(error) except aiohttp.ClientError as error: raise UpdateFailed(f"Error communication with API: {str(error)}") from error except Exception as exception: raise UpdateFailed(f"Unexpected exception: {str(exception)}") from exception - def _raise_from_tapo_exception(self, exception: TapoException): - _LOGGER.error("Tapo exception: %s", str(exception)) - if exception.error_code == TapoError.INVALID_CREDENTIAL.value: - raise ConfigEntryAuthFailed from exception - else: - raise UpdateFailed(f"Error tapo exception: {exception}") from exception - PowerStripChildrenState = dict[str, PowerStripChild] @@ -174,3 +167,11 @@ async def _update_state(self): ): children_state = (await self.device.get_children()).get_or_raise() self.update_state_of(PowerStripChildrenState, children_state) + + +def _raise_from_tapo_exception(exception: TapoException): + _LOGGER.error("Tapo exception: %s", str(exception)) + if exception.error_code == TapoError.INVALID_CREDENTIAL.value: + raise ConfigEntryAuthFailed from exception + else: + raise UpdateFailed(f"Error tapo exception: {exception}") from exception diff --git a/custom_components/tapo/light.py b/custom_components/tapo/light.py index a6d1c44..4087165 100755 --- a/custom_components/tapo/light.py +++ b/custom_components/tapo/light.py @@ -216,7 +216,7 @@ async def _change_brightness(self, new_brightness, apply_to_effect: str = None): ).get_or_raise() -def _components_to_color_modes(components: Components): +def _components_to_color_modes(components: Components) -> set[ColorMode]: color_modes = [ColorMode.ONOFF] if components.has(Component.COLOR_TEMPERATURE.value): color_modes.append(ColorMode.COLOR_TEMP) @@ -224,7 +224,7 @@ def _components_to_color_modes(components: Components): color_modes.append(ColorMode.BRIGHTNESS) if components.has(Component.COLOR.value): color_modes.append(ColorMode.HS) - return color_modes + return set(color_modes) def _components_to_light_effects(components: Components): diff --git a/custom_components/tapo/setup_helpers.py b/custom_components/tapo/setup_helpers.py index 85e65ca..232de57 100644 --- a/custom_components/tapo/setup_helpers.py +++ b/custom_components/tapo/setup_helpers.py @@ -31,5 +31,5 @@ async def create_api_from_config( def get_host_port(host_user_input: str) -> (str, int): if ":" in host_user_input: parts = host_user_input.split(":", 1) - return (parts[0], int(parts[1])) - return (host_user_input, 80) + return parts[0], int(parts[1]) + return host_user_input, 80 diff --git a/docs/discovery-devices.png b/docs/discovery-devices.png new file mode 100644 index 0000000..8df72f3 Binary files /dev/null and b/docs/discovery-devices.png differ