.
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
// GenericI60Driver.mjs
|
||||
import { BaseFileDriver } from '../../core/BaseFileDriver.mjs';
|
||||
import * as Parser from './parser.mjs';
|
||||
|
||||
/**
|
||||
* Driver genérico i60 (sin conectividad). Lee archivos .txt exportados del equipo.
|
||||
* Implementa el "Template Method" heredado de BaseFileDriver.
|
||||
*/
|
||||
export default class GenericI60Driver extends BaseFileDriver {
|
||||
constructor(opts = {}) {
|
||||
super({
|
||||
...opts,
|
||||
parserStrategy: { parseLine: Parser.parseLine },
|
||||
intervalBuilder: opts.intervalBuilder || 'crossDay'
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// index.mjs
|
||||
import GenericI60Driver from './GenericI60Driver.mjs';
|
||||
|
||||
export const manifest = {
|
||||
vendor: 'generic',
|
||||
model: 'i60',
|
||||
transport: 'file',
|
||||
capabilities: ['import', 'intervals:cross-day'],
|
||||
version: '1.0.0'
|
||||
};
|
||||
|
||||
export default GenericI60Driver;
|
||||
export { manifest };
|
||||
@@ -0,0 +1,54 @@
|
||||
// parser.mjs
|
||||
import { normDateStr, toUTCms } from '../../core/utils/dates.mjs';
|
||||
import { cleanDoc, normTime } from '../../core/utils/docs.mjs';
|
||||
|
||||
/**
|
||||
* Parsea una línea con prioridad por TAB; si no hay, cae a espacios;
|
||||
* separa fecha/hora si vienen juntas.
|
||||
* Devuelve { doc, name, isoDate, time, dt_ms, mode } o null.
|
||||
*/
|
||||
export function parseLine(line) {
|
||||
const raw = String(line || '').replace(/\r/g, '').trim();
|
||||
if (!raw) return null;
|
||||
|
||||
// omitir encabezados comunes
|
||||
if (/^no[\t ]|^mchn[\t ]|^enno[\t ]|^name[\t ]|^datetime[\t ]/i.test(raw)) return null;
|
||||
|
||||
let parts = raw.split(/\t+/);
|
||||
|
||||
// Fallback: dos o más espacios + DateTime al final
|
||||
if (parts.length < 7) {
|
||||
const dtMatch = raw.match(/(\d{2,4}[\/-]\d{1,2}[\/-]\d{1,2})\s+(\d{1,2}:\d{2}:\d{2})$/);
|
||||
if (dtMatch) {
|
||||
const head = raw.slice(0, dtMatch.index).trim();
|
||||
const headParts = head.split(/\t+|\s{2,}/).filter(Boolean);
|
||||
parts = [...headParts, dtMatch[1], dtMatch[2]];
|
||||
} else {
|
||||
parts = raw.split(/\s{2,}/).filter(Boolean);
|
||||
}
|
||||
}
|
||||
if (parts.length < 7) return null;
|
||||
|
||||
// Indices "normales": 0:No, 1:Mchn, 2:EnNo(doc), 3:Name, 4:Mode, 5:Fecha, 6:Hora
|
||||
const doc = cleanDoc(parts[2]);
|
||||
const name = String(parts[3] || '').trim();
|
||||
const mode = String(parts[4] || '').trim();
|
||||
|
||||
let dateStr = String(parts[5] || '').trim();
|
||||
let timeStr = String(parts[6] || '').trim();
|
||||
|
||||
// Caso: la última columna es "YYYY/MM/DD HH:MM:SS"
|
||||
const last = parts[parts.length - 1];
|
||||
const dtBoth = /(\d{2,4}[\/-]\d{1,2}[\/-]\d{1,2})\s+(\d{1,2}:\d{2}:\d{2})/.exec(last);
|
||||
if (dtBoth) { dateStr = dtBoth[1]; timeStr = dtBoth[2]; }
|
||||
else if (!timeStr && /\d{1,2}:\d{2}:\d{2}/.test(dateStr)) {
|
||||
const m = dateStr.match(/^(.+?)\s+(\d{1,2}:\d{2}:\d{2})$/);
|
||||
if (m) { dateStr = m[1]; timeStr = m[2]; }
|
||||
}
|
||||
|
||||
const iso = normDateStr(dateStr);
|
||||
const timeNorm = normTime(timeStr);
|
||||
if (!iso || !timeNorm) return null;
|
||||
|
||||
return { doc, name, isoDate: iso, time: timeNorm, dt_ms: toUTCms(iso, timeNorm), mode };
|
||||
}
|
||||
Reference in New Issue
Block a user