@switchbot/homebridge-switchbot 5.0.0-beta.133 → 5.0.0-beta.135
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/config.schema.json +0 -11
- package/dist/deviceFactory.d.ts +3 -1
- package/dist/deviceFactory.d.ts.map +1 -1
- package/dist/deviceFactory.js +3 -18
- package/dist/deviceFactory.js.map +1 -1
- package/dist/devices/genericDevice.d.ts +1 -1
- package/dist/devices/genericDevice.d.ts.map +1 -1
- package/dist/devices/genericDevice.js +67 -19
- package/dist/devices/genericDevice.js.map +1 -1
- package/dist/homebridge-ui/public/index.html +107 -124
- package/dist/homebridge-ui/public/js/api.d.ts +1 -4
- package/dist/homebridge-ui/public/js/api.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/api.js +1 -7
- package/dist/homebridge-ui/public/js/api.js.map +1 -1
- package/dist/homebridge-ui/public/js/api.ts +1 -8
- package/dist/homebridge-ui/public/js/app.js +201 -90
- package/dist/homebridge-ui/public/js/app.js.map +2 -2
- package/dist/homebridge-ui/public/js/app.ts +5 -6
- package/dist/homebridge-ui/public/js/credentials.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/credentials.js +1 -1
- package/dist/homebridge-ui/public/js/credentials.js.map +1 -1
- package/dist/homebridge-ui/public/js/credentials.ts +7 -3
- package/dist/homebridge-ui/public/js/devices-delete.js +1 -1
- package/dist/homebridge-ui/public/js/devices-delete.js.map +1 -1
- package/dist/homebridge-ui/public/js/devices-delete.ts +1 -1
- package/dist/homebridge-ui/public/js/devices.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/devices.js +0 -1
- package/dist/homebridge-ui/public/js/devices.js.map +1 -1
- package/dist/homebridge-ui/public/js/devices.ts +0 -2
- package/dist/homebridge-ui/public/js/discovery.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/discovery.js +6 -3
- package/dist/homebridge-ui/public/js/discovery.js.map +1 -1
- package/dist/homebridge-ui/public/js/discovery.ts +9 -3
- package/dist/homebridge-ui/public/js/logger.d.ts +1 -0
- package/dist/homebridge-ui/public/js/logger.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/logger.js +8 -3
- package/dist/homebridge-ui/public/js/logger.js.map +1 -1
- package/dist/homebridge-ui/public/js/logger.ts +12 -6
- package/dist/homebridge-ui/public/js/modals.d.ts +4 -0
- package/dist/homebridge-ui/public/js/modals.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/modals.js +152 -59
- package/dist/homebridge-ui/public/js/modals.js.map +1 -1
- package/dist/homebridge-ui/public/js/modals.ts +187 -60
- package/dist/homebridge-ui/public/js/render.d.ts +3 -0
- package/dist/homebridge-ui/public/js/render.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/render.js +63 -24
- package/dist/homebridge-ui/public/js/render.js.map +1 -1
- package/dist/homebridge-ui/public/js/render.ts +102 -51
- package/dist/homebridge-ui/utils/logger.js +1 -1
- package/dist/homebridge-ui/utils/logger.js.map +1 -1
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +38 -30
- package/dist/platform.js.map +1 -1
- package/dist/switchbotClient.d.ts +5 -5
- package/dist/switchbotClient.d.ts.map +1 -1
- package/dist/switchbotClient.js +21 -12
- package/dist/switchbotClient.js.map +1 -1
- package/docs/variables/default.html +1 -1
- package/package.json +1 -1
- package/scripts/build-ui.js +4 -3
- package/scripts/generate-matter-maps.js +34 -17
- package/scripts/sync-device-types.mjs +4 -1
- package/src/deviceFactory.ts +3 -18
- package/src/devices/genericDevice.ts +69 -21
- package/src/homebridge-ui/public/index.html +107 -124
- package/src/homebridge-ui/public/js/api.ts +1 -8
- package/src/homebridge-ui/public/js/app.ts +5 -6
- package/src/homebridge-ui/public/js/credentials.ts +7 -3
- package/src/homebridge-ui/public/js/devices-delete.ts +1 -1
- package/src/homebridge-ui/public/js/devices.ts +0 -2
- package/src/homebridge-ui/public/js/discovery.ts +9 -3
- package/src/homebridge-ui/public/js/logger.ts +12 -6
- package/src/homebridge-ui/public/js/modals.ts +187 -60
- package/src/homebridge-ui/public/js/render.ts +102 -51
- package/src/homebridge-ui/utils/logger.ts +1 -1
- package/src/platform.ts +38 -29
- package/src/switchbotClient.ts +42 -27
- package/test/accessory-restore.spec.ts +9 -8
- package/test/device-mapping.spec.ts +4 -3
- package/test/deviceFactory.spec.ts +4 -3
- package/test/e2e/run-e2e.spec.ts +6 -10
- package/test/fan-swing.spec.ts +7 -6
- package/test/helpers/matter-harness.ts +18 -7
- package/test/lock-users.spec.ts +5 -5
- package/test/matter-childbridge.spec.ts +10 -7
- package/test/matter-descriptors.spec.ts +8 -8
- package/test/matter-device-state.spec.ts +52 -36
- package/test/matter-integration.spec.ts +53 -6
- package/test/platform.integration.spec.ts +7 -5
- package/test/switchbot-client-debounce.spec.ts +36 -40
- package/test/switchbot-client-openapi.spec.ts +22 -15
- package/test/switchbotClient.spec.ts +4 -3
- package/test/utils.spec.ts +2 -1
|
@@ -261,19 +261,23 @@ var init_types = __esm({
|
|
|
261
261
|
});
|
|
262
262
|
|
|
263
263
|
// src/homebridge-ui/public/js/logger.ts
|
|
264
|
-
var uiLog;
|
|
264
|
+
var PREFIX, uiLog;
|
|
265
265
|
var init_logger = __esm({
|
|
266
266
|
"src/homebridge-ui/public/js/logger.ts"() {
|
|
267
267
|
"use strict";
|
|
268
|
+
PREFIX = "[SwitchBot UI/html]";
|
|
268
269
|
uiLog = {
|
|
269
270
|
info: (message, ...parameters) => {
|
|
270
|
-
console.
|
|
271
|
+
console.log(PREFIX, message, ...parameters);
|
|
271
272
|
},
|
|
272
273
|
warn: (message, ...parameters) => {
|
|
273
|
-
console.warn(
|
|
274
|
+
console.warn(PREFIX, message, ...parameters);
|
|
274
275
|
},
|
|
275
276
|
error: (message, ...parameters) => {
|
|
276
|
-
console.error(
|
|
277
|
+
console.error(PREFIX, message, ...parameters);
|
|
278
|
+
},
|
|
279
|
+
debug: (message, ...parameters) => {
|
|
280
|
+
console.debug(PREFIX, message, ...parameters);
|
|
277
281
|
}
|
|
278
282
|
};
|
|
279
283
|
}
|
|
@@ -443,9 +447,6 @@ async function addDevice(deviceId, name, type, options) {
|
|
|
443
447
|
if (options?.keyId) {
|
|
444
448
|
payload.keyId = options.keyId;
|
|
445
449
|
}
|
|
446
|
-
if (options?.matterType !== void 0) {
|
|
447
|
-
payload.matterType = options.matterType;
|
|
448
|
-
}
|
|
449
450
|
uiLog.info("Adding device to config:", payload);
|
|
450
451
|
const resp = await homebridge.request("/add-device", payload);
|
|
451
452
|
uiLog.info("Add device response:", resp);
|
|
@@ -462,7 +463,7 @@ async function addDevicesInBulk(devices) {
|
|
|
462
463
|
}
|
|
463
464
|
return resp.data || resp;
|
|
464
465
|
}
|
|
465
|
-
async function updateDevice(deviceId, configDeviceName, configDeviceType
|
|
466
|
+
async function updateDevice(deviceId, configDeviceName, configDeviceType) {
|
|
466
467
|
const params = { deviceId };
|
|
467
468
|
if (configDeviceName) {
|
|
468
469
|
params.configDeviceName = configDeviceName;
|
|
@@ -470,9 +471,6 @@ async function updateDevice(deviceId, configDeviceName, configDeviceType, option
|
|
|
470
471
|
if (configDeviceType) {
|
|
471
472
|
params.configDeviceType = configDeviceType;
|
|
472
473
|
}
|
|
473
|
-
if (options?.matterType !== void 0) {
|
|
474
|
-
params.matterType = options.matterType;
|
|
475
|
-
}
|
|
476
474
|
uiLog.info("[Update Device] Sending update request with params:", params);
|
|
477
475
|
const resp = await homebridge.request("/update-device", params);
|
|
478
476
|
uiLog.info("[Update Device] Update response:", resp);
|
|
@@ -1637,9 +1635,15 @@ async function updateDiscoveryView(allDevices, preferences, groupBy, hideAdded,
|
|
|
1637
1635
|
const enableSelectedBtn = document.querySelector("button")?.parentElement?.querySelector('button[aria-label="Enable Selected"]');
|
|
1638
1636
|
const disableSelectedBtn = document.querySelector("button")?.parentElement?.querySelector('button[aria-label="Disable Selected"]');
|
|
1639
1637
|
const hasSelection = selectedIds.size > 0;
|
|
1640
|
-
if (addSelectedBtn)
|
|
1641
|
-
|
|
1642
|
-
|
|
1638
|
+
if (addSelectedBtn) {
|
|
1639
|
+
addSelectedBtn.disabled = !hasSelection;
|
|
1640
|
+
}
|
|
1641
|
+
if (enableSelectedBtn) {
|
|
1642
|
+
enableSelectedBtn.disabled = !hasSelection;
|
|
1643
|
+
}
|
|
1644
|
+
if (disableSelectedBtn) {
|
|
1645
|
+
disableSelectedBtn.disabled = !hasSelection;
|
|
1646
|
+
}
|
|
1643
1647
|
}
|
|
1644
1648
|
window.removeEventListener("discovery-selection-changed", updateBatchButtonStates);
|
|
1645
1649
|
window.addEventListener("discovery-selection-changed", updateBatchButtonStates);
|
|
@@ -1925,6 +1929,44 @@ async function importDiscoveredDevice(device) {
|
|
|
1925
1929
|
});
|
|
1926
1930
|
typeSelect.appendChild(optgroup);
|
|
1927
1931
|
});
|
|
1932
|
+
const connectionPrefLabel = document.createElement("label");
|
|
1933
|
+
connectionPrefLabel.textContent = "Connection Preference";
|
|
1934
|
+
connectionPrefLabel.style.display = "block";
|
|
1935
|
+
connectionPrefLabel.style.marginBottom = "6px";
|
|
1936
|
+
connectionPrefLabel.style.fontWeight = "500";
|
|
1937
|
+
connectionPrefLabel.style.fontSize = "12px";
|
|
1938
|
+
connectionPrefLabel.style.color = "#6b7280";
|
|
1939
|
+
const connectionPrefSelect = document.createElement("select");
|
|
1940
|
+
connectionPrefSelect.style.width = "100%";
|
|
1941
|
+
connectionPrefSelect.style.marginBottom = "12px";
|
|
1942
|
+
connectionPrefSelect.style.padding = "8px 10px";
|
|
1943
|
+
connectionPrefSelect.style.borderRadius = "6px";
|
|
1944
|
+
connectionPrefSelect.style.fontSize = "14px";
|
|
1945
|
+
connectionPrefSelect.style.boxSizing = "border-box";
|
|
1946
|
+
["auto", "ble", "openapi"].forEach((val) => {
|
|
1947
|
+
const opt = document.createElement("option");
|
|
1948
|
+
opt.value = val;
|
|
1949
|
+
opt.text = val.charAt(0).toUpperCase() + val.slice(1);
|
|
1950
|
+
opt.selected = (device.connectionPreference || "auto") === val;
|
|
1951
|
+
connectionPrefSelect.appendChild(opt);
|
|
1952
|
+
});
|
|
1953
|
+
const roomLabel = document.createElement("label");
|
|
1954
|
+
roomLabel.textContent = "Room";
|
|
1955
|
+
roomLabel.style.display = "block";
|
|
1956
|
+
roomLabel.style.marginBottom = "6px";
|
|
1957
|
+
roomLabel.style.fontWeight = "500";
|
|
1958
|
+
roomLabel.style.fontSize = "12px";
|
|
1959
|
+
roomLabel.style.color = "#6b7280";
|
|
1960
|
+
const roomInput = document.createElement("input");
|
|
1961
|
+
roomInput.type = "text";
|
|
1962
|
+
roomInput.value = device.room || "";
|
|
1963
|
+
roomInput.placeholder = "Optional room/location metadata";
|
|
1964
|
+
roomInput.style.width = "100%";
|
|
1965
|
+
roomInput.style.marginBottom = "12px";
|
|
1966
|
+
roomInput.style.padding = "8px 10px";
|
|
1967
|
+
roomInput.style.borderRadius = "6px";
|
|
1968
|
+
roomInput.style.fontSize = "14px";
|
|
1969
|
+
roomInput.style.boxSizing = "border-box";
|
|
1928
1970
|
const macLabel = document.createElement("label");
|
|
1929
1971
|
macLabel.textContent = "BLE MAC Address (optional)";
|
|
1930
1972
|
macLabel.style.display = "block";
|
|
@@ -2003,6 +2045,8 @@ async function importDiscoveredDevice(device) {
|
|
|
2003
2045
|
configDeviceName: nameInput.value || device.name || device.id,
|
|
2004
2046
|
configDeviceType: typeSelect.value || device.type,
|
|
2005
2047
|
address: macInput.value || void 0,
|
|
2048
|
+
connectionPreference: connectionPrefSelect.value || void 0,
|
|
2049
|
+
room: roomInput.value || void 0,
|
|
2006
2050
|
encryptionKey: encryptionKeyInput.value || void 0,
|
|
2007
2051
|
keyId: keyIdInput.value || void 0
|
|
2008
2052
|
});
|
|
@@ -2017,6 +2061,10 @@ async function importDiscoveredDevice(device) {
|
|
|
2017
2061
|
contentDiv.appendChild(nameInput);
|
|
2018
2062
|
contentDiv.appendChild(typeLabel);
|
|
2019
2063
|
contentDiv.appendChild(typeSelect);
|
|
2064
|
+
contentDiv.appendChild(connectionPrefLabel);
|
|
2065
|
+
contentDiv.appendChild(connectionPrefSelect);
|
|
2066
|
+
contentDiv.appendChild(roomLabel);
|
|
2067
|
+
contentDiv.appendChild(roomInput);
|
|
2020
2068
|
contentDiv.appendChild(macLabel);
|
|
2021
2069
|
contentDiv.appendChild(macInput);
|
|
2022
2070
|
contentDiv.appendChild(encryptionKeyLabel);
|
|
@@ -2062,57 +2110,6 @@ async function editDevice(device) {
|
|
|
2062
2110
|
});
|
|
2063
2111
|
typeSelect.appendChild(optgroup);
|
|
2064
2112
|
});
|
|
2065
|
-
const windowCoveringTypes = ["Roller Shade", "Curtain", "Curtain3", "Blind Tilt"];
|
|
2066
|
-
const showMatterType = windowCoveringTypes.includes(device.configDeviceType || device.deviceType || device.type || "");
|
|
2067
|
-
const matterTypeLabel = document.createElement("label");
|
|
2068
|
-
matterTypeLabel.textContent = "Matter Window Covering Type (Advanced)";
|
|
2069
|
-
matterTypeLabel.style.display = showMatterType ? "block" : "none";
|
|
2070
|
-
matterTypeLabel.style.marginBottom = "6px";
|
|
2071
|
-
matterTypeLabel.style.fontWeight = "500";
|
|
2072
|
-
matterTypeLabel.style.fontSize = "12px";
|
|
2073
|
-
matterTypeLabel.style.color = "#6b7280";
|
|
2074
|
-
matterTypeLabel.style.marginTop = "2px";
|
|
2075
|
-
const matterTypes = [
|
|
2076
|
-
{ value: "", label: "Auto-detect (recommended)" },
|
|
2077
|
-
{ value: 0, label: "Roller Shade (0)" },
|
|
2078
|
-
{ value: 1, label: "Roman Shade (1)" },
|
|
2079
|
-
{ value: 2, label: "Balloon Shade (2)" },
|
|
2080
|
-
{ value: 3, label: "Woven Wood (3)" },
|
|
2081
|
-
{ value: 4, label: "Drapery (4)" },
|
|
2082
|
-
{ value: 5, label: "Awning (5)" },
|
|
2083
|
-
{ value: 6, label: "Shutter (6)" },
|
|
2084
|
-
{ value: 7, label: "Tilt Blind (7)" },
|
|
2085
|
-
{ value: 8, label: "Blind Tilt (8)" },
|
|
2086
|
-
{ value: 9, label: "Projector Screen (9)" },
|
|
2087
|
-
{ value: 15, label: "Other (15)" }
|
|
2088
|
-
];
|
|
2089
|
-
const matterTypeSelect = document.createElement("select");
|
|
2090
|
-
matterTypeSelect.style.width = "100%";
|
|
2091
|
-
matterTypeSelect.style.marginBottom = "12px";
|
|
2092
|
-
matterTypeSelect.style.padding = "8px 10px";
|
|
2093
|
-
matterTypeSelect.style.borderRadius = "6px";
|
|
2094
|
-
matterTypeSelect.style.fontSize = "14px";
|
|
2095
|
-
matterTypeSelect.style.boxSizing = "border-box";
|
|
2096
|
-
matterTypes.forEach((opt) => {
|
|
2097
|
-
const option = document.createElement("option");
|
|
2098
|
-
option.value = String(opt.value);
|
|
2099
|
-
option.textContent = opt.label;
|
|
2100
|
-
if (device.matterType != null && String(opt.value) === String(device.matterType)) {
|
|
2101
|
-
option.selected = true;
|
|
2102
|
-
}
|
|
2103
|
-
matterTypeSelect.appendChild(option);
|
|
2104
|
-
});
|
|
2105
|
-
function updateMatterTypeVisibility() {
|
|
2106
|
-
if (windowCoveringTypes.includes(typeSelect.value)) {
|
|
2107
|
-
matterTypeLabel.style.display = "block";
|
|
2108
|
-
matterTypeSelect.style.display = "block";
|
|
2109
|
-
} else {
|
|
2110
|
-
matterTypeLabel.style.display = "none";
|
|
2111
|
-
matterTypeSelect.style.display = "none";
|
|
2112
|
-
}
|
|
2113
|
-
}
|
|
2114
|
-
typeSelect.addEventListener("change", updateMatterTypeVisibility);
|
|
2115
|
-
updateMatterTypeVisibility();
|
|
2116
2113
|
const div = document.createElement("div");
|
|
2117
2114
|
div.style.position = "fixed";
|
|
2118
2115
|
div.style.top = "0";
|
|
@@ -2195,6 +2192,78 @@ async function editDevice(device) {
|
|
|
2195
2192
|
});
|
|
2196
2193
|
typeSelect.appendChild(optgroup);
|
|
2197
2194
|
});
|
|
2195
|
+
const connectionPrefLabel = document.createElement("label");
|
|
2196
|
+
connectionPrefLabel.textContent = "Connection Preference";
|
|
2197
|
+
connectionPrefLabel.style.display = "block";
|
|
2198
|
+
connectionPrefLabel.style.marginBottom = "6px";
|
|
2199
|
+
connectionPrefLabel.style.fontWeight = "500";
|
|
2200
|
+
connectionPrefLabel.style.fontSize = "12px";
|
|
2201
|
+
connectionPrefLabel.style.color = "#6b7280";
|
|
2202
|
+
const connectionPrefSelect = document.createElement("select");
|
|
2203
|
+
connectionPrefSelect.style.width = "100%";
|
|
2204
|
+
connectionPrefSelect.style.marginBottom = "12px";
|
|
2205
|
+
connectionPrefSelect.style.padding = "8px 10px";
|
|
2206
|
+
connectionPrefSelect.style.borderRadius = "6px";
|
|
2207
|
+
connectionPrefSelect.style.fontSize = "14px";
|
|
2208
|
+
connectionPrefSelect.style.boxSizing = "border-box";
|
|
2209
|
+
["auto", "ble", "openapi"].forEach((val) => {
|
|
2210
|
+
const opt = document.createElement("option");
|
|
2211
|
+
opt.value = val;
|
|
2212
|
+
opt.text = val.charAt(0).toUpperCase() + val.slice(1);
|
|
2213
|
+
opt.selected = (device.connectionPreference || "auto") === val;
|
|
2214
|
+
connectionPrefSelect.appendChild(opt);
|
|
2215
|
+
});
|
|
2216
|
+
const roomLabel = document.createElement("label");
|
|
2217
|
+
roomLabel.textContent = "Room";
|
|
2218
|
+
roomLabel.style.display = "block";
|
|
2219
|
+
roomLabel.style.marginBottom = "6px";
|
|
2220
|
+
roomLabel.style.fontWeight = "500";
|
|
2221
|
+
roomLabel.style.fontSize = "12px";
|
|
2222
|
+
roomLabel.style.color = "#6b7280";
|
|
2223
|
+
const roomInput = document.createElement("input");
|
|
2224
|
+
roomInput.type = "text";
|
|
2225
|
+
roomInput.value = device.room || "";
|
|
2226
|
+
roomInput.placeholder = "Optional room/location metadata";
|
|
2227
|
+
roomInput.style.width = "100%";
|
|
2228
|
+
roomInput.style.marginBottom = "12px";
|
|
2229
|
+
roomInput.style.padding = "8px 10px";
|
|
2230
|
+
roomInput.style.borderRadius = "6px";
|
|
2231
|
+
roomInput.style.fontSize = "14px";
|
|
2232
|
+
roomInput.style.boxSizing = "border-box";
|
|
2233
|
+
const encryptionKeyLabel = document.createElement("label");
|
|
2234
|
+
encryptionKeyLabel.textContent = "BLE Encryption Key (optional)";
|
|
2235
|
+
encryptionKeyLabel.style.display = "block";
|
|
2236
|
+
encryptionKeyLabel.style.marginBottom = "6px";
|
|
2237
|
+
encryptionKeyLabel.style.fontWeight = "500";
|
|
2238
|
+
encryptionKeyLabel.style.fontSize = "12px";
|
|
2239
|
+
encryptionKeyLabel.style.color = "#6b7280";
|
|
2240
|
+
const encryptionKeyInput = document.createElement("input");
|
|
2241
|
+
encryptionKeyInput.type = "password";
|
|
2242
|
+
encryptionKeyInput.value = device.encryptionKey || "";
|
|
2243
|
+
encryptionKeyInput.placeholder = "Paste device BLE encryption key";
|
|
2244
|
+
encryptionKeyInput.style.width = "100%";
|
|
2245
|
+
encryptionKeyInput.style.marginBottom = "12px";
|
|
2246
|
+
encryptionKeyInput.style.padding = "8px 10px";
|
|
2247
|
+
encryptionKeyInput.style.borderRadius = "6px";
|
|
2248
|
+
encryptionKeyInput.style.fontSize = "14px";
|
|
2249
|
+
encryptionKeyInput.style.boxSizing = "border-box";
|
|
2250
|
+
const keyIdLabel = document.createElement("label");
|
|
2251
|
+
keyIdLabel.textContent = "BLE Key ID (optional)";
|
|
2252
|
+
keyIdLabel.style.display = "block";
|
|
2253
|
+
keyIdLabel.style.marginBottom = "6px";
|
|
2254
|
+
keyIdLabel.style.fontWeight = "500";
|
|
2255
|
+
keyIdLabel.style.fontSize = "12px";
|
|
2256
|
+
keyIdLabel.style.color = "#6b7280";
|
|
2257
|
+
const keyIdInput = document.createElement("input");
|
|
2258
|
+
keyIdInput.type = "text";
|
|
2259
|
+
keyIdInput.value = device.keyId || "";
|
|
2260
|
+
keyIdInput.placeholder = "e.g. ff";
|
|
2261
|
+
keyIdInput.style.width = "100%";
|
|
2262
|
+
keyIdInput.style.marginBottom = "12px";
|
|
2263
|
+
keyIdInput.style.padding = "8px 10px";
|
|
2264
|
+
keyIdInput.style.borderRadius = "6px";
|
|
2265
|
+
keyIdInput.style.fontSize = "14px";
|
|
2266
|
+
keyIdInput.style.boxSizing = "border-box";
|
|
2198
2267
|
const errorMessage = document.createElement("div");
|
|
2199
2268
|
errorMessage.style.color = "var(--switchbot-red, #ef4444)";
|
|
2200
2269
|
errorMessage.style.marginBottom = "12px";
|
|
@@ -2231,9 +2300,29 @@ async function editDevice(device) {
|
|
|
2231
2300
|
deviceId: device.id,
|
|
2232
2301
|
configDeviceName: nameInput.value || void 0,
|
|
2233
2302
|
configDeviceType: typeSelect.value,
|
|
2234
|
-
|
|
2303
|
+
connectionPreference: connectionPrefSelect.value,
|
|
2304
|
+
room: roomInput.value || void 0,
|
|
2305
|
+
encryptionKey: encryptionKeyInput.value || void 0,
|
|
2306
|
+
keyId: keyIdInput.value || void 0
|
|
2235
2307
|
};
|
|
2236
|
-
|
|
2308
|
+
const options = {};
|
|
2309
|
+
if (params.connectionPreference !== void 0) {
|
|
2310
|
+
options.connectionPreference = params.connectionPreference;
|
|
2311
|
+
}
|
|
2312
|
+
if (params.room !== void 0) {
|
|
2313
|
+
options.room = params.room;
|
|
2314
|
+
}
|
|
2315
|
+
if (params.encryptionKey !== void 0) {
|
|
2316
|
+
options.encryptionKey = params.encryptionKey;
|
|
2317
|
+
}
|
|
2318
|
+
if (params.keyId !== void 0) {
|
|
2319
|
+
options.keyId = params.keyId;
|
|
2320
|
+
}
|
|
2321
|
+
await updateDevice2(
|
|
2322
|
+
params.deviceId,
|
|
2323
|
+
params.configDeviceName,
|
|
2324
|
+
params.configDeviceType
|
|
2325
|
+
);
|
|
2237
2326
|
await syncParentPluginConfigFromDisk2();
|
|
2238
2327
|
uiLog.info("[Edit Device] Refreshing device list after update");
|
|
2239
2328
|
const list = await fetchDevices2();
|
|
@@ -2253,8 +2342,14 @@ async function editDevice(device) {
|
|
|
2253
2342
|
contentDiv.appendChild(apiTypeInput);
|
|
2254
2343
|
contentDiv.appendChild(typeLabel);
|
|
2255
2344
|
contentDiv.appendChild(typeSelect);
|
|
2256
|
-
contentDiv.appendChild(
|
|
2257
|
-
contentDiv.appendChild(
|
|
2345
|
+
contentDiv.appendChild(connectionPrefLabel);
|
|
2346
|
+
contentDiv.appendChild(connectionPrefSelect);
|
|
2347
|
+
contentDiv.appendChild(roomLabel);
|
|
2348
|
+
contentDiv.appendChild(roomInput);
|
|
2349
|
+
contentDiv.appendChild(encryptionKeyLabel);
|
|
2350
|
+
contentDiv.appendChild(encryptionKeyInput);
|
|
2351
|
+
contentDiv.appendChild(keyIdLabel);
|
|
2352
|
+
contentDiv.appendChild(keyIdInput);
|
|
2258
2353
|
contentDiv.appendChild(errorMessage);
|
|
2259
2354
|
contentDiv.appendChild(buttons);
|
|
2260
2355
|
modal.appendChild(title);
|
|
@@ -2704,18 +2799,22 @@ function renderDeviceDetailsPanel(device) {
|
|
|
2704
2799
|
let batteryHistory = [];
|
|
2705
2800
|
try {
|
|
2706
2801
|
const raw = localStorage.getItem(batteryHistoryKey);
|
|
2707
|
-
if (raw)
|
|
2708
|
-
|
|
2802
|
+
if (raw) {
|
|
2803
|
+
batteryHistory = JSON.parse(raw);
|
|
2804
|
+
}
|
|
2805
|
+
} catch (e) {
|
|
2709
2806
|
}
|
|
2710
2807
|
const now = Date.now();
|
|
2711
2808
|
if (typeof device?.battery === "number") {
|
|
2712
|
-
const last = batteryHistory
|
|
2809
|
+
const last = batteryHistory.at(-1);
|
|
2713
2810
|
if (!last || last.value !== device.battery || now - last.ts > 60 * 60 * 1e3) {
|
|
2714
2811
|
batteryHistory.push({ value: device.battery, ts: now });
|
|
2715
|
-
if (batteryHistory.length > 30)
|
|
2812
|
+
if (batteryHistory.length > 30) {
|
|
2813
|
+
batteryHistory = batteryHistory.slice(-30);
|
|
2814
|
+
}
|
|
2716
2815
|
try {
|
|
2717
2816
|
localStorage.setItem(batteryHistoryKey, JSON.stringify(batteryHistory));
|
|
2718
|
-
} catch {
|
|
2817
|
+
} catch (e) {
|
|
2719
2818
|
}
|
|
2720
2819
|
}
|
|
2721
2820
|
}
|
|
@@ -2792,7 +2891,9 @@ function renderDeviceDetailsPanel(device) {
|
|
|
2792
2891
|
chart.style.width = "100%";
|
|
2793
2892
|
chart.style.height = "28px";
|
|
2794
2893
|
chart.style.display = "flex";
|
|
2795
|
-
const w = 120
|
|
2894
|
+
const w = 120;
|
|
2895
|
+
const h = 24;
|
|
2896
|
+
const pad = 2;
|
|
2796
2897
|
const min = Math.min(...batteryHistory.map((b) => b.value), 100);
|
|
2797
2898
|
const max = Math.max(...batteryHistory.map((b) => b.value), 0);
|
|
2798
2899
|
const range = max - min || 1;
|
|
@@ -2864,7 +2965,7 @@ function renderDeviceDetailsPanel(device) {
|
|
|
2864
2965
|
"capabilities",
|
|
2865
2966
|
"state"
|
|
2866
2967
|
];
|
|
2867
|
-
const shown = new Set(rows.map((r) => r.label.toLowerCase().replace(
|
|
2968
|
+
const shown = new Set(rows.map((r) => r.label.toLowerCase().replace(SPACES_REGEX, "")));
|
|
2868
2969
|
for (const key of featureKeys) {
|
|
2869
2970
|
if (device && device[key] !== void 0 && !shown.has(key.toLowerCase())) {
|
|
2870
2971
|
const line = document.createElement("div");
|
|
@@ -2876,7 +2977,7 @@ function renderDeviceDetailsPanel(device) {
|
|
|
2876
2977
|
const label = document.createElement("span");
|
|
2877
2978
|
label.style.fontWeight = "600";
|
|
2878
2979
|
label.style.minWidth = "110px";
|
|
2879
|
-
label.textContent = key.replace(
|
|
2980
|
+
label.textContent = `${key.replace(CAMELCASE_REGEX, " $1").replace(FIRST_CHAR_REGEX, (s) => s.toUpperCase())}:`;
|
|
2880
2981
|
const value = document.createElement("span");
|
|
2881
2982
|
value.style.fontFamily = "monospace";
|
|
2882
2983
|
value.style.fontSize = "11px";
|
|
@@ -2956,14 +3057,16 @@ async function renderDiscoveredDevices(devices, options = {}) {
|
|
|
2956
3057
|
nameContainer.appendChild(fwBadge);
|
|
2957
3058
|
}
|
|
2958
3059
|
let offline = false;
|
|
2959
|
-
|
|
3060
|
+
const lastSeen = d.lastSeen || d.lastseen || d.updatedAt;
|
|
2960
3061
|
if (typeof d.offline === "boolean") {
|
|
2961
3062
|
offline = d.offline;
|
|
2962
3063
|
} else if (lastSeen) {
|
|
2963
3064
|
try {
|
|
2964
3065
|
const last = new Date(lastSeen).getTime();
|
|
2965
|
-
if (!isNaN(last)
|
|
2966
|
-
|
|
3066
|
+
if (!Number.isNaN(last)) {
|
|
3067
|
+
if (Date.now() - last > 1e3 * 60 * 60) {
|
|
3068
|
+
offline = true;
|
|
3069
|
+
}
|
|
2967
3070
|
}
|
|
2968
3071
|
} catch {
|
|
2969
3072
|
}
|
|
@@ -3153,11 +3256,11 @@ function sortDevices(devices, sortBy = "name") {
|
|
|
3153
3256
|
}
|
|
3154
3257
|
case "connection": {
|
|
3155
3258
|
const connectionOrder = {
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3259
|
+
Both: 0,
|
|
3260
|
+
BLE: 1,
|
|
3261
|
+
OpenAPI: 2,
|
|
3262
|
+
API: 2,
|
|
3263
|
+
Unknown: 3
|
|
3161
3264
|
};
|
|
3162
3265
|
sorted.sort((a, b) => {
|
|
3163
3266
|
const aOrder = connectionOrder[a.connectionType || "Unknown"] ?? 3;
|
|
@@ -3316,7 +3419,12 @@ function renderDeviceList(list) {
|
|
|
3316
3419
|
copyBtn.classList.remove("success");
|
|
3317
3420
|
}, 1200);
|
|
3318
3421
|
} catch (e) {
|
|
3319
|
-
|
|
3422
|
+
copyBtn.textContent = "Failed";
|
|
3423
|
+
copyBtn.classList.add("error");
|
|
3424
|
+
setTimeout(() => {
|
|
3425
|
+
copyBtn.textContent = "Copy ID";
|
|
3426
|
+
copyBtn.classList.remove("error");
|
|
3427
|
+
}, 1200);
|
|
3320
3428
|
}
|
|
3321
3429
|
});
|
|
3322
3430
|
const deleteBtn = document.createElement("button");
|
|
@@ -3337,9 +3445,13 @@ function renderDeviceList(list) {
|
|
|
3337
3445
|
ul.appendChild(li);
|
|
3338
3446
|
}
|
|
3339
3447
|
}
|
|
3448
|
+
var SPACES_REGEX, CAMELCASE_REGEX, FIRST_CHAR_REGEX;
|
|
3340
3449
|
var init_render = __esm({
|
|
3341
3450
|
"src/homebridge-ui/public/js/render.ts"() {
|
|
3342
3451
|
"use strict";
|
|
3452
|
+
SPACES_REGEX = /\s/g;
|
|
3453
|
+
CAMELCASE_REGEX = /([A-Z])/g;
|
|
3454
|
+
FIRST_CHAR_REGEX = /^./;
|
|
3343
3455
|
}
|
|
3344
3456
|
});
|
|
3345
3457
|
|
|
@@ -3365,8 +3477,7 @@ async function addDeviceToConfig2(device, options = {}) {
|
|
|
3365
3477
|
model: device.model,
|
|
3366
3478
|
rssi: device.rssi,
|
|
3367
3479
|
encryptionKey: importValues.encryptionKey,
|
|
3368
|
-
keyId: importValues.keyId
|
|
3369
|
-
matterType: importValues.matterType
|
|
3480
|
+
keyId: importValues.keyId
|
|
3370
3481
|
});
|
|
3371
3482
|
uiLog.info("Add device response:", resp);
|
|
3372
3483
|
if (!resp || resp.success === false) {
|
|
@@ -3510,7 +3621,7 @@ async function saveCredentials2() {
|
|
|
3510
3621
|
;
|
|
3511
3622
|
document.getElementById("token").value = "";
|
|
3512
3623
|
document.getElementById("secret").value = "";
|
|
3513
|
-
setTimeout(
|
|
3624
|
+
setTimeout(loadCredentialStatus, 500);
|
|
3514
3625
|
setTimeout(() => {
|
|
3515
3626
|
saveStatus.textContent = "";
|
|
3516
3627
|
saveStatus.classList.remove("success-msg");
|
|
@@ -3536,7 +3647,7 @@ window.discoverDevices = discoverDevices2;
|
|
|
3536
3647
|
async function init() {
|
|
3537
3648
|
await loadCredentialStatus();
|
|
3538
3649
|
await initializeDiscoverySettings();
|
|
3539
|
-
|
|
3650
|
+
await loadConfiguredDevices();
|
|
3540
3651
|
await initRemoveAllButton();
|
|
3541
3652
|
}
|
|
3542
3653
|
if (document.readyState === "loading") {
|