I tried this project in my HA setup, it generally works well, thanks a lot for creating it!
One issue I noticed is that PorcupinePipeline often worked for some time and then suddenly crashed and had to be restarted. After some digging I figured out the reason: PorcupinePipeline assumes that after sending a message the response will arrive in the very next received message, which however is not guaranteed.
A common crash scenario: if a pipeline fails for some reason with an error event, stt_task will terminate, going back to wakeword detection. In such case, however, the run-end event will not be processed. Then the next ping will receive back the unconsumed run-end, instead of the pong, causing a disconnect which breaks the program.
The solution is to properly dispatch websocket messages based on their message ids.
A response always has the same message id as the corresponding request
Pipeline events have the same message id as the assist_pipeline/run request that started the pipeline.
To make the logic cleaner, this PR adds a class HAConnection which handles all low-level websocket communication and only provides 3 high-level public functions to communicate with HA.
send_and_receive_json(message): sends JSON message and receives the response
receive_json(message_id): receives JSON message with a specific message_id
The functions have clear semantics and proprely dispatch messages based on their ids. So stt_task reads only pipeline events, ping/pong are correctly matched, etc.
Outside the HAConnection class the PR is almost trivial, the core functionality remains identical, just replacing the low-level websocket functions with the ones above. There are also some small changes to fix all typing errors (with both pyright and mypy).
With this PR the the crashes stopped in my setup (at least in my limited testing).
I tried this project in my HA setup, it generally works well, thanks a lot for creating it!
One issue I noticed is that PorcupinePipeline often worked for some time and then suddenly crashed and had to be restarted. After some digging I figured out the reason: PorcupinePipeline assumes that after sending a message the response will arrive in the very next received message, which however is not guaranteed.
A common crash scenario: if a pipeline fails for some reason with an
error
event,stt_task
will terminate, going back to wakeword detection. In such case, however, therun-end
event will not be processed. Then the nextping
will receive back the unconsumedrun-end
, instead of thepong
, causing a disconnect which breaks the program.The solution is to properly dispatch websocket messages based on their message ids.
assist_pipeline/run
request that started the pipeline.To make the logic cleaner, this PR adds a class
HAConnection
which handles all low-level websocket communication and only provides 3 high-level public functions to communicate with HA.send_and_receive_json(message)
: sends JSON message and receives the responsereceive_json(message_id)
: receives JSON message with a specificmessage_id
send_bytes(bytes)
: sends binary message (without response)The functions have clear semantics and proprely dispatch messages based on their ids. So
stt_task
reads only pipeline events, ping/pong are correctly matched, etc.Outside the
HAConnection
class the PR is almost trivial, the core functionality remains identical, just replacing the low-level websocket functions with the ones above. There are also some small changes to fix all typing errors (with both pyright and mypy).With this PR the the crashes stopped in my setup (at least in my limited testing).