jmri-client 4.0.0 → 4.1.1
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/browser/jmri-client.js +212 -0
- package/dist/cjs/client.js +48 -0
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/managers/index.js +1 -0
- package/dist/cjs/managers/light-manager.js +111 -0
- package/dist/cjs/mocks/mock-data.js +7 -0
- package/dist/cjs/mocks/mock-response-manager.js +41 -0
- package/dist/cjs/types/jmri-messages.js +28 -1
- package/dist/esm/client.js +48 -0
- package/dist/esm/index.js +2 -2
- package/dist/esm/managers/index.js +1 -0
- package/dist/esm/managers/light-manager.js +107 -0
- package/dist/esm/mocks/mock-data.js +7 -0
- package/dist/esm/mocks/mock-response-manager.js +42 -1
- package/dist/esm/types/jmri-messages.js +26 -0
- package/dist/types/client.d.ts +30 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/managers/index.d.ts +1 -0
- package/dist/types/managers/light-manager.d.ts +47 -0
- package/dist/types/mocks/mock-data.d.ts +30 -0
- package/dist/types/mocks/mock-response-manager.d.ts +10 -1
- package/dist/types/types/events.d.ts +2 -1
- package/dist/types/types/jmri-messages.d.ts +33 -1
- package/docs/API.md +46 -1
- package/docs/EXAMPLES.md +31 -0
- package/docs/MOCK_MODE.md +16 -0
- package/package.json +1 -1
|
@@ -638,6 +638,23 @@ function turnoutStateToString(state) {
|
|
|
638
638
|
return "UNKNOWN";
|
|
639
639
|
}
|
|
640
640
|
}
|
|
641
|
+
var LightState = /* @__PURE__ */ ((LightState2) => {
|
|
642
|
+
LightState2[LightState2["UNKNOWN"] = 0] = "UNKNOWN";
|
|
643
|
+
LightState2[LightState2["ON"] = 2] = "ON";
|
|
644
|
+
LightState2[LightState2["OFF"] = 4] = "OFF";
|
|
645
|
+
return LightState2;
|
|
646
|
+
})(LightState || {});
|
|
647
|
+
function lightStateToString(state) {
|
|
648
|
+
switch (state) {
|
|
649
|
+
case 2 /* ON */:
|
|
650
|
+
return "ON";
|
|
651
|
+
case 4 /* OFF */:
|
|
652
|
+
return "OFF";
|
|
653
|
+
case 0 /* UNKNOWN */:
|
|
654
|
+
default:
|
|
655
|
+
return "UNKNOWN";
|
|
656
|
+
}
|
|
657
|
+
}
|
|
641
658
|
|
|
642
659
|
// src/mocks/mock-data.ts
|
|
643
660
|
var mockData = {
|
|
@@ -823,6 +840,13 @@ var mockData = {
|
|
|
823
840
|
}
|
|
824
841
|
}
|
|
825
842
|
},
|
|
843
|
+
"light": {
|
|
844
|
+
"list": [
|
|
845
|
+
{ "type": "light", "data": { "name": "IL1", "userName": "Yard Light", "comment": null, "properties": [], "state": 4 } },
|
|
846
|
+
{ "type": "light", "data": { "name": "IL2", "userName": "Platform Light", "comment": null, "properties": [], "state": 4 } },
|
|
847
|
+
{ "type": "light", "data": { "name": "IL3", "userName": "Signal Lamp", "comment": null, "properties": [], "state": 2 } }
|
|
848
|
+
]
|
|
849
|
+
},
|
|
826
850
|
"turnout": {
|
|
827
851
|
"list": [
|
|
828
852
|
{ "type": "turnout", "data": { "name": "LT1", "userName": "Main Diverge", "state": 2 } },
|
|
@@ -868,6 +892,11 @@ var mockData = {
|
|
|
868
892
|
var MockResponseManager = class {
|
|
869
893
|
constructor(options = {}) {
|
|
870
894
|
this.throttles = /* @__PURE__ */ new Map();
|
|
895
|
+
this.lights = /* @__PURE__ */ new Map([
|
|
896
|
+
["IL1", 4 /* OFF */],
|
|
897
|
+
["IL2", 4 /* OFF */],
|
|
898
|
+
["IL3", 2 /* ON */]
|
|
899
|
+
]);
|
|
871
900
|
this.turnouts = /* @__PURE__ */ new Map([
|
|
872
901
|
["LT1", 2 /* CLOSED */],
|
|
873
902
|
["LT2", 2 /* CLOSED */],
|
|
@@ -892,6 +921,8 @@ var MockResponseManager = class {
|
|
|
892
921
|
return this.getRosterResponse(message);
|
|
893
922
|
case "throttle":
|
|
894
923
|
return this.getThrottleResponse(message);
|
|
924
|
+
case "light":
|
|
925
|
+
return this.getLightResponse(message);
|
|
895
926
|
case "turnout":
|
|
896
927
|
return this.getTurnoutResponse(message);
|
|
897
928
|
case "ping":
|
|
@@ -1007,6 +1038,26 @@ var MockResponseManager = class {
|
|
|
1007
1038
|
data: {}
|
|
1008
1039
|
};
|
|
1009
1040
|
}
|
|
1041
|
+
/**
|
|
1042
|
+
* Get light response
|
|
1043
|
+
*/
|
|
1044
|
+
getLightResponse(message) {
|
|
1045
|
+
if (message.method === "list") {
|
|
1046
|
+
return {
|
|
1047
|
+
type: "light",
|
|
1048
|
+
data: JSON.parse(JSON.stringify(mockData.light.list))
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
const name = message.data?.name;
|
|
1052
|
+
if (!name) {
|
|
1053
|
+
return { type: "light", data: { name: "", state: 0 /* UNKNOWN */ } };
|
|
1054
|
+
}
|
|
1055
|
+
if (message.method === "post" && message.data?.state !== void 0) {
|
|
1056
|
+
this.lights.set(name, message.data.state);
|
|
1057
|
+
}
|
|
1058
|
+
const state = this.lights.get(name) ?? 0 /* UNKNOWN */;
|
|
1059
|
+
return { type: "light", data: { name, state } };
|
|
1060
|
+
}
|
|
1010
1061
|
/**
|
|
1011
1062
|
* Get turnout response
|
|
1012
1063
|
*/
|
|
@@ -1057,6 +1108,12 @@ var MockResponseManager = class {
|
|
|
1057
1108
|
getThrottles() {
|
|
1058
1109
|
return this.throttles;
|
|
1059
1110
|
}
|
|
1111
|
+
/**
|
|
1112
|
+
* Get all light states (for testing)
|
|
1113
|
+
*/
|
|
1114
|
+
getLights() {
|
|
1115
|
+
return this.lights;
|
|
1116
|
+
}
|
|
1060
1117
|
/**
|
|
1061
1118
|
* Get all turnout states (for testing)
|
|
1062
1119
|
*/
|
|
@@ -1069,6 +1126,11 @@ var MockResponseManager = class {
|
|
|
1069
1126
|
reset() {
|
|
1070
1127
|
this.powerState = 4 /* OFF */;
|
|
1071
1128
|
this.throttles.clear();
|
|
1129
|
+
this.lights = /* @__PURE__ */ new Map([
|
|
1130
|
+
["IL1", 4 /* OFF */],
|
|
1131
|
+
["IL2", 4 /* OFF */],
|
|
1132
|
+
["IL3", 2 /* ON */]
|
|
1133
|
+
]);
|
|
1072
1134
|
this.turnouts = /* @__PURE__ */ new Map([
|
|
1073
1135
|
["LT1", 2 /* CLOSED */],
|
|
1074
1136
|
["LT2", 2 /* CLOSED */],
|
|
@@ -1891,6 +1953,104 @@ var TurnoutManager = class extends import_index.default {
|
|
|
1891
1953
|
}
|
|
1892
1954
|
};
|
|
1893
1955
|
|
|
1956
|
+
// src/managers/light-manager.ts
|
|
1957
|
+
var LightManager = class extends import_index.default {
|
|
1958
|
+
constructor(client) {
|
|
1959
|
+
super();
|
|
1960
|
+
this.lights = /* @__PURE__ */ new Map();
|
|
1961
|
+
this.client = client;
|
|
1962
|
+
this.client.on("update", (message) => {
|
|
1963
|
+
if (message.type === "light") {
|
|
1964
|
+
this.handleLightUpdate(message);
|
|
1965
|
+
}
|
|
1966
|
+
});
|
|
1967
|
+
}
|
|
1968
|
+
/**
|
|
1969
|
+
* Get the current state of a light.
|
|
1970
|
+
* Also registers a server-side listener so subsequent changes are pushed.
|
|
1971
|
+
*/
|
|
1972
|
+
async getLight(name) {
|
|
1973
|
+
const message = {
|
|
1974
|
+
type: "light",
|
|
1975
|
+
data: { name }
|
|
1976
|
+
};
|
|
1977
|
+
const response = await this.client.request(message);
|
|
1978
|
+
const state = response.data?.state ?? 0 /* UNKNOWN */;
|
|
1979
|
+
this.lights.set(name, state);
|
|
1980
|
+
return state;
|
|
1981
|
+
}
|
|
1982
|
+
/**
|
|
1983
|
+
* Set a light to the given state
|
|
1984
|
+
*/
|
|
1985
|
+
async setLight(name, state) {
|
|
1986
|
+
const message = {
|
|
1987
|
+
type: "light",
|
|
1988
|
+
method: "post",
|
|
1989
|
+
data: { name, state }
|
|
1990
|
+
};
|
|
1991
|
+
await this.client.request(message);
|
|
1992
|
+
const oldState = this.lights.get(name);
|
|
1993
|
+
this.lights.set(name, state);
|
|
1994
|
+
if (oldState !== state) {
|
|
1995
|
+
this.emit("light:changed", name, state);
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
/**
|
|
1999
|
+
* Turn a light on
|
|
2000
|
+
*/
|
|
2001
|
+
async turnOnLight(name) {
|
|
2002
|
+
return this.setLight(name, 2 /* ON */);
|
|
2003
|
+
}
|
|
2004
|
+
/**
|
|
2005
|
+
* Turn a light off
|
|
2006
|
+
*/
|
|
2007
|
+
async turnOffLight(name) {
|
|
2008
|
+
return this.setLight(name, 4 /* OFF */);
|
|
2009
|
+
}
|
|
2010
|
+
/**
|
|
2011
|
+
* List all lights known to JMRI
|
|
2012
|
+
*/
|
|
2013
|
+
async listLights() {
|
|
2014
|
+
const message = {
|
|
2015
|
+
type: "light",
|
|
2016
|
+
method: "list"
|
|
2017
|
+
};
|
|
2018
|
+
const response = await this.client.request(message);
|
|
2019
|
+
const entries = Array.isArray(response?.data) ? response.data.map((r) => r.data ?? r) : [];
|
|
2020
|
+
for (const entry of entries) {
|
|
2021
|
+
if (entry.name && entry.state !== void 0) {
|
|
2022
|
+
this.lights.set(entry.name, entry.state);
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
return entries;
|
|
2026
|
+
}
|
|
2027
|
+
/**
|
|
2028
|
+
* Get cached light state without a network request
|
|
2029
|
+
*/
|
|
2030
|
+
getLightState(name) {
|
|
2031
|
+
return this.lights.get(name);
|
|
2032
|
+
}
|
|
2033
|
+
/**
|
|
2034
|
+
* Get all cached light states
|
|
2035
|
+
*/
|
|
2036
|
+
getCachedLights() {
|
|
2037
|
+
return new Map(this.lights);
|
|
2038
|
+
}
|
|
2039
|
+
/**
|
|
2040
|
+
* Handle unsolicited light state updates from JMRI
|
|
2041
|
+
*/
|
|
2042
|
+
handleLightUpdate(message) {
|
|
2043
|
+
const name = message.data?.name;
|
|
2044
|
+
const state = message.data?.state;
|
|
2045
|
+
if (!name || state === void 0) return;
|
|
2046
|
+
const oldState = this.lights.get(name);
|
|
2047
|
+
this.lights.set(name, state);
|
|
2048
|
+
if (oldState !== state) {
|
|
2049
|
+
this.emit("light:changed", name, state);
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
};
|
|
2053
|
+
|
|
1894
2054
|
// src/types/client-options.ts
|
|
1895
2055
|
var DEFAULT_CLIENT_OPTIONS = {
|
|
1896
2056
|
host: "localhost",
|
|
@@ -1967,6 +2127,7 @@ var JmriClient = class extends import_index.default {
|
|
|
1967
2127
|
this.rosterManager = new RosterManager(this.wsClient);
|
|
1968
2128
|
this.throttleManager = new ThrottleManager(this.wsClient);
|
|
1969
2129
|
this.turnoutManager = new TurnoutManager(this.wsClient);
|
|
2130
|
+
this.lightManager = new LightManager(this.wsClient);
|
|
1970
2131
|
this.wsClient.on("connected", () => this.emit("connected"));
|
|
1971
2132
|
this.wsClient.on("disconnected", (reason) => this.emit("disconnected", reason));
|
|
1972
2133
|
this.wsClient.on(
|
|
@@ -1994,6 +2155,10 @@ var JmriClient = class extends import_index.default {
|
|
|
1994
2155
|
"turnout:changed",
|
|
1995
2156
|
(name, state) => this.emit("turnout:changed", name, state)
|
|
1996
2157
|
);
|
|
2158
|
+
this.lightManager.on(
|
|
2159
|
+
"light:changed",
|
|
2160
|
+
(name, state) => this.emit("light:changed", name, state)
|
|
2161
|
+
);
|
|
1997
2162
|
this.throttleManager.on(
|
|
1998
2163
|
"throttle:acquired",
|
|
1999
2164
|
(id) => this.emit("throttle:acquired", id)
|
|
@@ -2142,6 +2307,51 @@ var JmriClient = class extends import_index.default {
|
|
|
2142
2307
|
return this.turnoutManager.getCachedTurnouts();
|
|
2143
2308
|
}
|
|
2144
2309
|
// ============================================================================
|
|
2310
|
+
// Light Control
|
|
2311
|
+
// ============================================================================
|
|
2312
|
+
/**
|
|
2313
|
+
* Get the current state of a light
|
|
2314
|
+
*/
|
|
2315
|
+
async getLight(name) {
|
|
2316
|
+
return this.lightManager.getLight(name);
|
|
2317
|
+
}
|
|
2318
|
+
/**
|
|
2319
|
+
* Set a light to the given state
|
|
2320
|
+
*/
|
|
2321
|
+
async setLight(name, state) {
|
|
2322
|
+
return this.lightManager.setLight(name, state);
|
|
2323
|
+
}
|
|
2324
|
+
/**
|
|
2325
|
+
* Turn a light on
|
|
2326
|
+
*/
|
|
2327
|
+
async turnOnLight(name) {
|
|
2328
|
+
return this.lightManager.turnOnLight(name);
|
|
2329
|
+
}
|
|
2330
|
+
/**
|
|
2331
|
+
* Turn a light off
|
|
2332
|
+
*/
|
|
2333
|
+
async turnOffLight(name) {
|
|
2334
|
+
return this.lightManager.turnOffLight(name);
|
|
2335
|
+
}
|
|
2336
|
+
/**
|
|
2337
|
+
* List all lights known to JMRI
|
|
2338
|
+
*/
|
|
2339
|
+
async listLights() {
|
|
2340
|
+
return this.lightManager.listLights();
|
|
2341
|
+
}
|
|
2342
|
+
/**
|
|
2343
|
+
* Get cached light state without a network request
|
|
2344
|
+
*/
|
|
2345
|
+
getLightState(name) {
|
|
2346
|
+
return this.lightManager.getLightState(name);
|
|
2347
|
+
}
|
|
2348
|
+
/**
|
|
2349
|
+
* Get all cached light states
|
|
2350
|
+
*/
|
|
2351
|
+
getCachedLights() {
|
|
2352
|
+
return this.lightManager.getCachedLights();
|
|
2353
|
+
}
|
|
2354
|
+
// ============================================================================
|
|
2145
2355
|
// Throttle Control
|
|
2146
2356
|
// ============================================================================
|
|
2147
2357
|
/**
|
|
@@ -2239,12 +2449,14 @@ var JmriClient = class extends import_index.default {
|
|
|
2239
2449
|
export {
|
|
2240
2450
|
ConnectionState,
|
|
2241
2451
|
JmriClient,
|
|
2452
|
+
LightState,
|
|
2242
2453
|
MockResponseManager,
|
|
2243
2454
|
PowerState,
|
|
2244
2455
|
TurnoutState,
|
|
2245
2456
|
WebSocketClient,
|
|
2246
2457
|
isThrottleFunctionKey,
|
|
2247
2458
|
isValidSpeed,
|
|
2459
|
+
lightStateToString,
|
|
2248
2460
|
mockData,
|
|
2249
2461
|
mockResponseManager,
|
|
2250
2462
|
powerStateToString,
|
package/dist/cjs/client.js
CHANGED
|
@@ -10,6 +10,7 @@ const power_manager_js_1 = require("./managers/power-manager.js");
|
|
|
10
10
|
const roster_manager_js_1 = require("./managers/roster-manager.js");
|
|
11
11
|
const throttle_manager_js_1 = require("./managers/throttle-manager.js");
|
|
12
12
|
const turnout_manager_js_1 = require("./managers/turnout-manager.js");
|
|
13
|
+
const light_manager_js_1 = require("./managers/light-manager.js");
|
|
13
14
|
const client_options_js_1 = require("./types/client-options.js");
|
|
14
15
|
/**
|
|
15
16
|
* JMRI WebSocket Client
|
|
@@ -43,6 +44,7 @@ class JmriClient extends eventemitter3_1.EventEmitter {
|
|
|
43
44
|
this.rosterManager = new roster_manager_js_1.RosterManager(this.wsClient);
|
|
44
45
|
this.throttleManager = new throttle_manager_js_1.ThrottleManager(this.wsClient);
|
|
45
46
|
this.turnoutManager = new turnout_manager_js_1.TurnoutManager(this.wsClient);
|
|
47
|
+
this.lightManager = new light_manager_js_1.LightManager(this.wsClient);
|
|
46
48
|
// Forward events from WebSocket client
|
|
47
49
|
this.wsClient.on('connected', () => this.emit('connected'));
|
|
48
50
|
this.wsClient.on('disconnected', (reason) => this.emit('disconnected', reason));
|
|
@@ -57,6 +59,7 @@ class JmriClient extends eventemitter3_1.EventEmitter {
|
|
|
57
59
|
// Forward events from managers
|
|
58
60
|
this.powerManager.on('power:changed', (state) => this.emit('power:changed', state));
|
|
59
61
|
this.turnoutManager.on('turnout:changed', (name, state) => this.emit('turnout:changed', name, state));
|
|
62
|
+
this.lightManager.on('light:changed', (name, state) => this.emit('light:changed', name, state));
|
|
60
63
|
this.throttleManager.on('throttle:acquired', (id) => this.emit('throttle:acquired', id));
|
|
61
64
|
this.throttleManager.on('throttle:updated', (id, data) => this.emit('throttle:updated', id, data));
|
|
62
65
|
this.throttleManager.on('throttle:released', (id) => this.emit('throttle:released', id));
|
|
@@ -196,6 +199,51 @@ class JmriClient extends eventemitter3_1.EventEmitter {
|
|
|
196
199
|
return this.turnoutManager.getCachedTurnouts();
|
|
197
200
|
}
|
|
198
201
|
// ============================================================================
|
|
202
|
+
// Light Control
|
|
203
|
+
// ============================================================================
|
|
204
|
+
/**
|
|
205
|
+
* Get the current state of a light
|
|
206
|
+
*/
|
|
207
|
+
async getLight(name) {
|
|
208
|
+
return this.lightManager.getLight(name);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Set a light to the given state
|
|
212
|
+
*/
|
|
213
|
+
async setLight(name, state) {
|
|
214
|
+
return this.lightManager.setLight(name, state);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Turn a light on
|
|
218
|
+
*/
|
|
219
|
+
async turnOnLight(name) {
|
|
220
|
+
return this.lightManager.turnOnLight(name);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Turn a light off
|
|
224
|
+
*/
|
|
225
|
+
async turnOffLight(name) {
|
|
226
|
+
return this.lightManager.turnOffLight(name);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* List all lights known to JMRI
|
|
230
|
+
*/
|
|
231
|
+
async listLights() {
|
|
232
|
+
return this.lightManager.listLights();
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Get cached light state without a network request
|
|
236
|
+
*/
|
|
237
|
+
getLightState(name) {
|
|
238
|
+
return this.lightManager.getLightState(name);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Get all cached light states
|
|
242
|
+
*/
|
|
243
|
+
getCachedLights() {
|
|
244
|
+
return this.lightManager.getCachedLights();
|
|
245
|
+
}
|
|
246
|
+
// ============================================================================
|
|
199
247
|
// Throttle Control
|
|
200
248
|
// ============================================================================
|
|
201
249
|
/**
|
package/dist/cjs/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* WebSocket client for JMRI with real-time updates and throttle control
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.mockData = exports.mockResponseManager = exports.MockResponseManager = exports.turnoutStateToString = exports.powerStateToString = exports.isValidSpeed = exports.isThrottleFunctionKey = exports.ConnectionState = exports.TurnoutState = exports.PowerState = exports.WebSocketClient = exports.JmriClient = void 0;
|
|
7
|
+
exports.mockData = exports.mockResponseManager = exports.MockResponseManager = exports.lightStateToString = exports.turnoutStateToString = exports.powerStateToString = exports.isValidSpeed = exports.isThrottleFunctionKey = exports.ConnectionState = exports.LightState = exports.TurnoutState = exports.PowerState = exports.WebSocketClient = exports.JmriClient = void 0;
|
|
8
8
|
var client_js_1 = require("./client.js");
|
|
9
9
|
Object.defineProperty(exports, "JmriClient", { enumerable: true, get: function () { return client_js_1.JmriClient; } });
|
|
10
10
|
var websocket_client_js_1 = require("./core/websocket-client.js");
|
|
@@ -14,6 +14,7 @@ var index_js_1 = require("./types/index.js");
|
|
|
14
14
|
// JMRI message types
|
|
15
15
|
Object.defineProperty(exports, "PowerState", { enumerable: true, get: function () { return index_js_1.PowerState; } });
|
|
16
16
|
Object.defineProperty(exports, "TurnoutState", { enumerable: true, get: function () { return index_js_1.TurnoutState; } });
|
|
17
|
+
Object.defineProperty(exports, "LightState", { enumerable: true, get: function () { return index_js_1.LightState; } });
|
|
17
18
|
// Event types
|
|
18
19
|
Object.defineProperty(exports, "ConnectionState", { enumerable: true, get: function () { return index_js_1.ConnectionState; } });
|
|
19
20
|
// Export utility functions
|
|
@@ -23,6 +24,7 @@ Object.defineProperty(exports, "isValidSpeed", { enumerable: true, get: function
|
|
|
23
24
|
var jmri_messages_js_1 = require("./types/jmri-messages.js");
|
|
24
25
|
Object.defineProperty(exports, "powerStateToString", { enumerable: true, get: function () { return jmri_messages_js_1.powerStateToString; } });
|
|
25
26
|
Object.defineProperty(exports, "turnoutStateToString", { enumerable: true, get: function () { return jmri_messages_js_1.turnoutStateToString; } });
|
|
27
|
+
Object.defineProperty(exports, "lightStateToString", { enumerable: true, get: function () { return jmri_messages_js_1.lightStateToString; } });
|
|
26
28
|
// Export mock system for testing and demo purposes
|
|
27
29
|
var index_js_2 = require("./mocks/index.js");
|
|
28
30
|
Object.defineProperty(exports, "MockResponseManager", { enumerable: true, get: function () { return index_js_2.MockResponseManager; } });
|
|
@@ -21,3 +21,4 @@ __exportStar(require("./power-manager.js"), exports);
|
|
|
21
21
|
__exportStar(require("./roster-manager.js"), exports);
|
|
22
22
|
__exportStar(require("./throttle-manager.js"), exports);
|
|
23
23
|
__exportStar(require("./turnout-manager.js"), exports);
|
|
24
|
+
__exportStar(require("./light-manager.js"), exports);
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Light manager
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.LightManager = void 0;
|
|
7
|
+
const eventemitter3_1 = require("eventemitter3");
|
|
8
|
+
const jmri_messages_js_1 = require("../types/jmri-messages.js");
|
|
9
|
+
/**
|
|
10
|
+
* Manages JMRI light state
|
|
11
|
+
*/
|
|
12
|
+
class LightManager extends eventemitter3_1.EventEmitter {
|
|
13
|
+
constructor(client) {
|
|
14
|
+
super();
|
|
15
|
+
this.lights = new Map();
|
|
16
|
+
this.client = client;
|
|
17
|
+
this.client.on('update', (message) => {
|
|
18
|
+
if (message.type === 'light') {
|
|
19
|
+
this.handleLightUpdate(message);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get the current state of a light.
|
|
25
|
+
* Also registers a server-side listener so subsequent changes are pushed.
|
|
26
|
+
*/
|
|
27
|
+
async getLight(name) {
|
|
28
|
+
const message = {
|
|
29
|
+
type: 'light',
|
|
30
|
+
data: { name }
|
|
31
|
+
};
|
|
32
|
+
const response = await this.client.request(message);
|
|
33
|
+
const state = response.data?.state ?? jmri_messages_js_1.LightState.UNKNOWN;
|
|
34
|
+
this.lights.set(name, state);
|
|
35
|
+
return state;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Set a light to the given state
|
|
39
|
+
*/
|
|
40
|
+
async setLight(name, state) {
|
|
41
|
+
const message = {
|
|
42
|
+
type: 'light',
|
|
43
|
+
method: 'post',
|
|
44
|
+
data: { name, state }
|
|
45
|
+
};
|
|
46
|
+
await this.client.request(message);
|
|
47
|
+
const oldState = this.lights.get(name);
|
|
48
|
+
this.lights.set(name, state);
|
|
49
|
+
if (oldState !== state) {
|
|
50
|
+
this.emit('light:changed', name, state);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Turn a light on
|
|
55
|
+
*/
|
|
56
|
+
async turnOnLight(name) {
|
|
57
|
+
return this.setLight(name, jmri_messages_js_1.LightState.ON);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Turn a light off
|
|
61
|
+
*/
|
|
62
|
+
async turnOffLight(name) {
|
|
63
|
+
return this.setLight(name, jmri_messages_js_1.LightState.OFF);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* List all lights known to JMRI
|
|
67
|
+
*/
|
|
68
|
+
async listLights() {
|
|
69
|
+
const message = {
|
|
70
|
+
type: 'light',
|
|
71
|
+
method: 'list'
|
|
72
|
+
};
|
|
73
|
+
const response = await this.client.request(message);
|
|
74
|
+
const entries = Array.isArray(response?.data)
|
|
75
|
+
? response.data.map((r) => r.data ?? r)
|
|
76
|
+
: [];
|
|
77
|
+
for (const entry of entries) {
|
|
78
|
+
if (entry.name && entry.state !== undefined) {
|
|
79
|
+
this.lights.set(entry.name, entry.state);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return entries;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get cached light state without a network request
|
|
86
|
+
*/
|
|
87
|
+
getLightState(name) {
|
|
88
|
+
return this.lights.get(name);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Get all cached light states
|
|
92
|
+
*/
|
|
93
|
+
getCachedLights() {
|
|
94
|
+
return new Map(this.lights);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Handle unsolicited light state updates from JMRI
|
|
98
|
+
*/
|
|
99
|
+
handleLightUpdate(message) {
|
|
100
|
+
const name = message.data?.name;
|
|
101
|
+
const state = message.data?.state;
|
|
102
|
+
if (!name || state === undefined)
|
|
103
|
+
return;
|
|
104
|
+
const oldState = this.lights.get(name);
|
|
105
|
+
this.lights.set(name, state);
|
|
106
|
+
if (oldState !== state) {
|
|
107
|
+
this.emit('light:changed', name, state);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exports.LightManager = LightManager;
|
|
@@ -188,6 +188,13 @@ exports.mockData = {
|
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
190
|
},
|
|
191
|
+
"light": {
|
|
192
|
+
"list": [
|
|
193
|
+
{ "type": "light", "data": { "name": "IL1", "userName": "Yard Light", "comment": null, "properties": [], "state": 4 } },
|
|
194
|
+
{ "type": "light", "data": { "name": "IL2", "userName": "Platform Light", "comment": null, "properties": [], "state": 4 } },
|
|
195
|
+
{ "type": "light", "data": { "name": "IL3", "userName": "Signal Lamp", "comment": null, "properties": [], "state": 2 } }
|
|
196
|
+
]
|
|
197
|
+
},
|
|
191
198
|
"turnout": {
|
|
192
199
|
"list": [
|
|
193
200
|
{ "type": "turnout", "data": { "name": "LT1", "userName": "Main Diverge", "state": 2 } },
|
|
@@ -13,6 +13,11 @@ const mock_data_js_1 = require("./mock-data.js");
|
|
|
13
13
|
class MockResponseManager {
|
|
14
14
|
constructor(options = {}) {
|
|
15
15
|
this.throttles = new Map();
|
|
16
|
+
this.lights = new Map([
|
|
17
|
+
['IL1', jmri_messages_js_1.LightState.OFF],
|
|
18
|
+
['IL2', jmri_messages_js_1.LightState.OFF],
|
|
19
|
+
['IL3', jmri_messages_js_1.LightState.ON]
|
|
20
|
+
]);
|
|
16
21
|
this.turnouts = new Map([
|
|
17
22
|
['LT1', jmri_messages_js_1.TurnoutState.CLOSED],
|
|
18
23
|
['LT2', jmri_messages_js_1.TurnoutState.CLOSED],
|
|
@@ -39,6 +44,8 @@ class MockResponseManager {
|
|
|
39
44
|
return this.getRosterResponse(message);
|
|
40
45
|
case 'throttle':
|
|
41
46
|
return this.getThrottleResponse(message);
|
|
47
|
+
case 'light':
|
|
48
|
+
return this.getLightResponse(message);
|
|
42
49
|
case 'turnout':
|
|
43
50
|
return this.getTurnoutResponse(message);
|
|
44
51
|
case 'ping':
|
|
@@ -164,6 +171,29 @@ class MockResponseManager {
|
|
|
164
171
|
data: {}
|
|
165
172
|
};
|
|
166
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Get light response
|
|
176
|
+
*/
|
|
177
|
+
getLightResponse(message) {
|
|
178
|
+
// List all lights
|
|
179
|
+
if (message.method === 'list') {
|
|
180
|
+
return {
|
|
181
|
+
type: 'light',
|
|
182
|
+
data: JSON.parse(JSON.stringify(mock_data_js_1.mockData.light.list))
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
const name = message.data?.name;
|
|
186
|
+
if (!name) {
|
|
187
|
+
return { type: 'light', data: { name: '', state: jmri_messages_js_1.LightState.UNKNOWN } };
|
|
188
|
+
}
|
|
189
|
+
// Set light state
|
|
190
|
+
if (message.method === 'post' && message.data?.state !== undefined) {
|
|
191
|
+
this.lights.set(name, message.data.state);
|
|
192
|
+
}
|
|
193
|
+
// Get or confirm current state
|
|
194
|
+
const state = this.lights.get(name) ?? jmri_messages_js_1.LightState.UNKNOWN;
|
|
195
|
+
return { type: 'light', data: { name, state } };
|
|
196
|
+
}
|
|
167
197
|
/**
|
|
168
198
|
* Get turnout response
|
|
169
199
|
*/
|
|
@@ -217,6 +247,12 @@ class MockResponseManager {
|
|
|
217
247
|
getThrottles() {
|
|
218
248
|
return this.throttles;
|
|
219
249
|
}
|
|
250
|
+
/**
|
|
251
|
+
* Get all light states (for testing)
|
|
252
|
+
*/
|
|
253
|
+
getLights() {
|
|
254
|
+
return this.lights;
|
|
255
|
+
}
|
|
220
256
|
/**
|
|
221
257
|
* Get all turnout states (for testing)
|
|
222
258
|
*/
|
|
@@ -229,6 +265,11 @@ class MockResponseManager {
|
|
|
229
265
|
reset() {
|
|
230
266
|
this.powerState = jmri_messages_js_1.PowerState.OFF;
|
|
231
267
|
this.throttles.clear();
|
|
268
|
+
this.lights = new Map([
|
|
269
|
+
['IL1', jmri_messages_js_1.LightState.OFF],
|
|
270
|
+
['IL2', jmri_messages_js_1.LightState.OFF],
|
|
271
|
+
['IL3', jmri_messages_js_1.LightState.ON]
|
|
272
|
+
]);
|
|
232
273
|
this.turnouts = new Map([
|
|
233
274
|
['LT1', jmri_messages_js_1.TurnoutState.CLOSED],
|
|
234
275
|
['LT2', jmri_messages_js_1.TurnoutState.CLOSED],
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
* Based on JMRI JSON protocol specification
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.TurnoutState = exports.PowerState = void 0;
|
|
7
|
+
exports.LightState = exports.TurnoutState = exports.PowerState = void 0;
|
|
8
8
|
exports.powerStateToString = powerStateToString;
|
|
9
9
|
exports.turnoutStateToString = turnoutStateToString;
|
|
10
|
+
exports.lightStateToString = lightStateToString;
|
|
10
11
|
/**
|
|
11
12
|
* Power state values (from JMRI JSON protocol constants)
|
|
12
13
|
* UNKNOWN = 0 (state cannot be determined)
|
|
@@ -66,3 +67,29 @@ function turnoutStateToString(state) {
|
|
|
66
67
|
return 'UNKNOWN';
|
|
67
68
|
}
|
|
68
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Light state values (from JMRI JSON protocol constants)
|
|
72
|
+
* UNKNOWN = 0 (state cannot be determined)
|
|
73
|
+
* ON = 2 (light is on)
|
|
74
|
+
* OFF = 4 (light is off)
|
|
75
|
+
*/
|
|
76
|
+
var LightState;
|
|
77
|
+
(function (LightState) {
|
|
78
|
+
LightState[LightState["UNKNOWN"] = 0] = "UNKNOWN";
|
|
79
|
+
LightState[LightState["ON"] = 2] = "ON";
|
|
80
|
+
LightState[LightState["OFF"] = 4] = "OFF";
|
|
81
|
+
})(LightState || (exports.LightState = LightState = {}));
|
|
82
|
+
/**
|
|
83
|
+
* Convert LightState enum to human-readable string
|
|
84
|
+
*/
|
|
85
|
+
function lightStateToString(state) {
|
|
86
|
+
switch (state) {
|
|
87
|
+
case LightState.ON:
|
|
88
|
+
return 'ON';
|
|
89
|
+
case LightState.OFF:
|
|
90
|
+
return 'OFF';
|
|
91
|
+
case LightState.UNKNOWN:
|
|
92
|
+
default:
|
|
93
|
+
return 'UNKNOWN';
|
|
94
|
+
}
|
|
95
|
+
}
|