node-mavlink 1.0.13 → 1.2.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.
@@ -1,172 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DESERIALIZERS = exports.SERIALIZERS = void 0;
4
- /**
5
- * A dictionary containing functions that serialize a certain value based on the field type
6
- */
7
- exports.SERIALIZERS = {
8
- // special types
9
- 'uint8_t_mavlink_version': (value, buffer, offset) => buffer.writeUInt8(value, offset),
10
- // singular types
11
- 'char': (value, buffer, offset) => buffer.writeUInt8(value, offset),
12
- 'int8_t': (value, buffer, offset) => buffer.writeInt8(value, offset),
13
- 'uint8_t': (value, buffer, offset) => buffer.writeUInt8(value, offset),
14
- 'int16_t': (value, buffer, offset) => buffer.writeInt16LE(value, offset),
15
- 'uint16_t': (value, buffer, offset) => buffer.writeUInt16LE(value, offset),
16
- 'int32_t': (value, buffer, offset) => buffer.writeInt32LE(value, offset),
17
- 'uint32_t': (value, buffer, offset) => buffer.writeUInt32LE(value, offset),
18
- 'int64_t': (value, buffer, offset) => buffer.writeBigInt64LE(value, offset),
19
- 'uint64_t': (value, buffer, offset) => buffer.writeBigUInt64LE(value, offset),
20
- 'float': (value, buffer, offset) => buffer.writeFloatLE(value, offset),
21
- 'double': (value, buffer, offset) => buffer.writeDoubleLE(value, offset),
22
- // array types
23
- 'char[]': (value, buffer, offset, maxLen) => {
24
- for (let i = 0; i < value.length && i < maxLen; i++) {
25
- const code = value.charCodeAt(i);
26
- buffer.writeUInt8(code, offset + i);
27
- }
28
- },
29
- 'int8_t[]': (value, buffer, offset, maxLen) => {
30
- for (let i = 0; i < value.length && i < maxLen; i++) {
31
- buffer.writeInt8(value[i], offset + i);
32
- }
33
- },
34
- 'uint8_t[]': (value, buffer, offset, maxLen) => {
35
- for (let i = 0; i < value.length && i < maxLen; i++) {
36
- buffer.writeUInt8(value[i], offset + i);
37
- }
38
- },
39
- 'int16_t[]': (value, buffer, offset, maxLen) => {
40
- for (let i = 0; i < value.length && i < maxLen; i++) {
41
- buffer.writeInt16LE(value[i], offset + i * 2);
42
- }
43
- },
44
- 'uint16_t[]': (value, buffer, offset, maxLen) => {
45
- for (let i = 0; i < value.length && i < maxLen; i++) {
46
- buffer.writeUInt16LE(value[i], offset + i * 2);
47
- }
48
- },
49
- 'int32_t[]': (value, buffer, offset, maxLen) => {
50
- for (let i = 0; i < value.length && i < maxLen; i++) {
51
- buffer.writeInt32LE(value[i], offset + i * 4);
52
- }
53
- },
54
- 'uint32_t[]': (value, buffer, offset, maxLen) => {
55
- for (let i = 0; i < value.length && i < maxLen; i++) {
56
- buffer.writeUInt32LE(value[i], offset + i * 4);
57
- }
58
- },
59
- 'int64_t[]': (value, buffer, offset, maxLen) => {
60
- for (let i = 0; i < value.length && i < maxLen; i++) {
61
- buffer.writeBigInt64LE(value[i], offset + i * 8);
62
- }
63
- },
64
- 'uint64_t[]': (value, buffer, offset, maxLen) => {
65
- for (let i = 0; i < value.length && i < maxLen; i++) {
66
- buffer.writeBigUInt64LE(value[i], offset + i * 8);
67
- }
68
- },
69
- 'float[]': (value, buffer, offset, maxLen) => {
70
- for (let i = 0; i < value.length && i < maxLen; i++) {
71
- buffer.writeFloatLE(value[i], offset + i * 4);
72
- }
73
- },
74
- 'double[]': (value, buffer, offset, maxLen) => {
75
- for (let i = 0; i < value.length && i < maxLen; i++) {
76
- buffer.writeDoubleLE(value[i], offset + i * 8);
77
- }
78
- },
79
- };
80
- /**
81
- * A dictionary containing functions that deserialize a certain value based on the field type
82
- */
83
- exports.DESERIALIZERS = {
84
- // special types
85
- 'uint8_t_mavlink_version': (buffer, offset) => buffer.readUInt8(offset),
86
- // singular types
87
- 'char': (buffer, offset) => String.fromCharCode(buffer.readUInt8(offset)),
88
- 'int8_t': (buffer, offset) => buffer.readInt8(offset),
89
- 'uint8_t': (buffer, offset) => buffer.readUInt8(offset),
90
- 'int16_t': (buffer, offset) => buffer.readInt16LE(offset),
91
- 'uint16_t': (buffer, offset) => buffer.readUInt16LE(offset),
92
- 'int32_t': (buffer, offset) => buffer.readInt32LE(offset),
93
- 'uint32_t': (buffer, offset) => buffer.readUInt32LE(offset),
94
- 'int64_t': (buffer, offset) => buffer.readBigInt64LE(offset),
95
- 'uint64_t': (buffer, offset) => buffer.readBigUInt64LE(offset),
96
- 'float': (buffer, offset) => buffer.readFloatLE(offset),
97
- 'double': (buffer, offset) => buffer.readDoubleLE(offset),
98
- // array types
99
- 'char[]': (buffer, offset, length) => {
100
- let result = '';
101
- for (let i = 0; i < length; i++) {
102
- const charCode = buffer.readUInt8(offset + i);
103
- if (charCode !== 0) {
104
- result += String.fromCharCode(charCode);
105
- }
106
- else {
107
- break;
108
- }
109
- }
110
- return result;
111
- },
112
- 'int8_t[]': (buffer, offset, length) => {
113
- const result = new Array(length);
114
- for (let i = 0; i < length; i++)
115
- result[i] = buffer.readInt8(offset + i);
116
- return result;
117
- },
118
- 'uint8_t[]': (buffer, offset, length) => {
119
- const result = new Array(length);
120
- for (let i = 0; i < length; i++)
121
- result[i] = buffer.readUInt8(offset + i);
122
- return result;
123
- },
124
- 'int16_t[]': (buffer, offset, length) => {
125
- const result = new Array(length);
126
- for (let i = 0; i < length; i++)
127
- result[i] = buffer.readInt16LE(offset + i * 2);
128
- return result;
129
- },
130
- 'uint16_t[]': (buffer, offset, length) => {
131
- const result = new Array(length);
132
- for (let i = 0; i < length; i++)
133
- result[i] = buffer.readUInt16LE(offset + i * 2);
134
- return result;
135
- },
136
- 'int32_t[]': (buffer, offset, length) => {
137
- const result = new Array(length);
138
- for (let i = 0; i < length; i++)
139
- result[i] = buffer.readInt32LE(offset + i * 4);
140
- return result;
141
- },
142
- 'uint32_t[]': (buffer, offset, length) => {
143
- const result = new Array(length);
144
- for (let i = 0; i < length; i++)
145
- result[i] = buffer.readUInt32LE(offset + i * 4);
146
- return result;
147
- },
148
- 'int64_t[]': (buffer, offset, length) => {
149
- const result = new Array(length);
150
- for (let i = 0; i < length; i++)
151
- result[i] = buffer.readBigInt64LE(offset + i * 8);
152
- return result;
153
- },
154
- 'uint64_t[]': (buffer, offset, length) => {
155
- const result = new Array(length);
156
- for (let i = 0; i < length; i++)
157
- result[i] = buffer.readBigUInt64LE(offset + i * 8);
158
- return result;
159
- },
160
- 'float[]': (buffer, offset, length) => {
161
- const result = new Array(length);
162
- for (let i = 0; i < length; i++)
163
- result[i] = buffer.readFloatLE(offset + i * 4);
164
- return result;
165
- },
166
- 'double[]': (buffer, offset, length) => {
167
- const result = new Array(length);
168
- for (let i = 0; i < length; i++)
169
- result[i] = buffer.readDoubleLE(offset + i * 8);
170
- return result;
171
- },
172
- };
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.DESERIALIZERS=exports.SERIALIZERS=void 0,exports.SERIALIZERS={uint8_t_mavlink_version:(r,e,n)=>e.writeUInt8(r,n),char:(r,e,n)=>e.writeUInt8(r,n),int8_t:(r,e,n)=>e.writeInt8(r,n),uint8_t:(r,e,n)=>e.writeUInt8(r,n),int16_t:(r,e,n)=>e.writeInt16LE(r,n),uint16_t:(r,e,n)=>e.writeUInt16LE(r,n),int32_t:(r,e,n)=>e.writeInt32LE(r,n),uint32_t:(r,e,n)=>e.writeUInt32LE(r,n),int64_t:(r,e,n)=>e.writeBigInt64LE(r,n),uint64_t:(r,e,n)=>e.writeBigUInt64LE(r,n),float:(r,e,n)=>e.writeFloatLE(r,n),double:(r,e,n)=>e.writeDoubleLE(r,n),"char[]":(r,e,n,i)=>{for(let t=0;t<r.length&&t<i;t++){const o=r.charCodeAt(t);e.writeUInt8(o,n+t)}},"int8_t[]":(r,e,n,i)=>{for(let t=0;t<r.length&&t<i;t++)e.writeInt8(r[t],n+t)},"uint8_t[]":(r,e,n,i)=>{for(let t=0;t<r.length&&t<i;t++)e.writeUInt8(r[t],n+t)},"int16_t[]":(r,e,n,i)=>{for(let t=0;t<r.length&&t<i;t++)e.writeInt16LE(r[t],n+t*2)},"uint16_t[]":(r,e,n,i)=>{for(let t=0;t<r.length&&t<i;t++)e.writeUInt16LE(r[t],n+t*2)},"int32_t[]":(r,e,n,i)=>{for(let t=0;t<r.length&&t<i;t++)e.writeInt32LE(r[t],n+t*4)},"uint32_t[]":(r,e,n,i)=>{for(let t=0;t<r.length&&t<i;t++)e.writeUInt32LE(r[t],n+t*4)},"int64_t[]":(r,e,n,i)=>{for(let t=0;t<r.length&&t<i;t++)e.writeBigInt64LE(r[t],n+t*8)},"uint64_t[]":(r,e,n,i)=>{for(let t=0;t<r.length&&t<i;t++)e.writeBigUInt64LE(r[t],n+t*8)},"float[]":(r,e,n,i)=>{for(let t=0;t<r.length&&t<i;t++)e.writeFloatLE(r[t],n+t*4)},"double[]":(r,e,n,i)=>{for(let t=0;t<r.length&&t<i;t++)e.writeDoubleLE(r[t],n+t*8)}},exports.DESERIALIZERS={uint8_t_mavlink_version:(r,e)=>r.readUInt8(e),char:(r,e)=>String.fromCharCode(r.readUInt8(e)),int8_t:(r,e)=>r.readInt8(e),uint8_t:(r,e)=>r.readUInt8(e),int16_t:(r,e)=>r.readInt16LE(e),uint16_t:(r,e)=>r.readUInt16LE(e),int32_t:(r,e)=>r.readInt32LE(e),uint32_t:(r,e)=>r.readUInt32LE(e),int64_t:(r,e)=>r.readBigInt64LE(e),uint64_t:(r,e)=>r.readBigUInt64LE(e),float:(r,e)=>r.readFloatLE(e),double:(r,e)=>r.readDoubleLE(e),"char[]":(r,e,n)=>{let i="";for(let t=0;t<n;t++){const o=r.readUInt8(e+t);if(o!==0)i+=String.fromCharCode(o);else break}return i},"int8_t[]":(r,e,n)=>{const i=new Array(n);for(let t=0;t<n;t++)i[t]=r.readInt8(e+t);return i},"uint8_t[]":(r,e,n)=>{const i=new Array(n);for(let t=0;t<n;t++)i[t]=r.readUInt8(e+t);return i},"int16_t[]":(r,e,n)=>{const i=new Array(n);for(let t=0;t<n;t++)i[t]=r.readInt16LE(e+t*2);return i},"uint16_t[]":(r,e,n)=>{const i=new Array(n);for(let t=0;t<n;t++)i[t]=r.readUInt16LE(e+t*2);return i},"int32_t[]":(r,e,n)=>{const i=new Array(n);for(let t=0;t<n;t++)i[t]=r.readInt32LE(e+t*4);return i},"uint32_t[]":(r,e,n)=>{const i=new Array(n);for(let t=0;t<n;t++)i[t]=r.readUInt32LE(e+t*4);return i},"int64_t[]":(r,e,n)=>{const i=new Array(n);for(let t=0;t<n;t++)i[t]=r.readBigInt64LE(e+t*8);return i},"uint64_t[]":(r,e,n)=>{const i=new Array(n);for(let t=0;t<n;t++)i[t]=r.readBigUInt64LE(e+t*8);return i},"float[]":(r,e,n)=>{const i=new Array(n);for(let t=0;t<n;t++)i[t]=r.readFloatLE(e+t*4);return i},"double[]":(r,e,n)=>{const i=new Array(n);for(let t=0;t<n;t++)i[t]=r.readDoubleLE(e+t*8);return i}};
package/dist/lib/utils.js CHANGED
@@ -1,77 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.waitFor = exports.sleep = exports.dump = exports.hex = void 0;
4
- /**
5
- * Convert a number to hexadecimal representation with a minumum
6
- * number of characters and optional prefix (0x by default)
7
- *
8
- * @param n value to convert
9
- * @param len length of the converted string (without prefix)
10
- * @param prefix prefix to prepend the generated string with
11
- */
12
- function hex(n, len = 2, prefix = '0x') {
13
- return `${prefix}${n.toString(16).padStart(len, '0')}`;
14
- }
15
- exports.hex = hex;
16
- /**
17
- * Dump a buffer in a readable form
18
- *
19
- * @param buffer buffer to dump
20
- * @param lineWidth width of the line, in bytes of buffer
21
- */
22
- function dump(buffer, lineWidth = 16) {
23
- const line = [];
24
- let address = 0;
25
- for (let i = 0; i < buffer.length; i++) {
26
- line.push(hex(buffer[i], 2, '0x'));
27
- if (line.length === lineWidth) {
28
- console.log(hex(address, 4), '|', line.join(' '));
29
- address += lineWidth;
30
- line.length = 0;
31
- }
32
- }
33
- if (line.length > 0) {
34
- console.log(hex(address, 4), '|', line.join(' '));
35
- }
36
- }
37
- exports.dump = dump;
38
- /**
39
- * Sleep for a given number of miliseconds
40
- *
41
- * @param ms number of miliseconds to sleep
42
- */
43
- function sleep(ms) {
44
- return new Promise(resolve => setTimeout(resolve, ms));
45
- }
46
- exports.sleep = sleep;
47
- /**
48
- * Execute a callback every <code>interval</code>ms and if it will not return
49
- * a truthy value in the <code>timeout<code>ms then throw a Timeout exception.
50
- * This is a very useful utility that will allow you to specify how often
51
- * a particular expression should be evaluated and how long will it take to end
52
- * the execution without success. Great for time-sensitive operations.
53
- *
54
- * @param cb callback to call every <code>interval</code>ms
55
- * @param timeout number of miliseconds that need to pass before the Timeout exception is thrown
56
- * @param interval number of miliseconds before re-running the callback
57
- */
58
- async function waitFor(cb, timeout = 10000, interval = 100) {
59
- return new Promise((resolve, reject) => {
60
- const timeoutTimer = setTimeout(() => {
61
- cleanup();
62
- reject('Timeout');
63
- }, timeout);
64
- const intervalTimer = setInterval(() => {
65
- const result = cb();
66
- if (result) {
67
- cleanup();
68
- resolve(result);
69
- }
70
- });
71
- const cleanup = () => {
72
- clearTimeout(timeoutTimer);
73
- clearTimeout(intervalTimer);
74
- };
75
- });
76
- }
77
- exports.waitFor = waitFor;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.waitFor=exports.sleep=exports.dump=exports.hex=void 0;function hex(t,o=2,e="0x"){return`${e}${t.toString(16).padStart(o,"0")}`}exports.hex=hex;function dump(t,o=16){const e=[];let r=0;for(let n=0;n<t.length;n++)e.push(hex(t[n],2,"0x")),e.length===o&&(console.log(hex(r,4),"|",e.join(" ")),r+=o,e.length=0);e.length>0&&console.log(hex(r,4),"|",e.join(" "))}exports.dump=dump;function sleep(t){return new Promise(o=>setTimeout(o,t))}exports.sleep=sleep;async function waitFor(t,o=1e4,e=100){return new Promise((r,n)=>{const l=setTimeout(()=>{s(),n("Timeout")},o),u=setInterval(()=>{const i=t();i&&(s(),r(i))}),s=()=>{clearTimeout(l),clearTimeout(u)}})}exports.waitFor=waitFor;
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env -S npx ts-node
2
+
3
+ import { createReadStream } from 'fs'
4
+ import { MavLinkPacketSplitter, MavLinkPacketParser } from '..'
5
+ import {
6
+ minimal, common, ardupilotmega, uavionix, icarous,
7
+ asluav, development, ualberta,
8
+ } from '..'
9
+
10
+ const splitter = new MavLinkPacketSplitter()
11
+ const parser = new MavLinkPacketParser()
12
+ const file = createReadStream(__dirname + '/vtol.tlog')
13
+ const reader = file.pipe(splitter).pipe(parser)
14
+
15
+ // create a registry of mappings between a message id and a data class
16
+ const REGISTRY = {
17
+ ...minimal.REGISTRY,
18
+ ...common.REGISTRY,
19
+ ...ardupilotmega.REGISTRY,
20
+ ...uavionix.REGISTRY,
21
+ ...icarous.REGISTRY,
22
+ ...asluav.REGISTRY,
23
+ ...development.REGISTRY,
24
+ ...ualberta.REGISTRY,
25
+ }
26
+
27
+ reader.on('data', packet => {
28
+ const clazz = REGISTRY[packet.header.msgid]
29
+ if (clazz) {
30
+ const data = packet.protocol.data(packet.payload, clazz)
31
+ if (packet.header.timestamp) {
32
+ console.log(new Date(Number(packet.header.timestamp)).toISOString(), data)
33
+ } else {
34
+ console.log(data)
35
+ }
36
+ }
37
+ })
38
+
39
+ file.on('close', () => {
40
+ console.log('\n\nNumber of invalid packages:', splitter.invalidPackages)
41
+ console.log('Number of unknown packages:', splitter.unknownPackagesCount)
42
+ console.log('\nTotal number of consumed packets:', splitter.validPackages)
43
+ })
@@ -7,14 +7,10 @@ import {
7
7
  asluav, development, ualberta,
8
8
  } from '..'
