Skip to content

Commit

Permalink
Official prices for BE/FR/LU from Carbu.com, #37
Browse files Browse the repository at this point in the history
  • Loading branch information
myTselection committed Dec 22, 2023
1 parent d054838 commit cbf6597
Show file tree
Hide file tree
Showing 3 changed files with 257 additions and 44 deletions.
2 changes: 1 addition & 1 deletion custom_components/carbu_com/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
"iot_class": "cloud_polling",
"issue_tracker": "https://github.com/myTselection/carbu_com/issues",
"requirements": ["bs4","requests","ratelimit"],
"version": "8.1.1"
"version": "9.0.0"
}
190 changes: 164 additions & 26 deletions custom_components/carbu_com/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,12 @@ async def dry_setup(hass, config_entry, async_add_devices):
sensors.append(sensorSuper95Neigh)

if country.lower() in ['be','fr','lu']:
sensorSuper95Prediction = ComponentFuelPredictionSensor(componentData, FuelType.SUPER95_Prediction)
sensorSuper95Prediction = ComponentFuelPredictionSensor(componentData, FuelType.SUPER95_PREDICTION)
# await sensorSuper95Prediction.async_update()
sensors.append(sensorSuper95Prediction)
sensorSuper95Official = ComponentFuelOfficialSensor(componentData, FuelType.SUPER95_OFFICIAL_E10)
# await sensorSuper95Official.async_update()
sensors.append(sensorSuper95Official)


if super98:
Expand All @@ -107,6 +110,12 @@ async def dry_setup(hass, config_entry, async_add_devices):
# await sensorSuper95Neigh.async_update()
sensors.append(sensorSuper98Neigh)

if country.lower() in ['be','fr','lu']:
sensorSuper98OfficialE10 = ComponentFuelOfficialSensor(componentData, FuelType.SUPER98_OFFICIAL_E10)
sensors.append(sensorSuper98OfficialE10)
sensorSuper98OfficialE5 = ComponentFuelOfficialSensor(componentData, FuelType.SUPER98_OFFICIAL_E5)
sensors.append(sensorSuper98OfficialE5)

if diesel:
sensorDiesel = ComponentPriceSensor(componentData, FuelType.DIESEL, postalcode, False, 0, station)
# await sensorDiesel.async_update()
Expand All @@ -125,6 +134,12 @@ async def dry_setup(hass, config_entry, async_add_devices):
sensorDieselPrediction = ComponentFuelPredictionSensor(componentData, FuelType.DIESEL_Prediction)
# await sensorDieselPrediction.async_update()
sensors.append(sensorDieselPrediction)
sensorDieselfficialB10 = ComponentFuelOfficialSensor(componentData, FuelType.DIESEL_OFFICIAL_B10)
sensors.append(sensorDieselfficialB10)
sensorDieselfficialB7 = ComponentFuelOfficialSensor(componentData, FuelType.DIESEL_OFFICIAL_B7)
sensors.append(sensorDieselfficialB7)
sensorDieselfficialXTL = ComponentFuelOfficialSensor(componentData, FuelType.DIESEL_OFFICIAL_XTL)
sensors.append(sensorDieselfficialXTL)

if lpg:
sensorLpg = ComponentPriceSensor(componentData, FuelType.LPG, postalcode, False, 0, station)
Expand All @@ -145,7 +160,7 @@ async def dry_setup(hass, config_entry, async_add_devices):
# await sensorOilstd.async_update()
sensors.append(sensorOilstd)

sensorOilstdPrediction = ComponentOilPredictionSensor(componentData, FuelType.OILSTD_Prediction, quantity)
sensorOilstdPrediction = ComponentOilPredictionSensor(componentData, FuelType.OILSTD_PREDICTION, quantity)
# await sensorOilstdPrediction.async_update()
sensors.append(sensorOilstdPrediction)

