@switchbot/homebridge-switchbot 5.0.1 → 5.0.2
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/release.yml +3 -3
- package/CHANGELOG.md +9 -0
- package/dist/homebridge-ui/public/index.html +0 -4
- package/dist/homebridge-ui/public/js/app.js +21 -39
- package/dist/homebridge-ui/public/js/app.js.map +2 -2
- package/dist/homebridge-ui/public/js/discovery.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/discovery.js +0 -36
- package/dist/homebridge-ui/public/js/discovery.js.map +1 -1
- package/dist/homebridge-ui/public/js/discovery.ts +0 -37
- package/dist/homebridge-ui/public/js/render.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/render.js +22 -3
- package/dist/homebridge-ui/public/js/render.js.map +1 -1
- package/dist/homebridge-ui/public/js/render.ts +22 -3
- package/docs/variables/default.html +1 -1
- package/package.json +1 -1
- package/src/homebridge-ui/public/index.html +0 -4
- package/src/homebridge-ui/public/js/discovery.ts +0 -37
- package/src/homebridge-ui/public/js/render.ts +22 -3
|
@@ -5,6 +5,22 @@ const SPACES_REGEX = /\s/g
|
|
|
5
5
|
const CAMELCASE_REGEX = /([A-Z])/g
|
|
6
6
|
const FIRST_CHAR_REGEX = /^./
|
|
7
7
|
|
|
8
|
+
async function copyTextWithFallback(text: string): Promise<void> {
|
|
9
|
+
try {
|
|
10
|
+
await navigator.clipboard.writeText(text)
|
|
11
|
+
} catch {
|
|
12
|
+
const textarea = document.createElement('textarea')
|
|
13
|
+
textarea.value = text
|
|
14
|
+
textarea.setAttribute('readonly', '')
|
|
15
|
+
textarea.style.cssText = 'position:fixed;left:-9999px;opacity:0;pointer-events:none'
|
|
16
|
+
document.body.appendChild(textarea)
|
|
17
|
+
textarea.select()
|
|
18
|
+
textarea.setSelectionRange(0, textarea.value.length)
|
|
19
|
+
document.execCommand('copy')
|
|
20
|
+
textarea.remove()
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
8
24
|
/**
|
|
9
25
|
* Get RSSI signal quality level and color based on dBm value
|
|
10
26
|
* @param rssi Signal strength in dBm (typically -30 to -90)
|
|
@@ -994,7 +1010,8 @@ export function renderDeviceList(list: any[]): void {
|
|
|
994
1010
|
meta.style.fontSize = '10px'
|
|
995
1011
|
meta.style.fontFamily = 'monospace'
|
|
996
1012
|
|
|
997
|
-
const
|
|
1013
|
+
const deviceIdentifier = d.deviceId || d.id
|
|
1014
|
+
const id = `ID: ${deviceIdentifier}`
|
|
998
1015
|
const typeText = d.configDeviceType || d.type ? `Type: ${d.configDeviceType || d.type}` : ''
|
|
999
1016
|
const connText = d.connectionPreference ? `Conn: ${d.connectionPreference}` : ''
|
|
1000
1017
|
const roomText = d.room ? `Room: ${d.room}` : ''
|
|
@@ -1029,7 +1046,9 @@ export function renderDeviceList(list: any[]): void {
|
|
|
1029
1046
|
copyBtn.style.fontSize = '11px'
|
|
1030
1047
|
copyBtn.addEventListener('click', async () => {
|
|
1031
1048
|
try {
|
|
1032
|
-
|
|
1049
|
+
if (deviceIdentifier) {
|
|
1050
|
+
await copyTextWithFallback(deviceIdentifier)
|
|
1051
|
+
}
|
|
1033
1052
|
copyBtn.textContent = 'Copied'
|
|
1034
1053
|
copyBtn.classList.add('success')
|
|
1035
1054
|
setTimeout(() => {
|
|
@@ -1058,8 +1077,8 @@ export function renderDeviceList(list: any[]): void {
|
|
|
1058
1077
|
|
|
1059
1078
|
buttons.appendChild(editBtn)
|
|
1060
1079
|
buttons.appendChild(copyBtn)
|
|
1061
|
-
buttons.appendChild(createConnectionTestControls(d))
|
|
1062
1080
|
buttons.appendChild(deleteBtn)
|
|
1081
|
+
buttons.appendChild(createConnectionTestControls(d))
|
|
1063
1082
|
|
|
1064
1083
|
li.appendChild(info)
|
|
1065
1084
|
li.appendChild(buttons)
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
<!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>default | @switchbot/homebridge-switchbot</title><meta name="description" content="Documentation for @switchbot/homebridge-switchbot"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">@switchbot/homebridge-switchbot</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="" aria-current="page">default</a></li></ul><h1>Variable default</h1></div><div class="tsd-signature"><span class="tsd-kind-variable">default</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span> <span class="tsd-signature-symbol">=></span> <span class="tsd-signature-type">void</span></div><div class="tsd-comment tsd-typography"><p>Registers the SwitchBot platform with Homebridge.</p>
|
|
2
2
|
</div><div class="tsd-type-declaration"><h4>Type Declaration</h4><ul class="tsd-parameters"><li class="tsd-parameter-signature"><ul class="tsd-signatures"><li class="tsd-signature" id="__type"><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">void</span></li><li class="tsd-description"><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">api</span>: <span class="tsd-signature-type">API</span></span><div class="tsd-comment tsd-typography"><p>The Homebridge API instance.</p>
|
|
3
|
-
</div></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4></li></ul></li></ul></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/blob/
|
|
3
|
+
</div></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4></li></ul></li></ul></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/blob/beddb5beda694522535549f5627e37285d89cc52/src/index.ts#L22">index.ts:22</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">@switchbot/homebridge-switchbot</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer></footer><div class="overlay"></div></body></html>
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@switchbot/homebridge-switchbot",
|
|
3
3
|
"displayName": "SwitchBot",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "5.0.
|
|
5
|
+
"version": "5.0.2",
|
|
6
6
|
"description": "The SwitchBot plugin allows you to access your SwitchBot device(s) from HomeKit.",
|
|
7
7
|
"author": "SwitchBot <support@wondertechlabs.com> (https://github.com/SwitchBot)",
|
|
8
8
|
"contributors": [
|
|
@@ -81,10 +81,6 @@
|
|
|
81
81
|
<button id="discoverBtn" onclick="discoverDevices()" style="margin-bottom: 8px">
|
|
82
82
|
🔍 Discover
|
|
83
83
|
</button>
|
|
84
|
-
<button id="cancelDiscoverBtn"
|
|
85
|
-
style="margin-left: 6px; margin-bottom: 8px; display: none; padding: 6px 10px; font-size: 11px" class="secondary">
|
|
86
|
-
Cancel
|
|
87
|
-
</button>
|
|
88
84
|
<div id="discoverStatus" style="margin-bottom: 6px; font-size: 11px"></div>
|
|
89
85
|
<div id="discoverDevicesFound" style="margin-bottom: 6px; font-size: 11px; display: none"></div>
|
|
90
86
|
<div id="discoverPhaseProgress" class="discover-phase-progress" style="display: none">
|
|
@@ -394,7 +394,6 @@ function setDiscoveryGroupExpanded(groupKey: string, expanded: boolean): void {
|
|
|
394
394
|
|
|
395
395
|
export async function discoverDevices(): Promise<void> {
|
|
396
396
|
const btn = document.getElementById('discoverBtn') as HTMLButtonElement
|
|
397
|
-
const cancelBtn = document.getElementById('cancelDiscoverBtn') as HTMLButtonElement | null
|
|
398
397
|
const status = document.getElementById('discoverStatus')
|
|
399
398
|
const phaseProgress = document.getElementById('discoverPhaseProgress') as HTMLElement | null
|
|
400
399
|
const phaseFill = document.getElementById('discoverPhaseFill') as HTMLElement | null
|
|
@@ -424,7 +423,6 @@ export async function discoverDevices(): Promise<void> {
|
|
|
424
423
|
const startedAt = Date.now()
|
|
425
424
|
let phaseStartedAt = startedAt
|
|
426
425
|
let phase = 'Preparing discovery...'
|
|
427
|
-
let cancelled = false
|
|
428
426
|
|
|
429
427
|
// --- Real-time RSSI polling additions ---
|
|
430
428
|
// (bleScanDurationSeconds is now only used in bleSettings below)
|
|
@@ -936,32 +934,8 @@ export async function discoverDevices(): Promise<void> {
|
|
|
936
934
|
devicesFoundDisplay.classList.remove('discovery-scanning-pulse')
|
|
937
935
|
}
|
|
938
936
|
|
|
939
|
-
if (cancelBtn) {
|
|
940
|
-
cancelBtn.style.display = 'inline-block'
|
|
941
|
-
cancelBtn.disabled = false
|
|
942
|
-
cancelBtn.onclick = () => {
|
|
943
|
-
cancelled = true
|
|
944
|
-
const totalSeconds = Math.max(0, Math.floor((Date.now() - startedAt) / 1000))
|
|
945
|
-
status.textContent = `Discovery cancelled (${totalSeconds}s total)`
|
|
946
|
-
if (phaseProgress) {
|
|
947
|
-
phaseProgress.style.display = 'none'
|
|
948
|
-
}
|
|
949
|
-
if (devicesFoundDisplay) {
|
|
950
|
-
devicesFoundDisplay.style.display = 'none'
|
|
951
|
-
devicesFoundDisplay.classList.remove('discovery-scanning-pulse')
|
|
952
|
-
}
|
|
953
|
-
cancelBtn.style.display = 'none'
|
|
954
|
-
btn.disabled = false
|
|
955
|
-
btn.textContent = '🔍 Discover Devices'
|
|
956
|
-
hideBusyUi()
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
|
|
960
937
|
if (bleSettings.bleEnabled) {
|
|
961
938
|
const bleDevicesRaw = await apiDiscoverDevices('ble', bleSettings)
|
|
962
|
-
if (cancelled) {
|
|
963
|
-
return
|
|
964
|
-
}
|
|
965
939
|
|
|
966
940
|
discoveredDevices = dedupeById(bleDevicesRaw)
|
|
967
941
|
uiLog.info('BLE discover response:', bleDevicesRaw)
|
|
@@ -988,9 +962,6 @@ export async function discoverDevices(): Promise<void> {
|
|
|
988
962
|
|
|
989
963
|
try {
|
|
990
964
|
const openApiDevicesRaw = await apiDiscoverDevices('openapi')
|
|
991
|
-
if (cancelled) {
|
|
992
|
-
return
|
|
993
|
-
}
|
|
994
965
|
|
|
995
966
|
uiLog.info('OpenAPI discover response:', openApiDevicesRaw)
|
|
996
967
|
discoveredDevices = mergeDiscoveredDevices(discoveredDevices, openApiDevicesRaw)
|
|
@@ -1096,9 +1067,6 @@ export async function discoverDevices(): Promise<void> {
|
|
|
1096
1067
|
setDiscoveryCache(discoveredDevices)
|
|
1097
1068
|
updateLastScannedStatus()
|
|
1098
1069
|
} catch (e) {
|
|
1099
|
-
if (cancelled) {
|
|
1100
|
-
return
|
|
1101
|
-
}
|
|
1102
1070
|
uiLog.error('Discovery error:', e)
|
|
1103
1071
|
status.textContent = `Error: ${e instanceof Error ? e.message : 'Discovery failed'}`
|
|
1104
1072
|
status.classList.add('error')
|
|
@@ -1123,11 +1091,6 @@ export async function discoverDevices(): Promise<void> {
|
|
|
1123
1091
|
}
|
|
1124
1092
|
btn.disabled = false
|
|
1125
1093
|
btn.textContent = '🔍 Discover Devices'
|
|
1126
|
-
if (cancelBtn) {
|
|
1127
|
-
cancelBtn.disabled = false
|
|
1128
|
-
cancelBtn.style.display = 'none'
|
|
1129
|
-
cancelBtn.onclick = null
|
|
1130
|
-
}
|
|
1131
1094
|
}
|
|
1132
1095
|
}
|
|
1133
1096
|
|
|
@@ -5,6 +5,22 @@ const SPACES_REGEX = /\s/g
|
|
|
5
5
|
const CAMELCASE_REGEX = /([A-Z])/g
|
|
6
6
|
const FIRST_CHAR_REGEX = /^./
|
|
7
7
|
|
|
8
|
+
async function copyTextWithFallback(text: string): Promise<void> {
|
|
9
|
+
try {
|
|
10
|
+
await navigator.clipboard.writeText(text)
|
|
11
|
+
} catch {
|
|
12
|
+
const textarea = document.createElement('textarea')
|
|
13
|
+
textarea.value = text
|
|
14
|
+
textarea.setAttribute('readonly', '')
|
|
15
|
+
textarea.style.cssText = 'position:fixed;left:-9999px;opacity:0;pointer-events:none'
|
|
16
|
+
document.body.appendChild(textarea)
|
|
17
|
+
textarea.select()
|
|
18
|
+
textarea.setSelectionRange(0, textarea.value.length)
|
|
19
|
+
document.execCommand('copy')
|
|
20
|
+
textarea.remove()
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
8
24
|
/**
|
|
9
25
|
* Get RSSI signal quality level and color based on dBm value
|
|
10
26
|
* @param rssi Signal strength in dBm (typically -30 to -90)
|
|
@@ -994,7 +1010,8 @@ export function renderDeviceList(list: any[]): void {
|
|
|
994
1010
|
meta.style.fontSize = '10px'
|
|
995
1011
|
meta.style.fontFamily = 'monospace'
|
|
996
1012
|
|
|
997
|
-
const
|
|
1013
|
+
const deviceIdentifier = d.deviceId || d.id
|
|
1014
|
+
const id = `ID: ${deviceIdentifier}`
|
|
998
1015
|
const typeText = d.configDeviceType || d.type ? `Type: ${d.configDeviceType || d.type}` : ''
|
|
999
1016
|
const connText = d.connectionPreference ? `Conn: ${d.connectionPreference}` : ''
|
|
1000
1017
|
const roomText = d.room ? `Room: ${d.room}` : ''
|
|
@@ -1029,7 +1046,9 @@ export function renderDeviceList(list: any[]): void {
|
|
|
1029
1046
|
copyBtn.style.fontSize = '11px'
|
|
1030
1047
|
copyBtn.addEventListener('click', async () => {
|
|
1031
1048
|
try {
|
|
1032
|
-
|
|
1049
|
+
if (deviceIdentifier) {
|
|
1050
|
+
await copyTextWithFallback(deviceIdentifier)
|
|
1051
|
+
}
|
|
1033
1052
|
copyBtn.textContent = 'Copied'
|
|
1034
1053
|
copyBtn.classList.add('success')
|
|
1035
1054
|
setTimeout(() => {
|
|
@@ -1058,8 +1077,8 @@ export function renderDeviceList(list: any[]): void {
|
|
|
1058
1077
|
|
|
1059
1078
|
buttons.appendChild(editBtn)
|
|
1060
1079
|
buttons.appendChild(copyBtn)
|
|
1061
|
-
buttons.appendChild(createConnectionTestControls(d))
|
|
1062
1080
|
buttons.appendChild(deleteBtn)
|
|
1081
|
+
buttons.appendChild(createConnectionTestControls(d))
|
|
1063
1082
|
|
|
1064
1083
|
li.appendChild(info)
|
|
1065
1084
|
li.appendChild(buttons)
|