Skip to content

Add S7Comm plugin for Siemens S7 protocol support#70

Closed
thiagoralves wants to merge 12 commits into
mainfrom
feature/s7comm-plugin
Closed

Add S7Comm plugin for Siemens S7 protocol support#70
thiagoralves wants to merge 12 commits into
mainfrom
feature/s7comm-plugin

Conversation

@thiagoralves

Copy link
Copy Markdown
Contributor

Summary

  • Add S7Comm native plugin enabling OpenPLC to communicate using the Siemens S7 protocol
  • Allows S7-compatible HMIs and SCADA systems (WinCC, TIA Portal, etc.) to read/write OpenPLC I/O buffers
  • Built on Snap7 library (embedded, no external dependencies)

Implementation

Phase 1 - Foundation

  • Snap7 library integration (source included for cross-platform builds)
  • Server lifecycle management (init, start, stop, cleanup)
  • Plugin hooks for PLC cycle integration

Phase 2 - Configuration System

  • JSON configuration parser using cJSON library
  • Configurable data blocks, system areas, and PLC identity
  • Support for all OpenPLC buffer types (BOOL, INT, DINT, LINT)

Phase 3/4 - Buffer Management & Integration

  • Double-buffered architecture for thread safety
  • S7 clients run asynchronously from PLC scan cycle
  • Mutex held only during brief memcpy operations (minimal contention)
  • Automatic skip of sync when no clients connected (zero overhead when idle)

Documentation

  • Complete user guide with examples
  • JSON schema reference for Editor developers
  • S7 address mapping documentation

Key Files

  • core/src/drivers/plugins/native/s7comm/ - Plugin source code
  • core/src/drivers/plugins/native/s7comm/snap7/ - Embedded Snap7 library
  • core/src/drivers/plugins/native/s7comm/cjson/ - Embedded cJSON library
  • core/src/drivers/plugins/native/s7comm/docs/ - Documentation
  • install.sh - Updated with native plugin build system

Test plan

  • Builds successfully on amd64, arm64, arm/v7 (CI verified)
  • Manual test with S7 client (python-snap7)
  • Test with WinCC or TIA Portal HMI
  • Verify buffer sync with PLC program

Generated with Claude Code

thiagoralves and others added 12 commits January 12, 2026 17:47
- Add comprehensive implementation plan covering:
  - Analysis of OpenPLC v3 S7Comm/Snap7 implementation
  - Snap7 library API documentation
  - JSON configuration schema design
  - Plugin structure and data structures
  - 7-phase implementation roadmap
  - Testing strategy

- Add user guide with:
  - Configuration reference
  - Example configurations
  - S7 address mapping guide
  - Client connection examples
  - Troubleshooting guide

- Add default s7comm_config.json with standard mappings

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 1 implementation of S7Comm plugin for OpenPLC Runtime v4:

- Include Snap7 library source code (v1.4.3) for self-contained build
- Add plugin source files (s7comm_plugin.cpp/h)
- Add CMakeLists.txt for standalone plugin compilation
- Implement plugin lifecycle: init, start_loop, stop_loop, cleanup
- Implement cycle hooks for buffer synchronization
- Register S7 system areas (PE, PA, MK) and data blocks (DB1, DB2, DB10, DB20, DB100, DB200)
- Handle big-endian conversion for S7 protocol compatibility
- Add event logging for client connections

Data block mapping (Phase 1 - hardcoded):
- DB1: bool_input (%IX)
- DB2: bool_output (%QX)
- DB10: int_input (%IW)
- DB20: int_output (%QW)
- DB100: int_memory (%MW)
- DB200: dint_memory (%MD)

Note: JSON configuration support will be added in Phase 2.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add build_native_plugins() function that automatically scans for native
plugins with CMakeLists.txt and builds them during installation. This
enables Docker images to include pre-built native plugins like s7comm.

