// main.js - DEFINITIVE VERSION - Dynamic Line-by-Line Generation const { app, BrowserWindow, ipcMain, dialog } = require('electron'); const path = require('path'); const fs = require('fs'); const createWindow = () => { const win = new BrowserWindow({ width: 900, height: 750, webPreferences: { preload: path.join(__dirname, 'preload.js'), contextIsolation: true, nodeIntegration: false } }); win.maximize(); win.loadFile('index.html'); // win.webContents.openDevTools(); // You can comment this out for production }; app.whenReady().then(() => { ipcMain.handle('form:submit', (event, data) => { console.log('--- Data received in main.js ---', data); // Define spacing constants for indentation const sp2 = ' '; const sp4 = ' '; const sp6 = ' '; const sp8 = ' '; // Create an array to hold each line of the YAML file const yamlLines = []; // --- Build the YAML content section by section --- // 1. Build the 'machine' section const machineType = data.machineType || 'Unspecified'; const machineModel = data.model || ''; const serialNo = data.serialNo || ''; const VendorName = data.vendor || ''; yamlLines.push('machine:'); yamlLines.push(`${sp2}profile: ${machineType}`); yamlLines.push(`${sp2}identification:`); yamlLines.push(`${sp4}namespace: http://${VendorName}/${machineType}/${machineModel}/${serialNo}`); yamlLines.push(`${sp4}browseName: ${data.browseName || ''}`); yamlLines.push(`${sp4}manufacturer: "[${VendorName}]"`); yamlLines.push(`${sp4}model: "${machineModel}"`); yamlLines.push(`${sp4}serialNumber: "${serialNo}"`); yamlLines.push(`${sp4}yearofconstruction: "${data.buildYear || ''}"`); yamlLines.push(`${sp2}version: "${data.version || 'Unset'}"`); // 2. Build the 'alarms' section if (data.alarms) { yamlLines.push(''); yamlLines.push(`${sp2}alarms:`); yamlLines.push(`${sp4}packing: ${data.alarmPacking || 'OBJECTS'}`); yamlLines.push(`${sp4}behavior: ${data.alarmBehavior || 'STATIC'}`); yamlLines.push(`${sp4}count: ${data.alarmCount || data.alarms.length}`); yamlLines.push(`${sp4}alarms:`); data.alarms.forEach(alarm => { const id = alarm.id || 0; const name = alarm.name || `Alarm_${id}`; const message = (alarm.message || '').replace(/:/g, ';'); yamlLines.push(`${sp6}- ID: ${id}`); yamlLines.push(`${sp8}name: ${name}`); yamlLines.push(`${sp8}message: ${message}`); }); } // 3. Build the 'warnings' section if (data.warnings && data.warnings.length > 0) { yamlLines.push(''); yamlLines.push(`${sp2}warnings:`); yamlLines.push(`${sp4}packing: ${data.warningPacking || 'OBJECTS'}`); yamlLines.push(`${sp4}behavior: ${data.warningBehavior || 'STATIC'}`); yamlLines.push(`${sp4}count: ${data.warningCount || data.warnings.length}`); yamlLines.push(`${sp4}warnings:`); data.warnings.forEach(warning => { const id = warning.id || 0; const name = warning.name || `Warning_${id}`; const message = (warning.message || '').replace(/:/g, ';'); yamlLines.push(`${sp6}- ID: ${id}`); yamlLines.push(`${sp8}name: ${name}`); yamlLines.push(`${sp8}message: ${message}`); }); } // 4. Build the 'states' section if (data.states && data.states.length > 0) { yamlLines.push(''); yamlLines.push(`${sp2}states:`); yamlLines.push(`${sp4}states:`); data.states.forEach(state => { const id = state.id || 0; const name = state.name || `State_${id}`; const description = (state.description || '').replace(/:/g, ';'); yamlLines.push(`${sp6}- ID: ${id}`); yamlLines.push(`${sp8}name: ${name}`); yamlLines.push(`${sp8}description: ${description}`); }); } // 5. Build the 'counters' section if (data.counters && data.counters.length > 0) { yamlLines.push(''); yamlLines.push(`${sp2}counters:`); data.counters.forEach(counter => { const id = counter.id || 0; const name = counter.name || `Counter_${id}`; const type = counter.type || ''; const description = (counter.description || '').replace(/:/g, ';'); yamlLines.push(`${sp4}- name: ${name}`); yamlLines.push(`${sp6}ID: ${id}`); yamlLines.push(`${sp6}type: ${type}`); yamlLines.push(`${sp6}description: ${description}`); }); } // 6. Build the 'setpoints' section if (data.setpoints && data.setpoints.length > 0) { yamlLines.push(''); yamlLines.push(`${sp2}setpoints:`); yamlLines.push(`${sp4}setpoints:`); data.setpoints.forEach(setpoint => { const id = setpoint.id || 0; const name = setpoint.name || `Setpoint_${id}`; const message = (setpoint.message || '').replace(/:/g, ';'); yamlLines.push(`${sp6}- ID: ${id}`); yamlLines.push(`${sp8}name: ${name}`); yamlLines.push(`${sp8}message: ${message}`); }); } // 7. Build the 'realtimes' section if (data.realtime && data.realtime.length > 0) { yamlLines.push(''); yamlLines.push(`${sp2}realtimes:`); yamlLines.push(`${sp4}realtimes:`); data.realtime.forEach(rt => { const id = rt.id || 0; const name = rt.name || `Realtime_${id}`; const message = (rt.message || '').replace(/:/g, ';'); yamlLines.push(`${sp6}- ID: ${id}`); yamlLines.push(`${sp8}name: ${name}`); yamlLines.push(`${sp8}message: ${message}`); }); } // 8. Build the 'optionals' section if (data.stopReason === 'Yes') { yamlLines.push(''); yamlLines.push(`${sp2}optionals:`); yamlLines.push(`${sp4}- StopReason`); } // 9. Build the 'addins' section const selectedAddins = data.addins || []; if (selectedAddins.length > 0) { yamlLines.push(''); yamlLines.push(`${sp2}addins:`); if (selectedAddins.includes('AcPower')) { yamlLines.push(`${sp4}- name: AcPower`); } if (selectedAddins.includes('Utilities')) { yamlLines.push(`${sp4}- name: EnergyUtilitiesAddin`); yamlLines.push(`${sp6}# Requires data from a future 'Utilities ADDIN' UI.`); } if (selectedAddins.includes('TrackAdvance')) { yamlLines.push(`${sp4}- name: TrackAdvance`); yamlLines.push(`${sp6}# Requires data from a future 'TrackAdvance ADDIN' UI.`); } if (selectedAddins.includes('AGV')) { yamlLines.push(`${sp4}- name: AGV`); yamlLines.push(`${sp6}# Requires data from a future 'AGV ADDIN' UI.`); } } // --- Finalize and Save the File --- const generatedContent = yamlLines.join('\n'); console.log('--- Generated YAML Content ---\n', generatedContent); const nameParts = [data.machineType, data.vendor, data.model, data.serialNo, data.browseName]; const nonEmptyParts = nameParts.filter(Boolean); const baseName = nonEmptyParts.join('_'); const safeBaseName = baseName.replace(/[/\\?%*:|"<>]/g, '-'); const yamlFileName = `${safeBaseName}.yml`; const documentsPath = app.getPath('documents'); const yamlFilePath = path.join(documentsPath, yamlFileName); try { fs.writeFileSync(yamlFilePath, generatedContent, 'utf8'); dialog.showMessageBox({ type: 'info', title: 'Success', message: 'YAML File Generated Successfully!', detail: `The file was saved to:\n${yamlFilePath}` }); return { success: true, filePath: yamlFilePath }; } catch (error) { console.error("Failed to write YAML file:", error); dialog.showErrorBox('File Save Error', `Failed to save the YAML file.\nError: ${error.message}`); return { success: false, error: error.message }; } }); createWindow(); app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createWindow(); }); }); app.on('window-all-closed', () => { if (process.platform !== 'darwin') app.quit(); });