Python script not working

Resurrecting an old post since I am having a similar issue.
I created my own python script for a handler, and it works from container terminal, but doesn’t seem to be called from Rhasspy.

So - I copied the example handler.py to the profile/en directory, created intents to match it, and still nothing… can someone help me debug this? I’m not sure where to find any errors (the log in the GUI shows nothing useful).
image
I tried adding the arguments and forward_to_hass flags and those didn’t seem to have any effect.

image

handler.py

#!/usr/bin/env python

import sys
import json
import random
import datetime


def speech(text):
    global o
    o["speech"] = {"text": text}


# get json from stdin and load into python dict
o = json.loads(sys.stdin.read())

intent = o["intent"]["name"]

if intent == "GetTime":
    now = datetime.datetime.now()
    speech("It's %s %d %s." % (now.strftime('%H'), now.minute, now.strftime('%p')))

elif intent == "Hello":
    replies = ['Hi!', 'Hello!', 'Hey there!', 'Greetings.']
    speech(random.choice(replies))

# convert dict to json and print to stdout
print(json.dumps(o))

sentences.ini

[GetTime]
What time is it

[Hello]
Hello

Can anyone spot what I am missing or doing wrong?
Currently on Rhasspy version 2.5.5

Thanks!
DeadEnd

Last time I tested in 2.5 after it came out I noticed that the script isn’t called. I opened an issue and kept an eye on the development and I don’t think it is fixed yet. Try the rhasspy-hermes-app or another mqtt library to get it working, that is the preferred way for 2.5 right now.

Okay, I copied the example time app from
https://raw.githubusercontent.com/rhasspy/rhasspy-hermes-app/v1.0.0/examples/time_app.py

Created the script copy and pasting in the time_app.py, set the intent handler to the new file (making sure it was executable). GetTime was already a sentence, so no change there.

Still not working…
I’m sure I’m missing something stupidly simple… but I can’t figure it out.

I was digging in the code trying to understand something, and I think I found something but don’t know if it would cause a problem…

In the intent handler, there is a reference to satellites… but at least in the GUI there is no way to set them… I wasn’t sure if this would cause it to error when trying to use a local intent handler.

rhasspy-supervisor/rhasspysupervisor/hasspysupervisor/init.py
Lines 140-145

    # Intent Handling
    handle_system = profile.get("handle.system", "dummy")
    if handle_system not in {"dummy", "hermes"}:
        satellite_site_ids = str(profile.get("handle.satellite_site_ids", "")).split(
            ","
        )

Since I’m pretty dev dumb… would this cause an error if the value doesn’t exist and doesn’t have a fallback default? Going to post this on your issue to help track it.

I haven’t seen you mention MQTT, but Rhasspy Hermes App is meant to be used with an MQTT broker, as the Hermes protocol is defined as MQTT messages. Have a look at the arguments such as --host to define the address of the MQTT broker in the usage documentation.

I’m probably just using it wrong. At first I was trying to use it as an intent handler (setup in the GUI). Then I ran it just in terminal realizing that it was probably stand alone.

I was running it within the container. It says in the usage docs that it uses localhost and 1883. I changed the port to 12183 since that’s what the internal MQTT uses. I didn’t change the address since it should be localhost, but I have had issues with that in containers in the past, so I will try using the container IP and see if that fixes it.

Try running it with the --debug option, that should show you some useful logging information.

By the way:

With Rhasspy Hermes App you don’t have to configure your app as an intent handler in Rhasspy’s web interface, it works completely independently from Rhasspy. It works even when there’s no intent handler defined in Rhasspy because it’s using MQTT.

Yes I did… looks like localhost worked fine - starts up and connects.
I did a sentence recognition from the GUI and that appears to be caught too…
So it looks like the speech isn’t getting back into Rhasspy.

root@9cf8105ec75a:/profiles/en# python3 app_handler.py --port 12183 --debug 
[DEBUG:2020-08-04 15:37:56,524] HermesApp: Namespace(debug=True, host='localhost', log_format='[%(levelname)s:%(asctime)s] %(name)s: %(message)s', password=None, port=12183, site_id=None, tls=False, tls_ca_certs=None, tls_cert_reqs='CERT_REQUIRED', tls_certfile=None, tls_ciphers=None, tls_keyfile=None, tls_version=None, username=None)
[DEBUG:2020-08-04 15:37:56,524] asyncio: Using selector: EpollSelector
[DEBUG:2020-08-04 15:37:56,524] HermesApp: Connecting to localhost:12183
[DEBUG:2020-08-04 15:37:56,527] asyncio: Using selector: EpollSelector
[DEBUG:2020-08-04 15:37:56,527] TimeApp: Connected to MQTT broker
[DEBUG:2020-08-04 15:37:56,527] TimeApp: Subscribed to hermes/intent/GetTime
[DEBUG:2020-08-04 15:38:07,357] TimeApp: -> DialogueEndSession(session_id='ab1c6af1-6199-4fc3-b1ad-db542f83114b', site_id='default', text="It's 15 38", custom_data=None)
[DEBUG:2020-08-04 15:38:07,358] TimeApp: Publishing 116 bytes(s) to hermes/dialogueManager/endSession

