Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for Bbox Bouygues Modem Router."""
2 
3 from __future__ import annotations
4 
5 from datetime import timedelta
6 import logging
7 
8 import pybbox
9 import requests
10 import voluptuous as vol
11 
13  PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
14  SensorDeviceClass,
15  SensorEntity,
16  SensorEntityDescription,
17  SensorStateClass,
18 )
19 from homeassistant.const import CONF_MONITORED_VARIABLES, CONF_NAME, UnitOfDataRate
20 from homeassistant.core import HomeAssistant
22 from homeassistant.helpers.entity_platform import AddEntitiesCallback
23 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
24 from homeassistant.util import Throttle
25 from homeassistant.util.dt import utcnow
26 
27 _LOGGER = logging.getLogger(__name__)
28 
29 ATTRIBUTION = "Powered by Bouygues Telecom"
30 
31 DEFAULT_NAME = "Bbox"
32 
33 MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60)
34 
35 SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
37  key="down_max_bandwidth",
38  name="Maximum Download Bandwidth",
39  device_class=SensorDeviceClass.DATA_RATE,
40  native_unit_of_measurement=UnitOfDataRate.MEGABITS_PER_SECOND,
41  icon="mdi:download",
42  ),
44  key="up_max_bandwidth",
45  name="Maximum Upload Bandwidth",
46  device_class=SensorDeviceClass.DATA_RATE,
47  native_unit_of_measurement=UnitOfDataRate.MEGABITS_PER_SECOND,
48  icon="mdi:upload",
49  ),
51  key="current_down_bandwidth",
52  name="Currently Used Download Bandwidth",
53  device_class=SensorDeviceClass.DATA_RATE,
54  native_unit_of_measurement=UnitOfDataRate.MEGABITS_PER_SECOND,
55  state_class=SensorStateClass.MEASUREMENT,
56  icon="mdi:download",
57  ),
59  key="current_up_bandwidth",
60  name="Currently Used Upload Bandwidth",
61  device_class=SensorDeviceClass.DATA_RATE,
62  native_unit_of_measurement=UnitOfDataRate.MEGABITS_PER_SECOND,
63  state_class=SensorStateClass.MEASUREMENT,
64  icon="mdi:upload",
65  ),
67  key="number_of_reboots",
68  name="Number of reboot",
69  icon="mdi:restart",
70  ),
71 )
72 
73 SENSOR_TYPES_UPTIME: tuple[SensorEntityDescription, ...] = (
75  key="uptime",
76  name="Uptime",
77  icon="mdi:clock",
78  ),
79 )
80 
81 SENSOR_KEYS: list[str] = [desc.key for desc in (*SENSOR_TYPES, *SENSOR_TYPES_UPTIME)]
82 
83 PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
84  {
85  vol.Required(CONF_MONITORED_VARIABLES): vol.All(
86  cv.ensure_list, [vol.In(SENSOR_KEYS)]
87  ),
88  vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
89  }
90 )
91 
92 
94  hass: HomeAssistant,
95  config: ConfigType,
96  add_entities: AddEntitiesCallback,
97  discovery_info: DiscoveryInfoType | None = None,
98 ) -> None:
99  """Set up the Bbox sensor."""
100  # Create a data fetcher to support all of the configured sensors. Then make
101  # the first call to init the data.
102  try:
103  bbox_data = BboxData()
104  bbox_data.update()
105  except requests.exceptions.HTTPError as error:
106  _LOGGER.error(error)
107  return
108 
109  name = config[CONF_NAME]
110 
111  monitored_variables = config[CONF_MONITORED_VARIABLES]
112  entities: list[BboxSensor | BboxUptimeSensor] = [
113  BboxSensor(bbox_data, name, description)
114  for description in SENSOR_TYPES
115  if description.key in monitored_variables
116  ]
117  entities.extend(
118  [
119  BboxUptimeSensor(bbox_data, name, description)
120  for description in SENSOR_TYPES_UPTIME
121  if description.key in monitored_variables
122  ]
123  )
124 
125  add_entities(entities, True)
126 
127 
129  """Bbox uptime sensor."""
130 
131  _attr_attribution = ATTRIBUTION
132  _attr_device_class = SensorDeviceClass.TIMESTAMP
133 
134  def __init__(self, bbox_data, name, description: SensorEntityDescription) -> None:
135  """Initialize the sensor."""
136  self.entity_descriptionentity_description = description
137  self._attr_name_attr_name = f"{name} {description.name}"
138  self.bbox_databbox_data = bbox_data
139 
140  def update(self) -> None:
141  """Get the latest data from Bbox and update the state."""
142  self.bbox_databbox_data.update()
143  self._attr_native_value_attr_native_value = utcnow() - timedelta(
144  seconds=self.bbox_databbox_data.router_infos["device"]["uptime"]
145  )
146 
147 
149  """Implementation of a Bbox sensor."""
150 
151  _attr_attribution = ATTRIBUTION
152 
153  def __init__(self, bbox_data, name, description: SensorEntityDescription) -> None:
154  """Initialize the sensor."""
155  self.entity_descriptionentity_description = description
156  self._attr_name_attr_name = f"{name} {description.name}"
157  self.bbox_databbox_data = bbox_data
158 
159  def update(self) -> None:
160  """Get the latest data from Bbox and update the state."""
161  self.bbox_databbox_data.update()
162  sensor_type = self.entity_descriptionentity_description.key
163  if sensor_type == "down_max_bandwidth":
164  self._attr_native_value_attr_native_value = round(
165  self.bbox_databbox_data.data["rx"]["maxBandwidth"] / 1000, 2
166  )
167  elif sensor_type == "up_max_bandwidth":
168  self._attr_native_value_attr_native_value = round(
169  self.bbox_databbox_data.data["tx"]["maxBandwidth"] / 1000, 2
170  )
171  elif sensor_type == "current_down_bandwidth":
172  self._attr_native_value_attr_native_value = round(
173  self.bbox_databbox_data.data["rx"]["bandwidth"] / 1000, 2
174  )
175  elif sensor_type == "current_up_bandwidth":
176  self._attr_native_value_attr_native_value = round(
177  self.bbox_databbox_data.data["tx"]["bandwidth"] / 1000, 2
178  )
179  elif sensor_type == "number_of_reboots":
180  self._attr_native_value_attr_native_value = self.bbox_databbox_data.router_infos["device"][
181  "numberofboots"
182  ]
183 
184 
185 class BboxData:
186  """Get data from the Bbox."""
187 
188  def __init__(self) -> None:
189  """Initialize the data object."""
190  self.datadata = None
191  self.router_infosrouter_infos = None
192 
193  @Throttle(MIN_TIME_BETWEEN_UPDATES)
194  def update(self):
195  """Get the latest data from the Bbox."""
196 
197  try:
198  box = pybbox.Bbox()
199  self.datadata = box.get_ip_stats()
200  self.router_infosrouter_infos = box.get_bbox_info()
201  except requests.exceptions.HTTPError as error:
202  _LOGGER.error(error)
203  self.datadata = None
204  self.router_infosrouter_infos = None
205  return False
None __init__(self, bbox_data, name, SensorEntityDescription description)
Definition: sensor.py:153
None __init__(self, bbox_data, name, SensorEntityDescription description)
Definition: sensor.py:134
None setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback add_entities, DiscoveryInfoType|None discovery_info=None)
Definition: sensor.py:98
def add_entities(account, async_add_entities, tracked)
Definition: sensor.py:40