Skip to content

Commit

Permalink
Merge pull request #997 from puddly/rc
Browse files Browse the repository at this point in the history
0.47.0 Release
  • Loading branch information
puddly committed Jun 16, 2022
2 parents 41c53fa + b41dcbe commit 4f0604b
Show file tree
Hide file tree
Showing 18 changed files with 1,089 additions and 575 deletions.
10 changes: 5 additions & 5 deletions README.md
Expand Up @@ -3,15 +3,15 @@
[![Build](https://github.com/zigpy/zigpy/workflows/CI/badge.svg?branch=dev)](https://github.com/zigpy/zigpy/workflows/CI/badge.svg?branch=dev)
[![Coverage](https://coveralls.io/repos/github/zigpy/zigpy/badge.svg?branch=dev)](https://coveralls.io/github/zigpy/zigpy?branch=dev)

**[zigpy](https://github.com/zigpy/zigpy)** is **[Zigbee protocol stack](https://en.wikipedia.org/wiki/Zigbee)** integration project to implement the **[Zigbee Home Automation](https://www.zigbee.org/)** standard as a Python 3 library.
**[zigpy](https://github.com/zigpy/zigpy)** is a hardware independent **[Zigbee protocol stack](https://en.wikipedia.org/wiki/Zigbee)** integration project to implement **[Zigbee](https://www.zigbee.org/)** standard specifications as a Python 3 library.

Zigbee Home Automation integration with zigpy allows you to connect one of many off-the-shelf Zigbee adapters using one of the available Zigbee radio library modules compatible with zigpy to control Zigbee based devices. There is currently support for controlling Zigbee device types such as binary sensors (e.g., motion and door sensors), sensors (e.g., temperature sensors), lightbulbs, switches, and fans.
Zigbee integration via zigpy allows you to connect one of many off-the-shelf Zigbee Coordinator adapters using one of the available Zigbee radio library modules compatible with zigpy to control Zigbee based devices. There is currently support for controlling Zigbee device types such as binary sensors (e.g., motion and door sensors), sensors (e.g., temperature sensors), lights, switches, buttons, covers, fans, climate control equipment, locks, and intruder alarm system devices.

Zigbee coordinator hardware from many different hardware manufacturers are supported via radio libraries which translate their proprietary communication protocol into a common API which is shared among all radio libraries for zigpy. If some Zigbee coordinator hardware for other manufacturers is not supported by yet zigpy it is possible for any independent developer to step-up and develop a new radio library for zigpy which translates its proprietary communication protocol into the common API that zigpy can understand.
Zigbee stacks and hardware from many different hardware chip manufacturers are supported via radio libraries which translate their proprietary communication protocol into a common API which is shared among all radio libraries for zigpy. If some Zigbee stack or Zigbee Coordinator hardware for other manufacturers is not supported by yet zigpy it is possible for any independent developer to step-up and develop a new radio library for zigpy which translates its proprietary communication protocol into the common API that zigpy can understand.

zigpy contains common code implementing Zigbee ZCL, ZDO and application state management which is being used by various radio libraries implementing the actual interface with the radio modules from different manufacturers. The separate radio libraries interface with radio hardware adapters/modules over USB and GPIO using different native UART serial protocols.
zigpy contains common code implementing ZCL (Zigbee Cluster Library) and ZDO (Zigbee Device Object) application state management which is being used by various radio libraries implementing the actual interface with the radio modules from different manufacturers. The separate radio libraries interface with radio hardware adapters/modules over USB and GPIO using different native UART serial protocols.

Reference implementation of the zigpy library exist in **[Home Assistant](https://www.home-assistant.io)** (Python based open source home automation software) as part of its **[ZHA integration component](https://www.home-assistant.io/integrations/zha/)**.
The **[ZHA integration component for Home Assistant](https://www.home-assistant.io/integrations/zha/)**, the [Zigbee Plugin for Domoticz](https://www.domoticz.com/wiki/ZigbeeForDomoticz), and the [Zigbee Plugin for Jeedom](https://doc.jeedom.com/en_US/plugins/automation%20protocol/zigbee/) (competing open-source home automation software) are all using [zigpy libraries](https://github.com/zigpy/) as dependencies, as such they could be used as references of different implementations if looking to integrate a Zigbee solution into your application.

### Zigbee device OTA updates

Expand Down
70 changes: 60 additions & 10 deletions tests/conftest.py
@@ -1,5 +1,6 @@
"""Common fixtures."""
import logging
from unittest.mock import patch

import pytest

Expand Down Expand Up @@ -38,12 +39,6 @@ def raise_on_bad_log_formatting():


class App(zigpy.application.ControllerApplication):
async def shutdown(self):
pass

async def startup(self, auto_form=False):
pass

async def request(
self,
device,
Expand All @@ -58,11 +53,60 @@ async def request(
):
pass

async def connect(self):
pass

async def disconnect(self):
pass

async def start_network(self):
pass

async def force_remove(self, dev):
pass

async def add_endpoint(self, descriptor):
pass

async def permit_ncp(self, time_s=60):
pass

async def probe(self, config):
return True
async def broadcast(
self,
profile,
cluster,
src_ep,
dst_ep,
grpid,
radius,
sequence,
data,
broadcast_address,
):
pass

async def mrequest(
self,
group_id,
profile,
cluster,
src_ep,
sequence,
data,
*,
hops=0,
non_member_radius=3,
):
pass

async def permit_with_key(self, node, code, time_s=60):
pass

async def write_network_info(self, *, network_info, node_info):
pass

async def load_network_info(self, *, load_devices=False):
pass


@pytest.fixture
Expand All @@ -72,8 +116,14 @@ def app_mock():
config = App.SCHEMA(
{CONF_DATABASE: None, CONF_DEVICE: {CONF_DEVICE_PATH: "/dev/null"}}
)
app_mock = MagicMock(spec_set=App(config))
app_mock.state.node_information = app_state.NodeInfo(

app = App(config)

# Accessing the property fails when the mock's `spec_set` is being created
with patch.object(app, "devices"):
app_mock = MagicMock(spec_set=app)

app_mock.state.node_info = app_state.NodeInfo(
t.NWK(0x0000), ieee=NCP_IEEE, logical_type=zdo_t.LogicalType.Coordinator
)
return app_mock
82 changes: 82 additions & 0 deletions tests/test_app_state.py
Expand Up @@ -3,6 +3,8 @@
import pytest

import zigpy.state as app_state
import zigpy.types as t
import zigpy.zdo.types as zdo_t

COUNTER_NAMES = ["counter_1", "counter_2", "some random name"]

Expand Down Expand Up @@ -210,3 +212,83 @@ def test_counter_groups():

new_groups = [group for group in groups]
assert new_groups == [counter_group]


@pytest.fixture
def node_info():
return app_state.NodeInfo(
nwk=t.NWK(0x0000),
ieee=t.EUI64.convert("93:2C:A9:34:D9:D0:5D:12"),
logical_type=zdo_t.LogicalType.Coordinator,
)


@pytest.fixture
def network_info(node_info):
return app_state.NetworkInfo(
extended_pan_id=t.ExtendedPanId.convert("0D:49:91:99:AE:CD:3C:35"),
pan_id=t.PanId(0x9BB0),
nwk_update_id=0x12,
nwk_manager_id=t.NWK(0x0000),
channel=t.uint8_t(15),
channel_mask=t.Channels.from_channel_list([15, 20, 25]),
security_level=t.uint8_t(5),
network_key=app_state.Key(
key=t.KeyData.convert("9A:79:D6:9A:DA:EC:45:C6:F2:EF:EB:AF:DA:A3:07:B6"),
seq=108,
tx_counter=39009277,
),
tc_link_key=app_state.Key(
key=t.KeyData(b"ZigBeeAlliance09"),
partner_ieee=node_info.ieee,
tx_counter=8712428,
),
key_table=[
app_state.Key(
key=t.KeyData.convert(
"85:7C:05:00:3E:76:1A:F9:68:9A:49:41:6A:60:5C:76"
),
tx_counter=3792973670,
rx_counter=1083290572,
seq=147,
partner_ieee=t.EUI64.convert("69:0C:07:52:AA:D7:7D:71"),
),
app_state.Key(
key=t.KeyData.convert(
"CA:02:E8:BB:75:7C:94:F8:93:39:D3:9C:B3:CD:A7:BE"
),
tx_counter=2597245184,
rx_counter=824424412,
seq=19,
partner_ieee=t.EUI64.convert("A3:1A:F6:8E:19:95:23:BE"),
),
],
children=[
# Has a key
t.EUI64.convert("A3:1A:F6:8E:19:95:23:BE"),
# Does not have a key
t.EUI64.convert("C6:DF:28:F9:60:33:DB:03"),
],
# If exposed by the stack, NWK addresses of other connected devices on the network
nwk_addresses={
# Two children above
t.EUI64.convert("A3:1A:F6:8E:19:95:23:BE"): t.NWK(0x2C59),
t.EUI64.convert("C6:DF:28:F9:60:33:DB:03"): t.NWK(0x1CA0),
# Random devices on the network
t.EUI64.convert("7A:BF:38:A9:59:21:A0:7A"): t.NWK(0x16B5),
t.EUI64.convert("10:55:FE:67:24:EA:96:D3"): t.NWK(0xBFB9),
t.EUI64.convert("9A:0E:10:50:00:1B:1A:5F"): t.NWK(0x1AF6),
},
stack_specific={"zstack": {"tclk_seed": "71e31105bb92a2d15747a0d0a042dbfd"}},
metadata={"zstack": {"version": "20220102"}},
)


def test_state_backup_restore_unchanged(network_info, node_info):
obj = app_state.network_state_to_json(
network_info=network_info, node_info=node_info
)
network_info2, node_info2 = app_state.json_to_network_state(obj)

assert node_info == node_info2
assert network_info == network_info2

0 comments on commit 4f0604b

Please sign in to comment.