From ccb5c42a75104a6584c57528a2e403d6610536b4 Mon Sep 17 00:00:00 2001 From: umu <46300268+xZetsubou@users.noreply.github.com> Date: Thu, 21 Sep 2023 10:40:18 +0300 Subject: [PATCH] Add an events to HA (#28) * add an events to ha Fire an events in HA when something happen to the device * typo event name * Adjust: moves event handler to TuyaDevice instance Calling the event in entity instance will trigger the same event as many entitles we have * Optimize events to trigger correctly. Check for `old_states` because if it doesn't exists that mean the device is Initializing we can use this when devices initialized if we want, * device triggered event will fire even if states change. * fix device_triggered event * Add dp trigger event * store dispatched dp to trigger an event. * change the returns of returns of dp_triggered * check if dps in payload before add [safety] * Update README.md * add templates guide to readme * check interface before detect dispatched dps --- README.md | 16 +++++--- custom_components/localtuya/common.py | 39 +++++++++++++++++++ .../localtuya/pytuya/__init__.py | 4 ++ 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d28b1f1e4..0c2d1f0b6 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ A Home Assistant custom Integration for local handling of Tuya-based devices. * [Adding the Integration](#adding-the-integration) * [Integration Options](#integration-options) * [Add Devices](#add-devices) + * [Templates](https://github.com/xZetsubou/hass-localtuya/discussions/13) - [Debugging](#debugging) - [Notes](#notes) - [Credits](#credits) @@ -161,11 +162,10 @@ data: +## Debugging
Debugging

-# Debugging - Whenever you write a bug report, it helps tremendously if you include debug logs directly (otherwise we will just ask for them and it will take longer). So please enable debug logs like this and include them in your issue: ```yaml @@ -194,15 +194,19 @@ The Cloud API account configuration is not mandatory (LocalTuya can work also wi # Credits: -NameLessJedi https://github.com/NameLessJedi/localtuya-homeassistant and mileperhour https://github.com/mileperhour/localtuya-homeassistant being the major sources of inspiration, and whose code for switches is substantially unchanged. +[Rospogrigio](https://github.com/rospogrigio), The original maintainer of localtuya. this fork made when upstream version was `v5.2.1` + +[NameLessJedi](https://github.com/NameLessJedi/localtuya-homeassistant) and [mileperhour](https://github.com/mileperhour/localtuya-homeassistant) being the major sources of inspiration, and whose code for switches is substantially unchanged. -TradeFace, for being the only one to provide the correct code for communication with the cover (in particular, the 0x0d command for the status instead of the 0x0a, and related needs such as double reply to be received): https://github.com/TradeFace/tuya/ +[TradeFace](https://github.com/TradeFace/tuya/), for being the only one to provide the correct code for communication with the cover (in particular, the 0x0d command for the status instead of the 0x0a, and related needs such as double reply to be received): sean6541, for the working (standard) Python Handler for Tuya devices. -jasonacox, for the TinyTuya project from where I could import the code to communicate with devices using protocol 3.4. +[jasonacox](https://github.com/jasonacox), for the TinyTuya project from where I big help and refrences to upgrade integration. + +[uzlonewolf](https://github.com/uzlonewolf), for maintaining in TinyTuya who improved the tool so much and introduce new features like new protocols etc.. postlund, for the ideas, for coding 95% of the refactoring and boosting the quality of this repo to levels hard to imagine (by me, at least) and teaching me A LOT of how things work in Home Assistant.

-
\ No newline at end of file + diff --git a/custom_components/localtuya/common.py b/custom_components/localtuya/common.py index 0d6ed94b8..23ef1b854 100644 --- a/custom_components/localtuya/common.py +++ b/custom_components/localtuya/common.py @@ -19,6 +19,7 @@ STATE_UNKNOWN, CONF_ENTITY_CATEGORY, EntityCategory, + CONF_TYPE, ) from homeassistant.core import callback from homeassistant.helpers.dispatcher import ( @@ -360,6 +361,7 @@ async def set_dps(self, states): @callback def status_updated(self, status): """Device updated status.""" + self._handle_event(self._status, status) self._status.update(status) self._dispatch_status() @@ -367,6 +369,43 @@ def _dispatch_status(self): signal = f"localtuya_{self._dev_config_entry[CONF_DEVICE_ID]}" async_dispatcher_send(self._hass, signal, self._status) + def _handle_event(self, old_status, new_status): + """Handle events in HA when devices updated.""" + + def fire_event(event, data: dict): + event_data = { + CONF_DEVICE_ID: self._dev_config_entry[CONF_DEVICE_ID], + CONF_TYPE: event, + } + event_data.update(data) + # Send an event with status, The default length of event without data is 2. + if len(event_data) > 2: + self._hass.bus.async_fire(f"localtuya_{event}", event_data) + + event = "states_update" + device_triggered = "device_triggered" + device_dp_triggered = "device_dp_triggered" + + # Device Initializing. if not old_states. + # States update event. + if old_status and old_status != new_status: + data = {"old_states": old_status, "new_states": new_status} + fire_event(event, data) + + # Device triggered event. + if old_status and new_status is not None: + event = device_triggered + data = {CONF_TYPE: event, "states": new_status} + fire_event(event, data) + + if self._interface is not None: + if len(self._interface.dispatched_dps) == 1: + event = device_dp_triggered + dp_trigger = list(self._interface.dispatched_dps)[0] + dp_value = self._interface.dispatched_dps.get(dp_trigger) + data = {CONF_TYPE: event, "dp": dp_trigger, "value": dp_value} + fire_event(event, data) + @callback def disconnected(self): """Device disconnected.""" diff --git a/custom_components/localtuya/pytuya/__init__.py b/custom_components/localtuya/pytuya/__init__.py index 5dea6b609..8154c219f 100644 --- a/custom_components/localtuya/pytuya/__init__.py +++ b/custom_components/localtuya/pytuya/__init__.py @@ -783,6 +783,7 @@ def __init__( self.local_nonce = b"0123456789abcdef" # not-so-random random key self.remote_nonce = b"" self.dps_whitelist = UPDATE_DPS_WHITELIST + self.dispatched_dps = {} # Store payload so we can trigger an event in HA. def set_version(self, protocol_version): """Set the device version and eventually start available DPs detection.""" @@ -1188,6 +1189,9 @@ def _decode_payload(self, payload): ): json_payload["dps"] = json_payload["data"]["dps"] + # We will store the payload to trigger an event in HA. + if "dps" in json_payload: + self.dispatched_dps = json_payload["dps"] return json_payload async def _negotiate_session_key(self):