Page 1 of 2

Calculate daily energy cost

Posted: Tuesday 25 September 2018 22:28
by tristanp
I am trying to accomplish something really simple (but I have never used LUA, so I am really struggling....)

I have a USB P1 energy + gas meter I want to extract the "CounterToday" from the sensor called "Stroom" (energy) - I would like to multiply that by 0.20 (power cost per KwH) and update this to a dummy sensor "Stroomkosten vandaag" and the same thing for gas if possible so I can have these on a sweet little dashboard mounted on my livingroom wall.

I want the script to run everytime "CounterToday" updates.

Is there anyone who is willing to help me? Thanks in advance!

Re: Calculate daily energy cost

Posted: Tuesday 25 September 2018 23:52
by waaren
tristanp wrote: Tuesday 25 September 2018 22:28 I am trying to accomplish something really simple (but I have never used LUA, so I am really struggling....)

I have a USB P1 energy + gas meter I want to extract the "CounterToday" from the sensor called "Stroom" (energy) - I would like to multiply that by 0.20 (power cost per KwH) and update this to a dummy sensor "Stroomkosten vandaag" and the same thing for gas if possible so I can have these on a sweet little dashboard mounted on my livingroom wall.

I want the script to run everytime "CounterToday" updates.

Is there anyone who is willing to help me? Thanks in advance!
in dzVents it would look like

Code: Select all

return {
    on = { timer   = { "every minute" }},                 -- using every minute because Stroom and Gas are updated very frequently
    -- on = { devices = { "Stroom","Gas" }},              -- Remove -- at the beginning of this line and place them the line above if 
                                                          -- you want to trigger the script (much) more frequent

--     logging =   {   level   =   domoticz.LOG_DEBUG,    -- Remove -- on these two lines if you want debug logging
--                    marker  =   "EnergyCost" },    

    execute = function(dz)
        -- Devices
        local todayKwh      = dz.devices("Stroom").counterToday
        local todayM3       = dz.devices("Gas").counterToday
        local kwhTextdevice = dz.devices("Stroomkosten vandaag")
        local m3Textdevice  = dz.devices("Gaskosten vandaag")
        
        -- Price in Euro's / Kwh - M3
        local kwhPrice      = 0.20
        local gasM3Price    = 0.44
        
        -- Prepare text
        local kwhText  = "€ "  .. tostring(dz.utils.round( (kwhPrice * todayKwh),2)):gsub("%.",",")   -- rounded to two decimals and replace dot by comma
        local m3Text   = "€ "  .. tostring(dz.utils.round( (gasM3Price * todayM3),2)):gsub("%.",",")
        
        local function updateTextDeviceCheckFirst(device,text)
            if text ~= device.text then              -- Update only needed when new text is different fom previous text 
                dz.log(device.name .. " ==>> previous text: " .. device.text .. " ; new text " .. text,dz.LOG_DEBUG)
                device.updateText(text) 
            end
        end
        
        -- call function
        updateTextDeviceCheckFirst( kwhTextdevice, kwhText) 
        updateTextDeviceCheckFirst( m3Textdevice, m3Text) 
        
    end
}
When not familiar yet with Lua / dzVents), read this Quickstart (only a couple of lines) and the "About dzVents .."just above this Quickstart section.

Re: Calculate daily energy cost

Posted: Monday 08 October 2018 12:11
by Thuis
Thank you very much, the script works like a charm :)

Re: Calculate daily energy cost

Posted: Wednesday 31 October 2018 11:43
by lodie
Hello,

I am getting an error, and don't know ow to fix it. I used te example and get this error

2018-10-31 11:42:00.574 Status: dzVents: Info: ------ Start external script: stroom.lua:, trigger: every minute
2018-10-31 11:42:00.603 Status: dzVents: Error (2.4.6): An error occured when calling event handler stroom
2018-10-31 11:42:00.603 Status: dzVents: Error (2.4.6): /home/pi/domoticz/scripts/dzVents/scripts/stroom.lua:26: attempt to concatenate field 'text' (a nil value)
2018-10-31 11:42:00.603 Status: dzVents: Info: ------ Finished stroom.lua

Re: Calculate daily energy cost

Posted: Thursday 01 November 2018 12:10
by MikeF
By making small changes to @waaren 's script, if you use custom sensors instead of text devices, then you can view graphs of your costs.

