OilPal / Watchman Ultrasonic Oil Tank level reading for Home Assistant

I haven’t done anything for any stats, but as i store all the oilpal data in mariadb it shouldn’t be hard to pull 30 days worth of data, average that to get a daily usage amount and then divide the current tanks volume by the daily used value to get a rough days left.

But as you say there’s a few factors that could mess with that, a fill or a leak.

2 Likes

@PatrickT1

I’m going to assume you’re running Influx, if so, the following should expose 2 new sensors that will give you a 30 day average usage and days left.

In your configuration.yaml (or sensors.yaml) add the following under sensor:/platform: influxdb
(you won’t need the queries: line if it’s already there)

    queries:
    - name: OilPalData 1 Hour Ago
      unit_of_measurement: Litres
      value_template: '{{ value | round(0) }}'
      group_function: last
      where: '"entity_id" = ''oilpaldata'' and time < now() - 1h'
      measurement: '"Litres"'
      field: value
      database: homeassistant    
    - name: OilPalData 30 Days Ago
      unit_of_measurement: Litres
      group_function: mean
      where: '"entity_id" = ''oilpaldata'' and time < now() - 30d'
      measurement: '"Litres"'
      field: value
      database: homeassistant
      value_template: '{{ value | round(0) }}'

under sensor:/platform: template add the following
(you probably won’t need the sensors: line as it should already be there)

    sensors:
      oilpal30dayaverageusage:
        friendly_name: "OilPal 30 Day Average Usage"
        value_template: "{{ (((states.sensor.oilpaldata_30_days_ago.state | int) - (states.sensor.oilpaldata_1_hour_ago.state | int)) / 30) | round(0) }}"
      oilpaldaysleft:
        friendly_name: "OilPal Days Left"
        value_template: "{{ ((states.sensor.oilpaldata.state | int) / (states.sensor.oilpal30dayaverageusage.state | int)) | round(0) }}"

You should now be able to add an entities card and display the new sensors

type: entities
entities:
  - entity: sensor.oilpal30dayaverageusage
    name: Average Daily Usage (Litres)
    icon: mdi:oil-level
  - entity: sensor.oilpaldaysleft
    name: Days Left
    icon: mdi:calendar-clock

While you’re at it, you may also want to edit the following, as I’ve added a quicker update to the original script to update the oilpal value from influx if there has been no reading from the modem. The value is taken from the previous hour reading.

        {% if states.sensor.oilpaldata.state == "" %}
          {{ states.sensor.OilPalData_1_Hour_Ago.state }}
        {% else %}

Let me know how you get on and if this works as expected for you

Wow. Thanks for the effort @c0rnflake . I’m not yet running Influx, but you’ve given me lots to play with there.

I know the oilpal system used to have a fill alert and a theft alert where you’d get a notification if there was a sudden change in oil level. Do you have any idea if that gets triggered by data from the sensor itself (in one of those other data fields) or if that was calculated on the Web service?

Thanks again.

Hi @PatrickT1

In the TEK608 manual there is a statement

And the webserver provides what I’m assuming is this info

But I’ve absolutely no idea how to interpet the values or how often they change. I’m pretty sure that the FL is Fill and would only be populated when the tank is filled so it wouldn’t be practical to test that.

Thanks @c0rnflake - I think I’ll have to take the sensor off the tank and play with what data I can get it to report.

Thanks again for your help.

So the above posts gave me a little motivation to tinker with the original scipt. I’m now using the Apex Charts integration and have finally settled with the below chart and information. Once I’m 100% happy that everythings working as expected I’ll post the updates needed to reproduce this.

1 Like

Hi,

I have my oilpal up and running, but can’t seem to get the right dimensions reporting back. My oil tank is a horizontal cylinder type, and the dimensions are

95 cm (w) x 165 cm (l) x 95 cm (h)

Could someone tell me what settings I need to put in, it’s a horizontal cylinder type tank

in the configuration here

        {% set tank_type = {
          "value": 1
        } %}
        {% set tank_dimentions = {
          "height": 125,
          "radius": 58.65,
          "width": 64,
          "length": 150,
        } %}

change the tank type to 2, and put your dimensions in height, width, and length. If you keep the tank type as 1 you’ll get volume calculation for a cylindrical tank with height and radius as specified.

The height you need is from the floor of the tank to the sensor, which might be slightly less than the total height, depending on the sensor mounting position on your tank.

Hope that helps.

1 Like

sorry for the late reply, that helped, ths js very much.

I was wondering how this is going now,

Also if anyone has developed anything to check optimal time to buy , I was thinking if could check qty of tank needed and trend oil pricing , it could be an a nice automation to secure oil at best price.

The updates seem to be working just fine. Famous last words eh? :slight_smile:

As for the tracking you mentioned, I’ve had something similar running for a while now also. The problem is where to scrape the info from. As I’m in the UK, i’m scraping local suppliers for mine.

