Page 1 of 1

monitor the switch on time

Posted: Monday 26 October 2020 13:10
by Johan1974
Hello,

Is it possible with Dzvents to display the switch on time in a counter? (Seconds or Minutes)
For example: switch name = 'Woonkamer' and Counter name = 'Tijd_aan’

Re: monitor the switch on time

Posted: Monday 26 October 2020 22:00
by Johan1974
It's working but the real time does not match with the displayed time. The displayed time is faster then the real time.
Would it be possible to make this in DZvents instead of LUA?

Re: monitor the switch on time

Posted: Monday 26 October 2020 22:16
by waaren
Johan1974 wrote: Monday 26 October 2020 22:00 It's working but the real time does not match with the displayed time. The displayed time is faster then the real time.
Would it be possible to make this in DZvents instead of LUA?
Sure it's possible but what is the granularity you need? Does it need to be accurate on the second and should the counting sensor be updated every minute or is it enough to update the counter when "Woonkamer" is switched off?

Re: monitor the switch on time

Posted: Monday 26 October 2020 22:34
by Johan1974
It would be nice if the time is accurate to the second, but updated when the device turns off no problem.

Re: monitor the switch on time

Posted: Tuesday 27 October 2020 0:32
by waaren
Johan1974 wrote: Monday 26 October 2020 22:00 The displayed time is faster then the real time.
Did you save it as a time triggered Lua script?

Re: monitor the switch on time

Posted: Tuesday 27 October 2020 1:34
by waaren
Johan1974 wrote: Monday 26 October 2020 22:34 It would be nice if the time is accurate to the second, but updated when the device turns off no problem.
Can you try below script?

Code: Select all

--[[ 
           dzVents script to keep track of active device time
]]--

local scriptVar = 'Woonkamer'  -- must be a switch- or light type of device.

return 
{
    on = 
    {
        devices = 
        {
            scriptVar,  
        },
        
        timer =
        {
            'at *:29', -- twice / hour to update timer when device is on for a longer period.
            'at *:59',
        },
    },
    
    data =
    {
        [scriptVar] =
        {
            initial = 
            { 
                ['active'] = false,
                ['lastSet'] = os.time(),
            },
        },
    },

    logging =
    {
        level = domoticz.LOG_DEBUG, -- change to domoticz.LOG_ERROR when all OK
        marker = 'timeKeeper for ' .. scriptVar, 
    },
    
    execute = function(dz, item)
        local deltaSeconds = os.time() - dz.data[scriptVar].lastSet
        local myCounter = dz.devices('Tijd_aan')  -- define as counter and set to type: Counter, value Quantity: time, value Units: seconds 
        
        if item.isDevice and item.active and not(dz.data[scriptVar].active) then
            dz.data[scriptVar].active = true 
            dz.data[scriptVar].lastSet = os.time()
            dz.log('Counting seconds started', dz.LOG_DEBUG)
        elseif item.isDevice and dz.data[scriptVar].active and not(item.active) then
            dz.data[scriptVar].active = false
            dz.log(item.name .. ' has been active for ' .. deltaSeconds .. ' seconds ', dz.LOG_DEBUG)
            myCounter.updateCounter(myCounter.counter + deltaSeconds)
            dz.data[scriptVar].lastSet = os.time()
        elseif item.isTimer and dz.data[scriptVar].active then
            dz.log('Updating the counter', dz.LOG_DEBUG)
            myCounter.updateCounter(myCounter.counter + deltaSeconds)
            dz.data[scriptVar].lastSet = os.time()
        else
            dz.log('No action needed', dz.LOG_DEBUG)
        end
    end
}

Re: monitor the switch on time

Posted: Tuesday 27 October 2020 15:37
by Johan1974
This works perfectly. One more little question, is it possible to count in seconds, and display in minutes.?

Re: monitor the switch on time

Posted: Tuesday 27 October 2020 17:07
by waaren
Johan1974 wrote: Tuesday 27 October 2020 15:37 This works perfectly. One more little question, is it possible to count in seconds, and display in minutes.?
Yes but you will loose some accuracy..

change

Code: Select all

myCounter.updateCounter(myCounter.counter + deltaSeconds)
to

Code: Select all

myCounter.updateCounter(dz.utils.round( ( myCounter.counter * 60 + deltaSeconds ) / 60 , 1 ) )
at lines 52 and 56

