как вы декодируете protobufs gtfs в узле

Я пытаюсь использовать https://github.com/dcodeIO/ProtoBuf.js для анализа триментов. данные gtf.

Вот код, который у меня есть до сих пор, он правильно анализирует файл .proto и создает билдер и имеет все ожидаемые свойства и методы, он выдает ошибку, когда я пытаюсь декодировать любые данные с его помощью.

Error: Data must be corrupt: Buffer overrun

файл прототипа взят с сайта https://developers.google.com/transit/gtfs-realtime/gtfs-realtime-proto

var ProtoBuf = require('protobufjs')
  , request = require('request')

var transit = ProtoBuf.protoFromFile('gtfs-realtime.proto').build('transit_realtime')

request('http://developer.trimet.org/ws/V1/FeedSpecAlerts/?appID=618F30BB3062F39AF24AED9EC', parse)

function parse(err, res, body) {
  try {
    console.log(transit.FeedMessage.decode(res.body))
  } catch(e) {
    console.log(e)
  }
}

Благодаря Брайану Феррису я смог разобрать первую часть заголовка gtfs_realtime_version: "1", но синтаксический анализатор не работает со следующим компонентом (отметка времени uint64)

Благодаря


person MiGnH    schedule 30.08.2013    source источник
comment
Я использую res.body, потому что это буфер, а тело, которое передается, представляет собой строку.   -  person MiGnH    schedule 30.08.2013
comment
ты уже разобрался с этим вопросом? Я получаю точно такую ​​​​же проблему, глядя на ленту gtfs-r метро MTA.   -  person Alex Muro    schedule 08.11.2013
comment
нет, извините, я сдался, в то время я пришел к выводу, что парсеры js не соответствуют спецификациям, но, возможно, некоторые из них были обновлены с тех пор   -  person MiGnH    schedule 14.01.2014


Ответы (5)


Я продолжал находить ваш вопрос, когда искал ту же проблему, что и у вас, и, надеюсь, я смогу помочь кому-то еще. После поиска в Интернете намного дольше, чем я должен был, я придумал кое-что, что работает. Я не совсем понимал данные, пока не расшифровал рабочий канал.

В значительной степени кажется, что это связано с тем, как данные считываются. Я не человек NodeJS, поэтому я не знаю, почему, но это зависит от того, как данные читаются с помощью http, а не request для декодирования. Я не мог заставить тот же метод работать с request для данных.

Часть этого я нашел из https://github.com/dcodeIO/ProtoBuf.js/wiki/How-to-read-binary-data-in-the-browser-or-under-node.js.%3F но я еще не совсем понял, как использовать protobufjs, поэтому привожу здесь рабочий пример для других. Надеюсь, поможет.

var ProtoBuf = require('protobufjs');
var http = require("http");

// create a protobuf decoder
var transit = ProtoBuf.protoFromFile('gtfs-realtime.proto').build('transit_realtime');
// your protobuf binary feed URL
var feedUrl = "...";    

// HTTP GET the binary feed
http.get(feedUrl, parse);

// process the feed
function parse(res) {
    // gather the data chunks into a list
    var data = [];
    res.on("data", function(chunk) {
        data.push(chunk);
    });
    res.on("end", function() {
        // merge the data to one buffer, since it's in a list
        data = Buffer.concat(data);
        // create a FeedMessage object by decooding the data with the protobuf object
        var msg = transit.FeedMessage.decode(data);
        // do whatever with the object
        console.log(msg);
    }); 
});
person Kirk    schedule 08.09.2014

Я смог заставить это работать (во всяком случае, с нью-йоркскими каналами MTA), заставив модуль request иметь нулевую кодировку, таким образом гарантируя, что он возвращает буфер вместо строки. Вот так:

request({
    url: 'http://developer.trimet.org/ws/V1/FeedSpecAlerts/?appID=618F30BB3062F39AF24AED9EC'
    encoding: null
}, parse)

Тогда синтаксический анализ работает нормально.

person Alastair    schedule 03.07.2014

Со страницы разработчиков Google по адресу developers.google.com/transit/gtfs-realtime. /образцы кода. Google теперь сделал доступным модуль Node.js npm, чтобы упростить задачу:

npm install gtfs-realtime-bindings

Вот фрагмент кода Google ( Лицензия Apache 2.0)

var GtfsRealtimeBindings = require('gtfs-realtime-bindings');
var request = require('request');

var requestSettings = {
  method: 'GET',
  url: 'URL OF YOUR GTFS-REALTIME SOURCE GOES HERE',
  encoding: null
};
request(requestSettings, function (error, response, body) {
  if (!error && response.statusCode == 200) {
    var feed = GtfsRealtimeBindings.FeedMessage.decode(body);
    feed.entity.forEach(function(entity) {
      if (entity.trip_update) {
        console.log(entity.trip_update);
      }
    });
  }
});
person JJones    schedule 13.09.2015
comment
Как я могу получить такое же преимущество в своем проекте angularjs? stackoverflow.com/questions/36320162 / - person KhoPhi; 31.03.2016

Это не решает вашу проблему, но вы можете получить RT-канал в текстовом виде, используя URL-адрес, например http://developer.trimet.org/ws/V1/FeedSpecAlerts/appid/618F30BB3062F39AF24AED9EC/text/true

Также взгляните на модуль node-gtfs.

person vinayr    schedule 30.08.2013
comment
спасибо за текстовую ссылку, я не видел этого в документах. это дает мне что-то, с чем можно работать, видя, каким должен быть результат, мне будет легче отлаживать проблему. Модуль node-gtfs довольно классный, но я в основном работаю над ним, потому что хотел посмотреть, как protobufs могут работать с node. На самом деле я не работаю над какой-то конкретной целью, но если у меня все получится, я, вероятно, напишу простую обертку вокруг API Trimet и положу ее на npm. - person MiGnH; 30.08.2013

Я не эксперт по узлам, но тип корневого сообщения фида GTFS в реальном времени — «FeedMessage»:

https://developers.google.com/transit/gtfs-realtime/reference

Кажется, вы пытаетесь проанализировать канал как сообщение «Предупреждение»:

console.log(transit.Alert.decode(res.body))

Может быть, попробовать изменить Alert на FeedMessage и посмотреть, что произойдет?

person Brian Ferris    schedule 30.08.2013
comment
Благодарить! это шаг в правильном направлении. К сожалению, теперь я получаю новую ошибку Error: Data must be corrupt: Buffer overrun Я собираюсь обновить вопрос - person MiGnH; 30.08.2013