From 6214b6cdf17cd5c47950056ef8f011ab6e91b9cd Mon Sep 17 00:00:00 2001 From: Filip Znachor Date: Thu, 8 Dec 2022 22:17:26 +0100 Subject: [PATCH] Improved backend & multi stop support --- server/api.py | 11 +++-------- server/departures.py | 28 ++++++++++++++++++---------- server/lora.py | 22 +++++++++++----------- server/main.py | 14 ++++++++------ server/static/index.html | 6 +++--- 5 files changed, 43 insertions(+), 38 deletions(-) diff --git a/server/api.py b/server/api.py index d0bd630..1d35cae 100644 --- a/server/api.py +++ b/server/api.py @@ -1,5 +1,4 @@ import threading -from operator import itemgetter from wsgiref.simple_server import make_server, WSGIRequestHandler from departures import Departure from bottle import route, error, run, get, ServerAdapter, static_file @@ -17,13 +16,9 @@ class Server(ServerAdapter): def stop(self): self.server.shutdown() -@route('/departures') -def index(): - resp = [] - for d in Departure.storage: - resp.append(Departure.storage[d].json()) - resp.sort(key=itemgetter("departure")) - return {'departures': resp} +@route('/departures/') +def index(stop_id: int): + return {'departures': Departure.get(stop_id)} @get("/") def static(): diff --git a/server/departures.py b/server/departures.py index 37f4a66..41ec1db 100644 --- a/server/departures.py +++ b/server/departures.py @@ -1,4 +1,5 @@ from math import floor +from operator import itemgetter from datetime import datetime from dateutil import parser @@ -7,6 +8,16 @@ class Departure: id_pool = [] storage = dict() + @staticmethod + def get(stop_id: str): + resp = [] + for id in Departure.storage: + d = Departure.storage[id] + if d.stop_id == int(stop_id): + resp.append(d.json()) + resp.sort(key=itemgetter("departure")) + return resp + @staticmethod def get_id(): i = 0 @@ -21,20 +32,20 @@ class Departure: remove = [] for did in Departure.storage: d = Departure.storage[did] - if d.get_departure() < -35: + if d.get_departure() < -3.5: Departure.id_pool.remove(d.id) remove.append(did) for did in remove: Departure.storage.pop(did) - def __init__(self, did, type, line, last_stop, departure, delay, lora_controller): + def __init__(self, did, stop_id, type, line, last_stop, departure, delay, lora_controller): departure = (parser.parse(departure)).timestamp() if -(datetime.now().timestamp() - (departure + delay*60))/60 <= -1: return - Departure.storage[did] = self if len(last_stop) >= 21: last_stop = last_stop[:20].strip() + "..." self.did = did + self.stop_id = stop_id self.id = Departure.get_id() self.line = line self.type = type @@ -43,6 +54,7 @@ class Departure: self.delay = delay self.controller = lora_controller self.controller.data(self) + Departure.storage[did] = self def update(self, delay): if delay != self.delay: @@ -50,14 +62,10 @@ class Departure: self.delay = delay def get_departure(self): - departure = floor(self.get_accurate_departure()*10) - return departure - - def get_accurate_departure(self): - return -((datetime.now().timestamp() - (self.departure + self.delay*60))/60) + return -(floor(((datetime.now().timestamp() - (self.departure + self.delay*60))/60)*10)/10) def __repr__(self): - return f"{self.id}|{self.type}|{self.line}|{self.last_stop}|{self.get_departure()}" + return f"{self.id}|{self.type}|{self.line}|{self.last_stop}|{(self.get_departure()*10):.0f}" def json(self): return { @@ -65,6 +73,6 @@ class Departure: 'line': self.line, 'type': self.type, 'last_stop': self.last_stop, - 'departure': floor(self.get_accurate_departure()), + 'departure': self.get_departure(), 'delay': self.delay } \ No newline at end of file diff --git a/server/lora.py b/server/lora.py index df9b7a7..69c2d94 100644 --- a/server/lora.py +++ b/server/lora.py @@ -35,8 +35,8 @@ class LoraController: data = requests.post(url, verify=False, headers=headers, data=json.dumps(data)).json() self.token = data["token"] - def new(self, id): - self.devices.append(LoraDevice(self, id)) + def new(self, id: int, stop_id: int): + self.devices.append(LoraDevice(self, id, stop_id)) def time(self): def to_string(): @@ -46,10 +46,11 @@ class LoraController: def data(self, data): for d in self.devices: - d.send(data.__repr__) + if d.stop_id == data.stop_id: + d.send(data.__repr__) - def send(self, id, port, msg): - self.message_pool.append((id, port, msg)) + def send(self, id, msg): + self.message_pool.append((id, msg)) if not self.thread or not self.thread.is_alive(): self.thread = threading.Thread(target=self.thread_sending) self.thread.start() @@ -60,14 +61,14 @@ class LoraController: break data = self.message_pool.pop(0) url = f"https://lora.plzen.eu/api/v2/nodes/{data[0]:0>16x}/queue" - string = data[2]() + string = data[1]() headers = CaseInsensitiveDict() headers["Content-Type"] = "application/json" headers["Authorization"] = f"Bearer {self.token}" payload = { "confirmed": True, "data": b64encode(string.encode("utf-8")).decode("ascii"), - "fPort": data[1], + "fPort": 10, "reference": "string" } requests.post(url, verify=False, headers=headers, data=json.dumps(payload)) @@ -75,11 +76,10 @@ class LoraController: class LoraDevice: - def __init__(self, controller: LoraController, deveui: int): + def __init__(self, controller: LoraController, deveui: int, stop_id: int): self.controller = controller self.id = deveui - self.port = 0 + self.stop_id = stop_id def send(self, msg): - self.controller.send(self.id, self.port+1, msg) - self.port = (self.port + 1) % 15 \ No newline at end of file + self.controller.send(self.id, msg) \ No newline at end of file diff --git a/server/main.py b/server/main.py index f20a608..b6a2b53 100644 --- a/server/main.py +++ b/server/main.py @@ -12,7 +12,7 @@ import sys class Main: - def __init__(self, stop_id): + def __init__(self): config = Path("config.yml") try: self.config = yaml.safe_load(config.read_text(encoding="utf-8-sig")) @@ -20,9 +20,9 @@ class Main: print("Invalid config file!") sys.exit(-1) self.ended = False - self.stop_id = stop_id lora_controller = LoraController(self) - lora_controller.new(0xbdea85badeedf1) + for d in self.config["devices"]: + lora_controller.new(d["id"], d["stop_id"]) self.controller = lora_controller self.thread = threading.Thread(target=self.update_loop) self.thread.start() @@ -44,13 +44,14 @@ class Main: "FullResults": False } - resp = requests.post(url, headers=headers, data=json.dumps(data), timeout=100).json() + resp = requests.post(url, headers=headers, data=json.dumps(data), timeout=1000).json() for c in resp: did = f"{stop_id}|{abs(c['ConnectionId']['ConnectionId'])}" if did not in Departure.storage: Departure( did, + stop_id, c["Line"]["TractionType"], c["Line"]["Name"], c["LastStopName"], @@ -76,7 +77,8 @@ class Main: if refetch == 0: self.controller.time() - self.fetch(self.stop_id, 20) + for s in self.config["stops"]: + self.fetch(s["id"], 15) refetch = (refetch + 1) % 3 regenerate = (regenerate + 1) % (6*30) @@ -119,5 +121,5 @@ class Main: except KeyboardInterrupt: self.stop() -main = Main("40") +main = Main() main.input_loop() \ No newline at end of file diff --git a/server/static/index.html b/server/static/index.html index 5bd770a..15927ee 100644 --- a/server/static/index.html +++ b/server/static/index.html @@ -47,11 +47,11 @@
zpoždění
odjezd