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.
@@ -1,28 +1,38 @@
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 {
1
+ import { RATGDO_MOTION_DURATION, RATGDO_OCCUPANCY_DURATION, RATGDO_TRANSITION_DURATION } from "./settings.js";
2
+ import { RatgdoReservedNames } from "./ratgdo-types.js";
3
+ import { getOptionFloat, getOptionNumber, getOptionValue, isOptionEnabled } from "./ratgdo-options.js";
4
+ import util from "node:util";
5
+ export class RatgdoAccessory {
6
+ accessory;
7
+ api;
8
+ config;
9
+ device;
10
+ doorOccupancyTimer;
11
+ doorTimer;
12
+ hap;
13
+ hints;
14
+ log;
15
+ motionOccupancyTimer;
16
+ motionTimer;
17
+ obstructionTimer;
18
+ platform;
19
+ status;
11
20
  // The constructor initializes key variables and calls configureDevice().
12
21
  constructor(platform, accessory, device) {
13
22
  this.accessory = accessory;
14
23
  this.api = platform.api;
15
24
  this.status = {};
16
25
  this.config = platform.config;
26
+ this.doorTimer = null;
17
27
  this.hap = this.api.hap;
18
28
  this.hints = {};
19
29
  this.device = device;
20
30
  this.platform = platform;
21
31
  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))
32
+ debug: (message, ...parameters) => platform.debug(util.format(this.name + ": " + message, ...parameters)),
33
+ error: (message, ...parameters) => platform.log.error(util.format(this.name + ": " + message, ...parameters)),
34
+ info: (message, ...parameters) => platform.log.info(util.format(this.name + ": " + message, ...parameters)),
35
+ warn: (message, ...parameters) => platform.log.warn(util.format(this.name + ": " + message, ...parameters))
26
36
  };
27
37
  // Initialize our internal state.
28
38
  this.status.availability = false;
@@ -31,9 +41,10 @@ class ratgdoAccessory {
31
41
  this.status.lock = this.hap.Characteristic.LockCurrentState.UNSECURED;
32
42
  this.status.motion = false;
33
43
  this.status.obstruction = false;
44
+ this.doorOccupancyTimer = null;
45
+ this.motionOccupancyTimer = null;
34
46
  this.motionTimer = null;
35
47
  this.obstructionTimer = null;
36
- this.occupancyTimer = null;
37
48
  this.configureDevice();
38
49
  }
39
50
  // Configure a garage door accessory for HomeKit.
@@ -44,40 +55,102 @@ class ratgdoAccessory {
44
55
  this.configureHints();
45
56
  this.configureInfo();
46
57
  this.configureGarageDoor();
58
+ this.configureMqtt();
59
+ this.configureAutomationSwitch();
60
+ this.configureDoorOpenOccupancySensor();
47
61
  this.configureLight();
48
62
  this.configureMotionSensor();
49
- // this.configureSwitch();
50
- // this.configureOccupancySensor();
63
+ this.configureMotionOccupancySensor();
51
64
  }
52
65
  // Configure device-specific settings.
53
66
  configureHints() {
54
67
  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;
68
+ this.hints.doorOpenOccupancySensor = this.hasFeature("Opener.OccupancySensor");
69
+ this.hints.doorOpenOccupancyDuration = this.getFeatureNumber("Opener.OccupancySensor.Duration") ?? RATGDO_OCCUPANCY_DURATION;
70
+ this.hints.light = this.hasFeature("Light");
71
+ this.hints.motionOccupancySensor = this.hasFeature("Motion.OccupancySensor");
72
+ this.hints.motionOccupancyDuration = this.getFeatureNumber("Motion.OccupancySensor.Duration") ?? RATGDO_OCCUPANCY_DURATION;
73
+ this.hints.motionSensor = this.hasFeature("Motion");
57
74
  this.hints.readOnly = this.hasFeature("Opener.ReadOnly");
58
- this.hints.syncNames = this.hasFeature("Device.SyncNames");
75
+ this.hints.syncName = this.hasFeature("Device.SyncName");
59
76
  return true;
60
77
  }
61
78
  // Configure the device information for HomeKit.
