Page 1 of 1

Showing energy costs for double tarrif meter

Posted: Thursday 02 May 2019 11:45
by DaanV
First of all, thank you for this great piece of software. I have been enjoying it a lot already.

At the moment I am trying to get a custom sensor to show my daily gas and energy costs. the complicating factor is that I have a double tariff meter and fixed daily costs.

I have used a script which I found at:
https://ehoco.nl/stroom-gas-en-waterkos ... -domoticz/
The standard script is for a single tariff meter, which is why I played around with the other script found in the comment section of the page.

The thing is, I don't get it to work. I don't get any errors, but I don't see any energy costs either. So, I have the following questions:
1. As Domoticz uses the T1 and T2 tariffs correctly, would it be possible to write a script that reads out the kwh usage of the usage1 and usage2 (i.e., T1 and T2), multiply it with the Costs from the Domoticz 'Meters/Counters' settings and show it in a Custom Sensor?

2. Given the script I have below, how could I add a rule that states that the 'khwPrijs' = 0.21 between 7.00 and 23.00 hours and that the KwhPrijs = 0.19 between 23.00 and 07.00 hours. Using the code from the website I mentioned, doesn't work.

I have spend a full day searching for solutions, but can't seem to find the answer. Your help is appreciated :)

Code: Select all

return {
    -- on = { timer   = { "every 5 minutes" }},                    -- script draait iedere 5 minuten
    on = { devices = { "Stroom","Gas","Waterverbruik" }},    -- Verwijder -- aan het begin van deze regel en plaats -- voor bovenstaande regel als 
                                                                -- je het script wilt draaien zodra er een nieuw verbruik aan Domoticz is doorgegeven
    execute = function(dz)
        -- Devices
        local vandaagKwh    = dz.devices('Stroom').counterToday         -- Stroommeter device
        local vandaagM3Gas  = dz.devices('Gas').counterToday            -- Gasmeter device
    
        local StroomKosten  = dz.devices('Stroomkosten')                -- Stroomkosten device
        local GasKosten     = dz.devices('Gaskosten')                   -- Gaskosten device
    
        -- Eenheidsprijs in Euro's / Kwh - M3
        local kwhPrijs      = 0.21 
        local gasM3Prijs    = 0.5836
      
        -- Vaste kosten in Euro's per dag (zoals vastrecht) 
        local kwhPrijsVast      = 0.89000
        local gasM3PrijsVast    = 0.79000
     
        -- Kosten berekenen
        local kwhKosten      = tonumber(dz.utils.round( (kwhPrijs * vandaagKwh),2) + kwhPrijsVast)--)--:gsub("%.",",")   -- rounded to two decimals and replace dot by comma
        local GasM3Kosten    = tonumber(dz.utils.round( (gasM3Prijs * vandaagM3Gas),2) + gasM3PrijsVast)--)--:gsub("%.",",")
    
        -- Kosten updaten
          StroomKosten.updateCustomSensor(kwhKosten)
          GasKosten.updateCustomSensor(GasM3Kosten)
    end
}

Re: Showing energy costs for double tarrif meter

Posted: Thursday 02 May 2019 12:53
by waaren
DaanV wrote: Thursday 02 May 2019 11:45 At the moment I am trying to get a custom sensor to show my daily gas and energy costs. the complicating factor is that I have a double tariff meter and fixed daily costs.

I have used a script which I found at:
https://ehoco.nl/stroom-gas-en-waterkos ... -domoticz/
Can you try this one ? If something is not clear please feel free to ask for clarification

Code: Select all

