From a352264efe1dee49676ebfe46fa7a641a5c11f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Kaarevik?= Date: Sun, 1 Dec 2024 01:55:29 +0100 Subject: [PATCH] =?UTF-8?q?Crystal=20Orb=20MVP,=20omtrent.=20Programmet=20?= =?UTF-8?q?henter=20avgangstider=20og=20kan=20skrive=20dem=20til=20en=20kj?= =?UTF-8?q?=C3=B8rende=20mpv-instans?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 78 ++++++++++++++++++++++++++++++++++++++++++++++++-- crystal_orb.py | 63 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 crystal_orb.py diff --git a/README.md b/README.md index 1d2b9e5..845453b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,77 @@ # crystal-orb -> Ta en titt inn i krystallkulen og se om det går en buss i dag. - -AtB-infoskjerm til å visepå TV-skjermen på terminalrommet. \ No newline at end of file +> Ta en titt inn i krystallkulen og se om det går en buss i dag. + +AtB-infoskjerm til å visepå TV-skjermen på terminalrommet. + +## Få tak i avgangstider + +Det ser ut til at API-et [mpolden](https://github.com/mpolden/atb) har laget er tilstrekkelig +for å få tak i alle busser og avgangstider for et gitt stoppested (stopPlace). +API-et hans er en wrapper for Entur sitt API som er litt tyngre skyts en det hackere har behov for, +derav hvorfor han lagde et (tror jeg). + +### Informasjon fra mpolden sitt API + +Dersom man gir https://mpolden.no/atb/v2/departures/ en høvelig kode for stoppested, gir den tilbake +disse feltene: + +- `line` + - Dette er linje-nummeret til bussen +- `scheduledDepartureTime` + - Dette er den forventede avgangstiden til bussen, basert på Entur sitt felt `expectedDepartureTime` + - I tilleg finnes `aimedDepartureTime` og `actualDepartureTime` hos Entur, + som er hva bussen er satt opp til etter planen og når bussen faktisk dro. + - Av disse er naturligvis `expectedDepartureTime` det viktigste feltet for oss +- `destination` + - Hvor bussen skal til slutt, det er dette som står foran på bussen + - Basert på `destinationDisplay.frontText` hos Entur +- `isRealTimeData` + - Hvorvidt tidspunktet er oppdatert/basert på sanntidsdata + - Gir en indikasjon på hvor stabil informasjonen er + - Hvis det er sanntid skal man ta det med en klype salt + - Hvis det ikke er sanntid er det ikke vits å finne frem saltbøssen engang +- `isGoingTowardsCentrum` + - Basert på `journeyPattern.directionType` hos Entur + - Busser går stort sett enten inn mot Midtbyen eller ut, + dette er kjekt å vite ettersom man ofte vet hvilken retning man skal herfra + +### Koder for stoppested + +Man kan finne stoppestedskoden på url https://stoppested.entur.org/ . +De mest relevante kodene for oss på PVV er: + +- Gløshaugen: 44085 +- Høgskoleringen: 42029 +- Hesthagen: 41620 + +## Funksjonalitet + +Vi har på dette tidspunktet ingen anelse hvilken funksjonalitet dette programmet skal ha, +men noen ideer har vi allerede. + +- Mulighet for å vise de kommende avgangstidene på Georg/Grzegorz + - Mer generelt gjennom `mpv` på en eller annen måte + - Gjerne med kule farger eller et nice layout +- Hadde kanskje vært kult med et cli hvor man kjapt kan sjekke de neste bussene som drar + - Kule farger er også nice her +- En nettside eller en annen visualiseringsmetode + - Nettopp for å kunne støtte et brukervennlig layout av informasjonen + +## Hvordan kjøre programmet slik det er + +Akkurat nå funker `crystal_orb.py` omtrent slik: + +- Man kjører programmet med `python crystal_orb.py ` + - Stoppested kan være gløshaugen, høgskoleringen eller hesthagen +- `crystal orb` får avgangsinformasjon fra `mpolden` sitt API +- `crystal orb` lager en liste av all avgangsinformasjonen den fikk +- `crystal orb` skriver teksten på en kjørende mpv-sesjon + - Merk at `mpv` må ha satt opp en ipc socket som `crystal orb` skriver til + - Hvis denne socket-en ikke finnes, skrives listen til stdout + +## Forbedringer + +- Legge til `aimedDepartureTime` slik at vi kan se hva avviket er + - Av og til kjører bussen inn igjen etterslepet, dermed kan det være nyttig +- diff --git a/crystal_orb.py b/crystal_orb.py new file mode 100644 index 0000000..b4325e2 --- /dev/null +++ b/crystal_orb.py @@ -0,0 +1,63 @@ +import json +import requests +import sys +import os +import subprocess + +# See github project: https://github.com/mpolden/atb +ATB_API_URL = "https://mpolden.no/atb/v2/departures/" +# Stop place codes found through https://stoppested.entur.org/ +STOP_PLACES = { + "gløshaugen": "44085", + "høgskoleringen": "42029", + "hesthagen": "41620" +} + +def format_departure(departure_dict: dict) -> str: + """Formats the json supplied by mpolden's atb api to a single line of text + quickly summarizing the scheduled bus. + """ + line = departure_dict["line"] + departure_time = departure_dict["scheduledDepartureTime"].split("T")[1].split(".")[0] + destination = departure_dict["destination"] + is_real_time = departure_dict["isRealtimeData"] + towards_city_center = departure_dict["isGoingTowardsCentrum"] + + # return f"{departure_time}: {line}\t({'R' if is_real_time else 'S'}, {'I' if towards_city_center else 'O'}) {destination}" + return f"{departure_time}: {line}\t{destination}\t ({'realtime' if is_real_time else 'aimed'},\t{'til Midtbyen' if towards_city_center else 'fra Midtbyen'})" + + +def write_to_socket(s: str, mpv_socket) -> None: + """Writes the string s to the mpv on screen display through + the open mpv ipc socket located at the path `mpv_socket`. + """ + cmd_dict = {"command": ["show-text", f"{s}", 10000]} + mpv_cmd = json.dumps(cmd_dict) + cmd = f'echo \'{mpv_cmd}\' | socat - ./{mpv_socket}' + subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + return None + + +if __name__ == "__main__": + input_stop_place = sys.argv[1] + if input_stop_place in STOP_PLACES.keys(): + active_stop_place = STOP_PLACES[input_stop_place] + else: + active_stop_place = STOP_PLACES["gløshaugen"] + + r = requests.get(ATB_API_URL + active_stop_place) + departures = r.json()["departures"] + sorted_departures = sorted(departures, key = lambda d: d["scheduledDepartureTime"]) + + # ensure mpv is running with the ipc-server socket set in MPV_SOCKET + MPV_SOCKET = "mpv_ipc.socket" + if os.path.exists(MPV_SOCKET): + write_to_socket( + f"{'\n'.join([ + format_departure(sorted_departures[i]) + for i in range(len(sorted_departures)) + ])}", MPV_SOCKET) + else: + for dep in sorted_departures: + print(format_departure(dep)) +