@zimo-elektronik/zcan 1.0.57 → 1.0.59
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/dist/MX10.d.ts +1 -2
- package/dist/MX10.js +25 -21
- package/dist/MX10.js.map +1 -1
- package/dist/accessory/accessoryCommandGroup.d.ts +5 -3
- package/dist/accessory/accessoryCommandGroup.js +24 -27
- package/dist/accessory/accessoryCommandGroup.js.map +1 -1
- package/dist/common/communication.d.ts +1 -0
- package/dist/common/communication.js +1 -0
- package/dist/common/communication.js.map +1 -1
- package/dist/common/models.d.ts +7 -1
- package/dist/loco/vehicleGroup.d.ts +1 -0
- package/dist/loco/vehicleGroup.js +7 -0
- package/dist/loco/vehicleGroup.js.map +1 -1
- package/dist/loco/vehicleMsg.d.ts +0 -1
- package/dist/loco/vehicleMsg.js +0 -1
- package/dist/loco/vehicleMsg.js.map +1 -1
- package/dist/network/networkGroup.d.ts +5 -6
- package/dist/network/networkGroup.js +42 -24
- package/dist/network/networkGroup.js.map +1 -1
- package/dist/network/networkMsg.d.ts +8 -0
- package/dist/network/networkMsg.js +16 -0
- package/dist/network/networkMsg.js.map +1 -1
- package/package.json +1 -1
- package/src/MX10.ts +36 -45
- package/src/accessory/accessoryCommandGroup.ts +99 -113
- package/src/common/communication.ts +3 -0
- package/src/common/models.ts +7 -1
- package/src/loco/vehicleGroup.ts +8 -8
- package/src/loco/vehicleMsg.ts +0 -1
- package/src/network/networkGroup.ts +74 -33
- package/src/network/networkMsg.ts +21 -0
|
@@ -1,15 +1,42 @@
|
|
|
1
1
|
import { Subject } from 'rxjs';
|
|
2
|
+
import { Query } from '../docs_entrypoint';
|
|
3
|
+
import { MsgPing } from './networkMsg';
|
|
4
|
+
import { MsgMode } from '../common/enums';
|
|
2
5
|
export default class NetworkGroup {
|
|
3
|
-
|
|
6
|
+
onPing = new Subject();
|
|
4
7
|
onPortClose = new Subject();
|
|
8
|
+
pingQ = undefined;
|
|
5
9
|
portCloseQ = undefined;
|
|
6
10
|
mx10;
|
|
7
|
-
pingTimeout = null;
|
|
8
11
|
constructor(mx10) {
|
|
9
12
|
this.mx10 = mx10;
|
|
10
13
|
}
|
|
11
|
-
ping(
|
|
12
|
-
this.
|
|
14
|
+
async ping(nid = 0xc000) {
|
|
15
|
+
if (this.pingQ !== undefined && !await this.pingQ.lock()) {
|
|
16
|
+
this.mx10.logInfo.next("mx10.ping: failed to acquire lock");
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
this.pingQ = new Query(MsgPing.header(MsgMode.CMD, nid), this.onPing);
|
|
20
|
+
this.pingQ.log = ((msg) => {
|
|
21
|
+
this.mx10.logInfo.next(msg);
|
|
22
|
+
});
|
|
23
|
+
this.pingQ.tx = ((header) => {
|
|
24
|
+
const msg = new MsgPing(header, nid);
|
|
25
|
+
this.mx10.logInfo.next('ping query tx: ' + JSON.stringify(msg));
|
|
26
|
+
this.mx10.sendMsg(msg, true);
|
|
27
|
+
});
|
|
28
|
+
this.pingQ.match = ((msg) => {
|
|
29
|
+
this.mx10.logInfo.next('ping query rx: ' + JSON.stringify(msg));
|
|
30
|
+
if (nid & 0xff)
|
|
31
|
+
return msg.header.nid === nid;
|
|
32
|
+
return ((msg.header.nid || 0) & 0xff00) === (nid & 0xff00);
|
|
33
|
+
});
|
|
34
|
+
this.pingQ.subscribe(false);
|
|
35
|
+
const rv = await this.pingQ.run(100);
|
|
36
|
+
this.mx10.logInfo.next("mx10.ping.rv: " + JSON.stringify(rv));
|
|
37
|
+
this.pingQ.unlock();
|
|
38
|
+
this.pingQ = undefined;
|
|
39
|
+
return rv;
|
|
13
40
|
}
|
|
14
41
|
async portClose() {
|
|
15
42
|
this.mx10.sendData(0x0a, 0x07, [{ value: this.mx10.myNID, length: 2 }], 0b01);
|
|
@@ -18,33 +45,24 @@ export default class NetworkGroup {
|
|
|
18
45
|
parse(size, command, mode, nid, buffer) {
|
|
19
46
|
switch (command) {
|
|
20
47
|
case 0x00:
|
|
21
|
-
this.
|
|
48
|
+
this.parsePing(size, mode, nid, buffer);
|
|
22
49
|
break;
|
|
23
50
|
}
|
|
24
51
|
}
|
|
25
|
-
|
|
26
|
-
if (!this.
|
|
52
|
+
parsePing(size, mode, nid, buffer) {
|
|
53
|
+
if (!this.onPing.observed)
|
|
27
54
|
return;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
this.mx10.connected = true;
|
|
33
|
-
if (this.pingTimeout)
|
|
34
|
-
clearTimeout(this.pingTimeout);
|
|
35
|
-
this.pingTimeout = setTimeout(() => {
|
|
36
|
-
this.mx10.connected = false;
|
|
37
|
-
this.onPingResponse.next({
|
|
38
|
-
connected: this.mx10.connected,
|
|
39
|
-
});
|
|
40
|
-
this.mx10.logInfo.next('No ping for 2 seconds, disconnected');
|
|
41
|
-
}, 2000);
|
|
55
|
+
this.mx10.logInfo.next('parsePing from 0x' + nid.toString(16) + ': ' + JSON.stringify(buffer));
|
|
56
|
+
if (mode < MsgMode.EVT) {
|
|
57
|
+
const nid = buffer.readUInt16LE(0);
|
|
58
|
+
this.onPing.next(new MsgPing(MsgPing.header(mode, nid)));
|
|
42
59
|
}
|
|
43
60
|
else {
|
|
44
|
-
|
|
45
|
-
|
|
61
|
+
const masterUid = buffer.readUInt32LE(0);
|
|
62
|
+
const type = buffer.readUInt16LE(4);
|
|
63
|
+
const session = buffer.readUInt16LE(6);
|
|
64
|
+
this.onPing.next(new MsgPing(MsgPing.header(mode, nid), masterUid, type, session));
|
|
46
65
|
}
|
|
47
|
-
this.onPingResponse.next({ connected: this.mx10.connected });
|
|
48
66
|
}
|
|
49
67
|
}
|
|
50
68
|
//# sourceMappingURL=networkGroup.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"networkGroup.js","sourceRoot":"","sources":["../../src/network/networkGroup.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,OAAO,EAAC,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"networkGroup.js","sourceRoot":"","sources":["../../src/network/networkGroup.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,3 +11,11 @@ export declare class MsgPortClose extends Message {
|
|
|
11
11
|
static header(mode: MsgMode, nid: number): Header;
|
|
12
12
|
constructor(header: Header, myNid: number);
|
|
13
13
|
}
|
|
14
|
+
export declare class MsgPing extends Message {
|
|
15
|
+
static header(mode: MsgMode, nid: number): Header;
|
|
16
|
+
constructor(header: Header, masterUid?: number, type?: number, session?: number);
|
|
17
|
+
nid(): number;
|
|
18
|
+
masterUid(): number;
|
|
19
|
+
type(): number;
|
|
20
|
+
session(): number;
|
|
21
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Message } from "../common/communication";
|
|
2
|
+
import { MsgMode } from "../common/enums";
|
|
2
3
|
export class MsgPortOpen extends Message {
|
|
3
4
|
static header(mode, nid) { return { group: 0x1a, cmd: 0x6, mode: mode, nid: nid }; }
|
|
4
5
|
constructor(header, clientId, comFlags = 0xffffffff, clientName) {
|
|
@@ -19,4 +20,19 @@ export class MsgPortClose extends Message {
|
|
|
19
20
|
super.push({ value: myNid, length: 2 });
|
|
20
21
|
}
|
|
21
22
|
}
|
|
23
|
+
export class MsgPing extends Message {
|
|
24
|
+
static header(mode, nid) { return { group: 0xa, cmd: 0x0, mode: mode, nid: nid }; }
|
|
25
|
+
constructor(header, masterUid, type, session) {
|
|
26
|
+
super(header);
|
|
27
|
+
if (header.mode < MsgMode.EVT)
|
|
28
|
+
return;
|
|
29
|
+
super.push({ value: masterUid || 0, length: 4 });
|
|
30
|
+
super.push({ value: type || 0, length: 2 });
|
|
31
|
+
super.push({ value: session || 0, length: 2 });
|
|
32
|
+
}
|
|
33
|
+
nid() { return this.header.nid; }
|
|
34
|
+
masterUid() { return this.data[0].value; }
|
|
35
|
+
type() { return this.data[0].value; }
|
|
36
|
+
session() { return this.data[0].value; }
|
|
37
|
+
}
|
|
22
38
|
//# sourceMappingURL=networkMsg.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"networkMsg.js","sourceRoot":"","sources":["../../src/network/networkMsg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,OAAO,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"networkMsg.js","sourceRoot":"","sources":["../../src/network/networkMsg.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": "https://github.com/ZIMO-Elektronik/zcan",
|
|
8
|
-
"version": "1.0.
|
|
8
|
+
"version": "1.0.59",
|
|
9
9
|
"scripts": {
|
|
10
10
|
"start": "node dist/main.js",
|
|
11
11
|
"start:dev": "nodemon --ext js,ts,json,env --exec \"node --experimental-specifier-resolution=node --loader ts-node/esm\" src/main.ts",
|
package/src/MX10.ts
CHANGED
|
@@ -3,27 +3,10 @@
|
|
|
3
3
|
import {Buffer} from 'buffer';
|
|
4
4
|
import {interval, Subject} from 'rxjs';
|
|
5
5
|
import {Message} from './common/communication';
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
FileTransferGroup,
|
|
11
|
-
InfoGroup,
|
|
12
|
-
LanDataGroup,
|
|
13
|
-
LanInfoGroup,
|
|
14
|
-
LanNetworkGroup,
|
|
15
|
-
LanLocoStateGroup,
|
|
16
|
-
LanZimoProgrammableScriptGroup,
|
|
17
|
-
NetworkGroup,
|
|
18
|
-
PropertyConfigGroup,
|
|
19
|
-
RailwayControlGroup,
|
|
20
|
-
SystemControlGroup,
|
|
21
|
-
TrackCfgGroup,
|
|
22
|
-
TrainControlGroup,
|
|
23
|
-
VehicleGroup,
|
|
24
|
-
ZimoProgrammableScriptGroup,
|
|
25
|
-
MsgMode,
|
|
26
|
-
} from './';
|
|
6
|
+
import {AccessoryCommandGroup, DataGroup, FileControlGroup, FileTransferGroup, InfoGroup, LanDataGroup, LanInfoGroup,
|
|
7
|
+
LanNetworkGroup, LanLocoStateGroup, LanZimoProgrammableScriptGroup, NetworkGroup, PropertyConfigGroup,
|
|
8
|
+
RailwayControlGroup, SystemControlGroup, TrackCfgGroup, TrainControlGroup, VehicleGroup,
|
|
9
|
+
ZimoProgrammableScriptGroup, MsgMode} from './';
|
|
27
10
|
import {CreateSocketFunction, NIDGenerator, Socket, ZcanDataArray} from './common/communication';
|
|
28
11
|
import {delay} from './common/utils';
|
|
29
12
|
import ExtendedASCII from './common/extendedAscii';
|
|
@@ -61,7 +44,6 @@ export default class MX10
|
|
|
61
44
|
readonly logError = new Subject<string>();
|
|
62
45
|
readonly logWarning = new Subject<string>();
|
|
63
46
|
readonly logInfo = new Subject<string>();
|
|
64
|
-
readonly connectionTimeout: number;
|
|
65
47
|
|
|
66
48
|
private mx10Socket: Socket | null = null;
|
|
67
49
|
private incomingPort = 14521;
|
|
@@ -76,24 +58,26 @@ export default class MX10
|
|
|
76
58
|
private readonly reconnectionTime: number = 0;
|
|
77
59
|
|
|
78
60
|
|
|
79
|
-
constructor(nidGeneratorFunction: NIDGenerator, clientName: string, clientId: number,
|
|
80
|
-
connectionTimeout = 1000, debugCommunication = false)
|
|
61
|
+
constructor(nidGeneratorFunction: NIDGenerator, clientName: string, clientId: number, debugCommunication = false)
|
|
81
62
|
{
|
|
82
63
|
this.nidGeneratorFunction = nidGeneratorFunction;
|
|
83
|
-
this.connectionTimeout = connectionTimeout;
|
|
84
64
|
this.debugCommunication = debugCommunication;
|
|
85
|
-
this.reconnectionTime =
|
|
65
|
+
this.reconnectionTime = 2000;
|
|
86
66
|
this.clientName = clientName;
|
|
87
67
|
this.clientId = clientId;
|
|
88
68
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
69
|
+
interval(1000).subscribe(async () => {
|
|
70
|
+
if(this.connected) {
|
|
71
|
+
this.logInfo.next('ping, weil connected');
|
|
72
|
+
const msg = await this.network.ping(this.mx10NID);
|
|
73
|
+
if(msg)
|
|
74
|
+
this.lastPing = Date.now();
|
|
75
|
+
else if(Date.now() - this.lastPing > 2000) {
|
|
76
|
+
this.logInfo.next('No ping for 2 seconds, disconnected');
|
|
77
|
+
this.connected = false;
|
|
78
|
+
this.closeSocket();
|
|
79
|
+
this.logError.next('.mx10.connection.not_connected');
|
|
80
|
+
}
|
|
97
81
|
}
|
|
98
82
|
});
|
|
99
83
|
}
|
|
@@ -101,11 +85,12 @@ export default class MX10
|
|
|
101
85
|
async initSocket(createSocketFunction: CreateSocketFunction, ipAddress: string,
|
|
102
86
|
incomingPort = 14521, outgoingPort = 14520)
|
|
103
87
|
{
|
|
104
|
-
this.mx10IP = ipAddress;
|
|
105
88
|
this.incomingPort = incomingPort;
|
|
106
89
|
this.outgoingPort = outgoingPort;
|
|
90
|
+
this.mx10IP = ipAddress;
|
|
91
|
+
// this.mx10NID = 0xc000 | Number.parseInt(ipAddress.split('.')[3]);
|
|
107
92
|
|
|
108
|
-
if
|
|
93
|
+
if(this.mx10Socket == null)
|
|
109
94
|
{
|
|
110
95
|
const socket = (this.mx10Socket = createSocketFunction({type: 'udp4'}) as Socket);
|
|
111
96
|
|
|
@@ -117,18 +102,23 @@ export default class MX10
|
|
|
117
102
|
|
|
118
103
|
this.mx10Socket.on('message', this.readRawData.bind(this));
|
|
119
104
|
this.myNID = await this.nidGeneratorFunction();
|
|
120
|
-
const
|
|
121
|
-
if(
|
|
122
|
-
this.mx10NID = ack.header.nid || 0;
|
|
105
|
+
const ping = await this.network.ping();
|
|
106
|
+
if(ping) {
|
|
123
107
|
this.connected = true;
|
|
108
|
+
} else {
|
|
109
|
+
const ack = await this.lanNetwork.portOpen(this.clientName, this.clientId);
|
|
110
|
+
if(ack) {
|
|
111
|
+
this.mx10NID = ack.header.nid || 0;
|
|
112
|
+
this.connected = true;
|
|
113
|
+
}
|
|
124
114
|
}
|
|
125
|
-
this.connected = true; // since subsequent portOpen cmd don't seem to be answered..
|
|
126
|
-
await delay(this.connectionTimeout);
|
|
115
|
+
// this.connected = true; // since subsequent portOpen cmd don't seem to be answered..
|
|
116
|
+
// await delay(this.connectionTimeout);
|
|
127
117
|
|
|
128
|
-
if
|
|
118
|
+
if(!this.connected) {
|
|
129
119
|
await this.closeSocket();
|
|
130
120
|
// throw new Error('mx10.connection.timeout');
|
|
131
|
-
throw new Error('mx10.connection.not_connected');
|
|
121
|
+
// throw new Error('mx10.connection.not_connected');
|
|
132
122
|
}
|
|
133
123
|
}
|
|
134
124
|
}
|
|
@@ -148,7 +138,7 @@ export default class MX10
|
|
|
148
138
|
this.connected = false;
|
|
149
139
|
this.mx10NID = 0;
|
|
150
140
|
this.lanNetwork.portOpen(this.clientName, this.clientId);
|
|
151
|
-
this.network.ping(
|
|
141
|
+
this.network.ping();
|
|
152
142
|
}
|
|
153
143
|
}, this.reconnectionTime);
|
|
154
144
|
}
|
|
@@ -171,6 +161,7 @@ export default class MX10
|
|
|
171
161
|
|
|
172
162
|
sendMsg(msg: Message, force = false)
|
|
173
163
|
{
|
|
164
|
+
// Message.log = (msg) => this.logInfo.next(msg);
|
|
174
165
|
const buffer = msg.udp(this.myNID);
|
|
175
166
|
this.logInfo.next("mx10.sendMsg: " + JSON.stringify(buffer));
|
|
176
167
|
this.send(buffer, force);
|
|
@@ -231,7 +222,7 @@ export default class MX10
|
|
|
231
222
|
private send(message: Buffer, force = false)
|
|
232
223
|
{
|
|
233
224
|
if(!this.connected && !force) {
|
|
234
|
-
this.logError.next('.mx10.connection.not_connected');
|
|
225
|
+
// this.logError.next('.mx10.connection.not_connected');
|
|
235
226
|
this.logInfo.next('unable to send ' + JSON.stringify(message));
|
|
236
227
|
return;
|
|
237
228
|
}
|
|
@@ -1,133 +1,119 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
2
|
import {Subject} from 'rxjs';
|
|
3
3
|
import MX10 from '../MX10';
|
|
4
|
-
import {
|
|
5
|
-
AccessoryModeData,
|
|
6
|
-
AccessoryPinData,
|
|
7
|
-
AccessoryPortData,
|
|
8
|
-
} from '../common/models';
|
|
4
|
+
import {AccessoryModeData, AccessoryPin4Data, AccessoryPin6Data, AccessoryPortData} from '../common/models';
|
|
9
5
|
import {AccessoryMode} from '../common/enums';
|
|
10
6
|
|
|
11
7
|
/**
|
|
12
8
|
*
|
|
13
9
|
* @category Groups
|
|
14
10
|
*/
|
|
15
|
-
export default class AccessoryCommandGroup
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
export default class AccessoryCommandGroup
|
|
12
|
+
{
|
|
13
|
+
public readonly onAccessoryMode = new Subject<AccessoryModeData>();
|
|
14
|
+
public readonly onAccessoryPort = new Subject<AccessoryPortData>();
|
|
15
|
+
public readonly onAccessoryPin4 = new Subject<AccessoryPin4Data>();
|
|
16
|
+
public readonly onAccessoryPin6 = new Subject<AccessoryPin6Data>();
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
private mx10: MX10;
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
constructor(mx10: MX10)
|
|
21
|
+
{
|
|
22
|
+
this.mx10 = mx10;
|
|
23
|
+
}
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
accessoryModeByNid(nid: number)
|
|
26
|
+
{
|
|
27
|
+
this.mx10.sendData(0x01, 0x01, [{value: nid, length: 2}], 0b00);
|
|
28
|
+
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
[
|
|
35
|
-
{value: nid, length: 2},
|
|
36
|
-
{value: 0, length: 2},
|
|
37
|
-
],
|
|
38
|
-
0b00,
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
accessoryPortByPin(nid: number, pin: number, state: number) {
|
|
42
|
-
this.mx10.sendData(
|
|
43
|
-
0x01,
|
|
44
|
-
0x04,
|
|
45
|
-
[
|
|
46
|
-
{value: nid, length: 2},
|
|
47
|
-
{value: pin, length: 1},
|
|
48
|
-
{value: state, length: 1},
|
|
49
|
-
],
|
|
50
|
-
0b01,
|
|
51
|
-
);
|
|
52
|
-
}
|
|
30
|
+
accessoryPortByNid(nid: number)
|
|
31
|
+
{
|
|
32
|
+
this.mx10.sendData(0x01, 0x02, [{value: nid, length: 2}, {value: 0, length: 2}], 0b00);
|
|
33
|
+
}
|
|
53
34
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
buffer: Buffer,
|
|
60
|
-
) {
|
|
61
|
-
switch (command) {
|
|
62
|
-
case 0x01:
|
|
63
|
-
this.parseAccessoryMode(size, mode, nid, buffer);
|
|
64
|
-
break;
|
|
65
|
-
case 0x02:
|
|
66
|
-
this.parseAccessoryPort(size, mode, nid, buffer);
|
|
67
|
-
break;
|
|
68
|
-
case 0x04:
|
|
69
|
-
this.parseAccessoryPin(size, mode, nid, buffer);
|
|
70
|
-
break;
|
|
71
|
-
default:
|
|
72
|
-
this.mx10.logInfo.next('accessoryCommandGroup command ' + command + ' not parsed: ' + JSON.stringify(buffer));
|
|
73
|
-
}
|
|
74
|
-
}
|
|
35
|
+
accessoryPortByPin(nid: number, pin: number, state: number)
|
|
36
|
+
{
|
|
37
|
+
this.mx10.sendData(0x01, 0x04,
|
|
38
|
+
[{value: nid, length: 2}, {value: pin, length: 1}, {value: state, length: 1}], 0b01);
|
|
39
|
+
}
|
|
75
40
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
41
|
+
parse(size: number, command: number, mode: number, nid: number, buffer: Buffer)
|
|
42
|
+
{
|
|
43
|
+
switch (command) {
|
|
44
|
+
case 0x01:
|
|
45
|
+
this.parseAccessoryMode(size, mode, nid, buffer);
|
|
46
|
+
break;
|
|
47
|
+
case 0x02:
|
|
48
|
+
this.parseAccessoryPort(size, mode, nid, buffer);
|
|
49
|
+
break;
|
|
50
|
+
case 0x04:
|
|
51
|
+
this.parseAccessoryPin4(size, mode, nid, buffer);
|
|
52
|
+
break;
|
|
53
|
+
case 0x06:
|
|
54
|
+
this.parseAccessoryPin6(size, mode, nid, buffer);
|
|
55
|
+
break;
|
|
56
|
+
default:
|
|
57
|
+
this.mx10.logInfo.next('accessoryCommandGroup command ' + command + ' not parsed: ' + JSON.stringify(buffer));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
80
60
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
61
|
+
parseAccessoryMode(size: number, mode: number, nid: number, buffer: Buffer)
|
|
62
|
+
{
|
|
63
|
+
if (this.onAccessoryMode.observed) {
|
|
64
|
+
const deviceNID = buffer.readUInt16LE(0);
|
|
65
|
+
const mode = buffer.readUInt16LE(2);
|
|
66
|
+
let parsedMode: AccessoryMode;
|
|
67
|
+
switch (mode) {
|
|
68
|
+
case 1:
|
|
69
|
+
parsedMode = AccessoryMode.PAIRED;
|
|
70
|
+
break;
|
|
71
|
+
case 2:
|
|
72
|
+
parsedMode = AccessoryMode.SINGLE;
|
|
73
|
+
break;
|
|
74
|
+
default:
|
|
75
|
+
parsedMode = AccessoryMode.UNKNOWN;
|
|
76
|
+
}
|
|
77
|
+
if (deviceNID) {
|
|
78
|
+
this.onAccessoryMode.next({nid: deviceNID, mode: parsedMode});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
92
82
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
83
|
+
parseAccessoryPort(size: number, mode: number, nid: number, buffer: Buffer)
|
|
84
|
+
{
|
|
85
|
+
if (this.onAccessoryPort.observed) {
|
|
86
|
+
const deviceNID = buffer.readUInt16LE(0);
|
|
87
|
+
const type = buffer.readUInt16LE(2);
|
|
88
|
+
const port = buffer.readUInt8(4); // only 1.st byte represents state of pins
|
|
89
|
+
if (deviceNID) {
|
|
90
|
+
this.onAccessoryPort.next({nid: deviceNID, type, port});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
101
94
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
95
|
+
parseAccessoryPin4(size: number, mode: number, nid: number, buffer: Buffer)
|
|
96
|
+
{
|
|
97
|
+
if (this.onAccessoryPin4.observed) {
|
|
98
|
+
const deviceNID = buffer.readUInt16LE(0);
|
|
99
|
+
const pin = buffer.readUInt8(2);
|
|
100
|
+
const state = buffer.readUInt8(3);
|
|
101
|
+
if (deviceNID) {
|
|
102
|
+
this.onAccessoryPin4.next({nid: deviceNID, pin, state});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
107
106
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const deviceNID = buffer.readUInt16LE(0);
|
|
121
|
-
const pin = buffer.readUInt8(2);
|
|
122
|
-
const state = buffer.readUInt8(3);
|
|
123
|
-
|
|
124
|
-
if (deviceNID) {
|
|
125
|
-
this.onAccessoryPin.next({
|
|
126
|
-
nid: deviceNID,
|
|
127
|
-
pin,
|
|
128
|
-
state,
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
107
|
+
parseAccessoryPin6(size: number, mode: number, nid: number, buffer: Buffer)
|
|
108
|
+
{
|
|
109
|
+
if (this.onAccessoryPin6.observed) {
|
|
110
|
+
const deviceNID = buffer.readUInt16LE(0);
|
|
111
|
+
const pin = buffer.readUInt8(2);
|
|
112
|
+
const type = buffer.readUInt8(3);
|
|
113
|
+
const state = buffer.readUInt16LE(4);
|
|
114
|
+
if (deviceNID) {
|
|
115
|
+
this.onAccessoryPin6.next({nid: deviceNID, pin, type, state});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
133
119
|
}
|
|
@@ -21,6 +21,8 @@ export type ZcanDataArray = ZcanData[];
|
|
|
21
21
|
|
|
22
22
|
export class Message
|
|
23
23
|
{
|
|
24
|
+
public static log: (msg: string) => void = () => {};
|
|
25
|
+
|
|
24
26
|
header: Header;
|
|
25
27
|
data: ZcanDataArray;
|
|
26
28
|
|
|
@@ -55,6 +57,7 @@ export class Message
|
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
this.data.forEach((element) => {
|
|
60
|
+
// Message.log('offset = ' + offset + ', element: ' + JSON.stringify(element) + ', buffer: ' + JSON.stringify(buffer));
|
|
58
61
|
if (typeof element.value === 'string') {
|
|
59
62
|
ExtendedASCII.str2byte(element.value, buffer, offset, element.length);
|
|
60
63
|
offset += element.length;
|
package/src/common/models.ts
CHANGED
|
@@ -268,8 +268,14 @@ export interface AccessoryPortData {
|
|
|
268
268
|
type: number;
|
|
269
269
|
port: number;
|
|
270
270
|
}
|
|
271
|
-
export interface
|
|
271
|
+
export interface AccessoryPin4Data {
|
|
272
272
|
nid: number;
|
|
273
273
|
pin: number;
|
|
274
274
|
state: number;
|
|
275
275
|
}
|
|
276
|
+
export interface AccessoryPin6Data {
|
|
277
|
+
nid: number;
|
|
278
|
+
pin: number;
|
|
279
|
+
type: number;
|
|
280
|
+
state: number;
|
|
281
|
+
}
|
package/src/loco/vehicleGroup.ts
CHANGED
|
@@ -192,14 +192,14 @@ export default class VehicleGroup
|
|
|
192
192
|
]);
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
195
|
+
callFunction(vehicleAddress: number, functionId: number, functionStatus: boolean)
|
|
196
|
+
{
|
|
197
|
+
this.mx10.sendData(0x02, 0x04, [
|
|
198
|
+
{value: vehicleAddress, length: 2},
|
|
199
|
+
{value: functionId, length: 2},
|
|
200
|
+
{value: Number(functionStatus), length: 2},
|
|
201
|
+
]);
|
|
202
|
+
}
|
|
203
203
|
|
|
204
204
|
async getFx(nid: number, fxNr: number)
|
|
205
205
|
{
|
package/src/loco/vehicleMsg.ts
CHANGED
|
@@ -9,7 +9,6 @@ export class MsgVehicleMode extends Message
|
|
|
9
9
|
{
|
|
10
10
|
public static header = (mode: MsgMode, nid: number) => {return {group: 0x2, cmd: 0x1, mode, nid}}
|
|
11
11
|
public static rxDelay = () => {return this.rxTiming.now()}
|
|
12
|
-
public static log: (msg: string) => void = () => {};
|
|
13
12
|
|
|
14
13
|
private static rxTiming = new Ranger({min: 5, max: 20, now: 5});
|
|
15
14
|
|