Skip to content

Commit

Permalink
Merge pull request #66 from deler-aziz/fix_missing_unit
Browse files Browse the repository at this point in the history
Fix missing unit and add more fuel types for OKQ8
  • Loading branch information
deler-aziz authored Sep 14, 2024
2 parents 121021c + 237bbfe commit cd0863f
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 46 deletions.
2 changes: 1 addition & 1 deletion custom_components/fuel_prices_sweden/config_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def station_config_schema(step_id, config: dict = None) -> dict:
CONF_FUELTYPES, default=config.get(CONF_FUELTYPES)
): SelectSelector(
SelectSelectorConfig(
options=options,
options=[item["name"] for item in options],
multiple=True,
mode=SelectSelectorMode.LIST,
)
Expand Down
72 changes: 50 additions & 22 deletions custom_components/fuel_prices_sweden/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,32 +27,60 @@
DATA_STATION_ST1]
)
DATA_CIRCLEK_FUEL_TYPES = [
"miles 95",
"miles 98",
"miles+ 98",
"miles diesel",
"miles+ diesel",
"HVO100",
"Fordonsgas",
"E85",
{ "name": "miles 95", "unit": "l" },
{ "name": "miles 98", "unit": "l" },
{ "name": "miles+ 98", "unit": "l" },
{ "name": "miles diesel", "unit": "l" },
{ "name": "miles+ diesel", "unit": "l" },
{ "name": "HVO100", "unit": "l" },
{ "name": "Fordonsgas", "unit": "kg" },
{ "name": "E85", "unit": "l" }
]
DATA_INGO_FUEL_TYPES = [
{ "name": "Bensin 95", "unit": "l" },
{ "name": "Bensin 98 E5", "unit": "l" },
{ "name": "Diesel", "unit": "l" },
{ "name": "Etanol", "unit": "l" }
]
DATA_INGO_FUEL_TYPES = ["Bensin 95", "Bensin 98 E5", "Diesel", "Etanol"]
DATA_OKQ8_FUEL_TYPES = [
"GoEasy Bensin 95 (E10)",
"GoEasy Bensin Extra 98 (E5)",
"GoEasy Diesel (B7)",
"GoEasy Diesel Extra (B0)",
"Neste MY Förnybar Diesel (HVO100)",
"Etanol E85",
"Biogas Bas Sthlm & Uppsala län",
"Biogas Bas Övriga landet",
"Biogas 100 Sthlm & Uppsala län",
"Biogas 100 Övriga landet"
{ "name": "GoEasy Bensin 95 (E10)", "unit": "l" },
{ "name": "GoEasy Bensin Extra 98 (E5)", "unit": "l" },
{ "name": "GoEasy Diesel (B7)", "unit": "l" },
{ "name": "GoEasy Diesel Extra (B0)", "unit": "l" },
{ "name": "Neste MY Förnybar Diesel (HVO100)", "unit": "l" },
{ "name": "Etanol E85", "unit": "l" },
{ "name": "Biogas Bas Sthlm & Uppsala län", "unit": "kg" },
{ "name": "Biogas Bas Övriga landet", "unit": "kg" },
{ "name": "Biogas 100 Sthlm & Uppsala län", "unit": "kg" },
{ "name": "Biogas 100 Övriga landet", "unit": "kg" },
{ "name": "AdBlue", "unit": "l" },
{ "name": "Snabbladdning 150 kW", "unit": "kWh" },
{ "name": "Snabbladdning 50 kW", "unit": "kWh" },
]
DATA_PREEM_FUEL_TYPES = [
{ "name": "Preem Evolution Bensin 95", "unit": "l" },
{ "name": "Preem Evolution Diesel", "unit": "l" },
{ "name": "HVO100", "unit": "l" },
{ "name": "E85", "unit": "l" }
]
DATA_SHELL_FUEL_TYPES = [
{ "name": "Blyfri 95", "unit": "l" },
{ "name": "Blyfri 98", "unit": "l" },
{ "name": "V-Power", "unit": "l" },
{ "name": "CityDiesel", "unit": "l" },
{ "name": "E85", "unit": "l" },
{ "name": "Biogas", "unit": "kg" },
{ "name": "HVO", "unit": "l" }
]
DATA_ST1_FUEL_TYPES = [
{ "name": "Bensin 95", "unit": "l" },
{ "name": "Diesel RE+r", "unit": "l" },
{ "name": "Diesel", "unit": "l" },
{ "name": "E85", "unit": "l" },
{ "name": "Fordonsgas", "unit": "kg" }
]
DATA_PREEM_FUEL_TYPES = [ "Preem Evolution Bensin 95", "Preem Evolution Diesel", "HVO100", "E85"]
DATA_SHELL_FUEL_TYPES = [ "Blyfri 95", "Blyfri 98", "V-Power", "CityDiesel", "E85", "Biogas", "HVO"]
DATA_ST1_FUEL_TYPES = [ "Bensin 95", "Diesel RE+r", "Diesel", "E85", "Fordonsgas"]
DATA_TZ = "Europe/Stockholm"
DATA_CURRENCY = "Kr"

