2016-10-16 4 views
1

私が使用しようとしている約束ベースのコードは、完全な応答を得るたびに問題になります。私は.onでデータリスナーを使用していましたが、テストでは各呼び出しでデータリスナーを積み重ねていたため、.onceに変更しました。しかし、いずれにせよ私はときどき部分的な反応を得る。だからどうすればこの問題を解決できますか?リスナーをスタックするのではなく、毎回完全な応答を得る...約束を使ってそれを行う。ここでノードリスナーを積み重ねるリスナーと約束を使って完全な応答が得られない

sendPort: function(port, src) { 
     return new Promise((resolve, reject) => { 
     // .once, not stacking but sometimes incomplete responses, .on stacking listener 
      port.once('data', (data) => { 
       resolve(data); // TODO parse data here or maybe after return 

      }); 
      port.once('error', (err) => { 
       reject(err); 
      }); 
      // have same debug in .then after call showing listerner not removed with .on 
      Debug.L1('sendport num data listeners: ', port.listenerCount("data")); 

      port.write(src); 
     }); 

は、ここでは、コード

com.openPort(port).then(port => { 
          _.pTimeout(3000, com.sendPort(port, NCD.gen(args.cmd))) 
           .then(received => { 
            console.log('complete response: ', NCD.parse(received)); 
            Debug.L1('resolved num data listeners: ', port.listenerCount("data")); 
           }) 
         }) 
         .catch(function(e) { 
          console.log('error: ', e) 
         }); 

を呼び出している.onを使用して、出力が4回、完全な応答が[ 170, 1, 0, 171 ]

debug:1 api command array: +0ms [ 170, 3, 254, 175, 0, 90 ] 
    debug:1 sendport num data listeners: +1ms 4 
    complete response: [ 170 ] 
    debug:1 resolved num data listeners: +2ms 4 

応答だった別の時間[170、1されている必要がありますと呼ばれています、0]、ほとんどの時間私は完全な応答を返す。

結果は.onceと似ていますが、リスナーはスタックされません。

debug:1 sendport num data listeners: +0ms 1 
complete response: [ 170, 1, 0 ] 
    debug:1 resolved num data listeners: +1ms 0 

思考?アイデア?修正については約束を使用しています。

私のコードは私がここで見つけたアイデアから来ています。 Nodejs map serial port write to receive data

+0

受信したデータが1つのチャンクではなく複数のチャンクである可能性があるため、解決する前にまずデータを渡してください。 – Tim

+0

「データを最初に解析する」という意味ですか?そうであれば、解析されたデータを生。私は議論していた(TODOコメントで)。まだそれがそれを行うことを確信していますが、私は試して報告する – DKebler

答えて

1

serialport gitterの人々の助けを借りて、完成した解決策を投稿しました。一番下の行は.onを使用しなければならないということです。そして、あなたは戻ってくるバイト数を何らかの形で知っていなければなりません。私の場合、私のデバイスでは先頭のバイトを取得し、次に2番目のバイトは最後のバイトがチェックサムに従うバイト数を指示します。私はこれを書いて、あなたがdoneフラグをtrueに変更しないように指示するまで、チャンクを連結し続ける独自のバッファパーサを "プラグイン"することができました。

バッファとparserはあなたまでチャンクで返すバッファを解析するお使いのデバイスに固有の機能であるように、このportが既に作成してserialPortを開いたところのようになってしまったsendPort以上、cmdは、デバイスにあなたの発信コマンドでありますそれは終わったと言う。解析オブジェクトがこの

// See sendPort - used with custom parser function to return response and completion flag 
Parse: function(parser) { 
let parse = function() {} 

parse.parser = parser; 

parse.reset = function reset() { 
    this.response = []; 
    this.done = ''; 
} 

parse.reset(); // used here to intialize response and 

return parse 

}

のように見える、あなたはあなたのデバイスに固有であるあなたがここに let parse = _.Parse(parser);に渡し、独自のパーサ関数を記述する必要が

sendPort: function(port, cmd, parser) { 
    return new Promise((resolve, reject) => { 
     Debug.L2('port and buffer for write', port, cmd) 

     let parse = _.Parse(parser); //create object with response and done fields and reference to attached parser 

     Debug.L1('parse response and done initally, ', parse.response, parse.done); 

     port.on('data', (chunk) => { 

      parse.parser(chunk) 
       // Debug.L1('parsed: ', parse.response) 
      Debug.L1('parse done after parser call:', parse.done); 

      if (parse.done) { 
       resolve(parse.response); 
       parse.reset() // sets .done to false and clears out .response 
       Debug.L1('response and done after resolve/complete, ', parse.response, parse.done); 
       port.reset(); //removes all listners to avoid stacking on next call to sendPort 
      } 

     }); 
     port.on('error', (err) => { 
      reject(err); 
     }); 

     port.write(cmd); 
    }); 
}, 

。これはNCD ProXRリレーボード用です。

parse: function(chunk) { 

    for (var byte of chunk) { 
     this.response.push(byte); 
     Debug.L1('response being built ', this.response) 
    } 
    Debug.L1('current chunck response ', this.response) 
     // api version where first byte is 170, 
    if (this.response[1]) { // second slot is number of bits to follow exlcuding checksum 
     if (this.response.length >= 3 + this.response[1]) { // 3 = 170 + number of bits bit + checksum 
      this.done = true 
     } 
    } 
}, 

私は完全な応答が取得された知っているとき、私が呼び出すことができるポートを作成するとき、私はresetメソッドを追加した「データ」のリスナーをスタックしないようにこれを取得します。私はremoveALLlistenersを使用しました。なぜなら、単一のものを動作させることができなかったからです。どこにでもコードに他の "データ"リスナーがないことはわかっています。

let serialport = require('serialport'), 

createPort: function(sysDevName, opts) { 
    opts = opts || {}; 
    opts.autoOpen = false; // actually open device later 
    Debug.L1(sysDevName, opts); 
    let port = new serialport(sysDevName, opts, (err) => { 
     if (err) { 
      Debug.L1("create error" + err.message); 
      return err; 
     } 

    }) 
    port.reset = function() { 
     this.removeAllListeners("data"); 
     this.removeAllListeners("error"); 
    } 
    return port; 

最後の注意はParseオブジェクトが.resetメソッドが含まれていて、あなたがそれを見ると、完全な応答が遵守された後port.resetが呼び出されているということです。これを行う必要があります。そうしないと、doneフラグはfalseにならず、.responseには以前のものが含まれ、"data"のリスナーがスタックします。

関連する問題