@nubisco/openbridge 0.29.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.
- package/LICENSE +21 -0
- package/README.md +306 -0
- package/dist/__tests__/homekit-service-type.test.d.ts +2 -0
- package/dist/__tests__/homekit-service-type.test.d.ts.map +1 -0
- package/dist/__tests__/homekit-service-type.test.js +239 -0
- package/dist/__tests__/homekit-service-type.test.js.map +1 -0
- package/dist/__tests__/homekit-visibility.test.d.ts +2 -0
- package/dist/__tests__/homekit-visibility.test.d.ts.map +1 -0
- package/dist/__tests__/homekit-visibility.test.js +157 -0
- package/dist/__tests__/homekit-visibility.test.js.map +1 -0
- package/dist/__tests__/server.test.d.ts +2 -0
- package/dist/__tests__/server.test.d.ts.map +1 -0
- package/dist/__tests__/server.test.js +837 -0
- package/dist/__tests__/server.test.js.map +1 -0
- package/dist/__tests__/timeseries.test.d.ts +2 -0
- package/dist/__tests__/timeseries.test.d.ts.map +1 -0
- package/dist/__tests__/timeseries.test.js +216 -0
- package/dist/__tests__/timeseries.test.js.map +1 -0
- package/dist/auth.d.ts +23 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +171 -0
- package/dist/auth.js.map +1 -0
- package/dist/daemon.d.ts +57 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +636 -0
- package/dist/daemon.js.map +1 -0
- package/dist/homekit-service-type.d.ts +82 -0
- package/dist/homekit-service-type.d.ts.map +1 -0
- package/dist/homekit-service-type.js +184 -0
- package/dist/homekit-service-type.js.map +1 -0
- package/dist/homekit-visibility.d.ts +79 -0
- package/dist/homekit-visibility.d.ts.map +1 -0
- package/dist/homekit-visibility.js +164 -0
- package/dist/homekit-visibility.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/metrics.d.ts +17 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +52 -0
- package/dist/metrics.js.map +1 -0
- package/dist/platform-client.d.ts +42 -0
- package/dist/platform-client.d.ts.map +1 -0
- package/dist/platform-client.js +92 -0
- package/dist/platform-client.js.map +1 -0
- package/dist/server.d.ts +30 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +1744 -0
- package/dist/server.js.map +1 -0
- package/dist/timeseries.d.ts +134 -0
- package/dist/timeseries.d.ts.map +1 -0
- package/dist/timeseries.js +378 -0
- package/dist/timeseries.js.map +1 -0
- package/dist/version.d.ts +4 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +28 -0
- package/dist/version.js.map +1 -0
- package/package.json +79 -0
- package/scripts/entrypoint.sh +82 -0
- package/scripts/fix-node-pty.mjs +22 -0
- package/ui-dist/android-chrome-192x192.png +0 -0
- package/ui-dist/android-chrome-512x512.png +0 -0
- package/ui-dist/apple-touch-icon.png +0 -0
- package/ui-dist/assets/index-Q0sxZHIR.css +32 -0
- package/ui-dist/assets/index-ZZYyAzBo.js +106 -0
- package/ui-dist/favicon-16x16.png +0 -0
- package/ui-dist/favicon-32x32.png +0 -0
- package/ui-dist/favicon.ico +0 -0
- package/ui-dist/fonts/MesloLGLDZNerdFontMono-Bold.woff2 +0 -0
- package/ui-dist/fonts/MesloLGLDZNerdFontMono-BoldItalic.woff2 +0 -0
- package/ui-dist/fonts/MesloLGLDZNerdFontMono-Italic.woff2 +0 -0
- package/ui-dist/fonts/MesloLGLDZNerdFontMono-Regular.woff2 +0 -0
- package/ui-dist/index.html +18 -0
- package/ui-dist/logo.svg +30 -0
- package/ui-dist/nubisco-logo.svg +120 -0
- package/ui-dist/site.webmanifest +19 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nubisco Lda
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<br />
|
|
4
|
+
|
|
5
|
+
<img src="apps/docs/docs/public/logo.svg" alt="OpenBridge" width="96" />
|
|
6
|
+
|
|
7
|
+
<br />
|
|
8
|
+
|
|
9
|
+
# OpenBridge
|
|
10
|
+
|
|
11
|
+
**Local-first home automation bridge for developers. Plugin-based, TypeScript-first, Homebridge-compatible.**
|
|
12
|
+
|
|
13
|
+
[](https://github.com/nubisco/openbridge/actions/workflows/ci.yml)
|
|
14
|
+
[](https://github.com/nubisco/openbridge/releases)
|
|
15
|
+
[](https://www.npmjs.com/package/@nubisco/openbridge)
|
|
16
|
+
[](https://nodejs.org/)
|
|
17
|
+
[](https://pnpm.io/)
|
|
18
|
+
[](LICENSE)
|
|
19
|
+
[](docs/CLA-INDIVIDUAL.md)
|
|
20
|
+
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Table of Contents
|
|
26
|
+
|
|
27
|
+
- [Why OpenBridge?](#why-openbridge)
|
|
28
|
+
- [Features](#features)
|
|
29
|
+
- [Quick Start](#quick-start)
|
|
30
|
+
- [Development](#development)
|
|
31
|
+
- [Writing a Plugin](#writing-a-plugin)
|
|
32
|
+
- [Configuration](#configuration)
|
|
33
|
+
- [HTTP API](#http-api)
|
|
34
|
+
- [Monorepo Structure](#monorepo-structure)
|
|
35
|
+
- [License](#license)
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Why OpenBridge?
|
|
40
|
+
|
|
41
|
+
Homebridge works, but it was designed for a different era. OpenBridge is built from scratch with a developer-first philosophy:
|
|
42
|
+
|
|
43
|
+
- **No cloud, no accounts**: the HAP bridge is published directly on your local network
|
|
44
|
+
- **Clean plugin SDK**: `setup / start / stop` lifecycle, one exported object, full TypeScript types
|
|
45
|
+
- **Drop-in Homebridge compatibility**: existing `platform` plugins work with zero modification
|
|
46
|
+
- **Built-in dashboard**: Vue 3 UI included; no separate install needed
|
|
47
|
+
- **Full HTTP API**: everything the UI does, your scripts can do too
|
|
48
|
+
- **MIT licensed**: no paid tiers, no telemetry, no gatekeeping
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Features
|
|
53
|
+
|
|
54
|
+
- Plugin lifecycle management (load, start, stop, reload)
|
|
55
|
+
- HAP bridge via hap-nodejs: exposes accessories to Apple Home
|
|
56
|
+
- Homebridge platform plugin compatibility shim
|
|
57
|
+
- Vue 3 dashboard: accessories, plugins, logs, config editor, terminal
|
|
58
|
+
- REST API + WebSocket streams for logs and metrics
|
|
59
|
+
- Zod-validated JSON config
|
|
60
|
+
- Structured logger with in-memory buffer
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Quick Start
|
|
65
|
+
|
|
66
|
+
**Requirements:** Node.js 20 or newer.
|
|
67
|
+
|
|
68
|
+
### Install from npm
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
npm install -g @nubisco/openbridge
|
|
72
|
+
openbridge
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Open **http://localhost:8582**: the dashboard is bundled in the package and loads immediately.
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
openbridge --help # usage
|
|
79
|
+
openbridge --port 9000 # run on a different port
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
State lives in `~/.openbridge` (config, plugins, HomeKit pairing). Override it with `OPENBRIDGE_HOME`.
|
|
83
|
+
|
|
84
|
+
### Install from source
|
|
85
|
+
|
|
86
|
+
**Requirements:** Node.js 20+, pnpm 9+, roughly 1 GB of free disk (`node_modules` lands around 720 MB).
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# Install dependencies
|
|
90
|
+
pnpm install
|
|
91
|
+
|
|
92
|
+
# Build the runtime packages and the dashboard
|
|
93
|
+
pnpm build
|
|
94
|
+
|
|
95
|
+
# Start the daemon
|
|
96
|
+
node apps/daemon/dist/index.js
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Open **http://localhost:8582**: the dashboard loads immediately.
|
|
100
|
+
|
|
101
|
+
### Platform notes
|
|
102
|
+
|
|
103
|
+
- **Alpine / musl** is a supported target, on x64 and arm64. The only native
|
|
104
|
+
dependency, `node-pty`, is optional: without it everything runs normally and
|
|
105
|
+
only the dashboard's interactive shell pane is disabled. `npm install -g @nubisco/openbridge`
|
|
106
|
+
will try to build it and silently carry on if no compiler is present.
|
|
107
|
+
To enable the shell pane on Alpine, install `build-base python3 linux-headers`
|
|
108
|
+
before installing OpenBridge.
|
|
109
|
+
- **Building the docs site needs memory.** `pnpm build` covers the runtime
|
|
110
|
+
packages and the dashboard only. The VitePress docs site is built separately
|
|
111
|
+
with `pnpm build:docs` and needs more than 1 GB of RAM, so it is kept out of
|
|
112
|
+
the default build to keep OpenBridge installable on small SBCs.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Development
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# Build all packages once
|
|
120
|
+
pnpm build
|
|
121
|
+
|
|
122
|
+
# Start the daemon in watch mode (terminal 1)
|
|
123
|
+
pnpm --filter @nubisco/openbridge dev
|
|
124
|
+
|
|
125
|
+
# Start the UI dev server with HMR (terminal 2)
|
|
126
|
+
pnpm --filter @nubisco/openbridge-ui dev
|
|
127
|
+
# → UI at http://localhost:5174 (proxies /api and /ws to daemon on :8582)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
To rebuild individual packages during development:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
pnpm --filter @nubisco/openbridge-core dev # watch mode
|
|
134
|
+
pnpm --filter @nubisco/openbridge-logger dev
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Writing a Plugin
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
import { definePlugin } from '@nubisco/openbridge-sdk'
|
|
143
|
+
|
|
144
|
+
export default definePlugin({
|
|
145
|
+
manifest: {
|
|
146
|
+
name: 'my-plugin',
|
|
147
|
+
version: '1.0.0',
|
|
148
|
+
description: 'Does something useful',
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
async setup(ctx) {
|
|
152
|
+
ctx.log.info('Setup: runs once at load time')
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
async start(ctx) {
|
|
156
|
+
ctx.log.info('Start: begin plugin operation')
|
|
157
|
+
// ctx.config has values from config.json
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
async stop(ctx) {
|
|
161
|
+
ctx.log.info('Stop: clean up resources')
|
|
162
|
+
},
|
|
163
|
+
})
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
For a full guide, see the [Plugin Development docs](apps/docs/docs/guide/creating-a-plugin.md).
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Configuration
|
|
171
|
+
|
|
172
|
+
Default config path: `~/.openbridge/config.json`
|
|
173
|
+
|
|
174
|
+
```json
|
|
175
|
+
{
|
|
176
|
+
"bridge": {
|
|
177
|
+
"name": "My OpenBridge",
|
|
178
|
+
"port": 8582,
|
|
179
|
+
"logLevel": "info"
|
|
180
|
+
},
|
|
181
|
+
"plugins": [
|
|
182
|
+
{
|
|
183
|
+
"name": "my-plugin",
|
|
184
|
+
"enabled": true,
|
|
185
|
+
"config": {
|
|
186
|
+
"interval": 5000
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
]
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
See [Configuration Reference](apps/docs/docs/guide/config-reference.md) for all options.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## HTTP API
|
|
198
|
+
|
|
199
|
+
The daemon exposes a REST API on port 8582:
|
|
200
|
+
|
|
201
|
+
| Method | Path | Description |
|
|
202
|
+
| ------ | -------------------------- | ---------------------------------------- |
|
|
203
|
+
| GET | `/api/health` | Daemon status, version, and capabilities |
|
|
204
|
+
| GET | `/api/plugins` | List all loaded plugins |
|
|
205
|
+
| GET | `/api/plugins/:id` | Get a single plugin |
|
|
206
|
+
| POST | `/api/plugins/:id/start` | Start a plugin |
|
|
207
|
+
| POST | `/api/plugins/:id/stop` | Stop a plugin |
|
|
208
|
+
| GET | `/api/accessories` | List all HAP accessories |
|
|
209
|
+
| GET | `/api/logs?plugin=&limit=` | Retrieve log entries |
|
|
210
|
+
| WS | `/ws/logs` | Stream live logs |
|
|
211
|
+
| WS | `/ws/shell` | Interactive terminal (requires node-pty) |
|
|
212
|
+
|
|
213
|
+
`GET /api/health` reports which optional features are present:
|
|
214
|
+
|
|
215
|
+
```json
|
|
216
|
+
{ "status": "ok", "version": "0.29.0", "capabilities": { "shell": true, "ui": true } }
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
`capabilities.shell` is `false` when the optional `node-pty` dependency is not
|
|
220
|
+
installed; the interactive terminal is then unavailable and nothing else is affected.
|
|
221
|
+
|
|
222
|
+
Full reference: [HTTP API docs](apps/docs/docs/guide/api-reference.md).
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Monorepo Structure
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
openbridge/
|
|
230
|
+
apps/
|
|
231
|
+
daemon/ Node.js runtime: plugin loader + Fastify HTTP API + HAP bridge
|
|
232
|
+
(published to npm as `@nubisco/openbridge`, dashboard bundled in)
|
|
233
|
+
ui/ Vue 3 dashboard: accessories, plugins, logs, config, terminal
|
|
234
|
+
cli/ Standalone CLI scaffold (not published; the daemon provides `openbridge`)
|
|
235
|
+
docs/ VitePress documentation site
|
|
236
|
+
packages/
|
|
237
|
+
core/ Plugin types, registry, lifecycle, loader
|
|
238
|
+
logger/ Structured logging with in-memory buffer + WebSocket
|
|
239
|
+
config/ Zod-validated JSON config
|
|
240
|
+
sdk/ definePlugin() helper for plugin authors
|
|
241
|
+
compatibility-homebridge/ Homebridge platform plugin adapter
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Published packages
|
|
245
|
+
|
|
246
|
+
Everything below is released together, under one version, from a single git tag.
|
|
247
|
+
|
|
248
|
+
| npm package | Source |
|
|
249
|
+
| ---------------------------------------------- | ----------------------------------- |
|
|
250
|
+
| `@nubisco/openbridge` | `apps/daemon` |
|
|
251
|
+
| `@nubisco/openbridge-core` | `packages/core` |
|
|
252
|
+
| `@nubisco/openbridge-logger` | `packages/logger` |
|
|
253
|
+
| `@nubisco/openbridge-config` | `packages/config` |
|
|
254
|
+
| `@nubisco/openbridge-sdk` | `packages/sdk` |
|
|
255
|
+
| `@nubisco/openbridge-compatibility-homebridge` | `packages/compatibility-homebridge` |
|
|
256
|
+
|
|
257
|
+
### Releasing
|
|
258
|
+
|
|
259
|
+
Releases are automated and should not be run by hand.
|
|
260
|
+
|
|
261
|
+
1. Merging to `master` runs semantic-release, which bumps the version, writes the
|
|
262
|
+
CHANGELOG entry, commits and pushes a `vX.Y.Z` tag.
|
|
263
|
+
2. That tag triggers [`npm-publish.yml`](.github/workflows/npm-publish.yml), which
|
|
264
|
+
builds, packs each package with `pnpm pack` and publishes the tarballs to npm.
|
|
265
|
+
|
|
266
|
+
Authentication uses **npm trusted publishing** (OIDC), so there is no npm token
|
|
267
|
+
stored in the repository. Each package has this workflow registered as a trusted
|
|
268
|
+
publisher on npmjs.com, and npm accepts publishes only from it. Provenance
|
|
269
|
+
attestations are generated automatically, so every release is cryptographically
|
|
270
|
+
attested to the commit and workflow run it was built from, and CI fails the release
|
|
271
|
+
if an attestation is missing.
|
|
272
|
+
|
|
273
|
+
To inspect exactly what would be published, without publishing anything:
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
pnpm pack:check
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
That builds, stages the tarballs and asserts each one carries `dist`, a README and
|
|
280
|
+
a LICENSE, and that no `workspace:*` range survived into the published manifest.
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## Contributing
|
|
285
|
+
|
|
286
|
+
Contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request. All contributions are made under the [Individual CLA](docs/CLA-INDIVIDUAL.md).
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Security
|
|
291
|
+
|
|
292
|
+
To report a vulnerability, please use [GitHub Security Advisories](https://github.com/nubisco/openbridge/security/advisories/new) rather than opening a public issue. See [SECURITY.md](.github/SECURITY.md) for the full policy.
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Support this project
|
|
297
|
+
|
|
298
|
+
If OpenBridge is useful to you, consider [sponsoring the maintainer](https://github.com/sponsors/joseporto).
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## License
|
|
303
|
+
|
|
304
|
+
MIT: see [LICENSE](LICENSE).
|
|
305
|
+
|
|
306
|
+
Part of the [Nubisco](https://nubisco.io) ecosystem.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"homekit-service-type.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/homekit-service-type.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { mkdtempSync, rmSync, readFileSync, existsSync } from 'fs';
|
|
3
|
+
import { tmpdir } from 'os';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { HomeKitServiceTypes, CONVERTIBLE_SERVICES, isConvertible } from '../homekit-service-type.js';
|
|
6
|
+
import { HomeKitVisibility } from '../homekit-visibility.js';
|
|
7
|
+
let dir;
|
|
8
|
+
let path;
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
dir = mkdtempSync(join(tmpdir(), 'ob-hkst-'));
|
|
11
|
+
path = join(dir, 'homekit-service-types.json');
|
|
12
|
+
});
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
rmSync(dir, { recursive: true, force: true });
|
|
15
|
+
});
|
|
16
|
+
const SWITCH = CONVERTIBLE_SERVICES.switch.uuid;
|
|
17
|
+
const LIGHT = CONVERTIBLE_SERVICES.light.uuid;
|
|
18
|
+
const ON = '00000025-0000-1000-8000-0026BB765291';
|
|
19
|
+
const THERMOSTAT = '0000004A-0000-1000-8000-0026BB765291';
|
|
20
|
+
/**
|
|
21
|
+
* Minimal stand-ins for the hap-nodejs surface the swap touches: a
|
|
22
|
+
* characteristic that records writes and notifies `change` listeners, and a
|
|
23
|
+
* service holding one.
|
|
24
|
+
*/
|
|
25
|
+
function fakeCharacteristic(uuid, value = false) {
|
|
26
|
+
const listeners = [];
|
|
27
|
+
return {
|
|
28
|
+
UUID: uuid,
|
|
29
|
+
value,
|
|
30
|
+
sets: [],
|
|
31
|
+
getHandler: null,
|
|
32
|
+
setHandler: null,
|
|
33
|
+
setValue(v) {
|
|
34
|
+
this.sets.push(v);
|
|
35
|
+
this.value = v;
|
|
36
|
+
return this;
|
|
37
|
+
},
|
|
38
|
+
updateValue(v) {
|
|
39
|
+
this.value = v;
|
|
40
|
+
return this;
|
|
41
|
+
},
|
|
42
|
+
on(event, cb) {
|
|
43
|
+
if (event === 'change')
|
|
44
|
+
listeners.push(cb);
|
|
45
|
+
return this;
|
|
46
|
+
},
|
|
47
|
+
onGet(cb) {
|
|
48
|
+
this.getHandler = cb;
|
|
49
|
+
return this;
|
|
50
|
+
},
|
|
51
|
+
onSet(cb) {
|
|
52
|
+
this.setHandler = cb;
|
|
53
|
+
return this;
|
|
54
|
+
},
|
|
55
|
+
emitChange(newValue) {
|
|
56
|
+
this.value = newValue;
|
|
57
|
+
listeners.forEach((cb) => cb({ newValue }));
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function fakeService(uuid, displayName, charUuid = ON) {
|
|
62
|
+
const characteristics = [fakeCharacteristic(charUuid)];
|
|
63
|
+
return {
|
|
64
|
+
UUID: uuid,
|
|
65
|
+
displayName,
|
|
66
|
+
subtype: undefined,
|
|
67
|
+
characteristics,
|
|
68
|
+
getCharacteristic() {
|
|
69
|
+
return characteristics[0];
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function fakeAccessory(uuid, services) {
|
|
74
|
+
return {
|
|
75
|
+
UUID: uuid,
|
|
76
|
+
displayName: uuid,
|
|
77
|
+
category: 8,
|
|
78
|
+
services,
|
|
79
|
+
addService(svc) {
|
|
80
|
+
this.services.push(svc);
|
|
81
|
+
return svc;
|
|
82
|
+
},
|
|
83
|
+
removeService(svc) {
|
|
84
|
+
this.services = this.services.filter((s) => s !== svc);
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/** hap-nodejs stand-in exposing just Service.<Name> and Characteristic.On. */
|
|
89
|
+
function fakeHap() {
|
|
90
|
+
class Svc {
|
|
91
|
+
UUID;
|
|
92
|
+
displayName;
|
|
93
|
+
subtype;
|
|
94
|
+
characteristics;
|
|
95
|
+
constructor(uuid, displayName, subtype) {
|
|
96
|
+
this.UUID = uuid;
|
|
97
|
+
this.displayName = displayName;
|
|
98
|
+
this.subtype = subtype;
|
|
99
|
+
this.characteristics = [fakeCharacteristic(ON)];
|
|
100
|
+
}
|
|
101
|
+
getCharacteristic() {
|
|
102
|
+
return this.characteristics[0];
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
Characteristic: { On: { UUID: ON } },
|
|
107
|
+
Service: {
|
|
108
|
+
Lightbulb: class extends Svc {
|
|
109
|
+
constructor(name, subtype) {
|
|
110
|
+
super(LIGHT, name, subtype);
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
Switch: class extends Svc {
|
|
114
|
+
constructor(name, subtype) {
|
|
115
|
+
super(SWITCH, name, subtype);
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
describe('convertibility', () => {
|
|
122
|
+
it('accepts the On-based service family', () => {
|
|
123
|
+
for (const def of Object.values(CONVERTIBLE_SERVICES)) {
|
|
124
|
+
expect(isConvertible(def.uuid)).toBe(true);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
it('rejects services that are not built on On', () => {
|
|
128
|
+
// A thermostat has no On characteristic, so presenting it as a lightbulb
|
|
129
|
+
// would silently drop everything that makes it a thermostat.
|
|
130
|
+
expect(isConvertible(THERMOSTAT)).toBe(false);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
describe('persistence', () => {
|
|
134
|
+
it('round trips an override across instances', () => {
|
|
135
|
+
const a = new HomeKitServiceTypes(path);
|
|
136
|
+
a.set('pool', SWITCH, 'light');
|
|
137
|
+
expect(existsSync(path)).toBe(true);
|
|
138
|
+
expect(new HomeKitServiceTypes(path).get('pool', SWITCH)).toBe('light');
|
|
139
|
+
});
|
|
140
|
+
it('clearing an override removes the entry rather than storing a null', () => {
|
|
141
|
+
const s = new HomeKitServiceTypes(path);
|
|
142
|
+
s.set('pool', SWITCH, 'light');
|
|
143
|
+
s.set('pool', SWITCH, null);
|
|
144
|
+
expect(s.get('pool', SWITCH)).toBeNull();
|
|
145
|
+
expect(JSON.parse(readFileSync(path, 'utf8'))).toEqual({});
|
|
146
|
+
});
|
|
147
|
+
it('treats selecting the service’s own type as clearing it', () => {
|
|
148
|
+
const s = new HomeKitServiceTypes(path);
|
|
149
|
+
s.set('pool', SWITCH, 'switch');
|
|
150
|
+
expect(s.get('pool', SWITCH)).toBeNull();
|
|
151
|
+
});
|
|
152
|
+
it('survives a corrupt store by falling back to plugin defaults', () => {
|
|
153
|
+
const s = new HomeKitServiceTypes(join(dir, 'missing.json'));
|
|
154
|
+
expect(s.all()).toEqual({});
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
describe('applying an override', () => {
|
|
158
|
+
it('presents a Switch as a Lightbulb and re-categorises the accessory', () => {
|
|
159
|
+
const s = new HomeKitServiceTypes(path, fakeHap());
|
|
160
|
+
s.set('pool', SWITCH, 'light');
|
|
161
|
+
const acc = fakeAccessory('pool', [fakeService(SWITCH, 'Pool Light')]);
|
|
162
|
+
s.apply(acc);
|
|
163
|
+
expect(acc.services).toHaveLength(1);
|
|
164
|
+
expect(acc.services[0].UUID).toBe(LIGHT);
|
|
165
|
+
expect(acc.services[0].displayName).toBe('Pool Light');
|
|
166
|
+
expect(acc.category).toBe(CONVERTIBLE_SERVICES.light.category);
|
|
167
|
+
});
|
|
168
|
+
it('forwards HomeKit writes to the original characteristic, so the plugin still acts on them', async () => {
|
|
169
|
+
const s = new HomeKitServiceTypes(path, fakeHap());
|
|
170
|
+
s.set('pool', SWITCH, 'light');
|
|
171
|
+
const original = fakeService(SWITCH, 'Pool Light');
|
|
172
|
+
const originalOn = original.characteristics[0];
|
|
173
|
+
const acc = fakeAccessory('pool', [original]);
|
|
174
|
+
s.apply(acc);
|
|
175
|
+
await acc.services[0].getCharacteristic().setHandler(true);
|
|
176
|
+
expect(originalOn.sets).toEqual([true]);
|
|
177
|
+
});
|
|
178
|
+
it('mirrors plugin-side updates onto the replacement service', () => {
|
|
179
|
+
const s = new HomeKitServiceTypes(path, fakeHap());
|
|
180
|
+
s.set('pool', SWITCH, 'light');
|
|
181
|
+
const original = fakeService(SWITCH, 'Pool Light');
|
|
182
|
+
const acc = fakeAccessory('pool', [original]);
|
|
183
|
+
s.apply(acc);
|
|
184
|
+
original.characteristics[0].emitChange(true);
|
|
185
|
+
expect(acc.services[0].getCharacteristic().value).toBe(true);
|
|
186
|
+
});
|
|
187
|
+
it('leaves non-convertible services alone', () => {
|
|
188
|
+
const s = new HomeKitServiceTypes(path, fakeHap());
|
|
189
|
+
// Written directly: set() would accept this, but apply() must refuse it.
|
|
190
|
+
s.set('thermo', THERMOSTAT, 'light');
|
|
191
|
+
const acc = fakeAccessory('thermo', [fakeService(THERMOSTAT, 'Heating', 'other')]);
|
|
192
|
+
s.apply(acc);
|
|
193
|
+
expect(acc.services[0].UUID).toBe(THERMOSTAT);
|
|
194
|
+
expect(acc.category).toBe(8);
|
|
195
|
+
});
|
|
196
|
+
it('leaves accessories with no override untouched', () => {
|
|
197
|
+
const s = new HomeKitServiceTypes(path, fakeHap());
|
|
198
|
+
const acc = fakeAccessory('other', [fakeService(SWITCH, 'Garden Tap')]);
|
|
199
|
+
s.apply(acc);
|
|
200
|
+
expect(acc.services[0].UUID).toBe(SWITCH);
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
describe('bridge integration', () => {
|
|
204
|
+
it('applies overrides on the way to the bridge, before HomeKit sees the accessory', () => {
|
|
205
|
+
const types = new HomeKitServiceTypes(path, fakeHap());
|
|
206
|
+
types.set('pool', SWITCH, 'light');
|
|
207
|
+
const bridge = {
|
|
208
|
+
added: [],
|
|
209
|
+
addBridgedAccessory(acc) {
|
|
210
|
+
this.added.push(acc);
|
|
211
|
+
return acc;
|
|
212
|
+
},
|
|
213
|
+
removeBridgedAccessory() { },
|
|
214
|
+
};
|
|
215
|
+
const wrapped = new HomeKitVisibility(join(dir, 'hidden.json'), null, types).wrapBridge(bridge);
|
|
216
|
+
wrapped.addBridgedAccessory(fakeAccessory('pool', [fakeService(SWITCH, 'Pool Light')]));
|
|
217
|
+
expect(bridge.added[0].services[0].UUID).toBe(LIGHT);
|
|
218
|
+
});
|
|
219
|
+
it('does not bother re-typing an accessory that is hidden anyway', () => {
|
|
220
|
+
const types = new HomeKitServiceTypes(path, fakeHap());
|
|
221
|
+
types.set('pool', SWITCH, 'light');
|
|
222
|
+
const hiddenPath = join(dir, 'hidden.json');
|
|
223
|
+
const visibility = new HomeKitVisibility(hiddenPath, null, types);
|
|
224
|
+
visibility.setVisible('pool', false);
|
|
225
|
+
const bridge = {
|
|
226
|
+
added: [],
|
|
227
|
+
addBridgedAccessory(acc) {
|
|
228
|
+
this.added.push(acc);
|
|
229
|
+
return acc;
|
|
230
|
+
},
|
|
231
|
+
removeBridgedAccessory() { },
|
|
232
|
+
};
|
|
233
|
+
const acc = fakeAccessory('pool', [fakeService(SWITCH, 'Pool Light')]);
|
|
234
|
+
visibility.wrapBridge(bridge).addBridgedAccessory(acc);
|
|
235
|
+
expect(bridge.added).toHaveLength(0);
|
|
236
|
+
expect(acc.services[0].UUID).toBe(SWITCH);
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
//# sourceMappingURL=homekit-service-type.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"homekit-service-type.test.js","sourceRoot":"","sources":["../../src/__tests__/homekit-service-type.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"homekit-visibility.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/homekit-visibility.test.ts"],"names":[],"mappings":""}
|