Skip to content

Commit 6d57457

Browse files
committed
first pass at wait_until and global ident checks
1 parent 0da11b9 commit 6d57457

File tree

1 file changed

+82
-115
lines changed

1 file changed

+82
-115
lines changed

custom_components/pyscript/trigger.py

Lines changed: 82 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
51119
class 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

Comments
 (0)