/// <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(); }
/// <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(); }
/// <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 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); } }
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(); } } }