Пример #1
0
  /**
   * @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());
      }
    }
  }
Пример #2
0
  /**
   * @param fitFile
   * @return
   */
  public static boolean isValid(final Path fitFile) {
    final InputStream in;
    try {
      in = Files.newInputStream(fitFile);
    } catch (final IOException | SecurityException e) {
      logger.info("Could not open fit file.", e);
      return false;
    }

    final Header header = new Header();
    try {
      header.readHeader(in);
    } catch (final IOException e) {
      logger.info("Error while reading fit file header.", e);
      return false;
    }

    if (!header.isValid()) {
      logger.info("Fit file header is not valid.");
      return false;
    }

    final byte[] data = new byte[header.getDataSize() + 2];
    try {
      in.read(data);
    } catch (final IOException e) {
      logger.info("Error while reading fit records and CRC.", e);
      return false;
    }

    final CRC crc = new CRC();
    crc.update(header.getHeader(), header.getHeaderSize());
    crc.update(data);

    if (crc.getValue() != 0x0000) {
      logger.info("Fit file CRC error.");
      return false;
    }

    return true;
  }
Пример #3
0
  /**
   * @param defMsg
   * @param in
   * @throws IOException
   */
  protected void readDefinitionMessage(final DefinitionMessage defMsg, InputStream in)
      throws IOException {
    final byte[] params = new byte[5];
    readBytes += in.read(params);

    crc.update(defMsg.getHeader());
    crc.update(params);

    defMsg.setReserved(params[0]);
    defMsg.setArchitecture(params[1]);
    defMsg.setFitMessageNumber(
        ByteBuffer.wrap(params, 2, 2).order(defMsg.getByteOrder()).getShort());
    defMsg.setNumOfFields(params[4]);

    final List<FieldDefinition> fields = new ArrayList<>();
    for (int i = 0; i < defMsg.getNumOfFields(); i++) {
      final byte[] fieldDef = new byte[3];
      readBytes += in.read(fieldDef);
      crc.update(fieldDef);

      fields.add(new FieldDefinition(fieldDef[0], fieldDef[1], fieldDef[2]));
    }
    defMsg.setFields(fields);
  }
Пример #4
0
  /**
   * @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;
  }