<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.domoticz.com/index.php?action=history&amp;feed=atom&amp;title=Lua_%2F_dzVents_-_Oil_Tank_Monitor</id>
	<title>Lua / dzVents - Oil Tank Monitor - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.domoticz.com/index.php?action=history&amp;feed=atom&amp;title=Lua_%2F_dzVents_-_Oil_Tank_Monitor"/>
	<link rel="alternate" type="text/html" href="https://wiki.domoticz.com/index.php?title=Lua_/_dzVents_-_Oil_Tank_Monitor&amp;action=history"/>
	<updated>2026-09-20T04:09:09Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://wiki.domoticz.com/index.php?title=Lua_/_dzVents_-_Oil_Tank_Monitor&amp;diff=16362&amp;oldid=prev</id>
		<title>Walter vl: Categories</title>
		<link rel="alternate" type="text/html" href="https://wiki.domoticz.com/index.php?title=Lua_/_dzVents_-_Oil_Tank_Monitor&amp;diff=16362&amp;oldid=prev"/>
		<updated>2021-08-24T08:20:10Z</updated>

		<summary type="html">&lt;p&gt;Categories&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;
=Purpose=&lt;br /&gt;
&lt;br /&gt;
The purpose of this script is to allow monitoring of a heating oil tank, by use of an ultrasonic sensor which measures the distance &amp;#039;&amp;#039;(of air)&amp;#039;&amp;#039; from the top of the fuel to the top of the tank.&lt;br /&gt;
&lt;br /&gt;
The script is configured with the dimensions of the tank, and calculates the fuel level both as a percentage and as a volume in litres. It can also adjust to compensate for fuel expansion/contraction with temperature, to give a stable reading.&lt;br /&gt;
&lt;br /&gt;
=Dependencies=&lt;br /&gt;
&lt;br /&gt;
You will require a distance sensor which measures the air gap at the top of the tank. This is outside the scope of this example, but there are plenty of such devices on the market and many of them actually seem to be the &amp;#039;&amp;#039;same&amp;#039;&amp;#039; design, just rehoused and rebranded. &lt;br /&gt;
&lt;br /&gt;
The Beckett Rocket, Watchman Sonic, and Apollo Ultrasonic oil tank monitors, and probably others, should all work with [https://github.com/merbanan/rtl_433 rtl_433] using a cheap USB DVB receiver. With a little more work, it should also be possible to [http://www.susa.net/wordpress/2012/08/raspberry-pi-reading-wh1081-weather-sensors-using-an-rfm01-and-rfm12b/ use an RFM01 or RFM12B FSK receiver module] on a Raspberry Pi, which should require less CPU.&lt;br /&gt;
&lt;br /&gt;
Note that the RFXtrx433 modules are not suitable for this, as the modulation of the 433MHz signal is FSK. See [https://hackaday.io/project/1548-rocket-receiver-teardown here] for the full details.&lt;br /&gt;
&lt;br /&gt;
Others have [http://www.domoticz.com/forum/viewtopic.php?f=38&amp;amp;t=8647&amp;amp;p=59737&amp;amp;hilit=oil+tank#p59737 made their own sensors].&lt;br /&gt;
&lt;br /&gt;
Most sensors will also provide a temperature reading, since the speed of sound varies significantly across the temperature range that they need to operate within. However, is this is not required — the compensation for expansion of the fuel can be disabled if no temperature sensor is available.&lt;br /&gt;
&lt;br /&gt;
=Domoticz Setup=&lt;br /&gt;
&lt;br /&gt;
==Input sensors==&lt;br /&gt;
&lt;br /&gt;
In my case, the input sensors are virtual; I haven&amp;#039;t yet hooked up the [https://github.com/merbanan/rtl_433 rtl_433] receiver software to Domoticz directly, so I&amp;#039;m feeding values in externally. They were created as follows:&lt;br /&gt;
&lt;br /&gt;
Temperature sensor (type 80):&lt;br /&gt;
 curl &amp;#039;http://localhost:8080/json.htm?type=createvirtualsensor&amp;amp;idx=1&amp;amp;sensortype=80&amp;#039;&lt;br /&gt;
Depth sensor (type 13):&lt;br /&gt;
 curl &amp;#039;http://localhost:8080/json.htm?type=createvirtualsensor&amp;amp;idx=1&amp;amp;sensortype=13&amp;#039;&lt;br /&gt;
&lt;br /&gt;
==Output sensors==&lt;br /&gt;
&lt;br /&gt;
Percentage sensor (type 2):&lt;br /&gt;
 curl &amp;#039;http://localhost:8080/json.htm?type=createvirtualsensor&amp;amp;idx=1&amp;amp;sensortype=2&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Volume sensor (RFXMeter type 113, subtype 2):&lt;br /&gt;
 curl &amp;#039;http://localhost:8080/json.htm?type=createvirtualsensor&amp;amp;idx=1&amp;amp;sensortype=113&amp;#039;&lt;br /&gt;
 curl &amp;#039;http://localhost:8080/json.htm?type=setused&amp;amp;idx=5&amp;amp;name=Oil&amp;amp;switchtype=2&amp;amp;used=true&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;idx=5&amp;lt;/tt&amp;gt; in the above will need to be replaced with the index of the created device in your own system.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;(In fact, it&amp;#039;s not clear that this is the correct device type to use. It&amp;#039;s the only one I could find that has a unit of litres &amp;#039;&amp;#039;(or m³ in some cases)&amp;#039;&amp;#039;, but it&amp;#039;s designed for measuring water &amp;#039;&amp;#039;flow&amp;#039;&amp;#039;&amp;#039; not an amount. So the graphs aren&amp;#039;t useful. We might need to add a new sensor type of plain &amp;#039;&amp;#039;volume&amp;#039;&amp;#039; to Domoticz.)&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=Installation instructions for the dzVents version=&lt;br /&gt;
&lt;br /&gt;
Having configured the devices as described above, all that remains is to edit the configuration in the script below, and place it into your &amp;lt;tt&amp;gt;scripts/dzVents/scripts&amp;lt;/tt&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
=dzVents Script with comments=&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lua&amp;quot;&amp;gt;--&lt;br /&gt;
-- dzVents script to calculate oil tank levels&lt;br /&gt;
-- Based on https://www.domoticz.com/wiki/Lua_-_Oil_Tank_Monitor&lt;br /&gt;
-- David Woodhouse &amp;lt;dwmw2@infradead.org&amp;gt;&lt;br /&gt;
--&lt;br /&gt;
&lt;br /&gt;
-- Input devices: Temperature and air gap above fluid in tank&lt;br /&gt;
--local tank_temp_sensor = &amp;#039;Oil tank temperature&amp;#039;&lt;br /&gt;
local tank_temp_sensor = &amp;#039;Gas Temperature (left)&amp;#039;&lt;br /&gt;
local depth_sensor = &amp;#039;Oil level sensor&amp;#039;&lt;br /&gt;
&lt;br /&gt;
-- Output devices: Percentage full, volume.&lt;br /&gt;
local pct_sensor = &amp;#039;Oil level&amp;#039;&lt;br /&gt;
local volume_sensor = &amp;#039;Oil&amp;#039;&lt;br /&gt;
&lt;br /&gt;
-- To adjust for fluid expansion&lt;br /&gt;
-- Report volume/percentage as they would be at 10°C&lt;br /&gt;
local canon_temp = 10&lt;br /&gt;
-- Kerosene&lt;br /&gt;
local expansion_coeff = 1.00099&lt;br /&gt;
&lt;br /&gt;
-- Tank dimensions&lt;br /&gt;
local tank_height = 120&lt;br /&gt;
local tank_area = 60 * 181&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
        on = {&lt;br /&gt;
                devices = {&lt;br /&gt;
                        depth_sensor&lt;br /&gt;
                }&lt;br /&gt;
        },&lt;br /&gt;
        execute = function(domoticz, device)&lt;br /&gt;
		local depthdev = domoticz.devices(depth_sensor)&lt;br /&gt;
		local tempdev = domoticz.devices(tank_temp_sensor)&lt;br /&gt;
		local pctdev = domoticz.devices(pct_sensor)&lt;br /&gt;
		local volumedev = domoticz.devices(volume_sensor)&lt;br /&gt;
&lt;br /&gt;
		local depth = depthdev.state&lt;br /&gt;
		-- Calculate percentage and volume&lt;br /&gt;
		local pct = (tank_height - depth) / tank_height * 100&lt;br /&gt;
		local volume = (tank_height - depth) * tank_area / 1000&lt;br /&gt;
&lt;br /&gt;
		-- Adjust for fluid expansion&lt;br /&gt;
		if tempdev ~= nil then&lt;br /&gt;
		   local temp = tempdev.state&lt;br /&gt;
		   local temp_delta = canon_temp - temp&lt;br /&gt;
		   local scale = expansion_coeff ^ temp_delta&lt;br /&gt;
&lt;br /&gt;
		   -- temp_delta is how much colder the tank is than the canonical temperature&lt;br /&gt;
		   -- When the tank is colder, we scale *up* the reported volume to report it what it would be at 10°C&lt;br /&gt;
		   -- When the tank is warmer, we scale down.&lt;br /&gt;
		   -- domoticz.log(&amp;#039;Scale factor &amp;#039; .. scale .. &amp;#039; for &amp;#039; .. temp .. &amp;#039;°C delta &amp;#039; .. temp_delta .. &amp;#039;°C&amp;#039;, domoticz.LOG_INFO)&lt;br /&gt;
		   pct = pct * scale&lt;br /&gt;
		   volume = volume * scale&lt;br /&gt;
		end&lt;br /&gt;
		domoticz.log(&amp;#039;Tank update to &amp;#039; .. pct.. &amp;#039;% &amp;#039; .. volume .. &amp;#039;l&amp;#039;, domoticz.LOG_INFO)&lt;br /&gt;
		pctdev.updatePercentage(pct)&lt;br /&gt;
&lt;br /&gt;
		local prev_volume = volumedev.state + 0&lt;br /&gt;
		volume = -volume&lt;br /&gt;
		domoticz.log(&amp;#039;Volume &amp;#039; .. volume .. &amp;#039; was &amp;#039; .. prev_volume, domoticz.LOG_INFO)&lt;br /&gt;
		-- Don&amp;#039;t allow fluctuations to screw up the usage calculations. Only go up if it&amp;#039;s been refilled.&lt;br /&gt;
		if volume &amp;gt;= prev_volume or (volume &amp;lt; (prev_volume - 100)) then&lt;br /&gt;
		    -- domoticz.log(&amp;#039;Raising volume from &amp;#039; .. prev_volume .. &amp;#039; to &amp;#039; .. volume, domoticz.LOG_INFO)&lt;br /&gt;
		    volumedev.update(0, volume)&lt;br /&gt;
		else&lt;br /&gt;
		    -- domoticz.log(&amp;#039;Not reducing volume from &amp;#039; .. prev_volume .. &amp;#039; to &amp;#039; .. volume, domoticz.LOG_INFO)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Installation instructions for the Lua version=&lt;br /&gt;
&lt;br /&gt;
Having configured the devices as described above, all that remains is to edit the configuration in the script below, and place it into your &amp;lt;tt&amp;gt;scripts/lua&amp;lt;/tt&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
=Lua Script with comments=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
------------------------------------------------------------------------------&lt;br /&gt;
--&lt;br /&gt;
-- Copyright © 2015 David Woodhouse &amp;lt;dwmw2@infradead.org&amp;gt; and released under&lt;br /&gt;
-- the GNU General Public License, v2 or later.&lt;br /&gt;
--&lt;br /&gt;
--&lt;br /&gt;
-- Domoticz lua script to convert ultrasonic tank monitor readings into&lt;br /&gt;
-- percentage and volume virtual sensors for fuel tanks.&lt;br /&gt;
--&lt;br /&gt;
-- Takes input from distance sensor measuring the air above the fluid, and&lt;br /&gt;
-- converts to percentage and volume using the dimensions of the tank as&lt;br /&gt;
-- configured below.&lt;br /&gt;
--&lt;br /&gt;
-- Optionally, to prevent fluctuation as the fluid expands/contracts with&lt;br /&gt;
-- temperature, can convert the output values to report what the percentage&lt;br /&gt;
-- and volume *would* be at a fixed temperature.&lt;br /&gt;
--&lt;br /&gt;
------------------------------------------------------------------------------&lt;br /&gt;
--&lt;br /&gt;
-- Input sensors don&amp;#039;t *have* to be virtual; mine are because they&amp;#039;re filled in&lt;br /&gt;
-- by an external script running rtl_433 and receiving Watchman Sonic transmissions&lt;br /&gt;
--&lt;br /&gt;
-- Add tank temperature sensor:&lt;br /&gt;
-- &amp;#039;http://localhost:8080/json.htm?type=createvirtualsensor&amp;amp;idx=1&amp;amp;sensortype=80&amp;#039;&lt;br /&gt;
-- Add depth sensor:&lt;br /&gt;
-- &amp;#039;http://localhost:8080/json.htm?type=createvirtualsensor&amp;amp;idx=1&amp;amp;sensortype=13&amp;#039;&lt;br /&gt;
--&lt;br /&gt;
------------------------------------------------------------------------------&lt;br /&gt;
-- Output sensors are virtual, fed solely by this script&lt;br /&gt;
--&lt;br /&gt;
-- Add percentage sensor:&lt;br /&gt;
-- &amp;#039;http://localhost:8080/json.htm?type=createvirtualsensor&amp;amp;idx=1&amp;amp;sensortype=2&amp;#039;&lt;br /&gt;
--&lt;br /&gt;
-- Add tank volume:&lt;br /&gt;
-- &amp;#039;http://localhost:8080/json.htm?type=createvirtualsensor&amp;amp;idx=1&amp;amp;sensortype=113&amp;#039;&lt;br /&gt;
-- &amp;#039;http://localhost:8080/json.htm?type=setused&amp;amp;idx=5&amp;amp;name=Oil&amp;amp;switchtype=2&amp;amp;used=true&amp;#039;&lt;br /&gt;
--&lt;br /&gt;
------------------------------------------------------------------------------&lt;br /&gt;
--&lt;br /&gt;
-- Update depth:&lt;br /&gt;
-- &amp;#039;http://localhost:8080/json.htm?type=command&amp;amp;param=udevice&amp;amp;idx=3&amp;amp;nvalue=0&amp;amp;svalue=59&amp;#039;&lt;br /&gt;
--&lt;br /&gt;
------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- Input devices: Temperature and air gap above fluid in tank&lt;br /&gt;
tank_temp_sensor = &amp;#039;Oil tank temp&amp;#039;&lt;br /&gt;
depth_sensor = &amp;#039;Oil tank sensor&amp;#039;&lt;br /&gt;
&lt;br /&gt;
-- Output devices: Percentage full, volume.&lt;br /&gt;
pct_sensor = &amp;#039;Oil tank&amp;#039;&lt;br /&gt;
pct_sensor_id = 4&lt;br /&gt;
volume_sensor = &amp;#039;Oil&amp;#039;&lt;br /&gt;
volume_sensor_id = 5&lt;br /&gt;
&lt;br /&gt;
-- To adjust for fluid expansion&lt;br /&gt;
-- Report volume/percentage as they would be at 10°C&lt;br /&gt;
canon_temp = -10&lt;br /&gt;
-- Kerosene&lt;br /&gt;
expansion_coeff = 1.00099&lt;br /&gt;
&lt;br /&gt;
-- Tank dimensions&lt;br /&gt;
tank_height = 120&lt;br /&gt;
tank_area = 60 * 181&lt;br /&gt;
&lt;br /&gt;
-----------------------------------------------------------------------------------&lt;br /&gt;
commandArray = {}&lt;br /&gt;
&lt;br /&gt;
if (devicechanged[depth_sensor] or devicechanged[tank_temp_sensor]) then&lt;br /&gt;
   -- Use otherdevices_svalues[] because devicechanged[foo_Utility] is not&lt;br /&gt;
   -- present when the value is zero&lt;br /&gt;
   depth = otherdevices_svalues[depth_sensor]&lt;br /&gt;
&lt;br /&gt;
   -- Calculate percentage and volume&lt;br /&gt;
   pct = (tank_height - depth) / tank_height * 100&lt;br /&gt;
   volume = (tank_height - depth) * tank_area / 1000&lt;br /&gt;
&lt;br /&gt;
   -- Adjust for fluid expansion&lt;br /&gt;
   tank_temp = otherdevices_svalues[tank_temp_sensor]&lt;br /&gt;
   if (tank_temp ~= nil) then&lt;br /&gt;
      temp_delta = tank_temp - canon_temp&lt;br /&gt;
      scale = expansion_coeff ^ temp_delta&lt;br /&gt;
      pct = pct * scale&lt;br /&gt;
      volume = volume * scale&lt;br /&gt;
   end&lt;br /&gt;
&lt;br /&gt;
-- print(string.format(&amp;quot;depth now %f; percentage %f %% volume %f l&amp;quot;, depth, pct, volume))&lt;br /&gt;
&lt;br /&gt;
   commandArray[1] = {[&amp;#039;UpdateDevice&amp;#039;] = pct_sensor_id .. &amp;quot;|0|&amp;quot; .. pct}&lt;br /&gt;
   commandArray[2] = {[&amp;#039;UpdateDevice&amp;#039;] = volume_sensor_id .. &amp;quot;|0|&amp;quot; .. volume}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return commandArray&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Example of use (if relevant) i.e. output files / screen displays=&lt;br /&gt;
&lt;br /&gt;
[[File:Oil.png||Domoticz displaying oil tank levels]]&lt;br /&gt;
[[Category:Lua]]&lt;br /&gt;
[[Category:DzVents]]&lt;br /&gt;
[[Category:Scripting]]&lt;/div&gt;</summary>
		<author><name>Walter vl</name></author>
	</entry>
</feed>