In the two lines under '--Prepare text', delete "€ " .. (these need to be numeric strings - add € as the axis label by editing the devices in the GUI).
In local function updateTextDeviceCheckFirst, change 'device.updateText(text)' to 'device.updateCustomSensor(text)'.

Here's an amended version of the script (I've changed the variable names for the costs, to show that these are custom sensors).

Code: Select all

return {
    on = { timer   = { "every minute" }},                 -- using every minute because Stroom and Gas are updated very frequently
    -- on = { devices = { "Stroom","Gas" }},              -- Remove -- at the beginning of this line and place them the line above if 
                                                          -- you want to trigger the script (much) more frequent

--     logging =   {   level   =   domoticz.LOG_DEBUG,    -- Remove -- on these two lines if you want debug logging
--                    marker  =   "EnergyCost" },    

    execute = function(dz)
        -- Devices
        local todayKwh        = dz.devices("Stroom").counterToday
        local todayM3         = dz.devices("Gas").counterToday
        local kwhCustomdevice = dz.devices("Stroomkosten vandaag") -- custom sensor
        local m3Customdevice  = dz.devices("Gaskosten vandaag")    -- custom sensor
        
        -- Price in Euro's / Kwh - M3
        local kwhPrice      = 0.20
        local gasM3Price    = 0.44
        
        -- Prepare text (add '€' as axis label by editing devices in GUI)
        local kwhText  = tostring(dz.utils.round( (kwhPrice * todayKwh),2)):gsub("%.",",")   -- rounded to two decimals and replace dot by comma
        local m3Text   = tostring(dz.utils.round( (gasM3Price * todayM3),2)):gsub("%.",",")
        
        local function updateTextDeviceCheckFirst(device,text)
            if text ~= device.text then              -- Update only needed when new text is different fom previous text 
                dz.log(device.name .. " ==>> previous text: " .. device.text .. " ; new text " .. text,dz.LOG_DEBUG)
                device.updateCustomSensor(text) 
            end
        end
        
        -- call function
        updateTextDeviceCheckFirst( kwhCustomdevice, kwhText) 
        updateTextDeviceCheckFirst( m3Customdevice, m3Text) 
        
    end
}

Re: Calculate daily energy cost

Posted: Thursday 01 November 2018 16:13
by Toulon7559
Did you look at Domoticz' Setup => Setup => Meters/Counters?
In that section you can set all tariffs you like to have .......

;-) Thinking Out-of-the-box for alternative solution

If you upload your info for production & consumption to PVOutput.org, the answer becomes very simple:
under Settings just insert the information for the various tariffs and the times that they are applicable.
Then PVOutput calculates the yield respectively the cost.

Re: Calculate daily energy cost

Posted: Friday 30 November 2018 21:05
by Yardco
Im getting an error message as well, just like @lodie. Anyone who has an idea on how to fix this?

Re: Calculate daily energy cost

Posted: Tuesday 16 April 2019 13:10
by yazoo
Help i get an error

2019-04-16 12:57:00.640 Status: dzVents: Info: ------ Start internal script: Stroom:, trigger: every minute
2019-04-16 12:57:00.693 Status: dzVents: Error (2.4.16): An error occured when calling event handler Stroom
2019-04-16 12:57:00.693 Status: dzVents: Error (2.4.16): ...pi/domoticz/scripts/dzVents/generated_scripts/Stroom.lua:22: attempt to concatenate field 'text' (a nil value)

What i do wrong

script:

return {
on = { timer = { "every minute" }}, -- using every minute because Stroom and Gas are updated very frequently
-- on = { devices = { "Stroom" }}, -- Remove -- at the beginning of this line and place them the line above if
-- you want to trigger the script (much) more frequent

-- logging = { level = domoticz.LOG_DEBUG, -- Remove -- on these two lines if you want debug logging
-- marker = "EnergyCost" },

execute = function(dz)
-- Devices
local todayKwh = dz.devices("Stroom").counterToday
local kwhCustomdevice = dz.devices("Stroomkosten vandaag") -- custom sensor

-- Price in Euro's / Kwh - M3
local kwhPrice = 0.22

-- Prepare text (add '€' as axis label by editing devices in GUI)
local kwhText = tostring(dz.utils.round( (kwhPrice * todayKwh),2)):gsub("%.",",") -- rounded to two decimals and replace dot by comma

local function updateTextDeviceCheckFirst(device,text)
if text ~= device.text then -- Update only needed when new text is different fom previous text
dz.log(device.name .. " ==>> previous text: " .. device.text .. " ; new text " .. text,dz.LOG_DEBUG)
device.updateCustomSensor(text)
end
end

-- call function
updateTextDeviceCheckFirst( kwhCustomdevice, kwhText)

end
}

