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.
- package/.vscode/launch.json +11 -10
- package/README.md +5 -8
- package/dist/index.js +1 -21
- package/dist/lib/logger.js +1 -118
- package/dist/lib/mavesp.js +1 -99
- package/dist/lib/mavlink.d.ts +9 -4
- package/dist/lib/mavlink.js +1 -676
- package/dist/lib/serialization.js +1 -172
- package/dist/lib/utils.js +1 -77
- package/examples/parse-tlog-file.ts +43 -0
- package/examples/send-receive-file.ts +3 -8
- package/examples/send-receive-serial.ts +17 -5
- package/examples/send-receive-signed-serial.ts +17 -5
- package/examples/send-receive-signed-udp.ts +15 -4
- package/examples/send-receive-udp.ts +15 -3
- package/examples/vtol.tlog +0 -0
- package/lib/mavlink.ts +22 -12
- package/package.json +8 -7
- package/tests/main.ts +4 -8
- package/coverage/coverage-final.json +0 -1
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -101
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/serialization.ts.html +0 -613
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov.info +0 -0
@@ -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
|
15
|
-
|
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
|
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
|
-
|
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
|
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 '
|
4
|
-
import { MavLinkPacket,
|
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
|
-
|
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(
|
721
|
-
const protocol = this.getProtocol(
|
722
|
-
const header = protocol.header(
|
723
|
-
const payload = protocol.payload(
|
724
|
-
const crc = protocol.crc(
|
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(
|
736
|
+
? protocol.signature(buffer, header)
|
727
737
|
: null
|
728
738
|
|
729
|
-
const packet = new MavLinkPacket(
|
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
|
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.
|
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
|
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
|
-
"
|
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 {
|
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
|
-
|
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
|
-
{}
|