Browse Source

first commit

psophometric 3 years ago
commit
5496c60d89
9 changed files with 607 additions and 0 deletions
  1. 5 0
      .gitignore
  2. 0 0
      README.md
  3. 1 0
      __init__.py
  4. BIN
      data/geo_sncf.db
  5. 204 0
      export_geoloc_sncf.py
  6. 58 0
      open_localisateur_ANDROID.py
  7. 251 0
      open_pkfieur_PC.py
  8. 1 0
      utils/__init__.py
  9. 87 0
      utils/pkfieur.py

+ 5 - 0
.gitignore

@@ -0,0 +1,5 @@
1
+*.pyc
2
+*.html
3
+*.txt
4
+*.csv
5
+*.json

+ 0 - 0
README.md


+ 1 - 0
__init__.py

@@ -0,0 +1 @@
1
+from . import utils

BIN
data/geo_sncf.db


+ 204 - 0
export_geoloc_sncf.py

@@ -0,0 +1,204 @@
1
+#!/usr/bin/python
2
+# -*- coding: utf-8 -*-
3
+from __future__ import unicode_literals, print_function #Compatibilité Python3
4
+import json
5
+import os, sys, argparse
6
+import sqlite3
7
+import re, requests
8
+try : #Vérification dépendance Pandas
9
+    import pandas as pd
10
+except ImportError:
11
+    print('Nécessite le module Pandas\npip install pandas\n')
12
+
13
+# CONSTANTES
14
+REPERTOIRE_JSON = 'json/'
15
+GAR_FILE = 'liste-des-gares.json'
16
+REPERTOIRE_DATA = 'data/'
17
+CSV_GEO_FILE = 'open_geo_sncf__.csv'
18
+CSV_GAR_FILE = 'open_gar_sncf__.csv'
19
+DB_FILE = 'geo_sncf.db'
20
+
21
+# VARIABLES GLOBALES
22
+dico = {}
23
+dfout = pd.DataFrame()
24
+dfgar = pd.DataFrame()
25
+
26
+#API KEYWORD : GEOLOCALISATION
27
+urlall = 'https://ressources.data.sncf.com/api/datasets/1.0/search/?rows=999&facet=keyword&refine.keyword=G%C3%A9olocalisation'
28
+
29
+def telechargement(url_req):
30
+    """ Recherche par l'API les datasets tagés 'Géolocalisation'
31
+        Télécharge les datasets dans le répertoire 'REPERTOIRE_JSON' """
32
+    try:
33
+        ls_dir_zip = os.listdir(REPERTOIRE_JSON)
34
+    except:
35
+        print('création du dossier ', REPERTOIRE_JSON)
36
+        os.mkdir(REPERTOIRE_JSON)
37
+    req = requests.get(url_req)
38
+    req = req.json()
39
+    req = req['datasets']
40
+    print('Il y a %s datasets avec données de géolocalisation à télécharger' % len(req))
41
+    for i in range(0,len(req)):
42
+        datasetid = req[i]['datasetid']
43
+        url = 'https://ressources.data.sncf.com/explore/dataset/{}/download/?format=json'.format(datasetid)
44
+        print('Téléchargement du dataset ', datasetid)
45
+        r = requests.get(url)
46
+        with open(REPERTOIRE_JSON+datasetid+'.json', "wb") as f:
47
+            f.write(r.content)
48
+
49
+def list_files():
50
+    """ Liste les fichiers .json présent dans le répertoire 'REPERTOIRE_JSON'  """
51
+    liste=[]
52
+    for file in os.listdir(REPERTOIRE_JSON):
53
+        if file.endswith(".json"):
54
+            liste.append(os.path.join(REPERTOIRE_JSON, file))
55
+    return liste
56
+
57
+def regex_fields(list_fields):
58
+    """ Regex sur les dans une liste les noms correspondants aux libellés suivants :
59
+        - ligne
60
+        - pk
61
+        - coordonnées géographiques
62
+        Et renvoit une liste contenant les libellés trouvés. """
63
+    debfin=False
64
+    for fields in list_fields:
65
+        if re.match(r"^(?=.*coord)(?=.*geo)(?=.*deb|.*fin)", fields) :
66
+            debfin = True
67
+    try:
68
+        for fields in list_fields:
69
+            if fields == 'ligne' or fields == 'code_ligne': ligne = fields
70
+            if debfin :
71
+                if re.match(r"^(?=.*pk)(?=.*deb)", fields): pk_deb = fields
72
+                if re.match(r"^(?=.*pk)(?=.*fin)", fields): pk_fin = fields
73
+                if re.match(r"^(?=.*coord)(?=.*geo)(?=.*deb)",fields): cg_deb=fields
74
+                if re.match(r"^(?=.*coord)(?=.*geo)(?=.*fin)",fields): cg_fin=fields
75
+            else:
76
+                if re.match(r"^(?=.*pk)", fields): pk = fields
77
+                if re.match(r"^(?=.*coord)(?=.*geo)", fields): cg = fields
78
+        if debfin:
79
+            list_fields = [[ligne, pk_deb, cg_deb],
80
+                           [ligne, pk_fin, cg_fin]]
81
+        else:
82
+            list_fields = [[ligne, pk, cg]]
83
+    except:
84
+        return False
85
+    else:
86
+        return list_fields
87
+
88
+def geo2df(f):
89
+    """ Mise en forme du dataset avec Pandas """
90
+    global dfout
91
+    try:
92
+        df = pd.read_json(f, orient = 'columns')
93
+    except:
94
+        print('erreur de lecture du fichier ', f)
95
+        return False
96
+    print('création de la base Géolocalisation')
97
+    df = pd.read_json(df['fields'].to_json(),orient = 'index')
98
+    list_fields = list(df.columns.values)
99
+    list_fields = regex_fields(list_fields) # APPEL FCT regex_fields()
100
+    if list_fields:
101
+        for i in list_fields:
102
+            df_out_tmp = dfout
103
+            df_tmp = df[i]
104
+            df_tmp = df_tmp.dropna()
105
+            df_tmp = df_tmp.reset_index(drop=True)
106
+            df_tmp[['lat','lon']] = pd.DataFrame([x for x in df_tmp[i[2]]])
107
+            df_tmp[i[1]] = df_tmp[i[1]].str.replace('+','.').str.replace('-','.')
108
+            df_tmp[i[1]] = df_tmp[i[1]].astype(float)
109
+            df_tmp[i[0]] = df_tmp[i[0]].astype('int64')
110
+            df_tmp = df_tmp.drop(i[2], axis=1)
111
+            df_tmp = df_tmp.rename(columns = {i[1]:'pk'})
112
+            df_tmp = df_tmp.rename(columns = {i[0]:'code_ligne'})
113
+            dfout = pd.concat([df_out_tmp,df_tmp], ignore_index=True)
114
+            dfout = dfout.drop_duplicates()
115
+    else:
116
+        print('le fichier %s, ne contient pas de données géolocalisées' % f)
117
+        return False
118
+    return True
119
+
120
+def geo2csv():
121
+    """ Export CSV """
122
+    dfout.to_csv(REPERTOIRE_DATA+CSV_GEO_FILE, sep=str(';'), encoding='utf-8', index=False)
123
+
124
+def geo2db():
125
+    """ Export SQLite """
126
+    try:
127
+        ls_dir_zip = os.listdir(REPERTOIRE_DATA)
128
+    except:
129
+        print('création du dossier ', REPERTOIRE_DATA)
130
+        os.mkdir(REPERTOIRE_DATA)
131
+    con = sqlite3.connect(REPERTOIRE_DATA+DB_FILE)
132
+    dfout.to_sql("geo", con, if_exists="replace", index=False)
133
+    con.commit()
134
+    con.close()
135
+
136
+def gar2df():
137
+    """ Mise en forme du dataset avec Pandas
138
+        Spécifique Liste des Gares """
139
+    global dfgar
140
+    try:
141
+        dfgar = pd.read_json(REPERTOIRE_JSON+GAR_FILE, orient = 'columns')
142
+    except:
143
+        print('erreur de lecture du fichier ', REPERTOIRE_JSON+GAR_FILE)
144
+        return False
145
+    print('création de la base Gares')
146
+    dfgar = pd.read_json(dfgar['fields'].to_json(),orient = 'index')
147
+    dfgar = dfgar[['code_ligne','pk','libelle_gare']]
148
+    dfgar['pk'] = dfgar['pk'].str.replace('+','.').str.replace('-','.')
149
+    dfgar['pk'] = dfgar['pk'].astype(float)
150
+    dfgar['code_ligne'] = dfgar['code_ligne'].astype('int64')
151
+    dfgar = dfgar.dropna()
152
+    dfgar = dfgar.reset_index(drop=True)
153
+    dfgar = dfgar.drop_duplicates()
154
+
155
+def gar2csv():
156
+    """ Export CSV
157
+        Spécifique Liste des Gares """
158
+    dfgar.to_csv(REPERTOIRE_DATA+CSV_GAR_FILE, sep=str(';'), encoding='utf-8', index=False)
159
+
160
+def gar2db():
161
+    """ Export SQLite
162
+        Spécifique Liste des Gares """
163
+    global dfgar
164
+    con = sqlite3.connect(REPERTOIRE_DATA+DB_FILE)
165
+    dfgar.to_sql("gar", con, if_exists="replace", index=False)
166
+    con.commit()
167
+    con.close()
168
+
169
+def supprimer_fichiers_JSON():
170
+    """ Supprime les fichiers .json de 'REPERTOIRE_JSON '"""
171
+    #SUPRESSION DES FICHIERS DU REPERTOIRE
172
+    for file in os.listdir(REPERTOIRE_JSON):
173
+        if file.endswith(".json"):
174
+            os.remove(os.path.join(REPERTOIRE_JSON, file))
175
+    return True
176
+
177
+def parser():
178
+    """ Passage des arguments par ligne de commande """
179
+    parser = argparse.ArgumentParser(description='Demo')
180
+    parser.add_argument('--sql','-s', action='store_true', help='export SQLite' )
181
+    parser.add_argument('--csv','-c', action='store_true', help='export CSV' )
182
+    parser.add_argument('--delete','-d', action='store_true', help='delete JSON files after export' )
183
+    return parser.parse_args()
184
+
185
+if __name__ == '__main__':
186
+    args = parser()
187
+    if not len(sys.argv) > 1: # Si aucun argument : export SQLite
188
+        args.sql = True
189
+    telechargement(urlall)
190
+    list_f=list_files()
191
+    for f in list_f:
192
+        print(f)
193
+        geo2df(f)
194
+if args.sql:
195
+    geo2db()
196
+if args.csv:
197
+     geo2csv()
198
+gar2df()
199
+if args.sql:
200
+    gar2db()
201
+if args.csv:
202
+    gar2csv()
203
+if args.delete:
204
+    supprimer_fichiers_JSON()

