Skip to content

Commit 1c9afc2

Browse files
committed
updated docs for #82
1 parent 0ef374d commit 1c9afc2

File tree

2 files changed

+71
-31
lines changed

2 files changed

+71
-31
lines changed

docs/new_features.rst

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,33 @@ The new features since 0.32 in master include:
1818

1919
- Pyscript state variables (entity_ids) can be persisted across pyscript reloads and HASS restarts,
2020
from @swazrgb and @dlashua (#48).
21-
- The ``hass`` object is available in all pyscript global contexts if the ``hass_is_global`` configuration parameter
22-
is true (default false). This allows access to HASS internals that might not be otherwise exposed by pyscript.
23-
Use with caution (#51).
24-
- Improvements to UI config flow, including allowing parameters to be updated, and the UI reload now works the same
25-
as the ``pyscript.reload`` service call, submitted by @raman325 (#53)
21+
- ``@state_trigger`` now supports triggering on an attribute change with ``"domain.entity.attr"`` and
22+
any attribute change with ``"domain.entity.*"``, submitted by @dlashua (#82)
2623
- State variables now support virtual attributes ``last_changed`` and ``last_updated`` for the UTC time when state
2724
values or any attribute was last changed.
25+
- State variable values (eg, from ``domain.entity`` or ``state.get()``) now include attributes that can be accessed
26+
after they are assigned to another, normal, variable.
2827
- ``@state_trigger`` and ``task.wait_until`` now have an optional ``state_hold`` duration in seconds that requires
2928
the state trigger to remain true for that period of time. The trigger occurs after that time elapses. If the state
3029
trigger changes to false before the time expires, the process of waiting for a new trigger starts over.
3130
- ``@time_active`` now has an optional ``hold_off`` duration in seconds, which ignores a new trigger if the last
3231
one happened within that time. Can be used for rate limiting or debouncing. Also, ``@time_active`` can now take
3332
zero time range arguments, in case you want to just specify ``hold_off``.
33+
- The ``hass`` object is available in all pyscript global contexts if the ``hass_is_global`` configuration parameter
34+
is true (default false). This allows access to HASS internals that might not be otherwise exposed by pyscript.
35+
Use with caution (#51).
36+
- Improvements to UI config flow, including allowing parameters to be updated, and the UI reload now works the same
37+
as the ``pyscript.reload`` service call, submitted by @raman325 (#53)
3438
- Added inbound ``context`` variable to trigger functions and support optional ``context`` setting on state,
3539
event firing and service calls. Proposal and PR by @dlashua (#50, #60).
36-
- Logbook now supported using ``context`` and informational message based on trigger type. Proposal and PR by
37-
@dlashua (#50, #62).
40+
- Logbook now supported using ``context`` and informational message based on trigger type. Proposal and PR
41+
by @dlashua (#50, #62).
3842
- Required Python packages can be specified in ``requirements.txt`` files at the top-level pyscript
3943
directory, and each module's or app's directory. Those files are read and any missing packages are
4044
installed on HASS startup and pyscript reload. If a specific version of a package is needed, it must be
4145
pinned using the format 'package_name==version'. Contributed by @raman325 (#66, #68, #69, #70, #78).
42-
- State variable attributes can be set by direct assignment, eg: ``DOMAIN.name.attr = value``. A
43-
equivalent new function ``state.setattr()`` allows a specific attribute to be set.
46+
- State variable attributes can be set by direct assignment, eg: ``DOMAIN.name.attr = value``.
47+
An equivalent new function ``state.setattr()`` allows a specific attribute to be set.
4448
- The reload service now takes an optional parameter ``global_ctx`` that specifies just that
4549
global context is reloaded, eg: ``global_ctx="file.my_scripts"``. Proposed by @dlashua (#63).
4650
- The ``state.get_attr()`` function has been renamed ``state.getattr()``. The old function is
@@ -56,12 +60,14 @@ The new features since 0.32 in master include:
5660
down.
5761
- Service calls now accept ``blocking`` and ``limit`` parameters. The default behavior for a service call is
5862
to run it in the background, but using ``blocking=True`` will force a task to wait up to ``limit`` seconds
59-
for the service call to finish executing before continuing. Contributed by @raman325 (#85)
63+
for the service call to finish executing before continuing. Contributed by @raman325 (#85).
6064

6165
The bug fixes since 0.32 in master include:
6266

67+
- The ``@state_trigger`` expression is only evaluated when at least one of specific state variable
68+
or attribute values mentioned in the expression have changed; fixed by @dlashua (#82).
6369
- Jupyter autocomplete now works on multiline code blocks.
6470
- Improved error message reporting for syntax errors inside f-strings.
65-
- Fixed incorrect global context update on calling module that, in turn, does a callback (#58)
66-
- `task.wait_until` no longer silently ignores unrecognized keyword arguments (#80)
67-
- `task.wait_until` incorrectly ignored the keyword optional state_check_now argument (#81)
71+
- Fixed incorrect global context update on calling module that, in turn, does a callback (#58).
72+
- `task.wait_until` no longer silently ignores unrecognized keyword arguments (#80).
73+
- `task.wait_until` incorrectly ignored the keyword optional state_check_now argument (#81).

docs/reference.rst

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ State variables can be accessed in any Python code simply by name. State variabl
111111
``entity_id``) are of the form ``DOMAIN.name``, where ``DOMAIN`` is typically the name of the
112112
component that sets that variable. You can set a state variable by assigning to it.
113113

114-
State variables only have string values, so you will need to convert them to ``int`` or ``float`` if
115-
you need their numeric value.
114+
State variables only have string values, so you will need to convert them to ``int`` or ``float``
115+
if you need their numeric value.
116116

117117
State variables have attributes that can be accessed by adding the name of the attribute, as in
118118
``DOMAIN.name.attr``. The attribute names and their meaning depend on the component that sets them,
@@ -133,8 +133,20 @@ component has a state variable name that collides with one of its services, you
133133

134134
Accessing state variables that don't exist will throw a ``NameError`` exception, and accessing
135135
an attribute that doesn't exist will throw a ``AttributeError`` exception. One exception (!)
136-
to this that in a ``@state_trigger`` expression, undefined state variables will evaluate to
137-
``None`` instead of throwing an exception.
136+
to this that in a ``@state_trigger`` expression, undefined state variables and attributes will
137+
evaluate to ``None`` instead of throwing an exception.
138+
139+
You can assign a state variable (or the return value of ``state.get()``) to a normal Python variable,
140+
and that variable will capture the value and attributes of the state variable at the time of the
141+
assignment. So, for example, after this assignment:
142+
143+
.. code:: python
144+
145+
test1_state = binary_sensor.test1
146+
147+
the variable ``test1_state`` captures both the value and attributes of ``binary_sensor.test1``.
148+
Later, if ``binary_sensor.test1`` changes, ``test1_state`` continues to represent the previous
149+
value and attributes at the time of the assignment.
138150

139151
State variables also support virtual methods that are service calls with that ``entity_id``.
140152
For any state variable ``DOMAIN.ENTITY``, any services registered by ``DOMAIN``, eg:
@@ -249,10 +261,12 @@ function.
249261
250262
``@state_trigger`` takes one or more string arguments that contain any expression based on one or
251263
more state variables, and evaluates to ``True`` or ``False`` (or non-zero or zero). Whenever the
252-
state variables mentioned in the expression change, the expression is evaluated and the trigger
253-
occurs if it evaluates to ``True`` (or non-zero). For each state variable, eg: ``domain.name``,
254-
the prior value is also available to the expression as ``domain.name.old`` in case you want to
255-
condition the trigger on the prior value too.
264+
state variables or attributes values mentioned in the expression change, the expression is evaluated
265+
and the trigger occurs if it evaluates to ``True`` (or non-zero). For each state variable,
266+
eg: ``domain.name``, the prior value is also available to the expression as ``domain.name.old``
267+
in case you want to condition the trigger on the prior value too. Attribute values can be used
268+
in the expression too, using the forms ``domain.name.attr`` and ``domain.name.old.attr`` for
269+
the new and old attribute values respectively.
256270

257271
Multiple ``str_expr`` arguments are logically "or"ed together, so the trigger occurs if any of the
258272
expressions evaluate to ``True``. Any argument can alternatively be a list or set of strings, and
@@ -297,24 +311,36 @@ You can also use state variable attributes in the trigger expression, with an id
297311
form ``DOMAIN.name.attr``. Attributes maintain their original type, so there is no need to cast
298312
then to another type.
299313

300-
You can specify a state trigger on any change with a string that is just the state variable name:
314+
You can specify a state trigger on any change with a string that can take three forms:
315+
``"domain.entity"``
316+
triggers on any change to the state variable value
317+
``"domain.entity.attr"``
318+
triggers on any change to the state variable attribute ``attr`` value
319+
``"domain.entity.*"``
320+
triggers on any change to any state variable attribute (but not its value)
321+
322+
For example:
301323

302324
.. code:: python
303325
304326
@state_trigger("domain.light_level")
305327
306-
If you use this form, there's no point in also specifying ``state_hold`` since the expression
307-
is always ``True`` whenever the state variable changes - there is no way for it to evaluate
308-
to ``False`` and to re-start the trigger process. If you do specify ``state_hold`` in this
309-
case it will simply delay the trigger by the specified time.
328+
will trigger any time the value of ``domain.light_level`` changes (not its attributes), which
329+
includes the cases when that variable is first created (ie, the ``old_value`` is ``None``)
330+
and when it is deleted (ie, the ``value`` is ``None``).
331+
332+
If you use the "any change" form, there's no point in also specifying ``state_hold`` since the
333+
expression is always ``True`` whenever the state variable changes - there is no way for it to
334+
evaluate to ``False`` and to re-start the trigger process. If you do specify ``state_hold`` in
335+
this case it will simply delay the trigger by the specified time.
310336

311337
The trigger can include arguments with any mixture of string expressions (that are evaluated
312-
when any of the underlying state variables change) and string state variable names (that trigger
313-
whenever that variable changes).
338+
when any of the underlying state variables change) and string state variable or attribute
339+
names (that trigger whenever that variable or attribute changes).
314340

315-
Note that if a state variable is set to the same value, HASS doesn’t generate a state change event,
316-
so the ``@state_trigger`` condition will not be checked. It is only evaluated each time a state
317-
variable changes to a new value.
341+
Note that if a state variable and attributes are set to the same value, HASS doesn’t generate a
342+
state change event, so the ``@state_trigger`` condition will not be checked. It is only evaluated
343+
each time a state variable or any of its attributes change to a new value.
318344

319345
When the trigger occurs and the function is executed (meaning any active checks passed too), keyword
320346
arguments are passed to the function so it can tell which state variable caused it to succeed and
@@ -329,6 +355,11 @@ run, in cases where the trigger condition involves multiple variables. These are
329355
"old_value": old_value
330356
}
331357
358+
The ``value`` and ``old_value`` represent the current and old values of the state variable
359+
``var_name`` whose change caused the trigger. Those variables include the state attributes too.
360+
If the trigger occurs when the state variable is newly created, ``old_value`` will be ``None``,
361+
and if the trigger occurs when a state variable is deleted, ``value`` will be ``None``.
362+
332363
If your function needs to know any of these values, you can list the keyword arguments you need,
333364
with defaults:
334365

@@ -1304,6 +1335,9 @@ You can use ``hass`` to compute sunrise and sunset times using the same method H
13041335
sunset = location.sunset(datetime.datetime.today()).replace(tzinfo=None)
13051336
print(f"today sunrise = {sunrise}, sunset = {sunset}")
13061337
1338+
(Note that the ``sun.sun`` attributes already provide times for the next sunrise and sunset, so
1339+
this example is a bit contrived.)
1340+
13071341
Here's another method that uses the installed version of ``astral`` directly, rather than the HASS
13081342
helper function. It's a bit more cryptic since it's a very old version of ``astral``, but you can
13091343
see how the HASS configuration values are used:

0 commit comments

Comments
 (0)