From a8c9fefbced334aea6e6b010863f38876bb01cbd Mon Sep 17 00:00:00 2001 From: luosheng Date: Wed, 1 Mar 2023 09:36:07 +0800 Subject: [PATCH] Change log system --- Libraries/h-opc/ClientUtils.cs | 178 +-- Libraries/h-opc/Common/ClientExtensions.cs | 50 +- Libraries/h-opc/Common/IClient.cs | 166 +-- Libraries/h-opc/Common/Node.cs | 80 +- Libraries/h-opc/Common/OpcException.cs | 116 +- Libraries/h-opc/Common/OpcStatus.cs | 24 +- Libraries/h-opc/Common/Quality.cs | 38 +- Libraries/h-opc/Common/ReadEvent.cs | 48 +- Libraries/h-opc/NodeExtensions.cs | 28 +- Libraries/h-opc/UaClient.cs | 1172 ++++++++--------- Libraries/h-opc/UaClientOptions.cs | 223 ++-- Libraries/h-opc/UaNode.cs | 38 +- Modbus.Net/.editorconfig | 226 ++++ .../AddressTranslatorNA200H.cs | 6 +- .../Modbus.Net.Modbus.NA200H.csproj | 2 +- .../Modbus.Net.Modbus.csproj | 2 +- .../ModbusAsciiProtocolLinker.cs | 2 +- .../Modbus.Net.Modbus/ModbusProtocol.cs | 54 +- .../ModbusProtocolLinkerBytesExtend.cs | 6 +- .../ModbusRtuProtocolLinker.cs | 2 +- .../ModbusTcpProtocolLinker.cs | 2 +- Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs | 158 +-- Modbus.Net/Modbus.Net.OPC/ClientExtend.cs | 6 +- .../Modbus.Net.OPC/Modbus.Net.OPC.csproj | 2 +- Modbus.Net/Modbus.Net.OPC/OpcConnector.cs | 25 +- Modbus.Net/Modbus.Net.OPC/OpcProtocol.cs | 4 +- .../Modbus.Net.OPC/OpcProtocolLinker.cs | 2 +- Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs | 1 - Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs | 8 +- Modbus.Net/Modbus.Net.OPC/OpcUtility.cs | 10 +- .../AddressTranslatorSiemens.cs | 1 - .../Modbus.Net.Siemens.csproj | 2 +- .../Modbus.Net.Siemens/SiemensPpiProtocol.cs | 4 +- .../Modbus.Net.Siemens/SiemensProtocol.cs | 80 +- .../SiemensProtocolLinkerBytesExtend.cs | 8 +- .../Modbus.Net.Siemens/SiemensTcpProtocol.cs | 4 +- .../SiemensTcpProtocolLinker.cs | 2 +- .../Modbus.Net.Siemens/SiemensUtility.cs | 134 +- .../Modbus.Net/Connector/BaseConnector.cs | 28 +- .../Modbus.Net/Connector/ComConnector.cs | 63 +- .../Modbus.Net/Connector/MessageEventArgs.cs | 4 +- .../Modbus.Net/Connector/TcpConnector.cs | 46 +- .../Modbus.Net/Connector/UdpConnector.cs | 42 +- .../Modbus.Net/Controller/BaseController.cs | 10 +- .../Modbus.Net/Controller/FifoController.cs | 16 +- .../Modbus.Net/Controller/MatchController.cs | 4 +- .../Job/JobChainingJobListenerWithDataMap.cs | 10 +- .../Modbus.Net/Job/MachineJobScheduler.cs | 13 +- .../Modbus.Net/Linker/ComProtocolLinker.cs | 6 +- .../Modbus.Net/Linker/TcpProtocolLinker.cs | 6 +- .../Modbus.Net/Linker/UdpProtocolLinker.cs | 4 +- Modbus.Net/Modbus.Net/Log/LogProvider.cs | 43 + .../Modbus.Net/Machine/AddressCombiner.cs | 24 +- Modbus.Net/Modbus.Net/Machine/BaseMachine.cs | 174 +-- .../Modbus.Net/Machine/BaseMachineExtend.cs | 4 +- Modbus.Net/Modbus.Net/Modbus.Net.csproj | 6 +- Modbus.Net/Modbus.Net/Protocol/PipeUnit.cs | 2 +- .../Modbus.Net/Protocol/ProtocolLinker.cs | 2 +- Modbus.Net/Modbus.Net/Utility/BaseUtility.cs | 16 +- Modbus.Net/Modbus.Net/Value/CRC16.cs | 8 +- Modbus.Net/Modbus.Net/Value/ValueHelper.cs | 492 +++---- Samples/AnyType/Controllers/HomeController.cs | 18 +- Samples/AnyType/Models/TaskViewModel.cs | 7 +- Samples/CrossLamp/Models/Lamp.cs | 7 +- Samples/MachineJob/ConsoleLogProvider.cs | 30 + Samples/MachineJob/DatabaseWrite.cs | 3 +- Samples/MachineJob/MachineJob.csproj | 3 + .../20230212103438_InitialCreate.cs | 3 +- Samples/MachineJob/Program.cs | 21 + Samples/MachineJob/Worker.cs | 27 +- Samples/MachineJob/appsettings.json | 9 +- .../TripleAdd/Models/TripleAddViewModel.cs | 7 +- .../Modbus.Net.PersistedTests.csproj | 4 +- Tests/Modbus.Net.PersistedTests/Program.cs | 35 +- Tests/Modbus.Net.Tests/BaseTest.cs | 5 +- Tests/Modbus.Net.Tests/EndianTest.cs | 7 +- Tests/Modbus.Net.Tests/MachineMethodTest.cs | 8 +- .../ModbusMultiStationTest.cs | 6 +- Tests/Modbus.Net.Tests/ModbusTest.cs | 5 +- Tests/Modbus.Net.Tests/SiemensTest.cs | 6 +- 80 files changed, 2227 insertions(+), 1921 deletions(-) create mode 100644 Modbus.Net/.editorconfig create mode 100644 Modbus.Net/Modbus.Net/Log/LogProvider.cs create mode 100644 Samples/MachineJob/ConsoleLogProvider.cs diff --git a/Libraries/h-opc/ClientUtils.cs b/Libraries/h-opc/ClientUtils.cs index 6eaaf46..493cc48 100644 --- a/Libraries/h-opc/ClientUtils.cs +++ b/Libraries/h-opc/ClientUtils.cs @@ -1,100 +1,100 @@ -using System.Linq; -using Opc.Ua; -using System; +using Opc.Ua; using Opc.Ua.Client; +using System; +using System.Linq; namespace Hylasoft.Opc.Ua { - /// - /// List of static utility methods - /// - internal static class ClientUtils - { - // TODO I didn't write these methods. I should rewrite it once I understand whtat it does, beacuse it looks crazy - - public static EndpointDescription SelectEndpoint(Uri discoveryUrl, bool useSecurity) + /// + /// List of static utility methods + /// + internal static class ClientUtils { - var configuration = EndpointConfiguration.Create(); - configuration.OperationTimeout = 5000; - EndpointDescription endpointDescription1 = null; - using (var discoveryClient = DiscoveryClient.Create(discoveryUrl, configuration)) - { - var endpoints = discoveryClient.GetEndpoints(null); - foreach (var endpointDescription2 in endpoints.Where(endpointDescription2 => endpointDescription2.EndpointUrl.StartsWith(discoveryUrl.Scheme))) - { - if (useSecurity) - { - if (endpointDescription2.SecurityMode == MessageSecurityMode.None) - continue; - } - else if (endpointDescription2.SecurityMode != MessageSecurityMode.None) - continue; - if (endpointDescription1 == null) - endpointDescription1 = endpointDescription2; - if (endpointDescription2.SecurityLevel > endpointDescription1.SecurityLevel) - endpointDescription1 = endpointDescription2; - } - if (endpointDescription1 == null) - { - if (endpoints.Count > 0) - endpointDescription1 = endpoints[0]; - } - } - var uri = Utils.ParseUri(endpointDescription1.EndpointUrl); - if (uri != null && uri.Scheme == discoveryUrl.Scheme) - endpointDescription1.EndpointUrl = new UriBuilder(uri) - { - Host = discoveryUrl.DnsSafeHost, - Port = discoveryUrl.Port - }.ToString(); - return endpointDescription1; - } + // TODO I didn't write these methods. I should rewrite it once I understand whtat it does, beacuse it looks crazy - public static ReferenceDescriptionCollection Browse(Session session, NodeId nodeId) - { - var desc = new BrowseDescription - { - NodeId = nodeId, - BrowseDirection = BrowseDirection.Forward, - IncludeSubtypes = true, - NodeClassMask = 0U, - ResultMask = 63U, - }; - return Browse(session, desc, true); - } - - public static ReferenceDescriptionCollection Browse(Session session, BrowseDescription nodeToBrowse, bool throwOnError) - { - try - { - var descriptionCollection = new ReferenceDescriptionCollection(); - var nodesToBrowse = new BrowseDescriptionCollection { nodeToBrowse }; - BrowseResultCollection results; - DiagnosticInfoCollection diagnosticInfos; - session.Browse(null, null, 0U, nodesToBrowse, out results, out diagnosticInfos); - ClientBase.ValidateResponse(results, nodesToBrowse); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); - while (!StatusCode.IsBad(results[0].StatusCode)) + public static EndpointDescription SelectEndpoint(Uri discoveryUrl, bool useSecurity) { - for (var index = 0; index < results[0].References.Count; ++index) - descriptionCollection.Add(results[0].References[index]); - if (results[0].References.Count == 0 || results[0].ContinuationPoint == null) - return descriptionCollection; - var continuationPoints = new ByteStringCollection(); - continuationPoints.Add(results[0].ContinuationPoint); - session.BrowseNext(null, false, continuationPoints, out results, out diagnosticInfos); - ClientBase.ValidateResponse(results, continuationPoints); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, continuationPoints); + var configuration = EndpointConfiguration.Create(); + configuration.OperationTimeout = 5000; + EndpointDescription endpointDescription1 = null; + using (var discoveryClient = DiscoveryClient.Create(discoveryUrl, configuration)) + { + var endpoints = discoveryClient.GetEndpoints(null); + foreach (var endpointDescription2 in endpoints.Where(endpointDescription2 => endpointDescription2.EndpointUrl.StartsWith(discoveryUrl.Scheme))) + { + if (useSecurity) + { + if (endpointDescription2.SecurityMode == MessageSecurityMode.None) + continue; + } + else if (endpointDescription2.SecurityMode != MessageSecurityMode.None) + continue; + if (endpointDescription1 == null) + endpointDescription1 = endpointDescription2; + if (endpointDescription2.SecurityLevel > endpointDescription1.SecurityLevel) + endpointDescription1 = endpointDescription2; + } + if (endpointDescription1 == null) + { + if (endpoints.Count > 0) + endpointDescription1 = endpoints[0]; + } + } + var uri = Utils.ParseUri(endpointDescription1.EndpointUrl); + if (uri != null && uri.Scheme == discoveryUrl.Scheme) + endpointDescription1.EndpointUrl = new UriBuilder(uri) + { + Host = discoveryUrl.DnsSafeHost, + Port = discoveryUrl.Port + }.ToString(); + return endpointDescription1; + } + + public static ReferenceDescriptionCollection Browse(Session session, NodeId nodeId) + { + var desc = new BrowseDescription + { + NodeId = nodeId, + BrowseDirection = BrowseDirection.Forward, + IncludeSubtypes = true, + NodeClassMask = 0U, + ResultMask = 63U, + }; + return Browse(session, desc, true); + } + + public static ReferenceDescriptionCollection Browse(Session session, BrowseDescription nodeToBrowse, bool throwOnError) + { + try + { + var descriptionCollection = new ReferenceDescriptionCollection(); + var nodesToBrowse = new BrowseDescriptionCollection { nodeToBrowse }; + BrowseResultCollection results; + DiagnosticInfoCollection diagnosticInfos; + session.Browse(null, null, 0U, nodesToBrowse, out results, out diagnosticInfos); + ClientBase.ValidateResponse(results, nodesToBrowse); + ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); + while (!StatusCode.IsBad(results[0].StatusCode)) + { + for (var index = 0; index < results[0].References.Count; ++index) + descriptionCollection.Add(results[0].References[index]); + if (results[0].References.Count == 0 || results[0].ContinuationPoint == null) + return descriptionCollection; + var continuationPoints = new ByteStringCollection(); + continuationPoints.Add(results[0].ContinuationPoint); + session.BrowseNext(null, false, continuationPoints, out results, out diagnosticInfos); + ClientBase.ValidateResponse(results, continuationPoints); + ClientBase.ValidateDiagnosticInfos(diagnosticInfos, continuationPoints); + } + throw new ServiceResultException(results[0].StatusCode); + } + catch (Exception ex) + { + if (throwOnError) + throw new ServiceResultException(ex, 2147549184U); + return null; + } } - throw new ServiceResultException(results[0].StatusCode); - } - catch (Exception ex) - { - if (throwOnError) - throw new ServiceResultException(ex, 2147549184U); - return null; - } } - } } diff --git a/Libraries/h-opc/Common/ClientExtensions.cs b/Libraries/h-opc/Common/ClientExtensions.cs index afa4f63..6ff6549 100644 --- a/Libraries/h-opc/Common/ClientExtensions.cs +++ b/Libraries/h-opc/Common/ClientExtensions.cs @@ -2,33 +2,33 @@ namespace Hylasoft.Opc.Common { - /// - /// Useful extension methods for OPC Clients - /// - public static class ClientExtensions - { /// - /// Reads a tag from the OPC. If for whatever reason the read fails (Tag doesn't exist, server not available) returns a default value + /// Useful extension methods for OPC Clients /// - /// the opc client to use for the read - /// The fully qualified identifier of the tag - /// the default value to read if the read fails - /// - public static ReadEvent ReadOrdefault(this IClient client, string tag, T defaultValue = default(T)) + public static class ClientExtensions { - try - { - return client.Read(tag); - } - catch (OpcException) - { - var readEvent = new ReadEvent(); - readEvent.Quality = Quality.Good; - readEvent.Value = defaultValue; - readEvent.SourceTimestamp = DateTime.Now; - readEvent.ServerTimestamp = DateTime.Now; - return readEvent; - } + /// + /// Reads a tag from the OPC. If for whatever reason the read fails (Tag doesn't exist, server not available) returns a default value + /// + /// the opc client to use for the read + /// The fully qualified identifier of the tag + /// the default value to read if the read fails + /// + public static ReadEvent ReadOrdefault(this IClient client, string tag, T defaultValue = default(T)) + { + try + { + return client.Read(tag); + } + catch (OpcException) + { + var readEvent = new ReadEvent(); + readEvent.Quality = Quality.Good; + readEvent.Value = defaultValue; + readEvent.SourceTimestamp = DateTime.Now; + readEvent.ServerTimestamp = DateTime.Now; + return readEvent; + } + } } - } } \ No newline at end of file diff --git a/Libraries/h-opc/Common/IClient.cs b/Libraries/h-opc/Common/IClient.cs index 6edaa7c..f09d405 100644 --- a/Libraries/h-opc/Common/IClient.cs +++ b/Libraries/h-opc/Common/IClient.cs @@ -4,100 +4,100 @@ using System.Threading.Tasks; namespace Hylasoft.Opc.Common { - /// - /// Client interface to perform basic Opc tasks, like discovery, monitoring, reading/writing tags, - /// - public interface IClient : IDisposable + /// + /// Client interface to perform basic Opc tasks, like discovery, monitoring, reading/writing tags, + /// + public interface IClient : IDisposable where TNode : Node - { - /// - /// Connect the client to the OPC Server - /// - Task Connect(); + { + /// + /// Connect the client to the OPC Server + /// + Task Connect(); - /// - /// Gets the current status of the OPC Client - /// - OpcStatus Status { get; } + /// + /// Gets the current status of the OPC Client + /// + OpcStatus Status { get; } - /// - /// Gets the datatype of an OPC tag - /// - /// Tag to get datatype of - /// System Type - System.Type GetDataType(string tag); + /// + /// Gets the datatype of an OPC tag + /// + /// Tag to get datatype of + /// System Type + System.Type GetDataType(string tag); - /// - /// Read a tag - /// - /// The type of tag to read - /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. - /// E.g: the tag `foo.bar` reads the tag `bar` on the folder `foo` - /// The value retrieved from the OPC - ReadEvent Read(string tag); + /// + /// Read a tag + /// + /// The type of tag to read + /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. + /// E.g: the tag `foo.bar` reads the tag `bar` on the folder `foo` + /// The value retrieved from the OPC + ReadEvent Read(string tag); - /// - /// Write a value on the specified opc tag - /// - /// The type of tag to write on - /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. - /// E.g: the tag `foo.bar` writes on the tag `bar` on the folder `foo` - /// - void Write(string tag, T item); + /// + /// Write a value on the specified opc tag + /// + /// The type of tag to write on + /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. + /// E.g: the tag `foo.bar` writes on the tag `bar` on the folder `foo` + /// + void Write(string tag, T item); - /// - /// Monitor the specified tag for changes - /// - /// the type of tag to monitor - /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. - /// E.g: the tag `foo.bar` monitors the tag `bar` on the folder `foo` - /// the callback to execute when the value is changed. - /// The first parameter is the new value of the node, the second is an `unsubscribe` function to unsubscribe the callback - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an async method.")] - void Monitor(string tag, Action, Action> callback); + /// + /// Monitor the specified tag for changes + /// + /// the type of tag to monitor + /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. + /// E.g: the tag `foo.bar` monitors the tag `bar` on the folder `foo` + /// the callback to execute when the value is changed. + /// The first parameter is the new value of the node, the second is an `unsubscribe` function to unsubscribe the callback + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an async method.")] + void Monitor(string tag, Action, Action> callback); - /// - /// Finds a node on the Opc Server - /// - /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. - /// E.g: the tag `foo.bar` finds the tag `bar` on the folder `foo` - /// If there is a tag, it returns it, otherwise it throws an - TNode FindNode(string tag); + /// + /// Finds a node on the Opc Server + /// + /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. + /// E.g: the tag `foo.bar` finds the tag `bar` on the folder `foo` + /// If there is a tag, it returns it, otherwise it throws an + TNode FindNode(string tag); - /// - /// Gets the root node of the server - /// - TNode RootNode { get; } + /// + /// Gets the root node of the server + /// + TNode RootNode { get; } - /// - /// Explore a folder on the Opc Server - /// - /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. - /// E.g: the tag `foo.bar` finds the sub nodes of `bar` on the folder `foo` - /// The list of sub-nodes - IEnumerable ExploreFolder(string tag); + /// + /// Explore a folder on the Opc Server + /// + /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. + /// E.g: the tag `foo.bar` finds the sub nodes of `bar` on the folder `foo` + /// The list of sub-nodes + IEnumerable ExploreFolder(string tag); - /// - /// Read a tag asynchronusly - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an async method.")] - Task> ReadAsync(string tag); + /// + /// Read a tag asynchronusly + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an async method.")] + Task> ReadAsync(string tag); - /// - /// Write a value on the specified opc tag asynchronously - /// - Task WriteAsync(string tag, T item); + /// + /// Write a value on the specified opc tag asynchronously + /// + Task WriteAsync(string tag, T item); - /// - /// Finds a node on the Opc Server asynchronously - /// - Task FindNodeAsync(string tag); + /// + /// Finds a node on the Opc Server asynchronously + /// + Task FindNodeAsync(string tag); - /// - /// Explore a folder on the Opc Server asynchronously - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", - Justification = "Task")] - Task> ExploreFolderAsync(string tag); - } + /// + /// Explore a folder on the Opc Server asynchronously + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", + Justification = "Task")] + Task> ExploreFolderAsync(string tag); + } } \ No newline at end of file diff --git a/Libraries/h-opc/Common/Node.cs b/Libraries/h-opc/Common/Node.cs index 41ea03c..ae6750f 100644 --- a/Libraries/h-opc/Common/Node.cs +++ b/Libraries/h-opc/Common/Node.cs @@ -1,48 +1,46 @@ -using System.Collections.Generic; - -namespace Hylasoft.Opc.Common +namespace Hylasoft.Opc.Common { - /// - /// Base class representing a node on the OPC server - /// - public abstract class Node - { /// - /// Gets the displayed name of the node + /// Base class representing a node on the OPC server /// - public string Name { get; protected set; } - - /// - /// Gets the dot-separated fully qualified tag of the node - /// - public string Tag { get; protected set; } - - /// - /// Gets the parent node. If the node is root, returns null - /// - public Node Parent { get; private set; } - - /// - /// Creates a new node - /// - /// the name of the node - /// The parent node - protected Node(string name, Node parent = null) + public abstract class Node { - Name = name; - Parent = parent; - if (parent != null && !string.IsNullOrEmpty(parent.Tag)) - Tag = parent.Tag + '.' + name; - else - Tag = name; - } + /// + /// Gets the displayed name of the node + /// + public string Name { get; protected set; } - /// - /// Overrides ToString() - /// - public override string ToString() - { - return Tag; + /// + /// Gets the dot-separated fully qualified tag of the node + /// + public string Tag { get; protected set; } + + /// + /// Gets the parent node. If the node is root, returns null + /// + public Node Parent { get; private set; } + + /// + /// Creates a new node + /// + /// the name of the node + /// The parent node + protected Node(string name, Node parent = null) + { + Name = name; + Parent = parent; + if (parent != null && !string.IsNullOrEmpty(parent.Tag)) + Tag = parent.Tag + '.' + name; + else + Tag = name; + } + + /// + /// Overrides ToString() + /// + public override string ToString() + { + return Tag; + } } - } } diff --git a/Libraries/h-opc/Common/OpcException.cs b/Libraries/h-opc/Common/OpcException.cs index 90053e2..67e0ae7 100644 --- a/Libraries/h-opc/Common/OpcException.cs +++ b/Libraries/h-opc/Common/OpcException.cs @@ -4,67 +4,67 @@ using System.Runtime.Serialization; namespace Hylasoft.Opc.Common { - /// - /// Identifies an exception occurred during OPC Communication - /// - [Serializable] - public class OpcException : Exception - { /// - /// Initialize a new instance of the OpcException class + /// Identifies an exception occurred during OPC Communication /// - public OpcException() + [Serializable] + public class OpcException : Exception { + /// + /// Initialize a new instance of the OpcException class + /// + public OpcException() + { + } + + /// + /// Initialize a new instance of the OpcException class + /// + public OpcException(string message) + : base(message) + { + } + + /// + /// Returns an (optional) associated OPC UA StatusCode for the exception. + /// + public StatusCode? Status { get; private set; } + + /// + /// Initialize a new instance of the OpcException class + /// + public OpcException(string message, StatusCode status) + : base(message) + { + Status = status; + } + + /// + /// Initialize a new instance of the OpcException class + /// + public OpcException(string message, Exception inner) + : base(message, inner) + { + } + + /// + /// Initialize a new instance of the OpcException class + /// + protected OpcException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + + /// + /// Sets the System.Runtime.Serialization.SerializationInfo with information about the exception. + /// + /// The System.Runtime.Serialization.SerializationInfo that holds the serialized object data about the exception being thrown. + /// The System.Runtime.Serialization.StreamingContext that contains contextual information about the source or destination. + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + } + } - /// - /// Initialize a new instance of the OpcException class - /// - public OpcException(string message) - : base(message) - { - } - - /// - /// Returns an (optional) associated OPC UA StatusCode for the exception. - /// - public StatusCode? Status { get; private set; } - - /// - /// Initialize a new instance of the OpcException class - /// - public OpcException(string message, StatusCode status) - : base(message) - { - Status = status; - } - - /// - /// Initialize a new instance of the OpcException class - /// - public OpcException(string message, Exception inner) - : base(message, inner) - { - } - - /// - /// Initialize a new instance of the OpcException class - /// - protected OpcException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - - /// - /// Sets the System.Runtime.Serialization.SerializationInfo with information about the exception. - /// - /// The System.Runtime.Serialization.SerializationInfo that holds the serialized object data about the exception being thrown. - /// The System.Runtime.Serialization.StreamingContext that contains contextual information about the source or destination. - public override void GetObjectData(SerializationInfo info, StreamingContext context) - { - base.GetObjectData(info, context); - } - - } - } \ No newline at end of file diff --git a/Libraries/h-opc/Common/OpcStatus.cs b/Libraries/h-opc/Common/OpcStatus.cs index 2413cfe..3534d4a 100644 --- a/Libraries/h-opc/Common/OpcStatus.cs +++ b/Libraries/h-opc/Common/OpcStatus.cs @@ -1,18 +1,18 @@ namespace Hylasoft.Opc.Common { - /// - /// Identifies the status of an OPC connector - /// - public enum OpcStatus - { /// - /// The client is not connected + /// Identifies the status of an OPC connector /// - NotConnected, + public enum OpcStatus + { + /// + /// The client is not connected + /// + NotConnected, - /// - /// The client is connected - /// - Connected - } + /// + /// The client is connected + /// + Connected + } } \ No newline at end of file diff --git a/Libraries/h-opc/Common/Quality.cs b/Libraries/h-opc/Common/Quality.cs index 759702e..b9bfcc9 100644 --- a/Libraries/h-opc/Common/Quality.cs +++ b/Libraries/h-opc/Common/Quality.cs @@ -2,27 +2,27 @@ namespace Hylasoft.Opc.Common { - /// - /// Represents the quality of the value captured - /// - public enum Quality - { /// - /// Quality: Unknown, the value of the quality could not be inferred by the library + /// Represents the quality of the value captured /// - [Description("Unknown")] - Unknown, + public enum Quality + { + /// + /// Quality: Unknown, the value of the quality could not be inferred by the library + /// + [Description("Unknown")] + Unknown, - /// - /// Quality: Good - /// - [Description("Good")] - Good, + /// + /// Quality: Good + /// + [Description("Good")] + Good, - /// - /// Quality: Bad - /// - [Description("Bad")] - Bad - } + /// + /// Quality: Bad + /// + [Description("Bad")] + Bad + } } \ No newline at end of file diff --git a/Libraries/h-opc/Common/ReadEvent.cs b/Libraries/h-opc/Common/ReadEvent.cs index 6728b5c..78e8ffa 100644 --- a/Libraries/h-opc/Common/ReadEvent.cs +++ b/Libraries/h-opc/Common/ReadEvent.cs @@ -1,37 +1,33 @@ using System; -using System.Collections.Generic; using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Hylasoft.Opc.Common { - /// - /// Base class representing a monitor event on the OPC server - /// - /// - public class ReadEvent - { /// - /// Gets the value that was read from the server + /// Base class representing a monitor event on the OPC server /// - public T Value { get; set; } + /// + public class ReadEvent + { + /// + /// Gets the value that was read from the server + /// + public T Value { get; set; } - /// - /// Gets the quality of the signal from the server - /// - [DefaultValue(Common.Quality.Unknown)] - public Quality Quality { get; set; } + /// + /// Gets the quality of the signal from the server + /// + [DefaultValue(Common.Quality.Unknown)] + public Quality Quality { get; set; } - /// - /// Gets the source timestamp on when the event ocurred - /// - public DateTime SourceTimestamp { get; set; } + /// + /// Gets the source timestamp on when the event ocurred + /// + public DateTime SourceTimestamp { get; set; } - /// - /// Gets the server timestamp on when the event ocurred - /// - public DateTime ServerTimestamp { get; set; } - } + /// + /// Gets the server timestamp on when the event ocurred + /// + public DateTime ServerTimestamp { get; set; } + } } diff --git a/Libraries/h-opc/NodeExtensions.cs b/Libraries/h-opc/NodeExtensions.cs index 85f2bf0..8913f4b 100644 --- a/Libraries/h-opc/NodeExtensions.cs +++ b/Libraries/h-opc/NodeExtensions.cs @@ -3,22 +3,22 @@ using OpcF = Opc.Ua; namespace Hylasoft.Opc.Ua { - /// - /// Class with extension methods for OPC UA - /// - public static class NodeExtensions - { /// - /// Converts an OPC Foundation node to an Hylasoft OPC UA Node + /// Class with extension methods for OPC UA /// - /// The node to convert - /// the parent node (optional) - /// - internal static UaNode ToHylaNode(this OpcF.ReferenceDescription node, Node parent = null) + public static class NodeExtensions { - var name = node.DisplayName.ToString(); - var nodeId = node.NodeId.ToString(); - return new UaNode(name, nodeId, parent); + /// + /// Converts an OPC Foundation node to an Hylasoft OPC UA Node + /// + /// The node to convert + /// the parent node (optional) + /// + internal static UaNode ToHylaNode(this OpcF.ReferenceDescription node, Node parent = null) + { + var name = node.DisplayName.ToString(); + var nodeId = node.NodeId.ToString(); + return new UaNode(name, nodeId, parent); + } } - } } \ No newline at end of file diff --git a/Libraries/h-opc/UaClient.cs b/Libraries/h-opc/UaClient.cs index 030d3dd..29b6100 100644 --- a/Libraries/h-opc/UaClient.cs +++ b/Libraries/h-opc/UaClient.cs @@ -9,638 +9,638 @@ using System.Threading.Tasks; namespace Hylasoft.Opc.Ua { - /// - /// Client Implementation for UA - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", + /// + /// Client Implementation for UA + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "Doesn't make sense to split this class")] - public class UaClient : IClient - { - private readonly UaClientOptions _options = new UaClientOptions(); - private readonly Uri _serverUrl; - private Session _session; - - private readonly IDictionary _nodesCache = new Dictionary(); - private readonly IDictionary> _folderCache = new Dictionary>(); - - /// - /// Creates a server object - /// - /// the url of the server to connect to - public UaClient(Uri serverUrl) + public class UaClient : IClient { - _serverUrl = serverUrl; - Status = OpcStatus.NotConnected; - } + private readonly UaClientOptions _options = new UaClientOptions(); + private readonly Uri _serverUrl; + private Session _session; - /// - /// Creates a server object - /// - /// the url of the server to connect to - /// custom options to use with ua client - public UaClient(Uri serverUrl, UaClientOptions options) - { - _serverUrl = serverUrl; - _options = options; - Status = OpcStatus.NotConnected; - } + private readonly IDictionary _nodesCache = new Dictionary(); + private readonly IDictionary> _folderCache = new Dictionary>(); - /// - /// Options to configure the UA client session - /// - public UaClientOptions Options - { - get { return _options; } - } - - /// - /// OPC Foundation underlying session object - /// - protected Session Session - { - get - { - return _session; - } - } - - private void PostInitializeSession() - { - var node = _session.NodeCache.Find(ObjectIds.ObjectsFolder); - RootNode = new UaNode(string.Empty, node.NodeId.ToString()); - AddNodeToCache(RootNode); - Status = OpcStatus.Connected; - } - - /// - /// Connect the client to the OPC Server - /// - public async Task Connect() - { - if (Status == OpcStatus.Connected) - return; - _session = await InitializeSession(_serverUrl); - _session.KeepAlive += SessionKeepAlive; - _session.SessionClosing += SessionClosing; - PostInitializeSession(); - } - - /// - /// Gets the datatype of an OPC tag - /// - /// Tag to get datatype of - /// System Type - public System.Type GetDataType(string tag) - { - var nodesToRead = BuildReadValueIdCollection(tag, Attributes.Value); - DataValueCollection results; - DiagnosticInfoCollection diag; - _session.Read( - requestHeader: null, - maxAge: 0, - timestampsToReturn: TimestampsToReturn.Neither, - nodesToRead: nodesToRead, - results: out results, - diagnosticInfos: out diag); - var type = results[0].WrappedValue.TypeInfo.BuiltInType; - return System.Type.GetType("System." + type.ToString()); - } - - private void SessionKeepAlive(ISession session, KeepAliveEventArgs e) - { - if (e.CurrentState != ServerState.Running) - { - if (Status == OpcStatus.Connected) + /// + /// Creates a server object + /// + /// the url of the server to connect to + public UaClient(Uri serverUrl) { - Status = OpcStatus.NotConnected; - NotifyServerConnectionLost(); + _serverUrl = serverUrl; + Status = OpcStatus.NotConnected; } - } - else if (e.CurrentState == ServerState.Running) - { - if (Status == OpcStatus.NotConnected) + + /// + /// Creates a server object + /// + /// the url of the server to connect to + /// custom options to use with ua client + public UaClient(Uri serverUrl, UaClientOptions options) { - Status = OpcStatus.Connected; - NotifyServerConnectionRestored(); + _serverUrl = serverUrl; + _options = options; + Status = OpcStatus.NotConnected; } - } - } - private void SessionClosing(object sender, EventArgs e) - { - Status = OpcStatus.NotConnected; - NotifyServerConnectionLost(); - } + /// + /// Options to configure the UA client session + /// + public UaClientOptions Options + { + get { return _options; } + } + /// + /// OPC Foundation underlying session object + /// + protected Session Session + { + get + { + return _session; + } + } - /// - /// Reconnect the OPC session - /// - public void ReConnect() - { - Status = OpcStatus.NotConnected; - _session.Reconnect(); - Status = OpcStatus.Connected; - } + private void PostInitializeSession() + { + var node = _session.NodeCache.Find(ObjectIds.ObjectsFolder); + RootNode = new UaNode(string.Empty, node.NodeId.ToString()); + AddNodeToCache(RootNode); + Status = OpcStatus.Connected; + } - /// - /// Create a new OPC session, based on the current session parameters. - /// - public void RecreateSession() - { - Status = OpcStatus.NotConnected; - _session = Session.Recreate(_session); - PostInitializeSession(); - } + /// + /// Connect the client to the OPC Server + /// + public async Task Connect() + { + if (Status == OpcStatus.Connected) + return; + _session = await InitializeSession(_serverUrl); + _session.KeepAlive += SessionKeepAlive; + _session.SessionClosing += SessionClosing; + PostInitializeSession(); + } - - /// - /// Gets the current status of the OPC Client - /// - public OpcStatus Status { get; private set; } - - - private ReadValueIdCollection BuildReadValueIdCollection(string tag, uint attributeId) - { - var n = FindNode(tag, RootNode); - var readValue = new ReadValueId - { - NodeId = n.NodeId, - AttributeId = attributeId - }; - return new ReadValueIdCollection { readValue }; - } - - /// - /// Read a tag - /// - /// The type of tag to read - /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. - /// E.g: the tag `foo.bar` reads the tag `bar` on the folder `foo` - /// The value retrieved from the OPC - public ReadEvent Read(string tag) - { - var nodesToRead = BuildReadValueIdCollection(tag, Attributes.Value); - DataValueCollection results; - DiagnosticInfoCollection diag; - _session.Read( - requestHeader: null, - maxAge: 0, - timestampsToReturn: TimestampsToReturn.Neither, - nodesToRead: nodesToRead, - results: out results, - diagnosticInfos: out diag); - var val = results[0]; - - var readEvent = new ReadEvent(); - readEvent.Value = (T)val.Value; - readEvent.SourceTimestamp = val.SourceTimestamp; - readEvent.ServerTimestamp = val.ServerTimestamp; - if (StatusCode.IsGood(val.StatusCode)) readEvent.Quality = Quality.Good; - if (StatusCode.IsBad(val.StatusCode)) readEvent.Quality = Quality.Bad; - return readEvent; - } - - - /// - /// Read a tag asynchronously - /// - /// The type of tag to read - /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. - /// E.g: the tag `foo.bar` reads the tag `bar` on the folder `foo` - /// The value retrieved from the OPC - public Task> ReadAsync(string tag) - { - var nodesToRead = BuildReadValueIdCollection(tag, Attributes.Value); - - // Wrap the ReadAsync logic in a TaskCompletionSource, so we can use C# async/await syntax to call it: - var taskCompletionSource = new TaskCompletionSource>(); - _session.BeginRead( - requestHeader: null, - maxAge: 0, - timestampsToReturn: TimestampsToReturn.Neither, - nodesToRead: nodesToRead, - callback: ar => - { + /// + /// Gets the datatype of an OPC tag + /// + /// Tag to get datatype of + /// System Type + public System.Type GetDataType(string tag) + { + var nodesToRead = BuildReadValueIdCollection(tag, Attributes.Value); DataValueCollection results; DiagnosticInfoCollection diag; - var response = _session.EndRead( - result: ar, + _session.Read( + requestHeader: null, + maxAge: 0, + timestampsToReturn: TimestampsToReturn.Neither, + nodesToRead: nodesToRead, results: out results, diagnosticInfos: out diag); + var type = results[0].WrappedValue.TypeInfo.BuiltInType; + return System.Type.GetType("System." + type.ToString()); + } - try + private void SessionKeepAlive(ISession session, KeepAliveEventArgs e) + { + if (e.CurrentState != ServerState.Running) { - CheckReturnValue(response.ServiceResult); - var val = results[0]; - var readEvent = new ReadEvent(); - readEvent.Value = (T)val.Value; - readEvent.SourceTimestamp = val.SourceTimestamp; - readEvent.ServerTimestamp = val.ServerTimestamp; - if (StatusCode.IsGood(val.StatusCode)) readEvent.Quality = Quality.Good; - if (StatusCode.IsBad(val.StatusCode)) readEvent.Quality = Quality.Bad; - taskCompletionSource.TrySetResult(readEvent); + if (Status == OpcStatus.Connected) + { + Status = OpcStatus.NotConnected; + NotifyServerConnectionLost(); + } } - catch (Exception ex) + else if (e.CurrentState == ServerState.Running) { - taskCompletionSource.TrySetException(ex); + if (Status == OpcStatus.NotConnected) + { + Status = OpcStatus.Connected; + NotifyServerConnectionRestored(); + } } - }, - asyncState: null); + } - return taskCompletionSource.Task; - } + private void SessionClosing(object sender, EventArgs e) + { + Status = OpcStatus.NotConnected; + NotifyServerConnectionLost(); + } - private WriteValueCollection BuildWriteValueCollection(string tag, uint attributeId, object dataValue) - { - var n = FindNode(tag, RootNode); - var writeValue = new WriteValue - { - NodeId = n.NodeId, - AttributeId = attributeId, - Value = { Value = dataValue } - }; - return new WriteValueCollection { writeValue }; - } + /// + /// Reconnect the OPC session + /// + public void ReConnect() + { + Status = OpcStatus.NotConnected; + _session.Reconnect(); + Status = OpcStatus.Connected; + } - /// - /// Write a value on the specified opc tag - /// - /// The type of tag to write on - /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. - /// E.g: the tag `foo.bar` writes on the tag `bar` on the folder `foo` - /// The value for the item to write - public void Write(string tag, T item) - { - var nodesToWrite = BuildWriteValueCollection(tag, Attributes.Value, item); + /// + /// Create a new OPC session, based on the current session parameters. + /// + public void RecreateSession() + { + Status = OpcStatus.NotConnected; + _session = Session.Recreate(_session); + PostInitializeSession(); + } - StatusCodeCollection results; - DiagnosticInfoCollection diag; - _session.Write( - requestHeader: null, - nodesToWrite: nodesToWrite, - results: out results, - diagnosticInfos: out diag); - CheckReturnValue(results[0]); - } + /// + /// Gets the current status of the OPC Client + /// + public OpcStatus Status { get; private set; } - /// - /// Write a value on the specified opc tag asynchronously - /// - /// The type of tag to write on - /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. - /// E.g: the tag `foo.bar` writes on the tag `bar` on the folder `foo` - /// The value for the item to write - public Task WriteAsync(string tag, T item) - { - var nodesToWrite = BuildWriteValueCollection(tag, Attributes.Value, item); - // Wrap the WriteAsync logic in a TaskCompletionSource, so we can use C# async/await syntax to call it: - var taskCompletionSource = new TaskCompletionSource(); - _session.BeginWrite( - requestHeader: null, - nodesToWrite: nodesToWrite, - callback: ar => - { + private ReadValueIdCollection BuildReadValueIdCollection(string tag, uint attributeId) + { + var n = FindNode(tag, RootNode); + var readValue = new ReadValueId + { + NodeId = n.NodeId, + AttributeId = attributeId + }; + return new ReadValueIdCollection { readValue }; + } + + /// + /// Read a tag + /// + /// The type of tag to read + /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. + /// E.g: the tag `foo.bar` reads the tag `bar` on the folder `foo` + /// The value retrieved from the OPC + public ReadEvent Read(string tag) + { + var nodesToRead = BuildReadValueIdCollection(tag, Attributes.Value); + DataValueCollection results; + DiagnosticInfoCollection diag; + _session.Read( + requestHeader: null, + maxAge: 0, + timestampsToReturn: TimestampsToReturn.Neither, + nodesToRead: nodesToRead, + results: out results, + diagnosticInfos: out diag); + var val = results[0]; + + var readEvent = new ReadEvent(); + readEvent.Value = (T)val.Value; + readEvent.SourceTimestamp = val.SourceTimestamp; + readEvent.ServerTimestamp = val.ServerTimestamp; + if (StatusCode.IsGood(val.StatusCode)) readEvent.Quality = Quality.Good; + if (StatusCode.IsBad(val.StatusCode)) readEvent.Quality = Quality.Bad; + return readEvent; + } + + + /// + /// Read a tag asynchronously + /// + /// The type of tag to read + /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. + /// E.g: the tag `foo.bar` reads the tag `bar` on the folder `foo` + /// The value retrieved from the OPC + public Task> ReadAsync(string tag) + { + var nodesToRead = BuildReadValueIdCollection(tag, Attributes.Value); + + // Wrap the ReadAsync logic in a TaskCompletionSource, so we can use C# async/await syntax to call it: + var taskCompletionSource = new TaskCompletionSource>(); + _session.BeginRead( + requestHeader: null, + maxAge: 0, + timestampsToReturn: TimestampsToReturn.Neither, + nodesToRead: nodesToRead, + callback: ar => + { + DataValueCollection results; + DiagnosticInfoCollection diag; + var response = _session.EndRead( + result: ar, + results: out results, + diagnosticInfos: out diag); + + try + { + CheckReturnValue(response.ServiceResult); + var val = results[0]; + var readEvent = new ReadEvent(); + readEvent.Value = (T)val.Value; + readEvent.SourceTimestamp = val.SourceTimestamp; + readEvent.ServerTimestamp = val.ServerTimestamp; + if (StatusCode.IsGood(val.StatusCode)) readEvent.Quality = Quality.Good; + if (StatusCode.IsBad(val.StatusCode)) readEvent.Quality = Quality.Bad; + taskCompletionSource.TrySetResult(readEvent); + } + catch (Exception ex) + { + taskCompletionSource.TrySetException(ex); + } + }, + asyncState: null); + + return taskCompletionSource.Task; + } + + + private WriteValueCollection BuildWriteValueCollection(string tag, uint attributeId, object dataValue) + { + var n = FindNode(tag, RootNode); + var writeValue = new WriteValue + { + NodeId = n.NodeId, + AttributeId = attributeId, + Value = { Value = dataValue } + }; + return new WriteValueCollection { writeValue }; + } + + /// + /// Write a value on the specified opc tag + /// + /// The type of tag to write on + /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. + /// E.g: the tag `foo.bar` writes on the tag `bar` on the folder `foo` + /// The value for the item to write + public void Write(string tag, T item) + { + var nodesToWrite = BuildWriteValueCollection(tag, Attributes.Value, item); + StatusCodeCollection results; DiagnosticInfoCollection diag; - var response = _session.EndWrite( - result: ar, + _session.Write( + requestHeader: null, + nodesToWrite: nodesToWrite, results: out results, diagnosticInfos: out diag); + + CheckReturnValue(results[0]); + } + + /// + /// Write a value on the specified opc tag asynchronously + /// + /// The type of tag to write on + /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. + /// E.g: the tag `foo.bar` writes on the tag `bar` on the folder `foo` + /// The value for the item to write + public Task WriteAsync(string tag, T item) + { + var nodesToWrite = BuildWriteValueCollection(tag, Attributes.Value, item); + + // Wrap the WriteAsync logic in a TaskCompletionSource, so we can use C# async/await syntax to call it: + var taskCompletionSource = new TaskCompletionSource(); + _session.BeginWrite( + requestHeader: null, + nodesToWrite: nodesToWrite, + callback: ar => + { + StatusCodeCollection results; + DiagnosticInfoCollection diag; + var response = _session.EndWrite( + result: ar, + results: out results, + diagnosticInfos: out diag); + try + { + CheckReturnValue(response.ServiceResult); + CheckReturnValue(results[0]); + taskCompletionSource.SetResult(response.ServiceResult); + } + catch (Exception ex) + { + taskCompletionSource.TrySetException(ex); + } + }, + asyncState: null); + return taskCompletionSource.Task; + } + + + /// + /// Monitor the specified tag for changes + /// + /// the type of tag to monitor + /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. + /// E.g: the tag `foo.bar` monitors the tag `bar` on the folder `foo` + /// the callback to execute when the value is changed. + /// The first parameter is a MonitorEvent object which represents the data point, the second is an `unsubscribe` function to unsubscribe the callback + public void Monitor(string tag, Action, Action> callback) + { + var node = FindNode(tag); + + var sub = new Subscription + { + PublishingInterval = _options.DefaultMonitorInterval, + PublishingEnabled = true, + LifetimeCount = _options.SubscriptionLifetimeCount, + KeepAliveCount = _options.SubscriptionKeepAliveCount, + DisplayName = tag, + Priority = byte.MaxValue + }; + + var item = new MonitoredItem + { + StartNodeId = node.NodeId, + AttributeId = Attributes.Value, + DisplayName = tag, + SamplingInterval = _options.DefaultMonitorInterval + }; + sub.AddItem(item); + _session.AddSubscription(sub); + sub.Create(); + sub.ApplyChanges(); + + item.Notification += (monitoredItem, args) => + { + var p = (MonitoredItemNotification)args.NotificationValue; + var t = p.Value.WrappedValue.Value; + Action unsubscribe = () => + { + sub.RemoveItems(sub.MonitoredItems); + sub.Delete(true); + _session.RemoveSubscription(sub); + sub.Dispose(); + }; + + var monitorEvent = new ReadEvent(); + monitorEvent.Value = (T)t; + monitorEvent.SourceTimestamp = p.Value.SourceTimestamp; + monitorEvent.ServerTimestamp = p.Value.ServerTimestamp; + if (StatusCode.IsGood(p.Value.StatusCode)) monitorEvent.Quality = Quality.Good; + if (StatusCode.IsBad(p.Value.StatusCode)) monitorEvent.Quality = Quality.Bad; + callback(monitorEvent, unsubscribe); + }; + } + + /// + /// Explore a folder on the Opc Server + /// + /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. + /// E.g: the tag `foo.bar` finds the sub nodes of `bar` on the folder `foo` + /// The list of sub-nodes + public IEnumerable ExploreFolder(string tag) + { + IList nodes; + _folderCache.TryGetValue(tag, out nodes); + if (nodes != null) + return nodes; + + var folder = FindNode(tag); + nodes = ClientUtils.Browse(_session, folder.NodeId) + .GroupBy(n => n.NodeId) //this is to select distinct + .Select(n => n.First()) + .Where(n => n.NodeClass == NodeClass.Variable || n.NodeClass == NodeClass.Object) + .Select(n => n.ToHylaNode(folder)) + .ToList(); + + //add nodes to cache + if (!_folderCache.ContainsKey(tag)) + _folderCache.Add(tag, nodes); + foreach (var node in nodes) + AddNodeToCache(node); + + return nodes; + } + + /// + /// Explores a folder asynchronously + /// + public async Task> ExploreFolderAsync(string tag) + { + return await Task.Run(() => ExploreFolder(tag)); + } + + /// + /// Finds a node on the Opc Server + /// + /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. + /// E.g: the tag `foo.bar` finds the tag `bar` on the folder `foo` + /// If there is a tag, it returns it, otherwise it throws an + public UaNode FindNode(string tag) + { + // if the tag already exists in cache, return it + if (_nodesCache.ContainsKey(tag)) + return _nodesCache[tag]; + + // try to find the tag otherwise + var found = FindNode(tag, RootNode); + if (found != null) + { + AddNodeToCache(found); + return found; + } + + // throws an exception if not found + throw new OpcException(string.Format("The tag \"{0}\" doesn't exist on the Server", tag)); + } + + /// + /// Find node asynchronously + /// + public async Task FindNodeAsync(string tag) + { + return await Task.Run(() => FindNode(tag)); + } + + /// + /// Gets the root node of the server + /// + public UaNode RootNode { get; private set; } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + if (_session != null) + { + _session.RemoveSubscriptions(_session.Subscriptions.ToList()); + _session.Close(); + _session.Dispose(); + } + GC.SuppressFinalize(this); + } + + private void CheckReturnValue(StatusCode status) + { + if (!StatusCode.IsGood(status)) + throw new OpcException(string.Format("Invalid response from the server. (Response Status: {0})", status), status); + } + + /// + /// Adds a node to the cache using the tag as its key + /// + /// the node to add + private void AddNodeToCache(UaNode node) + { + if (!_nodesCache.ContainsKey(node.Tag)) + _nodesCache.Add(node.Tag, node); + } + + /// + /// Return identity login object for a given URI. + /// + /// Login URI + /// AnonUser or User with name and password + private UserIdentity GetIdentity(Uri url) + { + if (_options.UserIdentity != null) + { + return _options.UserIdentity; + } + var uriLogin = new UserIdentity(); + if (!string.IsNullOrEmpty(url.UserInfo)) + { + var uis = url.UserInfo.Split(':'); + uriLogin = new UserIdentity(uis[0], uis[1]); + } + return uriLogin; + } + + /// + /// Crappy method to initialize the session. I don't know what many of these things do, sincerely. + /// + private async Task InitializeSession(Uri url) + { + var certificateValidator = new CertificateValidator(); + certificateValidator.CertificateValidation += (sender, eventArgs) => + { + if (ServiceResult.IsGood(eventArgs.Error)) + eventArgs.Accept = true; + else if ((eventArgs.Error.StatusCode.Code == StatusCodes.BadCertificateUntrusted) && _options.AutoAcceptUntrustedCertificates) + eventArgs.Accept = true; + else + throw new OpcException(string.Format("Failed to validate certificate with error code {0}: {1}", eventArgs.Error.Code, eventArgs.Error.AdditionalInfo), eventArgs.Error.StatusCode); + }; + // Build the application configuration + var appInstance = new ApplicationInstance + { + ApplicationType = ApplicationType.Client, + ConfigSectionName = _options.ConfigSectionName, + ApplicationConfiguration = new ApplicationConfiguration + { + ApplicationUri = url.ToString(), + ApplicationName = _options.ApplicationName, + ApplicationType = ApplicationType.Client, + CertificateValidator = certificateValidator, + ServerConfiguration = new ServerConfiguration + { + MaxSubscriptionCount = _options.MaxSubscriptionCount, + MaxMessageQueueSize = _options.MaxMessageQueueSize, + MaxNotificationQueueSize = _options.MaxNotificationQueueSize, + MaxPublishRequestCount = _options.MaxPublishRequestCount + }, + SecurityConfiguration = new SecurityConfiguration + { + AutoAcceptUntrustedCertificates = _options.AutoAcceptUntrustedCertificates + }, + TransportQuotas = new TransportQuotas + { + OperationTimeout = 600000, + MaxStringLength = 1048576, + MaxByteStringLength = 1048576, + MaxArrayLength = 65535, + MaxMessageSize = 4194304, + MaxBufferSize = 65535, + ChannelLifetime = 600000, + SecurityTokenLifetime = 3600000 + }, + ClientConfiguration = new ClientConfiguration + { + DefaultSessionTimeout = 60000, + MinSubscriptionLifetime = 10000 + }, + DisableHiResClock = true + } + }; + + // Assign a application certificate (when specified) + if (_options.ApplicationCertificate != null) + appInstance.ApplicationConfiguration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(_options.ApplicationCertificate); + + // Find the endpoint to be used + var endpoints = ClientUtils.SelectEndpoint(url, _options.UseMessageSecurity); + + // Create the OPC session: + var session = await Session.Create( + configuration: appInstance.ApplicationConfiguration, + endpoint: new ConfiguredEndpoint( + collection: null, + description: endpoints, + configuration: EndpointConfiguration.Create(applicationConfiguration: appInstance.ApplicationConfiguration)), + updateBeforeConnect: false, + checkDomain: false, + sessionName: _options.SessionName, + sessionTimeout: _options.SessionTimeout, + identity: GetIdentity(url), + preferredLocales: new string[] { }); + + return session; + } + + /// + /// Finds a node starting from the specified node as the root folder + /// + /// the tag to find + /// the root node + /// + private UaNode FindNode(string tag, UaNode node) + { + var folders = tag.Split('.'); + var head = folders.FirstOrDefault(); + UaNode found; try { - CheckReturnValue(response.ServiceResult); - CheckReturnValue(results[0]); - taskCompletionSource.SetResult(response.ServiceResult); + var subNodes = ExploreFolder(node.Tag); + found = subNodes.Single(n => n.Name == head); } catch (Exception ex) { - taskCompletionSource.TrySetException(ex); + throw new OpcException(string.Format("The tag \"{0}\" doesn't exist on folder \"{1}\"", head, node.Tag), ex); } - }, - asyncState: null); - return taskCompletionSource.Task; - } - - /// - /// Monitor the specified tag for changes - /// - /// the type of tag to monitor - /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. - /// E.g: the tag `foo.bar` monitors the tag `bar` on the folder `foo` - /// the callback to execute when the value is changed. - /// The first parameter is a MonitorEvent object which represents the data point, the second is an `unsubscribe` function to unsubscribe the callback - public void Monitor(string tag, Action, Action> callback) - { - var node = FindNode(tag); - - var sub = new Subscription - { - PublishingInterval = _options.DefaultMonitorInterval, - PublishingEnabled = true, - LifetimeCount = _options.SubscriptionLifetimeCount, - KeepAliveCount = _options.SubscriptionKeepAliveCount, - DisplayName = tag, - Priority = byte.MaxValue - }; - - var item = new MonitoredItem - { - StartNodeId = node.NodeId, - AttributeId = Attributes.Value, - DisplayName = tag, - SamplingInterval = _options.DefaultMonitorInterval - }; - sub.AddItem(item); - _session.AddSubscription(sub); - sub.Create(); - sub.ApplyChanges(); - - item.Notification += (monitoredItem, args) => - { - var p = (MonitoredItemNotification)args.NotificationValue; - var t = p.Value.WrappedValue.Value; - Action unsubscribe = () => - { - sub.RemoveItems(sub.MonitoredItems); - sub.Delete(true); - _session.RemoveSubscription(sub); - sub.Dispose(); - }; - - var monitorEvent = new ReadEvent(); - monitorEvent.Value = (T)t; - monitorEvent.SourceTimestamp = p.Value.SourceTimestamp; - monitorEvent.ServerTimestamp = p.Value.ServerTimestamp; - if (StatusCode.IsGood(p.Value.StatusCode)) monitorEvent.Quality = Quality.Good; - if (StatusCode.IsBad(p.Value.StatusCode)) monitorEvent.Quality = Quality.Bad; - callback(monitorEvent, unsubscribe); - }; - } - - /// - /// Explore a folder on the Opc Server - /// - /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. - /// E.g: the tag `foo.bar` finds the sub nodes of `bar` on the folder `foo` - /// The list of sub-nodes - public IEnumerable ExploreFolder(string tag) - { - IList nodes; - _folderCache.TryGetValue(tag, out nodes); - if (nodes != null) - return nodes; - - var folder = FindNode(tag); - nodes = ClientUtils.Browse(_session, folder.NodeId) - .GroupBy(n => n.NodeId) //this is to select distinct - .Select(n => n.First()) - .Where(n => n.NodeClass == NodeClass.Variable || n.NodeClass == NodeClass.Object) - .Select(n => n.ToHylaNode(folder)) - .ToList(); - - //add nodes to cache - if (!_folderCache.ContainsKey(tag)) - _folderCache.Add(tag, nodes); - foreach (var node in nodes) - AddNodeToCache(node); - - return nodes; - } - - /// - /// Explores a folder asynchronously - /// - public async Task> ExploreFolderAsync(string tag) - { - return await Task.Run(() => ExploreFolder(tag)); - } - - /// - /// Finds a node on the Opc Server - /// - /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. - /// E.g: the tag `foo.bar` finds the tag `bar` on the folder `foo` - /// If there is a tag, it returns it, otherwise it throws an - public UaNode FindNode(string tag) - { - // if the tag already exists in cache, return it - if (_nodesCache.ContainsKey(tag)) - return _nodesCache[tag]; - - // try to find the tag otherwise - var found = FindNode(tag, RootNode); - if (found != null) - { - AddNodeToCache(found); - return found; - } - - // throws an exception if not found - throw new OpcException(string.Format("The tag \"{0}\" doesn't exist on the Server", tag)); - } - - /// - /// Find node asynchronously - /// - public async Task FindNodeAsync(string tag) - { - return await Task.Run(() => FindNode(tag)); - } - - /// - /// Gets the root node of the server - /// - public UaNode RootNode { get; private set; } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - if (_session != null) - { - _session.RemoveSubscriptions(_session.Subscriptions.ToList()); - _session.Close(); - _session.Dispose(); - } - GC.SuppressFinalize(this); - } - - private void CheckReturnValue(StatusCode status) - { - if (!StatusCode.IsGood(status)) - throw new OpcException(string.Format("Invalid response from the server. (Response Status: {0})", status), status); - } - - /// - /// Adds a node to the cache using the tag as its key - /// - /// the node to add - private void AddNodeToCache(UaNode node) - { - if (!_nodesCache.ContainsKey(node.Tag)) - _nodesCache.Add(node.Tag, node); - } - - /// - /// Return identity login object for a given URI. - /// - /// Login URI - /// AnonUser or User with name and password - private UserIdentity GetIdentity(Uri url) - { - if (_options.UserIdentity != null) - { - return _options.UserIdentity; - } - var uriLogin = new UserIdentity(); - if (!string.IsNullOrEmpty(url.UserInfo)) - { - var uis = url.UserInfo.Split(':'); - uriLogin = new UserIdentity(uis[0], uis[1]); - } - return uriLogin; - } - - /// - /// Crappy method to initialize the session. I don't know what many of these things do, sincerely. - /// - private async Task InitializeSession(Uri url) - { - var certificateValidator = new CertificateValidator(); - certificateValidator.CertificateValidation += (sender, eventArgs) => - { - if (ServiceResult.IsGood(eventArgs.Error)) - eventArgs.Accept = true; - else if ((eventArgs.Error.StatusCode.Code == StatusCodes.BadCertificateUntrusted) && _options.AutoAcceptUntrustedCertificates) - eventArgs.Accept = true; - else - throw new OpcException(string.Format("Failed to validate certificate with error code {0}: {1}", eventArgs.Error.Code, eventArgs.Error.AdditionalInfo), eventArgs.Error.StatusCode); - }; - // Build the application configuration - var appInstance = new ApplicationInstance - { - ApplicationType = ApplicationType.Client, - ConfigSectionName = _options.ConfigSectionName, - ApplicationConfiguration = new ApplicationConfiguration - { - ApplicationUri = url.ToString(), - ApplicationName = _options.ApplicationName, - ApplicationType = ApplicationType.Client, - CertificateValidator = certificateValidator, - ServerConfiguration = new ServerConfiguration - { - MaxSubscriptionCount = _options.MaxSubscriptionCount, - MaxMessageQueueSize = _options.MaxMessageQueueSize, - MaxNotificationQueueSize = _options.MaxNotificationQueueSize, - MaxPublishRequestCount = _options.MaxPublishRequestCount - }, - SecurityConfiguration = new SecurityConfiguration - { - AutoAcceptUntrustedCertificates = _options.AutoAcceptUntrustedCertificates - }, - TransportQuotas = new TransportQuotas - { - OperationTimeout = 600000, - MaxStringLength = 1048576, - MaxByteStringLength = 1048576, - MaxArrayLength = 65535, - MaxMessageSize = 4194304, - MaxBufferSize = 65535, - ChannelLifetime = 600000, - SecurityTokenLifetime = 3600000 - }, - ClientConfiguration = new ClientConfiguration - { - DefaultSessionTimeout = 60000, - MinSubscriptionLifetime = 10000 - }, - DisableHiResClock = true + // remove an array element by converting it to a list + var folderList = folders.ToList(); + folderList.RemoveAt(0); // remove the first node + folders = folderList.ToArray(); + return folders.Length == 0 + ? found // last node, return it + : FindNode(string.Join(".", folders), found); // find sub nodes } - }; - // Assign a application certificate (when specified) - if (_options.ApplicationCertificate != null) - appInstance.ApplicationConfiguration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(_options.ApplicationCertificate); - // Find the endpoint to be used - var endpoints = ClientUtils.SelectEndpoint(url, _options.UseMessageSecurity); + private void NotifyServerConnectionLost() + { + if (ServerConnectionLost != null) + ServerConnectionLost(this, EventArgs.Empty); + } - // Create the OPC session: - var session = await Session.Create( - configuration: appInstance.ApplicationConfiguration, - endpoint: new ConfiguredEndpoint( - collection: null, - description: endpoints, - configuration: EndpointConfiguration.Create(applicationConfiguration: appInstance.ApplicationConfiguration)), - updateBeforeConnect: false, - checkDomain: false, - sessionName: _options.SessionName, - sessionTimeout: _options.SessionTimeout, - identity: GetIdentity(url), - preferredLocales: new string[] { }); + private void NotifyServerConnectionRestored() + { + if (ServerConnectionRestored != null) + ServerConnectionRestored(this, EventArgs.Empty); + } + + /// + /// This event is raised when the connection to the OPC server is lost. + /// + public event EventHandler ServerConnectionLost; + + /// + /// This event is raised when the connection to the OPC server is restored. + /// + public event EventHandler ServerConnectionRestored; - return session; } - /// - /// Finds a node starting from the specified node as the root folder - /// - /// the tag to find - /// the root node - /// - private UaNode FindNode(string tag, UaNode node) - { - var folders = tag.Split('.'); - var head = folders.FirstOrDefault(); - UaNode found; - try - { - var subNodes = ExploreFolder(node.Tag); - found = subNodes.Single(n => n.Name == head); - } - catch (Exception ex) - { - throw new OpcException(string.Format("The tag \"{0}\" doesn't exist on folder \"{1}\"", head, node.Tag), ex); - } - - // remove an array element by converting it to a list - var folderList = folders.ToList(); - folderList.RemoveAt(0); // remove the first node - folders = folderList.ToArray(); - return folders.Length == 0 - ? found // last node, return it - : FindNode(string.Join(".", folders), found); // find sub nodes - } - - - private void NotifyServerConnectionLost() - { - if (ServerConnectionLost != null) - ServerConnectionLost(this, EventArgs.Empty); - } - - private void NotifyServerConnectionRestored() - { - if (ServerConnectionRestored != null) - ServerConnectionRestored(this, EventArgs.Empty); - } - - /// - /// This event is raised when the connection to the OPC server is lost. - /// - public event EventHandler ServerConnectionLost; - - /// - /// This event is raised when the connection to the OPC server is restored. - /// - public event EventHandler ServerConnectionRestored; - - } - } diff --git a/Libraries/h-opc/UaClientOptions.cs b/Libraries/h-opc/UaClientOptions.cs index 83f1e29..5bb82a4 100644 --- a/Libraries/h-opc/UaClientOptions.cs +++ b/Libraries/h-opc/UaClientOptions.cs @@ -1,121 +1,120 @@ -using System; -using System.Security.Cryptography.X509Certificates; +using System.Security.Cryptography.X509Certificates; using OpcUa = Opc.Ua; namespace Hylasoft.Opc.Ua { - /// - /// This class defines the configuration options for the setup of the UA client session - /// - public class UaClientOptions - { /// - /// Specifies the (optional) certificate for the application to connect to the server + /// This class defines the configuration options for the setup of the UA client session /// - public X509Certificate2 ApplicationCertificate { get; set; } - - /// - /// Specifies the ApplicationName for the client application. - /// - public string ApplicationName { get; set; } - - /// - /// Should untrusted certificates be silently accepted by the client? - /// - public bool AutoAcceptUntrustedCertificates { get; set; } - - /// - /// Specifies the ConfigSectionName for the client configuration. - /// - public string ConfigSectionName { get; set; } - - /// - /// default monitor interval in Milliseconds. - /// - public int DefaultMonitorInterval { get; set; } - - /// - /// Specifies a name to be associated with the created sessions. - /// - public string SessionName { get; set; } - - /// - /// Specifies the timeout for the sessions. - /// - public uint SessionTimeout { get; set; } - - /// - /// Specify whether message exchange should be secured. - /// - public bool UseMessageSecurity { get; set; } - - /// - /// The maximum number of notifications per publish request. - /// The client’s responsibility is to send PublishRequests to the server, - /// in order to enable the server to send PublishResponses back. - /// The PublishResponses are used to deliver the notifications: but if there - /// are no PublishRequests, the server cannot send a notification to the client. - /// The server will also verify that the client is alive by checking that - /// new PublishRequests are received – LifeTimeCount defines the number of - /// PublishingIntervals to wait for a new PublishRequest, before realizing - /// that the client is no longer active.The Subscription is then removed from - /// the server. - /// - public uint SubscriptionLifetimeCount { get; set; } - - /// - /// If there is no data to send after the next PublishingInterval, - /// the server will skip it. But KeepAlive defines how many intervals may be skipped, - /// before an empty notification is sent anyway: to give the client a hint that - /// the subscription is still alive in the server and that there just has not been - /// any data arriving to the client. - /// - public uint SubscriptionKeepAliveCount { get; set; } - - /// - /// Gets or sets the max subscription count. - /// - public int MaxSubscriptionCount { get; set; } - - /// - /// The maximum number of messages saved in the queue for each subscription. - /// - public int MaxMessageQueueSize { get; set; } - - /// - /// The maximum number of notificates saved in the queue for each monitored item. - /// - public int MaxNotificationQueueSize { get; set; } - - /// - /// Gets or sets the max publish request count. - /// - public int MaxPublishRequestCount { get; set; } - - /// - /// The identity to connect to the OPC server as - /// - public OpcUa.UserIdentity UserIdentity { get; set; } - - /// - /// Creates a client options object - /// - public UaClientOptions() + public class UaClientOptions { - // Initialize default values: - ApplicationName = "h-opc-client"; - AutoAcceptUntrustedCertificates = true; - ConfigSectionName = "h-opc-client"; - DefaultMonitorInterval = 100; - SessionName = "h-opc-client"; - SessionTimeout = 60000U; - UseMessageSecurity = false; - SubscriptionLifetimeCount = 0; - SubscriptionKeepAliveCount = 0; - MaxSubscriptionCount = 100; - MaxMessageQueueSize = 10; - MaxNotificationQueueSize = 100; - MaxPublishRequestCount = 20; + /// + /// Specifies the (optional) certificate for the application to connect to the server + /// + public X509Certificate2 ApplicationCertificate { get; set; } + + /// + /// Specifies the ApplicationName for the client application. + /// + public string ApplicationName { get; set; } + + /// + /// Should untrusted certificates be silently accepted by the client? + /// + public bool AutoAcceptUntrustedCertificates { get; set; } + + /// + /// Specifies the ConfigSectionName for the client configuration. + /// + public string ConfigSectionName { get; set; } + + /// + /// default monitor interval in Milliseconds. + /// + public int DefaultMonitorInterval { get; set; } + + /// + /// Specifies a name to be associated with the created sessions. + /// + public string SessionName { get; set; } + + /// + /// Specifies the timeout for the sessions. + /// + public uint SessionTimeout { get; set; } + + /// + /// Specify whether message exchange should be secured. + /// + public bool UseMessageSecurity { get; set; } + + /// + /// The maximum number of notifications per publish request. + /// The client’s responsibility is to send PublishRequests to the server, + /// in order to enable the server to send PublishResponses back. + /// The PublishResponses are used to deliver the notifications: but if there + /// are no PublishRequests, the server cannot send a notification to the client. + /// The server will also verify that the client is alive by checking that + /// new PublishRequests are received – LifeTimeCount defines the number of + /// PublishingIntervals to wait for a new PublishRequest, before realizing + /// that the client is no longer active.The Subscription is then removed from + /// the server. + /// + public uint SubscriptionLifetimeCount { get; set; } + + /// + /// If there is no data to send after the next PublishingInterval, + /// the server will skip it. But KeepAlive defines how many intervals may be skipped, + /// before an empty notification is sent anyway: to give the client a hint that + /// the subscription is still alive in the server and that there just has not been + /// any data arriving to the client. + /// + public uint SubscriptionKeepAliveCount { get; set; } + + /// + /// Gets or sets the max subscription count. + /// + public int MaxSubscriptionCount { get; set; } + + /// + /// The maximum number of messages saved in the queue for each subscription. + /// + public int MaxMessageQueueSize { get; set; } + + /// + /// The maximum number of notificates saved in the queue for each monitored item. + /// + public int MaxNotificationQueueSize { get; set; } + + /// + /// Gets or sets the max publish request count. + /// + public int MaxPublishRequestCount { get; set; } + + /// + /// The identity to connect to the OPC server as + /// + public OpcUa.UserIdentity UserIdentity { get; set; } + + /// + /// Creates a client options object + /// + public UaClientOptions() + { + // Initialize default values: + ApplicationName = "h-opc-client"; + AutoAcceptUntrustedCertificates = true; + ConfigSectionName = "h-opc-client"; + DefaultMonitorInterval = 100; + SessionName = "h-opc-client"; + SessionTimeout = 60000U; + UseMessageSecurity = false; + SubscriptionLifetimeCount = 0; + SubscriptionKeepAliveCount = 0; + MaxSubscriptionCount = 100; + MaxMessageQueueSize = 10; + MaxNotificationQueueSize = 100; + MaxPublishRequestCount = 20; + } } - } } diff --git a/Libraries/h-opc/UaNode.cs b/Libraries/h-opc/UaNode.cs index a6e9320..edaa021 100644 --- a/Libraries/h-opc/UaNode.cs +++ b/Libraries/h-opc/UaNode.cs @@ -2,28 +2,28 @@ namespace Hylasoft.Opc.Ua { - /// - /// Represents a node to be used specifically for OPC UA - /// - public class UaNode : Node - { /// - /// The UA Id of the node + /// Represents a node to be used specifically for OPC UA /// - public string NodeId { get; private set; } - - /// - /// Instantiates a UaNode class - /// - /// the name of the node - /// The UA Id of the node - /// The parent node - internal UaNode(string name, string nodeId, Node parent = null) - : base(name, parent) + public class UaNode : Node { - NodeId = nodeId; + /// + /// The UA Id of the node + /// + public string NodeId { get; private set; } + + /// + /// Instantiates a UaNode class + /// + /// the name of the node + /// The UA Id of the node + /// The parent node + internal UaNode(string name, string nodeId, Node parent = null) + : base(name, parent) + { + NodeId = nodeId; + } + } - } - } diff --git a/Modbus.Net/.editorconfig b/Modbus.Net/.editorconfig new file mode 100644 index 0000000..ad5b7ba --- /dev/null +++ b/Modbus.Net/.editorconfig @@ -0,0 +1,226 @@ +# 如果要从更高级别的目录继承 .editorconfig 设置,请删除以下行 +root = true + +# c# 文件 +[*.cs] + +#### Core EditorConfig 选项 #### + +# 缩进和间距 +indent_size = 4 +indent_style = space +tab_width = 4 + +# 新行首选项 +end_of_line = crlf +insert_final_newline = false + +#### .NET 编码约定 #### + +# 组织 Using +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = false +file_header_template = unset + +# this. 和 Me. 首选项 +dotnet_style_qualification_for_event = false +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_method = false +dotnet_style_qualification_for_property = false + +# 语言关键字与 bcl 类型首选项 +dotnet_style_predefined_type_for_locals_parameters_members = true +dotnet_style_predefined_type_for_member_access = true + +# 括号首选项 +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_operators = never_if_unnecessary +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity + +# 修饰符首选项 +dotnet_style_require_accessibility_modifiers = for_non_interface_members + +# 表达式级首选项 +dotnet_style_coalesce_expression = true +dotnet_style_collection_initializer = true +dotnet_style_explicit_tuple_names = true +dotnet_style_namespace_match_folder = true +dotnet_style_null_propagation = true +dotnet_style_object_initializer = true +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true +dotnet_style_prefer_compound_assignment = true +dotnet_style_prefer_conditional_expression_over_assignment = true +dotnet_style_prefer_conditional_expression_over_return = true +dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed +dotnet_style_prefer_inferred_anonymous_type_member_names = true +dotnet_style_prefer_inferred_tuple_names = true +dotnet_style_prefer_is_null_check_over_reference_equality_method = true +dotnet_style_prefer_simplified_boolean_expressions = true +dotnet_style_prefer_simplified_interpolation = true + +# 字段首选项 +dotnet_style_readonly_field = true + +# 参数首选项 +dotnet_code_quality_unused_parameters = all + +# 禁止显示首选项 +dotnet_remove_unnecessary_suppression_exclusions = none + +# 新行首选项 +dotnet_style_allow_multiple_blank_lines_experimental = true +dotnet_style_allow_statement_immediately_after_block_experimental = true + +#### c# 编码约定 #### + +# var 首选项 +csharp_style_var_elsewhere = false +csharp_style_var_for_built_in_types = false +csharp_style_var_when_type_is_apparent = false + +# Expression-bodied 成员 +csharp_style_expression_bodied_accessors = true +csharp_style_expression_bodied_constructors = false +csharp_style_expression_bodied_indexers = true +csharp_style_expression_bodied_lambdas = true +csharp_style_expression_bodied_local_functions = false +csharp_style_expression_bodied_methods = false +csharp_style_expression_bodied_operators = false +csharp_style_expression_bodied_properties = true + +# 模式匹配首选项 +csharp_style_pattern_matching_over_as_with_null_check = true +csharp_style_pattern_matching_over_is_with_cast_check = true +csharp_style_prefer_extended_property_pattern = true +csharp_style_prefer_not_pattern = true +csharp_style_prefer_pattern_matching = true +csharp_style_prefer_switch_expression = true + +# Null 检查首选项 +csharp_style_conditional_delegate_call = true + +# 修饰符首选项 +csharp_prefer_static_local_function = true +csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async +csharp_style_prefer_readonly_struct = true + +# 代码块首选项 +csharp_prefer_braces = true +csharp_prefer_simple_using_statement = true +csharp_style_namespace_declarations = block_scoped +csharp_style_prefer_method_group_conversion = true +csharp_style_prefer_top_level_statements = true + +# 表达式级首选项 +csharp_prefer_simple_default_expression = true +csharp_style_deconstructed_variable_declaration = true +csharp_style_implicit_object_creation_when_type_is_apparent = true +csharp_style_inlined_variable_declaration = true +csharp_style_prefer_index_operator = true +csharp_style_prefer_local_over_anonymous_function = true +csharp_style_prefer_null_check_over_type_check = true +csharp_style_prefer_range_operator = true +csharp_style_prefer_tuple_swap = true +csharp_style_prefer_utf8_string_literals = true +csharp_style_throw_expression = true +csharp_style_unused_value_assignment_preference = discard_variable +csharp_style_unused_value_expression_statement_preference = discard_variable + +# "using" 指令首选项 +csharp_using_directive_placement = outside_namespace + +# 新行首选项 +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true +csharp_style_allow_embedded_statements_on_same_line_experimental = true + +#### C# 格式规则 #### + +# 新行首选项 +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# 缩进首选项 +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +# 空格键首选项 +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# 包装首选项 +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +#### 命名样式 #### + +# 命名规则 + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# 符号规范 + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# 命名样式 + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case diff --git a/Modbus.Net/Modbus.Net.Modbus.NA200H/AddressTranslatorNA200H.cs b/Modbus.Net/Modbus.Net.Modbus.NA200H/AddressTranslatorNA200H.cs index 440571f..de520d5 100644 --- a/Modbus.Net/Modbus.Net.Modbus.NA200H/AddressTranslatorNA200H.cs +++ b/Modbus.Net/Modbus.Net.Modbus.NA200H/AddressTranslatorNA200H.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; namespace Modbus.Net.Modbus.NA200H { diff --git a/Modbus.Net/Modbus.Net.Modbus.NA200H/Modbus.Net.Modbus.NA200H.csproj b/Modbus.Net/Modbus.Net.Modbus.NA200H/Modbus.Net.Modbus.NA200H.csproj index 84f11f2..c1fb175 100644 --- a/Modbus.Net/Modbus.Net.Modbus.NA200H/Modbus.Net.Modbus.NA200H.csproj +++ b/Modbus.Net/Modbus.Net.Modbus.NA200H/Modbus.Net.Modbus.NA200H.csproj @@ -5,7 +5,7 @@ Modbus.Net.Modbus.NA200H Modbus.Net.Modbus.NA200H Modbus.Net.Modbus.NA200H - 1.4.0 + 1.4.0-beta03 Chris L.(Luo Sheng) Hangzhou Delian Science Technology Co.,Ltd. Modbus.Net.Modbus diff --git a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj index 6245222..66cb140 100644 --- a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj +++ b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj @@ -5,7 +5,7 @@ Modbus.Net.Modbus Modbus.Net.Modbus Modbus.Net.Modbus - 1.4.0 + 1.4.0-beta03 Chris L.(Luo Sheng) Hangzhou Delian Science Technology Co.,Ltd. Modbus.Net.Modbus diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocolLinker.cs index a5c3ca1..fc78c9c 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocolLinker.cs @@ -18,7 +18,7 @@ namespace Modbus.Net.Modbus public ModbusAsciiProtocolLinker(string com, int slaveAddress) : base(com, 9600, Parity.None, StopBits.One, 8, slaveAddress) { - ((BaseConnector)BaseConnector).AddController(new MatchController(new ICollection<(int,int)>[] { new List<(int,int)> { (1,1), (2,2) }, new List<(int, int)> { (3, 3), (4, 4) }}, int.Parse(new ConfigurationBuilder().AddJsonFile($"appsettings.json").Build().GetSection("Config")["FetchSleepTime"] ?? "0"))); + ((BaseConnector)BaseConnector).AddController(new MatchController(new ICollection<(int, int)>[] { new List<(int, int)> { (1, 1), (2, 2) }, new List<(int, int)> { (3, 3), (4, 4) } }, int.Parse(new ConfigurationBuilder().AddJsonFile($"appsettings.json").Build().GetSection("Config")["FetchSleepTime"] ?? "0"))); } /// diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocol.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocol.cs index 81b1cc5..d834ff9 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocol.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocol.cs @@ -132,10 +132,10 @@ namespace Modbus.Net.Modbus { SlaveAddress = slaveAddress; var translateAddress = addressTranslator.AddressTranslate(startAddress, true); - FunctionCode = (byte) translateAddress.Area; - StartAddress = (ushort) translateAddress.Address; + FunctionCode = (byte)translateAddress.Area; + StartAddress = (ushort)translateAddress.Address; GetCount = - (ushort) Math.Ceiling(getCount / addressTranslator.GetAreaByteLength(translateAddress.AreaString)); + (ushort)Math.Ceiling(getCount / addressTranslator.GetAreaByteLength(translateAddress.AreaString)); } /// @@ -213,7 +213,7 @@ namespace Modbus.Net.Modbus /// 读取数据的协议核心 public override byte[] Format(IInputStruct message) { - var r_message = (ReadDataModbusInputStruct) message; + var r_message = (ReadDataModbusInputStruct)message; return Format(r_message.SlaveAddress, r_message.FunctionCode, r_message.StartAddress, r_message.GetCount); } @@ -257,12 +257,12 @@ namespace Modbus.Net.Modbus { SlaveAddress = slaveAddress; var translateAddress = addressTranslator.AddressTranslate(startAddress, false); - FunctionCode = (byte) translateAddress.Area; - StartAddress = (ushort) translateAddress.Address; + FunctionCode = (byte)translateAddress.Area; + StartAddress = (ushort)translateAddress.Address; var writeByteValue = ValueHelper.GetInstance(endian).ObjectArrayToByteArray(writeValue); WriteCount = - (ushort) (writeByteValue.Length / addressTranslator.GetAreaByteLength(translateAddress.AreaString)); - WriteByteCount = (byte) writeByteValue.Length; + (ushort)(writeByteValue.Length / addressTranslator.GetAreaByteLength(translateAddress.AreaString)); + WriteByteCount = (byte)writeByteValue.Length; WriteValue = writeByteValue; } @@ -351,7 +351,7 @@ namespace Modbus.Net.Modbus /// 写寄存器协议核心 public override byte[] Format(IInputStruct message) { - var r_message = (WriteDataModbusInputStruct) message; + var r_message = (WriteDataModbusInputStruct)message; var dataValue = Format(r_message.WriteValue); var formattingBytes = Format(r_message.SlaveAddress, r_message.FunctionCode, r_message.StartAddress, r_message.WriteCount, r_message.WriteByteCount, dataValue); @@ -393,13 +393,13 @@ namespace Modbus.Net.Modbus { SlaveAddress = slaveAddress; var translateAddress = addressTranslator.AddressTranslate(startAddress, false, true); - FunctionCode = (byte) translateAddress.Area; - StartAddress = (ushort) translateAddress.Address; + FunctionCode = (byte)translateAddress.Area; + StartAddress = (ushort)translateAddress.Address; var writeByteValue = - FunctionCode == (byte) ModbusProtocolWriteDataFunctionCode.WriteSingleCoil - ? ((bool) writeValue - ? new byte[] {0xFF, 0x00} - : new byte[] {0x00, 0x00}) + FunctionCode == (byte)ModbusProtocolWriteDataFunctionCode.WriteSingleCoil + ? ((bool)writeValue + ? new byte[] { 0xFF, 0x00 } + : new byte[] { 0x00, 0x00 }) : ValueHelper.GetInstance(endian).GetBytes(ushort.Parse(writeValue.ToString())); WriteValue = writeByteValue; } @@ -480,7 +480,7 @@ namespace Modbus.Net.Modbus /// 写寄存器协议核心 public override byte[] Format(IInputStruct message) { - var r_message = (WriteSingleDataModbusInputStruct) message; + var r_message = (WriteSingleDataModbusInputStruct)message; var dataValue = Format(r_message.WriteValue); var formattingBytes = Format(r_message.SlaveAddress, r_message.FunctionCode, r_message.StartAddress, dataValue); @@ -522,7 +522,7 @@ namespace Modbus.Net.Modbus public GetSystemTimeModbusInputStruct(byte slaveAddress) { SlaveAddress = slaveAddress; - FunctionCode = (byte) ModbusProtocolTimeFunctionCode.GetSystemTime; + FunctionCode = (byte)ModbusProtocolTimeFunctionCode.GetSystemTime; StartAddress = 30000; GetCount = 5; } @@ -609,7 +609,7 @@ namespace Modbus.Net.Modbus /// 写系统时间的核心 public override byte[] Format(IInputStruct message) { - var r_message = (GetSystemTimeModbusInputStruct) message; + var r_message = (GetSystemTimeModbusInputStruct)message; return Format(r_message.SlaveAddress, r_message.FunctionCode, r_message.StartAddress, r_message.GetCount); } @@ -654,17 +654,17 @@ namespace Modbus.Net.Modbus public SetSystemTimeModbusInputStruct(byte slaveAddress, DateTime time) { SlaveAddress = slaveAddress; - FunctionCode = (byte) ModbusProtocolTimeFunctionCode.SetSystemTime; + FunctionCode = (byte)ModbusProtocolTimeFunctionCode.SetSystemTime; StartAddress = 30000; WriteCount = 5; WriteByteCount = 10; - Year = (ushort) time.Year; - Day = (byte) time.Day; - Month = (byte) time.Month; - Hour = (ushort) time.Hour; - Second = (byte) time.Second; - Minute = (byte) time.Minute; - Millisecond = (ushort) time.Millisecond; + Year = (ushort)time.Year; + Day = (byte)time.Day; + Month = (byte)time.Month; + Hour = (ushort)time.Hour; + Second = (byte)time.Second; + Minute = (byte)time.Minute; + Millisecond = (ushort)time.Millisecond; } /// @@ -782,7 +782,7 @@ namespace Modbus.Net.Modbus /// 写系统时间的核心 public override byte[] Format(IInputStruct message) { - var r_message = (SetSystemTimeModbusInputStruct) message; + var r_message = (SetSystemTimeModbusInputStruct)message; return Format(r_message.SlaveAddress, r_message.FunctionCode, r_message.StartAddress, r_message.WriteCount, r_message.WriteByteCount, r_message.Year, r_message.Day, diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocolLinkerBytesExtend.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocolLinkerBytesExtend.cs index b9db51b..662ac5f 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocolLinkerBytesExtend.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocolLinkerBytesExtend.cs @@ -26,7 +26,7 @@ namespace Modbus.Net.Modbus /// public class ModbusUdpProtocolLinkerBytesExtend : ModbusTcpProtocolLinkerBytesExtend { - + } /// @@ -34,7 +34,7 @@ namespace Modbus.Net.Modbus /// public class ModbusRtuInTcpProtocolLinkerBytesExtend : ModbusRtuProtocolLinkerBytesExtend { - + } /// @@ -60,7 +60,7 @@ namespace Modbus.Net.Modbus //Modbus/Tcp协议扩张,前面加6个字节,前面4个为0,后面两个为协议整体内容的长度 var newFormat = new byte[6 + content.Length]; var tag = 0; - var leng = (ushort) content.Length; + var leng = (ushort)content.Length; Array.Copy(BigEndianValueHelper.Instance.GetBytes(tag), 0, newFormat, 0, 4); Array.Copy(BigEndianValueHelper.Instance.GetBytes(leng), 0, newFormat, 4, 2); Array.Copy(content, 0, newFormat, 6, content.Length); diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolLinker.cs index 0672669..d0e8499 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolLinker.cs @@ -17,7 +17,7 @@ namespace Modbus.Net.Modbus public ModbusRtuProtocolLinker(string com, int slaveAddress) : base(com, 9600, Parity.None, StopBits.One, 8, slaveAddress) { - ((BaseConnector)BaseConnector).AddController(new MatchController(new ICollection<(int,int)>[]{new List<(int,int)>{(0,0)}, new List<(int, int)>{(1,1)}}, int.Parse(new ConfigurationBuilder().AddJsonFile($"appsettings.json").Build().GetSection("Config")["FetchSleepTime"] ?? "0"))); + ((BaseConnector)BaseConnector).AddController(new MatchController(new ICollection<(int, int)>[] { new List<(int, int)> { (0, 0) }, new List<(int, int)> { (1, 1) } }, int.Parse(new ConfigurationBuilder().AddJsonFile($"appsettings.json").Build().GetSection("Config")["FetchSleepTime"] ?? "0"))); } /// diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocolLinker.cs index 4791e8a..35bfa9c 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocolLinker.cs @@ -24,7 +24,7 @@ namespace Modbus.Net.Modbus /// 端口 public ModbusTcpProtocolLinker(string ip, int port) : base(ip, port) { - ((BaseConnector)BaseConnector).AddController(new FifoController(int.Parse(new ConfigurationBuilder().AddJsonFile($"appsettings.json").Build().GetSection("Config")["FetchSleepTime"] ?? "0"), true, DuplicateWithCount.GetDuplcateFunc(new List{4,5}, 6))); + ((BaseConnector)BaseConnector).AddController(new FifoController(int.Parse(new ConfigurationBuilder().AddJsonFile($"appsettings.json").Build().GetSection("Config")["FetchSleepTime"] ?? "0"), true, DuplicateWithCount.GetDuplcateFunc(new List { 4, 5 }, 6))); } /// diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs index 82da0b2..ab68099 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs @@ -1,6 +1,6 @@ -using System; +using Microsoft.Extensions.Logging; +using System; using System.Threading.Tasks; -using Serilog; namespace Modbus.Net.Modbus { @@ -69,6 +69,8 @@ namespace Modbus.Net.Modbus /// public class ModbusUtility : BaseUtility, IUtilityMethodTime, IUtilityMethodWriteSingle { + private static readonly ILogger logger = LogProvider.CreateLogger(); + /// /// Modbus协议类型 /// @@ -87,7 +89,7 @@ namespace Modbus.Net.Modbus { Endian = endian; ConnectionString = null; - ModbusType = (ModbusType) connectionType; + ModbusType = (ModbusType)connectionType; AddressTranslator = new AddressTranslatorModbus(); } @@ -138,11 +140,11 @@ namespace Modbus.Net.Modbus var connectionStringSplit = ConnectionString.Split(':'); try { - return connectionStringSplit.Length < 2 ? (int?) null : int.Parse(connectionStringSplit[1]); + return connectionStringSplit.Length < 2 ? (int?)null : int.Parse(connectionStringSplit[1]); } catch (Exception e) { - Log.Error(e, $"ModbusUtility: {ConnectionString} format error"); + logger.LogError(e, $"ModbusUtility: {ConnectionString} format error"); return null; } } @@ -161,86 +163,86 @@ namespace Modbus.Net.Modbus { //Rtu协议 case ModbusType.Rtu: - { - Wrapper = ConnectionString == null - ? new ModbusRtuProtocol(SlaveAddress, MasterAddress) - : new ModbusRtuProtocol(ConnectionString, SlaveAddress, MasterAddress); - break; - } + { + Wrapper = ConnectionString == null + ? new ModbusRtuProtocol(SlaveAddress, MasterAddress) + : new ModbusRtuProtocol(ConnectionString, SlaveAddress, MasterAddress); + break; + } //Tcp协议 case ModbusType.Tcp: - { - Wrapper = ConnectionString == null - ? new ModbusTcpProtocol(SlaveAddress, MasterAddress) - : (ConnectionStringPort == null - ? new ModbusTcpProtocol(ConnectionString, SlaveAddress, MasterAddress) - : new ModbusTcpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, - MasterAddress)); - break; - } + { + Wrapper = ConnectionString == null + ? new ModbusTcpProtocol(SlaveAddress, MasterAddress) + : (ConnectionStringPort == null + ? new ModbusTcpProtocol(ConnectionString, SlaveAddress, MasterAddress) + : new ModbusTcpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, + MasterAddress)); + break; + } //Ascii协议 case ModbusType.Ascii: - { - Wrapper = ConnectionString == null - ? new ModbusAsciiProtocol(SlaveAddress, MasterAddress) - : new ModbusAsciiProtocol(ConnectionString, SlaveAddress, MasterAddress); - break; - } + { + Wrapper = ConnectionString == null + ? new ModbusAsciiProtocol(SlaveAddress, MasterAddress) + : new ModbusAsciiProtocol(ConnectionString, SlaveAddress, MasterAddress); + break; + } //Rtu协议Tcp透传 case ModbusType.RtuInTcp: - { - Wrapper = ConnectionString == null - ? new ModbusRtuInTcpProtocol(SlaveAddress, MasterAddress) - : (ConnectionStringPort == null - ? new ModbusRtuInTcpProtocol(ConnectionString, SlaveAddress, MasterAddress) - : new ModbusRtuInTcpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, - MasterAddress)); - break; - } + { + Wrapper = ConnectionString == null + ? new ModbusRtuInTcpProtocol(SlaveAddress, MasterAddress) + : (ConnectionStringPort == null + ? new ModbusRtuInTcpProtocol(ConnectionString, SlaveAddress, MasterAddress) + : new ModbusRtuInTcpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, + MasterAddress)); + break; + } //Ascii协议Tcp透传 case ModbusType.AsciiInTcp: - { - Wrapper = ConnectionString == null - ? new ModbusAsciiInTcpProtocol(SlaveAddress, MasterAddress) - : (ConnectionStringPort == null - ? new ModbusAsciiInTcpProtocol(ConnectionString, SlaveAddress, MasterAddress) - : new ModbusAsciiInTcpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, - MasterAddress)); - break; - } + { + Wrapper = ConnectionString == null + ? new ModbusAsciiInTcpProtocol(SlaveAddress, MasterAddress) + : (ConnectionStringPort == null + ? new ModbusAsciiInTcpProtocol(ConnectionString, SlaveAddress, MasterAddress) + : new ModbusAsciiInTcpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, + MasterAddress)); + break; + } //Tcp协议Udp透传 case ModbusType.Udp: - { - Wrapper = ConnectionString == null - ? new ModbusUdpProtocol(SlaveAddress, MasterAddress) - : (ConnectionStringPort == null - ? new ModbusUdpProtocol(ConnectionString, SlaveAddress, MasterAddress) - : new ModbusUdpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, - MasterAddress)); - break; - } + { + Wrapper = ConnectionString == null + ? new ModbusUdpProtocol(SlaveAddress, MasterAddress) + : (ConnectionStringPort == null + ? new ModbusUdpProtocol(ConnectionString, SlaveAddress, MasterAddress) + : new ModbusUdpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, + MasterAddress)); + break; + } //Rtu协议Udp透传 case ModbusType.RtuInUdp: - { - Wrapper = ConnectionString == null - ? new ModbusRtuInUdpProtocol(SlaveAddress, MasterAddress) - : (ConnectionStringPort == null - ? new ModbusRtuInUdpProtocol(ConnectionString, SlaveAddress, MasterAddress) - : new ModbusRtuInUdpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, - MasterAddress)); - break; - } + { + Wrapper = ConnectionString == null + ? new ModbusRtuInUdpProtocol(SlaveAddress, MasterAddress) + : (ConnectionStringPort == null + ? new ModbusRtuInUdpProtocol(ConnectionString, SlaveAddress, MasterAddress) + : new ModbusRtuInUdpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, + MasterAddress)); + break; + } //Rtu协议Udp透传 case ModbusType.AsciiInUdp: - { - Wrapper = ConnectionString == null - ? new ModbusAsciiInUdpProtocol(SlaveAddress, MasterAddress) - : (ConnectionStringPort == null - ? new ModbusAsciiInUdpProtocol(ConnectionString, SlaveAddress, MasterAddress) - : new ModbusAsciiInUdpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, - MasterAddress)); - break; - } + { + Wrapper = ConnectionString == null + ? new ModbusAsciiInUdpProtocol(SlaveAddress, MasterAddress) + : (ConnectionStringPort == null + ? new ModbusAsciiInUdpProtocol(ConnectionString, SlaveAddress, MasterAddress) + : new ModbusAsciiInUdpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, + MasterAddress)); + break; + } } } } @@ -261,7 +263,7 @@ namespace Modbus.Net.Modbus } catch (Exception e) { - Log.Error(e, $"ModbusUtility -> GetTime: {ConnectionString} error"); + logger.LogError(e, $"ModbusUtility -> GetTime: {ConnectionString} error"); return DateTime.MinValue; } } @@ -283,7 +285,7 @@ namespace Modbus.Net.Modbus } catch (Exception e) { - Log.Error(e, $"ModbusUtility -> SetTime: {ConnectionString} error"); + logger.LogError(e, $"ModbusUtility -> SetTime: {ConnectionString} error"); return false; } } @@ -294,7 +296,7 @@ namespace Modbus.Net.Modbus /// 协议类型 public override void SetConnectionType(int connectionType) { - ModbusType = (ModbusType) connectionType; + ModbusType = (ModbusType)connectionType; } /// @@ -308,7 +310,7 @@ namespace Modbus.Net.Modbus try { var inputStruct = new ReadDataModbusInputStruct(SlaveAddress, startAddress, - (ushort) getByteCount, AddressTranslator); + (ushort)getByteCount, AddressTranslator); var outputStruct = await Wrapper.SendReceiveAsync(Wrapper[typeof(ReadDataModbusProtocol)], inputStruct); @@ -316,7 +318,7 @@ namespace Modbus.Net.Modbus } catch (Exception e) { - Log.Error(e, $"ModbusUtility -> GetDatas: {ConnectionString} error"); + logger.LogError(e, $"ModbusUtility -> GetDatas: {ConnectionString} error"); return null; } } @@ -340,7 +342,7 @@ namespace Modbus.Net.Modbus } catch (Exception e) { - Log.Error(e, $"ModbusUtility -> SetDatas: {ConnectionString} error"); + logger.LogError(e, $"ModbusUtility -> SetDatas: {ConnectionString} error"); return false; } } @@ -364,7 +366,7 @@ namespace Modbus.Net.Modbus } catch (Exception e) { - Log.Error(e, $"ModbusUtility -> SetSingleDatas: {ConnectionString} error"); + logger.LogError(e, $"ModbusUtility -> SetSingleDatas: {ConnectionString} error"); return false; } } diff --git a/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs b/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs index 3b21d2f..92ebb5f 100644 --- a/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs +++ b/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs @@ -1,8 +1,8 @@ -using System; +using Hylasoft.Opc.Common; +using Hylasoft.Opc.Ua; +using System; using System.Collections.Generic; using System.Threading.Tasks; -using Hylasoft.Opc.Common; -using Hylasoft.Opc.Ua; namespace Modbus.Net.OPC { diff --git a/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj b/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj index 299c197..659a26d 100644 --- a/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj +++ b/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj @@ -5,7 +5,7 @@ Modbus.Net.OPC Modbus.Net.OPC Modbus.Net.OPC - 1.4.0 + 1.4.0-beta03 Chris L.(Luo Sheng) Hangzhou Delian Science Technology Co.,Ltd. Modbus.Net.OPC diff --git a/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs b/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs index c25234d..87ecc42 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs @@ -1,11 +1,10 @@ -using System; +using Hylasoft.Opc.Common; +using Microsoft.Extensions.Logging; +using System; using System.Collections.Generic; -using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; -using Hylasoft.Opc.Common; -using Serilog; namespace Modbus.Net.OPC { @@ -14,6 +13,8 @@ namespace Modbus.Net.OPC /// public abstract class OpcConnector : BaseConnector { + private static readonly ILogger logger = LogProvider.CreateLogger(); + /// /// 是否正在连接 /// @@ -61,12 +62,12 @@ namespace Modbus.Net.OPC Client?.Dispose(); Client = null; _connect = false; - Log.Information("opc client {ConnectionToken} disconnected success", ConnectionToken); + logger.LogInformation("opc client {ConnectionToken} disconnected success", ConnectionToken); return true; } catch (Exception ex) { - Log.Error(ex, "opc client {ConnectionToken} disconnected error", ConnectionToken); + logger.LogError(ex, "opc client {ConnectionToken} disconnected error", ConnectionToken); _connect = false; return false; } @@ -108,7 +109,7 @@ namespace Modbus.Net.OPC if (answerTag != null) { var result = await Client.ReadAsync(answerTag); - Log.Verbose($"Opc Machine {ConnectionToken} Read opc tag {answerTag} for value {result}"); + logger.LogDebug($"Opc Machine {ConnectionToken} Read opc tag {answerTag} for value {result}"); return new OpcParamOut { Success = true, @@ -134,11 +135,11 @@ namespace Modbus.Net.OPC try { await Client.WriteAsync(answerTag, value); - Log.Verbose($"Opc Machine {ConnectionToken} Write opc tag {answerTag} for value {value}"); + logger.LogDebug($"Opc Machine {ConnectionToken} Write opc tag {answerTag} for value {value}"); } catch (Exception e) { - Log.Error(e, "opc client {ConnectionToken} write exception", ConnectionToken); + logger.LogError(e, "opc client {ConnectionToken} write exception", ConnectionToken); return new OpcParamOut { Success = false @@ -157,7 +158,7 @@ namespace Modbus.Net.OPC } catch (Exception e) { - Log.Error(e, "opc client {ConnectionToken} read exception", ConnectionToken); + logger.LogError(e, "opc client {ConnectionToken} read exception", ConnectionToken); return new OpcParamOut { Success = false, @@ -200,12 +201,12 @@ namespace Modbus.Net.OPC { await Client.Connect(); _connect = true; - Log.Information("opc client {ConnectionToken} connect success", ConnectionToken); + logger.LogInformation("opc client {ConnectionToken} connect success", ConnectionToken); return true; } catch (Exception ex) { - Log.Error(ex, "opc client {ConnectionToken} connected failed", ConnectionToken); + logger.LogError(ex, "opc client {ConnectionToken} connected failed", ConnectionToken); _connect = false; return false; } diff --git a/Modbus.Net/Modbus.Net.OPC/OpcProtocol.cs b/Modbus.Net/Modbus.Net.OPC/OpcProtocol.cs index a9e376f..fdec28f 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcProtocol.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcProtocol.cs @@ -77,7 +77,7 @@ /// 格式化后的字节流 public override OpcParamIn Format(IInputStruct message) { - var r_message = (ReadRequestOpcInputStruct) message; + var r_message = (ReadRequestOpcInputStruct)message; return new OpcParamIn { IsRead = true, @@ -169,7 +169,7 @@ /// 格式化后的字节流 public override OpcParamIn Format(IInputStruct message) { - var r_message = (WriteRequestOpcInputStruct) message; + var r_message = (WriteRequestOpcInputStruct)message; return new OpcParamIn { IsRead = false, diff --git a/Modbus.Net/Modbus.Net.OPC/OpcProtocolLinker.cs b/Modbus.Net/Modbus.Net.OPC/OpcProtocolLinker.cs index de7e595..67abf73 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcProtocolLinker.cs @@ -34,7 +34,7 @@ namespace Modbus.Net.OPC //容错处理 var checkRight = CheckRight(receiveBytes); return checkRight == null - ? new OpcParamOut {Success = false, Value = new byte[0]} + ? new OpcParamOut { Success = false, Value = new byte[0] } : (!checkRight.Value ? null : receiveBytes); //返回字符 } diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs index 7aebb2b..acae757 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Threading.Tasks; namespace Modbus.Net.OPC { diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs index dd0db53..e829614 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs @@ -23,8 +23,8 @@ namespace Modbus.Net.OPC : base(id, getAddresses, keepConnect) { BaseUtility = new OpcUaUtility(connectionString, isRegexOn); - ((OpcUtility) BaseUtility).GetSeperator += - () => ((AddressFormaterOpc) AddressFormater).Seperator; + ((OpcUtility)BaseUtility).GetSeperator += + () => ((AddressFormaterOpc)AddressFormater).Seperator; } /// @@ -56,8 +56,8 @@ namespace Modbus.Net.OPC : base(id, getAddresses, keepConnect) { BaseUtility = new OpcUaUtility(connectionString, isRegexOn); - ((OpcUtility) BaseUtility).GetSeperator += - () => ((AddressFormaterOpc) AddressFormater).Seperator; + ((OpcUtility)BaseUtility).GetSeperator += + () => ((AddressFormaterOpc)AddressFormater).Seperator; } /// diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs b/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs index e098b32..2c7c301 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs @@ -1,6 +1,6 @@ -using System; +using Microsoft.Extensions.Logging; +using System; using System.Threading.Tasks; -using Serilog; namespace Modbus.Net.OPC { @@ -11,6 +11,8 @@ namespace Modbus.Net.OPC PipeUnit, ProtocolUnit>> { + private static readonly ILogger logger = LogProvider.CreateLogger(); + /// /// 获取分隔符 /// @@ -66,7 +68,7 @@ namespace Modbus.Net.OPC } catch (Exception e) { - Log.Error(e, $"OpcUtility -> GetDatas: {ConnectionString} error"); + logger.LogError(e, $"OpcUtility -> GetDatas: {ConnectionString} error"); return null; } } @@ -92,7 +94,7 @@ namespace Modbus.Net.OPC } catch (Exception e) { - Log.Error(e, $"OpcUtility -> SetDatas: {ConnectionString} error"); + logger.LogError(e, $"OpcUtility -> SetDatas: {ConnectionString} error"); return false; } } diff --git a/Modbus.Net/Modbus.Net.Siemens/AddressTranslatorSiemens.cs b/Modbus.Net/Modbus.Net.Siemens/AddressTranslatorSiemens.cs index fd69247..43e3126 100644 --- a/Modbus.Net/Modbus.Net.Siemens/AddressTranslatorSiemens.cs +++ b/Modbus.Net/Modbus.Net.Siemens/AddressTranslatorSiemens.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; namespace Modbus.Net.Siemens { diff --git a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj index 93f0582..62ee924 100644 --- a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj +++ b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj @@ -5,7 +5,7 @@ Modbus.Net.Siemens Modbus.Net.Siemens Modbus.Net.Siemens - 1.4.0 + 1.4.0-beta03 Chris L.(Luo Sheng) Hangzhou Delian Science Technology Co.,Ltd. Modbus.Net Siemens Profinet Implementation diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocol.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocol.cs index 6fb3bae..62edeab 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocol.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocol.cs @@ -1,6 +1,6 @@ -using System.Threading.Tasks; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration; using Nito.AsyncEx; +using System.Threading.Tasks; namespace Modbus.Net.Siemens { diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensProtocol.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensProtocol.cs index 0b4c182..ce798e3 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensProtocol.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensProtocol.cs @@ -151,10 +151,10 @@ namespace Modbus.Net.Siemens { public override byte[] Format(IInputStruct message) { - var r_message = (ComCreateReferenceSiemensInputStruct) message; + var r_message = (ComCreateReferenceSiemensInputStruct)message; var crc = (r_message.SlaveAddress + r_message.MasterAddress + 0x49) % 256; - return Format((byte) 0x10, r_message.SlaveAddress, r_message.MasterAddress, (byte) 0x49, (byte) crc, - (byte) 0x16); + return Format((byte)0x10, r_message.SlaveAddress, r_message.MasterAddress, (byte)0x49, (byte)crc, + (byte)0x16); } public override IOutputStruct Unformat(byte[] messageBytes, ref int pos) @@ -206,7 +206,7 @@ namespace Modbus.Net.Siemens { public override byte[] Format(IInputStruct message) { - var r_message = (CreateReferenceSiemensInputStruct) message; + var r_message = (CreateReferenceSiemensInputStruct)message; const ushort head = 0x0300; const ushort len = 0x0016; const byte contentLen = 0x11; @@ -232,23 +232,23 @@ namespace Modbus.Net.Siemens switch (messageBytes[pos]) { case 0xc0: - { - pos += 2; - tdpuSize = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos); - break; - } + { + pos += 2; + tdpuSize = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos); + break; + } case 0xc1: - { - pos += 2; - srcTsap = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos); - break; - } + { + pos += 2; + srcTsap = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos); + break; + } case 0xc2: - { - pos += 2; - dstTsap = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos); - break; - } + { + pos += 2; + dstTsap = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos); + break; + } } return new CreateReferenceSiemensOutputStruct(tdpuSize, srcTsap, dstTsap); } @@ -318,10 +318,10 @@ namespace Modbus.Net.Siemens /// 格式化数据 public override byte[] Format(IInputStruct message) { - var r_message = (ComConfirmMessageSiemensInputStruct) message; + var r_message = (ComConfirmMessageSiemensInputStruct)message; var crc = r_message.SlaveAddress + r_message.MasterAddress + 0x5c % 256; - return Format((byte) 0x10, r_message.SlaveAddress, r_message.MasterAddress, (byte) 0x5c, (byte) crc, - (byte) 0x16); + return Format((byte)0x10, r_message.SlaveAddress, r_message.MasterAddress, (byte)0x5c, (byte)crc, + (byte)0x16); } /// @@ -378,7 +378,7 @@ namespace Modbus.Net.Siemens { public override byte[] Format(IInputStruct message) { - var r_message = (EstablishAssociationSiemensInputStruct) message; + var r_message = (EstablishAssociationSiemensInputStruct)message; const byte protoId = 0x32; const byte rosctr = 0x01; const ushort redId = 0x0000; @@ -431,12 +431,12 @@ namespace Modbus.Net.Siemens SlaveAddress = slaveAddress; MasterAddress = masterAddress; PduRef = pduRef; - TypeCode = (byte) getType; + TypeCode = (byte)getType; var address = addressTranslator.AddressTranslate(startAddress, true); Offset = address.Address; var area = address.Area; - Area = (byte) (area % 256); - DbBlock = Area == 0x84 ? (ushort) (area / 256) : (ushort) 0; + Area = (byte)(area % 256); + DbBlock = Area == 0x84 ? (ushort)(area / 256) : (ushort)0; NumberOfElements = getCount; } @@ -542,7 +542,7 @@ namespace Modbus.Net.Siemens /// 格式化数据 public override byte[] Format(IInputStruct message) { - var r_message = (ReadRequestSiemensInputStruct) message; + var r_message = (ReadRequestSiemensInputStruct)message; var slaveAddress = r_message.SlaveAddress; var masterAddress = r_message.MasterAddress; const byte protoId = 0x32; @@ -562,7 +562,7 @@ namespace Modbus.Net.Siemens var area = r_message.Area; var offsetBit = r_message.Offset * 8; var offsetBitBytes = BigEndianValueHelper.Instance.GetBytes(offsetBit); - return Format(new byte[4], slaveAddress, masterAddress, (byte) 0x6c, protoId, rosctr, redId, pduRef, parLg, + return Format(new byte[4], slaveAddress, masterAddress, (byte)0x6c, protoId, rosctr, redId, pduRef, parLg, datLg, serviceId, numberOfVariables , variableSpec, vAddrLg, syntaxId, type, numberOfElements, dbBlock, area, offsetBitBytes.Skip(1).ToArray()); @@ -585,8 +585,8 @@ namespace Modbus.Net.Siemens var byteLength = length / 8; var values = new byte[byteLength]; Array.Copy(messageBytes, pos, values, 0, byteLength); - return new ReadRequestSiemensOutputStruct(pduRef, (SiemensAccessResult) accessResult, - (SiemensDataType) dataType, length, values); + return new ReadRequestSiemensOutputStruct(pduRef, (SiemensAccessResult)accessResult, + (SiemensDataType)dataType, length, values); } } @@ -617,8 +617,8 @@ namespace Modbus.Net.Siemens var address = addressTranslator.AddressTranslate(startAddress, true); Offset = address.Address; var area = address.Area; - Area = (byte) (area % 256); - DbBlock = Area == 0x84 ? (ushort) (area / 256) : (ushort) 0; + Area = (byte)(area % 256); + DbBlock = Area == 0x84 ? (ushort)(area / 256) : (ushort)0; WriteValue = writeValue; } @@ -697,7 +697,7 @@ namespace Modbus.Net.Siemens /// 格式化数据 public override byte[] Format(IInputStruct message) { - var r_message = (WriteRequestSiemensInputStruct) message; + var r_message = (WriteRequestSiemensInputStruct)message; var valueBytes = BigEndianValueHelper.Instance.ObjectArrayToByteArray(r_message.WriteValue); var slaveAddress = r_message.SlaveAddress; var masterAddress = r_message.MasterAddress; @@ -706,22 +706,22 @@ namespace Modbus.Net.Siemens const ushort redId = 0x0000; var pduRef = r_message.PduRef; const ushort parLg = 14; // 参数字节数(2+12的倍数),目前仅为14 - var datLg = (ushort) (4 + valueBytes.Length); // 数据字节数 + var datLg = (ushort)(4 + valueBytes.Length); // 数据字节数 const byte serviceId = 0x05; const byte numberOfVariables = 1; const byte variableSpec = 0x12; const byte vAddrLg = 0x0A; const byte syntaxId = 0x10; - const byte typeR = (byte) SiemensTypeCode.Byte; - var numberOfElements = (ushort) valueBytes.Length; + const byte typeR = (byte)SiemensTypeCode.Byte; + var numberOfElements = (ushort)valueBytes.Length; var dbBlock = r_message.DbBlock; var area = r_message.Area; var offsetBit = r_message.Offset * 8; var offsetBitBytes = BigEndianValueHelper.Instance.GetBytes(offsetBit); const byte reserved = 0x00; - const byte type = (byte) SiemensDataType.OtherAccess; - var numberOfWriteBits = (ushort) (valueBytes.Length * 8); - return Format(new byte[4], slaveAddress, masterAddress, (byte) 0x7c, protoId, rosctr, redId, pduRef, parLg, + const byte type = (byte)SiemensDataType.OtherAccess; + var numberOfWriteBits = (ushort)(valueBytes.Length * 8); + return Format(new byte[4], slaveAddress, masterAddress, (byte)0x7c, protoId, rosctr, redId, pduRef, parLg, datLg, serviceId, numberOfVariables , variableSpec, vAddrLg, syntaxId, typeR, numberOfElements, dbBlock, area, offsetBitBytes.Skip(1).ToArray(), reserved, type, numberOfWriteBits, valueBytes); @@ -747,7 +747,7 @@ namespace Modbus.Net.Siemens var pduRef = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos); pos = 14; var accessResult = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos); - return new WriteRequestSiemensOutputStruct(pduRef, (SiemensAccessResult) accessResult); + return new WriteRequestSiemensOutputStruct(pduRef, (SiemensAccessResult)accessResult); } } } diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensProtocolLinkerBytesExtend.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensProtocolLinkerBytesExtend.cs index 79433e1..6adf06b 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensProtocolLinkerBytesExtend.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensProtocolLinkerBytesExtend.cs @@ -14,8 +14,8 @@ namespace Modbus.Net.Siemens /// 扩展后的协议内容 public byte[] BytesExtend(byte[] content) { - Array.Copy(new byte[] {0x03, 0x00, 0x00, 0x00, 0x02, 0xf0, 0x80}, 0, content, 0, 7); - Array.Copy(BigEndianValueHelper.Instance.GetBytes((ushort) content.Length), 0, content, 2, 2); + Array.Copy(new byte[] { 0x03, 0x00, 0x00, 0x00, 0x02, 0xf0, 0x80 }, 0, content, 0, 7); + Array.Copy(BigEndianValueHelper.Instance.GetBytes((ushort)content.Length), 0, content, 2, 2); return content; } @@ -46,13 +46,13 @@ namespace Modbus.Net.Siemens { var newContent = new byte[content.Length + 2]; Array.Copy(content, 0, newContent, 0, content.Length); - Array.Copy(new byte[] {0x68, (byte) (content.Length - 4), (byte) (content.Length - 4), 0x68}, 0, newContent, + Array.Copy(new byte[] { 0x68, (byte)(content.Length - 4), (byte)(content.Length - 4), 0x68 }, 0, newContent, 0, 4); var check = 0; for (var i = 4; i < newContent.Length - 2; i++) check += newContent[i]; check = check % 256; - newContent[newContent.Length - 2] = (byte) check; + newContent[newContent.Length - 2] = (byte)check; newContent[newContent.Length - 1] = 0x16; return newContent; } diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocol.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocol.cs index f986ddb..3993f16 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocol.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocol.cs @@ -1,6 +1,6 @@ -using System.Threading.Tasks; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration; using Nito.AsyncEx; +using System.Threading.Tasks; namespace Modbus.Net.Siemens { diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocolLinker.cs index 90d5274..c576005 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocolLinker.cs @@ -26,7 +26,7 @@ namespace Modbus.Net.Siemens public SiemensTcpProtocolLinker(string ip, int port) : base(ip, port) { - ((BaseConnector)BaseConnector).AddController(new MatchDirectlySendController(new ICollection<(int,int)>[] { new List<(int,int)> { (11,11), (12,12) } }, DuplicateWithCount.GetDuplcateFunc(new List{2, 3}, 0), 100)); + ((BaseConnector)BaseConnector).AddController(new MatchDirectlySendController(new ICollection<(int, int)>[] { new List<(int, int)> { (11, 11), (12, 12) } }, DuplicateWithCount.GetDuplcateFunc(new List { 2, 3 }, 0), 100)); } /// diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensUtility.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensUtility.cs index eb8bbf6..a136f56 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensUtility.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensUtility.cs @@ -1,6 +1,6 @@ -using System; +using Microsoft.Extensions.Logging; +using System; using System.Threading.Tasks; -using Serilog; namespace Modbus.Net.Siemens { @@ -59,6 +59,8 @@ namespace Modbus.Net.Siemens /// public class SiemensUtility : BaseUtility { + private static readonly ILogger logger = LogProvider.CreateLogger(); + private readonly ushort _maxCalled; private readonly ushort _maxCalling; private readonly ushort _maxPdu; @@ -89,51 +91,51 @@ namespace Modbus.Net.Siemens switch (model) { case SiemensMachineModel.S7_200: - { - _tdpuSize = 0x09; - _taspSrc = (ushort)(0x1000 + src); - _tsapDst = (ushort)(0x1000 + dst); - _maxCalling = 0x0001; - _maxCalled = 0x0001; - _maxPdu = 0x03c0; - break; - } + { + _tdpuSize = 0x09; + _taspSrc = (ushort)(0x1000 + src); + _tsapDst = (ushort)(0x1000 + dst); + _maxCalling = 0x0001; + _maxCalled = 0x0001; + _maxPdu = 0x03c0; + break; + } case SiemensMachineModel.S7_300: case SiemensMachineModel.S7_400: - { - _tdpuSize = 0x1a; - _taspSrc = 0x4b54; - _tsapDst = (ushort)(0x0300 + dst); - _maxCalling = 0x0001; - _maxCalled = 0x0001; - _maxPdu = 0x00f0; - break; - } + { + _tdpuSize = 0x1a; + _taspSrc = 0x4b54; + _tsapDst = (ushort)(0x0300 + dst); + _maxCalling = 0x0001; + _maxCalled = 0x0001; + _maxPdu = 0x00f0; + break; + } case SiemensMachineModel.S7_1200: case SiemensMachineModel.S7_1500: - { - _tdpuSize = 0x0a; - _taspSrc = 0x1011; - _tsapDst = (ushort)(0x0300 + dst); + { + _tdpuSize = 0x0a; + _taspSrc = 0x1011; + _tsapDst = (ushort)(0x0300 + dst); _maxCalling = 0x0003; - _maxCalled = 0x0003; - _maxPdu = 0x0100; - break; - } + _maxCalled = 0x0003; + _maxPdu = 0x0100; + break; + } case SiemensMachineModel.S7_200_Smart: - { - _tdpuSize = 0x0a; - _taspSrc = 0x0101; - _tsapDst = 0x0101; - _maxCalling = 0x0001; - _maxCalled = 0x0001; - _maxPdu = 0x03c0; - break; - } + { + _tdpuSize = 0x0a; + _taspSrc = 0x0101; + _tsapDst = 0x0101; + _maxCalling = 0x0001; + _maxCalled = 0x0001; + _maxPdu = 0x03c0; + break; + } default: - { - throw new NotImplementedException("Siemens PLC Model not Supported"); - } + { + throw new NotImplementedException("Siemens PLC Model not Supported"); + } } ConnectionType = connectionType; AddressTranslator = new AddressTranslatorSiemens(); @@ -169,11 +171,11 @@ namespace Modbus.Net.Siemens var connectionStringSplit = ConnectionString.Split(':'); try { - return connectionStringSplit.Length < 2 ? (int?) null : int.Parse(connectionStringSplit[1]); + return connectionStringSplit.Length < 2 ? (int?)null : int.Parse(connectionStringSplit[1]); } catch (Exception e) { - Log.Error(e, $"SiemensUtility: {ConnectionString} format error"); + logger.LogError(e, $"SiemensUtility: {ConnectionString} format error"); return null; } } @@ -192,29 +194,29 @@ namespace Modbus.Net.Siemens { //PPI case SiemensType.Ppi: - { - Wrapper = ConnectionString == null - ? new SiemensPpiProtocol(SlaveAddress, MasterAddress) - : new SiemensPpiProtocol(ConnectionString, SlaveAddress, MasterAddress); - break; - } + { + Wrapper = ConnectionString == null + ? new SiemensPpiProtocol(SlaveAddress, MasterAddress) + : new SiemensPpiProtocol(ConnectionString, SlaveAddress, MasterAddress); + break; + } //MPI case SiemensType.Mpi: - { - throw new NotImplementedException(); - } + { + throw new NotImplementedException(); + } //Ethenet case SiemensType.Tcp: - { - Wrapper = ConnectionString == null - ? new SiemensTcpProtocol(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu) - : (ConnectionStringPort == null - ? new SiemensTcpProtocol(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu, - ConnectionString) - : new SiemensTcpProtocol(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu, - ConnectionStringIp, ConnectionStringPort.Value)); - break; - } + { + Wrapper = ConnectionString == null + ? new SiemensTcpProtocol(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu) + : (ConnectionStringPort == null + ? new SiemensTcpProtocol(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu, + ConnectionString) + : new SiemensTcpProtocol(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu, + ConnectionStringIp, ConnectionStringPort.Value)); + break; + } } } } @@ -225,7 +227,7 @@ namespace Modbus.Net.Siemens /// 需要设置的连接类型 public override void SetConnectionType(int connectionType) { - ConnectionType = (SiemensType) connectionType; + ConnectionType = (SiemensType)connectionType; } /// @@ -244,7 +246,7 @@ namespace Modbus.Net.Siemens _sendCount = (ushort)(_sendCount % ushort.MaxValue + 1); readRequestSiemensInputStruct = new ReadRequestSiemensInputStruct(SlaveAddress, MasterAddress, _sendCount, SiemensTypeCode.Byte, startAddress, (ushort)getByteCount, AddressTranslator); - } + } var readRequestSiemensOutputStruct = await Wrapper.SendReceiveAsync( @@ -254,7 +256,7 @@ namespace Modbus.Net.Siemens } catch (Exception e) { - Log.Error(e, $"SiemensUtility -> GetDatas: {ConnectionString} error"); + logger.LogError(e, $"SiemensUtility -> GetDatas: {ConnectionString} error"); return null; } } @@ -275,7 +277,7 @@ namespace Modbus.Net.Siemens _sendCount = (ushort)(_sendCount % ushort.MaxValue + 1); writeRequestSiemensInputStruct = new WriteRequestSiemensInputStruct(SlaveAddress, MasterAddress, _sendCount, startAddress, setContents, AddressTranslator); - } + } var writeRequestSiemensOutputStruct = await Wrapper.SendReceiveAsync( @@ -285,7 +287,7 @@ namespace Modbus.Net.Siemens } catch (Exception e) { - Log.Error(e, $"ModbusUtility -> SetDatas: {ConnectionString} error"); + logger.LogError(e, $"ModbusUtility -> SetDatas: {ConnectionString} error"); return false; } } diff --git a/Modbus.Net/Modbus.Net/Connector/BaseConnector.cs b/Modbus.Net/Modbus.Net/Connector/BaseConnector.cs index bc33512..c0f3052 100644 --- a/Modbus.Net/Modbus.Net/Connector/BaseConnector.cs +++ b/Modbus.Net/Modbus.Net/Connector/BaseConnector.cs @@ -1,18 +1,20 @@ -using System; -using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using Nito.AsyncEx; -using Serilog; +using System; +using System.Threading.Tasks; namespace Modbus.Net { /// public abstract class BaseConnector : BaseConnector { + private static readonly ILogger logger = LogProvider.CreateLogger(); + /// /// 发送锁 /// protected abstract AsyncLock Lock { get; } - + /// /// 是否为全双工 /// @@ -51,7 +53,7 @@ namespace Modbus.Net { IDisposable asyncLock = null; try - { + { var messageSendingdef = Controller.AddMessage(message); if (messageSendingdef != null) { @@ -71,12 +73,12 @@ namespace Modbus.Net } Controller.ForceRemoveWaitingMessage(messageSendingdef); } - Log.Information("Message is waiting in {0}. Cancel!", ConnectionToken); + logger.LogInformation("Message is waiting in {0}. Cancel!", ConnectionToken); return null; } catch (Exception e) { - Log.Error(e, "Connector {0} Send Error.", ConnectionToken); + logger.LogError(e, "Connector {0} Send Error.", ConnectionToken); return null; } finally @@ -149,14 +151,14 @@ namespace Modbus.Net /// protected abstract void ReceiveMsgThreadStop(); - /// - /// 数据返回代理函数 - /// - /// - /// + /// + /// 数据返回代理函数 + /// + /// + /// protected TParamIn InvokeReturnMessage(TParamOut receiveMessage) { - return MessageReturn?.Invoke(this, new MessageReturnArgs{ReturnMessage = receiveMessage})?.SendMessage; + return MessageReturn?.Invoke(this, new MessageReturnArgs { ReturnMessage = receiveMessage })?.SendMessage; } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/Connector/ComConnector.cs b/Modbus.Net/Modbus.Net/Connector/ComConnector.cs index 3fa7d0f..d752069 100644 --- a/Modbus.Net/Modbus.Net/Connector/ComConnector.cs +++ b/Modbus.Net/Modbus.Net/Connector/ComConnector.cs @@ -1,11 +1,11 @@ -using System; +using Microsoft.Extensions.Logging; +using Nito.AsyncEx; +using System; using System.Collections.Generic; using System.IO.Ports; using System.Linq; using System.Threading; using System.Threading.Tasks; -using Nito.AsyncEx; -using Serilog; namespace Modbus.Net { @@ -25,6 +25,8 @@ namespace Modbus.Net /// public class ComConnector : BaseConnector, IDisposable { + private static readonly ILogger logger = LogProvider.CreateLogger(); + /// /// 波特率 /// @@ -124,7 +126,8 @@ namespace Modbus.Net ; /// - protected override IController Controller { + protected override IController Controller + { get { if (Controllers.ContainsKey(_com)) @@ -139,7 +142,7 @@ namespace Modbus.Net { Controllers.Add(_com, value); } - } + } } /// @@ -198,7 +201,7 @@ namespace Modbus.Net while (SerialPort.BytesToRead > 0) { - readBuf[nBytelen] = (byte) SerialPort.ReadByte(); + readBuf[nBytelen] = (byte)SerialPort.ReadByte(); var bTmp = new byte[bufRoom]; Array.Clear(bTmp, 0, bTmp.Length); @@ -235,7 +238,7 @@ namespace Modbus.Net while (nBytelen < readRoom - 1 && SerialPort.BytesToRead > 0) { - readBuf[nBytelen] = (byte) SerialPort.ReadByte(); + readBuf[nBytelen] = (byte)SerialPort.ReadByte(); nBytelen++; // add one } readBuf[nBytelen] = 0x00; @@ -265,14 +268,14 @@ namespace Modbus.Net SerialPort.Close(); } SerialPort.Dispose(); - Log.Information("Com interface {Com} Disposed", _com); + logger.LogInformation("Com interface {Com} Disposed", _com); Connectors[_com] = null; Connectors.Remove(_com); ReceiveMsgThreadStop(); } Linkers.Remove(_slave); - Log.Information("Com connector {ConnectionToken} Removed", ConnectionToken); - } + logger.LogInformation("Com connector {ConnectionToken} Removed", ConnectionToken); + } m_disposed = true; } } @@ -289,19 +292,19 @@ namespace Modbus.Net private void RefreshSendCount() { _sendCount++; - Log.Verbose("Com client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount); + logger.LogDebug("Com client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount); } private void RefreshReceiveCount() { _receiveCount++; - Log.Verbose("Com client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount); + logger.LogDebug("Com client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount); } private void RefreshErrorCount() { _errorCount++; - Log.Verbose("Com client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount); + logger.LogDebug("Com client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount); } /// @@ -352,14 +355,14 @@ namespace Modbus.Net } } } - - Log.Information("Com client {ConnectionToken} connect success", ConnectionToken); + + logger.LogInformation("Com client {ConnectionToken} connect success", ConnectionToken); return true; } catch (Exception e) { - Log.Error(e, "Com client {ConnectionToken} connect error", ConnectionToken); + logger.LogError(e, "Com client {ConnectionToken} connect error", ConnectionToken); Dispose(); return false; } @@ -378,15 +381,15 @@ namespace Modbus.Net try { Dispose(); - Log.Information("Com client {ConnectionToken} disconnect success", ConnectionToken); + logger.LogInformation("Com client {ConnectionToken} disconnect success", ConnectionToken); return true; } catch (Exception e) { - Log.Error(e, "Com client {ConnectionToken} disconnect error", ConnectionToken); + logger.LogError(e, "Com client {ConnectionToken} disconnect error", ConnectionToken); return false; } - Log.Error(new Exception("Linkers or Connectors Dictionary not found"), + logger.LogError(new Exception("Linkers or Connectors Dictionary not found"), "Com client {ConnectionToken} disconnect error", ConnectionToken); return false; } @@ -420,7 +423,7 @@ namespace Modbus.Net } catch (Exception err) { - Log.Error(err, "Com client {ConnectionToken} open error", ConnectionToken); + logger.LogError(err, "Com client {ConnectionToken} open error", ConnectionToken); Dispose(); try { @@ -428,7 +431,7 @@ namespace Modbus.Net } catch (Exception err2) { - Log.Error(err2, "Com client {ConnectionToken} open error", ConnectionToken); + logger.LogError(err2, "Com client {ConnectionToken} open error", ConnectionToken); Dispose(); } } @@ -447,15 +450,15 @@ namespace Modbus.Net { try { - Log.Verbose("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken, + logger.LogDebug("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken, message.Length); - Log.Verbose( + logger.LogDebug( $"Com client {ConnectionToken} send msg: {String.Concat(message.Select(p => " " + p.ToString("X2")))}"); await Task.Run(() => SerialPort.Write(message, 0, message.Length)); } catch (Exception err) { - Log.Error(err, "Com client {ConnectionToken} send msg error", ConnectionToken); + logger.LogError(err, "Com client {ConnectionToken} send msg error", ConnectionToken); Dispose(); } RefreshSendCount(); @@ -464,7 +467,7 @@ namespace Modbus.Net /// protected override void ReceiveMsgThreadStart() { - _receiveThread = Task.Run(()=>ReceiveMessage()); + _receiveThread = Task.Run(() => ReceiveMessage()); } /// @@ -483,9 +486,9 @@ namespace Modbus.Net var returnBytes = ReadMsg(); if (returnBytes != null) { - Log.Verbose("Com client {ConnectionToken} receive msg length: {Length}", ConnectionToken, + logger.LogDebug("Com client {ConnectionToken} receive msg length: {Length}", ConnectionToken, returnBytes.Length); - Log.Verbose( + logger.LogDebug( $"Com client {ConnectionToken} receive msg: {String.Concat(returnBytes.Select(p => " " + p.ToString("X2")))}"); var isMessageConfirmed = Controller.ConfirmMessage(returnBytes); @@ -498,11 +501,11 @@ namespace Modbus.Net } RefreshReceiveCount(); - } + } } catch (Exception e) { - Log.Error(e, "Com client {ConnectionToken} read msg error", ConnectionToken); + logger.LogError(e, "Com client {ConnectionToken} read msg error", ConnectionToken); } } } @@ -524,7 +527,7 @@ namespace Modbus.Net } catch (Exception e) { - Log.Error(e, "Com client {ConnectionToken} read error", ConnectionToken); + logger.LogError(e, "Com client {ConnectionToken} read error", ConnectionToken); RefreshErrorCount(); Dispose(); return null; diff --git a/Modbus.Net/Modbus.Net/Connector/MessageEventArgs.cs b/Modbus.Net/Modbus.Net/Connector/MessageEventArgs.cs index 2abe6ee..c8929f3 100644 --- a/Modbus.Net/Modbus.Net/Connector/MessageEventArgs.cs +++ b/Modbus.Net/Modbus.Net/Connector/MessageEventArgs.cs @@ -1,5 +1,5 @@ namespace Modbus.Net -{ +{ /// /// 数据返回代理参数 /// @@ -12,7 +12,7 @@ public TParamOut ReturnMessage { get; set; } } - + /// /// 数据发送代理参数 /// diff --git a/Modbus.Net/Modbus.Net/Connector/TcpConnector.cs b/Modbus.Net/Modbus.Net/Connector/TcpConnector.cs index da790bb..b859afa 100644 --- a/Modbus.Net/Modbus.Net/Connector/TcpConnector.cs +++ b/Modbus.Net/Modbus.Net/Connector/TcpConnector.cs @@ -1,10 +1,10 @@ -using System; +using Microsoft.Extensions.Logging; +using Nito.AsyncEx; +using System; using System.Linq; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; -using Nito.AsyncEx; -using Serilog; namespace Modbus.Net { @@ -14,6 +14,8 @@ namespace Modbus.Net /// public class TcpConnector : BaseConnector, IDisposable { + private static readonly ILogger logger = LogProvider.CreateLogger(); + private readonly string _host; private readonly int _port; @@ -53,7 +55,7 @@ namespace Modbus.Net /// protected override int TimeoutTime { - get => + get => _timeoutTime; set { @@ -94,7 +96,7 @@ namespace Modbus.Net { CloseClientSocket(); _socketClient = null; - Log.Debug("Tcp client {ConnectionToken} Disposed", ConnectionToken); + logger.LogDebug("Tcp client {ConnectionToken} Disposed", ConnectionToken); } } @@ -134,16 +136,16 @@ namespace Modbus.Net _taskCancel = false; Controller.SendStart(); ReceiveMsgThreadStart(); - Log.Information("Tcp client {ConnectionToken} connected", ConnectionToken); + logger.LogInformation("Tcp client {ConnectionToken} connected", ConnectionToken); return true; } - Log.Error("Tcp client {ConnectionToken} connect failed.", ConnectionToken); + logger.LogError("Tcp client {ConnectionToken} connect failed.", ConnectionToken); Dispose(); return false; } catch (Exception err) { - Log.Error(err, "Tcp client {ConnectionToken} connect exception", ConnectionToken); + logger.LogError(err, "Tcp client {ConnectionToken} connect exception", ConnectionToken); Dispose(); return false; } @@ -159,12 +161,12 @@ namespace Modbus.Net try { Dispose(); - Log.Information("Tcp client {ConnectionToken} disconnected successfully", ConnectionToken); + logger.LogInformation("Tcp client {ConnectionToken} disconnected successfully", ConnectionToken); return true; } catch (Exception err) { - Log.Error(err, "Tcp client {ConnectionToken} disconnected exception", ConnectionToken); + logger.LogError(err, "Tcp client {ConnectionToken} disconnected exception", ConnectionToken); return false; } finally @@ -187,13 +189,13 @@ namespace Modbus.Net RefreshSendCount(); - Log.Verbose("Tcp client {ConnectionToken} send text len = {Length}", ConnectionToken, datagram.Length); - Log.Verbose($"Tcp client {ConnectionToken} send: {String.Concat(datagram.Select(p => " " + p.ToString("X2")))}"); + logger.LogDebug("Tcp client {ConnectionToken} send text len = {Length}", ConnectionToken, datagram.Length); + logger.LogDebug($"Tcp client {ConnectionToken} send: {String.Concat(datagram.Select(p => " " + p.ToString("X2")))}"); await stream.WriteAsync(datagram, 0, datagram.Length); } catch (Exception err) { - Log.Error(err, "Tcp client {ConnectionToken} send exception", ConnectionToken); + logger.LogError(err, "Tcp client {ConnectionToken} send exception", ConnectionToken); Dispose(); } } @@ -229,9 +231,9 @@ namespace Modbus.Net if (len > 0) { byte[] receiveBytes = CheckReplyDatagram(len); - Log.Verbose("Tcp client {ConnectionToken} receive text len = {Length}", ConnectionToken, + logger.LogDebug("Tcp client {ConnectionToken} receive text len = {Length}", ConnectionToken, receiveBytes.Length); - Log.Verbose( + logger.LogDebug( $"Tcp client {ConnectionToken} receive: {String.Concat(receiveBytes.Select(p => " " + p.ToString("X2")))}"); var isMessageConfirmed = Controller.ConfirmMessage(receiveBytes); foreach (var confirmed in isMessageConfirmed) @@ -246,7 +248,7 @@ namespace Modbus.Net } } } - + RefreshReceiveCount(); } } @@ -257,7 +259,7 @@ namespace Modbus.Net } catch (Exception err) { - Log.Error(err, "Tcp client {ConnectionToken} receive exception", ConnectionToken); + logger.LogError(err, "Tcp client {ConnectionToken} receive exception", ConnectionToken); //CloseClientSocket(); } } @@ -280,19 +282,19 @@ namespace Modbus.Net private void RefreshSendCount() { _sendCount++; - Log.Verbose("Tcp client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount); + logger.LogDebug("Tcp client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount); } private void RefreshReceiveCount() { _receiveCount++; - Log.Verbose("Tcp client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount); + logger.LogDebug("Tcp client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount); } private void RefreshErrorCount() { _errorCount++; - Log.Verbose("Tcp client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount); + logger.LogDebug("Tcp client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount); } private void CloseClientSocket() @@ -307,12 +309,12 @@ namespace Modbus.Net if (_socketClient.Connected) { _socketClient.Close(); - } + } } } catch (Exception ex) { - Log.Error(ex, "Tcp client {ConnectionToken} client close exception", ConnectionToken); + logger.LogError(ex, "Tcp client {ConnectionToken} client close exception", ConnectionToken); } } } diff --git a/Modbus.Net/Modbus.Net/Connector/UdpConnector.cs b/Modbus.Net/Modbus.Net/Connector/UdpConnector.cs index 0eb94d9..0f2cb5d 100644 --- a/Modbus.Net/Modbus.Net/Connector/UdpConnector.cs +++ b/Modbus.Net/Modbus.Net/Connector/UdpConnector.cs @@ -1,10 +1,10 @@ -using System; +using Microsoft.Extensions.Logging; +using Nito.AsyncEx; +using System; using System.Linq; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; -using Nito.AsyncEx; -using Serilog; namespace Modbus.Net { @@ -13,6 +13,8 @@ namespace Modbus.Net /// public class UdpConnector : BaseConnector, IDisposable { + private static readonly ILogger logger = LogProvider.CreateLogger(); + private readonly string _host; private readonly int _port; @@ -81,7 +83,7 @@ namespace Modbus.Net { CloseClientSocket(); _socketClient = null; - Log.Debug("Udp client {ConnectionToken} Disposed", ConnectionToken); + logger.LogDebug("Udp client {ConnectionToken} Disposed", ConnectionToken); } } @@ -101,7 +103,7 @@ namespace Modbus.Net { if (_socketClient != null) { - return true; + return true; } try { @@ -116,17 +118,17 @@ namespace Modbus.Net _taskCancel = false; Controller.SendStart(); ReceiveMsgThreadStart(); - Log.Information("Udp client {ConnectionToken} connected", ConnectionToken); + logger.LogInformation("Udp client {ConnectionToken} connected", ConnectionToken); return true; } - Log.Error("Udp client {ConnectionToken} connect failed.", ConnectionToken); + logger.LogError("Udp client {ConnectionToken} connect failed.", ConnectionToken); Dispose(); return false; } catch (Exception err) { - Log.Error(err, "Udp client {ConnectionToken} connect exception", ConnectionToken); + logger.LogError(err, "Udp client {ConnectionToken} connect exception", ConnectionToken); Dispose(); return false; } @@ -142,12 +144,12 @@ namespace Modbus.Net try { Dispose(); - Log.Information("Udp client {ConnectionToken} disconnected successfully", ConnectionToken); + logger.LogInformation("Udp client {ConnectionToken} disconnected successfully", ConnectionToken); return true; } catch (Exception err) { - Log.Error(err, "Udp client {ConnectionToken} disconnected exception", ConnectionToken); + logger.LogError(err, "Udp client {ConnectionToken} disconnected exception", ConnectionToken); return false; } finally @@ -168,13 +170,13 @@ namespace Modbus.Net RefreshSendCount(); - Log.Verbose("Udp client {ConnectionToken} send text len = {Length}", ConnectionToken, datagram.Length); - Log.Verbose($"Udp client {ConnectionToken} send: {String.Concat(datagram.Select(p => " " + p.ToString("X2")))}"); + logger.LogDebug("Udp client {ConnectionToken} send text len = {Length}", ConnectionToken, datagram.Length); + logger.LogDebug($"Udp client {ConnectionToken} send: {String.Concat(datagram.Select(p => " " + p.ToString("X2")))}"); await _socketClient.SendAsync(datagram, datagram.Length); } catch (Exception err) { - Log.Error(err, "Udp client {ConnectionToken} send exception", ConnectionToken); + logger.LogError(err, "Udp client {ConnectionToken} send exception", ConnectionToken); Dispose(); } } @@ -210,9 +212,9 @@ namespace Modbus.Net { if (receive.Buffer.Clone() is byte[] receiveBytes) { - Log.Verbose("Udp client {ConnectionToken} receive text len = {Length}", ConnectionToken, + logger.LogDebug("Udp client {ConnectionToken} receive text len = {Length}", ConnectionToken, receiveBytes.Length); - Log.Verbose( + logger.LogDebug( $"Udp client {ConnectionToken} receive: {String.Concat(receiveBytes.Select(p => " " + p.ToString("X2")))}"); var isMessageConfirmed = Controller.ConfirmMessage(receiveBytes); foreach (var confirmed in isMessageConfirmed) @@ -239,7 +241,7 @@ namespace Modbus.Net } catch (Exception err) { - Log.Error(err, "Udp client {ConnectionToken} receive exception", ConnectionToken); + logger.LogError(err, "Udp client {ConnectionToken} receive exception", ConnectionToken); //CloseClientSocket(); } } @@ -247,19 +249,19 @@ namespace Modbus.Net private void RefreshSendCount() { _sendCount++; - Log.Verbose("Udp client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount); + logger.LogDebug("Udp client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount); } private void RefreshReceiveCount() { _receiveCount++; - Log.Verbose("Udp client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount); + logger.LogDebug("Udp client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount); } private void RefreshErrorCount() { _errorCount++; - Log.Verbose("Udp client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount); + logger.LogDebug("Udp client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount); } private void CloseClientSocket() @@ -280,7 +282,7 @@ namespace Modbus.Net } catch (Exception ex) { - Log.Error(ex, "Udp client {ConnectionToken} client close exception", ConnectionToken); + logger.LogError(ex, "Udp client {ConnectionToken} client close exception", ConnectionToken); } } } diff --git a/Modbus.Net/Modbus.Net/Controller/BaseController.cs b/Modbus.Net/Modbus.Net/Controller/BaseController.cs index 80642ce..6284192 100644 --- a/Modbus.Net/Modbus.Net/Controller/BaseController.cs +++ b/Modbus.Net/Modbus.Net/Controller/BaseController.cs @@ -10,7 +10,7 @@ namespace Modbus.Net /// /// public abstract class BaseController : IController - { + { /// /// ȴϢ /// @@ -66,7 +66,7 @@ namespace Modbus.Net { if (SendingThread == null) { - SendingThread = Task.Run(()=>SendingMessageControlInner()); + SendingThread = Task.Run(() => SendingMessageControlInner()); } } @@ -101,14 +101,14 @@ namespace Modbus.Net /// /// ȷϵϢ /// Ϣļؼ - protected abstract (string,string)? GetKeyFromMessage(byte[] message); + protected abstract (string, string)? GetKeyFromMessage(byte[] message); /// public ICollection<(byte[], bool)> ConfirmMessage(byte[] receiveMessage) { var ans = new List<(byte[], bool)>(); var duplicatedMessages = DuplicateFunc?.Invoke(receiveMessage); - duplicatedMessages = duplicatedMessages ?? new List {receiveMessage}; + duplicatedMessages = duplicatedMessages ?? new List { receiveMessage }; foreach (var message in duplicatedMessages) { var def = GetMessageFromWaitingList(message); @@ -127,7 +127,7 @@ namespace Modbus.Net return ans; } - + /// /// ӵȴƥϢ diff --git a/Modbus.Net/Modbus.Net/Controller/FifoController.cs b/Modbus.Net/Modbus.Net/Controller/FifoController.cs index 503f4da..f69ccbc 100644 --- a/Modbus.Net/Modbus.Net/Controller/FifoController.cs +++ b/Modbus.Net/Modbus.Net/Controller/FifoController.cs @@ -1,8 +1,8 @@ -using System; +using Microsoft.Extensions.Logging; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; -using Serilog; namespace Modbus.Net { @@ -11,6 +11,8 @@ namespace Modbus.Net /// public class FifoController : BaseController { + private static readonly ILogger logger = LogProvider.CreateLogger(); + private MessageWaitingDef _currentSendingPos; private bool _taskCancel = false; @@ -39,7 +41,7 @@ namespace Modbus.Net { _taskCycleSema = new Semaphore(0, _waitingListMaxCount); } - AcquireTime = acquireTime; + AcquireTime = acquireTime; } /// @@ -66,7 +68,7 @@ namespace Modbus.Net sendSuccess = true; } } - else + else { if (WaitingMessages.Count <= 0) { @@ -83,7 +85,7 @@ namespace Modbus.Net } } if (sendSuccess) - { + { _taskCycleSema?.WaitOne(); } } @@ -94,7 +96,7 @@ namespace Modbus.Net } catch (Exception e) { - Log.Error(e, "Controller throws exception"); + logger.LogError(e, "Controller throws exception"); } } @@ -113,7 +115,7 @@ namespace Modbus.Net } /// - protected override (string,string)? GetKeyFromMessage(byte[] message) + protected override (string, string)? GetKeyFromMessage(byte[] message) { return null; } diff --git a/Modbus.Net/Modbus.Net/Controller/MatchController.cs b/Modbus.Net/Modbus.Net/Controller/MatchController.cs index 95f2331..4ce239d 100644 --- a/Modbus.Net/Modbus.Net/Controller/MatchController.cs +++ b/Modbus.Net/Modbus.Net/Controller/MatchController.cs @@ -12,7 +12,7 @@ namespace Modbus.Net /// /// 匹配字典 /// - protected ICollection<(int,int)>[] KeyMatches { get; } + protected ICollection<(int, int)>[] KeyMatches { get; } /// /// 构造器 @@ -29,7 +29,7 @@ namespace Modbus.Net } /// - protected override (string,string)? GetKeyFromMessage(byte[] message) + protected override (string, string)? GetKeyFromMessage(byte[] message) { string ans1 = ""; string ans2 = ""; diff --git a/Modbus.Net/Modbus.Net/Job/JobChainingJobListenerWithDataMap.cs b/Modbus.Net/Modbus.Net/Job/JobChainingJobListenerWithDataMap.cs index abcde6a..d25a122 100644 --- a/Modbus.Net/Modbus.Net/Job/JobChainingJobListenerWithDataMap.cs +++ b/Modbus.Net/Modbus.Net/Job/JobChainingJobListenerWithDataMap.cs @@ -1,6 +1,6 @@ -using Quartz.Listener; +using Microsoft.Extensions.Logging; using Quartz; -using Serilog; +using Quartz.Listener; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -12,6 +12,8 @@ namespace Modbus.Net /// public class JobChainingJobListenerWithDataMap : JobListenerSupport { + private static readonly ILogger logger = LogProvider.CreateLogger(); + /// /// JobChaningJobListener with DataMap passing from parent job to next job /// @@ -58,7 +60,7 @@ namespace Modbus.Net return; } - Log.Information("Job '{JobKey}' will now chain to Job '{Job}'", context.JobDetail.Key, sj); + logger.LogInformation("Job '{JobKey}' will now chain to Job '{Job}'", context.JobDetail.Key, sj); try { @@ -78,7 +80,7 @@ namespace Modbus.Net } catch (SchedulerException se) { - Log.Error(se, "Error encountered during chaining to Job '{Job}'", sj); + logger.LogError(se, "Error encountered during chaining to Job '{Job}'", sj); } } #nullable disable diff --git a/Modbus.Net/Modbus.Net/Job/MachineJobScheduler.cs b/Modbus.Net/Modbus.Net/Job/MachineJobScheduler.cs index b5eb778..8f63bc8 100644 --- a/Modbus.Net/Modbus.Net/Job/MachineJobScheduler.cs +++ b/Modbus.Net/Modbus.Net/Job/MachineJobScheduler.cs @@ -3,7 +3,6 @@ using Quartz.Impl; using Quartz.Impl.Matchers; using System; using System.Collections.Generic; -using System.Reflection.PortableExecutable; using System.Threading.Tasks; namespace Modbus.Net @@ -67,13 +66,13 @@ namespace Modbus.Net ITrigger trigger; if (count >= 0) trigger = TriggerBuilder.Create() - .WithIdentity(triggerKey, "Modbus.Net.DataQuery.Group."+ triggerKey) + .WithIdentity(triggerKey, "Modbus.Net.DataQuery.Group." + triggerKey) .StartNow() .WithSimpleSchedule(b => b.WithInterval(TimeSpan.FromSeconds(interval)).WithRepeatCount(count)) .Build(); else trigger = TriggerBuilder.Create() - .WithIdentity(triggerKey, "Modbus.Net.DataQuery.Group."+ triggerKey) + .WithIdentity(triggerKey, "Modbus.Net.DataQuery.Group." + triggerKey) .StartNow() .WithSimpleSchedule(b => b.WithInterval(TimeSpan.FromSeconds(interval)).RepeatForever()) .Build(); @@ -101,7 +100,7 @@ namespace Modbus.Net IScheduler scheduler = await StdSchedulerFactory.GetDefaultScheduler(); var jobKeys = await scheduler.GetJobKeys(GroupMatcher.GroupEquals("Modbus.Net.DataQuery.Group." + triggerKey)); await scheduler.UnscheduleJob(new TriggerKey(triggerKey, "Modbus.Net.DataQuery.Group." + triggerKey)); - await scheduler.DeleteJobs(jobKeys); + await scheduler.DeleteJobs(jobKeys); } } @@ -219,7 +218,7 @@ namespace Modbus.Net await _scheduler.AddJob(job, true); } else - { + { await _scheduler.ScheduleJob(job, _trigger); } @@ -395,7 +394,7 @@ namespace Modbus.Net await _scheduler.Start(); } } - + /// /// 处理写返回任务 /// @@ -544,7 +543,7 @@ namespace Modbus.Net /// /// 处理写返回任务 /// - public class MachineDealDataJob : IJob where TMachineKey: IEquatable + public class MachineDealDataJob : IJob where TMachineKey : IEquatable { /// public async Task Execute(IJobExecutionContext context) diff --git a/Modbus.Net/Modbus.Net/Linker/ComProtocolLinker.cs b/Modbus.Net/Modbus.Net/Linker/ComProtocolLinker.cs index dfebe1b..af7683d 100644 --- a/Modbus.Net/Modbus.Net/Linker/ComProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net/Linker/ComProtocolLinker.cs @@ -55,14 +55,14 @@ namespace Modbus.Net { if (connectionTimeout == -1) { - BaseConnector = new ComConnector(com + ":" + slaveAddress, baudRate, parity, stopBits, dataBits, isFullDuplex:isFullDuplex); + BaseConnector = new ComConnector(com + ":" + slaveAddress, baudRate, parity, stopBits, dataBits, isFullDuplex: isFullDuplex); } else { BaseConnector = new ComConnector(com + ":" + slaveAddress, baudRate, parity, stopBits, dataBits, - connectionTimeout, isFullDuplex:isFullDuplex); + connectionTimeout, isFullDuplex: isFullDuplex); } - + } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/Linker/TcpProtocolLinker.cs b/Modbus.Net/Modbus.Net/Linker/TcpProtocolLinker.cs index dba17cc..397f4e9 100644 --- a/Modbus.Net/Modbus.Net/Linker/TcpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net/Linker/TcpProtocolLinker.cs @@ -39,13 +39,13 @@ namespace Modbus.Net if (connectionTimeout == -1) { //初始化连接对象 - BaseConnector = new TcpConnector(ip, port, isFullDuplex:isFullDuplex); + BaseConnector = new TcpConnector(ip, port, isFullDuplex: isFullDuplex); } else { //初始化连接对象 - BaseConnector = new TcpConnector(ip, port, connectionTimeout, isFullDuplex:isFullDuplex); - } + BaseConnector = new TcpConnector(ip, port, connectionTimeout, isFullDuplex: isFullDuplex); + } } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/Linker/UdpProtocolLinker.cs b/Modbus.Net/Modbus.Net/Linker/UdpProtocolLinker.cs index a94625e..6b11779 100644 --- a/Modbus.Net/Modbus.Net/Linker/UdpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net/Linker/UdpProtocolLinker.cs @@ -39,12 +39,12 @@ namespace Modbus.Net if (connectionTimeout == -1) { //初始化连接对象 - BaseConnector = new UdpConnector(ip, port, isFullDuplex:isFullDuplex); + BaseConnector = new UdpConnector(ip, port, isFullDuplex: isFullDuplex); } else { //初始化连接对象 - BaseConnector = new UdpConnector(ip, port, connectionTimeout, isFullDuplex:isFullDuplex); + BaseConnector = new UdpConnector(ip, port, connectionTimeout, isFullDuplex: isFullDuplex); } } } diff --git a/Modbus.Net/Modbus.Net/Log/LogProvider.cs b/Modbus.Net/Modbus.Net/Log/LogProvider.cs new file mode 100644 index 0000000..0a9e0a2 --- /dev/null +++ b/Modbus.Net/Modbus.Net/Log/LogProvider.cs @@ -0,0 +1,43 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; + +namespace Modbus.Net +{ + /// + /// + /// + public static class LogProvider + { + private static ILoggerFactory _loggerFactory = null; + + /// + /// Sets the current log provider based on logger factory. + /// + /// The logger factory. + public static void SetLogProvider(ILoggerFactory loggerFactory) + { + _loggerFactory = loggerFactory; + } + + /// + /// + /// + /// + /// + public static ILogger CreateLogger(string category) => _loggerFactory != null ? _loggerFactory.CreateLogger(category) : NullLogger.Instance; + /// + /// + /// + /// + /// + public static ILogger CreateLogger() => _loggerFactory != null ? _loggerFactory.CreateLogger() : NullLogger.Instance; + +#if DIAGNOSTICS_SOURCE + internal static class Cached + { + internal static readonly System.Lazy Default = + new(() => new System.Diagnostics.DiagnosticListener(DiagnosticHeaders.DefaultListenerName)); + } +#endif + } +} \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/Machine/AddressCombiner.cs b/Modbus.Net/Modbus.Net/Machine/AddressCombiner.cs index 1d4c243..c059e0c 100644 --- a/Modbus.Net/Modbus.Net/Machine/AddressCombiner.cs +++ b/Modbus.Net/Modbus.Net/Machine/AddressCombiner.cs @@ -75,12 +75,12 @@ namespace Modbus.Net { //按从小到大的顺序对地址进行排序 var groupedAddresses = from address in addresses - orderby - AddressHelper.GetProtocolCoordinate(address.Address, address.SubAddress, - AddressTranslator.GetAreaByteLength(address.Area)) - group address by address.Area + orderby + AddressHelper.GetProtocolCoordinate(address.Address, address.SubAddress, + AddressTranslator.GetAreaByteLength(address.Area)) + group address by address.Area into grouped - select grouped; + select grouped; var ans = new List>(); foreach (var groupedAddress in groupedAddresses) { @@ -140,12 +140,12 @@ namespace Modbus.Net ans.Add(new CommunicationUnit { Area = area, - Address = (int) Math.Floor(initNum), + Address = (int)Math.Floor(initNum), GetCount = (int) Math.Ceiling( AddressHelper.MapProtocolGetCountToAbstractByteCount( - preNum - (int) Math.Floor(initNum), + preNum - (int)Math.Floor(initNum), AddressTranslator.GetAreaByteLength(address.Area), BigEndianValueHelper.Instance.ByteLength[preType.FullName])), DataType = typeof(byte), @@ -170,12 +170,12 @@ namespace Modbus.Net ans.Add(new CommunicationUnit { Area = area, - Address = (int) Math.Floor(initNum), + Address = (int)Math.Floor(initNum), GetCount = (int) Math.Ceiling( AddressHelper.MapProtocolGetCountToAbstractByteCount( - preNum - (int) Math.Floor(initNum), AddressTranslator.GetAreaByteLength(area), + preNum - (int)Math.Floor(initNum), AddressTranslator.GetAreaByteLength(area), BigEndianValueHelper.Instance.ByteLength[preType.FullName])), DataType = typeof(byte), OriginalAddresses = originalAddresses.ToList() @@ -255,7 +255,7 @@ namespace Modbus.Net SubAddress = address.SubAddress, DataType = address.DataType, GetCount = 1, - OriginalAddresses = new List> {address} + OriginalAddresses = new List> { address } }).ToList(); } } @@ -351,7 +351,7 @@ namespace Modbus.Net { if (orderedGap.GapNumber <= 0) continue; var nowAddress = orderedGap.EndUnit; - var index = continusAddresses.FindIndex(p=>p.Area == nowAddress.Area && p.Address == nowAddress.Address && p.SubAddress == nowAddress.SubAddress); + var index = continusAddresses.FindIndex(p => p.Area == nowAddress.Area && p.Address == nowAddress.Address && p.SubAddress == nowAddress.SubAddress); nowAddress = continusAddresses[index]; index--; var preAddress = continusAddresses[index]; @@ -432,7 +432,7 @@ namespace Modbus.Net var addressUnits = addresses as IList> ?? addresses.ToList(); var count = addressUnits.Sum(address => BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]); return - new AddressCombinerNumericJump((int) (count * Percentage / 100.0), MaxLength, AddressTranslator) + new AddressCombinerNumericJump((int)(count * Percentage / 100.0), MaxLength, AddressTranslator) .Combine( addressUnits); } diff --git a/Modbus.Net/Modbus.Net/Machine/BaseMachine.cs b/Modbus.Net/Modbus.Net/Machine/BaseMachine.cs index fff4717..31bbecf 100644 --- a/Modbus.Net/Modbus.Net/Machine/BaseMachine.cs +++ b/Modbus.Net/Modbus.Net/Machine/BaseMachine.cs @@ -1,8 +1,8 @@ -using System; +using Microsoft.Extensions.Logging; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Serilog; namespace Modbus.Net { @@ -80,6 +80,8 @@ namespace Modbus.Net where TKey : IEquatable where TUnitKey : IEquatable { + private static readonly ILogger> logger = LogProvider.CreateLogger>(); + private readonly int _maxErrorCount = 3; /// @@ -243,39 +245,39 @@ namespace Modbus.Net AddressTranslator.GetAreaByteLength(communicateAddress.Area)) + address.SubAddress * 0.125; //字节坐标的主地址位置 - var localMainPos = (int) localPos; + var localMainPos = (int)localPos; //字节坐标的子地址位置 - var localSubPos = (int) ((localPos - localMainPos) * 8); + var localSubPos = (int)((localPos - localMainPos) * 8); //根据类型选择返回结果的键是通讯标识还是地址 string key; switch (getDataType) { case MachineDataType.CommunicationTag: - { - key = address.CommunicationTag; - break; - } + { + key = address.CommunicationTag; + break; + } case MachineDataType.Address: - { - key = AddressFormater.FormatAddress(address.Area, address.Address, address.SubAddress); - break; - } + { + key = AddressFormater.FormatAddress(address.Area, address.Address, address.SubAddress); + break; + } case MachineDataType.Name: - { - key = address.Name; - break; - } + { + key = address.Name; + break; + } case MachineDataType.Id: - { - key = address.Id.ToString(); - break; - } + { + key = address.Id.ToString(); + break; + } default: - { - key = address.CommunicationTag; - break; - } + { + key = address.CommunicationTag; + break; + } } try @@ -302,7 +304,7 @@ namespace Modbus.Net catch (Exception e) { ErrorCount++; - Log.Error(e, $"BaseMachine -> GetDatas, Id:{Id} Connection:{ConnectionToken} key {key} existing. ErrorCount {ErrorCount}."); + logger.LogError(e, $"BaseMachine -> GetDatas, Id:{Id} Connection:{ConnectionToken} key {key} existing. ErrorCount {ErrorCount}."); if (ErrorCount >= _maxErrorCount) Disconnect(); @@ -321,8 +323,8 @@ namespace Modbus.Net catch (Exception e) { ErrorCount++; - Log.Error(e, $"BaseMachine -> GetDatas, Id:{Id} Connection:{ConnectionToken} error. ErrorCount {ErrorCount}."); - + logger.LogError(e, $"BaseMachine -> GetDatas, Id:{Id} Connection:{ConnectionToken} error. ErrorCount {ErrorCount}."); + if (ErrorCount >= _maxErrorCount) Disconnect(); return null; @@ -364,48 +366,48 @@ namespace Modbus.Net switch (setDataType) { case MachineDataType.Address: - { - address = - GetAddresses.SingleOrDefault( - p => - AddressFormater.FormatAddress(p.Area, p.Address, p.SubAddress) == value.Key || - p.DataType != typeof(bool) && - AddressFormater.FormatAddress(p.Area, p.Address) == value.Key); - break; - } + { + address = + GetAddresses.SingleOrDefault( + p => + AddressFormater.FormatAddress(p.Area, p.Address, p.SubAddress) == value.Key || + p.DataType != typeof(bool) && + AddressFormater.FormatAddress(p.Area, p.Address) == value.Key); + break; + } case MachineDataType.CommunicationTag: - { - address = - GetAddresses.SingleOrDefault(p => p.CommunicationTag == value.Key); - break; - } + { + address = + GetAddresses.SingleOrDefault(p => p.CommunicationTag == value.Key); + break; + } case MachineDataType.Name: - { - address = GetAddresses.SingleOrDefault(p => p.Name == value.Key); - break; - } + { + address = GetAddresses.SingleOrDefault(p => p.Name == value.Key); + break; + } case MachineDataType.Id: - { - address = GetAddresses.SingleOrDefault(p => p.Id.ToString() == value.Key); - break; - } + { + address = GetAddresses.SingleOrDefault(p => p.Id.ToString() == value.Key); + break; + } default: - { - address = - GetAddresses.SingleOrDefault(p => p.CommunicationTag == value.Key); - break; - } + { + address = + GetAddresses.SingleOrDefault(p => p.CommunicationTag == value.Key); + break; + } } //地址为空报错 if (address == null) { - Log.Error($"Machine {ConnectionToken} Address {value.Key} doesn't exist."); + logger.LogError($"Machine {ConnectionToken} Address {value.Key} doesn't exist."); continue; } //不能写报错 if (!address.CanWrite) { - Log.Error($"Machine {ConnectionToken} Address {value.Key} cannot write."); + logger.LogError($"Machine {ConnectionToken} Address {value.Key} cannot write."); continue; } addresses.Add(address); @@ -449,58 +451,58 @@ namespace Modbus.Net AddressTranslator.GetAreaByteLength(communicateAddress.Area), AddressTranslator.GetAreaByteLength(communicateAddress.Area), 0); //字节坐标主地址 - var mainByteCount = (int) byteCount; + var mainByteCount = (int)byteCount; //字节坐标自地址 - var localByteCount = (int) ((byteCount - (int) byteCount) * 8); + var localByteCount = (int)((byteCount - (int)byteCount) * 8); //协议坐标地址 var localPos = byteCount / AddressTranslator.GetAreaByteLength(communicateAddress.Area); //协议坐标子地址 var subPos = (int) - ((localPos - (int) localPos) / + ((localPos - (int)localPos) / (0.125 / AddressTranslator.GetAreaByteLength(communicateAddress.Area))); //协议主地址字符串 var address = AddressFormater.FormatAddress(communicateAddress.Area, - communicateAddress.Address + (int) localPos, subPos); + communicateAddress.Address + (int)localPos, subPos); //协议完整地址字符串 var address2 = subPos != 0 ? null : AddressFormater.FormatAddress(communicateAddress.Area, - communicateAddress.Address + (int) localPos); + communicateAddress.Address + (int)localPos); //获取写入类型 var dataType = addressUnit.DataType; KeyValuePair value; switch (setDataType) { case MachineDataType.Address: - { - //获取要写入的值 - value = - values.SingleOrDefault( - p => p.Key == address || address2 != null && p.Key == address2); - break; - } + { + //获取要写入的值 + value = + values.SingleOrDefault( + p => p.Key == address || address2 != null && p.Key == address2); + break; + } case MachineDataType.CommunicationTag: - { - value = values.SingleOrDefault(p => p.Key == addressUnit.CommunicationTag); - break; - } + { + value = values.SingleOrDefault(p => p.Key == addressUnit.CommunicationTag); + break; + } case MachineDataType.Name: - { - value = values.SingleOrDefault(p => p.Key == addressUnit.Name); - break; - } + { + value = values.SingleOrDefault(p => p.Key == addressUnit.Name); + break; + } case MachineDataType.Id: - { - value = values.SingleOrDefault(p => p.Key == addressUnit.Id.ToString()); - break; - } + { + value = values.SingleOrDefault(p => p.Key == addressUnit.Id.ToString()); + break; + } default: - { - value = values.SingleOrDefault(p => p.Key == addressUnit.CommunicationTag); - break; - } + { + value = values.SingleOrDefault(p => p.Key == addressUnit.CommunicationTag); + break; + } } //将要写入的值加入队列 var data = Convert.ChangeType(value.Value / addressUnit.Zoom, dataType); @@ -521,7 +523,7 @@ namespace Modbus.Net catch (Exception e) { ErrorCount++; - Log.Error(e, $"BaseMachine -> SetDatas, Id:{Id} Connection:{ConnectionToken} error. ErrorCount {ErrorCount}."); + logger.LogError(e, $"BaseMachine -> SetDatas, Id:{Id} Connection:{ConnectionToken} error. ErrorCount {ErrorCount}."); if (ErrorCount >= _maxErrorCount) Disconnect(); @@ -619,7 +621,7 @@ namespace Modbus.Net } catch (Exception e) { - Log.Error(e, $"BaseMachine -> GetAddressUnitById Id:{Id} ConnectionToken:{ConnectionToken} addressUnitId:{addressUnitId} Repeated"); + logger.LogError(e, $"BaseMachine -> GetAddressUnitById Id:{Id} ConnectionToken:{ConnectionToken} addressUnitId:{addressUnitId} Repeated"); return null; } } diff --git a/Modbus.Net/Modbus.Net/Machine/BaseMachineExtend.cs b/Modbus.Net/Modbus.Net/Machine/BaseMachineExtend.cs index 574bb5d..0aad808 100644 --- a/Modbus.Net/Modbus.Net/Machine/BaseMachineExtend.cs +++ b/Modbus.Net/Modbus.Net/Machine/BaseMachineExtend.cs @@ -18,8 +18,8 @@ namespace Modbus.Net { if (getValues == null) return null; return (from getValue in getValues - where getValue.Value.DeviceValue != null - select new KeyValuePair(getValue.Key, getValue.Value.DeviceValue.Value)).ToDictionary( + where getValue.Value.DeviceValue != null + select new KeyValuePair(getValue.Key, getValue.Value.DeviceValue.Value)).ToDictionary( p => p.Key, p => p.Value); } } diff --git a/Modbus.Net/Modbus.Net/Modbus.Net.csproj b/Modbus.Net/Modbus.Net/Modbus.Net.csproj index 6da3f18..bd18f9b 100644 --- a/Modbus.Net/Modbus.Net/Modbus.Net.csproj +++ b/Modbus.Net/Modbus.Net/Modbus.Net.csproj @@ -5,7 +5,7 @@ Modbus.Net Modbus.Net Modbus.Net - 1.4.0 + 1.4.0-beta03 Modbus.Net Chris L.(Luo Sheng) Hangzhou Delian Science Technology Co.,Ltd. @@ -28,10 +28,8 @@ - - - + diff --git a/Modbus.Net/Modbus.Net/Protocol/PipeUnit.cs b/Modbus.Net/Modbus.Net/Protocol/PipeUnit.cs index 10981f1..4d49d7b 100644 --- a/Modbus.Net/Modbus.Net/Protocol/PipeUnit.cs +++ b/Modbus.Net/Modbus.Net/Protocol/PipeUnit.cs @@ -96,7 +96,7 @@ namespace Modbus.Net /// 连接器 public PipeUnit(TProtocolLinker protocolLinker) : this(protocolLinker, null, null, true) { - + } /// diff --git a/Modbus.Net/Modbus.Net/Protocol/ProtocolLinker.cs b/Modbus.Net/Modbus.Net/Protocol/ProtocolLinker.cs index e9fd246..aa4f15e 100644 --- a/Modbus.Net/Modbus.Net/Protocol/ProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net/Protocol/ProtocolLinker.cs @@ -82,7 +82,7 @@ namespace Modbus.Net return true; } } - + /// /// 基本的协议连接器 /// diff --git a/Modbus.Net/Modbus.Net/Utility/BaseUtility.cs b/Modbus.Net/Modbus.Net/Utility/BaseUtility.cs index 30df334..f17b7bb 100644 --- a/Modbus.Net/Modbus.Net/Utility/BaseUtility.cs +++ b/Modbus.Net/Modbus.Net/Utility/BaseUtility.cs @@ -1,8 +1,8 @@ -using System; +using Microsoft.Extensions.Logging; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Serilog; /// /// 端格式 @@ -47,6 +47,8 @@ namespace Modbus.Net where TProtocolUnit : class, IProtocolFormatting where TParamOut : class where TPipeUnit : PipeUnit, TProtocolUnit> { + private static readonly ILogger> logger = LogProvider.CreateLogger>(); + /// /// 协议收发主体 /// @@ -122,13 +124,13 @@ namespace Modbus.Net var typeName = getTypeAndCount.Key.FullName; var bCount = BigEndianValueHelper.Instance.ByteLength[typeName]; var getReturnValue = await GetDatasAsync(startAddress, - (int) Math.Ceiling(bCount * getTypeAndCount.Value)); + (int)Math.Ceiling(bCount * getTypeAndCount.Value)); var getBytes = getReturnValue; return ValueHelper.GetInstance(Endian).ByteArrayToObjectArray(getBytes, getTypeAndCount); } catch (Exception e) { - Log.Error(e, $"ModbusUtility -> GetDatas: {ConnectionString} error"); + logger.LogError(e, $"ModbusUtility -> GetDatas: {ConnectionString} error"); return null; } } @@ -164,7 +166,7 @@ namespace Modbus.Net } catch (Exception e) { - Log.Error(e, $"ModbusUtility -> GetDatas Generic: {ConnectionString} error"); + logger.LogError(e, $"ModbusUtility -> GetDatas Generic: {ConnectionString} error"); return null; } } @@ -198,14 +200,14 @@ namespace Modbus.Net from getTypeAndCount in translateTypeAndCount let typeName = getTypeAndCount.Key.FullName let bCount = BigEndianValueHelper.Instance.ByteLength[typeName] - select (int) Math.Ceiling(bCount * getTypeAndCount.Value)).Sum(); + select (int)Math.Ceiling(bCount * getTypeAndCount.Value)).Sum(); var getReturnValue = await GetDatasAsync(startAddress, bAllCount); var getBytes = getReturnValue; return ValueHelper.GetInstance(Endian).ByteArrayToObjectArray(getBytes, translateTypeAndCount); } catch (Exception e) { - Log.Error(e, $"ModbusUtility -> GetDatas pair: {ConnectionString} error"); + logger.LogError(e, $"ModbusUtility -> GetDatas pair: {ConnectionString} error"); return null; } } diff --git a/Modbus.Net/Modbus.Net/Value/CRC16.cs b/Modbus.Net/Modbus.Net/Value/CRC16.cs index 16e19b2..8339bbb 100644 --- a/Modbus.Net/Modbus.Net/Value/CRC16.cs +++ b/Modbus.Net/Modbus.Net/Value/CRC16.cs @@ -64,11 +64,11 @@ namespace Modbus.Net CRC = CRC >> 1; } } - Rcvbuf[1] = (byte) ((CRC & 0xff00) >> 8); //高位置 - Rcvbuf[0] = (byte) (CRC & 0x00ff); //低位置 + Rcvbuf[1] = (byte)((CRC & 0xff00) >> 8); //高位置 + Rcvbuf[0] = (byte)(CRC & 0x00ff); //低位置 CRC = Rcvbuf[0] << 8; CRC += Rcvbuf[1]; - return (short) CRC; + return (short)CRC; } #endregion @@ -195,7 +195,7 @@ namespace Modbus.Net byte sum = 0; foreach (var b in code) sum += b; - sum = (byte) (~sum + 1); //取反+1 + sum = (byte)(~sum + 1); //取反+1 var lrc = sum.ToString("X2"); return lrc; } diff --git a/Modbus.Net/Modbus.Net/Value/ValueHelper.cs b/Modbus.Net/Modbus.Net/Value/ValueHelper.cs index 7d0a1cf..78ad456 100644 --- a/Modbus.Net/Modbus.Net/Value/ValueHelper.cs +++ b/Modbus.Net/Modbus.Net/Value/ValueHelper.cs @@ -1,9 +1,9 @@ -using System; +using Microsoft.Extensions.Logging; +using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; -using Serilog; namespace Modbus.Net { @@ -12,6 +12,8 @@ namespace Modbus.Net /// public class ValueHelper { + private static readonly ILogger logger = LogProvider.CreateLogger(); + /// /// 兼容数据类型对应的字节长度 /// @@ -53,7 +55,7 @@ namespace Modbus.Net /// byte数组 public byte[] GetBytes(byte value) { - return new[] {value}; + return new[] { value }; } /// @@ -147,54 +149,54 @@ namespace Modbus.Net switch (type.FullName) { case "System.Int16": - { - var bytes = _Instance.GetBytes((short) value); - return bytes; - } + { + var bytes = _Instance.GetBytes((short)value); + return bytes; + } case "System.Int32": - { - var bytes = _Instance.GetBytes((int) value); - return bytes; - } + { + var bytes = _Instance.GetBytes((int)value); + return bytes; + } case "System.Int64": - { - var bytes = _Instance.GetBytes((long) value); - return bytes; - } + { + var bytes = _Instance.GetBytes((long)value); + return bytes; + } case "System.UInt16": - { - var bytes = _Instance.GetBytes((ushort) value); - return bytes; - } + { + var bytes = _Instance.GetBytes((ushort)value); + return bytes; + } case "System.UInt32": - { - var bytes = _Instance.GetBytes((uint) value); - return bytes; - } + { + var bytes = _Instance.GetBytes((uint)value); + return bytes; + } case "System.UInt64": - { - var bytes = _Instance.GetBytes((ulong) value); - return bytes; - } + { + var bytes = _Instance.GetBytes((ulong)value); + return bytes; + } case "System.Single": - { - var bytes = _Instance.GetBytes((float) value); - return bytes; - } + { + var bytes = _Instance.GetBytes((float)value); + return bytes; + } case "System.Double": - { - var bytes = _Instance.GetBytes((double) value); - return bytes; - } + { + var bytes = _Instance.GetBytes((double)value); + return bytes; + } case "System.Byte": - { - var bytes = _Instance.GetBytes((byte) value); - return bytes; - } + { + var bytes = _Instance.GetBytes((byte)value); + return bytes; + } default: - { - throw new NotImplementedException("没有实现除整数以外的其它转换方式"); - } + { + throw new NotImplementedException("没有实现除整数以外的其它转换方式"); + } } } @@ -211,59 +213,59 @@ namespace Modbus.Net switch (t.FullName) { case "System.Int16": - { - var value = _Instance.GetShort(data, ref pos); - return value; - } + { + var value = _Instance.GetShort(data, ref pos); + return value; + } case "System.Int32": - { - var value = _Instance.GetInt(data, ref pos); - return value; - } + { + var value = _Instance.GetInt(data, ref pos); + return value; + } case "System.Int64": - { - var value = _Instance.GetLong(data, ref pos); - return value; - } + { + var value = _Instance.GetLong(data, ref pos); + return value; + } case "System.UInt16": - { - var value = _Instance.GetUShort(data, ref pos); - return value; - } + { + var value = _Instance.GetUShort(data, ref pos); + return value; + } case "System.UInt32": - { - var value = _Instance.GetUInt(data, ref pos); - return value; - } + { + var value = _Instance.GetUInt(data, ref pos); + return value; + } case "System.UInt64": - { - var value = _Instance.GetULong(data, ref pos); - return value; - } + { + var value = _Instance.GetULong(data, ref pos); + return value; + } case "System.Single": - { - var value = _Instance.GetFloat(data, ref pos); - return value; - } + { + var value = _Instance.GetFloat(data, ref pos); + return value; + } case "System.Double": - { - var value = _Instance.GetDouble(data, ref pos); - return value; - } + { + var value = _Instance.GetDouble(data, ref pos); + return value; + } case "System.Byte": - { - var value = _Instance.GetByte(data, ref pos); - return value; - } + { + var value = _Instance.GetByte(data, ref pos); + return value; + } case "System.Boolean": - { - var value = _Instance.GetBit(data, ref pos, ref subPos); - return value; - } + { + var value = _Instance.GetBit(data, ref pos, ref subPos); + return value; + } default: - { - throw new NotImplementedException("没有实现除整数以外的其它转换方式"); - } + { + throw new NotImplementedException("没有实现除整数以外的其它转换方式"); + } } } @@ -468,7 +470,7 @@ namespace Modbus.Net for (var i = 0; i < 8; i++) { result <<= 1; - result |= (byte) (originalByte & 1); + result |= (byte)(originalByte & 1); originalByte >>= 1; } return result; @@ -492,7 +494,7 @@ namespace Modbus.Net b = true; //自动将目标数组中内含的子数组展开,是所有包含在子数组拼接为一个数组 var contentArray = - ArrayList.Adapter((Array) content).ToArray(typeof(object)).OfType(); + ArrayList.Adapter((Array)content).ToArray(typeof(object)).OfType(); newContentsList.AddRange(contentArray); } else @@ -521,9 +523,9 @@ namespace Modbus.Net } lastIsBool = true; if (!LittleEndianBit) - boolToByteTemp = (byte) (boolToByteTemp * 2 + ((bool) content ? 1 : 0)); + boolToByteTemp = (byte)(boolToByteTemp * 2 + ((bool)content ? 1 : 0)); else - boolToByteTemp += (byte) ((bool) content ? Math.Pow(2, boolToByteCount) : 0); + boolToByteTemp += (byte)((bool)content ? Math.Pow(2, boolToByteCount) : 0); boolToByteCount++; } else @@ -538,54 +540,54 @@ namespace Modbus.Net switch (t) { case "System.Int16": - { - translateTarget.AddRange(_Instance.GetBytes((short) content)); - break; - } + { + translateTarget.AddRange(_Instance.GetBytes((short)content)); + break; + } case "System.Int32": - { - translateTarget.AddRange(_Instance.GetBytes((int) content)); - break; - } + { + translateTarget.AddRange(_Instance.GetBytes((int)content)); + break; + } case "System.Int64": - { - translateTarget.AddRange(_Instance.GetBytes((long) content)); - break; - } + { + translateTarget.AddRange(_Instance.GetBytes((long)content)); + break; + } case "System.UInt16": - { - translateTarget.AddRange(_Instance.GetBytes((ushort) content)); - break; - } + { + translateTarget.AddRange(_Instance.GetBytes((ushort)content)); + break; + } case "System.UInt32": - { - translateTarget.AddRange(_Instance.GetBytes((uint) content)); - break; - } + { + translateTarget.AddRange(_Instance.GetBytes((uint)content)); + break; + } case "System.UInt64": - { - translateTarget.AddRange(_Instance.GetBytes((ulong) content)); - break; - } + { + translateTarget.AddRange(_Instance.GetBytes((ulong)content)); + break; + } case "System.Single": - { - translateTarget.AddRange(_Instance.GetBytes((float) content)); - break; - } + { + translateTarget.AddRange(_Instance.GetBytes((float)content)); + break; + } case "System.Double": - { - translateTarget.AddRange(_Instance.GetBytes((double) content)); - break; - } + { + translateTarget.AddRange(_Instance.GetBytes((double)content)); + break; + } case "System.Byte": - { - translateTarget.AddRange(_Instance.GetBytes((byte) content)); - break; - } + { + translateTarget.AddRange(_Instance.GetBytes((byte)content)); + break; + } default: - { - throw new NotImplementedException("没有实现除整数以外的其它转换方式"); - } + { + throw new NotImplementedException("没有实现除整数以外的其它转换方式"); + } } } } @@ -604,7 +606,7 @@ namespace Modbus.Net /// object数组 public virtual object[] ByteArrayToObjectArray(byte[] contents, KeyValuePair translateTypeAndCount) { - return ByteArrayToObjectArray(contents, new List> {translateTypeAndCount}); + return ByteArrayToObjectArray(contents, new List> { translateTypeAndCount }); } /// @@ -644,77 +646,77 @@ namespace Modbus.Net switch (translateUnit.Key.ToString()) { case "System.Int16": - { - var value = _Instance.GetShort(contents, ref count); - translation.Add(value); - break; - } + { + var value = _Instance.GetShort(contents, ref count); + translation.Add(value); + break; + } case "System.Int32": - { - var value = _Instance.GetInt(contents, ref count); - translation.Add(value); - break; - } + { + var value = _Instance.GetInt(contents, ref count); + translation.Add(value); + break; + } case "System.Int64": - { - var value = _Instance.GetLong(contents, ref count); - translation.Add(value); - break; - } + { + var value = _Instance.GetLong(contents, ref count); + translation.Add(value); + break; + } case "System.UInt16": - { - var value = _Instance.GetUShort(contents, ref count); - translation.Add(value); - break; - } + { + var value = _Instance.GetUShort(contents, ref count); + translation.Add(value); + break; + } case "System.UInt32": - { - var value = _Instance.GetUInt(contents, ref count); - translation.Add(value); - break; - } + { + var value = _Instance.GetUInt(contents, ref count); + translation.Add(value); + break; + } case "System.UInt64": - { - var value = _Instance.GetULong(contents, ref count); - translation.Add(value); - break; - } + { + var value = _Instance.GetULong(contents, ref count); + translation.Add(value); + break; + } case "System.Single": - { - var value = _Instance.GetFloat(contents, ref count); - translation.Add(value); - break; - } + { + var value = _Instance.GetFloat(contents, ref count); + translation.Add(value); + break; + } case "System.Double": - { - var value = _Instance.GetDouble(contents, ref count); - translation.Add(value); - break; - } + { + var value = _Instance.GetDouble(contents, ref count); + translation.Add(value); + break; + } case "System.Byte": - { - var value = _Instance.GetByte(contents, ref count); - translation.Add(value); - break; - } + { + var value = _Instance.GetByte(contents, ref count); + translation.Add(value); + break; + } case "System.Boolean": - { - var value = _Instance.GetBits(contents, ref count); - var k = translateUnit.Value - i < 8 ? translateUnit.Value - i : 8; - for (var j = 0; j < k; j++) - translation.Add(value[j]); - i += 7; - break; - } + { + var value = _Instance.GetBits(contents, ref count); + var k = translateUnit.Value - i < 8 ? translateUnit.Value - i : 8; + for (var j = 0; j < k; j++) + translation.Add(value[j]); + i += 7; + break; + } default: - { - throw new NotImplementedException("Number casting not implemented"); - } + { + throw new NotImplementedException("Number casting not implemented"); + } } } catch (Exception e) { - Log.Error(e, "ValueHelper -> ByteArrayToObjectArray error"); + logger.LogError(e, "ValueHelper -> ByteArrayToObjectArray error"); count = contents.Length; } } @@ -749,59 +751,59 @@ namespace Modbus.Net switch (type.FullName) { case "System.Int16": - { - var success = _Instance.SetValue(contents, setPos, (short) setValue); - return success; - } + { + var success = _Instance.SetValue(contents, setPos, (short)setValue); + return success; + } case "System.Int32": - { - var success = _Instance.SetValue(contents, setPos, (int) setValue); - return success; - } + { + var success = _Instance.SetValue(contents, setPos, (int)setValue); + return success; + } case "System.Int64": - { - var success = _Instance.SetValue(contents, setPos, (long) setValue); - return success; - } + { + var success = _Instance.SetValue(contents, setPos, (long)setValue); + return success; + } case "System.UInt16": - { - var success = _Instance.SetValue(contents, setPos, (ushort) setValue); - return success; - } + { + var success = _Instance.SetValue(contents, setPos, (ushort)setValue); + return success; + } case "System.UInt32": - { - var success = _Instance.SetValue(contents, setPos, (uint) setValue); - return success; - } + { + var success = _Instance.SetValue(contents, setPos, (uint)setValue); + return success; + } case "System.UInt64": - { - var success = _Instance.SetValue(contents, setPos, (ulong) setValue); - return success; - } + { + var success = _Instance.SetValue(contents, setPos, (ulong)setValue); + return success; + } case "System.Single": - { - var success = _Instance.SetValue(contents, setPos, (float) setValue); - return success; - } + { + var success = _Instance.SetValue(contents, setPos, (float)setValue); + return success; + } case "System.Double": - { - var success = _Instance.SetValue(contents, setPos, (double) setValue); - return success; - } + { + var success = _Instance.SetValue(contents, setPos, (double)setValue); + return success; + } case "System.Byte": - { - var success = _Instance.SetValue(contents, setPos, (byte) setValue); - return success; - } + { + var success = _Instance.SetValue(contents, setPos, (byte)setValue); + return success; + } case "System.Boolean": - { - var success = _Instance.SetBit(contents, setPos, subPos, (bool) setValue); - return success; - } + { + var success = _Instance.SetBit(contents, setPos, subPos, (bool)setValue); + return success; + } default: - { - throw new NotImplementedException("Number casting not implemented"); - } + { + throw new NotImplementedException("Number casting not implemented"); + } } } @@ -822,7 +824,7 @@ namespace Modbus.Net } catch (Exception e) { - Log.Error(e, "ValueHelper -> SetValue set value failed"); + logger.LogError(e, "ValueHelper -> SetValue set value failed"); return false; } } @@ -844,14 +846,14 @@ namespace Modbus.Net creation *= 2; if (i == subPos) creation++; } - return (byte) (number | creation); + return (byte)(number | creation); } for (var i = 7; i >= 0; i--) { creation *= 2; if (i != subPos) creation++; } - return (byte) (number & creation); + return (byte)(number & creation); } /// @@ -871,7 +873,7 @@ namespace Modbus.Net } catch (Exception e) { - Log.Error(e, "ValueHelper -> SetBit set bit failed"); + logger.LogError(e, "ValueHelper -> SetBit set bit failed"); return false; } } @@ -900,21 +902,21 @@ namespace Modbus.Net switch (endian) { case Endian.LittleEndianLsb: - { - return Instance; - } + { + return Instance; + } case Endian.BigEndianLsb: - { - return BigEndianValueHelper.Instance; - } + { + return BigEndianValueHelper.Instance; + } case Endian.BigEndianMsb: - { - return BigEndianMsbValueHelper.Instance; - } + { + return BigEndianMsbValueHelper.Instance; + } default: - { - return Instance; - } + { + return Instance; + } } } diff --git a/Samples/AnyType/Controllers/HomeController.cs b/Samples/AnyType/Controllers/HomeController.cs index 0b8c124..0902d54 100644 --- a/Samples/AnyType/Controllers/HomeController.cs +++ b/Samples/AnyType/Controllers/HomeController.cs @@ -44,15 +44,15 @@ namespace AnyType.Controllers }; values = from unitValue in addressUnits - select - new TaskViewModel() - { - Id = unitValue.Id, - Name = unitValue.Name, - Address = unitValue.Address + "." + unitValue.SubAddress, - Value = 0, - Type = unitValue.DataType.Name - }; + select + new TaskViewModel() + { + Id = unitValue.Id, + Name = unitValue.Name, + Address = unitValue.Address + "." + unitValue.SubAddress, + Value = 0, + Type = unitValue.DataType.Name + }; var machine = new ModbusMachine("1", ModbusType.Tcp, "192.168.0.172:502", addressUnits, true, 2, 0); //启动任务 await MachineJobSchedulerCreator.CreateScheduler("Trigger1", -1, 1).Result.From(machine.Id, machine, MachineDataType.CommunicationTag).Result.Query("Query1", diff --git a/Samples/AnyType/Models/TaskViewModel.cs b/Samples/AnyType/Models/TaskViewModel.cs index 02932d6..1248c8b 100644 --- a/Samples/AnyType/Models/TaskViewModel.cs +++ b/Samples/AnyType/Models/TaskViewModel.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; - -namespace AnyType.Models +namespace AnyType.Models { public class TaskViewModel { diff --git a/Samples/CrossLamp/Models/Lamp.cs b/Samples/CrossLamp/Models/Lamp.cs index abd1342..0e3ef51 100644 --- a/Samples/CrossLamp/Models/Lamp.cs +++ b/Samples/CrossLamp/Models/Lamp.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; - -public enum LightLamp{Red,Yellow,Green} +public enum LightLamp { Red, Yellow, Green } namespace CrossLampControl.WebApi.Models { public class Lamp diff --git a/Samples/MachineJob/ConsoleLogProvider.cs b/Samples/MachineJob/ConsoleLogProvider.cs new file mode 100644 index 0000000..c65d043 --- /dev/null +++ b/Samples/MachineJob/ConsoleLogProvider.cs @@ -0,0 +1,30 @@ +using Quartz.Logging; + +namespace MachineJob +{ + // simple log provider to get something to the console + public class ConsoleLogProvider : ILogProvider + { + public Logger GetLogger(string name) + { + return (level, func, exception, parameters) => + { + if (level >= Quartz.Logging.LogLevel.Info && func != null) + { + Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] [" + level + "] " + func(), parameters); + } + return true; + }; + } + + public IDisposable OpenNestedContext(string message) + { + throw new NotImplementedException(); + } + + public IDisposable OpenMappedContext(string key, object value, bool destructure = false) + { + throw new NotImplementedException(); + } + } +} diff --git a/Samples/MachineJob/DatabaseWrite.cs b/Samples/MachineJob/DatabaseWrite.cs index 32e8fb1..28c5025 100644 --- a/Samples/MachineJob/DatabaseWrite.cs +++ b/Samples/MachineJob/DatabaseWrite.cs @@ -1,5 +1,4 @@ using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration; using System.ComponentModel.DataAnnotations; @@ -24,7 +23,7 @@ namespace MachineJob public double? Value1 { get; set; } public double? Value2 { get; set; } public double? Value3 { get; set; } - public double? Value4 { get; set; } + public double? Value4 { get; set; } public double? Value5 { get; set; } public double? Value6 { get; set; } public double? Value7 { get; set; } diff --git a/Samples/MachineJob/MachineJob.csproj b/Samples/MachineJob/MachineJob.csproj index f7f0214..4dd76b6 100644 --- a/Samples/MachineJob/MachineJob.csproj +++ b/Samples/MachineJob/MachineJob.csproj @@ -15,6 +15,9 @@ + + + diff --git a/Samples/MachineJob/Migrations/20230212103438_InitialCreate.cs b/Samples/MachineJob/Migrations/20230212103438_InitialCreate.cs index ffdfe29..6c6a8f8 100644 --- a/Samples/MachineJob/Migrations/20230212103438_InitialCreate.cs +++ b/Samples/MachineJob/Migrations/20230212103438_InitialCreate.cs @@ -1,5 +1,4 @@ -using System; -using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable diff --git a/Samples/MachineJob/Program.cs b/Samples/MachineJob/Program.cs index ce2bb8e..51e8a7a 100644 --- a/Samples/MachineJob/Program.cs +++ b/Samples/MachineJob/Program.cs @@ -1,10 +1,31 @@ +using MachineJob; using MachineJob.Service; +using Serilog; + +var configuration = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json") + .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", true) + .Build(); + +Log.Logger = new LoggerConfiguration() + .ReadFrom.Configuration(configuration) + .WriteTo.Console() + .CreateLogger(); + +var loggerFactory = new LoggerFactory().AddSerilog(Log.Logger); + +Quartz.Logging.LogProvider.SetCurrentLogProvider(new ConsoleLogProvider()); +Modbus.Net.LogProvider.SetLogProvider(loggerFactory); IHost host = Host.CreateDefaultBuilder(args) .ConfigureServices(services => { services.AddHostedService(); + + services.AddLogging(loggingBuilder => loggingBuilder.AddSerilog(Log.Logger, true)); }) .Build(); await host.RunAsync(); + diff --git a/Samples/MachineJob/Worker.cs b/Samples/MachineJob/Worker.cs index 88bd0d9..053aab0 100644 --- a/Samples/MachineJob/Worker.cs +++ b/Samples/MachineJob/Worker.cs @@ -15,7 +15,7 @@ namespace MachineJob.Service protected override async Task ExecuteAsync(CancellationToken stoppingToken) { - + List _addresses = new List { new AddressUnit() { Area = "4X", Address = 1, DataType = typeof(short), Id = "1", Name = "Test1" }, @@ -29,8 +29,7 @@ namespace MachineJob.Service new AddressUnit() { Area = "4X", Address = 9, DataType = typeof(short), Id = "9", Name = "Test9" }, new AddressUnit() { Area = "4X", Address = 10, DataType = typeof(short), Id = "10", Name = "Test10" } }; - - /* + List _addresses2 = new List { new AddressUnit() { Area = "DB1", Address = 0, DataType = typeof(short), Id = "1", Name = "Test1" }, @@ -44,28 +43,30 @@ namespace MachineJob.Service new AddressUnit() { Area = "DB1", Address = 16, DataType = typeof(short), Id = "9", Name = "Test9" }, new AddressUnit() { Area = "DB1", Address = 18, DataType = typeof(short), Id = "10", Name = "Test10" } }; - */ - IMachine machine = new ModbusMachine("ModbusMachine1", ModbusType.Tcp, "192.168.0.161", _addresses, true, 1, 2, Endian.BigEndianLsb); - //IMachine machine2 = new SiemensMachine("SiemensMachine1", SiemensType.Tcp, "192.168.0.161", SiemensMachineModel.S7_1200, _addresses2, true, 1, 2); - await MachineJobSchedulerCreator.CreateScheduler("Trigger1", -1, 5).Result.From(machine.Id, machine, MachineDataType.Name).Result.Query(machine.Id + ".ConsoleQuery", QueryConsole).Result.To(machine.Id + ".To", machine).Result.Deal(machine.Id+".Deal", OnSuccess, OnFailure).Result.Run(); - //await MachineJobSchedulerCreator.CreateScheduler("Trigger2", -1, 5).Result.From(machine2.Id, machine2, MachineDataType.Name).Result.Query(machine2.Id + ".ConsoleQuery", QueryConsole).Result.To(machine2.Id + ".To", machine2).Result.Deal(machine2.Id + ".Deal", OnSuccess, OnFailure).Result.Run(); + IMachine machine = new ModbusMachine("ModbusMachine1", ModbusType.Tcp, "192.168.0.161", _addresses, true, 1, 2, Endian.BigEndianLsb); + IMachine machine2 = new SiemensMachine("SiemensMachine1", SiemensType.Tcp, "192.168.0.161", SiemensMachineModel.S7_1200, _addresses2, true, 1, 2); + + await MachineJobSchedulerCreator.CreateScheduler("Trigger1", -1, 10).Result.From(machine.Id, machine, MachineDataType.Name).Result.Query(machine.Id + ".ConsoleQuery", QueryConsole).Result.To(machine.Id + ".To", machine).Result.Deal(machine.Id + ".Deal", OnSuccess, OnFailure).Result.Run(); + Thread.Sleep(5000); + await MachineJobSchedulerCreator.CreateScheduler("Trigger2", -1, 10).Result.From(machine2.Id, machine2, MachineDataType.Name).Result.Query(machine2.Id + ".ConsoleQuery", QueryConsole).Result.To(machine2.Id + ".To", machine2).Result.Deal(machine2.Id + ".Deal", OnSuccess, OnFailure).Result.Run(); } public override async Task StopAsync(CancellationToken cancellationToken) { await MachineJobSchedulerCreator.CancelJob("Trigger1"); + await MachineJobSchedulerCreator.CancelJob("Trigger2"); } public Task OnSuccess(string machineId) { - Console.WriteLine("Machine {0} set success", machineId); + _logger.LogInformation("Machine {0} set success", machineId); return Task.CompletedTask; } public Task OnFailure(string machineId) { - Console.WriteLine("Machine {0} set failure", machineId); + _logger.LogError("Machine {0} set failure", machineId); return Task.CompletedTask; } @@ -74,9 +75,9 @@ namespace MachineJob.Service var values = dataReturnDef.ReturnValues; foreach (var value in values) { - Console.WriteLine(dataReturnDef.MachineId + " " + value.Key + " " + value.Value.DeviceValue); + _logger.LogInformation(dataReturnDef.MachineId + " " + value.Key + " " + value.Value.DeviceValue); } - + try { using (var context = new DatabaseWriteContext()) @@ -102,7 +103,7 @@ namespace MachineJob.Service { //ignore } - + Random r = new Random(); foreach (var value in values) { diff --git a/Samples/MachineJob/appsettings.json b/Samples/MachineJob/appsettings.json index 3cacfdd..0f91a9c 100644 --- a/Samples/MachineJob/appsettings.json +++ b/Samples/MachineJob/appsettings.json @@ -1,8 +1,11 @@ { - "Logging": { - "LogLevel": { + "Serilog": { + "MinimumLevel": { "Default": "Information", - "Microsoft.Hosting.Lifetime": "Information" + "Override": { + "Microsoft": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } } }, "ConnectionStrings": { diff --git a/Samples/TripleAdd/Models/TripleAddViewModel.cs b/Samples/TripleAdd/Models/TripleAddViewModel.cs index 802828c..26c41e0 100644 --- a/Samples/TripleAdd/Models/TripleAddViewModel.cs +++ b/Samples/TripleAdd/Models/TripleAddViewModel.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; - -namespace TripleAdd.Models +namespace TripleAdd.Models { public class TripleAddViewModel { diff --git a/Tests/Modbus.Net.PersistedTests/Modbus.Net.PersistedTests.csproj b/Tests/Modbus.Net.PersistedTests/Modbus.Net.PersistedTests.csproj index f430833..dad71a6 100644 --- a/Tests/Modbus.Net.PersistedTests/Modbus.Net.PersistedTests.csproj +++ b/Tests/Modbus.Net.PersistedTests/Modbus.Net.PersistedTests.csproj @@ -6,7 +6,9 @@ - + + + diff --git a/Tests/Modbus.Net.PersistedTests/Program.cs b/Tests/Modbus.Net.PersistedTests/Program.cs index c3696df..2fb0d6a 100644 --- a/Tests/Modbus.Net.PersistedTests/Program.cs +++ b/Tests/Modbus.Net.PersistedTests/Program.cs @@ -1,11 +1,18 @@ -using System; -using System.Collections.Generic; +using Microsoft.Extensions.Logging; using Modbus.Net; using Modbus.Net.Modbus; using Serilog; +using System; +using System.Collections.Generic; +Log.Logger = new LoggerConfiguration() + .MinimumLevel.Information() + .WriteTo.Console() +.CreateLogger(); -Log.Logger = new LoggerConfiguration().MinimumLevel.Verbose().WriteTo.Console().CreateLogger(); +var loggerFactory = new LoggerFactory() + .AddSerilog(Log.Logger); +LogProvider.SetLogProvider(loggerFactory); ModbusMachine machine = new ModbusMachine(1, ModbusType.Rtu, "COM1", new List() @@ -92,34 +99,34 @@ ModbusMachine machine3 = new ModbusMachine(3, ModbusTy }, }, true, 4, 1); Random r = new Random(); -await MachineJobSchedulerCreator.CreateScheduler("Trigger1", -1, 10).Result.ApplyTo(machine.Id+".Apply", new Dictionary() {{ - "4X 1.0", r.Next() % 65536 +await MachineJobSchedulerCreator.CreateScheduler("Trigger1", -1, 10).Result.ApplyTo(machine.Id + ".Apply", new Dictionary() {{ + "4X 1.0", r.Next() % 65536 }, { - "4X 2.0", r.Next() % 65536 + "4X 2.0", r.Next() % 65536 }, { - "4X 3.0", r.Next() % 65536 - } + "4X 3.0", r.Next() % 65536 + } }, MachineDataType.Address).Result.To(machine.Id + ".To", machine).Result.Deal().Result.Run(); await MachineJobSchedulerCreator.CreateScheduler("Trigger2", -1, 10).Result.ApplyTo(machine2.Id + ".Apply", new Dictionary() {{ - "4X 1.0", r.Next() % 65536 + "4X 1.0", r.Next() % 65536 }, { - "4X 2.0", r.Next() % 65536 + "4X 2.0", r.Next() % 65536 }, { - "4X 3.0", r.Next() % 65536 + "4X 3.0", r.Next() % 65536 } }, MachineDataType.Address).Result.To(machine2.Id + ".To", machine2).Result.Deal().Result.Run(); await MachineJobSchedulerCreator.CreateScheduler("Trigger3", -1, 10).Result.ApplyTo(machine3.Id + ".Apply", new Dictionary() {{ - "4X 1.0", r.Next() % 65536 + "4X 1.0", r.Next() % 65536 }, { - "4X 2.0", r.Next() % 65536 + "4X 2.0", r.Next() % 65536 }, { - "4X 3.0", r.Next() % 65536 + "4X 3.0", r.Next() % 65536 } }, MachineDataType.Address).Result.To(machine3.Id + ".To", machine3).Result.Deal().Result.Run(); Console.ReadLine(); \ No newline at end of file diff --git a/Tests/Modbus.Net.Tests/BaseTest.cs b/Tests/Modbus.Net.Tests/BaseTest.cs index bc9629e..1853732 100644 --- a/Tests/Modbus.Net.Tests/BaseTest.cs +++ b/Tests/Modbus.Net.Tests/BaseTest.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Modbus.Net.Modbus; using Modbus.Net.Siemens; diff --git a/Tests/Modbus.Net.Tests/EndianTest.cs b/Tests/Modbus.Net.Tests/EndianTest.cs index 99772b6..09d144f 100644 --- a/Tests/Modbus.Net.Tests/EndianTest.cs +++ b/Tests/Modbus.Net.Tests/EndianTest.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Modbus.Net.Modbus; namespace Modbus.Net.Tests diff --git a/Tests/Modbus.Net.Tests/MachineMethodTest.cs b/Tests/Modbus.Net.Tests/MachineMethodTest.cs index 207d3bc..0f1b825 100644 --- a/Tests/Modbus.Net.Tests/MachineMethodTest.cs +++ b/Tests/Modbus.Net.Tests/MachineMethodTest.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Modbus.Net.Modbus; +using System.Reflection; namespace Modbus.Net.Tests { diff --git a/Tests/Modbus.Net.Tests/ModbusMultiStationTest.cs b/Tests/Modbus.Net.Tests/ModbusMultiStationTest.cs index cb633f8..feb6970 100644 --- a/Tests/Modbus.Net.Tests/ModbusMultiStationTest.cs +++ b/Tests/Modbus.Net.Tests/ModbusMultiStationTest.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Modbus.Net.Modbus; namespace Modbus.Net.Tests diff --git a/Tests/Modbus.Net.Tests/ModbusTest.cs b/Tests/Modbus.Net.Tests/ModbusTest.cs index 9af3cb0..dadfb31 100644 --- a/Tests/Modbus.Net.Tests/ModbusTest.cs +++ b/Tests/Modbus.Net.Tests/ModbusTest.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Modbus.Net.Modbus; namespace Modbus.Net.Tests diff --git a/Tests/Modbus.Net.Tests/SiemensTest.cs b/Tests/Modbus.Net.Tests/SiemensTest.cs index bc35f66..2b9e878 100644 --- a/Tests/Modbus.Net.Tests/SiemensTest.cs +++ b/Tests/Modbus.Net.Tests/SiemensTest.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Modbus.Net.Modbus; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Modbus.Net.Siemens; namespace Modbus.Net.Tests