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
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