2016. február havi bejegyzések

BKK Futár Microsoft Bandre – service és webtile (3. rész)

A Microsoft Band programozási lehetőségeinek és a BKK Futár API-jának a megismerése után el kellett döntenem, hogyan is szeretnék menetrendi adatokat megjeleníteni a Banden. Végül a webtile mellett döntöttem, leginkább azért, mert az SDK-s megoldás egy folyamatosan futó mobil alkalmazást igényelt volna.

A webtile korlátja, hogy sajnos nem tudjuk befolyásolni, mikor frissüljön, ezért nem álmodozhatunk olyan megoldásról, ami relatív időpontokat használ. Le kell tehát mondanunk a “3 perc múlva indul” stílusú, azonnal érthető megjelenítésről, helyette abszolút időpontokat használhatunk, azaz például “indulás 11:23-kor”. Ez nem annyira szép, de nem óriási probléma, hiszen a Band elsődleges képernyője (Me Tile) mindig a pontos időt mutatja, egy ilyen bonyolult kivonást pedig rá merek bízni a felhasználóra.

A nagyobb probléma, hogy ezzel megszűnik a “következő indulás” fogalma, hiszen a frissítési időközön belül akár több indulás is lehet, és előfordulhat, hogy egy vagy több már múltbeli lesz, mikor a felhasználó rápillant a csempére. Erre nem tudtam jobb megoldást kitalálni, mint hogy több indulási időpontot jelenítek meg, amiből majd a felhasználó némi humán komparálással kiválasztja, hogy melyik a legközelebbi. Egyébként is terveztem, hogy célszerű lenne több időpontot megmutatni, hiszen előfordulhat, hogy a nem a következő buszt, hanem csak a következő utánit szeretném elérni, mert túl messze van a megálló. A sajnálatos szépséghiba, hogy a listában jó eséllyel lesz múltbeli időpont is.

Az adatforrás

A leendő webtile-t természetesen el kell látni adatokkal, azaz szükséges hozzá egy GET-en elérhető szerviz. Bár ahogy az előző részben láttuk, létezik BKK Futár API, az sajnos nem tudja az adatokat pont olyan formában szolgáltatni, amire nekünk szükségünk van. Az eltérések:

  • A Futár API az indulási időpontokat epochtól eltelt másodpercben adja meg, azaz egy bazi nagy, igen barátságtalan számként. Ezt sajnos a webtile nem tudja emberileg fogyasztható formátumra konvertálni.
  • Az API-ban van predictedArrivalTime, arrivalTime és departureTime mező is, és változó, hogy mikor melyik van kitöltve, vagy melyiket érdemes használni. Dokumentáció híján csak tippelni tudok, melyik mit jelent, de a tapasztalat az, hogy a predicted csak a már közeledő járműveknél van kitöltve (tipikusan a következő vagy esetleg a következő kettő), és ez a legpontosabb. A sima arrivalTime szinte mindig ki van töltve, kivéve végállomásoknál, ahol csak a departureTime jelenik meg.
  • Az API hívás sikerességét nem (vagy nem csak?) a HTTP status code, hanem a HTTP válaszban lévő több mező értéke együttesen írja le, amit webtile esetén nem tudunk vizsgálni.
  • A Futár API-tól a következő indulások objektum tömbként kérhetők le, azonban egyik lehetséges webtile layout sem tudja azokat praktikusan megjeleníteni. Sokkal jobb lenne egy vesszővel elválasztott string, például “10:45, 10:56, 11:07”, de ilyen adat átalakításra a webtile nem képes.

Ezen problémák miatt végül úgy döntöttem, hogy készítek egy saját webszervizt, ami adatokkal fogja táplálni Bandit. Tekintve, hogy viszonylag primitív logikáról van szó, ellenben van benne JSON matatás rendesen, és mostanában elsősorban JavaScriptben dolgozom, egy Node.js-es szolgáltatást készítettem. Webszerver frameworkként Hapi-t, a Futár API hívásához pedig a request-promise NPM package-et választottam, mert ezeket már ismertem korábban.