62
79
  configureInfo() {
63
- var _a, _b, _c, _d;
64
80
  // 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");
81
+ this.accessory.getService(this.hap.Service.AccessoryInformation)?.updateCharacteristic(this.hap.Characteristic.Manufacturer, "github.com/hjdhjd");
66
82
  // 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");
83
+ this.accessory.getService(this.hap.Service.AccessoryInformation)?.updateCharacteristic(this.hap.Characteristic.Model, "Ratgdo");
68
84
  // 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);
85
+ this.accessory.getService(this.hap.Service.AccessoryInformation)?.updateCharacteristic(this.hap.Characteristic.SerialNumber, this.device.mac);
70
86
  // 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);
87
+ this.accessory.getService(this.hap.Service.AccessoryInformation)?.updateCharacteristic(this.hap.Characteristic.FirmwareRevision, this.device.firmwareVersion);
88
+ return true;
89
+ }
90
+ // Configure MQTT services.
91
+ configureMqtt() {
92
+ // Return our garage door state.
93
+ this.platform.mqtt?.subscribeGet(this, "garagedoor", "Garage Door", () => {
94
+ // Return our current status using our HomeKit current state decoder ring.
95
+ return this.translateCurrentDoorState(this.status.door);
96
+ });
97
+ // Set our garage door state.
98
+ this.platform.mqtt?.subscribeSet(this, "garagedoor", "Garage Door", (value) => {
99
+ let command;
100
+ switch (value) {
101
+ case "close":
102
+ command = this.hap.Characteristic.TargetDoorState.CLOSED;
103
+ break;
104
+ case "open":
105
+ command = this.hap.Characteristic.TargetDoorState.OPEN;
106
+ break;
107
+ default:
108
+ this.log.error("Invalid command.");
109
+ return;
110
+ break;
111
+ }
112
+ // Set our door state accordingly.
113
+ this.setDoorState(command);
114
+ });
115
+ // Return our obstruction state.
116
+ this.platform.mqtt?.subscribeGet(this, "obstruction", "Obstruction", () => {
117
+ return this.status.obstruction.toString();
118
+ });
119
+ // Return our door open occupancy state if configured to do so.
120
+ if (this.hints.doorOpenOccupancySensor) {
121
+ this.platform.mqtt?.subscribeGet(this, "dooropenoccupancy", "Door Open Indicator Occupancy", () => {
122
+ return (this.accessory.getServiceById(this.hap.Service.OccupancySensor, RatgdoReservedNames.OCCUPANCY_SENSOR_DOOR_OPEN)
123
+ ?.getCharacteristic(this.hap.Characteristic.OccupancyDetected).value ?? "false").toString();
124
+ });
125
+ }
126
+ // Return our light state if configured to do so.
127
+ if (this.hints.light) {
128
+ this.platform.mqtt?.subscribeGet(this, "light", "Light", () => {
129
+ return this.status.light.toString();
130
+ });
131
+ }
132
+ // Return our motion occupancy state if configured to do so.
133
+ if (this.hints.motionOccupancySensor) {
134
+ this.platform.mqtt?.subscribeGet(this, "occupancy", "Occupancy", () => {
135
+ return (this.accessory.getServiceById(this.hap.Service.OccupancySensor, RatgdoReservedNames.OCCUPANCY_SENSOR_MOTION)
136
+ ?.getCharacteristic(this.hap.Characteristic.OccupancyDetected).value ?? "false").toString();
137
+ });
138
+ }
139
+ // Return our motion state if configured to do so.
140
+ if (this.hints.motionSensor) {
141
+ this.platform.mqtt?.subscribeGet(this, "motion", "Motion", () => {
142
+ return this.status.motion.toString();
143
+ });
144
+ }
72
145
  return true;
73
146
  }
74
147
  // Configure the garage door service for HomeKit.
75
148
  configureGarageDoor() {
76
- var _a;
77
149
  let garageDoorService = this.accessory.getService(this.hap.Service.GarageDoorOpener);
78
150
  // Add the garage door opener service to the accessory, if needed.
79
151
  if (!garageDoorService) {
80
152
  garageDoorService = new this.hap.Service.GarageDoorOpener(this.name);
153
+ garageDoorService.addOptionalCharacteristic(this.hap.Characteristic.ConfiguredName);
81
154
  this.accessory.addService(garageDoorService);
82
155
  }
83
156
  // Set the initial current and target door states to closed since ratgdo doesn't tell us initial state over MQTT on startup.
@@ -91,23 +164,30 @@ class ratgdoAccessory {
91
164
  garageDoorService.getCharacteristic(this.hap.Characteristic.CurrentDoorState).onGet(() => this.status.door);
92
165
  // Inform HomeKit of any obstructions.
93
166
  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);
167
+ // Configure the lock garage door lock current and target state characteristics.
97
168
  garageDoorService.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.status.lock);
98
169
  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
170
  // 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");
171
+ if (this.hints.syncName) {
172
+ this.setServiceName(garageDoorService, this.device.name);
173
+ if (this.hints.automationSwitch) {
174
+ this.setServiceName(this.accessory.getServiceById(this.hap.Service.Switch, RatgdoReservedNames.SWITCH_OPENER_AUTOMATION), this.device.name + " Automation Switch");
175
+ }
176
+ if (this.hints.doorOpenOccupancySensor) {
177
+ this.setServiceName(this.accessory.getServiceById(this.hap.Service.OccupancySensor, RatgdoReservedNames.OCCUPANCY_SENSOR_DOOR_OPEN), this.device.name + " Open");
107
178
  }
179
+ if (this.hints.light) {
180
+ this.setServiceName(this.accessory.getService(this.hap.Service.Lightbulb), this.device.name);
181
+ }
182
+ if (this.hints.motionSensor) {
183
+ this.setServiceName(this.accessory.getService(this.hap.Service.MotionSensor), this.device.name);
184
+ }
185
+ if (this.hints.motionOccupancySensor) {
186
+ this.setServiceName(this.accessory.getServiceById(this.hap.Service.OccupancySensor, RatgdoReservedNames.OCCUPANCY_SENSOR_MOTION), this.device.name);
187
+ }
188
+ // Finally, update the accessory name.
189
+ this.accessoryName = this.device.name;
108
190
  }
