> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coreflux.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Siemens S7 Route

> Connect to Siemens S7-200, S7-300, S7-400, S7-1200, and S7-1500 PLCs using native S7 protocol

## Siemens S7 Overview

The `SIEMENS_S7` route enables direct communication with Siemens S7 PLCs using the native S7 protocol (ISO-on-TCP). It supports all major S7 PLC families and provides access to data blocks, memory areas, inputs, outputs, timers, and counters.

> [!TIP]
>
> The S7 route uses native protocol communication, which is typically faster and more efficient than OPC UA for Siemens PLCs.

## Basic Syntax

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE SiemensPLC WITH TYPE SIEMENS_S7
    ADD S7_CONFIG
        WITH IP "192.168.1.100"
        WITH CPU_TYPE "S71500"
        WITH RACK 0
        WITH SLOT 1
    ADD MAPPING ProcessData
        WITH EVERY 500 MILLISECONDS
        ADD TAG Temperature
            WITH ADDRESS "DB1.DBD100"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "plc/temperature"
```

***

## Supported CPU Types

| CPU Type | Parameter Value | Typical Slot | Description |
| - | - | - | - |
| S7-200 | `S7200` | 0 | Compact micro PLCs |
| S7-300 | `S7300` | 2 | Modular PLCs |
| S7-400 | `S7400` | 2/3 | High-performance PLCs |
| S7-1200 | `S71200` | 1 | Compact controllers |
| S7-1500 | `S71500` | 1 | Advanced controllers |

> [!NOTE]
>
> For S7-1200/1500 PLCs, you may need to enable "Permit access with PUT/GET" in the PLC's protection settings (Hardware Configuration → Protection & Security).

***

## Connection Configuration

### S7\_CONFIG Parameters

**IP** `string` *required*

S7 PLC IP address.

**CPU\_TYPE** `string` *required*

CPU type: `S7200`, `S7300`, `S7400`, `S71200`, or `S71500`.

**RACK** `integer`

PLC rack number. Default: 0.

**SLOT** `integer`

PLC slot number. Default: 1 for S7-1200/1500, 2 for S7-300/400.

**CONNECTION\_TYPE** `string`

Connection type: `PG` (Programming device), `OP` (Operator Panel), or `S7BASIC`. Default: PG.

**RETRY\_ATTEMPTS** `integer`

Number of retry attempts on failure. Default: 3.

**RETRY\_TIME\_SECONDS** `integer`

Seconds to wait between retries. Default: 5.

**REFRESH\_TIME\_MS** `integer`

Refresh time in milliseconds. Default: 1000.

**READ\_TIMEOUT** `integer`

Read timeout in milliseconds. Default: 5000.

**WRITE\_TIMEOUT** `integer`

Write timeout in milliseconds. Default: 5000.

### Connection Examples

**S7-1500**

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD S7_CONFIG
    WITH IP "192.168.1.100"
    WITH CPU_TYPE "S71500"
    WITH RACK 0
    WITH SLOT 1
    WITH CONNECTION_TYPE "PG"
```

**S7-1200**

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD S7_CONFIG
    WITH IP "192.168.1.50"
    WITH CPU_TYPE "S71200"
    WITH RACK 0
    WITH SLOT 1
```

**S7-300**

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD S7_CONFIG
    WITH IP "192.168.1.30"
    WITH CPU_TYPE "S7300"
    WITH RACK 0
    WITH SLOT 2
```

**S7-400**

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD S7_CONFIG
    WITH IP "192.168.1.20"
    WITH CPU_TYPE "S7400"
    WITH RACK 0
    WITH SLOT 3
