Skip to content

Add Rust telemetry backend (bevo-rust) for Angelique#9

Draft
Copilot wants to merge 1 commit into
mainfrom
copilot/angelique-rust
Draft

Add Rust telemetry backend (bevo-rust) for Angelique#9
Copilot wants to merge 1 commit into
mainfrom
copilot/angelique-rust

Conversation

Copy link
Copy Markdown

Copilot AI commented Mar 29, 2026

Python's GIL prevents true concurrency in the existing telemd/ backend, making it unsuitable for high-frequency CAN telemetry. This replaces it with a Rust implementation using the lhre-2026 daemon-based architecture.

Structure

Two binaries under bevo-rust/, communicating over a Unix socket:

  • publishd — connects to MQTT as BEVO-Angelique, optionally syncs packet_id from server via client-connections/server-communication handshake, writes startup semaphore, then forwards length-prefixed protobuf frames from cand to the angelique topic
  • cand — waits for semaphore, reads CAN frames from can0 (or UDP mock via CAND_USE_MOCK=1), decodes into AngeliqueSensorData protobuf at configurable rate (default 100 Hz), broadcasts over Unix socket to all connected clients

CAN Decoding

Field mappings are ported 1:1 from telemd/core/field_mappings.py as a hardcoded match on CAN ID — no JSON config needed. The CellAggregator mirrors Python's CellDataAggregator, accumulating voltage (0x370–0x392) and temperature (0x470–0x486) frames and computing running averages:

// 0x370–0x392: cell voltages → diagnostics.cells_v + pack.avg_cell_v
if (0x370..=0x392).contains(&can_id) {
    if let Some((all_v, avg_v)) = cell_agg.process_voltage(can_id, payload) {
        data.diagnostics.get_or_insert_with(Default::default).cells_v = all_v;
        data.pack.get_or_insert_with(Default::default).avg_cell_v = avg_v;
    }
    return;
}

Proto

bevo-rust/proto/template.proto is a copy of telemd/protobuf/template.proto with package angelique; added for correct prost codegen. Compiled at build time via prost-build.

Concurrency model

Each daemon runs three threads: CAN reader → frame decoder/proto updater (shared Mutex<AngeliqueSensorData>) → IPC broadcaster. The outbound MQTT queue drops frames on overflow rather than back-pressuring the encoder.

Environment variables

Variable Default Description
CAND_USE_MOCK 0 Use UDP mock socket instead of can0
CAND_CAN_INTERFACE can0 CAN interface name
CAND_PUBLISH_HZ 100 Encode/broadcast rate
PUBLISHD_MQTT_HOST 192.168.1.109 Broker address
PUBLISHD_MQTT_PORT 1883 Broker port
PUBLISHD_REQUIRE_SERVER_PACKET_ID 0 Block until server returns packet_id

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants