firmware: discard partial RS485 echoes

This commit is contained in:
2026-07-17 02:47:13 -06:00
parent 75845a18e3
commit d5578ce796
3 changed files with 5 additions and 1 deletions
+1
View File
@@ -5,6 +5,7 @@
- Added standalone XIAO ESP32-C6 BNO086/MAX-M10S sensor-node firmware and a versioned RS485 telemetry contract without changing Cargo `/api/v1` or JBD/NimBLE behavior. - Added standalone XIAO ESP32-C6 BNO086/MAX-M10S sensor-node firmware and a versioned RS485 telemetry contract without changing Cargo `/api/v1` or JBD/NimBLE behavior.
- Added XIAO-side persistent level calibration with stability checking and RS485 start/clear commands; no dashboard behavior changed. - Added XIAO-side persistent level calibration with stability checking and RS485 start/clear commands; no dashboard behavior changed.
- Prevented echoed or oversized RS485 frames from starving the XIAO sensor loop. - Prevented echoed or oversized RS485 frames from starving the XIAO sensor loop.
- Silently discard malformed partial RS485 echoes instead of emitting recursive `invalid_json` responses.
## Unreleased ## Unreleased
@@ -89,7 +89,9 @@ void pollRs485Commands(HardwareSerial& serial, const ImuState& imu) {
StaticJsonDocument<192> request; StaticJsonDocument<192> request;
DeserializationError error = deserializeJson(request, commandBuffer); DeserializationError error = deserializeJson(request, commandBuffer);
commandBuffer = ""; commandBuffer = "";
if (error) { publishCalibrationResult(serial, "invalid_json"); continue; } // Partial self-echoes and line noise are not commands. Dropping them
// silently avoids turning one bad fragment into a response/echo loop.
if (error) continue;
String type = request["type"] | ""; String type = request["type"] | "";
// Some RS485 boards echo transmitted frames into RX. Ignore our own output. // Some RS485 boards echo transmitted frames into RX. Ignore our own output.
if (type == "sensor_status" || type == "calibration_response") continue; if (type == "sensor_status" || type == "calibration_response") continue;
+1
View File
@@ -61,6 +61,7 @@ def test_rs485_echo_cannot_starve_sensor_loop():
assert "bytesRemaining" in transport assert "bytesRemaining" in transport
assert "discardCommandUntilNewline" in transport assert "discardCommandUntilNewline" in transport
assert 'type == "sensor_status"' in transport assert 'type == "sensor_status"' in transport
assert 'publishCalibrationResult(serial, "invalid_json")' not in transport
def test_node_does_not_take_cargo_or_ble_authority(): def test_node_does_not_take_cargo_or_ble_authority():
combined = "\n".join(p.read_text() for p in NODE.glob("*.*")) combined = "\n".join(p.read_text() for p in NODE.glob("*.*"))