Change log system

This commit is contained in:
luosheng
2023-03-01 09:36:07 +08:00
parent 46222348be
commit a8c9fefbce
80 changed files with 2227 additions and 1921 deletions

View File

@@ -1,100 +1,100 @@
using System.Linq; using Opc.Ua;
using Opc.Ua;
using System;
using Opc.Ua.Client; using Opc.Ua.Client;
using System;
using System.Linq;
namespace Hylasoft.Opc.Ua namespace Hylasoft.Opc.Ua
{ {
/// <summary> /// <summary>
/// List of static utility methods /// List of static utility methods
/// </summary> /// </summary>
internal static class ClientUtils 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)
{ {
var configuration = EndpointConfiguration.Create(); // TODO I didn't write these methods. I should rewrite it once I understand whtat it does, beacuse it looks crazy
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) public static EndpointDescription SelectEndpoint(Uri discoveryUrl, bool useSecurity)
{
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) var configuration = EndpointConfiguration.Create();
descriptionCollection.Add(results[0].References[index]); configuration.OperationTimeout = 5000;
if (results[0].References.Count == 0 || results[0].ContinuationPoint == null) EndpointDescription endpointDescription1 = null;
return descriptionCollection; using (var discoveryClient = DiscoveryClient.Create(discoveryUrl, configuration))
var continuationPoints = new ByteStringCollection(); {
continuationPoints.Add(results[0].ContinuationPoint); var endpoints = discoveryClient.GetEndpoints(null);
session.BrowseNext(null, false, continuationPoints, out results, out diagnosticInfos); foreach (var endpointDescription2 in endpoints.Where(endpointDescription2 => endpointDescription2.EndpointUrl.StartsWith(discoveryUrl.Scheme)))
ClientBase.ValidateResponse(results, continuationPoints); {
ClientBase.ValidateDiagnosticInfos(diagnosticInfos, continuationPoints); 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;
}
} }
}
} }

View File

@@ -2,33 +2,33 @@
namespace Hylasoft.Opc.Common namespace Hylasoft.Opc.Common
{ {
/// <summary>
/// Useful extension methods for OPC Clients
/// </summary>
public static class ClientExtensions
{
/// <summary> /// <summary>
/// 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
/// </summary> /// </summary>
/// <param name="client">the opc client to use for the read</param> public static class ClientExtensions
/// <param name="tag">The fully qualified identifier of the tag</param>
/// <param name="defaultValue">the default value to read if the read fails</param>
/// <returns></returns>
public static ReadEvent<T> ReadOrdefault<T>(this IClient<Node> client, string tag, T defaultValue = default(T))
{ {
try /// <summary>
{ /// Reads a tag from the OPC. If for whatever reason the read fails (Tag doesn't exist, server not available) returns a default value
return client.Read<T>(tag); /// </summary>
} /// <param name="client">the opc client to use for the read</param>
catch (OpcException) /// <param name="tag">The fully qualified identifier of the tag</param>
{ /// <param name="defaultValue">the default value to read if the read fails</param>
var readEvent = new ReadEvent<T>(); /// <returns></returns>
readEvent.Quality = Quality.Good; public static ReadEvent<T> ReadOrdefault<T>(this IClient<Node> client, string tag, T defaultValue = default(T))
readEvent.Value = defaultValue; {
readEvent.SourceTimestamp = DateTime.Now; try
readEvent.ServerTimestamp = DateTime.Now; {
return readEvent; return client.Read<T>(tag);
} }
catch (OpcException)
{
var readEvent = new ReadEvent<T>();
readEvent.Quality = Quality.Good;
readEvent.Value = defaultValue;
readEvent.SourceTimestamp = DateTime.Now;
readEvent.ServerTimestamp = DateTime.Now;
return readEvent;
}
}
} }
}
} }

View File

@@ -4,100 +4,100 @@ using System.Threading.Tasks;
namespace Hylasoft.Opc.Common namespace Hylasoft.Opc.Common
{ {
/// <summary> /// <summary>
/// Client interface to perform basic Opc tasks, like discovery, monitoring, reading/writing tags, /// Client interface to perform basic Opc tasks, like discovery, monitoring, reading/writing tags,
/// </summary> /// </summary>
public interface IClient<out TNode> : IDisposable public interface IClient<out TNode> : IDisposable
where TNode : Node where TNode : Node
{ {
/// <summary> /// <summary>
/// Connect the client to the OPC Server /// Connect the client to the OPC Server
/// </summary> /// </summary>
Task Connect(); Task Connect();
/// <summary> /// <summary>
/// Gets the current status of the OPC Client /// Gets the current status of the OPC Client
/// </summary> /// </summary>
OpcStatus Status { get; } OpcStatus Status { get; }
/// <summary> /// <summary>
/// Gets the datatype of an OPC tag /// Gets the datatype of an OPC tag
/// </summary> /// </summary>
/// <param name="tag">Tag to get datatype of</param> /// <param name="tag">Tag to get datatype of</param>
/// <returns>System Type</returns> /// <returns>System Type</returns>
System.Type GetDataType(string tag); System.Type GetDataType(string tag);
/// <summary> /// <summary>
/// Read a tag /// Read a tag
/// </summary> /// </summary>
/// <typeparam name="T">The type of tag to read</typeparam> /// <typeparam name="T">The type of tag to read</typeparam>
/// <param name="tag">The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. /// <param name="tag">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`</param> /// E.g: the tag `foo.bar` reads the tag `bar` on the folder `foo`</param>
/// <returns>The value retrieved from the OPC</returns> /// <returns>The value retrieved from the OPC</returns>
ReadEvent<T> Read<T>(string tag); ReadEvent<T> Read<T>(string tag);
/// <summary> /// <summary>
/// Write a value on the specified opc tag /// Write a value on the specified opc tag
/// </summary> /// </summary>
/// <typeparam name="T">The type of tag to write on</typeparam> /// <typeparam name="T">The type of tag to write on</typeparam>
/// <param name="tag">The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. /// <param name="tag">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`</param> /// E.g: the tag `foo.bar` writes on the tag `bar` on the folder `foo`</param>
/// <param name="item"></param> /// <param name="item"></param>
void Write<T>(string tag, T item); void Write<T>(string tag, T item);
/// <summary> /// <summary>
/// Monitor the specified tag for changes /// Monitor the specified tag for changes
/// </summary> /// </summary>
/// <typeparam name="T">the type of tag to monitor</typeparam> /// <typeparam name="T">the type of tag to monitor</typeparam>
/// <param name="tag">The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. /// <param name="tag">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`</param> /// E.g: the tag `foo.bar` monitors the tag `bar` on the folder `foo`</param>
/// <param name="callback">the callback to execute when the value is changed. /// <param name="callback">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</param> /// The first parameter is the new value of the node, the second is an `unsubscribe` function to unsubscribe the callback</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an async method.")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an async method.")]
void Monitor<T>(string tag, Action<ReadEvent<T>, Action> callback); void Monitor<T>(string tag, Action<ReadEvent<T>, Action> callback);
/// <summary> /// <summary>
/// Finds a node on the Opc Server /// Finds a node on the Opc Server
/// </summary> /// </summary>
/// <param name="tag">The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. /// <param name="tag">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`</param> /// E.g: the tag `foo.bar` finds the tag `bar` on the folder `foo`</param>
/// <returns>If there is a tag, it returns it, otherwise it throws an </returns> /// <returns>If there is a tag, it returns it, otherwise it throws an </returns>
TNode FindNode(string tag); TNode FindNode(string tag);
/// <summary> /// <summary>
/// Gets the root node of the server /// Gets the root node of the server
/// </summary> /// </summary>
TNode RootNode { get; } TNode RootNode { get; }
/// <summary> /// <summary>
/// Explore a folder on the Opc Server /// Explore a folder on the Opc Server
/// </summary> /// </summary>
/// <param name="tag">The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. /// <param name="tag">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`</param> /// E.g: the tag `foo.bar` finds the sub nodes of `bar` on the folder `foo`</param>
/// <returns>The list of sub-nodes</returns> /// <returns>The list of sub-nodes</returns>
IEnumerable<TNode> ExploreFolder(string tag); IEnumerable<TNode> ExploreFolder(string tag);
/// <summary> /// <summary>
/// Read a tag asynchronusly /// Read a tag asynchronusly
/// </summary> /// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an async method.")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an async method.")]
Task<ReadEvent<T>> ReadAsync<T>(string tag); Task<ReadEvent<T>> ReadAsync<T>(string tag);
/// <summary> /// <summary>
/// Write a value on the specified opc tag asynchronously /// Write a value on the specified opc tag asynchronously
/// </summary> /// </summary>
Task WriteAsync<T>(string tag, T item); Task WriteAsync<T>(string tag, T item);
/// <summary> /// <summary>
/// Finds a node on the Opc Server asynchronously /// Finds a node on the Opc Server asynchronously
/// </summary> /// </summary>
Task<Node> FindNodeAsync(string tag); Task<Node> FindNodeAsync(string tag);
/// <summary> /// <summary>
/// Explore a folder on the Opc Server asynchronously /// Explore a folder on the Opc Server asynchronously
/// </summary> /// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "Task")] Justification = "Task")]
Task<IEnumerable<Node>> ExploreFolderAsync(string tag); Task<IEnumerable<Node>> ExploreFolderAsync(string tag);
} }
} }

View File

@@ -1,48 +1,46 @@
using System.Collections.Generic; namespace Hylasoft.Opc.Common
namespace Hylasoft.Opc.Common
{ {
/// <summary>
/// Base class representing a node on the OPC server
/// </summary>
public abstract class Node
{
/// <summary> /// <summary>
/// Gets the displayed name of the node /// Base class representing a node on the OPC server
/// </summary> /// </summary>
public string Name { get; protected set; } public abstract class Node
/// <summary>
/// Gets the dot-separated fully qualified tag of the node
/// </summary>
public string Tag { get; protected set; }
/// <summary>
/// Gets the parent node. If the node is root, returns null
/// </summary>
public Node Parent { get; private set; }
/// <summary>
/// Creates a new node
/// </summary>
/// <param name="name">the name of the node</param>
/// <param name="parent">The parent node</param>
protected Node(string name, Node parent = null)
{ {
Name = name; /// <summary>
Parent = parent; /// Gets the displayed name of the node
if (parent != null && !string.IsNullOrEmpty(parent.Tag)) /// </summary>
Tag = parent.Tag + '.' + name; public string Name { get; protected set; }
else
Tag = name;
}
/// <summary> /// <summary>
/// Overrides ToString() /// Gets the dot-separated fully qualified tag of the node
/// </summary> /// </summary>
public override string ToString() public string Tag { get; protected set; }
{
return Tag; /// <summary>
/// Gets the parent node. If the node is root, returns null
/// </summary>
public Node Parent { get; private set; }
/// <summary>
/// Creates a new node
/// </summary>
/// <param name="name">the name of the node</param>
/// <param name="parent">The parent node</param>
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;
}
/// <summary>
/// Overrides ToString()
/// </summary>
public override string ToString()
{
return Tag;
}
} }
}
} }

View File

@@ -4,67 +4,67 @@ using System.Runtime.Serialization;
namespace Hylasoft.Opc.Common namespace Hylasoft.Opc.Common
{ {
/// <summary>
/// Identifies an exception occurred during OPC Communication
/// </summary>
[Serializable]
public class OpcException : Exception
{
/// <summary> /// <summary>
/// Initialize a new instance of the OpcException class /// Identifies an exception occurred during OPC Communication
/// </summary> /// </summary>
public OpcException() [Serializable]
public class OpcException : Exception
{ {
/// <summary>
/// Initialize a new instance of the OpcException class
/// </summary>
public OpcException()
{
}
/// <summary>
/// Initialize a new instance of the OpcException class
/// </summary>
public OpcException(string message)
: base(message)
{
}
/// <summary>
/// Returns an (optional) associated OPC UA StatusCode for the exception.
/// </summary>
public StatusCode? Status { get; private set; }
/// <summary>
/// Initialize a new instance of the OpcException class
/// </summary>
public OpcException(string message, StatusCode status)
: base(message)
{
Status = status;
}
/// <summary>
/// Initialize a new instance of the OpcException class
/// </summary>
public OpcException(string message, Exception inner)
: base(message, inner)
{
}
/// <summary>
/// Initialize a new instance of the OpcException class
/// </summary>
protected OpcException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
/// <summary>
/// Sets the System.Runtime.Serialization.SerializationInfo with information about the exception.
/// </summary>
/// <param name="info">The System.Runtime.Serialization.SerializationInfo that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The System.Runtime.Serialization.StreamingContext that contains contextual information about the source or destination.</param>
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
}
} }
/// <summary>
/// Initialize a new instance of the OpcException class
/// </summary>
public OpcException(string message)
: base(message)
{
}
/// <summary>
/// Returns an (optional) associated OPC UA StatusCode for the exception.
/// </summary>
public StatusCode? Status { get; private set; }
/// <summary>
/// Initialize a new instance of the OpcException class
/// </summary>
public OpcException(string message, StatusCode status)
: base(message)
{
Status = status;
}
/// <summary>
/// Initialize a new instance of the OpcException class
/// </summary>
public OpcException(string message, Exception inner)
: base(message, inner)
{
}
/// <summary>
/// Initialize a new instance of the OpcException class
/// </summary>
protected OpcException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
/// <summary>
/// Sets the System.Runtime.Serialization.SerializationInfo with information about the exception.
/// </summary>
/// <param name="info">The System.Runtime.Serialization.SerializationInfo that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The System.Runtime.Serialization.StreamingContext that contains contextual information about the source or destination.</param>
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
}
}
} }

View File

@@ -1,18 +1,18 @@
namespace Hylasoft.Opc.Common namespace Hylasoft.Opc.Common
{ {
/// <summary>
/// Identifies the status of an OPC connector
/// </summary>
public enum OpcStatus
{
/// <summary> /// <summary>
/// The client is not connected /// Identifies the status of an OPC connector
/// </summary> /// </summary>
NotConnected, public enum OpcStatus
{
/// <summary>
/// The client is not connected
/// </summary>
NotConnected,
/// <summary> /// <summary>
/// The client is connected /// The client is connected
/// </summary> /// </summary>
Connected Connected
} }
} }

View File

@@ -2,27 +2,27 @@
namespace Hylasoft.Opc.Common namespace Hylasoft.Opc.Common
{ {
/// <summary>
/// Represents the quality of the value captured
/// </summary>
public enum Quality
{
/// <summary> /// <summary>
/// Quality: Unknown, the value of the quality could not be inferred by the library /// Represents the quality of the value captured
/// </summary> /// </summary>
[Description("Unknown")] public enum Quality
Unknown, {
/// <summary>
/// Quality: Unknown, the value of the quality could not be inferred by the library
/// </summary>
[Description("Unknown")]
Unknown,
/// <summary> /// <summary>
/// Quality: Good /// Quality: Good
/// </summary> /// </summary>
[Description("Good")] [Description("Good")]
Good, Good,
/// <summary> /// <summary>
/// Quality: Bad /// Quality: Bad
/// </summary> /// </summary>
[Description("Bad")] [Description("Bad")]
Bad Bad
} }
} }

View File

@@ -1,37 +1,33 @@
using System; using System;
using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hylasoft.Opc.Common namespace Hylasoft.Opc.Common
{ {
/// <summary>
/// Base class representing a monitor event on the OPC server
/// </summary>
/// <typeparam name="T"></typeparam>
public class ReadEvent<T>
{
/// <summary> /// <summary>
/// Gets the value that was read from the server /// Base class representing a monitor event on the OPC server
/// </summary> /// </summary>
public T Value { get; set; } /// <typeparam name="T"></typeparam>
public class ReadEvent<T>
{
/// <summary>
/// Gets the value that was read from the server
/// </summary>
public T Value { get; set; }
/// <summary> /// <summary>
/// Gets the quality of the signal from the server /// Gets the quality of the signal from the server
/// </summary> /// </summary>
[DefaultValue(Common.Quality.Unknown)] [DefaultValue(Common.Quality.Unknown)]
public Quality Quality { get; set; } public Quality Quality { get; set; }
/// <summary> /// <summary>
/// Gets the source timestamp on when the event ocurred /// Gets the source timestamp on when the event ocurred
/// </summary> /// </summary>
public DateTime SourceTimestamp { get; set; } public DateTime SourceTimestamp { get; set; }
/// <summary> /// <summary>
/// Gets the server timestamp on when the event ocurred /// Gets the server timestamp on when the event ocurred
/// </summary> /// </summary>
public DateTime ServerTimestamp { get; set; } public DateTime ServerTimestamp { get; set; }
} }
} }

View File

@@ -3,22 +3,22 @@ using OpcF = Opc.Ua;
namespace Hylasoft.Opc.Ua namespace Hylasoft.Opc.Ua
{ {
/// <summary>
/// Class with extension methods for OPC UA
/// </summary>
public static class NodeExtensions
{
/// <summary> /// <summary>
/// Converts an OPC Foundation node to an Hylasoft OPC UA Node /// Class with extension methods for OPC UA
/// </summary> /// </summary>
/// <param name="node">The node to convert</param> public static class NodeExtensions
/// <param name="parent">the parent node (optional)</param>
/// <returns></returns>
internal static UaNode ToHylaNode(this OpcF.ReferenceDescription node, Node parent = null)
{ {
var name = node.DisplayName.ToString(); /// <summary>
var nodeId = node.NodeId.ToString(); /// Converts an OPC Foundation node to an Hylasoft OPC UA Node
return new UaNode(name, nodeId, parent); /// </summary>
/// <param name="node">The node to convert</param>
/// <param name="parent">the parent node (optional)</param>
/// <returns></returns>
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);
}
} }
}
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,121 +1,120 @@
using System; using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.X509Certificates;
using OpcUa = Opc.Ua; using OpcUa = Opc.Ua;
namespace Hylasoft.Opc.Ua namespace Hylasoft.Opc.Ua
{ {
/// <summary>
/// This class defines the configuration options for the setup of the UA client session
/// </summary>
public class UaClientOptions
{
/// <summary> /// <summary>
/// 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
/// </summary> /// </summary>
public X509Certificate2 ApplicationCertificate { get; set; } public class UaClientOptions
/// <summary>
/// Specifies the ApplicationName for the client application.
/// </summary>
public string ApplicationName { get; set; }
/// <summary>
/// Should untrusted certificates be silently accepted by the client?
/// </summary>
public bool AutoAcceptUntrustedCertificates { get; set; }
/// <summary>
/// Specifies the ConfigSectionName for the client configuration.
/// </summary>
public string ConfigSectionName { get; set; }
/// <summary>
/// default monitor interval in Milliseconds.
/// </summary>
public int DefaultMonitorInterval { get; set; }
/// <summary>
/// Specifies a name to be associated with the created sessions.
/// </summary>
public string SessionName { get; set; }
/// <summary>
/// Specifies the timeout for the sessions.
/// </summary>
public uint SessionTimeout { get; set; }
/// <summary>
/// Specify whether message exchange should be secured.
/// </summary>
public bool UseMessageSecurity { get; set; }
/// <summary>
/// The maximum number of notifications per publish request.
/// The clients 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.
/// </summary>
public uint SubscriptionLifetimeCount { get; set; }
/// <summary>
/// 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.
/// </summary>
public uint SubscriptionKeepAliveCount { get; set; }
/// <summary>
/// Gets or sets the max subscription count.
/// </summary>
public int MaxSubscriptionCount { get; set; }
/// <summary>
/// The maximum number of messages saved in the queue for each subscription.
/// </summary>
public int MaxMessageQueueSize { get; set; }
/// <summary>
/// The maximum number of notificates saved in the queue for each monitored item.
/// </summary>
public int MaxNotificationQueueSize { get; set; }
/// <summary>
/// Gets or sets the max publish request count.
/// </summary>
public int MaxPublishRequestCount { get; set; }
/// <summary>
/// The identity to connect to the OPC server as
/// </summary>
public OpcUa.UserIdentity UserIdentity { get; set; }
/// <summary>
/// Creates a client options object
/// </summary>
public UaClientOptions()
{ {
// Initialize default values: /// <summary>
ApplicationName = "h-opc-client"; /// Specifies the (optional) certificate for the application to connect to the server
AutoAcceptUntrustedCertificates = true; /// </summary>
ConfigSectionName = "h-opc-client"; public X509Certificate2 ApplicationCertificate { get; set; }
DefaultMonitorInterval = 100;
SessionName = "h-opc-client"; /// <summary>
SessionTimeout = 60000U; /// Specifies the ApplicationName for the client application.
UseMessageSecurity = false; /// </summary>
SubscriptionLifetimeCount = 0; public string ApplicationName { get; set; }
SubscriptionKeepAliveCount = 0;
MaxSubscriptionCount = 100; /// <summary>
MaxMessageQueueSize = 10; /// Should untrusted certificates be silently accepted by the client?
MaxNotificationQueueSize = 100; /// </summary>
MaxPublishRequestCount = 20; public bool AutoAcceptUntrustedCertificates { get; set; }
/// <summary>
/// Specifies the ConfigSectionName for the client configuration.
/// </summary>
public string ConfigSectionName { get; set; }
/// <summary>
/// default monitor interval in Milliseconds.
/// </summary>
public int DefaultMonitorInterval { get; set; }
/// <summary>
/// Specifies a name to be associated with the created sessions.
/// </summary>
public string SessionName { get; set; }
/// <summary>
/// Specifies the timeout for the sessions.
/// </summary>
public uint SessionTimeout { get; set; }
/// <summary>
/// Specify whether message exchange should be secured.
/// </summary>
public bool UseMessageSecurity { get; set; }
/// <summary>
/// The maximum number of notifications per publish request.
/// The clients 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.
/// </summary>
public uint SubscriptionLifetimeCount { get; set; }
/// <summary>
/// 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.
/// </summary>
public uint SubscriptionKeepAliveCount { get; set; }
/// <summary>
/// Gets or sets the max subscription count.
/// </summary>
public int MaxSubscriptionCount { get; set; }
/// <summary>
/// The maximum number of messages saved in the queue for each subscription.
/// </summary>
public int MaxMessageQueueSize { get; set; }
/// <summary>
/// The maximum number of notificates saved in the queue for each monitored item.
/// </summary>
public int MaxNotificationQueueSize { get; set; }
/// <summary>
/// Gets or sets the max publish request count.
/// </summary>
public int MaxPublishRequestCount { get; set; }
/// <summary>
/// The identity to connect to the OPC server as
/// </summary>
public OpcUa.UserIdentity UserIdentity { get; set; }
/// <summary>
/// Creates a client options object
/// </summary>
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;
}
} }
}
} }

