velibdataset/velib.py

166 lines
6.2 KiB
Python
Raw Normal View History

2015-09-26 00:04:41 +02:00
#!/usr/bin/env python3
2017-08-28 18:03:36 +02:00
import datetime
2015-09-26 00:04:41 +02:00
import json
2017-08-28 18:03:36 +02:00
import os
2022-03-14 21:30:31 +01:00
import requests
2015-09-26 00:04:41 +02:00
import sqlite3
import time
2018-01-15 13:58:39 +01:00
def db_init(db_name=None):
2015-09-26 00:04:41 +02:00
"""
Initialize a database connection, initialize the tables.
Returns a new connection.
"""
2017-08-28 18:03:36 +02:00
now = datetime.datetime.now()
2018-01-15 13:58:39 +01:00
if db_name is None:
db_name = "week_%s.db" % now.strftime("%V")
2017-08-28 18:03:36 +02:00
db_folder = os.path.join(
'data',
now.strftime('%Y')
)
if not os.path.isdir(db_folder):
os.makedirs(db_folder)
conn = sqlite3.connect(os.path.join(db_folder, db_name))
2015-09-26 00:04:41 +02:00
c = conn.cursor()
2017-08-28 14:20:36 +02:00
# Init tables
2015-09-26 00:04:41 +02:00
c.execute("CREATE TABLE IF NOT EXISTS stations(" +
2018-01-15 13:58:39 +01:00
"id INTEGER, " +
2015-09-26 00:04:41 +02:00
"name TEXT, " +
"address TEXT, " +
"latitude REAL, " +
"longitude REAL, " +
"banking INTEGER, " +
"bonus INTEGER, " +
"bike_stands INTEGER)")
c.execute("CREATE TABLE IF NOT EXISTS stationsstats(" +
"station_id INTEGER, " +
"available_bikes INTEGER, " +
2018-01-15 13:58:39 +01:00
"available_ebikes INTEGER, " +
2015-09-26 00:04:41 +02:00
"free_stands INTEGER, " +
"status TEXT, " +
"updated INTEGER, " +
"FOREIGN KEY(station_id) REFERENCES stations(id) ON DELETE CASCADE)")
c.execute("CREATE TABLE IF NOT EXISTS stationsevents(" +
2015-11-12 23:23:41 +01:00
"station_id INTEGER, " +
2015-09-26 00:04:41 +02:00
"timestamp INTEGER, " +
"event TEXT, " +
"FOREIGN KEY(station_id) REFERENCES stations(id) ON DELETE CASCADE)")
c.execute("CREATE INDEX IF NOT EXISTS stationstats_station_id ON stationsstats (station_id)");
c.execute("CREATE INDEX IF NOT EXISTS stationsstats_updated ON stationsstats (updated)");
2016-01-21 11:55:12 +01:00
c.execute("CREATE INDEX IF NOT EXISTS stationsevents_station_id ON stationsevents (station_id)");
c.execute("CREATE INDEX IF NOT EXISTS stationsevents_timestamp ON stationsevents (timestamp)");
2015-09-26 00:04:41 +02:00
conn.commit()
return conn
2018-01-15 13:58:39 +01:00
def update_stations(conn):
2015-09-26 00:04:41 +02:00
"""
Update the stored station list.
2018-01-15 13:58:39 +01:00
:param conn: Database connection.
2015-09-26 00:04:41 +02:00
"""
c = conn.cursor()
database_stations = {i[0]: i
for i in
c.execute("SELECT id, name, address, latitude, longitude, banking, bonus, bike_stands FROM stations").fetchall()}
2018-01-15 13:58:39 +01:00
2022-03-14 21:30:31 +01:00
req_stations = requests.get('https://velib-metropole-opendata.smoove.pro/opendata/Velib_Metropole/station_information.json')
stations = {
station['stationCode']: station
for station in req_stations.json()['data']['stations']
}
req_status = requests.get('https://velib-metropole-opendata.smoove.pro/opendata/Velib_Metropole/station_status.json')
for station in req_status.json()['data']['stations']:
uid = station["stationCode"]
2015-09-26 00:04:41 +02:00
try:
# Get old station entry if it exists
2022-03-14 21:30:31 +01:00
old_station = database_stations[uid]
2015-09-26 00:04:41 +02:00
# Diff the two stations
event = []
2022-03-14 21:30:31 +01:00
if stations[uid]['name'] != old_station[1]:
2015-09-26 00:04:41 +02:00
event.append({"key": "name",
"old_value": old_station[1],
2022-03-14 21:30:31 +01:00
"new_value": stations[uid]['name']})
if stations[uid]['latitude'] != old_station[3]:
2015-09-26 00:04:41 +02:00
event.append({"key": "latitude",
"old_value": old_station[3],
2022-03-14 21:30:31 +01:00
"new_value": stations[uid]['lat']})
if stations[uid]['lon'] != old_station[4]:
2015-09-26 00:04:41 +02:00
event.append({"key": "longitude",
"old_value": old_station[4],
2022-03-14 21:30:31 +01:00
"new_value": station[uid]['lon']})
if station["numDocksAvailable"] != old_station[7]:
2015-09-26 00:04:41 +02:00
event.append({"key": "bike_stands",
"old_value": old_station[7],
2022-03-14 21:30:31 +01:00
"new_value": stations[uid]["capacity"]})
2015-09-26 00:04:41 +02:00
# If diff was found
if len(event) > 0:
# Update
c.execute("UPDATE " +
"stations " +
2018-01-15 13:58:39 +01:00
"SET name=?, latitude=?, longitude=?, " +
"banking=?, bike_stands=? WHERE id=?",
2022-03-14 21:30:31 +01:00
(stations[uid]['name'],
stations[uid]['lat'],
stations[uid]['lon'],
None,
stations[uid]['capacity'],
uid))
2015-09-26 00:04:41 +02:00
# And insert event in the table
c.execute("INSERT INTO " +
"stationsevents(station_id, timestamp, event) " +
"VALUES(?, ?, ?)",
2022-03-14 21:30:31 +01:00
(uid,
2017-08-31 14:40:33 +02:00
int(time.time()),
2015-09-26 00:04:41 +02:00
json.dumps(event)))
except KeyError:
c.execute("INSERT INTO " +
"stations(id, name, address, latitude, longitude, banking, bonus, bike_stands) " +
"VALUES(?, ?, ?, ?, ?, ?, ?, ?)",
2022-03-14 21:30:31 +01:00
(uid,
stations[uid]['name'],
2018-01-15 13:58:39 +01:00
"", # Not available
2022-03-14 21:30:31 +01:00
stations[uid]['lat'],
stations[uid]['lon'],
None, # Not available
2018-01-15 13:58:39 +01:00
False, # Not available
2022-03-14 21:30:31 +01:00
stations[uid]["capacity"]))
2016-01-21 11:55:12 +01:00
except TypeError:
2016-01-21 11:58:53 +01:00
conn.rollback()
return
2015-09-26 00:04:41 +02:00
2022-03-14 21:30:31 +01:00
numEBikesAvailable = (
station['numBikesAvailable']
- next(
x['ebike']
for x in station['num_bikes_available_types']
if 'ebike' in x
)
)
2015-09-26 00:04:41 +02:00
c.execute("INSERT INTO " +
2018-01-15 13:58:39 +01:00
"stationsstats(station_id, available_bikes, available_ebikes, free_stands, status, updated) " +
"VALUES(?, ?, ?, ?, ?, ?)",
2022-03-14 21:30:31 +01:00
(uid,
station['numBikesAvailable'],
numEBikesAvailable,
station['numDocksAvailable'],
None,
2018-01-15 13:58:39 +01:00
int(time.time()))) # Not available, using current timestamp
conn.commit()
2015-09-26 00:04:41 +02:00
def main():
"""
Handle main operations.
"""
2018-01-15 13:58:39 +01:00
# Get updated list of stations for smovengo
conn = db_init()
update_stations(conn)
2015-09-26 00:04:41 +02:00
if __name__ == "__main__":
main()