109
- // Add our status active characteristic.
110
- garageDoorService.addOptionalCharacteristic(this.hap.Characteristic.StatusActive);
111
191
  garageDoorService.getCharacteristic(this.hap.Characteristic.StatusActive).onGet(() => this.status.availability);
112
192
  garageDoorService.updateCharacteristic(this.hap.Characteristic.StatusActive, this.status.availability);
113
193
  // Let HomeKit know that this is the primary service on this accessory.
@@ -116,9 +196,16 @@ class ratgdoAccessory {
116
196
  }
117
197
  // Configure the light for HomeKit.
118
198
  configureLight() {
119
- var _a, _b;
120
199
  // Find the service, if it exists.
121
200
  let lightService = this.accessory.getService(this.hap.Service.Lightbulb);
201
+ // Have we disabled the light?
202
+ if (!this.hints.light) {
203
+ if (lightService) {
204
+ this.accessory.removeService(lightService);
205
+ this.log.info("Disabling light.");
206
+ }
207
+ return false;
208
+ }
122
209
  // Add the service to the accessory, if needed.
123
210
  if (!lightService) {
124
211
  lightService = new this.hap.Service.Lightbulb(this.name);
@@ -126,24 +213,34 @@ class ratgdoAccessory {
126
213
  this.log.error("Unable to add the light.");
127
214
  return false;
128
215
  }
216
+ lightService.addOptionalCharacteristic(this.hap.Characteristic.ConfiguredName);
129
217
  this.accessory.addService(lightService);
130
218
  this.log.info("Enabling light.");
131
219
  }
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
220
  // Initialize the light.
138
221
  lightService.displayName = this.name;
139
222
  lightService.updateCharacteristic(this.hap.Characteristic.Name, this.name);
223
+ lightService.updateCharacteristic(this.hap.Characteristic.ConfiguredName, this.name);
140
224
  lightService.updateCharacteristic(this.hap.Characteristic.On, this.status.light);
225
+ // Turn the light on or off.
226
+ lightService.getCharacteristic(this.hap.Characteristic.On)?.onGet(() => this.status.light);
227
+ lightService.getCharacteristic(this.hap.Characteristic.On)?.onSet((value) => {
228
+ this.command("light", value === true ? "on" : "off");
229
+ });
141
230
  return true;
142
231
  }
143
232
  // Configure the motion sensor for HomeKit.
144
233
  configureMotionSensor() {
145
234
  // Find the motion sensor service, if it exists.
146
235
  let motionService = this.accessory.getService(this.hap.Service.MotionSensor);
236
+ // Have we disabled the motion sensor?
237
+ if (!this.hints.motionSensor) {
238
+ if (motionService) {
239
+ this.accessory.removeService(motionService);
240
+ this.log.info("Disabling motion sensor.");
241
+ }
242
+ return false;
243
+ }
147
244
  // We don't have a motion sensor, let's add it to the device.
148
245
  if (!motionService) {
149
246
  // We don't have it, add the motion sensor to the device.
@@ -152,17 +249,132 @@ class ratgdoAccessory {
152
249
  this.log.error("Unable to add the motion sensor.");
153
250
  return false;
154
251
  }
252
+ motionService.addOptionalCharacteristic(this.hap.Characteristic.ConfiguredName);
155
253
  this.accessory.addService(motionService);
156
254
  this.log.info("Enabling motion sensor.");
157
255
  }
158
256
  // Initialize the state of the motion sensor.
159
257
  motionService.displayName = this.name;
160
258
  motionService.updateCharacteristic(this.hap.Characteristic.Name, this.name);
259
+ motionService.updateCharacteristic(this.hap.Characteristic.ConfiguredName, this.name);
161
260
  motionService.updateCharacteristic(this.hap.Characteristic.MotionDetected, false);
162
261
  motionService.updateCharacteristic(this.hap.Characteristic.StatusActive, this.status.availability);
163
262
  motionService.getCharacteristic(this.hap.Characteristic.StatusActive).onGet(() => this.status.availability);
164
263
  return true;
165
264
  }
