# 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.