homebridge-unifi-access 0.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +3 -3
- package/README.md +88 -3
- package/config.schema.json +202 -0
- package/dist/access-controller.d.ts +45 -0
- package/dist/access-controller.js +387 -0
- package/dist/access-controller.js.map +1 -0
- package/dist/access-device.d.ts +53 -0
- package/dist/access-device.js +362 -0
- package/dist/access-device.js.map +1 -0
- package/dist/access-events.d.ts +24 -0
- package/dist/access-events.js +151 -0
- package/dist/access-events.js.map +1 -0
- package/dist/access-hub.d.ts +21 -0
- package/dist/access-hub.js +277 -0
- package/dist/access-hub.js.map +1 -0
- package/dist/access-mqtt.d.ts +20 -0
- package/dist/access-mqtt.js +163 -0
- package/dist/access-mqtt.js.map +1 -0
- package/dist/access-options.d.ts +38 -0
- package/dist/access-options.js +167 -0
- package/dist/access-options.js.map +1 -0
- package/dist/access-platform.d.ts +16 -0
- package/dist/access-platform.js +103 -0
- package/dist/access-platform.js.map +1 -0
- package/dist/access-types.d.ts +11 -0
- package/dist/access-types.js +13 -0
- package/dist/access-types.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +9 -5
- package/dist/index.js.map +1 -1
- package/dist/settings.d.ts +10 -0
- package/dist/settings.js +23 -10
- package/dist/settings.js.map +1 -1
- package/homebridge-ui/public/access-featureoptions.mjs +748 -0
- package/homebridge-ui/public/index.html +151 -0
- package/homebridge-ui/public/lib/featureoptions.mjs +201 -0
- package/homebridge-ui/public/ui.mjs +182 -0
- package/homebridge-ui/server.js +153 -0
- package/package.json +55 -23
- package/.eslintrc.json +0 -45
- package/dist/platform.js +0 -98
- package/dist/platform.js.map +0 -1
- package/dist/platformAccessory.js +0 -104
- package/dist/platformAccessory.js.map +0 -1
- package/src/index.ts +0 -11
- package/src/platform.ts +0 -116
- package/src/platformAccessory.ts +0 -130
- package/src/settings.ts +0 -9
- package/tsconfig.json +0 -20
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { AccessDevice } from "./access-device.js";
|
|
2
|
+
import { AccessReservedNames } from "./access-types.js";
|
|
3
|
+
export class AccessHub extends AccessDevice {
|
|
4
|
+
_hkLockState;
|
|
5
|
+
doorbellRingRequestId;
|
|
6
|
+
lockDelayInterval;
|
|
7
|
+
uda;
|
|
8
|
+
// Create an instance.
|
|
9
|
+
constructor(controller, device, accessory) {
|
|
10
|
+
super(controller, accessory);
|
|
11
|
+
this.uda = device;
|
|
12
|
+
this._hkLockState = this.hubLockState;
|
|
13
|
+
this.lockDelayInterval = this.getFeatureNumber("Hub.LockDelayInterval");
|
|
14
|
+
this.doorbellRingRequestId = null;
|
|
15
|
+
// If we attempt to set the delay interval to something invalid, then assume we are using the default unlock behavior.
|
|
16
|
+
if ((this.lockDelayInterval !== undefined) && (this.lockDelayInterval < 0)) {
|
|
17
|
+
this.lockDelayInterval = undefined;
|
|
18
|
+
}
|
|
19
|
+
this.configureHints();
|
|
20
|
+
this.configureDevice();
|
|
21
|
+
}
|
|
22
|
+
// Configure device-specific settings for this device.
|
|
23
|
+
configureHints() {
|
|
24
|
+
// Configure our parent's hints.
|
|
25
|
+
super.configureHints();
|
|
26
|
+
this.hints.logDoorbell = this.hasFeature("Log.Doorbell");
|
|
27
|
+
this.hints.logLock = this.hasFeature("Log.Lock");
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
// Initialize and configure the light accessory for HomeKit.
|
|
31
|
+
configureDevice() {
|
|
32
|
+
this._hkLockState = this.hubLockState;
|
|
33
|
+
// Clean out the context object in case it's been polluted somehow.
|
|
34
|
+
this.accessory.context = {};
|
|
35
|
+
this.accessory.context.mac = this.uda.mac;
|
|
36
|
+
this.accessory.context.controller = this.controller.uda.host.mac;
|
|
37
|
+
if (this.lockDelayInterval === undefined) {
|
|
38
|
+
this.log.info("The door lock relay will lock five seconds after unlocking in HomeKit.");
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
this.log.info("The door lock relay will remain unlocked %s after unlocking in HomeKit.", this.lockDelayInterval === 0 ? "indefinitely" : "for " + this.lockDelayInterval.toString() + " minutes");
|
|
42
|
+
}
|
|
43
|
+
// Configure accessory information.
|
|
44
|
+
this.configureInfo();
|
|
45
|
+
// Configure the doorbell.
|
|
46
|
+
this.configureDoorbell();
|
|
47
|
+
this.configureDoorbellTrigger();
|
|
48
|
+
// Configure the lock.
|
|
49
|
+
this.configureLock();
|
|
50
|
+
// Configure MQTT services.
|
|
51
|
+
this.configureMqtt();
|
|
52
|
+
// Listen for events.
|
|
53
|
+
this.controller.events.on(this.uda.unique_id, this.listeners[this.uda.unique_id] = this.eventHandler.bind(this));
|
|
54
|
+
this.controller.events.on("access.remote_view", this.listeners[this.uda.unique_id] = this.eventHandler.bind(this));
|
|
55
|
+
this.controller.events.on("access.remote_view.change", this.listeners[this.uda.unique_id] = this.eventHandler.bind(this));
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
// Configure the lock for HomeKit.
|
|
59
|
+
configureLock() {
|
|
60
|
+
// Find the service, if it exists.
|
|
61
|
+
let lockService = this.accessory.getService(this.hap.Service.LockMechanism);
|
|
62
|
+
// Add the service to the accessory, if needed.
|
|
63
|
+
if (!lockService) {
|
|
64
|
+
lockService = new this.hap.Service.LockMechanism(this.accessoryName);
|
|
65
|
+
if (!lockService) {
|
|
66
|
+
this.log.error("Unable to add lock.");
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
this.accessory.addService(lockService);
|
|
70
|
+
}
|
|
71
|
+
// Return the lock state.
|
|
72
|
+
lockService.getCharacteristic(this.hap.Characteristic.LockCurrentState)?.onGet(() => {
|
|
73
|
+
return this.hkLockState;
|
|
74
|
+
});
|
|
75
|
+
lockService.getCharacteristic(this.hap.Characteristic.LockTargetState)?.onSet(async (value) => {
|
|
76
|
+
if (!await this.controller.udaApi.unlock(this.uda, (this.lockDelayInterval === undefined) ? undefined : (value === this.hap.Characteristic.LockTargetState.SECURED ? 0 : Infinity))) {
|
|
77
|
+
this.log.error("Unable to %s.", value === this.hap.Characteristic.LockTargetState.SECURED ? "lock" : "unlock");
|
|
78
|
+
// Revert our target state.
|
|
79
|
+
setTimeout(() => {
|
|
80
|
+
lockService.updateCharacteristic(this.hap.Characteristic.LockTargetState, !value);
|
|
81
|
+
}, 50);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
// Initialize the lock.
|
|
85
|
+
this._hkLockState = -1;
|
|
86
|
+
lockService.displayName = this.accessoryName;
|
|
87
|
+
lockService.updateCharacteristic(this.hap.Characteristic.Name, this.accessoryName);
|
|
88
|
+
this.hkLockState = this.hubLockState;
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
// Configure the doorbell service for HomeKit.
|
|
92
|
+
configureDoorbell() {
|
|
93
|
+
// Find the doorbell service, if it exists.
|
|
94
|
+
let doorbellService = this.accessory.getService(this.hap.Service.Doorbell);
|
|
95
|
+
// If we don't have HKSV or the HKSV recording switch enabled, disable it and we're done.
|
|
96
|
+
if (!this.hasFeature("Hub.Doorbell")) {
|
|
97
|
+
if (doorbellService) {
|
|
98
|
+
this.accessory.removeService(doorbellService);
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
// Add the doorbell service. HomeKit requires the doorbell service to be marked as the primary service on the accessory.
|
|
103
|
+
if (!doorbellService) {
|
|
104
|
+
doorbellService = new this.hap.Service.Doorbell(this.accessoryName);
|
|
105
|
+
if (!doorbellService) {
|
|
106
|
+
this.log.error("Unable to add doorbell.");
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
this.accessory.addService(doorbellService);
|
|
110
|
+
}
|
|
111
|
+
doorbellService.setPrimaryService(true);
|
|
112
|
+
this.log.info("Enabling doorbell.");
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
// Configure a switch to manually trigger a doorbell ring event for HomeKit.
|
|
116
|
+
configureDoorbellTrigger() {
|
|
117
|
+
// Find the switch service, if it exists.
|
|
118
|
+
let triggerService = this.accessory.getServiceById(this.hap.Service.Switch, AccessReservedNames.SWITCH_DOORBELL_TRIGGER);
|
|
119
|
+
// Doorbell switches are disabled by default and primarily exist for automation purposes.
|
|
120
|
+
if (!this.hasFeature("Hub.Doorbell.Trigger")) {
|
|
121
|
+
if (triggerService) {
|
|
122
|
+
this.accessory.removeService(triggerService);
|
|
123
|
+
}
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
const triggerName = this.accessoryName + " Doorbell Trigger";
|
|
127
|
+
// Add the switch to the hub, if needed.
|
|
128
|
+
if (!triggerService) {
|
|
129
|
+
triggerService = new this.hap.Service.Switch(triggerName, AccessReservedNames.SWITCH_DOORBELL_TRIGGER);
|
|
130
|
+
if (!triggerService) {
|
|
131
|
+
this.log.error("Unable to add the doorbell trigger.");
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
triggerService.addOptionalCharacteristic(this.hap.Characteristic.ConfiguredName);
|
|
135
|
+
this.accessory.addService(triggerService);
|
|
136
|
+
}
|
|
137
|
+
// Trigger the doorbell.
|
|
138
|
+
triggerService.getCharacteristic(this.hap.Characteristic.On)?.onGet(() => {
|
|
139
|
+
return this.doorbellRingRequestId !== null;
|
|
140
|
+
});
|
|
141
|
+
// The state isn't really user-triggerable. We have no way, currently, to trigger a ring event on the hub.
|
|
142
|
+
triggerService.getCharacteristic(this.hap.Characteristic.On)?.onSet(() => {
|
|
143
|
+
setTimeout(() => {
|
|
144
|
+
triggerService?.updateCharacteristic(this.hap.Characteristic.On, this.doorbellRingRequestId !== null);
|
|
145
|
+
}, 50);
|
|
146
|
+
});
|
|
147
|
+
// Initialize the switch.
|
|
148
|
+
triggerService.updateCharacteristic(this.hap.Characteristic.ConfiguredName, triggerName);
|
|
149
|
+
triggerService.updateCharacteristic(this.hap.Characteristic.On, false);
|
|
150
|
+
this.log.info("Enabling doorbell automation trigger.");
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
// Configure MQTT capabilities of this light.
|
|
154
|
+
configureMqtt() {
|
|
155
|
+
const lockService = this.accessory.getService(this.hap.Service.LockMechanism);
|
|
156
|
+
if (!lockService) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
// MQTT doorbell status.
|
|
160
|
+
this.controller.mqtt?.subscribeGet(this.accessory, "doorbell", "Doorbell ring", () => {
|
|
161
|
+
return this.doorbellRingRequestId !== null ? "true" : "false";
|
|
162
|
+
});
|
|
163
|
+
// MQTT lock status.
|
|
164
|
+
this.controller.mqtt?.subscribeGet(this.accessory, "lock", "Lock", () => {
|
|
165
|
+
switch (this.hkLockState) {
|
|
166
|
+
case this.hap.Characteristic.LockCurrentState.SECURED:
|
|
167
|
+
return "true";
|
|
168
|
+
break;
|
|
169
|
+
case this.hap.Characteristic.LockCurrentState.UNSECURED:
|
|
170
|
+
return "false";
|
|
171
|
+
break;
|
|
172
|
+
default:
|
|
173
|
+
return "unknown";
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
// MQTT lock status.
|
|
178
|
+
this.controller.mqtt?.subscribeSet(this.accessory, "lock", "Lock", (value) => {
|
|
179
|
+
switch (value) {
|
|
180
|
+
case "true":
|
|
181
|
+
void this.controller.udaApi.unlock(this.uda, 0);
|
|
182
|
+
break;
|
|
183
|
+
case "false":
|
|
184
|
+
void this.controller.udaApi.unlock(this.uda, Infinity);
|
|
185
|
+
break;
|
|
186
|
+
default:
|
|
187
|
+
this.log.error("MQTT: Unknown lock set message received: %s.", value);
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
// Return the current HomeKit lock state that we are tracking for this hub.
|
|
194
|
+
get hkLockState() {
|
|
195
|
+
return this._hkLockState;
|
|
196
|
+
}
|
|
197
|
+
// Set the current HomeKit lock state for this hub.
|
|
198
|
+
set hkLockState(value) {
|
|
199
|
+
// If nothing is changed, we're done.
|
|
200
|
+
if (this.hkLockState === value) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
// Update the lock state.
|
|
204
|
+
this._hkLockState = value;
|
|
205
|
+
// Retrieve the lock service.
|
|
206
|
+
const lockService = this.accessory.getService(this.hap.Service.LockMechanism);
|
|
207
|
+
if (!lockService) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
// Update the state in HomeKit.
|
|
211
|
+
lockService.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hkLockState === this.hap.Characteristic.LockCurrentState.UNSECURED ?
|
|
212
|
+
this.hap.Characteristic.LockTargetState.UNSECURED : this.hap.Characteristic.LockTargetState.SECURED);
|
|
213
|
+
lockService.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hkLockState);
|
|
214
|
+
}
|
|
215
|
+
// Return the current state of the relay lock on the hub.
|
|
216
|
+
get hubLockState() {
|
|
217
|
+
const lockRelay = this.uda.configs.find(x => x.key === "input_state_rly-lock_dry");
|
|
218
|
+
return (lockRelay?.value === "off" ?
|
|
219
|
+
this.hap.Characteristic.LockCurrentState.SECURED : this.hap.Characteristic.LockCurrentState.UNSECURED) ?? this.hap.Characteristic.LockCurrentState.UNKNOWN;
|
|
220
|
+
}
|
|
221
|
+
// Handle hub-related events.
|
|
222
|
+
eventHandler(packet) {
|
|
223
|
+
switch (packet.event) {
|
|
224
|
+
case "access.data.device.remote_unlock":
|
|
225
|
+
// Process an Access unlock event.
|
|
226
|
+
this.hkLockState = this.hap.Characteristic.LockCurrentState.UNSECURED;
|
|
227
|
+
if (this.hints.logLock) {
|
|
228
|
+
this.log.info("Unlocked.");
|
|
229
|
+
}
|
|
230
|
+
break;
|
|
231
|
+
case "access.data.device.update":
|
|
232
|
+
// Process an Access device update event if our state has changed.
|
|
233
|
+
if (this.hubLockState === this.hkLockState) {
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
this.hkLockState = this.hubLockState;
|
|
237
|
+
if (this.hints.logLock) {
|
|
238
|
+
this.log.info(this.hkLockState === this.hap.Characteristic.LockCurrentState.SECURED ? "Locked." : "Unlocked.");
|
|
239
|
+
}
|
|
240
|
+
break;
|
|
241
|
+
case "access.remote_view":
|
|
242
|
+
// Process an Access ring event if we're the intended target.
|
|
243
|
+
if (packet.data.connected_uah_id !== this.uda.unique_id) {
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
this.doorbellRingRequestId = packet.data.request_id;
|
|
247
|
+
// Trigger the doorbell event in HomeKit.
|
|
248
|
+
this.accessory.getService(this.hap.Service.Doorbell)?.getCharacteristic(this.hap.Characteristic.ProgrammableSwitchEvent)
|
|
249
|
+
?.sendEventNotification(this.hap.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
|
|
250
|
+
// Update our doorbell trigger, if needed.
|
|
251
|
+
this.accessory.getServiceById(this.hap.Service.Switch, AccessReservedNames.SWITCH_DOORBELL_TRIGGER)?.updateCharacteristic(this.hap.Characteristic.On, true);
|
|
252
|
+
// Publish to MQTT, if configured to do so.
|
|
253
|
+
this.controller.mqtt?.publish(this.accessory, "doorbell", "true");
|
|
254
|
+
if (this.hints.logDoorbell) {
|
|
255
|
+
this.log.info("Doorbell ring detected.");
|
|
256
|
+
}
|
|
257
|
+
break;
|
|
258
|
+
case "access.remote_view.change":
|
|
259
|
+
// Process the cancellation of an Access ring event if we're the intended target.
|
|
260
|
+
if (this.doorbellRingRequestId !== packet.data.remote_call_request_id) {
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
this.doorbellRingRequestId = null;
|
|
264
|
+
// Update our doorbell trigger, if needed.
|
|
265
|
+
this.accessory.getServiceById(this.hap.Service.Switch, AccessReservedNames.SWITCH_DOORBELL_TRIGGER)?.updateCharacteristic(this.hap.Characteristic.On, false);
|
|
266
|
+
// Publish to MQTT, if configured to do so.
|
|
267
|
+
this.controller.mqtt?.publish(this.accessory, "doorbell", "false");
|
|
268
|
+
if (this.hints.logDoorbell) {
|
|
269
|
+
this.log.info("Doorbell ring cancelled.");
|
|
270
|
+
}
|
|
271
|
+
break;
|
|
272
|
+
default:
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=access-hub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-hub.js","sourceRoot":"","sources":["../src/access-hub.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { AccessController } from "./access-controller.js";
|
|
3
|
+
import { PlatformAccessory } from "homebridge";
|
|
4
|
+
export declare class AccessMqtt {
|
|
5
|
+
private config;
|
|
6
|
+
private controller;
|
|
7
|
+
private isConnected;
|
|
8
|
+
private log;
|
|
9
|
+
private mqtt;
|
|
10
|
+
private subscriptions;
|
|
11
|
+
private udaApi;
|
|
12
|
+
constructor(controller: AccessController);
|
|
13
|
+
private configure;
|
|
14
|
+
publish(accessory: PlatformAccessory | string, topic: string, message: string): void;
|
|
15
|
+
subscribe(accessory: PlatformAccessory | string, topic: string, callback: (cbBuffer: Buffer) => void): void;
|
|
16
|
+
subscribeGet(accessory: PlatformAccessory, topic: string, type: string, getValue: () => string): void;
|
|
17
|
+
subscribeSet(accessory: PlatformAccessory, topic: string, type: string, setValue: (value: string) => void): void;
|
|
18
|
+
unsubscribe(accessory: PlatformAccessory | string, topic: string): void;
|
|
19
|
+
private expandTopic;
|
|
20
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/* Copyright(C) 2017-2024, HJD (https://github.com/hjdhjd). All rights reserved.
|
|
2
|
+
*
|
|
3
|
+
* access-mqtt.ts: MQTT connectivity class for UniFi Access.
|
|
4
|
+
*/
|
|
5
|
+
import mqtt from "mqtt";
|
|
6
|
+
import { ACCESS_MQTT_RECONNECT_INTERVAL } from "./settings.js";
|
|
7
|
+
export class AccessMqtt {
|
|
8
|
+
config;
|
|
9
|
+
controller;
|
|
10
|
+
isConnected;
|
|
11
|
+
log;
|
|
12
|
+
mqtt;
|
|
13
|
+
subscriptions;
|
|
14
|
+
udaApi;
|
|
15
|
+
constructor(controller) {
|
|
16
|
+
this.config = controller.config;
|
|
17
|
+
this.isConnected = false;
|
|
18
|
+
this.log = controller.log;
|
|
19
|
+
this.mqtt = null;
|
|
20
|
+
this.controller = controller;
|
|
21
|
+
this.udaApi = controller.udaApi;
|
|
22
|
+
this.subscriptions = {};
|
|
23
|
+
if (!this.config.mqttUrl) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
this.configure();
|
|
27
|
+
}
|
|
28
|
+
// Connect to the MQTT broker.
|
|
29
|
+
configure() {
|
|
30
|
+
// Try to connect to the MQTT broker and make sure we catch any URL errors.
|
|
31
|
+
try {
|
|
32
|
+
this.mqtt = mqtt.connect(this.config.mqttUrl, { reconnectPeriod: ACCESS_MQTT_RECONNECT_INTERVAL * 1000, rejectUnauthorized: false });
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
if (error instanceof Error) {
|
|
36
|
+
switch (error.message) {
|
|
37
|
+
case "Missing protocol":
|
|
38
|
+
this.log.error("MQTT Broker: Invalid URL provided: %s.", this.config.mqttUrl);
|
|
39
|
+
break;
|
|
40
|
+
default:
|
|
41
|
+
this.log.error("MQTT Broker: Error: %s.", error.message);
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// We've been unable to even attempt to connect. It's likely we have a configuration issue - we're done here.
|
|
47
|
+
if (!this.mqtt) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
// Notify the user when we connect to the broker.
|
|
51
|
+
this.mqtt.on("connect", () => {
|
|
52
|
+
this.isConnected = true;
|
|
53
|
+
// Magic incantation to redact passwords.
|
|
54
|
+
const redact = /^(?<pre>.*:\/{0,2}.*:)(?<pass>.*)(?<post>@.*)/;
|
|
55
|
+
this.log.info("Connected to MQTT broker: %s (topic: %s).", this.config.mqttUrl.replace(redact, "$<pre>REDACTED$<post>"), this.config.mqttTopic);
|
|
56
|
+
});
|
|
57
|
+
// Notify the user when we've disconnected.
|
|
58
|
+
this.mqtt.on("close", () => {
|
|
59
|
+
if (this.isConnected) {
|
|
60
|
+
this.isConnected = false;
|
|
61
|
+
// Magic incantation to redact passwords.
|
|
62
|
+
const redact = /^(?<pre>.*:\/{0,2}.*:)(?<pass>.*)(?<post>@.*)/;
|
|
63
|
+
this.log.info("Disconnected from MQTT broker: %s.", this.config.mqttUrl.replace(redact, "$<pre>REDACTED$<post>"));
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
// Process inbound messages and pass it to the right message handler.
|
|
67
|
+
this.mqtt.on("message", (topic, message) => {
|
|
68
|
+
if (this.subscriptions[topic]) {
|
|
69
|
+
this.subscriptions[topic](message);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
// Notify the user when there's a connectivity error.
|
|
73
|
+
this.mqtt.on("error", (error) => {
|
|
74
|
+
switch (error.code) {
|
|
75
|
+
case "ECONNREFUSED":
|
|
76
|
+
this.log.error("MQTT Broker: Connection refused (url: %s). Will retry again in %s minute%s.", this.config.mqttUrl, ACCESS_MQTT_RECONNECT_INTERVAL / 60, ACCESS_MQTT_RECONNECT_INTERVAL / 60 > 1 ? "s" : "");
|
|
77
|
+
break;
|
|
78
|
+
case "ECONNRESET":
|
|
79
|
+
this.log.error("MQTT Broker: Connection reset (url: %s). Will retry again in %s minute%s.", this.config.mqttUrl, ACCESS_MQTT_RECONNECT_INTERVAL / 60, ACCESS_MQTT_RECONNECT_INTERVAL / 60 > 1 ? "s" : "");
|
|
80
|
+
break;
|
|
81
|
+
case "ENOTFOUND":
|
|
82
|
+
this.mqtt?.end(true);
|
|
83
|
+
this.log.error("MQTT Broker: Hostname or IP address not found. (url: %s).", this.config.mqttUrl);
|
|
84
|
+
break;
|
|
85
|
+
default:
|
|
86
|
+
this.log.error("MQTT Broker: %s (url: %s). Will retry again in %s minute%s.", error, this.config.mqttUrl, ACCESS_MQTT_RECONNECT_INTERVAL / 60, ACCESS_MQTT_RECONNECT_INTERVAL / 60 > 1 ? "s" : "");
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
// Publish an MQTT event to a broker.
|
|
92
|
+
publish(accessory, topic, message) {
|
|
93
|
+
const expandedTopic = this.expandTopic(accessory, topic);
|
|
94
|
+
// No valid topic returned, we're done.
|
|
95
|
+
if (!expandedTopic) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
this.log.debug("MQTT publish: %s Message: %s.", expandedTopic, message);
|
|
99
|
+
// By default, we publish as: unifi/access/mac/event/name
|
|
100
|
+
this.mqtt?.publish(expandedTopic, message);
|
|
101
|
+
}
|
|
102
|
+
// Subscribe to an MQTT topic.
|
|
103
|
+
subscribe(accessory, topic, callback) {
|
|
104
|
+
const expandedTopic = this.expandTopic(accessory, topic);
|
|
105
|
+
// No valid topic returned, we're done.
|
|
106
|
+
if (!expandedTopic) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
this.log.debug("MQTT subscribe: %s.", expandedTopic);
|
|
110
|
+
// Add to our callback list.
|
|
111
|
+
this.subscriptions[expandedTopic] = callback;
|
|
112
|
+
// Tell MQTT we're subscribing to this event.
|
|
113
|
+
// By default, we subscribe as: unifi/access/mac/event/name.
|
|
114
|
+
this.mqtt?.subscribe(expandedTopic);
|
|
115
|
+
}
|
|
116
|
+
// Subscribe to a specific MQTT topic and publish a value on a get request.
|
|
117
|
+
subscribeGet(accessory, topic, type, getValue) {
|
|
118
|
+
// Return the current status of a given sensor.
|
|
119
|
+
this.subscribe(accessory, topic + "/get", (message) => {
|
|
120
|
+
const value = message.toString().toLowerCase();
|
|
121
|
+
// When we get the right message, we return the system information JSON.
|
|
122
|
+
if (value !== "true") {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
this.publish(accessory, topic, getValue());
|
|
126
|
+
(this.controller.configuredDevices[accessory.UUID]?.log ?? this.log).info("MQTT: %s status published.", type);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
// Subscribe to a specific MQTT topic and set a value on a set request.
|
|
130
|
+
subscribeSet(accessory, topic, type, setValue) {
|
|
131
|
+
// Return the current status of a given sensor.
|
|
132
|
+
this.subscribe(accessory, topic + "/set", (message) => {
|
|
133
|
+
const value = message.toString().toLowerCase();
|
|
134
|
+
// Set our value and inform the user.
|
|
135
|
+
setValue(value);
|
|
136
|
+
(this.controller.configuredDevices[accessory.UUID]?.log ?? this.log).info("MQTT: set message received for %s: %s.", type, value);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
// Unsubscribe to an MQTT topic.
|
|
140
|
+
unsubscribe(accessory, topic) {
|
|
141
|
+
const expandedTopic = this.expandTopic(accessory, topic);
|
|
142
|
+
// No valid topic returned, we're done.
|
|
143
|
+
if (!expandedTopic) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
delete this.subscriptions[expandedTopic];
|
|
147
|
+
}
|
|
148
|
+
// Expand a topic to a unique, fully formed one.
|
|
149
|
+
expandTopic(accessory, topic) {
|
|
150
|
+
// No accessory, we're done.
|
|
151
|
+
if (!accessory) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
// Check if we were passed the MAC as an input. Otherwise, assume it's the controller's MAC initially.
|
|
155
|
+
let mac = (typeof accessory === "string") ? accessory : accessory.context.controller;
|
|
156
|
+
// Check to see if it's really an Access device...if it is, use it's MAC address.
|
|
157
|
+
if ((typeof accessory !== "string") && ("mac" in accessory.context)) {
|
|
158
|
+
mac = accessory.context.mac;
|
|
159
|
+
}
|
|
160
|
+
return this.config.mqttTopic + "/" + mac.replace(/:/g, "") + "/" + topic;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=access-mqtt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-mqtt.js","sourceRoot":"","sources":["../src/access-mqtt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { AccessControllerConfig, AccessDeviceConfig } from "unifi-access";
|
|
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
|
+
export declare const featureOptionCategories: {
|
|
17
|
+
description: string;
|
|
18
|
+
modelKey: string[];
|
|
19
|
+
name: string;
|
|
20
|
+
}[];
|
|
21
|
+
export declare const featureOptions: {
|
|
22
|
+
[index: string]: FeatureOption[];
|
|
23
|
+
};
|
|
24
|
+
export interface FeatureOption {
|
|
25
|
+
default: boolean;
|
|
26
|
+
defaultValue?: number | string;
|
|
27
|
+
description: string;
|
|
28
|
+
group?: string;
|
|
29
|
+
hasFeature?: string[];
|
|
30
|
+
hasProperty?: string[];
|
|
31
|
+
hasSmartObjectType?: string[];
|
|
32
|
+
modelKey?: string[];
|
|
33
|
+
name: string;
|
|
34
|
+
}
|
|
35
|
+
export declare function isOptionEnabled(configOptions: string[], controller: AccessControllerConfig | null, device: AccessControllerConfig | AccessDeviceConfig | null, option?: string, defaultReturnValue?: boolean): boolean;
|
|
36
|
+
export declare function getOptionValue(configOptions: string[], controller: AccessControllerConfig | null, device: AccessControllerConfig | AccessDeviceConfig | null, option: string): string | undefined;
|
|
37
|
+
export declare function getOptionFloat(optionValue: string | undefined): number | undefined;
|
|
38
|
+
export declare function getOptionNumber(optionValue: string | undefined): number | undefined;
|