diff --git a/PlatformIO/.gitignore b/PlatformIO/.gitignore index 89cc49c..153e286 100644 --- a/PlatformIO/.gitignore +++ b/PlatformIO/.gitignore @@ -3,3 +3,4 @@ .vscode/c_cpp_properties.json .vscode/launch.json .vscode/ipch +settings.ini diff --git a/PlatformIO/load_settings.py b/PlatformIO/load_settings.py new file mode 100644 index 0000000..71d28fd --- /dev/null +++ b/PlatformIO/load_settings.py @@ -0,0 +1,46 @@ +Import ("env") +import os.path +import configparser +import hashlib +from string import Template + +settings = "settings.ini" +sectionMatrix = "Matrix" +sectionWifi = "Wifi" +sectionOta = "OTA" +sectionMqtt = "MQTT" + +if os.path.isfile(settings): + config = configparser.RawConfigParser() + config.read(settings) + + otaPasswordHash = hashlib.md5(config[sectionOta]['password'].encode()).hexdigest() + + env.Append(CPPDEFINES=[ + ("WIFI_SSID", "\\\"" + config[sectionWifi]["ssid"] + "\\\""), + ("WIFI_PASS", "\\\"" + config[sectionWifi]["password"] + "\\\""), + ("OTA_PASS_HASH", "\\\"" + otaPasswordHash + "\\\""), + ("SITEID", "\\\"" + config[sectionMatrix]["siteId"] + "\\\""), + ("HOSTNAME", "\\\"" + config[sectionMatrix]["hostname"] + "\\\""), + ("MQTT_IP", "IPAddress\(" + config[sectionMqtt]["ip"].replace(".", ",") + "\)"), + ("MQTT_HOST", "\\\"" + config[sectionMqtt]["hostname"] + "\\\""), + ("MQTT_PORT", "\\\"" + config[sectionMqtt]["port"] + "\\\""), + ("MQTT_USER", "\\\"" + config[sectionMqtt]["username"] + "\\\""), + ("MQTT_PASS", "\\\"" + config[sectionMqtt]["password"] + "\\\""), + ("MQTT_MAX_PACKET_SIZE", config[sectionMqtt]["maxPacketSize"]) + ]) + + env.Replace( + UPLOAD_PROTOCOL="espota", + UPLOAD_PORT=config[sectionMatrix]["hostname"], + UPLOAD_FLAGS=[ + "--port=" + config[sectionOta]["port"], + "--auth=" + config[sectionOta]["password"], + "--timeout=30", + "--f=.pio/build/esp32dev/firmware.bin" + ], + ) +else: + print() + print("Please copy 'settings.ini.example' to 'settings.ini' and set the correct values before building") + exit(1) diff --git a/PlatformIO/platformio.ini b/PlatformIO/platformio.ini index 82651e6..ce68049 100644 --- a/PlatformIO/platformio.ini +++ b/PlatformIO/platformio.ini @@ -12,18 +12,7 @@ build_flags = '-DFIXED_POINT=1' '-DOUTSIDE_SPEEX=1' - '-DWIFI_SSID="SSID"' ; Change to your wifi ssid - '-DWIFI_PASS="password"' ; Change to your wifi password - '-DHOSTNAME="192.168.43.140"' ; Should match above upload_port - '-DSITEID="matrixvoice"' ; siteid is part of the MQTT topic '-DMODELID="alexa"' ; modelid is part of the MQTT topic - '-DOTA_PASS_HASH="createmd5hash"' ; hashed with MD5 https://www.md5hashgenerator.com/ - '-DMQTT_IP=IPAddress(192, 168, 43, 54)' ; Change to the IP of your MQTT broker - '-DMQTT_HOST="192.168.43.54"' ; Change to the IP of your MQTT broker - '-DMQTT_PORT=1883' ; Change to the port of your MQTT broker - '-DMQTT_USER="username"' ; Change to your MQTT username - '-DMQTT_PASS="password"' ; Change to your MQTT password - '-DMQTT_MAX_PACKET_SIZE=2000' ; This is required, otherwise audiopackets will not be send '-lnn_model_alexa_wn3' '-Llib/esp_sr' '-lwakenet' @@ -31,21 +20,15 @@ build_flags = '-lc_speech_features' [env:esp32dev] +extra_scripts = pre:load_settings.py platform = espressif32@1.9.0 upload_protocol = espota board = esp32dev framework = arduino board_build.partitions = ../OTABuilder/partitions_two_ota.csv ; MatrixVoice ESP32 LAN name or IP, should match HOSTNAME in build_flags -upload_port = '192.168.43.140' build_flags = ${common.build_flags} -; MatrixVoice OTA password (auth), should match hashed password (OTA_PASS_HASH) in build_flags -upload_flags = - --port=3232 - --auth=unhashedmd5pass - --f=.pio/build/esp32dev/firmware.bin - lib_deps = https://github.com/matrix-io/matrixio_hal_esp32.git https://github.com/matrix-io/esp32-arduino-ota.git @@ -54,4 +37,4 @@ lib_deps = https://github.com/me-no-dev/AsyncTCP.git https://github.com/knolleary/pubsubclient.git https://github.com/bblanchon/ArduinoJson.git - ESP Async WebServer \ No newline at end of file + ESP Async WebServer diff --git a/PlatformIO/settings.ini.example b/PlatformIO/settings.ini.example new file mode 100644 index 0000000..8517bbb --- /dev/null +++ b/PlatformIO/settings.ini.example @@ -0,0 +1,19 @@ +[Matrix] +hostname=192.168.43.140 +siteId=matrixvoice + +[Wifi] +ssid=SSID +password=password + +[OTA] +password=OTA +port=3232 + +[MQTT] +ip=192.168.43.54 +hostname=192.168.43.54 +port=1883 +username=username +password=password +maxPacketSize=2000 diff --git a/README.md b/README.md index 73c382b..6f33407 100644 --- a/README.md +++ b/README.md @@ -23,22 +23,24 @@ The Arduino code is no longer maintained and will not be further developed, I fo To get the code running I suggest you first reset the Voice if you have flashed it previously - Follow Step 1 and 2 (or all steps) from this guide https://matrix-io.github.io/matrix-documentation/matrix-voice/esp32/ -- ssh into the pi, execute this command: voice_esp32_enable. If you get a permission denied, execute the command again. -- esptool.py --chip esp32 --port /dev/ttyS0 --baud 115200 --before default_reset --after hard_reset erase_flash -- Reboot the Pi. -- Follow this guide on HacksterIO to get started: https://www.hackster.io/matrix-labs/program-matrix-voice-esp32-with-vs-code-using-platformio-3dd498, but in step 2 use "https://github.com/Romkabouter/Matrix-Voice-ESP32-MQTT-Audio-Streamer.git" and not the esp32-platformio repository. Also, the platform.ui file can be found in the PlatformIO subfolder, make the changes from step 3 in that file. -- After that you can use OTA, the platformIO is more stable then the Arduino version +- Once your environment is set up go into the PlatformIO directory +- Copy and configure the `settings.ini.example` to `settings.ini` and configure the proper parameters. Any `$` in the `settings.ini` will be threated as an environment variable, did not find a way to escape it yet, fixes or workarounds are welcome +- Build the project with PlatformIO, for example run `pio run` from the commandline +- Remotely flash the bin file using the provided script `sh deploy.sh pi@raspberry_ip_address` +- From this point one the MatrixVoice can run standalone and you should be able to update via OTA by running `pio run --target upload` ## Arduino (deprecated) In the folder "MatrixVoiceAudioServer", there are two bin files: + - bootloader.bin - partitions_two_ota.bin -These files are needed in order to do the first flashing. You can build your own versions of it by checking out the OTABuilder folder. -In OTABuilder is a program in c++, which does nothing but if you do a make menuconfig you will see that the partition is set to OTA. -When you do a make, the partitions_two_ota.bin will be in the build folder and the bootloader.bin in the build/bootloader folder. + These files are needed in order to do the first flashing. You can build your own versions of it by checking out the OTABuilder folder. + In OTABuilder is a program in c++, which does nothing but if you do a make menuconfig you will see that the partition is set to OTA. + When you do a make, the partitions_two_ota.bin will be in the build folder and the bootloader.bin in the build/bootloader folder. + +To flash the OTA version for the first time, attach the Voice to a Raspberry Pi. -To flash the OTA version for the first time, attach the Voice to a Raspberry Pi. - Get the HAL code from https://github.com/matrix-io/matrixio_hal_esp32/tree/master/components/hal - Copy the folder "hal" to your Arduino IDE libraries folder - Add to Arduino IDE: AsyncMqttClient https://github.com/marvinroger/async-mqtt-client @@ -62,7 +64,7 @@ To flash the OTA version for the first time, attach the Voice to a Raspberry Pi. - Make a change (or not) and do a Sketch -> Upload. The leds will turn WHITE - Sometimes uploading fails, just retry until it succeeds. -If you change code and OTA does not work anymore for some reason, you can always start over by doing the "get started" part except for the first bullet +If you change code and OTA does not work anymore for some reason, you can always start over by doing the "get started" part except for the first bullet ## MQTT commands @@ -70,31 +72,35 @@ The Matrix Voice Audio Server is subscribed to various topics. The topic SITEID/everloop, where SITEID is the name you have given the device, is used for commands concerning the LED Ring. When publishing to this topic, the everloop colors and brightness can be altered without coding, setting it to retained will update the settings as soon as the device is connected. The message can contain 4 keys: - - brightness: integer value between 0 and 100 (%) - - idle: array of 4 codes: [red,green,blue,white], ranging 0-255 - - hotword: array of 4 codes: [red,green,blue,white], ranging 0-255 - - update: array of 4 codes: [red,green,blue,white], ranging 0-255 - - disconnect: array of 4 codes: [red,green,blue,white], ranging 0-255 + +- brightness: integer value between 0 and 100 (%) +- idle: array of 4 codes: [red,green,blue,white], ranging 0-255 +- hotword: array of 4 codes: [red,green,blue,white], ranging 0-255 +- update: array of 4 codes: [red,green,blue,white], ranging 0-255 +- disconnect: array of 4 codes: [red,green,blue,white], ranging 0-255 Example: {"brightness":20,"idle":[240,210,17,0],"hotword":[173,17,240,0],"update":[0,255,255,0]} The topic SITEID/audio also can receive multiple commands: -* Mute/unmute microphones: publish {"mute_input":"true"} or {"mute_input":"false"} -* Mute/unmute playback: publishing {"mute_output":"true"} or {"mute_output":"false"} -* Change the amp to jack/speaker: publish {"amp_output":"0"} or {"amp_output":"1"} -* Adjust mic gain: publish {"gain":5} -* Change the framesize: publish {"framerate":256}, Limited to 32,64,128,256,512 or 1024. -* Switch local/remote hotword detection: publish {"hotword":"local"} or {"hotword":"remote"}, Local only supports "Alexa" -* Adjust volume: publish {"volume": 50} -Restart the device by publishing {"passwordhash":"yourpasswordhash"} to SITEID/restart +- Mute/unmute microphones: publish {"mute_input":"true"} or {"mute_input":"false"} +- Mute/unmute playback: publishing {"mute_output":"true"} or {"mute_output":"false"} +- Change the amp to jack/speaker: publish {"amp_output":"0"} or {"amp_output":"1"} +- Adjust mic gain: publish {"gain":5} +- Change the framesize: publish {"framerate":256}, Limited to 32,64,128,256,512 or 1024. +- Switch local/remote hotword detection: publish {"hotword":"local"} or {"hotword":"remote"}, Local only supports "Alexa" +- Adjust volume: publish {"volume": 50} + +Restart the device by publishing {"passwordhash":"yourpasswordhash"} to SITEID/restart ## Roadmap These features I want to implement in the future, not ordered in any way + - led animations - 3D case including small speakers. ## Known issues -- Uploading sometimes fails or an error is thrown when the uploading is done. + +- Uploading sometimes fails or an error is thrown when the uploading is done. - On device hotword detection seems a bit slow and also the OTA seems to be impacted.