@uboness/homebridge-tedee 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +17 -0
  3. package/README.md +41 -0
  4. package/config.schema.json +146 -0
  5. package/dist/common.d.ts +25 -0
  6. package/dist/common.d.ts.map +1 -0
  7. package/dist/common.js +51 -0
  8. package/dist/common.js.map +1 -0
  9. package/dist/device/device.d.ts +26 -0
  10. package/dist/device/device.d.ts.map +1 -0
  11. package/dist/device/device.js +46 -0
  12. package/dist/device/device.js.map +1 -0
  13. package/dist/device/index.d.ts +5 -0
  14. package/dist/device/index.d.ts.map +1 -0
  15. package/dist/device/index.js +5 -0
  16. package/dist/device/index.js.map +1 -0
  17. package/dist/device/lock.d.ts +28 -0
  18. package/dist/device/lock.d.ts.map +1 -0
  19. package/dist/device/lock.js +175 -0
  20. package/dist/device/lock.js.map +1 -0
  21. package/dist/index.d.ts +4 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +6 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/logger.d.ts +16 -0
  26. package/dist/logger.d.ts.map +1 -0
  27. package/dist/logger.js +26 -0
  28. package/dist/logger.js.map +1 -0
  29. package/dist/settings.d.ts +9 -0
  30. package/dist/settings.d.ts.map +1 -0
  31. package/dist/settings.js +10 -0
  32. package/dist/settings.js.map +1 -0
  33. package/dist/tedee-client.d.ts +51 -0
  34. package/dist/tedee-client.d.ts.map +1 -0
  35. package/dist/tedee-client.js +442 -0
  36. package/dist/tedee-client.js.map +1 -0
  37. package/dist/tedee-event-server.d.ts +25 -0
  38. package/dist/tedee-event-server.d.ts.map +1 -0
  39. package/dist/tedee-event-server.js +109 -0
  40. package/dist/tedee-event-server.js.map +1 -0
  41. package/dist/tedee-platform.d.ts +51 -0
  42. package/dist/tedee-platform.d.ts.map +1 -0
  43. package/dist/tedee-platform.js +186 -0
  44. package/dist/tedee-platform.js.map +1 -0
  45. package/dist/tedee.d.ts +99 -0
  46. package/dist/tedee.d.ts.map +1 -0
  47. package/dist/tedee.js +30 -0
  48. package/dist/tedee.js.map +1 -0
  49. package/package.json +66 -0
  50. package/tsconfig.json +31 -0