+ 58 - 0
open_localisateur_ANDROID.py

@@ -0,0 +1,58 @@
1
+#!/usr/bin/python
2
+# -*- coding: utf8 -*-
3
+from __future__ import unicode_literals
4
+import time, os, sys
5
+import thread
6
+try :
7
+    import androidhelper
8
+except ImportError:
9
+    print('Uniquement compatible avec périphérique sous ANDROID\n')
10
+from utils import *
11
+
12
+#Emplacement de la base de données sur le smartphone
13
+table_name = '/storage/emulated/0/qpython/scripts/open-geolocalisation-sncf/data/geo_sncf.db'
14
+rgps = False
15
+
16
+def Gps():
17
+    global rgps
18
+    while True:
19
+        droid.eventClearBuffer()
20
+        res = droid.eventWait(3000).result
21
+        if res == None:
22
+          os.system('clear')
23
+          sys.stdout.write("no fix")
24
+          sys.stdout.flush()
25
+          continue
26
+        elif res['name'] == "location":
27
+          # It's a GPS message!
28
+          try:
29
+            loc = res['data']['gps']
30
+          except (KeyError, TypeError):
31
+            #print("Location message, but no GPS data")
32
+            continue
33
+          else:
34
+            rgps = str(loc['latitude']) +','+ str(loc['longitude'])
35
+        time.sleep(1)
36
+
37
+if __name__ == '__main__':
38
+    print "Chargement..."
39
+    droid = androidhelper.Android()
40
+    droid.startLocating(0, 0)
41
+    thread.start_new_thread(Gps,())
42
+    while True:
43
+        try:
44
+          if rgps:
45
+            res, ecart = pkfieur.coord2pk(rgps, table_name)
46
+            gar1, gar2 = pkfieur.gares(res['ligne'], res['pk'], table_name)
47
+            os.system('clear')
48
+            sys.stdout.write("GPS : {0}\n\n".format(rgps))
49
+            sys.stdout.write("Ligne : {0}\n".format(res['ligne']))
50
+            sys.stdout.write("PK : {0}\n\n".format(res['pk']))
51
+            sys.stdout.write("Distance du PK : {0} m\n\n".format(ecart).encode('utf8'))
52
+            sys.stdout.write(u"Gares encadrantes :\n{0}\n{1}\n".format(gar1, gar2).encode('utf8'))
53
+            sys.stdout.flush()
54
+            time.sleep(1)
55
+        except KeyboardInterrupt:
56
+           print "\nQuit"
57
+           droid.stopLocating()
58
+           thread.exit()

