OilPal / Watchman Ultrasonic Oil Tank level reading for Home Assistant

Looked at it a few times, but havent gotten around to trying to port over from the legacy setup yet :frowning:

Am I getting the message correctly from the last couple of posts that the old code in the top post here won’t work on a new HA install

It works just fine upto and including 2023.1

Thanks very much. Means it’s user error on my part then.

If I’ve dropped the code into my configuration.yaml, updated the IP etc, then dropped in the card code but get “Entity not available: sensor.oilpaldata”

Are there dependencies I need to install or anything like that. If anyone has got a good guide in general to how this type of scraping works in HA I can take a look at that too instead of clogging up this thread?

If you check in Developer Tools/States, do any oilpal sensors exist?

Hi, just boarded the HA train, config.yaml wud not load the sensor data “scrappe not allowed”, and is disabled :thinking:
Please suggest any other way of integration if possible
Thank you

It’s because the scrape integration changed. I updated the first few llines of my sensor definition like this


scrape:
  - resource: http://192.168.10.8/diag.htm
    scan_interval: 60
    sensor:
    - name: OilPalData
      .....

Hope that helps

With all the changes and variations, would anyone be able to post an up to date yaml config for a horizontal cylinder tank. Myu understanding is cormatting etc has changed, and I have been trying to reformat/change my config and cant get it working.

Regards,
Eamon

Maybe someone can help if I give a bit more info. My config.yaml file throws an error when I add the oilpal scrape info. The error says
“Invalid config for [scrape]: [name] is an invalid option for [scrape]. Check: scrape->scrape->1->name. (See /config/configuration.yaml, line 18).”

and my config file is below. Would really appreciate some advice, stumped at the moment!

‘’’

Loads default set of integrations. Do not remove.

default_config:

Load frontend themes from the themes folder

frontend:
themes: !include_dir_merge_named themes

Text-to-speech

tts:

  • platform: google_translate

automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

Example configuration.yaml entry

