Example #1
0
		internal static void AssertModbusMessagePropertiesAreEqual(IModbusMessage obj1, IModbusMessage obj2)
		{
			Assert.AreEqual(obj1.FunctionCode, obj2.FunctionCode);
			Assert.AreEqual(obj1.SlaveAddress, obj2.SlaveAddress);
			Assert.AreEqual(obj1.MessageFrame, obj2.MessageFrame);
			Assert.AreEqual(obj1.ProtocolDataUnit, obj2.ProtocolDataUnit);
		}
        public void ValidateResponse(IModbusMessage response)
        {
            ReadHoldingInputRegistersResponse typedResponse = (ReadHoldingInputRegistersResponse) response;

            int expectedByteCount = ReadRequest.NumberOfPoints * 2;
            if (expectedByteCount != typedResponse.ByteCount)
            {
                throw new IOException(String.Format(CultureInfo.InvariantCulture,
                    "Unexpected byte count in response. Expected {0}, received {1}.", expectedByteCount, typedResponse.ByteCount));
            }
        }
        public void ValidateResponse(IModbusMessage response)
        {
            ReadCoilsInputsResponse typedResponse = (ReadCoilsInputsResponse) response;

            // best effort validation - the same response for a request for 1 vs 6 coils (same byte count) will pass validation.
            int expectedByteCount = (NumberOfPoints + 7) / 8;
            if (expectedByteCount != typedResponse.ByteCount)
            {
                throw new IOException(String.Format(CultureInfo.InvariantCulture,
                    "Unexpected byte count. Expected {0}, received {1}.", expectedByteCount, typedResponse.ByteCount));
            }
        }
        public void ValidateResponse(IModbusMessage response)
        {
            var typedResponse = response as ReadHoldingInputRegistersResponse;
            Debug.Assert(typedResponse != null, "Argument response should be of type ReadHoldingInputRegistersResponse.");
            var expectedByteCount = NumberOfPoints * 2;

            if (expectedByteCount != typedResponse.ByteCount)
            {
                throw new IOException(String.Format(CultureInfo.InvariantCulture,
                    "Unexpected byte count. Expected {0}, received {1}.",
                    expectedByteCount,
                    typedResponse.ByteCount));
            }
        }
