Skip to content

Commit da380de

Browse files
author
NoahAndrews
committed
Once a heartbeat has been started, always send while the bus is present
If the application is not responding, we should start sending out a disabled heartbeat, instead of ceasing to send anything
1 parent 6f692b8 commit da380de

File tree

1 file changed

+45
-25
lines changed

1 file changed

+45
-25
lines changed

src/canWrapper.cc

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <thread>
1313
#include <chrono>
1414
#include <map>
15+
#include <array>
1516
#include <vector>
1617
#include <set>
1718
#include <exception>
@@ -33,10 +34,15 @@ bool halInitialized = false;
3334
uint32_t m_notifier;
3435

3536
std::mutex canDevicesMtx;
37+
// These values should only be accessed while holding canDevicesMtx
3638
std::map<std::string, std::shared_ptr<rev::usb::CANDevice>> canDeviceMap;
3739

3840
std::mutex watchdogMtx;
41+
// These values should only be accessed while holding watchdogMtx
3942
std::vector<std::string> heartbeatsRunning;
43+
bool heartbeatTimeoutExpired = false; // Should only be changed in heartbeatsWatchdog()
44+
std::map<std::string, std::array<uint8_t, 1>> revCommonHeartbeatMap;
45+
std::map<std::string, std::array<uint8_t, 8>> sparkHeartbeatMap;
4046
auto latestHeartbeatAck = std::chrono::steady_clock::now();
4147

