SK
Signal K•3mo ago
night199uk

night199uk - i'm trying to make some updates to...

i'm trying to make some updates to signalk-to-nmea2000 to add new PGNs (raymarine autopilot PGNs again). to get the newer PGNs that are in canboat/canboatjs, i need to update the canboatjs version that signalk-to-nmea2000 pulls in (it's an old 2.x). i notice that canboatjs has moved to camelCase. this breaks all the tests in signalk-to-nmea2000 when updating the canboatjs version > 3.0.0. is anyone already working on a PR for this, any guidance on a simple way to fix? @Scott Bender probably
47 Replies
Scott Bender
Scott Bender•3mo ago
But you can still update the version, when in sk canboatjs is output it both camelCase and the old way Thus how it is currently working in the latest sk server versions which use the latest canboatjs
night199uk
night199ukOP•3mo ago
yeah. updating the version within signalk-to-nmea2000 broke the other tests 🙂 will that PR landing ^^^ automagically fix the tests in signalk-to-nmea2000?
Scott Bender
Scott Bender•3mo ago
Yes But I don’t know when I’m going to get around to finishing that…
night199uk
night199ukOP•3mo ago
okay, so it's not helpful for me to start working on that in signalk-to-nmea20000 is it something i could help with? now i got my boat back in the water and living aboard - i really want to get 130848 and 130918 working so i can use signalk to drive my raymarine autopilot full time. my axiom 2 pro's SUCK and Lighthouse 4 has so many bugs and issues and i just need to get rid of them and move to signalk as my plotter. we sail full time now and i can't deal with how bad lighthouse 4 is. 🤦‍♂️
Scott Bender
Scott Bender•3mo ago
The AP plugin does not work for you? Sorry, on the phone, what are those pgns?
night199uk
night199ukOP•3mo ago
the AP plugin lets me do simple +1 / +10. but 130848 and 130918 + 129284/129285 let me follow a full pre-programmed route from signalk/freeboard.
Scott Bender
Scott Bender•3mo ago
You can update the tests to turn off camelCase
night199uk
night199ukOP•3mo ago
i.e. i can make a route in freeboard and then hit "track" on the AP and the boat just folllows the full track.
Scott Bender
Scott Bender•3mo ago
Or turn on camelCaseCompat mode
night199uk
night199ukOP•3mo ago
@Scott Bender any tips on how to do that? otherwise i can go spelunking. i am motivated to get this working and have a few weeks sat here in annapolis until the boat show.
Scott Bender
Scott Bender•3mo ago
GitHub
signalk-to-nmea2000/test/test.js at 444a955854a1159684cde0990cdec08...
Plugin to convert Signal K to NMEA2000. Contribute to SignalK/signalk-to-nmea2000 development by creating an account on GitHub.
night199uk
night199ukOP•3mo ago
i see, so at the parser creation we can control the mode? let me go digging on that. thanks!
Scott Bender
Scott Bender•3mo ago
const parser = new FromPgn({useCamelCompat: true}) actually, should probably const parser = new FromPgn({useCamelCase: false}) will be sailing past Annapolis tomorrow...
night199uk
night199ukOP•3mo ago
okay, doesn't work off the bat, but that gets me a breadcrumb. let me work on this. would you accept an interim PR just to update package.json and enable compat? come say hi! where you going?
Scott Bender
Scott Bender•3mo ago
Wye River
night199uk
night199ukOP•3mo ago
oh nice. going to the boat show in a few weeks? or heading straight past?
Scott Bender
Scott Bender•3mo ago
I am local, on the Magothy River, so I will be at the boat show I am surprised that does not work...checking sorry, the option is useCamel not useCamelCase
night199uk
night199ukOP•3mo ago
const parser = new FromPgn({useCamel: false}) yup, just found. 🙂 works. there are some other minors now, but I can clean this up and PR these which will unblock me. after updating to canboatjs > 3.x for this, i'm seeing an issue with encoding/decoding just one pgn in the test suite - 126720 (Seatalk Display Brightness) i've simplified this to the following simple test case; which successfully encodes the PGN but fails to decode it. this is a simpler version of the test in the signalk-to-nmea2000 test suite.
const { pgnToActisenseSerialFormat, FromPgn } = require("@canboat/canboatjs");
const parser = new FromPgn()