--[[
            put today's electricity and / or today's Gas / and or todays Water usage costs in custom virtual sensor
            Collect information from a P1 device and /or a Gas and /or water meter 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
        local water = dz.devices("Water") -- Water 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
        local waterCost = dz.devices("waterCost 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 
        local waterFixedMonth = 6.36
        --      ********************************************************************** 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
                local daysThisMonth = getDaysForMonth()
                dz.data.energyCosts.electricityFixedDay  = (electricityFixedMonth or 0 ) / daysThisMonth
                dz.data.energyCosts.gasFixedDay  = (gasFixedMonth or 0 ) / daysThisMonth
                dz.data.energyCosts.waterFixedDay  = (waterFixedMonth or 0 ) / daysThisMonth
                
                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 makeTodaysWaterCosts()
            local waterTodayCost 
            if waterCost then
                waterTodaysCost = dz.data.energyCosts.waterFixedDay 
                dz.log("WaterFixed: " .. waterTodaysCost,dz.LOG_FORCED)
                waterTodaysCost = waterTodaysCost + ( water.counterToday * dz.data.energyCosts.CostWater / ( dz.data.energyCosts.DividerWater * 100000))
                dz.log("WaterToday: " .. waterTodaysCost,dz.LOG_FORCED)
            end
           return dz.utils.round(waterTodaysCost, 2)
        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())
            updateCustomSensor( waterCost, makeTodaysWaterCosts())
        else
            makeCostTable(item.json)
        end
    end
}

Re: Showing energy costs for double tarrif meter

Posted: Thursday 02 May 2019 13:41
by DaanV
Thanks for your swift reply!

This is a familiar script. I have come across it and tested it before. The script seems to be working without errors.

There is just one problem: my fixed costs are calculated per day instead of on a monthly base. I tried to change that in the script, but it turns out my knowledge is not sufficient to change it.

If you could fix that, I would be very grateful.

Re: Showing energy costs for double tarrif meter

Posted: Thursday 02 May 2019 14:28
by waaren
DaanV wrote: Thursday 02 May 2019 13:41 There is just one problem: my fixed costs are calculated per day instead of on a monthly base. I tried to change that in the script, but it turns out my knowledge is not sufficient to change it.

If you could fix that, I would be very grateful.
What are your daily fixed costs for Gas, Power and Water ?

Re: Showing energy costs for double tarrif meter

Posted: Thursday 02 May 2019 14:38
by DaanV
the fixed costs per day for electricity are -0,11286
the fixed costs per day for gas are 0,45619

I don't have a smart water meter

Re: Showing energy costs for double tarrif meter

Posted: Thursday 02 May 2019 15:36
by waaren
DaanV wrote: Thursday 02 May 2019 14:38 the fixed costs per day for electricity are -0,11286
the fixed costs per day for gas are 0,45619

I don't have a smart water meter
Please have a look at this one. If you use the same script-name make sure you delete <domoticz_dir>/scripts/dzVents/data/ __data_<scriptname.lua> before first run of this new script.

Code: Select all

--[[
            put today's electricity and / or today's Gas / and or todays Water usage costs in custom virtual sensor
            Collect information from a P1 device and /or a Gas and /or water meter 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  =   scriptVar},

        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
        local water = dz.devices("Water") -- Water 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
        local waterCost = dz.devices("waterCost today")   -- define this virtual sensor as Custom sensor or comment this line when not used
        
        -- fixed Transport + contract costs per Year / Month or Day in Euro's 
        local electricityFixedMonth = 6.31    -- either electricityFixedyear, electricityFixedMonth or electricityFixedDay or comment this line 
        local gasFixedYear = 75.72            -- either gasFixedyear, gasFixedMonth or gasFixedDay or comment this line 
        local waterFixedDay = 0.2052          -- either waterFixedyear, waterFixedMonth or waterFixedDay or comment this line 
        --      ********************************************************************** 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 getDaysForYear(year)       -- Returns number of days in given or current year
              if year == nil then year = dz.time.year end
              return (year%4==0 and (year%100~=0 or year%400==0) and 366 or 365)
        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
                local daysThisMonth = getDaysForMonth()
                local daysThisYear = getDaysForYear()
                
                dz.data.energyCosts = t
                dz.data.energyCosts.electricityFixedDay = ( electricityFixedMonth and ( electricityFixedMonth / daysThisMonth )) or 
                                                          ( electricityFixedYear  and  ( electricityFixedYear / daysThisYear )) or 
                                                            electricityFixedDay
                
                dz.data.energyCosts.gasFixedDay = ( gasFixedMonth and ( gasFixedMonth / daysThisMonth )) or 
                                                  ( gasFixedYear  and  ( gasFixedYear / daysThisYear )) or 
                                                    gasFixedDay
                
                dz.data.energyCosts.waterFixedDay = ( waterFixedMonth and ( waterFixedMonth / daysThisMonth )) or 
                                                    ( waterFixedYear  and  ( waterFixedYear / daysThisYear )) or 
                                                      waterFixedDay
                
                
                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 makeTodaysWaterCosts()
            local waterTodayCost 
            if waterCost then
                waterTodaysCost = dz.data.energyCosts.waterFixedDay 
                dz.log("WaterFixed: " .. waterTodaysCost,dz.LOG_FORCED)
                waterTodaysCost = waterTodaysCost + ( water.counterToday * dz.data.energyCosts.CostWater / ( dz.data.energyCosts.DividerWater * 100000))
                dz.log("WaterToday: " .. waterTodaysCost,dz.LOG_FORCED)
            end
           return dz.utils.round(waterTodaysCost, 2)
        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())
            updateCustomSensor( waterCost, makeTodaysWaterCosts())
        else
            makeCostTable(item.json)
        end
    end
}