Example #5
0
        internal virtual T UnicastMessage <T>(IModbusMessage message)
            where T : IModbusMessage, new()
        {
            IModbusMessage response = null;
            int            attempt  = 1;
            bool           success  = false;

            do
            {
                try
                {
                    lock (_syncLock)
                    {
                        Write(message);

                        bool readAgain;
                        do
                        {
                            readAgain = false;
                            response  = ReadResponse <T>();

                            if (response is SlaveExceptionResponse exceptionResponse)
                            {
                                // if SlaveExceptionCode == ACKNOWLEDGE we retry reading the response without resubmitting request
                                readAgain = exceptionResponse.SlaveExceptionCode == Modbus.Acknowledge;

                                if (readAgain)
                                {
                                    Debug.WriteLine($"Received ACKNOWLEDGE slave exception response, waiting {_waitToRetryMilliseconds} milliseconds and retrying to read response.");
                                    Sleep(WaitToRetryMilliseconds);
                                }
                                else
                                {
                                    throw new SlaveException(exceptionResponse);
                                }
                            }
                            else if (ShouldRetryResponse(message, response))
                            {
                                readAgain = true;
                            }
                        }while (readAgain);
                    }

                    ValidateResponse(message, response);
                    success = true;
                }
                catch (SlaveException se)
                {
                    if (se.SlaveExceptionCode != Modbus.SlaveDeviceBusy)
                    {
                        throw;
                    }

                    if (SlaveBusyUsesRetryCount && attempt++ > _retries)
                    {
                        throw;
                    }

                    Debug.WriteLine($"Received SLAVE_DEVICE_BUSY exception response, waiting {_waitToRetryMilliseconds} milliseconds and resubmitting request.");
                    Sleep(WaitToRetryMilliseconds);
                }
                catch (Exception e)
                {
                    if (e is FormatException ||
                        e is NotImplementedException ||
                        e is TimeoutException ||
                        e is IOException)
                    {
                        Debug.WriteLine($"{e.GetType().Name}, {_retries - attempt + 1} retries remaining - {e}");

                        if (attempt++ > _retries)
                        {
                            throw;
                        }
                    }
                    else
                    {
                        throw;
                    }
                }
            }while (!success);

            return((T)response);
        }
        // TODO unit test
        internal IModbusMessage ApplyRequest(IModbusMessage request)
        {
            IModbusMessage response;
            _log.Info(request.ToString());

            switch (request.FunctionCode)
            {
                case Modbus.ReadCoils:
                    response = ReadDiscretes((ReadCoilsInputsRequest) request, DataStore.CoilDiscretes);
                    break;
                case Modbus.ReadInputs:
                    response = ReadDiscretes((ReadCoilsInputsRequest) request, DataStore.InputDiscretes);
                    break;
                case Modbus.ReadHoldingRegisters:
                    response = ReadRegisters((ReadHoldingInputRegistersRequest) request, DataStore.HoldingRegisters);
                    break;
                case Modbus.ReadInputRegisters:
                    response = ReadRegisters((ReadHoldingInputRegistersRequest) request, DataStore.InputRegisters);
                    break;
                case Modbus.WriteSingleCoil:
                    response = WriteSingleCoil((WriteSingleCoilRequestResponse) request, DataStore.CoilDiscretes);
                    break;
                case Modbus.WriteSingleRegister:
                    response = WriteSingleRegister((WriteSingleRegisterRequestResponse) request, DataStore.HoldingRegisters);
                    break;
                case Modbus.Diagnostics:
                    response = request;
                    break;
                case Modbus.WriteMultipleCoils:
                    response = WriteMultipleCoils((WriteMultipleCoilsRequest) request, DataStore.CoilDiscretes);
                    break;
                case Modbus.WriteMultipleRegisters:
                    response = WriteMultipleRegisters((WriteMultipleRegistersRequest) request, DataStore.HoldingRegisters);
                    break;
                case Modbus.ReadWriteMultipleRegisters:
                    ReadWriteMultipleRegistersRequest readWriteRequest = (ReadWriteMultipleRegistersRequest) request;
                    WriteMultipleRegisters(readWriteRequest.WriteRequest, DataStore.HoldingRegisters);
                    response = ReadRegisters(readWriteRequest.ReadRequest, DataStore.HoldingRegisters);
                    break;
                default:
                    string errorMessage = String.Format("Unsupported function code {0}", request.FunctionCode);
                    _log.Error(errorMessage);
                    throw new ArgumentException(errorMessage, "request");
            }

            return response;
        }
Example #7
0
 internal override void OnValidateResponse(IModbusMessage request, IModbusMessage response)
 {
     // no-op
 }
Example #8
0
 internal override void Write(IModbusMessage message)
 {
     throw new NotImplementedException();
 }
Example #9
0
            public IModbusMessage HandleSlaveRequest(IModbusMessage request, ISlaveDataStore dataStore)
            {
                Console.WriteLine("HMI Buffer Message Receieved");

                throw new NotImplementedException();
            }
Example #10
0
 private Task PerformWriteRequestAsync <T>(IModbusMessage request)
     where T : IModbusMessage, new()
 {
     return(Task.Factory.StartNew(() => Transport.UnicastMessage <T>(request)));
 }
Example #11
0
 internal override bool ChecksumsMatch(IModbusMessage message, byte[] messageFrame)
 {
     return(BitConverter.ToUInt16(messageFrame, messageFrame.Length - 2) == BitConverter.ToUInt16(ModbusUtility.CalculateCrc(message.MessageFrame), 0));
 }
Example #12
0
 internal static void AssertModbusMessagePropertiesAreEqual(IModbusMessage obj1, IModbusMessage obj2)
 {
     Assert.AreEqual(obj1.FunctionCode, obj2.FunctionCode);
     Assert.AreEqual(obj1.SlaveAddress, obj2.SlaveAddress);
     Assert.AreEqual(obj1.MessageFrame, obj2.MessageFrame);
     Assert.AreEqual(obj1.ProtocolDataUnit, obj2.ProtocolDataUnit);
 }
