8000 Add Gaposa integration by mwatson2 · Pull Request #138754 · home-assistant/core · GitHub
[go: up one dir, main page]

Skip to content

Add Gaposa integration #138754

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 17 commits into
base: dev
Choose a base branch
from
Draft

Add Gaposa integration #138754

wants to merge 17 commits into from

Conversation

mwatson2
Copy link
@mwatson2 mwatson2 commented Feb 18, 2025

Proposed change

This change introduces a new component for Gaposa blinds and shades (https://www.gaposa.it/eng). The component uses the cloud pull model, accessing the same server and API as the Gaposa RollApp mobile application (https://www.gaposa.it/eng/news/rollapp/). This cloud service communicates with the shades through their LinkIt hub (https://www.gaposa.it/eng/prod/?residential/electronics/control-units/home-automation/linkit).

The Gaposa blinds do not report position or battery level. The integration obtains position information from the cloud service. Motion status is inferred from elapsed time since last command and an assumed motion duration.

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

  • 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.

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 link to the changelog, or at minimum a diff between library versions is added to the PR description.

To help with the load of incoming pull requests:

Copy link
@home-assistant home-assistant bot left a comment

Choose a reason for hiding this comment

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

Hi @mwatson2

It seems you haven't yet signed a CLA. Please do so here.

Once you do that we will be able to review and accept this pull request.

Thanks!

@home-assistant
Copy link

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.

@mwatson2 mwatson2 marked this pull request as ready for review February 18, 2025 02:12
@thecode thecode changed the title Gaposa Add Gaposa integration Feb 18, 2025
Comment on lines 24 to 28
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Gaposa from a config entry."""

hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN].setdefault(entry.entry_id, {})
Copy link
Member

Choose a reason for hiding this comment

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

please extend the typing of ConfigEntry and store the data you would store in hass.data in entry.runtime_data

password = entry.data[CONF_PASSWORD]

try:
gaposa = Gaposa(api_key, loop=hass.loop, websession=websession)
Copy link
Member

Choose a reason for hiding this comment

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

why do we add the loop?

Comment on lines 1 to 19
rules:
action-setup: "done"
appropriate-polling: "done"
brands: "done"
common-modules: "done"
config-flow: "done"
config-flow-test-coverage: "done"
dependency-transparency: "done"
docs-actions: "done"
docs-high-level-description: "done"
docs-installation-instructions: "done"
docs-removal-instructions: "done"
entity-event-setup: "done"
entity-unique-id: "done"
has-entity-name: "done"
runtime-data: "done"
test-before-configure: "done"
test-before-setup: "done"
unique-config-entry: "done"
Copy link
Member

Choose a reason for hiding this comment

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

Please add the full yaml file

Comment on lines 44 to 52
coordinator = DataUpdateCoordinatorGaposa(
hass,
_LOGGER,
gaposa,
# Name of the data. For logging purposes.
name=entry.title,
# Polling interval. Will only be polled if there are subscribers.
update_interval=timedelta(seconds=UPDATE_INTERVAL),
)
Copy link
Member

Choose a reason for hiding this comment

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

Why isn't this in the coordinator.py?

Comment on lines +54 to +55
# Store runtime data that should persist between restarts
entry.async_on_unload(entry.add_update_listener(update_listener))
Copy link
Member

Choose a reason for hiding this comment

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

can be removed

Comment on lines +82 to +83
await self.async_set_unique_id(DOMAIN)
self._abort_if_unique_id_configured()
Copy link
Member

Choose a reason for hiding this comment

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

why do we set the domain as unique id?

Comment on lines 92 to 101
# The supported features of a cover are done using a bitmask. Using the constants
# imported above, we can tell HA the features that are supported by this entity.
# If the supported features were dynamic (ie: different depending on the external
# device it connected to), then this should be function with an @property decorator.
@property
def supported_features(self) -> CoverEntityFeature:
"""Return supported features."""
return (
CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE | CoverEntityFeature.STOP
)
Copy link
Member

Choose a reason for hiding this comment

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

This can be set to _attr_supported_features instead

Comment on lines 103 to 120
# Add device actions support
@property
def device_actions(self) -> list[dict[str, str]]:
"""Return the available actions for this cover."""
return [
{
"name": "Open",
"service": "cover.open_cover",
},
{
"name": "Close",
"service": "cover.close_cover",
},
{
"name": "Stop",
"service": "cover.stop_cover",
},
]
Copy link
Member

Choose a reason for hiding this comment

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

why?

Comment on lines 135 to 173
A93C
# A unique_id for this entity with in this domain. This means for example if you
# have a sensor on this cover, you must ensure the value returned is unique,
# which is done here by appending "_cover". For more information, see:
# https://developers.home-assistant.io/docs/entity_registry_index/#unique-id-requirements
# Note: This is NOT used to generate the user visible Entity ID used in automations.
self._attr_unique_id = self.id

# This is the name for this *entity*, the "name" attribute from "device_info"
# is used as the device name for device screens in the UI. This name is used on
# entity screens, and used to build the Entity ID that's used is automations etc.
self._attr_name = self.motor.name

async def async_will_remove_from_hass(self) -> None:
"""Entity being removed from hass."""
# The opposite of async_added_to_hass. Remove any registered call backs here.
await super().async_will_remove_from_hass()

# Information about the devices that is partially visible in the UI.
# The most critical thing here is to give this entity a name so it is displayed
# as a "device" in the HA UI. This name is used on the Devices overview table,
# and the initial screen when the device is added (rather than the entity name
# property below). You can then associate other Entities (eg: a battery
# sensor) with this device, so it shows more like a unified element in the UI.
# For example, an associated battery sensor will be displayed in the right most
# column in the Configuration > Devices view for a device.
# To associate an entity with this device, the device_info must also return an
# identical "identifiers" attribute, but not return a name attribute.
# See the sensors.py file for the corresponding example setup.
# Additional meta data can also be returned here, including sw_version (displayed
# as Firmware), model and manufacturer (displayed as <model> by <manufacturer>)
# shown on the device info screen. The Manufacturer and model also have their
# respective columns on the Devices overview table. Note: Many of these must be
# set when the device is first added, and they are not always automatically
# refreshed by HA from it's internal cache.
# For more information see:
# https://developers.home-assistant.io/docs/device_registry_index/#device-properties
@property
def device_info(self) -> DeviceInfo:
"""Information about this entity/device."""
Copy link
Member

Choose a reason for hiding this comment

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

Why do we have a whole paragraph here

Copy link
Member

Choose a reason for hiding this comment

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

Remove so we can add in a separate PR

@home-assistant home-assistant bot marked this pull request as draft March 16, 2025 21:59
mwatson2 and others added 3 commits March 31, 2025 03:06
Fixes an issue where the UI state of Gaposa covers wasn't properly updating after actions:
- When stop button is pressed, immediately request a refresh from the API and update UI
- After open/close actions, refresh API state before updating UI when motion completes
- Add tests to verify this behavior

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Fix context parameter in GaposaCover initialization
- Change log levels from INFO to DEBUG for routine operations
- Improve test handling of coroutines to avoid warnings
- Remove loop parameter from Gaposa API initialization
- Move API initialization to coordinator
- Use entry.runtime_data instead of hass.data for storing data
- Update quality_scale.yaml file
- Remove device_actions property as it's not needed
- Remove diagnostics.py for future PR
- Cleanup code by removing excessive comments
Copy link

There hasn't been any activity on this pull request recently. This pull request has been automatically marked as stale because of that and will be closed if no further activity occurs within 7 days.
If you are the author of this PR, please leave a comment if you want to keep it open. Also, please rebase your PR onto the latest dev branch to ensure that it's up to date with the latest changes.
Thank you for your contribution!

@github-actions github-actions bot added the stale label May 30, 2025
@mwatson2
Copy link
Author

Apologies for the lack of progress. I have push changes for the review comments, but unfortunately I have not had an opportunity to visit the property where my Gaposa blinds are installed in order to test with those changes. So the changes are not ready for review yet. I do expect to have that opportunity in the next month.

@github-actions github-actions bot removed the stale label May 30, 2025
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
0