Browse Source

Demo : show the name of sources

Olivier Marty 8 years ago
parent
commit
ec88c41467
4 changed files with 41 additions and 31 deletions
  1. 2 0
      README.md
  2. 2 1
      config.py
  3. 11 14
      demo.py
  4. 26 16
      source.py

+ 2 - 0
README.md

@@ -16,6 +16,8 @@ Avec Python 3, faites :
 Dans le fichier `config.py`, il faut configurer une API pour le service
 jcdecaux_vls (pour l'obtenir, aller à http://developer.jcdecaux.com/)
 
+Pour la démo, il faut configurer une clef API Google Maps (https://developers.google.com/maps/documentation/javascript/get-api-key)
+
 La section notifications de ce fichier permet de configurer la façon dont les
 notifications sont envoyées :
  - sendmail : envoie un mail (nécessite que la commande `mail` foncitonne)

+ 2 - 1
config.py

@@ -2,7 +2,8 @@
 # API KEYS
 
 api_key = {
-  'jcdecaux_vls' : ''
+  'jcdecaux_vls' : '',
+  'google_maps'  : ''
 }
 
 

+ 11 - 14
demo.py

@@ -8,30 +8,28 @@ import os
 def str_of_pos(pos):
   return '{lat: ' + str(pos[0]) + ', lng: ' + str(pos[1]) + '}'
 
+def escape(str):
+  return str.replace("'", "\\'")
+
 def str_of_marker(pos, description):
   return """
   marker = new google.maps.Marker({
     position: """ + str_of_pos(pos) + """,
     map: map,
-    title: '""" + description + """'
+    title: '""" + escape(description) + """'
   });
   var infowindow = new google.maps.InfoWindow({
-    content: '""" + description + """'
+    content: '""" + escape(description) + """'
   });
   infowindow.open(marker.get('map'), marker);"""
 
 
-def open_markers(center, markers):
-  # markers_str = map(lambda pos_name: '&markers=color:blue|label:' + pos_name[1] + '|' + str_of_pos(pos_name[0]) , markers)
-  # if input('Montrer la carte ? [Y/n] ') != 'n':
-  #   url = "http://maps.google.com/maps/api/staticmap?center" + str_of_pos(center) +\
-  #   '&zoom=14&size=512x512&maptype=roadmap' +\
-  #   '&markers=color:red|label:destination|' + str_of_pos(center) + ''.join(markers_str)
-  #   webbrowser.open_new(url)
+def open_markers(center, location, markers):
   if input('Montrer la carte ? [Y/n] ') != 'n':
     html = """<!DOCTYPE html>
 <html>
   <head>
+    <meta charset="utf-8">
     <style type="text/css">
       html, body { height: 100%; margin: 0; padding: 0; }
       #map { height: 100%; }
@@ -46,7 +44,7 @@ function initMap() {
     center: """ + str_of_pos(center) + """,
     zoom: 15
   });
-""" + str_of_marker(center, 'destination')
+""" + str_of_marker(center, 'Destination : ' + location)
     for (pos, name) in markers:
       html += str_of_marker(pos, name)
     html += """
@@ -58,7 +56,7 @@ function initMap() {
   </body>
 </html>"""
     (f, path) = tempfile.mkstemp(suffix=".html")
-    os.write(f, html.encode())
+    os.write(f, html.encode('utf-8'))
     os.close(f)
     webbrowser.open_new('file://' + path)
 
@@ -80,7 +78,6 @@ for m in message():
   if not position:
     print("Désolé, l'adresse n'est pas reconnue :-(")
   else:
-    #open_pos(position)
     markers = []
 
     for source in main.gen_sources(sourceProviders, location):
@@ -89,9 +86,9 @@ for m in message():
         else:
             print("Pas de problème : ", end='')
         notification.notify(source.message)
-        markers.append((source.pos, source.id))
+        markers.append((source.pos, source.name))
 
-    open_markers(position, markers)
+    open_markers(position, location, markers)
 
   # empty line
   print()

+ 26 - 16
source.py

@@ -26,9 +26,10 @@ class SourceProvider:
 ############## RATP ##############
 
 class Source_ratp(Source):
-  def __init__(self, ident, pos, status, message):
+  def __init__(self, ident, name, pos, status, message):
     self.source = 'ratp_trafic'
     self.id = ident
+    self.name = name
     self.pos = pos
     self.status = status
     self.message = message
@@ -68,16 +69,17 @@ class SourceProvider_ratp(SourceProvider):
   def sources_of_ids(self, ids_pos):
     for tag in XML(url="http://www.ratp.fr/meteo/", lang="html").data.select('div.encadre_ligne'):
       if tag['id'] in ids_pos:
-        yield Source_ratp(tag['id'], ids_pos[tag['id']], tag.img['alt'],\
+        yield Source_ratp(tag['id'], self.dic_of_names()[tag['id']], ids_pos[tag['id']], tag.img['alt'],\
           tag['id'].replace('_', ' ') + ' : ' + tag.select('span.perturb_message')[0].string)
 
 
 ############## JCDECAUX_VLS ##############
 
 class Source_jcdecaux_vls(Source):
-  def __init__(self, ident, pos, nom, timestamp, status):
+  def __init__(self, ident, name, pos, nom, timestamp, status):
     self.source = 'jcdecaux_vls'
     self.id = ident
+    self.name = name
     self.pos = pos
     self.status = status # TODO dans l'API pour 1 station il semble que c'est toujours OPEN :-(
     self.date = datetime.datetime.fromtimestamp(int(timestamp)/1000).strftime('à %Hh%M le %d/%m')
@@ -90,8 +92,8 @@ class Source_jcdecaux_vls(Source):
     return self.status != "OPEN"
 
 class Source_jcdecaux_vls_full(Source_jcdecaux_vls):
-  def __init__(self, ident, pos, nom, timestamp, places, status):
-    super(Source_jcdecaux_vls_full, self).__init__(ident, pos, nom, timestamp, status)
+  def __init__(self, ident, name, pos, nom, timestamp, places, status):
+    super(Source_jcdecaux_vls_full, self).__init__(ident, name, pos, nom, timestamp, status)
     self.id += "_full"
     self.places = int(places)
     if not self.message:
@@ -108,8 +110,8 @@ class Source_jcdecaux_vls_full(Source_jcdecaux_vls):
 
 
 class Source_jcdecaux_vls_empty(Source_jcdecaux_vls):
-  def __init__(self, ident, pos, nom, timestamp, bikes, status):
-    super(Source_jcdecaux_vls_empty, self).__init__(ident, pos, nom, timestamp, status)
+  def __init__(self, ident, name, pos, nom, timestamp, bikes, status):
+    super(Source_jcdecaux_vls_empty, self).__init__(ident, name, pos, nom, timestamp, status)
     self.id += "_empty"
     self.bikes = int(bikes)
     if not self.message:
@@ -128,17 +130,25 @@ class Source_jcdecaux_vls_empty(Source_jcdecaux_vls):
 class SourceProvider_jcdecaux_vls(SourceProvider):
   def __init__(self):
     self.names = {}
+    self.contracts = set() # known contracts
     self.positions = None
+    self.xml_all = None
+
+  def get_xml_all(self):
+    if not self.xml_all:
+      print('Téléchargement de la liste des stations...')
+      self.xml_all = XML(url='https://api.jcdecaux.com/vls/v1/stations?apiKey=' + config.api_key['jcdecaux_vls'], lang='json')
+    return self.xml_all
 
   def dic_of_names(self, contract=None):
     contract = contract or 'all'
-    if contract not in self.names:
+    if contract not in self.contracts:
+      self.contracts.add(contract)
       print('Téléchargement de la liste des stations pour le contrat ' + contract + '...')
       if contract != 'all':
         xml = XML(url='https://api.jcdecaux.com/vls/v1/stations?contract=' + contract + '&apiKey=' + config.api_key['jcdecaux_vls'], lang='json')
       else:
-        xml = XML(url='https://api.jcdecaux.com/vls/v1/stations?apiKey=' + config.api_key['jcdecaux_vls'], lang='json')
-      self.names = {}
+        xml = self.get_xml_all()
       for sta in xml.data.json.find_all("item", recursive=False):
         self.names[sta.contract_name.string.lower() + '_' + sta.number.string] =\
           sta.find('name').string + ' (' + sta.address.get_text() + ')'
@@ -147,8 +157,7 @@ class SourceProvider_jcdecaux_vls(SourceProvider):
 
   def dic_of_positions(self):
     if not self.positions:
-      print('Téléchargement de la liste des stations...')
-      xml = XML(url='https://api.jcdecaux.com/vls/v1/stations?apiKey=' + config.api_key['jcdecaux_vls'], lang='json')
+      xml = self.get_xml_all()
       self.positions = {}
       for sta in xml.data.json.find_all("item", recursive=False):
         self.positions[sta.contract_name.string.lower() + '_' + sta.number.string + '_' + 'full'] =\
@@ -164,18 +173,19 @@ class SourceProvider_jcdecaux_vls(SourceProvider):
       tag = xml.data.json
       id = contract + '_' + number + '_full'
       if id in ids_pos:
-        yield Source_jcdecaux_vls_full(contract + '_' + number, ids_pos[id], tag.find('name').string, tag.last_update.string, tag.available_bike_stands.string, tag.status.string)
+        yield Source_jcdecaux_vls_full(contract + '_' + number, self.dic_of_names()[contract + '_' + number], ids_pos[id], tag.find('name').string, tag.last_update.string, tag.available_bike_stands.string, tag.status.string)
       id = contract + '_' + number + '_empty'
       if id in ids_pos:
-        yield Source_jcdecaux_vls_empty(contract + '_' + number, ids_pos[id], tag.find('name').string, tag.last_update.string, tag.available_bikes.string, tag.status.string)
+        yield Source_jcdecaux_vls_empty(contract + '_' + number, self.dic_of_names()[contract + '_' + number], ids_pos[id], tag.find('name').string, tag.last_update.string, tag.available_bikes.string, tag.status.string)
 
 
 ############## TRANSILIEN ##############
 
 class Source_transilien(Source):
-  def __init__(self, ident, pos, message):
+  def __init__(self, ident, name, pos, message):
     self.source = 'transilien'
     self.id = ident
+    self.name = name
     self.pos = pos
     self.message = message
 
@@ -217,4 +227,4 @@ class SourceProvider_transilien(SourceProvider):
         for det in line.select('.item-disruption'):
           message += det.get_text()
         message = " ".join(message.split()) # delete multiple spaces
-        yield Source_transilien(id, ids_pos[id], message)
+        yield Source_transilien(id, self.dic_of_names()[id], ids_pos[id], message)