scrape:

  • resource: http://192.168.100.243/diag.htm
    scan_interval: 60
    sensor:

  • name: “OilPalData”
    select: ‘table:nth-of-type(2) td:nth-of-type(5)’
    unit_of_measurement: ‘Litres’
    value_template: >-
    {% set modem_values = value.split(’ ') %}
    {% set tank_temp = modem_values[1] %}
    {% if tank_temp != “Data” %}
    {% set tank_depth = modem_values[0] | int %}
    {% set tank_dimentions = {

    “height”: 106,

    “width”: 67,

    “length”: 175,

    } %}

    {% set tank_volume = {

    “value”: (tank_dimentions.height - tank_depth) * tank_dimentions.length * tank_dimentions.width / 1000,

    } %}

    {{ tank_volume.value | round (0) }}

    {% else %}

    {% if states.sensor.oilpaldata.state == “” %}

    Waiting for first reading

    {% else %}

    {{ states.sensor.oilpaldata.state }}

    {% endif %}

    {% endif %}

mqtt:
switch:
- name: “Sunset”
unique_id: “Sunset”
state_topic: “comfort2/flag1”
command_topic: “comfort2/flag1/set”
availability_topic: “comfort2/alarm/online”
payload_on: “0” #logic is opposite, comfort announces only if flag16 is 0
payload_off: “1”
payload_available: “1”
payload_not_available: “0”
binary_sensor:
- name: “Front Door”
unique_id: “front door”
state_topic: “comfort2/input1”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “Kitchen Door”
unique_id: “Kitchen door”
state_topic: “comfort2/input2”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “Back Door”
unique_id: “Back door”
state_topic: “comfort2/input3”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “Office Door”
unique_id: “Office door”
state_topic: “comfort2/input4”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “Hall Motion”
unique_id: “Hall Motion”
state_topic: “comfort2/input5”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “Corridoor Motion”
unique_id: “Corridoor Motion”
state_topic: “comfort2/input6”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “Kitchen Motion”
unique_id: “Kitchen Motion”
state_topic: “comfort2/input7”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “Den Motion”
unique_id: “Den Motion”
state_topic: “comfort2/input8”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “Utility Motion”
unique_id: “Utility Motion”
state_topic: “comfort2/input9”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “Office Motion”
unique_id: “Office motion”
state_topic: “comfort2/input10”
payload_on: “1”
payload_off: “0”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
- name: “Bathroom Motion”
unique_id: “Bathroom Motion”
state_topic: “comfort2/input11”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “Ciaran Motion”
unique_id: “Ciaran Motion”
state_topic: “comfort2/input12”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “Guest Motion”
unique_id: “Guest Motion”
state_topic: “comfort2/input13”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “Master Bedroom Motion”
unique_id: “Master Bedroom Motion”
state_topic: “comfort2/input14”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “En Suite Motion”
unique_id: “En Suite Motion”
state_topic: “comfort2/input15”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “En Suite Door”
unique_id: “En Suite Door”
state_topic: “comfort2/input16”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “Dressing Room Door”
unique_id: “Dressing Room Door”
state_topic: “comfort2/input17”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “Kelly Motion”
unique_id: “Kelly Motion”
state_topic: “comfort2/input18”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “Living Room Motion”
unique_id: “Living Room Motion”
state_topic: “comfort2/input19”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
- name: “En Suite Door”
unique_id: “En Suite door”
state_topic: “comfort2/input24”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
payload_on: “1”
payload_off: “0”
alarm_control_panel:
- name: “Comfort Alarm”
unique_id: “Comfort Alarm”
state_topic: “comfort2/alarm”
command_topic: “comfort2/alarm/set”
availability_topic: “comfort2/alarm/online”
payload_available: “1”
payload_not_available: “0”
code: “1234” #code can be different from Comfort’s
‘’’

Got a notification that oil pal monitoring was ceasing as of end of dec, so asked them if they could provide details of my tank configuration, thought this might be interesting as it shows unuseable capacity etc to make things a bit more accurate.

Might be of use to anyone interested in making it more accurate.

Im too stupid to change this correctly. I get


with this

Lines 51 to 87 in your config need to be indented by a further 2 spaces. That should fix it.

@Wexfordman - Just saw your post and the info from Oilpal. It made me think that the calculation in the scrape code is not correct for your tank.

I have a cylindrical vertical tank, so the radius is constant and the sensor measures the height, so Pi x r² mulutplied by height gives me the volume.

But your cylindrical horizontal tank has a different area at each height, so the maths is more complex to get the volume - it’s not a linear relationship between height and volume.

The config you posted is assuming your tank is a rectangular tank - its just multiplying height by a fixed width and length.

This might help with the calculations:

Not sure how you then turn that into a value template…

Hope that helps.

Thank you. That cracked it. I can get on putting the right dimensions etc in now

Hmm. So I have the sensor now but its shows some wacky readings with a depth of -35184 litres. I can see why that is. My table is different in data entered to that above.

image

I suspect that 2725 is temperature and 45 is depth and I can see the temperature change on the sensor which makes sense as night is approaching. If that is correct I need to change select: ‘table:nth-of-type(2) td:nth-of-type(5)’ but to what as to my mind I am looking at the 2nd element of the 5th column. Or am I missing something (highly likely)

Thanks

If your sensor is different and you need the second (Aux) field, you need to change line 57 in your config (as per your image you posted)

from

{% set tank_depth = modem_values[0] | int %}

to

{% set tank_depth = modem_values[1] | int %}

Might be worth double checking your tank depth with a dipstick to confirm. I’ve had spurious readings before when the battery in the sensor was getting low. The measurement is cm from the sensor to the oil surface.

Thanks so much. That is looking more like it. I am starting to understand some of this at least. I will check the tank as you suggest and also correct the measurements to match my tank now its looking in the right ballpark. For the record for others I am using a Olive Oil monitor from eSmartmetrics which shows up on the diag webpage as a TEK608A device

Hi @c0rnflake
I have my OilPal sensor integrated into HA thanks to your script above but I’d love to enhance it like you have above using the graphs, estimated days left and battery level of the sensor.

Can you please share some details on how to enhance it?

Thanks very much!

I have just set up a new HA incidence again after using it in the past. I forgot how fiddly it can be and the configuration.yaml requiring very precise inputs to be registered, especially with those changes from 2022 the version of HA and how it needs the code it uses slightly differently I thought I’d help here with my vanilla updated version for others. Which seems to have been accepted and given me a reading, with those default values.

With the Oilpal app stopping working I needed to integrate something and it was great to see this. Thanks @c0rnflake for the original code and @PatrickT1 for guide to updating it.

I have a horizontal cylindrical tank so the maths changes quite a bit.

We need to know the radius and length of the tank, then if we know, with the sensor, the height of the oil in the bottom of the tank we should be able to calculate its volume.

I’m going to play with the code a bit and try to get things right and will update if I can see its working.

Below is the original script intended for a vertical cylinder oil tank (when tank type set to 1) and updated as little as possible to make it work with the latest version of home assistant, as below.

  • Core 2024.2.4
  • Frontend 20240207.1
# Sensors
scrape:
  - resource: http://192.168.0.7/diag.htm
    scan_interval: 60
    sensor:
    - name: OilPalData
      select: 'table:nth-of-type(2) td:nth-of-type(5)'
      unit_of_measurement: 'Litres'
      value_template: >-
        {% set modem_values = value.split(' ') %}
        {% set tank_temp = modem_values[1] %}
        {% if tank_temp != "Data" %}
          {% set tank_depth = modem_values[0] | int %}
          {% set tank_type = {
            "value": 1
          } %}
          {% set tank_dimentions = {
            "height": 125,
            "radius": 58.65,
            "width": 64,
            "length": 150,
          } %}
          {% set tank_area = {
            "value": (3.1472 * (tank_dimentions.radius * tank_dimentions.radius) * tank_dimentions.height) / 1000,
          } %}
          {% if tank_type.value == 1 %}
            {% set tank_volume = {
              "value": (tank_dimentions.height - tank_depth) * tank_area.value / 100,
            } %}
          {% else %}
            {% set tank_volume = {
              "value": (tank_dimentions.height - tank_depth) * tank_dimentions.length * tank_dimentions.width / 1000,
            } %}
          {% endif %}
          {{ tank_volume.value | round (0) }}
        {% else %}
          {% if states.sensor.oilpaldata.state == "" %}
            Waiting for first reading
          {% else %}
            {{ states.sensor.oilpaldata.state }}
          {% endif %}
        {% endif %}

It took me a little time but I think I have figured the code for a horizontal cylinder oil tank.

NB - I am in the UK and use the original oilpal sensor the same as the OP. Therefore scraped values might not be the same for your sensor if it was from a different manufacturer.

The math comes from the following website and I double checked my test code/math with various readings with their onsite calculator and they matched perfectly. https://www.mathsisfun.com/geometry/cylinder-horizontal-volume.html

A lot of the ideas for the code and what would work within HA without having to involve any python or extra addon programs for the trig came from the following other tread and thanks to @Petro

Also you should note most Horizontal tanks aren’t a perfect cylinder and have elliptical ends I used the following website and his excel spread sheet to compensate and try to get a better estimate - i.e. the length of my tank is 180cm so for its height this would only hold 2000L, however I know from the documentation it holds 2500L (which is quite a underestimate) so I increased the length to 220cm on the spread sheet to account for this and increase the overall volume until I hit 2500L (marked in pink below) and I think its probably a little more accurate for me. I’ll keep an eye on it though especially at fill times.

You’ll have to discover the IP address of your device yourself, via your router home page and perhaps its DCHP / LAN settings - once you find the ip address if you pop it into a web browser you should see the below if you click the sensor data link on the left.

Below is the code, which works fine with my vanilla home assistant setup as part of a TrueNAS App. I’ve not included a card as yet - as doing so can confuse things if you haven’t already added the below and made sure it appears within “settings” click, “devices and service” then “entities” then you have bigger issues to sort.

# Sensors
scrape:
#Edit below IP address to your oilpal/watchman sensor's IP address's sensor data page - this must be found via your home routers DHCP info.
  - resource: http://192.168.0.7/diag.htm
    scan_interval: 60
    sensor:
      - name: Estimated_Oil_Remaining
        unique_id: estimated_oil_remaining
        select: 'table:nth-of-type(2) td:nth-of-type(5)'
        unit_of_measurement: 'Litres'
        # units for a horizontal oil cylinder tank measured as height (of sensor from bottom of tank - which "should" be 2 times the radius but not always), radius and length which should be in cm - width isn't really involved for a horizonal cyclinder
        value_template: >-
          {% set modem_values = value.split(' ') %} {% set tank_temp = modem_values[1] %} {% if tank_temp != "Data" %}

            {% set tank_depth = modem_values[0] | int %}
            {% set tank_type = {
              "value": 1
            } %}
            {% set tank_dimentions = {
              "height": 120,
              "radius": 60,
              "width": 130,
              "length": 220,
            } %}
            {% set tank_area = {
              "value": tank_dimentions.radius ** 2 * acos((tank_dimentions.radius - (tank_dimentions.height - tank_depth)) / tank_dimentions.radius) - (tank_dimentions.radius - (tank_dimentions.height - tank_depth)) * sqrt(2 * tank_dimentions.radius * (tank_dimentions.height - tank_depth) - (tank_dimentions.height - tank_depth)**2),
            } %}
            {% if tank_type.value == 1 %}
              {% set tank_volume = {
                "value": (tank_dimentions.length * tank_area.value) / 1000,
              } %}
            {% else %}
              {% set tank_volume = {
                "value": (tank_dimentions.height - tank_depth) * tank_dimentions.length * tank_dimentions.width / 1000,
              } %}
            {% endif %}
            {{ tank_volume.value | round (0) }}
          {% else %}

            {% if states.sensor.oilpaldata.state == "" %}
              Waiting for first reading
            {% else %}
              {{ states.sensor.oilpaldata.state }}
            {% endif %}
          {% endif %}

Here’s a post of my login overview without having to even add any custom code for a card.

Screenshot 2024-03-01 085532

Here’s if I click the card the graph I get (the large ups and downs are all test results).