View File

@@ -2,28 +2,28 @@
namespace Hylasoft.Opc.Ua namespace Hylasoft.Opc.Ua
{ {
/// <summary>
/// Represents a node to be used specifically for OPC UA
/// </summary>
public class UaNode : Node
{
/// <summary> /// <summary>
/// The UA Id of the node /// Represents a node to be used specifically for OPC UA
/// </summary> /// </summary>
public string NodeId { get; private set; } public class UaNode : Node
/// <summary>
/// Instantiates a UaNode class
/// </summary>
/// <param name="name">the name of the node</param>
/// <param name="nodeId">The UA Id of the node</param>
/// <param name="parent">The parent node</param>
internal UaNode(string name, string nodeId, Node parent = null)
: base(name, parent)
{ {
NodeId = nodeId; /// <summary>
/// The UA Id of the node
/// </summary>
public string NodeId { get; private set; }
/// <summary>
/// Instantiates a UaNode class
/// </summary>
/// <param name="name">the name of the node</param>
/// <param name="nodeId">The UA Id of the node</param>
/// <param name="parent">The parent node</param>
internal UaNode(string name, string nodeId, Node parent = null)
: base(name, parent)
{
NodeId = nodeId;
}
} }
}
} }

226
Modbus.Net/.editorconfig Normal file
View File

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

View File

@@ -1,8 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Modbus.Net.Modbus.NA200H namespace Modbus.Net.Modbus.NA200H
{ {

View File

@@ -5,7 +5,7 @@
<AssemblyName>Modbus.Net.Modbus.NA200H</AssemblyName> <AssemblyName>Modbus.Net.Modbus.NA200H</AssemblyName>
<RootNamespace>Modbus.Net.Modbus.NA200H</RootNamespace> <RootNamespace>Modbus.Net.Modbus.NA200H</RootNamespace>
<PackageId>Modbus.Net.Modbus.NA200H</PackageId> <PackageId>Modbus.Net.Modbus.NA200H</PackageId>
<Version>1.4.0</Version> <Version>1.4.0-beta03</Version>
<Authors>Chris L.(Luo Sheng)</Authors> <Authors>Chris L.(Luo Sheng)</Authors>
<Company>Hangzhou Delian Science Technology Co.,Ltd.</Company> <Company>Hangzhou Delian Science Technology Co.,Ltd.</Company>
<Product>Modbus.Net.Modbus</Product> <Product>Modbus.Net.Modbus</Product>

View File

@@ -5,7 +5,7 @@
<AssemblyName>Modbus.Net.Modbus</AssemblyName> <AssemblyName>Modbus.Net.Modbus</AssemblyName>
<RootNamespace>Modbus.Net.Modbus</RootNamespace> <RootNamespace>Modbus.Net.Modbus</RootNamespace>
<PackageId>Modbus.Net.Modbus</PackageId> <PackageId>Modbus.Net.Modbus</PackageId>
<Version>1.4.0</Version> <Version>1.4.0-beta03</Version>
<Authors>Chris L.(Luo Sheng)</Authors> <Authors>Chris L.(Luo Sheng)</Authors>
<Company>Hangzhou Delian Science Technology Co.,Ltd.</Company> <Company>Hangzhou Delian Science Technology Co.,Ltd.</Company>
<Product>Modbus.Net.Modbus</Product> <Product>Modbus.Net.Modbus</Product>

View File

@@ -18,7 +18,7 @@ namespace Modbus.Net.Modbus
public ModbusAsciiProtocolLinker(string com, int slaveAddress) public ModbusAsciiProtocolLinker(string com, int slaveAddress)
: base(com, 9600, Parity.None, StopBits.One, 8, 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")));
} }
/// <summary> /// <summary>

View File

@@ -132,10 +132,10 @@ namespace Modbus.Net.Modbus
{ {
SlaveAddress = slaveAddress; SlaveAddress = slaveAddress;
var translateAddress = addressTranslator.AddressTranslate(startAddress, true); var translateAddress = addressTranslator.AddressTranslate(startAddress, true);
FunctionCode = (byte) translateAddress.Area; FunctionCode = (byte)translateAddress.Area;
StartAddress = (ushort) translateAddress.Address; StartAddress = (ushort)translateAddress.Address;
GetCount = GetCount =
(ushort) Math.Ceiling(getCount / addressTranslator.GetAreaByteLength(translateAddress.AreaString)); (ushort)Math.Ceiling(getCount / addressTranslator.GetAreaByteLength(translateAddress.AreaString));
} }
/// <summary> /// <summary>
@@ -213,7 +213,7 @@ namespace Modbus.Net.Modbus
/// <returns>读取数据的协议核心</returns> /// <returns>读取数据的协议核心</returns>
public override byte[] Format(IInputStruct message) public override byte[] Format(IInputStruct message)
{ {
var r_message = (ReadDataModbusInputStruct) message; var r_message = (ReadDataModbusInputStruct)message;
return Format(r_message.SlaveAddress, r_message.FunctionCode, return Format(r_message.SlaveAddress, r_message.FunctionCode,
r_message.StartAddress, r_message.GetCount); r_message.StartAddress, r_message.GetCount);
} }
@@ -257,12 +257,12 @@ namespace Modbus.Net.Modbus
{ {
SlaveAddress = slaveAddress; SlaveAddress = slaveAddress;
var translateAddress = addressTranslator.AddressTranslate(startAddress, false); var translateAddress = addressTranslator.AddressTranslate(startAddress, false);
FunctionCode = (byte) translateAddress.Area; FunctionCode = (byte)translateAddress.Area;
StartAddress = (ushort) translateAddress.Address; StartAddress = (ushort)translateAddress.Address;
var writeByteValue = ValueHelper.GetInstance(endian).ObjectArrayToByteArray(writeValue); var writeByteValue = ValueHelper.GetInstance(endian).ObjectArrayToByteArray(writeValue);
WriteCount = WriteCount =
(ushort) (writeByteValue.Length / addressTranslator.GetAreaByteLength(translateAddress.AreaString)); (ushort)(writeByteValue.Length / addressTranslator.GetAreaByteLength(translateAddress.AreaString));
WriteByteCount = (byte) writeByteValue.Length; WriteByteCount = (byte)writeByteValue.Length;
WriteValue = writeByteValue; WriteValue = writeByteValue;
} }
@@ -351,7 +351,7 @@ namespace Modbus.Net.Modbus
/// <returns>写寄存器协议核心</returns> /// <returns>写寄存器协议核心</returns>
public override byte[] Format(IInputStruct message) public override byte[] Format(IInputStruct message)
{ {
var r_message = (WriteDataModbusInputStruct) message; var r_message = (WriteDataModbusInputStruct)message;
var dataValue = Format(r_message.WriteValue); var dataValue = Format(r_message.WriteValue);
var formattingBytes = Format(r_message.SlaveAddress, r_message.FunctionCode, var formattingBytes = Format(r_message.SlaveAddress, r_message.FunctionCode,
r_message.StartAddress, r_message.WriteCount, r_message.WriteByteCount, dataValue); r_message.StartAddress, r_message.WriteCount, r_message.WriteByteCount, dataValue);
@@ -393,13 +393,13 @@ namespace Modbus.Net.Modbus
{ {
SlaveAddress = slaveAddress; SlaveAddress = slaveAddress;
var translateAddress = addressTranslator.AddressTranslate(startAddress, false, true); var translateAddress = addressTranslator.AddressTranslate(startAddress, false, true);
FunctionCode = (byte) translateAddress.Area; FunctionCode = (byte)translateAddress.Area;
StartAddress = (ushort) translateAddress.Address; StartAddress = (ushort)translateAddress.Address;
var writeByteValue = var writeByteValue =
FunctionCode == (byte) ModbusProtocolWriteDataFunctionCode.WriteSingleCoil FunctionCode == (byte)ModbusProtocolWriteDataFunctionCode.WriteSingleCoil
? ((bool) writeValue ? ((bool)writeValue
? new byte[] {0xFF, 0x00} ? new byte[] { 0xFF, 0x00 }
: new byte[] {0x00, 0x00}) : new byte[] { 0x00, 0x00 })
: ValueHelper.GetInstance(endian).GetBytes(ushort.Parse(writeValue.ToString())); : ValueHelper.GetInstance(endian).GetBytes(ushort.Parse(writeValue.ToString()));
WriteValue = writeByteValue; WriteValue = writeByteValue;
} }
@@ -480,7 +480,7 @@ namespace Modbus.Net.Modbus
/// <returns>写寄存器协议核心</returns> /// <returns>写寄存器协议核心</returns>
public override byte[] Format(IInputStruct message) public override byte[] Format(IInputStruct message)
{ {
var r_message = (WriteSingleDataModbusInputStruct) message; var r_message = (WriteSingleDataModbusInputStruct)message;
var dataValue = Format(r_message.WriteValue); var dataValue = Format(r_message.WriteValue);
var formattingBytes = Format(r_message.SlaveAddress, r_message.FunctionCode, var formattingBytes = Format(r_message.SlaveAddress, r_message.FunctionCode,
r_message.StartAddress, dataValue); r_message.StartAddress, dataValue);
@@ -522,7 +522,7 @@ namespace Modbus.Net.Modbus
public GetSystemTimeModbusInputStruct(byte slaveAddress) public GetSystemTimeModbusInputStruct(byte slaveAddress)
{ {
SlaveAddress = slaveAddress; SlaveAddress = slaveAddress;
FunctionCode = (byte) ModbusProtocolTimeFunctionCode.GetSystemTime; FunctionCode = (byte)ModbusProtocolTimeFunctionCode.GetSystemTime;
StartAddress = 30000; StartAddress = 30000;
GetCount = 5; GetCount = 5;
} }
@@ -609,7 +609,7 @@ namespace Modbus.Net.Modbus
/// <returns>写系统时间的核心</returns> /// <returns>写系统时间的核心</returns>
public override byte[] Format(IInputStruct message) public override byte[] Format(IInputStruct message)
{ {
var r_message = (GetSystemTimeModbusInputStruct) message; var r_message = (GetSystemTimeModbusInputStruct)message;
return Format(r_message.SlaveAddress, r_message.FunctionCode, return Format(r_message.SlaveAddress, r_message.FunctionCode,
r_message.StartAddress, r_message.GetCount); r_message.StartAddress, r_message.GetCount);
} }
@@ -654,17 +654,17 @@ namespace Modbus.Net.Modbus
public SetSystemTimeModbusInputStruct(byte slaveAddress, DateTime time) public SetSystemTimeModbusInputStruct(byte slaveAddress, DateTime time)
{ {
SlaveAddress = slaveAddress; SlaveAddress = slaveAddress;
FunctionCode = (byte) ModbusProtocolTimeFunctionCode.SetSystemTime; FunctionCode = (byte)ModbusProtocolTimeFunctionCode.SetSystemTime;
StartAddress = 30000; StartAddress = 30000;
WriteCount = 5; WriteCount = 5;
WriteByteCount = 10; WriteByteCount = 10;
Year = (ushort) time.Year; Year = (ushort)time.Year;
Day = (byte) time.Day; Day = (byte)time.Day;
Month = (byte) time.Month; Month = (byte)time.Month;
Hour = (ushort) time.Hour; Hour = (ushort)time.Hour;
Second = (byte) time.Second; Second = (byte)time.Second;
Minute = (byte) time.Minute; Minute = (byte)time.Minute;
Millisecond = (ushort) time.Millisecond; Millisecond = (ushort)time.Millisecond;
} }
/// <summary> /// <summary>
@@ -782,7 +782,7 @@ namespace Modbus.Net.Modbus
/// <returns>写系统时间的核心</returns> /// <returns>写系统时间的核心</returns>
public override byte[] Format(IInputStruct message) public override byte[] Format(IInputStruct message)
{ {
var r_message = (SetSystemTimeModbusInputStruct) message; var r_message = (SetSystemTimeModbusInputStruct)message;
return Format(r_message.SlaveAddress, r_message.FunctionCode, return Format(r_message.SlaveAddress, r_message.FunctionCode,
r_message.StartAddress, r_message.WriteCount, r_message.WriteByteCount, r_message.Year, r_message.StartAddress, r_message.WriteCount, r_message.WriteByteCount, r_message.Year,
r_message.Day, r_message.Day,

View File

@@ -26,7 +26,7 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
public class ModbusUdpProtocolLinkerBytesExtend : ModbusTcpProtocolLinkerBytesExtend public class ModbusUdpProtocolLinkerBytesExtend : ModbusTcpProtocolLinkerBytesExtend
{ {
} }
/// <summary> /// <summary>
@@ -34,7 +34,7 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
public class ModbusRtuInTcpProtocolLinkerBytesExtend : ModbusRtuProtocolLinkerBytesExtend public class ModbusRtuInTcpProtocolLinkerBytesExtend : ModbusRtuProtocolLinkerBytesExtend
{ {
} }
/// <summary> /// <summary>
@@ -60,7 +60,7 @@ namespace Modbus.Net.Modbus
//Modbus/Tcp协议扩张前面加6个字节前面4个为0后面两个为协议整体内容的长度 //Modbus/Tcp协议扩张前面加6个字节前面4个为0后面两个为协议整体内容的长度
var newFormat = new byte[6 + content.Length]; var newFormat = new byte[6 + content.Length];
var tag = 0; 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(tag), 0, newFormat, 0, 4);
Array.Copy(BigEndianValueHelper.Instance.GetBytes(leng), 0, newFormat, 4, 2); Array.Copy(BigEndianValueHelper.Instance.GetBytes(leng), 0, newFormat, 4, 2);
Array.Copy(content, 0, newFormat, 6, content.Length); Array.Copy(content, 0, newFormat, 6, content.Length);

View File

@@ -17,7 +17,7 @@ namespace Modbus.Net.Modbus
public ModbusRtuProtocolLinker(string com, int slaveAddress) public ModbusRtuProtocolLinker(string com, int slaveAddress)
: base(com, 9600, Parity.None, StopBits.One, 8, 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")));
} }
/// <summary> /// <summary>

View File

@@ -24,7 +24,7 @@ namespace Modbus.Net.Modbus
/// <param name="port">端口</param> /// <param name="port">端口</param>
public ModbusTcpProtocolLinker(string ip, int port) : base(ip, port) 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<int>{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<int> { 4, 5 }, 6)));
} }
/// <summary> /// <summary>

View File

@@ -1,6 +1,6 @@
using System; using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Serilog;
namespace Modbus.Net.Modbus namespace Modbus.Net.Modbus
{ {
@@ -69,6 +69,8 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
public class ModbusUtility : BaseUtility, IUtilityMethodTime, IUtilityMethodWriteSingle public class ModbusUtility : BaseUtility, IUtilityMethodTime, IUtilityMethodWriteSingle
{ {
private static readonly ILogger<ModbusUtility> logger = LogProvider.CreateLogger<ModbusUtility>();
/// <summary> /// <summary>
/// Modbus协议类型 /// Modbus协议类型
/// </summary> /// </summary>
@@ -87,7 +89,7 @@ namespace Modbus.Net.Modbus
{ {
Endian = endian; Endian = endian;
ConnectionString = null; ConnectionString = null;
ModbusType = (ModbusType) connectionType; ModbusType = (ModbusType)connectionType;
AddressTranslator = new AddressTranslatorModbus(); AddressTranslator = new AddressTranslatorModbus();
} }
@@ -138,11 +140,11 @@ namespace Modbus.Net.Modbus
var connectionStringSplit = ConnectionString.Split(':'); var connectionStringSplit = ConnectionString.Split(':');
try try
{ {
return connectionStringSplit.Length < 2 ? (int?) null : int.Parse(connectionStringSplit[1]); return connectionStringSplit.Length < 2 ? (int?)null : int.Parse(connectionStringSplit[1]);
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility: {ConnectionString} format error"); logger.LogError(e, $"ModbusUtility: {ConnectionString} format error");
return null; return null;
} }
} }
@@ -161,86 +163,86 @@ namespace Modbus.Net.Modbus
{ {
//Rtu协议 //Rtu协议
case ModbusType.Rtu: case ModbusType.Rtu:
{ {
Wrapper = ConnectionString == null Wrapper = ConnectionString == null
? new ModbusRtuProtocol(SlaveAddress, MasterAddress) ? new ModbusRtuProtocol(SlaveAddress, MasterAddress)
: new ModbusRtuProtocol(ConnectionString, SlaveAddress, MasterAddress); : new ModbusRtuProtocol(ConnectionString, SlaveAddress, MasterAddress);
break; break;
} }
//Tcp协议 //Tcp协议
case ModbusType.Tcp: case ModbusType.Tcp:
{ {
Wrapper = ConnectionString == null Wrapper = ConnectionString == null
? new ModbusTcpProtocol(SlaveAddress, MasterAddress) ? new ModbusTcpProtocol(SlaveAddress, MasterAddress)
: (ConnectionStringPort == null : (ConnectionStringPort == null
? new ModbusTcpProtocol(ConnectionString, SlaveAddress, MasterAddress) ? new ModbusTcpProtocol(ConnectionString, SlaveAddress, MasterAddress)
: new ModbusTcpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, : new ModbusTcpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress,
MasterAddress)); MasterAddress));
break; break;
} }
//Ascii协议 //Ascii协议
case ModbusType.Ascii: case ModbusType.Ascii:
{ {
Wrapper = ConnectionString == null Wrapper = ConnectionString == null
? new ModbusAsciiProtocol(SlaveAddress, MasterAddress) ? new ModbusAsciiProtocol(SlaveAddress, MasterAddress)
: new ModbusAsciiProtocol(ConnectionString, SlaveAddress, MasterAddress); : new ModbusAsciiProtocol(ConnectionString, SlaveAddress, MasterAddress);
break; break;
} }
//Rtu协议Tcp透传 //Rtu协议Tcp透传
case ModbusType.RtuInTcp: case ModbusType.RtuInTcp:
{ {
Wrapper = ConnectionString == null Wrapper = ConnectionString == null
? new ModbusRtuInTcpProtocol(SlaveAddress, MasterAddress) ? new ModbusRtuInTcpProtocol(SlaveAddress, MasterAddress)
: (ConnectionStringPort == null : (ConnectionStringPort == null
? new ModbusRtuInTcpProtocol(ConnectionString, SlaveAddress, MasterAddress) ? new ModbusRtuInTcpProtocol(ConnectionString, SlaveAddress, MasterAddress)
: new ModbusRtuInTcpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, : new ModbusRtuInTcpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress,
MasterAddress)); MasterAddress));
break; break;
} }
//Ascii协议Tcp透传 //Ascii协议Tcp透传
case ModbusType.AsciiInTcp: case ModbusType.AsciiInTcp:
{ {
Wrapper = ConnectionString == null Wrapper = ConnectionString == null
? new ModbusAsciiInTcpProtocol(SlaveAddress, MasterAddress) ? new ModbusAsciiInTcpProtocol(SlaveAddress, MasterAddress)
: (ConnectionStringPort == null : (ConnectionStringPort == null
? new ModbusAsciiInTcpProtocol(ConnectionString, SlaveAddress, MasterAddress) ? new ModbusAsciiInTcpProtocol(ConnectionString, SlaveAddress, MasterAddress)
: new ModbusAsciiInTcpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, : new ModbusAsciiInTcpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress,
MasterAddress)); MasterAddress));
break; break;
} }
//Tcp协议Udp透传 //Tcp协议Udp透传
case ModbusType.Udp: case ModbusType.Udp:
{ {
Wrapper = ConnectionString == null Wrapper = ConnectionString == null
? new ModbusUdpProtocol(SlaveAddress, MasterAddress) ? new ModbusUdpProtocol(SlaveAddress, MasterAddress)
: (ConnectionStringPort == null : (ConnectionStringPort == null
? new ModbusUdpProtocol(ConnectionString, SlaveAddress, MasterAddress) ? new ModbusUdpProtocol(ConnectionString, SlaveAddress, MasterAddress)
: new ModbusUdpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, : new ModbusUdpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress,
MasterAddress)); MasterAddress));
break; break;
} }
//Rtu协议Udp透传 //Rtu协议Udp透传
case ModbusType.RtuInUdp: case ModbusType.RtuInUdp:
{ {
Wrapper = ConnectionString == null Wrapper = ConnectionString == null
? new ModbusRtuInUdpProtocol(SlaveAddress, MasterAddress) ? new ModbusRtuInUdpProtocol(SlaveAddress, MasterAddress)
: (ConnectionStringPort == null : (ConnectionStringPort == null
? new ModbusRtuInUdpProtocol(ConnectionString, SlaveAddress, MasterAddress) ? new ModbusRtuInUdpProtocol(ConnectionString, SlaveAddress, MasterAddress)
: new ModbusRtuInUdpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, : new ModbusRtuInUdpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress,
MasterAddress)); MasterAddress));
break; break;
} }
//Rtu协议Udp透传 //Rtu协议Udp透传
case ModbusType.AsciiInUdp: case ModbusType.AsciiInUdp:
{ {
Wrapper = ConnectionString == null Wrapper = ConnectionString == null
? new ModbusAsciiInUdpProtocol(SlaveAddress, MasterAddress) ? new ModbusAsciiInUdpProtocol(SlaveAddress, MasterAddress)
: (ConnectionStringPort == null : (ConnectionStringPort == null
? new ModbusAsciiInUdpProtocol(ConnectionString, SlaveAddress, MasterAddress) ? new ModbusAsciiInUdpProtocol(ConnectionString, SlaveAddress, MasterAddress)
: new ModbusAsciiInUdpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress, : new ModbusAsciiInUdpProtocol(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress,
MasterAddress)); MasterAddress));
break; break;
} }
} }
} }
} }
@@ -261,7 +263,7 @@ namespace Modbus.Net.Modbus
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility -> GetTime: {ConnectionString} error"); logger.LogError(e, $"ModbusUtility -> GetTime: {ConnectionString} error");
return DateTime.MinValue; return DateTime.MinValue;
} }
} }
@@ -283,7 +285,7 @@ namespace Modbus.Net.Modbus
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility -> SetTime: {ConnectionString} error"); logger.LogError(e, $"ModbusUtility -> SetTime: {ConnectionString} error");
return false; return false;
} }
} }
@@ -294,7 +296,7 @@ namespace Modbus.Net.Modbus
/// <param name="connectionType">协议类型</param> /// <param name="connectionType">协议类型</param>
public override void SetConnectionType(int connectionType) public override void SetConnectionType(int connectionType)
{ {
ModbusType = (ModbusType) connectionType; ModbusType = (ModbusType)connectionType;
} }
/// <summary> /// <summary>
@@ -308,7 +310,7 @@ namespace Modbus.Net.Modbus
try try
{ {
var inputStruct = new ReadDataModbusInputStruct(SlaveAddress, startAddress, var inputStruct = new ReadDataModbusInputStruct(SlaveAddress, startAddress,
(ushort) getByteCount, AddressTranslator); (ushort)getByteCount, AddressTranslator);
var outputStruct = await var outputStruct = await
Wrapper.SendReceiveAsync<ReadDataModbusOutputStruct>(Wrapper[typeof(ReadDataModbusProtocol)], Wrapper.SendReceiveAsync<ReadDataModbusOutputStruct>(Wrapper[typeof(ReadDataModbusProtocol)],
inputStruct); inputStruct);
@@ -316,7 +318,7 @@ namespace Modbus.Net.Modbus
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility -> GetDatas: {ConnectionString} error"); logger.LogError(e, $"ModbusUtility -> GetDatas: {ConnectionString} error");
return null; return null;
} }
} }
@@ -340,7 +342,7 @@ namespace Modbus.Net.Modbus
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility -> SetDatas: {ConnectionString} error"); logger.LogError(e, $"ModbusUtility -> SetDatas: {ConnectionString} error");
return false; return false;
} }
} }
@@ -364,7 +366,7 @@ namespace Modbus.Net.Modbus
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility -> SetSingleDatas: {ConnectionString} error"); logger.LogError(e, $"ModbusUtility -> SetSingleDatas: {ConnectionString} error");
return false; return false;
} }
} }

