@canboat/canboatjs 3.0.2 → 3.2.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/.github/workflows/publish.yml +18 -9
- package/.github/workflows/test.yml +2 -2
- package/.github/workflows/test_canboat_changes.yml +91 -0
- package/.husky/pre-commit +4 -0
- package/.mocharc.js +7 -0
- package/.prettierrc.json +5 -0
- package/README.md +5 -14
- package/dist/actisense-serial.d.ts +17 -0
- package/dist/actisense-serial.d.ts.map +1 -0
- package/dist/actisense-serial.js +569 -0
- package/dist/actisense-serial.js.map +1 -0
- package/dist/bin/actisense-file.d.ts +3 -0
- package/dist/bin/actisense-file.d.ts.map +1 -0
- package/dist/bin/actisense-file.js +49 -0
- package/dist/bin/actisense-file.js.map +1 -0
- package/dist/bin/actisense-n2k-tcp.d.ts +3 -0
- package/dist/bin/actisense-n2k-tcp.d.ts.map +1 -0
- package/dist/bin/actisense-n2k-tcp.js +46 -0
- package/dist/bin/actisense-n2k-tcp.js.map +1 -0
- package/dist/bin/actisense-serialjs.d.ts +3 -0
- package/dist/bin/actisense-serialjs.d.ts.map +1 -0
- package/dist/bin/actisense-serialjs.js +51 -0
- package/dist/bin/actisense-serialjs.js.map +1 -0
- package/dist/bin/analyzerjs.d.ts +3 -0
- package/dist/bin/analyzerjs.d.ts.map +1 -0
- package/dist/bin/analyzerjs.js +61 -0
- package/dist/bin/analyzerjs.js.map +1 -0
- package/dist/bin/candumpjs.d.ts +3 -0
- package/dist/bin/candumpjs.d.ts.map +1 -0
- package/dist/bin/candumpjs.js +73 -0
- package/dist/bin/candumpjs.js.map +1 -0
- package/dist/bin/cansend.d.ts +3 -0
- package/dist/bin/cansend.d.ts.map +1 -0
- package/dist/bin/cansend.js +123 -0
- package/dist/bin/cansend.js.map +1 -0
- package/dist/bin/ikonvert-serial.d.ts +3 -0
- package/dist/bin/ikonvert-serial.d.ts.map +1 -0
- package/dist/bin/ikonvert-serial.js +36 -0
- package/dist/bin/ikonvert-serial.js.map +1 -0
- package/dist/bin/to-pgn.d.ts +3 -0
- package/dist/bin/to-pgn.d.ts.map +1 -0
- package/dist/bin/to-pgn.js +57 -0
- package/dist/bin/to-pgn.js.map +1 -0
- package/dist/canId.d.ts +21 -0
- package/dist/canId.d.ts.map +1 -0
- package/dist/canId.js +66 -0
- package/dist/canId.js.map +1 -0
- package/dist/canId.test.d.ts +2 -0
- package/dist/canId.test.d.ts.map +1 -0
- package/dist/canId.test.js +58 -0
- package/dist/canId.test.js.map +1 -0
- package/dist/canbus.d.ts +17 -0
- package/dist/canbus.d.ts.map +1 -0
- package/dist/canbus.js +261 -0
- package/dist/canbus.js.map +1 -0
- package/dist/candevice.d.ts +23 -0
- package/dist/candevice.d.ts.map +1 -0
- package/dist/candevice.js +36 -0
- package/dist/candevice.js.map +1 -0
- package/dist/codes.d.ts +2 -0
- package/dist/codes.d.ts.map +1 -0
- package/dist/codes.js +24 -0
- package/dist/codes.js.map +1 -0
- package/dist/discovery.d.ts +17 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +119 -0
- package/dist/discovery.js.map +1 -0
- package/dist/fromPgn.d.ts +51 -0
- package/dist/fromPgn.d.ts.map +1 -0
- package/dist/fromPgn.js +989 -0
- package/dist/fromPgn.js.map +1 -0
- package/dist/fromPgnStream.d.ts +17 -0
- package/dist/fromPgnStream.d.ts.map +1 -0
- package/dist/fromPgnStream.js +47 -0
- package/dist/fromPgnStream.js.map +1 -0
- package/dist/ikonvert.d.ts +17 -0
- package/dist/ikonvert.d.ts.map +1 -0
- package/dist/ikonvert.js +224 -0
- package/dist/ikonvert.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -0
- package/dist/n2k-actisense.d.ts +24 -0
- package/dist/n2k-actisense.d.ts.map +1 -0
- package/dist/n2k-actisense.js +126 -0
- package/dist/n2k-actisense.js.map +1 -0
- package/dist/n2k-actisense.test.d.ts +2 -0
- package/dist/n2k-actisense.test.d.ts.map +1 -0
- package/dist/n2k-actisense.test.js +49 -0
- package/dist/n2k-actisense.test.js.map +1 -0
- package/dist/n2kDevice.d.ts +44 -0
- package/dist/n2kDevice.d.ts.map +1 -0
- package/dist/n2kDevice.js +436 -0
- package/dist/n2kDevice.js.map +1 -0
- package/dist/pgns.d.ts +22 -0
- package/dist/pgns.d.ts.map +1 -0
- package/dist/pgns.js +157 -0
- package/dist/pgns.js.map +1 -0
- package/dist/pgns.test.d.ts +2 -0
- package/dist/pgns.test.d.ts.map +1 -0
- package/dist/pgns.test.js +14 -0
- package/dist/pgns.test.js.map +1 -0
- package/dist/simpleCan.d.ts +17 -0
- package/dist/simpleCan.d.ts.map +1 -0
- package/dist/simpleCan.js +125 -0
- package/dist/simpleCan.js.map +1 -0
- package/dist/stringMsg.d.ts +33 -0
- package/dist/stringMsg.d.ts.map +1 -0
- package/dist/stringMsg.js +359 -0
- package/dist/stringMsg.js.map +1 -0
- package/dist/stringMsg.test.d.ts +2 -0
- package/dist/stringMsg.test.d.ts.map +1 -0
- package/dist/stringMsg.test.js +244 -0
- package/dist/stringMsg.test.js.map +1 -0
- package/dist/toPgn.d.ts +34 -0
- package/dist/toPgn.d.ts.map +1 -0
- package/dist/toPgn.js +500 -0
- package/dist/toPgn.js.map +1 -0
- package/dist/utilities.d.ts +28 -0
- package/dist/utilities.d.ts.map +1 -0
- package/dist/utilities.js +159 -0
- package/dist/utilities.js.map +1 -0
- package/dist/utilities.test.d.ts +2 -0
- package/dist/utilities.test.d.ts.map +1 -0
- package/dist/utilities.test.js +9 -0
- package/dist/utilities.test.js.map +1 -0
- package/dist/venus-mqtt.d.ts +11 -0
- package/dist/venus-mqtt.d.ts.map +1 -0
- package/dist/venus-mqtt.js +100 -0
- package/dist/venus-mqtt.js.map +1 -0
- package/dist/venus.d.ts +11 -0
- package/dist/venus.d.ts.map +1 -0
- package/dist/venus.js +71 -0
- package/dist/venus.js.map +1 -0
- package/dist/w2k01.d.ts +17 -0
- package/dist/w2k01.d.ts.map +1 -0
- package/dist/w2k01.js +119 -0
- package/dist/w2k01.js.map +1 -0
- package/dist/yddevice.d.ts +25 -0
- package/dist/yddevice.d.ts.map +1 -0
- package/dist/yddevice.js +43 -0
- package/dist/yddevice.js.map +1 -0
- package/dist/ydgw02.d.ts +17 -0
- package/dist/ydgw02.d.ts.map +1 -0
- package/dist/ydgw02.js +163 -0
- package/dist/ydgw02.js.map +1 -0
- package/dist/ydvr.d.ts +17 -0
- package/dist/ydvr.d.ts.map +1 -0
- package/dist/ydvr.js +120 -0
- package/dist/ydvr.js.map +1 -0
- package/eslint.config.js +58 -0
- package/jest.config.js +5 -0
- package/lib/actisense-serial.ts +644 -0
- package/lib/bin/actisense-file.ts +53 -0
- package/lib/bin/actisense-n2k-tcp.ts +50 -0
- package/lib/bin/actisense-serialjs.ts +55 -0
- package/{bin/analyzerjs → lib/bin/analyzerjs.ts} +16 -15
- package/{bin/candumpjs → lib/bin/candumpjs.ts} +19 -20
- package/lib/bin/cansend.ts +131 -0
- package/lib/bin/ikonvert-serial.ts +44 -0
- package/{bin/to-pgn → lib/bin/to-pgn.ts} +23 -17
- package/lib/bin/ydvr-file +33 -0
- package/lib/canId.test.js +35 -15
- package/lib/canId.ts +84 -0
- package/lib/canbus.ts +293 -0
- package/lib/candevice.ts +41 -0
- package/lib/codes.ts +21 -0
- package/lib/{discovery.js → discovery.ts} +32 -30
- package/lib/fromPgn.ts +1207 -0
- package/lib/{fromPgnStream.js → fromPgnStream.ts} +17 -12
- package/lib/{ikonvert.js → ikonvert.ts} +99 -94
- package/lib/index.ts +48 -0
- package/lib/n2k-actisense.test.js +31 -32
- package/lib/n2k-actisense.ts +152 -0
- package/lib/n2kDevice.ts +516 -0
- package/lib/pgns.test.ts +12 -0
- package/lib/pgns.ts +191 -0
- package/lib/simpleCan.ts +140 -0
- package/lib/stringMsg.test.js +58 -41
- package/lib/stringMsg.ts +464 -0
- package/lib/toPgn.ts +597 -0
- package/lib/utilities.ts +169 -0
- package/lib/venus-mqtt.js +69 -73
- package/lib/venus.js +8 -8
- package/lib/w2k01.ts +142 -0
- package/lib/{yddevice.js → yddevice.ts} +18 -16
- package/lib/{ydgw02.js → ydgw02.ts} +58 -51
- package/lib/ydvr.js +65 -147
- package/package.json +54 -18
- package/tsconfig.json +19 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/CHANGELOG.md +0 -101
- package/bin/actisense-file +0 -47
- package/bin/actisense-n2k-tcp +0 -45
- package/bin/actisense-serialjs +0 -52
- package/bin/candumpanalyzerjs +0 -29
- package/bin/cansend +0 -130
- package/bin/ikonvert-serial +0 -50
- package/bin/ydgw-analyzerjs +0 -36
- package/bin/ydvr-file +0 -33
- package/index.js +0 -53
- package/ios_canboat.js/main.js +0 -2
- package/ios_canboat.js/main.js.LICENSE.txt +0 -17
- package/ios_canboat.js/main.js.map +0 -1
- package/lib/canId.js +0 -64
- package/lib/canbus.js +0 -278
- package/lib/candevice.js +0 -51
- package/lib/codes.js +0 -69
- package/lib/codes.test.js +0 -17
- package/lib/codesMfgs.json +0 -166
- package/lib/fromPgn.js +0 -1027
- package/lib/n2k-actisense.js +0 -108
- package/lib/n2kDevice.js +0 -390
- package/lib/pgns.js +0 -196
- package/lib/pgns.test.js +0 -13
- package/lib/serial.js +0 -647
- package/lib/simpleCan.js +0 -105
- package/lib/stringMsg.js +0 -339
- package/lib/toPgn.js +0 -518
- package/lib/utilities.js +0 -111
- package/lib/w2k01.js +0 -129
package/lib/toPgn.ts
ADDED
|
@@ -0,0 +1,597 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2018 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
|
+
import { Field, PGN } from '@canboat/ts-pgns'
|
|
18
|
+
import { getField } from './fromPgn'
|
|
19
|
+
import {
|
|
20
|
+
getPgn,
|
|
21
|
+
getCustomPgn,
|
|
22
|
+
lookupEnumerationValue,
|
|
23
|
+
lookupFieldTypeEnumerationValue,
|
|
24
|
+
lookupBitEnumerationName,
|
|
25
|
+
lookupFieldTypeEnumerationBits
|
|
26
|
+
} from './pgns'
|
|
27
|
+
import _ from 'lodash'
|
|
28
|
+
import { BitStream } from 'bit-buffer'
|
|
29
|
+
import { Int64LE, Uint64LE } from 'int64-buffer'
|
|
30
|
+
import {
|
|
31
|
+
encodeActisense,
|
|
32
|
+
encodeActisenseN2KACSII,
|
|
33
|
+
encodeYDRAW,
|
|
34
|
+
encodeYDRAWFull,
|
|
35
|
+
parseActisense,
|
|
36
|
+
encodePCDIN,
|
|
37
|
+
encodeMXPGN,
|
|
38
|
+
encodePDGY
|
|
39
|
+
} from './stringMsg'
|
|
40
|
+
import { encodeN2KActisense } from './n2k-actisense'
|
|
41
|
+
import { createDebug } from './utilities'
|
|
42
|
+
|
|
43
|
+
const debug = createDebug('canboatjs:toPgn')
|
|
44
|
+
|
|
45
|
+
const RES_STRINGLAU = 'STRING_LAU' //'ASCII or UNICODE string starting with length and control byte'
|
|
46
|
+
const RES_STRINGLZ = 'STRING_LZ' //'ASCII string starting with length byte'
|
|
47
|
+
|
|
48
|
+
type FieldTypeWriter = (
|
|
49
|
+
pgn: number,
|
|
50
|
+
field: Field,
|
|
51
|
+
value: any,
|
|
52
|
+
bs: BitStream
|
|
53
|
+
) => void
|
|
54
|
+
type FieldTypeMapper = (field: Field, value: any) => any
|
|
55
|
+
|
|
56
|
+
const fieldTypeWriters: {
|
|
57
|
+
[key: string]: FieldTypeWriter
|
|
58
|
+
} = {}
|
|
59
|
+
const fieldTypeMappers: {
|
|
60
|
+
[key: string]: FieldTypeMapper
|
|
61
|
+
} = {}
|
|
62
|
+
|
|
63
|
+
//const lengthsOff: {[key: number]: number} = { 129029: 45, 127257:8, 127258:8, 127251:8 }
|
|
64
|
+
|
|
65
|
+
const a126208_oldKey = '# of Parameters'
|
|
66
|
+
const a126208_newKey = 'Number of Parameters'
|
|
67
|
+
|
|
68
|
+
export function toPgn(data: any): Buffer | undefined {
|
|
69
|
+
const customPgns = getCustomPgn(data.pgn)
|
|
70
|
+
let pgnList = getPgn(data.pgn)
|
|
71
|
+
if (!pgnList && !customPgns) {
|
|
72
|
+
debug('no pgn found: ' + data.pgn)
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (customPgns) {
|
|
77
|
+
pgnList = [...customPgns.definitions, ...(pgnList || [])]
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!pgnList || pgnList.length === 0) {
|
|
81
|
+
debug('no pgn found: ' + data.pgn)
|
|
82
|
+
return undefined
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const pgn_number = data.pgn
|
|
86
|
+
let pgnData = pgnList[0]
|
|
87
|
+
|
|
88
|
+
const bs = new BitStream(Buffer.alloc(500))
|
|
89
|
+
|
|
90
|
+
if (data.fields) {
|
|
91
|
+
data = data.fields
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (pgn_number === 126208 && !data[a126208_newKey] && data[a126208_oldKey]) {
|
|
95
|
+
//a bit of a hack because this field name changed and I'm sure there is code out
|
|
96
|
+
//there that still uses the old field name
|
|
97
|
+
|
|
98
|
+
data[a126208_newKey] = data[a126208_oldKey]
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let fields = pgnData.Fields
|
|
102
|
+
let RepeatingFields = pgnData.RepeatingFieldSet1Size
|
|
103
|
+
? pgnData.RepeatingFieldSet1Size
|
|
104
|
+
: 0
|
|
105
|
+
for (let index = 0; index < fields.length - RepeatingFields; index++) {
|
|
106
|
+
const field = fields[index]
|
|
107
|
+
let value =
|
|
108
|
+
data[field.Name] !== undefined ? data[field.Name] : data[field.Id]
|
|
109
|
+
|
|
110
|
+
if (!_.isUndefined(field.Match)) {
|
|
111
|
+
//console.log(`matching ${field.Name} ${field.Match} ${value} ${_.isString(value)}`)
|
|
112
|
+
if (_.isString(value)) {
|
|
113
|
+
pgnList = pgnList.filter((f) => f.Fields[index].Description == value)
|
|
114
|
+
} else {
|
|
115
|
+
pgnList = pgnList.filter((f) => f.Fields[index].Match == value)
|
|
116
|
+
}
|
|
117
|
+
if (pgnList.length > 0) {
|
|
118
|
+
//console.log(`matched ${field.Name} ${pgnList[0].Fields[index].Match}`)
|
|
119
|
+
pgnData = pgnList[0]
|
|
120
|
+
value = pgnData.Fields[index].Match
|
|
121
|
+
fields = pgnData.Fields
|
|
122
|
+
RepeatingFields = pgnData.RepeatingFieldSet1Size
|
|
123
|
+
? pgnData.RepeatingFieldSet1Size
|
|
124
|
+
: 0
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
writeField(bs, pgn_number, field, data, value, fields)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (data.list) {
|
|
131
|
+
data.list.forEach((repeat: any) => {
|
|
132
|
+
for (let index = 0; index < RepeatingFields; index++) {
|
|
133
|
+
const field = fields[pgnData.Fields.length - RepeatingFields + index]
|
|
134
|
+
const value =
|
|
135
|
+
repeat[field.Name] !== undefined
|
|
136
|
+
? repeat[field.Name]
|
|
137
|
+
: repeat[field.Id]
|
|
138
|
+
|
|
139
|
+
writeField(bs, pgn_number, field, data, value, fields)
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const bitsLeft = bs.byteIndex * 8 - bs.index
|
|
145
|
+
if (bitsLeft > 0) {
|
|
146
|
+
//finish off the last byte
|
|
147
|
+
bs.writeBits(0xffff, bitsLeft)
|
|
148
|
+
//console.log(`bits left ${bitsLeft}`)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (
|
|
152
|
+
pgnData.Length !== undefined &&
|
|
153
|
+
pgnData.Length !== 0xff &&
|
|
154
|
+
fields[fields.length - 1].FieldType !== RES_STRINGLAU &&
|
|
155
|
+
fields[fields.length - 1].FieldType !== RES_STRINGLZ &&
|
|
156
|
+
!RepeatingFields
|
|
157
|
+
) {
|
|
158
|
+
//const len = lengthsOff[pgnData.PGN] || pgnData.Length
|
|
159
|
+
//console.log(`Length ${len}`)
|
|
160
|
+
|
|
161
|
+
//if ( bs.byteIndex < pgnData.Length ) {
|
|
162
|
+
//console.log(`bytes left ${pgnData.Length-bs.byteIndex}`)
|
|
163
|
+
//}
|
|
164
|
+
|
|
165
|
+
for (let i = bs.byteIndex; i < pgnData.Length; i++) {
|
|
166
|
+
bs.writeUint8(0xff)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return bs.view.buffer.slice(0, bs.byteIndex)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/*
|
|
174
|
+
function dumpWritten(bs, field, startPos, value) {
|
|
175
|
+
//console.log(`${startPos} ${bs.byteIndex}`)
|
|
176
|
+
if ( startPos == bs.byteIndex )
|
|
177
|
+
startPos--
|
|
178
|
+
let string = `${field.Name} (${field.BitLength}): [`
|
|
179
|
+
for ( let i = startPos; i < bs.byteIndex; i++ ) {
|
|
180
|
+
string = string + bs.view.buffer[i].toString(16) + ', '
|
|
181
|
+
}
|
|
182
|
+
console.log(string + `] ${value}`)
|
|
183
|
+
}
|
|
184
|
+
*/
|
|
185
|
+
|
|
186
|
+
function writeField(
|
|
187
|
+
bs: BitStream,
|
|
188
|
+
pgn_number: number,
|
|
189
|
+
field: Field,
|
|
190
|
+
data: any,
|
|
191
|
+
value: any,
|
|
192
|
+
fields: Field[],
|
|
193
|
+
bitLength: number | undefined = undefined
|
|
194
|
+
) {
|
|
195
|
+
//const startPos = bs.byteIndex
|
|
196
|
+
|
|
197
|
+
if (bitLength === undefined) {
|
|
198
|
+
if (field.BitLengthVariable && field.FieldType === 'DYNAMIC_FIELD_VALUE') {
|
|
199
|
+
bitLength = lookupKeyBitLength(data, fields)
|
|
200
|
+
} else {
|
|
201
|
+
bitLength = field.BitLength
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// console.log(`${field.Name}:${value}(${bitLength}-${field.Resolution})`)
|
|
206
|
+
if (value === undefined || value === null) {
|
|
207
|
+
if (field.FieldType && fieldTypeWriters[field.FieldType]) {
|
|
208
|
+
fieldTypeWriters[field.FieldType](pgn_number, field, value, bs)
|
|
209
|
+
} else if (bitLength !== undefined && bitLength % 8 == 0) {
|
|
210
|
+
const bytes = bitLength / 8
|
|
211
|
+
//const byte = field.Name.startsWith('Reserved') ? 0x00 : 0xff
|
|
212
|
+
for (let i = 0; i < bytes - 1; i++) {
|
|
213
|
+
bs.writeUint8(0xff)
|
|
214
|
+
}
|
|
215
|
+
bs.writeUint8(field.Signed ? 0x7f : 0xff)
|
|
216
|
+
} else if (bitLength !== undefined) {
|
|
217
|
+
bs.writeBits(0xffffffff, bitLength)
|
|
218
|
+
} else {
|
|
219
|
+
//FIXME: error! should not happen
|
|
220
|
+
}
|
|
221
|
+
} else {
|
|
222
|
+
const type = field.FieldType
|
|
223
|
+
if (type && fieldTypeMappers[type]) {
|
|
224
|
+
value = fieldTypeMappers[type](field, value)
|
|
225
|
+
} else if (
|
|
226
|
+
(field.FieldType === 'LOOKUP' ||
|
|
227
|
+
field.FieldType === 'DYNAMIC_FIELD_KEY') &&
|
|
228
|
+
_.isString(value)
|
|
229
|
+
) {
|
|
230
|
+
value = lookup(field, value)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (field.FieldType == 'NUMBER' && _.isString(value)) {
|
|
234
|
+
value = Number(value)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (field.Resolution && typeof value === 'number') {
|
|
238
|
+
value = Number((value / field.Resolution).toFixed(0))
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (field.FieldType && fieldTypeWriters[field.FieldType]) {
|
|
242
|
+
fieldTypeWriters[field.FieldType](pgn_number, field, value, bs)
|
|
243
|
+
} else {
|
|
244
|
+
/*
|
|
245
|
+
if ( _.isString(value) && typeof bitLength !== 'undefined' && bitLength !== 0 ) {
|
|
246
|
+
value = Number(value)
|
|
247
|
+
}
|
|
248
|
+
*/
|
|
249
|
+
|
|
250
|
+
if (field.Unit === 'kWh') {
|
|
251
|
+
value /= 3.6e6 // 1 kWh = 3.6 MJ.
|
|
252
|
+
} else if (field.Unit === 'Ah') {
|
|
253
|
+
value /= 3600.0 // 1 Ah = 3600 C.
|
|
254
|
+
}
|
|
255
|
+
if (field.Offset) {
|
|
256
|
+
value -= field.Offset
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (field.FieldType === 'VARIABLE') {
|
|
260
|
+
writeVariableLengthField(bs, pgn_number, data, field, value, fields)
|
|
261
|
+
} else if (_.isBuffer(value)) {
|
|
262
|
+
value.copy(bs.view.buffer, bs.byteIndex)
|
|
263
|
+
bs.byteIndex += value.length
|
|
264
|
+
} else if (bitLength !== undefined) {
|
|
265
|
+
if (bitLength === 8) {
|
|
266
|
+
if (field.Signed) {
|
|
267
|
+
bs.writeInt8(value)
|
|
268
|
+
} else {
|
|
269
|
+
bs.writeUint8(value)
|
|
270
|
+
}
|
|
271
|
+
} else if (bitLength === 16) {
|
|
272
|
+
if (field.Signed) {
|
|
273
|
+
bs.writeInt16(value)
|
|
274
|
+
} else {
|
|
275
|
+
bs.writeUint16(value)
|
|
276
|
+
}
|
|
277
|
+
} else if (bitLength === 32) {
|
|
278
|
+
if (field.Signed) {
|
|
279
|
+
bs.writeInt32(value)
|
|
280
|
+
} else {
|
|
281
|
+
bs.writeUint32(value)
|
|
282
|
+
}
|
|
283
|
+
} else if (bitLength === 48 || bitLength == 24) {
|
|
284
|
+
let count = bitLength / 8
|
|
285
|
+
let val = value
|
|
286
|
+
if (value < 0) {
|
|
287
|
+
val++
|
|
288
|
+
}
|
|
289
|
+
while (count-- > 0) {
|
|
290
|
+
if (value > 0) {
|
|
291
|
+
bs.writeUint8(val & 255)
|
|
292
|
+
val /= 256
|
|
293
|
+
} else {
|
|
294
|
+
bs.writeUint8((-val & 255) ^ 255)
|
|
295
|
+
val /= 256
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
} else if (bitLength === 64) {
|
|
299
|
+
let num
|
|
300
|
+
if (field.Signed) {
|
|
301
|
+
num = new Int64LE(value)
|
|
302
|
+
} else {
|
|
303
|
+
num = new Uint64LE(value)
|
|
304
|
+
}
|
|
305
|
+
const buf = num.toBuffer()
|
|
306
|
+
buf.copy(bs.view.buffer, bs.byteIndex)
|
|
307
|
+
bs.byteIndex += buf.length
|
|
308
|
+
} else {
|
|
309
|
+
bs.writeBits(value, bitLength)
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
//dumpWritten(bs, field, startPos, value)
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function writeVariableLengthField(
|
|
318
|
+
bs: BitStream,
|
|
319
|
+
pgn_number: number,
|
|
320
|
+
pgn: any,
|
|
321
|
+
field: Field,
|
|
322
|
+
value: any,
|
|
323
|
+
fields: Field[]
|
|
324
|
+
) {
|
|
325
|
+
const refField = getField(pgn.PGN, bs.view.buffer[bs.byteIndex - 1] - 1, pgn)
|
|
326
|
+
|
|
327
|
+
if (refField) {
|
|
328
|
+
let bits
|
|
329
|
+
|
|
330
|
+
if (refField.BitLength !== undefined) {
|
|
331
|
+
bits = (refField.BitLength + 7) & ~7 // Round # of bits in field refField up to complete bytes: 1->8, 7->8, 8->8 etc.
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return writeField(bs, pgn_number, refField, pgn, value, fields, bits)
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function lookup(field: Field, stringValue: string) {
|
|
339
|
+
let res
|
|
340
|
+
if (field.LookupEnumeration) {
|
|
341
|
+
res = lookupEnumerationValue(field.LookupEnumeration, stringValue)
|
|
342
|
+
} else {
|
|
343
|
+
res = lookupFieldTypeEnumerationValue(
|
|
344
|
+
field.LookupFieldTypeEnumeration,
|
|
345
|
+
stringValue
|
|
346
|
+
)
|
|
347
|
+
}
|
|
348
|
+
return _.isUndefined(res) ? stringValue : res
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function lookupKeyBitLength(data: any, fields: Field[]) {
|
|
352
|
+
const field = fields.find((field) => field.Name === 'Key')
|
|
353
|
+
|
|
354
|
+
if (field) {
|
|
355
|
+
let val = data['Key'] || data['key']
|
|
356
|
+
if (typeof val === 'string') {
|
|
357
|
+
val = lookupFieldTypeEnumerationValue(
|
|
358
|
+
field.LookupFieldTypeEnumeration,
|
|
359
|
+
val
|
|
360
|
+
)
|
|
361
|
+
}
|
|
362
|
+
return lookupFieldTypeEnumerationBits(field.LookupFieldTypeEnumeration, val)
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/*
|
|
367
|
+
|
|
368
|
+
function parseHex(s:string): number {
|
|
369
|
+
return parseInt(s, 16)
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
function canboat2Buffer(canboatData:string) {
|
|
373
|
+
return Buffer.alloc(canboatData
|
|
374
|
+
.split(',')
|
|
375
|
+
.slice(6)
|
|
376
|
+
.map(parseHex), 'hex')
|
|
377
|
+
}
|
|
378
|
+
*/
|
|
379
|
+
|
|
380
|
+
export function pgnToActisenseSerialFormat(pgn: PGN) {
|
|
381
|
+
return encodeActisense({
|
|
382
|
+
pgn: pgn.pgn,
|
|
383
|
+
data: toPgn(pgn),
|
|
384
|
+
dst: pgn.dst,
|
|
385
|
+
src: pgn.src,
|
|
386
|
+
prio: pgn.prio,
|
|
387
|
+
timestamp: undefined
|
|
388
|
+
})
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
export function pgnToActisenseN2KAsciiFormat(pgn: PGN) {
|
|
392
|
+
return encodeActisenseN2KACSII({
|
|
393
|
+
pgn: pgn.pgn,
|
|
394
|
+
data: toPgn(pgn),
|
|
395
|
+
dst: pgn.dst,
|
|
396
|
+
src: pgn.src,
|
|
397
|
+
prio: pgn.prio,
|
|
398
|
+
timestamp: undefined
|
|
399
|
+
})
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export function pgnToN2KActisenseFormat(pgn: PGN) {
|
|
403
|
+
const data = toPgn(pgn)
|
|
404
|
+
if (data) {
|
|
405
|
+
return encodeN2KActisense(pgn, data)
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export function toiKonvertSerialFormat(pgn: number, data: Buffer, dst = 255) {
|
|
410
|
+
return `!PDGY,${pgn},${dst},${data.toString('base64')}`
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
export function pgnToiKonvertSerialFormat(pgn: any) {
|
|
414
|
+
const data = toPgn(pgn)
|
|
415
|
+
if (data) {
|
|
416
|
+
return toiKonvertSerialFormat(pgn.pgn, data, pgn.dst)
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
export function pgnToYdgwRawFormat(info: any) {
|
|
421
|
+
return encodeYDRAW({ ...info, data: toPgn(info) })
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
export function pgnToYdgwFullRawFormat(info: any) {
|
|
425
|
+
return encodeYDRAWFull({ ...info, data: toPgn(info) })
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
export function pgnToPCDIN(info: any) {
|
|
429
|
+
return encodePCDIN({ ...info, data: toPgn(info) })
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
export function pgnToMXPGN(info: any) {
|
|
433
|
+
return encodeMXPGN({ ...info, data: toPgn(info) })
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
export const actisenseToYdgwRawFormat = _.flow(parseActisense, encodeYDRAW)
|
|
437
|
+
export const actisenseToYdgwFullRawFormat = _.flow(
|
|
438
|
+
parseActisense,
|
|
439
|
+
encodeYDRAWFull
|
|
440
|
+
)
|
|
441
|
+
export const actisenseToPCDIN = _.flow(parseActisense, encodePCDIN)
|
|
442
|
+
export const actisenseToMXPGN = _.flow(parseActisense, encodeMXPGN)
|
|
443
|
+
export const actisenseToiKonvert = _.flow(parseActisense, encodePDGY)
|
|
444
|
+
export const actisenseToN2KAsciiFormat = _.flow(
|
|
445
|
+
parseActisense,
|
|
446
|
+
encodeActisenseN2KACSII
|
|
447
|
+
)
|
|
448
|
+
export const actisenseToN2KActisenseFormat = _.flow(
|
|
449
|
+
parseActisense,
|
|
450
|
+
encodeN2KActisense
|
|
451
|
+
)
|
|
452
|
+
|
|
453
|
+
function bitIsSet(field: Field, index: number, value: string) {
|
|
454
|
+
const enumName = lookupBitEnumerationName(
|
|
455
|
+
field.LookupBitEnumeration as string,
|
|
456
|
+
index
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
return enumName ? value.indexOf(enumName) != -1 : false
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
fieldTypeWriters['BITLOOKUP'] = (pgn, field, value, bs) => {
|
|
463
|
+
if (field.BitLength !== undefined) {
|
|
464
|
+
if (value === undefined || value.length === 0) {
|
|
465
|
+
if (field.BitLength % 8 == 0) {
|
|
466
|
+
const bytes = field.BitLength / 8
|
|
467
|
+
//const lastByte = field.Signed ? 0x7f : 0xff
|
|
468
|
+
for (let i = 0; i < bytes - 1; i++) {
|
|
469
|
+
bs.writeUint8(0x0)
|
|
470
|
+
}
|
|
471
|
+
bs.writeUint8(0x0)
|
|
472
|
+
} else {
|
|
473
|
+
bs.writeBits(0xffffffff, field.BitLength)
|
|
474
|
+
}
|
|
475
|
+
} else {
|
|
476
|
+
for (let i = 0; i < field.BitLength; i++) {
|
|
477
|
+
bs.writeBits(bitIsSet(field, i, value) ? 1 : 0, 1)
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
fieldTypeWriters['STRING_FIX'] = (pgn, field, value, bs) => {
|
|
484
|
+
if (field.BitLength !== undefined) {
|
|
485
|
+
let fill = 0xff
|
|
486
|
+
if (
|
|
487
|
+
(pgn === 129810 &&
|
|
488
|
+
(field.Name === 'Vendor ID' || field.Name === 'Callsign')) ||
|
|
489
|
+
(pgn === 129809 && field.Name === 'Name')
|
|
490
|
+
) {
|
|
491
|
+
if (_.isUndefined(value) || value.length == 0) {
|
|
492
|
+
{
|
|
493
|
+
fill = 0x40
|
|
494
|
+
value = ''
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
if (value === undefined) {
|
|
500
|
+
value = ''
|
|
501
|
+
}
|
|
502
|
+
const fieldLen = field.BitLength / 8
|
|
503
|
+
|
|
504
|
+
for (let i = 0; i < value.length; i++) {
|
|
505
|
+
bs.writeUint8(value.charCodeAt(i))
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
for (let i = 0; i < fieldLen - value.length; i++) {
|
|
509
|
+
bs.writeUint8(fill)
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
fieldTypeWriters[RES_STRINGLZ] = (pgn, field, value, bs) => {
|
|
515
|
+
if (_.isUndefined(value)) {
|
|
516
|
+
value = ''
|
|
517
|
+
}
|
|
518
|
+
bs.writeUint8(value.length)
|
|
519
|
+
for (let i = 0; i < value.length; i++) {
|
|
520
|
+
bs.writeUint8(value.charCodeAt(i))
|
|
521
|
+
}
|
|
522
|
+
bs.writeUint8(0)
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
fieldTypeWriters['String with start/stop byte'] = (pgn, field, value, bs) => {
|
|
526
|
+
if (_.isUndefined(value)) {
|
|
527
|
+
value = ''
|
|
528
|
+
}
|
|
529
|
+
bs.writeUint8(0x02)
|
|
530
|
+
for (let i = 0; i < value.length; i++) {
|
|
531
|
+
bs.writeUint8(value.charCodeAt(i))
|
|
532
|
+
}
|
|
533
|
+
bs.writeUint8(0x01)
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
fieldTypeWriters[RES_STRINGLAU] = (pgn, field, value, bs) => {
|
|
537
|
+
if (pgn === 129041 && field.Name === 'AtoN Name') {
|
|
538
|
+
if (value.length > 18) {
|
|
539
|
+
value = value.substring(0, 18)
|
|
540
|
+
} else {
|
|
541
|
+
value = value.padEnd(18, ' ')
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
bs.writeUint8(value ? value.length + 2 : 2)
|
|
546
|
+
bs.writeUint8(1)
|
|
547
|
+
|
|
548
|
+
if (value) {
|
|
549
|
+
for (let idx = 0; idx < value.length; idx++) {
|
|
550
|
+
bs.writeUint8(value.charCodeAt(idx))
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
fieldTypeMappers['DATE'] = (field, value) => {
|
|
556
|
+
//console.log(`Date: ${value}`)
|
|
557
|
+
if (_.isString(value)) {
|
|
558
|
+
const date = new Date(value)
|
|
559
|
+
return date.getTime() / 86400 / 1000
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
return value
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
fieldTypeMappers['TIME'] = (field, value) => {
|
|
566
|
+
if (_.isString(value)) {
|
|
567
|
+
const split = value.split(':')
|
|
568
|
+
|
|
569
|
+
const hours = Number(split[0])
|
|
570
|
+
const minutes = Number(split[1])
|
|
571
|
+
const seconds = Number(split[2])
|
|
572
|
+
|
|
573
|
+
value = hours * 60 * 60 + minutes * 60 + seconds
|
|
574
|
+
}
|
|
575
|
+
return value
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
fieldTypeMappers['DURATION'] = fieldTypeMappers['TIME']
|
|
579
|
+
|
|
580
|
+
fieldTypeMappers['Pressure'] = (field, value) => {
|
|
581
|
+
if (field.Unit) {
|
|
582
|
+
switch (field.Unit[0]) {
|
|
583
|
+
case 'h':
|
|
584
|
+
case 'H':
|
|
585
|
+
value /= 100
|
|
586
|
+
break
|
|
587
|
+
case 'k':
|
|
588
|
+
case 'K':
|
|
589
|
+
value /= 1000
|
|
590
|
+
break
|
|
591
|
+
case 'd':
|
|
592
|
+
value *= 10
|
|
593
|
+
break
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return value
|
|
597
|
+
}
|