UNPKG

s7-server

Version:
285 lines 10.6 kB
"use strict"; /** * S7 Address Parser Utility * Handles parsing of S7 PLC address strings into structured format */ Object.defineProperty(exports, "__esModule", { value: true }); exports.S7AddressParser = void 0; // Internal modules const s7_types_1 = require("../types/s7-types"); /** * S7 Address Parser Class * Provides comprehensive parsing of S7 address strings */ class S7AddressParser { /** * Parse S7 address string into structured format * Supports full S7 addressing formats including data types */ static parseAddress(address) { if (!address || typeof address !== 'string') { return { success: false, error: 'Invalid address format' }; } const trimmed = address.trim().toUpperCase(); // Parse DB addresses with data types (e.g., DB5,X0.1, DB23,B1, DB42,I3, etc.) const dbWithTypeMatch = trimmed.match(/^DB(\d+),([XIBWDR]|DI|DW)(\d+)(?:\.(\d+))?$/); if (dbWithTypeMatch) { const [, dbNumber, dataType, offset, bitOffset] = dbWithTypeMatch; const db = parseInt(dbNumber, 10); const byteOffset = parseInt(offset, 10); if (db < 0 || db > 65535) { return { success: false, error: 'DB number out of range' }; } if (byteOffset < 0 || byteOffset > 65535) { return { success: false, error: 'Byte offset out of range' }; } // Handle bit addressing for X type if (dataType === 'X' && bitOffset !== undefined) { const bit = parseInt(bitOffset, 10); if (bit < 0 || bit > 7) { return { success: false, error: 'Bit offset must be 0-7' }; } return { success: true, address: { area: s7_types_1.S7Area.DB, index: db, start: byteOffset, wordLen: s7_types_1.S7WordLength.Bit, size: 1 } }; } // Handle other data types let wordLen; let size; switch (dataType) { case 'B': // Byte wordLen = s7_types_1.S7WordLength.Byte; size = 1; break; case 'I': // Signed 16-bit wordLen = s7_types_1.S7WordLength.Word; size = 1; break; case 'W': // Unsigned 16-bit wordLen = s7_types_1.S7WordLength.Word; size = 1; break; case 'DI': // Signed 32-bit wordLen = s7_types_1.S7WordLength.DWord; size = 1; break; case 'DW': // Unsigned 32-bit wordLen = s7_types_1.S7WordLength.DWord; size = 1; break; case 'R': // Real (32-bit float) wordLen = s7_types_1.S7WordLength.Real; size = 1; break; default: return { success: false, error: 'Invalid data type for DB address' }; } return { success: true, address: { area: s7_types_1.S7Area.DB, index: db, start: byteOffset, wordLen, size } }; } // Parse simple DB addresses (e.g., DB1, DB2, etc.) const dbMatch = trimmed.match(/^DB(\d+)$/); if (dbMatch) { const dbNumber = parseInt(dbMatch[1], 10); if (dbNumber < 0 || dbNumber > 65535) { return { success: false, error: 'DB number out of range' }; } return { success: true, address: { area: s7_types_1.S7Area.DB, index: dbNumber, start: 0, wordLen: s7_types_1.S7WordLength.Byte, size: 1 } }; } // Parse bit addresses (e.g., I1.0, Q2.1, M3.2, X0.0, etc.) const bitMatch = trimmed.match(/^([IMQX])(\d+)\.(\d+)$/); if (bitMatch) { const [, areaType, byteOffset, bitOffset] = bitMatch; const byte = parseInt(byteOffset, 10); const bit = parseInt(bitOffset, 10); if (byte < 0 || byte > 65535) { return { success: false, error: 'Byte offset out of range' }; } if (bit < 0 || bit > 7) { return { success: false, error: 'Bit offset must be 0-7' }; } let area; switch (areaType) { case 'I': area = s7_types_1.S7Area.PE; // Process inputs break; case 'Q': area = s7_types_1.S7Area.PA; // Process outputs break; case 'M': case 'X': area = s7_types_1.S7Area.MK; // Merkers (memory) break; default: return { success: false, error: 'Invalid area type' }; } return { success: true, address: { area, index: 0, start: byte, wordLen: s7_types_1.S7WordLength.Bit, size: 1 } }; } // Parse byte addresses (e.g., IB0, QB1, MB2, XB2, etc.) const byteMatch = trimmed.match(/^([IMQX])B(\d+)$/); if (byteMatch) { const [, areaType, byteOffset] = byteMatch; const byte = parseInt(byteOffset, 10); if (byte < 0 || byte > 65535) { return { success: false, error: 'Byte offset out of range' }; } let area; switch (areaType) { case 'I': area = s7_types_1.S7Area.PE; // Process inputs break; case 'Q': area = s7_types_1.S7Area.PA; // Process outputs break; case 'M': case 'X': area = s7_types_1.S7Area.MK; // Merkers (memory) break; default: return { success: false, error: 'Invalid area type' }; } return { success: true, address: { area, index: 0, start: byte, wordLen: s7_types_1.S7WordLength.Byte, size: 1 } }; } // Parse word addresses with data types (e.g., II10, QI12, MI14, IW16, QW18, MW20, MR38, etc.) // Note: B is excluded from this pattern since it's handled by byte addresses above const wordMatch = trimmed.match(/^([IMQX])([IWDR])(\d+)$/); if (wordMatch) { const [, areaType, dataType, offset] = wordMatch; const byteOffset = parseInt(offset, 10); if (byteOffset < 0 || byteOffset > 65535) { return { success: false, error: 'Byte offset out of range' }; } let area; switch (areaType) { case 'I': area = s7_types_1.S7Area.PE; // Process inputs break; case 'Q': area = s7_types_1.S7Area.PA; // Process outputs break; case 'M': case 'X': area = s7_types_1.S7Area.MK; // Merkers (memory) break; default: return { success: false, error: 'Invalid area type' }; } let wordLen; let size; switch (dataType) { case 'I': // Signed 16-bit wordLen = s7_types_1.S7WordLength.Word; size = 1; break; case 'W': // Unsigned 16-bit wordLen = s7_types_1.S7WordLength.Word; size = 1; break; case 'R': // Real (32-bit float) wordLen = s7_types_1.S7WordLength.Real; size = 1; break; default: return { success: false, error: `Invalid data type for word address: ${address}` }; } return { success: true, address: { area, index: 0, start: byteOffset, wordLen, size } }; } return { success: false, error: `Unsupported address format: ${address}` }; } /** * Validate if an address string is a valid S7 address */ static isValidAddress(address) { const result = this.parseAddress(address); return result.success; } /** * Get the byte count required for a word length */ static getByteCountFromWordLen(wordLen) { switch (wordLen) { case s7_types_1.S7WordLength.Bit: case s7_types_1.S7WordLength.Byte: return 1; case s7_types_1.S7WordLength.Word: case s7_types_1.S7WordLength.Counter: case s7_types_1.S7WordLength.Timer: return 2; case s7_types_1.S7WordLength.Real: case s7_types_1.S7WordLength.DWord: return 4; default: return 0; } } /** * Extract bit offset from address string for bit addressing */ static extractBitOffset(address) { const parts = address.split('.'); return parts.length > 1 ? parseInt(parts[1], 10) : 0; } /** * Check if an address represents a signed data type */ static isSignedDataType(address) { const trimmed = address.trim().toUpperCase(); return (trimmed.includes(',I') || trimmed.includes(',DI') || /^[IMQX]I\d+$/.test(trimmed) || /^[IMQX]DI\d+$/.test(trimmed)); } } exports.S7AddressParser = S7AddressParser; //# sourceMappingURL=address-parser.js.map