CONF_INTEGRATION_ID = "id"
CONF_UPDATE_INTERVAL = "update_interval"
Expand Down
5 changes: 2 additions & 3 deletions custom_components/fuel_prices_sweden/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import pytz

from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from .const import DOMAIN, DATA_TZ
from .const import DOMAIN, DATA_TZ, CONF_UPDATED_AT
from .fuel_pirce_provider import FuelPriceProvider

logger = logging.getLogger(f"custom_components.{DOMAIN}")
Expand All @@ -23,13 +23,12 @@ def __init__(self, hass, provider: FuelPriceProvider, update_interval: timedelta

)
self._provider = provider
self.updated_at = None

async def _async_update_data(self):
logger.debug("[coordinator][update_data] Started")
try:
data = await self._provider.async_fetch()
self.updated_at = datetime.now(TZ).strftime("%y/%m/%d, %H:%M:%S")
data.setdefault(CONF_UPDATED_AT, datetime.now(TZ).strftime("%y/%m/%d %H:%M:%S"))
logger.debug("[coordinator][update_data] Data fetch completed")
return data
except Exception as e: # pylint: disable=broad-exception-caught
Expand Down
27 changes: 12 additions & 15 deletions custom_components/fuel_prices_sweden/fuel_pirce_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
DATA_STATION_ST1_URL)
from .types import FuelPrice, FuelPriceFetchResult
from .misc import get_entity_station, get_entity_fuel_type
from .unit_helper import get_fuel_type_unit

logger = logging.getLogger(f"custom_components.{DOMAIN}")

Expand Down Expand Up @@ -41,57 +42,51 @@ async def async_fetch(self) -> FuelPriceFetchResult:
station[CONF_FUELTYPES]
)
for price in prices:
result.setdefault(price["name"], price["price"])
result.setdefault(price["name"], {"price": price["price"], "unit": price["unit"]})

return result

async def async_circle_k_prices(self, fuel_types) -> list[FuelPrice]:
"""Get Circle K station fuel prices."""
logger.debug("[fuel_prices_provider][circlek_prices] Started")
tables = await self._asyc_get_html_tables(DATA_STATION_CIRCLE_K_URL)
station_entity_name = get_entity_station("Circle K")
rows = tables[0].find_all("tr")
return self._extratct_fuel_type_price(rows, fuel_types, station_entity_name, 1, 2)
return self._extratct_fuel_type_price(rows, fuel_types, "Circle K", 1, 2)

