[api] `homeassistant.action replaces homeassistant.service` (#7171)

This commit is contained in:
Jesse Hills 2024-08-01 22:38:36 +12:00 committed by GitHub
parent 144f1d3663
commit cb9906b921
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 103 additions and 63 deletions

View file

@ -1,25 +1,27 @@
import base64 import base64
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import automation from esphome import automation
from esphome.automation import Condition from esphome.automation import Condition
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.const import ( from esphome.const import (
CONF_ACTION,
CONF_ACTIONS,
CONF_DATA, CONF_DATA,
CONF_DATA_TEMPLATE, CONF_DATA_TEMPLATE,
CONF_EVENT,
CONF_ID, CONF_ID,
CONF_KEY, CONF_KEY,
CONF_ON_CLIENT_CONNECTED,
CONF_ON_CLIENT_DISCONNECTED,
CONF_PASSWORD, CONF_PASSWORD,
CONF_PORT, CONF_PORT,
CONF_REBOOT_TIMEOUT, CONF_REBOOT_TIMEOUT,
CONF_SERVICE, CONF_SERVICE,
CONF_VARIABLES,
CONF_SERVICES, CONF_SERVICES,
CONF_TRIGGER_ID,
CONF_EVENT,
CONF_TAG, CONF_TAG,
CONF_ON_CLIENT_CONNECTED, CONF_TRIGGER_ID,
CONF_ON_CLIENT_DISCONNECTED, CONF_VARIABLES,
) )
from esphome.core import coroutine_with_priority from esphome.core import coroutine_with_priority
@ -63,40 +65,51 @@ def validate_encryption_key(value):
return value return value
CONFIG_SCHEMA = cv.Schema( ACTIONS_SCHEMA = automation.validate_automation(
{ {
cv.GenerateID(): cv.declare_id(APIServer), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(UserServiceTrigger),
cv.Optional(CONF_PORT, default=6053): cv.port, cv.Exclusive(CONF_SERVICE, group_of_exclusion=CONF_ACTION): cv.valid_name,
cv.Optional(CONF_PASSWORD, default=""): cv.string_strict, cv.Exclusive(CONF_ACTION, group_of_exclusion=CONF_ACTION): cv.valid_name,
cv.Optional( cv.Optional(CONF_VARIABLES, default={}): cv.Schema(
CONF_REBOOT_TIMEOUT, default="15min"
): cv.positive_time_period_milliseconds,
cv.Optional(CONF_SERVICES): automation.validate_automation(
{ {
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(UserServiceTrigger), cv.validate_id_name: cv.one_of(*SERVICE_ARG_NATIVE_TYPES, lower=True),
cv.Required(CONF_SERVICE): cv.valid_name,
cv.Optional(CONF_VARIABLES, default={}): cv.Schema(
{
cv.validate_id_name: cv.one_of(
*SERVICE_ARG_NATIVE_TYPES, lower=True
),
}
),
} }
), ),
cv.Optional(CONF_ENCRYPTION): cv.Schema( },
{ cv.All(
cv.Required(CONF_KEY): validate_encryption_key, cv.has_exactly_one_key(CONF_SERVICE, CONF_ACTION),
} cv.rename_key(CONF_SERVICE, CONF_ACTION),
), ),
cv.Optional(CONF_ON_CLIENT_CONNECTED): automation.validate_automation( )
single=True
), CONFIG_SCHEMA = cv.All(
cv.Optional(CONF_ON_CLIENT_DISCONNECTED): automation.validate_automation( cv.Schema(
single=True {
), cv.GenerateID(): cv.declare_id(APIServer),
} cv.Optional(CONF_PORT, default=6053): cv.port,
).extend(cv.COMPONENT_SCHEMA) cv.Optional(CONF_PASSWORD, default=""): cv.string_strict,
cv.Optional(
CONF_REBOOT_TIMEOUT, default="15min"
): cv.positive_time_period_milliseconds,
cv.Exclusive(
CONF_SERVICES, group_of_exclusion=CONF_ACTIONS
): ACTIONS_SCHEMA,
cv.Exclusive(CONF_ACTIONS, group_of_exclusion=CONF_ACTIONS): ACTIONS_SCHEMA,
cv.Optional(CONF_ENCRYPTION): cv.Schema(
{
cv.Required(CONF_KEY): validate_encryption_key,
}
),
cv.Optional(CONF_ON_CLIENT_CONNECTED): automation.validate_automation(
single=True
),
cv.Optional(CONF_ON_CLIENT_DISCONNECTED): automation.validate_automation(
single=True
),
}
).extend(cv.COMPONENT_SCHEMA),
cv.rename_key(CONF_SERVICES, CONF_ACTIONS),
)
@coroutine_with_priority(40.0) @coroutine_with_priority(40.0)
@ -108,7 +121,7 @@ async def to_code(config):
cg.add(var.set_password(config[CONF_PASSWORD])) cg.add(var.set_password(config[CONF_PASSWORD]))
cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT])) cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT]))
for conf in config.get(CONF_SERVICES, []): for conf in config.get(CONF_ACTIONS, []):
template_args = [] template_args = []
func_args = [] func_args = []
service_arg_names = [] service_arg_names = []
@ -119,7 +132,7 @@ async def to_code(config):
service_arg_names.append(name) service_arg_names.append(name)
templ = cg.TemplateArguments(*template_args) templ = cg.TemplateArguments(*template_args)
trigger = cg.new_Pvariable( trigger = cg.new_Pvariable(
conf[CONF_TRIGGER_ID], templ, conf[CONF_SERVICE], service_arg_names conf[CONF_TRIGGER_ID], templ, conf[CONF_ACTION], service_arg_names
) )
cg.add(var.register_user_service(trigger)) cg.add(var.register_user_service(trigger))
await automation.build_automation(trigger, func_args, conf) await automation.build_automation(trigger, func_args, conf)
@ -152,28 +165,43 @@ async def to_code(config):
KEY_VALUE_SCHEMA = cv.Schema({cv.string: cv.templatable(cv.string_strict)}) KEY_VALUE_SCHEMA = cv.Schema({cv.string: cv.templatable(cv.string_strict)})
HOMEASSISTANT_SERVICE_ACTION_SCHEMA = cv.Schema(
{ HOMEASSISTANT_ACTION_ACTION_SCHEMA = cv.All(
cv.GenerateID(): cv.use_id(APIServer), cv.Schema(
cv.Required(CONF_SERVICE): cv.templatable(cv.string), {
cv.Optional(CONF_DATA, default={}): KEY_VALUE_SCHEMA, cv.GenerateID(): cv.use_id(APIServer),
cv.Optional(CONF_DATA_TEMPLATE, default={}): KEY_VALUE_SCHEMA, cv.Exclusive(CONF_SERVICE, group_of_exclusion=CONF_ACTION): cv.templatable(
cv.Optional(CONF_VARIABLES, default={}): cv.Schema( cv.string
{cv.string: cv.returning_lambda} ),
), cv.Exclusive(CONF_ACTION, group_of_exclusion=CONF_ACTION): cv.templatable(
} cv.string
),
cv.Optional(CONF_DATA, default={}): KEY_VALUE_SCHEMA,
cv.Optional(CONF_DATA_TEMPLATE, default={}): KEY_VALUE_SCHEMA,
cv.Optional(CONF_VARIABLES, default={}): cv.Schema(
{cv.string: cv.returning_lambda}
),
}
),
cv.has_exactly_one_key(CONF_SERVICE, CONF_ACTION),
cv.rename_key(CONF_SERVICE, CONF_ACTION),
) )
@automation.register_action(
"homeassistant.action",
HomeAssistantServiceCallAction,
HOMEASSISTANT_ACTION_ACTION_SCHEMA,
)
@automation.register_action( @automation.register_action(
"homeassistant.service", "homeassistant.service",
HomeAssistantServiceCallAction, HomeAssistantServiceCallAction,
HOMEASSISTANT_SERVICE_ACTION_SCHEMA, HOMEASSISTANT_ACTION_ACTION_SCHEMA,
) )
async def homeassistant_service_to_code(config, action_id, template_arg, args): async def homeassistant_service_to_code(config, action_id, template_arg, args):
serv = await cg.get_variable(config[CONF_ID]) serv = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, serv, False) var = cg.new_Pvariable(action_id, template_arg, serv, False)
templ = await cg.templatable(config[CONF_SERVICE], args, None) templ = await cg.templatable(config[CONF_ACTION], args, None)
cg.add(var.set_service(templ)) cg.add(var.set_service(templ))
for key, value in config[CONF_DATA].items(): for key, value in config[CONF_DATA].items():
templ = await cg.templatable(value, args, None) templ = await cg.templatable(value, args, None)

