@zimo-elektronik/zcan 1.0.45 → 1.0.47

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.
@@ -62,7 +62,7 @@ export default class InfoGroup
62
62
  this.parseModuleInfo(size, mode, nid, buffer);
63
63
  break;
64
64
  default:
65
- this.mx10.logInfo.next('command not parsed: ' + command.toString());
65
+ this.mx10.logInfo.next('infoGroup command ' + command + ' not parsed: ' + JSON.stringify(buffer));
66
66
  }
67
67
  }
68
68
 
@@ -6,7 +6,7 @@ import {Direction, Manual, MaxSpeedSteps, MsgMode, OperatingMode, ShuntingFuncti
6
6
  } from '../common/enums';
7
7
  import {combineSpeedAndDirection} from '../common/speedUtils';
8
8
  import { Query } from '../common/communication';
9
- import { MsgVehicleMode, MsgVehicleSpeed } from './vehicleMsg';
9
+ import { MsgVehicleLastCtl, MsgVehicleMode, MsgVehicleSpeed, MsgVehicleState } from './vehicleMsg';
10
10
 
11
11
  /**
12
12
  *
@@ -14,12 +14,15 @@ import { MsgVehicleMode, MsgVehicleSpeed } from './vehicleMsg';
14
14
  */
15
15
  export default class VehicleGroup
16
16
  {
17
- public readonly onVehicleState = new Subject<VehicleStateData>();
17
+ public readonly onVehicleState = new Subject<MsgVehicleState>();
18
+ public readonly onVehicleLastCtl = new Subject<MsgVehicleLastCtl>();
18
19
  public readonly onVehicleMode = new Subject<MsgVehicleMode>();
19
20
  public readonly onVehicleSpeed = new Subject<MsgVehicleSpeed>(); // VehicleSpeedData
20
21
  public readonly onCallFunction = new Subject<CallFunctionData>();
21
22
  public readonly onCallSpecialFunction = new Subject<CallSpecialFunctionData>();
22
23
 
24
+ private stateQ: Query<MsgVehicleState> | undefined = undefined;
25
+ private lastCtlQ: Query<MsgVehicleLastCtl> | undefined = undefined;
23
26
  private modeQ: Query<MsgVehicleMode> | undefined = undefined;
24
27
  private speedQ: Query<MsgVehicleSpeed> | undefined = undefined;
25
28
 
@@ -27,7 +30,57 @@ export default class VehicleGroup
27
30
 
28
31
  constructor(mx10: MX10) {this.mx10 = mx10}
29
32
 
30
- async getVehicleMode(trainNid: number)
33
+ //0x02.0x00
34
+ async getState(nid: number)
35
+ {
36
+ if(this.stateQ !== undefined && !await this.stateQ.lock()) {
37
+ this.mx10.logInfo.next("mx10.getVehicleState: failed to acquire lock");
38
+ return undefined;
39
+ }
40
+ this.stateQ = new Query(MsgVehicleState.header(MsgMode.REQ, nid), this.onVehicleState);
41
+ this.stateQ.log = (msg) => {this.mx10.logInfo.next(msg)};
42
+ this.stateQ.tx = ((header) => {
43
+ const msg = new MsgVehicleState(header);
44
+ // this.mx10.logInfo.next('state query tx: ' + JSON.stringify(msg));
45
+ this.mx10.sendMsg(msg);
46
+ });
47
+ this.stateQ.match = ((msg) => {
48
+ // this.mx10.logInfo.next('state query rx: ' + JSON.stringify(msg));
49
+ return (msg.trainNid() === nid);
50
+ })
51
+ const rv = await this.stateQ.run();
52
+ // this.mx10.logInfo.next("mx10.getVehicleState.rv: " + JSON.stringify(rv));
53
+ this.stateQ.unlock();
54
+ this.stateQ = undefined;
55
+ return rv;
56
+ }
57
+
58
+ //0x02.0x00
59
+ async getLastController(locoNid: number, type: number = 1)
60
+ {
61
+ if(this.lastCtlQ !== undefined && !await this.lastCtlQ.lock()) {
62
+ this.mx10.logInfo.next("mx10.getVehicleLastCtl: failed to acquire lock");
63
+ return undefined;
64
+ }
65
+ this.lastCtlQ = new Query(MsgVehicleLastCtl.header(MsgMode.REQ, locoNid), this.onVehicleLastCtl);
66
+ this.lastCtlQ.log = (msg) => {this.mx10.logInfo.next(msg)};
67
+ this.lastCtlQ.tx = ((header) => {
68
+ const msg = new MsgVehicleLastCtl(header, type);
69
+ this.mx10.logInfo.next('lastCtl query tx: ' + JSON.stringify(msg));
70
+ this.mx10.sendMsg(msg);
71
+ });
72
+ this.lastCtlQ.match = ((msg) => {
73
+ this.mx10.logInfo.next('lastCtl query rx: ' + JSON.stringify(msg));
74
+ return (msg.trainNid() === locoNid);
75
+ })
76
+ const rv = await this.lastCtlQ.run();
77
+ this.mx10.logInfo.next("mx10.getVehicleLastCtl.rv: " + JSON.stringify(rv));
78
+ this.lastCtlQ.unlock();
79
+ this.lastCtlQ = undefined;
80
+ return rv;
81
+ }
82
+
83
+ async getMode(trainNid: number)
31
84
  {
32
85
  if(this.modeQ !== undefined && !await this.modeQ.lock()) {
33
86
  this.mx10.logInfo.next("mx10.getVehicleMode: failed to acquire lock");
@@ -45,13 +98,13 @@ export default class VehicleGroup
45
98
  return (msg.trainNid() === trainNid);
46
99
  })
47
100
  const rv = await this.modeQ.run();
48
- this.mx10.logInfo.next("mx10.getVehicleMode.rv: " + JSON.stringify(rv));
101
+ // this.mx10.logInfo.next("mx10.getVehicleMode.rv: " + JSON.stringify(rv));
49
102
  this.modeQ.unlock();
50
103
  this.modeQ = undefined;
51
104
  return rv;
52
105
  }
