@canboat/canboatjs 1.21.0 → 1.22.1
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/README.md +2 -2
- package/lib/canbus.js +1 -1
- package/lib/candevice.js +2 -2
- package/lib/codes.test.js +2 -0
- package/lib/codesMfgs.json +1 -0
- package/lib/fromPgn.js +42 -31
- package/lib/simpleCan.js +2 -2
- package/lib/stringMsg.js +16 -7
- package/lib/stringMsg.test.js +2 -1
- package/lib/ydgw02.js +1 -1
- package/package.json +1 -1
- package/ios_canboat.js +0 -26
package/README.md
CHANGED
|
@@ -205,9 +205,9 @@ Output: `!PDGY,127245,255,/Pj/f/9///8=`
|
|
|
205
205
|
## Generate YDGW-02 format from canboat json
|
|
206
206
|
|
|
207
207
|
```js
|
|
208
|
-
const
|
|
208
|
+
const pgnToYdgwRawFormat = require("./index").pgnToYdgwRawFormat;
|
|
209
209
|
|
|
210
|
-
const array =
|
|
210
|
+
const array = pgnToYdgwRawFormat({
|
|
211
211
|
src: 127,
|
|
212
212
|
prio: 3,
|
|
213
213
|
dst: 255,
|
package/lib/canbus.js
CHANGED
|
@@ -120,7 +120,7 @@ function CanbusStream (options) {
|
|
|
120
120
|
})
|
|
121
121
|
} else {
|
|
122
122
|
try {
|
|
123
|
-
this.channel = socketcan.
|
|
123
|
+
this.channel = socketcan.createRawChannelWithOptions(canDevice, { non_block_send: true} );
|
|
124
124
|
this.channel.addListener('onMessage', (msg) => {
|
|
125
125
|
var pgn = parseCanId(msg.id)
|
|
126
126
|
|
package/lib/candevice.js
CHANGED
|
@@ -177,7 +177,7 @@ function handleGroupFunction(device, n2kMsg) {
|
|
|
177
177
|
const acknowledgement = {
|
|
178
178
|
pgn: 126208,
|
|
179
179
|
dst: n2kMsg.src,
|
|
180
|
-
"Function Code":
|
|
180
|
+
"Function Code": 2,
|
|
181
181
|
"PGN": n2kMsg.fields.PGN,
|
|
182
182
|
"PGN error code": 4,
|
|
183
183
|
"Transmission interval/Priority error code": 0,
|
|
@@ -195,7 +195,7 @@ function handleGroupFunction(device, n2kMsg) {
|
|
|
195
195
|
const acknowledgement = {
|
|
196
196
|
pgn: 126208,
|
|
197
197
|
dst: n2kMsg.src,
|
|
198
|
-
"Function Code":
|
|
198
|
+
"Function Code": 2,
|
|
199
199
|
"PGN": n2kMsg.fields.PGN,
|
|
200
200
|
"PGN error code": 4,
|
|
201
201
|
"Transmission interval/Priority error code": 0,
|
package/lib/codes.test.js
CHANGED
|
@@ -4,6 +4,7 @@ describe('getManufacturerCode', () => {
|
|
|
4
4
|
test('Return mfg number from name string', () => {
|
|
5
5
|
expect(getManufacturerCode('Furuno')).toBe(1855)
|
|
6
6
|
expect(getManufacturerCode('Yacht Devices')).toBe(717)
|
|
7
|
+
expect(getManufacturerCode('TJC Micro')).toBe(963)
|
|
7
8
|
})
|
|
8
9
|
})
|
|
9
10
|
|
|
@@ -11,5 +12,6 @@ describe('getManufacturerName', () => {
|
|
|
11
12
|
test('Return name string from mfg number', () => {
|
|
12
13
|
expect(getManufacturerName(1855)).toBe('Furuno')
|
|
13
14
|
expect(getManufacturerName(717)).toBe('Yacht Devices')
|
|
15
|
+
expect(getManufacturerName(963)).toBe('TJC Micro')
|
|
14
16
|
})
|
|
15
17
|
})
|
package/lib/codesMfgs.json
CHANGED
package/lib/fromPgn.js
CHANGED
|
@@ -39,7 +39,7 @@ const maxUint64 = new Int64LE(0xffffffff, 0xffffffff)
|
|
|
39
39
|
const maxInt64 = new Int64LE(0x7fffffff, 0xffffffff)
|
|
40
40
|
|
|
41
41
|
const FORMAT_PLAIN = 0
|
|
42
|
-
const
|
|
42
|
+
const FORMAT_COALESCED = 1
|
|
43
43
|
|
|
44
44
|
const FASTPACKET_INDEX = 0
|
|
45
45
|
const FASTPACKET_SIZE = 1
|
|
@@ -111,14 +111,13 @@ class Parser extends EventEmitter {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
trace(`${pgn.pgn} ${len} ${pgnData.Length} ${pgnData.RepeatingFields} ${couldBeMulti}`)
|
|
114
|
-
if ( len > 0x8 || (this.format ==
|
|
115
|
-
|
|
116
|
-
this.format = FORMAT_FAST
|
|
114
|
+
if ( coalesced || len > 0x8 || (this.format == FORMAT_COALESCED && !this.mixedFormat) ) {
|
|
115
|
+
this.format = FORMAT_COALESCED
|
|
117
116
|
if ( sourceString ) {
|
|
118
117
|
pgn.input = [ sourceString ]
|
|
119
118
|
}
|
|
120
|
-
} else if ( pgnData.Length > 0x8 || (len == 0x8 && (pgnData.RepeatingFields || couldBeMulti))) {
|
|
121
|
-
|
|
119
|
+
//} else if ( pgnData.Length > 0x8 || (len == 0x8 && (pgnData.RepeatingFields || couldBeMulti))) {
|
|
120
|
+
} else if ( pgnData.Type === 'Fast' ) {
|
|
122
121
|
//partial packet
|
|
123
122
|
this.format = FORMAT_PLAIN
|
|
124
123
|
|
|
@@ -138,7 +137,6 @@ class Parser extends EventEmitter {
|
|
|
138
137
|
var start = bs.byteIndex
|
|
139
138
|
var packetIndex = bs.view.buffer.readUInt8(FASTPACKET_INDEX)
|
|
140
139
|
var bucket = packetIndex & FASTPACKET_MAX_INDEX;
|
|
141
|
-
var maybeBad = false
|
|
142
140
|
|
|
143
141
|
trace(`${pgn.pgn} partial ${packetIndex} ${bucket} ${packet.size}`)
|
|
144
142
|
|
|
@@ -156,14 +154,12 @@ class Parser extends EventEmitter {
|
|
|
156
154
|
bs.view.buffer.copy(packet.buffer, 0, FASTPACKET_BUCKET_0_OFFSET, 8)
|
|
157
155
|
trace(`${pgn.pgn} targetStart: 0 sourceStart: ${FASTPACKET_BUCKET_0_OFFSET}`)
|
|
158
156
|
} else {
|
|
159
|
-
if ( sourceString ) {
|
|
160
|
-
packet.src.push(sourceString)
|
|
161
|
-
}
|
|
162
157
|
if (packet.lastPacket + 1 != packetIndex) {
|
|
163
158
|
debug(`PGN ${pgn.pgn} malformed packet for ${pgn.src} received; expected ${packet.lastPacket+1} but got ${packetIndex}`)
|
|
164
159
|
cb && cb(`Could not parse ${JSON.stringify(pgn)}`)
|
|
165
160
|
bs.byteIndex = start
|
|
166
|
-
|
|
161
|
+
delete this.devices[pgn.src][pgn.pgn]
|
|
162
|
+
return
|
|
167
163
|
} else {
|
|
168
164
|
trace(`${pgn.pgn} targetStart: ${FASTPACKET_BUCKET_0_SIZE + FASTPACKET_BUCKET_N_SIZE * (bucket-1)} sourceStart: ${FASTPACKET_BUCKET_N_OFFSET} sourceEned: ${FASTPACKET_BUCKET_N_SIZE}`)
|
|
169
165
|
bs.view.buffer.copy(
|
|
@@ -173,20 +169,18 @@ class Parser extends EventEmitter {
|
|
|
173
169
|
)
|
|
174
170
|
}
|
|
175
171
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
var view = new BitView(packet.buffer)
|
|
185
|
-
bs = new BitStream(view)
|
|
186
|
-
trace(`${pgn.pgn} done`)
|
|
187
|
-
pgn.input = packet.src
|
|
188
|
-
delete this.devices[pgn.src][pgn.pgn]
|
|
172
|
+
packet.lastPacket = packetIndex;
|
|
173
|
+
if (FASTPACKET_BUCKET_0_SIZE + FASTPACKET_BUCKET_N_SIZE * bucket < packet.size)
|
|
174
|
+
{
|
|
175
|
+
// Packet is not complete yet
|
|
176
|
+
trace(`${pgn.pgn} not complete`)
|
|
177
|
+
return;
|
|
189
178
|
}
|
|
179
|
+
var view = new BitView(packet.buffer)
|
|
180
|
+
bs = new BitStream(view)
|
|
181
|
+
trace(`${pgn.pgn} done`)
|
|
182
|
+
pgn.input = packet.src
|
|
183
|
+
delete this.devices[pgn.src][pgn.pgn]
|
|
190
184
|
} else if ( sourceString ) {
|
|
191
185
|
pgn.input = [ sourceString ]
|
|
192
186
|
}
|
|
@@ -520,17 +514,26 @@ function readField(options, runPostProcessor, pgn, field, bs) {
|
|
|
520
514
|
if ( field.Resolution && typeof value === 'number' ) {
|
|
521
515
|
var resolution = field.Resolution
|
|
522
516
|
|
|
517
|
+
if ( _.isString(resolution) ) {
|
|
518
|
+
resolution = Number.parseFloat(resolution)
|
|
519
|
+
}
|
|
520
|
+
|
|
523
521
|
value = (value * resolution)
|
|
522
|
+
|
|
523
|
+
let precision = 0;
|
|
524
|
+
for (let r = resolution; (r > 0.0) && (r < 1.0); r = r * 10.0)
|
|
525
|
+
{
|
|
526
|
+
precision++;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
value = Number.parseFloat(value.toFixed(precision))
|
|
524
530
|
|
|
531
|
+
/*
|
|
525
532
|
if ( resolution === 3.125e-8 ) {
|
|
526
533
|
//yes. hack.
|
|
527
534
|
resolution = "0.0000000001"
|
|
528
535
|
}
|
|
529
|
-
|
|
530
|
-
if ( _.isString(resolution) &&
|
|
531
|
-
resolution.indexOf('.') != -1 ) {
|
|
532
|
-
value = Number.parseFloat(value.toFixed(resolution.length-2))
|
|
533
|
-
}
|
|
536
|
+
*/
|
|
534
537
|
}
|
|
535
538
|
|
|
536
539
|
if (field.EnumValues &&
|
|
@@ -662,7 +665,13 @@ function readVariableLengthField(options, pgn, field, bs) {
|
|
|
662
665
|
|
|
663
666
|
if ( refField ) {
|
|
664
667
|
var bits = (refField.BitLength + 7) & ~7; // Round # of bits in field refField up to complete bytes: 1->8, 7->8, 8->8 etc.
|
|
665
|
-
|
|
668
|
+
let res = readField(options, false, pgn, refField, bs)
|
|
669
|
+
|
|
670
|
+
if ( bits > field.BitLength ) {
|
|
671
|
+
bs.readBits(bits - refField.BitLength, false)
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
return res
|
|
666
675
|
}
|
|
667
676
|
}
|
|
668
677
|
|
|
@@ -708,7 +717,9 @@ fieldTypeReaders['ASCII string starting with length byte'] = (pgn, field, bs) =>
|
|
|
708
717
|
fieldTypeReaders["String with start/stop byte"] = (pgn, field, bs) => {
|
|
709
718
|
var len
|
|
710
719
|
var first = bs.readUint8()
|
|
711
|
-
if ( first ==
|
|
720
|
+
if ( first == 0xff ) { // no name, stop reading
|
|
721
|
+
return ''
|
|
722
|
+
} else if ( first == 0x02 ) {
|
|
712
723
|
var buf = Buffer.alloc(255)
|
|
713
724
|
var c
|
|
714
725
|
var idx = 0
|
package/lib/simpleCan.js
CHANGED
|
@@ -27,9 +27,9 @@ SimpleCan.prototype.start = function () {
|
|
|
27
27
|
|
|
28
28
|
pgn.timestamp = new Date().toISOString()
|
|
29
29
|
if ( this.plainText ) {
|
|
30
|
-
messageCb(binToActisense(pgn, msg.data, msg.data.length))
|
|
30
|
+
this.messageCb(binToActisense(pgn, msg.data, msg.data.length))
|
|
31
31
|
} else {
|
|
32
|
-
messageCb({ pgn, length: msg.data.length, data: msg.data })
|
|
32
|
+
this.messageCb({ pgn, length: msg.data.length, data: msg.data })
|
|
33
33
|
}
|
|
34
34
|
})
|
|
35
35
|
}
|
package/lib/stringMsg.js
CHANGED
|
@@ -49,7 +49,7 @@ exports.parseActisense = (input) => {
|
|
|
49
49
|
buildCanId(prio, pgn, dst, src),
|
|
50
50
|
'Actisense',
|
|
51
51
|
Buffer.from(data.join(''), 'hex'),
|
|
52
|
-
{ len: Number(len), timestamp
|
|
52
|
+
{ len: Number(len), timestamp },
|
|
53
53
|
)
|
|
54
54
|
}
|
|
55
55
|
exports.encodeActisense = ({
|
|
@@ -153,12 +153,21 @@ exports.encodeMXPGN = ({ prefix = '$MXPGN', pgn, prio, src, data }) => {
|
|
|
153
153
|
exports.isPDGY = startsWith('!PDGY,')
|
|
154
154
|
exports.parsePDGY = (input) => {
|
|
155
155
|
const parts = input.split(',')
|
|
156
|
-
if ( parts.length
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
156
|
+
if ( parts.length === 7 ) {
|
|
157
|
+
const [ prefix, pgn, prio, src, dst, timer, data ] = parts
|
|
158
|
+
return buildMsg(
|
|
159
|
+
buildCanId(prio, pgn, dst, src), 'PDGY', Buffer.from(data, 'base64'),
|
|
160
|
+
{ timer: Number(timer), prefix, coalesced: true },
|
|
161
|
+
)
|
|
162
|
+
} else if ( parts.length === 4 ) {
|
|
163
|
+
const [ prefix, pgn, dst, data ] = parts
|
|
164
|
+
return buildMsg(
|
|
165
|
+
buildCanId(0, pgn, dst, 0), 'PDGY', Buffer.from(data, 'base64'),
|
|
166
|
+
{ coalesced: true }
|
|
167
|
+
)
|
|
168
|
+
} else {
|
|
169
|
+
return buildErr('iKonvert', 'Invalid parts.', input)
|
|
170
|
+
}
|
|
162
171
|
}
|
|
163
172
|
exports.encodePDGY = ({ prefix = '!PDGY', pgn, data, dst = 255}) => (
|
|
164
173
|
[ prefix, pgn, dst, data.toString('base64')].join(',')
|
package/lib/stringMsg.test.js
CHANGED
|
@@ -65,7 +65,6 @@ describe('parseActisense', () => {
|
|
|
65
65
|
test('basic msg', () => {
|
|
66
66
|
const msg = '2016-04-09T16:41:09.078Z,3,127257,17,255,8,00,ff,7f,52,00,21,fe,ff'
|
|
67
67
|
expect(parseActisense(msg)).toEqual({
|
|
68
|
-
coalesced: true,
|
|
69
68
|
data: Buffer.from('00ff7f520021feff', 'hex'),
|
|
70
69
|
dst: 255,
|
|
71
70
|
len: 8,
|
|
@@ -99,6 +98,7 @@ describe('parsePDGY', () => {
|
|
|
99
98
|
prio: 3,
|
|
100
99
|
src: 2,
|
|
101
100
|
timer: 0.563,
|
|
101
|
+
coalesced: true
|
|
102
102
|
})
|
|
103
103
|
})
|
|
104
104
|
test('long msg', () => {
|
|
@@ -111,6 +111,7 @@ describe('parsePDGY', () => {
|
|
|
111
111
|
prio: 3,
|
|
112
112
|
src: 2,
|
|
113
113
|
timer: 483.236,
|
|
114
|
+
coalesced: true
|
|
114
115
|
})
|
|
115
116
|
})
|
|
116
117
|
})
|
package/lib/ydgw02.js
CHANGED