View File

@@ -1,8 +1,8 @@
using System; using Hylasoft.Opc.Common;
using Hylasoft.Opc.Ua;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hylasoft.Opc.Common;
using Hylasoft.Opc.Ua;
namespace Modbus.Net.OPC namespace Modbus.Net.OPC
{ {

View File

@@ -5,7 +5,7 @@
<AssemblyName>Modbus.Net.OPC</AssemblyName> <AssemblyName>Modbus.Net.OPC</AssemblyName>
<RootNamespace>Modbus.Net.OPC</RootNamespace> <RootNamespace>Modbus.Net.OPC</RootNamespace>
<PackageId>Modbus.Net.OPC</PackageId> <PackageId>Modbus.Net.OPC</PackageId>
<Version>1.4.0</Version> <Version>1.4.0-beta03</Version>
<Authors>Chris L.(Luo Sheng)</Authors> <Authors>Chris L.(Luo Sheng)</Authors>
<Company>Hangzhou Delian Science Technology Co.,Ltd.</Company> <Company>Hangzhou Delian Science Technology Co.,Ltd.</Company>
<Product>Modbus.Net.OPC</Product> <Product>Modbus.Net.OPC</Product>

View File

@@ -1,11 +1,10 @@
using System; using Hylasoft.Opc.Common;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hylasoft.Opc.Common;
using Serilog;
namespace Modbus.Net.OPC namespace Modbus.Net.OPC
{ {
@@ -14,6 +13,8 @@ namespace Modbus.Net.OPC
/// </summary> /// </summary>
public abstract class OpcConnector : BaseConnector<OpcParamIn, OpcParamOut> public abstract class OpcConnector : BaseConnector<OpcParamIn, OpcParamOut>
{ {
private static readonly ILogger<OpcConnector> logger = LogProvider.CreateLogger<OpcConnector>();
/// <summary> /// <summary>
/// 是否正在连接 /// 是否正在连接
/// </summary> /// </summary>
@@ -61,12 +62,12 @@ namespace Modbus.Net.OPC
Client?.Dispose(); Client?.Dispose();
Client = null; Client = null;
_connect = false; _connect = false;
Log.Information("opc client {ConnectionToken} disconnected success", ConnectionToken); logger.LogInformation("opc client {ConnectionToken} disconnected success", ConnectionToken);
return true; return true;
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.Error(ex, "opc client {ConnectionToken} disconnected error", ConnectionToken); logger.LogError(ex, "opc client {ConnectionToken} disconnected error", ConnectionToken);
_connect = false; _connect = false;
return false; return false;
} }
@@ -108,7 +109,7 @@ namespace Modbus.Net.OPC
if (answerTag != null) if (answerTag != null)
{ {
var result = await Client.ReadAsync<object>(answerTag); var result = await Client.ReadAsync<object>(answerTag);
Log.Verbose($"Opc Machine {ConnectionToken} Read opc tag {answerTag} for value {result}"); logger.LogDebug($"Opc Machine {ConnectionToken} Read opc tag {answerTag} for value {result}");
return new OpcParamOut return new OpcParamOut
{ {
Success = true, Success = true,
@@ -134,11 +135,11 @@ namespace Modbus.Net.OPC
try try
{ {
await Client.WriteAsync(answerTag, value); await Client.WriteAsync(answerTag, value);
Log.Verbose($"Opc Machine {ConnectionToken} Write opc tag {answerTag} for value {value}"); logger.LogDebug($"Opc Machine {ConnectionToken} Write opc tag {answerTag} for value {value}");
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "opc client {ConnectionToken} write exception", ConnectionToken); logger.LogError(e, "opc client {ConnectionToken} write exception", ConnectionToken);
return new OpcParamOut return new OpcParamOut
{ {
Success = false Success = false
@@ -157,7 +158,7 @@ namespace Modbus.Net.OPC
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "opc client {ConnectionToken} read exception", ConnectionToken); logger.LogError(e, "opc client {ConnectionToken} read exception", ConnectionToken);
return new OpcParamOut return new OpcParamOut
{ {
Success = false, Success = false,
@@ -200,12 +201,12 @@ namespace Modbus.Net.OPC
{ {
await Client.Connect(); await Client.Connect();
_connect = true; _connect = true;
Log.Information("opc client {ConnectionToken} connect success", ConnectionToken); logger.LogInformation("opc client {ConnectionToken} connect success", ConnectionToken);
return true; return true;
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.Error(ex, "opc client {ConnectionToken} connected failed", ConnectionToken); logger.LogError(ex, "opc client {ConnectionToken} connected failed", ConnectionToken);
_connect = false; _connect = false;
return false; return false;
} }

View File

@@ -77,7 +77,7 @@
/// <returns>格式化后的字节流</returns> /// <returns>格式化后的字节流</returns>
public override OpcParamIn Format(IInputStruct message) public override OpcParamIn Format(IInputStruct message)
{ {
var r_message = (ReadRequestOpcInputStruct) message; var r_message = (ReadRequestOpcInputStruct)message;
return new OpcParamIn return new OpcParamIn
{ {
IsRead = true, IsRead = true,
@@ -169,7 +169,7 @@
/// <returns>格式化后的字节流</returns> /// <returns>格式化后的字节流</returns>
public override OpcParamIn Format(IInputStruct message) public override OpcParamIn Format(IInputStruct message)
{ {
var r_message = (WriteRequestOpcInputStruct) message; var r_message = (WriteRequestOpcInputStruct)message;
return new OpcParamIn return new OpcParamIn
{ {
IsRead = false, IsRead = false,

View File

@@ -34,7 +34,7 @@ namespace Modbus.Net.OPC
//容错处理 //容错处理
var checkRight = CheckRight(receiveBytes); var checkRight = CheckRight(receiveBytes);
return checkRight == null return checkRight == null
? new OpcParamOut {Success = false, Value = new byte[0]} ? new OpcParamOut { Success = false, Value = new byte[0] }
: (!checkRight.Value ? null : receiveBytes); : (!checkRight.Value ? null : receiveBytes);
//返回字符 //返回字符
} }

View File

@@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
namespace Modbus.Net.OPC namespace Modbus.Net.OPC
{ {

View File

@@ -23,8 +23,8 @@ namespace Modbus.Net.OPC
: base(id, getAddresses, keepConnect) : base(id, getAddresses, keepConnect)
{ {
BaseUtility = new OpcUaUtility(connectionString, isRegexOn); BaseUtility = new OpcUaUtility(connectionString, isRegexOn);
((OpcUtility) BaseUtility).GetSeperator += ((OpcUtility)BaseUtility).GetSeperator +=
() => ((AddressFormaterOpc<string, string>) AddressFormater).Seperator; () => ((AddressFormaterOpc<string, string>)AddressFormater).Seperator;
} }
/// <summary> /// <summary>
@@ -56,8 +56,8 @@ namespace Modbus.Net.OPC
: base(id, getAddresses, keepConnect) : base(id, getAddresses, keepConnect)
{ {
BaseUtility = new OpcUaUtility(connectionString, isRegexOn); BaseUtility = new OpcUaUtility(connectionString, isRegexOn);
((OpcUtility) BaseUtility).GetSeperator += ((OpcUtility)BaseUtility).GetSeperator +=
() => ((AddressFormaterOpc<string, string>) AddressFormater).Seperator; () => ((AddressFormaterOpc<string, string>)AddressFormater).Seperator;
} }
/// <summary> /// <summary>

View File

@@ -1,6 +1,6 @@
using System; using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Serilog;
namespace Modbus.Net.OPC namespace Modbus.Net.OPC
{ {
@@ -11,6 +11,8 @@ namespace Modbus.Net.OPC
PipeUnit<OpcParamIn, OpcParamOut, IProtocolLinker<OpcParamIn, OpcParamOut>, PipeUnit<OpcParamIn, OpcParamOut, IProtocolLinker<OpcParamIn, OpcParamOut>,
ProtocolUnit<OpcParamIn, OpcParamOut>>> ProtocolUnit<OpcParamIn, OpcParamOut>>>
{ {
private static readonly ILogger<OpcUtility> logger = LogProvider.CreateLogger<OpcUtility>();
/// <summary> /// <summary>
/// 获取分隔符 /// 获取分隔符
/// </summary> /// </summary>
@@ -66,7 +68,7 @@ namespace Modbus.Net.OPC
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, $"OpcUtility -> GetDatas: {ConnectionString} error"); logger.LogError(e, $"OpcUtility -> GetDatas: {ConnectionString} error");
return null; return null;
} }
} }
@@ -92,7 +94,7 @@ namespace Modbus.Net.OPC
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, $"OpcUtility -> SetDatas: {ConnectionString} error"); logger.LogError(e, $"OpcUtility -> SetDatas: {ConnectionString} error");
return false; return false;
} }
} }

View File

@@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace Modbus.Net.Siemens namespace Modbus.Net.Siemens
{ {

View File

@@ -5,7 +5,7 @@
<AssemblyName>Modbus.Net.Siemens</AssemblyName> <AssemblyName>Modbus.Net.Siemens</AssemblyName>
<RootNamespace>Modbus.Net.Siemens</RootNamespace> <RootNamespace>Modbus.Net.Siemens</RootNamespace>
<PackageId>Modbus.Net.Siemens</PackageId> <PackageId>Modbus.Net.Siemens</PackageId>
<Version>1.4.0</Version> <Version>1.4.0-beta03</Version>
<Authors>Chris L.(Luo Sheng)</Authors> <Authors>Chris L.(Luo Sheng)</Authors>
<Company>Hangzhou Delian Science Technology Co.,Ltd.</Company> <Company>Hangzhou Delian Science Technology Co.,Ltd.</Company>
<Description>Modbus.Net Siemens Profinet Implementation</Description> <Description>Modbus.Net Siemens Profinet Implementation</Description>

View File

@@ -1,6 +1,6 @@
using System.Threading.Tasks; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration;
using Nito.AsyncEx; using Nito.AsyncEx;
using System.Threading.Tasks;
namespace Modbus.Net.Siemens namespace Modbus.Net.Siemens
{ {

View File

@@ -151,10 +151,10 @@ namespace Modbus.Net.Siemens
{ {
public override byte[] Format(IInputStruct message) public override byte[] Format(IInputStruct message)
{ {
var r_message = (ComCreateReferenceSiemensInputStruct) message; var r_message = (ComCreateReferenceSiemensInputStruct)message;
var crc = (r_message.SlaveAddress + r_message.MasterAddress + 0x49) % 256; var crc = (r_message.SlaveAddress + r_message.MasterAddress + 0x49) % 256;
return Format((byte) 0x10, r_message.SlaveAddress, r_message.MasterAddress, (byte) 0x49, (byte) crc, return Format((byte)0x10, r_message.SlaveAddress, r_message.MasterAddress, (byte)0x49, (byte)crc,
(byte) 0x16); (byte)0x16);
} }
public override IOutputStruct Unformat(byte[] messageBytes, ref int pos) public override IOutputStruct Unformat(byte[] messageBytes, ref int pos)
@@ -206,7 +206,7 @@ namespace Modbus.Net.Siemens
{ {
public override byte[] Format(IInputStruct message) public override byte[] Format(IInputStruct message)
{ {
var r_message = (CreateReferenceSiemensInputStruct) message; var r_message = (CreateReferenceSiemensInputStruct)message;
const ushort head = 0x0300; const ushort head = 0x0300;
const ushort len = 0x0016; const ushort len = 0x0016;
const byte contentLen = 0x11; const byte contentLen = 0x11;
@@ -232,23 +232,23 @@ namespace Modbus.Net.Siemens
switch (messageBytes[pos]) switch (messageBytes[pos])
{ {
case 0xc0: case 0xc0:
{ {
pos += 2; pos += 2;
tdpuSize = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos); tdpuSize = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
break; break;
} }
case 0xc1: case 0xc1:
{ {
pos += 2; pos += 2;
srcTsap = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos); srcTsap = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
break; break;
} }
case 0xc2: case 0xc2:
{ {
pos += 2; pos += 2;
dstTsap = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos); dstTsap = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
break; break;
} }
} }
return new CreateReferenceSiemensOutputStruct(tdpuSize, srcTsap, dstTsap); return new CreateReferenceSiemensOutputStruct(tdpuSize, srcTsap, dstTsap);
} }
@@ -318,10 +318,10 @@ namespace Modbus.Net.Siemens
/// <returns>格式化数据</returns> /// <returns>格式化数据</returns>
public override byte[] Format(IInputStruct message) public override byte[] Format(IInputStruct message)
{ {
var r_message = (ComConfirmMessageSiemensInputStruct) message; var r_message = (ComConfirmMessageSiemensInputStruct)message;
var crc = r_message.SlaveAddress + r_message.MasterAddress + 0x5c % 256; var crc = r_message.SlaveAddress + r_message.MasterAddress + 0x5c % 256;
return Format((byte) 0x10, r_message.SlaveAddress, r_message.MasterAddress, (byte) 0x5c, (byte) crc, return Format((byte)0x10, r_message.SlaveAddress, r_message.MasterAddress, (byte)0x5c, (byte)crc,
(byte) 0x16); (byte)0x16);
} }
/// <summary> /// <summary>
@@ -378,7 +378,7 @@ namespace Modbus.Net.Siemens
{ {
public override byte[] Format(IInputStruct message) public override byte[] Format(IInputStruct message)
{ {
var r_message = (EstablishAssociationSiemensInputStruct) message; var r_message = (EstablishAssociationSiemensInputStruct)message;
const byte protoId = 0x32; const byte protoId = 0x32;
const byte rosctr = 0x01; const byte rosctr = 0x01;
const ushort redId = 0x0000; const ushort redId = 0x0000;
@@ -431,12 +431,12 @@ namespace Modbus.Net.Siemens
SlaveAddress = slaveAddress; SlaveAddress = slaveAddress;
MasterAddress = masterAddress; MasterAddress = masterAddress;
PduRef = pduRef; PduRef = pduRef;
TypeCode = (byte) getType; TypeCode = (byte)getType;
var address = addressTranslator.AddressTranslate(startAddress, true); var address = addressTranslator.AddressTranslate(startAddress, true);
Offset = address.Address; Offset = address.Address;
var area = address.Area; var area = address.Area;
Area = (byte) (area % 256); Area = (byte)(area % 256);
DbBlock = Area == 0x84 ? (ushort) (area / 256) : (ushort) 0; DbBlock = Area == 0x84 ? (ushort)(area / 256) : (ushort)0;
NumberOfElements = getCount; NumberOfElements = getCount;
} }
@@ -542,7 +542,7 @@ namespace Modbus.Net.Siemens
/// <returns>格式化数据</returns> /// <returns>格式化数据</returns>
public override byte[] Format(IInputStruct message) public override byte[] Format(IInputStruct message)
{ {
var r_message = (ReadRequestSiemensInputStruct) message; var r_message = (ReadRequestSiemensInputStruct)message;
var slaveAddress = r_message.SlaveAddress; var slaveAddress = r_message.SlaveAddress;
var masterAddress = r_message.MasterAddress; var masterAddress = r_message.MasterAddress;
const byte protoId = 0x32; const byte protoId = 0x32;
@@ -562,7 +562,7 @@ namespace Modbus.Net.Siemens
var area = r_message.Area; var area = r_message.Area;
var offsetBit = r_message.Offset * 8; var offsetBit = r_message.Offset * 8;
var offsetBitBytes = BigEndianValueHelper.Instance.GetBytes(offsetBit); var offsetBitBytes = BigEndianValueHelper.Instance.GetBytes(offsetBit);
return Format(new byte[4], slaveAddress, masterAddress, (byte) 0x6c, protoId, rosctr, redId, pduRef, parLg, return Format(new byte[4], slaveAddress, masterAddress, (byte)0x6c, protoId, rosctr, redId, pduRef, parLg,
datLg, serviceId, numberOfVariables datLg, serviceId, numberOfVariables
, variableSpec, vAddrLg, syntaxId, type, numberOfElements, dbBlock, area, , variableSpec, vAddrLg, syntaxId, type, numberOfElements, dbBlock, area,
offsetBitBytes.Skip(1).ToArray()); offsetBitBytes.Skip(1).ToArray());
@@ -585,8 +585,8 @@ namespace Modbus.Net.Siemens
var byteLength = length / 8; var byteLength = length / 8;
var values = new byte[byteLength]; var values = new byte[byteLength];
Array.Copy(messageBytes, pos, values, 0, byteLength); Array.Copy(messageBytes, pos, values, 0, byteLength);
return new ReadRequestSiemensOutputStruct(pduRef, (SiemensAccessResult) accessResult, return new ReadRequestSiemensOutputStruct(pduRef, (SiemensAccessResult)accessResult,
(SiemensDataType) dataType, length, values); (SiemensDataType)dataType, length, values);
} }
} }
@@ -617,8 +617,8 @@ namespace Modbus.Net.Siemens
var address = addressTranslator.AddressTranslate(startAddress, true); var address = addressTranslator.AddressTranslate(startAddress, true);
Offset = address.Address; Offset = address.Address;
var area = address.Area; var area = address.Area;
Area = (byte) (area % 256); Area = (byte)(area % 256);
DbBlock = Area == 0x84 ? (ushort) (area / 256) : (ushort) 0; DbBlock = Area == 0x84 ? (ushort)(area / 256) : (ushort)0;
WriteValue = writeValue; WriteValue = writeValue;
} }
@@ -697,7 +697,7 @@ namespace Modbus.Net.Siemens
/// <returns>格式化数据</returns> /// <returns>格式化数据</returns>
public override byte[] Format(IInputStruct message) public override byte[] Format(IInputStruct message)
{ {
var r_message = (WriteRequestSiemensInputStruct) message; var r_message = (WriteRequestSiemensInputStruct)message;
var valueBytes = BigEndianValueHelper.Instance.ObjectArrayToByteArray(r_message.WriteValue); var valueBytes = BigEndianValueHelper.Instance.ObjectArrayToByteArray(r_message.WriteValue);
var slaveAddress = r_message.SlaveAddress; var slaveAddress = r_message.SlaveAddress;
var masterAddress = r_message.MasterAddress; var masterAddress = r_message.MasterAddress;
@@ -706,22 +706,22 @@ namespace Modbus.Net.Siemens
const ushort redId = 0x0000; const ushort redId = 0x0000;
var pduRef = r_message.PduRef; var pduRef = r_message.PduRef;
const ushort parLg = 14; // 参数字节数2+12的倍数目前仅为14 const ushort parLg = 14; // 参数字节数2+12的倍数目前仅为14
var datLg = (ushort) (4 + valueBytes.Length); // 数据字节数 var datLg = (ushort)(4 + valueBytes.Length); // 数据字节数
const byte serviceId = 0x05; const byte serviceId = 0x05;
const byte numberOfVariables = 1; const byte numberOfVariables = 1;
const byte variableSpec = 0x12; const byte variableSpec = 0x12;
const byte vAddrLg = 0x0A; const byte vAddrLg = 0x0A;
const byte syntaxId = 0x10; const byte syntaxId = 0x10;
const byte typeR = (byte) SiemensTypeCode.Byte; const byte typeR = (byte)SiemensTypeCode.Byte;
var numberOfElements = (ushort) valueBytes.Length; var numberOfElements = (ushort)valueBytes.Length;
var dbBlock = r_message.DbBlock; var dbBlock = r_message.DbBlock;
var area = r_message.Area; var area = r_message.Area;
var offsetBit = r_message.Offset * 8; var offsetBit = r_message.Offset * 8;
var offsetBitBytes = BigEndianValueHelper.Instance.GetBytes(offsetBit); var offsetBitBytes = BigEndianValueHelper.Instance.GetBytes(offsetBit);
const byte reserved = 0x00; const byte reserved = 0x00;
const byte type = (byte) SiemensDataType.OtherAccess; const byte type = (byte)SiemensDataType.OtherAccess;
var numberOfWriteBits = (ushort) (valueBytes.Length * 8); var numberOfWriteBits = (ushort)(valueBytes.Length * 8);
return Format(new byte[4], slaveAddress, masterAddress, (byte) 0x7c, protoId, rosctr, redId, pduRef, parLg, return Format(new byte[4], slaveAddress, masterAddress, (byte)0x7c, protoId, rosctr, redId, pduRef, parLg,
datLg, serviceId, numberOfVariables datLg, serviceId, numberOfVariables
, variableSpec, vAddrLg, syntaxId, typeR, numberOfElements, dbBlock, area, , variableSpec, vAddrLg, syntaxId, typeR, numberOfElements, dbBlock, area,
offsetBitBytes.Skip(1).ToArray(), reserved, type, numberOfWriteBits, valueBytes); offsetBitBytes.Skip(1).ToArray(), reserved, type, numberOfWriteBits, valueBytes);
@@ -747,7 +747,7 @@ namespace Modbus.Net.Siemens
var pduRef = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos); var pduRef = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
pos = 14; pos = 14;
var accessResult = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos); var accessResult = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
return new WriteRequestSiemensOutputStruct(pduRef, (SiemensAccessResult) accessResult); return new WriteRequestSiemensOutputStruct(pduRef, (SiemensAccessResult)accessResult);
} }
} }
} }

View File

@@ -14,8 +14,8 @@ namespace Modbus.Net.Siemens
/// <returns>扩展后的协议内容</returns> /// <returns>扩展后的协议内容</returns>
public byte[] BytesExtend(byte[] content) public byte[] BytesExtend(byte[] content)
{ {
Array.Copy(new byte[] {0x03, 0x00, 0x00, 0x00, 0x02, 0xf0, 0x80}, 0, content, 0, 7); Array.Copy(new byte[] { 0x03, 0x00, 0x00, 0x00, 0x02, 0xf0, 0x80 }, 0, content, 0, 7);
Array.Copy(BigEndianValueHelper.Instance.GetBytes((ushort) content.Length), 0, content, 2, 2); Array.Copy(BigEndianValueHelper.Instance.GetBytes((ushort)content.Length), 0, content, 2, 2);
return content; return content;
} }
@@ -46,13 +46,13 @@ namespace Modbus.Net.Siemens
{ {
var newContent = new byte[content.Length + 2]; var newContent = new byte[content.Length + 2];
Array.Copy(content, 0, newContent, 0, content.Length); Array.Copy(content, 0, newContent, 0, content.Length);
Array.Copy(new byte[] {0x68, (byte) (content.Length - 4), (byte) (content.Length - 4), 0x68}, 0, newContent, Array.Copy(new byte[] { 0x68, (byte)(content.Length - 4), (byte)(content.Length - 4), 0x68 }, 0, newContent,
0, 4); 0, 4);
var check = 0; var check = 0;
for (var i = 4; i < newContent.Length - 2; i++) for (var i = 4; i < newContent.Length - 2; i++)
check += newContent[i]; check += newContent[i];
check = check % 256; check = check % 256;
newContent[newContent.Length - 2] = (byte) check; newContent[newContent.Length - 2] = (byte)check;
newContent[newContent.Length - 1] = 0x16; newContent[newContent.Length - 1] = 0x16;
return newContent; return newContent;
} }

View File

@@ -1,6 +1,6 @@
using System.Threading.Tasks; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration;
using Nito.AsyncEx; using Nito.AsyncEx;
using System.Threading.Tasks;
namespace Modbus.Net.Siemens namespace Modbus.Net.Siemens
{ {

View File

@@ -26,7 +26,7 @@ namespace Modbus.Net.Siemens
public SiemensTcpProtocolLinker(string ip, int port) public SiemensTcpProtocolLinker(string ip, int port)
: base(ip, port) : base(ip, port)
{ {
((BaseConnector)BaseConnector).AddController(new MatchDirectlySendController(new ICollection<(int,int)>[] { new List<(int,int)> { (11,11), (12,12) } }, DuplicateWithCount.GetDuplcateFunc(new List<int>{2, 3}, 0), 100)); ((BaseConnector)BaseConnector).AddController(new MatchDirectlySendController(new ICollection<(int, int)>[] { new List<(int, int)> { (11, 11), (12, 12) } }, DuplicateWithCount.GetDuplcateFunc(new List<int> { 2, 3 }, 0), 100));
} }
/// <summary> /// <summary>

View File

@@ -1,6 +1,6 @@
using System; using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Serilog;
namespace Modbus.Net.Siemens namespace Modbus.Net.Siemens
{ {
@@ -59,6 +59,8 @@ namespace Modbus.Net.Siemens
/// </summary> /// </summary>
public class SiemensUtility : BaseUtility public class SiemensUtility : BaseUtility
{ {
private static readonly ILogger<SiemensUtility> logger = LogProvider.CreateLogger<SiemensUtility>();
private readonly ushort _maxCalled; private readonly ushort _maxCalled;
private readonly ushort _maxCalling; private readonly ushort _maxCalling;
private readonly ushort _maxPdu; private readonly ushort _maxPdu;
@@ -89,51 +91,51 @@ namespace Modbus.Net.Siemens
switch (model) switch (model)
{ {
case SiemensMachineModel.S7_200: case SiemensMachineModel.S7_200:
{ {
_tdpuSize = 0x09; _tdpuSize = 0x09;
_taspSrc = (ushort)(0x1000 + src); _taspSrc = (ushort)(0x1000 + src);
_tsapDst = (ushort)(0x1000 + dst); _tsapDst = (ushort)(0x1000 + dst);
_maxCalling = 0x0001; _maxCalling = 0x0001;
_maxCalled = 0x0001; _maxCalled = 0x0001;
_maxPdu = 0x03c0; _maxPdu = 0x03c0;
break; break;
} }
case SiemensMachineModel.S7_300: case SiemensMachineModel.S7_300:
case SiemensMachineModel.S7_400: case SiemensMachineModel.S7_400:
{ {
_tdpuSize = 0x1a; _tdpuSize = 0x1a;
_taspSrc = 0x4b54; _taspSrc = 0x4b54;
_tsapDst = (ushort)(0x0300 + dst); _tsapDst = (ushort)(0x0300 + dst);
_maxCalling = 0x0001; _maxCalling = 0x0001;
_maxCalled = 0x0001; _maxCalled = 0x0001;
_maxPdu = 0x00f0; _maxPdu = 0x00f0;
break; break;
} }
case SiemensMachineModel.S7_1200: case SiemensMachineModel.S7_1200:
case SiemensMachineModel.S7_1500: case SiemensMachineModel.S7_1500:
{ {
_tdpuSize = 0x0a; _tdpuSize = 0x0a;
_taspSrc = 0x1011; _taspSrc = 0x1011;
_tsapDst = (ushort)(0x0300 + dst); _tsapDst = (ushort)(0x0300 + dst);
_maxCalling = 0x0003; _maxCalling = 0x0003;
_maxCalled = 0x0003; _maxCalled = 0x0003;
_maxPdu = 0x0100; _maxPdu = 0x0100;
break; break;
} }
case SiemensMachineModel.S7_200_Smart: case SiemensMachineModel.S7_200_Smart:
{ {
_tdpuSize = 0x0a; _tdpuSize = 0x0a;
_taspSrc = 0x0101; _taspSrc = 0x0101;
_tsapDst = 0x0101; _tsapDst = 0x0101;
_maxCalling = 0x0001; _maxCalling = 0x0001;
_maxCalled = 0x0001; _maxCalled = 0x0001;
_maxPdu = 0x03c0; _maxPdu = 0x03c0;
break; break;
} }
default: default:
{ {
throw new NotImplementedException("Siemens PLC Model not Supported"); throw new NotImplementedException("Siemens PLC Model not Supported");
} }
} }
ConnectionType = connectionType; ConnectionType = connectionType;
AddressTranslator = new AddressTranslatorSiemens(); AddressTranslator = new AddressTranslatorSiemens();
@@ -169,11 +171,11 @@ namespace Modbus.Net.Siemens
var connectionStringSplit = ConnectionString.Split(':'); var connectionStringSplit = ConnectionString.Split(':');
try try
{ {
return connectionStringSplit.Length < 2 ? (int?) null : int.Parse(connectionStringSplit[1]); return connectionStringSplit.Length < 2 ? (int?)null : int.Parse(connectionStringSplit[1]);
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, $"SiemensUtility: {ConnectionString} format error"); logger.LogError(e, $"SiemensUtility: {ConnectionString} format error");
return null; return null;
} }
} }
@@ -192,29 +194,29 @@ namespace Modbus.Net.Siemens
{ {
//PPI //PPI
case SiemensType.Ppi: case SiemensType.Ppi:
{ {
Wrapper = ConnectionString == null Wrapper = ConnectionString == null
? new SiemensPpiProtocol(SlaveAddress, MasterAddress) ? new SiemensPpiProtocol(SlaveAddress, MasterAddress)
: new SiemensPpiProtocol(ConnectionString, SlaveAddress, MasterAddress); : new SiemensPpiProtocol(ConnectionString, SlaveAddress, MasterAddress);
break; break;
} }
//MPI //MPI
case SiemensType.Mpi: case SiemensType.Mpi:
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
//Ethenet //Ethenet
case SiemensType.Tcp: case SiemensType.Tcp:
{ {
Wrapper = ConnectionString == null Wrapper = ConnectionString == null
? new SiemensTcpProtocol(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu) ? new SiemensTcpProtocol(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu)
: (ConnectionStringPort == null : (ConnectionStringPort == null
? new SiemensTcpProtocol(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu, ? new SiemensTcpProtocol(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu,
ConnectionString) ConnectionString)
: new SiemensTcpProtocol(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu, : new SiemensTcpProtocol(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu,
ConnectionStringIp, ConnectionStringPort.Value)); ConnectionStringIp, ConnectionStringPort.Value));
break; break;
} }
} }
} }
} }
@@ -225,7 +227,7 @@ namespace Modbus.Net.Siemens
/// <param name="connectionType">需要设置的连接类型</param> /// <param name="connectionType">需要设置的连接类型</param>
public override void SetConnectionType(int connectionType) public override void SetConnectionType(int connectionType)
{ {
ConnectionType = (SiemensType) connectionType; ConnectionType = (SiemensType)connectionType;
} }
/// <summary> /// <summary>
@@ -244,7 +246,7 @@ namespace Modbus.Net.Siemens
_sendCount = (ushort)(_sendCount % ushort.MaxValue + 1); _sendCount = (ushort)(_sendCount % ushort.MaxValue + 1);
readRequestSiemensInputStruct = new ReadRequestSiemensInputStruct(SlaveAddress, MasterAddress, readRequestSiemensInputStruct = new ReadRequestSiemensInputStruct(SlaveAddress, MasterAddress,
_sendCount, SiemensTypeCode.Byte, startAddress, (ushort)getByteCount, AddressTranslator); _sendCount, SiemensTypeCode.Byte, startAddress, (ushort)getByteCount, AddressTranslator);
} }
var readRequestSiemensOutputStruct = var readRequestSiemensOutputStruct =
await await
Wrapper.SendReceiveAsync<ReadRequestSiemensOutputStruct>( Wrapper.SendReceiveAsync<ReadRequestSiemensOutputStruct>(
@@ -254,7 +256,7 @@ namespace Modbus.Net.Siemens
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, $"SiemensUtility -> GetDatas: {ConnectionString} error"); logger.LogError(e, $"SiemensUtility -> GetDatas: {ConnectionString} error");
return null; return null;
} }
} }
@@ -275,7 +277,7 @@ namespace Modbus.Net.Siemens
_sendCount = (ushort)(_sendCount % ushort.MaxValue + 1); _sendCount = (ushort)(_sendCount % ushort.MaxValue + 1);
writeRequestSiemensInputStruct = new WriteRequestSiemensInputStruct(SlaveAddress, MasterAddress, writeRequestSiemensInputStruct = new WriteRequestSiemensInputStruct(SlaveAddress, MasterAddress,
_sendCount, startAddress, setContents, AddressTranslator); _sendCount, startAddress, setContents, AddressTranslator);
} }
var writeRequestSiemensOutputStruct = var writeRequestSiemensOutputStruct =
await await
Wrapper.SendReceiveAsync<WriteRequestSiemensOutputStruct>( Wrapper.SendReceiveAsync<WriteRequestSiemensOutputStruct>(
@@ -285,7 +287,7 @@ namespace Modbus.Net.Siemens
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility -> SetDatas: {ConnectionString} error"); logger.LogError(e, $"ModbusUtility -> SetDatas: {ConnectionString} error");
return false; return false;
} }
} }

View File

@@ -1,18 +1,20 @@
using System; using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
using Nito.AsyncEx; using Nito.AsyncEx;
using Serilog; using System;
using System.Threading.Tasks;
namespace Modbus.Net namespace Modbus.Net
{ {
/// <inheritdoc /> /// <inheritdoc />
public abstract class BaseConnector : BaseConnector<byte[], byte[]> public abstract class BaseConnector : BaseConnector<byte[], byte[]>
{ {
private static readonly ILogger<BaseConnector> logger = LogProvider.CreateLogger<BaseConnector>();
/// <summary> /// <summary>
/// 发送锁 /// 发送锁
/// </summary> /// </summary>
protected abstract AsyncLock Lock { get; } protected abstract AsyncLock Lock { get; }
/// <summary> /// <summary>
/// 是否为全双工 /// 是否为全双工
/// </summary> /// </summary>
@@ -51,7 +53,7 @@ namespace Modbus.Net
{ {
IDisposable asyncLock = null; IDisposable asyncLock = null;
try try
{ {
var messageSendingdef = Controller.AddMessage(message); var messageSendingdef = Controller.AddMessage(message);
if (messageSendingdef != null) if (messageSendingdef != null)
{ {
@@ -71,12 +73,12 @@ namespace Modbus.Net
} }
Controller.ForceRemoveWaitingMessage(messageSendingdef); Controller.ForceRemoveWaitingMessage(messageSendingdef);
} }
Log.Information("Message is waiting in {0}. Cancel!", ConnectionToken); logger.LogInformation("Message is waiting in {0}. Cancel!", ConnectionToken);
return null; return null;
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Connector {0} Send Error.", ConnectionToken); logger.LogError(e, "Connector {0} Send Error.", ConnectionToken);
return null; return null;
} }
finally finally
@@ -149,14 +151,14 @@ namespace Modbus.Net
/// </summary> /// </summary>
protected abstract void ReceiveMsgThreadStop(); protected abstract void ReceiveMsgThreadStop();
/// <summary> /// <summary>
/// 数据返回代理函数 /// 数据返回代理函数
/// </summary> /// </summary>
/// <param name="receiveMessage"></param> /// <param name="receiveMessage"></param>
/// <returns></returns> /// <returns></returns>
protected TParamIn InvokeReturnMessage(TParamOut receiveMessage) protected TParamIn InvokeReturnMessage(TParamOut receiveMessage)
{ {
return MessageReturn?.Invoke(this, new MessageReturnArgs<TParamOut>{ReturnMessage = receiveMessage})?.SendMessage; return MessageReturn?.Invoke(this, new MessageReturnArgs<TParamOut> { ReturnMessage = receiveMessage })?.SendMessage;
} }
} }
} }

View File

@@ -1,11 +1,11 @@
using System; using Microsoft.Extensions.Logging;
using Nito.AsyncEx;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO.Ports; using System.IO.Ports;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Nito.AsyncEx;
using Serilog;
namespace Modbus.Net namespace Modbus.Net
{ {
@@ -25,6 +25,8 @@ namespace Modbus.Net
/// </summary> /// </summary>
public class ComConnector : BaseConnector, IDisposable public class ComConnector : BaseConnector, IDisposable
{ {
private static readonly ILogger<ComConnector> logger = LogProvider.CreateLogger<ComConnector>();
/// <summary> /// <summary>
/// 波特率 /// 波特率
/// </summary> /// </summary>
@@ -124,7 +126,8 @@ namespace Modbus.Net
; ;
/// <inheritdoc /> /// <inheritdoc />
protected override IController Controller { protected override IController Controller
{
get get
{ {
if (Controllers.ContainsKey(_com)) if (Controllers.ContainsKey(_com))
@@ -139,7 +142,7 @@ namespace Modbus.Net
{ {
Controllers.Add(_com, value); Controllers.Add(_com, value);
} }
} }
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -198,7 +201,7 @@ namespace Modbus.Net
while (SerialPort.BytesToRead > 0) while (SerialPort.BytesToRead > 0)
{ {
readBuf[nBytelen] = (byte) SerialPort.ReadByte(); readBuf[nBytelen] = (byte)SerialPort.ReadByte();
var bTmp = new byte[bufRoom]; var bTmp = new byte[bufRoom];
Array.Clear(bTmp, 0, bTmp.Length); Array.Clear(bTmp, 0, bTmp.Length);
@@ -235,7 +238,7 @@ namespace Modbus.Net
while (nBytelen < readRoom - 1 && SerialPort.BytesToRead > 0) while (nBytelen < readRoom - 1 && SerialPort.BytesToRead > 0)
{ {
readBuf[nBytelen] = (byte) SerialPort.ReadByte(); readBuf[nBytelen] = (byte)SerialPort.ReadByte();
nBytelen++; // add one nBytelen++; // add one
} }
readBuf[nBytelen] = 0x00; readBuf[nBytelen] = 0x00;
@@ -265,14 +268,14 @@ namespace Modbus.Net
SerialPort.Close(); SerialPort.Close();
} }
SerialPort.Dispose(); SerialPort.Dispose();
Log.Information("Com interface {Com} Disposed", _com); logger.LogInformation("Com interface {Com} Disposed", _com);
Connectors[_com] = null; Connectors[_com] = null;
Connectors.Remove(_com); Connectors.Remove(_com);
ReceiveMsgThreadStop(); ReceiveMsgThreadStop();
} }
Linkers.Remove(_slave); Linkers.Remove(_slave);
Log.Information("Com connector {ConnectionToken} Removed", ConnectionToken); logger.LogInformation("Com connector {ConnectionToken} Removed", ConnectionToken);
} }
m_disposed = true; m_disposed = true;
} }
} }
@@ -289,19 +292,19 @@ namespace Modbus.Net
private void RefreshSendCount() private void RefreshSendCount()
{ {
_sendCount++; _sendCount++;
Log.Verbose("Com client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount); logger.LogDebug("Com client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount);
} }
private void RefreshReceiveCount() private void RefreshReceiveCount()
{ {
_receiveCount++; _receiveCount++;
Log.Verbose("Com client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount); logger.LogDebug("Com client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount);
} }
private void RefreshErrorCount() private void RefreshErrorCount()
{ {
_errorCount++; _errorCount++;
Log.Verbose("Com client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount); logger.LogDebug("Com client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount);
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -352,14 +355,14 @@ namespace Modbus.Net
} }
} }
} }
Log.Information("Com client {ConnectionToken} connect success", ConnectionToken); logger.LogInformation("Com client {ConnectionToken} connect success", ConnectionToken);
return true; return true;
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Com client {ConnectionToken} connect error", ConnectionToken); logger.LogError(e, "Com client {ConnectionToken} connect error", ConnectionToken);
Dispose(); Dispose();
return false; return false;
} }
@@ -378,15 +381,15 @@ namespace Modbus.Net
try try
{ {
Dispose(); Dispose();
Log.Information("Com client {ConnectionToken} disconnect success", ConnectionToken); logger.LogInformation("Com client {ConnectionToken} disconnect success", ConnectionToken);
return true; return true;
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Com client {ConnectionToken} disconnect error", ConnectionToken); logger.LogError(e, "Com client {ConnectionToken} disconnect error", ConnectionToken);
return false; return false;
} }
Log.Error(new Exception("Linkers or Connectors Dictionary not found"), logger.LogError(new Exception("Linkers or Connectors Dictionary not found"),
"Com client {ConnectionToken} disconnect error", ConnectionToken); "Com client {ConnectionToken} disconnect error", ConnectionToken);
return false; return false;
} }
@@ -420,7 +423,7 @@ namespace Modbus.Net
} }
catch (Exception err) catch (Exception err)
{ {
Log.Error(err, "Com client {ConnectionToken} open error", ConnectionToken); logger.LogError(err, "Com client {ConnectionToken} open error", ConnectionToken);
Dispose(); Dispose();
try try
{ {
@@ -428,7 +431,7 @@ namespace Modbus.Net
} }
catch (Exception err2) catch (Exception err2)
{ {
Log.Error(err2, "Com client {ConnectionToken} open error", ConnectionToken); logger.LogError(err2, "Com client {ConnectionToken} open error", ConnectionToken);
Dispose(); Dispose();
} }
} }
@@ -447,15 +450,15 @@ namespace Modbus.Net
{ {
try try
{ {
Log.Verbose("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken, logger.LogDebug("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken,
message.Length); message.Length);
Log.Verbose( logger.LogDebug(
$"Com client {ConnectionToken} send msg: {String.Concat(message.Select(p => " " + p.ToString("X2")))}"); $"Com client {ConnectionToken} send msg: {String.Concat(message.Select(p => " " + p.ToString("X2")))}");
await Task.Run(() => SerialPort.Write(message, 0, message.Length)); await Task.Run(() => SerialPort.Write(message, 0, message.Length));
} }
catch (Exception err) catch (Exception err)
{ {
Log.Error(err, "Com client {ConnectionToken} send msg error", ConnectionToken); logger.LogError(err, "Com client {ConnectionToken} send msg error", ConnectionToken);
Dispose(); Dispose();
} }
RefreshSendCount(); RefreshSendCount();
@@ -464,7 +467,7 @@ namespace Modbus.Net
/// <inheritdoc /> /// <inheritdoc />
protected override void ReceiveMsgThreadStart() protected override void ReceiveMsgThreadStart()
{ {
_receiveThread = Task.Run(()=>ReceiveMessage()); _receiveThread = Task.Run(() => ReceiveMessage());
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -483,9 +486,9 @@ namespace Modbus.Net
var returnBytes = ReadMsg(); var returnBytes = ReadMsg();
if (returnBytes != null) if (returnBytes != null)
{ {
Log.Verbose("Com client {ConnectionToken} receive msg length: {Length}", ConnectionToken, logger.LogDebug("Com client {ConnectionToken} receive msg length: {Length}", ConnectionToken,
returnBytes.Length); returnBytes.Length);
Log.Verbose( logger.LogDebug(
$"Com client {ConnectionToken} receive msg: {String.Concat(returnBytes.Select(p => " " + p.ToString("X2")))}"); $"Com client {ConnectionToken} receive msg: {String.Concat(returnBytes.Select(p => " " + p.ToString("X2")))}");
var isMessageConfirmed = Controller.ConfirmMessage(returnBytes); var isMessageConfirmed = Controller.ConfirmMessage(returnBytes);
@@ -498,11 +501,11 @@ namespace Modbus.Net
} }
RefreshReceiveCount(); RefreshReceiveCount();
} }
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Com client {ConnectionToken} read msg error", ConnectionToken); logger.LogError(e, "Com client {ConnectionToken} read msg error", ConnectionToken);
} }
} }
} }
@@ -524,7 +527,7 @@ namespace Modbus.Net
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Com client {ConnectionToken} read error", ConnectionToken); logger.LogError(e, "Com client {ConnectionToken} read error", ConnectionToken);
RefreshErrorCount(); RefreshErrorCount();
Dispose(); Dispose();
return null; return null;

