Skip to content

Commit a591ddc

Browse files
committed
break change check logic into functions and move above trig eval
1 parent c57a311 commit a591ddc

File tree

1 file changed

+64
-53
lines changed

1 file changed

+64
-53
lines changed

custom_components/pyscript/trigger.py

Lines changed: 64 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,55 @@ def start(self):
644644
self.task = Function.create_task(self.trigger_watch())
645645
_LOGGER.debug("trigger %s is active", self.name)
646646

647+
def ident_any_values_changed(self, func_args):
648+
"""Check for changes to state or attributes on ident any vars"""
649+
value = func_args['value']
650+
old_value = func_args['old_value']
651+
var_name = func_args['var_name']
652+
653+
if var_name is None:
654+
return False
655+
656+
for check_var in self.state_trig_ident_any:
657+
if check_var == var_name and old_value != value:
658+
return True
659+
660+
if check_var.startswith(f"{var_name}."):
661+
var_pieces = check_var.split('.')
662+
if len(var_pieces) == 3 and f"{var_pieces[0]}.{var_pieces[1]}" == var_name:
663+
if var_pieces[2] == "*":
664+
# catch all has been requested, check all attributes for change
665+
all_attributes = (set(value.__dict__.keys()) | set(old_value.__dict__.keys())) - {"last_updated", "last_changed"}
666+
for attribute in all_attributes:
667+
attrib_val = getattr(value, attribute, None)
668+
attrib_old_val = getattr(old_value, attribute, None)
669+
if attrib_old_val != attrib_val:
670+
return True
671+
else:
672+
attrib_val = getattr(value, var_pieces[2], None)
673+
attrib_old_val = getattr(old_value, var_pieces[2], None)
674+
if attrib_old_val != attrib_val:
675+
return True
676+
return False
677+
678+
def ident_values_changed(self, func_args):
679+
"""Check for changes to state or attributes on ident vars"""
680+
value = func_args['value']
681+
old_value = func_args['old_value']
682+
var_name = func_args['var_name']
683+
for check_var in self.state_trig_ident:
684+
var_pieces = check_var.split('.')
685+
if len(var_pieces) == 2 and check_var == var_name:
686+
if value != old_value:
687+
return True
688+
elif len(var_pieces) == 3 and f"{var_pieces[0]}.{var_pieces[1]}" == var_name:
689+
attrib_val = getattr(value, var_pieces[2], None)
690+
attrib_old_val = getattr(old_value, var_pieces[2], None)
691+
if attrib_old_val != attrib_val:
692+
return True
693+
694+
return False
695+
647696
async def trigger_watch(self):
648697
"""Task that runs for each trigger, waiting for the next trigger and calling the function."""
649698

@@ -739,25 +788,22 @@ async def trigger_watch(self):
739788
elif notify_type == "state":
740789
new_vars, func_args = notify_info
741790

742-
# check if any state_trig_ident_any starts with var_name
743-
any_match = False
744-
if "var_name" in func_args:
745-
for check_var in self.state_trig_ident_any:
746-
if check_var == func_args['var_name']:
747-
any_match = True
748-
break
749-
if check_var.startswith(f"{func_args['var_name']}."):
750-
any_match = True
751-
break
752-
if not any_match:
753-
if self.state_trig_eval:
754-
trig_ok = await self.state_trig_eval.eval(new_vars)
755-
exc = self.state_trig_eval.get_exception_long()
756-
if exc is not None:
757-
self.state_trig_eval.get_logger().error(exc)
758-
trig_ok = False
759-
else:
791+
# if func_args is not fully populated, then we are state_check_now so skip changed check
792+
if all([(x in func_args) for x in ['value', 'old_value', 'var_name']]):
793+
# check for changes to ident vars
794+
if not self.ident_any_values_changed(func_args) and not self.ident_values_changed(func_args):
795+
# nothing changed so no need to evaluate trigger
796+
continue
797+
798+
if self.state_trig_eval:
799+
trig_ok = await self.state_trig_eval.eval(new_vars)
800+
exc = self.state_trig_eval.get_exception_long()
801+
if exc is not None:
802+
self.state_trig_eval.get_logger().error(exc)
760803
trig_ok = False
804+
else:
805+
trig_ok = False
806+
761807
if self.state_hold_dur is not None:
762808
if trig_ok:
763809
if not state_trig_waiting:
@@ -822,42 +868,7 @@ async def trigger_watch(self):
822868
if self.task_unique is not None:
823869
task_unique_func = Function.task_unique_factory(action_ast_ctx)
824870

825-
#
826-
# check for changes to state or attributes
827-
#
828-
829-
# if "value" not in func_args, then we are state_check_now
830-
if notify_type == 'state' and all([(x in func_args) for x in ['value', 'old_value', 'var_name']]):
831-
trig_ident_change = False
832871

833-
value = func_args['value']
834-
old_value = func_args['old_value']
835-
var_name = func_args['var_name']
836-
# determine if the catchall has been requested in state_trig_ident_any
837-
catch_all_entity = f"{var_name}.*"
838-
if catch_all_entity in self.state_trig_ident_any:
839-
# catch all has been requested, check all attributes for change
840-
all_attributes = (set(value.__dict__.keys()) | set(old_value.__dict__.keys())) - {"last_updated", "last_changed"}
841-
for attribute in all_attributes:
842-
attrib_val = getattr(value, attribute, None)
843-
attrib_old_val = getattr(old_value, attribute, None)
844-
if attrib_old_val != attrib_val:
845-
trig_ident_change = True
846-
847-
if not trig_ident_change:
848-
for var in self.state_trig_ident:
849-
var_pieces = var.split('.')
850-
if len(var_pieces) == 2 and var == var_name:
851-
if value != old_value:
852-
trig_ident_change = True
853-
elif len(var_pieces) == 3 and f"{var_pieces[0]}.{var_pieces[1]}" == var_name:
854-
attrib_val = getattr(value, var_pieces[2], None)
855-
attrib_old_val = getattr(old_value, var_pieces[2], None)
856-
if attrib_old_val != attrib_val:
857-
trig_ident_change = True
858-
859-
if not trig_ident_change:
860-
continue
861872

862873
#
863874
# check for @task_unique with kill_me=True

0 commit comments

Comments
 (0)