research/transjakarta-live-data/recipes.md
hermes 3a518be39f Add transjakarta-live-data research topic
Verified TransJakarta realtime stack: anonymous MQTT bus feed (wss://mqtt.tj.co.id:8084/mqtt), guest REST API (tijeapi.transjakarta.co.id), official GTFS. Cross-capture verification vs third-party tracker, connection recipes, snapshot tool.
2026-10-12 09:34:23 +00:00

71 lines
3.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Recipes — using TransJakarta live data
Prerequisites: `curl` + `jq` (REST), `node` + `npm install mqtt` (live stream). Any MQTT 3.1.1-over-WSS client works (e.g. MQTTX, paho with websockets transport).
## 1. Live stream (MQTT, anonymous)
```js
// save as live.mjs; run: npm i mqtt && node live.mjs
import mqtt from 'mqtt';
const client = mqtt.connect('wss://mqtt.tj.co.id:8084/mqtt', {
protocolVersion: 4, clean: true, connectTimeout: 15000
});
// whole fleet: '/mobile_armada/#' — or narrow to map cells, e.g. '/mobile_armada/0018-0022/#'
client.on('connect', () => client.subscribe('/mobile_armada/#', { qos: 0 }));
client.on('message', (topic, payload) => {
const b = JSON.parse(payload.toString());
console.log(b.bus_body_no, b.route_code, b.trip_id, b.latitude, b.longitude, b.bearing);
});
```
Notes:
- Expect a retained burst (~2,000 messages) right after subscribing, then live updates.
- `clean: true` avoids stale queues; add simple reconnect handling for long runs.
- Subscribe to specific cells instead of `#` if you only care about one area.
Ready-made snapshot tool: [[transjakarta-live-data/scripts/tj-snapshot.mjs|scripts/tj-snapshot.mjs]]
`node tj-snapshot.mjs --seconds 60 --out snapshot.json`
## 2. REST — guest token + nearby buses
```bash
# 1) guest token (no account)
TOKEN=$(curl -s -X POST 'https://tijeapi.transjakarta.co.id/v1/auth/login/guest' \
-H 'Content-Type: application/json' -H 'Accept: application/json' \
-H 'User-Agent: okhttp/4.12.0' -H 'X-App-OS: android' -H 'X-App-Version: 2.10.2' \
-H 'X-Device-ID: tj-research-01' \
-d '{"device_id":"tj-research-01"}' | jq -r .token)
# 2) nearby buses (Monas-area example)
curl -s 'https://tijeapi.transjakarta.co.id/v1/bus?latitude=-6.2088&longitude=106.8456&radius=1' \
-H "Authorization: Bearer $TOKEN" -H 'Accept: application/json' \
-H 'User-Agent: okhttp/4.12.0' -H 'X-App-OS: android' -H 'X-App-Version: 2.10.2' \
-H 'X-Device-ID: tj-research-01' | jq '.data[0]'
# 3) discovery: which MQTT topics cover a location?
curl -s -X POST 'https://tijeapi.transjakarta.co.id/v1/bus' \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -H 'Accept: application/json' \
-H 'User-Agent: okhttp/4.12.0' -H 'X-App-OS: android' -H 'X-App-Version: 2.10.2' \
-H 'X-Device-ID: tj-research-01' \
-d '{"latitude":-6.2088,"longitude":106.8456,"radius":1,"event":"change_loc"}' | jq '.data.topics'
```
- Any stable `X-Device-ID` string appears accepted; tokens last ~24 h.
- `radius` units unverified (try 1–50).
## 3. Static schedule (GTFS)
```bash
curl -LO https://gtfs.transjakarta.co.id/files/file_gtfs.zip
unzip -d gtfs file_gtfs.zip # stops.txt, routes.txt, trips.txt, shapes.txt, stop_times.txt, ...
```
Join strategy: bus positions arrive with `trip_id` / `route_code`; use GTFS for stop names, shapes, and schedules. Feed stop IDs (`B00436P`-style) match GTFS `stop_id`.
## Cautions
- Undocumented infrastructure: endpoints can change or close without notice. Access is currently open and shared with the official app path — be gentle (one connection goes a long way; avoid aggressive polling).
- Do not open many parallel broker connections or reconnect in tight loops.
- Guest tokens expire; log in again rather than hammering the refresh endpoint.