NoResponseController

This commit is contained in:
luosheng
2023-09-07 09:08:26 +08:00
parent 3acd6aa1e0
commit fac39b0bf1
26 changed files with 384 additions and 57 deletions

View File

@@ -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;
@@ -15,9 +16,19 @@ namespace Modbus.Net.HJ212
/// </summary> /// </summary>
public HJ212Protocol(string ip) public HJ212Protocol(string ip)
: base(0, 0, Endian.BigEndianLsb) : base(0, 0, Endian.BigEndianLsb)
{
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")); 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);
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -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]);

View File

@@ -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]);

View File

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

View File

@@ -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]);

View File

@@ -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]);

View File

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

View File

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

View 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);
}
}
}
}
}

View File

@@ -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);
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); this.AddController(new object[2] { com, slaveAddress }, BaseConnector);
} }
} }
} }
}

View File

@@ -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);
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); this.AddController(new object[2] { ip, port }, BaseConnector);
} }
} }
} }
}

View File

@@ -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);
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); this.AddController(new object[2] { ip, port }, BaseConnector);
} }
} }
} }
}

View File

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

View File

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

View File

@@ -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)
{
if (receiveContent.Length > 0)
{
return new PipeUnit(ProtocolLinker, unit, return new PipeUnit(ProtocolLinker, unit,
receiveContent, true); 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);

View File

@@ -13,7 +13,7 @@
/// <summary> /// <summary>
/// 操作是否成功 /// 操作是否成功
/// </summary> /// </summary>
public bool IsSuccess { get; set; } public bool? IsSuccess { get; set; }
/// <summary> /// <summary>
/// 错误代码 /// 错误代码
/// </summary> /// </summary>

View File

@@ -46,7 +46,8 @@
"Host": "opc.tcp://localhost/test" "Host": "opc.tcp://localhost/test"
}, },
"Controller": { "Controller": {
"WaitingListCount": "100" "WaitingListCount": "100",
"NoResponse": false
} }
} }
} }

View File

@@ -46,7 +46,8 @@
"Host": "opc.tcp://localhost/test" "Host": "opc.tcp://localhost/test"
}, },
"Controller": { "Controller": {
"WaitingListCount": "100" "WaitingListCount": "100",
"NoResponse": false
} }
} }
} }

View File

@@ -46,7 +46,8 @@
"Host": "opc.tcp://localhost/test" "Host": "opc.tcp://localhost/test"
}, },
"Controller": { "Controller": {
"WaitingListCount": "100" "WaitingListCount": "100",
"NoResponse": false
} }
} }
} }

View File

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

View File

@@ -46,7 +46,8 @@
"Host": "opc.tcp://localhost/test" "Host": "opc.tcp://localhost/test"
}, },
"Controller": { "Controller": {
"WaitingListCount": "100" "WaitingListCount": "100",
"NoResponse": false
} }
} }
} }

View File

@@ -46,7 +46,8 @@
"Host": "opc.tcp://localhost/test" "Host": "opc.tcp://localhost/test"
}, },
"Controller": { "Controller": {
"WaitingListCount": "100" "WaitingListCount": "100",
"NoResponse": false
} }
} }
} }