Mivel a webtile nem paraméterezhető, nem láttam értelmét olyan szolgáltatást készítésének, amit bárki, bármilyen járat indulásainak lekérésére használhat. Ez nagyban egyszerűsítette a dolgomat, mert így a KoviBuszból kikeresett megálló azonosítókat én bizony simán beledrótoztam a forráskódba. Az én szervizem, az én megállóim. Persze a forráskódot kitettem Githubra, hogy bárki barkácsolhasson magának hasonlót, vagy még jobbat:

github-logo

 https://github.com/balassy/band-futar-tile

Íme néhány érdekesebb pont a kódból:

  • A webszerviz kódja az src mappában található, a webtile által hívott végpont pedig azon belül a next-ride mappában.
  • Azon belül a service.js hívja a Futár API-t a paraméterként kapott megálló azonosítóval.
  • A service.js-t a controller.js hívja, átadva neki a keresett megállók azonosítóit.
  • A gulpfile.js az urbanjs-tools nevű NPM package-t használja statikus kódelemzésre, ami nagyon kényelmessé teszi az ESLint és az ES6 használatát.
  • A forráskódot Visual Studio Code-dal írtam, erre utalnak a .vscode, typings mappák és a tsd.json fájl. (Igen, a typings mappát nem kellene betenni a repoba, de így sokkal kényelmesebb volt.)
  • A projektet pillanatok alatt sikerült bekötnöm Travisbe és AppVeyorba, ezek beállításai találhatók a .travis.yml és az appveyor.yml fájlokban. Ezek az ingyenes online build környezetek segítettek a forráskód folyamatos karbantartásában, mindkettőt csak ajánlani tudom.

Hosting környezetnek természetesen Azure-t választottam, mert piszkosul egyszerű egy Githubon tárolt web alkalmazás continuous deploymentjét összelőni. Most amint felküldök egy kód módosítást a Githubra, lefut a build Travisben és települ is ki automatikusan az Azure-os webszerverre. Ez az automatizmus még egy ilyen egyszerű alkalmazás esetén is óriási segítség fejlesztés közben.

A webtile

A webtile elkészítéséhez az első részben is említett varázslót használtam. Úgy döntöttem, hogy ez egyes járatok adatait külön page-en fogom megjeleníteni (Multiple page tile), azon belül egy a Scrolling text wrap (MSBand_ScrollingText) elrendezés bizonyult legpraktikusabbnak az ismeretlen hosszúságú szöveg megjelenítésére. Ezt így mutatja a varázsló (az 59-es villamos következő indulásai a Vas Gereben utcai megállóból):

band-webtile-wizard-preview-1

Jelenleg a szerviz az engem leginkább érdeklő három járat adatait adja vissza, ezek mind külön page-et kaptak, utánuk pedig egy negyedik oldalra az utolsó frissítés időpontját tettem. Ez hibakereséshez lehet jó, a szerviz a válasz JSON egyik property-jében visszaadja, hogy mikor kérte le utoljára az adatokat a Futár API-tól, így könnyű volt megjeleníteni:

band-webtile-wizard-preview-2

A varázsló által generált webtile-t nem közvetlenül telepítettem Bandira, hanem letöltöttem, kicsomagoltam (mert valójában egy ZIP fájl), és módosítottam rajta (a végeredmény megtalálható a a webtile/manifest.json fájlban):

  • Kijavítottam azokat az apró hibákat, amiket a webes varázslóban egyszerűen nem sikerült.
  • Beállítottam a refreshIntervalMinutes tulajdonság értékét 15-re, ami negyedórás frissítési időközt jelent, ennél sűrűbben nem is lehet.
  • Beállítottam a version és a versionString tulajdonságokat, és minden újabb kísérletnél inkrementáltam őket, hogy biztosan észrevegye a Microsoft Health alkalmazás, hogy újabb verziót akarok telepíteni.
  • Beállítottam a name, description, author, organization és contactEmail tulajdonságok értékeit, hogy azok kulturáltan jelenjenek meg telepítéskor.

