Python : fichiers GPS - OMD

<< retour accueil

Convertir les fichiers OMD des montres ONMOVE 500 Décathlon Coach


Télécharger le programme Python permettant de convertir les données OMD en tableau de données (voir les mises à jour en bas de page):
>> omd_to_txt02.py  génère automatiquement un graphique représentatif de votre course
>>  omd_to_txt01.py : génère en plus un fichier GPX maj: 26/12/2020  
>> omd_to_txt.py maj: 13/12/2020


Depuis une mise à jour de sécurité Windows, il n'est plus possible de lire les fichiers Cardio/GPS de la montre ONMOVE 500 de décathlon. Il ne restait plus qu'a la jeter à la poubelle apres seulement quelques mois après son achat.

La solution était d'ailleurs problématique pour les linuxiens qui n'avaient pas de solution du tout. Heureusement, une solution sous linux a été développé par Colin Pitrat pour la montre ONMOVE200. A ma connaissance, il n'existe pas de solution sous Windows, et je me suis penché sur le problème en m'aidant des programmes Linux et en le traitant sous un outil multiplateforme Python.
Onmove 200 => https://github.com/rboninsegna/OnMove200

Récupérer les fichiers OMD de la montre

En connectant la montre sur le pc par USB, il est possible de récuperer les fichiers OMD et OMH. Je n'exploite ici que les OMD que je colle dans le dossier d'installation de Python (en général, quelque chose qui ressemble à c:\Python) (Remarque, ce programme utilisé ici est Python 3.6).
Dans notre exemple ici, nous exploiterons le fichier appelé ACT_0000.OMD

Structure du fichier OMD

Les fichiers OMD sont des fichiers dits "binaires", c'est a dire qu'ils se présentent sous des octets écrits les uns derrière les autres. En les ouvrant avec le BlocNote, ils sont illisibles par les humains.

Les octets présentés sous leur forme hexadécimale se présentent ainsi sous Notepad++. On y remarque un motif récurent :
  • 20eme caractere : F1 en hexa (=241 en décimal),
  • 40eme caractère : F1
  • et 60eme caractère F2 (=242 en décimal)
Code hexadécimal des fichiers OMD