Re: Calculate daily energy cost

Posted: Tuesday 16 April 2019 14:37
by EdwinK
Line 22 is:

Code: Select all

        local m3Text   = tostring(dz.utils.round( (gasM3Price * todayM3),2)):gsub("%.",",")
since you don't have

Code: Select all

local gasM3Price    = 0.44
the script is unable to calculate it.

Re: Calculate daily energy cost

Posted: Tuesday 16 April 2019 14:48
by EdwinK
Now I have an error myself :(

Code: Select all

2019-04-16 14:44:00.226 Status: dzVents: Error (2.4.18): EnergyCost: ...pi/domoticz/scripts/dzVents/generated_scripts/Kosten.lua:25: attempt to index local 'device' (a nil value)
I know what it is supposed to do, but can't figure out why it isn't doing that.

Re: Calculate daily energy cost

Posted: Tuesday 16 April 2019 21:04
by waaren
yazoo wrote: Tuesday 16 April 2019 13:10 Help i get an error

2019-04-16 12:57:00.640 Status: dzVents: Info: ------ Start internal script: Stroom:, trigger: every minute
2019-04-16 12:57:00.693 Status: dzVents: Error (2.4.16): An error occured when calling event handler Stroom
2019-04-16 12:57:00.693 Status: dzVents: Error (2.4.16): ...pi/domoticz/scripts/dzVents/generated_scripts/Stroom.lua:22: attempt to concatenate field 'text' (a nil value)
the method text is not available for device type custom sensor. You need another function to do that. Try this:

Code: Select all

return {
    on = { timer   = { "every 6 minutes" }},                 -- using 6 minutes because Stroom and Gas are updated very frequently

      logging =   {   level   =   domoticz.LOG_DEBUG,    -- Remove -- on these two lines if you want debug logging
                      marker  =   "EnergyCost" },    

    execute = function(dz)
        -- Devices
        local todayKwh      = dz.devices("Power").counterToday
        local todayM3       = dz.devices("Gas").counterToday
        local energyCost    = dz.devices("energyCost today") -- define this virtual sensor as Custom sensor
        local gasCost       = dz.devices("gasCost today")   -- define this virtual sensor as Custom sensor
        
        -- Price in Euro's / Kwh - M3
        local kwhPrice      = 0.20
        local gasM3Price    = 0.62
        local kwHFixedDay   = 6.99 / 31
        local m3FixedDay    = 6.99 / 31

        -- calculations
        local kwhValue  = dz.utils.round( (kwhPrice * todayKwh + kwHFixedDay),2)   -- rounded to two decimals
        local m3Value   = dz.utils.round( (gasM3Price * todayM3 + m3FixedDay),2)
        
        local function updateCustomSensor(device, value)
            local currentValue = device.rawData[1]
            if value ~= tonumber(currentValue) then              -- Update only needed when new value is different fom previous one 
                dz.log(device.name .. " ==>> previous value: " .. currentValue .. " ; new value " .. value,dz.LOG_DEBUG)
                device.updateCustomSensor(value) 
            end
        end
        
        -- call function
        updateCustomSensor(energyCost, kwhValue) 
        updateCustomSensor(gasCost, m3Value) 
        
    end
}

Re: Calculate daily energy cost

Posted: Wednesday 17 April 2019 9:47
by yazoo
Thanks @waaren this was the sulution its working now.

Re: Calculate daily energy cost

Posted: Wednesday 17 April 2019 10:37
by EdwinK
Working for me too ;)

