Rebranded the Matrix Voice to esp32-rhasspy-satellite

@romkabouter again…awesome work on the satellite. Some questions:
I followed this part

  1. In the settings.ini file there is a hostname, what do I put there?
  2. My Wifi password has a $ in it. Am I screwed in getting this to work… :frowning:

1: whatever you want, the device should then be reachable via that hostname. I do not really know if that works, I always use the ip adress
2: I think uploading via the matrix method should work (connected to a pi), but I am not sure. You could try and change the password, flash it, change wifi password back and try OTA.
Or just change the wifi password?

Thx for the help.

I get this error: KeyError: ‘network_type’: Could this be that darn password with the $

 File "C:\Users\xxxxxx\.platformio\penv\Lib\site-packages\platformio\builder\main.py", line 178:
    env.SConscript(item, exports="env")
  File "C:\Users\xxxxxx\.platformio\packages\tool-scons\scons-local-4.2.0\SCons\Script\SConscript.py", line 597:
    return _SConscript(self.fs, *files, **subst_kw)
  File "C:\Users\xxxxxx\.platformio\packages\tool-scons\scons-local-4.2.0\SCons\Script\SConscript.py", line 285:
    exec(compile(scriptdata, scriptname, 'exec'), call_stack[-1].globals)
  File "E:\xxxxxx\GitHub\RHASSPY\ESP32-Rhasspy-Satellite\PlatformIO\load_settings.py", line 32:
    ("NETWORK_TYPE", config[sectionGeneral]["network_type"])
  File "C:\Users\xxxxxx\AppData\Local\Programs\Python\Python310\lib\configparser.py", line 1258:
    raise KeyError(key)

I have Python 3.10 newly installed on windows 10and then Platformio latest via script and then the app on VSCode v1.61.2. Matrix ESP32 hat on Raspberry with latest OS. Shell setup in system environmental and python vars there to.

No, I do not think so. Do you have the latest code?

Yes I do.
Here is my settings file(redacted for safety)

[General]
hostname=188.0.0.58
deployhost=188.0.0.25
siteId=satellite
;supported: M5ATOMECHO=0, MATRIXVOICE=1, AUDIOKIT=2
device_type=1

[Wifi]
ssid='xxxx'
password='xxx$xxx'

;uncomment next 4 lines and fill with your own values if you want to use a static ip address
;ip=192.168.xxx.xxx
;gateway=192.168.xxx.xxx
;subnet=255.255.255.0
;dns1=192.168.xxx.xxx
;optional: second dns server
;dns2=192.168.xxx.xxx 

[OTA]
;supported: upload, ota, matrix
;-upload: device should be attached to computer via usb
;-ota: will use espota
;-matrix: matrix voice should be attached to a raspberry pi with matrix software.
;         deployhost should be set to ip of the pi
method=matrix
password=OTApassword
port=3232

[MQTT]
ip=188.0.0.46:8123
port=1883
username='xxxx'
password='xxxxx'

This is missingL

network_type=0

Check the example here:

1 Like

Aah right. Hmm not sure why it was not there.

I now get this error uploading to the ESP32:
‘sh’ is not recognized as an internal or external command, operable program or batch file.

I did a verbose and at the end saw this:

<lambda>(["upload"], [".pio\build\esp32dev\firmware.bin"])
AVAILABLE: custom, esp-prog, espota, esptool, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa
CURRENT: upload_protocol = custom
sh deploy.sh 144.0.0.25

Also what do you mean here?

  • After first flash you can use ‘ota’ as method under the OTA section in the settings.ini

Thx a lot for you help.

You are probably on windows? sh is a linux/unix shell. I do not know how to run that on windows.

The code supports OTA (Over The Air) updates, but you first have to flash it once via another way :slight_smile:

Might this help:
How to run .sh or Shell Script file in Windows 11/10 (thewindowsclub.com)

I do not know, I do not have windows. Just try I guess, or maybe create a VM or something?

I changed load_settings.py line from

UPLOADCMD="sh deploy.sh " + config[sectionGeneral]["deployhost"]

to

UPLOADCMD="bash deploy.sh " + config[sectionGeneral]["deployhost"]

but I now get this error and I can not see what the problem is within the deploy.sh code

