Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for the Torque OBD application."""
2 
3 from __future__ import annotations
4 
5 import re
6 
7 from aiohttp import web
8 import voluptuous as vol
9 
10 from homeassistant.components.http import HomeAssistantView
12  PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
13  SensorEntity,
14 )
15 from homeassistant.const import CONF_EMAIL, CONF_NAME, DEGREE
16 from homeassistant.core import HomeAssistant, callback
18 from homeassistant.helpers.entity_platform import AddEntitiesCallback
19 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
20 
21 API_PATH = "/api/torque"
22 
23 DEFAULT_NAME = "vehicle"
24 DOMAIN = "torque"
25 
26 ENTITY_NAME_FORMAT = "{0} {1}"
27 
28 SENSOR_EMAIL_FIELD = "eml"
29 SENSOR_NAME_KEY = r"userFullName(\w+)"
30 SENSOR_UNIT_KEY = r"userUnit(\w+)"
31 SENSOR_VALUE_KEY = r"k(\w+)"
32 
33 NAME_KEY = re.compile(SENSOR_NAME_KEY)
34 UNIT_KEY = re.compile(SENSOR_UNIT_KEY)
35 VALUE_KEY = re.compile(SENSOR_VALUE_KEY)
36 
37 PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
38  {
39  vol.Required(CONF_EMAIL): cv.string,
40  vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
41  }
42 )
43 
44 
45 def convert_pid(value):
46  """Convert pid from hex string to integer."""
47  return int(value, 16)
48 
49 
51  hass: HomeAssistant,
52  config: ConfigType,
53  async_add_entities: AddEntitiesCallback,
54  discovery_info: DiscoveryInfoType | None = None,
55 ) -> None:
56  """Set up the Torque platform."""
57  vehicle: str | None = config.get(CONF_NAME)
58  email: str | None = config.get(CONF_EMAIL)
59  sensors: dict[int, TorqueSensor] = {}
60 
61  hass.http.register_view(
62  TorqueReceiveDataView(email, vehicle, sensors, async_add_entities)
63  )
64 
65 
66 class TorqueReceiveDataView(HomeAssistantView):
67  """Handle data from Torque requests."""
68 
69  url = API_PATH
70  name = "api:torque"
71 
72  def __init__(
73  self,
74  email: str | None,
75  vehicle: str | None,
76  sensors: dict[int, TorqueSensor],
77  async_add_entities: AddEntitiesCallback,
78  ) -> None:
79  """Initialize a Torque view."""
80  self.emailemail = email
81  self.vehiclevehicle = vehicle
82  self.sensorssensors = sensors
83  self.async_add_entitiesasync_add_entities = async_add_entities
84 
85  @callback
86  def get(self, request: web.Request) -> str | None:
87  """Handle Torque data request."""
88  data = request.query
89 
90  if self.emailemail is not None and self.emailemail != data[SENSOR_EMAIL_FIELD]:
91  return None
92 
93  names = {}
94  units = {}
95  for key in data:
96  is_name = NAME_KEY.match(key)
97  is_unit = UNIT_KEY.match(key)
98  is_value = VALUE_KEY.match(key)
99 
100  if is_name:
101  pid = convert_pid(is_name.group(1))
102  names[pid] = data[key]
103  elif is_unit:
104  pid = convert_pid(is_unit.group(1))
105 
106  temp_unit = data[key]
107  if "\\xC2\\xB0" in temp_unit:
108  temp_unit = temp_unit.replace("\\xC2\\xB0", DEGREE)
109 
110  units[pid] = temp_unit
111  elif is_value:
112  pid = convert_pid(is_value.group(1))
113  if pid in self.sensorssensors:
114  self.sensorssensors[pid].async_on_update(data[key])
115 
116  new_sensor_entities: list[TorqueSensor] = []
117  for pid, name in names.items():
118  if pid not in self.sensorssensors:
119  torque_sensor_entity = TorqueSensor(
120  ENTITY_NAME_FORMAT.format(self.vehiclevehicle, name), units.get(pid)
121  )
122  new_sensor_entities.append(torque_sensor_entity)
123  self.sensorssensors[pid] = torque_sensor_entity
124 
125  if new_sensor_entities:
126  self.async_add_entitiesasync_add_entities(new_sensor_entities)
127 
128  return "OK!"
129 
130 
132  """Representation of a Torque sensor."""
133 
134  def __init__(self, name, unit):
135  """Initialize the sensor."""
136  self._name_name = name
137  self._unit_unit = unit
138  self._state_state = None
139 
140  @property
141  def name(self):
142  """Return the name of the sensor."""
143  return self._name_name
144 
145  @property
147  """Return the unit of measurement."""
148  return self._unit_unit
149 
150  @property
151  def native_value(self):
152  """Return the state of the sensor."""
153  return self._state_state
154 
155  @property
156  def icon(self):
157  """Return the default icon of the sensor."""
158  return "mdi:car"
159 
160  @callback
161  def async_on_update(self, value):
162  """Receive an update."""
163  self._state_state = value
164  self.async_write_ha_stateasync_write_ha_state()
str|None get(self, web.Request request)
Definition: sensor.py:86
None __init__(self, str|None email, str|None vehicle, dict[int, TorqueSensor] sensors, AddEntitiesCallback async_add_entities)
Definition: sensor.py:78
None async_setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback async_add_entities, DiscoveryInfoType|None discovery_info=None)
Definition: sensor.py:55