homebridge-securitysystem 9.1.2-beta.3 → 10.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +3 -0
- package/AGENTS.md +214 -0
- package/dist/conditions/already-triggered-condition.d.ts +10 -0
- package/dist/conditions/already-triggered-condition.js +16 -0
- package/dist/conditions/already-triggered-condition.js.map +1 -0
- package/dist/conditions/arming-in-progress-condition.d.ts +10 -0
- package/dist/conditions/arming-in-progress-condition.js +15 -0
- package/dist/conditions/arming-in-progress-condition.js.map +1 -0
- package/dist/conditions/arming-lock-condition.d.ts +13 -0
- package/dist/conditions/arming-lock-condition.js +42 -0
- package/dist/conditions/arming-lock-condition.js.map +1 -0
- package/dist/conditions/condition.d.ts +15 -0
- package/dist/conditions/condition.js +9 -0
- package/dist/conditions/condition.js.map +1 -0
- package/dist/conditions/double-knock-condition.d.ts +22 -0
- package/dist/conditions/double-knock-condition.js +70 -0
- package/dist/conditions/double-knock-condition.js.map +1 -0
- package/dist/conditions/not-armed-condition.d.ts +10 -0
- package/dist/conditions/not-armed-condition.js +20 -0
- package/dist/conditions/not-armed-condition.js.map +1 -0
- package/dist/constants/default-constant.d.ts +26 -0
- package/dist/constants/default-constant.js +28 -0
- package/dist/constants/default-constant.js.map +1 -0
- package/dist/constants/homekit-constant.d.ts +4 -0
- package/dist/constants/homekit-constant.js +5 -0
- package/dist/constants/homekit-constant.js.map +1 -0
- package/dist/constants/switch-uuid-constant.d.ts +23 -0
- package/dist/constants/switch-uuid-constant.js +24 -0
- package/dist/constants/switch-uuid-constant.js.map +1 -0
- package/dist/handlers/sensor-handler.d.ts +17 -0
- package/dist/handlers/sensor-handler.js +53 -0
- package/dist/handlers/sensor-handler.js.map +1 -0
- package/dist/handlers/state-handler.d.ts +41 -0
- package/dist/handlers/state-handler.js +213 -0
- package/dist/handlers/state-handler.js.map +1 -0
- package/dist/handlers/switch-handler.d.ts +27 -0
- package/dist/handlers/switch-handler.js +139 -0
- package/dist/handlers/switch-handler.js.map +1 -0
- package/dist/handlers/trip-handler.d.ts +45 -0
- package/dist/handlers/trip-handler.js +179 -0
- package/dist/handlers/trip-handler.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/condition-context-interface.d.ts +13 -0
- package/dist/interfaces/condition-context-interface.js +2 -0
- package/dist/interfaces/condition-context-interface.js.map +1 -0
- package/dist/interfaces/hap-types-interface.d.ts +9 -0
- package/dist/interfaces/hap-types-interface.js +2 -0
- package/dist/interfaces/hap-types-interface.js.map +1 -0
- package/dist/interfaces/options-interface.d.ts +93 -0
- package/dist/interfaces/options-interface.js +2 -0
- package/dist/interfaces/options-interface.js.map +1 -0
- package/dist/interfaces/persisted-state-interface.d.ts +6 -0
- package/dist/interfaces/persisted-state-interface.js +2 -0
- package/dist/interfaces/persisted-state-interface.js.map +1 -0
- package/dist/interfaces/service-registry-interface.d.ts +26 -0
- package/dist/interfaces/service-registry-interface.js +2 -0
- package/dist/interfaces/service-registry-interface.js.map +1 -0
- package/dist/interfaces/system-state-interface.d.ts +21 -0
- package/dist/interfaces/system-state-interface.js +2 -0
- package/dist/interfaces/system-state-interface.js.map +1 -0
- package/dist/security-system.d.ts +26 -0
- package/dist/security-system.js +377 -0
- package/dist/security-system.js.map +1 -0
- package/dist/services/audio-service.d.ts +21 -0
- package/dist/services/audio-service.js +113 -0
- package/dist/services/audio-service.js.map +1 -0
- package/dist/services/command-service.d.ts +16 -0
- package/dist/services/command-service.js +65 -0
- package/dist/services/command-service.js.map +1 -0
- package/dist/services/event-bus-service.d.ts +12 -0
- package/dist/services/event-bus-service.js +17 -0
- package/dist/services/event-bus-service.js.map +1 -0
- package/dist/services/server-service.d.ts +25 -0
- package/dist/services/server-service.js +140 -0
- package/dist/services/server-service.js.map +1 -0
- package/dist/services/storage-service.d.ts +14 -0
- package/dist/services/storage-service.js +70 -0
- package/dist/services/storage-service.js.map +1 -0
- package/dist/services/webhook-service.d.ts +16 -0
- package/dist/services/webhook-service.js +73 -0
- package/dist/services/webhook-service.js.map +1 -0
- package/dist/tests/conditions.test.d.ts +1 -0
- package/dist/tests/conditions.test.js +151 -0
- package/dist/tests/conditions.test.js.map +1 -0
- package/dist/tests/state-handler.test.d.ts +1 -0
- package/dist/tests/state-handler.test.js +171 -0
- package/dist/tests/state-handler.test.js.map +1 -0
- package/dist/tests/trip-handler.test.d.ts +1 -0
- package/dist/tests/trip-handler.test.js +160 -0
- package/dist/tests/trip-handler.test.js.map +1 -0
- package/dist/types/event-payload-map-type.d.ts +9 -0
- package/dist/types/event-payload-map-type.js +2 -0
- package/dist/types/event-payload-map-type.js.map +1 -0
- package/dist/types/event-type.d.ts +24 -0
- package/dist/types/event-type.js +9 -0
- package/dist/types/event-type.js.map +1 -0
- package/dist/types/mode-type.d.ts +4 -0
- package/dist/types/mode-type.js +2 -0
- package/dist/types/mode-type.js.map +1 -0
- package/dist/types/origin-type.d.ts +9 -0
- package/dist/types/origin-type.js +11 -0
- package/dist/types/origin-type.js.map +1 -0
- package/dist/types/security-state-type.d.ts +11 -0
- package/dist/types/security-state-type.js +13 -0
- package/dist/types/security-state-type.js.map +1 -0
- package/dist/utils/log-util.d.ts +4 -0
- package/dist/utils/log-util.js +47 -0
- package/dist/utils/log-util.js.map +1 -0
- package/dist/utils/options-util.d.ts +6 -0
- package/dist/utils/options-util.js +171 -0
- package/dist/utils/options-util.js.map +1 -0
- package/dist/utils/state-util.d.ts +8 -0
- package/dist/utils/state-util.js +29 -0
- package/dist/utils/state-util.js.map +1 -0
- package/eslint.config.js +35 -0
- package/package.json +40 -34
- package/src/@types/homebridge-lib.d.ts +14 -0
- package/src/conditions/already-triggered-condition.ts +18 -0
- package/src/conditions/arming-in-progress-condition.ts +17 -0
- package/src/conditions/arming-lock-condition.ts +48 -0
- package/src/conditions/condition.ts +17 -0
- package/src/conditions/double-knock-condition.ts +82 -0
- package/src/conditions/not-armed-condition.ts +24 -0
- package/src/constants/default-constant.ts +28 -0
- package/src/constants/homekit-constant.ts +5 -0
- package/src/constants/switch-uuid-constant.ts +23 -0
- package/src/handlers/sensor-handler.ts +81 -0
- package/src/handlers/state-handler.ts +268 -0
- package/src/handlers/switch-handler.ts +166 -0
- package/src/handlers/trip-handler.ts +219 -0
- package/src/index.ts +9 -0
- package/src/interfaces/condition-context-interface.ts +14 -0
- package/src/interfaces/hap-types-interface.ts +11 -0
- package/src/interfaces/options-interface.ts +120 -0
- package/src/interfaces/persisted-state-interface.ts +7 -0
- package/src/interfaces/service-registry-interface.ts +37 -0
- package/src/interfaces/system-state-interface.ts +25 -0
- package/src/security-system.ts +433 -0
- package/src/services/audio-service.ts +133 -0
- package/src/services/command-service.ts +76 -0
- package/src/services/event-bus-service.ts +21 -0
- package/src/services/server-service.ts +176 -0
- package/src/services/storage-service.ts +80 -0
- package/src/services/webhook-service.ts +83 -0
- package/src/tests/conditions.test.ts +180 -0
- package/src/tests/state-handler.test.ts +200 -0
- package/src/tests/trip-handler.test.ts +182 -0
- package/src/types/event-payload-map-type.ts +15 -0
- package/src/types/event-type.ts +29 -0
- package/src/types/mode-type.ts +4 -0
- package/src/types/origin-type.ts +9 -0
- package/src/types/security-state-type.ts +11 -0
- package/src/utils/log-util.ts +54 -0
- package/src/utils/options-util.ts +202 -0
- package/src/utils/state-util.ts +32 -0
- package/tsconfig.json +25 -0
- package/vitest.config.ts +8 -0
- package/.eslintrc.js +0 -16
- package/.vscode/settings.json +0 -12
- package/src/index.js +0 -2525
- package/src/utils/options.js +0 -409
package/AGENTS.md
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# AGENTS.md — Architecture & Development Rules
|
|
2
|
+
|
|
3
|
+
This document defines the architecture, naming conventions, and rules that all contributors and AI agents must follow when working on this codebase.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Project Overview
|
|
8
|
+
|
|
9
|
+
`homebridge-securitysystem` is a Homebridge v2 accessory plugin (not a platform plugin) that exposes a fully-featured security system to HomeKit. It is written in TypeScript with ESM modules.
|
|
10
|
+
|
|
11
|
+
The plugin:
|
|
12
|
+
- Exposes one `SecuritySystem` HAP service plus up to 22 optional switch/sensor accessories.
|
|
13
|
+
- Uses an event-driven architecture: core state changes emit domain events; side-effect services (audio, webhook, command) listen and react.
|
|
14
|
+
- Uses an abstract `Condition` class hierarchy to encapsulate all blocking-logic decisions.
|
|
15
|
+
- Provides an optional Hono HTTP server for remote control.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Source Layout
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
src/
|
|
23
|
+
@types/ Third-party type declarations
|
|
24
|
+
conditions/ Abstract Condition base + concrete condition classes
|
|
25
|
+
constants/ Compile-time constants (no logic)
|
|
26
|
+
handlers/ Stateful handlers wired by security-system.ts
|
|
27
|
+
interfaces/ TypeScript interfaces (plain object shapes)
|
|
28
|
+
services/ Stateful services (audio, webhook, command, storage, server, event bus)
|
|
29
|
+
tests/ Vitest test suites
|
|
30
|
+
types/ TypeScript enums and type aliases
|
|
31
|
+
utils/ Pure utility functions
|
|
32
|
+
index.ts Homebridge plugin entry point
|
|
33
|
+
security-system.ts Root AccessoryPlugin class
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Layer Rules
|
|
39
|
+
|
|
40
|
+
| Layer | What belongs here | What does NOT belong |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| `types/` | Enums, type aliases | Logic, classes |
|
|
43
|
+
| `interfaces/` | Plain object shape interfaces | Logic, classes, enums |
|
|
44
|
+
| `constants/` | `const` objects, literal values | Logic, mutable state |
|
|
45
|
+
| `utils/` | Pure functions with no side effects | Classes, state, I/O |
|
|
46
|
+
| `conditions/` | Classes extending `Condition` | Handlers, services |
|
|
47
|
+
| `services/` | Stateful singleton classes, I/O | Embedded types, enums, interfaces |
|
|
48
|
+
| `handlers/` | State-machine logic classes | Embedded types, enums, interfaces |
|
|
49
|
+
|
|
50
|
+
**Types, enums, and interfaces must never be defined inside a service or handler file.** Always create a separate file in `types/` or `interfaces/` and import it.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## File Naming Conventions
|
|
55
|
+
|
|
56
|
+
All filenames use **kebab-case** with a mandatory suffix describing their kind:
|
|
57
|
+
|
|
58
|
+
| Kind | Suffix | Example |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| Enum or type alias | `-type.ts` | `security-state-type.ts` |
|
|
61
|
+
| Interface | `-interface.ts` | `system-state-interface.ts` |
|
|
62
|
+
| Constant object | `-constant.ts` | `homekit-constant.ts` |
|
|
63
|
+
| Utility functions | `-util.ts` | `state-util.ts` |
|
|
64
|
+
| Service class | `-service.ts` | `audio-service.ts` |
|
|
65
|
+
| Handler class | `-handler.ts` | `state-handler.ts` |
|
|
66
|
+
| Condition class | `-condition.ts` | `double-knock-condition.ts` |
|
|
67
|
+
| Test suite | `.test.ts` | `conditions.test.ts` |
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Naming Conventions
|
|
72
|
+
|
|
73
|
+
### No Abbreviations
|
|
74
|
+
|
|
75
|
+
**Variable names, parameter names, and type names must not use abbreviations.**
|
|
76
|
+
|
|
77
|
+
This rule applies everywhere: source files, test files, and any new code.
|
|
78
|
+
|
|
79
|
+
Forbidden examples and their correct replacements:
|
|
80
|
+
|
|
81
|
+
| Forbidden | Use instead |
|
|
82
|
+
|---|---|
|
|
83
|
+
| `s`, `st` for state | `state` |
|
|
84
|
+
| `o`, `opts` for options | `options` |
|
|
85
|
+
| `v` for value | `value` |
|
|
86
|
+
| `req` for request | `request` |
|
|
87
|
+
| `res` for response | `response` |
|
|
88
|
+
| `c` for context | `context` |
|
|
89
|
+
| `e` for error | `error` |
|
|
90
|
+
| `cb` for callback | `callback` |
|
|
91
|
+
| `fn` for function | the actual semantic name |
|
|
92
|
+
| `svc` for service | `service` |
|
|
93
|
+
| `char` for characteristic | `characteristic` |
|
|
94
|
+
| `Char` for Characteristic constructor | `Characteristic` |
|
|
95
|
+
| `Svc` for Service constructor | `Service` |
|
|
96
|
+
| `proc` for process | `process` |
|
|
97
|
+
| `dir` for directory | `directory` |
|
|
98
|
+
| `msg` for message | `message` |
|
|
99
|
+
| `buf` for buffer | `buffer` |
|
|
100
|
+
| `idx` for index | `index` |
|
|
101
|
+
| `len` for length | `length` |
|
|
102
|
+
| `num` for number | `number` or a semantic name |
|
|
103
|
+
| `str` for string | the semantic name |
|
|
104
|
+
| `tmp` for temporary | the semantic name |
|
|
105
|
+
| `args` for arguments | `arguments` (or a semantic name) |
|
|
106
|
+
|
|
107
|
+
**Exception:** loop variables `i`, `j`, `k` in tight numeric loops where the name carries no domain meaning are acceptable. All other names must be descriptive.
|
|
108
|
+
|
|
109
|
+
### Class Names
|
|
110
|
+
|
|
111
|
+
- PascalCase, no abbreviations.
|
|
112
|
+
- Suffix matches the layer: `...Service`, `...Handler`, `...Condition`.
|
|
113
|
+
|
|
114
|
+
### Enum Members
|
|
115
|
+
|
|
116
|
+
- UPPER_SNAKE_CASE (e.g. `SecurityState.TRIGGERED`).
|
|
117
|
+
|
|
118
|
+
### Interface Names
|
|
119
|
+
|
|
120
|
+
- PascalCase, no `I` prefix.
|
|
121
|
+
- Suffix: `...Interface` is not used in the filename's export — the filename carries it.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Architecture: Event-Driven Side Effects
|
|
126
|
+
|
|
127
|
+
The core state machine (`StateHandler`, `TripHandler`, `SwitchHandler`) never calls side-effect services directly. Instead it emits domain events via `EventBusService`:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
StateHandler → bus.emit(EventType.CURRENT_CHANGED, payload)
|
|
131
|
+
↓ ↓ ↓
|
|
132
|
+
AudioService WebhookService CommandService
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Each side-effect service calls `attachToBus(bus)` during construction in `security-system.ts`.
|
|
136
|
+
|
|
137
|
+
**New side effects must follow this pattern** — never add direct calls from handlers to services.
|
|
138
|
+
|
|
139
|
+
Events and their payload types are defined in `src/types/event-type.ts`. The mapping from event to payload is in `src/types/event-payload-map-type.ts`.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Architecture: Condition System
|
|
144
|
+
|
|
145
|
+
All trip-blocking decisions use the `Condition` abstract base class:
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
abstract class Condition {
|
|
149
|
+
abstract readonly name: string;
|
|
150
|
+
abstract evaluate(context: ConditionContext): boolean;
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
`evaluate` returns `true` to **block** the action, `false` to **allow** it.
|
|
155
|
+
|
|
156
|
+
Conditions are instantiated once inside `TripHandler` and evaluated in order. To add a new blocking rule, create a new file in `conditions/`, extend `Condition`, and add it to `TripHandler`.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Architecture: Circular Dependency Resolution
|
|
161
|
+
|
|
162
|
+
`StateHandler` ↔ `TripHandler` and `StateHandler` ↔ `SwitchHandler` are mutually dependent. This is resolved with **setter injection**:
|
|
163
|
+
|
|
164
|
+
1. Construct all handlers independently.
|
|
165
|
+
2. Wire them with `setHandlers()` / `setStateHandler()` after all instances exist.
|
|
166
|
+
|
|
167
|
+
Do not introduce `new` calls between these classes at construction time.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Code Style Rules
|
|
172
|
+
|
|
173
|
+
### File Length
|
|
174
|
+
Maximum **400 lines** per file. Split into smaller focused files if the limit is reached.
|
|
175
|
+
|
|
176
|
+
### Inline Guards
|
|
177
|
+
Use early-return guard clauses rather than deep nesting:
|
|
178
|
+
```typescript
|
|
179
|
+
if (!value) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Imports
|
|
185
|
+
- Use `import type` for types and interfaces that are not needed at runtime.
|
|
186
|
+
- Always use `.js` extensions on relative imports (required for ESM).
|
|
187
|
+
|
|
188
|
+
### Async
|
|
189
|
+
- Use `async`/`await`. Avoid `.then()` chains except when fire-and-forget is intentional.
|
|
190
|
+
|
|
191
|
+
### Error Handling
|
|
192
|
+
- Validate only at system boundaries (config parsing, HTTP input, external storage).
|
|
193
|
+
- Do not add defensive null-checks for values guaranteed by the type system.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Testing
|
|
198
|
+
|
|
199
|
+
- Framework: **Vitest** (`npm test`).
|
|
200
|
+
- Test files live in `src/tests/` and are named `<subject>.test.ts`.
|
|
201
|
+
- Tests cover: conditions (all blocking paths), handler logic, and event-driven interactions.
|
|
202
|
+
- Mock only what is strictly necessary. Prefer structural mocks over full mock libraries.
|
|
203
|
+
- Do not test private methods directly — test through the public API.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Adding a New Feature
|
|
208
|
+
|
|
209
|
+
1. **Types/interfaces first** — create files in `types/` or `interfaces/` before writing logic.
|
|
210
|
+
2. **Condition** — if the feature blocks a trip, add a `Condition` subclass.
|
|
211
|
+
3. **Service** — if the feature is a side effect, implement `attachToBus(bus)` and wire in `security-system.ts`.
|
|
212
|
+
4. **Handler** — if the feature changes state-machine logic, modify the relevant handler.
|
|
213
|
+
5. **Tests** — add a test covering the happy path and the main blocking/edge case.
|
|
214
|
+
6. **No abbreviations** — all new identifiers must be fully spelled out.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ConditionContext } from '../interfaces/condition-context-interface.js';
|
|
2
|
+
import { Condition } from './condition.js';
|
|
3
|
+
/**
|
|
4
|
+
* Blocks a new trip activation when the alarm has already been triggered.
|
|
5
|
+
* Prevents stacking multiple trigger events on an active alarm.
|
|
6
|
+
*/
|
|
7
|
+
export declare class AlreadyTriggeredCondition extends Condition {
|
|
8
|
+
readonly name = "already-triggered";
|
|
9
|
+
evaluate({ state, value }: ConditionContext): boolean;
|
|
10
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SecurityState } from '../types/security-state-type.js';
|
|
2
|
+
import { Condition } from './condition.js';
|
|
3
|
+
/**
|
|
4
|
+
* Blocks a new trip activation when the alarm has already been triggered.
|
|
5
|
+
* Prevents stacking multiple trigger events on an active alarm.
|
|
6
|
+
*/
|
|
7
|
+
export class AlreadyTriggeredCondition extends Condition {
|
|
8
|
+
name = 'already-triggered';
|
|
9
|
+
evaluate({ state, value }) {
|
|
10
|
+
if (!value) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
return state.currentState === SecurityState.TRIGGERED;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=already-triggered-condition.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -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 action while the arm delay countdown is still running.
|
|
5
|
+
* Prevents an intruder from tripping the system before it has fully armed.
|
|
6
|
+
*/
|
|
7
|
+
export declare class ArmingInProgressCondition extends Condition {
|
|
8
|
+
readonly name = "arming-in-progress";
|
|
9
|
+
evaluate({ state, value }: ConditionContext): boolean;
|
|
10
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Condition } from './condition.js';
|
|
2
|
+
/**
|
|
3
|
+
* Blocks a trip action while the arm delay countdown is still running.
|
|
4
|
+
* Prevents an intruder from tripping the system before it has fully armed.
|
|
5
|
+
*/
|
|
6
|
+
export class ArmingInProgressCondition extends Condition {
|
|
7
|
+
name = 'arming-in-progress';
|
|
8
|
+
evaluate({ state, value }) {
|
|
9
|
+
if (!value) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
return state.isArming;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=arming-in-progress-condition.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ConditionContext } from '../interfaces/condition-context-interface.js';
|
|
2
|
+
import type { CharacteristicConstructor } from '../interfaces/hap-types-interface.js';
|
|
3
|
+
import { Condition } from './condition.js';
|
|
4
|
+
/**
|
|
5
|
+
* Blocks arming when an arming-lock switch (global or mode-specific) is active.
|
|
6
|
+
* Does NOT block disarming.
|
|
7
|
+
*/
|
|
8
|
+
export declare class ArmingLockCondition extends Condition {
|
|
9
|
+
private readonly Characteristic;
|
|
10
|
+
readonly name = "arming-lock";
|
|
11
|
+
constructor(Characteristic: CharacteristicConstructor);
|
|
12
|
+
evaluate({ state, services, options }: ConditionContext): boolean;
|
|
13
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { SecurityState } from '../types/security-state-type.js';
|
|
2
|
+
import { Condition } from './condition.js';
|
|
3
|
+
/**
|
|
4
|
+
* Blocks arming when an arming-lock switch (global or mode-specific) is active.
|
|
5
|
+
* Does NOT block disarming.
|
|
6
|
+
*/
|
|
7
|
+
export class ArmingLockCondition extends Condition {
|
|
8
|
+
Characteristic;
|
|
9
|
+
name = 'arming-lock';
|
|
10
|
+
constructor(Characteristic) {
|
|
11
|
+
super();
|
|
12
|
+
this.Characteristic = Characteristic;
|
|
13
|
+
}
|
|
14
|
+
evaluate({ state, services, options }) {
|
|
15
|
+
const hasLockFeature = options.armingLockSwitch || options.armingLockSwitches;
|
|
16
|
+
if (!hasLockFeature) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
const targetState = state.targetState;
|
|
20
|
+
if (targetState === SecurityState.OFF) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
// Check global arming-lock switch.
|
|
24
|
+
const globalOn = services.armingLockSwitchService
|
|
25
|
+
.getCharacteristic(this.Characteristic.On).value;
|
|
26
|
+
if (globalOn) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
// Check mode-specific arming-lock switch.
|
|
30
|
+
switch (targetState) {
|
|
31
|
+
case SecurityState.HOME:
|
|
32
|
+
return Boolean(services.armingLockHomeSwitchService.getCharacteristic(this.Characteristic.On).value);
|
|
33
|
+
case SecurityState.AWAY:
|
|
34
|
+
return Boolean(services.armingLockAwaySwitchService.getCharacteristic(this.Characteristic.On).value);
|
|
35
|
+
case SecurityState.NIGHT:
|
|
36
|
+
return Boolean(services.armingLockNightSwitchService.getCharacteristic(this.Characteristic.On).value);
|
|
37
|
+
default:
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=arming-lock-condition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arming-lock-condition.js","sourceRoot":"","sources":["../../src/conditions/arming-lock-condition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAGhE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;;GAGG;AACH,MAAM,OAAO,mBAAoB,SAAQ,SAAS;IAGnB;IAFpB,IAAI,GAAG,aAAa,CAAC;IAE9B,YAA6B,cAAyC;QACpE,KAAK,EAAE,CAAC;QADmB,mBAAc,GAAd,cAAc,CAA2B;IAEtE,CAAC;IAED,QAAQ,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAoB;QACrD,MAAM,cAAc,GAAG,OAAO,CAAC,gBAAgB,IAAI,OAAO,CAAC,kBAAkB,CAAC;QAC9E,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QACtC,IAAI,WAAW,KAAK,aAAa,CAAC,GAAG,EAAE,CAAC;YACtC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,mCAAmC;QACnC,MAAM,QAAQ,GAAG,QAAQ,CAAC,uBAAuB;aAC9C,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC;QAEnD,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,IAAI,CAAC;QACd,CAAC;QAED,0CAA0C;QAC1C,QAAQ,WAAW,EAAE,CAAC;YACtB,KAAK,aAAa,CAAC,IAAI;gBACrB,OAAO,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAAC,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;YACvG,KAAK,aAAa,CAAC,IAAI;gBACrB,OAAO,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAAC,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;YACvG,KAAK,aAAa,CAAC,KAAK;gBACtB,OAAO,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAAC,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;YACxG;gBACE,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ConditionContext } from '../interfaces/condition-context-interface.js';
|
|
2
|
+
/**
|
|
3
|
+
* Base class for all conditions that can block a trip/trigger action.
|
|
4
|
+
*
|
|
5
|
+
* Extend this class and implement `evaluate()` to return `true` when the
|
|
6
|
+
* condition should prevent the action from proceeding.
|
|
7
|
+
*/
|
|
8
|
+
export declare abstract class Condition {
|
|
9
|
+
abstract readonly name: string;
|
|
10
|
+
/**
|
|
11
|
+
* Returns `true` if this condition blocks the action described by `context`.
|
|
12
|
+
* When `true` is returned the caller must reject the HomeKit request.
|
|
13
|
+
*/
|
|
14
|
+
abstract evaluate(context: ConditionContext): boolean;
|
|
15
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base class for all conditions that can block a trip/trigger action.
|
|
3
|
+
*
|
|
4
|
+
* Extend this class and implement `evaluate()` to return `true` when the
|
|
5
|
+
* condition should prevent the action from proceeding.
|
|
6
|
+
*/
|
|
7
|
+
export class Condition {
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=condition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"condition.js","sourceRoot":"","sources":["../../src/conditions/condition.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,OAAgB,SAAS;CAQ9B"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ConditionContext } from '../interfaces/condition-context-interface.js';
|
|
2
|
+
import { Condition } from './condition.js';
|
|
3
|
+
/**
|
|
4
|
+
* Implements the double-knock pattern: the first activation within a mode that
|
|
5
|
+
* has double-knock enabled sets a "knocked" flag and rejects the trip. Only the
|
|
6
|
+
* second activation within the configured window proceeds.
|
|
7
|
+
*
|
|
8
|
+
* The caller is responsible for managing `state.isKnocked` and the timeout
|
|
9
|
+
* via the `onFirstKnock` callback injected at construction.
|
|
10
|
+
*/
|
|
11
|
+
export declare class DoubleKnockCondition extends Condition {
|
|
12
|
+
private readonly onFirstKnock;
|
|
13
|
+
readonly name = "double-knock";
|
|
14
|
+
/**
|
|
15
|
+
* @param onFirstKnock Called when the first knock is detected.
|
|
16
|
+
* The callback receives the window duration in seconds and a reset function
|
|
17
|
+
* to invoke when the window expires.
|
|
18
|
+
*/
|
|
19
|
+
constructor(onFirstKnock: (seconds: number, onExpire: () => void) => void);
|
|
20
|
+
evaluate({ state, options, value, origin }: ConditionContext): boolean;
|
|
21
|
+
private resolveWindow;
|
|
22
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { SecurityState } from '../types/security-state-type.js';
|
|
2
|
+
import { OriginType } from '../types/origin-type.js';
|
|
3
|
+
import { modeToState } from '../utils/state-util.js';
|
|
4
|
+
import { Condition } from './condition.js';
|
|
5
|
+
/**
|
|
6
|
+
* Implements the double-knock pattern: the first activation within a mode that
|
|
7
|
+
* has double-knock enabled sets a "knocked" flag and rejects the trip. Only the
|
|
8
|
+
* second activation within the configured window proceeds.
|
|
9
|
+
*
|
|
10
|
+
* The caller is responsible for managing `state.isKnocked` and the timeout
|
|
11
|
+
* via the `onFirstKnock` callback injected at construction.
|
|
12
|
+
*/
|
|
13
|
+
export class DoubleKnockCondition extends Condition {
|
|
14
|
+
onFirstKnock;
|
|
15
|
+
name = 'double-knock';
|
|
16
|
+
/**
|
|
17
|
+
* @param onFirstKnock Called when the first knock is detected.
|
|
18
|
+
* The callback receives the window duration in seconds and a reset function
|
|
19
|
+
* to invoke when the window expires.
|
|
20
|
+
*/
|
|
21
|
+
constructor(onFirstKnock) {
|
|
22
|
+
super();
|
|
23
|
+
this.onFirstKnock = onFirstKnock;
|
|
24
|
+
}
|
|
25
|
+
evaluate({ state, options, value, origin }) {
|
|
26
|
+
if (!value || !options.doubleKnock) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
if (origin === OriginType.OVERRIDE_SWITCH) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
if (state.isArming) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
const knockableStates = options.doubleKnockModes.map(m => modeToState(m.toLowerCase()));
|
|
36
|
+
if (!knockableStates.includes(state.currentState)) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
if (state.isKnocked) {
|
|
40
|
+
// Second knock — clear the flag and allow through.
|
|
41
|
+
state.isKnocked = false;
|
|
42
|
+
if (state.doubleKnockTimeout !== null) {
|
|
43
|
+
clearTimeout(state.doubleKnockTimeout);
|
|
44
|
+
state.doubleKnockTimeout = null;
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
// First knock — block and schedule expiry.
|
|
49
|
+
state.isKnocked = true;
|
|
50
|
+
const seconds = this.resolveWindow(state.currentState, options);
|
|
51
|
+
this.onFirstKnock(seconds, () => {
|
|
52
|
+
state.isKnocked = false;
|
|
53
|
+
state.doubleKnockTimeout = null;
|
|
54
|
+
});
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
resolveWindow(currentState, options) {
|
|
58
|
+
if (currentState === SecurityState.HOME && options.homeDoubleKnockSeconds !== null) {
|
|
59
|
+
return options.homeDoubleKnockSeconds;
|
|
60
|
+
}
|
|
61
|
+
if (currentState === SecurityState.AWAY && options.awayDoubleKnockSeconds !== null) {
|
|
62
|
+
return options.awayDoubleKnockSeconds;
|
|
63
|
+
}
|
|
64
|
+
if (currentState === SecurityState.NIGHT && options.nightDoubleKnockSeconds !== null) {
|
|
65
|
+
return options.nightDoubleKnockSeconds;
|
|
66
|
+
}
|
|
67
|
+
return options.doubleKnockSeconds;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=double-knock-condition.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -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 action when the system is disarmed and neither
|
|
5
|
+
* `override_off` nor the override switch is in use.
|
|
6
|
+
*/
|
|
7
|
+
export declare class NotArmedCondition extends Condition {
|
|
8
|
+
readonly name = "not-armed";
|
|
9
|
+
evaluate({ state, options, value, origin }: ConditionContext): boolean;
|
|
10
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { SecurityState } from '../types/security-state-type.js';
|
|
2
|
+
import { OriginType } from '../types/origin-type.js';
|
|
3
|
+
import { Condition } from './condition.js';
|
|
4
|
+
/**
|
|
5
|
+
* Blocks a trip action when the system is disarmed and neither
|
|
6
|
+
* `override_off` nor the override switch is in use.
|
|
7
|
+
*/
|
|
8
|
+
export class NotArmedCondition extends Condition {
|
|
9
|
+
name = 'not-armed';
|
|
10
|
+
evaluate({ state, options, value, origin }) {
|
|
11
|
+
if (!value) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
const isDisarmed = state.currentState === SecurityState.OFF;
|
|
15
|
+
const isNotOverridingOff = !options.overrideOff;
|
|
16
|
+
const isNotOverrideSwitch = origin !== OriginType.OVERRIDE_SWITCH;
|
|
17
|
+
return isDisarmed && isNotOverridingOff && isNotOverrideSwitch;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=not-armed-condition.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Default configuration values applied when a config property is not set. */
|
|
2
|
+
export declare const DEFAULTS: {
|
|
3
|
+
readonly NAME: "Security System";
|
|
4
|
+
readonly SERIAL_NUMBER: "S3CUR1TYSYST3M";
|
|
5
|
+
readonly DEFAULT_MODE: "off";
|
|
6
|
+
readonly ARM_SECONDS: 0;
|
|
7
|
+
readonly TRIGGER_SECONDS: 0;
|
|
8
|
+
readonly RESET_MINUTES: 10;
|
|
9
|
+
readonly DOUBLE_KNOCK_SECONDS: 90;
|
|
10
|
+
readonly TRIPPED_SENSOR_SECONDS: 5;
|
|
11
|
+
readonly TRIGGERED_SENSOR_SECONDS: 5;
|
|
12
|
+
readonly PAUSE_MINUTES: 0;
|
|
13
|
+
readonly AUDIO_LANGUAGE: "en-US";
|
|
14
|
+
readonly TRIP_SWITCH_NAME: "Trip";
|
|
15
|
+
readonly TRIP_HOME_SWITCH_NAME: "Trip Home";
|
|
16
|
+
readonly TRIP_AWAY_SWITCH_NAME: "Trip Away";
|
|
17
|
+
readonly TRIP_NIGHT_SWITCH_NAME: "Trip Night";
|
|
18
|
+
readonly TRIP_OVERRIDE_SWITCH_NAME: "Trip Override";
|
|
19
|
+
readonly MODE_HOME_SWITCH_NAME: "Mode Home";
|
|
20
|
+
readonly MODE_AWAY_SWITCH_NAME: "Mode Away";
|
|
21
|
+
readonly MODE_NIGHT_SWITCH_NAME: "Mode Night";
|
|
22
|
+
readonly MODE_OFF_SWITCH_NAME: "Mode Off";
|
|
23
|
+
readonly MODE_AWAY_EXTENDED_SWITCH_NAME: "Mode Away Extended";
|
|
24
|
+
readonly MODE_PAUSE_SWITCH_NAME: "Mode Pause";
|
|
25
|
+
readonly AUDIO_SWITCH_NAME: "Audio";
|
|
26
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Default configuration values applied when a config property is not set. */
|
|
2
|
+
export const DEFAULTS = {
|
|
3
|
+
NAME: 'Security System',
|
|
4
|
+
SERIAL_NUMBER: 'S3CUR1TYSYST3M',
|
|
5
|
+
DEFAULT_MODE: 'off',
|
|
6
|
+
ARM_SECONDS: 0,
|
|
7
|
+
TRIGGER_SECONDS: 0,
|
|
8
|
+
RESET_MINUTES: 10,
|
|
9
|
+
DOUBLE_KNOCK_SECONDS: 90,
|
|
10
|
+
TRIPPED_SENSOR_SECONDS: 5,
|
|
11
|
+
TRIGGERED_SENSOR_SECONDS: 5,
|
|
12
|
+
PAUSE_MINUTES: 0,
|
|
13
|
+
AUDIO_LANGUAGE: 'en-US',
|
|
14
|
+
// Switch display names
|
|
15
|
+
TRIP_SWITCH_NAME: 'Trip',
|
|
16
|
+
TRIP_HOME_SWITCH_NAME: 'Trip Home',
|
|
17
|
+
TRIP_AWAY_SWITCH_NAME: 'Trip Away',
|
|
18
|
+
TRIP_NIGHT_SWITCH_NAME: 'Trip Night',
|
|
19
|
+
TRIP_OVERRIDE_SWITCH_NAME: 'Trip Override',
|
|
20
|
+
MODE_HOME_SWITCH_NAME: 'Mode Home',
|
|
21
|
+
MODE_AWAY_SWITCH_NAME: 'Mode Away',
|
|
22
|
+
MODE_NIGHT_SWITCH_NAME: 'Mode Night',
|
|
23
|
+
MODE_OFF_SWITCH_NAME: 'Mode Off',
|
|
24
|
+
MODE_AWAY_EXTENDED_SWITCH_NAME: 'Mode Away Extended',
|
|
25
|
+
MODE_PAUSE_SWITCH_NAME: 'Mode Pause',
|
|
26
|
+
AUDIO_SWITCH_NAME: 'Audio',
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=default-constant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-constant.js","sourceRoot":"","sources":["../../src/constants/default-constant.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,iBAAiB;IACvB,aAAa,EAAE,gBAAgB;IAC/B,YAAY,EAAE,KAAK;IACnB,WAAW,EAAE,CAAC;IACd,eAAe,EAAE,CAAC;IAClB,aAAa,EAAE,EAAE;IACjB,oBAAoB,EAAE,EAAE;IACxB,sBAAsB,EAAE,CAAC;IACzB,wBAAwB,EAAE,CAAC;IAC3B,aAAa,EAAE,CAAC;IAChB,cAAc,EAAE,OAAO;IAEvB,uBAAuB;IACvB,gBAAgB,EAAE,MAAM;IACxB,qBAAqB,EAAE,WAAW;IAClC,qBAAqB,EAAE,WAAW;IAClC,sBAAsB,EAAE,YAAY;IACpC,yBAAyB,EAAE,eAAe;IAC1C,qBAAqB,EAAE,WAAW;IAClC,qBAAqB,EAAE,WAAW;IAClC,sBAAsB,EAAE,YAAY;IACpC,oBAAoB,EAAE,UAAU;IAChC,8BAA8B,EAAE,oBAAoB;IACpD,sBAAsB,EAAE,YAAY;IACpC,iBAAiB,EAAE,OAAO;CAClB,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** HomeKit HAP status code returned when an action is not permitted in the current state. */
|
|
2
|
+
export declare const HK_NOT_ALLOWED_IN_CURRENT_STATE = -70412;
|
|
3
|
+
/** Pulse duration in ms used by motion sensors to emit a brief motion event. */
|
|
4
|
+
export declare const SENSOR_PULSE_MS = 750;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** HomeKit HAP status code returned when an action is not permitted in the current state. */
|
|
2
|
+
export const HK_NOT_ALLOWED_IN_CURRENT_STATE = -70412;
|
|
3
|
+
/** Pulse duration in ms used by motion sensors to emit a brief motion event. */
|
|
4
|
+
export const SENSOR_PULSE_MS = 750;
|
|
5
|
+
//# sourceMappingURL=homekit-constant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"homekit-constant.js","sourceRoot":"","sources":["../../src/constants/homekit-constant.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,KAAK,CAAC;AAEtD,gFAAgF;AAChF,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Stable subtype UUIDs for each HomeKit service. Must not change between restarts. */
|
|
2
|
+
export declare const SWITCH_UUIDS: {
|
|
3
|
+
readonly TRIP: "siren-switch";
|
|
4
|
+
readonly TRIP_HOME: "siren-home";
|
|
5
|
+
readonly TRIP_AWAY: "siren-away";
|
|
6
|
+
readonly TRIP_NIGHT: "siren-night";
|
|
7
|
+
readonly TRIP_OVERRIDE: "pink-sheep";
|
|
8
|
+
readonly ARMING_LOCK: "arming-lock";
|
|
9
|
+
readonly ARMING_LOCK_HOME: "arming-lock-home";
|
|
10
|
+
readonly ARMING_LOCK_AWAY: "arming-lock-away";
|
|
11
|
+
readonly ARMING_LOCK_NIGHT: "arming-lock-night";
|
|
12
|
+
readonly MODE_HOME: "mode-home";
|
|
13
|
+
readonly MODE_AWAY: "mode-away";
|
|
14
|
+
readonly MODE_NIGHT: "mode-night";
|
|
15
|
+
readonly MODE_OFF: "mode-off";
|
|
16
|
+
readonly MODE_AWAY_EXTENDED: "mode-away-extended";
|
|
17
|
+
readonly MODE_PAUSE: "mode-pause";
|
|
18
|
+
readonly AUDIO: "kx82r64zN3txDXKFiX9JDi";
|
|
19
|
+
readonly ARMING_SENSOR: "arming-motion-sensor";
|
|
20
|
+
readonly TRIPPED_SENSOR: "siren-tripped";
|
|
21
|
+
readonly TRIGGERED_SENSOR: "siren-triggered";
|
|
22
|
+
readonly RESET_SENSOR: "reset-event";
|
|
23
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Stable subtype UUIDs for each HomeKit service. Must not change between restarts. */
|
|
2
|
+
export const SWITCH_UUIDS = {
|
|
3
|
+
TRIP: 'siren-switch',
|
|
4
|
+
TRIP_HOME: 'siren-home',
|
|
5
|
+
TRIP_AWAY: 'siren-away',
|
|
6
|
+
TRIP_NIGHT: 'siren-night',
|
|
7
|
+
TRIP_OVERRIDE: 'pink-sheep',
|
|
8
|
+
ARMING_LOCK: 'arming-lock',
|
|
9
|
+
ARMING_LOCK_HOME: 'arming-lock-home',
|
|
10
|
+
ARMING_LOCK_AWAY: 'arming-lock-away',
|
|
11
|
+
ARMING_LOCK_NIGHT: 'arming-lock-night',
|
|
12
|
+
MODE_HOME: 'mode-home',
|
|
13
|
+
MODE_AWAY: 'mode-away',
|
|
14
|
+
MODE_NIGHT: 'mode-night',
|
|
15
|
+
MODE_OFF: 'mode-off',
|
|
16
|
+
MODE_AWAY_EXTENDED: 'mode-away-extended',
|
|
17
|
+
MODE_PAUSE: 'mode-pause',
|
|
18
|
+
AUDIO: 'kx82r64zN3txDXKFiX9JDi',
|
|
19
|
+
ARMING_SENSOR: 'arming-motion-sensor',
|
|
20
|
+
TRIPPED_SENSOR: 'siren-tripped',
|
|
21
|
+
TRIGGERED_SENSOR: 'siren-triggered',
|
|
22
|
+
RESET_SENSOR: 'reset-event',
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=switch-uuid-constant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"switch-uuid-constant.js","sourceRoot":"","sources":["../../src/constants/switch-uuid-constant.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,cAAc;IACpB,SAAS,EAAE,YAAY;IACvB,SAAS,EAAE,YAAY;IACvB,UAAU,EAAE,aAAa;IACzB,aAAa,EAAE,YAAY;IAC3B,WAAW,EAAE,aAAa;IAC1B,gBAAgB,EAAE,kBAAkB;IACpC,gBAAgB,EAAE,kBAAkB;IACpC,iBAAiB,EAAE,mBAAmB;IACtC,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,WAAW;IACtB,UAAU,EAAE,YAAY;IACxB,QAAQ,EAAE,UAAU;IACpB,kBAAkB,EAAE,oBAAoB;IACxC,UAAU,EAAE,YAAY;IACxB,KAAK,EAAE,wBAAwB;IAC/B,aAAa,EAAE,sBAAsB;IACrC,cAAc,EAAE,eAAe;IAC/B,gBAAgB,EAAE,iBAAiB;IACnC,YAAY,EAAE,aAAa;CACnB,CAAC"}
|