Skip to content

Upgrade Swisscom integration#171816

Merged
joostlek merged 10 commits into
home-assistant:devfrom
anatosun:upgrade/swisscom
Jun 4, 2026
Merged

Upgrade Swisscom integration#171816
joostlek merged 10 commits into
home-assistant:devfrom
anatosun:upgrade/swisscom

Conversation

@anatosun
Copy link
Copy Markdown
Contributor

@anatosun anatosun commented May 22, 2026

Breaking change

The Swisscom Internet-Box integration is no longer configured via YAML. Existing entries in configuration.yaml are automatically imported into a config entry on the next restart, after which a repair issue will ask you to remove the YAML block from configuration.yaml. YAML support will be removed in Home Assistant 2027.5.

Authentication is now required. The legacy YAML platform queried /ws unauthenticated, which no longer works reliably on recent Internet-Box firmware. During the YAML→config-entry import you will need to provide the administrator password (printed on the bottom of the box); the username defaults to admin.

Proposed change

Migrate the Swisscom Internet-Box integration from a legacy YAML-only DeviceScanner to a UI config flow:

  • New config_flow.py with a user and an import step that asks for host, username (default admin) and password, validates by performing the Sagemcom sah.Device.Information.createContext handshake against http://<host>/ws, and uses the box's BaseMAC (from DeviceInfo.get) as the config entry unique ID.
  • Small async client in api.py (SwisscomClient) that encapsulates the /ws calls and transparently re-authenticates once when the context ID expires.
  • SwisscomDataUpdateCoordinator polling Devices.get every 30 seconds and re-raising authentication failures as ConfigEntryAuthFailed.
  • device_tracker.py rewritten to expose one ScannerEntity per LAN device known to the box, fed by the coordinator.
  • The legacy YAML platform still validates via the original PLATFORM_SCHEMA, but async_setup_scanner now triggers SOURCE_IMPORT for the config flow and raises the standard deprecated_yaml repair issue so existing users are migrated transparently.
  • manifest.json updated: config_flow: true, integration_type: hub, legacy quality scale marker removed.

The change was validated against an IB4-00 box running firmware 14.20.40.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Deprecation (breaking change to happen in the future)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Checklist

  • I understand the code I am submitting and can explain how it works.
  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • I have followed the perfect PR recommendations
  • The code has been formatted using Ruff (ruff format homeassistant tests)
  • Tests have been added to verify that the new code works.
  • Any generated code has been carefully reviewed for correctness and compliance with project standards.

If user exposed functionality or configuration variables are added/changed:

Please allow me to finish my rejuvenation work before updating the documentation.

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • For the updated dependencies a diff between library versions and ideally a link to the changelog/release notes is added to the PR description.

To help with the load of incoming pull requests:

Copilot AI review requested due to automatic review settings May 22, 2026 06:14
@home-assistant home-assistant Bot added cla-signed config-flow This integration migrates to the UI by adding a config flow deprecation Indicates a breaking change to happen in the future integration: swisscom Quality Scale: legacy labels May 22, 2026
Copy link
Copy Markdown
Contributor

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

Note

Copilot was unable to run its full agentic suite in this review.

This PR modernizes the Swisscom Internet-Box integration by adding a config flow and refactoring device tracking to use an async DataUpdateCoordinator + entity-based device tracker.

Changes:

  • Added config flow, constants, API client, and coordinator for async polling and authentication handling.
  • Refactored device_tracker platform from legacy DeviceScanner to config-entry setup with ScannerEntity + coordinator.
  • Updated the integration manifest and added base UI strings for the config flow.

Reviewed changes

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

Show a summary per file
File Description
homeassistant/components/swisscom/strings.json Adds config flow strings for setup/abort/errors.
homeassistant/components/swisscom/manifest.json Enables config flow and updates integration metadata.
homeassistant/components/swisscom/device_tracker.py Migrates device tracker to config entries + coordinator + entities; adds YAML import deprecation issue.
homeassistant/components/swisscom/coordinator.py Introduces polling coordinator that fetches and normalizes device data.
homeassistant/components/swisscom/const.py Adds integration constants and defaults.
homeassistant/components/swisscom/config_flow.py Implements UI and YAML import config flow with credential validation.
homeassistant/components/swisscom/api.py Adds aiohttp-based client for the router web-services endpoint.
homeassistant/components/swisscom/init.py Sets up config-entry lifecycle and forwards platforms.

},
)
if (
result.get("type") is FlowResultType.ABORT
Comment on lines +57 to +61
devices[device["Key"]] = {
"ip": device["IPAddress"],
"mac": device["PhysAddress"],
"host": device["Name"],
"active": device["Active"],
Comment on lines +61 to +75
ir.async_create_issue(
hass,
HOMEASSISTANT_DOMAIN,
f"deprecated_yaml_{DOMAIN}",
breaks_in_ha_version="2027.5.0",
is_fixable=False,
is_persistent=False,
issue_domain=DOMAIN,
severity=ir.IssueSeverity.WARNING,
translation_key="deprecated_yaml",
translation_placeholders={
"domain": DOMAIN,
"integration_title": "Swisscom Internet-Box",
},
)
Comment on lines +55 to +64
for device in raw:
try:
devices[device["Key"]] = {
"ip": device["IPAddress"],
"mac": device["PhysAddress"],
"host": device["Name"],
"active": device["Active"],
}
except KeyError:
continue
@anatosun
Copy link
Copy Markdown
Contributor Author

This superseeds this PR.

Comment on lines +44 to +54
try:
async with self._session.post(
self._url,
json=payload,
headers={"Content-Type": CONTENT_TYPE, **headers},
timeout=REQUEST_TIMEOUT,
) as response:
if response.status == 401:
raise SwisscomAuthError("Unauthorized")
response.raise_for_status()
return await response.json(content_type=None)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So device specific logic should exist in a library hosted on PyPI, not in the integration

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Just so I understand, you're saying I should wrap the calls in a specific library and publish the package to PyPI?

@home-assistant home-assistant Bot marked this pull request as draft May 26, 2026 19:33
@home-assistant
Copy link
Copy Markdown
Contributor

Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍

Learn more about our pull request process.

Copilot AI review requested due to automatic review settings May 28, 2026 11:19
@anatosun anatosun marked this pull request as ready for review May 28, 2026 11:20
@home-assistant home-assistant Bot requested a review from joostlek May 28, 2026 11:20
Copy link
Copy Markdown
Member

@joostlek joostlek left a comment

Choose a reason for hiding this comment

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

Awesome!

Okay so 3 other things:

  1. Because we migrate away from DeviceScanner we have more room to change stuff as we need to step away from the Scanner onto ScannerEntities. Usually we would ask to change to the library beforehand, but as that code wouldn't be used afterwards I am fine with moving to the library in this PR as well.
  2. The config flow needs to be 100% unit tested
  3. I see that we add more YAML config to the device tracker platform. Let's not do that and just import the host if we have that. If we can't import it now because people have set a username or password, we can let users know in the issue we raise.

We merged the opnsense PR last week that had the same kind of migration, you can use that as example. Feel free to message me on Discord!

@home-assistant home-assistant Bot marked this pull request as draft May 28, 2026 11:43
@anatosun
Copy link
Copy Markdown
Contributor Author

Thanks for the guidance @joostlek, really helpful, especially the pointer to the OPNsense PR.

Since the new integration genuinely needs credentials and the legacy YAML can't carry them, I diverged slightly from the OPNsense pattern: instead of routing through async_step_import only to abort, async_setup_scanner raises a repair issue directly, telling the user to set up via UI and including their existing host as a placeholder for convenience. Is that fine this way?

@anatosun anatosun force-pushed the upgrade/swisscom branch from 63baad2 to 6b7157e Compare May 28, 2026 13:36
@anatosun anatosun marked this pull request as ready for review May 28, 2026 13:37
@home-assistant home-assistant Bot requested a review from joostlek May 28, 2026 13:37
@joostlek
Copy link
Copy Markdown
Member

Can you elaborate on why we now need credentials? With OPNSense the issue was that this was only supporting an OLD version, and the new one worked differently

@anatosun
Copy link
Copy Markdown
Contributor Author

The /ws endpoint on recent Internet-Box firmware (I tested on IB4-00 running 14.20.40) no longer reliably responds to unauthenticated sah.Device.Information.get calls, it either returns an empty device list or a 401, depending on the firmware revision. The legacy scanner worked only because older firmware didn't enforce authentication on that endpoint.

@joostlek
Copy link
Copy Markdown
Member

But it currently is still installed in 48 installations. How big is the chance that people are still running older firmware?

@anatosun
Copy link
Copy Markdown
Contributor Author

But it currently is still installed in 48 installations. How big is the chance that people are still running older firmware?

Realistically very low, and I'd argue most of those 48 are already broken rather than quietly working passwordless.

The unauthenticated Devices.get call the legacy scanner relies on stopped working with Swisscom firmware 13.20.18/13.20.26 back in early 2023. The box now returns error 13 "Permission denied". That's documented in #87220, which has been open since Feb 2023 with a steady stream of users confirming the integration returns no devices on current firmware.

Every working solution since then has required the router admin password: christophniederberger's patch in #89460, and schmidtfx's swisscom-internetbox-hass HACS component that a lot of users in that thread migrated to. There's no known working passwordless path on any firmware from the last three years.

So requiring credentials isn't breaking working installs, those installs have been dead since 2023. It's the only way to make the integration work again on supported firmware. The only people who'd be on genuinely passwordless firmware are those who haven't taken a router update in 3+ years (e.g. an Internet-Box 2 that never got 13.20.x), which is a vanishing minority, and they get a clear repair issue pointing them to the UI setup rather than a silent failure.

@joostlek
Copy link
Copy Markdown
Member

Okay understood. Let's go ahead then :)

Comment thread homeassistant/components/swisscom/config_flow.py Outdated
Comment thread homeassistant/components/swisscom/device_tracker.py Outdated
Comment thread tests/components/swisscom/conftest.py
@home-assistant home-assistant Bot marked this pull request as draft May 29, 2026 10:19
@anatosun anatosun marked this pull request as ready for review June 4, 2026 11:23
@home-assistant home-assistant Bot requested a review from joostlek June 4, 2026 11:23
Comment thread homeassistant/components/swisscom/device_tracker.py Outdated
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 4, 2026

Check requirements

⚠️ Some checks require attention — see the details below.

Package Old New No Advisories Not Yanked Repo Public CI Upload Release Pipeline PR Link Async Safe
python-swisscom-internet-box 0.1.1
📦 python-swisscom-internet-box: 0.1.1
  • No Advisories: ✅ No active advisories reported by PyPI for version 0.1.1.
  • Not Yanked: ✅ Version 0.1.1 is a live (non-yanked) release.
  • Repo Public: ✅ https://github.com/anatosun/python-swisscom-internet-box is publicly accessible.
  • CI Upload: ✅ Trusted Publisher attestation found (GitHub).
  • Release Pipeline: ✅ OIDC via Trusted Publisher attestation (GitHub); automated CI upload verified by PyPI.
  • PR Link: ❌ PR description must link to the source repository at https://github.com/anatosun/python-swisscom-internet-box. A PyPI page link is not sufficient.
  • Async Safe: ✅ No blocking calls found in the async surface; all I/O uses aiohttp.ClientSession exclusively.

Generated by Check requirements (AW) · sonnet46 970.6K ·

@anatosun
Copy link
Copy Markdown
Contributor Author

anatosun commented Jun 4, 2026

Should I do something more?

@joostlek joostlek merged commit 9f5cb63 into home-assistant:dev Jun 4, 2026
47 of 48 checks passed
@joostlek
Copy link
Copy Markdown
Member

joostlek commented Jun 4, 2026

Can you send open a documentation PR and send me a message on Discord?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed config-flow This integration migrates to the UI by adding a config flow deprecation Indicates a breaking change to happen in the future integration: swisscom Quality Scale: legacy

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants