Skip to content

Commit

Permalink
Merge pull request #551 from puddly/rc
Browse files Browse the repository at this point in the history
0.35.2 Release
  • Loading branch information
puddly authored Apr 27, 2023
2 parents 9330e1b + a834be1 commit 9ab1cde
Show file tree
Hide file tree
Showing 11 changed files with 185 additions and 145 deletions.
2 changes: 1 addition & 1 deletion bellows/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
MAJOR_VERSION = 0
MINOR_VERSION = 35
PATCH_VERSION = "1"
PATCH_VERSION = "2"
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
__version__ = f"{__short_version__}.{PATCH_VERSION}"
76 changes: 76 additions & 0 deletions bellows/ezsp/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from __future__ import annotations

import dataclasses

import bellows.ezsp.v4.types as types_v4
import bellows.ezsp.v6.types as types_v6
import bellows.types as t


@dataclasses.dataclass(frozen=True)
class RuntimeConfig:
config_id: t.enum8
value: int
minimum: bool = False


DEFAULT_CONFIG = [
RuntimeConfig(
config_id=types_v4.EzspConfigId.CONFIG_SOURCE_ROUTE_TABLE_SIZE,
value=200,
minimum=True,
),
RuntimeConfig(
config_id=types_v4.EzspConfigId.CONFIG_END_DEVICE_POLL_TIMEOUT,
value=8,
),
RuntimeConfig(
config_id=types_v4.EzspConfigId.CONFIG_INDIRECT_TRANSMISSION_TIMEOUT,
value=7680,
),
RuntimeConfig(
config_id=types_v4.EzspConfigId.CONFIG_STACK_PROFILE,
value=2,
),
RuntimeConfig(
config_id=types_v4.EzspConfigId.CONFIG_SUPPORTED_NETWORKS,
value=1,
minimum=True,
),
RuntimeConfig(
config_id=types_v4.EzspConfigId.CONFIG_MULTICAST_TABLE_SIZE,
value=16,
minimum=True,
),
RuntimeConfig(
config_id=types_v4.EzspConfigId.CONFIG_TRUST_CENTER_ADDRESS_CACHE_SIZE,
value=2,
minimum=True,
),
RuntimeConfig(
config_id=types_v4.EzspConfigId.CONFIG_SECURITY_LEVEL,
value=5,
),
RuntimeConfig(
config_id=types_v4.EzspConfigId.CONFIG_ADDRESS_TABLE_SIZE,
value=16,
minimum=True,
),
RuntimeConfig(
config_id=types_v6.EzspConfigId.CONFIG_TC_REJOINS_USING_WELL_KNOWN_KEY_TIMEOUT_S,
value=90,
),
RuntimeConfig(
config_id=types_v4.EzspConfigId.CONFIG_PAN_ID_CONFLICT_REPORT_THRESHOLD,
value=2,
),
RuntimeConfig(
config_id=types_v4.EzspConfigId.CONFIG_APPLICATION_ZDO_FLAGS,
value=(
t.EmberZdoConfigurationFlags.APP_RECEIVES_SUPPORTED_ZDO_REQUESTS
| t.EmberZdoConfigurationFlags.APP_HANDLES_UNSUPPORTED_ZDO_REQUESTS
),
),
# Must be set last
RuntimeConfig(types_v4.EzspConfigId.CONFIG_PACKET_BUFFER_COUNT, value=0xFF),
]
105 changes: 63 additions & 42 deletions bellows/ezsp/protocol.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import abc
import asyncio
import binascii
import dataclasses
import functools
import logging
import sys
Expand All @@ -16,7 +17,6 @@
from bellows.typing import GatewayType

LOGGER = logging.getLogger(__name__)

EZSP_CMD_TIMEOUT = 5


Expand All @@ -38,9 +38,6 @@ def __init__(self, cb_handler: Callable, gateway: GatewayType) -> None:
self.tc_policy = 0

async def _cfg(self, config_id: int, value: Any) -> None:
if value is None:
return