265
+ // Configure a switch to automate open and close events in HomeKit beyond what HomeKit might allow for a garage opener service that gets treated as a secure service.
266
+ configureAutomationSwitch() {
267
+ // Find the switch service, if it exists.
268
+ let switchService = this.accessory.getServiceById(this.hap.Service.Switch, RatgdoReservedNames.SWITCH_OPENER_AUTOMATION);
269
+ // The switch is disabled by default and primarily exists for automation purposes.
270
+ if (!this.hints.automationSwitch) {
271
+ if (switchService) {
272
+ this.accessory.removeService(switchService);
273
+ this.log.info("Disabling automation switch.");
274
+ }
275
+ return false;
276
+ }
277
+ // Add the switch to the opener, if needed.
278
+ if (!switchService) {
279
+ switchService = new this.hap.Service.Switch(this.name + " Automation Switch", RatgdoReservedNames.SWITCH_OPENER_AUTOMATION);
280
+ if (!switchService) {
281
+ this.log.error("Unable to add automation switch.");
282
+ return false;
283
+ }
284
+ switchService.addOptionalCharacteristic(this.hap.Characteristic.ConfiguredName);
285
+ this.accessory.addService(switchService);
286
+ }
287
+ // Return the current state of the opener.
288
+ switchService.getCharacteristic(this.hap.Characteristic.On)?.onGet(() => {
289
+ // We're on if we are in any state other than closed (specifically open or stopped).
290
+ return this.doorCurrentStateBias(this.status.door) !== this.hap.Characteristic.CurrentDoorState.CLOSED;
291
+ });
292
+ // Open or close the opener.
293
+ switchService.getCharacteristic(this.hap.Characteristic.On)?.onSet((value) => {
294
+ // Inform the user.
295
+ this.log.info("Automation switch: %s.", value ? "open" : "close");
296
+ // Send the command.
297
+ if (!this.setDoorState(value ? this.hap.Characteristic.TargetDoorState.OPEN : this.hap.Characteristic.TargetDoorState.CLOSED)) {
298
+ // Something went wrong. Let's make sure we revert the switch to it's prior state.
299
+ setTimeout(() => {
300
+ switchService?.updateCharacteristic(this.hap.Characteristic.On, !value);
301
+ }, 50);
302
+ }
303
+ });
304
+ // Initialize the switch.
305
+ switchService.updateCharacteristic(this.hap.Characteristic.ConfiguredName, this.name + " Automation Switch");
306
+ switchService.updateCharacteristic(this.hap.Characteristic.On, this.doorCurrentStateBias(this.status.door) !== this.hap.Characteristic.CurrentDoorState.CLOSED);
307
+ this.log.info("Enabling automation switch.");
308
+ return true;
309
+ }
310
+ // Configure the door open occupancy sensor for HomeKit.
311
+ configureDoorOpenOccupancySensor() {
312
+ // Find the occupancy sensor service, if it exists.
313
+ let occupancyService = this.accessory.getServiceById(this.hap.Service.OccupancySensor, RatgdoReservedNames.OCCUPANCY_SENSOR_DOOR_OPEN);
314
+ // The occupancy sensor is disabled by default and primarily exists for automation purposes.
315
+ if (!this.hints.doorOpenOccupancySensor) {
316
+ if (occupancyService) {
317
+ this.accessory.removeService(occupancyService);
318
+ this.log.info("Disabling door open indicator occupancy sensor.");
319
+ }
320
+ return false;
321
+ }
322
+ // We don't have an occupancy sensor, let's add it to the device.
323
+ if (!occupancyService) {
324
+ // We don't have it, add the occupancy sensor to the device.
325
+ occupancyService = new this.hap.Service.OccupancySensor(this.name + " Open", RatgdoReservedNames.OCCUPANCY_SENSOR_DOOR_OPEN);
326
+ if (!occupancyService) {
327
+ this.log.error("Unable to add door open occupancy sensor.");
328
+ return false;
329
+ }
330
+ occupancyService.addOptionalCharacteristic(this.hap.Characteristic.ConfiguredName);
331
+ this.accessory.addService(occupancyService);
332
+ }
333
+ // Ensure we can configure the name of the occupancy sensor.
334
+ occupancyService.updateCharacteristic(this.hap.Characteristic.ConfiguredName, this.name + " Open");
335
+ // Initialize the state of the occupancy sensor.
336
+ occupancyService.updateCharacteristic(this.hap.Characteristic.OccupancyDetected, false);
337
+ occupancyService.updateCharacteristic(this.hap.Characteristic.StatusActive, this.status.availability);
338
+ occupancyService.getCharacteristic(this.hap.Characteristic.StatusActive).onGet(() => {
339
+ return this.status.availability;
340
+ });
341
+ this.log.info("Enabling door open indicator occupancy sensor. Occupancy will be triggered when the opener has been continuously open for more than %s seconds.", this.hints.doorOpenOccupancyDuration);
342
+ return true;
343
+ }
344
+ // Configure the motion occupancy sensor for HomeKit.
345
+ configureMotionOccupancySensor() {
346
+ // Find the occupancy sensor service, if it exists.
347
+ let occupancyService = this.accessory.getServiceById(this.hap.Service.OccupancySensor, RatgdoReservedNames.OCCUPANCY_SENSOR_MOTION);
348
+ // The occupancy sensor is disabled by default and primarily exists for automation purposes.
349
+ if (!this.hints.motionOccupancySensor) {
350
+ if (occupancyService) {
351
+ this.accessory.removeService(occupancyService);
352
+ this.log.info("Disabling occupancy sensor.");
353
+ }
354
+ return false;
355
+ }
356
+ // We don't have an occupancy sensor, let's add it to the device.
357
+ if (!occupancyService) {
358
+ // We don't have it, add the occupancy sensor to the device.
359
+ occupancyService = new this.hap.Service.OccupancySensor(this.name, RatgdoReservedNames.OCCUPANCY_SENSOR_MOTION);
360
+ if (!occupancyService) {
361
+ this.log.error("Unable to add occupancy sensor.");
362
+ return false;
363
+ }
364
+ occupancyService.addOptionalCharacteristic(this.hap.Characteristic.ConfiguredName);
365
+ this.accessory.addService(occupancyService);
366
+ }
367
+ // Ensure we can configure the name of the occupancy sensor.
368
+ occupancyService.updateCharacteristic(this.hap.Characteristic.ConfiguredName, this.name);
369
+ // Initialize the state of the occupancy sensor.
370
+ occupancyService.updateCharacteristic(this.hap.Characteristic.OccupancyDetected, false);
371
+ occupancyService.updateCharacteristic(this.hap.Characteristic.StatusActive, this.status.availability);
372
+ occupancyService.getCharacteristic(this.hap.Characteristic.StatusActive).onGet(() => {
373
+ return this.status.availability;
374
+ });
375
+ this.log.info("Enabling occupancy sensor. Occupancy event duration set to %s seconds.", this.hints.motionOccupancyDuration);
376
+ return true;
377
+ }
166
378
  // Open or close the garage door.
