Realtime Bus Feed Error with NodeJS

I am trying to get the real-time bus positions through the live-feed, but cannot get it to work.

I am using NodeJS with the gtfs-realtime-bindings library to decode the realtime bus GTFS feed. I have also tried to use protobufjs using the 2011 and 2015 versions of proto files but doesn’t work either.

The error I am consistently getting is this: “Illegal wire type of unknown field 1242 in Message”.

My full code is here:

var config = require('./buses-config.json');
var gtfsrb = require('gtfs-realtime-bindings');
var protobuf = require('protobufjs');

var request = require('request');
  var url = 'https://api.transport.nsw.gov.au/v1/gtfs/vehiclepos/buses';
  request({
    url: url,
    headers: { 'authorization':'apikey xxxxx' },
    method: 'GET'
  }, function (error, response, body) {
    console.log('Status', response.statusCode);
    console.log('Headers', JSON.stringify(response.headers));
    console.log('Reponse received', body);
	
    
    // 1: If I use this line, I get "Illegal argument: Not a valid base64 encoded string"
    var feed = gtfsrb.FeedMessage.decode(body);
	
    // 2: If I use this line, I get "Illegal wire type of unknown field 1242 in Message"
    var feed = gtfsrb.FeedMessage.decode(new Buffer(body, 'base64'));
	
	  
    // 3: If I use protobufjs, I still get "Illegal wire type for unknown field 1242 in Message .transit_realtime.FeedMessage#decode". I have tried both 2011 and 2015 versions of the proto files.
    var transit = protobuf.loadProtoFile("gtfs-realtime.proto").build("transit_realtime");
    var feed = transit.FeedMessage.decode(body);
    
    console.log(feed);
});

What am I doing wrong?

Hi,

Have you tried the file from Illegal value Error when decoding SydneyTrains GTFS data - #5 by yvonne.lee - Real-time Public Transport - Open Data - Transport for NSW forum at all?

Cheers,
Alistair

My colleague helped me to figure it out. The problem was that the data returned was in some weird format, so when we make a request, we needed to explicitly specify the encoding to null, like below:

...
request({
    url: url,
    headers: { 'authorization':'apikey xxxxx' },
    method: 'GET',
    encoding: null
  },
...

Can someone please explain why this works exactly? What’s the encoding used as the default for the returned value?

Also, can someone from the TfNSW / OpenData team update the documentation(s) to capture this?

This is something specific to your use of request package. See the docs on the encoding parameter (especially the note at the end):

encoding - Encoding to be used on setEncoding of response data. If null, the body is returned as a Buffer. Anything else (including the default value of undefined) will be passed as the encoding parameter to toString() (meaning this is effectively utf8 by default). (Note: if you expect binary data, you should set encoding: null.)

1 Like

Ah I see. Do you mean the code samples? I see the Node code sample doesn’t include the encoding parameter. Not sure they can include this for the binary APIs, and not include it for the text APIs. Also not sure where the best place to document this is, since it’s specific to Node. Maybe someone can update all the code samples to include the parameter? That’s probably the simplest solution.

Yeah, I meant code samples. I copied the Node.js code sample directly from the website (after you click the “submit” button) and that did not work. Yes, updating the code sample would be good.

Hi @jayen, @phiali, we’ll look at getting the code sample updated.

Thanks,
Alex

Thanks Alejandro.

I still get “TypeError: Cannot read property ‘decode’ of undefined” with following code
var requestSettings = {
method: ‘GET’,
url: ‘https://api.transport.nsw.gov.au/v1/gtfs/vehiclepos/buses?debug=true’,
//encoding: null,
proxy: ‘http://127.0.0.1:3128’,
rejectUnauthorized: false,
headers: {
‘Accept’: ‘text/plain’,
‘Authorization’: ‘apikey oEE3PvdBdfY22VrFbsq9iuaWE2FDVbmnuypp’
}
};
request(requestSettings, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log("Success :: ", body);
var feed = GtfsRealtimeBindings.FeedMessage.decode(body);
feed.entity.forEach(function(entity) {
if (entity.trip_update) {
console.log(entity.trip_update);
}
});
}
});

@jasmeetsehgal you shouldn’t use the GtfsRealtimeBindings package because TfNSW uses an extension to the GTFS proto.

I have made you a small repo that shows how I have used the api in node.

hope that helps

2 Likes

also written it in typescript on the ‘ts’ branch

While Matt is right, you should still be able to decode the message, just not every field will have a name.

From the error it looks like GtfsRealtimeBindings.FeedMessage didn’t load properly. Nothing TfNSW related and you’d probably have the same issue with the examples.