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:
Nikolay Vasilchuk
2021-01-13 22:44:24 +03:00
committed by GitHub
parent 7872e6caf8
commit eca6bc6a73
8 changed files with 105 additions and 9 deletions

View File

@ -8,10 +8,13 @@ from homeassistant.exceptions import ConfigEntryNotReady
from .account import StarlineAccount
from .const import (
CONF_SCAN_INTERVAL,
CONF_SCAN_OBD_INTERVAL,
DEFAULT_SCAN_INTERVAL,
DEFAULT_SCAN_OBD_INTERVAL,
DOMAIN,
PLATFORMS,
SERVICE_SET_SCAN_INTERVAL,
SERVICE_SET_SCAN_OBD_INTERVAL,
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."""
account = StarlineAccount(hass, config_entry)
await account.update()
await account.update_obd()
if not account.api.available:
raise ConfigEntryNotReady
@ -44,12 +48,23 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
)
async def async_set_scan_interval(call):
"""Service for set scan interval."""
"""Set scan interval."""
options = dict(config_entry.options)
options[CONF_SCAN_INTERVAL] = call.data[CONF_SCAN_INTERVAL]
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(
DOMAIN,
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)
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."""
account: StarlineAccount = hass.data[DOMAIN][config_entry.entry_id]
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_obd_interval(scan_obd_interval)

View File

@ -15,6 +15,7 @@ from .const import (
DATA_SLNET_TOKEN,
DATA_USER_ID,
DEFAULT_SCAN_INTERVAL,
DEFAULT_SCAN_OBD_INTERVAL,
DOMAIN,
)
@ -27,17 +28,19 @@ class StarlineAccount:
self._hass: HomeAssistant = hass
self._config_entry: ConfigEntry = config_entry
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_obd_updater: Optional[Callable] = None
self._api: StarlineApi = StarlineApi(
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."""
now = datetime.now().timestamp()
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()
def _update_slnet_token(self) -> None:
@ -64,9 +67,14 @@ class StarlineAccount:
def _update_data(self):
"""Update StarLine data."""
self._check_slnet_token()
self._check_slnet_token(self._update_interval)
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
def api(self) -> StarlineApi:
"""Return the instance of the API."""
@ -76,6 +84,10 @@ class StarlineAccount:
"""Update StarLine 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:
"""Set StarLine API update interval."""
_LOGGER.debug("Setting update interval: %ds", interval)
@ -88,12 +100,27 @@ class StarlineAccount:
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):
"""Unload StarLine API."""
_LOGGER.debug("Unloading StarLine API.")
if self._unsubscribe_auto_updater is not None:
self._unsubscribe_auto_updater()
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
def device_info(device: StarlineDevice) -> Dict[str, Any]:
@ -140,3 +167,8 @@ class StarlineAccount:
"autostart": device.car_state.get("r_start"),
"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")}

View File

@ -13,6 +13,8 @@ CONF_CAPTCHA_CODE = "captcha_code"
CONF_SCAN_INTERVAL = "scan_interval"
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_USER = "error_auth_user"
@ -25,3 +27,4 @@ DATA_EXPIRES = "expires"
SERVICE_UPDATE_STATE = "update_state"
SERVICE_SET_SCAN_INTERVAL = "set_scan_interval"
SERVICE_SET_SCAN_OBD_INTERVAL = "set_scan_obd_interval"

View File

@ -3,6 +3,6 @@
"name": "StarLine",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/starline",
"requirements": ["starline==0.1.3"],
"requirements": ["starline==0.1.5"],
"codeowners": ["@anonym-tsk"]
}

View File

@ -1,6 +1,12 @@
"""Reads vehicle status from StarLine API."""
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.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],
"etemp": ["Engine Temperature", DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, 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
if self._key == "gsm_lvl":
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
@property
@ -80,6 +95,12 @@ class StarlineSensor(StarlineEntity, Entity):
"""Get the unit of measurement."""
if self._key == "balance":
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
@property
@ -94,4 +115,6 @@ class StarlineSensor(StarlineEntity, Entity):
return self._account.balance_attrs(self._device)
if self._key == "gsm_lvl":
return self._account.gsm_attrs(self._device)
if self._key == "errors":
return self._account.errors_attrs(self._device)
return None

View File

@ -8,3 +8,10 @@ set_scan_interval:
scan_interval:
description: Update frequency (in seconds).
example: 180
set_scan_obd_interval:
description: >
Set OBD info update frequency.
fields:
scan_interval:
description: Update frequency (in seconds).
example: 10800

View File

@ -2100,7 +2100,7 @@ sqlalchemy==1.3.22
srpenergy==1.3.2
# homeassistant.components.starline
starline==0.1.3
starline==0.1.5
# homeassistant.components.starlingbank
starlingbank==3.2

View File

@ -1043,7 +1043,7 @@ sqlalchemy==1.3.22
srpenergy==1.3.2
# homeassistant.components.starline
starline==0.1.3
starline==0.1.5
# homeassistant.components.statsd
statsd==3.2.1