homebridge-securitysystem 12.0.0 → 13.0.0

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 (205) hide show
  1. package/.github/workflows/bump-version.yml +1 -1
  2. package/.gitignore +127 -0
  3. package/AGENTS.md +7 -7
  4. package/CHANGELOG.md +30 -0
  5. package/config.schema.json +1 -145
  6. package/package.json +1 -1
  7. package/src/constants/default-constant.ts +0 -3
  8. package/src/constants/switch-uuid-constant.ts +0 -2
  9. package/src/handlers/sensor-handler.ts +0 -22
  10. package/src/handlers/state-handler.ts +0 -17
  11. package/src/handlers/trip-handler.ts +0 -3
  12. package/src/homekit/homekit-registrar.ts +1 -6
  13. package/src/homekit/service-factory.ts +0 -11
  14. package/src/interfaces/options-interface.ts +0 -19
  15. package/src/interfaces/service-registry-interface.ts +0 -4
  16. package/src/interfaces/system-state-interface.ts +0 -2
  17. package/src/security-system.ts +2 -14
  18. package/src/services/configuration-service.ts +0 -33
  19. package/src/services/event-bus-service.ts +1 -1
  20. package/src/tests/conditions.test.ts +0 -1
  21. package/src/tests/mqtt-service.test.ts +0 -1
  22. package/src/tests/server-service.test.ts +0 -1
  23. package/src/tests/state-handler.test.ts +14 -65
  24. package/src/tests/switch-handler.test.ts +2 -6
  25. package/src/tests/trip-handler.test.ts +7 -11
  26. package/src/timers/timer-manager.ts +0 -17
  27. package/src/types/mode-type.ts +1 -1
  28. package/dist/conditions/already-triggered-condition.d.ts +0 -10
  29. package/dist/conditions/already-triggered-condition.js +0 -22
  30. package/dist/conditions/already-triggered-condition.js.map +0 -1
  31. package/dist/conditions/arming-in-progress-condition.d.ts +0 -10
  32. package/dist/conditions/arming-in-progress-condition.js +0 -21
  33. package/dist/conditions/arming-in-progress-condition.js.map +0 -1
  34. package/dist/conditions/arming-lock-condition.d.ts +0 -13
  35. package/dist/conditions/arming-lock-condition.js +0 -50
  36. package/dist/conditions/arming-lock-condition.js.map +0 -1
  37. package/dist/conditions/condition.d.ts +0 -22
  38. package/dist/conditions/condition.js +0 -19
  39. package/dist/conditions/condition.js.map +0 -1
  40. package/dist/conditions/double-knock-condition.d.ts +0 -24
  41. package/dist/conditions/double-knock-condition.js +0 -73
  42. package/dist/conditions/double-knock-condition.js.map +0 -1
  43. package/dist/conditions/not-armed-condition.d.ts +0 -10
  44. package/dist/conditions/not-armed-condition.js +0 -26
  45. package/dist/conditions/not-armed-condition.js.map +0 -1
  46. package/dist/conditions/trigger-already-running-condition.d.ts +0 -10
  47. package/dist/conditions/trigger-already-running-condition.js +0 -21
  48. package/dist/conditions/trigger-already-running-condition.js.map +0 -1
  49. package/dist/constants/default-constant.d.ts +0 -27
  50. package/dist/constants/default-constant.js +0 -30
  51. package/dist/constants/default-constant.js.map +0 -1
  52. package/dist/constants/homekit-constant.d.ts +0 -4
  53. package/dist/constants/homekit-constant.js +0 -5
  54. package/dist/constants/homekit-constant.js.map +0 -1
  55. package/dist/constants/switch-uuid-constant.d.ts +0 -23
  56. package/dist/constants/switch-uuid-constant.js +0 -24
  57. package/dist/constants/switch-uuid-constant.js.map +0 -1
  58. package/dist/handlers/sensor-handler.d.ts +0 -20
  59. package/dist/handlers/sensor-handler.js +0 -66
  60. package/dist/handlers/sensor-handler.js.map +0 -1
  61. package/dist/handlers/state-handler.d.ts +0 -52
  62. package/dist/handlers/state-handler.js +0 -213
  63. package/dist/handlers/state-handler.js.map +0 -1
  64. package/dist/handlers/switch-handler.d.ts +0 -35
  65. package/dist/handlers/switch-handler.js +0 -134
  66. package/dist/handlers/switch-handler.js.map +0 -1
  67. package/dist/handlers/trip-handler.d.ts +0 -51
  68. package/dist/handlers/trip-handler.js +0 -198
  69. package/dist/handlers/trip-handler.js.map +0 -1
  70. package/dist/homekit/homekit-registrar.d.ts +0 -19
  71. package/dist/homekit/homekit-registrar.js +0 -156
  72. package/dist/homekit/homekit-registrar.js.map +0 -1
  73. package/dist/homekit/service-factory.d.ts +0 -9
  74. package/dist/homekit/service-factory.js +0 -124
  75. package/dist/homekit/service-factory.js.map +0 -1
  76. package/dist/index.d.ts +0 -3
  77. package/dist/index.js.map +0 -1
  78. package/dist/interfaces/condition-context-interface.d.ts +0 -16
  79. package/dist/interfaces/condition-context-interface.js +0 -2
  80. package/dist/interfaces/condition-context-interface.js.map +0 -1
  81. package/dist/interfaces/hap-types-interface.d.ts +0 -9
  82. package/dist/interfaces/hap-types-interface.js +0 -2
  83. package/dist/interfaces/hap-types-interface.js.map +0 -1
  84. package/dist/interfaces/mqtt-status-payload-interface.d.ts +0 -6
  85. package/dist/interfaces/mqtt-status-payload-interface.js +0 -2
  86. package/dist/interfaces/mqtt-status-payload-interface.js.map +0 -1
  87. package/dist/interfaces/options-interface.d.ts +0 -103
  88. package/dist/interfaces/options-interface.js +0 -2
  89. package/dist/interfaces/options-interface.js.map +0 -1
  90. package/dist/interfaces/persisted-state-interface.d.ts +0 -6
  91. package/dist/interfaces/persisted-state-interface.js +0 -2
  92. package/dist/interfaces/persisted-state-interface.js.map +0 -1
  93. package/dist/interfaces/service-registry-interface.d.ts +0 -33
  94. package/dist/interfaces/service-registry-interface.js +0 -2
  95. package/dist/interfaces/service-registry-interface.js.map +0 -1
  96. package/dist/interfaces/system-state-interface.d.ts +0 -15
  97. package/dist/interfaces/system-state-interface.js +0 -2
  98. package/dist/interfaces/system-state-interface.js.map +0 -1
  99. package/dist/schemas/arming-lock-schema.d.ts +0 -10
  100. package/dist/schemas/arming-lock-schema.js +0 -12
  101. package/dist/schemas/arming-lock-schema.js.map +0 -1
  102. package/dist/schemas/error-schema.d.ts +0 -4
  103. package/dist/schemas/error-schema.js +0 -7
  104. package/dist/schemas/error-schema.js.map +0 -1
  105. package/dist/schemas/mode-request-schema.d.ts +0 -10
  106. package/dist/schemas/mode-request-schema.js +0 -18
  107. package/dist/schemas/mode-request-schema.js.map +0 -1
  108. package/dist/schemas/status-response-schema.d.ts +0 -7
  109. package/dist/schemas/status-response-schema.js +0 -10
  110. package/dist/schemas/status-response-schema.js.map +0 -1
  111. package/dist/schemas/trip-mode-request-schema.d.ts +0 -9
  112. package/dist/schemas/trip-mode-request-schema.js +0 -24
  113. package/dist/schemas/trip-mode-request-schema.js.map +0 -1
  114. package/dist/security-system.d.ts +0 -22
  115. package/dist/security-system.js +0 -154
  116. package/dist/security-system.js.map +0 -1
  117. package/dist/services/audio-service.d.ts +0 -21
  118. package/dist/services/audio-service.js +0 -113
  119. package/dist/services/audio-service.js.map +0 -1
  120. package/dist/services/command-service.d.ts +0 -16
  121. package/dist/services/command-service.js +0 -65
  122. package/dist/services/command-service.js.map +0 -1
  123. package/dist/services/configuration-service.d.ts +0 -25
  124. package/dist/services/configuration-service.js +0 -218
  125. package/dist/services/configuration-service.js.map +0 -1
  126. package/dist/services/event-bus-service.d.ts +0 -12
  127. package/dist/services/event-bus-service.js +0 -17
  128. package/dist/services/event-bus-service.js.map +0 -1
  129. package/dist/services/mqtt-service.d.ts +0 -16
  130. package/dist/services/mqtt-service.js +0 -97
  131. package/dist/services/mqtt-service.js.map +0 -1
  132. package/dist/services/server-service.d.ts +0 -28
  133. package/dist/services/server-service.js +0 -275
  134. package/dist/services/server-service.js.map +0 -1
  135. package/dist/services/storage-service.d.ts +0 -14
  136. package/dist/services/storage-service.js +0 -70
  137. package/dist/services/storage-service.js.map +0 -1
  138. package/dist/services/webhook-service.d.ts +0 -16
  139. package/dist/services/webhook-service.js +0 -68
  140. package/dist/services/webhook-service.js.map +0 -1
  141. package/dist/tests/conditions.test.d.ts +0 -1
  142. package/dist/tests/conditions.test.js +0 -148
  143. package/dist/tests/conditions.test.js.map +0 -1
  144. package/dist/tests/mqtt-service.test.d.ts +0 -1
  145. package/dist/tests/mqtt-service.test.js +0 -167
  146. package/dist/tests/mqtt-service.test.js.map +0 -1
  147. package/dist/tests/server-service.test.d.ts +0 -1
  148. package/dist/tests/server-service.test.js +0 -187
  149. package/dist/tests/server-service.test.js.map +0 -1
  150. package/dist/tests/state-handler.test.d.ts +0 -1
  151. package/dist/tests/state-handler.test.js +0 -273
  152. package/dist/tests/state-handler.test.js.map +0 -1
  153. package/dist/tests/switch-handler.test.d.ts +0 -1
  154. package/dist/tests/switch-handler.test.js +0 -267
  155. package/dist/tests/switch-handler.test.js.map +0 -1
  156. package/dist/tests/trip-handler.test.d.ts +0 -1
  157. package/dist/tests/trip-handler.test.js +0 -289
  158. package/dist/tests/trip-handler.test.js.map +0 -1
  159. package/dist/timers/timer-manager.d.ts +0 -34
  160. package/dist/timers/timer-manager.js +0 -132
  161. package/dist/timers/timer-manager.js.map +0 -1
  162. package/dist/types/event-payload-map-type.d.ts +0 -14
  163. package/dist/types/event-payload-map-type.js +0 -2
  164. package/dist/types/event-payload-map-type.js.map +0 -1
  165. package/dist/types/event-type.d.ts +0 -38
  166. package/dist/types/event-type.js +0 -17
  167. package/dist/types/event-type.js.map +0 -1
  168. package/dist/types/mode-type.d.ts +0 -4
  169. package/dist/types/mode-type.js +0 -2
  170. package/dist/types/mode-type.js.map +0 -1
  171. package/dist/types/origin-type.d.ts +0 -9
  172. package/dist/types/origin-type.js +0 -11
  173. package/dist/types/origin-type.js.map +0 -1
  174. package/dist/types/security-state-type.d.ts +0 -11
  175. package/dist/types/security-state-type.js +0 -13
  176. package/dist/types/security-state-type.js.map +0 -1
  177. package/dist/types/service-result-type.d.ts +0 -4
  178. package/dist/types/service-result-type.js +0 -2
  179. package/dist/types/service-result-type.js.map +0 -1
  180. package/dist/utils/arming-util.d.ts +0 -19
  181. package/dist/utils/arming-util.js +0 -24
  182. package/dist/utils/arming-util.js.map +0 -1
  183. package/dist/utils/state-util.d.ts +0 -8
  184. package/dist/utils/state-util.js +0 -29
  185. package/dist/utils/state-util.js.map +0 -1
  186. package/sounds/README +0 -22
  187. package/sounds/de-DE/current-away.mp3 +0 -0
  188. package/sounds/de-DE/current-home.mp3 +0 -0
  189. package/sounds/de-DE/current-night.mp3 +0 -0
  190. package/sounds/de-DE/current-off.mp3 +0 -0
  191. package/sounds/de-DE/current-triggered.mp3 +0 -0
  192. package/sounds/de-DE/current-warning.mp3 +0 -0
  193. package/sounds/de-DE/target-away.mp3 +0 -0
  194. package/sounds/de-DE/target-home.mp3 +0 -0
  195. package/sounds/de-DE/target-night.mp3 +0 -0
  196. package/sounds/en-US/current-away.mp3 +0 -0
  197. package/sounds/en-US/current-home.mp3 +0 -0
  198. package/sounds/en-US/current-night.mp3 +0 -0
  199. package/sounds/en-US/current-off.mp3 +0 -0
  200. package/sounds/en-US/current-triggered.mp3 +0 -0
  201. package/sounds/en-US/current-warning.mp3 +0 -0
  202. package/sounds/en-US/target-away.mp3 +0 -0
  203. package/sounds/en-US/target-home.mp3 +0 -0
  204. package/sounds/en-US/target-night.mp3 +0 -0
  205. package/src/services/audio-service.ts +0 -133
