npm 包 serial-port 与 meteor 的光纤错误

Fiber Error with npm package serial-port with meteor

我正在使用带有 meteor 的 SerialPort npm 包。我已经使用 wrapAsync 列出串行端口,但我不知道如何使用 serialPort.on 方法。 当我想在我的汽车中插入数据时出现错误 collection :

Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.

代码:

Meteor.startup(function () {
  SerialPort = Meteor.npmRequire('serialport');
  // Wrap method SerialPort.list to call it Synchronously
  listSerialPorts = function(callback) {
    SerialPort.list(function (err, ports) {
      callback(null, ports);
    });  
  }
  // Reset cars collection

});



Meteor.methods({
  serialPortsRefresh: function () {
    // TODO : problem when several arduinos ?
    Config.remove({key:'serialPorts'});
    // Call SerialPort.list
    var asyncListSerialPorts = Meteor.wrapAsync(listSerialPorts);
    var resultsListSerialPorts = asyncListSerialPorts();
    // Insert results in database
    var configSerialPorts = {key: "serialPorts", value: resultsListSerialPorts[0].comName };
    Config.insert(configSerialPorts);
  },
  // Connect Serial port
  serialPortConnect: function (port) {
    // debugger;
    // serialPort = new SerialPort(port.value, {baudrate: 9600});
    serialPort = new SerialPort.SerialPort("/dev/ttyUSB0", {baudrate: 9600, parser: SerialPort.parsers.readline("\n")});
    // connectSerialPort(port);
    serialPort.on('open', function() {
        console.log('Port ' + port.value + ' open');
    });    
    serialPort.on('data', function(data) {
          dispatchMessages(data);
        //Watchdog.insert({key: "Receiving data", value: data })
    });  
    sendToArduino = function(message) {
      console.log(message);
      serialPort.write(message);
    };      
    dispatchMessages = function(data) {
      console.log(data);
      //Split data
      var datas = data.split(" ");
      if (datas[1] == "OK") {
        console.log("Car " + datas[0] + " is here");
        // Add car to database
        Cars.insert({
          cid: datas[0],
          active: true
        });
      }

    };    
  },  
  // Ping bridge
  ping: function () {
    sendToArduino("LED13\n");
  }    


});

问题是您传递给 serialPort.on 的回调在被调用时不会 运行 在与您的方法相同的纤程中。事实上,它们根本不会 运行 在光纤中,除非你适当地包裹它们。

Meteor.bindEnvironment 运行s 在纤程中传递的函数,但也在周围环境中复制,这是必要的,因为 Meteor 在当前纤程中存储各种变量,这可能需要运行 有问题的回调。

因此,如果您这样做,它应该会起作用:

serialPort.on('open', Meteor.bindEnvironment(function() {
    // Wrapping this one is unnecessary at present as it doesn't
    // do anything that needs to be run in a fiber, but you should
    // probably wrap it anyway so that you can safely add more code
    // if required.
    console.log('Port ' + port.value + ' open');
}, function(e) {
    // This is an error-handler - you don't have to pass one, but
    // if you don't it can make debugging a nightmare.
    throw e;
}));    
serialPort.on('data', Meteor.bindEnvironment(function(data) {
    dispatchMessages(data);
    //Watchdog.insert({key: "Receiving data", value: data })
}, function(e) {
    throw e;
}));  

请注意,您还需要将回调包含在回调等中,这可能会变得非常冗长(并且将 var mBE = Meteor.bindEnvironment 之类的内容放在方法文件的顶部是个不错的主意)。