```

***

## S7 Addressing

### Address Format

S7 addresses follow the pattern: `<Area><Number>.<Offset>` or `<DB>.<Type><Offset>`

| Address | Description | Example |
| - | - | - |
| `DBn.DBXx.y` | Data Block bit | `DB1.DBX0.0` - DB1, byte 0, bit 0 |
| `DBn.DBBx` | Data Block byte | `DB1.DBB0` - DB1, byte 0 |
| `DBn.DBWx` | Data Block word (16-bit) | `DB1.DBW100` - DB1, word at byte 100 |
| `DBn.DBDx` | Data Block double word (32-bit) | `DB1.DBD100` - DB1, dword at byte 100 |
| `Mx.y` | Memory bit | `M0.0` - Marker byte 0, bit 0 |
| `MBx` | Memory byte | `MB0` - Marker byte 0 |
| `MWx` | Memory word | `MW100` - Marker word at byte 100 |
| `MDx` | Memory double word | `MD100` - Marker dword at byte 100 |
| `Ix.y` | Input bit | `I0.0` - Input byte 0, bit 0 |
| `IBx` | Input byte | `IB0` - Input byte 0 |
| `IWx` | Input word | `IW0` - Input word at byte 0 |
| `Qx.y` | Output bit | `Q0.0` - Output byte 0, bit 0 |
| `QBx` | Output byte | `QB0` - Output byte 0 |
| `QWx` | Output word | `QW0` - Output word at byte 0 |
| `Tx` | Timer | `T0` - Timer 0 |
| `Cx` | Counter | `C0` - Counter 0 |

### Address Types

**ADDRESS\_TYPE** `string`

Memory area type: `DATABLOCK`, `MEMORY`, `INPUT`, `OUTPUT`, `TIMER`, `COUNTER`.

> [!NOTE]
>
> For most configurations, the ADDRESS\_TYPE is inferred from the address format. Use explicit ADDRESS\_TYPE when needed for clarity.

***

## Data Types

| Data Type | S7 Type | Size | Description |
| - | - | - | - |
| `BOOL` / `BIT` | BOOL | 1 bit | Boolean value |
| `BYTE` | BYTE | 8 bits | Unsigned 8-bit |
| `SINT` | SINT | 8 bits | Signed 8-bit integer |
| `USINT` | USINT | 8 bits | Unsigned 8-bit integer |
| `WORD` | WORD | 16 bits | Unsigned 16-bit |
| `INT` / `INT16` | INT | 16 bits | Signed 16-bit integer |
| `UINT` / `UINT16` | UINT | 16 bits | Unsigned 16-bit integer |
| `DWORD` | DWORD | 32 bits | Unsigned 32-bit |
| `DINT` / `INT32` | DINT | 32 bits | Signed 32-bit integer |
| `UDINT` / `UINT32` | UDINT | 32 bits | Unsigned 32-bit integer |
| `LWORD` | LWORD | 64 bits | Unsigned 64-bit |
| `LINT` / `INT64` | LINT | 64 bits | Signed 64-bit integer |
| `ULINT` / `UINT64` | ULINT | 64 bits | Unsigned 64-bit integer |
| `REAL` / `FLOAT` | REAL | 32 bits | 32-bit floating point |
| `LREAL` / `DOUBLE` | LREAL | 64 bits | 64-bit floating point |
| `STRING` | STRING | Variable | S7 string type; sized with `LENGTH` (default 256 bytes, includes two-byte header) |
| `CHAR` | CHAR | 8 bits | Single character |
| `WCHAR` | WCHAR | 16 bits | Wide character |
| `TIME` | TIME | 32 bits | Time duration |
| `DATE` | DATE | 16 bits | Date value |
| `TOD` | TOD | 32 bits | Time of day |
| `DTL` / `DATETIME` / `DATE_AND_TIME` | DTL | 12 bytes | Date and time combined |

### String sizing

For `STRING` tags, `WITH LENGTH` is the **total allocated buffer in bytes** on the wire—the S7 two-byte maximum-length/current-length header **plus** the maximum character payload. It is **not** the character count alone. Default: **256** bytes. `STRING_SIZE` is accepted as an alias for the same field.

In TIA Portal, a `STRING[n]` variable occupies **n + 2** bytes (two header bytes plus **n** characters of capacity). Set `WITH LENGTH` to that combined total so the route reads the full allocation from the starting byte address—for example, `STRING[254]` occupies 256 bytes, so use `WITH LENGTH 256`.

```lot wrap focus={13} theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE S7Strings WITH TYPE SIEMENS_S7
    ADD S7_CONFIG
        WITH IP "192.168.1.100"
        WITH CPU_TYPE "S71500"
        WITH RACK 0
        WITH SLOT 1
    ADD MAPPING ProductData
        WITH EVERY 1 SECOND
        ADD TAG ProductName
            WITH ADDRESS "DB1.DBB300"
            WITH ADDRESS_TYPE "DATABLOCK"
            WITH DATA_TYPE "STRING"
            WITH LENGTH 64
            WITH SOURCE_TOPIC "plc/product/name"