53
106
 
54
- async setVehicleMode(trainNid: number, opMode: OperatingMode, speedSteps: MaxSpeedSteps)
107
+ async setMode(trainNid: number, opMode: OperatingMode, speedSteps: MaxSpeedSteps)
55
108
  {
56
109
  MsgVehicleMode.log = (msg) => {this.mx10.logInfo.next(msg)};
57
110
  if(this.modeQ !== undefined && !await this.modeQ.lock()) {
@@ -62,21 +115,21 @@ export default class VehicleGroup
62
115
  this.modeQ.log = (msg) => {this.mx10.logInfo.next(msg)};
63
116
  this.modeQ.tx = ((header) => {
64
117
  const msg = new MsgVehicleMode(header, {opMode, speedSteps});
65
- this.mx10.logInfo.next('mode query tx: ' + JSON.stringify(msg));
118
+ // this.mx10.logInfo.next('mode query tx: ' + JSON.stringify(msg));
66
119
  this.mx10.sendMsg(msg);
67
120
  });
68
121
  this.modeQ.match = ((msg) => {
69
- this.mx10.logInfo.next('mode query rx: ' + JSON.stringify(msg));
122
+ // this.mx10.logInfo.next('mode query rx: ' + JSON.stringify(msg));
70
123
  return (msg.trainNid() === trainNid);
71
124
  })
72
125
  const rv = await this.modeQ.run(MsgVehicleMode.rxDelay());
73
- this.mx10.logInfo.next("mx10.setVehicleMode.rv: " + JSON.stringify(rv));
126
+ // this.mx10.logInfo.next("mx10.setVehicleMode.rv: " + JSON.stringify(rv));
74
127
  this.modeQ.unlock();
75
128
  this.modeQ = undefined;
76
129
  return rv;
77
130
  }
78
131
 
79
- async getVehicleSpeed(trainNid: number)
132
+ async getSpeed(trainNid: number)
80
133
  {
81
134
  if(this.speedQ !== undefined && !await this.speedQ.lock()) {
82
135
  this.mx10.logInfo.next("mx10.getVehicleSpeed: failed to acquire lock");
@@ -94,13 +147,13 @@ export default class VehicleGroup
94
147
  return (msg.trainNid() === trainNid);
95
148
  })
96
149
  const rv = await this.speedQ.run();
97
- this.mx10.logInfo.next("mx10.getVehicleSpeed.rv: " + JSON.stringify(rv));
150
+ // this.mx10.logInfo.next("mx10.getVehicleSpeed.rv: " + JSON.stringify(rv));
98
151
  this.speedQ.unlock();
99
152
  this.speedQ = undefined;
100
153
  return rv;
101
154
  }
102
155
 
103
- async setVehicleSpeed(trainNid: number, speedStep: number, divisor: number = 0, forward: boolean = true,
156
+ async setSpeed(trainNid: number, speedStep: number, divisor: number = 0, forward: boolean = true,
104
157
  emergencyStop: boolean = false, eastWest: Direction = Direction.UNDEFINED)
105
158
  {
106
159
  MsgVehicleSpeed.log = (msg) => {this.mx10.logInfo.next(msg)};
@@ -113,15 +166,15 @@ export default class VehicleGroup
113
166
  this.speedQ.tx = ((header) => {
114
167
  const speedAndDir= MsgVehicleSpeed.speedAndDir(speedStep, forward, emergencyStop, eastWest);
115
168
  const msg = new MsgVehicleSpeed(header, speedAndDir, divisor);
116
- this.mx10.logInfo.next('speed query tx: ' + JSON.stringify(msg));
169
+ // this.mx10.logInfo.next('speed query tx: ' + JSON.stringify(msg));
117
170
  this.mx10.sendMsg(msg);
118
171
  });
119
172
  this.speedQ.match = ((msg) => {
120
- this.mx10.logInfo.next('speed query rx: ' + JSON.stringify(msg));
173
+ // this.mx10.logInfo.next('speed query rx: ' + JSON.stringify(msg));
121
174
  return (msg.trainNid() === trainNid);
122
175
  })
123
176
  const rv = await this.speedQ.run(MsgVehicleSpeed.rxDelay());
124
- this.mx10.logInfo.next("mx10.setVehicleSpeed.rv: " + JSON.stringify(rv));
177
+ // this.mx10.logInfo.next("mx10.setVehicleSpeed.rv: " + JSON.stringify(rv));
125
178
  this.speedQ.unlock();
126
179
  this.speedQ = undefined;
127
180
  return rv;
@@ -155,11 +208,6 @@ export default class VehicleGroup
155
208
  ]);
156
209
  }
157
210
 
158
- //0x02.0x00
159
- vehicleState(vehicleAddress: number) {
160
- return this.mx10.sendData(0x02, 0x00, [{value: vehicleAddress, length: 2}], 0b00);
161
- }
162
-
163
211
  // 0x02.0x10
164
212
  activeModeTrain(vehicleAddress: number) {
165
213
  return this.mx10.sendData(0x02, 0x10, [
@@ -184,24 +232,18 @@ export default class VehicleGroup
184
232
  case 0x02: this.parseVehicleSpeed(size, mode, nid, buffer); break;
185
233
  case 0x04: this.parseVehicleFunction(size, mode, nid, buffer); break;
186
234
  case 0x05: this.parseVehicleSpecialFunction(size, mode, nid, buffer); break;
235
+ case 0x12: this.parseVehicleLastCtl(size, mode, nid, buffer); break;
187
236
  }
188
237
  }
189
238
 
190
239
  // 0x02.0x00
191
240
  private parseVehicleState( size: number, mode: number, nid: number, buffer: Buffer)
192
241
  {
193
- if (this.onVehicleState.observed) {
194
- const NID = buffer.readUInt16LE(0);
195
- const stateFlags = buffer.readUInt16LE(2); // TODO: add
196
- const ctrlTick = buffer.readUInt16LE(4);
197
- const ctrlDevice = buffer.readUInt16LE(6);
198
-
199
- this.onVehicleState.next({
200
- nid: NID,
201
- ctrlTick,
202
- ctrlDevice,
203
- });
204
- }
242
+ if(!this.onVehicleState.observed)
243
+ return;
244
+ const msg = MsgVehicleState.fromBuffer(mode, buffer);
245
+ // this.mx10.logInfo.next('parseVehicleState' + JSON.stringify(buffer));
246
+ this.onVehicleState.next(msg);
205
247
  }
206
248
 
207
249
  // 0x02.0x01
@@ -224,23 +266,6 @@ export default class VehicleGroup
224
266
  const msg = MsgVehicleSpeed.fromBuffer(mode, buffer);
225
267
  // this.mx10.logInfo.next('parseVehicleSpeed: ' + JSON.stringify(msg));
226
268
  this.onVehicleSpeed.next(msg);
227
-
228
-
229
- // const NID = buffer.readUInt16LE(0);
230
- // const speedAndDirection = buffer.readUInt16LE(2);
231
- // const divisor = buffer.readUint8(4);
232
-
233
- // const {speedStep, forward, eastWest, emergencyStop} =
234
- // parseSpeed(speedAndDirection);
235
-
236
- // {
237
- // nid: NID,
238
- // divisor,
239
- // speedStep,
240
- // forward,
241
- // eastWest,
242
- // emergencyStop,
243
- // });
244
269
  }
245
270
 
246
271
  // 0x02.0x04
@@ -250,7 +275,6 @@ export default class VehicleGroup
250
275
  const NID = buffer.readUInt16LE(0);
251
276
  const functionNumber = buffer.readUInt16LE(2);
252
277
  const functionState = buffer.readUInt16LE(4);