+ 251 - 0
open_pkfieur_PC.py

@@ -0,0 +1,251 @@
1
+#!/usr/bin/python
2
+# -*- coding: utf8 -*-
3
+from __future__ import unicode_literals
4
+try: # Compatibilité Python 3
5
+    from Tkinter import *
6
+except:
7
+    from tkinter import ttk
8
+    from tkinter import messagebox as tkMessageBox
9
+    from tkinter import Tk, Label, Entry, Button, END
10
+else:
11
+    import ttk, tkFileDialog, tkMessageBox
12
+import socket
13
+import threading
14
+import time
15
+import re
16
+import webbrowser
17
+from utils import *
18
+
19
+#Emplacement de la base de données
20
+table_name = 'data/geo_sncf.db'
21
+var = True
22
+rgps = False
23
+
24
+class App(Tk):
25
+    def __init__(self, parent):
26
+        self.parent = parent
27
+        self.initUI()
28
+        self.config={}
29
+
30
+    def initUI(self):
31
+        self.parent.title("open_pkfieur")
32
+        self.n = ttk.Notebook(self.parent)
33
+        self.f1 = ttk.Frame(self.n)
34
+        self.f2 = ttk.Frame(self.n)
35
+        self.f3 = ttk.Frame(self.n)
36
+        self.n.add(self.f1, text='Géo2pk')
37
+        self.n.add(self.f2, text='Pk2Géo')
38
+        self.n.add(self.f3, text='Localisateur Gps')
39
+        self.n.grid(column=0, row=0, columnspan=1, sticky="nsew")
40
+        self.f1_populate()
41
+        self.f2_populate()
42
+        self.f3_populate()
43
+
44
+    def f1_populate(self):
45
+        self.Frame10 = ttk.LabelFrame(self.f1, text='Coordonnées Géographiques')
46
+        self.Frame10.grid(column=0, row=0, columnspan=3, rowspan=2, sticky="ew")
47
+        self.Frame11 = ttk.LabelFrame(self.f1, text='Ligne/Pk')
48
+        self.Frame11.grid(column=0, row=2, columnspan=3, rowspan=41, sticky="ew")
49
+        self.Frame14 = ttk.Frame(self.f1, borderwidth=0, relief='groove')
50
+        self.Frame14.grid(column=4, row=0, rowspan=6, sticky="EW")
51
+
52
+        label = Label(self.Frame10, text="Lat").grid(row=0, column=0)
53
+        label = Label(self.Frame10, text="Lon").grid(row=1, column=0)
54
+        self.lat = Entry(self.Frame10)
55
+        self.lat.grid(row=0, column=1)
56
+        self.lon = Entry(self.Frame10)
57
+        self.lon.grid(row=1, column=1)
58
+
59
+        label = Label(self.Frame11, text="Ligne").grid(row=0, column=0)
60
+        label = Label(self.Frame11, text="Pk").grid(row=1, column=0)
61
+        label = Label(self.Frame11, text="Précision").grid(row=2, column=0)
62
+
63
+        self.button_tri = Button(self.Frame14, text="Rechercher", command=self.get_coord)
64
+        self.button_tri.grid(row=0,column=0)
65
+
66
+    def f2_populate(self):
67
+        self.Frame20 = ttk.LabelFrame(self.f2, text='Ligne/Pk')
68
+        self.Frame20.grid(column=0, row=0, columnspan=2, rowspan=2, sticky="ew")
69
+        self.Frame21 = ttk.LabelFrame(self.f2, text='Coordonnées Géographiques')
70
+        self.Frame21.grid(column=0, row=3, columnspan=2, rowspan=3, sticky="ew")
71
+        self.Frame23 = ttk.Frame(self.f2, borderwidth=0, relief='groove')
72
+        self.Frame23.grid(column=3, row=0, rowspan=3, sticky="EW")
73
+        self.Frame24 = ttk.Frame(self.f2, borderwidth=0, relief='groove')
74
+        self.Frame24.grid(column=3, row=3, rowspan=3, sticky="EW")
75
+
76
+        label = Label(self.Frame20, text="Ligne").grid(row=0, column=0)
77
+        label = Label(self.Frame20, text="Pk").grid(row=1, column=0)
78
+        self.ligne = Entry(self.Frame20)
79
+        self.ligne.grid(row=0, column=1)
80
+        self.pk = Entry(self.Frame20)
81
+        self.pk.grid(row=1, column=1)
82
+
83
+        label = Label(self.Frame21, text="Lat").grid(row=0, column=0)
84
+        label = Label(self.Frame21, text="Lon").grid(row=1, column=0)
85
+        label = Label(self.Frame21, text="Précision").grid(row=2, column=0)
86
+
87
+        self.button_tri = Button(self.Frame23, text="Rechercher", command=self.get_pk)
88
+        self.button_tri.grid(row=0,column=0)
89
+
90
+    def f3_populate(self):
91
+        self.Frame30 = ttk.LabelFrame(self.f3, text='@ NMEA')
92
+        self.Frame30.grid(column=0, row=0, columnspan=2, rowspan=2, sticky="ew")
93
+        self.Frame31 = ttk.LabelFrame(self.f3, text='Ligne/Pk')
94
+        self.Frame31.grid(column=0, row=2, columnspan=2, rowspan=3, sticky="ew")
95
+        self.Frame33 = ttk.Frame(self.f3, borderwidth=0, relief='groove')
96
+        self.Frame33.grid(column=3, row=0, rowspan=3, sticky="EW")
97
+        self.Frame34 = ttk.Frame(self.f3, borderwidth=0, relief='groove')
98
+        self.Frame34.grid(column=3, row=3, rowspan=3, sticky="EW")
99
+
100
+        label = Label(self.Frame30, text="IP").grid(row=0, column=0)
101
+        label = Label(self.Frame30, text="Port").grid(row=1, column=0)
102
+        self.adresse = Entry(self.Frame30)
103
+        self.adresse.grid(row=0, column=1)
104
+        self.adresse.insert(END, '192.168.43.1') # Adresse par défaut du Point d'accès mobile Android
105
+        self.port = Entry(self.Frame30)
106
+        self.port.grid(row=1, column=1)
107
+        self.port.insert(END, '50000') # Port par défaut de Share GPS
108
+
109
+        label = Label(self.Frame31, text="Ligne").grid(row=0, column=0)
110
+        label = Label(self.Frame31, text="Pk").grid(row=1, column=0)
111
+        label = Label(self.Frame31, text="Précision").grid(row=2, column=0)
112
+
113
+        self.button_tri = Button(self.Frame33, text="Démarrer", command=self.get_nmea)
114
+        self.button_tri.grid(row=0,column=0)
115
+
116
+    def get_coord(self):
117
+        lat = self.lat.get()
118
+        lon = self.lon.get()
119
+        lat = lat.replace(',','.')
120
+        lon = lon.replace(',','.')
121
+        regex = True
122
+        rLatLon = re.compile(r"^[-]{0,1}\d{1,}[.]{1}\d{1,}$")
123
+        if not rLatLon.search(lat):regex=False
124
+        if not rLatLon.search(lon):regex=False
125
+        if not regex :
126
+            tkMessageBox.showinfo("Erreur Saisie", "Erreur de saisie lat/lon.")
127
+            return False
128
+        inp = lat+','+lon
129
+        res, ecart = pkfieur.coord2pk(inp, table_name)
130
+        if len(res) == 0:
131
+            tkMessageBox.showinfo("Lat/lon introuvable", "Aucune correspondance trouvée.")
132
+            return False
133
+        try:
134
+            for widget in self.Frame11.winfo_children():
135
+                widget.destroy()
136
+        except:
137
+            pass
138
+        label = Label(self.Frame11, text="Ligne").grid(row=0, column=0)
139
+        label = Label(self.Frame11, text="Pk").grid(row=1, column=0)
140
+        label = Label(self.Frame11, text="Précision").grid(row=2, column=0)
141
+        label_nb = Label(self.Frame11, text=res['ligne']).grid(row=0, column=1)
142
+        label_nb = Label(self.Frame11, text=res['pk']).grid(row=1, column=1)
143
+        label_nb = Label(self.Frame11, text=(str(ecart)+' m')).grid(row=2, column=1)
144
+
145
+    def get_pk(self):
146
+        ligne = self.ligne.get()
147
+        pk = self.pk.get()
148
+        pk = pk.replace('+','.').replace(',','.')
149
+        regex = True
150
+        rLigne = re.compile(r"^\d{1,6}$")
151
+        rPk = re.compile(r"^\d{1,3}[.]{0,1}\d{0,3}$")
152
+        if not rLigne.match(ligne):regex=False
153
+        if not rPk.match(pk):regex=False
154
+        if not regex :
155
+            tkMessageBox.showinfo("Erreur Saisie", "Erreur de saisie ligne/pk.")
156
+            return False
157
+        res, ecart = pkfieur.pk2coord(ligne, pk, table_name)
158
+        if len(res) == 0:
159
+            tkMessageBox.showinfo("Erreur Ligne", "Aucune ligne trouvée.")
160
+            return False
161
+        try:
162
+            for widget in self.Frame21.winfo_children():
163
+                widget.destroy()
164
+        except:
165
+            pass
166
+        label = Label(self.Frame21, text="Lat").grid(row=0, column=0)
167
+        label = Label(self.Frame21, text="Lon").grid(row=1, column=0)
168
+        label = Label(self.Frame21, text="Précision").grid(row=2, column=0)
169
+        label_nb = Label(self.Frame21, text=res['lat']).grid(row=0, column=1)
170
+        label_nb = Label(self.Frame21, text=res['lon']).grid(row=1, column=1)
171
+        label_nb = Label(self.Frame21, text=(str(ecart)+' m')).grid(row=2, column=1)
172
+        button = Button(self.Frame24, text='web', command=lambda:self.web(res))
173
+        button.grid(row=0,column=0)
174
+
175
+    def web(self,res):
176
+        url = 'http://www.openstreetmap.org/?mlat={0}&mlon={1}&zoom=15'.format(res['lat'],res['lon'])
177
+        webbrowser.open(url)
178
+
179
+    def stop(self):
180
+        global var
181
+        var = False
182
+
183
+    def get_nmea(self):
184
+        global var
185
+        var = True
186
+        adresse = self.adresse.get()
187
+        port = self.port.get()
188
+
189
+        def affiche():
190
+            global rgps, var
191
+            while var:
192
+                if rgps:
193
+                    res, ecart = pkfieur.coord2pk(rgps, table_name)
194
+                else:
195
+                    res = {'ligne':'no fix', 'pk':'no fix'}
196
+                    ecart = 9999
197
+                try:
198
+                    for widget in self.Frame31.winfo_children():
199
+                        widget.destroy()
200
+                except:
201
+                    pass
202
+                label = Label(self.Frame31, text="Ligne").grid(row=0, column=0)
203
+                label = Label(self.Frame31, text="Pk").grid(row=1, column=0)
204
+                label = Label(self.Frame31, text="Précision").grid(row=2, column=0)
205
+                label_nb = Label(self.Frame31, text=res['ligne']).grid(row=0, column=1)
206
+                label_nb = Label(self.Frame31, text=res['pk']).grid(row=1, column=1)
207
+                label_nb = Label(self.Frame31, text=(str(ecart)+' m')).grid(row=2, column=1)
208
+                button = Button(self.Frame34, text='stop', command=self.stop)
209
+                button.grid(row=0,column=0)
210
+                time.sleep(1)
211
+
212
+        def nmeaGps():
213
+            global rgps, var
214
+            host = adresse
215
+            p = int(port)
216
+            PACKET_SIZE=1152
217
+            sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
218
+            try:
219
+                sock.connect((host,p))
220
+            except :
221
+                var = False
222
+                tkMessageBox.showinfo("Echec connection", "Vérifier adresse IP et périphérique GPS")
223
+            else:
224
+                while var: #continuously read and handle data
225
+                    data = sock.recv(PACKET_SIZE)
226
+                    try:
227
+                        for line in data.split(b"\r\n"):
228
+                            if line.startswith(b'$GPGGA'):
229
+                                lat, NS, lon, EW, fix = line.strip().split(b',')[2:7]
230
+                                if fix != '0':
231
+                                    Decilat = int(float(lat)/100) + (float(lat)-int(float(lat)/100)*100)/60
232
+                                    Decilon = int(float(lon)/100) + (float(lon)-int(float(lon)/100)*100)/60
233
+                                    if (NS=='S'):
234
+                                        Decilat = (-1)*Decilat
235
+                                    if (EW=='W'):
236
+                                        Decilon = (-1)*Decilon
237
+                                    rgps = str(Decilat) + "," + str(Decilon)
238
+                                else: rgps = False
239
+                    except:
240
+                        pass
241
+                sock.close()
242
+
243
+        gps = threading.Thread(target=nmeaGps)
244
+        aff = threading.Thread(target=affiche)
245
+        gps.start()
246
+        aff.start()
247
+
248
+if __name__ == '__main__':
249
+    root = Tk()
250
+    app = App(root)
251
+    root.mainloop()

