diff --git a/lib/binding.ts b/lib/binding.ts index 56de42c..5a710f2 100644 --- a/lib/binding.ts +++ b/lib/binding.ts @@ -74,6 +74,10 @@ export class CanBridge { startRevCommonHeartbeat: (descriptor: string) => void; stopHeartbeats: (descriptor: string, sendDisabledHeartbeatsFirst: boolean) => void; ackHeartbeats: () => void; + /** + * @return Object that maps arbitration IDs to the last-received message with that ID + */ + getLatestMessageOfEveryReceivedArbId: (descriptor: string, maxAgeMs: number) => Record; constructor() { try { @@ -103,30 +107,9 @@ export class CanBridge { this.startRevCommonHeartbeat = addon.startRevCommonHeartbeat; this.ackHeartbeats = addon.ackHeartbeats; this.stopHeartbeats = addon.stopHeartbeats; + this.getLatestMessageOfEveryReceivedArbId = addon.getLatestMessageOfEveryReceivedArbId; } catch (e: any) { throw new CanBridgeInitializationError(e); } } } - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/download-CanBridge.mjs b/scripts/download-CanBridge.mjs index c26898a..7530a91 100644 --- a/scripts/download-CanBridge.mjs +++ b/scripts/download-CanBridge.mjs @@ -3,7 +3,7 @@ import * as path from "path"; import axios from 'axios'; import AdmZip from 'adm-zip'; -const canBridgeTag = "v2.5.1"; +const canBridgeTag = "v2.6.0"; const canBridgeReleaseAssetUrlPrefix = `https://github.com/REVrobotics/CANBridge/releases/download/${canBridgeTag}`; const externalCompileTimeDepsPath = 'externalCompileTimeDeps'; diff --git a/src/addon.cc b/src/addon.cc index 10bc0bf..296db51 100644 --- a/src/addon.cc +++ b/src/addon.cc @@ -50,6 +50,8 @@ Napi::Object Init(Napi::Env env, Napi::Object exports) { Napi::Function::New(env, stopHeartbeats)); exports.Set(Napi::String::New(env, "ackHeartbeats"), Napi::Function::New(env, ackHeartbeats)); + exports.Set(Napi::String::New(env, "getLatestMessageOfEveryReceivedArbId"), + Napi::Function::New(env, getLatestMessageOfEveryReceivedArbId)); return exports; } diff --git a/src/canWrapper.cc b/src/canWrapper.cc index c8fb1ae..6209652 100644 --- a/src/canWrapper.cc +++ b/src/canWrapper.cc @@ -724,6 +724,60 @@ Napi::Array getImageElements(const Napi::CallbackInfo& info) { return elements; } +Napi::Object getLatestMessageOfEveryReceivedArbId(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + std::string descriptor = info[0].As().Utf8Value(); + uint32_t maxAgeMs = info[1].As().Uint32Value(); + + std::shared_ptr device; + + { // This block exists to define how long we hold canDevicesMtx + std::scoped_lock lock{canDevicesMtx}; + auto deviceIterator = canDeviceMap.find(descriptor); + if (deviceIterator == canDeviceMap.end()) { + if (devicesRegisteredToHal.find(descriptor) != devicesRegisteredToHal.end()) return receiveHalMessage(info); + Napi::Error::New(env, DEVICE_NOT_FOUND_ERROR).ThrowAsJavaScriptException(); + return Napi::Object::New(env); + } + device = deviceIterator->second; + } + + std::map> messages; + bool success = device->CopyReceivedMessagesMap(messages); + if (!success) { + Napi::Error::New(env, "Failed to copy the map of received messages").ThrowAsJavaScriptException(); + return Napi::Object::New(env); + } + + // TODO(Harper): Use HAL clock + const auto nowMs = std::chrono::time_point_cast(std::chrono::steady_clock::now()).time_since_epoch().count(); + + Napi::Object result = Napi::Object::New(env); + for (auto& m: messages) { + uint32_t arbId = m.first; + auto message = m.second; + uint32_t timestampMs = message->GetTimestampUs(); + + if (nowMs - timestampMs > maxAgeMs) { + continue; + } + + size_t messageSize = message->GetSize(); + const uint8_t* messageData = message->GetData(); + Napi::Array napiMessage = Napi::Array::New(env, messageSize); + for (int i = 0; i < messageSize; i++) { + napiMessage[i] = messageData[i]; + } + Napi::Object messageInfo = Napi::Object::New(env); + messageInfo.Set("messageID", message->GetMessageId()); + messageInfo.Set("timeStamp", timestampMs); + messageInfo.Set("data", napiMessage); + result.Set(arbId, messageInfo); + } + + return result; +} + void cleanupHeartbeatsRunning() { // Erase removed CAN buses from heartbeatsRunning std::scoped_lock lock{watchdogMtx, canDevicesMtx}; diff --git a/src/canWrapper.h b/src/canWrapper.h index 6629980..ced4460 100644 --- a/src/canWrapper.h +++ b/src/canWrapper.h @@ -28,4 +28,5 @@ void setSparkMaxHeartbeatData(const Napi::CallbackInfo& info); void startRevCommonHeartbeat(const Napi::CallbackInfo& info); void stopHeartbeats(const Napi::CallbackInfo& info); void ackHeartbeats(const Napi::CallbackInfo& info); +Napi::Object getLatestMessageOfEveryReceivedArbId(const Napi::CallbackInfo& info); #endif