/** * @param defMsg * @param msg * @param in * @throws IOException */ protected void readDataMessage( final DefinitionMessage defMsg, final DataMessage msg, InputStream in) throws IOException { crc.update(msg.getHeader()); final ByteOrder bo = defMsg.getByteOrder(); for (final FieldDefinition def : defMsg.getFields()) { final byte[] value = new byte[def.getSize()]; readBytes += in.read(value); crc.update(value); final Field<?> field = FieldFactory.build(def, value, bo); msg.getFields().add(field); // Update timestamp. if (field.isTimestamp() && field.toNumber() != null) { timestampOffset.updateTimestamp(field.toNumber().longValue()); } } }
/** * @param in * @return * @throws IOException */ public boolean read(InputStream in) throws IOException { // Read header. final Header header = new Header(); header.readHeader(in); if (!header.isValid()) { logger.error("Fit file header is not valid."); return false; } crc.reset(); readBytes = 0; stop = false; for (int i = 0; i < header.getHeaderSize(); i++) { crc.update(header.getHeader()[i]); } dispatcher.onHeader(header); // Read data records. final DefinitionMessage[] definitions = new DefinitionMessage[MAX_LOCAL_MESSAGE_NUMS]; final int dataSize = header.getDataSize(); int data = -1; while (readBytes < dataSize && (data = in.read()) > -1) { // Record header byte was read. readBytes++; final int recordType = data & RECORD_HEADER_TYPE_MASK; if (recordType == DEFINITION_MESSAGE) { final DefinitionMessage defMsg = new DefinitionMessage((byte) data); readDefinitionMessage(defMsg, in); // Store new definition message. definitions[defMsg.getLocalMessageType()] = defMsg; dispatcher.onDefinitionMessage(defMsg); } else { final DataMessage msg; if (recordType == COMPRESSED_TIMESTAMP) { final int timeOffset = data & COMPRESSED_TIMESTAMP_MASK; timestampOffset.setOffset(timeOffset); msg = new DataMessage((byte) data, timestampOffset.getTimestamp()); } else if (recordType == DATA_MESSAGE) { msg = new DataMessage((byte) data); } else { logger.error( "Unknown message header type. message header: 0x{}", Integer.toHexString(data)); return false; } final DefinitionMessage defMsg = definitions[msg.getLocalMessageType()]; if (defMsg == null) { logger.error( "Definition message does not exists. message header: {}, read: {} bytes", data, header.getHeaderSize() + readBytes); return false; } readDataMessage(defMsg, msg, in); dispatcher.onDataMessage(defMsg, msg); } if (stop) { logger.info("Stop reading. read: {} bytes", header.getHeaderSize() + readBytes); return false; } } if (readBytes != dataSize) { logger.error( "A mismatch between read message size and defined size of the header. read: {} bytes, defined: {} bytes", readBytes, dataSize); return false; } // read crc(2 bytes). for (int i = 0; i < 2; i++) { final int d = in.read(); if (d < 0) { logger.error( "Unexpected EOF while reading crc. read: {} bytes", header.getHeaderSize() + readBytes + i + 1); return false; } crc.update((byte) d); } if (crc.getValue() != 0) { logger.error("Fit file CRC error."); return false; } // check EOF. if (in.read() > 0) { logger.error( "Unexpected data exists after crc. read: {} bytes", header.getHeaderSize() + readBytes + 2); return false; } return true; }