예제 #1
0
        /// <summary>
        /// Sends a modbus telegram over the interface and waits for a response
        /// </summary>
        /// <param name="deviceAddress">Modbus device address.</param>
        /// <param name="fc">Function code.</param>
        /// <param name="timeout">Timeout in Milli seconds.</param>
        /// <param name="telegramLength">Total length of the telegram in bytes</param>
        /// <param name="desiredDataLength">Length of the desired telegram data (without fc, cs, ...) of the response in bytes. -1 for unknown.</param>
        /// <param name="telegramContext">Interface specific context of the telegram</param>
        /// <param name="dataPos">Index of the response data in the buffer.</param>
        /// <returns></returns>
        protected virtual short SendReceive(byte deviceAddress, ModbusFunctionCode fc, int timeout, short telegramLength, short desiredDataLength,
                                            object telegramContext, ref short dataPos)
        {
            lock (_SyncObject)
            {
                try
                {
                    _Interface.SendTelegram(_Buffer, telegramLength);
                    _Interface.PrepareRead();

                    if (deviceAddress == ModbusConst.BroadcastAddress)
                    {
                        return(0);
                    }

                    byte  responseDeviceAddress;
                    byte  responseFc = 0;
                    short dataLength = 0;

                    while (timeout > 0)
                    {
                        var ts = DateTime.Now.Ticks;

                        if (!_Interface.ReceiveTelegram(_Buffer, desiredDataLength, timeout, out telegramLength))
                        {
                            throw new ModbusException(ModbusErrorCode.Timeout);
                        }

                        timeout -= (int)((DateTime.Now.Ticks - ts) / 10000);

                        // if this is not the response we are waiting for wait again until time runs out
                        if (_Interface.ParseTelegram(_Buffer, telegramLength, true, ref telegramContext,
                                                     out responseDeviceAddress,
                                                     out responseFc,
                                                     out dataPos, out dataLength) &&
                            responseDeviceAddress == deviceAddress &&
                            (responseFc & 0x7f) == (byte)fc)
                        {
                            break;
                        }
                        if (timeout <= 0)
                        {
                            throw new ModbusException(ModbusErrorCode.Timeout);
                        }
                    }

                    if ((responseFc & 0x80) != 0)
                    {
                        // error response
                        throw new ModbusException((ModbusErrorCode)_Buffer[dataPos]);
                    }
                    return(dataLength);
                }
                finally
                {
                    _Interface.PrepareWrite();
                }
            }
        }
예제 #2
0
      private short SendReceive(IModbusInterface masterInterface, byte[] buffer, byte deviceAddress, ModbusFunctionCode fc, int timeout, short telegramLength, short desiredDataLength,
                                          object telegramContext, ref short dataPos)
      {
         lock (masterInterface)
         {
            masterInterface.SendTelegram(buffer, telegramLength);

            if (deviceAddress == ModbusConst.BroadcastAddress)
            {
               return 0;
            }

            try
            {
               masterInterface.PrepareRead();

               byte responseDeviceAddress;
               byte responseFc = 0;
               short dataLength = 0;

               while (timeout > 0)
               {
                  var ts = DateTime.Now.Ticks;
                  if (!masterInterface.ReceiveTelegram(buffer, desiredDataLength, timeout, out telegramLength))
                  {
                     throw new ModbusException(ModbusErrorCode.Timeout);
                  }
                  timeout -= (int) ((DateTime.Now.Ticks - ts)/10000);

                  // if this is not the response we are waiting for wait again until time runs out
                  if (masterInterface.ParseTelegram(buffer, telegramLength, true, ref telegramContext,
                     out responseDeviceAddress,
                     out responseFc,
                     out dataPos, out dataLength)
                      && responseDeviceAddress == deviceAddress
                      && (responseFc & 0x7f) == (byte) fc)
                  {
                     break;
                  }
                  if (timeout <= 0)
                  {
                     throw new ModbusException(ModbusErrorCode.Timeout);
                  }
               }
               if ((responseFc & 0x80) != 0)
               {
                  // error response
                  throw new ModbusException((ModbusErrorCode) buffer[dataPos]);
               }
               return dataLength;
            }
            finally
            {
               masterInterface.PrepareWrite();
            }
         }
      }