homebridge-plugin-utils 1.34.0 → 2.0.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/README.md +130 -2
- package/build/eslint-plugin/README.md +164 -0
- package/build/eslint-plugin/config.mjs +308 -0
- package/build/eslint-plugin/index.mjs +7 -0
- package/build/eslint-plugin/plugin.mjs +46 -0
- package/build/eslint-plugin/rules/blank-line-after-open-brace.mjs +137 -0
- package/build/eslint-plugin/rules/blank-line-after-open-brace.test.mjs +112 -0
- package/build/eslint-plugin/rules/comment-style.mjs +190 -0
- package/build/eslint-plugin/rules/comment-style.test.mjs +190 -0
- package/build/eslint-plugin/rules/enforce-node-protocol.mjs +114 -0
- package/build/eslint-plugin/rules/enforce-node-protocol.test.mjs +116 -0
- package/build/eslint-plugin/rules/paren-comparisons-in-logical.mjs +94 -0
- package/build/eslint-plugin/rules/paren-comparisons-in-logical.test.mjs +107 -0
- package/build/eslint-plugin/rules/split-type-imports.mjs +354 -0
- package/build/eslint-plugin/rules/split-type-imports.test.mjs +268 -0
- package/build/eslint-plugin/test-setup.mjs +21 -0
- package/build/fs-ops.mjs +184 -0
- package/build/tsconfig.json +18 -3
- package/dist/backpressure.d.ts +128 -0
- package/dist/backpressure.js +273 -0
- package/dist/backpressure.js.map +1 -0
- package/dist/cli/index.d.ts +95 -0
- package/dist/cli/index.js +355 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/clock-double.d.ts +93 -0
- package/dist/clock-double.js +141 -0
- package/dist/clock-double.js.map +1 -0
- package/dist/clock.d.ts +39 -0
- package/dist/clock.js +34 -0
- package/dist/clock.js.map +1 -0
- package/dist/eslint-plugin/config.d.mts +193 -0
- package/dist/eslint-plugin/index.d.mts +2 -0
- package/dist/eslint-plugin/plugin.d.mts +87 -0
- package/dist/eslint-plugin/rules/blank-line-after-open-brace.d.mts +19 -0
- package/dist/eslint-plugin/rules/comment-style.d.mts +15 -0
- package/dist/eslint-plugin/rules/enforce-node-protocol.d.mts +18 -0
- package/dist/eslint-plugin/rules/paren-comparisons-in-logical.d.mts +15 -0
- package/dist/eslint-plugin/rules/split-type-imports.d.mts +16 -0
- package/dist/featureOptions-docs.d.ts +96 -0
- package/dist/featureOptions-docs.js +193 -0
- package/dist/featureOptions-docs.js.map +1 -0
- package/dist/featureOptions.d.ts +674 -0
- package/dist/featureOptions.js +870 -0
- package/dist/featureOptions.js.map +1 -0
- package/dist/ffmpeg/codecs.d.ts +256 -72
- package/dist/ffmpeg/codecs.js +477 -257
- package/dist/ffmpeg/codecs.js.map +1 -1
- package/dist/ffmpeg/dgram-util.d.ts +46 -0
- package/dist/ffmpeg/dgram-util.js +38 -0
- package/dist/ffmpeg/dgram-util.js.map +1 -0
- package/dist/ffmpeg/exec.d.ts +83 -64
- package/dist/ffmpeg/exec.js +77 -86
- package/dist/ffmpeg/exec.js.map +1 -1
- package/dist/ffmpeg/fmp4.d.ts +70 -4
- package/dist/ffmpeg/fmp4.js +100 -11
- package/dist/ffmpeg/fmp4.js.map +1 -1
- package/dist/ffmpeg/hap-enums.d.ts +214 -0
- package/dist/ffmpeg/hap-enums.js +92 -0
- package/dist/ffmpeg/hap-enums.js.map +1 -0
- package/dist/ffmpeg/index.d.ts +16 -9
- package/dist/ffmpeg/index.js +6 -0
- package/dist/ffmpeg/index.js.map +1 -1
- package/dist/ffmpeg/mp4-assembler.d.ts +120 -0
- package/dist/ffmpeg/mp4-assembler.js +387 -0
- package/dist/ffmpeg/mp4-assembler.js.map +1 -0
- package/dist/ffmpeg/mp4-parser.d.ts +94 -0
- package/dist/ffmpeg/mp4-parser.js +130 -0
- package/dist/ffmpeg/mp4-parser.js.map +1 -0
- package/dist/ffmpeg/options.d.ts +62 -149
- package/dist/ffmpeg/options.js +608 -499
- package/dist/ffmpeg/options.js.map +1 -1
- package/dist/ffmpeg/process.d.ts +143 -91
- package/dist/ffmpeg/process.js +406 -265
- package/dist/ffmpeg/process.js.map +1 -1
- package/dist/ffmpeg/record.d.ts +302 -188
- package/dist/ffmpeg/record.js +408 -560
- package/dist/ffmpeg/record.js.map +1 -1
- package/dist/ffmpeg/recording-process-double.d.ts +144 -0
- package/dist/ffmpeg/recording-process-double.js +168 -0
- package/dist/ffmpeg/recording-process-double.js.map +1 -0
- package/dist/ffmpeg/rtp-parser.d.ts +70 -0
- package/dist/ffmpeg/rtp-parser.js +77 -0
- package/dist/ffmpeg/rtp-parser.js.map +1 -0
- package/dist/ffmpeg/rtp.d.ts +198 -141
- package/dist/ffmpeg/rtp.js +473 -244
- package/dist/ffmpeg/rtp.js.map +1 -1
- package/dist/ffmpeg/settings.d.ts +5 -1
- package/dist/ffmpeg/settings.js +20 -2
- package/dist/ffmpeg/settings.js.map +1 -1
- package/dist/ffmpeg/stream.d.ts +57 -107
- package/dist/ffmpeg/stream.js +121 -148
- package/dist/ffmpeg/stream.js.map +1 -1
- package/dist/formatters.d.ts +106 -0
- package/dist/formatters.js +174 -0
- package/dist/formatters.js.map +1 -0
- package/dist/homebridge-enums.d.ts +30 -0
- package/dist/homebridge-enums.js +17 -0
- package/dist/homebridge-enums.js.map +1 -0
- package/dist/index.d.ts +12 -5
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/logclient/auth.d.ts +114 -0
- package/dist/logclient/auth.js +199 -0
- package/dist/logclient/auth.js.map +1 -0
- package/dist/logclient/cli-run.d.ts +76 -0
- package/dist/logclient/cli-run.js +639 -0
- package/dist/logclient/cli-run.js.map +1 -0
- package/dist/logclient/cli.d.ts +3 -0
- package/dist/logclient/cli.js +97 -0
- package/dist/logclient/cli.js.map +1 -0
- package/dist/logclient/client.d.ts +145 -0
- package/dist/logclient/client.js +600 -0
- package/dist/logclient/client.js.map +1 -0
- package/dist/logclient/config.d.ts +173 -0
- package/dist/logclient/config.js +199 -0
- package/dist/logclient/config.js.map +1 -0
- package/dist/logclient/endpoints.d.ts +54 -0
- package/dist/logclient/endpoints.js +73 -0
- package/dist/logclient/endpoints.js.map +1 -0
- package/dist/logclient/filter.d.ts +45 -0
- package/dist/logclient/filter.js +51 -0
- package/dist/logclient/filter.js.map +1 -0
- package/dist/logclient/frame.d.ts +93 -0
- package/dist/logclient/frame.js +203 -0
- package/dist/logclient/frame.js.map +1 -0
- package/dist/logclient/index.d.ts +31 -0
- package/dist/logclient/index.js +12 -0
- package/dist/logclient/index.js.map +1 -0
- package/dist/logclient/parser.d.ts +211 -0
- package/dist/logclient/parser.js +393 -0
- package/dist/logclient/parser.js.map +1 -0
- package/dist/logclient/rest.d.ts +41 -0
- package/dist/logclient/rest.js +111 -0
- package/dist/logclient/rest.js.map +1 -0
- package/dist/logclient/settings.d.ts +15 -0
- package/dist/logclient/settings.js +64 -0
- package/dist/logclient/settings.js.map +1 -0
- package/dist/logclient/socket-double.d.ts +201 -0
- package/dist/logclient/socket-double.js +384 -0
- package/dist/logclient/socket-double.js.map +1 -0
- package/dist/logclient/socket.d.ts +257 -0
- package/dist/logclient/socket.js +620 -0
- package/dist/logclient/socket.js.map +1 -0
- package/dist/logclient/stitch.d.ts +83 -0
- package/dist/logclient/stitch.js +146 -0
- package/dist/logclient/stitch.js.map +1 -0
- package/dist/logclient/time-expression.d.ts +42 -0
- package/dist/logclient/time-expression.js +181 -0
- package/dist/logclient/time-expression.js.map +1 -0
- package/dist/logclient/time-window.d.ts +38 -0
- package/dist/logclient/time-window.js +53 -0
- package/dist/logclient/time-window.js.map +1 -0
- package/dist/logclient/types.d.ts +107 -0
- package/dist/logclient/types.js +6 -0
- package/dist/logclient/types.js.map +1 -0
- package/dist/mqttClient.d.ts +287 -0
- package/dist/mqttClient.js +433 -0
- package/dist/mqttClient.js.map +1 -0
- package/dist/service.d.ts +64 -15
- package/dist/service.js +93 -66
- package/dist/service.js.map +1 -1
- package/dist/ui/featureOptions.js +870 -0
- package/dist/ui/featureOptions.js.map +1 -0
- package/dist/ui/formatters.js +174 -0
- package/dist/ui/formatters.js.map +1 -0
- package/dist/ui/pluginConfigSession.mjs +141 -0
- package/dist/ui/webUi-featureOptions/categoryState.mjs +135 -0
- package/dist/ui/webUi-featureOptions/effects/keyboard.mjs +61 -0
- package/dist/ui/webUi-featureOptions/effects/persist.mjs +226 -0
- package/dist/ui/webUi-featureOptions/effects/theme.mjs +398 -0
- package/dist/ui/webUi-featureOptions/effects/tokens.mjs +152 -0
- package/dist/ui/webUi-featureOptions/rendering.mjs +431 -0
- package/dist/ui/webUi-featureOptions/selectors.mjs +360 -0
- package/dist/ui/webUi-featureOptions/state.mjs +319 -0
- package/dist/ui/webUi-featureOptions/store.mjs +181 -0
- package/dist/ui/webUi-featureOptions/utils.mjs +200 -0
- package/dist/ui/webUi-featureOptions/views/connectionError.mjs +152 -0
- package/dist/ui/webUi-featureOptions/views/deviceInfo.mjs +80 -0
- package/dist/ui/webUi-featureOptions/views/header.mjs +77 -0
- package/dist/ui/webUi-featureOptions/views/nav.mjs +327 -0
- package/dist/ui/webUi-featureOptions/views/options.mjs +521 -0
- package/dist/ui/webUi-featureOptions/views/search.mjs +395 -0
- package/dist/ui/webUi-featureOptions.mjs +677 -0
- package/dist/ui/webUi.mjs +192 -87
- package/dist/util.d.ts +597 -45
- package/dist/util.js +787 -68
- package/dist/util.js.map +1 -1
- package/package.json +33 -15
- package/build/eslint-rules.mjs +0 -511
- package/dist/featureoptions.d.ts +0 -264
- package/dist/featureoptions.js +0 -480
- package/dist/featureoptions.js.map +0 -1
- package/dist/mqttclient.d.ts +0 -178
- package/dist/mqttclient.js +0 -310
- package/dist/mqttclient.js.map +0 -1
- package/dist/ui/featureoptions.js +0 -480
- package/dist/ui/featureoptions.js.map +0 -1
- package/dist/ui/webUi-featureoptions.mjs +0 -3765
package/dist/featureoptions.js
DELETED
|
@@ -1,480 +0,0 @@
|
|
|
1
|
-
/* Copyright(C) 2017-2026, HJD (https://github.com/hjdhjd). All rights reserved.
|
|
2
|
-
*
|
|
3
|
-
* featureoptions.ts: Hierarchical feature option capabilities for use in plugins and applications.
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* FeatureOptions provides a hierarchical feature option system for plugins and applications.
|
|
7
|
-
*
|
|
8
|
-
* Supports global, controller, and device-level configuration, value-centric feature options, grouping, and category management.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
*
|
|
12
|
-
* ```ts
|
|
13
|
-
* // Define categories and options.
|
|
14
|
-
* const categories = [
|
|
15
|
-
*
|
|
16
|
-
* { name: "motion", description: "Motion Options" },
|
|
17
|
-
* { name: "audio", description: "Audio Options" }
|
|
18
|
-
* ];
|
|
19
|
-
*
|
|
20
|
-
* const options = {
|
|
21
|
-
*
|
|
22
|
-
* motion: [
|
|
23
|
-
* { name: "detect", default: true, description: "Enable motion detection." }
|
|
24
|
-
* ],
|
|
25
|
-
*
|
|
26
|
-
* audio: [
|
|
27
|
-
* { name: "volume", default: false, defaultValue: 50, description: "Audio volume." }
|
|
28
|
-
* ]
|
|
29
|
-
* };
|
|
30
|
-
*
|
|
31
|
-
* // Instantiate FeatureOptions.
|
|
32
|
-
* const featureOpts = new FeatureOptions(categories, options, ["Enable.motion.detect"]);
|
|
33
|
-
*
|
|
34
|
-
* // Check if a feature is enabled.
|
|
35
|
-
* const motionEnabled = featureOpts.test("motion.detect");
|
|
36
|
-
*
|
|
37
|
-
* // Get a value-centric feature option.
|
|
38
|
-
* const volume = featureOpts.value("audio.volume");
|
|
39
|
-
* ```
|
|
40
|
-
*
|
|
41
|
-
* @see FeatureOptionEntry
|
|
42
|
-
* @see FeatureCategoryEntry
|
|
43
|
-
* @see OptionScope
|
|
44
|
-
*/
|
|
45
|
-
export class FeatureOptions {
|
|
46
|
-
/**
|
|
47
|
-
* Default return value for unknown options (defaults to false).
|
|
48
|
-
*/
|
|
49
|
-
defaultReturnValue;
|
|
50
|
-
_categories;
|
|
51
|
-
_configuredOptions;
|
|
52
|
-
_groups;
|
|
53
|
-
_options;
|
|
54
|
-
configLookup;
|
|
55
|
-
defaults;
|
|
56
|
-
valueOptions;
|
|
57
|
-
/**
|
|
58
|
-
* Create a new FeatureOptions instance.
|
|
59
|
-
*
|
|
60
|
-
* @param categories - Array of feature option categories.
|
|
61
|
-
* @param options - Dictionary mapping category names to arrays of feature options.
|
|
62
|
-
* @param configuredOptions - Optional. Array of currently configured option strings.
|
|
63
|
-
*
|
|
64
|
-
* @example
|
|
65
|
-
*
|
|
66
|
-
* ```ts
|
|
67
|
-
* const featureOpts = new FeatureOptions(categories, options, ["Enable.motion.detect"]);
|
|
68
|
-
* ```
|
|
69
|
-
*/
|
|
70
|
-
constructor(categories, options, configuredOptions = []) {
|
|
71
|
-
// Initialize our defaults.
|
|
72
|
-
this._categories = [];
|
|
73
|
-
this._configuredOptions = [];
|
|
74
|
-
this._groups = {};
|
|
75
|
-
this._options = {};
|
|
76
|
-
this.configLookup = new Map();
|
|
77
|
-
this.defaultReturnValue = false;
|
|
78
|
-
this.defaults = {};
|
|
79
|
-
this.valueOptions = {};
|
|
80
|
-
this.categories = categories;
|
|
81
|
-
this.configuredOptions = configuredOptions;
|
|
82
|
-
this.options = options;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Return a Bootstrap-specific color reference depending on the scope of a given feature option.
|
|
86
|
-
*
|
|
87
|
-
* @param option - Feature option to check.
|
|
88
|
-
* @param device - Optional device scope identifier.
|
|
89
|
-
* @param controller - Optional controller scope identifier.
|
|
90
|
-
*
|
|
91
|
-
* @returns Returns a Bootstrap color utility class associated with each scope level. `text-info` denotes an entry that's been modified at that scope level, while
|
|
92
|
-
* `text-success` and `text-warning` denote options that were defined at higher levels in the scope hierarchy - controller and global, respectively.
|
|
93
|
-
*/
|
|
94
|
-
color(option, device, controller) {
|
|
95
|
-
switch (this.scope(option, device, controller)) {
|
|
96
|
-
case "device":
|
|
97
|
-
return "text-info";
|
|
98
|
-
case "controller":
|
|
99
|
-
return "text-success";
|
|
100
|
-
case "global":
|
|
101
|
-
return device ? "text-warning" : "text-info";
|
|
102
|
-
default:
|
|
103
|
-
return "";
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Return the default value for an option.
|
|
108
|
-
*
|
|
109
|
-
* @param option - Feature option to check.
|
|
110
|
-
*
|
|
111
|
-
* @returns Returns true or false, depending on the option default.
|
|
112
|
-
*/
|
|
113
|
-
defaultValue(option) {
|
|
114
|
-
// If it's unknown to us, return the default return value.
|
|
115
|
-
return this.defaults[option.toLowerCase()] ?? this.defaultReturnValue;
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Return whether the option explicitly exists in the list of configured options.
|
|
119
|
-
*
|
|
120
|
-
* @param option - Feature option to check.
|
|
121
|
-
* @param id - Optional device or controller scope identifier to check.
|
|
122
|
-
*
|
|
123
|
-
* @returns Returns true if the option has been explicitly configured, false otherwise.
|
|
124
|
-
*/
|
|
125
|
-
exists(option, id) {
|
|
126
|
-
return this.configLookup.has(option.toLowerCase() + (id ? "." + id.toLowerCase() : ""));
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Return a fully formed feature option string.
|
|
130
|
-
*
|
|
131
|
-
* @param category - Feature option category entry or category name string.
|
|
132
|
-
* @param option - Feature option entry of option name string.
|
|
133
|
-
*
|
|
134
|
-
* @returns Returns a fully formed feature option in the form of `category.option`.
|
|
135
|
-
*/
|
|
136
|
-
expandOption(category, option) {
|
|
137
|
-
const categoryName = (typeof category === "string") ? category : category.name;
|
|
138
|
-
const optionName = (typeof option === "string") ? option : option.name;
|
|
139
|
-
if (!categoryName.length) {
|
|
140
|
-
return "";
|
|
141
|
-
}
|
|
142
|
-
return (!optionName.length) ? categoryName : categoryName + "." + optionName;
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Parse a floating point feature option value.
|
|
146
|
-
*
|
|
147
|
-
* @param option - Feature option to check.
|
|
148
|
-
* @param device - Optional device scope identifier.
|
|
149
|
-
* @param controller - Optional controller scope identifier.
|
|
150
|
-
*
|
|
151
|
-
* @returns Returns the value of a value-centric option as a floating point number, `undefined` if it doesn't exist or couldn't be parsed, and `null` if disabled.
|
|
152
|
-
*/
|
|
153
|
-
getFloat(option, device, controller) {
|
|
154
|
-
// Parse the number and return the value.
|
|
155
|
-
return this.parseOptionNumeric(this.value(option, device, controller), parseFloat);
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Parse an integer feature option value.
|
|
159
|
-
*
|
|
160
|
-
* @param option - Feature option to check.
|
|
161
|
-
* @param device - Optional device scope identifier.
|
|
162
|
-
* @param controller - Optional controller scope identifier.
|
|
163
|
-
*
|
|
164
|
-
* @returns Returns the value of a value-centric option as an integer, `undefined` if it doesn't exist or couldn't be parsed, and `null` if disabled.
|
|
165
|
-
*/
|
|
166
|
-
getInteger(option, device, controller) {
|
|
167
|
-
// Parse the number and return the value.
|
|
168
|
-
return this.parseOptionNumeric(this.value(option, device, controller), parseInt);
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Return whether an option has been set in either the device or controller scope context.
|
|
172
|
-
*
|
|
173
|
-
* @param option - Feature option to check.
|
|
174
|
-
*
|
|
175
|
-
* @returns Returns true if the option is set at the device or controller level and false otherwise.
|
|
176
|
-
*/
|
|
177
|
-
isScopeDevice(option, device) {
|
|
178
|
-
return this.exists(option, device);
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Return whether an option has been set in the global scope context.
|
|
182
|
-
*
|
|
183
|
-
* @param option - Feature option to check.
|
|
184
|
-
*
|
|
185
|
-
* @returns Returns true if the option is set globally and false otherwise.
|
|
186
|
-
*/
|
|
187
|
-
isScopeGlobal(option) {
|
|
188
|
-
return this.exists(option);
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* Return whether an option is value-centric or not.
|
|
192
|
-
*
|
|
193
|
-
* @param option - Feature option entry or string to check.
|
|
194
|
-
*
|
|
195
|
-
* @returns Returns true if it is a value-centric option and false otherwise.
|
|
196
|
-
*/
|
|
197
|
-
isValue(option) {
|
|
198
|
-
if (!option) {
|
|
199
|
-
return false;
|
|
200
|
-
}
|
|
201
|
-
return option.toLowerCase() in this.valueOptions;
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Return the scope hierarchy location of an option.
|
|
205
|
-
*
|
|
206
|
-
* @param option - Feature option to check.
|
|
207
|
-
* @param device - Optional device scope identifier.
|
|
208
|
-
* @param controller - Optional controller scope identifier.
|
|
209
|
-
*
|
|
210
|
-
* @returns Returns an object containing the location in the scope hierarchy of an `option` as well as the current value associated with the option.
|
|
211
|
-
*/
|
|
212
|
-
scope(option, device, controller) {
|
|
213
|
-
return this.optionInfo(option, device, controller).scope;
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* Return the current state of a feature option, traversing the scope hierarchy.
|
|
217
|
-
*
|
|
218
|
-
* @param option - Feature option to check.
|
|
219
|
-
* @param device - Optional device scope identifier.
|
|
220
|
-
* @param controller - Optional controller scope identifier.
|
|
221
|
-
*
|
|
222
|
-
* @returns Returns true if the option is enabled, and false otherwise.
|
|
223
|
-
*/
|
|
224
|
-
test(option, device, controller) {
|
|
225
|
-
return this.optionInfo(option, device, controller).value;
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Return the value associated with a value-centric feature option, traversing the scope hierarchy.
|
|
229
|
-
*
|
|
230
|
-
* @param option - Feature option to check.
|
|
231
|
-
* @param device - Optional device scope identifier.
|
|
232
|
-
* @param controller - Optional controller scope identifier.
|
|
233
|
-
*
|
|
234
|
-
* @returns Returns the current value associated with `option` if the feature option is enabled, `null` if disabled (or not a value-centric feature option), or
|
|
235
|
-
* `undefined` if it's not specified.
|
|
236
|
-
*/
|
|
237
|
-
value(option, device, controller) {
|
|
238
|
-
// If this isn't a value-centric feature option, we're done.
|
|
239
|
-
if (!this.isValue(option)) {
|
|
240
|
-
return null;
|
|
241
|
-
}
|
|
242
|
-
// Resolve the option through the scope hierarchy in a single traversal. This gives us the scope, enabled state, and raw value in one pass.
|
|
243
|
-
const resolved = this.resolveScope(option, device, controller);
|
|
244
|
-
// If the option has been explicitly disabled at any scope, or wasn't configured and its default is disabled, there's no value.
|
|
245
|
-
if (!resolved.enabled) {
|
|
246
|
-
return null;
|
|
247
|
-
}
|
|
248
|
-
// If we found an explicit value in the index, return it.
|
|
249
|
-
if (resolved.optionValue) {
|
|
250
|
-
return resolved.optionValue;
|
|
251
|
-
}
|
|
252
|
-
// The option is enabled but has no explicit value. If it wasn't configured at any scope (scope is "none"), fall back to the registered default value.
|
|
253
|
-
if (resolved.scope === "none") {
|
|
254
|
-
return this.valueOptions[option.toLowerCase()]?.toString() ?? null;
|
|
255
|
-
}
|
|
256
|
-
// The option is enabled at an explicit scope but no value was provided...return undefined to indicate "enabled, no value."
|
|
257
|
-
return undefined;
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* Return the list of available feature option categories.
|
|
261
|
-
*
|
|
262
|
-
* @returns Returns the current list of available feature option categories.
|
|
263
|
-
*/
|
|
264
|
-
get categories() {
|
|
265
|
-
return this._categories;
|
|
266
|
-
}
|
|
267
|
-
/**
|
|
268
|
-
* Set the list of available feature option categories.
|
|
269
|
-
*
|
|
270
|
-
* @param category - Array of available categories.
|
|
271
|
-
*/
|
|
272
|
-
set categories(category) {
|
|
273
|
-
this._categories = category;
|
|
274
|
-
// Regenerate defaults and the lookup index.
|
|
275
|
-
this.generateDefaults();
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* Return the list of currently configured feature options.
|
|
279
|
-
*
|
|
280
|
-
* @returns Returns the currently configured list of feature options.
|
|
281
|
-
*/
|
|
282
|
-
get configuredOptions() {
|
|
283
|
-
return this._configuredOptions;
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Set the list of currently configured feature options.
|
|
287
|
-
*
|
|
288
|
-
* @param options - Array of configured feature options.
|
|
289
|
-
*/
|
|
290
|
-
set configuredOptions(options) {
|
|
291
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
292
|
-
this._configuredOptions = options ?? [];
|
|
293
|
-
// Regenerate defaults and the lookup index.
|
|
294
|
-
this.generateDefaults();
|
|
295
|
-
}
|
|
296
|
-
/**
|
|
297
|
-
* Return the list of available feature option groups.
|
|
298
|
-
*
|
|
299
|
-
* @returns Returns the current list of available feature option groups.
|
|
300
|
-
*/
|
|
301
|
-
get groups() {
|
|
302
|
-
return this._groups;
|
|
303
|
-
}
|
|
304
|
-
/**
|
|
305
|
-
* Return the list of available feature options.
|
|
306
|
-
*
|
|
307
|
-
* @returns Returns the current list of available feature options.
|
|
308
|
-
*/
|
|
309
|
-
get options() {
|
|
310
|
-
return this._options;
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* Set the list of available feature options.
|
|
314
|
-
*
|
|
315
|
-
* @param options - Array of available feature options.
|
|
316
|
-
*/
|
|
317
|
-
set options(options) {
|
|
318
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
319
|
-
this._options = options ?? {};
|
|
320
|
-
// Regenerate defaults and the lookup index.
|
|
321
|
-
this.generateDefaults();
|
|
322
|
-
}
|
|
323
|
-
// Rebuild the defaults, groups, value options, and lookup index from the current categories, options, and configured options. All three property setters call this so
|
|
324
|
-
// that state is always consistent regardless of which setter is called or in what order.
|
|
325
|
-
generateDefaults() {
|
|
326
|
-
this.defaults = {};
|
|
327
|
-
this._groups = {};
|
|
328
|
-
this.valueOptions = {};
|
|
329
|
-
for (const category of this.categories) {
|
|
330
|
-
// If the category doesn't exist, let's skip it.
|
|
331
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
332
|
-
if (!this.options[category.name]) {
|
|
333
|
-
continue;
|
|
334
|
-
}
|
|
335
|
-
// Now enumerate all the feature options for a given device and add then to the full list.
|
|
336
|
-
for (const option of this.options[category.name]) {
|
|
337
|
-
// Expand the entry.
|
|
338
|
-
const entry = this.expandOption(category, option);
|
|
339
|
-
// Index the default value.
|
|
340
|
-
this.defaults[entry.toLowerCase()] = option.default;
|
|
341
|
-
// Track value-centric options.
|
|
342
|
-
if ("defaultValue" in option) {
|
|
343
|
-
this.valueOptions[entry.toLowerCase()] = option.defaultValue;
|
|
344
|
-
}
|
|
345
|
-
// Cross reference the feature option group it belongs to, if any.
|
|
346
|
-
if (option.group !== undefined) {
|
|
347
|
-
const expandedGroup = category.name + (option.group.length ? ("." + option.group) : "");
|
|
348
|
-
// Initialize the group entry if needed and add the entry.
|
|
349
|
-
(this._groups[expandedGroup] ??= []).push(entry);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
// Rebuild the lookup index now that we know which options are value-centric.
|
|
354
|
-
this.buildConfigIndex();
|
|
355
|
-
}
|
|
356
|
-
// Resolves a feature option through the scope hierarchy in a single traversal. Returns the scope where the option was found, whether it's enabled, and the raw string
|
|
357
|
-
// value for value-centric options. This is the core resolution method that both test()/scope() and value() build on, eliminating the need for separate traversals.
|
|
358
|
-
//
|
|
359
|
-
// There are a couple of ways to enable and disable options. The rules of the road are:
|
|
360
|
-
//
|
|
361
|
-
// 1. Explicitly disabling or enabling an option on the controller propagates to all the devices that are managed by that controller.
|
|
362
|
-
//
|
|
363
|
-
// 2. Explicitly disabling or enabling an option on a device always overrides the above. This means that it's possible to disable an option for a controller, and all
|
|
364
|
-
// the devices that are managed by it, and then override that behavior on a single device that it's managing.
|
|
365
|
-
resolveScope(option, device, controller) {
|
|
366
|
-
const normalizedOption = option.toLowerCase();
|
|
367
|
-
let entry;
|
|
368
|
-
// Check to see if we have a device-level option first.
|
|
369
|
-
if (device) {
|
|
370
|
-
entry = this.configLookup.get(normalizedOption + "." + device.toLowerCase());
|
|
371
|
-
if (entry) {
|
|
372
|
-
return { enabled: entry.enabled, optionValue: entry.value, scope: "device" };
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
// Now check to see if we have a controller-level option.
|
|
376
|
-
if (controller) {
|
|
377
|
-
entry = this.configLookup.get(normalizedOption + "." + controller.toLowerCase());
|
|
378
|
-
if (entry) {
|
|
379
|
-
return { enabled: entry.enabled, optionValue: entry.value, scope: "controller" };
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
// Finally, we check for a global-level value.
|
|
383
|
-
entry = this.configLookup.get(normalizedOption);
|
|
384
|
-
if (entry) {
|
|
385
|
-
return { enabled: entry.enabled, optionValue: entry.value, scope: "global" };
|
|
386
|
-
}
|
|
387
|
-
// The option hasn't been set at any scope, return our default value.
|
|
388
|
-
return { enabled: this.defaultValue(option), scope: "none" };
|
|
389
|
-
}
|
|
390
|
-
// Thin wrapper over resolveScope() that returns the OptionInfoEntry shape expected by test() and scope().
|
|
391
|
-
optionInfo(option, device, controller) {
|
|
392
|
-
const resolved = this.resolveScope(option, device, controller);
|
|
393
|
-
return { scope: resolved.scope, value: resolved.enabled };
|
|
394
|
-
}
|
|
395
|
-
// Utility function to parse and return a numeric configuration parameter.
|
|
396
|
-
parseOptionNumeric(option, convert) {
|
|
397
|
-
// If the option is disabled or we don't have it configured -- we're done.
|
|
398
|
-
if (!option) {
|
|
399
|
-
return (option === null) ? null : undefined;
|
|
400
|
-
}
|
|
401
|
-
// Convert it to a number, if needed.
|
|
402
|
-
const convertedValue = convert(option);
|
|
403
|
-
// Let's validate to make sure it's really a number.
|
|
404
|
-
if (isNaN(convertedValue)) {
|
|
405
|
-
return undefined;
|
|
406
|
-
}
|
|
407
|
-
// Return the value.
|
|
408
|
-
return convertedValue;
|
|
409
|
-
}
|
|
410
|
-
// Build a lookup index from the configured option strings. Each entry is keyed by its normalized lookup path (option name, or option name + scope id) and stores
|
|
411
|
-
// whether the option is enabled along with the extracted value for value-centric options. The index is built once when configured options or option definitions change,
|
|
412
|
-
// and all subsequent lookups are O(1).
|
|
413
|
-
buildConfigIndex() {
|
|
414
|
-
this.configLookup = new Map();
|
|
415
|
-
// Collect known value option names, sorted longest first for greedy prefix matching. This ensures that when option names overlap (e.g., a category "audio" and an
|
|
416
|
-
// option "audio.volume"), the more specific name matches first.
|
|
417
|
-
const valueOptionNames = Object.keys(this.valueOptions).sort((a, b) => b.length - a.length);
|
|
418
|
-
for (const rawEntry of this._configuredOptions) {
|
|
419
|
-
// Parse the action prefix (Enable or Disable).
|
|
420
|
-
const dotIndex = rawEntry.indexOf(".");
|
|
421
|
-
if (dotIndex === -1) {
|
|
422
|
-
continue;
|
|
423
|
-
}
|
|
424
|
-
const action = rawEntry.slice(0, dotIndex).toLowerCase();
|
|
425
|
-
if ((action !== "enable") && (action !== "disable")) {
|
|
426
|
-
continue;
|
|
427
|
-
}
|
|
428
|
-
const enabled = action === "enable";
|
|
429
|
-
const tailOriginal = rawEntry.slice(dotIndex + 1);
|
|
430
|
-
const tail = tailOriginal.toLowerCase();
|
|
431
|
-
// Register the exact tail as a lookup key. First-write-wins...if the same option appears multiple times, the earliest entry in the array takes precedence.
|
|
432
|
-
if (!this.configLookup.has(tail)) {
|
|
433
|
-
this.configLookup.set(tail, { enabled });
|
|
434
|
-
}
|
|
435
|
-
// For Enable entries on value-centric options, extract the trailing value segment and register under the base key (option or option.id) so that value lookups
|
|
436
|
-
// resolve in O(1) instead of requiring regex matching and array scanning.
|
|
437
|
-
if (!enabled) {
|
|
438
|
-
continue;
|
|
439
|
-
}
|
|
440
|
-
for (const optName of valueOptionNames) {
|
|
441
|
-
if (!tail.startsWith(optName)) {
|
|
442
|
-
continue;
|
|
443
|
-
}
|
|
444
|
-
const remainder = tail.slice(optName.length);
|
|
445
|
-
// Exact match on the option name with no trailing segments...there's no value to extract.
|
|
446
|
-
if (!remainder.length) {
|
|
447
|
-
break;
|
|
448
|
-
}
|
|
449
|
-
// The next character must be a dot separator. If not, this option name is merely a prefix of a longer unrelated token.
|
|
450
|
-
if (!remainder.startsWith(".")) {
|
|
451
|
-
continue;
|
|
452
|
-
}
|
|
453
|
-
const extra = remainder.slice(1);
|
|
454
|
-
const extraOriginal = tailOriginal.slice(optName.length + 1);
|
|
455
|
-
const separatorIndex = extra.indexOf(".");
|
|
456
|
-
if (separatorIndex === -1) {
|
|
457
|
-
// Single trailing segment after the option name. At global scope this is the value; at scoped scope it's the id. Register under the option name as the
|
|
458
|
-
// base key so that global value lookups find it.
|
|
459
|
-
if (!this.configLookup.has(optName)) {
|
|
460
|
-
this.configLookup.set(optName, { enabled: true, value: extraOriginal });
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
else {
|
|
464
|
-
// Two trailing segments: the first is the scope id and the second is the value.
|
|
465
|
-
const idLower = extra.slice(0, separatorIndex);
|
|
466
|
-
const valueOriginal = extraOriginal.slice(separatorIndex + 1);
|
|
467
|
-
// Only register if the value portion is a single segment (no additional dots).
|
|
468
|
-
if (!valueOriginal.includes(".")) {
|
|
469
|
-
const baseKey = optName + "." + idLower;
|
|
470
|
-
if (!this.configLookup.has(baseKey)) {
|
|
471
|
-
this.configLookup.set(baseKey, { enabled: true, value: valueOriginal });
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
break;
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
//# sourceMappingURL=featureoptions.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"featureoptions.js","sourceRoot":"","sources":["../src/featureoptions.ts"],"names":[],"mappings":"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"}
|
package/dist/mqttclient.d.ts
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MQTT connectivity and topic management for Homebridge plugins.
|
|
3
|
-
*
|
|
4
|
-
* @module
|
|
5
|
-
*/
|
|
6
|
-
import type { HomebridgePluginLogging } from "./util.js";
|
|
7
|
-
/**
|
|
8
|
-
* MQTT connectivity and topic management class for Homebridge plugins.
|
|
9
|
-
*
|
|
10
|
-
* This class manages connection, publishing, subscription, and message handling for an MQTT broker, and provides convenience methods for Homebridge accessories to
|
|
11
|
-
* interact with MQTT topics using a standard topic prefix.
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
*
|
|
15
|
-
* ```ts
|
|
16
|
-
* const mqtt = new MqttClient("mqtt://localhost:1883", "homebridge", log);
|
|
17
|
-
*
|
|
18
|
-
* // Publish a message to a topic.
|
|
19
|
-
* mqtt.publish("device1", "status", "on");
|
|
20
|
-
*
|
|
21
|
-
* // Subscribe to a topic.
|
|
22
|
-
* mqtt.subscribe("device1", "status", (msg) => {
|
|
23
|
-
*
|
|
24
|
-
* console.log(msg.toString());
|
|
25
|
-
* });
|
|
26
|
-
*
|
|
27
|
-
* // Subscribe to a 'get' topic and automatically publish a value in response.
|
|
28
|
-
* mqtt.subscribeGet("device1", "temperature", "Temperature", () => "21.5");
|
|
29
|
-
*
|
|
30
|
-
* // Subscribe to a 'set' topic and handle value changes.
|
|
31
|
-
* mqtt.subscribeSet("device1", "switch", "Switch", (value) => {
|
|
32
|
-
*
|
|
33
|
-
* console.log("Switch set to", value);
|
|
34
|
-
* });
|
|
35
|
-
*
|
|
36
|
-
* // Unsubscribe from a topic.
|
|
37
|
-
* mqtt.unsubscribe("device1", "status");
|
|
38
|
-
* ```
|
|
39
|
-
*/
|
|
40
|
-
export declare class MqttClient {
|
|
41
|
-
private brokerUrl;
|
|
42
|
-
private isConnected;
|
|
43
|
-
private reconnectInterval;
|
|
44
|
-
private log;
|
|
45
|
-
private mqtt;
|
|
46
|
-
private subscriptions;
|
|
47
|
-
private topicPrefix;
|
|
48
|
-
/**
|
|
49
|
-
* Creates a new MQTT client for connecting to a broker and managing topics with a given prefix.
|
|
50
|
-
*
|
|
51
|
-
* @param brokerUrl - The MQTT broker URL (e.g., "mqtt://localhost:1883").
|
|
52
|
-
* @param topicPrefix - Prefix to use for all MQTT topics (e.g., "homebridge").
|
|
53
|
-
* @param log - Logger for debug and info messages.
|
|
54
|
-
* @param reconnectInterval - Optional. Interval (in seconds) to wait between reconnection attempts. Defaults to 60 seconds.
|
|
55
|
-
*
|
|
56
|
-
* @example
|
|
57
|
-
*
|
|
58
|
-
* ```ts
|
|
59
|
-
* const mqtt = new MqttClient("mqtt://localhost", "homebridge", log);
|
|
60
|
-
* ```
|
|
61
|
-
*
|
|
62
|
-
* @remarks URL must conform to formats supported by {@link https://github.com/mqttjs/MQTT.js | MQTT.js}.
|
|
63
|
-
*/
|
|
64
|
-
constructor(brokerUrl: string, topicPrefix: string, log: HomebridgePluginLogging, reconnectInterval?: number);
|
|
65
|
-
/**
|
|
66
|
-
* Initializes and connects the MQTT client to the broker, setting up event handlers for connection, messages, and errors.
|
|
67
|
-
*
|
|
68
|
-
* Catches invalid broker URLs and logs errors. Handles all major MQTT client events internally.
|
|
69
|
-
*/
|
|
70
|
-
private configure;
|
|
71
|
-
/**
|
|
72
|
-
* Publishes a message to a topic for a specific device.
|
|
73
|
-
*
|
|
74
|
-
* Expands the topic using the topic prefix and device ID, then publishes the provided message string.
|
|
75
|
-
*
|
|
76
|
-
* @param id - The device or accessory identifier.
|
|
77
|
-
* @param topic - The topic name to publish to.
|
|
78
|
-
* @param message - The message payload to publish.
|
|
79
|
-
*
|
|
80
|
-
* @example
|
|
81
|
-
*
|
|
82
|
-
* ```ts
|
|
83
|
-
* mqtt.publish("device1", "status", "on");
|
|
84
|
-
* ```
|
|
85
|
-
*/
|
|
86
|
-
publish(id: string, topic: string, message: string): void;
|
|
87
|
-
/**
|
|
88
|
-
* Subscribes to a topic for a specific device and registers a handler for incoming messages.
|
|
89
|
-
*
|
|
90
|
-
* The topic is expanded using the prefix and device ID, and the callback will be called for each message received.
|
|
91
|
-
*
|
|
92
|
-
* @param id - The device or accessory identifier.
|
|
93
|
-
* @param topic - The topic name to subscribe to.
|
|
94
|
-
* @param callback - Handler function called with the message buffer.
|
|
95
|
-
*
|
|
96
|
-
* @example
|
|
97
|
-
*
|
|
98
|
-
* ```ts
|
|
99
|
-
* mqtt.subscribe("device1", "status", (msg) => {
|
|
100
|
-
*
|
|
101
|
-
* console.log(msg.toString());
|
|
102
|
-
* });
|
|
103
|
-
* ```
|
|
104
|
-
*/
|
|
105
|
-
subscribe(id: string, topic: string, callback: (cbBuffer: Buffer) => Promise<void> | void): void;
|
|
106
|
-
/**
|
|
107
|
-
* Subscribes to a '<topic>/get' topic and publishes a value in response to "true" messages.
|
|
108
|
-
*
|
|
109
|
-
* When a message "true" is received on the '<topic>/get' topic, this method will publish the result of `getValue()` on the main topic. The log will record each status
|
|
110
|
-
* publication event.
|
|
111
|
-
*
|
|
112
|
-
* @param id - The device or accessory identifier.
|
|
113
|
-
* @param topic - The topic name to use.
|
|
114
|
-
* @param type - A human-readable label for log messages (e.g., "Temperature").
|
|
115
|
-
* @param getValue - Function to get the value to publish as a string.
|
|
116
|
-
* @param log - Optional logger for status output. Defaults to the class logger.
|
|
117
|
-
*
|
|
118
|
-
* @example
|
|
119
|
-
*
|
|
120
|
-
* ```ts
|
|
121
|
-
* mqtt.subscribeGet("device1", "temperature", "Temperature", () => "21.5");
|
|
122
|
-
* ```
|
|
123
|
-
*/
|
|
124
|
-
subscribeGet(id: string, topic: string, type: string, getValue: () => string, log?: HomebridgePluginLogging): void;
|
|
125
|
-
/**
|
|
126
|
-
* Subscribes to a '<topic>/set' topic and calls a setter when a message is received.
|
|
127
|
-
*
|
|
128
|
-
* The `setValue` function is called with both a normalized value and the raw string. Handles both synchronous and promise-based setters. Logs when set messages are
|
|
129
|
-
* received and when errors occur.
|
|
130
|
-
*
|
|
131
|
-
* @param id - The device or accessory identifier.
|
|
132
|
-
* @param topic - The topic name to use.
|
|
133
|
-
* @param type - A human-readable label for log messages (e.g., "Switch").
|
|
134
|
-
* @param setValue - Function to call when a value is set. Can be synchronous or return a Promise.
|
|
135
|
-
* @param log - Optional logger for status output. Defaults to the class logger.
|
|
136
|
-
*
|
|
137
|
-
* @example
|
|
138
|
-
*
|
|
139
|
-
* ```ts
|
|
140
|
-
* mqtt.subscribeSet("device1", "switch", "Switch", (value) => {
|
|
141
|
-
*
|
|
142
|
-
* console.log("Switch set to", value);
|
|
143
|
-
* });
|
|
144
|
-
* ```
|
|
145
|
-
*/
|
|
146
|
-
subscribeSet(id: string, topic: string, type: string, setValue: (value: string, rawValue: string) => Promise<void> | void, log?: HomebridgePluginLogging): void;
|
|
147
|
-
/**
|
|
148
|
-
* Unsubscribes from a topic for a specific device, removing its message handler.
|
|
149
|
-
*
|
|
150
|
-
* @param id - The device or accessory identifier.
|
|
151
|
-
* @param topic - The topic name to unsubscribe from.
|
|
152
|
-
*
|
|
153
|
-
* @example
|
|
154
|
-
*
|
|
155
|
-
* ```ts
|
|
156
|
-
* mqtt.unsubscribe("device1", "status");
|
|
157
|
-
* ```
|
|
158
|
-
*/
|
|
159
|
-
unsubscribe(id: string, topic: string): void;
|
|
160
|
-
/**
|
|
161
|
-
* Expands a topic string into a fully-formed topic path including the prefix and device ID.
|
|
162
|
-
*
|
|
163
|
-
* Returns `null` if the device ID is missing or empty.
|
|
164
|
-
*
|
|
165
|
-
* @param id - The device or accessory identifier.
|
|
166
|
-
* @param topic - The topic name to expand.
|
|
167
|
-
*
|
|
168
|
-
* @returns The expanded topic string, or `null` if the ID is missing.
|
|
169
|
-
*
|
|
170
|
-
* @example
|
|
171
|
-
*
|
|
172
|
-
* ```ts
|
|
173
|
-
* const topic = mqtt['expandTopic']("device1", "status");
|
|
174
|
-
* // topic = "homebridge/device1/status"
|
|
175
|
-
* ```
|
|
176
|
-
*/
|
|
177
|
-
private expandTopic;
|
|
178
|
-
}
|