@switchbot/homebridge-switchbot 5.0.0-beta.86 → 5.0.0-beta.87

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.
@@ -259,7 +259,10 @@
259
259
  throw new Error(resp?.data?.message || 'Discovery failed')
260
260
  }
261
261
 
262
- const devices = resp.data || []
262
+ const devicesRaw = resp.data || []
263
+ const devices = devicesRaw.filter((d, index, arr) =>
264
+ !!d?.id && arr.findIndex((x) => x?.id === d.id) === index,
265
+ )
263
266
 
264
267
  if (!devices.length) {
265
268
  status.textContent = 'No devices found in your SwitchBot account'
@@ -275,8 +278,12 @@
275
278
 
276
279
  for (const d of devices) {
277
280
  try {
278
- await addDeviceToConfig(d)
279
- addedCount++
281
+ const result = await addDeviceToConfig(d, { refresh: false, showStatus: false })
282
+ if (result?.added) {
283
+ addedCount++
284
+ } else {
285
+ skippedCount++
286
+ }
280
287
  } catch (e) {
281
288
  console.warn(`Failed to add device ${d.id}:`, e)
282
289
  skippedCount++
@@ -288,7 +295,7 @@
288
295
  list.style.display = 'none'
289
296
 
290
297
  // Refresh the configured devices list
291
- await load()
298
+ await loadConfiguredDevices()
292
299
  return
293
300
  }
294
301
 
@@ -335,7 +342,8 @@
335
342
  }
336
343
  }
337
344
 
338
- async function addDeviceToConfig(device) {
345
+ async function addDeviceToConfig(device, options = {}) {
346
+ const { refresh = true, showStatus = true } = options
339
347
  try {
340
348
  console.log('Adding device to config:', device)
341
349
 
@@ -351,23 +359,29 @@
351
359
  throw new Error(resp?.data?.message || 'Failed to add device')
352
360
  }
353
361
 
354
- // Show success message
355
- const message = resp.data?.message || `Device "${device.name}" added successfully!`
356
- const status = document.getElementById('discoverStatus')
357
- status.textContent = '✓ ' + message
358
- status.classList.remove('error')
359
- status.classList.add('success-msg')
362
+ const alreadyExists = !!resp.data?.alreadyExists
363
+ const message = resp.data?.message || (alreadyExists
364
+ ? `Device "${device.name}" already in config`
365
+ : `Device "${device.name}" added successfully!`)
366
+
367
+ if (showStatus) {
368
+ const status = document.getElementById('discoverStatus')
369
+ status.textContent = (alreadyExists ? '• ' : '✓ ') + message
370
+ status.classList.remove('error')
371
+ status.classList.add('success-msg')
372
+ }
360
373
 
361
- // Refresh lists after 1 second
362
- setTimeout(async () => {
374
+ if (refresh) {
363
375
  await loadConfiguredDevices()
364
- await discoverDevices()
365
- }, 1000)
376
+ }
377
+
378
+ return { added: !alreadyExists }
366
379
  } catch (e) {
367
380
  console.error('Add device error:', e)
368
381
  const status = document.getElementById('discoverStatus')
369
382
  status.textContent = '✗ Error: ' + (e?.message || 'Failed to add device')
370
383
  status.classList.add('error')
384
+ return { added: false }
371
385
  }
372
386
  }
373
387
 
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/homebridge-ui/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAgB,MAAM,6BAA6B,CAAA;AAGpF,QAAA,MAAM,MAAM,0BAAiC,CAAA;AA4V7C,eAAe,MAAM,CAAA"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/homebridge-ui/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAgB,MAAM,6BAA6B,CAAA;AAGpF,QAAA,MAAM,MAAM,0BAAiC,CAAA;AAuY7C,eAAe,MAAM,CAAA"}
@@ -2,6 +2,35 @@
2
2
  import { HomebridgePluginUiServer, RequestError } from '@homebridge/plugin-ui-utils';
3
3
  import fs from 'node:fs/promises';
4
4
  const server = new HomebridgePluginUiServer();
5
+ function getDevicesRef(platform) {
6
+ if (Array.isArray(platform?.devices)) {
7
+ return platform.devices;
8
+ }
9
+ if (platform?.options && typeof platform.options === 'object') {
10
+ if (!Array.isArray(platform.options.devices)) {
11
+ platform.options.devices = [];
12
+ }
13
+ return platform.options.devices;
14
+ }
15
+ if (platform && typeof platform === 'object') {
16
+ platform.devices = [];
17
+ return platform.devices;
18
+ }
19
+ return [];
20
+ }
21
+ function getCredential(platform, key) {
22
+ return platform?.[key] ?? platform?.options?.[key];
23
+ }
24
+ function setCredential(platform, key, value) {
25
+ if (!platform || typeof platform !== 'object') {
26
+ return;
27
+ }
28
+ if (platform.options && Object.prototype.hasOwnProperty.call(platform.options, key)) {
29
+ platform.options[key] = value;
30
+ return;
31
+ }
32
+ platform[key] = value;
33
+ }
5
34
  // Helper function to find the SwitchBot platform config
6
35
  async function getSwitchBotPlatformConfig() {
7
36
  const cfgPath = server.homebridgeConfigPath;
@@ -11,12 +40,14 @@ async function getSwitchBotPlatformConfig() {
11
40
  const raw = await fs.readFile(cfgPath, 'utf8');
12
41
  const cfg = JSON.parse(raw);
13
42
  const platforms = Array.isArray(cfg.platforms) ? cfg.platforms : [];
14
- for (const p of platforms) {
43
+ const candidates = platforms.filter((p) => {
15
44
  const platformName = p.platform || p.name || '';
16
- if (!platformName || !/switchbot/i.test(String(platformName))) {
17
- continue;
18
- }
19
- return { config: cfg, platform: p, cfgPath };
45
+ return !!platformName && /switchbot/i.test(String(platformName));
46
+ });
47
+ const platform = candidates.find((p) => String(p.platform || '').toLowerCase() === 'switchbot')
48
+ ?? candidates[0];
49
+ if (platform) {
50
+ return { config: cfg, platform, cfgPath };
20
51
  }
21
52
  throw new Error('SwitchBot platform not found in config');
22
53
  }
@@ -37,8 +68,7 @@ server.onRequest('/devices', async () => {
37
68
  if (!platformName || !/switchbot/i.test(String(platformName))) {
38
69
  continue;
39
70
  }
40
- const options = p.options || p;
41
- const devices = Array.isArray(options.devices) ? options.devices : [];
71
+ const devices = getDevicesRef(p);
42
72
  for (const d of devices) {
43
73
  const id = d.deviceId ?? d.id;
44
74
  if (!id) {
@@ -69,7 +99,7 @@ server.onRequest('/discover', async () => {
69
99
  try {
70
100
  const { platform } = await getSwitchBotPlatformConfig();
71
101
  console.log('[SwitchBot UI] GET /discover - Platform config:', Object.keys(platform));
72
- const token = platform.openApiToken || platform.token;
102
+ const token = getCredential(platform, 'openApiToken') || platform.token;
73
103
  if (!token) {
74
104
  console.error('[SwitchBot UI] No API token found in platform config');
75
105
  throw new Error('OpenAPI token not configured. Please save your credentials first.');
@@ -139,17 +169,21 @@ server.onRequest('/add-device', async (body) => {
139
169
  }
140
170
  const { config, platform, cfgPath } = await getSwitchBotPlatformConfig();
141
171
  console.log('[SwitchBot UI] POST /add-device - Adding device:', deviceId);
142
- // Initialize devices array if needed
143
- if (!Array.isArray(platform.devices)) {
144
- platform.devices = [];
145
- }
172
+ const devices = getDevicesRef(platform);
146
173
  // Check if already exists
147
- const exists = platform.devices.some((d) => (d.deviceId ?? d.id) === deviceId);
174
+ const normalizedDeviceId = String(deviceId).trim().toLowerCase();
175
+ const exists = devices.some((d) => String(d.deviceId ?? d.id ?? '').trim().toLowerCase() === normalizedDeviceId);
148
176
  if (exists) {
149
- return { success: false, data: { message: 'Device already in config' } };
177
+ return {
178
+ success: true,
179
+ data: {
180
+ message: 'Device already in config',
181
+ alreadyExists: true,
182
+ },
183
+ };
150
184
  }
151
185
  // Add device
152
- platform.devices.push({
186
+ devices.push({
153
187
  deviceId,
154
188
  configDeviceName: name,
155
189
  configDeviceType: type,
@@ -159,7 +193,10 @@ server.onRequest('/add-device', async (body) => {
159
193
  console.log('[SwitchBot UI] Device added successfully:', deviceId);
160
194
  return {
161
195
  success: true,
162
- data: { message: `Device "${name}" added successfully` },
196
+ data: {
197
+ message: `Device "${name}" added successfully`,
198
+ alreadyExists: false,
199
+ },
163
200
  };
164
201
  }
165
202
  catch (e) {
@@ -177,13 +214,11 @@ server.onRequest('/update-device', async (body) => {
177
214
  const { config, platform, cfgPath } = await getSwitchBotPlatformConfig();
178
215
  console.log('[SwitchBot UI] POST /update-device - Updating device:', deviceId);
179
216
  console.log('[SwitchBot UI] Parameters - name:', configDeviceName, 'type:', configDeviceType, 'pref:', connectionPreference, 'room:', room);
180
- // Find and update device
181
- if (!Array.isArray(platform.devices)) {
182
- throw new TypeError('No devices found in config');
183
- }
184
- const device = platform.devices.find((d) => (d.deviceId ?? d.id) === deviceId);
217
+ const devices = getDevicesRef(platform);
218
+ const normalizedDeviceId = String(deviceId).trim().toLowerCase();
219
+ const device = devices.find((d) => String(d.deviceId ?? d.id ?? '').trim().toLowerCase() === normalizedDeviceId);
185
220
  if (!device) {
186
- console.error('[SwitchBot UI] Device not found. Available devices:', platform.devices.map((d) => d.deviceId ?? d.id));
221
+ console.error('[SwitchBot UI] Device not found. Available devices:', devices.map((d) => d.deviceId ?? d.id));
187
222
  throw new Error('Device not found in config');
188
223
  }
189
224
  console.log('[SwitchBot UI] Found device before update:', JSON.stringify(device, null, 2));
@@ -227,16 +262,14 @@ server.onRequest('/delete-device', async (body) => {
227
262
  }
228
263
  const { config, platform, cfgPath } = await getSwitchBotPlatformConfig();
229
264
  console.log('[SwitchBot UI] POST /delete-device - Deleting:', deviceId);
230
- // Remove device from array
231
- if (!Array.isArray(platform.devices)) {
232
- throw new TypeError('No devices found in config');
233
- }
234
- const index = platform.devices.findIndex((d) => (d.deviceId ?? d.id) === deviceId);
265
+ const devices = getDevicesRef(platform);
266
+ const normalizedDeviceId = String(deviceId).trim().toLowerCase();
267
+ const index = devices.findIndex((d) => String(d.deviceId ?? d.id ?? '').trim().toLowerCase() === normalizedDeviceId);
235
268
  if (index === -1) {
236
269
  throw new Error('Device not found in config');
237
270
  }
238
- const deviceName = platform.devices[index].configDeviceName || deviceId;
239
- platform.devices.splice(index, 1);
271
+ const deviceName = devices[index].configDeviceName || deviceId;
272
+ devices.splice(index, 1);
240
273
  // Save config
241
274
  await fs.writeFile(cfgPath, JSON.stringify(config, null, 2), 'utf8');
242
275
  console.log('[SwitchBot UI] Device deleted successfully:', deviceId);
@@ -256,11 +289,13 @@ server.onRequest('/credentials', async (body) => {
256
289
  if (!body || Object.keys(body).length === 0) {
257
290
  // GET request - return current status
258
291
  const { platform } = await getSwitchBotPlatformConfig();
292
+ const token = getCredential(platform, 'openApiToken');
293
+ const secret = getCredential(platform, 'openApiSecret');
259
294
  const status = {
260
- hasToken: !!platform.openApiToken,
261
- hasSecret: !!platform.openApiSecret,
262
- tokenLength: platform.openApiToken ? String(platform.openApiToken).length : 0,
263
- secretLength: platform.openApiSecret ? String(platform.openApiSecret).length : 0,
295
+ hasToken: !!token,
296
+ hasSecret: !!secret,
297
+ tokenLength: token ? String(token).length : 0,
298
+ secretLength: secret ? String(secret).length : 0,
264
299
  };
265
300
  console.log('[SwitchBot UI] GET /credentials - Status:', status);
266
301
  return { success: true, data: status };
@@ -275,9 +310,9 @@ server.onRequest('/credentials', async (body) => {
275
310
  console.log('[SwitchBot UI] POST /credentials - Saving to platform:', platform.platform || platform.name);
276
311
  console.log('[SwitchBot UI] Config path:', cfgPath);
277
312
  console.log('[SwitchBot UI] Token length:', token.length, 'Secret length:', secret.length);
278
- // Save token and secret directly on the platform config
279
- platform.openApiToken = token;
280
- platform.openApiSecret = secret;
313
+ // Save token and secret on the same config branch used by this platform
314
+ setCredential(platform, 'openApiToken', token);
315
+ setCredential(platform, 'openApiSecret', secret);
281
316
  // Write back to config file
282
317
  await fs.writeFile(cfgPath, JSON.stringify(config, null, 2), 'utf8');
283
318
  console.log('[SwitchBot UI] Credentials saved successfully');
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/homebridge-ui/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/homebridge-ui/server.ts"],"names":[],"mappings":"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"}
@@ -1 +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">=&gt;</span> <span class="tsd-signature-type">void</span></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></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/2dca97cab0afa8ab2831499e0bf438cda45a2791/src/index.ts#L12">index.ts:12</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>
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">=&gt;</span> <span class="tsd-signature-type">void</span></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></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/b714b419d7004e9f477bd9865b39854fd8742461/src/index.ts#L12">index.ts:12</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.0-beta.86",
5
+ "version": "5.0.0-beta.87",
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": [
@@ -83,7 +83,7 @@
83
83
  },
84
84
  "dependencies": {
85
85
  "@homebridge/plugin-ui-utils": "^2.2.1",
86
- "node-switchbot": "^4.0.0-beta.2"
86
+ "node-switchbot": "^4.0.0-beta.3"
87
87
  },
88
88
  "devDependencies": {
89
89
  "@antfu/eslint-config": "^7.6.1",
@@ -259,7 +259,10 @@
259
259
  throw new Error(resp?.data?.message || 'Discovery failed')
260
260
  }
261
261
 
262
- const devices = resp.data || []
262
+ const devicesRaw = resp.data || []
263
+ const devices = devicesRaw.filter((d, index, arr) =>
264
+ !!d?.id && arr.findIndex((x) => x?.id === d.id) === index,
265
+ )
263
266
 
264
267
  if (!devices.length) {
265
268
  status.textContent = 'No devices found in your SwitchBot account'
@@ -275,8 +278,12 @@
275
278
 
276
279
  for (const d of devices) {
277
280
  try {
278
- await addDeviceToConfig(d)
279
- addedCount++
281
+ const result = await addDeviceToConfig(d, { refresh: false, showStatus: false })
282
+ if (result?.added) {
283
+ addedCount++
284
+ } else {
285
+ skippedCount++
286
+ }
280
287
  } catch (e) {
281
288
  console.warn(`Failed to add device ${d.id}:`, e)
282
289
  skippedCount++
@@ -288,7 +295,7 @@
288
295
  list.style.display = 'none'
289
296
 
290
297
  // Refresh the configured devices list
291
- await load()
298
+ await loadConfiguredDevices()
292
299
  return
293
300
  }
294
301
 
@@ -335,7 +342,8 @@
335
342
  }
336
343
  }
337
344
 
338
- async function addDeviceToConfig(device) {
345
+ async function addDeviceToConfig(device, options = {}) {
346
+ const { refresh = true, showStatus = true } = options
339
347
  try {
340
348
  console.log('Adding device to config:', device)
341
349
 
@@ -351,23 +359,29 @@
351
359
  throw new Error(resp?.data?.message || 'Failed to add device')
352
360
  }
353
361
 
354
- // Show success message
355
- const message = resp.data?.message || `Device "${device.name}" added successfully!`
356
- const status = document.getElementById('discoverStatus')
357
- status.textContent = '✓ ' + message
358
- status.classList.remove('error')
359
- status.classList.add('success-msg')
362
+ const alreadyExists = !!resp.data?.alreadyExists
363
+ const message = resp.data?.message || (alreadyExists
364
+ ? `Device "${device.name}" already in config`
365
+ : `Device "${device.name}" added successfully!`)
366
+
367
+ if (showStatus) {
368
+ const status = document.getElementById('discoverStatus')
369
+ status.textContent = (alreadyExists ? '• ' : '✓ ') + message
370
+ status.classList.remove('error')
371
+ status.classList.add('success-msg')
372
+ }
360
373
 
361
- // Refresh lists after 1 second
362
- setTimeout(async () => {
374
+ if (refresh) {
363
375
  await loadConfiguredDevices()
364
- await discoverDevices()
365
- }, 1000)
376
+ }
377
+
378
+ return { added: !alreadyExists }
366
379
  } catch (e) {
367
380
  console.error('Add device error:', e)
368
381
  const status = document.getElementById('discoverStatus')
369
382
  status.textContent = '✗ Error: ' + (e?.message || 'Failed to add device')
370
383
  status.classList.add('error')
384
+ return { added: false }
371
385
  }
372
386
  }
373
387
 
@@ -4,6 +4,43 @@ import fs from 'node:fs/promises'
4
4
 
5
5
  const server = new HomebridgePluginUiServer()
6
6
 
7
+ function getDevicesRef(platform: any): any[] {
8
+ if (Array.isArray(platform?.devices)) {
9
+ return platform.devices
10
+ }
11
+
12
+ if (platform?.options && typeof platform.options === 'object') {
13
+ if (!Array.isArray(platform.options.devices)) {
14
+ platform.options.devices = []
15
+ }
16
+ return platform.options.devices
17
+ }
18
+
19
+ if (platform && typeof platform === 'object') {
20
+ platform.devices = []
21
+ return platform.devices
22
+ }
23
+
24
+ return []
25
+ }
26
+
27
+ function getCredential(platform: any, key: 'openApiToken' | 'openApiSecret') {
28
+ return platform?.[key] ?? platform?.options?.[key]
29
+ }
30
+
31
+ function setCredential(platform: any, key: 'openApiToken' | 'openApiSecret', value: string) {
32
+ if (!platform || typeof platform !== 'object') {
33
+ return
34
+ }
35
+
36
+ if (platform.options && Object.prototype.hasOwnProperty.call(platform.options, key)) {
37
+ platform.options[key] = value
38
+ return
39
+ }
40
+
41
+ platform[key] = value
42
+ }
43
+
7
44
  // Helper function to find the SwitchBot platform config
8
45
  async function getSwitchBotPlatformConfig() {
9
46
  const cfgPath = server.homebridgeConfigPath
@@ -15,12 +52,16 @@ async function getSwitchBotPlatformConfig() {
15
52
  const cfg = JSON.parse(raw)
16
53
  const platforms = Array.isArray(cfg.platforms) ? cfg.platforms : []
17
54
 
18
- for (const p of platforms) {
55
+ const candidates = platforms.filter((p: any) => {
19
56
  const platformName = p.platform || p.name || ''
20
- if (!platformName || !/switchbot/i.test(String(platformName))) {
21
- continue
22
- }
23
- return { config: cfg, platform: p, cfgPath }
57
+ return !!platformName && /switchbot/i.test(String(platformName))
58
+ })
59
+
60
+ const platform = candidates.find((p: any) => String(p.platform || '').toLowerCase() === 'switchbot')
61
+ ?? candidates[0]
62
+
63
+ if (platform) {
64
+ return { config: cfg, platform, cfgPath }
24
65
  }
25
66
 
26
67
  throw new Error('SwitchBot platform not found in config')
@@ -46,8 +87,7 @@ server.onRequest('/devices', async () => {
46
87
  continue
47
88
  }
48
89
 
49
- const options = p.options || p
50
- const devices = Array.isArray(options.devices) ? options.devices : []
90
+ const devices = getDevicesRef(p)
51
91
  for (const d of devices) {
52
92
  const id = d.deviceId ?? d.id
53
93
  if (!id) {
@@ -81,7 +121,7 @@ server.onRequest('/discover', async () => {
81
121
 
82
122
  console.log('[SwitchBot UI] GET /discover - Platform config:', Object.keys(platform))
83
123
 
84
- const token = platform.openApiToken || platform.token
124
+ const token = getCredential(platform, 'openApiToken') || platform.token
85
125
  if (!token) {
86
126
  console.error('[SwitchBot UI] No API token found in platform config')
87
127
  throw new Error('OpenAPI token not configured. Please save your credentials first.')
@@ -161,19 +201,23 @@ server.onRequest('/add-device', async (body: any) => {
161
201
 
162
202
  console.log('[SwitchBot UI] POST /add-device - Adding device:', deviceId)
163
203
 
164
- // Initialize devices array if needed
165
- if (!Array.isArray(platform.devices)) {
166
- platform.devices = []
167
- }
204
+ const devices = getDevicesRef(platform)
168
205
 
169
206
  // Check if already exists
170
- const exists = platform.devices.some((d: any) => (d.deviceId ?? d.id) === deviceId)
207
+ const normalizedDeviceId = String(deviceId).trim().toLowerCase()
208
+ const exists = devices.some((d: any) => String(d.deviceId ?? d.id ?? '').trim().toLowerCase() === normalizedDeviceId)
171
209
  if (exists) {
172
- return { success: false, data: { message: 'Device already in config' } }
210
+ return {
211
+ success: true,
212
+ data: {
213
+ message: 'Device already in config',
214
+ alreadyExists: true,
215
+ },
216
+ }
173
217
  }
174
218
 
175
219
  // Add device
176
- platform.devices.push({
220
+ devices.push({
177
221
  deviceId,
178
222
  configDeviceName: name,
179
223
  configDeviceType: type,
@@ -186,7 +230,10 @@ server.onRequest('/add-device', async (body: any) => {
186
230
 
187
231
  return {
188
232
  success: true,
189
- data: { message: `Device "${name}" added successfully` },
233
+ data: {
234
+ message: `Device "${name}" added successfully`,
235
+ alreadyExists: false,
236
+ },
190
237
  }
191
238
  } catch (e) {
192
239
  console.error('[SwitchBot UI] Error in /add-device:', e)
@@ -209,14 +256,11 @@ server.onRequest('/update-device', async (body: any) => {
209
256
  console.log('[SwitchBot UI] POST /update-device - Updating device:', deviceId)
210
257
  console.log('[SwitchBot UI] Parameters - name:', configDeviceName, 'type:', configDeviceType, 'pref:', connectionPreference, 'room:', room)
211
258
 
212
- // Find and update device
213
- if (!Array.isArray(platform.devices)) {
214
- throw new TypeError('No devices found in config')
215
- }
216
-
217
- const device = platform.devices.find((d: any) => (d.deviceId ?? d.id) === deviceId)
259
+ const devices = getDevicesRef(platform)
260
+ const normalizedDeviceId = String(deviceId).trim().toLowerCase()
261
+ const device = devices.find((d: any) => String(d.deviceId ?? d.id ?? '').trim().toLowerCase() === normalizedDeviceId)
218
262
  if (!device) {
219
- console.error('[SwitchBot UI] Device not found. Available devices:', platform.devices.map((d: any) => d.deviceId ?? d.id))
263
+ console.error('[SwitchBot UI] Device not found. Available devices:', devices.map((d: any) => d.deviceId ?? d.id))
220
264
  throw new Error('Device not found in config')
221
265
  }
222
266
 
@@ -270,18 +314,15 @@ server.onRequest('/delete-device', async (body: any) => {
270
314
 
271
315
  console.log('[SwitchBot UI] POST /delete-device - Deleting:', deviceId)
272
316
 
273
- // Remove device from array
274
- if (!Array.isArray(platform.devices)) {
275
- throw new TypeError('No devices found in config')
276
- }
277
-
278
- const index = platform.devices.findIndex((d: any) => (d.deviceId ?? d.id) === deviceId)
317
+ const devices = getDevicesRef(platform)
318
+ const normalizedDeviceId = String(deviceId).trim().toLowerCase()
319
+ const index = devices.findIndex((d: any) => String(d.deviceId ?? d.id ?? '').trim().toLowerCase() === normalizedDeviceId)
279
320
  if (index === -1) {
280
321
  throw new Error('Device not found in config')
281
322
  }
282
323
 
283
- const deviceName = platform.devices[index].configDeviceName || deviceId
284
- platform.devices.splice(index, 1)
324
+ const deviceName = devices[index].configDeviceName || deviceId
325
+ devices.splice(index, 1)
285
326
 
286
327
  // Save config
287
328
  await fs.writeFile(cfgPath, JSON.stringify(config, null, 2), 'utf8')
@@ -305,11 +346,13 @@ server.onRequest('/credentials', async (body: any) => {
305
346
  // GET request - return current status
306
347
  const { platform } = await getSwitchBotPlatformConfig()
307
348
 
349
+ const token = getCredential(platform, 'openApiToken')
350
+ const secret = getCredential(platform, 'openApiSecret')
308
351
  const status = {
309
- hasToken: !!platform.openApiToken,
310
- hasSecret: !!platform.openApiSecret,
311
- tokenLength: platform.openApiToken ? String(platform.openApiToken).length : 0,
312
- secretLength: platform.openApiSecret ? String(platform.openApiSecret).length : 0,
352
+ hasToken: !!token,
353
+ hasSecret: !!secret,
354
+ tokenLength: token ? String(token).length : 0,
355
+ secretLength: secret ? String(secret).length : 0,
313
356
  }
314
357
 
315
358
  console.log('[SwitchBot UI] GET /credentials - Status:', status)
@@ -328,9 +371,9 @@ server.onRequest('/credentials', async (body: any) => {
328
371
  console.log('[SwitchBot UI] Config path:', cfgPath)
329
372
  console.log('[SwitchBot UI] Token length:', token.length, 'Secret length:', secret.length)
330
373
 
331
- // Save token and secret directly on the platform config
332
- platform.openApiToken = token
333
- platform.openApiSecret = secret
374
+ // Save token and secret on the same config branch used by this platform
375
+ setCredential(platform, 'openApiToken', token)
376
+ setCredential(platform, 'openApiSecret', secret)
334
377
 
335
378
  // Write back to config file
336
379
  await fs.writeFile(cfgPath, JSON.stringify(config, null, 2), 'utf8')