예제 #1
0
 /// <summary>
 /// Creates a modbus master using the given interface
 /// </summary>
 /// <param name="intf">Interface to use for the master</param>
 /// <param name="syncObject">Object to use for multi threaded communication locking.</param>
 public RoSchmiModbusMaster(IModbusInterface intf, object syncObject = null)
 {
     _Interface  = intf;
     _SyncObject = syncObject ?? new object();
     _Buffer     = new byte[_Interface.MaxTelegramLength];
     _Interface.PrepareWrite();
 }
예제 #2
0
 /// <summary>
 /// Creates a modbus master using the given interface
 /// </summary>
 /// <param name="intf">Interface to use for the master</param>
 /// <param name="syncObject">Object to use for multi threaded communication locking.</param>
 public ModbusMaster(IModbusInterface intf, object syncObject = null)
 {
    _Interface = intf;
    _SyncObject = syncObject ?? new object();
    _Buffer = new byte[_Interface.MaxTelegramLength];
    _Interface.PrepareWrite();
 }
예제 #3
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();
                }
            }
        }
예제 #4
0
 /// <summary>
 /// Adds an additional master interface with an custom device id mapping
 /// </summary>
 /// <param name="masterInterface">master interface to add</param>
 /// <param name="timeout">Timeout for master interface</param>
 /// <param name="addressMap">A hashtable where the key is the incoming device id that is mapped to it's value as device id on the master interface.
 /// Both, key and value of the hashtable must be of type byte.</param>
 public void AddMaster(IModbusInterface masterInterface, int timeout, Hashtable addressMap)
 {
    masterInterface.PrepareWrite();
    foreach (byte sourceAddress in addressMap.Keys)
    {
       _masterMap[sourceAddress] = new GatewayMaster(masterInterface, (byte)addressMap[sourceAddress], timeout);
    }
 }
예제 #5
0
 /// <summary>
 /// Adds an additional master interface with an custom device id mapping
 /// </summary>
 /// <param name="masterInterface">master interface to add</param>
 /// <param name="timeout">Timeout for master interface</param>
 /// <param name="addressMap">A hashtable where the key is the incoming device id that is mapped to it's value as device id on the master interface.
 /// Both, key and value of the hashtable must be of type byte.</param>
 public void AddMaster(IModbusInterface masterInterface, int timeout, Hashtable addressMap)
 {
     masterInterface.PrepareWrite();
     foreach (byte sourceAddress in addressMap.Keys)
     {
         _masterMap[sourceAddress] = new GatewayMaster(masterInterface, (byte)addressMap[sourceAddress], timeout);
     }
 }
예제 #6
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();
            }
         }
      }