Hi @cpinnock00. I confirm the problem. I investigated and found that there is an incompatibility between the Python script from the tutorial's Docker image and the operating system image version 934.
There is actually a separate arduino/python-rpc-sensors Docker image that does the same thing as the one from the tutorial, but has a fix for the incompatibility:
Other than that fix, the significant difference between the arduino/python-rpc-sensors image and the "python-sensor-rpc" image from the tutorial is that the sketch bundled with the arduino/python-rpc-sensors only produces dummy sensor data (as opposed to the sketches bundled with the tutorial's image, which reads real data from the sensor):
The reason the "rpc-sensors" sketch bundled with the arduino/python-rpc-sensors image produces dummy data is to make it a more simple basic "hello world" demonstration. If you only want a minimal demonstration of RPC communication, the tutorial's dependence on an external sensor introduces significant irrelevant complexity.
You can see the fix that was made in the arduino/python-rpc-sensors image's Python script for the incompatibility with OS image 934 here:
--- a/python-rpc-sensors/python/main.py
+++ b/python-rpc-sensors/python/main.py
@@ -8,7 +8,7 @@
m4_proxy_host = 'm4-proxy'
m4_proxy_call_port = 5001
-def get_data_from_m4(rpc_client):
+def get_data_from_m4(rpc_address):
"""Get data from the M4 via RPC (MessagePack-RPC)
The Arduino sketch on the M4 must implement the following methods
@@ -20,17 +20,19 @@ def get_data_from_m4(rpc_client):
* `gas`
* `altitude`
+ WARNING: due to a known issue with msgpackrpc library, we can only
+ make a single call after RpcClient. If we need to make multiple calls,
+ we need to create a new RpcClient instance for each call.
+
"""
data = ()
+ sensors = ('temperature', 'humidity', 'pressure', 'gas', 'altitude')
try:
- temperature = rpc_client.call('temperature')
- humidity = rpc_client.call('humidity')
- pressure = rpc_client.call('pressure')
- gas = rpc_client.call('gas')
- altitude = rpc_client.call('altitude')
- data = temperature, humidity, pressure, gas, altitude
+ get_value = lambda value: RpcClient(rpc_address).call(value)
+ data = tuple(get_value(measure) for measure in sensors)
+
except RpcError.TimeoutError:
- print("Unable to retrive data from the M4.")
+ print("Unable to retrieve data from the M4.")
return data
if __name__ == '__main__':
@@ -43,9 +45,8 @@ def get_data_from_m4(rpc_client):
try:
rpc_address = RpcAddress(m4_proxy_host, m4_proxy_call_port)
- rpc_client = RpcClient(rpc_address)
while True:
- data = get_data_from_m4(rpc_client)
+ data = get_data_from_m4(rpc_address)
if len(data) > 0:
print("Temperature: ", data[0])
print("Humidity: ", data[1])
So the easiest solution will be to use the arduino/python-rpc-sensors image. I'll provide instructions you can follow to do that:
- Use
adb shellto open a shell in the X8's Linux machine, as usual. - Run the following command to create a folder to store the Docker "Compose file" that is used to configure the container:
mkdir python-rpc-sensors && cd python-rpc-sensors - Run the following command to download the Compose file:
wget https://raw.githubusercontent.com/arduino/portenta-containers/refs/heads/main/python-rpc-sensors/docker-compose.yml - Run the following command to override the image configuration from the downloaded Compose file to use the public image Arduino distributes via the Docker Hub registry:
echo ' services: python-rpc-sensors: image: arduino/python-rpc-sensors:latest ' > compose.override.yaml- ā This is required because the Compose file is configured to pull the image from a private FoundriesFactory image registry. That is useful if you have a FoundriesFactory account and want to manage your own copy/variant of the image via that service, but the publicly available image is perfectly sufficient for this simple demo.
- Run the following command:
sudo docker compose up
The container will now start running. You should see output with this form:
$ sudo docker compose up
WARN[0000] The "FACTORY" variable is not set. Defaulting to a blank string.
[+] Building 0.0s (0/0)
[+] Running 1/0
ā Container python-rpc-sensors-python-rpc-sensors-1 Created 0.0s
Attaching to python-rpc-sensors-python-rpc-sensors-1
python-rpc-sensors-python-rpc-sensors-1 |
python-rpc-sensors-python-rpc-sensors-1 | ============================================
python-rpc-sensors-python-rpc-sensors-1 | == Portenta X8 Sensor reading ==
python-rpc-sensors-python-rpc-sensors-1 | ============================================
python-rpc-sensors-python-rpc-sensors-1 |
python-rpc-sensors-python-rpc-sensors-1 | Temperature: 25.904266357421875
python-rpc-sensors-python-rpc-sensors-1 | Humidity: 25.564695358276367
python-rpc-sensors-python-rpc-sensors-1 | Pressure: 976.4400024414062
python-rpc-sensors-python-rpc-sensors-1 | Gas: 136.496
python-rpc-sensors-python-rpc-sensors-1 | Altitude: 311.0769348144531
[...]
You can use the arduino/python-rpc-sensors image with the "M4_BME680_RPC" sketch that is bundled with the image provided by the tutorial, or with the simplified "rpc-sensors" sketch.
Please let us know if you have any questions or problems while following those instructions.
I have notified the people at Arduino responsible for the tutorial about the problem of the incompatibility of the tutorial with the current operating system version. I apologize for any confusion and inconvenience this error has caused.