Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for Fido.
2 
3 Get data from 'Usage Summary' page:
4 https://www.fido.ca/pages/#/my-account/wireless
5 """
6 
7 from __future__ import annotations
8 
9 from datetime import timedelta
10 import logging
11 
12 from pyfido import FidoClient
13 from pyfido.client import PyFidoError
14 import voluptuous as vol
15 
17  PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
18  SensorDeviceClass,
19  SensorEntity,
20  SensorEntityDescription,
21 )
22 from homeassistant.const import (
23  CONF_MONITORED_VARIABLES,
24  CONF_NAME,
25  CONF_PASSWORD,
26  CONF_USERNAME,
27  UnitOfInformation,
28  UnitOfTime,
29 )
30 from homeassistant.core import HomeAssistant
31 from homeassistant.helpers.aiohttp_client import async_get_clientsession
33 from homeassistant.helpers.entity_platform import AddEntitiesCallback
34 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
35 from homeassistant.util import Throttle
36 
37 _LOGGER = logging.getLogger(__name__)
38 
39 PRICE = "CAD"
40 MESSAGES = "messages"
41 
42 DEFAULT_NAME = "Fido"
43 
44 REQUESTS_TIMEOUT = 15
45 MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=15)
46 
47 SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
49  key="fido_dollar",
50  name="Fido dollar",
51  native_unit_of_measurement=PRICE,
52  icon="mdi:cash",
53  ),
55  key="balance",
56  name="Balance",
57  native_unit_of_measurement=PRICE,
58  icon="mdi:cash",
59  ),
61  key="data_used",
62  name="Data used",
63  native_unit_of_measurement=UnitOfInformation.KILOBITS,
64  device_class=SensorDeviceClass.DATA_SIZE,
65  icon="mdi:download",
66  ),
68  key="data_limit",
69  name="Data limit",
70  native_unit_of_measurement=UnitOfInformation.KILOBITS,
71  device_class=SensorDeviceClass.DATA_SIZE,
72  icon="mdi:download",
73  ),
75  key="data_remaining",
76  name="Data remaining",
77  native_unit_of_measurement=UnitOfInformation.KILOBITS,
78  device_class=SensorDeviceClass.DATA_SIZE,
79  icon="mdi:download",
80  ),
82  key="text_used",
83  name="Text used",
84  native_unit_of_measurement=MESSAGES,
85  icon="mdi:message-text",
86  ),
88  key="text_limit",
89  name="Text limit",
90  native_unit_of_measurement=MESSAGES,
91  icon="mdi:message-text",
92  ),
94  key="text_remaining",
95  name="Text remaining",
96  native_unit_of_measurement=MESSAGES,
97  icon="mdi:message-text",
98  ),
100  key="mms_used",
101  name="MMS used",
102  native_unit_of_measurement=MESSAGES,
103  icon="mdi:message-image",
104  ),
106  key="mms_limit",
107  name="MMS limit",
108  native_unit_of_measurement=MESSAGES,
109  icon="mdi:message-image",
110  ),
112  key="mms_remaining",
113  name="MMS remaining",
114  native_unit_of_measurement=MESSAGES,
115  icon="mdi:message-image",
116  ),
118  key="text_int_used",
119  name="International text used",
120  native_unit_of_measurement=MESSAGES,
121  icon="mdi:message-alert",
122  ),
124  key="text_int_limit",
125  name="International text limit",
126  native_unit_of_measurement=MESSAGES,
127  icon="mdi:message-alert",
128  ),
130  key="text_int_remaining",
131  name="International remaining",
132  native_unit_of_measurement=MESSAGES,
133  icon="mdi:message-alert",
134  ),
136  key="talk_used",
137  name="Talk used",
138  native_unit_of_measurement=UnitOfTime.MINUTES,
139  icon="mdi:cellphone",
140  ),
142  key="talk_limit",
143  name="Talk limit",
144  native_unit_of_measurement=UnitOfTime.MINUTES,
145  icon="mdi:cellphone",
146  ),
148  key="talk_remaining",
149  name="Talk remaining",
150  native_unit_of_measurement=UnitOfTime.MINUTES,
151  icon="mdi:cellphone",
152  ),
154  key="other_talk_used",
155  name="Other Talk used",
156  native_unit_of_measurement=UnitOfTime.MINUTES,
157  icon="mdi:cellphone",
158  ),
160  key="other_talk_limit",
161  name="Other Talk limit",
162  native_unit_of_measurement=UnitOfTime.MINUTES,
163  icon="mdi:cellphone",
164  ),
166  key="other_talk_remaining",
167  name="Other Talk remaining",
168  native_unit_of_measurement=UnitOfTime.MINUTES,
169  icon="mdi:cellphone",
170  ),
171 )
172 
173 SENSOR_KEYS: list[str] = [desc.key for desc in SENSOR_TYPES]
174 
175 PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
176  {
177  vol.Required(CONF_MONITORED_VARIABLES): vol.All(
178  cv.ensure_list, [vol.In(SENSOR_KEYS)]
179  ),
180  vol.Required(CONF_USERNAME): cv.string,
181  vol.Required(CONF_PASSWORD): cv.string,
182  vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
183  }
184 )
185 
186 
188  hass: HomeAssistant,
189  config: ConfigType,
190  async_add_entities: AddEntitiesCallback,
191  discovery_info: DiscoveryInfoType | None = None,
192 ) -> None:
193  """Set up the Fido sensor."""
194  username = config[CONF_USERNAME]
195  password = config[CONF_PASSWORD]
196 
197  httpsession = async_get_clientsession(hass)
198  fido_data = FidoData(username, password, httpsession)
199  ret = await fido_data.async_update()
200  if ret is False:
201  return
202 
203  name = config[CONF_NAME]
204  monitored_variables = config[CONF_MONITORED_VARIABLES]
205  entities = [
206  FidoSensor(fido_data, name, number, description)
207  for number in fido_data.client.get_phone_numbers()
208  for description in SENSOR_TYPES
209  if description.key in monitored_variables
210  ]
211 
212  async_add_entities(entities, True)
213 
214 
216  """Implementation of a Fido sensor."""
217 
218  def __init__(
219  self, fido_data, name, number, description: SensorEntityDescription
220  ) -> None:
221  """Initialize the sensor."""
222  self.entity_descriptionentity_description = description
223  self.fido_datafido_data = fido_data
224  self._number_number = number
225 
226  self._attr_name_attr_name = f"{name} {number} {description.name}"
227 
228  @property
230  """Return the state attributes of the sensor."""
231  return {"number": self._number_number}
232 
233  async def async_update(self) -> None:
234  """Get the latest data from Fido and update the state."""
235  await self.fido_datafido_data.async_update()
236  if (sensor_type := self.entity_descriptionentity_description.key) == "balance":
237  if self.fido_datafido_data.data.get(sensor_type) is not None:
238  self._attr_native_value_attr_native_value = round(self.fido_datafido_data.data[sensor_type], 2)
239  elif self.fido_datafido_data.data.get(self._number_number, {}).get(sensor_type) is not None:
240  self._attr_native_value_attr_native_value = round(
241  self.fido_datafido_data.data[self._number_number][sensor_type], 2
242  )
243 
244 
245 class FidoData:
246  """Get data from Fido."""
247 
248  def __init__(self, username, password, httpsession):
249  """Initialize the data object."""
250 
251  self.clientclient = FidoClient(username, password, REQUESTS_TIMEOUT, httpsession)
252  self.datadata = {}
253 
254  @Throttle(MIN_TIME_BETWEEN_UPDATES)
255  async def async_update(self):
256  """Get the latest data from Fido."""
257 
258  try:
259  await self.clientclient.fetch_data()
260  except PyFidoError as exp:
261  _LOGGER.error("Error on receive last Fido data: %s", exp)
262  return False
263  # Update data
264  self.datadata = self.clientclient.get_data()
265  return True
def __init__(self, username, password, httpsession)
Definition: sensor.py:248
None __init__(self, fido_data, name, number, SensorEntityDescription description)
Definition: sensor.py:220
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
None async_setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback async_add_entities, DiscoveryInfoType|None discovery_info=None)
Definition: sensor.py:192
MetOfficeData fetch_data(datapoint.Manager connection, Site site, str mode)
Definition: helpers.py:32
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)