The function:
- Scans core/src/drivers/plugins/native/ for CMakeLists.txt files
- Creates isolated build directories for each plugin
- Passes OPENPLC_ROOT to cmake for proper header resolution
- Copies built .so files to build/plugins/
- Provides summary of successful/failed builds

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add full JSON configuration support using embedded cJSON library:

Configuration features:
- Server settings (port, max_clients, timeouts, PDU size)
- PLC identity (name, module_type, serial_number, etc.)
- Dynamic data block allocation with configurable mappings
- System areas (PE, PA, MK) with configurable sizes
- Logging options (connections, data_access, errors)

Implementation changes:
- Add cJSON library (v1.7.18, MIT license) for JSON parsing
- Add s7comm_config.h with configuration structures
- Add s7comm_config.c with parser and validation
- Refactor s7comm_plugin.cpp to use configuration:
  - Dynamic memory allocation for data blocks
  - All server parameters from config
  - Support for all buffer types (bool, int, dint, lint)
  - 64-bit (LINT) support with swap64 endianness conversion
- Update CMakeLists.txt to include new source files

The plugin now reads s7comm_config.json at startup and dynamically
allocates and registers S7 data areas based on configuration.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Refactor buffer synchronization to use double-buffering pattern:
- Add shadow buffers for all S7 areas (system areas + data blocks)
- Add S7 mutex (pthread_mutex_t) to protect S7 buffers during sync
- Implement three-step sync in cycle_end:
  1. Lock mutex, copy S7 -> shadow (capture client writes)
  2. Sync shadow <-> OpenPLC (slow part, no S7 mutex held)
  3. Lock mutex, copy shadow -> S7 (publish new values)
- Remove sync from cycle_start (now no-op)

This allows S7 clients to read/write asynchronously from the main
PLC cycle with minimal mutex contention.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use Srv_GetStatus to check client count at the start of cycle_end.
If no clients are connected, return early without any mutex operations
or buffer copies, reducing overhead when S7 server is idle.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add JSON_SCHEMA.md with complete configuration reference for Editor
- Document all fields, types, constraints, and default values
- Add Editor UI recommendations and validation rules
- Update USER_GUIDE.md with double-buffering architecture section
- Add data flow diagram and related documentation links

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix Srv_GetStatus: use references (int&) not pointers (int*)
- Fix CMakeLists.txt: apply -Wno-class-memaccess only to C++ files
  using COMPILE_LANGUAGE generator expression

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add S7Comm native plugin entry to plugins.conf and plugins_default.conf
so the runtime will recognize and load the S7Comm server when a config
file is provided by the editor.

Plugin configuration format:
- name: s7comm
- path: ./core/src/drivers/plugins/native/s7comm/libs7comm_plugin.so
- enabled: 0 (disabled by default, enabled when config file is present)
- type: 1 (native plugin)
- config_path: ./core/src/drivers/plugins/native/s7comm/s7comm_config.json

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update path to match where the installer places the built library:
core/src/drivers/plugins/native/s7comm/build/plugins/libs7comm_plugin.so

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Srv_GetStatus client count check was incorrectly returning 0
even when clients were connected, causing buffer sync to be skipped.
Remove this optimization to ensure buffer sync always happens.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ication

Change the sync strategy to copy ENTIRE buffers in both directions:
- cycle_start: Copy ENTIRE S7 buffer -> OpenPLC buffer (all types)
- cycle_end: Copy ENTIRE OpenPLC buffer -> S7 buffer (all types)

This allows S7 clients to write to any location (inputs, outputs, memory).
Values actively driven by the PLC program or I/O drivers will naturally
overwrite S7 writes during the scan cycle, but S7 writes to other
locations (e.g., outputs used only as contacts) will persist.

Fixes issue where PLC outputs were being overwritten with zeros from
the S7 buffer.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@thiagoralves thiagoralves deleted the feature/s7comm-plugin branch January 13, 2026 20:12
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