2

我正在使用带有流星的 SerialPort npm 包。我使用 wrapAsync 列出串行端口,但我不知道如何使用 serialPort.on 方法。当我想在我的 Cars 集合中插入数据时出现错误:

Meteor 代码必须始终在 Fiber 中运行。尝试使用 Meteor.bindEnvironment 包装传递给非 Meteor 库的回调。

代码 :

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");
  }    


});
4

1 回答 1

2

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

Meteor.bindEnvironment在光纤中运行传递的函数,但也在周围环境中复制,这是必要的,因为 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放在方法文件的顶部是一个好主意)。

于 2015-06-03T09:03:06.067 回答