SkillAgentSearch skills...

S7PlcRx

S7PlcRx is a comprehensive, production-ready reactive library for communicating with Siemens S7 PLCs. Built on Reactive Extensions (Rx.NET), it provides real-time data streaming, advanced performance optimizations, enterprise-grade reliability, and comprehensive industrial automation features.

Install / Use

/learn @ChrisPulman/S7PlcRx
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

License Build Nuget NuGet

Alt

<p align="left"> <a href="https://github.com/ChrisPulman/S7PlcRx"> <img alt="S7PlcRx" src="./Images/S7PlcRx.png" width="200"/> </a> </p>

S7PlcRx 🚀

Enterprise-Grade Reactive S7 PLC Communications Library

📖 Introduction

S7PlcRx is a comprehensive, production-ready reactive library for communicating with Siemens S7 PLCs. Built on Reactive Extensions (Rx.NET), it provides real-time data streaming, advanced performance optimizations, enterprise-grade reliability, and comprehensive industrial automation features.

Disclaimer

This project is not affiliated with or endorsed by Siemens AG. It is an independent implementation for educational and industrial use. S7PlcRx is designed to work with Siemens S7 PLCs, including S7-1500, S7-1200, S7-400, S7-300, S7-200, and Logo 0BA8 models. The use of this libarary is at your own risk. The author is not responsible for any damages or losses incurred from using this library in production environments. Ensure that you test thoroughly in a safe environment before deploying to production systems and always follow best practices for industrial automation.

🏭 Why S7PlcRx?

S7PlcRx is designed to meet the demanding requirements of modern industrial automation systems. It combines the power of reactive programming with high-performance optimizations, making it ideal for real-time PLC data monitoring, control, and diagnostics.

✨ Key Features

  • 🔄 Reactive Data Streaming - Real-time PLC data observation using Rx.NET
  • ⚡ High-Performance Optimizations - 5-10x faster with intelligent batching and caching
  • 🏭 Enterprise-Grade Reliability - Circuit breakers, failover, and 99.9% uptime
  • 📊 Advanced Analytics - Performance monitoring and AI-driven optimization
  • 🎯 Symbolic Addressing - CSV/JSON/XML symbol table support
  • 🌐 Multi-PLC Support - High-availability with automatic failover
  • 📈 Production Diagnostics - Comprehensive system health monitoring

🏭 Supported PLC Models

  • S7-1500 (S71500) - Latest generation with advanced features
  • S7-1200 (S71200) - Compact performance PLCs
  • S7-400 (S7400) - High-end automation systems
  • S7-300 (S7300) - Modular automation systems
  • S7-200 (S7200) - Micro automation systems
  • Logo 0BA8 - Logic modules for basic automation

🚀 Quick Start

Installation

S7PlcRx is available on NuGet.

# Package Manager
Install-Package S7PlcRx

# .NET CLI  
dotnet add package S7PlcRx

⚙️ PLC Configuration

Before using S7PlcRx, configure your Siemens PLC:

  1. Enable PUT/GET Communication in PLC settings
  2. Set Data Blocks to Non-Optimized for direct address access
  3. Configure Network Parameters (IP address, subnet)

🔌 Basic Connection

using S7PlcRx;
using S7PlcRx.Enums;
using System.Reactive.Linq;

// Create PLC connection
using var plc = new RxS7(CpuType.S71500, "192.168.1.100", rack: 0, slot: 1);

// Monitor connection status reactively
plc.IsConnected
    .Where(connected => connected)
    .Subscribe(_ => Console.WriteLine("✅ PLC Connected!"));

// Add tags for monitoring
plc.AddUpdateTagItem<float>("Temperature", "DB1.DBD0");
plc.AddUpdateTagItem<bool>("Running", "DB1.DBX4.0");

// Observe real-time data changes
plc.Observe<float>("Temperature")
    .Subscribe(temp => Console.WriteLine($"🌡️ Temperature: {temp:F1}°C"));

plc.Observe<bool>("Running")
    .Subscribe(running => Console.WriteLine($"⚙️ Running: {running}"));

📋 Core Functionality

🏷️ Tag Management

Adding Tags with Different Data Types

// Basic data types
plc.AddUpdateTagItem<bool>("MotorRunning", "DB1.DBX0.0");
plc.AddUpdateTagItem<byte>("Status", "DB1.DBB2");
plc.AddUpdateTagItem<short>("Counter", "DB1.DBW4");
plc.AddUpdateTagItem<int>("ProductCount", "DB1.DBD6");
plc.AddUpdateTagItem<float>("Temperature", "DB1.DBD10");
plc.AddUpdateTagItem<double>("Precision", "DB1.DBD14");

// Array types with specified lengths
plc.AddUpdateTagItem<byte[]>("ByteArray", "DB1.DBB100", length: 64);
plc.AddUpdateTagItem<float[]>("TemperatureArray", "DB1.DBD200", length: 10);

// Chainable tag creation
plc.AddUpdateTagItem<float>("Temp1", "DB1.DBD0")
   .AddUpdateTagItem<float>("Temp2", "DB1.DBD4")
   .AddUpdateTagItem<bool>("Alarm", "DB1.DBX8.0")
   .SetTagPollIng(false); // Disable polling on last tag

Tag Polling Control

// Add tag without automatic polling
var (tag, _) = plc.AddUpdateTagItem<float>("ManualRead", "DB1.DBD0")
                  .SetTagPollIng(false);

// Enable polling later
plc.GetTag("ManualRead").SetTagPollIng(true);