View File

@@ -1,5 +1,5 @@
namespace Modbus.Net namespace Modbus.Net
{ {
/// <summary> /// <summary>
/// 数据返回代理参数 /// 数据返回代理参数
/// </summary> /// </summary>
@@ -12,7 +12,7 @@
public TParamOut ReturnMessage { get; set; } public TParamOut ReturnMessage { get; set; }
} }
/// <summary> /// <summary>
/// 数据发送代理参数 /// 数据发送代理参数
/// </summary> /// </summary>

View File

@@ -1,10 +1,10 @@
using System; using Microsoft.Extensions.Logging;
using Nito.AsyncEx;
using System;
using System.Linq; using System.Linq;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Nito.AsyncEx;
using Serilog;
namespace Modbus.Net namespace Modbus.Net
{ {
@@ -14,6 +14,8 @@ namespace Modbus.Net
/// </summary> /// </summary>
public class TcpConnector : BaseConnector, IDisposable public class TcpConnector : BaseConnector, IDisposable
{ {
private static readonly ILogger<TcpConnector> logger = LogProvider.CreateLogger<TcpConnector>();
private readonly string _host; private readonly string _host;
private readonly int _port; private readonly int _port;
@@ -53,7 +55,7 @@ namespace Modbus.Net
/// <inheritdoc /> /// <inheritdoc />
protected override int TimeoutTime protected override int TimeoutTime
{ {
get => get =>
_timeoutTime; _timeoutTime;
set set
{ {
@@ -94,7 +96,7 @@ namespace Modbus.Net
{ {
CloseClientSocket(); CloseClientSocket();
_socketClient = null; _socketClient = null;
Log.Debug("Tcp client {ConnectionToken} Disposed", ConnectionToken); logger.LogDebug("Tcp client {ConnectionToken} Disposed", ConnectionToken);
} }
} }
@@ -134,16 +136,16 @@ namespace Modbus.Net
_taskCancel = false; _taskCancel = false;
Controller.SendStart(); Controller.SendStart();
ReceiveMsgThreadStart(); ReceiveMsgThreadStart();
Log.Information("Tcp client {ConnectionToken} connected", ConnectionToken); logger.LogInformation("Tcp client {ConnectionToken} connected", ConnectionToken);
return true; return true;
} }
Log.Error("Tcp client {ConnectionToken} connect failed.", ConnectionToken); logger.LogError("Tcp client {ConnectionToken} connect failed.", ConnectionToken);
Dispose(); Dispose();
return false; return false;
} }
catch (Exception err) catch (Exception err)
{ {
Log.Error(err, "Tcp client {ConnectionToken} connect exception", ConnectionToken); logger.LogError(err, "Tcp client {ConnectionToken} connect exception", ConnectionToken);
Dispose(); Dispose();
return false; return false;
} }
@@ -159,12 +161,12 @@ namespace Modbus.Net
try try
{ {
Dispose(); Dispose();
Log.Information("Tcp client {ConnectionToken} disconnected successfully", ConnectionToken); logger.LogInformation("Tcp client {ConnectionToken} disconnected successfully", ConnectionToken);
return true; return true;
} }
catch (Exception err) catch (Exception err)
{ {
Log.Error(err, "Tcp client {ConnectionToken} disconnected exception", ConnectionToken); logger.LogError(err, "Tcp client {ConnectionToken} disconnected exception", ConnectionToken);
return false; return false;
} }
finally finally
@@ -187,13 +189,13 @@ namespace Modbus.Net
RefreshSendCount(); RefreshSendCount();
Log.Verbose("Tcp client {ConnectionToken} send text len = {Length}", ConnectionToken, datagram.Length); logger.LogDebug("Tcp client {ConnectionToken} send text len = {Length}", ConnectionToken, datagram.Length);
Log.Verbose($"Tcp client {ConnectionToken} send: {String.Concat(datagram.Select(p => " " + p.ToString("X2")))}"); logger.LogDebug($"Tcp client {ConnectionToken} send: {String.Concat(datagram.Select(p => " " + p.ToString("X2")))}");
await stream.WriteAsync(datagram, 0, datagram.Length); await stream.WriteAsync(datagram, 0, datagram.Length);
} }
catch (Exception err) catch (Exception err)
{ {
Log.Error(err, "Tcp client {ConnectionToken} send exception", ConnectionToken); logger.LogError(err, "Tcp client {ConnectionToken} send exception", ConnectionToken);
Dispose(); Dispose();
} }
} }
@@ -229,9 +231,9 @@ namespace Modbus.Net
if (len > 0) if (len > 0)
{ {
byte[] receiveBytes = CheckReplyDatagram(len); byte[] receiveBytes = CheckReplyDatagram(len);
Log.Verbose("Tcp client {ConnectionToken} receive text len = {Length}", ConnectionToken, logger.LogDebug("Tcp client {ConnectionToken} receive text len = {Length}", ConnectionToken,
receiveBytes.Length); receiveBytes.Length);
Log.Verbose( logger.LogDebug(
$"Tcp client {ConnectionToken} receive: {String.Concat(receiveBytes.Select(p => " " + p.ToString("X2")))}"); $"Tcp client {ConnectionToken} receive: {String.Concat(receiveBytes.Select(p => " " + p.ToString("X2")))}");
var isMessageConfirmed = Controller.ConfirmMessage(receiveBytes); var isMessageConfirmed = Controller.ConfirmMessage(receiveBytes);
foreach (var confirmed in isMessageConfirmed) foreach (var confirmed in isMessageConfirmed)
@@ -246,7 +248,7 @@ namespace Modbus.Net
} }
} }
} }
RefreshReceiveCount(); RefreshReceiveCount();
} }
} }
@@ -257,7 +259,7 @@ namespace Modbus.Net
} }
catch (Exception err) catch (Exception err)
{ {
Log.Error(err, "Tcp client {ConnectionToken} receive exception", ConnectionToken); logger.LogError(err, "Tcp client {ConnectionToken} receive exception", ConnectionToken);
//CloseClientSocket(); //CloseClientSocket();
} }
} }
@@ -280,19 +282,19 @@ namespace Modbus.Net
private void RefreshSendCount() private void RefreshSendCount()
{ {
_sendCount++; _sendCount++;
Log.Verbose("Tcp client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount); logger.LogDebug("Tcp client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount);
} }
private void RefreshReceiveCount() private void RefreshReceiveCount()
{ {
_receiveCount++; _receiveCount++;
Log.Verbose("Tcp client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount); logger.LogDebug("Tcp client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount);
} }
private void RefreshErrorCount() private void RefreshErrorCount()
{ {
_errorCount++; _errorCount++;
Log.Verbose("Tcp client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount); logger.LogDebug("Tcp client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount);
} }
private void CloseClientSocket() private void CloseClientSocket()
@@ -307,12 +309,12 @@ namespace Modbus.Net
if (_socketClient.Connected) if (_socketClient.Connected)
{ {
_socketClient.Close(); _socketClient.Close();
} }
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.Error(ex, "Tcp client {ConnectionToken} client close exception", ConnectionToken); logger.LogError(ex, "Tcp client {ConnectionToken} client close exception", ConnectionToken);
} }
} }
} }

View File

@@ -1,10 +1,10 @@
using System; using Microsoft.Extensions.Logging;
using Nito.AsyncEx;
using System;
using System.Linq; using System.Linq;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Nito.AsyncEx;
using Serilog;
namespace Modbus.Net namespace Modbus.Net
{ {
@@ -13,6 +13,8 @@ namespace Modbus.Net
/// </summary> /// </summary>
public class UdpConnector : BaseConnector, IDisposable public class UdpConnector : BaseConnector, IDisposable
{ {
private static readonly ILogger<UdpConnector> logger = LogProvider.CreateLogger<UdpConnector>();
private readonly string _host; private readonly string _host;
private readonly int _port; private readonly int _port;
@@ -81,7 +83,7 @@ namespace Modbus.Net
{ {
CloseClientSocket(); CloseClientSocket();
_socketClient = null; _socketClient = null;
Log.Debug("Udp client {ConnectionToken} Disposed", ConnectionToken); logger.LogDebug("Udp client {ConnectionToken} Disposed", ConnectionToken);
} }
} }
@@ -101,7 +103,7 @@ namespace Modbus.Net
{ {
if (_socketClient != null) if (_socketClient != null)
{ {
return true; return true;
} }
try try
{ {
@@ -116,17 +118,17 @@ namespace Modbus.Net
_taskCancel = false; _taskCancel = false;
Controller.SendStart(); Controller.SendStart();
ReceiveMsgThreadStart(); ReceiveMsgThreadStart();
Log.Information("Udp client {ConnectionToken} connected", ConnectionToken); logger.LogInformation("Udp client {ConnectionToken} connected", ConnectionToken);
return true; return true;
} }
Log.Error("Udp client {ConnectionToken} connect failed.", ConnectionToken); logger.LogError("Udp client {ConnectionToken} connect failed.", ConnectionToken);
Dispose(); Dispose();
return false; return false;
} }
catch (Exception err) catch (Exception err)
{ {
Log.Error(err, "Udp client {ConnectionToken} connect exception", ConnectionToken); logger.LogError(err, "Udp client {ConnectionToken} connect exception", ConnectionToken);
Dispose(); Dispose();
return false; return false;
} }
@@ -142,12 +144,12 @@ namespace Modbus.Net
try try
{ {
Dispose(); Dispose();
Log.Information("Udp client {ConnectionToken} disconnected successfully", ConnectionToken); logger.LogInformation("Udp client {ConnectionToken} disconnected successfully", ConnectionToken);
return true; return true;
} }
catch (Exception err) catch (Exception err)
{ {
Log.Error(err, "Udp client {ConnectionToken} disconnected exception", ConnectionToken); logger.LogError(err, "Udp client {ConnectionToken} disconnected exception", ConnectionToken);
return false; return false;
} }
finally finally
@@ -168,13 +170,13 @@ namespace Modbus.Net
RefreshSendCount(); RefreshSendCount();
Log.Verbose("Udp client {ConnectionToken} send text len = {Length}", ConnectionToken, datagram.Length); logger.LogDebug("Udp client {ConnectionToken} send text len = {Length}", ConnectionToken, datagram.Length);
Log.Verbose($"Udp client {ConnectionToken} send: {String.Concat(datagram.Select(p => " " + p.ToString("X2")))}"); logger.LogDebug($"Udp client {ConnectionToken} send: {String.Concat(datagram.Select(p => " " + p.ToString("X2")))}");
await _socketClient.SendAsync(datagram, datagram.Length); await _socketClient.SendAsync(datagram, datagram.Length);
} }
catch (Exception err) catch (Exception err)
{ {
Log.Error(err, "Udp client {ConnectionToken} send exception", ConnectionToken); logger.LogError(err, "Udp client {ConnectionToken} send exception", ConnectionToken);
Dispose(); Dispose();
} }
} }
@@ -210,9 +212,9 @@ namespace Modbus.Net
{ {
if (receive.Buffer.Clone() is byte[] receiveBytes) if (receive.Buffer.Clone() is byte[] receiveBytes)
{ {
Log.Verbose("Udp client {ConnectionToken} receive text len = {Length}", ConnectionToken, logger.LogDebug("Udp client {ConnectionToken} receive text len = {Length}", ConnectionToken,
receiveBytes.Length); receiveBytes.Length);
Log.Verbose( logger.LogDebug(
$"Udp client {ConnectionToken} receive: {String.Concat(receiveBytes.Select(p => " " + p.ToString("X2")))}"); $"Udp client {ConnectionToken} receive: {String.Concat(receiveBytes.Select(p => " " + p.ToString("X2")))}");
var isMessageConfirmed = Controller.ConfirmMessage(receiveBytes); var isMessageConfirmed = Controller.ConfirmMessage(receiveBytes);
foreach (var confirmed in isMessageConfirmed) foreach (var confirmed in isMessageConfirmed)
@@ -239,7 +241,7 @@ namespace Modbus.Net
} }
catch (Exception err) catch (Exception err)
{ {
Log.Error(err, "Udp client {ConnectionToken} receive exception", ConnectionToken); logger.LogError(err, "Udp client {ConnectionToken} receive exception", ConnectionToken);
//CloseClientSocket(); //CloseClientSocket();
} }
} }
@@ -247,19 +249,19 @@ namespace Modbus.Net
private void RefreshSendCount() private void RefreshSendCount()
{ {
_sendCount++; _sendCount++;
Log.Verbose("Udp client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount); logger.LogDebug("Udp client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount);
} }
private void RefreshReceiveCount() private void RefreshReceiveCount()
{ {
_receiveCount++; _receiveCount++;
Log.Verbose("Udp client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount); logger.LogDebug("Udp client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount);
} }
private void RefreshErrorCount() private void RefreshErrorCount()
{ {
_errorCount++; _errorCount++;
Log.Verbose("Udp client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount); logger.LogDebug("Udp client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount);
} }
private void CloseClientSocket() private void CloseClientSocket()
@@ -280,7 +282,7 @@ namespace Modbus.Net
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.Error(ex, "Udp client {ConnectionToken} client close exception", ConnectionToken); logger.LogError(ex, "Udp client {ConnectionToken} client close exception", ConnectionToken);
} }
} }
} }

