-
Notifications
You must be signed in to change notification settings - Fork 156
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add schema for network parameters (#388)
* Add NETWORK and NETWORK_UPDATE schemas. * Refactor config.py * Validate keys. * Refactor update_network() signature. Remove NETWORK_UPDATE schema. * Add hex number validator/convertor. * Add tests. * Update coverage.
- Loading branch information
Showing
6 changed files
with
279 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
"""Config schemas and validation.""" | ||
|
||
import voluptuous as vol | ||
from zigpy.config.defaults import ( | ||
CONF_NWK_CHANNEL_DEFAULT, | ||
CONF_NWK_CHANNELS_DEFAULT, | ||
CONF_NWK_EXTENDED_PAN_ID_DEFAULT, | ||
CONF_NWK_KEY_DEFAULT, | ||
CONF_NWK_PAN_ID_DEFAULT, | ||
CONF_NWK_TC_LINK_KEY_DEFAULT, | ||
CONF_NWK_UPDATE_ID_DEFAULT, | ||
CONF_OTA_IKEA_DEFAULT, | ||
CONF_OTA_LEDVANCE_DEFAULT, | ||
CONF_OTA_OTAU_DIR_DEFAULT, | ||
) | ||
from zigpy.config.validators import cv_boolean, cv_hex, cv_key | ||
import zigpy.types as t | ||
|
||
CONF_DATABASE = "database_path" | ||
CONF_DEVICE = "device" | ||
CONF_DEVICE_PATH = "path" | ||
CONF_NWK = "network" | ||
CONF_NWK_CHANNEL = "channel" | ||
CONF_NWK_CHANNELS = "channels" | ||
CONF_NWK_EXTENDED_PAN_ID = "extended_pan_id" | ||
CONF_NWK_PAN_ID = "pan_id" | ||
CONF_NWK_KEY = "key" | ||
CONF_NWK_TC_LINK_KEY = "tc_link_key" | ||
CONF_NWK_UPDATE_ID = "update_id" | ||
CONF_OTA = "ota" | ||
CONF_OTA_DIR = "otau_directory" | ||
CONF_OTA_IKEA = "ikea_provider" | ||
CONF_OTA_LEDVANCE = "ledvance_provider" | ||
|
||
SCHEMA_DEVICE = vol.Schema({vol.Required(CONF_DEVICE_PATH): str}) | ||
SCHEMA_NETWORK = vol.Schema( | ||
{ | ||
vol.Optional(CONF_NWK_CHANNEL, default=CONF_NWK_CHANNEL_DEFAULT): vol.All( | ||
cv_hex, vol.Range(min=11, max=26) | ||
), | ||
vol.Optional(CONF_NWK_CHANNELS, default=CONF_NWK_CHANNELS_DEFAULT): vol.All( | ||
list, t.Channels.from_channel_list | ||
), | ||
vol.Optional( | ||
CONF_NWK_EXTENDED_PAN_ID, default=CONF_NWK_EXTENDED_PAN_ID_DEFAULT | ||
): t.ExtendedPanId, | ||
vol.Optional(CONF_NWK_KEY, default=CONF_NWK_KEY_DEFAULT): cv_key, | ||
vol.Optional(CONF_NWK_PAN_ID, default=CONF_NWK_PAN_ID_DEFAULT): vol.All( | ||
cv_hex, t.PanId | ||
), | ||
vol.Optional( | ||
CONF_NWK_TC_LINK_KEY, default=CONF_NWK_TC_LINK_KEY_DEFAULT | ||
): cv_key, | ||
vol.Optional(CONF_NWK_UPDATE_ID, default=CONF_NWK_UPDATE_ID_DEFAULT): vol.All( | ||
cv_hex, vol.Range(min=0, max=255) | ||
), | ||
} | ||
) | ||
SCHEMA_OTA = { | ||
vol.Optional(CONF_OTA_DIR, default=CONF_OTA_OTAU_DIR_DEFAULT): vol.Any(None, str), | ||
vol.Optional(CONF_OTA_IKEA, default=CONF_OTA_IKEA_DEFAULT): cv_boolean, | ||
vol.Optional(CONF_OTA_LEDVANCE, default=CONF_OTA_LEDVANCE_DEFAULT): cv_boolean, | ||
} | ||
|
||
ZIGPY_SCHEMA = vol.Schema( | ||
{ | ||
vol.Optional(CONF_DATABASE, default=None): vol.Any(None, str), | ||
vol.Optional(CONF_NWK, default={}): SCHEMA_NETWORK, | ||
vol.Optional(CONF_OTA, default={}): SCHEMA_OTA, | ||
}, | ||
extra=vol.ALLOW_EXTRA, | ||
) | ||
|
||
CONFIG_SCHEMA = ZIGPY_SCHEMA.extend( | ||
{vol.Required(CONF_DEVICE): SCHEMA_DEVICE}, extra=vol.ALLOW_EXTRA | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
from zigpy import types as t | ||
|
||
CONF_NWK_CHANNEL_DEFAULT = 15 | ||
CONF_NWK_CHANNELS_DEFAULT = [15, 20, 25] | ||
CONF_NWK_EXTENDED_PAN_ID_DEFAULT = t.ExtendedPanId( | ||
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] | ||
) | ||
CONF_NWK_PAN_ID_DEFAULT = t.PanId(0x0000) | ||
CONF_NWK_KEY_DEFAULT = t.KeyData( | ||
[ | ||
0x00, | ||
0x00, | ||
0x00, | ||
0x00, | ||
0x00, | ||
0x00, | ||
0x00, | ||
0x00, | ||
0x00, | ||
0x00, | ||
0x00, | ||
0x00, | ||
0x00, | ||
0x00, | ||
0x00, | ||
0x00, | ||
] | ||
) | ||
CONF_NWK_TC_LINK_KEY_DEFAULT = t.KeyData( | ||
[ | ||
0x5A, | ||
0x69, | ||
0x67, | ||
0x42, | ||
0x65, | ||
0x65, | ||
0x41, | ||
0x6C, | ||
0x6C, | ||
0x69, | ||
0x61, | ||
0x6E, | ||
0x63, | ||
0x65, | ||
0x30, | ||
0x39, | ||
] | ||
) | ||
CONF_NWK_UPDATE_ID_DEFAULT = 0x00 | ||
CONF_OTA_IKEA_DEFAULT = False | ||
CONF_OTA_LEDVANCE_DEFAULT = False | ||
CONF_OTA_OTAU_DIR_DEFAULT = None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
from typing import List, Union | ||
|
||
import voluptuous as vol | ||
import zigpy.types as t | ||
|
||
|
||
def cv_boolean(value: Union[bool, int, str]) -> bool: | ||
"""Validate and coerce a boolean value.""" | ||
if isinstance(value, bool): | ||
return value | ||
if isinstance(value, str): | ||
value = value.lower().strip() | ||
if value in ("1", "true", "yes", "on", "enable"): | ||
return True | ||
if value in ("0", "false", "no", "off", "disable"): | ||
return False | ||
elif isinstance(value, int): | ||
return bool(value) | ||
raise vol.Invalid(f"invalid boolean '{value}' value") | ||
|
||
|
||
def cv_hex(value: Union[int, str]) -> int: | ||
"""Convert string with possible hex number into int.""" | ||
if isinstance(value, int): | ||
return value | ||
|
||
if not isinstance(value, str): | ||
raise vol.Invalid(f"{value} is not a valid hex number") | ||
|
||
try: | ||
if value.startswith("0x"): | ||
value = int(value, base=16) | ||
else: | ||
value = int(value) | ||
except ValueError: | ||
raise vol.Invalid(f"Could not convert '{value}' to number") | ||
|
||
return value | ||
|
||
|
||
def cv_key(key: List[int]) -> t.KeyData: | ||
"""Validate a key.""" | ||
if not isinstance(key, list): | ||
raise vol.Invalid("key is expected to be a list of integers") | ||
|
||
if len(key) != 16: | ||
raise vol.Invalid("key list length must be 16") | ||
|
||
if not any((0 <= e <= 255 for e in key)): | ||
raise vol.Invalid("Key element myst be a within (0..255) range") | ||
|
||
return t.KeyData(key) |