So to run a hermes-app do you need to set it up as a service? It has to be running all the time I assume. Right now I just have a terminal running it, but of course it dies when I close.

Ah crap… I just realized I changed to a different example file and it uses the EndSession for the return… I’m going to go out on a limb and guess that doesn’t initiate speech like the speech command does. I’ll try changing to the other example file.

Ok, so the session is ended, this means that Rhasspy should have received this message over MQTT and should have activated the TTS. If you don’t hear anything, there’s something wrong with the TTS. Or does the TTS work otherwise?

Yes you have to run a Rhasspy Hermes App as a service. This could be in a systemd service or in another Docker container. An easy way to create this service is on the roadmap, but for now you’ll have to do it manually.

Thanks for the details.
Yes the TTS works for everything else setup (using Node-Red to post to HTTP API).

This is the code that should work:

"""Example app to react to an intent to tell you the time."""
import logging
from datetime import datetime

from rhasspyhermes.nlu import NluIntent

from rhasspyhermes_app import EndSession, HermesApp

_LOGGER = logging.getLogger("TimeApp")

app = HermesApp("TimeApp")


@app.on_intent("GetTime")
async def get_time(intent: NluIntent):
    """Tell the time."""
    now = datetime.now().strftime("%H %M")
    return EndSession(f"It's {now}")


app.run()

That’s the example file I am using, to the letter.

The only difference that I can think of now is that I am using this with an external MQTT broker. But that shouldn’t be relevant, I think.

In the connection line, it does have CERT_REQUIRED… but I don’t have any certs setup for Rhasspy since its all internal… would this cause a problem? I would expect it not to connect if that were the case…

Never mind - I added --tls-cert-reqs CERT_NONE and it didn’t fix it.

OKAY - I was able to install the mosquitto-client on the container, and subscript to the topics.
After doing recognition in Rhasspy, the hermes-app works, and does appear to post back to the correct topic:

root@9cf8105ec75a:/# mosquitto_sub -t 'hermes/dialogueManager/endSession' -p 12183 --debug
Client mosq/0qjmMRdVFgNnT86ckS sending CONNECT
Client mosq/0qjmMRdVFgNnT86ckS received CONNACK (0)
Client mosq/0qjmMRdVFgNnT86ckS sending SUBSCRIBE (Mid: 1, Topic: hermes/dialogueManager/endSession, QoS: 0, Options: 0x00)
Client mosq/0qjmMRdVFgNnT86ckS received SUBACK
Subscribed (mid: 1): 0
Client mosq/0qjmMRdVFgNnT86ckS received PUBLISH (d0, q0, r0, m0, 'hermes/dialogueManager/endSession', ... (116 bytes))
{"sessionId": "b973d357-7080-45a8-9102-f3b46cf62bf7", "siteId": "default", "text": "It's 16 12", "customData": null}

So the app is working, and posting back to the correct topic… just Rhasspy is not processing it… need to get some sort of log from Rhasspy…

What does docker logs -f rhasspy give?

Okay - found this error in the docker log, seems relavent:

[ERROR:2020-08-04 17:10:43,442] asyncio: Task exception was never retrieved
future: <Task finished coro=<HermesClient.publish_all() done, defined at /usr/lib/rhasspy/rhasspy-hermes/rhasspyhermes/client.py:368> exception=AssertionError('No session')>
Traceback (most recent call last):
  File "/usr/lib/rhasspy/rhasspy-hermes/rhasspyhermes/client.py", line 370, in publish_all
    async for maybe_message in async_generator:
  File "/usr/lib/rhasspy/rhasspy-dialogue-hermes/rhasspydialogue_hermes/__init__.py", line 668, in on_message
    async for end_result in self.handle_end(message):
  File "/usr/lib/rhasspy/rhasspy-dialogue-hermes/rhasspydialogue_hermes/__init__.py", line 375, in handle_end
    assert self.session is not None, "No session"
AssertionError: No session

Nice bonus, this actually helped me fix the other issue with the local command handler. Looks like it isn’t working with the ${RHASSPY_PROFILE_DIR} - using an absolute path seems to fix it.

Anyway, back to the hermes-app - something is wrong with the sessions I see… not sure how to dig deeper yet… will keep looking.

Is the intent part of a session? Did you try this starting from a wake word or by typing the sentence in the web interface?

typing into the web interface.

Can you try it by talking to Rhasspy? Typing into the web interface isn’t the same, it doesn’t trigger the TTS.

Try to write #!/usr/bin/env python3 in the first line