@mp-consulting/homebridge-unifi-access 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.
Files changed (74) hide show
  1. package/.claude/settings.local.json +91 -0
  2. package/CHANGELOG.md +13 -0
  3. package/LICENSE.md +22 -0
  4. package/README.md +159 -0
  5. package/config.schema.json +202 -0
  6. package/dist/access-controller.d.ts +41 -0
  7. package/dist/access-controller.js +342 -0
  8. package/dist/access-controller.js.map +1 -0
  9. package/dist/access-device-catalog.d.ts +43 -0
  10. package/dist/access-device-catalog.js +151 -0
  11. package/dist/access-device-catalog.js.map +1 -0
  12. package/dist/access-device.d.ts +68 -0
  13. package/dist/access-device.js +330 -0
  14. package/dist/access-device.js.map +1 -0
  15. package/dist/access-events.d.ts +27 -0
  16. package/dist/access-events.js +152 -0
  17. package/dist/access-events.js.map +1 -0
  18. package/dist/access-options.d.ts +32 -0
  19. package/dist/access-options.js +65 -0
  20. package/dist/access-options.js.map +1 -0
  21. package/dist/access-platform.d.ts +15 -0
  22. package/dist/access-platform.js +74 -0
  23. package/dist/access-platform.js.map +1 -0
  24. package/dist/access-types.d.ts +30 -0
  25. package/dist/access-types.js +42 -0
  26. package/dist/access-types.js.map +1 -0
  27. package/dist/hub/access-hub-api.d.ts +13 -0
  28. package/dist/hub/access-hub-api.js +140 -0
  29. package/dist/hub/access-hub-api.js.map +1 -0
  30. package/dist/hub/access-hub-events.d.ts +2 -0
  31. package/dist/hub/access-hub-events.js +229 -0
  32. package/dist/hub/access-hub-events.js.map +1 -0
  33. package/dist/hub/access-hub-mqtt.d.ts +2 -0
  34. package/dist/hub/access-hub-mqtt.js +137 -0
  35. package/dist/hub/access-hub-mqtt.js.map +1 -0
  36. package/dist/hub/access-hub-services.d.ts +4 -0
  37. package/dist/hub/access-hub-services.js +451 -0
  38. package/dist/hub/access-hub-services.js.map +1 -0
  39. package/dist/hub/access-hub-types.d.ts +145 -0
  40. package/dist/hub/access-hub-types.js +35 -0
  41. package/dist/hub/access-hub-types.js.map +1 -0
  42. package/dist/hub/access-hub-utils.d.ts +20 -0
  43. package/dist/hub/access-hub-utils.js +128 -0
  44. package/dist/hub/access-hub-utils.js.map +1 -0
  45. package/dist/hub/access-hub.d.ts +39 -0
  46. package/dist/hub/access-hub.js +185 -0
  47. package/dist/hub/access-hub.js.map +1 -0
  48. package/dist/hub/index.d.ts +4 -0
  49. package/dist/hub/index.js +7 -0
  50. package/dist/hub/index.js.map +1 -0
  51. package/dist/index.d.ts +3 -0
  52. package/dist/index.js +11 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/settings.d.ts +16 -0
  55. package/dist/settings.js +49 -0
  56. package/dist/settings.js.map +1 -0
  57. package/docs/FeatureOptions.md +120 -0
  58. package/docs/MQTT.md +116 -0
  59. package/docs/api_reference.pdf +0 -0
  60. package/docs/media/homebridge-unifi-access.png +0 -0
  61. package/docs/media/homebridge-unifi-access.svg +21 -0
  62. package/eslint.config.mjs +99 -0
  63. package/homebridge-ui/public/app.js +104 -0
  64. package/homebridge-ui/public/index.html +267 -0
  65. package/homebridge-ui/public/modules/constants.js +22 -0
  66. package/homebridge-ui/public/modules/controllers.js +202 -0
  67. package/homebridge-ui/public/modules/discovery.js +89 -0
  68. package/homebridge-ui/public/modules/dom-helpers.js +41 -0
  69. package/homebridge-ui/public/modules/feature-options.js +625 -0
  70. package/homebridge-ui/public/modules/state.js +26 -0
  71. package/homebridge-ui/public/styles.css +533 -0
  72. package/homebridge-ui/server.js +374 -0
  73. package/package.json +83 -0
  74. package/scripts/event-schema-monitor.ts +350 -0
@@ -0,0 +1,330 @@
1
+ /* Copyright(C) 2026, Mickael Palma. All rights reserved.
2
+ *
3
+ * access-device.ts: Base class for all UniFi Access devices.
4
+ */
5
+ import { ACCESS_MOTION_DURATION, ACCESS_OCCUPANCY_DURATION, HK_CHARACTERISTIC_REVERT_DELAY_MS, createPrefixedLogger, normalizeMac } from "./settings.js";
6
+ import { sanitizeName } from "homebridge-plugin-utils";
7
+ import { AccessReservedNames } from "./access-types.js";
8
+ import { getDeviceCatalog } from "./access-device-catalog.js";
9
+ // Pre-computed set for fast reserved name lookups.
10
+ const reservedNameSet = new Set(Object.values(AccessReservedNames).map(x => x.toUpperCase()));
11
+ export class AccessBase {
12
+ api;
13
+ hap;
14
+ log;
15
+ controller;
16
+ udaApi;
17
+ platform;
18
+ // The constructor initializes key variables and calls configureDevice().
19
+ constructor(controller) {
20
+ this.api = controller.platform.api;
21
+ this.hap = this.api.hap;
22
+ this.controller = controller;
23
+ this.udaApi = controller.udaApi;
24
+ this.platform = controller.platform;
25
+ this.log = createPrefixedLogger(controller.platform.log, controller.platform.debug.bind(controller.platform), () => this.name);
26
+ }
27
+ // Configure the device information for HomeKit.
28
+ setInfo(accessory, device) {
29
+ // Update the manufacturer information for this device.
30
+ accessory.getService(this.hap.Service.AccessoryInformation)?.updateCharacteristic(this.hap.Characteristic.Manufacturer, "Ubiquiti Inc.");
31
+ // Update the model information for this device.
32
+ const deviceModel = device.display_model ?? device.model;
33
+ if (deviceModel) {
34
+ accessory.getService(this.hap.Service.AccessoryInformation)?.updateCharacteristic(this.hap.Characteristic.Model, deviceModel);
35
+ }
36
+ // Update the serial number for this device.
37
+ if (device.mac) {
38
+ accessory.getService(this.hap.Service.AccessoryInformation)?.updateCharacteristic(this.hap.Characteristic.SerialNumber, normalizeMac(device.mac));
39
+ }
40
+ // Update the firmware revision for this device.
41
+ if (device.firmware) {
42
+ // Capture the version of the device firmware, ensuring we get major, minor, and patch levels if they exist.
43
+ const versionRegex = /^v(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.(.+))?$/;
44
+ const match = versionRegex.exec(device.firmware);
45
+ // Update our firmware revision.
46
+ accessory.getService(this.hap.Service.AccessoryInformation)?.updateCharacteristic(this.hap.Characteristic.FirmwareRevision, match ? match[1] + "." + (match[2] ?? "0") + "." + (match[3] ?? "0") : device.firmware);
47
+ }
48
+ return true;
49
+ }
50
+ // Utility function to return the fully enumerated name of this device.
51
+ get name() {
52
+ return this.controller.udaApi.name;
53
+ }
54
+ }
55
+ export class AccessDevice extends AccessBase {
56
+ accessory;
57
+ hints;
58
+ listeners;
59
+ // The constructor initializes key variables and calls configureDevice().
60
+ constructor(controller, accessory) {
61
+ // Call the constructor of our base class.
62
+ super(controller);
63
+ this.hints = {};
64
+ this.listeners = {};
65
+ // Set the accessory.
66
+ this.accessory = accessory;
67
+ }
68
+ // Configure device-specific settings.
69
+ configureHints() {
70
+ this.hints.enabled = this.hasFeature("Device");
71
+ this.hints.logMotion = this.hasFeature("Log.Motion");
72
+ this.hints.motionDuration = this.getFeatureNumber("Motion.Duration") ?? ACCESS_MOTION_DURATION;
73
+ this.hints.occupancyDuration = this.getFeatureNumber("Motion.OccupancySensor.Duration") ?? ACCESS_OCCUPANCY_DURATION;
74
+ this.hints.syncName = this.hasFeature("Device.SyncName");
75
+ // Sanity check motion detection duration. Make sure it's never less than 2 seconds so we can actually alert the user.
76
+ if (this.hints.motionDuration < 2) {
77
+ this.hints.motionDuration = 2;
78
+ }
79
+ // Sanity check occupancy detection duration. Make sure it's never less than 60 seconds so we can actually alert the user.
80
+ if (this.hints.occupancyDuration < 60) {
81
+ this.hints.occupancyDuration = 60;
82
+ }
83
+ // Inform the user if we've opted for something other than the defaults.
84
+ if (this.hints.syncName) {
85
+ this.log.info("Syncing Access device name to HomeKit.");
86
+ }
87
+ if (this.hints.motionDuration !== ACCESS_MOTION_DURATION) {
88
+ this.log.info("Motion event duration set to %s seconds.", this.hints.motionDuration);
89
+ }
90
+ if (this.hints.occupancyDuration !== ACCESS_OCCUPANCY_DURATION) {
91
+ this.log.info("Occupancy event duration set to %s seconds.", this.hints.occupancyDuration);
92
+ }
93
+ return true;
94
+ }
95
+ // Configure the device information details for HomeKit.
96
+ configureInfo() {
97
+ // Sync the Access name with HomeKit, if configured.
98
+ if (this.hints.syncName && this.uda.alias) {
99
+ this.accessoryName = this.uda.alias;
100
+ }
101
+ return this.setInfo(this.accessory, this.uda);
102
+ }
103
+ // Cleanup our event handlers and any other activities as needed.
104
+ cleanup() {
105
+ for (const eventName of Object.keys(this.listeners)) {
106
+ try {
107
+ this.controller.events.removeListener(eventName, this.listeners[eventName]);
108
+ }
109
+ catch (error) {
110
+ this.log.debug("Failed to remove event listener for %s: %s", eventName, error);
111
+ }
112
+ delete this.listeners[eventName];
113
+ }
114
+ }
115
+ // Configure the Access motion sensor for HomeKit.
116
+ configureMotionSensor(isEnabled = true) {
117
+ // Find the motion sensor service, if it exists.
118
+ let motionService = this.accessory.getService(this.hap.Service.MotionSensor);
119
+ // Have we disabled the motion sensor?
120
+ if (!isEnabled) {
121
+ if (motionService) {
122
+ this.accessory.removeService(motionService);
123
+ this.controller.mqtt?.unsubscribe(this.id, "motion/trigger");
124
+ this.log.info("Disabling motion sensor.");
125
+ }
126
+ this.configureMotionSwitch(isEnabled);
127
+ this.configureMotionTrigger(isEnabled);
128
+ return false;
129
+ }
130
+ // We don't have a motion sensor, let's add it to the device.
131
+ if (!motionService) {
132
+ // We don't have it, add the motion sensor to the device.
133
+ motionService = new this.hap.Service.MotionSensor(this.accessoryName);
134
+ this.accessory.addService(motionService);
135
+ this.log.info("Enabling motion sensor.");
136
+ }
137
+ // Initialize the state of the motion sensor.
138
+ motionService.displayName = this.accessoryName;
139
+ motionService.updateCharacteristic(this.hap.Characteristic.Name, this.accessoryName);
140
+ motionService.updateCharacteristic(this.hap.Characteristic.MotionDetected, false);
141
+ motionService.updateCharacteristic(this.hap.Characteristic.StatusActive, this.isOnline);
142
+ motionService.getCharacteristic(this.hap.Characteristic.StatusActive).onGet(() => {
143
+ return this.isOnline;
144
+ });
145
+ // Configure our MQTT support.
146
+ this.configureMqttMotionTrigger();
147
+ // Configure any motion switches or triggers the user may have enabled or disabled.
148
+ this.configureMotionSwitch(isEnabled);
149
+ this.configureMotionTrigger(isEnabled);
150
+ return true;
151
+ }
152
+ // Configure a switch to easily activate or deactivate motion sensor detection for HomeKit.
153
+ configureMotionSwitch(isEnabled = true) {
154
+ // Find the switch service, if it exists.
155
+ let switchService = this.accessory.getServiceById(this.hap.Service.Switch, AccessReservedNames.SWITCH_MOTION_SENSOR);
156
+ // Motion switches are disabled by default unless the user enables them.
157
+ if (!isEnabled || !this.hasFeature("Motion.Switch")) {
158
+ if (switchService) {
159
+ this.accessory.removeService(switchService);
160
+ }
161
+ // If we disable the switch, make sure we fully reset it's state. Otherwise, we can end up in a situation (e.g. liveview switches) where we have
162
+ // disabled motion detection with no meaningful way to enable it again.
163
+ this.accessory.context.detectMotion = true;
164
+ return false;
165
+ }
166
+ this.log.info("Enabling motion sensor switch.");
167
+ const switchName = this.accessoryName + " Motion Events";
168
+ // Add the switch to the device, if needed.
169
+ if (!switchService) {
170
+ switchService = new this.hap.Service.Switch(switchName, AccessReservedNames.SWITCH_MOTION_SENSOR);
171
+ switchService.addOptionalCharacteristic(this.hap.Characteristic.ConfiguredName);
172
+ this.accessory.addService(switchService);
173
+ }
174
+ // Activate or deactivate motion detection.
175
+ switchService.getCharacteristic(this.hap.Characteristic.On).onGet(() => {
176
+ return this.accessory.context.detectMotion === true;
177
+ });
178
+ switchService.getCharacteristic(this.hap.Characteristic.On).onSet((value) => {
179
+ if (this.accessory.context.detectMotion !== value) {
180
+ this.log.info("Motion detection %s.", (value === true) ? "enabled" : "disabled");
181
+ }
182
+ this.accessory.context.detectMotion = value === true;
183
+ });
184
+ // Initialize the switch state.
185
+ if (!("detectMotion" in this.accessory.context)) {
186
+ this.accessory.context.detectMotion = true;
187
+ }
188
+ switchService.updateCharacteristic(this.hap.Characteristic.ConfiguredName, switchName);
189
+ switchService.updateCharacteristic(this.hap.Characteristic.On, this.accessory.context.detectMotion);
190
+ return true;
191
+ }
192
+ // Configure a switch to manually trigger a motion sensor event for HomeKit.
193
+ configureMotionTrigger(isEnabled = true) {
194
+ // Find the switch service, if it exists.
195
+ let triggerService = this.accessory.getServiceById(this.hap.Service.Switch, AccessReservedNames.SWITCH_MOTION_TRIGGER);
196
+ // Motion triggers are disabled by default and primarily exist for automation purposes.
197
+ if (!isEnabled || !this.hasFeature("Motion.Trigger")) {
198
+ if (triggerService) {
199
+ this.accessory.removeService(triggerService);
200
+ }
201
+ return false;
202
+ }
203
+ const triggerName = this.accessoryName + " Motion Trigger";
204
+ // Add the switch to the device, if needed.
205
+ if (!triggerService) {
206
+ triggerService = new this.hap.Service.Switch(triggerName, AccessReservedNames.SWITCH_MOTION_TRIGGER);
207
+ triggerService.addOptionalCharacteristic(this.hap.Characteristic.ConfiguredName);
208
+ this.accessory.addService(triggerService);
209
+ }
210
+ const motionService = this.accessory.getService(this.hap.Service.MotionSensor);
211
+ const switchService = this.accessory.getServiceById(this.hap.Service.Switch, AccessReservedNames.SWITCH_MOTION_SENSOR);
212
+ // Activate or deactivate motion detection.
213
+ triggerService.getCharacteristic(this.hap.Characteristic.On).onGet(() => {
214
+ return motionService?.getCharacteristic(this.hap.Characteristic.MotionDetected).value === true;
215
+ });
216
+ triggerService.getCharacteristic(this.hap.Characteristic.On).onSet((isOn) => {
217
+ if (isOn) {
218
+ // Check to see if motion events are disabled.
219
+ if (switchService && !switchService.getCharacteristic(this.hap.Characteristic.On).value) {
220
+ setTimeout(() => triggerService.updateCharacteristic(this.hap.Characteristic.On, false), HK_CHARACTERISTIC_REVERT_DELAY_MS);
221
+ }
222
+ else {
223
+ // Trigger the motion event.
224
+ this.controller.events.motionEventHandler(this);
225
+ // Inform the user.
226
+ this.log.info("Motion event triggered.");
227
+ }
228
+ return;
229
+ }
230
+ // If the motion sensor is still on, we should be as well.
231
+ if (motionService?.getCharacteristic(this.hap.Characteristic.MotionDetected).value) {
232
+ setTimeout(() => triggerService.updateCharacteristic(this.hap.Characteristic.On, true), HK_CHARACTERISTIC_REVERT_DELAY_MS);
233
+ }
234
+ });
235
+ // Initialize the switch.
236
+ triggerService.updateCharacteristic(this.hap.Characteristic.ConfiguredName, triggerName);
237
+ triggerService.updateCharacteristic(this.hap.Characteristic.On, false);
238
+ this.log.info("Enabling motion sensor automation trigger.");
239
+ return true;
240
+ }
241
+ // Configure MQTT motion triggers.
242
+ configureMqttMotionTrigger() {
243
+ // Trigger a motion event in MQTT, if requested to do so.
244
+ this.controller.mqtt?.subscribe(this.id, "motion/trigger", (message) => {
245
+ const value = message.toString();
246
+ // When we get the right message, we trigger the motion event.
247
+ if (value.toLowerCase() !== "true") {
248
+ return;
249
+ }
250
+ // Trigger the motion event.
251
+ this.controller.events.motionEventHandler(this);
252
+ this.log.info("Motion event triggered via MQTT.");
253
+ });
254
+ return true;
255
+ }
256
+ // Configure the Access occupancy sensor for HomeKit.
257
+ configureOccupancySensor(isEnabled = true) {
258
+ // Find the occupancy sensor service, if it exists.
259
+ let occupancyService = this.accessory.getService(this.hap.Service.OccupancySensor);
260
+ // Occupancy sensors are disabled by default and primarily exist for automation purposes.
261
+ if (!isEnabled || !this.hasFeature("Motion.OccupancySensor")) {
262
+ if (occupancyService) {
263
+ this.accessory.removeService(occupancyService);
264
+ this.log.info("Disabling occupancy sensor.");
265
+ }
266
+ return false;
267
+ }
268
+ // We don't have an occupancy sensor, let's add it to the device.
269
+ if (!occupancyService) {
270
+ // We don't have it, add the occupancy sensor to the device.
271
+ occupancyService = new this.hap.Service.OccupancySensor(this.accessoryName);
272
+ this.accessory.addService(occupancyService);
273
+ }
274
+ // Initialize the state of the occupancy sensor.
275
+ occupancyService.updateCharacteristic(this.hap.Characteristic.OccupancyDetected, false);
276
+ occupancyService.updateCharacteristic(this.hap.Characteristic.StatusActive, this.isOnline);
277
+ occupancyService.getCharacteristic(this.hap.Characteristic.StatusActive).onGet(() => {
278
+ return this.isOnline;
279
+ });
280
+ this.log.info("Enabling occupancy sensor.");
281
+ return true;
282
+ }
283
+ // Utility function to return a floating point configuration parameter on a device.
284
+ getFeatureFloat(option) {
285
+ return this.platform.featureOptions.getFloat(option, this.id, this.controller.id);
286
+ }
287
+ // Utility function to return an integer configuration parameter on a device.
288
+ getFeatureNumber(option) {
289
+ return this.platform.featureOptions.getInteger(option, this.id, this.controller.id);
290
+ }
291
+ // Utility function to return a configuration parameter on a device.
292
+ getFeatureValue(option) {
293
+ return this.platform.featureOptions.value(option, this.id, this.controller.id);
294
+ }
295
+ // Utility for checking feature options on a device.
296
+ hasFeature(option) {
297
+ return this.controller.hasFeature(option, this.uda);
298
+ }
299
+ // Utility function for reserved identifiers for switches.
300
+ isReservedName(name) {
301
+ return name === undefined ? false : reservedNameSet.has(name.toUpperCase());
302
+ }
303
+ // Utility function to determine whether or not a device is currently online.
304
+ get isOnline() {
305
+ return ["is_adopted", "is_connected", "is_managed", "is_online"].every(key => this.uda[key]);
306
+ }
307
+ // Return a unique identifier for an Access device.
308
+ get id() {
309
+ return this.uda.mac.replace(/:/g, "") + ((getDeviceCatalog(this.uda.device_type)?.appendsSourceId) ? "-" + this.uda.source_id.toUpperCase() : "");
310
+ }
311
+ // Utility function to return the fully enumerated name of this device.
312
+ get name() {
313
+ return this.controller.udaApi.getFullName(this.uda);
314
+ }
315
+ // Utility function to return the current accessory name of this device.
316
+ get accessoryName() {
317
+ return this.accessory.getService(this.hap.Service.AccessoryInformation)?.getCharacteristic(this.hap.Characteristic.Name).value ??
318
+ (this.uda.alias ?? "Unknown");
319
+ }
320
+ // Utility function to set the current accessory name of this device.
321
+ set accessoryName(name) {
322
+ const cleanedName = sanitizeName(name);
323
+ // Set all the internally managed names within Homebridge to the new accessory name.
324
+ this.accessory.displayName = cleanedName;
325
+ this.accessory._associatedHAPAccessory.displayName = cleanedName;
326
+ // Set all the HomeKit-visible names.
327
+ this.accessory.getService(this.hap.Service.AccessoryInformation)?.updateCharacteristic(this.hap.Characteristic.Name, cleanedName);
328
+ }
329
+ }
330
+ //# sourceMappingURL=access-device.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access-device.js","sourceRoot":"","sources":["../src/access-device.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { AccessEventPacket } from "unifi-access";
2
+ import type { AccessController } from "./access-controller.js";
3
+ import type { AccessDevice } from "./access-device.js";
4
+ import { EventEmitter } from "node:events";
5
+ type AccessEventMap = Record<string, [AccessEventPacket]>;
6
+ export declare class AccessEvents extends EventEmitter<AccessEventMap> {
7
+ private api;
8
+ private controller;
9
+ private eventsHandler;
10
+ private readonly eventTimers;
11
+ private hap;
12
+ private log;
13
+ private mqttPublishTelemetry;
14
+ private platform;
15
+ private udaApi;
16
+ private udaDeviceState;
17
+ private udaUpdatesHandler;
18
+ private unsupportedDevices;
19
+ constructor(controller: AccessController);
20
+ private udaUpdates;
21
+ private manageDevices;
22
+ private configureEvents;
23
+ private sanitizeTelemetry;
24
+ motionEventHandler(accessDevice: AccessDevice): void;
25
+ private motionEventDelivery;
26
+ }
27
+ export {};
@@ -0,0 +1,152 @@
1
+ import { AccessEventType, AccessReservedNames } from "./access-types.js";
2
+ import { sanitizeName } from "homebridge-plugin-utils";
3
+ import { EventEmitter } from "node:events";
4
+ export class AccessEvents extends EventEmitter {
5
+ api;
6
+ controller;
7
+ eventsHandler;
8
+ eventTimers;
9
+ hap;
10
+ log;
11
+ mqttPublishTelemetry;
12
+ platform;
13
+ udaApi;
14
+ udaDeviceState;
15
+ udaUpdatesHandler;
16
+ unsupportedDevices;
17
+ // Initialize an instance of our Access events handler.
18
+ constructor(controller) {
19
+ super();
20
+ this.api = controller.platform.api;
21
+ this.eventTimers = {};
22
+ this.hap = controller.platform.api.hap;
23
+ this.log = controller.log;
24
+ this.mqttPublishTelemetry = controller.hasFeature("Controller.Publish.Telemetry");
25
+ this.controller = controller;
26
+ this.udaApi = controller.udaApi;
27
+ this.udaDeviceState = {};
28
+ this.platform = controller.platform;
29
+ this.unsupportedDevices = {};
30
+ this.eventsHandler = null;
31
+ this.udaUpdatesHandler = null;
32
+ // If we've enabled telemetry from the controller inform the user.
33
+ if (this.mqttPublishTelemetry) {
34
+ this.log.info("Access controller telemetry enabled.");
35
+ }
36
+ this.configureEvents();
37
+ }
38
+ // Process Access API update events.
39
+ udaUpdates(packet) {
40
+ // Lookup the device.
41
+ const accessDevice = this.controller.deviceLookup(packet.event_object_id);
42
+ // We have the device, let's check for device updates.
43
+ if (accessDevice) {
44
+ // Update our device configuration state.
45
+ accessDevice.uda = packet.data;
46
+ // If we have services on the accessory associated with the Access device that have a StatusActive characteristic set, update our availability state.
47
+ accessDevice.accessory.services.filter(x => x.testCharacteristic(this.hap.Characteristic.StatusActive))
48
+ .map(x => x.updateCharacteristic(this.hap.Characteristic.StatusActive, accessDevice.isOnline));
49
+ // Sync names, if configured to do so.
50
+ if (accessDevice.hints.syncName && accessDevice.uda.alias && (accessDevice.accessoryName !== sanitizeName(accessDevice.uda.alias))) {
51
+ accessDevice.log.info("Name change detected. A restart of Homebridge may be needed in order to complete name synchronization with HomeKit.");
52
+ accessDevice.configureInfo();
53
+ }
54
+ }
55
+ // Update the internal list we maintain.
56
+ this.udaDeviceState[packet.event_object_id] = packet.data;
57
+ }
58
+ // Process device additions and removals from the Access events API.
59
+ manageDevices(packet) {
60
+ // Lookup the device.
61
+ const accessDevice = this.controller.deviceLookup(packet.event_object_id);
62
+ // We're unadopting.
63
+ if (packet.event === AccessEventType.DEVICE_DELETE) {
64
+ // If it's already gone, we're done.
65
+ if (!accessDevice) {
66
+ return;
67
+ }
68
+ // Remove the device.
69
+ this.controller.removeHomeKitDevice(accessDevice.accessory);
70
+ return;
71
+ }
72
+ }
73
+ // Listen to the UniFi Access events API for updates we are interested in (e.g. unlock).
74
+ configureEvents() {
75
+ // Only configure the event listener if it exists and it's not already configured.
76
+ if (this.eventsHandler && this.udaUpdatesHandler) {
77
+ return true;
78
+ }
79
+ // Ensure we update our UDA state before we process any other events.
80
+ this.prependListener(AccessEventType.DEVICE_UPDATE, this.udaUpdatesHandler = this.udaUpdates.bind(this));
81
+ // Process remove events.
82
+ this.prependListener(AccessEventType.DEVICE_DELETE, this.manageDevices.bind(this));
83
+ // Listen for any messages coming in from our listener. We route events to the appropriate handlers based on the type of event that comes across.
84
+ this.udaApi.on("message", this.eventsHandler = (packet) => {
85
+ // Emit messages based on the event type.
86
+ this.emit(packet.event, packet);
87
+ // Emit messages based on the specific device.
88
+ this.emit(packet.event_object_id, packet);
89
+ // For v2 device update events, we need to unpack the metadata to determine which device we're targeting.
90
+ if ((packet.event === AccessEventType.DEVICE_UPDATE_V2) && (packet.meta?.object_type === "device")) {
91
+ this.emit(packet.meta.id, packet);
92
+ }
93
+ // Finally, emit messages based on the specific event and device combination.
94
+ this.emit(packet.event + "." + packet.event_object_id, packet);
95
+ // If enabled, publish all the event traffic coming from the Access controller to MQTT.
96
+ if (this.mqttPublishTelemetry) {
97
+ this.controller.mqtt?.publish(this.controller.id ?? "", "telemetry", this.sanitizeTelemetry(packet));
98
+ }
99
+ });
100
+ return true;
101
+ }
102
+ // Sanitize an event packet for MQTT telemetry, stripping raw data that may contain sensitive information.
103
+ sanitizeTelemetry(packet) {
104
+ return JSON.stringify({
105
+ event: packet.event,
106
+ event_object_id: packet.event_object_id, // eslint-disable-line camelcase
107
+ ...(packet.meta ? { meta: { id: packet.meta.id, object_type: packet.meta.object_type } } : {}) // eslint-disable-line camelcase
108
+ });
109
+ }
110
+ // Motion event processing from UniFi Access.
111
+ motionEventHandler(accessDevice) {
112
+ // Only notify the user if we have a motion sensor and it's active.
113
+ const motionService = accessDevice.accessory.getService(this.hap.Service.MotionSensor);
114
+ if (motionService) {
115
+ this.motionEventDelivery(accessDevice, motionService);
116
+ }
117
+ }
118
+ // Motion event delivery to HomeKit.
119
+ motionEventDelivery(accessDevice, motionService) {
120
+ // If we have disabled motion events, we're done here.
121
+ if (("detectMotion" in accessDevice.accessory.context) && !accessDevice.accessory.context.detectMotion) {
122
+ return;
123
+ }
124
+ // If we have an active motion event inflight, we're done.
125
+ if (this.eventTimers[accessDevice.id]) {
126
+ accessDevice.log.debug("Motion event rate-limited: event already in progress.");
127
+ return;
128
+ }
129
+ // Trigger the motion event in HomeKit.
130
+ motionService.updateCharacteristic(this.hap.Characteristic.MotionDetected, true);
131
+ // If we have a motion trigger switch configured, update it.
132
+ accessDevice.accessory.getServiceById(this.hap.Service.Switch, AccessReservedNames.SWITCH_MOTION_TRIGGER)?.updateCharacteristic(this.hap.Characteristic.On, true);
133
+ // Publish the motion event to MQTT, if the user has configured it.
134
+ this.controller.mqtt?.publish(accessDevice.id, "motion", "true");
135
+ // Log the event, if configured to do so.
136
+ if (accessDevice.hints.logMotion) {
137
+ accessDevice.log.info("Motion detected.");
138
+ }
139
+ // Reset our motion event after motionDuration.
140
+ this.eventTimers[accessDevice.id] = setTimeout(() => {
141
+ motionService.updateCharacteristic(this.hap.Characteristic.MotionDetected, false);
142
+ // If we have a motion trigger switch configured, update it.
143
+ accessDevice.accessory.getServiceById(this.hap.Service.Switch, AccessReservedNames.SWITCH_MOTION_TRIGGER)?.updateCharacteristic(this.hap.Characteristic.On, false);
144
+ accessDevice.log.debug("Resetting motion event.");
145
+ // Publish to MQTT, if the user has configured it.
146
+ this.controller.mqtt?.publish(accessDevice.id, "motion", "false");
147
+ // Delete the timer from our motion event tracker.
148
+ delete this.eventTimers[accessDevice.id];
149
+ }, accessDevice.hints.motionDuration * 1000);
150
+ }
151
+ }
152
+ //# sourceMappingURL=access-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access-events.js","sourceRoot":"","sources":["../src/access-events.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAgC,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAIrF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAM3C,MAAM,OAAO,YAAa,SAAQ,YAA4B;IAEpD,GAAG,CAAM;IACT,UAAU,CAAmB;IAC7B,aAAa,CAA+C;IACnD,WAAW,CAA6C;IACjE,GAAG,CAAM;IACT,GAAG,CAA0B;IAC7B,oBAAoB,CAAU;IAC9B,QAAQ,CAAiB;IACzB,MAAM,CAAY;IAClB,cAAc,CAAqC;IACnD,iBAAiB,CAA+C;IAChE,kBAAkB,CAA0B;IAEpD,uDAAuD;IACvD,YAAY,UAA4B;QAEtC,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC;QACnC,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;QACvC,IAAI,CAAC,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC;QAC1B,IAAI,CAAC,oBAAoB,GAAG,UAAU,CAAC,UAAU,CAAC,8BAA8B,CAAC,CAAC;QAClF,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;QAChC,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC;QACpC,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAE9B,kEAAkE;QAClE,IAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAE7B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;QACxD,CAAC;QAED,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;IAED,oCAAoC;IAC5B,UAAU,CAAC,MAAyB;QAE1C,qBAAqB;QACrB,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAE1E,sDAAsD;QACtD,IAAG,YAAY,EAAE,CAAC;YAEhB,yCAAyC;YACzC,YAAY,CAAC,GAAG,GAAG,MAAM,CAAC,IAA0B,CAAC;YAErD,qJAAqJ;YACrJ,YAAY,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;iBACpG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,YAAY,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;YAEjG,sCAAsC;YACtC,IAAG,YAAY,CAAC,KAAK,CAAC,QAAQ,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,YAAY,CAAC,aAAa,KAAK,YAAY,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBAElI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,qHAAqH,CAAC,CAAC;gBAC7I,YAAY,CAAC,aAAa,EAAE,CAAC;YAC/B,CAAC;QACH,CAAC;QAED,wCAAwC;QACxC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,MAAM,CAAC,IAA0B,CAAC;IAClF,CAAC;IAED,oEAAoE;IAC5D,aAAa,CAAC,MAAyB;QAE7C,qBAAqB;QACrB,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAE1E,oBAAoB;QACpB,IAAG,MAAM,CAAC,KAAK,KAAK,eAAe,CAAC,aAAa,EAAE,CAAC;YAElD,oCAAoC;YACpC,IAAG,CAAC,YAAY,EAAE,CAAC;gBAEjB,OAAO;YACT,CAAC;YAED,qBAAqB;YACrB,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;YAE5D,OAAO;QACT,CAAC;IACH,CAAC;IAED,wFAAwF;IAChF,eAAe;QAErB,kFAAkF;QAClF,IAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAEhD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,qEAAqE;QACrE,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,aAAa,EAAE,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAEzG,yBAAyB;QACzB,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,aAAa,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAEnF,iJAAiJ;QACjJ,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,GAAG,CAAC,MAAyB,EAAQ,EAAE;YAEjF,yCAAyC;YACzC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAEhC,8CAA8C;YAC9C,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;YAE1C,yGAAyG;YACzG,IAAG,CAAC,MAAM,CAAC,KAAK,KAAK,eAAe,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,KAAK,QAAQ,CAAC,EAAE,CAAC;gBAElG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YACpC,CAAC;YAED,6EAA6E;YAC7E,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,GAAG,GAAG,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;YAE/D,uFAAuF;YACvF,IAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBAE7B,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;YACvG,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,0GAA0G;IAClG,iBAAiB,CAAC,MAAyB;QAEjD,OAAO,IAAI,CAAC,SAAS,CAAC;YAEpB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,eAAe,EAAE,MAAM,CAAC,eAAe,EAAE,gCAAgC;YACzE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,gCAAgC;SAChI,CAAC,CAAC;IACL,CAAC;IAED,6CAA6C;IACtC,kBAAkB,CAAC,YAA0B;QAElD,mEAAmE;QACnE,MAAM,aAAa,GAAG,YAAY,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAEvF,IAAG,aAAa,EAAE,CAAC;YAEjB,IAAI,CAAC,mBAAmB,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED,oCAAoC;IAC5B,mBAAmB,CAAC,YAA0B,EAAE,aAAsB;QAE5E,sDAAsD;QACtD,IAAG,CAAC,cAAc,IAAI,YAAY,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;YAEtG,OAAO;QACT,CAAC;QAED,0DAA0D;QAC1D,IAAG,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC;YAErC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;YAEhF,OAAO;QACT,CAAC;QAED,uCAAuC;QACvC,aAAa,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;QAEjF,4DAA4D;QAC5D,YAAY,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,qBAAqB,CAAC,EAAE,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAElK,mEAAmE;QACnE,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QAEjE,yCAAyC;QACzC,IAAG,YAAY,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;YAEhC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAC5C,CAAC;QAED,+CAA+C;QAC/C,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE;YAElD,aAAa,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;YAElF,4DAA4D;YAC5D,YAAY,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,qBAAqB,CAAC,EAAE,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YAEnK,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;YAElD,kDAAkD;YAClD,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;YAElE,kDAAkD;YAClD,OAAO,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QAC3C,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC/C,CAAC;CACF"}
@@ -0,0 +1,32 @@
1
+ import type { FeatureOptionEntry } from "homebridge-plugin-utils";
2
+ export interface AccessOptions {
3
+ controllers: AccessControllerOptions[];
4
+ debugAll: boolean;
5
+ options: string[];
6
+ ringDelay: number;
7
+ }
8
+ export interface AccessControllerOptions {
9
+ address: string;
10
+ mqttTopic: string;
11
+ mqttUrl?: string;
12
+ name?: string;
13
+ username: string;
14
+ password: string;
15
+ }
16
+ interface AccessFeatureOption extends FeatureOptionEntry {
17
+ hasCapability?: string[];
18
+ modelKey?: string[];
19
+ }
20
+ export declare const featureOptionCategories: ({
21
+ description: string;
22
+ modelKey: string[];
23
+ name: string;
24
+ hasCapability?: undefined;
25
+ } | {
26
+ description: string;
27
+ hasCapability: string[];
28
+ modelKey: string[];
29
+ name: string;
30
+ })[];
31
+ export declare const featureOptions: Record<string, AccessFeatureOption[]>;
32
+ export {};