Stockholms Lokaltrafik - Command Line Interface
Trött på grafiska gränssnitt? Är du en sann terminal-junkie? Har du en fetisch för att sitta framför terminalfönster med grön text på svart bakgrund i oldschool UNIX-anda? Drömmer du om en chans att imponera på dina anhöriga med dina l33t hax0r skills? Vill du att jag ska sluta ställa dessa frågor och komma till saken?
Med SL-CLI får du reseinformation direkt i kommandotolken utan att ens behöva ha igång en fönsterhanterare. Programmet är tänkt att fungera som ett alternativ till att få reseinformation via webbplatsen http://sl.se eller appen STHLM Traveling.
Build | Status |
---|---|
Linux | |
Windows | |
Landscape | |
Codacy | |
Coveralls |
-
# pip install sl-cli
eller# python setup.py install
-
Skapa en fil sensitive.xml som du fyller med följande innehåll:
<?xml version='1.0' encoding='utf-8'?> <root> <key name="platsuppslag" >1234567890abcdefghijklmnopqrstuv</key> <key name="reseplanerare3.1">1234567890abcdefghijklmnopqrstuv</key> </root>
där du byter ut de fejkade API-nycklarna mot riktiga nycklar. Har du inga nycklar kan du skaffa dem på trafiklab.se. Du behöver nycklar för API:erna Platsuppslag och Reseplanerare 3.1.
-
Kör programmet och installera din sensitive.xml:
$ sl-cli
Dina API-nycklar är inte installerade.
Ange sökvägen till dina nycklar [./sensitive.xml]:
>
Kopiera ./sensitive.xml till /home/sebelino/.config/sl-cli/sensitive.xml? (y/n) [n]:
> y
Skapar kataloger...
Kopierar ./sensitive.xml -> /home/sebelino/.config/sl-cli/sensitive.xml
usage: sl-cli [-h] [--verbose] from to [at]
sl-cli.py: error: the following arguments are required: from, to
$ make venv
$ source venv/bin/activate
...
Med executablen sl-cli får du reseinformation direkt i terminalen. Se manualen:
$ sl-cli -h
usage: sl-cli [-h] [--verbose] from to [at]
positional arguments:
from Varifrån ska du resa?
to Vart ska du?
at När ska du bege dig?
optional arguments:
-h, --help show this help message and exit
--verbose, -v Skriv ut debuggutskrifter
Exempel på användning:
$ sl-cli vårsta teknisk 8:00
08:06 2016-05-31 Vårsta centrum (Botkyrka) - Tekniska högskolan (Stockholm):
08:06....Vårsta centrum
08:07........Malmtorp
08:08........Bergudden
08:11........Kassmyra
08:13........Skrävstavägen
08:13........Solbo
08:18....Tumba station
08:26....Tumba
08:30........Tullinge
08:33........Flemingsberg
08:36........Huddinge
08:39........Stuvsta
08:42........Älvsjö
08:45........Årstaberg
08:48........Stockholms södra
08:52....Stockholms central
08:59....T-Centralen
09:02........Östermalmstorg
09:03........Stadion
09:05....Tekniska högskolan
>>> from slcli.slcli import travel
>>> travel('vårsta','teknisk','8:00')
{'origin': 'Vårsta centrum (Botkyrka)', 'trip': [{'origin': 'Vårsta centrum', 'arrivalTime': '08:18', 'departureTime': '08:06', 'destination': 'Tumba station', 'trip': [{'arrivalTime': '08:07', 'stop': 'Malmtorp'}, {'arrivalTime': '08:08', 'stop': 'Bergudden'}, {'arrivalTime': '08:11', 'stop': 'Kassmyra'}, {'arrivalTime': '08:13', 'stop': 'Skrävstavägen'}, {'arrivalTime': '08:13', 'stop': 'Solbo'}]}, {'origin': 'Tumba', 'arrivalTime': '08:52', 'departureTime': '08:26', 'destination': 'Stockholms central', 'trip': [{'arrivalTime': '08:30', 'stop': 'Tullinge'}, {'arrivalTime': '08:33', 'stop': 'Flemingsberg'}, {'arrivalTime': '08:36', 'stop': 'Huddinge'}, {'arrivalTime': '08:39', 'stop': 'Stuvsta'}, {'arrivalTime': '08:42', 'stop': 'Älvsjö'}, {'arrivalTime': '08:45', 'stop': 'Årstaberg'}, {'arrivalTime': '08:48', 'stop': 'Stockholms södra'}]}, {'origin': 'T-Centralen', 'arrivalTime': '09:05', 'departureTime': '08:59', 'destination': 'Tekniska högskolan', 'trip': [{'arrivalTime': '09:02', 'stop': 'Östermalmstorg'}, {'arrivalTime': '09:03', 'stop': 'Stadion'}]}], 'departureTime': '08:06', 'destination': 'Tekniska högskolan (Stockholm)', 'departureDate': '2016-05-31'}
Utöver den användarvänliga slcli-exekverbaren finns det några wrapper-moduler för API:erna SL Platsuppslag och SL Reseplanerare 3.1. CLI-argumenten till dessa är samma som de faktiska query-parametrarna; se --help för en beskrivning. Output är JSON.
$ mv locations.xml slcli/resources/
$ python -m slcli.keyreader platsuppslag | xargs -I % python -m slcli.platsuppslag % vårsta
{"ResponseData": [{"X": "17797365", "Type": "Station", "Y": "59165265", "Name": "V\u00e5rsta centrum (Botkyrka)", "SiteId": "7305"}, {"X": "17858123", "Type": "Station", "Y": "59626106", "Name": "M\u00e4rsta v\u00e5rdcentral (Sigtuna)", "SiteId": "5018"}, {"X": "17887931", "Type": "Station", "Y": "59273603", "Name": "V\u00e5rberg (Stockholm)", "SiteId": "9286"}, {"X": "17886520", "Type": "Station", "Y": "59263517", "Name": "V\u00e5rby g\u00e5rd (Huddinge)", "SiteId": "9285"}, {"X": "17797365", "Type": "Station", "Y": "59165265", "Name": "V\u00c5RC", "SiteId": "7305"}, {"X": "17954820", "Type": "Station", "Y": "59224872", "Name": "V\u00c5RK", "SiteId": "7015"}, {"X": "17886592", "Type": "Station", "Y": "59275868", "Name": "V\u00e5rbergs centrum (Stockholm)", "SiteId": "1796"}, {"X": "17421571", "Type": "Station", "Y": "59216440", "Name": "V\u00e5rtala (Nykvarn)", "SiteId": "7734"}, {"X": "18471763", "Type": "Station", "Y": "59424298", "Name": "V\u00e5rholma (V\u00e4rmd\u00f6)", "SiteId": "143"}, {"X": "18483071", "Type": "Station", "Y": "59423345", "Name": "V\u00e5rlunda (V\u00e4rmd\u00f6)", "SiteId": "144"}], "Message": null, "StatusCode": 0, "ExecutionTime": 0}
där
%
är en placeholder för en API-nyckel som keyreader.py spottar utvårsta
är söksträngen som Platsuppslag identifierar som "Vårsta centrum (Botkyrka)"
$ python -m slcli.keyreader reseplanerare3_1 | xargs -I % python -m slcli.reseplanerare3_1-trip % 9506 9526 '9:15'
{"Trip": [{"co2": "0.00", "dur": "38", "chg": "0", "PriceInfo": {"TariffRemark": {"$": "3 biljett"}, "TariffZones": {"$": "AB"}}, "LegList": {"Leg": {"Origin": {"routeIdx": "6", "date": "2016-04-20", "id": "400105061", "time": "09:27", "lat": "59.428019", "lon": "17.948833", "name": "Sollentuna", "type": "ST"}, "dir": "S\u00f6dert\u00e4lje C", "name": "pendelt\u00e5g 36", "JourneyDetailRef": {"ref": "ref%3D376593%2F133285%2F543308%2F146123%2F74%3Fdate%3D2016-04-20%26station_evaId%3D400105061%26station_type%3Ddep%26lang%3Dsv%26format%3Djson%26"}, "idx": "0", "line": "36", "type": "TRAIN", "Destination": {"routeIdx": "17", "date": "2016-04-20", "id": "400105171", "time": "10:05", "lat": "59.219047", "lon": "17.947206", "name": "Flemingsberg", "type": "ST"}, "GeometryRef": {"ref": "ref%3D376593%2F133285%2F543308%2F146123%2F74%26startIdx%3D6%26endIdx%3D17%26lang%3Dsv%26format%3Djson%26"}}}}, {"co2": "0.00", "dur": "38", "chg": "0", "PriceInfo": {"TariffRemark": {"$": "3 biljett"}, "TariffZones": {"$": "AB"}}, "LegList": {"Leg": {"Origin": {"routeIdx": "6", "date": "2016-04-20", "id": "400105061", "time": "09:42", "lat": "59.428019", "lon": "17.948833", "name": "Sollentuna", "type": "ST"}, "dir": "S\u00f6dert\u00e4lje C", "name": "pendelt\u00e5g 36", "JourneyDetailRef": {"ref": "ref%3D943599%2F322311%2F944690%2F157813%2F74%3Fdate%3D2016-04-20%26station_evaId%3D400105061%26station_type%3Ddep%26lang%3Dsv%26format%3Djson%26"}, "idx": "0", "line": "36", "type": "TRAIN", "Destination": {"routeIdx": "17", "date": "2016-04-20", "id": "400105171", "time": "10:20", "lat": "59.219047", "lon": "17.947206", "name": "Flemingsberg", "type": "ST"}, "GeometryRef": {"ref": "ref%3D943599%2F322311%2F944690%2F157813%2F74%26startIdx%3D6%26endIdx%3D17%26lang%3Dsv%26format%3Djson%26"}}}}, {"co2": "0.00", "dur": "38", "chg": "0", "PriceInfo": {"TariffRemark": {"$": "3 biljett"}, "TariffZones": {"$": "AB"}}, "LegList": {"Leg": {"Origin": {"routeIdx": "6", "date": "2016-04-20", "id": "400105061", "time": "09:57", "lat": "59.428019", "lon": "17.948833", "name": "Sollentuna", "type": "ST"}, "dir": "S\u00f6dert\u00e4lje C", "name": "pendelt\u00e5g 36", "JourneyDetailRef": {"ref": "ref%3D975198%2F332820%2F697512%2F23691%2F74%3Fdate%3D2016-04-20%26station_evaId%3D400105061%26station_type%3Ddep%26lang%3Dsv%26format%3Djson%26"}, "idx": "0", "line": "36", "type": "TRAIN", "Destination": {"routeIdx": "17", "date": "2016-04-20", "id": "400105171", "time": "10:35", "lat": "59.219047", "lon": "17.947206", "name": "Flemingsberg", "type": "ST"}, "GeometryRef": {"ref": "ref%3D975198%2F332820%2F697512%2F23691%2F74%26startIdx%3D6%26endIdx%3D17%26lang%3Dsv%26format%3Djson%26"}}}}, {"co2": "0.00", "dur": "38", "chg": "0", "PriceInfo": {"TariffRemark": {"$": "3 biljett"}, "TariffZones": {"$": "AB"}}, "LegList": {"Leg": {"Origin": {"routeIdx": "6", "date": "2016-04-20", "id": "400105061", "time": "10:12", "lat": "59.428019", "lon": "17.948833", "name": "Sollentuna", "type": "ST"}, "dir": "S\u00f6dert\u00e4lje C", "name": "pendelt\u00e5g 36", "JourneyDetailRef": {"ref": "ref%3D605097%2F209477%2F625428%2F111017%2F74%3Fdate%3D2016-04-20%26station_evaId%3D400105061%26station_type%3Ddep%26lang%3Dsv%26format%3Djson%26"}, "idx": "0", "line": "36", "type": "TRAIN", "Destination": {"routeIdx": "17", "date": "2016-04-20", "id": "400105171", "time": "10:50", "lat": "59.219047", "lon": "17.947206", "name": "Flemingsberg", "type": "ST"}, "GeometryRef": {"ref": "ref%3D605097%2F209477%2F625428%2F111017%2F74%26startIdx%3D6%26endIdx%3D17%26lang%3Dsv%26format%3Djson%26"}}}}, {"co2": "0.00", "dur": "38", "chg": "0", "PriceInfo": {"TariffRemark": {"$": "3 biljett"}, "TariffZones": {"$": "AB"}}, "LegList": {"Leg": {"Origin": {"routeIdx": "6", "date": "2016-04-20", "id": "400105061", "time": "10:27", "lat": "59.428019", "lon": "17.948833", "name": "Sollentuna", "type": "ST"}, "dir": "S\u00f6dert\u00e4lje C", "name": "pendelt\u00e5g 36", "JourneyDetailRef": {"ref": "ref%3D2337%2F8610%2F538500%2F268471%2F74%3Fdate%3D2016-04-20%26station_evaId%3D400105061%26station_type%3Ddep%26lang%3Dsv%26format%3Djson%26"}, "idx": "0", "line": "36", "type": "TRAIN", "Destination": {"routeIdx": "17", "date": "2016-04-20", "id": "400105171", "time": "11:05", "lat": "59.219047", "lon": "17.947206", "name": "Flemingsberg", "type": "ST"}, "GeometryRef": {"ref": "ref%3D2337%2F8610%2F538500%2F268471%2F74%26startIdx%3D6%26endIdx%3D17%26lang%3Dsv%26format%3Djson%26"}}}}], "noNamespaceSchemaLocation": "hafasRestTrip.xsd"}
där
9506
är ID:t för Sollentuna (avgångspunkten)9526
är ID:t för Flemingsberg (destinationen)'9:15'
är tidpunkten för avgång
$ python -m slcli.keyreader reseplanerare3_1 | xargs -I % python -m slcli.reseplanerare3_1-journeydetail.py % '970356/328288/925322/139225/74?date=2016-04-20&station_evaId=400101051&station_type=dep&lang=sv&format=json&'
{"JourneyDetail": {"GeometryRef": {"ref": "ref%3D169662%2F61390%2F252364%2F69644%2F74%26lang%3Dsv%26format%3Djson%26"}, "Types": {"Type": {"routeIdxFrom": "0", "$": "METRO", "routeIdxTo": "18"}}, "Directions": {"Direction": {"routeIdxFrom": "0", "$": "M\u00f6rby centrum", "routeIdxTo": "18"}}, "RTUMessages": {"RTUMessage": [{"$": "Tv\u00e5 hissar \u00e4r avst\u00e4ngda vid Danderyds sjukhus p.g.a. underh\u00e5llsarbeten."}, {"$": "Hissen till och fr\u00e5n plattformen vid Hornstull, fungerar inte."}]}, "Stops": {"Stop": [{"depTime": "08:39", "id": "400102851", "name": "Fru\u00e4ngen", "lon": "17.964843", "lat": "59.286754", "routeIdx": "0", "depDate": "2016-04-20"}, {"depTime": "08:40", "arrTime": "08:40", "id": "400102841", "name": "V\u00e4stertorp", "lon": "17.966704", "arrDate": "2016-04-20", "lat": "59.291347", "routeIdx": "1", "depDate": "2016-04-20"}, {"depTime": "08:42", "arrTime": "08:42", "id": "400102831", "name": "H\u00e4gerstens\u00e5sen", "lon": "17.978426", "arrDate": "2016-04-20", "lat": "59.295159", "routeIdx": "2", "depDate": "2016-04-20"}, {"depTime": "08:44", "arrTime": "08:44", "id": "400102821", "name": "Telefonplan", "lon": "17.997321", "arrDate": "2016-04-20", "lat": "59.298251", "routeIdx": "3", "depDate": "2016-04-20"}, {"depTime": "08:46", "arrTime": "08:46", "id": "400102811", "name": "Midsommarkransen", "lon": "18.011965", "arrDate": "2016-04-20", "lat": "59.301865", "routeIdx": "4", "depDate": "2016-04-20"}, {"depTime": "08:48", "arrTime": "08:48", "id": "400102603", "name": "Liljeholmen", "lon": "18.023093", "arrDate": "2016-04-20", "lat": "59.310710", "routeIdx": "5", "depDate": "2016-04-20"}, {"depTime": "08:50", "arrTime": "08:50", "id": "400102531", "name": "Hornstull", "lon": "18.035543", "arrDate": "2016-04-20", "lat": "59.315960", "routeIdx": "6", "depDate": "2016-04-20"}, {"depTime": "08:51", "arrTime": "08:51", "id": "400102521", "name": "Zinkensdamm", "lon": "18.049692", "arrDate": "2016-04-20", "lat": "59.317704", "routeIdx": "7", "depDate": "2016-04-20"}, {"depTime": "08:52", "arrTime": "08:52", "id": "400102511", "name": "Mariatorget", "lon": "18.062115", "arrDate": "2016-04-20", "lat": "59.317012", "routeIdx": "8", "depDate": "2016-04-20"}, {"depTime": "08:55", "arrTime": "08:55", "id": "400102011", "name": "Slussen", "lon": "18.071491", "arrDate": "2016-04-20", "lat": "59.319511", "routeIdx": "9", "depDate": "2016-04-20"}, {"depTime": "08:56", "arrTime": "08:56", "id": "400102021", "name": "Gamla stan", "lon": "18.067167", "arrDate": "2016-04-20", "lat": "59.323187", "routeIdx": "10", "depDate": "2016-04-20"}, {"depTime": "08:59", "arrTime": "08:59", "id": "400101051", "name": "T-Centralen", "lon": "18.061486", "arrDate": "2016-04-20", "lat": "59.331358", "routeIdx": "11", "depDate": "2016-04-20"}, {"depTime": "09:02", "arrTime": "09:02", "id": "400102101", "name": "\u00d6stermalmstorg", "lon": "18.076381", "arrDate": "2016-04-20", "lat": "59.334972", "routeIdx": "12", "depDate": "2016-04-20"}, {"depTime": "09:03", "arrTime": "09:03", "id": "400102211", "name": "Stadion", "lon": "18.081946", "arrDate": "2016-04-20", "lat": "59.340806", "routeIdx": "13", "depDate": "2016-04-20"}, {"depTime": "09:05", "arrTime": "09:05", "id": "400102221", "name": "Tekniska h\u00f6gskolan", "lon": "18.069316", "arrDate": "2016-04-20", "lat": "59.346541", "routeIdx": "14", "depDate": "2016-04-20"}, {"depTime": "09:08", "arrTime": "09:08", "id": "400102231", "name": "Universitetet (Tunnelbanan)", "lon": "18.054897", "arrDate": "2016-04-20", "lat": "59.365365", "routeIdx": "15", "depDate": "2016-04-20"}, {"depTime": "09:10", "arrTime": "09:10", "id": "400102241", "name": "Bergshamra", "lon": "18.037485", "arrDate": "2016-04-20", "lat": "59.380736", "routeIdx": "16", "depDate": "2016-04-20"}, {"depTime": "09:12", "arrTime": "09:12", "id": "400102251", "name": "Danderyds sjukhus", "lon": "18.041755", "arrDate": "2016-04-20", "lat": "59.390507", "routeIdx": "17", "depDate": "2016-04-20"}, {"arrTime": "09:14", "id": "400102301", "name": "M\u00f6rby centrum", "lon": "18.036424", "arrDate": "2016-04-20", "lat": "59.398319", "routeIdx": "18"}]}, "Names": {"Name": {"routeIdxFrom": "0", "$": "tunnelbanans r\u00f6da linje 14", "routeIdxTo": "18"}}, "noNamespaceSchemaLocation": "hafasRestJourneyDetail.xsd", "Lines": {"Line": {"routeIdxFrom": "0", "$": "14", "routeIdxTo": "18"}}}}
där
'970356/...
är en referensparameter (del av en URL)