From 1a5a7cd550e65d323b029f8198eaa44438bd88b6 Mon Sep 17 00:00:00 2001 From: Daniel Lashua Date: Wed, 4 Nov 2020 09:28:45 -0600 Subject: [PATCH 1/5] send old_state and new_state to func_args --- custom_components/pyscript/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/custom_components/pyscript/__init__.py b/custom_components/pyscript/__init__.py index b386ba1..2ab1c43 100644 --- a/custom_components/pyscript/__init__.py +++ b/custom_components/pyscript/__init__.py @@ -217,6 +217,8 @@ async def state_changed(event): "value": new_val, "old_value": old_val, "context": event.context, + "old_state": event.data.get('old_state'), + "new_state": event.data.get('new_state'), } await State.update(new_vars, func_args) From 337889bf26d75d0c9862d41ba3d7b326a8c849eb Mon Sep 17 00:00:00 2001 From: Daniel Lashua Date: Wed, 4 Nov 2020 09:28:57 -0600 Subject: [PATCH 2/5] process old/new state to determine changes --- custom_components/pyscript/trigger.py | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/custom_components/pyscript/trigger.py b/custom_components/pyscript/trigger.py index bbc6689..1b8bbad 100644 --- a/custom_components/pyscript/trigger.py +++ b/custom_components/pyscript/trigger.py @@ -812,6 +812,35 @@ async def trigger_watch(self): if self.task_unique is not None: task_unique_func = Function.task_unique_factory(action_ast_ctx) + + # + # for state notify, check that changes occurred in state_trig_ident variables + # + if notify_type == 'state' and func_args['old_state'] is not None: + trig_ident_changed = False + changes = {} + if func_args['old_state'].state != func_args['new_state'].state: + changes[func_args['var_name']] = { + "old": func_args['old_state'].state, + "new": func_args['new_state'].state, + } + if func_args['var_name'] in self.state_trig_ident: + trig_ident_changed = True + + for attribute in func_args['new_state'].attributes: + if func_args['new_state'].attributes[attribute] != func_args['old_state'].attributes[attribute]: + changes[f"{func_args['var_name']}.{attribute}"] = { + "old": func_args['old_state'].attributes[attribute], + "new": func_args['new_state'].attributes[attribute], + } + if f"{func_args['var_name']}.{attribute}" in self.state_trig_ident: + trig_ident_changed = True + + if not trig_ident_changed: + continue + + func_args['changes'] = changes + # # check for @task_unique with kill_me=True # From 498114475ebde99315af70415a638d8412d423b2 Mon Sep 17 00:00:00 2001 From: Daniel Lashua Date: Wed, 4 Nov 2020 16:08:43 -0600 Subject: [PATCH 3/5] detect change without using func_args --- custom_components/pyscript/__init__.py | 11 +++++++++-- custom_components/pyscript/state.py | 6 +++--- custom_components/pyscript/trigger.py | 24 ++++-------------------- 3 files changed, 16 insertions(+), 25 deletions(-) diff --git a/custom_components/pyscript/__init__.py b/custom_components/pyscript/__init__.py index 2ab1c43..8401b45 100644 --- a/custom_components/pyscript/__init__.py +++ b/custom_components/pyscript/__init__.py @@ -217,9 +217,16 @@ async def state_changed(event): "value": new_val, "old_value": old_val, "context": event.context, - "old_state": event.data.get('old_state'), - "new_state": event.data.get('new_state'), } + + if new_val is not None: + for attribute in event.data["new_state"].attributes: + new_vars[f"{var_name}.{attribute}"] = event.data["new_state"].attributes[attribute] + + if old_val is not None: + for attribute in event.data["old_state"].attributes: + new_vars[f"{var_name}.{attribute}.old"] = event.data["old_state"].attributes[attribute] + await State.update(new_vars, func_args) async def hass_started(event): diff --git a/custom_components/pyscript/state.py b/custom_components/pyscript/state.py index ea4c3a5..a55b2de 100644 --- a/custom_components/pyscript/state.py +++ b/custom_components/pyscript/state.py @@ -115,12 +115,12 @@ async def update(cls, new_vars, func_args): @classmethod def notify_var_get(cls, var_names, new_vars): """Return the most recent value of a state variable change.""" - notify_vars = {} + notify_vars = new_vars for var_name in var_names if var_names is not None else []: if var_name in cls.notify_var_last: notify_vars[var_name] = cls.notify_var_last[var_name] - elif var_name in new_vars: - notify_vars[var_name] = new_vars[var_name] + # elif var_name in new_vars: + # notify_vars[var_name] = new_vars[var_name] elif 1 <= var_name.count(".") <= 2 and not cls.exist(var_name): notify_vars[var_name] = None return notify_vars diff --git a/custom_components/pyscript/trigger.py b/custom_components/pyscript/trigger.py index 1b8bbad..1e3139c 100644 --- a/custom_components/pyscript/trigger.py +++ b/custom_components/pyscript/trigger.py @@ -816,31 +816,15 @@ async def trigger_watch(self): # # for state notify, check that changes occurred in state_trig_ident variables # - if notify_type == 'state' and func_args['old_state'] is not None: + if notify_type == 'state': trig_ident_changed = False - changes = {} - if func_args['old_state'].state != func_args['new_state'].state: - changes[func_args['var_name']] = { - "old": func_args['old_state'].state, - "new": func_args['new_state'].state, - } - if func_args['var_name'] in self.state_trig_ident: + for var in self.state_trig_ident: + if new_vars.get(var) != new_vars.get(f"{var}.old"): trig_ident_changed = True - - for attribute in func_args['new_state'].attributes: - if func_args['new_state'].attributes[attribute] != func_args['old_state'].attributes[attribute]: - changes[f"{func_args['var_name']}.{attribute}"] = { - "old": func_args['old_state'].attributes[attribute], - "new": func_args['new_state'].attributes[attribute], - } - if f"{func_args['var_name']}.{attribute}" in self.state_trig_ident: - trig_ident_changed = True - + if not trig_ident_changed: continue - func_args['changes'] = changes - # # check for @task_unique with kill_me=True # From 8aa12305a782fb4be852089f2bdbe540d9bdf703 Mon Sep 17 00:00:00 2001 From: Daniel Lashua Date: Wed, 4 Nov 2020 16:26:32 -0600 Subject: [PATCH 4/5] changing test to see if it passes --- tests/test_function.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_function.py b/tests/test_function.py index b8c6ca0..a2296f1 100644 --- a/tests/test_function.py +++ b/tests/test_function.py @@ -734,7 +734,7 @@ def func_startup_sync2(trigger_type=None, var_name=None): res = literal_eval(await wait_until_done(notify_q)) results[res[0]] = res - assert results == [[0, "state", None], [1, "state", None]] + assert results == [[0, "state", 'pyscript.fstartup2'], [1, "state", 'pyscript.fstartup0']] for _ in range(2): hass.states.async_set("pyscript.fstartup2", 10) From 8ceeeec75a27e1efce11df223c8b5b4df4a77adc Mon Sep 17 00:00:00 2001 From: Daniel Lashua Date: Wed, 4 Nov 2020 16:29:16 -0600 Subject: [PATCH 5/5] nope, I don't understand tests. --- tests/test_function.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_function.py b/tests/test_function.py index a2296f1..b8c6ca0 100644 --- a/tests/test_function.py +++ b/tests/test_function.py @@ -734,7 +734,7 @@ def func_startup_sync2(trigger_type=None, var_name=None): res = literal_eval(await wait_until_done(notify_q)) results[res[0]] = res - assert results == [[0, "state", 'pyscript.fstartup2'], [1, "state", 'pyscript.fstartup0']] + assert results == [[0, "state", None], [1, "state", None]] for _ in range(2): hass.states.async_set("pyscript.fstartup2", 10)