167
379
  setDoorState(value) {
168
380
  const actionExisting = this.status.door === this.hap.Characteristic.CurrentDoorState.OPENING ? "opening" : "closing";
@@ -172,15 +384,14 @@ class ratgdoAccessory {
172
384
  this.log.info("Unable to %s door. The door has been configured to be read only.", actionAttempt);
173
385
  // 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
386
  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);
387
+ this.accessory.getService(this.hap.Service.GarageDoorOpener)?.updateCharacteristic(this.hap.Characteristic.TargetDoorState, value === this.hap.Characteristic.TargetDoorState.CLOSED ? this.hap.Characteristic.TargetDoorState.OPEN : this.hap.Characteristic.TargetDoorState.CLOSED);
177
388
  });
178
389
  return false;
179
390
  }
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.
391
+ // If we are already opening or closing the garage door, we error out. As a precaution, we ensure we complete the current action before allowing a new one.
392
+ // This behavior may change in the future, but for now, we manage this edge case by eliminating the possibility of doing so.
182
393
  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);
394
+ this.log.error("Unable to %s door while currently attempting to complete %s. The existing action must be allowed to complete before attempting a new one.", actionAttempt, actionExisting);
184
395
  return false;
185
396
  }
186
397
  // Close the garage door.
@@ -188,7 +399,7 @@ class ratgdoAccessory {
188
399
  // HomeKit is asking us to close the garage door, but let's make sure it's not already closed first.
189
400
  if (this.status.door !== this.hap.Characteristic.CurrentDoorState.CLOSED) {
190
401
  // Execute the command.
191
- this.platform.broker.publish({ cmd: "publish", dup: false, payload: "close", qos: 0, retain: false, topic: this.device.name + "/command/door" }, () => { });
402
+ this.command("door", "close");
192
403
  }
193
404
  return true;
194
405
  }
@@ -197,7 +408,7 @@ class ratgdoAccessory {
197
408
  // HomeKit is informing us to open the door, but we don't want to act if it's already open.
198
409
  if (this.status.door !== this.hap.Characteristic.CurrentDoorState.OPEN) {
199
410
  // Execute the command.
200
- this.platform.broker.publish({ cmd: "publish", dup: false, payload: "open", qos: 0, retain: false, topic: this.device.name + "/command/door" }, () => { });
411
+ this.command("door", "open");
201
412
  }
202
413
  return true;
203
414
  }
@@ -207,63 +418,129 @@ class ratgdoAccessory {
207
418
  }
208
419
  // Update the state of the accessory.