9
9
 
10
- const file = createReadStream('./GH-5.bin')
11
-
12
10
  const splitter = new MavLinkPacketSplitter()
13
-
14
- const reader = file
15
- .pipe(splitter)
16
- .pipe(new MavLinkPacketParser())
17
-
11
+ const parser = new MavLinkPacketParser()
12
+ const file = createReadStream('./GH-5.bin')
13
+ const reader = file.pipe(splitter).pipe(parser)
18
14
 
19
15
  // create a registry of mappings between a message id and a data class
20
16
  const REGISTRY = {
@@ -41,4 +37,3 @@ file.on('close', () => {
41
37
  console.log('Number of unknown packages:', splitter.unknownPackagesCount)
42
38
  console.log('\nTotal number of consumed packets:', splitter.validPackages)
43
39
  })
44
-
@@ -1,12 +1,18 @@
1
1
  #!/usr/bin/env -S npx ts-node
2
2
 
3
- import * as SerialPort from 'serialport'
4
- import { MavLinkPacketSplitter, MavLinkPacketParser, MavLinkPacket } from '..'
5
- import { common, waitFor, send } from '..'
3
+ import { SerialPort } from 'serialport'
4
+ import { MavLinkPacketRegistry, MavLinkPacketSplitter, MavLinkPacketParser, MavLinkPacket } from '..'
5
+ import { minimal, common, ardupilotmega, waitFor, send } from '..'
6
+
7
+ const REGISTRY: MavLinkPacketRegistry = {
8
+ ...minimal.REGISTRY,
9
+ ...common.REGISTRY,
10
+ ...ardupilotmega.REGISTRY,
11
+ }
6
12
 
7
13
  async function main() {
8
14
  // Create an output stream to write data to the controller
9
- const port = new SerialPort('/dev/ttyACM0')
15
+ const port = new SerialPort({ path: '/dev/ttyACM0', baudRate: 115200 })
10
16
 
11
17
  // Create the reader as usual by piping the source stream through the splitter
12
18
  // and packet parser
@@ -21,7 +27,13 @@ async function main() {
21
27
  // This is the place where all your application-level logic will exist
22
28
  reader.on('data', (packet: MavLinkPacket) => {
23
29
  online = true
24
- console.log(packet.debug())
30
+ const clazz = REGISTRY[packet.header.msgid]
31
+ if (clazz) {
32
+ const data = packet.protocol.data(packet.payload, clazz)
33
+ console.log('>', data)
34
+ } else {
35
+ console.log('!', packet.debug())
36
+ }
25
37
  })
26
38
 
27
39
  // Wait for the remote system to be available
@@ -1,16 +1,22 @@
1
1
  #!/usr/bin/env -S npx ts-node
2
2
 
3
- import * as SerialPort from 'serialport'
3
+ import { SerialPort } from 'serialport'
4
4
  import { MavLinkPacketSplitter, MavLinkPacketParser } from '..'
5
- import { MavLinkPacket, MavLinkPacketSignature } from '..'
6
- import { common, waitFor, sendSigned } from '..'
5
+ import { MavLinkPacket, MavLinkPacketSignature, MavLinkPacketRegistry } from '..'
6
+ import { minimal, common, ardupilotmega, waitFor, sendSigned } from '..'
7
+
8
+ const REGISTRY: MavLinkPacketRegistry = {
9
+ ...minimal.REGISTRY,
10
+ ...common.REGISTRY,
11
+ ...ardupilotmega.REGISTRY,
12
+ }
7
13
 
8
14
  // Use your own secret passphrase in place of 'qwerty'
9
15
  const key = MavLinkPacketSignature.key('qwerty')
10
16
 
11
17
  async function main() {
12
18
  // Create an output stream to write data to the controller
13
- const port = new SerialPort('/dev/ttyACM0')
19
+ const port = new SerialPort({ path: '/dev/ttyACM0', baudRate: 115200 })
14
20
 
15
21
  // Create the reader as usual by piping the source stream through the splitter
16
22
  // and packet parser
@@ -25,7 +31,6 @@ async function main() {
25
31
  // This is the place where all your application-level logic will exist
26
32
  reader.on('data', (packet: MavLinkPacket) => {
27
33
  online = true
28
- console.log(packet.debug())
29
34
  if (packet.signature) {
30
35
  if (packet.signature.matches(key)) {
31
36
  console.log('Signature check OK')
@@ -35,6 +40,13 @@ async function main() {
35
40
  } else {
36
41
  console.log('Packet not signed')
37
42
  }
43
+ const clazz = REGISTRY[packet.header.msgid]
44
+ if (clazz) {
45
+ const data = packet.protocol.data(packet.payload, clazz)
46
+ console.log('>', data)
47
+ } else {
48
+ console.log('!', packet.debug())
49
+ }
38
50
  })
39
51
 
40
52
  // Wait for the remote system to be available
@@ -1,7 +1,13 @@
1
1
  #!/usr/bin/env -S npx ts-node
2
2
 
3
- import { MavEsp8266, common } from '../dist'
4
- import { MavLinkPacket, MavLinkPacketSignature } from '../dist'
3
+ import { MavEsp8266, minimal, common, ardupilotmega } from '..'
4
+ import { MavLinkPacketSignature, MavLinkPacket, MavLinkPacketRegistry } from '..'
5
+
6
+ const REGISTRY: MavLinkPacketRegistry = {
7
+ ...minimal.REGISTRY,
8
+ ...common.REGISTRY,
9
+ ...ardupilotmega.REGISTRY,
10
+ }
5
11
 
6
12
  // Use your own secret passphrase in place of 'qwerty'
7
13
  const key = MavLinkPacketSignature.key('qwerty')
@@ -14,8 +20,6 @@ async function main() {
14
20
 
15
21
  // log incomming messages
16
22
  port.on('data', (packet: MavLinkPacket) => {
17
- console.log(packet.debug())
18
- console.log(packet.debug())
19
23
  if (packet.signature) {
20
24
  if (packet.signature.matches(key)) {
21
25
  console.log('Signature check OK')
@@ -25,6 +29,13 @@ async function main() {
25
29
  } else {
26
30
  console.log('Packet not signed')
27
31
  }
32
+ const clazz = REGISTRY[packet.header.msgid]
33
+ if (clazz) {
34
+ const data = packet.protocol.data(packet.payload, clazz)
35
+ console.log('>', data)
36
+ } else {
37
+ console.log('!', packet.debug())
38
+ }
28
39
  })
29
40
 
30
41
  // You're now ready to send messages to the controller using the socket
@@ -1,7 +1,13 @@
1
1
  #!/usr/bin/env -S npx ts-node
2
2
 
3
- import { MavEsp8266, common } from '..'
4
- import { MavLinkPacket } from '..'
3
+ import { MavEsp8266, minimal, common, ardupilotmega } from '..'
4
+ import { MavLinkPacket, MavLinkPacketRegistry } from '..'
5
+
6
+ const REGISTRY: MavLinkPacketRegistry = {
7
+ ...minimal.REGISTRY,
8
+ ...common.REGISTRY,
9
+ ...ardupilotmega.REGISTRY,
10
+ }
5
11
 
6
12
  async function main() {
7
13
  const port = new MavEsp8266()
@@ -13,7 +19,13 @@ async function main() {
13
19
 
14
20
  // log incomming messages
15
21
  port.on('data', (packet: MavLinkPacket) => {
16
- console.log(packet.debug())
22
+ const clazz = REGISTRY[packet.header.msgid]
23
+ if (clazz) {
24
+ const data = packet.protocol.data(packet.payload, clazz)
25
+ console.log('>', data)
26
+ } else {
27
+ console.log('!', packet.debug())
28
+ }
17
29
  })
18
30
 
19
31
  // You're now ready to send messages to the controller using the socket
Binary file
package/lib/mavlink.ts CHANGED
@@ -12,6 +12,7 @@ import { SERIALIZERS, DESERIALIZERS } from './serialization'
12
12
  * Header definition of the MavLink packet
13
13
  */
14
14
  export class MavLinkPacketHeader {
15
+ timestamp: BigInt = null
15
16
  magic: number = 0
16
17
  payloadLength: uint8_t = 0
17
18
  incompatibilityFlags: uint8_t = 0
@@ -47,7 +48,7 @@ export abstract class MavLinkProtocol {
47
48
  /**
48
49
  * Deserialize packet header
49
50
  */
50
- abstract header(buffer): MavLinkPacketHeader
51
+ abstract header(buffer, timestamp?): MavLinkPacketHeader
51
52
 
52
53
  /**
53
54
  * Deserialize packet checksum
@@ -139,7 +140,7 @@ export class MavLinkProtocolV1 extends MavLinkProtocol {
139
140
  return buffer
140
141
  }
141
142
 
142
- header(buffer: Buffer): MavLinkPacketHeader {
143
+ header(buffer: Buffer, timestamp = null): MavLinkPacketHeader {
143
144
  this.log.trace('Reading header from buffer (len:', buffer.length, ')')
144
145
 
145
146
  const startByte = buffer.readUInt8(0)
@@ -148,6 +149,7 @@ export class MavLinkProtocolV1 extends MavLinkProtocol {
148
149
  }
149
150
 
150
151
  const result = new MavLinkPacketHeader()
152
+ result.timestamp = timestamp
151
153
  result.magic = startByte
152
154
  result.payloadLength = buffer.readUInt8(1)
153
155
  result.seq = buffer.readUInt8(2)
@@ -272,7 +274,7 @@ export class MavLinkProtocolV2 extends MavLinkProtocol {
272
274
  return result - MavLinkProtocolV2.PAYLOAD_OFFSET
273
275
  }
274
276
 
275
- header(buffer: Buffer): MavLinkPacketHeader {
277
+ header(buffer: Buffer, timestamp = null): MavLinkPacketHeader {
276
278
  this.log.trace('Reading header from buffer (len:', buffer.length, ')')
277
279
 
278
280
  const startByte = buffer.readUInt8(0)
@@ -281,6 +283,7 @@ export class MavLinkProtocolV2 extends MavLinkProtocol {
281
283
  }
282
284
 
283
285
  const result = new MavLinkPacketHeader()
286
+ result.timestamp = timestamp
284
287
  result.magic = startByte
285
288
  result.payloadLength = buffer.readUInt8(1)
286
289
  result.incompatibilityFlags = buffer.readUInt8(2)
@@ -484,6 +487,7 @@ export class MavLinkPacketSplitter extends Transform {
484
487
 
485
488
  private buffer = Buffer.from([])
486
489
  private onCrcError = null
490
+ private timestamp = null
487
491
  private _validPackagesCount = 0
488
492
  private _unknownPackagesCount = 0
489
493
  private _invalidPackagesCount = 0
@@ -494,7 +498,7 @@ export class MavLinkPacketSplitter extends Transform {
494
498
  * @param onCrcError callback executed if there is a CRC error (mostly for debugging)
495
499
  */
496
500
  constructor(opts = {}, onCrcError: BufferCallback = () => {}) {
497
- super(opts)
501
+ super({ ...opts, objectMode: true })
498
502
  this.onCrcError = onCrcError
499
503
  }
500
504
 
@@ -508,6 +512,12 @@ export class MavLinkPacketSplitter extends Transform {
508
512
  break
509
513
  }
510
514
 
515
+ // if the current offset is exactly the size of the timestamp field from tlog then read it.
516
+ if (offset === 8) {
517
+ this.timestamp = Buffer.from(this.buffer, 0, 8).readBigUInt64BE() / 1000n
518
+ } else {
519
+ this.timestamp = null
520
+ }
511
521
  // fast-forward the buffer to the first start byte
512
522
  if (offset > 0) {
513
523
  this.buffer = this.buffer.slice(offset)
@@ -546,7 +556,7 @@ export class MavLinkPacketSplitter extends Transform {
546
556
  case PacketValidationResult.VALID:
547
557
  this.log.debug('Found a valid packet')
548
558
  this._validPackagesCount++
549
- this.push(buffer)
559
+ this.push({ buffer, timestamp: this.timestamp })
550
560
  // truncate the buffer to remove the current message
551
561
  this.buffer = this.buffer.slice(expectedBufferLength)
552
562
  break
@@ -717,16 +727,16 @@ export class MavLinkPacketParser extends Transform {
717
727
  }
718
728
  }
719
729
 
720
- _transform(chunk: Buffer, encoding, callback: TransformCallback) {
721
- const protocol = this.getProtocol(chunk)
722
- const header = protocol.header(chunk)
723
- const payload = protocol.payload(chunk)
724
- const crc = protocol.crc(chunk)
730
+ _transform({ buffer = Buffer.from([]), timestamp = null, ...rest } = {}, encoding, callback: TransformCallback) {
731
+ const protocol = this.getProtocol(buffer)
732
+ const header = protocol.header(buffer, timestamp)
733
+ const payload = protocol.payload(buffer)
734
+ const crc = protocol.crc(buffer)
725
735
  const signature = protocol instanceof MavLinkProtocolV2
726
- ? protocol.signature(chunk, header)
736
+ ? protocol.signature(buffer, header)
727
737
  : null
728
738
 
729
- const packet = new MavLinkPacket(chunk, header, payload, crc, protocol, signature)
739
+ const packet = new MavLinkPacket(buffer, header, payload, crc, protocol, signature)
730
740
 
731
741
  callback(null, packet)
732
742
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mavlink",
3
- "version": "1.0.13",
3
+ "version": "1.2.0",
4
4
  "author": "Matthias Hryniszak <padcom@gmail.com>",
5
5
  "license": "LGPL",
6
6
  "description": "MavLink definitions and parsing library",
@@ -22,23 +22,24 @@
22
22
  "main": "dist/index.js",
23
23
  "types": "dist/index.d.ts",
24
24
  "dependencies": {
25
- "mavlink-mappings": "^1.0.8-20220318"
25
+ "mavlink-mappings": "^1.0.9-20220424"
26
26
  },
27
27
  "scripts": {
28
- "build": "tsc",
29
- "test": "jest",
28
+ "build": "tsc && minimize-js dist",
29
+ "test": "jest && npm run test:batch",
30
+ "test:batch": "npx ts-node tests/main.ts e2e --input tests/data.mavlink",
30
31
  "dev": "jest --watch",
31
32
  "test:e2e": "cd tests && ./main.ts e2e --input data.mavlink",
32
- "prepublishOnly": "rm -rf dist && npm install && npm test && npm run test:e2e && npm run build"
33
+ "prepublishOnly": "rm -rf dist && npm install && npm run build && npm test"
33
34
  },
34
35
  "devDependencies": {
35
36
  "@types/jest": "^27.4.1",
36
37
  "@types/node": "^15.14.9",
37
- "@types/serialport": "^8.0.1",
38
38
  "@types/xml2js": "^0.4.8",
39
39
  "@types/yargs": "^17.0.8",
40
40
  "jest": "^27.5.1",
41
- "serialport": "^9.0.7",
41
+ "minimize-js": "^1.3.0",
42
+ "serialport": "^10.0.0",
42
43
  "ts-jest": "^27.1.4",
43
44
  "ts-node": "^9.1.1",
44
45
  "typescript": "^4.4.3",
package/tests/main.ts CHANGED
@@ -3,8 +3,8 @@
3
3
  import yargs from 'yargs'
4
4
  import { existsSync, createReadStream } from 'fs'
5
5
  import { minimal, common, ardupilotmega } from 'mavlink-mappings'
6
- import { createMavLinkStream, MavLinkPacket, Logger, LogLevel } from '..'
7
- import { hex, dump } from '..'
6
+ import { createMavLinkStream, MavLinkPacket, Logger, LogLevel, MavLinkPacketRegistry } from '..'
7
+ import { dump } from '..'
8
8
 
9
9
  Logger.on('log', ({ context, level, message }) => {
10
10
  if (level <= LogLevel.error) {
@@ -36,7 +36,7 @@ async function main() {
36
36
 
37
37
  const command = config._[0]
38
38
  if (command === 'e2e') {
39
- const REGISTRY = {
39
+ const REGISTRY: MavLinkPacketRegistry = {
40
40
  ...minimal.REGISTRY,
41
41
  ...common.REGISTRY,
42
42
  ...ardupilotmega.REGISTRY,
@@ -48,11 +48,7 @@ async function main() {
48
48
  reader.on('data', (packet: MavLinkPacket) => {
49
49
  const clazz = REGISTRY[packet.header.msgid]
50
50
  if (clazz) {
51
- const message = packet.protocol.data(packet.payload, clazz)
52
- console.log('<', packet.debug())
53
- clazz.FIELDS.forEach(field => {
54
- console.log(clazz.MSG_NAME + '.' + field.source + ' = ' + message[field.name])
55
- })
51
+ packet.protocol.data(packet.payload, clazz)
56
52
  } else {
57
53
  console.log('< (unknown)', packet.debug())
58
54
  }
@@ -1 +0,0 @@
1
- {}