@homebridge-plugins/homebridge-resideo 3.0.3-beta.6 → 3.0.3-beta.8
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/dist/homebridge-ui/public/index.html +196 -312
- package/dist/homebridge-ui/public/lib/featureoptions.js +455 -0
- package/dist/homebridge-ui/public/lib/featureoptions.js.map +1 -0
- package/dist/homebridge-ui/public/lib/webUi-featureoptions.mjs +3765 -0
- package/dist/homebridge-ui/public/lib/webUi.mjs +189 -0
- package/dist/homebridge-ui/server.d.ts.map +1 -1
- package/dist/homebridge-ui/server.js +202 -44
- package/dist/homebridge-ui/server.js.map +1 -1
- package/dist/resideo-options.d.ts +24 -0
- package/dist/resideo-options.d.ts.map +1 -0
- package/dist/resideo-options.js +215 -0
- package/dist/resideo-options.js.map +1 -0
- package/docs/assets/main.js +5 -5
- package/docs/assets/navigation.js +1 -0
- package/docs/assets/search.js +1 -0
- package/docs/assets/style.css +251 -229
- package/docs/hierarchy.html +1 -0
- package/docs/index.html +13 -14
- package/docs/modules.html +1 -2
- package/docs/variables/default.html +1 -0
- package/eslint.config.js +0 -2
- package/package.json +17 -21
- package/typedoc.json +0 -4
- package/docs/assets/dmt/dmt-component-data.js +0 -1
- package/docs/assets/dmt/dmt-components.css +0 -20
- package/docs/assets/dmt/dmt-components.js +0 -67
- package/docs/assets/dmt/dmt-search.cmp +0 -0
- package/docs/assets/dmt/dmt-theme.css +0 -1
- package/docs/functions/default.html +0 -2
|
@@ -41,13 +41,32 @@
|
|
|
41
41
|
<button type="button" class="btn btn-primary" id="menuSettings">
|
|
42
42
|
Settings
|
|
43
43
|
</button>
|
|
44
|
-
<button type="button" class="btn btn-primary" id="
|
|
44
|
+
<button type="button" class="btn btn-primary" id="menuFeatureOptions">
|
|
45
45
|
Devices
|
|
46
46
|
</button>
|
|
47
47
|
<button type="button" class="btn btn-primary mr-0" id="menuHome">
|
|
48
48
|
Support
|
|
49
49
|
</button>
|
|
50
50
|
</div>
|
|
51
|
+
<div id="pageFirstRun" class="mt-4" style="display: none;">
|
|
52
|
+
<div class="alert alert-info">
|
|
53
|
+
<h5>Getting Started</h5>
|
|
54
|
+
<p class="mb-2">Welcome to homebridge-resideo! Let's get your account configured.</p>
|
|
55
|
+
<p class="mb-0">Please enter your Resideo API credentials to continue.</p>
|
|
56
|
+
</div>
|
|
57
|
+
<div class="form-group">
|
|
58
|
+
<label for="firstRunKey">Consumer Key <span class="text-danger">*</span></label>
|
|
59
|
+
<input type="text" class="form-control" id="firstRunKey">
|
|
60
|
+
</div>
|
|
61
|
+
<div class="form-group">
|
|
62
|
+
<label for="firstRunSecret">Consumer Secret <span class="text-danger">*</span></label>
|
|
63
|
+
<input type="text" class="form-control" id="firstRunSecret">
|
|
64
|
+
</div>
|
|
65
|
+
<div id="loginError"> </div>
|
|
66
|
+
<div class="form-group text-center">
|
|
67
|
+
<button type="button" class="btn btn-primary" id="firstRun">Setup Account →</button>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
51
70
|
<div id="pageAccount" class="mt-4" style="display: none;">
|
|
52
71
|
<div class="alert alert-warning" style="display: none;" id="validateForm">
|
|
53
72
|
Please enter both values
|
|
@@ -69,15 +88,40 @@
|
|
|
69
88
|
<button type="button" class="btn btn-danger" id="unLinkButton">Unlink Account →</button>
|
|
70
89
|
</div>
|
|
71
90
|
</div>
|
|
91
|
+
<!-- Dynamic device configuration UI will be rendered here by webUI -->
|
|
92
|
+
<div id="pageFeatureOptions" class="mt-4" style="display: none;">
|
|
93
|
+
</div>
|
|
72
94
|
<div id="pageDevices" class="mt-4" style="display: none;">
|
|
95
|
+
<div class="alert alert-info" id="deviceConfigInfo">
|
|
96
|
+
<h5>Device Configuration Made Easy</h5>
|
|
97
|
+
<p class="mb-2">This section shows devices available from your Resideo account and provides dynamic configuration options.</p>
|
|
98
|
+
<p class="mb-0">Select a device below to view its details and configure its settings using the feature options system.</p>
|
|
99
|
+
</div>
|
|
73
100
|
<div id="deviceInfo">
|
|
74
101
|
<h5>Cached Devices</h5>
|
|
75
102
|
<p>These are devices already configured in Homebridge:</p>
|
|
76
103
|
<form>
|
|
77
104
|
<div class="form-group">
|
|
105
|
+
<label for="deviceSelect"><strong>Available Devices:</strong></label>
|
|
78
106
|
<select class="form-control" id="deviceSelect"></select>
|
|
79
107
|
</div>
|
|
80
108
|
</form>
|
|
109
|
+
<div id="quickConfigSection" style="display: none;" class="mt-3">
|
|
110
|
+
<div class="alert alert-success">
|
|
111
|
+
<h6>Quick Configuration</h6>
|
|
112
|
+
<p class="mb-2">Copy the device ID below and paste it into the plugin settings:</p>
|
|
113
|
+
<div class="input-group">
|
|
114
|
+
<input type="text" class="form-control" id="quickDeviceID" readonly>
|
|
115
|
+
<div class="input-group-append">
|
|
116
|
+
<button class="btn btn-outline-secondary" type="button" id="copyDeviceID">Copy</button>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
<small class="form-text text-muted mt-2">
|
|
120
|
+
Recommended device class: <span id="recommendedClass"></span><br>
|
|
121
|
+
Suggested device model: <span id="suggestedModel"></span>
|
|
122
|
+
</small>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
81
125
|
<table class="table w-100" id="deviceTable" style="display: none;">
|
|
82
126
|
<thead>
|
|
83
127
|
<tr class="table-active">
|
|
@@ -186,332 +230,172 @@
|
|
|
186
230
|
</li>
|
|
187
231
|
</ul>
|
|
188
232
|
</div>
|
|
189
|
-
<script>
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
233
|
+
<script type="module">
|
|
234
|
+
import { webUi } from "./lib/webUi.mjs";
|
|
235
|
+
|
|
236
|
+
// Initialize the webUI with homebridge-plugin-utils
|
|
237
|
+
const ui = new webUi({
|
|
238
|
+
featureOptions: {
|
|
239
|
+
getFeatureOptions: () => homebridge.request('/getFeatureOptions'),
|
|
240
|
+
getDevices: () => homebridge.request('/getDevices'),
|
|
241
|
+
infoPanel: (device) => {
|
|
242
|
+
return `
|
|
243
|
+
<div class="mt-3">
|
|
244
|
+
<h6>Device Information</h6>
|
|
245
|
+
<p><strong>Name:</strong> ${device.name}</p>
|
|
246
|
+
<p><strong>Device ID:</strong> ${device.deviceID}</p>
|
|
247
|
+
<p><strong>Type:</strong> ${device.deviceType || 'Unknown'}</p>
|
|
248
|
+
<p><strong>Location:</strong> ${device.locationName || 'Unknown'}</p>
|
|
249
|
+
<p><strong>Model:</strong> ${device.model}</p>
|
|
250
|
+
<p><strong>Firmware:</strong> ${device.firmwareRevision}</p>
|
|
251
|
+
</div>
|
|
252
|
+
`;
|
|
199
253
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
document.getElementById('backToIntro').style.display = 'none'
|
|
214
|
-
document.getElementById('linkButton').style.display = 'none'
|
|
215
|
-
document.getElementById('unLinkButton').style.display = 'none'
|
|
216
|
-
document.getElementById('linkSuccess').style.display = 'block'
|
|
217
|
-
} else {
|
|
218
|
-
throw new Error('no access/token received from server')
|
|
219
|
-
}
|
|
220
|
-
} catch (err) {
|
|
221
|
-
console.log(err)
|
|
222
|
-
homebridge.toast.error('Try again, or see the console message for info.', 'Error')
|
|
254
|
+
},
|
|
255
|
+
firstRun: {
|
|
256
|
+
isRequired: () => {
|
|
257
|
+
// Check if we need to run first-time setup
|
|
258
|
+
const currentConfig = homebridge.getPluginConfig();
|
|
259
|
+
return !currentConfig[0]?.credentials?.consumerKey || !currentConfig[0]?.credentials?.consumerSecret;
|
|
260
|
+
},
|
|
261
|
+
onStart: () => {
|
|
262
|
+
// Initialize first run form
|
|
263
|
+
const currentConfig = homebridge.getPluginConfig();
|
|
264
|
+
if (currentConfig[0]?.credentials) {
|
|
265
|
+
document.getElementById('firstRunKey').value = currentConfig[0].credentials.consumerKey || '';
|
|
266
|
+
document.getElementById('firstRunSecret').value = currentConfig[0].credentials.consumerSecret || '';
|
|
223
267
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
document.
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if (
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
) {
|
|
236
|
-
document.getElementById('validateForm').style.display = 'block'
|
|
237
|
-
return
|
|
268
|
+
return true;
|
|
269
|
+
},
|
|
270
|
+
onSubmit: async () => {
|
|
271
|
+
// Handle first run setup
|
|
272
|
+
const key = document.getElementById('firstRunKey').value;
|
|
273
|
+
const secret = document.getElementById('firstRunSecret').value;
|
|
274
|
+
const errorDiv = document.getElementById('loginError');
|
|
275
|
+
|
|
276
|
+
if (!key || !secret) {
|
|
277
|
+
errorDiv.innerHTML = '<div class="alert alert-danger">Please enter both Consumer Key and Consumer Secret.</div>';
|
|
278
|
+
return false;
|
|
238
279
|
}
|
|
239
|
-
|
|
240
|
-
const h = 700;
|
|
241
|
-
const y = window.top.outerHeight / 2 + window.top.screenY - (h / 2);
|
|
242
|
-
const x = window.top.outerWidth / 2 + window.top.screenX - (w / 2);
|
|
243
|
-
const urlToOpen = 'http://' + hostname + ':8585/start?' +
|
|
244
|
-
'key=' + document.getElementById('inputConsumerKey').value +
|
|
245
|
-
'&secret=' + document.getElementById('inputConsumerSecret').value +
|
|
246
|
-
'&host=' + encodeURI(hostname);
|
|
247
|
-
this.popup = window.open(
|
|
248
|
-
urlToOpen, 'honeywell-auth',
|
|
249
|
-
'toolbar=no, location=no, directories=no, status=no, menubar=no scrollbars=no, resizable=no, copyhistory=no, ' +
|
|
250
|
-
'width=' + w + ', height=' + h + ', top=' + y + ', left=' + x,
|
|
251
|
-
)
|
|
252
|
-
}
|
|
253
|
-
unLinkAccount = async () => {
|
|
280
|
+
|
|
254
281
|
try {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
) {
|
|
260
|
-
document.getElementById('validateForm').style.display = 'block'
|
|
261
|
-
return
|
|
282
|
+
// Test the credentials by attempting to link the account
|
|
283
|
+
const currentConfig = homebridge.getPluginConfig();
|
|
284
|
+
if (!currentConfig[0]) {
|
|
285
|
+
currentConfig.push({ name: 'Resideo' });
|
|
262
286
|
}
|
|
263
|
-
delete currentConfig[0].credentials
|
|
264
|
-
await homebridge.updatePluginConfig(currentConfig)
|
|
265
|
-
await homebridge.savePluginConfig()
|
|
266
|
-
document.getElementById('inputConsumerKey').value = ''
|
|
267
|
-
document.getElementById('inputConsumerSecret').value = ''
|
|
268
|
-
document.getElementById('unLinkButton').style.display = 'none'
|
|
269
|
-
} catch (err) {
|
|
270
|
-
console.error(err)
|
|
271
|
-
homebridge.toast.error('Try again, or see the console message for info.', 'Error')
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
showIntro = () => {
|
|
275
|
-
const introLink = document.getElementById('introLink')
|
|
276
|
-
document.getElementById('copyMe').value = 'http://' + hostname + ':8585/auth'
|
|
277
|
-
introLink.addEventListener('click', () => {
|
|
278
|
-
homebridge.showSpinner()
|
|
279
|
-
document.getElementById('pageIntro').style.display = 'none'
|
|
280
|
-
document.getElementById('menuWrapper').style.display = 'inline-flex'
|
|
281
|
-
showAccount()
|
|
282
|
-
homebridge.hideSpinner()
|
|
283
|
-
})
|
|
284
|
-
document.getElementById('pageAccount').style.display = 'none'
|
|
285
|
-
document.getElementById('menuWrapper').style.display = 'none'
|
|
286
|
-
document.getElementById('pageIntro').style.display = 'block'
|
|
287
|
-
}
|
|
288
|
-
showDevices = async () => {
|
|
289
|
-
homebridge.showSpinner()
|
|
290
|
-
homebridge.hideSchemaForm()
|
|
291
|
-
document.getElementById('menuHome').classList.remove('btn-elegant')
|
|
292
|
-
document.getElementById('menuHome').classList.add('btn-primary')
|
|
293
|
-
document.getElementById('menuDevices').classList.add('btn-elegant')
|
|
294
|
-
document.getElementById('menuDevices').classList.remove('btn-primary')
|
|
295
|
-
document.getElementById('menuAccount').classList.remove('btn-elegant')
|
|
296
|
-
document.getElementById('menuAccount').classList.add('btn-primary')
|
|
297
|
-
document.getElementById('menuSettings').classList.remove('btn-elegant')
|
|
298
|
-
document.getElementById('menuSettings').classList.add('btn-primary')
|
|
299
|
-
document.getElementById('pageSupport').style.display = 'none'
|
|
300
|
-
document.getElementById('pageAccount').style.display = 'none'
|
|
301
|
-
document.getElementById('pageDevices').style.display = 'block'
|
|
302
|
-
const cachedAccessories =
|
|
303
|
-
typeof homebridge.getCachedAccessories === 'function'
|
|
304
|
-
? await homebridge.getCachedAccessories()
|
|
305
|
-
: await homebridge.request('/getCachedAccessories')
|
|
306
|
-
if (cachedAccessories.length > 0) {
|
|
307
|
-
cachedAccessories.sort((a, b) => {
|
|
308
|
-
return a.displayName.toLowerCase() > b.displayName.toLowerCase()
|
|
309
|
-
? 1
|
|
310
|
-
: b.displayName.toLowerCase() > a.displayName.toLowerCase()
|
|
311
|
-
? -1
|
|
312
|
-
: 0
|
|
313
|
-
})
|
|
314
|
-
}
|
|
315
|
-
const deviceSelect = document.getElementById('deviceSelect')
|
|
316
|
-
deviceSelect.innerHTML = ''
|
|
317
|
-
cachedAccessories.forEach(a => {
|
|
318
|
-
const option = document.createElement('option')
|
|
319
|
-
option.text = a.displayName
|
|
320
|
-
option.value = a.UUID
|
|
321
|
-
deviceSelect.add(option)
|
|
322
|
-
})
|
|
323
|
-
showDeviceInfo = async UUID => {
|
|
324
|
-
homebridge.showSpinner()
|
|
325
|
-
const thisAcc = cachedAccessories.find(x => x.UUID === UUID)
|
|
326
|
-
const context = thisAcc.context
|
|
327
|
-
document.getElementById('displayName').innerHTML = thisAcc.displayName
|
|
328
|
-
document.getElementById('deviceID').innerHTML = context.deviceID
|
|
329
|
-
document.getElementById('model').innerHTML = context.model
|
|
330
|
-
document.getElementById('firmwareRevision').innerHTML = context.firmwareRevision || 'N/A'
|
|
331
|
-
document.getElementById('deviceTable').style.display = 'inline-table'
|
|
332
|
-
homebridge.hideSpinner()
|
|
333
|
-
}
|
|
334
|
-
deviceSelect.addEventListener('change', event => showDeviceInfo(event.target.value))
|
|
335
|
-
if (cachedAccessories.length > 0) {
|
|
336
|
-
showDeviceInfo(cachedAccessories[0].UUID)
|
|
337
|
-
} else {
|
|
338
|
-
const option = document.createElement('option')
|
|
339
|
-
option.text = 'No Devices'
|
|
340
|
-
deviceSelect.add(option)
|
|
341
|
-
deviceSelect.disabled = true
|
|
342
|
-
}
|
|
343
|
-
homebridge.hideSpinner()
|
|
344
|
-
|
|
345
|
-
// Load available devices when the page loads
|
|
346
|
-
loadAvailableDevices()
|
|
347
|
-
|
|
348
|
-
// Set up refresh button
|
|
349
|
-
document.getElementById('refreshDevicesButton').addEventListener('click', () => {
|
|
350
|
-
loadAvailableDevices()
|
|
351
|
-
})
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
loadAvailableDevices = async () => {
|
|
355
|
-
const messageDiv = document.getElementById('availableDevicesMessage')
|
|
356
|
-
const tableDiv = document.getElementById('availableDevicesTable')
|
|
357
|
-
const tableBody = document.getElementById('availableDevicesTableBody')
|
|
358
|
-
|
|
359
|
-
try {
|
|
360
|
-
homebridge.showSpinner()
|
|
361
|
-
messageDiv.style.display = 'none'
|
|
362
|
-
tableDiv.style.display = 'none'
|
|
363
287
|
|
|
364
|
-
|
|
288
|
+
currentConfig[0].credentials = {
|
|
289
|
+
consumerKey: key,
|
|
290
|
+
consumerSecret: secret
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
await homebridge.updatePluginConfig(currentConfig);
|
|
365
294
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
messageDiv.innerHTML = response.message || 'Failed to load devices'
|
|
369
|
-
messageDiv.style.display = 'block'
|
|
370
|
-
return
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
if (!response.data || response.data.length === 0) {
|
|
374
|
-
messageDiv.className = 'alert alert-warning'
|
|
375
|
-
messageDiv.innerHTML = 'No devices found in your Resideo account'
|
|
376
|
-
messageDiv.style.display = 'block'
|
|
377
|
-
return
|
|
378
|
-
}
|
|
295
|
+
// Now trigger the OAuth flow
|
|
296
|
+
await homebridge.request('Start Resideo Login Server');
|
|
379
297
|
|
|
380
|
-
//
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
<td>${device.deviceModel || 'N/A'}</td>
|
|
391
|
-
<td>${device.locationName}</td>
|
|
392
|
-
<td>
|
|
393
|
-
<span class="badge badge-${device.isOnline ? 'success' : 'secondary'}">
|
|
394
|
-
${device.isOnline ? 'Online' : 'Offline'}
|
|
395
|
-
</span>
|
|
396
|
-
</td>
|
|
397
|
-
`
|
|
398
|
-
tableBody.appendChild(row)
|
|
399
|
-
})
|
|
400
|
-
|
|
401
|
-
tableDiv.style.display = 'table'
|
|
402
|
-
messageDiv.className = 'alert alert-success'
|
|
403
|
-
messageDiv.innerHTML = `Found ${response.data.length} device(s) in your Resideo account. Copy the Device ID to add devices to your configuration.`
|
|
404
|
-
messageDiv.style.display = 'block'
|
|
298
|
+
// Open OAuth popup
|
|
299
|
+
const hostname = window.location.hostname;
|
|
300
|
+
const w = 450;
|
|
301
|
+
const h = 700;
|
|
302
|
+
const y = window.top.outerHeight / 2 + window.top.screenY - (h / 2);
|
|
303
|
+
const x = window.top.outerWidth / 2 + window.top.screenX - (w / 2);
|
|
304
|
+
const urlToOpen = 'http://' + hostname + ':8585/start?' +
|
|
305
|
+
'key=' + encodeURIComponent(key) +
|
|
306
|
+
'&secret=' + encodeURIComponent(secret) +
|
|
307
|
+
'&host=' + encodeURIComponent(hostname);
|
|
405
308
|
|
|
309
|
+
const popup = window.open(
|
|
310
|
+
urlToOpen, 'resideo-auth',
|
|
311
|
+
'toolbar=no, location=no, directories=no, status=no, menubar=no scrollbars=no, resizable=no, copyhistory=no, ' +
|
|
312
|
+
'width=' + w + ', height=' + h + ', top=' + y + ', left=' + x,
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
return new Promise((resolve) => {
|
|
316
|
+
const checkClosed = setInterval(() => {
|
|
317
|
+
if (popup.closed) {
|
|
318
|
+
clearInterval(checkClosed);
|
|
319
|
+
// Check if credentials were updated
|
|
320
|
+
const updatedConfig = homebridge.getPluginConfig();
|
|
321
|
+
if (updatedConfig[0]?.credentials?.accessToken) {
|
|
322
|
+
resolve(true);
|
|
323
|
+
} else {
|
|
324
|
+
errorDiv.innerHTML = '<div class="alert alert-danger">Authentication failed. Please try again.</div>';
|
|
325
|
+
resolve(false);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}, 1000);
|
|
329
|
+
});
|
|
406
330
|
} catch (error) {
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
messageDiv.style.display = 'block'
|
|
410
|
-
} finally {
|
|
411
|
-
homebridge.hideSpinner()
|
|
331
|
+
errorDiv.innerHTML = `<div class="alert alert-danger">Error: ${error.message}</div>`;
|
|
332
|
+
return false;
|
|
412
333
|
}
|
|
413
334
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
document.getElementById('menuDevices').classList.add('btn-primary')
|
|
436
|
-
document.getElementById('menuSettings').classList.add('btn-elegant')
|
|
437
|
-
document.getElementById('menuSettings').classList.remove('btn-primary')
|
|
438
|
-
document.getElementById('menuAccount').classList.remove('btn-elegant')
|
|
439
|
-
document.getElementById('menuAccount').classList.add('btn-primary')
|
|
440
|
-
document.getElementById('pageSupport').style.display = 'none'
|
|
441
|
-
document.getElementById('pageDevices').style.display = 'none'
|
|
442
|
-
document.getElementById('pageAccount').style.display = 'none'
|
|
443
|
-
homebridge.showSchemaForm()
|
|
444
|
-
homebridge.hideSpinner()
|
|
445
|
-
}
|
|
446
|
-
showAccount = () => {
|
|
447
|
-
homebridge.showSpinner()
|
|
448
|
-
const backToIntro = document.getElementById('backToIntro')
|
|
449
|
-
backToIntro.addEventListener('click', () => {
|
|
450
|
-
showIntro()
|
|
451
|
-
})
|
|
452
|
-
backToIntro.style.display = 'none'
|
|
453
|
-
const linkButton = document.getElementById('linkButton')
|
|
454
|
-
linkButton.addEventListener('click', () => {
|
|
455
|
-
linkAccount()
|
|
456
|
-
})
|
|
457
|
-
const unLinkButton = document.getElementById('unLinkButton')
|
|
458
|
-
unLinkButton.style.display = 'none'
|
|
459
|
-
unLinkButton.addEventListener('click', () => {
|
|
460
|
-
unLinkAccount()
|
|
461
|
-
})
|
|
462
|
-
document.getElementById('linkSuccess').style.display = 'none'
|
|
463
|
-
homebridge.hideSchemaForm()
|
|
464
|
-
document.getElementById('menuHome').classList.remove('btn-elegant')
|
|
465
|
-
document.getElementById('menuHome').classList.add('btn-primary')
|
|
466
|
-
document.getElementById('menuDevices').classList.remove('btn-elegant')
|
|
467
|
-
document.getElementById('menuDevices').classList.add('btn-primary')
|
|
468
|
-
document.getElementById('menuAccount').classList.add('btn-elegant')
|
|
469
|
-
document.getElementById('menuAccount').classList.remove('btn-primary')
|
|
470
|
-
document.getElementById('menuSettings').classList.remove('btn-elegant')
|
|
471
|
-
document.getElementById('menuSettings').classList.add('btn-primary')
|
|
472
|
-
document.getElementById('pageSupport').style.display = 'none'
|
|
473
|
-
document.getElementById('pageDevices').style.display = 'none'
|
|
474
|
-
document.getElementById('pageAccount').style.display = 'block'
|
|
475
|
-
document.getElementById('linkButton').style.display = 'inline-block'
|
|
476
|
-
let isRelink = false
|
|
477
|
-
if (currentConfig[0] && currentConfig[0].credentials) {
|
|
478
|
-
const key = currentConfig[0].credentials.consumerKey || ''
|
|
479
|
-
const secret = currentConfig[0].credentials.consumerSecret || ''
|
|
480
|
-
document.getElementById('inputConsumerKey').value = key
|
|
481
|
-
document.getElementById('inputConsumerSecret').value = secret
|
|
482
|
-
if (key && secret) {
|
|
483
|
-
isRelink = true
|
|
484
|
-
document.getElementById('unLinkButton').style.display = 'inline-block'
|
|
485
|
-
} else {
|
|
486
|
-
document.getElementById('unLinkButton').style.display = 'none'
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
document.getElementById('linkButton').innerHTML = isRelink
|
|
490
|
-
? 'Relink Account →'
|
|
491
|
-
: 'Link Account →'
|
|
492
|
-
if (!isRelink) {
|
|
493
|
-
document.getElementById('backToIntro').style.display = 'inline-block'
|
|
494
|
-
} else {
|
|
495
|
-
document.getElementById('backToIntro').style.display = 'none'
|
|
335
|
+
},
|
|
336
|
+
name: 'homebridge-resideo'
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
// Legacy functionality for existing UI elements
|
|
340
|
+
const setupLegacyHandlers = () => {
|
|
341
|
+
const currentConfig = homebridge.getPluginConfig();
|
|
342
|
+
const hostname = window.location.hostname;
|
|
343
|
+
|
|
344
|
+
homebridge.addEventListener('creds-received', async event => {
|
|
345
|
+
try {
|
|
346
|
+
if (event.data.access && event.data.refresh) {
|
|
347
|
+
currentConfig[0].credentials = {
|
|
348
|
+
consumerKey: event.data.key,
|
|
349
|
+
consumerSecret: event.data.secret,
|
|
350
|
+
accessToken: event.data.access,
|
|
351
|
+
refreshToken: event.data.refresh
|
|
352
|
+
};
|
|
353
|
+
await homebridge.updatePluginConfig(currentConfig);
|
|
354
|
+
await homebridge.savePluginConfig();
|
|
355
|
+
homebridge.toast.success("Successfully Linked Resideo Account", "homebridge-resideo");
|
|
496
356
|
}
|
|
497
|
-
|
|
357
|
+
} catch (err) {
|
|
358
|
+
console.log(err);
|
|
359
|
+
homebridge.toast.error('Try again, or see the console message for info.', 'Error');
|
|
498
360
|
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
window.copyMyText = () => {
|
|
364
|
+
const textToCopy = document.getElementById("copyMe");
|
|
365
|
+
textToCopy.select();
|
|
366
|
+
document.execCommand("copy");
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
window.linkAccount = async () => {
|
|
370
|
+
document.getElementById('validateForm').style.display = 'none';
|
|
371
|
+
if (!document.getElementById('inputConsumerKey').value || !document.getElementById('inputConsumerSecret').value) {
|
|
372
|
+
document.getElementById('validateForm').style.display = 'block';
|
|
373
|
+
return;
|
|
510
374
|
}
|
|
375
|
+
const w = 450;
|
|
376
|
+
const h = 700;
|
|
377
|
+
const y = window.top.outerHeight / 2 + window.top.screenY - (h / 2);
|
|
378
|
+
const x = window.top.outerWidth / 2 + window.top.screenX - (w / 2);
|
|
379
|
+
const urlToOpen = 'http://' + hostname + ':8585/start?' +
|
|
380
|
+
'key=' + document.getElementById('inputConsumerKey').value +
|
|
381
|
+
'&secret=' + document.getElementById('inputConsumerSecret').value +
|
|
382
|
+
'&host=' + encodeURI(hostname);
|
|
383
|
+
window.popup = window.open(
|
|
384
|
+
urlToOpen, 'honeywell-auth',
|
|
385
|
+
'toolbar=no, location=no, directories=no, status=no, menubar=no scrollbars=no, resizable=no, copyhistory=no, ' +
|
|
386
|
+
'width=' + w + ', height=' + h + ', top=' + y + ', left=' + x,
|
|
387
|
+
);
|
|
388
|
+
};
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
// Show the webUI
|
|
392
|
+
(async () => {
|
|
393
|
+
try {
|
|
394
|
+
await homebridge.request('Start Resideo Login Server');
|
|
395
|
+
setupLegacyHandlers();
|
|
396
|
+
ui.show();
|
|
511
397
|
} catch (err) {
|
|
512
|
-
homebridge.toast.error(err.message, 'Error')
|
|
513
|
-
} finally {
|
|
514
|
-
homebridge.hideSpinner()
|
|
398
|
+
homebridge.toast.error(err.message, 'Error');
|
|
515
399
|
}
|
|
516
|
-
})()
|
|
400
|
+
})();
|
|
517
401
|
</script>
|