Example #13
0
 internal override void Write(IModbusMessage message)
 {
     byte[] frame = BuildMessageFrame(message);
     _log.InfoFormat("TX: {0}", StringUtility.Join(", ", frame));
     _tcpStreamAdapter.Write(frame, 0, frame.Length);
 }
Example #14
0
        /// <summary>
        /// 通讯正常,把返回的数据返回到此函数接口。在Protocol类中的CheckData函数对数据进行校验。
        /// </summary>
        /// <param name="info"></param>
        public override void Communicate(IResponseInfo info)
        {
            if (_sendObject == null)
            {
                OnDeviceRuningLog("没有获得对应的发送请求实例");
                return;
            }

            byte[]         revData        = info.Data;
            IModbusMessage requestMessage = _sendObject.ModbusMessage;
            ITag           tag            = _sendObject.Tag;
            bool           deal           = false;
            object         val            = null;

            if (tag.Function == Modbus.Modbus.ReadCoils)
            {
                #region
                bool[] responseVals = _modbusTcpMaster.GetReadCoilsResponse(revData, tag.Quantity, requestMessage);
                if (responseVals.Length >= 1)
                {
                    val = responseVals[0] == true ? 1 : 0;
                    this.DeviceDynamic.DynamicData.Write(tag.TagName, val);
                    deal = true;
                }
                #endregion
            }
            else if (tag.Function == Modbus.Modbus.ReadInputs)
            {
                #region
                bool[] responseVals = _modbusTcpMaster.GetReadInputsResponse(revData, tag.Quantity, requestMessage);
                if (responseVals.Length >= 1)
                {
                    val = responseVals[0] == true ? 1 : 0;
                    this.DeviceDynamic.DynamicData.Write(tag.TagName, val);
                    deal = true;
                }
                #endregion
            }
            else if (tag.Function == Modbus.Modbus.ReadHoldingRegisters)
            {
                #region
                ushort[] responseVals = _modbusTcpMaster.GetReadHoldingRegistersResponse(revData, requestMessage);
                if (responseVals.Length >= 1)
                {
                    val = responseVals[0];
                    this.DeviceDynamic.DynamicData.Write(tag.TagName, val);
                    deal = true;
                }
                #endregion
            }
            else if (tag.Function == Modbus.Modbus.ReadInputRegisters)
            {
                #region
                ushort[] responseVals = _modbusTcpMaster.GetReadInputRegistersResponse(revData, requestMessage);
                if (responseVals.Length >= 1)
                {
                    val = responseVals[0];
                    this.DeviceDynamic.DynamicData.Write(tag.TagName, val);
                    deal = true;
                }
                #endregion
            }

            if (deal && val != null)
            {
                OnDeviceRuningLog("通讯正常,已经处理数据,值:" + (val == null ? "未知" : val.ToString()));

                this.DeviceDynamic.Save();
            }
        }
Example #15
0
 public SendObject(IModbusMessage modbusMessage, ITag tag)
 {
     ModbusMessage = modbusMessage;
     Tag           = tag;
 }
