-
Notifications
You must be signed in to change notification settings - Fork 687
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
32 changed files
with
416 additions
and
102 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,42 @@ | ||
## Initial Contribution Guidelines - WIP | ||
# Initial Contribution Guidelines - WIP | ||
|
||
- Capture the SimpleDescriptor log entries for each endpoint on the device. These can be found in the HA logs after joining a device and they look like this: `<SimpleDescriptor endpoint=1 profile=260 device_type=1026 device_version=0 input_clusters=[0, 1, 3, 32, 1026, 1280, 2821] output_clusters=[25]>`. This information can also be obtained from the zigbee.db if you want to take the time to query the tables and reconstitute the log entry. I find it easier to just remove and rejoin the device. ZHA entity ids are stable for the most part so it *shouldn't* disrupt anything you have configured. These need to match what the device reports EXACTLY or zigpy will not match them when a device joins and the handler will not be used for the device. | ||
- All code is formatted with black. The check format script that runs in CI will ensure that code meets this requirement and that it is correctly formatted with black. Instructions for installing black in many editors can be found here: <https://github.com/psf/black#editor-integration> | ||
|
||
- Capture the SimpleDescriptor log entries for each endpoint on the device. These can be found in the HA logs after joining a device and they look like this: `<SimpleDescriptor endpoint=1 profile=260 device_type=1026 device_version=0 input_clusters=[0, 1, 3, 32, 1026, 1280, 2821] output_clusters=[25]>`. This information can also be obtained from the zigbee.db if you want to take the time to query the tables and reconstitute the log entry. I find it easier to just remove and rejoin the device. ZHA entity ids are stable for the most part so it _shouldn't_ disrupt anything you have configured. These need to match what the device reports EXACTLY or zigpy will not match them when a device joins and the handler will not be used for the device. | ||
|
||
- Create a device class extending CustomDevice or a derivitave of it | ||
|
||
- Use an existing handler as a guide. signature and replacement dicts are required. Include the SimpleDescriptor entry for each endpoint in the signature dict above the definition of the endpoint in this format: | ||
- All custom cluster definitions must extend CustomCluster | ||
|
||
- Use an existing handler as a guide. signature and replacement dicts are required. Include the SimpleDescriptor entry for each endpoint in the signature dict above the definition of the endpoint in this format: | ||
|
||
```yaml | ||
# <SimpleDescriptor endpoint=1 profile=260 device_type=1026 | ||
# device_version=0 | ||
# input_clusters=[0, 1, 3, 32, 1026, 1280, 2821] | ||
# output_clusters=[25]> | ||
``` | ||
|
||
- Use constants for all attribute values referencing the appropriate labels from Zigpy / HA as necessary | ||
|
||
- how `device_automation_triggers` work: | ||
|
||
Device automation triggers are essentially representations of the events that the devices fire in HA. They allow users to use actions in the UI instead of using the raw events. Ex: For the Hue remote - the on button fires this event: | ||
|
||
`<Event zha_event[L]: unique_id=00:17:88:01:04:e7:f9:37:1:0x0006, device_ieee=00:17:88:01:04:e7:f9:37, endpoint_id=1, cluster_id=6, command=on, args=[]>` | ||
|
||
and the action defined for this is: | ||
|
||
`(SHORT_PRESS, TURN_ON): {COMMAND: COMMAND_ON}` | ||
|
||
The first part `(SHORT_PRESS, TURN_ON)` corresponds to the txt the user will see in the UI: | ||
|
||
```yaml | ||
<img width="620" alt="image" src="https://user-images.githubusercontent.com/1335687/73609115-76480b80-4598-11ea-97eb-8d8343e2355b.png"> | ||
|
||
# <SimpleDescriptor endpoint=1 profile=260 device_type=1026 | ||
# device_version=0 | ||
# input_clusters=[0, 1, 3, 32, 1026, 1280, 2821] | ||
# output_clusters=[25]> | ||
The second part is the event data. You only need to supply enough of the event data to uniquely match the event which in this case is just the command for this event fired by this device: `{COMMAND: COMMAND_ON}` | ||
|
||
``` | ||
If you look at another example for the same device: | ||
|
||
- manufacturer and model are required on EVERY replacement endpoint definition and they NEED to match what the device reports to HA. | ||
`(SHORT_PRESS, DIM_UP): {COMMAND: COMMAND_STEP, CLUSTER_ID: 8, ENDPOINT_ID: 1, ARGS: [0, 30, 9],}` | ||
|
||
- Use constants for all attribute values referencing the appropriate labels from Zigpy / HA as necessary | ||
you can see a pattern that illustrates how to match a more complex event. In this case the step command is used for the dim up and dim down buttons so we need to match more of the event data to uniquely match the event. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,20 @@ | ||
# Contributors | ||
- [David F. Mulcahey] (https://github.com/dmulcahey) | ||
- [roblandry] (https://github.com/roblandry) | ||
- [presslab-us] (https://github.com/presslab-us) | ||
- [Alexei Chetroi] (https://github.com/Adminiuga) | ||
- [Abílio Costa] (https://github.com/abmantis) | ||
- [Andreas Setterlind] (https://github.com/Gamester17) | ||
- [prairiesnpr] (https://github.com/prairiesnpr) | ||
- [Daniel Lashua] (https://github.com/dlashua) | ||
- [bballwiz5] (https://github.com/bballwiz5) | ||
- [Ross Patterson] (https://github.com/rpatterson) | ||
- [Marc Egli] (https://github.com/frog32) | ||
- [Dinko Bajric] (https://github.com/dbajric) | ||
- [brg468] (https://github.com/brg468) | ||
- [James Riley] (https://github.com/Thalagyrt) | ||
- [Shulyaka] (https://github.com/Shulyaka) | ||
- [Nemesis24] (https://github.com/Nemesis24) | ||
|
||
- [David F. Mulcahey](https://github.com/dmulcahey) | ||
- [roblandry](https://github.com/roblandry) | ||
- [presslab-us](https://github.com/presslab-us) | ||
- [Alexei Chetroi](https://github.com/Adminiuga) | ||
- [Abílio Costa](https://github.com/abmantis) | ||
- [Andreas Setterlind](https://github.com/Gamester17) | ||
- [prairiesnpr](https://github.com/prairiesnpr) | ||
- [Daniel Lashua](https://github.com/dlashua) | ||
- [bballwiz5](https://github.com/bballwiz5) | ||
- [Ross Patterson](https://github.com/rpatterson) | ||
- [Marc Egli](https://github.com/frog32) | ||
- [Dinko Bajric](https://github.com/dbajric) | ||
- [brg468](https://github.com/brg468) | ||
- [James Riley](https://github.com/Thalagyrt) | ||
- [Shulyaka](https://github.com/Shulyaka) | ||
- [Nemesis24](https://github.com/Nemesis24) | ||
- [Andy Zickler](https://github.com/andyzickler) | ||
- [Piotr Majkrzak](https://github.com/majkrzak) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
|
||
from setuptools import find_packages, setup | ||
|
||
VERSION = "0.0.32" | ||
VERSION = "0.0.33" | ||
|
||
|
||
def readme(): | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
"""Konke sensors.""" | ||
|
||
import asyncio | ||
|
||
from zigpy.quirks import CustomCluster | ||
from zigpy.zcl.clusters.measurement import OccupancySensing | ||
from zigpy.zcl.clusters.security import IasZone | ||
|
||
from .. import LocalDataCluster | ||
from ..const import CLUSTER_COMMAND, OFF, ON, ZONE_STATE | ||
|
||
KONKE = "Konke" | ||
OCCUPANCY_STATE = 0 | ||
OCCUPANCY_EVENT = "occupancy_event" | ||
MOTION_TYPE = 0x000D | ||
ZONE_TYPE = 0x0001 | ||
|
||
MOTION_TIME = 60 | ||
OCCUPANCY_TIME = 600 | ||
|
||
|
||
class OccupancyCluster(LocalDataCluster, OccupancySensing): | ||
"""Occupancy cluster.""" | ||
|
||
cluster_id = OccupancySensing.cluster_id | ||
|
||
def __init__(self, *args, **kwargs): | ||
"""Init.""" | ||
super().__init__(*args, **kwargs) | ||
self._timer_handle = None | ||
self.endpoint.device.occupancy_bus.add_listener(self) | ||
|
||
def occupancy_event(self): | ||
"""Occupancy event.""" | ||
self._update_attribute(OCCUPANCY_STATE, ON) | ||
|
||
if self._timer_handle: | ||
self._timer_handle.cancel() | ||
|
||
loop = asyncio.get_event_loop() | ||
self._timer_handle = loop.call_later(OCCUPANCY_TIME, self._turn_off) | ||
|
||
def _turn_off(self): | ||
self._timer_handle = None | ||
self._update_attribute(OCCUPANCY_STATE, OFF) | ||
|
||
|
||
class MotionCluster(CustomCluster, IasZone): | ||
"""Motion cluster.""" | ||
|
||
cluster_id = IasZone.cluster_id | ||
|
||
def __init__(self, *args, **kwargs): | ||
"""Init.""" | ||
super().__init__(*args, **kwargs) | ||
self._timer_handle = None | ||
|
||
def handle_cluster_request(self, tsn, command_id, args): | ||
"""Handle the cluster command.""" | ||
if command_id == 0: | ||
if self._timer_handle: | ||
self._timer_handle.cancel() | ||
loop = asyncio.get_event_loop() | ||
self._timer_handle = loop.call_later(MOTION_TIME, self._turn_off) | ||
self.endpoint.device.occupancy_bus.listener_event(OCCUPANCY_EVENT) | ||
|
||
def _turn_off(self): | ||
self._timer_handle = None | ||
self.listener_event(CLUSTER_COMMAND, 999, 0, [0, 0, 0, 0]) | ||
self._update_attribute(ZONE_STATE, OFF) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
"""Konke motion sensor.""" | ||
|
||
from zigpy.profiles import zha | ||
from zigpy.quirks import CustomDevice | ||
from zigpy.zcl.clusters.general import Basic, Identify, PowerConfiguration | ||
from zigpy.zcl.clusters.security import IasZone | ||
|
||
from . import KONKE, MotionCluster, OccupancyCluster | ||
from .. import Bus | ||
from ..const import ( | ||
DEVICE_TYPE, | ||
ENDPOINTS, | ||
INPUT_CLUSTERS, | ||
MODELS_INFO, | ||
OUTPUT_CLUSTERS, | ||
PROFILE_ID, | ||
) | ||
|
||
KONKE_CLUSTER_ID = 0xFCC0 | ||
|
||
|
||
class KonkeMotion(CustomDevice): | ||
"""Custom device representing konke motion sensors.""" | ||
|
||
def __init__(self, *args, **kwargs): | ||
"""Init.""" | ||
self.occupancy_bus = Bus() | ||
super().__init__(*args, **kwargs) | ||
|
||
signature = { | ||
# <SimpleDescriptor endpoint=1 profile=260 device_type=1026 | ||
# device_version=0 | ||
# input_clusters=[0, 1, 3, 1280, 64704] | ||
# output_clusters=[3, 64704]> | ||
MODELS_INFO: [ | ||
(KONKE, "3AFE28010402000D"), | ||
(KONKE, "3AFE14010402000D"), | ||
(KONKE, "3AFE27010402000D"), | ||
], | ||
ENDPOINTS: { | ||
1: { | ||
PROFILE_ID: zha.PROFILE_ID, | ||
DEVICE_TYPE: zha.DeviceType.IAS_ZONE, | ||
INPUT_CLUSTERS: [ | ||
Basic.cluster_id, | ||
PowerConfiguration.cluster_id, | ||
Identify.cluster_id, | ||
IasZone.cluster_id, | ||
KONKE_CLUSTER_ID, | ||
], | ||
OUTPUT_CLUSTERS: [Identify.cluster_id, KONKE_CLUSTER_ID], | ||
} | ||
}, | ||
} | ||
|
||
replacement = { | ||
ENDPOINTS: { | ||
1: { | ||
INPUT_CLUSTERS: [ | ||
Basic.cluster_id, | ||
PowerConfiguration.cluster_id, | ||
Identify.cluster_id, | ||
OccupancyCluster, | ||
MotionCluster, | ||
KONKE_CLUSTER_ID, | ||
], | ||
OUTPUT_CLUSTERS: [Identify.cluster_id, KONKE_CLUSTER_ID], | ||
} | ||
} | ||
} |
Oops, something went wrong.