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
|
2018-01-15 13:58:39 +01:00
|
|
|
import pybikes
|
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)")
|
2017-08-26 12:26:40 +02:00
|
|
|
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)");
|
2017-08-26 12:26:40 +02:00
|
|
|
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
|
|
|
|
|
|
|
velib = pybikes.get("velib")
|
|
|
|
velib.update()
|
|
|
|
for station in velib.stations:
|
2015-09-26 00:04:41 +02:00
|
|
|
try:
|
|
|
|
# Get old station entry if it exists
|
2018-01-15 13:58:39 +01:00
|
|
|
old_station = database_stations[station.extra["uid"]]
|
2015-09-26 00:04:41 +02:00
|
|
|
# Diff the two stations
|
|
|
|
event = []
|
2018-01-15 13:58:39 +01:00
|
|
|
if station.name != old_station[1]:
|
2015-09-26 00:04:41 +02:00
|
|
|
event.append({"key": "name",
|
|
|
|
"old_value": old_station[1],
|
2018-01-15 13:58:39 +01:00
|
|
|
"new_value": station.name})
|
|
|
|
if station.latitude != old_station[3]:
|
2015-09-26 00:04:41 +02:00
|
|
|
event.append({"key": "latitude",
|
|
|
|
"old_value": old_station[3],
|
2018-01-15 13:58:39 +01:00
|
|
|
"new_value": station.latitude})
|
|
|
|
if station.longitude != old_station[4]:
|
2015-09-26 00:04:41 +02:00
|
|
|
event.append({"key": "longitude",
|
|
|
|
"old_value": old_station[4],
|
2018-01-15 13:58:39 +01:00
|
|
|
"new_value": station.longitude})
|
|
|
|
if station.extra["banking"] != old_station[5]:
|
2015-09-26 00:04:41 +02:00
|
|
|
event.append({"key": "banking",
|
|
|
|
"old_value": old_station[5],
|
2018-01-15 13:58:39 +01:00
|
|
|
"new_value": station.extra["banking"]})
|
|
|
|
if station.extra["slots"] != old_station[7]:
|
2015-09-26 00:04:41 +02:00
|
|
|
event.append({"key": "bike_stands",
|
|
|
|
"old_value": old_station[7],
|
2018-01-15 13:58:39 +01:00
|
|
|
"new_value": station.extra["slots"]})
|
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=?",
|
|
|
|
(station.name,
|
|
|
|
station.latitude,
|
|
|
|
station.longitude,
|
|
|
|
station.extra["banking"],
|
|
|
|
station.extra["slots"],
|
|
|
|
station.extra["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(?, ?, ?)",
|
2018-01-15 13:58:39 +01:00
|
|
|
(station.extra["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(?, ?, ?, ?, ?, ?, ?, ?)",
|
2018-01-15 13:58:39 +01:00
|
|
|
(station.extra["uid"],
|
|
|
|
station.name,
|
|
|
|
"", # Not available
|
|
|
|
station.latitude,
|
|
|
|
station.longitude,
|
|
|
|
station.extra["banking"],
|
|
|
|
False, # Not available
|
|
|
|
station.extra["slots"]))
|
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
|
|
|
|
|
|
|
c.execute("INSERT INTO " +
|
2018-01-15 13:58:39 +01:00
|
|
|
"stationsstats(station_id, available_bikes, available_ebikes, free_stands, status, updated) " +
|
|
|
|
"VALUES(?, ?, ?, ?, ?, ?)",
|
|
|
|
(station.extra["uid"],
|
|
|
|
station.bikes - station.extra["ebikes"],
|
|
|
|
station.extra["ebikes"],
|
|
|
|
station.free,
|
|
|
|
station.extra["status"],
|
|
|
|
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()
|