async def async_ingo_prices(self, fuel_types) -> list[FuelPrice]:
"""Get Ingo station fuel prices."""
logger.debug("[fuel_prices_provider][ingo_prices] Started")
tables = await self._asyc_get_html_tables(DATA_STATION_INGO_URL)
station_entity_name = get_entity_station("Ingo")
rows = tables[0].find_all("tr")
return self._extratct_fuel_type_price(rows, fuel_types, station_entity_name, 1, 2)
return self._extratct_fuel_type_price(rows, fuel_types, "Ingo", 1, 2)

async def async_okq8_prices(self, fuel_types) -> list[FuelPrice]:
"""Get OKQ8 station fuel prices."""
logger.debug("[fuel_prices_provider][okq8_prices] Started")
tables = await self._asyc_get_html_tables(DATA_STATION_OKQ8_URL)
station_entity_name = get_entity_station("OKQ8")
rows = tables[0].find_all("tr")
return self._extratct_fuel_type_price(rows, fuel_types, station_entity_name, 0, 1)
return self._extratct_fuel_type_price(rows, fuel_types, "OKQ8", 0, 1)

async def async_preem_prices(self, fuel_types) -> list[FuelPrice]:
"""Get Preem station fuel prices."""
logger.debug("[fuel_prices_provider][preem_prices] Started")
tables = await self._asyc_get_html_tables(DATA_STATION_PREEM_URL)
station_entity_name = get_entity_station("Preem")
rows = tables[0].find_all("tr")
return self._extratct_fuel_type_price(rows, fuel_types, station_entity_name, 0, 1)
return self._extratct_fuel_type_price(rows, fuel_types, "Preem", 0, 1)

async def async_shell_prices(self, fuel_types) -> list[FuelPrice]:
"""Get Shell station fuel prices."""
logger.debug("[fuel_prices_provider][shell_prices] Started")
tables = await self._asyc_get_html_tables(DATA_STATION_SHELL_URL)
station_entity_name = get_entity_station("Shell")
rows = tables[0].find_all("tr")
return self._extratct_fuel_type_price(rows, fuel_types, station_entity_name, 0, 1)
return self._extratct_fuel_type_price(rows, fuel_types, "Shell", 0, 1)

async def async_st1_prices(self, fuel_types) -> list[FuelPrice]:
"""Get St1 station fuel prices."""
logger.debug("[fuel_prices_provider][st1_prices] Started")
tables = await self._asyc_get_html_tables(DATA_STATION_ST1_URL)
station_entity_name = get_entity_station("St1")
rows = tables[1].find_all("tr")
return self._extratct_fuel_type_price(rows, fuel_types, station_entity_name, 0, 1)
return self._extratct_fuel_type_price(rows, fuel_types, "St1", 0, 1)

async def _asyc_get_html_tables(self, url) -> ResultSet:
response = await self.hass.async_add_executor_job(self._get, url)
Expand All @@ -105,11 +100,12 @@ def _get(self, url) -> requests.Response:

def _extratct_fuel_type_price(self, rows,
fuel_types,
station_entity_name,
station_name,
name_col,
price_col)-> list[FuelPrice]:
result: list[FuelPrice] = []
logger.debug("[fuel_prices_provider][_extratct_fuel_type_price] Started")
station_entity_name = get_entity_station(station_name)
for row in rows:
th = row.find_all("th")
if th:
Expand All @@ -123,7 +119,8 @@ def _extratct_fuel_type_price(self, rows,
+ "_"
+ get_entity_fuel_type(self._sanitize_fuel_type_name(cells[name_col].text))
),
price=self._sanitize_fuel_type_price(cells[price_col].text)))
price=self._sanitize_fuel_type_price(cells[price_col].text),
unit=get_fuel_type_unit(station_name, fuel_type_name)))
return result

def _sanitize_fuel_type_name(self, name) -> str:
Expand Down
4 changes: 4 additions & 0 deletions custom_components/fuel_prices_sweden/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ def get_entity_fuel_type(name: str) -> str:
"""Get fuel type entity name."""
return _convert(name)

def get_attribute_station_name(name: str) -> str:
"""Get station name to as attribute."""
return name.upper().replace(" ", "")

