1 """Platform for sensor integration."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from dataclasses
import dataclass
10 from mypermobil
import (
11 BATTERY_AMPERE_HOURS_LEFT,
12 BATTERY_CHARGE_TIME_LEFT,
13 BATTERY_DISTANCE_LEFT,
14 BATTERY_INDOOR_DRIVE_TIME,
15 BATTERY_MAX_AMPERE_HOURS,
16 BATTERY_MAX_DISTANCE_LEFT,
17 BATTERY_STATE_OF_CHARGE,
18 BATTERY_STATE_OF_HEALTH,
20 RECORDS_DISTANCE_UNIT,
26 from homeassistant
import config_entries
30 SensorEntityDescription,
37 from .const
import BATTERY_ASSUMED_VOLTAGE, DOMAIN, KM, MILES
38 from .coordinator
import MyPermobilCoordinator
39 from .entity
import PermobilEntity
41 _LOGGER = logging.getLogger(__name__)
44 @dataclass(frozen=True, kw_only=True)
46 """Describes Permobil sensor entity."""
48 value_fn: Callable[[Any], float | int]
49 available_fn: Callable[[Any], bool]
52 SENSOR_DESCRIPTIONS: tuple[PermobilSensorEntityDescription, ...] = (
55 value_fn=
lambda data: data.battery[BATTERY_STATE_OF_CHARGE[0]],
56 available_fn=
lambda data: BATTERY_STATE_OF_CHARGE[0]
in data.battery,
57 key=
"state_of_charge",
58 translation_key=
"state_of_charge",
59 native_unit_of_measurement=PERCENTAGE,
60 device_class=SensorDeviceClass.BATTERY,
61 state_class=SensorStateClass.MEASUREMENT,
65 value_fn=
lambda data: data.battery[BATTERY_STATE_OF_HEALTH[0]],
66 available_fn=
lambda data: BATTERY_STATE_OF_HEALTH[0]
in data.battery,
67 key=
"state_of_health",
68 translation_key=
"state_of_health",
69 native_unit_of_measurement=PERCENTAGE,
70 state_class=SensorStateClass.MEASUREMENT,
74 value_fn=
lambda data: data.battery[BATTERY_CHARGE_TIME_LEFT[0]],
75 available_fn=
lambda data: BATTERY_CHARGE_TIME_LEFT[0]
in data.battery,
76 key=
"charge_time_left",
77 translation_key=
"charge_time_left",
78 native_unit_of_measurement=UnitOfTime.HOURS,
79 device_class=SensorDeviceClass.DURATION,
83 value_fn=
lambda data: data.battery[BATTERY_DISTANCE_LEFT[0]],
84 available_fn=
lambda data: BATTERY_DISTANCE_LEFT[0]
in data.battery,
86 translation_key=
"distance_left",
87 native_unit_of_measurement=UnitOfLength.KILOMETERS,
88 device_class=SensorDeviceClass.DISTANCE,
92 value_fn=
lambda data: data.battery[BATTERY_INDOOR_DRIVE_TIME[0]],
93 available_fn=
lambda data: BATTERY_INDOOR_DRIVE_TIME[0]
in data.battery,
94 key=
"indoor_drive_time",
95 translation_key=
"indoor_drive_time",
96 native_unit_of_measurement=UnitOfTime.HOURS,
97 device_class=SensorDeviceClass.DURATION,
101 value_fn=
lambda data: data.battery[BATTERY_MAX_AMPERE_HOURS[0]]
102 * BATTERY_ASSUMED_VOLTAGE,
103 available_fn=
lambda data: BATTERY_MAX_AMPERE_HOURS[0]
in data.battery,
104 key=
"max_watt_hours",
105 translation_key=
"max_watt_hours",
106 native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
107 device_class=SensorDeviceClass.ENERGY_STORAGE,
108 state_class=SensorStateClass.MEASUREMENT,
112 value_fn=
lambda data: data.battery[BATTERY_AMPERE_HOURS_LEFT[0]]
113 * BATTERY_ASSUMED_VOLTAGE,
114 available_fn=
lambda data: BATTERY_AMPERE_HOURS_LEFT[0]
in data.battery,
115 key=
"watt_hours_left",
116 translation_key=
"watt_hours_left",
117 native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
118 device_class=SensorDeviceClass.ENERGY_STORAGE,
119 state_class=SensorStateClass.MEASUREMENT,
123 value_fn=
lambda data: data.battery[BATTERY_MAX_DISTANCE_LEFT[0]],
124 available_fn=
lambda data: BATTERY_MAX_DISTANCE_LEFT[0]
in data.battery,
125 key=
"max_distance_left",
126 translation_key=
"max_distance_left",
127 native_unit_of_measurement=UnitOfLength.KILOMETERS,
128 device_class=SensorDeviceClass.DISTANCE,
132 value_fn=
lambda data: data.daily_usage[USAGE_DISTANCE[0]],
133 available_fn=
lambda data: USAGE_DISTANCE[0]
in data.daily_usage,
134 key=
"usage_distance",
135 translation_key=
"usage_distance",
136 native_unit_of_measurement=UnitOfLength.KILOMETERS,
137 device_class=SensorDeviceClass.DISTANCE,
138 state_class=SensorStateClass.TOTAL_INCREASING,
142 value_fn=
lambda data: data.daily_usage[USAGE_ADJUSTMENTS[0]],
143 available_fn=
lambda data: USAGE_ADJUSTMENTS[0]
in data.daily_usage,
144 key=
"usage_adjustments",
145 translation_key=
"usage_adjustments",
146 native_unit_of_measurement=
"adjustments",
147 state_class=SensorStateClass.TOTAL_INCREASING,
151 value_fn=
lambda data: data.records[RECORDS_SEATING[0]],
152 available_fn=
lambda data: RECORDS_SEATING[0]
in data.records,
153 key=
"record_adjustments",
154 translation_key=
"record_adjustments",
155 native_unit_of_measurement=
"adjustments",
156 state_class=SensorStateClass.TOTAL_INCREASING,
160 value_fn=
lambda data: data.records[RECORDS_DISTANCE[0]],
161 available_fn=
lambda data: RECORDS_DISTANCE[0]
in data.records,
162 key=
"record_distance",
163 translation_key=
"record_distance",
164 device_class=SensorDeviceClass.DISTANCE,
165 state_class=SensorStateClass.TOTAL_INCREASING,
169 DISTANCE_UNITS: dict[Any, UnitOfLength] = {
170 KM: UnitOfLength.KILOMETERS,
171 MILES: UnitOfLength.MILES,
178 async_add_entities: AddEntitiesCallback,
180 """Create sensors from a config entry created in the integrations UI."""
182 coordinator: MyPermobilCoordinator = hass.data[DOMAIN][config_entry.entry_id]
186 for description
in SENSOR_DESCRIPTIONS
191 """Representation of a Sensor.
193 This implements the common functions of all sensors.
196 _attr_suggested_display_precision = 0
197 entity_description: PermobilSensorEntityDescription
201 """Return the unit of measurement of the sensor."""
203 return DISTANCE_UNITS.get(
204 self.coordinator.data.records[RECORDS_DISTANCE_UNIT[0]]
210 """Return True if the sensor has value."""
212 self.coordinator.data
217 """Return the value of the sensor."""
float|int native_value(self)
str|None native_unit_of_measurement(self)
None async_setup_entry(HomeAssistant hass, config_entries.ConfigEntry config_entry, AddEntitiesCallback async_add_entities)