# Technical Documentation: Parsed S7 Data JSON Format

Last Updated: 2025-05-17

## 1. Introduction

This document describes the structure and content of the JSON file generated by the S7 source parser (`x3.py`). The JSON file provides a detailed, structured representation of User Defined Types (UDTs) and Data Blocks (DBs) parsed from Siemens S7 source files (e.g., `.udt`, `.db` text exports).

The primary goal of this JSON format is to enable other processes, such as automated documentation generation, data analysis, HMI/SCADA integration, or source code reconstruction, by providing a consistent and machine-readable format of the S7 block data.

## 2. Overall JSON Structure

The root of the JSON file is an object containing two main keys:

* `"udts"`: An array of UDT definition objects.
* `"dbs"`: An array of DB definition objects.

```json
{
  "udts": [ /* Array of UdtInfo objects */ ],
  "dbs":  [ /* Array of DbInfo objects */ ]
}
````

## 3\. UDT Definition Object (`UdtInfo`)

Each object in the `"udts"` array represents a single User Defined Type.

| Key                   | Type        | Description                                                                 | Presence    |
| :-------------------- | :---------- | :-------------------------------------------------------------------------- | :---------- |
| `name`                | String      | The name of the UDT (e.g., "Recipe\_Prod").                                  | Mandatory   |
| `family`              | String      | The family of the UDT as defined in the source (e.g., "DataType").          | Optional    |
| `version`             | String      | The version of the UDT (e.g., "0.1").                                       | Optional    |
| `total_size_in_bytes` | Integer     | The total calculated size of the UDT in bytes, including any padding.         | Mandatory   |
| `members`             | Array       | An array of `VariableInfo` objects representing the members of this UDT.    | Mandatory   |

**Example `UdtInfo` Object:**

```json
{
  "name": "MyUDT",
  "family": "DataType",
  "version": "1.0",
  "total_size_in_bytes": 128,
  "members": [
    {
      "name": "FirstMember",
      "data_type": "INT",
      "byte_offset": 0.0,
      "size_in_bytes": 2,
      "initial_value": "0",
      "comment": "Initial counter"
      /* ... more VariableInfo objects ... */
    }
  ]
}
```

## 4\. DB Definition Object (`DbInfo`)

Each object in the `"dbs"` array represents a single Data Block.

| Key                                    | Type        | Description                                                                                               | Presence    |
| :------------------------------------- | :---------- | :-------------------------------------------------------------------------------------------------------- | :---------- |
| `name`                                 | String      | The name of the DB (e.g., "HMI\_Blender\_Parameters").                                                      | Mandatory   |
| `title`                                | String      | The `TITLE` property of the DB, often including S7 language settings (e.g., "{ S7\_language := '...' }").  | Optional    |
| `family`                               | String      | The family of the DB (e.g., "Resource").                                                                  | Optional    |
| `version`                              | String      | The version of the DB (e.g., "0.0").                                                                      | Optional    |
| `total_size_in_bytes`                  | Integer     | The total calculated size of the DB's declaration section in bytes, including padding.                    | Mandatory   |
| `members`                              | Array       | An array of `VariableInfo` objects representing the variables declared in the DB.                         | Mandatory   |
| `_begin_block_assignments_ordered`     | Array       | An array of 2-element arrays (tuples) `[path_string, value_string]`, preserving the order of assignments from the `BEGIN` block. | Optional    |
| `_initial_values_from_begin_block`     | Object      | A dictionary mapping full variable paths (String) to their assigned values (String) from the `BEGIN` block. Used by the parser to populate `current_value` and `current_element_values`. | Optional    |

**Example `DbInfo` Object:**

```json
{
  "name": "InstanceDB",
  "title": "{ S7_language := 'English' }",
  "family": "ApplicationData",
  "version": "0.5",
  "total_size_in_bytes": 256,
  "members": [
    {
      "name": "MotorSpeed",
      "data_type": "DINT",
      "byte_offset": 0.0,
      "size_in_bytes": 4,
      "initial_value": "0",
      "current_value": "1500"
      /* ... more VariableInfo objects ... */
    }
  ],
  "_begin_block_assignments_ordered": [
    ["MotorSpeed", "1500"],
    ["Settings.Mode", "1"],
    ["Alarms[1]", "TRUE"]
  ],
  "_initial_values_from_begin_block": {
    "MotorSpeed": "1500",
    "Settings.Mode": "1",
    "Alarms[1]": "TRUE"
  }
}
```

## 5\. Variable Information Object (`VariableInfo`)

This object is used for members within UDTs and DBs.

| Key                        | Type        | Description                                                                                                                               | Presence                       |
| :------------------------- | :---------- | :---------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------- |
| `name`                     | String      | Name of the variable/member.                                                                                                              | Mandatory                      |
| `data_type`                | String      | The base S7 data type (e.g., "BOOL", "INT", "REAL", "STRING", "MyUDTName"). For UDT instances, this is the UDT name *without* quotes.          | Mandatory                      |
| `byte_offset`              | Float       | The absolute byte offset from the start of the parent block (DB or UDT). For `BOOL` types, this is a float `X.Y` where `X` is the byte and `Y` is the bit number (0-7). | Mandatory                      |
| `size_in_bytes`            | Integer     | The size of this variable in bytes. For single `BOOL` types, this is `0`. For `BOOL` arrays, it's the number of bytes spanned by the array.  | Mandatory                      |
| `bit_size`                 | Integer     | The size of the variable in bits. Typically `1` for `BOOL` and `0` for byte-aligned types.                                                | Optional (Defaults to 0)       |
| `udt_source_name`          | String      | If `data_type` is a UDT, this field holds the original UDT name *with* quotes as found in the source (e.g., `"MyUDTName"`).                  | Optional (Present for UDTs)    |
| `string_length`            | Integer     | For `STRING` types, the declared maximum length of the string (N in `STRING[N]`). The actual storage is N+2 bytes.                      | Optional (Present for STRINGs) |
| `array_dimensions`         | Array       | An array of `ArrayDimension` objects if the variable is an array. Empty if not an array.                                                  | Optional (Present for Arrays)  |
| `initial_value`            | String      | The initial value assigned in the declaration part (e.g., `:= 10`, `:= 'text'`). Stored as a string.                                       | Optional                       |
| `current_value`            | String      | The effective value of the variable after considering the `BEGIN` block assignments (for DBs) or the `initial_value` (for UDT members). Stored as a string. For arrays, this field might represent a global assignment if present, but individual element values are preferred in `current_element_values`. | Optional                       |
| `comment`                  | String      | The line comment associated with the variable declaration.                                                                                | Optional                       |
| `children`                 | Array       | If this variable is a `STRUCT` or an instance of a UDT, this array contains `VariableInfo` objects for its members. For UDT instances, these are the *expanded* members of the UDT. | Optional (Present for STRUCTs/UDTs) |
| `is_udt_expanded_member`   | Boolean     | `true` if this `VariableInfo` object represents a member that was expanded from a UDT definition (i.e., it's a child of a UDT instance variable). `false` otherwise. | Optional (Defaults to `false`) |
| `current_element_values`   | Object      | For array variables in DBs, this dictionary stores the current values of individual array elements assigned in the `BEGIN` block. Keys are string representations of indices (e.g., "1", "1,0"), values are the assigned string values. | Optional (Present for Arrays in DBs with BEGIN block assignments) |

**Example `VariableInfo` Object (for an INT):**

```json
{
  "name": "CycleCount",
  "data_type": "INT",
  "byte_offset": 10.0,
  "size_in_bytes": 2,
  "bit_size": 0,
  "initial_value": "0",
  "current_value": "123",
  "comment": "Counts machine cycles",
  "is_udt_expanded_member": false
}
```

**Example `VariableInfo` Object (for an Array of BOOLs in a DB):**

```json
{
  "name": "StatusBits",
  "data_type": "BOOL",
  "byte_offset": 12.0,
  "size_in_bytes": 2,
  "bit_size": 1,
  "array_dimensions": [
    { "lower_bound": 0, "upper_bound": 15, "count": 16 }
  ],
  "is_udt_expanded_member": false,
  "current_element_values": {
    "0": "TRUE",
    "5": "FALSE"
  }
}
```

**Example `VariableInfo` Object (for a UDT instance in a DB):**

```json
{
  "name": "MainRecipe",
  "data_type": "Recipe_Prod",
  "byte_offset": 100.0,
  "size_in_bytes": 184,
  "udt_source_name": "\"Recipe_Prod\"",
  "is_udt_expanded_member": false,
  "children": [
    {
      "name": "_Name",
      "data_type": "STRING",
      "byte_offset": 100.0,
      "size_in_bytes": 34,
      "string_length": 32,
      "initial_value": "'Default Name'",
      "current_value": "'Apple Pie Mix'",
      "is_udt_expanded_member": true
      /* ... other expanded members ... */
    }
  ]
}
```

## 6\. Array Dimension Object (`ArrayDimension`)

Each object in the `array_dimensions` array of a `VariableInfo` object.

| Key           | Type    | Description                               | Presence    |
| :------------ | :------ | :---------------------------------------- | :---------- |
| `lower_bound` | Integer | The lower bound of the array dimension.   | Mandatory   |
| `upper_bound` | Integer | The upper bound of the array dimension.   | Mandatory   |
| `count`       | Integer | The number of elements in this dimension (`upper_bound - lower_bound + 1`). This is calculated and included by the parser. | Mandatory   |

**Example `ArrayDimension` Object:**

```json
{
  "lower_bound": 1,
  "upper_bound": 10,
  "count": 10
}
```

For a multi-dimensional array like `ARRAY [1..2, 0..4] OF ...`, the `array_dimensions` key in `VariableInfo` would be:

```json
"array_dimensions": [
  { "lower_bound": 1, "upper_bound": 2, "count": 2 },
  { "lower_bound": 0, "upper_bound": 4, "count": 5 }
]
```

## 7\. Data Interpretation Notes

  * **Offsets**: `byte_offset` is always absolute from the start of its containing UDT or DB. For `BOOL`s, the fractional part indicates the bit number (e.g., `34.0` is byte 34, bit 0; `34.7` is byte 34, bit 7).
  * **`current_value` vs. `initial_value`**:
      * For UDT members (when describing the UDT definition itself), `current_value` is not typically relevant as UDTs are type definitions. Their `initial_value` from the UDT declaration is the primary value.
      * For DB members, `initial_value` is from the declaration section. `current_value` reflects the value after considering the `BEGIN` block assignments. If a variable is not mentioned in the `BEGIN` block, its `current_value` will typically be its `initial_value`.
  * **`current_element_values` for Arrays**: This field in `VariableInfo` (for DB arrays) provides specific values for array elements that were explicitly assigned in the `BEGIN` block. The keys are strings representing the index (or comma-separated indices for multi-dimensional arrays) as found in the S7 source's `BEGIN` block (e.g., "1", "0,15").
  * **`_begin_block_assignments_ordered` in `DbInfo`**: This array of `[path_string, value_string]` tuples is the most reliable source for reconstructing the `BEGIN` block in its original order. The `path_string` can be hierarchical (e.g., `MyStruct.MyArray[1]._Member`).
  * **String Values**: String literals (e.g., initial values for `STRING` types) are typically enclosed in single quotes in the JSON, mirroring S7 syntax (e.g., `'My Text'`).
  * **Boolean Values**: Boolean values in `initial_value`, `current_value`, or values within `current_element_values` and `_begin_block_assignments_ordered` are stored as strings "TRUE" or "FALSE" (or potentially raw `true`/`false` if the parser output Python booleans, which should then be interpreted as S7 `TRUE`/`FALSE`). The parser (`x3.py`) should aim to store them as "TRUE"/"FALSE" strings for consistency.

