@zimo-elektronik/zcan 1.0.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 (202) hide show
  1. package/.dockerignore +7 -0
  2. package/.editorconfig +15 -0
  3. package/.eslintignore +7 -0
  4. package/.eslintrc.cjs +17 -0
  5. package/.gitattributes +1 -0
  6. package/.github/workflows/docs.yml +46 -0
  7. package/.github/workflows/library.yml +59 -0
  8. package/.nvmrc +1 -0
  9. package/.prettierignore +14 -0
  10. package/.prettierrc.json +8 -0
  11. package/LICENSE.md +21 -0
  12. package/README.md +8 -0
  13. package/__tests__/connection.test.ts +58 -0
  14. package/__tests__/dataGroup.test.ts +98 -0
  15. package/__tests__/infoGroup.test.ts +30 -0
  16. package/__tests__/lanDataGroup.test.ts +82 -0
  17. package/__tests__/lanInfoGroup.test.ts +41 -0
  18. package/__tests__/systemControlGroup.test.ts +42 -0
  19. package/__tests__/trackCfgGroup.test.ts +43 -0
  20. package/__tests__/util/index.ts +14 -0
  21. package/__tests__/vehicleGroup.test.ts +128 -0
  22. package/dist/@types/communication.d.ts +30 -0
  23. package/dist/@types/communication.js +2 -0
  24. package/dist/@types/communication.js.map +1 -0
  25. package/dist/@types/models.d.ts +172 -0
  26. package/dist/@types/models.js +2 -0
  27. package/dist/@types/models.js.map +1 -0
  28. package/dist/MX10.d.ts +45 -0
  29. package/dist/MX10.js +233 -0
  30. package/dist/MX10.js.map +1 -0
  31. package/dist/docs_entrypoint.d.ts +6 -0
  32. package/dist/docs_entrypoint.js +7 -0
  33. package/dist/docs_entrypoint.js.map +1 -0
  34. package/dist/index.d.ts +6 -0
  35. package/dist/index.js +7 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/internal/bites.d.ts +9 -0
  38. package/dist/internal/bites.js +10 -0
  39. package/dist/internal/bites.js.map +1 -0
  40. package/dist/internal/speedUtils.d.ts +9 -0
  41. package/dist/internal/speedUtils.js +29 -0
  42. package/dist/internal/speedUtils.js.map +1 -0
  43. package/dist/internal/utils.d.ts +1 -0
  44. package/dist/internal/utils.js +4 -0
  45. package/dist/internal/utils.js.map +1 -0
  46. package/dist/util/enums.d.ts +113 -0
  47. package/dist/util/enums.js +137 -0
  48. package/dist/util/enums.js.map +1 -0
  49. package/dist/util/extended-ascii.d.ts +7 -0
  50. package/dist/util/extended-ascii.js +162 -0
  51. package/dist/util/extended-ascii.js.map +1 -0
  52. package/dist/zcan/accessoryCommandGroup.d.ts +6 -0
  53. package/dist/zcan/accessoryCommandGroup.js +9 -0
  54. package/dist/zcan/accessoryCommandGroup.js.map +1 -0
  55. package/dist/zcan/dataGroup.d.ts +31 -0
  56. package/dist/zcan/dataGroup.js +233 -0
  57. package/dist/zcan/dataGroup.js.map +1 -0
  58. package/dist/zcan/fileControlGroup.d.ts +7 -0
  59. package/dist/zcan/fileControlGroup.js +9 -0
  60. package/dist/zcan/fileControlGroup.js.map +1 -0
  61. package/dist/zcan/fileTransferGroup.d.ts +7 -0
  62. package/dist/zcan/fileTransferGroup.js +9 -0
  63. package/dist/zcan/fileTransferGroup.js.map +1 -0
  64. package/dist/zcan/index.d.ts +18 -0
  65. package/dist/zcan/index.js +19 -0
  66. package/dist/zcan/index.js.map +1 -0
  67. package/dist/zcan/infoGroup.d.ts +15 -0
  68. package/dist/zcan/infoGroup.js +64 -0
  69. package/dist/zcan/infoGroup.js.map +1 -0
  70. package/dist/zcan/lanDataGroup.d.ts +23 -0
  71. package/dist/zcan/lanDataGroup.js +226 -0
  72. package/dist/zcan/lanDataGroup.js.map +1 -0
  73. package/dist/zcan/lanInfoGroup.d.ts +11 -0
  74. package/dist/zcan/lanInfoGroup.js +58 -0
  75. package/dist/zcan/lanInfoGroup.js.map +1 -0
  76. package/dist/zcan/lanNetworkGroup.d.ts +11 -0
  77. package/dist/zcan/lanNetworkGroup.js +37 -0
  78. package/dist/zcan/lanNetworkGroup.js.map +1 -0
  79. package/dist/zcan/lanZimoProgrammableScriptGroup.d.ts +7 -0
  80. package/dist/zcan/lanZimoProgrammableScriptGroup.js +9 -0
  81. package/dist/zcan/lanZimoProgrammableScriptGroup.js.map +1 -0
  82. package/dist/zcan/networkGroup.d.ts +10 -0
  83. package/dist/zcan/networkGroup.js +38 -0
  84. package/dist/zcan/networkGroup.js.map +1 -0
  85. package/dist/zcan/propertyConfigGroup.d.ts +7 -0
  86. package/dist/zcan/propertyConfigGroup.js +9 -0
  87. package/dist/zcan/propertyConfigGroup.js.map +1 -0
  88. package/dist/zcan/railwayControlGroup.d.ts +7 -0
  89. package/dist/zcan/railwayControlGroup.js +9 -0
  90. package/dist/zcan/railwayControlGroup.js.map +1 -0
  91. package/dist/zcan/systemControlGroup.d.ts +13 -0
  92. package/dist/zcan/systemControlGroup.js +35 -0
  93. package/dist/zcan/systemControlGroup.js.map +1 -0
  94. package/dist/zcan/trackCfgGroup.d.ts +16 -0
  95. package/dist/zcan/trackCfgGroup.js +77 -0
  96. package/dist/zcan/trackCfgGroup.js.map +1 -0
  97. package/dist/zcan/trainControlGroup.d.ts +8 -0
  98. package/dist/zcan/trainControlGroup.js +19 -0
  99. package/dist/zcan/trainControlGroup.js.map +1 -0
  100. package/dist/zcan/vehicleGroup.d.ts +26 -0
  101. package/dist/zcan/vehicleGroup.js +145 -0
  102. package/dist/zcan/vehicleGroup.js.map +1 -0
  103. package/dist/zcan/zimoProgrammableScriptGroup.d.ts +7 -0
  104. package/dist/zcan/zimoProgrammableScriptGroup.js +9 -0
  105. package/dist/zcan/zimoProgrammableScriptGroup.js.map +1 -0
  106. package/gulpfile.js +37 -0
  107. package/jest.config.js +26 -0
  108. package/package.json +50 -0
  109. package/protocol_docs/README.md +41 -0
  110. package/protocol_docs/babel.config.js +3 -0
  111. package/protocol_docs/docs/command-groups/_category_.json +4 -0
  112. package/protocol_docs/docs/command-groups/accessories/_category_.json +4 -0
  113. package/protocol_docs/docs/command-groups/accessories/accessory-state.md +7 -0
  114. package/protocol_docs/docs/command-groups/command-groups.md +50 -0
  115. package/protocol_docs/docs/command-groups/data/_category_.json +4 -0
  116. package/protocol_docs/docs/command-groups/data/data-name-extended.md +60 -0
  117. package/protocol_docs/docs/command-groups/data/group-count.md +52 -0
  118. package/protocol_docs/docs/command-groups/data/item-fx-info.md +27 -0
  119. package/protocol_docs/docs/command-groups/data/item-image-config.md +44 -0
  120. package/protocol_docs/docs/command-groups/data/item-list-by-index.md +45 -0
  121. package/protocol_docs/docs/command-groups/data/item-list-by-nid.md +43 -0
  122. package/protocol_docs/docs/command-groups/data/remove-train.md +33 -0
  123. package/protocol_docs/docs/command-groups/info/_category_.json +4 -0
  124. package/protocol_docs/docs/command-groups/info/bidi-info.md +34 -0
  125. package/protocol_docs/docs/command-groups/lan-data/_category_.json +4 -0
  126. package/protocol_docs/docs/command-groups/lan-data/data-value-extended.md +65 -0
  127. package/protocol_docs/docs/command-groups/lan-data/loco-gui-extended.md +48 -0
  128. package/protocol_docs/docs/command-groups/lan-info/_category_.json +4 -0
  129. package/protocol_docs/docs/command-groups/lan-info/module-power-info.md +26 -0
  130. package/protocol_docs/docs/command-groups/lan-network/_category_.json +4 -0
  131. package/protocol_docs/docs/command-groups/lan-network/open-port.md +47 -0
  132. package/protocol_docs/docs/command-groups/network/_category_.json +4 -0
  133. package/protocol_docs/docs/command-groups/network/ping.md +49 -0
  134. package/protocol_docs/docs/command-groups/system/_category_.json +4 -0
  135. package/protocol_docs/docs/command-groups/system/system-state.md +59 -0
  136. package/protocol_docs/docs/command-groups/track/_category_.json +4 -0
  137. package/protocol_docs/docs/command-groups/track/tse-prog-read.md +37 -0
  138. package/protocol_docs/docs/command-groups/track/tse-prog-write.md +35 -0
  139. package/protocol_docs/docs/command-groups/train/_category_.json +4 -0
  140. package/protocol_docs/docs/command-groups/train/train-part-find.md +33 -0
  141. package/protocol_docs/docs/command-groups/vehicles/_category_.json +4 -0
  142. package/protocol_docs/docs/command-groups/vehicles/vehicle-function.md +36 -0
  143. package/protocol_docs/docs/command-groups/vehicles/vehicle-mode.md +143 -0
  144. package/protocol_docs/docs/command-groups/vehicles/vehicle-special-function-switch.md +35 -0
  145. package/protocol_docs/docs/command-groups/vehicles/vehicle-speed.md +55 -0
  146. package/protocol_docs/docs/description.md +4 -0
  147. package/protocol_docs/docs/introduction/_category_.json +4 -0
  148. package/protocol_docs/docs/introduction/how-it-works.md +61 -0
  149. package/protocol_docs/docs/introduction/implementation.md +39 -0
  150. package/protocol_docs/docs/introduction/interface.md +62 -0
  151. package/protocol_docs/docs/introduction/introduction.md +82 -0
  152. package/protocol_docs/docusaurus.config.js +111 -0
  153. package/protocol_docs/package-lock.json +25611 -0
  154. package/protocol_docs/package.json +47 -0
  155. package/protocol_docs/sidebars.js +22 -0
  156. package/protocol_docs/src/components/CommandAndGroup/index.tsx +16 -0
  157. package/protocol_docs/src/components/CommandAndGroup/styles.module.css +12 -0
  158. package/protocol_docs/src/components/HomepageFeatures/index.tsx +70 -0
  159. package/protocol_docs/src/components/HomepageFeatures/styles.module.css +11 -0
  160. package/protocol_docs/src/css/custom.css +76 -0
  161. package/protocol_docs/src/pages/index.module.css +23 -0
  162. package/protocol_docs/src/pages/index.tsx +41 -0
  163. package/protocol_docs/src/pages/markdown-page.md +7 -0
  164. package/protocol_docs/static/.nojekyll +0 -0
  165. package/protocol_docs/static/img/docusaurus.png +0 -0
  166. package/protocol_docs/static/img/favicon.ico +0 -0
  167. package/protocol_docs/static/img/undraw_docusaurus_mountain.svg +171 -0
  168. package/protocol_docs/static/img/undraw_docusaurus_react.svg +170 -0
  169. package/protocol_docs/static/img/undraw_docusaurus_tree.svg +40 -0
  170. package/protocol_docs/static/typedoc/index.html +10 -0
  171. package/protocol_docs/tsconfig.json +7 -0
  172. package/src/@types/communication.ts +73 -0
  173. package/src/@types/models.ts +215 -0
  174. package/src/MX10.ts +351 -0
  175. package/src/docs_entrypoint.ts +34 -0
  176. package/src/index.ts +8 -0
  177. package/src/internal/bites.ts +11 -0
  178. package/src/internal/speedUtils.ts +36 -0
  179. package/src/internal/utils.ts +3 -0
  180. package/src/util/enums.ts +147 -0
  181. package/src/util/extended-ascii.ts +179 -0
  182. package/src/zcan/accessoryCommandGroup.ts +24 -0
  183. package/src/zcan/dataGroup.ts +342 -0
  184. package/src/zcan/fileControlGroup.ts +25 -0
  185. package/src/zcan/fileTransferGroup.ts +25 -0
  186. package/src/zcan/index.ts +37 -0
  187. package/src/zcan/infoGroup.ts +90 -0
  188. package/src/zcan/lanDataGroup.ts +361 -0
  189. package/src/zcan/lanInfoGroup.ts +86 -0
  190. package/src/zcan/lanNetworkGroup.ts +70 -0
  191. package/src/zcan/lanZimoProgrammableScriptGroup.ts +25 -0
  192. package/src/zcan/networkGroup.ts +71 -0
  193. package/src/zcan/propertyConfigGroup.ts +25 -0
  194. package/src/zcan/railwayControlGroup.ts +25 -0
  195. package/src/zcan/systemControlGroup.ts +62 -0
  196. package/src/zcan/trackCfgGroup.ts +109 -0
  197. package/src/zcan/trainControlGroup.ts +48 -0
  198. package/src/zcan/vehicleGroup.ts +267 -0
  199. package/src/zcan/zimoProgrammableScriptGroup.ts +25 -0
  200. package/tsconfig.build.json +12 -0
  201. package/tsconfig.json +49 -0
  202. package/tsconfig.test.json +9 -0
