mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	[api] `homeassistant.action replaces homeassistant.service` (#7171)
				
					
				
			This commit is contained in:
		| @@ -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) | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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" | ||||||
|   | |||||||
| @@ -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[] | ||||||
|   | |||||||
| @@ -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: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user