Example #16
0
        internal IModbusMessage ApplyRequest(IModbusMessage request)
        {
            IModbusMessage response;
            try
            {
                Debug.WriteLine(request.ToString());
                var eventArgs = new ModbusSlaveRequestEventArgs(request);
                ModbusSlaveRequestReceived.Raise(this, eventArgs);

                switch (request.FunctionCode)
                {
                    case Modbus.ReadCoils:
                        response = ReadDiscretes((ReadCoilsInputsRequest)request, DataStore, DataStore.CoilDiscretes);
                        break;
                    case Modbus.ReadInputs:
                        response = ReadDiscretes((ReadCoilsInputsRequest)request, DataStore, DataStore.InputDiscretes);
                        break;
                    case Modbus.ReadHoldingRegisters:
                        response = ReadRegisters((ReadHoldingInputRegistersRequest)request, DataStore,
                            DataStore.HoldingRegisters);
                        break;
                    case Modbus.ReadInputRegisters:
                        response = ReadRegisters((ReadHoldingInputRegistersRequest)request, DataStore,
                            DataStore.InputRegisters);
                        break;
                    case Modbus.Diagnostics:
                        response = request;
                        break;
                    case Modbus.WriteSingleCoil:
                        response = WriteSingleCoil((WriteSingleCoilRequestResponse)request, DataStore,
                            DataStore.CoilDiscretes);
                        WriteComplete.Raise(this, eventArgs);
                        break;
                    case Modbus.WriteSingleRegister:
                        response = WriteSingleRegister((WriteSingleRegisterRequestResponse)request, DataStore,
                            DataStore.HoldingRegisters);
                        WriteComplete.Raise(this, eventArgs);
                        break;
                    case Modbus.WriteMultipleCoils:
                        response = WriteMultipleCoils((WriteMultipleCoilsRequest)request, DataStore,
                            DataStore.CoilDiscretes);
                        WriteComplete.Raise(this, eventArgs);
                        break;
                    case Modbus.WriteMultipleRegisters:
                        response = WriteMultipleRegisters((WriteMultipleRegistersRequest)request, DataStore,
                            DataStore.HoldingRegisters);
                        WriteComplete.Raise(this, eventArgs);
                        break;
                    case Modbus.ReadWriteMultipleRegisters:
                        ReadWriteMultipleRegistersRequest readWriteRequest = (ReadWriteMultipleRegistersRequest)request;
                        WriteMultipleRegisters(readWriteRequest.WriteRequest, DataStore, DataStore.HoldingRegisters);
                        WriteComplete.Raise(this, eventArgs);
                        response = ReadRegisters(readWriteRequest.ReadRequest, DataStore, DataStore.HoldingRegisters);
                        break;
                    default:
                        string errorMessage = String.Format(CultureInfo.InvariantCulture, "Unsupported function code {0}",
                            request.FunctionCode);
                        Debug.WriteLine(errorMessage);
                        throw new InvalidModbusRequestException(Modbus.IllegalFunction);
                }
            }
            catch (InvalidModbusRequestException ex) // Catches the exception for an illegal function or a custom exception from the ModbusSlaveRequestReceived event.
            {
                response = new SlaveExceptionResponse(request.SlaveAddress, (byte)(Modbus.ExceptionOffset + request.FunctionCode), ex.ExceptionCode);
            }

            return response;
        }
Example #17
0
 public byte[] BuildMessageFrame(IModbusMessage message)
 {
     return(Array.Empty <byte>());
 }
Example #18
0
 internal ModbusSlaveRequestEventArgs(IModbusMessage message)
 {
     Message = message;
 }
 internal override bool ChecksumsMatch(IModbusMessage message, byte[] messageFrame)
 {
     return(ModbusUtility.CalculateLrc(message.MessageFrame) == messageFrame[messageFrame.Length - 1]);
 }
Example #20
0
 public TResponse ExecuteCustomMessage <TResponse>(IModbusMessage request) where TResponse : IModbusMessage, new()
 {
     return((TResponse)request);
 }
Example #21
0
 /// <summary>
 ///     Provide hook to check whether receiving a response should be retried
 /// </summary>
 internal virtual bool OnShouldRetryResponse(IModbusMessage request, IModbusMessage response)
 {
     return(false);
 }
Example #22
0
 public override byte[] BuildMessageFrame(IModbusMessage message)
 {
     throw new NotImplementedException();
 }
Example #23
0
 public TResponse ExecuteCustomMessage <TResponse>(IModbusMessage request) where TResponse : IModbusMessage, new()
 {
     throw new NotImplementedException();
 }
Example #24
0
 public TResponse ExecuteCustomMessage <TResponse>(IModbusMessage request)
     where TResponse : IModbusMessage, new()
 {
     return(Transport.UnicastMessage <TResponse>(request));
 }
Example #25
0
 /// <summary>
 /// Provide hook to do transport level message validation.
 /// </summary>
 internal abstract void OnValidateResponse(IModbusMessage request, IModbusMessage response);
Example #26
0
 internal abstract bool ChecksumsMatch(IModbusMessage message, byte[] messageFrame);
Example #27
0
 internal abstract byte[] BuildMessageFrame(IModbusMessage message);
Example #28
0
        /// <summary>
        /// Start slave listening for requests.
        /// </summary>
        public override void Listen()
        {
            // This external Variable can stop this process
            stop = false;

            while (!stop)
            {
                try
                {
                    try
                    {
                        // read request and build message
                        byte[]         frame   = SerialTransport.ReadRequest();
                        IModbusMessage request = ModbusMessageFactory.CreateModbusRequest(frame);

                        // here for debugging purposes writes what port is being read
                        //                    using (StreamWriter outHandle = new StreamWriter("Output.txt", true))
                        //                    {

                        //                        if (request.FunctionCode == Modbus.ReadHoldingRegisters)
                        //                        {
                        //                            outHandle.WriteLine("{0} Reading Port {1} functioncode {2} startadress {3} points {4}", DateTime.Now.ToString(), request.SlaveAddress, request.FunctionCode,
                        //                                ((ReadHoldingInputRegistersRequest)request).StartAddress, ((ReadHoldingInputRegistersRequest)request).NumberOfPoints);

                        //                        }
                        //                        else if (request.FunctionCode == Modbus.ReadInputRegisters)
                        //                        {
                        //                            outHandle.WriteLine("{0} Reading Port {1} functioncode {2} startadress {3} points {4}", DateTime.Now.ToString(), request.SlaveAddress, request.FunctionCode,
                        //((ReadHoldingInputRegistersRequest)request).StartAddress, ((ReadHoldingInputRegistersRequest)request).NumberOfPoints);
                        //                        }
                        //                        //response = ReadRegisters((ReadHoldingInputRegistersRequest) request, DataStore, DataStore.HoldingRegisters);
                        //                //break;
                        //            //case Modbus.ReadInputRegisters:


                        //                        //outHandle.WriteLine("{0} Reading Port {1}", DateTime.Now.ToString(), request.SlaveAddress, request.FunctionCode );
                        //                    }

                        if (SerialTransport.CheckFrame && !SerialTransport.ChecksumsMatch(request, frame))
                        {
                            string errorMessage = String.Format(CultureInfo.InvariantCulture, "Checksums failed to match {0} != {1}", request.MessageFrame.Join(", "), frame.Join(", "));
                            _logger.Error(errorMessage);
                            throw new IOException(errorMessage);
                        }

                        // only service requests addressed to this particular slave

                        if (m_internalMap != null)
                        {
                            if (!doesIdExist(request.SlaveAddress))
                            {
                                _logger.DebugFormat("NModbus Slave {0} ignoring request intended for NModbus Slave {1}", UnitId, request.SlaveAddress);
                                continue;
                            }
                        }
                        else
                        {
                            if (request.SlaveAddress != UnitId)
                            {
                                _logger.DebugFormat("NModbus Slave {0} ignoring request intended for NModbus Slave {1}", UnitId, request.SlaveAddress);
                                continue;
                            }
                        }

                        // perform action

                        if (m_internalMap != null)
                        {
                            DataStore = m_internalMap[request.SlaveAddress];
                        }



                        IModbusMessage response = ApplyRequest(request);

                        // write response
                        SerialTransport.Write(response);
                    }
                    catch (IOException ioe)
                    {
                        _logger.ErrorFormat("IO Exception encountered while listening for requests - {0}", ioe.Message);
                        SerialTransport.DiscardInBuffer();
                    }
                    catch (TimeoutException te)
                    {
                        _logger.ErrorFormat("Timeout Exception encountered while listening for requests - {0}", te.Message);
                        SerialTransport.DiscardInBuffer();
                    }

                    // TODO better exception handling here, missing FormatException, NotImplemented...
                }
                catch (InvalidOperationException)
                {
                    // when the underlying transport is disposed
                    break;
                }
            }
        }
Example #29
0
 internal abstract void Write(IModbusMessage message);
Example #30
0
 internal override void OnValidateResponse(IModbusMessage request, IModbusMessage response)
 {
     throw new NotImplementedException();
 }
