@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,35 @@
|
|
|
1
|
+
import { AccessReservedNames } from "../access-types.js";
|
|
2
|
+
// Access methods available to us for readers.
|
|
3
|
+
export const accessMethods = [
|
|
4
|
+
{ capability: "identity_face_unlock", key: "face", name: "Face Unlock", option: "AccessMethod.Face", subtype: AccessReservedNames.SWITCH_ACCESSMETHOD_FACE },
|
|
5
|
+
{ capability: "hand_wave", key: "wave", name: "Hand Wave", option: "AccessMethod.Hand", subtype: AccessReservedNames.SWITCH_ACCESSMETHOD_HAND },
|
|
6
|
+
{ capability: ["mobile_unlock_ver2", "support_mobile_unlock"], configsApiKeys: ["bt", "bt_button", "bt_tap"], key: "bt_button",
|
|
7
|
+
name: "Mobile", option: "AccessMethod.Mobile", subtype: AccessReservedNames.SWITCH_ACCESSMETHOD_MOBILE },
|
|
8
|
+
{ capability: "nfc_card_easy_provision", key: "nfc", name: "NFC", option: "AccessMethod.NFC", subtype: AccessReservedNames.SWITCH_ACCESSMETHOD_NFC },
|
|
9
|
+
{ capability: "pin_code", key: "pin_code", name: "PIN", option: "AccessMethod.PIN", subtype: AccessReservedNames.SWITCH_ACCESSMETHOD_PIN },
|
|
10
|
+
{ capability: "qr_code", key: "qr_code", name: "QR Code", option: "AccessMethod.QR", subtype: AccessReservedNames.SWITCH_ACCESSMETHOD_QR },
|
|
11
|
+
{ capability: "support_apple_pass", key: "apple_pass", name: "TouchPass", option: "AccessMethod.TouchPass", subtype: AccessReservedNames.SWITCH_ACCESSMETHOD_TOUCHPASS }
|
|
12
|
+
];
|
|
13
|
+
// Define the dry contact inputs we're interested in for Access hubs.
|
|
14
|
+
export const sensorInputs = ["Dps", "Rel", "Ren", "Rex"];
|
|
15
|
+
// Constants for timing.
|
|
16
|
+
export const AUTO_LOCK_DELAY_MS = 5000;
|
|
17
|
+
export const GATE_TRANSITION_COOLDOWN_MS = 5000;
|
|
18
|
+
// Retrieve a config value by key from the Access device configs array.
|
|
19
|
+
export function getConfigValue(configs, key) {
|
|
20
|
+
return configs?.find(entry => entry.key === key)?.value;
|
|
21
|
+
}
|
|
22
|
+
// Check if all wiring keys are active ("on") in the Access device configs.
|
|
23
|
+
export function areWiringKeysActive(configs, wiringKeys) {
|
|
24
|
+
return wiringKeys.every(wire => configs?.some(e => (e.key === wire) && (e.value === "on")));
|
|
25
|
+
}
|
|
26
|
+
// Proxy mode configuration key for UA Ultra devices.
|
|
27
|
+
export const REX_BUTTON_MODE_CONFIG_KEY = "rex_button_mode";
|
|
28
|
+
// Terminal input definitions shared by configureTerminalInputs and handleDeviceUpdate.
|
|
29
|
+
export const terminalInputs = [
|
|
30
|
+
{ input: "Dps", label: "Door Position Sensor", topic: "dps" },
|
|
31
|
+
{ input: "Rel", label: "Remote Release", topic: "rel" },
|
|
32
|
+
{ input: "Ren", label: "Request to Enter Sensor", topic: "ren" },
|
|
33
|
+
{ input: "Rex", label: "Request to Exit Sensor", topic: "rex" }
|
|
34
|
+
];
|
|
35
|
+
//# sourceMappingURL=access-hub-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-hub-types.js","sourceRoot":"","sources":["../../src/hub/access-hub-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CharacteristicValue } from "homebridge";
|
|
2
|
+
import type { SensorInput } from "../access-device-catalog.js";
|
|
3
|
+
import { AccessReservedNames } from "../access-types.js";
|
|
4
|
+
import { type DoorServiceType } from "./access-hub-types.js";
|
|
5
|
+
import type { AccessHub } from "./access-hub.js";
|
|
6
|
+
export declare function toLockState(hub: AccessHub, lockValue: "locked" | "unlocked" | "lock" | "unlock"): CharacteristicValue;
|
|
7
|
+
export declare function toDpsState(hub: AccessHub, dpsValue: "open" | "close"): CharacteristicValue;
|
|
8
|
+
export declare function isLocked(hub: AccessHub, state: CharacteristicValue): boolean;
|
|
9
|
+
export declare function isClosed(hub: AccessHub, state: CharacteristicValue): boolean;
|
|
10
|
+
export declare function doorServiceType(hub: AccessHub): DoorServiceType;
|
|
11
|
+
export declare function hasCapability(hub: AccessHub, capability: string | readonly string[]): boolean;
|
|
12
|
+
export declare function isWired(hub: AccessHub, input: SensorInput): boolean;
|
|
13
|
+
export declare function isSideDoorDpsWired(hub: AccessHub): boolean;
|
|
14
|
+
export declare function checkUltraInputs(hub: AccessHub): void;
|
|
15
|
+
export declare function hubInputState(hub: AccessHub, input: SensorInput): CharacteristicValue;
|
|
16
|
+
export declare function hubDpsState(hub: AccessHub, isSideDoor?: boolean): CharacteristicValue;
|
|
17
|
+
export declare function hubLockState(hub: AccessHub, isSideDoor?: boolean): CharacteristicValue;
|
|
18
|
+
export declare function getContactSensorState(hub: AccessHub, name: AccessReservedNames): CharacteristicValue;
|
|
19
|
+
export declare function setContactSensorState(hub: AccessHub, name: AccessReservedNames, value: CharacteristicValue): void;
|
|
20
|
+
export declare function logLockDelayInterval(hub: AccessHub, doorLabel: string): void;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { REX_BUTTON_MODE_CONFIG_KEY, areWiringKeysActive, getConfigValue } from "./access-hub-types.js";
|
|
2
|
+
// Convert lock string value to HomeKit LockCurrentState.
|
|
3
|
+
export function toLockState(hub, lockValue) {
|
|
4
|
+
return ["unlock", "unlocked"].includes(lockValue) ? hub.hap.Characteristic.LockCurrentState.UNSECURED : hub.hap.Characteristic.LockCurrentState.SECURED;
|
|
5
|
+
}
|
|
6
|
+
// Convert DPS string value to HomeKit ContactSensorState.
|
|
7
|
+
export function toDpsState(hub, dpsValue) {
|
|
8
|
+
return dpsValue === "open" ? hub.hap.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED : hub.hap.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
9
|
+
}
|
|
10
|
+
// Check if a lock state represents "locked".
|
|
11
|
+
export function isLocked(hub, state) {
|
|
12
|
+
return state === hub.hap.Characteristic.LockCurrentState.SECURED;
|
|
13
|
+
}
|
|
14
|
+
// Check if a DPS state represents "closed" (contact detected).
|
|
15
|
+
export function isClosed(hub, state) {
|
|
16
|
+
return state === hub.hap.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
17
|
+
}
|
|
18
|
+
// Return the door service type from configuration. UA Gate devices default to GarageDoorOpener and can be overridden to Lock. Other hubs default to Lock and can be
|
|
19
|
+
// overridden to GarageDoorOpener.
|
|
20
|
+
export function doorServiceType(hub) {
|
|
21
|
+
if (hub.catalog.defaultDoorService === "GarageDoorOpener") {
|
|
22
|
+
return hub.hasFeature("Hub.Door.UseLock") ? "Lock" : "GarageDoorOpener";
|
|
23
|
+
}
|
|
24
|
+
return hub.hasFeature("Hub.Door.UseGarageOpener") ? "GarageDoorOpener" : "Lock";
|
|
25
|
+
}
|
|
26
|
+
// Utility to validate hub capabilities.
|
|
27
|
+
export function hasCapability(hub, capability) {
|
|
28
|
+
return Array.isArray(capability) ? capability.some(c => hub.uda.capabilities.includes(c)) : hub.uda.capabilities.includes(capability);
|
|
29
|
+
}
|
|
30
|
+
// Utility to check the wiring state of a given terminal input.
|
|
31
|
+
export function isWired(hub, input) {
|
|
32
|
+
const sensorConfig = hub.catalog.sensors[input];
|
|
33
|
+
if (!sensorConfig) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
// Proxy mode devices use extension config instead of wiring keys.
|
|
37
|
+
if (sensorConfig.proxyMode) {
|
|
38
|
+
return hub.uda.extensions?.[0]?.target_config?.some(e => (e.config_key === REX_BUTTON_MODE_CONFIG_KEY) && (e.config_value === sensorConfig.proxyMode)) ?? false;
|
|
39
|
+
}
|
|
40
|
+
if (!sensorConfig.wiringKeys) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return areWiringKeysActive(hub.uda.configs, sensorConfig.wiringKeys);
|
|
44
|
+
}
|
|
45
|
+
// Return the wiring state of the side door DPS.
|
|
46
|
+
export function isSideDoorDpsWired(hub) {
|
|
47
|
+
const wiringKeys = hub.catalog.sideDoor?.dpsWiringKeys;
|
|
48
|
+
if (!wiringKeys) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return areWiringKeysActive(hub.uda.configs, wiringKeys);
|
|
52
|
+
}
|
|
53
|
+
// Check and validate proxy mode inputs with what the user has configured in HomeKit.
|
|
54
|
+
export function checkUltraInputs(hub) {
|
|
55
|
+
for (const input of ["Dps", "Rex"]) {
|
|
56
|
+
const hint = ("hasWiring" + input);
|
|
57
|
+
const sensorConfig = hub.catalog.sensors[input];
|
|
58
|
+
if (!sensorConfig?.proxyMode) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
// Is the mode enabled on the hub?
|
|
62
|
+
const isEnabled = hub.uda.extensions?.[0]?.target_config
|
|
63
|
+
?.some(entry => (entry.config_key === REX_BUTTON_MODE_CONFIG_KEY) && (entry.config_value === sensorConfig.proxyMode));
|
|
64
|
+
if (hub.hints[hint] && !isEnabled) {
|
|
65
|
+
// The hub has disabled this input.
|
|
66
|
+
hub.hints[hint] = false;
|
|
67
|
+
}
|
|
68
|
+
else if (!hub.hints[hint] && isEnabled && hub.hasFeature("Hub." + input.toUpperCase())) {
|
|
69
|
+
// The hub has the input enabled, and we want it enabled in HomeKit.
|
|
70
|
+
hub.hints[hint] = true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Return the current state of a terminal input sensor on the hub. Checks wiring first and returns CONTACT_DETECTED if not wired.
|
|
75
|
+
export function hubInputState(hub, input) {
|
|
76
|
+
if (!isWired(hub, input)) {
|
|
77
|
+
return hub.hap.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
78
|
+
}
|
|
79
|
+
const configKey = hub.catalog.sensors[input]?.configKey;
|
|
80
|
+
if (!configKey) {
|
|
81
|
+
return hub.hap.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
82
|
+
}
|
|
83
|
+
return (getConfigValue(hub.uda.configs, configKey) === "on") ? hub.hap.Characteristic.ContactSensorState.CONTACT_DETECTED :
|
|
84
|
+
hub.hap.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
|
|
85
|
+
}
|
|
86
|
+
// Return the current state of the DPS on the hub.
|
|
87
|
+
export function hubDpsState(hub, isSideDoor = false) {
|
|
88
|
+
if (isSideDoor) {
|
|
89
|
+
if (!isSideDoorDpsWired(hub)) {
|
|
90
|
+
return hub.hap.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
91
|
+
}
|
|
92
|
+
const configKey = hub.catalog.sideDoor?.dpsConfigKey;
|
|
93
|
+
if (!configKey) {
|
|
94
|
+
return hub.hap.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
95
|
+
}
|
|
96
|
+
return (getConfigValue(hub.uda.configs, configKey) === "on") ? hub.hap.Characteristic.ContactSensorState.CONTACT_DETECTED :
|
|
97
|
+
hub.hap.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
|
|
98
|
+
}
|
|
99
|
+
return hubInputState(hub, "Dps");
|
|
100
|
+
}
|
|
101
|
+
// Return the current state of the relay lock on the hub.
|
|
102
|
+
export function hubLockState(hub, isSideDoor = false) {
|
|
103
|
+
const configKey = isSideDoor ? hub.catalog.sideDoor?.lockRelayConfigKey : hub.catalog.lockRelayConfigKey;
|
|
104
|
+
if (!configKey) {
|
|
105
|
+
return hub.hap.Characteristic.LockCurrentState.SECURED;
|
|
106
|
+
}
|
|
107
|
+
const lockRelayValue = getConfigValue(hub.uda.configs, configKey);
|
|
108
|
+
return (lockRelayValue === "off") ? hub.hap.Characteristic.LockCurrentState.SECURED : hub.hap.Characteristic.LockCurrentState.UNSECURED;
|
|
109
|
+
}
|
|
110
|
+
// Utility to retrieve a contact sensor state.
|
|
111
|
+
export function getContactSensorState(hub, name) {
|
|
112
|
+
return hub.accessory.getServiceById(hub.hap.Service.ContactSensor, name)?.getCharacteristic(hub.hap.Characteristic.ContactSensorState).value ??
|
|
113
|
+
hub.hap.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
|
|
114
|
+
}
|
|
115
|
+
// Utility to set a contact sensor state.
|
|
116
|
+
export function setContactSensorState(hub, name, value) {
|
|
117
|
+
hub.accessory.getServiceById(hub.hap.Service.ContactSensor, name)?.updateCharacteristic(hub.hap.Characteristic.ContactSensorState, value);
|
|
118
|
+
}
|
|
119
|
+
// Log the lock delay interval configuration for a door.
|
|
120
|
+
export function logLockDelayInterval(hub, doorLabel) {
|
|
121
|
+
if (hub.lockDelayInterval === undefined) {
|
|
122
|
+
hub.log.info("The %s lock relay will lock five seconds after unlocking in HomeKit.", doorLabel);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
hub.log.info("The %s lock relay will remain unlocked %s after unlocking in HomeKit.", doorLabel, hub.lockDelayInterval === 0 ? "indefinitely" : "for " + hub.lockDelayInterval.toString() + " minutes");
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=access-hub-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-hub-utils.js","sourceRoot":"","sources":["../../src/hub/access-hub-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AccessDeviceConfig } from "unifi-access";
|
|
2
|
+
import type { CharacteristicValue, PlatformAccessory } from "homebridge";
|
|
3
|
+
import { type DeviceCatalogEntry } from "../access-device-catalog.js";
|
|
4
|
+
import type { AccessController } from "../access-controller.js";
|
|
5
|
+
import { AccessDevice } from "../access-device.js";
|
|
6
|
+
import { type AccessHubHKProps, type AccessHubWiredProps, type HubEventKey, type HubEventMap, type KeyOf } from "./access-hub-types.js";
|
|
7
|
+
export interface AccessHub extends AccessHubHKProps, AccessHubWiredProps {
|
|
8
|
+
}
|
|
9
|
+
export type HkStateKey = KeyOf<AccessHub, "hk", "State">;
|
|
10
|
+
declare class HubEventBus {
|
|
11
|
+
private readonly emitter;
|
|
12
|
+
emit<K extends HubEventKey>(event: K, data: HubEventMap[K]): void;
|
|
13
|
+
on<K extends HubEventKey>(event: K, handler: (data: HubEventMap[K]) => void): void;
|
|
14
|
+
}
|
|
15
|
+
export declare class AccessHub extends AccessDevice {
|
|
16
|
+
_hkDpsState: CharacteristicValue;
|
|
17
|
+
_hkLockState: CharacteristicValue;
|
|
18
|
+
_hkSideDoorDpsState: CharacteristicValue;
|
|
19
|
+
_hkSideDoorLockState: CharacteristicValue;
|
|
20
|
+
readonly catalog: DeviceCatalogEntry;
|
|
21
|
+
doorbellRingRequestId: string | null;
|
|
22
|
+
gateTransitionUntil: number;
|
|
23
|
+
lockDelayInterval: number | undefined;
|
|
24
|
+
mainDoorLocationId: string | undefined;
|
|
25
|
+
sideDoorLocationId: string | undefined;
|
|
26
|
+
sideDoorGateTransitionUntil: number;
|
|
27
|
+
uda: AccessDeviceConfig;
|
|
28
|
+
readonly hubEvents: HubEventBus;
|
|
29
|
+
constructor(controller: AccessController, device: AccessDeviceConfig, accessory: PlatformAccessory);
|
|
30
|
+
protected configureHints(): boolean;
|
|
31
|
+
private configureDevice;
|
|
32
|
+
get hkDpsState(): CharacteristicValue;
|
|
33
|
+
set hkDpsState(value: CharacteristicValue);
|
|
34
|
+
get hkLockState(): CharacteristicValue;
|
|
35
|
+
set hkLockState(value: CharacteristicValue);
|
|
36
|
+
get hkSideDoorLockState(): CharacteristicValue;
|
|
37
|
+
set hkSideDoorLockState(value: CharacteristicValue);
|
|
38
|
+
}
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/* Copyright(C) 2026, Mickael Palma. All rights reserved.
|
|
2
|
+
*
|
|
3
|
+
* access-hub.ts: Core hub class for UniFi Access. State management, construction, orchestration, and static property definitions.
|
|
4
|
+
*/
|
|
5
|
+
import { EventEmitter } from "events";
|
|
6
|
+
import { getDeviceCatalog } from "../access-device-catalog.js";
|
|
7
|
+
import { AccessDevice } from "../access-device.js";
|
|
8
|
+
import { AccessReservedNames } from "../access-types.js";
|
|
9
|
+
import { sensorInputs } from "./access-hub-types.js";
|
|
10
|
+
import { discoverDoorIds } from "./access-hub-api.js";
|
|
11
|
+
import { registerEventHandlers } from "./access-hub-events.js";
|
|
12
|
+
import { configureMqtt } from "./access-hub-mqtt.js";
|
|
13
|
+
import { configureServices, registerServiceReactions } from "./access-hub-services.js";
|
|
14
|
+
import { checkUltraInputs, getContactSensorState, hubDpsState, hubLockState, isWired, logLockDelayInterval, setContactSensorState } from "./access-hub-utils.js";
|
|
15
|
+
// Typed event emitter wrapper for the hub event bus.
|
|
16
|
+
class HubEventBus {
|
|
17
|
+
emitter = new EventEmitter();
|
|
18
|
+
emit(event, data) {
|
|
19
|
+
this.emitter.emit(event, data);
|
|
20
|
+
}
|
|
21
|
+
on(event, handler) {
|
|
22
|
+
this.emitter.on(event, handler);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export class AccessHub extends AccessDevice {
|
|
26
|
+
// State backing fields - public for module access.
|
|
27
|
+
_hkDpsState;
|
|
28
|
+
_hkLockState;
|
|
29
|
+
_hkSideDoorDpsState;
|
|
30
|
+
_hkSideDoorLockState;
|
|
31
|
+
// Device configuration - public for module access.
|
|
32
|
+
catalog;
|
|
33
|
+
doorbellRingRequestId;
|
|
34
|
+
gateTransitionUntil;
|
|
35
|
+
lockDelayInterval;
|
|
36
|
+
mainDoorLocationId;
|
|
37
|
+
sideDoorLocationId;
|
|
38
|
+
sideDoorGateTransitionUntil;
|
|
39
|
+
uda;
|
|
40
|
+
// Internal event bus for state-change reactions.
|
|
41
|
+
hubEvents = new HubEventBus();
|
|
42
|
+
// Create an instance.
|
|
43
|
+
constructor(controller, device, accessory) {
|
|
44
|
+
super(controller, accessory);
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
46
|
+
this.catalog = getDeviceCatalog(device.device_type) ?? getDeviceCatalog("UAH");
|
|
47
|
+
this.uda = device;
|
|
48
|
+
this._hkDpsState = hubDpsState(this);
|
|
49
|
+
this._hkLockState = hubLockState(this);
|
|
50
|
+
this._hkSideDoorDpsState = hubDpsState(this, true);
|
|
51
|
+
this._hkSideDoorLockState = hubLockState(this, true);
|
|
52
|
+
this.gateTransitionUntil = 0;
|
|
53
|
+
this.lockDelayInterval = this.getFeatureNumber("Hub.LockDelayInterval") ?? undefined;
|
|
54
|
+
this.mainDoorLocationId = undefined;
|
|
55
|
+
this.sideDoorLocationId = undefined;
|
|
56
|
+
this.sideDoorGateTransitionUntil = 0;
|
|
57
|
+
this.doorbellRingRequestId = null;
|
|
58
|
+
// If we attempt to set the delay interval to something invalid, then assume we are using the default unlock behavior.
|
|
59
|
+
if ((this.lockDelayInterval !== undefined) && (this.lockDelayInterval < 0)) {
|
|
60
|
+
this.lockDelayInterval = undefined;
|
|
61
|
+
}
|
|
62
|
+
this.configureHints();
|
|
63
|
+
this.configureDevice();
|
|
64
|
+
}
|
|
65
|
+
// Configure device-specific settings for this device.
|
|
66
|
+
configureHints() {
|
|
67
|
+
// Configure our parent's hints.
|
|
68
|
+
super.configureHints();
|
|
69
|
+
this.hints.hasSideDoor = this.catalog.supportsSideDoor && this.hasFeature("Hub.SideDoor");
|
|
70
|
+
this.hints.hasWiringDps = this.catalog.hasDps && this.hasFeature("Hub.DPS");
|
|
71
|
+
this.hints.hasWiringRel = this.catalog.hasRel && this.hasFeature("Hub.REL");
|
|
72
|
+
this.hints.hasWiringRen = this.catalog.hasRen && this.hasFeature("Hub.REN");
|
|
73
|
+
this.hints.hasWiringRex = this.catalog.hasRex && this.hasFeature("Hub.REX");
|
|
74
|
+
this.hints.hasWiringSideDoorDps = this.hints.hasSideDoor && this.hasFeature("Hub.SideDoor.DPS");
|
|
75
|
+
this.hints.logDoorbell = this.hasFeature("Log.Doorbell");
|
|
76
|
+
this.hints.logDps = this.hasFeature("Log.DPS");
|
|
77
|
+
this.hints.logLock = this.hasFeature("Log.Lock");
|
|
78
|
+
this.hints.logRel = this.hasFeature("Log.REL");
|
|
79
|
+
this.hints.logRen = this.hasFeature("Log.REN");
|
|
80
|
+
this.hints.logRex = this.hasFeature("Log.REX");
|
|
81
|
+
// Proxy mode devices have a single terminal input that's selectable between DPS and REX modes.
|
|
82
|
+
if (this.catalog.usesProxyMode) {
|
|
83
|
+
checkUltraInputs(this);
|
|
84
|
+
}
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
// Initialize and configure the hub accessory for HomeKit. Orchestrates all module setup.
|
|
88
|
+
configureDevice() {
|
|
89
|
+
this._hkLockState = hubLockState(this);
|
|
90
|
+
this._hkSideDoorDpsState = hubDpsState(this, true);
|
|
91
|
+
this._hkSideDoorLockState = hubLockState(this, true);
|
|
92
|
+
// Clean out the context object in case it's been polluted somehow.
|
|
93
|
+
this.accessory.context = {};
|
|
94
|
+
this.accessory.context.mac = this.uda.mac;
|
|
95
|
+
this.accessory.context.controller = this.controller.uda.host.mac;
|
|
96
|
+
logLockDelayInterval(this, "door");
|
|
97
|
+
if (this.hints.hasSideDoor) {
|
|
98
|
+
logLockDelayInterval(this, "side door");
|
|
99
|
+
}
|
|
100
|
+
// Configure accessory information.
|
|
101
|
+
this.configureInfo();
|
|
102
|
+
// Register state-change reaction handlers on the event bus (must be done before services so reactions are ready).
|
|
103
|
+
registerServiceReactions(this);
|
|
104
|
+
// Configure all HomeKit services.
|
|
105
|
+
configureServices(this);
|
|
106
|
+
// Configure MQTT services (includes its own event bus subscriptions).
|
|
107
|
+
configureMqtt(this);
|
|
108
|
+
// Discover door IDs for UA Gate hubs (must be done before registering event handlers so door IDs are available).
|
|
109
|
+
if (this.catalog.usesLocationApi) {
|
|
110
|
+
discoverDoorIds(this);
|
|
111
|
+
}
|
|
112
|
+
// Register external event handlers (subscribes to controller events).
|
|
113
|
+
registerEventHandlers(this);
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
// HomeKit DPS state property accessor. Reads from the contact sensor service if available, otherwise falls back to the backing variable.
|
|
117
|
+
get hkDpsState() {
|
|
118
|
+
const service = this.accessory.getServiceById(this.hap.Service.ContactSensor, AccessReservedNames.CONTACT_DPS);
|
|
119
|
+
if (service) {
|
|
120
|
+
return service.getCharacteristic(this.hap.Characteristic.ContactSensorState).value ?? this._hkDpsState;
|
|
121
|
+
}
|
|
122
|
+
return this._hkDpsState;
|
|
123
|
+
}
|
|
124
|
+
// HomeKit DPS state setter. Updates the backing variable, contact sensor, and emits events.
|
|
125
|
+
set hkDpsState(value) {
|
|
126
|
+
this._hkDpsState = value;
|
|
127
|
+
setContactSensorState(this, AccessReservedNames.CONTACT_DPS, value);
|
|
128
|
+
// Emit events for DPS and sensor changes.
|
|
129
|
+
this.hubEvents.emit("dps:changed", { isSideDoor: false, value });
|
|
130
|
+
this.hubEvents.emit("sensor:changed", { input: "Dps", value });
|
|
131
|
+
}
|
|
132
|
+
// HomeKit lock state property accessor.
|
|
133
|
+
get hkLockState() {
|
|
134
|
+
return this._hkLockState;
|
|
135
|
+
}
|
|
136
|
+
// HomeKit lock state setter. Updates the backing variable and emits the lock:changed event.
|
|
137
|
+
set hkLockState(value) {
|
|
138
|
+
// Update the lock state.
|
|
139
|
+
this._hkLockState = value;
|
|
140
|
+
// Emit the lock:changed event - service reactions and MQTT will handle the rest.
|
|
141
|
+
this.hubEvents.emit("lock:changed", { isSideDoor: false, value });
|
|
142
|
+
}
|
|
143
|
+
// HomeKit side door lock state property accessor.
|
|
144
|
+
get hkSideDoorLockState() {
|
|
145
|
+
return this._hkSideDoorLockState;
|
|
146
|
+
}
|
|
147
|
+
// HomeKit side door lock state setter. Updates the backing variable and emits the lock:changed event.
|
|
148
|
+
set hkSideDoorLockState(value) {
|
|
149
|
+
// Update the lock state.
|
|
150
|
+
this._hkSideDoorLockState = value;
|
|
151
|
+
// Emit the lock:changed event - service reactions and MQTT will handle the rest.
|
|
152
|
+
this.hubEvents.emit("lock:changed", { isSideDoor: true, value });
|
|
153
|
+
}
|
|
154
|
+
// We dynamically define our getters and setters for terminal inputs so we can streamline redundancies.
|
|
155
|
+
static {
|
|
156
|
+
// Define wiring getters for all sensor inputs.
|
|
157
|
+
for (const input of sensorInputs) {
|
|
158
|
+
Object.defineProperty(AccessHub.prototype, "is" + input + "Wired", {
|
|
159
|
+
configurable: true,
|
|
160
|
+
enumerable: true,
|
|
161
|
+
get() {
|
|
162
|
+
return isWired(this, input);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// Define hk*State getters and setters. We skip DPS since we implement it with a manual getter/setter that provides fallback behavior when the DPS contact sensor
|
|
167
|
+
// is disabled.
|
|
168
|
+
for (const input of sensorInputs.filter(i => i !== "Dps")) {
|
|
169
|
+
const enumKey = "CONTACT_" + input.toUpperCase();
|
|
170
|
+
Object.defineProperty(AccessHub.prototype, "hk" + input + "State", {
|
|
171
|
+
configurable: true,
|
|
172
|
+
enumerable: true,
|
|
173
|
+
get() {
|
|
174
|
+
return getContactSensorState(this, AccessReservedNames[enumKey]);
|
|
175
|
+
},
|
|
176
|
+
set(value) {
|
|
177
|
+
setContactSensorState(this, AccessReservedNames[enumKey], value);
|
|
178
|
+
// Emit sensor:changed event for MQTT and logging.
|
|
179
|
+
this.hubEvents.emit("sensor:changed", { input: input, value });
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=access-hub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-hub.js","sourceRoot":"","sources":["../../src/hub/access-hub.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { AccessHub } from "./access-hub.js";
|
|
2
|
+
export type { HkStateKey } from "./access-hub.js";
|
|
3
|
+
export { AUTO_LOCK_DELAY_MS, GATE_TRANSITION_COOLDOWN_MS, REX_BUTTON_MODE_CONFIG_KEY, areWiringKeysActive, getConfigValue, accessMethods, sensorInputs, terminalInputs } from "./access-hub-types.js";
|
|
4
|
+
export type { AccessEventDeviceUpdateV2, AccessEventLocationUpdate, AccessHubHKProps, AccessHubWiredProps, AccessMethodKey, DoorServiceType, HasWiringHintKey, HubEventKey, HubEventMap, KeyOf, LogHintKey } from "./access-hub-types.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/* Copyright(C) 2026, Mickael Palma. All rights reserved.
|
|
2
|
+
*
|
|
3
|
+
* hub/index.ts: Barrel export for the UniFi Access hub module.
|
|
4
|
+
*/
|
|
5
|
+
export { AccessHub } from "./access-hub.js";
|
|
6
|
+
export { AUTO_LOCK_DELAY_MS, GATE_TRANSITION_COOLDOWN_MS, REX_BUTTON_MODE_CONFIG_KEY, areWiringKeysActive, getConfigValue, accessMethods, sensorInputs, terminalInputs } from "./access-hub-types.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hub/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EACL,kBAAkB,EAAE,2BAA2B,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAC9J,MAAM,uBAAuB,CAAC"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/* Copyright(C) 2026, Mickael Palma. All rights reserved.
|
|
2
|
+
*
|
|
3
|
+
* index.ts: homebridge-unifi-access plugin registration.
|
|
4
|
+
*/
|
|
5
|
+
import { PLATFORM_NAME, PLUGIN_NAME } from "./settings.js";
|
|
6
|
+
import { AccessPlatform } from "./access-platform.js";
|
|
7
|
+
// Register our platform with homebridge.
|
|
8
|
+
export default (api) => {
|
|
9
|
+
api.registerPlatform(PLUGIN_NAME, PLATFORM_NAME, AccessPlatform);
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE3D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,yCAAyC;AACzC,eAAe,CAAC,GAAQ,EAAQ,EAAE;IAEhC,GAAG,CAAC,gBAAgB,CAAC,WAAW,EAAE,aAAa,EAAE,cAAc,CAAC,CAAC;AACnE,CAAC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { HomebridgePluginLogging } from "homebridge-plugin-utils";
|
|
2
|
+
import type { Logging } from "homebridge";
|
|
3
|
+
export declare const PLUGIN_NAME = "@mp-consulting/homebridge-unifi-access";
|
|
4
|
+
export declare const PLATFORM_NAME = "UniFi Access";
|
|
5
|
+
export declare const ACCESS_CONTROLLER_REFRESH_INTERVAL = 120;
|
|
6
|
+
export declare const ACCESS_CONTROLLER_RETRY_INTERVAL = 10;
|
|
7
|
+
export declare const ACCESS_DEVICE_REMOVAL_DELAY_INTERVAL = 60;
|
|
8
|
+
export declare const ACCESS_DEVICE_UNLOCK_INTERVAL = 0;
|
|
9
|
+
export declare const ACCESS_MOTION_DURATION = 10;
|
|
10
|
+
export declare const ACCESS_MQTT_RECONNECT_INTERVAL = 60;
|
|
11
|
+
export declare const ACCESS_MQTT_TOPIC = "unifi/access";
|
|
12
|
+
export declare const ACCESS_OCCUPANCY_DURATION = 300;
|
|
13
|
+
export declare const HK_CHARACTERISTIC_REVERT_DELAY_MS = 50;
|
|
14
|
+
export declare function normalizeMac(mac: string): string;
|
|
15
|
+
export declare function isValidAddress(address: string): boolean;
|
|
16
|
+
export declare function createPrefixedLogger(platformLog: Logging, debugFn: (message: string, ...parameters: unknown[]) => void, nameGetter: () => string): HomebridgePluginLogging;
|
package/dist/settings.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import util from "node:util";
|
|
2
|
+
// The name of our plugin.
|
|
3
|
+
export const PLUGIN_NAME = "@mp-consulting/homebridge-unifi-access";
|
|
4
|
+
// The platform the plugin creates.
|
|
5
|
+
export const PLATFORM_NAME = "UniFi Access";
|
|
6
|
+
// How often, in seconds, should we check Access controllers for new or removed devices.
|
|
7
|
+
export const ACCESS_CONTROLLER_REFRESH_INTERVAL = 120;
|
|
8
|
+
// How often, in seconds, should we retry getting our bootstrap configuration from the Access controller.
|
|
9
|
+
export const ACCESS_CONTROLLER_RETRY_INTERVAL = 10;
|
|
10
|
+
// Default delay, in seconds, before removing Access devices that no longer exist.
|
|
11
|
+
export const ACCESS_DEVICE_REMOVAL_DELAY_INTERVAL = 60;
|
|
12
|
+
// Default delay, in minutes, before locking an unlocked door relay.
|
|
13
|
+
export const ACCESS_DEVICE_UNLOCK_INTERVAL = 0;
|
|
14
|
+
// Default duration, in seconds, of motion events. Setting this too low will potentially cause a lot of notification spam.
|
|
15
|
+
export const ACCESS_MOTION_DURATION = 10;
|
|
16
|
+
// How often, in seconds, should we try to reconnect with an MQTT broker, if we have one configured.
|
|
17
|
+
export const ACCESS_MQTT_RECONNECT_INTERVAL = 60;
|
|
18
|
+
// Default MQTT topic to use when publishing events. This is in the form of: unifi/access/MAC/event
|
|
19
|
+
export const ACCESS_MQTT_TOPIC = "unifi/access";
|
|
20
|
+
// Default duration, in seconds, of occupancy events.
|
|
21
|
+
export const ACCESS_OCCUPANCY_DURATION = 300;
|
|
22
|
+
// Delay, in milliseconds, before reverting a HomeKit characteristic value after a failed or no-op set.
|
|
23
|
+
export const HK_CHARACTERISTIC_REVERT_DELAY_MS = 50;
|
|
24
|
+
// Normalize a MAC address by stripping colons and uppercasing.
|
|
25
|
+
export function normalizeMac(mac) {
|
|
26
|
+
return mac.replace(/:/g, "").toUpperCase();
|
|
27
|
+
}
|
|
28
|
+
// Validate a controller address, rejecting loopback, link-local, and unspecified addresses.
|
|
29
|
+
export function isValidAddress(address) {
|
|
30
|
+
if (!address || (typeof address !== "string")) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
const trimmed = address.trim().toLowerCase();
|
|
34
|
+
if (!trimmed || (trimmed === "localhost") || trimmed.startsWith("127.") || trimmed.startsWith("169.254.") || (trimmed === "0.0.0.0") ||
|
|
35
|
+
trimmed.startsWith("[") || trimmed.includes("::")) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
// Factory for the prefixed logging adapter pattern used across devices and controllers.
|
|
41
|
+
export function createPrefixedLogger(platformLog, debugFn, nameGetter) {
|
|
42
|
+
return {
|
|
43
|
+
debug: (message, ...parameters) => debugFn(util.format(nameGetter() + ": " + message, ...parameters)),
|
|
44
|
+
error: (message, ...parameters) => platformLog.error(util.format(nameGetter() + ": " + message, ...parameters)),
|
|
45
|
+
info: (message, ...parameters) => platformLog.info(util.format(nameGetter() + ": " + message, ...parameters)),
|
|
46
|
+
warn: (message, ...parameters) => platformLog.warn(util.format(nameGetter() + ": " + message, ...parameters))
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAMA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,0BAA0B;AAC1B,MAAM,CAAC,MAAM,WAAW,GAAG,wCAAwC,CAAC;AAEpE,mCAAmC;AACnC,MAAM,CAAC,MAAM,aAAa,GAAG,cAAc,CAAC;AAE5C,wFAAwF;AACxF,MAAM,CAAC,MAAM,kCAAkC,GAAG,GAAG,CAAC;AAEtD,yGAAyG;AACzG,MAAM,CAAC,MAAM,gCAAgC,GAAG,EAAE,CAAC;AAEnD,kFAAkF;AAClF,MAAM,CAAC,MAAM,oCAAoC,GAAG,EAAE,CAAC;AAEvD,oEAAoE;AACpE,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAE/C,0HAA0H;AAC1H,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAEzC,oGAAoG;AACpG,MAAM,CAAC,MAAM,8BAA8B,GAAG,EAAE,CAAC;AAEjD,mGAAmG;AACnG,MAAM,CAAC,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAEhD,qDAAqD;AACrD,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAE7C,uGAAuG;AACvG,MAAM,CAAC,MAAM,iCAAiC,GAAG,EAAE,CAAC;AAEpD,+DAA+D;AAC/D,MAAM,UAAU,YAAY,CAAC,GAAW;IAEtC,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AAC7C,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,cAAc,CAAC,OAAe;IAE5C,IAAG,CAAC,OAAO,IAAI,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,EAAE,CAAC;QAE7C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAE7C,IAAG,CAAC,OAAO,IAAI,CAAC,OAAO,KAAK,WAAW,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC;QACjI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAEpD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,oBAAoB,CAAC,WAAoB,EAAE,OAA4D,EACrH,UAAwB;IAExB,OAAO;QAEL,KAAK,EAAE,CAAC,OAAe,EAAE,GAAG,UAAqB,EAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,IAAI,GAAG,OAAO,EAAE,GAAG,UAAU,CAAC,CAAC;QAC9H,KAAK,EAAE,CAAC,OAAe,EAAE,GAAG,UAAqB,EAAQ,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,IAAI,GAAG,OAAO,EAAE,GAAG,UAAU,CAAC,CAAC;QACxI,IAAI,EAAE,CAAC,OAAe,EAAE,GAAG,UAAqB,EAAQ,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,IAAI,GAAG,OAAO,EAAE,GAAG,UAAU,CAAC,CAAC;QACtI,IAAI,EAAE,CAAC,OAAe,EAAE,GAAG,UAAqB,EAAQ,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,IAAI,GAAG,OAAO,EAAE,GAAG,UAAU,CAAC,CAAC;KACvI,CAAC;AACJ,CAAC"}
|