Just something else.. I have two tariffs for electricity, (High and low (11pm-07am). How can I add those, and I guess that the other settings are for transportation costs.

Re: Calculate daily energy cost

Posted: Friday 19 April 2019 15:04
by smika
I'va got the following error in the log file after create this lua with the internal editor and add the dummy sensors.

2019-04-19 08:00:37.674 Error: EventSystem: in costs: [string "return {..."]:4: attempt to index global 'domoticz' (a nil value)

Can someone hint me to the right direction?

Thanks,

Smika

Re: Calculate daily energy cost

Posted: Friday 19 April 2019 16:37
by waaren
smika wrote: Friday 19 April 2019 15:04 I'va got the following error in the log file after create this lua with the internal editor and add the dummy sensors.

2019-04-19 08:00:37.674 Error: EventSystem: in costs: [string "return {..."]:4: attempt to index global 'domoticz' (a nil value)

Can someone hint me to the right direction?

Thanks,

Smika
Try choosing dzVents in the internal editor.

Re: Calculate daily energy cost

Posted: Saturday 20 April 2019 0:37
by waaren
EdwinK wrote: Wednesday 17 April 2019 10:37 Working for me too ;)

Just something else.. I have two tariffs for electricity, (High and low (11pm-07am). How can I add those, and I guess that the other settings are for transportation costs.
Working with tariffs and returning energy to the grid (solar panels) need a different approach.
Can you try below script ?

Code: Select all

--[[
            put today's electricity and / or today's Gas usage costs in custom virtual sensor
            Collect information from a P1 device and /or a Gas device
            electricity takes different tariffs and returns (from solarpanels or the likes) into account.
            
]]--

local scriptVar = "dailyEnergyCost"

return  {
            on = { timer = { "every 6 minutes" },           -- using 6 minutes because Stroom and Gas are updated very frequently
                   httpResponses = { scriptVar .. "*" },
        },

        logging = { level   =   domoticz.LOG_DEBUG,    -- change to LOG_ERROR when script executes OK
                    marker  =   sciptVar},

        data =  { energyCosts = { initial = {} }
                },

    execute = function(dz, item)
        --  ********************************************************************* Your changes below this line *************
        -- input Devices
        local electricity = dz.devices("Power") -- P1 device or comment this line
        local gas = dz.devices("Gas") -- Gas meter or comment this line
        
        -- outPut Devices
        local electricityCost = dz.devices("electricityCost today") -- define this virtual sensor as Custom sensor or comment this line when not used
        local gasCost = dz.devices("gasCost today")   -- define this virtual sensor as Custom sensor or comment this line when not used
        
        -- fixed Transport + contract costs per month in Euro's
        local electricityFixedMonth = 6.31 
        local gasFixedMonth = 6.31 
        --      ********************************************************************** No changes below this line **************

        local function getDaysForMonth(month, year)       -- Returns number of days in given or current month
            if month == nil then month = dz.time.month end
            if year == nil then year = dz.time.year end
            return os.date('*t',os.time{year=year,month=month+1,day=0}).day
        end

        local function triggerJSON(url, response, delay)
            local delay = delay or 0
            dz.openURL({    url = url,
                            method = "GET",
                            callback = response}).afterSec(delay)
        end
        
        local function getCosts(id) -- these costs should be set in domoticz settings
            if next(dz.data.energyCosts) == nil  or dz.data.energyCosts.creationTime < ( dz.time.dDate - dz.time.secondsSinceMidnight ) then
                local costURL = dz.settings['Domoticz url'] .. "/json.htm?param=getcosts&type=command&idx=" .. id
                triggerJSON(costURL, scriptVar .. "_cost")
            end
            return ( next(dz.data.energyCosts) ~= nil )
        end
        
        local function makeCostTable(t) -- (re)Create costTable if not existing yet; Refreshed at least once a day
            if next( dz.data.energyCosts ) == nil or dz.data.energyCosts.creationTime < ( dz.time.dDate - dz.time.secondsSinceMidnight ) then
                dz.data.energyCosts = t
                dz.data.energyCosts.electricityFixedDay  = (electricityFixedMonth or 0 ) / getDaysForMonth()
                dz.data.energyCosts.gasFixedDay  = (gasFixedMonth or 0 ) / getDaysForMonth()
                dz.data.energyCosts.creationTime = dz.time.dDate
                dz.data.energyCosts.humanReadableCreationTime = dz.time.raw
            end
        end
        
        local function updateCustomSensor(device, value) 
            local currentValue = device.rawData[1]
            if value ~= tonumber(currentValue) then              -- Update only needed when new value is different fom previous one 
                dz.log(device.name .. " ==>> previous value: " .. currentValue .. " ; new value " .. value,dz.LOG_DEBUG)
                device.updateCustomSensor(value) 
            end
        end
        
        local function getEnergy(id)
            local energyURL = dz.settings['Domoticz url'] .. "/json.htm?range=month&sensor=counter&type=graph" ..
                                "&actmonth=" .. dz.time.month ..
                                "&idx=" .. id
                triggerJSON(energyURL, scriptVar .. "_energy")
        end
        
        local function makeTodaysGasCosts()
            local gasTodayCost
            if gasCost then
                gasTodaysCost = dz.data.energyCosts.gasFixedDay * 10000
                gasTodaysCost = gasTodaysCost + gas.counterToday * dz.data.energyCosts.CostGas
            end
           return dz.utils.round(gasTodaysCost / 10000, 2)
        end
        
        local function makeTodaysElectricityCosts(t)
            local today
            for i, record in ipairs(t) do
                if record.d == dz.time.rawDate then
                    today = i
                end
            end
            
            local electricityTodaysCost
            if electricityCost then 
                electricityTodaysCost = dz.data.energyCosts.electricityFixedDay * 10000
                if today then 
                    electricityTodaysCost = electricityTodaysCost + t[today].v * dz.data.energyCosts.CostEnergy
                    electricityTodaysCost = electricityTodaysCost + t[today].v2 * dz.data.energyCosts.CostEnergyT2
                    electricityTodaysCost = electricityTodaysCost - t[today].r1 * dz.data.energyCosts.CostEnergyR1
                    electricityTodaysCost = electricityTodaysCost - t[today].r2 * dz.data.energyCosts.CostEnergyR2
                end
            end
           
           return dz.utils.round(electricityTodaysCost / 10000,2) 
        end
        
        local function updateCustomSensor(device, value)
            if device == nil or value == nil then
                return 
            end
            local currentValue = device.rawData[1]
            if value ~= tonumber(currentValue) then              -- Update only needed when new value is different fom previous one 
                dz.log(device.name .. " ==>> previous value: " .. currentValue .. " ; new value " .. value,dz.LOG_DEBUG)
                device.updateCustomSensor(value) 
            end
        end
        
        if not ( item.isHTTPResponse ) then
            if not ( getCosts(electricity.id) ) then 
                -- logWrite("No or outdated costs. Next time the costs will be there")
                return 
            end 
            -- logWrite("-- costs are there; get energy data")
            getEnergy(electricity.id)
        elseif item.trigger == ( scriptVar .. "_energy" ) then
            updateCustomSensor( electricityCost, makeTodaysElectricityCosts(item.json.result))
            updateCustomSensor( gasCost, makeTodaysGasCosts())
        else
            makeCostTable(item.json)
        end
    end
}

Re: Calculate daily energy cost

Posted: Saturday 20 April 2019 9:23
by EdwinK
Seems to work, but.. where does it get it tariffs from?

Re: Calculate daily energy cost

Posted: Saturday 20 April 2019 11:16
by waaren
EdwinK wrote: Saturday 20 April 2019 9:23 Seems to work, but.. where does it get it tariffs from?
Tariffs for gas and electricity are from what you entered in the fields gas Costs, Costs T1,Costs T2,Costs R1 and Costs R2 in tab [setup][system][meters/counters]
fixed Transport + contract costs per month in Euro's are to be entered in the script between the *** lines

Re: Calculate daily energy cost

Posted: Saturday 20 April 2019 15:31
by EdwinK
Maybe I'm overlooking something but this is the part between those lines:

Code: Select all

     
     -- input Devices
        local electricity = dz.devices("Power") -- P1 device or comment this line
        local gas = dz.devices("Gas") -- Gas meter or comment this line
        
     -- outPut Devices
        local electricityCost = dz.devices("electricityCost today") -- define this virtual sensor as Custom sensor or comment this line when not used
        local gasCost = dz.devices("gasCost today")   -- define this virtual sensor as Custom sensor or comment this line when not used
        
        -- fixed Transport + contract costs per month in Euro's
        local electricityFixedMonth = 3,46
        local gasFixedMonth = 3,46
I don't see any other lines to put those data.

Re: Calculate daily energy cost

Posted: Saturday 20 April 2019 15:34
by EdwinK
Nevermind... Found it ;)