View file

@ -2181,3 +2181,13 @@ SOURCE_SCHEMA = Any(
} }
), ),
) )
def rename_key(old_key, new_key):
def validator(config: dict) -> dict:
config = config.copy()
if old_key in config:
config[new_key] = config.pop(old_key)
return config
return validator

View file

@ -37,8 +37,10 @@ CONF_ACCELERATION_Y = "acceleration_y"
CONF_ACCELERATION_Z = "acceleration_z" CONF_ACCELERATION_Z = "acceleration_z"
CONF_ACCURACY = "accuracy" CONF_ACCURACY = "accuracy"
CONF_ACCURACY_DECIMALS = "accuracy_decimals" CONF_ACCURACY_DECIMALS = "accuracy_decimals"
CONF_ACTION = "action"
CONF_ACTION_ID = "action_id" CONF_ACTION_ID = "action_id"
CONF_ACTION_STATE_TOPIC = "action_state_topic" CONF_ACTION_STATE_TOPIC = "action_state_topic"
CONF_ACTIONS = "actions"
CONF_ACTIVE = "active" CONF_ACTIVE = "active"
CONF_ACTIVE_POWER = "active_power" CONF_ACTIVE_POWER = "active_power"
CONF_ACTUAL_GAIN = "actual_gain" CONF_ACTUAL_GAIN = "actual_gain"

