Skip to content

Commit a1ccad8

Browse files
authored
feat(OpcDa): add OpcDa lib (#514)
* chore: 增加 OpcUa 工程 * feat: 增加扩展服务 * test: 增加单元测试 * test: 增加测试工程 * feat: 增加基金会 OpcDa 组件 * chore: 增加 OpcDa 工程 * refactor: 重构扩展方法 * chore: 更新依赖包 * feat: 新增 OpcItemEqualityComparer 比较器 * refactor: 精简代码 * test: 更新单元测试 * feat: 增加 Opc 服务 * test: 更新单元测试 * refactor: 增加 OpcWriteItem 类 * test: 增加单元测试 * feat: 实现订阅数据回调功能 * test: 增加单元测试 * refactor: 更改为 Action 回调 * test: 更新单元测试 * chore: 增加依赖 * chore: 增加 targets 脚本 * chore: 增加打包配置 * chore: 更改 dll 包路径 * revert: 撤销包源更新
1 parent 5729731 commit a1ccad8

24 files changed

Lines changed: 833 additions & 0 deletions

BootstrapBlazor.Extensions.sln

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestSvgIcon", "test\Uni
192192
EndProject
193193
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BootstrapBlazor.FluentSystemIcon", "src\components\BootstrapBlazor.FluentSystemIcon\BootstrapBlazor.FluentSystemIcon.csproj", "{30449D30-0B4E-40FD-85BE-C9BAAC820162}"
194194
EndProject
195+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BootstrapBlazor.OpcUa", "src\components\BootstrapBlazor.OpcUa\BootstrapBlazor.OpcUa.csproj", "{6114A9DF-9DF5-474E-A5B0-25CDF0268B52}"
196+
EndProject
197+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestOpcUa", "test\UnitTestOpcUa\UnitTestOpcUa.csproj", "{98373A64-E224-4715-AE02-A8C6DAFF3338}"
198+
EndProject
199+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BootstrapBlazor.OpcDa", "src\extensions\BootstrapBlazor.OpcDa\BootstrapBlazor.OpcDa.csproj", "{01007B10-7C3C-4136-83FF-981CA39AD3D4}"
200+
EndProject
201+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestOpcDa", "test\UnitTestOpcDa\UnitTestOpcDa.csproj", "{835C8BA9-A9CC-4EA0-9002-34A20F8B2E86}"
202+
EndProject
195203
Global
196204
GlobalSection(SolutionConfigurationPlatforms) = preSolution
197205
Debug|Any CPU = Debug|Any CPU
@@ -522,6 +530,22 @@ Global
522530
{30449D30-0B4E-40FD-85BE-C9BAAC820162}.Debug|Any CPU.Build.0 = Debug|Any CPU
523531
{30449D30-0B4E-40FD-85BE-C9BAAC820162}.Release|Any CPU.ActiveCfg = Release|Any CPU
524532
{30449D30-0B4E-40FD-85BE-C9BAAC820162}.Release|Any CPU.Build.0 = Release|Any CPU
533+
{6114A9DF-9DF5-474E-A5B0-25CDF0268B52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
534+
{6114A9DF-9DF5-474E-A5B0-25CDF0268B52}.Debug|Any CPU.Build.0 = Debug|Any CPU
535+
{6114A9DF-9DF5-474E-A5B0-25CDF0268B52}.Release|Any CPU.ActiveCfg = Release|Any CPU
536+
{6114A9DF-9DF5-474E-A5B0-25CDF0268B52}.Release|Any CPU.Build.0 = Release|Any CPU
537+
{98373A64-E224-4715-AE02-A8C6DAFF3338}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
538+
{98373A64-E224-4715-AE02-A8C6DAFF3338}.Debug|Any CPU.Build.0 = Debug|Any CPU
539+
{98373A64-E224-4715-AE02-A8C6DAFF3338}.Release|Any CPU.ActiveCfg = Release|Any CPU
540+
{98373A64-E224-4715-AE02-A8C6DAFF3338}.Release|Any CPU.Build.0 = Release|Any CPU
541+
{01007B10-7C3C-4136-83FF-981CA39AD3D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
542+
{01007B10-7C3C-4136-83FF-981CA39AD3D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
543+
{01007B10-7C3C-4136-83FF-981CA39AD3D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
544+
{01007B10-7C3C-4136-83FF-981CA39AD3D4}.Release|Any CPU.Build.0 = Release|Any CPU
545+
{835C8BA9-A9CC-4EA0-9002-34A20F8B2E86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
546+
{835C8BA9-A9CC-4EA0-9002-34A20F8B2E86}.Debug|Any CPU.Build.0 = Debug|Any CPU
547+
{835C8BA9-A9CC-4EA0-9002-34A20F8B2E86}.Release|Any CPU.ActiveCfg = Release|Any CPU
548+
{835C8BA9-A9CC-4EA0-9002-34A20F8B2E86}.Release|Any CPU.Build.0 = Release|Any CPU
525549
EndGlobalSection
526550
GlobalSection(SolutionProperties) = preSolution
527551
HideSolutionNode = FALSE
@@ -612,6 +636,10 @@ Global
612636
{10D35EE5-FA31-4C80-B113-CD7A0FB76B4E} = {B6A98ADE-D26A-4D0B-8978-AB7AC915F5AE}
613637
{7CAD5915-CE3E-31ED-B1AC-15C61C3ED8C3} = {B6A98ADE-D26A-4D0B-8978-AB7AC915F5AE}
614638
{30449D30-0B4E-40FD-85BE-C9BAAC820162} = {FF1089BE-C704-4374-B629-C57C08E1798F}
639+
{6114A9DF-9DF5-474E-A5B0-25CDF0268B52} = {FF1089BE-C704-4374-B629-C57C08E1798F}
640+
{98373A64-E224-4715-AE02-A8C6DAFF3338} = {B6A98ADE-D26A-4D0B-8978-AB7AC915F5AE}
641+
{01007B10-7C3C-4136-83FF-981CA39AD3D4} = {7B29E81D-92DE-46C8-8EDC-1B48C8F12BC2}
642+
{835C8BA9-A9CC-4EA0-9002-34A20F8B2E86} = {B6A98ADE-D26A-4D0B-8978-AB7AC915F5AE}
615643
EndGlobalSection
616644
GlobalSection(ExtensibilityGlobals) = postSolution
617645
SolutionGuid = {D5EB1960-6F30-4CE1-B375-EAE1F787D6FF}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Razor">
2+
3+
<PropertyGroup>
4+
<Version>9.0.1</Version>
5+
</PropertyGroup>
6+
7+
<PropertyGroup>
8+
<PackageTags>Bootstrap Blazor WebAssembly wasm UI Components Opc Ua Client</PackageTags>
9+
<Description>Bootstrap UI components extensions of OpcUa</Description>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="BootstrapBlazor" Version="$(BBVersion)" />
14+
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client" Version="1.5.376.235" />
15+
</ItemGroup>
16+
17+
<ItemGroup>
18+
<Using Include="BootstrapBlazor.Components" />
19+
</ItemGroup>
20+
21+
</Project>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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 Microsoft.Extensions.DependencyInjection;
6+
7+
/// <summary>
8+
/// OpcUa 服务扩展类
9+
/// </summary>
10+
public static class ServiceCollectionExtensions
11+
{
12+
/// <summary>
13+
/// 增加 OpcUa 数据服务
14+
/// </summary>
15+
/// <param name="services"></param>
16+
/// <returns></returns>
17+
public static IServiceCollection AddBootstrapBlazorOpcUaService(this IServiceCollection services)
18+
{
19+
return services;
20+
}
21+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@using Microsoft.AspNetCore.Components.Web
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<Version>9.0.0-beta01</Version>
5+
<RootNamespace>BootstrapBlazor.OpcDa</RootNamespace>
6+
</PropertyGroup>
7+
8+
<PropertyGroup>
9+
<PackageTags>Bootstrap Blazor WebAssembly wasm UI Components SqlSugar</PackageTags>
10+
<Description>Bootstrap UI components extensions of SqlSugar</Description>
11+
</PropertyGroup>
12+
13+
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
14+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.*" />
15+
</ItemGroup>
16+
17+
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
18+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.*" />
19+
</ItemGroup>
20+
21+
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
22+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.*" />
23+
</ItemGroup>
24+
25+
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
26+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.*" />
27+
</ItemGroup>
28+
29+
<ItemGroup>
30+
<None Include="lib\OpcComRcw.dll" Pack="true" PackagePath="lib\net6.0" />
31+
<None Include="lib\OpcNetApi.dll" Pack="true" PackagePath="lib\net6.0" />
32+
<None Include="lib\OpcNetApi.Com.dll" Pack="true" PackagePath="lib\net6.0" />
33+
</ItemGroup>
34+
35+
<ItemGroup>
36+
<Reference Include="OpcComRcw" HintPath="lib\OpcComRcw.dll" Private="true" PackageCopyToOutput="true" />
37+
<Reference Include="OpcNetApi" HintPath="lib\OpcComRcw.dll" Private="true" PackageCopyToOutput="true" />
38+
<Reference Include="OpcNetApi.Com" HintPath="lib\OpcComRcw.dll" Private="true" PackageCopyToOutput="true" />
39+
</ItemGroup>
40+
41+
<ItemGroup>
42+
<Content Include="build\*.targets" PackagePath="build" />
43+
</ItemGroup>
44+
45+
<ItemGroup>
46+
<Using Remove="BootstrapBlazor.Components" />
47+
<Using Remove="Microsoft.AspNetCore.Components" />
48+
<Using Remove="Microsoft.Extensions.DependencyInjection" />
49+
</ItemGroup>
50+
51+
</Project>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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+
/// 扩展方法类
9+
/// </summary>
10+
internal static class Extensions
11+
{
12+
public static Quality ToQuality(this Opc.Da.Quality quality)
13+
{
14+
return quality.QualityBits == Opc.Da.qualityBits.good
15+
? Quality.Good
16+
: Quality.Bad;
17+
}
18+
19+
public static ISubscription ToOpcSubscription(this Opc.Da.ISubscription subscription)
20+
{
21+
return new OpcSubscription(subscription);
22+
}
23+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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+
using BootstrapBlazor.OpcDa;
6+
using System.Runtime.Versioning;
7+
8+
namespace Microsoft.Extensions.DependencyInjection;
9+
10+
/// <summary>
11+
/// Opc Da 服务扩展类
12+
/// </summary>
13+
public static class ServiceCollectionExtensions
14+
{
15+
/// <summary>
16+
/// 增加 Opc 操作服务
17+
/// </summary>
18+
/// <param name="services"></param>
19+
/// <returns></returns>
20+
[SupportedOSPlatform("windows")]
21+
public static IServiceCollection AddOpcServer(this IServiceCollection services)
22+
{
23+
services.AddSingleton<IOpcServer, OpcServer>();
24+
return services;
25+
}
26+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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+
///
9+
/// </summary>
10+
public interface IOpcItem
11+
{
12+
/// <summary>
13+
///
14+
/// </summary>
15+
string Name { get; }
16+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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+
/// Opc Server 接口定义
9+
/// </summary>
10+
public interface IOpcServer : IDisposable
11+
{
12+
/// <summary>
13+
/// 获得 OPC Server 是否已连接
14+
/// </summary>
15+
bool IsConnected { get; }
16+
17+
/// <summary>
18+
/// 获得 OPC Server 名称
19+
/// </summary>
20+
string? ServerName { get; }
21+
22+
/// <summary>
23+
/// 连接到 OPC Server 方法
24+
/// </summary>
25+
/// <param name="serverName"></param>
26+
/// <returns></returns>
27+
bool Connect(string serverName);
28+
29+
/// <summary>
30+
/// 断开连接方法
31+
/// </summary>
32+
void Disconnect();
33+
34+
/// <summary>
35+
/// 取消订阅方法
36+
/// </summary>
37+
/// <param name="subscription"></param>
38+
void CancelSubscription(ISubscription subscription);
39+
40+
/// <summary>
41+
/// 创建订阅方法
42+
/// </summary>
43+
/// <param name="name">订阅名称</param>
44+
/// <param name="updateRate">更新频率 默认 1000 毫秒</param>
45+
/// <param name="active">是否激活 默认 true</param>
46+
/// <returns></returns>
47+
ISubscription CreateSubscription(string name, int updateRate = 1000, bool active = true);
48+
49+
/// <summary>
50+
/// 读取 Item 值方法
51+
/// </summary>
52+
/// <param name="items"></param>
53+
/// <returns></returns>
54+
HashSet<OpcReadItem> Read(params HashSet<string> items);
55+
56+
/// <summary>
57+
/// 读取 Item 值方法
58+
/// </summary>
59+
/// <param name="items"></param>
60+
/// <returns></returns>
61+
HashSet<OpcWriteItem> Write(params HashSet<OpcWriteItem> items);
62+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
/// 订阅接口定义
9+
/// </summary>
10+
public interface ISubscription
11+
{
12+
/// <summary>
13+
/// 获得/设置 是否保留最后一个值
14+
/// </summary>
15+
public bool KeepLastValue { get; set; }
16+
17+
/// <summary>
18+
/// 获得/设置 数据变更回调
19+
/// </summary>
20+
Action<List<OpcReadItem>>? DataChanged { get; set; }
21+
22+
/// <summary>
23+
/// 获得 <see cref="Opc.Da.ISubscription"/> 实例
24+
/// </summary>
25+
/// <returns></returns>
26+
Opc.Da.ISubscription GetSubscription();
27+
28+
/// <summary>
29+
/// 增加数据项
30+
/// </summary>
31+
/// <param name="items"></param>
32+
void AddItems(IEnumerable<string> items);
33+
}

0 commit comments

Comments
 (0)