Summary
--set over TCP is silently lost against an ESP32-S3 node on Linux, with 2.7.11 — the
release that contains the #958 fix. #957 concluded the loss was Windows-only ("Same
commands work on Linux"); on this hardware it is not.
Two nodes, two client machines, verified by reading the value back over the other
transport rather than the one the write took.
Setup
One of the nodes has both USB serial and WiFi up, so the same device can be written one
way and read the other. Seeed XIAO ESP32S3, firmware 2.8.0.74578a8 (a build of
develop; I have not tried a release build). Clients: Debian 12 and CachyOS, both with
meshtastic 2.7.11 from PyPI.
| write |
read back over |
result |
--host <ip> --set display.screen_on_secs N |
serial |
unchanged, 6 of 6 |
--host <ip> --set … --wait-to-disconnect 8 |
serial |
applied |
--port /dev/ttyACM0 --set … |
TCP |
applied |
A second unit of the same model behaves the same over TCP.
The CLI reports success either way: it prints Set display.screen_on_secs to N,
Writing modified preferences to device and Writing display configuration to device
even when nothing is written. A BrokenPipeError sometimes precedes that and sometimes
does not, so it is not a usable signal — and it also shows up on successful reads, which
is #962.
What differs between the two transports
--debug shows both building the same packet — ADMIN_APP to the node's own number,
pki_encrypted: true, want_ack: true — both obtaining a sessionkey, and both logging
Wrote: display.
The difference is what comes back. Over serial:
ROUTING_APP … request_id: … routing { errorReason: NONE }
Over TCP nothing comes back; the CLI sends disconnect: true and closes first. The
device logs, at that moment:
[E][NetworkClient.cpp:435] write(): fail on fd 52, errno: 104, "Connection reset by peer"
That is the node failing to send the ack above.
Why the #958 fix does not cover this
Raising GRACEFUL_CLOSE_TIMEOUT from 0.25 to 5.0 changes nothing — two further writes,
both lost. _wait_for_reader_exit() returns as soon as the reader exits, and the
disconnect: true sent just before close causes exactly that. The half-close does
happen; the wait is simply over long before the device has applied the admin packet.
One thing worth separating while you are in there: #957 attributes the loss to Winsock
discarding received-but-unread data on RST. The receive buffer that matters here is the
device's, not the client's — the RST arrives at the ESP32. That would explain why a
client-side platform distinction does not hold up.
Ruled out
- A second client competing for the node's TCP server — same result with our
once-a-minute telemetry poller stopped.
- The field or the value — several fields, plain integers, same outcome.
- One bad node — two units, and two different Linux clients.
Workaround
--wait-to-disconnect 8 makes the write land every time. Useful for anyone scripting
against a node over the network in the meantime.
Summary
--setover TCP is silently lost against an ESP32-S3 node on Linux, with 2.7.11 — therelease that contains the #958 fix. #957 concluded the loss was Windows-only ("Same
commands work on Linux"); on this hardware it is not.
Two nodes, two client machines, verified by reading the value back over the other
transport rather than the one the write took.
Setup
One of the nodes has both USB serial and WiFi up, so the same device can be written one
way and read the other. Seeed XIAO ESP32S3, firmware 2.8.0.74578a8 (a build of
develop; I have not tried a release build). Clients: Debian 12 and CachyOS, both withmeshtastic 2.7.11 from PyPI.
--host <ip> --set display.screen_on_secs N--host <ip> --set … --wait-to-disconnect 8--port /dev/ttyACM0 --set …A second unit of the same model behaves the same over TCP.
The CLI reports success either way: it prints
Set display.screen_on_secs to N,Writing modified preferences to deviceandWriting display configuration to deviceeven when nothing is written. A
BrokenPipeErrorsometimes precedes that and sometimesdoes not, so it is not a usable signal — and it also shows up on successful reads, which
is #962.
What differs between the two transports
--debugshows both building the same packet —ADMIN_APPto the node's own number,pki_encrypted: true,want_ack: true— both obtaining asessionkey, and both loggingWrote: display.The difference is what comes back. Over serial:
Over TCP nothing comes back; the CLI sends
disconnect: trueand closes first. Thedevice logs, at that moment:
That is the node failing to send the ack above.
Why the #958 fix does not cover this
Raising
GRACEFUL_CLOSE_TIMEOUTfrom 0.25 to 5.0 changes nothing — two further writes,both lost.
_wait_for_reader_exit()returns as soon as the reader exits, and thedisconnect: truesent just before close causes exactly that. The half-close doeshappen; the wait is simply over long before the device has applied the admin packet.
One thing worth separating while you are in there: #957 attributes the loss to Winsock
discarding received-but-unread data on RST. The receive buffer that matters here is the
device's, not the client's — the RST arrives at the ESP32. That would explain why a
client-side platform distinction does not hold up.
Ruled out
once-a-minute telemetry poller stopped.
Workaround
--wait-to-disconnect 8makes the write land every time. Useful for anyone scriptingagainst a node over the network in the meantime.