Skip to content

feat: Add centralized IEC 61131-3 type conversion layer#96

Closed
marconetsf wants to merge 1 commit into
developmentfrom
feature/iec-type-converter-common-layer
Closed

feat: Add centralized IEC 61131-3 type conversion layer#96
marconetsf wants to merge 1 commit into
developmentfrom
feature/iec-type-converter-common-layer

Conversation

@marconetsf
Copy link
Copy Markdown
Contributor

Summary

This PR introduces a centralized type conversion infrastructure for all plugins, addressing the issue of duplicated type conversion code across OPC-UA, Modbus, S7Comm, and future plugins (EtherCAT, etc.).

New modules added to core/src/drivers/plugins/python/shared/:

iec_type_registry.py - Centralized registry of all 22 IEC 61131-3 types:

  • Complete metadata for each type (bounds, size, ctypes class, signedness, register count)
  • Alias resolution (INT32 -> DINT, FLOAT -> REAL, etc.)
  • Type category sets (INTEGER_TYPES, FLOAT_TYPES, TIME_TYPES, etc.)
  • Size code mapping (X, B, W, D, L)

iec_type_converter.py - Unified conversion utilities:

  • Value clamping with proper signed/unsigned handling
  • Float <-> integer bit representation (REAL/LREAL storage)
  • Modbus register combination/splitting with big/little endian support
  • IEC_TIMESPEC conversions for TIME/DATE/TOD/DT types
  • Default value generation per protocol
  • Endianness swapping utilities

Benefits

  • Eliminates ~500+ lines of duplicated code across plugins
  • Ensures consistency - all plugins use the same conversion logic
  • Simplifies maintenance - fix bugs in one place
  • Easier to extend - adding new types requires changes in one location
  • Well tested - 193 unit tests covering all edge cases

Usage example

from shared.iec_type_converter import IECTypeConverter
from shared.iec_type_registry import get_type_info

# Clamp value to type bounds
value = IECTypeConverter.clamp_to_type(1000, "SINT")  # Returns 127

# Convert float to integer representation for storage
int_repr = IECTypeConverter.float_to_int_repr(3.14, "REAL")

# Combine Modbus registers into value
value = IECTypeConverter.registers_to_value([0x1234, 0x5678], "DINT", big_endian=True)

# Get type metadata
info = get_type_info("DINT")
print(f"DINT: {info.size_bytes} bytes, range [{info.min_value}, {info.max_value}]")

Test plan

  • All 193 new unit tests pass
  • Pre-commit hooks pass (pylint, ruff, black, isort)
  • Manual integration testing with existing plugins (follow-up PR will refactor plugins to use this)

This is the foundation layer. A follow-up PR will refactor existing plugins (OPC-UA, Modbus) to use these shared utilities.

Generated with Claude Code

This commit introduces a common type conversion infrastructure for all plugins:

- iec_type_registry.py: Centralized registry of all 22 IEC 61131-3 types
  with metadata (bounds, size, ctypes class, register count, etc.)
- iec_type_converter.py: Unified conversion utilities including:
  - Value clamping with signed/unsigned handling
  - Float <-> integer bit representation conversion
  - Modbus register combination/splitting with endianness support
  - IEC_TIMESPEC time type conversions
  - Default value generation per protocol

This eliminates type conversion duplication across plugins (OPC-UA, Modbus,
S7Comm, etc.) and ensures consistent type handling throughout the system.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@marconetsf marconetsf closed this Feb 26, 2026
@thiagoralves thiagoralves deleted the feature/iec-type-converter-common-layer branch April 23, 2026 16:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant