@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.
Files changed (222) hide show
  1. package/.github/workflows/publish.yml +18 -9
  2. package/.github/workflows/test.yml +2 -2
  3. package/.github/workflows/test_canboat_changes.yml +91 -0
  4. package/.husky/pre-commit +4 -0
  5. package/.mocharc.js +7 -0
  6. package/.prettierrc.json +5 -0
  7. package/README.md +5 -14
  8. package/dist/actisense-serial.d.ts +17 -0
  9. package/dist/actisense-serial.d.ts.map +1 -0
  10. package/dist/actisense-serial.js +569 -0
  11. package/dist/actisense-serial.js.map +1 -0
  12. package/dist/bin/actisense-file.d.ts +3 -0
  13. package/dist/bin/actisense-file.d.ts.map +1 -0
  14. package/dist/bin/actisense-file.js +49 -0
  15. package/dist/bin/actisense-file.js.map +1 -0
  16. package/dist/bin/actisense-n2k-tcp.d.ts +3 -0
  17. package/dist/bin/actisense-n2k-tcp.d.ts.map +1 -0
  18. package/dist/bin/actisense-n2k-tcp.js +46 -0
  19. package/dist/bin/actisense-n2k-tcp.js.map +1 -0
  20. package/dist/bin/actisense-serialjs.d.ts +3 -0
  21. package/dist/bin/actisense-serialjs.d.ts.map +1 -0
  22. package/dist/bin/actisense-serialjs.js +51 -0
  23. package/dist/bin/actisense-serialjs.js.map +1 -0
  24. package/dist/bin/analyzerjs.d.ts +3 -0
  25. package/dist/bin/analyzerjs.d.ts.map +1 -0
  26. package/dist/bin/analyzerjs.js +61 -0
  27. package/dist/bin/analyzerjs.js.map +1 -0
  28. package/dist/bin/candumpjs.d.ts +3 -0
  29. package/dist/bin/candumpjs.d.ts.map +1 -0
  30. package/dist/bin/candumpjs.js +73 -0
  31. package/dist/bin/candumpjs.js.map +1 -0
  32. package/dist/bin/cansend.d.ts +3 -0
  33. package/dist/bin/cansend.d.ts.map +1 -0
  34. package/dist/bin/cansend.js +123 -0
  35. package/dist/bin/cansend.js.map +1 -0
  36. package/dist/bin/ikonvert-serial.d.ts +3 -0
  37. package/dist/bin/ikonvert-serial.d.ts.map +1 -0
  38. package/dist/bin/ikonvert-serial.js +36 -0
  39. package/dist/bin/ikonvert-serial.js.map +1 -0
  40. package/dist/bin/to-pgn.d.ts +3 -0
  41. package/dist/bin/to-pgn.d.ts.map +1 -0
  42. package/dist/bin/to-pgn.js +57 -0
  43. package/dist/bin/to-pgn.js.map +1 -0
  44. package/dist/canId.d.ts +21 -0
  45. package/dist/canId.d.ts.map +1 -0
  46. package/dist/canId.js +66 -0
  47. package/dist/canId.js.map +1 -0
  48. package/dist/canId.test.d.ts +2 -0
  49. package/dist/canId.test.d.ts.map +1 -0
  50. package/dist/canId.test.js +58 -0
  51. package/dist/canId.test.js.map +1 -0
  52. package/dist/canbus.d.ts +17 -0
  53. package/dist/canbus.d.ts.map +1 -0
  54. package/dist/canbus.js +261 -0
  55. package/dist/canbus.js.map +1 -0
  56. package/dist/candevice.d.ts +23 -0
  57. package/dist/candevice.d.ts.map +1 -0
  58. package/dist/candevice.js +36 -0
  59. package/dist/candevice.js.map +1 -0
  60. package/dist/codes.d.ts +2 -0
  61. package/dist/codes.d.ts.map +1 -0
  62. package/dist/codes.js +24 -0
  63. package/dist/codes.js.map +1 -0
  64. package/dist/discovery.d.ts +17 -0
  65. package/dist/discovery.d.ts.map +1 -0
  66. package/dist/discovery.js +119 -0
  67. package/dist/discovery.js.map +1 -0
  68. package/dist/fromPgn.d.ts +51 -0
  69. package/dist/fromPgn.d.ts.map +1 -0
  70. package/dist/fromPgn.js +989 -0
  71. package/dist/fromPgn.js.map +1 -0
  72. package/dist/fromPgnStream.d.ts +17 -0
  73. package/dist/fromPgnStream.d.ts.map +1 -0
  74. package/dist/fromPgnStream.js +47 -0
  75. package/dist/fromPgnStream.js.map +1 -0
  76. package/dist/ikonvert.d.ts +17 -0
  77. package/dist/ikonvert.d.ts.map +1 -0
  78. package/dist/ikonvert.js +224 -0
  79. package/dist/ikonvert.js.map +1 -0
  80. package/dist/index.d.ts +31 -0
  81. package/dist/index.d.ts.map +1 -0
  82. package/dist/index.js +60 -0
  83. package/dist/index.js.map +1 -0
  84. package/dist/n2k-actisense.d.ts +24 -0
  85. package/dist/n2k-actisense.d.ts.map +1 -0
  86. package/dist/n2k-actisense.js +126 -0
  87. package/dist/n2k-actisense.js.map +1 -0
  88. package/dist/n2k-actisense.test.d.ts +2 -0
  89. package/dist/n2k-actisense.test.d.ts.map +1 -0
  90. package/dist/n2k-actisense.test.js +49 -0
  91. package/dist/n2k-actisense.test.js.map +1 -0
  92. package/dist/n2kDevice.d.ts +44 -0
  93. package/dist/n2kDevice.d.ts.map +1 -0
  94. package/dist/n2kDevice.js +436 -0
  95. package/dist/n2kDevice.js.map +1 -0
  96. package/dist/pgns.d.ts +22 -0
  97. package/dist/pgns.d.ts.map +1 -0
  98. package/dist/pgns.js +157 -0
  99. package/dist/pgns.js.map +1 -0
  100. package/dist/pgns.test.d.ts +2 -0
  101. package/dist/pgns.test.d.ts.map +1 -0
  102. package/dist/pgns.test.js +14 -0
  103. package/dist/pgns.test.js.map +1 -0
  104. package/dist/simpleCan.d.ts +17 -0
  105. package/dist/simpleCan.d.ts.map +1 -0
  106. package/dist/simpleCan.js +125 -0
  107. package/dist/simpleCan.js.map +1 -0
  108. package/dist/stringMsg.d.ts +33 -0
  109. package/dist/stringMsg.d.ts.map +1 -0
  110. package/dist/stringMsg.js +359 -0
  111. package/dist/stringMsg.js.map +1 -0
  112. package/dist/stringMsg.test.d.ts +2 -0
  113. package/dist/stringMsg.test.d.ts.map +1 -0
  114. package/dist/stringMsg.test.js +244 -0
  115. package/dist/stringMsg.test.js.map +1 -0
  116. package/dist/toPgn.d.ts +34 -0
  117. package/dist/toPgn.d.ts.map +1 -0
  118. package/dist/toPgn.js +500 -0
  119. package/dist/toPgn.js.map +1 -0
  120. package/dist/utilities.d.ts +28 -0
  121. package/dist/utilities.d.ts.map +1 -0
  122. package/dist/utilities.js +159 -0
  123. package/dist/utilities.js.map +1 -0
  124. package/dist/utilities.test.d.ts +2 -0
  125. package/dist/utilities.test.d.ts.map +1 -0
  126. package/dist/utilities.test.js +9 -0
  127. package/dist/utilities.test.js.map +1 -0
  128. package/dist/venus-mqtt.d.ts +11 -0
  129. package/dist/venus-mqtt.d.ts.map +1 -0
  130. package/dist/venus-mqtt.js +100 -0
  131. package/dist/venus-mqtt.js.map +1 -0
  132. package/dist/venus.d.ts +11 -0
  133. package/dist/venus.d.ts.map +1 -0
  134. package/dist/venus.js +71 -0
  135. package/dist/venus.js.map +1 -0
  136. package/dist/w2k01.d.ts +17 -0
  137. package/dist/w2k01.d.ts.map +1 -0
  138. package/dist/w2k01.js +119 -0
  139. package/dist/w2k01.js.map +1 -0
  140. package/dist/yddevice.d.ts +25 -0
  141. package/dist/yddevice.d.ts.map +1 -0
  142. package/dist/yddevice.js +43 -0
  143. package/dist/yddevice.js.map +1 -0
  144. package/dist/ydgw02.d.ts +17 -0
  145. package/dist/ydgw02.d.ts.map +1 -0
  146. package/dist/ydgw02.js +163 -0
  147. package/dist/ydgw02.js.map +1 -0
  148. package/dist/ydvr.d.ts +17 -0
  149. package/dist/ydvr.d.ts.map +1 -0
  150. package/dist/ydvr.js +120 -0
  151. package/dist/ydvr.js.map +1 -0
  152. package/eslint.config.js +58 -0
  153. package/jest.config.js +5 -0
  154. package/lib/actisense-serial.ts +644 -0
  155. package/lib/bin/actisense-file.ts +53 -0
  156. package/lib/bin/actisense-n2k-tcp.ts +50 -0
  157. package/lib/bin/actisense-serialjs.ts +55 -0
  158. package/{bin/analyzerjs → lib/bin/analyzerjs.ts} +16 -15
  159. package/{bin/candumpjs → lib/bin/candumpjs.ts} +19 -20
  160. package/lib/bin/cansend.ts +131 -0
  161. package/lib/bin/ikonvert-serial.ts +44 -0
  162. package/{bin/to-pgn → lib/bin/to-pgn.ts} +23 -17
  163. package/lib/bin/ydvr-file +33 -0
  164. package/lib/canId.test.js +35 -15
  165. package/lib/canId.ts +84 -0
  166. package/lib/canbus.ts +293 -0
  167. package/lib/candevice.ts +41 -0
  168. package/lib/codes.ts +21 -0
  169. package/lib/{discovery.js → discovery.ts} +32 -30
  170. package/lib/fromPgn.ts +1207 -0
  171. package/lib/{fromPgnStream.js → fromPgnStream.ts} +17 -12
  172. package/lib/{ikonvert.js → ikonvert.ts} +99 -94
  173. package/lib/index.ts +48 -0
  174. package/lib/n2k-actisense.test.js +31 -32
  175. package/lib/n2k-actisense.ts +152 -0
  176. package/lib/n2kDevice.ts +516 -0
  177. package/lib/pgns.test.ts +12 -0
  178. package/lib/pgns.ts +191 -0
  179. package/lib/simpleCan.ts +140 -0
  180. package/lib/stringMsg.test.js +58 -41
  181. package/lib/stringMsg.ts +464 -0
  182. package/lib/toPgn.ts +597 -0
  183. package/lib/utilities.ts +169 -0
  184. package/lib/venus-mqtt.js +69 -73
  185. package/lib/venus.js +8 -8
  186. package/lib/w2k01.ts +142 -0
  187. package/lib/{yddevice.js → yddevice.ts} +18 -16
  188. package/lib/{ydgw02.js → ydgw02.ts} +58 -51
  189. package/lib/ydvr.js +65 -147
  190. package/package.json +54 -18
  191. package/tsconfig.json +19 -0
  192. package/tsconfig.tsbuildinfo +1 -0
  193. package/CHANGELOG.md +0 -101
  194. package/bin/actisense-file +0 -47
  195. package/bin/actisense-n2k-tcp +0 -45
  196. package/bin/actisense-serialjs +0 -52
  197. package/bin/candumpanalyzerjs +0 -29
  198. package/bin/cansend +0 -130
  199. package/bin/ikonvert-serial +0 -50
  200. package/bin/ydgw-analyzerjs +0 -36
  201. package/bin/ydvr-file +0 -33
  202. package/index.js +0 -53
  203. package/ios_canboat.js/main.js +0 -2
  204. package/ios_canboat.js/main.js.LICENSE.txt +0 -17
  205. package/ios_canboat.js/main.js.map +0 -1
  206. package/lib/canId.js +0 -64
  207. package/lib/canbus.js +0 -278
  208. package/lib/candevice.js +0 -51
  209. package/lib/codes.js +0 -69
  210. package/lib/codes.test.js +0 -17
  211. package/lib/codesMfgs.json +0 -166
  212. package/lib/fromPgn.js +0 -1027
  213. package/lib/n2k-actisense.js +0 -108
  214. package/lib/n2kDevice.js +0 -390
  215. package/lib/pgns.js +0 -196
  216. package/lib/pgns.test.js +0 -13
  217. package/lib/serial.js +0 -647
  218. package/lib/simpleCan.js +0 -105
  219. package/lib/stringMsg.js +0 -339
  220. package/lib/toPgn.js +0 -518
  221. package/lib/utilities.js +0 -111
  222. package/lib/w2k01.js +0 -129
