-
-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Describe the request
Please consider adding buffer config support and exposing it via the gRPC API:
message MonitorPortOpenRequest {
…
MonitorPortConfiguration portConfiguration = 4;
MonitorBufferConfig bufferConfig = 5; // NEW!
}
message MonitorBufferConfig {
uint32 highWaterMarkBytes = 1;
uint32 flushIntervalMs = 2;
bool lineBuffering = 3;
}
Add an optional buffering configuration to the Monitor RPC, for example:
highWaterMarkBytes
(e.g. 64)flushIntervalMs
(e.g. 16 ms)lineBuffering
(flush on \n)
With these, the daemon could accumulate data and send meaningful chunks instead of single characters. Of course, buffering can be done by the gRPC client with Node.js, for example, but it forces every single client of the Arduino CLI to implement this feature, and every implementation will be different. Perhaps, it would be better to support at this level.
Describe the current behavior
When using the Arduino CLI daemon’s Monitor RPC over gRPC, almost every single byte from the serial port is sent in its own RPC frame. This forces downstream clients (both browser-based UIs and Node.js bridges) to process one-character chunks, which is highly inefficient.
Assuming the following sketch to be compiled and uploaded to the board:
unsigned long previousMillis;
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
while (Serial.available() > 0) {
Serial.write(Serial.read());
delay(10);
}
}
else if (millis() - previousMillis >= 1000) {
previousMillis = millis();
Serial.println("hallo");
}
}
Open the Arduino CLI in daemon mode:
./arduino-cli version
arduino-cli Version: git-snapshot Commit: c41f5df7 Date: 2025-08-05T13:12:43Z
./arduino-cli daemon
Daemon is now listening on 127.0.0.1:50051
{"IP":"127.0.0.1","Port":"50051"}
Open a new shell inside the arduino-cli
repository, and execute the following commands:
Generate the .proto
files:
buf export . -o ./tmp/out
Create:
grpcurl \
-plaintext \
-import-path ./tmp/out \
-proto cc/arduino/cli/commands/v1/commands.proto \
127.0.0.1:50051 \
cc.arduino.cli.commands.v1.ArduinoCoreService.Create
{
"instance": {
"id": 1
}
}
Init:
grpcurl \
-plaintext \
-import-path ./tmp/out \
-proto cc/arduino/cli/commands/v1/commands.proto \
-d '{"instance": {"id": 1}}' \
127.0.0.1:50051 \
cc.arduino.cli.commands.v1.ArduinoCoreService.Init
Monitor:
grpcurl \
-plaintext \
-import-path ./tmp/out \
-proto cc/arduino/cli/commands/v1/commands.proto \
-d @ \
127.0.0.1:50051 \
cc.arduino.cli.commands.v1.ArduinoCoreService.Monitor
To open the monitor, paste the following and press Enter:
{
"openRequest": {
"instance": { "id": 1 },
"fqbn": "esp32:esp32:esp32da",
"port": {
"address": "/dev/cu.usbserial-0001",
"protocol": "serial"
},
"portConfiguration": {
"settings": [
{ "settingId": "baudrate", "value": "9600" }
]
}
}
}
Received monitor rx_data responses:
{
"success": true
}
{
"rxData": "aAIWUiCk0gzBLBWBSUEBJbFBI/g="
}
{
"rxData": "aGE="
}
{
"rxData": "bA=="
}
{
"rxData": "bA=="
}
{
"rxData": "bw=="
}
{
"rxData": "DQ=="
}
{
"rxData": "Cg=="
}
{
"rxData": "aA=="
}
{
"rxData": "YQ=="
}
{
"rxData": "bA=="
}
{
"rxData": "bA=="
}
{
"rxData": "bw=="
}
{
"rxData": "DQ=="
}
{
"rxData": "Cg=="
}
{
"rxData": "aGFsbA=="
}
{
"rxData": "bw0="
}
{
"rxData": "Cg=="
}
{
"rxData": "aA=="
}
{
"rxData": "YQ=="
}
{
"rxData": "bA=="
}
{
"rxData": "bA=="
}
{
"rxData": "bw=="
}
{
"rxData": "DQ=="
}
{
"rxData": "Cg=="
}
Decoded rx_data:
Raw Frame | Decoded Content |
---|---|
{ "success": true } |
|
{ "rxData": "aAIWUiCk0gzBLBWBSUEBJbFBI/g=" } |
h\x02\x16R \xa4\xd2\x0c\xc1,\x15\x81IA\x01%\xb1A#\xf8 |
{ "rxData": "aGE=" } |
ha |
{ "rxData": "bA==" } |
l |
{ "rxData": "bA==" } |
l |
{ "rxData": "bw==" } |
o |
{ "rxData": "DQ==" } |
\r |
{ "rxData": "Cg==" } |
\n |
{ "rxData": "aA==" } |
h |
{ "rxData": "YQ==" } |
a |
{ "rxData": "bA==" } |
l |
{ "rxData": "bA==" } |
l |
{ "rxData": "bw==" } |
o |
{ "rxData": "DQ==" } |
\r |
{ "rxData": "Cg==" } |
\n |
{ "rxData": "aGFsbA==" } |
hall |
{ "rxData": "bw0=" } |
o\r |
{ "rxData": "Cg==" } |
\n |
{ "rxData": "aA==" } |
h |
{ "rxData": "YQ==" } |
a |
{ "rxData": "bA==" } |
l |
{ "rxData": "bA==" } |
l |
{ "rxData": "bw==" } |
o |
{ "rxData": "DQ==" } |
\r |
{ "rxData": "Cg==" } |
\n |
Sending a message to the monitor from a client is even worse. The Arduino IDE can process a large amount of data transmitted from the board (such as Teensy) via the CLI, but even within the IDE, message sending is done character by character. Super slow output. Imagine when the IDE could support sending multiline text to the monitor:
Screen.Recording.2025-08-08.at.10.17.07.mov
This is a complete rewrite of the monitor with a different client than the Arduino IDE uses, but the send message is poor:
Screen.Recording.2025-08-08.at.10.22.54.mov
'github.com/arduino/pluggable-monitor-protocol-handler' version
0.9.2
Additional context
No response
Issue checklist
- I searched for previous requests in the issue tracker
- I verified the feature was still missing when using the latest version
- My request contains all necessary details