Skip to content

Commit

Permalink
Add an events to HA (#28)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
xZetsubou authored Sep 21, 2023
1 parent 363f3bc commit ccb5c42
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 6 deletions.
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -161,11 +162,10 @@ data:
</details>
## Debugging
<details><summary>Debugging</summary>
<p>
# 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
Expand Down Expand Up @@ -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.

</p>
</details>
</details>
39 changes: 39 additions & 0 deletions custom_components/localtuya/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
STATE_UNKNOWN,
CONF_ENTITY_CATEGORY,
EntityCategory,
CONF_TYPE,
)
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import (
Expand Down Expand Up @@ -360,13 +361,51 @@ 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()

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."""
Expand Down
4 changes: 4 additions & 0 deletions custom_components/localtuya/pytuya/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down Expand Up @@ -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):
Expand Down

0 comments on commit ccb5c42

Please sign in to comment.