# Siemens S7

This document explains how to use the S7 Connector to communicate with Siemens S7 PLCs. Think of this connector as a universal translator that allows your app to "speak" the same language as the PLC.

The process is simple:

1. **Connect** to the PLC.
2. **Define** the variables (or "tags") you want to read or write.
3. **Perform** the read or write operations.

## Finding Connection Details in TIA Portal

To connect to a PLC, you need three key pieces of information: its **IP Address**, **Rack**, and **Slot**. You can find these in your TIA Portal project.

### 1. IP Address

Select the PLC in the "Project tree" on the left. In the "Properties" tab below, go to "**PROFINET interface > Ethernet addresses**". The **IP address** is listed here.

### 2. Rack & Slot

For S7-1200 and S7-1500 series PLCs, the Rack and Slot are almost always **Rack `0`** and **Slot `1`**. For older S7-300/400 series, you can find this by clicking on "**Device configuration**". The PLC is typically on Rack `0`, and the Slot is usually `2`.

### 3. Enable PUT/GET Communication (Crucial!)

For the connector to have permission to read and write data, you must enable this setting in TIA Portal:

1. Right-click the PLC and select "**Properties**".
2. Go to "**Protection & Security > Connection mechanisms**".
3. Check the box for "**Permit access with PUT/GET communication from remote partner**".
4. Download the hardware configuration to the PLC.

## Connector Functions

You must first create an instance of the connector and then use its functions to interact with your PLC.

{% hint style="success" %}
Typically you will first install the Siemens S7 connector within an [agent](/app-builder/build-backend/function-explorer/agents.md). That way you can connect your cloud platform to your shopfloor (OT), on-premises PLCs.
{% endhint %}

### connect

Establishes the connection to the target PLC using the details you found in TIA Portal.

**Example:**

```yaml
# options
host: 192.168.0.1  # IP Address from TIA Portal
port: 102
rack: 0
slot: 1            # Use 1 for S7-1200/1500, often 2 for S7-300/400
```

### Addressing PLC Variables

You have two ways to tell the connector which variables to read or write: using an **Address Dictionary** for convenience or using **Direct Addresses**. You can even use both at the same time!

**Method 1: Using an Address Dictionary (Recommended)**

An Address Dictionary lets you create a "shopping list" of all the PLC variables you want to work with. You give each variable a simple, human-readable name (an alias) and map it to its specific address in the PLC. This makes your code much easier to read and maintain.

**Method 2: Using Direct & Mixed Addresses**

If you prefer, you can use the PLC's raw memory address directly in functions like `addItems` and `writeItems`. The connector is smart enough to handle a mix of aliases and direct addresses. When it sees a string, it first checks if it's an alias in the dictionary. If not, it treats it as a direct address.

### setAddressDictionary

Configures the connector with your list of aliases.

{% hint style="danger" %}
Setting a new dictionary will clear the current list of items being monitored. Always set your dictionary **before** adding items that rely on it.
{% endhint %}

**Example:**

```yaml
# dictionary
MOTOR_SPEED: 'DB1,REAL4'
E_STOP_PRESSED: 'I0.0'
CONVEYOR_RUNNING: 'Q4.1'
PROCESS_STEP_COMPLETE: 'M10.5'
```

### addItems

Tells the connector which variables you want to actively monitor. You can provide aliases, direct addresses, or a mix of both.

**Example 1: Using Aliases**

```yaml
# items
[MOTOR_SPEED, E_STOP_PRESSED]
```

**Example 2: Using a Mix**

```yaml
# items
[MOTOR_SPEED, 'DB10,X20.4']
```

**Example 3: Using a single item**

```yaml
# items
'DB10,X20.4'
```

### readAllItems

Reads the current values of all variables you added with `addItems`. The keys in the output object will match the strings you added (aliases and/or direct addresses).

**Output from "Using a Mix" example above:**

