302 lines
9.5 KiB
Python
302 lines
9.5 KiB
Python
"""Sensor for Hyundai / Kia Connect integration."""
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Callable
|
|
import logging
|
|
from typing import Final
|
|
|
|
from hyundai_kia_connect_api import Vehicle
|
|
|
|
from homeassistant.components.sensor import (
|
|
SensorDeviceClass,
|
|
SensorEntity,
|
|
SensorEntityDescription,
|
|
SensorStateClass,
|
|
)
|
|
from homeassistant.const import (
|
|
PERCENTAGE,
|
|
TIME_MINUTES,
|
|
ENERGY_WATT_HOUR,
|
|
ENERGY_KILO_WATT_HOUR,
|
|
)
|
|
|
|
from homeassistant.config_entries import ConfigEntry
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
|
|
from .const import DOMAIN, DYNAMIC_UNIT
|
|
from .coordinator import HyundaiKiaConnectDataUpdateCoordinator
|
|
from .entity import HyundaiKiaConnectEntity
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
SENSOR_DESCRIPTIONS: Final[tuple[SensorEntityDescription, ...]] = (
|
|
SensorEntityDescription(
|
|
key="_total_driving_range",
|
|
name="Total Driving Range",
|
|
icon="mdi:road-variant",
|
|
device_class=SensorDeviceClass.DISTANCE,
|
|
native_unit_of_measurement=DYNAMIC_UNIT,
|
|
),
|
|
SensorEntityDescription(
|
|
key="_odometer",
|
|
name="Odometer",
|
|
icon="mdi:speedometer",
|
|
native_unit_of_measurement=DYNAMIC_UNIT,
|
|
device_class=SensorDeviceClass.DISTANCE,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
SensorEntityDescription(
|
|
key="_last_service_distance",
|
|
name="Last Service",
|
|
icon="mdi:car-wrench",
|
|
device_class=SensorDeviceClass.DISTANCE,
|
|
native_unit_of_measurement=DYNAMIC_UNIT,
|
|
),
|
|
SensorEntityDescription(
|
|
key="_next_service_distance",
|
|
name="Next Service",
|
|
icon="mdi:car-wrench",
|
|
device_class=SensorDeviceClass.DISTANCE,
|
|
native_unit_of_measurement=DYNAMIC_UNIT,
|
|
),
|
|
SensorEntityDescription(
|
|
key="car_battery_percentage",
|
|
name="Car Battery Level",
|
|
icon="mdi:car-battery",
|
|
native_unit_of_measurement=PERCENTAGE,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
SensorEntityDescription(
|
|
key="last_updated_at",
|
|
name="Last Updated At",
|
|
icon="mdi:update",
|
|
device_class=SensorDeviceClass.TIMESTAMP,
|
|
),
|
|
SensorEntityDescription(
|
|
key="ev_battery_percentage",
|
|
name="EV Battery Level",
|
|
native_unit_of_measurement=PERCENTAGE,
|
|
device_class=SensorDeviceClass.BATTERY,
|
|
),
|
|
SensorEntityDescription(
|
|
key="_ev_driving_range",
|
|
name="EV Range",
|
|
icon="mdi:road-variant",
|
|
device_class=SensorDeviceClass.DISTANCE,
|
|
native_unit_of_measurement=DYNAMIC_UNIT,
|
|
),
|
|
SensorEntityDescription(
|
|
key="_fuel_driving_range",
|
|
name="Fuel Driving Range",
|
|
icon="mdi:road-variant",
|
|
device_class=SensorDeviceClass.DISTANCE,
|
|
native_unit_of_measurement=DYNAMIC_UNIT,
|
|
),
|
|
SensorEntityDescription(
|
|
key="fuel_level",
|
|
name="Fuel Level",
|
|
native_unit_of_measurement=PERCENTAGE,
|
|
icon="mdi:fuel",
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
SensorEntityDescription(
|
|
key="_air_temperature",
|
|
name="Set Temperature",
|
|
native_unit_of_measurement=DYNAMIC_UNIT,
|
|
device_class=SensorDeviceClass.TEMPERATURE,
|
|
),
|
|
SensorEntityDescription(
|
|
key="ev_estimated_current_charge_duration",
|
|
name="Estimated Charge Duration",
|
|
icon="mdi:ev-station",
|
|
native_unit_of_measurement=TIME_MINUTES,
|
|
),
|
|
SensorEntityDescription(
|
|
key="ev_estimated_fast_charge_duration",
|
|
name="Estimated Fast Charge Duration",
|
|
icon="mdi:ev-station",
|
|
native_unit_of_measurement=TIME_MINUTES,
|
|
),
|
|
SensorEntityDescription(
|
|
key="ev_estimated_portable_charge_duration",
|
|
name="Estimated portable Charge Duration",
|
|
icon="mdi:ev-station",
|
|
native_unit_of_measurement=TIME_MINUTES,
|
|
),
|
|
SensorEntityDescription(
|
|
key="ev_estimated_station_charge_duration",
|
|
name="Estimated Station Charge Duration",
|
|
icon="mdi:ev-station",
|
|
native_unit_of_measurement=TIME_MINUTES,
|
|
),
|
|
SensorEntityDescription(
|
|
key="_ev_target_range_charge_AC",
|
|
name="Target Range of Charge AC",
|
|
icon="mdi:ev-station",
|
|
device_class=SensorDeviceClass.DISTANCE,
|
|
native_unit_of_measurement=DYNAMIC_UNIT,
|
|
),
|
|
SensorEntityDescription(
|
|
key="_ev_target_range_charge_DC",
|
|
name="Target Range of Charge DC",
|
|
icon="mdi:ev-station",
|
|
device_class=SensorDeviceClass.DISTANCE,
|
|
native_unit_of_measurement=DYNAMIC_UNIT,
|
|
),
|
|
SensorEntityDescription(
|
|
key="total_power_consumed",
|
|
name="Monthly Energy Consumption",
|
|
icon="mdi:car-electric",
|
|
native_unit_of_measurement=ENERGY_WATT_HOUR,
|
|
device_class=SensorDeviceClass.ENERGY,
|
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
|
),
|
|
# Need to remove km hard coding. Underlying API needs this fixed first. EU always does KM.
|
|
SensorEntityDescription(
|
|
key="power_consumption_30d",
|
|
name="Average Energy Consumption",
|
|
icon="mdi:car-electric",
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
native_unit_of_measurement=f"{ENERGY_WATT_HOUR}/km",
|
|
),
|
|
SensorEntityDescription(
|
|
key="front_left_seat_status",
|
|
name="Front Left Seat",
|
|
icon="mdi:car-seat-heater",
|
|
),
|
|
SensorEntityDescription(
|
|
key="front_right_seat_status",
|
|
name="Front Right Seat",
|
|
icon="mdi:car-seat-heater",
|
|
),
|
|
SensorEntityDescription(
|
|
key="rear_left_seat_status",
|
|
name="Rear Left Seat",
|
|
icon="mdi:car-seat-heater",
|
|
),
|
|
SensorEntityDescription(
|
|
key="rear_right_seat_status",
|
|
name="Rear Right Seat",
|
|
icon="mdi:car-seat-heater",
|
|
),
|
|
SensorEntityDescription(
|
|
key="_geocode_name",
|
|
name="Geocoded Location",
|
|
icon="mdi:map",
|
|
),
|
|
SensorEntityDescription(
|
|
key="dtc_count",
|
|
name="DTC Count",
|
|
icon="mdi:alert-circle",
|
|
),
|
|
SensorEntityDescription(
|
|
key="ev_first_departure_time",
|
|
name="EV First Scheduled Depature Time",
|
|
icon="mdi:clock-outline",
|
|
),
|
|
SensorEntityDescription(
|
|
key="ev_second_departure_time",
|
|
name="EV Second Scheduled Depature Time",
|
|
icon="mdi:clock-outline",
|
|
),
|
|
SensorEntityDescription(
|
|
key="ev_off_peak_start_time",
|
|
name="EV Off Peak Start Time",
|
|
icon="mdi:clock-outline",
|
|
),
|
|
SensorEntityDescription(
|
|
key="ev_off_peak_end_time",
|
|
name="EV Off Peak End Time",
|
|
icon="mdi:clock-outline",
|
|
),
|
|
)
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant,
|
|
config_entry: ConfigEntry,
|
|
async_add_entities: AddEntitiesCallback,
|
|
) -> None:
|
|
"""Set up sensor platform."""
|
|
coordinator = hass.data[DOMAIN][config_entry.unique_id]
|
|
entities = []
|
|
for vehicle_id in coordinator.vehicle_manager.vehicles.keys():
|
|
vehicle: Vehicle = coordinator.vehicle_manager.vehicles[vehicle_id]
|
|
for description in SENSOR_DESCRIPTIONS:
|
|
if getattr(vehicle, description.key, None) is not None:
|
|
entities.append(
|
|
HyundaiKiaConnectSensor(coordinator, description, vehicle)
|
|
)
|
|
async_add_entities(entities)
|
|
async_add_entities(
|
|
[VehicleEntity(coordinator, coordinator.vehicle_manager.vehicles[vehicle_id])],
|
|
True,
|
|
)
|
|
return True
|
|
|
|
|
|
class HyundaiKiaConnectSensor(SensorEntity, HyundaiKiaConnectEntity):
|
|
"""Hyundai / Kia Connect sensor class."""
|
|
|
|
def __init__(
|
|
self, coordinator, description: SensorEntityDescription, vehicle: Vehicle
|
|
):
|
|
"""Initialize the sensor."""
|
|
super().__init__(coordinator, vehicle)
|
|
self._description = description
|
|
self._key = self._description.key
|
|
self._attr_unique_id = f"{DOMAIN}_{vehicle.id}_{self._key}"
|
|
self._attr_icon = self._description.icon
|
|
self._attr_name = f"{vehicle.name} {self._description.name}"
|
|
self._attr_state_class = self._description.state_class
|
|
self._attr_device_class = self._description.device_class
|
|
|
|
@property
|
|
def native_value(self):
|
|
"""Return the value reported by the sensor."""
|
|
return getattr(self.vehicle, self._key)
|
|
|
|
@property
|
|
def native_unit_of_measurement(self):
|
|
"""Return the unit the value was reported in by the sensor"""
|
|
if self._description.native_unit_of_measurement == DYNAMIC_UNIT:
|
|
return getattr(self.vehicle, self._key + "_unit")
|
|
else:
|
|
return self._description.native_unit_of_measurement
|
|
|
|
@property
|
|
def state_attributes(self):
|
|
if self._description.key == "_geocode_name":
|
|
return {"address": getattr(self.vehicle, "_geocode_address")}
|
|
elif self._description.key == "dtc_count":
|
|
return {"DTC Text": getattr(self.vehicle, "dtc_descriptions")}
|
|
|
|
|
|
class VehicleEntity(SensorEntity, HyundaiKiaConnectEntity):
|
|
def __init__(self, coordinator, vehicle: Vehicle):
|
|
super().__init__(coordinator, vehicle)
|
|
|
|
@property
|
|
def state(self):
|
|
return "on"
|
|
|
|
@property
|
|
def is_on(self) -> bool:
|
|
return True
|
|
|
|
@property
|
|
def state_attributes(self):
|
|
return {
|
|
"vehicle_data": self.vehicle.data,
|
|
"vehicle_name": self.vehicle.name,
|
|
}
|
|
|
|
@property
|
|
def name(self):
|
|
return f"{self.vehicle.name} Data"
|
|
|
|
@property
|
|
def unique_id(self):
|
|
return f"{DOMAIN}-all-data-{self.vehicle.id}"
|