package/src/MX10.ts ADDED
@@ -0,0 +1,351 @@
1
+ /* eslint-disable no-bitwise */
2
+
3
+ import {Buffer} from 'buffer';
4
+ import {interval, Subject} from 'rxjs';
5
+
6
+ import {
7
+ AccessoryCommandGroup,
8
+ DataGroup,
9
+ FileControlGroup,
10
+ FileTransferGroup,
11
+ InfoGroup,
12
+ LanDataGroup,
13
+ LanInfoGroup,
14
+ LanNetworkGroup,
15
+ LanZimoProgrammableScriptGroup,
16
+ NetworkGroup,
17
+ PropertyConfigGroup,
18
+ RailwayControlGroup,
19
+ SystemControlGroup,
20
+ TrackCfgGroup,
21
+ TrainControlGroup,
22
+ VehicleGroup,
23
+ ZimoProgrammableScriptGroup,
24
+ } from './zcan';
25
+ import {
26
+ CreateSocketFunction,
27
+ NIDGenerator,
28
+ Socket,
29
+ ZcanDataArray,
30
+ } from './@types/communication';
31
+ import {delay} from './internal/utils';
32
+ import ExtendedASCII from './util/extended-ascii';
33
+
34
+ /**
35
+ *
36
+ * @category Entrypoint
37
+ */
38
+ export default class MX10 {
39
+ myNID = 0;
40
+ mx10NID = 0;
41
+ mx10IP: string | undefined;
42
+ connected = false;
43
+
44
+ readonly systemControl = new SystemControlGroup(this);
45
+ readonly accessoryCommand = new AccessoryCommandGroup(this);
46
+ readonly vehicle = new VehicleGroup(this);
47
+ readonly trainControl = new TrainControlGroup(this);
48
+ readonly trackCfg = new TrackCfgGroup(this);
49
+ readonly data = new DataGroup(this);
50
+ readonly info = new InfoGroup(this);
51
+ readonly propertyConfig = new PropertyConfigGroup(this);
52
+ readonly network = new NetworkGroup(this);
53
+ readonly railwayControl = new RailwayControlGroup(this);
54
+ readonly zimoProgrammableScript = new ZimoProgrammableScriptGroup(this);
55
+ readonly fileControl = new FileControlGroup(this);
56
+ readonly fileTransfer = new FileTransferGroup(this);
57
+ readonly lanInfo = new LanInfoGroup(this);
58
+ readonly lanData = new LanDataGroup(this);
59
+ readonly lanNetwork = new LanNetworkGroup(this);
60
+ readonly lanZimoProgrammableScript = new LanZimoProgrammableScriptGroup(this);
61
+
62
+ readonly errors = new Subject<string>();
63
+
64
+ private mx10Socket: Socket | null = null;
65
+ private incomingPort = 14521;
66
+ private outgoingPort = 14520;
67
+
68
+ private lastPing = 0;
69
+ private interval: NodeJS.Timeout | undefined = undefined;
70
+
71
+ private readonly nidGeneratorFunction: NIDGenerator;
72
+ private readonly debugCommunication: boolean;
73
+ private readonly reconnectionTime: number = 0;
74
+
75
+ readonly connectionTimeout: number;
76
+
77
+ constructor(
78
+ nidGeneratorFunction: NIDGenerator,
79
+ connectionTimeout = 1000,
80
+ debugCommunication = false,
81
+ ) {
82
+ this.nidGeneratorFunction = nidGeneratorFunction;
83
+ this.connectionTimeout = connectionTimeout;
84
+ this.debugCommunication = debugCommunication;
85
+ this.reconnectionTime = connectionTimeout * 4;
86
+
87
+ const pingIntervalMs = 1000;
88
+
89
+ if (this.connected) {
90
+ this.network.ping();
91
+ }
92
+ interval(pingIntervalMs).subscribe(() => {
93
+ if (this.connected) {
94
+ this.network.ping();
95
+ }
96
+ });
97
+ }
98
+
99
+ async initSocket(
100
+ createSocketFunction: CreateSocketFunction,
101
+ ipAddress: string,
102
+ incomingPort = 14521,
103
+ outgoingPort = 14520,
104
+ ) {
105
+ this.mx10IP = ipAddress;
106
+ this.incomingPort = incomingPort;
107
+ this.outgoingPort = outgoingPort;
108
+
109
+ if (this.mx10Socket == null) {
110
+ const socket = (this.mx10Socket = createSocketFunction({
111
+ type: 'udp4',
112
+ }) as Socket);
113
+
114
+ await new Promise((resolve) => {
115
+ socket.bind(incomingPort, () => {
116
+ resolve(null);
117
+ });
118
+ });
119
+
120
+ this.mx10Socket.on('message', this.readRawData.bind(this));
121
+
122
+ this.myNID = await this.nidGeneratorFunction();
123
+ this.lanNetwork.portOpen();
124
+
125
+ await delay(this.connectionTimeout);
126
+
127
+ if (!this.connected) {
128
+ this.closeSocket();
129
+ throw new Error('mx10.connection.timeout');
130
+ }
131
+ }
132
+ }
133
+
134
+ reconnectLogic() {
135
+ const date = Date.now();
136
+ if (
137
+ date - this.lastPing < this.reconnectionTime &&
138
+ this.interval !== undefined
139
+ ) {
140
+ clearInterval(this.interval);
141
+ this.interval = undefined;
142
+ }
143
+
144
+ if (this.interval === undefined) {
145
+ this.interval = setInterval(() => {
146
+ if (!this.connected) {
147
+ // eslint-disable-next-line no-console
148
+ console.log('Reconnecting...');
149
+ this.network.portClose();
150
+ this.lanNetwork.portOpen();
151
+ this.network.ping(0b00);
152
+ }
153
+ }, this.reconnectionTime);
154
+ }
155
+
156
+ this.lastPing = date;
157
+ }
158
+
159
+ closeSocket(callMx10: boolean = true) {
160
+ if (this.mx10Socket != null) {
161
+ if (this.connected && callMx10) {
162
+ this.network.portClose();
163
+ }
164
+ this.mx10Socket?.close();
165
+ this.mx10Socket = null;
166
+ this.connected = false;
167
+ }
168
+ }
169
+
170
+ sendData(
171
+ group: number,
172
+ cmd: number,
173
+ data: ZcanDataArray = [],
174
+ mode = 0b01,
175
+ nid = this.myNID,
176
+ force = false,
177
+ ) {
178
+ const buffer = this.formatData(group, cmd, mode, nid, data);
179
+ this.send(buffer, force);
180
+ }
181
+
182
+ private formatData(
183
+ group: number,
184
+ cmd: number,
185
+ mode: number,
186
+ nid: number,
187
+ data: ZcanDataArray = [],
188
+ ) {
189
+ //Datagram Structure: Size(16) (Hex) (of Data), Unused(16) (Hex), Group(8) (Hex), Cmd+Mode(8) (command bit (Hex) shifted by mode (Binary)), NID(16) (Hex), Data(0...x) (Format: [{value: HEX, length: (1,2,4)}, {...}])
190
+
191
+ const size = data.reduce((sum, obj) => sum + obj.length, 0);
192
+ const buffer = Buffer.alloc(size + 8);
193
+
194
+ const cmd_md = (cmd << 2) | mode;
195
+
196
+ buffer.writeUInt16LE(size, 0);
197
+ buffer.writeUInt16LE(0, 2); // unused
198
+ buffer.writeUInt8(group, 4);
199
+ buffer.writeUInt8(cmd_md, 5);
200
+ buffer.writeUInt16LE(nid, 6);
201
+
202
+ let offset = 8;
203
+
204
+ data.forEach((element) => {
205
+ if (typeof element.value === 'string') {
206
+ ExtendedASCII.str2byte(element.value, buffer, offset, element.length);
207
+ offset += element.length;
208
+ } else {
209
+ switch (element.length) {
210
+ case 1:
211
+ buffer.writeUInt8(element.value, offset);
212
+ offset += 1;
213
+ break;
214
+
215
+ case 2:
216
+ buffer.writeUInt16LE(element.value, offset);
217
+ offset += 2;
218
+ break;
219
+
220
+ case 4:
221
+ buffer.writeUInt32LE(element.value, offset);
222
+ offset += 4;
223
+ break;
224
+
225
+ default:
226
+ // eslint-disable-next-line no-console
227
+ console.warn(`ELEMENT LENGTH NOT DEFINED, ${element}`);
228
+ }
229
+ }
230
+ });
231
+
232
+ this.printReadout(group, cmd, mode, nid, size, buffer.slice(8));
233
+
234
+ return buffer;
235
+ }
236
+
237
+ private send(message: Buffer, force = false) {
238
+ if (this.connected || force) {
239
+ this.mx10Socket?.send(
240
+ message,
241
+ 0,
242
+ message.length,
243
+ this.outgoingPort,
244
+ this.mx10IP,
245
+ (err) => {
246
+ if (err && this.debugCommunication) {
247
+ // eslint-disable-next-line no-console
248
+ console.log(err);
249
+ }
250
+ },
251
+ );
252
+ } else {
253
+ this.errors.next('mx10.connection.not_connected');
254
+ }
255
+ }
256
+
257
+ private readRawData(message: Buffer) {
258
+ const size = message.readUInt16LE(0);
259
+ const group = message.readUInt8(4);
260
+ const commandAndMode = message.readUInt8(5);
261
+
262
+ const command = commandAndMode >> 2;
263
+ const mode = commandAndMode & 0x03;
264
+
265
+ const nid = message.readUInt16LE(6);
266
+
267
+ const buffer = message.slice(8); //Remove first 8 bytes; left only with data
268
+ this.printReadout(group, command, mode, nid, size, buffer, false);
269
+
270
+ switch (group) {
271
+ case 0x00:
272
+ this.systemControl.parse(size, command, mode, nid, buffer);
273
+ break;
274
+ case 0x01:
275
+ this.accessoryCommand.parse(size, command, mode, nid, buffer);
276
+ break;
277
+ case 0x02:
278
+ this.vehicle.parse(size, command, mode, nid, buffer);
279
+ break;
280
+ case 0x05:
281
+ this.trainControl.parse(size, command, mode, nid, buffer);
282
+ break;
283
+ case 0x06:
284
+ case 0x16:
285
+ this.trackCfg.parse(size, command, mode, nid, buffer);
286
+ break;
287
+ case 0x07:
288
+ this.data.parse(size, command, mode, nid, buffer);
289
+ break;
290
+ case 0x08:
291
+ this.info.parse(size, command, mode, nid, buffer);
292
+ break;
293
+ case 0x09:
294
+ this.propertyConfig.parse(size, command, mode, nid, buffer);
295
+ break;
296
+ case 0x0a:
297
+ this.network.parse(size, command, mode, nid, buffer);
298
+ break;
299
+ case 0x0b:
300
+ this.railwayControl.parse(size, command, mode, nid, buffer);
301
+ break;
302
+ case 0x0c:
303
+ this.zimoProgrammableScript.parse(size, command, mode, nid, buffer);
304
+ break;
305
+ case 0x0e:
306
+ this.fileControl.parse(size, command, mode, nid, buffer);
307
+ break;
308
+ case 0x0f:
309
+ this.fileTransfer.parse(size, command, mode, nid, buffer);
310
+ break;
311
+ case 0x17:
312
+ this.lanData.parse(size, command, mode, nid, buffer);
313
+ break;
314
+ case 0x18:
315
+ this.lanInfo.parse(size, command, mode, nid, buffer);
316
+ break;
317
+ case 0x1a:
318
+ this.lanNetwork.parse(size, command, mode, nid, buffer);
319
+ break;
320
+ case 0x1c:
321
+ this.lanZimoProgrammableScript.parse(size, command, mode, nid, buffer);
322
+ break;
323
+ default:
324
+ // eslint-disable-next-line no-console
325
+ console.warn('Unknown group: ' + Number(group).toString(16));
326
+ }
327
+ }
328
+
329
+ private printReadout(
330
+ group: number,
331
+ cmd: number,
332
+ mode: number,
333
+ nid: number | undefined,
334
+ size: number,
335
+ raw_data: Buffer,
336
+ out = true,
337
+ ) {
338
+ if (this.debugCommunication) {
339
+ const data = JSON.stringify(Array.apply([], [...raw_data]));
340
+ const f = (obj: unknown) => Number(obj).toString(16);
341
+ const arrow = '|' + (out ? '→' : '←');
342
+
343
+ // eslint-disable-next-line no-console
344
+ console.debug(
345
+ `${arrow} g=${f(group)} c=${f(cmd)} m=${f(mode)} n=${f(nid)} l=${f(
346
+ size,
347
+ )} : ${data}`,
348
+ );
349
+ }
350
+ }
351
+ }
@@ -0,0 +1,34 @@
1
+ export {default as MX10} from './MX10';
2
+
3
+ export {
4
+ AccessoryCommandGroup,
5
+ DataGroup,
6
+ FileControlGroup,
7
+ FileTransferGroup,
8
+ InfoGroup,
9
+ LanDataGroup,
10
+ LanInfoGroup,
11
+ LanNetworkGroup,
12
+ LanZimoProgrammableScriptGroup,
13
+ NetworkGroup,
14
+ PropertyConfigGroup,
15
+ RailwayControlGroup,
16
+ SystemControlGroup,
17
+ TrackCfgGroup,
18
+ TrainControlGroup,
19
+ VehicleGroup,
20
+ ZimoProgrammableScriptGroup,
21
+ } from './zcan';
22
+
23
+ export {
24
+ Direction as Direction,
25
+ ExternalController,
26
+ FunctionMode,
27
+ OperatingMode,
28
+ SystemStateMode,
29
+ } from './util/enums';
30
+
31
+ export * from './@types/models';
32
+ export * from './@types/communication';
33
+
34
+ export {Subject, Observable} from 'rxjs';
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ import MX10 from './MX10';
2
+
3
+ export default MX10;
4
+ export * from './util/enums';
5
+ export * from './@types/models';
6
+ export * from './@types/communication';
7
+
8
+ export * from 'rxjs';
@@ -0,0 +1,11 @@
1
+ export const speedBites____ = 0b0000001111111111; // 0-9
2
+ export const directionBites = 0b0000010000000000; // 10
3
+ export const directACKBites = 0b0000100000000000; // 11
4
+ export const eastWestBites_ = 0b0011000000000000; // 12-13
5
+ export const emergencyStopB = 0b1000000000000000; // 15
6
+
7
+ export const speedStepBites = 0b00001111;
8
+ export const modeBites_____ = 0b11110000;
9
+
10
+ export const shuntingFunctionB = 0b1111;
11
+ export const manualModeB = 0b110000;
@@ -0,0 +1,36 @@
1
+ import {Direction} from "../util/enums";
2
+ import {directACKBites, directionBites, eastWestBites_, emergencyStopB, speedBites____, speedStepBites} from "./bites";
3
+
4
+ export const combineSpeedAndDirection = (speed: number, forward: boolean, eastWest = Direction.UNDEFINED, emergencyStop = false) => {
5
+ const direction = Number(!forward);
6
+ const stop = Number(emergencyStop);
7
+
8
+ return speed | (direction << 10) | (eastWest << 12) | (stop << 15);
9
+ };
10
+
11
+ export const parseSpeed = (speedAndDirection: number) => {
12
+ const speedStep = speedAndDirection & speedBites____;
13
+ const direction = (speedAndDirection & directionBites) === directionBites;
14
+ const directionACK = (speedAndDirection & directACKBites) === directACKBites;
15
+ const sideways = (speedAndDirection & eastWestBites_) >> 12;
16
+ const emergencyStop = (speedAndDirection & emergencyStopB) === emergencyStopB;
17
+
18
+ const forward = !direction && !directionACK;
19
+
20
+ return {
21
+ speedStep,
22
+ forward,
23
+ eastWest: sideways,
24
+ emergencyStop
25
+ };
26
+ }
27
+
28
+ export const getSpeedSteps = (val: number) => {
29
+ const steps = val & speedStepBites;
30
+
31
+ if (steps == 0 || steps >= 6) {
32
+ return undefined;
33
+ }
34
+
35
+ return steps;
36
+ }
@@ -0,0 +1,3 @@
1
+ export function delay(ms: number) {
2
+ return new Promise( resolve => setTimeout(resolve, ms) );
3
+ }
@@ -0,0 +1,147 @@
1
+ export enum OperatingMode {
2
+ UNKNOWN = '',
3
+ DCC = 'DCC',
4
+ MM1 = 'MM1',
5
+ MM2 = 'MM2',
6
+ SX = 'SX',
7
+ MFX = 'mfx',
8
+ NOT_DEFINED = 'N/A',
9
+ SYS = 'System',
10
+ }
11
+
12
+ export const getOperatingMode = (val: number) => {
13
+ // eslint-disable-next-line no-bitwise
14
+ const mode = val >> 4;
15
+ const modes = Object.values(OperatingMode);
16
+ if (mode >= 1 && mode <= 7) {
17
+ return modes[mode];
18
+ }
19
+ return OperatingMode.UNKNOWN;
20
+ };
21
+
22
+ export enum MaxSpeedSteps {
23
+ UNKNOWN,
24
+ MAX14,
25
+ MAX27,
26
+ MAX28,
27
+ MAX128,
28
+ MAX1024,
29
+ }
30
+
31
+ export enum ExternalController {
32
+ /** external controll: active on another controller */
33
+ FS = 'FS',
34
+ /** vehicle intergrated to its own traction T1, T2 */
35
+ T1 = 'T1',
36
+ T2 = 'T2',
37
+ FT = 'FT',
38
+ /** FT(...) f.e. FT(2) external traction on different controller */
39
+ FT2 = 'FT(2)',
40
+ /** external traction active on different controller */
41
+ FS2 = 'FS(2)',
42
+ }
43
+
44
+ /**
45
+ * Enum describing how given functions behaves.
46
+ */
47
+ export enum FunctionMode {
48
+ /** Functions needs to be pressed down and held to remain activated */
49
+ momentary,
50
+
51
+ /** Functions works as standart toggle switch */
52
+ switch,
53
+ }
54
+
55
+ export enum SystemStateMode {
56
+ NORMAL = 1,
57
+ SSP0 = 2,
58
+ SSPe = 3,
59
+ OFF = 4,
60
+ SERVICE = 5,
61
+ OVERRCURRENT = 10,
62
+ }
63
+
64
+ export enum TrackMode {
65
+ OFF = -1,
66
+ NORMAL = 0,
67
+ SSP0 = 1,
68
+ SSPe = 2,
69
+ SMP = 4,
70
+ UPDATE = 5,
71
+ SOUND = 6,
72
+ ERROR = 8,
73
+ ERROR_SMP = 9,
74
+ }
75
+
76
+ export enum Direction {
77
+ UNDEFINED = 0,
78
+ EAST = 1,
79
+ WEST = 2,
80
+ }
81
+
82
+ export enum NameType {
83
+ VEHICLE,
84
+ RAILWAY,
85
+ CONNECTION,
86
+ MANUFACTURER,
87
+ DECODER,
88
+ DESIGNATION,
89
+ CFGDB,
90
+ ICON,
91
+ ZIMO_PARTNER,
92
+ LAND,
93
+ COMPANY_CV,
94
+ }
95
+
96
+ export enum ImageType {
97
+ VEHICLE = 1,
98
+ VEHICLE_CRC32 = 2,
99
+ TACHO = 3,
100
+ VEHICLE_INSTRUMENT_BRAKE_BAR = 10,
101
+ VEHICLE_INSTRUMENT = 0x1f,
102
+ }
103
+
104
+ export enum FxInfoType {
105
+ ICON = 0x10,
106
+ }
107
+
108
+ export enum SpecialFunctionMode {
109
+ MANUAL = 1,
110
+ SHUNTING_FUNCTION = 2,
111
+ DIRECTION_DEFAULT = 3,
112
+ }
113
+
114
+ export enum Manual {
115
+ OFF = 0,
116
+ ON = 1,
117
+ }
118
+
119
+ export enum ShuntingFunction {
120
+ OFF = 0,
121
+ AZBZ = 1,
122
+ HALF = 2,
123
+ }
124
+
125
+ export enum DirectionDefault {
126
+ NO_CHANGE = 0,
127
+ DIRECTION_EAST = 1,
128
+ DIRECTION_WEST = 2,
129
+ }
130
+
131
+ export enum BidiType {
132
+ RAILCOM_STATISTICS = 0x0000,
133
+ SPEED_REPORT = 0x0100,
134
+ TILT_AND_CURVE = 0x0101,
135
+ CV = 0x0200,
136
+ QOS = 0x0300,
137
+ FILL_LEVEL = 0x0400,
138
+ DIRECTION = 0x0800,
139
+ TRACK_VOLTAGE = 0x1000,
140
+ ALARMS = 0x1100,
141
+ }
142
+
143
+ export enum ForwardOrReverse {
144
+ UNKNOWN = 0,
145
+ FORWARD = 1,
146
+ REVERSE = 2,
147
+ }