```json
{
  "MOTOR_SPEED": 1499.98,
  "DB10,X20.4": true
}
```

### writeItems

Writes one or more new values to one or more variables in the PLC. If several values are written make sure the `items` and the `values` array are of same order and length.

{% hint style="warning" %}
You can only have one write operation running at a time.
{% endhint %}

**Example:**

```yaml
# items
CONVEYOR_RUNNING
# values
true
```

### removeItems

Removes one or more variables from the active monitoring list.

**Example: Removes a single item**

```yaml
# items
E_STOP_PRESSED
```

### removeAllItems

A convenient function to completely clear the list of monitored items.

### showAddressDictionary & showAllItems

These functions are useful for debugging by showing the current state of the connector.

* `showAddressDictionary`: Returns the currently configured address dictionary object.
* `showAllItems`: Returns an array of all item strings currently in the monitoring list.

### getStatus

Checks the current connection state.

**Output:** Returns a string: `'disconnected'`, `'connecting'`, or `'connected'`.

## Appendix: S7 Address Syntax

### Memory Areas

The first part of an address defines *where* the data is stored in the PLC.

| **Area**         | **Name**       | **Description**                                                                             | **Example** |
| ---------------- | -------------- | ------------------------------------------------------------------------------------------- | ----------- |
| **`DB<number>`** | Data Block     | The main area for storing program data, settings, and recipes. The most common area to use. | `DB1,REAL4` |
| **`I`**          | Inputs         | Reads the status of **physical inputs** like sensors and buttons. (Read-Only)               | `I0.0`      |
| **`Q`**          | Outputs        | Reads or controls **physical outputs** like motors and lights.                              | `Q4.1`      |
| **`M`**          | Merkers/Memory | The PLC's internal "scratchpad" memory for flags and intermediate values.                   | `M10.5`     |

### Data Types

The address format is `AREA,TYPE<BYTE_OFFSET>[.BIT_OR_LENGTH]`.

| **Data Type**              | **S7 Name** | **Description & Example**                         |
| -------------------------- | ----------- | ------------------------------------------------- |
| **Boolean** (On/Off)       | `X`         | A single bit. `DB1,X0.0`                          |
| **Byte** (0-255)           | `B`         | An 8-bit number. `DB1,B1`                         |
| **Char Array**             | `C`         | Reads raw text. `DB1,C20.10` (10 characters)      |
| **String**                 | `S`         | A standard S7 string. `DB1,S20.10` (max 10 chars) |
| **Integer** (Whole Number) | `INT`       | A 16-bit signed number. `DB1,INT2`                |
| **Word** (Unsigned)        | `WORD`      | A 16-bit positive number. `DB1,WORD4`             |
| **Double Int**             | `DINT`      | A 32-bit signed number. `DB1,DINT6`               |
| **DWord** (Unsigned)       | `DWORD`     | A 32-bit positive number. `DB1,DWORD10`           |
| **Real** (Decimal)         | `REAL`      | A 32-bit decimal number. `DB1,REAL14`             |

## Common Pitfalls & Solutions

* **Error: "Object does not exist"**
  * **Problem:** You are trying to write to a Data Block (`DB`) that either doesn't exist or is too small in the PLC.
  * **Solution:** Ensure the DB number is correct and that its size in TIA Portal is large enough to hold all your variables.
* **Reading a String Looks Garbled**
  * **Problem:** You might be using the `S` type on a raw array of characters.
  * **Solution:** Use the `C` type (Char Array) for reading raw text that doesn't have the standard S7 string header. For example: `DB1,C0.16`.
* **Working with `TIME` Values**
  * **Problem:** The S7 `TIME` data type is a special format.
  * **Solution:** Treat it as a `DINT`. The value will be the time in milliseconds. An address for a `TIME` variable would be `DB1,DINT32`.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.heisenware.com/app-builder/build-backend/function-explorer/connectors/siemens-s7.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
