diff --git a/README.md b/README.md index 2669dad..1337607 100644 --- a/README.md +++ b/README.md @@ -79,123 +79,124 @@ Note: If you are having issues with pairing your vehicle, we recommend investing ## Available Sensors -| Name | Domain | Description | -| --------------------------------------------------- | -------------- | -------------------------------------- | -| 12V Battery Health | Sensor | | -| Altitude | Sensor | | -| Battery Capactiy | Sensor | | -| Battery State of Charge | Sensor | | -| Battery State of Charge Limit | Sensor | | -| Battery Thermal Runaway Propagation | Sensor | | -| Battery Thermal Status | Sensor | | -| Bearing | Sensor | | -| Bluetooth Module Failure Status Door Front Left | Sensor | | -| Bluetooth Module Failure Status Door Front Right | Sensor | | -| Bluetooth Module Failure Status Fascia Front | Sensor | | -| Bluetooth Module Failure Status Fascia Rear | Sensor | | -| Bluetooth Module Failure Status Instrument Controls | Sensor | | -| Brake Fluid Level Low | Sensor | | -| Cabin Climate Preconditioning | Binary Sensor | Running/not running status | -| Cabin Climate Preconditioning Type | Sensor | | -| Cabin Temperature | Sensor | | -| Car Wash Mode | Binary Sensor | On/off status | -| Charger Connection | Binary Sensor | Plugged in/unplugged status | -| Charger Derate Status | Sensor | | -| Charging Status | Binary Sensor | Charging/not charging status | -| Charging Time Remaining | Sensor | | -| Closure State | Binary Sensor | Open/closed status of all closures | -| Defrost/Defog | Binary Sensor | Running/not running status | -| Door Front Left | Binary Sensor | Open/closed status | -| Door Front Left Lock | Binary Sensor | Locked/unlocked status | -| Door Front Right | Binary Sensor | Open/closed status | -| Door Front Right Lock | Binary Sensor | Locked/unlocked status | -| Door Rear Left | Binary Sensor | Open/closed status | -| Door Rear Left Lock | Binary Sensor | Locked/unlocked status | -| Door Rear Right | Binary Sensor | Open/closed status | -| Door Rear Right Lock | Binary Sensor | Locked/unlocked status | -| Door State | Binary Sensor | Open/closed status of all doors | -| Drive Mode | Sensor | | -| Driver Temperature | Sensor | | -| Estimated Vehicle Range | Sensor | | -| Front Trunk | Binary Sensor | Open/closed status | -| Front Trunk Lock | Binary Sensor | Locked/unlocked status | -| Gear Guard | Binary Sensor | Locked/unlocked status | -| Gear Guard Alarm | Binary Sensor | Tampered/clear status | -| Gear Guard Video Mode | Sensor | | -| Gear Guard Video Status | Sensor | | -| Gear Guard Video Terms Accepted\* | Sensor | | -| Gear Selector | Sensor | | -| Gear Tunnel Left | Binary Sensor | Open/closed status, R1T only | -| Gear Tunnel Left Lock | Binary Sensor | Locked/unlocked status, R1T only | -| Gear Tunnel Right | Binary Sensor | Open/closed status, R1T only | -| Gear Tunnel Right Lock | Binary Sensor | Locked/unlocked status, R1T only | -| Heated Seat 3rd Row Left | Binary Sensor | Running/not running status, R1S only | -| Heated Seat 3rd Row Right | Binary Sensor | Running/not running status, R1S only | -| Heated Seat Front Left | Binary Sensor | Running/not running status | -| Heated Seat Front Right | Binary Sensor | Running/not running status | -| Heated Seat Rear Left | Binary Sensor | Running/not running status | -| Heated Seat Rear Right | Binary Sensor | Running/not running status | -| Heated Steering Wheel | Binary Sensor | Running/not running status | -| In Use State | Binary Sensor | Moving/stopped status | -| Liftgate | Binary Sensor | Open/close status | -| Liftgate Lock | Binary Sensor | Locked/unlocked status | -| Liftgate Next Action | Sensor | | -| Limited Acceleration (Cold) | Sensor | | -| Limited Regenerative Braking (Cold) | Sensor | | -| Location | Device Tracker | | -| Locked State | Binary Sensor | Locked/unlocked status of all closures | -| Odometer | Sensor | | -| Pet Mode | Binary Sensor | Running/not running status | -| Pet Mode Temperature Status | Sensor | | -| Power State | Sensor | | -| Range Threshold | Sensor | | -| Remote Charging Available | Sensor | | -| Service Mode | Sensor | | -| Software | Update | | -| Software OTA - Available Version\* | Sensor | | -| Software OTA - Available Version Git Hash\* | Sensor | | -| Software OTA - Available Version Number\* | Sensor | | -| Software OTA - Available Version Week\* | Sensor | | -| Software OTA - Available Version Year\* | Sensor | | -| Software OTA - Current Version\* | Sensor | | -| Software OTA - Current Version Git Hash\* | Sensor | | -| Software OTA - Current Version Number\* | Sensor | | -| Software OTA - Current Version Week\* | Sensor | | -| Software OTA - Current Version Year\* | Sensor | | -| Software OTA - Download Progress | Sensor | | -| Software OTA - Install Duration | Sensor | | -| Software OTA - Install Progress\* | Sensor | | -| Software OTA - Install Ready | Sensor | | -| Software OTA - Install Time | Sensor | | -| Software OTA - Install Type | Sensor | | -| Software OTA - Status | Sensor | | -| Software OTA - Status Current | Sensor | | -| Speed | Sensor | | -| Tailgate | Binary Sensor | Open/close status | -| Tailgate Lock | Binary Sensor | Locked/unlocked status | -| Tire Pressure Front Left | Sensor | | -| Tire Pressure Front Left Validity | Binary Sensor | OK/problem status | -| Tire Pressure Front Right | Sensor | | -| Tire Pressure Front Right Validity | Binary Sensor | OK/problem status | -| Tire Pressure Rear Left | Sensor | | -| Tire Pressure Rear Left Validity | Binary Sensor | OK/problem status | -| Tire Pressure Rear Right | Sensor | | -| Tire Pressure Rear Right Validity | Binary Sensor | OK/problem status | -| Tonneau | Binary Sensor | Open/close status, R1T only | -| Tonneau Lock | Binary Sensor | Locked/unlocked status, R1T only | -| Trailer Status | Sensor | | -| Vented Seat Front Left | Binary Sensor | Running/not running status | -| Vented Seat Front Right | Binary Sensor | Running/not running status | -| Window Calibration Front Left State | Sensor | | -| Window Calibration Front Right State | Sensor | | -| Window Calibration Rear Left State | Sensor | | -| Window Calibration Rear Right State | Sensor | | -| Window Front Left | Binary Sensor | Open/close status | -| Window Front Right | Binary Sensor | Open/close status | -| Window Rear Left | Binary Sensor | Open/close status | -| Window Rear Right | Binary Sensor | Open/close status | -| Windows Next Action | Sensor | | -| Wiper Fluid Level | Binary Sensor | OK/problem status | +| Name | Domain | Description | +| --------------------------------------------------- | -------------- | ----------------------------------------------- | +| 12V Battery Health | Sensor | | +| Altitude | Sensor | | +| Battery Capactiy | Sensor | | +| Battery State of Charge | Sensor | | +| Battery State of Charge Limit | Sensor | | +| Battery Thermal Runaway Propagation | Sensor | | +| Battery Thermal Status | Sensor | | +| Bearing | Sensor | | +| Bluetooth Module Failure Status Door Front Left | Sensor | | +| Bluetooth Module Failure Status Door Front Right | Sensor | | +| Bluetooth Module Failure Status Fascia Front | Sensor | | +| Bluetooth Module Failure Status Fascia Rear | Sensor | | +| Bluetooth Module Failure Status Instrument Controls | Sensor | | +| Brake Fluid Level Low | Sensor | | +| Cabin Climate Preconditioning | Binary Sensor | Running/not running status | +| Cabin Climate Preconditioning Type | Sensor | | +| Cabin Temperature | Sensor | | +| Car Wash Mode | Binary Sensor | On/off status | +| Charger Connection | Binary Sensor | Plugged in/unplugged status | +| Charger Derate Status | Sensor | | +| Charging Status | Binary Sensor | Charging/not charging status | +| Charging Time Remaining | Sensor | | +| Closure State | Binary Sensor | Open/closed status of all closures | +| Defrost/Defog | Binary Sensor | Running/not running status | +| Door Front Left | Binary Sensor | Open/closed status | +| Door Front Left Lock | Binary Sensor | Locked/unlocked status | +| Door Front Right | Binary Sensor | Open/closed status | +| Door Front Right Lock | Binary Sensor | Locked/unlocked status | +| Door Rear Left | Binary Sensor | Open/closed status | +| Door Rear Left Lock | Binary Sensor | Locked/unlocked status | +| Door Rear Right | Binary Sensor | Open/closed status | +| Door Rear Right Lock | Binary Sensor | Locked/unlocked status | +| Door State | Binary Sensor | Open/closed status of all doors | +| Drive Mode | Sensor | | +| Driver Temperature | Sensor | | +| Estimated Vehicle Range | Sensor | | +| Front Trunk | Binary Sensor | Open/closed status | +| Front Trunk Lock | Binary Sensor | Locked/unlocked status | +| Gear Guard | Binary Sensor | Locked/unlocked status | +| Gear Guard Alarm | Binary Sensor | Tampered/clear status | +| Gear Guard Video Mode | Sensor | | +| Gear Guard Video Status | Sensor | | +| Gear Guard Video Terms Accepted\* | Sensor | | +| Gear Selector | Sensor | | +| Gear Tunnel Left | Binary Sensor | Open/closed status, R1T only | +| Gear Tunnel Left Lock | Binary Sensor | Locked/unlocked status, R1T only | +| Gear Tunnel Right | Binary Sensor | Open/closed status, R1T only | +| Gear Tunnel Right Lock | Binary Sensor | Locked/unlocked status, R1T only | +| Heated Seat 3rd Row Left | Binary Sensor | Running/not running status, R1S only | +| Heated Seat 3rd Row Right | Binary Sensor | Running/not running status, R1S only | +| Heated Seat Front Left | Binary Sensor | Running/not running status | +| Heated Seat Front Right | Binary Sensor | Running/not running status | +| Heated Seat Rear Left | Binary Sensor | Running/not running status | +| Heated Seat Rear Right | Binary Sensor | Running/not running status | +| Heated Steering Wheel | Binary Sensor | Running/not running status | +| In Use State | Binary Sensor | Moving/stopped status | +| Liftgate | Binary Sensor | Open/close status | +| Liftgate Lock | Binary Sensor | Locked/unlocked status | +| Liftgate Next Action | Sensor | | +| Limited Acceleration (Cold) | Sensor | | +| Limited Regenerative Braking (Cold) | Sensor | | +| Location | Device Tracker | | +| Locked State | Binary Sensor | Locked/unlocked status of all closures | +| Odometer | Sensor | | +| Pet Mode | Binary Sensor | Running/not running status | +| Pet Mode Temperature Status | Sensor | | +| Power State | Sensor | | +| Range Threshold | Sensor | | +| Remote Charging Available | Sensor | | +| Service Mode | Sensor | | +| Software | Update | | +| Software OTA - Available Version\* | Sensor | | +| Software OTA - Available Version Git Hash\* | Sensor | | +| Software OTA - Available Version Number\* | Sensor | | +| Software OTA - Available Version Week\* | Sensor | | +| Software OTA - Available Version Year\* | Sensor | | +| Software OTA - Current Version\* | Sensor | | +| Software OTA - Current Version Git Hash\* | Sensor | | +| Software OTA - Current Version Number\* | Sensor | | +| Software OTA - Current Version Week\* | Sensor | | +| Software OTA - Current Version Year\* | Sensor | | +| Software OTA - Download Progress | Sensor | | +| Software OTA - Install Duration | Sensor | | +| Software OTA - Install Progress\* | Sensor | | +| Software OTA - Install Ready | Sensor | | +| Software OTA - Install Time | Sensor | | +| Software OTA - Install Type | Sensor | | +| Software OTA - Status | Sensor | | +| Software OTA - Status Current | Sensor | | +| Speed | Sensor | | +| Tailgate | Binary Sensor | Open/close status | +| Tailgate Lock | Binary Sensor | Locked/unlocked status | +| Tire Pressure Front Left | Sensor | | +| Tire Pressure Front Left Validity | Binary Sensor | OK/problem status | +| Tire Pressure Front Right | Sensor | | +| Tire Pressure Front Right Validity | Binary Sensor | OK/problem status | +| Tire Pressure Rear Left | Sensor | | +| Tire Pressure Rear Left Validity | Binary Sensor | OK/problem status | +| Tire Pressure Rear Right | Sensor | | +| Tire Pressure Rear Right Validity | Binary Sensor | OK/problem status | +| Tonneau | Binary Sensor | Open/close status, R1T only | +| Tonneau Lock | Binary Sensor | Locked/unlocked status, R1T only | +| Trailer Status | Sensor | | +| Vehicle state last update time\* | Sensor | The most recent vehicle state update timestamp. | +| Vented Seat Front Left | Binary Sensor | Running/not running status | +| Vented Seat Front Right | Binary Sensor | Running/not running status | +| Window Calibration Front Left State | Sensor | | +| Window Calibration Front Right State | Sensor | | +| Window Calibration Rear Left State | Sensor | | +| Window Calibration Rear Right State | Sensor | | +| Window Front Left | Binary Sensor | Open/close status | +| Window Front Right | Binary Sensor | Open/close status | +| Window Rear Left | Binary Sensor | Open/close status | +| Window Rear Right | Binary Sensor | Open/close status | +| Windows Next Action | Sensor | | +| Wiper Fluid Level | Binary Sensor | OK/problem status | \* Disabled by default diff --git a/custom_components/rivian/binary_sensor.py b/custom_components/rivian/binary_sensor.py index d516fab..fdea052 100644 --- a/custom_components/rivian/binary_sensor.py +++ b/custom_components/rivian/binary_sensor.py @@ -2,7 +2,6 @@ from __future__ import annotations -from collections.abc import Mapping from typing import Any from homeassistant.components.binary_sensor import BinarySensorEntity @@ -76,20 +75,3 @@ def is_on(self) -> bool: result = val in values return result if not self.entity_description.negate else not result return STATE_UNAVAILABLE - - @property - def extra_state_attributes(self) -> Mapping[str, Any] | None: - """Return the state attributes of the device.""" - if self._aggregate: - return None - try: - entity = self.coordinator.data[self.entity_description.field] - if entity is None: - return "Binary Sensor Unavailable" - return { - "value": entity["value"], - "last_update": entity["timeStamp"], - "history": str(entity["history"]), - } - except KeyError: - return None diff --git a/custom_components/rivian/const.py b/custom_components/rivian/const.py index 66bb91e..bf2f2d6 100644 --- a/custom_components/rivian/const.py +++ b/custom_components/rivian/const.py @@ -642,6 +642,15 @@ icon="mdi:bluetooth", entity_category=EntityCategory.DIAGNOSTIC, ), + RivianSensorEntityDescription( + key="vehicle_state_last_update_time", + translation_key="vehicle_state_last_update_time", + field=None, + device_class=SensorDeviceClass.TIMESTAMP, + entity_category=EntityCategory.DIAGNOSTIC, + entity_registry_enabled_default=False, + value_fn=lambda coor: coor.last_update_time, + ), ), "R1S": ( RivianSensorEntityDescription( @@ -1033,7 +1042,12 @@ } VEHICLE_STATE_API_FIELDS: Final[set[str]] = { - *(description.field for sensor in SENSORS.values() for description in sensor), + *( + description.field + for sensor in SENSORS.values() + for description in sensor + if description.field + ), *( field for sensors in BINARY_SENSORS.values() diff --git a/custom_components/rivian/coordinator.py b/custom_components/rivian/coordinator.py index fad1495..0d52485 100644 --- a/custom_components/rivian/coordinator.py +++ b/custom_components/rivian/coordinator.py @@ -250,6 +250,7 @@ class VehicleCoordinator(RivianDataUpdateCoordinator[dict[str, Any]]): key = "vehicleState" _update_interval_seconds = 15 * 60 # 15 minutes + _last_update_time: datetime | None = None def __init__( self, @@ -271,6 +272,11 @@ def __init__( self._unsub_handler: Coroutine[None, None, None] | None = None self._awake = asyncio.Event() + @property + def last_update_time(self) -> datetime | None: + """Return the last update time, if any.""" + return self._last_update_time + async def _async_update_data(self) -> dict[str, Any]: """Get the latest data from Rivian.""" if not self.data or not self.last_update_success: @@ -313,14 +319,13 @@ def _process_new_data(self, data: dict[str, Any]) -> None: def _build_vehicle_info_dict(self, vijson: dict[str, Any]) -> dict[str, Any]: """Take the json output of vehicle_info and build a dictionary.""" - items = { - k: v | ({"history": {v["value"]}} if "value" in v else {}) - for k, v in vijson.items() - if v - } + items = {k: v for k, v in vijson.items() if v} if items: _LOGGER.debug("Vehicle %s updated: %s", self.vehicle_id, redact(items)) + self._last_update_time = datetime.fromisoformat( + max(v["timeStamp"] for k, v in items.items()) + ) if power_state := items.get("powerState"): if power_state.get("value") == "sleep": @@ -342,7 +347,6 @@ def _build_vehicle_info_dict(self, vijson: dict[str, Any]) -> dict[str, Any]: value = items[key].get("value") if str(value).lower() in INVALID_SENSOR_STATES and key in prev_items: new_data[key] = prev_items[key] - new_data[key]["history"] |= prev_items.get(key, {}).get("history", set()) return new_data diff --git a/custom_components/rivian/device_tracker.py b/custom_components/rivian/device_tracker.py index 65434ee..5c586c2 100644 --- a/custom_components/rivian/device_tracker.py +++ b/custom_components/rivian/device_tracker.py @@ -2,7 +2,6 @@ from __future__ import annotations -from collections.abc import Mapping from typing import Any from homeassistant.components.device_tracker import SourceType, TrackerEntity @@ -26,14 +25,12 @@ async def async_setup_entry( vehicles: dict[str, Any] = data[ATTR_VEHICLE] coordinators: dict[str, VehicleCoordinator] = data[ATTR_COORDINATOR][ATTR_VEHICLE] - entities = [ + async_add_entities( RivianDeviceEntity( coordinators[vehicle_id], entry, LOCATION_DESCRIPTION, vehicle ) for vehicle_id, vehicle in vehicles.items() - ] - - async_add_entities(entities) + ) class RivianDeviceEntity(RivianVehicleEntity, TrackerEntity): @@ -73,17 +70,6 @@ def source_type(self) -> SourceType: """Return the source type, eg gps or router, of the device.""" return SourceType.GPS - # @property - # def location_accuracy(self) -> int: - # return self._tracker_data[6] - - @property - def extra_state_attributes(self) -> Mapping[str, Any]: - """Return the state attributes of the device.""" - return { - "last_update": self._tracker_data["timeStamp"], - } - @callback def _handle_coordinator_update(self) -> None: """Respond to a DataUpdateCoordinator update.""" diff --git a/custom_components/rivian/sensor.py b/custom_components/rivian/sensor.py index d03a8f1..944b365 100644 --- a/custom_components/rivian/sensor.py +++ b/custom_components/rivian/sensor.py @@ -126,25 +126,6 @@ def native_value(self) -> str | None: self.options.append(rval) return rval - @property - def extra_state_attributes(self) -> Mapping[str, Any] | None: - """Return the state attributes of the device.""" - try: - entity = self.coordinator.data[self.entity_description.field] - if entity is None: - return None - if self.entity_description.value_lambda is None: - return { - "last_update": entity["timeStamp"], - } - return { - "native_value": entity["value"], - "last_update": entity["timeStamp"], - "history": str(entity["history"]), - } - except KeyError: - return None - class RivianChargingSensorEntity(RivianChargingEntity, SensorEntity): """Representation of a Rivian charging sensor entity.""" diff --git a/custom_components/rivian/strings.json b/custom_components/rivian/strings.json index edc6b31..b3be2c0 100644 --- a/custom_components/rivian/strings.json +++ b/custom_components/rivian/strings.json @@ -60,6 +60,9 @@ "plugged_in": "Plugged in", "charging": "Charging" } + }, + "vehicle_state_last_update_time": { + "name": "Vehicle state last update time" } } }, diff --git a/custom_components/rivian/translations/en.json b/custom_components/rivian/translations/en.json index 588e465..224357d 100644 --- a/custom_components/rivian/translations/en.json +++ b/custom_components/rivian/translations/en.json @@ -59,6 +59,9 @@ "plugged_in": "Plugged in", "charging": "Charging" } + }, + "vehicle_state_last_update_time": { + "name": "Vehicle state last update time" } } },