Skip to content

Commit 1ef4d91

Browse files
authored
doc(OpcDa): add MockOpcDaServer sample code (#6563)
* chore: 更加 OpcDa 依赖包 * doc: 增加菜单 * doc: 增加 OpcDa 示例页面 * refactor: 增加模拟 OpcServer 实现类 * doc: 增加 OpcDa 源码映射 * doc: 更新示例 * chore: 增加 MockOpcDaServer 支持 Linux 演示 * chore: 更新依赖包 * feat: 完善模拟 OpcServer 服务实现类 * doc: 更新示例 * refactor: 更新依赖 * doc: 更新按钮可用逻辑 * refactor: 更新注入服务 * doc: 更新示例 * refactor: 删除 Mock 服务 * chore: 更新依赖包
1 parent 22e67cf commit 1ef4d91

File tree

8 files changed

+201
-5
lines changed

8 files changed

+201
-5
lines changed

src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,19 @@
6060
<PackageReference Include="BootstrapBlazor.OctIcon" Version="9.0.4" />
6161
<PackageReference Include="BootstrapBlazor.OfficeViewer" Version="9.0.0" />
6262
<PackageReference Include="BootstrapBlazor.OnScreenKeyboard" Version="9.0.1" />
63+
<PackageReference Include="BootstrapBlazor.OpcDa" Version="9.0.0" />
6364
<PackageReference Include="BootstrapBlazor.PdfReader" Version="9.0.1" />
6465
<PackageReference Include="BootstrapBlazor.PdfViewer" Version="9.0.6" />
6566
<PackageReference Include="BootstrapBlazor.Player" Version="9.0.1" />
6667
<PackageReference Include="BootstrapBlazor.RDKit" Version="9.0.2" />
6768
<PackageReference Include="BootstrapBlazor.SignaturePad" Version="9.0.1" />
6869
<PackageReference Include="BootstrapBlazor.SmilesDrawer" Version="9.0.2" />
69-
<PackageReference Include="BootstrapBlazor.Sortable" Version="9.0.2" />
70+
<PackageReference Include="BootstrapBlazor.Sortable" Version="9.0.3" />
7071
<PackageReference Include="BootstrapBlazor.Splitting" Version="9.0.3" />
7172
<PackageReference Include="BootstrapBlazor.SvgEditor" Version="9.0.3" />
7273
<PackageReference Include="BootstrapBlazor.SummerNote" Version="9.0.4" />
7374
<PackageReference Include="BootstrapBlazor.TableExport" Version="9.2.6" />
74-
<PackageReference Include="BootstrapBlazor.TcpSocket" Version="9.0.0-beta01" />
75+
<PackageReference Include="BootstrapBlazor.TcpSocket" Version="9.0.0" />
7576
<PackageReference Include="BootstrapBlazor.Topology" Version="9.0.1" />
7677
<PackageReference Include="BootstrapBlazor.UniverIcon" Version="9.0.1" />
7778
<PackageReference Include="BootstrapBlazor.UniverSheet" Version="9.0.5" />
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
@page "/opc-da"
2+
@inject IStringLocalizer<OpcDa> Localizer
3+
4+
<h3>@Localizer["OpcDaTitle"]</h3>
5+
6+
<h4>@Localizer["OpcDaDescription"]</h4>
7+
8+
<PackageTips Name="BootstrapBlazor.OpcDa"/>
9+
10+
<DemoBlock Title="@Localizer["OpcDaNormalTitle"]" Introduction="@Localizer["OpcDaNormalIntro"]" Name="Normal">
11+
<p class="code-label">1. 点击 <b>连接</b> 按钮与 <code>OpcDa</code> 服务器建立通讯连接</p>
12+
<p>
13+
<BootstrapInputGroup>
14+
<BootstrapInputGroupLabel DisplayText="OpcDa Server"></BootstrapInputGroupLabel>
15+
<Display @bind-Value="@_serverName"></Display>
16+
<Button Text="连接" OnClick="OnConnect" IsDisabled="OpcDaServer.IsConnected"></Button>
17+
<Button Text="断开" OnClick="OnDisConnect" IsDisabled="!OpcDaServer.IsConnected"
18+
Color="Color.Danger"></Button>
19+
</BootstrapInputGroup>
20+
</p>
21+
22+
<p class="code-label">2. 点击 <b>读取</b> 按钮读取 <code>OpcDa</code> 服务器上的位号值</p>
23+
<div class="row g-3 mb-3">
24+
<div class="col-12 col-sm-6">
25+
<BootstrapInputGroup>
26+
<BootstrapInputGroupLabel DisplayText="转速"></BootstrapInputGroupLabel>
27+
<BootstrapInputGroupLabel DisplayText="@Tag1"></BootstrapInputGroupLabel>
28+
<Display @bind-Value="@_tagValue1"></Display>
29+
</BootstrapInputGroup>
30+
</div>
31+
<div class="col-12 col-sm-6">
32+
<BootstrapInputGroup>
33+
<BootstrapInputGroupLabel DisplayText="流速"></BootstrapInputGroupLabel>
34+
<BootstrapInputGroupLabel DisplayText="@Tag2"></BootstrapInputGroupLabel>
35+
<Display @bind-Value="@_tagValue2"></Display>
36+
</BootstrapInputGroup>
37+
</div>
38+
<div class="col-12 col-sm-6">
39+
<Button OnClick="OnRead" Text="读取" IsDisabled="!OpcDaServer.IsConnected"></Button>
40+
</div>
41+
</div>
42+
43+
<p class="code-label">3. 订阅功能</p>
44+
<p>通过订阅可以监控一组 <b>位号</b> 数据改变情况,当数据改变时通过 <code>DataChanged</code> 回调方法通知订阅者</p>
45+
<div class="row g-3">
46+
<div class="col-12 col-sm-6">
47+
<BootstrapInputGroup>
48+
<BootstrapInputGroupLabel DisplayText="订阅名称"></BootstrapInputGroupLabel>
49+
<BootstrapInputGroupLabel DisplayText="Subscription1"></BootstrapInputGroupLabel>
50+
</BootstrapInputGroup>
51+
</div>
52+
<div class="col-12 col-sm-6">
53+
<BootstrapInputGroup>
54+
<BootstrapInputGroupLabel DisplayText="更新频率"></BootstrapInputGroupLabel>
55+
<BootstrapInputGroupLabel DisplayText="1000"></BootstrapInputGroupLabel>
56+
</BootstrapInputGroup>
57+
</div>
58+
<div class="col-12 col-sm-6">
59+
<BootstrapInputGroup>
60+
<BootstrapInputGroupLabel DisplayText="转速"></BootstrapInputGroupLabel>
61+
<BootstrapInputGroupLabel DisplayText="@Tag3"></BootstrapInputGroupLabel>
62+
<Display @bind-Value="@_tagValue3"></Display>
63+
</BootstrapInputGroup>
64+
</div>
65+
<div class="col-12 col-sm-6">
66+
<BootstrapInputGroup>
67+
<BootstrapInputGroupLabel DisplayText="流速"></BootstrapInputGroupLabel>
68+
<BootstrapInputGroupLabel DisplayText="@Tag4"></BootstrapInputGroupLabel>
69+
<Display @bind-Value="@_tagValue4"></Display>
70+
</BootstrapInputGroup>
71+
</div>
72+
<div class="col-12 col-sm-6">
73+
<Button OnClick="OnCreateSubscription" Text="订阅" IsDisabled="@(!OpcDaServer.IsConnected || _subscribed)"></Button>
74+
<Button OnClick="OnCancelSubscription" Text="取消" IsDisabled="!_subscribed"></Button>
75+
</div>
76+
</div>
77+
</DemoBlock>
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the Apache 2.0 License
3+
// See the LICENSE file in the project root for more information.
4+
// Maintainer: Argo Zhang([email protected]) Website: https://www.blazor.zone
5+
6+
using BootstrapBlazor.OpcDa;
7+
using System.Globalization;
8+
9+
namespace BootstrapBlazor.Server.Components.Samples;
10+
11+
/// <summary>
12+
/// OpcDa 示例
13+
/// </summary>
14+
public partial class OpcDa : ComponentBase
15+
{
16+
[Inject]
17+
[NotNull]
18+
private IOpcDaServer? OpcDaServer { get; set; }
19+
20+
private string? _serverName = "opcda://localhost/Kepware.KEPServerEX.V6/Mock";
21+
22+
private const string Tag1 = "Channel1.Device1.Tag1";
23+
private const string Tag2 = "Channel1.Device1.Tag2";
24+
private const string Tag3 = "Channel1.Device1.Tag3";
25+
private const string Tag4 = "Channel1.Device1.Tag4";
26+
27+
private string? _tagValue1;
28+
private string? _tagValue2;
29+
private string? _tagValue3;
30+
private string? _tagValue4;
31+
32+
private IOpcSubscription? _subscription;
33+
34+
private bool _subscribed;
35+
36+
private void OnConnect()
37+
{
38+
if (!string.IsNullOrEmpty(_serverName))
39+
{
40+
OpcDaServer.Connect(_serverName);
41+
}
42+
}
43+
44+
private void OnDisConnect()
45+
{
46+
OnCancelSubscription();
47+
OpcDaServer.Disconnect();
48+
}
49+
50+
private void OnRead()
51+
{
52+
var values = OpcDaServer.Read(Tag1, Tag2);
53+
_tagValue1 = values.ElementAt(0).Value?.ToString();
54+
55+
var v = (int)values.ElementAt(1).Value! / 100d;
56+
_tagValue2 = v.ToString(CultureInfo.InvariantCulture);
57+
}
58+
59+
private void OnCreateSubscription()
60+
{
61+
_subscribed = true;
62+
_subscription = OpcDaServer.CreateSubscription("Subscription1", 1000, true);
63+
_subscription.DataChanged += UpdateValues;
64+
_subscription.AddItems([Tag3, Tag4]);
65+
}
66+
67+
private void OnCancelSubscription()
68+
{
69+
_subscribed = false;
70+
if (_subscription != null)
71+
{
72+
_subscription.DataChanged -= UpdateValues;
73+
OpcDaServer.CancelSubscription(_subscription);
74+
}
75+
}
76+
77+
private void UpdateValues(List<OpcReadItem> items)
78+
{
79+
_tagValue3 = items[0].Value?.ToString();
80+
var v = (int)items[1].Value! / 100d;
81+
_tagValue4 = v.ToString(CultureInfo.InvariantCulture);
82+
83+
InvokeAsync(StateHasChanged);
84+
}
85+
}
86+

src/BootstrapBlazor.Server/Extensions/MenusLocalizerExtensions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,12 @@ void AddServices(DemoMenuItem item)
16121612
Url = "mask"
16131613
},
16141614
new()
1615+
{
1616+
IsNew = true,
1617+
Text = Localizer["OpcDaService"],
1618+
Url = "opc-da"
1619+
},
1620+
new()
16151621
{
16161622
Text = Localizer["PrintService"],
16171623
Url = "print-service"

src/BootstrapBlazor.Server/Extensions/ServiceCollectionExtensions.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44
// Maintainer: Argo Zhang([email protected]) Website: https://www.blazor.zone
55

6+
using BootstrapBlazor.OpcDa;
67
using Longbow.Tasks.Services;
78
using Microsoft.AspNetCore.SignalR;
89
using Microsoft.Extensions.Options;
@@ -45,6 +46,16 @@ public static IServiceCollection AddBootstrapBlazorServerService(this IServiceCo
4546
services.AddHostedService<MockCustomProtocolSocketServerService>();
4647
services.AddHostedService<MockDisconnectServerService>();
4748

49+
if (OperatingSystem.IsWindows())
50+
{
51+
services.AddOpcDaServer();
52+
}
53+
else
54+
{
55+
// 增加 OpcDa 模拟服务(给 Linux 平台使用)
56+
services.AddMockOpcDaServer();
57+
}
58+
4859
// 增加通用服务
4960
services.AddBootstrapBlazorServices();
5061

src/BootstrapBlazor.Server/Locales/en-US.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4846,7 +4846,8 @@
48464846
"SocketAutoConnect": "Reconnect",
48474847
"SocketDataEntity": "DataEntity",
48484848
"NetworkMonitor": "Network Monitor",
4849-
"Toolbar": "Toolbar"
4849+
"Toolbar": "Toolbar",
4850+
"OpcDaService": "OpcDaServer"
48504851
},
48514852
"BootstrapBlazor.Server.Components.Samples.Table.TablesHeader": {
48524853
"TablesHeaderTitle": "Header grouping function",
@@ -7158,5 +7159,11 @@
71587159
"ToolbarSubTitle": "ToolBar component is a container for buttons or other application-specific tools",
71597160
"NormalTitle": "Normal",
71607161
"NormalIntro": ""
7162+
},
7163+
"BootstrapBlazor.Server.Components.Samples.OpcDa": {
7164+
"OpcDaTitle": "OpcDa Server",
7165+
"OpcDaDescription": "Connect to OpcDa Server to obtain PLC real-time data",
7166+
"OpcDaNormalTitle": "Basic usage",
7167+
"OpcDaNormalIntro": "Get an instance by injecting the service <code>IOpcDaServer</code> and call the <code>Read</code> method to get the PLC Tag value."
71617168
}
71627169
}

