tracktracker/src/tam/sources/tam.js

105 lines
3.4 KiB
JavaScript

const csv = require("csv-parse");
const axios = require("axios");
const { snakeToCamelCase, unzipFile } = require("../../util");
/**
* Data available for each passing of a vehicle at a station.
*
* See also <http://data.montpellier3m.fr/node/10733/download>.
* @typedef {Object} Passing
* @property {string} course Identifier of the overall trip of the same vehicle
* from one end of the route to another (unique for the day).
* @property {string} stopCode Unused internal stop identifier.
* @property {string} stopId Unique network identifier for the station at
* which the vehicle will pass (same id as in GTFS).
* @property {string} routeShortName Transport line number.
* @property {string} tripHeadsign Name of the final stop of this trip.
* @property {string} directionId Route identifier inside the line.
* @property {string} departureTime Theoretical time at which the
* vehicle will depart the stop (HH:MM:SS format).
* @property {string} isTheorical (sic) Whether the arrival time is only
* a theoretical information.
* @property {string} delaySec Number of seconds before the vehicle arrives
* at the station.
* @property {string} destArCode Unique network identifier for the final
* stop of this trip.
*/
const realtimeEndpoint = "http://data.montpellier3m.fr/node/10732/download";
/**
* Fetch real time passings of vehicles across the network.
* @yields {{{lastUpdate: number, nextUpdate: number}|Passing}} First value
* is an object containing the time of last update and the time of next
* update of this information. Next values are informations about each vehicle
* passing.
*/
const fetchRealtime = async function *() {
const res = await axios.get(realtimeEndpoint, {
responseType: "stream"
});
const lastUpdate = new Date(res.headers["last-modified"]).getTime();
const nextUpdate = lastUpdate + 65 * 1000;
yield { lastUpdate, nextUpdate };
const parser = res.data.pipe(csv({
delimiter: ";",
columns: header => header.map(snakeToCamelCase)
}));
for await (const passing of parser) {
yield passing;
}
};
exports.fetchRealtime = fetchRealtime;
const theoreticalEndpoint = "http://data.montpellier3m.fr/node/10731/download";
/**
* Fetch theoretical passings for the current day across the network.
* @yields {{{lastUpdate: number, nextUpdate: number}|Passing}} First value
* is an object containing the time of last update and the time of next
* update of this information. Next values are informations about each vehicle
* passing.
*/
const fetchTheoretical = async function *() {
const res = await axios.get(theoreticalEndpoint, {
responseType: "stream"
});
const lastUpdate = new Date();
if (lastUpdate.getHours() < 4) {
lastUpdate.setDate(lastUpdate.getDate() - 1);
}
lastUpdate.setHours(4);
lastUpdate.setMinutes(0);
lastUpdate.setSeconds(0);
lastUpdate.setMilliseconds(0);
const nextUpdate = new Date(lastUpdate);
nextUpdate.setDate(nextUpdate.getDate() + 1);
yield {
lastUpdate: lastUpdate.getTime(),
nextUpdate: nextUpdate.getTime()
};
const stream = await unzipFile(res.data, "offre_du_jour.csv");
const parser = stream.pipe(csv({
delimiter: ";",
columns: header => header.map(snakeToCamelCase)
}));
for await (const passing of parser) {
yield passing;
}
};
exports.fetchTheoretical = fetchTheoretical;