ArduPilot / node-mavlink

This project is providing native TypeScript bindings and tools for sending and receiving MavLink messages over a verity of medium

Repository from Github https://github.comArduPilot/node-mavlinkRepository from Github https://github.comArduPilot/node-mavlink

Crash on receiving message (in MavLinkPacketSplitter, MSG_ID_MAGIC_NUMBER is undefined)

Luzzifus opened this issue · comments

Hi,

I'm trying to get started with this library and literally just copy-pasted the example code from the readme. Whenever a message is received, the MavLinkPacketSplitter crashes with the following error trace:

TypeError: Cannot read properties of undefined (reading '21')
    at MavLinkPacketSplitter.validatePacket (D:\code\testmavlink\node_modules\node-mavlink\dist\lib\mavlink.js:1:10582)
    at MavLinkPacketSplitter._transform (D:\code\testmavlink\node_modules\node-mavlink\dist\lib\mavlink.js:1:9569)
    at MavLinkPacketSplitter.Transform._write (node:internal/streams/transform:184:23)
    at writeOrBuffer (node:internal/streams/writable:389:12)
    at _write (node:internal/streams/writable:330:10)
    at MavLinkPacketSplitter.Writable.write (node:internal/streams/writable:334:10)
    at SerialPort.ondata (node:internal/streams/readable:754:22)
    at SerialPort.emit (node:events:527:28)
    at addChunk (node:internal/streams/readable:315:12)
    at readableAddChunk (node:internal/streams/readable:289:9)

I already investigated a bit and it seems that it tries to access MSG_ID_MAGIC_NUMBER from mavlink-mappings, which resolves to undefined because in the required version of mavlink-mappings (1.0.9-20220424) this was removed.

I can manually fix it by upgrading the required version of mavlink-mappings to 1.0.11-20220706 and rebuilding the package. But it would be nice if it would work out of the box.

I see this was already discussed in #14 and #15, but as of today, the wrong version of mavlink-mappings is still linked.

**edit: How would I add magic numbers for my own custom messages without modifying the library itself? I can define, send and receive custom messages just fine, but I have to add their magic number manually to the magic numbers file in mavlink-mappings. What am I missing?

Hi @Luzzifus! Thanks for the hint. It should currently be automatically picked up (I mean the latest version). If that is not the case there are two options:

  • either your package-lock.json has the old version of mappings stored, in which case you will always get the old one
  • or your local npm cache didn't refresh properly in which case running npm cache clean -f would help

In point of fact I'd do both of the things to see if that'd help. My money is on the lock file, but you never know what'll happen.

As for generation of magic numbers by yourself, I think you might want to reconsider. Calculating the magic numbers takes knowledge of each and every field in the packet and that is really better of left to the npm package. But if you really really must here's a link to the part of the generator that does it:

https://github.com/ArduPilot/node-mavlink-mappings/blob/master/code-generator.ts#L335

Hope it helps.

Hi @padcom,
thanks for your reply and thank you for taking the time to help! =)

I'm using Yarn and I never used the node-mavlink or mavlink-mappings before. I even added them to a completely new test project (empty otherwise) just to make sure I'm not going insane or making some stupid mistake. But still whatever I do, version 1.0.9 of the mappings is auto installed and upgrading manually to the new version doesn't have any effect unless I rebuild the node-mavlink package manually.

As for the magic numbers:
I'm new to mavlink, so please forgive me any stupid questions! How would you suggest adding new message types without generating magic numbers myself? I was able to define my own message types just fine, but omitting the magic number led to the packet splitter dropping the messages as invalid.

@Luzzifus I promise I'll take a look at it Today in the evening, sorry for the delay.

@Luzzifus I was able to successfully reproduce this problem on a fresh minimalistic project with only node-mavlink and serialport packages installed:

#!/usr/bin/env node

const { SerialPort } = require('serialport')
const { createMavLinkStream } = require('node-mavlink')

const port = new SerialPort({ path: '/dev/ttyACM0', baudRate: 57600, autoOpen: true })
const parser = createMavLinkStream(port)
parser.on('data', packet => console.log(packet.debug()))

The output I get is something like this:

TypeError: Cannot read properties of undefined (reading '125')
    at MavLinkPacketSplitter.validatePacket (/home/padcom/projects/learning/mavlink-example/node_modules/node-mavlink/dist/lib/mavlink.js:1:10582)
    at MavLinkPacketSplitter._transform (/home/padcom/projects/learning/mavlink-example/node_modules/node-mavlink/dist/lib/mavlink.js:1:9569)
...

Does that match what you've seen?

@padcom Yes that's exactly what happened for me.

@Luzzifus Would you be able to verify if the latest version of node-mavlink pulls in all the correct packages? Here's a minimal project that does work for me:

$ mkdir node-mavlink-example
$ cd node-mavlink-example
$ npm init -y
$ npm install --save node-mavlink

At this point, it's vital to verify that the proper version has been installed. Check out node_modules/node-mavlink/package.json and node_modules/mavlink-mappings/package.json. node-mavlink should be in version 1.3.0 (or later) and mavlink-mappings should be 1.0.12-20220825-2 (or later). If it is not the case, remove node_modules, package-lock.json and NPM cache:

$ npm cache clean -f

Once all dependencies are correctly installed, put this into index.mjs

import { createReadStream } from 'node:fs'
import { createMavLinkStream } from 'node-mavlink'

const port = createReadStream('node_modules/node-mavlink/examples/GH-5.bin')
const parser = createMavLinkStream(port)
parser.on('data', packet => console.log(packet.debug()))

and this into index.cjs

const { createReadStream } = require('node:fs')
const { createMavLinkStream } = require('node-mavlink')

const port = createReadStream('node_modules/node-mavlink/examples/GH-5.bin')
const parser = createMavLinkStream(port)
parser.on('data', packet => console.log(packet.debug()))

Here's a bit of explanation:

  • .mjs files are treated by node 16.x and above as ES modules (using import statements)
  • .cjs files are treated by node 16.x and above as CommonJS modules (using require())

@Luzzifus Also, as a sanity check, you'll find the same content in node_modules/node-mavlink/sanity-check.mjs and node_modules/node-mavlink/sanity-check.cjs (you have to run them both from within node_modules/node-mavlink folder or else the example log file won't be found!). If that doesn't work then we have a problem :) But I am pretty sure this will work now. As an added bonus the mavlink-mappings have been updated to the latest version so you'll get the latest Mavlink package definitions - just in case you need them :)

@Luzzifus For convenience version 1.3.1 of node-mavlink has the sanity checks smart enough to know where to read the example log file from so they can be executed from any folder, for example from the root of your project:

$ ./node_modules/node-mavlink/sanity-check.mjs

or for CommonJS version:

$ ./node_modules/node-mavlink/sanity-check.cjs

@padcom I can confirm that it works now and the correct dependencies are installed. Thank you very much for fixing this so quickly! =)

Closing as compleled