4248
// Only call when holding canDevicesMtx
@@ -667,12 +673,29 @@ void heartbeatsWatchdog() {
667673

668674
auto now = std::chrono::steady_clock::now();
669675
std::chrono::duration<double> elapsed_seconds = now-latestHeartbeatAck;
670-
if (elapsed_seconds.count() > 1) {
671-
uint8_t sparkMaxHeartbeat[] = {0, 0, 0, 0, 0, 0, 0, 0};
672-
uint8_t revCommonHeartbeat[] = {0};
676+
if (elapsed_seconds.count() >= 1 && !heartbeatTimeoutExpired) {
677+
// The heartbeat timeout just expired
678+
heartbeatTimeoutExpired = true;
679+
uint8_t disabledSparkHeartbeat[] = {0, 0, 0, 0, 0, 0, 0, 0};
680+
uint8_t disabledRevCommonHeartbeat[] = {0};
673681
for(int i = 0; i < heartbeatsRunning.size(); i++) {
674-
_sendCANMessage(heartbeatsRunning[i], SPARK_HEARTBEAT_ID, sparkMaxHeartbeat, 8, -1);
675-
_sendCANMessage(heartbeatsRunning[i], REV_COMMON_HEARTBEAT_ID, revCommonHeartbeat, 1, -1);
682+
if (sparkHeartbeatMap.contains(heartbeatsRunning[i])) {
683+
_sendCANMessage(heartbeatsRunning[i], SPARK_HEARTBEAT_ID, disabledSparkHeartbeat, 8, HEARTBEAT_PERIOD_MS);
684+
}
685+
if (revCommonHeartbeatMap.contains(heartbeatsRunning[i])) {
686+
_sendCANMessage(heartbeatsRunning[i], REV_COMMON_HEARTBEAT_ID, disabledRevCommonHeartbeat, 1, HEARTBEAT_PERIOD_MS);
687+
}
688+
}
689+
} else if (elapsed_seconds.count() < 1 && heartbeatTimeoutExpired) {
690+
// The heartbeat timeout is newly un-expired
691+
heartbeatTimeoutExpired = false;
692+
for(int i = 0; i < heartbeatsRunning.size(); i++) {
693+
if (auto heartbeatEntry = sparkHeartbeatMap.find(heartbeatsRunning[i]); heartbeatEntry != sparkHeartbeatMap.end()) {
694+
_sendCANMessage(heartbeatsRunning[i], SPARK_HEARTBEAT_ID, heartbeatEntry->second.data(), 8, HEARTBEAT_PERIOD_MS);
695+
}
696+
if (auto heartbeatEntry = revCommonHeartbeatMap.find(heartbeatsRunning[i]); heartbeatEntry != revCommonHeartbeatMap.end()) {
697+
_sendCANMessage(heartbeatsRunning[i], REV_COMMON_HEARTBEAT_ID, heartbeatEntry->second.data(), 1, HEARTBEAT_PERIOD_MS);
698+
}
676699
}
677700
}
678701
}
@@ -695,10 +718,11 @@ void startRevCommonHeartbeat(const Napi::CallbackInfo& info) {
695718
if (deviceIterator == canDeviceMap.end()) return;
696719
}
697720

698-
uint8_t payload[] = {1};
699-
_sendCANMessage(descriptor, REV_COMMON_HEARTBEAT_ID, payload, 1, HEARTBEAT_PERIOD_MS);
721+
std::array<uint8_t, 1> payload = {1};
722+
_sendCANMessage(descriptor, REV_COMMON_HEARTBEAT_ID, payload.data(), 1, HEARTBEAT_PERIOD_MS);
700723

701724
std::scoped_lock lock{watchdogMtx};
725+
revCommonHeartbeatMap[descriptor] = payload;
702726

703727
if (heartbeatsRunning.size() == 0) {
704728
heartbeatsRunning.push_back(descriptor);
@@ -721,7 +745,7 @@ void setSparkMaxHeartbeatData(const Napi::CallbackInfo& info) {
721745
std::string descriptor = info[0].As<Napi::String>().Utf8Value();
722746
Napi::Array dataParam = info[1].As<Napi::Array>();
723747

724-
uint8_t heartbeat[] = {0, 0, 0, 0, 0, 0, 0, 0};
748+
std::array<uint8_t, 8> heartbeat = {0, 0, 0, 0, 0, 0, 0, 0};
725749

726750
{
727751
std::scoped_lock lock{canDevicesMtx};
@@ -730,32 +754,28 @@ void setSparkMaxHeartbeatData(const Napi::CallbackInfo& info) {
730754
}
731755

732756
// Clear the scheduled heartbeat that has outdated data so that the updated one gets sent out immediately
733-
_sendCANMessage(descriptor, SPARK_HEARTBEAT_ID, heartbeat, 8, -1);
757+
_sendCANMessage(descriptor, SPARK_HEARTBEAT_ID, heartbeat.data(), 8, -1);
734758

735759
int sum = 0;
736760
for (uint32_t i = 0; i < dataParam.Length(); i++) {
737761
heartbeat[i] = dataParam.Get(i).As<Napi::Number>().Uint32Value();
738762
sum+= heartbeat[i];
739763
}
740764

741-
if (sum == 0) {
742-
_sendCANMessage(descriptor, SPARK_HEARTBEAT_ID, heartbeat, 8, -1);
743-
}
744-
else {
745-
_sendCANMessage(descriptor, SPARK_HEARTBEAT_ID, heartbeat, 8, HEARTBEAT_PERIOD_MS);
765+
_sendCANMessage(descriptor, SPARK_HEARTBEAT_ID, heartbeat.data(), 8, HEARTBEAT_PERIOD_MS);
746766

747-
std::scoped_lock lock{watchdogMtx};
767+
std::scoped_lock lock{watchdogMtx};
768+
sparkHeartbeatMap[descriptor] = heartbeat;
748769

749-
if (heartbeatsRunning.size() == 0) {
750-
heartbeatsRunning.push_back(descriptor);
751-
latestHeartbeatAck = std::chrono::steady_clock::now();
752-
std::thread hb(heartbeatsWatchdog);
753-
hb.detach();
754-
} else {
755-
for(int i = 0; i < heartbeatsRunning.size(); i++) {
756-
if (heartbeatsRunning[i].compare(descriptor) == 0) return;
757-
}
758-
heartbeatsRunning.push_back(descriptor);
770+
if (heartbeatsRunning.size() == 0) {
771+
heartbeatsRunning.push_back(descriptor);
772+
latestHeartbeatAck = std::chrono::steady_clock::now();
773+
std::thread hb(heartbeatsWatchdog);
774+
hb.detach();
775+
} else {
776+
for(int i = 0; i < heartbeatsRunning.size(); i++) {
777+
if (heartbeatsRunning[i].compare(descriptor) == 0) return;
759778
}
779+
heartbeatsRunning.push_back(descriptor);
760780
}
761781
}

0 commit comments

Comments
 (0)