@canboat/canboatjs 3.0.2 → 3.1.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.
Files changed (222) hide show
  1. package/.github/workflows/test.yml +2 -2
  2. package/.github/workflows/test_canboat_changes.yml +91 -0
  3. package/.husky/pre-commit +4 -0
  4. package/.mocharc.js +7 -0
  5. package/.prettierrc.json +5 -0
  6. package/README.md +2 -7
  7. package/dist/actisense-serial.d.ts +17 -0
  8. package/dist/actisense-serial.d.ts.map +1 -0
  9. package/dist/actisense-serial.js +569 -0
  10. package/dist/actisense-serial.js.map +1 -0
  11. package/dist/bin/actisense-file.d.ts +3 -0
  12. package/dist/bin/actisense-file.d.ts.map +1 -0
  13. package/dist/bin/actisense-file.js +49 -0
  14. package/dist/bin/actisense-file.js.map +1 -0
  15. package/dist/bin/actisense-n2k-tcp.d.ts +3 -0
  16. package/dist/bin/actisense-n2k-tcp.d.ts.map +1 -0
  17. package/dist/bin/actisense-n2k-tcp.js +46 -0
  18. package/dist/bin/actisense-n2k-tcp.js.map +1 -0
  19. package/dist/bin/actisense-serialjs.d.ts +3 -0
  20. package/dist/bin/actisense-serialjs.d.ts.map +1 -0
  21. package/dist/bin/actisense-serialjs.js +51 -0
  22. package/dist/bin/actisense-serialjs.js.map +1 -0
  23. package/dist/bin/analyzerjs.d.ts +3 -0
  24. package/dist/bin/analyzerjs.d.ts.map +1 -0
  25. package/dist/bin/analyzerjs.js +61 -0
  26. package/dist/bin/analyzerjs.js.map +1 -0
  27. package/dist/bin/candumpanalyzerjs.d.ts +3 -0
  28. package/dist/bin/candumpanalyzerjs.d.ts.map +1 -0
  29. package/dist/bin/candumpanalyzerjs.js +31 -0
  30. package/dist/bin/candumpanalyzerjs.js.map +1 -0
  31. package/dist/bin/candumpjs.d.ts +3 -0
  32. package/dist/bin/candumpjs.d.ts.map +1 -0
  33. package/dist/bin/candumpjs.js +73 -0
  34. package/dist/bin/candumpjs.js.map +1 -0
  35. package/dist/bin/cansend.d.ts +3 -0
  36. package/dist/bin/cansend.d.ts.map +1 -0
  37. package/dist/bin/cansend.js +123 -0
  38. package/dist/bin/cansend.js.map +1 -0
  39. package/dist/bin/ikonvert-serial.d.ts +3 -0
  40. package/dist/bin/ikonvert-serial.d.ts.map +1 -0
  41. package/dist/bin/ikonvert-serial.js +36 -0
  42. package/dist/bin/ikonvert-serial.js.map +1 -0
  43. package/dist/bin/to-pgn.d.ts +3 -0
  44. package/dist/bin/to-pgn.d.ts.map +1 -0
  45. package/dist/bin/to-pgn.js +57 -0
  46. package/dist/bin/to-pgn.js.map +1 -0
  47. package/dist/canId.d.ts +21 -0
  48. package/dist/canId.d.ts.map +1 -0
  49. package/dist/canId.js +66 -0
  50. package/dist/canId.js.map +1 -0
  51. package/dist/canId.test.d.ts +2 -0
  52. package/dist/canId.test.d.ts.map +1 -0
  53. package/dist/canId.test.js +58 -0
  54. package/dist/canId.test.js.map +1 -0
  55. package/dist/canbus.d.ts +17 -0
  56. package/dist/canbus.d.ts.map +1 -0
  57. package/dist/canbus.js +261 -0
  58. package/dist/canbus.js.map +1 -0
  59. package/dist/candevice.d.ts +23 -0
  60. package/dist/candevice.d.ts.map +1 -0
  61. package/dist/candevice.js +38 -0
  62. package/dist/candevice.js.map +1 -0
  63. package/dist/codes.d.ts +2 -0
  64. package/dist/codes.d.ts.map +1 -0
  65. package/dist/codes.js +24 -0
  66. package/dist/codes.js.map +1 -0
  67. package/dist/discovery.d.ts +17 -0
  68. package/dist/discovery.d.ts.map +1 -0
  69. package/dist/discovery.js +119 -0
  70. package/dist/discovery.js.map +1 -0
  71. package/dist/fromPgn.d.ts +51 -0
  72. package/dist/fromPgn.d.ts.map +1 -0
  73. package/dist/fromPgn.js +989 -0
  74. package/dist/fromPgn.js.map +1 -0
  75. package/dist/fromPgnStream.d.ts +17 -0
  76. package/dist/fromPgnStream.d.ts.map +1 -0
  77. package/dist/fromPgnStream.js +47 -0
  78. package/dist/fromPgnStream.js.map +1 -0
  79. package/dist/ikonvert.d.ts +17 -0
  80. package/dist/ikonvert.d.ts.map +1 -0
  81. package/dist/ikonvert.js +224 -0
  82. package/dist/ikonvert.js.map +1 -0
  83. package/dist/index.d.ts +31 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +60 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/n2k-actisense.d.ts +24 -0
  88. package/dist/n2k-actisense.d.ts.map +1 -0
  89. package/dist/n2k-actisense.js +126 -0
  90. package/dist/n2k-actisense.js.map +1 -0
  91. package/dist/n2k-actisense.test.d.ts +2 -0
  92. package/dist/n2k-actisense.test.d.ts.map +1 -0
  93. package/dist/n2k-actisense.test.js +49 -0
  94. package/dist/n2k-actisense.test.js.map +1 -0
  95. package/dist/n2kDevice.d.ts +40 -0
  96. package/dist/n2kDevice.d.ts.map +1 -0
  97. package/dist/n2kDevice.js +387 -0
  98. package/dist/n2kDevice.js.map +1 -0
  99. package/dist/ncanbus.d.ts +17 -0
  100. package/dist/ncanbus.d.ts.map +1 -0
  101. package/dist/ncanbus.js +92 -0
  102. package/dist/ncanbus.js.map +1 -0
  103. package/dist/pgns.d.ts +22 -0
  104. package/dist/pgns.d.ts.map +1 -0
  105. package/dist/pgns.js +157 -0
  106. package/dist/pgns.js.map +1 -0
  107. package/dist/pgns.test.d.ts +2 -0
  108. package/dist/pgns.test.d.ts.map +1 -0
  109. package/dist/pgns.test.js +14 -0
  110. package/dist/pgns.test.js.map +1 -0
  111. package/dist/simpleCan.d.ts +17 -0
  112. package/dist/simpleCan.d.ts.map +1 -0
  113. package/dist/simpleCan.js +125 -0
  114. package/dist/simpleCan.js.map +1 -0
  115. package/dist/stringMsg.d.ts +33 -0
  116. package/dist/stringMsg.d.ts.map +1 -0
  117. package/dist/stringMsg.js +359 -0
  118. package/dist/stringMsg.js.map +1 -0
  119. package/dist/stringMsg.test.d.ts +2 -0
  120. package/dist/stringMsg.test.d.ts.map +1 -0
  121. package/dist/stringMsg.test.js +244 -0
  122. package/dist/stringMsg.test.js.map +1 -0
  123. package/dist/toPgn.d.ts +34 -0
  124. package/dist/toPgn.d.ts.map +1 -0
  125. package/dist/toPgn.js +500 -0
  126. package/dist/toPgn.js.map +1 -0
  127. package/dist/utilities.d.ts +26 -0
  128. package/dist/utilities.d.ts.map +1 -0
  129. package/dist/utilities.js +112 -0
  130. package/dist/utilities.js.map +1 -0
  131. package/dist/utilities.test.d.ts +2 -0
  132. package/dist/utilities.test.d.ts.map +1 -0
  133. package/dist/utilities.test.js +9 -0
  134. package/dist/utilities.test.js.map +1 -0
  135. package/dist/venus-mqtt.d.ts +11 -0
  136. package/dist/venus-mqtt.d.ts.map +1 -0
  137. package/dist/venus-mqtt.js +100 -0
  138. package/dist/venus-mqtt.js.map +1 -0
  139. package/dist/venus.d.ts +11 -0
  140. package/dist/venus.d.ts.map +1 -0
  141. package/dist/venus.js +71 -0
  142. package/dist/venus.js.map +1 -0
  143. package/dist/w2k01.d.ts +17 -0
  144. package/dist/w2k01.d.ts.map +1 -0
  145. package/dist/w2k01.js +119 -0
  146. package/dist/w2k01.js.map +1 -0
  147. package/dist/yddevice.d.ts +25 -0
  148. package/dist/yddevice.d.ts.map +1 -0
  149. package/dist/yddevice.js +45 -0
  150. package/dist/yddevice.js.map +1 -0
  151. package/dist/ydgw02.d.ts +17 -0
  152. package/dist/ydgw02.d.ts.map +1 -0
  153. package/dist/ydgw02.js +163 -0
  154. package/dist/ydgw02.js.map +1 -0
  155. package/dist/ydvr.d.ts +17 -0
  156. package/dist/ydvr.d.ts.map +1 -0
  157. package/dist/ydvr.js +120 -0
  158. package/dist/ydvr.js.map +1 -0
  159. package/eslint.config.js +58 -0
  160. package/jest.config.js +5 -0
  161. package/lib/actisense-serial.ts +644 -0
  162. package/lib/bin/actisense-file.ts +53 -0
  163. package/lib/bin/actisense-n2k-tcp.ts +50 -0
  164. package/lib/bin/actisense-serialjs.ts +55 -0
  165. package/{bin/analyzerjs → lib/bin/analyzerjs.ts} +16 -15
  166. package/{bin/candumpjs → lib/bin/candumpjs.ts} +19 -20
  167. package/lib/bin/cansend.ts +131 -0
  168. package/lib/bin/ikonvert-serial.ts +44 -0
  169. package/{bin/to-pgn → lib/bin/to-pgn.ts} +23 -17
  170. package/lib/bin/ydvr-file +33 -0
  171. package/lib/canId.test.js +35 -15
  172. package/lib/canId.ts +84 -0
  173. package/lib/canbus.ts +293 -0
  174. package/lib/{candevice.js → candevice.ts} +14 -21
  175. package/lib/codes.ts +21 -0
  176. package/lib/{discovery.js → discovery.ts} +32 -30
  177. package/lib/fromPgn.ts +1207 -0
  178. package/lib/{fromPgnStream.js → fromPgnStream.ts} +17 -12
  179. package/lib/{ikonvert.js → ikonvert.ts} +90 -85
  180. package/lib/index.ts +48 -0
  181. package/lib/n2k-actisense.test.js +31 -32
  182. package/lib/n2k-actisense.ts +152 -0
  183. package/lib/n2kDevice.ts +458 -0
  184. package/lib/pgns.test.ts +12 -0
  185. package/lib/pgns.ts +191 -0
  186. package/lib/simpleCan.ts +140 -0
  187. package/lib/stringMsg.test.js +58 -41
  188. package/lib/stringMsg.ts +464 -0
  189. package/lib/toPgn.ts +597 -0
  190. package/lib/{utilities.js → utilities.ts} +48 -37
  191. package/lib/venus-mqtt.js +69 -73
  192. package/lib/venus.js +8 -8
  193. package/lib/{w2k01.js → w2k01.ts} +57 -44
  194. package/lib/{yddevice.js → yddevice.ts} +18 -13
  195. package/lib/{ydgw02.js → ydgw02.ts} +55 -47
  196. package/lib/ydvr.js +65 -147
  197. package/package.json +54 -18
  198. package/tsconfig.json +19 -0
  199. package/tsconfig.tsbuildinfo +1 -0
  200. package/bin/actisense-file +0 -47
  201. package/bin/actisense-n2k-tcp +0 -45
  202. package/bin/actisense-serialjs +0 -52
  203. package/bin/candumpanalyzerjs +0 -29
  204. package/bin/cansend +0 -130
  205. package/bin/ikonvert-serial +0 -50
  206. package/bin/ydgw-analyzerjs +0 -36
  207. package/bin/ydvr-file +0 -33
  208. package/index.js +0 -53
  209. package/lib/canId.js +0 -64
  210. package/lib/canbus.js +0 -278
  211. package/lib/codes.js +0 -69
  212. package/lib/codes.test.js +0 -17
  213. package/lib/codesMfgs.json +0 -166
  214. package/lib/fromPgn.js +0 -1027
  215. package/lib/n2k-actisense.js +0 -108
  216. package/lib/n2kDevice.js +0 -390
  217. package/lib/pgns.js +0 -196
  218. package/lib/pgns.test.js +0 -13
  219. package/lib/serial.js +0 -647
  220. package/lib/simpleCan.js +0 -105
  221. package/lib/stringMsg.js +0 -339
  222. package/lib/toPgn.js +0 -518
package/lib/simpleCan.js DELETED
@@ -1,105 +0,0 @@
1
- const CanDevice = require('./candevice')
2
- const debug = require('debug')('canboatjs:simpleCan')
3
- const { encodeCanId, parseCanId } = require('./canId')
4
- const { toActisenseSerialFormat, parseActisense } = require('./stringMsg')
5
- const { toPgn } = require('./toPgn')
6
- const { getPlainPGNs, binToActisense } = require('./utilities')
7
- const _ = require('lodash')
8
-
9
- function SimpleCan (options, messageCb) {
10
- this.options = options
11
- this.messageCb = messageCb
12
- this.plainText = false
13
- this.socketcan = require('socketcan')
14
- }
15
-
16
- SimpleCan.prototype.start = function () {
17
- const canDevice = this.options.canDevice || 'can0'
18
-
19
- this.channel = this.socketcan.createRawChannel(canDevice);
20
- if ( this.messageCb ) {
21
- this.channel.addListener('onMessage', (msg) => {
22
- var pgn = parseCanId(msg.id)
23
-
24
- if ( this.candevice && this.candevice.cansend && pgn.src == this.candevice.address ) {
25
- return
26
- }
27
-
28
- pgn.timestamp = new Date().toISOString()
29
- if ( this.plainText ) {
30
- this.messageCb(binToActisense(pgn, msg.data, msg.data.length))
31
- } else {
32
- this.messageCb({ pgn, length: msg.data.length, data: msg.data })
33
- }
34
- })
35
- }
36
- this.channel.start()
37
- this.candevice = new CanDevice(this,
38
- {...this.options,
39
- disableDefaultTransmitPGNs: true,
40
- disableNAKs: true
41
- },
42
- )
43
- this.candevice.start()
44
- }
45
-
46
- SimpleCan.prototype.sendPGN = function (msg) {
47
- if ( this.candevice ) {
48
- if ( !this.candevice.cansend && msg.pgn !== 59904 && msg.pgn !== 60928 && msg.pgn !== 126996 ) {
49
- debug('ignoring %j', msg)
50
- return
51
- }
52
-
53
- debug('sending %j', msg)
54
-
55
- let src = msg.pgn === 59904 || msg.forceSrc ? msg.src : this.candevice.address
56
- if ( _.isString(msg) ) {
57
- var split = msg.split(',')
58
- split[3] = src
59
- msg = split.join(',')
60
- } else {
61
- msg.src = src
62
- if ( _.isUndefined(msg.prio) ) {
63
- msg.prio = 3
64
- }
65
- if ( _.isUndefined(msg.dst) ) {
66
- msg.dst = 255
67
- }
68
- }
69
-
70
- var canid
71
- var buffer
72
-
73
- var pgn
74
- if ( _.isObject(msg) ) {
75
- canid = encodeCanId(msg)
76
- buffer = toPgn(msg)
77
- pgn = msg
78
- } else {
79
- pgn = parseActisense(msg)
80
- canid = encodeCanId(pgn)
81
- buffer = pgn.data
82
- }
83
-
84
- if ( debug.enabled ) {
85
- var str = toActisenseSerialFormat(pgn.pgn, buffer, pgn.dst, pgn.src)
86
- debug(str)
87
- }
88
-
89
- //seems as though 126720 should always be encoded this way
90
- if ( buffer.length > 8 || pgn.pgn == 126720 ) {
91
- var pgns = getPlainPGNs(buffer)
92
- pgns.forEach(pbuffer => {
93
- this.channel.send({id: canid, ext:true, data: pbuffer})
94
- })
95
- } else {
96
- this.channel.send({id: canid, ext:true, data: buffer})
97
- }
98
- }
99
- }
100
-
101
- SimpleCan.prototype.sendActisenseFormat = function (msg) {
102
- this.sendPGN(msg)
103
- }
104
-
105
- module.exports = SimpleCan
package/lib/stringMsg.js DELETED
@@ -1,339 +0,0 @@
1
- const {
2
- compact, cond, constant, curry, flow, isEmpty,
3
- isString, negate, overSome, startsWith, stubTrue, toNumber, zipObject
4
- } = require('lodash/fp')
5
- const {
6
- arrBuff, byteString, getPlainPGNs, rmChecksum, trimWrap, compute0183Checksum, hexByte
7
- } = require('./utilities')
8
- const {
9
- buildCanId, encodeCanIdString, parseCanId, parseCanIdStr,
10
- } = require('./canId')
11
- const moment = require('moment')
12
-
13
- /**
14
- * Helper function that helps merge canId fields with format, data, and others.
15
- * The idea here is to reflect what was in the source and not remove or add.
16
- * If the source has a len or timestamp attribute it should be added but not created.
17
- * @param {Object} canIdInfo The result of parseCanId, parseCanIdStr, or buildCanId.
18
- * @param {string} format String that defines the source format.
19
- * @param {Buffer} data Buffer array that contains the fields data.
20
- * @param {Object} [rest={}] Anything else to be added like len, timestamp, direction.
21
- * @return {Object} All canId fields with format and data props added.
22
- */
23
- function buildMsg(_canIdInfo, format, data, rest = {}) {
24
- const canIdInfo = Object.assign({}, _canIdInfo, {
25
- format,
26
- data
27
- })
28
- for (const property in rest) {
29
- if (canIdInfo[property] === undefined) {
30
- canIdInfo[property] = rest[property]
31
- }
32
- }
33
- return canIdInfo
34
- }
35
- function buildErrMsg(msg, input) {
36
- if (input && isString(input)) return `${msg} - ${input}`
37
- return msg
38
- }
39
- const buildErr = curry((format, msg, input) => ({
40
- error: new Error(buildErrMsg(msg, input)), format, input,
41
- }))
42
-
43
- function toPaddedHexString(num, len) {
44
- str = num.toString(16).toUpperCase();
45
- return "0".repeat(len - str.length) + str;
46
- }
47
-
48
- // 2016-02-28T19:57:02.364Z,2,127250,7,255,8,ff,10,3b,ff,7f,ce,f5,fc
49
- exports.isActisense = input => (input.charAt(10) === 'T' && input.charAt(23) === 'Z') || (input.charAt(10) === '-' && input.charAt(23) === ',')
50
-
51
- exports.parseActisense = (input) => {
52
- const [ timestamp, prio, pgn, src, dst, len, ...data ] = input.split(',')
53
- return buildMsg(
54
- buildCanId(prio, pgn, dst, src),
55
- 'Actisense',
56
- Buffer.from(data.join(''), 'hex'),
57
- { len: Number(len), timestamp },
58
- )
59
- }
60
- exports.encodeActisense = ({
61
- pgn, data, timestamp, prio = 2, dst = 255, src = 0 }) => ([
62
- timestamp || new Date().toISOString(),
63
- prio, pgn, src, dst, data.length,
64
- byteString(data)
65
- ].join(','))
66
-
67
- exports.toActisenseSerialFormat = (pgn, data, dst=255, src=0, prio=2) => exports.encodeActisense({
68
- pgn, data, dst, src, prio
69
- })
70
-
71
- // A764027.880 05FF7 1EF00 E59861060202FFFFFFFF03030000FFFFFFFFFFFFFFFFFFFF0000FFFFFF7FFFFFFF7FFFFFFF7F0000FF7F
72
- exports.isActisenseN2KASCII = input => input.charAt(0) === 'A' && input.charAt(7) === '.' && input.charAt(11) === ' '
73
- exports.parseActisenseN2KASCII = (input) => {
74
- const [ timestamp, srcdstp, pgn, data ] = input.split(' ')
75
- const src = parseInt(srcdstp.substring(0, 2), 16)
76
- const dst = parseInt(srcdstp.substring(2,4), 16)
77
- const prio = parseInt(srcdstp.substring(4))
78
- return buildMsg(
79
- buildCanId(prio, parseInt(pgn, 16), dst, src),
80
- 'Actisense N2K ASCII',
81
- Buffer.from(data, 'hex'),
82
- { len: data.length, time: timestamp.substring(1) },
83
- )
84
- }
85
- exports.encodeActisenseN2KACSII = ({
86
- pgn, data, timestamp, prio = 2, dst = 255, src = 0 }) => {
87
- timestamp = 'A000000.000'
88
-
89
- const srcdstp = hexByte(src) + hexByte(dst) + prio
90
- return ([
91
- timestamp,
92
- srcdstp.toUpperCase(),
93
- toPaddedHexString(pgn, 5).toUpperCase(),
94
- byteString(data, '').toUpperCase()
95
- ].join(' '))
96
- }
97
-
98
-
99
- // 16:29:27.082 R 09F8017F 50 C3 B8 13 47 D8 2B C6
100
- exports.isYDRAW = (input) => {
101
- if (input.charAt(2) !== ':') return false
102
- const direction = input.substr(12, 3)
103
- return direction === ' R ' || direction === ' T '
104
- }
105
- exports.parseYDRAW = (input) => {
106
- const parts = input.split(' ')
107
- if ( parts.length < 4 ) return buildErr('YDRAW', 'Invalid parts.', input)
108
- const [ time, direction, canId, ...data ] = parts // time format HH:mm:ss.SSS
109
- return buildMsg(
110
- parseCanIdStr(canId), 'YDRAW', arrBuff(data),
111
- { direction, time }
112
- )
113
- }
114
- //19F51323 01 02<CR><LF>
115
- exports.encodeYDRAW = ({ data, ...canIdInfo }) => {
116
- const canId = encodeCanIdString(canIdInfo)
117
- const pgns = data.length > 8 || canIdInfo.pgn == 126720 ? getPlainPGNs(data) : [ data ]
118
- return pgns.map(buffer => canId + ' ' + byteString(buffer, ' '))
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
-
132
- const get0183Sentence = (msg) => {
133
- let sentence = msg
134
- if (sentence.charAt(0) === '\\') {
135
- split = sentence.split('\\')
136
- if ( split.length < 3 ) {
137
- return false
138
- }
139
- sentence = split[2]
140
- }
141
- return sentence
142
- }
143
-
144
- // $PCDIN,01F119,00000000,0F,2AAF00D1067414FF*59
145
- exports.isPCDIN = (msg) => {
146
- const sentence = get0183Sentence(msg)
147
- return sentence.startsWith('$PCDIN,')
148
- }
149
- exports.parsePCDIN = (input) => {
150
- const sentence = get0183Sentence(input)
151
- const [ prefix, pgn, timeHex, src, data ] = sentence.split(',')
152
- let timer = parseInt(timeHex, 32)
153
-
154
- timer = timer / 1024
155
- timer = timer + 1262304000 // starts epoch time from 1/1/2010
156
- timer = timer * 1000
157
-
158
- return buildMsg(
159
- buildCanId(0, parseInt(pgn, 16), 255, parseInt(src, 16)),
160
- 'PCDIN',
161
- Buffer.from(rmChecksum(data), 'hex'),
162
- { coalesced: true, prefix, timer, timestamp: new Date(timer) },
163
- )
164
- }
165
-
166
- exports.encodePCDIN = ({ prefix = '$PCDIN', pgn, data, dst = 255}) => {
167
- const sentence = [ prefix, toPaddedHexString(pgn, 6), '0000180C', hexByte(dst).toUpperCase(), byteString(data, '').toUpperCase()].join(',')
168
- return sentence + compute0183Checksum(sentence)
169
- }
170
-
171
- const changeEndianness = (string) => {
172
- const result = [];
173
- let len = string.length - 2;
174
- while (len >= 0) {
175
- result.push(string.substr(len, 2));
176
- len -= 2;
177
- }
178
- return result.join('');
179
- }
180
-
181
- // $MXPGN,01F801,2801,C1308AC40C5DE343*19
182
- exports.isMXPGN = (msg) => {
183
- const sentence = get0183Sentence(msg)
184
- return sentence.startsWith('$MXPGN,')
185
- }
186
- exports.parseMXPGN = (input, options) => {
187
- const sentence = get0183Sentence(input)
188
- const [ prefix, pgn, attr_word, data ] = sentence.split(',')
189
-
190
- const send_prio_len = (parseInt(attr_word.substr(0,2), 16).toString(2)).padStart(8, '0');
191
- const addr = (parseInt(attr_word.substr(2,2), 16));
192
- const send = parseInt(send_prio_len.substr(0,1), 2);
193
- const prio = parseInt(send_prio_len.substr(1,3), 2);
194
- const len = parseInt(send_prio_len.substr(4,4), 2);
195
- let src, dst;
196
- send ? dst = addr: src = addr;
197
-
198
- let reversed
199
-
200
- if ( options && options.littleEndianMXPGN )
201
- reversed = changeEndianness(rmChecksum(data))
202
- else
203
- reversed = data
204
-
205
- return buildMsg(
206
- buildCanId(0, parseInt(pgn, 16), 255, parseInt(src, 16)),
207
- 'MXPGN',
208
- Buffer.from(reversed, 'hex'),
209
- { coalesced: true, prefix },
210
- )
211
- }
212
-
213
- exports.encodeMXPGN = ({ prefix = '$MXPGN', pgn, prio, src, data }) => {
214
- if (src > 255) src = 255;
215
- if (!prio) prio = 3;
216
- if (!src) src = 255;
217
- const dataLength = hexByte(128 + (prio * 16) + (byteString(data, '').toUpperCase().length / 2)).toUpperCase()
218
- const attribWord = dataLength + hexByte(src).toUpperCase()
219
-
220
- var buff = Buffer.from(byteString(data, ''), 'Hex');
221
- for (var i = 0, j = buff.length - 1; i < j; ++i, --j) {
222
- var t = buff[j]
223
-
224
- buff[j] = buff[i]
225
- buff[i] = t
226
- }
227
-
228
- const sentence = [prefix, toPaddedHexString(pgn, 6), attribWord, buff.toString('Hex').toUpperCase()].join(',')
229
- return sentence + compute0183Checksum(sentence)
230
- }
231
-
232
- // iKonvert
233
- // !PDGY,126992,3,2,255,0.563,d2009e45b3b8821d
234
- exports.isPDGY = startsWith('!PDGY,')
235
- exports.parsePDGY = (input) => {
236
- const parts = input.split(',')
237
- if ( parts.length === 7 ) {
238
- const [ prefix, pgn, prio, src, dst, timer, data ] = parts
239
- return buildMsg(
240
- buildCanId(prio, pgn, dst, src), 'PDGY', Buffer.from(data, 'base64'),
241
- { timer: Number(timer), prefix, coalesced: true },
242
- )
243
- } else if ( parts.length === 4 ) {
244
- const [ prefix, pgn, dst, data ] = parts
245
- return buildMsg(
246
- buildCanId(0, pgn, dst, 0), 'PDGY', Buffer.from(data, 'base64'),
247
- { coalesced: true }
248
- )
249
- } else {
250
- return buildErr('iKonvert', 'Invalid parts.', input)
251
- }
252
- }
253
- exports.encodePDGY = ({ prefix = '!PDGY', pgn, data, dst = 255}) => (
254
- [ prefix, pgn, dst, data.toString('base64')].join(',')
255
- )
256
-
257
- exports.isPDGYdebug = startsWith('$PDGY,')
258
- exports.parsePDGYdebug = (input) => {
259
- const [ prefix, pgn, ...fieldParts ] = input.split(',')
260
- const fieldVals = fieldParts.map(toNumber)
261
- const fields = zipObject([
262
- 'busLoad', 'errors', 'deviceCount', 'timer', 'gatewaySrc', 'rejectedTX',
263
- ], fieldVals)
264
- const src = fields.gatewaySrc
265
- return buildMsg(
266
- buildCanId(3, pgn, src, src), 'PDGYdebug', Buffer.from(fieldVals),
267
- { fields, prefix },
268
- )
269
- }
270
-
271
- // candump1 Angstrom
272
- // <0x18eeff01> [8] 05 a0 be 1c 00 a0 a0 c0
273
- exports.isCandump1 = startsWith('<0x')
274
- exports.parseCandump1 = (input) => {
275
- const [ canId, len, ...data ] = input.split(' ')
276
- return buildMsg(
277
- parseCanIdStr(trimWrap(canId)), 'candump1', arrBuff(data),
278
- { len: Number(trimWrap(len)) },
279
- )
280
- }
281
-
282
- // candump2 Debian
283
- // can0 09F8027F [8] 00 FC FF FF 00 00 FF FF
284
- exports.isCandump2 = startsWith('can')
285
- exports.parseCandump2 = (input) => {
286
- const [ bus, canId, len, ...data ] = compact(input.split(' '))
287
- return buildMsg(
288
- parseCanIdStr(canId), 'candump2', arrBuff(data),
289
- { bus, len: Number(trimWrap(len)) },
290
- )
291
- }
292
-
293
- // candump3 log
294
- // (1502979132.106111) slcan0 09F50374#000A00FFFF00FFFF
295
- exports.isCandump3 = startsWith('(')
296
- exports.parseCandump3 = (input) => {
297
- const [ timestamp, bus, canFrame ] = input.split(' ')
298
- const [ canId, data ] = canFrame.split('#')
299
- return buildMsg(
300
- parseCanIdStr(canId), 'candump3', Buffer.from(data, 'hex'), { timestamp, bus }
301
- )
302
- }
303
-
304
- const hasErr = overSome([negate(isString), isEmpty])
305
- exports.parseN2kString = cond([
306
- [hasErr, buildErr('INVALID', 'Input not string or empty.')],
307
- [exports.isActisense, exports.parseActisense],
308
- [exports.isYDRAW, exports.parseYDRAW],
309
- [exports.isPCDIN, exports.parsePCDIN],
310
- [exports.isMXPGN, exports.parseMXPGN],
311
- [exports.isPDGY, exports.parsePDGY],
312
- [exports.isCandump1, exports.parseCandump1],
313
- [exports.isCandump2, exports.parseCandump2],
314
- [exports.isCandump3, exports.parseCandump3],
315
- [exports.isPDGYdebug, exports.parsePDGYdebug],
316
- [exports.isActisenseN2KASCII, exports.parseActisenseN2KASCII],
317
- [stubTrue, buildErr('MISSING_PARSER', 'Parser not found for input.')],
318
- ])
319
-
320
- exports.isN2KString = cond([
321
- [hasErr, () => false],
322
- [exports.isActisense, () => true],
323
- [exports.isYDRAW, () => true],
324
- [exports.isPCDIN, () => true],
325
- [exports.isMXPGN, () => true],
326
- [exports.isPDGY, () => true],
327
- [exports.isCandump1, () => true],
328
- [exports.isCandump2, () => true],
329
- [exports.isCandump3, () => true],
330
- [exports.isPDGYdebug, () => true],
331
- [exports.isActisenseN2KASCII, () => true],
332
- [stubTrue, () => false],
333
- ])
334
-
335
- exports.isN2KOver0183 = (msg) => { return exports.isPCDIN(msg) || exports.isMXPGN(msg) }
336
-
337
- exports.parseN2KOver0183 = (msg) => { return exports.parsePCDIN(msg) || exports.parseMXPGN(msg) }
338
-
339
-