split-frames 2.5.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +13 -13
- package/README.md +268 -263
- package/lib/cjs/SplitFrames.d.ts +52 -57
- package/lib/cjs/SplitFrames.js +400 -384
- package/lib/cjs/checkers/checkTagsValidity.d.ts +2 -3
- package/lib/cjs/checkers/checkTagsValidity.js +22 -18
- package/lib/cjs/checkers/initData.d.ts +2 -2
- package/lib/cjs/checkers/initData.js +94 -85
- package/lib/cjs/main.cjs +8 -8
- package/lib/cjs/main.d.cts +2 -2
- package/package.json +111 -96
package/LICENSE
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
Copyright (c)
|
|
2
|
-
|
|
3
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
4
|
-
purpose with or without fee is hereby granted, provided that the above
|
|
5
|
-
copyright notice and this permission notice appear in all copies.
|
|
6
|
-
|
|
7
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
8
|
-
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
9
|
-
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
10
|
-
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
11
|
-
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
12
|
-
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
13
|
-
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
1
|
+
Copyright (c) 2026, Sébastien Vidal
|
|
2
|
+
|
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
4
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
5
|
+
copyright notice and this permission notice appear in all copies.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
8
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
9
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
10
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
11
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
12
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
13
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,263 +1,268 @@
|
|
|
1
|
-
# split-frames
|
|
2
|
-
Split Buffer frames from streams
|
|
3
|
-
|
|
4
|
-
[](https://sonarcloud.io/summary/new_code?id=Psychopoulet_split-frames)
|
|
5
|
+
[](https://github.com/Psychopoulet/split-frames/issues)
|
|
6
|
+
[](https://github.com/Psychopoulet/split-frames/pulls)
|
|
7
|
+
|
|
8
|
+
[](https://sonarcloud.io/summary/new_code?id=Psychopoulet_split-frames)
|
|
9
|
+
[](https://sonarcloud.io/summary/new_code?id=Psychopoulet_split-frames)
|
|
10
|
+
[](https://sonarcloud.io/summary/new_code?id=Psychopoulet_split-frames)
|
|
11
|
+
[](https://sonarcloud.io/summary/new_code?id=Psychopoulet_split-frames)
|
|
12
|
+
[](https://sonarcloud.io/summary/new_code?id=Psychopoulet_split-frames)
|
|
13
|
+
|
|
14
|
+
[](https://snyk.io/test/github/Psychopoulet/split-frames)
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
$ npm install split-frames
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Doc
|
|
23
|
+
|
|
24
|
+
> Works very well with, for example, [serialport](https://www.npmjs.com/package/serialport) for industrial protocols like Concert
|
|
25
|
+
|
|
26
|
+
> /!\ this version only split frames properly, and does not remove start & end tags or escape bits anymore.
|
|
27
|
+
|
|
28
|
+
### Methods
|
|
29
|
+
|
|
30
|
+
* inherited from [stream.Transform](https://nodejs.org/api/stream.html#stream_duplex_and_transform_streams)
|
|
31
|
+
* constructor ([ options: object ]): split-frames instance
|
|
32
|
+
|
|
33
|
+
### Options
|
|
34
|
+
|
|
35
|
+
> All these options are optionnal
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
type ControlBits = "none" | "end+1" | "end+2";
|
|
39
|
+
type Tag: number | Buffer | Array< number | Buffer >
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
* ```javascript "startWith": Tag ```
|
|
43
|
+
* ```javascript "startTimeout": integer ``` (default: 200)
|
|
44
|
+
* ```javascript "endWith": Tag ```
|
|
45
|
+
* ```javascript "escapeWith": number ```
|
|
46
|
+
* ```javascript "escaped": Array<number> ```
|
|
47
|
+
* ```javascript "specifics": object ```
|
|
48
|
+
* ```javascript "controlBits": ControlBits ``` (default: "none")
|
|
49
|
+
|
|
50
|
+
> "startTimeout" is a timeout (in milliseconds) which end frame in "start only" mode, if no second "start" bit is encountered after the first one
|
|
51
|
+
|
|
52
|
+
> "specifics" is a [ key: string => value: Tag ] object which fire a "key" event when a "value" tag is found out of the message and not escaped
|
|
53
|
+
> ex : { "specifics": { "nak": 0x25 } } will fire an "nak" event when 0x25 bit is encountered
|
|
54
|
+
|
|
55
|
+
## Examples
|
|
56
|
+
|
|
57
|
+
In the following exemples, "Splitter" and "Readable" classes are defined like that :
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// typescript
|
|
61
|
+
import Splitter = require("split-frames");
|
|
62
|
+
import { Readable } from "stream";
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
// javascript
|
|
67
|
+
const Splitter = require("split-frames");
|
|
68
|
+
const { Readable } = require("stream");
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The "createReadStream" function is defined like that :
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
function createReadStream () {
|
|
75
|
+
return new Readable({
|
|
76
|
+
read () { }
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
And the "STX", "DLE" and "ETX" constants are defined like that :
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
const STX = 0x02, ETX = 0x03, DLE = 0x10, ACK = 0x06, NAK = 0x15, WAK = 0x13;
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### want to split frames content on a start bit ?
|
|
88
|
+
|
|
89
|
+
```javascript
|
|
90
|
+
const stream = createReadStream();
|
|
91
|
+
|
|
92
|
+
stream.pipe(new Splitter({
|
|
93
|
+
"startWith": STX
|
|
94
|
+
})).on("data", (chunk) => {
|
|
95
|
+
// Buffer([ STX, 0x24, 0x25, 0x26 ])
|
|
96
|
+
// Buffer([ STX, 0x24, 0x25 ])
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
stream.push(Buffer.from([ 0x20, STX, 0x24, 0x25, 0x26, STX, 0x24 ]));
|
|
100
|
+
stream.push(Buffer.from([ 0x25, STX ]));
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### prefere an end bit ?
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
const stream = createReadStream();
|
|
107
|
+
|
|
108
|
+
stream.pipe(new Splitter({
|
|
109
|
+
"endWith": ETX
|
|
110
|
+
})).on("data", (chunk) => {
|
|
111
|
+
// Buffer([ 0x24, 0x25, 0x26, ETX ])
|
|
112
|
+
// Buffer([ 0x24, 0x25, ETX ])
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
stream.push(Buffer.from([ 0x24, 0x25, 0x26, ETX, 0x24, 0x25 ]));
|
|
116
|
+
stream.push(Buffer.from([ ETX ]));
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### want both ?
|
|
120
|
+
|
|
121
|
+
```javascript
|
|
122
|
+
const stream = createReadStream();
|
|
123
|
+
|
|
124
|
+
stream.pipe(new Splitter({
|
|
125
|
+
"startWith": STX, "endWith": ETX
|
|
126
|
+
})).on("data", (chunk) => {
|
|
127
|
+
// Buffer([ STX, 0x24, 0x25, 0x26, ETX ])
|
|
128
|
+
// Buffer([ STX, 0x24, 0x25, ETX ])
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
stream.push(Buffer.from([ 0x20, STX, 0x24, 0x25, 0x26, ETX, 0x24, 0x25, STX ]));
|
|
132
|
+
stream.push(Buffer.from([ 0x24, 0x25, ETX ]));
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### what about two end bits (works with start one as well) ?
|
|
136
|
+
|
|
137
|
+
```javascript
|
|
138
|
+
const stream = createReadStream();
|
|
139
|
+
|
|
140
|
+
stream.pipe(new Splitter({
|
|
141
|
+
"startWith": STX, "endWith": Buffer.from([ DLE, ETX ])
|
|
142
|
+
})).on("data", (chunk) => {
|
|
143
|
+
// Buffer([ STX, 0x24, 0x25, 0x26, DLE, ETX ])
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
stream.push(Buffer.from([ 0x20, STX, 0x24, 0x25, 0x26, DLE, ETX, STX, 0x24, 0x25 ]));
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Do you need to parse escaped bits ?
|
|
150
|
+
|
|
151
|
+
```javascript
|
|
152
|
+
const stream = createReadStream();
|
|
153
|
+
|
|
154
|
+
stream.pipe(new Splitter({
|
|
155
|
+
"startWith": STX, "endWith": ETX,
|
|
156
|
+
"escapeWith": DLE, "escaped": [ DLE, STX, ETX ]
|
|
157
|
+
})).on("data", (chunk) => {
|
|
158
|
+
// Buffer([ STX, 0x24, DLE, STX, 0x25, 0x26, DLE, DLE, 0x27, DLE, ETX, 0x28, ETX ])
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
stream.push(Buffer.from([ 0x20, STX, 0x24, DLE, STX, 0x25, 0x26 ]));
|
|
162
|
+
stream.push(Buffer.from([ DLE, DLE, 0x27, DLE, ETX, 0x28, ETX, STX, 0x24, 0x25 ]));
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### And what do you think about multiple start (or end !) bits possibilities ?
|
|
166
|
+
|
|
167
|
+
For even parity in seriaport, for example
|
|
168
|
+
|
|
169
|
+
```javascript
|
|
170
|
+
const STX2 = 0x82;
|
|
171
|
+
const stream = createReadStream();
|
|
172
|
+
|
|
173
|
+
stream.pipe(new Splitter({
|
|
174
|
+
"startWith": [ STX, STX2 ], "endWith": ETX,
|
|
175
|
+
"escapeWith": DLE, "escaped": [ DLE, STX, ETX ]
|
|
176
|
+
})).on("data", (chunk) => {
|
|
177
|
+
// Buffer([ STX, 0x24, DLE, STX, 0x25, 0x26, DLE, DLE, 0x27, DLE, ETX, 0x28, ETX ])
|
|
178
|
+
// Buffer([ STX2, 0x24, DLE, STX, 0x25, 0x26, DLE, DLE, 0x27, DLE, ETX, 0x28, ETX ])
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
stream.push(Buffer.from([ 0x24, STX, 0x24, DLE, STX, 0x25, ACK ]));
|
|
182
|
+
stream.push(Buffer.from([ DLE, DLE, 0x27, DLE, ETX, 0x28, ETX, ACK, 0x24, 0x25 ]));
|
|
183
|
+
stream.push(Buffer.from([ STX2, 0x24, DLE, STX, 0x25, ACK ]));
|
|
184
|
+
stream.push(Buffer.from([ DLE, DLE, 0x27, DLE, ETX, 0x28, ETX, ACK, 0x24, 0x25 ]));
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Want to extract specific tags ?
|
|
188
|
+
|
|
189
|
+
> positive acknowledgement, negative acknowledgement, waiting for acknowledgement, whatever...
|
|
190
|
+
> only with no tags || start AND end tags || end tags (for firsts bits)
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
const stream = createReadStream();
|
|
194
|
+
|
|
195
|
+
stream.pipe(new Splitter({
|
|
196
|
+
"startWith": STX, "endWith": ETX,
|
|
197
|
+
"specifics": {
|
|
198
|
+
"ack": ACK, "nak": NAK, "wak": WAK, "whatever": 0x51
|
|
199
|
+
},
|
|
200
|
+
"escapeWith": DLE, "escaped": [ DLE, ACK, NAK, WAK ]
|
|
201
|
+
})).on("ack", () => {
|
|
202
|
+
console.log("ack received"); // (only 1x) -> good, escaped, in data
|
|
203
|
+
}).on("nak", () => {
|
|
204
|
+
console.log("nak received"); // (only 1x) -> in data, good, escaped
|
|
205
|
+
}).on("wak", () => {
|
|
206
|
+
console.log("wak received"); // (only 1x) -> in data, good, escaped
|
|
207
|
+
}).on("whatever", () => {
|
|
208
|
+
console.log("whatever received"); // (only 1x)
|
|
209
|
+
}).on("data", (chunk) => {
|
|
210
|
+
// Buffer([ STX, 0x20, 0x21, 0x22, ACK, NAK, WAK, 0x23, ETX ]) (x1)
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
stream.push(Buffer.from([ 0x51, 0x24, ACK, DLE, ACK, STX, 0x20, 0x21, 0x22, ACK, NAK, WAK ]));
|
|
214
|
+
stream.push(Buffer.from([ 0x23, ETX, NAK, DLE, NAK, WAK, DLE, WAK, 0x20, 0x21 ]));
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Want to use control bits ?
|
|
218
|
+
|
|
219
|
+
> used to compute LRC, MSB, LSB, etc...
|
|
220
|
+
> this example is for a structure like STX <data> ETX LRC, where LRC compute all <data> bits
|
|
221
|
+
|
|
222
|
+
```javascript
|
|
223
|
+
|
|
224
|
+
function _computeLRC (frame) {
|
|
225
|
+
|
|
226
|
+
let lrc = 0x00;
|
|
227
|
+
|
|
228
|
+
for (let i = 0; i < frame.length; ++i) {
|
|
229
|
+
lrc ^= frame[i];
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return lrc;
|
|
233
|
+
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const stream = createReadStream();
|
|
237
|
+
|
|
238
|
+
stream.pipe(new Splitter({
|
|
239
|
+
"startWith": STX, "endWith": ETX,
|
|
240
|
+
"controlBits": "end+1"
|
|
241
|
+
})).on("data", (chunk) => {
|
|
242
|
+
|
|
243
|
+
// Buffer([ STX, 0x20, 0x21, 0x22, 0x24, ETX, 0x07 ]) (x1)
|
|
244
|
+
|
|
245
|
+
const data = chunk.slice(1, chunk.length - 2); // Buffer([ 0x20, 0x21, 0x22, 0x24 ])
|
|
246
|
+
const LRC = chunk[chunk.length - 1];
|
|
247
|
+
|
|
248
|
+
if (_computeLRC(data) === LRC) {
|
|
249
|
+
console.log("OK");
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
console.error(new Error("not well-computed data :" + data.toString("hex") + "|" + Buffer.from([ LRC ]).toString("hex")));
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
stream.push(Buffer.from([ 0x51, 0x24, STX, 0x20, 0x21, 0x22, 0x24, ETX, 0x07, 0x24 ]));
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## Tests
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
$ npm run-script tests
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## License
|
|
267
|
+
|
|
268
|
+
[ISC](LICENSE)
|