homebridge-securitysystem 10.0.0-beta.2 → 10.0.0-beta.4

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 (83) hide show
  1. package/dist/conditions/already-triggered-condition.d.ts +1 -1
  2. package/dist/conditions/already-triggered-condition.js +6 -2
  3. package/dist/conditions/already-triggered-condition.js.map +1 -1
  4. package/dist/conditions/arming-in-progress-condition.d.ts +1 -1
  5. package/dist/conditions/arming-in-progress-condition.js +6 -2
  6. package/dist/conditions/arming-in-progress-condition.js.map +1 -1
  7. package/dist/conditions/double-knock-condition.d.ts +4 -2
  8. package/dist/conditions/double-knock-condition.js +9 -8
  9. package/dist/conditions/double-knock-condition.js.map +1 -1
  10. package/dist/conditions/not-armed-condition.d.ts +1 -1
  11. package/dist/conditions/not-armed-condition.js +6 -2
  12. package/dist/conditions/not-armed-condition.js.map +1 -1
  13. package/dist/conditions/trigger-already-running-condition.d.ts +10 -0
  14. package/dist/conditions/trigger-already-running-condition.js +19 -0
  15. package/dist/conditions/trigger-already-running-condition.js.map +1 -0
  16. package/dist/handlers/state-handler.d.ts +14 -9
  17. package/dist/handlers/state-handler.js +44 -75
  18. package/dist/handlers/state-handler.js.map +1 -1
  19. package/dist/handlers/switch-handler.d.ts +12 -5
  20. package/dist/handlers/switch-handler.js +17 -22
  21. package/dist/handlers/switch-handler.js.map +1 -1
  22. package/dist/handlers/trip-handler.d.ts +9 -11
  23. package/dist/handlers/trip-handler.js +34 -55
  24. package/dist/handlers/trip-handler.js.map +1 -1
  25. package/dist/homekit/homekit-registrar.d.ts +19 -0
  26. package/dist/homekit/homekit-registrar.js +134 -0
  27. package/dist/homekit/homekit-registrar.js.map +1 -0
  28. package/dist/homekit/service-factory.d.ts +9 -0
  29. package/dist/homekit/service-factory.js +117 -0
  30. package/dist/homekit/service-factory.js.map +1 -0
  31. package/dist/interfaces/condition-context-interface.d.ts +3 -0
  32. package/dist/interfaces/system-state-interface.d.ts +1 -7
  33. package/dist/security-system.d.ts +1 -5
  34. package/dist/security-system.js +39 -269
  35. package/dist/security-system.js.map +1 -1
  36. package/dist/services/configuration-service.d.ts +24 -0
  37. package/dist/services/configuration-service.js +187 -0
  38. package/dist/services/configuration-service.js.map +1 -0
  39. package/dist/services/server-service.js +1 -1
  40. package/dist/services/server-service.js.map +1 -1
  41. package/dist/tests/conditions.test.js +10 -13
  42. package/dist/tests/conditions.test.js.map +1 -1
  43. package/dist/tests/state-handler.test.js +21 -24
  44. package/dist/tests/state-handler.test.js.map +1 -1
  45. package/dist/tests/trip-handler.test.js +33 -24
  46. package/dist/tests/trip-handler.test.js.map +1 -1
  47. package/dist/timers/timer-manager.d.ts +34 -0
  48. package/dist/timers/timer-manager.js +132 -0
  49. package/dist/timers/timer-manager.js.map +1 -0
  50. package/dist/types/event-payload-map-type.d.ts +6 -1
  51. package/dist/types/event-type.d.ts +15 -1
  52. package/dist/types/event-type.js +8 -0
  53. package/dist/types/event-type.js.map +1 -1
  54. package/dist/utils/arming-util.d.ts +19 -0
  55. package/dist/utils/arming-util.js +24 -0
  56. package/dist/utils/arming-util.js.map +1 -0
  57. package/package.json +12 -12
  58. package/src/conditions/already-triggered-condition.ts +7 -3
  59. package/src/conditions/arming-in-progress-condition.ts +7 -3
  60. package/src/conditions/double-knock-condition.ts +11 -11
  61. package/src/conditions/not-armed-condition.ts +7 -3
  62. package/src/conditions/trigger-already-running-condition.ts +21 -0
  63. package/src/handlers/state-handler.ts +51 -85
  64. package/src/handlers/switch-handler.ts +21 -31
  65. package/src/handlers/trip-handler.ts +42 -66
  66. package/src/homekit/homekit-registrar.ts +147 -0
  67. package/src/homekit/service-factory.ts +139 -0
  68. package/src/interfaces/condition-context-interface.ts +3 -0
  69. package/src/interfaces/system-state-interface.ts +1 -9
  70. package/src/security-system.ts +44 -298
  71. package/src/services/configuration-service.ts +220 -0
  72. package/src/services/server-service.ts +1 -1
  73. package/src/tests/conditions.test.ts +11 -13
  74. package/src/tests/state-handler.test.ts +22 -24
  75. package/src/tests/trip-handler.test.ts +41 -26
  76. package/src/timers/timer-manager.ts +158 -0
  77. package/src/types/event-payload-map-type.ts +8 -0
  78. package/src/types/event-type.ts +22 -0
  79. package/src/utils/arming-util.ts +44 -0
  80. package/dist/utils/options-util.d.ts +0 -6
  81. package/dist/utils/options-util.js +0 -171
  82. package/dist/utils/options-util.js.map +0 -1
  83. package/src/utils/options-util.ts +0 -202
@@ -6,5 +6,5 @@ import { Condition } from './condition.js';
6
6
  */
7
7
  export declare class AlreadyTriggeredCondition extends Condition {
8
8
  readonly name = "already-triggered";
9
- evaluate({ state, value }: ConditionContext): boolean;
9
+ evaluate({ state, value, log }: ConditionContext): boolean;
10
10
  }
@@ -6,11 +6,15 @@ import { Condition } from './condition.js';
6
6
  */
7
7
  export class AlreadyTriggeredCondition extends Condition {
8
8
  name = 'already-triggered';
9
- evaluate({ state, value }) {
9
+ evaluate({ state, value, log }) {
10
10
  if (!value) {
11
11
  return false;
12
12
  }
13
- return state.currentState === SecurityState.TRIGGERED;
13
+ const blocked = state.currentState === SecurityState.TRIGGERED;
14
+ if (blocked) {
15
+ log.warn('Security System (Already triggered): alarm is already active');
16
+ }
17
+ return blocked;
14
18
  }
15
19
  }
16
20
  //# sourceMappingURL=already-triggered-condition.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"already-triggered-condition.js","sourceRoot":"","sources":["../../src/conditions/already-triggered-condition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAEhE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;;GAGG;AACH,MAAM,OAAO,yBAA0B,SAAQ,SAAS;IAC7C,IAAI,GAAG,mBAAmB,CAAC;IAEpC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAoB;QACzC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,KAAK,CAAC,YAAY,KAAK,aAAa,CAAC,SAAS,CAAC;IACxD,CAAC;CACF"}
1
+ {"version":3,"file":"already-triggered-condition.js","sourceRoot":"","sources":["../../src/conditions/already-triggered-condition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAEhE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;;GAGG;AACH,MAAM,OAAO,yBAA0B,SAAQ,SAAS;IAC7C,IAAI,GAAG,mBAAmB,CAAC;IAEpC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAoB;QAC9C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,YAAY,KAAK,aAAa,CAAC,SAAS,CAAC;QAC/D,IAAI,OAAO,EAAE,CAAC;YACZ,GAAG,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
@@ -6,5 +6,5 @@ import { Condition } from './condition.js';
6
6
  */
7
7
  export declare class ArmingInProgressCondition extends Condition {
8
8
  readonly name = "arming-in-progress";
9
- evaluate({ state, value }: ConditionContext): boolean;
9
+ evaluate({ state, value, log }: ConditionContext): boolean;
10
10
  }
@@ -5,11 +5,15 @@ import { Condition } from './condition.js';
5
5
  */
6
6
  export class ArmingInProgressCondition extends Condition {
7
7
  name = 'arming-in-progress';
8
- evaluate({ state, value }) {
8
+ evaluate({ state, value, log }) {
9
9
  if (!value) {
10
10
  return false;
11
11
  }
12
- return state.isArming;
12
+ if (state.isArming) {
13
+ log.warn('Trip Switch (Still arming): arm delay countdown is still in progress');
14
+ return true;
15
+ }
16
+ return false;
13
17
  }
14
18
  }
15
19
  //# sourceMappingURL=arming-in-progress-condition.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"arming-in-progress-condition.js","sourceRoot":"","sources":["../../src/conditions/arming-in-progress-condition.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;;GAGG;AACH,MAAM,OAAO,yBAA0B,SAAQ,SAAS;IAC7C,IAAI,GAAG,oBAAoB,CAAC;IAErC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAoB;QACzC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,KAAK,CAAC,QAAQ,CAAC;IACxB,CAAC;CACF"}
1
+ {"version":3,"file":"arming-in-progress-condition.js","sourceRoot":"","sources":["../../src/conditions/arming-in-progress-condition.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;;GAGG;AACH,MAAM,OAAO,yBAA0B,SAAQ,SAAS;IAC7C,IAAI,GAAG,oBAAoB,CAAC;IAErC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAoB;QAC9C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACnB,GAAG,CAAC,IAAI,CAAC,sEAAsE,CAAC,CAAC;YACjF,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
@@ -10,13 +10,15 @@ import { Condition } from './condition.js';
10
10
  */
11
11
  export declare class DoubleKnockCondition extends Condition {
12
12
  private readonly onFirstKnock;
13
+ private readonly onCancelTimer;
13
14
  readonly name = "double-knock";
14
15
  /**
15
16
  * @param onFirstKnock Called when the first knock is detected.
16
17
  * The callback receives the window duration in seconds and a reset function
17
18
  * to invoke when the window expires.
19
+ * @param onCancelTimer Called on the second knock to cancel the running window timer.
18
20
  */
19
- constructor(onFirstKnock: (seconds: number, onExpire: () => void) => void);
20
- evaluate({ state, options, value, origin }: ConditionContext): boolean;
21
+ constructor(onFirstKnock: (seconds: number, onExpire: () => void) => void, onCancelTimer: () => void);
22
+ evaluate({ state, options, value, origin, log }: ConditionContext): boolean;
21
23
  private resolveWindow;
22
24
  }
@@ -12,17 +12,20 @@ import { Condition } from './condition.js';
12
12
  */
13
13
  export class DoubleKnockCondition extends Condition {
14
14
  onFirstKnock;
15
+ onCancelTimer;
15
16
  name = 'double-knock';
16
17
  /**
17
18
  * @param onFirstKnock Called when the first knock is detected.
18
19
  * The callback receives the window duration in seconds and a reset function
19
20
  * to invoke when the window expires.
21
+ * @param onCancelTimer Called on the second knock to cancel the running window timer.
20
22
  */
21
- constructor(onFirstKnock) {
23
+ constructor(onFirstKnock, onCancelTimer) {
22
24
  super();
23
25
  this.onFirstKnock = onFirstKnock;
26
+ this.onCancelTimer = onCancelTimer;
24
27
  }
25
- evaluate({ state, options, value, origin }) {
28
+ evaluate({ state, options, value, origin, log }) {
26
29
  if (!value || !options.doubleKnock) {
27
30
  return false;
28
31
  }
@@ -37,12 +40,9 @@ export class DoubleKnockCondition extends Condition {
37
40
  return false;
38
41
  }
39
42
  if (state.isKnocked) {
40
- // Second knock — clear the flag and allow through.
43
+ // Second knock — clear the flag and cancel the window timer, then allow through.
41
44
  state.isKnocked = false;
42
- if (state.doubleKnockTimeout !== null) {
43
- clearTimeout(state.doubleKnockTimeout);
44
- state.doubleKnockTimeout = null;
45
- }
45
+ this.onCancelTimer();
46
46
  return false;
47
47
  }
48
48
  // First knock — block and schedule expiry.
@@ -50,8 +50,9 @@ export class DoubleKnockCondition extends Condition {
50
50
  const seconds = this.resolveWindow(state.currentState, options);
51
51
  this.onFirstKnock(seconds, () => {
52
52
  state.isKnocked = false;
53
- state.doubleKnockTimeout = null;
53
+ log.info('Trip Switch (Reset): double-knock window expired without second activation');
54
54
  });
55
+ log.warn('Trip Switch (Knock): double-knock is required, waiting for second activation');
55
56
  return true;
56
57
  }
57
58
  resolveWindow(currentState, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"double-knock-condition.js","sourceRoot":"","sources":["../../src/conditions/double-knock-condition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;;;;;;GAOG;AACH,MAAM,OAAO,oBAAqB,SAAQ,SAAS;IAS9B;IARV,IAAI,GAAG,cAAc,CAAC;IAE/B;;;;OAIG;IACH,YACmB,YAA6D;QAE9E,KAAK,EAAE,CAAC;QAFS,iBAAY,GAAZ,YAAY,CAAiD;IAGhF,CAAC;IAED,QAAQ,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAoB;QAC1D,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;YACnC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,MAAM,KAAK,UAAU,CAAC,eAAe,EAAE,CAAC;YAC1C,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACnB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QACxF,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;YAClD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YACpB,mDAAmD;YACnD,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC;YACxB,IAAI,KAAK,CAAC,kBAAkB,KAAK,IAAI,EAAE,CAAC;gBACtC,YAAY,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;gBACvC,KAAK,CAAC,kBAAkB,GAAG,IAAI,CAAC;YAClC,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,2CAA2C;QAC3C,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAEhE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,EAAE;YAC9B,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC;YACxB,KAAK,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,aAAa,CACnB,YAA2B,EAC3B,OAAoC;QAEpC,IAAI,YAAY,KAAK,aAAa,CAAC,IAAI,IAAI,OAAO,CAAC,sBAAsB,KAAK,IAAI,EAAE,CAAC;YACnF,OAAO,OAAO,CAAC,sBAAsB,CAAC;QACxC,CAAC;QACD,IAAI,YAAY,KAAK,aAAa,CAAC,IAAI,IAAI,OAAO,CAAC,sBAAsB,KAAK,IAAI,EAAE,CAAC;YACnF,OAAO,OAAO,CAAC,sBAAsB,CAAC;QACxC,CAAC;QACD,IAAI,YAAY,KAAK,aAAa,CAAC,KAAK,IAAI,OAAO,CAAC,uBAAuB,KAAK,IAAI,EAAE,CAAC;YACrF,OAAO,OAAO,CAAC,uBAAuB,CAAC;QACzC,CAAC;QACD,OAAO,OAAO,CAAC,kBAAkB,CAAC;IACpC,CAAC;CACF"}
1
+ {"version":3,"file":"double-knock-condition.js","sourceRoot":"","sources":["../../src/conditions/double-knock-condition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;;;;;;GAOG;AACH,MAAM,OAAO,oBAAqB,SAAQ,SAAS;IAU9B;IACA;IAVV,IAAI,GAAG,cAAc,CAAC;IAE/B;;;;;OAKG;IACH,YACmB,YAA6D,EAC7D,aAAyB;QAE1C,KAAK,EAAE,CAAC;QAHS,iBAAY,GAAZ,YAAY,CAAiD;QAC7D,kBAAa,GAAb,aAAa,CAAY;IAG5C,CAAC;IAED,QAAQ,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAoB;QAC/D,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;YACnC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,MAAM,KAAK,UAAU,CAAC,eAAe,EAAE,CAAC;YAC1C,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACnB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QACxF,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;YAClD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YACpB,iFAAiF;YACjF,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC;YACxB,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,2CAA2C;QAC3C,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAEhE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,EAAE;YAC9B,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC;YACxB,GAAG,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;QACzF,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,IAAI,CAAC,8EAA8E,CAAC,CAAC;QACzF,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,aAAa,CACnB,YAA2B,EAC3B,OAAoC;QAEpC,IAAI,YAAY,KAAK,aAAa,CAAC,IAAI,IAAI,OAAO,CAAC,sBAAsB,KAAK,IAAI,EAAE,CAAC;YACnF,OAAO,OAAO,CAAC,sBAAsB,CAAC;QACxC,CAAC;QACD,IAAI,YAAY,KAAK,aAAa,CAAC,IAAI,IAAI,OAAO,CAAC,sBAAsB,KAAK,IAAI,EAAE,CAAC;YACnF,OAAO,OAAO,CAAC,sBAAsB,CAAC;QACxC,CAAC;QACD,IAAI,YAAY,KAAK,aAAa,CAAC,KAAK,IAAI,OAAO,CAAC,uBAAuB,KAAK,IAAI,EAAE,CAAC;YACrF,OAAO,OAAO,CAAC,uBAAuB,CAAC;QACzC,CAAC;QACD,OAAO,OAAO,CAAC,kBAAkB,CAAC;IACpC,CAAC;CACF"}
@@ -6,5 +6,5 @@ import { Condition } from './condition.js';
6
6
  */
7
7
  export declare class NotArmedCondition extends Condition {
8
8
  readonly name = "not-armed";
9
- evaluate({ state, options, value, origin }: ConditionContext): boolean;
9
+ evaluate({ state, options, value, origin, log }: ConditionContext): boolean;
10
10
  }
@@ -7,14 +7,18 @@ import { Condition } from './condition.js';
7
7
  */
8
8
  export class NotArmedCondition extends Condition {
9
9
  name = 'not-armed';
10
- evaluate({ state, options, value, origin }) {
10
+ evaluate({ state, options, value, origin, log }) {
11
11
  if (!value) {
12
12
  return false;
13
13
  }
14
14
  const isDisarmed = state.currentState === SecurityState.OFF;
15
15
  const isNotOverridingOff = !options.overrideOff;
16
16
  const isNotOverrideSwitch = origin !== OriginType.OVERRIDE_SWITCH;
17
- return isDisarmed && isNotOverridingOff && isNotOverrideSwitch;
17
+ const blocked = isDisarmed && isNotOverridingOff && isNotOverrideSwitch;
18
+ if (blocked) {
19
+ log.warn('Trip Switch (Not armed): system is disarmed and override is not enabled');
20
+ }
21
+ return blocked;
18
22
  }
19
23
  }
20
24
  //# sourceMappingURL=not-armed-condition.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"not-armed-condition.js","sourceRoot":"","sources":["../../src/conditions/not-armed-condition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;;GAGG;AACH,MAAM,OAAO,iBAAkB,SAAQ,SAAS;IACrC,IAAI,GAAG,WAAW,CAAC;IAE5B,QAAQ,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAoB;QAC1D,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,YAAY,KAAK,aAAa,CAAC,GAAG,CAAC;QAC5D,MAAM,kBAAkB,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC;QAChD,MAAM,mBAAmB,GAAG,MAAM,KAAK,UAAU,CAAC,eAAe,CAAC;QAElE,OAAO,UAAU,IAAI,kBAAkB,IAAI,mBAAmB,CAAC;IACjE,CAAC;CACF"}
1
+ {"version":3,"file":"not-armed-condition.js","sourceRoot":"","sources":["../../src/conditions/not-armed-condition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;;GAGG;AACH,MAAM,OAAO,iBAAkB,SAAQ,SAAS;IACrC,IAAI,GAAG,WAAW,CAAC;IAE5B,QAAQ,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAoB;QAC/D,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,YAAY,KAAK,aAAa,CAAC,GAAG,CAAC;QAC5D,MAAM,kBAAkB,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC;QAChD,MAAM,mBAAmB,GAAG,MAAM,KAAK,UAAU,CAAC,eAAe,CAAC;QAElE,MAAM,OAAO,GAAG,UAAU,IAAI,kBAAkB,IAAI,mBAAmB,CAAC;QACxE,IAAI,OAAO,EAAE,CAAC;YACZ,GAAG,CAAC,IAAI,CAAC,yEAAyE,CAAC,CAAC;QACtF,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ import type { ConditionContext } from '../interfaces/condition-context-interface.js';
2
+ import { Condition } from './condition.js';
3
+ /**
4
+ * Blocks a trip activation when the trigger-delay countdown is already running.
5
+ * Prevents stacking multiple trigger events during the pre-alarm window.
6
+ */
7
+ export declare class TriggerAlreadyRunningCondition extends Condition {
8
+ readonly name = "trigger-already-running";
9
+ evaluate({ state, value, log }: ConditionContext): boolean;
10
+ }
@@ -0,0 +1,19 @@
1
+ import { Condition } from './condition.js';
2
+ /**
3
+ * Blocks a trip activation when the trigger-delay countdown is already running.
4
+ * Prevents stacking multiple trigger events during the pre-alarm window.
5
+ */
6
+ export class TriggerAlreadyRunningCondition extends Condition {
7
+ name = 'trigger-already-running';
8
+ evaluate({ state, value, log }) {
9
+ if (!value) {
10
+ return false;
11
+ }
12
+ if (state.isTripping) {
13
+ log.warn('Security System (Already tripped): trigger delay countdown is already running');
14
+ return true;
15
+ }
16
+ return false;
17
+ }
18
+ }
19
+ //# sourceMappingURL=trigger-already-running-condition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trigger-already-running-condition.js","sourceRoot":"","sources":["../../src/conditions/trigger-already-running-condition.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;;GAGG;AACH,MAAM,OAAO,8BAA+B,SAAQ,SAAS;IAClD,IAAI,GAAG,yBAAyB,CAAC;IAE1C,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAoB;QAC9C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YACrB,GAAG,CAAC,IAAI,CAAC,+EAA+E,CAAC,CAAC;YAC1F,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
@@ -8,10 +8,13 @@ import type { SecuritySystemOptions } from '../interfaces/options-interface.js';
8
8
  import type { EventBusService } from '../services/event-bus-service.js';
9
9
  import type { StorageService } from '../services/storage-service.js';
10
10
  import type { AudioService } from '../services/audio-service.js';
11
- import type { TripHandler } from './trip-handler.js';
12
- import type { SwitchHandler } from './switch-handler.js';
13
11
  import type { SensorHandler } from './sensor-handler.js';
14
- /** Manages the core security-system state machine: arming, triggering, and resetting. */
12
+ import type { TimerManager } from '../timers/timer-manager.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
+ */
15
18
  export declare class StateHandler {
16
19
  private readonly services;
17
20
  private readonly state;
@@ -21,15 +24,17 @@ export declare class StateHandler {
21
24
  private readonly bus;
22
25
  private readonly storageService;
23
26
  private readonly audio;
24
- private tripHandler;
25
- private switchHandler;
26
- private sensorHandler;
27
- constructor(services: ServiceRegistry, state: SystemState, options: SecuritySystemOptions, Characteristic: CharacteristicConstructor, log: Logging, bus: EventBusService, storageService: StorageService, audio: AudioService);
28
- setHandlers(trip: TripHandler, sw: SwitchHandler, sensor: SensorHandler): void;
27
+ private readonly timers;
28
+ private readonly sensorHandler;
29
+ constructor(services: ServiceRegistry, state: SystemState, options: SecuritySystemOptions, Characteristic: CharacteristicConstructor, log: Logging, bus: EventBusService, storageService: StorageService, audio: AudioService, timers: TimerManager, sensorHandler: SensorHandler);
29
30
  setCurrentState(state: SecurityState, origin: OriginType): void;
30
31
  updateTargetState(state: SecurityState, origin: OriginType, delay: number): boolean;
31
- getArmingSeconds(state: SecurityState): number;
32
+ getArmingSeconds(targetState: SecurityState): number;
32
33
  resetTimers(): void;
34
+ /** Returns true while the trigger delay is counting down (trip switch is active). */
35
+ isTripping(): boolean;
36
+ /** Checks whether arming is currently blocked by an arming-lock switch. */
37
+ isArmingLocked(targetState: SecurityState): boolean;
33
38
  getAvailableTargetStates(): SecurityState[];
34
39
  logMode(type: string, state: SecurityState | string): void;
35
40
  private isBadTargetState;
@@ -3,7 +3,12 @@ import { OriginType } from '../types/origin-type.js';
3
3
  import { stateToMode, capitalise } from '../utils/state-util.js';
4
4
  import { modeToState } from '../utils/state-util.js';
5
5
  import { EventType } from '../types/event-type.js';
6
- /** Manages the core security-system state machine: arming, triggering, and resetting. */
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
+ */
7
12
  export class StateHandler {
8
13
  services;
9
14
  state;
@@ -13,10 +18,9 @@ export class StateHandler {
13
18
  bus;
14
19
  storageService;
15
20
  audio;
16
- tripHandler;
17
- switchHandler;
21
+ timers;
18
22
  sensorHandler;
19
- constructor(services, state, options, Characteristic, log, bus, storageService, audio) {
23
+ constructor(services, state, options, Characteristic, log, bus, storageService, audio, timers, sensorHandler) {
20
24
  this.services = services;
21
25
  this.state = state;
22
26
  this.options = options;
@@ -25,11 +29,8 @@ export class StateHandler {
25
29
  this.bus = bus;
26
30
  this.storageService = storageService;
27
31
  this.audio = audio;
28
- }
29
- setHandlers(trip, sw, sensor) {
30
- this.tripHandler = trip;
31
- this.switchHandler = sw;
32
- this.sensorHandler = sensor;
32
+ this.timers = timers;
33
+ this.sensorHandler = sensorHandler;
33
34
  }
34
35
  // ── Public API ─────────────────────────────────────────────────────────────
35
36
  setCurrentState(state, origin) {
@@ -67,66 +68,36 @@ export class StateHandler {
67
68
  this.state.isArming = true;
68
69
  this.handleArmingState();
69
70
  this.log.info(`Arm delay (${armSeconds}s)`);
70
- this.state.armTimeout = setTimeout(() => {
71
- this.state.armTimeout = null;
71
+ this.timers.setArmTimer(armSeconds * 1000, () => {
72
72
  this.state.isArming = false;
73
73
  this.setCurrentState(state, origin);
74
- }, armSeconds * 1000);
74
+ });
75
75
  return true;
76
76
  }
77
- getArmingSeconds(state) {
78
- const isTriggered = this.state.currentState === SecurityState.TRIGGERED;
79
- const isOff = state === SecurityState.OFF;
80
- if (isTriggered || isOff) {
81
- return 0;
82
- }
83
- if (state === SecurityState.HOME && this.options.homeArmSeconds !== null) {
84
- return this.options.homeArmSeconds;
85
- }
86
- if (state === SecurityState.AWAY && this.options.awayArmSeconds !== null) {
87
- return this.options.awayArmSeconds;
88
- }
89
- if (state === SecurityState.NIGHT && this.options.nightArmSeconds !== null) {
90
- return this.options.nightArmSeconds;
91
- }
92
- return this.options.armSeconds;
77
+ getArmingSeconds(targetState) {
78
+ return getArmingSeconds(this.state, this.options, targetState);
93
79
  }
94
80
  resetTimers() {
95
- if (this.state.triggerTimeout) {
96
- clearTimeout(this.state.triggerTimeout);
97
- this.state.triggerTimeout = null;
98
- this.log.debug('Trigger timeout (Cleared)');
99
- }
100
- if (this.state.armTimeout) {
101
- clearTimeout(this.state.armTimeout);
102
- this.state.armTimeout = null;
103
- this.log.debug('Arming timeout (Cleared)');
104
- }
105
- if (this.state.triggeredMotionSensorInterval) {
106
- clearInterval(this.state.triggeredMotionSensorInterval);
107
- this.state.triggeredMotionSensorInterval = null;
108
- this.log.debug('Triggered interval (Cleared)');
109
- }
110
- if (this.state.trippedMotionSensorInterval) {
111
- clearInterval(this.state.trippedMotionSensorInterval);
112
- this.state.trippedMotionSensorInterval = null;
113
- this.log.debug('Tripped interval (Cleared)');
114
- }
115
- if (this.state.doubleKnockTimeout) {
116
- clearTimeout(this.state.doubleKnockTimeout);
117
- this.state.doubleKnockTimeout = null;
118
- this.log.debug('Double-knock timeout (Cleared)');
119
- }
120
- if (this.state.pauseTimeout) {
121
- clearTimeout(this.state.pauseTimeout);
122
- this.state.pauseTimeout = null;
123
- this.log.debug('Pause timeout (Cleared)');
124
- }
125
- if (this.state.resetTimeout) {
126
- clearTimeout(this.state.resetTimeout);
127
- this.state.resetTimeout = null;
128
- this.log.debug('Reset timeout (Cleared)');
81
+ this.timers.clearAll();
82
+ }
83
+ /** Returns true while the trigger delay is counting down (trip switch is active). */
84
+ isTripping() {
85
+ return this.state.isTripping;
86
+ }
87
+ /** Checks whether arming is currently blocked by an arming-lock switch. */
88
+ isArmingLocked(targetState) {
89
+ if (this.services.armingLockSwitchService.getCharacteristic(this.Characteristic.On).value) {
90
+ return true;
129
91
  }
92
+ const modeMap = {
93
+ [SecurityState.HOME]: 'armingLockHomeSwitchService',
94
+ [SecurityState.AWAY]: 'armingLockAwaySwitchService',
95
+ [SecurityState.NIGHT]: 'armingLockNightSwitchService',
96
+ };
97
+ const svcKey = modeMap[targetState];
98
+ return svcKey
99
+ ? Boolean(this.services[svcKey].getCharacteristic(this.Characteristic.On).value)
100
+ : false;
130
101
  }
131
102
  getAvailableTargetStates() {
132
103
  const all = [SecurityState.HOME, SecurityState.AWAY, SecurityState.NIGHT, SecurityState.OFF];
@@ -150,7 +121,7 @@ export class StateHandler {
150
121
  return true;
151
122
  }
152
123
  const hasLock = this.options.armingLockSwitch || this.options.armingLockSwitches;
153
- if (state !== SecurityState.OFF && hasLock && this.switchHandler.isArmingLocked(state)) {
124
+ if (state !== SecurityState.OFF && hasLock && this.isArmingLocked(state)) {
154
125
  this.log.warn('Arming lock (Not allowed)');
155
126
  return true;
156
127
  }
@@ -158,10 +129,11 @@ export class StateHandler {
158
129
  }
159
130
  handleTargetStateChange(origin) {
160
131
  this.resetTimers();
161
- this.tripHandler.resetTripSwitches();
132
+ // Notify handlers to reset their displayed state (bus is synchronous).
133
+ this.bus.emit(EventType.RESET_TRIP_SWITCHES, {});
162
134
  this.sensorHandler.resetTrippedMotionSensor();
163
- this.switchHandler.resetModeSwitches();
164
- this.switchHandler.updateModeSwitches();
135
+ this.bus.emit(EventType.RESET_MODE_SWITCHES, {});
136
+ this.bus.emit(EventType.UPDATE_MODE_SWITCHES, {});
165
137
  this.bus.emit(EventType.TARGET_CHANGED, { state: this.state.targetState, origin });
166
138
  if (this.state.currentState === SecurityState.TRIGGERED) {
167
139
  this.sensorHandler.pulseResetMotionSensor();
@@ -175,19 +147,16 @@ export class StateHandler {
175
147
  return;
176
148
  }
177
149
  }
178
- this.tripHandler.resetTripSwitches();
150
+ // Notify TripHandler to reset trip switches on any state change.
151
+ this.bus.emit(EventType.RESET_TRIP_SWITCHES, {});
179
152
  this.bus.emit(EventType.CURRENT_CHANGED, { state: this.state.currentState, origin });
180
153
  }
181
154
  handleTriggeredState() {
182
- if (this.state.trippedMotionSensorInterval) {
183
- clearInterval(this.state.trippedMotionSensorInterval);
184
- this.state.trippedMotionSensorInterval = null;
185
- }
155
+ this.timers.clearTrippedInterval();
186
156
  if (this.options.triggeredMotionSensor) {
187
- this.state.triggeredMotionSensorInterval = setInterval(() => this.sensorHandler.pulseTriggeredMotionSensor(), this.options.triggeredMotionSensorSeconds * 1000);
157
+ this.timers.setTriggeredInterval(this.options.triggeredMotionSensorSeconds * 1000, () => this.sensorHandler.pulseTriggeredMotionSensor());
188
158
  }
189
- this.state.resetTimeout = setTimeout(() => {
190
- this.state.resetTimeout = null;
159
+ this.timers.setResetTimer(this.options.resetMinutes * 60 * 1000, () => {
191
160
  this.log.info('Reset (Finished)');
192
161
  this.sensorHandler.pulseResetMotionSensor();
193
162
  if (this.options.resetOffFlow) {
@@ -196,7 +165,7 @@ export class StateHandler {
196
165
  else {
197
166
  this.setCurrentState(this.state.targetState, OriginType.EXTERNAL);
198
167
  }
199
- }, this.options.resetMinutes * 60 * 1000);
168
+ });
200
169
  }
201
170
  handleArmingState() {
202
171
  this.sensorHandler.updateArmingMotionSensor(true);
@@ -1 +1 @@
1
- {"version":3,"file":"state-handler.js","sourceRoot":"","sources":["../../src/handlers/state-handler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAKrD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAOnD,yFAAyF;AACzF,MAAM,OAAO,YAAY;IAMJ;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IAZX,WAAW,CAAe;IAC1B,aAAa,CAAiB;IAC9B,aAAa,CAAiB;IAEtC,YACmB,QAAyB,EACzB,KAAkB,EAClB,OAA8B,EAC9B,cAAyC,EACzC,GAAY,EACZ,GAAoB,EACpB,cAA8B,EAC9B,KAAmB;QAPnB,aAAQ,GAAR,QAAQ,CAAiB;QACzB,UAAK,GAAL,KAAK,CAAa;QAClB,YAAO,GAAP,OAAO,CAAuB;QAC9B,mBAAc,GAAd,cAAc,CAA2B;QACzC,QAAG,GAAH,GAAG,CAAS;QACZ,QAAG,GAAH,GAAG,CAAiB;QACpB,mBAAc,GAAd,cAAc,CAAgB;QAC9B,UAAK,GAAL,KAAK,CAAc;IACnC,CAAC;IAEJ,WAAW,CAAC,IAAiB,EAAE,EAAiB,EAAE,MAAqB;QACrE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC;IAC9B,CAAC;IAED,8EAA8E;IAE9E,eAAe,CAAC,KAAoB,EAAE,MAAkB;QACtD,IAAI,CAAC,aAAa,CAAC,uBAAuB,EAAE,CAAC;QAC7C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAElC,IAAI,IAAI,CAAC,KAAK,CAAC,YAAY,KAAK,KAAK,EAAE,CAAC;YACtC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;YAC5C,OAAO;QACT,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC;QAChC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,iBAAiB,CACzC,IAAI,CAAC,cAAc,CAAC,0BAA0B,EAC9C,KAAK,CACN,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAE/B,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IAED,iBAAiB,CAAC,KAAoB,EAAE,MAAkB,EAAE,KAAa;QACvE,IAAI,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;YACjC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC;QAC/B,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAE9B,IAAI,MAAM,KAAK,UAAU,CAAC,QAAQ,IAAI,MAAM,KAAK,UAAU,CAAC,QAAQ,EAAE,CAAC;YACrE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,oBAAoB,CAC5C,IAAI,CAAC,cAAc,CAAC,yBAAyB,EAC7C,KAAK,CACN,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;QAErC,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;YACtC,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YACpC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAEzC,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;YACrB,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YACpC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,UAAU,IAAI,CAAC,CAAC;QAE5C,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,UAAU,CAAC,GAAG,EAAE;YACtC,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;YAC7B,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC;YAC5B,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC,CAAC;QAEtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gBAAgB,CAAC,KAAoB;QACnC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,KAAK,aAAa,CAAC,SAAS,CAAC;QACxE,MAAM,KAAK,GAAG,KAAK,KAAK,aAAa,CAAC,GAAG,CAAC;QAE1C,IAAI,WAAW,IAAI,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,IAAI,KAAK,KAAK,aAAa,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC;YACzE,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC;QACrC,CAAC;QACD,IAAI,KAAK,KAAK,aAAa,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC;YACzE,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC;QACrC,CAAC;QACD,IAAI,KAAK,KAAK,aAAa,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;YAC3E,OAAO,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC;QACtC,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;IACjC,CAAC;IAED,WAAW;QACT,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;YAC9B,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YACxC,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC;YACjC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;YAC1B,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACpC,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;YAC7B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,6BAA6B,EAAE,CAAC;YAC7C,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;YACxD,IAAI,CAAC,KAAK,CAAC,6BAA6B,GAAG,IAAI,CAAC;YAChD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QACjD,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,2BAA2B,EAAE,CAAC;YAC3C,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;YACtD,IAAI,CAAC,KAAK,CAAC,2BAA2B,GAAG,IAAI,CAAC;YAC9C,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,kBAAkB,EAAE,CAAC;YAClC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;YAC5C,IAAI,CAAC,KAAK,CAAC,kBAAkB,GAAG,IAAI,CAAC;YACrC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACnD,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;YAC5B,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YACtC,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;YAC/B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC5C,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;YAC5B,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YACtC,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;YAC/B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,wBAAwB;QACtB,MAAM,GAAG,GAAG,CAAC,aAAa,CAAC,IAAI,EAAE,aAAa,CAAC,IAAI,EAAE,aAAa,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;QAC7F,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QACnF,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,OAAO,CAAC,IAAY,EAAE,KAA6B;QACjD,MAAM,IAAI,GAAG,UAAU,CAAC,WAAW,CAAC,KAAsB,CAAC,CAAC,CAAC;QAC7D,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,UAAU,IAAI,GAAG,CAAC,CAAC;IAC1C,CAAC;IAED,8EAA8E;IAEtE,gBAAgB,CAAC,KAAoB;QAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,KAAK,aAAa,CAAC,SAAS,CAAC;QACxE,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,KAAK,KAAK,CAAC;QAEpD,IAAI,UAAU,IAAI,CAAC,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;YAC3C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACtD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;YACxC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,IAAI,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC;QACjF,IAAI,KAAK,KAAK,aAAa,CAAC,GAAG,IAAI,OAAO,IAAI,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;YACvF,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;YAC3C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,uBAAuB,CAAC,MAAkB;QAChD,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,WAAW,CAAC,iBAAiB,EAAE,CAAC;QACrC,IAAI,CAAC,aAAa,CAAC,wBAAwB,EAAE,CAAC;QAC9C,IAAI,CAAC,aAAa,CAAC,iBAAiB,EAAE,CAAC;QACvC,IAAI,CAAC,aAAa,CAAC,kBAAkB,EAAE,CAAC;QAExC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;QAEnF,IAAI,IAAI,CAAC,KAAK,CAAC,YAAY,KAAK,aAAa,CAAC,SAAS,EAAE,CAAC;YACxD,IAAI,CAAC,aAAa,CAAC,sBAAsB,EAAE,CAAC;QAC9C,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC;IAC/B,CAAC;IAEO,wBAAwB,CAAC,MAAkB;QACjD,IAAI,IAAI,CAAC,KAAK,CAAC,YAAY,KAAK,aAAa,CAAC,SAAS,EAAE,CAAC;YACxD,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAE5B,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;gBAC1B,OAAO;YACT,CAAC;QACH,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,iBAAiB,EAAE,CAAC;QACrC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC;IACvF,CAAC;IAEO,oBAAoB;QAC1B,IAAI,IAAI,CAAC,KAAK,CAAC,2BAA2B,EAAE,CAAC;YAC3C,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;YACtD,IAAI,CAAC,KAAK,CAAC,2BAA2B,GAAG,IAAI,CAAC;QAChD,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC;YACvC,IAAI,CAAC,KAAK,CAAC,6BAA6B,GAAG,WAAW,CACpD,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,0BAA0B,EAAE,EACrD,IAAI,CAAC,OAAO,CAAC,4BAA4B,GAAG,IAAI,CACjD,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,UAAU,CAAC,GAAG,EAAE;YACxC,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;YAC/B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YAClC,IAAI,CAAC,aAAa,CAAC,sBAAsB,EAAE,CAAC;YAE5C,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;gBAC9B,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;YACpE,CAAC;QACH,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAC5C,CAAC;IAEO,iBAAiB;QACvB,IAAI,CAAC,aAAa,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IACrE,CAAC;IAEO,eAAe;QACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;QACxC,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,GAAG,EAAE,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAElE,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzF,CAAC,EAAE,GAAG,CAAC,CAAC;IACV,CAAC;CACF"}
1
+ {"version":3,"file":"state-handler.js","sourceRoot":"","sources":["../../src/handlers/state-handler.ts"],"names":[],"mappings":"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"}
@@ -5,22 +5,29 @@ import type { ServiceRegistry } from '../interfaces/service-registry-interface.j
5
5
  import type { SystemState } from '../interfaces/system-state-interface.js';
6
6
  import type { SecuritySystemOptions } from '../interfaces/options-interface.js';
7
7
  import type { StateHandler } from './state-handler.js';
8
- /** Handles all mode switches, arming-lock switches, and the pause/extended switches. */
8
+ import type { TimerManager } from '../timers/timer-manager.js';
9
+ import type { EventBusService } from '../services/event-bus-service.js';
10
+ /**
11
+ * Handles all mode switches and the pause/extended switches.
12
+ * Calls StateHandler directly (one-way dependency — no cycle).
13
+ * Subscribes to bus events emitted by StateHandler to reset its own display state.
14
+ */
9
15
  export declare class SwitchHandler {
10
16
  private readonly services;
11
17
  private readonly state;
12
18
  private readonly options;
13
19
  private readonly Characteristic;
14
20
  private readonly log;
15
- private stateHandler;
16
- constructor(services: ServiceRegistry, state: SystemState, options: SecuritySystemOptions, Characteristic: CharacteristicConstructor, log: Logging);
17
- setStateHandler(handler: StateHandler): void;
21
+ private readonly timers;
22
+ private readonly stateHandler;
23
+ constructor(services: ServiceRegistry, state: SystemState, options: SecuritySystemOptions, Characteristic: CharacteristicConstructor, log: Logging, timers: TimerManager, stateHandler: StateHandler);
24
+ /** Register bus listeners so StateHandler can signal display resets without importing this class. */
25
+ subscribeToStateEvents(bus: EventBusService): void;
18
26
  setModeSwitch(mode: SecurityState, value: boolean): number | null;
19
27
  setModeOffSwitch(value: boolean): number | null;
20
28
  setModeAwayExtendedSwitch(value: boolean): number | null;
21
29
  setModePauseSwitch(value: boolean): number | null;
22
30
  updateArmingLock(mode: string, value: boolean): boolean;
23
- isArmingLocked(targetState: SecurityState): boolean;
24
31
  resetModeSwitches(): void;
25
32
  updateModeSwitches(): void;
26
33
  private logArmingLock;
@@ -2,23 +2,33 @@ import { SecurityState } from '../types/security-state-type.js';
2
2
  import { HK_NOT_ALLOWED_IN_CURRENT_STATE } from '../constants/homekit-constant.js';
3
3
  import { OriginType } from '../types/origin-type.js';
4
4
  import { capitalise } from '../utils/state-util.js';
5
- /** Handles all mode switches, arming-lock switches, and the pause/extended switches. */
5
+ import { EventType } from '../types/event-type.js';
6
+ /**
7
+ * Handles all mode switches and the pause/extended switches.
8
+ * Calls StateHandler directly (one-way dependency — no cycle).
9
+ * Subscribes to bus events emitted by StateHandler to reset its own display state.
10
+ */
6
11
  export class SwitchHandler {
7
12
  services;
8
13
  state;
9
14
  options;
10
15
  Characteristic;
11
16
  log;
17
+ timers;
12
18
  stateHandler;
13
- constructor(services, state, options, Characteristic, log) {
19
+ constructor(services, state, options, Characteristic, log, timers, stateHandler) {
14
20
  this.services = services;
15
21
  this.state = state;
16
22
  this.options = options;
17
23
  this.Characteristic = Characteristic;
18
24
  this.log = log;
25
+ this.timers = timers;
26
+ this.stateHandler = stateHandler;
19
27
  }
20
- setStateHandler(handler) {
21
- this.stateHandler = handler;
28
+ /** Register bus listeners so StateHandler can signal display resets without importing this class. */
29
+ subscribeToStateEvents(bus) {
30
+ bus.on(EventType.RESET_MODE_SWITCHES, () => this.resetModeSwitches());
31
+ bus.on(EventType.UPDATE_MODE_SWITCHES, () => this.updateModeSwitches());
22
32
  }
23
33
  // ── Mode switches ──────────────────────────────────────────────────────────
24
34
  setModeSwitch(mode, value) {
@@ -58,19 +68,16 @@ export class SwitchHandler {
58
68
  this.state.pausedCurrentState = this.state.currentState;
59
69
  this.stateHandler.updateTargetState(SecurityState.OFF, OriginType.INTERNAL, 0);
60
70
  if (this.options.pauseMinutes !== 0) {
61
- this.state.pauseTimeout = setTimeout(() => {
71
+ this.timers.setPauseTimer(this.options.pauseMinutes * 60 * 1000, () => {
62
72
  this.log.info('Mode pause (Finished)');
63
73
  const prev = this.state.pausedCurrentState ?? this.state.defaultState;
64
74
  this.stateHandler.updateTargetState(prev, OriginType.INTERNAL, this.stateHandler.getArmingSeconds(prev));
65
- }, this.options.pauseMinutes * 60 * 1000);
75
+ });
66
76
  }
67
77
  }
68
78
  else {
69
79
  this.log.info('Mode pause (Cancelled)');
70
- if (this.state.pauseTimeout !== null) {
71
- clearTimeout(this.state.pauseTimeout);
72
- this.state.pauseTimeout = null;
73
- }
80
+ this.timers.clearPauseTimer();
74
81
  const prev = this.state.pausedCurrentState ?? this.state.defaultState;
75
82
  this.stateHandler.updateTargetState(prev, OriginType.INTERNAL, this.stateHandler.getArmingSeconds(prev));
76
83
  }
@@ -93,18 +100,6 @@ export class SwitchHandler {
93
100
  this.services[key].getCharacteristic(this.Characteristic.On).updateValue(value);
94
101
  return true;
95
102
  }
96
- isArmingLocked(targetState) {
97
- if (this.services.armingLockSwitchService.getCharacteristic(this.Characteristic.On).value) {
98
- return true;
99
- }
100
- const modeMap = {
101
- [SecurityState.HOME]: 'armingLockHomeSwitchService',
102
- [SecurityState.AWAY]: 'armingLockAwaySwitchService',
103
- [SecurityState.NIGHT]: 'armingLockNightSwitchService',
104
- };
105
- const svcKey = modeMap[targetState];
106
- return svcKey ? Boolean(this.services[svcKey].getCharacteristic(this.Characteristic.On).value) : false;
107
- }
108
103
  // ── Mode switch display ────────────────────────────────────────────────────
109
104
  resetModeSwitches() {
110
105
  const switches = [