homebridge-securitysystem 9.1.2 → 10.0.0-beta.2

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 (163) hide show
  1. package/.github/workflows/publish.yml +3 -0
  2. package/AGENTS.md +214 -0
  3. package/dist/conditions/already-triggered-condition.d.ts +10 -0
  4. package/dist/conditions/already-triggered-condition.js +16 -0
  5. package/dist/conditions/already-triggered-condition.js.map +1 -0
  6. package/dist/conditions/arming-in-progress-condition.d.ts +10 -0
  7. package/dist/conditions/arming-in-progress-condition.js +15 -0
  8. package/dist/conditions/arming-in-progress-condition.js.map +1 -0
  9. package/dist/conditions/arming-lock-condition.d.ts +13 -0
  10. package/dist/conditions/arming-lock-condition.js +42 -0
  11. package/dist/conditions/arming-lock-condition.js.map +1 -0
  12. package/dist/conditions/condition.d.ts +15 -0
  13. package/dist/conditions/condition.js +9 -0
  14. package/dist/conditions/condition.js.map +1 -0
  15. package/dist/conditions/double-knock-condition.d.ts +22 -0
  16. package/dist/conditions/double-knock-condition.js +70 -0
  17. package/dist/conditions/double-knock-condition.js.map +1 -0
  18. package/dist/conditions/not-armed-condition.d.ts +10 -0
  19. package/dist/conditions/not-armed-condition.js +20 -0
  20. package/dist/conditions/not-armed-condition.js.map +1 -0
  21. package/dist/constants/default-constant.d.ts +26 -0
  22. package/dist/constants/default-constant.js +28 -0
  23. package/dist/constants/default-constant.js.map +1 -0
  24. package/dist/constants/homekit-constant.d.ts +4 -0
  25. package/dist/constants/homekit-constant.js +5 -0
  26. package/dist/constants/homekit-constant.js.map +1 -0
  27. package/dist/constants/switch-uuid-constant.d.ts +23 -0
  28. package/dist/constants/switch-uuid-constant.js +24 -0
  29. package/dist/constants/switch-uuid-constant.js.map +1 -0
  30. package/dist/handlers/sensor-handler.d.ts +17 -0
  31. package/dist/handlers/sensor-handler.js +53 -0
  32. package/dist/handlers/sensor-handler.js.map +1 -0
  33. package/dist/handlers/state-handler.d.ts +41 -0
  34. package/dist/handlers/state-handler.js +213 -0
  35. package/dist/handlers/state-handler.js.map +1 -0
  36. package/dist/handlers/switch-handler.d.ts +27 -0
  37. package/dist/handlers/switch-handler.js +139 -0
  38. package/dist/handlers/switch-handler.js.map +1 -0
  39. package/dist/handlers/trip-handler.d.ts +45 -0
  40. package/dist/handlers/trip-handler.js +179 -0
  41. package/dist/handlers/trip-handler.js.map +1 -0
  42. package/dist/index.d.ts +3 -0
  43. package/dist/index.js +7 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/interfaces/condition-context-interface.d.ts +13 -0
  46. package/dist/interfaces/condition-context-interface.js +2 -0
  47. package/dist/interfaces/condition-context-interface.js.map +1 -0
  48. package/dist/interfaces/hap-types-interface.d.ts +9 -0
  49. package/dist/interfaces/hap-types-interface.js +2 -0
  50. package/dist/interfaces/hap-types-interface.js.map +1 -0
  51. package/dist/interfaces/options-interface.d.ts +93 -0
  52. package/dist/interfaces/options-interface.js +2 -0
  53. package/dist/interfaces/options-interface.js.map +1 -0
  54. package/dist/interfaces/persisted-state-interface.d.ts +6 -0
  55. package/dist/interfaces/persisted-state-interface.js +2 -0
  56. package/dist/interfaces/persisted-state-interface.js.map +1 -0
  57. package/dist/interfaces/service-registry-interface.d.ts +26 -0
  58. package/dist/interfaces/service-registry-interface.js +2 -0
  59. package/dist/interfaces/service-registry-interface.js.map +1 -0
  60. package/dist/interfaces/system-state-interface.d.ts +21 -0
  61. package/dist/interfaces/system-state-interface.js +2 -0
  62. package/dist/interfaces/system-state-interface.js.map +1 -0
  63. package/dist/security-system.d.ts +26 -0
  64. package/dist/security-system.js +377 -0
  65. package/dist/security-system.js.map +1 -0
  66. package/dist/services/audio-service.d.ts +21 -0
  67. package/dist/services/audio-service.js +113 -0
  68. package/dist/services/audio-service.js.map +1 -0
  69. package/dist/services/command-service.d.ts +16 -0
  70. package/dist/services/command-service.js +65 -0
  71. package/dist/services/command-service.js.map +1 -0
  72. package/dist/services/event-bus-service.d.ts +12 -0
  73. package/dist/services/event-bus-service.js +17 -0
  74. package/dist/services/event-bus-service.js.map +1 -0
  75. package/dist/services/server-service.d.ts +25 -0
  76. package/dist/services/server-service.js +140 -0
  77. package/dist/services/server-service.js.map +1 -0
  78. package/dist/services/storage-service.d.ts +14 -0
  79. package/dist/services/storage-service.js +70 -0
  80. package/dist/services/storage-service.js.map +1 -0
  81. package/dist/services/webhook-service.d.ts +16 -0
  82. package/dist/services/webhook-service.js +73 -0
  83. package/dist/services/webhook-service.js.map +1 -0
  84. package/dist/tests/conditions.test.d.ts +1 -0
  85. package/dist/tests/conditions.test.js +151 -0
  86. package/dist/tests/conditions.test.js.map +1 -0
  87. package/dist/tests/state-handler.test.d.ts +1 -0
  88. package/dist/tests/state-handler.test.js +171 -0
  89. package/dist/tests/state-handler.test.js.map +1 -0
  90. package/dist/tests/trip-handler.test.d.ts +1 -0
  91. package/dist/tests/trip-handler.test.js +160 -0
  92. package/dist/tests/trip-handler.test.js.map +1 -0
  93. package/dist/types/event-payload-map-type.d.ts +9 -0
  94. package/dist/types/event-payload-map-type.js +2 -0
  95. package/dist/types/event-payload-map-type.js.map +1 -0
  96. package/dist/types/event-type.d.ts +24 -0
  97. package/dist/types/event-type.js +9 -0
  98. package/dist/types/event-type.js.map +1 -0
  99. package/dist/types/mode-type.d.ts +4 -0
  100. package/dist/types/mode-type.js +2 -0
  101. package/dist/types/mode-type.js.map +1 -0
  102. package/dist/types/origin-type.d.ts +9 -0
  103. package/dist/types/origin-type.js +11 -0
  104. package/dist/types/origin-type.js.map +1 -0
  105. package/dist/types/security-state-type.d.ts +11 -0
  106. package/dist/types/security-state-type.js +13 -0
  107. package/dist/types/security-state-type.js.map +1 -0
  108. package/dist/utils/log-util.d.ts +4 -0
  109. package/dist/utils/log-util.js +47 -0
  110. package/dist/utils/log-util.js.map +1 -0
  111. package/dist/utils/options-util.d.ts +6 -0
  112. package/dist/utils/options-util.js +171 -0
  113. package/dist/utils/options-util.js.map +1 -0
  114. package/dist/utils/state-util.d.ts +8 -0
  115. package/dist/utils/state-util.js +29 -0
  116. package/dist/utils/state-util.js.map +1 -0
  117. package/eslint.config.js +35 -0
  118. package/package.json +40 -34
  119. package/src/@types/homebridge-lib.d.ts +14 -0
  120. package/src/conditions/already-triggered-condition.ts +18 -0
  121. package/src/conditions/arming-in-progress-condition.ts +17 -0
  122. package/src/conditions/arming-lock-condition.ts +48 -0
  123. package/src/conditions/condition.ts +17 -0
  124. package/src/conditions/double-knock-condition.ts +82 -0
  125. package/src/conditions/not-armed-condition.ts +24 -0
  126. package/src/constants/default-constant.ts +28 -0
  127. package/src/constants/homekit-constant.ts +5 -0
  128. package/src/constants/switch-uuid-constant.ts +23 -0
  129. package/src/handlers/sensor-handler.ts +81 -0
  130. package/src/handlers/state-handler.ts +268 -0
  131. package/src/handlers/switch-handler.ts +166 -0
  132. package/src/handlers/trip-handler.ts +219 -0
  133. package/src/index.ts +9 -0
  134. package/src/interfaces/condition-context-interface.ts +14 -0
  135. package/src/interfaces/hap-types-interface.ts +11 -0
  136. package/src/interfaces/options-interface.ts +120 -0
  137. package/src/interfaces/persisted-state-interface.ts +7 -0
  138. package/src/interfaces/service-registry-interface.ts +37 -0
  139. package/src/interfaces/system-state-interface.ts +25 -0
  140. package/src/security-system.ts +433 -0
  141. package/src/services/audio-service.ts +133 -0
  142. package/src/services/command-service.ts +76 -0
  143. package/src/services/event-bus-service.ts +21 -0
  144. package/src/services/server-service.ts +176 -0
  145. package/src/services/storage-service.ts +80 -0
  146. package/src/services/webhook-service.ts +83 -0
  147. package/src/tests/conditions.test.ts +180 -0
  148. package/src/tests/state-handler.test.ts +200 -0
  149. package/src/tests/trip-handler.test.ts +182 -0
  150. package/src/types/event-payload-map-type.ts +15 -0
  151. package/src/types/event-type.ts +29 -0
  152. package/src/types/mode-type.ts +4 -0
  153. package/src/types/origin-type.ts +9 -0
  154. package/src/types/security-state-type.ts +11 -0
  155. package/src/utils/log-util.ts +54 -0
  156. package/src/utils/options-util.ts +202 -0
  157. package/src/utils/state-util.ts +32 -0
  158. package/tsconfig.json +25 -0
  159. package/vitest.config.ts +8 -0
  160. package/.eslintrc.js +0 -16
  161. package/.vscode/settings.json +0 -12
  162. package/src/index.js +0 -2525
  163. package/src/utils/options.js +0 -409
@@ -0,0 +1,12 @@
1
+ import { EventEmitter } from 'events';
2
+ import { EventType } from '../types/event-type.js';
3
+ import type { EventPayloadMap } from '../types/event-payload-map-type.js';
4
+ /**
5
+ * Typed event bus used to decouple side-effect services (audio, commands,
6
+ * webhooks, storage) from the core state-machine handlers.
7
+ */
8
+ export declare class EventBusService extends EventEmitter {
9
+ emit<K extends EventType>(event: K, payload: EventPayloadMap[K]): boolean;
10
+ on<K extends EventType>(event: K, listener: (payload: EventPayloadMap[K]) => void): this;
11
+ off<K extends EventType>(event: K, listener: (payload: EventPayloadMap[K]) => void): this;
12
+ }
@@ -0,0 +1,17 @@
1
+ import { EventEmitter } from 'events';
2
+ /**
3
+ * Typed event bus used to decouple side-effect services (audio, commands,
4
+ * webhooks, storage) from the core state-machine handlers.
5
+ */
6
+ export class EventBusService extends EventEmitter {
7
+ emit(event, payload) {
8
+ return super.emit(event, payload);
9
+ }
10
+ on(event, listener) {
11
+ return super.on(event, listener);
12
+ }
13
+ off(event, listener) {
14
+ return super.off(event, listener);
15
+ }
16
+ }
17
+ //# sourceMappingURL=event-bus-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus-service.js","sourceRoot":"","sources":["../../src/services/event-bus-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAItC;;;GAGG;AACH,MAAM,OAAO,eAAgB,SAAQ,YAAY;IAC/C,IAAI,CAAsB,KAAQ,EAAE,OAA2B;QAC7D,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,EAAE,CAAsB,KAAQ,EAAE,QAA+C;QAC/E,OAAO,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC;IAED,GAAG,CAAsB,KAAQ,EAAE,QAA+C;QAChF,OAAO,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC;CACF"}
@@ -0,0 +1,25 @@
1
+ import type { Logging } from 'homebridge';
2
+ import type { SecuritySystemOptions } from '../interfaces/options-interface.js';
3
+ import type { SystemState } from '../interfaces/system-state-interface.js';
4
+ import type { StateHandler } from '../handlers/state-handler.js';
5
+ import type { TripHandler } from '../handlers/trip-handler.js';
6
+ import type { SwitchHandler } from '../handlers/switch-handler.js';
7
+ /** Hono HTTP server providing remote control of the security system. */
8
+ export declare class ServerService {
9
+ private readonly log;
10
+ private readonly options;
11
+ private readonly state;
12
+ private readonly stateHandler;
13
+ private readonly tripHandler;
14
+ private readonly switchHandler;
15
+ private readonly application;
16
+ constructor(log: Logging, options: SecuritySystemOptions, state: SystemState, stateHandler: StateHandler, tripHandler: TripHandler, switchHandler: SwitchHandler);
17
+ start(): void;
18
+ private registerRoutes;
19
+ /**
20
+ * Checks authentication and returns an error Response if it fails,
21
+ * or null if the request is allowed to proceed.
22
+ */
23
+ private authenticate;
24
+ private parseDelay;
25
+ }
@@ -0,0 +1,140 @@
1
+ import { Hono } from 'hono';
2
+ import { serve } from '@hono/node-server';
3
+ import { SecurityState } from '../types/security-state-type.js';
4
+ import { OriginType } from '../types/origin-type.js';
5
+ import { stateToMode } from '../utils/state-util.js';
6
+ /** Hono HTTP server providing remote control of the security system. */
7
+ export class ServerService {
8
+ log;
9
+ options;
10
+ state;
11
+ stateHandler;
12
+ tripHandler;
13
+ switchHandler;
14
+ application = new Hono();
15
+ constructor(log, options, state, stateHandler, tripHandler, switchHandler) {
16
+ this.log = log;
17
+ this.options = options;
18
+ this.state = state;
19
+ this.stateHandler = stateHandler;
20
+ this.tripHandler = tripHandler;
21
+ this.switchHandler = switchHandler;
22
+ }
23
+ start() {
24
+ this.registerRoutes();
25
+ const server = serve({ fetch: this.application.fetch, port: this.options.serverPort }, () => this.log.info(`Server (${this.options.serverPort})`));
26
+ server.on('error', (error) => {
27
+ this.log.error('Server error.');
28
+ this.log.error(String(error));
29
+ });
30
+ }
31
+ registerRoutes() {
32
+ this.application.get('/', (context) => context.redirect('https://github.com/MiguelRipoll23/homebridge-securitysystem/wiki/Server'));
33
+ this.application.get('/status', (context) => {
34
+ const authError = this.authenticate(context);
35
+ if (authError !== null) {
36
+ return authError;
37
+ }
38
+ return context.json({
39
+ arming: this.state.isArming,
40
+ current_mode: stateToMode(this.state.currentState),
41
+ target_mode: stateToMode(this.state.targetState),
42
+ tripped: this.state.triggerTimeout !== null,
43
+ });
44
+ });
45
+ this.application.get('/triggered', (context) => {
46
+ const authError = this.authenticate(context);
47
+ if (authError !== null) {
48
+ return authError;
49
+ }
50
+ const delay = this.parseDelay(context);
51
+ let success;
52
+ if (delay > 0) {
53
+ success = this.tripHandler.updateTripSwitch(true, OriginType.EXTERNAL, false);
54
+ }
55
+ else {
56
+ if (this.state.currentState === SecurityState.OFF && !this.options.overrideOff) {
57
+ return context.json({ error: true });
58
+ }
59
+ this.stateHandler.setCurrentState(SecurityState.TRIGGERED, OriginType.EXTERNAL);
60
+ success = true;
61
+ }
62
+ return context.json({ error: !success });
63
+ });
64
+ this.application.get('/home', (context) => {
65
+ const authError = this.authenticate(context);
66
+ if (authError !== null) {
67
+ return authError;
68
+ }
69
+ const delay = this.parseDelay(context);
70
+ const success = this.stateHandler.updateTargetState(SecurityState.HOME, OriginType.EXTERNAL, delay);
71
+ return context.json({ error: !success });
72
+ });
73
+ this.application.get('/away', (context) => {
74
+ const authError = this.authenticate(context);
75
+ if (authError !== null) {
76
+ return authError;
77
+ }
78
+ const delay = this.parseDelay(context);
79
+ const success = this.stateHandler.updateTargetState(SecurityState.AWAY, OriginType.EXTERNAL, delay);
80
+ return context.json({ error: !success });
81
+ });
82
+ this.application.get('/night', (context) => {
83
+ const authError = this.authenticate(context);
84
+ if (authError !== null) {
85
+ return authError;
86
+ }
87
+ const delay = this.parseDelay(context);
88
+ const success = this.stateHandler.updateTargetState(SecurityState.NIGHT, OriginType.EXTERNAL, delay);
89
+ return context.json({ error: !success });
90
+ });
91
+ this.application.get('/off', (context) => {
92
+ const authError = this.authenticate(context);
93
+ if (authError !== null) {
94
+ return authError;
95
+ }
96
+ const success = this.stateHandler.updateTargetState(SecurityState.OFF, OriginType.EXTERNAL, 0);
97
+ return context.json({ error: !success });
98
+ });
99
+ this.application.get('/arming-lock/:mode/:value', (context) => {
100
+ const authError = this.authenticate(context);
101
+ if (authError !== null) {
102
+ return authError;
103
+ }
104
+ const mode = context.req.param('mode').toLowerCase();
105
+ const value = context.req.param('value').includes('on');
106
+ const success = this.switchHandler.updateArmingLock(mode, value);
107
+ return context.json({ error: !success });
108
+ });
109
+ }
110
+ /**
111
+ * Checks authentication and returns an error Response if it fails,
112
+ * or null if the request is allowed to proceed.
113
+ */
114
+ authenticate(context) {
115
+ if (this.options.serverCode === null) {
116
+ return null;
117
+ }
118
+ const code = context.req.query('code');
119
+ if (code === undefined) {
120
+ this.log.info('Code required (Server)');
121
+ return context.json({ error: true, message: 'Code required', hint: 'Add the \'code\' URL parameter.' }, 401);
122
+ }
123
+ if (this.state.invalidCodeCount >= 5) {
124
+ this.log.info('Code blocked (Server)');
125
+ return context.json({ error: true, message: 'Code blocked' }, 403);
126
+ }
127
+ if (parseInt(code, 10) !== this.options.serverCode) {
128
+ this.state.invalidCodeCount++;
129
+ this.log.info('Code invalid (Server)');
130
+ return context.json({ error: true, message: 'Code invalid' }, 403);
131
+ }
132
+ this.state.invalidCodeCount = 0;
133
+ return null;
134
+ }
135
+ parseDelay(context) {
136
+ const rawValue = parseInt(context.req.query('delay') ?? '', 10);
137
+ return isNaN(rawValue) || rawValue < 0 ? 0 : rawValue;
138
+ }
139
+ }
140
+ //# sourceMappingURL=server-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-service.js","sourceRoot":"","sources":["../../src/services/server-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { Logging } from 'homebridge';
2
+ import type { SecuritySystemOptions } from '../interfaces/options-interface.js';
3
+ import type { SystemState } from '../interfaces/system-state-interface.js';
4
+ /** Persists and restores security system state across Homebridge restarts. */
5
+ export declare class StorageService {
6
+ private readonly log;
7
+ private readonly options;
8
+ private readonly storagePath;
9
+ private initialised;
10
+ constructor(log: Logging, options: SecuritySystemOptions, storagePath: string);
11
+ init(): Promise<void>;
12
+ load(state: SystemState): Promise<void>;
13
+ save(state: SystemState): Promise<void>;
14
+ }
@@ -0,0 +1,70 @@
1
+ import path from 'path';
2
+ import storage from 'node-persist';
3
+ import { SecurityState } from '../types/security-state-type.js';
4
+ /** Persists and restores security system state across Homebridge restarts. */
5
+ export class StorageService {
6
+ log;
7
+ options;
8
+ storagePath;
9
+ initialised = false;
10
+ constructor(log, options, storagePath) {
11
+ this.log = log;
12
+ this.options = options;
13
+ this.storagePath = storagePath;
14
+ }
15
+ async init() {
16
+ const dir = path.join(this.storagePath, `homebridge-securitysystem-${this.options.serialNumber}`);
17
+ try {
18
+ await storage.init({ dir });
19
+ this.initialised = true;
20
+ }
21
+ catch (err) {
22
+ this.log.error('Unable to initialise storage.');
23
+ this.log.error(String(err));
24
+ }
25
+ }
26
+ async load(state) {
27
+ if (!this.initialised) {
28
+ return;
29
+ }
30
+ if (this.options.testMode) {
31
+ await storage.clear();
32
+ this.log.debug('Saved state cleared (test mode).');
33
+ return;
34
+ }
35
+ try {
36
+ const saved = await storage.getItem('state');
37
+ if (!saved) {
38
+ return;
39
+ }
40
+ this.log.info('Saved state (Found)');
41
+ this.log.debug('State (Loaded)', String(JSON.stringify(saved)));
42
+ const current = saved.currentState ?? state.defaultState;
43
+ const target = saved.targetState ?? state.defaultState;
44
+ state.currentState = current;
45
+ state.targetState = current === SecurityState.TRIGGERED ? target : current;
46
+ }
47
+ catch (err) {
48
+ this.log.error('Saved state (Error)');
49
+ this.log.error(String(err));
50
+ }
51
+ }
52
+ async save(state) {
53
+ if (!this.options.saveState || !this.initialised) {
54
+ return;
55
+ }
56
+ const data = {
57
+ currentState: state.currentState,
58
+ targetState: state.targetState,
59
+ };
60
+ try {
61
+ await storage.setItem('state', data);
62
+ this.log.debug('State (Saved)', String(JSON.stringify(data)));
63
+ }
64
+ catch (err) {
65
+ this.log.error('Unable to save state.');
66
+ this.log.error(String(err));
67
+ }
68
+ }
69
+ }
70
+ //# sourceMappingURL=storage-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-service.js","sourceRoot":"","sources":["../../src/services/storage-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { Logging } from 'homebridge';
2
+ import { SecurityState } from '../types/security-state-type.js';
3
+ import { OriginType } from '../types/origin-type.js';
4
+ import type { SecuritySystemOptions } from '../interfaces/options-interface.js';
5
+ import type { SystemState } from '../interfaces/system-state-interface.js';
6
+ import type { EventBusService } from './event-bus-service.js';
7
+ /** Sends HTTP GET webhook requests in response to state-machine events. */
8
+ export declare class WebhookService {
9
+ private readonly log;
10
+ private readonly options;
11
+ private readonly state;
12
+ constructor(log: Logging, options: SecuritySystemOptions, state: SystemState);
13
+ attachToBus(bus: EventBusService): void;
14
+ send(type: string, stateOrMode: SecurityState | string, origin: OriginType): void;
15
+ private resolvePath;
16
+ }
@@ -0,0 +1,73 @@
1
+ import { SecurityState } from '../types/security-state-type.js';
2
+ import { OriginType } from '../types/origin-type.js';
3
+ import { stateToMode } from '../utils/state-util.js';
4
+ import { EventType } from '../types/event-type.js';
5
+ /** Sends HTTP GET webhook requests in response to state-machine events. */
6
+ export class WebhookService {
7
+ log;
8
+ options;
9
+ state;
10
+ constructor(log, options, state) {
11
+ this.log = log;
12
+ this.options = options;
13
+ this.state = state;
14
+ }
15
+ attachToBus(bus) {
16
+ bus.on(EventType.TARGET_CHANGED, ({ state, origin }) => {
17
+ this.send('target', state, origin);
18
+ });
19
+ bus.on(EventType.CURRENT_CHANGED, ({ state, origin }) => {
20
+ this.send('current', state, origin);
21
+ });
22
+ bus.on(EventType.WARNING, ({ origin }) => {
23
+ this.send('current', 'warning', origin);
24
+ });
25
+ }
26
+ send(type, stateOrMode, origin) {
27
+ if (!this.options.webhookUrl) {
28
+ this.log.debug('Webhook base URL not set.');
29
+ return;
30
+ }
31
+ if (this.options.proxyMode && origin === OriginType.EXTERNAL) {
32
+ this.log.debug('Webhook bypassed (proxy mode).');
33
+ return;
34
+ }
35
+ const urlPath = this.resolvePath(type, stateOrMode);
36
+ if (!urlPath) {
37
+ this.log.debug(`Webhook path for ${type}/${stateOrMode} not set.`);
38
+ return;
39
+ }
40
+ const currentMode = stateToMode(this.state.currentState);
41
+ const finalPath = urlPath.replace('${currentMode}', currentMode);
42
+ const url = this.options.webhookUrl + finalPath;
43
+ fetch(url)
44
+ .then(res => {
45
+ if (!res.ok) {
46
+ throw new Error(`Status ${res.status}`);
47
+ }
48
+ this.log.info('Webhook event (Sent)');
49
+ })
50
+ .catch(err => {
51
+ this.log.error(`Webhook request failed (${finalPath})`);
52
+ this.log.error(String(err));
53
+ });
54
+ }
55
+ resolvePath(type, stateOrMode) {
56
+ const s = stateOrMode;
57
+ const o = this.options;
58
+ if (s === 'warning') {
59
+ return o.webhookCurrentWarning;
60
+ }
61
+ switch (s) {
62
+ case SecurityState.TRIGGERED: return o.webhookCurrentTriggered;
63
+ case SecurityState.HOME: return type === 'current' ? o.webhookCurrentHome : o.webhookTargetHome;
64
+ case SecurityState.AWAY: return type === 'current' ? o.webhookCurrentAway : o.webhookTargetAway;
65
+ case SecurityState.NIGHT: return type === 'current' ? o.webhookCurrentNight : o.webhookTargetNight;
66
+ case SecurityState.OFF: return type === 'current' ? o.webhookCurrentOff : o.webhookTargetOff;
67
+ default:
68
+ this.log.error(`Unknown webhook state (${s})`);
69
+ return null;
70
+ }
71
+ }
72
+ }
73
+ //# sourceMappingURL=webhook-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-service.js","sourceRoot":"","sources":["../../src/services/webhook-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,151 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { SecurityState } from '../types/security-state-type.js';
3
+ import { OriginType } from '../types/origin-type.js';
4
+ import { NotArmedCondition } from '../conditions/not-armed-condition.js';
5
+ import { ArmingInProgressCondition } from '../conditions/arming-in-progress-condition.js';
6
+ import { AlreadyTriggeredCondition } from '../conditions/already-triggered-condition.js';
7
+ import { DoubleKnockCondition } from '../conditions/double-knock-condition.js';
8
+ // ── Helpers ──────────────────────────────────────────────────────────────────
9
+ function makeState(overrides = {}) {
10
+ return {
11
+ currentState: SecurityState.HOME,
12
+ targetState: SecurityState.HOME,
13
+ defaultState: SecurityState.OFF,
14
+ availableTargetStates: [SecurityState.HOME, SecurityState.AWAY, SecurityState.NIGHT, SecurityState.OFF],
15
+ isArming: false,
16
+ isKnocked: false,
17
+ invalidCodeCount: 0,
18
+ pausedCurrentState: null,
19
+ audioProcess: null,
20
+ armTimeout: null,
21
+ pauseTimeout: null,
22
+ triggerTimeout: null,
23
+ doubleKnockTimeout: null,
24
+ resetTimeout: null,
25
+ trippedMotionSensorInterval: null,
26
+ triggeredMotionSensorInterval: null,
27
+ ...overrides,
28
+ };
29
+ }
30
+ function makeOptions(overrides = {}) {
31
+ return {
32
+ overrideOff: false,
33
+ doubleKnock: false,
34
+ doubleKnockSeconds: 90,
35
+ doubleKnockModes: [],
36
+ homeDoubleKnockSeconds: null,
37
+ awayDoubleKnockSeconds: null,
38
+ nightDoubleKnockSeconds: null,
39
+ armingLockSwitch: false,
40
+ armingLockSwitches: false,
41
+ ...overrides,
42
+ };
43
+ }
44
+ function makeCtx(state, options, value, origin = OriginType.REGULAR_SWITCH) {
45
+ return { state, services: {}, options, value, origin };
46
+ }
47
+ // ── NotArmedCondition ─────────────────────────────────────────────────────────
48
+ describe('NotArmedCondition', () => {
49
+ const cond = new NotArmedCondition();
50
+ it('blocks when disarmed and override_off is false', () => {
51
+ const state = makeState({ currentState: SecurityState.OFF });
52
+ const opts = makeOptions({ overrideOff: false });
53
+ expect(cond.evaluate(makeCtx(state, opts, true))).toBe(true);
54
+ });
55
+ it('allows when disarmed but override_off is true', () => {
56
+ const state = makeState({ currentState: SecurityState.OFF });
57
+ const opts = makeOptions({ overrideOff: true });
58
+ expect(cond.evaluate(makeCtx(state, opts, true))).toBe(false);
59
+ });
60
+ it('allows when disarmed but origin is OVERRIDE_SWITCH', () => {
61
+ const state = makeState({ currentState: SecurityState.OFF });
62
+ const opts = makeOptions({ overrideOff: false });
63
+ expect(cond.evaluate(makeCtx(state, opts, true, OriginType.OVERRIDE_SWITCH))).toBe(false);
64
+ });
65
+ it('allows when system is armed', () => {
66
+ const state = makeState({ currentState: SecurityState.HOME });
67
+ const opts = makeOptions({ overrideOff: false });
68
+ expect(cond.evaluate(makeCtx(state, opts, true))).toBe(false);
69
+ });
70
+ it('does not block on value=false', () => {
71
+ const state = makeState({ currentState: SecurityState.OFF });
72
+ const opts = makeOptions({ overrideOff: false });
73
+ expect(cond.evaluate(makeCtx(state, opts, false))).toBe(false);
74
+ });
75
+ });
76
+ // ── ArmingInProgressCondition ─────────────────────────────────────────────────
77
+ describe('ArmingInProgressCondition', () => {
78
+ const cond = new ArmingInProgressCondition();
79
+ it('blocks when isArming is true and value is true', () => {
80
+ const state = makeState({ isArming: true });
81
+ expect(cond.evaluate(makeCtx(state, makeOptions(), true))).toBe(true);
82
+ });
83
+ it('allows when not arming', () => {
84
+ const state = makeState({ isArming: false });
85
+ expect(cond.evaluate(makeCtx(state, makeOptions(), true))).toBe(false);
86
+ });
87
+ it('does not block on value=false', () => {
88
+ const state = makeState({ isArming: true });
89
+ expect(cond.evaluate(makeCtx(state, makeOptions(), false))).toBe(false);
90
+ });
91
+ });
92
+ // ── AlreadyTriggeredCondition ─────────────────────────────────────────────────
93
+ describe('AlreadyTriggeredCondition', () => {
94
+ const cond = new AlreadyTriggeredCondition();
95
+ it('blocks when currently triggered and value is true', () => {
96
+ const state = makeState({ currentState: SecurityState.TRIGGERED });
97
+ expect(cond.evaluate(makeCtx(state, makeOptions(), true))).toBe(true);
98
+ });
99
+ it('allows when not triggered', () => {
100
+ const state = makeState({ currentState: SecurityState.HOME });
101
+ expect(cond.evaluate(makeCtx(state, makeOptions(), true))).toBe(false);
102
+ });
103
+ it('does not block on value=false (cancel)', () => {
104
+ const state = makeState({ currentState: SecurityState.TRIGGERED });
105
+ expect(cond.evaluate(makeCtx(state, makeOptions(), false))).toBe(false);
106
+ });
107
+ });
108
+ // ── DoubleKnockCondition ──────────────────────────────────────────────────────
109
+ describe('DoubleKnockCondition', () => {
110
+ it('allows through when doubleKnock option is disabled', () => {
111
+ const onFirstKnock = vi.fn();
112
+ const cond = new DoubleKnockCondition(onFirstKnock);
113
+ const state = makeState({ isKnocked: false });
114
+ const opts = makeOptions({ doubleKnock: false, doubleKnockModes: ['home'] });
115
+ expect(cond.evaluate(makeCtx(state, opts, true))).toBe(false);
116
+ expect(onFirstKnock).not.toHaveBeenCalled();
117
+ });
118
+ it('allows override switch to bypass double-knock', () => {
119
+ const onFirstKnock = vi.fn();
120
+ const cond = new DoubleKnockCondition(onFirstKnock);
121
+ const state = makeState({ isKnocked: false, currentState: SecurityState.HOME });
122
+ const opts = makeOptions({ doubleKnock: true, doubleKnockModes: ['home'], doubleKnockSeconds: 90 });
123
+ expect(cond.evaluate(makeCtx(state, opts, true, OriginType.OVERRIDE_SWITCH))).toBe(false);
124
+ expect(onFirstKnock).not.toHaveBeenCalled();
125
+ });
126
+ it('blocks first knock and calls onFirstKnock', () => {
127
+ const onFirstKnock = vi.fn();
128
+ const cond = new DoubleKnockCondition(onFirstKnock);
129
+ const state = makeState({ isKnocked: false, currentState: SecurityState.HOME });
130
+ const opts = makeOptions({ doubleKnock: true, doubleKnockModes: ['home'], doubleKnockSeconds: 90 });
131
+ expect(cond.evaluate(makeCtx(state, opts, true))).toBe(true);
132
+ expect(state.isKnocked).toBe(true);
133
+ expect(onFirstKnock).toHaveBeenCalledWith(90, expect.any(Function));
134
+ });
135
+ it('allows second knock through and clears isKnocked', () => {
136
+ const cond = new DoubleKnockCondition(vi.fn());
137
+ const state = makeState({ isKnocked: true, currentState: SecurityState.HOME });
138
+ const opts = makeOptions({ doubleKnock: true, doubleKnockModes: ['home'], doubleKnockSeconds: 90 });
139
+ expect(cond.evaluate(makeCtx(state, opts, true))).toBe(false);
140
+ expect(state.isKnocked).toBe(false);
141
+ });
142
+ it('uses mode-specific knock window when configured', () => {
143
+ const onFirstKnock = vi.fn();
144
+ const cond = new DoubleKnockCondition(onFirstKnock);
145
+ const state = makeState({ isKnocked: false, currentState: SecurityState.AWAY });
146
+ const opts = makeOptions({ doubleKnock: true, doubleKnockModes: ['away'], doubleKnockSeconds: 90, awayDoubleKnockSeconds: 30 });
147
+ cond.evaluate(makeCtx(state, opts, true));
148
+ expect(onFirstKnock).toHaveBeenCalledWith(30, expect.any(Function));
149
+ });
150
+ });
151
+ //# sourceMappingURL=conditions.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conditions.test.js","sourceRoot":"","sources":["../../src/tests/conditions.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};