View File

@@ -10,7 +10,7 @@ namespace Modbus.Net
/// 控制器基类 /// 控制器基类
/// </summary> /// </summary>
public abstract class BaseController : IController public abstract class BaseController : IController
{ {
/// <summary> /// <summary>
/// 等待的消息队列 /// 等待的消息队列
/// </summary> /// </summary>
@@ -66,7 +66,7 @@ namespace Modbus.Net
{ {
if (SendingThread == null) if (SendingThread == null)
{ {
SendingThread = Task.Run(()=>SendingMessageControlInner()); SendingThread = Task.Run(() => SendingMessageControlInner());
} }
} }
@@ -101,14 +101,14 @@ namespace Modbus.Net
/// </summary> /// </summary>
/// <param name="message">待确认的信息</param> /// <param name="message">待确认的信息</param>
/// <returns>信息的检索关键字</returns> /// <returns>信息的检索关键字</returns>
protected abstract (string,string)? GetKeyFromMessage(byte[] message); protected abstract (string, string)? GetKeyFromMessage(byte[] message);
/// <inheritdoc /> /// <inheritdoc />
public ICollection<(byte[], bool)> ConfirmMessage(byte[] receiveMessage) public ICollection<(byte[], bool)> ConfirmMessage(byte[] receiveMessage)
{ {
var ans = new List<(byte[], bool)>(); var ans = new List<(byte[], bool)>();
var duplicatedMessages = DuplicateFunc?.Invoke(receiveMessage); var duplicatedMessages = DuplicateFunc?.Invoke(receiveMessage);
duplicatedMessages = duplicatedMessages ?? new List<byte[]> {receiveMessage}; duplicatedMessages = duplicatedMessages ?? new List<byte[]> { receiveMessage };
foreach (var message in duplicatedMessages) foreach (var message in duplicatedMessages)
{ {
var def = GetMessageFromWaitingList(message); var def = GetMessageFromWaitingList(message);
@@ -127,7 +127,7 @@ namespace Modbus.Net
return ans; return ans;
} }
/// <summary> /// <summary>
/// 从等待队列中匹配信息 /// 从等待队列中匹配信息

View File

@@ -1,8 +1,8 @@
using System; using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Serilog;
namespace Modbus.Net namespace Modbus.Net
{ {
@@ -11,6 +11,8 @@ namespace Modbus.Net
/// </summary> /// </summary>
public class FifoController : BaseController public class FifoController : BaseController
{ {
private static readonly ILogger<FifoController> logger = LogProvider.CreateLogger<FifoController>();
private MessageWaitingDef _currentSendingPos; private MessageWaitingDef _currentSendingPos;
private bool _taskCancel = false; private bool _taskCancel = false;
@@ -39,7 +41,7 @@ namespace Modbus.Net
{ {
_taskCycleSema = new Semaphore(0, _waitingListMaxCount); _taskCycleSema = new Semaphore(0, _waitingListMaxCount);
} }
AcquireTime = acquireTime; AcquireTime = acquireTime;
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -66,7 +68,7 @@ namespace Modbus.Net
sendSuccess = true; sendSuccess = true;
} }
} }
else else
{ {
if (WaitingMessages.Count <= 0) if (WaitingMessages.Count <= 0)
{ {
@@ -83,7 +85,7 @@ namespace Modbus.Net
} }
} }
if (sendSuccess) if (sendSuccess)
{ {
_taskCycleSema?.WaitOne(); _taskCycleSema?.WaitOne();
} }
} }
@@ -94,7 +96,7 @@ namespace Modbus.Net
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Controller throws exception"); logger.LogError(e, "Controller throws exception");
} }
} }
@@ -113,7 +115,7 @@ namespace Modbus.Net
} }
/// <inheritdoc /> /// <inheritdoc />
protected override (string,string)? GetKeyFromMessage(byte[] message) protected override (string, string)? GetKeyFromMessage(byte[] message)
{ {
return null; return null;
} }

View File

@@ -12,7 +12,7 @@ namespace Modbus.Net
/// <summary> /// <summary>
/// 匹配字典 /// 匹配字典
/// </summary> /// </summary>
protected ICollection<(int,int)>[] KeyMatches { get; } protected ICollection<(int, int)>[] KeyMatches { get; }
/// <summary> /// <summary>
/// 构造器 /// 构造器
@@ -29,7 +29,7 @@ namespace Modbus.Net
} }
/// <inheritdoc /> /// <inheritdoc />
protected override (string,string)? GetKeyFromMessage(byte[] message) protected override (string, string)? GetKeyFromMessage(byte[] message)
{ {
string ans1 = ""; string ans1 = "";
string ans2 = ""; string ans2 = "";

View File

@@ -1,6 +1,6 @@
using Quartz.Listener; using Microsoft.Extensions.Logging;
using Quartz; using Quartz;
using Serilog; using Quartz.Listener;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -12,6 +12,8 @@ namespace Modbus.Net
/// </summary> /// </summary>
public class JobChainingJobListenerWithDataMap : JobListenerSupport public class JobChainingJobListenerWithDataMap : JobListenerSupport
{ {
private static readonly ILogger<JobChainingJobListenerWithDataMap> logger = LogProvider.CreateLogger<JobChainingJobListenerWithDataMap>();
/// <summary> /// <summary>
/// JobChaningJobListener with DataMap passing from parent job to next job /// JobChaningJobListener with DataMap passing from parent job to next job
/// </summary> /// </summary>
@@ -58,7 +60,7 @@ namespace Modbus.Net
return; 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 try
{ {
@@ -78,7 +80,7 @@ namespace Modbus.Net
} }
catch (SchedulerException se) 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 #nullable disable

View File

@@ -3,7 +3,6 @@ using Quartz.Impl;
using Quartz.Impl.Matchers; using Quartz.Impl.Matchers;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection.PortableExecutable;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Modbus.Net namespace Modbus.Net
@@ -67,13 +66,13 @@ namespace Modbus.Net
ITrigger trigger; ITrigger trigger;
if (count >= 0) if (count >= 0)
trigger = TriggerBuilder.Create() trigger = TriggerBuilder.Create()
.WithIdentity(triggerKey, "Modbus.Net.DataQuery.Group."+ triggerKey) .WithIdentity(triggerKey, "Modbus.Net.DataQuery.Group." + triggerKey)
.StartNow() .StartNow()
.WithSimpleSchedule(b => b.WithInterval(TimeSpan.FromSeconds(interval)).WithRepeatCount(count)) .WithSimpleSchedule(b => b.WithInterval(TimeSpan.FromSeconds(interval)).WithRepeatCount(count))
.Build(); .Build();
else else
trigger = TriggerBuilder.Create() trigger = TriggerBuilder.Create()
.WithIdentity(triggerKey, "Modbus.Net.DataQuery.Group."+ triggerKey) .WithIdentity(triggerKey, "Modbus.Net.DataQuery.Group." + triggerKey)
.StartNow() .StartNow()
.WithSimpleSchedule(b => b.WithInterval(TimeSpan.FromSeconds(interval)).RepeatForever()) .WithSimpleSchedule(b => b.WithInterval(TimeSpan.FromSeconds(interval)).RepeatForever())
.Build(); .Build();
@@ -101,7 +100,7 @@ namespace Modbus.Net
IScheduler scheduler = await StdSchedulerFactory.GetDefaultScheduler(); IScheduler scheduler = await StdSchedulerFactory.GetDefaultScheduler();
var jobKeys = await scheduler.GetJobKeys(GroupMatcher<JobKey>.GroupEquals("Modbus.Net.DataQuery.Group." + triggerKey)); var jobKeys = await scheduler.GetJobKeys(GroupMatcher<JobKey>.GroupEquals("Modbus.Net.DataQuery.Group." + triggerKey));
await scheduler.UnscheduleJob(new TriggerKey(triggerKey, "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); await _scheduler.AddJob(job, true);
} }
else else
{ {
await _scheduler.ScheduleJob(job, _trigger); await _scheduler.ScheduleJob(job, _trigger);
} }
@@ -395,7 +394,7 @@ namespace Modbus.Net
await _scheduler.Start(); await _scheduler.Start();
} }
} }
/// <summary> /// <summary>
/// 处理写返回任务 /// 处理写返回任务
/// </summary> /// </summary>
@@ -544,7 +543,7 @@ namespace Modbus.Net
/// <summary> /// <summary>
/// 处理写返回任务 /// 处理写返回任务
/// </summary> /// </summary>
public class MachineDealDataJob<TMachineKey> : IJob where TMachineKey: IEquatable<TMachineKey> public class MachineDealDataJob<TMachineKey> : IJob where TMachineKey : IEquatable<TMachineKey>
{ {
/// <inheritdoc /> /// <inheritdoc />
public async Task Execute(IJobExecutionContext context) public async Task Execute(IJobExecutionContext context)

View File

@@ -55,14 +55,14 @@ namespace Modbus.Net
{ {
if (connectionTimeout == -1) 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 else
{ {
BaseConnector = new ComConnector(com + ":" + slaveAddress, baudRate, parity, stopBits, dataBits, BaseConnector = new ComConnector(com + ":" + slaveAddress, baudRate, parity, stopBits, dataBits,
connectionTimeout, isFullDuplex:isFullDuplex); connectionTimeout, isFullDuplex: isFullDuplex);
} }
} }
} }
} }

View File

@@ -39,13 +39,13 @@ namespace Modbus.Net
if (connectionTimeout == -1) if (connectionTimeout == -1)
{ {
//初始化连接对象 //初始化连接对象
BaseConnector = new TcpConnector(ip, port, isFullDuplex:isFullDuplex); BaseConnector = new TcpConnector(ip, port, isFullDuplex: isFullDuplex);
} }
else else
{ {
//初始化连接对象 //初始化连接对象
BaseConnector = new TcpConnector(ip, port, connectionTimeout, isFullDuplex:isFullDuplex); BaseConnector = new TcpConnector(ip, port, connectionTimeout, isFullDuplex: isFullDuplex);
} }
} }
} }
} }

View File

@@ -39,12 +39,12 @@ namespace Modbus.Net
if (connectionTimeout == -1) if (connectionTimeout == -1)
{ {
//初始化连接对象 //初始化连接对象
BaseConnector = new UdpConnector(ip, port, isFullDuplex:isFullDuplex); BaseConnector = new UdpConnector(ip, port, isFullDuplex: isFullDuplex);
} }
else else
{ {
//初始化连接对象 //初始化连接对象
BaseConnector = new UdpConnector(ip, port, connectionTimeout, isFullDuplex:isFullDuplex); BaseConnector = new UdpConnector(ip, port, connectionTimeout, isFullDuplex: isFullDuplex);
} }
} }
} }

View File

@@ -0,0 +1,43 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
namespace Modbus.Net
{
/// <summary>
///
/// </summary>
public static class LogProvider
{
private static ILoggerFactory _loggerFactory = null;
/// <summary>
/// Sets the current log provider based on logger factory.
/// </summary>
/// <param name="loggerFactory">The logger factory.</param>
public static void SetLogProvider(ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
}
/// <summary>
///
/// </summary>
/// <param name="category"></param>
/// <returns></returns>
public static ILogger CreateLogger(string category) => _loggerFactory != null ? _loggerFactory.CreateLogger(category) : NullLogger.Instance;
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static ILogger<T> CreateLogger<T>() => _loggerFactory != null ? _loggerFactory.CreateLogger<T>() : NullLogger<T>.Instance;
#if DIAGNOSTICS_SOURCE
internal static class Cached
{
internal static readonly System.Lazy<System.Diagnostics.DiagnosticListener> Default =
new(() => new System.Diagnostics.DiagnosticListener(DiagnosticHeaders.DefaultListenerName));
}
#endif
}
}

View File

@@ -75,12 +75,12 @@ namespace Modbus.Net
{ {
//按从小到大的顺序对地址进行排序 //按从小到大的顺序对地址进行排序
var groupedAddresses = from address in addresses var groupedAddresses = from address in addresses
orderby orderby
AddressHelper.GetProtocolCoordinate(address.Address, address.SubAddress, AddressHelper.GetProtocolCoordinate(address.Address, address.SubAddress,
AddressTranslator.GetAreaByteLength(address.Area)) AddressTranslator.GetAreaByteLength(address.Area))
group address by address.Area group address by address.Area
into grouped into grouped
select grouped; select grouped;
var ans = new List<CommunicationUnit<TKey>>(); var ans = new List<CommunicationUnit<TKey>>();
foreach (var groupedAddress in groupedAddresses) foreach (var groupedAddress in groupedAddresses)
{ {
@@ -140,12 +140,12 @@ namespace Modbus.Net
ans.Add(new CommunicationUnit<TKey> ans.Add(new CommunicationUnit<TKey>
{ {
Area = area, Area = area,
Address = (int) Math.Floor(initNum), Address = (int)Math.Floor(initNum),
GetCount = GetCount =
(int) (int)
Math.Ceiling( Math.Ceiling(
AddressHelper.MapProtocolGetCountToAbstractByteCount( AddressHelper.MapProtocolGetCountToAbstractByteCount(
preNum - (int) Math.Floor(initNum), preNum - (int)Math.Floor(initNum),
AddressTranslator.GetAreaByteLength(address.Area), AddressTranslator.GetAreaByteLength(address.Area),
BigEndianValueHelper.Instance.ByteLength[preType.FullName])), BigEndianValueHelper.Instance.ByteLength[preType.FullName])),
DataType = typeof(byte), DataType = typeof(byte),
@@ -170,12 +170,12 @@ namespace Modbus.Net
ans.Add(new CommunicationUnit<TKey> ans.Add(new CommunicationUnit<TKey>
{ {
Area = area, Area = area,
Address = (int) Math.Floor(initNum), Address = (int)Math.Floor(initNum),
GetCount = GetCount =
(int) (int)
Math.Ceiling( Math.Ceiling(
AddressHelper.MapProtocolGetCountToAbstractByteCount( AddressHelper.MapProtocolGetCountToAbstractByteCount(
preNum - (int) Math.Floor(initNum), AddressTranslator.GetAreaByteLength(area), preNum - (int)Math.Floor(initNum), AddressTranslator.GetAreaByteLength(area),
BigEndianValueHelper.Instance.ByteLength[preType.FullName])), BigEndianValueHelper.Instance.ByteLength[preType.FullName])),
DataType = typeof(byte), DataType = typeof(byte),
OriginalAddresses = originalAddresses.ToList() OriginalAddresses = originalAddresses.ToList()
@@ -255,7 +255,7 @@ namespace Modbus.Net
SubAddress = address.SubAddress, SubAddress = address.SubAddress,
DataType = address.DataType, DataType = address.DataType,
GetCount = 1, GetCount = 1,
OriginalAddresses = new List<AddressUnit<TKey>> {address} OriginalAddresses = new List<AddressUnit<TKey>> { address }
}).ToList(); }).ToList();
} }
} }
@@ -351,7 +351,7 @@ namespace Modbus.Net
{ {
if (orderedGap.GapNumber <= 0) continue; if (orderedGap.GapNumber <= 0) continue;
var nowAddress = orderedGap.EndUnit; 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]; nowAddress = continusAddresses[index];
index--; index--;
var preAddress = continusAddresses[index]; var preAddress = continusAddresses[index];
@@ -432,7 +432,7 @@ namespace Modbus.Net
var addressUnits = addresses as IList<AddressUnit<TKey>> ?? addresses.ToList(); var addressUnits = addresses as IList<AddressUnit<TKey>> ?? addresses.ToList();
var count = addressUnits.Sum(address => BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]); var count = addressUnits.Sum(address => BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]);
return return
new AddressCombinerNumericJump<TKey>((int) (count * Percentage / 100.0), MaxLength, AddressTranslator) new AddressCombinerNumericJump<TKey>((int)(count * Percentage / 100.0), MaxLength, AddressTranslator)
.Combine( .Combine(
addressUnits); addressUnits);
} }

View File

@@ -1,8 +1,8 @@
using System; using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Serilog;
namespace Modbus.Net namespace Modbus.Net
{ {
@@ -80,6 +80,8 @@ namespace Modbus.Net
where TKey : IEquatable<TKey> where TKey : IEquatable<TKey>
where TUnitKey : IEquatable<TUnitKey> where TUnitKey : IEquatable<TUnitKey>
{ {
private static readonly ILogger<BaseMachine<TKey, TUnitKey>> logger = LogProvider.CreateLogger<BaseMachine<TKey, TUnitKey>>();
private readonly int _maxErrorCount = 3; private readonly int _maxErrorCount = 3;
/// <summary> /// <summary>
@@ -243,39 +245,39 @@ namespace Modbus.Net
AddressTranslator.GetAreaByteLength(communicateAddress.Area)) + AddressTranslator.GetAreaByteLength(communicateAddress.Area)) +
address.SubAddress * 0.125; 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; string key;
switch (getDataType) switch (getDataType)
{ {
case MachineDataType.CommunicationTag: case MachineDataType.CommunicationTag:
{ {
key = address.CommunicationTag; key = address.CommunicationTag;
break; break;
} }
case MachineDataType.Address: case MachineDataType.Address:
{ {
key = AddressFormater.FormatAddress(address.Area, address.Address, address.SubAddress); key = AddressFormater.FormatAddress(address.Area, address.Address, address.SubAddress);
break; break;
} }
case MachineDataType.Name: case MachineDataType.Name:
{ {
key = address.Name; key = address.Name;
break; break;
} }
case MachineDataType.Id: case MachineDataType.Id:
{ {
key = address.Id.ToString(); key = address.Id.ToString();
break; break;
} }
default: default:
{ {
key = address.CommunicationTag; key = address.CommunicationTag;
break; break;
} }
} }
try try
@@ -302,7 +304,7 @@ namespace Modbus.Net
catch (Exception e) catch (Exception e)
{ {
ErrorCount++; 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) if (ErrorCount >= _maxErrorCount)
Disconnect(); Disconnect();
@@ -321,8 +323,8 @@ namespace Modbus.Net
catch (Exception e) catch (Exception e)
{ {
ErrorCount++; 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) if (ErrorCount >= _maxErrorCount)
Disconnect(); Disconnect();
return null; return null;
@@ -364,48 +366,48 @@ namespace Modbus.Net
switch (setDataType) switch (setDataType)
{ {
case MachineDataType.Address: case MachineDataType.Address:
{ {
address = address =
GetAddresses.SingleOrDefault( GetAddresses.SingleOrDefault(
p => p =>
AddressFormater.FormatAddress(p.Area, p.Address, p.SubAddress) == value.Key || AddressFormater.FormatAddress(p.Area, p.Address, p.SubAddress) == value.Key ||
p.DataType != typeof(bool) && p.DataType != typeof(bool) &&
AddressFormater.FormatAddress(p.Area, p.Address) == value.Key); AddressFormater.FormatAddress(p.Area, p.Address) == value.Key);
break; break;
} }
case MachineDataType.CommunicationTag: case MachineDataType.CommunicationTag:
{ {
address = address =
GetAddresses.SingleOrDefault(p => p.CommunicationTag == value.Key); GetAddresses.SingleOrDefault(p => p.CommunicationTag == value.Key);
break; break;
} }
case MachineDataType.Name: case MachineDataType.Name:
{ {
address = GetAddresses.SingleOrDefault(p => p.Name == value.Key); address = GetAddresses.SingleOrDefault(p => p.Name == value.Key);
break; break;
} }
case MachineDataType.Id: case MachineDataType.Id:
{ {
address = GetAddresses.SingleOrDefault(p => p.Id.ToString() == value.Key); address = GetAddresses.SingleOrDefault(p => p.Id.ToString() == value.Key);
break; break;
} }
default: default:
{ {
address = address =
GetAddresses.SingleOrDefault(p => p.CommunicationTag == value.Key); GetAddresses.SingleOrDefault(p => p.CommunicationTag == value.Key);
break; break;
} }
} }
//地址为空报错 //地址为空报错
if (address == null) if (address == null)
{ {
Log.Error($"Machine {ConnectionToken} Address {value.Key} doesn't exist."); logger.LogError($"Machine {ConnectionToken} Address {value.Key} doesn't exist.");
continue; continue;
} }
//不能写报错 //不能写报错
if (!address.CanWrite) if (!address.CanWrite)
{ {
Log.Error($"Machine {ConnectionToken} Address {value.Key} cannot write."); logger.LogError($"Machine {ConnectionToken} Address {value.Key} cannot write.");
continue; continue;
} }
addresses.Add(address); addresses.Add(address);
@@ -449,58 +451,58 @@ namespace Modbus.Net
AddressTranslator.GetAreaByteLength(communicateAddress.Area), AddressTranslator.GetAreaByteLength(communicateAddress.Area),
AddressTranslator.GetAreaByteLength(communicateAddress.Area), 0); 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 localPos = byteCount / AddressTranslator.GetAreaByteLength(communicateAddress.Area);
//协议坐标子地址 //协议坐标子地址
var subPos = var subPos =
(int) (int)
((localPos - (int) localPos) / ((localPos - (int)localPos) /
(0.125 / AddressTranslator.GetAreaByteLength(communicateAddress.Area))); (0.125 / AddressTranslator.GetAreaByteLength(communicateAddress.Area)));
//协议主地址字符串 //协议主地址字符串
var address = AddressFormater.FormatAddress(communicateAddress.Area, var address = AddressFormater.FormatAddress(communicateAddress.Area,
communicateAddress.Address + (int) localPos, subPos); communicateAddress.Address + (int)localPos, subPos);
//协议完整地址字符串 //协议完整地址字符串
var address2 = subPos != 0 var address2 = subPos != 0
? null ? null
: AddressFormater.FormatAddress(communicateAddress.Area, : AddressFormater.FormatAddress(communicateAddress.Area,
communicateAddress.Address + (int) localPos); communicateAddress.Address + (int)localPos);
//获取写入类型 //获取写入类型
var dataType = addressUnit.DataType; var dataType = addressUnit.DataType;
KeyValuePair<string, double> value; KeyValuePair<string, double> value;
switch (setDataType) switch (setDataType)
{ {
case MachineDataType.Address: case MachineDataType.Address:
{ {
//获取要写入的值 //获取要写入的值
value = value =
values.SingleOrDefault( values.SingleOrDefault(
p => p.Key == address || address2 != null && p.Key == address2); p => p.Key == address || address2 != null && p.Key == address2);
break; break;
} }
case MachineDataType.CommunicationTag: case MachineDataType.CommunicationTag:
{ {
value = values.SingleOrDefault(p => p.Key == addressUnit.CommunicationTag); value = values.SingleOrDefault(p => p.Key == addressUnit.CommunicationTag);
break; break;
} }
case MachineDataType.Name: case MachineDataType.Name:
{ {
value = values.SingleOrDefault(p => p.Key == addressUnit.Name); value = values.SingleOrDefault(p => p.Key == addressUnit.Name);
break; break;
} }
case MachineDataType.Id: case MachineDataType.Id:
{ {
value = values.SingleOrDefault(p => p.Key == addressUnit.Id.ToString()); value = values.SingleOrDefault(p => p.Key == addressUnit.Id.ToString());
break; break;
} }
default: default:
{ {
value = values.SingleOrDefault(p => p.Key == addressUnit.CommunicationTag); value = values.SingleOrDefault(p => p.Key == addressUnit.CommunicationTag);
break; break;
} }
} }
//将要写入的值加入队列 //将要写入的值加入队列
var data = Convert.ChangeType(value.Value / addressUnit.Zoom, dataType); var data = Convert.ChangeType(value.Value / addressUnit.Zoom, dataType);
@@ -521,7 +523,7 @@ namespace Modbus.Net
catch (Exception e) catch (Exception e)
{ {
ErrorCount++; 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) if (ErrorCount >= _maxErrorCount)
Disconnect(); Disconnect();
@@ -619,7 +621,7 @@ namespace Modbus.Net
} }
catch (Exception e) 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; return null;
} }
} }

View File

@@ -18,8 +18,8 @@ namespace Modbus.Net
{ {
if (getValues == null) return null; if (getValues == null) return null;
return (from getValue in getValues return (from getValue in getValues
where getValue.Value.DeviceValue != null where getValue.Value.DeviceValue != null
select new KeyValuePair<string, double>(getValue.Key, getValue.Value.DeviceValue.Value)).ToDictionary( select new KeyValuePair<string, double>(getValue.Key, getValue.Value.DeviceValue.Value)).ToDictionary(
p => p.Key, p => p.Value); p => p.Key, p => p.Value);
} }
} }

View File

@@ -5,7 +5,7 @@
<AssemblyName>Modbus.Net</AssemblyName> <AssemblyName>Modbus.Net</AssemblyName>
<RootNamespace>Modbus.Net</RootNamespace> <RootNamespace>Modbus.Net</RootNamespace>
<PackageId>Modbus.Net</PackageId> <PackageId>Modbus.Net</PackageId>
<Version>1.4.0</Version> <Version>1.4.0-beta03</Version>
<Product>Modbus.Net</Product> <Product>Modbus.Net</Product>
<Authors>Chris L.(Luo Sheng)</Authors> <Authors>Chris L.(Luo Sheng)</Authors>
<Company>Hangzhou Delian Science Technology Co.,Ltd.</Company> <Company>Hangzhou Delian Science Technology Co.,Ltd.</Company>
@@ -28,10 +28,8 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" /> <PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
<PackageReference Include="Quartz" Version="3.6.0" /> <PackageReference Include="Quartz" Version="3.6.2" />
<PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="System.IO.Ports" Version="7.0.0" /> <PackageReference Include="System.IO.Ports" Version="7.0.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" /> <PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup> </ItemGroup>

View File

@@ -96,7 +96,7 @@ namespace Modbus.Net
/// <param name="protocolLinker">连接器</param> /// <param name="protocolLinker">连接器</param>
public PipeUnit(TProtocolLinker protocolLinker) : this(protocolLinker, null, null, true) public PipeUnit(TProtocolLinker protocolLinker) : this(protocolLinker, null, null, true)
{ {
} }
/// <summary> /// <summary>

View File

@@ -82,7 +82,7 @@ namespace Modbus.Net
return true; return true;
} }
} }
/// <summary> /// <summary>
/// 基本的协议连接器 /// 基本的协议连接器
/// </summary> /// </summary>

View File

@@ -1,8 +1,8 @@
using System; using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Serilog;
/// <summary> /// <summary>
/// 端格式 /// 端格式
@@ -47,6 +47,8 @@ namespace Modbus.Net
where TProtocolUnit : class, IProtocolFormatting<TParamIn, TParamOut> where TParamOut : class where TProtocolUnit : class, IProtocolFormatting<TParamIn, TParamOut> where TParamOut : class
where TPipeUnit : PipeUnit<TParamIn, TParamOut, IProtocolLinker<TParamIn, TParamOut>, TProtocolUnit> where TPipeUnit : PipeUnit<TParamIn, TParamOut, IProtocolLinker<TParamIn, TParamOut>, TProtocolUnit>
{ {
private static readonly ILogger<BaseUtility<TParamIn, TParamOut, TProtocolUnit, TPipeUnit>> logger = LogProvider.CreateLogger<BaseUtility<TParamIn, TParamOut, TProtocolUnit, TPipeUnit>>();
/// <summary> /// <summary>
/// 协议收发主体 /// 协议收发主体
/// </summary> /// </summary>
@@ -122,13 +124,13 @@ namespace Modbus.Net
var typeName = getTypeAndCount.Key.FullName; var typeName = getTypeAndCount.Key.FullName;
var bCount = BigEndianValueHelper.Instance.ByteLength[typeName]; var bCount = BigEndianValueHelper.Instance.ByteLength[typeName];
var getReturnValue = await GetDatasAsync(startAddress, var getReturnValue = await GetDatasAsync(startAddress,
(int) Math.Ceiling(bCount * getTypeAndCount.Value)); (int)Math.Ceiling(bCount * getTypeAndCount.Value));
var getBytes = getReturnValue; var getBytes = getReturnValue;
return ValueHelper.GetInstance(Endian).ByteArrayToObjectArray(getBytes, getTypeAndCount); return ValueHelper.GetInstance(Endian).ByteArrayToObjectArray(getBytes, getTypeAndCount);
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility -> GetDatas: {ConnectionString} error"); logger.LogError(e, $"ModbusUtility -> GetDatas: {ConnectionString} error");
return null; return null;
} }
} }
@@ -164,7 +166,7 @@ namespace Modbus.Net
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility -> GetDatas Generic: {ConnectionString} error"); logger.LogError(e, $"ModbusUtility -> GetDatas Generic: {ConnectionString} error");
return null; return null;
} }
} }
@@ -198,14 +200,14 @@ namespace Modbus.Net
from getTypeAndCount in translateTypeAndCount from getTypeAndCount in translateTypeAndCount
let typeName = getTypeAndCount.Key.FullName let typeName = getTypeAndCount.Key.FullName
let bCount = BigEndianValueHelper.Instance.ByteLength[typeName] 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 getReturnValue = await GetDatasAsync(startAddress, bAllCount);
var getBytes = getReturnValue; var getBytes = getReturnValue;
return ValueHelper.GetInstance(Endian).ByteArrayToObjectArray(getBytes, translateTypeAndCount); return ValueHelper.GetInstance(Endian).ByteArrayToObjectArray(getBytes, translateTypeAndCount);
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility -> GetDatas pair: {ConnectionString} error"); logger.LogError(e, $"ModbusUtility -> GetDatas pair: {ConnectionString} error");
return null; return null;
} }
} }

View File

@@ -64,11 +64,11 @@ namespace Modbus.Net
CRC = CRC >> 1; CRC = CRC >> 1;
} }
} }
Rcvbuf[1] = (byte) ((CRC & 0xff00) >> 8); //高位置 Rcvbuf[1] = (byte)((CRC & 0xff00) >> 8); //高位置
Rcvbuf[0] = (byte) (CRC & 0x00ff); //低位置 Rcvbuf[0] = (byte)(CRC & 0x00ff); //低位置
CRC = Rcvbuf[0] << 8; CRC = Rcvbuf[0] << 8;
CRC += Rcvbuf[1]; CRC += Rcvbuf[1];
return (short) CRC; return (short)CRC;
} }
#endregion #endregion
@@ -195,7 +195,7 @@ namespace Modbus.Net
byte sum = 0; byte sum = 0;
foreach (var b in code) foreach (var b in code)
sum += b; sum += b;
sum = (byte) (~sum + 1); //取反+1 sum = (byte)(~sum + 1); //取反+1
var lrc = sum.ToString("X2"); var lrc = sum.ToString("X2");
return lrc; return lrc;
} }

View File