+ 1 - 0
utils/__init__.py

@@ -0,0 +1 @@
1
+from . import pkfieur

+ 87 - 0
utils/pkfieur.py

@@ -0,0 +1,87 @@
1
+#!/usr/bin/python
2
+# -*- coding: utf8 -*-
3
+from __future__ import unicode_literals
4
+import sqlite3
5
+from math import atan, tan, sin, cos, pi, sqrt, atan2, asin, radians, degrees
6
+
7
+# From GEOPY https://github.com/geopy/geopy
8
+EARTH_RADIUS = 6371.009
9
+def great(lat1,lng1,lat2,lng2):
10
+    lat1, lng1 = radians(lat1), radians(lng1)
11
+    lat2, lng2 = radians(lat2), radians(lng2)
12
+    sin_lat1, cos_lat1 = sin(lat1), cos(lat1)
13
+    sin_lat2, cos_lat2 = sin(lat2), cos(lat2)
14
+    delta_lng = lng2 - lng1
15
+    cos_delta_lng, sin_delta_lng = cos(delta_lng), sin(delta_lng)
16
+    d = atan2(sqrt((cos_lat2 * sin_delta_lng) ** 2 +
17
+                   (cos_lat1 * sin_lat2 -
18
+                    sin_lat1 * cos_lat2 * cos_delta_lng) ** 2),
19
+              sin_lat1 * sin_lat2 + cos_lat1 * cos_lat2 * cos_delta_lng)
20
+    return EARTH_RADIUS * d
21
+def destination(lat1,lng1,distance,bearing):
22
+    lat1, lng1 = radians(lat1), radians(lng1)
23
+    bearing = radians(bearing)
24
+    d_div_r = distance / EARTH_RADIUS
25
+    lat2 = asin(
26
+        sin(lat1) * cos(d_div_r) +
27
+        cos(lat1) * sin(d_div_r) * cos(bearing)
28
+    )
29
+    lng2 = lng1 + atan2(
30
+        sin(bearing) * sin(d_div_r) * cos(lat1),
31
+        cos(d_div_r) - sin(lat1) * sin(lat2)
32
+    )
33
+    return degrees(lat2), degrees(lng2)
34
+
35
+def pk2coord(ligne, pk, table_name):
36
+    ref = 9999
37
+    result = ''
38
+    con = sqlite3.connect(table_name)
39
+    cur = con.cursor()
40
+    cur.execute("""SELECT pk, lat, lon FROM geo WHERE code_ligne = {}""".format(ligne))
41
+    req = cur.fetchall()
42
+    con.close()
43
+    pk = float(pk)
44
+    for pk2, lat2, lon2 in req:
45
+        test = abs(pk2 - pk)
46
+        if test < ref:
47
+            ref = test
48
+            result = {'lat': lat2, 'lon':lon2}
49
+    return result, round(ref*1000,3)
50
+
51
+def coord2pk(coord, table_name):
52
+    lat1,lon1 = coord.split(',')
53
+    lat1, lon1 = float(lat1), float(lon1)
54
+    lat0, lon0 = destination(lat1,lon1,1,0)
55
+    lat90, lon90 = destination(lat1,lon1,1,90)
56
+    dif0 = lat0 - lat1
57
+    dif90 = lon90 - lon1
58
+    latmini = lat1 - dif0
59
+    lonmini = lon1 - dif90
60
+    latmaxi, lonmaxi = lat0, lon90
61
+    ref = 9999
62
+    result=''
63
+    con = sqlite3.connect(table_name)
64
+    cur = con.cursor()
65
+    cur.execute("""SELECT code_ligne, pk, lat, lon FROM geo WHERE (lat < {}) AND (lat > {}) AND (lon < {}) AND (lon > {})""".format(latmaxi, latmini,lonmaxi,lonmini))
66
+    req = cur.fetchall()
67
+    con.close()
68
+    for ligne,pk, lat2, lon2 in  req:
69
+        test =  great(lat1,lon1,lat2,lon2)
70
+        if test < ref:
71
+            ref = test
72
+            result = {'ligne':ligne, 'pk':pk}
73
+    return result, round(ref*1000,3)
74
+
75
+def gares(ligne, pk, table_name):
76
+    result = '', ''
77
+    con = sqlite3.connect(table_name)
78
+    cur = con.cursor()
79
+    cur.execute("""SELECT pk, libelle_gare FROM gar WHERE code_ligne = {} ORDER BY pk ASC""".format(ligne))
80
+    req = cur.fetchall()
81
+    con.close()
82
+    pk = float(pk)
83
+    for i in range(0,len(req)):
84
+        if req[i][0] < pk <= req[i+1][0]:
85
+            result = req[i][1], req[i+1][1]
86
+            break
87
+    return result