UNPKG

s7-server

Version:
436 lines (343 loc) 12.9 kB
# S7 PLC Server Simulator A comprehensive TypeScript implementation of an S7 PLC server simulator. This server implements the complete Siemens S7 communication protocol and can simulate a real S7 PLC, responding to all standard S7 protocol requests from clients. ## Features - **Complete S7 Protocol Implementation**: Full ISO-on-TCP (RFC 1006) and S7 PDU protocol support - **Memory Area Management**: Support for all S7 memory areas (PE, PA, MK, CT, TM, DB) - **Resourceless Mode**: Custom read/write handlers for dynamic data management - **Event System**: Comprehensive event handling for server and client events - **TypeScript**: Full type safety and IntelliSense support - **Production Ready**: Thread-safe, error-handling, and production-grade code quality - **Easy to Use**: Simple and intuitive API for S7 server operations ## Installation ```bash npm install npm run build ``` ## Quick Start ### Basic Server ```typescript import { S7Server, S7Area } from './src/index'; const server = new S7Server({ localPort: 102, maxClients: 8, pduRequest: 960 }); // Register memory areas const dbBuffer = Buffer.alloc(200); server.registerArea(S7Area.DB, 1, dbBuffer); // Start server await server.start(); ``` ### Resourceless Server ```typescript import { S7Server, RWAreaCallback, Operation } from './src/index'; const server = new S7Server(); server.setResourceless(true); const rwCallback: RWAreaCallback = (sender, operation, tag, buffer, callback) => { if (operation === Operation.Read) { // Handle read request buffer.fill(0x42); // Example data callback(buffer); } else { // Handle write request console.log('Data written:', buffer); callback(); } }; server.setRWAreaCallback(rwCallback); await server.start(); ``` ## S7 Protocol Implementation ### Protocol Stack The implementation follows the complete S7 protocol stack: ``` ┌─────────────────────────────────────┐ │ Application Layer │ ← S7 PDU (Protocol Data Unit) ├─────────────────────────────────────┤ │ Presentation Layer │ ← ISO-on-TCP (RFC 1006) ├─────────────────────────────────────┤ │ Session Layer │ ← ISO-on-TCP Connection ├─────────────────────────────────────┤ │ Transport Layer │ ← TCP ├─────────────────────────────────────┤ │ Network Layer │ ← IP ├─────────────────────────────────────┤ │ Data Link Layer │ ← Ethernet └─────────────────────────────────────┘ ``` ### ISO-on-TCP Protocol (RFC 1006) The transport layer implements ISO-on-TCP as specified in RFC 1006: - **Connection Establishment**: ISO-on-TCP connection negotiation - **TPDU Handling**: Transport Protocol Data Unit management - **Connection State Management**: Proper connection lifecycle handling - **Error Handling**: Connection error detection and recovery #### Connection Parameters - **Local TSAP**: Source Transport Service Access Point - **Remote TSAP**: Destination Transport Service Access Point - **PDU Size**: Maximum Protocol Data Unit size (default: 960 bytes) ### S7 PDU (Protocol Data Unit) The S7 PDU implementation handles all S7 protocol messages: #### Request Types 1. **PDU Negotiation** (`0xF0`): Client-server PDU size negotiation 2. **Read Request** (`0x04`): Read data from memory areas 3. **Write Request** (`0x05`): Write data to memory areas 4. **Control Request** (`0x28`): PLC control operations #### Response Types 1. **Negotiate Response** (`0xF0`): PDU negotiation response 2. **Read Response** (`0x04`): Read data response with return codes 3. **Write Response** (`0x05`): Write operation confirmation 4. **Control Response** (`0x28`): Control operation result #### Message Structure **S7 Request Header (10 bytes)** ``` Offset Size Description 0 1 Protocol ID (0x32) 1 1 Job Type (Request=0x01, Response=0x03) 2 2 Redundancy ID 4 2 Protocol Data Unit Reference 6 2 Parameter Length 8 2 Data Length ``` **S7 Response Header (12 bytes)** ``` Offset Size Description 0 1 Protocol ID (0x32) 1 1 Job Type (Request=0x01, Response=0x03) 2 2 Redundancy ID 4 2 Protocol Data Unit Reference 6 2 Parameter Length 8 2 Data Length 10 1 Error Class 11 1 Error Code ``` ### Memory Areas The server supports all standard S7 memory areas: | Area | Code | Description | Access | |------|------|-------------|---------| | `S7Area.PE` | 0x81 | Process Inputs | Read | | `S7Area.PA` | 0x82 | Process Outputs | Write | | `S7Area.MK` | 0x83 | Merkers (Memory) | Read/Write | | `S7Area.DB` | 0x84 | Data Blocks | Read/Write | | `S7Area.CT` | 0x1C | Counters | Read/Write | | `S7Area.TM` | 0x1D | Timers | Read/Write | ### Data Types and Word Lengths | Word Length | Code | Size | Description | |-------------|------|------|-------------| | `S7WordLength.Bit` | 0x01 | 1 bit | Single bit access | | `S7WordLength.Byte` | 0x02 | 1 byte | Byte access | | `S7WordLength.Char` | 0x03 | 1 byte | Character access | | `S7WordLength.Word` | 0x04 | 2 bytes | Word access (16-bit) | | `S7WordLength.Int` | 0x05 | 2 bytes | Integer access | | `S7WordLength.DWord` | 0x06 | 4 bytes | Double word access (32-bit) | | `S7WordLength.DInt` | 0x07 | 4 bytes | Double integer access | | `S7WordLength.Real` | 0x08 | 4 bytes | Real number access (IEEE 754) | | `S7WordLength.Counter` | 0x1C | 2 bytes | Counter access | | `S7WordLength.Timer` | 0x1D | 2 bytes | Timer access | ### Transport Sizes | Transport Size | Code | Description | |----------------|------|-------------| | `TS_RES_BIT` | 0x03 | Bit data | | `TS_RES_BYTE` | 0x04 | Byte data | | `TS_RES_INT` | 0x05 | Integer data | | `TS_RES_REAL` | 0x07 | Real number data | | `TS_RES_OCTET` | 0x09 | Octet string data | ### Address Format S7 addresses use a 3-byte format: - **Byte 0**: High byte of address - **Byte 1**: Middle byte of address - **Byte 2**: Low byte of address + bit index (bits 0-2) The byte address is calculated as: `(address >> 3)` The bit index is: `(address & 0x07)` ### Communication Flow #### 1. Connection Establishment ``` Client Server | | |------ Connect TCP ----->| |<----- TCP Accept -------| | | |-- ISO-on-TCP Connect -->| |<- ISO-on-TCP Accept ----| | | |---- PDU Negotiate ----->| |<--- PDU Response -------| ``` #### 2. Read Operation ``` Client Server | | |---- S7 Read Request --->| | | (Process request) |<--- S7 Read Response ---| ``` #### 3. Write Operation ``` Client Server | | |---- S7 Write Request -->| | | (Process request) |<--- S7 Write Response --| ``` ### Error Handling The server implements comprehensive error handling: #### Return Codes - `0xFF`: Success - `0x01`: Hardware error - `0x03`: Access denied - `0x05`: Invalid address - `0x06`: Data type not supported - `0x07`: Data type inconsistent - `0x0A`: Object not available - `0x0D`: Insufficient memory #### Error Recovery - Automatic connection cleanup on errors - Proper resource deallocation - Graceful error responses to clients - Comprehensive logging for debugging ## API Reference ### S7Server Class #### Constructor ```typescript new S7Server(config?: Partial<ServerConfig>) ``` #### Methods **Server Control** - `start(): Promise<boolean>` - Start the server - `startTo(address: string): Promise<boolean>` - Start server on specific address - `stop(): Promise<boolean>` - Stop the server **Memory Management** - `registerArea(areaCode: S7Area, index: number, buffer: Buffer): boolean` - `unregisterArea(areaCode: S7Area, index: number): boolean` - `getArea(areaCode: S7Area, index: number): Buffer | null` - `setArea(areaCode: S7Area, index: number, buffer: Buffer): boolean` - `lockArea(areaCode: S7Area, index: number): boolean` - `unlockArea(areaCode: S7Area, index: number): boolean` **Configuration** - `setResourceless(value: boolean): boolean` - `getParam(paramNumber: ServerParam): number | false` - `setParam(paramNumber: ServerParam, value: number): boolean` - `getEventsMask(): number` - `setEventsMask(mask: number): void` **Status** - `serverStatus(): ServerStatus` - `clientsCount(): number` - `getCpuStatus(): CpuStatus` - `setCpuStatus(status: CpuStatus): boolean` - `lastError(): number` **Events** - `on('event', callback: EventCallback)` - Server events - `setRWAreaCallback(callback: RWAreaCallback)` - Read/write callback ## Examples ### Basic Server Example ```bash npm run start:server ``` ### Client Example ```bash npm run start:client ``` ## Running Examples ```bash # Build the project npm run build # Run server example npm run start:server # Run client example (in another terminal) npm run start:client ``` ## Testing with S7 Clients You can test the server with any S7-compatible client: 1. **TIA Portal**: Use the S7 communication blocks 2. **WinCC**: Connect as an S7 client 3. **Custom Applications**: Use libraries like snap7, libnodave, or similar 4. **SCADA Systems**: Most SCADA systems support S7 protocol ### Connection Parameters - **IP Address**: `127.0.0.1` (localhost) - **Port**: `102` (default S7 port) - **Rack**: `0` - **Slot**: `1` ## Development ### Building ```bash npm run build ``` ### Development Mode ```bash npm run dev ``` ### Testing ```bash npm test ``` ### Linting ```bash npm run lint npm run lint:fix ``` ### Code Formatting ```bash npm run format npm run format:check ``` ## Architecture The TypeScript S7 Server consists of several key components: ### Core Components 1. **S7Server** (`src/server/s7-server.ts`) - Main server class that manages memory areas and handles high-level operations - Event system for server and client events - Configuration and parameter management 2. **S7Protocol** (`src/protocol/s7-protocol.ts`) - Low-level protocol handler that manages TCP connections and S7 PDU parsing - Handles read/write requests and responses - Manages client connections and PDU negotiation 3. **S7PDUParser** (`src/protocol/s7-pdu.ts`) - Parses and creates S7 Protocol Data Units - Handles all S7 message types (negotiate, read, write, control) - Manages address parsing and data type conversion 4. **ConnectionManager** (`src/protocol/connection-manager.ts`) - Manages client connections and connection state - Handles ISO-on-TCP protocol implementation - Connection lifecycle management 5. **ISOTCPProtocol** (`src/protocol/iso-tcp.ts`) - Implements ISO-on-TCP (RFC 1006) transport protocol - Handles TPDU (Transport Protocol Data Unit) management - Connection establishment and teardown 6. **MemoryManager** (`src/memory/memory-manager.ts`) - Thread-safe memory area management - Memory locking and synchronization - Area registration and data access 7. **S7Types** (`src/types/s7-types.ts`) - Comprehensive type definitions for all S7 protocol elements - Enums for areas, word lengths, and status codes - Interface definitions for all data structures ### Protocol Flow ``` Client RequestTCP SocketISOTCPProtocol (RFC 1006) ↓ ConnectionManagerS7ProtocolS7PDUParserS7ServerMemoryManagerResponse Back to Client ``` ## License MIT License - see LICENSE file for details. ## Contributing 1. Fork the repository 2. Create a feature branch 3. Make your changes 4. Add tests if applicable 5. Run linting and formatting 6. Submit a pull request ## Acknowledgments This project implements the Siemens S7 communication protocol specification and RFC 1006 (ISO-on-TCP) from scratch, providing a complete TypeScript solution for S7 PLC server simulation.