S7Sharp.Watch
1.1.2
dotnet add package S7Sharp.Watch --version 1.1.2
NuGet\Install-Package S7Sharp.Watch -Version 1.1.2
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="S7Sharp.Watch" Version="1.1.2" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="S7Sharp.Watch" Version="1.1.2" />
<PackageReference Include="S7Sharp.Watch" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add S7Sharp.Watch --version 1.1.2
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: S7Sharp.Watch, 1.1.2"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package S7Sharp.Watch@1.1.2
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=S7Sharp.Watch&version=1.1.2
#tool nuget:?package=S7Sharp.Watch&version=1.1.2
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
S7Sharp.Watch — 数据变化监控
按每个定义自己的间隔周期读一块数据 → 与缓存按字节比 → 变了才通知(event);没变什么都不做。
- 只读:从不写设备(写面仍归调用方与既有工具)。
- 进程内:缓存与通知槽都在内存,进程退出即丢。
- 零第三方依赖:唯一依赖是
S7Sharp(版本锁步)。 - 不动产品库:本库只消费
S7Sharp的公开面(ReadStructBytes/TryGetLayout/S7StructLayout),不重算地址与宽度。 - 通知与读解耦:读只把事件放进"每定义的最新未消费槽"(覆盖式 ⇒ 不丢变化、只丢中间态),由独立的通知步投递 ⇒ 慢订阅者拖不住轮询。
本质边界(先知道再看代码):漏报是本质的 —— 两次读之间"变了又变回去"永远检测不到(不做去抖、不做变化历史、不做趋势)。
用法(一):C# 类定义
using S7Sharp.Siemens;
using S7Sharp.Watch;
var plc = new SiemensS7Net("192.168.0.1", 102) { Rack = 0, Slot = 1 };
// 连接由库在每次请求前保证(含既有的"自动重连一次")—— 这里也可以先 ConnectServerAsync 一次
using var watch = new S7WatchService(plc, new S7WatchOptions { IncludeBytes = false });
watch.Changed += e =>
{
if (e.Kind == S7WatchEventKind.Initial)
Console.WriteLine($"[{e.Id}] 基线已建立({e.Timestamp:HH:mm:ss})");
else
Console.WriteLine($"[{e.Id}] 变了:{string.Join(", ", e.ChangedFields)}(差异字节 {e.ChangedBytes.Count} 个)");
};
watch.Failed += e => Console.WriteLine($"[{e.Id}] 读失败:{e.Failure.Message}(缓存未动)");
// 1 秒看一次;只关心 Temp 与 Head1.Temp 两个字段
watch.Add(new S7WatchDefinition(
id: "job1",
type: typeof(JobData),
interval: TimeSpan.FromSeconds(1),
fields: ["Temp", "Head1.Temp"]));
watch.Start();
// 随时取当前值(**不触网**)
if (watch.TryGetSnapshot("job1", out S7WatchSnapshot snapshot))
Console.WriteLine($"当前 {snapshot.Bytes.Length} 字节,取于 {snapshot.ReadAt:HH:mm:ss}");
// 运行期调优:先密后疏(**保留基线、不重发 Initial**)
watch.Update(new S7WatchDefinition("job1", typeof(JobData), TimeSpan.FromSeconds(10), fields: ["Temp"]));
watch.Stop(); // 暂停(保留基线);再 Start() 沿用
用法(二):JSON 配置(动态类型)
JSON 配置与类定义在监控这一层合一 —— 注册后拿到 Type 即可:
using S7Sharp.Siemens;
using S7Sharp.Watch;
string json = File.ReadAllText("dynamic-types.json"); // R-5 的同一份 schema
using S7DynTypeSet set = S7DynTypes.Register(json); // 运行期生成类型
if (!set.TryGetType("JobData", out Type jobType))
throw new InvalidOperationException("配置里没有 JobData");
using var watch = new S7WatchService(plc);
watch.Add(new S7WatchDefinition("job1", jobType, TimeSpan.FromMilliseconds(500)));
watch.Start();
注意:
S7DynTypeSet的生命周期要盖住监控期(Dispose会丢引用、类型随之可被卸载)。
事件与队列语义(重要)
| 项 | 语义 |
|---|---|
| 事件种类 | Initial(建立基线,不是"变了")/ Changed(数据变了,缓存已更新)/ Failed(读失败,缓存未动) |
| 载荷 | ChangedBytes(差异字节下标)· ChangedFields(字段名,含嵌套路径如 Head1.Temp)· Coalesced(本条合并掉几条中间变化)· AfterFailure(上一次读失败过) |
IncludeBytes |
默认 false(事件轻);打开则附整块变化前后字节 |
| 队列 | 每定义只留最新一条未消费事件(覆盖式):不丢变化、只丢中间态;Coalesced 计数可见 |
| 顺序 | 同一定义保序;跨定义无全序(各自到期 + 覆盖式槽)⇒ 别按"全局时间线"读 |
| 线程 | 事件在通知步的线程上抛(不是读数据的线程)⇒ 订阅者慢不拖轮询;回调抛异常被吞掉并计数(S7WatchStatus.NotifyErrors) |
失败与基线
- 读失败:不动缓存、不发
Changed,发Failed(ErrorCode/Message原样透出,不翻译)+ 计数。 - 失败后首次成功读:照常比较并报(期间真的变了就是真事实),事件带
AfterFailure = true。 - 首读:
Add时同步完成(顺序确定)并发一条Initial。 Update:只改Interval/Fields(保留基线);换Type/ByteOffset/Id请Remove+Add(那等于换了监控对象)。
刻意不做
工具侧"监控页签"(要改写配置工具"不点不连 / 不加轮询"的既有契约,须另立)· 语义等价比对(float -0.0 / NaN、string 填充:字节不同即现场真变了,如实报)· 变化历史 / 趋势 / 去抖 · 事件持久化 · 监控定义的 JSON 化 · 连接池 / 并行读。
设计与判据见 docs/03-P7-1-数据变化监控设计.md;需求见 docs/01-需求规格说明书.md R-7。
| 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. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net8.0
- S7Sharp (>= 1.1.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.