@@ -0,0 +1,16 @@
1
+ import { Logging } from 'homebridge';
2
+ export type ILogger = Pick<Logging, 'debug' | 'info' | 'warn' | 'error'> & {
3
+ getLogger(category: string, ...categories: string[]): ILogger;
4
+ };
5
+ export declare class ContextLogger implements ILogger {
6
+ private readonly logger;
7
+ readonly categories: string[];
8
+ readonly context: string;
9
+ constructor(logger: Omit<ILogger, 'getLogger'>, ...categories: string[]);
10
+ debug(message: string, ...parameters: any[]): void;
11
+ error(message: string, ...parameters: any[]): void;
12
+ info(message: string, ...parameters: any[]): void;
13
+ warn(message: string, ...parameters: any[]): void;
14
+ getLogger(category: string, ...categories: string[]): ILogger;
15
+ }
16
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,MAAM,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG;IACvE,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAA;CAChE,CAAA;AAED,qBAAa,aAAc,YAAW,OAAO;IAEzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE;IAMvE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,GAAG,EAAE,GAAG,IAAI;IAIlD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,GAAG,EAAE,GAAG,IAAI;IAIlD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,GAAG,EAAE,GAAG,IAAI;IAIjD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,GAAG,EAAE,GAAG,IAAI;IAIjD,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO;CAGhE"}
package/dist/logger.js ADDED
@@ -0,0 +1,26 @@
1
+ export class ContextLogger {
2
+ logger;
3
+ categories;
4
+ context;
5
+ constructor(logger, ...categories) {
6
+ this.logger = logger;
7
+ this.categories = categories;
8
+ this.context = categories.length === 0 ? '' : `[${categories.join('] [')}]`;
9
+ }
10
+ debug(message, ...parameters) {
11
+ this.logger.debug(this.context ? `${this.context} ${message}` : message, ...parameters);
12
+ }
13
+ error(message, ...parameters) {
14
+ this.logger.error(this.context ? `${this.context} ${message}` : message, ...parameters);
15
+ }
16
+ info(message, ...parameters) {
17
+ this.logger.info(this.context ? `${this.context} ${message}` : message, ...parameters);
18
+ }
19
+ warn(message, ...parameters) {
20
+ this.logger.warn(this.context ? `${this.context} ${message}` : message, ...parameters);
21
+ }
22
+ getLogger(category, ...categories) {
23
+ return new ContextLogger(this.logger, ...[...this.categories, category, ...categories]);
24
+ }
25
+ }
26
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,aAAa;IAEL,MAAM,CAA6B;IAC3C,UAAU,CAAW;IACrB,OAAO,CAAS;IAEzB,YAAY,MAAkC,EAAE,GAAG,UAAoB;QACnE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;IAChF,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,GAAG,UAAiB;QACvC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,UAAU,CAAC,CAAC;IAC5F,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,GAAG,UAAiB;QACvC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,UAAU,CAAC,CAAC;IAC5F,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,GAAG,UAAiB;QACtC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,UAAU,CAAC,CAAC;IAC3F,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,GAAG,UAAiB;QACtC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,UAAU,CAAC,CAAC;IAC3F,CAAC;IAED,SAAS,CAAC,QAAgB,EAAE,GAAG,UAAoB;QAC/C,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAE,GAAG,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAE,CAAC,CAAC;IAC9F,CAAC;CACJ"}
@@ -0,0 +1,9 @@
1
+ import { Tedee } from './tedee.ts';
2
+ export declare const PLATFORM_NAME = "Tedee";
3
+ export declare const PLUGIN_NAME: string;
4
+ export declare const WEBHOOK_INSTANCE_HEADER = "X-Homebridge-Tedee-Instance";
5
+ export declare const WEBHOOK_PATH = "/tedee/events";
6
+ export declare const WEBHOOK_DEFAULT_PORT = 8088;
7
+ export declare const DEFAULT_LOW_BATTERY_THRESHOLD = 20;
8
+ export declare const DEFAULT_LOCK_UNLOCK_MODE = Tedee.UnlockMode.WithoutPull;
9
+ //# sourceMappingURL=settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,eAAO,MAAM,aAAa,UAAU,CAAC;AACrC,eAAO,MAAM,WAAW,QAAW,CAAC;AAEpC,eAAO,MAAM,uBAAuB,gCAAgC,CAAC;AACrE,eAAO,MAAM,YAAY,kBAAkB,CAAC;AAC5C,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAEhD,eAAO,MAAM,wBAAwB,+BAA+B,CAAC"}
@@ -0,0 +1,10 @@
1
+ import pkg from '../package.json' with { type: 'json' };
2
+ import { Tedee } from "./tedee.js";
3
+ export const PLATFORM_NAME = 'Tedee';
4
+ export const PLUGIN_NAME = pkg.name;
5
+ export const WEBHOOK_INSTANCE_HEADER = 'X-Homebridge-Tedee-Instance';
6
+ export const WEBHOOK_PATH = '/tedee/events';
7
+ export const WEBHOOK_DEFAULT_PORT = 8088;
8
+ export const DEFAULT_LOW_BATTERY_THRESHOLD = 20;
9
+ export const DEFAULT_LOCK_UNLOCK_MODE = Tedee.UnlockMode.WithoutPull;
10
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC;AACrC,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC,IAAI,CAAC;AAEpC,MAAM,CAAC,MAAM,uBAAuB,GAAG,6BAA6B,CAAC;AACrE,MAAM,CAAC,MAAM,YAAY,GAAG,eAAe,CAAC;AAC5C,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAEzC,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAEhD,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC"}
@@ -0,0 +1,51 @@
1
+ import type { Detachable, Promisable } from './common.ts';
2
+ import type { ILogger } from './logger.ts';
3
+ import type { Tedee } from './tedee.ts';
4
+ type EventMap = {
5
+ connect: [];
6
+ disconnect: [];
7
+ close: [];
8
+ event: [Tedee.Event];
9
+ };
10
+ type EventHandler<Event extends keyof EventMap> = (...args: EventMap[Event]) => Promisable;
11
+ export declare class TedeeClient {
12
+ #private;
13
+ constructor(config: TedeeClient.Config, logger: ILogger);
14
+ get state(): TedeeClient.State;
15
+ start(): Promise<void>;
16
+ close(): Promise<void>;
17
+ on<Event extends keyof EventMap>(event: Event, handler: EventHandler<Event>): Detachable;
18
+ bridge(): Promise<Tedee.Bridge>;
19
+ listLocks(): Promise<Tedee.Lock[]>;
20
+ getLock(id: number): Promise<Tedee.Lock>;
21
+ lock(id: number): Promise<void>;
22
+ unlock(id: number, mode?: Tedee.UnlockMode): Promise<void>;
23
+ pullSpring(id: number): Promise<void>;
24
+ listCallbacks(): Promise<Tedee.Callback[]>;
25
+ addCallback(registration: Tedee.CallbackRegistration): Promise<number>;
26
+ updateCallback(id: number, registration: Tedee.CallbackRegistration): Promise<void>;
27
+ deleteCallback(id: number): Promise<void>;
28
+ private callbackMatches;
29
+ private headerValue;
30
+ private rest;
31
+ private restUrl;
32
+ private apiToken;
33
+ private ensureCallback;
34
+ }
35
+ export declare namespace TedeeClient {
36
+ type State = 'init' | 'connecting' | 'connected' | 'disconnected' | 'closing' | 'closed';
37
+ type Method = 'get' | 'post' | 'put' | 'delete';
38
+ type Config = {
39
+ host: string;
40
+ port?: number;
41
+ token: string;
42
+ tokenMode?: 'plain' | 'encrypted';
43
+ apiVersion?: string;
44
+ webhook: {
45
+ port?: number;
46
+ instanceId: string;
47
+ };
48
+ };
49
+ }
50
+ export {};
51
+ //# sourceMappingURL=tedee-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tedee-client.d.ts","sourceRoot":"","sources":["../src/tedee-client.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAQ,UAAU,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,KAAK,QAAQ,GAAG;IACZ,OAAO,EAAE,EAAE,CAAC;IACZ,UAAU,EAAE,EAAE,CAAC;IACf,KAAK,EAAE,EAAE,CAAC;IACV,KAAK,EAAE,CAAE,KAAK,CAAC,KAAK,CAAE,CAAA;CACzB,CAAA;AAED,KAAK,YAAY,CAAC,KAAK,SAAS,MAAM,QAAQ,IAAI,CAAC,GAAG,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,UAAU,CAAC;AAY3F,qBAAa,WAAW;;gBAgBR,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO;IAWvD,IAAI,KAAK,IAAI,WAAW,CAAC,KAAK,CAE7B;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAyCtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,EAAE,CAAC,KAAK,SAAS,MAAM,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,GAAG,UAAU;IAMlF,MAAM,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC;IAI/B,SAAS,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAIlC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;IAIxC,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK/B,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,KAAK,CAAC,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1D,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKrC,aAAa,IAAI,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;IAI1C,WAAW,CAAC,YAAY,EAAE,KAAK,CAAC,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC;IAYtE,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,CAAC,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAInF,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,WAAW;YA4BL,IAAI;IAuClB,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,QAAQ;YASF,cAAc;CA4N/B;AAED,yBAAiB,WAAW,CAAC;IAEzB,KAAY,KAAK,GAAG,MAAM,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc,GAAG,SAAS,GAAG,QAAQ,CAAC;IAEhG,KAAY,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;IAEvD,KAAY,MAAM,GAAG;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC;QAClC,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE;YACL,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,UAAU,EAAE,MAAM,CAAA;SACrB,CAAA;KACJ,CAAA;CAEJ"}
@@ -0,0 +1,442 @@
1
+ import EventEmitter from 'node:events';
2
+ import { createHash } from 'node:crypto';
3
+ import { lookup } from 'node:dns/promises';
4
+ import { networkInterfaces } from 'node:os';
5
+ import { fetch } from 'undici';
6
+ import { sleep } from "./common.js";
7
+ import { WEBHOOK_INSTANCE_HEADER } from "./settings.js";
8
+ import { TedeeEventServer } from "./tedee-event-server.js";
9
+ const HEARTBEAT_INTERVAL_MS = 60_000;
10
+ const START_MAX_ATTEMPTS = 5;
11
+ // Tedee bridge caps the local API at ~1 request/second.
12
+ const REQUEST_INTERVAL_MS = 1_000;
13
+ // Waits before retrying connect during start() (between attempt N and N+1).
14
+ const START_BACKOFFS_MS = [3_000, 5_000, 8_000, 13_000];
15
+ // Waits between reconnect attempts; last value repeats indefinitely.
16
+ const RECONNECT_BACKOFFS_MS = [3_000, 5_000, 8_000, 13_000, 21_000, 30_000];
17
+ export class TedeeClient {
18
+ #config;
19
+ #logger;
20
+ #emitter = new EventEmitter({ captureRejections: false });
21
+ #server;
22
+ #abort = new AbortController();
23
+ #state = 'init';
24
+ #queue = Promise.resolve();
25
+ #lastRequestAt = 0;
26
+ #heartbeatTimer;
27
+ #reconnecting = false;
28
+ #registration;
29
+ #localHost;
30
+ constructor(config, logger) {
31
+ this.#config = config;
32
+ this.#logger = logger.getLogger('client');
33
+ this.#emitter.setMaxListeners(1000);
34
+ this.#server = new TedeeEventServer({
35
+ port: config.webhook.port,
36
+ instanceId: config.webhook.instanceId
37
+ }, this.#logger);
38
+ this.#server.on('event', event => { this.#emitter.emit('event', event); });
39
+ }
40
+ get state() {
41
+ return this.#state;
42
+ }
43
+ async start() {
44
+ if (this.#state === 'closed' || this.#state === 'closing') {
45
+ throw new Error('Tedee client is closed');
46
+ }
47
+ if (this.#state !== 'init') {
48
+ return; // start was already called
49
+ }
50
+ this.#state = 'connecting';
51
+ this.#localHost = await this.#resolveLocalHost();
52
+ this.#logger.debug(`resolved local host [${this.#localHost}] for webhook server`);
53
+ await this.#server.start();
54
+ this.#registration = this.#buildRegistration();
55
+ let lastError;
56
+ for (let attempt = 0; attempt < START_MAX_ATTEMPTS; attempt++) {
57
+ if (this.#aborted()) {
58
+ throw new Error('Tedee client closed before connection was established');
59
+ }
60
+ if (attempt > 0) {
61
+ const wait = START_BACKOFFS_MS[Math.min(attempt - 1, START_BACKOFFS_MS.length - 1)];
62
+ this.#logger.info(`retrying Tedee connection in ${Math.round(wait / 1000)}s (attempt ${attempt + 1}/${START_MAX_ATTEMPTS})`);
63
+ try {
64
+ await this.#waitInterruptible(wait);
65
+ }
66
+ catch {
67
+ throw new Error('Tedee client closed before connection was established');
68
+ }
69
+ }
70
+ try {
71
+ await this.#doConnect();
72
+ return;
73
+ }
74
+ catch (error) {
75
+ lastError = error;
76
+ this.#logger.warn(`failed to connect to Tedee (attempt ${attempt + 1}/${START_MAX_ATTEMPTS})`, error);
77
+ }
78
+ }
79
+ await this.#shutdown();
80
+ throw lastError ?? new Error('Failed to connect to Tedee bridge');
81
+ }
82
+ async close() {
83
+ if (this.#state === 'closed' || this.#state === 'closing') {
84
+ return;
85
+ }
86
+ await this.#shutdown();
87
+ }
88
+ on(event, handler) {
89
+ const listener = handler;
90
+ this.#emitter.on(event, listener);
91
+ return { detach: () => this.#emitter.off(event, listener) };
92
+ }
93
+ async bridge() {
94
+ return await this.rest('get', '/bridge');
95
+ }
96
+ async listLocks() {
97
+ return await this.rest('get', '/lock');
98
+ }
99
+ async getLock(id) {
100
+ return await this.rest('get', `/lock/${id}`);
101
+ }
102
+ async lock(id) {
103
+ this.#logger.debug(`locking lock [${id}]`);
104
+ await this.rest('post', `/lock/${id}/lock`);
105
+ }
106
+ async unlock(id, mode) {
107
+ this.#logger.debug(`unlocking lock [${id}]${mode === undefined ? '' : ` with mode [${mode}]`}`);
108
+ await this.rest('post', `/lock/${id}/unlock`, undefined, mode === undefined ? undefined : { mode: String(mode) });
109
+ }
110
+ async pullSpring(id) {
111
+ this.#logger.debug(`pulling spring for lock [${id}]`);
112
+ await this.rest('post', `/lock/${id}/pull`);
113
+ }
114
+ async listCallbacks() {
115
+ return await this.rest('get', '/callback');
116
+ }
117
+ async addCallback(registration) {
118
+ const response = await this.rest('post', '/callback', registration);
119
+ if (Array.isArray(response)) {
120
+ const first = response[0];
121
+ return typeof first === 'number' ? first : Number(first?.id);
122
+ }
123
+ if (typeof response === 'number') {
124
+ return response;
125
+ }
126
+ return response.id;
127
+ }
128
+ async updateCallback(id, registration) {
129
+ await this.rest('put', `/callback/${id}`, registration);
130
+ }
131
+ async deleteCallback(id) {
132
+ await this.rest('delete', `/callback/${id}`);
133
+ }
134
+ callbackMatches(callback, registration) {
135
+ if (callback.url !== registration.url || callback.method !== registration.method) {
136
+ return false;
137
+ }
138
+ return (registration.headers ?? []).every(expected => {
139
+ const [name, value] = Object.entries(expected)[0] ?? [];
140
+ return !!name && this.headerValue(callback, name) === value;
141
+ });
142
+ }
143
+ headerValue(callback, name) {
144
+ const lowerName = name.toLowerCase();
145
+ for (const header of callback.headers ?? []) {
146
+ for (const [candidateName, value] of Object.entries(header)) {
147
+ if (candidateName.toLowerCase() === lowerName) {
148
+ return String(value);
149
+ }
150
+ }
151
+ }
152
+ return undefined;
153
+ }
154
+ async #retryStorageBusy(operation) {
155
+ let lastError;
156
+ for (let attempt = 0; attempt < 3; attempt++) {
157
+ try {
158
+ return await operation();
159
+ }
160
+ catch (error) {
161
+ lastError = error;
162
+ if (!(error instanceof TedeeError) || error.status !== 409 || attempt === 2) {
163
+ throw error;
164
+ }
165
+ await sleep((attempt + 1) * 1000);
166
+ }
167
+ }
168
+ throw lastError;
169
+ }
170
+ async rest(method, endpoint, body, extraHeaders) {
171
+ try {
172
+ return await this.#enqueue(async () => {
173
+ const apiToken = this.apiToken();
174
+ const url = this.restUrl(endpoint);
175
+ const hasBody = body !== undefined;
176
+ const response = await fetch(url, {
177
+ method: method.toUpperCase(),
178
+ headers: {
179
+ Accept: 'application/json',
180
+ 'Content-Type': 'application/json',
181
+ api_token: apiToken,
182
+ ...(hasBody ? {} : method === 'post' || method === 'put' ? { 'Content-Length': '0' } : {}),
183
+ ...extraHeaders
184
+ },
185
+ body: hasBody ? global.JSON.stringify(body) : method === 'post' || method === 'put' ? '' : undefined
186
+ });
187
+ if (response.status === 204) {
188
+ return undefined;
189
+ }
190
+ const responseText = await response.text();
191
+ const responseBody = responseText ? global.JSON.parse(responseText) : undefined;
192
+ if (!response.ok) {
193
+ const errorDescription = responseBody?.['error-description'] ?? responseBody?.message ?? response.statusText;
194
+ throw new TedeeError(`Failed to fetch [${endpoint}]. ${response.status}: ${errorDescription}`, response.status, responseBody);
195
+ }
196
+ return responseBody;
197
+ });
198
+ }
199
+ catch (error) {
200
+ if (!(error instanceof TedeeError)) {
201
+ // fetch threw — the bridge is unreachable; trip the reconnect logic
202
+ this.#enterReconnect(error);
203
+ }
204
+ throw error;
205
+ }
206
+ }
207
+ restUrl(endpoint) {
208
+ const port = this.#config.port ?? 80;
209
+ const apiVersion = this.#config.apiVersion ?? 'v1.0';
210
+ return `http://${this.#config.host}:${port}/${apiVersion}${endpoint}`;
211
+ }
212
+ apiToken() {
213
+ if (this.#config.tokenMode !== 'encrypted') {
214
+ return this.#config.token;
215
+ }
216
+ const timestamp = String(Date.now());
217
+ const hash = createHash('sha256').update(`${this.#config.token}${timestamp}`).digest('hex');
218
+ return `${hash}${timestamp}`;
219
+ }
220
+ async ensureCallback(registration, instanceId) {
221
+ const callbacks = await this.listCallbacks();
222
+ const ownedCallbacks = callbacks.filter(callback => {
223
+ return callback.url === registration.url || this.headerValue(callback, WEBHOOK_INSTANCE_HEADER) === instanceId;
224
+ });
225
+ const [primary, ...duplicates] = ownedCallbacks.sort((a, b) => {
226
+ const aHasInstance = this.headerValue(a, WEBHOOK_INSTANCE_HEADER) === instanceId ? 0 : 1;
227
+ const bHasInstance = this.headerValue(b, WEBHOOK_INSTANCE_HEADER) === instanceId ? 0 : 1;
228
+ return aHasInstance - bHasInstance;
229
+ });
230
+ let callbackId;
231
+ if (!primary) {
232
+ callbackId = await this.#retryStorageBusy(() => this.addCallback(registration));
233
+ this.#logger.info(`registered Tedee webhook callback [${registration.url}] with id [${callbackId}]`);
234
+ }
235
+ else {
236
+ callbackId = primary.id;
237
+ if (!this.callbackMatches(primary, registration)) {
238
+ await this.#retryStorageBusy(() => this.updateCallback(primary.id, registration));
239
+ this.#logger.info(`updated Tedee callback [${registration.url}] with id [${callbackId}]`);
240
+ }
241
+ else {
242
+ this.#logger.info(`found existing Tedee callback [${registration.url}] with id [${callbackId}]`);
243
+ }
244
+ }
245
+ for (const duplicate of duplicates) {
246
+ await this.#retryStorageBusy(() => this.deleteCallback(duplicate.id));
247
+ this.#logger.warn(`removed duplicate Tedee callback [${duplicate.url}] with id [${duplicate.id}]`);
248
+ }
249
+ return callbackId;
250
+ }
251
+ #buildRegistration() {
252
+ if (!this.#localHost) {
253
+ throw new Error('Local host has not been resolved yet');
254
+ }
255
+ return {
256
+ url: this.#server.callbackUrl(this.#localHost),
257
+ method: 'POST',
258
+ headers: [{ [WEBHOOK_INSTANCE_HEADER]: this.#config.webhook.instanceId }]
259
+ };
260
+ }
261
+ // Picks the local IPv4 address whose subnet contains the Tedee bridge — that's
262
+ // the interface the kernel would route bridge traffic over, and therefore the
263
+ // address the bridge can reach the plugin on. Falls back to throwing if no
264
+ // interface matches (eg. bridge unreachable, or host on a different L3 segment).
265
+ async #resolveLocalHost() {
266
+ const { address: bridgeIp } = await lookup(this.#config.host, { family: 4 });
267
+ const bridgeInt = ipv4ToInt(bridgeIp);
268
+ for (const ifaces of Object.values(networkInterfaces())) {
269
+ for (const iface of ifaces ?? []) {
270
+ if (iface.internal || iface.family !== 'IPv4') {
271
+ continue;
272
+ }
273
+ const mask = ipv4ToInt(iface.netmask);
274
+ if ((ipv4ToInt(iface.address) & mask) === (bridgeInt & mask)) {
275
+ return iface.address;
276
+ }
277
+ }
278
+ }
279
+ throw new Error(`No local IPv4 interface on the same subnet as Tedee Bridge [${this.#config.host} → ${bridgeIp}]`);
280
+ }
281
+ async #doConnect() {
282
+ if (!this.#registration) {
283
+ this.#registration = this.#buildRegistration();
284
+ }
285
+ await this.ensureCallback(this.#registration, this.#config.webhook.instanceId);
286
+ this.#setConnected();
287
+ }
288
+ async #verifyCallback() {
289
+ const registration = this.#registration;
290
+ if (!registration) {
291
+ throw new Error('Tedee callback registration is not configured');
292
+ }
293
+ const callbacks = await this.listCallbacks();
294
+ const found = callbacks.find(callback => this.callbackMatches(callback, registration));
295
+ if (!found) {
296
+ throw new Error('Tedee webhook callback is no longer registered with the bridge');
297
+ }
298
+ }
299
+ // Serializes outbound requests and spaces them by REQUEST_INTERVAL_MS to stay
300
+ // within the bridge's rate limit.
301
+ #enqueue(operation) {
302
+ const run = this.#queue.then(async () => {
303
+ const wait = Math.max(0, this.#lastRequestAt + REQUEST_INTERVAL_MS - Date.now());
304
+ if (wait > 0) {
305
+ await sleep(wait);
306
+ }
307
+ this.#lastRequestAt = Date.now();
308
+ return await operation();
309
+ });
310
+ this.#queue = run.then(() => undefined, () => undefined);
311
+ return run;
312
+ }
313
+ #scheduleHeartbeat() {
314
+ this.#cancelHeartbeat();
315
+ this.#heartbeatTimer = setTimeout(() => void this.#runHeartbeat(), HEARTBEAT_INTERVAL_MS);
316
+ this.#heartbeatTimer.unref?.();
317
+ }
318
+ #cancelHeartbeat() {
319
+ if (this.#heartbeatTimer) {
320
+ clearTimeout(this.#heartbeatTimer);
321
+ this.#heartbeatTimer = undefined;
322
+ }
323
+ }
324
+ async #runHeartbeat() {
325
+ this.#heartbeatTimer = undefined;
326
+ if (this.#state !== 'connected') {
327
+ return;
328
+ }
329
+ try {
330
+ await this.#verifyCallback();
331
+ if (this.#state === 'connected') {
332
+ this.#scheduleHeartbeat();
333
+ }
334
+ }
335
+ catch (error) {
336
+ this.#enterReconnect(error);
337
+ }
338
+ }
339
+ #setConnected() {
340
+ if (this.#state === 'closing' || this.#state === 'closed') {
341
+ return;
342
+ }
343
+ const wasConnected = this.#state === 'connected';
344
+ this.#state = 'connected';
345
+ if (!wasConnected) {
346
+ this.#logger.info('connected');
347
+ this.#emitter.emit('connect');
348
+ }
349
+ this.#scheduleHeartbeat();
350
+ }
351
+ #enterReconnect(error) {
352
+ if (this.#state !== 'connected') {
353
+ // only a live connection drops into the reconnect loop;
354
+ // start() and the loop itself manage their own retries
355
+ return;
356
+ }
357
+ this.#cancelHeartbeat();
358
+ this.#state = 'disconnected';
359
+ this.#logger.warn('disconnected', error);
360
+ this.#emitter.emit('disconnect');
361
+ if (!this.#reconnecting) {
362
+ this.#reconnecting = true;
363
+ void this.#reconnectLoop();
364
+ }
365
+ }
366
+ async #reconnectLoop() {
367
+ try {
368
+ let attempt = 0;
369
+ while (this.#state === 'disconnected') {
370
+ const wait = RECONNECT_BACKOFFS_MS[Math.min(attempt, RECONNECT_BACKOFFS_MS.length - 1)];
371
+ this.#logger.info(`reconnecting to Tedee in ${Math.round(wait / 1000)}s (attempt ${attempt + 1})`);
372
+ try {
373
+ await this.#waitInterruptible(wait);
374
+ }
375
+ catch {
376
+ return;
377
+ }
378
+ if (this.#state !== 'disconnected') {
379
+ return;
380
+ }
381
+ try {
382
+ await this.#doConnect();
383
+ return;
384
+ }
385
+ catch (error) {
386
+ this.#logger.warn(`reconnect attempt ${attempt + 1} failed`, error);
387
+ attempt++;
388
+ }
389
+ }
390
+ }
391
+ finally {
392
+ this.#reconnecting = false;
393
+ }
394
+ }
395
+ #waitInterruptible(ms) {
396
+ return new Promise((resolve, reject) => {
397
+ if (this.#abort.signal.aborted) {
398
+ reject(new Error('aborted'));
399
+ return;
400
+ }
401
+ const timer = setTimeout(() => {
402
+ this.#abort.signal.removeEventListener('abort', onAbort);
403
+ resolve();
404
+ }, ms);
405
+ timer.unref?.();
406
+ const onAbort = () => {
407
+ clearTimeout(timer);
408
+ reject(new Error('aborted'));
409
+ };
410
+ this.#abort.signal.addEventListener('abort', onAbort, { once: true });
411
+ });
412
+ }
413
+ #aborted() {
414
+ return this.#state === 'closing' || this.#state === 'closed' || this.#abort.signal.aborted;
415
+ }
416
+ async #shutdown() {
417
+ this.#state = 'closing';
418
+ this.#cancelHeartbeat();
419
+ this.#abort.abort();
420
+ try {
421
+ await this.#server.close();
422
+ }
423
+ catch (error) {
424
+ this.#logger.warn('failed to close Tedee event server', error);
425
+ }
426
+ this.#state = 'closed';
427
+ this.#emitter.emit('close');
428
+ }
429
+ }
430
+ function ipv4ToInt(ip) {
431
+ return ip.split('.').reduce((acc, part) => ((acc << 8) | (parseInt(part, 10) & 0xff)), 0) >>> 0;
432
+ }
433
+ class TedeeError extends Error {
434
+ status;
435
+ body;
436
+ constructor(message, status, body) {
437
+ super(message);
438
+ this.status = status;
439
+ this.body = body;
440
+ }
441
+ }
442
+ //# sourceMappingURL=tedee-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tedee-client.js","sourceRoot":"","sources":["../src/tedee-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { Detachable, ValueCallback } from './common.ts';
2
+ import type { ILogger } from './logger.ts';
3
+ import type { Tedee } from './tedee.ts';
4
+ export declare class TedeeEventServer {
5
+ private readonly config;
6
+ private readonly logger;
7
+ private readonly emitter;
8
+ private server?;
9
+ private actualPort?;
10
+ constructor(config: TedeeEventServer.Config, logger: ILogger);
11
+ callbackUrl(host: string): string;
12
+ on(event: 'event', handler: ValueCallback<Tedee.Event>): Detachable;
13
+ start(): Promise<void>;
14
+ close(): Promise<void>;
15
+ private handle;
16
+ private validateSecret;
17
+ private readBody;
18
+ }
19
+ export declare namespace TedeeEventServer {
20
+ type Config = {
21
+ port?: number;
22
+ instanceId: string;
23
+ };
24
+ }
25
+ //# sourceMappingURL=tedee-event-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tedee-event-server.d.ts","sourceRoot":"","sources":["../src/tedee-event-server.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAOxC,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgC;IACxD,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,UAAU,CAAC,CAAS;gBAEhB,MAAM,EAAE,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO;IAM5D,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAOjC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,UAAU;IAK7D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgCtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAWd,MAAM;IA8BpB,OAAO,CAAC,cAAc;YAKR,QAAQ;CAczB;AAED,yBAAiB,gBAAgB,CAAC;IAE9B,KAAY,MAAM,GAAG;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAA;KACrB,CAAA;CAEJ"}