Google Map With BART Stations Using Websockets

This flow adds an HTTP endpoint called /mapstations to your Node-RED instance that when hit returns a Google Map with pins for all the BART stations in San Francisco.

The flow works by using a template node to return some HTML and Javascript to the browser that renders the Google Map and then makes a websocket request to get all the BART stations. When the websocket request is received an HTTP request is made to the BART API to fetch the the station data. The XML returned by the BART API is converted to JSON and returned back to the websocket. The JavaScript returned by the template node parses the JSON object from the websocket and creates a pin for each station according to the GPS coordinates returned by the BART API.

[{"id":"13257eec.669069","type":"websocket-listener","path":"/ws/stations","wholemsg":"false"},{"id":"657ffd47.1eeaac","type":"http in","name":"","url":"/mapstations","method":"get","x":115,"y":97,"z":"7ce797c4.7cd3f8","wires":[["4d6eafc2.b04bd"]]},{"id":"c374d4a.6904ca8","type":"http response","name":"","x":464,"y":94,"z":"7ce797c4.7cd3f8","wires":[]},{"id":"dac12350.5d931","type":"http request","name":"","method":"GET","url":"","x":268,"y":189,"z":"7ce797c4.7cd3f8","wires":[["9ab7b248.4897d"]]},{"id":"9ab7b248.4897d","type":"xml","name":"","x":421,"y":189,"z":"7ce797c4.7cd3f8","wires":[["92c36729.42acf8"]]},{"id":"4d6eafc2.b04bd","type":"template","name":"","field":"payload","template":"<!DOCTYPE html>\n<html>\n  <head>\n    <meta name=\"viewport\" content=\"initial-scale=1.0, user-scalable=no\">\n    <meta charset=\"utf-8\">\n    <title>Bart Stations</title>\n    <style>\n      html, body, #map-canvas {\n        height: 100%;\n        margin: 0px;\n        padding: 0px\n      }\n    </style>\n    <script src=\"\"></script>\n    <script>\n\t\tfunction initialize() {\n\t\t  var myLatlng = new google.maps.LatLng(37.765062,-122.419694);\n\t\t  var mapOptions = {\n\t\t    zoom: 10,\n\t\t    center: myLatlng\n\t\t  };\n\t\t  var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);\n\t\t  \n\t\t  var loc = window.location;\n          if (loc.protocol === \"https:\") {\n            newUri = \"wss:\";\n          } else {\n            newUri = \"ws:\";\n          }\n          newUri += \"//\" + + \"/ws/stations\";\n\t\t  \n\t\t  \n\t\t  var sock = new WebSocket(newUri);\n\t\t  sock.onopen = function(){ \n\t\t    console.log(\"Connected websocket\");\n\t\t    console.log(\"Sending ping..\");\n\t\t\tsock.send(\"Ping!\");\n\t\t    console.log(\"Ping sent..\");\n\t\t  };\n\t\t  sock.onerror = function(){ console.log(\"Websocket error\"); };\n\t\t  sock.onmessage = function(evt){\n\t\t    var stationData = JSON.parse(;\n\t\t    var stations = stationData.root.stations[0].station;\n\t\t\tfor(var i = 0; i < stations.length; i++) {\n\t\t\t  var station = stations[i];\n              var marker = new google.maps.Marker({\n\t\t\t    position: new google.maps.LatLng(station.gtfs_latitude[0],station.gtfs_longitude[0]),\n\t\t\t    map: map,\n\t\t\t    animation: google.maps.Animation.DROP,\n\t\t\t    title:[0]\n\t\t\t  });\n\t\t\t  \n\t\t\t}\n\t\t  };\n\t\t};\n\t\t\n\t\tgoogle.maps.event.addDomListener(window, 'load', initialize);\n\n    </script>\n  </head>\n  <body>\n    <div id=\"map-canvas\"></div>\n  </body>\n</html>","x":299,"y":96,"z":"7ce797c4.7cd3f8","wires":[["c374d4a.6904ca8"]]},{"id":"70bcbb30.ebad6c","type":"websocket in","name":"","server":"13257eec.669069","x":95,"y":190,"z":"7ce797c4.7cd3f8","wires":[["dac12350.5d931"]]},{"id":"92c36729.42acf8","type":"websocket out","name":"","server":"13257eec.669069","x":606,"y":189,"z":"7ce797c4.7cd3f8","wires":[]}]

Flow Info

created 2 years, 4 months ago

Node Types

  • http in (x1)
  • http request (x1)
  • http response (x1)
  • template (x1)
  • websocket in (x1)
  • websocket out (x1)
  • websocket-listener (x1)
  • xml (x1)


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