From bcb492f3869d53425778b610d31efc2cd46063c8 Mon Sep 17 00:00:00 2001 From: Frank Lemanschik Date: Sun, 1 Oct 2017 22:03:38 +0100 Subject: [PATCH] feat(parsers): Add cctalk parsers (#1342) * Added Working CCTalk Parser * add basic tests * compiled docs for cctalk parser --- README.md | 9 +++++++++ lib/parsers/cctalk.js | 31 +++++++++++++++++++++++++++++++ lib/parsers/index.js | 10 ++++++++++ test/parser-cctalk.js | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+) create mode 100644 lib/parsers/cctalk.js create mode 100644 test/parser-cctalk.js diff --git a/README.md b/README.md index e5a767ceb..188f9b354 100644 --- a/README.md +++ b/README.md @@ -788,6 +788,15 @@ const parser = port.pipe(new Regex({ regex: /[\r\n]+/ })); parser.on('data', console.log); ``` +To use the `CCTalk` parser you need to provide nothing. CCTalk Messages get emitted as buffer. +```js +const SerialPort = require('serialport'); +const CCTalk = SerialPort.parsers.CCTalk; +const port = new SerialPort('/dev/ttyUSB0'); +const parser = port.pipe(new CCtalk()); +parser.on('data', console.log); +``` + * * * diff --git a/lib/parsers/cctalk.js b/lib/parsers/cctalk.js new file mode 100644 index 000000000..19104522b --- /dev/null +++ b/lib/parsers/cctalk.js @@ -0,0 +1,31 @@ +'use strict'; +const Transform = require('stream').Transform; +const Buffer = require('safe-buffer').Buffer; + +module.exports = class CCTalkParser extends Transform { + constructor() { + super(); + this.array = []; + this.cursor = 0; + } + _transform(buffer, _, cb) { + this.cursor += buffer.length; + // TODO: Better Faster es7 no supported by node 4 + // ES7 allows directly push [...buffer] + // this.array = this.array.concat(Array.from(buffer)); //Slower ?!? + Array.from(buffer) + .map((byte) => this.array.push(byte)); + while (this.cursor > 1 && this.cursor >= this.array[1] + 5) { + // full frame accumulated + // copy command from the array + const FullMsgLength = this.array[1] + 5; + + const frame = Buffer.from(this.array.slice(0, FullMsgLength)); + // Preserve Extra Data + this.array = this.array.slice(frame.length, this.array.length); + this.cursor -= FullMsgLength; + this.push(frame); + } + cb(); + } +}; diff --git a/lib/parsers/index.js b/lib/parsers/index.js index c05e05045..275ba44ba 100644 --- a/lib/parsers/index.js +++ b/lib/parsers/index.js @@ -71,11 +71,21 @@ const Regex = SerialPort.parsers.Regex; const port = new SerialPort('/dev/tty-usbserial1'); const parser = port.pipe(new Regex({ regex: /[\r\n]+/ })); parser.on('data', console.log); +``` + +To use the `CCTalk` parser you need to provide nothing. CCTalk Messages get emitted as buffer. +```js +const SerialPort = require('serialport'); +const CCTalk = SerialPort.parsers.CCTalk; +const port = new SerialPort('/dev/ttyUSB0'); +const parser = port.pipe(new CCtalk()); +parser.on('data', console.log); ``` */ module.exports = { ByteLength: require('./byte-length'), + CCTalk: require('./cctalk'), Delimiter: require('./delimiter'), Readline: require('./readline'), Ready: require('./ready'), diff --git a/test/parser-cctalk.js b/test/parser-cctalk.js new file mode 100644 index 000000000..7c757a8e7 --- /dev/null +++ b/test/parser-cctalk.js @@ -0,0 +1,41 @@ +'use strict'; +/* eslint-disable no-new */ + +const Buffer = require('safe-buffer').Buffer; +const sinon = require('sinon'); +const CCTalkParser = require('../lib/parsers/cctalk'); + +describe('CCTalkParser', () => { + it('emits data for a default length message', () => { + const data = Buffer.from([2, 0, 1, 254, 217]); + const spy = sinon.spy(); + const parser = new CCTalkParser(); + parser.on('data', spy); + parser.write(data); + assert.equal(spy.callCount, 1); + assert.deepEqual(spy.getCall(0).args[0], Buffer.from([2, 0, 1, 254, 217])); + }); + + it('emits data for a 7 byte length message', () => { + const parser = new CCTalkParser(); + const spy = sinon.spy(); + parser.on('data', spy); + parser.write(Buffer.from([2, 2, 1, 254, 1, 1, 217])); + assert.equal(spy.callCount, 1); + assert.deepEqual(spy.getCall(0).args[0], Buffer.from([2, 2, 1, 254, 1, 1, 217])); + }); + + it('emits 2 times data first length 7 secund length 5', () => { + const parser = new CCTalkParser(); + const spy = sinon.spy(); + parser.on('data', spy); + parser.write(Buffer.from([2, 2, 1])); + parser.write(Buffer.from([254, 1, 1])); + parser.write(Buffer.from([217, 2])); + parser.write(Buffer.from([0, 1, 254, 217])); + assert.equal(spy.callCount, 2); + assert.deepEqual(spy.getCall(0).args[0], Buffer.from([2, 2, 1, 254, 1, 1, 217])); + assert.deepEqual(spy.getCall(1).args[0], Buffer.from([2, 0, 1, 254, 217])); + }); +}); +// TODO: parser.write(Buffer.from([2, 2, 1, 254, 1, 1, 217, 2, 0, 1, 254, 217, 2, 2, 1, 251, 1, 1, 217, 2, 2, 1, 252, 1, 1, 217, 2, 0, 1, 253, 217]));