Skip to content

New integation: BirdNET-Go - #181457

Open
TN-1 wants to merge 15 commits into
home-assistant:devfrom
TN-1:birdnet_go
Open

New integation: BirdNET-Go#181457
TN-1 wants to merge 15 commits into
home-assistant:devfrom
TN-1:birdnet_go

Conversation

@TN-1

@TN-1 TN-1 commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Proposed change

BirdNET-Go is an acoustic monitoring system for real-time bird species identification from audio streams using AI classifiers.

This initial PR provides:
Config flow with connectivity and authentication validation.
Coordinator polling the API every 30 seconds.
Sensors: Todays detections, Lifetime species, Detection streak, Best day detections

This is limited to a single platform per the guidelines for new integrations. Future work may include:

  • Real-Time Detection Events, Fire Home Assistant events on each bird identification (common name, scientific name, confidence score, audio source) for instant automations and alerts.
  • Sensors for Last Detected Species, Confidence, and Detection Time.
  • Audio & Station Monitoring (sensor & binary_sensor)
  • Media Browser (media_source)

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:

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 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Port normalization and KPI authentication validation must be fixed before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds a local-polling BirdNET-Go integration with configuration, KPI sensors, metadata, and tests.

Changes:

  • Adds connection configuration and 30-second coordinator polling.
  • Exposes four BirdNET-Go statistics sensors.
  • Adds dependency metadata, translations, icons, quality-scale declarations, and tests.
File summaries
File Description
tests/components/birdnet_go/test_sensor.py Tests sensors and registries. Remove the four redundant numbered section comments.
tests/components/birdnet_go/test_init.py Tests setup, unloading, and failures.
tests/components/birdnet_go/test_config_flow.py Tests configuration-flow outcomes.
tests/components/birdnet_go/fixtures/kpis.json Provides KPI response data.
tests/components/birdnet_go/fixtures/health.json Provides health response data.
tests/components/birdnet_go/conftest.py Provides shared mocks and fixtures.
tests/components/birdnet_go/__init__.py Initializes the test package.
requirements_all.txt Adds aiobirdnetgo.
mypy.ini Enables strict mypy checks.
homeassistant/generated/integrations.json Adds generated integration metadata.
homeassistant/generated/config_flows.py Registers the configuration flow.
homeassistant/components/birdnet_go/strings.json Adds UI and entity translations.
homeassistant/components/birdnet_go/sensor.py Implements four KPI sensors.
homeassistant/components/birdnet_go/quality_scale.yaml Records quality-scale compliance; dependency source links need correction.
homeassistant/components/birdnet_go/manifest.json Declares integration metadata and dependency.
homeassistant/components/birdnet_go/icons.json Defines sensor icons.
homeassistant/components/birdnet_go/coordinator.py Polls KPI data and handles errors.
homeassistant/components/birdnet_go/const.py Defines integration constants.
homeassistant/components/birdnet_go/config_flow.py Adds configuration and validation. Must persist an integer port and validate credentials against the required KPI endpoint.
homeassistant/components/birdnet_go/__init__.py Implements setup and unloading.
CODEOWNERS Adds integration owners.
.strict-typing Enables strict typing.
Review details

Suppressed comments (5)

homeassistant/components/birdnet_go/quality_scale.yaml:11

  • Correct the dependency's source links before marking dependency transparency complete. The published 0.1.0 metadata and README point to the nonexistent tphakala/aiobirdnetgo, while its source and release are under TN-1/aiobirdnetgo, so consumers cannot follow the package's declared repository or bug-tracker links.
  dependency-transparency: done

tests/components/birdnet_go/test_sensor.py:24

  • Remove this numbered section comment; the following entity ID already makes the sensor under test explicit.
    # 1. Today Detections

tests/components/birdnet_go/test_sensor.py:29

  • Remove this numbered section comment; the following entity ID already makes the sensor under test explicit.
    # 2. Lifetime Species

tests/components/birdnet_go/test_sensor.py:34

  • Remove this numbered section comment; the following entity ID already makes the sensor under test explicit.
    # 3. Detection Streak

tests/components/birdnet_go/test_sensor.py:40

  • Remove this numbered section comment; the following entity ID already makes the sensor under test explicit.
    # 4. Best Day Count
  • Files reviewed: 20/22 changed files
  • Comments generated: 2
  • Review effort level: Balanced

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread homeassistant/components/birdnet_go/config_flow.py Outdated
Comment thread homeassistant/components/birdnet_go/config_flow.py Outdated
Copilot AI review requested due to automatic review settings September 6, 2026 14:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Endpoint deduplication and authentication handling have unresolved moderate issues.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (8)

Previously missed (1) — in code that hasn't changed since the last review.

homeassistant/components/birdnet_go/config_flow.py:54

  • Implement BirdNET-Go's supported token/session flow before exposing username and password. The native v2 middleware accepts only Bearer tokens or session cookies, while aiobirdnetgo turns these fields into an HTTP Basic header that BirdNET-Go rejects as malformed; remove these fields or add login/token handling in the library (including renewal/reauth for expiring tokens).

homeassistant/components/birdnet_go/quality_scale.yaml:11

  • Correct the dependency's published source links before marking dependency transparency complete. Version 0.1.0 points its Repository and Bug Tracker metadata at the nonexistent tphakala/aiobirdnetgo, while its tagged source and release are under TN-1/aiobirdnetgo, preventing consumers from reliably tracing the package to its source.
  dependency-transparency: done

tests/components/birdnet_go/test_sensor.py:24

  • Remove this numbered section comment because the following entity ID already identifies the sensor under test.
    # 1. Today Detections

tests/components/birdnet_go/test_sensor.py:34

  • Remove this numbered section comment because the following entity ID already identifies the sensor under test.
    # 3. Detection Streak

tests/components/birdnet_go/test_sensor.py:40

  • Remove this numbered section comment because the following entity ID already identifies the sensor under test.
    # 4. Best Day Count

tests/components/birdnet_go/test_sensor.py:45

  • Remove this section comment because the registry call already makes the assertion's subject explicit.
    # Entity registry check

tests/components/birdnet_go/test_sensor.py:52

  • Remove this section comment because the registry lookup already makes the assertion's subject explicit.
    # Device registry check

tests/components/birdnet_go/test_sensor.py:29

  • Remove this numbered section comment because the following entity ID already identifies the sensor under test.
    # 2. Lifetime Species
  • Files reviewed: 20/22 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread homeassistant/components/birdnet_go/config_flow.py
Copilot AI review requested due to automatic review settings September 6, 2026 14:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Config-flow validation, URL handling, and API-key test coverage have unresolved moderate issues.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (3)

Previously missed (1) — in code that hasn't changed since the last review.

tests/components/birdnet_go/test_config_flow.py:37

  • Add tests for the optional API-key configuration path. No test submits CONF_API_KEY or verifies that it is persisted and passed to BirdNetGoClient during both validation and entry setup, leaving this user-facing authentication path uncovered despite config-flow-test-coverage being marked done.

homeassistant/components/birdnet_go/config_flow.py:92

  • Preserve or reject URL base paths consistently before saving the entry. BirdNetGoClient parses the /api/ portion of the tested full URL as base_path during validation, but replacing CONF_HOST with client.host discards it; setup later reconstructs the client without that path and contacts a different endpoint. Either persist the base path or restrict input to a bare host and validate against that canonical endpoint.
                    host = client.host
                    port = client.port
                    use_ssl = client.use_ssl
                    user_input[CONF_HOST] = host

homeassistant/components/birdnet_go/config_flow.py:88

  • Remove this narrating comment. The assignments below already make the canonicalization explicit, so it adds no non-obvious constraint.
                    # Canonicalize endpoint parameters from client
  • Files reviewed: 20/22 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread homeassistant/components/birdnet_go/config_flow.py
Copilot AI review requested due to automatic review settings September 6, 2026 15:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Four moderate issues involving validation, IPv6 support, authentication, and statistics must be resolved.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (2)

Previously missed (1) — in code that hasn't changed since the last review.

homeassistant/components/birdnet_go/sensor.py:37

  • Use TOTAL_INCREASING for this daily-resetting counter. With TOTAL, the midnight reset is recorded as a large negative change in long-term statistics; TOTAL_INCREASING treats the decrease as a new meter cycle.

homeassistant/components/birdnet_go/config_flow.py:76

  • Require all four sensor fields in aiobirdnetgo before treating this probe as successful. Version 0.1.3 only requires today_detections and lifetime_species; missing best_day or detection_streak data is silently converted to zero, so an incompatible response still creates misleading sensors despite this validation step.
                await client.get_kpis()
  • Files reviewed: 20/22 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread homeassistant/components/birdnet_go/config_flow.py Outdated
