Merge branch 'dev'
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
<AssemblyName>Modbus.Net.BigEndian3412</AssemblyName>
|
<AssemblyName>Modbus.Net.BigEndian3412</AssemblyName>
|
||||||
<RootNamespace>Modbus.Net.BigEndian3412</RootNamespace>
|
<RootNamespace>Modbus.Net.BigEndian3412</RootNamespace>
|
||||||
<PackageId>Modbus.Net.BigEndian3412</PackageId>
|
<PackageId>Modbus.Net.BigEndian3412</PackageId>
|
||||||
<Version>1.4.2</Version>
|
<Version>1.4.3</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>
|
||||||
|
|||||||
@@ -0,0 +1,158 @@
|
|||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Modbus.Net.CodeGenerator
|
||||||
|
{
|
||||||
|
[Generator]
|
||||||
|
public class BaseConnectorCodeGenerator : ISourceGenerator
|
||||||
|
{
|
||||||
|
public void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
var source = $@"
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Nito.AsyncEx;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Modbus.Net
|
||||||
|
{{
|
||||||
|
public abstract partial class BaseConnector : BaseConnector<byte[], byte[]>
|
||||||
|
{{
|
||||||
|
"
|
||||||
|
+ ConnectorWithControllerByteArrayCodeContent.Code("BaseConnector")
|
||||||
|
+ $@"
|
||||||
|
}}
|
||||||
|
}}";
|
||||||
|
context.AddSource("BaseConnectorContent.g.cs", source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize(GeneratorInitializationContext context)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Generator]
|
||||||
|
public class EventHandlerConnectorCodeGenerator : ISourceGenerator
|
||||||
|
{
|
||||||
|
public void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
var source = $@"
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Nito.AsyncEx;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Modbus.Net
|
||||||
|
{{
|
||||||
|
public abstract partial class EventHandlerConnector : EventHandlerConnector<byte[], byte[]>
|
||||||
|
{{
|
||||||
|
"
|
||||||
|
+ ConnectorWithControllerByteArrayCodeContent.Code("EventHandlerConnector")
|
||||||
|
+ $@"
|
||||||
|
}}
|
||||||
|
}}";
|
||||||
|
context.AddSource("EventHandlerConnectorContent.g.cs", source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize(GeneratorInitializationContext context)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ConnectorWithControllerByteArrayCodeContent
|
||||||
|
{
|
||||||
|
public static string Code(string className)
|
||||||
|
{
|
||||||
|
return new StringBuilder(@"
|
||||||
|
/// <summary>
|
||||||
|
/// 发送锁
|
||||||
|
/// </summary>
|
||||||
|
protected abstract AsyncLock Lock { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否为全双工
|
||||||
|
/// </summary>
|
||||||
|
public bool IsFullDuplex { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送超时时间
|
||||||
|
/// </summary>
|
||||||
|
protected abstract int TimeoutTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造器
|
||||||
|
/// </summary>
|
||||||
|
/// <param name=""timeoutTime"">发送超时时间</param>
|
||||||
|
/// <param name=""isFullDuplex"">是否为全双工</param>
|
||||||
|
protected {%0}(int timeoutTime = 10000, bool isFullDuplex = false)
|
||||||
|
{
|
||||||
|
IsFullDuplex = isFullDuplex;
|
||||||
|
if (timeoutTime < -1) timeoutTime = -1;
|
||||||
|
TimeoutTime = timeoutTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override async Task<byte[]> SendMsgAsync(byte[] message)
|
||||||
|
{
|
||||||
|
var ans = await SendMsgInner(message);
|
||||||
|
if (ans == null) return new byte[0];
|
||||||
|
return ans.ReceiveMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送内部
|
||||||
|
/// </summary>
|
||||||
|
/// <param name=""message"">发送的信息</param>
|
||||||
|
/// <param name=""repeat"">是否为重发消息</param>
|
||||||
|
/// <returns>发送信息的定义</returns>
|
||||||
|
protected async Task<MessageWaitingDef> SendMsgInner(byte[] message, bool repeat = false)
|
||||||
|
{
|
||||||
|
IDisposable asyncLock = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!Controller.IsSending)
|
||||||
|
{
|
||||||
|
Controller.SendStart();
|
||||||
|
}
|
||||||
|
var messageSendingdef = Controller.AddMessage(message);
|
||||||
|
if (messageSendingdef != null)
|
||||||
|
{
|
||||||
|
if (!IsFullDuplex)
|
||||||
|
{
|
||||||
|
asyncLock = await Lock.LockAsync();
|
||||||
|
}
|
||||||
|
var success = messageSendingdef.SendMutex.WaitOne(TimeoutTime);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
await SendMsgWithoutConfirm(message);
|
||||||
|
success = messageSendingdef.ReceiveMutex.WaitOne(TimeoutTime);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
if (!repeat && messageSendingdef.ReceiveMessage == null)
|
||||||
|
{
|
||||||
|
asyncLock?.Dispose();
|
||||||
|
return await SendMsgInner(message, true);
|
||||||
|
}
|
||||||
|
return messageSendingdef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Controller.ForceRemoveWaitingMessage(messageSendingdef);
|
||||||
|
}
|
||||||
|
logger.LogInformation(""Message is waiting in {0}. Cancel!"", ConnectionToken);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogError(e, ""Connector {0} Send Error."", ConnectionToken);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
asyncLock?.Dispose();
|
||||||
|
}
|
||||||
|
}").Replace("{%0}", className).ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<LangVersion>9.0</LangVersion>
|
||||||
|
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.6.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
10
Modbus.Net/Modbus.Net.HJ212/HJ212Controller.cs
Normal file
10
Modbus.Net/Modbus.Net.HJ212/HJ212Controller.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Modbus.Net.HJ212
|
||||||
|
{
|
||||||
|
public class HJ212Controller : FifoController
|
||||||
|
{
|
||||||
|
public HJ212Controller(string ip, int port) : base(int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FetchSleepTime")))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
101
Modbus.Net/Modbus.Net.HJ212/HJ212Machine.cs
Normal file
101
Modbus.Net/Modbus.Net.HJ212/HJ212Machine.cs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Modbus.Net.HJ212
|
||||||
|
{
|
||||||
|
public class HJ212Machine<TKey, TUnitKey> : BaseMachine<TKey, TUnitKey, string, string> where TKey : IEquatable<TKey>
|
||||||
|
where TUnitKey : IEquatable<TUnitKey>
|
||||||
|
{
|
||||||
|
private static readonly ILogger<HJ212Machine<TKey, TUnitKey>> logger = LogProvider.CreateLogger<HJ212Machine<TKey, TUnitKey>>();
|
||||||
|
|
||||||
|
private readonly int _maxErrorCount = 3;
|
||||||
|
|
||||||
|
protected string ST { get; }
|
||||||
|
|
||||||
|
protected string CN { get; }
|
||||||
|
|
||||||
|
protected string PW { get; }
|
||||||
|
|
||||||
|
protected string MN { get; }
|
||||||
|
|
||||||
|
private int ErrorCount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">设备的ID号</param>
|
||||||
|
/// <param name="connectionString">连接地址</param>
|
||||||
|
public HJ212Machine(TKey id, string connectionString, string st, string cn, string pw, string mn)
|
||||||
|
: base(id, null, true)
|
||||||
|
{
|
||||||
|
BaseUtility = new HJ212Utility(connectionString);
|
||||||
|
ST = st;
|
||||||
|
CN = cn;
|
||||||
|
PW = pw;
|
||||||
|
MN = mn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task<ReturnStruct<Dictionary<string, ReturnUnit<double>>>> GetDatasAsync(MachineDataType getDataType)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<ReturnStruct<bool>> SetDatasAsync(MachineDataType setDataType, Dictionary<string, double> values)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//检测并连接设备
|
||||||
|
if (!BaseUtility.IsConnected)
|
||||||
|
await BaseUtility.ConnectAsync();
|
||||||
|
//如果设备无法连接,终止
|
||||||
|
if (!BaseUtility.IsConnected) return new ReturnStruct<bool>()
|
||||||
|
{
|
||||||
|
Datas = false,
|
||||||
|
IsSuccess = false,
|
||||||
|
ErrorCode = -1,
|
||||||
|
ErrorMsg = "Connection Error"
|
||||||
|
};
|
||||||
|
|
||||||
|
//遍历每个要设置的值
|
||||||
|
Dictionary<string, string> formatValues = new Dictionary<string, string>();
|
||||||
|
foreach (var value in values)
|
||||||
|
{
|
||||||
|
//根据设置类型找到对应的地址描述
|
||||||
|
formatValues.Add(value.Key, value.Value.ToString());
|
||||||
|
}
|
||||||
|
var sendValues = new List<Dictionary<string, string>>() { formatValues };
|
||||||
|
//写入数据
|
||||||
|
await
|
||||||
|
BaseUtility.GetUtilityMethods<IUtilityMethodDatas>().SetDatasAsync("0", new object[] { ST, CN, PW, MN, sendValues, DateTime.Now });
|
||||||
|
|
||||||
|
//如果不保持连接,断开连接
|
||||||
|
if (!KeepConnect)
|
||||||
|
BaseUtility.Disconnect();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ErrorCount++;
|
||||||
|
logger.LogError(e, $"BaseMachine -> SetDatas, Id:{Id} Connection:{ConnectionToken} error. ErrorCount {ErrorCount}.");
|
||||||
|
|
||||||
|
if (ErrorCount >= _maxErrorCount)
|
||||||
|
Disconnect();
|
||||||
|
return new ReturnStruct<bool>()
|
||||||
|
{
|
||||||
|
Datas = false,
|
||||||
|
IsSuccess = false,
|
||||||
|
ErrorCode = -100,
|
||||||
|
ErrorMsg = "Unknown Exception"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return new ReturnStruct<bool>()
|
||||||
|
{
|
||||||
|
Datas = true,
|
||||||
|
IsSuccess = true,
|
||||||
|
ErrorCode = 0,
|
||||||
|
ErrorMsg = ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
130
Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs
Normal file
130
Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Modbus.Net.HJ212
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// HJ212协议
|
||||||
|
/// </summary>
|
||||||
|
public class HJ212Protocol : BaseProtocol
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
public HJ212Protocol(string ip)
|
||||||
|
: base(0, 0, Endian.BigEndianLsb)
|
||||||
|
{
|
||||||
|
ProtocolLinker = new HJ212ProtocolLinker(ip, int.Parse(ConfigurationReader.GetValueDirect("TCP:" + ip, "HJ212Port") ?? ConfigurationReader.GetValueDirect("TCP:Modbus", "HJ212Port") ?? "443"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 连接
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>是否连接成功</returns>
|
||||||
|
public override async Task<bool> ConnectAsync()
|
||||||
|
{
|
||||||
|
return await ProtocolLinker.ConnectAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region 写数据
|
||||||
|
/// <summary>
|
||||||
|
/// 写数据协议
|
||||||
|
/// </summary>
|
||||||
|
public class WriteRequestHJ212Protocol : ProtocolUnit<byte[], byte[]>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 从对象的参数数组格式化
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">非结构化的输入数据</param>
|
||||||
|
/// <returns>格式化后的字节流</returns>
|
||||||
|
public override byte[] Format(IInputStruct message)
|
||||||
|
{
|
||||||
|
var r_message = (WriteRequestHJ212InputStruct)message;
|
||||||
|
string formatMessage = "##0633";
|
||||||
|
formatMessage += "QN=" + r_message.QN + ";";
|
||||||
|
formatMessage += "ST=" + r_message.ST + ";";
|
||||||
|
formatMessage += "CN=" + r_message.CN + ";";
|
||||||
|
formatMessage += "PW=" + r_message.PW + ";";
|
||||||
|
formatMessage += "MN=" + r_message.MN + ";";
|
||||||
|
formatMessage += "CP=&&";
|
||||||
|
formatMessage += "DateTime=" + r_message.Datetime.ToString("yyyyMMddHHmmss") + ";";
|
||||||
|
foreach (var record in r_message.CP)
|
||||||
|
{
|
||||||
|
foreach (var data in record)
|
||||||
|
{
|
||||||
|
formatMessage += data.Key + "=" + data.Value + ",";
|
||||||
|
}
|
||||||
|
formatMessage = formatMessage[..^1];
|
||||||
|
formatMessage += ";";
|
||||||
|
}
|
||||||
|
formatMessage = formatMessage[..^1];
|
||||||
|
formatMessage += "&&";
|
||||||
|
return Encoding.ASCII.GetBytes(formatMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 把仪器返回的内容填充到输出结构中
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="messageBytes">返回数据的字节流</param>
|
||||||
|
/// <param name="pos">转换标记位</param>
|
||||||
|
/// <returns>结构化的输出数据</returns>
|
||||||
|
public override IOutputStruct Unformat(byte[] messageBytes, ref int pos)
|
||||||
|
{
|
||||||
|
return new WriteRequestHJ212OutputStruct(Encoding.ASCII.GetString(messageBytes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写数据输入
|
||||||
|
/// </summary>
|
||||||
|
public class WriteRequestHJ212InputStruct : IInputStruct
|
||||||
|
{
|
||||||
|
public WriteRequestHJ212InputStruct(string st, string cn, string pw, string mn, List<Dictionary<string, string>> cp, DateTime datetime)
|
||||||
|
{
|
||||||
|
ST = st;
|
||||||
|
CN = cn;
|
||||||
|
PW = pw;
|
||||||
|
MN = mn;
|
||||||
|
CP = cp;
|
||||||
|
Datetime = datetime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string QN => "20170101000926706";
|
||||||
|
|
||||||
|
public string ST { get; }
|
||||||
|
|
||||||
|
public string CN { get; }
|
||||||
|
|
||||||
|
public string PW { get; }
|
||||||
|
|
||||||
|
public string MN { get; }
|
||||||
|
|
||||||
|
public List<Dictionary<string, string>> CP { get; }
|
||||||
|
|
||||||
|
public DateTime Datetime { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写数据输出
|
||||||
|
/// </summary>
|
||||||
|
public class WriteRequestHJ212OutputStruct : IOutputStruct
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">读取的数据</param>
|
||||||
|
public WriteRequestHJ212OutputStruct(string value)
|
||||||
|
{
|
||||||
|
GetValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取的地址
|
||||||
|
/// </summary>
|
||||||
|
public string GetValue { get; private set; }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
22
Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinker.cs
Normal file
22
Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinker.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
namespace Modbus.Net.HJ212
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// HJ212协议连接器
|
||||||
|
/// </summary>
|
||||||
|
public class HJ212ProtocolLinker : TcpProtocolLinker
|
||||||
|
{
|
||||||
|
public HJ212ProtocolLinker(string ip, int port) : base(ip, port)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查接收的数据是否正确
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">接收协议的内容</param>
|
||||||
|
/// <returns>协议是否是正确的</returns>
|
||||||
|
public override bool? CheckRight(byte[] content)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Modbus.Net.HJ212
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Rtu协议字节伸缩
|
||||||
|
/// </summary>
|
||||||
|
public class HJ212ProtocolLinkerBytesExtend : IProtocolLinkerBytesExtend<byte[], byte[]>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 协议扩展,协议内容发送前调用
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">扩展前的原始协议内容</param>
|
||||||
|
/// <returns>扩展后的协议内容</returns>
|
||||||
|
public byte[] BytesExtend(byte[] content)
|
||||||
|
{
|
||||||
|
var crc = new byte[2];
|
||||||
|
//Modbus/Rtu协议扩张,增加CRC校验
|
||||||
|
var newFormat = new byte[content.Length + 4];
|
||||||
|
Crc16.GetInstance().GetCRC(content, ref crc);
|
||||||
|
Array.Copy(content, 0, newFormat, 0, content.Length);
|
||||||
|
string crcString = BitConverter.ToString(crc).Replace("-", string.Empty);
|
||||||
|
var crcCalc = Encoding.ASCII.GetBytes(crcString);
|
||||||
|
Array.Copy(crcCalc, 0, newFormat, newFormat.Length - 4, 4);
|
||||||
|
return newFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 协议收缩,协议内容接收后调用
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">收缩前的完整协议内容</param>
|
||||||
|
/// <returns>收缩后的协议内容</returns>
|
||||||
|
public byte[] BytesDecact(byte[] content)
|
||||||
|
{
|
||||||
|
//Modbus/Rtu协议收缩,抛弃后面2个字节的内容
|
||||||
|
var newContent = new byte[content.Length - 2];
|
||||||
|
Array.Copy(content, 0, newContent, 0, newContent.Length);
|
||||||
|
return newContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
61
Modbus.Net/Modbus.Net.HJ212/HJ212Utility.cs
Normal file
61
Modbus.Net/Modbus.Net.HJ212/HJ212Utility.cs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Modbus.Net.HJ212
|
||||||
|
{
|
||||||
|
public class HJ212Utility : BaseUtility<byte[], byte[], ProtocolUnit<byte[], byte[]>, PipeUnit>
|
||||||
|
{
|
||||||
|
private static readonly ILogger<HJ212Utility> logger = LogProvider.CreateLogger<HJ212Utility>();
|
||||||
|
|
||||||
|
public HJ212Utility(string connectionString) : base(0, 0)
|
||||||
|
{
|
||||||
|
ConnectionString = connectionString;
|
||||||
|
Wrapper = new HJ212Protocol(connectionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Endian Endian => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public override Task<ReturnStruct<byte[]>> GetDatasAsync(string startAddress, int getByteCount)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetConnectionType(int connectionType)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<ReturnStruct<bool>> SetDatasAsync(string startAddress, object[] setContents)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var writeRequestHJ212InputStruct =
|
||||||
|
new WriteRequestHJ212InputStruct((string)setContents[0], (string)setContents[1], (string)setContents[2], (string)setContents[3], (List<Dictionary<string, string>>)setContents[4], (DateTime)setContents[5]);
|
||||||
|
var writeRequestOpcOutputStruct =
|
||||||
|
await
|
||||||
|
Wrapper.SendReceiveAsync<WriteRequestHJ212OutputStruct>(Wrapper[typeof(WriteRequestHJ212Protocol)],
|
||||||
|
writeRequestHJ212InputStruct);
|
||||||
|
return new ReturnStruct<bool>
|
||||||
|
{
|
||||||
|
Datas = writeRequestOpcOutputStruct?.GetValue != null,
|
||||||
|
IsSuccess = writeRequestOpcOutputStruct?.GetValue != null,
|
||||||
|
ErrorCode = 0,
|
||||||
|
ErrorMsg = null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogError(e, $"OpcUtility -> SetDatas: {ConnectionString} error: {e.Message}");
|
||||||
|
return new ReturnStruct<bool>
|
||||||
|
{
|
||||||
|
Datas = false,
|
||||||
|
IsSuccess = false,
|
||||||
|
ErrorCode = -100,
|
||||||
|
ErrorMsg = e.Message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
Modbus.Net/Modbus.Net.HJ212/Modbus.Net.HJ212.csproj
Normal file
39
Modbus.Net/Modbus.Net.HJ212/Modbus.Net.HJ212.csproj
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFrameworks>net6.0</TargetFrameworks>
|
||||||
|
<LangVersion>10.0</LangVersion>
|
||||||
|
<AssemblyName>Modbus.Net.HJ212</AssemblyName>
|
||||||
|
<RootNamespace>Modbus.Net.HJ212</RootNamespace>
|
||||||
|
<PackageId>Modbus.Net.HJ212</PackageId>
|
||||||
|
<Version>1.4.3</Version>
|
||||||
|
<Authors>Chris L.(Luo Sheng)</Authors>
|
||||||
|
<Company>Hangzhou Delian Science Technology Co.,Ltd.</Company>
|
||||||
|
<Product>Modbus.Net.HJ212</Product>
|
||||||
|
<Description>Modbus.Net Modbus Implementation</Description>
|
||||||
|
<Copyright>Copyright 2023 Hangzhou Delian Science Technology Co.,Ltd.</Copyright>
|
||||||
|
<PackageProjectUrl>https://github.com/parallelbgls/Modbus.Net/tree/master/Modbus.Net/Modbus.Net.HJ212</PackageProjectUrl>
|
||||||
|
<RepositoryUrl>https://github.com/parallelbgls/Modbus.Net</RepositoryUrl>
|
||||||
|
<RepositoryType>git</RepositoryType>
|
||||||
|
<PackageTags>hardware communicate protocol modbus Delian</PackageTags>
|
||||||
|
<PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance>
|
||||||
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
|
<IncludeSymbols>True</IncludeSymbols>
|
||||||
|
<IncludeSource>True</IncludeSource>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<DocumentationFile>bin\Debug\Modbus.Net.HJ212.xml</DocumentationFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Modbus.Net\Modbus.Net.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="README.md" Pack="true" PackagePath=""/>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
7
Modbus.Net/Modbus.Net.HJ212/README.md
Normal file
7
Modbus.Net/Modbus.Net.HJ212/README.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Modbus.Net.HJ212
|
||||||
|
===================
|
||||||
|
[](https://www.nuget.org/packages/Modbus.Net.HJ212/)
|
||||||
|
|
||||||
|
HJ212 Implementation of Modbus.Net
|
||||||
|
|
||||||
|
Doc has been moved to wiki.
|
||||||
@@ -6,7 +6,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.2</Version>
|
<Version>1.4.3</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>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<AssemblyName>Modbus.Net.Modbus.SelfDefinedSample</AssemblyName>
|
<AssemblyName>Modbus.Net.Modbus.SelfDefinedSample</AssemblyName>
|
||||||
<RootNamespace>Modbus.Net.Modbus.SelfDefinedSample</RootNamespace>
|
<RootNamespace>Modbus.Net.Modbus.SelfDefinedSample</RootNamespace>
|
||||||
<PackageId>Modbus.Net.Modbus.SelfDefinedSample</PackageId>
|
<PackageId>Modbus.Net.Modbus.SelfDefinedSample</PackageId>
|
||||||
<Version>1.4.2</Version>
|
<Version>1.4.3</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>
|
||||||
|
|||||||
@@ -6,7 +6,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.2</Version>
|
<Version>1.4.3</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>
|
||||||
|
|||||||
@@ -24,21 +24,6 @@ namespace Modbus.Net.Modbus
|
|||||||
public ModbusAsciiInTcpProtocolLinker(string ip, int port)
|
public ModbusAsciiInTcpProtocolLinker(string ip, int port)
|
||||||
: base(ip, port)
|
: base(ip, port)
|
||||||
{
|
{
|
||||||
((IConnectorWithController<byte[], byte[]>)BaseConnector).AddController(new FifoController(int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FetchSleepTime")),
|
|
||||||
lengthCalc: content =>
|
|
||||||
{
|
|
||||||
if (content[0] != 0x3a) return 0;
|
|
||||||
for (int i = 1; i < content.Length; i++)
|
|
||||||
{
|
|
||||||
if (content[i - 1] == 0x0D && content[i] == 0x0A) return i + 1;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
},
|
|
||||||
checkRightFunc: ContentCheck.LrcCheckRight,
|
|
||||||
waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null
|
|
||||||
? int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount"))
|
|
||||||
: null
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -24,22 +24,6 @@ namespace Modbus.Net.Modbus
|
|||||||
public ModbusAsciiInUdpProtocolLinker(string ip, int port)
|
public ModbusAsciiInUdpProtocolLinker(string ip, int port)
|
||||||
: base(ip, port)
|
: base(ip, port)
|
||||||
{
|
{
|
||||||
((IConnectorWithController<byte[], byte[]>)BaseConnector).AddController(new FifoController(int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FetchSleepTime")),
|
|
||||||
lengthCalc: content =>
|
|
||||||
{
|
|
||||||
if (content[0] != 0x3a) return 0;
|
|
||||||
for (int i = 1; i < content.Length; i++)
|
|
||||||
{
|
|
||||||
if (content[i - 1] == 0x0D && content[i] == 0x0A)
|
|
||||||
return i + 1;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
},
|
|
||||||
checkRightFunc: ContentCheck.LrcCheckRight,
|
|
||||||
waitingListMaxCount: ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount") != null
|
|
||||||
? int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount"))
|
|
||||||
: null
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -15,22 +15,6 @@ namespace Modbus.Net.Modbus
|
|||||||
public ModbusAsciiProtocolLinker(string com, int slaveAddress)
|
public ModbusAsciiProtocolLinker(string com, int slaveAddress)
|
||||||
: base(com, slaveAddress)
|
: base(com, slaveAddress)
|
||||||
{
|
{
|
||||||
((IConnectorWithController<byte[], byte[]>)BaseConnector).AddController(new FifoController(
|
|
||||||
int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime")),
|
|
||||||
lengthCalc: content =>
|
|
||||||
{
|
|
||||||
if (content[0] != 0x3a) return 0;
|
|
||||||
for (int i = 1; i < content.Length; i++)
|
|
||||||
{
|
|
||||||
if (content[i - 1] == 0x0D && content[i] == 0x0A) return i + 1;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
},
|
|
||||||
checkRightFunc: ContentCheck.LrcCheckRight,
|
|
||||||
waitingListMaxCount: ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount") != null ?
|
|
||||||
int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount")) :
|
|
||||||
null
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
238
Modbus.Net/Modbus.Net.Modbus/ModbusController.cs
Normal file
238
Modbus.Net/Modbus.Net.Modbus/ModbusController.cs
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Modbus.Net.Modbus
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Modbus长度计算
|
||||||
|
/// </summary>
|
||||||
|
public static class ModbusLengthCalc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Modbus Ascii协议长度计算
|
||||||
|
/// </summary>
|
||||||
|
public static Func<byte[], int> ModbusAsciiLengthCalc => content =>
|
||||||
|
{
|
||||||
|
if (content[0] != 0x3a) return 0;
|
||||||
|
for (int i = 1; i < content.Length; i++)
|
||||||
|
{
|
||||||
|
if (content[i - 1] == 0x0D && content[i] == 0x0A) return i + 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Modbus Rtu协议长度计算
|
||||||
|
/// </summary>
|
||||||
|
public static Func<byte[], int> ModbusRtuLengthCalc => content =>
|
||||||
|
{
|
||||||
|
if (content[1] > 128) return 5;
|
||||||
|
else if (content[1] == 5 || content[1] == 6 || content[1] == 8 || content[1] == 11 || content[1] == 15 || content[1] == 16) return 8;
|
||||||
|
else if (content[1] == 7) return 5;
|
||||||
|
else if (content[1] == 22) return 10;
|
||||||
|
else return DuplicateWithCount.GetDuplcateFunc(new List<int> { 2 }, 5).Invoke(content);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Modbus Ascii协议控制器
|
||||||
|
/// </summary>
|
||||||
|
public class ModbusAsciiController : FifoController
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="com">串口</param>
|
||||||
|
/// <param name="slaveAddress">从站号</param>
|
||||||
|
public ModbusAsciiController(string com, int slaveAddress) : base(
|
||||||
|
int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime")),
|
||||||
|
lengthCalc: ModbusLengthCalc.ModbusAsciiLengthCalc,
|
||||||
|
checkRightFunc: ContentCheck.LrcCheckRight,
|
||||||
|
waitingListMaxCount: ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount") != null ?
|
||||||
|
int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount")) :
|
||||||
|
null
|
||||||
|
)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Modbus Ascii in Tcp协议控制器
|
||||||
|
/// </summary>
|
||||||
|
public class ModbusAsciiInTcpController : FifoController
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip">ip地址</param>
|
||||||
|
/// <param name="port">端口号</param>
|
||||||
|
public ModbusAsciiInTcpController(string ip, int port) : base(int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FetchSleepTime")),
|
||||||
|
lengthCalc: ModbusLengthCalc.ModbusAsciiLengthCalc,
|
||||||
|
checkRightFunc: ContentCheck.LrcCheckRight,
|
||||||
|
waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null
|
||||||
|
? int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount"))
|
||||||
|
: null
|
||||||
|
)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Modbus Ascii in Udp协议控制器
|
||||||
|
/// </summary>
|
||||||
|
public class ModbusAsciiInUdpController : FifoController
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip">ip地址</param>
|
||||||
|
/// <param name="port">端口号</param>
|
||||||
|
public ModbusAsciiInUdpController(string ip, int port) : base(int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FetchSleepTime")),
|
||||||
|
lengthCalc: ModbusLengthCalc.ModbusAsciiLengthCalc,
|
||||||
|
checkRightFunc: ContentCheck.LrcCheckRight,
|
||||||
|
waitingListMaxCount: ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount") != null
|
||||||
|
? int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount"))
|
||||||
|
: null
|
||||||
|
)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Modbus Rtu协议控制器
|
||||||
|
/// </summary>
|
||||||
|
public class ModbusRtuController : FifoController
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="com">串口</param>
|
||||||
|
/// <param name="slaveAddress">从站号</param>
|
||||||
|
public ModbusRtuController(string com, int slaveAddress) : base(
|
||||||
|
int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime")),
|
||||||
|
lengthCalc: ModbusLengthCalc.ModbusRtuLengthCalc,
|
||||||
|
checkRightFunc: ContentCheck.Crc16CheckRight,
|
||||||
|
waitingListMaxCount: ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount") != null ?
|
||||||
|
int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount")) :
|
||||||
|
null
|
||||||
|
)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Modbus Rtu in Tcp协议控制器
|
||||||
|
/// </summary>
|
||||||
|
public class ModbusRtuInTcpController : FifoController
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip">ip地址</param>
|
||||||
|
/// <param name="port">端口号</param>
|
||||||
|
public ModbusRtuInTcpController(string ip, int port) : base(
|
||||||
|
int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FetchSleepTime")),
|
||||||
|
lengthCalc: ModbusLengthCalc.ModbusRtuLengthCalc,
|
||||||
|
checkRightFunc: ContentCheck.Crc16CheckRight,
|
||||||
|
waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ?
|
||||||
|
int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) :
|
||||||
|
null
|
||||||
|
)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Modbus Rtu in Udp协议控制器
|
||||||
|
/// </summary>
|
||||||
|
public class ModbusRtuInUdpController : FifoController
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip">ip地址</param>
|
||||||
|
/// <param name="port">端口号</param>
|
||||||
|
public ModbusRtuInUdpController(string ip, int port) : base(
|
||||||
|
int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FetchSleepTime")),
|
||||||
|
lengthCalc: ModbusLengthCalc.ModbusRtuLengthCalc,
|
||||||
|
checkRightFunc: ContentCheck.Crc16CheckRight,
|
||||||
|
waitingListMaxCount: ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount") != null ?
|
||||||
|
int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount")) :
|
||||||
|
null
|
||||||
|
)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Modbus Tcp协议控制器
|
||||||
|
/// </summary>
|
||||||
|
public class ModbusTcpController : ModbusEthMatchDirectlySendController
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip">ip地址</param>
|
||||||
|
/// <param name="port">端口号</param>
|
||||||
|
public ModbusTcpController(string ip, int port) : base(
|
||||||
|
new ICollection<(int, int)>[] { new List<(int, int)> { (0, 0), (1, 1) } },
|
||||||
|
lengthCalc: DuplicateWithCount.GetDuplcateFunc(new List<int> { 4, 5 }, 6),
|
||||||
|
waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ?
|
||||||
|
int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) :
|
||||||
|
null
|
||||||
|
)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Modbus Udp协议控制器
|
||||||
|
/// </summary>
|
||||||
|
public class ModbusUdpController : ModbusEthMatchDirectlySendController
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip">ip地址</param>
|
||||||
|
/// <param name="port">端口号</param>
|
||||||
|
public ModbusUdpController(string ip, int port) : base(
|
||||||
|
new ICollection<(int, int)>[] { new List<(int, int)> { (0, 0), (1, 1) } },
|
||||||
|
lengthCalc: DuplicateWithCount.GetDuplcateFunc(new List<int> { 4, 5 }, 6),
|
||||||
|
waitingListMaxCount: ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount") != null ?
|
||||||
|
int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount")) :
|
||||||
|
null
|
||||||
|
)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 匹配控制器,载入队列后直接发送
|
||||||
|
/// </summary>
|
||||||
|
public class ModbusEthMatchDirectlySendController : MatchDirectlySendController
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ModbusEthMatchDirectlySendController(ICollection<(int, int)>[] keyMatches,
|
||||||
|
Func<byte[], int> lengthCalc = null, Func<byte[], bool?> checkRightFunc = null, int? waitingListMaxCount = null) : base(keyMatches,
|
||||||
|
lengthCalc, checkRightFunc, waitingListMaxCount)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override MessageWaitingDef GetMessageFromWaitingList(byte[] receiveMessage)
|
||||||
|
{
|
||||||
|
MessageWaitingDef ans;
|
||||||
|
if (receiveMessage[0] == 0 && receiveMessage[1] == 0)
|
||||||
|
{
|
||||||
|
lock (WaitingMessages)
|
||||||
|
{
|
||||||
|
ans = WaitingMessages.FirstOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var returnKey = GetKeyFromMessage(receiveMessage);
|
||||||
|
lock (WaitingMessages)
|
||||||
|
{
|
||||||
|
ans = WaitingMessages.FirstOrDefault(p => returnKey.HasValue && p.Key == returnKey.Value.Item2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
namespace Modbus.Net.Modbus
|
||||||
|
|
||||||
namespace Modbus.Net.Modbus
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Modbus/Rtu协议连接器Tcp透传
|
/// Modbus/Rtu协议连接器Tcp透传
|
||||||
@@ -24,19 +22,6 @@ namespace Modbus.Net.Modbus
|
|||||||
public ModbusRtuInTcpProtocolLinker(string ip, int port)
|
public ModbusRtuInTcpProtocolLinker(string ip, int port)
|
||||||
: base(ip, port)
|
: base(ip, port)
|
||||||
{
|
{
|
||||||
((IConnectorWithController<byte[], byte[]>)BaseConnector).AddController(new FifoController(
|
|
||||||
int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FetchSleepTime")),
|
|
||||||
lengthCalc: content =>
|
|
||||||
{
|
|
||||||
if (content[1] > 128) return 5;
|
|
||||||
else if (content[1] == 5 || content[1] == 6 || content[1] == 15 || content[1] == 16 || content[1] == 21) return 8;
|
|
||||||
else return DuplicateWithCount.GetDuplcateFunc(new List<int> { 2 }, 5).Invoke(content);
|
|
||||||
},
|
|
||||||
checkRightFunc: ContentCheck.Crc16CheckRight,
|
|
||||||
waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ?
|
|
||||||
int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) :
|
|
||||||
null
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
namespace Modbus.Net.Modbus
|
||||||
|
|
||||||
namespace Modbus.Net.Modbus
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Modbus/Rtu协议连接器Udp透传
|
/// Modbus/Rtu协议连接器Udp透传
|
||||||
@@ -24,19 +22,6 @@ namespace Modbus.Net.Modbus
|
|||||||
public ModbusRtuInUdpProtocolLinker(string ip, int port)
|
public ModbusRtuInUdpProtocolLinker(string ip, int port)
|
||||||
: base(ip, port)
|
: base(ip, port)
|
||||||
{
|
{
|
||||||
((IConnectorWithController<byte[], byte[]>)BaseConnector).AddController(new FifoController(
|
|
||||||
int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FetchSleepTime")),
|
|
||||||
lengthCalc: content =>
|
|
||||||
{
|
|
||||||
if (content[1] > 128) return 5;
|
|
||||||
else if (content[1] == 5 || content[1] == 6 || content[1] == 15 || content[1] == 16 || content[1] == 21) return 8;
|
|
||||||
else return DuplicateWithCount.GetDuplcateFunc(new List<int> { 2 }, 5).Invoke(content);
|
|
||||||
},
|
|
||||||
checkRightFunc: ContentCheck.Crc16CheckRight,
|
|
||||||
waitingListMaxCount: ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount") != null ?
|
|
||||||
int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount")) :
|
|
||||||
null
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
namespace Modbus.Net.Modbus
|
||||||
|
|
||||||
namespace Modbus.Net.Modbus
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Modbus/Rtu协议连接器
|
/// Modbus/Rtu协议连接器
|
||||||
@@ -15,21 +13,6 @@ namespace Modbus.Net.Modbus
|
|||||||
public ModbusRtuProtocolLinker(string com, int slaveAddress)
|
public ModbusRtuProtocolLinker(string com, int slaveAddress)
|
||||||
: base(com, slaveAddress)
|
: base(com, slaveAddress)
|
||||||
{
|
{
|
||||||
((IConnectorWithController<byte[], byte[]>)BaseConnector).AddController(new FifoController(
|
|
||||||
int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime")),
|
|
||||||
lengthCalc: content =>
|
|
||||||
{
|
|
||||||
if (content[1] > 128) return 5;
|
|
||||||
else if (content[1] == 5 || content[1] == 6 || content[1] == 8 || content[1] == 11 || content[1] == 15 || content[1] == 16) return 8;
|
|
||||||
else if (content[1] == 7) return 5;
|
|
||||||
else if (content[1] == 22) return 10;
|
|
||||||
else return DuplicateWithCount.GetDuplcateFunc(new List<int> { 2 }, 5).Invoke(content);
|
|
||||||
},
|
|
||||||
checkRightFunc: ContentCheck.Crc16CheckRight,
|
|
||||||
waitingListMaxCount: ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount") != null ?
|
|
||||||
int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount")) :
|
|
||||||
null
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Modbus.Net
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 匹配控制器,载入队列后直接发送
|
|
||||||
/// </summary>
|
|
||||||
public class ModbusTcpMatchDirectlySendController : MatchDirectlySendController
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public ModbusTcpMatchDirectlySendController(ICollection<(int, int)>[] keyMatches,
|
|
||||||
Func<byte[], int> lengthCalc = null, Func<byte[], bool?> checkRightFunc = null, int? waitingListMaxCount = null) : base(keyMatches,
|
|
||||||
lengthCalc, checkRightFunc, waitingListMaxCount)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override MessageWaitingDef GetMessageFromWaitingList(byte[] receiveMessage)
|
|
||||||
{
|
|
||||||
MessageWaitingDef ans;
|
|
||||||
if (receiveMessage[0] == 0 && receiveMessage[1] == 0)
|
|
||||||
{
|
|
||||||
lock (WaitingMessages)
|
|
||||||
{
|
|
||||||
ans = WaitingMessages.FirstOrDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var returnKey = GetKeyFromMessage(receiveMessage);
|
|
||||||
lock (WaitingMessages)
|
|
||||||
{
|
|
||||||
ans = WaitingMessages.FirstOrDefault(p => returnKey.HasValue && p.Key == returnKey.Value.Item2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ans;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
namespace Modbus.Net.Modbus
|
||||||
|
|
||||||
namespace Modbus.Net.Modbus
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Modbus/Tcp协议连接器
|
/// Modbus/Tcp协议连接器
|
||||||
@@ -23,13 +21,6 @@ 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)
|
||||||
{
|
{
|
||||||
((IConnectorWithController<byte[], byte[]>)BaseConnector).AddController(new ModbusTcpMatchDirectlySendController(
|
|
||||||
new ICollection<(int, int)>[] { new List<(int, int)> { (0, 0), (1, 1) } },
|
|
||||||
lengthCalc: DuplicateWithCount.GetDuplcateFunc(new List<int> { 4, 5 }, 6),
|
|
||||||
waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ?
|
|
||||||
int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) :
|
|
||||||
null
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
namespace Modbus.Net.Modbus
|
||||||
|
|
||||||
namespace Modbus.Net.Modbus
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Modbus/Udp协议连接器
|
/// Modbus/Udp协议连接器
|
||||||
@@ -23,13 +21,6 @@ namespace Modbus.Net.Modbus
|
|||||||
/// <param name="port">端口</param>
|
/// <param name="port">端口</param>
|
||||||
public ModbusUdpProtocolLinker(string ip, int port) : base(ip, port)
|
public ModbusUdpProtocolLinker(string ip, int port) : base(ip, port)
|
||||||
{
|
{
|
||||||
((IConnectorWithController<byte[], byte[]>)BaseConnector).AddController(new ModbusTcpMatchDirectlySendController(
|
|
||||||
new ICollection<(int, int)>[] { new List<(int, int)> { (0, 0), (1, 1) } },
|
|
||||||
lengthCalc: DuplicateWithCount.GetDuplcateFunc(new List<int> { 4, 5 }, 6),
|
|
||||||
waitingListMaxCount: ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount") != null ?
|
|
||||||
int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount")) :
|
|
||||||
null
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -6,7 +6,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.2</Version>
|
<Version>1.4.3</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>
|
||||||
|
|||||||
@@ -6,7 +6,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.2</Version>
|
<Version>1.4.3</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>
|
||||||
|
|||||||
53
Modbus.Net/Modbus.Net.Siemens/SiemensController.cs
Normal file
53
Modbus.Net/Modbus.Net.Siemens/SiemensController.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Modbus.Net.Siemens
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 西门子Ppi协议控制器
|
||||||
|
/// </summary>
|
||||||
|
public class SiemensPpiController : FifoController
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="com">串口</param>
|
||||||
|
/// <param name="slaveAddress">从站号</param>
|
||||||
|
public SiemensPpiController(string com, int slaveAddress) : base(
|
||||||
|
int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime")),
|
||||||
|
lengthCalc: content =>
|
||||||
|
{
|
||||||
|
if (content[0] == 0x10)
|
||||||
|
return 6;
|
||||||
|
else if (content[0] == 0xE5)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return DuplicateWithCount.GetDuplcateFunc(new List<int> { 1 }, 6)(content);
|
||||||
|
},
|
||||||
|
checkRightFunc: ContentCheck.FcsCheckRight,
|
||||||
|
waitingListMaxCount: ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount") != null ?
|
||||||
|
int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount")) :
|
||||||
|
null
|
||||||
|
)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 西门子Tcp协议控制器
|
||||||
|
/// </summary>
|
||||||
|
public class SiemensTcpController : MatchDirectlySendController
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip">ip地址</param>
|
||||||
|
/// <param name="port">端口号</param>
|
||||||
|
public SiemensTcpController(string ip, int port) : base(
|
||||||
|
new ICollection<(int, int)>[] { new List<(int, int)> { (11, 11), (12, 12) } },
|
||||||
|
lengthCalc: DuplicateWithCount.GetDuplcateFunc(new List<int> { 2, 3 }, 0),
|
||||||
|
waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ?
|
||||||
|
int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) :
|
||||||
|
null
|
||||||
|
)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO.Ports;
|
using System.IO.Ports;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -23,22 +22,6 @@ namespace Modbus.Net.Siemens
|
|||||||
: null
|
: null
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
((IConnectorWithController<byte[], byte[]>)BaseConnector).AddController(new FifoController(
|
|
||||||
int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime")),
|
|
||||||
lengthCalc: content =>
|
|
||||||
{
|
|
||||||
if (content[0] == 0x10)
|
|
||||||
return 6;
|
|
||||||
else if (content[0] == 0xE5)
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return DuplicateWithCount.GetDuplcateFunc(new List<int> { 1 }, 6)(content);
|
|
||||||
},
|
|
||||||
checkRightFunc: ContentCheck.FcsCheckRight,
|
|
||||||
waitingListMaxCount: ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount") != null ?
|
|
||||||
int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount")) :
|
|
||||||
null
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Modbus.Net.Siemens
|
namespace Modbus.Net.Siemens
|
||||||
{
|
{
|
||||||
@@ -25,13 +24,6 @@ namespace Modbus.Net.Siemens
|
|||||||
public SiemensTcpProtocolLinker(string ip, int port)
|
public SiemensTcpProtocolLinker(string ip, int port)
|
||||||
: base(ip, port)
|
: base(ip, port)
|
||||||
{
|
{
|
||||||
((IConnectorWithController<byte[], byte[]>)BaseConnector).AddController(new MatchDirectlySendController(
|
|
||||||
new ICollection<(int, int)>[] { new List<(int, int)> { (11, 11), (12, 12) } },
|
|
||||||
lengthCalc: DuplicateWithCount.GetDuplcateFunc(new List<int> { 2, 3 }, 0),
|
|
||||||
waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ?
|
|
||||||
int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) :
|
|
||||||
null
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -45,6 +45,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Technosoftware.DaAeHdaClien
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Technosoftware.DaAeHdaClient.Com", "..\Technosoftware\DaAeHdaClient.Com\Technosoftware.DaAeHdaClient.Com.csproj", "{ACAF0A16-FC51-4369-BFA8-484FF20707D7}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Technosoftware.DaAeHdaClient.Com", "..\Technosoftware\DaAeHdaClient.Com\Technosoftware.DaAeHdaClient.Com.csproj", "{ACAF0A16-FC51-4369-BFA8-484FF20707D7}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Modbus.Net.HJ212", "Modbus.Net.HJ212\Modbus.Net.HJ212.csproj", "{057644EF-1407-4C2B-808A-AEF0F2979EA8}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Modbus.Net.CodeGenerator", "Modbus.Net.CodeGenerator\Modbus.Net.CodeGenerator.csproj", "{D3210531-BA79-49B2-9F99-09FD0E1627B6}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MachineJob.CodeGenerator", "..\Samples\MachineJob.CodeGenerator\MachineJob.CodeGenerator.csproj", "{7337BC9A-ED07-463D-8FCD-A82896CEC6BE}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -181,6 +187,30 @@ Global
|
|||||||
{ACAF0A16-FC51-4369-BFA8-484FF20707D7}.Release|Any CPU.Build.0 = Release|Any CPU
|
{ACAF0A16-FC51-4369-BFA8-484FF20707D7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{ACAF0A16-FC51-4369-BFA8-484FF20707D7}.Release|x64.ActiveCfg = Release|x64
|
{ACAF0A16-FC51-4369-BFA8-484FF20707D7}.Release|x64.ActiveCfg = Release|x64
|
||||||
{ACAF0A16-FC51-4369-BFA8-484FF20707D7}.Release|x64.Build.0 = Release|x64
|
{ACAF0A16-FC51-4369-BFA8-484FF20707D7}.Release|x64.Build.0 = Release|x64
|
||||||
|
{057644EF-1407-4C2B-808A-AEF0F2979EA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{057644EF-1407-4C2B-808A-AEF0F2979EA8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{057644EF-1407-4C2B-808A-AEF0F2979EA8}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{057644EF-1407-4C2B-808A-AEF0F2979EA8}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{057644EF-1407-4C2B-808A-AEF0F2979EA8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{057644EF-1407-4C2B-808A-AEF0F2979EA8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{057644EF-1407-4C2B-808A-AEF0F2979EA8}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{057644EF-1407-4C2B-808A-AEF0F2979EA8}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{D3210531-BA79-49B2-9F99-09FD0E1627B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D3210531-BA79-49B2-9F99-09FD0E1627B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D3210531-BA79-49B2-9F99-09FD0E1627B6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{D3210531-BA79-49B2-9F99-09FD0E1627B6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{D3210531-BA79-49B2-9F99-09FD0E1627B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D3210531-BA79-49B2-9F99-09FD0E1627B6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D3210531-BA79-49B2-9F99-09FD0E1627B6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{D3210531-BA79-49B2-9F99-09FD0E1627B6}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Release|x64.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -191,6 +221,7 @@ Global
|
|||||||
{1857DA63-3335-428F-84D8-1FA4F8178643} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A}
|
{1857DA63-3335-428F-84D8-1FA4F8178643} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A}
|
||||||
{AA3A42D2-0502-41D3-929A-BAB729DF07D6} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A}
|
{AA3A42D2-0502-41D3-929A-BAB729DF07D6} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A}
|
||||||
{414956B8-DBD4-414C-ABD3-565580739646} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A}
|
{414956B8-DBD4-414C-ABD3-565580739646} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A}
|
||||||
|
{7337BC9A-ED07-463D-8FCD-A82896CEC6BE} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {AF00D64E-3C70-474A-8A81-E9E48017C4B5}
|
SolutionGuid = {AF00D64E-3C70-474A-8A81-E9E48017C4B5}
|
||||||
|
|||||||
@@ -1,102 +1,12 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Nito.AsyncEx;
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Modbus.Net
|
namespace Modbus.Net
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public abstract class BaseConnector : BaseConnector<byte[], byte[]>
|
public abstract partial class BaseConnector : BaseConnector<byte[], byte[]>
|
||||||
{
|
{
|
||||||
private static readonly ILogger<BaseConnector> logger = LogProvider.CreateLogger<BaseConnector>();
|
private static readonly ILogger<EventHandlerConnector> logger = LogProvider.CreateLogger<EventHandlerConnector>();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 发送锁
|
|
||||||
/// </summary>
|
|
||||||
protected abstract AsyncLock Lock { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否为全双工
|
|
||||||
/// </summary>
|
|
||||||
public bool IsFullDuplex { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 发送超时时间
|
|
||||||
/// </summary>
|
|
||||||
protected abstract int TimeoutTime { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 构造器
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="timeoutTime">发送超时时间</param>
|
|
||||||
/// <param name="isFullDuplex">是否为全双工</param>
|
|
||||||
protected BaseConnector(int timeoutTime = 10000, bool isFullDuplex = false)
|
|
||||||
{
|
|
||||||
IsFullDuplex = isFullDuplex;
|
|
||||||
if (timeoutTime < -1) timeoutTime = -1;
|
|
||||||
TimeoutTime = timeoutTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override async Task<byte[]> SendMsgAsync(byte[] message)
|
|
||||||
{
|
|
||||||
var ans = await SendMsgInner(message);
|
|
||||||
if (ans == null) return new byte[0];
|
|
||||||
return ans.ReceiveMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 发送内部
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">发送的信息</param>
|
|
||||||
/// <param name="repeat">是否为重发消息</param>
|
|
||||||
/// <returns>发送信息的定义</returns>
|
|
||||||
protected async Task<MessageWaitingDef> SendMsgInner(byte[] message, bool repeat = false)
|
|
||||||
{
|
|
||||||
IDisposable asyncLock = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!Controller.IsSending)
|
|
||||||
{
|
|
||||||
Controller.SendStart();
|
|
||||||
}
|
|
||||||
var messageSendingdef = Controller.AddMessage(message);
|
|
||||||
if (messageSendingdef != null)
|
|
||||||
{
|
|
||||||
if (!IsFullDuplex)
|
|
||||||
{
|
|
||||||
asyncLock = await Lock.LockAsync();
|
|
||||||
}
|
|
||||||
var success = messageSendingdef.SendMutex.WaitOne(TimeoutTime);
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
await SendMsgWithoutConfirm(message);
|
|
||||||
success = messageSendingdef.ReceiveMutex.WaitOne(TimeoutTime);
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
if (!repeat && messageSendingdef.ReceiveMessage == null)
|
|
||||||
{
|
|
||||||
asyncLock?.Dispose();
|
|
||||||
return await SendMsgInner(message, true);
|
|
||||||
}
|
|
||||||
return messageSendingdef;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Controller.ForceRemoveWaitingMessage(messageSendingdef);
|
|
||||||
}
|
|
||||||
logger.LogInformation("Message is waiting in {0}. Cancel!", ConnectionToken);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
logger.LogError(e, "Connector {0} Send Error.", ConnectionToken);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
asyncLock?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -82,10 +82,11 @@ namespace Modbus.Net
|
|||||||
/// 获取线程
|
/// 获取线程
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Task _receiveThread;
|
private Task _receiveThread;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取线程关闭
|
/// 终止获取线程
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool _taskCancel = false;
|
private CancellationTokenSource _receiveThreadCancel;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 缓冲的字节流
|
/// 缓冲的字节流
|
||||||
@@ -276,24 +277,23 @@ namespace Modbus.Net
|
|||||||
// Release managed resources
|
// Release managed resources
|
||||||
}
|
}
|
||||||
// Release unmanaged resources
|
// Release unmanaged resources
|
||||||
if (SerialPort != null)
|
Controller?.SendStop();
|
||||||
|
ReceiveMsgThreadStop();
|
||||||
|
Linkers?.Remove((_slave, _com));
|
||||||
|
logger.LogInformation("Com connector {ConnectionToken} Removed", _com);
|
||||||
|
if (Linkers?.Count(p => p.Item2 == _com) == 0)
|
||||||
{
|
{
|
||||||
Linkers.Remove((_slave, _com));
|
if (SerialPort?.IsOpen == true)
|
||||||
logger.LogInformation("Com connector {ConnectionToken} Removed", _com);
|
{
|
||||||
if (Linkers.Count(p => p.Item2 == _com) == 0)
|
SerialPort?.Close();
|
||||||
|
}
|
||||||
|
SerialPort?.Dispose();
|
||||||
|
logger.LogInformation("Com interface {Com} Disposed", _com);
|
||||||
|
if (Connectors.ContainsKey(_com))
|
||||||
{
|
{
|
||||||
if (SerialPort.IsOpen)
|
|
||||||
{
|
|
||||||
SerialPort.Close();
|
|
||||||
}
|
|
||||||
SerialPort.Dispose();
|
|
||||||
logger.LogInformation("Com interface {Com} Disposed", _com);
|
|
||||||
Controller.SendStop();
|
|
||||||
Controllers.Remove(_com);
|
|
||||||
Connectors[_com] = null;
|
Connectors[_com] = null;
|
||||||
Connectors.Remove(_com);
|
Connectors.Remove(_com);
|
||||||
ReceiveMsgThreadStop();
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,7 +366,7 @@ namespace Modbus.Net
|
|||||||
{
|
{
|
||||||
lock (SerialPort)
|
lock (SerialPort)
|
||||||
{
|
{
|
||||||
_taskCancel = false;
|
ReceiveMsgThreadStop();
|
||||||
SerialPort.Open();
|
SerialPort.Open();
|
||||||
ReceiveMsgThreadStart();
|
ReceiveMsgThreadStart();
|
||||||
Controller.SendStart();
|
Controller.SendStart();
|
||||||
@@ -484,7 +484,7 @@ namespace Modbus.Net
|
|||||||
message.Length);
|
message.Length);
|
||||||
logger.LogDebug(
|
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)
|
||||||
{
|
{
|
||||||
@@ -495,20 +495,57 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void ReceiveMsgThreadStart()
|
protected override async void ReceiveMsgThreadStart()
|
||||||
{
|
{
|
||||||
_receiveThread = Task.Run(ReceiveMessage);
|
if (_receiveThread == null)
|
||||||
|
{
|
||||||
|
_receiveThreadCancel = new CancellationTokenSource();
|
||||||
|
_receiveThread = Task.Run(async ()=>await ReceiveMessage(_receiveThreadCancel.Token), _receiveThreadCancel.Token);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _receiveThread;
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{ }
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_receiveThreadCancel.Dispose();
|
||||||
|
_receiveThreadCancel = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void ReceiveMsgThreadStop()
|
protected override void ReceiveMsgThreadStop()
|
||||||
{
|
{
|
||||||
_taskCancel = true;
|
_receiveThreadCancel?.Cancel();
|
||||||
|
if (_receiveThread != null)
|
||||||
|
{
|
||||||
|
while (!_receiveThread.IsCanceled)
|
||||||
|
{
|
||||||
|
Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
_receiveThread.Dispose();
|
||||||
|
_receiveThread = null;
|
||||||
|
}
|
||||||
|
CacheClear();
|
||||||
|
Controller?.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ReceiveMessage()
|
private void CacheClear()
|
||||||
{
|
{
|
||||||
while (!_taskCancel)
|
if (CacheBytes != null)
|
||||||
|
{
|
||||||
|
lock (CacheBytes)
|
||||||
|
{
|
||||||
|
CacheBytes.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ReceiveMessage(CancellationToken token)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -533,10 +570,7 @@ namespace Modbus.Net
|
|||||||
CacheBytes.Count);
|
CacheBytes.Count);
|
||||||
logger.LogError(
|
logger.LogError(
|
||||||
$"Com client {ConnectionToken} cached msg: {string.Concat(CacheBytes.Select(p => " " + p.ToString("X2")))}");
|
$"Com client {ConnectionToken} cached msg: {string.Concat(CacheBytes.Select(p => " " + p.ToString("X2")))}");
|
||||||
lock (CacheBytes)
|
CacheClear();
|
||||||
{
|
|
||||||
CacheBytes.Clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -570,8 +604,13 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
CacheClear();
|
||||||
logger.LogError(e, "Com client {ConnectionToken} read msg error", ConnectionToken);
|
logger.LogError(e, "Com client {ConnectionToken} read msg error", ConnectionToken);
|
||||||
}
|
}
|
||||||
|
if (token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,106 +1,17 @@
|
|||||||
using DotNetty.Transport.Channels;
|
using DotNetty.Transport.Channels;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Nito.AsyncEx;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Modbus.Net
|
namespace Modbus.Net
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public abstract class EventHandlerConnector : EventHandlerConnector<byte[], byte[]>
|
public abstract partial class EventHandlerConnector : EventHandlerConnector<byte[], byte[]>
|
||||||
{
|
{
|
||||||
/// <inheridoc />
|
|
||||||
public override bool IsSharable => true;
|
|
||||||
|
|
||||||
private static readonly ILogger<EventHandlerConnector> logger = LogProvider.CreateLogger<EventHandlerConnector>();
|
private static readonly ILogger<EventHandlerConnector> logger = LogProvider.CreateLogger<EventHandlerConnector>();
|
||||||
|
|
||||||
/// <summary>
|
/// <inheridoc />
|
||||||
/// 发送锁
|
public override bool IsSharable => true;
|
||||||
/// </summary>
|
|
||||||
protected abstract AsyncLock Lock { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否为全双工
|
|
||||||
/// </summary>
|
|
||||||
public bool IsFullDuplex { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 发送超时时间
|
|
||||||
/// </summary>
|
|
||||||
protected abstract int TimeoutTime { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 构造器
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="timeoutTime">发送超时时间</param>
|
|
||||||
/// <param name="isFullDuplex">是否为全双工</param>
|
|
||||||
protected EventHandlerConnector(int timeoutTime = 10000, bool isFullDuplex = true)
|
|
||||||
{
|
|
||||||
IsFullDuplex = isFullDuplex;
|
|
||||||
if (timeoutTime < -1) timeoutTime = -1;
|
|
||||||
TimeoutTime = timeoutTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override async Task<byte[]> SendMsgAsync(byte[] message)
|
|
||||||
{
|
|
||||||
var ans = await SendMsgInner(message);
|
|
||||||
if (ans == null) return new byte[0];
|
|
||||||
return ans.ReceiveMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 发送内部
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">发送的信息</param>
|
|
||||||
/// <param name="repeat">是否为重发消息</param>
|
|
||||||
/// <returns>发送信息的定义</returns>
|
|
||||||
protected async Task<MessageWaitingDef> SendMsgInner(byte[] message, bool repeat = false)
|
|
||||||
{
|
|
||||||
IDisposable asyncLock = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!Controller.IsSending)
|
|
||||||
{
|
|
||||||
Controller.SendStart();
|
|
||||||
}
|
|
||||||
var messageSendingdef = Controller.AddMessage(message);
|
|
||||||
if (messageSendingdef != null)
|
|
||||||
{
|
|
||||||
if (!IsFullDuplex)
|
|
||||||
{
|
|
||||||
asyncLock = await Lock.LockAsync();
|
|
||||||
}
|
|
||||||
var success = messageSendingdef.SendMutex.WaitOne(TimeoutTime);
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
await SendMsgWithoutConfirm(message);
|
|
||||||
success = messageSendingdef.ReceiveMutex.WaitOne(TimeoutTime);
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
if (!repeat && messageSendingdef.ReceiveMessage == null)
|
|
||||||
{
|
|
||||||
asyncLock?.Dispose();
|
|
||||||
return await SendMsgInner(message, true);
|
|
||||||
}
|
|
||||||
return messageSendingdef;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Controller.ForceRemoveWaitingMessage(messageSendingdef);
|
|
||||||
}
|
|
||||||
logger.LogInformation("Message is waiting in {0}. Cancel!", ConnectionToken);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
logger.LogError(e, "Connector {0} Send Error.", ConnectionToken);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
asyncLock?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheridoc />
|
/// <inheridoc />
|
||||||
public override void ChannelReadComplete(IChannelHandlerContext ctx)
|
public override void ChannelReadComplete(IChannelHandlerContext ctx)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Quartz.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -24,7 +25,9 @@ namespace Modbus.Net
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 消息维护线程是否在运行
|
/// 消息维护线程是否在运行
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual bool IsSending => SendingThread.Status.Equals(TaskStatus.Running);
|
public virtual bool IsSending => SendingThread != null;
|
||||||
|
|
||||||
|
private CancellationTokenSource _sendingThreadCancel;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 包切分位置函数
|
/// 包切分位置函数
|
||||||
@@ -68,26 +71,55 @@ namespace Modbus.Net
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送消息的实际内部方法
|
/// 发送消息的实际内部方法
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected abstract void SendingMessageControlInner();
|
protected abstract void SendingMessageControlInner(CancellationToken token);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public abstract void SendStop();
|
public virtual void SendStop()
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public virtual void SendStart()
|
|
||||||
{
|
{
|
||||||
if (SendingThread == null)
|
Clear();
|
||||||
|
_sendingThreadCancel?.Cancel();
|
||||||
|
if (SendingThread != null)
|
||||||
{
|
{
|
||||||
SendingThread = Task.Run(() => SendingMessageControlInner());
|
while (!SendingThread.IsCanceled)
|
||||||
|
{
|
||||||
|
Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
SendingThread.Dispose();
|
||||||
|
SendingThread = null;
|
||||||
|
}
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public virtual async void SendStart()
|
||||||
|
{
|
||||||
|
if (!IsSending)
|
||||||
|
{
|
||||||
|
_sendingThreadCancel = new CancellationTokenSource();
|
||||||
|
SendingThread = Task.Run(() => SendingMessageControlInner(_sendingThreadCancel.Token), _sendingThreadCancel.Token);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await SendingThread;
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{ }
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_sendingThreadCancel.Dispose();
|
||||||
|
_sendingThreadCancel = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
lock (WaitingMessages)
|
if (WaitingMessages != null)
|
||||||
{
|
{
|
||||||
WaitingMessages.Clear();
|
lock (WaitingMessages)
|
||||||
|
{
|
||||||
|
WaitingMessages.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,13 +223,7 @@ namespace Modbus.Net
|
|||||||
if (def != null)
|
if (def != null)
|
||||||
{
|
{
|
||||||
def.ReceiveMessage = message.Item1;
|
def.ReceiveMessage = message.Item1;
|
||||||
lock (WaitingMessages)
|
ForceRemoveWaitingMessage(def);
|
||||||
{
|
|
||||||
if (WaitingMessages.IndexOf(def) >= 0)
|
|
||||||
{
|
|
||||||
WaitingMessages.Remove(def);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
def.ReceiveMutex.Set();
|
def.ReceiveMutex.Set();
|
||||||
ans.Add((message.Item1, true));
|
ans.Add((message.Item1, true));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ namespace Modbus.Net
|
|||||||
|
|
||||||
private MessageWaitingDef _currentSendingPos;
|
private MessageWaitingDef _currentSendingPos;
|
||||||
|
|
||||||
private bool _taskCancel = false;
|
|
||||||
|
|
||||||
private int _waitingListMaxCount;
|
private int _waitingListMaxCount;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -38,9 +36,9 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void SendingMessageControlInner()
|
protected override void SendingMessageControlInner(CancellationToken token)
|
||||||
{
|
{
|
||||||
while (!_taskCancel)
|
while (true)
|
||||||
{
|
{
|
||||||
if (AcquireTime > 0)
|
if (AcquireTime > 0)
|
||||||
{
|
{
|
||||||
@@ -79,24 +77,14 @@ namespace Modbus.Net
|
|||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
logger.LogError(e, "Controller throws exception");
|
logger.LogError(e, "Controller throws exception");
|
||||||
_taskCancel = true;
|
SendStop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override void SendStart()
|
|
||||||
{
|
|
||||||
_taskCancel = false;
|
|
||||||
base.SendStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override void SendStop()
|
|
||||||
{
|
|
||||||
_taskCancel = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -123,7 +111,7 @@ namespace Modbus.Net
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (_taskCancel)
|
if (!IsSending)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Modbus.Net
|
namespace Modbus.Net
|
||||||
{
|
{
|
||||||
@@ -32,7 +33,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void SendingMessageControlInner()
|
protected override void SendingMessageControlInner(CancellationToken token)
|
||||||
{
|
{
|
||||||
//empty
|
//empty
|
||||||
}
|
}
|
||||||
|
|||||||
40
Modbus.Net/Modbus.Net/Helper/ControllerHelper.cs
Normal file
40
Modbus.Net/Modbus.Net/Helper/ControllerHelper.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Modbus.Net
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ProtocolLinker添加Controller扩展方法
|
||||||
|
/// </summary>
|
||||||
|
public static class ControllerHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 添加一个Controller
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="protocolLinker">ProtocolLinker实例</param>
|
||||||
|
/// <param name="constructorParams">参数</param>
|
||||||
|
/// <param name="connector">Connector实例</param>
|
||||||
|
/// <exception cref="NotImplementedException">如果没有发现控制器,报错</exception>
|
||||||
|
public static void AddController(this IProtocolLinker<byte[], byte[]> protocolLinker, object[] constructorParams, IConnector<byte[], byte[]> connector)
|
||||||
|
{
|
||||||
|
IController controller = null;
|
||||||
|
var assemblies = AssemblyHelper.GetAllLibraryAssemblies();
|
||||||
|
string controllerName = protocolLinker.GetType().Name.Substring(0, protocolLinker.GetType().Name.Length - 14) + "Controller";
|
||||||
|
foreach (var assembly in assemblies)
|
||||||
|
{
|
||||||
|
var controllerType = assembly.GetType(assembly.GetName().Name + "." + controllerName);
|
||||||
|
if (controllerType != null)
|
||||||
|
{
|
||||||
|
controller = assembly.CreateInstance(controllerType.FullName, true, BindingFlags.Default, null, constructorParams, null, null) as IController;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (controller != null)
|
||||||
|
{
|
||||||
|
((IConnectorWithController<byte[], byte[]>)connector).AddController(controller);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new NotImplementedException(controllerName + " not found exception");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,7 @@ namespace Modbus.Net
|
|||||||
connectionTimeout = int.Parse(connectionTimeout != null ? connectionTimeout.ToString() : null ?? ConfigurationReader.GetValue("COM:" + com, "ConnectionTimeout"));
|
connectionTimeout = int.Parse(connectionTimeout != null ? connectionTimeout.ToString() : null ?? ConfigurationReader.GetValue("COM:" + com, "ConnectionTimeout"));
|
||||||
isFullDuplex = bool.Parse(isFullDuplex != null ? isFullDuplex.ToString() : null ?? ConfigurationReader.GetValue("COM:" + com, "FullDuplex"));
|
isFullDuplex = bool.Parse(isFullDuplex != null ? isFullDuplex.ToString() : null ?? ConfigurationReader.GetValue("COM:" + com, "FullDuplex"));
|
||||||
BaseConnector = new ComConnector(com + ":" + slaveAddress, baudRate.Value, parity.Value, stopBits.Value, dataBits.Value, handshake.Value, connectionTimeout.Value, isFullDuplex.Value);
|
BaseConnector = new ComConnector(com + ":" + slaveAddress, baudRate.Value, parity.Value, stopBits.Value, dataBits.Value, handshake.Value, connectionTimeout.Value, isFullDuplex.Value);
|
||||||
|
this.AddController(new object[2] { com, slaveAddress }, BaseConnector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
isFullDuplex = bool.Parse(isFullDuplex != null ? isFullDuplex.ToString() : null ?? ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FullDuplex"));
|
isFullDuplex = bool.Parse(isFullDuplex != null ? isFullDuplex.ToString() : null ?? ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FullDuplex"));
|
||||||
//初始化连接对象
|
//初始化连接对象
|
||||||
BaseConnector = new TcpConnector(ip, port, connectionTimeout.Value, isFullDuplex.Value);
|
BaseConnector = new TcpConnector(ip, port, connectionTimeout.Value, isFullDuplex.Value);
|
||||||
|
this.AddController(new object[2] { ip, port }, BaseConnector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
isFullDuplex = bool.Parse(isFullDuplex != null ? isFullDuplex.ToString() : null ?? ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FullDuplex"));
|
isFullDuplex = bool.Parse(isFullDuplex != null ? isFullDuplex.ToString() : null ?? ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FullDuplex"));
|
||||||
//初始化连接对象
|
//初始化连接对象
|
||||||
BaseConnector = new UdpConnector(ip, port, connectionTimeout.Value, isFullDuplex.Value);
|
BaseConnector = new UdpConnector(ip, port, connectionTimeout.Value, isFullDuplex.Value);
|
||||||
|
this.AddController(new object[2] { ip, port }, BaseConnector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,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.2</Version>
|
<Version>1.4.3</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>
|
||||||
@@ -34,18 +34,21 @@
|
|||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DotNetty.Handlers" Version="0.7.5" />
|
<PackageReference Include="DotNetty.Handlers" Version="0.7.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" 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.2" />
|
<PackageReference Include="Quartz" Version="3.6.3" />
|
||||||
<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" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="README.md" Pack="true" PackagePath="" />
|
<None Include="README.md" Pack="true" PackagePath="" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Modbus.Net.CodeGenerator\Modbus.Net.CodeGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Modbus.Net.CodeGenerator
|
||||||
|
{
|
||||||
|
[Generator]
|
||||||
|
public class DatabaseWriteEntityCodeGenerator : ISourceGenerator
|
||||||
|
{
|
||||||
|
public void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
var content = "";
|
||||||
|
for (int i = 1; i <= 10; i++)
|
||||||
|
{
|
||||||
|
content += $@"public double? Value{i} {{ get; set; }}
|
||||||
|
";
|
||||||
|
}
|
||||||
|
var source = $@"
|
||||||
|
|
||||||
|
namespace MachineJob
|
||||||
|
{{
|
||||||
|
public partial class DatabaseWriteEntity
|
||||||
|
{{
|
||||||
|
{content}
|
||||||
|
}}
|
||||||
|
}}";
|
||||||
|
context.AddSource("DatabaseWriteContent.g.cs", source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize(GeneratorInitializationContext context)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<LangVersion>9.0</LangVersion>
|
||||||
|
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.6.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -24,20 +24,11 @@ namespace MachineJob
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Table(name: "databasewrites")]
|
[Table(name: "databasewrites")]
|
||||||
public class DatabaseWriteEntity
|
public partial class DatabaseWriteEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public double? Value1 { get; set; }
|
|
||||||
public double? Value2 { get; set; }
|
|
||||||
public double? Value3 { get; set; }
|
|
||||||
public double? Value4 { get; set; }
|
|
||||||
public double? Value5 { get; set; }
|
|
||||||
public double? Value6 { get; set; }
|
|
||||||
public double? Value7 { get; set; }
|
|
||||||
public double? Value8 { get; set; }
|
|
||||||
public double? Value9 { get; set; }
|
|
||||||
public double? Value10 { get; set; }
|
|
||||||
public DateTime UpdateTime { get; set; }
|
public DateTime UpdateTime { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,17 +8,18 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.3">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.9">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<TreatAsUsed>true</TreatAsUsed>
|
<TreatAsUsed>true</TreatAsUsed>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" 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.Extensions.Logging" Version="7.0.0" />
|
||||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -26,5 +27,6 @@
|
|||||||
<ProjectReference Include="..\..\Modbus.Net\Modbus.Net.OPC\Modbus.Net.Opc.csproj" />
|
<ProjectReference Include="..\..\Modbus.Net\Modbus.Net.OPC\Modbus.Net.Opc.csproj" />
|
||||||
<ProjectReference Include="..\..\Modbus.Net\Modbus.Net.Siemens\Modbus.Net.Siemens.csproj" />
|
<ProjectReference Include="..\..\Modbus.Net\Modbus.Net.Siemens\Modbus.Net.Siemens.csproj" />
|
||||||
<ProjectReference Include="..\..\Modbus.Net\Modbus.Net\Modbus.Net.csproj" />
|
<ProjectReference Include="..\..\Modbus.Net\Modbus.Net\Modbus.Net.csproj" />
|
||||||
|
<ProjectReference Include="..\MachineJob.CodeGenerator\MachineJob.CodeGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ IHost host = Host.CreateDefaultBuilder(args).UseWindowsService()
|
|||||||
|
|
||||||
Log.Logger = new LoggerConfiguration()
|
Log.Logger = new LoggerConfiguration()
|
||||||
.ReadFrom.Configuration(configuration)
|
.ReadFrom.Configuration(configuration)
|
||||||
|
.Enrich.FromLogContext()
|
||||||
.WriteTo.Console()
|
.WriteTo.Console()
|
||||||
|
.WriteTo.File("Log\\log..txt", Serilog.Events.LogEventLevel.Error, shared: true, rollingInterval: RollingInterval.Day)
|
||||||
.CreateLogger();
|
.CreateLogger();
|
||||||
|
|
||||||
var loggerFactory = new LoggerFactory().AddSerilog(Log.Logger);
|
var loggerFactory = new LoggerFactory().AddSerilog(Log.Logger);
|
||||||
|
|||||||
@@ -22,10 +22,13 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
|
||||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
|
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
|
||||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
|
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
|
||||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user