# 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 Request
     ↓
TCP Socket
     ↓
ISOTCPProtocol (RFC 1006)
     ↓
ConnectionManager
     ↓
S7Protocol
     ↓
S7PDUParser
     ↓
S7Server
     ↓
MemoryManager
     ↓
Response 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.