```

For cross-protocol defaults and caps, see [String sizing by Route](./overview#string-sizing-by-route) on the industrial overview.

***

## TAG Configuration

### Complete TAG Example

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD TAG ProcessTemperature
    WITH ADDRESS "DB1.DBD100"
    WITH ADDRESS_TYPE "DATABLOCK"
    WITH DATA_TYPE "REAL"
    WITH SOURCE_TOPIC "plc/process/temperature"
    WITH SCALING 1
    WITH OFFSET 0
    WITH UNIT "°C"
    WITH DECIMAL_PLACES 2
    WITH MIN_VALUE -50
    WITH MAX_VALUE 200
    WITH DEADBAND 0.5
    WITH PUBLISH_MODE "JSON"
    WITH WRITABLE "true"
    WITH DESTINATION_TOPIC "plc/process/temperature/set"
    WITH BYTE_ORDER "BIGENDIAN"
    WITH DESCRIPTION "Main process temperature"
```

### TAG Parameters

> **Address Configuration**
>
> **ADDRESS** `string` *required*
>
> S7 address in standard notation (e.g., `DB1.DBW100`, `M0.0`, `I0.0`, `Q0.0`).
>
> **ADDRESS\_TYPE** `string`
>
> Address type: `DATABLOCK`, `MEMORY`, `INPUT`, `OUTPUT`, `TIMER`, `COUNTER`.
>
> **DATA\_TYPE** `string` *required*
>
> S7 data type: `BOOL`, `BYTE`, `WORD`, `DWORD`, `INT`, `DINT`, `REAL`, `STRING`.
>
> **LENGTH** `integer` (default: 256)
>
> **STRING only.** Total string buffer size in bytes, including the two-byte S7 header. Alias: `STRING_SIZE`.

> **Value Transformation**
>
> **SCALING** `double`
>
> Multiplier applied to raw value. Default: 1.0.
>
> **OFFSET** `double`
>
> Value added after scaling. Default: 0.0.
>
> **DECIMAL\_PLACES** `integer`
>
> Number of decimal places in output. Default: 2.

> **Filtering**
>
> **MIN\_VALUE** `double`
>
> Minimum allowed value.
>
> **MAX\_VALUE** `double`
>
> Maximum allowed value.
>
> **DEADBAND** `double`
>
> Minimum change to trigger publish. Default: 0.0.

> **Publishing**
>
> **SOURCE\_TOPIC** `string`
>
> Topic where PLC values are published. Subscribe here to receive sensor data.
>
> **PUBLISH\_MODE** `string`
>
> Output format: `VALUE_ONLY` or `JSON`. Default: VALUE\_ONLY.
>
> **UNIT** `string`
>
> Engineering unit (e.g., °C, bar, RPM).

> **Write Configuration**
>
> **WRITABLE** `boolean`
>
> Allow writing to this address. Default: false.
>
> **DESTINATION\_TOPIC** `string`
>
> Topic to send write commands. Publish a value here to write it to the PLC.

***

## Event-Based Operations

For on-demand S7 operations (not polling), use the EVENT syntax. Publish a message to SOURCE\_TOPIC to trigger the operation; the route executes it and publishes the result to DESTINATION\_TOPIC.

### Supported Operations

| Operation | Description | Query Parameters |
| - | - | - |
| `READ` | Read data from a memory address | `address`, `data_type`, `count` |
| `WRITE` | Write a value to a memory address | `address`, `data_type`, `value` |

### Query Parameters

| Parameter | Description | Example |
| - | - | - |
| `operation` | Operation type: `READ` or `WRITE` | `READ` |
| `address` | S7 address in standard notation | `DB1.DBW0`, `MW100`, `I0.0` |
| `data_type` | S7 data type | `WORD`, `REAL`, `BOOL`, `DINT` |
| `count` | Number of consecutive values to read (READ only) | `10` |
| `value` | Value to write (WRITE only) | `42`, `23.5`, `true` |

### Read Example

Read 10 words from Data Block 1 on demand:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD EVENT ReadOnDemand
    WITH SOURCE_TOPIC "s7/commands/read"
    WITH DESTINATION_TOPIC "s7/responses/read"
    WITH QUERY "{operation: READ, address: DB1.DBW0, data_type: WORD, count: 10}"
