Skip to content

Commit

Permalink
Add support for Greater Manchester realtime feeds
Browse files Browse the repository at this point in the history
  • Loading branch information
juyrjola committed Mar 23, 2013
1 parent 1985606 commit d5d96dd
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 46 deletions.
59 changes: 59 additions & 0 deletions src/helsinki.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
net = require 'net'
carrier = require 'carrier'

col_names = [
"id", "name", "type", "ip", "lat", "lng", "speed", "bearing",
"acceleration", "gps_time_difference", "unix_epoch_gps_time", "low_floor", "route", "direction",
"departure", "departure_time", "departure_stars_in", "distance_from_start", "snapped_lat", "snapped_lng",
"snapped_bearing", "next_stop_index", "on_stop", "difference_from_timetable"
]

class HSLClient
constructor: (@callback, @args) ->

connect: ->
@client = net.connect 8080, '83.145.232.209'
@client.on 'connect', (conn) =>
console.log "HSLClient connected"
@client.write '&okffin;tuusula1 onroute:1&'

line_handler = (line) =>
@.handle_line line
@carrier = carrier.carry @client
@carrier.on 'line', line_handler

handle_line: (line) ->
cols = line.split ';'
if cols.length < 10
return
info = {}
for n, idx in col_names
info[n] = cols[idx]
# Skip line if no coordinates supplied
if info.lat == '0' or info.lng == '0'
return
timestamp = (parseInt info.unix_epoch_gps_time) / 1000
if timestamp <= 0
return
if not info.route
return
out_info =
vehicle:
id: info.id
label: info.name
trip:
route: info.route
direction: info.direction
position:
latitude: parseFloat info.lat
longitude: parseFloat info.lng
bearing: parseFloat info.bearing
odometer: parseFloat info.distance_from_start
speed: (parseFloat info.speed) / 3.6
timestamp: (parseInt info.unix_epoch_gps_time) / 1000
route = info.route.replace " ", "_"
vehicle_id = out_info.vehicle.id.replace " ", "_"
path = "/location/helsinki/#{route}/#{vehicle_id}"
@callback path, out_info, @args

module.exports.HSLClient = HSLClient
80 changes: 80 additions & 0 deletions src/manchester.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
http = require 'http'


class TfGMClient
constructor: (@callback, @args) ->
@dev_key = 'e5541db9-e410-45d0-8481-08adf0a193ce'
@app_key = '2c4abc94-240f-490e-bb86-880471640b37'
@routes =
'MET3':
gtfs_name: 'GMN: 3:C:'
'MET2':
gtfs_name: 'GMN: 2:C:'
'MET1':
gtfs_name: 'GMN: 1:C:'
@poll_delay = 5

set_poll_timer: (route_name, is_error) ->
route = @routes[route_name]
if route.timeout
clearTimeout route.timeout
timeout_handler = =>
route.timeout = null
@.poll_route route_name
if is_error
delay = @poll_delay * 10
else
delay = @poll_delay
delay *= 1000
route.timeout = setTimeout timeout_handler, delay

update_location: (route_name, data) ->
out_info =
vehicle:
id: data['Registration']
trip:
route: @routes[route_name].gtfs_name
timestamp: data['LastUpdated']
position:
latitude: data['Latitude']
longitude: data['Longitude']
bearing: data['Heading']
route = out_info.trip.route.replace(/\ /g, "_").replace(/:/g, '-')
path = "/location/manchester/#{route}/#{out_info.vehicle.id}"
@callback path, out_info, @args

poll_route: (route_name) ->
route = @routes[route_name]
opts =
host: 'opendata.tfgm.com'
path: "/api/routes/#{route_name}/buses"
headers:
'DevKey': @dev_key
'AppKey': @app_key

route.req = http.get opts, (resp) =>
data = ''
route.req = null
resp.on 'data', (chunk) =>
data += chunk
resp.on 'end', (chunk) =>
objs = JSON.parse data
for vehicle in objs
if not vehicle['HasFix']
continue
@.update_location route_name, vehicle
@.set_poll_timer route_name, false
route.req.on 'error', (e) =>
console.log "polling failed: " + e.message
route.req = null
@.set_poll_timer route_name, true

connect: ->
for route_name of @routes
@.poll_route route_name

#cli = new TfGMClient
#cli.poll_route('MET1')
#cli.connect()

module.exports.TfGMClient = TfGMClient
57 changes: 11 additions & 46 deletions src/server.coffee
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
http = require 'http'
faye = require 'faye'
net = require 'net'
carrier = require 'carrier'

bayeux = new faye.NodeAdapter
mount: '/faye', timeout: 45
Expand All @@ -13,55 +11,22 @@ server = http.createServer (request, response) ->
response.end()

bayeux.attach server
server.bayeux = bayeux
module.exports = server

bayeux.bind 'handshake', (client_id) ->
console.log "client " + client_id + " connected"

bay_client = bayeux.getClient()
client = bayeux.getClient()

hsl_client = net.connect 8080, '83.145.232.209'
hsl_client.write '&okffin;tuusula1 type:1&'
handle_event = (path, msg) ->
console.log path
client.publish path, msg

col_names = [
"id", "name", "type", "ip", "lat", "lng", "speed", "bearing",
"acceleration", "gps_time_difference", "unix_epoch_gps_time", "low_floor", "route", "direction",
"departure", "departure_time", "departure_stars_in", "distance_from_start", "snapped_lat", "snapped_lng",
"snapped_bearing", "next_stop_index", "on_stop", "difference_from_timetable"
]
helsinki = require './helsinki.js'
manchester = require './manchester.js'

event_carrier = carrier.carry hsl_client
event_carrier.on 'line', (line) ->
cols = line.split ';'
if cols.length < 10
return
info = {}
for n, idx in col_names
info[n] = cols[idx]
# Skip line if no coordinates supplied
if info.lat == '0' or info.lng == '0'
return
timestamp = (parseInt info.unix_epoch_gps_time) / 1000
if timestamp <= 0
return
if not info.route
return
out_info =
vehicle:
id: info.id
label: info.name
trip:
route: info.route
direction: info.direction
position:
latitude: parseFloat info.lat
longtitude: parseFloat info.lng
bearing: parseFloat info.bearing
odometer: parseFloat info.distance_from_start
speed: (parseFloat info.speed) / 3.6
timestamp: (parseInt info.unix_epoch_gps_time) / 1000
#console.log info
path = "/location/helsinki/#{out_info.trip.route}/#{out_info.vehicle.id}"
#console.log path
#console.log out_info
bay_client.publish path, out_info
hel_client = new helsinki.HSLClient handle_event
hel_client.connect()
man_client = new manchester.TfGMClient handle_event
man_client.connect()

0 comments on commit d5d96dd

Please sign in to comment.