res = {
pgn: 126720,
dst: 255,
'Manufacturer Code': 'Raymarine',
'Industry Code': 'Marine Industry',
'Proprietary ID': '0x0c8c',
Group: 'Helm 2',
'Unknown 1': 1,
Command: 'Brightness',
Brightness: 85,
'Unknown 2': 0
}
let encoded = pgnToActisenseSerialFormat(res);

// All parse to same JSON structure
[encoded].forEach(message => {
const json = parser.parseString(message)
console.log("%o", json);
if (json) {
console.log(`PGN ${json.pgn}: ${json.description}`)
}
})
const { pgnToActisenseSerialFormat, FromPgn } = require("@canboat/canboatjs");
const parser = new FromPgn()

res = {
pgn: 126720,
dst: 255,
'Manufacturer Code': 'Raymarine',
'Industry Code': 'Marine Industry',
'Proprietary ID': '0x0c8c',
Group: 'Helm 2',
'Unknown 1': 1,
Command: 'Brightness',
Brightness: 85,
'Unknown 2': 0
}
let encoded = pgnToActisenseSerialFormat(res);

// All parse to same JSON structure
[encoded].forEach(message => {
const json = parser.parseString(message)
console.log("%o", json);
if (json) {
console.log(`PGN ${json.pgn}: ${json.description}`)
}
})
trying to debug this myself but it's deeper in canboat/canboatjs so it'll take me time to understand all of whats going on there. highly suspect you could figure this out faster than me.
Scott Bender
Scott Bender•3mo ago
That’s interesting because I am having an issue with my signalk-n2k-displays plugin, but that is with changing the color. Brightness is working b Note that you can use that plugin to change the brightness via PUT I suspect the two issues are related. I’ll look into it this weekend…
night199uk
night199ukOP•3mo ago
ahh. looking deeper, it looks like perhaps seatalk brightness is not making it into the PGNs that canboatjs knows? oh, i don't need to change it myself. I'm just trying to get signalk-to-nmea2000 working and passing the test suite with canboatjs > 3.0.0 adding some debug in FromPgn.readPGN, i only see seatalk1PilotMode in pgnData as a possible PGN to decode 126720 to. I don't see seatalk1DisplayBrightness as a decode option. so the issue is probably deeper in findMatchPgns somewhere. working on that. aha. so the problem is in readPgns, findMatchPgns is only returning one entry (seatalk1PilotMode), despite there being multiple instances of 126720 in pgnList that have Match entries defined... getting there.
return pgnList.**find**((f) => {
console.log("fields: %o", f.Fields);
return f.Fields.find((f) => f.Match !== undefined);
});
return pgnList.**find**((f) => {
console.log("fields: %o", f.Fields);
return f.Fields.find((f) => f.Match !== undefined);
});
find only returns the first match from the array, in this case pgnList. as far as I grok the code, we want all PGNs with a Match entry defined.
Scott Bender
Scott Bender•3mo ago
Hmm. Yeah. That would do it. That should be filter() I think
night199uk
night199ukOP•3mo ago
hrm, sort of. getting close. what is the goal of findMatchPgn? the code expects findMatchPgn to return a singular pgn (pgnData), not a list. i changed the find to filter; which returns a list, but this breaks further down. it would seem like the goal of findMatchPgn is to find the exact pgn, given a list of PGNs, that we should use to parse our incoming pgn. but findMatchPgns isn't complex enough to do that.
Scott Bender
Scott Bender•3mo ago
I need to take a closer look at the code. I think you are right. That should find the exact match. I am underway now…
night199uk
night199ukOP•3mo ago
cool, no worries. just noodling on this. trying to unblock myself, no rush. is there a simple way to make canboatjs 3.x fall back on the old canboat parsing code? i guess from what i'm reading here you're moving the pgn parsing up into canboatjs./
Scott Bender
Scott Bender•3mo ago
The parsing has always been there. But this part has changed a lot If the only thing blocking you for now is the tests. Just install and use your local version of the plugin until I figure this out?
night199uk
night199ukOP•3mo ago
am already doing that. just wanted to finish off this PR 🙂 also just figured i'd fix it myself & PR it instead of forcing you to work on it.
Scott Bender
Scott Bender•3mo ago
So something is wrong with that that findMatchingPGn function, I just don’t know what it is… And it does explain my issue…
night199uk
night199ukOP•3mo ago
yeah. i'm trying to figure out what findMatchPgn is trying to achieve, because we pass the full pgnList into readFields, and pgnData is just "startDef" i assume we want to read all the fields from all of the possible PGNs in a kind of scatter approach, and then i guess we filter the list later to only output PGNs in which all the fields match otherwise findMatchPgn needs to be much more complex, and needs to accept the incoming PGN and then actually do the matching of match fields let me try a few things okay, so from what i can surmise, findMatchPgn is only to get the list of PGNs with a "Match" field defined; that could possibly be candidates for decoding the PGN. it can't go further than that as the pgn is not yet decoded. so it's to find a list of possible decoders for the pgn. therefore; it can't actually do the matching. it should return a list of possible matchPgns in my mind. this means readFields needs to change. by the time we call findMatchPgn the pgn is not yet decoded, so we can't actually "do" the matching in findMatchPgn.
Scott Bender
Scott Bender•3mo ago
I don’t think issue is in the decoding. It’s in the encoding
night199uk
night199ukOP•3mo ago
i thought that originally too. the actisense stream "looked" wrong, but didn't dig into it enough to check.
Scott Bender
Scott Bender•3mo ago
If it was in decoding, there would tons of issues coming up One way to check is by running the encoded data through the canboat analyzer
night199uk
night199ukOP•3mo ago
fair, let me try that
Scott Bender
Scott Bender•3mo ago
And part of our confusion here, I thought we were talking about encoding! 🤣 When encoding, this kind of match happens, but it’s an exact match. Where as when decoding, we are looking for the list of possible pgns as we decode more fields.
night199uk
night199ukOP•3mo ago
yup, that makes sense with what i read.
Scott Bender
Scott Bender•3mo ago
Seems like it might not be finding the correct pgn definition to decode?
night199uk
night199ukOP•3mo ago
is there a way to send an actisense string like this to canboat analyzer? 2025-09-26T15:42:18.401Z,2,126720,0,255,21,3b,9f,8c,ff,ff,01,00,00,ff,ff,ff,00,00,00,00,00,00,00,00,00,00
Scott Bender
Scott Bender•3mo ago
Yes Just run analyzer and paste that Same with analyzerjs
night199uk
night199ukOP•3mo ago
yes. what i see of the decoder is that it finds the first or any pgn with a Match field and uses that to decode the fields in the PGN. then tries to match those values against the "possibly" pgn list.
Scott Bender
Scott Bender•3mo ago
Yep
night199uk
night199ukOP•3mo ago
yup, canboat also doesn't decode it: 2025-09-26T15:42:18.401Z,2,126720,0,255,21,3b,9f,8c,ff,ff,01,00,00,ff,ff,ff,00,00,00,00,00,00,00,00,00,00 2025-09-26T15:42:18.401Z 2 0 255 126720 0x1EF00: Manufacturer Proprietary fast-packet addressed: Manufacturer Code = Raymarine; Industry Code = Marine; Data = 8C FF FF 01 00 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 that's the top level PGN of 126720. 126720 is heavily overloaded with manufacturer definitions it looks like, there is Garmin stuff in there, raymarine stuff in there. so looks like there is an encoding issue for sure. (or canboat has the same bug as canboatjs) aha. so i went back to canboatjs 2.x and made it encode the same pgn canboatjs 2.x: 2025-09-26T15:59:09.022Z,2,126720,0,255,9,3b,9f,8c,0c,02,01,00,55,00 canboatjs 3.x.x: 2025-09-26T15:42:18.401Z,2,126720,0,255,21,3b,9f,8c,ff,ff,01,00,00,ff,ff,ff,00,00,00,00,00,00,00,00,00,00 good call. let me try and make canboatjs 3.x decode the canboatjs 2.x pgn canboatjs3.x:
2025-09-26T15:59:09.022Z,2,126720,0,255,9,3b,9f,8c,0c,02,01,00,55,00
{
prio: 2,
pgn: 126720,
dst: 255,
src: 0,
timestamp: '2025-09-26T15:59:09.022Z',
fields: {
manufacturerCode: 'Raymarine',
industryCode: 'Marine Industry',
proprietaryId: 'Display',
command1: 'Settings',
group: 'Helm 2',
shared: 'Shared',
command: 'Brightness',
brightness: 85,
unknown2: 0
},
description: 'Seatalk1: Display Brightness',
id: 'seatalk1DisplayBrightness'
}
PGN 126720: Seatalk1: Display Brightness
2025-09-26T15:59:09.022Z,2,126720,0,255,9,3b,9f,8c,0c,02,01,00,55,00
{
prio: 2,
pgn: 126720,
dst: 255,
src: 0,
timestamp: '2025-09-26T15:59:09.022Z',
fields: {
manufacturerCode: 'Raymarine',
industryCode: 'Marine Industry',
proprietaryId: 'Display',
command1: 'Settings',
group: 'Helm 2',
shared: 'Shared',
command: 'Brightness',
brightness: 85,
unknown2: 0
},
description: 'Seatalk1: Display Brightness',
id: 'seatalk1DisplayBrightness'
}
PGN 126720: Seatalk1: Display Brightness
it's an encoding issue not a decoding one, you're right.
Scott Bender
Scott Bender•3mo ago
So my guess is that it is not finding the right pgn definition to encode But that’s a huge guess!!
night199uk
night199ukOP•3mo ago
looking now getting there...
matching Manufacturer Code 1851 Raymarine true
matched Manufacturer Code 1851
matching Industry Code 4 Marine Industry true
matched Industry Code 4
matching Proprietary ID 240 0x0c8c true
matching command 129 undefined false
matching Seatalk1 Command 132 undefined false
matching Manufacturer Code 1851 Raymarine true
matched Manufacturer Code 1851
matching Industry Code 4 Marine Industry true
matched Industry Code 4
matching Proprietary ID 240 0x0c8c true
matching command 129 undefined false
matching Seatalk1 Command 132 undefined false
🤦‍♂️
Scott Bender
Scott Bender•3mo ago
??
night199uk
night199ukOP•3mo ago
"Proprietary ID": "0x0c8c", the original test case for Raymarine Brightness had Proprietary ID encoded like this I don't know how this is supposed to map, but the encoder in canboatjs 3.x no longer groks this. prop ID is meant to be a lookup value with these: LookupEnumeration: 'SEATALK_MESSAGE_ID',
{
"Name":"SEATALK_MESSAGE_ID",
"MaxValue":255,
"EnumValues":[
{"Name":"Seatalk 1 Encoded", "Value":240},
{"Name":"Display", "Value":140},
{"Name":"Pilot Configuration", "Value":108}
]
},
{
"Name":"SEATALK_MESSAGE_ID",
"MaxValue":255,
"EnumValues":[
{"Name":"Seatalk 1 Encoded", "Value":240},
{"Name":"Display", "Value":140},
{"Name":"Pilot Configuration", "Value":108}
]
},
so somehow the encoder was mapping 0xc8c to that enum; or more likely encoding it literally into the field. in canboatjs 3.x that doesn't work. changing: "Proprietary ID": "DIsplay", fixes it. now with canboatjs 3.x: 2025-09-26T16:30:10.680Z,2,126720,0,255,9,3b,9f,8c,ff,02,ff,00,55,00 canboatjs 2.x: 2025-09-26T15:59:09.022Z,2,126720,0,255,9,3b,9f,8c,0c,02,01,00,55,00 still a difference, but closer. i'm guessing the differences now are from updates to the field definition yup, the definitions of all the seatalk commands were updated underneath and this test case wasn't updated... simple fix now.
Scott Bender
Scott Bender•3mo ago
Well, dang
night199uk
night199ukOP•3mo ago
fixed
2025-09-26T16:39:58.016Z,2,126720,0,255,9,3b,9f,8c,0c,02,ff,00,55,00
{
prio: 2,
pgn: 126720,
dst: 255,
src: 0,
timestamp: '2025-09-26T16:39:58.016Z',
fields: {
manufacturerCode: 'Raymarine',
industryCode: 'Marine Industry',
proprietaryId: 'Display',
command1: 'Settings',
group: 'Helm 2',
command: 'Brightness',
brightness: 85,
unknown2: 0
},
description: 'Seatalk1: Display Brightness',
id: 'seatalk1DisplayBrightness'
}
PGN 126720: Seatalk1: Display Brightness
2025-09-26T16:39:58.016Z,2,126720,0,255,9,3b,9f,8c,0c,02,ff,00,55,00
{
prio: 2,
pgn: 126720,
dst: 255,
src: 0,
timestamp: '2025-09-26T16:39:58.016Z',
fields: {
manufacturerCode: 'Raymarine',
industryCode: 'Marine Industry',
proprietaryId: 'Display',
command1: 'Settings',
group: 'Helm 2',
command: 'Brightness',
brightness: 85,
unknown2: 0
},
description: 'Seatalk1: Display Brightness',
id: 'seatalk1DisplayBrightness'
}
PGN 126720: Seatalk1: Display Brightness
https://github.com/SignalK/signalk-to-nmea2000/pull/135

Did you find this page helpful?