/// <summary> /// Parses a telegram received by ReceiveTelegram. /// </summary> /// <param name="buffer">Buffer containing the data.</param> /// <param name="telegramLength">Total length of the telegram in bytes.</param> /// <param name="isResponse">true if the telegram is a response telegram; false if the telegram is a request telegram.</param> /// <param name="telegramContext"> /// If isResponse == true: pass the telegramContext returned by CreateTelegram from the request. /// If isResponse == false: returns the telegramContext from the received request. It must pe passed to the CreateTelegram method for the response. /// </param> /// <param name="address">Returns the device address.</param> /// <param name="fkt">Returns the function code.</param> /// <param name="dataPos">Returns the offset in buffer of the function code specific data.</param> /// <param name="dataLength">Returns the length of the function code specific data.</param> /// <returns>Returns true if this is the matching response according to the telegramContext; else false. If isResponse == false this method should return always true.</returns> public bool ParseTelegram(byte[] buffer, short telegramLength, bool isResponse, ref object telegramContext, out byte address, out byte fkt, out short dataPos, out short dataLength) { if (telegramLength < 8) { throw new ModbusException(ModbusErrorCode.ResponseTooShort); } if (isResponse) { if (telegramContext is ushort) { ushort transactionId = ModbusUtils.ExtractUShort(buffer, 0); if (transactionId != (ushort)telegramContext) { // telegram does not match address = 0; fkt = 0; dataPos = 0; dataLength = 0; return(false); } } } else { telegramContext = ModbusUtils.ExtractUShort(buffer, 0); } address = buffer[6]; fkt = buffer[7]; dataPos = 8; dataLength = (short)(telegramLength - 8); return(true); }
/// <summary> /// Waits and receives a telegram. /// </summary> /// <param name="buffer">Buffer to write data into.</param> /// <param name="desiredDataLength">Desired length of the function code specific data in bytes. -1 if length is unknown.</param> /// <param name="timeout">Timeout in milliseconds to wait for the telegram.</param> /// <param name="telegramLength">Returns the total length of the telegram in bytes.</param> /// <returns>Returns true if the telegram was received successfully; false on timeout.</returns> public bool ReceiveTelegram(byte[] buffer, short desiredDataLength, int timeout, out short telegramLength) { if (_Socket == null) { throw new ObjectDisposedException("ModbusTcp interface"); } if (!_Socket.Poll(timeout * 1000, SelectMode.SelectRead) || _Socket.Available == 0) { telegramLength = 0; return(false); } // get the 1st 6 bytes, which includes the remaining length int pos = 0; while (pos < 6) { pos += _Socket.Receive(buffer, pos, 6 - pos, SocketFlags.None); } telegramLength = (short)(ModbusUtils.ExtractUShort(buffer, 4) + 6); // receive remaining data while (pos < telegramLength) { pos += _Socket.Receive(buffer, pos, telegramLength - pos, SocketFlags.None); } return(true); }