@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
@@ -1,108 +0,0 @@
1
- const debug = require('debug')('canboatjs:w2k01')
2
- const debugData = require('debug')('canboatjs:w2k01-data')
3
- const { parseCanId, encodeCanId } = require('./canId')
4
- const BitStream = require('bit-buffer').BitStream
5
- const { binToActisense } = require('./utilities')
6
-
7
- exports.readN2KActisense = function (data, plainText, context, cb) {
8
- const inBuf = Buffer.from(data)
9
- let inOffset = 0
10
- let last
11
-
12
- if ( debugData.enabled ) {
13
- debugData('Received: (' + data.length + ') ' + Buffer.from(data).toString('hex'))
14
- }
15
-
16
- try {
17
- while ( true ) {
18
- let len = inBuf.readUInt16LE(inOffset+3)
19
-
20
- if ( inBuf.length < inOffset + 5 + len ) {
21
- /*
22
- I've never seen this happen
23
- context.lastChunk = Buffer.alloc(inBuf.length - inOffset)
24
- inBuf.copy(context.lastChunk, 0, inOffset, inBuf.length-1)
25
- */
26
-
27
- if ( debug.enabled ) {
28
- debug('incomplete packet: (' + len + ') ' + inBuf.toString('hex', inOffset))
29
- }
30
-
31
- return
32
- } else if ( inBuf[inOffset + 5 + len -1] != 0x03 ||
33
- inBuf[inOffset + 5 + len -2] != 0x10 ) {
34
- if ( debug.enabled ) {
35
- debug('bad packet: (' + len + ') ' + inBuf.toString('hex', inOffset))
36
- }
37
- //context.lastChunk = null
38
- return
39
- }
40
-
41
- let buf = Buffer.alloc(len)
42
- inBuf.copy(buf, 0, inOffset+5, inOffset+len+5)
43
-
44
- //console.log('NextBuf: (' + buf.length + ') ' + buf.toString('hex'))
45
-
46
- let offset = 0
47
- let dst = buf.readUInt8(offset)
48
- offset += 1
49
- let canid = buf.readUInt32LE(offset)
50
- offset += 4
51
- let timestamp = buf.readUInt32LE(offset)
52
- offset += 4
53
- let mhs = buf.readUInt8(offset)
54
- offset += 1
55
-
56
- let info = parseCanId(canid)
57
-
58
- //console.log(`${len} ${mhs} ${dst} (${info.src}, ${info.dst}) ${info.pgn} ${timestamp}`)
59
-
60
- let pgnData = Buffer.alloc(len-offset-3)
61
- buf.copy(pgnData, 0, offset, len-3)
62
- info.timestamp = new Date().toISOString()
63
-
64
- if ( plainText ) {
65
- last = binToActisense(info, pgnData, pgnData.length)
66
- cb && cb(last)
67
- } else {
68
- last = { pgn:info, length: pgnData.length, data: pgnData, coalesced: true }
69
- cb && cb(last)
70
- }
71
-
72
- inOffset += len + 5
73
- if ( inOffset == inBuf.length ) {
74
- return last
75
- }
76
- }
77
- } catch ( error ) {
78
- debug(`[error] ${error}`)
79
- //context.lastChunk = null
80
- return
81
- }
82
- }
83
-
84
- exports.encodeN2KActisense = ({
85
- pgn, data, timestamp, prio = 2, dst = 255, src = 0 }) => {
86
- const bs = new BitStream(Buffer.alloc(18 + data.length))
87
-
88
- bs.writeUint8(0x10) //BST Message ID
89
- bs.writeUint8(0x02)
90
- bs.writeUint8(0xd0)
91
-
92
- bs.writeUint16(13 + data.length) //len
93
- bs.writeUint8(dst)
94
- bs.writeUint32(encodeCanId({dst, pgn, prio, src}))
95
- bs.writeUint32(0) //timestamp
96
- bs.writeUint8(0) //mhs
97
- data.copy(bs.view.buffer, bs.byteIndex, 0)
98
- bs.byteIndex += data.length
99
- bs.writeUint8(0) // ??
100
- bs.writeUint8(0x10)
101
- bs.writeUint8(0x03)
102
-
103
- if ( debugData.enabled ) {
104
- debugData('encoded: ' + bs.view.buffer.toString('hex'))
105
- }
106
-
107
- return bs.view.buffer
108
- }
package/lib/n2kDevice.js DELETED
@@ -1,390 +0,0 @@
1
- /**
2
- * Copyright 2025 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
- const debug = require('debug')('canboatjs:n2kdevice')
18
- const EventEmitter = require('events')
19
- const _ = require('lodash')
20
- const Uint64LE = require('int64-buffer').Uint64LE
21
- const { defaultTransmitPGNs, getIndustryCode, getManufacturerCode, getDeviceClassCode } = require('./codes')
22
- const { toPgn } = require('./toPgn')
23
- let packageJson
24
-
25
- try
26
- {
27
- packageJson = require('../' + 'package.json')
28
- } catch (ex) {
29
- }
30
-
31
- const deviceTransmitPGNs = [ 60928, 59904, 126996, 126464 ]
32
-
33
- class N2kDevice extends EventEmitter {
34
- constructor (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
-
93
- this.options = _.isUndefined(options) ? {} : options
94
-
95
- this.address = _.isUndefined(options.preferredAddress) ? 100 : options.preferredAddress
96
- this.cansend = false
97
- this.foundConflict = false
98
- this.heartbeatCounter = 0
99
- this.devices = {}
100
- this.sentAvailable = false
101
- this.addressClaimDetectionTime = options.addressClaimDetectionTime !== undefined ? options.addressClaimDetectionTime : 5000
102
-
103
- if ( !options.disableDefaultTransmitPGNs ) {
104
- this.transmitPGNs = _.union(deviceTransmitPGNs, defaultTransmitPGNs)
105
- } else {
106
- this.transmitPGNs = [...deviceTransmitPGNs]
107
- }
108
-
109
- if ( this.options.transmitPGNs ) {
110
- this.transmitPGNs = _.union(this.transmitPGNs,
111
- this.options.transmitPGNs)
112
- }
113
- }
114
-
115
- start() {
116
- sendISORequest(this, 60928, 254)
117
- setTimeout(() => {
118
- sendAddressClaim(this)
119
- }, 1000)
120
- }
121
-
122
- setStatus(msg) {
123
- if ( this.options.app && this.options.app.setPluginStatus ) {
124
- this.options.app.setProviderStatus(this.options.providerId, msg)
125
- }
126
- }
127
-
128
- n2kMessage(pgn) {
129
- if ( pgn.dst == 255 || pgn.dst == this.address ) {
130
- try {
131
- if ( pgn.pgn == 59904 ) {
132
- handleISORequest(this, pgn)
133
- } else if ( pgn.pgn == 126208 ) {
134
- handleGroupFunction(this, pgn)
135
- } else if ( pgn.pgn == 60928 ) {
136
- handleISOAddressClaim(this, pgn)
137
- } else if ( pgn.pgn == 126996 ) {
138
- handleProductInformation(this, pgn)
139
- }
140
- } catch ( err ) {
141
- console.error(err)
142
- console.error(err.stack)
143
- }
144
-
145
- /*
146
- var handler = this.handlers[pgn.pgn.toString()]
147
- if ( pgn.dst == this.address )
148
- debug(`handler ${handler}`)
149
- if ( _.isFunction(handler) ) {
150
- debug(`got handled PGN %j ${handled}`, pgn)
151
- handler(pgn)
152
- }
153
- */
154
- }
155
- }
156
-
157
- sendPGN(pgn, src) {
158
- }
159
- }
160
-
161
- function handleISORequest(device, n2kMsg) {
162
- debug('handleISORequest %j', n2kMsg)
163
-
164
- const PGN = n2kMsg.fields.PGN || n2kMsg.fields.pgn
165
-
166
- switch (PGN) {
167
- case 126996: // Product Information request
168
- sendProductInformation(device)
169
- break;
170
- case 126998: // Config Information request
171
- sendConfigInformation(device)
172
- break;
173
- case 60928: // ISO address claim request
174
- debug('sending address claim %j', device.addressClaim)
175
- device.sendPGN(device.addressClaim)
176
- break;
177
- case 126464:
178
- sendPGNList(device)
179
- break;
180
- default:
181
- if ( !device.options.disableNAKs ) {
182
- debug(`Got unsupported ISO request for PGN ${PGN}. Sending NAK.`)
183
- sendNAKAcknowledgement(device, n2kMsg.src, PGN)
184
- }
185
- }
186
- }
187
-
188
- function handleGroupFunction(device, n2kMsg) {
189
- debug('handleGroupFunction %j', n2kMsg)
190
- const functionCode = n2kMsg.fields.functionCode || n2kMsg.fields["Function Code"]
191
- if(functionCode === 'Request') {
192
- handleRequestGroupFunction(device, n2kMsg)
193
- } else if(functionCode === 'Command') {
194
- handleCommandGroupFunction(device, n2kMsg)
195
- } else {
196
- debug('Got unsupported Group Function PGN: %j', n2kMsg)
197
- }
198
-
199
- function handleRequestGroupFunction(device, n2kMsg) {
200
- if ( !device.options.disableNAKs ) {
201
- // We really don't support group function requests for any PGNs yet -> always respond with pgnErrorCode 1 = "PGN not supported"
202
-
203
- const PGN = n2kMsg.fields.PGN || n2kMsg.fields.pgn
204
-
205
- debug("Sending 'PGN Not Supported' Group Function response for requested PGN", PGN)
206
-
207
- const acknowledgement = {
208
- pgn: 126208,
209
- dst: n2kMsg.src,
210
- "Function Code": 2,
211
- "PGN": PGN,
212
- "PGN error code": 4,
213
- "Transmission interval/Priority error code": 0,
214
- "# of Parameters": 0
215
- }
216
- device.sendPGN(acknowledgement)
217
- }
218
- }
219
-
220
- function handleCommandGroupFunction(device, n2kMsg) {
221
- if ( !device.options.disableNAKs ) {
222
- // We really don't support group function commands for any PGNs yet -> always respond with pgnErrorCode 1 = "PGN not supported"
223
-
224
- const PGN = n2kMsg.fields.PGN || n2kMsg.fields.pgn
225
-
226
- debug("Sending 'PGN Not Supported' Group Function response for commanded PGN", PGN)
227
-
228
- const acknowledgement = {
229
- pgn: 126208,
230
- dst: n2kMsg.src,
231
- "Function Code": 2,
232
- "PGN": PGN,
233
- "PGN error code": 4,
234
- "Transmission interval/Priority error code": 0,
235
- "# of Parameters": 0
236
- }
237
- device.sendPGN(acknowledgement)
238
- }
239
- }
240
- }
241
-
242
- function handleISOAddressClaim(device, n2kMsg) {
243
- if ( n2kMsg.src != device.address ) {
244
- if ( !device.devices[n2kMsg.src] ) {
245
- debug(`registering device ${n2kMsg.src}`)
246
- device.devices[n2kMsg.src] = { addressClaim: n2kMsg }
247
- if ( device.cansend ) {
248
- //sendISORequest(device, 126996, undefined, n2kMsg.src)
249
- }
250
- }
251
- return
252
- }
253
-
254
- debug('Checking ISO address claim. %j', n2kMsg)
255
-
256
- const uint64ValueFromReceivedClaim = getISOAddressClaimAsUint64(n2kMsg)
257
- const uint64ValueFromOurOwnClaim = getISOAddressClaimAsUint64(device.addressClaim)
258
-
259
- if(uint64ValueFromOurOwnClaim < uint64ValueFromReceivedClaim) {
260
- debug(`Address conflict detected! Kept our address as ${device.address}.`)
261
- sendAddressClaim(device) // We have smaller address claim data -> we can keep our address -> re-claim it
262
- } else if(uint64ValueFromOurOwnClaim > uint64ValueFromReceivedClaim) {
263
- this.foundConflict = true
264
- increaseOwnAddress(device) // We have bigger address claim data -> we have to change our address
265
- debug(`Address conflict detected! trying address ${device.address}.`)
266
- sendAddressClaim(device)
267
- }
268
- }
269
-
270
- function increaseOwnAddress(device) {
271
- var start = device.address
272
- do {
273
- device.address = (device.address + 1) % 253
274
- } while ( device.address != start && device.devices[device.address] )
275
- }
276
-
277
- function handleProductInformation(device, n2kMsg) {
278
- if ( !device.devices[n2kMsg.src] ) {
279
- device.devices[n2kMsg.src] = {}
280
- }
281
- debug('got product information %j', n2kMsg)
282
- device.devices[n2kMsg.src].productInformation = n2kMsg
283
- }
284
-
285
- function sendHeartbeat(device)
286
- {
287
- device.heartbeatCounter = device.heartbeatCounter + 1
288
- if ( device.heartbeatCounter > 252 )
289
- {
290
- device.heartbeatCounter = 0
291
- }
292
- device.sendPGN({
293
- pgn: 126993,
294
- dst: 255,
295
- prio:7,
296
- "Data transmit offset": "00:01:00",
297
- "Sequence Counter": device.heartbeatCounter,
298
- "Controller 1 State":"Error Active"
299
- })
300
- }
301
-
302
-
303
- function sendAddressClaim(device) {
304
- if ( device.devices[device.address] ) {
305
- //someone already has this address, so find a free one
306
- increaseOwnAddress(device)
307
- }
308
- debug(`Sending address claim ${device.address}`)
309
- device.sendPGN(device.addressClaim)
310
- device.setStatus(`Claimed address ${device.address}`)
311
- device.addressClaimSentAt = Date.now()
312
- if ( device.addressClaimChecker ) {
313
- clearTimeout(device.addressClaimChecker)
314
- }
315
-
316
- device.addressClaimChecker = setTimeout(() => {
317
- //if ( Date.now() - device.addressClaimSentAt > 1000 ) {
318
- //device.addressClaimChecker = null
319
- debug('claimed address %d', device.address)
320
- device.cansend = true
321
- if ( !device.sentAvailable ) {
322
- if ( device.options.app ) {
323
- device.options.app.emit('nmea2000OutAvailable')
324
- }
325
- device.emit('nmea2000OutAvailable')
326
- device.sentAvailable = true
327
- }
328
- sendISORequest(device, 126996)
329
- if ( !device.heartbeatInterval ) {
330
- device.heartbeatInterval = setInterval(() => {
331
- sendHeartbeat(device)
332
- }, 60*1000)
333
- }
334
- //}
335
- }, device.addressClaimDetectionTime)
336
- }
337
-
338
- function sendISORequest(device, pgn, src, dst=255) {
339
- debug(`Sending iso request for ${pgn} to ${dst}`)
340
-
341
- const isoRequest = {
342
- pgn: 59904,
343
- dst: dst,
344
- "PGN": pgn
345
- }
346
- device.sendPGN(isoRequest, src)
347
- }
348
-
349
-
350
- function sendProductInformation(device) {
351
- debug("Sending product info %j", device.productInfo)
352
-
353
- device.sendPGN(device.productInfo)
354
- }
355
-
356
- function sendConfigInformation(device) {
357
- if ( device.configurationInfo ) {
358
- debug("Sending config info..")
359
- device.sendPGN(device.configurationInfo)
360
- }
361
- }
362
-
363
- function sendNAKAcknowledgement(device, src, requestedPGN) {
364
- const acknowledgement = {
365
- pgn: 59392,
366
- dst: src,
367
- Control: 1,
368
- "Group Function": 255,
369
- PGN: requestedPGN
370
- }
371
- device.sendPGN(acknowledgement)
372
- }
373
-
374
- function sendPGNList(device, src) {
375
- //FIXME: for now, adding everything that signalk-to-nmea2000 supports
376
- //need a way for plugins, etc. to register the pgns they provide
377
- const pgnList = {
378
- pgn: 126464,
379
- dst: src,
380
- "Function Code": 0,
381
- list: device.transmitPGNs
382
- }
383
- device.sendPGN(pgnList)
384
- }
385
-
386
- function getISOAddressClaimAsUint64(pgn) {
387
- return new Uint64LE(toPgn(pgn))
388
- }
389
-
390
- module.exports = N2kDevice
package/lib/pgns.js DELETED
@@ -1,196 +0,0 @@
1
- const { flow, first, isArray, isEmpty, propertyOf } = require('lodash/fp')
2
- const canboat = require('@canboat/pgns')
3
- const pgns = canboat.pgns
4
- const pgnsIK = { PGNs: [] } //require('@canboat/pgns/pgns-ik')
5
- const pgnsNGT = { PGNs: [] } //require('@canboat/pgns/pgns-ngt')
6
- const _ = require('lodash')
7
- const debug = require('debug')('canboatjs:pgns')
8
-
9
- function organizePGNs() {
10
- const res = {}
11
- const all = [...canboat.getPGNs(), ...pgnsIK.PGNs, ...pgnsNGT.PGNs]
12
- all.forEach(pgn => {
13
- if ( !res[pgn.PGN] ) {
14
- res[pgn.PGN] = []
15
- }
16
- res[pgn.PGN].push(pgn)
17
- pgn.Fields = isArray(pgn.Fields) ? pgn.Fields : (pgn.Fields ? [pgn.Fields.Field] : [])
18
- var reservedCount = 1
19
- pgn.Fields.forEach((field) => {
20
- if ( field.Name === 'Reserved' ) {
21
- field.Name = `Reserved${reservedCount++}`
22
- }
23
- })
24
- /*
25
- eval(`pgn.create = function(timestamp, prio, pgn, src, dst) {\
26
- return {\
27
- timestamp: timestamp,\
28
- prio: prio,\
29
- pgn: pgn,\
30
- src: src,\
31
- dst: dst,\
32
- fields: { ${pgn.fields.map(field => '"' + field.Name+'": null').join(',')} } \
33
- }\
34
- }`)
35
- */
36
- })
37
- return res
38
- }
39
-
40
- function getEnumeration(name) {
41
- const enumeration = lookupEnumerations[name]
42
- if ( enumeration ) {
43
- if ( !enumeration.value2name ) {
44
- enumeration.value2name = {}
45
- enumeration.EnumValues.forEach((enumPair) => {
46
- enumeration.value2name[Number(enumPair.Value)] = enumPair.Name
47
- })
48
-
49
- enumeration.name2value = {}
50
- enumeration.EnumValues.forEach((enumPair) => {
51
- enumeration.name2value[enumPair.Name] = Number(enumPair.Value)
52
- })
53
- }
54
- }
55
- return enumeration
56
- }
57
-
58
- function getFieldTypeEnumeration(name) {
59
- const enumeration = lookupFieldTypeEnumerations[name]
60
- if ( enumeration ) {
61
- if ( !enumeration.value2name ) {
62
- enumeration.value2name = {}
63
- enumeration.EnumFieldTypeValues.forEach((enumPair) => {
64
- enumeration.value2name[Number(enumPair.value)] = enumPair.name
65
- })
66
-
67
- enumeration.name2value = {}
68
- enumeration.EnumFieldTypeValues.forEach((enumPair) => {
69
- enumeration.name2value[enumPair.name] = Number(enumPair.value)
70
- })
71
-
72
- enumeration.value2bits = {}
73
- enumeration.EnumFieldTypeValues.forEach((enumPair) => {
74
- enumeration.value2bits[enumPair.value] = Number(enumPair.Bits)
75
- })
76
- }
77
- }
78
- return enumeration
79
- }
80
-
81
- function getBitEnumeration(name) {
82
- const enumeration = lookupBitEnumerations[name]
83
- if ( enumeration ) {
84
- if ( !enumeration.value2name ) {
85
- enumeration.value2name = {}
86
- enumeration.EnumBitValues.forEach((enumPair) => {
87
- enumeration.value2name[Number(enumPair.Bit)] = enumPair.Name
88
- })
89
-
90
- enumeration.name2value = {}
91
- enumeration.EnumBitValues.forEach((enumPair) => {
92
- enumeration.name2value[enumPair.Name] = Number(enumPair.Bit)
93
- })
94
- }
95
- }
96
- return enumeration
97
- }
98
-
99
- function lookupEnumerationName(enumName, value) {
100
- const enumeration = getEnumeration(enumName)
101
- return enumeration && enumeration.value2name[value]
102
- }
103
-
104
- function lookupEnumerationValue(enumName, name) {
105
- const enumeration = getEnumeration(enumName)
106
- return enumeration && enumeration.name2value[name]
107
- }
108
-
109
- function lookupFieldTypeEnumerationName(enumName, value) {
110
- const enumeration = getFieldTypeEnumeration(enumName)
111
- return enumeration && enumeration.value2name[value]
112
- }
113
-
114
- function lookupFieldTypeEnumerationBits(enumName, value) {
115
- const enumeration = getFieldTypeEnumeration(enumName)
116
- return enumeration && enumeration.value2bits[value]
117
- }
118
-
119
- function lookupFieldTypeEnumerationValue(enumName, name) {
120
- const enumeration = getFieldTypeEnumeration(enumName)
121
- return enumeration && enumeration.name2value[name]
122
- }
123
-
124
- function lookupBitEnumerationName(enumName, value) {
125
- const enumeration = getBitEnumeration(enumName)
126
- return enumeration && enumeration.value2name[value]
127
- }
128
-
129
- function lookupBitEnumerationValue(enumName, name) {
130
- const enumeration = getBitEnumeration(enumName)
131
- return enumeration.name2value[name]
132
- }
133
-
134
- function organizeEnumerations(enums) {
135
- let map = {}
136
- enums.forEach(e => {
137
- map[e.Name] = e
138
- })
139
- return map
140
- }
141
-
142
- const lookupEnumerations = organizeEnumerations(pgns.LookupEnumerations)
143
- const lookupFieldTypeEnumerations = organizeEnumerations(pgns.LookupFieldTypeEnumerations)
144
- const lookupBitEnumerations = organizeEnumerations(pgns.LookupBitEnumerations)
145
- const organizedPGNs = organizePGNs()
146
- const getPgn = pgn => organizedPGNs[pgn]
147
- const getPgn0 = flow(getPgn, first)
148
- const customPgns = {}
149
-
150
- module.exports = {
151
- getPgn,
152
- getPgn0,
153
- pgns: organizedPGNs,
154
- lookupEnumerationName,
155
- lookupEnumerationValue,
156
- lookupFieldTypeEnumerationName,
157
- lookupFieldTypeEnumerationValue,
158
- lookupFieldTypeEnumerationBits,
159
- lookupBitEnumerationName,
160
- lookupBitEnumerationValue,
161
- addCustomPgns: (pgns, setter) => {
162
- pgns.PGNs.forEach(pgn => {
163
- if ( !customPgns[pgn.PGN] ) {
164
- customPgns[pgn.PGN] = {
165
- definitions: [],
166
- callbacks: []
167
- }
168
- }
169
-
170
- customPgns[pgn.PGN].definitions.push(pgn)
171
-
172
- /*
173
- if ( pgn.calllback ) {
174
- customPgns[pgn.PGN].callbacks.push()
175
- }
176
- */
177
-
178
- debug('registered custom pgn %d by %s', pgn.PGN, setter)
179
- })
180
-
181
- if ( pgns.LookupEnumerations ) {
182
- pgns.LookupEnumerations.forEach(e => {
183
- if ( !lookupEnumerations[e.Name] ) {
184
- lookupEnumerations[e.Name] = e
185
- } else {
186
- debug(`enumeration ${e.Name} already exists`)
187
- }
188
- })
189
- }
190
- },
191
- getCustomPgn: (pgnNum) => {
192
- return customPgns[pgnNum]
193
- },
194
- getEnumForField: (pgnNumber, fieldName) => {
195
- }
196
- }
package/lib/pgns.test.js DELETED
@@ -1,13 +0,0 @@
1
- const { getPgn, getPgn0, pgns } = require('./pgns')
2
-
3
- // console.log(pgns)
4
- describe('getPgn', () => {
5
- test('Return info array about a pgn number', () => {
6
- expect(getPgn('60928')[0].Description).toBe('ISO Address Claim')
7
- })
8
- })
9
- describe('getPgn0', () => {
10
- test('Return first info object about a pgn number', () => {
11
- expect(getPgn0('60928').Description).toBe('ISO Address Claim')
12
- })
13
- })