def _convert(name: str) -> str:
name =_replace_non_letter_digit(name)
name = _replace_multi_underscore(name)
Expand Down
10 changes: 8 additions & 2 deletions custom_components/fuel_prices_sweden/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,19 @@ def icon(self):
@property
def state(self) -> float:
"""Return the state of the sensor and perform unit conversions, if needed."""
return self._coordinator.data.get(self._id) or 0
return self._coordinator.data.get(self._id)["price"] or 0

@property
def unit_of_measurement(self) -> str:
"""Return the unit of measurement this sensor."""
return self._coordinator.data.get(self._id)["unit"]


@property
def extra_state_attributes(self):
"""Get extra_state_attributes."""
attr = {}
attr[CONF_UPDATED_AT] = self._updated_at
attr[CONF_UPDATED_AT] = self._coordinator.data.get(CONF_UPDATED_AT)
return attr

@callback
Expand Down
3 changes: 2 additions & 1 deletion custom_components/fuel_prices_sweden/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class FuelPrice(TypedDict):

name: str
price: float
unit: str


FuelPriceFetchResult = dict[str, float]
FuelPriceFetchResult = dict[str, float, str]
27 changes: 27 additions & 0 deletions custom_components/fuel_prices_sweden/unit_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""Validator module."""
# ruff: noqa: F401
import sys
import logging
# pylint: disable=unused-import
from .const import (DOMAIN,
DATA_CURRENCY,
DATA_STATIONS_NAME,
DATA_CIRCLEK_FUEL_TYPES,
DATA_INGO_FUEL_TYPES,
DATA_OKQ8_FUEL_TYPES,
DATA_PREEM_FUEL_TYPES,
DATA_SHELL_FUEL_TYPES,
DATA_ST1_FUEL_TYPES)
from .misc import get_attribute_station_name

logger = logging.getLogger(f"custom_components.{DOMAIN}")

def get_fuel_type_unit(station_name, fuel_type) -> str:
"""Get fuel type unit."""
logger.debug("[unit_helper][get_fuel_type_unit] Started")
this_module = sys.modules[__name__]
fuel_units = {item["name"]: item["unit"] for item in getattr(this_module, "DATA_"+get_attribute_station_name(station_name)+"_FUEL_TYPES")}
unit = fuel_units.get(fuel_type, None)
logger.debug("[unit_helper][get_fuel_type_unit] Completed")
return None if unit is None else f"{DATA_CURRENCY}/{unit}"

5 changes: 3 additions & 2 deletions custom_components/fuel_prices_sweden/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
DATA_PREEM_FUEL_TYPES,
DATA_SHELL_FUEL_TYPES,
DATA_ST1_FUEL_TYPES)
from .misc import get_attribute_station_name

logger = logging.getLogger(f"custom_components.{DOMAIN}")

Expand All @@ -42,15 +43,15 @@ def validate_config(config: dict) -> bool:
station.get(CONF_NAME),
DATA_STATIONS_NAME)
return False
station_name:str = station.get(CONF_NAME).upper().replace(" ", "")
station_name:str = get_attribute_station_name(station.get(CONF_NAME))
fuel_types = station.get(CONF_FUELTYPES)
if fuel_types is None:
logger.error("[validator][validate_config] Invalid fuel_types for station: %s" ,
station.get(CONF_NAME))
return False

for fuel_type in fuel_types:
supported_fuel_types = getattr(this_module, "DATA_"+station_name+"_FUEL_TYPES")
supported_fuel_types = [item["name"] for item in getattr(this_module, "DATA_"+station_name+"_FUEL_TYPES")]
if fuel_type not in supported_fuel_types:
logger.error("[validator][validate_config] Invalid fuel_types for station: %s. Supported fuel types: %s"
, station.get(CONF_NAME),
Expand Down

0 comments on commit cd0863f

Please sign in to comment.