Skip to content

Commit ae33670

Browse files
committed
CAN decode fallback, signed ID support
1 parent e337d62 commit ae33670

2 files changed

Lines changed: 62 additions & 5 deletions

File tree

pecan/src/utils/canProcessor.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,5 +462,37 @@ describe('CAN Processor Unit Tests', () => {
462462
expect(chargerCmd?.messageName).toBe('Charger_Command');
463463
expect(chargerSts?.messageName).toBe('Charger_Status');
464464
});
465+
466+
it('should handle IDs that already have the EFF bit set', () => {
467+
const CHARGER_CMD_DBC_ID = 2550588916; // 0x9806E5F4
468+
const data = [0x68, 0x10, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00];
469+
const result = decodeCanMessage(can, CHARGER_CMD_DBC_ID, data, 7000);
470+
expect(result).not.toBeNull();
471+
expect(result?.messageName).toBe('Charger_Command');
472+
});
473+
474+
it('should handle negative IDs (if bridge sends signed uint32)', () => {
475+
const CHARGER_CMD_SIGNED_ID = -1744378380; // 0x9806E5F4 as signed 32-bit
476+
const data = [0x68, 0x10, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00];
477+
const result = decodeCanMessage(can, CHARGER_CMD_SIGNED_ID, data, 8000);
478+
479+
// With the new fallback, this should now be decoded correctly
480+
expect(result).not.toBeNull();
481+
expect(result?.messageName).toBe('Charger_Command');
482+
});
483+
484+
it('should handle small extended IDs using fallback', () => {
485+
// If we have an extended message with ID 0x123 in DBC,
486+
// but we send it as standard ID 0x123.
487+
// (Note: example.dbc doesn't have this, but we can simulate the logic)
488+
// For now, testing that EFF bit toggling works for known IDs.
489+
const CHARGER_CMD_WITHOUT_EFF = 0x1806E5F4; // Raw arbitration ID
490+
const data = [0x68, 0x10, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00];
491+
const result = decodeCanMessage(can, CHARGER_CMD_WITHOUT_EFF, data, 9000);
492+
493+
expect(result).not.toBeNull();
494+
expect(result?.messageName).toBe('Charger_Command');
495+
expect(result?.canId).toBe(2550588916); // Should return the DBC ID
496+
});
465497
});
466498
});

pecan/src/utils/canProcessor.ts

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ const CAN_EFF_FLAG = 0x80000000;
1515
const CAN_STD_MAX = 0x7FF;
1616

1717
function toDbcId(rawCanId: number): number {
18-
return rawCanId > CAN_STD_MAX ? (rawCanId | CAN_EFF_FLAG) >>> 0 : rawCanId;
18+
const unsignedId = rawCanId >>> 0;
19+
return unsignedId > CAN_STD_MAX ? (unsignedId | CAN_EFF_FLAG) >>> 0 : unsignedId;
1920
}
2021

2122
export function formatCanId(canId: number): string {
22-
const raw = canId > CAN_STD_MAX ? canId & ~CAN_EFF_FLAG : canId;
23+
const unsignedId = canId >>> 0;
24+
const raw = unsignedId > CAN_STD_MAX ? unsignedId & ~CAN_EFF_FLAG : unsignedId;
2325
if (raw > CAN_STD_MAX) {
2426
return `0x${raw.toString(16).toUpperCase().padStart(8, "0")}`;
2527
}
@@ -393,9 +395,32 @@ export function decodeCanMessage(
393395
time: number
394396
): DecodedMessage | null {
395397
try {
396-
const dbcId = toDbcId(canId);
397-
const frame = canInstance.createFrame(dbcId, messageData);
398-
const decoded = canInstance.decode(frame);
398+
let dbcId = toDbcId(canId);
399+
let frame = canInstance.createFrame(dbcId, messageData);
400+
let decoded = canInstance.decode(frame);
401+
402+
// Fallback: If decoding fails, try toggling the EFF bit (bit 31)
403+
// This handles cases where a small ID is actually an extended frame
404+
// or the bridge sends a raw arbitration ID without the flag.
405+
if (!decoded) {
406+
const fallbackId = (dbcId & 0x80000000) ? (dbcId & 0x7FFFFFFF) : (dbcId | 0x80000000);
407+
try {
408+
const fallbackFrame = canInstance.createFrame(fallbackId, messageData);
409+
const fallbackDecoded = canInstance.decode(fallbackFrame);
410+
if (fallbackDecoded) {
411+
console.log(`[DBC Fallback] Decoded message ${canId} (0x${canId.toString(16)}) using fallback ID ${fallbackId} (0x${fallbackId.toString(16)})`);
412+
dbcId = fallbackId;
413+
frame = fallbackFrame;
414+
decoded = fallbackDecoded;
415+
}
416+
} catch (e) {
417+
// Silently fail fallback attempt
418+
}
419+
}
420+
421+
if (canId === 0x18FF50E5 || canId > 0x7FF || (decoded === null && canId !== 1999)) {
422+
console.debug(`[DBC Debug] rawId=${canId} (0x${canId.toString(16)}), dbcId=${dbcId} (0x${dbcId.toString(16)}), decodedName=${decoded?.name ?? 'null'}`);
423+
}
399424

400425
const rawDataStr = messageData
401426
.map((b) => b.toString(16).padStart(2, "0").toUpperCase())

0 commit comments

Comments
 (0)