@canboat/canboatjs 2.9.0 → 2.11.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/lib/fromPgn.js CHANGED
@@ -847,7 +847,7 @@ fieldTypeReaders[
847
847
  buf.writeUInt8(c, idx)
848
848
  }
849
849
 
850
- return buf.toString('ascii', 0, idx)
850
+ return buf.toString('utf-8', 0, idx)
851
851
  }
852
852
 
853
853
  fieldTypeReaders["String with start/stop byte"] = (pgn, field, bs) => {
@@ -891,18 +891,27 @@ fieldTypeReaders['STRING_FIX'] = (pgn, field, bs) => {
891
891
  }
892
892
 
893
893
  var lastbyte = buf[len-1]
894
- if (lastbyte == 0xff ||
895
- lastbyte == 32 ||
896
- lastbyte == 0 ||
897
- lastbyte == 64
898
- )
899
- {
900
- while (len > 0 && (buf[len - 1] == lastbyte))
901
- {
902
- len--;
903
- }
904
- }
905
- return buf.toString('ascii', 0, len)
894
+ while (len > 0 && (lastbyte == 0xff ||
895
+ lastbyte == 32 ||
896
+ lastbyte == 0 ||
897
+ lastbyte == 64
898
+ )) {
899
+ len--
900
+ lastbyte = buf[len-1]
901
+ }
902
+
903
+ //look for a zero byte, some proprietary Raymarine pgns do this
904
+ let zero = 0
905
+ while ( zero < len ) {
906
+ if ( buf[zero] == 0 ) {
907
+ len = zero
908
+ break
909
+ }
910
+ zero++
911
+ }
912
+ len = zero
913
+ let res = len > 0 ? buf.toString('ascii', 0, len) : undefined
914
+ return res
906
915
  }
907
916
 
908
917
  fieldTypeReaders['BITLOOKUP'] = (pgn, field, bs) => {
package/lib/ikonvert.js CHANGED
@@ -75,9 +75,11 @@ function iKonvertStream (options) {
75
75
  } else {
76
76
  that.sendPGN(msg)
77
77
  }
78
+ options.app.emit('connectionwrite', { providerId: options.providerId })
78
79
  })
79
80
  options.app.on(options.jsonOutEvent || 'nmea2000JsonOut', (msg) => {
80
81
  that.sendPGN(msg)
82
+ options.app.emit('connectionwrite', { providerId: options.providerId })
81
83
  })
82
84
 
83
85
  this.isSetup = false
