diff --git a/.gitignore b/.gitignore
index 2d0bc9a..580d67c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,3 @@
-# Ignore compiled code
-dist
-homebridge-ui/public
-
# ------------- Defaults ------------- #
# Logs
@@ -87,7 +83,6 @@ web_modules/
# Nuxt.js build / generate output
.nuxt
-dist
# Gatsby files
.cache/
diff --git a/dist/bold/api/api.d.ts b/dist/bold/api/api.d.ts
new file mode 100644
index 0000000..58f81b0
--- /dev/null
+++ b/dist/bold/api/api.d.ts
@@ -0,0 +1,28 @@
+///
+import { EventEmitter } from 'node:events';
+import type { BoldApiAuthentication, BoldApiCommand, BoldApiDevice, BoldApiHandshake } from './types';
+export declare type BoldApiEvent = {
+ refresh: (newAuth: BoldApiAuthentication, oldAuth?: BoldApiAuthentication) => void;
+};
+export declare interface BoldApi {
+ on(event: U, listener: BoldApiEvent[U]): this;
+ off(event: U, listener: BoldApiEvent[U]): this;
+ emit(event: U, ...args: Parameters): boolean;
+}
+export declare class BoldApi extends EventEmitter {
+ private auth?;
+ private tokenExpiry?;
+ constructor(auth?: Readonly | undefined);
+ private updateAuth;
+ call>(method: 'GET' | 'POST', endpoint: string, payload?: Record, needsAuth?: boolean, asFormData?: boolean): Promise;
+ requestVerificationCode(phoneNumber: string): Promise;
+ verifyVerificationCode(phoneNumber: string, verificationCode: string): Promise;
+ private processLegacyAuthResponse;
+ private processDefaultAuthResponse;
+ login(phoneNumber: string, password: string, verificationToken: string): Promise;
+ refresh(): Promise;
+ getEffectiveDevicePermissions(): Promise;
+ getHandshakes(deviceId: number): Promise;
+ getActivateCommands(deviceId: number): Promise;
+}
+//# sourceMappingURL=api.d.ts.map
\ No newline at end of file
diff --git a/dist/bold/api/api.d.ts.map b/dist/bold/api/api.d.ts.map
new file mode 100644
index 0000000..7d9af9d
--- /dev/null
+++ b/dist/bold/api/api.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/bold/api/api.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,OAAO,KAAK,EACV,qBAAqB,EACrB,cAAc,EAEd,aAAa,EAGb,gBAAgB,EAKjB,MAAM,SAAS,CAAC;AAQjB,oBAAY,YAAY,GAAG;IACzB,OAAO,EAAE,CAAC,OAAO,EAAE,qBAAqB,EAAE,OAAO,CAAC,EAAE,qBAAqB,KAAK,IAAI,CAAC;CACpF,CAAC;AAEF,MAAM,CAAC,OAAO,WAAW,OAAO;IAC9B,EAAE,CAAC,CAAC,SAAS,MAAM,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC5E,GAAG,CAAC,CAAC,SAAS,MAAM,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7E,IAAI,CAAC,CAAC,SAAS,MAAM,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;CAC7F;AAED,qBAAa,OAAQ,SAAQ,YAAY;IAG3B,OAAO,CAAC,IAAI,CAAC;IAFzB,OAAO,CAAC,WAAW,CAAC,CAAO;gBAEP,IAAI,CAAC,6CAAiC;IAI1D,OAAO,CAAC,UAAU;IAML,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EACpD,MAAM,EAAE,KAAK,GAAG,MAAM,EACtB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,EAC1D,SAAS,UAAO,EAChB,UAAU,UAAQ,GACjB,OAAO,CAAC,YAAY,CAAC;IAmDX,uBAAuB,CAAC,WAAW,EAAE,MAAM;IAa3C,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM;IAcjF,OAAO,CAAC,yBAAyB;IAejC,OAAO,CAAC,0BAA0B;IAoBrB,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAoBvG,OAAO,IAAI,OAAO,CAAC,qBAAqB,CAAC;IAwCzC,6BAA6B,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAIzD,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAO5D,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;CAM9E"}
\ No newline at end of file
diff --git a/dist/bold/api/api.js b/dist/bold/api/api.js
new file mode 100644
index 0000000..bb82615
--- /dev/null
+++ b/dist/bold/api/api.js
@@ -0,0 +1,153 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.BoldApi = void 0;
+const node_events_1 = require("node:events");
+const node_fetch_1 = __importDefault(require("node-fetch"));
+const BASE_URL = 'https://api.boldsmartlock.com/';
+const DEFAULT_AUTH_REFRESH_URL = 'https://bold.nienhuisdevelopment.com/oauth/refresh';
+const LEGACY_AUTH_CLIENT_ID = 'BoldApp';
+const LEGACY_CLIENT_SECRET = 'pgJFgnGB87f9ednFiiHygCbf';
+class BoldApi extends node_events_1.EventEmitter {
+ constructor(auth) {
+ super();
+ this.auth = auth;
+ }
+ updateAuth(newAuth) {
+ const oldAuth = this.auth;
+ this.auth = newAuth;
+ this.emit('refresh', newAuth, oldAuth);
+ }
+ async call(method, endpoint, payload, needsAuth = true, asFormData = false) {
+ var _a, _b, _c, _d, _e, _f;
+ const url = `${BASE_URL}${endpoint.replace(/^\//, '')}`;
+ const headers = {};
+ if (needsAuth) {
+ if (!this.auth) {
+ throw new Error('Missing access token');
+ }
+ if (!this.tokenExpiry || new Date() > this.tokenExpiry) {
+ await this.refresh();
+ }
+ headers['Authorization'] = `Bearer ${this.auth.accessToken}`;
+ }
+ if (payload) {
+ headers['ContentType'] = asFormData ? 'application/x-www-form-urlencoded' : 'application/json';
+ }
+ const response = await (0, node_fetch_1.default)(url, {
+ method,
+ headers,
+ body: payload &&
+ (asFormData ? new URLSearchParams(payload).toString() : JSON.stringify(payload)),
+ });
+ let body;
+ try {
+ body = (await response.json());
+ }
+ catch (error) {
+ throw new Error(await response.text());
+ }
+ if (!response.ok) {
+ const error = body;
+ throw new Error((_f = (_e = (_d = (_c = (_b = (_a = error.error_description) !== null && _a !== void 0 ? _a : error.errorMessage) !== null && _b !== void 0 ? _b : error.message) !== null && _c !== void 0 ? _c : error.error) !== null && _d !== void 0 ? _d : error.errorCode) !== null && _e !== void 0 ? _e : error.code) !== null && _f !== void 0 ? _f : 'Unknown API response');
+ }
+ return body;
+ }
+ async requestVerificationCode(phoneNumber) {
+ await this.call('POST', 'v2/verification/request-code', {
+ phoneNumber,
+ language: 'en',
+ destination: 'Phone',
+ }, false);
+ }
+ async verifyVerificationCode(phoneNumber, verificationCode) {
+ const { verificationToken } = await this.call('POST', 'v2/verification/verify-code', {
+ phoneNumber,
+ verificationCode,
+ }, false);
+ return verificationToken;
+ }
+ processLegacyAuthResponse(response, requestTime = new Date()) {
+ var _a;
+ const auth = {
+ accessToken: response.access_token,
+ refreshToken: response.refresh_token,
+ legacyAuthentication: true,
+ };
+ this.updateAuth(auth);
+ this.tokenExpiry = new Date(requestTime.getTime() + ((_a = response.expires_in) !== null && _a !== void 0 ? _a : 86400) * 1000);
+ return auth;
+ }
+ processDefaultAuthResponse(response, requestTime = new Date()) {
+ var _a;
+ if (!response.success) {
+ throw new Error(response.error.message);
+ }
+ const auth = {
+ accessToken: response.data.accessToken,
+ refreshToken: response.data.refreshToken,
+ legacyAuthentication: false,
+ ...(((_a = this.auth) === null || _a === void 0 ? void 0 : _a.refreshURL) && { refreshURL: this.auth.refreshURL }),
+ };
+ this.updateAuth(auth);
+ this.tokenExpiry = new Date(requestTime.getTime() + 86400 * 1000);
+ return auth;
+ }
+ async login(phoneNumber, password, verificationToken) {
+ const now = new Date();
+ const response = await this.call('POST', 'v2/oauth/token', {
+ grant_type: 'password',
+ username: phoneNumber,
+ password,
+ mfa_token: verificationToken,
+ client_id: LEGACY_AUTH_CLIENT_ID,
+ client_secret: LEGACY_CLIENT_SECRET,
+ }, false, true);
+ return this.processLegacyAuthResponse(response, now);
+ }
+ async refresh() {
+ var _a;
+ if (!this.auth) {
+ throw new Error('Missing refresh token');
+ }
+ if (this.auth.legacyAuthentication) {
+ const now = new Date();
+ const response = await this.call('POST', 'v2/oauth/token', {
+ grant_type: 'refresh_token',
+ refresh_token: this.auth.refreshToken,
+ client_id: LEGACY_AUTH_CLIENT_ID,
+ client_secret: LEGACY_CLIENT_SECRET,
+ }, false, true);
+ return this.processLegacyAuthResponse(response, now);
+ }
+ else {
+ const now = new Date();
+ const response = await (0, node_fetch_1.default)((_a = this.auth.refreshURL) !== null && _a !== void 0 ? _a : DEFAULT_AUTH_REFRESH_URL, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ refreshToken: this.auth.refreshToken }),
+ });
+ let body;
+ try {
+ body = (await response.json());
+ }
+ catch (error) {
+ throw new Error('Token refresh failed');
+ }
+ return this.processDefaultAuthResponse(body, now);
+ }
+ }
+ async getEffectiveDevicePermissions() {
+ return await this.call('GET', 'v1/effective-device-permissions');
+ }
+ async getHandshakes(deviceId) {
+ return await this.call('GET', `v1/controller/v0/handshakes?deviceId=${encodeURIComponent(deviceId)}`);
+ }
+ async getActivateCommands(deviceId) {
+ return await this.call('GET', `v1/controller/v0/commands/activate-device?deviceId=${encodeURIComponent(deviceId)}`);
+ }
+}
+exports.BoldApi = BoldApi;
+//# sourceMappingURL=api.js.map
\ No newline at end of file
diff --git a/dist/bold/api/api.js.map b/dist/bold/api/api.js.map
new file mode 100644
index 0000000..a2ba220
--- /dev/null
+++ b/dist/bold/api/api.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/bold/api/api.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/dist/bold/api/index.d.ts b/dist/bold/api/index.d.ts
new file mode 100644
index 0000000..dc32713
--- /dev/null
+++ b/dist/bold/api/index.d.ts
@@ -0,0 +1,3 @@
+export * from './api.js';
+export * from './types.js';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/dist/bold/api/index.d.ts.map b/dist/bold/api/index.d.ts.map
new file mode 100644
index 0000000..c2c003f
--- /dev/null
+++ b/dist/bold/api/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/bold/api/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC"}
\ No newline at end of file
diff --git a/dist/bold/api/index.js b/dist/bold/api/index.js
new file mode 100644
index 0000000..3547f8a
--- /dev/null
+++ b/dist/bold/api/index.js
@@ -0,0 +1,15 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./api.js"), exports);
+__exportStar(require("./types.js"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/dist/bold/api/index.js.map b/dist/bold/api/index.js.map
new file mode 100644
index 0000000..bdeefc1
--- /dev/null
+++ b/dist/bold/api/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/bold/api/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAyB;AACzB,6CAA2B"}
\ No newline at end of file
diff --git a/dist/bold/api/types.d.ts b/dist/bold/api/types.d.ts
new file mode 100644
index 0000000..ca4fc6c
--- /dev/null
+++ b/dist/bold/api/types.d.ts
@@ -0,0 +1,157 @@
+declare type Base64String = string;
+declare type IsoDateTimeString = string;
+export declare type BoldApiAuthentication = {
+ accessToken: string;
+ refreshToken: string;
+ legacyAuthentication: boolean;
+ refreshURL?: string;
+};
+export declare type BoldApiDeviceOwner = {
+ organizationId: number;
+ accountId: number;
+ name: string;
+ firstName: string;
+ lastName: string;
+};
+export declare type BoldApiDeviceModel = {
+ id: number;
+ make: string;
+ model: string;
+ name: string;
+ isCertified: boolean;
+ deviceType: BoldApiDeviceType;
+};
+export declare type BoldApiDeviceType = {
+ id: number;
+ name: string;
+ description: string;
+};
+export declare type BoldApiDevicePermissionSchedule = {
+ dayOfWeek: 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday' | 'Saturday' | 'Sunday';
+ period: {
+ startTime: string;
+ endTime: string;
+ };
+ recurrence: 'Weekly';
+};
+export declare type BoldApiDevicePermission = {
+ devicePermission: 'UseDevice' | string;
+ schedule: BoldApiDevicePermissionSchedule[];
+ startDate?: string;
+ endDate?: string;
+ startTime?: string;
+ endTime?: string;
+};
+export declare type BoldApiDeviceSettings = {
+ deviceId: number;
+ activationTime: number;
+ soundVolume: number;
+ pressButtonActivation: boolean;
+ controllerFunctionality: boolean;
+ backupPin1: number;
+ backupPin2: number;
+ backupPin3: number;
+ backupPinsConfigured: boolean;
+ acknowledged: boolean;
+ dateCreated: IsoDateTimeString;
+ dateModified: IsoDateTimeString;
+ backupPin1Name?: string;
+ backupPin2Name?: string;
+ backupPin3Name?: string;
+ dateLastExternalSync: IsoDateTimeString;
+ relayNormallyOpen: boolean;
+ vibrationTamperDetection: boolean;
+ vibrationTamperSensitivity: number;
+ rotationsTamperDetection: boolean;
+};
+export declare type BoldApiDeviceFeatureSet = {
+ isActivatable: boolean;
+ storeDeviceEvents: boolean;
+};
+export declare type BoldApiDevice = {
+ id: number;
+ deviceId: number;
+ serial?: string;
+ owner: BoldApiDeviceOwner;
+ name: string;
+ personalName: string;
+ organizationId: number;
+ model: BoldApiDeviceModel;
+ type: BoldApiDeviceType;
+ actualFirmwareVersion: number;
+ requiredFirmwareVersion: number;
+ dateCreated: IsoDateTimeString;
+ dateModified: IsoDateTimeString;
+ timeZone: string;
+ batteryLevel: 'Excellent' | string;
+ batteryLastMeasurement: IsoDateTimeString;
+ settingsAcknowledged: boolean;
+ permissions: BoldApiDevicePermission[];
+ permissionAdministrate: boolean;
+ permissionRemoteActivate: boolean;
+ permissionAssignKeyfob: boolean;
+ organizationSuperUser: boolean;
+ permissionHash: Base64String;
+ settings: BoldApiDeviceSettings;
+ featureSet: BoldApiDeviceFeatureSet;
+ synced: boolean;
+ secure: boolean;
+ carouselImageUrl: string;
+};
+export declare type BoldApiHandshake = {
+ deviceId: number;
+ clientId: number;
+ expiration: IsoDateTimeString;
+ handshakeKey: Base64String;
+ permissionHash: Base64String;
+ payload: Base64String;
+};
+declare const BoldApiCommandTypes: {
+ readonly Activate: 1;
+ readonly ActivateWithKeepActive: 2;
+ readonly Deactivate: 3;
+};
+export declare type BoldApiCommandType = typeof BoldApiCommandTypes[keyof typeof BoldApiCommandTypes];
+export declare type BoldApiCommand = {
+ deviceId: number;
+ commandType: BoldApiCommandType;
+ expiration: IsoDateTimeString;
+ permissionHash: Base64String;
+ payload: Base64String;
+};
+export declare type BoldApiErrorResponse = {
+ error?: string;
+ error_description?: string;
+ message?: string;
+ code?: string;
+ errorMessage?: string;
+ errorCode?: string;
+};
+export declare type BoldApiVerifyCodeResponse = {
+ verificationToken: string;
+};
+export declare type BoldApiOAuthResponse = {
+ access_token: string;
+ refresh_token: string;
+ token_type: 'Bearer';
+ expires_in: number;
+ account_id: number;
+};
+export declare type BoldDefaultAuthResponse = {
+ success: true;
+ data: {
+ accessToken: string;
+ refreshToken: string;
+ };
+} | {
+ success: false;
+ error: {
+ code: number;
+ message: string;
+ };
+};
+export declare type BoldApiEffectiveDevicePermissionsResponse = BoldApiDevice[];
+export declare type BoldApiHandshakesResponse = BoldApiHandshake[];
+export declare type BoldApiCommandsResponse = BoldApiCommand[];
+export {};
+//# sourceMappingURL=types.d.ts.map
\ No newline at end of file
diff --git a/dist/bold/api/types.d.ts.map b/dist/bold/api/types.d.ts.map
new file mode 100644
index 0000000..61df4ac
--- /dev/null
+++ b/dist/bold/api/types.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/bold/api/types.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/dist/bold/api/types.js b/dist/bold/api/types.js
new file mode 100644
index 0000000..b0862b4
--- /dev/null
+++ b/dist/bold/api/types.js
@@ -0,0 +1,8 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const BoldApiCommandTypes = {
+ Activate: 1,
+ ActivateWithKeepActive: 2,
+ Deactivate: 3,
+};
+//# sourceMappingURL=types.js.map
\ No newline at end of file
diff --git a/dist/bold/api/types.js.map b/dist/bold/api/types.js.map
new file mode 100644
index 0000000..d0f42bf
--- /dev/null
+++ b/dist/bold/api/types.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/bold/api/types.ts"],"names":[],"mappings":";;AAuHA,MAAM,mBAAmB,GAAG;IAC1B,QAAQ,EAAE,CAAC;IACX,sBAAsB,EAAE,CAAC;IACzB,UAAU,EAAE,CAAC;CACL,CAAC"}
\ No newline at end of file
diff --git a/dist/bold/ble/ble.d.ts b/dist/bold/ble/ble.d.ts
new file mode 100644
index 0000000..bccc3e0
--- /dev/null
+++ b/dist/bold/ble/ble.d.ts
@@ -0,0 +1,14 @@
+import { Peripheral } from '@abandonware/noble';
+import { Logger } from 'homebridge';
+import { BoldApiCommand, BoldApiHandshake } from '../api';
+import { BoldBleDeviceInfo } from './types';
+export declare class BoldBle {
+ private readonly log;
+ constructor(log: Logger);
+ private waitForBluetooth;
+ discoverBoldPeripherals(deviceIds?: number[], timeout?: number): Promise