Giter Club home page Giter Club logo

mytselection / carbu_com Goto Github PK

View Code? Open in Web Editor NEW
18.0 5.0 6.0 813 KB

Home Assistant custom component HACS integration to Carbu.com site to compare and save on your actual fuel oil / heating oil (mazout) and fuel (diesel, super and lpg) purchases in Belgium, France and Luxembourg. Actual fuel prices per gasstation supported for Belgium, France, Luxembourg, Spain, Netherlands, Germany, Italy and US too!

License: MIT License

Python 100.00%
fuel-prices hacs home-assistant homeassistant price-tracker python

carbu_com's Introduction

HACS Default GitHub release GitHub repo size

GitHub issues GitHub last commit GitHub commit activity

Carbu.com Home Assistant integration

Carbu.com Home Assistant custom component. This custom component has been built from the ground up to bring Carbu.com & Mazout.com site data to compare and save on your fuel oil, diesel, lpg and Super prices and integrate this information into Home Assistant to help you towards a better follow up. This integration is built against the public website provided by Carbu.com and other similar sites. Sensors will be created for the currently cheapest gas station in a region (at location, within 5km and within 10km).

This integration is in no way affiliated with Carbu.com.

⚠️ Please don't report issues with this integration to Carbu or other platforms, they will not be able to support you.

Since R5.0, beta support for fuel prices in Germany (DE) has been added. City or postalcode can be provided as location.

Since R6.0, beta support for fuel prices in Italy (IT) has been added. Postalcode and town need to be provided.

Since R7.0, beta support for fuel prices in Netherlands (NL) has been added. Postalcode and town need to be provided.

Since R8.0, beta support for fuel prices in Spain (ES) has been added. Postalcode and town need to be provided.

Since R10.0, beta support for fuel prices in USA (US) has been added. Postalcode and town need to be provided.

Some discussion on this topic can be found within the Home Assistant community forum.

For electricity price expectations this Entso-E HACS integration can be used.

For cheapest Belgian gas and electricity contracts, prices and promotions, please check out my other integration MyEnergy

Installation

  • HACS: add url https://github.com/myTselection/carbu_com as custom repository (HACS > Integration > option: Custom Repositories)
    • Open your Home Assistant instance and open the repository inside the Home Assistant Community Store.
  • Restart Home Assistant
  • Add 'Carbu.com' integration via HA Settings > 'Devices and Services' > 'Integrations'
  • Provide country, postal code and select the desired sensors
    • The name of the town can be selected from the dropdown in the next step of the setup config flow. See carbu.com website for known towns and postal codes. (Only for BE/FR/LU)
    • An extra checkbox can be set to select a specific individual gas station. If set, a station can be selected in a dropdown with known gas stations (for which a price is available) close to the provided postalcode and town. No sensor for 5km and 10km will be created, only the price sensor for the individual selected station. The name of the sensor will contain the name of the supplier.
    • For Italy, Netherlands, Spain and US the town will be requested in the second step of the config flow
  • A filter on supplier brand name can be set (optional). If the filter match, the fuel station will be considered, else next will be searched. A python regex filter value be set
  • An option is avaible to show a logo (entity picture) with price or the original logo provided by the source. This is mainly visible when mapping the sensor on a map.
  • After setting up the integration, the configuration can be updated using the 'Configure' button of the integration. The usage of a station filter can be enabled and set, the usage of a template to set the 'friendly name' of each sensor type can be enabled and set and the usage of icons with price indication can be enabled or disabled.
    • The checkboxes are required since else clearing the text of the configuration was not recorded (HA bug?) and filter or templates could no longer be removed once set.
    • When setting a sensor 'friendly name' template, any sensor attribute can be used as a placeholder which will be replaced with the actual value. Eg: Price {fueltype} {fuelname} {supplier} could be used as a template for te Price sensor. All available attributes can be fetched using the 'Developer Tools' > 'States' > 'Attributes' view in HA or using the tables listed below.

Integration

