Added departure filter

This commit is contained in:
Filip Znachor 2022-12-20 19:29:51 +01:00
parent 3fce82e971
commit ee7bf407b2
7 changed files with 79 additions and 20 deletions

View file

@ -79,6 +79,15 @@ class API:
d.set_stop(request.forms.get('stop_id'))
return {'success': True}
@route('/admin/devices/change_filter', method='POST')
def admin_devices_change_filter():
if main.config["admin"]["secret"] != request.forms.get('secret'):
return {'error': "unauthorized"}
for i, d in enumerate(main.controller.devices):
if str(i) == request.forms.get('index'):
d.set_filter(request.forms.get('filter'))
return {'success': True}
@route('/admin/devices/toggle', method='POST')
def admin_devices_toggle():
if main.config["admin"]["secret"] != request.forms.get('secret'):

View file

@ -2,6 +2,38 @@ from math import floor
from datetime import datetime
from dateutil import parser
class Filter:
storage = dict()
@staticmethod
def get(name: str):
if name in Filter.storage:
return Filter.storage[name]
return None
def __init__(self, name: str, filters):
if "lines" not in filters:
filters["lines"] = None
if "types" not in filters:
filters["types"] = None
if "destinations" not in filters:
filters["destinations"] = None
self.name = name
self.lines = filters["lines"]
self.types = filters["types"]
self.destinations = filters["destinations"]
Filter.storage[name] = self
def filter(self, departures):
results = []
for d in departures:
if not self.types or d.type in self.types:
if not self.lines or d.line in self.lines:
if not self.destinations or d.last_stop in self.destinations:
results.append(d)
return results
class Departure:
id_pool = {}

View file

@ -7,7 +7,7 @@ from base64 import b64encode
from datetime import datetime
from random import randint, shuffle
from time import sleep
from departures import Departure
from departures import Departure, Filter
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
@ -34,22 +34,23 @@ class LoraController:
data = requests.post(url, verify=False, headers=headers, data=json.dumps(data)).json()
self.token = data["token"]
def new(self, id: int, stop_id: str, enabled: bool):
self.devices.append(LoraDevice(self, id, stop_id, enabled))
def new(self, id: int, stop_id: str, enabled: bool, filter: Filter):
self.devices.append(LoraDevice(self, id, stop_id, enabled, filter))
def json(self):
resp = []
for d in self.devices:
resp.append({'id': f"{d.id:0>16x}", 'stop_id': d.stop_id, 'enabled': d.enabled})
resp.append({'id': f"{d.id:0>16x}", 'stop_id': d.stop_id, 'enabled': d.enabled, 'filter': d.filter.name if d.filter else None})
return resp
class LoraDevice:
def __init__(self, controller: LoraController, deveui: int, stop_id: str, enabled: bool):
def __init__(self, controller: LoraController, deveui: int, stop_id: str, enabled: bool, filter: Filter):
self.controller = controller
self.id = deveui
self.stop_id = stop_id
self.enabled = enabled
self.filter = filter
self.message_pool = []
self.thread = None
self.port = 1
@ -59,11 +60,17 @@ class LoraDevice:
self.clear()
self.stop_id = stop_id
def set_filter(self, name: str):
self.filter = Filter.get(name)
def get_updated_departures(self):
if not self.enabled:
return
self.send_time()
for d in Departure.get(self.stop_id):
departures = Departure.get(self.stop_id)
if self.filter:
departures = self.filter.filter(departures)
for d in departures:
if self.id not in d.updated or d.updated[self.id] > 0:
self.send(d.data)

View file

@ -1,4 +1,4 @@
from departures import Departure
from departures import Departure, Filter
from requests.structures import CaseInsensitiveDict
import json
import requests
@ -24,11 +24,15 @@ class Main:
self.controller = lora_controller
self.api = API(self)
lora_controller.generate_token()
for name in self.config["filters"]:
Filter(name, self.config["filters"][name])
for d in self.config["devices"]:
if "stop_id" in d:
if "enabled" not in d:
d["enabled"] = True
lora_controller.new(d["id"], str(d["stop_id"]), d["enabled"])
if "filter" not in d:
d["filter"] = None
lora_controller.new(d["id"], str(d["stop_id"]), d["enabled"], Filter.get(d["filter"]))
self.thread = threading.Thread(target=self.update_loop)
self.thread.start()

View file

@ -3,11 +3,13 @@
.cards .header {padding: 15px; display: grid; grid-template-columns: 1fr max-content; user-select: none;}
.cards .first {font-weight: 700;}
.cards .settings {padding: 15px; border-top: 1px solid var(--border-color2); background: var(--alt-bg2); display: none;}
.cards .settings.visible {display: block;}
.cards .settings {padding: 15px; border-top: 1px solid var(--border-color2); background: var(--alt-bg2); display: none; flex-direction: column; gap: 13px;}
.cards .settings.visible {display: flex;}
.cards .actions {display: flex; gap: 10px; flex-wrap: wrap; align-items: center;}
.cards .actions::before {content: "Akce:"; font-weight: 500; font-size: 90%; opacity: .5; text-transform: uppercase;}
.cards .actions::before, .cards .filter::before {content: "Akce:"; font-weight: 500; font-size: 90%; opacity: .5; text-transform: uppercase;}
.cards .filter::before {content: "Aktivní filtr:"; margin-right: 10px;}
@media screen and (max-width: 500px) {
.cards .actions::before {display: none;}
}

View file

@ -18,12 +18,14 @@
<div class="second">{{ stops[d.stop_id] ? stops[d.stop_id].name : "Nenastaveno" }}</div>
</div>
<div class="settings" :class="{ visible: d.visible }">
<div class="filter">{{ d.filter ? d.filter : "žádný" }}</div>
<div class="actions">
<button @click="device_clear(i)">Vymazat</button>
<button @click="device_resend(i)" v-if="d.enabled">Přeposlat</button>
<button @click="device_change_stop(i)">Změnit zastávku</button>
<button @click="device_toggle(i, false)" v-if="d.enabled">Deaktivovat</button>
<button @click="device_toggle(i, true)" v-else>Aktivovat</button>
<button @click="device_resend(i)" v-if="d.enabled">Přeposlat</button>
<button @click="device_change_stop(i)">Zastávka</button>
<button @click="device_change_filter(i)">Filtr</button>
</div>
</div>
</div>

View file

@ -3,10 +3,8 @@ const { createApp } = Vue;
let app = createApp({
data() {
return {
// logged: false,
// secret: "",
logged: true,
secret: "TajneHeslo",
logged: false,
secret: "",
stops: {},
devices: []
}
@ -14,11 +12,11 @@ let app = createApp({
methods: {
async update() {
let devices = await api("/admin/devices", {secret: this.secret});
let stops = await api("/stops");
if(devices.error) {
alert("Neplatné heslo!");
return;
}
let stops = await api("/stops");
this.devices = devices.devices;
this.stops = stops.stops;
this.logged = true;
@ -38,6 +36,12 @@ let app = createApp({
if(!stop_id || stop_id.trim() == "") return;
this.devices[index].stop_id = stop_id;
await api("/admin/devices/change_stop", {index, stop_id, secret: this.secret});
},
async device_change_filter(index) {
let filter = prompt("Zadejte jméno filtru:");
if(!filter || filter.trim() == "") return;
this.devices[index].filter = filter;
await api("/admin/devices/change_filter", {index, filter, secret: this.secret});
}
}
}).mount('#app');
@ -63,5 +67,4 @@ async function api(url, data) {
}
xhr.send(str.join("&"));
});
}
app.update();
}