homebridge-ratgdo 0.0.1 → 0.1.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 +44 -3
- package/config.schema.json +106 -0
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/ratgdo-device.js +374 -0
- package/dist/ratgdo-device.js.map +1 -0
- package/dist/ratgdo-options.js +122 -0
- package/dist/ratgdo-options.js.map +1 -0
- package/dist/ratgdo-platform.js +181 -0
- package/dist/ratgdo-platform.js.map +1 -0
- package/dist/settings.js +14 -9
- package/dist/settings.js.map +1 -1
- package/package.json +11 -9
- package/dist/platform.js +0 -98
- package/dist/platform.js.map +0 -1
- package/dist/platformAccessory.js +0 -104
- package/dist/platformAccessory.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
<SPAN ALIGN="CENTER" STYLE="text-align:center">
|
|
2
|
+
<DIV ALIGN="CENTER" STYLE="text-align:center">
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
# Homebridge Ratgdo
|
|
5
5
|
|
|
6
|
+
[](https://www.npmjs.com/package/homebridge-ratgdo)
|
|
7
|
+
[](https://www.npmjs.com/package/homebridge-ratgdo)
|
|
8
|
+
[](https://discord.gg/QXqfHEW)
|
|
9
|
+
[](https://github.com/homebridge/homebridge/wiki/Verified-Plugins)
|
|
10
|
+
|
|
11
|
+
## Ratgdo-enabled garage door opener support for [Homebridge](https://homebridge.io).
|
|
12
|
+
</DIV>
|
|
13
|
+
</SPAN>
|
|
14
|
+
|
|
15
|
+
`homebridge-ratgdo` is a [Homebridge](https://homebridge.io) plugin that makes Chamberlain, Liftmaster, and other garage door openers that utilize the Ratgdo hardware control board available to [Apple's](https://www.apple.com) [HomeKit](https://www.apple.com/ios/home) smart home platform. You can determine if your garage door opener by checking the [Ratgdo website](https://paulwieland.github.io/ratgdo/).
|
|
16
|
+
|
|
17
|
+
## Why use this plugin for Ratgdo support in HomeKit?
|
|
18
|
+
In a nutshell, the aim of this plugin for things to *just work* with minimal required configuration by users. The goal is to provide as close to a streamlined experience as you would expect from a first-party or native HomeKit solution. For the adventurous, those additional granular options are, of course, available to support more esoteric use cases or other unique needs.
|
|
19
|
+
|
|
20
|
+
What does *just work* mean in practice? It means that this plugin will discover all your Ratgdo devices without the need for additional configuration beyond telling the Ratgdo device about `homebridge-ratgdo`.
|
|
21
|
+
|
|
22
|
+
**I rely on this plugin every day and actively maintain and support it. That said, at the moment, this plugin should be considered beta and is still evolving its core feature set. I am currently not accepting any issues or feedback through GitHub for the time being, though support on the Homebridge Discord is available on the ratgdo channel.**
|
|
23
|
+
|
|
24
|
+
In the interest of the community seeking a solution outside of myQ, I'm releasing an initial implementation that enables the following features:
|
|
25
|
+
|
|
26
|
+
* Control of the garage door opener. This includes, for those that have always wanted the feature, the ability to close the garage door without the requisite safety warning and delay that Chamberlain and Liftmaster garage door openers emit when being controlled remotely.
|
|
27
|
+
* A motion sensor when it's available.
|
|
28
|
+
* Control of the light attached to the garage door opener, when available.
|
|
29
|
+
* Obstruction detection.
|
|
30
|
+
|
|
31
|
+
## Known Caveats
|
|
32
|
+
Ratgdo is a terrific solution that solves a problem for many stranded former myQ users and others. There are some quirks and caveats to note, however. As of Ratgdo firmware v2.51:
|
|
33
|
+
|
|
34
|
+
* Misconfiguring your MQTT server IP or port number in any way **will** lock up / brick the Ratgdo. The only fix for this I've discovered is to reflash the Ratgdo and don't misconfigure it the next time around.
|
|
35
|
+
* Ratgdo currently has no useful way to query it's state over MQTT. That means that on startup, the state of the garage door opener in Homebridge / HomeKit will be unknowable. Given that challenge, `homebridge-ratgdo` will assume the garage door opener is closed on startup. Once an action is taken, the state of the garage door opener will be accurately reflected in Homebridge / HomeKit. There is technically a *query* command available through the MQTT interface to Ratgdo, but all that currently does is to set the Ratgdo state information to an unknown state, awaiting the next state update from the garage door opener, rather than actually publish the current state, which is really what we need.
|
|
36
|
+
* In some wiring configurations, Ratgdo reads information from the garage door opener either incorrectly or inconsistently. I would advise closely checking and confirming the wiring you're using to ensure it's correct and the physical wiring used is good. If it is, I'd suggest filing a support request on the [Ratgdo support page](https://github.com/PaulWieland/ratgdo/issues).
|
|
37
|
+
|
|
38
|
+
I hope these issues can be addressed in future Ratgdo releases.
|
|
39
|
+
|
|
40
|
+
## Plugin Development Dashboard
|
|
41
|
+
This is mostly of interest to the true developer nerds amongst us.
|
|
42
|
+
|
|
43
|
+
[](https://github.com/hjdhjd/homebridge-ratgdo/blob/main/LICENSE.md)
|
|
44
|
+
[](https://github.com/hjdhjd/homebridge-ratgdo/actions?query=workflow%3A%22Continuous+Integration%22)
|
|
45
|
+
[](https://libraries.io/npm/homebridge-ratgdo)
|
|
46
|
+
[](https://github.com/hjdhjd/homebridge-ratgdo/commits/main)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pluginAlias": "Ratgdo",
|
|
3
|
+
"pluginType": "platform",
|
|
4
|
+
"singular": true,
|
|
5
|
+
"customUi": false,
|
|
6
|
+
"headerDisplay": "[homebridge-ratgdo](https://github.com/hjdhjd/homebridge-ratgdo) provides HomeKit support to Chamberlain and Liftmaster garage door openers that use the Ratgdo hardware control board without using myQ. This version is a beta and should not be relied upon daily.",
|
|
7
|
+
"footerDisplay": "See the [homebridge-ratgdo developer page](https://github.com/hjdhjd/homebridge-ratgdo) for detailed documentation, including [feature options](https://github.com/hjdhjd/homebridge-ratgdo#feature-options). This version is a beta and should not be relied upon daily.",
|
|
8
|
+
"schema": {
|
|
9
|
+
"type": "object",
|
|
10
|
+
"properties": {
|
|
11
|
+
|
|
12
|
+
"port": {
|
|
13
|
+
"title": "MQTT Broker Port",
|
|
14
|
+
"type": "number",
|
|
15
|
+
"placeholder": "e.g. 18830",
|
|
16
|
+
"minimum": 1024,
|
|
17
|
+
"maximum": 65535,
|
|
18
|
+
"required": false,
|
|
19
|
+
"description": "Set the port to use for the builtin MQTT broker. Ensure you set the Ratgdo hardware control board to use the same MQTT server port."
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
"name": {
|
|
23
|
+
"title": "Plugin Name",
|
|
24
|
+
"type": "string",
|
|
25
|
+
"required": true,
|
|
26
|
+
"default": "Ratgdo",
|
|
27
|
+
"description": "Name to use for Homebridge logging purposes. Default: Ratgdo."
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
"options": {
|
|
31
|
+
"title": "Feature Options",
|
|
32
|
+
"type": "array",
|
|
33
|
+
|
|
34
|
+
"items": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"title": "Feature Option",
|
|
37
|
+
"required": false,
|
|
38
|
+
"description": "Enter only one option per entry. See the plugin documentation for the complete list of available options or use the feature options webUI tab above.",
|
|
39
|
+
"placeholder": "e.g. Disable.Device"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
"debug": {
|
|
44
|
+
"title": "Debug Logging",
|
|
45
|
+
"type": "boolean",
|
|
46
|
+
"required": false,
|
|
47
|
+
"description": "Logging verbosity for debugging. Default: false."
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
"layout": [
|
|
54
|
+
{
|
|
55
|
+
"type": "section",
|
|
56
|
+
"title": "Settings",
|
|
57
|
+
"expandable": true,
|
|
58
|
+
"expanded": false,
|
|
59
|
+
"items": [
|
|
60
|
+
{
|
|
61
|
+
"description": "Ensure your Ratgdo hardware control board is configured to use the IP address of your Homebridge server for the MQTT server IP",
|
|
62
|
+
"items": [
|
|
63
|
+
"port"
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
{
|
|
70
|
+
"type": "section",
|
|
71
|
+
"title": "Plugin Feature Options (Not Available Yet)",
|
|
72
|
+
"expandable": true,
|
|
73
|
+
"expanded": false,
|
|
74
|
+
"items": [
|
|
75
|
+
{
|
|
76
|
+
"key": "options",
|
|
77
|
+
"type": "array",
|
|
78
|
+
"orderable": true,
|
|
79
|
+
"title": " ",
|
|
80
|
+
"description": "Use the feature options webUI tab above instead of manually configuring feature options here.",
|
|
81
|
+
"buttonText": "Add Feature Option",
|
|
82
|
+
"items": [
|
|
83
|
+
"options[]"
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
{
|
|
90
|
+
"type": "section",
|
|
91
|
+
"title": "Advanced Settings (Optional)",
|
|
92
|
+
"expandable": true,
|
|
93
|
+
"expanded": false,
|
|
94
|
+
"items": [
|
|
95
|
+
{
|
|
96
|
+
"description": "These settings should be rarely used or needed by most people. Use these with caution.",
|
|
97
|
+
"items": [
|
|
98
|
+
"name",
|
|
99
|
+
"debug"
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
]
|
|
106
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/* Copyright(C) 2017-2023, HJD (https://github.com/hjdhjd). All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* index.ts: homebridge-ratgdo plugin registration.
|
|
6
|
+
*/
|
|
7
|
+
const settings_js_1 = require("./settings.js");
|
|
8
|
+
const ratgdo_platform_js_1 = require("./ratgdo-platform.js");
|
|
9
|
+
// Register our platform with homebridge.
|
|
10
|
+
exports.default = (api) => {
|
|
11
|
+
api.registerPlatform(settings_js_1.PLUGIN_NAME, settings_js_1.PLATFORM_NAME, ratgdo_platform_js_1.ratgdoPlatform);
|
|
6
12
|
};
|
|
7
13
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA;;;GAGG;AACH,+CAA2D;AAE3D,6DAAsD;AAEtD,yCAAyC;AACzC,kBAAe,CAAC,GAAQ,EAAQ,EAAE;IAEhC,GAAG,CAAC,gBAAgB,CAAC,yBAAW,EAAE,2BAAa,EAAE,mCAAc,CAAC,CAAC;AACnE,CAAC,CAAC"}
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ratgdoAccessory = void 0;
|
|
7
|
+
const ratgdo_options_js_1 = require("./ratgdo-options.js");
|
|
8
|
+
const settings_js_1 = require("./settings.js");
|
|
9
|
+
const node_util_1 = __importDefault(require("node:util"));
|
|
10
|
+
class ratgdoAccessory {
|
|
11
|
+
// The constructor initializes key variables and calls configureDevice().
|
|
12
|
+
constructor(platform, accessory, device) {
|
|
13
|
+
this.accessory = accessory;
|
|
14
|
+
this.api = platform.api;
|
|
15
|
+
this.status = {};
|
|
16
|
+
this.config = platform.config;
|
|
17
|
+
this.hap = this.api.hap;
|
|
18
|
+
this.hints = {};
|
|
19
|
+
this.device = device;
|
|
20
|
+
this.platform = platform;
|
|
21
|
+
this.log = {
|
|
22
|
+
debug: (message, ...parameters) => platform.debug(node_util_1.default.format(this.name + ": " + message, ...parameters)),
|
|
23
|
+
error: (message, ...parameters) => platform.log.error(node_util_1.default.format(this.name + ": " + message, ...parameters)),
|
|
24
|
+
info: (message, ...parameters) => platform.log.info(node_util_1.default.format(this.name + ": " + message, ...parameters)),
|
|
25
|
+
warn: (message, ...parameters) => platform.log.warn(node_util_1.default.format(this.name + ": " + message, ...parameters))
|
|
26
|
+
};
|
|
27
|
+
// Initialize our internal state.
|
|
28
|
+
this.status.availability = false;
|
|
29
|
+
this.status.door = this.hap.Characteristic.CurrentDoorState.CLOSED;
|
|
30
|
+
this.status.light = false;
|
|
31
|
+
this.status.lock = this.hap.Characteristic.LockCurrentState.UNSECURED;
|
|
32
|
+
this.status.motion = false;
|
|
33
|
+
this.status.obstruction = false;
|
|
34
|
+
this.motionTimer = null;
|
|
35
|
+
this.obstructionTimer = null;
|
|
36
|
+
this.occupancyTimer = null;
|
|
37
|
+
this.configureDevice();
|
|
38
|
+
}
|
|
39
|
+
// Configure a garage door accessory for HomeKit.
|
|
40
|
+
configureDevice() {
|
|
41
|
+
// Clean out the context object.
|
|
42
|
+
this.accessory.context = {};
|
|
43
|
+
// Configure ourselves.
|
|
44
|
+
this.configureHints();
|
|
45
|
+
this.configureInfo();
|
|
46
|
+
this.configureGarageDoor();
|
|
47
|
+
this.configureLight();
|
|
48
|
+
this.configureMotionSensor();
|
|
49
|
+
// this.configureSwitch();
|
|
50
|
+
// this.configureOccupancySensor();
|
|
51
|
+
}
|
|
52
|
+
// Configure device-specific settings.
|
|
53
|
+
configureHints() {
|
|
54
|
+
this.hints.automationSwitch = this.hasFeature("Opener.Switch");
|
|
55
|
+
this.hints.occupancySensor = this.hasFeature("Opener.OccupancySensor");
|
|
56
|
+
// this.hints.occupancyDuration = this.getFeatureNumber("Opener.OccupancySensor.Duration") ?? RATGDO_OCCUPANCY_DURATION;
|
|
57
|
+
this.hints.readOnly = this.hasFeature("Opener.ReadOnly");
|
|
58
|
+
this.hints.syncNames = this.hasFeature("Device.SyncNames");
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
// Configure the device information for HomeKit.
|
|
62
|
+
configureInfo() {
|
|
63
|
+
var _a, _b, _c, _d;
|
|
64
|
+
// Update the manufacturer information for this device.
|
|
65
|
+
(_a = this.accessory.getService(this.hap.Service.AccessoryInformation)) === null || _a === void 0 ? void 0 : _a.updateCharacteristic(this.hap.Characteristic.Manufacturer, "Liftmaster");
|
|
66
|
+
// Update the model information for this device.
|
|
67
|
+
(_b = this.accessory.getService(this.hap.Service.AccessoryInformation)) === null || _b === void 0 ? void 0 : _b.updateCharacteristic(this.hap.Characteristic.Model, "Ratgdo");
|
|
68
|
+
// Update the serial number for this device.
|
|
69
|
+
(_c = this.accessory.getService(this.hap.Service.AccessoryInformation)) === null || _c === void 0 ? void 0 : _c.updateCharacteristic(this.hap.Characteristic.SerialNumber, this.device.mac);
|
|
70
|
+
// Update the firmware information for this device.
|
|
71
|
+
(_d = this.accessory.getService(this.hap.Service.AccessoryInformation)) === null || _d === void 0 ? void 0 : _d.updateCharacteristic(this.hap.Characteristic.FirmwareRevision, this.device.firmwareVersion);
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
// Configure the garage door service for HomeKit.
|
|
75
|
+
configureGarageDoor() {
|
|
76
|
+
var _a;
|
|
77
|
+
let garageDoorService = this.accessory.getService(this.hap.Service.GarageDoorOpener);
|
|
78
|
+
// Add the garage door opener service to the accessory, if needed.
|
|
79
|
+
if (!garageDoorService) {
|
|
80
|
+
garageDoorService = new this.hap.Service.GarageDoorOpener(this.name);
|
|
81
|
+
this.accessory.addService(garageDoorService);
|
|
82
|
+
}
|
|
83
|
+
// Set the initial current and target door states to closed since ratgdo doesn't tell us initial state over MQTT on startup.
|
|
84
|
+
garageDoorService.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, this.status.door);
|
|
85
|
+
garageDoorService.updateCharacteristic(this.hap.Characteristic.TargetDoorState, this.doorTargetStateBias(this.status.door));
|
|
86
|
+
// Handle HomeKit open and close events.
|
|
87
|
+
garageDoorService.getCharacteristic(this.hap.Characteristic.TargetDoorState).onSet((value) => {
|
|
88
|
+
this.setDoorState(value);
|
|
89
|
+
});
|
|
90
|
+
// Inform HomeKit of our current state.
|
|
91
|
+
garageDoorService.getCharacteristic(this.hap.Characteristic.CurrentDoorState).onGet(() => this.status.door);
|
|
92
|
+
// Inform HomeKit of any obstructions.
|
|
93
|
+
garageDoorService.getCharacteristic(this.hap.Characteristic.ObstructionDetected).onGet(() => this.status.obstruction === true);
|
|
94
|
+
// Add the lock garage door lock current and target state characteristics.
|
|
95
|
+
garageDoorService.addOptionalCharacteristic(this.hap.Characteristic.LockCurrentState);
|
|
96
|
+
garageDoorService.addOptionalCharacteristic(this.hap.Characteristic.LockTargetState);
|
|
97
|
+
garageDoorService.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.status.lock);
|
|
98
|
+
garageDoorService.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.lockTargetStateBias(this.status.lock));
|
|
99
|
+
// Add the configured name for this device.
|
|
100
|
+
garageDoorService.addOptionalCharacteristic(this.hap.Characteristic.ConfiguredName);
|
|
101
|
+
// switchService.updateCharacteristic(this.hap.Characteristic.ConfiguredName, switchName);
|
|
102
|
+
// Update our configured name, if requested.
|
|
103
|
+
if (this.hints.syncNames) {
|
|
104
|
+
garageDoorService.updateCharacteristic(this.hap.Characteristic.ConfiguredName, this.device.name);
|
|
105
|
+
if (this.hints.occupancySensor) {
|
|
106
|
+
(_a = this.accessory.getService(this.hap.Service.OccupancySensor)) === null || _a === void 0 ? void 0 : _a.updateCharacteristic(this.hap.Characteristic.ConfiguredName, this.device.name + " Open");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Add our status active characteristic.
|
|
110
|
+
garageDoorService.addOptionalCharacteristic(this.hap.Characteristic.StatusActive);
|
|
111
|
+
garageDoorService.getCharacteristic(this.hap.Characteristic.StatusActive).onGet(() => this.status.availability);
|
|
112
|
+
garageDoorService.updateCharacteristic(this.hap.Characteristic.StatusActive, this.status.availability);
|
|
113
|
+
// Let HomeKit know that this is the primary service on this accessory.
|
|
114
|
+
garageDoorService.setPrimaryService(true);
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
// Configure the light for HomeKit.
|
|
118
|
+
configureLight() {
|
|
119
|
+
var _a, _b;
|
|
120
|
+
// Find the service, if it exists.
|
|
121
|
+
let lightService = this.accessory.getService(this.hap.Service.Lightbulb);
|
|
122
|
+
// Add the service to the accessory, if needed.
|
|
123
|
+
if (!lightService) {
|
|
124
|
+
lightService = new this.hap.Service.Lightbulb(this.name);
|
|
125
|
+
if (!lightService) {
|
|
126
|
+
this.log.error("Unable to add the light.");
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
this.accessory.addService(lightService);
|
|
130
|
+
this.log.info("Enabling light.");
|
|
131
|
+
}
|
|
132
|
+
// Turn the light on or off.
|
|
133
|
+
(_a = lightService.getCharacteristic(this.hap.Characteristic.On)) === null || _a === void 0 ? void 0 : _a.onGet(() => this.status.light);
|
|
134
|
+
(_b = lightService.getCharacteristic(this.hap.Characteristic.On)) === null || _b === void 0 ? void 0 : _b.onSet((value) => {
|
|
135
|
+
this.platform.broker.publish({ cmd: "publish", dup: false, payload: value === true ? "on" : "off", qos: 0, retain: false, topic: this.device.name + "/command/light" }, () => { });
|
|
136
|
+
});
|
|
137
|
+
// Initialize the light.
|
|
138
|
+
lightService.displayName = this.name;
|
|
139
|
+
lightService.updateCharacteristic(this.hap.Characteristic.Name, this.name);
|
|
140
|
+
lightService.updateCharacteristic(this.hap.Characteristic.On, this.status.light);
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
// Configure the motion sensor for HomeKit.
|
|
144
|
+
configureMotionSensor() {
|
|
145
|
+
// Find the motion sensor service, if it exists.
|
|
146
|
+
let motionService = this.accessory.getService(this.hap.Service.MotionSensor);
|
|
147
|
+
// We don't have a motion sensor, let's add it to the device.
|
|
148
|
+
if (!motionService) {
|
|
149
|
+
// We don't have it, add the motion sensor to the device.
|
|
150
|
+
motionService = new this.hap.Service.MotionSensor(this.name);
|
|
151
|
+
if (!motionService) {
|
|
152
|
+
this.log.error("Unable to add the motion sensor.");
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
this.accessory.addService(motionService);
|
|
156
|
+
this.log.info("Enabling motion sensor.");
|
|
157
|
+
}
|
|
158
|
+
// Initialize the state of the motion sensor.
|
|
159
|
+
motionService.displayName = this.name;
|
|
160
|
+
motionService.updateCharacteristic(this.hap.Characteristic.Name, this.name);
|
|
161
|
+
motionService.updateCharacteristic(this.hap.Characteristic.MotionDetected, false);
|
|
162
|
+
motionService.updateCharacteristic(this.hap.Characteristic.StatusActive, this.status.availability);
|
|
163
|
+
motionService.getCharacteristic(this.hap.Characteristic.StatusActive).onGet(() => this.status.availability);
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
// Open or close the garage door.
|
|
167
|
+
setDoorState(value) {
|
|
168
|
+
const actionExisting = this.status.door === this.hap.Characteristic.CurrentDoorState.OPENING ? "opening" : "closing";
|
|
169
|
+
const actionAttempt = value === this.hap.Characteristic.TargetDoorState.CLOSED ? "close" : "open";
|
|
170
|
+
// If this garage door is read-only, we won't process any requests to set state.
|
|
171
|
+
if (this.hints.readOnly) {
|
|
172
|
+
this.log.info("Unable to %s door. The door has been configured to be read only.", actionAttempt);
|
|
173
|
+
// Tell HomeKit that we haven't in fact changed our state so we don't end up in an inadvertent opening or closing state.
|
|
174
|
+
setImmediate(() => {
|
|
175
|
+
var _a;
|
|
176
|
+
(_a = this.accessory.getService(this.hap.Service.GarageDoorOpener)) === null || _a === void 0 ? void 0 : _a.updateCharacteristic(this.hap.Characteristic.TargetDoorState, value === this.hap.Characteristic.TargetDoorState.CLOSED ? this.hap.Characteristic.TargetDoorState.OPEN : this.hap.Characteristic.TargetDoorState.CLOSED);
|
|
177
|
+
});
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
// If we are already opening or closing the garage door, we error out. ratgdo doesn't appear to allow interruptions to an open or close command that is currently executing - it
|
|
181
|
+
// must be allowed to complete its action before accepting a new one.
|
|
182
|
+
if ((this.status.door === this.hap.Characteristic.CurrentDoorState.OPENING) || (this.status.door === this.hap.Characteristic.CurrentDoorState.CLOSING)) {
|
|
183
|
+
this.log.error("Unable to %s door while currently attempting to complete %s. Ratgdo must complete it's existing action before attempting a new one.", actionAttempt, actionExisting);
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
// Close the garage door.
|
|
187
|
+
if (value === this.hap.Characteristic.TargetDoorState.CLOSED) {
|
|
188
|
+
// HomeKit is asking us to close the garage door, but let's make sure it's not already closed first.
|
|
189
|
+
if (this.status.door !== this.hap.Characteristic.CurrentDoorState.CLOSED) {
|
|
190
|
+
// Execute the command.
|
|
191
|
+
this.platform.broker.publish({ cmd: "publish", dup: false, payload: "close", qos: 0, retain: false, topic: this.device.name + "/command/door" }, () => { });
|
|
192
|
+
}
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
// Open the garage door.
|
|
196
|
+
if (value === this.hap.Characteristic.TargetDoorState.OPEN) {
|
|
197
|
+
// HomeKit is informing us to open the door, but we don't want to act if it's already open.
|
|
198
|
+
if (this.status.door !== this.hap.Characteristic.CurrentDoorState.OPEN) {
|
|
199
|
+
// Execute the command.
|
|
200
|
+
this.platform.broker.publish({ cmd: "publish", dup: false, payload: "open", qos: 0, retain: false, topic: this.device.name + "/command/door" }, () => { });
|
|
201
|
+
}
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
// HomeKit has told us something that we don't know how to handle.
|
|
205
|
+
this.log.error("Unknown HomeKit set event received: %s.", value);
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
// Update the state of the accessory.
|
|
209
|
+
updateState(event, payload) {
|
|
210
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
211
|
+
let currentState, targetState;
|
|
212
|
+
const camelCase = (text) => text.charAt(0).toUpperCase() + text.slice(1);
|
|
213
|
+
switch (event) {
|
|
214
|
+
case "availability":
|
|
215
|
+
this.status.availability = payload === "online";
|
|
216
|
+
// Update our availability.
|
|
217
|
+
(_a = this.accessory.getService(this.hap.Service.GarageDoorOpener)) === null || _a === void 0 ? void 0 : _a.updateCharacteristic(this.hap.Characteristic.StatusActive, this.status.availability);
|
|
218
|
+
(_b = this.accessory.getService(this.hap.Service.MotionSensor)) === null || _b === void 0 ? void 0 : _b.updateCharacteristic(this.hap.Characteristic.StatusActive, this.status.availability);
|
|
219
|
+
// Inform the user:
|
|
220
|
+
this.log.info("Device %s.", this.status.availability ? "connected" : "disconnected");
|
|
221
|
+
break;
|
|
222
|
+
case "door":
|
|
223
|
+
switch (payload) {
|
|
224
|
+
case "closed":
|
|
225
|
+
currentState = this.hap.Characteristic.CurrentDoorState.CLOSED;
|
|
226
|
+
break;
|
|
227
|
+
case "closing":
|
|
228
|
+
currentState = this.hap.Characteristic.CurrentDoorState.CLOSING;
|
|
229
|
+
break;
|
|
230
|
+
case "open":
|
|
231
|
+
currentState = this.hap.Characteristic.CurrentDoorState.OPEN;
|
|
232
|
+
break;
|
|
233
|
+
case "opening":
|
|
234
|
+
currentState = this.hap.Characteristic.CurrentDoorState.OPENING;
|
|
235
|
+
break;
|
|
236
|
+
case "stopped":
|
|
237
|
+
currentState = this.hap.Characteristic.CurrentDoorState.STOPPED;
|
|
238
|
+
break;
|
|
239
|
+
default:
|
|
240
|
+
currentState = this.hap.Characteristic.CurrentDoorState.CLOSED;
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
// We are only going to update the target state if our current state is NOT stopped. If we are stopped, we are at the target state by definition. We also want to
|
|
244
|
+
// ensure we update TargetDoorState before updating CurrentDoorState in order to work around some notification quirks HomeKit occasionally has.
|
|
245
|
+
if (currentState !== this.hap.Characteristic.CurrentDoorState.STOPPED) {
|
|
246
|
+
(_c = this.accessory.getService(this.hap.Service.GarageDoorOpener)) === null || _c === void 0 ? void 0 : _c.updateCharacteristic(this.hap.Characteristic.TargetDoorState, this.doorTargetStateBias(currentState));
|
|
247
|
+
}
|
|
248
|
+
(_d = this.accessory.getService(this.hap.Service.GarageDoorOpener)) === null || _d === void 0 ? void 0 : _d.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, currentState);
|
|
249
|
+
// Inform the user:
|
|
250
|
+
this.log.info("%s.", camelCase(payload));
|
|
251
|
+
break;
|
|
252
|
+
case "light":
|
|
253
|
+
this.status.light = payload === "on";
|
|
254
|
+
(_e = this.accessory.getService(this.hap.Service.Lightbulb)) === null || _e === void 0 ? void 0 : _e.updateCharacteristic(this.hap.Characteristic.On, this.status.light);
|
|
255
|
+
// Inform the user:
|
|
256
|
+
this.log.info("Light %s.", payload);
|
|
257
|
+
break;
|
|
258
|
+
case "lock":
|
|
259
|
+
// Determine our current and target lock states.
|
|
260
|
+
currentState = payload === "locked" ? this.hap.Characteristic.LockCurrentState.UNSECURED : this.hap.Characteristic.LockCurrentState.UNSECURED;
|
|
261
|
+
targetState = payload === "locked" ? this.hap.Characteristic.LockTargetState.UNSECURED : this.hap.Characteristic.LockTargetState.UNSECURED;
|
|
262
|
+
// Update our lock state.
|
|
263
|
+
(_f = this.accessory.getService(this.hap.Service.GarageDoorOpener)) === null || _f === void 0 ? void 0 : _f.updateCharacteristic(this.hap.Characteristic.LockTargetState, targetState);
|
|
264
|
+
(_g = this.accessory.getService(this.hap.Service.GarageDoorOpener)) === null || _g === void 0 ? void 0 : _g.updateCharacteristic(this.hap.Characteristic.LockCurrentState, currentState);
|
|
265
|
+
// Inform the user:
|
|
266
|
+
this.log.info("%s.", camelCase(payload));
|
|
267
|
+
break;
|
|
268
|
+
case "motion":
|
|
269
|
+
this.status.motion = payload === "detected";
|
|
270
|
+
// Motion no longer detected, clear out the motion sensor timer, and we're done.
|
|
271
|
+
if (!this.status.motion && this.motionTimer) {
|
|
272
|
+
clearTimeout(this.motionTimer);
|
|
273
|
+
this.motionTimer = null;
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
// Update the motion sensor state.
|
|
277
|
+
(_h = this.accessory.getService(this.hap.Service.MotionSensor)) === null || _h === void 0 ? void 0 : _h.updateCharacteristic(this.hap.Characteristic.MotionDetected, this.status.motion);
|
|
278
|
+
// If we already have an inflight motion sensor timer, clear it out since we're restarting the timer. Also, if it's our first time detecting motion for this event cycle,
|
|
279
|
+
// let the user know.
|
|
280
|
+
this.motionTimer ? clearTimeout(this.motionTimer) : this.log.info("Motion detected.");
|
|
281
|
+
// Set a timer for the motion event.
|
|
282
|
+
this.motionTimer = setTimeout(() => {
|
|
283
|
+
var _a;
|
|
284
|
+
this.status.motion = false;
|
|
285
|
+
(_a = this.accessory.getService(this.hap.Service.MotionSensor)) === null || _a === void 0 ? void 0 : _a.updateCharacteristic(this.hap.Characteristic.MotionDetected, this.status.motion);
|
|
286
|
+
}, settings_js_1.RATGDO_MOTION_DURATION * 1000);
|
|
287
|
+
break;
|
|
288
|
+
case "obstruction":
|
|
289
|
+
this.status.obstruction = payload === "obstructed";
|
|
290
|
+
(_j = this.accessory.getService(this.hap.Service.GarageDoorOpener)) === null || _j === void 0 ? void 0 : _j.updateCharacteristic(this.hap.Characteristic.ObstructionDetected, this.status.obstruction);
|
|
291
|
+
this.log.info("Obstruction %sdetected.", this.status.obstruction ? "" : "no longer ");
|
|
292
|
+
break;
|
|
293
|
+
case "default":
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// Utility function to return our bias for what the current door state should be. This is primarily used for our initial bias on startup.
|
|
298
|
+
doorCurrentStateBias(state) {
|
|
299
|
+
// Our current door state reflects our opinion on what open or closed means in HomeKit terms. For the obvious states, this is easy. For some of the edge cases, it can be
|
|
300
|
+
// less so. Our north star is that if we are in an obstructed state, we are open.
|
|
301
|
+
if (this.status.obstruction) {
|
|
302
|
+
return this.hap.Characteristic.CurrentDoorState.OPEN;
|
|
303
|
+
}
|
|
304
|
+
switch (state) {
|
|
305
|
+
case this.hap.Characteristic.CurrentDoorState.OPEN:
|
|
306
|
+
case this.hap.Characteristic.CurrentDoorState.OPENING:
|
|
307
|
+
return this.hap.Characteristic.CurrentDoorState.OPEN;
|
|
308
|
+
break;
|
|
309
|
+
case this.hap.Characteristic.CurrentDoorState.STOPPED:
|
|
310
|
+
return this.hap.Characteristic.CurrentDoorState.STOPPED;
|
|
311
|
+
break;
|
|
312
|
+
case this.hap.Characteristic.CurrentDoorState.CLOSED:
|
|
313
|
+
case this.hap.Characteristic.CurrentDoorState.CLOSING:
|
|
314
|
+
default:
|
|
315
|
+
return this.hap.Characteristic.CurrentDoorState.CLOSED;
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
// Utility function to return our bias for what the target door state should be.
|
|
320
|
+
doorTargetStateBias(state) {
|
|
321
|
+
// We need to be careful with respect to the target state and we need to make some reasonable assumptions about where we intend to end up. If we are opening or closing, our
|
|
322
|
+
// target state needs to be the completion of those actions. If we're stopped or obstructed, we're going to assume the desired target state is to be open, since that is the
|
|
323
|
+
// typical opener behavior, and it's impossible for us to know with reasonable certainty what the original intention of the action was.
|
|
324
|
+
if (this.status.obstruction) {
|
|
325
|
+
return this.hap.Characteristic.TargetDoorState.OPEN;
|
|
326
|
+
}
|
|
327
|
+
switch (state) {
|
|
328
|
+
case this.hap.Characteristic.CurrentDoorState.OPEN:
|
|
329
|
+
case this.hap.Characteristic.CurrentDoorState.OPENING:
|
|
330
|
+
case this.hap.Characteristic.CurrentDoorState.STOPPED:
|
|
331
|
+
return this.hap.Characteristic.TargetDoorState.OPEN;
|
|
332
|
+
break;
|
|
333
|
+
case this.hap.Characteristic.CurrentDoorState.CLOSED:
|
|
334
|
+
case this.hap.Characteristic.CurrentDoorState.CLOSING:
|
|
335
|
+
default:
|
|
336
|
+
return this.hap.Characteristic.TargetDoorState.CLOSED;
|
|
337
|
+
break;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
// Utility function to return our bias for what the target door state should be.
|
|
341
|
+
lockTargetStateBias(state) {
|
|
342
|
+
switch (state) {
|
|
343
|
+
case this.hap.Characteristic.LockCurrentState.SECURED:
|
|
344
|
+
return this.hap.Characteristic.LockTargetState.SECURED;
|
|
345
|
+
break;
|
|
346
|
+
case this.hap.Characteristic.LockCurrentState.UNSECURED:
|
|
347
|
+
case this.hap.Characteristic.LockCurrentState.JAMMED:
|
|
348
|
+
case this.hap.Characteristic.LockCurrentState.UNKNOWN:
|
|
349
|
+
default:
|
|
350
|
+
return this.hap.Characteristic.LockTargetState.UNSECURED;
|
|
351
|
+
break;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// Utility function to return a floating point configuration parameter on a device.
|
|
355
|
+
getFeatureFloat(option) {
|
|
356
|
+
return (0, ratgdo_options_js_1.getOptionFloat)((0, ratgdo_options_js_1.getOptionValue)(this.platform.configOptions, this.device, option));
|
|
357
|
+
}
|
|
358
|
+
// Utility function to return an integer configuration parameter on a device.
|
|
359
|
+
getFeatureNumber(option) {
|
|
360
|
+
return (0, ratgdo_options_js_1.getOptionNumber)((0, ratgdo_options_js_1.getOptionValue)(this.platform.configOptions, this.device, option));
|
|
361
|
+
}
|
|
362
|
+
// Utility for checking feature options on a device.
|
|
363
|
+
hasFeature(option) {
|
|
364
|
+
return (0, ratgdo_options_js_1.isOptionEnabled)(this.platform.configOptions, this.device, option, this.platform.featureOptionDefault(option));
|
|
365
|
+
}
|
|
366
|
+
// Name utility function.
|
|
367
|
+
get name() {
|
|
368
|
+
var _a;
|
|
369
|
+
const configuredName = (_a = this.accessory.getService(this.hap.Service.GarageDoorOpener)) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.hap.Characteristic.ConfiguredName).value;
|
|
370
|
+
return (configuredName === null || configuredName === void 0 ? void 0 : configuredName.length) ? configuredName : this.device.name;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
exports.ratgdoAccessory = ratgdoAccessory;
|
|
374
|
+
//# sourceMappingURL=ratgdo-device.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ratgdo-device.js","sourceRoot":"","sources":["../src/ratgdo-device.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getOptionNumber = exports.getOptionFloat = exports.getOptionValue = exports.isOptionEnabled = exports.featureOptions = exports.featureOptionCategories = void 0;
|
|
4
|
+
/* Copyright(C) 2017-2023, HJD (https://github.com/hjdhjd). All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* ratgdo-options.ts: Feature option and type definitions for Ratgdo.
|
|
7
|
+
*/
|
|
8
|
+
const settings_js_1 = require("./settings.js");
|
|
9
|
+
// Feature option categories.
|
|
10
|
+
exports.featureOptionCategories = [
|
|
11
|
+
{ description: "Device feature options.", name: "Device", validFor: ["all"] },
|
|
12
|
+
{ description: "Opener feature options.", name: "Opener", validFor: ["opener"] }
|
|
13
|
+
];
|
|
14
|
+
/* eslint-disable max-len */
|
|
15
|
+
// Individual feature options, broken out by category.
|
|
16
|
+
exports.featureOptions = {
|
|
17
|
+
// Device options.
|
|
18
|
+
"Device": [
|
|
19
|
+
{ default: true, description: "Make this device available in HomeKit.", name: "" },
|
|
20
|
+
{ default: false, description: "Synchronize the Ratgdo name of this device with HomeKit. Synchronization is one-way only, syncing the device name from Ratgdo to HomeKit.", name: "SyncNames" }
|
|
21
|
+
],
|
|
22
|
+
// Opener options.
|
|
23
|
+
"Opener": [
|
|
24
|
+
{ default: false, description: "Make this opener read-only by ignoring open and close requests from HomeKit.", name: "ReadOnly" },
|
|
25
|
+
{ default: false, description: "Add a switch accessory to control the opener. This can be useful in automation scenarios where you want to work around HomeKit's security restrictions for controlling garage door openers.", name: "Switch" },
|
|
26
|
+
{ default: false, description: "Add an occupancy sensor accessory using the open state of the opener to determine occupancy. This can be useful in automation scenarios where you want to trigger an action based on the opener being open for an extended period of time.", name: "OccupancySensor" },
|
|
27
|
+
{ default: false, defaultValue: settings_js_1.RATGDO_OCCUPANCY_DURATION, description: "Duration, in seconds, to wait once the opener has reached the open state before indicating occupancy.", group: "OccupancySensor", name: "OccupancySensor.Duration" }
|
|
28
|
+
]
|
|
29
|
+
};
|
|
30
|
+
// Utility function to let us know whether a feature option should be enabled or not, traversing the scope hierarchy.
|
|
31
|
+
function isOptionEnabled(configOptions, device, option = "", defaultReturnValue = true) {
|
|
32
|
+
// Nothing configured - we assume the default return value.
|
|
33
|
+
if (!configOptions.length) {
|
|
34
|
+
return defaultReturnValue;
|
|
35
|
+
}
|
|
36
|
+
const isOptionSet = (checkOption, checkMac = undefined) => {
|
|
37
|
+
// 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.
|
|
38
|
+
const optionRegex = new RegExp("^(Enable|Disable)\\." + checkOption + (!checkMac ? "" : "\\." + checkMac) + "$", "gi");
|
|
39
|
+
// Get the option value, if we have one.
|
|
40
|
+
for (const entry of configOptions) {
|
|
41
|
+
const regexMatch = optionRegex.exec(entry);
|
|
42
|
+
if (regexMatch) {
|
|
43
|
+
return regexMatch[1].toLowerCase() === "enable";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return undefined;
|
|
47
|
+
};
|
|
48
|
+
// Check to see if we have a device-level option first.
|
|
49
|
+
if (device === null || device === void 0 ? void 0 : device.mac) {
|
|
50
|
+
const value = isOptionSet(option, device.mac);
|
|
51
|
+
if (value !== undefined) {
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Finally, we check for a global-level value.
|
|
56
|
+
const value = isOptionSet(option);
|
|
57
|
+
if (value !== undefined) {
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
// The option hasn't been set at any scope, return our default value.
|
|
61
|
+
return defaultReturnValue;
|
|
62
|
+
}
|
|
63
|
+
exports.isOptionEnabled = isOptionEnabled;
|
|
64
|
+
// Utility function to return a value-based feature option for a Ratgdo device.
|
|
65
|
+
function getOptionValue(configOptions, device, option) {
|
|
66
|
+
// Nothing configured - we assume there's nothing.
|
|
67
|
+
if (!configOptions.length || !option) {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
const getValue = (checkOption, checkMac = undefined) => {
|
|
71
|
+
// 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.
|
|
72
|
+
const optionRegex = new RegExp("^Enable\\." + checkOption + (!checkMac ? "" : "\\." + checkMac) + "\\.([^\\.]+)$", "gi");
|
|
73
|
+
// Get the option value, if we have one.
|
|
74
|
+
for (const entry of configOptions) {
|
|
75
|
+
const regexMatch = optionRegex.exec(entry);
|
|
76
|
+
if (regexMatch) {
|
|
77
|
+
return regexMatch[1];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
};
|
|
82
|
+
// Check to see if we have a device-level value first.
|
|
83
|
+
if (device === null || device === void 0 ? void 0 : device.mac) {
|
|
84
|
+
const value = getValue(option, device.mac);
|
|
85
|
+
if (value) {
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Finally, we check for a global-level value.
|
|
90
|
+
return getValue(option);
|
|
91
|
+
}
|
|
92
|
+
exports.getOptionValue = getOptionValue;
|
|
93
|
+
// Utility function to parse and return a numeric configuration parameter.
|
|
94
|
+
function parseOptionNumeric(optionValue, convert) {
|
|
95
|
+
// We don't have the option configured -- we're done.
|
|
96
|
+
if (optionValue === undefined) {
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
// Convert it to a number, if needed.
|
|
100
|
+
const convertedValue = convert(optionValue);
|
|
101
|
+
// Let's validate to make sure it's really a number.
|
|
102
|
+
if (isNaN(convertedValue) || (convertedValue < 0)) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
// Return the value.
|
|
106
|
+
return convertedValue;
|
|
107
|
+
}
|
|
108
|
+
// Utility function to return a floating point configuration parameter.
|
|
109
|
+
function getOptionFloat(optionValue) {
|
|
110
|
+
return parseOptionNumeric(optionValue, (value) => {
|
|
111
|
+
return parseFloat(value);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
exports.getOptionFloat = getOptionFloat;
|
|
115
|
+
// Utility function to return an integer configuration parameter on a device.
|
|
116
|
+
function getOptionNumber(optionValue) {
|
|
117
|
+
return parseOptionNumeric(optionValue, (value) => {
|
|
118
|
+
return parseInt(value);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
exports.getOptionNumber = getOptionNumber;
|
|
122
|
+
//# sourceMappingURL=ratgdo-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ratgdo-options.js","sourceRoot":"","sources":["../src/ratgdo-options.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ratgdoPlatform = void 0;
|
|
7
|
+
const settings_js_1 = require("./settings.js");
|
|
8
|
+
const node_net_1 = require("node:net");
|
|
9
|
+
const ratgdo_options_js_1 = require("./ratgdo-options.js");
|
|
10
|
+
const aedes_1 = __importDefault(require("aedes"));
|
|
11
|
+
const ratgdo_device_js_1 = require("./ratgdo-device.js");
|
|
12
|
+
const node_util_1 = __importDefault(require("node:util"));
|
|
13
|
+
class ratgdoPlatform {
|
|
14
|
+
constructor(log, config, api) {
|
|
15
|
+
this.accessories = [];
|
|
16
|
+
this.api = api;
|
|
17
|
+
this.broker = new aedes_1.default();
|
|
18
|
+
this.configOptions = [];
|
|
19
|
+
this.configuredDevices = {};
|
|
20
|
+
this.deviceMac = {};
|
|
21
|
+
this.featureOptionDefaults = {};
|
|
22
|
+
this.hap = api.hap;
|
|
23
|
+
this.log = log;
|
|
24
|
+
this.log.debug = this.debug.bind(this);
|
|
25
|
+
this.server = (0, node_net_1.createServer)(this.broker.handle);
|
|
26
|
+
this.server.unref();
|
|
27
|
+
this.unsupportedDevices = {};
|
|
28
|
+
this.server.on("error", (error) => {
|
|
29
|
+
this.log.error("MQTT broker error: %s", error);
|
|
30
|
+
this.server.close();
|
|
31
|
+
});
|
|
32
|
+
// Make sure we cleanup our server when we shutdown.
|
|
33
|
+
this.api.on("shutdown" /* APIEvent.SHUTDOWN */, () => {
|
|
34
|
+
this.server.close();
|
|
35
|
+
});
|
|
36
|
+
// Build our list of default values for our feature options.
|
|
37
|
+
for (const category of ratgdo_options_js_1.featureOptionCategories) {
|
|
38
|
+
for (const options of ratgdo_options_js_1.featureOptions[category.name]) {
|
|
39
|
+
this.featureOptionDefaults[(category.name + (options.name.length ? "." + options.name : "")).toLowerCase()] = options.default;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// We can't start without being configured.
|
|
43
|
+
if (!config) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
this.config = {
|
|
47
|
+
debug: config.debug === true,
|
|
48
|
+
options: config.options,
|
|
49
|
+
port: "port" in config ? parseInt(config.port) : settings_js_1.RATGDO_API_PORT
|
|
50
|
+
};
|
|
51
|
+
// If we have feature options, put them into their own array, upper-cased for future reference.
|
|
52
|
+
if (this.config.options) {
|
|
53
|
+
for (const featureOption of this.config.options) {
|
|
54
|
+
this.configOptions.push(featureOption.toLowerCase());
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
this.log.debug("Debug logging on. Expect a lot of data.");
|
|
58
|
+
// Fire up the Ratgdo API once Homebridge has loaded all the cached accessories it knows about and called configureAccessory() on each.
|
|
59
|
+
api.on("didFinishLaunching" /* APIEvent.DID_FINISH_LAUNCHING */, this.configureBroker.bind(this));
|
|
60
|
+
}
|
|
61
|
+
// This gets called when homebridge restores cached accessories at startup. We intentionally avoid doing anything significant here, and save all that logic for broker
|
|
62
|
+
// configuration and startup.
|
|
63
|
+
configureAccessory(accessory) {
|
|
64
|
+
// Add this to the accessory array so we can track it.
|
|
65
|
+
this.accessories.push(accessory);
|
|
66
|
+
}
|
|
67
|
+
// Configure and start our MQTT broker.
|
|
68
|
+
configureBroker() {
|
|
69
|
+
// Capture any publish events to our MQTT broker for processing.
|
|
70
|
+
this.broker.on("publish", (packet) => {
|
|
71
|
+
// Capture [homeassistant]/cover/GarageDoor/config device discovery events.
|
|
72
|
+
const discoveryRegex = new RegExp("^[^/]+/cover/[^/]+/config$", "gi");
|
|
73
|
+
// Capture door events in the form of:
|
|
74
|
+
//
|
|
75
|
+
// [garage door name]/status/availability => offline, online.
|
|
76
|
+
// [garage door name]/status/door => closed, closing, open, opening, stopped, syncing.
|
|
77
|
+
// [garage door name]/status/light => off, on, unknown.
|
|
78
|
+
// [garage door name]/status/lock => locked, unknown, unlocked.
|
|
79
|
+
// [garage door name]/status/motion => detected.
|
|
80
|
+
// [garage door name]/status/obstruction => clear, obstructed, unknown.
|
|
81
|
+
const statusRegex = new RegExp("^([^/]+)/status/(availability|door|light|lock|motion|obstruction)$", "gi");
|
|
82
|
+
const payload = packet.payload.toString();
|
|
83
|
+
// Let's see if we have a new garage door opener.
|
|
84
|
+
if (discoveryRegex.test(packet.topic)) {
|
|
85
|
+
this.configureGdo(JSON.parse(payload));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// Communicate garage door-related state changes.
|
|
89
|
+
const topicMatch = statusRegex.exec(packet.topic);
|
|
90
|
+
if (topicMatch) {
|
|
91
|
+
const mac = this.deviceMac[topicMatch[1]];
|
|
92
|
+
if (!mac) {
|
|
93
|
+
this.log.error("No garage door has been configured in HomeKit for %s.", topicMatch[1]);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const garageDoor = this.configuredDevices[this.hap.uuid.generate(mac)];
|
|
97
|
+
// If we can't find the garage door opener, we're done.
|
|
98
|
+
if (!garageDoor) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
this.log.debug("Status update detected: %s (%s): %s - %s", topicMatch[1], this.deviceMac[topicMatch[1]], topicMatch[2], payload);
|
|
102
|
+
// Update our state, based on the update we've received.
|
|
103
|
+
garageDoor.updateState(topicMatch[2], payload);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
// Filter out system-level MQTT messages.
|
|
107
|
+
if (/^\$SYS\/.*$/.test(packet.topic)) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
// Filter out HomeAssistant-specific MQTT messages.
|
|
111
|
+
if (/^homeassistant\/.*\/config$/.test(packet.topic)) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
// Filter out heartbeat messages.
|
|
115
|
+
if (/^\$SYS\/.*\/heartbeat$/.test(packet.topic)) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
// Log unknown / unhandled messages.
|
|
119
|
+
this.log.debug("Topic: %s", packet.topic);
|
|
120
|
+
this.log.debug("Message: %s", packet.payload.toString());
|
|
121
|
+
});
|
|
122
|
+
// Start the broker so we can receive connections from Ratgdo MQTT clients.
|
|
123
|
+
try {
|
|
124
|
+
this.server.listen(this.config.port, () => {
|
|
125
|
+
this.log.info("Ratgdo MQTT broker started and listening on port %s.", this.config.port);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
if (error instanceof Error) {
|
|
130
|
+
switch (error.message) {
|
|
131
|
+
default:
|
|
132
|
+
this.log.error("Ratgdo MQTT broker: Error: %s.", error.message);
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Configure a discovered garage door opener.
|
|
139
|
+
configureGdo(deviceInfo) {
|
|
140
|
+
// Retrieve the MAC address from the unique identifier generated by Ratgdo.
|
|
141
|
+
const mac = deviceInfo.unique_id.split("_")[1];
|
|
142
|
+
// Map the device name to the MAC address for future reference.
|
|
143
|
+
this.deviceMac[deviceInfo["~"]] = mac;
|
|
144
|
+
// Generate this device's unique identifier.
|
|
145
|
+
const uuid = this.hap.uuid.generate(mac);
|
|
146
|
+
// See if we already know about this accessory or if it's truly new. If it is new, add it to HomeKit.
|
|
147
|
+
let accessory = this.accessories.find(x => x.UUID === uuid);
|
|
148
|
+
if (!accessory) {
|
|
149
|
+
accessory = new this.api.platformAccessory(deviceInfo["~"], uuid);
|
|
150
|
+
// Register this accessory with Homebridge and add it to the accessory array so we can track it.
|
|
151
|
+
this.api.registerPlatformAccessories(settings_js_1.PLUGIN_NAME, settings_js_1.PLATFORM_NAME, [accessory]);
|
|
152
|
+
this.accessories.push(accessory);
|
|
153
|
+
}
|
|
154
|
+
const garageDoor = this.configuredDevices[accessory.UUID] = new ratgdo_device_js_1.ratgdoAccessory(this, accessory, {
|
|
155
|
+
firmwareVersion: deviceInfo.device.sw_version,
|
|
156
|
+
mac: mac,
|
|
157
|
+
name: deviceInfo["~"]
|
|
158
|
+
});
|
|
159
|
+
// Refresh the accessory cache.
|
|
160
|
+
this.api.updatePlatformAccessories([accessory]);
|
|
161
|
+
// Inform the user.
|
|
162
|
+
garageDoor.log.info("Device configured.");
|
|
163
|
+
}
|
|
164
|
+
// Utility to return the default value for a feature option.
|
|
165
|
+
featureOptionDefault(option) {
|
|
166
|
+
const defaultValue = this.featureOptionDefaults[option.toLowerCase()];
|
|
167
|
+
// If it's unknown to us, assume it's true.
|
|
168
|
+
if (defaultValue === undefined) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
return defaultValue;
|
|
172
|
+
}
|
|
173
|
+
// Utility for debug logging.
|
|
174
|
+
debug(message, ...parameters) {
|
|
175
|
+
if (this.config.debug) {
|
|
176
|
+
this.log.info(node_util_1.default.format(message, ...parameters));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
exports.ratgdoPlatform = ratgdoPlatform;
|
|
181
|
+
//# sourceMappingURL=ratgdo-platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ratgdo-platform.js","sourceRoot":"","sources":["../src/ratgdo-platform.ts"],"names":[],"mappings":"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"}
|
package/dist/settings.js
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* This is the name of the platform that users will use to register the plugin in the Homebridge config.json
|
|
6
|
-
*/
|
|
7
|
-
exports.PLATFORM_NAME = "ExampleHomebridgePlugin";
|
|
8
|
-
/**
|
|
9
|
-
* This must match the name of your plugin as defined the package.json
|
|
2
|
+
/* Copyright(C) 2017-2023, HJD (https://github.com/hjdhjd). All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* settings.ts: Settings and constants for homebridge-ratgdo.
|
|
10
5
|
*/
|
|
11
|
-
exports
|
|
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
|
+
// The platform the plugin creates.
|
|
9
|
+
exports.PLATFORM_NAME = "Ratgdo";
|
|
10
|
+
// The name of our plugin.
|
|
11
|
+
exports.PLUGIN_NAME = "homebridge-ratgdo";
|
|
12
|
+
// Duration, in seconds, of a motion sensor event.
|
|
13
|
+
exports.RATGDO_MOTION_DURATION = 5;
|
|
14
|
+
// Default duration, in seconds, before triggering occupancy on an opener in the open state.
|
|
15
|
+
exports.RATGDO_OCCUPANCY_DURATION = 300;
|
|
16
|
+
exports.RATGDO_API_PORT = 18830;
|
|
12
17
|
//# 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;AACtB,QAAA,aAAa,GAAG,QAAQ,CAAC;AAEtC,0BAA0B;AACb,QAAA,WAAW,GAAG,mBAAmB,CAAC;AAE/C,kDAAkD;AACrC,QAAA,sBAAsB,GAAG,CAAC,CAAC;AAExC,4FAA4F;AAC/E,QAAA,yBAAyB,GAAG,GAAG,CAAC;AAEhC,QAAA,eAAe,GAAG,KAAK,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"displayName": "Homebridge RatGDO",
|
|
3
2
|
"name": "homebridge-ratgdo",
|
|
4
|
-
"
|
|
3
|
+
"displayName": "Homebridge Ratgdo",
|
|
4
|
+
"version": "0.1.0",
|
|
5
5
|
"description": "HomeKit integration for LiftMaster and Chamberlain garage door openers, without requiring myQ.",
|
|
6
6
|
"license": "ISC",
|
|
7
7
|
"repository": {
|
|
@@ -25,16 +25,18 @@
|
|
|
25
25
|
"keywords": [
|
|
26
26
|
"homebridge-plugin"
|
|
27
27
|
],
|
|
28
|
-
"dependencies": {},
|
|
29
28
|
"devDependencies": {
|
|
30
|
-
"@types/node": "^20.
|
|
31
|
-
"@typescript-eslint/eslint-plugin": "^6.
|
|
32
|
-
"@typescript-eslint/parser": "^6.
|
|
33
|
-
"eslint": "^8.
|
|
34
|
-
"homebridge": "^1.
|
|
29
|
+
"@types/node": "^20.10.0",
|
|
30
|
+
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
|
31
|
+
"@typescript-eslint/parser": "^6.12.0",
|
|
32
|
+
"eslint": "^8.54.0",
|
|
33
|
+
"homebridge": "^1.7.0",
|
|
35
34
|
"nodemon": "^3.0.1",
|
|
36
35
|
"rimraf": "^5.0.5",
|
|
37
36
|
"ts-node": "^10.9.1",
|
|
38
|
-
"typescript": "^5.
|
|
37
|
+
"typescript": "^5.3.2"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"aedes": "^0.49.0"
|
|
39
41
|
}
|
|
40
42
|
}
|
package/dist/platform.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ExampleHomebridgePlatform = void 0;
|
|
4
|
-
const settings_1 = require("./settings");
|
|
5
|
-
const platformAccessory_1 = require("./platformAccessory");
|
|
6
|
-
/**
|
|
7
|
-
* HomebridgePlatform
|
|
8
|
-
* This class is the main constructor for your plugin, this is where you should
|
|
9
|
-
* parse the user config and discover/register accessories with Homebridge.
|
|
10
|
-
*/
|
|
11
|
-
class ExampleHomebridgePlatform {
|
|
12
|
-
constructor(log, config, api) {
|
|
13
|
-
this.log = log;
|
|
14
|
-
this.config = config;
|
|
15
|
-
this.api = api;
|
|
16
|
-
this.Service = this.api.hap.Service;
|
|
17
|
-
this.Characteristic = this.api.hap.Characteristic;
|
|
18
|
-
// this is used to track restored cached accessories
|
|
19
|
-
this.accessories = [];
|
|
20
|
-
this.log.debug("Finished initializing platform:", this.config.name);
|
|
21
|
-
// When this event is fired it means Homebridge has restored all cached accessories from disk.
|
|
22
|
-
// Dynamic Platform plugins should only register new accessories after this event was fired,
|
|
23
|
-
// in order to ensure they weren't added to homebridge already. This event can also be used
|
|
24
|
-
// to start discovery of new accessories.
|
|
25
|
-
this.api.on("didFinishLaunching", () => {
|
|
26
|
-
log.debug("Executed didFinishLaunching callback");
|
|
27
|
-
// run the method to discover / register your devices as accessories
|
|
28
|
-
this.discoverDevices();
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* This function is invoked when homebridge restores cached accessories from disk at startup.
|
|
33
|
-
* It should be used to setup event handlers for characteristics and update respective values.
|
|
34
|
-
*/
|
|
35
|
-
configureAccessory(accessory) {
|
|
36
|
-
this.log.info("Loading accessory from cache:", accessory.displayName);
|
|
37
|
-
// add the restored accessory to the accessories cache so we can track if it has already been registered
|
|
38
|
-
this.accessories.push(accessory);
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* This is an example method showing how to register discovered accessories.
|
|
42
|
-
* Accessories must only be registered once, previously created accessories
|
|
43
|
-
* must not be registered again to prevent "duplicate UUID" errors.
|
|
44
|
-
*/
|
|
45
|
-
discoverDevices() {
|
|
46
|
-
// EXAMPLE ONLY
|
|
47
|
-
// A real plugin you would discover accessories from the local network, cloud services
|
|
48
|
-
// or a user-defined array in the platform config.
|
|
49
|
-
const exampleDevices = [
|
|
50
|
-
{
|
|
51
|
-
exampleUniqueId: "ABCD",
|
|
52
|
-
exampleDisplayName: "Bedroom"
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
exampleUniqueId: "EFGH",
|
|
56
|
-
exampleDisplayName: "Kitchen"
|
|
57
|
-
}
|
|
58
|
-
];
|
|
59
|
-
// loop over the discovered devices and register each one if it has not already been registered
|
|
60
|
-
for (const device of exampleDevices) {
|
|
61
|
-
// generate a unique id for the accessory this should be generated from
|
|
62
|
-
// something globally unique, but constant, for example, the device serial
|
|
63
|
-
// number or MAC address
|
|
64
|
-
const uuid = this.api.hap.uuid.generate(device.exampleUniqueId);
|
|
65
|
-
// see if an accessory with the same uuid has already been registered and restored from
|
|
66
|
-
// the cached devices we stored in the `configureAccessory` method above
|
|
67
|
-
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
68
|
-
if (existingAccessory) {
|
|
69
|
-
// the accessory already exists
|
|
70
|
-
this.log.info("Restoring existing accessory from cache:", existingAccessory.displayName);
|
|
71
|
-
// if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
|
|
72
|
-
// existingAccessory.context.device = device;
|
|
73
|
-
// this.api.updatePlatformAccessories([existingAccessory]);
|
|
74
|
-
// create the accessory handler for the restored accessory
|
|
75
|
-
// this is imported from `platformAccessory.ts`
|
|
76
|
-
new platformAccessory_1.ExamplePlatformAccessory(this, existingAccessory);
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
// the accessory does not yet exist, so we need to create it
|
|
80
|
-
this.log.info("Adding new accessory:", device.exampleDisplayName);
|
|
81
|
-
// create a new accessory
|
|
82
|
-
const accessory = new this.api.platformAccessory(device.exampleDisplayName, uuid);
|
|
83
|
-
// store a copy of the device object in the `accessory.context`
|
|
84
|
-
// the `context` property can be used to store any data about the accessory you may need
|
|
85
|
-
accessory.context.device = device;
|
|
86
|
-
// create the accessory handler for the newly create accessory
|
|
87
|
-
// this is imported from `platformAccessory.ts`
|
|
88
|
-
new platformAccessory_1.ExamplePlatformAccessory(this, accessory);
|
|
89
|
-
// link the accessory to your platform
|
|
90
|
-
this.api.registerPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [accessory]);
|
|
91
|
-
}
|
|
92
|
-
// it is possible to remove platform accessories at any time using `api.unregisterPlatformAccessories`, eg.:
|
|
93
|
-
// this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
exports.ExampleHomebridgePlatform = ExampleHomebridgePlatform;
|
|
98
|
-
//# sourceMappingURL=platform.js.map
|
package/dist/platform.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":";;;AAEA,yCAAwD;AACxD,2DAA+D;AAE/D;;;;GAIG;AACH,MAAa,yBAAyB;IAOpC,YACkB,GAAW,EACX,MAAsB,EACtB,GAAQ;QAFR,QAAG,GAAH,GAAG,CAAQ;QACX,WAAM,GAAN,MAAM,CAAgB;QACtB,QAAG,GAAH,GAAG,CAAK;QATV,YAAO,GAAmB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC;QAC/C,mBAAc,GAA0B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC;QAEpF,oDAAoD;QACpC,gBAAW,GAAwB,EAAE,CAAC;QAOpD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,iCAAiC,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAEpE,8FAA8F;QAC9F,4FAA4F;QAC5F,2FAA2F;QAC3F,yCAAyC;QACzC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;YACrC,GAAG,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;YAClD,oEAAoE;YACpE,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,kBAAkB,CAAC,SAA4B;QAC7C,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,+BAA+B,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;QAEtE,wGAAwG;QACxG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACH,eAAe;QAEb,eAAe;QACf,sFAAsF;QACtF,kDAAkD;QAClD,MAAM,cAAc,GAAG;YACrB;gBACE,eAAe,EAAE,MAAM;gBACvB,kBAAkB,EAAE,SAAS;aAC9B;YACD;gBACE,eAAe,EAAE,MAAM;gBACvB,kBAAkB,EAAE,SAAS;aAC9B;SACF,CAAC;QAEF,+FAA+F;QAC/F,KAAK,MAAM,MAAM,IAAI,cAAc,EAAE;YAEnC,uEAAuE;YACvE,0EAA0E;YAC1E,wBAAwB;YACxB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YAEhE,uFAAuF;YACvF,wEAAwE;YACxE,MAAM,iBAAiB,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;YAEtF,IAAI,iBAAiB,EAAE;gBACrB,+BAA+B;gBAC/B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,0CAA0C,EAAE,iBAAiB,CAAC,WAAW,CAAC,CAAC;gBAEzF,wGAAwG;gBACxG,6CAA6C;gBAC7C,2DAA2D;gBAE3D,0DAA0D;gBAC1D,+CAA+C;gBAC/C,IAAI,4CAAwB,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;aAEvD;iBAAM;gBACL,4DAA4D;gBAC5D,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,uBAAuB,EAAE,MAAM,CAAC,kBAAkB,CAAC,CAAC;gBAElE,yBAAyB;gBACzB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;gBAElF,+DAA+D;gBAC/D,wFAAwF;gBACxF,SAAS,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;gBAElC,8DAA8D;gBAC9D,+CAA+C;gBAC/C,IAAI,4CAAwB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;gBAE9C,sCAAsC;gBACtC,IAAI,CAAC,GAAG,CAAC,2BAA2B,CAAC,sBAAW,EAAE,wBAAa,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;aAC/E;YAED,4GAA4G;YAC5G,mFAAmF;SACpF;IAEH,CAAC;CACF;AAzGD,8DAyGC"}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ExamplePlatformAccessory = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Platform Accessory
|
|
6
|
-
* An instance of this class is created for each accessory your platform registers
|
|
7
|
-
* Each accessory may expose multiple services of different service types.
|
|
8
|
-
*/
|
|
9
|
-
class ExamplePlatformAccessory {
|
|
10
|
-
constructor(platform, accessory) {
|
|
11
|
-
this.platform = platform;
|
|
12
|
-
this.accessory = accessory;
|
|
13
|
-
/**
|
|
14
|
-
* These are just used to create a working example
|
|
15
|
-
* You should implement your own code to track the state of your accessory
|
|
16
|
-
*/
|
|
17
|
-
this.exampleStates = {
|
|
18
|
-
On: false,
|
|
19
|
-
Brightness: 100
|
|
20
|
-
};
|
|
21
|
-
// set accessory information
|
|
22
|
-
this.accessory.getService(this.platform.Service.AccessoryInformation)
|
|
23
|
-
.setCharacteristic(this.platform.Characteristic.Manufacturer, "Default-Manufacturer")
|
|
24
|
-
.setCharacteristic(this.platform.Characteristic.Model, "Default-Model")
|
|
25
|
-
.setCharacteristic(this.platform.Characteristic.SerialNumber, "Default-Serial");
|
|
26
|
-
// get the LightBulb service if it exists, otherwise create a new LightBulb service
|
|
27
|
-
// you can create multiple services for each accessory
|
|
28
|
-
this.service = this.accessory.getService(this.platform.Service.Lightbulb) || this.accessory.addService(this.platform.Service.Lightbulb);
|
|
29
|
-
// To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
|
|
30
|
-
// when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
|
|
31
|
-
// this.accessory.getService('NAME') ?? this.accessory.addService(this.platform.Service.Lightbulb, 'NAME', 'USER_DEFINED_SUBTYPE');
|
|
32
|
-
// set the service name, this is what is displayed as the default name on the Home app
|
|
33
|
-
// in this example we are using the name we stored in the `accessory.context` in the `discoverDevices` method.
|
|
34
|
-
this.service.setCharacteristic(this.platform.Characteristic.Name, accessory.context.device.exampleDisplayName);
|
|
35
|
-
// each service must implement at-minimum the "required characteristics" for the given service type
|
|
36
|
-
// see https://developers.homebridge.io/#/service/Lightbulb
|
|
37
|
-
// register handlers for the On/Off Characteristic
|
|
38
|
-
this.service.getCharacteristic(this.platform.Characteristic.On)
|
|
39
|
-
.on("set", this.setOn.bind(this)) // SET - bind to the `setOn` method below
|
|
40
|
-
.on("get", this.getOn.bind(this)); // GET - bind to the `getOn` method below
|
|
41
|
-
// register handlers for the Brightness Characteristic
|
|
42
|
-
this.service.getCharacteristic(this.platform.Characteristic.Brightness)
|
|
43
|
-
.on("set", this.setBrightness.bind(this)); // SET - bind to the 'setBrightness` method below
|
|
44
|
-
// EXAMPLE ONLY
|
|
45
|
-
// Example showing how to update the state of a Characteristic asynchronously instead
|
|
46
|
-
// of using the `on('get')` handlers.
|
|
47
|
-
//
|
|
48
|
-
// Here we change update the brightness to a random value every 5 seconds using
|
|
49
|
-
// the `updateCharacteristic` method.
|
|
50
|
-
setInterval(() => {
|
|
51
|
-
// assign the current brightness a random value between 0 and 100
|
|
52
|
-
const currentBrightness = Math.floor(Math.random() * 100);
|
|
53
|
-
// push the new value to HomeKit
|
|
54
|
-
this.service.updateCharacteristic(this.platform.Characteristic.Brightness, currentBrightness);
|
|
55
|
-
this.platform.log.debug("Pushed updated current Brightness state to HomeKit:", currentBrightness);
|
|
56
|
-
}, 10000);
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Handle "SET" requests from HomeKit
|
|
60
|
-
* These are sent when the user changes the state of an accessory, for example, turning on a Light bulb.
|
|
61
|
-
*/
|
|
62
|
-
setOn(value, callback) {
|
|
63
|
-
// implement your own code to turn your device on/off
|
|
64
|
-
this.exampleStates.On = value;
|
|
65
|
-
this.platform.log.debug("Set Characteristic On ->", value);
|
|
66
|
-
// you must call the callback function
|
|
67
|
-
callback(null);
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Handle the "GET" requests from HomeKit
|
|
71
|
-
* These are sent when HomeKit wants to know the current state of the accessory, for example, checking if a Light bulb is on.
|
|
72
|
-
*
|
|
73
|
-
* GET requests should return as fast as possbile. A long delay here will result in
|
|
74
|
-
* HomeKit being unresponsive and a bad user experience in general.
|
|
75
|
-
*
|
|
76
|
-
* If your device takes time to respond you should update the status of your device
|
|
77
|
-
* asynchronously instead using the `updateCharacteristic` method instead.
|
|
78
|
-
|
|
79
|
-
* @example
|
|
80
|
-
* this.service.updateCharacteristic(this.platform.Characteristic.On, true)
|
|
81
|
-
*/
|
|
82
|
-
getOn(callback) {
|
|
83
|
-
// implement your own code to check if the device is on
|
|
84
|
-
const isOn = this.exampleStates.On;
|
|
85
|
-
this.platform.log.debug("Get Characteristic On ->", isOn);
|
|
86
|
-
// you must call the callback function
|
|
87
|
-
// the first argument should be null if there were no errors
|
|
88
|
-
// the second argument should be the value to return
|
|
89
|
-
callback(null, isOn);
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Handle "SET" requests from HomeKit
|
|
93
|
-
* These are sent when the user changes the state of an accessory, for example, changing the Brightness
|
|
94
|
-
*/
|
|
95
|
-
setBrightness(value, callback) {
|
|
96
|
-
// implement your own code to set the brightness
|
|
97
|
-
this.exampleStates.Brightness = value;
|
|
98
|
-
this.platform.log.debug("Set Characteristic Brightness -> ", value);
|
|
99
|
-
// you must call the callback function
|
|
100
|
-
callback(null);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
exports.ExamplePlatformAccessory = ExamplePlatformAccessory;
|
|
104
|
-
//# sourceMappingURL=platformAccessory.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"platformAccessory.js","sourceRoot":"","sources":["../src/platformAccessory.ts"],"names":[],"mappings":"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"}
|