@canboat/canboatjs 2.11.1 → 3.0.0-beta.2

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/candevice.js CHANGED
@@ -20,9 +20,8 @@ const _ = require('lodash')
20
20
  const Uint64LE = require('int64-buffer').Uint64LE
21
21
  const { defaultTransmitPGNs, getIndustryCode, getManufacturerCode, getDeviceClassCode } = require('./codes')
22
22
  const { toPgn } = require('./toPgn')
23
- const N2kDevice = require('./n2kDevice')
24
-
25
23
  let packageJson
24
+
26
25
  try
27
26
  {
28
27
  packageJson = require('../' + 'package.json')
@@ -31,21 +30,344 @@ try
31
30
 
32
31
  const deviceTransmitPGNs = [ 60928, 59904, 126996, 126464 ]
33
32
 
34
- class CanDevice extends N2kDevice {
33
+ class CanDevice extends EventEmitter {
35
34
  constructor (canbus, options) {
36
- super(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
+
37
93
  this.canbus = canbus
94
+ this.options = _.isUndefined(options) ? {} : options
95
+
96
+ this.address = _.isUndefined(options.preferredAddress) ? 100 : options.preferredAddress
97
+ this.cansend = false
98
+ this.foundConflict = false
99
+ this.heartbeatCounter = 0
100
+ this.devices = {}
101
+
102
+ if ( !options.disableDefaultTransmitPGNs ) {
103
+ this.transmitPGNs = _.union(deviceTransmitPGNs, defaultTransmitPGNs)
104
+ } else {
105
+ this.transmitPGNs = [...deviceTransmitPGNs]
106
+ }
107
+
108
+ if ( this.options.transmitPGNs ) {
109
+ this.transmitPGNs = _.union(this.transmitPGNs,
110
+ this.options.transmitPGNs)
111
+ }
38
112
 
39
113
  if ( options.app ) {
40
114
  options.app.on(options.analyzerOutEvent || 'N2KAnalyzerOut', this.n2kMessage.bind(this))
41
115
  }
42
116
  }
43
117
 
44
- sendPGN(pgn, src) {
45
- pgn.src = src || this.address
46
- debug('Sending PGN %j', pgn)
47
- this.canbus.sendPGN(pgn)
118
+ start() {
119
+ sendISORequest(this, 60928, 254)
120
+ setTimeout(() => {
121
+ sendAddressClaim(this)
122
+ }, 1000)
123
+ }
124
+
125
+ n2kMessage(pgn) {
126
+ if ( pgn.dst == 255 || pgn.dst == this.address ) {
127
+ try {
128
+ if ( pgn.pgn == 59904 ) {
129
+ handleISORequest(this, pgn)
130
+ } else if ( pgn.pgn == 126208 ) {
131
+ handleGroupFunction(this, pgn)
132
+ } else if ( pgn.pgn == 60928 ) {
133
+ handleISOAddressClaim(this, pgn)
134
+ } else if ( pgn.pgn == 126996 ) {
135
+ handleProductInformation(this, pgn)
136
+ }
137
+ } catch ( err ) {
138
+ console.error(err)
139
+ console.error(err.stack)
140
+ }
141
+
142
+ /*
143
+ var handler = this.handlers[pgn.pgn.toString()]
144
+ if ( pgn.dst == this.address )
145
+ debug(`handler ${handler}`)
146
+ if ( _.isFunction(handler) ) {
147
+ debug(`got handled PGN %j ${handled}`, pgn)
148
+ handler(pgn)
149
+ }
150
+ */
151
+ }
152
+ }
153
+ }
154
+
155
+ function sendPGN(device, pgn, src, dest) {
156
+ pgn.src = src || device.address
157
+ debug('Sending PGN %j', pgn)
158
+ device.canbus.sendPGN(pgn)
159
+ }
160
+
161
+ function handleISORequest(device, n2kMsg) {
162
+ debug('handleISORequest %j', n2kMsg)
163
+
164
+ switch (n2kMsg.fields.PGN) {
165
+ case 126996: // Product Information request
166
+ sendProductInformation(device)
167
+ break;
168
+ case 126998: // Config Information request
169
+ sendConfigInformation(device)
170
+ break;
171
+ case 60928: // ISO address claim request
172
+ sendPGN(device, device.addressClaim)
173
+ break;
174
+ case 126464:
175
+ sendPGNList(device)
176
+ break;
177
+ default:
178
+ if ( !device.options.disableNAKs ) {
179
+ debug(`Got unsupported ISO request for PGN ${n2kMsg.fields.PGN}. Sending NAK.`)
180
+ sendNAKAcknowledgement(device, n2kMsg.src, n2kMsg.fields.PGN)
181
+ }
182
+ }
183
+ }
184
+
185
+ function handleGroupFunction(device, n2kMsg) {
186
+ debug('handleGroupFunction %j', n2kMsg)
187
+ if(n2kMsg.fields.functionCodeRequest) {
188
+ handleRequestGroupFunction(device, n2kMsg)
189
+ } else if(n2kMsg.fields.functionCodeCommand) {
190
+ handleCommandGroupFunction(device, n2kMsg)
191
+ } else {
192
+ debug('Got unsupported Group Function PGN: %j', n2kMsg)
193
+ }
194
+
195
+ function handleRequestGroupFunction(device, n2kMsg) {
196
+ if ( !device.options.disableNAKs ) {
197
+ // We really don't support group function requests for any PGNs yet -> always respond with pgnErrorCode 1 = "PGN not supported"
198
+ debug("Sending 'PGN Not Supported' Group Function response for requested PGN", n2kMsg.fields.PGN)
199
+
200
+ const acknowledgement = {
201
+ pgn: 126208,
202
+ dst: n2kMsg.src,
203
+ "Function Code": 2,
204
+ "PGN": n2kMsg.fields.PGN,
205
+ "PGN error code": 4,
206
+ "Transmission interval/Priority error code": 0,
207
+ "# of Parameters": 0
208
+ }
209
+ sendPGN(device, acknowledgement)
210
+ }
211
+ }
212
+
213
+ function handleCommandGroupFunction(device, n2kMsg) {
214
+ if ( !device.options.disableNAKs ) {
215
+ // We really don't support group function commands for any PGNs yet -> always respond with pgnErrorCode 1 = "PGN not supported"
216
+ debug("Sending 'PGN Not Supported' Group Function response for commanded PGN", n2kMsg.fields.PGN)
217
+
218
+ const acknowledgement = {
219
+ pgn: 126208,
220
+ dst: n2kMsg.src,
221
+ "Function Code": 2,
222
+ "PGN": n2kMsg.fields.PGN,
223
+ "PGN error code": 4,
224
+ "Transmission interval/Priority error code": 0,
225
+ "# of Parameters": 0
226
+ }
227
+ sendPGN(device, acknowledgement)
228
+ }
229
+ }
230
+ }
231
+
232
+ function handleISOAddressClaim(device, n2kMsg) {
233
+ if ( n2kMsg.src != device.address ) {
234
+ if ( !device.devices[n2kMsg.src] ) {
235
+ debug(`registering device ${n2kMsg.src}`)
236
+ device.devices[n2kMsg.src] = { addressClaim: n2kMsg }
237
+ if ( device.cansend ) {
238
+ //sendISORequest(device, 126996, undefined, n2kMsg.src)
239
+ }
240
+ }
241
+ return
242
+ }
243
+
244
+ debug('Checking ISO address claim. %j', n2kMsg)
245
+
246
+ const uint64ValueFromReceivedClaim = getISOAddressClaimAsUint64(n2kMsg)
247
+ const uint64ValueFromOurOwnClaim = getISOAddressClaimAsUint64(device.addressClaim)
248
+
249
+ if(uint64ValueFromOurOwnClaim < uint64ValueFromReceivedClaim) {
250
+ debug(`Address conflict detected! Kept our address as ${device.address}.`)
251
+ sendAddressClaim(device) // We have smaller address claim data -> we can keep our address -> re-claim it
252
+ } else if(uint64ValueFromOurOwnClaim > uint64ValueFromReceivedClaim) {
253
+ this.foundConflict = true
254
+ increaseOwnAddress(device) // We have bigger address claim data -> we have to change our address
255
+ sendAddressClaim(device)
256
+ debug(`Address conflict detected! Changed our address to ${device.address}.`)
257
+ }
258
+ }
259
+
260
+ function increaseOwnAddress(device) {
261
+ var start = device.address
262
+ do {
263
+ device.address = (device.address + 1) % 253
264
+ } while ( device.address != start && device.devices[device.address] )
265
+ }
266
+
267
+ function handleProductInformation(device, n2kMsg) {
268
+ if ( !device.devices[n2kMsg.src] ) {
269
+ device.devices[n2kMsg.src] = {}
270
+ }
271
+ debug('got production information %j', n2kMsg)
272
+ device.devices[n2kMsg.src].productInformation = n2kMsg
273
+ }
274
+
275
+ function sendHeartbeat(device)
276
+ {
277
+ device.heartbeatCounter = device.heartbeatCounter + 1
278
+ if ( device.heartbeatCounter > 252 )
279
+ {
280
+ device.heartbeatCounter = 0
281
+ }
282
+ sendPGN(device,{
283
+ pgn: 126993,
284
+ dst: 255,
285
+ prio:7,
286
+ "Data transmit offset": "00:01:00",
287
+ "Sequence Counter": device.heartbeatCounter,
288
+ "Controller 1 State":"Error Active"
289
+ })
290
+ }
291
+
292
+
293
+ function sendAddressClaim(device) {
294
+ if ( device.devices[device.address] ) {
295
+ //someone already has this address, so find a free one
296
+ increaseOwnAddress(device)
297
+ }
298
+ debug(`Sending address claim ${device.address}`)
299
+ sendPGN(device, device.addressClaim)
300
+ setTimeout(() => {
301
+ if ( !device.foundConflict ) {
302
+ debug('no address conflics, enabling send')
303
+ device.cansend = true
304
+ if ( device.options.app ) {
305
+ device.options.app.emit('nmea2000OutAvailable')
306
+ }
307
+ sendISORequest(device, 126996)
308
+ device.heartbeatInterval = setInterval(() => {
309
+ sendHeartbeat(device)
310
+ }, 60*1000)
311
+ /*
312
+ _.keys(device.devices).forEach((address) => {
313
+ sendISORequest(device, 126996, undefined, address)
314
+ })
315
+ */
316
+
317
+ }
318
+ }, 250)
319
+ }
320
+
321
+ function sendISORequest(device, pgn, src, dst=255) {
322
+ debug(`Sending iso request for ${pgn} to ${dst}`)
323
+
324
+ const isoRequest = {
325
+ pgn: 59904,
326
+ dst: dst,
327
+ "PGN": pgn
328
+ }
329
+ sendPGN(device, isoRequest, src)
330
+ }
331
+
332
+
333
+ function sendProductInformation(device) {
334
+ debug("Sending product info..")
335
+
336
+ sendPGN(device, device.productInfo)
337
+ }
338
+
339
+ function sendConfigInformation(device) {
340
+ if ( device.configurationInfo ) {
341
+ debug("Sending config info..")
342
+ sendPGN(device, device.configurationInfo)
48
343
  }
49
344
  }
50
345
 
346
+ function sendNAKAcknowledgement(device, src, requestedPGN) {
347
+ const acknowledgement = {
348
+ pgn: 59392,
349
+ dst: src,
350
+ Control: 1,
351
+ "Group Function": 255,
352
+ PGN: requestedPGN
353
+ }
354
+ sendPGN(device, acknowledgement)
355
+ }
356
+
357
+ function sendPGNList(device, src) {
358
+ //FIXME: for now, adding everything that signalk-to-nmea2000 supports
359
+ //need a way for plugins, etc. to register the pgns they provide
360
+ const pgnList = {
361
+ pgn: 126464,
362
+ dst: src,
363
+ "Function Code": 0,
364
+ list: device.transmitPGNs
365
+ }
366
+ sendPGN(device, pgnList)
367
+ }
368
+
369
+ function getISOAddressClaimAsUint64(pgn) {
370
+ return new Uint64LE(toPgn(pgn))
371
+ }
372
+
51
373
  module.exports = CanDevice
package/lib/fromPgn.js CHANGED
@@ -62,6 +62,14 @@ class Parser extends EventEmitter {
62
62
  if ( this.options.returnNulls === undefined ) {
63
63
  this.options.returnNulls = false
64
64
  }
65
+
66
+ if ( this.options.useCamel === undefined ) {
67
+ this.options.useCamel = false
68
+ }
69
+
70
+ if ( this.options.useCamelCompat === undefined ) {
71
+ this.options.useCamelCompat = false
72
+ }
65
73
 
66
74
  this.name = pkg.name
67
75
  this.version = pkg.version
@@ -204,6 +212,7 @@ class Parser extends EventEmitter {
204
212
  let RepeatingFields = pgnData.RepeatingFieldSet1Size ? pgnData.RepeatingFieldSet1Size : 0
205
213
 
206
214
  pgn.fields = {}
215
+
207
216
  try {
208
217
  var fields = pgnData.Fields
209
218
 
@@ -234,8 +243,8 @@ class Parser extends EventEmitter {
234
243
  const ts = _.get(pgn, 'timestamp', new Date())
235
244
  pgn.timestamp = _.isDate(ts) ? ts.toISOString() : ts
236
245
  if ( !_.isUndefined(value) && (value != null ||
237
- this.options.returnNulls) ) {
238
- pgn.fields[field.Name] = value
246
+ this.options.returnNulls) ) {
247
+ this.setField(pgn.fields, field, value)
239
248
  }
240
249
  this.emit('pgn', pgn)
241
250
  cb && cb(undefined, pgn)
@@ -255,7 +264,7 @@ class Parser extends EventEmitter {
255
264
 
256
265
  if ( !_.isUndefined(value) && (value != null ||
257
266
  this.options.returnNulls) ) {
258
- pgn.fields[field.Name] = value
267
+ this.setField(pgn.fields, field, value)
259
268
  }
260
269
  }
261
270
  if ( RepeatingFields > 0 ) {
@@ -265,7 +274,7 @@ class Parser extends EventEmitter {
265
274
  let count
266
275
 
267
276
  if ( pgnData.RepeatingFieldSet1CountField !== undefined ) {
268
- count = pgn.fields[pgnData.Fields[pgnData.RepeatingFieldSet1CountField-1].Name]
277
+ count = pgn.fields[pgnData.Fields[pgnData.RepeatingFieldSet1CountField-1][this.options.useCamel ? 'Id' : 'Name']]
269
278
  } else {
270
279
  count = 2048
271
280
  }
@@ -276,7 +285,7 @@ class Parser extends EventEmitter {
276
285
  if ( bs.bitsLeft > 0 ) {
277
286
  var value = readField(this.options, true, pgn, field, bs, fields)
278
287
  if ( !_.isUndefined(value) && value != null ) {
279
- group[field.Name] = value
288
+ this.setField(group, field, value)
280
289
  }
281
290
  }
282
291
  })
@@ -306,6 +315,17 @@ class Parser extends EventEmitter {
306
315
  }
307
316
  }
308
317
 
318
+ setField(res, field, value) {
319
+ if ( this.options.useCamelCompat ) {
320
+ res[field.Id] = value
321
+ res[field.Name] = value
322
+ } else if ( this.options.useCamel ) {
323
+ res[field.Id] = value
324
+ } else {
325
+ res[field.Name] = value
326
+ }
327
+ }
328
+
309
329
  findNonMatchPgn(pgnList) {
310
330
  return pgnList.find(f => {
311
331
  return !f.Fields.find(f => !_.isUndefined(f.Match))
@@ -616,8 +636,9 @@ function readField(options, runPostProcessor, pgn, field, bs, fields) {
616
636
  if ( options.checkForInvalidFields !== false && max !== 'undefined' &&
617
637
  field.FieldType !== 'LOOKUP' &&
618
638
  field.FieldType !== 'FIELDTYPE_LOOKUP' &&
639
+ field.FieldType !== 'PGN' &&
619
640
  field.BitLength > 1 &&
620
- max - value <= 0 ) {
641
+ max - value < 0 ) {
621
642
  //console.log(`Bad field ${field.Name} ${max - value}`)
622
643
  value = null
623
644
  } if ( field.Resolution && typeof value === 'number' ) {
@@ -724,9 +745,9 @@ function readValue(options, pgn, field, bs, fields, bitLength) {
724
745
  var y = bs.readUint32()
725
746
 
726
747
  if ( field.Signed ) {
727
- value = x === 0xffffffff && y == 0x7fffffff ? null : new Int64LE(y,x)
748
+ value = (x === 0xffffffff || x === 0xfffffffe) && y == 0x7fffffff ? null : new Int64LE(y,x)
728
749
  } else {
729
- value = x === 0xffffffff && y == 0xffffffff ? null : new Uint64LE(y,x)
750
+ value = (x === 0xffffffff || x === 0xfffffffe) && y == 0xffffffff ? null : new Uint64LE(y,x)
730
751
  }
731
752
  } else if ( bitLength <= 64 ) {
732
753
  value = bs.readBits(bitLength, field.Signed)
@@ -930,7 +951,7 @@ function lookupKeyBitLength(data, fields)
930
951
  {
931
952
  let field = fields.find(field => (field.Name === 'Key'))
932
953
 
933
- let val = data['Key']
954
+ let val = data['Key'] || data['key']
934
955
  if ( typeof val === 'string' ) {
935
956
  val = lookupFieldTypeEnumerationValue(field.LookupFieldTypeEnumeration, val)
936
957
  }
@@ -967,6 +988,8 @@ fieldTypePostProcessors['TIME'] = (field, value) => {
967
988
  return value
968
989
  }
969
990
 
991
+ fieldTypePostProcessors['DURATION'] = fieldTypePostProcessors['TIME']
992
+
970
993
  fieldTypePostProcessors['Pressure'] = (field, value) => {
971
994
  if (field.Unit)
972
995
  {
package/lib/pgns.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const { flow, first, isArray, isEmpty, propertyOf } = require('lodash/fp')
2
- const pgns = require('@canboat/pgns')
2
+ const canboat = require('@canboat/pgns')
3
+ const pgns = canboat.pgns
3
4
  const pgnsIK = { PGNs: [] } //require('@canboat/pgns/pgns-ik')
4
5
  const pgnsNGT = { PGNs: [] } //require('@canboat/pgns/pgns-ngt')
5
6
  const _ = require('lodash')
@@ -7,7 +8,7 @@ const debug = require('debug')('canboatjs:pgns')
7
8
 
8
9
  function organizePGNs() {
9
10
  const res = {}
10
- const all = [...pgns.PGNs, ...pgnsIK.PGNs, ...pgnsNGT.PGNs]
11
+ const all = [...canboat.getPGNs(), ...pgnsIK.PGNs, ...pgnsNGT.PGNs]
11
12
  all.forEach(pgn => {
12
13
  if ( !res[pgn.PGN] ) {
13
14
  res[pgn.PGN] = []
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,10 +98,6 @@ SimpleCan.prototype.sendPGN = function (msg) {
98
98
  }
99
99
  }
100
100
 
101
- SimpleCan.prototype.sendActisenseFormat = function (msg) {
102
- this.sendPGN(msg)
103
- }
104
-
105
101
  function binToActisense(pgn, data, length) {
106
102
  return (
107
103
  pgn.timestamp +
package/lib/stringMsg.js CHANGED
@@ -8,7 +8,6 @@ const {
8
8
  const {
9
9
  buildCanId, encodeCanIdString, parseCanId, parseCanIdStr,
10
10
  } = require('./canId')
11
- const moment = require('moment')
12
11
 
13
12
  /**
14
13
  * Helper function that helps merge canId fields with format, data, and others.
@@ -118,17 +117,6 @@ exports.encodeYDRAW = ({ data, ...canIdInfo }) => {
118
117
  return pgns.map(buffer => canId + ' ' + byteString(buffer, ' '))
119
118
  }
120
119
 
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
-
132
120
  const get0183Sentence = (msg) => {
133
121
  let sentence = msg
134
122
  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, encodeYDRAWFull, parseActisense, encodePCDIN, encodeMXPGN, encodePDGY } = require('./stringMsg')
24
+ const { encodeActisense, encodeActisenseN2KACSII, encodeYDRAW, 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')
@@ -74,7 +74,7 @@ function toPgn(data) {
74
74
  let RepeatingFields = pgnData.RepeatingFieldSet1Size ? pgnData.RepeatingFieldSet1Size : 0
75
75
  for ( var index = 0; index < fields.length - RepeatingFields; index++ ) {
76
76
  var field = fields[index]
77
- var value = data[field.Name];
77
+ var value = data[field.Name] !== undefined ? data[field.Name] : data[field.Id]
78
78
 
79
79
  if ( !_.isUndefined(field.Match) ) {
80
80
  //console.log(`matching ${field.Name} ${field.Match} ${value} ${_.isString(value)}`)
@@ -98,7 +98,7 @@ function toPgn(data) {
98
98
  data.list.forEach(repeat => {
99
99
  for (var index = 0; index < RepeatingFields; index++ ) {
100
100
  var field = fields[pgnData.Fields.length-RepeatingFields+index]
101
- var value = repeat[field.Name];
101
+ var value = repeat[field.Name] !== undefined ? repeat[field.Name] : repeat[field.Id]
102
102
 
103
103
  writeField(bs, pgn_number, field, data, value, fields)
104
104
  }
@@ -171,7 +171,7 @@ function writeField(bs, pgn_number, field, data, value, fields, bitLength) {
171
171
  }
172
172
  } else {
173
173
  let type = field.FieldType
174
- if ( field.Name === 'Industry Code' ) {
174
+ if ( field.Id === 'industryCode' ) {
175
175
  if ( _.isString(value) ) {
176
176
  value = Number(getIndustryCode(value))
177
177
  }
@@ -184,6 +184,10 @@ function writeField(bs, pgn_number, field, data, value, fields, bitLength) {
184
184
  }
185
185
  }
186
186
 
187
+ if ( field.FieldType == "NUMBER" && _.isString(value) ) {
188
+ value = Number(value)
189
+ }
190
+
187
191
  if (field.Resolution && typeof value === 'number' ) {
188
192
  value = Number((value / field.Resolution).toFixed(0))
189
193
  }
@@ -191,9 +195,11 @@ function writeField(bs, pgn_number, field, data, value, fields, bitLength) {
191
195
  if ( field.FieldType && fieldTypeWriters[field.FieldType] ) {
192
196
  fieldTypeWriters[field.FieldType](pgn_number, field, value, bs)
193
197
  } else {
198
+ /*
194
199
  if ( _.isString(value) && typeof bitLength !== 'undefined' && bitLength !== 0 ) {
195
200
  value = Number(value)
196
- }
201
+ }
202
+ */
197
203
 
198
204
  if ( field.Unit === "kWh" ) {
199
205
  value /= 3.6e6; // 1 kWh = 3.6 MJ.
@@ -284,7 +290,7 @@ function lookupKeyBitLength(data, fields)
284
290
  {
285
291
  let field = fields.find(field => (field.Name === 'Key'))
286
292
 
287
- let val = data['Key']
293
+ let val = data['Key'] || data['key']
288
294
  if ( typeof val === 'string' ) {
289
295
  val = lookupFieldTypeEnumerationValue(field.LookupFieldTypeEnumeration, val)
290
296
  }
@@ -327,10 +333,6 @@ function pgnToYdgwRawFormat(info) {
327
333
  return encodeYDRAW({ ...info, data: toPgn(info) })
328
334
  }
329
335
 
330
- function pgnToYdgwFullRawFormat(info) {
331
- return encodeYDRAWFull({ ...info, data: toPgn(info) })
332
- }
333
-
334
336
  function pgnToPCDIN(info) {
335
337
  return encodePCDIN({ ...info, data: toPgn(info) })
336
338
  }
@@ -340,7 +342,6 @@ function pgnToMXPGN(info) {
340
342
  }
341
343
 
342
344
  const actisenseToYdgwRawFormat = _.flow(parseActisense, encodeYDRAW)
343
- const actisenseToYdgwFullRawFormat = _.flow(parseActisense, encodeYDRAWFull)
344
345
  const actisenseToPCDIN = _.flow(parseActisense, encodePCDIN)
345
346
  const actisenseToMXPGN = _.flow(parseActisense, encodeMXPGN)
346
347
  const actisenseToiKonvert = _.flow(parseActisense, encodePDGY)
@@ -460,6 +461,8 @@ fieldTypeMappers['TIME'] = (field, value) => {
460
461
  return value
461
462
  }
462
463
 
464
+ fieldTypeMappers['DURATION'] = fieldTypeMappers['TIME']
465
+
463
466
  /*
464
467
  fieldTypeMappers['Manufacturer code'] = (field, value) => {
465
468
  if ( _.isString(value) ) {
@@ -495,9 +498,7 @@ module.exports.toPgn = toPgn
495
498
  module.exports.toiKonvertSerialFormat = toiKonvertSerialFormat
496
499
  module.exports.pgnToiKonvertSerialFormat = pgnToiKonvertSerialFormat
497
500
  module.exports.pgnToYdgwRawFormat = pgnToYdgwRawFormat
498
- module.exports.pgnToYdgwFullRawFormat = pgnToYdgwFullRawFormat
499
501
  module.exports.actisenseToYdgwRawFormat = actisenseToYdgwRawFormat
500
- module.exports.actisenseToYdgwFullRawFormat = actisenseToYdgwFullRawFormat
501
502
  module.exports.pgnToActisenseSerialFormat = pgnToActisenseSerialFormat
502
503
  module.exports.pgnToActisenseN2KAsciiFormat = pgnToActisenseN2KAsciiFormat
503
504
  module.exports.pgnToN2KActisenseFormat = pgnToN2KActisenseFormat
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, pgnToYdgwFullRawFormat, actisenseToYdgwRawFormat } = require('./toPgn')
23
+ const { pgnToYdgwRawFormat, actisenseToYdgwRawFormat } = require('./toPgn')
24
24
 
25
25
  const pgnsSent = {}
26
26
 
@@ -63,11 +63,6 @@ function Ydgw02Stream (options, type) {
63
63
  options.app.emit('connectionwrite', { providerId: options.providerId })
64
64
  })
65
65
 
66
- options.app.on('ydFullRawOut', (msgs) => {
67
- this.sendYdgwFullPGN(msgs)
68
- options.app.emit('connectionwrite', { providerId: options.providerId })
69
- })
70
-
71
66
  //this.sendString('$PDGY,N2NET_OFFLINE')
72
67
 
73
68
  if ( type === 'usb' ) {
@@ -87,24 +82,12 @@ Ydgw02Stream.prototype.sendString = function (msg) {
87
82
  Ydgw02Stream.prototype.sendPGN = function (pgn) {
88
83
  let now = Date.now()
89
84
  let lastSent = pgnsSent[pgn.pgn]
90
- let msgs
91
- if ( pgn.ydFullFormat === true ) {
92
- msgs = pgnToYdgwFullRawFormat(pgn)
93
- } else {
94
- msgs = pgnToYdgwRawFormat(pgn)
95
- }
96
- msgs.forEach(raw => {
85
+ pgnToYdgwRawFormat(pgn).forEach(raw => {
97
86
  this.sendString(raw + '\r\n')
98
87
  })
99
88
  pgnsSent[pgn.pgn] = now
100
89
  }
101
90
 
102
- Ydgw02Stream.prototype.sendYdgwFullPGN = function (msgs) {
103
- msgs.forEach(raw => {
104
- this.sendString(raw + '\r\n')
105
- })
106
- }
107
-
108
91
  Ydgw02Stream.prototype.sendYdgwPGN = function (msg) {
109
92
 
110
93
  actisenseToYdgwRawFormat(msg).forEach(raw => {