Re: monitor the switch on time

Posted: Tuesday 27 October 2020 18:24
by Johan1974
When the 'Living room' switch is on for 2 x 40 seconds (On off on), the counter should be at 1 minute. The counter will reset to 0 if it has not reached 60 seconds.??

Re: monitor the switch on time

Posted: Tuesday 27 October 2020 20:01
by waaren
Johan1974 wrote: Tuesday 27 October 2020 18:24 When the 'Living room' switch is on for 2 x 40 seconds (On off on), the counter should be at 1 minute. The counter will reset to 0 if it has not reached 60 seconds.??
No what i meant with loosing accuracy was this:

because of the round function the first time is will be 40/60 = 0.66667 ==> 0.7 minutes and the next time
( 0.7 * 60 + 40 ) / 60 ==> 1.36666 = 1.4
in seconds it would have been 80 / 60 = 1.3333 = 1.3

NB. If you start again and use the same counter you will not see the expected outcome. So better "start fresh"

Re: monitor the switch on time

Posted: Wednesday 28 October 2020 9:12
by waaren
Johan1974 wrote: Tuesday 27 October 2020 18:24 When the 'Living room' switch is on for 2 x 40 seconds (On off on), the counter should be at 1 minute. The counter will reset to 0 if it has not reached 60 seconds.??
Had another look at it and below version limits the loss of accuracy by keeping track of the total number of seconds in the background.

Code: Select all

--[[
         dzVents script to keep track of active device time

        History:
        20201026: Start coding
        20201027: Add timer section to update when device is active for a longer period
        20201027: Changed updating counter to minutes
        20201028: Add keeping track of total seconds to improve accuracy

]]--

local scriptVar = 'Woonkamer'  -- must be a switch- or light type of device.

return
{
    on =
    {
        devices =
        {
            scriptVar,
        },

        timer =
        {
            'at *:29', -- twice / hour to update timer when device is on for a longer period.
            'at *:59',
        },
    },

    data =
    {
        [scriptVar] =
        {
            initial =
            {
                ['active'] = false,
                ['activeAt'] = os.time(),
                ['total'] = 0,

            },
        },
    },

    logging =
    {
        level = domoticz.LOG_DEBUG, -- change to domoticz.LOG_ERROR when all OK
        marker = 'timeKeeper for ' .. scriptVar,
    },

    execute = function(dz, item)
        local deltaSeconds = os.time() - dz.data[scriptVar].activeAt
        local myCounter = dz.devices('teller2')  -- define as counter and set to type: Counter, value Quantity: time, value Units: seconds

        local function managedUpdate(myCounter, deltaSeconds)
            if dz.data[scriptVar].total == nil or dz.data[scriptVar].total == 0 then
                dz.data[scriptVar].total = myCounter.counter * 60 + deltaSeconds
            else
                dz.data[scriptVar].total = dz.data[scriptVar].total + deltaSeconds
            end
            local newTotal = dz.utils.round( ( dz.data[scriptVar].total / 60 ), 1 )
            myCounter.updateCounter(newTotal)
            return newTotal
        end

        if item.isDevice and item.active and not(dz.data[scriptVar].active) then
            dz.data[scriptVar].active = true
            dz.data[scriptVar].activeAt = os.time()
            dz.log('Counting seconds started', dz.LOG_DEBUG)
        elseif item.isDevice and dz.data[scriptVar].active and not(item.active) then
            dz.data[scriptVar].active = false
            dz.log(item.name .. ' has been active for ' .. deltaSeconds .. ' seconds since last update.', dz.LOG_DEBUG)
            local activeTotalMinutes = managedUpdate(myCounter, deltaSeconds)
            dz.log('Overall active time for ' .. item.name .. ' is ' .. activeTotalMinutes .. ' minutes.', dz.LOG_DEBUG)
        elseif item.isTimer and dz.data[scriptVar].active then
            local activeTotalMinutes = managedUpdate(myCounter, deltaSeconds)
            dz.log('Updated the counter to ' .. activeTotalMinutes .. ' minutes', dz.LOG_DEBUG)
            dz.data[scriptVar].activeAt = os.time()
        else
            dz.log('No action needed', dz.LOG_DEBUG)
        end
    end
}

Re: monitor the switch on time  [Solved]

Posted: Thursday 29 October 2020 11:41
by Johan1974
Thank you very much.!
The script is already running here ..