Canboat typescript?
I would love some input from all you typescript experts, I am trying to bring canboat to ts.
https://github.com/sbender9/pgns/tree/types
This is generated from the canboat data
https://github.com/sbender9/pgns/blob/types/src/pgns.ts
And this is about the definitions
https://github.com/sbender9/pgns/blob/types/src/definition.ts
GitHub
GitHub - sbender9/pgns at types
Contribute to sbender9/pgns development by creating an account on GitHub.
GitHub
pgns/src/pgns.ts at types · sbender9/pgns
Contribute to sbender9/pgns development by creating an account on GitHub.
GitHub
pgns/src/definition.ts at types · sbender9/pgns
Contribute to sbender9/pgns development by creating an account on GitHub.
17 Replies
@Teppo Kurki @Brandon Keepers @Kees Verruijt
Is there something specific, like developer use cases, that you’d like to make easier or bring type safety to?
Yes, both for the canboatjs code , n2k-signalk, plugins, etc.
as a practical example: should we add a
sendN2K(pgn: PGN)
to the plugin API to make use of the pgn types?
timetimestamp is not optional in PGN, but if I construct a message to be sent i would not assign that. likewise source. should there be separate types for an abstract "PGNData" object, with just the data fields, and another AddressedPGN
with source and dest and third for ReceivedPGN
? or just make the addresses and timestamp optional?
the one pgns.ts to rule them all file is a bit unwieldy, how about breaking the enums to enums.ts?the enums are now compiler-checked constants that map to string values that you can use when constructing PGNs. what about the other way, when decoding? If i had some received pgn data and wanted to do a lookup on same lookup field value, like tank type with value 1 the current enums are no help
typescript has also Numeric Enums that provide Reverse Mappings: from numeric value to the name of the enum value
...or is canboatjs going to taking care of all this, parsing and encoding, and code outside canboatjs only deals with PGN objects, not the raw data?
numeric lookups can also wait until somebody needs them, just pointing out that one could leverage ts enums in this
Handbook - Enums
How TypeScript enums work
have you tried converting n2k-signalk or sk-to-n2k to ts using these? or something else, like autopilot plugin
Yes, canboatjs deals with that, the enums are strings coming out of canboatjs. (always have been)
yes!
I've done the initial pass of converting canboatjs to typescript, going to start on n2k-signalk today...
I think I
I think I'll just make those optional
start of n2k-signal conversion https://github.com/SignalK/n2k-signalk/pull/287
All the PGN_xxxFields’ properties are optional. Doesn’t that make them less valuable, as the structure of the object can be kind of anything?
well, you still get type checking
and not all of them are, if they are "PartOfOrimaryKey", then not optional
other than that, we don't really know if they are optional or not, but most fields are optional
a recent change is tha now all the enum fields can be a number.,
pilotMode?: enums.SeatalkPilotMode16|number
for example
this is because it's possible that something comes in that is not in the lookup
don't love it, but don't know of any other way to deal with it
(just made fields that are only 1 bit, not optional)FYI. pgns moved to https://github.com/canboat/ts-pgns
GitHub
GitHub - canboat/ts-pgns: TypeScript Canboat PGN Definitions
TypeScript Canboat PGN Definitions. Contribute to canboat/ts-pgns development by creating an account on GitHub.
canboatjs now conerted to typescript
also of interest, a workflow that tests canboat.json changes with canboatjs, n2k-signalk and signalk-nmea2000, this will eventually get triggered any time canboat.json changes in the canboat repository
https://github.com/canboat/canboatjs/blob/ts-pgns/.github/workflows/test_canboat_changes.yml
GitHub
canboatjs/.github/workflows/test_canboat_changes.yml at ts-pgns · ...
Native javascript NMEA 2000 decoder and encoder. Contribute to canboat/canboatjs development by creating an account on GitHub.
signalk-to-nmea2000 converted to ts
https://github.com/SignalK/signalk-to-nmea2000/pull/128
And note that I have released canboatjs 3.1.x which uses the new ts-pgns package.
@Teppo Kurki this brings up an issue that I can’t find a great solution for. The new sk-to-n2k (and eventually others), won’t work with older versions of the server. This is because of the use of camelCase keys.
The best I can come up with is to have the plugin check the server version and refuse to start with an error message on the console.
Going forward, it would be great to have a way for plugins to specify min server version. Sadly, I don't see any way to add extra meta data to the info coming from npmjs.com. So, the only things I can think of:
1. Use keywords, so a plugin could add a keyword like
signalk-server-min-version-1.15.x
2. We have talked about moving away from npmjs.com and creating our own plugin registry.
Unless anyone has a better solution or wants to work on #2, I'll probably go ahead and implement #11. would mean removing the generic plugin keyword, or people with older servers would update the plugin to a nonfunctioning one
3. create sk-to-n2k-v2 with separate plugin id and the way you said, prompts people with older servers to upgrade. Then plugin updates won’t break people’s systems. Publish one more version of the old series that also prompts people to update to v2. Bootstrap v2 settings from v1
Is mapping from old keys to camelCase ones not feasible?
yeah, I was just thinking about that, or the other way around. I could map the camelCase keys to the old keys when running on an older server
canboatjs support both as input, so existing plugins that output N2K won't be broken
and by default, canboatjs outputs both camelCase and the old keys, so existing plugins/node-red flows won't be broken
(currently there is a switch in the admin-ui to turn that off)
I think I'll add a utility function in ts-pgns that maps from camelCase keys to the old keys, sk-to-n2k and other plugins can use that to support old versions of the server
For you typescript gurus, I am thinking there is probably a cooler way to do this.
Currently this is how you create pgn to be send out.
`
Any ideas on a more elegant way?
I think this is better?
And the result looks like: