Transport for London Unified API schedule

This flow uses the Unified TFL API to pull in train schedule data for a local London train station. It then extracts and filters out the next train times and destinations. The schedule data is then formatted and sent to an OLED screen powered by an Arduino compatible board via MQTT messaging.

More info on TFL API: https://api-portal.tfl.gov.uk/docs

##Complete write-up:

###http://www.internetoflego.com/train-schedule-display-2/

##Usage

An inject node will perform a GET request to the TFL service, where the msg.stationid specifies the station schedule

msg.url = "https://api.tfl.gov.uk/StopPoint/"+msg.stationid+"/arrivals";

The data will then be sent out using MQTT, to be received by the Arduino powered OLED display.

The flow also includes additional APIs to retrieve the formatted schedule on demand.

####http://yourserver.com:1880/trainschedule?station=910GLONFLDS

Forces an API lookup with the specified train station ID

Test APIs to see data

These URLs will look to the local flow context variable to display the most recent schedule

####http://yourserver.com:1880/trainjson

{"station":"London Fields Rail Station","schedule":[{"expected":0,"destination":"Enfield Town Rail Station"},{"expected":3,"destination":"Cheshunt Rail Station"},{"expected":18,"destination":"Enfield Town Rail Station"},{"expected":26,"destination":"Cheshunt Rail Station"},{"expected":33,"destination":"Enfield Town Rail Station"},{"expected":48,"destination":"Enfield Town Rail Station"},{"expected":63,"destination":"Cheshunt Rail Station"}]}

####http://yourserver.com:1880/traindisplay

London Fields Rail Station 
0min Cheshunt Rail Station 
11min Enfield Town Rail Station 1
9min Cheshunt Rail Station 
26min Enfield Town Rail Station 
41min Enfield Town Rail Station 
56min Cheshunt Rail Station 
71min Enfield Town Rail Station

#Note This flow requires Node-RED 0.13.0 to make use of the flow context variable.

Written by: Cory Guynn, 2016 www.InternetOfLEGO.com