(status,) = await self.setConfigurationValue(config_id, value)
if status != self.types.EmberStatus.SUCCESS:
LOGGER.warning(
Expand Down Expand Up @@ -68,45 +65,69 @@ async def pre_permit(self, time_s: int) -> None:
async def initialize(self, zigpy_config: Dict) -> None:
"""Initialize EmberZNet Stack."""

buffers = await self.get_free_buffers()
_, conf_buffers = await self.getConfigurationValue(
self.types.EzspConfigId.CONFIG_PACKET_BUFFER_COUNT
)
LOGGER.debug(
"Free/configured buffers before any configurations: %s/%s",
buffers,
conf_buffers,
)
ezsp_config = self.SCHEMAS[CONF_EZSP_CONFIG](zigpy_config[CONF_EZSP_CONFIG])
for config, value in ezsp_config.items():
if config in (self.types.EzspConfigId.CONFIG_PACKET_BUFFER_COUNT.name,):
# we want to set these last
# Prevent circular import
from bellows.ezsp.config import DEFAULT_CONFIG, RuntimeConfig

# Not all config will be present in every EZSP version so only use valid keys
ezsp_config = {}

for cfg in DEFAULT_CONFIG:
try:
config_id = self.types.EzspConfigId[cfg.config_id.name]
except KeyError:
pass
else:
ezsp_config[cfg.config_id.name] = dataclasses.replace(
cfg, config_id=config_id
)

# Override the defaults with user-specified values (or `None` for deletions)
for name, value in self.SCHEMAS[CONF_EZSP_CONFIG](
zigpy_config[CONF_EZSP_CONFIG]
).items():
if value is None:
ezsp_config.pop(name)
continue
await self._cfg(self.types.EzspConfigId[config], value)

buffers = await self.get_free_buffers()
_, conf_buffers = await self.getConfigurationValue(
self.types.EzspConfigId.CONFIG_PACKET_BUFFER_COUNT
)
LOGGER.debug(
"Free/configured buffers before all memory allocation: %s/%s",
buffers,
conf_buffers,
)
c = self.types.EzspConfigId
await self._cfg(
self.types.EzspConfigId.CONFIG_PACKET_BUFFER_COUNT,
ezsp_config[c.CONFIG_PACKET_BUFFER_COUNT.name],
)
buffers = await self.get_free_buffers()
_, conf_buffers = await self.getConfigurationValue(
self.types.EzspConfigId.CONFIG_PACKET_BUFFER_COUNT
)
LOGGER.debug(
"Free/configured buffers after all memory allocation: %s/%s",
buffers,
conf_buffers,
)

ezsp_config[name] = RuntimeConfig(
config_id=self.types.EzspConfigId[name],
value=value,
)

# Make sure CONFIG_PACKET_BUFFER_COUNT is always set last
if self.types.EzspConfigId.CONFIG_PACKET_BUFFER_COUNT.name in ezsp_config:
ezsp_config = {
**ezsp_config,
self.types.EzspConfigId.CONFIG_PACKET_BUFFER_COUNT.name: ezsp_config[
self.types.EzspConfigId.CONFIG_PACKET_BUFFER_COUNT.name
],
}

# Finally, set the config
for cfg in ezsp_config.values():
(status, current_value) = await self.getConfigurationValue(cfg.config_id)

# Only grow some config entries, all others should be set
if (
status == self.types.EmberStatus.SUCCESS
and cfg.minimum
and current_value >= cfg.value
):
LOGGER.debug(
"Current config %s = %s exceeds the default of %s, skipping",
cfg.config_id.name,
current_value,
cfg.value,
)
continue

LOGGER.debug(
"Setting config %s = %s (old value %s)",
cfg.config_id.name,
cfg.value,
current_value,
)
await self._cfg(cfg.config_id, cfg.value)

async def get_free_buffers(self) -> Optional[int]:
status, value = await self.getValue(self.types.EzspValueId.VALUE_FREE_BUFFERS)
Expand Down
73 changes: 30 additions & 43 deletions bellows/ezsp/v4/config.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
import voluptuous as vol

from bellows.config import cv_optional_int, cv_uint16
import bellows.multicast

from .types import (
EmberZdoConfigurationFlags as zdo_flags,
EzspConfigId,
EzspDecisionId,
EzspPolicyId,
)
from .types import EzspConfigId, EzspDecisionId, EzspPolicyId

EZSP_SCHEMA = {
#
# 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
vol.Optional(
EzspConfigId.CONFIG_PACKET_BUFFER_COUNT.name, default=0xFF
): cv_optional_int(min=1, max=255),
vol.Optional(EzspConfigId.CONFIG_PACKET_BUFFER_COUNT.name): cv_optional_int(
min=1, max=255
),
# The maximum number of router neighbors the stack can keep track of. A neighbor
# is a node within radio range
vol.Optional(EzspConfigId.CONFIG_NEIGHBOR_TABLE_SIZE.name): cv_optional_int(
Expand All @@ -40,15 +34,12 @@
# 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 EZSP_CONFIG_TRUST_CENTER_ADDRESS_CA CHE_SIZE)
vol.Optional(
EzspConfigId.CONFIG_ADDRESS_TABLE_SIZE.name, default=16
): cv_optional_int(min=0),
vol.Optional(EzspConfigId.CONFIG_ADDRESS_TABLE_SIZE.name): cv_optional_int(min=0),
#
# The maximum number of multicast groups that the device may be a member of
vol.Optional(
EzspConfigId.CONFIG_MULTICAST_TABLE_SIZE.name,
default=bellows.multicast.Multicast.TABLE_SIZE,
): cv_optional_int(min=0, max=255),
vol.Optional(EzspConfigId.CONFIG_MULTICAST_TABLE_SIZE.name): cv_optional_int(
min=0, max=255
),
#
# 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
Expand All @@ -72,39 +63,39 @@
),
#
# Specifies the stack profile
vol.Optional(EzspConfigId.CONFIG_STACK_PROFILE.name, default=2): cv_optional_int(
vol.Optional(EzspConfigId.CONFIG_STACK_PROFILE.name): cv_optional_int(
min=0, max=255
),
#
# 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)
vol.Optional(EzspConfigId.CONFIG_SECURITY_LEVEL.name, default=5): cv_optional_int(
vol.Optional(EzspConfigId.CONFIG_SECURITY_LEVEL.name): cv_optional_int(
min=0, max=5
),
#
# The maximum number of hops for a message
vol.Optional(EzspConfigId.CONFIG_MAX_HOPS.name): cv_optional_int(min=0, max=30),
#
# The maximum number of end device children that a router will support
vol.Optional(
EzspConfigId.CONFIG_MAX_END_DEVICE_CHILDREN.name, default=32
): cv_optional_int(min=0, max=32),
vol.Optional(EzspConfigId.CONFIG_MAX_END_DEVICE_CHILDREN.name): cv_optional_int(
min=0, max=32
),
#
# The maximum amount of time that the MAC will hold a message for indirect
# transmission to a child
vol.Optional(
EzspConfigId.CONFIG_INDIRECT_TRANSMISSION_TIMEOUT.name, default=7680
EzspConfigId.CONFIG_INDIRECT_TRANSMISSION_TIMEOUT.name
): cv_optional_int(min=0, max=30000),
#
# 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. The timeout corresponding to a value of zero is 10
# seconds. The timeout corresponding to a nonzero value N is 2^N minutes,
# ranging from 2^1 = 2 minutes to 2^14 = 16384 minutes
vol.Optional(
EzspConfigId.CONFIG_END_DEVICE_POLL_TIMEOUT.name, default=60
): cv_optional_int(min=0, max=255),
vol.Optional(EzspConfigId.CONFIG_END_DEVICE_POLL_TIMEOUT.name): cv_optional_int(
min=0, max=255
),
#
# The maximum amount of time that a mobile node can wait between polls. If no
# poll is heard within this timeout, then the parent removes the mobile node
Expand Down Expand Up @@ -135,16 +126,16 @@
# by the NCP is the sum of the value of this setting and the value of
# EZSP_CONFIG_ADDRESS_TABLE_SIZE)
vol.Optional(
EzspConfigId.CONFIG_TRUST_CENTER_ADDRESS_CACHE_SIZE.name, default=2
EzspConfigId.CONFIG_TRUST_CENTER_ADDRESS_CACHE_SIZE.name
): cv_optional_int(min=0),
#
# The size of the source route table
vol.Optional(
EzspConfigId.CONFIG_SOURCE_ROUTE_TABLE_SIZE.name, default=16
): cv_optional_int(min=0),
vol.Optional(EzspConfigId.CONFIG_SOURCE_ROUTE_TABLE_SIZE.name): cv_optional_int(
min=0
),
# The units used for timing out end devices on their parent
vol.Optional(
EzspConfigId.CONFIG_END_DEVICE_POLL_TIMEOUT_SHIFT.name, default=8
EzspConfigId.CONFIG_END_DEVICE_POLL_TIMEOUT_SHIFT.name
): cv_optional_int(min=0, max=10),
#
# The number of blocks of a fragmented message that can be sent in a single
Expand All @@ -159,9 +150,7 @@
#
# 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)
vol.Optional(EzspConfigId.CONFIG_KEY_TABLE_SIZE.name, default=4): cv_optional_int(
min=0
),
vol.Optional(EzspConfigId.CONFIG_KEY_TABLE_SIZE.name): cv_optional_int(min=0),
#
# The APS ACK timeout value (ms). The stack waits this amount of time between
# resends of APS retried messages
Expand All @@ -182,7 +171,7 @@
# The number of PAN id conflict reports that must be received by the network
# manager within one minute to trigger a PAN id change
vol.Optional(
EzspConfigId.CONFIG_PAN_ID_CONFLICT_REPORT_THRESHOLD.name, default=2
EzspConfigId.CONFIG_PAN_ID_CONFLICT_REPORT_THRESHOLD.name
): cv_optional_int(min=1, max=63),
#
# The timeout value in minutes for how long the Trust Center or a normal node
Expand Down Expand Up @@ -210,11 +199,9 @@
# reply to an incoming message, the application must check the APS options
# bitfield within the incomingMessageHandler callback to see if the
# EMBER_APS_OPTION_ZDO_RESPONSE_REQUIRED flag is set
vol.Optional(
EzspConfigId.CONFIG_APPLICATION_ZDO_FLAGS.name,
default=zdo_flags.APP_RECEIVES_SUPPORTED_ZDO_REQUESTS
| zdo_flags.APP_HANDLES_UNSUPPORTED_ZDO_REQUESTS,
): cv_optional_int(min=0, max=255),
vol.Optional(EzspConfigId.CONFIG_APPLICATION_ZDO_FLAGS.name): cv_optional_int(
min=0, max=255
),
#
# The maximum number of broadcasts during a single broadcast timeout period
vol.Optional(EzspConfigId.CONFIG_BROADCAST_TABLE_SIZE.name): cv_optional_int(
Expand All @@ -227,9 +214,9 @@
),
#
# The number of supported networks
vol.Optional(
EzspConfigId.CONFIG_SUPPORTED_NETWORKS.name, default=1
): cv_optional_int(min=1, max=2),
vol.Optional(EzspConfigId.CONFIG_SUPPORTED_NETWORKS.name): cv_optional_int(
min=1, max=2
),
#
# Whether multicasts are sent to the RxOnWhenIdle=true address (0xFFFD) or the
# sleepy broadcast address (0xFFFF). The RxOnWhenIdle=true address is the ZigBee
Expand Down
3 changes: 1 addition & 2 deletions bellows/ezsp/v8/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@
): cv_optional_int(min=0, max=14),
vol.Optional(EzspConfigId.CONFIG_KEY_TABLE_SIZE.name): cv_optional_int(min=0),
vol.Optional(
EzspConfigId.CONFIG_TC_REJOINS_USING_WELL_KNOWN_KEY_TIMEOUT_S.name,
default=90,
EzspConfigId.CONFIG_TC_REJOINS_USING_WELL_KNOWN_KEY_TIMEOUT_S.name
): cv_optional_int(min=0),
},
)
Expand Down
Loading

0 comments on commit 9ab1cde

Please sign in to comment.