Skip to content

feat(ui): detect legacy v4 config format and surface incompatibility warning#1360

Merged
donavanbecker merged 3 commits intobeta-5.1.0from
copilot/fix-config-compatibility-issues
Apr 15, 2026
Merged

feat(ui): detect legacy v4 config format and surface incompatibility warning#1360
donavanbecker merged 3 commits intobeta-5.1.0from
copilot/fix-config-compatibility-issues

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 12, 2026

v4 configs nest credentials under credentials{} and devices under options.devices[]; v5+ expects openApiToken/openApiSecret at the platform root and a top-level devices[]. When a v4 config is present, the plugin silently finds no devices — no error, no indication of what's wrong.

Changes

  • src/homebridge-ui/utils/v4-detection.ts — new shared pure utility isV4Config(platform): detects v4 format via presence of credentials object or options.devices array; no Node.js deps so it bundles cleanly for the browser

  • src/homebridge-ui/utils/config-parser.ts — re-exports isV4Config from the new shared module

  • src/homebridge-ui/endpoints/config.ts — server-side /devices endpoint now calls isV4Config, logs a warning, and includes v4ConfigDetected: true in the response

  • src/homebridge-ui/public/js/api.ts — new detectV4Config() async function queries the Homebridge plugin config via the UI API and delegates to the shared isV4Config()

  • src/homebridge-ui/public/js/app.ts — calls checkV4Config() at init; reveals the warning banner when v4 is detected

  • src/homebridge-ui/public/index.html — hidden #v4ConfigWarning banner with step-by-step migration instructions; shown programmatically

  • src/homebridge-ui/public/css/styles.css — warning banner styles with dark/light theme support

  • test/homebridge-ui/config-parser.spec.ts — unit tests for isV4Config() covering the exact config shape from the bug report

Example v4 config that triggers the warning:

{
  "platform": "SwitchBot",
  "credentials": { "notice": "Keep your token a secret!" },
  "options": {
    "devices": [{ "deviceId": "xxxxxxxx", "configDeviceType": "Curtain", "connectionType": "BLE" }]
  }
}

The banner directs users to flatten to openApiToken, openApiSecret, and devices[] and rename connectionTypeconnectionPreference.

Copilot AI linked an issue Apr 12, 2026 that may be closed by this pull request
Copilot AI changed the title [WIP] Fix config compatibility issues for BLE devices feat(ui): detect legacy v4 config format and surface incompatibility warning Apr 12, 2026
Copilot AI requested a review from donavanbecker April 12, 2026 21:46
@donavanbecker donavanbecker marked this pull request as ready for review April 15, 2026 14:15
Copilot AI review requested due to automatic review settings April 15, 2026 14:15
@donavanbecker donavanbecker merged commit 4e01015 into beta-5.1.0 Apr 15, 2026
1 check passed
@donavanbecker donavanbecker deleted the copilot/fix-config-compatibility-issues branch April 15, 2026 14:15
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds legacy v4 config detection to the Homebridge UI (and server logs) so users get a clear incompatibility warning instead of silently seeing “no devices”.

Changes:

  • Introduces a shared isV4Config() utility to detect v4-style credentials / options.devices shapes.
  • Surfaces v4 detection in the UI via a warning banner and in server logs/response metadata.
  • Adds unit tests covering known v4 config shapes from the bug report.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/homebridge-ui/utils/v4-detection.ts New shared pure helper to detect legacy v4 config shapes.
src/homebridge-ui/utils/config-parser.ts Re-exports isV4Config for server-side utilities to consume.
src/homebridge-ui/endpoints/config.ts Detects v4 configs during /devices scan, logs warning, and returns v4ConfigDetected.
src/homebridge-ui/public/js/api.ts Adds detectV4Config() using the UI API + shared isV4Config().
src/homebridge-ui/public/js/app.ts Calls v4 detection at init and shows the warning banner when applicable.
src/homebridge-ui/public/index.html Adds hidden v4 incompatibility banner with migration steps and link.
src/homebridge-ui/public/css/styles.css Styles the v4 warning banner for dark/light modes.
test/homebridge-ui/config-parser.spec.ts New Vitest coverage for isV4Config() behavior.
package-lock.json Lockfile updated (contains additional dependency graph churn beyond the feature).