Sensors

  • Sensor with lowest diesel and super sensor.carbu_com_[fueltype]_[postalcode]_price and lowest fuel oil sensor.carbu_com_[fueltype]_[postalcode]_[quantity]l_price Fuel oil only supported for BE/FR/LU
    Attribute Description
    State Price
    last update Timestamp info last retrieved from the carbu.com website. (There is a throttling of 1h active to limit requests. Restart HA to force update)
    fueltype Fuel type
    fuelname Full name of the fuel type
    postalcode Postalcode at which the price was retrieved
    supplier Name of the supplier of the fuel
    supplier_brand Brand name of the supplier (eg Shell, Texaco, ...) Not supported for DE
    url Url with details of the supplier
    entity_picture Url with the logo of the supplier
    address Address of the supplier
    city City of the supplier
    latitude Latitude of the supplier
    longitude Longitude of the supplier
    distance Distance to the supplier vs postal code ( Not supported for IT )
    date Date for the validity of the price
    quantity Quantity of fuel (only for fuel oil)
    score Score of the supplier
    id Unique id of the supplier
    suppliers Full json list of all suppliers with prices and detials found in neighbourhood around the postal code
  • Sensor with lowest diesel and super price in neighbourhood: sensor.carbu_com_[fueltype]_[postalcode]_[*]km for 5km and 10km
    Attribute Description
    State Price
    last update Timestamp info last retrieved from the carbu.com website. (There is a throttling of 1h active to limit requests. Restart HA to force update)
    fueltype Fuel type
    fuelname Full name of the fuel type
    postalcode Postalcode at which the price was retrieved
    supplier Name of the supplier of the fuel
    supplier_brand Brand name of the supplier (eg Shell, Texaco, ...) Not supported for DE
    url Url with details of the supplier
    entity_picture Url with the logo of the supplier
    address Address of the supplier
    city City of the supplier
    latitude Latitude of the supplier Not supported for DE
    longitude Longitude of the supplier Not supported for DE
    region Distand 5km or 10km around postal code in which cheapest prices is found
    distance Distance to the supplier vs postal code ( Not supported for IT )
    price diff Price difference between the cheapest found in region versus the local price
    price diff % Price difference in % between the cheapest found in region versus the local price
    price diff 30l Price difference for 30 liters between the cheapest found in region versus the local price
    date Date for the validity of the price
    quantity Quantity of fuel (only for fuel oil)
    score Score of the supplier
    id Unique id of the supplier
  • Sensor with official diesel and super price sensor.carbu_com_[fueltype]_officia_[fueltypecode], only supported for BE/FR/LU
    Attribute Description
    State Price
    last update Timestamp info last retrieved from the carbu.com website. (There is a throttling of 1h active to limit requests. Restart HA to force update)
    fueltype Fuel type
    price Price
    date Date for the validity of the price
    price next Next official price
    date next Date as of when the next price will be applicable
  • Sensor diesel and super prediction: sensor.carbu_com_[fueltype]_prediction Only supported for BE/FR/LU
    Attribute Description
    State Percentage of increase or decrease predicted for coming days
    last update Timestamp info last retrieved from the carbu.com website. (There is a throttling of 1h active to limit requests. Restart HA to force update)
    fueltype Fuel type
    trend Percentage of increase or decrease predicted for coming days
    date Date for the validity of the price
  • Sensor fuel oil prediction: sensor.carbu_com_[oiltype]_[quantity]l_prediction Only supported for BE/FR/LU
    Attribute Description
    State Percentage of increase or decrease predicted for coming days
    last update Timestamp info last retrieved from the carbu.com website. (There is a throttling of 1h active to limit requests. Restart HA to force update)
    fueltype Fuel type
    fuelname Full name of the fuel type
    trend Percentage of increase or decrease predicted for coming days
    price Predicted maximum price for type and quantity
    date Date for the validity of the price
    current official max price Currently official max price
    current official max price date Date of the currently official max price
    quantity Quantity for which the price is expected. Main difference between below or above 2000l

Services

A service carbu_com.get_lowest_fuel_price to get the lowest fuel price in the area of a postalcode is available. For a given fuel type and a distance in km, the lowest fuel price will be fetched and an event will be triggered with all the details found. Similar, the service carbu_com.get_lowest_fuel_price_coor can be called providing latitude and longitude coordinates instead of country, postalcode and town.

  • Event data returned, event name: carbu_com_lowest_fuel_price / carbu_com_lowest_fuel_price_coor
    Attribute Description
    fueltype Fuel type
    fuelname Full name of the fuel type
    postalcode Postalcode at which the price was retrieved
    supplier Name of the supplier of the fuel
    supplier_brand Brand name of the supplier (eg Shell, Texaco, ...) Not supported for DE
    url Url with details of the supplier
    entity_picture Url with the logo of the supplier
    address Address of the supplier
    city City of the supplier
    latitude Latitude of the supplier Not supported for DE
    longitude Longitude of the supplier Not supported for DE
    region Distand 5km or 10km around postal code in which cheapest prices is found
    distance Distance to the supplier vs postal code ( Not supported for IT )
    price diff Price difference between the cheapest found in region versus the local price
    price diff % Price difference in % between the cheapest found in region versus the local price
    price diff 30l Price difference for 30 liters between the cheapest found in region versus the local price
    date Date for the validity of the price
  • Example service call using iphone gecoded user location
    service: carbu_com.get_lowest_fuel_price
    data:
      fuel_type: diesel
      country: BE
      postalcode: "{{state_attr('sensor.iphone_geocoded_location','Postal Code')}}"
      town: "{{state_attr('sensor.iphone_geocoded_location','Locality')}}"
      max_distance: 5
      filter: Total
    
    
  • Example service call using iphone lat lon coordinates location
    service: carbu_com.get_lowest_fuel_price_coor
    data:
      fuel_type: diesel
      latitude: "{{state_attr('device_tracker.iphone','latitude')}}"
      longitude: "{{state_attr('device_tracker.iphone','longitude')}}"
      max_distance: 5
      filter: Total
    
    
  • Example automation triggered by event
    alias: Carbu event
    description: ""
    trigger:
      - platform: event
        event_type: carbu_com_lowest_fuel_price # or carbu_com_lowest_fuel_price_coor
    condition: []
    action:
      - service: notify.persistent_notification
        data:
          message: >-
            {{ trigger.event.data.supplier_brand }}: {{ trigger.event.data.price }}€
            at {{ trigger.event.data.distance }}km, {{ trigger.event.data.address }}
    mode: single
    
    

