NoResponseController
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@@ -16,7 +17,17 @@ namespace Modbus.Net.HJ212
|
|||||||
public HJ212Protocol(string ip)
|
public HJ212Protocol(string ip)
|
||||||
: base(0, 0, Endian.BigEndianLsb)
|
: base(0, 0, Endian.BigEndianLsb)
|
||||||
{
|
{
|
||||||
ProtocolLinker = new HJ212ProtocolLinker(ip, int.Parse(ConfigurationReader.GetValueDirect("TCP:" + ip, "HJ212Port") ?? ConfigurationReader.GetValueDirect("TCP:Modbus", "HJ212Port") ?? "443"));
|
var splitPos = ip.IndexOf(':');
|
||||||
|
if (splitPos > -1)
|
||||||
|
{
|
||||||
|
string realIp = ip.Substring(0, splitPos);
|
||||||
|
string port = ip.Substring(splitPos + 1);
|
||||||
|
ProtocolLinker = new HJ212ProtocolLinker(realIp, int.Parse(port));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ProtocolLinker = new HJ212ProtocolLinker(ip, int.Parse(ConfigurationReader.GetValueDirect("TCP:" + ip, "HJ212Port") ?? ConfigurationReader.GetValueDirect("TCP:Modbus", "HJ212Port") ?? "443"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -43,7 +54,7 @@ namespace Modbus.Net.HJ212
|
|||||||
public override byte[] Format(IInputStruct message)
|
public override byte[] Format(IInputStruct message)
|
||||||
{
|
{
|
||||||
var r_message = (WriteRequestHJ212InputStruct)message;
|
var r_message = (WriteRequestHJ212InputStruct)message;
|
||||||
string formatMessage = "##0633";
|
string formatMessage = "";
|
||||||
formatMessage += "QN=" + r_message.QN + ";";
|
formatMessage += "QN=" + r_message.QN + ";";
|
||||||
formatMessage += "ST=" + r_message.ST + ";";
|
formatMessage += "ST=" + r_message.ST + ";";
|
||||||
formatMessage += "CN=" + r_message.CN + ";";
|
formatMessage += "CN=" + r_message.CN + ";";
|
||||||
@@ -61,7 +72,6 @@ namespace Modbus.Net.HJ212
|
|||||||
formatMessage += ";";
|
formatMessage += ";";
|
||||||
}
|
}
|
||||||
formatMessage = formatMessage[..^1];
|
formatMessage = formatMessage[..^1];
|
||||||
formatMessage += "&&";
|
|
||||||
return Encoding.ASCII.GetBytes(formatMessage);
|
return Encoding.ASCII.GetBytes(formatMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,14 +15,21 @@ namespace Modbus.Net.HJ212
|
|||||||
/// <returns>扩展后的协议内容</returns>
|
/// <returns>扩展后的协议内容</returns>
|
||||||
public byte[] BytesExtend(byte[] content)
|
public byte[] BytesExtend(byte[] content)
|
||||||
{
|
{
|
||||||
var crc = new byte[2];
|
var newFormat = new byte[content.Length + 12];
|
||||||
|
Array.Copy(content, 0, newFormat, 6, content.Length);
|
||||||
|
//表头长度扩张
|
||||||
|
var length = content.Length;
|
||||||
|
string lengthString = length.ToString("0000");
|
||||||
|
lengthString = "##" + lengthString;
|
||||||
|
var lengthCalc = Encoding.ASCII.GetBytes(lengthString);
|
||||||
|
Array.Copy(lengthCalc, 0, newFormat, 0, 6);
|
||||||
//Modbus/Rtu协议扩张,增加CRC校验
|
//Modbus/Rtu协议扩张,增加CRC校验
|
||||||
var newFormat = new byte[content.Length + 4];
|
var crc = new byte[2];
|
||||||
Crc16.GetInstance().GetCRC(content, ref crc);
|
Crc16.GetInstance().GetCRC(content, ref crc);
|
||||||
Array.Copy(content, 0, newFormat, 0, content.Length);
|
|
||||||
string crcString = BitConverter.ToString(crc).Replace("-", string.Empty);
|
string crcString = BitConverter.ToString(crc).Replace("-", string.Empty);
|
||||||
|
crcString = "&&" + crcString;
|
||||||
var crcCalc = Encoding.ASCII.GetBytes(crcString);
|
var crcCalc = Encoding.ASCII.GetBytes(crcString);
|
||||||
Array.Copy(crcCalc, 0, newFormat, newFormat.Length - 4, 4);
|
Array.Copy(crcCalc, 0, newFormat, newFormat.Length - 6, 6);
|
||||||
return newFormat;
|
return newFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ namespace Modbus.Net.Modbus
|
|||||||
/// <returns>校验是否正确</returns>
|
/// <returns>校验是否正确</returns>
|
||||||
public override bool? CheckRight(byte[] content)
|
public override bool? CheckRight(byte[] content)
|
||||||
{
|
{
|
||||||
//ProtocolLinker不会返回null
|
if (base.CheckRight(content) != true) return base.CheckRight(content);
|
||||||
if (base.CheckRight(content) != true) return false;
|
|
||||||
//Modbus协议错误
|
//Modbus协议错误
|
||||||
var contentString = Encoding.ASCII.GetString(content);
|
var contentString = Encoding.ASCII.GetString(content);
|
||||||
if (byte.Parse(contentString.Substring(3, 2)) > 127)
|
if (byte.Parse(contentString.Substring(3, 2)) > 127)
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ namespace Modbus.Net.Modbus
|
|||||||
/// <returns>校验是否正确</returns>
|
/// <returns>校验是否正确</returns>
|
||||||
public override bool? CheckRight(byte[] content)
|
public override bool? CheckRight(byte[] content)
|
||||||
{
|
{
|
||||||
//ProtocolLinker不会返回null
|
if (base.CheckRight(content) != true) return base.CheckRight(content);
|
||||||
if (base.CheckRight(content) != true) return false;
|
|
||||||
//Modbus协议错误
|
//Modbus协议错误
|
||||||
var contentString = Encoding.ASCII.GetString(content);
|
var contentString = Encoding.ASCII.GetString(content);
|
||||||
if (byte.Parse(contentString.Substring(3, 2)) > 127)
|
if (byte.Parse(contentString.Substring(3, 2)) > 127)
|
||||||
|
|||||||
@@ -24,8 +24,7 @@ namespace Modbus.Net.Modbus
|
|||||||
/// <returns>校验是否正确</returns>
|
/// <returns>校验是否正确</returns>
|
||||||
public override bool? CheckRight(byte[] content)
|
public override bool? CheckRight(byte[] content)
|
||||||
{
|
{
|
||||||
//ProtocolLinker不会返回null
|
if (base.CheckRight(content) != true) return base.CheckRight(content);
|
||||||
if (base.CheckRight(content) != true) return false;
|
|
||||||
//Modbus协议错误
|
//Modbus协议错误
|
||||||
var contentString = Encoding.ASCII.GetString(content);
|
var contentString = Encoding.ASCII.GetString(content);
|
||||||
if (byte.Parse(contentString.Substring(3, 2)) > 127)
|
if (byte.Parse(contentString.Substring(3, 2)) > 127)
|
||||||
|
|||||||
@@ -31,8 +31,7 @@
|
|||||||
/// <returns>数据是否正确</returns>
|
/// <returns>数据是否正确</returns>
|
||||||
public override bool? CheckRight(byte[] content)
|
public override bool? CheckRight(byte[] content)
|
||||||
{
|
{
|
||||||
//ProtocolLinker的CheckRight不会返回null
|
if (base.CheckRight(content) != true) return base.CheckRight(content);
|
||||||
if (base.CheckRight(content) != true) return false;
|
|
||||||
//Modbus协议错误
|
//Modbus协议错误
|
||||||
if (content[1] > 127)
|
if (content[1] > 127)
|
||||||
throw new ModbusProtocolErrorException(content[2]);
|
throw new ModbusProtocolErrorException(content[2]);
|
||||||
|
|||||||
@@ -31,8 +31,7 @@
|
|||||||
/// <returns>数据是否正确</returns>
|
/// <returns>数据是否正确</returns>
|
||||||
public override bool? CheckRight(byte[] content)
|
public override bool? CheckRight(byte[] content)
|
||||||
{
|
{
|
||||||
//ProtocolLinker的CheckRight不会返回null
|
if (base.CheckRight(content) != true) return base.CheckRight(content);
|
||||||
if (base.CheckRight(content) != true) return false;
|
|
||||||
//Modbus协议错误
|
//Modbus协议错误
|
||||||
if (content[1] > 127)
|
if (content[1] > 127)
|
||||||
throw new ModbusProtocolErrorException(content[2]);
|
throw new ModbusProtocolErrorException(content[2]);
|
||||||
|
|||||||
@@ -22,8 +22,7 @@
|
|||||||
/// <returns>数据是否正确</returns>
|
/// <returns>数据是否正确</returns>
|
||||||
public override bool? CheckRight(byte[] content)
|
public override bool? CheckRight(byte[] content)
|
||||||
{
|
{
|
||||||
//ProtocolLinker的CheckRight不会返回null
|
if (base.CheckRight(content) != true) return base.CheckRight(content);
|
||||||
if (base.CheckRight(content) != true) return false;
|
|
||||||
//CRC校验失败
|
//CRC校验失败
|
||||||
if (!Crc16.GetInstance().CrcEfficacy(content))
|
if (!Crc16.GetInstance().CrcEfficacy(content))
|
||||||
throw new ModbusProtocolErrorException(501);
|
throw new ModbusProtocolErrorException(501);
|
||||||
|
|||||||
@@ -30,8 +30,7 @@
|
|||||||
/// <returns>数据是否正确</returns>
|
/// <returns>数据是否正确</returns>
|
||||||
public override bool? CheckRight(byte[] content)
|
public override bool? CheckRight(byte[] content)
|
||||||
{
|
{
|
||||||
//ProtocolLinker的CheckRight不会返回null
|
if (base.CheckRight(content) != true) return base.CheckRight(content);
|
||||||
if (base.CheckRight(content) != true) return false;
|
|
||||||
//Modbus协议错误
|
//Modbus协议错误
|
||||||
if (content[7] > 127)
|
if (content[7] > 127)
|
||||||
throw new ModbusProtocolErrorException(content[2] > 0 ? content[2] : content[8]);
|
throw new ModbusProtocolErrorException(content[2] > 0 ? content[2] : content[8]);
|
||||||
|
|||||||
@@ -30,8 +30,7 @@
|
|||||||
/// <returns>数据是否正确</returns>
|
/// <returns>数据是否正确</returns>
|
||||||
public override bool? CheckRight(byte[] content)
|
public override bool? CheckRight(byte[] content)
|
||||||
{
|
{
|
||||||
//ProtocolLinker的CheckRight不会返回null
|
if (base.CheckRight(content) != true) return base.CheckRight(content);
|
||||||
if (base.CheckRight(content) != true) return false;
|
|
||||||
//Modbus协议错误
|
//Modbus协议错误
|
||||||
if (content[7] > 127)
|
if (content[7] > 127)
|
||||||
throw new ModbusProtocolErrorException(content[2] > 0 ? content[2] : content[8]);
|
throw new ModbusProtocolErrorException(content[2] > 0 ? content[2] : content[8]);
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ namespace Modbus.Net.Modbus
|
|||||||
return new ReturnStruct<byte[]>
|
return new ReturnStruct<byte[]>
|
||||||
{
|
{
|
||||||
Datas = outputStruct?.DataValue,
|
Datas = outputStruct?.DataValue,
|
||||||
IsSuccess = true,
|
IsSuccess = outputStruct == null ? null : true,
|
||||||
ErrorCode = 0,
|
ErrorCode = 0,
|
||||||
ErrorMsg = ""
|
ErrorMsg = ""
|
||||||
};
|
};
|
||||||
@@ -325,7 +325,7 @@ namespace Modbus.Net.Modbus
|
|||||||
return new ReturnStruct<byte>()
|
return new ReturnStruct<byte>()
|
||||||
{
|
{
|
||||||
Datas = outputStruct.OutputData,
|
Datas = outputStruct.OutputData,
|
||||||
IsSuccess = true,
|
IsSuccess = outputStruct == null ? null : true,
|
||||||
ErrorCode = 0,
|
ErrorCode = 0,
|
||||||
ErrorMsg = null
|
ErrorMsg = null
|
||||||
};
|
};
|
||||||
@@ -355,7 +355,7 @@ namespace Modbus.Net.Modbus
|
|||||||
return new ReturnStruct<DiagnoticsData>()
|
return new ReturnStruct<DiagnoticsData>()
|
||||||
{
|
{
|
||||||
Datas = new DiagnoticsData() { SubFunction = outputStruct.SubFunction, Data = outputStruct.Data },
|
Datas = new DiagnoticsData() { SubFunction = outputStruct.SubFunction, Data = outputStruct.Data },
|
||||||
IsSuccess = true,
|
IsSuccess = outputStruct == null ? null : true,
|
||||||
ErrorCode = 0,
|
ErrorCode = 0,
|
||||||
ErrorMsg = null
|
ErrorMsg = null
|
||||||
};
|
};
|
||||||
@@ -385,7 +385,7 @@ namespace Modbus.Net.Modbus
|
|||||||
return new ReturnStruct<CommEventCounterData>()
|
return new ReturnStruct<CommEventCounterData>()
|
||||||
{
|
{
|
||||||
Datas = new CommEventCounterData() { EventCount = outputStruct.EventCount, Status = outputStruct.Status },
|
Datas = new CommEventCounterData() { EventCount = outputStruct.EventCount, Status = outputStruct.Status },
|
||||||
IsSuccess = true,
|
IsSuccess = outputStruct == null ? null : true,
|
||||||
ErrorCode = 0,
|
ErrorCode = 0,
|
||||||
ErrorMsg = null
|
ErrorMsg = null
|
||||||
};
|
};
|
||||||
@@ -415,7 +415,7 @@ namespace Modbus.Net.Modbus
|
|||||||
return new ReturnStruct<CommEventLogData>()
|
return new ReturnStruct<CommEventLogData>()
|
||||||
{
|
{
|
||||||
Datas = new CommEventLogData() { Status = outputStruct.Status, Events = outputStruct.Events },
|
Datas = new CommEventLogData() { Status = outputStruct.Status, Events = outputStruct.Events },
|
||||||
IsSuccess = true,
|
IsSuccess = outputStruct == null ? null : true,
|
||||||
ErrorCode = 0,
|
ErrorCode = 0,
|
||||||
ErrorMsg = null
|
ErrorMsg = null
|
||||||
};
|
};
|
||||||
@@ -445,7 +445,7 @@ namespace Modbus.Net.Modbus
|
|||||||
return new ReturnStruct<SlaveIdData>()
|
return new ReturnStruct<SlaveIdData>()
|
||||||
{
|
{
|
||||||
Datas = new SlaveIdData() { SlaveId = outputStruct.SlaveId, IndicatorStatus = outputStruct.RunIndicatorStatus, AdditionalData = outputStruct.AdditionalData },
|
Datas = new SlaveIdData() { SlaveId = outputStruct.SlaveId, IndicatorStatus = outputStruct.RunIndicatorStatus, AdditionalData = outputStruct.AdditionalData },
|
||||||
IsSuccess = true,
|
IsSuccess = outputStruct == null ? null : true,
|
||||||
ErrorCode = 0,
|
ErrorCode = 0,
|
||||||
ErrorMsg = null
|
ErrorMsg = null
|
||||||
};
|
};
|
||||||
@@ -475,7 +475,7 @@ namespace Modbus.Net.Modbus
|
|||||||
return new ReturnStruct<ReadFileRecordOutputDef[]>()
|
return new ReturnStruct<ReadFileRecordOutputDef[]>()
|
||||||
{
|
{
|
||||||
Datas = outputStruct.RecordDefs,
|
Datas = outputStruct.RecordDefs,
|
||||||
IsSuccess = true,
|
IsSuccess = outputStruct == null ? null : true,
|
||||||
ErrorCode = 0,
|
ErrorCode = 0,
|
||||||
ErrorMsg = null
|
ErrorMsg = null
|
||||||
};
|
};
|
||||||
@@ -505,7 +505,7 @@ namespace Modbus.Net.Modbus
|
|||||||
return new ReturnStruct<WriteFileRecordOutputDef[]>()
|
return new ReturnStruct<WriteFileRecordOutputDef[]>()
|
||||||
{
|
{
|
||||||
Datas = outputStruct.WriteRecords,
|
Datas = outputStruct.WriteRecords,
|
||||||
IsSuccess = true,
|
IsSuccess = outputStruct == null ? null : true,
|
||||||
ErrorCode = 0,
|
ErrorCode = 0,
|
||||||
ErrorMsg = null
|
ErrorMsg = null
|
||||||
};
|
};
|
||||||
@@ -535,7 +535,7 @@ namespace Modbus.Net.Modbus
|
|||||||
return new ReturnStruct<MaskRegisterData>()
|
return new ReturnStruct<MaskRegisterData>()
|
||||||
{
|
{
|
||||||
Datas = new MaskRegisterData() { ReferenceAddress = outputStruct.ReferenceAddress, AndMask = outputStruct.AndMask, OrMask = outputStruct.OrMask },
|
Datas = new MaskRegisterData() { ReferenceAddress = outputStruct.ReferenceAddress, AndMask = outputStruct.AndMask, OrMask = outputStruct.OrMask },
|
||||||
IsSuccess = true,
|
IsSuccess = outputStruct == null ? null : true,
|
||||||
ErrorCode = 0,
|
ErrorCode = 0,
|
||||||
ErrorMsg = null
|
ErrorMsg = null
|
||||||
};
|
};
|
||||||
@@ -565,7 +565,7 @@ namespace Modbus.Net.Modbus
|
|||||||
return new ReturnStruct<ushort[]>()
|
return new ReturnStruct<ushort[]>()
|
||||||
{
|
{
|
||||||
Datas = outputStruct.ReadRegisterValues,
|
Datas = outputStruct.ReadRegisterValues,
|
||||||
IsSuccess = true,
|
IsSuccess = outputStruct == null ? null : true,
|
||||||
ErrorCode = 0,
|
ErrorCode = 0,
|
||||||
ErrorMsg = null
|
ErrorMsg = null
|
||||||
};
|
};
|
||||||
@@ -595,7 +595,7 @@ namespace Modbus.Net.Modbus
|
|||||||
return new ReturnStruct<ushort[]>()
|
return new ReturnStruct<ushort[]>()
|
||||||
{
|
{
|
||||||
Datas = outputStruct.FIFOValueRegister,
|
Datas = outputStruct.FIFOValueRegister,
|
||||||
IsSuccess = true,
|
IsSuccess = outputStruct == null ? null : true,
|
||||||
ErrorCode = 0,
|
ErrorCode = 0,
|
||||||
ErrorMsg = null
|
ErrorMsg = null
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace Modbus.Net
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public abstract partial class BaseConnector : BaseConnector<byte[], byte[]>
|
public abstract partial class BaseConnector : BaseConnector<byte[], byte[]>
|
||||||
{
|
{
|
||||||
private static readonly ILogger<EventHandlerConnector> logger = LogProvider.CreateLogger<EventHandlerConnector>();
|
private static readonly ILogger<BaseConnector> logger = LogProvider.CreateLogger<BaseConnector>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
243
Modbus.Net/Modbus.Net/Controller/NoResponseController.cs
Normal file
243
Modbus.Net/Modbus.Net/Controller/NoResponseController.cs
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Quartz.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Modbus.Net
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 控制器基类
|
||||||
|
/// </summary>
|
||||||
|
public class NoResponseController : IController
|
||||||
|
{
|
||||||
|
private static readonly ILogger<NoResponseController> logger = LogProvider.CreateLogger<NoResponseController>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 等待的消息队列
|
||||||
|
/// </summary>
|
||||||
|
protected List<MessageWaitingDef> WaitingMessages { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 消息维护线程
|
||||||
|
/// </summary>
|
||||||
|
protected Task SendingThread { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 间隔时间
|
||||||
|
/// </summary>
|
||||||
|
public int AcquireTime { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 消息维护线程是否在运行
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool IsSending => SendingThread != null;
|
||||||
|
|
||||||
|
private MessageWaitingDef _currentSendingPos;
|
||||||
|
|
||||||
|
private CancellationTokenSource _sendingThreadCancel;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造器
|
||||||
|
/// </summary>
|
||||||
|
public NoResponseController(int acquireTime)
|
||||||
|
{
|
||||||
|
WaitingMessages = new List<MessageWaitingDef>();
|
||||||
|
AcquireTime = acquireTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public MessageWaitingDef AddMessage(byte[] sendMessage)
|
||||||
|
{
|
||||||
|
var def = new MessageWaitingDef
|
||||||
|
{
|
||||||
|
Key = GetKeyFromMessage(sendMessage)?.Item1,
|
||||||
|
SendMessage = sendMessage,
|
||||||
|
SendMutex = new AutoResetEvent(false),
|
||||||
|
ReceiveMutex = new AutoResetEvent(false)
|
||||||
|
};
|
||||||
|
if (AddMessageToList(def))
|
||||||
|
{
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送消息的实际内部方法
|
||||||
|
/// </summary>
|
||||||
|
protected void SendingMessageControlInner(CancellationToken token)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (AcquireTime > 0)
|
||||||
|
{
|
||||||
|
Thread.Sleep(AcquireTime);
|
||||||
|
}
|
||||||
|
lock (WaitingMessages)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_currentSendingPos == null)
|
||||||
|
{
|
||||||
|
if (WaitingMessages.Count > 0)
|
||||||
|
{
|
||||||
|
_currentSendingPos = WaitingMessages.First();
|
||||||
|
_currentSendingPos.SendMutex.Set();
|
||||||
|
_currentSendingPos.ReceiveMessage = new byte[0];
|
||||||
|
_currentSendingPos.ReceiveMutex.Set();
|
||||||
|
ForceRemoveWaitingMessage(_currentSendingPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (WaitingMessages.Count <= 0)
|
||||||
|
{
|
||||||
|
_currentSendingPos = null;
|
||||||
|
}
|
||||||
|
else if (WaitingMessages.IndexOf(_currentSendingPos) == -1)
|
||||||
|
{
|
||||||
|
_currentSendingPos = WaitingMessages.First();
|
||||||
|
_currentSendingPos.SendMutex.Set();
|
||||||
|
_currentSendingPos.ReceiveMessage = new byte[0];
|
||||||
|
_currentSendingPos.ReceiveMutex.Set();
|
||||||
|
ForceRemoveWaitingMessage(_currentSendingPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException e)
|
||||||
|
{
|
||||||
|
logger.LogError(e, "Controller _currentSendingPos disposed");
|
||||||
|
_currentSendingPos = null;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogError(e, "Controller throws exception");
|
||||||
|
SendStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public virtual void SendStop()
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
_sendingThreadCancel?.Cancel();
|
||||||
|
if (SendingThread != null)
|
||||||
|
{
|
||||||
|
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 />
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
if (WaitingMessages != null)
|
||||||
|
{
|
||||||
|
lock (WaitingMessages)
|
||||||
|
{
|
||||||
|
WaitingMessages.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将信息添加到队列
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="def">需要添加的信息信息</param>
|
||||||
|
protected virtual bool AddMessageToList(MessageWaitingDef def)
|
||||||
|
{
|
||||||
|
var ans = false;
|
||||||
|
lock (WaitingMessages)
|
||||||
|
{
|
||||||
|
if (WaitingMessages.FirstOrDefault(p => p.Key == def.Key) == null || def.Key == null)
|
||||||
|
{
|
||||||
|
WaitingMessages.Add(def);
|
||||||
|
ans = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取信息的检索关键字
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">待确认的信息</param>
|
||||||
|
/// <returns>信息的检索关键字</returns>
|
||||||
|
protected (string, string)? GetKeyFromMessage(byte[] message)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ICollection<(byte[], bool)> ConfirmMessage(byte[] receiveMessage)
|
||||||
|
{
|
||||||
|
var ans = new List<(byte[], bool)>
|
||||||
|
{
|
||||||
|
(receiveMessage, true)
|
||||||
|
};
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从等待队列中匹配信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="receiveMessage">返回的信息</param>
|
||||||
|
/// <returns>从等待队列中匹配的信息</returns>
|
||||||
|
protected MessageWaitingDef GetMessageFromWaitingList(byte[] receiveMessage)
|
||||||
|
{
|
||||||
|
MessageWaitingDef ans;
|
||||||
|
lock (WaitingMessages)
|
||||||
|
{
|
||||||
|
ans = WaitingMessages.FirstOrDefault();
|
||||||
|
}
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void ForceRemoveWaitingMessage(MessageWaitingDef def)
|
||||||
|
{
|
||||||
|
lock (WaitingMessages)
|
||||||
|
{
|
||||||
|
if (WaitingMessages.IndexOf(def) >= 0)
|
||||||
|
{
|
||||||
|
WaitingMessages.Remove(def);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,7 +31,15 @@ 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);
|
var noResponse = bool.Parse(ConfigurationReader.GetValue("COM:" + com, "NoResponse") ?? ConfigurationReader.GetValue("Controller", "NoResponse"));
|
||||||
|
if (noResponse)
|
||||||
|
{
|
||||||
|
((IConnectorWithController<byte[], byte[]>)BaseConnector).AddController(new NoResponseController(int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime"))));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.AddController(new object[2] { com, slaveAddress }, BaseConnector);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,15 @@
|
|||||||
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);
|
var noResponse = bool.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "NoResponse") ?? ConfigurationReader.GetValue("Controller", "NoResponse"));
|
||||||
|
if (noResponse)
|
||||||
|
{
|
||||||
|
((IConnectorWithController<byte[], byte[]>)BaseConnector).AddController(new NoResponseController(int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FetchSleepTime"))));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.AddController(new object[2] { ip, port }, BaseConnector);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,15 @@
|
|||||||
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);
|
var noResponse = bool.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "NoResponse") ?? ConfigurationReader.GetValue("Controller", "NoResponse"));
|
||||||
|
if (noResponse)
|
||||||
|
{
|
||||||
|
((IConnectorWithController<byte[], byte[]>)BaseConnector).AddController(new NoResponseController(int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FetchSleepTime"))));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.AddController(new object[2] { ip, port }, BaseConnector);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,9 +98,19 @@ namespace Modbus.Net
|
|||||||
ValueHelper.ByteLength[
|
ValueHelper.ByteLength[
|
||||||
communicateAddress.DataType.FullName]));
|
communicateAddress.DataType.FullName]));
|
||||||
|
|
||||||
|
//如果已知没有返回,终止
|
||||||
|
if (datas.IsSuccess == null)
|
||||||
|
{
|
||||||
|
return new ReturnStruct<Dictionary<string, ReturnUnit<double>>>()
|
||||||
|
{
|
||||||
|
Datas = null,
|
||||||
|
IsSuccess = null,
|
||||||
|
ErrorCode = datas.ErrorCode,
|
||||||
|
ErrorMsg = datas.ErrorMsg
|
||||||
|
};
|
||||||
|
}
|
||||||
//如果没有数据,终止
|
//如果没有数据,终止
|
||||||
if (datas.IsSuccess == false || datas.Datas == null)
|
else if (datas.IsSuccess == false || datas.Datas == null)
|
||||||
{
|
{
|
||||||
return new ReturnStruct<Dictionary<string, ReturnUnit<double>>>()
|
return new ReturnStruct<Dictionary<string, ReturnUnit<double>>>()
|
||||||
{
|
{
|
||||||
@@ -336,6 +346,14 @@ namespace Modbus.Net
|
|||||||
//如果设备本身能获取到数据但是没有数据
|
//如果设备本身能获取到数据但是没有数据
|
||||||
var datas = datasReturn;
|
var datas = datasReturn;
|
||||||
|
|
||||||
|
//没有返回,直接设0
|
||||||
|
if (datas.IsSuccess == null)
|
||||||
|
{
|
||||||
|
datas.Datas = new byte[(int)
|
||||||
|
Math.Ceiling(communicateAddress.GetCount *
|
||||||
|
ValueHelper.ByteLength[
|
||||||
|
communicateAddress.DataType.FullName])];
|
||||||
|
}
|
||||||
//如果没有数据,终止
|
//如果没有数据,终止
|
||||||
if (datas.IsSuccess == false || datas.Datas == null)
|
if (datas.IsSuccess == false || datas.Datas == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -185,7 +185,12 @@ namespace Modbus.Net
|
|||||||
public virtual async Task<T> SendReceiveAsync<T>(TProtocolUnit unit, IInputStruct content)
|
public virtual async Task<T> SendReceiveAsync<T>(TProtocolUnit unit, IInputStruct content)
|
||||||
where T : class, IOutputStruct
|
where T : class, IOutputStruct
|
||||||
{
|
{
|
||||||
return (await SendReceiveAsync(unit, content)).Unwrap<T>();
|
var ans = await SendReceiveAsync(unit, content);
|
||||||
|
if (ans.Success == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return ans.Unwrap<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Modbus.Net
|
|||||||
/// <param name="parameters">传递给输入结构的参数</param>
|
/// <param name="parameters">传递给输入结构的参数</param>
|
||||||
/// <param name="success">上次的管道是否成功执行</param>
|
/// <param name="success">上次的管道是否成功执行</param>
|
||||||
protected PipeUnit(IProtocolLinker<byte[], byte[]> protocolLinker, ProtocolUnit<byte[], byte[]> protocolUnit, byte[] parameters,
|
protected PipeUnit(IProtocolLinker<byte[], byte[]> protocolLinker, ProtocolUnit<byte[], byte[]> protocolUnit, byte[] parameters,
|
||||||
bool success) : base(protocolLinker, protocolUnit, parameters, success)
|
bool? success) : base(protocolLinker, protocolUnit, parameters, success)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ namespace Modbus.Net
|
|||||||
/// <returns>发送完成之后新的管道实例</returns>
|
/// <returns>发送完成之后新的管道实例</returns>
|
||||||
public async Task<PipeUnit> SendReceiveAsync(Endian endian, Func<byte[], object[]> inputStructCreator)
|
public async Task<PipeUnit> SendReceiveAsync(Endian endian, Func<byte[], object[]> inputStructCreator)
|
||||||
{
|
{
|
||||||
if (Success)
|
if (Success == true)
|
||||||
{
|
{
|
||||||
var content = inputStructCreator.Invoke(ReturnParams);
|
var content = inputStructCreator.Invoke(ReturnParams);
|
||||||
if (ProtocolLinker != null)
|
if (ProtocolLinker != null)
|
||||||
@@ -47,7 +47,7 @@ namespace Modbus.Net
|
|||||||
await ProtocolLinker.SendReceiveAsync(ProtocolUnit<byte[], byte[]>.TranslateContent(endian, content)),
|
await ProtocolLinker.SendReceiveAsync(ProtocolUnit<byte[], byte[]>.TranslateContent(endian, content)),
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
return new PipeUnit(ProtocolLinker, null, ReturnParams, false);
|
return new PipeUnit(ProtocolLinker, null, ReturnParams, Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -62,8 +62,18 @@ namespace Modbus.Net
|
|||||||
{
|
{
|
||||||
var receiveContent = await SendReceiveAsyncParamOut(unit, inputStructCreator);
|
var receiveContent = await SendReceiveAsyncParamOut(unit, inputStructCreator);
|
||||||
if (receiveContent != null)
|
if (receiveContent != null)
|
||||||
return new PipeUnit(ProtocolLinker, unit,
|
{
|
||||||
receiveContent, true);
|
if (receiveContent.Length > 0)
|
||||||
|
{
|
||||||
|
return new PipeUnit(ProtocolLinker, unit,
|
||||||
|
receiveContent, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new PipeUnit(ProtocolLinker, unit,
|
||||||
|
receiveContent, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
return new PipeUnit(ProtocolLinker, unit, ReturnParams,
|
return new PipeUnit(ProtocolLinker, unit, ReturnParams,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
@@ -106,7 +116,7 @@ namespace Modbus.Net
|
|||||||
/// <param name="protocolUnit">协议单元</param>
|
/// <param name="protocolUnit">协议单元</param>
|
||||||
/// <param name="parameters">输入参数</param>
|
/// <param name="parameters">输入参数</param>
|
||||||
/// <param name="success">上一次管道结果是否成功</param>
|
/// <param name="success">上一次管道结果是否成功</param>
|
||||||
protected PipeUnit(TProtocolLinker protocolLinker, TProtocolUnit protocolUnit, TParamOut parameters, bool success)
|
protected PipeUnit(TProtocolLinker protocolLinker, TProtocolUnit protocolUnit, TParamOut parameters, bool? success)
|
||||||
{
|
{
|
||||||
ProtocolLinker = protocolLinker;
|
ProtocolLinker = protocolLinker;
|
||||||
ProtocolUnit = protocolUnit;
|
ProtocolUnit = protocolUnit;
|
||||||
@@ -132,7 +142,7 @@ namespace Modbus.Net
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 本次管道是否成功
|
/// 本次管道是否成功
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Success { get; }
|
public bool? Success { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 向设备发送数据,返回输出参数
|
/// 向设备发送数据,返回输出参数
|
||||||
@@ -143,7 +153,7 @@ namespace Modbus.Net
|
|||||||
protected async Task<TParamOut> SendReceiveAsyncParamOut(TProtocolUnit unit,
|
protected async Task<TParamOut> SendReceiveAsyncParamOut(TProtocolUnit unit,
|
||||||
Func<TParamOut, IInputStruct> inputStructCreator)
|
Func<TParamOut, IInputStruct> inputStructCreator)
|
||||||
{
|
{
|
||||||
if (Success)
|
if (Success == true)
|
||||||
{
|
{
|
||||||
var content = inputStructCreator.Invoke(ReturnParams);
|
var content = inputStructCreator.Invoke(ReturnParams);
|
||||||
var formatContent = unit.Format(content);
|
var formatContent = unit.Format(content);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 操作是否成功
|
/// 操作是否成功
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsSuccess { get; set; }
|
public bool? IsSuccess { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 错误代码
|
/// 错误代码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -46,7 +46,8 @@
|
|||||||
"Host": "opc.tcp://localhost/test"
|
"Host": "opc.tcp://localhost/test"
|
||||||
},
|
},
|
||||||
"Controller": {
|
"Controller": {
|
||||||
"WaitingListCount": "100"
|
"WaitingListCount": "100",
|
||||||
|
"NoResponse": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,8 @@
|
|||||||
"Host": "opc.tcp://localhost/test"
|
"Host": "opc.tcp://localhost/test"
|
||||||
},
|
},
|
||||||
"Controller": {
|
"Controller": {
|
||||||
"WaitingListCount": "100"
|
"WaitingListCount": "100",
|
||||||
|
"NoResponse": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,8 @@
|
|||||||
"Host": "opc.tcp://localhost/test"
|
"Host": "opc.tcp://localhost/test"
|
||||||
},
|
},
|
||||||
"Controller": {
|
"Controller": {
|
||||||
"WaitingListCount": "100"
|
"WaitingListCount": "100",
|
||||||
|
"NoResponse": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,7 @@ namespace MachineJob.Service
|
|||||||
private Dictionary<string, double>? QueryConsole(DataReturnDef dataReturnDef)
|
private Dictionary<string, double>? QueryConsole(DataReturnDef dataReturnDef)
|
||||||
{
|
{
|
||||||
var values = dataReturnDef.ReturnValues.Datas;
|
var values = dataReturnDef.ReturnValues.Datas;
|
||||||
if (dataReturnDef.ReturnValues.IsSuccess)
|
if (dataReturnDef.ReturnValues.IsSuccess == true)
|
||||||
{
|
{
|
||||||
foreach (var value in values)
|
foreach (var value in values)
|
||||||
{
|
{
|
||||||
@@ -135,6 +135,19 @@ namespace MachineJob.Service
|
|||||||
|
|
||||||
return values.MapGetValuesToSetValues();
|
return values.MapGetValuesToSetValues();
|
||||||
}
|
}
|
||||||
|
else if(dataReturnDef.ReturnValues.IsSuccess == null)
|
||||||
|
{
|
||||||
|
Random r = new Random();
|
||||||
|
|
||||||
|
Dictionary<string, double> ans = new Dictionary<string, double>();
|
||||||
|
|
||||||
|
for (int i = 0; i< 10; i++)
|
||||||
|
{
|
||||||
|
ans["Test" + (i+1)] = r.Next(65536) - 32768;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,8 @@
|
|||||||
"Host": "opc.tcp://localhost/test"
|
"Host": "opc.tcp://localhost/test"
|
||||||
},
|
},
|
||||||
"Controller": {
|
"Controller": {
|
||||||
"WaitingListCount": "100"
|
"WaitingListCount": "100",
|
||||||
|
"NoResponse": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,8 @@
|
|||||||
"Host": "opc.tcp://localhost/test"
|
"Host": "opc.tcp://localhost/test"
|
||||||
},
|
},
|
||||||
"Controller": {
|
"Controller": {
|
||||||
"WaitingListCount": "100"
|
"WaitingListCount": "100",
|
||||||
|
"NoResponse": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user