@@ -690,6 +690,7 @@ def __init__(
690
690
self .have_trigger = False
691
691
self .setup_ok = False
692
692
self .run_on_startup = False
693
+ self .run_on_shutdown = False
693
694
694
695
if self .state_active is not None :
695
696
self .active_expr = AstEval (
@@ -702,14 +703,17 @@ def __init__(
702
703
self .active_expr .get_logger ().error (exc )
703
704
return
704
705
706
+ if "time_trigger" in trig_cfg and self .time_trigger is None :
707
+ self .run_on_startup = True
705
708
if self .time_trigger is not None :
706
709
while "startup" in self .time_trigger :
707
710
self .run_on_startup = True
708
711
self .time_trigger .remove ("startup" )
712
+ while "shutdown" in self .time_trigger :
713
+ self .run_on_shutdown = True
714
+ self .time_trigger .remove ("shutdown" )
709
715
if len (self .time_trigger ) == 0 :
710
716
self .time_trigger = None
711
- if "time_trigger" in trig_cfg and self .time_trigger is None :
712
- self .run_on_startup = True
713
717
714
718
if self .state_trigger is not None :
715
719
state_trig = []
@@ -783,7 +787,12 @@ def stop(self):
783
787
if self .mqtt_trigger is not None :
784
788
Mqtt .notify_del (self .mqtt_trigger [0 ], self .notify_q )
785
789
if self .task :
786
- Function .task_cancel (self .task )
790
+ Function .reaper_cancel (self .task )
791
+ if self .run_on_shutdown :
792
+ notify_type = "shutdown"
793
+ notify_info = {"trigger_type" : "shutdown" , "trigger_time" : None }
794
+ action_future = self .call_action (notify_type , notify_info , run_task = False )
795
+ Function .reaper_await (action_future )
787
796
788
797
def start (self ):
789
798
"""Start this trigger task."""
@@ -1000,30 +1009,6 @@ async def trigger_watch(self):
1000
1009
)
1001
1010
continue
1002
1011
1003
- action_ast_ctx = AstEval (
1004
- f"{ self .action .global_ctx_name } .{ self .action .name } " , self .action .global_ctx
1005
- )
1006
- Function .install_ast_funcs (action_ast_ctx )
1007
- task_unique_func = None
1008
- if self .task_unique is not None :
1009
- task_unique_func = Function .task_unique_factory (action_ast_ctx )
1010
-
1011
- #
1012
- # check for @task_unique with kill_me=True
1013
- #
1014
- if (
1015
- self .task_unique is not None
1016
- and self .task_unique_kwargs
1017
- and self .task_unique_kwargs ["kill_me" ]
1018
- and Function .unique_name_used (action_ast_ctx , self .task_unique )
1019
- ):
1020
- _LOGGER .debug (
1021
- "trigger %s got %s trigger, @task_unique kill_me=True prevented new action" ,
1022
- notify_type ,
1023
- self .name ,
1024
- )
1025
- continue
1026
-
1027
1012
if (
1028
1013
self .time_active_hold_off is not None
1029
1014
and last_trig_time is not None
@@ -1037,49 +1022,8 @@ async def trigger_watch(self):
1037
1022
)
1038
1023
continue
1039
1024
1040
- # Create new HASS Context with incoming as parent
1041
- if "context" in func_args and isinstance (func_args ["context" ], Context ):
1042
- hass_context = Context (parent_id = func_args ["context" ].id )
1043
- else :
1044
- hass_context = Context ()
1045
-
1046
- # Fire an event indicating that pyscript is running
1047
- # Note: the event must have an entity_id for logbook to work correctly.
1048
- ev_name = self .name .replace ("." , "_" )
1049
- ev_entity_id = f"pyscript.{ ev_name } "
1050
-
1051
- event_data = dict (name = ev_name , entity_id = ev_entity_id , func_args = func_args )
1052
- Function .hass .bus .async_fire ("pyscript_running" , event_data , context = hass_context )
1053
-
1054
- _LOGGER .debug (
1055
- "trigger %s got %s trigger, running action (kwargs = %s)" ,
1056
- self .name ,
1057
- notify_type ,
1058
- func_args ,
1059
- )
1060
-
1061
- async def do_func_call (func , ast_ctx , task_unique , task_unique_func , hass_context , ** kwargs ):
1062
- # Store HASS Context for this Task
1063
- Function .store_hass_context (hass_context )
1064
-
1065
- if task_unique and task_unique_func :
1066
- await task_unique_func (task_unique )
1067
- await func .call (ast_ctx , ** kwargs )
1068
- if ast_ctx .get_exception_obj ():
1069
- ast_ctx .get_logger ().error (ast_ctx .get_exception_long ())
1070
-
1071
- last_trig_time = time .monotonic ()
1072
-
1073
- Function .create_task (
1074
- do_func_call (
1075
- self .action ,
1076
- action_ast_ctx ,
1077
- self .task_unique ,
1078
- task_unique_func ,
1079
- hass_context ,
1080
- ** func_args ,
1081
- )
1082
- )
1025
+ if self .call_action (notify_type , func_args ):
1026
+ last_trig_time = time .monotonic ()
1083
1027
1084
1028
except asyncio .CancelledError :
1085
1029
raise
@@ -1094,3 +1038,63 @@ async def do_func_call(func, ast_ctx, task_unique, task_unique_func, hass_contex
1094
1038
if self .mqtt_trigger is not None :
1095
1039
Mqtt .notify_del (self .mqtt_trigger [0 ], self .notify_q )
1096
1040
return
1041
+
1042
+ def call_action (self , notify_type , func_args , run_task = True ):
1043
+ """Call the trigger action function."""
1044
+ action_ast_ctx = AstEval (f"{ self .action .global_ctx_name } .{ self .action .name } " , self .action .global_ctx )
1045
+ Function .install_ast_funcs (action_ast_ctx )
1046
+ task_unique_func = None
1047
+ if self .task_unique is not None :
1048
+ task_unique_func = Function .task_unique_factory (action_ast_ctx )
1049
+
1050
+ #
1051
+ # check for @task_unique with kill_me=True
1052
+ #
1053
+ if (
1054
+ self .task_unique is not None
1055
+ and self .task_unique_kwargs
1056
+ and self .task_unique_kwargs ["kill_me" ]
1057
+ and Function .unique_name_used (action_ast_ctx , self .task_unique )
1058
+ ):
1059
+ _LOGGER .debug (
1060
+ "trigger %s got %s trigger, @task_unique kill_me=True prevented new action" ,
1061
+ notify_type ,
1062
+ self .name ,
1063
+ )
1064
+ return False
1065
+
1066
+ # Create new HASS Context with incoming as parent
1067
+ if "context" in func_args and isinstance (func_args ["context" ], Context ):
1068
+ hass_context = Context (parent_id = func_args ["context" ].id )
1069
+ else :
1070
+ hass_context = Context ()
1071
+
1072
+ # Fire an event indicating that pyscript is running
1073
+ # Note: the event must have an entity_id for logbook to work correctly.
1074
+ ev_name = self .name .replace ("." , "_" )
1075
+ ev_entity_id = f"pyscript.{ ev_name } "
1076
+
1077
+ event_data = dict (name = ev_name , entity_id = ev_entity_id , func_args = func_args )
1078
+ Function .hass .bus .async_fire ("pyscript_running" , event_data , context = hass_context )
1079
+
1080
+ _LOGGER .debug (
1081
+ "trigger %s got %s trigger, running action (kwargs = %s)" , self .name , notify_type , func_args ,
1082
+ )
1083
+
1084
+ async def do_func_call (func , ast_ctx , task_unique , task_unique_func , hass_context , ** kwargs ):
1085
+ # Store HASS Context for this Task
1086
+ Function .store_hass_context (hass_context )
1087
+
1088
+ if task_unique and task_unique_func :
1089
+ await task_unique_func (task_unique )
1090
+ await func .call (ast_ctx , ** kwargs )
1091
+ if ast_ctx .get_exception_obj ():
1092
+ ast_ctx .get_logger ().error (ast_ctx .get_exception_long ())
1093
+
1094
+ func = do_func_call (
1095
+ self .action , action_ast_ctx , self .task_unique , task_unique_func , hass_context , ** func_args ,
1096
+ )
1097
+ if run_task :
1098
+ Function .create_task (func )
1099
+ return True
1100
+ return func
0 commit comments