From 69162deb67e7039179f994b9318a6d0fecfe4e7a Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 15 Apr 2020 18:15:41 -0400 Subject: [PATCH 01/20] 0.17.0.dev0 version bump. --- bellows/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bellows/__init__.py b/bellows/__init__.py index 6f95f50f..9a483f95 100644 --- a/bellows/__init__.py +++ b/bellows/__init__.py @@ -1,5 +1,5 @@ MAJOR_VERSION = 0 -MINOR_VERSION = 16 -PATCH_VERSION = "a2" +MINOR_VERSION = 17 +PATCH_VERSION = "0.dev0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 483fecdebbe7be180b7b8ac7e626218a51f2d785 Mon Sep 17 00:00:00 2001 From: Hedda Date: Tue, 21 Apr 2020 21:54:14 +0200 Subject: [PATCH 02/20] Update README.md with more links to reference documentation (#248) Update README.md with more links to reference documentation --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c7a6cd42..ef64c842 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,8 @@ Packages of tagged versions are also released via PyPI https://www.silabs.com/Support%20Documents/TechnicalDocs/UG101.pdf * EZSP Reference Guide: http://www.silabs.com/Support%20Documents/TechnicalDocs/UG100-EZSPReferenceGuide.pdf + * EZSP UART Host Interfacing Reference Guide: https://www.silabs.com/documents/public/application-notes/an706-ezsp-uart-host-interfacing-guide.pdf + * Silicon Labs forum https://www.silabs.com/community/wireless/zigbee-and-thread/forum ## How to contribute From 3d98bab19140cb48f749bd9f9ef75ece8e0965f8 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 21 Apr 2020 17:54:03 -0400 Subject: [PATCH 03/20] Add "bootloader" CLI command (#249) * Add boot-loader CLI command --- bellows/cli/ncp.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/bellows/cli/ncp.py b/bellows/cli/ncp.py index 3bdf258b..ac487a41 100644 --- a/bellows/cli/ncp.py +++ b/bellows/cli/ncp.py @@ -79,3 +79,31 @@ async def info(ctx): click.echo(v) s.close() + + +@main.command() +@click.pass_context +@util.background +async def bootloader(ctx): + """Start bootloader""" + + ezsp = await util.setup(ctx.obj["device"], ctx.obj["baudrate"], configure=False) + version, plat, micro, phy = await ezsp.getStandaloneBootloaderVersionPlatMicroPhy() + if version == 0xFFFF: + click.echo("No boot loader installed") + ezsp.close() + return + + click.echo( + ( + f"bootloader version: 0x{version:04x}, nodePlat: 0x{plat:02x}, " + f"nodeMicro: 0x{micro:02x}, nodePhy: 0x{phy:02x}" + ) + ) + + res = await ezsp.launchStandaloneBootloader(0x00) + if res[0] != t.EmberStatus.SUCCESS: + click.echo(f"Couldn't launch bootloader: {res[0]}") + else: + click.echo("bootloader launched successfully") + ezsp.close() From 106758f03457d398740fe04b7b2b2df52d37cd0a Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 21 Apr 2020 19:13:02 -0400 Subject: [PATCH 04/20] Add probe() method to ControllerApplication class (#250) --- bellows/zigbee/application.py | 1 + tests/test_application.py | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/bellows/zigbee/application.py b/bellows/zigbee/application.py index 8005f0ed..d93b8b7d 100644 --- a/bellows/zigbee/application.py +++ b/bellows/zigbee/application.py @@ -33,6 +33,7 @@ class ControllerApplication(zigpy.application.ControllerApplication): direct = t.EmberOutgoingMessageType.OUTGOING_DIRECT + probe = bellows.ezsp.EZSP.probe SCHEMA = CONFIG_SCHEMA def __init__(self, config: Dict): diff --git a/tests/test_application.py b/tests/test_application.py index c59e34c6..b396d872 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -4,8 +4,9 @@ from asynctest import CoroutineMock, mock import bellows.config as config from bellows.exception import ControllerError, EzspError -import bellows.ezsp +import bellows.ezsp as ezsp import bellows.types as t +import bellows.uart as uart import bellows.zigbee.application import pytest import zigpy.config @@ -1034,3 +1035,27 @@ def test_src_rtg_config(config, result): ) ctrl = bellows.zigbee.application.ControllerApplication(config=app_cfg) assert ctrl.use_source_routing is result + + +@pytest.mark.asyncio +@mock.patch.object(ezsp.EZSP, "reset", new_callable=CoroutineMock) +@mock.patch.object(uart, "connect") +async def test_probe_success(mock_connect, mock_reset): + """Test device probing.""" + + res = await ezsp.EZSP.probe(APP_CONFIG[config.CONF_DEVICE]) + assert res is True + assert mock_connect.call_count == 1 + assert mock_connect.await_count == 1 + assert mock_reset.call_count == 1 + assert mock_connect.return_value.close.call_count == 1 + + mock_connect.reset_mock() + mock_reset.reset_mock() + mock_connect.reset_mock() + res = await ezsp.EZSP.probe(APP_CONFIG[config.CONF_DEVICE]) + assert res is True + assert mock_connect.call_count == 1 + assert mock_connect.await_count == 1 + assert mock_reset.call_count == 1 + assert mock_connect.return_value.close.call_count == 1 From e9e9b0c48fca2607eecd76d403f84dd3f673a696 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 21 Apr 2020 20:58:26 -0400 Subject: [PATCH 05/20] Add SCHEMA_DEVICE to ControllerApplication --- bellows/zigbee/application.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bellows/zigbee/application.py b/bellows/zigbee/application.py index d93b8b7d..747276e2 100644 --- a/bellows/zigbee/application.py +++ b/bellows/zigbee/application.py @@ -3,7 +3,7 @@ import os from typing import Dict -from bellows.config import CONF_EZSP_CONFIG, CONF_PARAM_SRC_RTG, CONFIG_SCHEMA +from bellows.config import CONF_EZSP_CONFIG, CONF_PARAM_SRC_RTG, CONFIG_SCHEMA, SCHEMA_DEVICE from bellows.exception import ControllerError, EzspError import bellows.ezsp import bellows.multicast @@ -35,6 +35,7 @@ class ControllerApplication(zigpy.application.ControllerApplication): direct = t.EmberOutgoingMessageType.OUTGOING_DIRECT probe = bellows.ezsp.EZSP.probe SCHEMA = CONFIG_SCHEMA + SCHEMA_DEVICE = SCHEMA_DEVICE def __init__(self, config: Dict): super().__init__(config=zigpy.config.ZIGPY_SCHEMA(config)) From db617d8de705a92e41199fa688340b892236b13d Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 21 Apr 2020 21:43:18 -0400 Subject: [PATCH 06/20] Black --- bellows/zigbee/application.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bellows/zigbee/application.py b/bellows/zigbee/application.py index 747276e2..19851002 100644 --- a/bellows/zigbee/application.py +++ b/bellows/zigbee/application.py @@ -3,7 +3,12 @@ import os from typing import Dict -from bellows.config import CONF_EZSP_CONFIG, CONF_PARAM_SRC_RTG, CONFIG_SCHEMA, SCHEMA_DEVICE +from bellows.config import ( + CONF_EZSP_CONFIG, + CONF_PARAM_SRC_RTG, + CONFIG_SCHEMA, + SCHEMA_DEVICE, +) from bellows.exception import ControllerError, EzspError import bellows.ezsp import bellows.multicast From 6ea2d8328f4bf1cb67eb883a59043f89caf80a9c Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 21 Apr 2020 21:45:51 -0400 Subject: [PATCH 07/20] Refactor EmberKeyData (#251) Make EmberKeyData just a fixed list. --- bellows/types/named.py | 4 ++++ bellows/types/struct.py | 22 +++++++--------------- bellows/zigbee/application.py | 3 +-- bellows/zigbee/util.py | 8 ++------ 4 files changed, 14 insertions(+), 23 deletions(-) diff --git a/bellows/types/named.py b/bellows/types/named.py index 15a7f89a..e14ce111 100644 --- a/bellows/types/named.py +++ b/bellows/types/named.py @@ -1664,3 +1664,7 @@ class EmberNetworkInitBitmask(basic.uint16_t): # Save parent info (node ID and EUI64) in a token during joining/rejoin, # and restore on reboot. NETWORK_INIT_PARENT_INFO_IN_TOKEN = 0x0001 + + +class EmberKeyData(basic.fixed_list(16, basic.uint8_t)): + """A 128-bit key. """ diff --git a/bellows/types/struct.py b/bellows/types/struct.py index 22c35ee8..85403410 100644 --- a/bellows/types/struct.py +++ b/bellows/types/struct.py @@ -138,14 +138,6 @@ class EmberMulticastTableEntry(EzspStruct): ] -class EmberKeyData(EzspStruct): - # A 128-bit key. - _fields = [ - # The key data. - ("contents", basic.fixed_list(16, basic.uint8_t)) - ] - - class EmberCertificateData(EzspStruct): # The implicit certificate used in CBKE. _fields = [ @@ -176,7 +168,7 @@ class EmberTransientKeyData(EzspStruct): # The IEEE address paired with the transient link key. ("eui64", named.EmberEUI64), # The key data structure matching the transient key. - ("keyData", EmberKeyData), + ("keyData", named.EmberKeyData), # The incoming frame counter associated with this key. ("incomingFrameCounter", basic.uint32_t), # The number of milliseconds remaining before the key @@ -314,12 +306,12 @@ class EmberInitialSecurityState(EzspStruct): # joining the network. The security bitmask must be set with the # HAVE_PRECONFIGURED_KEY bit to indicate that the key contains valid # data. - ("preconfiguredKey", EmberKeyData), + ("preconfiguredKey", named.EmberKeyData), # The Network Key that should be used by the Trust Center when it forms # the network, or the Network Key currently in use by a joined device. # The security bitmask must be set with HAVE_NETWORK_KEY to indicate # that the key contains valid data. - ("networkKey", EmberKeyData), + ("networkKey", named.EmberKeyData), # The sequence number associated with the network key. This is only # valid if the HAVE_NETWORK_KEY has been set in the security bitmask. ("networkKeySequenceNumber", basic.uint8_t), @@ -354,7 +346,7 @@ class EmberKeyStruct(EzspStruct): # The type of the key. ("type", named.EmberKeyType), # The actual key data. - ("key", EmberKeyData), + ("key", named.EmberKeyData), # The outgoing frame counter associated with the key. ("outgoingFrameCounter", basic.uint32_t), # The frame counter of the partner device associated with the key. @@ -419,10 +411,10 @@ class EmberZllInitialSecurityState(EzspStruct): # The key encryption algorithm advertised by the application. ("keyIndex", named.EmberZllKeyIndex), # The encryption key for use by algorithms that require it. - ("encryptionKey", EmberKeyData), + ("encryptionKey", named.EmberKeyData), # The pre-configured link key used during classical ZigBee # commissioning. - ("preconfiguredKey", EmberKeyData), + ("preconfiguredKey", named.EmberKeyData), ] @@ -531,7 +523,7 @@ class EmberRf4cePairingTableEntry(EzspStruct): # The internal representation of an RF4CE pairing table entry. _fields = [ # The link key to be used to secure this pairing link. - ("securityLinkKey", EmberKeyData), + ("securityLinkKey", named.EmberKeyData), # The IEEE address of the destination device. ("destLongId", named.EmberEUI64), # The frame counter last received from the recipient node. diff --git a/bellows/zigbee/application.py b/bellows/zigbee/application.py index 19851002..7e9aed2f 100644 --- a/bellows/zigbee/application.py +++ b/bellows/zigbee/application.py @@ -526,8 +526,7 @@ async def permit_with_key(self, node, code, time_s=60): if key is None: raise Exception("Invalid install code") - link_key = t.EmberKeyData() - link_key.contents = key + link_key = t.EmberKeyData(key) v = await self._ezsp.addTransientLinkKey(node, link_key) if v[0] != t.EmberStatus.SUCCESS: diff --git a/bellows/zigbee/util.py b/bellows/zigbee/util.py index ebf0144f..144fdddf 100644 --- a/bellows/zigbee/util.py +++ b/bellows/zigbee/util.py @@ -4,12 +4,8 @@ def zha_security(controller=False): - empty_key_data = t.EmberKeyData() - empty_key_data.contents = t.fixed_list(16, t.uint8_t)([t.uint8_t(0)] * 16) - zha_key = t.EmberKeyData() - zha_key.contents = t.fixed_list(16, t.uint8_t)( - [t.uint8_t(c) for c in b"ZigBeeAlliance09"] - ) + empty_key_data = t.EmberKeyData([t.uint8_t(0)] * 16) + zha_key = t.EmberKeyData(b"ZigBeeAlliance09") isc = t.EmberInitialSecurityState() isc.bitmask = t.uint16_t( From 528fae09d58d6768e35cca8e2186a4f804eefe9a Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 22 Apr 2020 11:12:23 -0400 Subject: [PATCH 08/20] Refactor form_network() method (#253) * Form network based on SCHEMA_NETWORK content. * Bupmp up zigpy dependency. --- bellows/zigbee/application.py | 25 ++++++++++++------------- bellows/zigbee/util.py | 20 ++++++++++++-------- setup.py | 2 +- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/bellows/zigbee/application.py b/bellows/zigbee/application.py index 7e9aed2f..6114da8c 100644 --- a/bellows/zigbee/application.py +++ b/bellows/zigbee/application.py @@ -21,7 +21,6 @@ from zigpy.quirks import CustomDevice, CustomEndpoint from zigpy.types import BroadcastAddress import zigpy.util -import zigpy.zdo import zigpy.zdo.types as zdo_t APS_ACK_TIMEOUT = 120 @@ -43,7 +42,7 @@ class ControllerApplication(zigpy.application.ControllerApplication): SCHEMA_DEVICE = SCHEMA_DEVICE def __init__(self, config: Dict): - super().__init__(config=zigpy.config.ZIGPY_SCHEMA(config)) + super().__init__(config) self._ctrl_event = asyncio.Event() self._ezsp = None self._multicast = None @@ -204,29 +203,29 @@ async def shutdown(self): self._reset_task.cancel() self._ezsp.close() - async def form_network(self, channel=15, pan_id=None, extended_pan_id=None): - channel = t.uint8_t(channel) + async def form_network(self): + nwk = self.config[zigpy.config.CONF_NWK] + pan_id = nwk[zigpy.config.CONF_NWK_PAN_ID] if pan_id is None: - pan_id = t.uint16_t.from_bytes(os.urandom(2), "little") - pan_id = t.uint16_t(pan_id) + pan_id = int.from_bytes(os.urandom(2), byteorder="little") + extended_pan_id = nwk[zigpy.config.CONF_NWK_EXTENDED_PAN_ID] if extended_pan_id is None: - extended_pan_id = t.fixed_list(8, t.uint8_t)([t.uint8_t(0)] * 8) + extended_pan_id = t.EmberEUI64([t.uint8_t(0)] * 8) - initial_security_state = bellows.zigbee.util.zha_security(controller=True) + initial_security_state = bellows.zigbee.util.zha_security(nwk, controller=True) v = await self._ezsp.setInitialSecurityState(initial_security_state) assert v[0] == t.EmberStatus.SUCCESS # TODO: Better check - parameters = t.EmberNetworkParameters() - parameters.panId = pan_id + parameters.panId = t.EmberPanId(pan_id) parameters.extendedPanId = extended_pan_id parameters.radioTxPower = t.uint8_t(8) - parameters.radioChannel = channel + parameters.radioChannel = t.uint8_t(nwk[zigpy.config.CONF_NWK_CHANNEL]) parameters.joinMethod = t.EmberJoinMethod.USE_MAC_ASSOCIATION parameters.nwkManagerId = t.EmberNodeId(0) - parameters.nwkUpdateId = t.uint8_t(0) - parameters.channels = t.uint32_t(0) + parameters.nwkUpdateId = t.uint8_t(nwk[zigpy.config.CONF_NWK_UPDATE_ID]) + parameters.channels = nwk[zigpy.config.CONF_NWK_CHANNELS] await self._ezsp.formNetwork(parameters) await self._ezsp.setValue(t.EzspValueId.VALUE_STACK_TOKEN_WRITING, 1) diff --git a/bellows/zigbee/util.py b/bellows/zigbee/util.py index 144fdddf..be102ca6 100644 --- a/bellows/zigbee/util.py +++ b/bellows/zigbee/util.py @@ -1,21 +1,27 @@ import os +from typing import Any, Dict import bellows.types as t +import zigpy.config -def zha_security(controller=False): - empty_key_data = t.EmberKeyData([t.uint8_t(0)] * 16) - zha_key = t.EmberKeyData(b"ZigBeeAlliance09") +def zha_security(config: Dict[str, Any], controller: bool = False) -> None: isc = t.EmberInitialSecurityState() isc.bitmask = t.uint16_t( t.EmberInitialSecurityBitmask.HAVE_PRECONFIGURED_KEY | t.EmberInitialSecurityBitmask.REQUIRE_ENCRYPTED_KEY ) - isc.preconfiguredKey = zha_key - isc.networkKey = empty_key_data + isc.preconfiguredKey = t.EmberKeyData(config[zigpy.config.CONF_NWK_TC_LINK_KEY]) + nwk_key = config[zigpy.config.CONF_NWK_KEY] + if nwk_key is None: + nwk_key = os.urandom(16) + isc.networkKey = t.EmberKeyData(nwk_key) isc.networkKeySequenceNumber = t.uint8_t(0) - isc.preconfiguredTrustCenterEui64 = t.EmberEUI64([t.uint8_t(0)] * 8) + tc_addr = config[zigpy.config.CONF_NWK_TC_ADDRESS] + if tc_addr is None: + tc_addr = [0x00] * 8 + isc.preconfiguredTrustCenterEui64 = t.EmberEUI64(tc_addr) if controller: isc.bitmask |= ( @@ -23,6 +29,4 @@ def zha_security(controller=False): | t.EmberInitialSecurityBitmask.HAVE_NETWORK_KEY ) isc.bitmask = t.uint16_t(isc.bitmask) - random_key = t.fixed_list(16, t.uint8_t)([t.uint8_t(x) for x in os.urandom(16)]) - isc.networkKey = random_key return isc diff --git a/setup.py b/setup.py index 4eae306f..77f479aa 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ "pure_pcapy3==1.0.1", "pyserial-asyncio", "voluptuous", - "zigpy>=0.20.0a1", + "zigpy>=0.20.1a1", ], dependency_links=["https://codeload.github.com/rcloran/pure-pcapy-3/zip/master"], tests_require=["asynctest", "pytest", "pytest-asyncio"], From 650c0190f663037657f2137ba19580d10120673e Mon Sep 17 00:00:00 2001 From: Hedda Date: Wed, 22 Apr 2020 19:33:03 +0200 Subject: [PATCH 09/20] Update README.md with new (old) link to PyPI project for bellows (#244) Update README.md with new (old) link to PyPI project for bellows --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ef64c842..9fd2be87 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,10 @@ $ bellows zcl 00:0d:6f:00:05:7d:2d:34 1 1026 read_attribute 0 ## Release packages available via PyPI -Packages of tagged versions are also released via PyPI +New packages of tagged versions are also released via the "bellows" project on PyPI + - https://pypi.org/project/bellows/ + +Older packages of tagged versions are still available on the "bellows-homeassistant" project on PyPI - https://pypi.org/project/bellows-homeassistant/ ## Reference documentation From 888db24f9292308c162303ef2d1f88ffc05daa51 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 22 Apr 2020 13:33:21 -0400 Subject: [PATCH 10/20] Fix zcl commands command (#254) Set default logging level to warning. --- bellows/cli/application.py | 8 +++----- bellows/cli/main.py | 2 +- bellows/ezsp.py | 4 +++- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bellows/cli/application.py b/bellows/cli/application.py index e1bb4378..c3b95e79 100644 --- a/bellows/cli/application.py +++ b/bellows/cli/application.py @@ -302,15 +302,13 @@ async def write_attribute(ctx, attribute, value, manufacturer): @zcl.command() @click.pass_context -def commands(ctx): - database = ctx.obj["database_file"] +@util.app +async def commands(ctx): + app = ctx.obj["app"] node = ctx.obj["node"] endpoint_id = ctx.obj["endpoint"] cluster_id = ctx.obj["cluster"] - ezsp = bellows.ezsp.EZSP() - app = bellows.zigbee.application.ControllerApplication(ezsp, database) - dev, endpoint, cluster = util.get_in_cluster(app, node, endpoint_id, cluster_id) if cluster is None: return diff --git a/bellows/cli/main.py b/bellows/cli/main.py index 69254f94..5c3cc871 100644 --- a/bellows/cli/main.py +++ b/bellows/cli/main.py @@ -7,7 +7,7 @@ @click.group() -@click_log.simple_verbosity_option(logging.getLogger()) +@click_log.simple_verbosity_option(logging.getLogger(), default="WARNING") @opts.device @opts.baudrate @click.pass_context diff --git a/bellows/ezsp.py b/bellows/ezsp.py index cb810256..210a5ea0 100644 --- a/bellows/ezsp.py +++ b/bellows/ezsp.py @@ -92,7 +92,9 @@ async def version(self): self._ezsp_version = ver await self._command("version", ver) LOGGER.debug("Switched to EZSP protocol version %d", self.ezsp_version) - LOGGER.info("EZSP Stack Type: %s, Stack Version: %s", stack_type, stack_version) + LOGGER.debug( + "EZSP Stack Type: %s, Stack Version: %s", stack_type, stack_version + ) def close(self): self.stop_ezsp() From 5ab114183226f0450bc69c8d4644a078e903a06c Mon Sep 17 00:00:00 2001 From: Hedda Date: Thu, 23 Apr 2020 16:16:27 +0200 Subject: [PATCH 11/20] Update README.md with port configuration hints and suggestions (#247) * Update README.md with port configuration hints and suggestions Update README.md with port configuration hints and suggestions. Baud rate suggestion copied from https://github.com/zsmartsystems/com.zsmartsystems.zigbee so credits go to @cdjackson * Remove incorrect comment aboout auto as never been supported Remove incorrect comment aboout auto as never been supported --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 9fd2be87..8178010f 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,10 @@ $ bellows zcl 00:0d:6f:00:05:7d:2d:34 1 1026 read_attribute 0 0=1806 ``` +## Port configuration +- To configure usb port path for your EZSP serial device, just specify the TTY (serial com) port, example : `/dev/ttyUSB1` +- It is worth noting that EM3588 devices that have an embedded USB core will likely work with any baud rate, where dongles using external USB interface (eg CP2102 used with an EM3581) will likely require a specific baud rate. Currently there are two main NCP images - one that supports hardware flow control with a baud rate of 115200, and one that supports software flow control with a rate of 57600. + ## Release packages available via PyPI New packages of tagged versions are also released via the "bellows" project on PyPI From c9a79075ddd259d1b5bc56a29757f4421211e374 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sun, 26 Apr 2020 18:50:12 -0400 Subject: [PATCH 12/20] Remove default value for CONFIG_TRANSIENT_KEY_TIMEOUT_S (#256) --- bellows/config/ezsp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bellows/config/ezsp.py b/bellows/config/ezsp.py index a04078bc..20c72550 100644 --- a/bellows/config/ezsp.py +++ b/bellows/config/ezsp.py @@ -242,7 +242,7 @@ # Deprecated # The amount of time a trust center will store a transient key # with which a device can use to join the network - vol.Optional(c.CONFIG_TRANSIENT_KEY_TIMEOUT_S.name, default=180): vol.All( + vol.Optional(c.CONFIG_TRANSIENT_KEY_TIMEOUT_S.name): vol.All( int, vol.Range(min=0, max=65535) ), # From 9e2cddbf2a4f7706fc135f033766614c9d1b1e9d Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sun, 26 Apr 2020 21:44:48 -0400 Subject: [PATCH 13/20] Fix CLI form command (#257) Allow specification of the network key. --- bellows/cli/application.py | 17 +++++++++++++---- bellows/cli/opts.py | 8 ++++++++ bellows/cli/util.py | 28 ++++++++++++++-------------- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/bellows/cli/application.py b/bellows/cli/application.py index c3b95e79..98cef389 100644 --- a/bellows/cli/application.py +++ b/bellows/cli/application.py @@ -21,17 +21,26 @@ @opts.channel @opts.extended_pan @opts.pan +@opts.network_key @click.pass_context -def form(ctx, database, channel, pan_id, extended_pan_id): +def form(ctx, database, channel, pan_id, extended_pan_id, network_key): """Form a new ZigBee network""" ctx.obj["database_file"] = database + extra_config = { + zigpy.config.CONF_NWK: { + zigpy.config.CONF_NWK_CHANNEL: channel, + zigpy.config.CONF_NWK_EXTENDED_PAN_ID: extended_pan_id, + zigpy.config.CONF_NWK_PAN_ID: pan_id, + zigpy.config.CONF_NWK_KEY: network_key, + } + } + click.echo(f"Network key {network_key}") async def inner(ctx): app = ctx.obj["app"] - await app.initialize() - await app.form_network(channel, pan_id, extended_pan_id) + await app.startup(auto_form=True) - return util.app(inner, app_startup=False)(ctx) + return util.app(inner, app_startup=False, extra_config=extra_config)(ctx) @main.command() diff --git a/bellows/cli/opts.py b/bellows/cli/opts.py index 3cf599d2..4ca2b039 100644 --- a/bellows/cli/opts.py +++ b/bellows/cli/opts.py @@ -66,3 +66,11 @@ default=None, help="send a manufacturer specific command", ) + +network_key = click.option( + "-N", + "--network-key", + type=util.CSVParamType(0, 255), + default=None, + help="16 bytes of network key, lsb first", +) diff --git a/bellows/cli/util.py b/bellows/cli/util.py index 9b013d4d..22cc267e 100644 --- a/bellows/cli/util.py +++ b/bellows/cli/util.py @@ -40,20 +40,27 @@ def inner(*args, **kwargs): return inner -def app(f, app_startup=True): +def app(f, app_startup=True, extra_config=None): database_file = None application = None async def async_inner(ctx, *args, **kwargs): nonlocal database_file nonlocal application - database_file = ctx.obj["database_file"] - application = await setup_application( - ctx.obj["device"], ctx.obj["baudrate"], database_file, startup=app_startup - ) + app_config = { + config.CONF_DEVICE: { + config.CONF_DEVICE_PATH: ctx.obj["device"], + config.CONF_DEVICE_BAUDRATE: ctx.obj["baudrate"], + }, + zigpy_conf.CONF_DATABASE: ctx.obj["database_file"], + } + if extra_config: + app_config.update(extra_config) + application = await setup_application(app_config, startup=app_startup) ctx.obj["app"] = application await f(ctx, *args, **kwargs) await asyncio.sleep(0.5) + await application.shutdown() def shutdown(): try: @@ -124,17 +131,10 @@ async def cfg(config_id, value): return s -async def setup_application(dev, baudrate, database_file, startup=True): - app_config = { - config.CONF_DEVICE: { - config.CONF_DEVICE_PATH: dev, - config.CONF_DEVICE_BAUDRATE: baudrate, - }, - zigpy_conf.CONF_DATABASE: database_file, - } +async def setup_application(app_config, startup=True): app_config = bellows.zigbee.application.ControllerApplication.SCHEMA(app_config) app = await bellows.zigbee.application.ControllerApplication.new( - app_config, startup + app_config, start_radio=startup ) return app From 5f0082ad10a506a047af7c21350b4dbdef0e6c26 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sun, 26 Apr 2020 22:01:44 -0400 Subject: [PATCH 14/20] Remove network key logging. --- bellows/cli/application.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bellows/cli/application.py b/bellows/cli/application.py index 98cef389..e8a83ba9 100644 --- a/bellows/cli/application.py +++ b/bellows/cli/application.py @@ -34,8 +34,7 @@ def form(ctx, database, channel, pan_id, extended_pan_id, network_key): zigpy.config.CONF_NWK_KEY: network_key, } } - click.echo(f"Network key {network_key}") - + async def inner(ctx): app = ctx.obj["app"] await app.startup(auto_form=True) From 361c94df48d76d21e615702b0633c8cc50410d2e Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sun, 26 Apr 2020 22:04:20 -0400 Subject: [PATCH 15/20] Lint --- bellows/cli/application.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bellows/cli/application.py b/bellows/cli/application.py index e8a83ba9..4e27f163 100644 --- a/bellows/cli/application.py +++ b/bellows/cli/application.py @@ -34,7 +34,7 @@ def form(ctx, database, channel, pan_id, extended_pan_id, network_key): zigpy.config.CONF_NWK_KEY: network_key, } } - + async def inner(ctx): app = ctx.obj["app"] await app.startup(auto_form=True) From 37222f420e920062c1208e1d3eabeca10da57fac Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sun, 26 Apr 2020 22:07:06 -0400 Subject: [PATCH 16/20] 0.16.1.a0 version bump. --- bellows/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bellows/__init__.py b/bellows/__init__.py index 9a483f95..d93a11d7 100644 --- a/bellows/__init__.py +++ b/bellows/__init__.py @@ -1,5 +1,5 @@ MAJOR_VERSION = 0 -MINOR_VERSION = 17 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 16 +PATCH_VERSION = "1.a0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 665c52e407990b3a53e5076ebf6416677221f651 Mon Sep 17 00:00:00 2001 From: Hedda Date: Mon, 27 Apr 2020 15:37:10 +0200 Subject: [PATCH 17/20] Updated README.md with info on how-to test new releases (#258) Updated README.md for bellows with info on how-to test new releases. Copied this text from zigpy-cc README so credits go to @sanyatuning --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index 8178010f..3826430b 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,28 @@ $ bellows zcl 00:0d:6f:00:05:7d:2d:34 1 1026 read_attribute 0 - To configure usb port path for your EZSP serial device, just specify the TTY (serial com) port, example : `/dev/ttyUSB1` - It is worth noting that EM3588 devices that have an embedded USB core will likely work with any baud rate, where dongles using external USB interface (eg CP2102 used with an EM3581) will likely require a specific baud rate. Currently there are two main NCP images - one that supports hardware flow control with a baud rate of 115200, and one that supports software flow control with a rate of 57600. +## Testing new releases + +Testing a new release of the bellows library before it is released in Home Assistant. + +If you are using Supervised Home Assistant (formerly known as the Hassio/Hass.io distro): +- Add https://github.com/home-assistant/hassio-addons-development as "add-on" repository +- Install "Custom deps deployment" addon +- Update config like: + ``` + pypi: + - bellows==0.16.0 + apk: [] + ``` + where 0.16.0 is the new version +- Start the addon + +If you are instead using some custom python installation of Home Assistant then do this: +- Activate your python virtual env +- Update package with ``pip`` + ``` + pip install bellows==0.16.0 + ## Release packages available via PyPI New packages of tagged versions are also released via the "bellows" project on PyPI From 3608c03ca2bb446b368b10e372088dd6c7ac13d4 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Fri, 1 May 2020 19:46:49 -0400 Subject: [PATCH 18/20] Use network key sequence number from config (#260) * Use network key sequence number from config * Network seq # from CLI form. --- bellows/cli/application.py | 4 +++- bellows/cli/opts.py | 8 ++++++++ bellows/zigbee/util.py | 2 +- setup.py | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/bellows/cli/application.py b/bellows/cli/application.py index 4e27f163..51b63a70 100644 --- a/bellows/cli/application.py +++ b/bellows/cli/application.py @@ -22,8 +22,9 @@ @opts.extended_pan @opts.pan @opts.network_key +@opts.network_key_seq @click.pass_context -def form(ctx, database, channel, pan_id, extended_pan_id, network_key): +def form(ctx, database, channel, pan_id, extended_pan_id, network_key, network_key_seq): """Form a new ZigBee network""" ctx.obj["database_file"] = database extra_config = { @@ -32,6 +33,7 @@ def form(ctx, database, channel, pan_id, extended_pan_id, network_key): zigpy.config.CONF_NWK_EXTENDED_PAN_ID: extended_pan_id, zigpy.config.CONF_NWK_PAN_ID: pan_id, zigpy.config.CONF_NWK_KEY: network_key, + zigpy.config.CONF_NWK_KEY_SEQ: network_key_seq, } } diff --git a/bellows/cli/opts.py b/bellows/cli/opts.py index 4ca2b039..6ac79e30 100644 --- a/bellows/cli/opts.py +++ b/bellows/cli/opts.py @@ -74,3 +74,11 @@ default=None, help="16 bytes of network key, lsb first", ) + +network_key_seq = click.option( + "-s", + "--network-key-seq", + type=click.IntRange(0, 255), + default=0, + help="Network key sequence number", +) diff --git a/bellows/zigbee/util.py b/bellows/zigbee/util.py index be102ca6..45593ff1 100644 --- a/bellows/zigbee/util.py +++ b/bellows/zigbee/util.py @@ -17,7 +17,7 @@ def zha_security(config: Dict[str, Any], controller: bool = False) -> None: if nwk_key is None: nwk_key = os.urandom(16) isc.networkKey = t.EmberKeyData(nwk_key) - isc.networkKeySequenceNumber = t.uint8_t(0) + isc.networkKeySequenceNumber = t.uint8_t(config[zigpy.config.CONF_NWK_KEY_SEQ]) tc_addr = config[zigpy.config.CONF_NWK_TC_ADDRESS] if tc_addr is None: tc_addr = [0x00] * 8 diff --git a/setup.py b/setup.py index 77f479aa..e43274f2 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ "pure_pcapy3==1.0.1", "pyserial-asyncio", "voluptuous", - "zigpy>=0.20.1a1", + "zigpy>=0.20.1a3", ], dependency_links=["https://codeload.github.com/rcloran/pure-pcapy-3/zip/master"], tests_require=["asynctest", "pytest", "pytest-asyncio"], From a1e4ad599ce05985150345577d6f6e17583254a9 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Fri, 1 May 2020 19:50:17 -0400 Subject: [PATCH 19/20] 0.16.1a1 version bump --- bellows/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bellows/__init__.py b/bellows/__init__.py index d93a11d7..802d06e2 100644 --- a/bellows/__init__.py +++ b/bellows/__init__.py @@ -1,5 +1,5 @@ MAJOR_VERSION = 0 MINOR_VERSION = 16 -PATCH_VERSION = "1.a0" +PATCH_VERSION = "1.a1" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 9db87af8047c6b2e5e367c0201be4b96ce86142e Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sat, 2 May 2020 22:20:21 -0400 Subject: [PATCH 20/20] 0.16.1 version bump --- bellows/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bellows/__init__.py b/bellows/__init__.py index 802d06e2..b802c12a 100644 --- a/bellows/__init__.py +++ b/bellows/__init__.py @@ -1,5 +1,5 @@ MAJOR_VERSION = 0 MINOR_VERSION = 16 -PATCH_VERSION = "1.a1" +PATCH_VERSION = "1" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION)