/// <summary> /// Creates a new ModebusDevice with one initial interface. /// </summary> /// <param name="intf">Initial interface.</param> /// <param name="deviceAddress">Device address. Must be between 1 and 247 for RTU and should be 248 for TCP.</param> /// <param name="syncObject">Optional object for communication interface synchronization.</param> /// <remarks> /// More interfaces can be add or removed by AddInterface and RemoveInterface methods. /// </remarks> protected ModbusDevice(IModbusInterface intf, byte deviceAddress, object syncObject = null) : this(deviceAddress, syncObject) { intf.PrepareRead(); _interfaces.Add(intf); _buffer = new byte[intf.MaxTelegramLength]; }
/// <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(); } } }
/// <summary> /// Adds an additional interface to be polled for incoming messages. /// </summary> /// <param name="intf">Interface to add.</param> public void AddInterface(IModbusInterface intf) { lock (this.syncObject) { if (this.Buffer1 == null || intf.MaxTelegramLength > this.Buffer1.Length) { this.Buffer1 = new byte[intf.MaxTelegramLength]; } intf.PrepareRead(); this.interfaces.Add(intf); } }
/// <summary> /// Adds an additional interface to be polled for incoming messages. /// </summary> /// <param name="intf">Interface to add.</param> public void AddInterface(IModbusInterface intf) { lock (_syncObject) { if (_buffer == null || intf.MaxTelegramLength > _buffer.Length) { _buffer = new byte[intf.MaxTelegramLength]; } intf.PrepareRead(); _interfaces.Add(intf); } }
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(); } } }