@switchbot/homebridge-switchbot 5.0.0-beta.146 → 5.0.0-beta.148
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/.github/workflows/ci.yml +1 -1
- package/.github/workflows/manual-e2e.yml +3 -3
- package/config.schema.json +6 -0
- package/dist/deviceCommandMapper.d.ts +10 -0
- package/dist/deviceCommandMapper.d.ts.map +1 -0
- package/dist/deviceCommandMapper.js +319 -0
- package/dist/deviceCommandMapper.js.map +1 -0
- package/dist/deviceFactory.d.ts +2 -3
- package/dist/deviceFactory.d.ts.map +1 -1
- package/dist/deviceFactory.js +12 -3
- package/dist/deviceFactory.js.map +1 -1
- package/dist/homebridge-ui/endpoints/config.d.ts.map +1 -1
- package/dist/homebridge-ui/endpoints/config.js +1 -18
- package/dist/homebridge-ui/endpoints/config.js.map +1 -1
- package/dist/homebridge-ui/endpoints/devices.d.ts.map +1 -1
- package/dist/homebridge-ui/endpoints/devices.js +1 -350
- package/dist/homebridge-ui/endpoints/devices.js.map +1 -1
- package/dist/homebridge-ui/public/index.html +6 -0
- package/dist/homebridge-ui/public/js/advanced-settings.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/advanced-settings.js +22 -12
- package/dist/homebridge-ui/public/js/advanced-settings.js.map +1 -1
- package/dist/homebridge-ui/public/js/advanced-settings.ts +36 -25
- package/dist/homebridge-ui/public/js/api.d.ts +1 -1
- package/dist/homebridge-ui/public/js/api.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/api.js +111 -52
- package/dist/homebridge-ui/public/js/api.js.map +1 -1
- package/dist/homebridge-ui/public/js/api.ts +112 -53
- package/dist/homebridge-ui/public/js/app.js +234 -177
- package/dist/homebridge-ui/public/js/app.js.map +4 -4
- package/dist/homebridge-ui/public/js/credentials.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/credentials.js +26 -23
- package/dist/homebridge-ui/public/js/credentials.js.map +1 -1
- package/dist/homebridge-ui/public/js/credentials.ts +26 -25
- package/dist/homebridge-ui/public/js/devices-delete.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/devices-delete.js +3 -10
- package/dist/homebridge-ui/public/js/devices-delete.js.map +1 -1
- package/dist/homebridge-ui/public/js/devices-delete.ts +3 -12
- package/dist/homebridge-ui/public/js/devices.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/devices.js +0 -3
- package/dist/homebridge-ui/public/js/devices.js.map +1 -1
- package/dist/homebridge-ui/public/js/devices.ts +5 -9
- package/dist/homebridge-ui/server.js +0 -2
- package/dist/homebridge-ui/server.js.map +1 -1
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +3 -2
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +1 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +1 -0
- package/dist/settings.js.map +1 -1
- package/dist/switchbotClient.d.ts.map +1 -1
- package/dist/switchbotClient.js +42 -55
- package/dist/switchbotClient.js.map +1 -1
- package/docs/variables/default.html +1 -1
- package/package.json +1 -1
- package/src/deviceCommandMapper.ts +333 -0
- package/src/deviceFactory.ts +14 -6
- package/src/homebridge-ui/endpoints/config.ts +2 -18
- package/src/homebridge-ui/endpoints/devices.ts +1 -392
- package/src/homebridge-ui/public/index.html +6 -0
- package/src/homebridge-ui/public/js/advanced-settings.ts +36 -25
- package/src/homebridge-ui/public/js/api.ts +112 -53
- package/src/homebridge-ui/public/js/credentials.ts +26 -25
- package/src/homebridge-ui/public/js/devices-delete.ts +3 -12
- package/src/homebridge-ui/public/js/devices.ts +5 -9
- package/src/homebridge-ui/server.ts +0 -2
- package/src/platform.ts +3 -2
- package/src/settings.ts +2 -0
- package/src/switchbotClient.ts +43 -54
- package/dist/homebridge-ui/endpoints/credentials.d.ts +0 -6
- package/dist/homebridge-ui/endpoints/credentials.d.ts.map +0 -1
- package/dist/homebridge-ui/endpoints/credentials.js +0 -65
- package/dist/homebridge-ui/endpoints/credentials.js.map +0 -1
- package/src/homebridge-ui/endpoints/credentials.ts +0 -74
|
@@ -8,6 +8,98 @@ 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) {
|
|
43
|
+
try {
|
|
44
|
+
const value = homebridge?.[name];
|
|
45
|
+
if (typeof value === "function") {
|
|
46
|
+
const fn = value;
|
|
47
|
+
fn();
|
|
48
|
+
}
|
|
49
|
+
} catch (e) {
|
|
50
|
+
uiLog.warn(`Homebridge UI method ${String(name)} failed:`, e);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function showBusyUi() {
|
|
54
|
+
callUiMethod("disableSaveButton");
|
|
55
|
+
callUiMethod("showSpinner");
|
|
56
|
+
}
|
|
57
|
+
function hideBusyUi() {
|
|
58
|
+
callUiMethod("hideSpinner");
|
|
59
|
+
callUiMethod("enableSaveButton");
|
|
60
|
+
}
|
|
61
|
+
var init_modal = __esm({
|
|
62
|
+
"src/homebridge-ui/public/js/modal.ts"() {
|
|
63
|
+
"use strict";
|
|
64
|
+
init_types();
|
|
65
|
+
init_logger();
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// src/homebridge-ui/public/js/toast.ts
|
|
70
|
+
function showToast(method, message, title = "SwitchBot") {
|
|
71
|
+
try {
|
|
72
|
+
const toast = homebridge?.toast;
|
|
73
|
+
const fn = toast?.[method];
|
|
74
|
+
if (typeof fn === "function") {
|
|
75
|
+
fn(message, title);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
uiLog.info(`[Toast:${method}] ${title} - ${message}`);
|
|
79
|
+
} catch (e) {
|
|
80
|
+
uiLog.warn(`Toast ${method} failed:`, e);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function toastSuccess(message, title) {
|
|
84
|
+
showToast("success", message, title);
|
|
85
|
+
}
|
|
86
|
+
function toastError(message, title) {
|
|
87
|
+
showToast("error", message, title);
|
|
88
|
+
}
|
|
89
|
+
function toastWarning(message, title) {
|
|
90
|
+
showToast("warning", message, title);
|
|
91
|
+
}
|
|
92
|
+
function toastInfo(message, title) {
|
|
93
|
+
showToast("info", message, title);
|
|
94
|
+
}
|
|
95
|
+
var init_toast = __esm({
|
|
96
|
+
"src/homebridge-ui/public/js/toast.ts"() {
|
|
97
|
+
"use strict";
|
|
98
|
+
init_types();
|
|
99
|
+
init_logger();
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
11
103
|
// src/device-types.ts
|
|
12
104
|
function getValidDeviceTypes() {
|
|
13
105
|
const validTypes = /* @__PURE__ */ new Set();
|
|
@@ -253,36 +345,6 @@ var init_device_types = __esm({
|
|
|
253
345
|
}
|
|
254
346
|
});
|
|
255
347
|
|
|
256
|
-
// src/homebridge-ui/public/js/types.ts
|
|
257
|
-
var init_types = __esm({
|
|
258
|
-
"src/homebridge-ui/public/js/types.ts"() {
|
|
259
|
-
"use strict";
|
|
260
|
-
}
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
// src/homebridge-ui/public/js/logger.ts
|
|
264
|
-
var PREFIX, uiLog;
|
|
265
|
-
var init_logger = __esm({
|
|
266
|
-
"src/homebridge-ui/public/js/logger.ts"() {
|
|
267
|
-
"use strict";
|
|
268
|
-
PREFIX = "[SwitchBot UI/html]";
|
|
269
|
-
uiLog = {
|
|
270
|
-
info: (message, ...parameters) => {
|
|
271
|
-
console.log(PREFIX, message, ...parameters);
|
|
272
|
-
},
|
|
273
|
-
warn: (message, ...parameters) => {
|
|
274
|
-
console.warn(PREFIX, message, ...parameters);
|
|
275
|
-
},
|
|
276
|
-
error: (message, ...parameters) => {
|
|
277
|
-
console.error(PREFIX, message, ...parameters);
|
|
278
|
-
},
|
|
279
|
-
debug: (message, ...parameters) => {
|
|
280
|
-
console.debug(PREFIX, message, ...parameters);
|
|
281
|
-
}
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
|
|
286
348
|
// src/homebridge-ui/public/js/api.ts
|
|
287
349
|
var api_exports = {};
|
|
288
350
|
__export(api_exports, {
|
|
@@ -294,12 +356,29 @@ __export(api_exports, {
|
|
|
294
356
|
fetchBluetoothStatus: () => fetchBluetoothStatus,
|
|
295
357
|
fetchCredentialStatus: () => fetchCredentialStatus,
|
|
296
358
|
fetchDevices: () => fetchDevices,
|
|
297
|
-
saveCredentials: () =>
|
|
359
|
+
saveCredentials: () => saveCredentials2,
|
|
298
360
|
syncParentPluginConfigFromDisk: () => syncParentPluginConfigFromDisk,
|
|
299
361
|
testDeviceConnection: () => testDeviceConnection,
|
|
300
362
|
updateDevice: () => updateDevice,
|
|
301
363
|
validateAndFixDeviceTypes: () => validateAndFixDeviceTypes
|
|
302
364
|
});
|
|
365
|
+
async function fetchDevices() {
|
|
366
|
+
try {
|
|
367
|
+
if (typeof homebridge.getPluginConfig !== "function") {
|
|
368
|
+
throw new TypeError("Homebridge UI API not available");
|
|
369
|
+
}
|
|
370
|
+
const configArr = await homebridge.getPluginConfig();
|
|
371
|
+
const config = Array.isArray(configArr) && configArr.length > 0 ? configArr.find(isSwitchBotPlatformConfig) : null;
|
|
372
|
+
if (!config || !Array.isArray(config.devices)) {
|
|
373
|
+
return [];
|
|
374
|
+
}
|
|
375
|
+
return config.devices;
|
|
376
|
+
} catch (e) {
|
|
377
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
378
|
+
uiLog.error("Error fetching devices:", msg);
|
|
379
|
+
return [];
|
|
380
|
+
}
|
|
381
|
+
}
|
|
303
382
|
function validateAndFixDeviceTypes(devices) {
|
|
304
383
|
const errors = [];
|
|
305
384
|
for (const d of devices) {
|
|
@@ -375,7 +454,7 @@ async function fetchCredentialStatus() {
|
|
|
375
454
|
return null;
|
|
376
455
|
}
|
|
377
456
|
}
|
|
378
|
-
async function
|
|
457
|
+
async function saveCredentials2(token, secret) {
|
|
379
458
|
uiLog.info("Saving credentials...");
|
|
380
459
|
const resp = await homebridge.request("/credentials", { token, secret });
|
|
381
460
|
uiLog.info("Save response:", resp);
|
|
@@ -384,20 +463,6 @@ async function saveCredentials(token, secret) {
|
|
|
384
463
|
}
|
|
385
464
|
return resp.data || resp;
|
|
386
465
|
}
|
|
387
|
-
async function fetchDevices() {
|
|
388
|
-
try {
|
|
389
|
-
const resp = await homebridge.request("/devices", {});
|
|
390
|
-
if (!resp || resp.success === false) {
|
|
391
|
-
const backendMsg = resp?.data?.message || resp?.message;
|
|
392
|
-
throw new Error(backendMsg || "request failed");
|
|
393
|
-
}
|
|
394
|
-
return resp.data || [];
|
|
395
|
-
} catch (e) {
|
|
396
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
397
|
-
uiLog.error("Error fetching devices:", msg);
|
|
398
|
-
return [];
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
466
|
async function discoverDevices(mode = "all", options) {
|
|
402
467
|
const resp = await homebridge.request("/discover", { mode, ...options });
|
|
403
468
|
uiLog.info("Discover response:", resp);
|
|
@@ -431,29 +496,45 @@ async function testDeviceConnection(payload) {
|
|
|
431
496
|
};
|
|
432
497
|
}
|
|
433
498
|
async function addDevice(deviceId, name, type, options) {
|
|
434
|
-
|
|
499
|
+
if (typeof homebridge.getPluginConfig !== "function" || typeof homebridge.updatePluginConfig !== "function") {
|
|
500
|
+
throw new TypeError("Homebridge UI API not available");
|
|
501
|
+
}
|
|
502
|
+
const configArr = await homebridge.getPluginConfig();
|
|
503
|
+
const idx = Array.isArray(configArr) ? configArr.findIndex(isSwitchBotPlatformConfig) : -1;
|
|
504
|
+
if (idx === -1) {
|
|
505
|
+
throw new Error("SwitchBot config not found");
|
|
506
|
+
}
|
|
507
|
+
const config = configArr[idx];
|
|
508
|
+
if (!Array.isArray(config.devices)) {
|
|
509
|
+
config.devices = [];
|
|
510
|
+
}
|
|
511
|
+
const normalizedDeviceId = String(deviceId).trim().toLowerCase();
|
|
512
|
+
const exists = config.devices.some((d) => String(d.deviceId ?? d.id ?? "").trim().toLowerCase() === normalizedDeviceId);
|
|
513
|
+
if (exists) {
|
|
514
|
+
return { alreadyExists: true, message: "Device already in config" };
|
|
515
|
+
}
|
|
516
|
+
const newDevice = { deviceId, configDeviceName: name, configDeviceType: type };
|
|
435
517
|
if (options?.address) {
|
|
436
|
-
|
|
518
|
+
newDevice.address = options.address;
|
|
437
519
|
}
|
|
438
520
|
if (options?.model) {
|
|
439
|
-
|
|
521
|
+
newDevice.model = options.model;
|
|
440
522
|
}
|
|
441
523
|
if (options?.rssi !== void 0 && options?.rssi !== null && options?.rssi !== 0) {
|
|
442
|
-
|
|
524
|
+
newDevice.rssi = options.rssi;
|
|
443
525
|
}
|
|
444
526
|
if (options?.encryptionKey) {
|
|
445
|
-
|
|
527
|
+
newDevice.encryptionKey = options.encryptionKey;
|
|
446
528
|
}
|
|
447
529
|
if (options?.keyId) {
|
|
448
|
-
|
|
530
|
+
newDevice.keyId = options.keyId;
|
|
449
531
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
throw new Error(resp?.data?.message || "Failed to add device");
|
|
532
|
+
config.devices.push(newDevice);
|
|
533
|
+
await homebridge.updatePluginConfig(configArr);
|
|
534
|
+
if (typeof homebridge.savePluginConfig === "function") {
|
|
535
|
+
await homebridge.savePluginConfig();
|
|
455
536
|
}
|
|
456
|
-
return
|
|
537
|
+
return { added: true, message: `Device "${name}" added successfully` };
|
|
457
538
|
}
|
|
458
539
|
async function addDevicesInBulk(devices) {
|
|
459
540
|
const resp = await homebridge.request("/add-devices", { devices });
|
|
@@ -464,108 +545,88 @@ async function addDevicesInBulk(devices) {
|
|
|
464
545
|
return resp.data || resp;
|
|
465
546
|
}
|
|
466
547
|
async function updateDevice(deviceId, configDeviceName, configDeviceType, options) {
|
|
467
|
-
|
|
548
|
+
if (typeof homebridge.getPluginConfig !== "function" || typeof homebridge.updatePluginConfig !== "function") {
|
|
549
|
+
throw new TypeError("Homebridge UI API not available");
|
|
550
|
+
}
|
|
551
|
+
const configArr = await homebridge.getPluginConfig();
|
|
552
|
+
const idx = Array.isArray(configArr) ? configArr.findIndex(isSwitchBotPlatformConfig) : -1;
|
|
553
|
+
if (idx === -1) {
|
|
554
|
+
throw new Error("SwitchBot config not found");
|
|
555
|
+
}
|
|
556
|
+
const config = configArr[idx];
|
|
557
|
+
if (!Array.isArray(config.devices)) {
|
|
558
|
+
throw new TypeError("No devices array in config");
|
|
559
|
+
}
|
|
560
|
+
const normalizedDeviceId = String(deviceId).trim().toLowerCase();
|
|
561
|
+
const device = config.devices.find((d) => String(d.deviceId ?? d.id ?? "").trim().toLowerCase() === normalizedDeviceId);
|
|
562
|
+
if (!device) {
|
|
563
|
+
throw new Error("Device not found in config");
|
|
564
|
+
}
|
|
468
565
|
if (configDeviceName) {
|
|
469
|
-
|
|
566
|
+
device.configDeviceName = configDeviceName;
|
|
470
567
|
}
|
|
471
568
|
if (configDeviceType) {
|
|
472
|
-
|
|
569
|
+
device.configDeviceType = configDeviceType;
|
|
473
570
|
}
|
|
474
571
|
if (options) {
|
|
475
|
-
Object.assign(
|
|
572
|
+
Object.assign(device, options);
|
|
476
573
|
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
if (!resp || resp.success === false) {
|
|
481
|
-
throw new Error(resp?.data?.message || "Failed to update device");
|
|
574
|
+
await homebridge.updatePluginConfig(configArr);
|
|
575
|
+
if (typeof homebridge.savePluginConfig === "function") {
|
|
576
|
+
await homebridge.savePluginConfig();
|
|
482
577
|
}
|
|
483
|
-
return
|
|
578
|
+
return { updated: true, message: `Device updated successfully` };
|
|
484
579
|
}
|
|
485
580
|
async function deleteDevice(deviceId) {
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
uiLog.info("Delete response:", resp);
|
|
489
|
-
if (!resp || resp.success === false) {
|
|
490
|
-
throw new Error(resp?.data?.message || "Failed to delete device");
|
|
581
|
+
if (typeof homebridge.getPluginConfig !== "function" || typeof homebridge.updatePluginConfig !== "function") {
|
|
582
|
+
throw new TypeError("Homebridge UI API not available");
|
|
491
583
|
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
const resp = await homebridge.request("/delete-all-devices", {});
|
|
497
|
-
uiLog.info("Delete all response:", resp);
|
|
498
|
-
if (!resp || resp.success === false) {
|
|
499
|
-
throw new Error(resp?.data?.message || "Failed to delete all devices");
|
|
584
|
+
const configArr = await homebridge.getPluginConfig();
|
|
585
|
+
const idx = Array.isArray(configArr) ? configArr.findIndex(isSwitchBotPlatformConfig) : -1;
|
|
586
|
+
if (idx === -1) {
|
|
587
|
+
throw new Error("SwitchBot config not found");
|
|
500
588
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
"src/homebridge-ui/public/js/api.ts"() {
|
|
505
|
-
"use strict";
|
|
506
|
-
init_device_types();
|
|
507
|
-
init_types();
|
|
508
|
-
init_logger();
|
|
589
|
+
const config = configArr[idx];
|
|
590
|
+
if (!Array.isArray(config.devices)) {
|
|
591
|
+
throw new TypeError("No devices array in config");
|
|
509
592
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
const value = homebridge?.[name];
|
|
516
|
-
if (typeof value === "function") {
|
|
517
|
-
const fn = value;
|
|
518
|
-
fn();
|
|
519
|
-
}
|
|
520
|
-
} catch (e) {
|
|
521
|
-
uiLog.warn(`Homebridge UI method ${String(name)} failed:`, e);
|
|
593
|
+
const normalizedDeviceId = String(deviceId).trim().toLowerCase();
|
|
594
|
+
const before = config.devices.length;
|
|
595
|
+
config.devices = config.devices.filter((d) => String(d.deviceId ?? d.id ?? "").trim().toLowerCase() !== normalizedDeviceId);
|
|
596
|
+
if (config.devices.length === before) {
|
|
597
|
+
throw new Error("Device not found in config");
|
|
522
598
|
}
|
|
599
|
+
await homebridge.updatePluginConfig(configArr);
|
|
600
|
+
if (typeof homebridge.savePluginConfig === "function") {
|
|
601
|
+
await homebridge.savePluginConfig();
|
|
602
|
+
}
|
|
603
|
+
return { deleted: true, message: `Device removed from config` };
|
|
523
604
|
}
|
|
524
|
-
function
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
}
|
|
528
|
-
function hideBusyUi() {
|
|
529
|
-
callUiMethod("hideSpinner");
|
|
530
|
-
callUiMethod("enableSaveButton");
|
|
531
|
-
}
|
|
532
|
-
var init_modal = __esm({
|
|
533
|
-
"src/homebridge-ui/public/js/modal.ts"() {
|
|
534
|
-
"use strict";
|
|
535
|
-
init_types();
|
|
536
|
-
init_logger();
|
|
605
|
+
async function deleteAllDevices() {
|
|
606
|
+
if (typeof homebridge.getPluginConfig !== "function" || typeof homebridge.updatePluginConfig !== "function") {
|
|
607
|
+
throw new TypeError("Homebridge UI API not available");
|
|
537
608
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
try {
|
|
543
|
-
const toast = homebridge?.toast;
|
|
544
|
-
const fn = toast?.[method];
|
|
545
|
-
if (typeof fn === "function") {
|
|
546
|
-
fn(message, title);
|
|
547
|
-
return;
|
|
548
|
-
}
|
|
549
|
-
uiLog.info(`[Toast:${method}] ${title} - ${message}`);
|
|
550
|
-
} catch (e) {
|
|
551
|
-
uiLog.warn(`Toast ${method} failed:`, e);
|
|
609
|
+
const configArr = await homebridge.getPluginConfig();
|
|
610
|
+
const idx = Array.isArray(configArr) ? configArr.findIndex(isSwitchBotPlatformConfig) : -1;
|
|
611
|
+
if (idx === -1) {
|
|
612
|
+
throw new Error("SwitchBot config not found");
|
|
552
613
|
}
|
|
614
|
+
const config = configArr[idx];
|
|
615
|
+
if (!Array.isArray(config.devices)) {
|
|
616
|
+
throw new TypeError("No devices array in config");
|
|
617
|
+
}
|
|
618
|
+
const deletedCount = config.devices.length;
|
|
619
|
+
config.devices = [];
|
|
620
|
+
await homebridge.updatePluginConfig(configArr);
|
|
621
|
+
if (typeof homebridge.savePluginConfig === "function") {
|
|
622
|
+
await homebridge.savePluginConfig();
|
|
623
|
+
}
|
|
624
|
+
return { deleted: true, deletedCount, message: `Removed ${deletedCount} device(s) from config` };
|
|
553
625
|
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
}
|
|
557
|
-
function toastError(message, title) {
|
|
558
|
-
showToast("error", message, title);
|
|
559
|
-
}
|
|
560
|
-
function toastWarning(message, title) {
|
|
561
|
-
showToast("warning", message, title);
|
|
562
|
-
}
|
|
563
|
-
function toastInfo(message, title) {
|
|
564
|
-
showToast("info", message, title);
|
|
565
|
-
}
|
|
566
|
-
var init_toast = __esm({
|
|
567
|
-
"src/homebridge-ui/public/js/toast.ts"() {
|
|
626
|
+
var init_api = __esm({
|
|
627
|
+
"src/homebridge-ui/public/js/api.ts"() {
|
|
568
628
|
"use strict";
|
|
629
|
+
init_device_types();
|
|
569
630
|
init_types();
|
|
570
631
|
init_logger();
|
|
571
632
|
}
|
|
@@ -2569,12 +2630,9 @@ async function deleteDeviceFromConfig(deviceId, deviceName) {
|
|
|
2569
2630
|
}
|
|
2570
2631
|
try {
|
|
2571
2632
|
showBusyUi();
|
|
2572
|
-
uiLog.info("
|
|
2633
|
+
uiLog.info("Deleting device from config:", deviceId);
|
|
2573
2634
|
const resp = await deleteDevice(deviceId);
|
|
2574
2635
|
uiLog.info("Delete response:", resp);
|
|
2575
|
-
if (!resp || resp.success === false) {
|
|
2576
|
-
throw new Error(resp?.data?.message || "Failed to delete device");
|
|
2577
|
-
}
|
|
2578
2636
|
uiLog.info("Syncing parent config from disk...");
|
|
2579
2637
|
const synced = await syncParentPluginConfigFromDisk(true);
|
|
2580
2638
|
if (!synced) {
|
|
@@ -2672,12 +2730,9 @@ async function deleteAllDevicesFromConfig() {
|
|
|
2672
2730
|
return;
|
|
2673
2731
|
}
|
|
2674
2732
|
showBusyUi();
|
|
2675
|
-
uiLog.info("
|
|
2733
|
+
uiLog.info("Deleting all devices from config");
|
|
2676
2734
|
const resp = await deleteAllDevices();
|
|
2677
2735
|
uiLog.info("Delete all response:", resp);
|
|
2678
|
-
if (!resp || resp.success === false) {
|
|
2679
|
-
throw new Error(resp?.data?.message || "Failed to delete all devices");
|
|
2680
|
-
}
|
|
2681
2736
|
uiLog.info("Syncing parent config from disk...");
|
|
2682
2737
|
const synced = await syncParentPluginConfigFromDisk(true);
|
|
2683
2738
|
if (!synced) {
|
|
@@ -2687,7 +2742,7 @@ async function deleteAllDevicesFromConfig() {
|
|
|
2687
2742
|
const updatedList = await fetchDevices();
|
|
2688
2743
|
uiLog.info("Rendering devices:", updatedList.length);
|
|
2689
2744
|
renderDeviceList(updatedList);
|
|
2690
|
-
const deletedCount = resp?.deletedCount ||
|
|
2745
|
+
const deletedCount = resp?.deletedCount || 0;
|
|
2691
2746
|
uiLog.info(`\u2713 Removed ${deletedCount} device(s) successfully`);
|
|
2692
2747
|
toastSuccess(`Removed ${deletedCount} device(s) successfully`);
|
|
2693
2748
|
} catch (e) {
|
|
@@ -3611,9 +3666,6 @@ async function addDeviceToConfig2(device, options = {}) {
|
|
|
3611
3666
|
keyId: importValues.keyId
|
|
3612
3667
|
});
|
|
3613
3668
|
uiLog.info("Add device response:", resp);
|
|
3614
|
-
if (!resp || resp.success === false) {
|
|
3615
|
-
throw new Error(resp?.data?.message || "Failed to add device");
|
|
3616
|
-
}
|
|
3617
3669
|
const alreadyExists = !!resp?.alreadyExists;
|
|
3618
3670
|
const message = resp?.message || (alreadyExists ? `Device "${importValues.configDeviceName}" already in config` : `Device "${importValues.configDeviceName}" added successfully!`);
|
|
3619
3671
|
if (alreadyExists) {
|
|
@@ -3682,31 +3734,33 @@ var init_devices = __esm({
|
|
|
3682
3734
|
});
|
|
3683
3735
|
|
|
3684
3736
|
// src/homebridge-ui/public/js/credentials.ts
|
|
3685
|
-
init_api();
|
|
3686
3737
|
init_logger();
|
|
3687
3738
|
init_modal();
|
|
3688
3739
|
init_toast();
|
|
3689
3740
|
async function loadCredentialStatus() {
|
|
3690
3741
|
try {
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
uiLog.error("Failed to load credentials");
|
|
3742
|
+
if (typeof homebridge.getPluginConfig !== "function") {
|
|
3743
|
+
uiLog.error("Homebridge UI API not available");
|
|
3694
3744
|
return;
|
|
3695
3745
|
}
|
|
3746
|
+
const configArr = await homebridge.getPluginConfig();
|
|
3747
|
+
const config = Array.isArray(configArr) && configArr.length > 0 ? configArr[0] : {};
|
|
3748
|
+
const token = config.openApiToken || "";
|
|
3749
|
+
const secret = config.openApiSecret || "";
|
|
3696
3750
|
const tokenStatus = document.getElementById("tokenStatus");
|
|
3697
3751
|
const secretStatus = document.getElementById("secretStatus");
|
|
3698
3752
|
if (!tokenStatus || !secretStatus) {
|
|
3699
3753
|
return;
|
|
3700
3754
|
}
|
|
3701
|
-
if (
|
|
3702
|
-
tokenStatus.textContent = `\u2713 Configured (${
|
|
3755
|
+
if (token) {
|
|
3756
|
+
tokenStatus.textContent = `\u2713 Configured (${token.length} characters)`;
|
|
3703
3757
|
tokenStatus.classList.add("ok");
|
|
3704
3758
|
} else {
|
|
3705
3759
|
tokenStatus.textContent = "Not configured";
|
|
3706
3760
|
tokenStatus.classList.remove("ok");
|
|
3707
3761
|
}
|
|
3708
|
-
if (
|
|
3709
|
-
secretStatus.textContent = `\u2713 Configured (${
|
|
3762
|
+
if (secret) {
|
|
3763
|
+
secretStatus.textContent = `\u2713 Configured (${secret.length} characters)`;
|
|
3710
3764
|
secretStatus.classList.add("ok");
|
|
3711
3765
|
} else {
|
|
3712
3766
|
secretStatus.textContent = "Not configured";
|
|
@@ -3716,7 +3770,7 @@ async function loadCredentialStatus() {
|
|
|
3716
3770
|
uiLog.error("Error loading credentials:", e);
|
|
3717
3771
|
}
|
|
3718
3772
|
}
|
|
3719
|
-
async function
|
|
3773
|
+
async function saveCredentials() {
|
|
3720
3774
|
const token = document.getElementById("token")?.value;
|
|
3721
3775
|
const secret = document.getElementById("secret")?.value;
|
|
3722
3776
|
const saveStatus = document.getElementById("saveStatus");
|
|
@@ -3735,21 +3789,24 @@ async function saveCredentials2() {
|
|
|
3735
3789
|
saveBtn.disabled = true;
|
|
3736
3790
|
saveBtn.textContent = "Saving...";
|
|
3737
3791
|
uiLog.info("Saving credentials...");
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3792
|
+
if (typeof homebridge.getPluginConfig !== "function" || typeof homebridge.updatePluginConfig !== "function") {
|
|
3793
|
+
throw new TypeError("Homebridge UI API not available");
|
|
3794
|
+
}
|
|
3795
|
+
const configArr = await homebridge.getPluginConfig();
|
|
3796
|
+
if (!Array.isArray(configArr) || configArr.length === 0) {
|
|
3797
|
+
throw new Error("No plugin config found");
|
|
3798
|
+
}
|
|
3799
|
+
const config = configArr[0];
|
|
3800
|
+
config.openApiToken = token;
|
|
3801
|
+
config.openApiSecret = secret;
|
|
3802
|
+
await homebridge.updatePluginConfig([config]);
|
|
3803
|
+
if (typeof homebridge.savePluginConfig === "function") {
|
|
3804
|
+
await homebridge.savePluginConfig();
|
|
3805
|
+
}
|
|
3806
|
+
saveStatus.textContent = `\u2713 Credentials saved successfully`;
|
|
3742
3807
|
saveStatus.classList.remove("error");
|
|
3743
3808
|
saveStatus.classList.add("success-msg");
|
|
3744
|
-
toastSuccess(
|
|
3745
|
-
const synced = await syncParentPluginConfigFromDisk(true);
|
|
3746
|
-
if (synced) {
|
|
3747
|
-
saveStatus.textContent += " - Config saved automatically.";
|
|
3748
|
-
toastSuccess("Configuration synced and saved automatically");
|
|
3749
|
-
} else {
|
|
3750
|
-
toastWarning("Credentials saved, but configuration sync failed");
|
|
3751
|
-
}
|
|
3752
|
-
;
|
|
3809
|
+
toastSuccess("Credentials saved successfully");
|
|
3753
3810
|
document.getElementById("token").value = "";
|
|
3754
3811
|
document.getElementById("secret").value = "";
|
|
3755
3812
|
setTimeout(loadCredentialStatus, 500);
|
|
@@ -3773,7 +3830,7 @@ async function saveCredentials2() {
|
|
|
3773
3830
|
init_devices();
|
|
3774
3831
|
init_discovery();
|
|
3775
3832
|
window.loadCredentialStatus = loadCredentialStatus;
|
|
3776
|
-
window.saveCredentials =
|
|
3833
|
+
window.saveCredentials = saveCredentials;
|
|
3777
3834
|
window.discoverDevices = discoverDevices2;
|
|
3778
3835
|
async function init() {
|
|
3779
3836
|
await loadCredentialStatus();
|