```

### Write Example

Write a REAL value to Data Block 10 on demand:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD EVENT WriteSetpoint
    WITH SOURCE_TOPIC "s7/commands/write"
    WITH DESTINATION_TOPIC "s7/responses/write"
    WITH QUERY "{operation: WRITE, address: DB10.DBD4, data_type: REAL, value: 75.0}"
```

***

## Complete Examples

**Basic Data Block Reading**

Read values from a data block:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE ProductionPLC WITH TYPE SIEMENS_S7
    ADD S7_CONFIG
        WITH IP "192.168.1.100"
        WITH CPU_TYPE "S71500"
        WITH RACK 0
        WITH SLOT 1
    ADD MAPPING ProductionData
        WITH EVERY 500 MILLISECONDS
        ADD TAG Temperature
            WITH ADDRESS "DB1.DBD0"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "plc/temperature"
            WITH UNIT "°C"
        ADD TAG Pressure
            WITH ADDRESS "DB1.DBD4"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "plc/pressure"
            WITH UNIT "bar"
        ADD TAG Speed
            WITH ADDRESS "DB1.DBW8"
            WITH DATA_TYPE "INT"
            WITH SOURCE_TOPIC "plc/speed"
            WITH UNIT "RPM"
        ADD TAG Running
            WITH ADDRESS "DB1.DBX10.0"
            WITH DATA_TYPE "BOOL"
            WITH SOURCE_TOPIC "plc/running"
```

**Memory and I/O**

Read markers, inputs, and outputs:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE IOMonitor WITH TYPE SIEMENS_S7
    ADD S7_CONFIG
        WITH IP "192.168.1.100"
        WITH CPU_TYPE "S71200"
        WITH RACK 0
        WITH SLOT 1
    ADD MAPPING DigitalIO
        WITH EVERY 100 MILLISECONDS
        ADD TAG StartButton
            WITH ADDRESS "I0.0"
            WITH ADDRESS_TYPE "INPUT"
            WITH DATA_TYPE "BOOL"
            WITH SOURCE_TOPIC "plc/io/start"
        ADD TAG StopButton
            WITH ADDRESS "I0.1"
            WITH ADDRESS_TYPE "INPUT"
            WITH DATA_TYPE "BOOL"
            WITH SOURCE_TOPIC "plc/io/stop"
        ADD TAG MotorRunning
            WITH ADDRESS "Q0.0"
            WITH ADDRESS_TYPE "OUTPUT"
            WITH DATA_TYPE "BOOL"
            WITH SOURCE_TOPIC "plc/io/motor"
        ADD TAG SystemReady
            WITH ADDRESS "M0.0"
            WITH ADDRESS_TYPE "MEMORY"
            WITH DATA_TYPE "BOOL"
            WITH SOURCE_TOPIC "plc/status/ready"
```

**Bidirectional Control**

Read process values and write setpoints:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE ControlLoop WITH TYPE SIEMENS_S7
    ADD S7_CONFIG
        WITH IP "192.168.1.100"
        WITH CPU_TYPE "S71500"
        WITH RACK 0
        WITH SLOT 1
    ADD MAPPING ControlData
        WITH EVERY 200 MILLISECONDS
        ADD TAG ProcessValue
            WITH ADDRESS "DB10.DBD0"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "control/pv"
            WITH UNIT "°C"
            WITH PUBLISH_MODE "JSON"
        ADD TAG Setpoint
            WITH ADDRESS "DB10.DBD4"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "control/sp"
            WITH UNIT "°C"
            WITH WRITABLE "true"
            WITH DESTINATION_TOPIC "control/sp/set"
            WITH MIN_VALUE 0
            WITH MAX_VALUE 100
        ADD TAG Output
            WITH ADDRESS "DB10.DBD8"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "control/output"
            WITH UNIT "%"
        ADD TAG ManualMode
            WITH ADDRESS "DB10.DBX12.0"
            WITH DATA_TYPE "BOOL"
            WITH SOURCE_TOPIC "control/manual"
            WITH WRITABLE "true"
            WITH DESTINATION_TOPIC "control/manual/set"