Jelenleg a webszerviz HTTP 500 status code-dal tér vissza, ha valami nem sikerül szerver oldalon, de erősen gondolkodom rajta, hogy hibakeresési célzattal minden ilyen esetben HTTP 200 OK-val térjek vissza, és a hiba leírását adjam vissza a válaszban, hogy azt könnyen meg lehessen jeleníteni a Banden.

A végeredmény

Örömmel tölt el, hogy az elkészült megoldás működik, a Futár API-tól kapott adatok megjelennek, és a megoldás nem bonyolult.

band-futar-tile

band-futar-page

band-futar-update-page

A Futár igazi értéke abban van, hogy nem csak egy sima menetrend, hanem (elméletileg legalábbis) valós idejű adatokat tartalmaz, azaz az aktuális forgalmi helyzetet tükrözi. Sajnos a webtile legjobb esetben is negyedórás frissítési időköze ezt a remek lehetőséget tökéletesen megöli, ami már kevésbé örvendetes, hiszen így az esetek nagy részében “csak” a menetrendi adatokat látom, ami Tokióban minden bizonnyal tökéletesen működne, Budapesten még nem 100%-os. Mivel engem leggyakrabban egy villamosmegálló és egy buszvégállomás indulási időpontjai érdekelnek, számomra egészen jól használható a végeredmény.

Te milyen adatokat látnál szívesen az órádon?

 

Technorati-címkék: ,
Reklámok

BKK Futár Microsoft Bandre – a BKK Futár API (2. rész)

Ahogy az előző részben említettem, azt tűztem ki célul, hogy a BKK Futártól kapott aktuális tömegközlekedési információkat okosórán, konkrétan Microsoft Banden jelenítem meg. A Band programozási lehetőségeinek áttekintése után ebben a részben először nézzük meg azt, hogy a BKK Futár adatait hogyan érhetjük el.

A BKK Futár API

A Budapesti Közlekedése Központ honlapján igen haladó módon létezik egy Fejlesztőknek szóló oldal, ahol gyorsan kiderült, hogy nem rám gondoltak. A BKK megközelítése az, hogy a menetrendi információkat bizonyos időközönként publikálják az oldalukon egy kb. 28 MB-os ZIP fájlban. Értem én, hogy a ZIP-ben GTFS, azaz General Transit Feed Specification formátumban vannak az adatok, ami igen elterjedt, hiszen a G csak udvariasságból General és nem Google, meg hogy így könnyű feltölteni a Mapsre és hogy sűrűn frissítik, ez tényleg szép, csak nekem éppen most pont nem jó.

A következő utam a BKK Futár oldalára vezetett, ahol minden bevezető nélkül egy interaktív térképet találhatunk, ami már sokkal érdekesebb, hiszen ez teljesen friss adatokkal dolgozik. Irány a fejlesztőknek szóló leírás: F12. Nem is kellett sokáig keresgélni a Firebugban, hogy ráleljek erre a kérésre (kattints a teljes méretű képért):

ms-band-4-futar-api

Ebből az egyetlen kérésből több dolog is kiderült:

  • Létezik API, sőt már az URL-jét is tudom. Kellene dokumentáció, amiből kiderül, hogy milyen végpontok vannak.
  • Az API verziózottnak tűnik, ami általában jó hír. Kellene dokumentáció, amiből kiderül, hogy milyen verziók léteznek.
  • Az API hívásához lehet, hogy kell API kulcs. Kellene dokumentáció, amiből kiderül, honnan lesz API kulcsom.
  • Lehet, hogy van throttling, legalábbis a data.limitExceeded mező erre utal. Kellene dokumentáció, amiből kiderül, hogy mennyi az annyi.
  • Státusz információ van bőven: a HTTP státusz kódon kívül a válaszban is van egy status, egy code, és egy text mező, sőt (és ez a fenti képen nem látszik) a szerver még egy X-BKK-Status fejlécet is visszaküld “OK” értékkel. Kellene egy dokumentáció, amiből kiderül, hogy melyik kell nekem.