Comment thread homeassistant/components/birdnet_go/config_flow.py Outdated
@TN-1
TN-1 marked this pull request as draft September 6, 2026 15:15
Copilot AI review requested due to automatic review settings September 6, 2026 15:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Client-construction failures can currently crash the configuration flow instead of returning an actionable error.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (5)

homeassistant/components/birdnet_go/config_flow.py:71

  • Replace the invalid-credentials error with guidance that authentication is unsupported. This form accepts only host, port, and SSL, while the BirdNET-Go KPI endpoint itself is unauthenticated; a 401/403 from a protected proxy therefore leaves users at an invalid_auth error with no credential they can change. Add a dedicated translated error or support credentials end to end.
            except BirdNetGoAuthenticationError:
                errors["base"] = "invalid_auth"

homeassistant/components/birdnet_go/strings.json:40

  • Change this sensor label to “Today's detections” (or “Detections today”) to make the wording grammatical, and update the expected entity ID and linked documentation accordingly.
        "name": "Today detections"

requirements_all.txt:227

  • Add the aiobirdnetgo 0.1.4 release or comparison link to the PR description, or leave the dependency-diff checklist item unchecked; the current description claims that information is present but does not include it.
aiobirdnetgo==0.1.4

tests/components/birdnet_go/test_sensor.py:42

  • Remove this redundant section comment because the following entity-registry lookup already states its purpose.
    # Entity registry check

tests/components/birdnet_go/test_sensor.py:49

  • Remove this redundant section comment because the following device-registry lookup already states its purpose.
    # Device registry check
  • Files reviewed: 20/22 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread homeassistant/components/birdnet_go/config_flow.py Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 6, 2026 15:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Runtime authentication failures currently stop polling without providing a reauthentication or automatic recovery path.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

homeassistant/components/birdnet_go/coordinator.py:53

  • Treat unsupported authentication as a retryable update failure instead of ConfigEntryAuthFailed. This flow stores no credentials and implements no reauthentication step, so Home Assistant stops scheduling coordinator refreshes after a runtime 401/403 without opening a reauthentication flow; the entities then cannot recover after authentication is disabled until the entry is manually reloaded. Raise UpdateFailed here so polling can recover, and update the setup test accordingly.
  • Files reviewed: 20/22 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Copilot AI review requested due to automatic review settings September 6, 2026 16:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The config-entry setup must directly access the required port and SSL values so malformed data is not silently accepted.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

homeassistant/components/birdnet_go/init.py:20

  • Use direct access for the port and SSL values. The config flow always persists both keys, so fallback defaults hide malformed config-entry data instead of surfacing the broken invariant.
  • Files reviewed: 20/22 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@TN-1
TN-1 marked this pull request as ready for review September 6, 2026 16:34
Copilot AI review requested due to automatic review settings September 6, 2026 16:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Authentication failures must trigger reauthentication instead of repeated polling.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

homeassistant/components/birdnet_go/coordinator.py:52

  • Raise ConfigEntryAuthFailed for authentication failures instead of retrying them. Wrapping a 401/403 in UpdateFailed makes the first refresh enter SETUP_RETRY and keeps a loaded entry polling every 30 seconds even though authentication is unsupported; the coordinator only stops polling and starts reauthentication for ConfigEntryAuthFailed (homeassistant/helpers/update_coordinator.py:538-586).
  • Files reviewed: 20/22 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Copilot AI review requested due to automatic review settings September 6, 2026 16:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Equivalent IPv6 representations can bypass duplicate-entry prevention and must be canonicalized.

Review details

Suppressed comments (4)

homeassistant/components/birdnet_go/config_flow.py:57

  • Use direct access for the schema-guaranteed SSL value. STEP_USER_DATA_SCHEMA always supplies this key, so .get() silently masks a broken flow contract.
            raw_ssl = bool(user_input.get(CONF_SSL, False))

homeassistant/components/birdnet_go/config_flow.py:61

  • Use direct access for the schema-guaranteed port value. The selector default makes this key mandatory after validation, so .get() would hide an invalid flow state.
                raw_port = int(user_input.get(CONF_PORT, DEFAULT_PORT))