```

**Multiple Polling Rates**

Optimize with different update frequencies:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE OptimizedPLC WITH TYPE SIEMENS_S7
    ADD S7_CONFIG
        WITH IP "192.168.1.100"
        WITH CPU_TYPE "S71500"
        WITH RACK 0
        WITH SLOT 1
    
    ADD MAPPING FastLoop
        WITH EVERY 100 MILLISECONDS
        ADD TAG CriticalAlarm
            WITH ADDRESS "DB1.DBX0.0"
            WITH DATA_TYPE "BOOL"
            WITH SOURCE_TOPIC "plc/alarms/critical"
        ADD TAG MotorSpeed
            WITH ADDRESS "DB1.DBD10"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "plc/motor/speed"
    
    ADD MAPPING MediumLoop
        WITH EVERY 1 SECOND
        ADD TAG Temperature
            WITH ADDRESS "DB2.DBD0"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "plc/process/temp"
        ADD TAG Pressure
            WITH ADDRESS "DB2.DBD4"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "plc/process/pressure"
    
    ADD MAPPING SlowLoop
        WITH EVERY 10 SECONDS
        ADD TAG ProductionCount
            WITH ADDRESS "DB3.DBD0"
            WITH DATA_TYPE "DINT"
            WITH SOURCE_TOPIC "plc/production/count"
        ADD TAG RuntimeHours
            WITH ADDRESS "DB3.DBD4"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "plc/stats/runtime"
```

**Combined (Cyclic + On-Demand)**

Continuous monitoring with on-demand read and write events in the same route:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE FullS7Setup WITH TYPE SIEMENS_S7
    ADD S7_CONFIG
        WITH IP "192.168.1.100"
        WITH CPU_TYPE "S71500"
        WITH RACK 0
        WITH SLOT 1
    
    ADD MAPPING ProcessData
        WITH EVERY 500 MILLISECONDS
        ADD TAG Temperature
            WITH ADDRESS "DB1.DBD0"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "plc/temperature"
            WITH UNIT "°C"
        ADD TAG Pressure
            WITH ADDRESS "DB1.DBD4"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "plc/pressure"
            WITH UNIT "bar"
    
    ADD EVENT ReadBlock
        WITH SOURCE_TOPIC "s7/commands/read"
        WITH DESTINATION_TOPIC "s7/responses/read"
        WITH QUERY "{operation: READ, address: DB2.DBW0, data_type: WORD, count: 20}"
    
    ADD EVENT WriteSetpoint
        WITH SOURCE_TOPIC "s7/commands/write"
        WITH DESTINATION_TOPIC "s7/responses/write"
        WITH QUERY "{operation: WRITE, address: DB1.DBD8, data_type: REAL, value: 0}"
```

The MAPPING continuously reads temperature and pressure from DB1. To trigger an on-demand read of 20 words from DB2, publish any message to `s7/commands/read`. To write a setpoint, publish to `s7/commands/write`.

***

## S7-1200/1500 Setup

> [!WARNING]
>
> S7-1200 and S7-1500 PLCs require additional configuration to allow external access.

### Enable PUT/GET Access

1. Open TIA Portal project
2. Navigate to **Device Configuration** → **Properties**
3. Go to **Protection & Security** → **Connection mechanisms**
4. Enable **Permit access with PUT/GET communication from remote partner**

### Optimized Block Access

For S7-1500, ensure data blocks are set to allow standard access:

1. Open the Data Block in TIA Portal
2. In Properties, uncheck **Optimized block access**
3. Compile and download to PLC

***

## Troubleshooting

> **Connection Refused**
>
> * Verify IP address is correct
> * Check PLC is in RUN mode
> * For S7-1200/1500: Enable PUT/GET access
> * Verify correct RACK and SLOT settings
> * Check firewall allows TCP port 102

> **Wrong Slot Error**
>
> Use correct slot for your CPU:
>
> * S7-1200/1500: Slot 1
> * S7-300: Slot 2
> * S7-400: Slot 2 or 3 (check hardware config)

> **Optimized Block Access Error**
>
> For S7-1500: Disable optimized block access in TIA Portal for data blocks you want to access.

> **Incorrect Values**
>
> * Verify address matches TIA Portal
> * Check DATA\_TYPE corresponds to PLC variable type
> * For multi-word types, verify byte offset is correct
> * Check BYTE\_ORDER if values seem swapped

> **Write Fails**
>
> * Ensure WRITABLE is set to "true"
> * Verify PLC is in RUN mode
> * Check access permissions in PLC
> * Confirm value is within MIN\_VALUE/MAX\_VALUE

***

## Next Steps

> **[OPC UA Client](./opcua-client)**
>
> Cross-platform industrial communication.

> **[ADS (Beckhoff)](./ads)**
>
> Connect to TwinCAT systems.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.