Ez elég volt ahhoz, hogy elinduljak, de minden jel arra utalt, hogy nagy hasznát venném bármiféle további dokumentációnak.

Neki is álltam óriási lelkesedéssel, keresgéltem a BKK oldalán, a Bingben, de sajnos az összes Google-fu tudásom is kevésnek bizonyult, nem találtam hivatalos leírást. (Aki ismer ilyet, kérem küldje el nekem, köszönöm.)

Találtam viszont több nem hivatalos forrást is:

  • Létezik egy Index Fórum “A BKV GTFS adatbázisa” címmel, ahonnan számomra az derült ki, hogy a nép szenved a GTFS-től és egy barátságosabb API-t szeretne.
  • Az Apiary oldalán találtam egy dokumentációt BKK FUTÁR Utazástervező API címmel. Sajnos nem tűnik hivatalosnak, használhatónak viszont annál inkább.
  • Nádai Gábor (alias Mefi) nevén találtam egy Github repót KoviBusz néven, ami egy adott busz következő indulási idejét mutatja az API-t felhasználva. A kód Node.js-ben készült, és egy barátságos fájlban JSON formátumban tartalmazza a megállókat.

Járatinformációk

Az Apiary dokumentáció és a Firebug böngészése közben világossá vált, hogy nekem az Arrivals and Departures for Stop (nem is olyan nehéz egy API-t jól elnevezni, igaz?) API-ra van szükségem, amit így kell meghívni:

GET http://futar.bkk.hu/bkk-utvonaltervezo-api/ws/otp/api/where/arrivals-and-departures-for-stop.json?stopId&onlyDepartures&minutesBefore&minutesAfter

Ahol:

  • A stopId a megálló azonosítója, például BKK_F00945.
  • Az onlyDepartures paramétert true-ra állítva megadhatjuk, hogy csak az indulások érdekelnek.
  • A doksi szerint a minutesBefore-ral lekérdezhetjük a korábban elment járatokat, ami Marty McFly számára kétségkívül egy hasznos funkció, nálam 0 lesz, az biztos.
  • A minutesAfter-rel pedig azt állíthatjuk be, hogy hány percre előre szeretnénk lekérni az érkező és induló járatokat.

Következő lépésként megálló azonosítóra volt szükségem. Ehhez legjobb forrásnak a Mefi KoviBusz oldala bizonyult, ami térképen kirajzolja az összes megállót, csak rá kell bökni valamelyikre, és Firebugban máris látszódik az azonosítója. A József Nádor tér például F00979.

GET-es API-ról lévén szó, ezt könnyen ki is próbálhatjuk, csak tegyük a megálló azonosítója elé a BKK_ előtagot, és írjuk be a címet a böngésző címsorába:

http://futar.bkk.hu/bkk-utvonaltervezo-api/ws/otp/api/where/arrivals-and-departures-for-stop.json?stopId=BKK_F00979

Íme a szervertől kapott válasz, ahogy azt a Chrome mutatja:

ms-band-5-futar-api-response

Kiemeltem néhány érdekességet:

  • A dátumok és időpontok igen barátságtalanok: nem csak hogy epochtól számított számként jönnek, de hol másodpercben, hol milliszekundumban vannak kifejezve. És akkor az időzónákról még nem is beszéltünk.
  • A következő indulásoknál megjelenik a predictedArrivalTime tulajdonság, sőt létezik predictedDepartureTime is. Végállomásoknál indulási oldalon egyik sincs, csak departureTime.
  • Ebben a megállóban két járat is megáll, a 16-os és a 105-ös. Mi a stop azonosítóját tudjuk, ahhoz tartoznak stopTime-ok, ahhoz trip-ek és végül ahhoz route-ok.

Erős nézés módszerével meglett tehát az API, amiből kinyerhetőek az adatok, már csak össze kell kötnünk a Banddel.

 

(Folytatás következik…)

 

Technorati-címkék: ,