@@ -0,0 +1,464 @@
1
+ import {
2
+ compact,
3
+ cond,
4
+ isEmpty,
5
+ isString,
6
+ negate,
7
+ overSome,
8
+ startsWith,
9
+ stubTrue,
10
+ toNumber,
11
+ zipObject
12
+ } from 'lodash/fp'
13
+ import {
14
+ arrBuff,
15
+ byteString,
16
+ getPlainPGNs,
17
+ rmChecksum,
18
+ trimWrap,
19
+ compute0183Checksum,
20
+ hexByte
21
+ } from './utilities'
22
+ import { buildCanId, encodeCanIdString, parseCanIdStr } from './canId'
23
+ import moment from 'moment'
24
+
25
+ /**
26
+ * Helper function that helps merge canId fields with format, data, and others.
27
+ * The idea here is to reflect what was in the source and not remove or add.
28
+ * If the source has a len or timestamp attribute it should be added but not created.
29
+ * @param {Object} canIdInfo The result of parseCanId, parseCanIdStr, or buildCanId.
30
+ * @param {string} format String that defines the source format.
31
+ * @param {Buffer} data Buffer array that contains the fields data.
32
+ * @param {Object} [rest={}] Anything else to be added like len, timestamp, direction.
33
+ * @return {Object} All canId fields with format and data props added.
34
+ */
35
+ function buildMsg(
36
+ _canIdInfo: any,
37
+ format: string,
38
+ data: Buffer,
39
+ rest: any = {}
40
+ ) {
41
+ const canIdInfo = Object.assign({}, _canIdInfo, {
42
+ format,
43
+ data
44
+ })
45
+ for (const property in rest) {
46
+ if (canIdInfo[property] === undefined) {
47
+ canIdInfo[property] = rest[property]
48
+ }
49
+ }
50
+ return canIdInfo
51
+ }
52
+ function buildErrMsg(msg: string, input: string | undefined) {
53
+ if (input !== undefined && input.length > 0) return `${msg} - ${input}`
54
+ return msg
55
+ }
56
+ const buildErr = (
57
+ format: string,
58
+ msg: string,
59
+ input: string | undefined = undefined
60
+ ) => {
61
+ return {
62
+ error: new Error(buildErrMsg(msg, input)),
63
+ format,
64
+ input
65
+ }
66
+ }
67
+
68
+ function toPaddedHexString(num: number, len: number) {
69
+ const str = num.toString(16).toUpperCase()
70
+ return '0'.repeat(len - str.length) + str
71
+ }
72
+
73
+ // 2016-02-28T19:57:02.364Z,2,127250,7,255,8,ff,10,3b,ff,7f,ce,f5,fc
74
+ export const isActisense = (input: string) =>
75
+ (input.charAt(10) === 'T' && input.charAt(23) === 'Z') ||
76
+ (input.charAt(10) === '-' && input.charAt(23) === ',')
77
+
78
+ export const parseActisense = (input: string) => {
79
+ const [timestamp, prio, pgn, src, dst, len, ...data] = input.split(',')
80
+ return buildMsg(
81
+ buildCanId(prio, pgn, dst, src),
82
+ 'Actisense',
83
+ Buffer.from(data.join(''), 'hex'),
84
+ { len: Number(len), timestamp }
85
+ )
86
+ }
87
+ export const encodeActisense = ({
88
+ pgn,
89
+ data,
90
+ timestamp,
91
+ prio = 2,
92
+ dst = 255,
93
+ src = 0
94
+ }: any) =>
95
+ [
96
+ timestamp || new Date().toISOString(),
97
+ prio,
98
+ pgn,
99
+ src,
100
+ dst,
101
+ data.length,
102
+ byteString(data)
103
+ ].join(',')
104
+
105
+ export const toActisenseSerialFormat = (
106
+ pgn: any,
107
+ data: any,
108
+ dst = 255,
109
+ src = 0,
110
+ prio = 2
111
+ ) =>
112
+ exports.encodeActisense({
113
+ pgn,
114
+ data,
115
+ dst,
116
+ src,
117
+ prio
118
+ })
119
+
120
+ // A764027.880 05FF7 1EF00 E59861060202FFFFFFFF03030000FFFFFFFFFFFFFFFFFFFF0000FFFFFF7FFFFFFF7FFFFFFF7F0000FF7F
121
+ export const isActisenseN2KASCII = (input: string) =>
122
+ input.charAt(0) === 'A' && input.charAt(7) === '.' && input.charAt(11) === ' '
123
+ export const parseActisenseN2KASCII = (input: string) => {
124
+ const [timestamp, srcdstp, pgn, data] = input.split(' ')
125
+ const src = parseInt(srcdstp.substring(0, 2), 16)
126
+ const dst = parseInt(srcdstp.substring(2, 4), 16)
127
+ const prio = parseInt(srcdstp.substring(4))
128
+ return buildMsg(
129
+ buildCanId(prio, parseInt(pgn, 16), dst, src),
130
+ 'Actisense N2K ASCII',
131
+ Buffer.from(data, 'hex'),
132
+ { len: data.length, time: timestamp.substring(1) }
133
+ )
134
+ }
135
+ export const encodeActisenseN2KACSII = ({
136
+ pgn,
137
+ data,
138
+ timestamp,
139
+ prio = 2,
140
+ dst = 255,
141
+ src = 0
142
+ }: any) => {
143
+ timestamp = 'A000000.000'
144
+
145
+ const srcdstp = hexByte(src) + hexByte(dst) + prio
146
+ return [
147
+ timestamp,
148
+ srcdstp.toUpperCase(),
149
+ toPaddedHexString(pgn, 5).toUpperCase(),
150
+ byteString(data, '').toUpperCase()
151
+ ].join(' ')
152
+ }
153
+
154
+ // 16:29:27.082 R 09F8017F 50 C3 B8 13 47 D8 2B C6
155
+ export const isYDRAW = (input: string) => {
156
+ if (input.charAt(2) !== ':') return false
157
+ const direction = input.substr(12, 3)
158
+ return direction === ' R ' || direction === ' T '
159
+ }
160
+ export const parseYDRAW = (input: string) => {
161
+ const parts = input.split(' ')
162
+ if (parts.length < 4) return buildErr('YDRAW', 'Invalid parts.', input)
163
+ const [time, direction, canId, ...data] = parts // time format HH:mm:ss.SSS
164
+ return buildMsg(parseCanIdStr(canId), 'YDRAW', arrBuff(data), {
165
+ direction,
166
+ time
167
+ })
168
+ }
169
+ //19F51323 01 02<CR><LF>
170
+ export const encodeYDRAW = ({ data, ...canIdInfo }: any) => {
171
+ const canId = encodeCanIdString(canIdInfo)
172
+ const pgns =
173
+ data.length > 8 || canIdInfo.pgn == 126720 ? getPlainPGNs(data) : [data]
174
+ return pgns.map((buffer) => canId + ' ' + byteString(buffer, ' '))
175
+ }
176
+
177
+ //16:29:27.082 R 19F51323 01 02<CR><LF>
178
+ export const encodeYDRAWFull = ({ data, ...canIdInfo }: any) => {
179
+ const canId = encodeCanIdString(canIdInfo)
180
+ const pgns =
181
+ data.length > 8 || canIdInfo.pgn == 126720 ? getPlainPGNs(data) : [data]
182
+ return pgns.map(
183
+ (buffer) =>
184
+ moment().utc().format('hh:mm:ss.SSS') +
185
+ ' R ' +
186
+ canId +
187
+ ' ' +
188
+ byteString(buffer, ' ')
189
+ )
190
+ }
191
+
192
+ const get0183Sentence = (msg: string) => {
193
+ let sentence = msg
194
+ if (sentence.charAt(0) === '\\') {
195
+ const split = sentence.split('\\')
196
+ if (split.length < 3) {
197
+ return undefined
198
+ }
199
+ sentence = split[2]
200
+ }
201
+ return sentence
202
+ }
203
+
204
+ // $PCDIN,01F119,00000000,0F,2AAF00D1067414FF*59
205
+ export const isPCDIN = (msg: string) => {
206
+ const sentence = get0183Sentence(msg)
207
+ return sentence ? sentence.startsWith('$PCDIN,') : false
208
+ }
209
+ export const parsePCDIN = (input: string) => {
210
+ const sentence = get0183Sentence(input)
211
+ if (sentence) {
212
+ const [prefix, pgn, timeHex, src, data] = sentence.split(',')
213
+ let timer = parseInt(timeHex, 32)
214
+
215
+ timer = timer / 1024
216
+ timer = timer + 1262304000 // starts epoch time from 1/1/2010
217
+ timer = timer * 1000
218
+
219
+ return buildMsg(
220
+ buildCanId(0, parseInt(pgn, 16), 255, parseInt(src, 16)),
221
+ 'PCDIN',
222
+ Buffer.from(rmChecksum(data), 'hex'),
223
+ { coalesced: true, prefix, timer, timestamp: new Date(timer) }
224
+ )
225
+ }
226
+ }
227
+
228
+ export const encodePCDIN = ({
229
+ prefix = '$PCDIN',
230
+ pgn,
231
+ data,
232
+ dst = 255
233
+ }: any) => {
234
+ const sentence = [
235
+ prefix,
236
+ toPaddedHexString(pgn, 6),
237
+ '0000180C',
238
+ hexByte(dst).toUpperCase(),
239
+ byteString(data, '').toUpperCase()
240
+ ].join(',')
241
+ return sentence + compute0183Checksum(sentence)
242
+ }
243
+
244
+ const changeEndianness = (string: string) => {
245
+ const result = []
246
+ let len = string.length - 2
247
+ while (len >= 0) {
248
+ result.push(string.substr(len, 2))
249
+ len -= 2
250
+ }
251
+ return result.join('')
252
+ }
253
+
254
+ // $MXPGN,01F801,2801,C1308AC40C5DE343*19
255
+ export const isMXPGN = (msg: string) => {
256
+ const sentence = get0183Sentence(msg)
257
+ return sentence ? sentence.startsWith('$MXPGN,') : false
258
+ }
259
+ export const parseMXPGN = (
260
+ input: string,
261
+ options: any | undefined = undefined
262
+ ) => {
263
+ const sentence = get0183Sentence(input)
264
+ if (sentence) {
265
+ const [prefix, pgn, attr_word, data] = sentence.split(',')
266
+
267
+ const send_prio_len = parseInt(attr_word.substr(0, 2), 16)
268
+ .toString(2)
269
+ .padStart(8, '0')
270
+ const addr = parseInt(attr_word.substr(2, 2), 16)
271
+ const send = parseInt(send_prio_len.substr(0, 1), 2)
272
+ const prio = parseInt(send_prio_len.substr(1, 3), 2)
273
+ //const len = parseInt(send_prio_len.substr(4,4), 2);
274
+ let src = 0,
275
+ dst = 255
276
+
277
+ send ? (dst = addr) : (src = addr)
278
+
279
+ let reversed
280
+
281
+ if (options && options.littleEndianMXPGN)
282
+ reversed = changeEndianness(rmChecksum(data))
283
+ else reversed = data
284
+
285
+ return buildMsg(
286
+ buildCanId(prio, parseInt(pgn, 16), dst, src),
287
+ 'MXPGN',
288
+ Buffer.from(reversed, 'hex'),
289
+ { coalesced: true, prefix }
290
+ )
291
+ }
292
+ }
293
+
294
+ export const encodeMXPGN = ({
295
+ prefix = '$MXPGN',
296
+ pgn,
297
+ prio,
298
+ src,
299
+ data
300
+ }: any) => {
301
+ if (src > 255) src = 255
302
+ if (!prio) prio = 3
303
+ if (!src) src = 255
304
+ const dataLength = hexByte(
305
+ 128 + prio * 16 + byteString(data, '').toUpperCase().length / 2
306
+ ).toUpperCase()
307
+ const attribWord = dataLength + hexByte(src).toUpperCase()
308
+
309
+ const buff = Buffer.from(byteString(data, ''), 'hex')
310
+ for (let i = 0, j = buff.length - 1; i < j; ++i, --j) {
311
+ const t = buff[j]
312
+
313
+ buff[j] = buff[i]
314
+ buff[i] = t
315
+ }
316
+
317
+ const sentence = [
318
+ prefix,
319
+ toPaddedHexString(pgn, 6),
320
+ attribWord,
321
+ buff.toString('hex').toUpperCase()
322
+ ].join(',')
323
+ return sentence + compute0183Checksum(sentence)
324
+ }
325
+
326
+ // iKonvert
327
+ // !PDGY,126992,3,2,255,0.563,d2009e45b3b8821d
328
+ export const isPDGY = startsWith('!PDGY,')
329
+ export const parsePDGY = (input: string) => {
330
+ const parts = input.split(',')
331
+ if (parts.length === 7) {
332
+ const [prefix, pgn, prio, src, dst, timer, data] = parts
333
+ return buildMsg(
334
+ buildCanId(prio, pgn, dst, src),
335
+ 'PDGY',
336
+ Buffer.from(data, 'base64'),
337
+ { timer: Number(timer), prefix, coalesced: true }
338
+ )
339
+ } else if (parts.length === 4) {
340
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
341
+ const [prefix, pgn, dst, data] = parts
342
+ return buildMsg(
343
+ buildCanId(0, pgn, dst, 0),
344
+ 'PDGY',
345
+ Buffer.from(data, 'base64'),
346
+ { coalesced: true }
347
+ )
348
+ } else {
349
+ return buildErr('iKonvert', 'Invalid parts.', input)
350
+ }
351
+ }
352
+ export const encodePDGY = ({ prefix = '!PDGY', pgn, data, dst = 255 }: any) =>
353
+ [prefix, pgn, dst, data.toString('base64')].join(',')
354
+
355
+ export const isPDGYdebug = startsWith('$PDGY,')
356
+ export const parsePDGYdebug = (input: string) => {
357
+ const [prefix, pgn, ...fieldParts] = input.split(',')
358
+ const fieldVals = fieldParts.map(toNumber)
359
+ const fields = zipObject(
360
+ ['busLoad', 'errors', 'deviceCount', 'timer', 'gatewaySrc', 'rejectedTX'],
361
+ fieldVals
362
+ )
363
+ const src = fields.gatewaySrc
364
+ return buildMsg(
365
+ buildCanId(3, pgn, src, src),
366
+ 'PDGYdebug',
367
+ Buffer.from(fieldVals),
368
+ { fields, prefix }
369
+ )
370
+ }
371
+
372
+ // candump1 Angstrom
373
+ // <0x18eeff01> [8] 05 a0 be 1c 00 a0 a0 c0
374
+ export const isCandump1 = startsWith('<0x')
375
+ export const parseCandump1 = (input: string) => {
376
+ const [canId, len, ...data] = input.split(' ')
377
+ return buildMsg(parseCanIdStr(trimWrap(canId)), 'candump1', arrBuff(data), {
378
+ len: Number(trimWrap(len))
379
+ })
380
+ }
381
+
382
+ // candump2 Debian
383
+ // can0 09F8027F [8] 00 FC FF FF 00 00 FF FF
384
+ export const isCandump2 = startsWith('can')
385
+ export const parseCandump2 = (input: string) => {
386
+ const [bus, canId, len, ...data] = compact(input.split(' '))
387
+ return buildMsg(parseCanIdStr(canId), 'candump2', arrBuff(data), {
388
+ bus,
389
+ len: Number(trimWrap(len))
390
+ })
391
+ }
392
+
393
+ // candump3 log
394
+ // (1502979132.106111) slcan0 09F50374#000A00FFFF00FFFF
395
+ export const isCandump3 = startsWith('(')
396
+ export const parseCandump3 = (input: string) => {
397
+ const [timestamp, bus, canFrame] = input.split(' ')
398
+ const [canId, data] = canFrame.split('#')
399
+ return buildMsg(parseCanIdStr(canId), 'candump3', Buffer.from(data, 'hex'), {
400
+ timestamp,
401
+ bus
402
+ })
403
+ }
404
+
405
+ const hasErr = overSome([negate(isString), isEmpty])
406
+ export const parseN2kString = (str: string, options: any): any => {
407
+ if (hasErr(str)) {
408
+ return buildErr('INVALID', 'Input not string or empty.', str)
409
+ }
410
+ if (isActisense(str)) {
411
+ return parseActisense(str)
412
+ }
413
+ if (isYDRAW(str)) {
414
+ return parseYDRAW(str)
415
+ }
416
+ if (isPCDIN(str)) {
417
+ return parsePCDIN(str)
418
+ }
419
+ if (isMXPGN(str)) {
420
+ return parseMXPGN(str, options)
421
+ }
422
+ if (isPDGY(str)) {
423
+ return parsePDGY(str)
424
+ }
425
+ if (isCandump1(str)) {
426
+ return parseCandump1(str)
427
+ }
428
+ if (isCandump2(str)) {
429
+ return parseCandump2(str)
430
+ }
431
+ if (isCandump3(str)) {
432
+ return parseCandump3(str)
433
+ }
434
+ if (isPDGYdebug(str)) {
435
+ return parsePDGYdebug(str)
436
+ }
437
+ if (isActisenseN2KASCII(str)) {
438
+ return parseActisenseN2KASCII(str)
439
+ }
440
+ return buildErr('MISSING_PARSER', 'Parser not found for input.', str)
441
+ }
442
+
443
+ export const isN2KString = cond([
444
+ [hasErr, () => false],
445
+ [isActisense, () => true],
446
+ [isYDRAW, () => true],
447
+ [isPCDIN, () => true],
448
+ [isMXPGN, () => true],
449
+ [isPDGY, () => true],
450
+ [isCandump1, () => true],
451
+ [isCandump2, () => true],
452
+ [isCandump3, () => true],
453
+ [isPDGYdebug, () => true],
454
+ [isActisenseN2KASCII, () => true],
455
+ [stubTrue, () => false]
456
+ ])
457
+
458
+ export const isN2KOver0183 = (msg: string) => {
459
+ return isPCDIN(msg) || isMXPGN(msg)
460
+ }
461
+
462
+ export const parseN2KOver0183 = (msg: string) => {
463
+ return parsePCDIN(msg) || parseMXPGN(msg)
464
+ }