@homebridge-plugins/homebridge-resideo 3.1.2 → 3.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +10 -23
- package/config.schema.json +32 -28
- package/dist/homebridge-ui/server.d.ts.map +1 -1
- package/dist/homebridge-ui/server.js +42 -19
- package/dist/homebridge-ui/server.js.map +1 -1
- package/dist/homebridge-ui/server.test.d.ts +2 -0
- package/dist/homebridge-ui/server.test.d.ts.map +1 -0
- package/dist/homebridge-ui/server.test.js +37 -0
- package/dist/homebridge-ui/server.test.js.map +1 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## v3.1.4 (2026-07-20)
|
|
2
|
+
|
|
3
|
+
### Changed
|
|
4
|
+
|
|
5
|
+
- fix(ui): use the working resideo api host for login, so the setup flow stops failing on an expired certificate (#927) (@cowboydaks) (@carlosfranceschi)
|
|
6
|
+
- fix(ui): exchange the login code with fetch instead of shelling out to curl
|
|
7
|
+
|
|
8
|
+
## v3.1.3 (2026-07-20)
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- fix(schema): give the logging levels clear, distinct names
|
|
13
|
+
- chore(deps): dependency updates
|
|
14
|
+
|
|
1
15
|
## v3.1.2 (2026-07-18)
|
|
2
16
|
|
|
3
17
|
### Changed
|
package/README.md
CHANGED
|
@@ -21,32 +21,18 @@ Homebridge plugin to integrate Resideo (Honeywell Home) devices into HomeKit
|
|
|
21
21
|
- requires a (free) Resideo developer account to work - this is separate from the Resideo account you use in the Resideo app
|
|
22
22
|
- connects to the Resideo cloud to discover and control your devices
|
|
23
23
|
|
|
24
|
-
###
|
|
25
|
-
|
|
26
|
-
- Installation
|
|
27
|
-
- Search for "Resideo" on the plugin screen of the [Homebridge UI](https://github.com/homebridge/homebridge-config-ui-x) and click **Install**.
|
|
28
|
-
- Configuration
|
|
29
|
-
1. Login or create an account at the [Resideo developer portal](https://developer.honeywellhome.com/user).
|
|
30
|
-
2. Click **Create New App**, give your application a name, and copy the hostname shown in the plugin settings intro into the **Callback URL** field.
|
|
31
|
-
|
|
32
|
-
<p align="center">
|
|
33
|
-
|
|
34
|
-
<img alt="Resideo developer portal app setup" src="https://user-images.githubusercontent.com/9875439/192078620-6998511c-1c11-4e06-b7e1-475b22ef5180.png" width="300px">
|
|
35
|
-
|
|
36
|
-
</p>
|
|
37
|
-
|
|
38
|
-
3. Enter the generated consumer key and secret into the plugin settings and click **Link Account**.
|
|
39
|
-
|
|
40
|
-
<p align="center">
|
|
24
|
+
### Prerequisites
|
|
41
25
|
|
|
42
|
-
|
|
26
|
+
- To use this plugin, you will need to already have:
|
|
27
|
+
- [Node](https://nodejs.org): latest version of `v22` or `v24` - any other major version is not supported.
|
|
28
|
+
- [Homebridge](https://homebridge.io): `v2` - refer to link for more information and installation instructions.
|
|
43
29
|
|
|
44
|
-
|
|
30
|
+
### Setup
|
|
45
31
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
32
|
+
- [Installation](https://github.com/homebridge-plugins/homebridge-resideo/wiki/Installation)
|
|
33
|
+
- [Configuration](https://github.com/homebridge-plugins/homebridge-resideo/wiki/Configuration)
|
|
34
|
+
- [Beta Version](https://github.com/homebridge-plugins/homebridge-resideo/wiki/Beta-Version)
|
|
35
|
+
- [Node Version](https://github.com/homebridge-plugins/homebridge-resideo/wiki/Node-Version)
|
|
50
36
|
|
|
51
37
|
### Supported Devices
|
|
52
38
|
|
|
@@ -63,6 +49,7 @@ Homebridge plugin to integrate Resideo (Honeywell Home) devices into HomeKit
|
|
|
63
49
|
|
|
64
50
|
### Help/About
|
|
65
51
|
|
|
52
|
+
- [Common Errors](https://github.com/homebridge-plugins/homebridge-resideo/wiki/Common-Errors)
|
|
66
53
|
- [Support Request](https://github.com/homebridge-plugins/homebridge-resideo/issues/new/choose)
|
|
67
54
|
- [Changelog](https://github.com/homebridge-plugins/homebridge-resideo/blob/latest/CHANGELOG.md)
|
|
68
55
|
- [About Me](https://github.com/sponsors/bwp91)
|
package/config.schema.json
CHANGED
|
@@ -301,25 +301,26 @@
|
|
|
301
301
|
}
|
|
302
302
|
},
|
|
303
303
|
"logging": {
|
|
304
|
-
"title": "Room Sensor Thermostat Logging Override
|
|
304
|
+
"title": "Room Sensor Thermostat Logging Level Override",
|
|
305
|
+
"description": "Overrides the plugin logging level for this room sensor thermostat only. None turns off all messages from this plugin. Standard shows normal activity, warnings and errors. Debug adds detailed messages, and is what to use when reporting a problem. Default behaves the same as Standard.",
|
|
305
306
|
"type": "string",
|
|
306
307
|
"required": true,
|
|
307
308
|
"default": "",
|
|
308
309
|
"oneOf": [
|
|
309
310
|
{
|
|
310
|
-
"title": "Default
|
|
311
|
+
"title": "Default (same as Standard)",
|
|
311
312
|
"enum": [""]
|
|
312
313
|
},
|
|
313
314
|
{
|
|
314
|
-
"title": "
|
|
315
|
-
"enum": ["
|
|
315
|
+
"title": "None",
|
|
316
|
+
"enum": ["none"]
|
|
316
317
|
},
|
|
317
318
|
{
|
|
318
|
-
"title": "
|
|
319
|
-
"enum": ["
|
|
319
|
+
"title": "Standard",
|
|
320
|
+
"enum": ["standard"]
|
|
320
321
|
},
|
|
321
322
|
{
|
|
322
|
-
"title": "Debug
|
|
323
|
+
"title": "Debug",
|
|
323
324
|
"enum": ["debug"]
|
|
324
325
|
}
|
|
325
326
|
],
|
|
@@ -386,25 +387,26 @@
|
|
|
386
387
|
}
|
|
387
388
|
},
|
|
388
389
|
"logging": {
|
|
389
|
-
"title": "Room Sensor Logging Override
|
|
390
|
+
"title": "Room Sensor Logging Level Override",
|
|
391
|
+
"description": "Overrides the plugin logging level for this room sensor only. None turns off all messages from this plugin. Standard shows normal activity, warnings and errors. Debug adds detailed messages, and is what to use when reporting a problem. Default behaves the same as Standard.",
|
|
390
392
|
"type": "string",
|
|
391
393
|
"required": true,
|
|
392
394
|
"default": "",
|
|
393
395
|
"oneOf": [
|
|
394
396
|
{
|
|
395
|
-
"title": "Default
|
|
397
|
+
"title": "Default (same as Standard)",
|
|
396
398
|
"enum": [""]
|
|
397
399
|
},
|
|
398
400
|
{
|
|
399
|
-
"title": "
|
|
400
|
-
"enum": ["
|
|
401
|
+
"title": "None",
|
|
402
|
+
"enum": ["none"]
|
|
401
403
|
},
|
|
402
404
|
{
|
|
403
|
-
"title": "
|
|
404
|
-
"enum": ["
|
|
405
|
+
"title": "Standard",
|
|
406
|
+
"enum": ["standard"]
|
|
405
407
|
},
|
|
406
408
|
{
|
|
407
|
-
"title": "Debug
|
|
409
|
+
"title": "Debug",
|
|
408
410
|
"enum": ["debug"]
|
|
409
411
|
}
|
|
410
412
|
],
|
|
@@ -490,25 +492,26 @@
|
|
|
490
492
|
}
|
|
491
493
|
},
|
|
492
494
|
"logging": {
|
|
493
|
-
"title": "Device Logging Override
|
|
495
|
+
"title": "Device Logging Level Override",
|
|
496
|
+
"description": "Overrides the plugin logging level for this device only. None turns off all messages from this plugin. Standard shows normal activity, warnings and errors. Debug adds detailed messages, and is what to use when reporting a problem. Default behaves the same as Standard.",
|
|
494
497
|
"type": "string",
|
|
495
498
|
"required": true,
|
|
496
499
|
"default": "",
|
|
497
500
|
"oneOf": [
|
|
498
501
|
{
|
|
499
|
-
"title": "Default
|
|
502
|
+
"title": "Default (same as Standard)",
|
|
500
503
|
"enum": [""]
|
|
501
504
|
},
|
|
502
505
|
{
|
|
503
|
-
"title": "
|
|
504
|
-
"enum": ["
|
|
506
|
+
"title": "None",
|
|
507
|
+
"enum": ["none"]
|
|
505
508
|
},
|
|
506
509
|
{
|
|
507
|
-
"title": "
|
|
508
|
-
"enum": ["
|
|
510
|
+
"title": "Standard",
|
|
511
|
+
"enum": ["standard"]
|
|
509
512
|
},
|
|
510
513
|
{
|
|
511
|
-
"title": "Debug
|
|
514
|
+
"title": "Debug",
|
|
512
515
|
"enum": ["debug"]
|
|
513
516
|
}
|
|
514
517
|
],
|
|
@@ -534,25 +537,26 @@
|
|
|
534
537
|
"description": "Indicates the number of seconds between pushes to Honewell Home API."
|
|
535
538
|
},
|
|
536
539
|
"logging": {
|
|
537
|
-
"title": "Logging
|
|
540
|
+
"title": "Plugin Logging Level",
|
|
541
|
+
"description": "None turns off all messages from this plugin. Standard shows normal activity, warnings and errors. Debug adds detailed messages, and is what to use when reporting a problem. Default behaves the same as Standard.",
|
|
538
542
|
"type": "string",
|
|
539
543
|
"required": true,
|
|
540
544
|
"default": "",
|
|
541
545
|
"oneOf": [
|
|
542
546
|
{
|
|
543
|
-
"title": "Default
|
|
547
|
+
"title": "Default (same as Standard)",
|
|
544
548
|
"enum": [""]
|
|
545
549
|
},
|
|
546
550
|
{
|
|
547
|
-
"title": "
|
|
548
|
-
"enum": ["
|
|
551
|
+
"title": "None",
|
|
552
|
+
"enum": ["none"]
|
|
549
553
|
},
|
|
550
554
|
{
|
|
551
|
-
"title": "
|
|
552
|
-
"enum": ["
|
|
555
|
+
"title": "Standard",
|
|
556
|
+
"enum": ["standard"]
|
|
553
557
|
},
|
|
554
558
|
{
|
|
555
|
-
"title": "Debug
|
|
559
|
+
"title": "Debug",
|
|
556
560
|
"enum": ["debug"]
|
|
557
561
|
}
|
|
558
562
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/homebridge-ui/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/homebridge-ui/server.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAA;AAwBtE,qBAAa,cAAe,SAAQ,wBAAwB;IACnD,GAAG,EAAG,MAAM,CAAA;IACZ,MAAM,EAAG,MAAM,CAAA;IACf,QAAQ,EAAG,MAAM,CAAA;;CA2IzB"}
|
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import { Buffer } from 'node:buffer';
|
|
2
|
-
import { exec as execCb } from 'node:child_process';
|
|
3
2
|
import fs from 'node:fs';
|
|
4
3
|
import http from 'node:http';
|
|
5
|
-
import util from 'node:util';
|
|
6
4
|
/* eslint-disable no-console */
|
|
7
5
|
import { HomebridgePluginUiServer } from '@homebridge/plugin-ui-utils';
|
|
8
|
-
|
|
6
|
+
import { AuthorizeURL, TokenURL } from '../settings.js';
|
|
7
|
+
/**
|
|
8
|
+
* Escape text that is about to be written into the setup page.
|
|
9
|
+
*
|
|
10
|
+
* The failure messages come from Resideo, so they are not ours to trust with
|
|
11
|
+
* raw HTML.
|
|
12
|
+
*/
|
|
13
|
+
function escapeHtml(value) {
|
|
14
|
+
return value
|
|
15
|
+
.replace(/&/g, '&')
|
|
16
|
+
.replace(/</g, '<')
|
|
17
|
+
.replace(/>/g, '>')
|
|
18
|
+
.replace(/"/g, '"')
|
|
19
|
+
.replace(/'/g, ''');
|
|
20
|
+
}
|
|
9
21
|
export class PluginUiServer extends HomebridgePluginUiServer {
|
|
10
22
|
key;
|
|
11
23
|
secret;
|
|
@@ -25,7 +37,7 @@ export class PluginUiServer extends HomebridgePluginUiServer {
|
|
|
25
37
|
this.secret = query.get('secret');
|
|
26
38
|
this.hostname = query.get('host');
|
|
27
39
|
const redirectUrl = `http://${this.hostname}:8585/auth`;
|
|
28
|
-
const authUrl =
|
|
40
|
+
const authUrl = `${AuthorizeURL}response_type=code&appSelect=1&redirect_uri=${encodeURI(redirectUrl)}&client_id=${encodeURIComponent(this.key)}`;
|
|
29
41
|
res.end(`<script>window.location.replace('${authUrl}');</script>`);
|
|
30
42
|
break;
|
|
31
43
|
}
|
|
@@ -33,20 +45,26 @@ export class PluginUiServer extends HomebridgePluginUiServer {
|
|
|
33
45
|
if (query.get('code')) {
|
|
34
46
|
const code = query.get('code');
|
|
35
47
|
const auth = Buffer.from(`${this.key}:${this.secret}`).toString('base64');
|
|
36
|
-
let curlString = '';
|
|
37
|
-
curlString += 'curl -X POST ';
|
|
38
|
-
curlString += `--header "Authorization: Basic ${auth}" `;
|
|
39
|
-
curlString += '--header "Accept: application/json" ';
|
|
40
|
-
curlString += '--header "Content-Type: application/x-www-form-urlencoded" ';
|
|
41
|
-
curlString += '-d "';
|
|
42
|
-
curlString += 'grant_type=authorization_code&';
|
|
43
|
-
curlString += `code=${code}&`;
|
|
44
|
-
curlString += `redirect_uri=${encodeURI(`http://${this.hostname}:8585/auth`)}`;
|
|
45
|
-
curlString += '" ';
|
|
46
|
-
curlString += '"https://api.honeywell.com/oauth2/token"';
|
|
47
48
|
try {
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
// Exchanged with fetch rather than by shelling out to curl:
|
|
50
|
+
// curl is not present on every install, it validates against
|
|
51
|
+
// the system CA store rather than the one Node ships, and
|
|
52
|
+
// building a shell command by hand means anything arriving in
|
|
53
|
+
// the query string ends up inside that command.
|
|
54
|
+
const tokenResponse = await fetch(TokenURL, {
|
|
55
|
+
method: 'POST',
|
|
56
|
+
headers: {
|
|
57
|
+
'Authorization': `Basic ${auth}`,
|
|
58
|
+
'Accept': 'application/json',
|
|
59
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
60
|
+
},
|
|
61
|
+
body: new URLSearchParams({
|
|
62
|
+
grant_type: 'authorization_code',
|
|
63
|
+
code,
|
|
64
|
+
redirect_uri: `http://${this.hostname}:8585/auth`,
|
|
65
|
+
}),
|
|
66
|
+
});
|
|
67
|
+
const response = await tokenResponse.json();
|
|
50
68
|
if (response.access_token) {
|
|
51
69
|
this.pushEvent('creds-received', {
|
|
52
70
|
key: this.key,
|
|
@@ -57,11 +75,16 @@ export class PluginUiServer extends HomebridgePluginUiServer {
|
|
|
57
75
|
res.end('Success. You can close this window now.');
|
|
58
76
|
}
|
|
59
77
|
else {
|
|
60
|
-
|
|
78
|
+
// Report only what Resideo said went wrong. The request
|
|
79
|
+
// carries the consumer secret, so the request itself must
|
|
80
|
+
// never be echoed back to the page.
|
|
81
|
+
const reason = response.error_description ?? response.error ?? `unexpected response (HTTP ${tokenResponse.status})`;
|
|
82
|
+
res.end(`<strong>Could not get a token:</strong><br>${escapeHtml(reason)}<br><br>Close this window and start again`);
|
|
61
83
|
}
|
|
62
84
|
}
|
|
63
85
|
catch (err) {
|
|
64
|
-
|
|
86
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
87
|
+
res.end(`<strong>An error occurred:</strong><br>${escapeHtml(reason)}<br><br>Close this window and start again`);
|
|
65
88
|
}
|
|
66
89
|
}
|
|
67
90
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/homebridge-ui/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/homebridge-ui/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.test.d.ts","sourceRoot":"","sources":["../../src/homebridge-ui/server.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
import { AuthorizeURL, TokenURL } from '../settings.js';
|
|
5
|
+
const source = readFileSync(join(import.meta.dirname, 'server.ts'), 'utf8');
|
|
6
|
+
describe('setup server', () => {
|
|
7
|
+
it('uses the same host as the rest of the plugin', () => {
|
|
8
|
+
// api.honeywell.com served an expired certificate from 18 May 2026, which
|
|
9
|
+
// broke the login flow for everyone while the plugin itself kept working
|
|
10
|
+
// on api.honeywellhome.com (#927).
|
|
11
|
+
expect(AuthorizeURL).toContain('api.honeywellhome.com');
|
|
12
|
+
expect(TokenURL).toContain('api.honeywellhome.com');
|
|
13
|
+
});
|
|
14
|
+
it('does not hardcode an api host of its own', () => {
|
|
15
|
+
expect(source).not.toContain('api.honeywell.com/');
|
|
16
|
+
expect(source).not.toContain('https://api.honeywellhome.com');
|
|
17
|
+
});
|
|
18
|
+
it('exchanges the code without shelling out', () => {
|
|
19
|
+
// curl is not installed everywhere, it trusts the system CA store rather
|
|
20
|
+
// than the one Node ships, and a hand-built command line means query
|
|
21
|
+
// string values end up inside it.
|
|
22
|
+
expect(source).not.toContain('child_process');
|
|
23
|
+
expect(source).not.toMatch(/\bexec\(/);
|
|
24
|
+
expect(source).not.toContain('curlString');
|
|
25
|
+
expect(source).toContain('await fetch(TokenURL');
|
|
26
|
+
});
|
|
27
|
+
it('never echoes the request back to the page', () => {
|
|
28
|
+
// The token request carries the consumer secret in a Basic auth header, so
|
|
29
|
+
// dumping the error object (which used to include the whole command) put
|
|
30
|
+
// the user's own secret on screen.
|
|
31
|
+
expect(source).not.toContain('JSON.stringify(err)');
|
|
32
|
+
});
|
|
33
|
+
it('escapes anything it writes into the page', () => {
|
|
34
|
+
expect(source).toContain('escapeHtml');
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=server.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.test.js","sourceRoot":"","sources":["../../src/homebridge-ui/server.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAE7C,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEvD,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAA;AAE3E,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,0EAA0E;QAC1E,yEAAyE;QACzE,mCAAmC;QACnC,MAAM,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAA;QACvD,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAA;IACrD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAA;QAClD,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,+BAA+B,CAAC,CAAA;IAC/D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,yEAAyE;QACzE,qEAAqE;QACrE,kCAAkC;QAClC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,eAAe,CAAC,CAAA;QAC7C,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;QACtC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,YAAY,CAAC,CAAA;QAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,2EAA2E;QAC3E,yEAAyE;QACzE,mCAAmC;QACnC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAA;IACrD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@homebridge-plugins/homebridge-resideo",
|
|
3
3
|
"displayName": "Resideo",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "3.1.
|
|
5
|
+
"version": "3.1.4",
|
|
6
6
|
"description": "The Resideo plugin allows you to access your Resideo device(s) from HomeKit.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "bwp91",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"@antfu/eslint-config": "^9.1.0",
|
|
89
89
|
"@types/node": "^26.1.1",
|
|
90
90
|
"@vitest/coverage-v8": "^4.1.10",
|
|
91
|
-
"homebridge": "^2.2.
|
|
91
|
+
"homebridge": "^2.2.1",
|
|
92
92
|
"nodemon": "^3.1.14",
|
|
93
93
|
"rimraf": "^6.1.3",
|
|
94
94
|
"ts-node": "^10.9.2",
|