Skip to content

Commit 7de8616

Browse files
authored
Merge pull request #2770 from arduino/mcmchris/uno-q/rpc-doc
[PXCT-1614] Router + RPC Documentation Extended in User Manual
2 parents 2a4fe4e + d73fce6 commit 7de8616

File tree

2 files changed

+129
-3
lines changed

2 files changed

+129
-3
lines changed
2.38 MB
Loading

content/hardware/02.uno/boards/uno-q/tutorials/01.user-manual/content.md

Lines changed: 129 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,7 @@ The `Bridge` library provides a communication layer built on top of the `Arduino
821821

822822
#### The Arduino Router (Infrastructure)
823823

824-
Under the hood, the communication is managed by a background Linux service called the Arduino Router (`arduino-router`).
824+
Under the hood, the communication is managed by a background Linux service called the **Arduino Router** (`arduino-router`).
825825

826826
While the `Bridge` library is what you use in your code, the Router is the traffic controller that makes it possible. It implements a **Star Topology** network using MessagePack RPC.
827827

@@ -835,7 +835,22 @@ While the `Bridge` library is what you use in your code, the Router is the traff
835835

836836
- **Service Discovery:** Clients (like your Python® script or the MCU Sketch) "register" functions they want to expose. The Router keeps a directory of these functions and routes calls to the correct destination.
837837

838-
**Managing the Router Service**
838+
**Source Code:**
839+
840+
- **[Arduino Router Service](https://github.com/arduino/arduino-router)**
841+
- **[Arduino_RouterBridge Library](https://github.com/arduino-libraries/Arduino_RouterBridge/tree/main)**
842+
843+
#### System Configuration & Hardware Interfaces
844+
845+
The Router manages the physical connection between the two processors. It is important to know which hardware resources are claimed by the Router to avoid conflicts in your own applications.
846+
847+
* **Linux Side (MPU):** The router claims the serial device `/dev/ttyHS1`.
848+
* **MCU Side (STM32):** The router claims the hardware serial port `Serial1`.
849+
850+
> **⚠️ WARNING: Reserved Resources**
851+
> Do not attempt to open `/dev/ttyHS1` (on Linux) or `Serial1` (on Arduino/Zephyr) in your own code. These interfaces are exclusively locked by the `arduino-router` service. Attempting to access them directly will cause the Bridge to fail.
852+
853+
#### Managing the Router Service
839854

840855
The arduino-router runs automatically as a system service. In most cases, you do not need to interact with it directly. However, if you are debugging advanced issues or need to restart the communication stack, you can control it via the Linux terminal:
841856

@@ -923,7 +938,7 @@ To capture more detailed information in the logs, you can append the `--verbose`
923938
- **Incoming Updates**: Handled by a dedicated background thread (`updateEntryPoint`) that continuously polls for requests.
924939
- **Safe Execution**: The provide_safe mechanism hooks into the main loop (`__loopHook`) to execute user callbacks safely when the processor is idle.
925940

926-
#### Usage Example
941+
#### Usage Example (Arduino App Lab)
927942

928943
This example shows the **Linux side (Qualcomm QRB)** toggling an LED on the **MCU (STM32)** by calling a remote function over the Bridge.
929944

@@ -984,6 +999,117 @@ After pasting the Python script into your App’s Python file and the Arduino co
984999

9851000
***There are more advanced methods in the Bridge RPC library that you can discover by testing our different built-in examples inside Arduino App Lab.***
9861001

1002+
#### Interacting via Unix Socket (Advanced)
1003+
1004+
Linux processes communicate with the Router using a **Unix Domain Socket** located at:
1005+
`/var/run/arduino-router.sock`
1006+
1007+
While the `Bridge` library handles this automatically for you, you can manually connect to this socket to interact with the MCU or other Linux services using any language that supports **MessagePack RPC** (e.g., Python, C++, Rust, Go).
1008+
1009+
#### Usage Example (Custom Python Client)
1010+
1011+
The following example demonstrates how to control an MCU function (`set_led_state`) from a standard Python script using the `msgpack` library, without using the Arduino App Lab helper classes. This is useful for integrating Arduino functions into existing Linux applications.
1012+
1013+
**Prerequisites:**
1014+
1015+
1. **Flash the MCU Sketch**
1016+
1017+
Upload the following code using the Arduino IDE or Arduino App Lab. This registers the function we want to call.
1018+
1019+
```cpp
1020+
#include "Arduino_RouterBridge.h"
1021+
1022+
void setup() {
1023+
pinMode(LED_BUILTIN, OUTPUT);
1024+
1025+
Bridge.begin();
1026+
// We use provide_safe to ensure the hardware call runs in the main loop context
1027+
Bridge.provide_safe("set_led_state", set_led_state);
1028+
}
1029+
1030+
void loop() {
1031+
}
1032+
1033+
void set_led_state(bool state) {
1034+
digitalWrite(LED_BUILTIN, state ? LOW : HIGH);
1035+
}
1036+
```
1037+
2. **Install the Python Dependency**
1038+
1039+
Install the msgpack library using the system package manager:
1040+
1041+
```bash
1042+
sudo apt install python3-msgpack
1043+
```
1044+
3. **Create the Python Script**
1045+
1046+
Create a new file named msgpack_test.py:
1047+
1048+
```bash
1049+
nano msgpack_test.py
1050+
```
1051+
4. **Add the Script Content**
1052+
1053+
Copy and paste the following code. This script connects manually to the Router's Unix socket and sends a raw RPC request.
1054+
1055+
```python
1056+
import socket
1057+
import msgpack
1058+
import sys
1059+
1060+
# 1. Define the connection to the Router's Unix Socket
1061+
SOCKET_PATH = "/var/run/arduino-router.sock"
1062+
1063+
# 2. Parse command line arguments
1064+
# Default to turning LED ON (True) if no argument is provided
1065+
led_state = True
1066+
1067+
if len(sys.argv) > 1:
1068+
arg = sys.argv[1]
1069+
if arg == "1":
1070+
led_state = True
1071+
elif arg == "0":
1072+
led_state = False
1073+
else:
1074+
print("Usage: python3 msgpack_test.py [1|0]")
1075+
sys.exit(1)
1076+
1077+
print(f"Sending request to set LED: {led_state}")
1078+
1079+
# 3. Create the MessagePack RPC Request
1080+
# Format: [type=0 (Request), msgid=1, method="set_led_state", params=[led_state]]
1081+
request = [0, 1, "set_led_state", [led_state]]
1082+
packed_req = msgpack.packb(request)
1083+
1084+
# 4. Send the request
1085+
try:
1086+
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as client:
1087+
client.connect(SOCKET_PATH)
1088+
client.sendall(packed_req)
1089+
1090+
# 5. Receive the response
1091+
response_data = client.recv(1024)
1092+
response = msgpack.unpackb(response_data)
1093+
1094+
# Response Format: [type=1 (Response), msgid=1, error=None, result=None]
1095+
print(f"Router Response: {response}")
1096+
1097+
except Exception as e:
1098+
print(f"Connection failed: {e}")
1099+
```
1100+
1101+
**Running the Example**
1102+
1103+
You can now test the connection by running the script from the terminal and passing `1` (ON) or `0` (OFF):
1104+
1105+
```bash
1106+
python3 msgpack_test.py 1 # to turn on the LED
1107+
# or
1108+
python3 msgpack_test.py 0 # to turn off the LED
1109+
```
1110+
![Custom Python to Router example](assets/custom-python-rpc.png)
1111+
1112+
9871113
### SPI
9881114

9891115
The UNO Q supports SPI communication, which allows data transmission between the board and other SPI-compatible devices.

0 commit comments

Comments
 (0)