src/BootstrapBlazor.Server/Locales/zh-CN.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4846,7 +4846,8 @@
48464846
"SocketAutoConnect": "自动重连",
48474847
"SocketDataEntity": "通讯数据转实体类",
48484848
"NetworkMonitor": "网络状态 NetworkMonitor",
4849-
"Toolbar": "工具栏 Toolbar"
4849+
"Toolbar": "工具栏 Toolbar",
4850+
"OpcDaService": "OpcDaServer 服务"
48504851
},
48514852
"BootstrapBlazor.Server.Components.Samples.Table.TablesHeader": {
48524853
"TablesHeaderTitle": "表头分组功能",
@@ -7158,5 +7159,11 @@
71587159
"ToolbarSubTitle": "是按钮或其他应用程序特定工具的容器",
71597160
"NormalTitle": "基本用法",
71607161
"NormalIntro": ""
7162+
},
7163+
"BootstrapBlazor.Server.Components.Samples.OpcDa": {
7164+
"OpcDaTitle": "OpcDa Server 服务",
7165+
"OpcDaDescription": "连接 OpcDa Server 获得 PLC 实时数据",
7166+
"OpcDaNormalTitle": "基本用法",
7167+
"OpcDaNormalIntro": "通过注入服务 <code>IOpcDaServer</code> 获得实例,调用 <code>Read</code> 方法获得 PLC 位号值"
71617168
}
71627169
}

src/BootstrapBlazor.Server/docs.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,8 @@
249249
"socket/auto-connect": "Sockets\\AutoReconnects",
250250
"socket/data-entity": "Sockets\\DataEntities",
251251
"network-monitor": "NetworkMonitors",
252-
"toolbar": "Toolbars"
252+
"toolbar": "Toolbars",
253+
"opc-da": "OpcDa"
253254
},
254255
"video": {
255256
"table": "BV1ap4y1x7Qn?p=1",

0 commit comments

Comments
 (0)