// Disable polling temporarily  
plc.GetTag("ManualRead").SetTagPollIng(false);

Tag Removal

// Remove specific tag
plc.RemoveTagItem("OldTag");

// Check if tag exists
if (plc.TagList.ContainsKey("Temperature"))
{
    var (tag, _) = plc.GetTag("Temperature");
    Console.WriteLine($"Tag found: {tag?.Name}");
}

📖 Reading Data

Reactive Data Observation

// Observe single tag changes
plc.Observe<float>("Temperature")
    .Where(temp => temp > 80.0f)
    .Subscribe(temp => Console.WriteLine($"🚨 High Temperature: {temp:F1}°C"));

// Observe multiple tags with filtering
plc.Observe<bool>("AlarmStatus")
    .Where(alarm => alarm)
    .Subscribe(_ => Console.WriteLine("🔔 ALARM TRIGGERED!"));

// Observe with time-based operations
plc.Observe<float>("Pressure")
    .Sample(TimeSpan.FromSeconds(5)) // Sample every 5 seconds
    .Subscribe(pressure => Console.WriteLine($"📊 Pressure: {pressure:F2} bar"));

// Buffer values for analysis
plc.Observe<float>("FlowRate")
    .Buffer(TimeSpan.FromMinutes(1))
    .Subscribe(values => 
    {
        var avg = values.Average();
        Console.WriteLine($"📈 Average Flow Rate (1min): {avg:F2} L/min");
    });

Manual Reading

// Read single values
var temperature = await plc.Value<float>("Temperature");
var isRunning = await plc.Value<bool>("Running");
var productCount = await plc.Value<int>("ProductCount");

Console.WriteLine($"Current Temperature: {temperature:F1}°C");
Console.WriteLine($"System Running: {isRunning}");
Console.WriteLine($"Products Made: {productCount}");

✏️ Writing Data

Direct Value Writing

// Write different data types
plc.Value("SetPoint", 75.5f);           // Float
plc.Value("Enable", true);              // Boolean  
plc.Value("RecipeNumber", 42);          // Integer
plc.Value("OperatorID", 1234);          // Word

// Write arrays
plc.Value("Recipe", new float[] { 25.0f, 50.0f, 75.0f });
plc.Value("ByteData", new byte[] { 0x01, 0x02, 0x03 });

Conditional Writing

// Write only when connected
plc.IsConnected
    .Where(connected => connected)
    .Subscribe(_ => 
    {
        plc.Value("Heartbeat", DateTime.Now.Ticks);
        plc.Value("SystemReady", true);
    });

📊 System Information

CPU Information

// Get CPU info reactively
plc.GetCpuInfo()
    .Subscribe(info => 
    {
        Console.WriteLine("📟 PLC Information:");
        Console.WriteLine($"  AS Name: {info[0]}");
        Console.WriteLine($"  Module: {info[1]}");
        Console.WriteLine($"  Serial: {info[3]}");
        Console.WriteLine($"  Order Code: {info[5]}");
        Console.WriteLine($"  Version: {info[6]} {info[7]} {info[8]}");
    });

// Get CPU info once
var cpuInfo = await plc.GetCpuInfo().FirstAsync();

🐕 Watchdog Configuration

Keep your PLC connection alive with automatic watchdog functionality:

// Create PLC with watchdog
var plc = new RxS7(
    cpuType: CpuType.S71500,
    ip: "192.168.1.100", 
    rack: 0,
    slot: 1,
    watchDogAddress: "DB100.DBW0",    // Must be DBW address
    interval: 100,                    // Polling interval (ms)
    watchDogValueToWrite: 4500,       // Watchdog value
    watchDogInterval: 10              // Watchdog write interval (seconds)
);

// Configure watchdog display
plc.ShowWatchDogWriting = true; // Show watchdog activity

// Monitor watchdog status
plc.Status
    .Where(status => status.Contains("WatchDog"))
    .Subscribe(status => Console.WriteLine($"🐕 {status}"));

⚡ Performance Optimizations

🚀 Batch Operations

Dramatically improve performance with intelligent batch operations:

using S7PlcRx.Performance;

// Batch reading - up to 10x faster
var tagNames = new[] { "Temp1", "Temp2", "Temp3", "Pressure1", "Flow1" };
var results = await plc.ReadOptimized<float>(tagNames);

foreach (var (tag, value) in results)
{
    Console.WriteLine($"{tag}: {value:F2}");
}

// Batch writing with verification
var writeValues = new Dictionary<string, float>
{
    ["SetPoint1"] = 75.5f,
    ["SetPoint2"] = 80.0f,
    ["SetPoint3"] = 65.0f
};

var config = new WriteOptimizationConfig
{
    EnableParallelWrites = true,
    VerifyWrites = true,
    InterGroupDelayMs = 10
};

var writeResult = await plc.WriteOptimized(writeValues, config);
Console.WriteLine($"✅ {writeResult.SuccessfulWrites.Count} writes completed");

📊 Performance Monitoring

// Monitor real-time performance
plc.MonitorPerformance(TimeSpan.FromSeconds(30))
    .Subscribe(metrics => 
    {
        Console.WriteLine($"📈 Performance Metrics:");
        Console.WriteLine($"  Operations/sec: {metrics.OperationsPerSecond:F1}");
        Console.WriteLine($"  Avg Response: {metrics.AverageResponse

Related Skills

View on GitHub
GitHub Stars21
CategoryDevelopment
Updated23h ago
Forks5

Languages

C#

Security Score

95/100

Audited on Mar 23, 2026

No findings