From abda8def8f992a47c1a2c090401497a29cf1523a Mon Sep 17 00:00:00 2001 From: Filip Znachor Date: Wed, 7 Dec 2022 15:45:29 +0100 Subject: [PATCH] Improved Lora classes & addded threaded sending --- server/departures.py | 6 +-- server/lora.py | 115 ++++++++++++++++++++++++------------------- server/main.py | 6 +-- 3 files changed, 70 insertions(+), 57 deletions(-) diff --git a/server/departures.py b/server/departures.py index 1b4f92d..6ff29f3 100644 --- a/server/departures.py +++ b/server/departures.py @@ -5,7 +5,7 @@ import json import requests from dateutil import parser from datetime import datetime -from lora import DeviceController +from lora import lora_controller from math import floor @@ -83,11 +83,11 @@ class Departure: self.departure = departure self.type = type self.update(delay) - DeviceController.data(self) + lora_controller.data(self) def update(self, delay): self.delay = delay - DeviceController.data(self) + lora_controller.data(self) def get_departure(self): departure = -round(((datetime.now().timestamp() - (self.departure + self.delay*60))/60)*10) diff --git a/server/lora.py b/server/lora.py index 066b9a4..388518a 100644 --- a/server/lora.py +++ b/server/lora.py @@ -2,6 +2,7 @@ import requests from requests.structures import CaseInsensitiveDict import config import json +import threading from time import sleep from base64 import b64encode from datetime import datetime @@ -9,10 +10,15 @@ from datetime import datetime import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) -class LoraDevice: +class LoraController: - @staticmethod - def generate_token(): + def __init__(self): + self.storage = dict() + self.devices = [] + self.message_pool = [] + self.thread = None + + def generate_token(self): url = f"https://lora.plzen.eu/api/v2/login" @@ -26,58 +32,65 @@ class LoraDevice: data = requests.post(url, verify=False, headers=headers, data=json.dumps(data)).json() config.lora_api_token = data["token"] + + def new(self, id): + self.devices.append(LoraDevice(self, id)) + + def time(self): + for d in self.devices: + d.send(f"TIME|{(datetime.now() - datetime(1970, 1, 1)).total_seconds():.0f}") + + def data(self, data): + sent = True + if data.id in self.storage: + d = self.storage[data.id] + if data.line != d["line"] or data.last_stop != d["last_stop"] or data.delay != d["delay"]: + sent = False + else: + sent = False + self.storage[data.id] = { 'line': data.line, 'last_stop': data.last_stop, 'delay': data.delay } + if sent: + return + string = f"{data.id}|{data.type}|{data.line}|{data.last_stop}|{data.get_departure()}" + for d in self.devices: + d.send(f"{string}") + + def send(self, id, port, msg): + self.message_pool.append((id, port, msg)) + if not self.thread or not self.thread.is_alive(): + self.thread = threading.Thread(target=self.thread_sending) + self.thread.start() + + def thread_sending(self): + while True: + if not len(self.message_pool): + break + data = self.message_pool.pop() + url = f"https://lora.plzen.eu/api/v2/nodes/{data[0]:0>16x}/queue" + print(f"Sending {data[2]}") + headers = CaseInsensitiveDict() + headers["Content-Type"] = "application/json" + headers["Authorization"] = f"Bearer {config.lora_api_token}" + payload = { + "confirmed": True, + "data": b64encode(data[2].encode("utf-8")).decode("ascii"), + "fPort": data[1], + "reference": "string" + } + requests.post(url, verify=False, headers=headers, data=json.dumps(payload)) + +class LoraDevice: - def __init__(self, deveui: int): + def __init__(self, controller: LoraController, deveui: int): + self.controller = controller self.id = deveui - self.port = 1 + self.port = 0 def send(self, msg: str): + self.controller.send(self.id, self.port+1, msg) + self.port = (self.port + 1) % 15 - url = f"https://lora.plzen.eu/api/v2/nodes/{self.id:0>16x}/queue" - print(f"Sending {msg}") +lora_controller = LoraController() - headers = CaseInsensitiveDict() - headers["Content-Type"] = "application/json" - headers["Authorization"] = f"Bearer {config.lora_api_token}" - - data = { - "confirmed": True, - "data": b64encode(msg.encode("utf-8")).decode("ascii"), - "fPort": self.port, - "reference": "string" - } - self.port = (self.port + 1) % 15 + 1; - - data = requests.post(url, verify=False, headers=headers, data=json.dumps(data)) - -dev = LoraDevice(0xbdea85badeedf1) - -class DeviceController: - - storage = dict() - - @staticmethod - def time(): - dev.send(f"TIME|{(datetime.now() - datetime(1970, 1, 1)).total_seconds():.0f}") - - @staticmethod - def data(data): - send = False - if data.id in DeviceController.storage: - d = DeviceController.storage[data.id] - if data.line != d["line"] or data.last_stop != d["last_stop"] or data.delay != d["delay"]: - send = True - else: - send = True - DeviceController.storage[data.id] = { - 'line': data.line, - 'last_stop': data.last_stop, - 'delay': data.delay - } - - if not send: - return - - string = f"{data.id}|{data.type}|{data.line}|{data.last_stop}|{data.get_departure()}" - dev.send(f"{string}") \ No newline at end of file +lora_controller.new(0xbdea85badeedf1) diff --git a/server/main.py b/server/main.py index f1a1d05..0df5666 100644 --- a/server/main.py +++ b/server/main.py @@ -1,15 +1,15 @@ from departures import Departure from time import sleep -from lora import LoraDevice, DeviceController +from lora import lora_controller refetch = 0 -LoraDevice.generate_token() +lora_controller.generate_token() while True: if refetch == 0: - DeviceController.time() + lora_controller.time() Departure.fetch("40", 10) refetch = (refetch + 1) % 10