1 Like

Hi everyone, just wondering is this in HACS to pull down or what’s the easiest way of installing.

I think it’s a case of adding the code to the config file and creating a card on dashboard.

Probably also need to edit code for type of tank you have. The OP also is using apex cards from HACS he mentioned.

Just going to try it out myself once get sensor working again, my sensor seems to unpair itself from the modem every few months.

That looks good , do you correlate the two , oil level and price via some automation to alert that now is time to order or just eyeball them and order when looks good.

I’m just eyeballing it at the moment.

Still doing some testing. I’d be interested in converting what I have into an integration that could be easier to install/setup from the GUI.

If anyone has any suggestions on docs/how tos/youtube videos on where to start with that, that would be great.

Hi @c0rnflake. Many thanks for sharing your code - bringing my OilPal data into HA was always a goal of mine but I hadn’t a clue how to do it until your post!

So I’ve got the IP address of my OilPal modem and can connect to it via a browser no problem. My tank is rectangular and I also have the dimensions (l x w x h) - I also have the volume (1040 litres) as it’s printed on a label on the tank!

A few questions:

  • After 24 hours, I am getting a state of “unknown”. It was “waiting for first reading” but that updated to “unknown”, presumably after the first reading between the oilpal sensor and the oilpal modem. Any ideas what I’m doing wrong? My template sensor code is:
  - platform: scrape
    resource: http://192.168.86.54/diag.htm
    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": 2
        } %}
        {% set tank_dimensions = {
          "height": 142,    
          "radius": 58.65,
          "width": 69,
          "length": 165,
        } %}
        {% set tank_area = {
          "value": (3.1416 * (tank_dimensions.radius * tank_dimensions.radius) * tank_dimensions.height) / 1000,
        } %}
        {% if tank_type.value == 1 %}
          {% set tank_volume = {
            "value": (tank_dimensions.height - tank_depth) * tank_area.value / 100,
          } %}
        {% else %}
          {% set tank_volume = {
            "value": (tank_dimensions.height - tank_depth) * tank_dimensions.length * tank_dimensions.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 %}
    scan_interval: 60
  • If I know the volume, do I need the other dimensions? Can I just simply set the tank_volume variable to “1040” and remove the other calculations, as per below?
  - platform: scrape
    resource: http://192.168.86.54/diag.htm
    name: OilPalDataq
    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_volume = "1040" %}
        {{ tank_volume.value | round (0) }}
      {% else %}
        {% if states.sensor.oilpaldata.state == "" %}
          Waiting for first reading
        {% else %}
          {{ states.sensor.oilpaldata.state }}
        {% endif %}
      {% endif %}
    scan_interval: 60

  • Would you mind sharing your yaml for the Apex Charts (post #32 above)? I think it looks great and is exactly what I’d like for my own dashboard!

Thanks again for sharing your code - I really appreciate it.

Hi @dunner I’ll come back to this in the morning, but your second code paste has completely removed any of the tank volume steps, so you definately aren’t going to get any values with that. You need your dimensions at the moment as the tank volume is calculated using those.

1 Like

Any update @c0rnflake? Thanks!

UPDATE: Switched to direct reception using an RTL-SDR dongle and rtl_433 for which there is rudimentary support for GFSK ultrasonic oil sensors.

Finally got around to implementing this. Thank you to everyone who’s contributed so far.

First: we have two tanks.

Second: our sensors also report temperature.

I implemented a scraper (based on scrapy) here: GitHub - markferry/tekelek-scraper: Scrape Tekelek 608A data to MQTT

It scrapes diag.htm (once) and publishes data for all sensors to MQTT.
(There are still hardcoded values for my test setup.)

The table headings disagree with the data. For example we get:

Device # RF Address #Rx Rx Time (h) Data Aux Bat [Cache] [FL Hi Lo Dif]
1 662 363 8/1/15 02:01 1177 50 0 [80 64 99 ]
2 282 157 8/1/15 01:57 No Data
3 0 0 0/0/0 00:00 No Data
4 0 0 0/0/0 00:00 No Data

In our case the Data field is actually temperature and Aux field is the depth reading.

What was interesting was decoding some of the cache values - noting that the high bits for temperature overlap the low bits for the depth reading.

Speed of sound varies with temperature increasing more-or-less ~0.6m/s per ⁰C.
So Tekelek record the depth reading at a resolution of 0.5cm leading to a (rather compact) adjustment for temperature. And that’s close enough:

Temp Actual Estimated
@-40⁰C 306.2 m/s 311.4 m/s
@ 0⁰C 331.4 m/s
@+40⁰C 354.7 m/s 351.4 m/s

I’m not sure now that the diag page makes any sense with multiple sensors.

Did a test and our ID 282 sensor was the only device transmitting yet the data is showing up on the first sensor line. Line 2 always shows No Data.

I think it’s buggy…