From 067acce4deeb397717b6bb7f9ca3e5f0dab79c41 Mon Sep 17 00:00:00 2001 From: Jeef Date: Tue, 30 Jul 2024 15:42:10 -0600 Subject: [PATCH] Add SimpleFin sensor to show age of data (#122550) --- .../components/simplefin/manifest.json | 2 +- homeassistant/components/simplefin/sensor.py | 13 +- .../components/simplefin/strings.json | 3 + requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- .../simplefin/snapshots/test_sensor.ambr | 384 ++++++++++++++++++ 6 files changed, 401 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/simplefin/manifest.json b/homeassistant/components/simplefin/manifest.json index f3e312d9de5108..a790e64c57826e 100644 --- a/homeassistant/components/simplefin/manifest.json +++ b/homeassistant/components/simplefin/manifest.json @@ -7,5 +7,5 @@ "integration_type": "service", "iot_class": "cloud_polling", "loggers": ["simplefin"], - "requirements": ["simplefin4py==0.0.16"] + "requirements": ["simplefin4py==0.0.18"] } diff --git a/homeassistant/components/simplefin/sensor.py b/homeassistant/components/simplefin/sensor.py index 2fac42cbac5327..b2167a2c014cc0 100644 --- a/homeassistant/components/simplefin/sensor.py +++ b/homeassistant/components/simplefin/sensor.py @@ -4,6 +4,7 @@ from collections.abc import Callable from dataclasses import dataclass +from datetime import datetime from simplefin4py import Account @@ -13,6 +14,7 @@ SensorEntityDescription, SensorStateClass, ) +from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType @@ -25,7 +27,7 @@ class SimpleFinSensorEntityDescription(SensorEntityDescription): """Describes a sensor entity.""" - value_fn: Callable[[Account], StateType] + value_fn: Callable[[Account], StateType | datetime] icon_fn: Callable[[Account], str] | None = None unit_fn: Callable[[Account], str] | None = None @@ -40,6 +42,13 @@ class SimpleFinSensorEntityDescription(SensorEntityDescription): unit_fn=lambda account: account.currency, icon_fn=lambda account: account.inferred_account_type, ), + SimpleFinSensorEntityDescription( + key="age", + translation_key="age", + device_class=SensorDeviceClass.TIMESTAMP, + entity_category=EntityCategory.DIAGNOSTIC, + value_fn=lambda account: account.balance_date, + ), ) @@ -70,7 +79,7 @@ class SimpleFinSensor(SimpleFinEntity, SensorEntity): entity_description: SimpleFinSensorEntityDescription @property - def native_value(self) -> StateType: + def native_value(self) -> StateType | datetime | None: """Return the state.""" return self.entity_description.value_fn(self.account_data) diff --git a/homeassistant/components/simplefin/strings.json b/homeassistant/components/simplefin/strings.json index c54520a0451b4e..d6690e604c5602 100644 --- a/homeassistant/components/simplefin/strings.json +++ b/homeassistant/components/simplefin/strings.json @@ -24,6 +24,9 @@ "sensor": { "balance": { "name": "Balance" + }, + "age": { + "name": "Data age" } } } diff --git a/requirements_all.txt b/requirements_all.txt index c9e5ad7c2647a4..8389d5ed2cd87a 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2580,7 +2580,7 @@ sharp_aquos_rc==0.3.2 shodan==1.28.0 # homeassistant.components.simplefin -simplefin4py==0.0.16 +simplefin4py==0.0.18 # homeassistant.components.sighthound simplehound==0.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 33c1ebcdb09aa2..c5ad7e9da05702 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2032,7 +2032,7 @@ sfrbox-api==0.0.8 sharkiq==1.0.2 # homeassistant.components.simplefin -simplefin4py==0.0.16 +simplefin4py==0.0.18 # homeassistant.components.sighthound simplehound==0.3 diff --git a/tests/components/simplefin/snapshots/test_sensor.ambr b/tests/components/simplefin/snapshots/test_sensor.ambr index 2660bbd74ca025..c7dced9300e64b 100644 --- a/tests/components/simplefin/snapshots/test_sensor.ambr +++ b/tests/components/simplefin/snapshots/test_sensor.ambr @@ -52,6 +52,54 @@ 'state': '1000000.00', }) # --- +# name: test_all_entities[sensor.investments_dr_evil_data_age-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.investments_dr_evil_data_age', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Data age', + 'platform': 'simplefin', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'age', + 'unique_id': 'account_ACT-4k5l6m7n-8o9p-1q2r-3s4t_age', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[sensor.investments_dr_evil_data_age-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by SimpleFIN API', + 'device_class': 'timestamp', + 'friendly_name': 'Investments Dr Evil Data age', + }), + 'context': , + 'entity_id': 'sensor.investments_dr_evil_data_age', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2024-01-16T13:55:19+00:00', + }) +# --- # name: test_all_entities[sensor.investments_my_checking_balance-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ @@ -105,6 +153,54 @@ 'state': '12345.67', }) # --- +# name: test_all_entities[sensor.investments_my_checking_data_age-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.investments_my_checking_data_age', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Data age', + 'platform': 'simplefin', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'age', + 'unique_id': 'account_ACT-1k2l3m4n-5o6p-7q8r-9s0t_age', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[sensor.investments_my_checking_data_age-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by SimpleFIN API', + 'device_class': 'timestamp', + 'friendly_name': 'Investments My Checking Data age', + }), + 'context': , + 'entity_id': 'sensor.investments_my_checking_data_age', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2024-01-16T13:55:19+00:00', + }) +# --- # name: test_all_entities[sensor.investments_nerdcorp_series_b_balance-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ @@ -158,6 +254,54 @@ 'state': '13579.24', }) # --- +# name: test_all_entities[sensor.investments_nerdcorp_series_b_data_age-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.investments_nerdcorp_series_b_data_age', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Data age', + 'platform': 'simplefin', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'age', + 'unique_id': 'account_ACT-5k6l7m8n-9o0p-1q2r-3s4t_age', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[sensor.investments_nerdcorp_series_b_data_age-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by SimpleFIN API', + 'device_class': 'timestamp', + 'friendly_name': 'Investments NerdCorp Series B Data age', + }), + 'context': , + 'entity_id': 'sensor.investments_nerdcorp_series_b_data_age', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2024-01-16T13:55:19+00:00', + }) +# --- # name: test_all_entities[sensor.mythical_randomsavings_castle_mortgage_balance-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ @@ -211,6 +355,54 @@ 'state': '7500.00', }) # --- +# name: test_all_entities[sensor.mythical_randomsavings_castle_mortgage_data_age-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.mythical_randomsavings_castle_mortgage_data_age', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Data age', + 'platform': 'simplefin', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'age', + 'unique_id': 'account_ACT-7a8b9c0d-1e2f-3g4h-5i6j_age', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[sensor.mythical_randomsavings_castle_mortgage_data_age-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by SimpleFIN API', + 'device_class': 'timestamp', + 'friendly_name': 'Mythical RandomSavings Castle Mortgage Data age', + }), + 'context': , + 'entity_id': 'sensor.mythical_randomsavings_castle_mortgage_data_age', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2024-01-16T18:16:42+00:00', + }) +# --- # name: test_all_entities[sensor.mythical_randomsavings_unicorn_pot_balance-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ @@ -264,6 +456,54 @@ 'state': '10000.00', }) # --- +# name: test_all_entities[sensor.mythical_randomsavings_unicorn_pot_data_age-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.mythical_randomsavings_unicorn_pot_data_age', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Data age', + 'platform': 'simplefin', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'age', + 'unique_id': 'account_ACT-6a7b8c9d-0e1f-2g3h-4i5j_age', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[sensor.mythical_randomsavings_unicorn_pot_data_age-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by SimpleFIN API', + 'device_class': 'timestamp', + 'friendly_name': 'Mythical RandomSavings Unicorn Pot Data age', + }), + 'context': , + 'entity_id': 'sensor.mythical_randomsavings_unicorn_pot_data_age', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2024-01-16T18:16:42+00:00', + }) +# --- # name: test_all_entities[sensor.random_bank_costco_anywhere_visa_r_card_balance-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ @@ -317,6 +557,54 @@ 'state': '-532.69', }) # --- +# name: test_all_entities[sensor.random_bank_costco_anywhere_visa_r_card_data_age-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.random_bank_costco_anywhere_visa_r_card_data_age', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Data age', + 'platform': 'simplefin', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'age', + 'unique_id': 'account_ACT-3a4b5c6d-7e8f-9g0h-1i2j_age', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[sensor.random_bank_costco_anywhere_visa_r_card_data_age-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by SimpleFIN API', + 'device_class': 'timestamp', + 'friendly_name': 'Random Bank Costco Anywhere Visa® Card Data age', + }), + 'context': , + 'entity_id': 'sensor.random_bank_costco_anywhere_visa_r_card_data_age', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2024-01-16T18:16:42+00:00', + }) +# --- # name: test_all_entities[sensor.the_bank_of_go_prime_savings_balance-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ @@ -370,6 +658,54 @@ 'state': '9876.54', }) # --- +# name: test_all_entities[sensor.the_bank_of_go_prime_savings_data_age-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.the_bank_of_go_prime_savings_data_age', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Data age', + 'platform': 'simplefin', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'age', + 'unique_id': 'account_ACT-2a3b4c5d-6e7f-8g9h-0i1j_age', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[sensor.the_bank_of_go_prime_savings_data_age-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by SimpleFIN API', + 'device_class': 'timestamp', + 'friendly_name': 'The Bank of Go PRIME SAVINGS Data age', + }), + 'context': , + 'entity_id': 'sensor.the_bank_of_go_prime_savings_data_age', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2024-01-16T18:14:21+00:00', + }) +# --- # name: test_all_entities[sensor.the_bank_of_go_the_bank_balance-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ @@ -423,3 +759,51 @@ 'state': '7777.77', }) # --- +# name: test_all_entities[sensor.the_bank_of_go_the_bank_data_age-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.the_bank_of_go_the_bank_data_age', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Data age', + 'platform': 'simplefin', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'age', + 'unique_id': 'account_ACT-1a2b3c4d-5e6f-7g8h-9i0j_age', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[sensor.the_bank_of_go_the_bank_data_age-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by SimpleFIN API', + 'device_class': 'timestamp', + 'friendly_name': 'The Bank of Go The Bank Data age', + }), + 'context': , + 'entity_id': 'sensor.the_bank_of_go_the_bank_data_age', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2024-01-16T14:04:03+00:00', + }) +# ---