CeriL2Lib 1.26.7.8
See the version list below for details.
dotnet add package CeriL2Lib --version 1.26.7.8
NuGet\Install-Package CeriL2Lib -Version 1.26.7.8
<PackageReference Include="CeriL2Lib" Version="1.26.7.8" />
<PackageVersion Include="CeriL2Lib" Version="1.26.7.8" />
<PackageReference Include="CeriL2Lib" />
paket add CeriL2Lib --version 1.26.7.8
#r "nuget: CeriL2Lib, 1.26.7.8"
#:package CeriL2Lib@1.26.7.8
#addin nuget:?package=CeriL2Lib&version=1.26.7.8
#tool nuget:?package=CeriL2Lib&version=1.26.7.8
CeriL2Lib 使用说明书
1. 概述
CeriL2Lib 是一个面向工业应用的 .NET 8.0 类库,专门用于简化工业数据采集、通讯处理和事件生成的工作。该库的主要目标是将开发者从繁琐的通讯底层实现和数据处理中解放出来,使其能够专注于业务逻辑的实现。
1.1 设计目标
在工业应用开发中,处理各种通讯协议(如西门子S7、Modbus、OPC UA等)以及根据信号生成相应事件需要消耗大量的开发时间。CeriL2Lib 的设计初衷就是解决这些问题:
- 简化通讯处理:支持多种工业通讯协议,开发者无需关心底层实现细节
- 事件驱动架构:内置事件总线,支持 PU(上升沿)、DO(下降沿)、OverLimitPU(超限上升)、OverLimitDO(超限下降)等事件触发
- 数据按需存储:可选地将数据存储到时序数据库(TDengine),便于后续分析和问题排查
- 内置服务组件:集成 MQTT 服务器、OPC UA 服务器等工业常用服务
- 完善的授权管理:支持基于硬件ID的授权验证,保护知识产权
1.2 核心特性
- 多协议支持:支持西门子 S7、Modbus、OPC UA、TCP Socket、双工 Socket 等工业通讯协议
- 事件机制:提供 PU(上升沿)、DO(下降沿)、AVG(平均值计算)、变量变化检测、超限检测(OverLimitPU/OverLimitDO)等事件
- 时序数据库集成:内置 TDengine 支持,可将采集的数据和事件自动存储
- MQTT 服务器:内置轻量级 MQTT 代理服务,支持多用户权限管理
- OPC UA 服务器:可将采集的数据通过 OPC UA 协议对外提供服务
- 事件持久化:支持将事件存储到 TDengine,并支持分区和保留策略
- 事件分发:支持 EventBus(本地)和 RabbitMQ(跨进程)两种分发方式
- 许可证管理:基于硬件ID的授权验证,支持授权请求生成和验证
- 配置数据库:支持通过数据库动态管理配置(可选)
- 变量监控:提供网页端变量监控 Dashboard,支持页面修改变量值,用于调试
- 日志系统:支持分级日志记录,可配置不同级别的日志输出
2. 项目结构
CeriL2Lib 是一个独立的类库项目,包含以下主要组件:
| 组件 | 说明 |
|---|---|
| CeriL2Lib | 核心类库,包含所有通讯、数据处理和事件管理功能 |
3. 快速开始
3.1 环境要求
- .NET 8.0 或更高版本
- TDengine 3.x 时序数据库(可选,用于数据和事件存储)
- RabbitMQ 3.8+(可选,用于跨进程事件分发)
3.2 安装配置
在 ASP.NET Core 项目中安装 CeriL2Lib 并进行配置:
// Program.cs
using CeriL2Lib;
using CeriL2Lib.Dashboard;
var builder = WebApplication.CreateBuilder(args);
// 清除 .NET 内置日志提供程序(避免与 Serilog 控制台输出重复)
builder.Logging.ClearProviders();
// 注册 Serilog,并从 appsettings.json 读取配置
// 这里不需要 writeToProviders,因为我们通过 AttachToSerilog() 直接将 MemoryLogSink 注入 Serilog 管道
builder.Host.UseSerilog((context, services, configuration) =>
{
configuration.ReadFrom.Configuration(context.Configuration)
.Enrich.FromLogContext();
});
builder.Services.AddCeriL2Toolkit(builder.Configuration);
builder.AddCeriDashboard();
var app = builder.Build();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
// 注册 Dashboard 路由到主管道(含 CORS 和 AllowRemoteAccess 控制)
app.MapCeriDashboard();
app.Run();
3.3 配置文件
在 appsettings.json 中配置 CeriL2Lib:
{
"Dashboard": {
"PathMatch": "/ceridashboard",
"AllowRemoteAccess": false,
"StatsRefreshInterval": 3000
},
"Tsdb": {
"Enabled": false,
"Host": "localhost",
"Port": 6041,
"Username": "root",
"Password": "taosdata",
"Database": "l2",
"UseSSL": false
},
"Features": {
"SimRun": false
},
"DataFiles": [ "CeriPcsData.dll", "UaDataTest.dll" ]
}
重要配置说明:
- Tsdb.Enabled: 必须设置为 true 才能启用数据存储
- EventDispatch.Provider: "EventBus" 或 "RabbitMQ"
- EventDispatch.EventDelayWarningThresholdMs: 事件处理延迟报警阈值(毫秒),超过此值将输出警告日志,默认 5000ms
- DataFiles: 包含数据类定义的 DLL 程序集列表
4. 数据类定义
CeriL2Lib 使用特性(Attribute)来定义数据类与通讯变量的映射关系。以下是各种协议的数据类定义方式。
4.1 西门子 S7 数据类
using CeriL2Lib;
using System;
[MonitorStatic]
[SaveToRtdb]
[S7Config("192.168.1.100", 0, 1, DataDirection.Read, 1000)] // IP, Rack, Slot, Direction, 刷新间隔(毫秒)
public class MyS7Data
{
// 整型变量:DB块号, 起始地址, 位偏移, 数据类型
[S7ItemConfig(1, 0, 0, S7DataType.S7Int)]
public static int IntValue1 = 0;
[S7ItemConfig(1, 2, 0, S7DataType.S7Int)]
public static int IntValue2 = 0;
// 位变量(Bool)- 带沿检测
[PU(DurationMs = 500)] // 上升沿检测,DurationMs 为滤波时间(毫秒)
[DO(DurationMs = 500)] // 下降沿检测
[S7ItemConfig(1, 10, 0, S7DataType.S7Bit)]
public static bool BitValue1 = false;
// 浮点型变量
[S7ItemConfig(1, 12, 0, S7DataType.S7Real)]
public static float FloatValue = 0.0f;
// 双精度浮点型
[S7ItemConfig(1, 16, 0, S7DataType.S7LReal)]
public static double DoubleValue = 0.0;
// 字符串(需要指定长度)
[S7ItemConfig(1, 24, 0, S7DataType.S7String, "", 30)]
public static string StringValue = string.Empty;
// 字节数组
[S7ItemConfig(1, 54, 0, S7DataType.S7Byte, "", 10)]
public static byte[] ByteArray = new byte[10];
}
4.2 S7Config 特性参数说明
| 参数 | 说明 | 默认值 |
|---|---|---|
| IP | PLC IP 地址 | 127.0.0.1 |
| Rack | PLC Rack 编号 | 0 |
| Slot | PLC Slot 编号 | 1 |
| Direction | 数据方向,DataDirection.Read(读取)或 DataDirection.Write(写入) | DataDirection.Read |
| RefreshInterval | 刷新间隔(毫秒),最小 10ms | 1000 |
4.3 S7ItemConfig 特性参数说明
| 参数 | 说明 | 默认值 |
|---|---|---|
| DB | DB 块编号 | 必填 |
| Offset | 起始地址(字节) | 必填 |
| Bit | 位偏移(0-7) | 0 |
| S7DataType | 数据类型 | 必填 |
| Comments | 说明文字 | 空字符串 |
| Length | 字符串或数组长度 | 0 |
4.4 OPC UA 数据类
using CeriL2Lib;
using System;
[MonitorStatic]
[SaveToRtdb]
[UaServerConfig("opc.tcp://192.168.1.100:49320", 1000)] // 服务器地址, 刷新间隔
public class MyUaData
{
// 整型变量
[UaItemConfig("ns=2;s=Machine1.Temperature")]
public static int Temperature = 0;
// 浮点型变量
[UaItemConfig("ns=2;s=Machine1.Pressure")]
public static float Pressure = 0.0f;
// 布尔变量(带沿检测)
[PU(DurationMs = 500)]
[DO(DurationMs = 500)]
[UaItemConfig("ns=2;s=Machine1.Status")]
public static bool Status = false;
// 字符串变量
[UaItemConfig("ns=2;s=Machine1.Name")]
public static string Name = string.Empty;
// 时间戳
[UaItemConfig("ns=2;s=_System._DateTime")]
public static DateTime UpdateTime;
}
4.5 Modbus 数据类
using CeriL2Lib;
[MonitorStatic]
[SaveToRtdb]
[ModbusConfig("192.168.1.100", 502, 1, DataDirection.Read, 1000)] // IP, 端口, 从站地址, Direction, 刷新间隔
public class MyModbusData
{
// 保持寄存器(读取)
[ModbusItemConfig(3, 0, ModbusDataType.Int16)] // 功能码3, 起始地址, 数据类型
public static int HoldingRegister1 = 0;
// 输入寄存器
[ModbusItemConfig(4, 0, ModbusDataType.Int16)]
public static int InputRegister1 = 0;
// 线圈(读写)- 带沿检测
[PU(DurationMs = 500)]
[DO(DurationMs = 500)]
[ModbusItemConfig(1, 0, ModbusDataType.Bool)]
public static bool Coil1 = false;
// 输入离散量
[ModbusItemConfig(2, 0, ModbusDataType.Bool)]
public static bool DiscreteInput1 = false;
}
4.6 ModbusConfig 特性参数说明
| 参数 | 说明 | 默认值 |
|---|---|---|
| IP | Modbus 设备 IP 地址 | 必填 |
| Port | 端口号 | 502 |
| SlaveId | 从站地址 | 必填 |
| Direction | 数据方向,DataDirection.Read(读取)或 DataDirection.Write(写入) | DataDirection.Read |
| RefreshInterval | 刷新间隔(毫秒) | 1000 |
4.7 TCP Socket 数据类
using CeriL2Lib;
[MonitorStatic]
[SaveToRtdb]
[PLCSocketConfig(CommunicationMode.Client, 100, "", 0, "192.168.1.100", 8000)] // Mode, Length, LocalIP, LocalPort, RemoteIP, RemotePort
public class MySocketData
{
[PLCItemConfig(0, 4, PLCDataType.Int)]
public static int Value1 = 0;
[PLCItemConfig(4, 4, PLCDataType.Float)]
public static float Value2 = 0.0f;
}
4.8 PLCSocketConfig 特性参数说明
| 参数 | 说明 | 默认值 |
|---|---|---|
| Mode | 通讯模式,Server 或 Client | CommunicationMode.Server |
| Length | 报文总长度 | 必填 |
| LocalIP | 本地监听 IP(Server 模式) | 127.0.0.1 |
| LocalPort | 本地监听端口(Server 模式) | 1001 |
| RemoteIP | 远程设备 IP(Client 模式) | 必填 |
| RemotePort | 远程设备端口(Client 模式) | 必填 |
5. 事件机制
CeriL2Lib 提供了完善的事件机制,用于响应数据变化和状态改变。
5.1 事件总线
事件总线(EventBus)是 CeriL2Lib 的核心组件,提供发布/订阅功能:
// 取消订阅
EventBus.Unsubscribe("Area1", ProcessorMethod);
// 发布到指定区域(当启用多区域时)
EventBus.PublishMessage("Area1", eventArgs);
5.2 上升沿事件(PU)
当布尔变量从 false 变为 true 时触发:
[MonitorStatic]
// 轧钢产线
public class RollLine
{
[PU(Area = "RollLine",DurationMs = 1000, ReverseDurationMs = 1000)]
[DO(Area = "RollLine", DurationMs = 1000, ReverseDurationMs = 1000)]
[S7ItemConfig(1, 0, 0, S7DataType.S7Bit, "1#轧机正在轧制")]
public static bool IsRunning1 = false;
[PU(Area = "RollLine", DurationMs = 1000, ReverseDurationMs = 1000)]
[DO(Area = "RollLine", DurationMs = 1000, ReverseDurationMs = 1000)]
[S7ItemConfig(1, 1, 0, S7DataType.S7Bit, "2#轧机正在轧制")]
public static bool IsRunning2 = false;
}
public class MyEventHandler : ThreadDB
{
protected override async Task TaskRunAsync()
{
EventBus.Subscribe("Area1", OnPUEvent);
await base.TaskRunAsync();
}
private void OnPUEvent(object sender, object message)
{
PUEventArgs e = message as PUEventArgs;
Console.WriteLine($"上升沿事件: {e.TrigerField}");
// 业务逻辑处理
// ...
}
}
5.3 下降沿事件(DO)
当布尔变量从 true 变为 false 时触发:
EventBus.Subscribe("Area1", OnDOEvent);
private void OnDOEvent(object sender, object message)
{
DOEventArgs e = message as DOEventArgs;
Console.WriteLine($"下降沿事件: {e.TrigerField}");
}
5.4 平均值计算事件(AVG)
根据触发条件计算变量平均值:
public class MyData
{
// 定义平均值计算:TriggerField 为触发字段,AvgTime 为平均时间(毫秒)
[Avg("TriggerBit", AvgTime = 5000, DelayTime = 1000, IsPUTrigger = true)]
public static float Temperature = 0.0f;
[PU(DurationMs = 500)]
[DO(DurationMs = 500)]
public static bool TriggerBit = false;
}
// 订阅平均值事件
EventBus.Instance.Subscribe(SysConsts.AVG, OnAvgEvent);
private void OnAvgEvent(object sender, object message)
{
AvgEventArgs e = message as AvgEventArgs;
Console.WriteLine($"平均值计算完成: {e.ValueField} = {e.AvgValue}");
Console.WriteLine($"计算时间: {e.StartTime} - {e.EndTime}");
}
5.5 变量变化事件(VarChange)
检测变量值变化并触发事件:
// 需要在数据类上添加 VarChange 特性
[MonitorStatic]
[VarChange("Temperature", 0.5f)] // 字段名, 变化阈值
public class MyData
{
public static float Temperature = 0.0f;
}
// 订阅变量变化事件
EventBus.Subscribe("Area1", OnVarChangeEvent);
5.6 超限事件(OverLimitPU / OverLimitDO)
超限事件通过数值阈值来检测状态,适用于工业场景中的温度、压力、液位等模拟量监测。
5.6.1 OverLimitPU(超限上升)
当数值超过阈值持续一定时间后触发,适用于"有钢"、"有料"等场景:
public class PyrometerData
{
// 温度超过 800°C 持续 2 秒后触发有钢事件
[OverLimitPU(Threshold = 800, DurationMs = 2000, ReverseDurationMs = 1000, Area = "Furnace")]
public static double Temperature1 = 0.0;
// 温度超过 850°C 持续 3 秒后触发有钢事件
[OverLimitPU(Threshold = 850, DurationMs = 3000, Area = "Furnace")]
public static double Temperature2 = 0.0;
}
5.6.2 OverLimitDO(超限下降)
当数值低于阈值持续一定时间后触发,适用于"失钢"、"缺料"等场景:
public class PyrometerData
{
// 温度低于 200°C 持续 3 秒后触发失钢事件
[OverLimitDO(Threshold = 200, DurationMs = 3000, ReverseDurationMs = 1000, Area = "Furnace")]
public static double Temperature = 0.0;
}
5.6.3 特性参数说明
| 参数 | 说明 | 默认值 |
|---|---|---|
| Threshold | 阈值(double 类型) | 必填 |
| DurationMs | 触发滤波时间(毫秒),数值持续超过/低于阈值达到此时间后才触发事件 | 1000 |
| ReverseDurationMs | 反向滤波时间(毫秒),用于防止频繁重复触发 | 0 |
| Area | 事件区域,用于事件分发和筛选 | 空字符串 |
5.6.4 工作原理
- 正常状态:数值在阈值范围内,不触发事件
- 超限状态:数值超过/低于阈值,开始计时
- 持续判断:如果超限状态持续达到
DurationMs,则触发事件 - 反向保护:触发后,如果数值恢复到正常范围,需要持续
ReverseDurationMs才能重新开始计时 - 重新触发:数值再次超限并持续达到
DurationMs后,可以再次触发事件
5.6.5 事件订阅示例
// 订阅超限上升事件(有钢)
EventBus.Subscribe(SysConsts.OVER_LIMIT_PU, OnOverLimitPUEvent);
// 订阅超限下降事件(失钢)
EventBus.Subscribe(SysConsts.OVER_LIMIT_DO, OnOverLimitDOEvent);
private void OnOverLimitPUEvent(object sender, object message)
{
var e = message as OverLimitPUEventArgs;
Console.WriteLine($"有钢事件: {e.TrigerField}, 区域: {e.Area}, 当前值: {e.CurrentValue}, 阈值: {e.Threshold}");
}
private void OnOverLimitDOEvent(object sender, object message)
{
var e = message as OverLimitDOEventArgs;
Console.WriteLine($"失钢事件: {e.TrigerField}, 区域: {e.Area}, 当前值: {e.CurrentValue}, 阈值: {e.Threshold}");
}
5.6.6 事件数据
OverLimitPUEventArgs 和 OverLimitDOEventArgs 包含以下属性:
| 属性 | 说明 |
|---|---|
| TrigerField | 触发的字段名 |
| Area | 事件区域 |
| Threshold | 阈值 |
| CurrentValue | 触发时的当前值 |
| EventTime | 事件时间 |
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- libplctag (>= 1.5.2)
- MQTTnet (>= 5.1.0.1559)
- MQTTnet.Server (>= 5.1.0.1559)
- NModbus (>= 3.0.83)
- OPCFoundation.NetStandard.Opc.Ua (>= 1.5.378.134)
- RabbitMQ.Client (>= 6.8.1)
- Serilog (>= 4.3.1)
- Serilog.Extensions.Hosting (>= 10.0.0)
- Serilog.Sinks.Console (>= 6.1.1)
- Serilog.Sinks.File (>= 7.0.0)
- SqlSugarCore (>= 5.1.4.187)
- System.IO.Ports (>= 10.0.7)
- System.Management (>= 10.0.7)
- TDengine.Connector (>= 3.2.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated | |
|---|---|---|---|
| 1.26.7.2801 | 77 | 7/28/2026 | |
| 1.26.7.2800 | 79 | 7/28/2026 | |
| 1.26.7.1701 | 91 | 7/17/2026 | |
| 1.26.7.1700 | 84 | 7/17/2026 | |
| 1.26.7.1600 | 86 | 7/16/2026 | |
| 1.26.7.1102 | 98 | 7/10/2026 | |
| 1.26.7.15 | 88 | 7/15/2026 | |
| 1.26.7.11 | 96 | 7/10/2026 | |
| 1.26.7.10 | 92 | 7/10/2026 | |
| 1.26.7.8 | 94 | 7/8/2026 | |
| 1.26.6.8 | 118 | 6/8/2026 | |
| 1.26.6.3 | 106 | 6/3/2026 | |
| 1.0.0 | 136 | 5/28/2026 |