Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for Coinbase sensors."""
2 
3 from __future__ import annotations
4 
5 import logging
6 
7 from homeassistant.components.sensor import SensorEntity, SensorStateClass
8 from homeassistant.config_entries import ConfigEntry
9 from homeassistant.core import HomeAssistant
10 from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
11 from homeassistant.helpers.entity_platform import AddEntitiesCallback
12 
13 from . import CoinbaseData
14 from .const import (
15  ACCOUNT_IS_VAULT,
16  API_ACCOUNT_AMOUNT,
17  API_ACCOUNT_CURRENCY,
18  API_ACCOUNT_ID,
19  API_ACCOUNT_NAME,
20  API_RATES,
21  CONF_CURRENCIES,
22  CONF_EXCHANGE_PRECISION,
23  CONF_EXCHANGE_PRECISION_DEFAULT,
24  CONF_EXCHANGE_RATES,
25  DOMAIN,
26 )
27 
28 _LOGGER = logging.getLogger(__name__)
29 
30 ATTR_NATIVE_BALANCE = "Balance in native currency"
31 ATTR_API_VERSION = "API Version"
32 
33 CURRENCY_ICONS = {
34  "BTC": "mdi:currency-btc",
35  "ETH": "mdi:currency-eth",
36  "EUR": "mdi:currency-eur",
37  "LTC": "mdi:litecoin",
38  "USD": "mdi:currency-usd",
39 }
40 
41 DEFAULT_COIN_ICON = "mdi:cash"
42 
43 ATTRIBUTION = "Data provided by coinbase.com"
44 
45 
47  hass: HomeAssistant,
48  config_entry: ConfigEntry,
49  async_add_entities: AddEntitiesCallback,
50 ) -> None:
51  """Set up Coinbase sensor platform."""
52  instance: CoinbaseData = hass.data[DOMAIN][config_entry.entry_id]
53 
54  entities: list[SensorEntity] = []
55 
56  provided_currencies: list[str] = [
57  account[API_ACCOUNT_CURRENCY]
58  for account in instance.accounts
59  if not account[ACCOUNT_IS_VAULT]
60  ]
61 
62  desired_currencies: list[str] = []
63 
64  if CONF_CURRENCIES in config_entry.options:
65  desired_currencies = config_entry.options[CONF_CURRENCIES]
66 
67  exchange_base_currency: str = instance.exchange_rates[API_ACCOUNT_CURRENCY]
68 
69  exchange_precision: int = config_entry.options.get(
70  CONF_EXCHANGE_PRECISION, CONF_EXCHANGE_PRECISION_DEFAULT
71  )
72 
73  for currency in desired_currencies:
74  _LOGGER.debug(
75  "Attempting to set up %s account sensor with %s API",
76  currency,
77  instance.api_version,
78  )
79  if currency not in provided_currencies:
80  _LOGGER.warning(
81  (
82  "The currency %s is no longer provided by your account, please"
83  " check your settings in Coinbase's developer tools"
84  ),
85  currency,
86  )
87  continue
88  entities.append(AccountSensor(instance, currency))
89 
90  if CONF_EXCHANGE_RATES in config_entry.options:
91  for rate in config_entry.options[CONF_EXCHANGE_RATES]:
92  _LOGGER.debug(
93  "Attempting to set up %s account sensor with %s API",
94  rate,
95  instance.api_version,
96  )
97  entities.append(
99  instance, rate, exchange_base_currency, exchange_precision
100  )
101  )
102 
103  async_add_entities(entities)
104 
105 
107  """Representation of a Coinbase.com sensor."""
108 
109  _attr_attribution = ATTRIBUTION
110 
111  def __init__(self, coinbase_data: CoinbaseData, currency: str) -> None:
112  """Initialize the sensor."""
113  self._coinbase_data_coinbase_data = coinbase_data
114  self._currency_currency = currency
115  for account in coinbase_data.accounts:
116  if account[API_ACCOUNT_CURRENCY] != currency or account[ACCOUNT_IS_VAULT]:
117  continue
118  self._attr_name_attr_name = f"Coinbase {account[API_ACCOUNT_NAME]}"
119  self._attr_unique_id_attr_unique_id = (
120  f"coinbase-{account[API_ACCOUNT_ID]}-wallet-"
121  f"{account[API_ACCOUNT_CURRENCY]}"
122  )
123  self._attr_native_value_attr_native_value = account[API_ACCOUNT_AMOUNT]
124  self._attr_native_unit_of_measurement_attr_native_unit_of_measurement = account[API_ACCOUNT_CURRENCY]
125  self._attr_icon_attr_icon = CURRENCY_ICONS.get(
126  account[API_ACCOUNT_CURRENCY],
127  DEFAULT_COIN_ICON,
128  )
129  self._native_balance_native_balance = round(
130  float(account[API_ACCOUNT_AMOUNT])
131  / float(coinbase_data.exchange_rates[API_RATES][currency]),
132  2,
133  )
134  break
135 
136  self._attr_state_class_attr_state_class = SensorStateClass.TOTAL
137  self._attr_device_info_attr_device_info = DeviceInfo(
138  configuration_url="https://www.coinbase.com/settings/api",
139  entry_type=DeviceEntryType.SERVICE,
140  identifiers={(DOMAIN, self._coinbase_data_coinbase_data.user_id)},
141  manufacturer="Coinbase.com",
142  name=f"Coinbase {self._coinbase_data.user_id[-4:]}",
143  )
144 
145  @property
146  def extra_state_attributes(self) -> dict[str, str]:
147  """Return the state attributes of the sensor."""
148  return {
149  ATTR_NATIVE_BALANCE: f"{self._native_balance} {self._coinbase_data.exchange_base}",
150  ATTR_API_VERSION: self._coinbase_data_coinbase_data.api_version,
151  }
152 
153  def update(self) -> None:
154  """Get the latest state of the sensor."""
155  _LOGGER.debug(
156  "Updating %s account sensor with %s API",
157  self._currency_currency,
158  self._coinbase_data_coinbase_data.api_version,
159  )
160  self._coinbase_data_coinbase_data.update()
161  for account in self._coinbase_data_coinbase_data.accounts:
162  if (
163  account[API_ACCOUNT_CURRENCY] != self._currency_currency
164  or account[ACCOUNT_IS_VAULT]
165  ):
166  continue
167  self._attr_native_value_attr_native_value = account[API_ACCOUNT_AMOUNT]
168  self._native_balance_native_balance = round(
169  float(account[API_ACCOUNT_AMOUNT])
170  / float(self._coinbase_data_coinbase_data.exchange_rates[API_RATES][self._currency_currency]),
171  2,
172  )
173  break
174 
175 
177  """Representation of a Coinbase.com sensor."""
178 
179  _attr_attribution = ATTRIBUTION
180 
181  def __init__(
182  self,
183  coinbase_data: CoinbaseData,
184  exchange_currency: str,
185  exchange_base: str,
186  precision: int,
187  ) -> None:
188  """Initialize the sensor."""
189  self._coinbase_data_coinbase_data = coinbase_data
190  self._currency_currency = exchange_currency
191  self._attr_name_attr_name = f"{exchange_currency} Exchange Rate"
192  self._attr_unique_id_attr_unique_id = (
193  f"coinbase-{coinbase_data.user_id}-xe-{exchange_currency}"
194  )
195  self._precision_precision = precision
196  self._attr_icon_attr_icon = CURRENCY_ICONS.get(exchange_currency, DEFAULT_COIN_ICON)
197  self._attr_native_value_attr_native_value = round(
198  1 / float(coinbase_data.exchange_rates[API_RATES][exchange_currency]),
199  precision,
200  )
201  self._attr_native_unit_of_measurement_attr_native_unit_of_measurement = exchange_base
202  self._attr_state_class_attr_state_class = SensorStateClass.MEASUREMENT
203  self._attr_device_info_attr_device_info = DeviceInfo(
204  configuration_url="https://www.coinbase.com/settings/api",
205  entry_type=DeviceEntryType.SERVICE,
206  identifiers={(DOMAIN, self._coinbase_data_coinbase_data.user_id)},
207  manufacturer="Coinbase.com",
208  name=f"Coinbase {self._coinbase_data.user_id[-4:]}",
209  )
210 
211  def update(self) -> None:
212  """Get the latest state of the sensor."""
213  _LOGGER.debug(
214  "Updating %s rate sensor with %s API",
215  self._currency_currency,
216  self._coinbase_data_coinbase_data.api_version,
217  )
218  self._coinbase_data_coinbase_data.update()
219  self._attr_native_value_attr_native_value = round(
220  1 / float(self._coinbase_data_coinbase_data.exchange_rates[API_RATES][self._currency_currency]),
221  self._precision_precision,
222  )
None __init__(self, CoinbaseData coinbase_data, str currency)
Definition: sensor.py:111
None __init__(self, CoinbaseData coinbase_data, str exchange_currency, str exchange_base, int precision)
Definition: sensor.py:187
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:50