View file

@ -5,8 +5,8 @@ esphome:
event: esphome.button_pressed event: esphome.button_pressed
data: data:
message: Button was pressed message: Button was pressed
- homeassistant.service: - homeassistant.action:
service: notify.html5 action: notify.html5
data: data:
message: Button was pressed message: Button was pressed
- homeassistant.tag_scanned: pulse - homeassistant.tag_scanned: pulse
@ -21,8 +21,8 @@ api:
reboot_timeout: 0min reboot_timeout: 0min
encryption: encryption:
key: bOFFzzvfpg5DB94DuBGLXD/hMnhpDKgP9UQyBulwWVU= key: bOFFzzvfpg5DB94DuBGLXD/hMnhpDKgP9UQyBulwWVU=
services: actions:
- service: hello_world - action: hello_world
variables: variables:
name: string name: string
then: then:
@ -30,10 +30,10 @@ api:
format: Hello World %s! format: Hello World %s!
args: args:
- name.c_str() - name.c_str()
- service: empty_service - action: empty_action
then: then:
- logger.log: Service Called - logger.log: Action Called
- service: all_types - action: all_types
variables: variables:
bool_: bool bool_: bool
int_: int int_: int
@ -41,7 +41,7 @@ api:
string_: string string_: string
then: then:
- logger.log: Something happened - logger.log: Something happened
- service: array_types - action: array_types
variables: variables:
bool_arr: bool[] bool_arr: bool[]
int_arr: int[] int_arr: int[]

View file

@ -13,12 +13,12 @@ esphome:
message: The humidity is {{ my_variable }}%. message: The humidity is {{ my_variable }}%.
variables: variables:
my_variable: "return id(ha_hello_world_temperature).state;" my_variable: "return id(ha_hello_world_temperature).state;"
- homeassistant.service: - homeassistant.action:
service: notify.html5 action: notify.html5
data: data:
message: Button was pressed message: Button was pressed
- homeassistant.service: - homeassistant.action:
service: notify.html5 action: notify.html5
data: data:
title: New Humidity title: New Humidity
data_template: data_template: