Add SimpleFin sensor to show age of data (#122550)

This commit is contained in:
Jeef 2024-07-30 15:42:10 -06:00 committed by GitHub
parent 6999c6b0cf
commit 067acce4de
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 401 additions and 5 deletions

View File

@ -7,5 +7,5 @@
"integration_type": "service", "integration_type": "service",
"iot_class": "cloud_polling", "iot_class": "cloud_polling",
"loggers": ["simplefin"], "loggers": ["simplefin"],
"requirements": ["simplefin4py==0.0.16"] "requirements": ["simplefin4py==0.0.18"]
} }

View File

@ -4,6 +4,7 @@ from __future__ import annotations
from collections.abc import Callable from collections.abc import Callable
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime
from simplefin4py import Account from simplefin4py import Account
@ -13,6 +14,7 @@ from homeassistant.components.sensor import (
SensorEntityDescription, SensorEntityDescription,
SensorStateClass, SensorStateClass,
) )
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType from homeassistant.helpers.typing import StateType
@ -25,7 +27,7 @@ from .entity import SimpleFinEntity
class SimpleFinSensorEntityDescription(SensorEntityDescription): class SimpleFinSensorEntityDescription(SensorEntityDescription):
"""Describes a sensor entity.""" """Describes a sensor entity."""
value_fn: Callable[[Account], StateType] value_fn: Callable[[Account], StateType | datetime]
icon_fn: Callable[[Account], str] | None = None icon_fn: Callable[[Account], str] | None = None
unit_fn: Callable[[Account], str] | None = None unit_fn: Callable[[Account], str] | None = None
@ -40,6 +42,13 @@ SIMPLEFIN_SENSORS: tuple[SimpleFinSensorEntityDescription, ...] = (
unit_fn=lambda account: account.currency, unit_fn=lambda account: account.currency,
icon_fn=lambda account: account.inferred_account_type, 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 entity_description: SimpleFinSensorEntityDescription
@property @property
def native_value(self) -> StateType: def native_value(self) -> StateType | datetime | None:
"""Return the state.""" """Return the state."""
return self.entity_description.value_fn(self.account_data) return self.entity_description.value_fn(self.account_data)

View File

@ -24,6 +24,9 @@
"sensor": { "sensor": {
"balance": { "balance": {
"name": "Balance" "name": "Balance"
},
"age": {
"name": "Data age"
} }
} }
} }

View File

@ -2580,7 +2580,7 @@ sharp_aquos_rc==0.3.2
shodan==1.28.0 shodan==1.28.0
# homeassistant.components.simplefin # homeassistant.components.simplefin
simplefin4py==0.0.16 simplefin4py==0.0.18
# homeassistant.components.sighthound # homeassistant.components.sighthound
simplehound==0.3 simplehound==0.3

View File

@ -2032,7 +2032,7 @@ sfrbox-api==0.0.8
sharkiq==1.0.2 sharkiq==1.0.2
# homeassistant.components.simplefin # homeassistant.components.simplefin
simplefin4py==0.0.16 simplefin4py==0.0.18
# homeassistant.components.sighthound # homeassistant.components.sighthound
simplehound==0.3 simplehound==0.3

View File

@ -52,6 +52,54 @@
'state': '1000000.00', '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': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.investments_dr_evil_data_age',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
'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': <ANY>,
'entity_id': 'sensor.investments_dr_evil_data_age',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2024-01-16T13:55:19+00:00',
})
# ---
# name: test_all_entities[sensor.investments_my_checking_balance-entry] # name: test_all_entities[sensor.investments_my_checking_balance-entry]
EntityRegistryEntrySnapshot({ EntityRegistryEntrySnapshot({
'aliases': set({ 'aliases': set({
@ -105,6 +153,54 @@
'state': '12345.67', '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': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.investments_my_checking_data_age',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
'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': <ANY>,
'entity_id': 'sensor.investments_my_checking_data_age',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2024-01-16T13:55:19+00:00',
})
# ---
# name: test_all_entities[sensor.investments_nerdcorp_series_b_balance-entry] # name: test_all_entities[sensor.investments_nerdcorp_series_b_balance-entry]
EntityRegistryEntrySnapshot({ EntityRegistryEntrySnapshot({
'aliases': set({ 'aliases': set({
@ -158,6 +254,54 @@
'state': '13579.24', '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': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.investments_nerdcorp_series_b_data_age',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
'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': <ANY>,
'entity_id': 'sensor.investments_nerdcorp_series_b_data_age',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2024-01-16T13:55:19+00:00',
})
# ---
# name: test_all_entities[sensor.mythical_randomsavings_castle_mortgage_balance-entry] # name: test_all_entities[sensor.mythical_randomsavings_castle_mortgage_balance-entry]
EntityRegistryEntrySnapshot({ EntityRegistryEntrySnapshot({
'aliases': set({ 'aliases': set({
@ -211,6 +355,54 @@
'state': '7500.00', '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': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.mythical_randomsavings_castle_mortgage_data_age',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
'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': <ANY>,
'entity_id': 'sensor.mythical_randomsavings_castle_mortgage_data_age',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2024-01-16T18:16:42+00:00',
})
# ---
# name: test_all_entities[sensor.mythical_randomsavings_unicorn_pot_balance-entry] # name: test_all_entities[sensor.mythical_randomsavings_unicorn_pot_balance-entry]
EntityRegistryEntrySnapshot({ EntityRegistryEntrySnapshot({
'aliases': set({ 'aliases': set({
@ -264,6 +456,54 @@
'state': '10000.00', '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': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.mythical_randomsavings_unicorn_pot_data_age',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
'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': <ANY>,
'entity_id': 'sensor.mythical_randomsavings_unicorn_pot_data_age',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2024-01-16T18:16:42+00:00',
})
# ---
# name: test_all_entities[sensor.random_bank_costco_anywhere_visa_r_card_balance-entry] # name: test_all_entities[sensor.random_bank_costco_anywhere_visa_r_card_balance-entry]
EntityRegistryEntrySnapshot({ EntityRegistryEntrySnapshot({
'aliases': set({ 'aliases': set({
@ -317,6 +557,54 @@
'state': '-532.69', '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': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.random_bank_costco_anywhere_visa_r_card_data_age',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
'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': <ANY>,
'entity_id': 'sensor.random_bank_costco_anywhere_visa_r_card_data_age',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2024-01-16T18:16:42+00:00',
})
# ---
# name: test_all_entities[sensor.the_bank_of_go_prime_savings_balance-entry] # name: test_all_entities[sensor.the_bank_of_go_prime_savings_balance-entry]
EntityRegistryEntrySnapshot({ EntityRegistryEntrySnapshot({
'aliases': set({ 'aliases': set({
@ -370,6 +658,54 @@
'state': '9876.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': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.the_bank_of_go_prime_savings_data_age',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
'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': <ANY>,
'entity_id': 'sensor.the_bank_of_go_prime_savings_data_age',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2024-01-16T18:14:21+00:00',
})
# ---
# name: test_all_entities[sensor.the_bank_of_go_the_bank_balance-entry] # name: test_all_entities[sensor.the_bank_of_go_the_bank_balance-entry]
EntityRegistryEntrySnapshot({ EntityRegistryEntrySnapshot({
'aliases': set({ 'aliases': set({
@ -423,3 +759,51 @@
'state': '7777.77', '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': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.the_bank_of_go_the_bank_data_age',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
'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': <ANY>,
'entity_id': 'sensor.the_bank_of_go_the_bank_data_age',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2024-01-16T14:04:03+00:00',
})
# ---