@@ -35,7 +35,7 @@ jobs:
35
35
  node-version: 24
36
36
 
37
37
  - name: Get next version
38
- uses: MiguelRipoll23/get-next-version@v3.2.1
38
+ uses: MiguelRipoll23/get-next-version@v3.2.2
39
39
  id: get-next-version
40
40
  with:
41
41
  channel: ${{ inputs.channel }}
package/.gitignore ADDED
@@ -0,0 +1,127 @@
1
+ # Ignore compiled code
2
+ dist
3
+
4
+ # ------------- Defaults ------------- #
5
+ .DS_Store
6
+
7
+ # Logs
8
+ logs
9
+ *.log
10
+ npm-debug.log*
11
+ yarn-debug.log*
12
+ yarn-error.log*
13
+ lerna-debug.log*
14
+
15
+ # Diagnostic reports (https://nodejs.org/api/report.html)
16
+ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
17
+
18
+ # Runtime data
19
+ pids
20
+ *.pid
21
+ *.seed
22
+ *.pid.lock
23
+
24
+ # Directory for instrumented libs generated by jscoverage/JSCover
25
+ lib-cov
26
+
27
+ # Coverage directory used by tools like istanbul
28
+ coverage
29
+ *.lcov
30
+
31
+ # nyc test coverage
32
+ .nyc_output
33
+
34
+ # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
35
+ .grunt
36
+
37
+ # Bower dependency directory (https://bower.io/)
38
+ bower_components
39
+
40
+ # node-waf configuration
41
+ .lock-wscript
42
+
43
+ # Compiled binary addons (https://nodejs.org/api/addons.html)
44
+ build/Release
45
+
46
+ # Dependency directories
47
+ node_modules/
48
+ package-lock.json
49
+ jspm_packages/
50
+
51
+ # Snowpack dependency directory (https://snowpack.dev/)
52
+ web_modules/
53
+
54
+ # TypeScript cache
55
+ *.tsbuildinfo
56
+
57
+ # Optional npm cache directory
58
+ .npm
59
+
60
+ # Optional eslint cache
61
+ .eslintcache
62
+
63
+ # Microbundle cache
64
+ .rpt2_cache/
65
+ .rts2_cache_cjs/
66
+ .rts2_cache_es/
67
+ .rts2_cache_umd/
68
+
69
+ # Optional REPL history
70
+ .node_repl_history
71
+
72
+ # Output of 'npm pack'
73
+ *.tgz
74
+
75
+ # Yarn Integrity file
76
+ .yarn-integrity
77
+
78
+ # dotenv environment variables file
79
+ .env
80
+ .env.test
81
+
82
+ # parcel-bundler cache (https://parceljs.org/)
83
+ .cache
84
+ .parcel-cache
85
+
86
+ # Next.js build output
87
+ .next
88
+
89
+ # Nuxt.js build / generate output
90
+ .nuxt
91
+ dist
92
+
93
+ # Gatsby files
94
+ .cache/
95
+ # Comment in the public line in if your project uses Gatsby and not Next.js
96
+ # https://nextjs.org/blog/next-9-1#public-directory-support
97
+ # public
98
+
99
+ # vuepress build output
100
+ .vuepress/dist
101
+
102
+ # Serverless directories
103
+ .serverless/
104
+
105
+ # FuseBox cache
106
+ .fusebox/
107
+
108
+ # DynamoDB Local files
109
+ .dynamodb/
110
+
111
+ # TernJS port file
112
+ .tern-port
113
+
114
+ # Stores VSCode versions used for testing VSCode extensions
115
+ .vscode-test
116
+
117
+ # yarn v2
118
+
119
+ .yarn/cache
120
+ .yarn/unplugged
121
+ .yarn/build-state.yml
122
+ .pnp.*
123
+
124
+ # Webstorm
125
+ .idea
126
+
127
+ /test/hbConfig
package/AGENTS.md CHANGED
@@ -9,8 +9,8 @@ This document defines the architecture, naming conventions, and rules that all c
9
9
  `homebridge-securitysystem` is a Homebridge accessory plugin (not a platform plugin) that exposes a fully-featured security system to HomeKit. It is written in TypeScript with ESM modules.