A service carbu_com.get_lowest_fuel_price_on_route (BETA) to get the lowest fuel price on the route in between two postal codes. Can be used for example to get the lowest price between your current location and your home, or between office and home etc. The lowest fuel price will be fetched and an event will be triggered with all the details found. The route is retrieved using Open Source Routing Machine. For performance and request limitations, 30% of the locations (evenly distributed) are used for which the best price of each on a distance of 3km is fetched. So no guarantee this would be the absolute best price. If too long routes are searched, it might get stuck because of the limitations of the quota of the free API. Similar, the service carbu_com.get_lowest_fuel_price_on_route_coor can be called providing latitude and longitude coordinates instead of country, postalcode and town.

  • Event data returned, Event name: carbu_com_lowest_fuel_price_on_route or carbu_com_lowest_fuel_price_on_route_coor
    Attribute Description
    fueltype Fuel type
    fuelname Full name of the fuel type
    postalcode Postalcode at which the price was retrieved
    supplier Name of the supplier of the fuel
    supplier_brand Brand name of the supplier (eg Shell, Texaco, ...) Not supported for DE
    url Url with details of the supplier
    entity_picture Url with the logo of the supplier
    address Address of the supplier
    city City of the supplier
    latitude Latitude of the supplier Not supported for DE
    longitude Longitude of the supplier Not supported for DE
    region Distand 5km or 10km around postal code in which cheapest prices is found
    distance Distance to the supplier vs postal code ( Not supported for IT )
    price diff Price difference between the cheapest found in region versus the local price ( Not supported for IT )
    price diff % Price difference in % between the cheapest found in region versus the local price ( Not supported for IT )
    price diff 30l Price difference for 30 liters between the cheapest found in region versus the local price
    date Date for the validity of the price
  • Example service call
    service: carbu_com.get_lowest_fuel_price_on_route
    data:
      fuel_type: diesel
      country: BE
      from_postalcode: 3620 #"{{state_attr('sensor.iphone_geocoded_location','Postal Code')}}"
      to_postalcode: 3660
    
    
  • Example service call using lat lon coordinates location
    service: carbu_com.get_lowest_fuel_price_on_route
    data:
      fuel_type: diesel
      from_latitude: 50.8503
      from_longitude: 4.3517
      to_latitude: 51.2194
      to_longitude: 4.4025
    
    
  • Example automation triggered by event
    alias: Carbu event
    description: ""
    trigger:
      - platform: event
        event_type: carbu_com_lowest_fuel_price_on_route # or carbu_com_lowest_fuel_price_on_route_coor
    condition: []
    action:
      - service: notify.persistent_notification
        data:
          message: >-
            {{ trigger.event.data.supplier_brand }}: {{ trigger.event.data.price }}€
            at {{ trigger.event.data.distance }}km, {{ trigger.event.data.address }}
    mode: single
    
    

Status

Still some optimisations are planned, see Issues section in GitHub.

Technical pointers

The main logic and API connection related code can be found within source code Carbu.com/custom_components/Carbu.com:

All other files just contain boilerplat code for the integration to work wtihin HA or to have some constants/strings/translations.

If you would encounter some issues with this custom component, you can enable extra debug logging by adding below into your configuration.yaml:

logger:
  default: info
  logs:
     custom_components.carbu_com: debug

Example usage:

Gauge & Markdown

Click to show Mardown code example
type: vertical-stack
cards:
  - type: horizontal-stack
    cards:
      - type: markdown
        content: >
          ## Diesel

          <img
          src="{{state_attr('sensor.carbu_com_diesel_1000_5km','entity_picture')}}"
          width="40"/>
          [{{state_attr('sensor.carbu_com_diesel_1000_5km','supplier')}}]({{state_attr('sensor.carbu_com_diesel_1000_5km','url')}} "{{state_attr('sensor.carbu_com_diesel_1000_5km','address')}}")

          #### Coming days: {% if
          states('sensor.carbu_com_diesel_prediction')|float < 0 %}<font
          color=green>{{states('sensor.carbu_com_diesel_prediction')}}%</font>{%
          else %}<font
          color=red>{{states('sensor.carbu_com_diesel_prediction')}}%</font>{%
          endif %}

          Best price in region (10km vs local):
          {{states('sensor.carbu_com_diesel_1000_10km')}},
          {{state_attr('sensor.carbu_com_diesel_1000_10km','supplier')}}
          {{state_attr('sensor.carbu_com_diesel_1000_10km','price diff %')}}
          ({{state_attr('sensor.carbu_com_diesel_1000_10km','price diff 30l')}}
          on 30l)

          Best price in region (10km vs 5km):
          {{states('sensor.carbu_com_diesel_1000_10km')}}€/l:
          {{state_attr('sensor.carbu_com_diesel_1000_10km','supplier')}}
          {{(states('sensor.carbu_com_diesel_1000_5km')|float -
          states('sensor.carbu_com_diesel_1000_10km')|float)|round(2)}}€
          ({{(states('sensor.carbu_com_diesel_1000_5km')|float -
          states('sensor.carbu_com_diesel_1000_10km')|float)|round(2)*30}}€ on
          30l)
      - type: markdown
        content: >-
          ## Mazout

          [{{state_attr('sensor.carbu_com_oilstd_1000_1000l_price','supplier')}}]({{state_attr('sensor.carbu_com_oilstd_1000_1000l_price','url')}})


          #### Coming days: {% if
          states('sensor.carbu_com_oilextra_1000l_prediction')|float < 0 %}<font
          color=green>{{states('sensor.carbu_com_oilextra_1000l_prediction')}}%</font>{%
          else %}<font
          color=red>{{states('sensor.carbu_com_oilextra_1000l_prediction')}}%</font>{%
          endif %}
  - type: horizontal-stack
    cards:
      - type: gauge
        entity: sensor.carbu_com_diesel_1000_5km
        min: 0
        max: 5
        needle: true
        unit: €/l
        name: Diesel prijs
        severity:
          green: 0
          yellow: 0.8
          red: 2
      - type: gauge
        entity: sensor.carbu_com_oilstd_1000_1000l_price
        min: 0
        max: 5
        needle: true
        unit: €/l
        name: Mazout prijs
        severity:
          green: 0
          yellow: 0.8
          red: 2
  - type: history-graph
    entities:
      - entity: sensor.carbu_com_diesel_1000_5km
        name: Diesel
      - entity: sensor.carbu_com_oilextra_1000_1000l_price
        name: Oil extra (per 1000l)
    hours_to_show: 500
    refresh_interval: 60
    

