@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.
- package/.claude/settings.local.json +91 -0
- package/CHANGELOG.md +13 -0
- package/LICENSE.md +22 -0
- package/README.md +159 -0
- package/config.schema.json +202 -0
- package/dist/access-controller.d.ts +41 -0
- package/dist/access-controller.js +342 -0
- package/dist/access-controller.js.map +1 -0
- package/dist/access-device-catalog.d.ts +43 -0
- package/dist/access-device-catalog.js +151 -0
- package/dist/access-device-catalog.js.map +1 -0
- package/dist/access-device.d.ts +68 -0
- package/dist/access-device.js +330 -0
- package/dist/access-device.js.map +1 -0
- package/dist/access-events.d.ts +27 -0
- package/dist/access-events.js +152 -0
- package/dist/access-events.js.map +1 -0
- package/dist/access-options.d.ts +32 -0
- package/dist/access-options.js +65 -0
- package/dist/access-options.js.map +1 -0
- package/dist/access-platform.d.ts +15 -0
- package/dist/access-platform.js +74 -0
- package/dist/access-platform.js.map +1 -0
- package/dist/access-types.d.ts +30 -0
- package/dist/access-types.js +42 -0
- package/dist/access-types.js.map +1 -0
- package/dist/hub/access-hub-api.d.ts +13 -0
- package/dist/hub/access-hub-api.js +140 -0
- package/dist/hub/access-hub-api.js.map +1 -0
- package/dist/hub/access-hub-events.d.ts +2 -0
- package/dist/hub/access-hub-events.js +229 -0
- package/dist/hub/access-hub-events.js.map +1 -0
- package/dist/hub/access-hub-mqtt.d.ts +2 -0
- package/dist/hub/access-hub-mqtt.js +137 -0
- package/dist/hub/access-hub-mqtt.js.map +1 -0
- package/dist/hub/access-hub-services.d.ts +4 -0
- package/dist/hub/access-hub-services.js +451 -0
- package/dist/hub/access-hub-services.js.map +1 -0
- package/dist/hub/access-hub-types.d.ts +145 -0
- package/dist/hub/access-hub-types.js +35 -0
- package/dist/hub/access-hub-types.js.map +1 -0
- package/dist/hub/access-hub-utils.d.ts +20 -0
- package/dist/hub/access-hub-utils.js +128 -0
- package/dist/hub/access-hub-utils.js.map +1 -0
- package/dist/hub/access-hub.d.ts +39 -0
- package/dist/hub/access-hub.js +185 -0
- package/dist/hub/access-hub.js.map +1 -0
- package/dist/hub/index.d.ts +4 -0
- package/dist/hub/index.js +7 -0
- package/dist/hub/index.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/settings.d.ts +16 -0
- package/dist/settings.js +49 -0
- package/dist/settings.js.map +1 -0
- package/docs/FeatureOptions.md +120 -0
- package/docs/MQTT.md +116 -0
- package/docs/api_reference.pdf +0 -0
- package/docs/media/homebridge-unifi-access.png +0 -0
- package/docs/media/homebridge-unifi-access.svg +21 -0
- package/eslint.config.mjs +99 -0
- package/homebridge-ui/public/app.js +104 -0
- package/homebridge-ui/public/index.html +267 -0
- package/homebridge-ui/public/modules/constants.js +22 -0
- package/homebridge-ui/public/modules/controllers.js +202 -0
- package/homebridge-ui/public/modules/discovery.js +89 -0
- package/homebridge-ui/public/modules/dom-helpers.js +41 -0
- package/homebridge-ui/public/modules/feature-options.js +625 -0
- package/homebridge-ui/public/modules/state.js +26 -0
- package/homebridge-ui/public/styles.css +533 -0
- package/homebridge-ui/server.js +374 -0
- package/package.json +83 -0
- package/scripts/event-schema-monitor.ts +350 -0
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
/* Copyright(C) 2026, Mickael Palma. All rights reserved.
|
|
2
|
+
*
|
|
3
|
+
* access-controller.ts: Access controller device class for UniFi Access.
|
|
4
|
+
*/
|
|
5
|
+
import { ACCESS_CONTROLLER_REFRESH_INTERVAL, ACCESS_CONTROLLER_RETRY_INTERVAL, PLATFORM_NAME, PLUGIN_NAME, createPrefixedLogger, isValidAddress, normalizeMac } from "./settings.js";
|
|
6
|
+
import { AccessApi } from "unifi-access";
|
|
7
|
+
import { MqttClient, retry, sanitizeName, sleep } from "homebridge-plugin-utils";
|
|
8
|
+
import { AccessEventType } from "./access-types.js";
|
|
9
|
+
import { AccessEvents } from "./access-events.js";
|
|
10
|
+
import { AccessHub } from "./hub/index.js";
|
|
11
|
+
import { getDeviceCatalog } from "./access-device-catalog.js";
|
|
12
|
+
import util from "node:util";
|
|
13
|
+
// Check if a device has supported hub or reader capabilities.
|
|
14
|
+
function isSupportedDevice(device) {
|
|
15
|
+
return ["is_hub", "is_reader"].some(capability => device.capabilities.includes(capability));
|
|
16
|
+
}
|
|
17
|
+
export class AccessController {
|
|
18
|
+
api;
|
|
19
|
+
config;
|
|
20
|
+
deviceRemovalQueue;
|
|
21
|
+
configuredDevices;
|
|
22
|
+
events;
|
|
23
|
+
hap;
|
|
24
|
+
logApiErrors;
|
|
25
|
+
log;
|
|
26
|
+
mqtt;
|
|
27
|
+
name;
|
|
28
|
+
platform;
|
|
29
|
+
uda;
|
|
30
|
+
udaApi;
|
|
31
|
+
bootstrapRefreshTimer;
|
|
32
|
+
unsupportedDevices;
|
|
33
|
+
constructor(platform, accessOptions) {
|
|
34
|
+
this.api = platform.api;
|
|
35
|
+
this.config = accessOptions;
|
|
36
|
+
this.configuredDevices = {};
|
|
37
|
+
this.deviceRemovalQueue = {};
|
|
38
|
+
this.hap = this.api.hap;
|
|
39
|
+
this.logApiErrors = true;
|
|
40
|
+
this.mqtt = null;
|
|
41
|
+
this.name = accessOptions.name ?? accessOptions.address;
|
|
42
|
+
this.platform = platform;
|
|
43
|
+
this.uda = {};
|
|
44
|
+
this.unsupportedDevices = {};
|
|
45
|
+
// Configure our logging.
|
|
46
|
+
this.log = createPrefixedLogger(this.platform.log, this.platform.debug.bind(this.platform), () => this.name);
|
|
47
|
+
// Validate our controller address and login information.
|
|
48
|
+
if (!accessOptions.address || !accessOptions.username || !accessOptions.password) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// Validate that the controller address is not a loopback, link-local, or otherwise invalid address.
|
|
52
|
+
if (!isValidAddress(accessOptions.address)) {
|
|
53
|
+
this.log.error("Invalid controller address: %s. Please provide a valid network address.", accessOptions.address);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Retrieve the bootstrap configuration from the Access controller.
|
|
58
|
+
async bootstrapController() {
|
|
59
|
+
// Attempt to bootstrap the controller until we're successful.
|
|
60
|
+
await retry(async () => this.udaApi.getBootstrap(), ACCESS_CONTROLLER_RETRY_INTERVAL * 1000);
|
|
61
|
+
}
|
|
62
|
+
// Initialize our connection to the UniFi Access controller.
|
|
63
|
+
async login() {
|
|
64
|
+
// The plugin has been disabled globally. Let the user know that we're done here.
|
|
65
|
+
if (!this.hasFeature("Device")) {
|
|
66
|
+
this.log.info("Disabling this UniFi Access controller.");
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// Initialize our connection to the UniFi Access API.
|
|
70
|
+
const udaLog = {
|
|
71
|
+
debug: (message, ...parameters) => this.platform.debug(util.format(message, ...parameters)),
|
|
72
|
+
error: (message, ...parameters) => {
|
|
73
|
+
if (this.logApiErrors) {
|
|
74
|
+
this.platform.log.error(util.format(message, ...parameters));
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
info: (message, ...parameters) => this.platform.log.info(util.format(message, ...parameters)),
|
|
78
|
+
warn: (message, ...parameters) => this.platform.log.warn(util.format(message, ...parameters))
|
|
79
|
+
};
|
|
80
|
+
// Create our connection to the Access API.
|
|
81
|
+
this.udaApi = new AccessApi(udaLog);
|
|
82
|
+
// Attempt to login to the Access controller, retrying at reasonable intervals. This accounts for cases where the Access controller or the network connection
|
|
83
|
+
// may not be fully available when we startup.
|
|
84
|
+
await retry(async () => this.udaApi.login(this.config.address, this.config.username, this.config.password), ACCESS_CONTROLLER_RETRY_INTERVAL * 1000);
|
|
85
|
+
// Now, let's get the bootstrap configuration from the Access controller.
|
|
86
|
+
await this.bootstrapController();
|
|
87
|
+
// Set our Access configuration from the controller.
|
|
88
|
+
this.uda = this.udaApi.controller;
|
|
89
|
+
// Assign our name if the user hasn't explicitly specified a preference.
|
|
90
|
+
this.name = this.config.name ?? this.udaApi.name;
|
|
91
|
+
// We successfully logged in.
|
|
92
|
+
this.log.info("Connected to %s (UniFi Access %s running on UniFi OS %s).", this.config.address, this.uda.version, this.uda.host.firmware_version);
|
|
93
|
+
// Now that we know the Access controller configuration, check to see if we've disabled it.
|
|
94
|
+
if (!this.hasFeature("Device")) {
|
|
95
|
+
this.udaApi.logout();
|
|
96
|
+
this.log.info("Disabling this UniFi Access controller in HomeKit.");
|
|
97
|
+
// Let's sleep for thirty seconds to give all the accessories a chance to load before disabling everything. Homebridge doesn't have a good mechanism to notify us
|
|
98
|
+
// when all the cached accessories are loaded at startup.
|
|
99
|
+
await sleep(30);
|
|
100
|
+
// Unregister all the accessories for this controller from Homebridge that may have been restored already. Any additional ones will be automatically caught when
|
|
101
|
+
// they are restored.
|
|
102
|
+
this.platform.accessories.filter(accessory => accessory.context.controller === this.uda.host.mac).map(accessory => this.removeHomeKitDevice(accessory, true));
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
// Initialize our UniFi Access events handler.
|
|
106
|
+
this.events = new AccessEvents(this);
|
|
107
|
+
// Initialize MQTT, if needed.
|
|
108
|
+
if (!this.mqtt && this.config.mqttUrl) {
|
|
109
|
+
this.mqtt = new MqttClient(this.config.mqttUrl, this.config.mqttTopic, this.log);
|
|
110
|
+
}
|
|
111
|
+
// Inform the user about the devices we see.
|
|
112
|
+
if (this.udaApi.devices) {
|
|
113
|
+
for (const device of this.udaApi.devices) {
|
|
114
|
+
// Filter out any devices that aren't managed by this Access controller.
|
|
115
|
+
if (!device.is_managed) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
this.log.info("Discovered %s: %s.", this.resolveDeviceModel(device), this.udaApi.getDeviceName(device, this.resolveDeviceName(device), true));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Bootstrap refresh loop. Clear any existing timer to prevent accumulation.
|
|
122
|
+
const bootstrapRefresh = () => {
|
|
123
|
+
clearTimeout(this.bootstrapRefreshTimer);
|
|
124
|
+
this.bootstrapRefreshTimer = setTimeout(() => void this.bootstrapController(), ACCESS_CONTROLLER_REFRESH_INTERVAL * 1000);
|
|
125
|
+
};
|
|
126
|
+
// Sync the Access controller's devices with HomeKit.
|
|
127
|
+
const syncUdaHomeKit = () => {
|
|
128
|
+
// Sync status and check for any new or removed accessories.
|
|
129
|
+
this.discoverAndSyncAccessories();
|
|
130
|
+
// Refresh the accessory cache.
|
|
131
|
+
this.api.updatePlatformAccessories(this.platform.accessories);
|
|
132
|
+
};
|
|
133
|
+
// Initialize our Access controller device sync.
|
|
134
|
+
syncUdaHomeKit();
|
|
135
|
+
// Let's set a listener to wait for bootstrap events to occur so we can keep ourselves in sync with the Access controller.
|
|
136
|
+
this.udaApi.on("bootstrap", () => {
|
|
137
|
+
// Sync our device view.
|
|
138
|
+
syncUdaHomeKit();
|
|
139
|
+
// Refresh our bootstrap.
|
|
140
|
+
bootstrapRefresh();
|
|
141
|
+
});
|
|
142
|
+
// Kickoff our first round of bootstrap refreshes to ensure we stay in sync.
|
|
143
|
+
bootstrapRefresh();
|
|
144
|
+
}
|
|
145
|
+
// Create instances of Access device types in our plugin.
|
|
146
|
+
addAccessDevice(accessory, device) {
|
|
147
|
+
// Access hubs.
|
|
148
|
+
if (isSupportedDevice(device)) {
|
|
149
|
+
// We have a UniFi Access hub or reader.
|
|
150
|
+
this.configuredDevices[accessory.UUID] = new AccessHub(this, device, accessory);
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
// Default to an unknown device type.
|
|
154
|
+
this.log.error("Unknown device class %s detected for %s.", device.device_type, this.resolveDeviceName(device));
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
// Discover UniFi Access devices that may have been added to the controller since we last checked.
|
|
158
|
+
discoverDevices(devices) {
|
|
159
|
+
// Iterate through the list of devices that Access has returned and sync them with what we show HomeKit.
|
|
160
|
+
for (const device of devices) {
|
|
161
|
+
this.addHomeKitDevice(device);
|
|
162
|
+
}
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
// Add a newly detected Access device to HomeKit.
|
|
166
|
+
addHomeKitDevice(device) {
|
|
167
|
+
// If we have no MAC address, name, or this device isn't being managed by this Access controller, we're done.
|
|
168
|
+
if (!this.uda.host.mac || !device.mac || !device.is_managed) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
// We only support certain device capabilities.
|
|
172
|
+
if (!isSupportedDevice(device)) {
|
|
173
|
+
// If we've already informed the user about this one, we're done.
|
|
174
|
+
if (this.unsupportedDevices[device.mac]) {
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
// Notify the user we see this device, but we aren't adding it to HomeKit.
|
|
178
|
+
this.unsupportedDevices[device.mac] = true;
|
|
179
|
+
this.log.info("UniFi Access device type '%s' is not currently supported, ignoring: %s.", device.device_type, this.udaApi.getDeviceName(device));
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
// Generate this device's unique identifier. For multi-door devices, we append source_id to the MAC address to distinguish them.
|
|
183
|
+
const catalog = getDeviceCatalog(device.device_type);
|
|
184
|
+
const uuid = this.hap.uuid.generate(device.mac + (catalog?.appendsSourceId ? "-" + device.source_id.toUpperCase() : ""));
|
|
185
|
+
// See if we already know about this accessory.
|
|
186
|
+
let accessory = this.platform.accessories.find(x => x.UUID === uuid);
|
|
187
|
+
// Enable or disable certain devices based on configuration parameters.
|
|
188
|
+
if (!this.hasFeature("Device", device)) {
|
|
189
|
+
if (accessory) {
|
|
190
|
+
this.removeHomeKitDevice(accessory, true);
|
|
191
|
+
}
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
// We've got a new device, let's add it to HomeKit.
|
|
195
|
+
if (!accessory) {
|
|
196
|
+
accessory = new this.api.platformAccessory(sanitizeName(this.resolveDeviceName(device)), uuid);
|
|
197
|
+
this.log.info("%s: Adding %s to HomeKit.", this.udaApi.getFullName(device), device.display_model);
|
|
198
|
+
// Register this accessory with homebridge and add it to the accessory array so we can track it.
|
|
199
|
+
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
200
|
+
this.platform.accessories.push(accessory);
|
|
201
|
+
this.api.updatePlatformAccessories(this.platform.accessories);
|
|
202
|
+
}
|
|
203
|
+
// Setup the accessory as a new Access device in HBUA if we haven't configured it yet.
|
|
204
|
+
if (!this.configuredDevices[accessory.UUID]) {
|
|
205
|
+
this.addAccessDevice(accessory, device);
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
// Update the configuration on an existing Access device.
|
|
209
|
+
// eslint-disable-next-line camelcase
|
|
210
|
+
this.events.emit(AccessEventType.DEVICE_UPDATE, { data: device, event: AccessEventType.DEVICE_UPDATE, event_object_id: device.unique_id });
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
// Discover and sync UniFi Access devices between HomeKit and the Access controller.
|
|
214
|
+
discoverAndSyncAccessories() {
|
|
215
|
+
if (!this.udaApi.bootstrap) {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
if (this.udaApi.devices && !this.discoverDevices(this.udaApi.devices)) {
|
|
219
|
+
this.log.error("Error discovering devices.");
|
|
220
|
+
}
|
|
221
|
+
// Remove Access devices that are no longer found on this Access controller, but we still have in HomeKit.
|
|
222
|
+
this.cleanupDevices();
|
|
223
|
+
// Update our device information.
|
|
224
|
+
Object.keys(this.configuredDevices).map(x => this.configuredDevices[x]?.configureInfo());
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
// Cleanup removed Access devices from HomeKit.
|
|
228
|
+
cleanupDevices() {
|
|
229
|
+
// Process the device removal queue before we do anything else.
|
|
230
|
+
this.platform.accessories.filter(accessory => accessory.UUID in this.deviceRemovalQueue).map(accessory =>
|
|
231
|
+
// eslint-disable-next-line @stylistic/implicit-arrow-linebreak
|
|
232
|
+
this.removeHomeKitDevice(accessory, !this.platform.featureOptions.test("Device", (accessory.getService(this.hap.Service.AccessoryInformation)?.getCharacteristic(this.hap.Characteristic.SerialNumber).value ?? ""), this.id)));
|
|
233
|
+
for (const accessory of this.platform.accessories) {
|
|
234
|
+
const accessDevice = this.configuredDevices[accessory.UUID];
|
|
235
|
+
// Check to see if we have an orphan - where we haven't configured this in the plugin, but the accessory still exists in HomeKit. One example of when this might
|
|
236
|
+
// happen is when Homebridge might be shutdown and a device is then removed. When we start back up, the device still exists in HomeKit but not in Access. We
|
|
237
|
+
// catch those orphan devices here.
|
|
238
|
+
if (!accessDevice) {
|
|
239
|
+
this.removeHomeKitDevice(accessory, !this.platform.featureOptions.test("Device", (accessory.getService(this.hap.Service.AccessoryInformation)?.getCharacteristic(this.hap.Characteristic.SerialNumber).value ?? "")));
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
// If we don't have the Access bootstrap JSON available, we're done. We need to know what's on the Access controller in order to determine what to do with
|
|
243
|
+
// the accessories we know about.
|
|
244
|
+
if (!this.udaApi.bootstrap) {
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
// Check to see if the device still exists on the Access controller and the user has not chosen to hide it.
|
|
248
|
+
if (isSupportedDevice(accessDevice.uda) &&
|
|
249
|
+
this.udaApi.devices?.some((x) => x.mac.toLowerCase() === accessDevice.uda.mac.toLowerCase())) {
|
|
250
|
+
// In case we have previously queued a device for deletion, let's remove it from the queue since it's reappeared.
|
|
251
|
+
delete this.deviceRemovalQueue[accessDevice.accessory.UUID];
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
// Process the device removal.
|
|
255
|
+
this.removeHomeKitDevice(accessory, !this.hasFeature("Device", accessDevice.uda));
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// Utility to retrieve a reasonable device name for an Access device.
|
|
259
|
+
resolveDeviceName(device) {
|
|
260
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
261
|
+
return (device.alias?.length ? device.alias : device.name) ?? device.display_model ?? device.model ?? device.device_type ?? "Access Device";
|
|
262
|
+
}
|
|
263
|
+
// Utility to retrieve a reasonable device model for an Access device.
|
|
264
|
+
resolveDeviceModel(device) {
|
|
265
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
266
|
+
return device.display_model ?? device.model ?? device.device_type ?? "Unknown Model";
|
|
267
|
+
}
|
|
268
|
+
// Remove an individual Access device from HomeKit.
|
|
269
|
+
removeHomeKitDevice(accessory, noRemovalDelay = false) {
|
|
270
|
+
// Ensure that this accessory hasn't already been removed.
|
|
271
|
+
if (!this.platform.accessories.some(x => x.UUID === accessory.UUID)) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
// We only remove devices if they're on the Access controller we're interested in.
|
|
275
|
+
if (accessory.context.controller !== this.uda.host.mac) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const delayInterval = this.getFeatureNumber("Controller.DelayDeviceRemoval") ?? 0;
|
|
279
|
+
// For certain use cases, we may want to defer removal of an Access device where Access may lose track of devices for a brief period of time. This prevents a
|
|
280
|
+
// potential back-and-forth where devices are removed momentarily only to be readded later.
|
|
281
|
+
if (!noRemovalDelay && delayInterval) {
|
|
282
|
+
// Have we seen this device queued for removal previously? If not, let's add it to the queue and come back after our specified delay.
|
|
283
|
+
if (!this.deviceRemovalQueue[accessory.UUID]) {
|
|
284
|
+
this.deviceRemovalQueue[accessory.UUID] = Date.now();
|
|
285
|
+
this.log.info("%s: Delaying device removal for at least %s second%s.", accessory.displayName, delayInterval, delayInterval > 1 ? "s" : "");
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
// Is it time to process this device removal?
|
|
289
|
+
if ((delayInterval * 1000) > (Date.now() - this.deviceRemovalQueue[accessory.UUID])) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
// Cleanup after ourselves.
|
|
294
|
+
delete this.deviceRemovalQueue[accessory.UUID];
|
|
295
|
+
// Grab our instance of the Access device, if it exists.
|
|
296
|
+
const accessDevice = this.configuredDevices[accessory.UUID];
|
|
297
|
+
// See if we can pull the device's configuration details from our Access device instance or the controller.
|
|
298
|
+
const device = accessDevice?.uda ?? this.udaApi.devices?.find(dev => dev.unique_id === accessory.context.mac.toLowerCase()) ?? null;
|
|
299
|
+
this.log.info("%s: Removing %s from HomeKit.", device ? this.udaApi.getDeviceName(device) : accessDevice?.accessoryName ?? accessory.displayName, device?.display_model ?? "device");
|
|
300
|
+
// Cleanup our device instance.
|
|
301
|
+
accessDevice?.cleanup();
|
|
302
|
+
// Finally, remove it from our list of configured devices and HomeKit.
|
|
303
|
+
delete this.configuredDevices[accessory.UUID];
|
|
304
|
+
// Unregister the accessory and delete it's remnants from HomeKit and the plugin.
|
|
305
|
+
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
306
|
+
this.platform.accessories.splice(this.platform.accessories.indexOf(accessory), 1);
|
|
307
|
+
// Tell Homebridge to save the updated list of accessories.
|
|
308
|
+
this.api.updatePlatformAccessories(this.platform.accessories);
|
|
309
|
+
}
|
|
310
|
+
// Reauthenticate with the controller.
|
|
311
|
+
async resetControllerConnection() {
|
|
312
|
+
// Clear our login credentials and statistics.
|
|
313
|
+
this.udaApi.reset();
|
|
314
|
+
// Bootstrap the Access controller.
|
|
315
|
+
await this.bootstrapController();
|
|
316
|
+
}
|
|
317
|
+
// Lookup a device by it's identifier and return it if it exists.
|
|
318
|
+
deviceLookup(deviceId) {
|
|
319
|
+
// Find the device.
|
|
320
|
+
const foundDevice = Object.keys(this.configuredDevices).find(x => this.configuredDevices[x]?.uda.unique_id === deviceId);
|
|
321
|
+
return foundDevice ? this.configuredDevices[foundDevice] : null;
|
|
322
|
+
}
|
|
323
|
+
// Utility function to return a floating point configuration parameter on a device.
|
|
324
|
+
getFeatureFloat(option) {
|
|
325
|
+
return this.platform.featureOptions.getFloat(option, this.id);
|
|
326
|
+
}
|
|
327
|
+
// Utility function to return an integer configuration parameter on a device.
|
|
328
|
+
getFeatureNumber(option) {
|
|
329
|
+
return this.platform.featureOptions.getInteger(option, this.id);
|
|
330
|
+
}
|
|
331
|
+
// Utility for checking feature options on the controller.
|
|
332
|
+
hasFeature(option, device) {
|
|
333
|
+
const deviceMac = device?.mac;
|
|
334
|
+
return this.platform.featureOptions.test(option, deviceMac ? normalizeMac(deviceMac) : this.id, this.id);
|
|
335
|
+
}
|
|
336
|
+
// Return a unique identifier for an Access controller.
|
|
337
|
+
get id() {
|
|
338
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
339
|
+
return this.uda.host?.mac ? normalizeMac(this.uda.host.mac) : undefined;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
//# sourceMappingURL=access-controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-controller.js","sourceRoot":"","sources":["../src/access-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type SensorInput = "Dps" | "Rel" | "Ren" | "Rex";
|
|
2
|
+
type ProxyMode = "dps" | "rex";
|
|
3
|
+
export interface SensorConfig {
|
|
4
|
+
configKey?: string;
|
|
5
|
+
proxyMode?: ProxyMode;
|
|
6
|
+
wiringKeys?: string[];
|
|
7
|
+
}
|
|
8
|
+
interface SideDoorConfig {
|
|
9
|
+
dpsConfigKey: string;
|
|
10
|
+
dpsWiringKeys: string[];
|
|
11
|
+
lockRelayConfigKey: string;
|
|
12
|
+
}
|
|
13
|
+
export interface DeviceCatalogEntry {
|
|
14
|
+
appendsSourceId: boolean;
|
|
15
|
+
defaultDoorService: "Lock" | "GarageDoorOpener";
|
|
16
|
+
displayModel: string;
|
|
17
|
+
hasDps: boolean;
|
|
18
|
+
hasRel: boolean;
|
|
19
|
+
hasRen: boolean;
|
|
20
|
+
hasRex: boolean;
|
|
21
|
+
lockRelayConfigKey: string;
|
|
22
|
+
sensors: Partial<Record<SensorInput, SensorConfig>>;
|
|
23
|
+
sideDoor?: SideDoorConfig;
|
|
24
|
+
skipsV1LockEvents: boolean;
|
|
25
|
+
supportsSideDoor: boolean;
|
|
26
|
+
usesConfigsApi: boolean;
|
|
27
|
+
usesLocationApi: boolean;
|
|
28
|
+
usesProxyMode: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare const UGT_MAIN_PORT_SOURCE_ID = "port1";
|
|
31
|
+
export declare const UGT_SIDE_PORT_SOURCE_ID = "port2";
|
|
32
|
+
export declare const UGT_SIDE_DOOR_TARGET_NAME = "oper2";
|
|
33
|
+
export declare const deviceCatalog: Readonly<Record<string, DeviceCatalogEntry>>;
|
|
34
|
+
export declare function getDeviceCatalog(deviceType: string): DeviceCatalogEntry | undefined;
|
|
35
|
+
export declare function getSensorConfig(deviceType: string, sensor: SensorInput): SensorConfig | undefined;
|
|
36
|
+
export declare const modelsDps: string[];
|
|
37
|
+
export declare const modelsRel: string[];
|
|
38
|
+
export declare const modelsRen: string[];
|
|
39
|
+
export declare const modelsRex: string[];
|
|
40
|
+
export declare const modelsSideDoor: string[];
|
|
41
|
+
export declare const modelsDefaultGarageDoor: string[];
|
|
42
|
+
export declare const modelsDefaultLock: string[];
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/* Copyright(C) 2026, Mickael Palma. All rights reserved.
|
|
2
|
+
*
|
|
3
|
+
* access-device-catalog.ts: Device catalog for UniFi Access - single source of truth for all device-specific knowledge.
|
|
4
|
+
*/
|
|
5
|
+
// UGT port and extension identifiers used when mapping physical doors to location IDs.
|
|
6
|
+
export const UGT_MAIN_PORT_SOURCE_ID = "port1";
|
|
7
|
+
export const UGT_SIDE_PORT_SOURCE_ID = "port2";
|
|
8
|
+
export const UGT_SIDE_DOOR_TARGET_NAME = "oper2";
|
|
9
|
+
// The device catalog, keyed by device_type. This is the single source of truth for all device-specific knowledge in the plugin.
|
|
10
|
+
export const deviceCatalog = {
|
|
11
|
+
"UA-Hub-Door-Mini": {
|
|
12
|
+
appendsSourceId: false,
|
|
13
|
+
defaultDoorService: "Lock",
|
|
14
|
+
displayModel: "UA Hub Door Mini",
|
|
15
|
+
hasDps: true,
|
|
16
|
+
hasRel: false,
|
|
17
|
+
hasRen: false,
|
|
18
|
+
hasRex: true,
|
|
19
|
+
lockRelayConfigKey: "output_d1_lock_relay",
|
|
20
|
+
sensors: {
|
|
21
|
+
Dps: { configKey: "input_d1_dps", wiringKeys: ["wiring_state_d1-dps-neg", "wiring_state_d1-dps-pos"] },
|
|
22
|
+
Rex: { configKey: "input_d1_button", wiringKeys: ["wiring_state_d1-button-neg", "wiring_state_d1-button-pos"] }
|
|
23
|
+
},
|
|
24
|
+
skipsV1LockEvents: false,
|
|
25
|
+
supportsSideDoor: false,
|
|
26
|
+
usesConfigsApi: false,
|
|
27
|
+
usesLocationApi: false,
|
|
28
|
+
usesProxyMode: false
|
|
29
|
+
},
|
|
30
|
+
"UA-ULTRA": {
|
|
31
|
+
appendsSourceId: false,
|
|
32
|
+
defaultDoorService: "Lock",
|
|
33
|
+
displayModel: "UA Ultra",
|
|
34
|
+
hasDps: true,
|
|
35
|
+
hasRel: false,
|
|
36
|
+
hasRen: false,
|
|
37
|
+
hasRex: true,
|
|
38
|
+
lockRelayConfigKey: "output_d1_lock_relay",
|
|
39
|
+
sensors: {
|
|
40
|
+
Dps: { configKey: "input_d1_dps", proxyMode: "dps" },
|
|
41
|
+
Rex: { configKey: "input_d1_button", proxyMode: "rex" }
|
|
42
|
+
},
|
|
43
|
+
skipsV1LockEvents: false,
|
|
44
|
+
supportsSideDoor: false,
|
|
45
|
+
usesConfigsApi: false,
|
|
46
|
+
usesLocationApi: false,
|
|
47
|
+
usesProxyMode: true
|
|
48
|
+
},
|
|
49
|
+
"UAH": {
|
|
50
|
+
appendsSourceId: false,
|
|
51
|
+
defaultDoorService: "Lock",
|
|
52
|
+
displayModel: "UA Hub",
|
|
53
|
+
hasDps: true,
|
|
54
|
+
hasRel: true,
|
|
55
|
+
hasRen: true,
|
|
56
|
+
hasRex: true,
|
|
57
|
+
lockRelayConfigKey: "input_state_rly-lock_dry",
|
|
58
|
+
sensors: {
|
|
59
|
+
Dps: { configKey: "input_state_dps", wiringKeys: ["wiring_state_dps-neg", "wiring_state_dps-pos"] },
|
|
60
|
+
Rel: { configKey: "input_state_rel", wiringKeys: ["wiring_state_rel-neg", "wiring_state_rel-pos"] },
|
|
61
|
+
Ren: { configKey: "input_state_ren", wiringKeys: ["wiring_state_ren-neg", "wiring_state_ren-pos"] },
|
|
62
|
+
Rex: { configKey: "input_state_rex", wiringKeys: ["wiring_state_rex-neg", "wiring_state_rex-pos"] }
|
|
63
|
+
},
|
|
64
|
+
skipsV1LockEvents: false,
|
|
65
|
+
supportsSideDoor: false,
|
|
66
|
+
usesConfigsApi: false,
|
|
67
|
+
usesLocationApi: false,
|
|
68
|
+
usesProxyMode: false
|
|
69
|
+
},
|
|
70
|
+
"UAH-Ent": {
|
|
71
|
+
appendsSourceId: true,
|
|
72
|
+
defaultDoorService: "Lock",
|
|
73
|
+
displayModel: "UA Hub Enterprise",
|
|
74
|
+
hasDps: true,
|
|
75
|
+
hasRel: true,
|
|
76
|
+
hasRen: true,
|
|
77
|
+
hasRex: true,
|
|
78
|
+
lockRelayConfigKey: "input_state_rly-lock_dry",
|
|
79
|
+
sensors: {
|
|
80
|
+
Dps: { configKey: "input_state_dps", wiringKeys: ["wiring_state_dps-neg", "wiring_state_dps-pos"] },
|
|
81
|
+
Rel: { configKey: "input_state_rel", wiringKeys: ["wiring_state_rel-neg", "wiring_state_rel-pos"] },
|
|
82
|
+
Ren: { configKey: "input_state_ren", wiringKeys: ["wiring_state_ren-neg", "wiring_state_ren-pos"] },
|
|
83
|
+
Rex: { configKey: "input_state_rex", wiringKeys: ["wiring_state_rex-neg", "wiring_state_rex-pos"] }
|
|
84
|
+
},
|
|
85
|
+
skipsV1LockEvents: false,
|
|
86
|
+
supportsSideDoor: false,
|
|
87
|
+
usesConfigsApi: false,
|
|
88
|
+
usesLocationApi: false,
|
|
89
|
+
usesProxyMode: false
|
|
90
|
+
},
|
|
91
|
+
"UGT": {
|
|
92
|
+
appendsSourceId: false,
|
|
93
|
+
defaultDoorService: "GarageDoorOpener",
|
|
94
|
+
displayModel: "UA Gate",
|
|
95
|
+
hasDps: true,
|
|
96
|
+
hasRel: false,
|
|
97
|
+
hasRen: false,
|
|
98
|
+
hasRex: false,
|
|
99
|
+
lockRelayConfigKey: "output_oper1_relay",
|
|
100
|
+
sensors: {
|
|
101
|
+
Dps: { configKey: "input_gate_dps", wiringKeys: ["wiring_state_gate-dps-neg", "wiring_state_gate-dps-pos"] }
|
|
102
|
+
},
|
|
103
|
+
sideDoor: {
|
|
104
|
+
dpsConfigKey: "input_door_dps",
|
|
105
|
+
dpsWiringKeys: ["wiring_state_door-dps-neg", "wiring_state_door-dps-pos"],
|
|
106
|
+
lockRelayConfigKey: "output_oper2_relay"
|
|
107
|
+
},
|
|
108
|
+
skipsV1LockEvents: true,
|
|
109
|
+
supportsSideDoor: true,
|
|
110
|
+
usesConfigsApi: false,
|
|
111
|
+
usesLocationApi: true,
|
|
112
|
+
usesProxyMode: false
|
|
113
|
+
},
|
|
114
|
+
"UVC G6 Entry": {
|
|
115
|
+
appendsSourceId: false,
|
|
116
|
+
defaultDoorService: "Lock",
|
|
117
|
+
displayModel: "UVC G6 Entry",
|
|
118
|
+
hasDps: false,
|
|
119
|
+
hasRel: false,
|
|
120
|
+
hasRen: false,
|
|
121
|
+
hasRex: false,
|
|
122
|
+
lockRelayConfigKey: "input_state_rly-lock_dry",
|
|
123
|
+
sensors: {},
|
|
124
|
+
skipsV1LockEvents: false,
|
|
125
|
+
supportsSideDoor: false,
|
|
126
|
+
usesConfigsApi: true,
|
|
127
|
+
usesLocationApi: false,
|
|
128
|
+
usesProxyMode: false
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
// Look up a device catalog entry by device_type. Returns undefined for unknown devices.
|
|
132
|
+
export function getDeviceCatalog(deviceType) {
|
|
133
|
+
return deviceCatalog[deviceType];
|
|
134
|
+
}
|
|
135
|
+
// Look up sensor configuration for a specific device and sensor input.
|
|
136
|
+
export function getSensorConfig(deviceType, sensor) {
|
|
137
|
+
return getDeviceCatalog(deviceType)?.sensors[sensor];
|
|
138
|
+
}
|
|
139
|
+
// Returns an array of display_model strings for devices that match a given predicate.
|
|
140
|
+
function modelsWithCapability(predicate) {
|
|
141
|
+
return Object.values(deviceCatalog).filter(predicate).map(entry => entry.displayModel);
|
|
142
|
+
}
|
|
143
|
+
// Pre-computed model arrays, replacing the hardcoded arrays in access-options.ts.
|
|
144
|
+
export const modelsDps = modelsWithCapability(e => e.hasDps);
|
|
145
|
+
export const modelsRel = modelsWithCapability(e => e.hasRel);
|
|
146
|
+
export const modelsRen = modelsWithCapability(e => e.hasRen);
|
|
147
|
+
export const modelsRex = modelsWithCapability(e => e.hasRex);
|
|
148
|
+
export const modelsSideDoor = modelsWithCapability(e => e.supportsSideDoor);
|
|
149
|
+
export const modelsDefaultGarageDoor = modelsWithCapability(e => e.defaultDoorService === "GarageDoorOpener");
|
|
150
|
+
export const modelsDefaultLock = modelsWithCapability(e => (e.defaultDoorService === "Lock") && !e.appendsSourceId && !e.usesConfigsApi);
|
|
151
|
+
//# sourceMappingURL=access-device-catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-device-catalog.js","sourceRoot":"","sources":["../src/access-device-catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { API, HAP, PlatformAccessory } from "homebridge";
|
|
2
|
+
import type { AccessApi, AccessDeviceConfig, AccessEventPacket } from "unifi-access";
|
|
3
|
+
import { type HomebridgePluginLogging, type Nullable } from "homebridge-plugin-utils";
|
|
4
|
+
import type { AccessController } from "./access-controller.js";
|
|
5
|
+
import type { AccessPlatform } from "./access-platform.js";
|
|
6
|
+
export interface AccessHints {
|
|
7
|
+
enabled: boolean;
|
|
8
|
+
hasMethodFace: boolean;
|
|
9
|
+
hasMethodHand: boolean;
|
|
10
|
+
hasMethodMobile: boolean;
|
|
11
|
+
hasMethodNfc: boolean;
|
|
12
|
+
hasMethodPin: boolean;
|
|
13
|
+
hasMethodQr: boolean;
|
|
14
|
+
hasMethodTwoStep: boolean;
|
|
15
|
+
hasSideDoor: boolean;
|
|
16
|
+
hasWiringDps: boolean;
|
|
17
|
+
hasWiringRel: boolean;
|
|
18
|
+
hasWiringRen: boolean;
|
|
19
|
+
hasWiringRex: boolean;
|
|
20
|
+
hasWiringSideDoorDps: boolean;
|
|
21
|
+
ledStatus: boolean;
|
|
22
|
+
logDoorbell: boolean;
|
|
23
|
+
logDps: boolean;
|
|
24
|
+
logLock: boolean;
|
|
25
|
+
logMotion: boolean;
|
|
26
|
+
logRel: boolean;
|
|
27
|
+
logRen: boolean;
|
|
28
|
+
logRex: boolean;
|
|
29
|
+
motionDuration: number;
|
|
30
|
+
occupancyDuration: number;
|
|
31
|
+
syncName: boolean;
|
|
32
|
+
}
|
|
33
|
+
export declare abstract class AccessBase {
|
|
34
|
+
readonly api: API;
|
|
35
|
+
readonly hap: HAP;
|
|
36
|
+
readonly log: HomebridgePluginLogging;
|
|
37
|
+
readonly controller: AccessController;
|
|
38
|
+
udaApi: AccessApi;
|
|
39
|
+
readonly platform: AccessPlatform;
|
|
40
|
+
constructor(controller: AccessController);
|
|
41
|
+
protected setInfo(accessory: PlatformAccessory, device: AccessDeviceConfig): boolean;
|
|
42
|
+
get name(): string;
|
|
43
|
+
}
|
|
44
|
+
export declare abstract class AccessDevice extends AccessBase {
|
|
45
|
+
accessory: PlatformAccessory;
|
|
46
|
+
hints: AccessHints;
|
|
47
|
+
listeners: Record<string, (packet: AccessEventPacket) => void>;
|
|
48
|
+
abstract uda: AccessDeviceConfig;
|
|
49
|
+
constructor(controller: AccessController, accessory: PlatformAccessory);
|
|
50
|
+
protected configureHints(): boolean;
|
|
51
|
+
configureInfo(): boolean;
|
|
52
|
+
cleanup(): void;
|
|
53
|
+
protected configureMotionSensor(isEnabled?: boolean): boolean;
|
|
54
|
+
private configureMotionSwitch;
|
|
55
|
+
private configureMotionTrigger;
|
|
56
|
+
private configureMqttMotionTrigger;
|
|
57
|
+
protected configureOccupancySensor(isEnabled?: boolean): boolean;
|
|
58
|
+
getFeatureFloat(option: string): Nullable<number | undefined>;
|
|
59
|
+
getFeatureNumber(option: string): Nullable<number | undefined>;
|
|
60
|
+
getFeatureValue(option: string): Nullable<string | undefined>;
|
|
61
|
+
hasFeature(option: string): boolean;
|
|
62
|
+
isReservedName(name: string | undefined): boolean;
|
|
63
|
+
get isOnline(): boolean;
|
|
64
|
+
get id(): string;
|
|
65
|
+
get name(): string;
|
|
66
|
+
get accessoryName(): string;
|
|
67
|
+
set accessoryName(name: string);
|
|
68
|
+
}
|