209
420
  updateState(event, payload) {
210
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
211
- let currentState, targetState;
212
421
  const camelCase = (text) => text.charAt(0).toUpperCase() + text.slice(1);
422
+ const doorOccupancyService = this.accessory.getServiceById(this.hap.Service.OccupancySensor, RatgdoReservedNames.OCCUPANCY_SENSOR_DOOR_OPEN);
423
+ const garageDoorService = this.accessory.getService(this.hap.Service.GarageDoorOpener);
424
+ const lightBulbService = this.accessory.getService(this.hap.Service.Lightbulb);
425
+ const motionOccupancyService = this.accessory.getServiceById(this.hap.Service.OccupancySensor, RatgdoReservedNames.OCCUPANCY_SENSOR_MOTION);
426
+ const motionService = this.accessory.getService(this.hap.Service.MotionSensor);
427
+ const switchService = this.accessory.getServiceById(this.hap.Service.Switch, RatgdoReservedNames.SWITCH_OPENER_AUTOMATION);
213
428
  switch (event) {
214
429
  case "availability":
215
430
  this.status.availability = payload === "online";
216
431
  // 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);
432
+ garageDoorService?.updateCharacteristic(this.hap.Characteristic.StatusActive, this.status.availability);
433
+ doorOccupancyService?.updateCharacteristic(this.hap.Characteristic.StatusActive, this.status.availability);
434
+ motionOccupancyService?.updateCharacteristic(this.hap.Characteristic.StatusActive, this.status.availability);
435
+ motionService?.updateCharacteristic(this.hap.Characteristic.StatusActive, this.status.availability);
219
436
  // Inform the user:
220
437
  this.log.info("Device %s.", this.status.availability ? "connected" : "disconnected");
221
438
  break;
222
439
  case "door":
440
+ // If we're already in the state we're updating to, we're done.
441
+ if (this.translateCurrentDoorState(this.status.door) === payload) {
442
+ break;
443
+ }
444
+ // Clear out our door transition timer, if we have one.
445
+ if (this.doorTimer) {
446
+ clearTimeout(this.doorTimer);
447
+ this.doorTimer = null;
448
+ }
223
449
  switch (payload) {
224
450
  case "closed":
225
- currentState = this.hap.Characteristic.CurrentDoorState.CLOSED;
451
+ this.status.door = this.hap.Characteristic.CurrentDoorState.CLOSED;
226
452
  break;
227
453
  case "closing":
228
- currentState = this.hap.Characteristic.CurrentDoorState.CLOSING;
454
+ this.status.door = this.hap.Characteristic.CurrentDoorState.CLOSING;
455
+ // As a safety measure for occasionally unreliable MQTT message delivery, let's ensure we generate a closed state after a reasonable transition period. If we
456
+ // receive an actual state update before this, this safety measure won't be triggered.
457
+ this.doorTimer = setTimeout(() => {
458
+ // Mark the door as closed.
459
+ this.log.debug("Generating a close event to complete the state transition.");
460
+ this.updateState("door", "closed");
461
+ this.doorTimer = null;
462
+ }, RATGDO_TRANSITION_DURATION * 1000);
229
463
  break;
230
464
  case "open":
231
- currentState = this.hap.Characteristic.CurrentDoorState.OPEN;
465
+ this.status.door = this.hap.Characteristic.CurrentDoorState.OPEN;
466
+ // Trigger our occupancy timer, if configured to do so and we don't have one yet.
467
+ if (this.hints.doorOpenOccupancySensor && !this.doorOccupancyTimer) {
468
+ this.doorOccupancyTimer = setTimeout(() => {
469
+ doorOccupancyService?.updateCharacteristic(this.hap.Characteristic.OccupancyDetected, true);
470
+ this.log.info("Garage door open occupancy detected.");
471
+ // Publish to MQTT, if the user has configured it.
472
+ this.platform.mqtt?.publish(this, "dooropenoccupancy", "true");
473
+ }, this.hints.doorOpenOccupancyDuration * 1000);
474
+ }
232
475
  break;
233
476
  case "opening":
234
- currentState = this.hap.Characteristic.CurrentDoorState.OPENING;
477
+ this.status.door = this.hap.Characteristic.CurrentDoorState.OPENING;
478
+ // As a safety measure for occasionally unreliable MQTT message delivery, let's ensure we generate an open state after a reasonable transition period. If we
479
+ // receive an actual state update before this, this safety measure won't be triggered.
480
+ this.doorTimer = setTimeout(() => {
481
+ // Mark the door as open.
482
+ this.log.debug("Generating an open event to complete the state transition.");
483
+ this.updateState("door", "open");
484
+ this.doorTimer = null;
485
+ }, RATGDO_TRANSITION_DURATION * 1000);
235
486
  break;
236
487
  case "stopped":
237
- currentState = this.hap.Characteristic.CurrentDoorState.STOPPED;
488
+ this.status.door = this.hap.Characteristic.CurrentDoorState.STOPPED;
238
489
  break;
239
490
  default:
240
- currentState = this.hap.Characteristic.CurrentDoorState.CLOSED;
491
+ this.status.door = this.hap.Characteristic.CurrentDoorState.CLOSED;
241
492
  break;
242
493
  }
243
494
  // 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
495
  // 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));
496
+ if (this.status.door !== this.hap.Characteristic.CurrentDoorState.STOPPED) {
497
+ garageDoorService?.updateCharacteristic(this.hap.Characteristic.TargetDoorState, this.doorTargetStateBias(this.status.door));
247
498
  }
248
- (_d = this.accessory.getService(this.hap.Service.GarageDoorOpener)) === null || _d === void 0 ? void 0 : _d.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, currentState);
499
+ garageDoorService?.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, this.status.door);
500
+ // Update our automation switch, if configured.
501
+ switchService?.updateCharacteristic(this.hap.Characteristic.On, this.doorTargetStateBias(this.status.door) === this.hap.Characteristic.TargetDoorState.OPEN);
249
502
  // Inform the user:
250
503
  this.log.info("%s.", camelCase(payload));
504
+ // If we have an open occupancy sensor configured and our door state is anything other than open, clear our occupancy state.
505
+ if (this.hints.doorOpenOccupancySensor && this.doorOccupancyTimer && (payload !== "open")) {
506
+ clearTimeout(this.doorOccupancyTimer);
507
+ this.doorOccupancyTimer = null;
508
+ if (doorOccupancyService?.getCharacteristic(this.hap.Characteristic.OccupancyDetected).value) {
509
+ doorOccupancyService?.updateCharacteristic(this.hap.Characteristic.OccupancyDetected, false);
510
+ this.log.info("Garage door open occupancy no longer detected.");
511
+ // Publish to MQTT, if the user has configured it.
512
+ this.platform.mqtt?.publish(this, "dooropenoccupancy", "false");
513
+ }
514
+ }
515
+ // Publish to MQTT, if the user has configured it.
516
+ this.platform.mqtt?.publish(this, "garagedoor", payload);
251
517
  break;
