-
-
Notifications
You must be signed in to change notification settings - Fork 37.8k
Add sensors to Google Drive #156167
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
Add sensors to Google Drive #156167
Changes from 4 commits
0773bb8
013c474
c46baf1
005ad44
f02f4df
880abda
eb0905a
9bb083e
9dd2f24
d537ca3
e75bbed
2b3887c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| """DataUpdateCoordinator for Google Drive.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from dataclasses import dataclass | ||
| import logging | ||
|
|
||
| from google_drive_api.exceptions import GoogleDriveApiError | ||
|
|
||
| from homeassistant.config_entries import ConfigEntry | ||
| from homeassistant.core import HomeAssistant | ||
| from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed | ||
|
|
||
| from .api import DriveClient, StorageQuotaData | ||
| from .const import DOMAIN, SCAN_INTERVAL | ||
|
|
||
| type GoogleDriveConfigEntry = ConfigEntry[GoogleDriveDataUpdateCoordinator] | ||
|
|
||
| _LOGGER = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| @dataclass | ||
| class GoogleDriveCoordinatorData: | ||
| """Class to hold coordinator data.""" | ||
|
|
||
| storage_quota: StorageQuotaData | ||
| email_address: str | ||
|
|
||
|
|
||
| class GoogleDriveDataUpdateCoordinator( | ||
| DataUpdateCoordinator[GoogleDriveCoordinatorData] | ||
| ): | ||
| """Class to manage fetching Google Drive data from single endpoint.""" | ||
|
|
||
| client: DriveClient | ||
| config_entry: GoogleDriveConfigEntry | ||
| _email_address: str | ||
| backup_folder_id: str | ||
|
|
||
| def __init__( | ||
| self, | ||
| hass: HomeAssistant, | ||
| *, | ||
| client: DriveClient, | ||
| backup_folder_id: str, | ||
| entry: GoogleDriveConfigEntry, | ||
| ) -> None: | ||
| """Initialize Google Drive data updater.""" | ||
| self.client = client | ||
| self.backup_folder_id = backup_folder_id | ||
|
|
||
| super().__init__( | ||
| hass, | ||
| _LOGGER, | ||
| config_entry=entry, | ||
| name=DOMAIN, | ||
| update_interval=SCAN_INTERVAL, | ||
| ) | ||
|
|
||
| async def _async_setup(self) -> None: | ||
| """Do initialization logic.""" | ||
| self._email_address = await self.client.async_get_email_address() | ||
|
|
||
| async def _async_update_data(self) -> GoogleDriveCoordinatorData: | ||
| """Fetch data from Google Drive.""" | ||
| try: | ||
| storage_quota = await self.client.async_get_storage_quota() | ||
| return GoogleDriveCoordinatorData( | ||
| storage_quota=storage_quota, | ||
| email_address=self._email_address, | ||
| ) | ||
|
mik-laj marked this conversation as resolved.
Outdated
|
||
| except GoogleDriveApiError as error: | ||
| raise UpdateFailed( | ||
| translation_domain=DOMAIN, | ||
| translation_key="invalid_response_google_drive_error", | ||
| translation_placeholders={"error": str(error)}, | ||
| ) from error | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| """Define the Google Drive entity.""" | ||
|
|
||
| from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo | ||
| from homeassistant.helpers.update_coordinator import CoordinatorEntity | ||
|
|
||
| from .const import DOMAIN, DRIVE_FOLDER_URL_PREFIX | ||
| from .coordinator import GoogleDriveDataUpdateCoordinator | ||
|
|
||
|
|
||
| class GoogleDriveEntity(CoordinatorEntity[GoogleDriveDataUpdateCoordinator]): | ||
| """Defines a base Google Drive entity.""" | ||
|
|
||
| _attr_has_entity_name = True | ||
|
|
||
| @property | ||
| def device_info(self) -> DeviceInfo: | ||
| """Return device information about this Google Drive device.""" | ||
| return DeviceInfo( | ||
| identifiers={(DOMAIN, str(self.coordinator.config_entry.unique_id))}, | ||
| name=self.coordinator.data.email_address, | ||
| manufacturer="Google", | ||
| model="Google Drive", | ||
| configuration_url=f"{DRIVE_FOLDER_URL_PREFIX}{self.coordinator.backup_folder_id}", | ||
| entry_type=DeviceEntryType.SERVICE, | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| { | ||
| "entity": { | ||
| "sensor": { | ||
| "storage_total": { | ||
| "default": "mdi:database" | ||
| }, | ||
| "storage_used": { | ||
| "default": "mdi:database" | ||
| }, | ||
| "storage_used_in_drive": { | ||
| "default": "mdi:database" | ||
| }, | ||
| "storage_used_in_drive_trash": { | ||
| "default": "mdi:database" | ||
| } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,9 +3,7 @@ rules: | |
| action-setup: | ||
| status: exempt | ||
| comment: No actions. | ||
| appropriate-polling: | ||
| status: exempt | ||
| comment: No polling. | ||
| appropriate-polling: done | ||
| brands: done | ||
| common-modules: done | ||
| config-flow-test-coverage: done | ||
|
|
@@ -17,12 +15,8 @@ rules: | |
| docs-high-level-description: done | ||
| docs-installation-instructions: done | ||
| docs-removal-instructions: done | ||
| entity-event-setup: | ||
| status: exempt | ||
| comment: No entities. | ||
| entity-unique-id: | ||
| status: exempt | ||
| comment: No entities. | ||
| entity-event-setup: done | ||
| entity-unique-id: done | ||
| has-entity-name: | ||
| status: exempt | ||
| comment: No entities. | ||
|
|
@@ -38,39 +32,24 @@ rules: | |
| status: exempt | ||
| comment: No configuration options. | ||
| docs-installation-parameters: done | ||
| entity-unavailable: | ||
| status: exempt | ||
| comment: No entities. | ||
| entity-unavailable: done | ||
| integration-owner: done | ||
| log-when-unavailable: | ||
| status: exempt | ||
| comment: No entities. | ||
| parallel-updates: | ||
| status: exempt | ||
| comment: No actions and no entities. | ||
| log-when-unavailable: done | ||
| parallel-updates: done | ||
| reauthentication-flow: done | ||
| test-coverage: done | ||
|
|
||
| # Gold | ||
| devices: | ||
| status: exempt | ||
| comment: No devices. | ||
| diagnostics: | ||
| status: exempt | ||
| comment: No data to diagnose. | ||
| devices: done | ||
| diagnostics: todo | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To avoid downgrading the quality scale, can you add diagnostics? We could make an exception adding 2 platforms. Or you could add an empty diagnostics in a separate PR that we can merge first.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added diagnostics in this PR. |
||
| discovery-update-info: | ||
| status: exempt | ||
| comment: No discovery. | ||
| discovery: | ||
| status: exempt | ||
| comment: No discovery. | ||
| docs-data-update: | ||
| status: exempt | ||
| comment: No updates. | ||
| docs-examples: | ||
| status: exempt | ||
| comment: | | ||
| This integration only serves backup. | ||
| docs-data-update: done | ||
| docs-examples: done | ||
| docs-known-limitations: done | ||
| docs-supported-devices: | ||
| status: exempt | ||
|
|
@@ -79,20 +58,13 @@ rules: | |
| docs-troubleshooting: done | ||
| docs-use-cases: done | ||
| dynamic-devices: | ||
| status: exempt | ||
| comment: No devices. | ||
| entity-category: | ||
| status: exempt | ||
| comment: No entities. | ||
| entity-device-class: | ||
| status: exempt | ||
| comment: No entities. | ||
| entity-disabled-by-default: | ||
| status: exempt | ||
| comment: No entities. | ||
| entity-translations: | ||
| status: exempt | ||
| comment: No entities. | ||
| status: done | ||
| comment: | | ||
| This integration has a fixed single service. | ||
| entity-category: done | ||
| entity-device-class: done | ||
| entity-disabled-by-default: done | ||
| entity-translations: done | ||
| exception-translations: done | ||
| icon-translations: | ||
| status: exempt | ||
|
|
@@ -104,8 +76,9 @@ rules: | |
| status: exempt | ||
| comment: No repairs. | ||
| stale-devices: | ||
| status: exempt | ||
| comment: No devices. | ||
| status: done | ||
| comment: | | ||
| This integration has a fixed single service. | ||
|
|
||
| # Platinum | ||
| async-dependency: done | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems too frequent. The sensors are only expected to be updated after a backup (typically daily or weekly) or after a manual delete (uncommon). How about going with every few hours? In an earlier commit you had every 6h which seems more reasonable. Whoever wants more frequent can call the homeassistant.update_entity action.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This Google Drive account may not be only used to store HA backups. Other interactions are likely to happen more frequently and should be taken into account.
As long as we're not running into rate-limiting issues I'd say a 5 minute interval is fine. (Or at the very least keep the default more often than hourly).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find a 5 minute interval too excessive. Sure other uploads outside HA could increase your quota usage but do regular users care to track it within minutes? The example in the docs notifies you when you are low on storage. Every few hours is more than enough. Whoever wants more frequently can call
homeassistant.update_entityin an automation.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're merely sharing opinion, which is fine, but other users may not share the same view. If rate limits are not an issue on the API call having an extremely low polling rate should not be chosen.
Requiring users to take convoluted steps of implementing an automation to trigger polling at a different rate for any integration where no sensible default was chosen is just the wrong way of going about this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We generally avoid aggressive polling intervals (like 5 minutes) for data that is not critical for immediate, real-time automation (such as a motion sensor or light switch). Storage quota is a "slow-moving" metric.
The homeassistant.update_entity action is the documented, standard mechanism for the minority of users who require non-standard polling frequencies; it is not a workaround. See e.g. https://www.home-assistant.io/integrations/speedtestdotnet/
@mik-laj Please update the interval to proceed. The shortest I'd accept is 1h.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Six hours sounds good to me. Most users perform one backup per day, so if someone monitors free space to perform backups, everything will work because we'll have notifications four times more often than backups are performed.
This integration does not have services that allow us to create files on Google, so we do not have to worry about other changes on Google Drive.
If someone wants to monitor disk space, they can manually refresh the sensor, but I also don't think that's a common use case to justify changing the interval for all users. The main purpose of this integration is to provide backups, and for that use case, 6 hours is adequate.