Add integration for my-PV devices#169872
Add integration for my-PV devices#169872rrooggiieerr wants to merge 14 commits intohome-assistant:devfrom
Conversation
There was a problem hiding this comment.
When adding new integrations, limit included platforms to a single platform. Please reduce this PR to a single platform. See the review process for more details.
This PR includes a brand folder inside the component. Brand assets should not be part of the core repository. Please refer to the brand images documentation for the correct approach.
|
Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍 |
There was a problem hiding this comment.
Pull request overview
This PR adds a new my_pv Home Assistant integration, including discovery/config-flow support, entity platforms, generated metadata, and initial config-flow tests. It fits into the integrations codebase as a new device integration with local and cloud connection modes.
Changes:
- Adds the new
homeassistant.components.my_pvintegration with config flow, coordinator, manifests, translations, and multiple entity platforms. - Registers the integration in generated discovery/config-flow metadata and dependency lists.
- Adds initial pytest coverage for config flow setup, discovery, and reauthentication paths.
Reviewed changes
Copilot reviewed 21 out of 33 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
homeassistant/components/my_pv/__init__.py |
Sets up config entries, device connection, coordinator, and platform forwarding. |
homeassistant/components/my_pv/binary_sensor.py |
Adds dynamic binary sensor entities from device data definitions. |
homeassistant/components/my_pv/button.py |
Adds dynamic command button entities. |
homeassistant/components/my_pv/config_flow.py |
Implements user, discovery, local/cloud auth, and reauth flows. |
homeassistant/components/my_pv/const.py |
Defines integration constants and entity metadata mappings. |
homeassistant/components/my_pv/coordinator.py |
Implements the polling coordinator and device info handling. |
homeassistant/components/my_pv/icons.json |
Adds icon mappings for selected entities. |
homeassistant/components/my_pv/manifest.json |
Declares integration metadata, requirements, and discovery handlers. |
homeassistant/components/my_pv/number.py |
Adds dynamic number entities for writable setup values. |
homeassistant/components/my_pv/quality_scale.yaml |
Declares claimed quality-scale rule status for the integration. |
homeassistant/components/my_pv/select.py |
Adds dynamic select entities for enumerated setup values. |
homeassistant/components/my_pv/sensor.py |
Adds dynamic sensors for device telemetry. |
homeassistant/components/my_pv/strings.json |
Adds config-flow, exception, device, and entity translations. |
homeassistant/components/my_pv/switch.py |
Adds dynamic switch entities for boolean setup values. |
homeassistant/components/my_pv/update.py |
Adds firmware update entity support. |
homeassistant/components/my_pv/water_heater.py |
Adds water-heater entity support for boiler control. |
homeassistant/generated/config_flows.py |
Registers my_pv as a config-flow integration. |
homeassistant/generated/dhcp.py |
Registers DHCP discovery matchers for my_pv. |
homeassistant/generated/integrations.json |
Adds generated integration metadata entry. |
homeassistant/generated/zeroconf.py |
Registers Zeroconf discovery for _mypv._tcp.local.. |
tests/components/my_pv/__init__.py |
Initializes the test package. |
tests/components/my_pv/conftest.py |
Adds shared config-entry fixtures for tests. |
tests/components/my_pv/test_config_flow.py |
Adds config flow tests for setup, discovery, and reauth. |
requirements_all.txt |
Adds the my-PV dependency to the aggregate requirements list. |
CODEOWNERS |
Adds code owners for the new integration and tests. |
| # If reauthenticating only the existing configuration needs to be updated with the | ||
| # new password. | ||
| if self._reauth_entry is not None: | ||
| return self.async_update_reload_and_abort( | ||
| self._reauth_entry, | ||
| data_updates={ | ||
| CONF_PASSWORD: password, | ||
| }, | ||
| ) |
| # If reauthenticating only the existing configuration needs to be updated with the | ||
| # new API token. | ||
| if self._reauth_entry is not None: | ||
| return self.async_update_reload_and_abort( | ||
| self._reauth_entry, | ||
| data_updates={ | ||
| CONF_TOKEN: api_token, | ||
| }, | ||
| ) |
| # If reauthenticating only the existing configuration needs to be updated with the | ||
| # new password. | ||
| if self._reauth_entry is not None: | ||
| return self.async_update_reload_and_abort( | ||
| self._reauth_entry, | ||
| data_updates={ | ||
| CONF_PASSWORD: password, | ||
| }, | ||
| ) | ||
|
|
||
| if errors: | ||
| # Combine user input with schema. | ||
| data_schema = self.add_suggested_values_to_schema( | ||
| self.LOCAL_AUTH_SCHEMA, user_input | ||
| ) | ||
| return self.async_show_form( | ||
| step_id="setup_local", | ||
| data_schema=data_schema, | ||
| errors=errors, | ||
| ) | ||
|
|
| if ( | ||
| self.entity_description.download_command | ||
| and await self.coordinator.send_command( | ||
| self.entity_description.download_command | ||
| ) | ||
| ): | ||
| self._attr_in_progress = True | ||
| self._attr_update_percentage = 0 | ||
|
|
||
| # At some time implement timeout | ||
| while True: | ||
| if self.update_percentage == 100: | ||
| break | ||
|
|
||
| await asyncio.sleep(1) | ||
|
|
||
| await self.coordinator.send_command(self.entity_description.install_command) |
| "data_description": { | ||
| "password": "Password" | ||
| }, | ||
| "description": "Password description goes here. Provide instructions with where to find the default password.", |
| "serial_number": "Serial number", | ||
| "token": "Cloud API token" | ||
| }, | ||
| "description": "setup_cloud description goes here. Provide instructions with where to find the serial number and how to obtain a Cloud API token.", |
| The backup parameter indicates a backup should be taken before | ||
| installing the update. | ||
| """ | ||
| _LOGGER.error("Updating %s", self.name) |
| elif key == "temp1" and not coordinator.supports_data("temp2"): | ||
| translation_key = "temp" |
| if self._reauth_entry is not None: | ||
| return self.async_update_reload_and_abort( | ||
| self._reauth_entry, | ||
| data_updates={ | ||
| CONF_PASSWORD: password, | ||
| }, | ||
| ) |
| self.LOCAL_AUTH_SCHEMA, user_input | ||
| ) | ||
| return self.async_show_form( | ||
| step_id="setup_local", |
| elif key == "temp1" and not coordinator.supports_data("temp2"): | ||
| translation_key = "temp" |
| self._attr_update_percentage = 0 | ||
|
|
||
| # At some time implement timeout | ||
| while True: | ||
| if self.update_percentage == 100: | ||
| break | ||
|
|
||
| await asyncio.sleep(1) |
| if ( | ||
| self.entity_description.download_command | ||
| and await self.coordinator.send_command( | ||
| self.entity_description.download_command | ||
| ) | ||
| ): | ||
| self._attr_in_progress = True | ||
| self._attr_update_percentage = 0 | ||
|
|
||
| # At some time implement timeout | ||
| while True: | ||
| if self.update_percentage == 100: | ||
| break | ||
|
|
||
| await asyncio.sleep(1) | ||
|
|
||
| await self.coordinator.send_command(self.entity_description.install_command) |
| "data_description": { | ||
| "password": "Password" | ||
| }, | ||
| "description": "Password description goes here. Provide instructions with where to find the default password.", |
| "serial_number": "Serial number", | ||
| "token": "Cloud API token" | ||
| }, | ||
| "description": "setup_cloud description goes here. Provide instructions with where to find the serial number and how to obtain a Cloud API token.", |
| discovery-update-info: | ||
| status: exempt | ||
| comment: Integration is cloud-based and does not use local discovery. | ||
| discovery: | ||
| status: exempt | ||
| comment: Integration requires manual authentication via cloud service. |
| appropriate-polling: | ||
| status: exempt | ||
| comment: Integration uses WebSocket push updates, not polling. |
Proposed change
Add an integration for my-PV devices
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: