@@ -48,6 +48,74 @@ def parse_time_offset(offset_str):
4848 return value * scale
4949
5050
51+ def ident_any_values_changed (func_args , ident ):
52+ """Check for changes to state or attributes on ident any vars"""
53+ value = func_args .get ('value' )
54+ old_value = func_args .get ('old_value' )
55+ var_name = func_args .get ('var_name' )
56+
57+ if var_name is None :
58+ return False
59+
60+ for check_var in ident :
61+ if check_var == var_name and old_value != value :
62+ return True
63+
64+ if check_var .startswith (f"{ var_name } ." ):
65+ var_pieces = check_var .split ('.' )
66+ if len (var_pieces ) == 3 and f"{ var_pieces [0 ]} .{ var_pieces [1 ]} " == var_name :
67+ if var_pieces [2 ] == "*" :
68+ # catch all has been requested, check all attributes for change
69+ all_attributes = set ()
70+ if value is not None :
71+ all_attributes |= set (value .__dict__ .keys ())
72+ if old_value is not None :
73+ all_attributes |= set (old_value .__dict__ .keys ())
74+ all_attributes -= STATE_VIRTUAL_ATTRS
75+ for attribute in all_attributes :
76+ attrib_val = getattr (value , attribute , None )
77+ attrib_old_val = getattr (old_value , attribute , None )
78+ if attrib_old_val != attrib_val :
79+ return True
80+ else :
81+ attrib_val = getattr (value , var_pieces [2 ], None )
82+ attrib_old_val = getattr (old_value , var_pieces [2 ], None )
83+ if attrib_old_val != attrib_val :
84+ return True
85+
86+ return False
87+
88+ def ident_values_changed (func_args , ident ):
89+ """Check for changes to state or attributes on ident vars"""
90+ value = func_args .get ('value' )
91+ old_value = func_args .get ('old_value' )
92+ var_name = func_args .get ('var_name' )
93+
94+ if var_name is None :
95+ return False
96+
97+ for check_var in ident :
98+ # if check_var in self.state_trig_ident_any:
99+ # _LOGGER.debug(
100+ # "%s ident change skipping %s because also ident_any",
101+ # self.name,
102+ # check_var,
103+ # )
104+ # continue
105+ var_pieces = check_var .split ('.' )
106+ if len (var_pieces ) == 2 and check_var == var_name :
107+ if value != old_value :
108+ return True
109+ elif len (var_pieces ) == 3 and f"{ var_pieces [0 ]} .{ var_pieces [1 ]} " == var_name :
110+ attrib_val = getattr (value , var_pieces [2 ], None )
111+ attrib_old_val = getattr (old_value , var_pieces [2 ], None )
112+ if attrib_old_val != attrib_val :
113+ return True
114+
115+ return False
116+
117+
118+
51119class TrigTime :
52120 """Class for trigger time functions."""
53121
@@ -254,13 +322,18 @@ async def wait_until(
254322 new_vars , func_args = None , {}
255323
256324 state_trig_ok = False
257- if func_args .get ("var_name" , "" ) in state_trig_ident_any :
258- state_trig_ok = True
259- elif state_trig_eval :
260- state_trig_ok = await state_trig_eval .eval (new_vars )
261- exc = state_trig_eval .get_exception_obj ()
262- if exc is not None :
263- break
325+
326+ if not ident_any_values_changed (func_args , state_trig_ident_any ):
327+ # if var_name not in func_args we are state_check_now
328+ if "var_name" in func_args and not ident_values_changed (func_args , state_trig ):
329+ continue
330+
331+ if state_trig_eval :
332+ state_trig_ok = await state_trig_eval .eval (new_vars )
333+ exc = state_trig_eval .get_exception_obj ()
334+ if exc is not None :
335+ break
336+
264337 if state_hold is not None :
265338 if state_trig_ok :
266339 if not state_trig_waiting :
@@ -644,112 +717,6 @@ def start(self):
644717 self .task = Function .create_task (self .trigger_watch ())
645718 _LOGGER .debug ("trigger %s is active" , self .name )
646719
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 .get ('value' )
650- old_value = func_args .get ('old_value' )
651- var_name = func_args .get ('var_name' )
652-
653- if var_name is None :
654- _LOGGER .debug (
655- "%s ident_any change not detected because no var_name" ,
656- self .name ,
657- )
658- return False
659-
660- for check_var in self .state_trig_ident_any :
661- if check_var == var_name and old_value != value :
662- _LOGGER .debug (
663- "%s ident_any change detected at state" ,
664- self .name ,
665- )
666- return True
667-
668- if check_var .startswith (f"{ var_name } ." ):
669- var_pieces = check_var .split ('.' )
670- if len (var_pieces ) == 3 and f"{ var_pieces [0 ]} .{ var_pieces [1 ]} " == var_name :
671- if var_pieces [2 ] == "*" :
672- # catch all has been requested, check all attributes for change
673- all_attributes = set ()
674- if value is not None :
675- all_attributes |= set (value .__dict__ .keys ())
676- if old_value is not None :
677- all_attributes |= set (old_value .__dict__ .keys ())
678- all_attributes -= STATE_VIRTUAL_ATTRS
679- for attribute in all_attributes :
680- attrib_val = getattr (value , attribute , None )
681- attrib_old_val = getattr (old_value , attribute , None )
682- if attrib_old_val != attrib_val :
683- _LOGGER .debug (
684- "%s ident_any change detected in * at %s" ,
685- self .name ,
686- attribute ,
687- )
688- return True
689- else :
690- attrib_val = getattr (value , var_pieces [2 ], None )
691- attrib_old_val = getattr (old_value , var_pieces [2 ], None )
692- if attrib_old_val != attrib_val :
693- _LOGGER .debug (
694- "%s ident_any change detected at %s" ,
695- self .name ,
696- var_pieces [2 ],
697- )
698- return True
699-
700- _LOGGER .debug (
701- "%s no ident_any change detected" ,
702- self .name ,
703- )
704- return False
705-
706- def ident_values_changed (self , func_args ):
707- """Check for changes to state or attributes on ident vars"""
708- value = func_args .get ('value' )
709- old_value = func_args .get ('old_value' )
710- var_name = func_args .get ('var_name' )
711-
712- if var_name is None :
713- _LOGGER .debug (
714- "%s ident changes not detected because no var_name" ,
715- self .name ,
716- )
717- return False
718-
719- for check_var in self .state_trig_ident :
720- if check_var in self .state_trig_ident_any :
721- _LOGGER .debug (
722- "%s ident change skipping %s because also ident_any" ,
723- self .name ,
724- check_var ,
725- )
726- continue
727- var_pieces = check_var .split ('.' )
728- if len (var_pieces ) == 2 and check_var == var_name :
729- if value != old_value :
730- _LOGGER .debug (
731- "%s ident change detected at state" ,
732- self .name
733- )
734- return True
735- elif len (var_pieces ) == 3 and f"{ var_pieces [0 ]} .{ var_pieces [1 ]} " == var_name :
736- attrib_val = getattr (value , var_pieces [2 ], None )
737- attrib_old_val = getattr (old_value , var_pieces [2 ], None )
738- if attrib_old_val != attrib_val :
739- _LOGGER .debug (
740- "%s ident change detected at attribute %s" ,
741- self .name ,
742- var_pieces [2 ]
743- )
744- return True
745-
746- _LOGGER .debug (
747- "%s no ident change detected" ,
748- self .name ,
749- )
750-
751- return False
752-
753720 async def trigger_watch (self ):
754721 """Task that runs for each trigger, waiting for the next trigger and calling the function."""
755722
@@ -845,9 +812,9 @@ async def trigger_watch(self):
845812 elif notify_type == "state" :
846813 new_vars , func_args = notify_info
847814
848- if not self . ident_any_values_changed (func_args ):
815+ if not ident_any_values_changed (func_args , self . state_trig_ident_any ):
849816 # if var_name not in func_args we are state_check_now
850- if "var_name" in func_args and not self . ident_values_changed (func_args ):
817+ if "var_name" in func_args and not ident_values_changed (func_args , self . state_trig_ident ):
851818 continue
852819
853820 if self .state_trig_eval :
0 commit comments