1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-29 22:24:26 +00:00

Add support for BLE passkey authentication (#4258)

Co-authored-by: Branden Cash <203336+ammmze@users.noreply.github.com>
This commit is contained in:
Mat931
2023-05-01 21:25:10 +00:00
committed by GitHub
parent c97d361b6c
commit 1c4af08ed3
7 changed files with 312 additions and 5 deletions

View File

@@ -29,8 +29,35 @@ BLEClientConnectTrigger = ble_client_ns.class_(
BLEClientDisconnectTrigger = ble_client_ns.class_(
"BLEClientDisconnectTrigger", automation.Trigger.template(BLEClientNodeConstRef)
)
BLEClientPasskeyRequestTrigger = ble_client_ns.class_(
"BLEClientPasskeyRequestTrigger", automation.Trigger.template(BLEClientNodeConstRef)
)
BLEClientPasskeyNotificationTrigger = ble_client_ns.class_(
"BLEClientPasskeyNotificationTrigger",
automation.Trigger.template(BLEClientNodeConstRef, cg.uint32),
)
BLEClientNumericComparisonRequestTrigger = ble_client_ns.class_(
"BLEClientNumericComparisonRequestTrigger",
automation.Trigger.template(BLEClientNodeConstRef, cg.uint32),
)
# Actions
BLEWriteAction = ble_client_ns.class_("BLEClientWriteAction", automation.Action)
BLEPasskeyReplyAction = ble_client_ns.class_(
"BLEClientPasskeyReplyAction", automation.Action
)
BLENumericComparisonReplyAction = ble_client_ns.class_(
"BLEClientNumericComparisonReplyAction", automation.Action
)
BLERemoveBondAction = ble_client_ns.class_(
"BLEClientRemoveBondAction", automation.Action
)
CONF_PASSKEY = "passkey"
CONF_ACCEPT = "accept"
CONF_ON_PASSKEY_REQUEST = "on_passkey_request"
CONF_ON_PASSKEY_NOTIFICATION = "on_passkey_notification"
CONF_ON_NUMERIC_COMPARISON_REQUEST = "on_numeric_comparison_request"
# Espressif platformio framework is built with MAX_BLE_CONN to 3, so
# enforce this in yaml checks.
@@ -56,6 +83,29 @@ CONFIG_SCHEMA = (
),
}
),
cv.Optional(CONF_ON_PASSKEY_REQUEST): automation.validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
BLEClientPasskeyRequestTrigger
),
}
),
cv.Optional(CONF_ON_PASSKEY_NOTIFICATION): automation.validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
BLEClientPasskeyNotificationTrigger
),
}
),
cv.Optional(
CONF_ON_NUMERIC_COMPARISON_REQUEST
): automation.validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
BLEClientNumericComparisonRequestTrigger
),
}
),
}
)
.extend(cv.COMPONENT_SCHEMA)
@@ -85,13 +135,34 @@ BLE_WRITE_ACTION_SCHEMA = cv.Schema(
}
)
BLE_NUMERIC_COMPARISON_REPLY_ACTION_SCHEMA = cv.Schema(
{
cv.GenerateID(CONF_ID): cv.use_id(BLEClient),
cv.Required(CONF_ACCEPT): cv.templatable(cv.boolean),
}
)
BLE_PASSKEY_REPLY_ACTION_SCHEMA = cv.Schema(
{
cv.GenerateID(CONF_ID): cv.use_id(BLEClient),
cv.Required(CONF_PASSKEY): cv.templatable(cv.int_range(min=0, max=999999)),
}
)
BLE_REMOVE_BOND_ACTION_SCHEMA = cv.Schema(
{
cv.GenerateID(CONF_ID): cv.use_id(BLEClient),
}
)
@automation.register_action(
"ble_client.ble_write", BLEWriteAction, BLE_WRITE_ACTION_SCHEMA
)
async def ble_write_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, paren)
parent = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, parent)
value = config[CONF_VALUE]
if cg.is_template(value):
@@ -137,6 +208,54 @@ async def ble_write_to_code(config, action_id, template_arg, args):
return var
@automation.register_action(
"ble_client.numeric_comparison_reply",
BLENumericComparisonReplyAction,
BLE_NUMERIC_COMPARISON_REPLY_ACTION_SCHEMA,
)
async def numeric_comparison_reply_to_code(config, action_id, template_arg, args):
parent = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, parent)
accept = config[CONF_ACCEPT]
if cg.is_template(accept):
templ = await cg.templatable(accept, args, cg.bool_)
cg.add(var.set_value_template(templ))
else:
cg.add(var.set_value_simple(accept))
return var
@automation.register_action(
"ble_client.passkey_reply", BLEPasskeyReplyAction, BLE_PASSKEY_REPLY_ACTION_SCHEMA
)
async def passkey_reply_to_code(config, action_id, template_arg, args):
parent = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, parent)
passkey = config[CONF_PASSKEY]
if cg.is_template(passkey):
templ = await cg.templatable(passkey, args, cg.uint32)
cg.add(var.set_value_template(templ))
else:
cg.add(var.set_value_simple(passkey))
return var
@automation.register_action(
"ble_client.remove_bond",
BLERemoveBondAction,
BLE_REMOVE_BOND_ACTION_SCHEMA,
)
async def remove_bond_to_code(config, action_id, template_arg, args):
parent = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, parent)
return var
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
@@ -148,3 +267,12 @@ async def to_code(config):
for conf in config.get(CONF_ON_DISCONNECT, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
await automation.build_automation(trigger, [], conf)
for conf in config.get(CONF_ON_PASSKEY_REQUEST, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
await automation.build_automation(trigger, [], conf)
for conf in config.get(CONF_ON_PASSKEY_NOTIFICATION, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
await automation.build_automation(trigger, [(cg.uint32, "passkey")], conf)
for conf in config.get(CONF_ON_NUMERIC_COMPARISON_REQUEST, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
await automation.build_automation(trigger, [(cg.uint32, "passkey")], conf)