-
Notifications
You must be signed in to change notification settings - Fork 55
state_trigger only triggers on value changes (using StateVar) #82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 27 commits
5de420b
bf0543b
300c39f
57c04b1
8941b00
08f334d
8f9a323
7f8ffa0
e5a0bfa
3296f74
8c2bd0e
f06c0c4
c49310d
d43c79d
67cc67b
5d1d4d8
eeb6a6d
3228934
00de489
c57a311
a591ddc
cc9615d
50a083a
2497f0a
ba79200
b063ff6
a18e253
729f522
0da11b9
6d57457
0d4e32c
fe03993
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,7 @@ | |
_LOGGER = logging.getLogger(LOGGER_PATH + ".trigger") | ||
|
||
|
||
STATE_RE = re.compile(r"[a-zA-Z]\w*\.[a-zA-Z]\w*$") | ||
STATE_RE = re.compile(r"[a-zA-Z]\w*\.[a-zA-Z]\w*(\.[a-zA-Z\*]?[a-zA-Z]*)?$") | ||
|
||
|
||
def dt_now(): | ||
|
@@ -644,6 +644,112 @@ def start(self): | |
self.task = Function.create_task(self.trigger_watch()) | ||
_LOGGER.debug("trigger %s is active", self.name) | ||
|
||
def ident_any_values_changed(self, func_args): | ||
"""Check for changes to state or attributes on ident any vars""" | ||
value = func_args.get('value') | ||
old_value = func_args.get('old_value') | ||
dlashua marked this conversation as resolved.
Show resolved
Hide resolved
|
||
var_name = func_args.get('var_name') | ||
|
||
if var_name is None: | ||
_LOGGER.debug( | ||
"%s ident_any change not detected because no var_name", | ||
self.name, | ||
) | ||
return False | ||
|
||
for check_var in self.state_trig_ident_any: | ||
if check_var == var_name and old_value != value: | ||
_LOGGER.debug( | ||
"%s ident_any change detected at state", | ||
self.name, | ||
) | ||
return True | ||
|
||
if check_var.startswith(f"{var_name}."): | ||
var_pieces = check_var.split('.') | ||
if len(var_pieces) == 3 and f"{var_pieces[0]}.{var_pieces[1]}" == var_name: | ||
if var_pieces[2] == "*": | ||
# catch all has been requested, check all attributes for change | ||
all_attributes = set() | ||
if value is not None: | ||
all_attributes |= set(value.__dict__.keys()) | ||
if old_value is not None: | ||
all_attributes |= set(old_value.__dict__.keys()) | ||
all_attributes -= {"last_updated", "last_changed"} | ||
dlashua marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for attribute in all_attributes: | ||
attrib_val = getattr(value, attribute, None) | ||
attrib_old_val = getattr(old_value, attribute, None) | ||
if attrib_old_val != attrib_val: | ||
_LOGGER.debug( | ||
"%s ident_any change detected in * at %s", | ||
self.name, | ||
attribute, | ||
) | ||
return True | ||
else: | ||
attrib_val = getattr(value, var_pieces[2], None) | ||
attrib_old_val = getattr(old_value, var_pieces[2], None) | ||
if attrib_old_val != attrib_val: | ||
_LOGGER.debug( | ||
"%s ident_any change detected at %s", | ||
self.name, | ||
var_pieces[2], | ||
) | ||
return True | ||
|
||
_LOGGER.debug( | ||
"%s no ident_any change detected", | ||
self.name, | ||
) | ||
return False | ||
|
||
def ident_values_changed(self, func_args): | ||
"""Check for changes to state or attributes on ident vars""" | ||
value = func_args.get('value') | ||
old_value = func_args.get('old_value') | ||
dlashua marked this conversation as resolved.
Show resolved
Hide resolved
|
||
var_name = func_args.get('var_name') | ||
|
||
if var_name is None: | ||
_LOGGER.debug( | ||
"%s ident changes not detected because no var_name", | ||
self.name, | ||
) | ||
return False | ||
|
||
for check_var in self.state_trig_ident: | ||
if check_var in self.state_trig_ident_any: | ||
_LOGGER.debug( | ||
"%s ident change skipping %s because also ident_any", | ||
self.name, | ||
check_var, | ||
) | ||
continue | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this whole There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My thought process was that ident_any_values_changed() checked it, but the value did not change. Therefore, it didn't return True. So, in ident_values_changed() we can skip it (and save some CPU) since they were already checked. If we take the if out, since it didn't return True before, it won't return True now either. |
||
var_pieces = check_var.split('.') | ||
if len(var_pieces) == 2 and check_var == var_name: | ||
if value != old_value: | ||
_LOGGER.debug( | ||
"%s ident change detected at state", | ||
self.name | ||
) | ||
return True | ||
elif len(var_pieces) == 3 and f"{var_pieces[0]}.{var_pieces[1]}" == var_name: | ||
attrib_val = getattr(value, var_pieces[2], None) | ||
attrib_old_val = getattr(old_value, var_pieces[2], None) | ||
if attrib_old_val != attrib_val: | ||
_LOGGER.debug( | ||
"%s ident change detected at attribute %s", | ||
self.name, | ||
var_pieces[2] | ||
) | ||
return True | ||
|
||
_LOGGER.debug( | ||
"%s no ident change detected", | ||
self.name, | ||
) | ||
|
||
return False | ||
|
||
async def trigger_watch(self): | ||
"""Task that runs for each trigger, waiting for the next trigger and calling the function.""" | ||
|
||
|
@@ -739,7 +845,11 @@ async def trigger_watch(self): | |
elif notify_type == "state": | ||
new_vars, func_args = notify_info | ||
|
||
if "var_name" not in func_args or func_args["var_name"] not in self.state_trig_ident_any: | ||
if not self.ident_any_values_changed(func_args): | ||
# if var_name not in func_args we are state_check_now | ||
if "var_name" in func_args and not self.ident_values_changed(func_args): | ||
continue | ||
|
||
if self.state_trig_eval: | ||
trig_ok = await self.state_trig_eval.eval(new_vars) | ||
exc = self.state_trig_eval.get_exception_long() | ||
|
@@ -748,6 +858,7 @@ async def trigger_watch(self): | |
trig_ok = False | ||
else: | ||
trig_ok = False | ||
|
||
if self.state_hold_dur is not None: | ||
if trig_ok: | ||
if not state_trig_waiting: | ||
|
Uh oh!
There was an error while loading. Please reload this page.