Example #31
0
 public T UnicastMessage <T>(IModbusMessage message) where T : IModbusMessage, new()
 {
     return(new T());
 }
        internal IModbusMessage ApplyRequest(IModbusMessage request)
        {
            _logger.Info(request.ToString());
            EventHandler<ModbusSlaveRequestEventArgs> handler = ModbusSlaveRequestReceived;
            if (handler != null)
                handler(this, new ModbusSlaveRequestEventArgs(request));

            IModbusMessage response;
            switch (request.FunctionCode)
            {
                case Modbus.ReadCoils:
                    response = ReadDiscretes((ReadCoilsInputsRequest) request, DataStore, DataStore.CoilDiscretes);
                    break;
                case Modbus.ReadInputs:
                    response = ReadDiscretes((ReadCoilsInputsRequest) request, DataStore, DataStore.InputDiscretes);
                    break;
                case Modbus.ReadHoldingRegisters:
                    response = ReadRegisters((ReadHoldingInputRegistersRequest) request, DataStore, DataStore.HoldingRegisters);
                    break;
                case Modbus.ReadInputRegisters:
                    response = ReadRegisters((ReadHoldingInputRegistersRequest) request, DataStore, DataStore.InputRegisters);
                    break;
                case Modbus.Diagnostics:
                    response = request;
                    break;
                case Modbus.WriteSingleCoil:
                    response = WriteSingleCoil((WriteSingleCoilRequestResponse) request, DataStore, DataStore.CoilDiscretes);
                    break;
                case Modbus.WriteSingleRegister:
                    response = WriteSingleRegister((WriteSingleRegisterRequestResponse) request, DataStore, DataStore.HoldingRegisters);
                    break;
                case Modbus.WriteMultipleCoils:
                    response = WriteMultipleCoils((WriteMultipleCoilsRequest) request, DataStore, DataStore.CoilDiscretes);
                    break;
                case Modbus.WriteMultipleRegisters:
                    response = WriteMultipleRegisters((WriteMultipleRegistersRequest) request, DataStore, DataStore.HoldingRegisters);
                    break;
                case Modbus.ReadWriteMultipleRegisters:
                    ReadWriteMultipleRegistersRequest readWriteRequest = (ReadWriteMultipleRegistersRequest) request;
                    response = ReadRegisters(readWriteRequest.ReadRequest, DataStore, DataStore.HoldingRegisters);
                    WriteMultipleRegisters(readWriteRequest.WriteRequest, DataStore, DataStore.HoldingRegisters);
                    break;
                default:
                    string errorMessage = String.Format(CultureInfo.InvariantCulture, "Unsupported function code {0}", request.FunctionCode);
                    _logger.Error(errorMessage);
                    throw new ArgumentException(errorMessage, "request");
            }

            return response;
        }
Example #33
0
 internal override void Write(IModbusMessage message)
 {
     byte[] frame = BuildMessageFrame(message);
     Debug.WriteLine($"TX: {string.Join(", ", frame)}");
     StreamResource.Write(frame, 0, frame.Length);
 }
 internal ModbusSlaveRequestEventArgs(IModbusMessage message)
 {
     _message = message;
 }
