From 46cfe04b5b68b6e7c93c82fc0ea2c8b91235120e Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Mon, 20 Feb 2023 09:57:47 -0500 Subject: [PATCH 1/3] EZSP v10 (#529) * Document protocol v10 * Use the correct data type for the stack error code * Add tests for EZSP v10 * Update version numbers in docstrings --- bellows/ezsp/__init__.py | 5 +- bellows/ezsp/v10/__init__.py | 58 +++ bellows/ezsp/v10/commands.py | 694 ++++++++++++++++++++++++++++ bellows/ezsp/v10/config.py | 16 + bellows/ezsp/v10/types/__init__.py | 5 + bellows/ezsp/v10/types/named.py | 718 +++++++++++++++++++++++++++++ bellows/ezsp/v10/types/struct.py | 236 ++++++++++ bellows/ezsp/v9/__init__.py | 2 +- bellows/types/named.py | 26 ++ tests/test_ezsp_v10.py | 316 +++++++++++++ 10 files changed, 2073 insertions(+), 3 deletions(-) create mode 100644 bellows/ezsp/v10/__init__.py create mode 100644 bellows/ezsp/v10/commands.py create mode 100644 bellows/ezsp/v10/config.py create mode 100644 bellows/ezsp/v10/types/__init__.py create mode 100644 bellows/ezsp/v10/types/named.py create mode 100644 bellows/ezsp/v10/types/struct.py create mode 100644 tests/test_ezsp_v10.py diff --git a/bellows/ezsp/__init__.py b/bellows/ezsp/__init__.py index 3ca300b7..f4435beb 100644 --- a/bellows/ezsp/__init__.py +++ b/bellows/ezsp/__init__.py @@ -15,9 +15,9 @@ import bellows.types as t import bellows.uart -from . import v4, v5, v6, v7, v8, v9 +from . import v4, v5, v6, v7, v8, v9, v10 -EZSP_LATEST = v9.EZSP_VERSION +EZSP_LATEST = v10.EZSP_VERSION PROBE_TIMEOUT = 3 NETWORK_OPS_TIMEOUT = 10 LOGGER = logging.getLogger(__name__) @@ -37,6 +37,7 @@ class EZSP: v7.EZSP_VERSION: v7.EZSPv7, v8.EZSP_VERSION: v8.EZSPv8, v9.EZSP_VERSION: v9.EZSPv9, + v10.EZSP_VERSION: v10.EZSPv10, } def __init__(self, device_config: Dict): diff --git a/bellows/ezsp/v10/__init__.py b/bellows/ezsp/v10/__init__.py new file mode 100644 index 00000000..92918dec --- /dev/null +++ b/bellows/ezsp/v10/__init__.py @@ -0,0 +1,58 @@ +""""EZSP Protocol version 10 protocol handler.""" +import asyncio +import logging +from typing import Tuple + +import voluptuous + +import bellows.config + +from . import commands, config, types as v10_types +from .. import protocol + +EZSP_VERSION = 10 +LOGGER = logging.getLogger(__name__) + + +class EZSPv10(protocol.ProtocolHandler): + """EZSP Version 10 Protocol version handler.""" + + COMMANDS = commands.COMMANDS + SCHEMAS = { + bellows.config.CONF_EZSP_CONFIG: voluptuous.Schema(config.EZSP_SCHEMA), + bellows.config.CONF_EZSP_POLICIES: voluptuous.Schema(config.EZSP_POLICIES_SCH), + } + types = v10_types + + def _ezsp_frame_tx(self, name: str) -> bytes: + """Serialize the frame id.""" + cmd_id = self.COMMANDS[name][0] + hdr = [self._seq, 0x00, 0x01] + return bytes(hdr) + self.types.uint16_t(cmd_id).serialize() + + def _ezsp_frame_rx(self, data: bytes) -> Tuple[int, int, bytes]: + """Handler for received data frame.""" + seq, data = data[0], data[3:] + frame_id, data = self.types.uint16_t.deserialize(data) + + return seq, frame_id, data + + async def pre_permit(self, time_s: int) -> None: + """Temporarily change TC policy while allowing new joins.""" + wild_card_ieee = v10_types.EmberEUI64([0xFF] * 8) + tc_link_key = v10_types.EmberKeyData(b"ZigBeeAlliance09") + await self.addTransientLinkKey(wild_card_ieee, tc_link_key) + await self.setPolicy( + v10_types.EzspPolicyId.TRUST_CENTER_POLICY, + v10_types.EzspDecisionBitmask.ALLOW_JOINS + | v10_types.EzspDecisionBitmask.ALLOW_UNSECURED_REJOINS, + ) + await asyncio.sleep(time_s + 2) + await self.setPolicy( + v10_types.EzspPolicyId.TRUST_CENTER_POLICY, + self.tc_policy, + ) + + async def set_source_routing(self) -> None: + """Enable source routing on NCP.""" + await self.setSourceRouteDiscoveryMode(1) diff --git a/bellows/ezsp/v10/commands.py b/bellows/ezsp/v10/commands.py new file mode 100644 index 00000000..db1c9431 --- /dev/null +++ b/bellows/ezsp/v10/commands.py @@ -0,0 +1,694 @@ +from . import types as t + +COMMANDS = { + # 4. Configuration frames + "version": (0x0000, (t.uint8_t,), (t.uint8_t, t.uint8_t, t.uint16_t)), + "getConfigurationValue": (0x0052, (t.EzspConfigId,), (t.EzspStatus, t.uint16_t)), + "setConfigurationValue": (0x0053, (t.EzspConfigId, t.uint16_t), (t.EzspStatus,)), + "addEndpoint": ( + 0x0002, + ( + t.uint8_t, + t.uint16_t, + t.uint16_t, + t.uint8_t, + t.uint8_t, + t.uint8_t, + t.List(t.uint16_t), + t.List(t.uint16_t), + ), + (t.EzspStatus,), + ), + "setPolicy": (0x0055, (t.EzspPolicyId, t.uint16_t), (t.EzspStatus,)), + "getPolicy": (0x0056, (t.EzspPolicyId,), (t.EzspStatus, t.EzspDecisionId)), + "sendPanIdUpdate": (0x0057, (t.EmberPanId,), (t.Bool,)), + "getValue": (0x00AA, (t.EzspValueId,), (t.EzspStatus, t.LVBytes)), + "getExtendedValue": ( + 0x0003, + (t.EzspExtendedValueId, t.uint32_t), + (t.EzspStatus, t.LVBytes), + ), + "setValue": (0x00AB, (t.EzspValueId, t.LVBytes), (t.EzspStatus,)), + # 5. Utilities Frames + "nop": (0x0005, (), ()), + "echo": (0x0081, (t.LVBytes,), (t.LVBytes,)), + "invalidCommand": (0x0058, (), (t.EzspStatus,)), + "callback": (0x0006, (), ()), + "noCallbacks": (0x0007, (), ()), + "setToken": (0x0009, (t.uint8_t, t.fixed_list(8, t.uint8_t)), (t.EmberStatus,)), + "getToken": (0x000A, (t.uint8_t,), (t.EmberStatus, t.fixed_list(8, t.uint8_t))), + "getMfgToken": (0x000B, (t.EzspMfgTokenId,), (t.LVBytes,)), + "setMfgToken": (0x000C, (t.EzspMfgTokenId, t.LVBytes), (t.EmberStatus,)), + "stackTokenChangedHandler": (0x000D, (), (t.uint16_t,)), + "getRandomNumber": (0x0049, (), (t.EmberStatus, t.uint16_t)), + "setTimer": ( + 0x000E, + (t.uint8_t, t.uint16_t, t.EmberEventUnits, t.Bool), + (t.EmberStatus,), + ), + "getTimer": (0x004E, (t.uint8_t,), (t.uint16_t, t.EmberEventUnits, t.Bool)), + "timerHandler": (0x000F, (), (t.uint8_t,)), + "debugWrite": (0x0012, (t.Bool, t.LVBytes), (t.EmberStatus,)), + "readAndClearCounters": ( + 0x0065, + (), + (t.fixed_list(len(t.EmberCounterType), t.uint16_t),), + ), + "readCounters": ( + 0x00F1, + (), + (t.fixed_list(len(t.EmberCounterType), t.uint16_t),), + ), + "counterRolloverHandler": (0x00F2, (), (t.EmberCounterType,)), + "delayTest": (0x009D, (t.uint16_t,), ()), + "getLibraryStatus": (0x0001, (t.EmberLibraryId,), (t.EmberLibraryStatus,)), + "getXncpInfo": (0x0013, (), (t.EmberStatus, t.uint16_t, t.uint16_t)), + "customFrame": (0x0047, (t.LVBytes,), (t.EmberStatus, t.LVBytes)), + "customFrameHandler": (0x0054, (), (t.LVBytes,)), + "getEui64": (0x0026, (), (t.EmberEUI64,)), + "getNodeId": (0x0027, (), (t.EmberNodeId,)), + "getPhyInterfaceCount": (0x00FC, (), (t.uint8_t,)), + "getTrueRandomEntropySource": (0x004F, (), (t.EmberEntropySource,)), + "networkInit": (0x0017, (t.EmberNetworkInitStruct,), (t.EmberStatus,)), + # 6. Networking Frames + "setManufacturerCode": (0x0015, (t.uint16_t,), ()), + "setPowerDescriptor": (0x0016, (t.uint16_t,), ()), + "networkState": (0x0018, (), (t.EmberNetworkStatus,)), + "stackStatusHandler": (0x0019, (), (t.EmberStatus,)), + "startScan": ( + 0x001A, + (t.EzspNetworkScanType, t.uint32_t, t.uint8_t), + (t.sl_Status,), + ), + "energyScanResultHandler": (0x0048, (), (t.uint8_t, t.int8s)), + "networkFoundHandler": (0x001B, (), (t.EmberZigbeeNetwork, t.uint8_t, t.int8s)), + "scanCompleteHandler": (0x001C, (), (t.uint8_t, t.EmberStatus)), + "unusedPanIdFoundHandler": (0x00D2, (), (t.uint8_t, t.EmberStatus)), + "findUnusedPanId": (0x00D3, (t.Channels, t.uint8_t), (t.EmberStatus,)), + "stopScan": (0x001D, (), (t.EmberStatus,)), + "formNetwork": (0x001E, (t.EmberNetworkParameters,), (t.EmberStatus,)), + "joinNetwork": ( + 0x001F, + (t.EmberNodeType, t.EmberNetworkParameters), + (t.EmberStatus,), + ), + "joinNetworkDirectly": ( + 0x003B, + (t.EmberNodeType, t.EmberBeaconData, t.int8s, t.Bool), + (t.EmberStatus,), + ), + "leaveNetwork": (0x0020, (), (t.EmberStatus,)), + "findAndRejoinNetwork": (0x0021, (t.Bool, t.uint32_t), (t.EmberStatus,)), + "permitJoining": (0x0022, (t.uint8_t,), (t.EmberStatus,)), + "childJoinHandler": ( + 0x0023, + (), + (t.uint8_t, t.Bool, t.EmberNodeId, t.EmberEUI64, t.EmberNodeType), + ), + "energyScanRequest": ( + 0x009C, + (t.EmberNodeId, t.Channels, t.uint8_t, t.uint16_t), + (t.EmberStatus,), + ), + "getNetworkParameters": ( + 0x0028, + (), + (t.EmberStatus, t.EmberNodeType, t.EmberNetworkParameters), + ), + "getRadioParameters": ( + 0x00FD, + (t.uint8_t,), + (t.EmberStatus, t.EmberNodeType, t.EmberNetworkParameters), + ), + "getParentChildParameters": (0x0029, (), (t.uint8_t, t.EmberEUI64, t.EmberNodeId)), + "getChildData": ( + 0x004A, + (t.uint8_t,), + (t.EmberStatus, t.EmberChildData), + ), + "setChildData": ( + 0x00AC, + (t.uint8_t,), + (t.EmberStatus, t.EmberChildData), + ), + "getSourceRouteTableTotalSize": (0x00C3, (), (t.uint8_t,)), + "getSourceRouteTableFilledSize": (0x00C2, (), (t.uint8_t,)), + "getSourceRouteTableEntry": ( + 0x00C1, + (t.uint8_t,), + (t.EmberStatus, t.EmberNodeId, t.uint8_t), + ), + "getNeighbor": (0x0079, (t.uint8_t,), (t.EmberStatus, t.EmberNeighborTableEntry)), + "getNeighborFrameCounter": (0x003E, (t.EmberEUI64,), (t.EmberStatus, t.uint32_t)), + "setNeighborFrameCounter": (0x00AD, (t.EmberEUI64,), (t.EmberStatus, t.uint32_t)), + "setRoutingShortcutThreshold": (0x00D0, (t.uint8_t,), (t.EmberStatus,)), + "getRoutingShortcutThreshold": (0x00D1, (), (t.uint8_t,)), + "neighborCount": (0x007A, (), (t.uint8_t,)), + "getRouteTableEntry": ( + 0x007B, + (t.uint8_t,), + (t.EmberStatus, t.EmberRouteTableEntry), + ), + "setRadioPower": (0x0099, (t.int8s,), (t.EmberStatus,)), + "setRadioChannel": (0x009A, (t.uint8_t,), (t.EmberStatus,)), + "setRadioIeee802154CcaMode": (0x0095, (t.uint8_t,), (t.EmberStatus,)), + "setConcentrator": ( + 0x0010, + (t.Bool, t.uint16_t, t.uint16_t, t.uint16_t, t.uint8_t, t.uint8_t, t.uint8_t), + (t.EmberStatus,), + ), + "setBrokenRouteErrorCode": (0x0011, (t.uint8_t,), (t.EmberStatus,)), + "multiPhyStart": ( + 0x00F8, + (t.uint8_t, t.uint8_t, t.uint8_t, t.int8s, t.EmberMultiPhyNwkConfig), + (t.EmberStatus,), + ), + "multiPhyStop": (0x00F9, (t.uint8_t,), (t.EmberStatus,)), + "multiPhySetRadioPower": (0x00FA, (t.uint8_t, t.int8s), (t.EmberStatus,)), + "sendLinkPowerDeltaRequest": (0x00F7, (), (t.EmberStatus,)), + "multiPhySetRadioChannel": ( + 0x00FB, + (t.uint8_t, t.uint8_t, t.uint8_t), + (t.EmberStatus,), + ), + "getDutyCycleState": (0x0035, (), (t.EmberStatus, t.EmberDutyCycleState)), + "setDutyCycleLimitsInStack": ( + 0x0040, + (t.EmberDutyCycleLimits,), + (t.EmberStatus, t.EmberDutyCycleState), + ), + "getDutyCycleLimits": (0x004B, (), (t.EmberStatus, t.EmberDutyCycleLimits)), + "getCurrentDutyCycle": ( + 0x004C, + (t.uint8_t,), + (t.EmberStatus, t.fixed_list(134, t.uint8_t)), + ), + "dutyCycleHandler": ( + 0x004D, + (), + ( + t.uint8_t, + t.uint8_t, + t.EmberDutyCycleState, + t.uint8_t, + t.EmberPerDeviceDutyCycle, + ), + ), + "getFirstBeacon": (0x003D, (), (t.EmberStatus, t.EmberBeaconIterator)), + "getNextBeacon": (0x0004, (), (t.EmberStatus, t.EmberBeaconData)), + "getNumStoredBeacons": (0x0008, (), (t.uint8_t,)), + "clearStoredBeacons": (0x003C, (), ()), + "setLogicalAndRadioChannel": (0x00B9, (t.uint8_t,), (t.EmberStatus,)), + "getLogicalChannel": (0x00BA, (), (t.uint8_t,)), + # 7. Binding Frames + "clearBindingTable": (0x002A, (), (t.EmberStatus,)), + "setBinding": (0x002B, (t.uint8_t, t.EmberBindingTableEntry), (t.EmberStatus,)), + "getBinding": (0x002C, (t.uint8_t,), (t.EmberStatus, t.EmberBindingTableEntry)), + "deleteBinding": (0x002D, (t.uint8_t,), (t.EmberStatus,)), + "bindingIsActive": (0x002E, (t.uint8_t,), (t.Bool,)), + "getBindingRemoteNodeId": (0x002F, (t.uint8_t,), (t.EmberNodeId,)), + "setBindingRemoteNodeId": (0x0030, (t.uint8_t, t.EmberNodeId), ()), + "remoteSetBindingHandler": ( + 0x0031, + (), + (t.EmberBindingTableEntry, t.uint8_t, t.EmberStatus), + ), + "remoteDeleteBindingHandler": (0x0032, (), (t.uint8_t, t.EmberStatus)), + # 8. Messaging Frames + "maximumPayloadLength": (0x0033, (), (t.uint8_t,)), + "sendUnicast": ( + 0x0034, + ( + t.EmberOutgoingMessageType, + t.EmberNodeId, + t.EmberApsFrame, + t.uint8_t, + t.LVBytes, + ), + (t.EmberStatus, t.uint8_t), + ), + "sendBroadcast": ( + 0x0036, + (t.EmberNodeId, t.EmberApsFrame, t.uint8_t, t.uint8_t, t.LVBytes), + (t.EmberStatus, t.uint8_t), + ), + "proxyBroadcast": ( + 0x0037, + ( + t.EmberNodeId, + t.EmberNodeId, + t.uint8_t, + t.EmberApsFrame, + t.uint8_t, + t.uint8_t, + t.LVBytes, + ), + (t.EmberStatus, t.uint8_t), + ), + "sendMulticast": ( + 0x0038, + (t.EmberApsFrame, t.uint8_t, t.uint8_t, t.uint8_t, t.LVBytes), + (t.EmberStatus, t.uint8_t), + ), + "sendMulticastWithAlias": ( + 0x3A, + ( + t.EmberApsFrame, + t.uint8_t, + t.uint8_t, + t.uint16_t, + t.uint8_t, + t.uint8_t, + t.LVBytes, + ), + (t.EmberStatus, t.uint8_t), + ), + "sendReply": ( + 0x0039, + (t.EmberNodeId, t.EmberApsFrame, t.LVBytes), + (t.EmberStatus,), + ), + "messageSentHandler": ( + 0x003F, + (), + ( + t.EmberOutgoingMessageType, + t.uint16_t, + t.EmberApsFrame, + t.uint8_t, + t.EmberStatus, + t.LVBytes, + ), + ), + "sendManyToOneRouteRequest": (0x0041, (t.uint16_t, t.uint8_t), (t.EmberStatus,)), + "pollForData": ( + 0x0042, + (t.uint16_t, t.EmberEventUnits, t.uint8_t), + (t.EmberStatus,), + ), + "pollCompleteHandler": (0x0043, (), (t.EmberStatus,)), + "pollHandler": (0x0044, (), (t.EmberNodeId,)), + "incomingSenderEui64Handler": (0x0062, (), (t.EmberEUI64,)), + "incomingMessageHandler": ( + 0x0045, + (), + ( + t.EmberIncomingMessageType, + t.EmberApsFrame, + t.uint8_t, + t.int8s, + t.EmberNodeId, + t.uint8_t, + t.uint8_t, + t.LVBytes, + ), + ), + "incomingRouteRecordHandler": ( + 0x0059, + (), + (t.EmberNodeId, t.EmberEUI64, t.uint8_t, t.int8s, t.LVList(t.EmberNodeId)), + ), + "incomingNetworkStatusHandler": ( + 0x00C4, + (), + tuple({"errorCode": t.EmberStackError, "target": t.EmberNodeId}.values()), + ), + "setSourceRouteDiscoveryMode": (0x005A, (t.uint8_t,), (t.uint32_t,)), + "incomingManyToOneRouteRequestHandler": ( + 0x007D, + (), + (t.EmberNodeId, t.EmberEUI64, t.uint8_t), + ), + "incomingRouteErrorHandler": (0x0080, (), (t.EmberStatus, t.EmberNodeId)), + "unicastCurrentNetworkKey": ( + 0x0050, + (t.EmberNodeId, t.EmberEUI64, t.EmberNodeId), + (t.EmberStatus,), + ), + "addressTableEntryIsActive": (0x005B, (t.uint8_t,), (t.Bool,)), + "setAddressTableRemoteEui64": (0x005C, (t.uint8_t, t.EmberEUI64), (t.EmberStatus,)), + "setAddressTableRemoteNodeId": (0x005D, (t.uint8_t, t.EmberNodeId), ()), + "getAddressTableRemoteEui64": (0x005E, (t.uint8_t,), (t.EmberEUI64,)), + "getAddressTableRemoteNodeId": (0x005F, (t.uint8_t,), (t.EmberNodeId,)), + "setExtendedTimeout": (0x007E, (t.EmberEUI64, t.Bool), ()), + "getExtendedTimeout": (0x007F, (t.EmberEUI64,), (t.Bool,)), + "replaceAddressTableEntry": ( + 0x0082, + (t.uint8_t, t.EmberEUI64, t.EmberNodeId, t.Bool), + (t.EmberStatus, t.EmberEUI64, t.EmberNodeId, t.Bool), + ), + "lookupNodeIdByEui64": (0x0060, (t.EmberEUI64,), (t.EmberNodeId,)), + "lookupEui64ByNodeId": (0x0061, (t.EmberNodeId,), (t.EmberStatus, t.EmberEUI64)), + "getMulticastTableEntry": ( + 0x0063, + (t.uint8_t,), + (t.EmberStatus, t.EmberMulticastTableEntry), + ), + "setMulticastTableEntry": ( + 0x0064, + (t.uint8_t, t.EmberMulticastTableEntry), + (t.EmberStatus,), + ), + "idConflictHandler": (0x007C, (), (t.EmberNodeId,)), + "writeNodeData": (0x00FE, (t.Bool,), (t.EmberStatus,)), + "sendRawMessage": (0x0096, (t.LVBytes,), (t.EmberStatus,)), + "sendRawMessageExtended": ( + 0x0051, + (t.LVBytes, t.uint8_t, t.Bool), + (t.EmberStatus,), + ), + "macPassthroughMessageHandler": ( + 0x0097, + (), + (t.EmberMacPassthroughType, t.uint8_t, t.int8s, t.LVBytes), + ), + "macFilterMatchMessageHandler": ( + 0x0046, + (), + (t.uint8_t, t.EmberMacPassthroughType, t.uint8_t, t.int8s, t.LVBytes), + ), + "rawTransmitCompleteHandler": (0x0098, (), (t.EmberStatus,)), + "setMacPollFailureWaitTime": (0x00F4, (t.uint8_t,), ()), + "setBeaconClassificationParams": ( + 0x00EF, + (), + (t.EmberStatus, t.EmberBeaconClassificationParams), + ), + "getBeaconClassificationParams": ( + 0x00F3, + (), + (t.EmberStatus, t.EmberBeaconClassificationParams), + ), + # 9. Security Frames + "setInitialSecurityState": ( + 0x0068, + (t.EmberInitialSecurityState,), + (t.EmberStatus,), + ), + "getCurrentSecurityState": ( + 0x0069, + (), + (t.EmberStatus, t.EmberCurrentSecurityState), + ), + "getKey": (0x006A, (t.EmberKeyType,), (t.EmberStatus, t.EmberKeyStruct)), + "switchNetworkKeyHandler": (0x006E, (), (t.uint8_t,)), + "getKeyTableEntry": (0x0071, (t.uint8_t,), (t.EmberStatus, t.EmberKeyStruct)), + "setKeyTableEntry": ( + 0x0072, + (t.uint8_t, t.EmberEUI64, t.Bool, t.EmberKeyData), + (t.EmberStatus,), + ), + "findKeyTableEntry": (0x0075, (t.EmberEUI64, t.Bool), (t.uint8_t,)), + "addOrUpdateKeyTableEntry": ( + 0x0066, + (t.EmberEUI64, t.Bool, t.EmberKeyData), + (t.EmberStatus,), + ), + "sendTrustCenterLinkKey": (0x0067, (t.EmberNodeId, t.EmberEUI64), (t.EmberStatus,)), + "eraseKeyTableEntry": (0x0076, (t.uint8_t,), (t.EmberStatus,)), + "clearKeyTable": (0x00B1, (), (t.EmberStatus,)), + "requestLinkKey": (0x0014, (t.EmberEUI64,), (t.EmberStatus,)), + "updateTcLinkKey": (0x006C, (t.uint8_t,), (t.EmberStatus,)), + "zigbeeKeyEstablishmentHandler": (0x009B, (), (t.EmberEUI64, t.EmberKeyStatus)), + "addTransientLinkKey": (0x00AF, (t.EmberEUI64, t.EmberKeyData), (t.EmberStatus,)), + "clearTransientLinkKeys": (0x006B, (), ()), + "getTransientLinkKey": ( + 0x00CE, + (t.EmberEUI64,), + (t.EmberStatus, t.EmberTransientKeyData), + ), + "getTransientKeyTableEntry": ( + 0x006D, + (t.uint8_t,), + (t.EmberStatus, t.EmberTransientKeyData), + ), + # 10. Trust Center Frames + "trustCenterJoinHandler": ( + 0x0024, + (), + ( + t.EmberNodeId, + t.EmberEUI64, + t.EmberDeviceUpdate, + t.EmberJoinDecision, + t.EmberNodeId, + ), + ), + "broadcastNextNetworkKey": (0x0073, (t.EmberKeyData,), (t.EmberStatus,)), + "broadcastNetworkKeySwitch": (0x0074, (), (t.EmberStatus,)), + "becomeTrustCenter": (0x0077, (t.EmberKeyData,), (t.EmberStatus,)), + "aesMmoHash": ( + 0x006F, + (t.EmberAesMmoHashContext, t.Bool, t.LVBytes), + (t.EmberStatus, t.EmberAesMmoHashContext), + ), + "removeDevice": ( + 0x00A8, + (t.EmberNodeId, t.EmberEUI64, t.EmberEUI64), + (t.EmberStatus,), + ), + "unicastNwkKeyUpdate": ( + 0x00A9, + (t.EmberNodeId, t.EmberEUI64, t.EmberKeyData), + (t.EmberStatus,), + ), + # 11. Certificate Based Key Exchange (CBKE) Frames + "generateCbkeKeys": (0x00A4, (), (t.EmberStatus,)), + "generateCbkeKeysHandler": (0x009E, (), (t.EmberStatus, t.EmberPublicKeyData)), + "calculateSmacs": ( + 0x009F, + (t.Bool, t.EmberCertificateData, t.EmberPublicKeyData), + (t.EmberStatus,), + ), + "calculateSmacsHandler": ( + 0x00A0, + (), + (t.EmberStatus, t.EmberSmacData, t.EmberSmacData), + ), + "generateCbkeKeys283k1": (0x00E8, (), (t.EmberStatus,)), + "generateCbkeKeysHandler283k1": ( + 0x00E9, + (), + (t.EmberStatus, t.EmberPublicKey283k1Data), + ), + "calculateSmacs283k1": ( + 0x00EA, + (t.Bool, t.EmberCertificate283k1Data, t.EmberPublicKey283k1Data), + (t.EmberStatus,), + ), + "calculateSmacsHandler283k1": ( + 0x00EB, + (), + (t.EmberStatus, t.EmberSmacData, t.EmberSmacData), + ), + "clearTemporaryDataMaybeStoreLinkKey": (0x00A1, (t.Bool,), (t.EmberStatus,)), + "clearTemporaryDataMaybeStoreLinkKey283k1": (0x00EE, (t.Bool,), (t.EmberStatus,)), + "getCertificate": (0x00A5, (), (t.EmberStatus, t.EmberCertificateData)), + "getCertificate283k1": (0x00EC, (), (t.EmberStatus, t.EmberCertificate283k1Data)), + "dsaSign": (0x00A6, (t.LVBytes,), (t.EmberStatus,)), # Deprecated + "dsaSignHandler": (0x00A7, (), (t.EmberStatus, t.LVBytes)), # Deprecated + "dsaVerify": ( + 0x00A3, + (t.EmberMessageDigest, t.EmberCertificateData, t.EmberSignatureData), + (t.EmberStatus,), + ), + "dsaVerifyHandler": (0x0078, (), (t.EmberStatus,)), + "dsaVerify283k1": ( + 0x00B0, + (t.EmberMessageDigest, t.EmberCertificate283k1Data, t.EmberSignature283k1Data), + (t.EmberStatus,), + ), + "setPreinstalledCbkeData": ( + 0x00A2, + (t.EmberPublicKeyData, t.EmberCertificateData, t.EmberPrivateKeyData), + (t.EmberStatus,), + ), + "setPreinstalledCbkeData283k1": ( + 0x00ED, + ( + t.EmberPublicKey283k1Data, + t.EmberCertificate283k1Data, + t.EmberPrivateKey283k1Data, + ), + (t.EmberStatus,), + ), + # 12. Mfglib Frames + "mfglibStart": (0x0083, (t.Bool,), (t.EmberStatus,)), + "mfglibEnd": (0x0084, (), (t.EmberStatus,)), + "mfglibStartTone": (0x0085, (), (t.EmberStatus,)), + "mfglibStopTone": (0x0086, (), (t.EmberStatus,)), + "mfglibStartStream": (0x0087, (), (t.EmberStatus,)), + "mfglibStopStream": (0x0088, (), (t.EmberStatus,)), + "mfglibSendPacket": (0x0089, (t.LVBytes,), (t.EmberStatus,)), + "mfglibSetChannel": (0x008A, (t.uint8_t,), (t.EmberStatus,)), + "mfglibGetChannel": (0x008B, (), (t.uint8_t,)), + "mfglibSetPower": (0x008C, (t.uint16_t, t.int8s), (t.EmberStatus,)), + "mfglibGetPower": (0x008D, (), (t.int8s,)), + "mfglibRxHandler": (0x008E, (), (t.uint8_t, t.int8s, t.LVBytes)), + # 13. Bootloader Frames + "launchStandaloneBootloader": (0x008F, (t.uint8_t,), (t.EmberStatus,)), + "sendBootloadMessage": ( + 0x0090, + (t.Bool, t.EmberEUI64, t.LVBytes), + (t.EmberStatus,), + ), + "getStandaloneBootloaderVersionPlatMicroPhy": ( + 0x0091, + (), + (t.uint16_t, t.uint8_t, t.uint8_t, t.uint8_t), + ), + "incomingBootloadMessageHandler": ( + 0x0092, + (), + (t.EmberEUI64, t.uint8_t, t.int8s, t.LVBytes), + ), + "bootloadTransmitCompleteHandler": (0x0093, (), (t.EmberStatus, t.LVBytes)), + "aesEncrypt": ( + 0x0094, + (t.fixed_list(16, t.uint8_t), t.fixed_list(16, t.uint8_t)), + (t.fixed_list(16, t.uint8_t),), + ), + # 14. ZLL Frames + "zllNetworkOps": ( + 0x00B2, + (t.EmberZllNetwork, t.EzspZllNetworkOperation, t.int8s), + (t.EmberStatus,), + ), + "zllSetInitialSecurityState": ( + 0x00B3, + (t.EmberKeyData, t.EmberZllInitialSecurityState), + (t.EmberStatus,), + ), + "zllSetSecurityStateWithoutKey": ( + 0x00CF, + (t.EmberZllInitialSecurityState,), + (t.EmberStatus,), + ), + "zllStartScan": (0x00B4, (t.Channels, t.int8s, t.EmberNodeType), (t.EmberStatus,)), + "zllSetRxOnWhenIdle": (0x00B5, (t.uint32_t,), (t.EmberStatus,)), + "zllNetworkFoundHandler": ( + 0x00B6, + (), + (t.EmberZllNetwork, t.Bool, t.EmberZllDeviceInfoRecord, t.uint8_t, t.int8s), + ), + "zllScanCompleteHandler": (0x00B7, (), (t.EmberStatus,)), + "zllAddressAssignmentHandler": ( + 0x00B8, + (), + (t.EmberZllAddressAssignment, t.uint8_t, t.int8s), + ), + "zllTouchLinkTargetHandler": (0x00BB, (), (t.EmberZllNetwork,)), + "zllGetTokens": ( + 0x00BC, + (), + (t.EmberTokTypeStackZllData, t.EmberTokTypeStackZllSecurity), + ), + "zllSetDataToken": (0x00BD, (t.EmberTokTypeStackZllData,), ()), + "zllSetNonZllNetwork": (0x00BF, (), ()), + "isZllNetwork": (0x00BE, (), (t.Bool,)), + "zllSetRadioIdleMode": (0x00D4, (t.EmberRadioPowerMode,), ()), + "setZllNodeType": (0x00D5, (t.EmberNodeType,), ()), + "setZllAdditionalState": (0x00D6, (t.uint16_t,), ()), + "zllOperationInProgress": (0x00D7, (), (t.Bool,)), + "zllRxOnWhenIdleGetActive": (0x00D8, (), (t.Bool,)), + "getZllPrimaryChannelMask": (0x00D9, (), (t.Channels,)), + "getZllSecondaryChannelMask": (0x00DA, (), (t.Channels,)), + "setZllPrimaryChannelMask": (0x00DB, (t.Channels,), ()), + "setZllSecondaryChannelMask": (0x00DC, (t.Channels,), ()), + "zllClearTokens": (0x0025, (), ()), + # 15 WWAH Frames + "setParentClassificationEnabled": (0x00E7, (t.Bool,), ()), + "getParentClassificationEnabled": (0x00F0, (), (t.Bool,)), + "setLongUpTime": (0x00E3, (t.Bool,), ()), + "setHubConnectivity": (0x00E4, (t.Bool,), ()), + "isUpTimeLong": (0x00E5, (), (t.Bool,)), + "isHubConnected": (0x00E6, (), (t.Bool,)), + # 16 Green Power Frames + "gpProxyTableProcessGpPairing": ( + 0x00C9, + ( + t.uint32_t, + t.EmberGpAddress, + t.uint8_t, + t.uint16_t, + t.uint16_t, + t.uint16_t, + t.EmberEUI64, + t.EmberKeyData, + ), + (), + ), + "dGpSend": ( + 0x00C6, + (t.Bool, t.Bool, t.EmberGpAddress, t.uint8_t, t.LVBytes, t.uint8_t, t.uint16_t), + (t.EmberStatus,), + ), + "dGpSentHandler": (0x00C7, (), (t.EmberStatus, t.uint8_t)), + "gpepIncomingMessageHandler": ( + 0x00C5, + (), + ( + t.EmberStatus, + t.uint8_t, + t.uint8_t, + t.EmberGpAddress, + t.EmberGpSecurityLevel, + t.EmberGpKeyType, + t.Bool, + t.Bool, + t.uint32_t, + t.uint8_t, + t.uint32_t, + t.EmberGpSinkListEntry, + t.LVBytes, + ), + ), + "gpProxyTableGetEntry": ( + 0x00C8, + (t.uint8_t,), + (t.EmberStatus, t.EmberGpProxyTableEntry), + ), + "gpProxyTableLookup": (0x00C0, (t.EmberGpAddress,), (t.uint8_t,)), + "gpSinkTableGetEntry": ( + 0x00DD, + (t.uint8_t,), + (t.EmberStatus, t.EmberGpSinkTableEntry), + ), + "gpSinkTableLookup": (0x00DE, (t.EmberGpAddress,), (t.uint8_t,)), + "gpSinkTableSetEntry": ( + 0x00DF, + (t.uint8_t, t.EmberGpSinkTableEntry), + (t.EmberStatus,), + ), + "gpSinkTableRemoveEntry": (0x00E0, (t.uint8_t,), ()), + "gpSinkTableFindOrAllocateEntry": (0x00E1, (t.EmberGpAddress,), (t.uint8_t,)), + "gpSinkTableClearAll": (0x00E2, (), ()), + "gpSinkTableInit": (0x0070, (), ()), + # 17 Secure EZSP Frames + "setSecurityKey": ( + 0x00CA, + (t.EmberKeyData, t.SecureEzspSecurityType), + (t.EzspStatus,), + ), + "setSecurityParameters": ( + 0x00CB, + (t.SecureEzspSecurityLevel, t.SecureEzspRandomNumber), + (t.EzspStatus, t.SecureEzspRandomNumber), + ), + "resetToFactoryDefaults": (0x00CC, (), (t.EzspStatus,)), + "getSecurityKeyStatus": (0x00CD, (), (t.EzspStatus, t.SecureEzspSecurityType)), + # 18 Token Interface Frames + "getTokenCount": (0x0100, (), (t.uint8_t,)), + "getTokenInfo": (0x0101, (t.uint8_t,), (t.EmberStatus)), + "getTokenData": ( + 0x0102, + (t.uint32_t, t.uint32_t), + (t.EmberStatus, t.EmberTokenData), + ), + "setTokenData": ( + 0x0103, + (t.uint32_t, t.uint32_t, t.EmberTokenData), + (t.EmberStatus), + ), + "resetNode": (0x0104, (), ()), +} diff --git a/bellows/ezsp/v10/config.py b/bellows/ezsp/v10/config.py new file mode 100644 index 00000000..161b5f05 --- /dev/null +++ b/bellows/ezsp/v10/config.py @@ -0,0 +1,16 @@ +import voluptuous as vol + +from bellows.config import cv_uint16 + +from ..v4.config import EZSP_POLICIES_SHARED +from ..v9 import config as v9_config +from .types import EzspPolicyId + +EZSP_SCHEMA = { + **v9_config.EZSP_SCHEMA, +} + +EZSP_POLICIES_SCH = { + **EZSP_POLICIES_SHARED, + **{vol.Optional(policy.name): cv_uint16 for policy in EzspPolicyId}, +} diff --git a/bellows/ezsp/v10/types/__init__.py b/bellows/ezsp/v10/types/__init__.py new file mode 100644 index 00000000..d51e9473 --- /dev/null +++ b/bellows/ezsp/v10/types/__init__.py @@ -0,0 +1,5 @@ +from bellows.types import deserialize, serialize # noqa: F401, F403 +from bellows.types.basic import * # noqa: F401,F403 + +from .named import * # noqa: F401, F403 +from .struct import * # noqa: F401, F403 diff --git a/bellows/ezsp/v10/types/named.py b/bellows/ezsp/v10/types/named.py new file mode 100644 index 00000000..b1e2cb7f --- /dev/null +++ b/bellows/ezsp/v10/types/named.py @@ -0,0 +1,718 @@ +"""Protocol version 9 named types.""" + +import bellows.types.basic as basic +from bellows.types.named import ( # noqa: F401, F403 + Bool, + Channels, + EmberApsOption, + EmberBindingType, + EmberCertificate283k1Data, + EmberCertificateData, + EmberConcentratorType, + EmberConfigTxPowerMode, + EmberCurrentSecurityBitmask, + EmberEUI64, + EmberEventUnits, + EmberGpKeyType, + EmberGpSecurityLevel, + EmberIncomingMessageType, + EmberInitialSecurityBitmask, + EmberJoinDecision, + EmberKeyData, + EmberKeyStatus, + EmberKeyStructBitmask, + EmberLibraryId, + EmberLibraryStatus, + EmberMacPassthroughType, + EmberMessageDigest, + EmberMulticastId, + EmberNetworkStatus, + EmberNodeId, + EmberNodeType, + EmberOutgoingMessageType, + EmberPanId, + EmberPrivateKey283k1Data, + EmberPrivateKeyData, + EmberPublicKey283k1Data, + EmberPublicKeyData, + EmberSignature283k1Data, + EmberSignatureData, + EmberSmacData, + EmberStackError, + EmberStatus, + EmberZdoConfigurationFlags, + EmberZllKeyIndex, + EmberZllState, + ExtendedPanId, + EzspEndpointFlags, + EzspExtendedValueId, + EzspMfgTokenId, + EzspNetworkScanType, + EzspSourceRouteOverheadInformation, + EzspStatus, + EzspZllNetworkOperation, + sl_Status, +) + + +class EzspConfigId(basic.enum8): + # Identifies a configuration value. + + # The number of packet buffers available to the stack. When set to the + # special value 0xFF, the NCP will allocate all remaining configuration RAM + # towards packet buffers, such that the resulting count will be the largest + # whole number of packet buffers that can fit into the available memory. + CONFIG_PACKET_BUFFER_COUNT = 0x01 + # The maximum number of router neighbors the stack can keep track of. A + # neighbor is a node within radio range. + CONFIG_NEIGHBOR_TABLE_SIZE = 0x02 + # The maximum number of APS retried messages the stack can be transmitting + # at any time. + CONFIG_APS_UNICAST_MESSAGE_COUNT = 0x03 + # The maximum number of non-volatile bindings supported by the stack. + CONFIG_BINDING_TABLE_SIZE = 0x04 + # The maximum number of EUI64 to network address associations that the + # stack can maintain for the application. (Note, the total number of such + # address associations maintained by the NCP is the sum of the value of + # this setting and the value of ::CONFIG_TRUST_CENTER_ADDRESS_CACHE_SIZE). + CONFIG_ADDRESS_TABLE_SIZE = 0x05 + # The maximum number of multicast groups that the device may be a member + # of. + CONFIG_MULTICAST_TABLE_SIZE = 0x06 + # The maximum number of destinations to which a node can route messages. + # This includes both messages originating at this node and those relayed + # for others. + CONFIG_ROUTE_TABLE_SIZE = 0x07 + # The number of simultaneous route discoveries that a node will support. + CONFIG_DISCOVERY_TABLE_SIZE = 0x08 + # Specifies the stack profile. + CONFIG_STACK_PROFILE = 0x0C + # The security level used for security at the MAC and network layers. The + # supported values are 0 (no security) and 5 (payload is encrypted and a + # four-byte MIC is used for authentication). + CONFIG_SECURITY_LEVEL = 0x0D + # The maximum number of hops for a message. + CONFIG_MAX_HOPS = 0x10 + # The maximum number of end device children that a router will support. + CONFIG_MAX_END_DEVICE_CHILDREN = 0x11 + # The maximum amount of time that the MAC will hold a message for indirect + # transmission to a child. + CONFIG_INDIRECT_TRANSMISSION_TIMEOUT = 0x12 + # The maximum amount of time that an end device child can wait between + # polls. If no poll is heard within this timeout, then the parent removes + # the end device from its tables. + CONFIG_END_DEVICE_POLL_TIMEOUT = 0x13 + # Enables boost power mode and/or the alternate transmitter output. + CONFIG_TX_POWER_MODE = 0x17 + # 0: Allow this node to relay messages. 1: Prevent this node from relaying + # messages. + CONFIG_DISABLE_RELAY = 0x18 + # The maximum number of EUI64 to network address associations that the + # Trust Center can maintain. These address cache entries are reserved for + # and reused by the Trust Center when processing device join/rejoin + # authentications. This cache size limits the number of overlapping joins + # the Trust Center can process within a narrow time window (e.g. two + # seconds), and thus should be set to the maximum number of near + # simultaneous joins the Trust Center is expected to accommodate. (Note, + # the total number of such address associations maintained by the NCP is + # the sum of the value of this setting and the value of + # ::CONFIG_ADDRESS_TABLE_SIZE.) + CONFIG_TRUST_CENTER_ADDRESS_CACHE_SIZE = 0x19 + # The size of the source route table. + CONFIG_SOURCE_ROUTE_TABLE_SIZE = 0x1A + # The number of blocks of a fragmented message that can be sent in a single + # window. + CONFIG_FRAGMENT_WINDOW_SIZE = 0x1C + # The time the stack will wait (in milliseconds) between sending blocks of + # a fragmented message. + CONFIG_FRAGMENT_DELAY_MS = 0x1D + # The size of the Key Table used for storing individual link keys (if the + # device is a Trust Center) or Application Link Keys (if the device is a + # normal node). + CONFIG_KEY_TABLE_SIZE = 0x1E + # The APS ACK timeout value. The stack waits this amount of time between + # resends of APS retried messages. + CONFIG_APS_ACK_TIMEOUT = 0x1F + # The duration of an active scan, in the units used by the 15.4 scan + # parameter (((1 << duration) + 1) * 15ms). This also controls the jitter + # used when responding to a beacon request. + CONFIG_ACTIVE_SCAN_DURATION = 0x20 + # The time the coordinator will wait (in seconds) for a second end device + # bind request to arrive. + CONFIG_END_DEVICE_BIND_TIMEOUT = 0x21 + # The number of PAN id conflict reports that must be received by the + # network manager within one minute to trigger a PAN id change. + CONFIG_PAN_ID_CONFLICT_REPORT_THRESHOLD = 0x22 + # The timeout value in minutes for how long the Trust Center or a normal + # node waits for the ZigBee Request Key to complete. On the Trust Center + # this controls whether or not the device buffers the request, waiting for + # a matching pair of ZigBee Request Key. If the value is non-zero, the + # Trust Center buffers and waits for that amount of time. If the value is + # zero, the Trust Center does not buffer the request and immediately + # responds to the request. Zero is the most compliant behavior. + CONFIG_REQUEST_KEY_TIMEOUT = 0x24 + # This value indicates the size of the runtime modifiable certificate + # table. Normally certificates are stored in MFG tokens but this table can + # be used to field upgrade devices with new Smart Energy certificates. + # This value cannot be set, it can only be queried. + CONFIG_CERTIFICATE_TABLE_SIZE = 0x29 + # This is a bitmask that controls which incoming ZDO request messages are + # passed to the application. The bits are defined in the + # EmberZdoConfigurationFlags enumeration. To see if the application is + # required to send a ZDO response in reply to an incoming message, the + # application must check the APS options bitfield within the + # incomingMessageHandler callback to see if the + # APS_OPTION_ZDO_RESPONSE_REQUIRED flag is set. + CONFIG_APPLICATION_ZDO_FLAGS = 0x2A + # The maximum number of broadcasts during a single broadcast timeout + # period. + CONFIG_BROADCAST_TABLE_SIZE = 0x2B + # The size of the MAC filter list table. + CONFIG_MAC_FILTER_TABLE_SIZE = 0x2C + # The number of supported networks. + CONFIG_SUPPORTED_NETWORKS = 0x2D + # Whether multicasts are sent to the RxOnWhenIdle=true address (0xFFFD) or + # the sleepy broadcast address (0xFFFF). The RxOnWhenIdle=true address is + # the ZigBee compliant destination for multicasts. + CONFIG_SEND_MULTICASTS_TO_SLEEPY_ADDRESS = 0x2E + # ZLL group address initial configuration. + CONFIG_ZLL_GROUP_ADDRESSES = 0x2F + # ZLL rssi threshold initial configuration. + CONFIG_ZLL_RSSI_THRESHOLD = 0x30 + # Toggles the mtorr flow control in the stack. + # The maximum number of pairings supported by the stack. Controllers + # must support at least one pairing table entry while targets must + # support at least five. + CONFIG_MTORR_FLOW_CONTROL = 0x33 + # Setting the retry queue size. + CONFIG_RETRY_QUEUE_SIZE = 0x34 + # Setting the new broadcast entry threshold. + CONFIG_NEW_BROADCAST_ENTRY_THRESHOLD = 0x35 + # The length of time, in seconds, that a trust center will store a + # transient link key that a device can use to join its network. A transient + # key is added with a call to emberAddTransientLinkKey. After the transient + # key is added, it will be removed once this amount of time has passed. A + # joining device will not be able to use that key to join until it is added + # again on the trust center. The default value is 300 seconds, i.e., 5 + # minutes. + CONFIG_TRANSIENT_KEY_TIMEOUT_S = 0x36 + # The number of passive acknowledgements to record from neighbors before we stop + # re-transmitting broadcasts + CONFIG_BROADCAST_MIN_ACKS_NEEDED = 0x37 + # The length of time, in seconds, that a trust center will allow a Trust Center + # (insecure) rejoin for a device that is using the well-known link key. This timeout + # takes effect once rejoins using the well-known key has been allowed. This command + # updates the emAllowTcRejoinsUsingWellKnownKeyTimeoutSec value. + CONFIG_TC_REJOINS_USING_WELL_KNOWN_KEY_TIMEOUT_S = 0x38 + # Valid range of a CTUNE value is 0x0000-0x01FF. Higher order bits (0xFE00) of the + # 16-bit value are ignored. + CONFIG_CTUNE_VALUE = 0x39 + # To configure non trust center node to assume a concentrator type of the trust + # center it join to, until it receive many-to-one route request from the trust + # center. For the trust center node, concentrator type is configured from the + # concentrator plugin. The stack by default assumes trust center be a low RAM + # concentrator that make other devices send route record to the trust center even + # without receiving a many-to-one route request. The default concentrator type can + # be changed by setting appropriate EmberAssumeTrustCenterConcentratorType config + # value. + CONFIG_ASSUME_TC_CONCENTRATOR_TYPE = 0x40 + # This is green power proxy table size. This value is readonly and cannot be set at + # runtime. + CONFIG_GP_PROXY_TABLE_SIZE = 0x41 + # This is green power sink table size. This value is readonly and cannot be set at + # runtime. + EZSP_CONFIG_GP_SINK_TABLE_SIZE = 0x42 + + +class EzspValueId(basic.enum8): + # Identifies a value. + + # The contents of the node data stack token. + VALUE_TOKEN_STACK_NODE_DATA = 0x00 + # The types of MAC passthrough messages that the host wishes to receive. + VALUE_MAC_PASSTHROUGH_FLAGS = 0x01 + # The source address used to filter legacy EmberNet messages when the + # MAC_PASSTHROUGH_EMBERNET_SOURCE flag is set in VALUE_MAC_PASSTHROUGH_FLAGS. + VALUE_EMBERNET_PASSTHROUGH_SOURCE_ADDRESS = 0x02 + # The number of available message buffers. + VALUE_FREE_BUFFERS = 0x03 + # Selects sending synchronous callbacks in ezsp-uart. + VALUE_UART_SYNCH_CALLBACKS = 0x04 + # The maximum incoming transfer size for the local node. + VALUE_MAXIMUM_INCOMING_TRANSFER_SIZE = 0x05 + # The maximum outgoing transfer size for the local node. + VALUE_MAXIMUM_OUTGOING_TRANSFER_SIZE = 0x06 + # A boolean indicating whether stack tokens are written to persistent + # storage as they change. + VALUE_STACK_TOKEN_WRITING = 0x07 + # A read-only value indicating whether the stack is currently performing a rejoin. + VALUE_STACK_IS_PERFORMING_REJOIN = 0x08 + # A list of EmberMacFilterMatchData values. + VALUE_MAC_FILTER_LIST = 0x09 + # The Ember Extended Security Bitmask. + VALUE_EXTENDED_SECURITY_BITMASK = 0x0A + # The node short ID. + VALUE_NODE_SHORT_ID = 0x0B + # The descriptor capability of the local node. + VALUE_DESCRIPTOR_CAPABILITY = 0x0C + # The stack device request sequence number of the local node. + VALUE_STACK_DEVICE_REQUEST_SEQUENCE_NUMBER = 0x0D + # Enable or disable radio hold-off. + VALUE_RADIO_HOLD_OFF = 0x0E + # The flags field associated with the endpoint data. + VALUE_ENDPOINT_FLAGS = 0x0F + # Enable/disable the Mfg security config key settings. + VALUE_MFG_SECURITY_CONFIG = 0x10 + # Retrieves the version information from the stack on the NCP. + VALUE_VERSION_INFO = 0x11 + # This will get/set the rejoin reason noted by the host for a subsequent call to + # emberFindAndRejoinNetwork(). After a call to emberFindAndRejoinNetwork() the + # host's rejoin reason will be set to REJOIN_REASON_NONE. The NCP will store the + # rejoin reason used by the call to emberFindAndRejoinNetwork() + VALUE_NEXT_HOST_REJOIN_REASON = 0x12 + # This is the reason that the last rejoin took place. This value may only be + # retrieved, not set. The rejoin may have been initiated by the stack (NCP) or the + # application (host). If a host initiated a rejoin the reason will be set by default + # to REJOIN_DUE_TO_APP_EVENT_1. If the application wishes to denote its own rejoin + # reasons it can do so by calling ezspSetValue(VALUE_HOST_REJOIN_REASON, + # REJOIN_DUE_TO_APP_EVENT_X). X is a number corresponding to one of the app events + # defined. If the NCP initiated a rejoin it will record this value internally for + # retrieval by ezspGetValue(VALUE_REAL_REJOIN_REASON). + VALUE_LAST_REJOIN_REASON = 0x13 + # The next ZigBee sequence number. + VALUE_NEXT_ZIGBEE_SEQUENCE_NUMBER = 0x14 + # CCA energy detect threshold for radio. + VALUE_CCA_THRESHOLD = 0x15 + # The threshold value for a counter + VALUE_SET_COUNTER_THRESHOLD = 0x17 + # Resets all counters thresholds to 0xFF + VALUE_RESET_COUNTER_THRESHOLDS = 0x18 + # Clears all the counters + VALUE_CLEAR_COUNTERS = 0x19 + # The node's new certificate signed by the CA. + EZSP_VALUE_CERTIFICATE_283K1 = 0x1A + # The Certificate Authority's public key. + EZSP_VALUE_PUBLIC_KEY_283K1 = 0x1B + # The node's new static private key. + EZSP_VALUE_PRIVATE_KEY_283K1 = 0x1C + # The NWK layer security frame counter value + VALUE_NWK_FRAME_COUNTER = 0x23 + # The APS layer security frame counter value + VALUE_APS_FRAME_COUNTER = 0x24 + # Sets the device type to use on the next rejoin using device type + VALUE_RETRY_DEVICE_TYPE = 0x25 + # Setting this byte enables R21 behavior on the NCP. + VALUE_ENABLE_R21_BEHAVIOR = 0x29 + # Configure the antenna mode(0-primary,1-secondary,2- toggle on tx ack fail). + VALUE_ANTENNA_MODE = 0x30 + # Enable or disable packet traffic arbitration. + VALUE_ENABLE_PTA = 0x31 + # Set packet traffic arbitration configuration options. + VALUE_PTA_OPTIONS = 0x32 + # Configure manufacturing library options(0-non-CSMA transmits,1-CSMA transmits). + VALUE_MFGLIB_OPTIONS = 0x33 + # Sets the flag to use either negotiated power by link power delta (LPD) or fixed + # power value provided by user while forming/joining a network for packet + # transmissions on subghz interface. This is mainly for testing purposes. + VALUE_USE_NEGOTIATED_POWER_BY_LPD = 0x34 + # Set packet traffic arbitration configuration PWM options. + VALUE_PTA_PWM_OPTIONS = 0x35 + # Set packet traffic arbitration directional priority pulse width in microseconds. + VALUE_PTA_DIRECTIONAL_PRIORITY_PULSE_WIDTH = 0x36 + # Set packet traffic arbitration phy select timeout(ms) + VALUE_PTA_PHY_SELECT_TIMEOUT = 0x37 + # Configure the RX antenna mode: (0-do not switch; 1- primary; 2-secondary; + # 3-RX antenna diversity). + VALUE_ANTENNA_RX_MODE = 0x38 + # Configure the timeout to wait for the network key before failing a join. + VALUE_NWK_KEY_TIMEOUT = 0x39 + # The number of failed CSMA attempts due to failed CCA made by the MAC before + # continuing transmission with CCA disabled. This is the same as calling the + # emberForceTxAfterFailedCca(uint8_t csmaAttempts) API. A value of 0 disables the + # feature + VALUE_FORCE_TX_AFTER_FAILED_CCA_ATTEMPTS = 0x3A + # The length of time, in seconds, that a trust center will store a transient link + # key that a device can use to join its network. A transient key is added with a + # call to emberAddTransientLinkKey. After the transient key is added, it will be + # removed once this amount of time has passed. A joining device will not be able to + # use that key to join until it is added again on the trust center. The default + # value is 300 seconds (5 minutes). + VALUE_TRANSIENT_KEY_TIMEOUT_S = 0x3B + # Cumulative energy usage metric since the last value reset of the coulomb counter + # plugin. Setting this value will reset the coulomb counter. + VALUE_COULOMB_COUNTER_USAGE = 0x3C + # When scanning, configure the maximum number of beacons to store in cache. Each + # beacon consumes one packet buffer in RAM. + VALUE_MAX_BEACONS_TO_STORE = 0x3D + # Set the mask to filter out unacceptable child timeout options on a router. + VALUE_END_DEVICE_TIMEOUT_OPTIONS_MASK = 0x3E + # The end device keep alive mode supported by the parent. + VALUE_END_DEVICE_KEEP_ALIVE_SUPPORT_MODE = 0x3F + # Return the active radio config. + VALUE_ACTIVE_RADIO_CONFIG = 0x41 + # Timeout in milliseconds to store entries in the transient device table. + # If the devices are not authenticated before the timeout, the entry shall be + # purged. + VALUE_TRANSIENT_DEVICE_TIMEOUT = 0x43 + + +class EzspPolicyId(basic.enum8): + # Identifies a policy. + + # Controls trust center behavior. + TRUST_CENTER_POLICY = 0x00 + # Controls how external binding modification requests are handled. + BINDING_MODIFICATION_POLICY = 0x01 + # Controls whether the Host supplies unicast replies. + UNICAST_REPLIES_POLICY = 0x02 + # Controls whether pollHandler callbacks are generated. + POLL_HANDLER_POLICY = 0x03 + # Controls whether the message contents are included in the + # messageSentHandler callback. + MESSAGE_CONTENTS_IN_CALLBACK_POLICY = 0x04 + # Controls whether the Trust Center will respond to Trust Center link key + # requests. + TC_KEY_REQUEST_POLICY = 0x05 + # Controls whether the Trust Center will respond to application link key + # requests. + APP_KEY_REQUEST_POLICY = 0x06 + # Controls whether ZigBee packets that appear invalid are automatically + # dropped by the stack. A counter will be incremented when this occurs. + PACKET_VALIDATE_LIBRARY_POLICY = 0x07 + # Controls whether the stack will process ZLL messages. + ZLL_POLICY = 0x08 + # Controls whether Trust Center (insecure) rejoins for devices using the well-known + # link key are accepted. If rejoining using the well-known key is allowed, it is + # disabled again after emAllowTcRejoinsUsingWellKnownKeyTimeoutSec seconds. + TC_REJOINS_USING_WELL_KNOWN_KEY_POLICY = 0x09 + + +class EzspDecisionBitmask(basic.bitmap16): + """EZSP Decision bitmask.""" + + # Disallow joins and rejoins. + DEFAULT_CONFIGURATION = 0x0000 + # Send the network key to all joining devices. + ALLOW_JOINS = 0x0001 + # Send the network key to all rejoining devices. + ALLOW_UNSECURED_REJOINS = 0x0002 + # Send the network key in the clear. + SEND_KEY_IN_CLEAR = 0x0004 + # Do nothing for unsecured rejoins. + IGNORE_UNSECURED_REJOINS = 0x0008 + # Allow joins if there is an entry in the transient key table. + JOINS_USE_INSTALL_CODE_KEY = 0x0010 + # Delay sending the network key to a new joining device. + DEFER_JOINS = 0x0020 + + +class EzspDecisionId(basic.enum8): + # Identifies a policy decision. + + # BINDING_MODIFICATION_POLICY default decision. Do not allow the local + # binding table to be changed by remote nodes. + DISALLOW_BINDING_MODIFICATION = 0x10 + # BINDING_MODIFICATION_POLICY decision. Allow remote nodes to change + # the local binding table. + ALLOW_BINDING_MODIFICATION = 0x11 + # BINDING_MODIFICATION_POLICY decision. Allows remote nodes to set local + # binding entries only if the entries correspond to endpoints defined on + # the device, and for output clusters bound to those endpoints. + CHECK_BINDING_MODIFICATIONS_ARE_VALID_ENDPOINT_CLUSTERS = 0x12 + # UNICAST_REPLIES_POLICY default decision. The NCP will automatically send + # an empty reply (containing no payload) for every unicast received. + HOST_WILL_NOT_SUPPLY_REPLY = 0x20 + # UNICAST_REPLIES_POLICY decision. The NCP will only send a reply if it + # receives a sendReply command from the Host. + HOST_WILL_SUPPLY_REPLY = 0x21 + # POLL_HANDLER_POLICY default decision. Do not inform the Host when a child polls. + POLL_HANDLER_IGNORE = 0x30 + # POLL_HANDLER_POLICY decision. Generate a pollHandler callback when a child polls. + POLL_HANDLER_CALLBACK = 0x31 + # MESSAGE_CONTENTS_IN_CALLBACK_POLICY default decision. Include only the + # message tag in the messageSentHandler callback. + MESSAGE_TAG_ONLY_IN_CALLBACK = 0x40 + # MESSAGE_CONTENTS_IN_CALLBACK_POLICY decision. Include both the message + # tag and the message contents in the messageSentHandler callback. + MESSAGE_TAG_AND_CONTENTS_IN_CALLBACK = 0x41 + # TC_KEY_REQUEST_POLICY decision. When the Trust Center receives a request + # for a Trust Center link key, it will be ignored. + DENY_TC_KEY_REQUESTS = 0x50 + # TC_KEY_REQUEST_POLICY decision. When the Trust Center receives a request for a + # Trust Center link key, it will reply to it with the corresponding key. + ALLOW_TC_KEY_REQUESTS_AND_SEND_CURRENT_KEY = 0x51 + # TC_KEY_REQUEST_POLICY decision. When the Trust Center receives a request + # for a Trust Center link key, it will generate a key to send to the joiner. + ALLOW_TC_KEY_REQUEST_AND_GENERATE_NEW_KEY = 0x52 + # APP_KEY_REQUEST_POLICY decision. When the Trust Center receives a request + # for an application link key, it will be ignored. + DENY_APP_KEY_REQUESTS = 0x60 + # APP_KEY_REQUEST_POLICY decision. When the Trust Center receives a request + # for an application link key, it will randomly generate a key and send it + # to both partners. + ALLOW_APP_KEY_REQUESTS = 0x61 + # Indicates that packet validate library checks are enabled on the NCP. + PACKET_VALIDATE_LIBRARY_CHECKS_ENABLED = 0x62 + # Indicates that packet validate library checks are NOT enabled on the NCP. + PACKET_VALIDATE_LIBRARY_CHECKS_DISABLED = 0x63 + + +class EmberKeyType(basic.enum8): + # Describes the type of ZigBee security key. + + # A shared key between the Trust Center and a device. + TRUST_CENTER_LINK_KEY = 0x01 + # A shared secret used for deriving keys between the Trust Center and a + # device + CURRENT_NETWORK_KEY = 0x03 + # The alternate Network Key that was previously in use, or the newer key + # that will be switched to. + NEXT_NETWORK_KEY = 0x04 + # An Application Link Key shared with another (non-Trust Center) device. + APPLICATION_LINK_KEY = 0x05 + + +class EmberDeviceUpdate(basic.enum8): + # The status of the device update. + + STANDARD_SECURITY_SECURED_REJOIN = 0x0 + STANDARD_SECURITY_UNSECURED_JOIN = 0x1 + DEVICE_LEFT = 0x2 + STANDARD_SECURITY_UNSECURED_REJOIN = 0x3 + + +class EmberCounterType(basic.enum8): + # Defines the events reported to the application by the + # readAndClearCounters command. + + # The MAC received a broadcast. + COUNTER_MAC_RX_BROADCAST = 0 + # The MAC transmitted a broadcast. + COUNTER_MAC_TX_BROADCAST = 1 + # The MAC received a unicast. + COUNTER_MAC_RX_UNICAST = 2 + # The MAC successfully transmitted a unicast. + COUNTER_MAC_TX_UNICAST_SUCCESS = 3 + # The MAC retried a unicast. + COUNTER_MAC_TX_UNICAST_RETRY = 4 + # The MAC unsuccessfully transmitted a unicast. + COUNTER_MAC_TX_UNICAST_FAILED = 5 + # The APS layer received a data broadcast. + COUNTER_APS_DATA_RX_BROADCAST = 6 + # The APS layer transmitted a data broadcast. + COUNTER_APS_DATA_TX_BROADCAST = 7 + # The APS layer received a data unicast. + COUNTER_APS_DATA_RX_UNICAST = 8 + # The APS layer successfully transmitted a data unicast. + COUNTER_APS_DATA_TX_UNICAST_SUCCESS = 9 + # The APS layer retried a data unicast. + COUNTER_APS_DATA_TX_UNICAST_RETRY = 10 + # The APS layer unsuccessfully transmitted a data unicast. + COUNTER_APS_DATA_TX_UNICAST_FAILED = 11 + # The network layer successfully submitted a new route discovery to the MAC. + COUNTER_ROUTE_DISCOVERY_INITIATED = 12 + # An entry was added to the neighbor table. + COUNTER_NEIGHBOR_ADDED = 13 + # An entry was removed from the neighbor table. + COUNTER_NEIGHBOR_REMOVED = 14 + # A neighbor table entry became stale because it had not been heard from. + COUNTER_NEIGHBOR_STALE = 15 + # A node joined or rejoined to the network via this node. + COUNTER_JOIN_INDICATION = 16 + # An entry was removed from the child table. + COUNTER_CHILD_REMOVED = 17 + # EZSP-UART only. An overflow error occurred in the UART. + COUNTER_ASH_OVERFLOW_ERROR = 18 + # EZSP-UART only. A framing error occurred in the UART. + COUNTER_ASH_FRAMING_ERROR = 19 + # EZSP-UART only. An overrun error occurred in the UART. + COUNTER_ASH_OVERRUN_ERROR = 20 + # A message was dropped at the network layer because the NWK frame counter + # was not higher than the last message seen from that source. + COUNTER_NWK_FRAME_COUNTER_FAILURE = 21 + # A message was dropped at the APS layer because the APS frame counter was + # not higher than the last message seen from that source. + COUNTER_APS_FRAME_COUNTER_FAILURE = 22 + # Utility counter for general debugging use. + COUNTER_UTILITY = 23 + # A message was dropped at the APS layer because it had APS encryption but + # the key associated with the sender has not been authenticated, and thus + # the key is not authorized for use in APS data messages. + COUNTER_APS_LINK_KEY_NOT_AUTHORIZED = 24 + # A NWK encrypted message was received but dropped because decryption + # failed. + COUNTER_NWK_DECRYPTION_FAILURE = 25 + # An APS encrypted message was received but dropped because decryption + # failed. + COUNTER_APS_DECRYPTION_FAILURE = 26 + # The number of times we failed to allocate a set of linked packet buffers. + # This doesn't necessarily mean that the packet buffer count was 0 at the + # time, but that the number requested was greater than the number free. + COUNTER_ALLOCATE_PACKET_BUFFER_FAILURE = 27 + # The number of relayed unicast packets. + COUNTER_RELAYED_UNICAST = 28 + # The number of times we dropped a packet due to reaching + # the preset PHY to MAC queue limit (emMaxPhyToMacQueueLength). + COUNTER_PHY_TO_MAC_QUEUE_LIMIT_REACHED = 29 + # The number of times we dropped a packet due to the + # packet-validate library checking a packet and rejecting it + # due to length or other formatting problems. + COUNTER_PACKET_VALIDATE_LIBRARY_DROPPED_COUNT = 30 + # The number of times the NWK retry queue is full and a + # new message failed to be added. + COUNTER_TYPE_NWK_RETRY_OVERFLOW = 31 + # The number of times the PHY layer was unable to transmit + # due to a failed CCA. + COUNTER_PHY_CCA_FAIL_COUNT = 32 + # The number of times a NWK broadcast was dropped because + # the broadcast table was full. + COUNTER_BROADCAST_TABLE_FULL = 33 + # The number of low priority packet traffic arbitration requests. + COUNTER_PTA_LO_PRI_REQUESTED = 34 + # The number of high priority packet traffic arbitration requests. + COUNTER_PTA_HI_PRI_REQUESTED = 35 + # The number of low priority packet traffic arbitration requests denied. + COUNTER_PTA_LO_PRI_DENIED = 36 + # The number of high priority packet traffic arbitration requests denied. + COUNTER_PTA_HI_PRI_DENIED = 37 + # The number of aborted low priority packet traffic arbitration transmissions. + COUNTER_PTA_LO_PRI_TX_ABORTED = 38 + # The number of aborted high priority packet traffic arbitration transmissions. + COUNTER_PTA_HI_PRI_TX_ABORTED = 39 + # The number of times an address conflict has caused node_id change, and an address + # conflict error is sent + COUNTER_ADDRESS_CONFLICT_SENT = 40 + + +class EmberJoinMethod(basic.enum8): + # The type of method used for joining. + + # Normally devices use MAC Association to join a network, which respects + # the "permit joining" flag in the MAC Beacon. For mobile nodes this value + # causes the device to use an Ember Mobile Node Join, which is functionally + # equivalent to a MAC association. This value should be used by default. + USE_MAC_ASSOCIATION = 0x0 + # For those networks where the "permit joining" flag is never turned on, + # they will need to use a ZigBee NWK Rejoin. This value causes the rejoin + # to be sent without NWK security and the Trust Center will be asked to + # send the NWK key to the device. The NWK key sent to the device can be + # encrypted with the device's corresponding Trust Center link key. That is + # determined by the ::EmberJoinDecision on the Trust Center returned by the + # ::emberTrustCenterJoinHandler(). For a mobile node this value will cause + # it to use an Ember Mobile node rejoin, which is functionally equivalent. + USE_NWK_REJOIN = 0x1 + # For those networks where the "permit joining" flag is never turned on, + # they will need to use a NWK Rejoin. If those devices have been + # preconfigured with the NWK key (including sequence number) they can use a + # secured rejoin. This is only necessary for end devices since they need a + # parent. Routers can simply use the ::USE_NWK_COMMISSIONING join method + # below. + USE_NWK_REJOIN_HAVE_NWK_KEY = 0x2 + # For those networks where all network and security information is known + # ahead of time, a router device may be commissioned such that it does not + # need to send any messages to begin communicating on the network. + USE_CONFIGURED_NWK_STATE = 0x3 + + +class EmberNetworkInitBitmask(basic.bitmap16): + # Bitmask options for emberNetworkInit(). + + # No options for Network Init + NETWORK_INIT_NO_OPTIONS = 0x0000 + # Save parent info (node ID and EUI64) in a token during joining/rejoin, + # and restore on reboot. + NETWORK_INIT_PARENT_INFO_IN_TOKEN = 0x0001 + # Send a rejoin request as an end device on reboot if parent information is + # persisted. ZB3 end devices must rejoin on reboot. + NETWORK_INIT_END_DEVICE_REJOIN_ON_REBOOT = 0x0002 + + +EmberNetworkInitStruct = EmberNetworkInitBitmask + + +class EmberMultiPhyNwkConfig(basic.enum8): + """Network configuration for the desired radio interface for multi phy network.""" + + # Enable broadcast support on Routers + BROADCAST_SUPPORT = 0x01 + + +class EmberDutyCycleState(basic.enum8): + """Duty cycle states.""" + + # No Duty cycle tracking or metrics are taking place + DUTY_CYCLE_TRACKING_OFF = 0 + # Duty Cycle is tracked and has not exceeded any thresholds. + DUTY_CYCLE_LBT_NORMAL = 1 + # We have exceeded the limited threshold of our total duty cycle allotment. + DUTY_CYCLE_LBT_LIMITED_THRESHOLD_REACHED = 2 + # We have exceeded the critical threshold of our total duty cycle allotment. + DUTY_CYCLE_LBT_CRITICAL_THRESHOLD_REACHED = 3 + # We have reached the suspend limit and are blocking all outbound transmissions. + DUTY_CYCLE_LBT_SUSPEND_LIMIT_REACHED = 4 + + +class EmberRadioPowerMode(basic.enum8): + """Radio power mode.""" + + # The radio receiver is switched on. + RADIO_POWER_MODE_RX_ON = 0 + # The radio receiver is switched off. + RADIO_POWER_MODE_OFF = 1 + + +class EmberEntropySource(basic.enum8): + """Entropy sources.""" + + # Entropy source error + ENTROPY_SOURCE_ERROR = 0 + # Entropy source is the radio. + ENTROPY_SOURCE_RADIO = 1 + # Entropy source is the TRNG powered by mbed TLS. + ENTROPY_SOURCE_MBEDTLS_TRNG = 2 + # Entropy source is powered by mbed TLS, the source is not TRNG. + ENTROPY_SOURCE_MBEDTLS = 3 + + +class EmberDutyCycleHectoPct(basic.uint16_t): + """ "The percent of duty cycle for a limit. + + Duty Cycle, Limits, and Thresholds are reported in units of Percent * 100 + (i.e. 10000 = 100.00%, 1 = 0.01%)""" + + +class EmberGpProxyTableEntryStatus(basic.uint8_t): + """The proxy table entry status.""" + + +class EmberGpSecurityFrameCounter(basic.uint32_t): + """The security frame counter""" + + +class EmberGpSinkTableEntryStatus(basic.uint8_t): + """The sink table entry status.""" + + +class SecureEzspSecurityType(basic.uint32_t): + """Security type of the Secure EZSP Protocol.""" + + +class SecureEzspSecurityLevel(basic.uint8_t): + """Security level of the Secure EZSP Protocol.""" + + +class SecureEzspRandomNumber(basic.fixed_list(16, basic.uint8_t)): + """Randomly generated 64-bit number. + + Both NCP and Host contribute this number to create the Session ID, + which is used in the nonce. + """ + + +class SecureEzspSessionId(basic.fixed_list(8, basic.uint8_t)): + """Generated 64-bit Session ID, using random numbers from Host and NCP. + + It is generated at each reboot (during negotiation phase). Having both sides + contribute to the value prevents one side from choosing a number that might have + been previously used (either because of a bug or by malicious intent). + """ diff --git a/bellows/ezsp/v10/types/struct.py b/bellows/ezsp/v10/types/struct.py new file mode 100644 index 00000000..af81ec8a --- /dev/null +++ b/bellows/ezsp/v10/types/struct.py @@ -0,0 +1,236 @@ +"""Protocol version 9 specific structs.""" + +from __future__ import annotations + +import bellows.types.basic as basic +from bellows.types.struct import ( # noqa: F401 + EmberAesMmoHashContext, + EmberApsFrame, + EmberBindingTableEntry, + EmberCurrentSecurityState, + EmberGpAddress, + EmberInitialSecurityState, + EmberMulticastTableEntry, + EmberNeighborTableEntry, + EmberNetworkParameters, + EmberRouteTableEntry, + EmberTokenData, + EmberTokenInfo, + EmberTokTypeStackZllData, + EmberTokTypeStackZllSecurity, + EmberZigbeeNetwork, + EmberZllAddressAssignment, + EmberZllDeviceInfoRecord, + EmberZllInitialSecurityState, + EmberZllNetwork, + EmberZllSecurityAlgorithmData, + EzspStruct, +) + +from . import named + + +class EmberBeaconData(EzspStruct): + """Beacon data structure.""" + + # The channel of the received beacon. + channel: basic.uint8_t + # The LQI of the received beacon. + lqi: basic.uint8_t + # The RSSI of the received beacon. + rssi: basic.int8s + # The depth of the received beacon. + depth: basic.uint8_t + # The network update ID of the received beacon. + nwkUpdateId: basic.uint8_t + # The power level of the received beacon. This field is valid only if the beacon is + # an enhanced beacon + power: basic.int8s + # The TC connectivity and long uptime from capacity field. + parentPriority: basic.int8s + # The PAN ID of the received beacon. + panId: named.EmberPanId + # The extended PAN ID of the received beacon. + extendedPanId: named.ExtendedPanId + # The sender of the received beacon. + sender: named.EmberNodeId + # Whether or not the beacon is enhanced. + enhanced: named.Bool + # Whether the beacon is advertising permit join. + permitJoin: named.Bool + # Whether the beacon is advertising capacity. + hasCapacity: named.Bool + + +class EmberBeaconIterator(EzspStruct): + """Defines an iterator that is used to loop over cached beacons. Do not write to + fields denoted as Private. + """ + + # The retrieved beacon. + beacon: EmberBeaconData + # (Private) The index of the retrieved beacon. + index: basic.uint8_t + + +class EmberBeaconClassificationParams(EzspStruct): + """The parameters related to beacon prioritization.""" + + # The minimum RSSI value for receiving packets that is used in some beacon + # prioritization algorithms. + minRssiForReceivingPkts: basic.int8s + # The beacon classification mask that identifies which beacon prioritization + # algorithm to pick and defines the relevant parameters. + beaconClassificationMask: basic.uint16_t + + +class EmberKeyStruct(EzspStruct): + # A structure containing a key and its associated data. + # A bitmask indicating the presence of data within the various fields + # in the structure. + bitmask: named.EmberKeyStructBitmask + # The type of the key. + type: named.EmberKeyType + # The actual key data. + 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. + incomingFrameCounter: basic.uint32_t + # The sequence number associated with the key. + sequenceNumber: basic.uint8_t + # The IEEE address of the partner device also in possession of the key. + partnerEUI64: named.EmberEUI64 + + @classmethod + def deserialize(cls, data: bytes) -> tuple[named.EmberKeyStruct, bytes]: + # XXX: EZSPv9 serialization bug + if len(data) == 24: + return cls(), data[24:] + + return super().deserialize(data) + + +class EmberGpSinkListEntry(EzspStruct): + # A sink list entry + # The sink list type. + type: basic.uint8_t + # The EUI64 of the target sink. + sinkEUI: named.EmberEUI64 + # The short address of the target sink. + sinkNodeId: named.EmberNodeId + + +class EmberGpProxyTableEntry(EzspStruct): + """The internal representation of a proxy table entry.""" + + # The link key to be used to secure this pairing link. + securityLinkKey: named.EmberKeyData + # Internal status of the proxy table entry. + status: named.EmberGpProxyTableEntryStatus + # The tunneling options + # (this contains both options and extendedOptions from the spec). + options: basic.uint32_t + # The addressing info of the GPD. + gpd: EmberGpAddress + # The assigned alias for the GPD. + assignedAlias: named.EmberNodeId + # The security options field. + securityOptions: basic.uint8_t + # The security frame counter of the GPD. + gpdSecurityFrameCounter: named.EmberGpSecurityFrameCounter + # The list of sinks (hardcoded to 2 which is the spec minimum). + sinkList: basic.fixed_list(2, EmberGpSinkListEntry) + # The groupcast radius. + groupcastRadius: basic.uint8_t + # The search counter + searchCounter: basic.uint8_t + + +class EmberGpSinkTableEntry(EzspStruct): + """The internal representation of a sink table entry.""" + + # Internal status of the sink table entry + status: named.EmberGpSinkTableEntryStatus + # The tunneling options + # (this contains both options and extendedOptions from the spec). + options: basic.uint32_t + # The addressing info of the GPD. + gpd: EmberGpAddress + # The device id for the GPD. + deviceId: basic.uint8_t + # The list of sinks (hardcoded to 2 which is the spec minimum). + sinkList: basic.fixed_list(2, EmberGpSinkListEntry) + # The assigned alias for the GPD. + assignedAlias: named.EmberNodeId + # The groupcast radius. + groupcastRadius: basic.uint8_t + # The security options field. + securityOptions: basic.uint8_t + # The security frame counter of the GPD. + gpdSecurityFrameCounter: named.EmberGpSecurityFrameCounter + # The key to use for GPD. + gpdKey: named.EmberKeyData + + +class EmberDutyCycleLimits(EzspStruct): + """A structure containing duty cycle limit configurations. + + All limits are absolute, and are required to be as follows: + suspLimit > critThresh > limitThresh + For example: + suspLimit = 250 (2.5%), critThresh = 180 (1.8%), limitThresh 100 (1.00%). + """ + + # The vendor identifier field shall contain the vendor identifier of the node. + vendorId: basic.uint16_t + # The vendor string field shall contain the vendor string of the node. + vendorString: basic.fixed_list(7, basic.uint8_t) + + +class EmberPerDeviceDutyCycle(EzspStruct): + """A structure containing per device overall duty cycle consumed + + up to the suspend limit). + """ + + # Node Id of device whose duty cycle is reported. + nodeId: named.EmberNodeId + # Amount of overall duty cycle consumed (up to suspend limit). + dutyCycleConsumed: named.EmberDutyCycleHectoPct + + +class EmberTransientKeyData(EzspStruct): + """The transient key data structure. Added in ver. 5. Revised in ver 8""" + + # The IEEE address paired with the transient link key. + eui64: named.EmberEUI64 + # The key data structure matching the transient key. + keyData: named.EmberKeyData + # This bitmask indicates whether various fields in the structure contain valid data. + bitmask: named.EmberKeyStructBitmask + # The number of seconds remaining before the key is automatically timed out of the + # transient key table. + remainingTimeSeconds: basic.uint16_t + + +class EmberChildData(EzspStruct): + """A structure containing a child node's data.""" + + # The EUI64 of the child + eui64: named.EmberEUI64 + # The node type of the child + type: named.EmberNodeType + # The short address of the child + id: named.EmberNodeId + # The phy of the child + phy: basic.uint8_t + # The power of the child + power: basic.uint8_t + # The timeout of the child + timeout: basic.uint8_t + + # The GPD's EUI64. + # gpdIeeeAddress: named.EmberEUI64 + # The GPD's source ID. + # sourceId: basic.uint32_t diff --git a/bellows/ezsp/v9/__init__.py b/bellows/ezsp/v9/__init__.py index fc9b5b97..0c767ca4 100644 --- a/bellows/ezsp/v9/__init__.py +++ b/bellows/ezsp/v9/__init__.py @@ -15,7 +15,7 @@ class EZSPv9(protocol.ProtocolHandler): - """EZSP Version 8 Protocol version handler.""" + """EZSP Version 9 Protocol version handler.""" COMMANDS = commands.COMMANDS SCHEMAS = { diff --git a/bellows/types/named.py b/bellows/types/named.py index 1380a3d8..1099d429 100644 --- a/bellows/types/named.py +++ b/bellows/types/named.py @@ -1867,3 +1867,29 @@ class EmberDistinguishedNodeId(basic.enum16): # or getting the remote node ID from the binding table. It indicates that the # address or binding table entry is not in use. TABLE_ENTRY_UNUSED = 0xFFFF + + +class EmberStackError(basic.enum16): + """Stack error codes.""" + + ROUTE_ERROR_NO_ROUTE_AVAILABLE = 0x00 + ROUTE_ERROR_TREE_LINK_FAILURE = 0x01 + ROUTE_ERROR_NON_TREE_LINK_FAILURE = 0x02 + ROUTE_ERROR_LOW_BATTERY_LEVEL = 0x03 + ROUTE_ERROR_NO_ROUTING_CAPACITY = 0x04 + ROUTE_ERROR_NO_INDIRECT_CAPACITY = 0x05 + ROUTE_ERROR_INDIRECT_TRANSACTION_EXPIRY = 0x06 + ROUTE_ERROR_TARGET_DEVICE_UNAVAILABLE = 0x07 + ROUTE_ERROR_TARGET_ADDRESS_UNALLOCATED = 0x08 + ROUTE_ERROR_PARENT_LINK_FAILURE = 0x09 + ROUTE_ERROR_VALIDATE_ROUTE = 0x0A + ROUTE_ERROR_SOURCE_ROUTE_FAILURE = 0x0B + ROUTE_ERROR_MANY_TO_ONE_ROUTE_FAILURE = 0x0C + ROUTE_ERROR_ADDRESS_CONFLICT = 0x0D + ROUTE_ERROR_VERIFY_ADDRESSES = 0x0E + ROUTE_ERROR_PAN_IDENTIFIER_UPDATE = 0x0F + + ZIGBEE_NETWORK_STATUS_NETWORK_ADDRESS_UPDATE = 0x10 + ZIGBEE_NETWORK_STATUS_BAD_FRAME_COUNTER = 0x11 + ZIGBEE_NETWORK_STATUS_BAD_KEY_SEQUENCE_NUMBER = 0x12 + ZIGBEE_NETWORK_STATUS_UNKNOWN_COMMAND = 0x13 diff --git a/tests/test_ezsp_v10.py b/tests/test_ezsp_v10.py new file mode 100644 index 00000000..91c5eafb --- /dev/null +++ b/tests/test_ezsp_v10.py @@ -0,0 +1,316 @@ +import pytest + +import bellows.ezsp.v10 + +from .async_mock import AsyncMock, MagicMock, patch + + +@pytest.fixture +def ezsp_f(): + """EZSP v10 protocol handler.""" + return bellows.ezsp.v10.EZSPv10(MagicMock(), MagicMock()) + + +def test_ezsp_frame(ezsp_f): + ezsp_f._seq = 0x22 + data = ezsp_f._ezsp_frame("version", 10) + assert data == b"\x22\x00\x01\x00\x00\x0a" + + +def test_ezsp_frame_rx(ezsp_f): + """Test receiving a version frame.""" + ezsp_f(b"\x01\x01\x80\x00\x00\x01\x02\x34\x12") + assert ezsp_f._handle_callback.call_count == 1 + assert ezsp_f._handle_callback.call_args[0][0] == "version" + assert ezsp_f._handle_callback.call_args[0][1] == [0x01, 0x02, 0x1234] + + +async def test_set_source_routing(ezsp_f): + """Test setting source routing.""" + with patch.object( + ezsp_f, "setSourceRouteDiscoveryMode", new=AsyncMock() + ) as src_mock: + await ezsp_f.set_source_routing() + assert src_mock.await_count == 1 + + +async def test_pre_permit(ezsp_f): + """Test pre permit.""" + p1 = patch.object(ezsp_f, "setPolicy", new=AsyncMock()) + p2 = patch.object(ezsp_f, "addTransientLinkKey", new=AsyncMock()) + with p1 as pre_permit_mock, p2 as tclk_mock: + await ezsp_f.pre_permit(-1.9) + assert pre_permit_mock.await_count == 2 + assert tclk_mock.await_count == 1 + + +def test_command_frames(ezsp_f): + """Test alphabetical list of frames matches the commands.""" + assert set(ezsp_f.COMMANDS) == set(command_frames) + for name, frame_id in command_frames.items(): + assert ezsp_f.COMMANDS[name][0] == frame_id + assert ezsp_f.COMMANDS_BY_ID[frame_id][0] == name + + +command_frames = { + "addEndpoint": 0x0002, + "addOrUpdateKeyTableEntry": 0x0066, + "addTransientLinkKey": 0x00AF, + "addressTableEntryIsActive": 0x005B, + "aesEncrypt": 0x0094, + "aesMmoHash": 0x006F, + "becomeTrustCenter": 0x0077, + "bindingIsActive": 0x002E, + "bootloadTransmitCompleteHandler": 0x0093, + "broadcastNetworkKeySwitch": 0x0074, + "broadcastNextNetworkKey": 0x0073, + "calculateSmacs": 0x009F, + "calculateSmacs283k1": 0x00EA, + "calculateSmacsHandler": 0x00A0, + "calculateSmacsHandler283k1": 0x00EB, + "callback": 0x0006, + "incomingNetworkStatusHandler": 0x00C4, + "childJoinHandler": 0x0023, + "clearBindingTable": 0x002A, + "clearKeyTable": 0x00B1, + "clearStoredBeacons": 0x003C, + "clearTemporaryDataMaybeStoreLinkKey": 0x00A1, + "clearTemporaryDataMaybeStoreLinkKey283k1": 0x00EE, + "clearTransientLinkKeys": 0x006B, + "counterRolloverHandler": 0x00F2, + "customFrame": 0x0047, + "customFrameHandler": 0x0054, + "dGpSend": 0x00C6, + "dGpSentHandler": 0x00C7, + "debugWrite": 0x0012, + "delayTest": 0x009D, + "deleteBinding": 0x002D, + "dsaSign": 0x00A6, + "dsaSignHandler": 0x00A7, + "dsaVerify": 0x00A3, + "dsaVerify283k1": 0x00B0, + "dsaVerifyHandler": 0x0078, + "dutyCycleHandler": 0x004D, + "echo": 0x0081, + "energyScanRequest": 0x009C, + "energyScanResultHandler": 0x0048, + "eraseKeyTableEntry": 0x0076, + "findAndRejoinNetwork": 0x0021, + "findKeyTableEntry": 0x0075, + "findUnusedPanId": 0x00D3, + "formNetwork": 0x001E, + "generateCbkeKeys": 0x00A4, + "generateCbkeKeys283k1": 0x00E8, + "generateCbkeKeysHandler": 0x009E, + "generateCbkeKeysHandler283k1": 0x00E9, + "getAddressTableRemoteEui64": 0x005E, + "getAddressTableRemoteNodeId": 0x005F, + "getBinding": 0x002C, + "getBeaconClassificationParams": 0x00F3, + "getBindingRemoteNodeId": 0x002F, + "getCertificate": 0x00A5, + "getCertificate283k1": 0x00EC, + "getChildData": 0x004A, + "setChildData": 0x00AC, + "getConfigurationValue": 0x0052, + "getCurrentDutyCycle": 0x004C, + "getCurrentSecurityState": 0x0069, + "getEui64": 0x0026, + "getDutyCycleLimits": 0x004B, + "getDutyCycleState": 0x0035, + "getExtendedTimeout": 0x007F, + "getExtendedValue": 0x0003, + "getFirstBeacon": 0x003D, + "getKey": 0x006A, + "getKeyTableEntry": 0x0071, + "getLibraryStatus": 0x0001, + "getLogicalChannel": 0x00BA, + "getMfgToken": 0x000B, + "getMulticastTableEntry": 0x0063, + "getNeighbor": 0x0079, + "getNeighborFrameCounter": 0x003E, + "setNeighborFrameCounter": 0x00AD, + "getNetworkParameters": 0x0028, + "getNextBeacon": 0x0004, + "getNodeId": 0x0027, + "getNumStoredBeacons": 0x0008, + "getParentChildParameters": 0x0029, + "getParentClassificationEnabled": 0x00F0, + "getPhyInterfaceCount": 0x00FC, + "getPolicy": 0x0056, + "getRadioParameters": 0x00FD, + "setRadioIeee802154CcaMode": 0x0095, + "getRandomNumber": 0x0049, + "getRouteTableEntry": 0x007B, + "getRoutingShortcutThreshold": 0x00D1, + "getSecurityKeyStatus": 0x00CD, + "getSourceRouteTableEntry": 0x00C1, + "getSourceRouteTableFilledSize": 0x00C2, + "getSourceRouteTableTotalSize": 0x00C3, + "getStandaloneBootloaderVersionPlatMicroPhy": 0x0091, + "getTimer": 0x004E, + "getToken": 0x000A, + "getTokenCount": 0x0100, + "getTokenInfo": 0x0101, + "getTokenData": 0x0102, + "setTokenData": 0x0103, + "resetNode": 0x0104, + "getTransientKeyTableEntry": 0x006D, + "getTransientLinkKey": 0x00CE, + "getTrueRandomEntropySource": 0x004F, + "getValue": 0x00AA, + "getXncpInfo": 0x0013, + "getZllPrimaryChannelMask": 0x00D9, + "getZllSecondaryChannelMask": 0x00DA, + "gpProxyTableGetEntry": 0x00C8, + "gpProxyTableLookup": 0x00C0, + "gpProxyTableProcessGpPairing": 0x00C9, + "gpSinkTableClearAll": 0x00E2, + "gpSinkTableFindOrAllocateEntry": 0x00E1, + "gpSinkTableGetEntry": 0x00DD, + "gpSinkTableInit": 0x0070, + "gpSinkTableLookup": 0x00DE, + "gpSinkTableRemoveEntry": 0x00E0, + "gpSinkTableSetEntry": 0x00DF, + "gpepIncomingMessageHandler": 0x00C5, + "idConflictHandler": 0x007C, + "incomingBootloadMessageHandler": 0x0092, + "incomingManyToOneRouteRequestHandler": 0x007D, + "incomingMessageHandler": 0x0045, + "incomingRouteErrorHandler": 0x0080, + "incomingRouteRecordHandler": 0x0059, + "incomingSenderEui64Handler": 0x0062, + "invalidCommand": 0x0058, + "isHubConnected": 0x00E6, + "isUpTimeLong": 0x00E5, + "isZllNetwork": 0x00BE, + "joinNetwork": 0x001F, + "joinNetworkDirectly": 0x003B, + "launchStandaloneBootloader": 0x008F, + "leaveNetwork": 0x0020, + "lookupEui64ByNodeId": 0x0061, + "lookupNodeIdByEui64": 0x0060, + "macFilterMatchMessageHandler": 0x0046, + "macPassthroughMessageHandler": 0x0097, + "maximumPayloadLength": 0x0033, + "messageSentHandler": 0x003F, + "mfglibEnd": 0x0084, + "mfglibGetChannel": 0x008B, + "mfglibGetPower": 0x008D, + "mfglibRxHandler": 0x008E, + "mfglibSendPacket": 0x0089, + "mfglibSetChannel": 0x008A, + "mfglibSetPower": 0x008C, + "mfglibStart": 0x0083, + "mfglibStartStream": 0x0087, + "mfglibStartTone": 0x0085, + "mfglibStopStream": 0x0088, + "mfglibStopTone": 0x0086, + "multiPhySetRadioChannel": 0x00FB, + "multiPhySetRadioPower": 0x00FA, + "multiPhyStart": 0x00F8, + "multiPhyStop": 0x00F9, + "neighborCount": 0x007A, + "networkFoundHandler": 0x001B, + "networkInit": 0x0017, + "networkState": 0x0018, + "noCallbacks": 0x0007, + "nop": 0x0005, + "permitJoining": 0x0022, + "pollCompleteHandler": 0x0043, + "pollForData": 0x0042, + "pollHandler": 0x0044, + "proxyBroadcast": 0x0037, + "rawTransmitCompleteHandler": 0x0098, + "readAndClearCounters": 0x0065, + "readCounters": 0x00F1, + "remoteDeleteBindingHandler": 0x0032, + "remoteSetBindingHandler": 0x0031, + "removeDevice": 0x00A8, + "replaceAddressTableEntry": 0x0082, + "requestLinkKey": 0x0014, + "resetToFactoryDefaults": 0x00CC, + "scanCompleteHandler": 0x001C, + "sendBootloadMessage": 0x0090, + "sendBroadcast": 0x0036, + "sendLinkPowerDeltaRequest": 0x00F7, + "sendManyToOneRouteRequest": 0x0041, + "sendMulticast": 0x0038, + "sendMulticastWithAlias": 0x003A, + "sendPanIdUpdate": 0x0057, + "sendRawMessage": 0x0096, + "sendRawMessageExtended": 0x0051, + "sendReply": 0x0039, + "sendTrustCenterLinkKey": 0x0067, + "sendUnicast": 0x0034, + "setAddressTableRemoteEui64": 0x005C, + "setAddressTableRemoteNodeId": 0x005D, + "setBeaconClassificationParams": 0x00EF, + "setBinding": 0x002B, + "setBindingRemoteNodeId": 0x0030, + "setBrokenRouteErrorCode": 0x0011, + "setChildData": 0x00AC, + "setConcentrator": 0x0010, + "setConfigurationValue": 0x0053, + "setDutyCycleLimitsInStack": 0x0040, + "setExtendedTimeout": 0x007E, + "setHubConnectivity": 0x00E4, + "setInitialSecurityState": 0x0068, + "setKeyTableEntry": 0x0072, + "setLogicalAndRadioChannel": 0x00B9, + "setLongUpTime": 0x00E3, + "setMacPollFailureWaitTime": 0x00F4, + "setManufacturerCode": 0x0015, + "setMfgToken": 0x000C, + "setMulticastTableEntry": 0x0064, + "setNeighborFrameCounter": 0x00AD, + "setParentClassificationEnabled": 0x00E7, + "setPolicy": 0x0055, + "setPowerDescriptor": 0x0016, + "setPreinstalledCbkeData": 0x00A2, + "setPreinstalledCbkeData283k1": 0x00ED, + "setRadioChannel": 0x009A, + "setRadioIeee802154CcaMode": 0x0095, + "setRadioPower": 0x0099, + "setRoutingShortcutThreshold": 0x00D0, + "setSecurityKey": 0x00CA, + "setSecurityParameters": 0x00CB, + "setSourceRouteDiscoveryMode": 0x005A, + "setTimer": 0x000E, + "setToken": 0x0009, + "setValue": 0x00AB, + "setZllAdditionalState": 0x00D6, + "setZllNodeType": 0x00D5, + "setZllPrimaryChannelMask": 0x00DB, + "setZllSecondaryChannelMask": 0x00DC, + "stackStatusHandler": 0x0019, + "stackTokenChangedHandler": 0x000D, + "startScan": 0x001A, + "stopScan": 0x001D, + "switchNetworkKeyHandler": 0x006E, + "timerHandler": 0x000F, + "trustCenterJoinHandler": 0x0024, + "unicastCurrentNetworkKey": 0x0050, + "unicastNwkKeyUpdate": 0x00A9, + "unusedPanIdFoundHandler": 0x00D2, + "updateTcLinkKey": 0x006C, + "version": 0x0000, + "writeNodeData": 0x00FE, + "zigbeeKeyEstablishmentHandler": 0x009B, + "zllAddressAssignmentHandler": 0x00B8, + "zllClearTokens": 0x0025, + "zllGetTokens": 0x00BC, + "zllNetworkFoundHandler": 0x00B6, + "zllNetworkOps": 0x00B2, + "zllOperationInProgress": 0x00D7, + "zllRxOnWhenIdleGetActive": 0x00D8, + "zllScanCompleteHandler": 0x00B7, + "zllSetDataToken": 0x00BD, + "zllSetInitialSecurityState": 0x00B3, + "zllSetNonZllNetwork": 0x00BF, + "zllSetRadioIdleMode": 0x00D4, + "zllSetRxOnWhenIdle": 0x00B5, + "zllSetSecurityStateWithoutKey": 0x00CF, + "zllStartScan": 0x00B4, + "zllTouchLinkTargetHandler": 0x00BB, +} From 1df29c32192da251c3b256f255339c93ce40f2e9 Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Wed, 22 Feb 2023 12:43:41 -0500 Subject: [PATCH 2/3] Use global zigpy unicast concurrency limit (#530) --- bellows/zigbee/application.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/bellows/zigbee/application.py b/bellows/zigbee/application.py index 02360a63..9ddc98d6 100644 --- a/bellows/zigbee/application.py +++ b/bellows/zigbee/application.py @@ -125,14 +125,6 @@ async def connect(self): ezsp = self._ezsp self._multicast = bellows.multicast.Multicast(ezsp) - - status, count = await ezsp.getConfigurationValue( - ezsp.types.EzspConfigId.CONFIG_APS_UNICAST_MESSAGE_COUNT - ) - assert status == t.EmberStatus.SUCCESS - self._concurrent_requests_semaphore.max_value = count - LOGGER.debug("APS_UNICAST_MESSAGE_COUNT is set to %s", count) - await self.register_endpoints() brd_manuf, brd_name, version = await self._get_board_info() From 4fecb5e470bb2fc23313389d28e85c12bf5d79f7 Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Wed, 22 Feb 2023 12:58:24 -0500 Subject: [PATCH 3/3] 0.34.9 version bump --- bellows/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bellows/__init__.py b/bellows/__init__.py index 52cdb99d..df432fd5 100644 --- a/bellows/__init__.py +++ b/bellows/__init__.py @@ -1,5 +1,5 @@ MAJOR_VERSION = 0 -MINOR_VERSION = 35 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 34 +PATCH_VERSION = "9" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}"