252
518
  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);
519
+ // Only act if we're not already at the state we're updating to.
520
+ if (this.status.light !== (payload === "on")) {
521
+ this.status.light = payload === "on";
522
+ lightBulbService?.updateCharacteristic(this.hap.Characteristic.On, this.status.light);
523
+ // Inform the user:
524
+ this.log.info("Light %s.", payload);
525
+ // Publish to MQTT, if the user has configured it.
526
+ this.platform.mqtt?.publish(this, "light", this.status.light.toString());
527
+ }
257
528
  break;
258
529
  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;
530
+ // If we're already in the state we're updating to, we're done.
531
+ if (this.status.lock === (payload === "locked" ? this.hap.Characteristic.LockCurrentState.SECURED : this.hap.Characteristic.LockCurrentState.UNSECURED)) {
532
+ break;
533
+ }
534
+ // Determine our lock state.
535
+ this.status.lock = payload === "locked" ? this.hap.Characteristic.LockCurrentState.SECURED : this.hap.Characteristic.LockCurrentState.UNSECURED;
262
536
  // 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);
537
+ garageDoorService?.updateCharacteristic(this.hap.Characteristic.LockTargetState, payload === "locked" ?
538
+ this.hap.Characteristic.LockTargetState.SECURED : this.hap.Characteristic.LockTargetState.UNSECURED);
539
+ garageDoorService?.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.status.lock);
265
540
  // Inform the user:
266
541
  this.log.info("%s.", camelCase(payload));
542
+ // Publish to MQTT, if the user has configured it.
543
+ this.platform.mqtt?.publish(this, "lock", this.status.lock.toString());
267
544
  break;
268
545
  case "motion":
269
546
  this.status.motion = payload === "detected";
@@ -274,30 +551,92 @@ class ratgdoAccessory {
274
551
  break;
275
552
  }
276
553
  // 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.");
554
+ motionService?.updateCharacteristic(this.hap.Characteristic.MotionDetected, this.status.motion);
555
+ // 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
556
+ // cycle, let the user know.
557
+ if (this.motionTimer) {
558
+ clearTimeout(this.motionTimer);
559
+ }
560
+ else {
561
+ this.log.info("Motion detected.");
562
+ // Publish to MQTT, if the user has configured it.
563
+ this.platform.mqtt?.publish(this, "motion", this.status.motion.toString());
564
+ }
281
565
  // Set a timer for the motion event.
282
566
  this.motionTimer = setTimeout(() => {
283
- var _a;
284
567
  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);
568
+ motionService?.updateCharacteristic(this.hap.Characteristic.MotionDetected, this.status.motion);
569
+ // Publish to MQTT, if the user has configured it.
570
+ this.platform.mqtt?.publish(this, "motion", this.status.motion.toString());
571
+ }, RATGDO_MOTION_DURATION * 1000);
572
+ // Kill any inflight occupancy sensor.
573
+ if (this.motionOccupancyTimer) {
574
+ clearTimeout(this.motionOccupancyTimer);
575
+ this.motionOccupancyTimer = null;
576
+ }
577
+ // If the motion occupancy sensor isn't already triggered, let's do so now.
578
+ if (motionOccupancyService?.getCharacteristic(this.hap.Characteristic.OccupancyDetected).value !== true) {
579
+ // Trigger the occupancy event in HomeKit.
580
+ motionOccupancyService?.updateCharacteristic(this.hap.Characteristic.OccupancyDetected, true);
581
+ // Publish to MQTT, if the user has configured it.
582
+ this.platform.mqtt?.publish(this, "occupancy", "true");
583
+ // Log the event.
584
+ this.log.info("Occupancy detected.");
585
+ }
586
+ // Reset our occupancy state after occupancyDuration.
587
+ this.motionOccupancyTimer = setTimeout(() => {
588
+ // Reset the occupancy sensor.
589
+ motionOccupancyService?.updateCharacteristic(this.hap.Characteristic.OccupancyDetected, false);
590
+ // Publish to MQTT, if the user has configured it.
591
+ this.platform.mqtt?.publish(this, "occupancy", "false");
592
+ // Log the event.
593
+ this.log.info("Occupancy no longer detected.");
594
+ // Delete the timer.
595
+ this.motionOccupancyTimer = null;
596
+ }, this.hints.motionOccupancyDuration * 1000);
287
597
  break;
288
598
  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 ");
599
+ garageDoorService?.updateCharacteristic(this.hap.Characteristic.ObstructionDetected, payload === "obstructed");
600
+ // Only act if we're not already at the state we're updating to.
601
+ if (this.status.obstruction !== (payload === "obstructed")) {
602
+ this.status.obstruction = payload === "obstructed";
603
+ this.log.info("Obstruction %sdetected.", this.status.obstruction ? "" : "no longer ");
604
+ // Publish to MQTT, if the user has configured it.
605
+ this.platform.mqtt?.publish(this, "obstruction", this.status.obstruction.toString());
606
+ }
292
607
  break;
293
608
  case "default":
