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,179 @@
1
+ import { SecurityState } from '../types/security-state-type.js';
2
+ import { OriginType } from '../types/origin-type.js';
3
+ import { HK_NOT_ALLOWED_IN_CURRENT_STATE } from '../constants/homekit-constant.js';
4
+ import { EventType } from '../types/event-type.js';
5
+ import { NotArmedCondition } from '../conditions/not-armed-condition.js';
6
+ import { ArmingInProgressCondition } from '../conditions/arming-in-progress-condition.js';
7
+ import { AlreadyTriggeredCondition } from '../conditions/already-triggered-condition.js';
8
+ import { DoubleKnockCondition } from '../conditions/double-knock-condition.js';
9
+ /** Handles the trip switch and trigger-delay logic, including all blocking conditions. */
10
+ export class TripHandler {
11
+ services;
12
+ state;
13
+ options;
14
+ Characteristic;
15
+ log;
16
+ bus;
17
+ audio;
18
+ sensorHandler;
19
+ stateHandler;
20
+ notArmed = new NotArmedCondition();
21
+ armingInProgress = new ArmingInProgressCondition();
22
+ alreadyTriggered = new AlreadyTriggeredCondition();
23
+ doubleKnock;
24
+ constructor(services, state, options, Characteristic, log, bus, audio, sensorHandler) {
25
+ this.services = services;
26
+ this.state = state;
27
+ this.options = options;
28
+ this.Characteristic = Characteristic;
29
+ this.log = log;
30
+ this.bus = bus;
31
+ this.audio = audio;
32
+ this.sensorHandler = sensorHandler;
33
+ this.doubleKnock = new DoubleKnockCondition((seconds, onExpire) => {
34
+ this.log.warn('Trip Switch (Knock)');
35
+ this.state.doubleKnockTimeout = setTimeout(() => {
36
+ onExpire();
37
+ this.log.info('Trip Switch (Reset)');
38
+ }, seconds * 1000);
39
+ });
40
+ }
41
+ setStateHandler(handler) {
42
+ this.stateHandler = handler;
43
+ }
44
+ /**
45
+ * Core trip-switch logic shared by all trip/trigger paths.
46
+ * Returns `true` on success, `false` if blocked.
47
+ */
48
+ updateTripSwitch(value, origin, stateChanged) {
49
+ const ctx = {
50
+ state: this.state,
51
+ services: this.services,
52
+ options: this.options,
53
+ value,
54
+ origin,
55
+ };
56
+ if (value) {
57
+ // Check blocking conditions in order.
58
+ if (this.notArmed.evaluate(ctx)) {
59
+ this.log.warn('Trip Switch (Not armed)');
60
+ return false;
61
+ }
62
+ if (this.armingInProgress.evaluate(ctx)) {
63
+ this.log.warn('Trip Switch (Still arming)');
64
+ return false;
65
+ }
66
+ if (this.doubleKnock.evaluate(ctx)) {
67
+ return false;
68
+ }
69
+ // Clear any lingering double-knock timeout once we've passed it.
70
+ if (this.state.doubleKnockTimeout !== null) {
71
+ clearTimeout(this.state.doubleKnockTimeout);
72
+ this.state.doubleKnockTimeout = null;
73
+ }
74
+ if (this.alreadyTriggered.evaluate(ctx)) {
75
+ this.log.warn('Security System (Already triggered)');
76
+ return false;
77
+ }
78
+ if (this.state.triggerTimeout !== null) {
79
+ this.log.warn('Security System (Already tripped)');
80
+ return false;
81
+ }
82
+ this.activateTrip(origin);
83
+ }
84
+ else {
85
+ this.cancelTrip(origin, stateChanged);
86
+ }
87
+ // Sync trip switch characteristic when origin is not a direct switch press.
88
+ if (origin === OriginType.INTERNAL || origin === OriginType.EXTERNAL) {
89
+ this.services.tripSwitchService.updateCharacteristic(this.Characteristic.On, value);
90
+ }
91
+ return true;
92
+ }
93
+ /**
94
+ * Trip a mode-specific switch. Only triggers if the system is currently in
95
+ * the required mode (or the alarm is triggered and target matches).
96
+ */
97
+ triggerIfModeSet(requiredState, value) {
98
+ const isTriggered = this.state.currentState === SecurityState.TRIGGERED;
99
+ if (value) {
100
+ const modeMatches = this.state.currentState === requiredState
101
+ || (isTriggered && this.state.targetState === requiredState);
102
+ if (!modeMatches) {
103
+ this.log.debug('Security System (Trip mode not set)');
104
+ return false;
105
+ }
106
+ }
107
+ return this.updateTripSwitch(value, OriginType.REGULAR_SWITCH, false);
108
+ }
109
+ resetTripSwitches() {
110
+ const switches = [
111
+ ['tripHomeSwitchService', 'Trip Home'],
112
+ ['tripAwaySwitchService', 'Trip Away'],
113
+ ['tripNightSwitchService', 'Trip Night'],
114
+ ['tripOverrideSwitchService', 'Trip Override'],
115
+ ];
116
+ for (const [key, label] of switches) {
117
+ const char = this.services[key].getCharacteristic(this.Characteristic.On);
118
+ if (char.value) {
119
+ char.updateValue(false);
120
+ this.log.debug(`${label} Switch (Off)`);
121
+ }
122
+ }
123
+ }
124
+ activateTrip(origin) {
125
+ this.log.info('Security System (Tripped)');
126
+ if (this.options.trippedMotionSensor) {
127
+ this.sensorHandler.pulseTrippedMotionSensor();
128
+ this.state.trippedMotionSensorInterval = setInterval(() => this.sensorHandler.pulseTrippedMotionSensor(), this.options.trippedMotionSensorSeconds * 1000);
129
+ }
130
+ const triggerSeconds = this.resolveTriggerSeconds();
131
+ this.log.debug(`Trigger delay (${triggerSeconds}s)`);
132
+ this.state.triggerTimeout = setTimeout(() => {
133
+ this.state.triggerTimeout = null;
134
+ this.stateHandler.setCurrentState(SecurityState.TRIGGERED, origin);
135
+ }, triggerSeconds * 1000);
136
+ if (triggerSeconds > 0) {
137
+ this.bus.emit(EventType.WARNING, { origin, triggerSeconds });
138
+ }
139
+ }
140
+ cancelTrip(origin, stateChanged) {
141
+ this.log.info('Security System (Cancelled)');
142
+ this.audio.stop();
143
+ if (this.state.currentState === SecurityState.TRIGGERED) {
144
+ if (!stateChanged) {
145
+ this.stateHandler.updateTargetState(SecurityState.OFF, OriginType.INTERNAL, 0);
146
+ }
147
+ }
148
+ else {
149
+ this.stateHandler.resetTimers();
150
+ }
151
+ if (this.options.trippedMotionSensor) {
152
+ this.sensorHandler.resetTrippedMotionSensor();
153
+ }
154
+ this.state.isKnocked = false;
155
+ }
156
+ resolveTriggerSeconds() {
157
+ const seconds = this.options.triggerSeconds;
158
+ const cur = this.state.currentState;
159
+ if (cur === SecurityState.HOME && this.options.homeTriggerSeconds !== null) {
160
+ return this.options.homeTriggerSeconds;
161
+ }
162
+ if (cur === SecurityState.AWAY) {
163
+ const extChar = this.services.modeAwayExtendedSwitchService
164
+ .getCharacteristic(this.Characteristic.On);
165
+ if (this.options.modeAwayExtendedSwitchTriggerSeconds !== null && extChar.value) {
166
+ return this.options.modeAwayExtendedSwitchTriggerSeconds;
167
+ }
168
+ if (this.options.awayTriggerSeconds !== null) {
169
+ return this.options.awayTriggerSeconds;
170
+ }
171
+ }
172
+ if (cur === SecurityState.NIGHT && this.options.nightTriggerSeconds !== null) {
173
+ return this.options.nightTriggerSeconds;
174
+ }
175
+ return seconds;
176
+ }
177
+ }
178
+ export { HK_NOT_ALLOWED_IN_CURRENT_STATE };
179
+ //# sourceMappingURL=trip-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trip-handler.js","sourceRoot":"","sources":["../../src/handlers/trip-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { API } from 'homebridge';
2
+ declare const _default: (api: API) => void;
3
+ export default _default;
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ import { SecuritySystem } from './security-system.js';
2
+ const PLUGIN_NAME = 'homebridge-securitysystem';
3
+ const ACCESSORY_NAME = 'security-system';
4
+ export default (api) => {
5
+ api.registerAccessory(PLUGIN_NAME, ACCESSORY_NAME, SecuritySystem);
6
+ };
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,WAAW,GAAG,2BAA2B,CAAC;AAChD,MAAM,cAAc,GAAG,iBAAiB,CAAC;AAEzC,eAAe,CAAC,GAAQ,EAAQ,EAAE;IAChC,GAAG,CAAC,iBAAiB,CAAC,WAAW,EAAE,cAAc,EAAE,cAAc,CAAC,CAAC;AACrE,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { OriginType } from '../types/origin-type.js';
2
+ import type { SecuritySystemOptions } from './options-interface.js';
3
+ import type { ServiceRegistry } from './service-registry-interface.js';
4
+ import type { SystemState } from './system-state-interface.js';
5
+ /** Context passed to Condition.evaluate() to determine if an action is blocked. */
6
+ export interface ConditionContext {
7
+ state: SystemState;
8
+ services: ServiceRegistry;
9
+ options: SecuritySystemOptions;
10
+ /** The value being set (true = activating, false = deactivating). */
11
+ value: boolean;
12
+ origin: OriginType;
13
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=condition-context-interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"condition-context-interface.js","sourceRoot":"","sources":["../../src/interfaces/condition-context-interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ import type { API } from 'homebridge';
2
+ /**
3
+ * Runtime type of `api.hap.Characteristic` (the class with all static characteristic
4
+ * definitions). Using `API['hap']['Characteristic']` avoids the self-referential
5
+ * `typeof Characteristic` issue that arises with `import type { Characteristic }`.
6
+ */
7
+ export type CharacteristicConstructor = API['hap']['Characteristic'];
8
+ /** Runtime type of `api.hap.Service`. */
9
+ export type ServiceConstructor = API['hap']['Service'];
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=hap-types-interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hap-types-interface.js","sourceRoot":"","sources":["../../src/interfaces/hap-types-interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,93 @@
1
+ /** Key-value pair for extra ffplay environment variables. */
2
+ export interface AudioVariable {
3
+ key: string;
4
+ value: string;
5
+ }
6
+ /** Fully-parsed, strongly-typed configuration options for the security system. */
7
+ export interface SecuritySystemOptions {
8
+ name: string;
9
+ serialNumber: string;
10
+ defaultMode: string;
11
+ armSeconds: number;
12
+ triggerSeconds: number;
13
+ resetMinutes: number;
14
+ saveState: boolean;
15
+ proxyMode: boolean;
16
+ testMode: boolean;
17
+ tripSwitchName: string;
18
+ tripHomeSwitchName: string;
19
+ tripAwaySwitchName: string;
20
+ tripNightSwitchName: string;
21
+ tripOverrideSwitchName: string;
22
+ modeHomeSwitchName: string;
23
+ modeAwaySwitchName: string;
24
+ modeNightSwitchName: string;
25
+ modeOffSwitchName: string;
26
+ modeAwayExtendedSwitchName: string;
27
+ modePauseSwitchName: string;
28
+ audioSwitchName: string;
29
+ logDirectory: string | null;
30
+ overrideOff: boolean;
31
+ resetOffFlow: boolean;
32
+ disabledModes: string[];
33
+ homeArmSeconds: number | null;
34
+ awayArmSeconds: number | null;
35
+ nightArmSeconds: number | null;
36
+ homeTriggerSeconds: number | null;
37
+ awayTriggerSeconds: number | null;
38
+ nightTriggerSeconds: number | null;
39
+ tripSwitch: boolean;
40
+ tripOverrideSwitch: boolean;
41
+ tripModeSwitches: boolean;
42
+ armingLockSwitch: boolean;
43
+ armingLockSwitches: boolean;
44
+ armingMotionSensor: boolean;
45
+ trippedMotionSensor: boolean;
46
+ trippedMotionSensorSeconds: number;
47
+ triggeredMotionSensor: boolean;
48
+ triggeredMotionSensorSeconds: number;
49
+ resetSensor: boolean;
50
+ modeSwitches: boolean;
51
+ modeOffSwitch: boolean;
52
+ modePauseSwitch: boolean;
53
+ pauseMinutes: number;
54
+ modeAwayExtendedSwitch: boolean;
55
+ modeAwayExtendedSwitchTriggerSeconds: number | null;
56
+ doubleKnock: boolean;
57
+ doubleKnockSeconds: number;
58
+ doubleKnockModes: string[];
59
+ homeDoubleKnockSeconds: number | null;
60
+ awayDoubleKnockSeconds: number | null;
61
+ nightDoubleKnockSeconds: number | null;
62
+ audio: boolean;
63
+ audioPath: string | null;
64
+ audioLanguage: string;
65
+ audioVolume: number | null;
66
+ audioArmingLooped: boolean;
67
+ audioAlertLooped: boolean;
68
+ audioExtraVariables: AudioVariable[];
69
+ audioSwitch: boolean;
70
+ serverPort: number | null;
71
+ serverCode: number | null;
72
+ commandTargetHome: string | null;
73
+ commandTargetAway: string | null;
74
+ commandTargetNight: string | null;
75
+ commandTargetOff: string | null;
76
+ commandCurrentHome: string | null;
77
+ commandCurrentAway: string | null;
78
+ commandCurrentNight: string | null;
79
+ commandCurrentOff: string | null;
80
+ commandCurrentWarning: string | null;
81
+ commandCurrentTriggered: string | null;
82
+ webhookUrl: string | null;
83
+ webhookTargetHome: string | null;
84
+ webhookTargetAway: string | null;
85
+ webhookTargetNight: string | null;
86
+ webhookTargetOff: string | null;
87
+ webhookCurrentHome: string | null;
88
+ webhookCurrentAway: string | null;
89
+ webhookCurrentNight: string | null;
90
+ webhookCurrentOff: string | null;
91
+ webhookCurrentWarning: string | null;
92
+ webhookCurrentTriggered: string | null;
93
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=options-interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options-interface.js","sourceRoot":"","sources":["../../src/interfaces/options-interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ import type { SecurityState } from '../types/security-state-type.js';
2
+ /** Subset of SystemState that is persisted across Homebridge restarts. */
3
+ export interface PersistedState {
4
+ currentState: SecurityState;
5
+ targetState: SecurityState;
6
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=persisted-state-interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persisted-state-interface.js","sourceRoot":"","sources":["../../src/interfaces/persisted-state-interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,26 @@
1
+ import type { Service } from 'homebridge';
2
+ /** All HomeKit services exposed by the security system accessory. */
3
+ export interface ServiceRegistry {
4
+ mainService: Service;
5
+ accessoryInfoService: Service;
6
+ tripSwitchService: Service;
7
+ tripHomeSwitchService: Service;
8
+ tripAwaySwitchService: Service;
9
+ tripNightSwitchService: Service;
10
+ tripOverrideSwitchService: Service;
11
+ armingLockSwitchService: Service;
12
+ armingLockHomeSwitchService: Service;
13
+ armingLockAwaySwitchService: Service;
14
+ armingLockNightSwitchService: Service;
15
+ modeHomeSwitchService: Service;
16
+ modeAwaySwitchService: Service;
17
+ modeNightSwitchService: Service;
18
+ modeOffSwitchService: Service;
19
+ modeAwayExtendedSwitchService: Service;
20
+ modePauseSwitchService: Service;
21
+ audioSwitchService: Service;
22
+ armingMotionSensorService: Service;
23
+ trippedMotionSensorService: Service;
24
+ triggeredMotionSensorService: Service;
25
+ triggeredResetMotionSensorService: Service;
26
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=service-registry-interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-registry-interface.js","sourceRoot":"","sources":["../../src/interfaces/service-registry-interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,21 @@
1
+ import type { ChildProcess } from 'child_process';
2
+ import type { SecurityState } from '../types/security-state-type.js';
3
+ /** Mutable runtime state shared across all handlers. */
4
+ export interface SystemState {
5
+ currentState: SecurityState;
6
+ targetState: SecurityState;
7
+ defaultState: SecurityState;
8
+ availableTargetStates: SecurityState[];
9
+ isArming: boolean;
10
+ isKnocked: boolean;
11
+ invalidCodeCount: number;
12
+ pausedCurrentState: SecurityState | null;
13
+ audioProcess: ChildProcess | null;
14
+ armTimeout: ReturnType<typeof setTimeout> | null;
15
+ pauseTimeout: ReturnType<typeof setTimeout> | null;
16
+ triggerTimeout: ReturnType<typeof setTimeout> | null;
17
+ doubleKnockTimeout: ReturnType<typeof setTimeout> | null;
18
+ resetTimeout: ReturnType<typeof setTimeout> | null;
19
+ trippedMotionSensorInterval: ReturnType<typeof setInterval> | null;
20
+ triggeredMotionSensorInterval: ReturnType<typeof setInterval> | null;
21
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=system-state-interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-state-interface.js","sourceRoot":"","sources":["../../src/interfaces/system-state-interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,26 @@
1
+ import type { API, AccessoryPlugin, Logging, Service } from 'homebridge';
2
+ export declare class SecuritySystem implements AccessoryPlugin {
3
+ private readonly log;
4
+ private readonly api;
5
+ private readonly options;
6
+ private readonly state;
7
+ private readonly svcs;
8
+ private readonly serviceList;
9
+ private readonly bus;
10
+ private readonly stateHandler;
11
+ private readonly tripHandler;
12
+ private readonly switchHandler;
13
+ private readonly sensorHandler;
14
+ private readonly storageService;
15
+ private readonly audioService;
16
+ constructor(log: Logging, config: Record<string, unknown>, api: API);
17
+ getServices(): Service[];
18
+ identify(): void;
19
+ private buildState;
20
+ private buildServices;
21
+ private registerHandlers;
22
+ private buildServiceList;
23
+ private calcAvailableStates;
24
+ private modeToStateVal;
25
+ private logStartup;
26
+ }