10
10
 
11
11
  The plugin:
12
- - Exposes one `SecuritySystem` HAP service plus a configurable set of optional switch/sensor accessories (trip, mode, arming-lock, and audio switches; motion sensors).
13
- - Uses an event-driven architecture: core state changes emit domain events; side-effect services (audio, webhook, command, MQTT) listen and react.
12
+ - Exposes one `SecuritySystem` HAP service plus a configurable set of optional switch/sensor accessories (trip, mode, and arming-lock switches; motion sensors).
13
+ - Uses an event-driven architecture: core state changes emit domain events; side-effect services (webhook, command, MQTT) listen and react.
14
14
  - Uses an abstract `Condition` class hierarchy to encapsulate all blocking-logic decisions.
15
15
  - Provides an optional Hono HTTP server (zod-validated routes with OpenAPI and Scalar docs) for remote control.
16
16
  - Optionally publishes status updates over MQTT.
@@ -28,7 +28,7 @@ src/
28
28
  homekit/ HomeKit service construction + characteristic registration
29
29
  interfaces/ TypeScript interfaces (plain object shapes)
30
30
  schemas/ Zod schemas for HTTP server request/response validation
31
- services/ Stateful services (audio, webhook, command, MQTT, storage, server, event bus)
31
+ services/ Stateful services (webhook, command, MQTT, storage, server, event bus)
32
32
  tests/ Vitest test suites
