public IResponse Parse(byte[] dataBytes)
        {
            if (dataBytes == null || dataBytes.Length < 13)
            {
                return(new CommonErrorResponse(CommonResponseCode.CorruptData, 0, 0, 0, 0, 0));
            }

            var requestType0 = dataBytes[1];
            var requestType1 = dataBytes[2];
            var requestType2 = dataBytes[3];
            var requestType3 = dataBytes[4];
            var counter      = BitConverter.ToUInt16(dataBytes, 7);

            var protocolVersion = dataBytes[0];

            if (protocolVersion != 0x00)
            {
                return(new CommonErrorResponse(CommonResponseCode.NotSupportedProtocolVersion, counter, requestType0, requestType1, requestType2, requestType3));
            }

            if (!_responseTypes.TryGetValue(new RequestTypeAttribute(requestType0, requestType1, requestType2, requestType3), out var responseType))
            {
                return(new CommonErrorResponse(CommonResponseCode.UnknownCommand, counter, requestType0, requestType1, requestType2, requestType3));
            }

            var dataLength = BitConverter.ToUInt16(dataBytes, 5);

            var crc0 = dataBytes[7 + dataLength];
            var crc1 = dataBytes[8 + dataLength];

            var computeChecksum = Crc16.ComputeChecksum(dataBytes.Take(dataBytes.Length - 2));

            if (crc0 != computeChecksum[0] || crc1 != computeChecksum[1])
            {
                return(new CommonErrorResponse(CommonResponseCode.WrongCrc, counter, requestType0, requestType1, requestType2, requestType3));
            }

            var responseCode0 = dataBytes[9];
            var responseCode1 = dataBytes[10];

            if (responseCode0 != 0x00 || responseCode1 != 0x00)
            {
                return(new CommonErrorResponse(responseCode0, responseCode1, counter, requestType0, requestType1, requestType2, requestType3));
            }

            var response  = Activator.CreateInstance(responseType);
            var dataIndex = 7;

            foreach (var propertyInfo in responseType.GetAllProperties())
            {
                object dataValue;
                (dataValue, dataIndex) = _dataConverterDispatcher.ConvertBack(propertyInfo.PropertyType, dataBytes, dataIndex);
                propertyInfo.SetValue(response, dataValue);
            }

            return((IResponse)response);
        }
        public IRequest Parse(byte[] dataBytes)
        {
            if (dataBytes == null || dataBytes.Length < 9)
            {
                throw new CorruptDataException();
            }

            var protocolVersion = dataBytes[0];

            if (protocolVersion != 0x00)
            {
                throw new NotSupportedProtocolException(protocolVersion);
            }

            var requestType0 = dataBytes[1];
            var requestType1 = dataBytes[2];
            var requestType2 = dataBytes[3];
            var requestType3 = dataBytes[4];

            if (!_requestTypes.TryGetValue(new RequestTypeAttribute(requestType0, requestType1, requestType2, requestType3), out var requestType))
            {
                throw new UnknownCommandException();
            }

            var dataLength = BitConverter.ToUInt16(dataBytes, 5);

            var crc0 = dataBytes[7 + dataLength];
            var crc1 = dataBytes[8 + dataLength];

            var computeChecksum = Crc16.ComputeChecksum(dataBytes.Take(dataBytes.Length - 2));

            if (crc0 != computeChecksum[0] || crc1 != computeChecksum[1])
            {
                throw new WrongCrcException();
            }

            var request   = Activator.CreateInstance(requestType);
            var dataIndex = 7;

            foreach (var propertyInfo in requestType.GetAllProperties())
            {
                object dataValue;
                (dataValue, dataIndex) = _dataConverterDispatcher.ConvertBack(propertyInfo.PropertyType, dataBytes, dataIndex);
                propertyInfo.SetValue(request, dataValue);
            }

            return((IRequest)request);
        }