[{"id":"e33ec540.1cc138","type":"ui_tab","z":"","name":"IoL","icon":"dashboard","order":"1"},{"id":"b1d8d4eb.4e2728","type":"mqtt-broker","z":"e60e9052.19f17","broker":"","port":"1883","clientid":"","usetls":false,"verifyservercert":true,"compatmode":true,"keepalive":"15","cleansession":true,"willTopic":"","willQos":"0","willRetain":"false","willPayload":"","birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":""},{"id":"4419e8c7.bbe618","type":"http request","z":"e60e9052.19f17","name":"API Call","method":"GET","ret":"txt","url":"","x":680,"y":120,"wires":[["9cb083cd.634f8","2ddf34e0.d220cc"]]},{"id":"4bf1e239.b40e1c","type":"inject","z":"e60e9052.19f17","name":"","topic":"","payload":"910GLONFLDS","payloadType":"string","repeat":"1","crontab":"","once":true,"x":140,"y":140,"wires":[["110734c1.eef8cb"]]},{"id":"9a4a5cb0.65b5a","type":"function","z":"e60e9052.19f17","name":"Request URL to TFL","func":"msg.stationid = msg.payload;\nmsg.url = \"https://api.tfl.gov.uk/StopPoint/\"+msg.stationid+\"/arrivals\";\nreturn msg;","outputs":1,"noerr":0,"x":500,"y":120,"wires":[["4419e8c7.bbe618"]]},{"id":"9cb083cd.634f8","type":"debug","z":"e60e9052.19f17","name":"TFL API response","active":true,"console":"false","complete":"payload","x":870,"y":120,"wires":[]},{"id":"9e12935e.61ed7","type":"debug","z":"e60e9052.19f17","name":"TFL Next Trains","active":true,"console":"false","complete":"payload","x":660,"y":220,"wires":[]},{"id":"2ddf34e0.d220cc","type":"json","z":"e60e9052.19f17","name":"","x":810,"y":160,"wires":[["2e361136.d1c9ee"]]},{"id":"b09a07d2.4f65f8","type":"http in","z":"e60e9052.19f17","name":"/trainschedule?station=910GLONFLDS","url":"/trainschedule","method":"get","swaggerDoc":"","x":190,"y":60,"wires":[["aca72f6.f5358d"]]},{"id":"aca72f6.f5358d","type":"function","z":"e60e9052.19f17","name":"request","func":"//msg.payload = \"910GLONFLDS\";\nmsg.payload = msg.req.station || \"910GLONFLDS\" ;\nreturn msg;","outputs":1,"noerr":0,"x":460,"y":60,"wires":[["9a4a5cb0.65b5a","51f23f28.ae0dc"]]},{"id":"f628b4f.f09d748","type":"http response","z":"e60e9052.19f17","name":"","x":630,"y":260,"wires":[]},{"id":"6b14d440.94eb2c","type":"comment","z":"e60e9052.19f17","name":"TFL Schedule","info":"","x":90,"y":20,"wires":[]},{"id":"4e1f5b18.b1e0a4","type":"comment","z":"e60e9052.19f17","name":"Sort Outbound Trains","info":"","x":120,"y":220,"wires":[]},{"id":"2e361136.d1c9ee","type":"function","z":"e60e9052.19f17","name":"Outbound Schedule new schema","func":"var tfl = msg.payload;\nvar trains = {};\nvar station;\nvar expected;\nvar nextTrains = [];\n\n\n// check for valid data first\nif (msg.statusCode == 200) {\n    //if(tfl[0] !== undefined){\n    if(tfl[0]){\n        station = tfl[0].stationName;\n\n        // sort schedule\n        tfl.sort(function(a,b){\n      \t    return (a.timeToStation - b.timeToStation);\n    \t});\n        \n        // iterate through all schedule records and save required data\n        for (var i = 0; i < tfl.length; i++) {\n          if(tfl[i].direction == 'outbound'){\n          \tnextTrains.push({\n          \t    'expected': (tfl[i].timeToStation)/60,\n          \t    'destination': tfl[i].destinationName\n          \t});\n          } \n        }\n    }else{\n        // no schedule received\n        station = msg.stationid; // use station id as default\n        nextTrains.push({\n            'expected': 0,\n          \t'destination': \"Out of Service\"\n        })\n    }\n    \n    trains.station = station;\n    trains.schedule = nextTrains;\n}\n\n// display and send schedule data\nconsole.log(\"outbound schedule new schema > \");\nconsole.log(util.inspect(trains, false, null));\nmsg.payload = trains;\nflow.set('trainschedule', msg.payload); // save for flow use\nreturn msg;","outputs":1,"noerr":0,"x":320,"y":260,"wires":[["9e12935e.61ed7","e9321505.16cde8","54451966.abbae8","f628b4f.f09d748"]]},{"id":"b4b2a289.4b4d6","type":"mqtt out","z":"e60e9052.19f17","name":"","topic":"","qos":"","retain":"","broker":"b1d8d4eb.4e2728","x":615.5,"y":520,"wires":[]},{"id":"e9321505.16cde8","type":"function","z":"e60e9052.19f17","name":"Format to MQTT display string","func":"var station = msg.payload.station;\nvar schedule = msg.payload.schedule;\nvar destination;\nvar split;\nmsg.topic = \"/trainschedule/\" + msg.stationid;\n\nif (schedule[0].destination == \"Out of Service\"){\n    destination = schedule[0].destination;\n    //destination = \"Out of Service\";\n    msg.payload = destination;\n    return msg;\n}else{\n    // Split the string and only use the first two words of each value\n    split = station.split(\" \");\n    station = split[0] +\" \"+ split[1] + \"\\n\\n\"; \n    msg.payload = station;\n    for(var x = 0; x < schedule.length; x++){\n        split = schedule[x].destination.split(\" \");\n        destination = split[0] +\" \"+ split[1];\n        msg.payload += pad(schedule[x].expected) + \"m\" + \"  \" + destination + \"\\n\";\n    }\n    return msg;\n}\n\n\nfunction pad(n) {\n    return (n < 10) ? (\"0\" + n) : n;\n}","outputs":1,"noerr":0,"x":310.5,"y":493,"wires":[["b4b2a289.4b4d6","e1254324.1edac"]]},{"id":"f91fdd8f.06e02","type":"mqtt in","z":"e60e9052.19f17","name":"","topic":"#","broker":"b1d8d4eb.4e2728","x":88.5,"y":637,"wires":[["c5795b82.3a86a8"]]},{"id":"c5795b82.3a86a8","type":"debug","z":"e60e9052.19f17","name":"MQTT #","active":false,"console":"false","complete":"payload","x":247.5,"y":637,"wires":[]},{"id":"56e7e2e7.a9181c","type":"comment","z":"e60e9052.19f17","name":"Schedule Display","info":"","x":103,"y":434,"wires":[]},{"id":"a4e58e24.5b1a7","type":"comment","z":"e60e9052.19f17","name":"MQTT Monitor","info":"","x":95.5,"y":601,"wires":[]},{"id":"110734c1.eef8cb","type":"delay","z":"e60e9052.19f17","name":"","pauseType":"rate","timeout":"30","timeoutUnits":"seconds","rate":"1","rateUnits":"minute","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":260,"y":180,"wires":[["9a4a5cb0.65b5a"]]},{"id":"e1254324.1edac","type":"debug","z":"e60e9052.19f17","name":"MQTT Format","active":true,"console":"false","complete":"payload","x":640,"y":580,"wires":[]},{"id":"12aefeac.ed5101","type":"comment","z":"e60e9052.19f17","name":"MQTT topic /trainschedule/stationid","info":"stationid is inherited from inject","x":660,"y":460,"wires":[]},{"id":"54451966.abbae8","type":"ui_template","z":"e60e9052.19f17","tab":"e33ec540.1cc138","name":"Station","group":"Train Schedule","order":1,"format":"{{msg.payload.station}}\n<ul>\n  <li ng-repeat=\"x in msg.payload.schedule\">\n  {{ x.expected + 'min, ' + x.destination }}</li>\n</ul>\n","storeOutMessages":true,"fwdInMessages":false,"x":640,"y":300,"wires":[[]]},{"id":"51f23f28.ae0dc","type":"debug","z":"e60e9052.19f17","name":"Train Schedule request","active":true,"console":"false","complete":"payload","x":690,"y":60,"wires":[]},{"id":"76b2b9d5.894d48","type":"http in","z":"e60e9052.19f17","name":"","url":"/trainjson","method":"get","swaggerDoc":"","x":110,"y":760,"wires":[["d7a9c399.28564"]]},{"id":"c3072bfd.3cf8d8","type":"http response","z":"e60e9052.19f17","name":"","x":630,"y":760,"wires":[]},{"id":"d7a9c399.28564","type":"function","z":"e60e9052.19f17","name":"","func":"msg.payload = flow.get('trainschedule');\nreturn msg;","outputs":1,"noerr":0,"x":270,"y":760,"wires":[["c3072bfd.3cf8d8"]]},{"id":"16456291.e9ba9d","type":"http in","z":"e60e9052.19f17","name":"","url":"/traindisplay","method":"get","swaggerDoc":"","x":120,"y":800,"wires":[["1ffadf81.e0052"]]},{"id":"aafb6bcf.550498","type":"http response","z":"e60e9052.19f17","name":"","x":630,"y":800,"wires":[]},{"id":"1ffadf81.e0052","type":"function","z":"e60e9052.19f17","name":"","func":"msg.payload = flow.get('trainschedule');\nreturn msg;","outputs":1,"noerr":0,"x":270,"y":800,"wires":[["487678b9.b78988"]]},{"id":"487678b9.b78988","type":"template","z":"e60e9052.19f17","name":"Format Screen","field":"payload","fieldType":"msg","format":"handlebars","template":"{{payload.station}}\n<br>\n{{#payload.schedule}}\n    {{expected}}min  {{destination}}\n{{/payload.schedule}}\n\n\n","x":460,"y":800,"wires":[["aafb6bcf.550498"]]},{"id":"6f8011f5.907ff","type":"comment","z":"e60e9052.19f17","name":"API Access","info":"","x":90,"y":720,"wires":[]}]
dexterlabora

Flow Info

created 1 year, 2 months ago

Node Types

Core
  • comment (x6)
  • debug (x5)
  • delay (x1)
  • function (x6)
  • http in (x3)
  • http request (x1)
  • http response (x3)
  • inject (x1)
  • json (x1)
  • mqtt in (x1)
  • mqtt out (x1)
  • mqtt-broker (x1)
  • template (x1)
Other
  • ui_tab (x1)
  • ui_template (x1)

Tags

  • mqtt
  • lego
  • tfl
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option