33
33
  timers/ Centralised timer/interval ownership (TimerManager)
34
34
  types/ TypeScript enums and type aliases
@@ -69,7 +69,7 @@ All filenames use **kebab-case** with a mandatory suffix describing their kind:
69
69
  | Constant object | `-constant.ts` | `homekit-constant.ts` |
70
70
  | Utility functions | `-util.ts` | `state-util.ts` |
71
71
  | Zod schema | `-schema.ts` | `error-schema.ts` |
72
- | Service class | `-service.ts` | `audio-service.ts` |
72
+ | Service class | `-service.ts` | `webhook-service.ts` |
73
73
  | Handler class | `-handler.ts` | `state-handler.ts` |
74
74
  | Condition class | `-condition.ts` | `double-knock-condition.ts` |
75
75
  | HomeKit registrar class | `-registrar.ts` | `homekit-registrar.ts` |
@@ -139,11 +139,11 @@ The core state machine (`StateHandler`, `TripHandler`, `SwitchHandler`) never ca
139
139
 
140
140
  ```
141
141
  StateHandler → bus.emit(EventType.CURRENT_CHANGED, payload)
142
- ↓ ↓ ↓ ↓
143
- AudioService WebhookService CommandService MqttService
142
+ ↓ ↓ ↓
143
+ WebhookService CommandService MqttService
144
144
  ```
145
145
 
146
- `AudioService` and `StorageService` are constructor-injected into the handlers that need them; `WebhookService`, `CommandService`, and `MqttService` are purely event-driven and call `attachToBus(bus)` during construction in `security-system.ts`.
146
+ `StorageService` is constructor-injected into the handlers that need it; `WebhookService`, `CommandService`, and `MqttService` are purely event-driven and call `attachToBus(bus)` during construction in `security-system.ts`.
147
147
 
148
148
  **New side effects must follow this pattern** — never add direct calls from handlers to services. The MQTT client is disconnected on shutdown via an `api.on('shutdown', ...)` hook wired in `security-system.ts`.
149
149
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## v13.0.0-beta.1 - 2026-09-02
4
+
5
+ <!-- Release notes generated using configuration in .github/release.yml at v13.0.0-beta.1 -->
6
+
7
+ ## What's Changed
8
+ ### 💥 Breaking Changes
9
+ * Remove audio playback by @MiguelRipoll23 in https://github.com/MiguelRipoll23/homebridge-securitysystem/pull/1001
10
+ * Remove triggered sensor by @MiguelRipoll23 in https://github.com/MiguelRipoll23/homebridge-securitysystem/pull/1002
11
+
12
+
13
+ **Full Changelog**: https://github.com/MiguelRipoll23/homebridge-securitysystem/compare/v12.0.0...v13.0.0-beta.1
14
+
15
+
16
+ ## v12.0.0 - 2026-08-30
17
+
18
+ <!-- Release notes generated using configuration in .github/release.yml at v12.0.0 -->
19
+
20
+ ## What's Changed
21
+ ### 💥 Breaking Changes
22
+ * Remove file logging by @MiguelRipoll23 in https://github.com/MiguelRipoll23/homebridge-securitysystem/pull/988
23
+ * feat: use full URL per webhook event (remove base URL) by @MiguelRipoll23 in https://github.com/MiguelRipoll23/homebridge-securitysystem/pull/992
24
+ ### 🛠️ Other Changes
25
+ * Deprecate audio playback by @MiguelRipoll23 in https://github.com/MiguelRipoll23/homebridge-securitysystem/pull/989
26
+ * Deprecate triggered sensor by @MiguelRipoll23 in https://github.com/MiguelRipoll23/homebridge-securitysystem/pull/990
27
+ * docs: update AGENTS.md to match current architecture by @MiguelRipoll23 in https://github.com/MiguelRipoll23/homebridge-securitysystem/pull/995
28
+
29
+
30
+ **Full Changelog**: https://github.com/MiguelRipoll23/homebridge-securitysystem/compare/v11.4.1...v12.0.0
31
+
32
+
3
33
  ## v12.0.0-beta.2 - 2026-08-29
4
34
 
5
35
  <!-- Release notes generated using configuration in .github/release.yml at v12.0.0-beta.2 -->
@@ -323,23 +323,6 @@
323
323
  "functionBody": "return !(model.disabled_modes || []).includes('Night');"
324
324
  }
325
325
  },
326
- "audio_switch": {
327
- "title": "Show Audio Enable Switch (Deprecated)",
328
- "description": "Adds a global switch to enable or disable audio except for alarm triggered. Deprecated — audio playback is deprecated, use command hooks instead.",
329
- "type": "boolean",
330
- "default": false,
331
- "required": false
332
- },
333
- "audio_switch_name": {
334
- "title": "Audio Enable Switch Name (Deprecated)",
335
- "description": "",
336
- "type": "string",
337
- "default": "Enable Audio",
338
- "required": false,
339
- "condition": {
340
- "functionBody": "return model.audio_switch === true;"
341
- }
342
- },
343
326
  "arming_sensor": {
344
327
  "title": "Show Arming Sensor",
345
328
  "description": "Adds a sensor that asserts when the security system is being armed.",
@@ -365,24 +348,6 @@
365
348
  "functionBody": "return model.tripped_sensor === true;"
366
349
  }
367
350
  },
368
- "triggered_sensor": {
369
- "title": "Show Triggered Sensor (Deprecated)",
370
- "description": "Adds a sensor that pulses at the set rate when the security system has been triggered. Deprecated — Apple already provides emergency alerts for security system accessories, so this sensor is redundant.",
371
- "type": "boolean",
372
- "default": false,
373
- "required": false
374
- },
375
- "triggered_sensor_seconds": {
376
- "title": "Triggered Sensor Pulse Rate (seconds) (Deprecated)",
377
- "description": "Set to 0 for steady on.",
378
- "type": "integer",
379
- "default": 5,
380
- "required": false,
381
- "minimum": 0,
382
- "condition": {
383
- "functionBody": "return model.triggered_sensor === true;"
384
- }
385
- },
386
351
  "reset_sensor": {
387
352
  "title": "Show Triggered Reset Sensor",
388
353
  "description": "Adds a sensor that asserts when the security system has reset after being triggered.",
@@ -390,72 +355,6 @@
390
355
  "default": false,
391
356
  "required": false
392
357
  },
393
- "audio": {
394
- "title": "Play Sounds (Deprecated, local-only, ffmpeg required)",
395
- "description": "Warns of pending or current events by playing sounds. Deprecated — use command hooks (command_current_*) to play audio instead, which is more flexible.",
396
- "type": "boolean",
397
- "default": false,
398
- "required": false
399
- },
400
- "audio_language": {
401
- "title": "Audio Language",
402
- "description": "",
403
- "type": "string",
404
- "default": "en-US",
405
- "required": false,
406
- "enum": ["en-US", "de-DE"]
407
- },
408
- "audio_extra_variables": {
409
- "title": "Audio Extra Variables",
410
- "description": "Add extra environment variables to the ffplay command that will be executed",
411
- "type": "array",
412
- "items": {
413
- "title": "Environment Variable",
414
- "type": "object",
415
- "properties": {
416
- "key": {
417
- "title": "Name",
418
- "type": "string",
419
- "required": true
420
- },
421
- "value": {
422
- "title": "Value",
423
- "type": "string",
424
- "required": true
425
- }
426
- }
427
- },
428
- "required": false
429
- },
430
- "audio_path": {
431
- "title": "Custom Audio Path",
432
- "description": "Instructions will be created in this path.",
433
- "type": "string",
434
- "required": false,
435
- "placeholder": "/home/user/sounds"
436
- },
437
- "audio_volume": {
438
- "title": "Audio Volume",
439
- "description": "",
440
- "type": "string",
441
- "required": false,
442
- "default": 100,
443
- "placeholder": "100"
444
- },
445
- "audio_arming_looped": {
446
- "title": "Loop Arming Sound",
447
- "description": "",
448
- "type": "boolean",
449
- "default": false,
450
- "required": false
451
- },
452
- "audio_alert_looped": {
453
- "title": "Loop Tripped Sound",
454
- "description": "",
455
- "type": "boolean",
456
- "default": false,
457
- "required": false
458
- },
459
358
  "server_port": {
460
359
  "title": "Listening Port",
461
360
  "description": "",
@@ -888,9 +787,7 @@
888
787
  "type": "tabarray",
889
788
  "title": "{{ value.label || 'Night Switch' }}",
890
789
  "items": ["trip_night_switches[].label"]
891
- },
892
- "audio_switch",
893
- "audio_switch_name"
790
+ }
894
791
  ]
895
792
  },
896
793
  {
@@ -908,50 +805,9 @@
908
805
  "flex-direction": "row",
909
806
  "items": ["tripped_sensor", "tripped_sensor_seconds"]
910
807
  },
911
- {
912
- "type": "div",
913
- "displayFlex": true,
914
- "flex-flow": "row",
915
- "flex-direction": "row",
916
- "items": ["triggered_sensor", "triggered_sensor_seconds"]
917
- },
918
808
  "reset_sensor"
919
809
  ]
920
810
  },
921
- {
922
- "type": "fieldset",
923
- "title": "Audio (Deprecated)",
924
- "description": "Play sounds on your connected speakers to notify events. Deprecated — use command hooks to play audio instead, which is more flexible.",
925
- "expandable": true,
926
- "expanded": false,
927
- "items": [
928
- {
929
- "type": "div",
930
- "displayFlex": true,
931
- "flex-flow": "row wrap",
932
- "flex-direction": "row",
933
- "items": ["audio", "audio_language"]
934
- },
935
- {
936
- "type": "div",
937
- "displayFlex": true,
938
- "flex-flow": "row wrap",
939
- "flex-direction": "row",
940
- "items": ["audio_path", "audio_volume"]
941
- },
942
- "audio_arming_looped",
943
- "audio_alert_looped",
944
- {
945
- "key": "audio_extra_variables",
946
- "type": "tabarray",
947
- "title": "{{ value.key || 'Environment Variable' }}",
948
- "items": [
949
- "audio_extra_variables[].key",
950
- "audio_extra_variables[].value"
951
- ]
952
- }
953
- ]
954
- },
955
811
  {
956
812
  "type": "fieldset",
957
813
  "title": "Server",
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "homebridge-securitysystem",
3
3
  "displayName": "Homebridge Security System",
4
4
  "type": "module",
5
- "version": "12.0.0",
5
+ "version": "13.0.0",
6
6
  "description": "Homebridge plugin that creates a security system accessory that can be triggered by HomeKit sensors.",
7
7
  "author": "MiguelRipoll23",
8
8
  "license": "MIT",
@@ -8,9 +8,7 @@ export const DEFAULTS = {
8
8
  RESET_MINUTES: 10,
9
9
  DOUBLE_KNOCK_SECONDS: 90,
10
10
  TRIPPED_SENSOR_SECONDS: 5,
11
- TRIGGERED_SENSOR_SECONDS: 5,
12
11
  PAUSE_MINUTES: 0,
13
- AUDIO_LANGUAGE: 'en-US',
14
12
 
15
13
  // Switch display names
16
14
  TRIP_SWITCH_NAME: 'Trip',
@@ -24,7 +22,6 @@ export const DEFAULTS = {
24
22
  MODE_OFF_SWITCH_NAME: 'Mode Off',
25
23
  MODE_AWAY_EXTENDED_SWITCH_NAME: 'Mode Away Extended',
26
24
  MODE_PAUSE_SWITCH_NAME: 'Mode Pause',
27
- AUDIO_SWITCH_NAME: 'Audio',
28
25
 
29
26
  // MQTT
30
27
  MQTT_TOPIC: 'security-system/state',
@@ -15,9 +15,7 @@ export const SWITCH_UUIDS = {
15
15
  MODE_OFF: 'mode-off',
16
16
  MODE_AWAY_EXTENDED: 'mode-away-extended',
17
17
  MODE_PAUSE: 'mode-pause',
18
- AUDIO: 'kx82r64zN3txDXKFiX9JDi',
19
18
  ARMING_SENSOR: 'arming-motion-sensor',
20
19
  TRIPPED_SENSOR: 'siren-tripped',
21
- TRIGGERED_SENSOR: 'siren-triggered',
22
20
  RESET_SENSOR: 'reset-event',
23
21
  } as const;
@@ -54,28 +54,6 @@ export class SensorHandler {
54
54
  }
55
55
  }
56
56
 
57
- // ── Triggered sensor ───────────────────────────────────────────────────────
58
-
59
- pulseTriggeredMotionSensor(): void {
60
- this.setTriggeredMotionSensor(true);
61
- this.scheduleReset(this.services.triggeredMotionSensorService);
62
- }
63
-
64
- setTriggeredMotionSensor(value: boolean): void {
65
- this.services.triggeredMotionSensorService.updateCharacteristic(
66
- this.Characteristic.MotionDetected,
67
- value,
68
- );
69
- }
70
-
71
- resetTriggeredMotionSensor(): void {
72
- const char = this.services.triggeredMotionSensorService
73
- .getCharacteristic(this.Characteristic.MotionDetected);
74
- if (char.value) {
75
- char.updateValue(false);
76
- }
77
- }
78
-
79
57
  // ── Reset sensor ───────────────────────────────────────────────────────────
80
58
 
81
59
  pulseResetMotionSensor(): void {
@@ -10,7 +10,6 @@ import type { SecuritySystemOptions } from '../interfaces/options-interface.js';
10
10
  import type { EventBusService } from '../services/event-bus-service.js';
11
11
  import { EventType } from '../types/event-type.js';
12
12
  import type { StorageService } from '../services/storage-service.js';
13
- import type { AudioService } from '../services/audio-service.js';
14
13
  import type { SensorHandler } from './sensor-handler.js';
15
14
  import type { TimerManager } from '../timers/timer-manager.js';
16
15
  import { getArmingSeconds } from '../utils/arming-util.js';
@@ -30,7 +29,6 @@ export class StateHandler {
30
29
  private readonly log: Logging,
31
30
  private readonly bus: EventBusService,
32
31
  private readonly storageService: StorageService,
33
- private readonly audio: AudioService,
34
32
  private readonly timers: TimerManager,
35
33
  private readonly sensorHandler: SensorHandler,
36
34
  ) {}
@@ -39,7 +37,6 @@ export class StateHandler {
39
37
 
40
38
  setCurrentState(state: SecurityState, origin: OriginType): void {
41
39
  this.sensorHandler.resetArmingMotionSensor();
42
- this.audio.play('current', state);
43
40
 
44
41
  if (this.state.currentState === state) {
45
42
  this.log.warn('Current mode (Already set)');
@@ -191,7 +188,6 @@ export class StateHandler {
191
188
  // Notify handlers to reset their displayed state (bus is synchronous).
192
189
  this.bus.emit(EventType.RESET_TRIP_SWITCHES, {});
193
190
  this.sensorHandler.resetTrippedMotionSensor();
194
- this.sensorHandler.resetTriggeredMotionSensor();
195
191
  this.bus.emit(EventType.RESET_MODE_SWITCHES, {});
196
192
  this.bus.emit(EventType.UPDATE_MODE_SWITCHES, {});
197
193
 
@@ -225,7 +221,6 @@ export class StateHandler {
225
221
  private handleTriggeredState(): void {
226
222
  this.timers.clearTrippedInterval();
227
223
  this.sensorHandler.resetTrippedMotionSensor();
228
- this.startTriggeredMotionSensor();
229
224
 
230
225
  this.timers.setResetTimer(this.options.resetMinutes * 60 * 1000, () => {
231
226
  this.log.info('Reset (Finished)');
@@ -239,18 +234,6 @@ export class StateHandler {
239
234
  });
240
235
  }
241
236
 
242
- private startTriggeredMotionSensor(): void {
243
- const seconds = this.options.triggeredMotionSensorSeconds;
244
- if (seconds === 0) {
245
- this.sensorHandler.setTriggeredMotionSensor(true);
246
- } else {
247
- this.timers.setTriggeredInterval(
248
- seconds * 1000,
249
- () => this.sensorHandler.pulseTriggeredMotionSensor(),
250
- );
251
- }
252
- }
253
-
254
237
  private handleArmingState(): void {
255
238
  this.sensorHandler.updateArmingMotionSensor(true);
256
239
  this.bus.emit(EventType.ARMING, { state: this.state.targetState });
@@ -7,7 +7,6 @@ import type { SystemState } from '../interfaces/system-state-interface.js';
7
7
  import type { SecuritySystemOptions } from '../interfaces/options-interface.js';
8
8
  import type { EventBusService } from '../services/event-bus-service.js';
9
9
  import { EventType } from '../types/event-type.js';
10
- import type { AudioService } from '../services/audio-service.js';
11
10
  import type { SensorHandler } from './sensor-handler.js';
12
11
  import type { Condition } from '../conditions/condition.js';
13
12
  import type { ConditionContext } from '../interfaces/condition-context-interface.js';
@@ -34,7 +33,6 @@ export class TripHandler {
34
33
  private readonly Characteristic: CharacteristicConstructor,
35
34
  private readonly log: Logging,
36
35
  private readonly bus: EventBusService,
37
- private readonly audio: AudioService,
38
36
  private readonly sensorHandler: SensorHandler,
39
37
  private readonly timers: TimerManager,
40
38
  ) {
@@ -200,7 +198,6 @@ export class TripHandler {
200
198
  private cancelTrip(origin: OriginType, stateChanged: boolean): void {
201
199
  this.log.info('Security System (Cancelled)');
202
200
  this.state.isTripping = false;
203
- this.audio.stop();
204
201
 
205
202
  this.bus.emit(EventType.TRIP_CANCELLED, { origin, stateChanged });
206
203
 
@@ -152,15 +152,10 @@ export class HomeKitRegistrar {
152
152
  .onSet(async (v: CharacteristicValue) => this.log.info(`Arming lock [${mode}] (${v ? 'On' : 'Off'})`));
153
153
  }
154
154
 
155
- // Audio switch.
156
- s.audioSwitchService.getCharacteristic(Char.On)
157
- .onGet(async () => Boolean(s.audioSwitchService.getCharacteristic(Char.On).value))
158
- .onSet(async (v: CharacteristicValue) => this.log.info(`Audio (${v ? 'Enabled' : 'Disabled'})`));
159
-
160
155
  // Motion sensors (read-only).
161
156
  const sensorKeys = [
162
157
  'armingMotionSensorService', 'trippedMotionSensorService',
163
- 'triggeredMotionSensorService', 'triggeredResetMotionSensorService',
158
+ 'triggeredResetMotionSensorService',
164
159
  ] as const;
165
160
  for (const key of sensorKeys) {
166
161
  s[key].getCharacteristic(Char.MotionDetected)
@@ -34,9 +34,6 @@ export function buildServiceRegistry(
34
34
  infoSvc.setCharacteristic(Char.Model, 'DIY');
35
35
  infoSvc.setCharacteristic(Char.SerialNumber, options.serialNumber);
36
36
 
37
- const audioSvc = sw(options.audioSwitchName, SWITCH_UUIDS.AUDIO);
38
- audioSvc.getCharacteristic(Char.On).value = true;
39
-
40
37
  const buildCustomTripSwitches = (mode: string, modeLabel: string, switches: TripModeSwitch[]): Service[] =>
41
38
  switches.map((s, i) => sw(`Trip ${modeLabel} ${s.label}`, `trip-${mode}-${i}`));
42
39
 
@@ -61,10 +58,8 @@ export function buildServiceRegistry(
61
58
  customTripHomeSwitchServices: buildCustomTripSwitches('home', 'Home', options.tripHomeSwitches),
62
59
  customTripAwaySwitchServices: buildCustomTripSwitches('away', 'Away', options.tripAwaySwitches),
63
60
  customTripNightSwitchServices: buildCustomTripSwitches('night', 'Night', options.tripNightSwitches),
64
- audioSwitchService: audioSvc,
65
61
  armingMotionSensorService: sensor('Arming', SWITCH_UUIDS.ARMING_SENSOR),
66
62
  trippedMotionSensorService: sensor('Tripped', SWITCH_UUIDS.TRIPPED_SENSOR),
67
- triggeredMotionSensorService: sensor('Triggered', SWITCH_UUIDS.TRIGGERED_SENSOR),
68
63
  triggeredResetMotionSensorService: sensor('Triggered Reset', SWITCH_UUIDS.RESET_SENSOR),
69
64
  };
70
65
  }
@@ -84,9 +79,6 @@ export function buildServiceList(
84
79
  if (options.trippedMotionSensor) {
85
80
  list.push(svcs.trippedMotionSensorService);
86
81
  }
87
- if (options.triggeredMotionSensor) {
88
- list.push(svcs.triggeredMotionSensorService);
89
- }
90
82
  if (options.resetSensor) {
91
83
  list.push(svcs.triggeredResetMotionSensorService);
92
84
  }
@@ -140,9 +132,6 @@ export function buildServiceList(
140
132
  if (options.modePauseSwitch) {
141
133
  list.push(svcs.modePauseSwitchService);
142
134
  }
143
- if (options.audio && options.audioSwitch) {
144
- list.push(svcs.audioSwitchService);
145
- }
146
135
 
147
136
  return list;
148
137
  }
@@ -1,9 +1,3 @@
1
- /** Key-value pair for extra ffplay environment variables. */
2
- export interface AudioVariable {
3
- key: string;
4
- value: string;
5
- }
6
-
7
1
  /** A single custom trip switch entry with a user-defined label. */
8
2
  export interface TripModeSwitch {
9
3
  label: string;
@@ -33,7 +27,6 @@ export interface SecuritySystemOptions {
33
27
  modeOffSwitchName: string;
34
28
  modeAwayExtendedSwitchName: string;
35
29
  modePauseSwitchName: string;
36
- audioSwitchName: string;
37
30
 
38
31
  // Behaviour toggles
39
32
  overrideOff: boolean;
@@ -68,8 +61,6 @@ export interface SecuritySystemOptions {
68
61
  armingMotionSensor: boolean;
69
62
  trippedMotionSensor: boolean;
70
63
  trippedMotionSensorSeconds: number;
71
- triggeredMotionSensor: boolean;
72
- triggeredMotionSensorSeconds: number;
73
64
  resetSensor: boolean;
74
65
 
75
66
  // Mode switches
@@ -88,16 +79,6 @@ export interface SecuritySystemOptions {
88
79
  awayDoubleKnockSeconds: number | null;
89
80
  nightDoubleKnockSeconds: number | null;
90
81
 
91
- // Audio
92
- audio: boolean;
93
- audioPath: string | null;
94
- audioLanguage: string;
95
- audioVolume: number | null;
96
- audioArmingLooped: boolean;
97
- audioAlertLooped: boolean;
98
- audioExtraVariables: AudioVariable[];
99
- audioSwitch: boolean;
100
-
101
82
  // Server
102
83
  serverPort: number | null;
103
84
  serverApiKey: string | null;
@@ -31,13 +31,9 @@ export interface ServiceRegistry {
31
31
  customTripAwaySwitchServices: Service[];
32
32
  customTripNightSwitchServices: Service[];
33
33
 
34
- // Audio switch
35
- audioSwitchService: Service;
36
-
37
34
  // Motion sensors
38
35
  armingMotionSensorService: Service;
39
36
  trippedMotionSensorService: Service;
40
- triggeredMotionSensorService: Service;
41
37
  triggeredResetMotionSensorService: Service;
42
38
  }
43
39
 
@@ -1,4 +1,3 @@
1
- import type { ChildProcess } from 'child_process';
2
1
  import type { SecurityState } from '../types/security-state-type.js';
3
2
 
4
3
  /** Mutable runtime state shared across all handlers. */
@@ -13,5 +12,4 @@ export interface SystemState {
13
12
  isKnocked: boolean;
14
13
  serverAuthenticationAttempts: number;
15
14
  pausedCurrentState: SecurityState | null;
16
- audioProcess: ChildProcess | null;
17
15
  }