deploy.sh: line 3: $'\r': command not found
deploy.sh: line 4: syntax error near unexpected token `$'{\r''
deploy.sh: line 4: `showhelp () {'

I’ll try and see if I can wrap up a windows machine somewhere

1 Like

seems like I need to ask the same question, but with other circumstances. Today I received my m5atom and flashed it successfully. Wakeword is working, receiving speech, transforming it to an intent is working, but my m5 doesn’t answer.

I have Rhasspy installed as a docker container on a pi4, using mosquitto as my external MQTT broker in another docker container on the same pi4, trying to make automation with node-red (not sure if I will count on node-red in the future). As I am new with Rhasspy and this is my first trial, I am even not sure if my settings are right.

Base station settings:

{
    "dialogue": {
        "satellite_site_ids": "rhasspy-mobile-chris,atom1",
        "system": "rhasspy"
    },
    "handle": {
        "remote": {
            "url": "http://192.168.XXX.XXX:8081/intent"
        },
        "satellite_site_ids": "rhasspy-mobile-chris,atom1",
        "system": "remote"
    },
    "intent": {
        "satellite_site_ids": "rhasspy-mobile-chris,atom1",
        "system": "fsticuffs"
    },
    "mqtt": {
        "enabled": true,
        "host": "192.168.XXX.XXX",
        "password": "...",
        "site_id": "pi4base",
        "username": "..."
    },
    "speech_to_text": {
        "satellite_site_ids": "rhasspy-mobile-chris,atom1",
        "system": "kaldi"
    },
    "text_to_speech": {
        "satellite_site_ids": "rhasspy-mobile-chris,atom1",
        "system": "nanotts"
    },
    "wake": {
        "porcupine": {
            "keyword_path": "jarvis_raspberry-pi.ppn",
            "udp_audio": "172.21.0.2:20000"
        },
        "satellite_site_ids": "rhasspy-mobile-chris,atom1",
        "system": "porcupine"
    }
}

172.21.0.2 is the docker container ID.

Base station log if I ask “Jarvis” something:

[DEBUG:2021-11-08 22:20:01,979] rhasspyserver_hermes: Sent 477 char(s) to websocket
[DEBUG:2021-11-08 22:20:01,975] rhasspyserver_hermes: Sent 477 char(s) to websocket
[DEBUG:2021-11-08 22:20:01,970] rhasspyserver_hermes: Sent 477 char(s) to websocket

That’s it…

In Node-Red this is the message I get from MQTT in:

{
  "topic": "hermes/intent/GetDate",
  "payload": {
    "input": "Welches Datum haben wir",
    "intent": { "intentName": "GetDate", "confidenceScore": 1 },
    "siteId": "atom1",
    "id": null,
    "slots": [],
    "sessionId": "atom1-jarvis_raspberry-pi-90dc7f88-d154-454a-9afc-551a29286664",
    "customData": "jarvis_raspberry-pi",
    "asrTokens": [
      [
        {
          "value": "Welches",
          "confidence": 1,
          "rangeStart": 0,
          "rangeEnd": 7,
          "time": null
        },
        {
          "value": "Datum",
          "confidence": 1,
          "rangeStart": 8,
          "rangeEnd": 13,
          "time": null
        },
        {
          "value": "haben",
          "confidence": 1,
          "rangeStart": 14,
          "rangeEnd": 19,
          "time": null
        },
        {
          "value": "wir",
          "confidence": 1,
          "rangeStart": 20,
          "rangeEnd": 23,
          "time": null
        }
      ]
    ],
    "asrConfidence": 1,
    "rawInput": "welches datum haben wir",
    "wakewordId": "jarvis_raspberry-pi",
    "lang": null
  },
  "qos": 0,
  "retain": false,
  "_msgid": "7ca31bd7.a8ed74"
}

And this is the output I hand over to MQTT out:

{
  "topic": "hermes/intent/GetDate",
  "payload": {
    "input": "Welches Datum haben wir",
    "intent": { "intentName": "GetDate", "confidenceScore": 1 },
    "siteId": "atom1",
    "id": null,
    "slots": [],
    "sessionId": "atom1-jarvis_raspberry-pi-90dc7f88-d154-454a-9afc-551a29286664",
    "customData": "jarvis_raspberry-pi",
    "asrTokens": [
      [
        {
          "value": "Welches",
          "confidence": 1,
          "rangeStart": 0,
          "rangeEnd": 7,
          "time": null
        },
        {
          "value": "Datum",
          "confidence": 1,
          "rangeStart": 8,
          "rangeEnd": 13,
          "time": null
        },
        {
          "value": "haben",
          "confidence": 1,
          "rangeStart": 14,
          "rangeEnd": 19,
          "time": null
        },
        {
          "value": "wir",
          "confidence": 1,
          "rangeStart": 20,
          "rangeEnd": 23,
          "time": null
        }
      ]
    ],
    "asrConfidence": 1,
    "rawInput": "welches datum haben wir",
    "wakewordId": "jarvis_raspberry-pi",
    "lang": null,
    "text": "Heute ist Montag der 8. November 2021"
  },
  "qos": 0,
  "retain": false,
  "_msgid": "7ca31bd7.a8ed74"
}

And this is the JSON of my node-red flow:

[
    {
        "id": "de4ca1a1.9c245",
        "type": "tab",
        "label": "Rhasspy_MQTT",
        "disabled": false,
        "info": ""
    },
    {
        "id": "d3a54a61.5f5bd",
        "type": "mqtt in",
        "z": "de4ca1a1.9c245",
        "name": "mosquitto",
        "topic": "hermes/intent/#",
        "qos": "2",
        "datatype": "json",
        "broker": "8494e798.106348",
        "nl": false,
        "rap": true,
        "rh": 0,
        "x": 220,
        "y": 140,
        "wires": [
            [
                "3b203211.bde36e",
                "6e70ab0.d19a954",
                "2c47428c.4b82e6"
            ]
        ]
    },
    {
        "id": "d11f5476.b548b8",
        "type": "mqtt out",
        "z": "de4ca1a1.9c245",
        "name": "mosquitto",
        "topic": "hermes/dialogueManager/endSession,hermes/tts/say",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "8494e798.106348",
        "x": 1320,
        "y": 160,
        "wires": []
    },
    {
        "id": "b82bc0c9.cae788",
        "type": "debug",
        "z": "de4ca1a1.9c245",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 1140,
        "y": 400,
        "wires": []
    },
    {
        "id": "6e70ab0.d19a954",
        "type": "switch",
        "z": "de4ca1a1.9c245",
        "name": "Intenterkennung",
        "property": "payload.intent.intentName",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "GetTime",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "GetDate",
                "vt": "str"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": true,
        "outputs": 3,
        "x": 430,
        "y": 240,
        "wires": [
            [
                "97ac5e01.dbf1e"
            ],
            [
                "524df9cb.70e5"
            ],
            [
                "e9e436e0.3c4d7"
            ]
        ]
    },
    {
        "id": "97ac5e01.dbf1e",
        "type": "function",
        "z": "de4ca1a1.9c245",
        "name": "Zeitausgabe",
        "func": "var timeString = new Date().toLocaleTimeString([],\n{\nhour: \"2-digit\", \nminute: \"2-digit\",\nhour12: false\n})\n\nreturn {\npayload: \"Es ist \" + timeString\n}",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 620,
        "y": 200,
        "wires": [
            [
                "d11f5476.b548b8",
                "b82bc0c9.cae788"
            ]
        ]
    },
    {
        "id": "e9e436e0.3c4d7",
        "type": "template",
        "z": "de4ca1a1.9c245",
        "name": "Unrecognized",
        "field": "payload",
        "fieldType": "msg",
        "format": "handlebars",
        "syntax": "plain",
        "template": "{\n  \"data\": {\n    \"intent\": {\n      \"name\": \"unrecognized\",\n      \"confidence\": 0\n    }\n  },\n  \"speech\": {\n    \"text\": \"Kommando nicht erkannt.\"\n  }\n}",
        "output": "json",
        "x": 630,
        "y": 300,
        "wires": [
            [
                "d11f5476.b548b8",
                "b82bc0c9.cae788"
            ]
        ]
    },
    {
        "id": "524df9cb.70e5",
        "type": "function",
        "z": "de4ca1a1.9c245",
        "name": "Datumsausgabe",
        "func": "var sessionId=flow.get('sessionId')\nvar siteId=flow.get('siteId')\nvar datum = new Date();\nvar tag = datum.getDay();\nvar wotag = wochentag(tag);\n//log(wotag);\nvar now = new Date();\nvar dd = now.getDate();\nvar mm = now.getMonth()+1;\nvar monat =\"\";\nif  (mm == 1)  { monat = \"Januar\";}   \nelse if (mm == 2)  { monat = \"Februar\";} \nelse if (mm == 3)  { monat = \"März\";} \nelse if (mm == 4)  { monat = \"April\";} \nelse if (mm == 5)  { monat = \"Mai\";} \nelse if (mm == 6)  { monat = \"Juni\";} \nelse if (mm == 7)  { monat = \"Juli\";} \nelse if (mm == 8)  { monat = \"August\";} \nelse if (mm == 9)  { monat = \"September\";} \nelse if (mm == 10) { monat = \"Oktober\";} \nelse if (mm == 11) { monat = \"November\";} \nelse if (mm == 12) { monat = \"Dezember\";} \nvar yyyy = now.getFullYear();\nmsg.payload.text = 'Heute ist ' + wotag + ' der ' + dd + '. '  + monat + ' ' + yyyy;\n//msg.siteId = 'atom1';\nmsg.payload.sessionId = sessionId;\nmsg.payload.siteId = siteId;\nreturn msg;\n\nfunction wochentag(i){\n\n    var tage = ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag'];\n\n    var tag = (typeof(i) == 'object') ? i.getDay() : i ;\n\n    return tage[tag];\n\n}",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 640,
        "y": 240,
        "wires": [
            [
                "d11f5476.b548b8",
                "b82bc0c9.cae788"
            ]
        ]
    },
    {
        "id": "3b203211.bde36e",
        "type": "debug",
        "z": "de4ca1a1.9c245",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 410,
        "y": 100,
        "wires": []
    },
    {
        "id": "2c47428c.4b82e6",
        "type": "function",
        "z": "de4ca1a1.9c245",
        "name": "Flow Variables",
        "func": "flow.set('siteId',msg.payload.siteId)\nflow.set('sessionId',msg.payload.sessionId)",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 440,
        "y": 400,
        "wires": [
            []
        ]
    },
    {
        "id": "8494e798.106348",
        "type": "mqtt-broker",
        "name": "mosquitto",
        "broker": "192.168.XXX.XXX",
        "port": "1883",
        "clientid": "iobroker_node-red",
        "usetls": false,
        "protocolVersion": "5",
        "keepalive": "60",
        "cleansession": true,
        "birthTopic": "",
        "birthQos": "0",
        "birthPayload": "",
        "birthMsg": {},
        "closeTopic": "",
        "closeQos": "0",
        "closePayload": "",
        "closeMsg": {},
        "willTopic": "",
        "willQos": "0",
        "willPayload": "",
        "willMsg": {},
        "sessionExpiry": ""
    }
]

Can someone help me to get the last pieces together?

I do not see a settings for sounds (Audio Playing), it should be Hermes MQTT.
This might be the issue, but I will have to import your Node-Red flow to see other issues.
One thing I notice is that you post to two topics. hermes/tts/say is not needed.

1 Like

I have imported your flow, there are several things not correct or missing.

  1. Your MQTT output only needs hermes/dialogueManager/endSession
  2. I will use the Zeitausgabe function node as example. This output only a payload, but this is incorrect. The correct payload to Rhasspy should be
    {"sessionId": """ + flow.get('sessionId') + """, "text" : "Es ist " + timeString}
    The sessionId is needed because that is how Rhasspy knows which satellite triggered the wakeword. Maybe I get the escaping incorrect in the sessionId, but if I look at your example the payload to your outputnode should become: {"sessionId":"atom1-jarvis_raspberry-pi-90dc7f88-d154-454a-9afc-551a29286664", "text":"Heute ist Montag der 8. November 2021"}
    Nothing more is needed and all the rest you send back might cause issues in processing.
1 Like

Hi all, I am new to Rhasspy, but managed to get it work on a raspberry Pi. Now I want to add M5 Atom Echo as satellite, but i am stuck. First, in the settings, we have hostname and deployhost, what are these variables ? is the hostname the name of the Atom echo i am flashing, so i can name it “AtomEcho-1” for example _ and is the deployhost the io of the rhasspy base?
Is this correct ?

I also wanted to flash the Atom Echo with platformio in my Visual studio code, but get an error
Configuring flash size…

A fatal error occurred: Timed out waiting for packet header
*** [upload] Error 2
=================================================================== [FAILED] Took 8.08 seconds ===================================================================
The terminal process “C:\Users\micro.platformio\penv\Scripts\platformio.exe ‘run’, ‘–target’, ‘upload’” terminated with exit code: 1.
Do i need to do something specuial to put the Atom Echo in flash mode ?
Thanks for any help

Dunno that was @romkabouter arena https://github.com/Romkabouter/ESP32-Rhasspy-Satellite

deployhost is only used for the Matrix Voice and is the Raspberry Pi the MV has to be connected to for the first flash. In your case: not used.

hostname is indeed the hostname of you device.

No. Did you attach the M5 to your pc? Since the message says timeout.
What instructions did you follow?

This is what I have done ( it is also the first time I use Platform.io, I am used to use arduino for my ESP32 projects
I imported the folder ESP32-Rhasspy-Satellite-master in mz platform io.
I then created a settings.ini file. I then enter the command line, and go the the folder platformio. I then run pio run --target upload
and here I already get the first problem as it seems that all arduino examples for the esp32 board are installed, but now,…
as I redo the complete process to write this answer, it works. Maybe because I added a Gitclient ?

Thanks for your support, now I have to figure out how this works. as I understand by looking at the webinterface it does not recognize a hotword locally.
I will try to figure out what to do next, and will come back once I get stuck next time

Nope it never had a hotword the LX6 based esp32s don’t really have the oomf and I really don’t like the idea of always on network mics but hey.
The m5atom shows with economies of sale where espressif can land price wise but for KWS I wouldn’t even consider a esp32 as even an always on mic satellite is a tight fit.

esp32-s3 is the newer lx7 architecture and has been tweaked and improved in just about every area giving approx > x10 performance with some instructions.
So comparing the 2 is a bit like the old Pi zero and new where the old zero just doesn’t make the grade and the zero2 hits a sweet spot where its capable but to be honest that m5atom is an odd fit for the role as is also a non kws based satelite, but hey.