Ces fichiers OMD sont cependant structurés, et en les convertissant en valeurs décimales, on fait apparaitre cette structure en les rangeant dans un tableau de 60 colonnes (ici les 60 colonnes sont représentées chacunes sur 3 lignes finissant par F1, F1 et F2.

lat0 lat1 lat2 lat3 lon0 lon1 lon2 lon3 dist0 dist1 dist2 dist3 tps0 tps1 inc alt0 alt1 inc inc F1
lat0 lat1 lat2 lat3 lon0 lon1 lon2 lon3 dist0 dist1 dist2 dist3 tps0 tps1 inc alt0 alt1 inc inc F1
tps0 tps1 vit0 vit1 KCal0 KCal1 coeur inc inc moitieF2 tps0 tps1 vit0 vit1 KCal0 KCal1 coeur inc inc F2




















44 56 240 2 253 240 59 0 12 0 0 0 5 0 3 125 0 0 0 241
62 56 240 2 173 240 59 0 19 0 0 0 10 0 3 126 0 0 0 241
5 0 27 2 0 0 79 0 2 0 10 0 2 3 0 0 74 0 2 242
65 56 240 2 134 240 59 0 22 0 0 0 15 0 3 124 0 0 0 241
40 56 240 2 68 240 59 0 27 0 0 0 20 0 3 122 0 0 0 241
15 0 250 0 0 0 75 0 2 0 20 0 100 1 1 0 80 0 2 242
10 56 240 2 6 240 59 0 33 0 0 0 25 0 3 122 0 0 0 241
...


Ce tableau est produit par le fichier Python que je vous propose sur cette page.

Par tatonnement, et grace aux commentaires du programme en C évoqu" plus haut, j'ai déduit quelles étaient les informations contenues dans chaque colonne.

F1, F1, F2

Il faut bien voir que mes 20 premieres valeurs (Type F1, partie 1) correspondent à un point de mesure, suivies de 20 nouvelle valeurs (type F1, partie 2), et suivit à nouveaux de 20 valeurs (Type F2).
En fait F2 est composé lui meme de 2 fois 10 valeurs: les 10 premieres venant complété le point de mesure "F1, partie1", et les 10 valeurs suivantes complétant le point de mesure "F1, partie 2".

En résumé sur une ligne de 60 colonnes, nous avons 2 points de mesures

Quant à la dernière ligne, si elle ne comporte qu'un seul point de mesure, il n'y aura alors que 40 colonnes, les premiers F1, suivi d'un F2 dont les 9 dernieres valeurs seront nulles pas de deuxieme valeur F1)  et la derniere correspondant à F2=242. Remarque, dans ce cas, le programme python ne lit pas ce derniere point de mesure.

Les informations disponibles

lat / 4 octets  = latitude (x1.000.000°)
lon / 4 octets = longitude (x1.000.000°)
dist / 4 octets = distance parcourue (m)
tps / 2 octets = temps (s) depuis le départ (1 point de mesure toutes les 5 secondes)
alt / 2 octets = altitude (m) (ATTENTION, cette information est peut etre codée sur d'avantage d'octets, voir plus loin)
vit / 2 octets = vitesse (100 m/h, si donne 1234, alors la vitesse est d e12.34km/h)
KCal / 2 octets =?? selon le programme Linux serait les kcalories dépensées (je n'ai pas vérifié, et j'ai oublié d'exporter cette donnée dans le fichier final)
coeur / 1 octet = rythme cardiaque  (battements par minute)
inc = information inconnue
moitierF2 = 0 car c'est pour marquer le milieu de la structure de F2

On remarque que certaines valeurs sont codées sur plusieurs octets  (la latitude est en effet codée sur 4 octets, tandis que le coeur sur 1 seul)
1 octet peut prendre entre 0 et 255 valeurs, ce qui est suffisant pour le ryhtnme cardiaque.
4 octets donnent des valeurs comprises entre 0 et 4.294.967.295 necessaire pour coder une lattitude avec suffisament de précision (exemple dans nos régions : 49,123456 sera codé 49.123.456)
Dans cet exemple, la latitude aura pour valeur (à un facteur 1000.000 pres) lat3*256^3 + lat2*256^2 + lat1*256 + lat0 (256 étant le nombre de valeurs maximales codées sur 1 octet)

L'altitude est codée sur 2 octets (65.535 valeurs), mais pourrait etre codé sur davantage d'octets, notamment pour prendre en considération les altitudes négatives qui peuvent apparaitre en différents points du monde, mais je n'ai pas eu les moyens de vérifier cela, et cela reste marginal.

Le tableau de données sortant du programme python donne ainsi les info suivantes (toutes les 5 secondes)
Exemple:
Temps(s) Cardio(ppm) Distance(m) Vitesse(km/h) Latitude(°) Longitude(°) Altitude(m)
5 79 12 5,39 49,297452 3,928317 125
10 74 19 7,7 49,29747 3,928237 126
15 75 22 2,5 49,297473 3,928198 124
...

Programme Python

Après avoir installé Python, il suffit de glisser le fichier suivant dans le dossier python (habituellement, un nom de dossier qui ressemble à ceci C:\Python36\). C'est également dans ce même dossier que vous glisserez le fichier OMD provenant de votre montre (pour l'exemple, mon fichier porte le nom ACT_0000.OMD

# créé par uncledens , http://uncledens.chez-alice.fr/

fichier='ACT_0000' #nom du fichier (sans l'extention .OMD)
champ=["lat0","lat1","lat2","lat3","lon0","lon1","lon2","lon3","dist0","dist1","dist2","dist3","tps0","tps1","inconnu","alt0","alt1","inconnu","inconnu","F1",
       "lat0","lat1","lat2","lat3","lon0","lon1","lon2","lon3","dist0","dist1","dist2","dist3","tps0","tps1","inconnu","alt0","alt1","inconnu","inconnu","F1",
       "tps0","tps1","vit0","vit1","KCal0","KCal1","coeur","inconnu","inconnu","moitieF2","tps0","tps1","vit0","vit1","KCal0","KCal1","coeur","inconnu","inconnu","F2"]
result=["Temps(s)","Cardio(ppm)","Distance(m)","Vitesse(km/h)","Latitude(°)","Longitude(°)","Altitude(m)"]
nbresult=len(result)
sep="\t" #separateur \t = tabulation

txt=""
for i in range(60):
    txt+=champ[i]+sep
txt+="\n"

txtresult=""
for i in range(nbresult):
    txtresult+=result[i]+sep
txtresult+="\n"
   
      
cpt=0
premiereligne=1
with open(fichier+'.OMD', 'rb') as file: #OMD et OMH 1, 2, 5, 40
    for c in file:
        for i in c:
            octet=str(i)
            col=cpt%60

           
            if col==0:
                txt+="\n"
               
                if premiereligne==1:
                    premiereligne=0
                else:# calcule toutes les variables et intégre dans txtresult
                    #calcul du temps
                    tps1=str(champ[13]*256+champ[12])
                    tps2=str(champ[33]*256+champ[32])
                    #Cardio
                    card1=str(champ[46])
                    card2=str(champ[56])
                    #distance(m)
                    dist1=str(champ[11]*256**3+champ[10]*256**2+champ[9]*256+champ[8])
                    dist2=str(champ[31]*256**3+champ[30]*256**2+champ[29]*256+champ[28])
                    #vitesse instantanée
                    vit1=str((champ[43]*256+champ[42])/100)
                    vit2=str((champ[53]*256+champ[52])/100)
                    #longitude
                    lon1=str((champ[7]*256**3+champ[6]*256**2+champ[5]*256+champ[4])/1000000)
                    lon2=str((champ[27]*256**3+champ[26]*256**2+champ[25]*256+champ[24])/1000000)
                    #latitude
                    lat1=str((champ[3]*256**3+champ[2]*256**2+champ[1]*256+champ[0])/1000000)
                    lat2=str((champ[23]*256**3+champ[22]*256**2+champ[21]*256+champ[20])/1000000)
                    #altitude
                    alt1=str(champ[16]*256+champ[15])
                    alt2=str(champ[36]*256+champ[35])

                    txtresult+=(tps1+sep+card1+sep+dist1+sep+vit1+sep+lat1+sep+lon1+sep+alt1+"\n").replace(".",",")
                    txtresult+=(tps2+sep+card2+sep+dist2+sep+vit2+sep+lat2+sep+lon2+sep+alt2+"\n").replace(".",",")               
            else:
                txt+="\t"
            
            if i<10:
                txt+="00"
            elif i<100:
                txt+="0"
            txt+=octet
            champ[col]=int(octet)
            cpt+=1


destinationsave = open(fichier+'DATA0.txt', "w")# traduction des valeurs hexadecimales brutes en valeurs décimales, exportées sous forme de tableau
destinationsave.write(txt)
destinationsave.close()
destinationsave = open(fichier+'DATA1.txt', "w")# export des données calculées depuis les valeurs brutes du précédent tableau
destinationsave.write(txtresult)
destinationsave.close()



Comment lire les fichiers résultants sous Excel ou OpenOffice, ou LibreOffice

Le programme python permet de générer les données brutes Hexadécimales (fichier ACT_0000.OMD ) en un tableau de données brutes au format décimal (ACT_0000DATA0.txt), ainsi qu'un second fichier ACT_0000DATA1.txt basé sur ce modèle:
Temps(s) Cardio(ppm) Distance(m) Vitesse(km/h) Latitude(°) Longitude(°) Altitude(m)
5 79 12 5,39 49,297452 3,928317 125
10 74 19 7,7 49,29747 3,928237 126
15 75 22 2,5 49,297473 3,928198 124
...

Les colonnes sont séparées par des tabulations. Ce séparateur (variable sep )peut être modifié dans le programme python
sep="\t" #separateur \t = tabulation
Si vous désirez avoir un point virgule à la place de la tabultaiton, vous définirez sep ainsi:
sep=";"

Ce fichier peut être lu avec le BlocNote, mais l'idée est de l'ouvrir avec un tableur Excel, OpenOffice, LibreOffice ou tout autre logiciel afin que vous traciez vos propres courbes de données.

Exemple:

  1. Fichier OMD
  2. Programme
  3. Tableau brut décimal
  4. Tableau Cardio, GPS, Vitesse... (format TXT)
  5. Tableau Excel avec courbes tracées
>> Télécharger l'ensemble des fichiers (zip)

Mises à jour

exemple:
exemple de trace GPX exportée sur Geoportail

  • Maj du 1er janvier 2021: omd_to_txt02.py  génère automatiquement un graphique vitesse / cardio, altitude en fonction de la distance parcourue. Ces graphiques sont automatiquement affichés et sauvegardés dans le dossier C:/Python. Ce programme necessite l'installation des librairies numpy et matplotlib.pyplot
    exemple:
    Vitesse, cardio, altitude en fonction de la distance parcourue