@@ -1,9 +1,9 @@
using System; using Microsoft.Extensions.Logging;
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Serilog;
namespace Modbus.Net namespace Modbus.Net
{ {
@@ -12,6 +12,8 @@ namespace Modbus.Net
/// </summary> /// </summary>
public class ValueHelper public class ValueHelper
{ {
private static readonly ILogger<ValueHelper> logger = LogProvider.CreateLogger<ValueHelper>();
/// <summary> /// <summary>
/// 兼容数据类型对应的字节长度 /// 兼容数据类型对应的字节长度
/// </summary> /// </summary>
@@ -53,7 +55,7 @@ namespace Modbus.Net
/// <returns>byte数组</returns> /// <returns>byte数组</returns>
public byte[] GetBytes(byte value) public byte[] GetBytes(byte value)
{ {
return new[] {value}; return new[] { value };
} }
/// <summary> /// <summary>
@@ -147,54 +149,54 @@ namespace Modbus.Net
switch (type.FullName) switch (type.FullName)
{ {
case "System.Int16": case "System.Int16":
{ {
var bytes = _Instance.GetBytes((short) value); var bytes = _Instance.GetBytes((short)value);
return bytes; return bytes;
} }
case "System.Int32": case "System.Int32":
{ {
var bytes = _Instance.GetBytes((int) value); var bytes = _Instance.GetBytes((int)value);
return bytes; return bytes;
} }
case "System.Int64": case "System.Int64":
{ {
var bytes = _Instance.GetBytes((long) value); var bytes = _Instance.GetBytes((long)value);
return bytes; return bytes;
} }
case "System.UInt16": case "System.UInt16":
{ {
var bytes = _Instance.GetBytes((ushort) value); var bytes = _Instance.GetBytes((ushort)value);
return bytes; return bytes;
} }
case "System.UInt32": case "System.UInt32":
{ {
var bytes = _Instance.GetBytes((uint) value); var bytes = _Instance.GetBytes((uint)value);
return bytes; return bytes;
} }
case "System.UInt64": case "System.UInt64":
{ {
var bytes = _Instance.GetBytes((ulong) value); var bytes = _Instance.GetBytes((ulong)value);
return bytes; return bytes;
} }
case "System.Single": case "System.Single":
{ {
var bytes = _Instance.GetBytes((float) value); var bytes = _Instance.GetBytes((float)value);
return bytes; return bytes;
} }
case "System.Double": case "System.Double":
{ {
var bytes = _Instance.GetBytes((double) value); var bytes = _Instance.GetBytes((double)value);
return bytes; return bytes;
} }
case "System.Byte": case "System.Byte":
{ {
var bytes = _Instance.GetBytes((byte) value); var bytes = _Instance.GetBytes((byte)value);
return bytes; return bytes;
} }
default: default:
{ {
throw new NotImplementedException("没有实现除整数以外的其它转换方式"); throw new NotImplementedException("没有实现除整数以外的其它转换方式");
} }
} }
} }
@@ -211,59 +213,59 @@ namespace Modbus.Net
switch (t.FullName) switch (t.FullName)
{ {
case "System.Int16": case "System.Int16":
{ {
var value = _Instance.GetShort(data, ref pos); var value = _Instance.GetShort(data, ref pos);
return value; return value;
} }
case "System.Int32": case "System.Int32":
{ {
var value = _Instance.GetInt(data, ref pos); var value = _Instance.GetInt(data, ref pos);
return value; return value;
} }
case "System.Int64": case "System.Int64":
{ {
var value = _Instance.GetLong(data, ref pos); var value = _Instance.GetLong(data, ref pos);
return value; return value;
} }
case "System.UInt16": case "System.UInt16":
{ {
var value = _Instance.GetUShort(data, ref pos); var value = _Instance.GetUShort(data, ref pos);
return value; return value;
} }
case "System.UInt32": case "System.UInt32":
{ {
var value = _Instance.GetUInt(data, ref pos); var value = _Instance.GetUInt(data, ref pos);
return value; return value;
} }
case "System.UInt64": case "System.UInt64":
{ {
var value = _Instance.GetULong(data, ref pos); var value = _Instance.GetULong(data, ref pos);
return value; return value;
} }
case "System.Single": case "System.Single":
{ {
var value = _Instance.GetFloat(data, ref pos); var value = _Instance.GetFloat(data, ref pos);
return value; return value;
} }
case "System.Double": case "System.Double":
{ {
var value = _Instance.GetDouble(data, ref pos); var value = _Instance.GetDouble(data, ref pos);
return value; return value;
} }
case "System.Byte": case "System.Byte":
{ {
var value = _Instance.GetByte(data, ref pos); var value = _Instance.GetByte(data, ref pos);
return value; return value;
} }
case "System.Boolean": case "System.Boolean":
{ {
var value = _Instance.GetBit(data, ref pos, ref subPos); var value = _Instance.GetBit(data, ref pos, ref subPos);
return value; return value;
} }
default: default:
{ {
throw new NotImplementedException("没有实现除整数以外的其它转换方式"); throw new NotImplementedException("没有实现除整数以外的其它转换方式");
} }
} }
} }
@@ -468,7 +470,7 @@ namespace Modbus.Net
for (var i = 0; i < 8; i++) for (var i = 0; i < 8; i++)
{ {
result <<= 1; result <<= 1;
result |= (byte) (originalByte & 1); result |= (byte)(originalByte & 1);
originalByte >>= 1; originalByte >>= 1;
} }
return result; return result;
@@ -492,7 +494,7 @@ namespace Modbus.Net
b = true; b = true;
//自动将目标数组中内含的子数组展开,是所有包含在子数组拼接为一个数组 //自动将目标数组中内含的子数组展开,是所有包含在子数组拼接为一个数组
var contentArray = var contentArray =
ArrayList.Adapter((Array) content).ToArray(typeof(object)).OfType<object>(); ArrayList.Adapter((Array)content).ToArray(typeof(object)).OfType<object>();
newContentsList.AddRange(contentArray); newContentsList.AddRange(contentArray);
} }
else else
@@ -521,9 +523,9 @@ namespace Modbus.Net
} }
lastIsBool = true; lastIsBool = true;
if (!LittleEndianBit) if (!LittleEndianBit)
boolToByteTemp = (byte) (boolToByteTemp * 2 + ((bool) content ? 1 : 0)); boolToByteTemp = (byte)(boolToByteTemp * 2 + ((bool)content ? 1 : 0));
else else
boolToByteTemp += (byte) ((bool) content ? Math.Pow(2, boolToByteCount) : 0); boolToByteTemp += (byte)((bool)content ? Math.Pow(2, boolToByteCount) : 0);
boolToByteCount++; boolToByteCount++;
} }
else else
@@ -538,54 +540,54 @@ namespace Modbus.Net
switch (t) switch (t)
{ {
case "System.Int16": case "System.Int16":
{ {
translateTarget.AddRange(_Instance.GetBytes((short) content)); translateTarget.AddRange(_Instance.GetBytes((short)content));
break; break;
} }
case "System.Int32": case "System.Int32":
{ {
translateTarget.AddRange(_Instance.GetBytes((int) content)); translateTarget.AddRange(_Instance.GetBytes((int)content));
break; break;
} }
case "System.Int64": case "System.Int64":
{ {
translateTarget.AddRange(_Instance.GetBytes((long) content)); translateTarget.AddRange(_Instance.GetBytes((long)content));
break; break;
} }
case "System.UInt16": case "System.UInt16":
{ {
translateTarget.AddRange(_Instance.GetBytes((ushort) content)); translateTarget.AddRange(_Instance.GetBytes((ushort)content));
break; break;
} }
case "System.UInt32": case "System.UInt32":
{ {
translateTarget.AddRange(_Instance.GetBytes((uint) content)); translateTarget.AddRange(_Instance.GetBytes((uint)content));
break; break;
} }
case "System.UInt64": case "System.UInt64":
{ {
translateTarget.AddRange(_Instance.GetBytes((ulong) content)); translateTarget.AddRange(_Instance.GetBytes((ulong)content));
break; break;
} }
case "System.Single": case "System.Single":
{ {
translateTarget.AddRange(_Instance.GetBytes((float) content)); translateTarget.AddRange(_Instance.GetBytes((float)content));
break; break;
} }
case "System.Double": case "System.Double":
{ {
translateTarget.AddRange(_Instance.GetBytes((double) content)); translateTarget.AddRange(_Instance.GetBytes((double)content));
break; break;
} }
case "System.Byte": case "System.Byte":
{ {
translateTarget.AddRange(_Instance.GetBytes((byte) content)); translateTarget.AddRange(_Instance.GetBytes((byte)content));
break; break;
} }
default: default:
{ {
throw new NotImplementedException("没有实现除整数以外的其它转换方式"); throw new NotImplementedException("没有实现除整数以外的其它转换方式");
} }
} }
} }
} }
@@ -604,7 +606,7 @@ namespace Modbus.Net
/// <returns>object数组</returns> /// <returns>object数组</returns>
public virtual object[] ByteArrayToObjectArray(byte[] contents, KeyValuePair<Type, int> translateTypeAndCount) public virtual object[] ByteArrayToObjectArray(byte[] contents, KeyValuePair<Type, int> translateTypeAndCount)
{ {
return ByteArrayToObjectArray(contents, new List<KeyValuePair<Type, int>> {translateTypeAndCount}); return ByteArrayToObjectArray(contents, new List<KeyValuePair<Type, int>> { translateTypeAndCount });
} }
/// <summary> /// <summary>
@@ -644,77 +646,77 @@ namespace Modbus.Net
switch (translateUnit.Key.ToString()) switch (translateUnit.Key.ToString())
{ {
case "System.Int16": case "System.Int16":
{ {
var value = _Instance.GetShort(contents, ref count); var value = _Instance.GetShort(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.Int32": case "System.Int32":
{ {
var value = _Instance.GetInt(contents, ref count); var value = _Instance.GetInt(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.Int64": case "System.Int64":
{ {
var value = _Instance.GetLong(contents, ref count); var value = _Instance.GetLong(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.UInt16": case "System.UInt16":
{ {
var value = _Instance.GetUShort(contents, ref count); var value = _Instance.GetUShort(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.UInt32": case "System.UInt32":
{ {
var value = _Instance.GetUInt(contents, ref count); var value = _Instance.GetUInt(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.UInt64": case "System.UInt64":
{ {
var value = _Instance.GetULong(contents, ref count); var value = _Instance.GetULong(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.Single": case "System.Single":
{ {
var value = _Instance.GetFloat(contents, ref count); var value = _Instance.GetFloat(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.Double": case "System.Double":
{ {
var value = _Instance.GetDouble(contents, ref count); var value = _Instance.GetDouble(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.Byte": case "System.Byte":
{ {
var value = _Instance.GetByte(contents, ref count); var value = _Instance.GetByte(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.Boolean": case "System.Boolean":
{ {
var value = _Instance.GetBits(contents, ref count); var value = _Instance.GetBits(contents, ref count);
var k = translateUnit.Value - i < 8 ? translateUnit.Value - i : 8; var k = translateUnit.Value - i < 8 ? translateUnit.Value - i : 8;
for (var j = 0; j < k; j++) for (var j = 0; j < k; j++)
translation.Add(value[j]); translation.Add(value[j]);
i += 7; i += 7;
break; break;
} }
default: default:
{ {
throw new NotImplementedException("Number casting not implemented"); throw new NotImplementedException("Number casting not implemented");
} }
} }
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "ValueHelper -> ByteArrayToObjectArray error"); logger.LogError(e, "ValueHelper -> ByteArrayToObjectArray error");
count = contents.Length; count = contents.Length;
} }
} }
@@ -749,59 +751,59 @@ namespace Modbus.Net
switch (type.FullName) switch (type.FullName)
{ {
case "System.Int16": case "System.Int16":
{ {
var success = _Instance.SetValue(contents, setPos, (short) setValue); var success = _Instance.SetValue(contents, setPos, (short)setValue);
return success; return success;
} }
case "System.Int32": case "System.Int32":
{ {
var success = _Instance.SetValue(contents, setPos, (int) setValue); var success = _Instance.SetValue(contents, setPos, (int)setValue);
return success; return success;
} }
case "System.Int64": case "System.Int64":
{ {
var success = _Instance.SetValue(contents, setPos, (long) setValue); var success = _Instance.SetValue(contents, setPos, (long)setValue);
return success; return success;
} }
case "System.UInt16": case "System.UInt16":
{ {
var success = _Instance.SetValue(contents, setPos, (ushort) setValue); var success = _Instance.SetValue(contents, setPos, (ushort)setValue);
return success; return success;
} }
case "System.UInt32": case "System.UInt32":
{ {
var success = _Instance.SetValue(contents, setPos, (uint) setValue); var success = _Instance.SetValue(contents, setPos, (uint)setValue);
return success; return success;
} }
case "System.UInt64": case "System.UInt64":
{ {
var success = _Instance.SetValue(contents, setPos, (ulong) setValue); var success = _Instance.SetValue(contents, setPos, (ulong)setValue);
return success; return success;
} }
case "System.Single": case "System.Single":
{ {
var success = _Instance.SetValue(contents, setPos, (float) setValue); var success = _Instance.SetValue(contents, setPos, (float)setValue);
return success; return success;
} }
case "System.Double": case "System.Double":
{ {
var success = _Instance.SetValue(contents, setPos, (double) setValue); var success = _Instance.SetValue(contents, setPos, (double)setValue);
return success; return success;
} }
case "System.Byte": case "System.Byte":
{ {
var success = _Instance.SetValue(contents, setPos, (byte) setValue); var success = _Instance.SetValue(contents, setPos, (byte)setValue);
return success; return success;
} }
case "System.Boolean": case "System.Boolean":
{ {
var success = _Instance.SetBit(contents, setPos, subPos, (bool) setValue); var success = _Instance.SetBit(contents, setPos, subPos, (bool)setValue);
return success; return success;
} }
default: default:
{ {
throw new NotImplementedException("Number casting not implemented"); throw new NotImplementedException("Number casting not implemented");
} }
} }
} }
@@ -822,7 +824,7 @@ namespace Modbus.Net
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "ValueHelper -> SetValue set value failed"); logger.LogError(e, "ValueHelper -> SetValue set value failed");
return false; return false;
} }
} }
@@ -844,14 +846,14 @@ namespace Modbus.Net
creation *= 2; creation *= 2;
if (i == subPos) creation++; if (i == subPos) creation++;
} }
return (byte) (number | creation); return (byte)(number | creation);
} }
for (var i = 7; i >= 0; i--) for (var i = 7; i >= 0; i--)
{ {
creation *= 2; creation *= 2;
if (i != subPos) creation++; if (i != subPos) creation++;
} }
return (byte) (number & creation); return (byte)(number & creation);
} }
/// <summary> /// <summary>
@@ -871,7 +873,7 @@ namespace Modbus.Net
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "ValueHelper -> SetBit set bit failed"); logger.LogError(e, "ValueHelper -> SetBit set bit failed");
return false; return false;
} }
} }
@@ -900,21 +902,21 @@ namespace Modbus.Net
switch (endian) switch (endian)
{ {
case Endian.LittleEndianLsb: case Endian.LittleEndianLsb:
{ {
return Instance; return Instance;
} }
case Endian.BigEndianLsb: case Endian.BigEndianLsb:
{ {
return BigEndianValueHelper.Instance; return BigEndianValueHelper.Instance;
} }
case Endian.BigEndianMsb: case Endian.BigEndianMsb:
{ {
return BigEndianMsbValueHelper.Instance; return BigEndianMsbValueHelper.Instance;
} }
default: default:
{ {
return Instance; return Instance;
} }
} }
} }

View File

@@ -44,15 +44,15 @@ namespace AnyType.Controllers
}; };
values = from unitValue in addressUnits values = from unitValue in addressUnits
select select
new TaskViewModel() new TaskViewModel()
{ {
Id = unitValue.Id, Id = unitValue.Id,
Name = unitValue.Name, Name = unitValue.Name,
Address = unitValue.Address + "." + unitValue.SubAddress, Address = unitValue.Address + "." + unitValue.SubAddress,
Value = 0, Value = 0,
Type = unitValue.DataType.Name Type = unitValue.DataType.Name
}; };
var machine = new ModbusMachine("1", ModbusType.Tcp, "192.168.0.172:502", addressUnits, true, 2, 0); var machine = new ModbusMachine("1", ModbusType.Tcp, "192.168.0.172:502", addressUnits, true, 2, 0);
//启动任务 //启动任务
await MachineJobSchedulerCreator.CreateScheduler("Trigger1", -1, 1).Result.From(machine.Id, machine, MachineDataType.CommunicationTag).Result.Query("Query1", await MachineJobSchedulerCreator.CreateScheduler("Trigger1", -1, 1).Result.From(machine.Id, machine, MachineDataType.CommunicationTag).Result.Query("Query1",

View File

@@ -1,9 +1,4 @@
using System; namespace AnyType.Models
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace AnyType.Models
{ {
public class TaskViewModel public class TaskViewModel
{ {

View File

@@ -1,9 +1,4 @@
using System; public enum LightLamp { Red, Yellow, Green }
using System.Collections.Generic;
using System.Linq;
using System.Web;
public enum LightLamp{Red,Yellow,Green}
namespace CrossLampControl.WebApi.Models namespace CrossLampControl.WebApi.Models
{ {
public class Lamp public class Lamp

View File

@@ -0,0 +1,30 @@
using Quartz.Logging;
namespace MachineJob
{
// simple log provider to get something to the console
public class ConsoleLogProvider : ILogProvider
{
public Logger GetLogger(string name)
{
return (level, func, exception, parameters) =>
{
if (level >= Quartz.Logging.LogLevel.Info && func != null)
{
Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] [" + level + "] " + func(), parameters);
}
return true;
};
}
public IDisposable OpenNestedContext(string message)
{
throw new NotImplementedException();
}
public IDisposable OpenMappedContext(string key, object value, bool destructure = false)
{
throw new NotImplementedException();
}
}
}

View File

@@ -1,5 +1,4 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
@@ -24,7 +23,7 @@ namespace MachineJob
public double? Value1 { get; set; } public double? Value1 { get; set; }
public double? Value2 { get; set; } public double? Value2 { get; set; }
public double? Value3 { get; set; } public double? Value3 { get; set; }
public double? Value4 { get; set; } public double? Value4 { get; set; }
public double? Value5 { get; set; } public double? Value5 { get; set; }
public double? Value6 { get; set; } public double? Value6 { get; set; }
public double? Value7 { get; set; } public double? Value7 { get; set; }

View File

@@ -15,6 +15,9 @@
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0" /> <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.1.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,5 +1,4 @@
using System; using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable #nullable disable

View File

@@ -1,10 +1,31 @@
using MachineJob;
using MachineJob.Service; using MachineJob.Service;
using Serilog;
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", true)
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.WriteTo.Console()
.CreateLogger();
var loggerFactory = new LoggerFactory().AddSerilog(Log.Logger);
Quartz.Logging.LogProvider.SetCurrentLogProvider(new ConsoleLogProvider());
Modbus.Net.LogProvider.SetLogProvider(loggerFactory);
IHost host = Host.CreateDefaultBuilder(args) IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services => .ConfigureServices(services =>
{ {
services.AddHostedService<Worker>(); services.AddHostedService<Worker>();
services.AddLogging(loggingBuilder => loggingBuilder.AddSerilog(Log.Logger, true));
}) })
.Build(); .Build();
await host.RunAsync(); await host.RunAsync();

View File

@@ -15,7 +15,7 @@ namespace MachineJob.Service
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
List<AddressUnit> _addresses = new List<AddressUnit> List<AddressUnit> _addresses = new List<AddressUnit>
{ {
new AddressUnit() { Area = "4X", Address = 1, DataType = typeof(short), Id = "1", Name = "Test1" }, new AddressUnit() { Area = "4X", Address = 1, DataType = typeof(short), Id = "1", Name = "Test1" },
@@ -29,8 +29,7 @@ namespace MachineJob.Service
new AddressUnit() { Area = "4X", Address = 9, DataType = typeof(short), Id = "9", Name = "Test9" }, new AddressUnit() { Area = "4X", Address = 9, DataType = typeof(short), Id = "9", Name = "Test9" },
new AddressUnit() { Area = "4X", Address = 10, DataType = typeof(short), Id = "10", Name = "Test10" } new AddressUnit() { Area = "4X", Address = 10, DataType = typeof(short), Id = "10", Name = "Test10" }
}; };
/*
List<AddressUnit> _addresses2 = new List<AddressUnit> List<AddressUnit> _addresses2 = new List<AddressUnit>
{ {
new AddressUnit() { Area = "DB1", Address = 0, DataType = typeof(short), Id = "1", Name = "Test1" }, new AddressUnit() { Area = "DB1", Address = 0, DataType = typeof(short), Id = "1", Name = "Test1" },
@@ -44,28 +43,30 @@ namespace MachineJob.Service
new AddressUnit() { Area = "DB1", Address = 16, DataType = typeof(short), Id = "9", Name = "Test9" }, new AddressUnit() { Area = "DB1", Address = 16, DataType = typeof(short), Id = "9", Name = "Test9" },
new AddressUnit() { Area = "DB1", Address = 18, DataType = typeof(short), Id = "10", Name = "Test10" } new AddressUnit() { Area = "DB1", Address = 18, DataType = typeof(short), Id = "10", Name = "Test10" }
}; };
*/
IMachine<string> machine = new ModbusMachine<string, string>("ModbusMachine1", ModbusType.Tcp, "192.168.0.161", _addresses, true, 1, 2, Endian.BigEndianLsb);
//IMachine<string> machine2 = new SiemensMachine<string, string>("SiemensMachine1", SiemensType.Tcp, "192.168.0.161", SiemensMachineModel.S7_1200, _addresses2, true, 1, 2);
await MachineJobSchedulerCreator.CreateScheduler("Trigger1", -1, 5).Result.From(machine.Id, machine, MachineDataType.Name).Result.Query(machine.Id + ".ConsoleQuery", QueryConsole).Result.To(machine.Id + ".To", machine).Result.Deal(machine.Id+".Deal", OnSuccess, OnFailure).Result.Run(); IMachine<string> machine = new ModbusMachine<string, string>("ModbusMachine1", ModbusType.Tcp, "192.168.0.161", _addresses, true, 1, 2, Endian.BigEndianLsb);
//await MachineJobSchedulerCreator.CreateScheduler("Trigger2", -1, 5).Result.From(machine2.Id, machine2, MachineDataType.Name).Result.Query(machine2.Id + ".ConsoleQuery", QueryConsole).Result.To(machine2.Id + ".To", machine2).Result.Deal(machine2.Id + ".Deal", OnSuccess, OnFailure).Result.Run(); IMachine<string> machine2 = new SiemensMachine<string, string>("SiemensMachine1", SiemensType.Tcp, "192.168.0.161", SiemensMachineModel.S7_1200, _addresses2, true, 1, 2);
await MachineJobSchedulerCreator.CreateScheduler("Trigger1", -1, 10).Result.From(machine.Id, machine, MachineDataType.Name).Result.Query(machine.Id + ".ConsoleQuery", QueryConsole).Result.To(machine.Id + ".To", machine).Result.Deal(machine.Id + ".Deal", OnSuccess, OnFailure).Result.Run();
Thread.Sleep(5000);
await MachineJobSchedulerCreator.CreateScheduler("Trigger2", -1, 10).Result.From(machine2.Id, machine2, MachineDataType.Name).Result.Query(machine2.Id + ".ConsoleQuery", QueryConsole).Result.To(machine2.Id + ".To", machine2).Result.Deal(machine2.Id + ".Deal", OnSuccess, OnFailure).Result.Run();
} }
public override async Task StopAsync(CancellationToken cancellationToken) public override async Task StopAsync(CancellationToken cancellationToken)
{ {
await MachineJobSchedulerCreator.CancelJob("Trigger1"); await MachineJobSchedulerCreator.CancelJob("Trigger1");
await MachineJobSchedulerCreator.CancelJob("Trigger2");
} }
public Task OnSuccess(string machineId) public Task OnSuccess(string machineId)
{ {
Console.WriteLine("Machine {0} set success", machineId); _logger.LogInformation("Machine {0} set success", machineId);
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task OnFailure(string machineId) public Task OnFailure(string machineId)
{ {
Console.WriteLine("Machine {0} set failure", machineId); _logger.LogError("Machine {0} set failure", machineId);
return Task.CompletedTask; return Task.CompletedTask;
} }
@@ -74,9 +75,9 @@ namespace MachineJob.Service
var values = dataReturnDef.ReturnValues; var values = dataReturnDef.ReturnValues;
foreach (var value in values) foreach (var value in values)
{ {
Console.WriteLine(dataReturnDef.MachineId + " " + value.Key + " " + value.Value.DeviceValue); _logger.LogInformation(dataReturnDef.MachineId + " " + value.Key + " " + value.Value.DeviceValue);
} }
try try
{ {
using (var context = new DatabaseWriteContext()) using (var context = new DatabaseWriteContext())
@@ -102,7 +103,7 @@ namespace MachineJob.Service
{ {
//ignore //ignore
} }
Random r = new Random(); Random r = new Random();
foreach (var value in values) foreach (var value in values)
{ {

View File

@@ -1,8 +1,11 @@
{ {
"Logging": { "Serilog": {
"LogLevel": { "MinimumLevel": {
"Default": "Information", "Default": "Information",
"Microsoft.Hosting.Lifetime": "Information" "Override": {
"Microsoft": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
} }
}, },
"ConnectionStrings": { "ConnectionStrings": {

View File

@@ -1,9 +1,4 @@
using System; namespace TripleAdd.Models
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace TripleAdd.Models
{ {
public class TripleAddViewModel public class TripleAddViewModel
{ {

View File

@@ -6,7 +6,9 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,11 +1,18 @@
using System; using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using Modbus.Net; using Modbus.Net;
using Modbus.Net.Modbus; using Modbus.Net.Modbus;
using Serilog; using Serilog;
using System;
using System.Collections.Generic;
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.Console()
.CreateLogger();
Log.Logger = new LoggerConfiguration().MinimumLevel.Verbose().WriteTo.Console().CreateLogger(); var loggerFactory = new LoggerFactory()
.AddSerilog(Log.Logger);
LogProvider.SetLogProvider(loggerFactory);
ModbusMachine<int, string> machine = new ModbusMachine<int, string>(1, ModbusType.Rtu, "COM1", ModbusMachine<int, string> machine = new ModbusMachine<int, string>(1, ModbusType.Rtu, "COM1",
new List<AddressUnit>() new List<AddressUnit>()
@@ -92,34 +99,34 @@ ModbusMachine<int, string> machine3 = new ModbusMachine<int, string>(3, ModbusTy
}, },
}, true, 4, 1); }, true, 4, 1);
Random r = new Random(); Random r = new Random();
await MachineJobSchedulerCreator.CreateScheduler("Trigger1", -1, 10).Result.ApplyTo(machine.Id+".Apply", new Dictionary<string, double>() {{ await MachineJobSchedulerCreator.CreateScheduler("Trigger1", -1, 10).Result.ApplyTo(machine.Id + ".Apply", new Dictionary<string, double>() {{
"4X 1.0", r.Next() % 65536 "4X 1.0", r.Next() % 65536
}, },
{ {
"4X 2.0", r.Next() % 65536 "4X 2.0", r.Next() % 65536
}, },
{ {
"4X 3.0", r.Next() % 65536 "4X 3.0", r.Next() % 65536
} }
}, MachineDataType.Address).Result.To(machine.Id + ".To", machine).Result.Deal().Result.Run(); }, MachineDataType.Address).Result.To(machine.Id + ".To", machine).Result.Deal().Result.Run();
await MachineJobSchedulerCreator.CreateScheduler("Trigger2", -1, 10).Result.ApplyTo(machine2.Id + ".Apply", new Dictionary<string, double>() {{ await MachineJobSchedulerCreator.CreateScheduler("Trigger2", -1, 10).Result.ApplyTo(machine2.Id + ".Apply", new Dictionary<string, double>() {{
"4X 1.0", r.Next() % 65536 "4X 1.0", r.Next() % 65536
}, },
{ {
"4X 2.0", r.Next() % 65536 "4X 2.0", r.Next() % 65536
}, },
{ {
"4X 3.0", r.Next() % 65536 "4X 3.0", r.Next() % 65536
} }
}, MachineDataType.Address).Result.To(machine2.Id + ".To", machine2).Result.Deal().Result.Run(); }, MachineDataType.Address).Result.To(machine2.Id + ".To", machine2).Result.Deal().Result.Run();
await MachineJobSchedulerCreator.CreateScheduler("Trigger3", -1, 10).Result.ApplyTo(machine3.Id + ".Apply", new Dictionary<string, double>() {{ await MachineJobSchedulerCreator.CreateScheduler("Trigger3", -1, 10).Result.ApplyTo(machine3.Id + ".Apply", new Dictionary<string, double>() {{
"4X 1.0", r.Next() % 65536 "4X 1.0", r.Next() % 65536
}, },
{ {
"4X 2.0", r.Next() % 65536 "4X 2.0", r.Next() % 65536
}, },
{ {
"4X 3.0", r.Next() % 65536 "4X 3.0", r.Next() % 65536
} }
}, MachineDataType.Address).Result.To(machine3.Id + ".To", machine3).Result.Deal().Result.Run(); }, MachineDataType.Address).Result.To(machine3.Id + ".To", machine3).Result.Deal().Result.Run();
Console.ReadLine(); Console.ReadLine();

View File

@@ -1,7 +1,4 @@
using System; using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Modbus.Net.Modbus; using Modbus.Net.Modbus;
using Modbus.Net.Siemens; using Modbus.Net.Siemens;

View File

@@ -1,9 +1,4 @@
using System; using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Modbus.Net.Modbus; using Modbus.Net.Modbus;
namespace Modbus.Net.Tests namespace Modbus.Net.Tests

View File

@@ -1,10 +1,6 @@
using System; using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Modbus.Net.Modbus; using Modbus.Net.Modbus;
using System.Reflection;
namespace Modbus.Net.Tests namespace Modbus.Net.Tests
{ {

View File

@@ -1,8 +1,4 @@
using System; using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Modbus.Net.Modbus; using Modbus.Net.Modbus;
namespace Modbus.Net.Tests namespace Modbus.Net.Tests

View File

@@ -1,7 +1,4 @@
using System; using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Modbus.Net.Modbus; using Modbus.Net.Modbus;
namespace Modbus.Net.Tests namespace Modbus.Net.Tests

View File

@@ -1,8 +1,4 @@
using System; using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Modbus.Net.Modbus;
using Modbus.Net.Siemens; using Modbus.Net.Siemens;
namespace Modbus.Net.Tests namespace Modbus.Net.Tests