homeassistant/components/birdnet_go/config_flow.py:91

  • Canonicalize IP literals before deriving the config-entry unique ID. The client currently only strips brackets and lowercases the host, so equivalent IPv6 inputs such as 2001:db8::1 and 2001:0db8:0:0:0:0:0:1 produce different IDs and let the same station be configured twice, despite unique-config-entry being marked done. Please normalize the host in aiobirdnetgo (for example, to the compressed IP form), bump the dependency, and cover the duplicate expanded/compressed IPv6 case.
                    unique_id = f"{host}:{port}"
                    await self.async_set_unique_id(unique_id)
                    self._abort_if_unique_id_configured()

tests/components/birdnet_go/conftest.py:30

  • Remove the unused health and ping scaffolding from this initial test fixture. Production and tests call only get_kpis, but every client fixture currently constructs mock_health and configures ping, get_ping, and get_health, coupling this suite to unrelated future APIs and retaining an otherwise unused JSON fixture.
def mock_birdnet_client(
    mock_kpis: DashboardKPIs, mock_health: HealthResponse
) -> Generator[AsyncMock]:
  • Files reviewed: 20/22 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Copilot AI review requested due to automatic review settings September 6, 2026 16:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The config-flow error handling, port validation, and best-day sensor statistics must be corrected before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (4)

Previously missed (2) — in code that hasn't changed since the last review.

homeassistant/components/birdnet_go/config_flow.py:76

  • Handle the API’s 409 response with an actionable migration error instead of cannot_connect. The released BirdNET-Go KPI endpoint returns 409 whenever the station is still using or migrating from the legacy database, so affected stations are reachable but this flow reports a connection failure; catch BirdNetGoResponseError first, inspect status_code, and tell the user that the enhanced database migration must complete.
    homeassistant/components/birdnet_go/sensor.py:56
  • Treat the best-day record as an absolute measurement rather than a cumulative total. TOTAL generates statistics for accumulated growth or decline, so a record changing from 420 to 500 is represented as a cumulative increase of 80 instead of the current record value.

homeassistant/components/birdnet_go/quality_scale.yaml:19

  • Document the authentication prerequisite before marking this rule done. The config flow rejects authenticated installations with auth_not_supported, but the linked documentation lists only host, port, and SSL, so users are not told that authentication must be disabled or bypassed before setup.
  docs-installation-instructions: done

homeassistant/components/birdnet_go/strings.json:7

  • Support authenticated connections instead of advising users to disable protection. aiobirdnetgo==0.1.5 accepts API-key or username/password credentials, but this flow never collects or passes them, so the advertised recovery weakens the BirdNET-Go deployment; add a credential path and pass it to both client constructions, or remove the disable-auth advice if authenticated installations are intentionally unsupported.
      "auth_not_supported": "Authentication is not supported. Please disable authentication or connect directly to BirdNET-Go.",
  • Files reviewed: 19/21 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread homeassistant/components/birdnet_go/config_flow.py Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 6, 2026 17:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The best-day sensor uses an incorrect state class, and its scope and API prerequisites need clarification.

Review details

Suppressed comments (3)

Previously missed (1) — in code that hasn't changed since the last review.

homeassistant/components/birdnet_go/sensor.py:56

  • Use SensorStateClass.MEASUREMENT for the best-day record. This value is a historical maximum rather than an accumulated total, so TOTAL produces misleading recorder sum statistics when the record changes; comparable maximum sensors such as ambient_station/sensor.py:403-407 use MEASUREMENT.

homeassistant/components/birdnet_go/quality_scale.yaml:19

  • Document the required BirdNET-Go database/API prerequisite before marking this rule done. In the released BirdNET-Go code, /api/v2/dashboard/kpis is registered only when the V2 manager is available, but the linked installation documentation does not tell legacy or actively migrating installations that setup cannot succeed until the enhanced-database migration is complete.
  docs-installation-instructions: done

homeassistant/components/birdnet_go/strings.json:31

  • Clarify that this metric covers only the past year. BirdNET-Go’s released KPI implementation explicitly filters best_day from oneYearAgo, while this label and the linked documentation describe an unbounded record, so users can misinterpret the value and be surprised when it decreases as an old record ages out.
        "name": "Best day detections"
  • Files reviewed: 19/21 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Copilot AI review requested due to automatic review settings September 6, 2026 17:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The reviewed implementation and tests have no unresolved approval-blocking issues.

Review details
  • Files reviewed: 19/21 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants