Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Bitcoin information service that uses blockchain.com."""
2 
3 from __future__ import annotations
4 
5 from datetime import timedelta
6 import logging
7 
8 from blockchain import exchangerates, statistics
9 import voluptuous as vol
10 
12  PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
13  SensorEntity,
14  SensorEntityDescription,
15 )
16 from homeassistant.const import CONF_CURRENCY, CONF_DISPLAY_OPTIONS, UnitOfTime
17 from homeassistant.core import HomeAssistant
19 from homeassistant.helpers.entity_platform import AddEntitiesCallback
20 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
21 
22 _LOGGER = logging.getLogger(__name__)
23 
24 DEFAULT_CURRENCY = "USD"
25 
26 SCAN_INTERVAL = timedelta(minutes=5)
27 
28 SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
30  key="exchangerate",
31  name="Exchange rate (1 BTC)",
32  ),
34  key="trade_volume_btc",
35  name="Trade volume",
36  native_unit_of_measurement="BTC",
37  ),
39  key="miners_revenue_usd",
40  name="Miners revenue",
41  native_unit_of_measurement="USD",
42  ),
44  key="btc_mined",
45  name="Mined",
46  native_unit_of_measurement="BTC",
47  ),
49  key="trade_volume_usd",
50  name="Trade volume",
51  native_unit_of_measurement="USD",
52  ),
54  key="difficulty",
55  name="Difficulty",
56  ),
58  key="minutes_between_blocks",
59  name="Time between Blocks",
60  native_unit_of_measurement=UnitOfTime.MINUTES,
61  ),
63  key="number_of_transactions",
64  name="No. of Transactions",
65  ),
67  key="hash_rate",
68  name="Hash rate",
69  native_unit_of_measurement=f"PH/{UnitOfTime.SECONDS}",
70  ),
72  key="timestamp",
73  name="Timestamp",
74  ),
76  key="mined_blocks",
77  name="Mined Blocks",
78  ),
80  key="blocks_size",
81  name="Block size",
82  ),
84  key="total_fees_btc",
85  name="Total fees",
86  native_unit_of_measurement="BTC",
87  ),
89  key="total_btc_sent",
90  name="Total sent",
91  native_unit_of_measurement="BTC",
92  ),
94  key="estimated_btc_sent",
95  name="Estimated sent",
96  native_unit_of_measurement="BTC",
97  ),
99  key="total_btc",
100  name="Total",
101  native_unit_of_measurement="BTC",
102  ),
104  key="total_blocks",
105  name="Total Blocks",
106  ),
108  key="next_retarget",
109  name="Next retarget",
110  ),
112  key="estimated_transaction_volume_usd",
113  name="Est. Transaction volume",
114  native_unit_of_measurement="USD",
115  ),
117  key="miners_revenue_btc",
118  name="Miners revenue",
119  native_unit_of_measurement="BTC",
120  ),
122  key="market_price_usd",
123  name="Market price",
124  native_unit_of_measurement="USD",
125  ),
126 )
127 
128 OPTION_KEYS = [desc.key for desc in SENSOR_TYPES]
129 
130 PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
131  {
132  vol.Required(CONF_DISPLAY_OPTIONS, default=[]): vol.All(
133  cv.ensure_list, [vol.In(OPTION_KEYS)]
134  ),
135  vol.Optional(CONF_CURRENCY, default=DEFAULT_CURRENCY): cv.string,
136  }
137 )
138 
139 
141  hass: HomeAssistant,
142  config: ConfigType,
143  add_entities: AddEntitiesCallback,
144  discovery_info: DiscoveryInfoType | None = None,
145 ) -> None:
146  """Set up the Bitcoin sensors."""
147 
148  currency = config[CONF_CURRENCY]
149 
150  if currency not in exchangerates.get_ticker():
151  _LOGGER.warning("Currency %s is not available. Using USD", currency)
152  currency = DEFAULT_CURRENCY
153 
154  data = BitcoinData()
155  entities = [
156  BitcoinSensor(data, currency, description)
157  for description in SENSOR_TYPES
158  if description.key in config[CONF_DISPLAY_OPTIONS]
159  ]
160 
161  add_entities(entities, True)
162 
163 
165  """Representation of a Bitcoin sensor."""
166 
167  _attr_attribution = "Data provided by blockchain.com"
168  _attr_icon = "mdi:currency-btc"
169 
170  def __init__(
171  self, data: BitcoinData, currency: str, description: SensorEntityDescription
172  ) -> None:
173  """Initialize the sensor."""
174  self.entity_descriptionentity_description = description
175  self.datadata = data
176  self._currency_currency = currency
177 
178  def update(self) -> None:
179  """Get the latest data and updates the states."""
180  self.datadata.update()
181  stats = self.datadata.stats
182  ticker = self.datadata.ticker
183 
184  sensor_type = self.entity_descriptionentity_description.key
185  if sensor_type == "exchangerate":
186  self._attr_native_value_attr_native_value = ticker[self._currency_currency].p15min
187  self._attr_native_unit_of_measurement_attr_native_unit_of_measurement = self._currency_currency
188  elif sensor_type == "trade_volume_btc":
189  self._attr_native_value_attr_native_value = f"{stats.trade_volume_btc:.1f}"
190  elif sensor_type == "miners_revenue_usd":
191  self._attr_native_value_attr_native_value = f"{stats.miners_revenue_usd:.0f}"
192  elif sensor_type == "btc_mined":
193  self._attr_native_value_attr_native_value = str(stats.btc_mined * 0.00000001)
194  elif sensor_type == "trade_volume_usd":
195  self._attr_native_value_attr_native_value = f"{stats.trade_volume_usd:.1f}"
196  elif sensor_type == "difficulty":
197  self._attr_native_value_attr_native_value = f"{stats.difficulty:.0f}"
198  elif sensor_type == "minutes_between_blocks":
199  self._attr_native_value_attr_native_value = f"{stats.minutes_between_blocks:.2f}"
200  elif sensor_type == "number_of_transactions":
201  self._attr_native_value_attr_native_value = str(stats.number_of_transactions)
202  elif sensor_type == "hash_rate":
203  self._attr_native_value_attr_native_value = f"{stats.hash_rate * 0.000001:.1f}"
204  elif sensor_type == "timestamp":
205  self._attr_native_value_attr_native_value = stats.timestamp
206  elif sensor_type == "mined_blocks":
207  self._attr_native_value_attr_native_value = str(stats.mined_blocks)
208  elif sensor_type == "blocks_size":
209  self._attr_native_value_attr_native_value = f"{stats.blocks_size:.1f}"
210  elif sensor_type == "total_fees_btc":
211  self._attr_native_value_attr_native_value = f"{stats.total_fees_btc * 0.00000001:.2f}"
212  elif sensor_type == "total_btc_sent":
213  self._attr_native_value_attr_native_value = f"{stats.total_btc_sent * 0.00000001:.2f}"
214  elif sensor_type == "estimated_btc_sent":
215  self._attr_native_value_attr_native_value = f"{stats.estimated_btc_sent * 0.00000001:.2f}"
216  elif sensor_type == "total_btc":
217  self._attr_native_value_attr_native_value = f"{stats.total_btc * 0.00000001:.2f}"
218  elif sensor_type == "total_blocks":
219  self._attr_native_value_attr_native_value = f"{stats.total_blocks:.0f}"
220  elif sensor_type == "next_retarget":
221  self._attr_native_value_attr_native_value = f"{stats.next_retarget:.2f}"
222  elif sensor_type == "estimated_transaction_volume_usd":
223  self._attr_native_value_attr_native_value = f"{stats.estimated_transaction_volume_usd:.2f}"
224  elif sensor_type == "miners_revenue_btc":
225  self._attr_native_value_attr_native_value = f"{stats.miners_revenue_btc * 0.00000001:.1f}"
226  elif sensor_type == "market_price_usd":
227  self._attr_native_value_attr_native_value = f"{stats.market_price_usd:.2f}"
228 
229 
231  """Get the latest data and update the states."""
232 
233  stats: statistics.Stats
234  ticker: dict[str, exchangerates.Currency]
235 
236  def update(self) -> None:
237  """Get the latest data from blockchain.com."""
238 
239  self.statsstats = statistics.get()
240  self.tickerticker = exchangerates.get_ticker()
None __init__(self, BitcoinData data, str currency, SensorEntityDescription description)
Definition: sensor.py:172
None setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback add_entities, DiscoveryInfoType|None discovery_info=None)
Definition: sensor.py:145
def add_entities(account, async_add_entities, tracked)
Definition: sensor.py:40