Python websockets connect call fails

I’m somewhat new to Rhasspy and Python.

I’ve installed Rhasspy version 2.5.11 on a Raspberry Pi 4 with Docker as per the instructions on the Rhasspy site. I’ve written a Python program to receive intents from Rhasspy using websockets and then act upon the intents.

When I start my program from the command line it works as expected. But when I auto start my program the websocket connection from my Python program to Rhasspy fails.

I’m wondering if it could be a timing issue where the Python program starts before Rhasspy. But I tried putting the websockets.connect() in the main() function and it worked. I’m missing something, so help is very much appreciated.

Thanks,
Steve

Here is the connect failure:

pi@NWI-RPI4-4:~ $ sudo systemctl status northern-wolf
● northern-wolf.service - Northern Wolf Inc.
   Loaded: loaded (/lib/systemd/system/northern-wolf.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Tue 2021-08-31 11:37:48 EDT; 1min 1s ago
  Process: 987 ExecStart=/usr/bin/sudo -H -u pi /usr/bin/python3 /home/pi/bin/released/controller.py > /home/pi/nwi.log 2>&1 (code=exited, status=1/FAILURE)
 Main PID: 987 (code=exited, status=1/FAILURE)

Aug 31 11:37:48 NWI-RPI4-4 sudo[987]:   File "/home/pi/.local/lib/python3.7/site-packages/websockets/client.py", line 517, in __aenter__
Aug 31 11:37:48 NWI-RPI4-4 sudo[987]:     return await self
Aug 31 11:37:48 NWI-RPI4-4 sudo[987]:   File "/home/pi/.local/lib/python3.7/site-packages/websockets/client.py", line 535, in __await_impl__
Aug 31 11:37:48 NWI-RPI4-4 sudo[987]:     transport, protocol = await self._create_connection()
Aug 31 11:37:48 NWI-RPI4-4 sudo[987]:   File "/usr/lib/python3.7/asyncio/base_events.py", line 968, in create_connection
Aug 31 11:37:48 NWI-RPI4-4 sudo[987]:     ', '.join(str(exc) for exc in exceptions)))
Aug 31 11:37:48 NWI-RPI4-4 sudo[987]: OSError: Multiple exceptions: [Errno 111] Connect call failed ('::1', 12101, 0, 0), [Errno 111] Connect call failed ('127.
Aug 31 11:37:48 NWI-RPI4-4 sudo[987]: pam_unix(sudo:session): session closed for user pi
Aug 31 11:37:48 NWI-RPI4-4 systemd[1]: northern-wolf.service: Main process exited, code=exited, status=1/FAILURE
Aug 31 11:37:48 NWI-RPI4-4 systemd[1]: northern-wolf.service: Failed with result 'exit-code'.
pi@NWI-RPI4-4:~ $ 

Here is the service file I’m using:

pi@NWI-RPI4-4:/lib/systemd/system $ more northern-wolf.service 
[Unit]
Description=Northern Wolf Inc.
After=multi-user.target

[Service]
ExecStart=sudo -H -u pi /usr/bin/python3 /home/pi/bin/released/controller.py > /home/pi/nwi.log 2>&1

[Install]
WantedBy=multi-user.target

pi@NWI-RPI4-4:/lib/systemd/system $ 

And here is my Python program:

#!/usr/bin/env python3

import asyncio
import json
import logging
import pyudev
import requests
from rhasspyclient import RhasspyClient
import serial
import serial.tools.list_ports
import subprocess
from time import strftime, localtime
import websockets
from websockets import WebSocketClientProtocol

logging.basicConfig(level = logging.INFO)


# Variables for the Rhasspy voice assistant.
RHASSPY_PROTOCOL                = 'http'
RHASSPY_HOST                    = 'localhost'
RHASSPY_PORT                    = '12101'
RHASSPY_ENDPOINT_INTENT         = 'api/events/intent'
RHASSPY_ENDPOINT_TEXT_TO_SPEECH = 'api/text-to-speech'

    
def process_intent(message, intent):
    # Get the intent (i.e. command).
    the_intent = intent['name']


async def consumerHandler(websocket: WebSocketClientProtocol):
    # Go through the messages from the websocket with Rhasspy.
    async for message in websocket:
        
        # Deserialize (decode) the the JSON message received.
        message = json.loads(message)
        logging.info('Received the following message from Rhasspy:')
        logging.info(json.dumps(message, indent = 2))
        
        try:
            # Get the intent that was invoked.
            intent = message['intent']
            
        except:
            # An exception occurred.
            logging.error('Received a message from Rhasspy that did not contain an intent.')
        
        else:
            # There is a message with an intent, now process the intent.
            process_intent(message, intent)


async def consume(hostname: str, port: int, endpoint: str):
    # Wait for messages on the websocket with Rhasspy.
    uri = f'ws://{hostname}:{port}/{endpoint}'
    async with websockets.connect(uri) as websocket:
        await consumerHandler(websocket)


def main():
    
    # Wait for messages from Rhasspy. These should have bed controller commands.
    asyncio.run(
         consume(
            hostname = RHASSPY_HOST,
            port     = RHASSPY_PORT,
            endpoint = RHASSPY_ENDPOINT_INTENT
        )
    )


if __name__ == '__main__':
   main()