diff --git a/Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs b/Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs index 6ec4256..e704324 100644 --- a/Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs +++ b/Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; using System.Threading.Tasks; @@ -16,7 +17,17 @@ namespace Modbus.Net.HJ212 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")); + 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")); + } } /// @@ -43,7 +54,7 @@ namespace Modbus.Net.HJ212 public override byte[] Format(IInputStruct message) { var r_message = (WriteRequestHJ212InputStruct)message; - string formatMessage = "##0633"; + string formatMessage = ""; formatMessage += "QN=" + r_message.QN + ";"; formatMessage += "ST=" + r_message.ST + ";"; formatMessage += "CN=" + r_message.CN + ";"; @@ -61,7 +72,6 @@ namespace Modbus.Net.HJ212 formatMessage += ";"; } formatMessage = formatMessage[..^1]; - formatMessage += "&&"; return Encoding.ASCII.GetBytes(formatMessage); } diff --git a/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinkerBytesExtend.cs b/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinkerBytesExtend.cs index d07317f..c006b2a 100644 --- a/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinkerBytesExtend.cs +++ b/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinkerBytesExtend.cs @@ -15,14 +15,21 @@ namespace Modbus.Net.HJ212 /// 扩展后的协议内容 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校验 - var newFormat = new byte[content.Length + 4]; - Crc16.GetInstance().GetCRC(content, ref crc); - Array.Copy(content, 0, newFormat, 0, content.Length); + var crc = new byte[2]; + Crc16.GetInstance().GetCRC(content, ref crc); string crcString = BitConverter.ToString(crc).Replace("-", string.Empty); + crcString = "&&" + 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; } diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInTcpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInTcpProtocolLinker.cs index 4844887..2e6cb9f 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInTcpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInTcpProtocolLinker.cs @@ -33,8 +33,7 @@ namespace Modbus.Net.Modbus /// 校验是否正确 public override bool? CheckRight(byte[] content) { - //ProtocolLinker不会返回null - if (base.CheckRight(content) != true) return false; + if (base.CheckRight(content) != true) return base.CheckRight(content); //Modbus协议错误 var contentString = Encoding.ASCII.GetString(content); if (byte.Parse(contentString.Substring(3, 2)) > 127) diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInUdpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInUdpProtocolLinker.cs index bda4526..dc3efaf 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInUdpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInUdpProtocolLinker.cs @@ -33,8 +33,7 @@ namespace Modbus.Net.Modbus /// 校验是否正确 public override bool? CheckRight(byte[] content) { - //ProtocolLinker不会返回null - if (base.CheckRight(content) != true) return false; + if (base.CheckRight(content) != true) return base.CheckRight(content); //Modbus协议错误 var contentString = Encoding.ASCII.GetString(content); if (byte.Parse(contentString.Substring(3, 2)) > 127) diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocolLinker.cs index 14cb1b7..f552984 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocolLinker.cs @@ -24,8 +24,7 @@ namespace Modbus.Net.Modbus /// 校验是否正确 public override bool? CheckRight(byte[] content) { - //ProtocolLinker不会返回null - if (base.CheckRight(content) != true) return false; + if (base.CheckRight(content) != true) return base.CheckRight(content); //Modbus协议错误 var contentString = Encoding.ASCII.GetString(content); if (byte.Parse(contentString.Substring(3, 2)) > 127) diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInTcpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInTcpProtocolLinker.cs index 270b72c..47f190d 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInTcpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInTcpProtocolLinker.cs @@ -31,8 +31,7 @@ /// 数据是否正确 public override bool? CheckRight(byte[] content) { - //ProtocolLinker的CheckRight不会返回null - if (base.CheckRight(content) != true) return false; + if (base.CheckRight(content) != true) return base.CheckRight(content); //Modbus协议错误 if (content[1] > 127) throw new ModbusProtocolErrorException(content[2]); diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInUdpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInUdpProtocolLinker.cs index d11f31f..6910449 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInUdpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInUdpProtocolLinker.cs @@ -31,8 +31,7 @@ /// 数据是否正确 public override bool? CheckRight(byte[] content) { - //ProtocolLinker的CheckRight不会返回null - if (base.CheckRight(content) != true) return false; + if (base.CheckRight(content) != true) return base.CheckRight(content); //Modbus协议错误 if (content[1] > 127) throw new ModbusProtocolErrorException(content[2]); diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolLinker.cs index f9b3953..aaeb218 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolLinker.cs @@ -22,8 +22,7 @@ /// 数据是否正确 public override bool? CheckRight(byte[] content) { - //ProtocolLinker的CheckRight不会返回null - if (base.CheckRight(content) != true) return false; + if (base.CheckRight(content) != true) return base.CheckRight(content); //CRC校验失败 if (!Crc16.GetInstance().CrcEfficacy(content)) throw new ModbusProtocolErrorException(501); diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocolLinker.cs index 4f678e0..1ba6cea 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocolLinker.cs @@ -30,8 +30,7 @@ /// 数据是否正确 public override bool? CheckRight(byte[] content) { - //ProtocolLinker的CheckRight不会返回null - if (base.CheckRight(content) != true) return false; + if (base.CheckRight(content) != true) return base.CheckRight(content); //Modbus协议错误 if (content[7] > 127) throw new ModbusProtocolErrorException(content[2] > 0 ? content[2] : content[8]); diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusUdpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusUdpProtocolLinker.cs index 7bd93db..34f19ac 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusUdpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusUdpProtocolLinker.cs @@ -30,8 +30,7 @@ /// 数据是否正确 public override bool? CheckRight(byte[] content) { - //ProtocolLinker的CheckRight不会返回null - if (base.CheckRight(content) != true) return false; + if (base.CheckRight(content) != true) return base.CheckRight(content); //Modbus协议错误 if (content[7] > 127) throw new ModbusProtocolErrorException(content[2] > 0 ? content[2] : content[8]); diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs index 45495b7..b7293ce 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs @@ -264,7 +264,7 @@ namespace Modbus.Net.Modbus return new ReturnStruct { Datas = outputStruct?.DataValue, - IsSuccess = true, + IsSuccess = outputStruct == null ? null : true, ErrorCode = 0, ErrorMsg = "" }; @@ -325,7 +325,7 @@ namespace Modbus.Net.Modbus return new ReturnStruct() { Datas = outputStruct.OutputData, - IsSuccess = true, + IsSuccess = outputStruct == null ? null : true, ErrorCode = 0, ErrorMsg = null }; @@ -355,7 +355,7 @@ namespace Modbus.Net.Modbus return new ReturnStruct() { Datas = new DiagnoticsData() { SubFunction = outputStruct.SubFunction, Data = outputStruct.Data }, - IsSuccess = true, + IsSuccess = outputStruct == null ? null : true, ErrorCode = 0, ErrorMsg = null }; @@ -385,7 +385,7 @@ namespace Modbus.Net.Modbus return new ReturnStruct() { Datas = new CommEventCounterData() { EventCount = outputStruct.EventCount, Status = outputStruct.Status }, - IsSuccess = true, + IsSuccess = outputStruct == null ? null : true, ErrorCode = 0, ErrorMsg = null }; @@ -415,7 +415,7 @@ namespace Modbus.Net.Modbus return new ReturnStruct() { Datas = new CommEventLogData() { Status = outputStruct.Status, Events = outputStruct.Events }, - IsSuccess = true, + IsSuccess = outputStruct == null ? null : true, ErrorCode = 0, ErrorMsg = null }; @@ -445,7 +445,7 @@ namespace Modbus.Net.Modbus return new ReturnStruct() { Datas = new SlaveIdData() { SlaveId = outputStruct.SlaveId, IndicatorStatus = outputStruct.RunIndicatorStatus, AdditionalData = outputStruct.AdditionalData }, - IsSuccess = true, + IsSuccess = outputStruct == null ? null : true, ErrorCode = 0, ErrorMsg = null }; @@ -475,7 +475,7 @@ namespace Modbus.Net.Modbus return new ReturnStruct() { Datas = outputStruct.RecordDefs, - IsSuccess = true, + IsSuccess = outputStruct == null ? null : true, ErrorCode = 0, ErrorMsg = null }; @@ -505,7 +505,7 @@ namespace Modbus.Net.Modbus return new ReturnStruct() { Datas = outputStruct.WriteRecords, - IsSuccess = true, + IsSuccess = outputStruct == null ? null : true, ErrorCode = 0, ErrorMsg = null }; @@ -535,7 +535,7 @@ namespace Modbus.Net.Modbus return new ReturnStruct() { Datas = new MaskRegisterData() { ReferenceAddress = outputStruct.ReferenceAddress, AndMask = outputStruct.AndMask, OrMask = outputStruct.OrMask }, - IsSuccess = true, + IsSuccess = outputStruct == null ? null : true, ErrorCode = 0, ErrorMsg = null }; @@ -565,7 +565,7 @@ namespace Modbus.Net.Modbus return new ReturnStruct() { Datas = outputStruct.ReadRegisterValues, - IsSuccess = true, + IsSuccess = outputStruct == null ? null : true, ErrorCode = 0, ErrorMsg = null }; @@ -595,7 +595,7 @@ namespace Modbus.Net.Modbus return new ReturnStruct() { Datas = outputStruct.FIFOValueRegister, - IsSuccess = true, + IsSuccess = outputStruct == null ? null : true, ErrorCode = 0, ErrorMsg = null }; diff --git a/Modbus.Net/Modbus.Net/Connector/BaseConnector.cs b/Modbus.Net/Modbus.Net/Connector/BaseConnector.cs index 3a315c9..5f83e7a 100644 --- a/Modbus.Net/Modbus.Net/Connector/BaseConnector.cs +++ b/Modbus.Net/Modbus.Net/Connector/BaseConnector.cs @@ -6,7 +6,7 @@ namespace Modbus.Net /// public abstract partial class BaseConnector : BaseConnector { - private static readonly ILogger logger = LogProvider.CreateLogger(); + private static readonly ILogger logger = LogProvider.CreateLogger(); } /// diff --git a/Modbus.Net/Modbus.Net/Controller/NoResponseController.cs b/Modbus.Net/Modbus.Net/Controller/NoResponseController.cs new file mode 100644 index 0000000..5b686ef --- /dev/null +++ b/Modbus.Net/Modbus.Net/Controller/NoResponseController.cs @@ -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 +{ + /// + /// 控制器基类 + /// + public class NoResponseController : IController + { + private static readonly ILogger logger = LogProvider.CreateLogger(); + + /// + /// 等待的消息队列 + /// + protected List WaitingMessages { get; set; } + + /// + /// 消息维护线程 + /// + protected Task SendingThread { get; set; } + + /// + /// 间隔时间 + /// + public int AcquireTime { get; } + + /// + /// 消息维护线程是否在运行 + /// + public virtual bool IsSending => SendingThread != null; + + private MessageWaitingDef _currentSendingPos; + + private CancellationTokenSource _sendingThreadCancel; + + /// + /// 构造器 + /// + public NoResponseController(int acquireTime) + { + WaitingMessages = new List(); + AcquireTime = acquireTime; + } + + /// + 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; + } + + /// + /// 发送消息的实际内部方法 + /// + 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(); + } + } + } + + /// + public virtual void SendStop() + { + Clear(); + _sendingThreadCancel?.Cancel(); + if (SendingThread != null) + { + while (!SendingThread.IsCanceled) + { + Thread.Sleep(10); + } + SendingThread.Dispose(); + SendingThread = null; + } + Clear(); + } + + /// + 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; + } + } + } + + /// + public void Clear() + { + if (WaitingMessages != null) + { + lock (WaitingMessages) + { + WaitingMessages.Clear(); + } + } + } + + /// + /// 将信息添加到队列 + /// + /// 需要添加的信息信息 + 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; + } + + /// + /// 获取信息的检索关键字 + /// + /// 待确认的信息 + /// 信息的检索关键字 + protected (string, string)? GetKeyFromMessage(byte[] message) + { + return null; + } + + /// + public ICollection<(byte[], bool)> ConfirmMessage(byte[] receiveMessage) + { + var ans = new List<(byte[], bool)> + { + (receiveMessage, true) + }; + return ans; + } + + /// + /// 从等待队列中匹配信息 + /// + /// 返回的信息 + /// 从等待队列中匹配的信息 + protected MessageWaitingDef GetMessageFromWaitingList(byte[] receiveMessage) + { + MessageWaitingDef ans; + lock (WaitingMessages) + { + ans = WaitingMessages.FirstOrDefault(); + } + return ans; + } + + /// + public void ForceRemoveWaitingMessage(MessageWaitingDef def) + { + lock (WaitingMessages) + { + if (WaitingMessages.IndexOf(def) >= 0) + { + WaitingMessages.Remove(def); + } + } + } + } +} \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/Linker/ComProtocolLinker.cs b/Modbus.Net/Modbus.Net/Linker/ComProtocolLinker.cs index 361c6b6..dbb9f24 100644 --- a/Modbus.Net/Modbus.Net/Linker/ComProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net/Linker/ComProtocolLinker.cs @@ -31,7 +31,15 @@ namespace Modbus.Net 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")); 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)BaseConnector).AddController(new NoResponseController(int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime")))); + } + else + { + this.AddController(new object[2] { com, slaveAddress }, BaseConnector); + } } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/Linker/TcpProtocolLinker.cs b/Modbus.Net/Modbus.Net/Linker/TcpProtocolLinker.cs index 4ef9b99..16ded16 100644 --- a/Modbus.Net/Modbus.Net/Linker/TcpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net/Linker/TcpProtocolLinker.cs @@ -18,7 +18,15 @@ isFullDuplex = bool.Parse(isFullDuplex != null ? isFullDuplex.ToString() : null ?? ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FullDuplex")); //初始化连接对象 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)BaseConnector).AddController(new NoResponseController(int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FetchSleepTime")))); + } + else + { + this.AddController(new object[2] { ip, port }, BaseConnector); + } } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/Linker/UdpProtocolLinker.cs b/Modbus.Net/Modbus.Net/Linker/UdpProtocolLinker.cs index 6fb4d93..aea3411 100644 --- a/Modbus.Net/Modbus.Net/Linker/UdpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net/Linker/UdpProtocolLinker.cs @@ -18,7 +18,15 @@ isFullDuplex = bool.Parse(isFullDuplex != null ? isFullDuplex.ToString() : null ?? ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FullDuplex")); //初始化连接对象 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)BaseConnector).AddController(new NoResponseController(int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FetchSleepTime")))); + } + else + { + this.AddController(new object[2] { ip, port }, BaseConnector); + } } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/Machine/BaseMachine.cs b/Modbus.Net/Modbus.Net/Machine/BaseMachine.cs index 59a6fd3..b659df7 100644 --- a/Modbus.Net/Modbus.Net/Machine/BaseMachine.cs +++ b/Modbus.Net/Modbus.Net/Machine/BaseMachine.cs @@ -98,9 +98,19 @@ namespace Modbus.Net ValueHelper.ByteLength[ communicateAddress.DataType.FullName])); - + //如果已知没有返回,终止 + if (datas.IsSuccess == null) + { + return new ReturnStruct>>() + { + 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>>() { @@ -336,6 +346,14 @@ namespace Modbus.Net //如果设备本身能获取到数据但是没有数据 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) { diff --git a/Modbus.Net/Modbus.Net/Protocol/BaseProtocol.cs b/Modbus.Net/Modbus.Net/Protocol/BaseProtocol.cs index 6036fd8..513dfd0 100644 --- a/Modbus.Net/Modbus.Net/Protocol/BaseProtocol.cs +++ b/Modbus.Net/Modbus.Net/Protocol/BaseProtocol.cs @@ -185,7 +185,12 @@ namespace Modbus.Net public virtual async Task SendReceiveAsync(TProtocolUnit unit, IInputStruct content) where T : class, IOutputStruct { - return (await SendReceiveAsync(unit, content)).Unwrap(); + var ans = await SendReceiveAsync(unit, content); + if (ans.Success == null) + { + return null; + } + return ans.Unwrap(); } /// diff --git a/Modbus.Net/Modbus.Net/Protocol/PipeUnit.cs b/Modbus.Net/Modbus.Net/Protocol/PipeUnit.cs index 53443e6..71b98ab 100644 --- a/Modbus.Net/Modbus.Net/Protocol/PipeUnit.cs +++ b/Modbus.Net/Modbus.Net/Protocol/PipeUnit.cs @@ -27,7 +27,7 @@ namespace Modbus.Net /// 传递给输入结构的参数 /// 上次的管道是否成功执行 protected PipeUnit(IProtocolLinker protocolLinker, ProtocolUnit protocolUnit, byte[] parameters, - bool success) : base(protocolLinker, protocolUnit, parameters, success) + bool? success) : base(protocolLinker, protocolUnit, parameters, success) { } @@ -39,7 +39,7 @@ namespace Modbus.Net /// 发送完成之后新的管道实例 public async Task SendReceiveAsync(Endian endian, Func inputStructCreator) { - if (Success) + if (Success == true) { var content = inputStructCreator.Invoke(ReturnParams); if (ProtocolLinker != null) @@ -47,7 +47,7 @@ namespace Modbus.Net await ProtocolLinker.SendReceiveAsync(ProtocolUnit.TranslateContent(endian, content)), true); } - return new PipeUnit(ProtocolLinker, null, ReturnParams, false); + return new PipeUnit(ProtocolLinker, null, ReturnParams, Success); } /// @@ -62,8 +62,18 @@ namespace Modbus.Net { var receiveContent = await SendReceiveAsyncParamOut(unit, inputStructCreator); 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, false); } @@ -106,7 +116,7 @@ namespace Modbus.Net /// 协议单元 /// 输入参数 /// 上一次管道结果是否成功 - protected PipeUnit(TProtocolLinker protocolLinker, TProtocolUnit protocolUnit, TParamOut parameters, bool success) + protected PipeUnit(TProtocolLinker protocolLinker, TProtocolUnit protocolUnit, TParamOut parameters, bool? success) { ProtocolLinker = protocolLinker; ProtocolUnit = protocolUnit; @@ -132,7 +142,7 @@ namespace Modbus.Net /// /// 本次管道是否成功 /// - public bool Success { get; } + public bool? Success { get; } /// /// 向设备发送数据,返回输出参数 @@ -143,7 +153,7 @@ namespace Modbus.Net protected async Task SendReceiveAsyncParamOut(TProtocolUnit unit, Func inputStructCreator) { - if (Success) + if (Success == true) { var content = inputStructCreator.Invoke(ReturnParams); var formatContent = unit.Format(content); diff --git a/Modbus.Net/Modbus.Net/ReturnStruct/ReturnStruct.cs b/Modbus.Net/Modbus.Net/ReturnStruct/ReturnStruct.cs index 04c13a5..6f5d9ae 100644 --- a/Modbus.Net/Modbus.Net/ReturnStruct/ReturnStruct.cs +++ b/Modbus.Net/Modbus.Net/ReturnStruct/ReturnStruct.cs @@ -13,7 +13,7 @@ /// /// 操作是否成功 /// - public bool IsSuccess { get; set; } + public bool? IsSuccess { get; set; } /// /// 错误代码 /// diff --git a/Modbus.Net/Modbus.Net/appsettings.default.json b/Modbus.Net/Modbus.Net/appsettings.default.json index 4f22fec..edc739c 100644 --- a/Modbus.Net/Modbus.Net/appsettings.default.json +++ b/Modbus.Net/Modbus.Net/appsettings.default.json @@ -46,7 +46,8 @@ "Host": "opc.tcp://localhost/test" }, "Controller": { - "WaitingListCount": "100" + "WaitingListCount": "100", + "NoResponse": false } } } \ No newline at end of file diff --git a/Samples/AnyType/appsettings.default.json b/Samples/AnyType/appsettings.default.json index 4f22fec..edc739c 100644 --- a/Samples/AnyType/appsettings.default.json +++ b/Samples/AnyType/appsettings.default.json @@ -46,7 +46,8 @@ "Host": "opc.tcp://localhost/test" }, "Controller": { - "WaitingListCount": "100" + "WaitingListCount": "100", + "NoResponse": false } } } \ No newline at end of file diff --git a/Samples/CrossLamp/appsettings.default.json b/Samples/CrossLamp/appsettings.default.json index 4f22fec..edc739c 100644 --- a/Samples/CrossLamp/appsettings.default.json +++ b/Samples/CrossLamp/appsettings.default.json @@ -46,7 +46,8 @@ "Host": "opc.tcp://localhost/test" }, "Controller": { - "WaitingListCount": "100" + "WaitingListCount": "100", + "NoResponse": false } } } \ No newline at end of file diff --git a/Samples/MachineJob/Worker.cs b/Samples/MachineJob/Worker.cs index a5b9a8d..07c2cf2 100644 --- a/Samples/MachineJob/Worker.cs +++ b/Samples/MachineJob/Worker.cs @@ -93,7 +93,7 @@ namespace MachineJob.Service private Dictionary? QueryConsole(DataReturnDef dataReturnDef) { var values = dataReturnDef.ReturnValues.Datas; - if (dataReturnDef.ReturnValues.IsSuccess) + if (dataReturnDef.ReturnValues.IsSuccess == true) { foreach (var value in values) { @@ -135,6 +135,19 @@ namespace MachineJob.Service return values.MapGetValuesToSetValues(); } + else if(dataReturnDef.ReturnValues.IsSuccess == null) + { + Random r = new Random(); + + Dictionary ans = new Dictionary(); + + for (int i = 0; i< 10; i++) + { + ans["Test" + (i+1)] = r.Next(65536) - 32768; + } + + return ans; + } return null; } } diff --git a/Samples/MachineJob/appsettings.default.json b/Samples/MachineJob/appsettings.default.json index 4f22fec..edc739c 100644 --- a/Samples/MachineJob/appsettings.default.json +++ b/Samples/MachineJob/appsettings.default.json @@ -46,7 +46,8 @@ "Host": "opc.tcp://localhost/test" }, "Controller": { - "WaitingListCount": "100" + "WaitingListCount": "100", + "NoResponse": false } } } \ No newline at end of file diff --git a/Samples/TripleAdd/appsettings.default.json b/Samples/TripleAdd/appsettings.default.json index 4f22fec..edc739c 100644 --- a/Samples/TripleAdd/appsettings.default.json +++ b/Samples/TripleAdd/appsettings.default.json @@ -46,7 +46,8 @@ "Host": "opc.tcp://localhost/test" }, "Controller": { - "WaitingListCount": "100" + "WaitingListCount": "100", + "NoResponse": false } } } \ No newline at end of file