Expand All @@ -154,7 +169,7 @@ async def dry_setup(hass, config_entry, async_add_devices):
# await sensorOilextra.async_update()
sensors.append(sensorOilextra)

sensorOilextraPrediction = ComponentOilPredictionSensor(componentData, FuelType.OILEXTRA_Prediction, quantity)
sensorOilextraPrediction = ComponentOilPredictionSensor(componentData, FuelType.OILEXTRA_PREDICTION, quantity)
# await sensorOilextraPrediction.async_update()
sensors.append(sensorOilextraPrediction)

Expand Down Expand Up @@ -245,13 +260,19 @@ async def get_fuel_price_prediction_info(self, fuel_type: FuelType):
_LOGGER.debug(f"{NAME} getting prediction price_info {fuel_type.name_lowercase}")
prediction_info = await self._hass.async_add_executor_job(lambda: self._session.getFuelPrediction(fuel_type.code))
self._price_info[fuel_type] = prediction_info
_LOGGER.debug(f"{NAME} prediction_info {fuel_type.name_lowercase}Prediction {prediction_info}")
_LOGGER.debug(f"{NAME} prediction_info {fuel_type.name_lowercase} Prediction {prediction_info}")

async def get_fuel_price_official_info(self, fuel_type: FuelType):
_LOGGER.debug(f"{NAME} getting official price_info {fuel_type.name_lowercase}")
official_info = await self._hass.async_add_executor_job(lambda: self._session.getFuelOfficial(fuel_type.code))
self._price_info[fuel_type] = official_info
_LOGGER.debug(f"{NAME} prediction_info {fuel_type.name_lowercase} Official {official_info}")

async def get_oil_price_prediction_info(self):
_LOGGER.debug(f"{NAME} getting price_info oil prediction")
prediction_info = await self._hass.async_add_executor_job(lambda: self._session.getOilPrediction())
self._price_info[FuelType.OILSTD_Prediction] = prediction_info
self._price_info[FuelType.OILEXTRA_Prediction] = prediction_info
self._price_info[FuelType.OILSTD_PREDICTION] = prediction_info
self._price_info[FuelType.OILEXTRA_PREDICTION] = prediction_info
_LOGGER.debug(f"{NAME} prediction_info oilPrediction {prediction_info}")

async def getStationInfoFromPriceInfo(self, priceinfo, postalcode, fueltype, max_distance, filter, individual_station=""):
Expand Down Expand Up @@ -280,15 +301,22 @@ async def _forced_update(self):
if self._super95:
await self.get_fuel_price_info(FuelType.SUPER95)
if self._country.lower() in ['be','fr','lu']:
await self.get_fuel_price_prediction_info(FuelType.SUPER95_Prediction)
await self.get_fuel_price_prediction_info(FuelType.SUPER95_PREDICTION)
await self.get_fuel_price_official_info(FuelType.SUPER95_OFFICIAL_E10)

if self._super98:
await self.get_fuel_price_info(FuelType.SUPER98)
if self._country.lower() in ['be','fr','lu']:
await self.get_fuel_price_official_info(FuelType.SUPER98_OFFICIAL_E10)
await self.get_fuel_price_official_info(FuelType.SUPER98_OFFICIAL_E5)

if self._diesel:
await self.get_fuel_price_info(FuelType.DIESEL)
if self._country.lower() in ['be','fr','lu']:
await self.get_fuel_price_prediction_info(FuelType.DIESEL_Prediction)
await self.get_fuel_price_official_info(FuelType.DIESEL_OFFICIAL_B10)
await self.get_fuel_price_official_info(FuelType.DIESEL_OFFICIAL_B7)
await self.get_fuel_price_official_info(FuelType.DIESEL_OFFICIAL_XTL)

if self._lpg:
await self.get_fuel_price_info(FuelType.LPG)
Expand Down Expand Up @@ -336,7 +364,7 @@ def unique_id(self):
@property
def name(self) -> str:
"""Return the name of the sensor."""
return self.unique_id
return self.unique_id.title()


