New integation: BirdNET-Go - #181457
Conversation
There was a problem hiding this comment.
🟡 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 underTN-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.
There was a problem hiding this comment.
🟡 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
aiobirdnetgoturns 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 underTN-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
There was a problem hiding this comment.
🟡 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_KEYor verifies that it is persisted and passed toBirdNetGoClientduring both validation and entry setup, leaving this user-facing authentication path uncovered despiteconfig-flow-test-coveragebeing marked done.
homeassistant/components/birdnet_go/config_flow.py:92
- Preserve or reject URL base paths consistently before saving the entry.
BirdNetGoClientparses the/api/portion of the tested full URL asbase_pathduring validation, but replacingCONF_HOSTwithclient.hostdiscards 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
There was a problem hiding this comment.
🟡 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_INCREASINGfor this daily-resetting counter. WithTOTAL, the midnight reset is recorded as a large negative change in long-term statistics;TOTAL_INCREASINGtreats the decrease as a new meter cycle.
homeassistant/components/birdnet_go/config_flow.py:76
- Require all four sensor fields in
aiobirdnetgobefore treating this probe as successful. Version 0.1.3 only requirestoday_detectionsandlifetime_species; missingbest_dayordetection_streakdata 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
There was a problem hiding this comment.
🟡 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_autherror 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
aiobirdnetgo0.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
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 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. RaiseUpdateFailedhere so polling can recover, and update the setup test accordingly.
- Files reviewed: 20/22 changed files
- Comments generated: 0 new
- Review effort level: Balanced
There was a problem hiding this comment.
🔵 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
There was a problem hiding this comment.
🔵 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
ConfigEntryAuthFailedfor authentication failures instead of retrying them. Wrapping a 401/403 inUpdateFailedmakes the first refresh enterSETUP_RETRYand keeps a loaded entry polling every 30 seconds even though authentication is unsupported; the coordinator only stops polling and starts reauthentication forConfigEntryAuthFailed(homeassistant/helpers/update_coordinator.py:538-586).
- Files reviewed: 20/22 changed files
- Comments generated: 0 new
- Review effort level: Balanced
There was a problem hiding this comment.
🔵 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_SCHEMAalways 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::1and2001:0db8:0:0:0:0:0:1produce different IDs and let the same station be configured twice, despiteunique-config-entrybeing marked done. Please normalize the host inaiobirdnetgo(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 constructsmock_healthand configuresping,get_ping, andget_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
There was a problem hiding this comment.
🟡 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; catchBirdNetGoResponseErrorfirst, inspectstatus_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.
TOTALgenerates 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.5accepts 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
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 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.MEASUREMENTfor the best-day record. This value is a historical maximum rather than an accumulated total, soTOTALproduces misleading recorder sum statistics when the record changes; comparable maximum sensors such asambient_station/sensor.py:403-407useMEASUREMENT.
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/kpisis 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_dayfromoneYearAgo, 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
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:
Type of change
Additional information
Checklist
ruff format homeassistant tests)If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest.requirements_all.txt.Updated by running
python3 -m script.gen_requirements_all.To help with the load of incoming pull requests: