STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
HeartbeatRouter.cpp
Go to the documentation of this file.
2
3#include <chrono>
4#include <iostream>
5
7
8namespace fsw {
9namespace routing {
10
14
16 const daq::PacketHeader& header, const daq::BoardHeartbeatPacket& heartbeat,
17 uint8_t board_type_wire, uint64_t receive_ts_ns, int elodin_board_id_if_known) {
18 uint8_t logical_id = heartbeat.board_id;
19 if (elodin_board_id_if_known >= 0 && elodin_board_id_if_known <= 255) {
20 logical_id = static_cast<uint8_t>(elodin_board_id_if_known);
21 }
22 const auto now = std::chrono::steady_clock::now();
23
24 // ── Detect reconnect / Setup re-entry ────────────────────────────────────
26 auto& state = board_states_[logical_id];
27
28 if (!state.seen_before) {
29 state.seen_before = true;
30 std::cout << "[HeartbeatRouter] New board seen: id=" << (int)logical_id
31 << " type_wire=" << (int)board_type_wire;
32 if (logical_id != heartbeat.board_id) {
33 std::cout << " (wire board_id=" << (int)heartbeat.board_id << " -> config board_id)";
34 }
35 std::cout << std::endl;
36 } else {
37 auto gap = std::chrono::duration_cast<std::chrono::milliseconds>(now - state.last_seen);
38 if (gap >= RECONNECT_THRESHOLD) {
40 std::cout << "[HeartbeatRouter] Board " << (int)logical_id << " reconnected after "
41 << gap.count() << "ms" << std::endl;
42 } else if (heartbeat.board_state == daq::BoardState::SETUP &&
43 state.last_board_state != daq::BoardState::SETUP) {
45 std::cout << "[HeartbeatRouter] Board " << (int)logical_id << " re-entered SETUP state"
46 << std::endl;
47 }
48 }
49
50 state.last_seen = now;
51 state.last_board_state = heartbeat.board_state;
52
53 // ── Publish to Elodin ─────────────────────────────────────────────────────
54 if (elodin_client_.is_connected()) {
56 msg.setField<0>(receive_ts_ns);
57 msg.setField<1>(logical_id);
58 msg.setField<2>(board_type_wire);
59 msg.setField<3>(static_cast<uint8_t>(heartbeat.engine_state));
60 msg.setField<4>(static_cast<uint8_t>(heartbeat.board_state));
61 msg.setField<5>(header.timestamp);
62
63 std::array<uint8_t, 2> pkt_id = {0x10, logical_id};
64 elodin_client_.publish(pkt_id, msg);
65 }
66
67 return event;
68}
69
70} // namespace routing
71} // namespace fsw
Standalone Elodin database client.
static constexpr auto RECONNECT_THRESHOLD
std::map< uint8_t, PerBoardState > board_states_
BoardEvent process_heartbeat(const daq::PacketHeader &header, const daq::BoardHeartbeatPacket &heartbeat, uint8_t board_type_wire, uint64_t receive_ts_ns, int elodin_board_id_if_known=-1)
Process one BOARD_HEARTBEAT and publish to Elodin.
elodin::ElodinClient & elodin_client_
HeartbeatRouter(elodin::ElodinClient &elodin_client)
static ActuatorControllerState state
Definition main.cpp:57
CommsMessage< uint64_t, uint8_t, uint8_t, uint8_t, uint8_t, uint32_t > BoardHeartbeatElodinMessage
Board heartbeat status record for Elodin.
Motorized ball valve position: raw ADC counts -> % open.
void setField(ValueType &&value)