Re: Showing energy costs for double tarrif meter  [Solved]

Posted: Thursday 02 May 2019 19:39
by DaanV
Thanks again. Thanks to your help, I've solved the puzzle. Turns out I was doing a couple of things wrong:
1. There is an option in the script to use the gasFixedDay/elecricityFixedDay command instead of yearly.
2. Apparently the T1 tariff in Domoticz is the nighttime tariff, whereas most energy supplier see T1 as the daytime tariff.

Just to be sure and for other people with similar questions, this is the script I used in the end:

Code: Select all

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

local scriptVar = "dailyEnergyCost"

return  {
            on = { timer = { "every 1 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  =   scriptVar},

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

    execute = function(dz, item)
        --  ********************************************************************* Your changes below this line *************
        -- input Devices
        local electricity = dz.devices("Stroom") -- P1 device or comment this line
        local gas = dz.devices("Gas") -- Gas meter or comment this line
    --    local water = dz.devices("Water") -- Water meter or comment this line
        
        -- outPut Devices
        local electricityCost = dz.devices("Stroomkosten") -- define this virtual sensor as Custom sensor or comment this line when not used
        local gasCost = dz.devices("Gaskosten")   -- define this virtual sensor as Custom sensor or comment this line when not used
    --    local waterCost = dz.devices("waterCost today")   -- define this virtual sensor as Custom sensor or comment this line when not used
        
        -- fixed Transport + contract costs per Year / Month or Day in Euro's 
        local electricityFixedDay = -0.11286    -- either electricityFixedyear, electricityFixedMonth or electricityFixedDay or comment this line 
        local gasFixedDay = 0.45619            -- either gasFixedyear, gasFixedMonth or gasFixedDay or comment this line 
    --    local waterFixedDay = 0.2052          -- either waterFixedyear, waterFixedMonth or waterFixedDay or comment this line 
        --      ********************************************************************** 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 getDaysForYear(year)       -- Returns number of days in given or current year
              if year == nil then year = dz.time.year end
              return (year%4==0 and (year%100~=0 or year%400==0) and 366 or 365)
        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
                local daysThisMonth = getDaysForMonth()
                local daysThisYear = getDaysForYear()
                
                dz.data.energyCosts = t
                dz.data.energyCosts.electricityFixedDay = ( electricityFixedMonth and ( electricityFixedMonth / daysThisMonth )) or 
                                                          ( electricityFixedYear  and  ( electricityFixedYear / daysThisYear )) or 
                                                            electricityFixedDay
                
                dz.data.energyCosts.gasFixedDay = ( gasFixedMonth and ( gasFixedMonth / daysThisMonth )) or 
                                                  ( gasFixedYear  and  ( gasFixedYear / daysThisYear )) or 
                                                    gasFixedDay
                
                dz.data.energyCosts.waterFixedDay = ( waterFixedMonth and ( waterFixedMonth / daysThisMonth )) or 
                                                    ( waterFixedYear  and  ( waterFixedYear / daysThisYear )) or 
                                                      waterFixedDay
                
                
                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 makeTodaysWaterCosts()
    --        local waterTodayCost 
    --        if waterCost then
    --            waterTodaysCost = dz.data.energyCosts.waterFixedDay 
    --            dz.log("WaterFixed: " .. waterTodaysCost,dz.LOG_FORCED)
    --            waterTodaysCost = waterTodaysCost + ( water.counterToday * dz.data.energyCosts.CostWater / ( dz.data.energyCosts.DividerWater * 100000))
    --            dz.log("WaterToday: " .. waterTodaysCost,dz.LOG_FORCED)
    --        end
    --       return dz.utils.round(waterTodaysCost, 2)
    --    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())
    --        updateCustomSensor( waterCost, makeTodaysWaterCosts())
        else
            makeCostTable(item.json)
        end
    end
}

Re: Showing energy costs for double tarrif meter

Posted: Thursday 02 May 2019 19:49
by waaren
DaanV wrote: Thursday 02 May 2019 19:39 I've solved the puzzle. Turns out I was doing a couple of things wrong:
Just to be sure and for other people with similar questions, this is the script I used in the end:
Your welcome. Please note that the only area you need to modify settings is between the lines

Code: Select all

--  ********************************************************************* Your changes below this line *************
 --      ********************************************************************** No changes below this line **************
If you don't need one or two meters you can just remove or comment the lines there.
The logic in remaining part of the script takes care of the rest.

Re: Showing energy costs for double tarrif meter

Posted: Thursday 02 May 2019 19:53
by EddyG
Nice script. :D
I get an error:

Code: Select all

2019-05-02 19:48:00.499  Status: dzVents: Error (2.4.18): dailyEnergyCost: An error occured when calling event handler utility_cost
2019-05-02 19:48:00.499  Status: dzVents: Error (2.4.18): dailyEnergyCost: /home/pi/domoticz/dzVents/runtime/Domoticz.lua:172: attempt to perform arithmetic on local 'x' (a nil value)
I have no "Water" yet. I commented 'Water' out.
Any idea?

Re: Showing energy costs for double tarrif meter

Posted: Thursday 02 May 2019 20:15
by DaanV
waaren wrote: Thursday 02 May 2019 19:49
DaanV wrote: Thursday 02 May 2019 19:39 I've solved the puzzle. Turns out I was doing a couple of things wrong:
Just to be sure and for other people with similar questions, this is the script I used in the end:
Your welcome. Please note that the only area you need to modify settings is between the lines

Code: Select all

--  ********************************************************************* Your changes below this line *************
 --      ********************************************************************** No changes below this line **************
If you don't need one or two meters you can just remove or comment the lines there.
The logic in remaining part of the script takes care of the rest.
Thanks. I had not realised that indeed. I'll correct that straight away.

Re: Showing energy costs for double tarrif meter

Posted: Thursday 02 May 2019 21:13
by waaren
EddyG wrote: Thursday 02 May 2019 19:53 Nice script. :D
I get an error:

Code: Select all

2019-05-02 19:48:00.499  Status: dzVents: Error (2.4.18): dailyEnergyCost: An error occured when calling event handler utility_cost
2019-05-02 19:48:00.499  Status: dzVents: Error (2.4.18): dailyEnergyCost: /home/pi/domoticz/dzVents/runtime/Domoticz.lua:172: attempt to perform arithmetic on local 'x' (a nil value)
I have no "Water" yet. I commented 'Water' out.
Any idea?
Sorry. A bit over enthusiastic so posted before finishing all tests. Can you try this one ?

Code: Select all

--[[
            put today's electricity and (optional) today's Gas and (optional) todays Water usage costs in custom virtual sensor
            Collect information from a P1 device and a Gas and water meter 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  =   scriptVar},

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

    execute = function(dz, item)
        --  ********************************************************************* Your changes below this line *************
        -- When change anything between these lines make sure you remove 
        -- <domoticz_dir>/scripts/dzVents/data/ __data_<scriptname.lua> before next run of this script.
        
        -- input Devices
        local electricity = dz.devices("Power") -- P1 device (required)
        local gas = dz.devices("Gas") -- Gas meter or comment this line
        local water = dz.devices("Water") -- Water meter or comment this line
        
        -- outPut Devices
        local electricityCost = dz.devices("electricityCost today") -- define this virtual sensor as Custom sensor 
        local gasCost = dz.devices("gasCost today")   -- define this virtual sensor as Custom sensor or comment this line when not used
        local waterCost = dz.devices("waterCost today")   -- define this virtual sensor as Custom sensor or comment this line when not used
        
        -- fixed Transport + contract costs per Year / Month or Day in Euro's 
        local electricityFixedMonth = 6.31    -- either electricityFixedyear, electricityFixedMonth or electricityFixedDay
        local gasFixedYear = 75.72            -- either gasFixedyear, gasFixedMonth or gasFixedDay or comment this line 
        local waterFixedDay = 0.2052          -- either waterFixedyear, waterFixedMonth or waterFixedDay or comment this line 
        --      ********************************************************************** 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 getDaysForYear(year)       -- Returns number of days in given or current year
              if year == nil then year = dz.time.year end
              return (year%4==0 and (year%100~=0 or year%400==0) and 366 or 365)
        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
                local daysThisMonth = getDaysForMonth()
                local daysThisYear = getDaysForYear()
                
                dz.data.energyCosts = t
                dz.data.energyCosts.electricityFixedDay = ( electricityFixedMonth and ( electricityFixedMonth / daysThisMonth )) or 
                                                          ( electricityFixedYear  and  ( electricityFixedYear / daysThisYear )) or 
                                                            electricityFixedDay
                
                dz.data.energyCosts.gasFixedDay = ( gasFixedMonth and ( gasFixedMonth / daysThisMonth )) or 
                                                  ( gasFixedYear  and  ( gasFixedYear / daysThisYear )) or 
                                                    gasFixedDay
                
                dz.data.energyCosts.waterFixedDay = ( waterFixedMonth and ( waterFixedMonth / daysThisMonth )) or 
                                                    ( waterFixedYear  and  ( waterFixedYear / daysThisYear )) or 
                                                      waterFixedDay
                
                
                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 makeTodaysWaterCosts()
            local waterTodayCost 
            if waterCost then
                local waterTodaysCost = dz.data.energyCosts.waterFixedDay 
                waterTodaysCost = waterTodaysCost + ( water.counterToday * dz.data.energyCosts.CostWater / ( dz.data.energyCosts.DividerWater * 100000))
                return dz.utils.round(waterTodaysCost, 2)
            end
        end
        
        local function makeTodaysGasCosts()
            local gasTodayCost
            if gasCost then
                gasTodaysCost = dz.data.energyCosts.gasFixedDay * 10000
                gasTodaysCost = gasTodaysCost + gas.counterToday * dz.data.energyCosts.CostGas
                return dz.utils.round(gasTodaysCost / 10000, 2)
            end
        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
                return dz.utils.round(electricityTodaysCost / 10000,2) 
            end
        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())
            updateCustomSensor( waterCost, makeTodaysWaterCosts())
        else
            makeCostTable(item.json)
        end
    end
}

Re: Showing energy costs for double tarrif meter

Posted: Thursday 02 May 2019 22:28
by EddyG
Sorry, still same error. Now with debug on.

Code: Select all

2019-05-02 22:24:00.488  Status: dzVents: Debug: dailyEnergyCost: ElectricityCost today ==>> previous value: 1.2 ; new value 1.21
2019-05-02 22:24:00.489  Status: dzVents: Error (2.4.18): dailyEnergyCost: An error occured when calling event handler utility_costs
2019-05-02 22:24:00.489  Status: dzVents: Error (2.4.18): dailyEnergyCost: /home/pi/domoticz/scripts/dzVents/scripts/utility_costs.lua:110: attempt to index global 'water' (a nil value)
2019-05-02 22:24:00.489  Status: dzVents: Info:  dailyEnergyCost: ------ Finished utility_costs.lua
I will try to disable all 'water' variables, I only did the first.

P.S. No error if all 'water' variables are disabled.