@canboat/canboatjs 3.5.3 → 3.6.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/.mocharc.js CHANGED
@@ -1,7 +1,6 @@
1
1
  module.exports = {
2
- require: ['ts-node/register'],
3
- extensions: ['ts', 'tsx', 'js'],
4
- timeout: 20000,
2
+ extensions: ['ts', 'js'],
3
+ timeout: 2000,
5
4
  exit: true,
6
5
  recursive: true
7
6
  }
package/README.md CHANGED
@@ -1,52 +1,629 @@
1
- # Canboatjs
1
+ # @canboat/canboatjs
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@canboat/canboatjs.svg)](https://www.npmjs.com/@canboat/canboatjs)
4
4
  [![Node.js CI & Test](https://github.com/canboat/canboatjs/actions/workflows/test.yml/badge.svg)](https://github.com/canboat/canboatjs/actions/workflows/test.yml)
5
5
  [![Test Canboat json Changes](https://github.com/canboat/canboatjs/actions/workflows/test_canboat_changes.yml/badge.svg)](https://github.com/canboat/canboatjs/actions/workflows/test_canboat_changes.yml)
6
6
  [![Test canboatjs dependents](https://github.com/canboat/canboatjs/actions/workflows/test_canboatjs_dependencies.yml/badge.svg)](https://github.com/canboat/canboatjs/actions/workflows/test_canboatjs_dependencies.yml)
7
7
 
8
- Pure javascript NMEA 2000 decoder and encoder
8
+ A TypeScript library for parsing, encoding, and interfacing with NMEA 2000 marine electronics networks. It used the PGN definition database from [canboat](https://github.com/canboat/canboat) with extensive device support, multiple data format compatibility, and PGN output.
9
9
 
10
- Canboatjs is a port of the canboat project (https://github.com/canboat/canboat) to javascript
10
+ ## Table of Contents
11
11
 
12
- # Features
12
+ - [Features](#features)
13
+ - [Architecture](#architecture)
14
+ - [Installation](#installation)
15
+ - [Quick Start](#quick-start)
16
+ - [Supported Devices](#supported-devices)
17
+ - [Command Line Tools](#command-line-tools)
18
+ - [API Reference](#api-reference)
19
+ - [Usage Examples](#usage-examples)
20
+ - [Device Integration](#device-integration)
21
+ - [Data Formats](#data-formats)
22
+ - [Contributing](#contributing)
23
+ - [License](#license)
13
24
 
14
- - Reads directly from CAN bus devices and NMEA 2000 gateways including:
15
- - Actisense NGT-1 and W2K-1
16
- - Digital Yacht iKonvert
17
- - Yacht Devices YDWG-02 and YDEN-02
18
- - Shipmodul MiniPlex-3-N2K
19
- - socketcan based devices
20
- - Parses input in canboat analyzer json format
21
- - Converts and outputs binary N2K format to supported devices
25
+ ## Features
22
26
 
23
- # PGN Descriptions
27
+ - **🔌 Multi-Device Support**: Direct interface with popular NMEA 2000 gateways and CAN bus devices
28
+ - **📡 Multiple Data Formats**: Parse and generate various N2K data formats (Actisense, iKonvert, YDWG, etc.)
29
+ - **🔄 Bidirectional**: Both decode incoming N2K messages and encode/transmit outgoing messages
30
+ - **🛠️ Command Line Tools**: Ready-to-use CLI utilities for data conversion and analysis
31
+ - **🎯 Type Safety**: Built with TypeScript and includes type definitions
32
+ - **📊 JSON Output**: Standardized JSON format compatible with Signal K and other marine data systems
24
33
 
25
- The details about the PGNs recognized by Canboatjs come from the canboat project in [canboat.json](https://github.com/canboat/canboat/blob/master/docs/canboat.json). If you want to add or update PGN details, please make changes to the [pgn.h file](https://github.com/canboat/canboat/blob/master/analyzer/pgn.h) in canboat and submit a pull request there. Include sample data and raise an issue here so that I can include your changes in Canboatjs.
34
+ ## Architecture
26
35
 
27
- # Command Line Programs
36
+ For an overview of how canboatjs integrates with signalk-server to create a complete marine data processing pipeline, see the [Architecture Diagram](./architecture-diagram.md).
28
37
 
29
- ## analyzerjs
38
+ The diagram illustrates:
39
+ - **Data Flow**: From NMEA 2000 hardware through parsing and conversion to Signal K format
40
+ - **Device Support**: Various hardware interfaces and data formats
41
+ - **Bidirectional Processing**: Both incoming data parsing and outgoing data generation
42
+ - **Integration Points**: How canboatjs works with other components in the marine data ecosystem
30
43
 
31
- This program is similar to the canboat `analyzer` command-line. It takes input in the actisense serial format and outputs canboat json for mat.
44
+ ## Installation
45
+
46
+ ### For Command Line Usage
47
+
48
+ ```bash
49
+ sudo npm install -g @canboat/canboatjs
50
+ ```
51
+
52
+ ### For Node.js Projects
53
+
54
+ ```bash
55
+ npm install @canboat/canboatjs
56
+ ```
57
+
58
+ ### Requirements
59
+
60
+ - **Node.js**: Version 20 or higher
61
+ - **Optional Dependencies**:
62
+ - `serialport`: For serial device communication
63
+ - `socketcan`: For direct CAN bus access on Linux
64
+
65
+ ## Quick Start
66
+
67
+ ### Basic Message Parsing
68
+
69
+ ```javascript
70
+ const { FromPgn } = require('@canboat/canboatjs')
71
+
72
+ // Create parser instance
73
+ const parser = new FromPgn()
74
+
75
+ // Handle warnings
76
+ parser.on('warning', (pgn, warning) => {
77
+ console.log(`[WARNING] PGN ${pgn.pgn}: ${warning}`)
78
+ })
79
+
80
+ // Parse an Actisense format message
81
+ const message = "2017-03-13T01:00:00.146Z,2,127245,204,255,8,fc,f8,ff,7f,ff,7f,ff,ff"
82
+ const json = parser.parseString(message)
83
+
84
+ if (json) {
85
+ console.log('Parsed PGN:', JSON.stringify(json, null, 2))
86
+ }
87
+ ```
88
+
89
+ ### Generate N2K Messages
90
+
91
+ ```javascript
92
+ const { pgnToActisenseSerialFormat } = require('@canboat/canboatjs')
93
+
94
+ // Create a rudder position message
95
+ const message = {
96
+ pgn: 127245,
97
+ prio: 2,
98
+ src: 204,
99
+ dst: 255,
100
+ fields: {
101
+ 'Instance': 252,
102
+ 'Direction Order': 0,
103
+ 'Reserved1': '62'
104
+ }
105
+ }
106
+
107
+ const actisenseString = pgnToActisenseSerialFormat(message)
108
+ console.log('Generated:', actisenseString)
109
+ ```
110
+
111
+ ## Supported Devices
112
+
113
+ ### NMEA 2000 Gateways
114
+ - **Actisense NGT-1** & **W2K-1** - USB and WiFi NMEA 2000 gateways
115
+ - **Digital Yacht iKonvert** - Serial to NMEA 2000 converter
116
+ - **Yacht Devices YDWG-02** & **YDEN-02** - WiFi and Ethernet gateways
117
+ - **Shipmodul MiniPlex-3-N2K** - Multi-protocol marine data multiplexer
118
+
119
+ ### CAN Bus Interfaces
120
+ - **SocketCAN devices** - Direct Linux CAN bus interface
121
+ - **Various CAN adapters** - Hardware CAN interfaces compatible with SocketCAN
122
+
123
+ ### Supported Data Formats
124
+ - **Actisense Serial Format** - Standard Actisense ASCII format
125
+ - **iKonvert Format** - Digital Yacht proprietary format
126
+ - **YDWG Raw Format** - Yacht Devices raw binary format
127
+ - **PCDIN Format** - Chetco Digital Instruments format
128
+ - **MXPGN Format** - MiniPlex-3 format
129
+ - **SocketCAN** - Linux CAN bus native format
130
+
131
+ ## Command Line Tools
132
+
133
+ Canboatjs includes several powerful command-line utilities:
134
+
135
+ ### `analyzerjs` - Message Analysis
136
+ Convert various N2K formats to standardized JSON:
137
+
138
+ ```bash
139
+ # From Actisense NGT-1
140
+ actisense-serialjs /dev/ttyUSB0 | analyzerjs
141
+
142
+ # From iKonvert
143
+ ikonvert-serial /dev/ttyUSB0 | analyzerjs
144
+
145
+ # From YDWG-02 over network
146
+ nc ydgw-ip 1475 | analyzerjs
147
+
148
+ # From W2K-1 WiFi gateway
149
+ nc w2k-1-ip 60002 | analyzerjs
150
+
151
+ # From SocketCAN
152
+ candumpjs can0
153
+
154
+ # Filter by specific PGN numbers
155
+ actisense-serialjs /dev/ttyUSB0 | analyzerjs --pgn 129025 # Position updates only
156
+ actisense-serialjs /dev/ttyUSB0 | analyzerjs --pgn 127245 # Rudder data only
157
+
158
+ # Filter by multiple PGNs
159
+ actisense-serialjs /dev/ttyUSB0 | analyzerjs --pgn 129025 --pgn 127245 --pgn 129029
160
+
161
+ # Filter by source address (device that sent the message)
162
+ actisense-serialjs /dev/ttyUSB0 | analyzerjs --src 15 # From device address 15
163
+ actisense-serialjs /dev/ttyUSB0 | analyzerjs --src 127 # From device address 127
164
+
165
+ # Filter by destination address
166
+ actisense-serialjs /dev/ttyUSB0 | analyzerjs --dst 255 # Broadcast messages only
167
+ actisense-serialjs /dev/ttyUSB0 | analyzerjs --dst 204 # Messages to device 204
168
+
169
+ # Filter by manufacturer
170
+ actisense-serialjs /dev/ttyUSB0 | analyzerjs --manufacturer "Garmin"
171
+
172
+ # Combine multiple filters
173
+ actisense-serialjs /dev/ttyUSB0 | analyzerjs --pgn 129025 --src 15 --dst 255
174
+
175
+ # Pretty print JSON output
176
+ actisense-serialjs /dev/ttyUSB0 | analyzerjs --pgn 129025 --pretty
177
+
178
+ # Process log files with filtering
179
+ analyzerjs --file my_log.txt --pgn 129025 --pgn 127245 --src 15
180
+ ```
181
+
182
+ ### `to-pgn` - Message Generation
183
+ Convert JSON to various N2K formats:
184
+
185
+ ```bash
186
+ echo '{"pgn":127245,"fields":{"Instance":0}}' | to-pgn --format=actisense
187
+ ```
188
+
189
+ ### `candumpjs` - Direct CAN Access
190
+ Read from SocketCAN without installing can-utils:
191
+
192
+ ```bash
193
+ # Basic CAN bus monitoring
194
+ candumpjs can0
195
+
196
+ # Filter by specific PGN numbers
197
+ candumpjs can0 --pgn 129025 # Position updates only
198
+ candumpjs can0 --pgn 127245 # Rudder data only
199
+
200
+ # Filter by multiple PGNs
201
+ candumpjs can0 --pgn 129025 --pgn 127245 --pgn 129029
202
+
203
+ # Filter by source address (device that sent the message)
204
+ candumpjs can0 --src 15 # From device address 15
205
+ candumpjs can0 --src 127 # From device address 127
206
+
207
+ # Filter by destination address
208
+ candumpjs can0 --dst 255 # Broadcast messages only
209
+ candumpjs can0 --dst 204 # Messages to device 204
210
+
211
+ # Filter by manufacturer
212
+ candumpjs can0 --manufacturer "Garmin"
213
+
214
+ # Combine multiple filters
215
+ candumpjs can0 --pgn 129025 --src 15 --dst 255
216
+
217
+ # Output in Actisense format instead of JSON
218
+ candumpjs can0 --format actisense
219
+
220
+ # Pretty print JSON with filtering
221
+ candumpjs can0 --pgn 129025 --pretty
222
+
223
+ # Common PGN filters for navigation data
224
+ candumpjs can0 --pgn 129025 --pgn 129026 --pgn 129029 # GPS position data
225
+ candumpjs can0 --pgn 127245 --pgn 127250 # Rudder and heading
226
+ candumpjs can0 --pgn 128267 --pgn 128259 # Depth and speed
227
+ ```
228
+
229
+ ### `ydvr-file` - YDVR File Processing
230
+ Process Yacht Devices recorder files:
231
+
232
+ ```bash
233
+ ydvr-file recording.ydvr | analyzerjs
234
+ ```
235
+
236
+ ### Additional Tools
237
+ - `actisense-file` - Process Actisense log files
238
+ - `actisense-n2k-tcp` - TCP server for Actisense data
239
+ - `cansend` - Send CAN messages
240
+ - `ikonvert-serial` - iKonvert serial interface
241
+
242
+ ### Message Filtering
243
+
244
+ Both `analyzerjs` and `candumpjs` support powerful filtering options to focus on specific data:
245
+
246
+ #### PGN Filtering
247
+ Filter by Parameter Group Number to see only specific message types:
248
+
249
+ ```bash
250
+ # Navigation data
251
+ --pgn 129025 # Position, Rapid Update
252
+ --pgn 129026 # COG & SOG, Rapid Update
253
+ --pgn 129029 # GNSS Position Data
254
+ --pgn 127250 # Vessel Heading
255
+
256
+ # Engine data
257
+ --pgn 127488 # Engine Parameters, Rapid Update
258
+ --pgn 127489 # Engine Parameters, Dynamic
259
+
260
+ # Environmental data
261
+ --pgn 128267 # Water Depth
262
+ --pgn 128259 # Speed
263
+ --pgn 130311 # Environmental Parameters
264
+
265
+ # Multiple PGNs
266
+ --pgn 129025 --pgn 129026 --pgn 127250
267
+ ```
268
+
269
+ #### Source and Destination Filtering
270
+ Filter by device addresses to monitor specific devices or message types:
271
+
272
+ ```bash
273
+ # Source address filtering (device that sent the message)
274
+ --src 15 # Messages from device address 15 (often a chartplotter)
275
+ --src 127 # Messages from device address 127 (often a GPS)
276
+ --src 204 # Messages from device address 204 (often an autopilot)
277
+
278
+ # Destination address filtering
279
+ --dst 255 # Broadcast messages (most common)
280
+ --dst 204 # Directed messages to device 204
281
+ --dst 15 # Directed messages to device 15
282
+
283
+ # Multiple source/destination addresses
284
+ --src 15 --src 127 --dst 255
285
+ ```
286
+
287
+ #### Manufacturer Filtering
288
+ Filter by device manufacturer:
289
+
290
+ ```bash
291
+ --manufacturer "Garmin"
292
+ --manufacturer "Raymarine"
293
+ --manufacturer "Simrad"
294
+ --manufacturer "Furuno"
295
+ ```
296
+
297
+ #### Practical Examples
298
+
299
+ ```bash
300
+ # Monitor only GPS position data from all devices
301
+ candumpjs can0 --pgn 129025 --pgn 129029
302
+
303
+ # Watch rudder and autopilot commands
304
+ actisense-serialjs /dev/ttyUSB0 | analyzerjs --pgn 127245 --pgn 127237
305
+
306
+ # Filter Garmin devices only
307
+ nc chartplotter-ip 1475 | analyzerjs --manufacturer "Garmin"
308
+
309
+ # Monitor messages from chartplotter (address 15) to autopilot (address 204)
310
+ candumpjs can0 --src 15 --dst 204
311
+
312
+ # Watch GPS data from specific device
313
+ actisense-serialjs /dev/ttyUSB0 | analyzerjs --pgn 129025 --src 127
314
+
315
+ # Monitor all broadcast navigation messages
316
+ candumpjs can0 --pgn 129025 --pgn 129026 --pgn 127250 --dst 255
317
+
318
+ # Combine filters for specific Garmin GPS data
319
+ candumpjs can0 --pgn 129025 --manufacturer "Garmin" --pretty
320
+
321
+ # Debug communication between specific devices
322
+ analyzerjs --file network_log.txt --src 15 --dst 204 --pretty
323
+ ```
324
+
325
+ #### Common PGN Reference
326
+
327
+ | PGN | Description | Use Case |
328
+ |-----|-------------|----------|
329
+ | **129025** | Position, Rapid Update | GPS lat/lon monitoring |
330
+ | **129026** | COG & SOG, Rapid Update | Course and speed tracking |
331
+ | **129029** | GNSS Position Data | Detailed GPS information |
332
+ | **127250** | Vessel Heading | Compass/heading data |
333
+ | **127245** | Rudder | Steering position |
334
+ | **127237** | Heading/Track Control | Autopilot commands |
335
+ | **128267** | Water Depth | Depth sounder data |
336
+ | **128259** | Speed | Speed through water |
337
+ | **127488** | Engine Parameters, Rapid | RPM, temperature |
338
+ | **130311** | Environmental Parameters | Air/water temperature |
339
+
340
+ #### Understanding Source and Destination
341
+
342
+ NMEA 2000 messages include source (src) and destination (dst) address fields:
343
+
344
+ - **Source (src)**: Address of the device sending the message (0-251)
345
+ - **Destination (dst)**: Target device address, or 255 for broadcast
346
+
347
+ Both `analyzerjs` and `candumpjs` support filtering by these address fields using `--src` and `--dst` options. Common device addresses:
348
+
349
+ - **15**: Often a chartplotter/display
350
+ - **127**: Often a GPS receiver
351
+ - **204**: Often an autopilot
352
+ - **255**: Broadcast to all devices (most common for dst)
32
353
 
33
354
  Examples:
355
+ ```bash
356
+ # Filter messages from GPS receiver
357
+ analyzerjs --src 127
358
+
359
+ # Filter only broadcast messages
360
+ candumpjs can0 --dst 255
361
+
362
+ # Monitor autopilot commands (directed messages to address 204)
363
+ analyzerjs --dst 204 --pgn 127237
364
+ ```
365
+
366
+ ## API Reference
367
+
368
+ ### Core Classes
369
+
370
+ #### `FromPgn` - Message Parser
371
+ ```javascript
372
+ const parser = new FromPgn(options)
373
+ parser.parseString(message) // Parse single message
374
+ parser.parse(buffer) // Parse binary data
375
+ ```
376
+
377
+ #### `canbus` - CAN Bus Interface
378
+ ```javascript
379
+ const canbus = new canbus(options)
380
+ canbus.sendPGN(message) // Send N2K message
381
+ ```
382
+
383
+ #### Device-Specific Streams
384
+ - `Ydwg02` - Yacht Devices YDWG-02 interface
385
+ - `W2k01` - Actisense W2K-1 interface
386
+ - `iKonvert` - Digital Yacht iKonvert interface
387
+ - `Venus` - Victron Venus OS interface
388
+ - `serial` - Actisense NGT-1 serial interface
389
+
390
+ ### Utility Functions
391
+
392
+ ```javascript
393
+ const {
394
+ parseN2kString, // Parse N2K string formats
395
+ isN2KString, // Detect N2K string format
396
+ toActisenseSerialFormat, // Convert to Actisense format
397
+ pgnToActisenseSerialFormat,
398
+ pgnToiKonvertSerialFormat,
399
+ pgnToYdgwRawFormat,
400
+ lookupEnumerationValue, // Get enumeration values
401
+ lookupEnumerationName, // Get enumeration names
402
+ discover // Network device discovery
403
+ } = require('@canboat/canboatjs')
404
+ ```
405
+
406
+ ## Usage Examples
407
+
408
+ ### Data Streaming
409
+
410
+ ```javascript
411
+ const { FromPgn, serial } = require('@canboat/canboatjs')
412
+
413
+ // Connect to Actisense NGT-1
414
+ const actisense = new serial({
415
+ device: '/dev/ttyUSB0',
416
+ baudrate: 115200
417
+ })
418
+
419
+ const parser = new FromPgn()
420
+
421
+ actisense.pipe(parser)
422
+
423
+ parser.on('pgn', (pgn) => {
424
+ if (pgn.pgn === 129025) { // Position Rapid Update
425
+ console.log(`Lat: ${pgn.fields.Latitude}, Lon: ${pgn.fields.Longitude}`)
426
+ }
427
+ })
428
+ ```
429
+
430
+ ### Device Discovery
431
+
432
+ ```javascript
433
+ const { discover } = require('@canboat/canboatjs')
434
+
435
+ // Discover NMEA 2000 devices on network
436
+ discover((device) => {
437
+ console.log(`Found device: ${device.name} at ${device.address}:${device.port}`)
438
+ })
439
+ ```
440
+
441
+ ### Working with Multiple Formats
442
+
443
+ ```javascript
444
+ const { FromPgn } = require('@canboat/canboatjs')
445
+ const parser = new FromPgn()
446
+
447
+ // Actisense format
448
+ const actisense = "2017-03-13T01:00:00.146Z,2,127245,204,255,8,fc,f8,ff,7f,ff,7f,ff,ff"
449
+
450
+ // YDWG-02 format
451
+ const ydwg = "16:29:27.082 R 09F8017F 50 C3 B8 13 47 D8 2B C6"
452
+
453
+ // MiniPlex-3 format
454
+ const miniplex = "$MXPGN,01F801,2801,C1308AC40C5DE343*19"
455
+
456
+ // All parse to same JSON structure
457
+ [actisense, ydwg, miniplex].forEach(message => {
458
+ const json = parser.parseString(message)
459
+ if (json) {
460
+ console.log(`PGN ${json.pgn}: ${json.description}`)
461
+ }
462
+ })
463
+ ```
464
+
465
+ ### Custom Device Integration
466
+
467
+ ```javascript
468
+ const { SimpleCan } = require('@canboat/canboatjs')
469
+
470
+ // Create virtual N2K device
471
+ const device = new SimpleCan({
472
+ canDevice: 'can0',
473
+ preferredAddress: 35,
474
+ addressClaim: {
475
+ "Unique Number": 139725,
476
+ "Manufacturer Code": 'My Company',
477
+ "Device Function": 130,
478
+ "Device Class": 'Navigation',
479
+ "Device Instance Lower": 0,
480
+ "Device Instance Upper": 0,
481
+ "System Instance": 0,
482
+ "Industry Group": 'Marine'
483
+ },
484
+ productInfo: {
485
+ "NMEA 2000 Version": 1300,
486
+ "Product Code": 667,
487
+ "Model ID": "MyDevice-1000",
488
+ "Software Version Code": "1.0",
489
+ "Model Version": "1.0",
490
+ "Model Serial Code": "123456"
491
+ }
492
+ }, (message) => {
493
+ // Handle incoming messages
494
+ console.log('Received:', message)
495
+ })
496
+
497
+ device.start()
498
+ ```
499
+
500
+ ## Data Formats
501
+
502
+ ### Input Format Support
503
+
504
+ | Format | Description | Example |
505
+ |--------|-------------|---------|
506
+ | **Actisense** | Standard timestamped CSV | `2017-03-13T01:00:00.146Z,2,127245,204,255,8,fc,f8,ff,7f,ff,7f,ff,ff` |
507
+ | **Actisense N2K ASCII** | Actisense ASCII format | `A764027.880 CCF52 1F10D FC10FF7FFF7FFFFF` |
508
+ | **YDWG Raw** | Yacht Devices binary | `16:29:27.082 R 09F8017F 50 C3 B8 13 47 D8 2B C6` |
509
+ | **iKonvert** | Digital Yacht base64 | `!PDGY,127245,255,/Pj/f/9///8=` |
510
+ | **PCDIN** | Chetco Digital | `$PCDIN,01F119,00000000,0F,2AAF00D1067414FF*59` |
511
+ | **MXPGN** | MiniPlex-3 | `$MXPGN,01F801,2801,C1308AC40C5DE343*19` |
512
+ | **candump1** | Linux CAN utils (Angstrom) | `<0x18eeff01> [8] 05 a0 be 1c 00 a0 a0 c0` |
513
+ | **candump2** | Linux CAN utils (Debian) | `can0 09F8027F [8] 00 FC FF FF 00 00 FF FF` |
514
+ | **candump3** | Linux CAN utils (log) | `(1502979132.106111) slcan0 09F50374#000A00FFFF00FFFF` |
515
+
516
+ ### Output Format Support
517
+
518
+ Generate data in any supported format from JSON:
519
+
520
+ ```javascript
521
+ const message = { pgn: 127245, fields: { Instance: 0 } }
522
+
523
+ // Convert to different formats
524
+ const actisense = pgnToActisenseSerialFormat(message)
525
+ const ikonvert = pgnToiKonvertSerialFormat(message)
526
+ const ydwg = pgnToYdgwRawFormat(message)
527
+ const pcdin = pgnToPCDIN(message)
528
+ const mxpgn = pgnToMXPGN(message)
529
+ ```
530
+
531
+ ## Building from Source
532
+
533
+ ```bash
534
+ # Clone repository
535
+ git clone https://github.com/canboat/canboatjs.git
536
+ cd canboatjs
537
+
538
+ # Install dependencies
539
+ npm install
540
+
541
+ # Build TypeScript
542
+ npm run build
543
+
544
+ # Run tests
545
+ npm test
546
+
547
+ # Run with coverage
548
+ npm run code-coverage
549
+
550
+ # Lint and format
551
+ npm run format
552
+ ```
553
+
554
+ ## Testing
555
+
556
+ ```bash
557
+ # Run all tests
558
+ npm test
559
+
560
+ # Run with file watching
561
+ npm run dev-test
562
+
563
+ # Generate coverage report
564
+ npm run code-coverage
565
+ ```
566
+
567
+ ## PGN Definitions
568
+
569
+ The PGN (Parameter Group Number) definitions used by canboatjs come from the [canboat project](https://github.com/canboat/canboat) via [canboat.json](https://github.com/canboat/canboat/blob/master/docs/canboat.json).
570
+
571
+ ### Adding New PGNs
572
+
573
+ To add or update PGN definitions:
574
+
575
+ 1. **Submit changes to canboat**: Modify [pgn.h](https://github.com/canboat/canboat/blob/master/analyzer/pgn.h) in the upstream canboat project
576
+ 2. **Include sample data**: Provide real-world message examples
577
+ 3. **Create issue here**: Let us know about the changes so we can update canboatjs
578
+
579
+ This ensures consistency across the entire canboat ecosystem.
580
+
581
+ ## Contributing
582
+
583
+ We welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.md) for details.
584
+
585
+ ### Development Workflow
586
+
587
+ 1. Fork the repository
588
+ 2. Create a feature branch: `git checkout -b feature/amazing-feature`
589
+ 3. Make your changes with tests
590
+ 4. Run the test suite: `npm test`
591
+ 5. Run formating and linting: `npm run format`
592
+ 6. Commit following [Angular conventions](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#commits)
593
+ 7. Submit a Pull Request
594
+
595
+ ### Commit Message Format
596
+
597
+ Use the format: `<type>: <description>`
598
+
599
+ - **feat**: New feature
600
+ - **fix**: Bug fix
601
+ - **docs**: Documentation changes
602
+ - **style**: Code formatting
603
+ - **refactor**: Code restructuring
604
+ - **test**: Adding tests
605
+ - **chore**: Maintenance tasks
606
+
607
+ ## License
608
+
609
+ Licensed under the Apache License, Version 2.0. See [LICENSE.md](LICENSE.md) for details.
34
610
 
35
- - `actisense-serialjs /dev/ttyUSB0 | analyzerjs`
36
- - `ikonvert-serial /dev/ttyUSB0 | analyzerjs`
37
- - `nc ydgw 1475 | analyzerjs`
38
- - `nc w2k-1 6002 | analyzerjs` // port should be N2K ACSCII format server on a w2k-1
39
- - `candump can0 | analyzerjs`
611
+ ## Related Projects
40
612
 
41
- ## to-pgn
613
+ - **[@canboat/ts-pgns](https://github.com/canboat/ts-pgns)** - TypeScript PGN definitions
614
+ - **[canboat](https://github.com/canboat/canboat)** - Original C implementation
615
+ - **[Signal K](https://signalk.org/)** - Modern marine data standard
616
+ - **[Signal K Server](https://github.com/SignalK/signalk-server-node)** - Signal K server implementation
42
617
 
43
- This program takes input in the canboat json format and outputs actisense serial format.
618
+ ## Support
44
619
 
45
- ## candumpjs
620
+ - **Issues**: [GitHub Issues](https://github.com/canboat/canboatjs/issues)
621
+ - **Discussions**: [GitHub Discussions](https://github.com/canboat/canboatjs/discussions)
622
+ - **Signal K Community**: [Community](https://signalk.org/community/)
46
623
 
47
- Read directly from a socketcan device without the need to install can-utils
624
+ ---
48
625
 
49
- Example: `candumpjs can0`
626
+ Made with ⚓ by the Canboat project contributors
50
627
 
51
628
  ## ydvr-file
52
629