253
-
254
278
  const functionActive = functionState !== 0x00;
255
279
 
256
280
  this.onCallFunction.next({
@@ -276,4 +300,19 @@ export default class VehicleGroup
276
300
  });
277
301
  }
278
302
  }
303
+
304
+ // 0x02.0x12
305
+ private parseVehicleLastCtl( size: number, mode: number, nid: number, buffer: Buffer)
306
+ {
307
+ if(!this.onVehicleLastCtl.observed)
308
+ return;
309
+
310
+ const NID = buffer.readUInt16LE(0);
311
+ const type = buffer.readUInt16LE(2);
312
+ const ctlNid = buffer.readUInt16LE(4);
313
+ const seconds = buffer.readUInt16LE(6);
314
+
315
+ const msg = new MsgVehicleLastCtl(MsgVehicleLastCtl.header(mode, NID), type, ctlNid, seconds);
316
+ this.onVehicleLastCtl.next(msg);
317
+ }
279
318
  }
@@ -102,4 +102,64 @@ export class MsgVehicleSpeed extends Message
102
102
  const stop = Number(emergencyStop);
103
103
  return speed | (direction << 10) | (eastWest << 12) | (stop << 15);
104
104
  };
105
+ }
106
+
107
+ export class MsgVehicleState extends Message
108
+ {
109
+ public static header = (mode: MsgMode, nid: number) => {return {group: 0x2, cmd: 0x0, mode, nid}}
110
+ public static log: (msg: string) => void = () => {};
111
+
112
+ constructor(header: Header, flags?: number, lastTick?: number, lastNid?: number)
113
+ {
114
+ super(header);
115
+ if(header.mode === MsgMode.REQ)
116
+ return;
117
+ super.push({value: flags || 0, length: 2});
118
+ super.push({value: lastTick || 0, length: 2});
119
+ super.push({value: lastNid || 0, length: 2});
120
+ }
121
+ trainNid(): number {return this.header.nid || 0}
122
+ stateFlags(): number {return this.data[0].value as number;}
123
+ lastCtlTick(): number {return this.data[1].value as number;}
124
+ lastCtlNid(): number {return this.data[2].value as number;}
125
+
126
+ public static fromBuffer(mode: MsgMode, buffer: Buffer)
127
+ {
128
+ const nid = buffer.readUInt16LE(0);
129
+ const flags = buffer.readUInt16LE(2);
130
+ const lastTick = buffer.readUint16LE(4);
131
+ const lastNid = buffer.readUint16LE(6);
132
+ const msg = new MsgVehicleState(MsgVehicleState.header(mode, nid), flags, lastTick, lastNid);
133
+ return msg;
134
+ }
135
+ }
136
+
137
+ export class MsgVehicleLastCtl extends Message
138
+ {
139
+ public static header = (mode: MsgMode, nid: number) => {return {group: 0x2, cmd: 0x12, mode, nid}}
140
+ public static log: (msg: string) => void = () => {};
141
+
142
+ constructor(header: Header, type: number, lastNid?: number, lastTick?: number)
143
+ {
144
+ super(header);
145
+ super.push({value: type, length: 2});
146
+ if(header.mode === MsgMode.REQ)
147
+ return;
148
+ super.push({value: lastNid || 0, length: 2});
149
+ super.push({value: lastTick || 0, length: 2});
150
+ }
151
+ trainNid(): number {return this.header.nid || 0}
152
+ type(): number {return this.data[0].value as number;}
153
+ ctlNid(): number {return this.data[1].value as number;}
154
+ seconds(): number {return this.data[2].value as number;}
155
+
156
+ public static fromBuffer(mode: MsgMode, buffer: Buffer)
157
+ {
158
+ const nid = buffer.readUInt16LE(0);
159
+ const type = buffer.readUInt16LE(2);
160
+ const ctlNid = buffer.readUint16LE(4);
161
+ const seconds = buffer.readUint16LE(6);
162
+ const msg = new MsgVehicleLastCtl(MsgVehicleLastCtl.header(mode, nid), type, ctlNid, seconds);
163
+ return msg;
164
+ }
105
165
  }
@@ -77,8 +77,7 @@ export default class LanNetworkGroup
77
77
  this.parseUnknownCommand(size, mode, nid, buffer);
78
78
  break;
79
79
  default:
80
- // eslint-disable-next-line no-console
81
- console.warn('command not parsed: ' + command.toString());
80
+ this.mx10.logInfo.next('lanNetworkGroup command ' + command + ' not parsed: ' + JSON.stringify(buffer));
82
81
  }
83
82
  }
84
83