NAME

Fitsed - Stream editor for Garmin .FIT files


SYNOPSIS

  fitsed -show_version=1
  fitsed [-parser_dump_indent=<number>] -parser_dump=1 <expression>
  fitsed <expression> [<input_file1> [<input_file2> ...] [<output file>]]


DESCRIPTION

Fitsed reads the contents of Garmin .FIT files, assigns specified values to specified fields of specified data messages, and outputs them with appropriate .FIT header and trailing CRC-16.

The latest version is obtained via
fitsed-0.09.tar.gz (8KB, 2017-06-18 14:36:07).

It uses a Perl class

Garmin::FIT

of version 0.27 or later.


EXPRESSION

Each time when a data message is read, <expression> is evaluated. <expression> is <single expression> or <compound expression>. All syntactical keywords and operators in explanations below are case-insensitive.

Single expression

A single expression must be one of the following forms.

<place spec><assignment or comparison><value>
<place spec>+
<place spec>-
<a Perl expression>

<place spec> must be one of the following forms.

<message spec>.<field spec>
<message spec> is a name or a number of a .FIT message, and <field spec> is a name or a index of a filed of the message, in a global .FTI profile.

_n.<name>
_s.<name>
_n.<name> and _s.<name> represent global variables named <name>. The value of _n.<name> is treated as a number, and the value of _s.<name> is treated as a string.

<message spec>., _n., or _s. can be omitted. In that case, the last refered one is assumed.

<assignment or comparison> must be one of =, :lt:, :le:, :eq:, :ge:, :gt:, or ::.

=
It assigns <value> to the specified place. It is evaluated to a true value.

An array value is expressed as a comma separated list of members enclosed with open and closing braces.

:lt:
:le:
:eq:
:ge:
:gt:
They stand for less than, less than or equal to, equal to, greater than or equal to, and greater than, respectively. They compare the value of the specified place against <value>.

::
It matches <value> as a regular expression against the value of the specified place.

The evaluation engine has two data stack. One is for numeric values, and the other is for string values.

+ pushs the value of <place spec> to one of the stacks. - pops a value from one of the stacks, and assigns the value to <place spec>. Which of stacks is selected is determined by data type of <place spec>. Both operations are evaluated to a true value.

<a Perl expression> is evaluated to a true value if and only if it is a true value as a Perl expression.

Compound expression

A compound expression must be one of the following form.

! <expression>
not <expression>
Each of them evaluates to a true or false value if <expression> evaluates to a false or true value, respectively.

( <sequence of expressions> )
[ <sequence of expressions> ]
< <sequence of expressions> >
{ <sequence of expressions> }
b <sequence of expressions> e
beg <sequence of expressions> end
begin <sequence of expressions> end
beginning <sequence of expressions> end
start <sequence of expressions> end
do <sequence of expressions> done
<sequence of expressions> is <and sequence> or <or sequence>, and evaluated with the following rule. The result of the evaluation becomes the value of the compound expression.

<and sequence> is simply a sequence of any number of <expression>'s. They are evaluated in order. Evaluation stops when an <expression> evaluates to a false value, and the false value becomes the value of the whole sequence.

If all <expression>'s evaluate to true values, this <and sequence> evaluates to a true value.

<or sequence> is a sequence of the form:
<and sequence> or <sequence of expressions>.

First the left <and sequence> is evaluated. If the evaluation generates a true value, the value becomes the value of this <or sequence>. In this case the right <sequence of expression> is not evaluated.

If the evaluation generates a false value, the right <sequence of expression> is evaluated, and the result becomes the value of this <or sequence>.

Special variables

The following variables have special meaning.

_n._stop
If this variable has a non-zero value after the expression given on the command line is evaluated, all succeeding evaluations of the expression and outputs of .FIT messages are skipped.

_n._skip
If this variable has a non-zero value after the expression given on the command line is evaluated, the corresponding .FIT message is not output. The value is changed to 0 before the next evaluation.

_n._global_message_type
assigned with the message number in a global .FIT profile of the corresponding .FIT message during evaluation.

_s._global_message_type
assigned with the message name in a global .FIT profile of the corresponding .FIT message or an empty string during evaluation.

_n._local_message_type
assigned with the local message number of the corresponding .FIT message during evaluation.

All other global variables with names starting with _ (underscore) are reserved for special purpose.


TYPICAL STORY

If you want to modify a .FIT file (say originalfile.fit), you can first look at the contents of the file with

fitdump

of version 0.3 or later. It shows messages with message numbers and fields with field indices defined in a global .FIT profile.

If you find the message number and the field index (say <M> and <I>, respectively) of data which you want to change, you can call fitsed like
fitsed <M>.<I>=<new value> originalfile.fit newfile.fit

where modified contens are saved to newfile.fit.


EXAPLES

Assuming Edge 500 is mounted on the folder /mnt/Edge500, it has a file Settings.fit in the folder /mnt/Edge500/Garmin/Settings.

To change the value of the field friendly_name of the message user_profile in Settings.fit to suto, and to save the result to /tmp/new_settings.fit:
fitsed user_profile.friendly_name=suto /mnt/Edge500/Garmin/Settings/Settings.fit /tmp/new_settings.fit

To change the value of the field weight of the same message to 54kg simultaneously:
fitsed B user_profile.friendly_name=suto weight=54kg E /mnt/Edge500/Garmin/Settings/Settings.fit /tmp/new_settings.fit

The file Settings.fit has 3 messages with message number 6. They seem to be bike profiles. The field with index 254 in a global .FIT profile of a message of this type, seems to be an identification number of the message in the file, and the field with index 10 seems to be a bike weight.

Adding to the above changes, to change the value of the field with index 10 of the first message to 7.5kg:
fitsed B 6.254:eq:0 6.10=7.5kg OR user_profile.friendly_name=suto weight=54kg E /mnt/Edge500/Garmin/Settings/Settings.fit /tmp/new_settings.fit


AUTHOR

Kiyokazu SUTO <suto@ks-and-ks.ne.jp>


DISCLAIMER etc.

This program is distributed with ABSOLUTELY NO WARRANTY.

Anyone can use, modify, and re-distibute this program without any restriction.


CHANGES

0.08 --> 0.09

force_proto_ver1
new option to set protocol version 1.00 unless consistency is broken.

When developer data or 64bit numbers are not used but major part of protocol version is 2, protocol version is set to 1.00 if this option is set to true.

Thanks to analysis by Stefan Heinen.

cat_cb()
should care the case where there are previously defined callback functions.

0.07 --> 0.08

drop_developer_data
new option to drop developer data from output for applications which support only FIT 1.0. Thanks to report from Stefan Heinen.

0.06 --> 0.07

Description about notation of an array literal is added to this document. Thanks to report from Leandro Lind.

0.05 --> 0.06

cat_cb()
used an undefined variable $self which should be $obj. Thanks to report and fix of this issue by Marcus.

0.04 --> 0.05

cat_cb()
use new method pack_data_message of Garmin::FIT.

0.03 --> 0.04

with_endian
new option to force specified endianness (-1 => little endian, 0 => machine endian, and 1 => big endian).

0.02 --> 0.03

cat()
saves extra octets in the first file header.

top level
pass extra octets in the first file header to cat_header().

0.01 --> 0.02

cat_cb()
special variables are introduced. Backward compatibility is broken.