Example #35
0
        internal IModbusMessage ApplyRequest(IModbusMessage request)
        {
            _logger.Info(request.ToString());
            ModbusSlaveRequestReceived.Raise(this, new ModbusSlaveRequestEventArgs(request));

            IModbusMessage response;
            /*
             * ANGELOXX: if datastore is null, this Slave returns an error to the Master
             * I use the datastore = null asignment to emulate a missing device. Returned
             * error is 0x02 -> Illegal Data Address
             */
            if (DataStore == null)
            {
                byte[] messageFrame = new byte[] { request.SlaveAddress, (byte)(Modbus.ExceptionOffset + request.FunctionCode), 2 };
                return ModbusMessageFactory.CreateModbusMessage<SlaveExceptionResponse>(messageFrame);
            }

            switch (request.FunctionCode)
            {
                case Modbus.ReadCoils:
                    response = ReadDiscretes((ReadCoilsInputsRequest) request, DataStore, DataStore.CoilDiscretes);
                    break;
                case Modbus.ReadInputs:
                    response = ReadDiscretes((ReadCoilsInputsRequest) request, DataStore, DataStore.InputDiscretes);
                    break;
                case Modbus.ReadHoldingRegisters:
                    response = ReadRegisters((ReadHoldingInputRegistersRequest) request, DataStore, DataStore.HoldingRegisters);
                    break;
                case Modbus.ReadInputRegisters:
                    response = ReadRegisters((ReadHoldingInputRegistersRequest) request, DataStore, DataStore.InputRegisters);
                    break;
                case Modbus.Diagnostics:
                    response = request;
                    break;
                case Modbus.WriteSingleCoil:
                    response = WriteSingleCoil((WriteSingleCoilRequestResponse) request, DataStore, DataStore.CoilDiscretes);
                    break;
                case Modbus.WriteSingleRegister:
                    response = WriteSingleRegister((WriteSingleRegisterRequestResponse) request, DataStore, DataStore.HoldingRegisters);
                    break;
                case Modbus.WriteMultipleCoils:
                    response = WriteMultipleCoils((WriteMultipleCoilsRequest) request, DataStore, DataStore.CoilDiscretes);
                    break;
                case Modbus.WriteMultipleRegisters:
                    response = WriteMultipleRegisters((WriteMultipleRegistersRequest) request, DataStore, DataStore.HoldingRegisters);
                    break;
                case Modbus.ReadWriteMultipleRegisters:
                    ReadWriteMultipleRegistersRequest readWriteRequest = (ReadWriteMultipleRegistersRequest) request;
                    response = ReadRegisters(readWriteRequest.ReadRequest, DataStore, DataStore.HoldingRegisters);
                    WriteMultipleRegisters(readWriteRequest.WriteRequest, DataStore, DataStore.HoldingRegisters);
                    break;
                default:
                    string errorMessage = String.Format(CultureInfo.InvariantCulture, "Unsupported function code {0}", request.FunctionCode);
                    _logger.Error(errorMessage);
                    throw new ArgumentException(errorMessage, "request");
            }

            return response;
        }
Example #36
0
        #pragma warning restore CS1591 // O comentário XML ausente não foi encontrado para o tipo ou membro visível publicamente


        internal virtual T UnicastMessage <T>(IModbusMessage message) where T : IModbusMessage, new()
        {
            IModbusMessage response = null;
            int            attempt  = 1;
            bool           readAgain;
            bool           success = false;

            do
            {
                try
                {
                    lock (_syncLock)
                    {
                        Write(message);

                        do
                        {
                            readAgain = false;
                            response  = ReadResponse <T>();

                            var exceptionResponse = response as SlaveExceptionResponse;
                            if (exceptionResponse != null)
                            {
                                // if SlaveExceptionCode == ACKNOWLEDGE we retry reading the response without resubmitting request
                                if (readAgain = exceptionResponse.SlaveExceptionCode == Modbus.Acknowledge)
                                {
                                    _logger.InfoFormat("Received ACKNOWLEDGE slave exception response, waiting {0} milliseconds and retrying to read response.", _waitToRetryMilliseconds);
                                    Thread.Sleep(WaitToRetryMilliseconds);
                                }
                                else
                                {
                                    throw new SlaveException(exceptionResponse);
                                }
                            }
                        } while (readAgain);
                    }

                    ValidateResponse(message, response);
                    success = true;
                }
                catch (SlaveException se)
                {
                    if (se.SlaveExceptionCode != Modbus.SlaveDeviceBusy)
                    {
                        throw;
                    }

                    _logger.InfoFormat("Received SLAVE_DEVICE_BUSY exception response, waiting {0} milliseconds and resubmitting request.", _waitToRetryMilliseconds);
                    Thread.Sleep(WaitToRetryMilliseconds);
                }
                catch (Exception e)
                {
                    if (e is FormatException ||
                        e is NotImplementedException ||
                        e is TimeoutException ||
                        e is IOException)
                    {
                        _logger.WarnFormat("{0}, {1} retries remaining - {2}", e.GetType().Name, _retries - attempt + 1, e);

                        if (attempt++ > _retries)
                        {
                            error = e.ToString();
                        }

                        return((T)response);
                    }
                    else
                    {
                        error = e.ToString();

                        return((T)response);
                    }
                }
            } while (!success);

            return((T)response);
        }
Example #37
0
 public void Write(IModbusMessage message)
 {
 }
 public abstract byte[] BuildMessageFrame(IModbusMessage message);
