var fs = require('fs'); var Mustache = require('mustache'); var XML = require('pixl-xml'); var iconv = require('iconv-lite'); var httpreq = require('httpreq'); /// CONFIG var CITY = 'Braunschweig'; var STOPS = ['Ludwigstraße','Hamburger Straße']; var ENTRIES = 6; /// VARS var CACHED = []; var TEMPLATES = {}; fs.readFile('modules/bus/outer.mustache', 'utf-8', function (err, data) { TEMPLATES.outer = data; }); fs.readFile('modules/bus/inner.mustache', 'utf-8', function (err, data) { TEMPLATES.inner = data; }); /// FUNS function pad(n, width, z) { z = z || '0'; n = n + ''; return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; } function fetchData(stop, cb) { var url = "http://62.154.206.87/efaws2/default/XML_DM_REQUEST?sessionID=0&requestID=0&language=de&useRealtime=1&coordOutputFormat=WGS84[DD.ddddd]&locationServerActive=1&mode=direct&dmLineSelectionAll=1&depType=STOPEVENTS&useAllStops=1&command=null&type_dm=stop&name_dm="+CITY+' '+stop+"&mId=efa_rc2" httpreq.get(url, {binary: true}, function (err, res) { try { cb(XML.parse(iconv.decode(res.body, 'latin1'))); } catch(e) { } }); } function renderLine(line) { var image = ''; if (line.charAt(0) == "M") { image = 'metro.svg'; line = line.substr(1); } else if (line.length < 3) { image = 'tram.svg'; } else { image = 'bus.svg'; } return '<img src="/modules/bus/'+image+'"> '+line; } function getData(stop, count, cb) { fetchData(stop, function (data) { var deps = data.itdDepartureMonitorRequest.itdDepartureList.itdDeparture; cb(deps.slice(0, count).map(function (dep) { return { line: dep.itdServingLine.symbol, renderedLine: renderLine(dep.itdServingLine.symbol), dir: dep.itdServingLine.direction.replace(CITY, '').trim(), platform: dep.platform, mean: dep.itdServingLine.itdNoTrain.name, day: pad(dep.itdDateTime.itdDate.day,2), month: pad(dep.itdDateTime.itdDate.month,2), hour: pad(dep.itdDateTime.itdTime.hour,2), minute: pad(dep.itdDateTime.itdTime.minute,2) }; })); }); } function update(io, allStopsDoneCb) { var done = []; var context = []; var innerGetData = function (stop, i) { var ns = normalizeStop(stop); getData(stop, ENTRIES, function (deps) { try { context[i] = {stop: stop, normalizedStop: ns, deps: deps}; io.emit('bus.'+ns, Mustache.render(TEMPLATES.inner, context[i])); if (done.indexOf(stop) === -1) { done.push(stop); if (done.length === STOPS.length) { allStopsDoneCb(); } } CACHED = context; } catch (e) {console.log(e);} // calculate when to update next var d = new Date(); var hour = d.getHours(); var minute = d.getMinutes(); var depHour = deps[0].hour < hour ? deps[0].hour+24 : deps[0].hour; var diff = (depHour-hour)*60 + (deps[0].minute-minute); setTimeout(function () { innerGetData(stop, i); }, (diff * 60 + (60-d.getSeconds()) % 60) * 1000); }); } STOPS.forEach(function (stop, i) { innerGetData(stop, i); }); } function normalizeStop(stop) { return stop.replace(/[^a-zA-Z0-9_]/g,''); } module.exports = function (io) { update(io, function () { var pushToClient = function (sock) { sock.emit('bus', Mustache.render(TEMPLATES.outer, CACHED)); setTimeout(function () { for (var i in CACHED) { sock.emit('bus.'+CACHED[i].normalizedStop, Mustache.render(TEMPLATES.inner, CACHED[i])); } }, 3000); //wait a second to let the client process the outlets }; io.on('connect', pushToClient); pushToClient(io); }); }