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.
This commit is contained in:
parent
cf8619cc5f
commit
3a518be39f
7 changed files with 306 additions and 0 deletions
63
transjakarta-live-data/scripts/tj-snapshot.mjs
Normal file
63
transjakarta-live-data/scripts/tj-snapshot.mjs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/env node
|
||||
// tj-snapshot.mjs — capture a live snapshot of the TransJakarta bus feed (MQTT over WSS).
|
||||
//
|
||||
// The broker (wss://mqtt.tj.co.id:8084/mqtt) is anonymous. This tool connects,
|
||||
// subscribes, and records the last known state of every bus it sees.
|
||||
//
|
||||
// Setup: npm install mqtt (in this directory, or a parent dir)
|
||||
// Usage: node tj-snapshot.mjs [--topic /mobile_armada/#] [--seconds 60] [--out snapshot.json]
|
||||
//
|
||||
// Output: summary on stdout; with --out, a JSON file:
|
||||
// { capturedAt, durationSec, topic, messages, busCount, buses: { <bus_body_no>: {...} } }
|
||||
//
|
||||
// Notes: undocumented infrastructure — be gentle; one connection is enough.
|
||||
// Whole fleet: '/mobile_armada/#'. One area: '/mobile_armada/0018-0022/#'.
|
||||
|
||||
import mqtt from 'mqtt';
|
||||
import fs from 'fs';
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const getArg = (name, fallback) => {
|
||||
const i = args.indexOf(name);
|
||||
return i >= 0 && args[i + 1] ? args[i + 1] : fallback;
|
||||
};
|
||||
|
||||
const topic = getArg('--topic', '/mobile_armada/#');
|
||||
const seconds = parseInt(getArg('--seconds', '60'), 10) || 60;
|
||||
const outFile = getArg('--out', '');
|
||||
|
||||
const out = { capturedAt: new Date().toISOString(), durationSec: seconds, topic, messages: 0, buses: {} };
|
||||
|
||||
const client = mqtt.connect('wss://mqtt.tj.co.id:8084/mqtt', {
|
||||
protocolVersion: 4, keepalive: 30, clean: true, connectTimeout: 15000, reconnectPeriod: 0
|
||||
});
|
||||
|
||||
client.on('connect', () => client.subscribe(topic, { qos: 0 }));
|
||||
client.on('error', (e) => console.error('MQTT error:', e.message));
|
||||
|
||||
client.on('message', (t, payload) => {
|
||||
out.messages++;
|
||||
try {
|
||||
const d = JSON.parse(payload.toString());
|
||||
if (!d.bus_body_no) return;
|
||||
out.buses[d.bus_body_no] = {
|
||||
lat: d.latitude, lng: d.longitude, bearing: d.bearing,
|
||||
route: d.route_code, trip: d.trip_id, headsign: d.trip_headsign,
|
||||
type: d.type, direction: d.direction,
|
||||
currStop: d.curr_stops, nextStop: d.next_stops,
|
||||
etaNextStopMin: d.estimated_time_next_stops,
|
||||
lastUpdate: d.timestamp, mqttTopic: t
|
||||
};
|
||||
} catch { /* skip malformed */ }
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
out.busCount = Object.keys(out.buses).length;
|
||||
console.log(`Captured ${out.messages} messages, ${out.busCount} unique buses in ${seconds}s`);
|
||||
if (outFile) {
|
||||
fs.writeFileSync(outFile, JSON.stringify(out));
|
||||
console.log(`Snapshot written to ${outFile}`);
|
||||
}
|
||||
client.end(true);
|
||||
process.exit(0);
|
||||
}, seconds * 1000);
|
||||
Loading…
Add table
Add a link
Reference in a new issue