Ich finde die Perl-Implementierung von oben noch immer ganz interessant. Die zugrundeliegende
FIT.pm ist riesig und sollte daher möglichst nicht verändert werden. Da müsste man höchstens ran, wenn neue Daten hinzukommen. Ich vermute zum Beispiel, dass die neuen Daten wie vertikale Oszillation und Bodenkontaktzeit dort noch nicht mit ihrer entsprechenden ID vermerkt sind.
fitdump liefert dann quasi alles, was in der FIT-Datei steckt. Das müsste man dann mit PHP noch einmal ordentlich parsen, aber das sollte zumindest möglich sein und würde uns unabhängig vom Konverter in TCX machen, der ja auch nicht ganz rund lief.
Fitdump startet mit ein paar generellen Infos:
Code: Select all
perl hannes$ ./fitdump 20140329-121758-1-1018-ANTFS-4-0.FIT
File size: 22105, protocol version: 1.00, profile_verion: 1.31
Extra octets in file header
00 00
Local message type: 0 (message name: file_id, message number: 0)
serial_number (3-1-UINT32Z): 3839241047
time_created (4-1-UINT32): 2014-03-29T12:17:58 (765026278)
manufacturer (1-1-UINT16): garmin (1)
garmin_product (2-1-UINT16, orignal name: product): fr310xt (1018)
number (5-1-UINT16, INVALID): 65535
type (0-1-ENUM): activity (4)
Local message type: 1 (message name: file_creator, message number: 49)
software_version (0-1-UINT16): 450
hardware_version (1-1-UINT8, INVALID): 255
Local message type: 2 (message name: event, message number: 21)
timestamp (253-1-UINT32): 2014-03-29T12:17:57 (765026277)
timer_trigger (3-1-UINT32, orignal name: data): manual (0)
event (0-1-ENUM): timer (0)
event_type (1-1-ENUM): start (0)
event_group (4-1-UINT8): 0
Local message type: 3 (message name: device_info, message number: 23)
timestamp (253-1-UINT32): 2014-03-29T12:17:57 (765026277)
serial_number (3-1-UINT32Z): 3839241047
cum_operating_time (7-1-UINT32, INVALID): 4294967295
xxx8 (8-1-UINT32, INVALID): 4294967295
xxx15 (15-1-UINT32, INVALID): 4294967295
xxx16 (16-1-UINT32, INVALID): 4294967295
manufacturer (2-1-UINT16): garmin (1)
garmin_product (4-1-UINT16, orignal name: product): fr310xt (1018)
software_version (5-1-UINT16): 4.50 (450)
battery_voltage (10-1-UINT16, INVALID): 65535
device_index (0-1-UINT8): creator (0)
device_type (1-1-UINT8): antfs (1)
hardware_version (6-1-UINT8, INVALID): 255
xxx9 (9-1-UINT8, INVALID): 255
battery_status (11-1-UINT8, INVALID): 255
Die eigentlichen Trackpoints kommen etwas später:
Code: Select all
Local message type: 6 (message name: record, message number: 20)
timestamp (253-1-UINT32): 2014-03-29T12:17:57 (765026277)
position_lat (0-1-SINT32): 49.4256911deg (589671463)
position_long (1-1-SINT32): 7.7506781deg (92469192)
distance (5-1-UINT32): 1.32m (132)
altitude (2-1-UINT16): 285.6m (3928)
speed (6-1-UINT16): 4.090km/h (1136)
heart_rate (3-1-UINT8): 83bpm (83)
... und werden dann teilweise von z.B. der Lap unterbrochen:
Code: Select all
Local message type: 7 (message name: lap, message number: 19)
timestamp (253-1-UINT32): 2014-03-29T12:24:48 (765026688)
start_time (2-1-UINT32): 2014-03-29T12:17:57 (765026277)
start_position_lat (3-1-SINT32): 49.4256911deg (589671463)
start_position_long (4-1-SINT32): 7.7506781deg (92469192)
end_position_lat (5-1-SINT32): 49.4183541deg (589583930)
end_position_long (6-1-SINT32): 7.7527631deg (92494066)
total_elapsed_time (7-1-UINT32): 411.394s (411394)
total_timer_time (8-1-UINT32): 411.206s (411206)
total_distance (9-1-UINT32): 1000.00m (100000)
total_strides (10-1-UINT32, orignal name: total_cycles, INVALID): 4294967295
nec_lat (27-1-SINT32): 49.4256911deg (589671463)
nec_long (28-1-SINT32): 7.7543965deg (92513554)
swc_lat (29-1-SINT32): 49.4183541deg (589583930)
swc_long (30-1-SINT32): 7.7506781deg (92469192)
message_index (254-1-UINT16): selected=0,reserved=0,mask=0 (0)
total_calories (11-1-UINT16): 45kcal (45)
total_fat_calories (12-1-UINT16): 0kcal (0)
avg_speed (13-1-UINT16): 8.755km/h (2432)
max_speed (14-1-UINT16): 12.298km/h (3416)
avg_power (19-1-UINT16, INVALID): 65535
max_power (20-1-UINT16, INVALID): 65535
total_ascent (21-1-UINT16): 17m (17)
total_descent (22-1-UINT16): 43m (43)
event (0-1-ENUM): lap (9)
event_type (1-1-ENUM): stop (1)
avg_heart_rate (15-1-UINT8): 125bpm (125)
max_heart_rate (16-1-UINT8): 134bpm (134)
avg_running_cadence (17-1-UINT8, orignal name: avg_cadence, INVALID): 255
max_running_cadence (18-1-UINT8, orignal name: max_cadence, INVALID): 255
intensity (23-1-ENUM, INVALID): 255
lap_trigger (24-1-ENUM): distance (2)
sport (25-1-ENUM): running (1)
event_group (26-1-UINT8, INVALID): 255
Besonders schön, zumindest bei dieser Datei, es wird eine Pause angezeigt:
Code: Select all
Local message type: 2 (message name: event, message number: 21)
timestamp (253-1-UINT32): 2014-03-29T12:26:25 (765026785)
timer_trigger (3-1-UINT32, orignal name: data): manual (0)
event (0-1-ENUM): timer (0)
event_type (1-1-ENUM): stop_all (4)
event_group (4-1-UINT8): 0
... danach folgen ein paar Device-Infos und dann wieder der Start:
Code: Select all
Local message type: 2 (message name: event, message number: 21)
timestamp (253-1-UINT32): 2014-03-29T12:26:32 (765026792)
timer_trigger (3-1-UINT32, orignal name: data): manual (0)
event (0-1-ENUM): timer (0)
event_type (1-1-ENUM): start (0)
event_group (4-1-UINT8): 0
Wir müssten mal schauen, inwiefern die FIT-Klasse auch für die neusten Dateien von z.B. der Fenix2 oder FR220/620 zu gebrauchen ist.
Wenn jemand Ahnung von Perl hat, könnte man auch schauen, ob man fitdump etwas abändert, um die Daten in einem für PHP einfacher zu parsendem Format zu erhalten. Ich könnte spontan aber auch damit leben, bei diesem Format zu bleiben.
Theoretisch könnte man auch
fit_to_cols (siehe
http://djconnel.blogspot.de/2011/01/per ... mited.html) verwenden, das sieht zumindest leicht anpassbar aus. Nachteil: Keine Laps, keine Pausen.