Skip to content

Instantly share code, notes, and snippets.

@serverwentdown
Last active September 25, 2016 10:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save serverwentdown/eea62b7a92dae6b11448b9e3f4c6a4d0 to your computer and use it in GitHub Desktop.
Save serverwentdown/eea62b7a92dae6b11448b9e3f4c6a4d0 to your computer and use it in GitHub Desktop.
Quick and dirty Node.js library for LTA's Arrival API
"use strict";
/* jshint esversion: 6 */
/* jshint node: true */
const fs = require("fs");
const url = require("url");
const http = require("http");
const path = require("path");
const querystring = require("querystring");
const ENDPOINT = "http://datamall2.mytransport.sg/ltaodataservice/";
const SERVICE = "BusArrival";
const AUTH = JSON.parse(fs.readFileSync(path.join(__dirname, "auth.json"), "utf8"));
const BASE_URL = url.parse(url.resolve(ENDPOINT, SERVICE));
const STOP_URL = (stopID) => Object.assign(BASE_URL, {
path: BASE_URL.path + "?" + querystring.stringify({ BusStopID: stopID, SST: true })
});
const STOP_OPTIONS = (stopID) => Object.assign(STOP_URL(stopID), {
headers: Object.assign({ "Accept": "application/json" }, AUTH)
});
const UPDATE_DELAY = 30 * 1000;
const UPDATE_DELAY_ERROR = 5 * 1000;
class ArrivalAPI {
constructor(onDemand) {
this.onDemand = onDemand;
this._cached = {};
this._timers = {};
}
get(stopID, cb) {
if (this.onDemand) {
this._fetch(stopID, cb);
}
else {
this._fetchCached(stopID, cb);
}
}
_fetchCached(stopID, cb) {
stopID = parseInt(stopID);
if (this._cached[stopID]) {
cb(this._cached[stopID][0], this._cached[stopID][1]);
}
else {
this._fetch(stopID, (data, err) => {
this._cached[stopID] = [data, err];
this._fetchCached(stopID, cb);
this._keepUpdated(stopID, UPDATE_DELAY);
});
}
}
_keepUpdated(stopID, delay) {
//stopID = parseInt(stopID); // Any internal call should not be a string
this._timers[stopID] = setTimeout(() => {
this._fetch(stopID, (data, err) => {
this._cached[stopID] = [data, err];
if (err) {
return this._keepUpdated(stopID, UPDATE_DELAY_ERROR);
}
return this._keepUpdated(stopID, UPDATE_DELAY);
});
}, delay);
}
_fetch(stopID, cb) {
http.get(STOP_OPTIONS(stopID), (res) => {
var buff = "";
res.on("data", (chunk) => {
buff += chunk;
});
res.on("error", (err) => {
cb({}, err);
console.error(err);
});
res.on("end", () => {
try {
if (res.statusCode == 200) {
cb(JSON.parse(buff));
}
else {
cb({}, {
status: res.statusCode
});
console.error(buff, res.statusCode);
}
}
catch (err) {
cb({}, err);
console.error(err);
}
});
});
}
}
module.exports = ArrivalAPI;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment