You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by ot...@apache.org on 2024/05/15 15:58:53 UTC

(plc4x) branch develop updated: Refactor / improve python modbus (#1581)

This is an automated email from the ASF dual-hosted git repository.

otluk pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/develop by this push:
     new cee493efe4 Refactor / improve python modbus (#1581)
cee493efe4 is described below

commit cee493efe4bb2e87c6b26ec189685e939582b39a
Author: otluk <ot...@apache.org>
AuthorDate: Wed May 15 17:58:42 2024 +0200

    Refactor / improve python modbus (#1581)
    
    * fix(plc4py/umas): Start to add write support
    
    * build(deps): bump github.com/stretchr/testify in /plc4go (#1439)
    
    Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.4 to 1.9.0.
    - [Release notes](https://github.com/stretchr/testify/releases)
    - [Commits](https://github.com/stretchr/testify/compare/v1.8.4...v1.9.0)
    
    ---
    updated-dependencies:
    - dependency-name: github.com/stretchr/testify
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump golang.org/x/tools from 0.18.0 to 0.19.0 in /plc4go (#1440)
    
    Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.18.0 to 0.19.0.
    - [Release notes](https://github.com/golang/tools/releases)
    - [Commits](https://github.com/golang/tools/compare/v0.18.0...v0.19.0)
    
    ---
    updated-dependencies:
    - dependency-name: golang.org/x/tools
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump logback.version from 1.5.0 to 1.5.1 (#1435)
    
    Bumps `logback.version` from 1.5.0 to 1.5.1.
    
    Updates `ch.qos.logback:logback-classic` from 1.5.0 to 1.5.1
    - [Commits](https://github.com/qos-ch/logback/compare/v_1.5.0...v_1.5.1)
    
    Updates `ch.qos.logback:logback-core` from 1.5.0 to 1.5.1
    - [Commits](https://github.com/qos-ch/logback/compare/v_1.5.0...v_1.5.1)
    
    ---
    updated-dependencies:
    - dependency-name: ch.qos.logback:logback-classic
      dependency-type: direct:production
      update-type: version-update:semver-patch
    - dependency-name: ch.qos.logback:logback-core
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump github.com/gdamore/tcell/v2 in /plc4go (#1438)
    
    Bumps [github.com/gdamore/tcell/v2](https://github.com/gdamore/tcell) from 2.7.1 to 2.7.4.
    - [Release notes](https://github.com/gdamore/tcell/releases)
    - [Changelog](https://github.com/gdamore/tcell/blob/main/CHANGESv2.md)
    - [Commits](https://github.com/gdamore/tcell/compare/v2.7.1...v2.7.4)
    
    ---
    updated-dependencies:
    - dependency-name: github.com/gdamore/tcell/v2
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump golang.org/x/net from 0.21.0 to 0.22.0 in /plc4go (#1441)
    
    Bumps [golang.org/x/net](https://github.com/golang/net) from 0.21.0 to 0.22.0.
    - [Commits](https://github.com/golang/net/compare/v0.21.0...v0.22.0)
    
    ---
    updated-dependencies:
    - dependency-name: golang.org/x/net
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump jakarta.activation:jakarta.activation-api (#1436)
    
    Bumps [jakarta.activation:jakarta.activation-api](https://github.com/jakartaee/jaf-api) from 2.1.2 to 2.1.3.
    - [Release notes](https://github.com/jakartaee/jaf-api/releases)
    - [Commits](https://github.com/jakartaee/jaf-api/compare/2.1.2...2.1.3)
    
    ---
    updated-dependencies:
    - dependency-name: jakarta.activation:jakarta.activation-api
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * fix(plc4j/genericcan) Fix of generic CAN driver and CAN transports after recent releases.
    
    Signed-off-by: Łukasz Dywicki <lu...@code-house.org>
    
    * chore: Disabled a flaky test in GO
    
    * docs: Updated the url for the opie tool
    
    * chore: Updated vendor ids
    
    * docs: Added some information on the site plugin and the asciidoctor plugin.
    
    * chore: Updated vendor ids
    
    * build: Continued fine-tuning the reproducible build release-scripts.
    
    * chore: Updated vendor ids
    
    * feat: The S7 driver now returns supporting S7, if the connected device is an S7-300.
    
    * fix: Fixed logging in the example.
    
    * refactor: Made the "protocol" accessible in the AbstractPlcConnection
    
    * refactor: Added S7-400 to the list of supported devices.
    
    * fix: Fixed the dependency usage error.
    
    * Fix/s7async (#1451)
    
    * Change type transfer in cyclic subscription from byte[] to PlcValue. Accepts cyclic subscription to bits.
    
    * Add short pattern to tag subscription.
    
    * Corrects short tag handling in CYC subscriptions. In observation./karaf
    
    * Modified the cyclical subscription system. TODO time base management fpr CYC.
    
    * Fixed time base handling for cyclical subscriptions. Subscription routine for changes is added experimentally.
    
    ---------
    
    Co-authored-by: Cesar Garcia <ce...@ceos.com.ve>
    
    * build(deps): bump com.google.googlejavaformat:google-java-format (#1449)
    
    Bumps [com.google.googlejavaformat:google-java-format](https://github.com/google/google-java-format) from 1.20.0 to 1.21.0.
    - [Release notes](https://github.com/google/google-java-format/releases)
    - [Commits](https://github.com/google/google-java-format/compare/v1.20.0...v1.21.0)
    
    ---
    updated-dependencies:
    - dependency-name: com.google.googlejavaformat:google-java-format
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump logback.version from 1.5.1 to 1.5.3 (#1448)
    
    Bumps `logback.version` from 1.5.1 to 1.5.3.
    
    Updates `ch.qos.logback:logback-classic` from 1.5.1 to 1.5.3
    - [Commits](https://github.com/qos-ch/logback/compare/v_1.5.1...v_1.5.3)
    
    Updates `ch.qos.logback:logback-core` from 1.5.1 to 1.5.3
    - [Commits](https://github.com/qos-ch/logback/compare/v_1.5.1...v_1.5.3)
    
    ---
    updated-dependencies:
    - dependency-name: ch.qos.logback:logback-classic
      dependency-type: direct:production
      update-type: version-update:semver-patch
    - dependency-name: ch.qos.logback:logback-core
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump com.gradle:common-custom-user-data-maven-extension (#1434)
    
    Bumps [com.gradle:common-custom-user-data-maven-extension](https://github.com/gradle/common-custom-user-data-maven-extension) from 1.12.5 to 1.13.
    - [Release notes](https://github.com/gradle/common-custom-user-data-maven-extension/releases)
    - [Commits](https://github.com/gradle/common-custom-user-data-maven-extension/compare/v1.12.5...v1.13)
    
    ---
    updated-dependencies:
    - dependency-name: com.gradle:common-custom-user-data-maven-extension
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * Update PlcRawByteArray.java (#1453)
    
    Removed method duplicate
    
    * chore: Disabled some OPC-UA tests, that were continuously failing the build.
    
    * chore: Disabled some OPC-UA tests, that were continuously failing the build.
    
    * feat: Added a new flag allowing to disable tests on Jenkins. Added this to the flaky OPC-UA tests and re-enabled them.
    
    * build(deps-dev): bump org.apache.commons:commons-compress (#1456)
    
    Bumps org.apache.commons:commons-compress from 1.26.0 to 1.26.1.
    
    ---
    updated-dependencies:
    - dependency-name: org.apache.commons:commons-compress
      dependency-type: direct:development
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.awaitility:awaitility from 4.2.0 to 4.2.1 (#1455)
    
    Bumps [org.awaitility:awaitility](https://github.com/awaitility/awaitility) from 4.2.0 to 4.2.1.
    - [Changelog](https://github.com/awaitility/awaitility/blob/master/changelog.txt)
    - [Commits](https://github.com/awaitility/awaitility/compare/awaitility-4.2.0...awaitility-4.2.1)
    
    ---
    updated-dependencies:
    - dependency-name: org.awaitility:awaitility
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * docs: Added "slave-id" to the description of the unit-identifier.
    
    * chore: Disabled the OpcuaPlcDriverTest as it also seems to regularly fail on GitHub actions.
    
    * build(deps): bump org.springframework.boot:spring-boot-maven-plugin (#1460)
    
    Bumps [org.springframework.boot:spring-boot-maven-plugin](https://github.com/spring-projects/spring-boot) from 3.2.3 to 3.2.4.
    - [Release notes](https://github.com/spring-projects/spring-boot/releases)
    - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.2.3...v3.2.4)
    
    ---
    updated-dependencies:
    - dependency-name: org.springframework.boot:spring-boot-maven-plugin
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump com.google.errorprone:error_prone_annotations (#1461)
    
    Bumps [com.google.errorprone:error_prone_annotations](https://github.com/google/error-prone) from 2.25.0 to 2.26.1.
    - [Release notes](https://github.com/google/error-prone/releases)
    - [Commits](https://github.com/google/error-prone/compare/v2.25.0...v2.26.1)
    
    ---
    updated-dependencies:
    - dependency-name: com.google.errorprone:error_prone_annotations
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.springframework.boot:spring-boot-dependencies (#1462)
    
    Bumps [org.springframework.boot:spring-boot-dependencies](https://github.com/spring-projects/spring-boot) from 3.2.3 to 3.2.4.
    - [Release notes](https://github.com/spring-projects/spring-boot/releases)
    - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.2.3...v3.2.4)
    
    ---
    updated-dependencies:
    - dependency-name: org.springframework.boot:spring-boot-dependencies
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * docs: Updated some documentation on the code-generation.
    
    * refactor: Renamed the paddingField paddingCondition to timesPadding
    
    * chore: Removed some unneeded code.
    
    * chore: Updated vendor ids
    
    * chore: Cleaned up in the sandbox
    
    * fix(plc4py): type extensions module added to setup.py
    
    * fix(plc4py): Move out of sandbox
    
    * chore(sandbox): Remove the Sandbox Directory
    
    * chore(plc4px): Remove manual test
    
    * feat(plc4x/modbus): Add support for unit-id option for modbus tags.
    
    Introduce support for tag config at the tag level.
    Closes #1234.
    
    * build(deps): bump nl.jqno.equalsverifier:equalsverifier (#1467)
    
    Bumps [nl.jqno.equalsverifier:equalsverifier](https://github.com/jqno/equalsverifier) from 3.15.7 to 3.16.
    - [Release notes](https://github.com/jqno/equalsverifier/releases)
    - [Changelog](https://github.com/jqno/equalsverifier/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/jqno/equalsverifier/compare/equalsverifier-3.15.7...equalsverifier-3.16)
    
    ---
    updated-dependencies:
    - dependency-name: nl.jqno.equalsverifier:equalsverifier
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.cyclonedx:cyclonedx-maven-plugin (#1466)
    
    Bumps [org.cyclonedx:cyclonedx-maven-plugin](https://github.com/CycloneDX/cyclonedx-maven-plugin) from 2.7.11 to 2.8.0.
    - [Release notes](https://github.com/CycloneDX/cyclonedx-maven-plugin/releases)
    - [Commits](https://github.com/CycloneDX/cyclonedx-maven-plugin/compare/cyclonedx-maven-plugin-2.7.11...cyclonedx-maven-plugin-2.8.0)
    
    ---
    updated-dependencies:
    - dependency-name: org.cyclonedx:cyclonedx-maven-plugin
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.apache.maven.plugins:maven-remote-resources-plugin (#1465)
    
    Bumps [org.apache.maven.plugins:maven-remote-resources-plugin](https://github.com/apache/maven-remote-resources-plugin) from 3.1.0 to 3.2.0.
    - [Release notes](https://github.com/apache/maven-remote-resources-plugin/releases)
    - [Commits](https://github.com/apache/maven-remote-resources-plugin/compare/maven-remote-resources-plugin-3.1.0...maven-remote-resources-plugin-3.2.0)
    
    ---
    updated-dependencies:
    - dependency-name: org.apache.maven.plugins:maven-remote-resources-plugin
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.aspectj:aspectjweaver from 1.9.21.1 to 1.9.22 (#1475)
    
    Bumps [org.aspectj:aspectjweaver](https://github.com/eclipse/org.aspectj) from 1.9.21.1 to 1.9.22.
    - [Release notes](https://github.com/eclipse/org.aspectj/releases)
    - [Commits](https://github.com/eclipse/org.aspectj/commits)
    
    ---
    updated-dependencies:
    - dependency-name: org.aspectj:aspectjweaver
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump jakarta.xml.bind:jakarta.xml.bind-api (#1474)
    
    Bumps [jakarta.xml.bind:jakarta.xml.bind-api](https://github.com/jakartaee/jaxb-api) from 4.0.1 to 4.0.2.
    - [Release notes](https://github.com/jakartaee/jaxb-api/releases)
    - [Commits](https://github.com/jakartaee/jaxb-api/compare/4.0.1...4.0.2)
    
    ---
    updated-dependencies:
    - dependency-name: jakarta.xml.bind:jakarta.xml.bind-api
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump com.google.guava:guava from 33.0.0-jre to 33.1.0-jre (#1473)
    
    Bumps [com.google.guava:guava](https://github.com/google/guava) from 33.0.0-jre to 33.1.0-jre.
    - [Release notes](https://github.com/google/guava/releases)
    - [Commits](https://github.com/google/guava/commits)
    
    ---
    updated-dependencies:
    - dependency-name: com.google.guava:guava
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump golang.org/x/net from 0.22.0 to 0.23.0 in /plc4go (#1477)
    
    Bumps [golang.org/x/net](https://github.com/golang/net) from 0.22.0 to 0.23.0.
    - [Commits](https://github.com/golang/net/compare/v0.22.0...v0.23.0)
    
    ---
    updated-dependencies:
    - dependency-name: golang.org/x/net
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump mockito.version from 5.10.0 to 5.11.0 (#1478)
    
    Bumps `mockito.version` from 5.10.0 to 5.11.0.
    
    Updates `org.mockito:mockito-core` from 5.10.0 to 5.11.0
    - [Release notes](https://github.com/mockito/mockito/releases)
    - [Commits](https://github.com/mockito/mockito/compare/v5.10.0...v5.11.0)
    
    Updates `org.mockito:mockito-junit-jupiter` from 5.10.0 to 5.11.0
    - [Release notes](https://github.com/mockito/mockito/releases)
    - [Commits](https://github.com/mockito/mockito/compare/v5.10.0...v5.11.0)
    
    ---
    updated-dependencies:
    - dependency-name: org.mockito:mockito-core
      dependency-type: direct:production
      update-type: version-update:semver-minor
    - dependency-name: org.mockito:mockito-junit-jupiter
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump io.swagger:swagger-annotations from 1.6.13 to 1.6.14 (#1479)
    
    Bumps io.swagger:swagger-annotations from 1.6.13 to 1.6.14.
    
    ---
    updated-dependencies:
    - dependency-name: io.swagger:swagger-annotations
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.sonarsource.scanner.maven:sonar-maven-plugin (#1480)
    
    Bumps [org.sonarsource.scanner.maven:sonar-maven-plugin](https://github.com/SonarSource/sonar-scanner-maven) from 3.10.0.2594 to 3.11.0.3922.
    - [Release notes](https://github.com/SonarSource/sonar-scanner-maven/releases)
    - [Commits](https://github.com/SonarSource/sonar-scanner-maven/compare/3.10.0.2594...3.11.0.3922)
    
    ---
    updated-dependencies:
    - dependency-name: org.sonarsource.scanner.maven:sonar-maven-plugin
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * Update PlcCHAR.java add Character type check to of method (#1489)
    
    As the API uses the of method to get the PlcCHAR object passing a char to API methods lead to errors, because internally the of method was used convert the passed object.
    
    * build(deps): bump golang.org/x/net from 0.23.0 to 0.24.0 in /plc4go (#1488)
    
    Bumps [golang.org/x/net](https://github.com/golang/net) from 0.23.0 to 0.24.0.
    - [Commits](https://github.com/golang/net/compare/v0.23.0...v0.24.0)
    
    ---
    updated-dependencies:
    - dependency-name: golang.org/x/net
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump groovy.version from 4.0.18 to 4.0.20 (#1486)
    
    Bumps `groovy.version` from 4.0.18 to 4.0.20.
    
    Updates `org.apache.groovy:groovy-test-junit5` from 4.0.18 to 4.0.20
    - [Commits](https://github.com/apache/groovy/commits)
    
    Updates `org.apache.groovy:groovy` from 4.0.18 to 4.0.20
    - [Commits](https://github.com/apache/groovy/commits)
    
    Updates `org.apache.groovy:groovy-xml` from 4.0.18 to 4.0.20
    - [Commits](https://github.com/apache/groovy/commits)
    
    ---
    updated-dependencies:
    - dependency-name: org.apache.groovy:groovy-test-junit5
      dependency-type: direct:production
      update-type: version-update:semver-patch
    - dependency-name: org.apache.groovy:groovy
      dependency-type: direct:production
      update-type: version-update:semver-patch
    - dependency-name: org.apache.groovy:groovy-xml
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.jacoco:jacoco-maven-plugin from 0.8.11 to 0.8.12 (#1485)
    
    Bumps [org.jacoco:jacoco-maven-plugin](https://github.com/jacoco/jacoco) from 0.8.11 to 0.8.12.
    - [Release notes](https://github.com/jacoco/jacoco/releases)
    - [Commits](https://github.com/jacoco/jacoco/compare/v0.8.11...v0.8.12)
    
    ---
    updated-dependencies:
    - dependency-name: org.jacoco:jacoco-maven-plugin
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.apache.maven.plugins:maven-source-plugin (#1484)
    
    Bumps [org.apache.maven.plugins:maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.3.0 to 3.3.1.
    - [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.3.0...maven-source-plugin-3.3.1)
    
    ---
    updated-dependencies:
    - dependency-name: org.apache.maven.plugins:maven-source-plugin
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump golang.org/x/tools from 0.19.0 to 0.20.0 in /plc4go (#1487)
    
    Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.19.0 to 0.20.0.
    - [Release notes](https://github.com/golang/tools/releases)
    - [Commits](https://github.com/golang/tools/compare/v0.19.0...v0.20.0)
    
    ---
    updated-dependencies:
    - dependency-name: golang.org/x/tools
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * fix: A compilation error.
    
    * refactor: Moved the examples, integrations and other extra stuff into the new plc4x-extras repository (#1483)
    
    * refactor: Moved the examples, integrations and other extra stuff into the new plc4x-extras repository
    
    * refactor: Cleaned up some of the managed dependencies.
    
    * refactor: Updated some of the go-tools used in the build
    
    * fix: Fixed the issues causing problems building PLC4C
    
    * fix: A compilation error.
    
    * fix: Fixed an error in the code-generation for C which only appeared in the code-gen testsuite.
    
    * fix: Fixed an error in the code-generation for C which only appeared in the code-gen testsuite.
    
    * fix: Disabling "CodeQL analysis" step as it's failing and I can't see from the output why.
    
    * fix: Disabling "Trivy Scan" workflow as it's randomy failing and I can't see from the output why.
    
    * chore: Updated the issue-tracker settings to point to GitHub instead of Jira
    
    * build(deps): bump nl.jqno.equalsverifier:equalsverifier (#1490)
    
    Bumps [nl.jqno.equalsverifier:equalsverifier](https://github.com/jqno/equalsverifier) from 3.16 to 3.16.1.
    - [Release notes](https://github.com/jqno/equalsverifier/releases)
    - [Changelog](https://github.com/jqno/equalsverifier/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/jqno/equalsverifier/compare/equalsverifier-3.16...equalsverifier-3.16.1)
    
    ---
    updated-dependencies:
    - dependency-name: nl.jqno.equalsverifier:equalsverifier
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.apache.maven.plugins:maven-assembly-plugin (#1491)
    
    Bumps [org.apache.maven.plugins:maven-assembly-plugin](https://github.com/apache/maven-assembly-plugin) from 3.6.0 to 3.7.1.
    - [Release notes](https://github.com/apache/maven-assembly-plugin/releases)
    - [Commits](https://github.com/apache/maven-assembly-plugin/compare/maven-assembly-plugin-3.6.0...maven-assembly-plugin-3.7.1)
    
    ---
    updated-dependencies:
    - dependency-name: org.apache.maven.plugins:maven-assembly-plugin
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * fix(plc4py): Fix exception on closing the connection
    
    * fix(plc4py): Fix connection lost exception being raised
    
    * fix(plc4py): set test to manual
    
    * fix(plc4py): Got rid of returning future, starting to understand it a bit more now ;)
    
    * build(deps): bump jakarta.annotation:jakarta.annotation-api (#1494)
    
    Bumps [jakarta.annotation:jakarta.annotation-api](https://github.com/jakartaee/common-annotations-api) from 2.1.1 to 3.0.0.
    - [Commits](https://github.com/jakartaee/common-annotations-api/compare/2.1.1...3.0.0)
    
    ---
    updated-dependencies:
    - dependency-name: jakarta.annotation:jakarta.annotation-api
      dependency-type: direct:production
      update-type: version-update:semver-major
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump io.netty:netty-bom from 4.1.107.Final to 4.1.108.Final (#1493)
    
    Bumps [io.netty:netty-bom](https://github.com/netty/netty) from 4.1.107.Final to 4.1.108.Final.
    - [Commits](https://github.com/netty/netty/compare/netty-4.1.107.Final...netty-4.1.108.Final)
    
    ---
    updated-dependencies:
    - dependency-name: io.netty:netty-bom
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * fix(plc4py): Add to dependabot
    
    * build(deps): bump pytest-mock from 3.12.0 to 3.14.0 in /plc4py (#1501)
    
    Bumps [pytest-mock](https://github.com/pytest-dev/pytest-mock) from 3.12.0 to 3.14.0.
    - [Release notes](https://github.com/pytest-dev/pytest-mock/releases)
    - [Changelog](https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst)
    - [Commits](https://github.com/pytest-dev/pytest-mock/compare/v3.12.0...v3.14.0)
    
    ---
    updated-dependencies:
    - dependency-name: pytest-mock
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump identify from 2.5.33 to 2.5.35 in /plc4py (#1500)
    
    Bumps [identify](https://github.com/pre-commit/identify) from 2.5.33 to 2.5.35.
    - [Commits](https://github.com/pre-commit/identify/compare/v2.5.33...v2.5.35)
    
    ---
    updated-dependencies:
    - dependency-name: identify
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump packaging from 23.2 to 24.0 in /plc4py (#1499)
    
    Bumps [packaging](https://github.com/pypa/packaging) from 23.2 to 24.0.
    - [Release notes](https://github.com/pypa/packaging/releases)
    - [Changelog](https://github.com/pypa/packaging/blob/main/CHANGELOG.rst)
    - [Commits](https://github.com/pypa/packaging/compare/23.2...24.0)
    
    ---
    updated-dependencies:
    - dependency-name: packaging
      dependency-type: direct:production
      update-type: version-update:semver-major
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump pytest-asyncio from 0.23.5 to 0.23.6 in /plc4py (#1498)
    
    Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.23.5 to 0.23.6.
    - [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases)
    - [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.23.5...v0.23.6)
    
    ---
    updated-dependencies:
    - dependency-name: pytest-asyncio
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump build from 1.0.3 to 1.2.1 in /plc4py (#1496)
    
    Bumps [build](https://github.com/pypa/build) from 1.0.3 to 1.2.1.
    - [Release notes](https://github.com/pypa/build/releases)
    - [Changelog](https://github.com/pypa/build/blob/main/CHANGELOG.rst)
    - [Commits](https://github.com/pypa/build/compare/1.0.3...1.2.1)
    
    ---
    updated-dependencies:
    - dependency-name: build
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * fix(plc4py): Use packet length estimator to be able to handle multiple packets in a queue
    
    * Update apache-kafka links to plc4x extra
    
    * feat(plc4go): change to TestingLog interface for TestLogger
    
    * build(deps): bump com.fasterxml.jackson.datatype:jackson-datatype-jsr310 (#1497)
    
    Bumps com.fasterxml.jackson.datatype:jackson-datatype-jsr310 from 2.16.1 to 2.17.0.
    
    ---
    updated-dependencies:
    - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump com.gradle:common-custom-user-data-maven-extension (#1492)
    
    Bumps [com.gradle:common-custom-user-data-maven-extension](https://github.com/gradle/common-custom-user-data-maven-extension) from 1.13 to 2.
    - [Release notes](https://github.com/gradle/common-custom-user-data-maven-extension/releases)
    - [Commits](https://github.com/gradle/common-custom-user-data-maven-extension/compare/v1.13...v2)
    
    ---
    updated-dependencies:
    - dependency-name: com.gradle:common-custom-user-data-maven-extension
      dependency-type: direct:production
      update-type: version-update:semver-major
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump mypy from 1.8.0 to 1.9.0 in /plc4py (#1502)
    
    Bumps [mypy](https://github.com/python/mypy) from 1.8.0 to 1.9.0.
    - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
    - [Commits](https://github.com/python/mypy/compare/v1.8.0...1.9.0)
    
    ---
    updated-dependencies:
    - dependency-name: mypy
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump black from 24.1.1 to 24.3.0 in /plc4py (#1503)
    
    Bumps [black](https://github.com/psf/black) from 24.1.1 to 24.3.0.
    - [Release notes](https://github.com/psf/black/releases)
    - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
    - [Commits](https://github.com/psf/black/compare/24.1.1...24.3.0)
    
    ---
    updated-dependencies:
    - dependency-name: black
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump filelock from 3.13.1 to 3.13.4 in /plc4py (#1504)
    
    Bumps [filelock](https://github.com/tox-dev/py-filelock) from 3.13.1 to 3.13.4.
    - [Release notes](https://github.com/tox-dev/py-filelock/releases)
    - [Changelog](https://github.com/tox-dev/filelock/blob/main/docs/changelog.rst)
    - [Commits](https://github.com/tox-dev/py-filelock/compare/3.13.1...3.13.4)
    
    ---
    updated-dependencies:
    - dependency-name: filelock
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump virtualenv from 20.25.0 to 20.25.1 in /plc4py (#1506)
    
    Bumps [virtualenv](https://github.com/pypa/virtualenv) from 20.25.0 to 20.25.1.
    - [Release notes](https://github.com/pypa/virtualenv/releases)
    - [Changelog](https://github.com/pypa/virtualenv/blob/main/docs/changelog.rst)
    - [Commits](https://github.com/pypa/virtualenv/compare/20.25.0...20.25.1)
    
    ---
    updated-dependencies:
    - dependency-name: virtualenv
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump typing-extensions from 4.9.0 to 4.11.0 in /plc4py (#1505)
    
    Bumps [typing-extensions](https://github.com/python/typing_extensions) from 4.9.0 to 4.11.0.
    - [Release notes](https://github.com/python/typing_extensions/releases)
    - [Changelog](https://github.com/python/typing_extensions/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/python/typing_extensions/compare/4.9.0...4.11.0)
    
    ---
    updated-dependencies:
    - dependency-name: typing-extensions
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.apache.maven.plugins:maven-invoker-plugin (#1514)
    
    Bumps [org.apache.maven.plugins:maven-invoker-plugin](https://github.com/apache/maven-invoker-plugin) from 3.6.0 to 3.6.1.
    - [Release notes](https://github.com/apache/maven-invoker-plugin/releases)
    - [Commits](https://github.com/apache/maven-invoker-plugin/compare/maven-invoker-plugin-3.6.0...maven-invoker-plugin-3.6.1)
    
    ---
    updated-dependencies:
    - dependency-name: org.apache.maven.plugins:maven-invoker-plugin
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.asciidoctor:asciidoctorj from 2.5.11 to 2.5.12 (#1515)
    
    Bumps [org.asciidoctor:asciidoctorj](https://github.com/asciidoctor/asciidoctorj) from 2.5.11 to 2.5.12.
    - [Release notes](https://github.com/asciidoctor/asciidoctorj/releases)
    - [Changelog](https://github.com/asciidoctor/asciidoctorj/blob/v2.5.12/CHANGELOG.adoc)
    - [Commits](https://github.com/asciidoctor/asciidoctorj/compare/v2.5.11...v2.5.12)
    
    ---
    updated-dependencies:
    - dependency-name: org.asciidoctor:asciidoctorj
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump com.google.googlejavaformat:google-java-format (#1516)
    
    Bumps [com.google.googlejavaformat:google-java-format](https://github.com/google/google-java-format) from 1.21.0 to 1.22.0.
    - [Release notes](https://github.com/google/google-java-format/releases)
    - [Commits](https://github.com/google/google-java-format/compare/v1.21.0...v1.22.0)
    
    ---
    updated-dependencies:
    - dependency-name: com.google.googlejavaformat:google-java-format
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump coverage from 7.4.1 to 7.4.4 in /plc4py (#1511)
    
    Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.4.1 to 7.4.4.
    - [Release notes](https://github.com/nedbat/coveragepy/releases)
    - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
    - [Commits](https://github.com/nedbat/coveragepy/compare/7.4.1...7.4.4)
    
    ---
    updated-dependencies:
    - dependency-name: coverage
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump pytest from 8.0.0 to 8.1.1 in /plc4py (#1510)
    
    Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.0.0 to 8.1.1.
    - [Release notes](https://github.com/pytest-dev/pytest/releases)
    - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
    - [Commits](https://github.com/pytest-dev/pytest/compare/8.0.0...8.1.1)
    
    ---
    updated-dependencies:
    - dependency-name: pytest
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump pre-commit from 3.6.0 to 3.7.0 in /plc4py (#1512)
    
    Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 3.6.0 to 3.7.0.
    - [Release notes](https://github.com/pre-commit/pre-commit/releases)
    - [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/pre-commit/pre-commit/compare/v3.6.0...v3.7.0)
    
    ---
    updated-dependencies:
    - dependency-name: pre-commit
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump pip-tools from 7.3.0 to 7.4.1 in /plc4py (#1513)
    
    Bumps [pip-tools](https://github.com/jazzband/pip-tools) from 7.3.0 to 7.4.1.
    - [Release notes](https://github.com/jazzband/pip-tools/releases)
    - [Changelog](https://github.com/jazzband/pip-tools/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/jazzband/pip-tools/compare/7.3.0...7.4.1)
    
    ---
    updated-dependencies:
    - dependency-name: pip-tools
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * fix(plc4j/ads): Fixed List serialization passing invalid datatype for child elements (#1517)
    
    * feat: Changed the ManualTest to allow enabling read and write requests separately as well as disabling the single-item requests and also test multi-item writes.
    
    * fix(plc4j/opcua): Cleanup discovery connection resources.
    
    Update of unit test to verify method exits.
    
    Closes #1101.
    
    Signed-off-by: Łukasz Dywicki <lu...@code-house.org>
    
    * fix(plc4j/ads): Invalid size writing multiple tags (#1524)
    
    * fix: Added the struct back to the manual ads test.
    
    * fix(plc4j/opcua): Make sure UA subscription acknowledges are retained over publish cycles.
    
    Closes #1364.
    
    Signed-off-by: Łukasz Dywicki <lu...@code-house.org>
    
    * chore: Updated vendor ids
    
    * chore: Addressed most high severity sonarcloud issues
    
    * build(deps): bump black from 24.3.0 to 24.4.0 in /plc4py (#1528)
    
    Bumps [black](https://github.com/psf/black) from 24.3.0 to 24.4.0.
    - [Release notes](https://github.com/psf/black/releases)
    - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
    - [Commits](https://github.com/psf/black/compare/24.3.0...24.4.0)
    
    ---
    updated-dependencies:
    - dependency-name: black
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.apache.maven.plugins:maven-compiler-plugin (#1525)
    
    Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.12.1 to 3.13.0.
    - [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
    - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.12.1...maven-compiler-plugin-3.13.0)
    
    ---
    updated-dependencies:
    - dependency-name: org.apache.maven.plugins:maven-compiler-plugin
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.codehaus.plexus:plexus-compiler-api (#1526)
    
    Bumps [org.codehaus.plexus:plexus-compiler-api](https://github.com/codehaus-plexus/plexus-compiler) from 2.14.2 to 2.15.0.
    - [Release notes](https://github.com/codehaus-plexus/plexus-compiler/releases)
    - [Commits](https://github.com/codehaus-plexus/plexus-compiler/compare/plexus-compiler-2.14.2...plexus-compiler-2.15.0)
    
    ---
    updated-dependencies:
    - dependency-name: org.codehaus.plexus:plexus-compiler-api
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump com.google.errorprone:error_prone_annotations (#1527)
    
    Bumps [com.google.errorprone:error_prone_annotations](https://github.com/google/error-prone) from 2.23.0 to 2.26.1.
    - [Release notes](https://github.com/google/error-prone/releases)
    - [Commits](https://github.com/google/error-prone/compare/v2.23.0...v2.26.1)
    
    ---
    updated-dependencies:
    - dependency-name: com.google.errorprone:error_prone_annotations
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump logback.version from 1.5.3 to 1.5.5 (#1531)
    
    Bumps `logback.version` from 1.5.3 to 1.5.5.
    
    Updates `ch.qos.logback:logback-classic` from 1.5.3 to 1.5.5
    - [Commits](https://github.com/qos-ch/logback/compare/v_1.5.3...v_1.5.5)
    
    Updates `ch.qos.logback:logback-core` from 1.5.3 to 1.5.5
    - [Commits](https://github.com/qos-ch/logback/compare/v_1.5.3...v_1.5.5)
    
    ---
    updated-dependencies:
    - dependency-name: ch.qos.logback:logback-classic
      dependency-type: direct:production
      update-type: version-update:semver-patch
    - dependency-name: ch.qos.logback:logback-core
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump io.netty:netty-bom from 4.1.108.Final to 4.1.109.Final (#1532)
    
    Bumps [io.netty:netty-bom](https://github.com/netty/netty) from 4.1.108.Final to 4.1.109.Final.
    - [Commits](https://github.com/netty/netty/compare/netty-4.1.108.Final...netty-4.1.109.Final)
    
    ---
    updated-dependencies:
    - dependency-name: io.netty:netty-bom
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump groovy.version from 4.0.20 to 4.0.21 (#1533)
    
    Bumps `groovy.version` from 4.0.20 to 4.0.21.
    
    Updates `org.apache.groovy:groovy-test-junit5` from 4.0.20 to 4.0.21
    - [Commits](https://github.com/apache/groovy/commits)
    
    Updates `org.apache.groovy:groovy` from 4.0.20 to 4.0.21
    - [Commits](https://github.com/apache/groovy/commits)
    
    Updates `org.apache.groovy:groovy-xml` from 4.0.20 to 4.0.21
    - [Commits](https://github.com/apache/groovy/commits)
    
    ---
    updated-dependencies:
    - dependency-name: org.apache.groovy:groovy-test-junit5
      dependency-type: direct:production
      update-type: version-update:semver-patch
    - dependency-name: org.apache.groovy:groovy
      dependency-type: direct:production
      update-type: version-update:semver-patch
    - dependency-name: org.apache.groovy:groovy-xml
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * fix(plc4j/ads): Fixed connection hang on exception (#1530)
    
    * build(deps): bump virtualenv from 20.25.1 to 20.25.2 in /plc4py (#1537)
    
    Bumps [virtualenv](https://github.com/pypa/virtualenv) from 20.25.1 to 20.25.2.
    - [Release notes](https://github.com/pypa/virtualenv/releases)
    - [Changelog](https://github.com/pypa/virtualenv/blob/main/docs/changelog.rst)
    - [Commits](https://github.com/pypa/virtualenv/compare/20.25.1...20.25.2)
    
    ---
    updated-dependencies:
    - dependency-name: virtualenv
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * Remove Protocols section in developers section (duplicate from
    
    https://plc4x.apache.org/users/protocols/ versus https://plc4x.apache.org/developers/protocols/index.html (to be deleted)
    
    * Delete src/site/asciidoc/developers/protocols directory
    
    * chore: Updated vendor ids
    
    * feat: Added a default-payload-byte-order option to the modbus driver in order to support devices with little-endian encoding of payload.
    
    * chore: Addressed more of the high severity sonarcloud issues
    
    * build(deps): bump slf4j.version from 2.0.12 to 2.0.13 (#1536)
    
    Bumps `slf4j.version` from 2.0.12 to 2.0.13.
    
    Updates `org.slf4j:slf4j-api` from 2.0.12 to 2.0.13
    
    Updates `org.slf4j:log4j-over-slf4j` from 2.0.12 to 2.0.13
    
    ---
    updated-dependencies:
    - dependency-name: org.slf4j:slf4j-api
      dependency-type: direct:production
      update-type: version-update:semver-patch
    - dependency-name: org.slf4j:log4j-over-slf4j
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.jetbrains.kotlin:kotlin-stdlib-jdk8 (#1534)
    
    Bumps [org.jetbrains.kotlin:kotlin-stdlib-jdk8](https://github.com/JetBrains/kotlin) from 1.9.22 to 1.9.23.
    - [Release notes](https://github.com/JetBrains/kotlin/releases)
    - [Changelog](https://github.com/JetBrains/kotlin/blob/v1.9.23/ChangeLog.md)
    - [Commits](https://github.com/JetBrains/kotlin/compare/v1.9.22...v1.9.23)
    
    ---
    updated-dependencies:
    - dependency-name: org.jetbrains.kotlin:kotlin-stdlib-jdk8
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * Revert "Remove Protocols section in developers section (duplicate from "
    
    This reverts commit f679a7d424b4d47c66b8ecfebe6646f6081f518a.
    
    * Revert "Delete src/site/asciidoc/developers/protocols directory"
    
    This reverts commit 58cd1f315d96362a740795d15f3aaa90bbb3a328.
    
    * Modbus in progress
    
    * add index for protocol usage page
    
    * Add eip
    
    * fixing URLs
    
    * build(deps): bump org.apache.commons:commons-configuration2 (#1541)
    
    Bumps org.apache.commons:commons-configuration2 from 2.9.0 to 2.10.1.
    
    ---
    updated-dependencies:
    - dependency-name: org.apache.commons:commons-configuration2
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.apache.karaf.tooling:karaf-maven-plugin (#1539)
    
    Bumps org.apache.karaf.tooling:karaf-maven-plugin from 4.4.5 to 4.4.6.
    
    ---
    updated-dependencies:
    - dependency-name: org.apache.karaf.tooling:karaf-maven-plugin
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump com.googlecode.maven-download-plugin:download-maven-plugin (#1540)
    
    Bumps [com.googlecode.maven-download-plugin:download-maven-plugin](https://github.com/maven-download-plugin/maven-download-plugin) from 1.8.1 to 1.9.0.
    - [Release notes](https://github.com/maven-download-plugin/maven-download-plugin/releases)
    - [Commits](https://github.com/maven-download-plugin/maven-download-plugin/compare/1.8.1...1.9.0)
    
    ---
    updated-dependencies:
    - dependency-name: com.googlecode.maven-download-plugin:download-maven-plugin
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump virtualenv from 20.25.2 to 20.25.3 in /plc4py (#1542)
    
    Bumps [virtualenv](https://github.com/pypa/virtualenv) from 20.25.2 to 20.25.3.
    - [Release notes](https://github.com/pypa/virtualenv/releases)
    - [Changelog](https://github.com/pypa/virtualenv/blob/main/docs/changelog.rst)
    - [Commits](https://github.com/pypa/virtualenv/compare/20.25.2...20.25.3)
    
    ---
    updated-dependencies:
    - dependency-name: virtualenv
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump net.bytebuddy:byte-buddy from 1.14.12 to 1.14.13 (#1545)
    
    Bumps [net.bytebuddy:byte-buddy](https://github.com/raphw/byte-buddy) from 1.14.12 to 1.14.13.
    - [Release notes](https://github.com/raphw/byte-buddy/releases)
    - [Changelog](https://github.com/raphw/byte-buddy/blob/master/release-notes.md)
    - [Commits](https://github.com/raphw/byte-buddy/compare/byte-buddy-1.14.12...byte-buddy-1.14.13)
    
    ---
    updated-dependencies:
    - dependency-name: net.bytebuddy:byte-buddy
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps-dev): bump commons-io:commons-io from 2.15.1 to 2.16.1 (#1544)
    
    Bumps commons-io:commons-io from 2.15.1 to 2.16.1.
    
    ---
    updated-dependencies:
    - dependency-name: commons-io:commons-io
      dependency-type: direct:development
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.apache.commons:commons-text from 1.11.0 to 1.12.0 (#1543)
    
    Bumps org.apache.commons:commons-text from 1.11.0 to 1.12.0.
    
    ---
    updated-dependencies:
    - dependency-name: org.apache.commons:commons-text
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * chore: Made line-breaks in the configuration option descriptions get output as line-breaks
    
    * chore: Updated vendor ids
    
    * feat: Added device-group options for local, remote and remote2 to the S7 config.
    
    * chore: Disabled the OpcuaSubscriptionHandleTest all together as it also seems to be randomly failing on GitHub Actions.
    
    * feat: Added a "Since" annotation that provides information on when a configuration-option was added.
    
    * feat: Create a source bundle for PLC4C
    
    * chore: Added newly generated files.
    
    * build(deps): bump org.codehaus.mojo:extra-enforcer-rules (#1548)
    
    Bumps [org.codehaus.mojo:extra-enforcer-rules](https://github.com/mojohaus/extra-enforcer-rules) from 1.7.0 to 1.8.0.
    - [Release notes](https://github.com/mojohaus/extra-enforcer-rules/releases)
    - [Commits](https://github.com/mojohaus/extra-enforcer-rules/compare/1.7.0...1.8.0)
    
    ---
    updated-dependencies:
    - dependency-name: org.codehaus.mojo:extra-enforcer-rules
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump logback.version from 1.5.5 to 1.5.6 (#1549)
    
    Bumps `logback.version` from 1.5.5 to 1.5.6.
    
    Updates `ch.qos.logback:logback-classic` from 1.5.5 to 1.5.6
    - [Commits](https://github.com/qos-ch/logback/compare/v_1.5.5...v_1.5.6)
    
    Updates `ch.qos.logback:logback-core` from 1.5.5 to 1.5.6
    - [Commits](https://github.com/qos-ch/logback/compare/v_1.5.5...v_1.5.6)
    
    ---
    updated-dependencies:
    - dependency-name: ch.qos.logback:logback-classic
      dependency-type: direct:production
      update-type: version-update:semver-patch
    - dependency-name: ch.qos.logback:logback-core
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump bouncycastle.version from 1.77 to 1.78.1 (#1550)
    
    Bumps `bouncycastle.version` from 1.77 to 1.78.1.
    
    Updates `org.bouncycastle:bcpkix-jdk18on` from 1.77 to 1.78.1
    - [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html)
    - [Commits](https://github.com/bcgit/bc-java/commits)
    
    Updates `org.bouncycastle:bcprov-jdk18on` from 1.77 to 1.78.1
    - [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html)
    - [Commits](https://github.com/bcgit/bc-java/commits)
    
    ---
    updated-dependencies:
    - dependency-name: org.bouncycastle:bcpkix-jdk18on
      dependency-type: direct:production
      update-type: version-update:semver-minor
    - dependency-name: org.bouncycastle:bcprov-jdk18on
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump identify from 2.5.35 to 2.5.36 in /plc4py (#1546)
    
    Bumps [identify](https://github.com/pre-commit/identify) from 2.5.35 to 2.5.36.
    - [Commits](https://github.com/pre-commit/identify/compare/v2.5.35...v2.5.36)
    
    ---
    updated-dependencies:
    - dependency-name: identify
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump pluggy from 1.4.0 to 1.5.0 in /plc4py (#1547)
    
    Bumps [pluggy](https://github.com/pytest-dev/pluggy) from 1.4.0 to 1.5.0.
    - [Changelog](https://github.com/pytest-dev/pluggy/blob/main/CHANGELOG.rst)
    - [Commits](https://github.com/pytest-dev/pluggy/compare/1.4.0...1.5.0)
    
    ---
    updated-dependencies:
    - dependency-name: pluggy
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump com.fazecast:jSerialComm from 2.10.4 to 2.11.0 (#1554)
    
    Bumps [com.fazecast:jSerialComm](https://github.com/Fazecast/jSerialComm) from 2.10.4 to 2.11.0.
    - [Release notes](https://github.com/Fazecast/jSerialComm/releases)
    - [Commits](https://github.com/Fazecast/jSerialComm/compare/v2.10.4...v2.11.0)
    
    ---
    updated-dependencies:
    - dependency-name: com.fazecast:jSerialComm
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * feat(plc4j/api): Convert the string address into a PlcTag (#1468)
    
    * Priority judgment using discovery parameter
    
    When the parameter discovery=false is configured, prefer using the custom address. If the transportEndpoint is empty, directly replace it with the TransportEndpoint returned by the server.
    
    * add setter for transportEndpoint
    
    * Convert the string address into a PlcTag.
    
    * rename string tag address to parseTagAddressSafe
    
    * rename  parseTagAddressSafe to parseTagAddress
    
    * move function parseTagAddress to PlcConnection
    
    * add logging for exceptions in PlcTag conversion.
    
    * Implement the parseTagAddress method for LeasedPlcConnection.
    
    * build(deps): bump commons-logging:commons-logging from 1.3.0 to 1.3.1 (#1553)
    
    Bumps commons-logging:commons-logging from 1.3.0 to 1.3.1.
    
    ---
    updated-dependencies:
    - dependency-name: commons-logging:commons-logging
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps-dev): bump org.json:json from 20240205 to 20240303 (#1552)
    
    Bumps [org.json:json](https://github.com/douglascrockford/JSON-java) from 20240205 to 20240303.
    - [Release notes](https://github.com/douglascrockford/JSON-java/releases)
    - [Changelog](https://github.com/stleary/JSON-java/blob/master/docs/RELEASES.md)
    - [Commits](https://github.com/douglascrockford/JSON-java/commits)
    
    ---
    updated-dependencies:
    - dependency-name: org.json:json
      dependency-type: direct:development
      update-type: version-update:semver-major
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.apache.maven.plugins:maven-jar-plugin (#1559)
    
    Bumps [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.3.0 to 3.4.1.
    - [Release notes](https://github.com/apache/maven-jar-plugin/releases)
    - [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.3.0...maven-jar-plugin-3.4.1)
    
    ---
    updated-dependencies:
    - dependency-name: org.apache.maven.plugins:maven-jar-plugin
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump virtualenv from 20.25.3 to 20.26.0 in /plc4py (#1555)
    
    Bumps [virtualenv](https://github.com/pypa/virtualenv) from 20.25.3 to 20.26.0.
    - [Release notes](https://github.com/pypa/virtualenv/releases)
    - [Changelog](https://github.com/pypa/virtualenv/blob/main/docs/changelog.rst)
    - [Commits](https://github.com/pypa/virtualenv/compare/20.25.3...20.26.0)
    
    ---
    updated-dependencies:
    - dependency-name: virtualenv
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump platformdirs from 4.2.0 to 4.2.1 in /plc4py (#1556)
    
    Bumps [platformdirs](https://github.com/platformdirs/platformdirs) from 4.2.0 to 4.2.1.
    - [Release notes](https://github.com/platformdirs/platformdirs/releases)
    - [Changelog](https://github.com/platformdirs/platformdirs/blob/main/CHANGES.rst)
    - [Commits](https://github.com/platformdirs/platformdirs/compare/4.2.0...4.2.1)
    
    ---
    updated-dependencies:
    - dependency-name: platformdirs
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump coverage from 7.4.4 to 7.5.0 in /plc4py (#1557)
    
    Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.4.4 to 7.5.0.
    - [Release notes](https://github.com/nedbat/coveragepy/releases)
    - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
    - [Commits](https://github.com/nedbat/coveragepy/compare/7.4.4...7.5.0)
    
    ---
    updated-dependencies:
    - dependency-name: coverage
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump net.bytebuddy:byte-buddy from 1.14.13 to 1.14.14 (#1562)
    
    Bumps [net.bytebuddy:byte-buddy](https://github.com/raphw/byte-buddy) from 1.14.13 to 1.14.14.
    - [Release notes](https://github.com/raphw/byte-buddy/releases)
    - [Changelog](https://github.com/raphw/byte-buddy/blob/master/release-notes.md)
    - [Commits](https://github.com/raphw/byte-buddy/compare/byte-buddy-1.14.13...byte-buddy-1.14.14)
    
    ---
    updated-dependencies:
    - dependency-name: net.bytebuddy:byte-buddy
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump commons-cli:commons-cli from 1.6.0 to 1.7.0 (#1563)
    
    Bumps commons-cli:commons-cli from 1.6.0 to 1.7.0.
    
    ---
    updated-dependencies:
    - dependency-name: commons-cli:commons-cli
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * build(deps): bump org.apache:apache from 31 to 32 (#1558)
    
    Bumps [org.apache:apache](https://github.com/apache/maven-apache-parent) from 31 to 32.
    - [Release notes](https://github.com/apache/maven-apache-parent/releases)
    - [Commits](https://github.com/apache/maven-apache-parent/commits)
    
    ---
    updated-dependencies:
    - dependency-name: org.apache:apache
      dependency-type: direct:production
      update-type: version-update:semver-major
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    
    * Change Python version to 3.10+
    
    macOS ARM version fails for python version 3.7 to 3.9.
    
    * fix(plc4py/umas): Start to add write support
    
    * rebase umas
    
    * Some small changes to python code
    
    * add additional comments in python code
    
    * fix(plc4py): Fix optional fields and clean some template stuff up
    
    * Reset to capture timeouts
    
    catch all in case it gets into the situation where we get stuck in a loop.
    
    * Revert "Reset to capture timeouts"
    
    This reverts commit d87081069a8fe94e10a4fb582db876c21e7973bc.
    
    * Adding commentary / explaination for PLC4Py
    
    * some smaller changes
    
    * fix(plc4py): start to make the umas and modbus drivers act similialy.
    
    * fix(plc4py/umas): Start to add write support
    
    * add @pytest.mark.xfail so that PLC4Py build succeeds (to be changed once the umas tests are working)
    
    ---------
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Signed-off-by: Łukasz Dywicki <lu...@code-house.org>
    Co-authored-by: Ben Hutcheson <be...@gmail.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    Co-authored-by: Łukasz Dywicki <lu...@code-house.org>
    Co-authored-by: Christofer Dutz <cd...@apache.org>
    Co-authored-by: César José García León <ce...@gmail.com>
    Co-authored-by: Cesar Garcia <ce...@ceos.com.ve>
    Co-authored-by: mrwhy-orig <bj...@b-have.de>
    Co-authored-by: Christofer Dutz <ch...@c-ware.de>
    Co-authored-by: Sebastian Rühl <sr...@apache.org>
    Co-authored-by: IsmoLeszczynski <15...@users.noreply.github.com>
    Co-authored-by: Qing <qt...@vip.qq.com>
---
 .../language/python/PythonLanguageOutput.java      |  113 +++
 .../python/PythonLanguageTemplateHelper.java       | 1043 +++++++++++++++++++-
 .../python/complex-type-template.python.ftlh       |   68 +-
 .../knxnetip/readwrite/model/KnxManufacturer.go    |    8 -
 plc4py/plc4py/PlcDriverManager.py                  |   31 +-
 .../plc4py/drivers/modbus/ModbusConfiguration.py   |   20 +-
 plc4py/plc4py/drivers/modbus/ModbusConnection.py   |  169 +++-
 plc4py/plc4py/drivers/modbus/ModbusDevice.py       |    1 +
 plc4py/plc4py/drivers/modbus/ModbusProtocol.py     |   72 +-
 plc4py/plc4py/drivers/umas/UmasDevice.py           |   11 +-
 plc4py/plc4py/drivers/umas/UmasVariables.py        |   20 +-
 plc4py/plc4py/protocols/modbus/StaticHelper.py     |   15 +-
 .../protocols/modbus/readwrite/ModbusConstants.py  |    2 +-
 .../readwrite/ModbusDeviceInformationObject.py     |    8 +-
 .../plc4py/protocols/modbus/readwrite/ModbusPDU.py |    8 +-
 .../modbus/readwrite/ModbusPDUDiagnosticRequest.py |    6 +-
 .../readwrite/ModbusPDUDiagnosticResponse.py       |    6 +-
 .../protocols/modbus/readwrite/ModbusPDUError.py   |    6 +-
 .../ModbusPDUGetComEventCounterRequest.py          |    4 +-
 .../ModbusPDUGetComEventCounterResponse.py         |    6 +-
 .../readwrite/ModbusPDUGetComEventLogRequest.py    |    4 +-
 .../readwrite/ModbusPDUGetComEventLogResponse.py   |   12 +-
 .../ModbusPDUMaskWriteHoldingRegisterRequest.py    |   10 +-
 .../ModbusPDUMaskWriteHoldingRegisterResponse.py   |   10 +-
 .../modbus/readwrite/ModbusPDUReadCoilsRequest.py  |    6 +-
 .../modbus/readwrite/ModbusPDUReadCoilsResponse.py |    8 +-
 .../ModbusPDUReadDeviceIdentificationRequest.py    |    8 +-
 .../ModbusPDUReadDeviceIdentificationResponse.py   |   18 +-
 .../ModbusPDUReadDiscreteInputsRequest.py          |    6 +-
 .../ModbusPDUReadDiscreteInputsResponse.py         |   12 +-
 .../ModbusPDUReadExceptionStatusRequest.py         |    8 +-
 .../ModbusPDUReadExceptionStatusResponse.py        |    4 +-
 .../readwrite/ModbusPDUReadFifoQueueRequest.py     |    6 +-
 .../readwrite/ModbusPDUReadFifoQueueResponse.py    |   16 +-
 .../readwrite/ModbusPDUReadFileRecordRequest.py    |    8 +-
 .../ModbusPDUReadFileRecordRequestItem.py          |   18 +-
 .../readwrite/ModbusPDUReadFileRecordResponse.py   |    8 +-
 .../ModbusPDUReadFileRecordResponseItem.py         |   10 +-
 .../ModbusPDUReadHoldingRegistersRequest.py        |    6 +-
 .../ModbusPDUReadHoldingRegistersResponse.py       |    8 +-
 .../ModbusPDUReadInputRegistersRequest.py          |    6 +-
 .../ModbusPDUReadInputRegistersResponse.py         |   12 +-
 ...sPDUReadWriteMultipleHoldingRegistersRequest.py |   16 +-
 ...PDUReadWriteMultipleHoldingRegistersResponse.py |    8 +-
 .../readwrite/ModbusPDUReportServerIdRequest.py    |    4 +-
 .../readwrite/ModbusPDUReportServerIdResponse.py   |    8 +-
 .../readwrite/ModbusPDUWriteFileRecordRequest.py   |    8 +-
 .../ModbusPDUWriteFileRecordRequestItem.py         |   16 +-
 .../readwrite/ModbusPDUWriteFileRecordResponse.py  |    8 +-
 .../ModbusPDUWriteFileRecordResponseItem.py        |   16 +-
 .../ModbusPDUWriteMultipleCoilsRequest.py          |   10 +-
 .../ModbusPDUWriteMultipleCoilsResponse.py         |   10 +-
 ...odbusPDUWriteMultipleHoldingRegistersRequest.py |   10 +-
 ...dbusPDUWriteMultipleHoldingRegistersResponse.py |    6 +-
 .../readwrite/ModbusPDUWriteSingleCoilRequest.py   |    4 +-
 .../readwrite/ModbusPDUWriteSingleCoilResponse.py  |    4 +-
 .../ModbusPDUWriteSingleRegisterRequest.py         |    8 +-
 .../ModbusPDUWriteSingleRegisterResponse.py        |    4 +-
 .../protocols/modbus/readwrite/ModbusTcpADU.py     |    6 +-
 .../plc4py/protocols/umas/readwrite/ModbusPDU.py   |    8 +-
 .../protocols/umas/readwrite/ModbusPDUError.py     |    6 +-
 .../protocols/umas/readwrite/ModbusTcpADU.py       |   10 +-
 .../umas/readwrite/PlcMemoryBlockIdent.py          |    4 +-
 .../protocols/umas/readwrite/UmasConstants.py      |    2 +-
 .../umas/readwrite/UmasDatatypeReference.py        |    8 +-
 .../umas/readwrite/UmasInitCommsRequest.py         |    4 +-
 .../umas/readwrite/UmasInitCommsResponse.py        |   12 +-
 .../umas/readwrite/UmasMemoryBlockBasicInfo.py     |    4 +-
 .../plc4py/protocols/umas/readwrite/UmasPDUItem.py |   32 +-
 .../umas/readwrite/UmasPDUPlcIdentRequest.py       |    6 +-
 .../umas/readwrite/UmasPDUPlcIdentResponse.py      |   22 +-
 .../umas/readwrite/UmasPDUPlcStatusRequest.py      |    6 +-
 .../umas/readwrite/UmasPDUPlcStatusResponse.py     |   12 +-
 .../umas/readwrite/UmasPDUProjectInfoRequest.py    |    6 +-
 .../readwrite/UmasPDUReadDatatypeNamesResponse.py  |    8 +-
 .../readwrite/UmasPDUReadMemoryBlockRequest.py     |   12 +-
 .../readwrite/UmasPDUReadMemoryBlockResponse.py    |    8 +-
 .../UmasPDUReadUmasUDTDefinitionResponse.py        |    6 +-
 .../UmasPDUReadUnlocatedVariableNamesRequest.py    |   12 +-
 .../UmasPDUReadUnlocatedVariableNamesResponse.py   |    8 +-
 .../UmasPDUReadUnlocatedVariableResponse.py        |    6 +-
 .../umas/readwrite/UmasPDUReadVariableRequest.py   |   18 +-
 .../umas/readwrite/UmasPDUReadVariableResponse.py  |    6 +-
 ...leRequest.py => UmasPDUWriteVariableRequest.py} |   44 +-
 ...Response.py => UmasPDUWriteVariableResponse.py} |   32 +-
 .../protocols/umas/readwrite/UmasUDTDefinition.py  |    6 +-
 .../readwrite/UmasUnlocatedVariableReference.py    |    4 +-
 .../umas/readwrite/VariableReadRequestReference.py |  182 ++++
 .../readwrite/VariableWriteRequestReference.py     |  209 ++++
 plc4py/tests/test_plc4py.py                        |   69 +-
 .../drivers/modbus/test_modbus_connection.py       |   19 +-
 .../plc4py/drivers/umas/test_umas_connection.py    |    5 +-
 .../src/main/resources/protocols/umas/umas.mspec   |   23 +-
 93 files changed, 2283 insertions(+), 503 deletions(-)

diff --git a/code-generation/language-python/src/main/java/org/apache/plc4x/language/python/PythonLanguageOutput.java b/code-generation/language-python/src/main/java/org/apache/plc4x/language/python/PythonLanguageOutput.java
index fa187f2fd8..cf931494c4 100644
--- a/code-generation/language-python/src/main/java/org/apache/plc4x/language/python/PythonLanguageOutput.java
+++ b/code-generation/language-python/src/main/java/org/apache/plc4x/language/python/PythonLanguageOutput.java
@@ -29,43 +29,156 @@ import java.util.*;
 
 public class PythonLanguageOutput extends FreemarkerLanguageOutput {
 
+    /**
+     * Returns the name of the language, which is used for outputting the generated code.
+     *
+     * @return The name of the language.
+     */
     @Override
     public String getName() {
         return "Python";
     }
 
+    /**
+     * Returns a set of options that are supported by this language output flavor.
+     * Options are key-value pairs that can be passed to the code generator to customize the generated code.
+     *
+     * @return A set of supported options.
+     */
     @Override
     public Set<String> supportedOptions() {
         return Collections.singleton("package");
     }
 
+
+    /**
+     * Returns a list of output flavors that are supported by this language output flavor.
+     * An output flavor is a customization option that can be passed to the code generator to
+     * produce code for a specific use case.
+     *
+     * @return A list of supported output flavors.
+     */
     @Override
     public List<String> supportedOutputFlavors() {
         return Arrays.asList("read-write", "read-only", "passive");
     }
 
+    /**
+     * Returns a list of templates that are used to generate a specification of the generated code.
+     * The specification is usually a markdown file that contains information about the structure of the
+     * generated code, such as method signatures, comments, and so on.
+     *
+     * @return A list of templates that are used to generate the specification.
+     */
     @Override
     protected List<Template> getSpecTemplates(Configuration freemarkerConfiguration) {
+        /**
+         * Python does not need a spec as it generates the code directly for the user.
+         * Therefore, this method returns an empty list.
+         */
         return Collections.emptyList();
     }
 
+    /**
+     * Returns a list of templates that are used to generate code for a complex type.
+     * A complex type is a type that is composed of multiple fields.
+     *
+     * @param freemarkerConfiguration The configuration of the FreeMarker engine.
+     * @return A list of templates that are used to generate code for a complex type.
+     * @throws IOException Thrown if an error occurs while reading a template file.
+     */
     @Override
     protected List<Template> getComplexTypeTemplates(Configuration freemarkerConfiguration) throws IOException {
+        /**
+         * The template used to generate code for a complex type is currently a single file.
+         * The template is stored at 'templates/python/complex-type-template.python.ftlh'.
+         *
+         * The template is used to generate code for a complex type by passing the complex type
+         * object as a variable named 'type' to the template.
+         *
+         * The template is also passed information about the fields of the complex type,
+         * such as their names, types and so on.
+         */
         return List.of(freemarkerConfiguration.getTemplate("templates/python/complex-type-template.python.ftlh"));
     }
 
+    /**
+     * Returns a list of templates that are used to generate code for an enumeration type.
+     * An enumeration type is a type that is composed of a set of constants.
+     *
+     * @param freemarkerConfiguration The configuration of the FreeMarker engine.
+     * @return A list of templates that are used to generate code for an enumeration type.
+     * @throws IOException Thrown if an error occurs while reading a template file.
+     */
     @Override
     protected List<Template> getEnumTypeTemplates(Configuration freemarkerConfiguration) throws IOException {
+        /**
+         * The template used to generate code for an enumeration type is currently a single file.
+         * The template is stored at 'templates/python/enum-template.python.ftlh'.
+         *
+         * The template is used to generate code for an enumeration type by passing the enumeration type
+         * object as a variable named 'type' to the template.
+         *
+         * The template is also passed information about the constants of the enumeration type,
+         * such as their names and so on.
+         */
         return Collections.singletonList(
             freemarkerConfiguration.getTemplate("templates/python/enum-template.python.ftlh"));
     }
 
+    /**
+     * Returns a list of templates that are used to generate code for a data IO class.
+     *
+     * A data IO class is a class that is responsible for reading and/or writing
+     * a specific type of data from and/or to a PLC (Programmable Logic Controller).
+     *
+     * The templates are used to generate code for a data IO class by passing the
+     * type of data that is being read and/or written as a variable named 'type'
+     * to the templates.
+     *
+     * The templates are also passed information about the fields of the type
+     * that is being read and/or written, such as their names, types and so on.
+     *
+     * @param freemarkerConfiguration The configuration of the FreeMarker engine.
+     * @return A list of templates that are used to generate code for a data IO class.
+     * @throws IOException Thrown if an error occurs while reading a template file.
+     */
     @Override
     protected List<Template> getDataIoTemplates(Configuration freemarkerConfiguration) throws IOException {
+        /**
+         * The template used to generate code for a data IO class is currently a single file.
+         * The template is stored at 'templates/python/data-io-template.python.ftlh'.
+         *
+         * The template is used to generate code for a data IO class by passing the
+         * type of data that is being read and/or written as a variable named 'type' to the
+         * template.
+         *
+         * The template is also passed information about the fields of the type
+         * that is being read and/or written, such as their names, types and so on.
+         */
         return Collections.singletonList(
             freemarkerConfiguration.getTemplate("templates/python/data-io-template.python.ftlh"));
     }
 
+    /**
+     * Returns an instance of a helper class that is used by the code generation
+     * templates to generate code.
+     *
+     * The helper class is responsible for generating code that is dependent on the
+     * language and the type of code being generated (e.g. data IO, enum, etc.).
+     *
+     * The helper class is also responsible for generating code that is dependent on
+     * the PLC protocol that is being generated code for.
+     *
+     * @param thisType     The type that is being generated code for.
+     * @param protocolName The name of the PLC protocol that the code is being generated
+     *                     for.
+     * @param flavorName  The name of the code generation flavor that the code is being
+     *                     generated for.
+     * @param types        A map of type definitions.
+     * @param options      A map of options that are passed to the code generator.
+     * @return An instance of a helper class.
+     */
     @Override
     protected FreemarkerLanguageTemplateHelper getHelper(TypeDefinition thisType, String protocolName, String flavorName, Map<String, TypeDefinition> types,
                                                          Map<String, String> options) {
diff --git a/code-generation/language-python/src/main/java/org/apache/plc4x/language/python/PythonLanguageTemplateHelper.java b/code-generation/language-python/src/main/java/org/apache/plc4x/language/python/PythonLanguageTemplateHelper.java
index 671de9eeca..c66537bc40 100644
--- a/code-generation/language-python/src/main/java/org/apache/plc4x/language/python/PythonLanguageTemplateHelper.java
+++ b/code-generation/language-python/src/main/java/org/apache/plc4x/language/python/PythonLanguageTemplateHelper.java
@@ -52,18 +52,59 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         super(thisType, protocolName, flavorName, types);
     }
 
+    /**
+     * Returns a file name for a generated Python file.
+     *
+     * The file name is constructed by taking the sanitized protocol name and
+     * the language flavor name and concatenating them with a dot in between.
+     *
+     * @param protocolName the name of the protocol
+     * @param languageName the name of the language
+     * @param languageFlavorName the name of the language flavor
+     * @return the file name for the generated Python file
+     */
     public String fileName(String protocolName, String languageName, String languageFlavorName) {
         return String.join("", protocolName.split("\\-")) + "." +
             String.join("", languageFlavorName.split("\\-"));
     }
 
+    /**
+     * Returns a sanitized version of the protocol name.
+     *
+     * The protocol name is used to construct the package name and is thus
+     * subject to a set of constraints:
+     *
+     * - It must only contain valid Java identifier characters.
+     * - It must not contain any periods.
+     *
+     * This method will replace all periods with forward slashes, convert to
+     * lower case and remove any dashes.
+     *
+     * @return a sanitized version of the protocol name
+     */
     public String getSanitizedPackageName() {
         String sanitizedName = getProtocolName().replaceAll("-", "");
+        // replace periods with forward slashes
         sanitizedName = sanitizedName.replaceAll("\\.", "/");
+        // convert to lower case
         sanitizedName = sanitizedName.toLowerCase();
         return sanitizedName;
     }
 
+    /**
+     * Returns a sanitized version of the protocol name.
+     *
+     * The protocol name is used to construct the package name and is thus
+     * subject to a set of constraints:
+     *
+     * - It must only contain valid Java identifier characters.
+     * - It must not contain any periods.
+     *
+     * This method takes the protocol name and removes any hyphens, and then
+     * converts the resulting string to camel case.
+     *
+     * @return the sanitized protocol name
+     */
     // TODO: check if protocol name can be enforced to only contain valid chars
     public String getSanitizedProtocolName() {
         String sanitizedName = getProtocolName().replaceAll("-", "");
@@ -71,6 +112,14 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return sanitizedName;
     }
 
+    /**
+     * Returns the package name for the generated code.
+     *
+     * The package name is composed of the sanitized protocol name, the language name
+     * ("python"), and the sanitized language flavor name.
+     *
+     * @return the package name.
+     */
     public String packageName() {
         return packageName(protocolName, "python", flavorName);
     }
@@ -103,15 +152,46 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return getLanguageTypeNameForTypeReference(typedField.getType(), encoding);
     }
 
+    /**
+     * Checks whether the given field is a complex field.
+     * <p>
+     * A complex field is a field which has a type which is not a simple type (like int or boolean).
+     * A complex type is a type which is not a primitive type and is not a {@link ComplexTypeReference}.
+     * Examples of complex types are {@link java.util.List}, {@link java.util.Map}, etc.
+     * @param field the field to check
+     * @return true if the field is a complex field, false otherwise
+     */
     public boolean isComplex(Field field) {
         return field instanceof PropertyField && ((PropertyField) field).getType() instanceof NonSimpleTypeReference;
     }
 
+    /**
+     * Returns the language type name for a given type reference.
+     * <p>
+     * This method is used in the generated code to generate type names for fields. The returned type name
+     * is the name of the type as it should be used in the generated code. If the type is a primitive
+     * type, the returned type name is usually more specific and will indicate that a
+     * com.plc4x.common.value.Value of the corresponding type should be used.
+     * @param typeReference the type reference to get the language type name for
+     * @return the language type name for the given type reference
+     */
     @Override
     public String getLanguageTypeNameForTypeReference(TypeReference typeReference) {
         return getLanguageTypeNameForTypeReference(typeReference, null);
     }
 
+    /**
+     * Get the language name for a given field, but return a non-primitive type name if the type is a
+     * primitive type.
+     *
+     * This method is used in the generated code to generate type names for fields. If the type is a
+     * primitive type, the returned type name is not the same as the one returned by
+     * {@link #getLanguageTypeNameForField(Field) getLanguageTypeNameForField}. Instead, the returned
+     * type name is usually more specific and will indicate that a complex type is expected.
+     *
+     * @param field the field to get the language name for
+     * @return the language name for the field
+     */
     public String getNonPrimitiveLanguageTypeNameForField(TypedField field) {
         return getLanguageTypeNameForTypeReference(field.getType(), false);
     }
@@ -120,79 +200,117 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return getLanguageTypeNameForTypeReference(typeReference, null);
     }
 
+    /**
+     * Get the language name for a given type reference.
+     * This method is used to generate code for type references
+     * in the generated code.
+     *
+     * @param typeReference the type reference for which the language name should be generated
+     * @param encoding the encoding for the type reference, if applicable
+     * @return the language name for the given type reference
+     */
     public String getLanguageTypeNameForTypeReference(TypeReference typeReference, String encoding) {
         if (typeReference == null) {
             // TODO: shouldn't this be an error case
             return "";
         }
         if (typeReference.isArrayTypeReference()) {
+            // We can use the array type reference to generate code for the type of the array.
             final ArrayTypeReference arrayTypeReference = (ArrayTypeReference) typeReference;
             TypeReference elementTypeReference = arrayTypeReference.getElementTypeReference();
             emitRequiredImport("from typing import List");
+            // We use List to represent an array in python, as the type system doesn't support arrays.
+            // We also use the name of the element type as the type parameter.
             return "List[" + getLanguageTypeNameForTypeReference(elementTypeReference) + "]";
         }
         if (typeReference.isNonSimpleTypeReference()) {
+            // We have a complex type, such as a data io type or a custom type.
             emitRequiredImport("from plc4py.protocols." + protocolName + "." + flavorName.replace("-", "") + "." + typeReference.asNonSimpleTypeReference().orElseThrow().getName() + " import " + typeReference.asNonSimpleTypeReference().orElseThrow().getName());
+            // We import the name of the complex type, and then use the name of the complex type as the type name.
             return typeReference.asNonSimpleTypeReference().orElseThrow().getName();
         }
         if (typeReference instanceof ByteOrderTypeReference) {
-            return "binary.byteOrder";
+            // Byte order is represented by a class in the protocol, so we import that class and use its name as the type name.
+            return "binary.ByteOrder";
         }
         SimpleTypeReference simpleTypeReference = typeReference.asSimpleTypeReference().orElseThrow();
         switch (simpleTypeReference.getBaseType()) {
             case BIT:
+                // Bit is represented by a boolean in python.
                 return "bool";
             case BYTE:
+                // Byte is represented by an integer in python.
                 return "int";
             case UINT:
+                // Unsigned integer is represented by an integer in python, with the appropriate size.
                 IntegerTypeReference unsignedIntegerTypeReference = simpleTypeReference.asIntegerTypeReference().orElseThrow();
-                if (unsignedIntegerTypeReference.getSizeInBits() <= 8) {
+                int sizeInBits = unsignedIntegerTypeReference.getSizeInBits();
+                if (sizeInBits <= 8) {
+                    // Size <= 8 bit is represented by an int in python.
                     return "int";
                 }
-                if (unsignedIntegerTypeReference.getSizeInBits() <= 16) {
+                if (sizeInBits <= 16) {
+                    // Size <= 16 bit is represented by an int in python.
                     return "int";
                 }
-                if (unsignedIntegerTypeReference.getSizeInBits() <= 32) {
+                if (sizeInBits <= 32) {
+                    // Size <= 32 bit is represented by an int in python.
                     return "int";
                 }
-                if (unsignedIntegerTypeReference.getSizeInBits() <= 64) {
+                if (sizeInBits <= 64) {
+                    // Size <= 64 bit is represented by an int in python.
                     return "int";
                 }
-                return "int";
+                // Size > 64 bit is not supported in python.
+                throw new UnsupportedOperationException("Size > 64 bit is not supported in python");
             case INT:
+                // Integer is represented by an integer in python, with the appropriate size.
                 IntegerTypeReference integerTypeReference = simpleTypeReference.asIntegerTypeReference().orElseThrow();
-                if (integerTypeReference.getSizeInBits() <= 8) {
+                int sizeInIntegerBits = integerTypeReference.getSizeInBits();
+                if (sizeInIntegerBits <= 8) {
+                    // Size <= 8 bit is represented by an int in python.
                     return "int";
                 }
-                if (integerTypeReference.getSizeInBits() <= 16) {
+                if (sizeInIntegerBits <= 16) {
+                    // Size <= 16 bit is represented by an int in python.
                     return "int";
                 }
-                if (integerTypeReference.getSizeInBits() <= 32) {
+                if (sizeInIntegerBits <= 32) {
+                    // Size <= 32 bit is represented by an int in python.
                     return "int";
                 }
-                if (integerTypeReference.getSizeInBits() <= 64) {
+                if (sizeInIntegerBits <= 64) {
+                    // Size <= 64 bit is represented by an int in python.
                     return "int";
                 }
-                return "int";
+                // Size > 64 bit is not supported in python.
+                throw new UnsupportedOperationException("Size > 64 bit is not supported in python");
             case FLOAT:
             case UFLOAT:
+                // Float is represented by a float in python, with the appropriate size.
                 FloatTypeReference floatTypeReference = simpleTypeReference.asFloatTypeReference().orElseThrow();
-                int sizeInBits = floatTypeReference.getSizeInBits();
-                if (sizeInBits <= 32) {
+                int sizeInFloatBits = floatTypeReference.getSizeInBits();
+                if (sizeInFloatBits <= 32) {
+                    // Size <= 32 bit is represented by a float in python.
                     return "float";
                 }
-                if (sizeInBits <= 64) {
+                if (sizeInFloatBits <= 64) {
+                    // Size <= 64 bit is represented by a float in python.
                     return "float";
                 }
-                return "float";
+                // Size > 64 bit is not supported in python.
+                throw new UnsupportedOperationException("Size > 64 bit is not supported in python");
             case STRING:
             case VSTRING:
+                // String is represented by a str in python.
                 return "str";
             case TIME:
             case DATE:
             case DATETIME:
-                return "time.Time";
+                // Time is represented by a datetime in python.
+                return "datetime";
             default:
+                // For all other types, an error should be thrown.
                 throw new FreemarkerException("Unsupported simple type");
         }
     }
@@ -202,16 +320,28 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return languageTypeName + "(" + reservedField.getReferenceValue() + ")";
     }
 
+    /**
+     * Generate code for options of a field, such as encoding and byte order.
+     * 
+     * @param field The field for which the options should be generated
+     * @param parserArguments The arguments of the parser, which may contain
+     * information about the encoding and byte order.
+     * @return A string containing the options, or an empty string if no options
+     * are needed.
+     */
     public String getFieldOptions(TypedField field, List<Argument> parserArguments) {
         StringBuilder sb = new StringBuilder();
+        // If the field has an encoding, add it as an option.
         final Optional<Term> encodingOptional = field.getEncoding();
         if (encodingOptional.isPresent()) {
             final String encoding = toParseExpression(field, field.getType(), encodingOptional.get(), parserArguments);
             sb.append(", encoding='").append(encoding).append("'");
         }
+        // If the field has a byte order, add it as an option.
         final Optional<Term> byteOrderOptional = field.getByteOrder();
         if (byteOrderOptional.isPresent()) {
             final String byteOrder = toParseExpression(field, field.getType(), byteOrderOptional.get(), parserArguments);
+            // We need to import the ByteOrder class, so add an import statement.
             emitRequiredImport("from plc4py.utils.GenericTypes import ByteOrder");
             sb.append(", byte_order=ByteOrder.").append(byteOrder);
         }
@@ -266,6 +396,15 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         }
     }
 
+    /**
+     * Returns the name of the Python data reader method that should be used to read a value of the given type.
+     *
+     * <p>
+     * This method is used to generate code for converting a type reference to a PLC4Py type name.
+     *
+     * @param simpleTypeReference the type reference to get the PLC4Py type name for
+     * @return the name of the Python data reader method
+     */
     public String getDataReaderCall(SimpleTypeReference simpleTypeReference) {
         final int sizeInBits = simpleTypeReference.getSizeInBits();
         switch (simpleTypeReference.getBaseType()) {
@@ -301,21 +440,57 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
                 throw new UnsupportedOperationException("Unsupported type " + simpleTypeReference.getBaseType());
         }
     }
+    /**
+     * Returns the name of the Python data writer method that should be used to write a value of the given type.
+     *
+     * <p>
+     * This method is used to generate code for converting a type reference to a PLC4Py type name.
+     *
+     * @param typeReference the type reference to get the PLC4Py type name for
+     * @param fieldName the name of the field to write
+     * @return the name of the Python data writer method
+     */
 
+    /**
+     * Returns the name of the Python data writer method that should be used to write a value of the given type.
+     *
+     * <p>
+     * This method is used to generate code for converting a type reference to a PLC4Py type name.
+     *
+     * @param typeReference the type reference to get the PLC4Py type name for
+     * @param fieldName the name of the field to write
+     * @return the name of the Python data writer method
+     */
     public String getDataWriterCall(TypeReference typeReference, String fieldName) {
         if (typeReference.isSimpleTypeReference()) {
-            SimpleTypeReference simpleTypeReference = typeReference.asSimpleTypeReference().orElseThrow(IllegalStateException::new);
-            return getDataWriterCall(simpleTypeReference);
+            // The type is a simple type, such as a byte or int.
+            // We can directly use the methods provided by the simple type.
+            return getDataWriterCall(typeReference.asSimpleTypeReference().orElseThrow());
         } else if (typeReference.isArrayTypeReference()) {
-            final ArrayTypeReference arrayTypeReference = typeReference.asArrayTypeReference().orElseThrow();
-            return getDataWriterCall(arrayTypeReference.getElementTypeReference(), fieldName);
+            // The type is an array, such as an array of bytes or an array of strings.
+            // We need to recursively call getDataWriterCall to determine the name of the PLC4Py
+            // type name for the element type of the array.
+            return getDataWriterCall(typeReference.asArrayTypeReference().orElseThrow().getElementTypeReference(), fieldName);
         } else if (typeReference.isComplexTypeReference()) {
+            // The type is a complex type, such as a struct.
+            // We can directly use the write_serializable method.
             return "write_serializable";
         } else {
             throw new IllegalStateException("What is this type? " + typeReference);
         }
     }
 
+    /**
+     * Returns the name of the Python data writer method that should be used to write a value of the given enum type.
+     *
+     * <p>
+     * This method is used to generate code for converting a type reference to a PLC4Py type name.
+     *
+     * @param typeReference the enum type reference to get the PLC4Py type name for
+     * @param fieldName the name of the field to write
+     * @param attributeName the name of the enum attribute to write, defaults to "value"
+     * @return the PLC4Py type name or an empty string if the type reference is not supported
+     */
     public String getEnumDataWriterCall(EnumTypeReference typeReference, String fieldName, String attributeName) {
         if (!typeReference.isEnumTypeReference()) {
             throw new IllegalArgumentException("this method should only be called for enum types");
@@ -330,6 +505,16 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return getDataWriterCall(outputTypeReference, fieldName);
     }
 
+    /**
+     * Returns the name of the Python data writer method that should be used to write a value of the given type.
+     *
+     * <p>
+     * This method is used to generate code for converting a type reference to a PLC4Py type name.
+     *
+     * @param simpleTypeReference the type reference to get the PLC4Py type name for
+     *
+     * @return the PLC4Py type name or an empty string if the type reference is not supported
+     */
     public String getDataWriterCall(SimpleTypeReference simpleTypeReference) {
         final int sizeInBits = simpleTypeReference.getSizeInBits();
         switch (simpleTypeReference.getBaseType()) {
@@ -353,6 +538,7 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
             case STRING:
                 return "write_str";
             case VSTRING:
+                // Vstring is serialized as string
                 VstringTypeReference vstringTypeReference = (VstringTypeReference) simpleTypeReference;
                 return "write_str";
             case TIME:
@@ -366,6 +552,16 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         }
     }
 
+    /**
+     * Returns the name of the PLC4Py value type that corresponds to the given type reference.
+     * 
+     * <p>
+     * This method is used to generate code for converting a type reference to a PLC4Py type name.
+     * 
+     * @param typeReference the type reference to get the PLC4Py type name for
+     * 
+     * @return the PLC4Py type name or an empty string if the type reference is not supported
+     */
     public String getPlcValueTypeForTypeReference(TypeReference typeReference) {
         if (typeReference == null) {
             // TODO: shouldn't this be an error case
@@ -377,67 +573,80 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         SimpleTypeReference simpleTypeReference = (SimpleTypeReference) typeReference;
         switch (simpleTypeReference.getBaseType()) {
             case BIT:
+                // Bit values are represented as boolean in PLC4Py
                 emitRequiredImport("from plc4py.spi.values.PlcValues import PlcBOOL");
                 return "PlcBOOL";
             case BYTE:
+                // Byte values are represented as signed integers in PLC4Py
                 emitRequiredImport("from plc4py.spi.values.PlcValues import PlcSINT");
                 return "PlcSINT";
             case UINT:
                 IntegerTypeReference unsignedIntegerTypeReference = (IntegerTypeReference) simpleTypeReference;
                 if (unsignedIntegerTypeReference.getSizeInBits() <= 4) {
+                    // Ubyte values are represented as unsigned short integers in PLC4Py
                     emitRequiredImport("from plc4py.spi.values.PlcValues import PlcUSINT");
                     return "PlcUSINT";
                 }
                 if (unsignedIntegerTypeReference.getSizeInBits() <= 8) {
+                    // Uword values are represented as unsigned integers in PLC4Py
                     emitRequiredImport("from plc4py.spi.values.PlcValues import PlcUINT");
                     return "PlcUINT";
                 }
                 if (unsignedIntegerTypeReference.getSizeInBits() <= 16) {
+                    // Uword16 values are represented as unsigned long integers in PLC4Py
                     emitRequiredImport("from plc4py.spi.values.PlcValues import PlcUDINT");
                     return "PlcUDINT";
                 }
                 if (unsignedIntegerTypeReference.getSizeInBits() <= 32) {
+                    // Uword32 values are represented as unsigned long long integers in PLC4Py
                     emitRequiredImport("from plc4py.spi.values.PlcValues import PlcULINT");
                     return "PlcULINT";
                 }
             case INT:
                 IntegerTypeReference integerTypeReference = (IntegerTypeReference) simpleTypeReference;
                 if (integerTypeReference.getSizeInBits() <= 8) {
+                    // Byte values are represented as signed integers in PLC4Py
                     emitRequiredImport("from plc4py.spi.values.PlcValues import PlcSINT");
                     return "PlcSINT";
                 }
                 if (integerTypeReference.getSizeInBits() <= 16) {
+                    // Word values are represented as signed long integers in PLC4Py
                     emitRequiredImport("from plc4py.spi.values.PlcValues import PlcINT");
                     return "PlcINT";
                 }
                 if (integerTypeReference.getSizeInBits() <= 32) {
+                    // Dword values are represented as signed long long integers in PLC4Py
                     emitRequiredImport("from plc4py.spi.values.PlcValues import PlcDINT");
                     return "PlcDINT";
                 }
                 if (integerTypeReference.getSizeInBits() <= 64) {
+                    // Lword values are represented as signed long long integers in PLC4Py
                     emitRequiredImport("from plc4py.spi.values.PlcValues import PlcLINT");
                     return "PlcLINT";
                 }
-
             case FLOAT:
             case UFLOAT:
                 FloatTypeReference floatTypeReference = (FloatTypeReference) simpleTypeReference;
                 int sizeInBits = floatTypeReference.getSizeInBits();
                 if (sizeInBits <= 32) {
+                    // Float values are represented as float in PLC4Py
                     emitRequiredImport("from plc4py.spi.values.PlcValues import PlcREAL");
                     return "PlcREAL";
                 }
                 if (sizeInBits <= 64) {
+                    // Double values are represented as double in PLC4Py
                     emitRequiredImport("from plc4py.spi.values.PlcValues import PlcLREAL");
                     return "PlcLREAL";
                 }
             case STRING:
             case VSTRING:
+                // String values are represented as a string in PLC4Py
                 emitRequiredImport("from plc4py.spi.values.PlcValues import PlcSTRING");
                 return "PlcSTRING";
             case TIME:
             case DATE:
             case DATETIME:
+                // Time values are represented as a time in PLC4Py
                 emitRequiredImport("from plc4py.spi.values.PlcValues import PlcTIME");
                 return "PlcTIME";
             default:
@@ -445,62 +654,131 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         }
     }
 
+    /**
+     * Returns the null value for the given type reference.
+     * 
+     * <p>
+     * This method is used to generate code for accessing the null value of a type.
+     * The null value is returned as a string that can be used directly in Python
+     * code.
+     * 
+     * @param typeReference the type reference to get the null value for
+     * @return the null value for the given type reference
+     */
     @Override
     public String getNullValueForTypeReference(TypeReference typeReference) {
         if (typeReference instanceof SimpleTypeReference) {
             SimpleTypeReference simpleTypeReference = (SimpleTypeReference) typeReference;
             switch (simpleTypeReference.getBaseType()) {
                 case BIT:
+                    // Boolean type: False is the null value
                     return "False";
                 case BYTE:
                 case UINT:
                 case INT:
+                    // Integer types: 0 is the null value
                     return "0";
                 case FLOAT:
+                    // Float types: 0.0 is the null value
                     return "0.0";
                 case STRING:
                 case VSTRING:
+                    // String types: an empty string is the null value
                     return "\"\"";
             }
         } else if (typeReference.isEnumTypeReference()) {
+            // Enum types: 0 is the null value
             return "0";
         }
+        // For all other types, return None as the null value
         return "None";
     }
+    
 
+    /**
+     * Returns the number of bits for the given simple type reference.
+     * 
+     * @param simpleTypeReference the simple type reference to get the number of bits for
+     * @return the number of bits for the given simple type reference
+     */
     public int getNumBits(SimpleTypeReference simpleTypeReference) {
         switch (simpleTypeReference.getBaseType()) {
             case BIT:
+                // bit is always 1 bit
                 return 1;
             case BYTE:
+                // byte is always 8 bits
                 return 8;
             case UINT:
             case INT:
+                // integer type references have a variable number of bits depending on the
+                // size specified by the type reference
                 IntegerTypeReference integerTypeReference = (IntegerTypeReference) simpleTypeReference;
                 return integerTypeReference.getSizeInBits();
             case FLOAT:
+                // float type references have a variable number of bits depending on the
+                // precision specified by the type reference
                 FloatTypeReference floatTypeReference = (FloatTypeReference) simpleTypeReference;
                 return floatTypeReference.getSizeInBits();
             case STRING:
             case VSTRING:
+                // string type references have a variable number of bits depending on the
+                // length of the string
                 StringTypeReference stringTypeReference = (StringTypeReference) simpleTypeReference;
                 return stringTypeReference.getSizeInBits();
             default:
+                // for all other types, return 0 as there is no meaningfull number of bits
                 return 0;
         }
     }
 
+    /**
+     * Returns true if the given property field needs pointer access or not.
+     * 
+     * <p>
+     * This method returns true if the property field has an optional attribute and its type reference
+     * needs pointer access or not. This is the case if the type reference is not a complex type reference
+     * and the type reference is not an array type reference or if the array type reference has an
+     * element type reference that is not a complex type reference.
+     * 
+     * @param field the property field to check
+     * @return true if the property field needs pointer access, false otherwise
+     */
     public boolean needsPointerAccess(PropertyField field) {
         boolean isAnTypeOfOptional = "optional".equals(field.getTypeName());
         return isAnTypeOfOptional && needPointerAccess(field.getType());
     }
 
+    /**
+     * Returns true if the given type reference needs pointer access or not. This
+     * method is used to determine whether the generated code needs to use a
+     * pointer for accessing data of the given type.
+     *
+     * <p>
+     * This method returns true if the type reference is not a complex type reference
+     * and the type reference is not an array type reference or if the array type
+     * reference has an element type reference that is not a complex type reference.
+     *
+     * @param typeReference the type reference to check
+     * @return true if the type reference needs pointer access, false otherwise
+     */
     public boolean needPointerAccess(TypeReference typeReference) {
         boolean isNotAnComplexTypeReference = !typeReference.isComplexTypeReference();
         boolean arrayTypeIsNotAnComplexTypeReference = !(typeReference.isArrayTypeReference() && typeReference.asArrayTypeReference().orElseThrow().getElementTypeReference().isComplexTypeReference());
         return isNotAnComplexTypeReference && arrayTypeIsNotAnComplexTypeReference;
     }
 
+    /**
+     * Gets a special read buffer read method call for a simple type reference and a typed field.
+     * The method is a convenience method that is used to call one of the read buffer methods depending
+     * on the type of the field. The method is used to generate code for reading data from a buffer.
+     *
+     * @param logicalName the logical name of the field
+     * @param simpleTypeReference the simple type reference of the field
+     * @param parserArguments the parser arguments used for the field
+     * @param field the typed field
+     * @return a string representing the read buffer read method call
+     */
     public String getSpecialReadBufferReadMethodCall(String logicalName, SimpleTypeReference simpleTypeReference, TypedField field) {
         return getReadBufferReadMethodCall(logicalName, simpleTypeReference, null, field);
     }
@@ -509,11 +787,22 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return getReadBufferReadMethodCall(logicalName, simpleTypeReference, null, field);
     }
 
+    /**
+     * Gets a read buffer read method call for a simple type reference and a typed field.
+     * The method will handle cases where the value string is present and in other cases it will default to the read buffer read method call without any arguments.
+     *
+     * @param logicalName the logical name of the field
+     * @param simpleTypeReference the simple type reference of the field
+     * @param valueString the value string to be passed to the read buffer read method call
+     * @param field the typed field
+     * @return the read buffer read method call
+     */
     @Override
     public String getReadBufferReadMethodCall(SimpleTypeReference simpleTypeReference, String valueString, TypedField field) {
         return getReadBufferReadMethodCall("", simpleTypeReference, valueString, field);
     }
 
+
     public String getReadBufferReadMethodCall(String logicalName, SimpleTypeReference simpleTypeReference, String valueString, TypedField field) {
         switch (simpleTypeReference.getBaseType()) {
             case BIT:
@@ -685,31 +974,85 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return tracer + toTypedParseExpression(field, resultType, term, parserArguments);
     }
 
+    /**
+     * Returns a Python expression that represents the given term parsed according to the given type reference.
+     *
+     * @param field the field of the given type reference
+     * @param resultType the type reference of the given data
+     * @param term the term to parse
+     * @param parserArguments the parser arguments
+     * @param suppressPointerAccess whether to suppress pointer access
+     * @return a Python expression representing the parsed term
+     */
     public String toParseExpression(Field field, TypeReference resultType, Term term, List<Argument> parserArguments, boolean suppressPointerAccess) {
         Tracer tracer = pythonTracerStart("toParseExpression");
         return tracer + toTypedParseExpression(field, resultType, term, parserArguments, suppressPointerAccess);
     }
 
+    /**
+     * Returns a Python expression that represents the given term serialized according to the given type reference.
+     *
+     * @param field the field of the given type reference
+     * @param resultType the type reference of the given data
+     * @param term the term to serialize
+     * @param serializerArguments the serializer arguments
+     * @return a Python expression representing the serialized term
+     */
     public String toSerializationExpression(Field field, TypeReference resultType, Term term, List<Argument> serializerArguments) {
         Tracer tracer = pythonTracerStart("toSerializationExpression");
         return tracer + toTypedSerializationExpression(field, resultType, term, serializerArguments);
     }
 
+    /**
+     * Returns a Python expression that represents the given term parsed according to the given type reference.
+     *
+     * @param field the field of the given type reference
+     * @param term the term to parse
+     * @param parserArguments the parser arguments
+     * @return a Python expression representing the parsed term
+     */
     public String toBooleanParseExpression(Field field, Term term, List<Argument> parserArguments) {
         Tracer tracer = pythonTracerStart("toBooleanParseExpression");
         return tracer + toTypedParseExpression(field, new DefaultBooleanTypeReference(), term, parserArguments);
     }
 
+    /**
+     * Returns a Python expression that represents the given term serialized according to the given type reference.
+     *
+     * @param field the field of the given type reference
+     * @param term the term to serialize
+     * @param serializerArguments the serializer arguments
+     * @return a Python expression representing the serialized term
+     */
     public String toBooleanSerializationExpression(Field field, Term term, List<Argument> serializerArguments) {
         Tracer tracer = pythonTracerStart("toBooleanSerializationExpression");
         return tracer + toTypedSerializationExpression(field, new DefaultBooleanTypeReference(), term, serializerArguments);
     }
 
+    /**
+     * Returns a Python expression that represents the given term parsed according to the given type reference.
+     *
+     * @param field the field of the given type reference
+     * @param sizeInBits the size of the integer in bits
+     * @param term the term to parse
+     * @param parserArguments the parser arguments
+     * @return a Python expression representing the parsed term
+     */
     public String toIntegerParseExpression(Field field, int sizeInBits, Term term, List<Argument> parserArguments) {
         Tracer tracer = pythonTracerStart("toIntegerParseExpression");
         return tracer + toTypedParseExpression(field, new DefaultIntegerTypeReference(SimpleTypeReference.SimpleBaseType.UINT, sizeInBits), term, parserArguments);
     }
 
+
+    /**
+     * Returns a Python expression that represents the given term serialized according to the given type reference.
+     *
+     * @param field the field of the given type reference
+     * @param sizeInBits the size of the integer in bits
+     * @param term the term to serialize
+     * @param serializerArguments the serializer arguments
+     * @return a Python expression representing the serialized term
+     */
     public String toIntegerSerializationExpression(Field field, int sizeInBits, Term term, List<Argument> serializerArguments) {
         Tracer tracer = pythonTracerStart("toIntegerSerializationExpression");
         return tracer + toTypedSerializationExpression(field, new DefaultIntegerTypeReference(SimpleTypeReference.SimpleBaseType.UINT, sizeInBits), term, serializerArguments);
@@ -720,30 +1063,82 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return tracer + toExpression(field, fieldType, term, parserArguments, null, false, fieldType != null && fieldType.isComplexTypeReference());
     }
 
+    /**
+     * Returns a Python expression that represents the given term parsed according to the given type reference.
+     *
+     * @param field the field of the given type reference
+     * @param fieldType the type reference of the given data
+     * @param term the term to parse
+     * @param parserArguments the parser arguments
+     * @param suppressPointerAccess whether to suppress pointer access
+     * @return a Python expression representing the parsed term
+     */
     public String toTypedParseExpression(Field field, TypeReference fieldType, Term term, List<Argument> parserArguments, boolean suppressPointerAccess) {
         Tracer tracer = pythonTracerStart("toTypedParseExpression");
         return tracer + toExpression(field, fieldType, term, parserArguments, null, false, suppressPointerAccess);
     }
 
+    /**
+     * Returns a Python expression that represents the given term serialized according to
+     * the given type reference.
+     *
+     * @param field the field of the given type reference
+     * @param fieldType the type reference of the given data
+     * @param term the term to serialize
+     * @param serializerArguments the serializer arguments
+     * @return a Python expression representing the serialized term
+     */
     public String toTypedSerializationExpression(Field field, TypeReference fieldType, Term term, List<Argument> serializerArguments) {
         Tracer tracer = pythonTracerStart("toTypedSerializationExpression");
         return tracer + toExpression(field, fieldType, term, null, serializerArguments, true, false);
     }
 
-    String getCastExpressionForTypeReference(TypeReference typeReference) {
+    /**
+     * Returns a Python expression that represents a cast operation for the given
+     * type reference.
+     *
+     * @param typeReference the type reference to cast the data to
+     * @return a Python expression representing the cast operation
+     */
+    private String getCastExpressionForTypeReference(TypeReference typeReference) {
         Tracer tracer = pythonTracerStart("castExpression");
         if (typeReference instanceof SimpleTypeReference) {
+            // Simple type reference, just use the language name
+            // e.g. int, char, etc.
             return tracer.dive("simpleTypeRef") + getLanguageTypeNameForTypeReference(typeReference);
         } else if (typeReference instanceof ByteOrderTypeReference) {
+            // Byte order, use the binary.ByteOrder enum
             return tracer.dive( "byteOrderTypeRef") + "binary.ByteOrder";
         } else if (typeReference != null) {
+            // Complex type reference, use the Cast class
+            // e.g. Cast[int], Cast[Char], etc.
             return tracer.dive("anyTypeRef") + "Cast" + getLanguageTypeNameForTypeReference(typeReference);
         } else {
+            // No type reference, return an empty string
             return tracer.dive("noTypeRef") + "";
         }
     }
 
-    private String toExpression(Field field, TypeReference fieldType, Term term, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess) {
+    /**
+     * Returns a Python expression that represents the given term.
+     *
+     * @param field the field of the given type reference
+     * @param fieldType the type reference of the given data
+     * @param term the term to represent
+     * @param parserArguments the parser arguments
+     * @param serializerArguments the serializer arguments
+     * @param serialize whether the data is serialized
+     * @param suppressPointerAccess whether to suppress pointer access
+     * @return a Python expression
+     */
+    private String toExpression(
+            Field field,
+            TypeReference fieldType,
+            Term term,
+            List<Argument> parserArguments,
+            List<Argument> serializerArguments,
+            boolean serialize,
+            boolean suppressPointerAccess) {
         Tracer tracer = pythonTracerStart("toExpression(suppressPointerAccess=" + suppressPointerAccess + ")");
         if (term == null) {
             return "";
@@ -761,15 +1156,30 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         }
     }
 
-    private String toTernaryTermExpression(Field field, TypeReference fieldType, TernaryTerm ternaryTerm, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, Tracer tracer) {
+    /**
+     * Returns a Python expression that represents the given ternary term.
+     *
+     * @param field the field of the given type reference
+     * @param fieldType the type reference of the given data
+     * @param ternaryTerm the ternary term to represent
+     * @param parserArguments the parser arguments
+     * @param serializerArguments the serializer arguments
+     * @param serialize whether the data is serialized
+     * @param tracer the tracer to use
+     * @return a Python expression
+     */
+    private String toTernaryTermExpression(Field field, TypeReference fieldType, TernaryTerm ternaryTerm, List<Argument> parserArguments,
+                                              List<Argument> serializerArguments, boolean serialize, Tracer tracer) {
         tracer = tracer.dive("ternary term instanceOf");
         if ("if".equals(ternaryTerm.getOperation())) {
+            // Ternary operation is "if", so we can build an inline if statement
             Term a = ternaryTerm.getA();
             Term b = ternaryTerm.getB();
             Term c = ternaryTerm.getC();
             String castExpressionForTypeReference = getCastExpressionForTypeReference(fieldType);
             String inlineIf = toExpression(field, fieldType, b, parserArguments, serializerArguments, serialize, false) + " if " +
-                toExpression(field, new DefaultBooleanTypeReference(), a, parserArguments, serializerArguments, serialize, false) + " else " +
+                toExpression(field, new DefaultBooleanTypeReference(), a, parserArguments, serializerArguments, serialize, false) +
+                " else " +
                 toExpression(field, fieldType, c, parserArguments, serializerArguments, serialize, false);
 
             return tracer + inlineIf;
@@ -803,8 +1213,8 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
                 // Except for doing a nil or not-nil check :-(
                 // So in case of such a check, we need to suppress the pointer-access.
                 boolean suppressPointerAccessOverride = (operation.equals("==") || operation.equals("!=")) && ((a instanceof NullLiteral) || (b instanceof NullLiteral));
-                String aExpression = toExpression(field, null, a, parserArguments, serializerArguments, serialize, suppressPointerAccessOverride);
-                String bExpression = toExpression(field, null, b, parserArguments, serializerArguments, serialize, suppressPointerAccessOverride);
+                String aExpression = toExpression(field, null, a, parserArguments, serializerArguments, serialize, true);
+                String bExpression = toExpression(field, null, b, parserArguments, serializerArguments, serialize, true);
                 return tracer + "bool((" + aExpression + ") " + operation + " (" + bExpression + "))";
             case ">>":
             case "<<":
@@ -813,35 +1223,56 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
                 tracer = tracer.dive("bitwise");
                 // We don't want casts here
                 return tracer +
-                    toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, false) +
+                    toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, true) +
                     operation + " " +
-                    toExpression(field, fieldType, b, parserArguments, serializerArguments, serialize, false);
+                    toExpression(field, fieldType, b, parserArguments, serializerArguments, serialize, true);
             default:
                 tracer = tracer.dive("default");
                 if (fieldType instanceof StringTypeReference) {
                     tracer = tracer.dive("string type reference");
-                    return tracer + toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, false) +
+                    return tracer + toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, true) +
                         operation + " " +
-                        toExpression(field, fieldType, b, parserArguments, serializerArguments, serialize, false);
+                        toExpression(field, fieldType, b, parserArguments, serializerArguments, serialize, true);
                 }
                 return tracer +
-                    toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, false) +
+                    toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, true) +
                     operation + " " +
-                    toExpression(field, fieldType, b, parserArguments, serializerArguments, serialize, false);
+                    toExpression(field, fieldType, b, parserArguments, serializerArguments, serialize, true);
         }
     }
 
+    /**
+     * Returns a Python expression that represents the given unary term.
+     *
+     * @param field the field of the given type reference
+     * @param typeReference the type reference of the given data
+     * @param unaryTerm the unary term to represent
+     * @param parserArguments the parser arguments
+     * @param serializerArguments the serializer arguments
+     * @param serialize whether the data is serialized
+     * @param tracer the tracer to use
+     * @return a Python expression
+     */
     private String toUnaryTermExpression(Field field, TypeReference fieldType, UnaryTerm unaryTerm, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, Tracer tracer) {
         tracer = tracer.dive("unary term instanceOf");
         Term a = unaryTerm.getA();
         switch (unaryTerm.getOperation()) {
             case "!":
+                // Not
+                // !x
+                // => "!(" + toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, false) + ")"
                 tracer = tracer.dive("case !");
                 return tracer + "!(" + toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, false) + ")";
             case "-":
-                tracer = tracer.dive("case -");
+                // Negate
+                // -x
+                // => "-(" + toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, false) + ")"
+                tracer =tracer.dive("case -");
                 return tracer + "-(" + toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, false) + ")";
             case "()":
+                // Identity
+                // x()
+                // => "(" + toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, false) + ")"
                 tracer = tracer.dive("case ()");
                 return tracer + "(" + toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, false) + ")";
             default:
@@ -849,49 +1280,86 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         }
     }
 
+    /**
+     * Returns a Python expression that represents the given literal term.
+     *
+     * @param field the field of the given type reference
+     * @param typeReference the type reference of the given data
+     * @param term the literal term to represent
+     * @param parserArguments the parser arguments
+     * @param serializerArguments the serializer arguments
+     * @param serialize whether the data is serialized
+     * @param suppressPointerAccess whether to suppress pointer 
+     *  access
+     * @param tracer the tracer to extend
+     * @return a Python expression that represents the given literal term
+     */
     private String toLiteralTermExpression(Field field, TypeReference fieldType, Term term, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess, Tracer tracer) {
         tracer = tracer.dive("literal term instanceOf");
         if (term instanceof NullLiteral) {
+            // Return None for null literals
             tracer = tracer.dive("null literal instanceOf");
             return tracer + "None";
         } else if (term instanceof BooleanLiteral) {
-            tracer = tracer.dive("boolean literal instanceOf");
+            // Return a string literal with the boolean value
             String bool = Boolean.toString(((BooleanLiteral) term).getValue());
             return tracer + bool.substring(0,1).toUpperCase() + bool.substring(1);
         } else if (term instanceof NumericLiteral) {
-            tracer = tracer.dive("numeric literal instanceOf");
+            // Return a numeric literal with the appropriate type cast,
+            // unless the type reference is a string type reference
             if (getCastExpressionForTypeReference(fieldType).equals("string")) {
+                // If the type reference is a string type reference, return a string literal
                 tracer = tracer.dive("type reference string");
                 return tracer + "(" + ((NumericLiteral) term).getNumber().toString() + ")";
             } else {
+                // Otherwise, return a numeric literal with the appropriate type cast
                 return tracer + getCastExpressionForTypeReference(fieldType) + "(" + ((NumericLiteral) term).getNumber().toString() + ")";
             }
         } else if (term instanceof HexadecimalLiteral) {
-            tracer = tracer.dive("hexadecimal literal instanceOf");
+            // Return a string literal with the hexadecimal value
             return tracer + ((HexadecimalLiteral) term).getHexString();
         } else if (term instanceof StringLiteral) {
-            tracer = tracer.dive("string literal instanceOf");
+            // Return a string literal with the value of the string literal
             return tracer + "\"" + ((StringLiteral) term).getValue() + "\"";
         } else if (term instanceof VariableLiteral) {
-            tracer = tracer.dive("variable literal instanceOf");
+            // Return a variable expression for the variable literal
             VariableLiteral variableLiteral = (VariableLiteral) term;
             if ("cur_pos".equals(((VariableLiteral) term).getName())) {
+                // If the variable is named "cur_pos", return an expression
+                // that computes the position from the position aware and the start position
                 return "(position_aware.get_pos() - startPos)";
             } else if ("BIG_ENDIAN".equals(((VariableLiteral) term).getName()) && (fieldType instanceof ByteOrderTypeReference)) {
+                // If the variable is named "BIG_ENDIAN" and the type reference is a byte order type reference,
+                // return the constant "ByteOrder.BIG_ENDIAN"
                 return "ByteOrder.BIG_ENDIAN";
             } else if ("LITTLE_ENDIAN".equals(((VariableLiteral) term).getName()) && (fieldType instanceof ByteOrderTypeReference)) {
+                // If the variable is named "LITTLE_ENDIAN" and the type reference is a byte order type reference,
+                // return the constant "ByteOrder.LITTLE_ENDIAN"
                 return "ByteOrder.LITTLE_ENDIAN";
             }
             return tracer + toVariableExpression(field, fieldType, (VariableLiteral) term, parserArguments, serializerArguments, serialize, suppressPointerAccess);
         } else {
+            // Throw an exception for unsupported Literal types
             throw new FreemarkerException("Unsupported Literal type " + term.getClass().getName());
         }
     }
 
+    /**
+     * Returns a Python expression that accesses the given variable literal.
+     * @param field the field of the given type reference
+     * @param typeReference the type reference of the given data
+     * @param variableLiteral the variable literal to access
+     * @param parserArguments the parser arguments
+     * @param serializerArguments the serializer arguments
+     * @param serialize whether the data is serialized
+     * @param suppressPointerAccess whether to suppress pointer access
+     * @return a Python expression that accesses the given variable literal.
+     */
     private String toVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess) {
         return toVariableExpression(field, typeReference, variableLiteral, parserArguments, serializerArguments, serialize, suppressPointerAccess, false);
     }
 
+
     private String toVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess, boolean isChild) {
         Tracer tracer = pythonTracerStart("toVariableExpression(serialize=" + serialize + ")");
         String variableLiteralName = variableLiteral.getName();
@@ -1074,6 +1542,27 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
                 .orElse("");
     }
 
+    /**
+     * Returns a Python expression that accesses the given variable literal
+     * in an upper-case format.
+     *
+     * If the given variable literal has arguments, they are enclosed in
+     * parentheses and separated by commas.
+     *
+     * If the given variable literal has an index, it is enclosed in square
+     * brackets.
+     *
+     * @param field the field of the given type reference
+     * @param typeReference the type reference of the given data
+     * @param variableLiteral the variable literal to access
+     * @param parserArguments the parser arguments
+     * @param serializerArguments the serializer arguments
+     * @param serialize whether the data is serialized
+     * @param suppressPointerAccess whether to suppress pointer access
+     * @param tracer the tracer for this expression
+     * @return a Python expression that accesses the given variable literal
+     *         in an upper-case format
+     */
     private String toUppercaseVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess, Tracer tracer) {
         tracer = tracer.dive("toUppercaseVariableExpression");
         StringBuilder sb = new StringBuilder(variableLiteral.getName().toUpperCase());
@@ -1097,6 +1586,20 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
             .orElse("");
     }
 
+    /**
+     * Returns a Python expression that computes the ceiling of the given
+     * variable literal in Python.
+     *
+     * @param field the field of the given type reference
+     * @param variableLiteral the variable literal to access
+     * @param parserArguments the parser arguments
+     * @param serializerArguments the serializer arguments
+     * @param serialize whether to serialize
+     * @param suppressPointerAccess whether to suppress pointer access
+     * @param tracer the tracer for this expression
+     * @return a Python expression that computes the ceiling of the given
+     * variable literal in Python
+     */
     private String toCeilVariableExpression(Field field, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess, Tracer tracer) {
         tracer = tracer.dive("ceil");
         Term va = variableLiteral.getArgs().orElseThrow(() -> new FreemarkerException("CEIL needs at least one arg"))
@@ -1107,6 +1610,21 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return tracer + "ceil(" + toExpression(field, tr, va, parserArguments, serializerArguments, serialize, suppressPointerAccess) + ")";
     }
 
+
+    /**
+     * Returns an expression that computes the size in bytes of the given
+     * variable literal in Python.
+     *
+     * @param field the field of the given type reference
+     * @param typeReference the type reference of the given data
+     * @param variableLiteral the variable literal to access
+     * @param parserArguments the parser arguments
+     * @param serializerArguments the serializer arguments
+     * @param suppressPointerAccess whether to suppress pointer access
+     * @param tracer the tracer for this expression
+     * @return an expression that computes the size in bytes of the given
+     * variable literal in Python.
+     */
     private String toArraySizeInBytesVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean suppressPointerAccess, Tracer tracer) {
         tracer = tracer.dive("array size in bytes");
         VariableLiteral va = variableLiteral.getArgs()
@@ -1116,6 +1634,7 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
             .orElseThrow(() -> new FreemarkerException("ARRAY_SIZE_IN_BYTES needs a literal"))
             .asVariableLiteral()
             .orElseThrow(() -> new FreemarkerException("ARRAY_SIZE_IN_BYTES needs a variable literal"));
+
         // "io" and "m" are always available in every parser.
         boolean isSerializerArg = "read_buffer".equals(va.getName()) || "write_buffer".equals(va.getName()) || "self".equals(va.getName()) || "element".equals(va.getName());
         if (!isSerializerArg && serializerArguments != null) {
@@ -1126,16 +1645,37 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
                 }
             }
         }
+
         StringBuilder sb = new StringBuilder();
         if (isSerializerArg) {
+            // Access the given variable literal via a serializer argument. This
+            // might be the case if the argument is called "read_buffer" or
+            // "write_buffer".
             sb.append(va.getName()).append(va.getChild().map(child -> "." + toVariableExpression(field, typeReference, child, parserArguments, serializerArguments, true, suppressPointerAccess, true)).orElse(""));
         } else {
+            // Access the given variable literal directly.
             sb.append(toVariableExpression(field, typeReference, va, parserArguments, serializerArguments, true, suppressPointerAccess));
         }
+
+        // We need the getsizeof function from the sys module.
         emitRequiredImport("from sys import getsizeof");
+        // Cast the result to the correct type if necessary.
         return tracer + getCastExpressionForTypeReference(typeReference) + "(getsizeof(" + sb + "))";
     }
 
+    /**
+     * Returns an expression that computes the count of the given variable literal in Python.
+     *
+     * @param field the field of the given type reference
+     * @param typeReference the type reference of the given data
+     * @param variableLiteral the variable literal to access
+     * @param parserArguments the parser arguments
+     * @param serializerArguments the serializer arguments
+     * @param serialize whether the data is serialized
+     * @param suppressPointerAccess whether to suppress pointer access
+     * @param tracer the tracer for this expression
+     * @return an expression that computes the count of the given variable literal in Python
+     */
     private String toCountVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess, Tracer tracer) {
         tracer = tracer.dive("count");
         VariableLiteral countLiteral = variableLiteral.getArgs()
@@ -1150,6 +1690,21 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
             "))";
     }
 
+    /**
+     * Returns an expression that computes the length of the given string variable
+     * literal in Python.
+     *
+     * @param field the field of the given type reference
+     * @param typeReference the type reference of the given data
+     * @param variableLiteral the variable literal to access
+     * @param parserArguments the parser arguments
+     * @param serializerArguments the serializer arguments
+     * @param serialize whether the data is serialized
+     * @param suppressPointerAccess whether to suppress pointer access
+     * @param tracer the tracer for this expression
+     * @return an expression that computes the length of the given string variable
+     * literal in Python.
+     */
     private String toStrLenVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess, Tracer tracer) {
         tracer = tracer.dive("str-len");
         VariableLiteral countLiteral = variableLiteral.getArgs()
@@ -1255,6 +1810,21 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return tracer + sb.toString();
     }
 
+    /**
+     * Returns a Python expression that casts the given variable literal to the
+     * given type.
+     *
+     * @param field the field of the given type reference
+     * @param typeReference the type reference of the given data
+     * @param variableLiteral the variable literal to cast
+     * @param parserArguments the parser arguments
+     * @param serializerArguments the serializer arguments
+     * @param serialize whether to serialize
+     * @param suppressPointerAccess whether to suppress pointer access
+     * @param tracer the tracer for this expression
+     * @return a Python expression that casts the given variable literal to the
+     * given type
+     */
     private String toCastVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess, Tracer tracer) {
         tracer = tracer.dive("CAST");
         List<Term> arguments = variableLiteral.getArgs().orElseThrow(() -> new FreemarkerException("A Cast expression needs arguments"));
@@ -1279,19 +1849,52 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return tracer + sb.toString() + variableLiteral.getChild().map(child -> "." + camelCaseToSnakeCase(toVariableExpression(field, typeReference, child, parserArguments, serializerArguments, false, suppressPointerAccess, true))).orElse("");
     }
 
+    /**
+     * Returns an expression that accesses the given optional field in Python.
+     * @param field the field of the given type reference
+     * @param typeReference the type reference of the given data
+     * @param variableLiteral the variable literal to access
+     * @param parserArguments the parser arguments
+     * @param serializerArguments the serializer arguments
+     * @param suppressPointerAccess whether to suppress pointer access
+     * @param tracer the tracer for this expression
+     * @return an expression that accesses the given optional field in Python
+     */
     private String toOptionalVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean suppressPointerAccess, Tracer tracer) {
         tracer = tracer.dive("optional fields");
-        return tracer + "(" + (suppressPointerAccess || (typeReference != null && typeReference.isComplexTypeReference()) ? "" : "*") + variableLiteral.getName() + ")" +
+        return tracer + (suppressPointerAccess || (typeReference != null && typeReference.isComplexTypeReference()) ? "" : "*") + camelCaseToSnakeCase(variableLiteral.getName()) +
             variableLiteral.getChild().map(child -> "." + camelCaseToSnakeCase(toVariableExpression(field, typeReference, child, parserArguments, serializerArguments, false, suppressPointerAccess, true))).orElse("");
     }
 
+    /**
+     * Returns an expression that accesses the given enum constant in Python.
+     * @param field the field of the given type reference
+     * @param typeReference the type reference of the given data
+     * @param variableLiteral the variable literal to access
+     * @param parserArguments the parser arguments
+     * @param serializerArguments the serializer arguments
+     * @param suppressPointerAccess whether to suppress pointer access
+     * @param tracer the tracer for this expression
+     * @return an expression that accesses the given enum constant in Python
+     */
     private String toConstantVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean suppressPointerAccess, Tracer tracer) {
         tracer = tracer.dive("enum constant");
-        VariableLiteral child = variableLiteral.getChild().orElseThrow(IllegalStateException::new);
+        VariableLiteral child = variableLiteral.getChild().orElseThrow(() -> new IllegalStateException("A constant expression should have a child"));
         return tracer + variableLiteral.getName() + "." + camelCaseToSnakeCase(child.getName()) + "()" +
             child.getChild().map(childChild -> "." + toVariableExpression(field, typeReference, childChild, parserArguments, serializerArguments, false, suppressPointerAccess, true)).orElse("");
     }
 
+    /**
+     * Returns an expression that accesses the given enum constant in Python.
+     * @param field the field of the given type reference
+     * @param typeReference the type reference of the given data
+     * @param variableLiteral the variable literal to access
+     * @param parserArguments the parser arguments
+     * @param serializerArguments the serializer arguments
+     * @param suppressPointerAccess whether to suppress pointer access
+     * @param tracer the tracer for this expression
+     * @return an expression that accesses the given enum constant in Python
+     */
     private String toEnumVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean suppressPointerAccess, Tracer tracer) {
         tracer = tracer.dive("enum");
         VariableLiteral child = variableLiteral.getChild().orElseThrow(() -> new FreemarkerException("Enum should have a child"));
@@ -1299,16 +1902,50 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
             child.getChild().map(childChild -> "." + toVariableExpression(field, typeReference, childChild, parserArguments, serializerArguments, false, suppressPointerAccess, true)).orElse("");
     }
 
+    /**
+     * Returns an expression that accesses the last item of the context in Python.
+     * @param typeReference the type reference of the given data
+     * @param serialize whether the data is serialized
+     * @param tracer the tracer for this expression
+     * @return an expression that accesses the last item of the context in Python
+     */
     private String toLastItemVariableExpression(TypeReference typeReference, boolean serialize, Tracer tracer) {
         tracer = tracer.dive("lastItem");
+        // The last item is accessed in the context via the utils.GetLastItemFromContext(ctx) method
         return tracer + "utils.GetLastItemFromContext(ctx)";
     }
 
+    /**
+     * Returns an expression that accesses the length of the given variable literal in the given type reference.
+     * If the variable literal has a child, this expression will be a method call of the form
+     * <code>self.length(&lt;child expression&gt;)</code>.
+     * Otherwise, this expression will be simply <code>self.length</code>.
+     * @param field the field of the given type reference
+     * @param variableLiteral the variable literal to access
+     * @param serialize whether the data is serialized
+     * @param tracer the tracer for this expression
+     * @return the expression to access the length of the given variable literal in the given type reference
+     */
     private String toLengthVariableExpression(Field field, VariableLiteral variableLiteral, boolean serialize, Tracer tracer) {
         tracer = tracer.dive("length");
         return tracer + (serialize ? ("len(self." + camelCaseToSnakeCase(variableLiteral.getName()) + ")") : ("(" + variableLiteral.getName() + ")"));
     }
 
+    /**
+     * Returns the expression to access the value of the given variable literal in the given type reference.
+     * If the given variable literal has a child, this expression will be a method call of the form
+     * <code>self._value(&lt;child expression&gt;)</code>.
+     * Otherwise, this expression will be simply <code>self.value</code>.
+     * @param field the field of the given type reference
+     * @param typeReference the type reference of the given data
+     * @param variableLiteral the variable literal to access
+     * @param parserArguments the parser arguments
+     * @param serializerArguments the serializer arguments
+     * @param serialize whether the data is serialized
+     * @param suppressPointerAccess whether to suppress pointer access
+     * @param tracer the tracer for this expression
+     * @return the expression to access the value of the given variable literal in the given type reference
+     */
     private String toValueVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess, Tracer tracer) {
         final Tracer tracer2 = tracer.dive("_value");
         return variableLiteral.getChild()
@@ -1316,11 +1953,30 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
             .orElse(tracer2 + "value");
     }
 
+    /**
+     * Returns the expression to access the length in bits of the given data.
+     * If the data is serialized, this will be a cast expression.
+     * Otherwise it will be just 'length_in_bits'.
+     * @param typeReference the type reference of the data
+     * @param serialize whether the data is serialized
+     * @param tracer the tracer for this expression
+     * @return the expression to access the length in bits of the given data
+     */
     private String toLengthInBitsVariableExpression(TypeReference typeReference, boolean serialize, Tracer tracer) {
         tracer = tracer.dive("lengthInBits");
         return tracer + (serialize ? getCastExpressionForTypeReference(typeReference) + "(" : "") + "length_in_bits" + (serialize ? "())" : "()");
     }
 
+
+    /**
+     * Returns the expression to access the length in bytes of the given data.
+     * If the data is serialized, this will be a cast expression.
+     * Otherwise it will be just 'length_in_bytes'.
+     * @param typeReference the type reference of the data
+     * @param serialize whether the data is serialized
+     * @param tracer the tracer for this expression
+     * @return the expression to access the length in bytes of the given data
+     */
     private String toLengthInBytesVariableExpression(TypeReference typeReference, boolean serialize, Tracer tracer) {
         tracer = tracer.dive("lengthInBytes");
         return tracer + (serialize ? getCastExpressionForTypeReference(typeReference) + "(" : "") + "length_in_bytes" + (serialize ? "())" : "()");
@@ -1361,6 +2017,16 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return sb.toString() + sizeInBits;
     }
 
+    /**
+     * Escapes a string value according to the type reference given.
+     * <p>
+     * This method is used by the generated Python code to properly handle string values when
+     * writing data to a PLC device.
+     * 
+     * @param typeReference the type reference of the field the value is being written to.
+     * @param valueString the string value to be escaped.
+     * @return an escaped string value.
+     */
     public String escapeValue(TypeReference typeReference, String valueString) {
         if (valueString == null) {
             return null;
@@ -1371,18 +2037,34 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
                 case UINT:
                 case INT:
                     // If it's a one character string and is numeric, output it as char.
+                    // This is necessary because in Python strings are Unicode by default
+                    // and the "char" type is not a subset of the string type, but rather
+                    // a distinct type. If a one character string is written as a string,
+                    // it will be encoded as Unicode and not as a single byte.
                     if (!NumberUtils.isParsable(valueString) && (valueString.length() == 1)) {
                         return "'" + valueString + "'";
                     }
                     break;
                 case STRING:
                 case VSTRING:
+                    // The Python string type is Unicode by default, so just add quotes
+                    // to the value to make it a string literal.
                     return "\"" + valueString + "\"";
             }
         }
         return valueString;
     }
 
+    /**
+     * Escapes a string value according to the type reference given.
+     * <p>
+     * This method is used by the generated Python code to properly handle string values when
+     * writing data to a PLC device.
+     * 
+     * @param typeReference the type reference of the field the value is being written to.
+     * @param valueString the string value to be escaped.
+     * @return an escaped string value.
+     */
     public String escapeEnumValue(TypeReference typeReference, String valueString) {
         // Currently the only case in which here complex type references are used are when referencing enum constants.
         if (typeReference != null && typeReference.isNonSimpleTypeReference()) {
@@ -1391,41 +2073,94 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
                 return "0";
             }
             if (valueString.contains(".")) {
+                // If the value string contains a dot, it's assumed to be a string
+                // representation of an enum constant with a name in the form:
+                // "typeName_constantName" (e.g. "MyEnum_MY_CONSTANT")
                 String typeName = valueString.substring(0, valueString.indexOf('.'));
                 String constantName = valueString.substring(valueString.indexOf('.') + 1);
                 return typeName + "_" + constantName;
             }
+            // Otherwise, return the value string as is.
             return valueString;
         } else {
+            // For simple types, just use the {@link #escapeValue(TypeReference, String)}
+            // method.
             return escapeValue(typeReference, valueString);
         }
     }
 
+    /**
+     * Returns a list of unique {@link EnumValue}s from the given list.
+     * <p>
+     * This is used by the generated Python code to filter out duplicates in a list of {@link EnumValue}s.
+     * 
+     * @param enumValues the list of {@link EnumValue}s to filter.
+     * @return a list of unique {@link EnumValue}s.
+     */
     public Collection<EnumValue> getUniqueEnumValues(List<EnumValue> enumValues) {
         Map<String, EnumValue> filteredEnumValues = new TreeMap<>();
+        // Iterate over the list of enum values and add only the first occurrence of each value to the map
         for (EnumValue enumValue : enumValues) {
             if (!filteredEnumValues.containsKey(enumValue.getValue())) {
                 filteredEnumValues.put(enumValue.getValue(), enumValue);
             }
         }
+        // Return the values of the map as a list
         return filteredEnumValues.values();
     }
 
+    /**
+     * Returns a list of unique {@link DiscriminatedComplexTypeDefinition}s from the given list.
+     * <p>
+     * This is used by the generated Python code to filter out duplicates in a {@link DiscriminatedComplexTypeDefinition} list.
+     * 
+     * @param allSwitchCases the list of {@link DiscriminatedComplexTypeDefinition}s to filter.
+     * @return a list of unique {@link DiscriminatedComplexTypeDefinition}s.
+     */
     public List<DiscriminatedComplexTypeDefinition> getUniqueSwitchCases(List<DiscriminatedComplexTypeDefinition> allSwitchCases) {
         Map<String, DiscriminatedComplexTypeDefinition> switchCases = new LinkedHashMap<>();
         for (DiscriminatedComplexTypeDefinition switchCase : allSwitchCases) {
+            // Check if the given switch case already exists in the map.
+            // If not, add it to the map.
             if (!switchCases.containsKey(switchCase.getName())) {
                 switchCases.put(switchCase.getName(), switchCase);
             }
         }
+        // Convert the map values to a list and return it.
         return new ArrayList<>(switchCases.values());
     }
 
+    /**
+     * Emits a required import statement for a data io class.
+     * <p>
+     * This is used by the generated Python code to import classes needed to read and write PLC
+     * data.
+     *
+     * @param requiredImport the name of the data io class to import
+     */
     public void emitRequiredImport(String requiredImport) {
-        LOGGER.debug("emitting import '\"{}\"'", requiredImport);
+        /**
+         * Logs the emitted import statement at debug level. This is useful for debugging
+         * purposes, as it allows you to quickly identify which classes are being imported for
+         * reading and writing PLC data.
+         */
+        LOGGER.debug("emitting import \"{}\"", requiredImport);
+        /**
+         * Keeps track of all the required imports that have been emitted. This collection is used
+         * when generating the __all__ list for the generated module.
+         */
         requiredImports.add(requiredImport);
     }
 
+    /**
+     * Emits a required import statement for a data io class.
+     * <p>
+     * This is used by the generated Python code to import classes needed to read and write PLC
+     * data.
+     *
+     * @param alias the alias of the imported class
+     * @param requiredImport the name of the data io class to import
+     */
     public void emitRequiredImport(String alias, String requiredImport) {
         LOGGER.debug("emitting import '{} \"{}'\"", alias, requiredImport);
         requiredImports.add(alias + ' ' + '"' + requiredImport + '"');
@@ -1435,20 +2170,63 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return requiredImports;
     }
 
+    /**
+     * Emits a required import statement for a data io class.
+     * <p>
+     * This is used by the generated Python code to import classes needed to read and write PLC
+     * data.
+     * <p>
+     * The imported class must be a subclass of {@link PlcDataIo}.
+     * @param requiredImport the name of the data io class to import
+     */
     public void emitDataIoRequiredImport(String requiredImport) {
         LOGGER.debug("emitting io import '\"{}\"'", requiredImport);
         requiredImportsForDataIo.add(requiredImport);
     }
 
+
+    /**
+     * Emits a required import statement for a data io class.
+     * <p>
+     * This is used by the generated Python code to import classes needed to read and write PLC
+     * data.
+     * <p>
+     * The alias parameter is used to specify an alias for the imported class. The alias is
+     * used in the generated Python code to refer to the imported class.
+     * @param alias an alias for the imported class
+     * @param requiredImport the class name to import
+     */
     public void emitDataIoRequiredImport(String alias, String requiredImport) {
         LOGGER.debug("emitting data io import '{} \"{}'\"", alias, requiredImport);
         requiredImportsForDataIo.add(alias + ' ' + '"' + requiredImport + '"');
     }
 
+    /**
+     * Returns a set of required import statements for data io classes.
+     * <p>
+     * This is used by the generated Python code to import classes needed to read and write PLC
+     * data.
+     * <p>
+     * The set returned is not modified by the code generator and is intended to be used by the
+     * generated code.
+     * @return a set of required import statements for data io classes
+     */
     public Set<String> getRequiredImportsForDataIo() {
         return requiredImportsForDataIo;
     }
 
+    /**
+     * Returns the variable name for a given field.
+     * <p>
+     * If the field is a named field, the name is used.
+     * Otherwise, the default is "_".
+     * <p>
+     * If there is a conflict between fields, the first one found is used.
+     * <p>
+     * This is used to generate the names of variables in the generated Python code.
+     * @param field the field to get the variable name for
+     * @return the variable name
+     */
     public String getVariableName(Field field) {
         if (!(field instanceof NamedField)) {
             return "_";
@@ -1457,9 +2235,21 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
 
         String name = null;
         for (Field curField : ((ComplexTypeDefinition) thisType).getFields()) {
+            // If this is the current field, use its name
             if (curField == field) {
                 name = namedField.getName();
             } else if (name != null) {
+                // Otherwise, check if this field's expressions contain the given name
+                // We check for:
+                // - Array fields and their loop expressions
+                // - Checksum fields and their checksum expressions
+                // - Implicit fields and their serialize expressions
+                // - Manual array fields and their length, loop, and serialize expressions
+                // - Manual fields and their length, parse, and serialize expressions
+                // - Optional fields and their condition expressions
+                // - Switch fields and their discriminator expressions and parser arguments
+                // - Virtual fields and their value expressions
+                // - Typed fields and their type's params (if applicable)
                 if (curField instanceof ArrayField) {
                     ArrayField arrayField = (ArrayField) curField;
                     if (arrayField.getLoopExpression().contains(name)) {
@@ -1507,11 +2297,13 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
                     }
                 } else if (curField instanceof SwitchField) {
                     SwitchField switchField = (SwitchField) curField;
+                    // Check discriminator expressions first
                     for (Term discriminatorExpression : switchField.getDiscriminatorExpressions()) {
                         if (discriminatorExpression.contains(name)) {
                             return name;
                         }
                     }
+                    // Then check parser arguments
                     for (DiscriminatedComplexTypeDefinition curCase : switchField.getCases()) {
                         for (Argument parserArgument : curCase.getParserArguments().orElse(Collections.emptyList())) {
                             if (parserArgument.getName().equals(name)) {
@@ -1525,6 +2317,7 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
                         return name;
                     }
                 }
+                // Finally, if the field is a typed field, check its type's params (if applicable)
                 List<Term> params = field.asTypedField()
                     .map(typedField -> typedField.getType().asNonSimpleTypeReference()
                         .map(NonSimpleTypeReference::getParams)
@@ -1543,7 +2336,18 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return "_";
     }
 
+    /**
+     * Checks whether a given field requires a variable.
+     *
+     * @param field the field to check
+     * @param variable the variable to check for
+     * @param serialization whether the field is used in serialization or not
+     * @return true if the field requires the variable, false otherwise
+     */
     public boolean needsVariable(Field field, String variableName, boolean serialization) {
+        // If it's not a serialization, check if the field is an array and the loop
+        // expression contains the variable name, or if it's a virtual field and
+        // the value expression contains the variable name.
         if (!serialization) {
             if (field instanceof ArrayField) {
                 ArrayField arrayField = (ArrayField) field;
@@ -1552,12 +2356,17 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
                 }
             }
         }
+        // If it's not a serialization, check if the field is a virtual field and
+        // the value expression contains the variable name.
         if (field instanceof VirtualField) {
             VirtualField virtualField = (VirtualField) field;
             if (virtualField.getValueExpression().contains(variableName)) {
                 return true;
             }
         }
+        // If it's not a serialization, check if the field is a padding field and
+        // the padding condition or padding value expression contains the variable
+        // name.
         if (field instanceof PaddingField) {
             PaddingField paddingField = (PaddingField) field;
             if (paddingField.getPaddingCondition().contains(variableName)) {
@@ -1567,10 +2376,14 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
                 return true;
             }
         }
+        // Otherwise, check if the field's type reference has a parameter that
+        // contains the variable name.
         return field.asTypedField()
             .map(typedField -> typedField.getType().asNonSimpleTypeReference()
                 .map(nonSimpleTypeReference -> nonSimpleTypeReference.getParams()
                     .map(params -> params.stream()
+                        // Stream over all parameters of the type reference and
+                        // returns true if any of them contains the variable name.
                         .anyMatch(param -> param.contains(variableName))
                     )
                     .orElse(false)
@@ -1613,46 +2426,83 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return result;
     }
 
+    /**
+     * Checks whether the complex type definition requires a "curPos" variable.
+     *
+     * @return true if a "curPos" variable is required, false otherwise
+     */
     public boolean requiresCurPos() {
+        // Iterate over all fields of the complex type definition.
         if (thisType instanceof ComplexTypeDefinition) {
             ComplexTypeDefinition complexTypeDefinition = (ComplexTypeDefinition) this.thisType;
+
+            // If any of the fields require a "curPos" variable, return true.
             for (Field curField : complexTypeDefinition.getFields()) {
                 if (requiresVariable(curField, "curPos")) {
                     return true;
                 }
             }
+
+            // If none of the fields require a "curPos" variable, return false.
+            return false;
         }
+
+        // If the complex type definition is null, return false.
         return false;
     }
 
+    /**
+     * Checks whether the complex type definition requires a "startPos" variable.
+     *
+     * @return true if a "startPos" variable is required, false otherwise
+     */
     public boolean requiresStartPos() {
         if (thisType instanceof ComplexTypeDefinition) {
             ComplexTypeDefinition complexTypeDefinition = (ComplexTypeDefinition) this.thisType;
+            // Iterate over all fields of the complex type definition.
             for (Field curField : complexTypeDefinition.getFields()) {
+                // If a field requires a "startPos" variable, return true.
                 if (requiresVariable(curField, "startPos")) {
                     return true;
                 }
             }
         }
+        // If none of the fields require a "startPos" variable, return false.
         return false;
     }
 
+    /**
+     * Checks whether a given field requires a variable.
+     *
+     * @param curField the field to check
+     * @param variable the variable to check for
+     * @return true if the field requires the variable, false otherwise
+     */
     public boolean requiresVariable(Field curField, String variable) {
         if (curField.isArrayField()) {
             ArrayField arrayField = (ArrayField) curField;
+            // Check if the loop expression of the array field contains the variable
+            // name.
             if (arrayField.getLoopExpression().contains(variable)) {
                 return true;
             }
         } else if (curField.isOptionalField()) {
+            // Check if the optional field has a condition expression that contains
+            // the variable name.
             OptionalField optionalField = (OptionalField) curField;
-            if (optionalField.getConditionExpression().isPresent() && optionalField.getConditionExpression().orElseThrow(IllegalStateException::new).contains(variable)) {
+            if (optionalField.getConditionExpression().isPresent() &&
+                optionalField.getConditionExpression().orElseThrow(IllegalStateException::new).contains(variable)) {
                 return true;
             }
         }
+        // Check if the type reference of the field's type has a parameter that
+        // contains the variable name.
         return curField.asTypedField()
             .map(typedField -> typedField.getType().asNonSimpleTypeReference()
                 .map(nonSimpleTypeReference -> nonSimpleTypeReference.getParams()
                     .map(params -> params.stream()
+                        // Stream over all parameters of the type reference and
+                        // returns true if any of them contains the variable name.
                         .anyMatch(param -> param.contains(variable))
                     )
                     .orElse(false)
@@ -1662,12 +2512,22 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
             .orElse(false);
     }
 
+    /**
+     * Finds a term by name in a given term.
+     *
+     * @param baseTerm the term to search
+     * @param name the name to search for
+     * @return the term with the given name, or null if not found.
+     */
     public Term findTerm(Term baseTerm, String name) {
         if (baseTerm instanceof VariableLiteral) {
             VariableLiteral variableLiteral = (VariableLiteral) baseTerm;
+            // Check if the variable literal itself has the desired name
             if (variableLiteral.getName().equals(name)) {
                 return variableLiteral;
             }
+            // Check if any of the arguments of the variable literal have the
+            // desired name.
             if (variableLiteral.getChild().isPresent()) {
                 Term found = findTerm(variableLiteral.getChild().get(), name);
                 if (found != null) {
@@ -1681,9 +2541,11 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
                 }
             }
         } else if (baseTerm instanceof UnaryTerm) {
+            // Recursively search the argument of the unary term.
             UnaryTerm unaryTerm = (UnaryTerm) baseTerm;
             return findTerm(unaryTerm.getA(), name);
         } else if (baseTerm instanceof BinaryTerm) {
+            // Recursively search both arguments of the binary term.
             BinaryTerm binaryTerm = (BinaryTerm) baseTerm;
             Term found = findTerm(binaryTerm.getA(), name);
             if (found != null) {
@@ -1692,6 +2554,7 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
             found = findTerm(binaryTerm.getB(), name);
             return found;
         } else if (baseTerm instanceof TernaryTerm) {
+            // Recursively search all three arguments of the ternary term.
             TernaryTerm ternaryTerm = (TernaryTerm) baseTerm;
             Term found = findTerm(ternaryTerm.getA(), name);
             if (found != null) {
@@ -1707,12 +2570,51 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return null;
     }
 
+    /**
+     * Converts a Python expression that refers to an enum constant to a constant
+     * reference.
+     *
+     * @param expression the expression to convert
+     * @return a string containing the enum name and constant name separated by
+     *         underscore.
+     */
     public String getEnumExpression(String expression) {
+        // Split the expression into enum name and enum constant name
         String enumName = expression.substring(0, expression.indexOf('.'));
         String enumConstant = expression.substring(expression.indexOf('.') + 1);
+
+        // Return enum name and constant name separated by underscore
         return enumName + "_" + enumConstant;
     }
 
+    /**
+     * Determines if a parser argument needs to be passed as a reference.
+
+     * <p>This method is a bit confusing: it checks if the argument type is
+     * complex and then checks if one of the properties of the complex type
+     * definition has the same name as the property name given as argument. If
+     * such a property exists and its type is not an enum, then the argument
+     * needs to be passed as a reference.
+
+     * <p>This method is implemented as it is because the information the
+     * {@link ComplexTypeDefinition} provides is not sufficient to determine
+     * whether an argument needs to be passed as a reference: the information
+     * about the fields of the complex type does not contain information about
+     * the type of the field. Instead, it contains information about the type
+     * definition of the field, which does not necessarily reflect the type of
+     * the field in the context of the given property.
+
+     * <p>This method is a bit broken because it does not consider the type
+     * of the argument. Instead, it only looks at the type of the property.
+     * This is problematic because the type of the argument could be a
+     * reference to a type that is not a complex type, but still needs to be
+     * passed as a reference. This is not the case here, because we only
+     * consider complex types.
+
+     * @param propertyName the name of the property
+     * @param argumentType the type of the parser argument
+     * @return whether the parser argument needs to be passed as a reference
+     */
     public boolean needsReferenceForParserArgument(String propertyName, TypeReference argumentType) {
         return argumentType.asComplexTypeReference()
             .map(complexTypeReference -> {
@@ -1734,6 +2636,19 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
             .orElse(false);
     }
 
+    /**
+     * Capitalizes a string by removing traces and capitalizing the first character
+     * of the remaining string.
+     *
+     * @param str the string to be capitalized
+     * @return the capitalized string
+     *
+     * <p>This method works by first extracting traces from the string using
+     * {@link #pythonTracerStart(String)}, then removing all traces from the
+     * string using {@link #removeTraces(String)}, and finally capitalizing the
+     * first character of the remaining string using
+     * {@link org.apache.commons.lang3.StringUtils#capitalize(String)}.
+     */
     public String capitalize(String str) {
         Tracer dummyTracer = pythonTracerStart("");
         String extractedTrace = dummyTracer.extractTraces(str);
@@ -1747,6 +2662,11 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
      *
      * @param camelCase camel-case string
      * @return snake-case string
+     *
+     * <p>Method that takes a camel-case string and converts it to a snake-case
+     * string. This is done by iterating over the characters in the string and
+     * adding an underscore in between uppercase and lowercase letters or when
+     * a dash is encountered.
      */
     public String camelCaseToSnakeCase(String camelCase) {
         StringBuilder snakeCase = new StringBuilder();
@@ -1756,15 +2676,21 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
             // If the previous letter is a lowercase letter and this one is uppercase, create a new snake-segment.
             if ((i > 0) && !Character.isUpperCase(chars[i - 1]) && Character.isUpperCase(chars[i])) {
                 snakeCase.append('_').append(lowerCaseChar);
-            } else if ((i < (chars.length - 2)) && Character.isUpperCase(chars[i]) && !Character.isUpperCase(chars[i + 1])) {
-                snakeCase.append('_').append(lowerCaseChar);
             }
-            // If this is uppercase and the previous one is too ... just make this letter lowercase.
+            // If the next letter is lowercase, or if this is the last letter, append this character directly.
+            else if ((i < (chars.length - 2)) && (Character.isLowerCase(chars[i + 1]) || i == (chars.length - 1))) {
+                snakeCase.append(lowerCaseChar);
+            }
+            // If this is uppercase and the previous one is too ..., append this letter in lowercase.
             else if ((i > 0) && Character.isUpperCase(chars[i - 1]) && Character.isUpperCase(chars[i])) {
                 snakeCase.append(lowerCaseChar);
-            } else if (chars[i] == '-') {
+            }
+            // If this is a dash, append it directly to the snake-case string.
+            else if (chars[i] == '-') {
                 snakeCase.append("_");
-            } else {
+            }
+            // Otherwise, append the character to the snake-case string.
+            else {
                 snakeCase.append(lowerCaseChar);
             }
         }
@@ -1776,16 +2702,37 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return snakeCase.toString();
     }
 
+    /**
+     * Creates a Python tracing object with a given base name. The Tracer object
+     * will use a '/' as separator, and prefix and suffix strings to include
+     * tracing info.
+     *
+     * @param base base name of the tracing object
+     * @return a Python Tracer object
+     */
     public Tracer pythonTracerStart(String base) {
         return new Tracer(base) {
+            /**
+             * Returns the separator used in the tracing object.
+             *
+             * @return '/' as separator
+             */
             protected String separator() {
                 return "/";
             }
 
+            /**
+             * Returns the prefix string used in the tracing object.
+             * @return a string used to prefix tracing information
+             */
             protected String prefix() {
                 return "\"\"\"";
             }
 
+            /**
+             * Returns the suffix string used in the tracing object.
+             * @return a string used to suffix tracing information
+             */
             protected String suffix() {
                 return "\"\"\"";
             }
diff --git a/code-generation/language-python/src/main/resources/templates/python/complex-type-template.python.ftlh b/code-generation/language-python/src/main/resources/templates/python/complex-type-template.python.ftlh
index 624e1a75f5..a98008359d 100644
--- a/code-generation/language-python/src/main/resources/templates/python/complex-type-template.python.ftlh
+++ b/code-generation/language-python/src/main/resources/templates/python/complex-type-template.python.ftlh
@@ -198,11 +198,11 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
 
         # Array Field (${arrayField.name})
                         <#if arrayField.type.elementTypeReference.isByteBased()>
-        write_buffer.write_byte_array(self.${helper.camelCaseToSnakeCase(namedField.name)}, logical_name="${namedField.name}")
+        write_buffer.write_byte_array(self.${helper.camelCaseToSnakeCase(namedField.name)}, logical_name="${helper.camelCaseToSnakeCase(namedField.name)}")
                         <#elseif arrayField.type.elementTypeReference.isSimpleTypeReference()>
-        write_buffer.write_simple_array(self.${helper.camelCaseToSnakeCase(namedField.name)}, write_buffer.${helper.getDataWriterCall(arrayField.type.elementTypeReference, namedField.name)}, logical_name="${namedField.name}")
+        write_buffer.write_simple_array(self.${helper.camelCaseToSnakeCase(namedField.name)}, write_buffer.${helper.getDataWriterCall(arrayField.type.elementTypeReference, namedField.name)}, logical_name="${helper.camelCaseToSnakeCase(namedField.name)}")
                         <#else>
-        write_buffer.write_complex_array(self.${helper.camelCaseToSnakeCase(namedField.name)}, logical_name="${namedField.name}")
+        write_buffer.write_complex_array(self.${helper.camelCaseToSnakeCase(namedField.name)}, logical_name="${helper.camelCaseToSnakeCase(namedField.name)}")
                         </#if>
                         <#break>
                     <#case "checksum">
@@ -212,7 +212,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                         <@emitImport import="from plc4py.protocols.${protocolName} import StaticHelper" />
 
         # Checksum Field (checksum) (Calculated)
-        write_buffer.${helper.getDataWriterCall(typedField.type, namedField.name)}(${helper.getLanguageTypeNameForField(field)}(StaticHelper.${helper.toParseExpression(checksumField, checksumField.type, checksumField.checksumExpression, parserArguments)}), logical_name="${namedField.name}")
+        write_buffer.${helper.getDataWriterCall(typedField.type, namedField.name)}(${helper.getLanguageTypeNameForField(field)}(StaticHelper.${helper.toParseExpression(checksumField, checksumField.type, checksumField.checksumExpression, parserArguments)}), logical_name="${helper.camelCaseToSnakeCase(namedField.name)}")
                         <#break>
                     <#case "const">
                         <#assign constField = field.asConstField().orElseThrow()>
@@ -229,10 +229,10 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
 
         # Discriminator Field (${discriminatorField.name}) (Used as input to a switch field)
                         <#if typedField.type.isEnumTypeReference()>
-        write_buffer.${helper.getEnumDataWriterCall(typedField.type, namedField.name, "value")}(self.${helper.camelCaseToSnakeCase(discriminatorField.name)}, logical_name="${namedField.name}" ${helper.getFieldOptions(typedField, parserArguments)})
+        write_buffer.${helper.getEnumDataWriterCall(typedField.type, namedField.name, "value")}(self.${helper.camelCaseToSnakeCase(discriminatorField.name)}, logical_name="${helper.camelCaseToSnakeCase(namedField.name)}" ${helper.getFieldOptions(typedField, parserArguments)})
                         <#else>
         <#assign simpleTypeReference = discriminatorField.type.asSimpleTypeReference().orElseThrow()>
-        write_buffer.${helper.getDataWriterCall(typedField.type, namedField.name)}(self.${helper.camelCaseToSnakeCase(discriminatorField.name)}, logical_name="${namedField.name}", bit_length=${simpleTypeReference.sizeInBits} ${helper.getFieldOptions(typedField, parserArguments)})
+        write_buffer.${helper.getDataWriterCall(typedField.type, namedField.name)}(self.${helper.camelCaseToSnakeCase(discriminatorField.name)}, logical_name="${helper.camelCaseToSnakeCase(namedField.name)}", bit_length=${simpleTypeReference.sizeInBits} ${helper.getFieldOptions(typedField, parserArguments)})
                         </#if>
                         <#break>
                     <#case "enum">
@@ -241,7 +241,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                         <#assign namedField = field.asNamedField().orElseThrow()>
 
         # Enum field (${namedField.name})
-        write_buffer.${helper.getEnumDataWriterCall(typedField.type, namedField.name, enumField.fieldName)}(self.${helper.camelCaseToSnakeCase(namedField.name)}, logical_name="${namedField.name}")
+        write_buffer.${helper.getEnumDataWriterCall(typedField.type, namedField.name, enumField.fieldName)}(self.${helper.camelCaseToSnakeCase(namedField.name)}, logical_name="${helper.camelCaseToSnakeCase(namedField.name)}")
                         <#break>
                     <#case "implicit">
                         <#assign implicitField = field.asImplicitField().orElseThrow()>
@@ -251,7 +251,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
         # Implicit Field (${helper.camelCaseToSnakeCase(implicitField.name)}) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
                         <#-- Implicit field values might be used in expressions, in order to avoid problems, we generate a temporary variable with the given name. -->
         ${helper.camelCaseToSnakeCase(implicitField.name)}: ${helper.getLanguageTypeNameForField(field)} = (${helper.toSerializationExpression(implicitField, implicitField.type, implicitField.serializeExpression, parserArguments)})
-        write_buffer.${helper.getDataWriterCall(typedField.type, namedField.name)}(${helper.camelCaseToSnakeCase(implicitField.name)}, logical_name="${namedField.name}")
+        write_buffer.${helper.getDataWriterCall(typedField.type, namedField.name)}(${helper.camelCaseToSnakeCase(implicitField.name)}, logical_name="${helper.camelCaseToSnakeCase(namedField.name)}")
                         <#break>
                     <#case "manualArray">
                         <#assign manualArrayField = field.asManualArrayField().orElseThrow()>
@@ -259,7 +259,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                         <#assign namedField = field.asNamedField().orElseThrow()>
 
         # Manual Array Field (${manualArrayField.name})
-        write_buffer.${helper.getDataWriterCall(typedField.type, namedField.name)}((${helper.getLanguageTypeNameForTypeReference(manualArrayField.type.elementTypeReference)} _value) -> ${helper.toParseExpression(manualArrayField, manualArrayField.type.elementTypeReference, manualArrayField.serializeExpression, parserArguments)}, logical_name="${namedField.name}")
+        write_buffer.${helper.getDataWriterCall(typedField.type, namedField.name)}((${helper.getLanguageTypeNameForTypeReference(manualArrayField.type.elementTypeReference)} _value) -> ${helper.toParseExpression(manualArrayField, manualArrayField.type.elementTypeReference, manualArrayField.serializeExpression, parserArguments)}, logical_name="${helper.camelCaseToSnakeCase(namedField.name)}")
                         <#break>
                     <#case "manual">
                         <#assign manualField = field.asManualField().orElseThrow()>
@@ -267,7 +267,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                         <#assign namedField = field.asNamedField().orElseThrow()>
                         <@emitImport import="from plc4py.protocols.${protocolName} import StaticHelper" />
         # Manual Field (${manualField.name})
-        write_buffer.write_manual(write_function=lambda : StaticHelper.${helper.toSerializationExpression(manualField, manualField.type, manualField.serializeExpression, parserArguments)}, logical_name="${namedField.name}")
+        write_buffer.write_manual(write_function=lambda : StaticHelper.${helper.toSerializationExpression(manualField, manualField.type, manualField.serializeExpression, parserArguments)}, logical_name="${helper.camelCaseToSnakeCase(namedField.name)}")
                         <#break>
                     <#case "optional">
                         <#assign optionalField = field.asOptionalField().orElseThrow()>
@@ -275,13 +275,16 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                         <#assign namedField = field.asNamedField().orElseThrow()>
 
         # Optional Field (${optionalField.name}) (Can be skipped, if the value is null)
+                        <#if optionalField.conditionExpression.present>
+        if ${helper.toSerializationExpression(optionalField, helper.boolTypeReference, optionalField.conditionExpression.get(), parserArguments)}:
                             <#if optionalField.type.isEnumTypeReference()>
-        write_buffer.${helper.getEnumDataWriterCall(optionalField.type, optionalField.name, "value")}(self.${helper.camelCaseToSnakeCase(optionalField.name)}, logical_name="${optionalField.name}")
+            write_buffer.${helper.getEnumDataWriterCall(optionalField.type, optionalField.name, "value")}(self.${helper.camelCaseToSnakeCase(optionalField.name)}, logical_name="${optionalField.name}")
                             <#elseif optionalField.type.isDataIoTypeReference()>
-        write_buffer.${helper.getDataWriterCall(typedField.type, optionalField.name)}(self.${helper.camelCaseToSnakeCase(optionalField.name)}, logical_name="${optionalField.name}", <#list optionalField.type.asComplexTypeReference().orElseThrow().params.orElseThrow() as param>${helper.toParseExpression(optionalField, helper.anyTypeReference, param, parserArguments)}<#sep>, </#sep></#list>)))
+            write_buffer.${helper.getDataWriterCall(typedField.type, optionalField.name)}(self.${helper.camelCaseToSnakeCase(optionalField.name)}, logical_name="${optionalField.name}", <#list optionalField.type.asComplexTypeReference().orElseThrow().params.orElseThrow() as param>${helper.toParseExpression(optionalField, helper.anyTypeReference, param, parserArguments)}<#sep>, </#sep></#list>)))
                             <#else>
-        write_buffer.${helper.getDataWriterCall(typedField.type, optionalField.name)}(self.${helper.camelCaseToSnakeCase(optionalField.name)}, logical_name="${optionalField.name}"<#if optionalField.conditionExpression.present></#if>)
+            write_buffer.${helper.getDataWriterCall(typedField.type, optionalField.name)}(self.${helper.camelCaseToSnakeCase(optionalField.name)}, logical_name="${optionalField.name}"<#if optionalField.conditionExpression.present></#if>)
                             </#if>
+                        </#if>
                         <#break>
                     <#case "padding">
                         <#assign paddingField = field.asPaddingField().orElseThrow()>
@@ -437,19 +440,20 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
 
         # Optional Field (${optionalField.name})
         <#if optionalField.type.isSimpleTypeReference()>
+        if ${helper.toSerializationExpression(optionalField, helper.boolTypeReference, optionalField.conditionExpression.get(), parserArguments)}:
             <#assign simpleTypeReference = optionalField.type.asSimpleTypeReference().orElseThrow()>
             <#if simpleTypeReference.isVstringTypeReference()>
                 <#assign vstringTypeReference = simpleTypeReference.asVstringTypeReference().orElseThrow()>
-        length_in_bits += ${helper.toSerializationExpression(optionalField, helper.intTypeReference, vstringTypeReference.getLengthExpression(), parserArguments)}
+            length_in_bits += ${helper.toSerializationExpression(optionalField, helper.intTypeReference, vstringTypeReference.getLengthExpression(), parserArguments)}
             <#else>
-        length_in_bits += ${simpleTypeReference.sizeInBits}
+            length_in_bits += ${simpleTypeReference.sizeInBits}
             </#if>
         <#elseif helper.isEnumField(field)>
-        length_in_bits += ${helper.getEnumBaseTypeReference(optionalField.type).sizeInBits}
+            length_in_bits += ${helper.getEnumBaseTypeReference(optionalField.type).sizeInBits}
         <#elseif optionalField.type.isDataIoTypeReference()>
-        length_in_bits += ${optionalField.type.asComplexTypeReference().orElseThrow().name}.length_in_bits(self.${helper.camelCaseToSnakeCase(optionalField.name)}<#if optionalField.type.asComplexTypeReference().orElseThrow().params?has_content>, <#list optionalField.type.asComplexTypeReference().orElseThrow().params.orElseThrow() as param>${helper.toParseExpression(optionalField, helper.anyTypeReference, param, parserArguments)}<#sep>, </#sep></#list></#if>)
+            length_in_bits += ${optionalField.type.asComplexTypeReference().orElseThrow().name}.length_in_bits(self.${helper.camelCaseToSnakeCase(optionalField.name)}<#if optionalField.type.asComplexTypeReference().orElseThrow().params?has_content>, <#list optionalField.type.asComplexTypeReference().orElseThrow().params.orElseThrow() as param>${helper.toParseExpression(optionalField, helper.anyTypeReference, param, parserArguments)}<#sep>, </#sep></#list></#if>)
         <#else>
-        length_in_bits += self.${helper.camelCaseToSnakeCase(optionalField.name)}.length_in_bits()
+            length_in_bits += self.${helper.camelCaseToSnakeCase(optionalField.name)}.length_in_bits()
         </#if>
 
         <#break>
@@ -595,7 +599,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                 <#assign typedField = field.asTypedField().orElseThrow()>
                 <#assign namedField = field.asNamedField().orElseThrow()>
 
-        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForField(field)} = read_buffer.${helper.getDataReaderCall(assertField.type)}(logical_name="${namedField.name}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)
+        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForField(field)} = read_buffer.${helper.getDataReaderCall(assertField.type)}(logical_name="${helper.camelCaseToSnakeCase(namedField.name)}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)
                 <#break>
             <#case "checksum">
                 <#assign checksumField = field.asChecksumField().orElseThrow()>
@@ -603,14 +607,14 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                 <#assign namedField = field.asNamedField().orElseThrow()>
                 <@emitImport import="from plc4py.protocols.${protocolName} import StaticHelper" />
 
-        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForField(field)} = read_buffer.${helper.getDataReaderCall(checksumField.type)}(logical_name="${namedField.name}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)
+        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForField(field)} = read_buffer.${helper.getDataReaderCall(checksumField.type)}(logical_name="${helper.camelCaseToSnakeCase(namedField.name)}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)
                 <#break>
             <#case "const">
                 <#assign constField = field.asConstField().orElseThrow()>
                 <#assign typedField = field.asTypedField().orElseThrow()>
                 <#assign namedField = field.asNamedField().orElseThrow()>
 
-        ${helper.camelCaseToSnakeCase(namedField.name)?upper_case}: ${helper.getLanguageTypeNameForField(field)} = read_buffer.${helper.getDataReaderCall(constField.type)}(logical_name="${namedField.name}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)
+        ${helper.camelCaseToSnakeCase(namedField.name)?upper_case}: ${helper.getLanguageTypeNameForField(field)} = read_buffer.${helper.getDataReaderCall(constField.type)}(logical_name="${helper.camelCaseToSnakeCase(namedField.name)}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)
                 <#break>
             <#case "discriminator">
                 <#assign discriminatorField = field.asDiscriminatorField().orElseThrow()>
@@ -618,9 +622,9 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                 <#assign namedField = field.asNamedField().orElseThrow()>
             <#if typedField.type.isSimpleTypeReference()>
                 <#assign simpleTypeReference = typedField.type.asSimpleTypeReference().orElseThrow()>
-        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForField(field)} = read_buffer.${helper.getDataReaderCall(discriminatorField.type)}(logical_name="${namedField.name}", bit_length=${simpleTypeReference.sizeInBits}${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)
+        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForField(field)} = read_buffer.${helper.getDataReaderCall(discriminatorField.type)}(logical_name="${helper.camelCaseToSnakeCase(namedField.name)}", bit_length=${simpleTypeReference.sizeInBits}${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)
             <#else>
-        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForField(field)} = read_buffer.${helper.getDataReaderCall(discriminatorField.type)}logical_name="${namedField.name}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)
+        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForField(field)} = read_buffer.${helper.getDataReaderCall(discriminatorField.type)}logical_name="${helper.camelCaseToSnakeCase(namedField.name)}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)
             </#if>
 
 
@@ -630,14 +634,14 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                 <#assign typedField = field.asTypedField().orElseThrow()>
                 <#assign namedField = field.asNamedField().orElseThrow()>
 
-        ${helper.camelCaseToSnakeCase(namedField.name)} = read_buffer.${helper.getDataReaderCall(enumField.type)}logical_name="${namedField.name}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)
+        ${helper.camelCaseToSnakeCase(namedField.name)} = read_buffer.${helper.getDataReaderCall(enumField.type)}logical_name="${helper.camelCaseToSnakeCase(namedField.name)}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)
                 <#break>
             <#case "implicit">
                 <#assign implicitField = field.asImplicitField().orElseThrow()>
                 <#assign typedField = field.asTypedField().orElseThrow()>
                 <#assign namedField = field.asNamedField().orElseThrow()>
 
-        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForField(field)} = read_buffer.${helper.getDataReaderCall(implicitField.type)}(logical_name="${namedField.name}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)
+        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForField(field)} = read_buffer.${helper.getDataReaderCall(implicitField.type)}(logical_name="${helper.camelCaseToSnakeCase(namedField.name)}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)
                 <#break>
             <#case "manualArray">
                 <#assign manualArrayField = field.asManualArrayField().orElseThrow()>
@@ -660,7 +664,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                 <#assign typedField = field.asTypedField().orElseThrow()>
                 <#assign namedField = field.asNamedField().orElseThrow()>
 
-        ${helper.camelCaseToSnakeCase(manualField.name)} = read_buffer.read_manual(read_function=lambda : StaticHelper.${helper.toParseExpression(manualField, manualField.type, manualField.parseExpression, parserArguments)}, logical_name="${namedField.name}")
+        ${helper.camelCaseToSnakeCase(manualField.name)} = read_buffer.read_manual(read_function=lambda : StaticHelper.${helper.toParseExpression(manualField, manualField.type, manualField.parseExpression, parserArguments)}, logical_name="${helper.camelCaseToSnakeCase(namedField.name)}")
                 <#break>
             <#case "optional">
                 <#assign optionalField = field.asOptionalField().orElseThrow()>
@@ -669,8 +673,8 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
 
         ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForTypeReference(optionalField.type, false)} = None
         <#if optionalField.conditionExpression.present>
-        if ${helper.toSerializationExpression(optionalField, helper.boolTypeReference, optionalField.conditionExpression.get(), parserArguments)}:
-            ${helper.camelCaseToSnakeCase(namedField.name)} = <#if typedField.type.isEnumTypeReference()>read_buffer.${helper.getDataReaderCall(optionalField.type)}bit_length=${helper.getEnumBaseTypeReference(typedField.type).sizeInBits}, logical_name="${namedField.name}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)<#else><#if optionalField.type.isComplexTypeReference()>read_buffer.${helper.getDataReaderCall(optionalField.type)}logic [...]
+        if ${helper.toParseExpression(optionalField, helper.boolTypeReference, optionalField.conditionExpression.get(), parserArguments)}:
+            ${helper.camelCaseToSnakeCase(namedField.name)} = <#if typedField.type.isEnumTypeReference()>read_buffer.${helper.getDataReaderCall(optionalField.type)}bit_length=${helper.getEnumBaseTypeReference(typedField.type).sizeInBits}, logical_name="${helper.camelCaseToSnakeCase(namedField.name)}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)<#else><#if optionalField.type.isComplexTypeReference()>read_buffer.${helper.getDataReaderC [...]
         </#if>
                 <#break>
             <#case "padding">
@@ -698,12 +702,12 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                     <#assign simpleTypeReference = typedField.type.asSimpleTypeReference().orElseThrow()>
                         <#if simpleTypeReference.isVstringTypeReference()>
                             <#assign vstringTypeReference = simpleTypeReference.asVstringTypeReference().orElseThrow()>
-        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForTypeReference(simpleField.type, false)} = <#if typedField.type.isEnumTypeReference()>read_buffer.${helper.getDataReaderCall(simpleField.type)}bit_length=${helper.toParseExpression(simpleField, helper.intTypeReference, vstringTypeReference.getLengthExpression(), parserArguments)}, logical_name="${namedField.name}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedLi [...]
+        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForTypeReference(simpleField.type, false)} = <#if typedField.type.isEnumTypeReference()>read_buffer.${helper.getDataReaderCall(simpleField.type)}bit_length=${helper.toParseExpression(simpleField, helper.intTypeReference, vstringTypeReference.getLengthExpression(), parserArguments)}, logical_name="${helper.camelCaseToSnakeCase(namedField.name)}"${helper.getFieldOptions(typedField, parserArguments)}<#if ha [...]
                         <#else>
-        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForTypeReference(simpleField.type, false)} = <#if typedField.type.isEnumTypeReference()>read_buffer.${helper.getDataReaderCall(simpleField.type)}bit_length=${simpleTypeReference.sizeInBits}, logical_name="${namedField.name}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)<#else><#if simpleField.type.isComplexTypeReference()>read_buffer.${helper.getDataR [...]
+        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForTypeReference(simpleField.type, false)} = <#if typedField.type.isEnumTypeReference()>read_buffer.${helper.getDataReaderCall(simpleField.type)}bit_length=${simpleTypeReference.sizeInBits}, logical_name="${helper.camelCaseToSnakeCase(namedField.name)}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)<#else><#if simpleField.type.isComplexTypeReference()> [...]
                         </#if>
                 <#else>
-        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForTypeReference(simpleField.type, false)} = <#if typedField.type.isEnumTypeReference()>read_buffer.${helper.getDataReaderCall(simpleField.type)}bit_length=${helper.getEnumBaseTypeReference(typedField.type).sizeInBits}, logical_name="${namedField.name}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)<#else><#if simpleField.type.isComplexTypeReference()> [...]
+        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForTypeReference(simpleField.type, false)} = <#if typedField.type.isEnumTypeReference()>read_buffer.${helper.getDataReaderCall(simpleField.type)}bit_length=${helper.getEnumBaseTypeReference(typedField.type).sizeInBits}, logical_name="${helper.camelCaseToSnakeCase(namedField.name)}"${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)<#else><#if simpleField.t [...]
                 </#if>
 
 
@@ -774,7 +778,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                 <#assign typedField = field.asTypedField().orElseThrow()>
                 <#assign namedField = field.asNamedField().orElseThrow()>
 
-        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForField(field)} = read_buffer.${helper.getDataReaderCall(peekField.type)}(logical_name="${namedField.name}"<#if peekField.offsetExpression.present>, ${helper.toParseExpression(peekField, helper.boolTypeReference, peekField.offsetExpression.get(), parserArguments)}</#if>${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)
+        ${helper.camelCaseToSnakeCase(namedField.name)}: ${helper.getLanguageTypeNameForField(field)} = read_buffer.${helper.getDataReaderCall(peekField.type)}(logical_name="${helper.camelCaseToSnakeCase(namedField.name)}"<#if peekField.offsetExpression.present>, ${helper.toParseExpression(peekField, helper.boolTypeReference, peekField.offsetExpression.get(), parserArguments)}</#if>${helper.getFieldOptions(typedField, parserArguments)}<#if hasParserArguments>, ${parsedList}</#if>)
                 <#break>
         </#switch>
     </#list>
diff --git a/plc4go/protocols/knxnetip/readwrite/model/KnxManufacturer.go b/plc4go/protocols/knxnetip/readwrite/model/KnxManufacturer.go
index 63e4c4b858..12adf9c50d 100644
--- a/plc4go/protocols/knxnetip/readwrite/model/KnxManufacturer.go
+++ b/plc4go/protocols/knxnetip/readwrite/model/KnxManufacturer.go
@@ -9510,10 +9510,6 @@ func KnxManufacturerByName(value string) (enum KnxManufacturer, ok bool) {
 		return KnxManufacturer_M_EUTELSAT, true
 	case "M_TECNIKABEL":
 		return KnxManufacturer_M_TECNIKABEL, true
-	case "M_ATIOS_AG":
-		return KnxManufacturer_M_ATIOS_AG, true
-	case "M_SMARTLICHT":
-		return KnxManufacturer_M_SMARTLICHT, true
 	case "M_ABB___RESERVED":
 		return KnxManufacturer_M_ABB___RESERVED, true
 	case "M_BUSCH_JAEGER_ELEKTRO___RESERVED":
@@ -10933,10 +10929,6 @@ func (e KnxManufacturer) PLC4XEnumName() string {
 		return "M_EUTELSAT"
 	case KnxManufacturer_M_TECNIKABEL:
 		return "M_TECNIKABEL"
-	case KnxManufacturer_M_ATIOS_AG:
-		return "M_ATIOS_AG"
-	case KnxManufacturer_M_SMARTLICHT:
-		return "M_SMARTLICHT"
 	case KnxManufacturer_M_ABB___RESERVED:
 		return "M_ABB___RESERVED"
 	case KnxManufacturer_M_BUSCH_JAEGER_ELEKTRO___RESERVED:
diff --git a/plc4py/plc4py/PlcDriverManager.py b/plc4py/plc4py/PlcDriverManager.py
index a61eec9497..e5e6c083e9 100644
--- a/plc4py/plc4py/PlcDriverManager.py
+++ b/plc4py/plc4py/PlcDriverManager.py
@@ -35,24 +35,47 @@ class PlcDriverManager:
     _driver_map: Dict[str, Type[PlcDriver]] = field(default_factory=lambda: {})
 
     def __post_init__(self):
+        """
+        Initialize the PLC Driver Manager.
+
+        This function is called automatically when a new instance of the
+        PlcDriverManager class is created.
+
+        It registers the available drivers, by loading the entry points
+        defined in the "plc4py.drivers" namespace.
+        """
+        # Log the class loader used
         logging.info(
             f"Instantiating new PLC Driver Manager with class loader {self.class_loader}"
         )
+
+        # Add the PlcDriverClassLoader hookspecs to the class loader
         self.class_loader.add_hookspecs(PlcDriverClassLoader)
+
+        # Log the registration of drivers
         logging.info("Registering available drivers...")
 
+        # Register the plc4py.drivers package
         import plc4py.drivers
 
         self.class_loader.register(plc4py.drivers)
+
+        # Load the setuptools entry points defined in the "plc4py.drivers" namespace
         self.class_loader.load_setuptools_entrypoints("plc4py.drivers")
+
+        # Create a dictionary mapping the hook names to the PlcDriver instances
         self._driver_map = {
             key: loader
             for key, loader in zip(
                 self.class_loader.hook.key(), self.class_loader.hook.get_driver()
             )
         }
+
+        # Log the successful registration of each driver
         for driver in self._driver_map:
             logging.info(f"... {driver} .. OK")
+
+        # Check for any pending plugins
         self.class_loader.check_pending()
 
     @asynccontextmanager
@@ -95,9 +118,13 @@ class PlcDriverManager:
 
     def get_driver_for_url(self, url: str) -> Type[PlcDriver]:
         """
-        Returns the driver class that matches that identified within the connection string
+        Returns the driver class that matches the one identified within the connection string.
+
         :param url: The plc connection string
-        :return: the protocol code
+        :return: The driver class that matches the protocol code identified within the connection string
         """
+        # Extract the protocol code from the connection string
         protocol_code = get_protocol_code(url)
+
+        # Retrieve the driver class using the protocol code
         return self._driver_map[protocol_code]
diff --git a/plc4py/plc4py/drivers/modbus/ModbusConfiguration.py b/plc4py/plc4py/drivers/modbus/ModbusConfiguration.py
index f3d897b168..e76707ad85 100644
--- a/plc4py/plc4py/drivers/modbus/ModbusConfiguration.py
+++ b/plc4py/plc4py/drivers/modbus/ModbusConfiguration.py
@@ -25,13 +25,17 @@ class ModbusConfiguration(PlcConfiguration):
     """
 
     def __init__(self, url):
-        super().__init__(url)
-
-        if self.transport is None:
-            self.transport = "tcp"
+        """
+        Initializes the ModbusConfiguration with the given URL.
 
-        if self.port is None:
-            self.port = 502
+        Args:
+            url (str): The URL of the Modbus device.
+        """
+        super().__init__(url)
 
-        if "unit_identifier" not in self.parameters:
-            self.unit_identifier = 1
+        # Set the transport to TCP if not specified
+        self.transport = self.transport or "tcp"
+        # Set the port to 502 if not specified
+        self.port = self.port or 502
+        # Get the unit identifier from the parameters, default to 1
+        self.unit_identifier = self.parameters.get("unit_identifier", 1)
diff --git a/plc4py/plc4py/drivers/modbus/ModbusConnection.py b/plc4py/plc4py/drivers/modbus/ModbusConnection.py
index a032153a77..d483afdcfc 100644
--- a/plc4py/plc4py/drivers/modbus/ModbusConnection.py
+++ b/plc4py/plc4py/drivers/modbus/ModbusConnection.py
@@ -54,14 +54,34 @@ class ModbusConnection(PlcConnection, PlcReader, PlcWriter, PlcConnectionMetaDat
     Modbus TCP PLC connection implementation
     """
 
+    """
+    Initialization of ModbusConnection object
+
+    :param config: Modbus configuration object
+    :param transport: Plc4xBaseTransport object used for the TCP connection
+    """
+
     def __init__(self, config: ModbusConfiguration, transport: Plc4xBaseTransport):
+        """
+        Initializes a ModbusConnection object
+
+        :param config: Modbus configuration object
+        :param transport: Plc4xBaseTransport object used for the TCP connection
+        """
         super().__init__(config)
-        self._configuration: ModbusConfiguration
+        self._configuration: ModbusConfiguration = config
+        """
+        ModbusDevice object that encapsulates the PLC device configuration
+        and provides methods for device related operations
+        """
         self._device: ModbusDevice = ModbusDevice(self._configuration)
+        """
+        Plc4xBaseTransport object used for the TCP connection
+        """
         self._transport: Plc4xBaseTransport = transport
 
     @staticmethod
-    async def create(url: str):
+    async def create(url: str) -> "ModbusConnection":
         """
         Static Factory to return an instance of a ModbusConnection.
         It creates the TCP connection to the Modbus device before returning.
@@ -69,27 +89,52 @@ class ModbusConnection(PlcConnection, PlcReader, PlcWriter, PlcConnectionMetaDat
         :param url: PLC4X connection string of the Modbus TCP connection
         :return ModbusConnection instance using the configuration from the url provided
         """
+        # Extract configuration from the given url
         config = ModbusConfiguration(url)
+        # Create a future to manage the creation of the TCP connection
         loop = asyncio.get_running_loop()
         connection_future = loop.create_future()
-        transport = await asyncio.wait_for(
-            TCPTransport.create(
-                protocol_factory=lambda: ModbusProtocol(connection_future),
-                host=config.host,
-                port=config.port,
-            ),
-            10,
-        )
+        # Create the TCP connection to the Modbus device.
+        # The creation process is asynchronous and takes up to 10 seconds.
+        # If the creation fails, the Future is cancelled.
+        try:
+            transport = await asyncio.wait_for(
+                TCPTransport.create(
+                    protocol_factory=lambda: ModbusProtocol(connection_future),
+                    host=config.host,
+                    port=config.port,
+                ),
+                10,
+            )
+        except asyncio.TimeoutError:
+            # If the creation times out, cancel the Future
+            connection_future.cancel()
+            raise ValueError(
+                f"Failed to connect to {url} in 10 seconds. "
+                "Please check the PLC device is running and the connection string is correct."
+            )
+        # If the creation succeeds, return a ModbusConnection object
+        # using the configuration from the url provided and the transport
         return ModbusConnection(config, transport)
 
     def is_connected(self) -> bool:
         """
         Indicates if the connection is established to a remote PLC.
+
         :return: True if connection, False otherwise
         """
+        """
+        The function checks if the connection to the remote PLC is established.
+        The connection is considered established if the transport object is not None
+        and the transport is not closing.
+
+        :return bool: True if connection, False otherwise
+        """
         if self._transport is not None:
+            # The transport is not None if a connection is established
             return not self._transport.is_closing()
         else:
+            # The transport is None if no connection is established
             return False
 
     def close(self) -> None:
@@ -106,7 +151,7 @@ class ModbusConnection(PlcConnection, PlcReader, PlcWriter, PlcConnectionMetaDat
         """
         return DefaultReadRequestBuilder(ModbusTagBuilder)
 
-    async def execute(self, request: PlcRequest) -> PlcResponse:
+    def execute(self, request: PlcRequest) -> Awaitable[PlcResponse]:
         """
         Executes a PlcRequest as long as it's already connected
         :param request: Plc Request to execute
@@ -116,47 +161,91 @@ class ModbusConnection(PlcConnection, PlcReader, PlcWriter, PlcConnectionMetaDat
             return self._default_failed_request(PlcResponseCode.NOT_CONNECTED)
 
         if isinstance(request, PlcReadRequest):
-            return await self._read(request)
+            return self._read(request)
+
         elif isinstance(request, PlcWriteRequest):
-            return await self._write(request)
+            return self._write(request)
 
         return self._default_failed_request(PlcResponseCode.NOT_CONNECTED)
 
     def _check_connection(self) -> bool:
+        """
+        Checks if a ModbusDevice is set.
+
+        :return: True if no device is set, False otherwise.
+        """
+        """
+        A ModbusDevice is only set if the device was successfully connected during the constructor.
+        If no device is set, it's not possible to execute any read or write requests.
+
+        This method is used to prevent calling methods on the ModbusConnection which are not possible
+        if no device is set.
+        """
         return self._device is None
 
-    async def _read(self, request: PlcReadRequest) -> PlcReadResponse:
+    def _read(self, request: PlcReadRequest) -> Awaitable[PlcReadResponse]:
         """
         Executes a PlcReadRequest
+
+        This method sends a read request to the connected modbus device and waits for a response.
+        The response is then returned as a PlcReadResponse.
+
+        If no device is set, an error is logged and a PlcResponseCode.NOT_CONNECTED is returned.
+        If an error occurs during the execution of the read request, a PlcResponseCode.INTERNAL_ERROR is
+        returned.
+
+        :param request: PlcReadRequest to execute
+        :return: PlcReadResponse
         """
-        if self._check_connection():
-            logging.error("No device is set in the modbus connection!")
+        if self._device is None:
+            logging.error("No device is set in the Umas connection!")
             return self._default_failed_request(PlcResponseCode.NOT_CONNECTED)
-        try:
-            logging.debug("Sending read request to Modbus Device")
-            response = await asyncio.wait_for(
-                self._device.read(request, self._transport), 5
-            )
-            return response
-        except Exception:
-            # TODO:- This exception is very general and probably should be replaced
-            return PlcReadResponse(PlcResponseCode.INTERNAL_ERROR, {})
 
-    async def _write(self, request: PlcWriteRequest) -> PlcTagResponse:
+        # TODO: Insert Optimizer base on data from a browse request
+        async def _request(req, device) -> PlcReadResponse:
+            try:
+                response = await asyncio.wait_for(device.read(req, self._transport), 10)
+                return response
+            except Exception:
+                # TODO:- This exception is very general and probably should be replaced
+
+                return PlcReadResponse(PlcResponseCode.INTERNAL_ERROR, {})
+
+        logging.debug("Sending read request to UmasDevice")
+        future = asyncio.ensure_future(_request(request, self._device))
+        return future
+
+    async def _write(self, request: PlcWriteRequest) -> PlcWriteResponse:
         """
         Executes a PlcWriteRequest
+
+        This method sends a write request to the connected Modbus device and waits for a response.
+        The response is then returned as a PlcWriteResponse.
+
+        If no device is set, an error is logged and a PlcWriteResponse with the
+        PlcResponseCode.NOT_CONNECTED code is returned.
+        If an error occurs during the execution of the write request, a
+        PlcWriteResponse with the PlcResponseCode.INTERNAL_ERROR code is returned.
+
+        :param request: PlcWriteRequest to execute
+        :return: PlcWriteResponse
         """
         if self._check_connection():
+            # If no device is set, log an error and return a response with the NOT_CONNECTED code
             logging.error("No device is set in the modbus connection!")
             return self._default_failed_request(PlcResponseCode.NOT_CONNECTED)
 
         try:
+            # Send the write request to the device and wait for a response
             logging.debug("Sending write request to Modbus Device")
             response = await asyncio.wait_for(
                 self._device.write(request, self._transport), 5
             )
+            # Return the response
             return response
         except Exception:
+            # If an error occurs during the execution of the write request, return a response with
+            # the INTERNAL_ERROR code. This exception is very general and probably should be replaced.
             # TODO:- This exception is very general and probably should be replaced
             return PlcWriteResponse(PlcResponseCode.INTERNAL_ERROR, {})
 
@@ -195,11 +284,25 @@ class ModbusDriver(PlcDriver):
         self.protocol_code = "modbus-tcp"
         self.protocol_name = "Modbus TCP"
 
+    """
+    Creates a new PlcConnection instance using the given URL.
+
+    This method is an asynchronous entry point to connect to a PLC using the Modbus TCP protocol.
+    It takes a URL (e.g. "tcp://<ip address>:<port>") as input and an optional PlcAuthentication instance.
+    The authentication instance is used to authenticate the connection. If it is not provided, the connection will
+    be attempted without authentication.
+
+    :param url: URL of the PLC to connect to (e.g. "tcp://<ip address>:<port>")
+    :param authentication: Optional PlcAuthentication instance used to authenticate the connection.
+    :return: An instance of PlcConnection that is connected to the PLC
+    """
+
     async def get_connection(
         self, url: str, authentication: PlcAuthentication = PlcAuthentication()
     ) -> PlcConnection:
         """
         Connects to a PLC using the given plc connection string.
+
         :param url: plc connection string
         :param authentication: authentication credentials.
         :return PlcConnection: PLC Connection object
@@ -215,9 +318,23 @@ class ModbusDriverLoader(PlcDriverLoader):
     @staticmethod
     @plc4py.hookimpl
     def get_driver() -> Type[ModbusDriver]:
+        """
+        Returns the ModbusDriver class used to instantiate Modbus plc drivers.
+
+        This method is an entry point for pluggy to load the Modbus driver.
+
+        :return Type[ModbusDriver]: ModbusDriver class used to instantiate Modbus plc drivers
+        """
         return ModbusDriver
 
     @staticmethod
     @plc4py.hookimpl
     def key() -> str:
+        """
+        Returns the unique key for the Modbus driver.
+
+        The key is used by PlcDriverManager to identify the driver.
+
+        :return str: Unique key for the Modbus driver
+        """
         return "modbus"
diff --git a/plc4py/plc4py/drivers/modbus/ModbusDevice.py b/plc4py/plc4py/drivers/modbus/ModbusDevice.py
index 977b9287e1..dedda15406 100644
--- a/plc4py/plc4py/drivers/modbus/ModbusDevice.py
+++ b/plc4py/plc4py/drivers/modbus/ModbusDevice.py
@@ -143,6 +143,7 @@ class ModbusDevice:
             read_buffer,
             request.tags[request.tag_names[0]].data_type,
             request.tags[request.tag_names[0]].quantity,
+            True,
         )
 
         response_item = ResponseItem(PlcResponseCode.OK, returned_value)
diff --git a/plc4py/plc4py/drivers/modbus/ModbusProtocol.py b/plc4py/plc4py/drivers/modbus/ModbusProtocol.py
index 8bd38f24b1..f3ae557611 100644
--- a/plc4py/plc4py/drivers/modbus/ModbusProtocol.py
+++ b/plc4py/plc4py/drivers/modbus/ModbusProtocol.py
@@ -34,37 +34,99 @@ class ModbusProtocol(Plc4xBaseProtocol):
     messages: Dict[int, Future] = field(default_factory=lambda: {})
 
     def packet_length_estimator(self, read_buffer: ReadBufferByteBased):
+        """
+        Estimate the length of the packet based on the provided `read_buffer`.
+
+        Args:
+            read_buffer (ReadBufferByteBased): The buffer containing the data to be read.
+
+        Returns:
+            bool: True if the estimated packet length plus the current position is less than the length of the buffer, False otherwise.
+        """
         current_position = read_buffer.position
+        logging.debug(
+            f"Current position in packet_length_estimator: {current_position}"
+        )
         read_buffer.position = 8 * 4
         packet_length: int = read_buffer.read_unsigned_short()
+        logging.debug(f"Packet length in packet_length_estimator: {packet_length}")
         read_buffer.position = current_position
+        logging.debug(
+            f"Buffer length in packet_length_estimator: {len(read_buffer.bb)}"
+        )
         return packet_length + current_position < len(read_buffer.bb)
 
     def data_received(self, data):
-        """Unpack the adu and return the pdu"""
+        """
+        Unpack the adu and return the pdu.
+
+        This function continuously processes incoming data until the complete
+        ADU (ModbusTcpADU) is extracted. If the ADU transaction identifier is
+        found in the messages dictionary, the corresponding PDU (data) is set
+        as a result of the associated Future object. If the transaction
+        identifier is not found, an error message is logged and the connection
+        is closed.
+
+        Args:
+            data (bytes): The raw data received from the transport.
+        """
+        # Convert data to ReadBufferByteBased
         read_buffer = ReadBufferByteBased(
             bytearray(data), byte_order=ByteOrder.BIG_ENDIAN
         )
+
+        # Continuously process incoming data until the complete ADU is
+        # extracted.
         while self.packet_length_estimator(read_buffer):
+            logging.debug(f"Processing {len(data)} bytes of data")
+            # Parse the ADU from the ReadBufferByteBased.
             adu: ModbusTcpADU = ModbusTcpADU.static_parse_builder(
                 read_buffer, DriverType.MODBUS_TCP, True
             ).build(True)
+            # logging.debug(f"Received ADU: {adu}")
+            # If the ADU transaction identifier is in the messages dictionary,
+            # set the PDU (data) as a result of the associated Future object.
             if adu.transaction_identifier in self.messages:
+                logging.debug(f"Found transaction ID {adu.transaction_identifier}")
                 self.messages[adu.transaction_identifier].set_result(adu.pdu)
                 self.messages.pop(adu.transaction_identifier)
+            # If the ADU transaction identifier is not found, log an error
+            # message and close the connection.
             else:
                 logging.error("Unsolicited message returned")
+                logging.debug(f"Transaction ID {adu.transaction_identifier} not found")
                 self.close()
 
     def write_wait_for_response(self, data, transport, transaction_id, message_future):
-        """Writes a message to the wire and records the identifier to identify and route the response"""
+        """
+        Writes a message to the wire and records the transaction identifier to identify and route the response.
+
+        Args:
+            data (bytes): The data to be written to the wire.
+            transport (asyncio.Transport): The transport to use for writing the data.
+            transaction_id (int): The transaction identifier of the message.
+            message_future (concurrent.futures.Future): The future to set the result of when the response is received.
+        """
+        # Record the message's transaction identifier and the future to set the result of.
         self.messages[transaction_id] = message_future
+        # Write the data to the wire.
         transport.write(data)
 
     def close(self):
-        """Clean up the message which didn't receive a response"""
-        for key, message in self.messages.items:
+        """
+        Clean up the message which didn't receive a response.
+
+        This function iterates over the messages dictionary,
+        sets the result of each message to None and removes it from the dictionary.
+        After that, it sets the messages dictionary to None.
+        """
+        # Iterate over the messages dictionary
+        for key, message in self.messages.items():
+            # Log the removal of un-replied message
             logging.debug("Removing un-replied message with identifier " + str(key))
+            # Set the result of the message to None
             message.set_result(None)
-            self.messages.pop()
+            # Remove the message from the dictionary
+            self.messages.pop(key)
+        # Set the messages dictionary to None
         self.messages = None
diff --git a/plc4py/plc4py/drivers/umas/UmasDevice.py b/plc4py/plc4py/drivers/umas/UmasDevice.py
index 91d67d2f07..0adc3210e1 100644
--- a/plc4py/plc4py/drivers/umas/UmasDevice.py
+++ b/plc4py/plc4py/drivers/umas/UmasDevice.py
@@ -87,8 +87,8 @@ from plc4py.protocols.umas.readwrite.UmasPDUReadVariableResponse import (
 from plc4py.protocols.umas.readwrite.UmasUnlocatedVariableReference import (
     UmasUnlocatedVariableReference,
 )
-from plc4py.protocols.umas.readwrite.VariableRequestReference import (
-    VariableRequestReference,
+from plc4py.protocols.umas.readwrite.VariableReadRequestReference import (
+    VariableReadRequestReference,
 )
 from plc4py.spi.generation.ReadBuffer import ReadBufferByteBased
 from plc4py.spi.messages.utils.ResponseItem import ResponseItem
@@ -351,7 +351,7 @@ class UmasDevice:
     ):
         message_future = loop.create_future()
 
-        sorted_variable_list: List[VariableRequestReference] = [
+        sorted_variable_list: List[VariableReadRequestReference] = [
             variable_reference[1] for variable_reference in sorted_tags
         ]
         request_pdu = UmasPDUReadVariableRequestBuilder(
@@ -391,7 +391,7 @@ class UmasDevice:
         return response
 
     def _sort_tags_based_on_memory_address(self, request):
-        tag_list: List[List[Tuple[str, VariableRequestReference]]] = [[]]
+        tag_list: List[List[Tuple[str, VariableReadRequestReference]]] = [[]]
         current_list_index = 0
         current_list = tag_list[current_list_index]
         byte_count: int = 0
@@ -412,7 +412,8 @@ class UmasDevice:
                     variable.get_variable_reference(umas_tag.tag_name),
                 )
             )
-        sorted_tag_lists: List[List[Tuple[str, VariableRequestReference]]] = []
+
+        sorted_tag_lists: List[List[Tuple[str, VariableReadRequestReference]]] = []
         for request in tag_list:
             sorted_tags = sorted(
                 request,
diff --git a/plc4py/plc4py/drivers/umas/UmasVariables.py b/plc4py/plc4py/drivers/umas/UmasVariables.py
index 344034936c..27b90c0d6b 100644
--- a/plc4py/plc4py/drivers/umas/UmasVariables.py
+++ b/plc4py/plc4py/drivers/umas/UmasVariables.py
@@ -22,8 +22,8 @@ from typing import Dict, List, Pattern, AnyStr, Union
 
 from plc4py.protocols.umas.readwrite.UmasDataType import UmasDataType
 
-from plc4py.protocols.umas.readwrite.VariableRequestReference import (
-    VariableRequestReference,
+from plc4py.protocols.umas.readwrite.VariableReadRequestReference import (
+    VariableReadRequestReference,
 )
 
 from plc4py.api.exceptions.exceptions import PlcDataTypeNotFoundException
@@ -42,7 +42,7 @@ class UmasVariable:
     block_no: int
     offset: int
 
-    def get_variable_reference(self, address: str) -> VariableRequestReference:
+    def get_variable_reference(self, address: str) -> VariableReadRequestReference:
         raise NotImplementedError(
             f"UmasVariable subclass not implemented for variable {self.variable_name}"
         )
@@ -55,9 +55,9 @@ class UmasVariable:
 
 @dataclass
 class UmasElementryVariable(UmasVariable):
-    def get_variable_reference(self, address: str) -> VariableRequestReference:
+    def get_variable_reference(self, address: str) -> VariableReadRequestReference:
         if self.data_type == UmasDataType.STRING.value:
-            return VariableRequestReference(
+            return VariableReadRequestReference(
                 is_array=1,
                 data_size_index=UmasDataType(self.data_type).request_size,
                 block=self.block_no,
@@ -66,7 +66,7 @@ class UmasElementryVariable(UmasVariable):
                 array_length=16,
             )
         else:
-            return VariableRequestReference(
+            return VariableReadRequestReference(
                 is_array=0,
                 data_size_index=UmasDataType(self.data_type).request_size,
                 block=self.block_no,
@@ -83,7 +83,7 @@ class UmasElementryVariable(UmasVariable):
 class UmasCustomVariable(UmasVariable):
     children: Dict[str, UmasVariable]
 
-    def get_variable_reference(self, address: str) -> VariableRequestReference:
+    def get_variable_reference(self, address: str) -> VariableReadRequestReference:
         split_tag_address: List[str] = address.split(".")
         child_index = None
         if len(split_tag_address) > 1:
@@ -106,14 +106,14 @@ class UmasArrayVariable(UmasVariable):
     start_index: int
     end_index: int
 
-    def get_variable_reference(self, address: str) -> VariableRequestReference:
+    def get_variable_reference(self, address: str) -> VariableReadRequestReference:
         split_tag_address: List[str] = address.split(".")
         address_index = None
         if len(split_tag_address) > 1:
             address_index = int(split_tag_address[1])
         data_type_enum = UmasDataType(self.data_type)
         if address_index:
-            return VariableRequestReference(
+            return VariableReadRequestReference(
                 is_array=0,
                 data_size_index=data_type_enum.request_size,
                 block=self.block_no,
@@ -123,7 +123,7 @@ class UmasArrayVariable(UmasVariable):
                 array_length=None,
             )
         else:
-            return VariableRequestReference(
+            return VariableReadRequestReference(
                 is_array=1,
                 data_size_index=data_type_enum.request_size,
                 block=self.block_no,
diff --git a/plc4py/plc4py/protocols/modbus/StaticHelper.py b/plc4py/plc4py/protocols/modbus/StaticHelper.py
index 8ac962bb5a..386dd2e6bd 100644
--- a/plc4py/plc4py/protocols/modbus/StaticHelper.py
+++ b/plc4py/plc4py/protocols/modbus/StaticHelper.py
@@ -63,6 +63,13 @@ auch_crc_lo: bytearray = bytearray(
 
 
 def rtu_crc_check(address: int, pdu: ModbusPDU) -> int:
+    """
+    Calculates the RTU style CRC16 value for a given PDU and address.
+
+    :param address: The address of the PDU.
+    :param pdu: The PDU to calculate the CRC for.
+    :return: The calculated CRC16 value.
+    """
     # Using the algorithm from PI_MBUS_300.pdf page 121
     write_buffer: WriteBufferByteBased = WriteBufferByteBased(
         pdu.length_in_bytes() + 2, byte_order=ByteOrder.LITTLE_ENDIAN
@@ -73,10 +80,14 @@ def rtu_crc_check(address: int, pdu: ModbusPDU) -> int:
     uch_crc_hi: int = 0xFF
     uch_crc_lo: int = 0xFF
     u_index: int
+    # Calculate the CRC16 value
     for b in m_view:
+        # XOR the current byte with the high byte of the CRC
         u_index = (uch_crc_hi ^ b) & 0xFF
-        uch_crc_hi = uch_crc_lo ^ auch_crc_hi[u_index]
-        uch_crc_lo = auch_crc_lo[u_index]
+        # Swap the high and low bytes, then XOR the low byte with
+        # the current high byte
+        uch_crc_hi, uch_crc_lo = uch_crc_lo ^ auch_crc_hi[u_index], uch_crc_hi
+    # Return the calculated CRC16 value
     return ((uch_crc_hi << 8) & 0xFFFF) | (uch_crc_lo & 0x00FF)
 
 
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusConstants.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusConstants.py
index 56c576964c..3047aab843 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusConstants.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusConstants.py
@@ -62,7 +62,7 @@ class ModbusConstants:
         read_buffer.push_context("ModbusConstants")
 
         MODBUS_TCP_DEFAULT_PORT: int = read_buffer.read_unsigned_short(
-            logical_name="modbusTcpDefaultPort"
+            logical_name="modbus_tcp_default_port"
         )
 
         read_buffer.pop_context("ModbusConstants")
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationObject.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationObject.py
index 800b8b89de..f862361bd6 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationObject.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationObject.py
@@ -44,7 +44,7 @@ class ModbusDeviceInformationObject:
 
         # Implicit Field (object_length) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         object_length: int = int(len(self.data))
-        write_buffer.write_unsigned_byte(object_length, logical_name="objectLength")
+        write_buffer.write_unsigned_byte(object_length, logical_name="object_length")
 
         # Array Field (data)
         write_buffer.write_byte_array(self.data, logical_name="data")
@@ -79,10 +79,12 @@ class ModbusDeviceInformationObject:
         read_buffer.push_context("ModbusDeviceInformationObject")
 
         object_id: int = read_buffer.read_unsigned_byte(
-            logical_name="objectId", bit_length=8
+            logical_name="object_id", bit_length=8
         )
 
-        object_length: int = read_buffer.read_unsigned_byte(logical_name="objectLength")
+        object_length: int = read_buffer.read_unsigned_byte(
+            logical_name="object_length"
+        )
 
         data: List[Any] = read_buffer.read_array_field(
             logical_name="data",
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDU.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDU.py
index bf1abb4bfd..8b13c367e1 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDU.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDU.py
@@ -54,11 +54,11 @@ class ModbusPDU(ABC, PlcMessage):
         write_buffer.push_context("ModbusPDU")
 
         # Discriminator Field (errorFlag) (Used as input to a switch field)
-        write_buffer.write_bit(self.error_flag, logical_name="errorFlag", bit_length=1)
+        write_buffer.write_bit(self.error_flag, logical_name="error_flag", bit_length=1)
 
         # Discriminator Field (functionFlag) (Used as input to a switch field)
         write_buffer.write_unsigned_byte(
-            self.function_flag, logical_name="functionFlag", bit_length=7
+            self.function_flag, logical_name="function_flag", bit_length=7
         )
 
         # Switch field (Serialize the sub-type)
@@ -108,11 +108,11 @@ class ModbusPDU(ABC, PlcMessage):
     def static_parse_context(read_buffer: ReadBuffer, response: bool):
         read_buffer.push_context("ModbusPDU")
         error_flag: bool = read_buffer.read_bit(
-            logical_name="errorFlag", bit_length=1, response=response
+            logical_name="error_flag", bit_length=1, response=response
         )
 
         function_flag: int = read_buffer.read_unsigned_byte(
-            logical_name="functionFlag", bit_length=7, response=response
+            logical_name="function_flag", bit_length=7, response=response
         )
 
         # Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticRequest.py
index 95e0102b9c..7352d366ea 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticRequest.py
@@ -71,7 +71,7 @@ class ModbusPDUDiagnosticRequest(ModbusPDU):
         read_buffer.push_context("ModbusPDUDiagnosticRequest")
 
         sub_function: int = read_buffer.read_unsigned_short(
-            logical_name="subFunction", bit_length=16, response=response
+            logical_name="sub_function", bit_length=16, response=response
         )
 
         data: int = read_buffer.read_unsigned_short(
@@ -119,7 +119,7 @@ class ModbusPDUDiagnosticRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUDiagnosticRequest:
-        modbus_pdu_diagnostic_request: ModbusPDUDiagnosticRequest = (
+        modbus_pdudiagnostic_request: ModbusPDUDiagnosticRequest = (
             ModbusPDUDiagnosticRequest(self.sub_function, self.data)
         )
-        return modbus_pdu_diagnostic_request
+        return modbus_pdudiagnostic_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticResponse.py
index f2e7e75309..23356067e2 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticResponse.py
@@ -71,7 +71,7 @@ class ModbusPDUDiagnosticResponse(ModbusPDU):
         read_buffer.push_context("ModbusPDUDiagnosticResponse")
 
         sub_function: int = read_buffer.read_unsigned_short(
-            logical_name="subFunction", bit_length=16, response=response
+            logical_name="sub_function", bit_length=16, response=response
         )
 
         data: int = read_buffer.read_unsigned_short(
@@ -119,7 +119,7 @@ class ModbusPDUDiagnosticResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUDiagnosticResponse:
-        modbus_pdu_diagnostic_response: ModbusPDUDiagnosticResponse = (
+        modbus_pdudiagnostic_response: ModbusPDUDiagnosticResponse = (
             ModbusPDUDiagnosticResponse(self.sub_function, self.data)
         )
-        return modbus_pdu_diagnostic_response
+        return modbus_pdudiagnostic_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUError.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUError.py
index 45b04779cc..6931affc51 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUError.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUError.py
@@ -67,7 +67,7 @@ class ModbusPDUError(ModbusPDU):
         exception_code: ModbusErrorCode = read_buffer.read_enum(
             read_function=ModbusErrorCode,
             bit_length=8,
-            logical_name="exceptionCode",
+            logical_name="exception_code",
             response=response,
         )
 
@@ -110,5 +110,5 @@ class ModbusPDUErrorBuilder:
     def build(
         self,
     ) -> ModbusPDUError:
-        modbus_pdu_error: ModbusPDUError = ModbusPDUError(self.exception_code)
-        return modbus_pdu_error
+        modbus_pduerror: ModbusPDUError = ModbusPDUError(self.exception_code)
+        return modbus_pduerror
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterRequest.py
index bdc1516faa..af9594f09a 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterRequest.py
@@ -88,7 +88,7 @@ class ModbusPDUGetComEventCounterRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUGetComEventCounterRequest:
-        modbus_pdu_get_com_event_counter_request: ModbusPDUGetComEventCounterRequest = (
+        modbus_pduget_com_event_counter_request: ModbusPDUGetComEventCounterRequest = (
             ModbusPDUGetComEventCounterRequest()
         )
-        return modbus_pdu_get_com_event_counter_request
+        return modbus_pduget_com_event_counter_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterResponse.py
index dd701be457..81532a092c 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterResponse.py
@@ -77,7 +77,7 @@ class ModbusPDUGetComEventCounterResponse(ModbusPDU):
         )
 
         event_count: int = read_buffer.read_unsigned_short(
-            logical_name="eventCount", bit_length=16, response=response
+            logical_name="event_count", bit_length=16, response=response
         )
 
         read_buffer.pop_context("ModbusPDUGetComEventCounterResponse")
@@ -123,7 +123,7 @@ class ModbusPDUGetComEventCounterResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUGetComEventCounterResponse:
-        modbus_pdu_get_com_event_counter_response: (
+        modbus_pduget_com_event_counter_response: (
             ModbusPDUGetComEventCounterResponse
         ) = ModbusPDUGetComEventCounterResponse(self.status, self.event_count)
-        return modbus_pdu_get_com_event_counter_response
+        return modbus_pduget_com_event_counter_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogRequest.py
index 46d19473df..29fdeb2c36 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogRequest.py
@@ -88,7 +88,7 @@ class ModbusPDUGetComEventLogRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUGetComEventLogRequest:
-        modbus_pdu_get_com_event_log_request: ModbusPDUGetComEventLogRequest = (
+        modbus_pduget_com_event_log_request: ModbusPDUGetComEventLogRequest = (
             ModbusPDUGetComEventLogRequest()
         )
-        return modbus_pdu_get_com_event_log_request
+        return modbus_pduget_com_event_log_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogResponse.py
index 5b38c5fb6b..a2e702c7d5 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogResponse.py
@@ -47,7 +47,7 @@ class ModbusPDUGetComEventLogResponse(ModbusPDU):
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         byte_count: int = int(len(self.events)) + int(6)
-        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byte_count")
 
         # Simple Field (status)
         write_buffer.write_unsigned_short(
@@ -99,7 +99,7 @@ class ModbusPDUGetComEventLogResponse(ModbusPDU):
         read_buffer.push_context("ModbusPDUGetComEventLogResponse")
 
         byte_count: int = read_buffer.read_unsigned_byte(
-            logical_name="byteCount", response=response
+            logical_name="byte_count", response=response
         )
 
         status: int = read_buffer.read_unsigned_short(
@@ -107,11 +107,11 @@ class ModbusPDUGetComEventLogResponse(ModbusPDU):
         )
 
         event_count: int = read_buffer.read_unsigned_short(
-            logical_name="eventCount", bit_length=16, response=response
+            logical_name="event_count", bit_length=16, response=response
         )
 
         message_count: int = read_buffer.read_unsigned_short(
-            logical_name="messageCount", bit_length=16, response=response
+            logical_name="message_count", bit_length=16, response=response
         )
 
         events: List[Any] = read_buffer.read_array_field(
@@ -168,9 +168,9 @@ class ModbusPDUGetComEventLogResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUGetComEventLogResponse:
-        modbus_pdu_get_com_event_log_response: ModbusPDUGetComEventLogResponse = (
+        modbus_pduget_com_event_log_response: ModbusPDUGetComEventLogResponse = (
             ModbusPDUGetComEventLogResponse(
                 self.status, self.event_count, self.message_count, self.events
             )
         )
-        return modbus_pdu_get_com_event_log_response
+        return modbus_pduget_com_event_log_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterRequest.py
index 724e7235be..ac2317b491 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterRequest.py
@@ -82,15 +82,15 @@ class ModbusPDUMaskWriteHoldingRegisterRequest(ModbusPDU):
         read_buffer.push_context("ModbusPDUMaskWriteHoldingRegisterRequest")
 
         reference_address: int = read_buffer.read_unsigned_short(
-            logical_name="referenceAddress", bit_length=16, response=response
+            logical_name="reference_address", bit_length=16, response=response
         )
 
         and_mask: int = read_buffer.read_unsigned_short(
-            logical_name="andMask", bit_length=16, response=response
+            logical_name="and_mask", bit_length=16, response=response
         )
 
         or_mask: int = read_buffer.read_unsigned_short(
-            logical_name="orMask", bit_length=16, response=response
+            logical_name="or_mask", bit_length=16, response=response
         )
 
         read_buffer.pop_context("ModbusPDUMaskWriteHoldingRegisterRequest")
@@ -140,9 +140,9 @@ class ModbusPDUMaskWriteHoldingRegisterRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUMaskWriteHoldingRegisterRequest:
-        modbus_pdu_mask_write_holding_register_request: (
+        modbus_pdumask_write_holding_register_request: (
             ModbusPDUMaskWriteHoldingRegisterRequest
         ) = ModbusPDUMaskWriteHoldingRegisterRequest(
             self.reference_address, self.and_mask, self.or_mask
         )
-        return modbus_pdu_mask_write_holding_register_request
+        return modbus_pdumask_write_holding_register_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterResponse.py
index e9fea00719..63c81c991c 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterResponse.py
@@ -82,15 +82,15 @@ class ModbusPDUMaskWriteHoldingRegisterResponse(ModbusPDU):
         read_buffer.push_context("ModbusPDUMaskWriteHoldingRegisterResponse")
 
         reference_address: int = read_buffer.read_unsigned_short(
-            logical_name="referenceAddress", bit_length=16, response=response
+            logical_name="reference_address", bit_length=16, response=response
         )
 
         and_mask: int = read_buffer.read_unsigned_short(
-            logical_name="andMask", bit_length=16, response=response
+            logical_name="and_mask", bit_length=16, response=response
         )
 
         or_mask: int = read_buffer.read_unsigned_short(
-            logical_name="orMask", bit_length=16, response=response
+            logical_name="or_mask", bit_length=16, response=response
         )
 
         read_buffer.pop_context("ModbusPDUMaskWriteHoldingRegisterResponse")
@@ -140,9 +140,9 @@ class ModbusPDUMaskWriteHoldingRegisterResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUMaskWriteHoldingRegisterResponse:
-        modbus_pdu_mask_write_holding_register_response: (
+        modbus_pdumask_write_holding_register_response: (
             ModbusPDUMaskWriteHoldingRegisterResponse
         ) = ModbusPDUMaskWriteHoldingRegisterResponse(
             self.reference_address, self.and_mask, self.or_mask
         )
-        return modbus_pdu_mask_write_holding_register_response
+        return modbus_pdumask_write_holding_register_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsRequest.py
index 7510e1821c..57f0ca2fca 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsRequest.py
@@ -73,7 +73,7 @@ class ModbusPDUReadCoilsRequest(ModbusPDU):
         read_buffer.push_context("ModbusPDUReadCoilsRequest")
 
         starting_address: int = read_buffer.read_unsigned_short(
-            logical_name="startingAddress", bit_length=16, response=response
+            logical_name="starting_address", bit_length=16, response=response
         )
 
         quantity: int = read_buffer.read_unsigned_short(
@@ -121,7 +121,7 @@ class ModbusPDUReadCoilsRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUReadCoilsRequest:
-        modbus_pdu_read_coils_request: ModbusPDUReadCoilsRequest = (
+        modbus_pduread_coils_request: ModbusPDUReadCoilsRequest = (
             ModbusPDUReadCoilsRequest(self.starting_address, self.quantity)
         )
-        return modbus_pdu_read_coils_request
+        return modbus_pduread_coils_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsResponse.py
index e5d2f19980..cd6a64fa78 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsResponse.py
@@ -44,7 +44,7 @@ class ModbusPDUReadCoilsResponse(ModbusPDU):
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         byte_count: int = int(len(self.value))
-        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byte_count")
 
         # Array Field (value)
         write_buffer.write_byte_array(self.value, logical_name="value")
@@ -72,7 +72,7 @@ class ModbusPDUReadCoilsResponse(ModbusPDU):
         read_buffer.push_context("ModbusPDUReadCoilsResponse")
 
         byte_count: int = read_buffer.read_unsigned_byte(
-            logical_name="byteCount", response=response
+            logical_name="byte_count", response=response
         )
 
         value: List[Any] = read_buffer.read_array_field(
@@ -117,7 +117,7 @@ class ModbusPDUReadCoilsResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUReadCoilsResponse:
-        modbus_pdu_read_coils_response: ModbusPDUReadCoilsResponse = (
+        modbus_pduread_coils_response: ModbusPDUReadCoilsResponse = (
             ModbusPDUReadCoilsResponse(self.value)
         )
-        return modbus_pdu_read_coils_response
+        return modbus_pduread_coils_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationRequest.py
index 2d0099ec77..2bc888bc5b 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationRequest.py
@@ -81,7 +81,7 @@ class ModbusPDUReadDeviceIdentificationRequest(ModbusPDU):
         read_buffer.push_context("ModbusPDUReadDeviceIdentificationRequest")
 
         MEI_TYPE: int = read_buffer.read_unsigned_byte(
-            logical_name="meiType", response=response
+            logical_name="mei_type", response=response
         )
 
         level: ModbusDeviceInformationLevel = read_buffer.read_enum(
@@ -92,7 +92,7 @@ class ModbusPDUReadDeviceIdentificationRequest(ModbusPDU):
         )
 
         object_id: int = read_buffer.read_unsigned_byte(
-            logical_name="objectId", bit_length=8, response=response
+            logical_name="object_id", bit_length=8, response=response
         )
 
         read_buffer.pop_context("ModbusPDUReadDeviceIdentificationRequest")
@@ -138,7 +138,7 @@ class ModbusPDUReadDeviceIdentificationRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUReadDeviceIdentificationRequest:
-        modbus_pdu_read_device_identification_request: (
+        modbus_pduread_device_identification_request: (
             ModbusPDUReadDeviceIdentificationRequest
         ) = ModbusPDUReadDeviceIdentificationRequest(self.level, self.object_id)
-        return modbus_pdu_read_device_identification_request
+        return modbus_pduread_device_identification_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationResponse.py
index 414db34755..baf68e4199 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationResponse.py
@@ -87,7 +87,7 @@ class ModbusPDUReadDeviceIdentificationResponse(ModbusPDU):
         # Implicit Field (number_of_objects) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         number_of_objects: int = int(len(self.objects))
         write_buffer.write_unsigned_byte(
-            number_of_objects, logical_name="numberOfObjects"
+            number_of_objects, logical_name="number_of_objects"
         )
 
         # Array Field (objects)
@@ -135,7 +135,7 @@ class ModbusPDUReadDeviceIdentificationResponse(ModbusPDU):
         read_buffer.push_context("ModbusPDUReadDeviceIdentificationResponse")
 
         MEI_TYPE: int = read_buffer.read_unsigned_byte(
-            logical_name="meiType", response=response
+            logical_name="mei_type", response=response
         )
 
         level: ModbusDeviceInformationLevel = read_buffer.read_enum(
@@ -146,14 +146,14 @@ class ModbusPDUReadDeviceIdentificationResponse(ModbusPDU):
         )
 
         individual_access: bool = read_buffer.read_bit(
-            logical_name="individualAccess", bit_length=1, response=response
+            logical_name="individual_access", bit_length=1, response=response
         )
 
         conformity_level: ModbusDeviceInformationConformityLevel = (
             read_buffer.read_enum(
                 read_function=ModbusDeviceInformationConformityLevel,
                 bit_length=7,
-                logical_name="conformityLevel",
+                logical_name="conformity_level",
                 response=response,
             )
         )
@@ -161,16 +161,16 @@ class ModbusPDUReadDeviceIdentificationResponse(ModbusPDU):
         more_follows: ModbusDeviceInformationMoreFollows = read_buffer.read_enum(
             read_function=ModbusDeviceInformationMoreFollows,
             bit_length=8,
-            logical_name="moreFollows",
+            logical_name="more_follows",
             response=response,
         )
 
         next_object_id: int = read_buffer.read_unsigned_byte(
-            logical_name="nextObjectId", bit_length=8, response=response
+            logical_name="next_object_id", bit_length=8, response=response
         )
 
         number_of_objects: int = read_buffer.read_unsigned_byte(
-            logical_name="numberOfObjects", response=response
+            logical_name="number_of_objects", response=response
         )
 
         objects: List[Any] = read_buffer.read_array_field(
@@ -238,7 +238,7 @@ class ModbusPDUReadDeviceIdentificationResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUReadDeviceIdentificationResponse:
-        modbus_pdu_read_device_identification_response: (
+        modbus_pduread_device_identification_response: (
             ModbusPDUReadDeviceIdentificationResponse
         ) = ModbusPDUReadDeviceIdentificationResponse(
             self.level,
@@ -248,4 +248,4 @@ class ModbusPDUReadDeviceIdentificationResponseBuilder:
             self.next_object_id,
             self.objects,
         )
-        return modbus_pdu_read_device_identification_response
+        return modbus_pduread_device_identification_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsRequest.py
index 4c2145e9d0..72d1fe455c 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsRequest.py
@@ -73,7 +73,7 @@ class ModbusPDUReadDiscreteInputsRequest(ModbusPDU):
         read_buffer.push_context("ModbusPDUReadDiscreteInputsRequest")
 
         starting_address: int = read_buffer.read_unsigned_short(
-            logical_name="startingAddress", bit_length=16, response=response
+            logical_name="starting_address", bit_length=16, response=response
         )
 
         quantity: int = read_buffer.read_unsigned_short(
@@ -121,7 +121,7 @@ class ModbusPDUReadDiscreteInputsRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUReadDiscreteInputsRequest:
-        modbus_pdu_read_discrete_inputs_request: ModbusPDUReadDiscreteInputsRequest = (
+        modbus_pduread_discrete_inputs_request: ModbusPDUReadDiscreteInputsRequest = (
             ModbusPDUReadDiscreteInputsRequest(self.starting_address, self.quantity)
         )
-        return modbus_pdu_read_discrete_inputs_request
+        return modbus_pduread_discrete_inputs_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsResponse.py
index 9376f041a4..9f7a18d4a2 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsResponse.py
@@ -44,7 +44,7 @@ class ModbusPDUReadDiscreteInputsResponse(ModbusPDU):
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         byte_count: int = int(len(self.value))
-        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byte_count")
 
         # Array Field (value)
         write_buffer.write_byte_array(self.value, logical_name="value")
@@ -72,7 +72,7 @@ class ModbusPDUReadDiscreteInputsResponse(ModbusPDU):
         read_buffer.push_context("ModbusPDUReadDiscreteInputsResponse")
 
         byte_count: int = read_buffer.read_unsigned_byte(
-            logical_name="byteCount", response=response
+            logical_name="byte_count", response=response
         )
 
         value: List[Any] = read_buffer.read_array_field(
@@ -119,7 +119,7 @@ class ModbusPDUReadDiscreteInputsResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUReadDiscreteInputsResponse:
-        modbus_pdu_read_discrete_inputs_response: (
-            ModbusPDUReadDiscreteInputsResponse
-        ) = ModbusPDUReadDiscreteInputsResponse(self.value)
-        return modbus_pdu_read_discrete_inputs_response
+        modbus_pduread_discrete_inputs_response: ModbusPDUReadDiscreteInputsResponse = (
+            ModbusPDUReadDiscreteInputsResponse(self.value)
+        )
+        return modbus_pduread_discrete_inputs_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusRequest.py
index 39b71e6823..b393b3746a 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusRequest.py
@@ -90,7 +90,7 @@ class ModbusPDUReadExceptionStatusRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUReadExceptionStatusRequest:
-        modbus_pdu_read_exception_status_request: (
-            ModbusPDUReadExceptionStatusRequest
-        ) = ModbusPDUReadExceptionStatusRequest()
-        return modbus_pdu_read_exception_status_request
+        modbus_pduread_exception_status_request: ModbusPDUReadExceptionStatusRequest = (
+            ModbusPDUReadExceptionStatusRequest()
+        )
+        return modbus_pduread_exception_status_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusResponse.py
index 25295616c8..00429e123f 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusResponse.py
@@ -102,7 +102,7 @@ class ModbusPDUReadExceptionStatusResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUReadExceptionStatusResponse:
-        modbus_pdu_read_exception_status_response: (
+        modbus_pduread_exception_status_response: (
             ModbusPDUReadExceptionStatusResponse
         ) = ModbusPDUReadExceptionStatusResponse(self.value)
-        return modbus_pdu_read_exception_status_response
+        return modbus_pduread_exception_status_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueRequest.py
index edb97862bc..dda62ad814 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueRequest.py
@@ -64,7 +64,7 @@ class ModbusPDUReadFifoQueueRequest(ModbusPDU):
         read_buffer.push_context("ModbusPDUReadFifoQueueRequest")
 
         fifo_pointer_address: int = read_buffer.read_unsigned_short(
-            logical_name="fifoPointerAddress", bit_length=16, response=response
+            logical_name="fifo_pointer_address", bit_length=16, response=response
         )
 
         read_buffer.pop_context("ModbusPDUReadFifoQueueRequest")
@@ -106,7 +106,7 @@ class ModbusPDUReadFifoQueueRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUReadFifoQueueRequest:
-        modbus_pdu_read_fifo_queue_request: ModbusPDUReadFifoQueueRequest = (
+        modbus_pduread_fifo_queue_request: ModbusPDUReadFifoQueueRequest = (
             ModbusPDUReadFifoQueueRequest(self.fifo_pointer_address)
         )
-        return modbus_pdu_read_fifo_queue_request
+        return modbus_pduread_fifo_queue_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueResponse.py
index 992b99c63b..9804bd3d25 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueResponse.py
@@ -44,15 +44,17 @@ class ModbusPDUReadFifoQueueResponse(ModbusPDU):
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         byte_count: int = (int(len(self.fifo_value)) * int(2)) + int(2)
-        write_buffer.write_unsigned_short(byte_count, logical_name="byteCount")
+        write_buffer.write_unsigned_short(byte_count, logical_name="byte_count")
 
         # Implicit Field (fifo_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         fifo_count: int = (int(len(self.fifo_value)) * int(2)) / int(2)
-        write_buffer.write_unsigned_short(fifo_count, logical_name="fifoCount")
+        write_buffer.write_unsigned_short(fifo_count, logical_name="fifo_count")
 
         # Array Field (fifoValue)
         write_buffer.write_simple_array(
-            self.fifo_value, write_buffer.write_unsigned_short, logical_name="fifoValue"
+            self.fifo_value,
+            write_buffer.write_unsigned_short,
+            logical_name="fifo_value",
         )
 
         write_buffer.pop_context("ModbusPDUReadFifoQueueResponse")
@@ -81,11 +83,11 @@ class ModbusPDUReadFifoQueueResponse(ModbusPDU):
         read_buffer.push_context("ModbusPDUReadFifoQueueResponse")
 
         byte_count: int = read_buffer.read_unsigned_short(
-            logical_name="byteCount", response=response
+            logical_name="byte_count", response=response
         )
 
         fifo_count: int = read_buffer.read_unsigned_short(
-            logical_name="fifoCount", response=response
+            logical_name="fifo_count", response=response
         )
 
         fifo_value: List[Any] = read_buffer.read_array_field(
@@ -130,7 +132,7 @@ class ModbusPDUReadFifoQueueResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUReadFifoQueueResponse:
-        modbus_pdu_read_fifo_queue_response: ModbusPDUReadFifoQueueResponse = (
+        modbus_pduread_fifo_queue_response: ModbusPDUReadFifoQueueResponse = (
             ModbusPDUReadFifoQueueResponse(self.fifo_value)
         )
-        return modbus_pdu_read_fifo_queue_response
+        return modbus_pduread_fifo_queue_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequest.py
index 15a07db6f0..0ca6b3409b 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequest.py
@@ -48,7 +48,7 @@ class ModbusPDUReadFileRecordRequest(ModbusPDU):
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         byte_count: int = int(getsizeof(self.items))
-        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byte_count")
 
         # Array Field (items)
         write_buffer.write_complex_array(self.items, logical_name="items")
@@ -77,7 +77,7 @@ class ModbusPDUReadFileRecordRequest(ModbusPDU):
         read_buffer.push_context("ModbusPDUReadFileRecordRequest")
 
         byte_count: int = read_buffer.read_unsigned_byte(
-            logical_name="byteCount", response=response
+            logical_name="byte_count", response=response
         )
 
         items: List[Any] = read_buffer.read_array_field(
@@ -122,7 +122,7 @@ class ModbusPDUReadFileRecordRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUReadFileRecordRequest:
-        modbus_pdu_read_file_record_request: ModbusPDUReadFileRecordRequest = (
+        modbus_pduread_file_record_request: ModbusPDUReadFileRecordRequest = (
             ModbusPDUReadFileRecordRequest(self.items)
         )
-        return modbus_pdu_read_file_record_request
+        return modbus_pduread_file_record_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequestItem.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequestItem.py
index c137be4438..82edeabe68 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequestItem.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequestItem.py
@@ -89,29 +89,29 @@ class ModbusPDUReadFileRecordRequestItem:
         read_buffer.push_context("ModbusPDUReadFileRecordRequestItem")
 
         reference_type: int = read_buffer.read_unsigned_byte(
-            logical_name="referenceType", bit_length=8
+            logical_name="reference_type", bit_length=8
         )
 
         file_number: int = read_buffer.read_unsigned_short(
-            logical_name="fileNumber", bit_length=16
+            logical_name="file_number", bit_length=16
         )
 
         record_number: int = read_buffer.read_unsigned_short(
-            logical_name="recordNumber", bit_length=16
+            logical_name="record_number", bit_length=16
         )
 
         record_length: int = read_buffer.read_unsigned_short(
-            logical_name="recordLength", bit_length=16
+            logical_name="record_length", bit_length=16
         )
 
         read_buffer.pop_context("ModbusPDUReadFileRecordRequestItem")
         # Create the instance
-        _modbus_pdu_read_file_record_request_item: (
-            ModbusPDUReadFileRecordRequestItem
-        ) = ModbusPDUReadFileRecordRequestItem(
-            reference_type, file_number, record_number, record_length
+        _modbus_pduread_file_record_request_item: ModbusPDUReadFileRecordRequestItem = (
+            ModbusPDUReadFileRecordRequestItem(
+                reference_type, file_number, record_number, record_length
+            )
         )
-        return _modbus_pdu_read_file_record_request_item
+        return _modbus_pduread_file_record_request_item
 
     def equals(self, o: object) -> bool:
         if self == o:
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponse.py
index e18b124fb0..0d72de17a5 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponse.py
@@ -48,7 +48,7 @@ class ModbusPDUReadFileRecordResponse(ModbusPDU):
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         byte_count: int = int(getsizeof(self.items))
-        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byte_count")
 
         # Array Field (items)
         write_buffer.write_complex_array(self.items, logical_name="items")
@@ -77,7 +77,7 @@ class ModbusPDUReadFileRecordResponse(ModbusPDU):
         read_buffer.push_context("ModbusPDUReadFileRecordResponse")
 
         byte_count: int = read_buffer.read_unsigned_byte(
-            logical_name="byteCount", response=response
+            logical_name="byte_count", response=response
         )
 
         items: List[Any] = read_buffer.read_array_field(
@@ -122,7 +122,7 @@ class ModbusPDUReadFileRecordResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUReadFileRecordResponse:
-        modbus_pdu_read_file_record_response: ModbusPDUReadFileRecordResponse = (
+        modbus_pduread_file_record_response: ModbusPDUReadFileRecordResponse = (
             ModbusPDUReadFileRecordResponse(self.items)
         )
-        return modbus_pdu_read_file_record_response
+        return modbus_pduread_file_record_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponseItem.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponseItem.py
index db33f4cbe8..33c52df5c4 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponseItem.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponseItem.py
@@ -39,7 +39,7 @@ class ModbusPDUReadFileRecordResponseItem:
 
         # Implicit Field (data_length) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         data_length: int = int(len(self.data)) + int(1)
-        write_buffer.write_unsigned_byte(data_length, logical_name="dataLength")
+        write_buffer.write_unsigned_byte(data_length, logical_name="data_length")
 
         # Simple Field (referenceType)
         write_buffer.write_unsigned_byte(
@@ -78,10 +78,10 @@ class ModbusPDUReadFileRecordResponseItem:
     def static_parse_context(read_buffer: ReadBuffer):
         read_buffer.push_context("ModbusPDUReadFileRecordResponseItem")
 
-        data_length: int = read_buffer.read_unsigned_byte(logical_name="dataLength")
+        data_length: int = read_buffer.read_unsigned_byte(logical_name="data_length")
 
         reference_type: int = read_buffer.read_unsigned_byte(
-            logical_name="referenceType", bit_length=8
+            logical_name="reference_type", bit_length=8
         )
 
         data: List[Any] = read_buffer.read_array_field(
@@ -92,10 +92,10 @@ class ModbusPDUReadFileRecordResponseItem:
 
         read_buffer.pop_context("ModbusPDUReadFileRecordResponseItem")
         # Create the instance
-        _modbus_pdu_read_file_record_response_item: (
+        _modbus_pduread_file_record_response_item: (
             ModbusPDUReadFileRecordResponseItem
         ) = ModbusPDUReadFileRecordResponseItem(reference_type, data)
-        return _modbus_pdu_read_file_record_response_item
+        return _modbus_pduread_file_record_response_item
 
     def equals(self, o: object) -> bool:
         if self == o:
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersRequest.py
index b9dbec86b1..11730c441f 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersRequest.py
@@ -73,7 +73,7 @@ class ModbusPDUReadHoldingRegistersRequest(ModbusPDU):
         read_buffer.push_context("ModbusPDUReadHoldingRegistersRequest")
 
         starting_address: int = read_buffer.read_unsigned_short(
-            logical_name="startingAddress", bit_length=16, response=response
+            logical_name="starting_address", bit_length=16, response=response
         )
 
         quantity: int = read_buffer.read_unsigned_short(
@@ -123,7 +123,7 @@ class ModbusPDUReadHoldingRegistersRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUReadHoldingRegistersRequest:
-        modbus_pdu_read_holding_registers_request: (
+        modbus_pduread_holding_registers_request: (
             ModbusPDUReadHoldingRegistersRequest
         ) = ModbusPDUReadHoldingRegistersRequest(self.starting_address, self.quantity)
-        return modbus_pdu_read_holding_registers_request
+        return modbus_pduread_holding_registers_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersResponse.py
index 7d220fae20..cd0b1eada0 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersResponse.py
@@ -44,7 +44,7 @@ class ModbusPDUReadHoldingRegistersResponse(ModbusPDU):
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         byte_count: int = int(len(self.value))
-        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byte_count")
 
         # Array Field (value)
         write_buffer.write_byte_array(self.value, logical_name="value")
@@ -72,7 +72,7 @@ class ModbusPDUReadHoldingRegistersResponse(ModbusPDU):
         read_buffer.push_context("ModbusPDUReadHoldingRegistersResponse")
 
         byte_count: int = read_buffer.read_unsigned_byte(
-            logical_name="byteCount", response=response
+            logical_name="byte_count", response=response
         )
 
         value: List[Any] = read_buffer.read_array_field(
@@ -119,7 +119,7 @@ class ModbusPDUReadHoldingRegistersResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUReadHoldingRegistersResponse:
-        modbus_pdu_read_holding_registers_response: (
+        modbus_pduread_holding_registers_response: (
             ModbusPDUReadHoldingRegistersResponse
         ) = ModbusPDUReadHoldingRegistersResponse(self.value)
-        return modbus_pdu_read_holding_registers_response
+        return modbus_pduread_holding_registers_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersRequest.py
index 8604e83300..92cec0d5ab 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersRequest.py
@@ -73,7 +73,7 @@ class ModbusPDUReadInputRegistersRequest(ModbusPDU):
         read_buffer.push_context("ModbusPDUReadInputRegistersRequest")
 
         starting_address: int = read_buffer.read_unsigned_short(
-            logical_name="startingAddress", bit_length=16, response=response
+            logical_name="starting_address", bit_length=16, response=response
         )
 
         quantity: int = read_buffer.read_unsigned_short(
@@ -121,7 +121,7 @@ class ModbusPDUReadInputRegistersRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUReadInputRegistersRequest:
-        modbus_pdu_read_input_registers_request: ModbusPDUReadInputRegistersRequest = (
+        modbus_pduread_input_registers_request: ModbusPDUReadInputRegistersRequest = (
             ModbusPDUReadInputRegistersRequest(self.starting_address, self.quantity)
         )
-        return modbus_pdu_read_input_registers_request
+        return modbus_pduread_input_registers_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersResponse.py
index cc2c40e31f..83a608c5fd 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersResponse.py
@@ -44,7 +44,7 @@ class ModbusPDUReadInputRegistersResponse(ModbusPDU):
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         byte_count: int = int(len(self.value))
-        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byte_count")
 
         # Array Field (value)
         write_buffer.write_byte_array(self.value, logical_name="value")
@@ -72,7 +72,7 @@ class ModbusPDUReadInputRegistersResponse(ModbusPDU):
         read_buffer.push_context("ModbusPDUReadInputRegistersResponse")
 
         byte_count: int = read_buffer.read_unsigned_byte(
-            logical_name="byteCount", response=response
+            logical_name="byte_count", response=response
         )
 
         value: List[Any] = read_buffer.read_array_field(
@@ -119,7 +119,7 @@ class ModbusPDUReadInputRegistersResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUReadInputRegistersResponse:
-        modbus_pdu_read_input_registers_response: (
-            ModbusPDUReadInputRegistersResponse
-        ) = ModbusPDUReadInputRegistersResponse(self.value)
-        return modbus_pdu_read_input_registers_response
+        modbus_pduread_input_registers_response: ModbusPDUReadInputRegistersResponse = (
+            ModbusPDUReadInputRegistersResponse(self.value)
+        )
+        return modbus_pduread_input_registers_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersRequest.py
index 92588f9c7f..ea162927d8 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersRequest.py
@@ -72,7 +72,7 @@ class ModbusPDUReadWriteMultipleHoldingRegistersRequest(ModbusPDU):
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         byte_count: int = int(len(self.value))
-        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byte_count")
 
         # Array Field (value)
         write_buffer.write_byte_array(self.value, logical_name="value")
@@ -112,23 +112,23 @@ class ModbusPDUReadWriteMultipleHoldingRegistersRequest(ModbusPDU):
         read_buffer.push_context("ModbusPDUReadWriteMultipleHoldingRegistersRequest")
 
         read_starting_address: int = read_buffer.read_unsigned_short(
-            logical_name="readStartingAddress", bit_length=16, response=response
+            logical_name="read_starting_address", bit_length=16, response=response
         )
 
         read_quantity: int = read_buffer.read_unsigned_short(
-            logical_name="readQuantity", bit_length=16, response=response
+            logical_name="read_quantity", bit_length=16, response=response
         )
 
         write_starting_address: int = read_buffer.read_unsigned_short(
-            logical_name="writeStartingAddress", bit_length=16, response=response
+            logical_name="write_starting_address", bit_length=16, response=response
         )
 
         write_quantity: int = read_buffer.read_unsigned_short(
-            logical_name="writeQuantity", bit_length=16, response=response
+            logical_name="write_quantity", bit_length=16, response=response
         )
 
         byte_count: int = read_buffer.read_unsigned_byte(
-            logical_name="byteCount", response=response
+            logical_name="byte_count", response=response
         )
 
         value: List[Any] = read_buffer.read_array_field(
@@ -193,7 +193,7 @@ class ModbusPDUReadWriteMultipleHoldingRegistersRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUReadWriteMultipleHoldingRegistersRequest:
-        modbus_pdu_read_write_multiple_holding_registers_request: (
+        modbus_pduread_write_multiple_holding_registers_request: (
             ModbusPDUReadWriteMultipleHoldingRegistersRequest
         ) = ModbusPDUReadWriteMultipleHoldingRegistersRequest(
             self.read_starting_address,
@@ -202,4 +202,4 @@ class ModbusPDUReadWriteMultipleHoldingRegistersRequestBuilder:
             self.write_quantity,
             self.value,
         )
-        return modbus_pdu_read_write_multiple_holding_registers_request
+        return modbus_pduread_write_multiple_holding_registers_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersResponse.py
index e9bbcaf3f2..c368ba85e5 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersResponse.py
@@ -44,7 +44,7 @@ class ModbusPDUReadWriteMultipleHoldingRegistersResponse(ModbusPDU):
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         byte_count: int = int(len(self.value))
-        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byte_count")
 
         # Array Field (value)
         write_buffer.write_byte_array(self.value, logical_name="value")
@@ -72,7 +72,7 @@ class ModbusPDUReadWriteMultipleHoldingRegistersResponse(ModbusPDU):
         read_buffer.push_context("ModbusPDUReadWriteMultipleHoldingRegistersResponse")
 
         byte_count: int = read_buffer.read_unsigned_byte(
-            logical_name="byteCount", response=response
+            logical_name="byte_count", response=response
         )
 
         value: List[Any] = read_buffer.read_array_field(
@@ -119,7 +119,7 @@ class ModbusPDUReadWriteMultipleHoldingRegistersResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUReadWriteMultipleHoldingRegistersResponse:
-        modbus_pdu_read_write_multiple_holding_registers_response: (
+        modbus_pduread_write_multiple_holding_registers_response: (
             ModbusPDUReadWriteMultipleHoldingRegistersResponse
         ) = ModbusPDUReadWriteMultipleHoldingRegistersResponse(self.value)
-        return modbus_pdu_read_write_multiple_holding_registers_response
+        return modbus_pduread_write_multiple_holding_registers_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdRequest.py
index 8acb58f35b..5e47469d28 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdRequest.py
@@ -88,7 +88,7 @@ class ModbusPDUReportServerIdRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUReportServerIdRequest:
-        modbus_pdu_report_server_id_request: ModbusPDUReportServerIdRequest = (
+        modbus_pdureport_server_id_request: ModbusPDUReportServerIdRequest = (
             ModbusPDUReportServerIdRequest()
         )
-        return modbus_pdu_report_server_id_request
+        return modbus_pdureport_server_id_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdResponse.py
index 6062721b08..90b46c2c9a 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdResponse.py
@@ -44,7 +44,7 @@ class ModbusPDUReportServerIdResponse(ModbusPDU):
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         byte_count: int = int(len(self.value))
-        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byte_count")
 
         # Array Field (value)
         write_buffer.write_byte_array(self.value, logical_name="value")
@@ -72,7 +72,7 @@ class ModbusPDUReportServerIdResponse(ModbusPDU):
         read_buffer.push_context("ModbusPDUReportServerIdResponse")
 
         byte_count: int = read_buffer.read_unsigned_byte(
-            logical_name="byteCount", response=response
+            logical_name="byte_count", response=response
         )
 
         value: List[Any] = read_buffer.read_array_field(
@@ -117,7 +117,7 @@ class ModbusPDUReportServerIdResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUReportServerIdResponse:
-        modbus_pdu_report_server_id_response: ModbusPDUReportServerIdResponse = (
+        modbus_pdureport_server_id_response: ModbusPDUReportServerIdResponse = (
             ModbusPDUReportServerIdResponse(self.value)
         )
-        return modbus_pdu_report_server_id_response
+        return modbus_pdureport_server_id_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequest.py
index a1c2534704..d9e9459933 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequest.py
@@ -48,7 +48,7 @@ class ModbusPDUWriteFileRecordRequest(ModbusPDU):
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         byte_count: int = int(getsizeof(self.items))
-        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byte_count")
 
         # Array Field (items)
         write_buffer.write_complex_array(self.items, logical_name="items")
@@ -77,7 +77,7 @@ class ModbusPDUWriteFileRecordRequest(ModbusPDU):
         read_buffer.push_context("ModbusPDUWriteFileRecordRequest")
 
         byte_count: int = read_buffer.read_unsigned_byte(
-            logical_name="byteCount", response=response
+            logical_name="byte_count", response=response
         )
 
         items: List[Any] = read_buffer.read_array_field(
@@ -122,7 +122,7 @@ class ModbusPDUWriteFileRecordRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUWriteFileRecordRequest:
-        modbus_pdu_write_file_record_request: ModbusPDUWriteFileRecordRequest = (
+        modbus_pduwrite_file_record_request: ModbusPDUWriteFileRecordRequest = (
             ModbusPDUWriteFileRecordRequest(self.items)
         )
-        return modbus_pdu_write_file_record_request
+        return modbus_pduwrite_file_record_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequestItem.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequestItem.py
index 9ce1004978..5ad57733eb 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequestItem.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequestItem.py
@@ -56,10 +56,10 @@ class ModbusPDUWriteFileRecordRequestItem:
 
         # Implicit Field (record_length) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         record_length: int = int(len(self.record_data)) / int(2)
-        write_buffer.write_unsigned_short(record_length, logical_name="recordLength")
+        write_buffer.write_unsigned_short(record_length, logical_name="record_length")
 
         # Array Field (recordData)
-        write_buffer.write_byte_array(self.record_data, logical_name="recordData")
+        write_buffer.write_byte_array(self.record_data, logical_name="record_data")
 
         write_buffer.pop_context("ModbusPDUWriteFileRecordRequestItem")
 
@@ -97,19 +97,19 @@ class ModbusPDUWriteFileRecordRequestItem:
         read_buffer.push_context("ModbusPDUWriteFileRecordRequestItem")
 
         reference_type: int = read_buffer.read_unsigned_byte(
-            logical_name="referenceType", bit_length=8
+            logical_name="reference_type", bit_length=8
         )
 
         file_number: int = read_buffer.read_unsigned_short(
-            logical_name="fileNumber", bit_length=16
+            logical_name="file_number", bit_length=16
         )
 
         record_number: int = read_buffer.read_unsigned_short(
-            logical_name="recordNumber", bit_length=16
+            logical_name="record_number", bit_length=16
         )
 
         record_length: int = read_buffer.read_unsigned_short(
-            logical_name="recordLength"
+            logical_name="record_length"
         )
 
         record_data: List[Any] = read_buffer.read_array_field(
@@ -120,12 +120,12 @@ class ModbusPDUWriteFileRecordRequestItem:
 
         read_buffer.pop_context("ModbusPDUWriteFileRecordRequestItem")
         # Create the instance
-        _modbus_pdu_write_file_record_request_item: (
+        _modbus_pduwrite_file_record_request_item: (
             ModbusPDUWriteFileRecordRequestItem
         ) = ModbusPDUWriteFileRecordRequestItem(
             reference_type, file_number, record_number, record_data
         )
-        return _modbus_pdu_write_file_record_request_item
+        return _modbus_pduwrite_file_record_request_item
 
     def equals(self, o: object) -> bool:
         if self == o:
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponse.py
index 00d323231b..e093468183 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponse.py
@@ -48,7 +48,7 @@ class ModbusPDUWriteFileRecordResponse(ModbusPDU):
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         byte_count: int = int(getsizeof(self.items))
-        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byte_count")
 
         # Array Field (items)
         write_buffer.write_complex_array(self.items, logical_name="items")
@@ -77,7 +77,7 @@ class ModbusPDUWriteFileRecordResponse(ModbusPDU):
         read_buffer.push_context("ModbusPDUWriteFileRecordResponse")
 
         byte_count: int = read_buffer.read_unsigned_byte(
-            logical_name="byteCount", response=response
+            logical_name="byte_count", response=response
         )
 
         items: List[Any] = read_buffer.read_array_field(
@@ -122,7 +122,7 @@ class ModbusPDUWriteFileRecordResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUWriteFileRecordResponse:
-        modbus_pdu_write_file_record_response: ModbusPDUWriteFileRecordResponse = (
+        modbus_pduwrite_file_record_response: ModbusPDUWriteFileRecordResponse = (
             ModbusPDUWriteFileRecordResponse(self.items)
         )
-        return modbus_pdu_write_file_record_response
+        return modbus_pduwrite_file_record_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponseItem.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponseItem.py
index ec2ebdd9f7..a64f30ee95 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponseItem.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponseItem.py
@@ -56,10 +56,10 @@ class ModbusPDUWriteFileRecordResponseItem:
 
         # Implicit Field (record_length) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         record_length: int = int(len(self.record_data)) / int(2)
-        write_buffer.write_unsigned_short(record_length, logical_name="recordLength")
+        write_buffer.write_unsigned_short(record_length, logical_name="record_length")
 
         # Array Field (recordData)
-        write_buffer.write_byte_array(self.record_data, logical_name="recordData")
+        write_buffer.write_byte_array(self.record_data, logical_name="record_data")
 
         write_buffer.pop_context("ModbusPDUWriteFileRecordResponseItem")
 
@@ -97,19 +97,19 @@ class ModbusPDUWriteFileRecordResponseItem:
         read_buffer.push_context("ModbusPDUWriteFileRecordResponseItem")
 
         reference_type: int = read_buffer.read_unsigned_byte(
-            logical_name="referenceType", bit_length=8
+            logical_name="reference_type", bit_length=8
         )
 
         file_number: int = read_buffer.read_unsigned_short(
-            logical_name="fileNumber", bit_length=16
+            logical_name="file_number", bit_length=16
         )
 
         record_number: int = read_buffer.read_unsigned_short(
-            logical_name="recordNumber", bit_length=16
+            logical_name="record_number", bit_length=16
         )
 
         record_length: int = read_buffer.read_unsigned_short(
-            logical_name="recordLength"
+            logical_name="record_length"
         )
 
         record_data: List[Any] = read_buffer.read_array_field(
@@ -120,12 +120,12 @@ class ModbusPDUWriteFileRecordResponseItem:
 
         read_buffer.pop_context("ModbusPDUWriteFileRecordResponseItem")
         # Create the instance
-        _modbus_pdu_write_file_record_response_item: (
+        _modbus_pduwrite_file_record_response_item: (
             ModbusPDUWriteFileRecordResponseItem
         ) = ModbusPDUWriteFileRecordResponseItem(
             reference_type, file_number, record_number, record_data
         )
-        return _modbus_pdu_write_file_record_response_item
+        return _modbus_pduwrite_file_record_response_item
 
     def equals(self, o: object) -> bool:
         if self == o:
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsRequest.py
index 618dd5d576..0ff4236f33 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsRequest.py
@@ -56,7 +56,7 @@ class ModbusPDUWriteMultipleCoilsRequest(ModbusPDU):
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         byte_count: int = int(len(self.value))
-        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byte_count")
 
         # Array Field (value)
         write_buffer.write_byte_array(self.value, logical_name="value")
@@ -90,7 +90,7 @@ class ModbusPDUWriteMultipleCoilsRequest(ModbusPDU):
         read_buffer.push_context("ModbusPDUWriteMultipleCoilsRequest")
 
         starting_address: int = read_buffer.read_unsigned_short(
-            logical_name="startingAddress", bit_length=16, response=response
+            logical_name="starting_address", bit_length=16, response=response
         )
 
         quantity: int = read_buffer.read_unsigned_short(
@@ -98,7 +98,7 @@ class ModbusPDUWriteMultipleCoilsRequest(ModbusPDU):
         )
 
         byte_count: int = read_buffer.read_unsigned_byte(
-            logical_name="byteCount", response=response
+            logical_name="byte_count", response=response
         )
 
         value: List[Any] = read_buffer.read_array_field(
@@ -153,9 +153,9 @@ class ModbusPDUWriteMultipleCoilsRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUWriteMultipleCoilsRequest:
-        modbus_pdu_write_multiple_coils_request: ModbusPDUWriteMultipleCoilsRequest = (
+        modbus_pduwrite_multiple_coils_request: ModbusPDUWriteMultipleCoilsRequest = (
             ModbusPDUWriteMultipleCoilsRequest(
                 self.starting_address, self.quantity, self.value
             )
         )
-        return modbus_pdu_write_multiple_coils_request
+        return modbus_pduwrite_multiple_coils_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsResponse.py
index b9e5574998..18c8a3fa34 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsResponse.py
@@ -73,7 +73,7 @@ class ModbusPDUWriteMultipleCoilsResponse(ModbusPDU):
         read_buffer.push_context("ModbusPDUWriteMultipleCoilsResponse")
 
         starting_address: int = read_buffer.read_unsigned_short(
-            logical_name="startingAddress", bit_length=16, response=response
+            logical_name="starting_address", bit_length=16, response=response
         )
 
         quantity: int = read_buffer.read_unsigned_short(
@@ -123,7 +123,7 @@ class ModbusPDUWriteMultipleCoilsResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUWriteMultipleCoilsResponse:
-        modbus_pdu_write_multiple_coils_response: (
-            ModbusPDUWriteMultipleCoilsResponse
-        ) = ModbusPDUWriteMultipleCoilsResponse(self.starting_address, self.quantity)
-        return modbus_pdu_write_multiple_coils_response
+        modbus_pduwrite_multiple_coils_response: ModbusPDUWriteMultipleCoilsResponse = (
+            ModbusPDUWriteMultipleCoilsResponse(self.starting_address, self.quantity)
+        )
+        return modbus_pduwrite_multiple_coils_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersRequest.py
index 9297d7e920..1dd8467645 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersRequest.py
@@ -56,7 +56,7 @@ class ModbusPDUWriteMultipleHoldingRegistersRequest(ModbusPDU):
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
         byte_count: int = int(len(self.value))
-        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byte_count")
 
         # Array Field (value)
         write_buffer.write_byte_array(self.value, logical_name="value")
@@ -90,7 +90,7 @@ class ModbusPDUWriteMultipleHoldingRegistersRequest(ModbusPDU):
         read_buffer.push_context("ModbusPDUWriteMultipleHoldingRegistersRequest")
 
         starting_address: int = read_buffer.read_unsigned_short(
-            logical_name="startingAddress", bit_length=16, response=response
+            logical_name="starting_address", bit_length=16, response=response
         )
 
         quantity: int = read_buffer.read_unsigned_short(
@@ -98,7 +98,7 @@ class ModbusPDUWriteMultipleHoldingRegistersRequest(ModbusPDU):
         )
 
         byte_count: int = read_buffer.read_unsigned_byte(
-            logical_name="byteCount", response=response
+            logical_name="byte_count", response=response
         )
 
         value: List[Any] = read_buffer.read_array_field(
@@ -155,9 +155,9 @@ class ModbusPDUWriteMultipleHoldingRegistersRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUWriteMultipleHoldingRegistersRequest:
-        modbus_pdu_write_multiple_holding_registers_request: (
+        modbus_pduwrite_multiple_holding_registers_request: (
             ModbusPDUWriteMultipleHoldingRegistersRequest
         ) = ModbusPDUWriteMultipleHoldingRegistersRequest(
             self.starting_address, self.quantity, self.value
         )
-        return modbus_pdu_write_multiple_holding_registers_request
+        return modbus_pduwrite_multiple_holding_registers_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersResponse.py
index 350ee4e922..d22e184831 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersResponse.py
@@ -73,7 +73,7 @@ class ModbusPDUWriteMultipleHoldingRegistersResponse(ModbusPDU):
         read_buffer.push_context("ModbusPDUWriteMultipleHoldingRegistersResponse")
 
         starting_address: int = read_buffer.read_unsigned_short(
-            logical_name="startingAddress", bit_length=16, response=response
+            logical_name="starting_address", bit_length=16, response=response
         )
 
         quantity: int = read_buffer.read_unsigned_short(
@@ -125,9 +125,9 @@ class ModbusPDUWriteMultipleHoldingRegistersResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUWriteMultipleHoldingRegistersResponse:
-        modbus_pdu_write_multiple_holding_registers_response: (
+        modbus_pduwrite_multiple_holding_registers_response: (
             ModbusPDUWriteMultipleHoldingRegistersResponse
         ) = ModbusPDUWriteMultipleHoldingRegistersResponse(
             self.starting_address, self.quantity
         )
-        return modbus_pdu_write_multiple_holding_registers_response
+        return modbus_pduwrite_multiple_holding_registers_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilRequest.py
index 9abfd20804..f44615411c 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilRequest.py
@@ -121,7 +121,7 @@ class ModbusPDUWriteSingleCoilRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUWriteSingleCoilRequest:
-        modbus_pdu_write_single_coil_request: ModbusPDUWriteSingleCoilRequest = (
+        modbus_pduwrite_single_coil_request: ModbusPDUWriteSingleCoilRequest = (
             ModbusPDUWriteSingleCoilRequest(self.address, self.value)
         )
-        return modbus_pdu_write_single_coil_request
+        return modbus_pduwrite_single_coil_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilResponse.py
index 5b6fe49c1c..8d96e13cb3 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilResponse.py
@@ -121,7 +121,7 @@ class ModbusPDUWriteSingleCoilResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUWriteSingleCoilResponse:
-        modbus_pdu_write_single_coil_response: ModbusPDUWriteSingleCoilResponse = (
+        modbus_pduwrite_single_coil_response: ModbusPDUWriteSingleCoilResponse = (
             ModbusPDUWriteSingleCoilResponse(self.address, self.value)
         )
-        return modbus_pdu_write_single_coil_response
+        return modbus_pduwrite_single_coil_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterRequest.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterRequest.py
index 56c2bb1669..00d9eeb80f 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterRequest.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterRequest.py
@@ -123,7 +123,7 @@ class ModbusPDUWriteSingleRegisterRequestBuilder:
     def build(
         self,
     ) -> ModbusPDUWriteSingleRegisterRequest:
-        modbus_pdu_write_single_register_request: (
-            ModbusPDUWriteSingleRegisterRequest
-        ) = ModbusPDUWriteSingleRegisterRequest(self.address, self.value)
-        return modbus_pdu_write_single_register_request
+        modbus_pduwrite_single_register_request: ModbusPDUWriteSingleRegisterRequest = (
+            ModbusPDUWriteSingleRegisterRequest(self.address, self.value)
+        )
+        return modbus_pduwrite_single_register_request
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterResponse.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterResponse.py
index 765198382d..f3609473d2 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterResponse.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterResponse.py
@@ -123,7 +123,7 @@ class ModbusPDUWriteSingleRegisterResponseBuilder:
     def build(
         self,
     ) -> ModbusPDUWriteSingleRegisterResponse:
-        modbus_pdu_write_single_register_response: (
+        modbus_pduwrite_single_register_response: (
             ModbusPDUWriteSingleRegisterResponse
         ) = ModbusPDUWriteSingleRegisterResponse(self.address, self.value)
-        return modbus_pdu_write_single_register_response
+        return modbus_pduwrite_single_register_response
diff --git a/plc4py/plc4py/protocols/modbus/readwrite/ModbusTcpADU.py b/plc4py/plc4py/protocols/modbus/readwrite/ModbusTcpADU.py
index 7bad436f61..f0edc3a8ee 100644
--- a/plc4py/plc4py/protocols/modbus/readwrite/ModbusTcpADU.py
+++ b/plc4py/plc4py/protocols/modbus/readwrite/ModbusTcpADU.py
@@ -103,7 +103,7 @@ class ModbusTcpADU(ModbusADU):
         read_buffer.push_context("ModbusTcpADU")
 
         transaction_identifier: int = read_buffer.read_unsigned_short(
-            logical_name="transactionIdentifier",
+            logical_name="transaction_identifier",
             bit_length=16,
             byte_order=ByteOrder.BIG_ENDIAN,
             driver_type=driver_type,
@@ -111,7 +111,7 @@ class ModbusTcpADU(ModbusADU):
         )
 
         PROTOCOL_IDENTIFIER: int = read_buffer.read_unsigned_short(
-            logical_name="protocolIdentifier",
+            logical_name="protocol_identifier",
             byte_order=ByteOrder.BIG_ENDIAN,
             driver_type=driver_type,
             response=response,
@@ -125,7 +125,7 @@ class ModbusTcpADU(ModbusADU):
         )
 
         unit_identifier: int = read_buffer.read_unsigned_byte(
-            logical_name="unitIdentifier",
+            logical_name="unit_identifier",
             bit_length=8,
             byte_order=ByteOrder.BIG_ENDIAN,
             driver_type=driver_type,
diff --git a/plc4py/plc4py/protocols/umas/readwrite/ModbusPDU.py b/plc4py/plc4py/protocols/umas/readwrite/ModbusPDU.py
index 4bfa67bff0..3b347c107e 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/ModbusPDU.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/ModbusPDU.py
@@ -53,11 +53,11 @@ class ModbusPDU(ABC, PlcMessage):
         write_buffer.push_context("ModbusPDU")
 
         # Discriminator Field (errorFlag) (Used as input to a switch field)
-        write_buffer.write_bit(self.error_flag, logical_name="errorFlag", bit_length=1)
+        write_buffer.write_bit(self.error_flag, logical_name="error_flag", bit_length=1)
 
         # Discriminator Field (functionFlag) (Used as input to a switch field)
         write_buffer.write_unsigned_byte(
-            self.function_flag, logical_name="functionFlag", bit_length=7
+            self.function_flag, logical_name="function_flag", bit_length=7
         )
 
         # Switch field (Serialize the sub-type)
@@ -124,14 +124,14 @@ class ModbusPDU(ABC, PlcMessage):
     ):
         read_buffer.push_context("ModbusPDU")
         error_flag: bool = read_buffer.read_bit(
-            logical_name="errorFlag",
+            logical_name="error_flag",
             bit_length=1,
             umas_request_function_key=umas_request_function_key,
             byte_length=byte_length,
         )
 
         function_flag: int = read_buffer.read_unsigned_byte(
-            logical_name="functionFlag",
+            logical_name="function_flag",
             bit_length=7,
             umas_request_function_key=umas_request_function_key,
             byte_length=byte_length,
diff --git a/plc4py/plc4py/protocols/umas/readwrite/ModbusPDUError.py b/plc4py/plc4py/protocols/umas/readwrite/ModbusPDUError.py
index 68ecf6190d..9a4139d4e2 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/ModbusPDUError.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/ModbusPDUError.py
@@ -71,7 +71,7 @@ class ModbusPDUError(ModbusPDU):
         exception_code: ModbusErrorCode = read_buffer.read_enum(
             read_function=ModbusErrorCode,
             bit_length=8,
-            logical_name="exceptionCode",
+            logical_name="exception_code",
             umas_request_function_key=umas_request_function_key,
             byte_length=byte_length,
         )
@@ -117,7 +117,7 @@ class ModbusPDUErrorBuilder:
         umas_request_function_key: int,
         byte_length: int,
     ) -> ModbusPDUError:
-        modbus_pdu_error: ModbusPDUError = ModbusPDUError(
+        modbus_pduerror: ModbusPDUError = ModbusPDUError(
             umas_request_function_key, byte_length, self.exception_code
         )
-        return modbus_pdu_error
+        return modbus_pduerror
diff --git a/plc4py/plc4py/protocols/umas/readwrite/ModbusTcpADU.py b/plc4py/plc4py/protocols/umas/readwrite/ModbusTcpADU.py
index c68abd5544..0b7fba1a48 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/ModbusTcpADU.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/ModbusTcpADU.py
@@ -62,7 +62,7 @@ class ModbusTcpADU:
         )
 
         # Array Field (pduArray)
-        write_buffer.write_byte_array(self.pdu_array, logical_name="pduArray")
+        write_buffer.write_byte_array(self.pdu_array, logical_name="pdu_array")
 
         write_buffer.pop_context("ModbusTcpADU")
 
@@ -100,13 +100,13 @@ class ModbusTcpADU:
         read_buffer.push_context("ModbusTcpADU")
 
         transaction_identifier: int = read_buffer.read_unsigned_short(
-            logical_name="transactionIdentifier",
+            logical_name="transaction_identifier",
             bit_length=16,
             byte_order=ByteOrder.BIG_ENDIAN,
         )
 
         PROTOCOL_IDENTIFIER: int = read_buffer.read_unsigned_short(
-            logical_name="protocolIdentifier", byte_order=ByteOrder.BIG_ENDIAN
+            logical_name="protocol_identifier", byte_order=ByteOrder.BIG_ENDIAN
         )
 
         length: int = read_buffer.read_unsigned_short(
@@ -114,7 +114,9 @@ class ModbusTcpADU:
         )
 
         unit_identifier: int = read_buffer.read_unsigned_byte(
-            logical_name="unitIdentifier", bit_length=8, byte_order=ByteOrder.BIG_ENDIAN
+            logical_name="unit_identifier",
+            bit_length=8,
+            byte_order=ByteOrder.BIG_ENDIAN,
         )
 
         pdu_array: List[Any] = read_buffer.read_array_field(
diff --git a/plc4py/plc4py/protocols/umas/readwrite/PlcMemoryBlockIdent.py b/plc4py/plc4py/protocols/umas/readwrite/PlcMemoryBlockIdent.py
index f2106088d1..eb02667c64 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/PlcMemoryBlockIdent.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/PlcMemoryBlockIdent.py
@@ -87,7 +87,7 @@ class PlcMemoryBlockIdent:
         read_buffer.push_context("PlcMemoryBlockIdent")
 
         block_type: int = read_buffer.read_unsigned_byte(
-            logical_name="blockType", bit_length=8
+            logical_name="block_type", bit_length=8
         )
 
         folio: int = read_buffer.read_unsigned_byte(logical_name="folio", bit_length=8)
@@ -97,7 +97,7 @@ class PlcMemoryBlockIdent:
         )
 
         memory_length: int = read_buffer.read_unsigned_int(
-            logical_name="memoryLength", bit_length=32
+            logical_name="memory_length", bit_length=32
         )
 
         read_buffer.pop_context("PlcMemoryBlockIdent")
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasConstants.py b/plc4py/plc4py/protocols/umas/readwrite/UmasConstants.py
index 754e38db52..bc8c7ad072 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasConstants.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasConstants.py
@@ -62,7 +62,7 @@ class UmasConstants:
         read_buffer.push_context("UmasConstants")
 
         UMAS_TCP_DEFAULT_PORT: int = read_buffer.read_unsigned_short(
-            logical_name="UmasTcpDefaultPort"
+            logical_name="umas_tcp_default_port"
         )
 
         read_buffer.pop_context("UmasConstants")
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasDatatypeReference.py b/plc4py/plc4py/protocols/umas/readwrite/UmasDatatypeReference.py
index bc547bd61b..088894eddd 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasDatatypeReference.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasDatatypeReference.py
@@ -110,7 +110,7 @@ class UmasDatatypeReference:
         read_buffer.push_context("UmasDatatypeReference")
 
         data_size: int = read_buffer.read_unsigned_short(
-            logical_name="dataSize", bit_length=16
+            logical_name="data_size", bit_length=16
         )
 
         unknown1: int = read_buffer.read_unsigned_short(
@@ -118,15 +118,15 @@ class UmasDatatypeReference:
         )
 
         class_identifier: int = read_buffer.read_unsigned_byte(
-            logical_name="classIdentifier", bit_length=8
+            logical_name="class_identifier", bit_length=8
         )
 
         data_type: int = read_buffer.read_unsigned_byte(
-            logical_name="dataType", bit_length=8
+            logical_name="data_type", bit_length=8
         )
 
         string_length: int = read_buffer.read_unsigned_byte(
-            logical_name="stringLength", bit_length=8
+            logical_name="string_length", bit_length=8
         )
 
         value = read_buffer.read_manual(
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasInitCommsRequest.py b/plc4py/plc4py/protocols/umas/readwrite/UmasInitCommsRequest.py
index fe29556007..c24cc49fb3 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasInitCommsRequest.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasInitCommsRequest.py
@@ -39,7 +39,7 @@ class UmasInitCommsRequest(UmasPDUItem):
     umas_function_key: ClassVar[int] = 0x01
     umas_request_function_key: ClassVar[int] = 0
 
-    def serialize_umas_pdu_item_child(self, write_buffer: WriteBuffer):
+    def serialize_umas_pduitem_child(self, write_buffer: WriteBuffer):
         write_buffer.push_context("UmasInitCommsRequest")
 
         # Simple Field (unknownObject)
@@ -68,7 +68,7 @@ class UmasInitCommsRequest(UmasPDUItem):
         read_buffer.push_context("UmasInitCommsRequest")
 
         unknown_object: int = read_buffer.read_unsigned_byte(
-            logical_name="unknownObject",
+            logical_name="unknown_object",
             bit_length=8,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasInitCommsResponse.py b/plc4py/plc4py/protocols/umas/readwrite/UmasInitCommsResponse.py
index 553ff3cb86..e48701a44b 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasInitCommsResponse.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasInitCommsResponse.py
@@ -44,7 +44,7 @@ class UmasInitCommsResponse(UmasPDUItem):
     umas_function_key: ClassVar[int] = 0xFE
     umas_request_function_key: ClassVar[int] = 0x01
 
-    def serialize_umas_pdu_item_child(self, write_buffer: WriteBuffer):
+    def serialize_umas_pduitem_child(self, write_buffer: WriteBuffer):
         write_buffer.push_context("UmasInitCommsResponse")
 
         # Simple Field (maxFrameSize)
@@ -111,7 +111,7 @@ class UmasInitCommsResponse(UmasPDUItem):
         read_buffer.push_context("UmasInitCommsResponse")
 
         max_frame_size: int = read_buffer.read_unsigned_short(
-            logical_name="maxFrameSize",
+            logical_name="max_frame_size",
             bit_length=16,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -119,7 +119,7 @@ class UmasInitCommsResponse(UmasPDUItem):
         )
 
         firmware_version: int = read_buffer.read_unsigned_short(
-            logical_name="firmwareVersion",
+            logical_name="firmware_version",
             bit_length=16,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -127,7 +127,7 @@ class UmasInitCommsResponse(UmasPDUItem):
         )
 
         not_sure: int = read_buffer.read_unsigned_int(
-            logical_name="notSure",
+            logical_name="not_sure",
             bit_length=32,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -135,7 +135,7 @@ class UmasInitCommsResponse(UmasPDUItem):
         )
 
         internal_code: int = read_buffer.read_unsigned_int(
-            logical_name="internalCode",
+            logical_name="internal_code",
             bit_length=32,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -143,7 +143,7 @@ class UmasInitCommsResponse(UmasPDUItem):
         )
 
         hostname_length: int = read_buffer.read_unsigned_byte(
-            logical_name="hostnameLength",
+            logical_name="hostname_length",
             bit_length=8,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasMemoryBlockBasicInfo.py b/plc4py/plc4py/protocols/umas/readwrite/UmasMemoryBlockBasicInfo.py
index 37c66165cf..d3af178d51 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasMemoryBlockBasicInfo.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasMemoryBlockBasicInfo.py
@@ -95,7 +95,7 @@ class UmasMemoryBlockBasicInfo(UmasMemoryBlock):
         )
 
         not_sure: int = read_buffer.read_unsigned_short(
-            logical_name="notSure",
+            logical_name="not_sure",
             bit_length=16,
             block_number=block_number,
             offset=offset,
@@ -106,7 +106,7 @@ class UmasMemoryBlockBasicInfo(UmasMemoryBlock):
         )
 
         hardware_id: int = read_buffer.read_unsigned_int(
-            logical_name="hardwareId",
+            logical_name="hardware_id",
             bit_length=32,
             block_number=block_number,
             offset=offset,
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUItem.py b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUItem.py
index 5ed3365996..6f2fe3f3e5 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUItem.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUItem.py
@@ -47,7 +47,7 @@ class UmasPDUItem(ABC, PlcMessage):
         pass
 
     @abstractmethod
-    def serialize_umas_pdu_item_child(self, write_buffer: WriteBuffer) -> None:
+    def serialize_umas_pduitem_child(self, write_buffer: WriteBuffer) -> None:
         pass
 
     def serialize(self, write_buffer: WriteBuffer):
@@ -61,13 +61,13 @@ class UmasPDUItem(ABC, PlcMessage):
         # Discriminator Field (umasFunctionKey) (Used as input to a switch field)
         write_buffer.write_unsigned_byte(
             self.umas_function_key,
-            logical_name="umasFunctionKey",
+            logical_name="umas_function_key",
             bit_length=8,
             byte_order=ByteOrder.LITTLE_ENDIAN,
         )
 
         # Switch field (Serialize the sub-type)
-        self.serialize_umas_pdu_item_child(write_buffer)
+        self.serialize_umas_pduitem_child(write_buffer)
 
         write_buffer.pop_context("UmasPDUItem")
 
@@ -131,7 +131,7 @@ class UmasPDUItem(ABC, PlcMessage):
         read_buffer.push_context("UmasPDUItem")
 
         pairing_key: int = read_buffer.read_unsigned_byte(
-            logical_name="pairingKey",
+            logical_name="pairing_key",
             bit_length=8,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -139,7 +139,7 @@ class UmasPDUItem(ABC, PlcMessage):
         )
 
         umas_function_key: int = read_buffer.read_unsigned_byte(
-            logical_name="umasFunctionKey",
+            logical_name="umas_function_key",
             bit_length=8,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -202,6 +202,15 @@ class UmasPDUItem(ABC, PlcMessage):
             builder = UmasPDUReadVariableRequest.static_parse_builder(
                 read_buffer, umas_request_function_key, byte_length
             )
+        from plc4py.protocols.umas.readwrite.UmasPDUWriteVariableRequest import (
+            UmasPDUWriteVariableRequest,
+        )
+
+        if umas_function_key == int(0x23):
+
+            builder = UmasPDUWriteVariableRequest.static_parse_builder(
+                read_buffer, umas_request_function_key, byte_length
+            )
         from plc4py.protocols.umas.readwrite.UmasPDUReadUnlocatedVariableNamesRequest import (
             UmasPDUReadUnlocatedVariableNamesRequest,
         )
@@ -256,6 +265,15 @@ class UmasPDUItem(ABC, PlcMessage):
             builder = UmasPDUReadVariableResponse.static_parse_builder(
                 read_buffer, umas_request_function_key, byte_length
             )
+        from plc4py.protocols.umas.readwrite.UmasPDUWriteVariableResponse import (
+            UmasPDUWriteVariableResponse,
+        )
+
+        if umas_function_key == int(0xFE) and umas_request_function_key == int(0x23):
+
+            builder = UmasPDUWriteVariableResponse.static_parse_builder(
+                read_buffer, umas_request_function_key, byte_length
+            )
         from plc4py.protocols.umas.readwrite.UmasPDUReadUnlocatedVariableResponse import (
             UmasPDUReadUnlocatedVariableResponse,
         )
@@ -279,8 +297,8 @@ class UmasPDUItem(ABC, PlcMessage):
 
         read_buffer.pop_context("UmasPDUItem")
         # Create the instance
-        _umas_pdu_item: UmasPDUItem = builder.build(pairing_key, byte_length)
-        return _umas_pdu_item
+        _umas_pduitem: UmasPDUItem = builder.build(pairing_key, byte_length)
+        return _umas_pduitem
 
     def equals(self, o: object) -> bool:
         if self == o:
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUPlcIdentRequest.py b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUPlcIdentRequest.py
index a10a925b2a..5d6c8946ad 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUPlcIdentRequest.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUPlcIdentRequest.py
@@ -37,7 +37,7 @@ class UmasPDUPlcIdentRequest(UmasPDUItem):
     umas_function_key: ClassVar[int] = 0x02
     umas_request_function_key: ClassVar[int] = 0
 
-    def serialize_umas_pdu_item_child(self, write_buffer: WriteBuffer):
+    def serialize_umas_pduitem_child(self, write_buffer: WriteBuffer):
         write_buffer.push_context("UmasPDUPlcIdentRequest")
 
         write_buffer.pop_context("UmasPDUPlcIdentRequest")
@@ -89,8 +89,8 @@ class UmasPDUPlcIdentRequest(UmasPDUItem):
 class UmasPDUPlcIdentRequestBuilder:
 
     def build(self, byte_length: int, pairing_key) -> UmasPDUPlcIdentRequest:
-        umas_pdu_plc_ident_request: UmasPDUPlcIdentRequest = UmasPDUPlcIdentRequest(
+        umas_pduplc_ident_request: UmasPDUPlcIdentRequest = UmasPDUPlcIdentRequest(
             byte_length,
             pairing_key,
         )
-        return umas_pdu_plc_ident_request
+        return umas_pduplc_ident_request
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUPlcIdentResponse.py b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUPlcIdentResponse.py
index ea6303d3ab..a1ad198f73 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUPlcIdentResponse.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUPlcIdentResponse.py
@@ -54,7 +54,7 @@ class UmasPDUPlcIdentResponse(UmasPDUItem):
     umas_function_key: ClassVar[int] = 0xFE
     umas_request_function_key: ClassVar[int] = 0x02
 
-    def serialize_umas_pdu_item_child(self, write_buffer: WriteBuffer):
+    def serialize_umas_pduitem_child(self, write_buffer: WriteBuffer):
         write_buffer.push_context("UmasPDUPlcIdentResponse")
 
         # Simple Field (range)
@@ -117,7 +117,7 @@ class UmasPDUPlcIdentResponse(UmasPDUItem):
 
         # Array Field (memoryIdents)
         write_buffer.write_complex_array(
-            self.memory_idents, logical_name="memoryIdents"
+            self.memory_idents, logical_name="memory_idents"
         )
 
         write_buffer.pop_context("UmasPDUPlcIdentResponse")
@@ -203,7 +203,7 @@ class UmasPDUPlcIdentResponse(UmasPDUItem):
         )
 
         com_version: int = read_buffer.read_unsigned_short(
-            logical_name="comVersion",
+            logical_name="com_version",
             bit_length=16,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -211,7 +211,7 @@ class UmasPDUPlcIdentResponse(UmasPDUItem):
         )
 
         com_patch: int = read_buffer.read_unsigned_short(
-            logical_name="comPatch",
+            logical_name="com_patch",
             bit_length=16,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -219,7 +219,7 @@ class UmasPDUPlcIdentResponse(UmasPDUItem):
         )
 
         int_version: int = read_buffer.read_unsigned_short(
-            logical_name="intVersion",
+            logical_name="int_version",
             bit_length=16,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -227,7 +227,7 @@ class UmasPDUPlcIdentResponse(UmasPDUItem):
         )
 
         hardware_version: int = read_buffer.read_unsigned_short(
-            logical_name="hardwareVersion",
+            logical_name="hardware_version",
             bit_length=16,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -235,7 +235,7 @@ class UmasPDUPlcIdentResponse(UmasPDUItem):
         )
 
         crash_code: int = read_buffer.read_unsigned_int(
-            logical_name="crashCode",
+            logical_name="crash_code",
             bit_length=32,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -251,7 +251,7 @@ class UmasPDUPlcIdentResponse(UmasPDUItem):
         )
 
         hostname_length: int = read_buffer.read_unsigned_byte(
-            logical_name="hostnameLength",
+            logical_name="hostname_length",
             bit_length=8,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -267,7 +267,7 @@ class UmasPDUPlcIdentResponse(UmasPDUItem):
         )
 
         number_of_memory_banks: int = read_buffer.read_unsigned_byte(
-            logical_name="numberOfMemoryBanks",
+            logical_name="number_of_memory_banks",
             bit_length=8,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -358,7 +358,7 @@ class UmasPDUPlcIdentResponseBuilder:
     memory_idents: List[PlcMemoryBlockIdent]
 
     def build(self, byte_length: int, pairing_key) -> UmasPDUPlcIdentResponse:
-        umas_pdu_plc_ident_response: UmasPDUPlcIdentResponse = UmasPDUPlcIdentResponse(
+        umas_pduplc_ident_response: UmasPDUPlcIdentResponse = UmasPDUPlcIdentResponse(
             byte_length,
             pairing_key,
             self.range,
@@ -375,4 +375,4 @@ class UmasPDUPlcIdentResponseBuilder:
             self.number_of_memory_banks,
             self.memory_idents,
         )
-        return umas_pdu_plc_ident_response
+        return umas_pduplc_ident_response
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUPlcStatusRequest.py b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUPlcStatusRequest.py
index 7878c85275..5b09bdf00c 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUPlcStatusRequest.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUPlcStatusRequest.py
@@ -37,7 +37,7 @@ class UmasPDUPlcStatusRequest(UmasPDUItem):
     umas_function_key: ClassVar[int] = 0x04
     umas_request_function_key: ClassVar[int] = 0
 
-    def serialize_umas_pdu_item_child(self, write_buffer: WriteBuffer):
+    def serialize_umas_pduitem_child(self, write_buffer: WriteBuffer):
         write_buffer.push_context("UmasPDUPlcStatusRequest")
 
         write_buffer.pop_context("UmasPDUPlcStatusRequest")
@@ -89,8 +89,8 @@ class UmasPDUPlcStatusRequest(UmasPDUItem):
 class UmasPDUPlcStatusRequestBuilder:
 
     def build(self, byte_length: int, pairing_key) -> UmasPDUPlcStatusRequest:
-        umas_pdu_plc_status_request: UmasPDUPlcStatusRequest = UmasPDUPlcStatusRequest(
+        umas_pduplc_status_request: UmasPDUPlcStatusRequest = UmasPDUPlcStatusRequest(
             byte_length,
             pairing_key,
         )
-        return umas_pdu_plc_status_request
+        return umas_pduplc_status_request
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUPlcStatusResponse.py b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUPlcStatusResponse.py
index 45c0e7f589..fe826510d6 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUPlcStatusResponse.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUPlcStatusResponse.py
@@ -44,7 +44,7 @@ class UmasPDUPlcStatusResponse(UmasPDUItem):
     umas_function_key: ClassVar[int] = 0xFE
     umas_request_function_key: ClassVar[int] = 0x04
 
-    def serialize_umas_pdu_item_child(self, write_buffer: WriteBuffer):
+    def serialize_umas_pduitem_child(self, write_buffer: WriteBuffer):
         write_buffer.push_context("UmasPDUPlcStatusResponse")
 
         # Simple Field (notUsed1)
@@ -98,7 +98,7 @@ class UmasPDUPlcStatusResponse(UmasPDUItem):
         read_buffer.push_context("UmasPDUPlcStatusResponse")
 
         not_used1: int = read_buffer.read_unsigned_byte(
-            logical_name="notUsed1",
+            logical_name="not_used1",
             bit_length=8,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -106,7 +106,7 @@ class UmasPDUPlcStatusResponse(UmasPDUItem):
         )
 
         not_used2: int = read_buffer.read_unsigned_short(
-            logical_name="notUsed2",
+            logical_name="not_used2",
             bit_length=16,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -114,7 +114,7 @@ class UmasPDUPlcStatusResponse(UmasPDUItem):
         )
 
         number_of_blocks: int = read_buffer.read_unsigned_byte(
-            logical_name="numberOfBlocks",
+            logical_name="number_of_blocks",
             bit_length=8,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -175,7 +175,7 @@ class UmasPDUPlcStatusResponseBuilder:
     blocks: List[int]
 
     def build(self, byte_length: int, pairing_key) -> UmasPDUPlcStatusResponse:
-        umas_pdu_plc_status_response: UmasPDUPlcStatusResponse = (
+        umas_pduplc_status_response: UmasPDUPlcStatusResponse = (
             UmasPDUPlcStatusResponse(
                 byte_length,
                 pairing_key,
@@ -185,4 +185,4 @@ class UmasPDUPlcStatusResponseBuilder:
                 self.blocks,
             )
         )
-        return umas_pdu_plc_status_response
+        return umas_pduplc_status_response
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUProjectInfoRequest.py b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUProjectInfoRequest.py
index 137985d3cd..dd98353137 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUProjectInfoRequest.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUProjectInfoRequest.py
@@ -39,7 +39,7 @@ class UmasPDUProjectInfoRequest(UmasPDUItem):
     umas_function_key: ClassVar[int] = 0x03
     umas_request_function_key: ClassVar[int] = 0
 
-    def serialize_umas_pdu_item_child(self, write_buffer: WriteBuffer):
+    def serialize_umas_pduitem_child(self, write_buffer: WriteBuffer):
         write_buffer.push_context("UmasPDUProjectInfoRequest")
 
         # Simple Field (subcode)
@@ -108,7 +108,7 @@ class UmasPDUProjectInfoRequestBuilder:
     subcode: int
 
     def build(self, byte_length: int, pairing_key) -> UmasPDUProjectInfoRequest:
-        umas_pdu_project_info_request: UmasPDUProjectInfoRequest = (
+        umas_pduproject_info_request: UmasPDUProjectInfoRequest = (
             UmasPDUProjectInfoRequest(byte_length, pairing_key, self.subcode)
         )
-        return umas_pdu_project_info_request
+        return umas_pduproject_info_request
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadDatatypeNamesResponse.py b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadDatatypeNamesResponse.py
index 84339c738e..cc0ca08c7a 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadDatatypeNamesResponse.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadDatatypeNamesResponse.py
@@ -101,7 +101,7 @@ class UmasPDUReadDatatypeNamesResponse:
         range: int = read_buffer.read_unsigned_byte(logical_name="range", bit_length=8)
 
         next_address: int = read_buffer.read_unsigned_short(
-            logical_name="nextAddress", bit_length=16
+            logical_name="next_address", bit_length=16
         )
 
         unknown1: int = read_buffer.read_unsigned_byte(
@@ -109,7 +109,7 @@ class UmasPDUReadDatatypeNamesResponse:
         )
 
         no_of_records: int = read_buffer.read_unsigned_short(
-            logical_name="noOfRecords", bit_length=16
+            logical_name="no_of_records", bit_length=16
         )
 
         records: List[Any] = read_buffer.read_array_field(
@@ -120,12 +120,12 @@ class UmasPDUReadDatatypeNamesResponse:
 
         read_buffer.pop_context("UmasPDUReadDatatypeNamesResponse")
         # Create the instance
-        _umas_pdu_read_datatype_names_response: UmasPDUReadDatatypeNamesResponse = (
+        _umas_pduread_datatype_names_response: UmasPDUReadDatatypeNamesResponse = (
             UmasPDUReadDatatypeNamesResponse(
                 range, next_address, unknown1, no_of_records, records
             )
         )
-        return _umas_pdu_read_datatype_names_response
+        return _umas_pduread_datatype_names_response
 
     def equals(self, o: object) -> bool:
         if self == o:
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadMemoryBlockRequest.py b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadMemoryBlockRequest.py
index f065cc6f60..a40d872903 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadMemoryBlockRequest.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadMemoryBlockRequest.py
@@ -43,7 +43,7 @@ class UmasPDUReadMemoryBlockRequest(UmasPDUItem):
     umas_function_key: ClassVar[int] = 0x20
     umas_request_function_key: ClassVar[int] = 0
 
-    def serialize_umas_pdu_item_child(self, write_buffer: WriteBuffer):
+    def serialize_umas_pduitem_child(self, write_buffer: WriteBuffer):
         write_buffer.push_context("UmasPDUReadMemoryBlockRequest")
 
         # Simple Field (range)
@@ -110,7 +110,7 @@ class UmasPDUReadMemoryBlockRequest(UmasPDUItem):
         )
 
         block_number: int = read_buffer.read_unsigned_short(
-            logical_name="blockNumber",
+            logical_name="block_number",
             bit_length=16,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -126,7 +126,7 @@ class UmasPDUReadMemoryBlockRequest(UmasPDUItem):
         )
 
         unknown_object1: int = read_buffer.read_unsigned_short(
-            logical_name="unknownObject1",
+            logical_name="unknown_object1",
             bit_length=16,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -134,7 +134,7 @@ class UmasPDUReadMemoryBlockRequest(UmasPDUItem):
         )
 
         number_of_bytes: int = read_buffer.read_unsigned_short(
-            logical_name="numberOfBytes",
+            logical_name="number_of_bytes",
             bit_length=16,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -188,7 +188,7 @@ class UmasPDUReadMemoryBlockRequestBuilder:
     number_of_bytes: int
 
     def build(self, byte_length: int, pairing_key) -> UmasPDUReadMemoryBlockRequest:
-        umas_pdu_read_memory_block_request: UmasPDUReadMemoryBlockRequest = (
+        umas_pduread_memory_block_request: UmasPDUReadMemoryBlockRequest = (
             UmasPDUReadMemoryBlockRequest(
                 byte_length,
                 pairing_key,
@@ -199,4 +199,4 @@ class UmasPDUReadMemoryBlockRequestBuilder:
                 self.number_of_bytes,
             )
         )
-        return umas_pdu_read_memory_block_request
+        return umas_pduread_memory_block_request
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadMemoryBlockResponse.py b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadMemoryBlockResponse.py
index 35f5ce1a61..c36f6d89e7 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadMemoryBlockResponse.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadMemoryBlockResponse.py
@@ -43,7 +43,7 @@ class UmasPDUReadMemoryBlockResponse(UmasPDUItem):
     umas_function_key: ClassVar[int] = 0xFE
     umas_request_function_key: ClassVar[int] = 0x20
 
-    def serialize_umas_pdu_item_child(self, write_buffer: WriteBuffer):
+    def serialize_umas_pduitem_child(self, write_buffer: WriteBuffer):
         write_buffer.push_context("UmasPDUReadMemoryBlockResponse")
 
         # Simple Field (range)
@@ -95,7 +95,7 @@ class UmasPDUReadMemoryBlockResponse(UmasPDUItem):
         )
 
         number_of_bytes: int = read_buffer.read_unsigned_short(
-            logical_name="numberOfBytes",
+            logical_name="number_of_bytes",
             bit_length=16,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -152,9 +152,9 @@ class UmasPDUReadMemoryBlockResponseBuilder:
     block: List[int]
 
     def build(self, byte_length: int, pairing_key) -> UmasPDUReadMemoryBlockResponse:
-        umas_pdu_read_memory_block_response: UmasPDUReadMemoryBlockResponse = (
+        umas_pduread_memory_block_response: UmasPDUReadMemoryBlockResponse = (
             UmasPDUReadMemoryBlockResponse(
                 byte_length, pairing_key, self.range, self.number_of_bytes, self.block
             )
         )
-        return umas_pdu_read_memory_block_response
+        return umas_pduread_memory_block_response
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadUmasUDTDefinitionResponse.py b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadUmasUDTDefinitionResponse.py
index b156b10959..61518eaa21 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadUmasUDTDefinitionResponse.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadUmasUDTDefinitionResponse.py
@@ -96,7 +96,7 @@ class UmasPDUReadUmasUDTDefinitionResponse:
         )
 
         no_of_records: int = read_buffer.read_unsigned_short(
-            logical_name="noOfRecords", bit_length=16
+            logical_name="no_of_records", bit_length=16
         )
 
         records: List[Any] = read_buffer.read_array_field(
@@ -107,12 +107,12 @@ class UmasPDUReadUmasUDTDefinitionResponse:
 
         read_buffer.pop_context("UmasPDUReadUmasUDTDefinitionResponse")
         # Create the instance
-        _umas_pdu_read_umas_udt_definition_response: (
+        _umas_pduread_umas_udtdefinition_response: (
             UmasPDUReadUmasUDTDefinitionResponse
         ) = UmasPDUReadUmasUDTDefinitionResponse(
             range, unknown1, no_of_records, records
         )
-        return _umas_pdu_read_umas_udt_definition_response
+        return _umas_pduread_umas_udtdefinition_response
 
     def equals(self, o: object) -> bool:
         if self == o:
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadUnlocatedVariableNamesRequest.py b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadUnlocatedVariableNamesRequest.py
index 3d03101233..c2f6c0055f 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadUnlocatedVariableNamesRequest.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadUnlocatedVariableNamesRequest.py
@@ -44,7 +44,7 @@ class UmasPDUReadUnlocatedVariableNamesRequest(UmasPDUItem):
     umas_function_key: ClassVar[int] = 0x26
     umas_request_function_key: ClassVar[int] = 0
 
-    def serialize_umas_pdu_item_child(self, write_buffer: WriteBuffer):
+    def serialize_umas_pduitem_child(self, write_buffer: WriteBuffer):
         write_buffer.push_context("UmasPDUReadUnlocatedVariableNamesRequest")
 
         # Simple Field (recordType)
@@ -109,7 +109,7 @@ class UmasPDUReadUnlocatedVariableNamesRequest(UmasPDUItem):
         read_buffer.push_context("UmasPDUReadUnlocatedVariableNamesRequest")
 
         record_type: int = read_buffer.read_unsigned_short(
-            logical_name="recordType",
+            logical_name="record_type",
             bit_length=16,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -125,7 +125,7 @@ class UmasPDUReadUnlocatedVariableNamesRequest(UmasPDUItem):
         )
 
         hardware_id: int = read_buffer.read_unsigned_int(
-            logical_name="hardwareId",
+            logical_name="hardware_id",
             bit_length=32,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -133,7 +133,7 @@ class UmasPDUReadUnlocatedVariableNamesRequest(UmasPDUItem):
         )
 
         block_no: int = read_buffer.read_unsigned_short(
-            logical_name="blockNo",
+            logical_name="block_no",
             bit_length=16,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -206,7 +206,7 @@ class UmasPDUReadUnlocatedVariableNamesRequestBuilder:
     def build(
         self, byte_length: int, pairing_key
     ) -> UmasPDUReadUnlocatedVariableNamesRequest:
-        umas_pdu_read_unlocated_variable_names_request: (
+        umas_pduread_unlocated_variable_names_request: (
             UmasPDUReadUnlocatedVariableNamesRequest
         ) = UmasPDUReadUnlocatedVariableNamesRequest(
             byte_length,
@@ -217,4 +217,4 @@ class UmasPDUReadUnlocatedVariableNamesRequestBuilder:
             self.block_no,
             self.offset,
         )
-        return umas_pdu_read_unlocated_variable_names_request
+        return umas_pduread_unlocated_variable_names_request
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadUnlocatedVariableNamesResponse.py b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadUnlocatedVariableNamesResponse.py
index 9de84d38b3..d41e44d5c7 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadUnlocatedVariableNamesResponse.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadUnlocatedVariableNamesResponse.py
@@ -105,7 +105,7 @@ class UmasPDUReadUnlocatedVariableNamesResponse:
         range: int = read_buffer.read_unsigned_byte(logical_name="range", bit_length=8)
 
         next_address: int = read_buffer.read_unsigned_short(
-            logical_name="nextAddress", bit_length=16
+            logical_name="next_address", bit_length=16
         )
 
         unknown1: int = read_buffer.read_unsigned_short(
@@ -113,7 +113,7 @@ class UmasPDUReadUnlocatedVariableNamesResponse:
         )
 
         no_of_records: int = read_buffer.read_unsigned_short(
-            logical_name="noOfRecords", bit_length=16
+            logical_name="no_of_records", bit_length=16
         )
 
         records: List[Any] = read_buffer.read_array_field(
@@ -124,12 +124,12 @@ class UmasPDUReadUnlocatedVariableNamesResponse:
 
         read_buffer.pop_context("UmasPDUReadUnlocatedVariableNamesResponse")
         # Create the instance
-        _umas_pdu_read_unlocated_variable_names_response: (
+        _umas_pduread_unlocated_variable_names_response: (
             UmasPDUReadUnlocatedVariableNamesResponse
         ) = UmasPDUReadUnlocatedVariableNamesResponse(
             range, next_address, unknown1, no_of_records, records
         )
-        return _umas_pdu_read_unlocated_variable_names_response
+        return _umas_pduread_unlocated_variable_names_response
 
     def equals(self, o: object) -> bool:
         if self == o:
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadUnlocatedVariableResponse.py b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadUnlocatedVariableResponse.py
index 6978984a09..ec3806ddc4 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadUnlocatedVariableResponse.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadUnlocatedVariableResponse.py
@@ -41,7 +41,7 @@ class UmasPDUReadUnlocatedVariableResponse(UmasPDUItem):
     umas_function_key: ClassVar[int] = 0xFE
     umas_request_function_key: ClassVar[int] = 0x26
 
-    def serialize_umas_pdu_item_child(self, write_buffer: WriteBuffer):
+    def serialize_umas_pduitem_child(self, write_buffer: WriteBuffer):
         write_buffer.push_context("UmasPDUReadUnlocatedVariableResponse")
 
         # Array Field (block)
@@ -116,7 +116,7 @@ class UmasPDUReadUnlocatedVariableResponseBuilder:
     def build(
         self, byte_length: int, pairing_key
     ) -> UmasPDUReadUnlocatedVariableResponse:
-        umas_pdu_read_unlocated_variable_response: (
+        umas_pduread_unlocated_variable_response: (
             UmasPDUReadUnlocatedVariableResponse
         ) = UmasPDUReadUnlocatedVariableResponse(byte_length, pairing_key, self.block)
-        return umas_pdu_read_unlocated_variable_response
+        return umas_pduread_unlocated_variable_response
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadVariableRequest.py b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadVariableRequest.py
index c5fe4f7fa3..0884ccd019 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadVariableRequest.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadVariableRequest.py
@@ -23,8 +23,8 @@ from plc4py.api.exceptions.exceptions import PlcRuntimeException
 from plc4py.api.exceptions.exceptions import SerializationException
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.umas.readwrite.UmasPDUItem import UmasPDUItem
-from plc4py.protocols.umas.readwrite.VariableRequestReference import (
-    VariableRequestReference,
+from plc4py.protocols.umas.readwrite.VariableReadRequestReference import (
+    VariableReadRequestReference,
 )
 from plc4py.spi.generation.ReadBuffer import ReadBuffer
 from plc4py.spi.generation.WriteBuffer import WriteBuffer
@@ -39,14 +39,14 @@ import math
 class UmasPDUReadVariableRequest(UmasPDUItem):
     crc: int
     variable_count: int
-    variables: List[VariableRequestReference]
+    variables: List[VariableReadRequestReference]
     # Arguments.
     byte_length: int
     # Accessors for discriminator values.
     umas_function_key: ClassVar[int] = 0x22
     umas_request_function_key: ClassVar[int] = 0
 
-    def serialize_umas_pdu_item_child(self, write_buffer: WriteBuffer):
+    def serialize_umas_pduitem_child(self, write_buffer: WriteBuffer):
         write_buffer.push_context("UmasPDUReadVariableRequest")
 
         # Simple Field (crc)
@@ -97,7 +97,7 @@ class UmasPDUReadVariableRequest(UmasPDUItem):
         )
 
         variable_count: int = read_buffer.read_unsigned_byte(
-            logical_name="variableCount",
+            logical_name="variable_count",
             bit_length=8,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -106,7 +106,7 @@ class UmasPDUReadVariableRequest(UmasPDUItem):
 
         variables: List[Any] = read_buffer.read_array_field(
             logical_name="variables",
-            read_function=VariableRequestReference.static_parse,
+            read_function=VariableReadRequestReference.static_parse,
             count=variable_count,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -151,12 +151,12 @@ class UmasPDUReadVariableRequest(UmasPDUItem):
 class UmasPDUReadVariableRequestBuilder:
     crc: int
     variable_count: int
-    variables: List[VariableRequestReference]
+    variables: List[VariableReadRequestReference]
 
     def build(self, byte_length: int, pairing_key) -> UmasPDUReadVariableRequest:
-        umas_pdu_read_variable_request: UmasPDUReadVariableRequest = (
+        umas_pduread_variable_request: UmasPDUReadVariableRequest = (
             UmasPDUReadVariableRequest(
                 byte_length, pairing_key, self.crc, self.variable_count, self.variables
             )
         )
-        return umas_pdu_read_variable_request
+        return umas_pduread_variable_request
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadVariableResponse.py b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadVariableResponse.py
index cc81151495..3bb995b4f4 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadVariableResponse.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadVariableResponse.py
@@ -41,7 +41,7 @@ class UmasPDUReadVariableResponse(UmasPDUItem):
     umas_function_key: ClassVar[int] = 0xFE
     umas_request_function_key: ClassVar[int] = 0x22
 
-    def serialize_umas_pdu_item_child(self, write_buffer: WriteBuffer):
+    def serialize_umas_pduitem_child(self, write_buffer: WriteBuffer):
         write_buffer.push_context("UmasPDUReadVariableResponse")
 
         # Array Field (block)
@@ -112,7 +112,7 @@ class UmasPDUReadVariableResponseBuilder:
     block: List[int]
 
     def build(self, byte_length: int, pairing_key) -> UmasPDUReadVariableResponse:
-        umas_pdu_read_variable_response: UmasPDUReadVariableResponse = (
+        umas_pduread_variable_response: UmasPDUReadVariableResponse = (
             UmasPDUReadVariableResponse(byte_length, pairing_key, self.block)
         )
-        return umas_pdu_read_variable_response
+        return umas_pduread_variable_response
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadVariableRequest.py b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUWriteVariableRequest.py
similarity index 77%
copy from plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadVariableRequest.py
copy to plc4py/plc4py/protocols/umas/readwrite/UmasPDUWriteVariableRequest.py
index c5fe4f7fa3..1620150f89 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadVariableRequest.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUWriteVariableRequest.py
@@ -23,8 +23,8 @@ from plc4py.api.exceptions.exceptions import PlcRuntimeException
 from plc4py.api.exceptions.exceptions import SerializationException
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.umas.readwrite.UmasPDUItem import UmasPDUItem
-from plc4py.protocols.umas.readwrite.VariableRequestReference import (
-    VariableRequestReference,
+from plc4py.protocols.umas.readwrite.VariableWriteRequestReference import (
+    VariableWriteRequestReference,
 )
 from plc4py.spi.generation.ReadBuffer import ReadBuffer
 from plc4py.spi.generation.WriteBuffer import WriteBuffer
@@ -36,18 +36,18 @@ import math
 
 
 @dataclass
-class UmasPDUReadVariableRequest(UmasPDUItem):
+class UmasPDUWriteVariableRequest(UmasPDUItem):
     crc: int
     variable_count: int
-    variables: List[VariableRequestReference]
+    variables: List[VariableWriteRequestReference]
     # Arguments.
     byte_length: int
     # Accessors for discriminator values.
-    umas_function_key: ClassVar[int] = 0x22
+    umas_function_key: ClassVar[int] = 0x23
     umas_request_function_key: ClassVar[int] = 0
 
-    def serialize_umas_pdu_item_child(self, write_buffer: WriteBuffer):
-        write_buffer.push_context("UmasPDUReadVariableRequest")
+    def serialize_umas_pduitem_child(self, write_buffer: WriteBuffer):
+        write_buffer.push_context("UmasPDUWriteVariableRequest")
 
         # Simple Field (crc)
         write_buffer.write_unsigned_int(self.crc, bit_length=32, logical_name="crc")
@@ -60,14 +60,14 @@ class UmasPDUReadVariableRequest(UmasPDUItem):
         # Array Field (variables)
         write_buffer.write_complex_array(self.variables, logical_name="variables")
 
-        write_buffer.pop_context("UmasPDUReadVariableRequest")
+        write_buffer.pop_context("UmasPDUWriteVariableRequest")
 
     def length_in_bytes(self) -> int:
         return int(math.ceil(float(self.length_in_bits() / 8.0)))
 
     def length_in_bits(self) -> int:
         length_in_bits: int = super().length_in_bits()
-        _value: UmasPDUReadVariableRequest = self
+        _value: UmasPDUWriteVariableRequest = self
 
         # Simple field (crc)
         length_in_bits += 32
@@ -86,7 +86,7 @@ class UmasPDUReadVariableRequest(UmasPDUItem):
     def static_parse_builder(
         read_buffer: ReadBuffer, umas_request_function_key: int, byte_length: int
     ):
-        read_buffer.push_context("UmasPDUReadVariableRequest")
+        read_buffer.push_context("UmasPDUWriteVariableRequest")
 
         crc: int = read_buffer.read_unsigned_int(
             logical_name="crc",
@@ -97,7 +97,7 @@ class UmasPDUReadVariableRequest(UmasPDUItem):
         )
 
         variable_count: int = read_buffer.read_unsigned_byte(
-            logical_name="variableCount",
+            logical_name="variable_count",
             bit_length=8,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
@@ -106,25 +106,25 @@ class UmasPDUReadVariableRequest(UmasPDUItem):
 
         variables: List[Any] = read_buffer.read_array_field(
             logical_name="variables",
-            read_function=VariableRequestReference.static_parse,
+            read_function=VariableWriteRequestReference.static_parse,
             count=variable_count,
             byte_order=ByteOrder.LITTLE_ENDIAN,
             umas_request_function_key=umas_request_function_key,
             byte_length=byte_length,
         )
 
-        read_buffer.pop_context("UmasPDUReadVariableRequest")
+        read_buffer.pop_context("UmasPDUWriteVariableRequest")
         # Create the instance
-        return UmasPDUReadVariableRequestBuilder(crc, variable_count, variables)
+        return UmasPDUWriteVariableRequestBuilder(crc, variable_count, variables)
 
     def equals(self, o: object) -> bool:
         if self == o:
             return True
 
-        if not isinstance(o, UmasPDUReadVariableRequest):
+        if not isinstance(o, UmasPDUWriteVariableRequest):
             return False
 
-        that: UmasPDUReadVariableRequest = UmasPDUReadVariableRequest(o)
+        that: UmasPDUWriteVariableRequest = UmasPDUWriteVariableRequest(o)
         return (
             (self.crc == that.crc)
             and (self.variable_count == that.variable_count)
@@ -148,15 +148,15 @@ class UmasPDUReadVariableRequest(UmasPDUItem):
 
 
 @dataclass
-class UmasPDUReadVariableRequestBuilder:
+class UmasPDUWriteVariableRequestBuilder:
     crc: int
     variable_count: int
-    variables: List[VariableRequestReference]
+    variables: List[VariableWriteRequestReference]
 
-    def build(self, byte_length: int, pairing_key) -> UmasPDUReadVariableRequest:
-        umas_pdu_read_variable_request: UmasPDUReadVariableRequest = (
-            UmasPDUReadVariableRequest(
+    def build(self, byte_length: int, pairing_key) -> UmasPDUWriteVariableRequest:
+        umas_pduwrite_variable_request: UmasPDUWriteVariableRequest = (
+            UmasPDUWriteVariableRequest(
                 byte_length, pairing_key, self.crc, self.variable_count, self.variables
             )
         )
-        return umas_pdu_read_variable_request
+        return umas_pduwrite_variable_request
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadVariableResponse.py b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUWriteVariableResponse.py
similarity index 75%
copy from plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadVariableResponse.py
copy to plc4py/plc4py/protocols/umas/readwrite/UmasPDUWriteVariableResponse.py
index cc81151495..9ee159efc0 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasPDUReadVariableResponse.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasPDUWriteVariableResponse.py
@@ -33,30 +33,30 @@ import math
 
 
 @dataclass
-class UmasPDUReadVariableResponse(UmasPDUItem):
+class UmasPDUWriteVariableResponse(UmasPDUItem):
     block: List[int]
     # Arguments.
     byte_length: int
     # Accessors for discriminator values.
     umas_function_key: ClassVar[int] = 0xFE
-    umas_request_function_key: ClassVar[int] = 0x22
+    umas_request_function_key: ClassVar[int] = 0x23
 
-    def serialize_umas_pdu_item_child(self, write_buffer: WriteBuffer):
-        write_buffer.push_context("UmasPDUReadVariableResponse")
+    def serialize_umas_pduitem_child(self, write_buffer: WriteBuffer):
+        write_buffer.push_context("UmasPDUWriteVariableResponse")
 
         # Array Field (block)
         write_buffer.write_simple_array(
             self.block, write_buffer.write_unsigned_byte, logical_name="block"
         )
 
-        write_buffer.pop_context("UmasPDUReadVariableResponse")
+        write_buffer.pop_context("UmasPDUWriteVariableResponse")
 
     def length_in_bytes(self) -> int:
         return int(math.ceil(float(self.length_in_bits() / 8.0)))
 
     def length_in_bits(self) -> int:
         length_in_bits: int = super().length_in_bits()
-        _value: UmasPDUReadVariableResponse = self
+        _value: UmasPDUWriteVariableResponse = self
 
         # Array field
         if self.block is not None:
@@ -68,7 +68,7 @@ class UmasPDUReadVariableResponse(UmasPDUItem):
     def static_parse_builder(
         read_buffer: ReadBuffer, umas_request_function_key: int, byte_length: int
     ):
-        read_buffer.push_context("UmasPDUReadVariableResponse")
+        read_buffer.push_context("UmasPDUWriteVariableResponse")
 
         block: List[Any] = read_buffer.read_array_field(
             logical_name="block",
@@ -79,18 +79,18 @@ class UmasPDUReadVariableResponse(UmasPDUItem):
             byte_length=byte_length,
         )
 
-        read_buffer.pop_context("UmasPDUReadVariableResponse")
+        read_buffer.pop_context("UmasPDUWriteVariableResponse")
         # Create the instance
-        return UmasPDUReadVariableResponseBuilder(block)
+        return UmasPDUWriteVariableResponseBuilder(block)
 
     def equals(self, o: object) -> bool:
         if self == o:
             return True
 
-        if not isinstance(o, UmasPDUReadVariableResponse):
+        if not isinstance(o, UmasPDUWriteVariableResponse):
             return False
 
-        that: UmasPDUReadVariableResponse = UmasPDUReadVariableResponse(o)
+        that: UmasPDUWriteVariableResponse = UmasPDUWriteVariableResponse(o)
         return (self.block == that.block) and super().equals(that) and True
 
     def hash_code(self) -> int:
@@ -108,11 +108,11 @@ class UmasPDUReadVariableResponse(UmasPDUItem):
 
 
 @dataclass
-class UmasPDUReadVariableResponseBuilder:
+class UmasPDUWriteVariableResponseBuilder:
     block: List[int]
 
-    def build(self, byte_length: int, pairing_key) -> UmasPDUReadVariableResponse:
-        umas_pdu_read_variable_response: UmasPDUReadVariableResponse = (
-            UmasPDUReadVariableResponse(byte_length, pairing_key, self.block)
+    def build(self, byte_length: int, pairing_key) -> UmasPDUWriteVariableResponse:
+        umas_pduwrite_variable_response: UmasPDUWriteVariableResponse = (
+            UmasPDUWriteVariableResponse(byte_length, pairing_key, self.block)
         )
-        return umas_pdu_read_variable_response
+        return umas_pduwrite_variable_response
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasUDTDefinition.py b/plc4py/plc4py/protocols/umas/readwrite/UmasUDTDefinition.py
index b12af5c28b..9ecc4c7725 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasUDTDefinition.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasUDTDefinition.py
@@ -101,7 +101,7 @@ class UmasUDTDefinition:
         read_buffer.push_context("UmasUDTDefinition")
 
         data_type: int = read_buffer.read_unsigned_short(
-            logical_name="dataType", bit_length=16
+            logical_name="data_type", bit_length=16
         )
 
         offset: int = read_buffer.read_unsigned_short(
@@ -123,10 +123,10 @@ class UmasUDTDefinition:
 
         read_buffer.pop_context("UmasUDTDefinition")
         # Create the instance
-        _umas_udt_definition: UmasUDTDefinition = UmasUDTDefinition(
+        _umas_udtdefinition: UmasUDTDefinition = UmasUDTDefinition(
             data_type, offset, unknown5, unknown4, value
         )
-        return _umas_udt_definition
+        return _umas_udtdefinition
 
     def equals(self, o: object) -> bool:
         if self == o:
diff --git a/plc4py/plc4py/protocols/umas/readwrite/UmasUnlocatedVariableReference.py b/plc4py/plc4py/protocols/umas/readwrite/UmasUnlocatedVariableReference.py
index 68c8af3379..f6b685bfc1 100644
--- a/plc4py/plc4py/protocols/umas/readwrite/UmasUnlocatedVariableReference.py
+++ b/plc4py/plc4py/protocols/umas/readwrite/UmasUnlocatedVariableReference.py
@@ -128,7 +128,7 @@ class UmasUnlocatedVariableReference:
         read_buffer.push_context("UmasUnlocatedVariableReference")
 
         data_type: int = read_buffer.read_unsigned_byte(
-            logical_name="dataType", bit_length=8
+            logical_name="data_type", bit_length=8
         )
 
         unknown1: int = read_buffer.read_unsigned_byte(
@@ -152,7 +152,7 @@ class UmasUnlocatedVariableReference:
         )
 
         string_length: int = read_buffer.read_unsigned_short(
-            logical_name="stringLength", bit_length=16
+            logical_name="string_length", bit_length=16
         )
 
         value = read_buffer.read_manual(
diff --git a/plc4py/plc4py/protocols/umas/readwrite/VariableReadRequestReference.py b/plc4py/plc4py/protocols/umas/readwrite/VariableReadRequestReference.py
new file mode 100644
index 0000000000..b7ab516279
--- /dev/null
+++ b/plc4py/plc4py/protocols/umas/readwrite/VariableReadRequestReference.py
@@ -0,0 +1,182 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+from dataclasses import dataclass
+
+from plc4py.api.exceptions.exceptions import PlcRuntimeException
+from plc4py.api.exceptions.exceptions import SerializationException
+from plc4py.api.messages.PlcMessage import PlcMessage
+from plc4py.spi.generation.ReadBuffer import ReadBuffer
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
+import math
+
+
+@dataclass
+class VariableReadRequestReference:
+    is_array: int
+    data_size_index: int
+    block: int
+    base_offset: int
+    offset: int
+    array_length: int
+    UNKNOWN1: int = 0x01
+
+    def serialize(self, write_buffer: WriteBuffer):
+        write_buffer.push_context("VariableReadRequestReference")
+
+        # Simple Field (isArray)
+        write_buffer.write_unsigned_byte(
+            self.is_array, bit_length=4, logical_name="isArray"
+        )
+
+        # Simple Field (dataSizeIndex)
+        write_buffer.write_unsigned_byte(
+            self.data_size_index, bit_length=4, logical_name="dataSizeIndex"
+        )
+
+        # Simple Field (block)
+        write_buffer.write_unsigned_short(
+            self.block, bit_length=16, logical_name="block"
+        )
+
+        # Const Field (unknown1)
+        write_buffer.write_unsigned_byte(self.UNKNOWN1, logical_name="unknown1")
+
+        # Simple Field (baseOffset)
+        write_buffer.write_unsigned_short(
+            self.base_offset, bit_length=16, logical_name="baseOffset"
+        )
+
+        # Simple Field (offset)
+        write_buffer.write_unsigned_byte(
+            self.offset, bit_length=8, logical_name="offset"
+        )
+
+        # Optional Field (arrayLength) (Can be skipped, if the value is null)
+        if self.is_array:
+            write_buffer.write_unsigned_short(
+                self.array_length, logical_name="arrayLength"
+            )
+
+        write_buffer.pop_context("VariableReadRequestReference")
+
+    def length_in_bytes(self) -> int:
+        return int(math.ceil(float(self.length_in_bits() / 8.0)))
+
+    def length_in_bits(self) -> int:
+        length_in_bits: int = 0
+        _value: VariableReadRequestReference = self
+
+        # Simple field (isArray)
+        length_in_bits += 4
+
+        # Simple field (dataSizeIndex)
+        length_in_bits += 4
+
+        # Simple field (block)
+        length_in_bits += 16
+
+        # Const Field (unknown1)
+        length_in_bits += 8
+
+        # Simple field (baseOffset)
+        length_in_bits += 16
+
+        # Simple field (offset)
+        length_in_bits += 8
+
+        # Optional Field (arrayLength)
+        if self.is_array:
+            length_in_bits += 16
+
+        return length_in_bits
+
+    @staticmethod
+    def static_parse(read_buffer: ReadBuffer, **kwargs):
+        return VariableReadRequestReference.static_parse_context(read_buffer)
+
+    @staticmethod
+    def static_parse_context(read_buffer: ReadBuffer):
+        read_buffer.push_context("VariableReadRequestReference")
+
+        is_array: int = read_buffer.read_unsigned_byte(
+            logical_name="is_array", bit_length=4
+        )
+
+        data_size_index: int = read_buffer.read_unsigned_byte(
+            logical_name="data_size_index", bit_length=4
+        )
+
+        block: int = read_buffer.read_unsigned_short(
+            logical_name="block", bit_length=16
+        )
+
+        UNKNOWN1: int = read_buffer.read_unsigned_byte(logical_name="unknown1")
+
+        base_offset: int = read_buffer.read_unsigned_short(
+            logical_name="base_offset", bit_length=16
+        )
+
+        offset: int = read_buffer.read_unsigned_byte(
+            logical_name="offset", bit_length=8
+        )
+
+        array_length: int = None
+        if is_array:
+            array_length = read_buffer.read_unsigned_short(logical_name="array_length")
+
+        read_buffer.pop_context("VariableReadRequestReference")
+        # Create the instance
+        _variable_read_request_reference: VariableReadRequestReference = (
+            VariableReadRequestReference(
+                is_array, data_size_index, block, base_offset, offset, array_length
+            )
+        )
+        return _variable_read_request_reference
+
+    def equals(self, o: object) -> bool:
+        if self == o:
+            return True
+
+        if not isinstance(o, VariableReadRequestReference):
+            return False
+
+        that: VariableReadRequestReference = VariableReadRequestReference(o)
+        return (
+            (self.is_array == that.is_array)
+            and (self.data_size_index == that.data_size_index)
+            and (self.block == that.block)
+            and (self.base_offset == that.base_offset)
+            and (self.offset == that.offset)
+            and (self.array_length == that.array_length)
+            and True
+        )
+
+    def hash_code(self) -> int:
+        return hash(self)
+
+    def __str__(self) -> str:
+        pass
+        # write_buffer_box_based: WriteBufferBoxBased = WriteBufferBoxBased(True, True)
+        # try:
+        #    write_buffer_box_based.writeSerializable(self)
+        # except SerializationException as e:
+        #    raise PlcRuntimeException(e)
+
+        # return "\n" + str(write_buffer_box_based.get_box()) + "\n"
diff --git a/plc4py/plc4py/protocols/umas/readwrite/VariableWriteRequestReference.py b/plc4py/plc4py/protocols/umas/readwrite/VariableWriteRequestReference.py
new file mode 100644
index 0000000000..09552e23c5
--- /dev/null
+++ b/plc4py/plc4py/protocols/umas/readwrite/VariableWriteRequestReference.py
@@ -0,0 +1,209 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+from dataclasses import dataclass
+
+from plc4py.api.exceptions.exceptions import PlcRuntimeException
+from plc4py.api.exceptions.exceptions import SerializationException
+from plc4py.api.messages.PlcMessage import PlcMessage
+from plc4py.spi.generation.ReadBuffer import ReadBuffer
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
+from typing import Any
+from typing import List
+import math
+
+
+@dataclass
+class VariableWriteRequestReference:
+    is_array: int
+    data_size_index: int
+    block: int
+    base_offset: int
+    offset: int
+    array_length: int
+    record_data: List[int]
+    UNKNOWN1: int = 0x01
+
+    def serialize(self, write_buffer: WriteBuffer):
+        write_buffer.push_context("VariableWriteRequestReference")
+
+        # Simple Field (isArray)
+        write_buffer.write_unsigned_byte(
+            self.is_array, bit_length=4, logical_name="isArray"
+        )
+
+        # Simple Field (dataSizeIndex)
+        write_buffer.write_unsigned_byte(
+            self.data_size_index, bit_length=4, logical_name="dataSizeIndex"
+        )
+
+        # Simple Field (block)
+        write_buffer.write_unsigned_short(
+            self.block, bit_length=16, logical_name="block"
+        )
+
+        # Const Field (unknown1)
+        write_buffer.write_unsigned_byte(self.UNKNOWN1, logical_name="unknown1")
+
+        # Simple Field (baseOffset)
+        write_buffer.write_unsigned_short(
+            self.base_offset, bit_length=16, logical_name="baseOffset"
+        )
+
+        # Simple Field (offset)
+        write_buffer.write_unsigned_byte(
+            self.offset, bit_length=8, logical_name="offset"
+        )
+
+        # Optional Field (arrayLength) (Can be skipped, if the value is null)
+        if self.is_array:
+            write_buffer.write_unsigned_short(
+                self.array_length, logical_name="arrayLength"
+            )
+
+        # Array Field (recordData)
+        write_buffer.write_byte_array(self.record_data, logical_name="record_data")
+
+        write_buffer.pop_context("VariableWriteRequestReference")
+
+    def length_in_bytes(self) -> int:
+        return int(math.ceil(float(self.length_in_bits() / 8.0)))
+
+    def length_in_bits(self) -> int:
+        length_in_bits: int = 0
+        _value: VariableWriteRequestReference = self
+
+        # Simple field (isArray)
+        length_in_bits += 4
+
+        # Simple field (dataSizeIndex)
+        length_in_bits += 4
+
+        # Simple field (block)
+        length_in_bits += 16
+
+        # Const Field (unknown1)
+        length_in_bits += 8
+
+        # Simple field (baseOffset)
+        length_in_bits += 16
+
+        # Simple field (offset)
+        length_in_bits += 8
+
+        # Optional Field (arrayLength)
+        if self.is_array:
+            length_in_bits += 16
+
+        # Array field
+        if self.record_data is not None:
+            length_in_bits += 8 * len(self.record_data)
+
+        return length_in_bits
+
+    @staticmethod
+    def static_parse(read_buffer: ReadBuffer, **kwargs):
+        return VariableWriteRequestReference.static_parse_context(read_buffer)
+
+    @staticmethod
+    def static_parse_context(read_buffer: ReadBuffer):
+        read_buffer.push_context("VariableWriteRequestReference")
+
+        is_array: int = read_buffer.read_unsigned_byte(
+            logical_name="is_array", bit_length=4
+        )
+
+        data_size_index: int = read_buffer.read_unsigned_byte(
+            logical_name="data_size_index", bit_length=4
+        )
+
+        block: int = read_buffer.read_unsigned_short(
+            logical_name="block", bit_length=16
+        )
+
+        UNKNOWN1: int = read_buffer.read_unsigned_byte(logical_name="unknown1")
+
+        base_offset: int = read_buffer.read_unsigned_short(
+            logical_name="base_offset", bit_length=16
+        )
+
+        offset: int = read_buffer.read_unsigned_byte(
+            logical_name="offset", bit_length=8
+        )
+
+        array_length: int = None
+        if is_array:
+            array_length = read_buffer.read_unsigned_short(logical_name="array_length")
+
+        record_data: List[Any] = read_buffer.read_array_field(
+            logical_name="recordData",
+            read_function=read_buffer.read_byte,
+            count=(
+                data_size_index * array_length
+                if bool((is_array) == ((1)))
+                else data_size_index
+            ),
+        )
+
+        read_buffer.pop_context("VariableWriteRequestReference")
+        # Create the instance
+        _variable_write_request_reference: VariableWriteRequestReference = (
+            VariableWriteRequestReference(
+                is_array,
+                data_size_index,
+                block,
+                base_offset,
+                offset,
+                array_length,
+                record_data,
+            )
+        )
+        return _variable_write_request_reference
+
+    def equals(self, o: object) -> bool:
+        if self == o:
+            return True
+
+        if not isinstance(o, VariableWriteRequestReference):
+            return False
+
+        that: VariableWriteRequestReference = VariableWriteRequestReference(o)
+        return (
+            (self.is_array == that.is_array)
+            and (self.data_size_index == that.data_size_index)
+            and (self.block == that.block)
+            and (self.base_offset == that.base_offset)
+            and (self.offset == that.offset)
+            and (self.array_length == that.array_length)
+            and (self.record_data == that.record_data)
+            and True
+        )
+
+    def hash_code(self) -> int:
+        return hash(self)
+
+    def __str__(self) -> str:
+        pass
+        # write_buffer_box_based: WriteBufferBoxBased = WriteBufferBoxBased(True, True)
+        # try:
+        #    write_buffer_box_based.writeSerializable(self)
+        # except SerializationException as e:
+        #    raise PlcRuntimeException(e)
+
+        # return "\n" + str(write_buffer_box_based.get_box()) + "\n"
diff --git a/plc4py/tests/test_plc4py.py b/plc4py/tests/test_plc4py.py
index 2ed6cb37c0..554a9db3b8 100644
--- a/plc4py/tests/test_plc4py.py
+++ b/plc4py/tests/test_plc4py.py
@@ -31,11 +31,44 @@ from plc4py.drivers.modbus.ModbusConnection import ModbusConnection
 
 
 def test_version():
+    """
+    This test verifies the version of the package.
+
+    The version is a string that is expected to match the version specified in the
+    `__version__` constant at the top of the file. If the versions do not match,
+    the test will fail.
+
+    :return: None
+    """
+    """
+    This test verifies the version of the package.
+
+    The version is a string that is expected to match the version specified in the
+    `__version__` constant at the top of the file. If the versions do not match,
+    the test will fail.
+
+    :return: None
+    """
     assert __version__ == "0.1.0"
 
 
 @pytest.mark.asyncio
 async def test_plc_driver_manager_init():
+    """
+    This test verifies that the PlcDriverManager class is able to create a connection
+    successfully.
+
+    :return: None
+    """
+    """
+    This test verifies that the PlcDriverManager class is able to create a connection
+    successfully.
+
+    The test creates a PlcDriverManager object and then uses the connection method
+    to get a connection to a mock PLC. The connection should be an instance of
+    the PlcConnection class.
+
+    """
     driver_manager = PlcDriverManager()
     async with driver_manager.connection("mock:tcp://127.0.0.1:502") as connection:
         assert isinstance(connection, PlcConnection)
@@ -43,13 +76,31 @@ async def test_plc_driver_manager_init():
 
 @pytest.mark.asyncio
 async def manual_test_plc_driver_manager_init_modbus():
+    """
+    This test verifies that the PlcDriverManager class is able to create a connection
+    successfully with the Modbus protocol.
+
+    The test creates a PlcDriverManager object and then uses the connection method
+    to get a connection to a Modbus PLC. The connection should be an instance of
+    the ModbusConnection class.
+
+    """
     driver_manager = PlcDriverManager()
-    async with driver_manager.connection("nodbus:tcp://127.0.0.1:502") as connection:
+    async with driver_manager.connection("modbus:tcp://127.0.0.1:502") as connection:
         assert isinstance(connection, ModbusConnection)
 
 
 @pytest.mark.asyncio
 async def test_plc_driver_manager_init_mock():
+    """
+    This test verifies that the PlcDriverManager class is able to create a connection
+    successfully with the Mock driver.
+
+    The test creates a PlcDriverManager object and then uses the connection method
+    to get a connection to a Mock PLC. The connection should be an instance of
+    the MockConnection class.
+
+    """
     driver_manager = PlcDriverManager()
     async with driver_manager.connection("mock:tcp://127.0.0.1:502") as connection:
         assert isinstance(connection, MockConnection)
@@ -57,16 +108,30 @@ async def test_plc_driver_manager_init_mock():
 
 @pytest.mark.asyncio
 async def test_plc_driver_manager_init_mock_read_request():
+    """
+    This test verifies that the PlcDriverManager class is able to create a
+    connection to a mock PLC and then execute a read request successfully.
+
+    The test creates a PlcDriverManager object and then uses the connection method
+    to get a connection to a Mock PLC. It then uses the read_request_builder
+    to construct a read request with one item. The request is then executed
+    and the result should be a PlcReadResponse with a response code of OK.
+
+    """
     driver_manager = PlcDriverManager()
     tag = "1:BOOL"
 
     async with driver_manager.connection("mock:tcp://127.0.0.1:502") as connection:
+        # Create a read request builder
         with connection.read_request_builder() as builder:
+            # Add the tag to the request
             builder.add_item("Random Tag", tag)
+            # Build the request
             request: PlcTagRequest = builder.build()
+            # Execute the request
             response: PlcReadResponse = cast(
                 PlcReadResponse, await connection.execute(request)
             )
 
-    # verify that request has one field
+    # Verify that the request has one field
     assert response.response_code == PlcResponseCode.OK
diff --git a/plc4py/tests/unit/plc4py/drivers/modbus/test_modbus_connection.py b/plc4py/tests/unit/plc4py/drivers/modbus/test_modbus_connection.py
index 8a4111a03c..fddd86cfac 100644
--- a/plc4py/tests/unit/plc4py/drivers/modbus/test_modbus_connection.py
+++ b/plc4py/tests/unit/plc4py/drivers/modbus/test_modbus_connection.py
@@ -36,21 +36,20 @@ async def manual_test_plc_driver_modbus_connect():
 
 
 @pytest.mark.asyncio
-async def manual_test_plc_driver_modbus_read():
+@pytest.mark.xfail
+async def test_plc_driver_modbus_read():
+    log = logging.getLogger(__name__)
 
-    connection_string = "modbus://127.0.0.1:5020"
     driver_manager = PlcDriverManager()
-    response = None
-
-    async def communicate_with_plc():
-        async with driver_manager.connection(connection_string) as connection:
-            with connection.read_request_builder() as builder:
-                builder.add_item("Random Tag", "4x00001[10]")
-                request = builder.build()
+    async with driver_manager.connection("modbus://127.0.0.1:5020") as connection:
+        with connection.read_request_builder() as builder:
+            builder.add_item("Random Tag", "4x00001[10]")
+            request = builder.build()
 
         future = connection.execute(request)
         await future
         response = future.result()
+        value = response.tags["Random Tag"].value
+        log.error(f"Read tag 4x00001[10] - {value}")
 
-    communicate_with_plc()
     pass
diff --git a/plc4py/tests/unit/plc4py/drivers/umas/test_umas_connection.py b/plc4py/tests/unit/plc4py/drivers/umas/test_umas_connection.py
index b99c28d88e..c1d6fc57a1 100644
--- a/plc4py/tests/unit/plc4py/drivers/umas/test_umas_connection.py
+++ b/plc4py/tests/unit/plc4py/drivers/umas/test_umas_connection.py
@@ -26,6 +26,7 @@ from plc4py.PlcDriverManager import PlcDriverManager
 
 
 @pytest.mark.asyncio
+@pytest.mark.xfail
 async def manual_test_plc_driver_umas_connect():
     driver_manager = PlcDriverManager()
     async with driver_manager.connection("umas://127.0.0.1:5555") as connection:
@@ -34,7 +35,8 @@ async def manual_test_plc_driver_umas_connect():
 
 
 @pytest.mark.asyncio
-async def manual_test_plc_driver_umas_read():
+@pytest.mark.xfail
+async def test_plc_driver_umas_read():
     log = logging.getLogger(__name__)
 
     driver_manager = PlcDriverManager()
@@ -53,6 +55,7 @@ async def manual_test_plc_driver_umas_read():
 
 
 @pytest.mark.asyncio
+@pytest.mark.xfail
 async def manual_test_plc_driver_umas_browse():
     driver_manager = PlcDriverManager()
     async with driver_manager.connection("umas://192.168.1.174:502") as connection:
diff --git a/protocols/umas/src/main/resources/protocols/umas/umas.mspec b/protocols/umas/src/main/resources/protocols/umas/umas.mspec
index 2a8c4b500a..e724fbb8c3 100644
--- a/protocols/umas/src/main/resources/protocols/umas/umas.mspec
+++ b/protocols/umas/src/main/resources/protocols/umas/umas.mspec
@@ -84,7 +84,12 @@
         ['0x22'      UmasPDUReadVariableRequest
             [simple     uint 32        crc]
             [simple     uint 8        variableCount]
-            [array      VariableRequestReference variables count 'variableCount']
+            [array      VariableReadRequestReference variables count 'variableCount']
+        ]
+        ['0x23'      UmasPDUWriteVariableRequest
+            [simple     uint 32        crc]
+            [simple     uint 8        variableCount]
+            [array      VariableWriteRequestReference variables count 'variableCount']
         ]
         ['0x26'     UmasPDUReadUnlocatedVariableNamesRequest
             [simple     uint 16         recordType]
@@ -131,6 +136,9 @@
         ['0xFE', '0x22'     UmasPDUReadVariableResponse
             [array      uint 8          block count 'byteLength - 2']
         ]
+        ['0xFE', '0x23'     UmasPDUWriteVariableResponse
+            [array      uint 8          block count 'byteLength - 2']
+        ]
         ['0xFE', '0x26'     UmasPDUReadUnlocatedVariableResponse
             [array      uint 8          block count 'byteLength - 2']
         ]
@@ -171,7 +179,17 @@
     [array      UmasDatatypeReference         records count 'noOfRecords']
 ]
 
-[type VariableRequestReference
+[type VariableReadRequestReference
+    [simple     uint 4           isArray]
+    [simple     uint 4           dataSizeIndex]
+    [simple     uint 16          block]
+    [const      uint 8           unknown1 0x01]
+    [simple     uint 16          baseOffset]
+    [simple     uint 8           offset]
+    [optional   uint 16          arrayLength 'isArray']
+]
+
+[type VariableWriteRequestReference
     [simple     uint 4           isArray]
     [simple     uint 4           dataSizeIndex]
     [simple     uint 16          block]
@@ -179,6 +197,7 @@
     [simple     uint 16          baseOffset]
     [simple     uint 8           offset]
     [optional   uint 16          arrayLength 'isArray']
+    [array      byte       recordData     length  'isArray == 1 ? dataSizeIndex * arrayLength : dataSizeIndex']
 ]
 
 [type UmasUnlocatedVariableReference