@@ -0,0 +1,365 @@
1
+ /**
2
+ * Copyright 2025 Scott Bender (scott@scottbender.net)
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ const debug = require('debug')('canboatjs:n2kdevice')
18
+ const EventEmitter = require('events')
19
+ const _ = require('lodash')
20
+ const Uint64LE = require('int64-buffer').Uint64LE
21
+ const { defaultTransmitPGNs, getIndustryCode, getManufacturerCode, getDeviceClassCode } = require('./codes')
22
+ const { toPgn } = require('./toPgn')
23
+ let packageJson
24
+
25
+ try
26
+ {
27
+ packageJson = require('../' + 'package.json')
28
+ } catch (ex) {
29
+ }
30
+
31
+ const deviceTransmitPGNs = [ 60928, 59904, 126996, 126464 ]
32
+
33
+ class N2kDevice extends EventEmitter {
34
+ constructor (options) {
35
+ super()
36
+
37
+ if ( options.addressClaim ) {
38
+ this.addressClaim = options.addressClaim
39
+ this.addressClaim.pgn = 60928
40
+ this.addressClaim.dst = 255
41
+ this.addressClaim.prio = 6
42
+ } else {
43
+ this.addressClaim = {
44
+ pgn: 60928,
45
+ dst: 255,
46
+ prio:6,
47
+ "Unique Number": 1263,
48
+ "Manufacturer Code": 999,
49
+ "Device Function": 130, // PC gateway
50
+ "Device Class": 25, // Inter/Intranetwork Device
51
+ "Device Instance Lower": 0,
52
+ "Device Instance Upper": 0,
53
+ "System Instance": 0,
54
+ "Industry Group": 4, // Marine
55
+ "Reserved1": 1,
56
+ "Reserved2": 2
57
+ }
58
+ this.addressClaim["Unique Number"] = options.uniqueNumber || Math.floor(Math.random() * Math.floor(2097151))
59
+ }
60
+
61
+ let version = packageJson ? packageJson.version : "1.0"
62
+
63
+ if ( options.productInfo ) {
64
+ this.productInfo = options.productInfo
65
+ this.productInfo.pgn = 126996
66
+ this.productInfo.dst = 255
67
+ } else {
68
+ this.productInfo = {
69
+ pgn: 126996,
70
+ dst: 255,
71
+ "NMEA 2000 Version": 1300,
72
+ "Product Code": 667, // Just made up..
73
+ "Model ID": "Signal K",
74
+ "Model Version": "canboatjs",
75
+ "Model Serial Code": options.uniqueNumber ? options.uniqueNumber.toString() : "000001",
76
+ "Certification Level": 0,
77
+ "Load Equivalency": 1
78
+ }
79
+ }
80
+
81
+ this.productInfo["Software Version Code"] = version
82
+
83
+ if ( options.serverVersion && options.serverUrl ) {
84
+ this.configurationInfo = {
85
+ pgn: 126998,
86
+ dst: 255,
87
+ "Installation Description #1": options.serverUrl,
88
+ "Installation Description #2": options.serverDescription,
89
+ "Manufacturer Information": options.serverVersion
90
+ }
91
+ }
92
+
93
+ this.options = _.isUndefined(options) ? {} : options
94
+
95
+ this.address = _.isUndefined(options.preferredAddress) ? 100 : options.preferredAddress
96
+ this.cansend = false
97
+ this.foundConflict = false
98
+ this.heartbeatCounter = 0
99
+ this.devices = {}
100
+
101
+ if ( !options.disableDefaultTransmitPGNs ) {
102
+ this.transmitPGNs = _.union(deviceTransmitPGNs, defaultTransmitPGNs)
103
+ } else {
104
+ this.transmitPGNs = [...deviceTransmitPGNs]
105
+ }
106
+
107
+ if ( this.options.transmitPGNs ) {
108
+ this.transmitPGNs = _.union(this.transmitPGNs,
109
+ this.options.transmitPGNs)
110
+ }
111
+ }
112
+
113
+ start() {
114
+ sendISORequest(this, 60928, 254)
115
+ setTimeout(() => {
116
+ sendAddressClaim(this)
117
+ }, 1000)
118
+ }
119
+
120
+ n2kMessage(pgn) {
121
+ if ( pgn.dst == 255 || pgn.dst == this.address ) {
122
+ try {
123
+ if ( pgn.pgn == 59904 ) {
124
+ handleISORequest(this, pgn)
125
+ } else if ( pgn.pgn == 126208 ) {
126
+ handleGroupFunction(this, pgn)
127
+ } else if ( pgn.pgn == 60928 ) {
128
+ handleISOAddressClaim(this, pgn)
129
+ } else if ( pgn.pgn == 126996 ) {
130
+ handleProductInformation(this, pgn)
131
+ }
132
+ } catch ( err ) {
133
+ console.error(err)
134
+ console.error(err.stack)
135
+ }
136
+
137
+ /*
138
+ var handler = this.handlers[pgn.pgn.toString()]
139
+ if ( pgn.dst == this.address )
140
+ debug(`handler ${handler}`)
141
+ if ( _.isFunction(handler) ) {
142
+ debug(`got handled PGN %j ${handled}`, pgn)
143
+ handler(pgn)
144
+ }
145
+ */
146
+ }
147
+ }
148
+
149
+ sendPGN(pgn, src) {
150
+ }
151
+ }
152
+
153
+ function handleISORequest(device, n2kMsg) {
154
+ debug('handleISORequest %j', n2kMsg)
155
+
156
+ switch (n2kMsg.fields.PGN) {
157
+ case 126996: // Product Information request
158
+ sendProductInformation(device)
159
+ break;
160
+ case 126998: // Config Information request
161
+ sendConfigInformation(device)
162
+ break;
163
+ case 60928: // ISO address claim request
164
+ device.sendPGN(device.addressClaim)
165
+ break;
166
+ case 126464:
167
+ sendPGNList(device)
168
+ break;
169
+ default:
170
+ if ( !device.options.disableNAKs ) {
171
+ debug(`Got unsupported ISO request for PGN ${n2kMsg.fields.PGN}. Sending NAK.`)
172
+ sendNAKAcknowledgement(device, n2kMsg.src, n2kMsg.fields.PGN)
173
+ }
174
+ }
175
+ }
176
+
177
+ function handleGroupFunction(device, n2kMsg) {
178
+ debug('handleGroupFunction %j', n2kMsg)
179
+ if(n2kMsg.fields["Function Code"] === 'Request') {
180
+ handleRequestGroupFunction(device, n2kMsg)
181
+ } else if(n2kMsg.fields["Function Code"] === 'Command') {
182
+ handleCommandGroupFunction(device, n2kMsg)
183
+ } else {
184
+ debug('Got unsupported Group Function PGN: %j', n2kMsg)
185
+ }
186
+
187
+ function handleRequestGroupFunction(device, n2kMsg) {
188
+ if ( !device.options.disableNAKs ) {
189
+ // We really don't support group function requests for any PGNs yet -> always respond with pgnErrorCode 1 = "PGN not supported"
190
+ debug("Sending 'PGN Not Supported' Group Function response for requested PGN", n2kMsg.fields.PGN)
191
+
192
+ const acknowledgement = {
193
+ pgn: 126208,
194
+ dst: n2kMsg.src,
195
+ "Function Code": 2,
196
+ "PGN": n2kMsg.fields.PGN,
197
+ "PGN error code": 4,
198
+ "Transmission interval/Priority error code": 0,
199
+ "# of Parameters": 0
200
+ }
201
+ device.sendPGN(acknowledgement)
202
+ }
203
+ }
204
+
205
+ function handleCommandGroupFunction(device, n2kMsg) {
206
+ if ( !device.options.disableNAKs ) {
207
+ // We really don't support group function commands for any PGNs yet -> always respond with pgnErrorCode 1 = "PGN not supported"
208
+ debug("Sending 'PGN Not Supported' Group Function response for commanded PGN", n2kMsg.fields.PGN)
209
+
210
+ const acknowledgement = {
211
+ pgn: 126208,
212
+ dst: n2kMsg.src,
213
+ "Function Code": 2,
214
+ "PGN": n2kMsg.fields.PGN,
215
+ "PGN error code": 4,
216
+ "Transmission interval/Priority error code": 0,
217
+ "# of Parameters": 0
218
+ }
219
+ device.sendPGN(acknowledgement)
220
+ }
221
+ }
222
+ }
223
+
224
+ function handleISOAddressClaim(device, n2kMsg) {
225
+ if ( n2kMsg.src != device.address ) {
226
+ if ( !device.devices[n2kMsg.src] ) {
227
+ debug(`registering device ${n2kMsg.src}`)
228
+ device.devices[n2kMsg.src] = { addressClaim: n2kMsg }
229
+ if ( device.cansend ) {
230
+ //sendISORequest(device, 126996, undefined, n2kMsg.src)
231
+ }
232
+ }
233
+ return
234
+ }
235
+
236
+ debug('Checking ISO address claim. %j', n2kMsg)
237
+
238
+ const uint64ValueFromReceivedClaim = getISOAddressClaimAsUint64(n2kMsg)
239
+ const uint64ValueFromOurOwnClaim = getISOAddressClaimAsUint64(device.addressClaim)
240
+
241
+ if(uint64ValueFromOurOwnClaim < uint64ValueFromReceivedClaim) {
242
+ debug(`Address conflict detected! Kept our address as ${device.address}.`)
243
+ sendAddressClaim(device) // We have smaller address claim data -> we can keep our address -> re-claim it
244
+ } else if(uint64ValueFromOurOwnClaim > uint64ValueFromReceivedClaim) {
245
+ this.foundConflict = true
246
+ increaseOwnAddress(device) // We have bigger address claim data -> we have to change our address
247
+ sendAddressClaim(device)
248
+ debug(`Address conflict detected! Changed our address to ${device.address}.`)
249
+ }
250
+ }
251
+
252
+ function increaseOwnAddress(device) {
253
+ var start = device.address
254
+ do {
255
+ device.address = (device.address + 1) % 253
256
+ } while ( device.address != start && device.devices[device.address] )
257
+ }
258
+
259
+ function handleProductInformation(device, n2kMsg) {
260
+ if ( !device.devices[n2kMsg.src] ) {
261
+ device.devices[n2kMsg.src] = {}
262
+ }
263
+ debug('got production information %j', n2kMsg)
264
+ device.devices[n2kMsg.src].productInformation = n2kMsg
265
+ }
266
+
267
+ function sendHeartbeat(device)
268
+ {
269
+ device.heartbeatCounter = device.heartbeatCounter + 1
270
+ if ( device.heartbeatCounter > 252 )
271
+ {
272
+ device.heartbeatCounter = 0
273
+ }
274
+ device.sendPGN({
275
+ pgn: 126993,
276
+ dst: 255,
277
+ prio:7,
278
+ "Data transmit offset": "00:01:00",
279
+ "Sequence Counter": device.heartbeatCounter,
280
+ "Controller 1 State":"Error Active"
281
+ })
282
+ }
283
+
284
+
285
+ function sendAddressClaim(device) {
286
+ if ( device.devices[device.address] ) {
287
+ //someone already has this address, so find a free one
288
+ increaseOwnAddress(device)
289
+ }
290
+ debug(`Sending address claim ${device.address}`)
291
+ device.sendPGN(device.addressClaim)
292
+ setTimeout(() => {
293
+ if ( !device.foundConflict ) {
294
+ debug('no address conflics, enabling send')
295
+ device.cansend = true
296
+ if ( device.options.app ) {
297
+ device.options.app.emit('nmea2000OutAvailable')
298
+ }
299
+ sendISORequest(device, 126996)
300
+ device.heartbeatInterval = setInterval(() => {
301
+ sendHeartbeat(device)
302
+ }, 60*1000)
303
+ /*
304
+ _.keys(device.devices).forEach((address) => {
305
+ sendISORequest(device, 126996, undefined, address)
306
+ })
307
+ */
308
+
309
+ }
310
+ }, 250)
311
+ }
312
+
313
+ function sendISORequest(device, pgn, src, dst=255) {
314
+ debug(`Sending iso request for ${pgn} to ${dst}`)
315
+
316
+ const isoRequest = {
317
+ pgn: 59904,
318
+ dst: dst,
319
+ "PGN": pgn
320
+ }
321
+ device.sendPGN(isoRequest, src)
322
+ }
323
+
324
+
325
+ function sendProductInformation(device) {
326
+ debug("Sending product info..")
327
+
328
+ device.sendPGN(device.productInfo)
329
+ }
330
+
331
+ function sendConfigInformation(device) {
332
+ if ( device.configurationInfo ) {
333
+ debug("Sending config info..")
334
+ device.sendPGN(device.configurationInfo)
335
+ }
336
+ }
337
+
338
+ function sendNAKAcknowledgement(device, src, requestedPGN) {
339
+ const acknowledgement = {
340
+ pgn: 59392,
341
+ dst: src,
342
+ Control: 1,
343
+ "Group Function": 255,
344
+ PGN: requestedPGN
345
+ }
346
+ device.sendPGN(device, acknowledgement)
347
+ }
348
+
349
+ function sendPGNList(device, src) {
350
+ //FIXME: for now, adding everything that signalk-to-nmea2000 supports
351
+ //need a way for plugins, etc. to register the pgns they provide
352
+ const pgnList = {
353
+ pgn: 126464,
354
+ dst: src,
355
+ "Function Code": 0,
356
+ list: device.transmitPGNs
357
+ }
358
+ device.sendPGN(pgnList)
359
+ }
360
+
361
+ function getISOAddressClaimAsUint64(pgn) {
362
+ return new Uint64LE(toPgn(pgn))
363
+ }
364
+
365
+ module.exports = N2kDevice
package/lib/serial.js CHANGED
@@ -148,6 +148,7 @@ SerialStream.prototype.start = function () {
148
148
  buf = composeMessage(N2K_MSG_SEND, buf, buf.length)
149
149
  debugOut(buf)
150
150
  that.serial.write(buf)
151
+ that.options.app.emit('connectionwrite', { providerId: that.options.providerId })
151
152
  }
