1 | mqtt-packet
|
2 | ===========
|
3 |
|
4 | Encode and Decode MQTT 3.1.1, 5.0 packets the node way.
|
5 |
|
6 | [![JavaScript Style Guide](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard)
|
7 |
|
8 | * <a href="#installation">Installation</a>
|
9 | * <a href="#examples">Examples</a>
|
10 | * <a href="#packets">Packets</a>
|
11 | * <a href="#api">API</a>
|
12 | * <a href="#contributing">Contributing</a>
|
13 | * <a href="#license">License & copyright</a>
|
14 |
|
15 | This library is tested with node v6, v8, v10, v12 and v14. The last version to support
|
16 | older versions of node was mqtt-packet@4.1.2.
|
17 |
|
18 | Installation
|
19 | ------------
|
20 |
|
21 | ```bash
|
22 | npm install mqtt-packet --save
|
23 | ```
|
24 |
|
25 | Examples
|
26 | --------
|
27 |
|
28 | ### Generating
|
29 |
|
30 | ```js
|
31 | const mqtt = require('mqtt-packet');
|
32 | const object = {
|
33 | cmd: 'publish',
|
34 | retain: false,
|
35 | qos: 0,
|
36 | dup: false,
|
37 | length: 10,
|
38 | topic: 'test',
|
39 | payload: 'test' // Can also be a Buffer
|
40 | };
|
41 | const opts = { protocolVersion: 4 }; // default is 4. Usually, opts is a connect packet
|
42 |
|
43 | console.log(mqtt.generate(object))
|
44 | // Prints:
|
45 | //
|
46 | // <Buffer 30 0a 00 04 74 65 73 74 74 65 73 74>
|
47 | //
|
48 | // Which is the same as:
|
49 | //
|
50 | // Buffer.from([
|
51 | // 48, 10, // Header (publish)
|
52 | // 0, 4, // Topic length
|
53 | // 116, 101, 115, 116, // Topic (test)
|
54 | // 116, 101, 115, 116 // Payload (test)
|
55 | // ])
|
56 | ```
|
57 |
|
58 | ### Parsing
|
59 |
|
60 | ```js
|
61 | const mqtt = require('mqtt-packet');
|
62 | const opts = { protocolVersion: 4 }; // default is 4. Usually, opts is a connect packet
|
63 | const parser = mqtt.parser(opts);
|
64 |
|
65 | // Synchronously emits all the parsed packets
|
66 | parser.on('packet', packet => {
|
67 | console.log(packet)
|
68 | // Prints:
|
69 | //
|
70 | // {
|
71 | // cmd: 'publish',
|
72 | // retain: false,
|
73 | // qos: 0,
|
74 | // dup: false,
|
75 | // length: 10,
|
76 | // topic: 'test',
|
77 | // payload: <Buffer 74 65 73 74>
|
78 | // }
|
79 | })
|
80 |
|
81 | parser.parse(Buffer.from([
|
82 | 48, 10, // Header (publish)
|
83 | 0, 4, // Topic length
|
84 | 116, 101, 115, 116, // Topic (test)
|
85 | 116, 101, 115, 116 // Payload (test)
|
86 | ]))
|
87 | // Returns the number of bytes left in the parser
|
88 | ```
|
89 |
|
90 | API
|
91 | ---
|
92 |
|
93 | * <a href="#generate"><code>mqtt#<b>generate()</b></code></a>
|
94 | * <a href="#writeToStream"><code>mqtt#<b>writeToStream()</b></code></a>
|
95 | * <a href="#parser"><code>mqtt#<b>parser()</b></code></a>
|
96 |
|
97 | <a name="generate">
|
98 |
|
99 | ### mqtt.generate(object, [opts])
|
100 |
|
101 | Generates a `Buffer` containing an MQTT packet.
|
102 | The object must be one of the ones specified by the [packets](#packets)
|
103 | section. Throws an `Error` if a packet cannot be generated.
|
104 |
|
105 | <a name="writeToStream">
|
106 |
|
107 | ### mqtt.writeToStream(object, stream, [opts])
|
108 |
|
109 | Writes the mqtt packet defined by `object` to the given stream.
|
110 | The object must be one of the ones specified by the [packets](#packets)
|
111 | section. Emits an `Error` on the stream if a packet cannot be generated.
|
112 | On node >= 0.12, this function automatically calls `cork()` on your stream,
|
113 | and then it calls `uncork()` on the next tick.
|
114 | By default cache for number buffers is enabled.
|
115 | It creates a list of buffers for faster write. To disable cache set `mqtt.writeToStream.cacheNumbers = false`.
|
116 | Should be set before any `writeToStream` calls.
|
117 |
|
118 | <a name="parser">
|
119 |
|
120 | ### mqtt.parser([opts])
|
121 |
|
122 | Returns a new `Parser` object. `Parser` inherits from `EventEmitter` and
|
123 | will emit:
|
124 |
|
125 | * `packet`, when a new packet is parsed, according to
|
126 | [packets](#packets)
|
127 | * `error`, if an error happens
|
128 |
|
129 | <a name="parse">
|
130 |
|
131 | #### Parser.parse(buffer)
|
132 |
|
133 | Parses a given `Buffer` and emits synchronously all the MQTT packets that
|
134 | are included. Returns the number of bytes left to parse.
|
135 |
|
136 | If an error happens, an `error` event will be emitted, but no `packet` events
|
137 | will be emitted after that. Calling `parse()` again clears the error and
|
138 | previous buffer, as if you created a new `Parser`.
|
139 |
|
140 | Packets
|
141 | -------
|
142 |
|
143 | This section describes the format of all packets emitted by the `Parser`
|
144 | and that you can input to `generate`.
|
145 |
|
146 | ### Connect
|
147 |
|
148 | ```js
|
149 | {
|
150 | cmd: 'connect',
|
151 | protocolId: 'MQTT', // Or 'MQIsdp' in MQTT 3.1 and 5.0
|
152 | protocolVersion: 4, // Or 3 in MQTT 3.1, or 5 in MQTT 5.0
|
153 | clean: true, // Can also be false
|
154 | clientId: 'my-device',
|
155 | keepalive: 0, // Seconds which can be any positive number, with 0 as the default setting
|
156 | username: 'matteo',
|
157 | password: Buffer.from('collina'), // Passwords are buffers
|
158 | will: {
|
159 | topic: 'mydevice/status',
|
160 | payload: Buffer.from('dead'), // Payloads are buffers
|
161 | properties: { // MQTT 5.0
|
162 | willDelayInterval: 1234,
|
163 | payloadFormatIndicator: false,
|
164 | messageExpiryInterval: 4321,
|
165 | contentType: 'test',
|
166 | responseTopic: 'topic',
|
167 | correlationData: Buffer.from([1, 2, 3, 4]),
|
168 | userProperties: {
|
169 | 'test': 'test'
|
170 | }
|
171 | }
|
172 | },
|
173 | properties: { // MQTT 5.0 properties
|
174 | sessionExpiryInterval: 1234,
|
175 | receiveMaximum: 432,
|
176 | maximumPacketSize: 100,
|
177 | topicAliasMaximum: 456,
|
178 | requestResponseInformation: true,
|
179 | requestProblemInformation: true,
|
180 | userProperties: {
|
181 | 'test': 'test'
|
182 | },
|
183 | authenticationMethod: 'test',
|
184 | authenticationData: Buffer.from([1, 2, 3, 4])
|
185 | }
|
186 | }
|
187 | ```
|
188 |
|
189 | If `protocolVersion` is 3, `clientId` is mandatory and `generate` will throw if
|
190 | missing.
|
191 |
|
192 | If `password` or `will.payload` are passed as strings, they will
|
193 | automatically be converted into a `Buffer`.
|
194 |
|
195 | ### Connack
|
196 |
|
197 | ```js
|
198 | {
|
199 | cmd: 'connack',
|
200 | returnCode: 0, // Or whatever else you see fit MQTT < 5.0
|
201 | sessionPresent: false, // Can also be true.
|
202 | reasonCode: 0, // reason code MQTT 5.0
|
203 | properties: { // MQTT 5.0 properties
|
204 | sessionExpiryInterval: 1234,
|
205 | receiveMaximum: 432,
|
206 | maximumQoS: 2,
|
207 | retainAvailable: true,
|
208 | maximumPacketSize: 100,
|
209 | assignedClientIdentifier: 'test',
|
210 | topicAliasMaximum: 456,
|
211 | reasonString: 'test',
|
212 | userProperties: {
|
213 | 'test': 'test'
|
214 | },
|
215 | wildcardSubscriptionAvailable: true,
|
216 | subscriptionIdentifiersAvailable: true,
|
217 | sharedSubscriptionAvailable: false,
|
218 | serverKeepAlive: 1234,
|
219 | responseInformation: 'test',
|
220 | serverReference: 'test',
|
221 | authenticationMethod: 'test',
|
222 | authenticationData: Buffer.from([1, 2, 3, 4])
|
223 | }
|
224 | }
|
225 | ```
|
226 |
|
227 | The only mandatory argument is `returnCode`, as `generate` will throw if
|
228 | missing.
|
229 |
|
230 | ### Subscribe
|
231 |
|
232 | ```js
|
233 | {
|
234 | cmd: 'subscribe',
|
235 | messageId: 42,
|
236 | properties: { // MQTT 5.0 properties
|
237 | subscriptionIdentifier: 145,
|
238 | userProperties: {
|
239 | test: 'test'
|
240 | }
|
241 | }
|
242 | subscriptions: [{
|
243 | topic: 'test',
|
244 | qos: 0,
|
245 | nl: false, // no Local MQTT 5.0 flag
|
246 | rap: true, // Retain as Published MQTT 5.0 flag
|
247 | rh: 1 // Retain Handling MQTT 5.0
|
248 | }]
|
249 | }
|
250 | ```
|
251 |
|
252 | All properties are mandatory.
|
253 |
|
254 | ### Suback
|
255 |
|
256 | ```js
|
257 | {
|
258 | cmd: 'suback',
|
259 | messageId: 42,
|
260 | properties: { // MQTT 5.0 properties
|
261 | reasonString: 'test',
|
262 | userProperties: {
|
263 | 'test': 'test'
|
264 | }
|
265 | }
|
266 | granted: [0, 1, 2, 128]
|
267 | }
|
268 | ```
|
269 |
|
270 | All the granted qos __must__ be < 256, as they are encoded as UInt8.
|
271 | All properties are mandatory.
|
272 |
|
273 | ### Unsubscribe
|
274 |
|
275 | ```js
|
276 | {
|
277 | cmd: 'unsubscribe',
|
278 | messageId: 42,
|
279 | properties: { // MQTT 5.0 properties
|
280 | userProperties: {
|
281 | 'test': 'test'
|
282 | }
|
283 | }
|
284 | unsubscriptions: [
|
285 | 'test',
|
286 | 'a/topic'
|
287 | ]
|
288 | }
|
289 | ```
|
290 |
|
291 | All properties are mandatory.
|
292 |
|
293 | ### Unsuback
|
294 |
|
295 | ```js
|
296 | {
|
297 | cmd: 'unsuback',
|
298 | messageId: 42,
|
299 | properties: { // MQTT 5.0 properties
|
300 | reasonString: 'test',
|
301 | userProperties: {
|
302 | 'test': 'test'
|
303 | }
|
304 | }
|
305 | }
|
306 | ```
|
307 |
|
308 | All properties are mandatory.
|
309 |
|
310 | ### Publish
|
311 |
|
312 | ```js
|
313 | {
|
314 | cmd: 'publish',
|
315 | messageId: 42,
|
316 | qos: 2,
|
317 | dup: false,
|
318 | topic: 'test',
|
319 | payload: Buffer.from('test'),
|
320 | retain: false,
|
321 | properties: { // optional properties MQTT 5.0
|
322 | payloadFormatIndicator: true,
|
323 | messageExpiryInterval: 4321,
|
324 | topicAlias: 100,
|
325 | responseTopic: 'topic',
|
326 | correlationData: Buffer.from([1, 2, 3, 4]),
|
327 | userProperties: {
|
328 | 'test': 'test'
|
329 | },
|
330 | subscriptionIdentifier: 120, // can be an Array in message from broker, if message included in few another subscriptions
|
331 | contentType: 'test'
|
332 | }
|
333 | }
|
334 | ```
|
335 |
|
336 | Only the `topic` property is mandatory.
|
337 | Both `topic` and `payload` can be `Buffer` objects instead of strings.
|
338 | `messageId` is mandatory for `qos > 0`.
|
339 |
|
340 | ### Puback
|
341 |
|
342 | ```js
|
343 | {
|
344 | cmd: 'puback',
|
345 | messageId: 42,
|
346 | reasonCode: 16, // only for MQTT 5.0
|
347 | properties: { // MQTT 5.0 properties
|
348 | reasonString: 'test',
|
349 | userProperties: {
|
350 | 'test': 'test'
|
351 | }
|
352 | }
|
353 | }
|
354 | ```
|
355 |
|
356 | The only mandatory property is `messageId`, as `generate` will throw if
|
357 | missing.
|
358 |
|
359 | ### Pubrec
|
360 |
|
361 | ```js
|
362 | {
|
363 | cmd: 'pubrec',
|
364 | messageId: 42,
|
365 | reasonCode: 16, // only for MQTT 5.0
|
366 | properties: { // properties MQTT 5.0
|
367 | reasonString: 'test',
|
368 | userProperties: {
|
369 | 'test': 'test'
|
370 | }
|
371 | }
|
372 | }
|
373 | ```
|
374 |
|
375 | The only mandatory property is `messageId`, as `generate` will throw if
|
376 | missing.
|
377 |
|
378 | ### Pubrel
|
379 |
|
380 | ```js
|
381 | {
|
382 | cmd: 'pubrel',
|
383 | messageId: 42,
|
384 | reasonCode: 16, // only for MQTT 5.0
|
385 | properties: { // properties MQTT 5.0
|
386 | reasonString: 'test',
|
387 | userProperties: {
|
388 | 'test': 'test'
|
389 | }
|
390 | }
|
391 | }
|
392 | ```
|
393 |
|
394 | The only mandatory property is `messageId`, as `generate` will throw if
|
395 | missing.
|
396 |
|
397 | ### Pubcomp
|
398 |
|
399 | ```js
|
400 | {
|
401 | cmd: 'pubcomp',
|
402 | messageId: 42,
|
403 | reasonCode: 16, // only for MQTT 5.0
|
404 | properties: { // properties MQTT 5.0
|
405 | reasonString: 'test',
|
406 | userProperties: {
|
407 | 'test': 'test'
|
408 | }
|
409 | }
|
410 | }
|
411 | ```
|
412 |
|
413 | The only mandatory property is `messageId`, as `generate` will throw if
|
414 | missing.
|
415 |
|
416 | ### Pingreq
|
417 |
|
418 | ```js
|
419 | {
|
420 | cmd: 'pingreq'
|
421 | }
|
422 | ```
|
423 |
|
424 | ### Pingresp
|
425 |
|
426 | ```js
|
427 | {
|
428 | cmd: 'pingresp'
|
429 | }
|
430 | ```
|
431 |
|
432 | ### Disconnect
|
433 |
|
434 | ```js
|
435 | {
|
436 | cmd: 'disconnect',
|
437 | reasonCode: 0, // MQTT 5.0 code
|
438 | properties: { // properties MQTT 5.0
|
439 | sessionExpiryInterval: 145,
|
440 | reasonString: 'test',
|
441 | userProperties: {
|
442 | 'test': 'test'
|
443 | },
|
444 | serverReference: 'test'
|
445 | }
|
446 | }
|
447 | ```
|
448 |
|
449 | ### Auth
|
450 |
|
451 | ```js
|
452 | {
|
453 | cmd: 'auth',
|
454 | reasonCode: 0, // MQTT 5.0 code
|
455 | properties: { // properties MQTT 5.0
|
456 | authenticationMethod: 'test',
|
457 | authenticationData: Buffer.from([0, 1, 2, 3]),
|
458 | reasonString: 'test',
|
459 | userProperties: {
|
460 | 'test': 'test'
|
461 | }
|
462 | }
|
463 | }
|
464 | ```
|
465 |
|
466 | <a name="contributing"></a>
|
467 |
|
468 | Contributing
|
469 | ------------
|
470 |
|
471 | mqtt-packet is an **OPEN Open Source Project**. This means that:
|
472 |
|
473 | > Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project.
|
474 |
|
475 | See the [CONTRIBUTING.md](https://github.com/mqttjs/mqtt-packet/blob/master/CONTRIBUTING.md) file for more details.
|
476 |
|
477 | ### Contributors
|
478 |
|
479 | mqtt-packet is only possible due to the excellent work of the following contributors:
|
480 |
|
481 | <table><tbody>
|
482 | <tr><th align="left">Matteo Collina</th><td><a href="https://github.com/mcollina">GitHub/mcollina</a></td><td><a href="http://twitter.com/matteocollina">Twitter/@matteocollina</a></td></tr>
|
483 | <tr><th align="left">Adam Rudd</th><td><a href="https://github.com/adamvr">GitHub/adamvr</a></td><td><a href="http://twitter.com/adam_vr">Twitter/@adam_vr</a></td></tr>
|
484 | <tr><th align="left">Peter Sorowka</th><td><a href="https://github.com/psorowka">GitHub/psorowka</a></td><td><a href="http://twitter.com/psorowka">Twitter/@psorowka</a></td></tr>
|
485 | <tr><th align="left">Siarhei Buntsevich</th><td><a href="https://github.com/scarry1992">GitHub/scarry1992</a></td></tr>
|
486 | </tbody></table>
|
487 |
|
488 | License
|
489 | -------
|
490 |
|
491 | MIT
|