@zimo-elektronik/zcan 1.0.51 → 1.0.53
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.
- package/.prettierrc.json +3 -1
- package/__tests__/accessoriesGroup.test.ts +26 -26
- package/__tests__/connection.test.ts +52 -52
- package/__tests__/dataGroup.test.ts +82 -92
- package/__tests__/infoGroup.test.ts +18 -18
- package/__tests__/lanDataGroup.test.ts +54 -66
- package/__tests__/lanInfoGroup.test.ts +34 -34
- package/__tests__/lanLocoStateGroup.test.ts +17 -17
- package/__tests__/systemControlGroup.test.ts +36 -36
- package/__tests__/trackCfgGroup.test.ts +38 -38
- package/__tests__/vehicleGroup.test.ts +109 -110
- package/dist/common/enums.d.ts +4 -4
- package/dist/common/enums.js +12 -12
- package/dist/common/enums.js.map +1 -1
- package/dist/common/models.d.ts +2 -18
- package/dist/data/lanDataGroup.d.ts +0 -2
- package/dist/data/lanDataGroup.js +0 -30
- package/dist/data/lanDataGroup.js.map +1 -1
- package/dist/data/lanDataMsg.d.ts +1 -0
- package/dist/data/lanDataMsg.js +20 -0
- package/dist/data/lanDataMsg.js.map +1 -1
- package/dist/info/infoGroup.d.ts +0 -4
- package/dist/info/infoGroup.js +1 -28
- package/dist/info/infoGroup.js.map +1 -1
- package/dist/info/infoMsg.d.ts +4 -0
- package/dist/info/infoMsg.js +12 -0
- package/dist/info/infoMsg.js.map +1 -1
- package/dist/loco/vehicleGroup.d.ts +7 -5
- package/dist/loco/vehicleGroup.js +41 -18
- package/dist/loco/vehicleGroup.js.map +1 -1
- package/dist/loco/vehicleMsg.d.ts +14 -1
- package/dist/loco/vehicleMsg.js +20 -0
- package/dist/loco/vehicleMsg.js.map +1 -1
- package/package.json +1 -1
- package/src/common/enums.ts +4 -4
- package/src/common/models.ts +14 -18
- package/src/data/lanDataGroup.ts +3 -92
- package/src/data/lanDataMsg.ts +23 -79
- package/src/info/infoGroup.ts +21 -33
- package/src/info/infoMsg.ts +20 -0
- package/src/loco/vehicleGroup.ts +62 -24
- package/src/loco/vehicleMsg.ts +27 -1
package/src/data/lanDataGroup.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// 0x17
|
|
2
2
|
import MX10 from '../MX10';
|
|
3
|
-
import {
|
|
4
|
-
import {DataNameExtendedData, DataValueExtendedData,
|
|
5
|
-
Train, TrainFlags
|
|
3
|
+
import {FxConfigType, getOperatingMode, MsgMode} from '../common/enums';
|
|
4
|
+
import {DataNameExtendedData, DataValueExtendedData, LocoSpeedTabExtended, SpeedTabData,
|
|
5
|
+
Train, TrainFlags} from '../common/models';
|
|
6
6
|
import {Subject} from 'rxjs';
|
|
7
7
|
import {parseSpeed} from '../common/speedUtils';
|
|
8
8
|
import ExtendedASCII from '../common/extendedAscii';
|
|
@@ -17,13 +17,11 @@ import { MsgLocoGuiReq, MsgLocoGuiRsp } from './lanDataMsg';
|
|
|
17
17
|
export default class LanDataGroup
|
|
18
18
|
{
|
|
19
19
|
public readonly onLocoGuiExtended = new Subject<MsgLocoGuiRsp>();
|
|
20
|
-
// public readonly onOldLocoGuiExtended = new Subject<MsgOldLocoGuiRsp>();
|
|
21
20
|
public readonly onDataValueExtended = new Subject<DataValueExtendedData>();
|
|
22
21
|
public readonly onDataNameExtended = new Subject<DataNameExtendedData>();
|
|
23
22
|
public readonly onLocoSpeedTabExtended = new Subject<LocoSpeedTabExtended>();
|
|
24
23
|
|
|
25
24
|
private locoGuiQ: Query<MsgLocoGuiRsp> | undefined = undefined;
|
|
26
|
-
// private oldLocoGuiQ: Query<MsgOldLocoGuiRsp> | undefined = undefined;
|
|
27
25
|
|
|
28
26
|
private mx10: MX10;
|
|
29
27
|
|
|
@@ -140,50 +138,6 @@ export default class LanDataGroup
|
|
|
140
138
|
return rv;
|
|
141
139
|
}
|
|
142
140
|
|
|
143
|
-
// async oldLocoGuiExtended(nid: number): Promise<MsgOldLocoGuiRsp | undefined>
|
|
144
|
-
// {
|
|
145
|
-
// if(this.oldLocoGuiQ !== undefined && !await this.oldLocoGuiQ.lock()) {
|
|
146
|
-
// this.mx10.logInfo.next("mx10.locoGuiExtended: failed to acquire lock");
|
|
147
|
-
// return undefined;
|
|
148
|
-
// }
|
|
149
|
-
// this.oldLocoGuiQ = new Query(MsgOldLocoGuiReq.header(MsgMode.REQ, this.mx10.mx10NID), this.onOldLocoGuiExtended);
|
|
150
|
-
// this.oldLocoGuiQ.log = ((msg) => {
|
|
151
|
-
// this.mx10.logInfo.next(msg);
|
|
152
|
-
// });
|
|
153
|
-
// this.oldLocoGuiQ.tx = ((header) => {
|
|
154
|
-
// const msg = new MsgOldLocoGuiReq(header, nid, 0);
|
|
155
|
-
// this.mx10.logInfo.next('locoGuiExtended query tx: ' + JSON.stringify(msg));
|
|
156
|
-
// this.mx10.sendMsg(msg);
|
|
157
|
-
// });
|
|
158
|
-
// this.oldLocoGuiQ.match = ((msg) => {
|
|
159
|
-
// this.mx10.logInfo.next('locoGuiExtended query rx: ' + JSON.stringify(msg));
|
|
160
|
-
// return (msg.locoNid() === nid);
|
|
161
|
-
// })
|
|
162
|
-
// const rv = await this.oldLocoGuiQ.run();
|
|
163
|
-
// this.mx10.logInfo.next("mx10.locoGuiExtended.rv: " + JSON.stringify(rv));
|
|
164
|
-
// this.oldLocoGuiQ.unlock();
|
|
165
|
-
// this.oldLocoGuiQ = undefined;
|
|
166
|
-
// return rv;
|
|
167
|
-
// }
|
|
168
|
-
|
|
169
|
-
// locoGuiExtended(NID: number)
|
|
170
|
-
// {
|
|
171
|
-
// this.mx10.sendData(0x17, 0x27, [
|
|
172
|
-
// {value: this.mx10.mx10NID, length: 2},
|
|
173
|
-
// {value: NID, length: 2},
|
|
174
|
-
// {value: 0, length: 2},
|
|
175
|
-
// ], 0b00);
|
|
176
|
-
// }
|
|
177
|
-
|
|
178
|
-
// locoGuiMXExtended(NID: number)
|
|
179
|
-
// {
|
|
180
|
-
// this.mx10.sendData(0x17,0x28, [
|
|
181
|
-
// {value: this.mx10.mx10NID, length: 2},
|
|
182
|
-
// {value: NID, length: 2},
|
|
183
|
-
// {value: 0, length: 2},
|
|
184
|
-
// ], 0b00);
|
|
185
|
-
// }
|
|
186
|
-
|
|
187
141
|
locoSpeedTapExtended(NID: number)
|
|
188
142
|
{
|
|
189
143
|
this.mx10.sendData(0x17, 0x19, [
|
|
@@ -194,11 +148,6 @@ export default class LanDataGroup
|
|
|
194
148
|
], 0b00);
|
|
195
149
|
}
|
|
196
150
|
|
|
197
|
-
// mxUpdateFnIcons(destructuredBuffer: ZcanDataArray)
|
|
198
|
-
// {
|
|
199
|
-
// this.mx10.sendData(0x17, 0x28, destructuredBuffer, 0b01);
|
|
200
|
-
// }
|
|
201
|
-
|
|
202
151
|
parse(size: number, command: number, mode: number, nid: number, buffer: Buffer)
|
|
203
152
|
{
|
|
204
153
|
switch (command)
|
|
@@ -209,9 +158,6 @@ export default class LanDataGroup
|
|
|
209
158
|
case 0x10:
|
|
210
159
|
this.parseDataNameExtended(size, mode, nid, buffer);
|
|
211
160
|
break;
|
|
212
|
-
// case 0x27:
|
|
213
|
-
// this.parseOldLocoGuiExtended(size, mode, nid, buffer);
|
|
214
|
-
// break;
|
|
215
161
|
case 0x28:
|
|
216
162
|
this.parseLocoGuiExtended(size, mode, nid, buffer);
|
|
217
163
|
break;
|
|
@@ -360,29 +306,6 @@ export default class LanDataGroup
|
|
|
360
306
|
this.onLocoSpeedTabExtended.next({srcid: SrcID, nid: NID, dbat6: DBat6, speedTab: locoSpeedTab});
|
|
361
307
|
}
|
|
362
308
|
|
|
363
|
-
private parseEra(eraString: number)
|
|
364
|
-
{
|
|
365
|
-
switch (eraString & 0xf0)
|
|
366
|
-
{
|
|
367
|
-
case 0x10:
|
|
368
|
-
return 'I';
|
|
369
|
-
case 0x20:
|
|
370
|
-
return 'II';
|
|
371
|
-
case 0x30:
|
|
372
|
-
return 'III';
|
|
373
|
-
case 0x40:
|
|
374
|
-
return 'IV';
|
|
375
|
-
case 0x50:
|
|
376
|
-
return 'V';
|
|
377
|
-
case 0x60:
|
|
378
|
-
return 'VI';
|
|
379
|
-
case 0x70:
|
|
380
|
-
return 'VII';
|
|
381
|
-
default:
|
|
382
|
-
return '';
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
|
|
386
309
|
private parseFlags(flagsNumber: number): TrainFlags
|
|
387
310
|
{
|
|
388
311
|
return {deleted: flagsNumber >> 31 === 1};
|
|
@@ -392,16 +315,4 @@ export default class LanDataGroup
|
|
|
392
315
|
{
|
|
393
316
|
return parseDeletedFlag === 1;
|
|
394
317
|
}
|
|
395
|
-
|
|
396
|
-
private destructureBuffer(buffer: Buffer): ZcanDataArray
|
|
397
|
-
{
|
|
398
|
-
const values = [];
|
|
399
|
-
for (let i = 0; i < buffer.length; i += 2) {
|
|
400
|
-
values.push({
|
|
401
|
-
value: buffer.readUInt16LE(i),
|
|
402
|
-
length: 2,
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
return values;
|
|
406
|
-
}
|
|
407
318
|
}
|
package/src/data/lanDataMsg.ts
CHANGED
|
@@ -3,73 +3,6 @@ import { Header, Message } from "../common/communication";
|
|
|
3
3
|
import { TrainFunction } from "../docs_entrypoint";
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
// export class MsgOldLocoGuiReq extends Message
|
|
7
|
-
// {
|
|
8
|
-
// public static header(mode: MsgMode, nid: number): Header
|
|
9
|
-
// {return {group: 0x17, cmd: 0x27, mode: mode, nid: nid}}
|
|
10
|
-
|
|
11
|
-
// constructor(header: Header, locoNid: number, subNid: number)
|
|
12
|
-
// {
|
|
13
|
-
// super(header);
|
|
14
|
-
// super.push({value: locoNid, length: 2});
|
|
15
|
-
// super.push({value: subNid, length: 2});
|
|
16
|
-
// }
|
|
17
|
-
// locoNid(): number {return (this.data[0].value as number)}
|
|
18
|
-
// subNid(): number {return (this.data[1].value as number)}
|
|
19
|
-
// }
|
|
20
|
-
|
|
21
|
-
// export class MsgOldLocoGuiRsp extends Message
|
|
22
|
-
// {
|
|
23
|
-
// public static header(mode: MsgMode, nid: number): Header
|
|
24
|
-
// {return {group: 0x17, cmd: 0x27, mode: mode, nid: nid}}
|
|
25
|
-
|
|
26
|
-
// constructor(header: Header, locoNid: number, subNid: number, group: number, name: string, imageId: number,
|
|
27
|
-
// tacho: number, speedFwd: number, speedRev: number, speedRange: number, driveType: number, era: number,
|
|
28
|
-
// country: number, functions: number[])
|
|
29
|
-
// {
|
|
30
|
-
// super(header);
|
|
31
|
-
// super.push({value: locoNid, length: 2});
|
|
32
|
-
// super.push({value: subNid, length: 2});
|
|
33
|
-
// super.push({value: group, length: 2});
|
|
34
|
-
// super.push({value: name, length: 32});
|
|
35
|
-
// super.push({value: imageId, length: 2});
|
|
36
|
-
// super.push({value: tacho, length: 2});
|
|
37
|
-
// super.push({value: speedFwd, length: 2});
|
|
38
|
-
// super.push({value: speedRev, length: 2});
|
|
39
|
-
// super.push({value: speedRange, length: 2});
|
|
40
|
-
// super.push({value: driveType, length: 2});
|
|
41
|
-
// super.push({value: era, length: 2});
|
|
42
|
-
// super.push({value: country, length: 2});
|
|
43
|
-
// functions.forEach(funk => {
|
|
44
|
-
// super.push({value: funk, length: 2});
|
|
45
|
-
// });
|
|
46
|
-
// }
|
|
47
|
-
// locoNid(): number {return (this.data[0].value as number)}
|
|
48
|
-
// subNid(): number {return (this.data[1].value as number)}
|
|
49
|
-
// group(): number {return (this.data[2].value as number)}
|
|
50
|
-
// name(): string {return (this.data[3].value as string)}
|
|
51
|
-
// imageId(): number {return (this.data[4].value as number)}
|
|
52
|
-
// tacho(): number {return (this.data[5].value as number)}
|
|
53
|
-
// speedFwd(): number {return (this.data[6].value as number)}
|
|
54
|
-
// speedRev(): number {return (this.data[7].value as number)}
|
|
55
|
-
// speedRange(): number {return (this.data[8].value as number)}
|
|
56
|
-
// driveType(): number {return (this.data[9].value as number)}
|
|
57
|
-
// era(): number {return (this.data[10].value as number)}
|
|
58
|
-
// country(): number {return (this.data[11].value as number)}
|
|
59
|
-
// functions(): Array<TrainFunction>
|
|
60
|
-
// {
|
|
61
|
-
// const rv = Array<TrainFunction>();
|
|
62
|
-
// for (let i = 12; i < this.data.length; i++) {
|
|
63
|
-
// const icon = (this.data[i].value as number);
|
|
64
|
-
// const iconString = icon === 0 ? String(i).padStart(2, '0') : String(icon);
|
|
65
|
-
// rv.push({mode: FunctionMode.switch, active: false,
|
|
66
|
-
// icon: iconString.padStart(4, icon === 0 ? '07' : '0'),
|
|
67
|
-
// });
|
|
68
|
-
// }
|
|
69
|
-
// return rv;
|
|
70
|
-
// }
|
|
71
|
-
// }
|
|
72
|
-
|
|
73
6
|
export class MsgLocoGuiReq extends Message
|
|
74
7
|
{
|
|
75
8
|
public static header(mode: MsgMode, nid: number): Header
|
|
@@ -146,16 +79,27 @@ export class MsgLocoGuiRsp extends Message
|
|
|
146
79
|
}
|
|
147
80
|
return rv;
|
|
148
81
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
82
|
+
|
|
83
|
+
public static parseEra(era: number)
|
|
84
|
+
{
|
|
85
|
+
switch (era & 0xf0)
|
|
86
|
+
{
|
|
87
|
+
case 0x10:
|
|
88
|
+
return 'I';
|
|
89
|
+
case 0x20:
|
|
90
|
+
return 'II';
|
|
91
|
+
case 0x30:
|
|
92
|
+
return 'III';
|
|
93
|
+
case 0x40:
|
|
94
|
+
return 'IV';
|
|
95
|
+
case 0x50:
|
|
96
|
+
return 'V';
|
|
97
|
+
case 0x60:
|
|
98
|
+
return 'VI';
|
|
99
|
+
case 0x70:
|
|
100
|
+
return 'VII';
|
|
101
|
+
default:
|
|
102
|
+
return '';
|
|
103
|
+
}
|
|
104
|
+
}
|
|
161
105
|
}
|
package/src/info/infoGroup.ts
CHANGED
|
@@ -2,8 +2,7 @@ import {Buffer} from 'buffer';
|
|
|
2
2
|
import MX10 from '../MX10';
|
|
3
3
|
import {Subject} from 'rxjs';
|
|
4
4
|
import {Query} from '../common/communication';
|
|
5
|
-
import {
|
|
6
|
-
import {BidiType, Direction, ForwardOrReverse, ModInfoType, MsgMode} from '../common/enums';
|
|
5
|
+
import {ModInfoType, MsgMode} from '../common/enums';
|
|
7
6
|
import {MsgBidiInfo, MsgModInfo} from './infoMsg';
|
|
8
7
|
|
|
9
8
|
/**
|
|
@@ -111,41 +110,30 @@ export default class InfoGroup
|
|
|
111
110
|
const type = buffer.readUInt16LE(2);
|
|
112
111
|
const info = buffer.readUInt32LE(4);
|
|
113
112
|
|
|
114
|
-
let data: BidiDirectionData | number = {};
|
|
115
|
-
switch (type) {
|
|
116
|
-
case BidiType.DIRECTION:
|
|
117
|
-
data.direction = this.parseEastWest(info);
|
|
118
|
-
data.directionChange = this.parseDirChange(info);
|
|
119
|
-
data.directionConfirm = this.parseDirectionConfirm(info);
|
|
120
|
-
data.forwardOrReverse = this.parseFwdRev(info);
|
|
121
|
-
break;
|
|
122
|
-
default:
|
|
123
|
-
data = info;
|
|
124
|
-
}
|
|
125
113
|
const msg = new MsgBidiInfo(MsgBidiInfo.header(mode, NID), type, undefined, info);
|
|
126
114
|
this.onBidiInfoChange.next(msg);
|
|
127
115
|
}
|
|
128
116
|
|
|
129
|
-
private parseEastWest(data: number)
|
|
130
|
-
{
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
117
|
+
// private parseEastWest(data: number)
|
|
118
|
+
// {
|
|
119
|
+
// if ((data & 0x02) == 0x02)
|
|
120
|
+
// return Direction.EAST;
|
|
121
|
+
// return Direction.WEST;
|
|
122
|
+
// }
|
|
135
123
|
|
|
136
|
-
private parseDirChange(data: number)
|
|
137
|
-
{
|
|
138
|
-
|
|
139
|
-
}
|
|
124
|
+
// private parseDirChange(data: number)
|
|
125
|
+
// {
|
|
126
|
+
// return (data & 0x04) == 0x04;
|
|
127
|
+
// }
|
|
140
128
|
|
|
141
|
-
private parseFwdRev(data: number)
|
|
142
|
-
{
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
private parseDirectionConfirm(data: number)
|
|
148
|
-
{
|
|
149
|
-
|
|
150
|
-
}
|
|
129
|
+
// private parseFwdRev(data: number)
|
|
130
|
+
// {
|
|
131
|
+
// if ((data & 0x01) == 0)
|
|
132
|
+
// return ForwardOrReverse.REVERSE;
|
|
133
|
+
// return ForwardOrReverse.FORWARD;
|
|
134
|
+
// }
|
|
135
|
+
// private parseDirectionConfirm(data: number)
|
|
136
|
+
// {
|
|
137
|
+
// return (data & 0x08) == 0x08;
|
|
138
|
+
// }
|
|
151
139
|
}
|
package/src/info/infoMsg.ts
CHANGED
|
@@ -40,4 +40,24 @@ export class MsgBidiInfo extends Message
|
|
|
40
40
|
nid(): number {return this.header.mode === MsgMode.REQ ? this.data[0].value as number : this.header.nid || 0}
|
|
41
41
|
type(): number {return this.data[this.header.mode === MsgMode.REQ ? 1 : 0].value as number}
|
|
42
42
|
info(): number | undefined {return this.data.length > 1 ? this.data[1].value as number : undefined}
|
|
43
|
+
|
|
44
|
+
public static dirEast(info: number)
|
|
45
|
+
{
|
|
46
|
+
return ((info & 0x02) == 0x02)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public static dirChanging(info: number)
|
|
50
|
+
{
|
|
51
|
+
return ((info & 0x04) == 0x04)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public static dirForward(info: number)
|
|
55
|
+
{
|
|
56
|
+
return ((info & 0x01) == 0x01)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public static dirConfirm(info: number)
|
|
60
|
+
{
|
|
61
|
+
return ((info & 0x08) == 0x08)
|
|
62
|
+
}
|
|
43
63
|
}
|
package/src/loco/vehicleGroup.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
2
|
import MX10 from '../MX10';
|
|
3
3
|
import {Subject} from 'rxjs';
|
|
4
|
-
import {CallFunctionData
|
|
5
|
-
import {Direction, Manual, MaxSpeedSteps, MsgMode, OperatingMode,
|
|
6
|
-
} from '../common/enums';
|
|
4
|
+
import {CallFunctionData} from '../common/models';
|
|
5
|
+
import {Direction, Manual, MaxSpeedSteps, MsgMode, OperatingMode, SpecialFxNr} from '../common/enums';
|
|
7
6
|
import {combineSpeedAndDirection} from '../common/speedUtils';
|
|
8
7
|
import { Query } from '../common/communication';
|
|
9
|
-
import { MsgVehicleLastCtl, MsgVehicleMode, MsgVehicleSpeed, MsgVehicleState } from './vehicleMsg';
|
|
8
|
+
import { MsgSpecialFx, MsgVehicleLastCtl, MsgVehicleMode, MsgVehicleSpeed, MsgVehicleState } from './vehicleMsg';
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
*
|
|
@@ -17,14 +16,15 @@ export default class VehicleGroup
|
|
|
17
16
|
public readonly onVehicleState = new Subject<MsgVehicleState>();
|
|
18
17
|
public readonly onVehicleLastCtl = new Subject<MsgVehicleLastCtl>();
|
|
19
18
|
public readonly onVehicleMode = new Subject<MsgVehicleMode>();
|
|
20
|
-
public readonly onVehicleSpeed = new Subject<MsgVehicleSpeed>();
|
|
19
|
+
public readonly onVehicleSpeed = new Subject<MsgVehicleSpeed>();
|
|
21
20
|
public readonly onCallFunction = new Subject<CallFunctionData>();
|
|
22
|
-
public readonly onCallSpecialFunction = new Subject<
|
|
21
|
+
public readonly onCallSpecialFunction = new Subject<MsgSpecialFx>();
|
|
23
22
|
|
|
24
23
|
private stateQ: Query<MsgVehicleState> | undefined = undefined;
|
|
25
24
|
private lastCtlQ: Query<MsgVehicleLastCtl> | undefined = undefined;
|
|
26
25
|
private modeQ: Query<MsgVehicleMode> | undefined = undefined;
|
|
27
26
|
private speedQ: Query<MsgVehicleSpeed> | undefined = undefined;
|
|
27
|
+
private sfxQ: Query<MsgSpecialFx> | undefined = undefined;
|
|
28
28
|
|
|
29
29
|
private mx10: MX10;
|
|
30
30
|
|
|
@@ -199,15 +199,61 @@ export default class VehicleGroup
|
|
|
199
199
|
]);
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
this.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
202
|
+
async getSpecialFx(nid: number, sfxNr: SpecialFxNr)
|
|
203
|
+
{
|
|
204
|
+
if(this.sfxQ !== undefined && !await this.sfxQ.lock()) {
|
|
205
|
+
this.mx10.logInfo.next("mx10.getSpecialFx: failed to acquire lock");
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
208
|
+
this.sfxQ = new Query(MsgSpecialFx.header(MsgMode.REQ, nid), this.onCallSpecialFunction);
|
|
209
|
+
this.sfxQ.tx = ((header) => {
|
|
210
|
+
const msg = new MsgSpecialFx(header, sfxNr);
|
|
211
|
+
// this.mx10.logInfo.next('sfx query tx: ' + JSON.stringify(msg));
|
|
212
|
+
this.mx10.sendMsg(msg);
|
|
213
|
+
});
|
|
214
|
+
this.sfxQ.match = ((msg) => {
|
|
215
|
+
// this.mx10.logInfo.next('sfx query rx: ' + JSON.stringify(msg));
|
|
216
|
+
return (msg.nid() === nid);
|
|
217
|
+
})
|
|
218
|
+
const rv = await this.sfxQ.run();
|
|
219
|
+
// this.mx10.logInfo.next("mx10.getSpecialFx.rv: " + JSON.stringify(rv));
|
|
220
|
+
this.sfxQ.unlock();
|
|
221
|
+
this.sfxQ = undefined;
|
|
222
|
+
return rv;
|
|
209
223
|
}
|
|
210
224
|
|
|
225
|
+
async setSpecialFx(nid: number, sfxNr: SpecialFxNr, state: number)
|
|
226
|
+
{
|
|
227
|
+
if(this.sfxQ !== undefined && !await this.sfxQ.lock()) {
|
|
228
|
+
this.mx10.logInfo.next("mx10.setSpecialFx: failed to acquire lock");
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
this.sfxQ = new Query(MsgSpecialFx.header(MsgMode.CMD, nid), this.onCallSpecialFunction);
|
|
232
|
+
this.sfxQ.tx = ((header) => {
|
|
233
|
+
const msg = new MsgSpecialFx(header, sfxNr, state);
|
|
234
|
+
// this.mx10.logInfo.next('sfx query tx: ' + JSON.stringify(msg));
|
|
235
|
+
this.mx10.sendMsg(msg);
|
|
236
|
+
});
|
|
237
|
+
this.sfxQ.match = ((msg) => {
|
|
238
|
+
// this.mx10.logInfo.next('sfx query rx: ' + JSON.stringify(msg));
|
|
239
|
+
return (msg.nid() === nid);
|
|
240
|
+
})
|
|
241
|
+
const rv = await this.sfxQ.run();
|
|
242
|
+
// this.mx10.logInfo.next("mx10.setSpecialFx.rv: " + JSON.stringify(rv));
|
|
243
|
+
this.sfxQ.unlock();
|
|
244
|
+
this.sfxQ = undefined;
|
|
245
|
+
return rv;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// changeSpecialFunction(vehicleAddress: number, specialFunctionMode: SpecialFunctionMode,
|
|
249
|
+
// specialFunctionStatus: Manual | ShuntingFunction | Direction) {
|
|
250
|
+
// this.mx10.sendData(0x02, 0x05, [
|
|
251
|
+
// {value: vehicleAddress, length: 2},
|
|
252
|
+
// {value: specialFunctionMode, length: 2},
|
|
253
|
+
// {value: specialFunctionStatus, length: 2},
|
|
254
|
+
// ]);
|
|
255
|
+
// }
|
|
256
|
+
|
|
211
257
|
// 0x02.0x10
|
|
212
258
|
activeModeTrain(vehicleAddress: number) {
|
|
213
259
|
return this.mx10.sendData(0x02, 0x10, [
|
|
@@ -288,17 +334,9 @@ export default class VehicleGroup
|
|
|
288
334
|
// 0x02.0x05
|
|
289
335
|
private parseVehicleSpecialFunction(size: number, mode: number, nid: number, buffer: Buffer)
|
|
290
336
|
{
|
|
291
|
-
if
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
const specialFunctionState = buffer.readUInt16LE(4);
|
|
295
|
-
|
|
296
|
-
this.onCallSpecialFunction.next({
|
|
297
|
-
nid: NID,
|
|
298
|
-
specialFunctionMode,
|
|
299
|
-
specialFunctionState,
|
|
300
|
-
});
|
|
301
|
-
}
|
|
337
|
+
if(!this.onCallSpecialFunction.observed)
|
|
338
|
+
return;
|
|
339
|
+
this.onCallSpecialFunction.next(MsgSpecialFx.fromBuffer(mode, buffer));
|
|
302
340
|
}
|
|
303
341
|
|
|
304
342
|
// 0x02.0x12
|
package/src/loco/vehicleMsg.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import { Header, Message } from "../common/communication";
|
|
3
3
|
import { Ranger } from "../common/utils";
|
|
4
|
-
import { Direction, MaxSpeedSteps, MsgMode, OperatingMode } from "../common/enums";
|
|
4
|
+
import { Direction, MaxSpeedSteps, MsgMode, OperatingMode, SpecialFxNr } from "../common/enums";
|
|
5
5
|
import { directACKBites, directionBites, eastWestBites_, emergencyStopB, speedBites____ } from "../common/bites";
|
|
6
6
|
|
|
7
7
|
|
|
@@ -162,4 +162,30 @@ export class MsgVehicleLastCtl extends Message
|
|
|
162
162
|
const msg = new MsgVehicleLastCtl(MsgVehicleLastCtl.header(mode, nid), type, ctlNid, seconds);
|
|
163
163
|
return msg;
|
|
164
164
|
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export class MsgSpecialFx extends Message
|
|
168
|
+
{
|
|
169
|
+
public static header = (mode: MsgMode, nid: number) => {return {group: 0x2, cmd: 0x5, mode, nid}}
|
|
170
|
+
|
|
171
|
+
constructor(header: Header, sfxNr: SpecialFxNr, state?: number)
|
|
172
|
+
{
|
|
173
|
+
super(header);
|
|
174
|
+
super.push({value: sfxNr || 0, length: 2});
|
|
175
|
+
if(header.mode === MsgMode.REQ)
|
|
176
|
+
return;
|
|
177
|
+
super.push({value: state || 0, length: 2});
|
|
178
|
+
}
|
|
179
|
+
nid(): number {return this.header.nid || 0}
|
|
180
|
+
sfxNr(): number {return this.data[0].value as number;}
|
|
181
|
+
state(): number | undefined {return this.data.length < 2 ? undefined : this.data[1].value as number;}
|
|
182
|
+
|
|
183
|
+
public static fromBuffer(mode: MsgMode, buffer: Buffer)
|
|
184
|
+
{
|
|
185
|
+
const nid = buffer.readUInt16LE(0);
|
|
186
|
+
const sfxNr = buffer.readUInt16LE(2);
|
|
187
|
+
const state = buffer.readUint16LE(4);
|
|
188
|
+
const msg = new MsgSpecialFx(MsgVehicleState.header(mode, nid), sfxNr, state);
|
|
189
|
+
return msg;
|
|
190
|
+
}
|
|
165
191
|
}
|