mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 08:17:08 +00:00
Starline OBD information (#37608)
* Starline OBD data * Small fix * Review (comments) * Review (service description) * Review (service method) * starline updated to 0.1.5 * Small typo fix
This commit is contained in:
parent
7872e6caf8
commit
eca6bc6a73
@ -8,10 +8,13 @@ from homeassistant.exceptions import ConfigEntryNotReady
|
|||||||
from .account import StarlineAccount
|
from .account import StarlineAccount
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_SCAN_INTERVAL,
|
CONF_SCAN_INTERVAL,
|
||||||
|
CONF_SCAN_OBD_INTERVAL,
|
||||||
DEFAULT_SCAN_INTERVAL,
|
DEFAULT_SCAN_INTERVAL,
|
||||||
|
DEFAULT_SCAN_OBD_INTERVAL,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
PLATFORMS,
|
PLATFORMS,
|
||||||
SERVICE_SET_SCAN_INTERVAL,
|
SERVICE_SET_SCAN_INTERVAL,
|
||||||
|
SERVICE_SET_SCAN_OBD_INTERVAL,
|
||||||
SERVICE_UPDATE_STATE,
|
SERVICE_UPDATE_STATE,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -25,6 +28,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
|||||||
"""Set up the StarLine device from a config entry."""
|
"""Set up the StarLine device from a config entry."""
|
||||||
account = StarlineAccount(hass, config_entry)
|
account = StarlineAccount(hass, config_entry)
|
||||||
await account.update()
|
await account.update()
|
||||||
|
await account.update_obd()
|
||||||
if not account.api.available:
|
if not account.api.available:
|
||||||
raise ConfigEntryNotReady
|
raise ConfigEntryNotReady
|
||||||
|
|
||||||
@ -44,12 +48,23 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
|||||||
)
|
)
|
||||||
|
|
||||||
async def async_set_scan_interval(call):
|
async def async_set_scan_interval(call):
|
||||||
"""Service for set scan interval."""
|
"""Set scan interval."""
|
||||||
options = dict(config_entry.options)
|
options = dict(config_entry.options)
|
||||||
options[CONF_SCAN_INTERVAL] = call.data[CONF_SCAN_INTERVAL]
|
options[CONF_SCAN_INTERVAL] = call.data[CONF_SCAN_INTERVAL]
|
||||||
hass.config_entries.async_update_entry(entry=config_entry, options=options)
|
hass.config_entries.async_update_entry(entry=config_entry, options=options)
|
||||||
|
|
||||||
hass.services.async_register(DOMAIN, SERVICE_UPDATE_STATE, account.update)
|
async def async_set_scan_obd_interval(call):
|
||||||
|
"""Set OBD info scan interval."""
|
||||||
|
options = dict(config_entry.options)
|
||||||
|
options[CONF_SCAN_OBD_INTERVAL] = call.data[CONF_SCAN_INTERVAL]
|
||||||
|
hass.config_entries.async_update_entry(entry=config_entry, options=options)
|
||||||
|
|
||||||
|
async def async_update(call=None):
|
||||||
|
"""Update all data."""
|
||||||
|
await account.update()
|
||||||
|
await account.update_obd()
|
||||||
|
|
||||||
|
hass.services.async_register(DOMAIN, SERVICE_UPDATE_STATE, async_update)
|
||||||
hass.services.async_register(
|
hass.services.async_register(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
SERVICE_SET_SCAN_INTERVAL,
|
SERVICE_SET_SCAN_INTERVAL,
|
||||||
@ -62,6 +77,18 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
|||||||
}
|
}
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
hass.services.async_register(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_SET_SCAN_OBD_INTERVAL,
|
||||||
|
async_set_scan_obd_interval,
|
||||||
|
schema=vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(CONF_SCAN_INTERVAL): vol.All(
|
||||||
|
vol.Coerce(int), vol.Range(min=180)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
config_entry.add_update_listener(async_options_updated)
|
config_entry.add_update_listener(async_options_updated)
|
||||||
await async_options_updated(hass, config_entry)
|
await async_options_updated(hass, config_entry)
|
||||||
@ -83,4 +110,8 @@ async def async_options_updated(hass: HomeAssistant, config_entry: ConfigEntry)
|
|||||||
"""Triggered by config entry options updates."""
|
"""Triggered by config entry options updates."""
|
||||||
account: StarlineAccount = hass.data[DOMAIN][config_entry.entry_id]
|
account: StarlineAccount = hass.data[DOMAIN][config_entry.entry_id]
|
||||||
scan_interval = config_entry.options.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
|
scan_interval = config_entry.options.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
|
||||||
|
scan_obd_interval = config_entry.options.get(
|
||||||
|
CONF_SCAN_OBD_INTERVAL, DEFAULT_SCAN_OBD_INTERVAL
|
||||||
|
)
|
||||||
account.set_update_interval(scan_interval)
|
account.set_update_interval(scan_interval)
|
||||||
|
account.set_update_obd_interval(scan_obd_interval)
|
||||||
|
@ -15,6 +15,7 @@ from .const import (
|
|||||||
DATA_SLNET_TOKEN,
|
DATA_SLNET_TOKEN,
|
||||||
DATA_USER_ID,
|
DATA_USER_ID,
|
||||||
DEFAULT_SCAN_INTERVAL,
|
DEFAULT_SCAN_INTERVAL,
|
||||||
|
DEFAULT_SCAN_OBD_INTERVAL,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,17 +28,19 @@ class StarlineAccount:
|
|||||||
self._hass: HomeAssistant = hass
|
self._hass: HomeAssistant = hass
|
||||||
self._config_entry: ConfigEntry = config_entry
|
self._config_entry: ConfigEntry = config_entry
|
||||||
self._update_interval: int = DEFAULT_SCAN_INTERVAL
|
self._update_interval: int = DEFAULT_SCAN_INTERVAL
|
||||||
|
self._update_obd_interval: int = DEFAULT_SCAN_OBD_INTERVAL
|
||||||
self._unsubscribe_auto_updater: Optional[Callable] = None
|
self._unsubscribe_auto_updater: Optional[Callable] = None
|
||||||
|
self._unsubscribe_auto_obd_updater: Optional[Callable] = None
|
||||||
self._api: StarlineApi = StarlineApi(
|
self._api: StarlineApi = StarlineApi(
|
||||||
config_entry.data[DATA_USER_ID], config_entry.data[DATA_SLNET_TOKEN]
|
config_entry.data[DATA_USER_ID], config_entry.data[DATA_SLNET_TOKEN]
|
||||||
)
|
)
|
||||||
|
|
||||||
def _check_slnet_token(self) -> None:
|
def _check_slnet_token(self, interval: int) -> None:
|
||||||
"""Check SLNet token expiration and update if needed."""
|
"""Check SLNet token expiration and update if needed."""
|
||||||
now = datetime.now().timestamp()
|
now = datetime.now().timestamp()
|
||||||
slnet_token_expires = self._config_entry.data[DATA_EXPIRES]
|
slnet_token_expires = self._config_entry.data[DATA_EXPIRES]
|
||||||
|
|
||||||
if now + self._update_interval > slnet_token_expires:
|
if now + interval > slnet_token_expires:
|
||||||
self._update_slnet_token()
|
self._update_slnet_token()
|
||||||
|
|
||||||
def _update_slnet_token(self) -> None:
|
def _update_slnet_token(self) -> None:
|
||||||
@ -64,9 +67,14 @@ class StarlineAccount:
|
|||||||
|
|
||||||
def _update_data(self):
|
def _update_data(self):
|
||||||
"""Update StarLine data."""
|
"""Update StarLine data."""
|
||||||
self._check_slnet_token()
|
self._check_slnet_token(self._update_interval)
|
||||||
self._api.update()
|
self._api.update()
|
||||||
|
|
||||||
|
def _update_obd_data(self):
|
||||||
|
"""Update StarLine OBD data."""
|
||||||
|
self._check_slnet_token(self._update_obd_interval)
|
||||||
|
self._api.update_obd()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def api(self) -> StarlineApi:
|
def api(self) -> StarlineApi:
|
||||||
"""Return the instance of the API."""
|
"""Return the instance of the API."""
|
||||||
@ -76,6 +84,10 @@ class StarlineAccount:
|
|||||||
"""Update StarLine data."""
|
"""Update StarLine data."""
|
||||||
await self._hass.async_add_executor_job(self._update_data)
|
await self._hass.async_add_executor_job(self._update_data)
|
||||||
|
|
||||||
|
async def update_obd(self, unused=None):
|
||||||
|
"""Update StarLine OBD data."""
|
||||||
|
await self._hass.async_add_executor_job(self._update_obd_data)
|
||||||
|
|
||||||
def set_update_interval(self, interval: int) -> None:
|
def set_update_interval(self, interval: int) -> None:
|
||||||
"""Set StarLine API update interval."""
|
"""Set StarLine API update interval."""
|
||||||
_LOGGER.debug("Setting update interval: %ds", interval)
|
_LOGGER.debug("Setting update interval: %ds", interval)
|
||||||
@ -88,12 +100,27 @@ class StarlineAccount:
|
|||||||
self._hass, self.update, delta
|
self._hass, self.update, delta
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def set_update_obd_interval(self, interval: int) -> None:
|
||||||
|
"""Set StarLine API OBD update interval."""
|
||||||
|
_LOGGER.debug("Setting OBD update interval: %ds", interval)
|
||||||
|
self._update_obd_interval = interval
|
||||||
|
if self._unsubscribe_auto_obd_updater is not None:
|
||||||
|
self._unsubscribe_auto_obd_updater()
|
||||||
|
|
||||||
|
delta = timedelta(seconds=interval)
|
||||||
|
self._unsubscribe_auto_obd_updater = async_track_time_interval(
|
||||||
|
self._hass, self.update_obd, delta
|
||||||
|
)
|
||||||
|
|
||||||
def unload(self):
|
def unload(self):
|
||||||
"""Unload StarLine API."""
|
"""Unload StarLine API."""
|
||||||
_LOGGER.debug("Unloading StarLine API.")
|
_LOGGER.debug("Unloading StarLine API.")
|
||||||
if self._unsubscribe_auto_updater is not None:
|
if self._unsubscribe_auto_updater is not None:
|
||||||
self._unsubscribe_auto_updater()
|
self._unsubscribe_auto_updater()
|
||||||
self._unsubscribe_auto_updater = None
|
self._unsubscribe_auto_updater = None
|
||||||
|
if self._unsubscribe_auto_obd_updater is not None:
|
||||||
|
self._unsubscribe_auto_obd_updater()
|
||||||
|
self._unsubscribe_auto_obd_updater = None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def device_info(device: StarlineDevice) -> Dict[str, Any]:
|
def device_info(device: StarlineDevice) -> Dict[str, Any]:
|
||||||
@ -140,3 +167,8 @@ class StarlineAccount:
|
|||||||
"autostart": device.car_state.get("r_start"),
|
"autostart": device.car_state.get("r_start"),
|
||||||
"ignition": device.car_state.get("run"),
|
"ignition": device.car_state.get("run"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def errors_attrs(device: StarlineDevice) -> Dict[str, Any]:
|
||||||
|
"""Attributes for errors sensor."""
|
||||||
|
return {"errors": device.errors.get("errors")}
|
||||||
|
@ -13,6 +13,8 @@ CONF_CAPTCHA_CODE = "captcha_code"
|
|||||||
|
|
||||||
CONF_SCAN_INTERVAL = "scan_interval"
|
CONF_SCAN_INTERVAL = "scan_interval"
|
||||||
DEFAULT_SCAN_INTERVAL = 180 # in seconds
|
DEFAULT_SCAN_INTERVAL = 180 # in seconds
|
||||||
|
CONF_SCAN_OBD_INTERVAL = "scan_obd_interval"
|
||||||
|
DEFAULT_SCAN_OBD_INTERVAL = 10800 # 3 hours in seconds
|
||||||
|
|
||||||
ERROR_AUTH_APP = "error_auth_app"
|
ERROR_AUTH_APP = "error_auth_app"
|
||||||
ERROR_AUTH_USER = "error_auth_user"
|
ERROR_AUTH_USER = "error_auth_user"
|
||||||
@ -25,3 +27,4 @@ DATA_EXPIRES = "expires"
|
|||||||
|
|
||||||
SERVICE_UPDATE_STATE = "update_state"
|
SERVICE_UPDATE_STATE = "update_state"
|
||||||
SERVICE_SET_SCAN_INTERVAL = "set_scan_interval"
|
SERVICE_SET_SCAN_INTERVAL = "set_scan_interval"
|
||||||
|
SERVICE_SET_SCAN_OBD_INTERVAL = "set_scan_obd_interval"
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
"name": "StarLine",
|
"name": "StarLine",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/starline",
|
"documentation": "https://www.home-assistant.io/integrations/starline",
|
||||||
"requirements": ["starline==0.1.3"],
|
"requirements": ["starline==0.1.5"],
|
||||||
"codeowners": ["@anonym-tsk"]
|
"codeowners": ["@anonym-tsk"]
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
"""Reads vehicle status from StarLine API."""
|
"""Reads vehicle status from StarLine API."""
|
||||||
from homeassistant.components.sensor import DEVICE_CLASS_TEMPERATURE
|
from homeassistant.components.sensor import DEVICE_CLASS_TEMPERATURE
|
||||||
from homeassistant.const import PERCENTAGE, TEMP_CELSIUS, VOLT
|
from homeassistant.const import (
|
||||||
|
LENGTH_KILOMETERS,
|
||||||
|
PERCENTAGE,
|
||||||
|
TEMP_CELSIUS,
|
||||||
|
VOLT,
|
||||||
|
VOLUME_LITERS,
|
||||||
|
)
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.icon import icon_for_battery_level, icon_for_signal_level
|
from homeassistant.helpers.icon import icon_for_battery_level, icon_for_signal_level
|
||||||
|
|
||||||
@ -14,6 +20,9 @@ SENSOR_TYPES = {
|
|||||||
"ctemp": ["Interior Temperature", DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, None],
|
"ctemp": ["Interior Temperature", DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, None],
|
||||||
"etemp": ["Engine Temperature", DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, None],
|
"etemp": ["Engine Temperature", DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, None],
|
||||||
"gsm_lvl": ["GSM Signal", None, PERCENTAGE, None],
|
"gsm_lvl": ["GSM Signal", None, PERCENTAGE, None],
|
||||||
|
"fuel": ["Fuel Volume", None, None, "mdi:fuel"],
|
||||||
|
"errors": ["OBD Errors", None, None, "mdi:alert-octagon"],
|
||||||
|
"mileage": ["Mileage", None, LENGTH_KILOMETERS, "mdi:counter"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -73,6 +82,12 @@ class StarlineSensor(StarlineEntity, Entity):
|
|||||||
return self._device.temp_engine
|
return self._device.temp_engine
|
||||||
if self._key == "gsm_lvl":
|
if self._key == "gsm_lvl":
|
||||||
return self._device.gsm_level_percent
|
return self._device.gsm_level_percent
|
||||||
|
if self._key == "fuel" and self._device.fuel:
|
||||||
|
return self._device.fuel.get("val")
|
||||||
|
if self._key == "errors" and self._device.errors:
|
||||||
|
return self._device.errors.get("val")
|
||||||
|
if self._key == "mileage" and self._device.mileage:
|
||||||
|
return self._device.mileage.get("val")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -80,6 +95,12 @@ class StarlineSensor(StarlineEntity, Entity):
|
|||||||
"""Get the unit of measurement."""
|
"""Get the unit of measurement."""
|
||||||
if self._key == "balance":
|
if self._key == "balance":
|
||||||
return self._device.balance.get("currency") or "₽"
|
return self._device.balance.get("currency") or "₽"
|
||||||
|
if self._key == "fuel":
|
||||||
|
type_value = self._device.fuel.get("type")
|
||||||
|
if type_value == "percents":
|
||||||
|
return PERCENTAGE
|
||||||
|
if type_value == "litres":
|
||||||
|
return VOLUME_LITERS
|
||||||
return self._unit
|
return self._unit
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -94,4 +115,6 @@ class StarlineSensor(StarlineEntity, Entity):
|
|||||||
return self._account.balance_attrs(self._device)
|
return self._account.balance_attrs(self._device)
|
||||||
if self._key == "gsm_lvl":
|
if self._key == "gsm_lvl":
|
||||||
return self._account.gsm_attrs(self._device)
|
return self._account.gsm_attrs(self._device)
|
||||||
|
if self._key == "errors":
|
||||||
|
return self._account.errors_attrs(self._device)
|
||||||
return None
|
return None
|
||||||
|
@ -8,3 +8,10 @@ set_scan_interval:
|
|||||||
scan_interval:
|
scan_interval:
|
||||||
description: Update frequency (in seconds).
|
description: Update frequency (in seconds).
|
||||||
example: 180
|
example: 180
|
||||||
|
set_scan_obd_interval:
|
||||||
|
description: >
|
||||||
|
Set OBD info update frequency.
|
||||||
|
fields:
|
||||||
|
scan_interval:
|
||||||
|
description: Update frequency (in seconds).
|
||||||
|
example: 10800
|
||||||
|
@ -2100,7 +2100,7 @@ sqlalchemy==1.3.22
|
|||||||
srpenergy==1.3.2
|
srpenergy==1.3.2
|
||||||
|
|
||||||
# homeassistant.components.starline
|
# homeassistant.components.starline
|
||||||
starline==0.1.3
|
starline==0.1.5
|
||||||
|
|
||||||
# homeassistant.components.starlingbank
|
# homeassistant.components.starlingbank
|
||||||
starlingbank==3.2
|
starlingbank==3.2
|
||||||
|
@ -1043,7 +1043,7 @@ sqlalchemy==1.3.22
|
|||||||
srpenergy==1.3.2
|
srpenergy==1.3.2
|
||||||
|
|
||||||
# homeassistant.components.starline
|
# homeassistant.components.starline
|
||||||
starline==0.1.3
|
starline==0.1.5
|
||||||
|
|
||||||
# homeassistant.components.statsd
|
# homeassistant.components.statsd
|
||||||
statsd==3.2.1
|
statsd==3.2.1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user