Senaste råmeddelande, fel och ignoreringsorsaker. Pausa visning, rensa och kopiera logg. Uppdateras utan att störa inställningsfält eller tidtagning.
51 lines
2.2 KiB
JavaScript
51 lines
2.2 KiB
JavaScript
export const DIAGNOSTIC_ROLES = ["main", "split", "pit_entry", "pit_exit"];
|
|
export function createDecoderDiagnostics(now = Date.now) {
|
|
const channels = new Map();
|
|
function channel(role) {
|
|
const key = DIAGNOSTIC_ROLES.includes(role) ? role : "main";
|
|
if (!channels.has(key)) channels.set(key, { role: key, status: "disconnected", url: "", connectedAt: null, lastReceivedAt: null, frames: 0, messages: 0, passings: 0, handled: 0, ignored: 0, invalid: 0, parseErrors: 0, lastFrame: "", log: [] });
|
|
return channels.get(key);
|
|
}
|
|
function log(entry, reason, sample = "") {
|
|
entry.log.push({ at: now(), reason, sample: String(sample).slice(0, 512) });
|
|
if (entry.log.length > 50) entry.log.splice(0, entry.log.length - 50);
|
|
}
|
|
return {
|
|
socket(role, status, url = "") {
|
|
const entry = channel(role);
|
|
entry.status = status;
|
|
if (url) entry.url = String(url);
|
|
if (status === "connected") entry.connectedAt = now();
|
|
log(entry, status);
|
|
},
|
|
frame(role, data) {
|
|
const entry = channel(role);
|
|
entry.frames++;
|
|
entry.lastReceivedAt = now();
|
|
entry.lastFrame = String(data).slice(0, 512);
|
|
},
|
|
parseError(role) {
|
|
const entry = channel(role);
|
|
entry.parseErrors++;
|
|
log(entry, "invalid_json", entry.lastFrame);
|
|
},
|
|
message(role, msg, reason, outcome = "ignored") {
|
|
const entry = channel(role);
|
|
entry.messages++;
|
|
if (String(msg?.msg || msg?.type || "").toUpperCase() === "PASSING") entry.passings++;
|
|
if (["handled", "ignored", "invalid"].includes(outcome)) entry[outcome]++;
|
|
let sample = "";
|
|
try { sample = JSON.stringify({ type: msg?.msg || msg?.type, transponder: msg?.transponder ?? msg?.tran_code, rtc_time: msg?.rtc_time }); } catch {}
|
|
log(entry, reason, sample);
|
|
},
|
|
snapshot() { return DIAGNOSTIC_ROLES.map(role => { const entry = channel(role); return { ...entry, log: entry.log.map(item => ({ ...item })) }; }); },
|
|
clear(role) {
|
|
const entry = channel(role);
|
|
for (const key of ["frames", "messages", "passings", "handled", "ignored", "invalid", "parseErrors"]) entry[key] = 0;
|
|
entry.lastFrame = "";
|
|
entry.log = [];
|
|
},
|
|
};
|
|
}
|
|
export const decoderDiagnostics = createDecoderDiagnostics();
|