https://github.com/philipp2604/variablevaluemonitor
A flexible, type-safe C# library for monitoring variable values with configurable alarms, thresholds, and custom conditions.
https://github.com/philipp2604/variablevaluemonitor
alarms alerts conditions industrial-automation monitoring
Last synced: about 2 months ago
JSON representation
A flexible, type-safe C# library for monitoring variable values with configurable alarms, thresholds, and custom conditions.
- Host: GitHub
- URL: https://github.com/philipp2604/variablevaluemonitor
- Owner: philipp2604
- License: mit
- Created: 2025-07-17T08:23:35.000Z (3 months ago)
- Default Branch: master
- Last Pushed: 2025-07-22T08:11:41.000Z (3 months ago)
- Last Synced: 2025-07-25T11:59:33.367Z (3 months ago)
- Topics: alarms, alerts, conditions, industrial-automation, monitoring
- Language: C#
- Homepage:
- Size: 82 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# VariableValueMonitor 🚨
A flexible, modern .NET library for monitoring variable values and triggering alarms based on a rich set of configurable conditions. It's designed to be a lightweight, type-safe, and thread-safe core for any application that needs to react to state changes, such as in industrial automation, IoT, or system monitoring.[](https://github.com/philipp2604/VariableValueMonitor/actions/workflows/dotnet-8-build-and-test.yml)
[](https://github.com/philipp2604/VariableValueMonitor/actions/workflows/dotnet-9-build-and-test.yml)
[](https://docs.microsoft.com/en-us/dotnet/csharp/)
[](https://opensource.org/licenses/MIT)
[](https://github.com/philipp2604/VariableValueMonitor/issues)
[](https://www.nuget.org/packages/philipp2604.VariableValueMonitor)
[](https://deepwiki.com/philipp2604/VariableValueMonitor)## ✨ Key Features
- **✅ Flexible Condition Engine**: Define alarms using five powerful, type-safe condition types:
- **Thresholds**: Trigger alarms when a numeric value goes above or below a set point (e.g., `temperature > 80.0`).
- **Predicates**: Use custom logic (`Predicate`) for complex state validation (e.g., `status == "Error"`, `isEmergencyStop == true`).
- **Value Changes**: React to the *dynamics* of a variable by comparing its old and new values (e.g., `newValue > oldValue`, `Math.Abs(newValue - oldValue) > 10.0`).
- **Delayed Conditions**: Wrap any condition to only trigger alarms if the condition remains active for a specified duration (e.g., prevent nuisance alarms from brief spikes).
- **Hysteresis Thresholds**: Use separate trigger and clear thresholds to prevent oscillating alarms (e.g., trigger at 85°C, clear at 75°C).
- **🔧 Fluent Condition Builders**: Use the static `CommonConditions` class for a clean, readable way to create common alarm logic like `OnTrue()`, `OnValueJump()`, `OnStringEquals()`, `WithDelay()`, and `OnHighValueHysteresis()`.
- **⏰ Time-Based Features**: Advanced timing capabilities including delayed conditions for filtering transient spikes and hysteresis conditions for stable alarm behavior.
- **🔔 Event-Driven Alarms**: Subscribe to `AlarmTriggered` and `AlarmCleared` events to seamlessly integrate alarm logic into your application's workflow.
- **🚀 Type-Safe & Generic**: Monitor any `IComparable` or `IEquatable` type, from primitives (`int`, `double`, `bool`) and `enums` to your own custom `record` or `class` types.
- **🎛️ Stateful Alarm Management**: The monitor tracks the state of all active alarms, preventing duplicate triggers and providing `Acknowledge` functionality.
- **⚡️ Thread-Safe by Design**: Built with `ConcurrentDictionary` to ensure that registering variables and notifying value changes is safe across multiple threads.
- **🏗️ Lightweight & Modern**: A focused library with a minimal footprint, written in modern C# with clear, testable components.## 🏛️ Architecture
The library is designed with a clear separation of concerns, making it easy to understand and extend.
- **The Monitor (`ValueMonitor`)**: The central engine and public API. It manages variable registrations, state, timing infrastructure, and orchestrates condition checking and event firing.
- **Conditions**: Five types of declarative, type-safe "rules" that you define:
- `ThresholdCondition`: Numeric threshold comparisons
- `PredicateCondition`: Custom predicate logic
- `ValueChangeCondition`: Old vs new value comparisons
- `DelayedCondition`: Wraps any condition with a time delay
- `HysteresisThresholdCondition`: Separate trigger and clear thresholds
- **Common Conditions (`CommonConditions`)**: A static helper class that acts as a factory for creating the most frequently used conditions, including time-based helpers like `WithDelay()` and `OnHighValueHysteresis()`.
- **Timing Infrastructure (`ITimerProvider`, `TimerProvider`, `ConditionTimer`)**: Manages time-based condition logic with testable abstractions.
- **Events (`AlarmEventArgs`, `ValueChangedEventArgs`)**: The primary output mechanism. These classes carry all the context about an alarm or value change to your event handlers.
- **Data Models (`ActiveAlarm`, `VariableRegistration`)**: Internal and public records/classes that represent the state of monitored variables and active alarms.As an end-user, you will primarily interact with the `ValueMonitor` class and define your logic using the various `Condition` types.
## 🚀 Getting Started
### Installation
VariableValueMonitor will be available on NuGet. You can install it using the .NET CLI:
```bash
dotnet add package philipp2604.VariableValueMonitor
```Or via the NuGet Package Manager in Visual Studio.
### Quick Start
Here's a practical example demonstrating how to monitor multiple variables with different types of conditions.
```csharp
using VariableValueMonitor.Alarms.Conditions;
using VariableValueMonitor.Enums;
using VariableValueMonitor.Events;
using VariableValueMonitor.Monitor;// 1. Initialize the ValueMonitor
var monitor = new ValueMonitor();// 2. Subscribe to the alarm events
monitor.AlarmTriggered += OnAlarmTriggered;
monitor.AlarmCleared += OnAlarmCleared;Console.WriteLine("--- Registering Variables for Monitoring ---");
// 3. Register variables with various conditions
// A temperature sensor with a high-temperature warning
monitor.RegisterVariable("temp_sensor_1", "Main Boiler Temperature", 25.0,
new ThresholdCondition(AlarmType.Warning, AlarmDirection.UpperBound, 85.0, "High temperature detected!"));// An emergency stop button (boolean)
monitor.RegisterVariable("emergency_stop_1", "Main Conveyor E-Stop", false,
CommonConditions.OnTrue(AlarmType.Alarm, "Emergency stop has been activated!"));// A pressure sensor that alarms on a sudden jump
monitor.RegisterVariable("pressure_sensor_1", "Hydraulic Pressure", 120.0,
CommonConditions.OnValueJump(AlarmType.Info, 20.0, "Rapid pressure change detected."));// A machine state monitor using enums
monitor.RegisterVariable("machine_1", "CNC Machine State", MachineState.Running,
[CommonConditions.OnEnumEquals(AlarmType.Alarm, MachineState.Error, "Machine has entered an error state!")]);
monitor.RegisterVariable("machine_1", "CNC Machine State", MachineState.Running,
[CommonConditions.OnEnumChange(AlarmType.Info, MachineState.Running, MachineState.Maintenance, "Machine is now under maintenance.")]);// A delayed condition - only triggers after temperature is high for 30 seconds
monitor.RegisterVariable("temp_delayed", "Oven Temperature", 60.0,
CommonConditions.OnHighValueDelayed(200.0, TimeSpan.FromSeconds(30), "Sustained high temperature detected!"));// A hysteresis condition - triggers at 85°C, clears at 75°C
monitor.RegisterVariable("temp_hysteresis", "Reactor Temperature", 70.0,
CommonConditions.OnHighValueHysteresis(85.0, 75.0, "Reactor temperature alarm"));Console.WriteLine("--- Simulating Value Changes ---\n");
// 4. Notify the monitor of new values
monitor.NotifyValueChanged("temp_sensor_1", 90.0); // Triggers "High temperature"
monitor.NotifyValueChanged("pressure_sensor_1", 155.5); // Triggers "Rapid pressure change"
monitor.NotifyValueChanged("emergency_stop_1", true); // Triggers "E-Stop activated"
monitor.NotifyValueChanged("machine_1", MachineState.Error); // Triggers "Error state"// Demonstrate hysteresis behavior
monitor.NotifyValueChanged("temp_hysteresis", 90.0); // Triggers at 85°C threshold
monitor.NotifyValueChanged("temp_hysteresis", 80.0); // Stays active (above 75°C clear threshold)
monitor.NotifyValueChanged("temp_hysteresis", 74.0); // Clears at 75°C threshold// Demonstrate delayed condition (would need to wait 30 seconds for actual trigger)
monitor.NotifyValueChanged("temp_delayed", 220.0); // Starts delay timer, no immediate alarmmonitor.NotifyValueChanged("temp_sensor_1", 80.0); // Clears the temperature alarm
Console.WriteLine($"\n--- Final State ---");
Console.WriteLine($"There are {monitor.GetActiveAlarms().Count} active alarms.");// Clean up event handlers
monitor.AlarmTriggered -= OnAlarmTriggered;
monitor.AlarmCleared -= OnAlarmCleared;// --- Event Handlers ---
void OnAlarmTriggered(object? sender, AlarmEventArgs e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"ALARM TRIGGERED for '{e.VariableName}' ({e.VariableId})");
Console.WriteLine($" - Type: {e.AlarmType}, Message: {e.Message}");
Console.WriteLine($" - Value changed from '{e.PreviousValue}' to '{e.CurrentValue}'");
Console.ResetColor();
}void OnAlarmCleared(object? sender, AlarmEventArgs e)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"ALARM CLEARED for '{e.VariableName}' ({e.VariableId})");
Console.WriteLine($" - Message: {e.Message}");
Console.WriteLine($" - Current value is now '{e.CurrentValue}'");
Console.ResetColor();
}public enum MachineState { Stopped, Running, Maintenance, Error }
```
## ⏰ Time-Based Features
### Delayed Conditions
Delayed conditions wrap existing conditions and only trigger alarms after the condition has been active for a specified duration. This prevents nuisance alarms from brief spikes or transient conditions.
```csharp
// Only trigger after temperature exceeds 85°C for 5 seconds
var delayedCondition = CommonConditions.OnHighValueDelayed(85.0, TimeSpan.FromSeconds(5), "Sustained high temperature");
monitor.RegisterVariable("temp_sensor", "Temperature", 70.0, delayedCondition);// You can wrap any condition type with a delay
var delayedPredicate = CommonConditions.WithDelay(
CommonConditions.OnTrue(AlarmType.Alarm, "Emergency stop activated"),
TimeSpan.FromSeconds(2));
monitor.RegisterVariable("e_stop", "Emergency Stop", false, delayedPredicate);
```### Hysteresis Thresholds
Hysteresis conditions use separate trigger and clear thresholds to prevent oscillating alarms around a single threshold value.
```csharp
// Trigger alarm at 85°C, but don't clear until temperature drops to 75°C
var hysteresisCondition = CommonConditions.OnHighValueHysteresis(85.0, 75.0, "High temperature with hysteresis");
monitor.RegisterVariable("temp_sensor", "Temperature", 70.0, hysteresisCondition);// Sequence of events:
monitor.NotifyValueChanged("temp_sensor", 90.0); // Alarm triggered (>= 85°C)
monitor.NotifyValueChanged("temp_sensor", 82.0); // Alarm stays active (> 75°C clear threshold)
monitor.NotifyValueChanged("temp_sensor", 74.0); // Alarm cleared (<= 75°C)
```### Custom Timer Provider
For testing or specialized timing needs, you can provide your own timer implementation:
```csharp
// Use custom timer provider (useful for unit testing)
var customTimerProvider = new MyCustomTimerProvider();
var monitor = new ValueMonitor(customTimerProvider);
```## 📖 Documentation
- **[ValueMonitor API Reference](./src/VariableValueMonitor/Monitor/IValueMonitor.cs)**: The `ValueMonitor` interface is the primary entry point for all operations. Its public methods define the library's capabilities.
- **[Common Conditions Reference](./src/VariableValueMonitor/Alarms/Conditions/CommonConditions.cs)**: Explore this static class to see the available pre-built condition helpers, including time-based features.
- **[Time-Based Conditions](./tests/VariableValueMonitor.Tests/Unit/Monitor/TimeBasedConditionTests.cs)**: Examples and tests for delayed conditions and hysteresis thresholds.
- **[Unit Tests](./tests/VariableValueMonitor.Tests/Unit/Monitor/ValueMonitorUnitTests.cs)**: The unit tests provide comprehensive, focused examples for every feature and condition type.
- **[Integration Tests](./tests/VariableValueMonitor.Tests/Integration/Monitor/ValueMonitorIntegrationTests.cs)**: These tests showcase how to handle more complex, multi-alarm scenarios.## 🤝 Contributing
Contributions are welcome! Whether it's bug reports, feature requests, or pull requests, your help is appreciated.
1. **Fork** the repository.
2. Create a new **branch** for your feature or bug fix.
3. Make your changes.
4. Add or update **unit/integration tests** to cover your changes.
5. Submit a **Pull Request** with a clear description of your changes.Please open an issue first to discuss any major changes.
## ⚖️ License
This project is licensed under the **MIT License**. This is a permissive license that allows for reuse in both open-source and proprietary software. You are free to use, modify, and distribute this library as you see fit. See the [LICENSE](./LICENSE.txt) file for full details.