homebridge-ratgdo 0.1.0 → 1.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/LICENSE.md +1 -1
- package/README.md +13 -3
- package/config.schema.json +46 -14
- package/dist/index.d.ts +3 -0
- package/dist/index.js +5 -7
- package/dist/index.js.map +1 -1
- package/dist/ratgdo-device.d.ts +44 -0
- package/dist/ratgdo-device.js +464 -96
- package/dist/ratgdo-device.js.map +1 -1
- package/dist/ratgdo-mqtt.d.ts +19 -0
- package/dist/ratgdo-mqtt.js +155 -0
- package/dist/ratgdo-mqtt.js.map +1 -0
- package/dist/ratgdo-options.d.ts +27 -0
- package/dist/ratgdo-options.js +26 -21
- package/dist/ratgdo-options.js.map +1 -1
- package/dist/ratgdo-platform.d.ts +28 -0
- package/dist/ratgdo-platform.js +65 -32
- package/dist/ratgdo-platform.js.map +1 -1
- package/dist/ratgdo-types.d.ts +17 -0
- package/dist/ratgdo-types.js +14 -0
- package/dist/ratgdo-types.js.map +1 -0
- package/dist/settings.d.ts +8 -0
- package/dist/settings.js +14 -9
- package/dist/settings.js.map +1 -1
- package/homebridge-ui/public/index.html +116 -0
- package/homebridge-ui/public/lib/featureoptions.mjs +200 -0
- package/homebridge-ui/public/ratgdo-featureoptions.mjs +638 -0
- package/homebridge-ui/public/ui.mjs +144 -0
- package/homebridge-ui/server.js +58 -0
- package/package.json +13 -9
package/dist/ratgdo-platform.js
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
import { PLATFORM_NAME, PLUGIN_NAME, RATGDO_API_PORT, RATGDO_MQTT_TOPIC } from "./settings.js";
|
|
2
|
+
import { featureOptionCategories, featureOptions, isOptionEnabled } from "./ratgdo-options.js";
|
|
3
|
+
import { createServer } from "node:net";
|
|
4
|
+
import Aedes from "aedes";
|
|
5
|
+
import { RatgdoAccessory } from "./ratgdo-device.js";
|
|
6
|
+
import { RatgdoMqtt } from "./ratgdo-mqtt.js";
|
|
7
|
+
import { URL } from "node:url";
|
|
8
|
+
import util from "node:util";
|
|
9
|
+
export class RatgdoPlatform {
|
|
10
|
+
accessories;
|
|
11
|
+
api;
|
|
12
|
+
broker;
|
|
13
|
+
deviceMac;
|
|
14
|
+
featureOptionDefaults;
|
|
15
|
+
config;
|
|
16
|
+
configOptions;
|
|
17
|
+
configuredDevices;
|
|
18
|
+
hap;
|
|
19
|
+
log;
|
|
20
|
+
mqtt;
|
|
21
|
+
server;
|
|
22
|
+
unsupportedDevices;
|
|
14
23
|
constructor(log, config, api) {
|
|
15
24
|
this.accessories = [];
|
|
16
25
|
this.api = api;
|
|
17
|
-
this.broker = new
|
|
26
|
+
this.broker = new Aedes();
|
|
18
27
|
this.configOptions = [];
|
|
19
28
|
this.configuredDevices = {};
|
|
20
29
|
this.deviceMac = {};
|
|
@@ -22,7 +31,8 @@ class ratgdoPlatform {
|
|
|
22
31
|
this.hap = api.hap;
|
|
23
32
|
this.log = log;
|
|
24
33
|
this.log.debug = this.debug.bind(this);
|
|
25
|
-
this.
|
|
34
|
+
this.mqtt = null;
|
|
35
|
+
this.server = createServer(this.broker.handle);
|
|
26
36
|
this.server.unref();
|
|
27
37
|
this.unsupportedDevices = {};
|
|
28
38
|
this.server.on("error", (error) => {
|
|
@@ -34,8 +44,8 @@ class ratgdoPlatform {
|
|
|
34
44
|
this.server.close();
|
|
35
45
|
});
|
|
36
46
|
// Build our list of default values for our feature options.
|
|
37
|
-
for (const category of
|
|
38
|
-
for (const options of
|
|
47
|
+
for (const category of featureOptionCategories) {
|
|
48
|
+
for (const options of featureOptions[category.name]) {
|
|
39
49
|
this.featureOptionDefaults[(category.name + (options.name.length ? "." + options.name : "")).toLowerCase()] = options.default;
|
|
40
50
|
}
|
|
41
51
|
}
|
|
@@ -45,8 +55,10 @@ class ratgdoPlatform {
|
|
|
45
55
|
}
|
|
46
56
|
this.config = {
|
|
47
57
|
debug: config.debug === true,
|
|
58
|
+
mqttTopic: config.mqttTopic ?? RATGDO_MQTT_TOPIC,
|
|
59
|
+
mqttUrl: config.mqttUrl,
|
|
48
60
|
options: config.options,
|
|
49
|
-
port: "port" in config ? parseInt(config.port) :
|
|
61
|
+
port: "port" in config ? parseInt(config.port) : RATGDO_API_PORT
|
|
50
62
|
};
|
|
51
63
|
// If we have feature options, put them into their own array, upper-cased for future reference.
|
|
52
64
|
if (this.config.options) {
|
|
@@ -54,6 +66,10 @@ class ratgdoPlatform {
|
|
|
54
66
|
this.configOptions.push(featureOption.toLowerCase());
|
|
55
67
|
}
|
|
56
68
|
}
|
|
69
|
+
// Initialize MQTT, if needed.
|
|
70
|
+
if (this.config.mqttUrl) {
|
|
71
|
+
this.mqtt = new RatgdoMqtt(this);
|
|
72
|
+
}
|
|
57
73
|
this.log.debug("Debug logging on. Expect a lot of data.");
|
|
58
74
|
// Fire up the Ratgdo API once Homebridge has loaded all the cached accessories it knows about and called configureAccessory() on each.
|
|
59
75
|
api.on("didFinishLaunching" /* APIEvent.DID_FINISH_LAUNCHING */, this.configureBroker.bind(this));
|
|
@@ -116,8 +132,7 @@ class ratgdoPlatform {
|
|
|
116
132
|
return;
|
|
117
133
|
}
|
|
118
134
|
// Log unknown / unhandled messages.
|
|
119
|
-
this.log.debug("Topic:
|
|
120
|
-
this.log.debug("Message: %s", packet.payload.toString());
|
|
135
|
+
this.log.debug("Topic: " + packet.topic + " | Message: " + packet.payload.toString());
|
|
121
136
|
});
|
|
122
137
|
// Start the broker so we can receive connections from Ratgdo MQTT clients.
|
|
123
138
|
try {
|
|
@@ -143,23 +158,42 @@ class ratgdoPlatform {
|
|
|
143
158
|
this.deviceMac[deviceInfo["~"]] = mac;
|
|
144
159
|
// Generate this device's unique identifier.
|
|
145
160
|
const uuid = this.hap.uuid.generate(mac);
|
|
146
|
-
// See if we already know about this accessory or if it's truly new.
|
|
161
|
+
// See if we already know about this accessory or if it's truly new.
|
|
147
162
|
let accessory = this.accessories.find(x => x.UUID === uuid);
|
|
163
|
+
// Our device details.
|
|
164
|
+
const device = {
|
|
165
|
+
address: new URL(deviceInfo.device.configuration_url)?.hostname ?? "unknown",
|
|
166
|
+
firmwareVersion: deviceInfo.device.sw_version,
|
|
167
|
+
mac: mac.replace(/:/g, ""),
|
|
168
|
+
name: deviceInfo["~"]
|
|
169
|
+
};
|
|
170
|
+
// Inform the user.
|
|
171
|
+
this.log.info("Discovered: %s (address: %s mac: %s firmware: v%s).", device.name, device.address, device.mac, device.firmwareVersion);
|
|
172
|
+
// Check to see if the user has disabled the device.
|
|
173
|
+
if (!isOptionEnabled(this.configOptions, device, "Device", this.featureOptionDefault("Device"))) {
|
|
174
|
+
// If the accessory already exists, let's remove it.
|
|
175
|
+
if (accessory) {
|
|
176
|
+
// Inform the user.
|
|
177
|
+
this.log.info("%s: Removing device from HomeKit.", accessory.displayName);
|
|
178
|
+
// Unregister the accessory and delete it's remnants from HomeKit.
|
|
179
|
+
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
180
|
+
this.accessories.splice(this.accessories.indexOf(accessory), 1);
|
|
181
|
+
this.api.updatePlatformAccessories(this.accessories);
|
|
182
|
+
}
|
|
183
|
+
// We're done.
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
// It's a new device - let's add it to HomeKit.
|
|
148
187
|
if (!accessory) {
|
|
149
|
-
accessory = new this.api.platformAccessory(
|
|
188
|
+
accessory = new this.api.platformAccessory(device.name, uuid);
|
|
150
189
|
// Register this accessory with Homebridge and add it to the accessory array so we can track it.
|
|
151
|
-
this.api.registerPlatformAccessories(
|
|
190
|
+
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
152
191
|
this.accessories.push(accessory);
|
|
153
192
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
mac: mac,
|
|
157
|
-
name: deviceInfo["~"]
|
|
158
|
-
});
|
|
193
|
+
// Add it to our list of configured devices.
|
|
194
|
+
this.configuredDevices[accessory.UUID] = new RatgdoAccessory(this, accessory, device);
|
|
159
195
|
// Refresh the accessory cache.
|
|
160
196
|
this.api.updatePlatformAccessories([accessory]);
|
|
161
|
-
// Inform the user.
|
|
162
|
-
garageDoor.log.info("Device configured.");
|
|
163
197
|
}
|
|
164
198
|
// Utility to return the default value for a feature option.
|
|
165
199
|
featureOptionDefault(option) {
|
|
@@ -173,9 +207,8 @@ class ratgdoPlatform {
|
|
|
173
207
|
// Utility for debug logging.
|
|
174
208
|
debug(message, ...parameters) {
|
|
175
209
|
if (this.config.debug) {
|
|
176
|
-
this.log.
|
|
210
|
+
this.log.error(util.format(message, ...parameters));
|
|
177
211
|
}
|
|
178
212
|
}
|
|
179
213
|
}
|
|
180
|
-
exports.ratgdoPlatform = ratgdoPlatform;
|
|
181
214
|
//# sourceMappingURL=ratgdo-platform.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ratgdo-platform.js","sourceRoot":"","sources":["../src/ratgdo-platform.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ratgdo-platform.js","sourceRoot":"","sources":["../src/ratgdo-platform.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface RatgdoDevice {
|
|
2
|
+
address: string;
|
|
3
|
+
firmwareVersion: string;
|
|
4
|
+
mac: string;
|
|
5
|
+
name: string;
|
|
6
|
+
}
|
|
7
|
+
export interface RatgdoLogging {
|
|
8
|
+
debug: (message: string, ...parameters: unknown[]) => void;
|
|
9
|
+
error: (message: string, ...parameters: unknown[]) => void;
|
|
10
|
+
info: (message: string, ...parameters: unknown[]) => void;
|
|
11
|
+
warn: (message: string, ...parameters: unknown[]) => void;
|
|
12
|
+
}
|
|
13
|
+
export declare enum RatgdoReservedNames {
|
|
14
|
+
OCCUPANCY_SENSOR_DOOR_OPEN = "OccupancySensor.DoorOpen",
|
|
15
|
+
OCCUPANCY_SENSOR_MOTION = "OccupancySensor.Motion",
|
|
16
|
+
SWITCH_OPENER_AUTOMATION = "Switch.Opener.Automation"
|
|
17
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/* Copyright(C) 2020-2024, HJD (https://github.com/hjdhjd). All rights reserved.
|
|
2
|
+
*
|
|
3
|
+
* ratgdo-types.ts: Interface and type definitions for Ratgdo.
|
|
4
|
+
*/
|
|
5
|
+
// Ratgdo reserved names.
|
|
6
|
+
export var RatgdoReservedNames;
|
|
7
|
+
(function (RatgdoReservedNames) {
|
|
8
|
+
// Manage our occupancy sensor types.
|
|
9
|
+
RatgdoReservedNames["OCCUPANCY_SENSOR_DOOR_OPEN"] = "OccupancySensor.DoorOpen";
|
|
10
|
+
RatgdoReservedNames["OCCUPANCY_SENSOR_MOTION"] = "OccupancySensor.Motion";
|
|
11
|
+
// Manage our switch types.
|
|
12
|
+
RatgdoReservedNames["SWITCH_OPENER_AUTOMATION"] = "Switch.Opener.Automation";
|
|
13
|
+
})(RatgdoReservedNames || (RatgdoReservedNames = {}));
|
|
14
|
+
//# sourceMappingURL=ratgdo-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ratgdo-types.js","sourceRoot":"","sources":["../src/ratgdo-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoBH,yBAAyB;AACzB,MAAM,CAAN,IAAY,mBAQX;AARD,WAAY,mBAAmB;IAE7B,qCAAqC;IACrC,8EAAuD,CAAA;IACvD,yEAAkD,CAAA;IAElD,2BAA2B;IAC3B,4EAAqD,CAAA;AACvD,CAAC,EARW,mBAAmB,KAAnB,mBAAmB,QAQ9B"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const PLATFORM_NAME = "Ratgdo";
|
|
2
|
+
export declare const PLUGIN_NAME = "homebridge-ratgdo";
|
|
3
|
+
export declare const RATGDO_API_PORT = 18830;
|
|
4
|
+
export declare const RATGDO_MOTION_DURATION = 5;
|
|
5
|
+
export declare const RATGDO_MQTT_RECONNECT_INTERVAL = 60;
|
|
6
|
+
export declare const RATGDO_MQTT_TOPIC = "ratgdo";
|
|
7
|
+
export declare const RATGDO_OCCUPANCY_DURATION = 300;
|
|
8
|
+
export declare const RATGDO_TRANSITION_DURATION = 25;
|
package/dist/settings.js
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
/* Copyright(C) 2017-2023, HJD (https://github.com/hjdhjd). All rights reserved.
|
|
1
|
+
/* Copyright(C) 2017-2024, HJD (https://github.com/hjdhjd). All rights reserved.
|
|
3
2
|
*
|
|
4
3
|
* settings.ts: Settings and constants for homebridge-ratgdo.
|
|
5
4
|
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.RATGDO_API_PORT = exports.RATGDO_OCCUPANCY_DURATION = exports.RATGDO_MOTION_DURATION = exports.PLUGIN_NAME = exports.PLATFORM_NAME = void 0;
|
|
8
5
|
// The platform the plugin creates.
|
|
9
|
-
|
|
6
|
+
export const PLATFORM_NAME = "Ratgdo";
|
|
10
7
|
// The name of our plugin.
|
|
11
|
-
|
|
8
|
+
export const PLUGIN_NAME = "homebridge-ratgdo";
|
|
9
|
+
// The default port to use for our builtin MQTT broker. This is intentionally not the default MQTT port number (1883) in case a user is already running a local broker.
|
|
10
|
+
export const RATGDO_API_PORT = 18830;
|
|
12
11
|
// Duration, in seconds, of a motion sensor event.
|
|
13
|
-
|
|
12
|
+
export const RATGDO_MOTION_DURATION = 5;
|
|
13
|
+
// How often, in seconds, should we try to reconnect with an MQTT broker, if we have one configured.
|
|
14
|
+
export const RATGDO_MQTT_RECONNECT_INTERVAL = 60;
|
|
15
|
+
// Default MQTT topic to use when publishing events. This is in the form of: ratgdo/device/event
|
|
16
|
+
export const RATGDO_MQTT_TOPIC = "ratgdo";
|
|
14
17
|
// Default duration, in seconds, before triggering occupancy on an opener in the open state.
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
export const RATGDO_OCCUPANCY_DURATION = 300;
|
|
19
|
+
// Duration, in seconds, of our door state transition safety timer. This should be long enough that any reasonable state change message from Ratgdo would have had ample
|
|
20
|
+
// time to be delivered, but short enough to provide that responsive feeling to an end user.
|
|
21
|
+
export const RATGDO_TRANSITION_DURATION = 25;
|
|
17
22
|
//# sourceMappingURL=settings.js.map
|
package/dist/settings.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mCAAmC;AACnC,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC;AAEtC,0BAA0B;AAC1B,MAAM,CAAC,MAAM,WAAW,GAAG,mBAAmB,CAAC;AAE/C,uKAAuK;AACvK,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AAErC,kDAAkD;AAClD,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAExC,oGAAoG;AACpG,MAAM,CAAC,MAAM,8BAA8B,GAAG,EAAE,CAAC;AAEjD,gGAAgG;AAChG,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC;AAE1C,4FAA4F;AAC5F,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAE7C,wKAAwK;AACxK,4FAA4F;AAC5F,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
<p class="text-center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/hjdhjd/homebridge-ratgdo/main/images/homebridge-ratgdo.svg" alt="homebridge-ratgdo logo" class="w-50" />
|
|
3
|
+
</p>
|
|
4
|
+
<div id="pageFirstRun" style="display: none;">
|
|
5
|
+
<div class="text-left">
|
|
6
|
+
<p>Welcome to <strong>homebridge-ratgdo</strong>. To get started:
|
|
7
|
+
<ol>
|
|
8
|
+
<li>Ensure you're running the latest <a href="https://paulwieland.github.io/ratgdo/flash.html">Ratgdo MQTT firmware</a>.</li>
|
|
9
|
+
<li>Edit the MQTT server and port configuration using the webUI on your Ratgdo devices to the IP address of this Homebridge server and port <code id="serverPortInfo" class="font-weight-bold"></code>.</li>
|
|
10
|
+
</ol>
|
|
11
|
+
</p>
|
|
12
|
+
</div>
|
|
13
|
+
<div class="text-center">
|
|
14
|
+
<br>
|
|
15
|
+
<button type="button" class="btn btn-primary" id="firstRun">Configure homebridge-ratgdo →</button>
|
|
16
|
+
<br>
|
|
17
|
+
To optimize performance and responsiveness, please make this plugin a <a target="_blank" href="https://github.com/homebridge/homebridge/wiki/Child-Bridges">child bridge</a> once you've completed configuration.
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
<div id="menuWrapper" class="btn-group w-100 mb-0" role="group" aria-label="UI Menu" style="display: none;">
|
|
21
|
+
<button type="button" class="btn btn-primary" id="menuSettings">Settings</button>
|
|
22
|
+
<button type="button" class="btn btn-primary" id="menuFeatureOptions">Feature Options</button>
|
|
23
|
+
<button type="button" class="btn btn-primary mr-0" id="menuHome">Support</button>
|
|
24
|
+
</div>
|
|
25
|
+
<div id="pageFeatureOptions" class="mt-4" style="display: none;">
|
|
26
|
+
<div id="deviceInfo">
|
|
27
|
+
<table class="table table-sm table-borderless">
|
|
28
|
+
<tr class="align-center">
|
|
29
|
+
<td id="headerInfo" colspan="2" class="m-0 p-2 text-center font-weight-bold"></td>
|
|
30
|
+
</tr>
|
|
31
|
+
<tr class="align-top">
|
|
32
|
+
<td rowspan="3" class="w-25">
|
|
33
|
+
<table id="sidebar" class="table table-sm table-bordered m-0 p-0">
|
|
34
|
+
<tr>
|
|
35
|
+
<td>
|
|
36
|
+
<table class="table table-sm table-borderless m-0 p-0" id="controllersTable"></table>
|
|
37
|
+
</td>
|
|
38
|
+
</tr>
|
|
39
|
+
<tr>
|
|
40
|
+
<td>
|
|
41
|
+
<table class="table table-sm table-borderless m-0 p-0" id="devicesTable"></table>
|
|
42
|
+
</td>
|
|
43
|
+
</tr>
|
|
44
|
+
</table>
|
|
45
|
+
</td>
|
|
46
|
+
<td id="deviceStatsTable">
|
|
47
|
+
<table class="table table-sm table-borderless border-bottom m-0 p-0">
|
|
48
|
+
<tr id="deviceStatsHeader">
|
|
49
|
+
<th class="m-0 p-0 w-25"><B>Serial</B></th>
|
|
50
|
+
<th class="m-0 p-0 w-25"><B>Firmware<B></th>
|
|
51
|
+
</tr>
|
|
52
|
+
<tr>
|
|
53
|
+
<td id="device_serial" class="m-0 p-0"></td>
|
|
54
|
+
<td id="device_firmware" class="m-0 p-0"></td>
|
|
55
|
+
</tr>
|
|
56
|
+
</table>
|
|
57
|
+
</td>
|
|
58
|
+
</tr>
|
|
59
|
+
<tr>
|
|
60
|
+
<td id="configTable" class="w-100"></td>
|
|
61
|
+
</tr>
|
|
62
|
+
</table>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
<div id="pageSupport" class="mt-4" style="display: none;">
|
|
66
|
+
<h5>Introduction</h5>
|
|
67
|
+
<p class="px-4">I hope you enjoy <a target="_blank" href="https://github.com/hjdhjd/homebridge-ratgdo">homebridge-ratgdo</a> as much as I enjoy developing it. All my projects are labors of love. If you'd like to show your appreciation - <a target="_blank" href="https://github.com/hjdhjd/homebridge-ratgdo">star this project on Github</A> and do some good in your community, either financially or with your time: a food bank, an animal shelter (two of my passions), or whatever resonates with you that can give something back to the world around you.</p>
|
|
68
|
+
|
|
69
|
+
<div class="px-4">
|
|
70
|
+
Other plugins by <a target="_blank" href="https://github.com/hjdhjd">HJD</a>:
|
|
71
|
+
|
|
72
|
+
<ul dir="auto">
|
|
73
|
+
<li><a target="_blank" href="https://github.com/hjdhjd/homebridge-unifi-protect">homebridge-unifi-protect: Complete HomeKit integration for the entire UniFi Protect ecosystem</a></li>
|
|
74
|
+
</ul>
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<h5>Getting Started</h5>
|
|
78
|
+
<ul dir="auto">
|
|
79
|
+
<li>
|
|
80
|
+
<a target="_blank" href="https://github.com/hjdhjd/homebridge-ratgdo#installation">Installation</a>: installing this plugin, including system requirements.
|
|
81
|
+
</li>
|
|
82
|
+
<li>
|
|
83
|
+
<a target="_blank" href="https://github.com/hjdhjd/homebridge-ratgdo#plugin-configuration">Plugin Configuration</a>: how to quickly get up and running.
|
|
84
|
+
</li>
|
|
85
|
+
<li>
|
|
86
|
+
<a target="_blank" href="https://github.com/hjdhjd/homebridge-ratgdo#notes">Additional Notes</a>: some things you should be aware of, including Ratgdo-specific quirks.
|
|
87
|
+
</li>
|
|
88
|
+
</ul>
|
|
89
|
+
|
|
90
|
+
<h5>Advanced Topics</h5>
|
|
91
|
+
<ul dir="auto">
|
|
92
|
+
<li>
|
|
93
|
+
<a target="_blank" href="https://github.com/hjdhjd/homebridge-ratgdo/blob/main/docs/FeatureOptions.md">Feature Options</a>: granular options to allow you to show or hide specific garage door and gate openers, and more.
|
|
94
|
+
</li>
|
|
95
|
+
<li>
|
|
96
|
+
<a target="_blank" href="https://github.com/hjdhjd/homebridge-ratgdo/blob/main/docs/MQTT.md">MQTT</a>: how to configure MQTT support.
|
|
97
|
+
</li>
|
|
98
|
+
<li>
|
|
99
|
+
<a target="_blank" href="https://github.com/hjdhjd/homebridge-ratgdo/blob/main/docs/AdvancedOptions.md">Advanced Configuration</a>: complete list of configuration options available in this plugin.
|
|
100
|
+
</li>
|
|
101
|
+
</ul>
|
|
102
|
+
|
|
103
|
+
<h5>Support</h5>
|
|
104
|
+
<ul>
|
|
105
|
+
<li>
|
|
106
|
+
<a target="_blank" href="https://discord.gg/QXqfHEW">Discord Support Channel</a>
|
|
107
|
+
</li>
|
|
108
|
+
<li>
|
|
109
|
+
<a target="_blank" href="https://github.com/hjdhjd/homebridge-ratgdo/issues/new/choose">Create a Developer Support Request</a>
|
|
110
|
+
</li>
|
|
111
|
+
<li>
|
|
112
|
+
<a target="_blank" href="https://github.com/hjdhjd/homebridge-ratgdo/blob/main/docs/Changelog.md">Changelog and Release Notes</a>
|
|
113
|
+
</li>
|
|
114
|
+
</ul>
|
|
115
|
+
</div>
|
|
116
|
+
<script src="./ui.mjs" type="module"></script>
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/* Copyright(C) 2017-2024, HJD (https://github.com/hjdhjd). All rights reserved.
|
|
2
|
+
*
|
|
3
|
+
* featureoptions.mjs: Feature option webUI base class.
|
|
4
|
+
*/
|
|
5
|
+
"use strict";
|
|
6
|
+
|
|
7
|
+
export class FeatureOptions {
|
|
8
|
+
|
|
9
|
+
controller;
|
|
10
|
+
|
|
11
|
+
featureOptionGroups;
|
|
12
|
+
featureOptionList;
|
|
13
|
+
optionsList;
|
|
14
|
+
|
|
15
|
+
constructor() {
|
|
16
|
+
|
|
17
|
+
this.featureOptionGroups = {};
|
|
18
|
+
this.featureOptionList = {};
|
|
19
|
+
this.controller = null;
|
|
20
|
+
this.optionsList = [];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Abstract method to be implemented by subclasses to render the feature option webUI.
|
|
24
|
+
async showUI() {
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Is this feature option set explicitly?
|
|
28
|
+
isOptionSet(featureOption, deviceMac) {
|
|
29
|
+
|
|
30
|
+
const optionRegex = new RegExp("^(?:Enable|Disable)\\." + featureOption + (!deviceMac ? "" : "\\." + deviceMac) + "$", "gi");
|
|
31
|
+
return this.optionsList.filter(x => optionRegex.test(x)).length ? true : false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Is a feature option globally enabled?
|
|
35
|
+
isGlobalOptionEnabled(featureOption, defaultState) {
|
|
36
|
+
|
|
37
|
+
featureOption = featureOption.toUpperCase();
|
|
38
|
+
|
|
39
|
+
// Test device-specific options.
|
|
40
|
+
return this.optionsList.some(x => x === ("ENABLE." + featureOption)) ? true :
|
|
41
|
+
(this.optionsList.some(x => x === ("DISABLE." + featureOption)) ? false : defaultState
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Is a feature option enabled at the device or global level. This function does not traverse the scoping hierarchy.
|
|
46
|
+
isDeviceOptionEnabled(featureOption, mac, defaultState) {
|
|
47
|
+
|
|
48
|
+
if(!mac) {
|
|
49
|
+
|
|
50
|
+
return this.isGlobalOptionEnabled(featureOption, defaultState);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
featureOption = featureOption.toUpperCase();
|
|
54
|
+
mac = mac.toUpperCase();
|
|
55
|
+
|
|
56
|
+
// Test device-specific options.
|
|
57
|
+
return this.optionsList.some(x => x === ("ENABLE." + featureOption + "." + mac)) ? true :
|
|
58
|
+
(this.optionsList.some(x => x === ("DISABLE." + featureOption + "." + mac)) ? false : defaultState
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Is a value-centric feature option enabled at the device or global level. This function does not traverse the scoping hierarchy.
|
|
63
|
+
isOptionValueSet(featureOption, deviceMac) {
|
|
64
|
+
|
|
65
|
+
const optionRegex = new RegExp("^Enable\\." + featureOption + (!deviceMac ? "" : "\\." + deviceMac) + "\\.([^\\.]+)$", "gi");
|
|
66
|
+
|
|
67
|
+
return this.optionsList.filter(x => optionRegex.test(x)).length ? true : false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Get the value of a value-centric feature option.
|
|
71
|
+
getOptionValue(featureOption, deviceMac) {
|
|
72
|
+
|
|
73
|
+
const optionRegex = new RegExp("^Enable\\." + featureOption + (!deviceMac ? "" : "\\." + deviceMac) + "\\.([^\\.]+)$", "gi");
|
|
74
|
+
|
|
75
|
+
// Get the option value, if we have one.
|
|
76
|
+
for(const option of this.optionsList) {
|
|
77
|
+
|
|
78
|
+
const regexMatch = optionRegex.exec(option);
|
|
79
|
+
|
|
80
|
+
if(regexMatch) {
|
|
81
|
+
|
|
82
|
+
return regexMatch[1];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Is a feature option enabled at the device or global level. It does traverse the scoping hierarchy.
|
|
90
|
+
isOptionEnabled(featureOption, deviceMac) {
|
|
91
|
+
|
|
92
|
+
const defaultState = this.featureOptionList[featureOption]?.default ?? true;
|
|
93
|
+
|
|
94
|
+
if(deviceMac) {
|
|
95
|
+
|
|
96
|
+
// Device level check.
|
|
97
|
+
if(this.isDeviceOptionEnabled(featureOption, deviceMac, defaultState) !== defaultState) {
|
|
98
|
+
|
|
99
|
+
return !defaultState;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Controller level check.
|
|
103
|
+
if(this.isDeviceOptionEnabled(featureOption, this.controller, defaultState) !== defaultState) {
|
|
104
|
+
|
|
105
|
+
return !defaultState;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Global check.
|
|
110
|
+
if(this.isGlobalOptionEnabled(featureOption, defaultState) !== defaultState) {
|
|
111
|
+
|
|
112
|
+
return !defaultState;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Return the default.
|
|
116
|
+
return defaultState;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Return the scope level of a feature option.
|
|
120
|
+
optionScope(featureOption, deviceMac, defaultState, isOptionValue = false) {
|
|
121
|
+
|
|
122
|
+
// Scope priority is always: device, controller, global.
|
|
123
|
+
|
|
124
|
+
// If we have a value-centric feature option, our lookups are a bit different.
|
|
125
|
+
if(isOptionValue) {
|
|
126
|
+
|
|
127
|
+
if(deviceMac) {
|
|
128
|
+
|
|
129
|
+
if(this.isOptionValueSet(featureOption, deviceMac)) {
|
|
130
|
+
|
|
131
|
+
return "device";
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if(this.isOptionValueSet(featureOption, this.controller)) {
|
|
135
|
+
|
|
136
|
+
return "controller";
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if(this.isOptionValueSet(featureOption)) {
|
|
141
|
+
|
|
142
|
+
return "global";
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return "none";
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if(deviceMac) {
|
|
149
|
+
|
|
150
|
+
// Let's see if we've set it at the device-level.
|
|
151
|
+
if((this.isDeviceOptionEnabled(featureOption, deviceMac, defaultState) !== defaultState) || this.isOptionSet(featureOption, deviceMac)) {
|
|
152
|
+
|
|
153
|
+
return "device";
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Now let's test the controller level.
|
|
157
|
+
if((this.isDeviceOptionEnabled(featureOption, this.controller, defaultState) !== defaultState) || this.isOptionSet(featureOption, this.controller)) {
|
|
158
|
+
|
|
159
|
+
return "controller";
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Finally, let's test the global level.
|
|
164
|
+
if((this.isGlobalOptionEnabled(featureOption, defaultState) !== defaultState) || this.isOptionSet(featureOption)) {
|
|
165
|
+
|
|
166
|
+
return "global";
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Option isn't set to a non-default value.
|
|
170
|
+
return "none";
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// Return the color hinting for a given option's scope.
|
|
174
|
+
optionScopeColor(featureOption, deviceMac, defaultState, isOptionValue) {
|
|
175
|
+
|
|
176
|
+
switch(this.optionScope(featureOption, deviceMac, defaultState, isOptionValue)) {
|
|
177
|
+
|
|
178
|
+
case "device":
|
|
179
|
+
|
|
180
|
+
return "text-info";
|
|
181
|
+
break;
|
|
182
|
+
|
|
183
|
+
case "controller":
|
|
184
|
+
|
|
185
|
+
return "text-success";
|
|
186
|
+
break;
|
|
187
|
+
|
|
188
|
+
case "global":
|
|
189
|
+
|
|
190
|
+
return deviceMac ? "text-warning" : "text-info";
|
|
191
|
+
break;
|
|
192
|
+
|
|
193
|
+
default:
|
|
194
|
+
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return null;
|
|
199
|
+
};
|
|
200
|
+
}
|