homebridge-securitysystem 0.0.1-matter

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 (257) hide show
  1. package/.gitattributes +1 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.yml +46 -0
  3. package/.github/ISSUE_TEMPLATE/feature-request.yml +17 -0
  4. package/.github/ISSUE_TEMPLATE/questions-answers.yml +40 -0
  5. package/.github/demo.jpg +0 -0
  6. package/.github/dependabot.yml +19 -0
  7. package/.github/release.yml +36 -0
  8. package/.github/workflows/build-package.yml +49 -0
  9. package/.github/workflows/bump-version.yml +59 -0
  10. package/.github/workflows/dependency-review.yml +26 -0
  11. package/.github/workflows/publish.yml +155 -0
  12. package/.github/workflows/stale-activity.yml +27 -0
  13. package/AGENTS.md +247 -0
  14. package/CHANGELOG.md +572 -0
  15. package/CODE_OF_CONDUCT.md +128 -0
  16. package/CONTRIBUTING.md +5 -0
  17. package/LICENSE +21 -0
  18. package/README.md +47 -0
  19. package/SECURITY.md +12 -0
  20. package/config.schema.json +934 -0
  21. package/dist/conditions/already-triggered-condition.d.ts +10 -0
  22. package/dist/conditions/already-triggered-condition.js +22 -0
  23. package/dist/conditions/already-triggered-condition.js.map +1 -0
  24. package/dist/conditions/arming-in-progress-condition.d.ts +10 -0
  25. package/dist/conditions/arming-in-progress-condition.js +21 -0
  26. package/dist/conditions/arming-in-progress-condition.js.map +1 -0
  27. package/dist/conditions/arming-lock-condition.d.ts +10 -0
  28. package/dist/conditions/arming-lock-condition.js +43 -0
  29. package/dist/conditions/arming-lock-condition.js.map +1 -0
  30. package/dist/conditions/condition.d.ts +22 -0
  31. package/dist/conditions/condition.js +19 -0
  32. package/dist/conditions/condition.js.map +1 -0
  33. package/dist/conditions/double-knock-condition.d.ts +24 -0
  34. package/dist/conditions/double-knock-condition.js +73 -0
  35. package/dist/conditions/double-knock-condition.js.map +1 -0
  36. package/dist/conditions/not-armed-condition.d.ts +10 -0
  37. package/dist/conditions/not-armed-condition.js +26 -0
  38. package/dist/conditions/not-armed-condition.js.map +1 -0
  39. package/dist/conditions/trigger-already-running-condition.d.ts +10 -0
  40. package/dist/conditions/trigger-already-running-condition.js +21 -0
  41. package/dist/conditions/trigger-already-running-condition.js.map +1 -0
  42. package/dist/constants/default-constant.d.ts +24 -0
  43. package/dist/constants/default-constant.js +27 -0
  44. package/dist/constants/default-constant.js.map +1 -0
  45. package/dist/constants/homekit-constant.d.ts +2 -0
  46. package/dist/constants/homekit-constant.js +3 -0
  47. package/dist/constants/homekit-constant.js.map +1 -0
  48. package/dist/constants/matter-constant.d.ts +21 -0
  49. package/dist/constants/matter-constant.js +61 -0
  50. package/dist/constants/matter-constant.js.map +1 -0
  51. package/dist/handlers/sensor-handler.d.ts +24 -0
  52. package/dist/handlers/sensor-handler.js +63 -0
  53. package/dist/handlers/sensor-handler.js.map +1 -0
  54. package/dist/handlers/state-handler.d.ts +49 -0
  55. package/dist/handlers/state-handler.js +204 -0
  56. package/dist/handlers/state-handler.js.map +1 -0
  57. package/dist/handlers/switch-handler.d.ts +28 -0
  58. package/dist/handlers/switch-handler.js +95 -0
  59. package/dist/handlers/switch-handler.js.map +1 -0
  60. package/dist/handlers/trip-handler.d.ts +44 -0
  61. package/dist/handlers/trip-handler.js +156 -0
  62. package/dist/handlers/trip-handler.js.map +1 -0
  63. package/dist/homekit/homekit-registrar.d.ts +12 -0
  64. package/dist/homekit/homekit-registrar.js +23 -0
  65. package/dist/homekit/homekit-registrar.js.map +1 -0
  66. package/dist/homekit/service-factory.d.ts +12 -0
  67. package/dist/homekit/service-factory.js +24 -0
  68. package/dist/homekit/service-factory.js.map +1 -0
  69. package/dist/index.d.ts +3 -0
  70. package/dist/index.js +7 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/interfaces/condition-context-interface.d.ts +14 -0
  73. package/dist/interfaces/condition-context-interface.js +2 -0
  74. package/dist/interfaces/condition-context-interface.js.map +1 -0
  75. package/dist/interfaces/hap-types-interface.d.ts +9 -0
  76. package/dist/interfaces/hap-types-interface.js +2 -0
  77. package/dist/interfaces/hap-types-interface.js.map +1 -0
  78. package/dist/interfaces/mqtt-status-payload-interface.d.ts +6 -0
  79. package/dist/interfaces/mqtt-status-payload-interface.js +2 -0
  80. package/dist/interfaces/mqtt-status-payload-interface.js.map +1 -0
  81. package/dist/interfaces/options-interface.d.ts +87 -0
  82. package/dist/interfaces/options-interface.js +2 -0
  83. package/dist/interfaces/options-interface.js.map +1 -0
  84. package/dist/interfaces/persisted-state-interface.d.ts +6 -0
  85. package/dist/interfaces/persisted-state-interface.js +2 -0
  86. package/dist/interfaces/persisted-state-interface.js.map +1 -0
  87. package/dist/interfaces/service-registry-interface.d.ts +10 -0
  88. package/dist/interfaces/service-registry-interface.js +2 -0
  89. package/dist/interfaces/service-registry-interface.js.map +1 -0
  90. package/dist/interfaces/system-state-interface.d.ts +22 -0
  91. package/dist/interfaces/system-state-interface.js +2 -0
  92. package/dist/interfaces/system-state-interface.js.map +1 -0
  93. package/dist/schemas/arming-lock-schema.d.ts +10 -0
  94. package/dist/schemas/arming-lock-schema.js +12 -0
  95. package/dist/schemas/arming-lock-schema.js.map +1 -0
  96. package/dist/schemas/error-schema.d.ts +4 -0
  97. package/dist/schemas/error-schema.js +7 -0
  98. package/dist/schemas/error-schema.js.map +1 -0
  99. package/dist/schemas/mode-request-schema.d.ts +10 -0
  100. package/dist/schemas/mode-request-schema.js +18 -0
  101. package/dist/schemas/mode-request-schema.js.map +1 -0
  102. package/dist/schemas/status-response-schema.d.ts +7 -0
  103. package/dist/schemas/status-response-schema.js +10 -0
  104. package/dist/schemas/status-response-schema.js.map +1 -0
  105. package/dist/schemas/trip-mode-request-schema.d.ts +9 -0
  106. package/dist/schemas/trip-mode-request-schema.js +24 -0
  107. package/dist/schemas/trip-mode-request-schema.js.map +1 -0
  108. package/dist/security-system-platform.d.ts +19 -0
  109. package/dist/security-system-platform.js +56 -0
  110. package/dist/security-system-platform.js.map +1 -0
  111. package/dist/security-system.d.ts +28 -0
  112. package/dist/security-system.js +169 -0
  113. package/dist/security-system.js.map +1 -0
  114. package/dist/services/command-service.d.ts +16 -0
  115. package/dist/services/command-service.js +65 -0
  116. package/dist/services/command-service.js.map +1 -0
  117. package/dist/services/configuration-service.d.ts +24 -0
  118. package/dist/services/configuration-service.js +189 -0
  119. package/dist/services/configuration-service.js.map +1 -0
  120. package/dist/services/event-bus-service.d.ts +12 -0
  121. package/dist/services/event-bus-service.js +17 -0
  122. package/dist/services/event-bus-service.js.map +1 -0
  123. package/dist/services/matter-service.d.ts +69 -0
  124. package/dist/services/matter-service.js +363 -0
  125. package/dist/services/matter-service.js.map +1 -0
  126. package/dist/services/mqtt-service.d.ts +16 -0
  127. package/dist/services/mqtt-service.js +97 -0
  128. package/dist/services/mqtt-service.js.map +1 -0
  129. package/dist/services/server-service.d.ts +28 -0
  130. package/dist/services/server-service.js +275 -0
  131. package/dist/services/server-service.js.map +1 -0
  132. package/dist/services/storage-service.d.ts +14 -0
  133. package/dist/services/storage-service.js +70 -0
  134. package/dist/services/storage-service.js.map +1 -0
  135. package/dist/services/webhook-service.d.ts +16 -0
  136. package/dist/services/webhook-service.js +68 -0
  137. package/dist/services/webhook-service.js.map +1 -0
  138. package/dist/tests/conditions.test.d.ts +1 -0
  139. package/dist/tests/conditions.test.js +175 -0
  140. package/dist/tests/conditions.test.js.map +1 -0
  141. package/dist/tests/matter-service.test.d.ts +1 -0
  142. package/dist/tests/matter-service.test.js +475 -0
  143. package/dist/tests/matter-service.test.js.map +1 -0
  144. package/dist/tests/mqtt-service.test.d.ts +1 -0
  145. package/dist/tests/mqtt-service.test.js +168 -0
  146. package/dist/tests/mqtt-service.test.js.map +1 -0
  147. package/dist/tests/sensor-handler.test.d.ts +1 -0
  148. package/dist/tests/sensor-handler.test.js +87 -0
  149. package/dist/tests/sensor-handler.test.js.map +1 -0
  150. package/dist/tests/server-service.test.d.ts +1 -0
  151. package/dist/tests/server-service.test.js +188 -0
  152. package/dist/tests/server-service.test.js.map +1 -0
  153. package/dist/tests/state-handler.test.d.ts +1 -0
  154. package/dist/tests/state-handler.test.js +276 -0
  155. package/dist/tests/state-handler.test.js.map +1 -0
  156. package/dist/tests/switch-handler.test.d.ts +1 -0
  157. package/dist/tests/switch-handler.test.js +186 -0
  158. package/dist/tests/switch-handler.test.js.map +1 -0
  159. package/dist/tests/trip-handler.test.d.ts +1 -0
  160. package/dist/tests/trip-handler.test.js +179 -0
  161. package/dist/tests/trip-handler.test.js.map +1 -0
  162. package/dist/timers/timer-manager.d.ts +31 -0
  163. package/dist/timers/timer-manager.js +118 -0
  164. package/dist/timers/timer-manager.js.map +1 -0
  165. package/dist/types/event-payload-map-type.d.ts +15 -0
  166. package/dist/types/event-payload-map-type.js +2 -0
  167. package/dist/types/event-payload-map-type.js.map +1 -0
  168. package/dist/types/event-type.d.ts +44 -0
  169. package/dist/types/event-type.js +20 -0
  170. package/dist/types/event-type.js.map +1 -0
  171. package/dist/types/matter-accessory-key-type.d.ts +7 -0
  172. package/dist/types/matter-accessory-key-type.js +2 -0
  173. package/dist/types/matter-accessory-key-type.js.map +1 -0
  174. package/dist/types/mode-type.d.ts +4 -0
  175. package/dist/types/mode-type.js +2 -0
  176. package/dist/types/mode-type.js.map +1 -0
  177. package/dist/types/origin-type.d.ts +9 -0
  178. package/dist/types/origin-type.js +11 -0
  179. package/dist/types/origin-type.js.map +1 -0
  180. package/dist/types/security-state-type.d.ts +11 -0
  181. package/dist/types/security-state-type.js +13 -0
  182. package/dist/types/security-state-type.js.map +1 -0
  183. package/dist/types/sensor-kind-type.d.ts +2 -0
  184. package/dist/types/sensor-kind-type.js +2 -0
  185. package/dist/types/sensor-kind-type.js.map +1 -0
  186. package/dist/types/service-result-type.d.ts +4 -0
  187. package/dist/types/service-result-type.js +2 -0
  188. package/dist/types/service-result-type.js.map +1 -0
  189. package/dist/utils/arming-util.d.ts +19 -0
  190. package/dist/utils/arming-util.js +24 -0
  191. package/dist/utils/arming-util.js.map +1 -0
  192. package/dist/utils/state-util.d.ts +8 -0
  193. package/dist/utils/state-util.js +29 -0
  194. package/dist/utils/state-util.js.map +1 -0
  195. package/docs/MQTT.md +50 -0
  196. package/package.json +64 -0
  197. package/src/@types/homebridge-lib.d.ts +11 -0
  198. package/src/conditions/already-triggered-condition.ts +24 -0
  199. package/src/conditions/arming-in-progress-condition.ts +23 -0
  200. package/src/conditions/arming-lock-condition.ts +50 -0
  201. package/src/conditions/condition.ts +31 -0
  202. package/src/conditions/double-knock-condition.ts +84 -0
  203. package/src/conditions/not-armed-condition.ts +30 -0
  204. package/src/conditions/trigger-already-running-condition.ts +23 -0
  205. package/src/constants/default-constant.ts +28 -0
  206. package/src/constants/homekit-constant.ts +2 -0
  207. package/src/constants/matter-constant.ts +69 -0
  208. package/src/handlers/sensor-handler.ts +78 -0
  209. package/src/handlers/state-handler.ts +257 -0
  210. package/src/handlers/switch-handler.ts +111 -0
  211. package/src/handlers/trip-handler.ts +193 -0
  212. package/src/homekit/homekit-registrar.ts +28 -0
  213. package/src/homekit/service-factory.ts +35 -0
  214. package/src/index.ts +9 -0
  215. package/src/interfaces/condition-context-interface.ts +15 -0
  216. package/src/interfaces/hap-types-interface.ts +11 -0
  217. package/src/interfaces/mqtt-status-payload-interface.ts +6 -0
  218. package/src/interfaces/options-interface.ts +116 -0
  219. package/src/interfaces/persisted-state-interface.ts +7 -0
  220. package/src/interfaces/service-registry-interface.ts +11 -0
  221. package/src/interfaces/system-state-interface.ts +25 -0
  222. package/src/schemas/arming-lock-schema.ts +12 -0
  223. package/src/schemas/error-schema.ts +7 -0
  224. package/src/schemas/mode-request-schema.ts +18 -0
  225. package/src/schemas/status-response-schema.ts +10 -0
  226. package/src/schemas/trip-mode-request-schema.ts +24 -0
  227. package/src/security-system-platform.ts +68 -0
  228. package/src/security-system.ts +199 -0
  229. package/src/services/command-service.ts +76 -0
  230. package/src/services/configuration-service.ts +224 -0
  231. package/src/services/event-bus-service.ts +21 -0
  232. package/src/services/matter-service.ts +446 -0
  233. package/src/services/mqtt-service.ts +123 -0
  234. package/src/services/server-service.ts +327 -0
  235. package/src/services/storage-service.ts +80 -0
  236. package/src/services/webhook-service.ts +77 -0
  237. package/src/tests/conditions.test.ts +212 -0
  238. package/src/tests/matter-service.test.ts +610 -0
  239. package/src/tests/mqtt-service.test.ts +231 -0
  240. package/src/tests/sensor-handler.test.ts +116 -0
  241. package/src/tests/server-service.test.ts +238 -0
  242. package/src/tests/state-handler.test.ts +371 -0
  243. package/src/tests/switch-handler.test.ts +234 -0
  244. package/src/tests/trip-handler.test.ts +244 -0
  245. package/src/timers/timer-manager.ts +141 -0
  246. package/src/types/event-payload-map-type.ts +25 -0
  247. package/src/types/event-type.ts +61 -0
  248. package/src/types/matter-accessory-key-type.ts +33 -0
  249. package/src/types/mode-type.ts +4 -0
  250. package/src/types/origin-type.ts +9 -0
  251. package/src/types/security-state-type.ts +11 -0
  252. package/src/types/sensor-kind-type.ts +2 -0
  253. package/src/types/service-result-type.ts +4 -0
  254. package/src/utils/arming-util.ts +44 -0
  255. package/src/utils/state-util.ts +32 -0
  256. package/tsconfig.json +26 -0
  257. package/vitest.config.ts +8 -0
@@ -0,0 +1,49 @@
1
+ import type { Logging } from 'homebridge';
2
+ import type { CharacteristicConstructor } from '../interfaces/hap-types-interface.js';
3
+ import { SecurityState } from '../types/security-state-type.js';
4
+ import { OriginType } from '../types/origin-type.js';
5
+ import type { ServiceRegistry } from '../interfaces/service-registry-interface.js';
6
+ import type { SystemState } from '../interfaces/system-state-interface.js';
7
+ import type { SecuritySystemOptions } from '../interfaces/options-interface.js';
8
+ import type { EventBusService } from '../services/event-bus-service.js';
9
+ import type { StorageService } from '../services/storage-service.js';
10
+ import type { SensorHandler } from './sensor-handler.js';
11
+ import type { TimerManager } from '../timers/timer-manager.js';
12
+ import type { ServiceResult } from '../types/service-result-type.js';
13
+ /**
14
+ * Manages the core security-system state machine: arming, triggering, and resetting.
15
+ * Cross-handler side effects are signalled via the event bus so that this class has
16
+ * no direct dependencies on TripHandler or SwitchHandler.
17
+ */
18
+ export declare class StateHandler {
19
+ private readonly services;
20
+ private readonly state;
21
+ private readonly options;
22
+ private readonly Characteristic;
23
+ private readonly log;
24
+ private readonly bus;
25
+ private readonly storageService;
26
+ private readonly timers;
27
+ private readonly sensorHandler;
28
+ constructor(services: ServiceRegistry, state: SystemState, options: SecuritySystemOptions, Characteristic: CharacteristicConstructor, log: Logging, bus: EventBusService, storageService: StorageService, timers: TimerManager, sensorHandler: SensorHandler);
29
+ setCurrentState(state: SecurityState, origin: OriginType): void;
30
+ updateTargetState(state: SecurityState, origin: OriginType, delay: number): ServiceResult;
31
+ getArmingSeconds(targetState: SecurityState): number;
32
+ resetTimers(): void;
33
+ /** Returns true while the trigger delay is counting down (trip switch is active). */
34
+ isTripping(): boolean;
35
+ /** Checks whether arming is currently blocked by an arming-lock switch. */
36
+ isArmingLocked(targetState: SecurityState): boolean;
37
+ getAvailableTargetStates(): SecurityState[];
38
+ logMode(type: string, state: SecurityState | string): void;
39
+ /**
40
+ * Returns a human-readable reason string if `state` is an invalid target,
41
+ * or `null` if the transition is permitted.
42
+ */
43
+ private getBadTargetStateReason;
44
+ private handleTargetStateChange;
45
+ private handleCurrentStateChange;
46
+ private handleTriggeredState;
47
+ private handleArmingState;
48
+ private resetViaOffMode;
49
+ }
@@ -0,0 +1,204 @@
1
+ import { SecurityState } from '../types/security-state-type.js';
2
+ import { OriginType } from '../types/origin-type.js';
3
+ import { stateToMode, capitalise } from '../utils/state-util.js';
4
+ import { modeToState } from '../utils/state-util.js';
5
+ import { EventType } from '../types/event-type.js';
6
+ import { getArmingSeconds } from '../utils/arming-util.js';
7
+ /**
8
+ * Manages the core security-system state machine: arming, triggering, and resetting.
9
+ * Cross-handler side effects are signalled via the event bus so that this class has
10
+ * no direct dependencies on TripHandler or SwitchHandler.
11
+ */
12
+ export class StateHandler {
13
+ services;
14
+ state;
15
+ options;
16
+ Characteristic;
17
+ log;
18
+ bus;
19
+ storageService;
20
+ timers;
21
+ sensorHandler;
22
+ constructor(services, state, options, Characteristic, log, bus, storageService, timers, sensorHandler) {
23
+ this.services = services;
24
+ this.state = state;
25
+ this.options = options;
26
+ this.Characteristic = Characteristic;
27
+ this.log = log;
28
+ this.bus = bus;
29
+ this.storageService = storageService;
30
+ this.timers = timers;
31
+ this.sensorHandler = sensorHandler;
32
+ }
33
+ // ── Public API ─────────────────────────────────────────────────────────────
34
+ setCurrentState(state, origin) {
35
+ this.sensorHandler.resetArmingMotionSensor();
36
+ if (this.state.currentState === state) {
37
+ this.log.warn('Current mode (Already set)');
38
+ return;
39
+ }
40
+ this.state.currentState = state;
41
+ this.services.mainService.setCharacteristic(this.Characteristic.SecuritySystemCurrentState, state);
42
+ this.logMode('Current', state);
43
+ this.handleCurrentStateChange(origin);
44
+ this.storageService.save(this.state);
45
+ }
46
+ updateTargetState(state, origin, delay) {
47
+ // Same-target re-call: "confirm this mode externally; apply it now"
48
+ if (state === this.state.targetState && this.state.currentState !== SecurityState.TRIGGERED) {
49
+ if (state === this.state.currentState) {
50
+ return { success: true };
51
+ }
52
+ if (this.state.isArming) {
53
+ this.timers.clearArmTimer();
54
+ this.state.isArming = false;
55
+ }
56
+ this.setCurrentState(state, origin);
57
+ return { success: true };
58
+ }
59
+ const reason = this.getBadTargetStateReason(state);
60
+ if (reason !== null) {
61
+ return { success: false, reason };
62
+ }
63
+ this.state.targetState = state;
64
+ this.logMode('Target', state);
65
+ if (origin === OriginType.INTERNAL || origin === OriginType.EXTERNAL) {
66
+ this.services.mainService.updateCharacteristic(this.Characteristic.SecuritySystemTargetState, state);
67
+ }
68
+ this.handleTargetStateChange(origin);
69
+ if (state === this.state.currentState) {
70
+ this.setCurrentState(state, origin);
71
+ return { success: true };
72
+ }
73
+ const armSeconds = delay > 0 ? delay : 0;
74
+ if (armSeconds === 0) {
75
+ this.setCurrentState(state, origin);
76
+ return { success: true };
77
+ }
78
+ this.state.isArming = true;
79
+ this.handleArmingState();
80
+ this.log.info(`Arm delay (${armSeconds}s)`);
81
+ this.timers.setArmTimer(armSeconds * 1000, () => {
82
+ this.state.isArming = false;
83
+ this.setCurrentState(state, origin);
84
+ });
85
+ return { success: true };
86
+ }
87
+ getArmingSeconds(targetState) {
88
+ return getArmingSeconds(this.state, this.options, targetState);
89
+ }
90
+ resetTimers() {
91
+ this.timers.clearAll();
92
+ }
93
+ /** Returns true while the trigger delay is counting down (trip switch is active). */
94
+ isTripping() {
95
+ return this.state.isTripping;
96
+ }
97
+ /** Checks whether arming is currently blocked by an arming-lock switch. */
98
+ isArmingLocked(targetState) {
99
+ // Locks never block disarming.
100
+ if (targetState === SecurityState.OFF) {
101
+ return false;
102
+ }
103
+ if (this.state.armingLocks.global) {
104
+ return true;
105
+ }
106
+ const modeMap = {
107
+ [SecurityState.HOME]: 'home',
108
+ [SecurityState.AWAY]: 'away',
109
+ [SecurityState.NIGHT]: 'night',
110
+ };
111
+ const lock = modeMap[targetState];
112
+ return lock ? this.state.armingLocks[lock] : false;
113
+ }
114
+ getAvailableTargetStates() {
115
+ const all = [SecurityState.HOME, SecurityState.AWAY, SecurityState.NIGHT, SecurityState.OFF];
116
+ const disabled = this.options.disabledModes.map(m => modeToState(m.toLowerCase()));
117
+ return all.filter(s => !disabled.includes(s));
118
+ }
119
+ logMode(type, state) {
120
+ const mode = capitalise(stateToMode(state));
121
+ this.log.info(`${type} mode (${mode})`);
122
+ }
123
+ // ── Private helpers ────────────────────────────────────────────────────────
124
+ /**
125
+ * Returns a human-readable reason string if `state` is an invalid target,
126
+ * or `null` if the transition is permitted.
127
+ */
128
+ getBadTargetStateReason(state) {
129
+ const isTriggered = this.state.currentState === SecurityState.TRIGGERED;
130
+ const alreadySet = this.state.targetState === state;
131
+ if (alreadySet && !isTriggered) {
132
+ this.log.warn('Target mode (Already set)');
133
+ return 'target mode is already set';
134
+ }
135
+ if (!this.state.availableTargetStates.includes(state)) {
136
+ this.log.warn('Target mode (Disabled)');
137
+ return 'target mode is disabled';
138
+ }
139
+ const hasLock = this.options.armingLockSwitch || this.options.armingLockSwitches;
140
+ if (state !== SecurityState.OFF && hasLock && this.isArmingLocked(state)) {
141
+ this.log.warn('Arming lock (Not allowed)');
142
+ return 'arming is blocked by an arming lock switch';
143
+ }
144
+ return null;
145
+ }
146
+ handleTargetStateChange(origin) {
147
+ this.resetTimers();
148
+ // The away-extended flag only applies to the arm cycle it started; any
149
+ // subsequent target change clears it (mirrors the HAP mode-switch reset).
150
+ this.state.modeAwayExtended = false;
151
+ // Notify handlers to reset their displayed state (bus is synchronous).
152
+ this.bus.emit(EventType.RESET_TRIP_SWITCHES, {});
153
+ this.sensorHandler.resetTrippedMotionSensor();
154
+ this.bus.emit(EventType.RESET_MODE_SWITCHES, {});
155
+ this.bus.emit(EventType.UPDATE_MODE_SWITCHES, {});
156
+ this.bus.emit(EventType.TARGET_CHANGED, { state: this.state.targetState, origin });
157
+ if (this.state.currentState === SecurityState.TRIGGERED) {
158
+ this.sensorHandler.pulseResetMotionSensor();
159
+ }
160
+ this.state.isTripping = false;
161
+ this.state.isKnocked = false;
162
+ }
163
+ handleCurrentStateChange(origin) {
164
+ if (this.state.currentState === SecurityState.TRIGGERED) {
165
+ this.handleTriggeredState();
166
+ if (this.options.testMode) {
167
+ return;
168
+ }
169
+ }
170
+ else {
171
+ // Notify TripHandler to reset trip switches on any non-triggered state change.
172
+ // (Do not reset when entering TRIGGERED — the trip switch should remain ON
173
+ // to reflect the active sensor / cause of the alarm.)
174
+ this.bus.emit(EventType.RESET_TRIP_SWITCHES, {});
175
+ }
176
+ this.bus.emit(EventType.CURRENT_CHANGED, { state: this.state.currentState, origin });
177
+ }
178
+ handleTriggeredState() {
179
+ this.timers.clearTrippedInterval();
180
+ this.sensorHandler.resetTrippedMotionSensor();
181
+ this.timers.setResetTimer(this.options.resetMinutes * 60 * 1000, () => {
182
+ this.log.info('Reset (Finished)');
183
+ this.sensorHandler.pulseResetMotionSensor();
184
+ if (this.options.resetOffFlow) {
185
+ this.resetViaOffMode();
186
+ }
187
+ else {
188
+ this.setCurrentState(this.state.targetState, OriginType.EXTERNAL);
189
+ }
190
+ });
191
+ }
192
+ handleArmingState() {
193
+ this.sensorHandler.updateArmingMotionSensor(true);
194
+ this.bus.emit(EventType.ARMING, { state: this.state.targetState });
195
+ }
196
+ resetViaOffMode() {
197
+ const original = this.state.targetState;
198
+ this.updateTargetState(SecurityState.OFF, OriginType.INTERNAL, 0);
199
+ setTimeout(() => {
200
+ this.updateTargetState(original, OriginType.INTERNAL, this.getArmingSeconds(original));
201
+ }, 100);
202
+ }
203
+ }
204
+ //# sourceMappingURL=state-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-handler.js","sourceRoot":"","sources":["../../src/handlers/state-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { Logging } from 'homebridge';
2
+ import { SecurityState } from '../types/security-state-type.js';
3
+ import type { SystemState } from '../interfaces/system-state-interface.js';
4
+ import type { SecuritySystemOptions } from '../interfaces/options-interface.js';
5
+ import type { StateHandler } from './state-handler.js';
6
+ import type { TimerManager } from '../timers/timer-manager.js';
7
+ import type { ServiceResult } from '../types/service-result-type.js';
8
+ /**
9
+ * Handles all mode switches and the pause/extended switches.
10
+ * Switches are published over Matter only; the HAP layer no longer carries them,
11
+ * so every method reports outcomes as ServiceResult which MatterService maps to
12
+ * Matter status errors. The switch display state is pushed to Matter via bus
13
+ * events handled by MatterService.
14
+ */
15
+ export declare class SwitchHandler {
16
+ private readonly state;
17
+ private readonly options;
18
+ private readonly log;
19
+ private readonly timers;
20
+ private readonly stateHandler;
21
+ constructor(state: SystemState, options: SecuritySystemOptions, log: Logging, timers: TimerManager, stateHandler: StateHandler);
22
+ setModeSwitch(mode: SecurityState, value: boolean): ServiceResult;
23
+ setModeOffSwitch(value: boolean): ServiceResult;
24
+ setModeAwayExtendedSwitch(value: boolean): ServiceResult;
25
+ setModePauseSwitch(value: boolean): ServiceResult;
26
+ updateArmingLock(mode: string, value: boolean): ServiceResult;
27
+ private logArmingLock;
28
+ }
@@ -0,0 +1,95 @@
1
+ import { SecurityState } from '../types/security-state-type.js';
2
+ import { OriginType } from '../types/origin-type.js';
3
+ import { capitalise } from '../utils/state-util.js';
4
+ /**
5
+ * Handles all mode switches and the pause/extended switches.
6
+ * Switches are published over Matter only; the HAP layer no longer carries them,
7
+ * so every method reports outcomes as ServiceResult which MatterService maps to
8
+ * Matter status errors. The switch display state is pushed to Matter via bus
9
+ * events handled by MatterService.
10
+ */
11
+ export class SwitchHandler {
12
+ state;
13
+ options;
14
+ log;
15
+ timers;
16
+ stateHandler;
17
+ constructor(state, options, log, timers, stateHandler) {
18
+ this.state = state;
19
+ this.options = options;
20
+ this.log = log;
21
+ this.timers = timers;
22
+ this.stateHandler = stateHandler;
23
+ }
24
+ // ── Mode switches ──────────────────────────────────────────────────────────
25
+ setModeSwitch(mode, value) {
26
+ if (!value) {
27
+ return { success: false, reason: 'a mode switch can only be turned on' };
28
+ }
29
+ const delay = this.stateHandler.getArmingSeconds(mode);
30
+ return this.stateHandler.updateTargetState(mode, OriginType.INTERNAL, delay);
31
+ }
32
+ setModeOffSwitch(value) {
33
+ if (!value) {
34
+ return { success: false, reason: 'a mode switch can only be turned on' };
35
+ }
36
+ return this.stateHandler.updateTargetState(SecurityState.OFF, OriginType.INTERNAL, 0);
37
+ }
38
+ setModeAwayExtendedSwitch(value) {
39
+ if (!value) {
40
+ return { success: false, reason: 'the away-extended switch can only be turned on' };
41
+ }
42
+ const delay = this.stateHandler.getArmingSeconds(SecurityState.AWAY);
43
+ const result = this.stateHandler.updateTargetState(SecurityState.AWAY, OriginType.INTERNAL, delay);
44
+ if (result.success) {
45
+ this.state.modeAwayExtended = true;
46
+ }
47
+ return result;
48
+ }
49
+ setModePauseSwitch(value) {
50
+ if (this.state.currentState === SecurityState.TRIGGERED) {
51
+ this.log.warn('Mode pause (Alarm is triggered)');
52
+ return { success: false, reason: 'mode pause is not allowed while the alarm is triggered' };
53
+ }
54
+ if (value) {
55
+ if (this.state.currentState === SecurityState.OFF) {
56
+ this.log.warn('Mode pause (Not armed)');
57
+ return { success: false, reason: 'mode pause is not allowed while disarmed' };
58
+ }
59
+ this.log.info('Mode pause (Started)');
60
+ this.state.pausedCurrentState = this.state.currentState;
61
+ this.stateHandler.updateTargetState(SecurityState.OFF, OriginType.INTERNAL, 0);
62
+ if (this.options.pauseMinutes !== 0) {
63
+ this.timers.setPauseTimer(this.options.pauseMinutes * 60 * 1000, () => {
64
+ this.log.info('Mode pause (Finished)');
65
+ const prev = this.state.pausedCurrentState ?? this.state.defaultState;
66
+ this.stateHandler.updateTargetState(prev, OriginType.INTERNAL, this.stateHandler.getArmingSeconds(prev));
67
+ });
68
+ }
69
+ }
70
+ else {
71
+ this.log.info('Mode pause (Cancelled)');
72
+ this.timers.clearPauseTimer();
73
+ const prev = this.state.pausedCurrentState ?? this.state.defaultState;
74
+ this.stateHandler.updateTargetState(prev, OriginType.INTERNAL, this.stateHandler.getArmingSeconds(prev));
75
+ }
76
+ return { success: true };
77
+ }
78
+ // ── Arming lock switches ───────────────────────────────────────────────────
79
+ updateArmingLock(mode, value) {
80
+ this.logArmingLock(mode, value);
81
+ const locks = this.state.armingLocks;
82
+ const key = ['global', 'home', 'away', 'night']
83
+ .find(candidate => candidate === mode);
84
+ if (!key) {
85
+ this.log.debug(`Unknown arming lock mode (${mode})`);
86
+ return { success: false, reason: `unknown arming lock mode: ${mode}` };
87
+ }
88
+ locks[key] = value;
89
+ return { success: true };
90
+ }
91
+ logArmingLock(mode, value) {
92
+ this.log.info(`Arming lock [${capitalise(mode)}] (${value ? 'On' : 'Off'})`);
93
+ }
94
+ }
95
+ //# sourceMappingURL=switch-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"switch-handler.js","sourceRoot":"","sources":["../../src/handlers/switch-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
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 { SystemState } from '../interfaces/system-state-interface.js';
5
+ import type { SecuritySystemOptions } from '../interfaces/options-interface.js';
6
+ import type { EventBusService } from '../services/event-bus-service.js';
7
+ import type { SensorHandler } from './sensor-handler.js';
8
+ import type { TimerManager } from '../timers/timer-manager.js';
9
+ import type { ServiceResult } from '../types/service-result-type.js';
10
+ /**
11
+ * Handles the trip switch and trigger-delay logic, including all blocking conditions.
12
+ * Communicates state transitions back to the state machine via the event bus so that
13
+ * no circular import is needed with StateHandler.
14
+ */
15
+ export declare class TripHandler {
16
+ private readonly state;
17
+ private readonly options;
18
+ private readonly log;
19
+ private readonly bus;
20
+ private readonly sensorHandler;
21
+ private readonly timers;
22
+ private readonly conditions;
23
+ constructor(state: SystemState, options: SecuritySystemOptions, log: Logging, bus: EventBusService, sensorHandler: SensorHandler, timers: TimerManager);
24
+ /**
25
+ * Evaluates all blocking conditions for a trip action without side effects.
26
+ * Returns a failed result with the condition's reason if any condition blocks the action.
27
+ */
28
+ checkTripConditions(value: boolean, origin: OriginType): ServiceResult;
29
+ /**
30
+ * Core trip-switch logic shared by all trip/trigger paths.
31
+ * Returns a result object indicating success or the reason for failure.
32
+ */
33
+ updateTripSwitch(value: boolean, origin: OriginType, stateChanged: boolean): ServiceResult;
34
+ /**
35
+ * Trip a mode-specific switch. Only triggers if the system is currently in
36
+ * the required mode (or the alarm is triggered and target matches).
37
+ */
38
+ triggerIfModeSet(requiredState: SecurityState, value: boolean): ServiceResult;
39
+ private makeContext;
40
+ private activateTrip;
41
+ private startTrippedMotionSensor;
42
+ private cancelTrip;
43
+ private resolveTriggerSeconds;
44
+ }
@@ -0,0 +1,156 @@
1
+ import { SecurityState } from '../types/security-state-type.js';
2
+ import { OriginType } from '../types/origin-type.js';
3
+ import { EventType } from '../types/event-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
+ import { TriggerAlreadyRunningCondition } from '../conditions/trigger-already-running-condition.js';
9
+ /**
10
+ * Handles the trip switch and trigger-delay logic, including all blocking conditions.
11
+ * Communicates state transitions back to the state machine via the event bus so that
12
+ * no circular import is needed with StateHandler.
13
+ */
14
+ export class TripHandler {
15
+ state;
16
+ options;
17
+ log;
18
+ bus;
19
+ sensorHandler;
20
+ timers;
21
+ conditions;
22
+ constructor(state, options, log, bus, sensorHandler, timers) {
23
+ this.state = state;
24
+ this.options = options;
25
+ this.log = log;
26
+ this.bus = bus;
27
+ this.sensorHandler = sensorHandler;
28
+ this.timers = timers;
29
+ const doubleKnock = new DoubleKnockCondition((seconds, onExpire) => {
30
+ this.timers.setDoubleKnockTimer(seconds * 1000, onExpire);
31
+ }, () => {
32
+ this.timers.clearDoubleKnockTimer();
33
+ });
34
+ this.conditions = [
35
+ new NotArmedCondition(),
36
+ new ArmingInProgressCondition(),
37
+ doubleKnock,
38
+ new AlreadyTriggeredCondition(),
39
+ new TriggerAlreadyRunningCondition(),
40
+ ];
41
+ }
42
+ /**
43
+ * Evaluates all blocking conditions for a trip action without side effects.
44
+ * Returns a failed result with the condition's reason if any condition blocks the action.
45
+ */
46
+ checkTripConditions(value, origin) {
47
+ if (!value) {
48
+ return { success: true };
49
+ }
50
+ const ctx = this.makeContext(value, origin);
51
+ for (const condition of this.conditions) {
52
+ if (condition.evaluate(ctx)) {
53
+ return { success: false, reason: condition.failureReason };
54
+ }
55
+ }
56
+ return { success: true };
57
+ }
58
+ /**
59
+ * Core trip-switch logic shared by all trip/trigger paths.
60
+ * Returns a result object indicating success or the reason for failure.
61
+ */
62
+ updateTripSwitch(value, origin, stateChanged) {
63
+ if (value) {
64
+ const conditionResult = this.checkTripConditions(value, origin);
65
+ if (!conditionResult.success) {
66
+ return conditionResult;
67
+ }
68
+ this.activateTrip(origin);
69
+ }
70
+ else {
71
+ this.cancelTrip(origin, stateChanged);
72
+ }
73
+ // Sync trip switch characteristic when origin is not a direct switch press.
74
+ return { success: true };
75
+ }
76
+ /**
77
+ * Trip a mode-specific switch. Only triggers if the system is currently in
78
+ * the required mode (or the alarm is triggered and target matches).
79
+ */
80
+ triggerIfModeSet(requiredState, value) {
81
+ const isTriggered = this.state.currentState === SecurityState.TRIGGERED;
82
+ if (value) {
83
+ const modeMatches = this.state.currentState === requiredState
84
+ || (isTriggered && this.state.targetState === requiredState);
85
+ if (!modeMatches) {
86
+ this.log.debug('Security System (Trip mode not set)');
87
+ return { success: false, reason: 'mode not set' };
88
+ }
89
+ }
90
+ return this.updateTripSwitch(value, OriginType.REGULAR_SWITCH, false);
91
+ }
92
+ makeContext(value, origin) {
93
+ return {
94
+ state: this.state,
95
+ options: this.options,
96
+ value,
97
+ origin,
98
+ log: this.log,
99
+ };
100
+ }
101
+ activateTrip(origin) {
102
+ this.log.info('Security System (Tripped)');
103
+ if (this.options.trippedMotionSensor) {
104
+ this.startTrippedMotionSensor();
105
+ }
106
+ const triggerSeconds = this.resolveTriggerSeconds();
107
+ this.log.debug(`Trigger delay (${triggerSeconds}s)`);
108
+ this.state.isTripping = true;
109
+ this.timers.setTriggerTimer(triggerSeconds * 1000, () => {
110
+ this.state.isTripping = false;
111
+ this.bus.emit(EventType.TRIGGER_FIRED, { origin });
112
+ });
113
+ if (triggerSeconds > 0) {
114
+ this.bus.emit(EventType.WARNING, { origin, triggerSeconds });
115
+ }
116
+ }
117
+ startTrippedMotionSensor() {
118
+ const seconds = this.options.trippedMotionSensorSeconds;
119
+ if (seconds === 0) {
120
+ this.sensorHandler.setTrippedMotionSensor(true);
121
+ }
122
+ else {
123
+ this.sensorHandler.pulseTrippedMotionSensor();
124
+ this.timers.setTrippedInterval(seconds * 1000, () => this.sensorHandler.pulseTrippedMotionSensor());
125
+ }
126
+ }
127
+ cancelTrip(origin, stateChanged) {
128
+ this.log.info('Security System (Cancelled)');
129
+ this.state.isTripping = false;
130
+ this.bus.emit(EventType.TRIP_CANCELLED, { origin, stateChanged });
131
+ if (this.options.trippedMotionSensor) {
132
+ this.sensorHandler.resetTrippedMotionSensor();
133
+ }
134
+ this.state.isKnocked = false;
135
+ }
136
+ resolveTriggerSeconds() {
137
+ const seconds = this.options.triggerSeconds;
138
+ const cur = this.state.currentState;
139
+ if (cur === SecurityState.HOME && this.options.homeTriggerSeconds !== null) {
140
+ return this.options.homeTriggerSeconds;
141
+ }
142
+ if (cur === SecurityState.AWAY) {
143
+ if (this.options.modeAwayExtendedSwitchTriggerSeconds !== null && this.state.modeAwayExtended) {
144
+ return this.options.modeAwayExtendedSwitchTriggerSeconds;
145
+ }
146
+ if (this.options.awayTriggerSeconds !== null) {
147
+ return this.options.awayTriggerSeconds;
148
+ }
149
+ }
150
+ if (cur === SecurityState.NIGHT && this.options.nightTriggerSeconds !== null) {
151
+ return this.options.nightTriggerSeconds;
152
+ }
153
+ return seconds;
154
+ }
155
+ }
156
+ //# 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,12 @@
1
+ import type { CharacteristicConstructor } from '../interfaces/hap-types-interface.js';
2
+ import type { ServiceRegistry } from '../interfaces/service-registry-interface.js';
3
+ import type { SystemState } from '../interfaces/system-state-interface.js';
4
+ import type { StateHandler } from '../handlers/state-handler.js';
5
+ /** Attaches the HomeKit characteristic handlers (onGet / onSet) to the security system service. */
6
+ export declare class HomeKitRegistrar {
7
+ private readonly svcs;
8
+ private readonly state;
9
+ private readonly stateHandler;
10
+ constructor(svcs: ServiceRegistry, state: SystemState, stateHandler: StateHandler);
11
+ register(Char: CharacteristicConstructor): void;
12
+ }
@@ -0,0 +1,23 @@
1
+ import { OriginType } from '../types/origin-type.js';
2
+ /** Attaches the HomeKit characteristic handlers (onGet / onSet) to the security system service. */
3
+ export class HomeKitRegistrar {
4
+ svcs;
5
+ state;
6
+ stateHandler;
7
+ constructor(svcs, state, stateHandler) {
8
+ this.svcs = svcs;
9
+ this.state = state;
10
+ this.stateHandler = stateHandler;
11
+ }
12
+ register(Char) {
13
+ const s = this.svcs;
14
+ s.mainService.getCharacteristic(Char.SecuritySystemCurrentState)
15
+ .onGet(async () => this.state.currentState);
16
+ s.mainService.getCharacteristic(Char.SecuritySystemTargetState)
17
+ .onGet(async () => this.state.targetState)
18
+ .onSet(async (v) => {
19
+ this.stateHandler.updateTargetState(v, OriginType.REGULAR_SWITCH, this.stateHandler.getArmingSeconds(v));
20
+ });
21
+ }
22
+ }
23
+ //# sourceMappingURL=homekit-registrar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"homekit-registrar.js","sourceRoot":"","sources":["../../src/homekit/homekit-registrar.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGrD,mGAAmG;AACnG,MAAM,OAAO,gBAAgB;IAER,IAAI;IACJ,KAAK;IACL,YAAY;IAH/B,YACmB,IAAqB,EACrB,KAAkB,EAClB,YAA0B;oBAF1B,IAAI;qBACJ,KAAK;4BACL,YAAY;IAC5B,CAAC;IAEJ,QAAQ,CAAC,IAA+B;QACtC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;QAEpB,CAAC,CAAC,WAAW,CAAC,iBAAiB,CAAC,IAAI,CAAC,0BAA0B,CAAC;aAC7D,KAAK,CAAC,KAAK,IAAkC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC5E,CAAC,CAAC,WAAW,CAAC,iBAAiB,CAAC,IAAI,CAAC,yBAAyB,CAAC;aAC5D,KAAK,CAAC,KAAK,IAAkC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;aACvE,KAAK,CAAC,KAAK,EAAE,CAAsB,EAAE,EAAE;YACtC,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAkB,EAAE,UAAU,CAAC,cAAc,EAAE,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAkB,CAAC,CAAC,CAAC;QAC7I,CAAC,CAAC,CAAC;IACP,CAAC;CACF"}