PyScript 1.0.0 has been released!
If you’re not already using PyScript, written by @craigb, you’re in for a treat. If you are, skip down a bit to see some highlights of the new features in this release.
What is PyScript?
PyScript is an alternative implementation for Home Assistant Automations. Similar in functionality to Node-RED’s Home Assistant integration or AppDaemon, it allows you to write Home Assistant Automations in what will be, for some, a much simpler syntax.
As an example, in Home Assistant, you might want to turn on a light for 5 minutes anytime a motion detector senses motion and it’s dark outside. That automation might look like this:
- alias: porch lights on
trigger:
- platform: template
value_template: >-
{{
is_state('binary_sensor.motion', 'on')
and is_state('binary_sensor.dark', 'on')
}}
action:
service: light.turn_on
data:
entity_id: light.porch
brightness: 255
color_temp: 300
- alias: porch lights off
trigger:
- platform: state
entity_id: binary_sensor.motion
to: "off"
for: 300
action:
- service: light.turn_off
data:
entity_id: light.porch
In PyScript, that automation might look like this:
@state_trigger('binary_sensor.motion == "on" and binary_sensor.dark == "off"')
def porch_lights_on():
light.porch.turn_on(brightness=255, color_temp=300)
@state_trigger('binary_sensor.motion == "off"', state_hold=300)
def porch_lights_off():
light.porch.turn_off()
PyScript offers many more features all designed to keep automations easy to read, even when the actions they perform are complex. If you’ve ever written a Home Assistant Automation with the choose
action in it, you’ll likely really appreciate the simpler form for this kind of logic in PyScript.
PyScript lets you use Python, instead of YAML, to write your automations. And with this comes nearly all of the Python language features. Python is incredibly simple to write – certainly not any more difficult than Home Assistant Automation YAML – and is designed to express logic like this.
New Features in 1.0.0
In this release there are a couple of very notable features.
Short Form Service Calls
Before this release, turning on a light looked like this:
light.turn_on(entity_id='light.porch')
Now, while that syntax still works, you can instead do this:
light.porch.turn_on()
Any service call that requires an entity_id
can be shortened in this way. While, in a single line like this, it make not look like much, it does a lot to improve the readability of your automation, and it requires fewer keystrokes.
State Persistence
There are times when an automation works best if we can store some piece of data and retrieve it later and we want that information to be maintained even if we need to restart Home Assistant.
Perhaps, for some reason, you need to keep track of how many times a switch has turned on. In Home Assistant automations, you’d likely use a counter
helper, or maybe an input_number
.
First, you have to create that helper. Once created, you might write an automation like this:
- alias: count my thing
trigger:
- platform: state
entity_id: switch.my_thing
to: "on"
action:
- service: counter.increment
data:
entity_id: counter.my_thing
In PyScript, you don’t need the helper at all. Instead that automation might look like this:
state.persist('pyscript.switch_counter', default_value="0")
@state_trigger('switch.my_thing == "on"')
def count_my_thing():
pyscript.switch_counter = int(pyscript.switch_counter) + 1
The state.persist
call lets PyScript know that you want this state to be persisted. After that, you can just update it like any other variable. If you don’t need the data restored after a Home Assistant restart, you can leave the state.persist
call out entirely and the rest will still work as you’d expect.
Working with Attributes
A lot of times, in Home Assistant Automations the solution to working with an attribute is to write a Template Sensor to expose that attribute in its own entity_id
and then write your Automation against this new entity_id
. With PyScript, that is, of course, still an option. But, in this release, all @state_trigger
s and task.wait_until()
calls can use attributes directly.
Perhaps you want to get a notification if your thermostat is set higher than 80 degrees:
@state_trigger('climate.thermostat.temperature > 80')
def send_thermostat_notification():
notify.me(
message=f"The Thermostat is now set to {climate.thermostat.temperature}, which is above 80"
)
Using task.wait_until()
you can also get a notification when the thermostat setpoint is restored to a more reasonable setting:
@state_trigger('climate.thermostat.temperature > 80')
def send_thermostat_notification():
task.unique('thermostat_notification')
notify.me(
message=f"The Thermostat is now set to {climate.thermostat.temperature}, which is above 80"
)
task.wait_until(state_trigger="climate.thermostat.temperature <= 80")
notify.me(
message=f"The Thermostat is now set below 80 degrees"
)
state_hold on @state_trigger
The state_hold
kwarg on a @state_trigger
works similar to the for:
option in a Home Assistant Automation Trigger. Before this feature, you had to jump through a few extra hoops with task.unique()
and task.sleep()
in order to wait for an entity to be in a certain state for a certain amount of time. But that’s no longer the case.
Logbook logging
When Home Assistant Automations fire, if you use the Logbook, you can consult it to see which automation turned on what. This helps answer the question “Why is this light on?” when Automations don’t work exactly like we thought they would.
With this release, you’ll see PyScript automations appearing in the logbook too, giving you a record of which PyScript turned on which light and when.
VSCode Jupyter Kernel
PyScript has an optional Jupyter Notebook kernel you can use. This provides entity_id
completion and also allows you to test automations without having to reload PyScript after every change. Once you have it working the way you want, you copy and paste the code into the PyScript directory and you’re done.
In this release, PyScript’s Jupyter Kernel works with VSCode’s Jupyter Notebook implementation. This means if you’re using VSCode to edit your Automations and PyScript files, you don’t have to leave that environment to test out some new code using Jupyter Notebook.
Much More
I’ve only highlighted a few of the new features available.
Check out the full release notes to get the details on all the changes in this release.
Share!
Share in the comments one of your PyScript automations to help others get a feel for just how easy automations can be with PyScript.