├── .gitignore ├── app.js ├── .gitattributes ├── package.json ├── routes └── main.js ├── README.md └── my_modules ├── trainData.js └── parseData.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | Procfile 3 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | 3 | var app = express(); 4 | 5 | require('./routes/main.js')(app); 6 | 7 | 8 | var port = Number(process.env.PORT || 5000); 9 | app.listen(port, function() { 10 | console.log("Listening on " + port); 11 | }); -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BAtrainAPIV2", 3 | "version": "0.0.0", 4 | "description": "Trains of Buenos Aires API", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "dependencies": { 10 | "express": "*", 11 | "request": "*", 12 | "logfmt": "~0.23.0" 13 | }, 14 | "engines": { 15 | "node": "0.10.x" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "github.com/fmtoffolo/BAtrainAPIV2" 20 | }, 21 | "author": "Fernando Toffolo", 22 | "license": "BSD-2-Clause" 23 | } -------------------------------------------------------------------------------- /routes/main.js: -------------------------------------------------------------------------------- 1 | var trainData = require('../my_modules/trainData'); 2 | var parseData = require('../my_modules/parseData'); 3 | 4 | module.exports = function(app) { 5 | app.get('/:ramal', function(req, res) { 6 | trainData.getTrainData(req.params.ramal, function(err, ramal, body) { 7 | 8 | if (!err) { 9 | console.log('got data ' + ramal); 10 | parseData.parseNow(ramal, body, function(err, body) { 11 | if (!err) { 12 | res.jsonp(body); 13 | } else { 14 | res.json(err.message); 15 | } 16 | }); 17 | } else { 18 | res.json(err.message); 19 | } 20 | 21 | }); 22 | }); 23 | app.get('/', function(req, res) { 24 | res.json('Invalid query. Please try: "laplata", "tigre", "mitre", "jlsuarez" or "moreno"') 25 | }) 26 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #BAtrainAPI 2 | 3 | ##Una API para los trenes en vivo de Buenos Aires usando nodeJS. 4 | 5 | Devuelve un JSON con la cantidad de trenes en circulación, las coordenadas de cada uno, velocidad y algunos datos más. 6 | 7 | ``` 8 | { 9 | "line": "mitre", 10 | "ramal": "tigre", 11 | "timeStamp": "Sat Mar 15 2014 00:03:06 GMT+0000 (UTC)", 12 | "trainsInCirculation": 6, 13 | "formations": [ 14 | { 15 | "destination": "tigre", 16 | "id": 2005, 17 | "latitude": -34.583901, 18 | "longitude": -58.385589, 19 | "ramal": 5, 20 | "speed": 37, 21 | "status": 1, 22 | "movingStatus": 1, 23 | "trainID": 3111, 24 | "lineOrden": 63 25 | }, 26 | ``` 27 | 28 | Aca sigue el array con todos los trenes. 29 | 30 | Obtiene la información de la misma url que los mapas en vivo, pero parsea el string que devuelve y arma un json legible. 31 | 32 | ##Instalación 33 | - Clona el repository 34 | - 'npm install' deberia instalar todas las dependencies y salir andando ya que creo que el package.js esta ok. 35 | - node app.js 36 | 37 | 38 | ##Como usarlo 39 | Las lineas que andan por ahora son: 40 | - tigre 41 | - mitre 42 | - jlsuarez 43 | - moreno 44 | - laplata 45 | 46 | Agregar el nombre de la line detras de la base url y listo. 47 | 48 | ej: http://localhost:5000/tigre 49 | 50 | ##JSONP para el front end 51 | agregale un callback y listo 52 | ej: http://localhost:5000/tigre?callback=yourfunction 53 | 54 | **Por ahora no usa CORS. Pero tiene jsonp.** 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /my_modules/trainData.js: -------------------------------------------------------------------------------- 1 | var request = require('request'); 2 | 3 | 4 | var randomStringGenerator = function() { 5 | var charSet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'; 6 | var stringLength = 16; 7 | var randomString = ''; 8 | for (var i = 0; i < stringLength; i++) { 9 | var randomChar = Math.floor(Math.random() * charSet.length); 10 | randomString += charSet.substring(randomChar, randomChar + 1); 11 | } 12 | return randomString; 13 | }; 14 | 15 | 16 | var getRawData = function(ramal, callback) { 17 | var key = 'v%23v%23QTUtWp%23MpWRy80Q0knTE10I30kj%23FNyZ'; 18 | var url = 'http://trenes.mininterior.gov.ar/v2_pg/mapas/ajax_posiciones.php?'; 19 | var rnd = randomStringGenerator(); 20 | var queryParams = { //create query parameters object 21 | rnd: rnd, 22 | key: key, 23 | ramal: 0 24 | }; 25 | 26 | var ramalData = [{ 27 | name: 'laplata', 28 | id: 11 29 | }, { 30 | name: 'tigre', 31 | id: 5 32 | }, { 33 | name: 'mitre', 34 | id: 7 35 | }, { 36 | name: 'jlsuarez', 37 | id: 9 38 | }, { 39 | name: 'moreno', 40 | id: 1 41 | }]; 42 | 43 | 44 | //set ramal to corresponding id 45 | for (var i = 0; i < ramalData.length; i++) { 46 | if (ramalData[i].name === ramal) { 47 | queryParams.ramal = ramalData[i].id; 48 | } 49 | } 50 | 51 | //if ramal non existant, throw error 52 | if (queryParams.ramal === 0) { 53 | callback(new Error('Not a valid line. Please try: "laplata", "tigre", "mitre", "jlsuarez" or "moreno"')); 54 | } else { 55 | //make request 56 | request({ 57 | url: url, 58 | qs: queryParams, 59 | headers: { 60 | 'Referer': 'http://trenes.mininterior.gov.ar/v2_pg/mapas/mitre/mapa_mitre_tigre.php' 61 | } 62 | }, function(error, response, body) { 63 | console.log('request done'); 64 | if (!error && response.statusCode === 200) { 65 | callback(null, ramal, JSON.parse(body)); 66 | } else { 67 | callback(new Error('error message: third party connection error')); 68 | } 69 | }); 70 | } 71 | }; 72 | 73 | exports.getTrainData = getRawData; 74 | -------------------------------------------------------------------------------- /my_modules/parseData.js: -------------------------------------------------------------------------------- 1 | var parseData = function(ramal, body, callback) { 2 | var rawObject = body; 3 | var date = '' + new Date(); 4 | 5 | 6 | //create object to store train data 7 | var trainData = { 8 | line: '', 9 | ramal: ramal, 10 | timeStamp: date, 11 | trainsInCirculation: '', 12 | formations: [] 13 | }; 14 | 15 | //add line name according to line name. change name with spaces so it looks pretty 16 | switch (ramal) { 17 | case 'tigre': 18 | trainData.line = 'mitre'; 19 | break; 20 | case 'mitre': 21 | trainData.line = 'mitre'; 22 | break; 23 | case 'jlsuarez': 24 | trainData.line = 'mitre'; 25 | trainData.ramal = 'jose leon suarez' 26 | break; 27 | case 'moreno': 28 | trainData.line = 'sarmiento'; 29 | break; 30 | case 'laplata': 31 | trainData.line = 'roca'; 32 | trainData.ramal = 'la plata'; 33 | break; 34 | } 35 | 36 | for (var i = 0; i < rawObject.length; i++) { 37 | var tempTrainData = { 38 | destination: '', 39 | id: rawObject[i].formacion_id, 40 | latitude: parseFloat(rawObject[i].latitud), 41 | longitude: parseFloat(rawObject[i].longitud), 42 | ramal: rawObject[i].ramal, 43 | speed: parseInt(rawObject[i].velocidad), 44 | status: rawObject[i].estado_servicio, 45 | movingStatus: rawObject[i].estado_mov, 46 | trainID: rawObject[i].tren, 47 | lineOrden: rawObject[i].orden_ramal 48 | }; 49 | 50 | //acording to ramal number, set correct destination 51 | switch (rawObject[i].ramal) { 52 | case 1: 53 | tempTrainData.destination = 'moreno'; 54 | break; 55 | case 2: 56 | tempTrainData.destination = 'once'; 57 | break; 58 | case 5: 59 | tempTrainData.destination = 'tigre'; 60 | break; 61 | case 6: 62 | tempTrainData.destination = 'retiro'; 63 | break; 64 | case 7: 65 | tempTrainData.destination = 'mitre'; 66 | break; 67 | case 8: 68 | tempTrainData.destination = 'retiro'; 69 | break; 70 | case 9: 71 | tempTrainData.destination = 'jose leon suarez'; 72 | break; 73 | case 10: 74 | tempTrainData.destination = 'retiro'; 75 | break; 76 | case 11: 77 | tempTrainData.destination = 'la plata'; 78 | break; 79 | case 12: 80 | tempTrainData.destination = 'consitucion'; 81 | break; 82 | } 83 | 84 | trainData.formations.push(tempTrainData); 85 | } 86 | 87 | trainData.trainsInCirculation = trainData.formations.length; 88 | 89 | callback(null, trainData); 90 | 91 | }; 92 | 93 | exports.parseNow = parseData; --------------------------------------------------------------------------------