@jgrimard/homebridge-vivint 2.0.1 → 2.0.2-beta.1
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.
|
@@ -47,6 +47,17 @@
|
|
|
47
47
|
const $ = (id) => document.getElementById(id);
|
|
48
48
|
const show = (el, visible) => { el.style.display = visible ? '' : 'none'; };
|
|
49
49
|
|
|
50
|
+
// homebridge.request() has no timeout: if the plugin's UI server process
|
|
51
|
+
// dies, the promise never settles and the spinner runs forever. Cap it so
|
|
52
|
+
// the user gets an actionable error instead.
|
|
53
|
+
const request = (path, body) => Promise.race([
|
|
54
|
+
homebridge.request(path, body),
|
|
55
|
+
new Promise((resolve, reject) => setTimeout(
|
|
56
|
+
() => reject(new Error('The plugin UI server did not respond within 45 seconds. Check the Homebridge log for errors mentioning homebridge-vivint, then close and reopen this settings window to try again.')),
|
|
57
|
+
45000,
|
|
58
|
+
)),
|
|
59
|
+
]);
|
|
60
|
+
|
|
50
61
|
let pluginConfig = await homebridge.getPluginConfig();
|
|
51
62
|
if (!pluginConfig.length) {
|
|
52
63
|
pluginConfig = [{ platform: 'Vivint', name: 'Vivint' }];
|
|
@@ -76,9 +87,16 @@
|
|
|
76
87
|
const saveToken = async (refreshToken) => {
|
|
77
88
|
pluginConfig[0].refreshToken = refreshToken;
|
|
78
89
|
await homebridge.updatePluginConfig(pluginConfig);
|
|
79
|
-
|
|
80
|
-
|
|
90
|
+
// Deliberately NOT calling homebridge.savePluginConfig() here: on
|
|
91
|
+
// config-ui-x v5 the parent passes its save promise straight into
|
|
92
|
+
// postMessage, which throws DataCloneError and never answers, leaving
|
|
93
|
+
// the spinner up forever. The modal's own Save button uses the working
|
|
94
|
+
// code path (and offers the restart prompt), so send the user there.
|
|
81
95
|
refreshView();
|
|
96
|
+
const status = $('tokenStatus');
|
|
97
|
+
status.className = 'alert alert-success';
|
|
98
|
+
status.textContent = 'Vivint account linked! Now click Save below, then restart Homebridge to apply.';
|
|
99
|
+
homebridge.toast.success('Click Save below, then restart Homebridge.', 'Vivint Account Linked');
|
|
82
100
|
};
|
|
83
101
|
|
|
84
102
|
$('loginForm').addEventListener('submit', async (event) => {
|
|
@@ -87,7 +105,7 @@
|
|
|
87
105
|
button.disabled = true;
|
|
88
106
|
homebridge.showSpinner();
|
|
89
107
|
try {
|
|
90
|
-
const response = await
|
|
108
|
+
const response = await request('/login', {
|
|
91
109
|
username: $('email').value,
|
|
92
110
|
password: $('password').value,
|
|
93
111
|
});
|
|
@@ -113,7 +131,7 @@
|
|
|
113
131
|
button.disabled = true;
|
|
114
132
|
homebridge.showSpinner();
|
|
115
133
|
try {
|
|
116
|
-
const response = await
|
|
134
|
+
const response = await request('/verify-code', { code: $('mfaCode').value });
|
|
117
135
|
await saveToken(response.refreshToken);
|
|
118
136
|
} catch (error) {
|
|
119
137
|
homebridge.toast.error(error.message || 'Verification failed.', 'Error');
|
|
@@ -8,6 +8,14 @@ import { HomebridgePluginUiServer, RequestError } from '@homebridge/plugin-ui-ut
|
|
|
8
8
|
* This file is intentionally self-contained: it runs as a separate process
|
|
9
9
|
* spawned by the Homebridge UI and does not load the plugin itself.
|
|
10
10
|
*/
|
|
11
|
+
// Diagnostics: these land in the Homebridge log prefixed with the plugin
|
|
12
|
+
// name. Never log tokens, cookies, or credentials here.
|
|
13
|
+
process.on('uncaughtException', (error) => {
|
|
14
|
+
console.error('Vivint UI server uncaught exception:', error);
|
|
15
|
+
});
|
|
16
|
+
process.on('unhandledRejection', (reason) => {
|
|
17
|
+
console.error('Vivint UI server unhandled rejection:', reason);
|
|
18
|
+
});
|
|
11
19
|
const VIVINT_LOGIN_URL = 'https://www.vivintsky.com/api/login';
|
|
12
20
|
const VIVINT_AUTHUSER_URL = 'https://www.vivintsky.com/api/authuser';
|
|
13
21
|
const VIVINT_MFA_URL = 'https://www.vivintsky.com/platform-user-api/v0/platformusers/2fa/validate';
|
|
@@ -17,11 +25,16 @@ function extractSessionCookie(response) {
|
|
|
17
25
|
return setCookies.find(cookie => cookie.startsWith('s='))?.split(';')[0];
|
|
18
26
|
}
|
|
19
27
|
async function vivintFetch(url, init) {
|
|
28
|
+
const step = new URL(url).pathname;
|
|
20
29
|
try {
|
|
21
|
-
|
|
30
|
+
console.log(`Vivint UI: requesting ${step} ...`);
|
|
31
|
+
const response = await fetch(url, { ...init, signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS) });
|
|
32
|
+
console.log(`Vivint UI: ${step} responded with HTTP ${response.status}`);
|
|
33
|
+
return response;
|
|
22
34
|
}
|
|
23
35
|
catch (error) {
|
|
24
36
|
const reason = error instanceof Error ? error.message : String(error);
|
|
37
|
+
console.error(`Vivint UI: ${step} failed: ${reason}`);
|
|
25
38
|
throw new RequestError(`Could not reach Vivint (${reason}). Check your internet connection and try again.`, {});
|
|
26
39
|
}
|
|
27
40
|
}
|
|
@@ -79,6 +92,7 @@ class VivintUiServer extends HomebridgePluginUiServer {
|
|
|
79
92
|
this.pendingToken = rotatedCookie;
|
|
80
93
|
}
|
|
81
94
|
if (authResponse.status === 401) {
|
|
95
|
+
console.log('Vivint UI: sign-in ok, MFA verification required');
|
|
82
96
|
return { requiresMfa: true };
|
|
83
97
|
}
|
|
84
98
|
if (!authResponse.ok) {
|
|
@@ -111,6 +125,7 @@ class VivintUiServer extends HomebridgePluginUiServer {
|
|
|
111
125
|
if (rotatedCookie) {
|
|
112
126
|
this.pendingToken = rotatedCookie;
|
|
113
127
|
}
|
|
128
|
+
console.log('Vivint UI: MFA verification succeeded');
|
|
114
129
|
const token = this.pendingToken;
|
|
115
130
|
this.pendingToken = '';
|
|
116
131
|
return { refreshToken: token };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../homebridge-ui/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAErF;;;;;;;;GAQG;AAEH,MAAM,gBAAgB,GAAG,qCAAqC,CAAC;AAC/D,MAAM,mBAAmB,GAAG,wCAAwC,CAAC;AACrE,MAAM,cAAc,GAAG,2EAA2E,CAAC;AACnG,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAElC,SAAS,oBAAoB,CAAC,QAAkB;IAC9C,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC;IAC3D,OAAO,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,GAAW,EAAE,IAAiB;IACvD,IAAI,CAAC;QACH,OAAO,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../homebridge-ui/server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@jgrimard/homebridge-vivint",
|
|
3
3
|
"displayName": "Homebridge Vivint",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "2.0.1",
|
|
5
|
+
"version": "2.0.2-beta.1",
|
|
6
6
|
"description": "Homebridge plugin for Vivint Smart Home security systems and devices.",
|
|
7
7
|
"license": "Apache-2.0",
|
|
8
8
|
"author": "Jason Grimard",
|