PLC Tag Database to OPC UA NodeSet Converter
This tool converts a simple list of PLC tags (e.g., exported from a PLC programming software as CSV or plain text) into a basic OPC UA NodeSet XML file.
Input Format Expected: Each line should represent a tag with properties separated by commas or tabs. The order should be: TagName,DataType,Description (optional).
Example Input:
MotorRPM,REAL,Current rotational speed of motorPumpStatus,BOOL,Status of the pump (ON/OFF)TankLevel,INT,Water level in tank (0-100%)ProductName,STRING,Name of the product currently being processed
No valid tags found for conversion after parsing.
'; outputNodeSet.value = ''; downloadPdfButton.style.display = 'none'; return; } // Start building the NodeSet XML xmlContent = `NodeSet XML generated successfully! Download the file below.
'; downloadPdfButton.style.display = 'block'; // Store data for PDF generation resultArea.dataset.originalInputPreview = rawData.substring(0, 500) + (rawData.length > 500 ? '...' : ''); resultArea.dataset.generatedNodeSetPreview = formattedXml.substring(0, 500) + (formattedXml.length > 500 ? '...' : ''); resultArea.dataset.tagCount = parsedTags.length; resultArea.dataset.conversionStatus = 'Success'; } /** * Formats an XML string for readability (basic indentation). * @param {string} xml The XML string to format. * @returns {string} The formatted XML string. */ function formatXml(xml) { let formatted = ''; const reg = /(>)(<)(\/?)/g; xml = xml.replace(reg, '$1\n$2$3'); let pad = 0; const indent = ' '; // 2 spaces const lines = xml.split('\n'); for (let i = 0; i < lines.length; i++) { let node = lines[i]; let indentOut = 0; if (node.match(/.+<\/\w[^>]*>$/)) { indentOut = 0; } else if (node.match(/^<\/\w/)) { if (pad !== 0) { pad -= 1; } } else if (node.match(/^<\w[^>]*[^\/]>.*$/)) { indentOut = 1; } else { indentOut = 0; } let indentString = ''; for (let j = 0; j < pad; j++) { indentString += indent; } formatted += indentString + node + '\n'; pad += indentOut; } return formatted.trim(); } /** * Triggers the download of the generated OPC UA NodeSet XML file. */ function downloadConvertedFile() { const outputNodeSet = document.getElementById('outputNodeSet'); if (!outputNodeSet || !outputNodeSet.value) { console.error('No generated NodeSet content to download.'); const resultArea = document.getElementById('resultArea'); if (resultArea) { resultArea.style.display = 'block'; resultArea.innerHTML = 'No NodeSet content available for download.
'; } return; } const content = outputNodeSet.value; const filename = 'PLC_Tags_NodeSet.xml'; const blob = new Blob([content], { type: 'application/xml;charset=utf-8;' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); const resultArea = document.getElementById('resultArea'); if (resultArea) { resultArea.style.display = 'block'; resultArea.innerHTML = `File "${filename}" downloaded successfully!
`; } } /** * Clears all input/output fields and hides results/PDF button. */ function clearAll() { document.getElementById('inputTagData').value = ''; document.getElementById('outputNodeSet').value = ''; const resultArea = document.getElementById('resultArea'); const downloadPdfButton = document.getElementById('downloadPdfButton'); resultArea.style.display = 'none'; resultArea.innerHTML = ''; // Clear stored data for PDF delete resultArea.dataset.originalInputPreview; delete resultArea.dataset.generatedNodeSetPreview; delete resultArea.dataset.tagCount; delete resultArea.dataset.conversionStatus; downloadPdfButton.style.display = 'none'; } /** * Generates a PDF summary of the conversion. */ function generatePdf() { if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined') { console.error('jsPDF library not loaded. Cannot generate PDF.'); const resultArea = document.getElementById('resultArea'); if (resultArea) { resultArea.innerHTML = 'PDF generation failed. Library not loaded.
'; } return; } const { jsPDF } = window.jspdf; const doc = new jsPDF(); const resultArea = document.getElementById('resultArea'); // Retrieve stored data for PDF const originalInputPreview = resultArea.dataset.originalInputPreview || 'No input data provided.'; const generatedNodeSetPreview = resultArea.dataset.generatedNodeSetPreview || 'No NodeSet generated.'; const tagCount = resultArea.dataset.tagCount || '0'; const conversionStatus = resultArea.dataset.conversionStatus || 'N/A'; const generationDate = new Date().toLocaleString(); let yOffset = 20; // Title doc.setFontSize(24); doc.setTextColor(44, 62, 80); doc.text("PLC Tag to OPC UA NodeSet Conversion Report", 105, yOffset, { align: 'center' }); yOffset += 20; // Summary details doc.setFontSize(14); doc.setTextColor(51, 51, 51); doc.text(`Conversion Date: ${generationDate}`, 20, yOffset); yOffset += 10; doc.text(`Conversion Status: ${conversionStatus}`, 20, yOffset); yOffset += 10; doc.text(`Number of Tags Converted: ${tagCount}`, 20, yOffset); yOffset += 20; // Input Format Assumptions doc.setFontSize(12); doc.setTextColor(80, 80, 80); doc.text("Input Format Assumption:", 20, yOffset); yOffset += 7; doc.text("Data expected as: TagName,DataType,[Description] per line (comma/tab separated).", 25, yOffset); yOffset += 15; // Data Type Mapping Used doc.text("PLC Data Type to OPC UA BuiltInType Mapping (Simplified):", 20, yOffset); yOffset += 7; Object.keys(plcDataTypeToOpcUaNodeId).forEach(plcType => { if (yOffset > 270) { doc.addPage(); yOffset = 20; doc.text("Mapping (cont.):", 20, yOffset); yOffset += 7;} doc.text(`- ${plcType} -> ${plcDataTypeToOpcUaNodeId[plcType]}`, 30, yOffset); yOffset += 6; }); yOffset += 15; // Original Content Preview if (yOffset > 250) { doc.addPage(); yOffset = 20; } doc.setFontSize(12); doc.setTextColor(51, 51, 51); doc.text("Original Input Data Preview (first 500 chars):", 20, yOffset); yOffset += 10; const originalPreviewLines = doc.splitTextToSize(originalInputPreview, 170); doc.text(originalPreviewLines, 20, yOffset); yOffset += (originalPreviewLines.length * 7) + 15; // Generated NodeSet Preview if (yOffset > 250) { doc.addPage(); yOffset = 20; } doc.setFontSize(12); doc.setTextColor(51, 51, 51); doc.text("Generated OPC UA NodeSet XML Preview (first 500 chars):", 20, yOffset); yOffset += 10; const generatedPreviewLines = doc.splitTextToSize(generatedNodeSetPreview, 170); doc.text(generatedPreviewLines, 20, yOffset); yOffset += (generatedPreviewLines.length * 7) + 15; // Footer doc.setFontSize(9); doc.setTextColor(150, 150, 150); doc.text(`Report Generated by PLC Tag to OPC UA NodeSet Converter Tool`, 20, doc.internal.pageSize.height - 15); doc.save("PLC_Tags_NodeSet_Conversion_Summary.pdf"); }