From c883d969e210e7b29b9b087f49c80230aff38533 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Fri, 20 Dec 2019 18:02:48 +0100 Subject: [PATCH] general documentation for mgate.exe endpoints :memo: [ci skip] --- docs/hafas-mgate-api.md | 135 ++++++++++++++++++++++++++++++++++++++ docs/readme.md | 4 ++ docs/writing-a-profile.md | 2 + 3 files changed, 141 insertions(+) create mode 100644 docs/hafas-mgate-api.md diff --git a/docs/hafas-mgate-api.md b/docs/hafas-mgate-api.md new file mode 100644 index 00000000..21afc1de --- /dev/null +++ b/docs/hafas-mgate-api.md @@ -0,0 +1,135 @@ +# HAFAS `mgate.exe` protocol + +The protocol of `mgate.exe` HAFAS endpoints is not openly (and freely) documented. The following documentation is based on general observations and reverse-engineering. + +*Note:* There are also `rest.exe` (a.k.a. "open API", a.k.a. "REST API") endpoints. This documentation is *not* about them. + +## date & time format + +Dates are encoded as `YYYYMMDD`, time strings as `HHMMSS`. These are in the timezone configured on the HAFAS/server side, *per endpoint*. + +Whenever HAFAS returns a time string that exceeds the day the response describes, it will add a "day offset". As an example, when you query departures at `2019-12-12T23:50+01:00` for the next 30 minutes, it will encode the departure at `2019-12-13T00:13+01:00` as `20191212` & `01001300`. + +For working code, check out [`parseDateTime()`](../parse/date-time.js). + +## coordinate format + +All endpoints I've seen so far use [WGS84](http://wiki.gis.com/wiki/index.php/WGS84). Values are multiplied by `10^6` though, so you would encode `{latitude: 1.23, longitude: -2.34}` as `{Y: 1230000: X: -2340000}`. There's an optional parameter `z` with the elevation. + +For working code, check out [`formatAddress()`](../format/address.js). + +## querying the API + +In many aspects, the API looks and feels like [RPCs](https://en.wikipedia.org/wiki/Remote_procedure_call). You must send queries via HTTP `POST`, with the minimal JSON body looking like this: + +```js +{ + "auth": { + "type": "AID", + "aid": "…" // endpoint-specific authentication token, e.g. `1Rxs112shyHLatUX4fofnmdxK` + }, + "ver": "…", // endpoint-specific string, e.g. `1.15` + "ext": "…", // endpoint-specific string, e.g. `BVG.1` + "client": { + "type": "IPA", // might also be `IPH` for "iPhone" or `WEB` for "web client" + "id": "…", // endpoint-specific string, e.g. `BVG` + "name": "…", // endpoint-specific string, e.g. `FahrInfo` + "v": "…" // endpoint-specific string, e.g. `4070700` + }, + "lang": "…", // language, sometimes 2-digit (e.g. `de`), sometimes 3-digit (e.g. `deu`) + "svcReqL": [ + { + "meth": "…", // name of the API call, supported values depend on the endpoint + "req": { + // actual request parameters… + } + // some endpoints also require this: + "cfg": { + "cfgGrpL": [], + "cfgHash": "…" // endpoint-specific string + } + } + ] +} +``` + +- The data in `client` must be correct, otherwise HAFAS will reject your request. +- HAFAS will return slightly different response formats (and slightly different levels of detail) for different `ver`, `ext` and `client.v` values. +- All endpoints known support JSON & UTF-8, so make sure to send `Accept: application/json` & `Accept-Charset: utf-8` headers. +- Most endpoints support at least GZIP compression, so make sure to send a `Accept-Encoding: gzip` header. + +For working code, check out [`request()`](lib/request.js). + +## API responses + +A minimal valid response looks like this: + +```js +{ + "ver": "…", // endpoint-specific string, e.g. `1.15` + "lang": "…", // language + "ext": "…", // endpoint-specific string, e.g. `BVG.1` + "id": "…", // unique ID for each response? + "svcResL": [ + { + "meth": "StationBoard", + "err": "OK", + "res": { + // result of the API call + } + } + ] +} +``` + +For working code, check out [`request()`](lib/request.js). + +### parse error + +todo: generic server error + +```js +{ + "ver": "…", // endpoint-specific string, e.g. `1.15` + "lang": "…", // language, sometimes 2-digit (e.g. `de`), sometimes 3-digit (e.g. `deu`) + "err": "PARSE", // error code + "errTxt": "…", // error message, not always present + "svcResL": [] +} +``` + +### authentication error + +```js +{ + "ver": "…", // endpoint-specific string, e.g. `1.15` + "lang": "…", // language + "ext": "…", // endpoint-specific string, e.g. `BVG.1` + "err": "AUTH", // error code + "errTxt": "…", // error message, not always present + "svcResL": [] +} +``` + +### API-call-specific error + +```js +{ + "ver": "…", // endpoint-specific string, e.g. `1.15` + "lang": "…", // language + "ext": "…", // endpoint-specific string, e.g. `BVG.1` + "svcResL": [ + { + "meth": "StationBoard", + "err": "…", // error code, e.g. `H9300` + "errTxt": "…", // error message, e.g. `Unknown arrival station` + "res": {} + } + ] +} +``` + +## more ressources + +- [@Nakaner's `strecken.info` API docs](https://github.com/Nakaner/bahnstoerungen/tree/62a72b1e0f0255668500b438187ff65aef39242a/api-doc/db-strecken-info) +- [unfinished HAFAS glossary](https://gist.github.com/derhuerst/74b703e2a0fc64e4a0fa8fbb1f3a61b4) diff --git a/docs/readme.md b/docs/readme.md index 77b3ba51..d403b727 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -77,3 +77,7 @@ const client = createRetryingClient(dbProfile, 'my-awesome-program') ## Writing a profile Check [the guide](writing-a-profile.md). + +## General documentation for `mgate.exe` APIs + +[`hafas-mgate-api.md`](hafas-mgate-api.md) diff --git a/docs/writing-a-profile.md b/docs/writing-a-profile.md index dceb96e4..80eff168 100644 --- a/docs/writing-a-profile.md +++ b/docs/writing-a-profile.md @@ -69,6 +69,8 @@ If you pass this profile into `hafas-client`, the `parseLine` method will overri ## 2. Basic profile +*Note:* You should have read the [general documentation on `mgate.exe` APIs](hafas-mgate-api.md) to make sense of the terminology used below. + You may want to start with the [profile boilerplate](profile-boilerplate.js). - **Identify the `endpoint`.** The protocol, host and path of the endpoint, *but not* the query string.