Skip to content

Commit 31682fb

Browse files
committed
feat: 增加 MockOpcDaServer 服务
1 parent 94bdbb3 commit 31682fb

6 files changed

Lines changed: 168 additions & 6 deletions

File tree

src/extensions/BootstrapBlazor.OpcDa/BootstrapBlazor.OpcDa.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<Version>9.0.0</Version>
4+
<Version>9.0.0-beta02</Version>
55
<RootNamespace>BootstrapBlazor.OpcDa</RootNamespace>
66
</PropertyGroup>
77

src/extensions/BootstrapBlazor.OpcDa/Extensions/ServiceCollectionExtensions.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,25 @@ namespace Microsoft.Extensions.DependencyInjection;
1313
public static class ServiceCollectionExtensions
1414
{
1515
/// <summary>
16-
/// 增加 Opc 操作服务
16+
/// 增加 OpcDaServer 操作服务
1717
/// </summary>
1818
/// <param name="services"></param>
1919
/// <returns></returns>
2020
[SupportedOSPlatform("windows")]
21-
public static IServiceCollection AddOpcServer(this IServiceCollection services)
21+
public static IServiceCollection AddOpcDaServer(this IServiceCollection services)
2222
{
23-
services.AddSingleton<IOpcServer, OpcServer>();
23+
services.AddSingleton<IOpcDaServer, OpcDaServer>();
24+
return services;
25+
}
26+
27+
/// <summary>
28+
/// 增加模拟 OpcDaServer 操作服务
29+
/// </summary>
30+
/// <param name="services"></param>
31+
/// <returns></returns>
32+
public static IServiceCollection AddMockOpcDaServer(this IServiceCollection services)
33+
{
34+
services.AddSingleton<IOpcDaServer, MockOpcDaServer>();
2435
return services;
2536
}
2637
}

src/extensions/BootstrapBlazor.OpcDa/IOpcServer.cs renamed to src/extensions/BootstrapBlazor.OpcDa/IOpcDaServer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace BootstrapBlazor.OpcDa;
77
/// <summary>
88
/// Opc Server 接口定义
99
/// </summary>
10-
public interface IOpcServer : IDisposable
10+
public interface IOpcDaServer : IDisposable
1111
{
1212
/// <summary>
1313
/// 获得 OPC Server 是否已连接
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
// Website: https://www.blazor.zone or https://argozhang.github.io/
4+
5+
namespace BootstrapBlazor.OpcDa;
6+
7+
/// <summary>
8+
/// 模拟 OpcDa Server 实现类
9+
/// </summary>
10+
sealed class MockOpcDaServer : IOpcDaServer
11+
{
12+
public bool IsConnected { get; set; }
13+
14+
public string? ServerName { get; set; }
15+
16+
private readonly Dictionary<string, IOpcSubscription> _subscriptions = [];
17+
18+
public bool Connect(string serverName)
19+
{
20+
ServerName = serverName;
21+
IsConnected = true;
22+
return true;
23+
}
24+
25+
public void Disconnect()
26+
{
27+
IsConnected = false;
28+
ServerName = null;
29+
}
30+
31+
public IOpcSubscription CreateSubscription(string name, int updateRate = 1000, bool active = true)
32+
{
33+
if (_subscriptions.TryGetValue(name, out var subscription))
34+
{
35+
CancelSubscription(subscription);
36+
}
37+
38+
subscription = new MockOpcDaSubscription(name, updateRate, active);
39+
_subscriptions.Add(name, subscription);
40+
return subscription;
41+
}
42+
43+
public void CancelSubscription(IOpcSubscription subscription)
44+
{
45+
_subscriptions.Remove(subscription.Name);
46+
if (subscription is IDisposable disposable)
47+
{
48+
disposable.Dispose();
49+
}
50+
}
51+
52+
public HashSet<OpcReadItem> Read(params HashSet<string> items)
53+
{
54+
return items.Select(i => new OpcReadItem(i, Quality.Good, DateTime.Now, Random.Shared.Next(1000, 2000)))
55+
.ToHashSet(OpcItemEqualityComparer<OpcReadItem>.Default);
56+
}
57+
58+
public HashSet<OpcWriteItem> Write(params HashSet<OpcWriteItem> items)
59+
{
60+
return items.Select(i => new OpcWriteItem(i.Name, i.Value) { Result = true })
61+
.ToHashSet(OpcItemEqualityComparer<OpcWriteItem>.Default);
62+
}
63+
64+
public void Dispose()
65+
{
66+
}
67+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
// Website: https://www.blazor.zone or https://argozhang.github.io/
4+
5+
namespace BootstrapBlazor.OpcDa;
6+
7+
sealed class MockOpcDaSubscription : IOpcSubscription, IDisposable
8+
{
9+
private readonly int _updateRate;
10+
private readonly bool _active;
11+
private readonly List<string> _items = [];
12+
private CancellationTokenSource? _cts;
13+
14+
public MockOpcDaSubscription(string name, int updateRate = 1000, bool active = true)
15+
{
16+
Name = name;
17+
_updateRate = updateRate;
18+
_active = active;
19+
20+
_cts = new CancellationTokenSource();
21+
_ = Task.Run(() => DoTask(_cts.Token));
22+
}
23+
24+
public string Name { get; }
25+
26+
public bool KeepLastValue { get; set; }
27+
28+
public Action<List<OpcReadItem>>? DataChanged { get; set; }
29+
30+
public void AddItems(IEnumerable<string> items)
31+
{
32+
_items.AddRange(items);
33+
}
34+
35+
private void UpdateValues()
36+
{
37+
if (DataChanged != null)
38+
{
39+
var values = _items.Select(i => new OpcReadItem(i, Quality.Good, DateTime.Now, Random.Shared.Next(1000, 2000))).ToList();
40+
DataChanged.Invoke(values);
41+
}
42+
}
43+
44+
private async Task DoTask(CancellationToken token)
45+
{
46+
do
47+
{
48+
try
49+
{
50+
if (_active)
51+
{
52+
UpdateValues();
53+
}
54+
55+
await Task.Delay(_updateRate, token);
56+
}
57+
catch (OperationCanceledException) { }
58+
catch (Exception)
59+
{
60+
// ignored
61+
}
62+
}
63+
while (!token.IsCancellationRequested);
64+
}
65+
66+
private void Dispose(bool disposing)
67+
{
68+
if (disposing)
69+
{
70+
if (_cts != null)
71+
{
72+
_cts.Cancel();
73+
_cts.Dispose();
74+
_cts = null;
75+
}
76+
}
77+
}
78+
79+
public void Dispose()
80+
{
81+
Dispose(true);
82+
GC.SuppressFinalize(this);
83+
}
84+
}

src/extensions/BootstrapBlazor.OpcDa/OpcServer.cs renamed to src/extensions/BootstrapBlazor.OpcDa/OpcDaServer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace BootstrapBlazor.OpcDa;
1313
/// OPC Server 操作类
1414
/// </summary>
1515
[SupportedOSPlatform("windows")]
16-
sealed class OpcServer : IOpcServer
16+
sealed class OpcDaServer : IOpcDaServer
1717
{
1818
private Opc.Da.Server? _server = null;
1919
private readonly ConcurrentDictionary<string, HashSet<OpcReadItem>> _valuesCache = [];

0 commit comments

Comments
 (0)