Embed Ignition metadata in SVG export (color, state, priority, tagpath)

Each symbol gets data-* attributes for Ignition integration:
- data-color="#000000", data-state="OFF", data-priority="No Alarms"
- data-tagpath="System/{MCM}/{Category}/{SubType}/{Label}"

Tag paths derived from label suffix (_VFD→VFD/APF, _TPE→Sensor/Tracking, etc.)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
igurielidze 2026-03-30 22:28:12 +04:00
parent 053b034a2a
commit 0b1f2c0c69

View File

@ -111,6 +111,51 @@ export function exportJSON() {
downloadBlob(new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }), `${mcmName}_layout.json`); downloadBlob(new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }), `${mcmName}_layout.json`);
} }
/** Build Ignition tag path from device label and MCM name.
* Format: System/{MCM}/{Category}/{SubCategory}/{Label} */
function getIgnitionTagPath(label: string, mcm: string): string | null {
if (!label) return null;
const upper = label.toUpperCase();
// VFD drives (conveyors, spurs, curves, inductions)
if (/_VFD\d*$/i.test(label)) return `System/${mcm}/VFD/APF/${label}`;
// EPC controllers
if (/_EPC\d*$/i.test(label)) return `System/${mcm}/VFD/APF/${label}`;
// Network nodes
if (/_FIOM\d*$/i.test(label) || /_FIO\d*$/i.test(label)) return `System/${mcm}/Network_Node/FIO/${label}`;
if (/_FIOH\d*$/i.test(label)) return `System/${mcm}/Network_Node/HUB/${label}`;
if (/_SIO\d*$/i.test(label)) return `System/${mcm}/Network_Node/SIO/${label}`;
if (/_DPM\d*$/i.test(label)) return `System/${mcm}/Network_Node/DPM/${label}`;
// Sensors
if (/_TPE\d*$/i.test(label)) return `System/${mcm}/Sensor/Tracking/${label}`;
if (/_LPE\d*$/i.test(label)) return `System/${mcm}/Sensor/Long_Range/${label}`;
if (/_FPE\d*$/i.test(label)) return `System/${mcm}/Sensor/Full/${label}`;
if (/_JPE\d*$/i.test(label)) return `System/${mcm}/Sensor/Jam/${label}`;
if (/_PPE\d*$/i.test(label) || /_PS\d*$/i.test(label)) return `System/${mcm}/Sensor/Pressure/${label}`;
// Controls / Station
if (/_JR\d*_PB$/i.test(label) || /_JR\d*$/i.test(label)) return `System/${mcm}/Station/Jam_Reset/${label}`;
if (/_SS\d*_PB$/i.test(label)) return `System/${mcm}/Station/Start_Stop/${label}`;
if (/_S\d*_PB$/i.test(label)) return `System/${mcm}/Station/Start/${label}`;
// Solenoids / Beacons
if (/_BCN\d*$/i.test(label)) return `System/${mcm}/Solenoids/${label}`;
if (/_SOL\d*$/i.test(label)) return `System/${mcm}/Solenoids/${label}`;
// PDP
if (/^PDP/i.test(label)) return `System/${mcm}/PDP/${label}`;
// MCM
if (/^MCM/i.test(label)) return null; // MCM itself has no tag path
return null;
}
/** Build Ignition data attributes for a symbol group element */
function getIgnitionAttrs(label: string): string {
const mcm = layout.currentMcm || 'MCM01';
const tagPath = getIgnitionTagPath(label, mcm);
let attrs = ` data-color="#000000" data-state="OFF" data-priority="No Alarms"`;
if (tagPath) attrs += ` data-tagpath="${tagPath}"`;
return attrs;
}
/** Serialize child elements of an SVG, stripping xmlns added by XMLSerializer */ /** Serialize child elements of an SVG, stripping xmlns added by XMLSerializer */
function serializeChildren(parent: Element): string { function serializeChildren(parent: Element): string {
return Array.from(parent.children) return Array.from(parent.children)
@ -147,7 +192,8 @@ export async function exportSVG() {
const cx = sym.x + sym.w / 2; const cx = sym.x + sym.w / 2;
const cy = sym.y + sym.h / 2; const cy = sym.y + sym.h / 2;
const label = sym.label || sym.name; const label = sym.label || sym.name;
const idAttr = `id="${label}" inkscape:label="${label}"`; const igAttrs = getIgnitionAttrs(label);
const idAttr = `id="${label}" inkscape:label="${label}"${igAttrs}`;
// Build outer transform (rotation + mirror) // Build outer transform (rotation + mirror)
const outerParts: string[] = []; const outerParts: string[] = [];