blocking=True not working as expected
I created a pyscript service for using text-to-speech with my Sonos speaker:
"""
Script for saying a text on the living room sonos.
Handles the initial snapshot and restores when done.
"""
@service
def say(text):
task.unique("tts", kill_me=True)
sonos.snapshot(entity_id="media_player.livingroom_sonos_beam", blocking=True)
media_player.volume_set(entity_id="media_player.livingroom_sonos_beam", volume_level=0.25, blocking=True)
tts.cloud_say(entity_id="media_player.livingroom_sonos_beam", message=text, language="de-DE", blocking=True)
task.sleep(1.5)
task.wait_until(state_trigger="media_player.livingroom_sonos_beam == 'paused'", timeout=10)
sonos.restore(entity_id="media_player.livingroom_sonos_beam", blocking=True)
Now I want to use this service when disabling my cinema mode:
@service()
def deactivateCinemaMode():
task.unique("changingcinemamode", kill_me=True)
pyscript.say(text="Some german text that says something like Thanks for visisting my cinema!", blocking=True)
#task.sleep(5)
media_player.livingroom_firetv.turn_off()
media_player.livingroom_projector.turn_off()
cover.livingroom_canvas.open_cover()
pyscript.livingroom_candles_turnoff()
Since I used blocking=True I expected the canvas to open AFTER the message was spoken. What I actually see is that all actions occur at the same time, e.g. the pyscript.say is not blocking.
Am I missing something? Am I doing something wrong or is this a bug?
Thanks in advance!
This is interesting!
It feels like it might be a bug, but I can't quite tell where the bug is. The "blocking=True" portion of this is not a pyscript feature. It's handled entirely by Home Assistant. It looks like pyscript is doing the right thing in the way that it detects this kwarg and passes it correctly to the internal async_call method of Home Assistant.
My best guess as to why this doesn't work is that pyscript services are implemented asynchronously. So, from the point of view of Home Assistant, this service call is "complete" as soon as pyscript acknowledges the service call. I think, perhaps, blocking=True (in the Home Assistant API) is intended to be used with non-async service calls. The default behavior (again, in the Home Assistant code, not pyscript) is to start that service call in the background. This works for both async and sync service calls. However, with blocking=True, the Home Assistant code wraps the service call in "wait" syntax. That's basically the only difference: see Home Assistant Code. Since service calls implemented in pyscript are asynchronous, the "wait" ends nearly instantly.
I think this means the "bug" is in Home Assistant, but, I also think they would indicate that it's working as intended.
To make this work as you would expect, I think @service(blocking=True) would need to be implemented, informing pyscript that you want that service call to be run synchronously. But, I'm not sure the way pyscript handles incoming service calls can accommodate such a feature since pyscript is entirely async in its core. @craigbarratt would know for sure.
I'm curious if a Home Assistant "script" with a "delay" in it would "block" correctly.