Markdown example card with prices for local, 5 & 10 km (by @bavala3010)

Click to show Mardown code example
type: vertical-stack
cards:
  - type: markdown
    content: >
      ## Super95 benzine

      #### Komende dagen: {% if
      states('sensor.carbu_com_super95_prediction')|float < 0 %}<font
      color=green>{{states('sensor.carbu_com_super95_prediction')}}%</font>{%
      else %}<font
      color=red>{{states('sensor.carbu_com_super95_prediction')}}%</font>{%
      endif %}
  - type: horizontal-stack
    cards:
      - type: markdown
        content: >
          #### <center>lokaal </center>


          <center><img
          src="{{state_attr('sensor.carbu_com_super95_3010_price','entity_picture')}}"
          width="45"/> </center>


          <center>


          [{{state_attr('sensor.carbu_com_super95_3010_price','supplier')}}]({{state_attr('sensor.carbu_com_super95_3010_5km','url')}})

          ### <center>{{states('sensor.carbu_com_super95_3010_price')}} €/l
      - type: markdown
        content: >
          #### <center>5 km</center>

          <center><img
          src="{{state_attr('sensor.carbu_com_super95_3010_5km','entity_picture')}}"
          width="45"/></center>


          <center>


          [{{state_attr('sensor.carbu_com_super95_3010_5km','supplier')}}]({{state_attr('sensor.carbu_com_super95_3010_5km','url')}})

          ### <center>{{states('sensor.carbu_com_super95_3010_5km')}} €/l

          Besparing tov lokaal =
          {{state_attr('sensor.carbu_com_super95_3010_5km','price diff %')}} of
          **{{state_attr('sensor.carbu_com_super95_3010_5km','price diff
          30l')}}** op 30l
      - type: markdown
        content: >
          #### <center>10 km

          <center><img
          src="{{state_attr('sensor.carbu_com_super95_3010_10km','entity_picture')}}"
          width="45"/></center>


          <center>


          [{{state_attr('sensor.carbu_com_super95_3010_10km','supplier')}}]({{state_attr('sensor.carbu_com_super95_3010_5km','url')}})

          ### <center>{{states('sensor.carbu_com_super95_3010_10km')}} €/l

          Besparing tov lokaal =
          {{state_attr('sensor.carbu_com_super95_3010_10km','price diff %')}} of
          **{{state_attr('sensor.carbu_com_super95_3010_10km','price diff
          30l')}}** op 30l


Markdown example card on map

The sensors contain latitude and longitude attributes and entity_picture attributes to allow the sensors to be shown nicely on a map

Click to show Mardown code example
type: map
entities:
  - entity: sensor.carbu_com_diesel_1000_price
  - entity: sensor.carbu_com_diesel_1000_5km
  - entity: sensor.carbu_com_diesel_1000_10km
title: carbu

carbu_com's People

Contributors

doudou14 avatar emerzh avatar mytselection avatar snyk-bot avatar viper5000 avatar zener82 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

carbu_com's Issues

warning insecure https request

Some warning appear during boot, to be analysed

WARNING (SyncWorker_12) [py.warnings] /usr/local/lib/python3.11/site-packages/urllib3/connectionpool.py:1061: InsecureRequestWarning: Unverified HTTPS request is being made to host 'api.carbu.com'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html#ssl-warnings
  warnings.warn(

[enhancement] Alternative markdown card with prices for local, 5 & 10 km

Carbu

First of all, thank you very much for this impressive and useful integration.
I have redesigned your markdown card a bit in order to display the local, 5 km and 10 km prices next to each other.
Just my small contribution to the community.

type: vertical-stack
cards:
  - type: markdown
    content: >
      ## Super95 benzine

      #### Komende dagen: {% if
      states('sensor.carbu_com_super95_prediction')|float < 0 %}<font
      color=green>{{states('sensor.carbu_com_super95_prediction')}}%</font>{%
      else %}<font
      color=red>{{states('sensor.carbu_com_super95_prediction')}}%</font>{%
      endif %}
  - type: horizontal-stack
    cards:
      - type: markdown
        content: >
          #### <center>lokaal </center>


          <center><img
          src="{{state_attr('sensor.carbu_com_super95_3010_price','logourl')}}"
          width="45"/> </center>


          <center>


          [{{state_attr('sensor.carbu_com_super95_3010_price','supplier')}}]({{state_attr('sensor.carbu_com_super95_3010_5km','url')}})

          ### <center>{{states('sensor.carbu_com_super95_3010_price')}} €/l
      - type: markdown
        content: >
          #### <center>5 km</center>

          <center><img
          src="{{state_attr('sensor.carbu_com_super95_3010_5km','logourl')}}"
          width="45"/></center>


          <center>


          [{{state_attr('sensor.carbu_com_super95_3010_5km','supplier')}}]({{state_attr('sensor.carbu_com_super95_3010_5km','url')}})

          ### <center>{{states('sensor.carbu_com_super95_3010_5km')}} €/l

          Besparing tov lokaal = 
          {{state_attr('sensor.carbu_com_super95_3010_5km','price diff %')}} of
          **{{state_attr('sensor.carbu_com_super95_3010_5km','price diff
          30l')}}** op 30l
      - type: markdown
        content: >
          #### <center>10 km

          <center><img
          src="{{state_attr('sensor.carbu_com_super95_3010_10km','logourl')}}"
          width="45"/></center>


          <center>


          [{{state_attr('sensor.carbu_com_super95_3010_10km','supplier')}}]({{state_attr('sensor.carbu_com_super95_3010_5km','url')}})

          ### <center>{{states('sensor.carbu_com_super95_3010_10km')}} €/l

          Besparing tov lokaal = 
          {{state_attr('sensor.carbu_com_super95_3010_10km','price diff %')}} of
          **{{state_attr('sensor.carbu_com_super95_3010_10km','price diff
          30l')}}** op 30l

Error while setting up carbu_com platform for sensor

Seen a few times now, thought it was a network hiccup but happens every once in a while.

Logger: homeassistant.components.sensor
Source: custom_components/carbu_com/utils.py:166
Integration: Sensor (documentation, issues)
First occurred: 22:36:56 (1 occurrences)
Last logged: 22:36:56

Error while setting up carbu_com platform for sensor
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 293, in _async_setup_platform
    await asyncio.shield(task)
  File "/config/custom_components/carbu_com/sensor.py", line 131, in async_setup_entry
    await dry_setup(hass, config, async_add_devices)
  File "/config/custom_components/carbu_com/sensor.py", line 60, in dry_setup
    await componentData._forced_update()
  File "/config/custom_components/carbu_com/sensor.py", line 223, in _forced_update
    prediction_info = await self._hass.async_add_executor_job(lambda: self._session.getFuelPrediction(self._diesel_fueltype_prediction_code))
  File "/usr/local/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/config/custom_components/carbu_com/sensor.py", line 223, in <lambda>
    prediction_info = await self._hass.async_add_executor_job(lambda: self._session.getFuelPrediction(self._diesel_fueltype_prediction_code))
  File "/config/custom_components/carbu_com/utils.py", line 166, in getFuelPrediction
    return value
UnboundLocalError: local variable 'value' referenced before assignment

Feature Request: Can we have a friendlier friendly_name?

Installed your Custom Component after the provider for Skons "dutch_gas_prices" apparently blocked access to their API.
Living literally on the border between Belgium and the Netherlands, I appreciate very much your components allows to query both sides of the border.
What I really liked about Skons' solution was that it allowed to create a "friendly_name" using any attribute returned in the sensor.
See Skons' DOCS.md for more information.

Thanks for the great work

Edit: I may have been shooting faster than my shadow .... blame it on being a newbie around here. Found this article in HA Configuration .... Would this be the way to provide a friendly name?

Wrong postcode search

Hi,

Great tool. I given my postcode 1082SG and Amsterdam. Those sensors are created:

sensor.carbu_com_super95_1082sg_10km
sensor.carbu_com_super95_1082sg_5km
sensor.carbu_com_super95_1082sg_price

But the name of sensors show this:

Carbu.com super95 1431WC 10km
Carbu.com super95 1431WC 5km
Carbu.com super95 1431WC price

1431WC is a total different postcode.

attribution: Carbu.com
last update: 2023-08-04T07:46:36.696720
fueltype: super95
fuelname: SUPER95
postalcode: 1431WC
supplier: Aalsmeer
supplier_brand: Tango
url: https://www.brandstof-zoeker.nl/station/tango-aalsmeer-2934
entity_picture: https://www.prezzibenzina.it/www2/marker.php?brand=TA&status=AP&price=2.009&certified=0&marker_type=1
address: Dreef 3
city: Aalsmeer
latitude: 52.256157
longitude: 4.765363
distance: 3.496622887109303km
date: 4 augustus 2023
quantity: 0
score: null
filter: 
country: NL
unit_of_measurement: €/l
device_class: monetary
icon: mdi:gas-station
friendly_name: Carbu.com super95 1431WC price

When I check brandstof zoeker then there are no hits on 1082SG. Maybe that is the issue? Better to make the sensor as: no info yet or something?

Warning: Detected code that calls async_forward_entry_setup

Logger: homeassistant.helpers.frame
Source: helpers/frame.py:151
First occurred: 00:28:51 (7 occurrences)
Last logged: 00:30:33

Detected code that calls async_forward_entry_setup for integration carbu_com with title: Diesel Retie and entry_id: 2c1e56b1a30143e38423615c975eb62c, during setup without awaiting async_forward_entry_setup, which can cause the setup lock to be released before the setup is done. This will stop working in Home Assistant 2025.1. Please report this issue.
Detected code that calls async_forward_entry_setup for integration carbu_com with title: Super 95 Meerhout and entry_id: 968a519797b373c44ddda8df1912a031, during setup without awaiting async_forward_entry_setup, which can cause the setup lock to be released before the setup is done. This will stop working in Home Assistant 2025.1. Please report this issue.

Price prediction date

I assume this is a bug since the attributes contain both a 'last update' and 'date' but they're the same. If would be more useful if the latter would indicate when the price will probably change.

Screenshot_20231101-222455.png

Platform carbu_com does not generate unique IDs

Logger: homeassistant.components.sensor
Source: helpers/entity_platform.py:610
Integration: Sensor (documentation, issues)
First occurred: 16:41:27 (2 occurrences)
Last logged: 16:41:27

ID Carbu.com super95 prediction already exists - ignoring sensor.carbu_com_super95_prediction
Platform carbu_com does not generate unique IDs. ID Carbu.com super95 official e10 already exists - ignoring sensor.carbu_com_super95_official_e10

Unique ids

Hi
Is it possible to add unique ids to the sensors? Ive tried to add multiple hubs in the carbu integration, so for instance 1 fuel station in NL and 2 in Belgiu 'maasmechelen with zipcode 3630, one in BE is succesfull, the other BE is not:

Platform carbu_com does not generate unique IDs. ID Carbu.com super95 prediction already exists

Platform carbu_com does not generate unique IDs. ID Carbu.com super95 3630 price already exists

Maybe you can add the name of the fuel station after the zipcode in the sensor id/name?

Thanks!

URL of 5km & 10km fuel station is NULL/Unknown

There seems to be an issue in the way URL's are generated for fuelstations. See screenshots. Maybe only an NL issue?
When I go to Developer Tools>States and compare the attributes for

  • sensor.carbu_com_super95_3731_ge_10km
  • sensor.carbu_com_super95_3731_ge_5km
  • sensor.carbu_com_super95_3731_ge_price

Only the sensor ending with _price has a valid URL for the fuelstation. The other ones have null as URL.
In this situation the cheapest station for all the 3 sensors are one and the same. So all three should have the same URL

Screenshot 2023-08-06 at 10 40 29 Screenshot 2023-08-06 at 10 40 00 Screenshot 2023-08-06 at 10 39 42

PostalCode read incorrectly from JSON

While checking the state of the entities of Carbu, it caught my eye that the postal code for Dutch gasstations is wrong. In my entity it reads:
postalcode: NoneNone

I checked utils.py and it reads pc_cijfer and pc_letter (

'postalcode': f"{block.get('station').get('pc_cijfer')}{block.get('station').get('pc_letter')}",
).

I checked the JSON response from the URL and now there is a postcode field in the JSON. I think that's the one you need to get.

fetch prices for selected stations

Thanks for this great integration!

Would it be possible to retrieve and display the price for one or two selected stations in home assistant?
I have a card for one brand (Total Energies) and two stations at about the same distance from my home. Their prices change often and sometimes show quite a nice difference...

Cheers,

Phil

Not possible to distinguish between areas with the same postal code

On carbu.com website you can enter a city/village by name, which will yield the correct result. In the integration it's not the case always.

E.g. imagine you live in Vissenaken (3300), a deelgemeente of Tienen, there is currently no way to get results for this location as it will take Tienen.

I believe at the moment it just takes whatever result comes first in the list, V comes after T, so you're out of luck ;-)

Service call error

Tried to call the following service:

service: carbu_com.get_lowest_fuel_price_on_route
data:
  fuel_type: diesel
  country: BE
  from_postalcode: '2470'
  to_postalcode: '2490'
  ors_api_key: '123xyz_real_key'

Getting the following errors:

This error originated from a custom integration.

Logger: homeassistant.helpers.script.websocket_api_script
Source: custom_components/carbu_com/utils.py:422
Integration: Carbu.com (documentation, issues)
First occurred: 14:41:48 (2 occurrences)
Last logged: 14:43:08

websocket_api script: Error executing script. Unexpected error for call_service at pos 1:
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 452, in _async_step
    await getattr(self, handler)()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 685, in _async_call_service_step
    await service_task
  File "/usr/src/homeassistant/homeassistant/core.py", line 1849, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1889, in _execute_service
    await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
  File "/config/custom_components/carbu_com/__init__.py", line 128, in handle_get_lowest_fuel_price_on_route
    station_info = await hass.async_add_executor_job(lambda: session.getPriceOnRoute(country, fuel_type, from_postalcode, to_postalcode, ors_api_key))
  File "/usr/local/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/config/custom_components/carbu_com/__init__.py", line 128, in <lambda>
    station_info = await hass.async_add_executor_job(lambda: session.getPriceOnRoute(country, fuel_type, from_postalcode, to_postalcode, ors_api_key))
  File "/config/custom_components/carbu_com/utils.py", line 422, in getPriceOnRoute
    assert from_location is not None
AssertionError

And

Logger: homeassistant.components.websocket_api.http.connection
Source: custom_components/carbu_com/utils.py:422
Integration: Home Assistant WebSocket API (documentation, issues)
First occurred: 14:41:48 (2 occurrences)
Last logged: 14:43:08

[546767443936] Error handling message: Unknown error (unknown_error) Jorim Tielemans from 127.0.0.1 (Mozilla/5.0 (Linux; Android 13; A063 Build/TKQ1.221220.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.53 Mobile Safari/537.36 Home Assistant/beta-10008-d81913b7-10008 (Android 13; A063))
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/decorators.py", line 26, in _handle_async_response
    await func(hass, connection, msg)
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 647, in handle_execute_script
    await script_obj.async_run(msg.get("variables"), context=context)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1533, in async_run
    await asyncio.shield(run.async_run())
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 410, in async_run
    await self._async_step(log_exceptions=False)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 454, in _async_step
    self._handle_exception(
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 477, in _handle_exception
    raise exception
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 452, in _async_step
    await getattr(self, handler)()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 685, in _async_call_service_step
    await service_task
  File "/usr/src/homeassistant/homeassistant/core.py", line 1849, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1889, in _execute_service
    await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
  File "/config/custom_components/carbu_com/__init__.py", line 128, in handle_get_lowest_fuel_price_on_route
    station_info = await hass.async_add_executor_job(lambda: session.getPriceOnRoute(country, fuel_type, from_postalcode, to_postalcode, ors_api_key))
  File "/usr/local/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/config/custom_components/carbu_com/__init__.py", line 128, in <lambda>
    station_info = await hass.async_add_executor_job(lambda: session.getPriceOnRoute(country, fuel_type, from_postalcode, to_postalcode, ors_api_key))
  File "/config/custom_components/carbu_com/utils.py", line 422, in getPriceOnRoute
    assert from_location is not None
AssertionError

State attributes for sensor.carbu_com* exceed maximum size of 16384 bytes

Version 1.0.0:

Logger: homeassistant.components.recorder.db_schema
Source: components/recorder/db_schema.py:491
Integration: Recorder (documentation, issues)
First occurred: 11:57:41 (8 occurrences)
Last logged: 11:57:44

State attributes for sensor.carbu_com_diesel_2440_price exceed maximum size of 16384 bytes. This can cause database performance issues; Attributes will not be stored
State attributes for sensor.carbu_com_diesel_2450_price exceed maximum size of 16384 bytes. This can cause database performance issues; Attributes will not be stored
State attributes for sensor.carbu_com_diesel_2470_price exceed maximum size of 16384 bytes. This can cause database performance issues; Attributes will not be stored
State attributes for sensor.carbu_com_diesel_2400_price exceed maximum size of 16384 bytes. This can cause database performance issues; Attributes will not be stored

Location as Entity

Hello 👋

Many thanks for this integration ... it looks really nice 👍

I was wondering if it's possible to put the stations on a map widget,
seems i can do that via en template sensor, but i guess it could be handy to add that for others too and put it directly in the integration.
What do you think ?

one fuel station is missing & markdown card question

Hi again!
I've got 2 things to mention:

Looks like this fuel station is missing / not listed anymore when I search for it in the dropdown (zip code 3630):

I also try to use the markdown card but I can't get this part to work:
image
The result stays on "none" but the prices differs between the two fuelstations, so I expect to see a result.
any ideas to get this fixed? is your example code still valid?

thanks!

Postal code not correct

Asking for postal 9100 and getting 2070 ?
[sensor.carbu_com_super98_9100_price] = Carbu.com super98 2070 price

region 5km & 10km on postal 9100 are correct

Showing a Fuelstation +30km away as the locale cheapest

Hi,

I've set this up for my current hometown (3650) and then it works perfect. yet for our new town (3960 Bree) it shows a fuelstation +30km away as the "cheapest local"
Bree fuel
here is the Carbu link for the Bocken NV station so you can see the adress : https://carbu.com/belgie/index.php/station/vrijlibre/maasmechelen/3630/2216

Would there be any way to add a check that if it's + xx km's away (free to setup or so I suppose) it will not show up in the integration.

Kind regards,

Jordy

Filter suppliers

It would be nice to have an option to pass in suppliers you want/don't want to be included in the search query

service: carbu_com.get_lowest_fuel_price

Hello, great job.
before this I scraped the sites also.

Quick Q:

I noticed that the service: carbu_com.get_lowest_fuel_price
is only working for BE?
because I only get data when i use like.

service: carbu_com.get_lowest_fuel_price
data: 
  fuel_type: diesel
  country: BE
  postalcode: 3620
  max_distance: 10

if I do

service: carbu_com.get_lowest_fuel_price
data: 
  fuel_type: diesel
  country: NL
  postalcode: 6051 JR
  max_distance: 10

I get errors

thanks for the answer ;)

ValueError: could not convert string to float: ''

Location "Lanaken" is not working properly. Upon inspecting I'm guessing it's using the wrong location ID (https://carbu.com//commonFunctions/getlocation/controller.getlocation_JSON.php?location=3620&SHRT=1)
BE_li_635 comes before BE_li_636 (the correct one) here, and the first one gets picked.
Maybe make both postal code and location ID required or at least configurable during setup to prevent this? While adding some documentation on how to find it ofc.

Logger: homeassistant.helpers.entity
Source: custom_components/carbu_com/sensor.py:440
Integration: Carbu.com (documentation, issues)
First occurred: 15:16:01 (4 occurrences)
Last logged: 15:16:01

Update for sensor.carbu_com_super95_3620_5km fails
Update for sensor.carbu_com_super95_3620_10km fails
Update for sensor.carbu_com_diesel_3620_5km fails
Update for sensor.carbu_com_diesel_3620_10km fails
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 550, in async_update_ha_state
await self.async_device_update()
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 755, in async_device_update
raise exc
File "/config/custom_components/carbu_com/sensor.py", line 440, in async_update
localPrice = float(self._priceinfo[0].get("price"))
ValueError: could not convert string to float: ''

Cheapest fuel price on route service

Service that is called with start and target location (or postal code) should determine all locations on the route and find the cheapest fuel price on the route.

carbu_com does not generate unique IDs

There should be a check in place to filter out existing places/postcoded.

Logger: homeassistant.components.sensor
Source: helpers/entity_platform.py:540
Integration: Sensor (documentation, issues)
First occurred: 9:50:13 AM (1 occurrences)
Last logged: 9:50:13 AM

Platform carbu_com does not generate unique IDs. ID Carbu.com diesel 2470 price already exists - ignoring sensor.carbu_com_diesel_2470_price

Service to get fuel price on custom postal code

Service that is called with args fuel type, country and postal code should give in return the cheapest fuel price and location.

Can be used to create an automation which compares the fuel cost of your current location with the fuel cost of your home location and notify you if (much) cheaper

How to get prices for a specific service station?

I really like this integration, but I was wondering if I could select the prices for a specific service station?
I've got several stations nearby, but they are geographically on opposite sides of town (one S, one N), the distance to my home is more or less the same.
It would be great if I could get the prices of both of them and put them next to each other.
Does the service supports the data-id from the source?

Another question more or less related.
I can call the service carbu_com.get_lowest_fuel_price but where is the response going? I just can't find the event in all the other events that are happening at the same time. So I also ask some advice on how to setup an automated service call which collects the results in a sensor so it can be exposed in a Lovelace dashboard.

Only pulls in 1 station per postcode

Setting up this integration only seems to set up a single device with a single entity.
Not sure if feature or bug.
I don't know what the logic here is: does it currently get the cheapest station, the first station in the list?
Feature request: would be nice if it adds all stations (entities) per postcode (device).

AttributeError: 'NoneType' object has no attribute 'lower'

Logger: homeassistant.components.sensor
Source: custom_components/carbu_com/utils.py:46
Integration: Sensor (documentation, issues)
First occurred: 2:19:52 AM (3 occurrences)
Last logged: 2:19:52 AM

Error while setting up carbu_com platform for sensor
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 304, in _async_setup_platform
    await asyncio.shield(task)
  File "/config/custom_components/carbu_com/sensor.py", line 132, in async_setup_entry
    await dry_setup(hass, config, async_add_devices)
  File "/config/custom_components/carbu_com/sensor.py", line 61, in dry_setup
    await componentData._forced_update()
  File "/config/custom_components/carbu_com/sensor.py", line 199, in _forced_update
    self._carbuLocationInfo = await self._hass.async_add_executor_job(lambda: self._session.convertPostalCode(self._postalcode, self._country, self._town))
  File "/usr/local/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/config/custom_components/carbu_com/sensor.py", line 199, in <lambda>
    self._carbuLocationInfo = await self._hass.async_add_executor_job(lambda: self._session.convertPostalCode(self._postalcode, self._country, self._town))
  File "/config/custom_components/carbu_com/utils.py", line 46, in convertPostalCode
    if info_dict["n"].lower() == town.lower() and info_dict["c"].lower() == country.lower() and info_dict["pc"] == postalcode:
AttributeError: 'NoneType' object has no attribute 'lower'

BE-9052 location becomes 9050 sensor

Configuring a 9052 BE postalcode for Carbu.com integration resulted in a sensor.carbu_com_super95_9052_5km sensor in HA, however the name of the sensor became "Carbu.Com Super95 9050 5Km".
So i'm wondering, is the bug in the naming (very small issue) or is the bug in the postalcode used in the algorithmes?

afbeelding

afbeelding

Trying to adjust radius

Thanks for this great integration. I use carbu.com quite often, nice to have it integrated in HA for further automation possibilities.

I would like to adjust the radius to 10 & 20 km. So I tried in sensor.py to change:

sensorSuper95Neigh = ComponentPriceNeighborhoodSensor(componentData, FuelType.SUPER95, postalcode, 5)
to
sensorSuper95Neigh = ComponentPriceNeighborhoodSensor(componentData, FuelType.SUPER95, postalcode, 10)

but I guess this would have been to simple.. in any case this action wasn't successful, any hints on how to adjust the radius?

Thinking further it would be a 'nice to have' add on for the integration to have this configuration option at the start. But no clue (yet) how to build this.

Again thanks a lot and keep up the good work!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.