class ComponentPriceSensor(Entity):
Expand Down Expand Up @@ -425,6 +453,8 @@ async def async_will_remove_from_hass(self):
@property
def icon(self) -> str:
"""Shows the correct icon for container."""
if self._isOil:
return "mdi:barrel"
return "mdi:gas-station"

@property
Expand All @@ -440,15 +470,15 @@ def unique_id(self) -> str:

@property
def name(self) -> str:
return self.unique_id
return self.unique_id.title()

@property
def extra_state_attributes(self) -> dict:
"""Return the state attributes."""
return {
ATTR_ATTRIBUTION: NAME,
"last update": self._last_update,
"fueltype": self._fueltype.name_lowercase,
"fueltype": self._fueltype.name_lowercase.title(),
"fuelname": self._fuelname,
"postalcode": self._postalcode,
"supplier": self._supplier,
Expand Down Expand Up @@ -497,7 +527,7 @@ def device_class(self):

@property
def friendly_name(self) -> str:
return self.unique_id
return self.unique_id.title()

class ComponentPriceNeighborhoodSensor(Entity):
def __init__(self, data, fueltype: FuelType, postalcode, max_distance):
Expand Down Expand Up @@ -584,15 +614,15 @@ def unique_id(self) -> str:

@property
def name(self) -> str:
return self.unique_id
return self.unique_id.title()

@property
def extra_state_attributes(self) -> dict:
"""Return the state attributes."""
return {
ATTR_ATTRIBUTION: self._supplier_brand,
"last update": self._last_update,
"fueltype": self._fueltype.name_lowercase,
"fueltype": self._fueltype.name_lowercase.title(),
"fuelname": self._fuelname,
"postalcode": self._postalcode,
"supplier": self._supplier,
Expand Down Expand Up @@ -644,7 +674,7 @@ def device_class(self):

@property
def friendly_name(self) -> str:
return self.unique_id
return self.unique_id.title()


class ComponentFuelPredictionSensor(Entity):
Expand Down Expand Up @@ -696,15 +726,15 @@ def unique_id(self) -> str:

@property
def name(self) -> str:
return self.unique_id
return self.unique_id.title()

@property
def extra_state_attributes(self) -> dict:
"""Return the state attributes."""
return {
ATTR_ATTRIBUTION: NAME,
"last update": self._last_update,
"fueltype": self._fueltype.name_lowercase.split('_')[0],
"fueltype": self._fueltype.name_lowercase.split('_')[0].title(),
"trend": f"{self._trend}%",
"date": self._date
}
Expand Down Expand Up @@ -738,8 +768,7 @@ def device_class(self):

@property
def friendly_name(self) -> str:
return self.unique_id

return self.unique_id.title()

class ComponentOilPredictionSensor(Entity):
def __init__(self, data, fueltype: FuelType, quantity):
Expand All @@ -753,6 +782,8 @@ def __init__(self, data, fueltype: FuelType, quantity):
self._price = None
self._trend = None
self._date = None
self._officialPriceToday = None
self._officialPriceTodayDate = None


@property
Expand Down Expand Up @@ -780,7 +811,7 @@ async def async_update(self):
tomorrowPrice = 0

for element in table:
if element.get("code") == code:
if element.get("code").lower() == code.lower():
self._fuelname = element.get("name")
if element.get("data")[1]:
todayPrice = element.get("data")[1].get("price")
Expand All @@ -792,9 +823,13 @@ async def async_update(self):

self._price = tomorrowPrice

self._trend = round(100 * ((tomorrowPrice - todayPrice) / todayPrice),3)
if todayPrice != 0:
self._trend = round(100 * ((tomorrowPrice - todayPrice) / todayPrice),3)
self._officialPriceToday = todayPrice

self._date = priceinfo.get("data").get("heads")[2].get("name")
if len(priceinfo.get("data").get("heads")) > 1:
self._date = priceinfo.get("data").get("heads")[2].get("name")
self._officialPriceTodayDate = priceinfo.get("data").get("heads")[1].get("name")



Expand All @@ -807,7 +842,7 @@ async def async_will_remove_from_hass(self):
@property
def icon(self) -> str:
"""Shows the correct icon for container."""
return "mdi:gas-station"
return "mdi:barrel"

@property
def unique_id(self) -> str:
Expand All @@ -820,18 +855,20 @@ def unique_id(self) -> str:

@property
def name(self) -> str:
return self.unique_id
return self.unique_id.title()

@property
def extra_state_attributes(self) -> dict:
"""Return the state attributes."""
return {
ATTR_ATTRIBUTION: NAME,
"last update": self._last_update,
"fueltype": self._fueltype.name_lowercase.split('_')[0],
"fueltype": self._fueltype.name_lowercase.split('_')[0].title(),
"fuelname": self._fuelname,
"price": f"{self._price}€",
"date": self._date,
"current official max price": f"{self._officialPriceToday} €/l",
"current official max price date": {self._officialPriceTodayDate},
"quantity": self._quantity
}

Expand Down Expand Up @@ -864,5 +901,106 @@ def device_class(self):

@property
def friendly_name(self) -> str:
return self.unique_id

return self.unique_id.title()

class ComponentFuelOfficialSensor(Entity):
def __init__(self, data, fueltype):
self._data = data
self._fueltype = fueltype


self._fuelname = None
self._last_update = None
self._price = None
self._date = None
self._priceNext = None
self._dateNext = None


@property
def state(self):
"""Return the state of the sensor."""
return self._price

async def async_update(self):
await self._data.update()
self._last_update = self._data._lastupdate

priceinfo = self._data._price_info.get(self._fueltype)
# _LOGGER.debug(f"official priceinfo: {priceinfo}")

self._price=priceinfo.get(self._fueltype.nl_name)
self._date = priceinfo.get('Brandstof')

self._priceNext=priceinfo.get(self._fueltype.nl_name+"Next")
self._dateNext = priceinfo.get('BrandstofNext')



async def async_will_remove_from_hass(self):
"""Clean up after entity before removal."""
_LOGGER.info("async_will_remove_from_hass " + NAME)
self._data.clear_session()


@property
def icon(self) -> str:
"""Shows the correct icon for container."""
return "mdi:gas-station"

@property
def unique_id(self) -> str:
"""Return the name of the sensor."""
name = f"{NAME} {self._fueltype.name_lowercase.replace('_',' ')}"
# _LOGGER.debug(f"official name: {name}")
return (name)

@property
def name(self) -> str:
return self.unique_id.title()

@property
def extra_state_attributes(self) -> dict:
"""Return the state attributes."""
return {
ATTR_ATTRIBUTION: NAME,
"last update": self._last_update,
"fueltype": self._fueltype.name_lowercase.replace('_',' ').replace('Official ','').title(),
"price": f"{self._price}",
"date": self._date,
"price next": f"{self._priceNext}",
"date next": f"{self._dateNext}"
}


@property
def device_info(self) -> DeviceInfo:
"""Return the device info."""
# _LOGGER.debug(f"official device_info: {self._data.name}")
return DeviceInfo(
identifiers={
# Serial numbers are unique identifiers within a specific domain
(NAME, self._data.unique_id)
},
name=self._data.name,
manufacturer= NAME
)

@property
def unit(self) -> int:
"""Unit"""
return int

@property
def unit_of_measurement(self) -> str:
"""Return the unit of measurement this sensor expresses itself in."""
return "€/l"

@property
def device_class(self):
return SensorDeviceClass.MONETARY

@property
def friendly_name(self) -> str:
return self.unique_id.title()

Loading

0 comments on commit cbf6597

Please sign in to comment.