Example #39
0
        private async Task HandleRequestAsync()
        {
            var serialTransport = (IModbusSerialTransport)Transport;

            while (true)
            {
                try
                {
                    // read request and build message
                    byte[] frame = serialTransport.ReadRequest();

                    //Create the request
                    IModbusMessage request = _modbusFactory.CreateModbusRequest(frame);

                    //Check the message
                    if (serialTransport.CheckFrame && !serialTransport.ChecksumsMatch(request, frame))
                    {
                        string msg = $"Checksums failed to match {string.Join(", ", request.MessageFrame)} != {string.Join(", ", frame)}.";
                        //Logger.Warning(msg);
                        throw new IOException(msg);
                    }

                    //Apply the request
                    // TODO: почистить класс и предусмотреть броадкаст request.SlaveAddress ==0
                    IModbusMessage response = _slaveNetwork.GetSlave(request.SlaveAddress)
                                              .ApplyRequest(request);

                    if (response == null)
                    {
                        serialTransport.IgnoreResponse();
                    }
                    else
                    {
                        Transport.Write(response);
                    }
                }
                catch (IOException /*ioe*/)
                {
                    //Logger.Warning($"IO Exception encountered while listening for requests - {ioe.Message}");
                    serialTransport.DiscardInBuffer();

                    ModbusMasterTcpConnectionClosed?.Invoke(this, new TcpConnectionEventArgs(EndPoint));
                }
                catch (TimeoutException /*te*/)
                {
                    //Logger.Trace($"Timeout Exception encountered while listening for requests - {te.Message}");
                    serialTransport.DiscardInBuffer();
                }
                catch (InvalidOperationException)
                {
                    // when the underlying transport is disposed
                    break;
                }
                catch (Exception /*ex*/)
                {
                    //Logger.Error($"{GetType()}: {ex.Message}");
                    serialTransport.DiscardInBuffer();
                }

                /* // OLD CODE
                 * // //Logger.Debug($"Begin reading header from Master at IP: {EndPoint}");
                 *
                 * int readBytes = await Stream.ReadAsync(_mbapHeader, 0, 6).ConfigureAwait(false);
                 * if (readBytes == 0)
                 * {
                 *  //Logger.Debug($"0 bytes read, Master at {EndPoint} has closed Socket connection.");
                 *  ModbusMasterTcpConnectionClosed?.Invoke(this, new TcpConnectionEventArgs(EndPoint));
                 *  return;
                 * }
                 *
                 * ushort frameLength = (ushort)IPAddress.HostToNetworkOrder(BitConverter.ToInt16(_mbapHeader, 4));
                 * //Logger.Debug($"Master at {EndPoint} sent header: \"{string.Join(", ", _mbapHeader)}\" with {frameLength} bytes in PDU");
                 *
                 * _messageFrame = new byte[frameLength];
                 * readBytes = await Stream.ReadAsync(_messageFrame, 0, frameLength).ConfigureAwait(false);
                 * if (readBytes == 0)
                 * {
                 *  //Logger.Debug($"0 bytes read, Master at {EndPoint} has closed Socket connection.");
                 *  ModbusMasterTcpConnectionClosed?.Invoke(this, new TcpConnectionEventArgs(EndPoint));
                 *  return;
                 * }
                 *
                 * //Logger.Debug($"Read frame from Master at {EndPoint} completed {readBytes} bytes");
                 * byte[] frame = _mbapHeader.Concat(_messageFrame).ToArray();
                 * //Logger.Trace($"RX from Master at {EndPoint}: {string.Join(", ", frame)}");
                 *
                 * var request = _modbusFactory.CreateModbusRequest(_messageFrame);
                 * request.TransactionId = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 0));
                 *
                 * IModbusSlave slave = _slaveNetwork.GetSlave(request.SlaveAddress);
                 *
                 * if (slave != null)
                 * {
                 *  //TODO: Determine if this is appropriate
                 *
                 *  // perform action and build response
                 *  IModbusMessage response = slave.ApplyRequest(request);
                 *  response.TransactionId = request.TransactionId;
                 *
                 *  // write response
                 *  byte[] responseFrame = Transport.BuildMessageFrame(response);
                 *  //Logger.Information($"TX to Master at {EndPoint}: {string.Join(", ", responseFrame)}");
                 *  await Stream.WriteAsync(responseFrame, 0, responseFrame.Length).ConfigureAwait(false);
                 * }
                 */
            }
        }