mirror of
https://github.com/esphome/esphome.git
synced 2024-11-30 18:54:14 +01:00
Import BT UUID validations
This commit is contained in:
parent
d20011d0b2
commit
fcb20b17f7
3 changed files with 47 additions and 61 deletions
|
@ -1,3 +1,5 @@
|
|||
import re
|
||||
|
||||
from esphome import automation
|
||||
import esphome.codegen as cg
|
||||
from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant
|
||||
|
@ -61,6 +63,43 @@ CONFIG_SCHEMA = cv.Schema(
|
|||
).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
bt_uuid16_format = "XXXX"
|
||||
bt_uuid32_format = "XXXXXXXX"
|
||||
bt_uuid128_format = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
|
||||
|
||||
|
||||
def bt_uuid(value):
|
||||
in_value = cv.string_strict(value)
|
||||
value = in_value.upper()
|
||||
|
||||
if len(value) == len(bt_uuid16_format):
|
||||
pattern = re.compile("^[A-F|0-9]{4,}$")
|
||||
if not pattern.match(value):
|
||||
raise cv.Invalid(
|
||||
f"Invalid hexadecimal value for 16 bit UUID format: '{in_value}'"
|
||||
)
|
||||
return value
|
||||
if len(value) == len(bt_uuid32_format):
|
||||
pattern = re.compile("^[A-F|0-9]{8,}$")
|
||||
if not pattern.match(value):
|
||||
raise cv.Invalid(
|
||||
f"Invalid hexadecimal value for 32 bit UUID format: '{in_value}'"
|
||||
)
|
||||
return value
|
||||
if len(value) == len(bt_uuid128_format):
|
||||
pattern = re.compile(
|
||||
"^[A-F|0-9]{8,}-[A-F|0-9]{4,}-[A-F|0-9]{4,}-[A-F|0-9]{4,}-[A-F|0-9]{12,}$"
|
||||
)
|
||||
if not pattern.match(value):
|
||||
raise cv.Invalid(
|
||||
f"Invalid hexadecimal value for 128 UUID format: '{in_value}'"
|
||||
)
|
||||
return value
|
||||
raise cv.Invalid(
|
||||
f"Service UUID must be in 16 bit '{bt_uuid16_format}', 32 bit '{bt_uuid32_format}', or 128 bit '{bt_uuid128_format}' format"
|
||||
)
|
||||
|
||||
|
||||
def validate_variant(_):
|
||||
variant = get_esp32_variant()
|
||||
if variant in NO_BLUETOOTH_VARIANTS:
|
||||
|
|
|
@ -2,6 +2,7 @@ from esphome import automation
|
|||
import esphome.codegen as cg
|
||||
from esphome.components import esp32_ble
|
||||
from esphome.components.esp32 import add_idf_sdkconfig_option
|
||||
from esphome.components.esp32_ble import bt_uuid, bt_uuid16_format, bt_uuid32_format, bt_uuid128_format
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
|
@ -70,12 +71,6 @@ PROPERTY_MAP = {
|
|||
}
|
||||
|
||||
|
||||
def validate_uuid(value):
|
||||
if len(value) != 36:
|
||||
raise cv.Invalid("UUID must be exactly 36 characters long")
|
||||
return value
|
||||
|
||||
|
||||
def validate_on_write(char_config):
|
||||
if CONF_ON_WRITE in char_config:
|
||||
if not char_config[CONF_WRITE] and not char_config[CONF_WRITE_NO_RESPONSE]:
|
||||
|
@ -113,8 +108,6 @@ def validate_notify_action(action_char_id):
|
|||
return action_char_id
|
||||
|
||||
|
||||
UUID_SCHEMA = cv.Any(cv.All(cv.string, validate_uuid), cv.uint32_t)
|
||||
|
||||
DESCRIPTOR_VALUE_SCHEMA = cv.Any(
|
||||
cv.boolean,
|
||||
cv.float_,
|
||||
|
@ -140,7 +133,7 @@ CHARACTERISTIC_VALUE_SCHEMA = cv.Any(
|
|||
DESCRIPTOR_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(BLEDescriptor),
|
||||
cv.Required(CONF_UUID): UUID_SCHEMA,
|
||||
cv.Required(CONF_UUID): bt_uuid,
|
||||
cv.Required(CONF_VALUE): DESCRIPTOR_VALUE_SCHEMA,
|
||||
}
|
||||
)
|
||||
|
@ -148,7 +141,7 @@ DESCRIPTOR_SCHEMA = cv.Schema(
|
|||
SERVICE_CHARACTERISTIC_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(BLECharacteristic),
|
||||
cv.Required(CONF_UUID): UUID_SCHEMA,
|
||||
cv.Required(CONF_UUID): bt_uuid,
|
||||
cv.Optional(CONF_WRITE_NO_RESPONSE, default=False): cv.boolean,
|
||||
cv.Optional(CONF_VALUE): CHARACTERISTIC_VALUE_SCHEMA,
|
||||
cv.GenerateID(CONF_VALUE_ACTION_ID_): cv.declare_id(
|
||||
|
@ -165,7 +158,7 @@ SERVICE_CHARACTERISTIC_SCHEMA = cv.Schema(
|
|||
SERVICE_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(BLEService),
|
||||
cv.Required(CONF_UUID): UUID_SCHEMA,
|
||||
cv.Required(CONF_UUID): bt_uuid,
|
||||
cv.Optional(CONF_ADVERTISE, default=False): cv.boolean,
|
||||
cv.Optional(CONF_CHARACTERISTICS, default=[]): cv.ensure_list(
|
||||
SERVICE_CHARACTERISTIC_SCHEMA
|
||||
|
@ -192,14 +185,6 @@ def parse_properties(char_conf):
|
|||
)
|
||||
|
||||
|
||||
def parse_uuid(uuid):
|
||||
# If the UUID is a string, use from_raw
|
||||
if isinstance(uuid, str):
|
||||
return ESPBTUUID_ns.from_raw(uuid)
|
||||
# Otherwise, use from_uint32
|
||||
return ESPBTUUID_ns.from_uint32(uuid)
|
||||
|
||||
|
||||
def parse_descriptor_value(value):
|
||||
# Compute the maximum length of the descriptor value
|
||||
# Also parse the value for byte arrays
|
||||
|
@ -288,7 +273,7 @@ async def to_code(config):
|
|||
service_var = cg.Pvariable(
|
||||
service_config[CONF_ID],
|
||||
var.create_service(
|
||||
parse_uuid(service_config[CONF_UUID]),
|
||||
ESPBTUUID_ns.from_raw(service_config[CONF_UUID]),
|
||||
service_config[CONF_ADVERTISE],
|
||||
num_handles,
|
||||
),
|
||||
|
@ -297,7 +282,7 @@ async def to_code(config):
|
|||
char_var = cg.Pvariable(
|
||||
char_conf[CONF_ID],
|
||||
service_var.create_characteristic(
|
||||
parse_uuid(char_conf[CONF_UUID]),
|
||||
ESPBTUUID_ns.from_raw(char_conf[CONF_UUID]),
|
||||
parse_properties(char_conf),
|
||||
),
|
||||
)
|
||||
|
@ -326,7 +311,7 @@ async def to_code(config):
|
|||
)
|
||||
desc_var = cg.new_Pvariable(
|
||||
descriptor_conf[CONF_ID],
|
||||
parse_uuid(descriptor_conf[CONF_UUID]),
|
||||
ESPBTUUID_ns.from_raw(descriptor_conf[CONF_UUID]),
|
||||
max_length,
|
||||
)
|
||||
if CONF_VALUE in descriptor_conf:
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import re
|
||||
|
||||
from esphome import automation
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import esp32_ble
|
||||
from esphome.components.esp32 import add_idf_sdkconfig_option
|
||||
from esphome.components.esp32_ble import bt_uuid, bt_uuid16_format, bt_uuid32_format, bt_uuid128_format
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_ACTIVE,
|
||||
|
@ -86,43 +85,6 @@ def validate_scan_parameters(config):
|
|||
return config
|
||||
|
||||
|
||||
bt_uuid16_format = "XXXX"
|
||||
bt_uuid32_format = "XXXXXXXX"
|
||||
bt_uuid128_format = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
|
||||
|
||||
|
||||
def bt_uuid(value):
|
||||
in_value = cv.string_strict(value)
|
||||
value = in_value.upper()
|
||||
|
||||
if len(value) == len(bt_uuid16_format):
|
||||
pattern = re.compile("^[A-F|0-9]{4,}$")
|
||||
if not pattern.match(value):
|
||||
raise cv.Invalid(
|
||||
f"Invalid hexadecimal value for 16 bit UUID format: '{in_value}'"
|
||||
)
|
||||
return value
|
||||
if len(value) == len(bt_uuid32_format):
|
||||
pattern = re.compile("^[A-F|0-9]{8,}$")
|
||||
if not pattern.match(value):
|
||||
raise cv.Invalid(
|
||||
f"Invalid hexadecimal value for 32 bit UUID format: '{in_value}'"
|
||||
)
|
||||
return value
|
||||
if len(value) == len(bt_uuid128_format):
|
||||
pattern = re.compile(
|
||||
"^[A-F|0-9]{8,}-[A-F|0-9]{4,}-[A-F|0-9]{4,}-[A-F|0-9]{4,}-[A-F|0-9]{12,}$"
|
||||
)
|
||||
if not pattern.match(value):
|
||||
raise cv.Invalid(
|
||||
f"Invalid hexadecimal value for 128 UUID format: '{in_value}'"
|
||||
)
|
||||
return value
|
||||
raise cv.Invalid(
|
||||
f"Service UUID must be in 16 bit '{bt_uuid16_format}', 32 bit '{bt_uuid32_format}', or 128 bit '{bt_uuid128_format}' format"
|
||||
)
|
||||
|
||||
|
||||
def as_hex(value):
|
||||
return cg.RawExpression(f"0x{value}ULL")
|
||||
|
||||
|
|
Loading…
Reference in a new issue