@switchbot/homebridge-switchbot 5.1.0-beta.0 → 5.1.0-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.
- package/dist/SwitchBotMatterPlatform.d.ts +1 -0
- package/dist/SwitchBotMatterPlatform.d.ts.map +1 -1
- package/dist/SwitchBotMatterPlatform.js +23 -0
- package/dist/SwitchBotMatterPlatform.js.map +1 -1
- package/dist/homebridge-ui/endpoints/config.d.ts.map +1 -1
- package/dist/homebridge-ui/endpoints/config.js +9 -2
- package/dist/homebridge-ui/endpoints/config.js.map +1 -1
- package/dist/homebridge-ui/homebridge-ui/endpoints/config.js +9 -2
- package/dist/homebridge-ui/homebridge-ui/endpoints/config.js.map +1 -1
- package/dist/homebridge-ui/homebridge-ui/utils/config-parser.js +8 -0
- package/dist/homebridge-ui/homebridge-ui/utils/config-parser.js.map +1 -1
- package/dist/homebridge-ui/homebridge-ui/utils/v4-detection.js +23 -0
- package/dist/homebridge-ui/homebridge-ui/utils/v4-detection.js.map +1 -0
- package/dist/homebridge-ui/public/css/styles.css +61 -1
- package/dist/homebridge-ui/public/index.html +25 -2
- package/dist/homebridge-ui/public/js/api.d.ts +10 -0
- package/dist/homebridge-ui/public/js/api.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/api.js +30 -0
- package/dist/homebridge-ui/public/js/api.js.map +1 -1
- package/dist/homebridge-ui/public/js/api.ts +30 -0
- package/dist/homebridge-ui/public/js/app.js +159 -109
- package/dist/homebridge-ui/public/js/app.js.map +4 -4
- package/dist/homebridge-ui/public/js/app.ts +22 -4
- package/dist/homebridge-ui/utils/config-parser.d.ts +8 -0
- package/dist/homebridge-ui/utils/config-parser.d.ts.map +1 -1
- package/dist/homebridge-ui/utils/config-parser.js +8 -0
- package/dist/homebridge-ui/utils/config-parser.js.map +1 -1
- package/dist/homebridge-ui/utils/v4-detection.d.ts +12 -0
- package/dist/homebridge-ui/utils/v4-detection.d.ts.map +1 -0
- package/dist/homebridge-ui/utils/v4-detection.js +23 -0
- package/dist/homebridge-ui/utils/v4-detection.js.map +1 -0
- package/docs/assets/icons.js +1 -1
- package/docs/assets/icons.svg +1 -1
- package/docs/assets/main.js +3 -3
- package/docs/variables/default.html +1 -1
- package/package.json +6 -6
- package/scripts/build-ui.js +30 -0
- package/src/SwitchBotMatterPlatform.ts +26 -0
- package/src/homebridge-ui/endpoints/config.ts +10 -2
- package/src/homebridge-ui/public/css/styles.css +61 -1
- package/src/homebridge-ui/public/index.html +23 -0
- package/src/homebridge-ui/public/js/api.ts +30 -0
- package/src/homebridge-ui/public/js/app.ts +22 -4
- package/src/homebridge-ui/utils/config-parser.ts +9 -0
- package/src/homebridge-ui/utils/v4-detection.ts +23 -0
- package/test/homebridge-ui/config-parser.spec.ts +61 -0
- package/test/platform/matter-integration.spec.ts +50 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Fetch the list of configured devices from the Homebridge UI API
|
|
2
2
|
import { isValidDeviceType, normalizeDeviceType } from '../../../device-types.js'
|
|
3
|
+
import { isV4Config } from '../../utils/v4-detection.js'
|
|
3
4
|
import './types.js'
|
|
4
5
|
import { uiLog } from './logger.js'
|
|
5
6
|
import { toastError } from './toast.js'
|
|
@@ -22,6 +23,35 @@ export async function fetchDevices(): Promise<any[]> {
|
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Detect whether the current plugin config is in the legacy v4 format.
|
|
28
|
+
*
|
|
29
|
+
* v4 configs stored credentials under a `credentials` sub-object and devices
|
|
30
|
+
* under `options.devices`. v5+ flattened these to `openApiToken`,
|
|
31
|
+
* `openApiSecret`, and a root-level `devices` array.
|
|
32
|
+
*
|
|
33
|
+
* Returns true when a v4 config block is found, false otherwise.
|
|
34
|
+
*/
|
|
35
|
+
export async function detectV4Config(): Promise<boolean> {
|
|
36
|
+
try {
|
|
37
|
+
if (typeof homebridge.getPluginConfig !== 'function') {
|
|
38
|
+
return false
|
|
39
|
+
}
|
|
40
|
+
const configArr = await homebridge.getPluginConfig()
|
|
41
|
+
if (!Array.isArray(configArr)) {
|
|
42
|
+
return false
|
|
43
|
+
}
|
|
44
|
+
const config = configArr.find(isSwitchBotPlatformConfig)
|
|
45
|
+
if (!config || typeof config !== 'object') {
|
|
46
|
+
return false
|
|
47
|
+
}
|
|
48
|
+
return isV4Config(config)
|
|
49
|
+
} catch (e) {
|
|
50
|
+
uiLog.warn('Error detecting v4 config:', e)
|
|
51
|
+
return false
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
25
55
|
/**
|
|
26
56
|
* Validate and auto-correct device types in the config array before saving.
|
|
27
57
|
* Returns an array of errors for devices that cannot be fixed.
|
|
@@ -8,111 +8,6 @@ var __export = (target, all) => {
|
|
|
8
8
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
// src/homebridge-ui/public/js/logger.ts
|
|
12
|
-
var PREFIX, uiLog;
|
|
13
|
-
var init_logger = __esm({
|
|
14
|
-
"src/homebridge-ui/public/js/logger.ts"() {
|
|
15
|
-
"use strict";
|
|
16
|
-
PREFIX = "[SwitchBot UI/html]";
|
|
17
|
-
uiLog = {
|
|
18
|
-
info: (message, ...parameters) => {
|
|
19
|
-
console.log(PREFIX, message, ...parameters);
|
|
20
|
-
},
|
|
21
|
-
warn: (message, ...parameters) => {
|
|
22
|
-
console.warn(PREFIX, message, ...parameters);
|
|
23
|
-
},
|
|
24
|
-
error: (message, ...parameters) => {
|
|
25
|
-
console.error(PREFIX, message, ...parameters);
|
|
26
|
-
},
|
|
27
|
-
debug: (message, ...parameters) => {
|
|
28
|
-
console.debug(PREFIX, message, ...parameters);
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
// src/homebridge-ui/public/js/types.ts
|
|
35
|
-
var init_types = __esm({
|
|
36
|
-
"src/homebridge-ui/public/js/types.ts"() {
|
|
37
|
-
"use strict";
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// src/homebridge-ui/public/js/modal.ts
|
|
42
|
-
function callUiMethod(name, ...args) {
|
|
43
|
-
try {
|
|
44
|
-
if (typeof homebridge?.[name] === "function") {
|
|
45
|
-
uiLog.info(`[callUiMethod] Invoking homebridge.${String(name)}()`);
|
|
46
|
-
const fn = homebridge?.[name];
|
|
47
|
-
if (typeof fn === "function") {
|
|
48
|
-
uiLog.info(`[callUiMethod] Invoking homebridge.${String(name)}()`);
|
|
49
|
-
fn.apply(homebridge, args);
|
|
50
|
-
} else {
|
|
51
|
-
uiLog.warn(`[callUiMethod] homebridge[${String(name)}] is not a function.`);
|
|
52
|
-
}
|
|
53
|
-
} else {
|
|
54
|
-
uiLog.warn(`[callUiMethod] homebridge[${String(name)}] is not a function.`);
|
|
55
|
-
}
|
|
56
|
-
} catch (e) {
|
|
57
|
-
uiLog.warn(`Homebridge UI method ${String(name)} failed:`, e);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
function showBusyUi() {
|
|
61
|
-
callUiMethod("disableSaveButton");
|
|
62
|
-
callUiMethod("showSpinner");
|
|
63
|
-
}
|
|
64
|
-
function hideBusyUi() {
|
|
65
|
-
callUiMethod("hideSpinner");
|
|
66
|
-
callUiMethod("enableSaveButton");
|
|
67
|
-
}
|
|
68
|
-
var init_modal = __esm({
|
|
69
|
-
"src/homebridge-ui/public/js/modal.ts"() {
|
|
70
|
-
"use strict";
|
|
71
|
-
init_types();
|
|
72
|
-
init_logger();
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
// src/homebridge-ui/public/js/toast.ts
|
|
77
|
-
function showToast(method, message, title = "SwitchBot") {
|
|
78
|
-
try {
|
|
79
|
-
const hb = typeof window !== "undefined" ? window.homebridge : void 0;
|
|
80
|
-
const toast = hb && typeof hb.toast === "object" ? hb.toast : void 0;
|
|
81
|
-
const fn = toast && typeof toast[method] === "function" ? toast[method] : void 0;
|
|
82
|
-
if (fn) {
|
|
83
|
-
try {
|
|
84
|
-
fn(message, title);
|
|
85
|
-
return;
|
|
86
|
-
} catch (err) {
|
|
87
|
-
uiLog.warn(`Toast ${method} threw:`, err);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
uiLog.info(`[Toast:${method}] ${title} - ${message}`);
|
|
91
|
-
} catch (e) {
|
|
92
|
-
uiLog.warn(`Toast ${method} outer error:`, e);
|
|
93
|
-
uiLog.info(`[Toast:${method}] ${title} - ${message}`);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
function toastSuccess(message, title) {
|
|
97
|
-
showToast("success", message, title);
|
|
98
|
-
}
|
|
99
|
-
function toastError(message, title) {
|
|
100
|
-
showToast("error", message, title);
|
|
101
|
-
}
|
|
102
|
-
function toastWarning(message, title) {
|
|
103
|
-
showToast("warning", message, title);
|
|
104
|
-
}
|
|
105
|
-
function toastInfo(message, title) {
|
|
106
|
-
showToast("info", message, title);
|
|
107
|
-
}
|
|
108
|
-
var init_toast = __esm({
|
|
109
|
-
"src/homebridge-ui/public/js/toast.ts"() {
|
|
110
|
-
"use strict";
|
|
111
|
-
init_types();
|
|
112
|
-
init_logger();
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
|
|
116
11
|
// src/device-types.js
|
|
117
12
|
function getValidDeviceTypes() {
|
|
118
13
|
const validTypes = /* @__PURE__ */ new Set();
|
|
@@ -354,6 +249,91 @@ var init_device_types = __esm({
|
|
|
354
249
|
}
|
|
355
250
|
});
|
|
356
251
|
|
|
252
|
+
// src/homebridge-ui/utils/v4-detection.ts
|
|
253
|
+
function isV4Config(platform) {
|
|
254
|
+
if (!platform || typeof platform !== "object") {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
const hasCredentials = platform.credentials !== void 0 && typeof platform.credentials === "object";
|
|
258
|
+
const hasOptionsDevices = platform.options !== void 0 && typeof platform.options === "object" && Array.isArray(platform.options.devices);
|
|
259
|
+
return hasCredentials || hasOptionsDevices;
|
|
260
|
+
}
|
|
261
|
+
var init_v4_detection = __esm({
|
|
262
|
+
"src/homebridge-ui/utils/v4-detection.ts"() {
|
|
263
|
+
"use strict";
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// src/homebridge-ui/public/js/types.ts
|
|
268
|
+
var init_types = __esm({
|
|
269
|
+
"src/homebridge-ui/public/js/types.ts"() {
|
|
270
|
+
"use strict";
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// src/homebridge-ui/public/js/logger.ts
|
|
275
|
+
var PREFIX, uiLog;
|
|
276
|
+
var init_logger = __esm({
|
|
277
|
+
"src/homebridge-ui/public/js/logger.ts"() {
|
|
278
|
+
"use strict";
|
|
279
|
+
PREFIX = "[SwitchBot UI/html]";
|
|
280
|
+
uiLog = {
|
|
281
|
+
info: (message, ...parameters) => {
|
|
282
|
+
console.log(PREFIX, message, ...parameters);
|
|
283
|
+
},
|
|
284
|
+
warn: (message, ...parameters) => {
|
|
285
|
+
console.warn(PREFIX, message, ...parameters);
|
|
286
|
+
},
|
|
287
|
+
error: (message, ...parameters) => {
|
|
288
|
+
console.error(PREFIX, message, ...parameters);
|
|
289
|
+
},
|
|
290
|
+
debug: (message, ...parameters) => {
|
|
291
|
+
console.debug(PREFIX, message, ...parameters);
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
// src/homebridge-ui/public/js/toast.ts
|
|
298
|
+
function showToast(method, message, title = "SwitchBot") {
|
|
299
|
+
try {
|
|
300
|
+
const hb = typeof window !== "undefined" ? window.homebridge : void 0;
|
|
301
|
+
const toast = hb && typeof hb.toast === "object" ? hb.toast : void 0;
|
|
302
|
+
const fn = toast && typeof toast[method] === "function" ? toast[method] : void 0;
|
|
303
|
+
if (fn) {
|
|
304
|
+
try {
|
|
305
|
+
fn(message, title);
|
|
306
|
+
return;
|
|
307
|
+
} catch (err) {
|
|
308
|
+
uiLog.warn(`Toast ${method} threw:`, err);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
uiLog.info(`[Toast:${method}] ${title} - ${message}`);
|
|
312
|
+
} catch (e) {
|
|
313
|
+
uiLog.warn(`Toast ${method} outer error:`, e);
|
|
314
|
+
uiLog.info(`[Toast:${method}] ${title} - ${message}`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
function toastSuccess(message, title) {
|
|
318
|
+
showToast("success", message, title);
|
|
319
|
+
}
|
|
320
|
+
function toastError(message, title) {
|
|
321
|
+
showToast("error", message, title);
|
|
322
|
+
}
|
|
323
|
+
function toastWarning(message, title) {
|
|
324
|
+
showToast("warning", message, title);
|
|
325
|
+
}
|
|
326
|
+
function toastInfo(message, title) {
|
|
327
|
+
showToast("info", message, title);
|
|
328
|
+
}
|
|
329
|
+
var init_toast = __esm({
|
|
330
|
+
"src/homebridge-ui/public/js/toast.ts"() {
|
|
331
|
+
"use strict";
|
|
332
|
+
init_types();
|
|
333
|
+
init_logger();
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
|
|
357
337
|
// src/homebridge-ui/public/js/api.ts
|
|
358
338
|
var api_exports = {};
|
|
359
339
|
__export(api_exports, {
|
|
@@ -361,11 +341,12 @@ __export(api_exports, {
|
|
|
361
341
|
addDevicesInBulk: () => addDevicesInBulk,
|
|
362
342
|
deleteAllDevices: () => deleteAllDevices,
|
|
363
343
|
deleteDevice: () => deleteDevice,
|
|
344
|
+
detectV4Config: () => detectV4Config,
|
|
364
345
|
discoverDevices: () => discoverDevices,
|
|
365
346
|
fetchBluetoothStatus: () => fetchBluetoothStatus,
|
|
366
347
|
fetchCredentialStatus: () => fetchCredentialStatus,
|
|
367
348
|
fetchDevices: () => fetchDevices,
|
|
368
|
-
saveCredentials: () =>
|
|
349
|
+
saveCredentials: () => saveCredentials,
|
|
369
350
|
syncParentPluginConfigFromDisk: () => syncParentPluginConfigFromDisk,
|
|
370
351
|
testDeviceConnection: () => testDeviceConnection,
|
|
371
352
|
updateDevice: () => updateDevice,
|
|
@@ -388,6 +369,25 @@ async function fetchDevices() {
|
|
|
388
369
|
return [];
|
|
389
370
|
}
|
|
390
371
|
}
|
|
372
|
+
async function detectV4Config() {
|
|
373
|
+
try {
|
|
374
|
+
if (typeof homebridge.getPluginConfig !== "function") {
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
const configArr = await homebridge.getPluginConfig();
|
|
378
|
+
if (!Array.isArray(configArr)) {
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
const config = configArr.find(isSwitchBotPlatformConfig);
|
|
382
|
+
if (!config || typeof config !== "object") {
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
return isV4Config(config);
|
|
386
|
+
} catch (e) {
|
|
387
|
+
uiLog.warn("Error detecting v4 config:", e);
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
391
|
function validateAndFixDeviceTypes(devices) {
|
|
392
392
|
const errors = [];
|
|
393
393
|
for (const d of devices) {
|
|
@@ -457,7 +457,7 @@ async function fetchCredentialStatus() {
|
|
|
457
457
|
return null;
|
|
458
458
|
}
|
|
459
459
|
}
|
|
460
|
-
async function
|
|
460
|
+
async function saveCredentials(token, secret) {
|
|
461
461
|
uiLog.info("Saving credentials...");
|
|
462
462
|
const resp = await homebridge.request("/credentials", { token, secret });
|
|
463
463
|
uiLog.info("Save response:", resp);
|
|
@@ -657,12 +657,48 @@ var init_api = __esm({
|
|
|
657
657
|
"src/homebridge-ui/public/js/api.ts"() {
|
|
658
658
|
"use strict";
|
|
659
659
|
init_device_types();
|
|
660
|
+
init_v4_detection();
|
|
660
661
|
init_types();
|
|
661
662
|
init_logger();
|
|
662
663
|
init_toast();
|
|
663
664
|
}
|
|
664
665
|
});
|
|
665
666
|
|
|
667
|
+
// src/homebridge-ui/public/js/modal.ts
|
|
668
|
+
function callUiMethod(name, ...args) {
|
|
669
|
+
try {
|
|
670
|
+
if (typeof homebridge?.[name] === "function") {
|
|
671
|
+
uiLog.info(`[callUiMethod] Invoking homebridge.${String(name)}()`);
|
|
672
|
+
const fn = homebridge?.[name];
|
|
673
|
+
if (typeof fn === "function") {
|
|
674
|
+
uiLog.info(`[callUiMethod] Invoking homebridge.${String(name)}()`);
|
|
675
|
+
fn.apply(homebridge, args);
|
|
676
|
+
} else {
|
|
677
|
+
uiLog.warn(`[callUiMethod] homebridge[${String(name)}] is not a function.`);
|
|
678
|
+
}
|
|
679
|
+
} else {
|
|
680
|
+
uiLog.warn(`[callUiMethod] homebridge[${String(name)}] is not a function.`);
|
|
681
|
+
}
|
|
682
|
+
} catch (e) {
|
|
683
|
+
uiLog.warn(`Homebridge UI method ${String(name)} failed:`, e);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
function showBusyUi() {
|
|
687
|
+
callUiMethod("disableSaveButton");
|
|
688
|
+
callUiMethod("showSpinner");
|
|
689
|
+
}
|
|
690
|
+
function hideBusyUi() {
|
|
691
|
+
callUiMethod("hideSpinner");
|
|
692
|
+
callUiMethod("enableSaveButton");
|
|
693
|
+
}
|
|
694
|
+
var init_modal = __esm({
|
|
695
|
+
"src/homebridge-ui/public/js/modal.ts"() {
|
|
696
|
+
"use strict";
|
|
697
|
+
init_types();
|
|
698
|
+
init_logger();
|
|
699
|
+
}
|
|
700
|
+
});
|
|
701
|
+
|
|
666
702
|
// src/homebridge-ui/public/js/discovery.ts
|
|
667
703
|
var discovery_exports = {};
|
|
668
704
|
__export(discovery_exports, {
|
|
@@ -3685,6 +3721,9 @@ var init_devices = __esm({
|
|
|
3685
3721
|
}
|
|
3686
3722
|
});
|
|
3687
3723
|
|
|
3724
|
+
// src/homebridge-ui/public/js/app.ts
|
|
3725
|
+
init_api();
|
|
3726
|
+
|
|
3688
3727
|
// src/homebridge-ui/public/js/credentials.ts
|
|
3689
3728
|
init_logger();
|
|
3690
3729
|
init_modal();
|
|
@@ -3722,7 +3761,7 @@ async function loadCredentialStatus() {
|
|
|
3722
3761
|
uiLog.error("Error loading credentials:", e);
|
|
3723
3762
|
}
|
|
3724
3763
|
}
|
|
3725
|
-
async function
|
|
3764
|
+
async function saveCredentials2() {
|
|
3726
3765
|
const token = document.getElementById("token")?.value;
|
|
3727
3766
|
const secret = document.getElementById("secret")?.value;
|
|
3728
3767
|
const saveStatus = document.getElementById("saveStatus");
|
|
@@ -3782,9 +3821,20 @@ async function saveCredentials() {
|
|
|
3782
3821
|
init_devices();
|
|
3783
3822
|
init_discovery();
|
|
3784
3823
|
window.loadCredentialStatus = loadCredentialStatus;
|
|
3785
|
-
window.saveCredentials =
|
|
3824
|
+
window.saveCredentials = saveCredentials2;
|
|
3786
3825
|
window.discoverDevices = discoverDevices2;
|
|
3826
|
+
async function checkV4Config() {
|
|
3827
|
+
const banner = document.getElementById("v4ConfigWarning");
|
|
3828
|
+
if (!banner) {
|
|
3829
|
+
return;
|
|
3830
|
+
}
|
|
3831
|
+
const isV4 = await detectV4Config();
|
|
3832
|
+
if (isV4) {
|
|
3833
|
+
banner.style.display = "block";
|
|
3834
|
+
}
|
|
3835
|
+
}
|
|
3787
3836
|
async function init() {
|
|
3837
|
+
await checkV4Config();
|
|
3788
3838
|
await loadCredentialStatus();
|
|
3789
3839
|
await initializeDiscoverySettings();
|
|
3790
3840
|
await loadConfiguredDevices();
|