294
609
  break;
295
610
  }
296
611
  }
612
+ // Utility function to translate HomeKit's current door state values into human-readable form.
613
+ translateCurrentDoorState(value) {
614
+ // HomeKit state decoder ring.
615
+ switch (value) {
616
+ case this.hap.Characteristic.CurrentDoorState.CLOSED:
617
+ return "closed";
618
+ break;
619
+ case this.hap.Characteristic.CurrentDoorState.CLOSING:
620
+ return "closing";
621
+ break;
622
+ case this.hap.Characteristic.CurrentDoorState.OPEN:
623
+ return "open";
624
+ break;
625
+ case this.hap.Characteristic.CurrentDoorState.OPENING:
626
+ return "opening";
627
+ break;
628
+ case this.hap.Characteristic.CurrentDoorState.STOPPED:
629
+ return "stopped";
630
+ break;
631
+ default:
632
+ break;
633
+ }
634
+ return "unknown";
635
+ }
297
636
  // 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
637
  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.
638
+ // 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
639
+ // be less so. Our north star is that if we are in an obstructed state, we are open.
301
640
  if (this.status.obstruction) {
302
641
  return this.hap.Characteristic.CurrentDoorState.OPEN;
303
642
  }
@@ -318,9 +657,9 @@ class ratgdoAccessory {
318
657
  }
319
658
  // Utility function to return our bias for what the target door state should be.
320
659
  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.
660
+ // 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
661
+ // closing, our 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
662
+ // open, since that is the typical opener behavior, and it's impossible for us to know with reasonable certainty what the original intention of the action was.
324
663
  if (this.status.obstruction) {
325
664
  return this.hap.Characteristic.TargetDoorState.OPEN;
326
665
  }
@@ -351,24 +690,53 @@ class ratgdoAccessory {
351
690
  break;
352
691
  }
353
692
  }
693
+ // Utility function to transmit a command to Ratgdo.
694
+ command(topic, payload) {
695
+ this.platform.broker.publish({ cmd: "publish", dup: false, payload: payload, qos: 2, retain: false, topic: this.device.name + "/command/" + topic }, (error) => {
696
+ if (error) {
697
+ this.log.error("Publish error:");
698
+ this.log.error(util.inspect(error), { colors: true, depth: null, sorted: true });
699
+ }
700
+ });
701
+ }
354
702
  // Utility function to return a floating point configuration parameter on a device.
355
703
  getFeatureFloat(option) {
356
- return (0, ratgdo_options_js_1.getOptionFloat)((0, ratgdo_options_js_1.getOptionValue)(this.platform.configOptions, this.device, option));
704
+ return getOptionFloat(getOptionValue(this.platform.configOptions, this.device, option));
357
705
  }
358
706
  // Utility function to return an integer configuration parameter on a device.
359
707
  getFeatureNumber(option) {
360
- return (0, ratgdo_options_js_1.getOptionNumber)((0, ratgdo_options_js_1.getOptionValue)(this.platform.configOptions, this.device, option));
708
+ return getOptionNumber(getOptionValue(this.platform.configOptions, this.device, option));
361
709
  }
362
710
  // Utility for checking feature options on a device.
363
711
  hasFeature(option) {
364
- return (0, ratgdo_options_js_1.isOptionEnabled)(this.platform.configOptions, this.device, option, this.platform.featureOptionDefault(option));
712
+ return isOptionEnabled(this.platform.configOptions, this.device, option, this.platform.featureOptionDefault(option));
713
+ }
714
+ // Utility function to set the name of a service.
715
+ setServiceName(service, name) {
716
+ if (!service) {
717
+ return;
718
+ }
719
+ service.displayName = name;
720
+ service.updateCharacteristic(this.hap.Characteristic.ConfiguredName, name);
365
721
  }
366
- // Name utility function.
722
+ // Utility function to return the name of this device.
367
723
  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;
724
+ // We use the garage door service as the natural proxy for the name.
725
+ const configuredName = this.accessory.getService(this.hap.Service.GarageDoorOpener)?.getCharacteristic(this.hap.Characteristic.ConfiguredName).value;
726
+ // If we don't have a name for the garage door service, return the device name from Ratgdo.
727
+ return configuredName?.length ? configuredName : this.device.name;
728
+ }
729
+ // Utility function to return the current accessory name of this device.
730
+ get accessoryName() {
731
+ return this.accessory.getService(this.hap.Service.AccessoryInformation)?.getCharacteristic(this.hap.Characteristic.Name).value ?? this.device.name;
732
+ }
733
+ // Utility function to set the current accessory name of this device.
734
+ set accessoryName(name) {
735
+ // Set all the internally managed names within Homebridge to the new accessory name.
736
+ this.accessory.displayName = name;
737
+ this.accessory._associatedHAPAccessory.displayName = name;
738
+ // Set all the HomeKit-visible names.
739
+ this.accessory.getService(this.hap.Service.AccessoryInformation)?.updateCharacteristic(this.hap.Characteristic.Name, name);
371
740
  }
372
741
  }
373
- exports.ratgdoAccessory = ratgdoAccessory;
374
742
  //# sourceMappingURL=ratgdo-device.js.map