homebridge-ratgdo 2.1.3 → 2.2.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.
- package/dist/ratgdo-device.d.ts +0 -2
- package/dist/ratgdo-device.js +21 -47
- package/dist/ratgdo-device.js.map +1 -1
- package/dist/ratgdo-options.d.ts +4 -15
- package/dist/ratgdo-options.js +2 -93
- package/dist/ratgdo-options.js.map +1 -1
- package/dist/ratgdo-platform.d.ts +4 -4
- package/dist/ratgdo-platform.js +20 -31
- package/dist/ratgdo-platform.js.map +1 -1
- package/homebridge-ui/public/index.html +20 -1
- package/homebridge-ui/public/lib/featureoptions.js +366 -0
- package/homebridge-ui/public/lib/webUi.mjs +155 -0
- package/homebridge-ui/public/{ratgdo-featureoptions.mjs → lib/webui-featureoptions.mjs} +104 -142
- package/homebridge-ui/server.js +3 -39
- package/package.json +13 -13
- package/dist/ratgdo-mqtt.d.ts +0 -19
- package/dist/ratgdo-mqtt.js +0 -155
- package/dist/ratgdo-mqtt.js.map +0 -1
- package/homebridge-ui/public/lib/featureoptions.mjs +0 -200
- package/homebridge-ui/public/ui.mjs +0 -144
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { API, DynamicPlatformPlugin, HAP, Logging, PlatformAccessory, PlatformConfig } from "homebridge";
|
|
2
|
+
import { FeatureOptions, MqttClient } from "homebridge-plugin-utils";
|
|
2
3
|
import { RatgdoOptions } from "./ratgdo-options.js";
|
|
3
4
|
import { RatgdoAccessory } from "./ratgdo-device.js";
|
|
4
|
-
import { RatgdoMqtt } from "./ratgdo-mqtt.js";
|
|
5
5
|
export declare class RatgdoPlatform implements DynamicPlatformPlugin {
|
|
6
6
|
private readonly accessories;
|
|
7
7
|
readonly api: API;
|
|
8
|
+
private discoveredDevices;
|
|
8
9
|
private espHomeEvents;
|
|
9
|
-
|
|
10
|
+
featureOptions: FeatureOptions;
|
|
10
11
|
config: RatgdoOptions;
|
|
11
12
|
readonly configOptions: string[];
|
|
12
13
|
readonly configuredDevices: {
|
|
@@ -14,12 +15,11 @@ export declare class RatgdoPlatform implements DynamicPlatformPlugin {
|
|
|
14
15
|
};
|
|
15
16
|
readonly hap: HAP;
|
|
16
17
|
readonly log: Logging;
|
|
17
|
-
readonly mqtt:
|
|
18
|
+
readonly mqtt: MqttClient | null;
|
|
18
19
|
constructor(log: Logging, config: PlatformConfig, api: API);
|
|
19
20
|
configureAccessory(accessory: PlatformAccessory): void;
|
|
20
21
|
private configureRatgdo;
|
|
21
22
|
private discoverRatgdoDevice;
|
|
22
23
|
private configureGdo;
|
|
23
|
-
featureOptionDefault(option: string): boolean;
|
|
24
24
|
debug(message: string, ...parameters: unknown[]): void;
|
|
25
25
|
}
|
package/dist/ratgdo-platform.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { Bonjour } from "bonjour-service";
|
|
2
|
+
import { FeatureOptions, MqttClient } from "homebridge-plugin-utils";
|
|
2
3
|
import { PLATFORM_NAME, PLUGIN_NAME, RATGDO_AUTODISCOVERY_INTERVAL, RATGDO_HEARTBEAT_DURATION, RATGDO_HEARTBEAT_INTERVAL, RATGDO_MQTT_TOPIC } from "./settings.js";
|
|
3
|
-
import { featureOptionCategories, featureOptions
|
|
4
|
+
import { featureOptionCategories, featureOptions } from "./ratgdo-options.js";
|
|
4
5
|
import EventSource from "eventsource";
|
|
5
6
|
import { RatgdoAccessory } from "./ratgdo-device.js";
|
|
6
|
-
import { RatgdoMqtt } from "./ratgdo-mqtt.js";
|
|
7
7
|
import http from "node:http";
|
|
8
8
|
import net from "node:net";
|
|
9
9
|
import util from "node:util";
|
|
10
10
|
export class RatgdoPlatform {
|
|
11
11
|
accessories;
|
|
12
12
|
api;
|
|
13
|
+
discoveredDevices;
|
|
13
14
|
espHomeEvents;
|
|
14
|
-
|
|
15
|
+
featureOptions;
|
|
15
16
|
config;
|
|
16
17
|
configOptions;
|
|
17
18
|
configuredDevices;
|
|
@@ -21,39 +22,29 @@ export class RatgdoPlatform {
|
|
|
21
22
|
constructor(log, config, api) {
|
|
22
23
|
this.accessories = [];
|
|
23
24
|
this.api = api;
|
|
25
|
+
this.config = {};
|
|
24
26
|
this.configOptions = [];
|
|
25
27
|
this.configuredDevices = {};
|
|
28
|
+
this.discoveredDevices = {};
|
|
26
29
|
this.espHomeEvents = {};
|
|
27
|
-
this.featureOptionDefaults = {};
|
|
28
30
|
this.hap = api.hap;
|
|
29
31
|
this.log = log;
|
|
30
32
|
this.log.debug = this.debug.bind(this);
|
|
31
33
|
this.mqtt = null;
|
|
32
|
-
|
|
33
|
-
for (const category of featureOptionCategories) {
|
|
34
|
-
for (const options of featureOptions[category.name]) {
|
|
35
|
-
this.featureOptionDefaults[(category.name + (options.name.length ? "." + options.name : "")).toLowerCase()] = options.default;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
34
|
+
this.featureOptions = new FeatureOptions(featureOptionCategories, featureOptions, config.options);
|
|
38
35
|
// We can't start without being configured.
|
|
39
36
|
if (!config) {
|
|
40
37
|
return;
|
|
41
38
|
}
|
|
42
39
|
this.config = {
|
|
43
40
|
debug: config.debug === true,
|
|
44
|
-
mqttTopic: config.mqttTopic
|
|
41
|
+
mqttTopic: config.mqttTopic,
|
|
45
42
|
mqttUrl: config.mqttUrl,
|
|
46
43
|
options: config.options
|
|
47
44
|
};
|
|
48
|
-
// If we have feature options, put them into their own array, upper-cased for future reference.
|
|
49
|
-
if (this.config.options) {
|
|
50
|
-
for (const featureOption of this.config.options) {
|
|
51
|
-
this.configOptions.push(featureOption.toLowerCase());
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
45
|
// Initialize MQTT, if needed.
|
|
55
46
|
if (this.config.mqttUrl) {
|
|
56
|
-
this.mqtt = new
|
|
47
|
+
this.mqtt = new MqttClient(this.config.mqttUrl, this.config.mqttTopic ?? RATGDO_MQTT_TOPIC, this.log);
|
|
57
48
|
}
|
|
58
49
|
this.log.debug("Debug logging on. Expect a lot of data.");
|
|
59
50
|
// Fire up the Ratgdo API once Homebridge has loaded all the cached accessories it knows about and called configureAccessory() on each.
|
|
@@ -167,7 +158,6 @@ export class RatgdoPlatform {
|
|
|
167
158
|
default:
|
|
168
159
|
ratgdoAccessory.log.error("Unknown door operation detected: %s.", event.current_operation);
|
|
169
160
|
return;
|
|
170
|
-
break;
|
|
171
161
|
}
|
|
172
162
|
ratgdoAccessory.updateState("door", state, (event.position !== undefined) ? event.position * 100 : undefined);
|
|
173
163
|
break;
|
|
@@ -204,6 +194,10 @@ export class RatgdoPlatform {
|
|
|
204
194
|
}
|
|
205
195
|
// Configure a discovered garage door opener.
|
|
206
196
|
configureGdo(address, mac, name, firmwareVersion) {
|
|
197
|
+
// If we've already discovered this device, we're done.
|
|
198
|
+
if (this.discoveredDevices[mac]) {
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
207
201
|
// Generate this device's unique identifier.
|
|
208
202
|
const uuid = this.hap.uuid.generate(mac);
|
|
209
203
|
// See if we already know about this accessory or if it's truly new.
|
|
@@ -215,8 +209,12 @@ export class RatgdoPlatform {
|
|
|
215
209
|
mac: mac.replace(/:/g, ""),
|
|
216
210
|
name: name
|
|
217
211
|
};
|
|
212
|
+
// Inform the user that we've discovered a device.
|
|
213
|
+
this.log.info("Discovered: %s (address: %s mac: %s ESPHome firmware: v%s).", device.name, device.address, device.mac, device.firmwareVersion);
|
|
214
|
+
// Mark it as discovered.
|
|
215
|
+
this.discoveredDevices[mac] = true;
|
|
218
216
|
// Check to see if the user has disabled the device.
|
|
219
|
-
if (!
|
|
217
|
+
if (!this.featureOptions.test("Device", device.mac)) {
|
|
220
218
|
// If the accessory already exists, let's remove it.
|
|
221
219
|
if (accessory) {
|
|
222
220
|
// Inform the user.
|
|
@@ -233,8 +231,6 @@ export class RatgdoPlatform {
|
|
|
233
231
|
if (this.configuredDevices[uuid]) {
|
|
234
232
|
return null;
|
|
235
233
|
}
|
|
236
|
-
// Inform the user.
|
|
237
|
-
this.log.info("Discovered: %s (address: %s mac: %s ESPHome firmware: v%s).", device.name, device.address, device.mac, device.firmwareVersion);
|
|
238
234
|
// It's a new device - let's add it to HomeKit.
|
|
239
235
|
if (!accessory) {
|
|
240
236
|
accessory = new this.api.platformAccessory(device.name, uuid);
|
|
@@ -242,21 +238,14 @@ export class RatgdoPlatform {
|
|
|
242
238
|
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
243
239
|
this.accessories.push(accessory);
|
|
244
240
|
}
|
|
241
|
+
// Inform the user.
|
|
242
|
+
this.log.info("Configuring: %s (address: %s mac: %s ESPHome firmware: v%s).", device.name, device.address, device.mac, device.firmwareVersion);
|
|
245
243
|
// Add it to our list of configured devices.
|
|
246
244
|
this.configuredDevices[uuid] = new RatgdoAccessory(this, accessory, device);
|
|
247
245
|
// Refresh the accessory cache.
|
|
248
246
|
this.api.updatePlatformAccessories([accessory]);
|
|
249
247
|
return this.configuredDevices[uuid];
|
|
250
248
|
}
|
|
251
|
-
// Utility to return the default value for a feature option.
|
|
252
|
-
featureOptionDefault(option) {
|
|
253
|
-
const defaultValue = this.featureOptionDefaults[option.toLowerCase()];
|
|
254
|
-
// If it's unknown to us, assume it's true.
|
|
255
|
-
if (defaultValue === undefined) {
|
|
256
|
-
return true;
|
|
257
|
-
}
|
|
258
|
-
return defaultValue;
|
|
259
|
-
}
|
|
260
249
|
// Utility for debug logging.
|
|
261
250
|
debug(message, ...parameters) {
|
|
262
251
|
if (this.config.debug) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ratgdo-platform.js","sourceRoot":"","sources":["../src/ratgdo-platform.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAW,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,6BAA6B,EAAE,yBAAyB,EAAE,yBAAyB,EACtH,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAiB,uBAAuB,EAAE,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"ratgdo-platform.js","sourceRoot":"","sources":["../src/ratgdo-platform.ts"],"names":[],"mappings":"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"}
|
|
@@ -110,4 +110,23 @@
|
|
|
110
110
|
</li>
|
|
111
111
|
</ul>
|
|
112
112
|
</div>
|
|
113
|
-
<script
|
|
113
|
+
<script type="module">
|
|
114
|
+
|
|
115
|
+
/* Copyright(C) 2017-2024, HJD (https://github.com/hjdhjd). All rights reserved.
|
|
116
|
+
*
|
|
117
|
+
* Plugin webUI.
|
|
118
|
+
*/
|
|
119
|
+
|
|
120
|
+
"use strict;"
|
|
121
|
+
|
|
122
|
+
import { webUi } from "./lib/webUi.mjs";
|
|
123
|
+
import { webUiFeatureOptions } from "./lib/webui-featureoptions.mjs";
|
|
124
|
+
|
|
125
|
+
const pluginName = "Ratgdo"
|
|
126
|
+
|
|
127
|
+
// Keep a list of all the feature options and option groups.
|
|
128
|
+
const featureOptions = new webUiFeatureOptions({ sidebar: "Ratgdo Devices", useControllers: false });
|
|
129
|
+
|
|
130
|
+
// Instantiate the webUI.
|
|
131
|
+
new webUi({ featureOptions: featureOptions, homebridge: homebridge, name: "Ratgdo" });
|
|
132
|
+
</script>
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
export class FeatureOptions {
|
|
2
|
+
_categories;
|
|
3
|
+
_configuredOptions;
|
|
4
|
+
_groups;
|
|
5
|
+
_options;
|
|
6
|
+
defaultReturnValue;
|
|
7
|
+
defaults;
|
|
8
|
+
valueOptions;
|
|
9
|
+
// Create a feature option instance.
|
|
10
|
+
constructor(categories, options, configuredOptions) {
|
|
11
|
+
// Initialize our defaults.
|
|
12
|
+
this._categories = [];
|
|
13
|
+
this._configuredOptions = [];
|
|
14
|
+
this._groups = {};
|
|
15
|
+
this._options = {};
|
|
16
|
+
this.defaultReturnValue = false;
|
|
17
|
+
this.defaults = {};
|
|
18
|
+
this.valueOptions = {};
|
|
19
|
+
this.categories = categories ?? [];
|
|
20
|
+
this.configuredOptions = configuredOptions;
|
|
21
|
+
this.options = options ?? {};
|
|
22
|
+
}
|
|
23
|
+
color(option, device) {
|
|
24
|
+
switch (this.scope(option, device)) {
|
|
25
|
+
case "device":
|
|
26
|
+
return "text-info";
|
|
27
|
+
case "controller":
|
|
28
|
+
return "text-success";
|
|
29
|
+
case "global":
|
|
30
|
+
return device ? "text-warning" : "text-info";
|
|
31
|
+
default:
|
|
32
|
+
return "";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Return the default value for an option.
|
|
37
|
+
*
|
|
38
|
+
* @param option - Feature option to check.
|
|
39
|
+
*
|
|
40
|
+
* @returns Returns true or false, depending on the option default.
|
|
41
|
+
*/
|
|
42
|
+
defaultValue(option) {
|
|
43
|
+
// Value-centric feature options don't have default values.
|
|
44
|
+
if (this.isValue(option)) {
|
|
45
|
+
return this.defaultReturnValue;
|
|
46
|
+
}
|
|
47
|
+
const value = this.defaults[option.toLowerCase()];
|
|
48
|
+
// If it's unknown to us, assume it's true.
|
|
49
|
+
if (value === undefined) {
|
|
50
|
+
return this.defaultReturnValue;
|
|
51
|
+
}
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Return whether the option explicitly exists in the list of configured options.
|
|
56
|
+
*
|
|
57
|
+
* @param option - Feature option to check.
|
|
58
|
+
* @param id - Optional device or controller scope identifier to check.
|
|
59
|
+
*
|
|
60
|
+
* @returns Returns true if the option has been explicitly configured, false otherwise.
|
|
61
|
+
*/
|
|
62
|
+
exists(option, id) {
|
|
63
|
+
const regex = this.isValue(option) ? this.valueRegex(option, id) : this.optionRegex(option, id);
|
|
64
|
+
return this.configuredOptions.some(x => regex.test(x));
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Return a fully formed feature option string.
|
|
68
|
+
*
|
|
69
|
+
* @param category - Feature option category entry or category name string.
|
|
70
|
+
* @param option - Feature option entry of option name string.
|
|
71
|
+
*
|
|
72
|
+
* @returns Returns a fully formed feature option in the form of `category.option`.
|
|
73
|
+
*/
|
|
74
|
+
expandOption(category, option) {
|
|
75
|
+
const categoryName = (typeof category === "string") ? category : category.name;
|
|
76
|
+
const optionName = (typeof option === "string") ? option : option.name;
|
|
77
|
+
if (!categoryName || !categoryName.length) {
|
|
78
|
+
return "";
|
|
79
|
+
}
|
|
80
|
+
return (!optionName || !optionName.length) ? categoryName : categoryName + "." + optionName;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Parse a floating point feature option value.
|
|
84
|
+
*
|
|
85
|
+
* @param value - Value to parse.
|
|
86
|
+
*
|
|
87
|
+
* @returns Returns a floating point number from a string, or `undefined` if it couldn't be parsed.
|
|
88
|
+
*/
|
|
89
|
+
getFloat(value) {
|
|
90
|
+
// We don't have the value configured -- we're done.
|
|
91
|
+
if (value === undefined) {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
// Parse the number and return the value.
|
|
95
|
+
return this.parseOptionNumeric(value, parseFloat);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Parse an integer feature option value.
|
|
99
|
+
*
|
|
100
|
+
* @param value - Value to parse.
|
|
101
|
+
*
|
|
102
|
+
* @returns Returns an integer from a string, or `undefined` if it couldn't be parsed.
|
|
103
|
+
*/
|
|
104
|
+
getInteger(value) {
|
|
105
|
+
// We don't have the value configured -- we're done.
|
|
106
|
+
if (value === undefined) {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
// Parse the number and return the value.
|
|
110
|
+
return this.parseOptionNumeric(value, parseInt);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Return whether an option has been set in either the device or controller scope context.
|
|
114
|
+
*
|
|
115
|
+
* @param option - Feature option to check.
|
|
116
|
+
*
|
|
117
|
+
* @returns Returns true if the option is set at the device or controller level and false otherwise.
|
|
118
|
+
*/
|
|
119
|
+
isScopeDevice(option, device) {
|
|
120
|
+
const value = this.exists(option, device);
|
|
121
|
+
// Return the value if it's set, or the default value for this option.
|
|
122
|
+
return (value !== undefined) ? value : this.defaultValue(option);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Return whether an option has been set in the global scope context.
|
|
126
|
+
*
|
|
127
|
+
* @param option - Feature option to check.
|
|
128
|
+
*
|
|
129
|
+
* @returns Returns true if the option is set globally and false otherwise.
|
|
130
|
+
*/
|
|
131
|
+
isScopeGlobal(option) {
|
|
132
|
+
const value = this.exists(option);
|
|
133
|
+
// Return the value if it's set, or the default value for this option.
|
|
134
|
+
return (value !== undefined) ? value : this.defaultValue(option);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Return whether an option is value-centric or not.
|
|
138
|
+
*
|
|
139
|
+
* @param option - Feature option entry or string to check.
|
|
140
|
+
*
|
|
141
|
+
* @returns Returns true if it is a value-centric option and false otherwise.
|
|
142
|
+
*/
|
|
143
|
+
isValue(option) {
|
|
144
|
+
return this.valueOptions[option?.toLowerCase()] === true;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Return the scope hierarchy location of an option.
|
|
148
|
+
*
|
|
149
|
+
* @param option - Feature option to check.
|
|
150
|
+
* @param device - Optional device scope identifier.
|
|
151
|
+
* @param controller - Optional controller scope identifier.
|
|
152
|
+
*
|
|
153
|
+
* @returns Returns an object containing the location in the scope hierarchy of an `option` as well as the current value associated with the option.
|
|
154
|
+
*/
|
|
155
|
+
scope(option, device, controller) {
|
|
156
|
+
return this.getOptionInfo(option, device, controller).scope;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Return the current state of a feature option, traversing the scope hierarchy.
|
|
160
|
+
*
|
|
161
|
+
* @param option - Feature option to check.
|
|
162
|
+
* @param device - Optional device scope identifier.
|
|
163
|
+
* @param controller - Optional controller scope identifier.
|
|
164
|
+
*
|
|
165
|
+
* @returns Returns true if the option is enabled, and false otherwise.
|
|
166
|
+
*/
|
|
167
|
+
test(option, device, controller) {
|
|
168
|
+
return this.getOptionInfo(option, device, controller).value;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Return the value associated with a value-centric feature option, traversing the scope hierarchy.
|
|
172
|
+
*
|
|
173
|
+
* @param option - Feature option to check.
|
|
174
|
+
* @param device - Optional device scope identifier.
|
|
175
|
+
* @param controller - Optional controller scope identifier.
|
|
176
|
+
*
|
|
177
|
+
* @returns Returns the current value associated with `option` or `undefined` if none.
|
|
178
|
+
*/
|
|
179
|
+
value(option, device, controller) {
|
|
180
|
+
const getValue = (checkOption, checkId) => {
|
|
181
|
+
const regex = this.valueRegex(checkOption, checkId);
|
|
182
|
+
// Get the option value, if we have one.
|
|
183
|
+
for (const entry of this.configuredOptions) {
|
|
184
|
+
const regexMatch = regex.exec(entry);
|
|
185
|
+
if (regexMatch) {
|
|
186
|
+
return regexMatch[1];
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return undefined;
|
|
190
|
+
};
|
|
191
|
+
// Check to see if we have a device-level value first.
|
|
192
|
+
if (device) {
|
|
193
|
+
const value = getValue(option, device);
|
|
194
|
+
if (value) {
|
|
195
|
+
return value;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Now check to see if we have an controller-level value.
|
|
199
|
+
if (controller) {
|
|
200
|
+
const value = getValue(option, controller);
|
|
201
|
+
if (value) {
|
|
202
|
+
return value;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Finally, we check for a global-level value.
|
|
206
|
+
return getValue(option);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Return the list of available feature option categories.
|
|
210
|
+
*
|
|
211
|
+
* @returns Returns the current list of available feature option categories.
|
|
212
|
+
*/
|
|
213
|
+
get categories() {
|
|
214
|
+
return this._categories;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Set the list of available feature option categories.
|
|
218
|
+
*
|
|
219
|
+
* @param options - Array of available feature options.
|
|
220
|
+
*/
|
|
221
|
+
set categories(category) {
|
|
222
|
+
this._categories = category;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Return the list of currently configured feature options.
|
|
226
|
+
*
|
|
227
|
+
* @returns Returns the currently configured list of feature options.
|
|
228
|
+
*/
|
|
229
|
+
get configuredOptions() {
|
|
230
|
+
return this._configuredOptions;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Set the list of currently configured feature options.
|
|
234
|
+
*
|
|
235
|
+
* @param options - Array of configured feature options.
|
|
236
|
+
*/
|
|
237
|
+
set configuredOptions(options) {
|
|
238
|
+
this._configuredOptions = options ?? [];
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Return the list of available feature option groups.
|
|
242
|
+
*
|
|
243
|
+
* @returns Returns the current list of available feature option groups.
|
|
244
|
+
*/
|
|
245
|
+
get groups() {
|
|
246
|
+
return this._groups;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Return the list of available feature options.
|
|
250
|
+
*
|
|
251
|
+
* @returns Returns the current list of available feature options.
|
|
252
|
+
*/
|
|
253
|
+
get options() {
|
|
254
|
+
return this._options;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Set the list of available feature options.
|
|
258
|
+
*
|
|
259
|
+
* @param options - Array of available feature options.
|
|
260
|
+
*/
|
|
261
|
+
set options(options) {
|
|
262
|
+
this._options = options ?? {};
|
|
263
|
+
// Regenerate our defaults.
|
|
264
|
+
this.generateDefaults();
|
|
265
|
+
}
|
|
266
|
+
// Build our list of default values for our feature options.
|
|
267
|
+
generateDefaults() {
|
|
268
|
+
this.defaults = {};
|
|
269
|
+
this._groups = {};
|
|
270
|
+
this.valueOptions = {};
|
|
271
|
+
for (const category of this.categories) {
|
|
272
|
+
// Now enumerate all the feature options for a given device and add then to the full list.
|
|
273
|
+
for (const option of this.options[category.name]) {
|
|
274
|
+
// Expand the entry.
|
|
275
|
+
const entry = this.expandOption(category, option);
|
|
276
|
+
// Index the default value.
|
|
277
|
+
this.defaults[entry.toLowerCase()] = option.default;
|
|
278
|
+
// Track value-centric options.
|
|
279
|
+
this.valueOptions[entry.toLowerCase()] = "defaultValue" in option;
|
|
280
|
+
// Cross reference the feature option group it belongs to, if any.
|
|
281
|
+
if (option.group !== undefined) {
|
|
282
|
+
const expandedGroup = category.name + (option.group.length ? ("." + option.group) : "");
|
|
283
|
+
// Initialize the group entry if needed and add the entry.
|
|
284
|
+
(this._groups[expandedGroup] ??= []).push(entry);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
// Utility function to return the setting of a particular option and it's position in the scoping hierarchy.
|
|
290
|
+
getOptionInfo(option, device, controller) {
|
|
291
|
+
// There are a couple of ways to enable and disable options. The rules of the road are:
|
|
292
|
+
//
|
|
293
|
+
// 1. Explicitly disabling, or enabling an option on the controller propogates to all the devices that are managed by that controller. Why might you want to do this?
|
|
294
|
+
// Because...
|
|
295
|
+
//
|
|
296
|
+
// 2. Explicitly disabling, or enabling an option on a device always override the above. This means that it's possible to disable an option for a controller, and all
|
|
297
|
+
// the devices that are managed by it, and then override that behavior on a single device that it's managing.
|
|
298
|
+
// Check to see if we have a device-level option first.
|
|
299
|
+
if (device && this.exists(option, device)) {
|
|
300
|
+
const value = this.isOptionEnabled(option, device);
|
|
301
|
+
if (value !== undefined) {
|
|
302
|
+
return { scope: "device", value: value };
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
// Now check to see if we have an controller-level option.
|
|
306
|
+
if (controller && this.exists(option, controller)) {
|
|
307
|
+
const value = this.isOptionEnabled(option, controller);
|
|
308
|
+
if (value !== undefined) {
|
|
309
|
+
return { scope: "controller", value: value };
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
// Finally, we check for a global-level value.
|
|
313
|
+
if (this.exists(option)) {
|
|
314
|
+
const value = this.isOptionEnabled(option);
|
|
315
|
+
if (value !== undefined) {
|
|
316
|
+
return { scope: "global", value: value };
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
// The option hasn't been set at any scope, return our default value.
|
|
320
|
+
return { scope: "none", value: this.defaultValue(option) };
|
|
321
|
+
}
|
|
322
|
+
// Utility to test whether an option is set in a given scope.
|
|
323
|
+
// We return true if an option is enabled, false for disabled, undefined otherwise. For value-centric options, we return true if a value exists.
|
|
324
|
+
isOptionEnabled(option, id) {
|
|
325
|
+
// Deal with value-centric options uniquely.
|
|
326
|
+
if (this.isValue(option)) {
|
|
327
|
+
return this.exists(option, id);
|
|
328
|
+
}
|
|
329
|
+
const regex = this.optionRegex(option, id);
|
|
330
|
+
// Get the option value, if we have one.
|
|
331
|
+
for (const entry of this.configuredOptions) {
|
|
332
|
+
const regexMatch = regex.exec(entry);
|
|
333
|
+
if (regexMatch) {
|
|
334
|
+
return regexMatch[1].toLowerCase() === "enable";
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return undefined;
|
|
338
|
+
}
|
|
339
|
+
// Regular expression test for feature options.
|
|
340
|
+
optionRegex(option, id) {
|
|
341
|
+
// This regular expression is a bit more intricate than you might think it should be due to the need to ensure we capture values at the very end of the option. We
|
|
342
|
+
// also need to escape out our option to ensure we have no inadvertent issues in matching the regular expression.
|
|
343
|
+
return new RegExp("^(Enable|Disable)\\." + option.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + (!id ? "" : "\\." + id) + "$", "gi");
|
|
344
|
+
}
|
|
345
|
+
// Utility function to parse and return a numeric configuration parameter.
|
|
346
|
+
parseOptionNumeric(option, convert) {
|
|
347
|
+
// We don't have the option configured -- we're done.
|
|
348
|
+
if (option === undefined) {
|
|
349
|
+
return undefined;
|
|
350
|
+
}
|
|
351
|
+
// Convert it to a number, if needed.
|
|
352
|
+
const convertedValue = convert(option);
|
|
353
|
+
// Let's validate to make sure it's really a number.
|
|
354
|
+
if (isNaN(convertedValue) || (convertedValue < 0)) {
|
|
355
|
+
return undefined;
|
|
356
|
+
}
|
|
357
|
+
// Return the value.
|
|
358
|
+
return convertedValue;
|
|
359
|
+
}
|
|
360
|
+
// Regular expression test for value-centric feature options.
|
|
361
|
+
valueRegex(option, id) {
|
|
362
|
+
// This regular expression is a bit more intricate than you might think it should be due to the need to ensure we capture values at the very end of the option.
|
|
363
|
+
return new RegExp("^Enable\\." + option.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + (!id ? "" : "\\." + id) + "\\.([^\\.]+)$", "gi");
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
//# sourceMappingURL=featureoptions.js.map
|