Snapshot of the working tree exactly as it stood, no edits. This is the predecessor
PRICEGOD was rewritten from ("kept intact, untouched" per pricegod/README.md), and it
is still the only place the DYMO scale is actually implemented —
rfid-daemon/index.js:1068-1265: HID discovery, parseScaleReport, one-shot read, and a
streaming /weight + /scale/start|stop session whose JSON shape PRICEGOD's daemon.js
already speaks.
Preserved verbatim on purpose (hence -og), including the known bug: DYMO_PIDS at
index.js:1082 is [0x8003, 0x8004], so it cannot see the bench M25 (0x8009). Fix that
in whatever daemon inherits the scale, not here.
node_modules stays ignored (22M of the 24M tree). No credentials in the import: the
two PEM markers in utils.js/sheets.js only strip headers off a key read from settings,
and mrpadmin / johnking are an SSH and a Postgres username, both key/trust auth.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
76 lines
2.3 KiB
JavaScript
76 lines
2.3 KiB
JavaScript
'use strict';
|
|
// Per-session JSON-lines logger shared across all variants. Writes to
|
|
// rfid-daemon/diagnostics/run-<variant>-<YYYYMMDD-HHMMSS>.log so we can
|
|
// compare variants apples-to-apples after a session.
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const pad2 = n => n.toString().padStart(2, '0');
|
|
function tsForFilename(d = new Date()) {
|
|
return `${d.getFullYear()}${pad2(d.getMonth()+1)}${pad2(d.getDate())}-${pad2(d.getHours())}${pad2(d.getMinutes())}${pad2(d.getSeconds())}`;
|
|
}
|
|
|
|
function createLogger(variant, diagDir) {
|
|
fs.mkdirSync(diagDir, { recursive: true });
|
|
const logPath = path.join(diagDir, `run-${variant}-${tsForFilename()}.log`);
|
|
const stream = fs.createWriteStream(logPath, { flags: 'a' });
|
|
|
|
const counters = {
|
|
write_ok: 0, write_failed: 0,
|
|
read_ok: 0, read_failed: 0,
|
|
inventory_ok: 0, inventory_failed: 0,
|
|
timeout: 0,
|
|
keepalive_sent: 0, preflight_run: 0,
|
|
recover_attempted: 0,
|
|
lockups: 0,
|
|
};
|
|
let lastSuccessAt = null;
|
|
let inLockupSince = null;
|
|
const startedAt = Date.now();
|
|
|
|
function writeLine(obj) {
|
|
stream.write(JSON.stringify(obj) + '\n');
|
|
}
|
|
|
|
function event(name, data = {}) {
|
|
const obj = { ts: new Date().toISOString(), ev: name, ...data };
|
|
writeLine(obj);
|
|
|
|
if (name in counters) counters[name]++;
|
|
|
|
const isSuccess = (name === 'write_ok' || name === 'read_ok' || name === 'inventory_ok');
|
|
if (isSuccess) {
|
|
lastSuccessAt = Date.now();
|
|
if (inLockupSince) {
|
|
writeLine({ ts: obj.ts, ev: 'recovered', afterMs: Date.now() - inLockupSince });
|
|
inLockupSince = null;
|
|
}
|
|
}
|
|
if (name === 'timeout' && !inLockupSince) {
|
|
inLockupSince = Date.now();
|
|
counters.lockups++;
|
|
writeLine({ ts: obj.ts, ev: 'lockup_detected', sinceLastSuccessMs: lastSuccessAt ? Date.now() - lastSuccessAt : null });
|
|
}
|
|
}
|
|
|
|
function summary() {
|
|
return {
|
|
variant,
|
|
runtimeMs: Date.now() - startedAt,
|
|
counters: { ...counters },
|
|
lastSuccessAgoMs: lastSuccessAt ? Date.now() - lastSuccessAt : null,
|
|
currentlyLocked: !!inLockupSince,
|
|
};
|
|
}
|
|
|
|
function close() {
|
|
writeLine({ ts: new Date().toISOString(), ev: 'end', ...summary() });
|
|
stream.end();
|
|
}
|
|
|
|
return { event, summary, close, logPath };
|
|
}
|
|
|
|
module.exports = { createLogger };
|