152
153
 
153
154
  function writeObject(msg) {
@@ -158,6 +159,7 @@ SerialStream.prototype.start = function () {
158
159
  buf = composeMessage(N2K_MSG_SEND, buf, buf.length)
159
160
  debugOut(buf)
160
161
  that.serial.write(buf)
162
+ that.options.app.emit('connectionwrite', { providerId: that.options.providerId })
161
163
  }
162
164
 
163
165
  this.options.app.on(this.options.outEevent || 'nmea2000out', msg => {
package/lib/simpleCan.js CHANGED
@@ -39,7 +39,7 @@ SimpleCan.prototype.start = function () {
39
39
  disableDefaultTransmitPGNs: true,
40
40
  disableNAKs: true
41
41
  },
42
- )
42
+ )
43
43
  this.candevice.start()
44
44
  }
45
45
 
@@ -98,6 +98,10 @@ SimpleCan.prototype.sendPGN = function (msg) {
98
98
  }
99
99
  }
100
100
 
101
+ SimpleCan.prototype.sendActisenseFormat = function (msg) {
102
+ this.sendPGN(msg)
103
+ }
104
+
101
105
  function binToActisense(pgn, data, length) {
102
106
  return (
103
107
  pgn.timestamp +
package/lib/stringMsg.js CHANGED
@@ -8,6 +8,7 @@ const {
8
8
  const {
9
9
  buildCanId, encodeCanIdString, parseCanId, parseCanIdStr,
10
10
  } = require('./canId')
11
+ const moment = require('moment')
11
12
 
12
13
  /**
13
14
  * Helper function that helps merge canId fields with format, data, and others.
@@ -117,6 +118,17 @@ exports.encodeYDRAW = ({ data, ...canIdInfo }) => {
117
118
  return pgns.map(buffer => canId + ' ' + byteString(buffer, ' '))
118
119
  }
119
120
 
121
+ //16:29:27.082 R 19F51323 01 02<CR><LF>
122
+ exports.encodeYDRAWFull = ({ data, ...canIdInfo }) => {
123
+ const canId = encodeCanIdString(canIdInfo)
124
+ const pgns = data.length > 8 || canIdInfo.pgn == 126720 ? getPlainPGNs(data) : [ data ]
125
+ return pgns.map(buffer =>
126
+ moment().utc().format('hh:mm:ss.SSS')
127
+ + ' R '
128
+ + canId + ' '
129
+ + byteString(buffer, ' '))
130
+ }
131
+
120
132
  const get0183Sentence = (msg) => {
121
133
  let sentence = msg
122
134
  if (sentence.charAt(0) === '\\') {
package/lib/toPgn.js CHANGED
@@ -21,7 +21,7 @@ const BitStream = require('bit-buffer').BitStream
21
21
  const Int64LE = require('int64-buffer').Int64LE
22
22
  const Uint64LE = require('int64-buffer').Uint64LE
23
23
  const { getPlainPGNs } = require('./utilities')
24
- const { encodeActisense, encodeActisenseN2KACSII, encodeYDRAW, parseActisense, encodePCDIN, encodeMXPGN, encodePDGY } = require('./stringMsg')
24
+ const { encodeActisense, encodeActisenseN2KACSII, encodeYDRAW, encodeYDRAWFull, parseActisense, encodePCDIN, encodeMXPGN, encodePDGY } = require('./stringMsg')
25
25
  const { encodeN2KActisense } = require('./n2k-actisense')
26
26
  const { encodeCanId } = require('./canId')
27
27
  const { getIndustryCode, getManufacturerCode } = require('./codes')
@@ -327,6 +327,10 @@ function pgnToYdgwRawFormat(info) {
327
327
  return encodeYDRAW({ ...info, data: toPgn(info) })
328
328
  }
329
329
 
330
+ function pgnToYdgwFullRawFormat(info) {
331
+ return encodeYDRAWFull({ ...info, data: toPgn(info) })
332
+ }
333
+
330
334
  function pgnToPCDIN(info) {
331
335
  return encodePCDIN({ ...info, data: toPgn(info) })
332
336
  }
@@ -336,6 +340,7 @@ function pgnToMXPGN(info) {
336
340
  }
337
341
 
338
342
  const actisenseToYdgwRawFormat = _.flow(parseActisense, encodeYDRAW)
343
+ const actisenseToYdgwFullRawFormat = _.flow(parseActisense, encodeYDRAWFull)
339
344
  const actisenseToPCDIN = _.flow(parseActisense, encodePCDIN)
340
345
  const actisenseToMXPGN = _.flow(parseActisense, encodeMXPGN)
341
346
  const actisenseToiKonvert = _.flow(parseActisense, encodePDGY)
@@ -490,7 +495,9 @@ module.exports.toPgn = toPgn
490
495
  module.exports.toiKonvertSerialFormat = toiKonvertSerialFormat
491
496
  module.exports.pgnToiKonvertSerialFormat = pgnToiKonvertSerialFormat
492
497
  module.exports.pgnToYdgwRawFormat = pgnToYdgwRawFormat
498
+ module.exports.pgnToYdgwFullRawFormat = pgnToYdgwFullRawFormat
493
499
  module.exports.actisenseToYdgwRawFormat = actisenseToYdgwRawFormat
500
+ module.exports.actisenseToYdgwFullRawFormat = actisenseToYdgwFullRawFormat
494
501
  module.exports.pgnToActisenseSerialFormat = pgnToActisenseSerialFormat
495
502
  module.exports.pgnToActisenseN2KAsciiFormat = pgnToActisenseN2KAsciiFormat
496
503
  module.exports.pgnToN2KActisenseFormat = pgnToN2KActisenseFormat
package/lib/w2k01.js CHANGED
@@ -49,10 +49,12 @@ function W2K01Stream (options, type, outEvent) {
49
49
  } else {
50
50
  this.sendPGN(msg)
51
51
  }
52
+ options.app.emit('connectionwrite', { providerId: options.providerId })
52
53
  })
53
54
 
54
55
  options.app.on(options.jsonOutEvent || 'nmea2000JsonOut', (msg) => {
55
56
  this.sendPGN(msg)
57
+ options.app.emit('connectionwrite', { providerId: options.providerId })
56
58
  })
57
59
  }
58
60
  }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Copyright 2025 Scott Bender (scott@scottbender.net)
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+
18
+ const debug = require('debug')('canboatjs:n2kdevice')
19
+ const N2kDevice = require('./n2kDevice')
20
+
21
+ const { actisenseToYdgwFullRawFormat } = require('./toPgn')
22
+
23
+ class YdDevice extends N2kDevice {
24
+ constructor (options) {
25
+ super(options)
26
+ this.app = options.app
27
+ this.n2kOutEvent = options.jsonOutEvent || 'nmea2000JsonOut'
28
+
29
+ const analyzerOutEvent = options.analyzerOutEvent || 'N2KAnalyzerOut'
30
+
31
+ this.app.on(options.analyzerOutEvent || 'N2KAnalyzerOut', this.n2kMessage.bind(this))
32
+ }
33
+
34
+ sendPGN(pgn, src) {
35
+ pgn.src = src || this.address
36
+ pgn.
37
+ pgn.ydFullFormat = true
38
+ debug('Sending PGN %j', pgn)
39
+ this.app.emit(this.n2kOutEvent, pgn)
40
+ }
41
+
42
+ sendActisenseFormat(msg) {
43
+ this.app.emit('ydFullRawOut', actisenseToYdgwFullRawFormat(msg))
44
+ }
45
+ }
46
+
47
+ module.exports = YdDevice
package/lib/ydgw02.js CHANGED
@@ -20,7 +20,7 @@ const FromPgn = require('./fromPgn').Parser
20
20
  const Parser = require('./fromPgn').Parser
21
21
  const _ = require('lodash')
22
22
  const { defaultTransmitPGNs } = require('./codes')
23
- const { pgnToYdgwRawFormat, actisenseToYdgwRawFormat } = require('./toPgn')
23
+ const { pgnToYdgwRawFormat, pgnToYdgwFullRawFormat, actisenseToYdgwRawFormat } = require('./toPgn')
24
24
 
25
25
  const pgnsSent = {}
26
26
 
@@ -55,10 +55,17 @@ function Ydgw02Stream (options, type) {
55
55
  } else {
56
56
  this.sendPGN(msg)
57
57
  }
58
+ options.app.emit('connectionwrite', { providerId: options.providerId })
58
59
  })
59
60
 
60
61
  options.app.on(options.jsonOutEvent || 'nmea2000JsonOut', (msg) => {
61
62
  this.sendPGN(msg)
63
+ options.app.emit('connectionwrite', { providerId: options.providerId })
64
+ })
65
+
66
+ options.app.on('ydFullRawOut', (msgs) => {
67
+ this.sendYdgwFullPGN(msgs)
68
+ options.app.emit('connectionwrite', { providerId: options.providerId })
62
69
  })
63
70
 
64
71
  //this.sendString('$PDGY,N2NET_OFFLINE')
@@ -80,12 +87,24 @@ Ydgw02Stream.prototype.sendString = function (msg) {
80
87
  Ydgw02Stream.prototype.sendPGN = function (pgn) {
81
88
  let now = Date.now()
82
89
  let lastSent = pgnsSent[pgn.pgn]
83
- pgnToYdgwRawFormat(pgn).forEach(raw => {
90
+ let msgs
91
+ if ( pgn.ydFullFormat === true ) {
92
+ msgs = pgnToYdgwFullRawFormat(pgn)
93
+ } else {
94
+ msgs = pgnToYdgwRawFormat(pgn)
95
+ }
96
+ msgs.forEach(raw => {
84
97
  this.sendString(raw + '\r\n')
85
98
  })
86
99
  pgnsSent[pgn.pgn] = now
87
100
  }
88
101
 
102
+ Ydgw02Stream.prototype.sendYdgwFullPGN = function (msgs) {
103
+ msgs.forEach(raw => {
104
+ this.sendString(raw + '\r\n')
105
+ })
106
+ }
107
+
89
108
  Ydgw02Stream.prototype.sendYdgwPGN = function (msg) {
90
109
 
91
110
  actisenseToYdgwRawFormat(msg).forEach(raw => {
package/package.json CHANGED
@@ -1,14 +1,12 @@
1
1
  {
2
2
  "name": "@canboat/canboatjs",
3
- "version": "2.9.0",
3
+ "version": "2.11.0",
4
4
  "description": "Native javascript version of canboat",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "dev-test": "jest --watch",
8
8
  "test": "jest && mocha --exit",
9
9
  "code-coverage": "jest --coverage && nyc mocha --exit",
10
- "create-release": "github-create-release --owner canboat --repository canboatjs",
11
- "release": "git tag -d v$npm_package_version && git tag v$npm_package_version && git push --tags && git push && npm run create-release",
12
10
  "build_ios": "webpack -c ./webpack.config.js --mode development ./ios.js -o ios_canboat.js",
13
11
  "build_prod_ios": "webpack -c ./webpack.config.js --mode production ./ios.js -o ios_canboat.js"
14
12
  },
@@ -66,7 +64,6 @@
66
64
  "split": "^1.0.1"
67
65
  },
68
66
  "devDependencies": {
69
- "@signalk/github-create-release": "^1.0.1",
70
67
  "@signalk/server-api": "^1.39.0",
71
68
  "baconjs": "^1.0.1",
72
69
  "buffer": "^6.0.3",