-
-
Notifications
You must be signed in to change notification settings - Fork 385
feat(OpcDa): bump version 10.0.1 #8070
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,10 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the Apache 2.0 License | ||
| // See the LICENSE file in the project root for more information. | ||
| // Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone | ||
|
|
||
| using BootstrapBlazor.OpcDa; | ||
| using System.Globalization; | ||
|
|
||
| namespace BootstrapBlazor.Server.Components.Samples; | ||
|
|
||
|
|
@@ -29,6 +30,8 @@ public partial class OpcDa : ComponentBase | |
| private IOpcSubscription? _subscription; | ||
|
|
||
| private bool _subscribed; | ||
| private CultureInfo? _culture; | ||
| private CultureInfo? _uiCulture; | ||
|
|
||
| private void OnConnect() | ||
| { | ||
|
|
@@ -62,6 +65,8 @@ private void OnRead() | |
| private void OnCreateSubscription() | ||
| { | ||
| _subscribed = true; | ||
| _culture = CultureInfo.CurrentCulture; | ||
| _uiCulture = CultureInfo.CurrentUICulture; | ||
| _subscription = OpcDaServer.CreateSubscription("Subscription1", 1000, true); | ||
| _subscription.DataChanged += UpdateValues; | ||
| _subscription.AddItems([Tag1, Tag2]); | ||
|
Comment on lines
+68
to
72
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): Persisting and globally setting cultures in subscription callbacks can have side effects and is not reverted. The callback captures |
||
|
|
@@ -79,18 +84,30 @@ private void OnCancelSubscription() | |
|
|
||
| private void UpdateValues(List<OpcReadItem> items) | ||
| { | ||
| var value1 = items.Find(i => i.Name == Tag1).Value; | ||
| if (value1 != null) | ||
| { | ||
| _tagValue3 = value1.ToString(); | ||
| } | ||
| var value2 = items.Find(i => i.Name == Tag2).Value; | ||
| if (value2 != null) | ||
| _ = InvokeAsync(() => | ||
|
Comment on lines
84
to
+87
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): Potential null dereference when an expected tag is missing from the subscription update list.
|
||
| { | ||
| _tagValue4 = value2.ToString(); | ||
| } | ||
|
|
||
| InvokeAsync(StateHasChanged); | ||
| if (_culture != null) | ||
| { | ||
| CultureInfo.CurrentCulture = _culture; | ||
| } | ||
| if (_uiCulture != null) | ||
| { | ||
| CultureInfo.CurrentUICulture = _uiCulture; | ||
| } | ||
|
|
||
| var value1 = items.Find(i => i.Name == Tag1).Value; | ||
| if (value1 != null) | ||
| { | ||
| _tagValue3 = value1.ToString(); | ||
| } | ||
| var value2 = items.Find(i => i.Name == Tag2).Value; | ||
| if (value2 != null) | ||
| { | ||
| _tagValue4 = value2.ToString(); | ||
| } | ||
|
|
||
| StateHasChanged(); | ||
| }); | ||
| } | ||
|
|
||
| private List<TreeViewItem<OpcBrowseElement>> _roots = []; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,145 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the Apache 2.0 License | ||
| // See the LICENSE file in the project root for more information. | ||
| // Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone | ||
|
|
||
| namespace BootstrapBlazor.OpcDa; | ||
|
|
||
| /// <summary> | ||
| /// 模拟 OpcDa Server 实现类 | ||
| /// </summary> | ||
| sealed class MockOpcDaServer : IOpcDaServer | ||
| { | ||
| public bool IsConnected { get; set; } | ||
|
|
||
| public string? ServerName { get; set; } | ||
|
|
||
| private readonly Dictionary<string, IOpcSubscription> _subscriptions = []; | ||
|
|
||
| public bool Connect(string serverName) | ||
| { | ||
| ServerName = serverName; | ||
| IsConnected = true; | ||
| return true; | ||
| } | ||
|
|
||
| public void Disconnect() | ||
| { | ||
| IsConnected = false; | ||
| ServerName = null; | ||
| } | ||
|
|
||
| public IOpcSubscription CreateSubscription(string name, int updateRate = 1000, bool active = true) | ||
| { | ||
| if (_subscriptions.TryGetValue(name, out var subscription)) | ||
| { | ||
| CancelSubscription(subscription); | ||
| } | ||
|
|
||
| subscription = new MockOpcDaSubscription(name, updateRate, active); | ||
| _subscriptions.Add(name, subscription); | ||
| return subscription; | ||
| } | ||
|
|
||
| public void CancelSubscription(IOpcSubscription subscription) | ||
| { | ||
| _subscriptions.Remove(subscription.Name); | ||
| if (subscription is IDisposable disposable) | ||
| { | ||
| disposable.Dispose(); | ||
| } | ||
| } | ||
|
|
||
| public HashSet<OpcReadItem> Read(params HashSet<string> items) | ||
| { | ||
| return items.Select(i => new OpcReadItem(i, Quality.Good, DateTime.Now, Random.Shared.Next(1000, 2000))) | ||
| .ToHashSet(OpcItemEqualityComparer<OpcReadItem>.Default); | ||
| } | ||
|
|
||
| public HashSet<OpcWriteItem> Write(params HashSet<OpcWriteItem> items) | ||
| { | ||
| return items.Select(i => new OpcWriteItem(i.Name, i.Value) { Result = true }) | ||
| .ToHashSet(OpcItemEqualityComparer<OpcWriteItem>.Default); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// 浏览 OPC Server 中的位号 (即数据项或者标签) | ||
| /// </summary> | ||
| /// <param name="name"></param> | ||
| /// <param name="filters"></param> | ||
| /// <param name="position"></param> | ||
| /// <returns></returns> | ||
| public OpcBrowseElement[] Browse(string name, OpcBrowseFilters filters, out OpcBrowsePosition? position) | ||
| { | ||
| position = null; | ||
| if (string.IsNullOrEmpty(name)) | ||
| { | ||
| return [ | ||
| new OpcBrowseElement() | ||
| { | ||
| Name ="Channel1", | ||
| ItemName = "Channel1", | ||
| IsItem = false, | ||
| HasChildren = true | ||
| }, | ||
| new OpcBrowseElement() | ||
| { | ||
| Name ="Channel2", | ||
| ItemName = "Channel2", | ||
| IsItem = false, | ||
| HasChildren = true | ||
| } | ||
| ]; | ||
| } | ||
|
|
||
| if (name == "Channel1") | ||
| { | ||
| return [ | ||
| new OpcBrowseElement() | ||
| { | ||
| Name ="Device1", | ||
| ItemName = "Channel1.Device1", | ||
| IsItem = false, | ||
| HasChildren = true | ||
| } | ||
| ]; | ||
| } | ||
|
|
||
| if (name == "Channel1.Device1") | ||
| { | ||
| return [ | ||
| new OpcBrowseElement() | ||
| { | ||
| Name ="Tag1", | ||
| ItemName = "Channel1.Device1.Tag1", | ||
| IsItem = true, | ||
| HasChildren = false | ||
| }, | ||
| new OpcBrowseElement() | ||
| { | ||
| Name ="Tag2", | ||
| ItemName = "Channel1.Device1.Tag2", | ||
| IsItem = true, | ||
| HasChildren = false | ||
| } | ||
| ]; | ||
| } | ||
|
|
||
| return []; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// 浏览 OPC Server 中的位号 (即数据项或者标签) | ||
| /// </summary> | ||
| /// <param name="position"></param> | ||
| /// <returns></returns> | ||
| public OpcBrowseElement[] BrowseNext(OpcBrowsePosition position) | ||
| { | ||
| return []; | ||
| } | ||
|
|
||
| public void Dispose() | ||
| { | ||
|
|
||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.