<li>Remove the <code>credentials</code> and <code>options</code> wrapper objects</li>
</ul>
<p>
See the <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/blob/latest/MIGRATION.md" target="_blank" rel="noopener">Migration Guide</a> for full details.
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The banner links to MIGRATION.md, but the current migration guide (repo root MIGRATION.md:18-20) states “Existing configs do not need changes” and doesn’t mention credentials/options.devices. Either update the linked doc in this PR or adjust the link/text so the user is sent to documentation that matches these migration steps.

Suggested change
See the <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/blob/latest/MIGRATION.md" target="_blank" rel="noopener">Migration Guide</a> for full details.
Follow the migration steps above to update your config to the v5 format before saving changes in this UI.

Copilot uses AI. Check for mistakes.
= platform.options !== undefined
&& typeof platform.options === 'object'
&& Array.isArray(platform.options.devices)
return hasCredentials || hasOptionsDevices
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isV4Config will return true for any config that still contains a credentials object even if it has already been migrated to v5 fields (e.g. openApiToken/openApiSecret and root devices). That makes the banner/log message (“not compatible with v5+”) incorrect for mixed configs. Consider tightening detection to require legacy fields and absence of the v5 equivalents (or at least absence of root devices).

Suggested change
return hasCredentials || hasOptionsDevices
// v5+ configs flatten credentials and move devices to the platform root
const hasRootDevices = Array.isArray(platform.devices)
const hasOpenApiToken = typeof platform.openApiToken === 'string' && platform.openApiToken.length > 0
const hasOpenApiSecret = typeof platform.openApiSecret === 'string' && platform.openApiSecret.length > 0
const hasV5Fields = hasRootDevices || hasOpenApiToken || hasOpenApiSecret
return (hasCredentials || hasOptionsDevices) && !hasV5Fields

Copilot uses AI. Check for mistakes.
}

// Detect legacy v4 config format
if (isV4Config(p)) {
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This warning will be logged once per matching platform block, which can spam logs if multiple SwitchBot blocks exist. Since you already track v4ConfigDetected, consider only logging the warning the first time (e.g. guard with if (!v4ConfigDetected && isV4Config(p))).

Suggested change
if (isV4Config(p)) {
if (!v4ConfigDetected && isV4Config(p)) {

Copilot uses AI. Check for mistakes.
Comment on lines +44 to +48
const config = configArr.find(isSwitchBotPlatformConfig)
if (!config || typeof config !== 'object') {
return false
}
return isV4Config(config)
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

detectV4Config() only checks the first SwitchBot config block (find). If users have multiple SwitchBot platform blocks and the first one is v5 while another is legacy v4, the warning banner will not show. Consider scanning all matching blocks (e.g. some(isSwitchBotPlatformConfig && isV4Config)) and returning true if any are v4.

Suggested change
const config = configArr.find(isSwitchBotPlatformConfig)
if (!config || typeof config !== 'object') {
return false
}
return isV4Config(config)
return configArr.some(config => isSwitchBotPlatformConfig(config) && isV4Config(config))

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +20
<div id="v4ConfigWarning" class="v4-config-warning" style="display: none">
<strong>⚠️ Incompatible v4 Configuration Detected</strong>
<p>
Your config.json appears to be in the <strong>v4 format</strong> (using <code>credentials</code> and
<code>options.devices</code> fields). This format is <strong>not compatible with v5 or newer</strong> of the
SwitchBot plugin. Devices will not be recognised until the config is updated.
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this banner is shown dynamically, it likely won’t be announced by screen readers. Consider adding an appropriate ARIA role/live region (e.g. role="alert" and/or aria-live) and ensuring the heading/structure is accessible when displayed.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Config compatibility issues

3 participants