Branch data Line data Source code
1 : : #include <cstring>
2 : :
3 : : #include "esp_log.h"
4 : :
5 : : #include "heartbeat_manager.hpp"
6 : :
7 : : static const char* TAG = "HeartbeatMgr";
8 : :
9 : 36 : HeartbeatManager::HeartbeatManager(ITxManager& tx_mgr, IPeerManager& peer_mgr, ITimerHAL& hal_timer)
10 : 36 : : tx_mgr_(tx_mgr)
11 : 36 : , peer_mgr_(peer_mgr)
12 : 36 : , hal_timer_(hal_timer)
13 : : {
14 : 36 : }
15 : :
16 : 17 : void HeartbeatManager::init(NodeId id, NodeType type, uint32_t interval_ms)
17 : : {
18 : 17 : my_id_ = id;
19 : 17 : my_type_ = type;
20 : 17 : interval_ms_ = interval_ms;
21 : 17 : is_initialized_ = true;
22 : 17 : }
23 : :
24 : 1 : void HeartbeatManager::deinit()
25 : : {
26 : 1 : is_initialized_ = false;
27 : 1 : }
28 : :
29 : 1 : void HeartbeatManager::set_interval_ms(uint32_t heartbeat_interval_ms)
30 : : {
31 : 1 : interval_ms_ = heartbeat_interval_ms;
32 : 1 : }
33 : :
34 : 14 : void HeartbeatManager::tick(int64_t now_ms)
35 : : {
36 [ + + + + : 14 : if (!is_initialized_ || my_type_ == ReservedTypes::HUB || interval_ms_ <= 0) {
+ - ]
37 : : return;
38 : : }
39 : :
40 [ + + ]: 11 : if (now_ms - last_heartbeat_ms_ >= interval_ms_) {
41 : 9 : send_heartbeat();
42 : 9 : last_heartbeat_ms_ = now_ms;
43 : : }
44 : : }
45 : :
46 : 1 : void HeartbeatManager::handle_response(const DecodedRxPacket& decoded)
47 : : {
48 : 1 : last_rssi_ = decoded.raw.rssi;
49 : 1 : ESP_LOGI(TAG, "Heartbeat response received from Hub (RSSI: %d dBm)", last_rssi_);
50 : 1 : }
51 : :
52 : 2 : void HeartbeatManager::handle_request(const DecodedRxPacket& decoded)
53 : : {
54 : 2 : const MessageHeader& header = decoded.header;
55 : :
56 : 2 : int64_t now_ms = get_time_ms();
57 : :
58 : 2 : peer_mgr_.update_last_seen(header.sender_node_id, now_ms);
59 : 2 : ESP_LOGI(TAG, "Heartbeat received from Node ID %d.", (int)header.sender_node_id);
60 : :
61 : 2 : DecodedTxPacket tx_packet{};
62 : 2 : memcpy(tx_packet.dest_mac, decoded.raw.src_mac, 6);
63 : :
64 : 2 : tx_packet.header.msg_type = MessageType::HEARTBEAT_RESPONSE;
65 : 2 : tx_packet.header.sender_node_id = my_id_;
66 : 2 : tx_packet.header.sender_type = my_type_;
67 : 2 : tx_packet.header.dest_node_id = header.sender_node_id;
68 : 2 : tx_packet.header.timestamp_ms = now_ms;
69 : :
70 : 2 : HeartbeatResponse resp{};
71 : 2 : resp.server_time_ms = now_ms;
72 : :
73 : : // Copy only the payload portion of HeartbeatResponse, skipping the MessageHeader
74 : : // which is already set separately in tx_packet.header above.
75 : : // &resp.server_time_ms points to the first field after the header.
76 : 2 : tx_packet.payload_len = sizeof(HeartbeatResponse) - sizeof(MessageHeader);
77 : 2 : memcpy(tx_packet.payload, &resp.server_time_ms, tx_packet.payload_len);
78 : :
79 : 2 : tx_mgr_.queue_packet(tx_packet);
80 : 2 : }
81 : :
82 : 13 : void HeartbeatManager::send_heartbeat()
83 : : {
84 : 13 : DecodedTxPacket tx_packet{};
85 [ + + ]: 13 : if (!peer_mgr_.find_mac(ReservedIds::HUB, tx_packet.dest_mac)) {
86 : 12 : memcpy(tx_packet.dest_mac, BROADCAST_MAC, 6);
87 : : }
88 : :
89 : 13 : int64_t now_ms = get_time_ms();
90 : :
91 : 13 : tx_packet.header.msg_type = MessageType::HEARTBEAT;
92 : 13 : tx_packet.header.sender_node_id = my_id_;
93 : 13 : tx_packet.header.sender_type = my_type_;
94 : 13 : tx_packet.header.dest_node_id = ReservedIds::HUB;
95 : 13 : tx_packet.header.timestamp_ms = now_ms;
96 : :
97 : 13 : HeartbeatMessage hb{};
98 : 13 : hb.uptime_ms = now_ms;
99 : 13 : hb.rssi = last_rssi_;
100 : : // battery_mv remains zero until hardware support is added
101 : :
102 : : // Copy only the payload portion of HeartbeatMessage, skipping MessageHeader.
103 : : // &hb.uptime_ms points to the first field after the header.
104 : 13 : tx_packet.payload_len = sizeof(HeartbeatMessage) - sizeof(MessageHeader);
105 : 13 : memcpy(tx_packet.payload, &hb.uptime_ms, tx_packet.payload_len);
106 : :
107 : 13 : tx_mgr_.queue_packet(tx_packet);
108 : 13 : }
109 : :
110 : : // ==========================================================================================
111 : : // Private methods
112 : : // ==========================================================================================
113 : :
114 : 15 : int64_t HeartbeatManager::get_time_ms() const
115 : : {
116 : 15 : return hal_timer_.get_time_us() / 1000;
117 : : }
|