Countdown timer Topic is solved

Topics (not sure which fora)
when not sure where to post, post here and mods will move it to right forum.

Moderators: leecollings, remb0

Post Reply
Patricen
Posts: 121
Joined: Tuesday 06 February 2018 18:48
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta rel
Contact:

Countdown timer

Post by Patricen »

Hello,

Is there a way using a dummy device to make a countdown timer that I can set the duration with GUI ?
The idea would be to be able setting the heating setpoints to 16° while I'm out for a weekend for example (1 day, 2 days, 1 week) and change the timerplan back to comfort mode.

Any idea is warmly welcome!
Patrice
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: Countdown timer

Post by waaren »

Patricen wrote: Monday 02 November 2020 22:27 Is there a way using a dummy device to make a countdown timer that I can set the duration with GUI ?
The method to set an Alarm time as posted here could be modified without much effort to create such a countdown.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
Patricen
Posts: 121
Joined: Tuesday 06 February 2018 18:48
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta rel
Contact:

Re: Countdown timer

Post by Patricen »

Thanks a lot waaren,
I'll try this, it could be interesting having this kind of object native in Domoticz!
Patrice
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: Countdown timer

Post by waaren »

Patricen wrote: Tuesday 03 November 2020 6:58 Thanks a lot waaren,
I'll try this, it could be interesting having this kind of object native in Domoticz!
Patrice
Can you try this proof of concept?

Code: Select all

--[[
            dzvents script to use a selector type switch to set and start a countdown

            selector levels must be set and named to:

            0    Off
            10   add 1 week
            20   add 3 days
            30   add 1 day
            40   add 4 hours
            50   add 1 hour
            60   add 10 minutes
            70   add 1 minute
            80   reset to now
            90   start Countdown
            100  set idle
            110  Choose

            Off level must be set to "hided" and for lay-out purposes best to set Selector Style to "select Menu"

            The name of the selector switch should initially be set to: "Countdown"
            
            History:
            20201102 Start coding
            20201103 first proof of concept
            
            todo:
            -- Allow multiple Countdown selectors

]]

local scriptVar = 'Countdown'

return
{
    on =
    {
        devices =
        {
             700,  -- id of your selector type switch with initial name "Countdown"
        },

        system =
        {
            'start', -- Needed in case domoticz was restarted (the customEvent need to be emitted again)
        },

        customEvents =
        {
            scriptVar, -- This will come back once the countdown "reaches zero"
        }
    },


    logging =
    {
        level = domoticz.LOG_DEBUG, -- set to domotiocz.LOG_ERROR when all OK
        marker =  scriptVar,
    },

    data =
    {
        countdown =
        {
            initial = 0,
        },
    },

    execute = function(dz, item)

        local datePattern = '(%d%d%d%d)-(%d%d)-(%d%d)%s(%d+):(%d%d+)' -- this will catch "yyyy-mm-dd hh:mm"


        local minutesTable =
        {
           ["add 1 week"] = 10080,
           ["add 3 days"] = 4320,
           ["add 1 day"] = 1440,
           ["add 4 hours"] = 240,
           ["add 1 hour"] = 60,
           ["add 10 minutes"] = 10,
           ["add 1 minute"] = 1,
           ["reset to now"] = 0,
           ["start Countdown"] = 0,
           ["set idle"] = 0,
           ["Choose"] = 0,
        }

        local function date2Timestamp(str)-- Assuming a date pattern like: yyyy-mm-dd hh:mm
            dz.log(str)
            local year, month, day, hour, minute = str:match(datePattern)
            return os.time({year = year, month = month, day = day, hour = hour, min = minute})
        end

        local function timeStamp2dateString(timestamp)
            return os.date('%Y-%m-%d %H:%M',( timestamp or os.time() ) )
        end

        local function resetLevel()
            if item.isDevice then
                item.switchSelector('Choose').afterSec(1).silent() -- force display of new name
            end
        end

        local function closeEnough()
            return os.time() > dz.data.countdown - 5 and os.time() < dz.data.countdown + 5
        end

        local function emitCountdown()
            if dz.data.countdown > os.time() then
                dz.emitEvent(scriptVar).afterSec(dz.data.countdown - os.time())
                dz.log('Countdown set for ' .. ( dz.data.countdown - os.time() ) .. ' seconds.' .. '('.. timeStamp2dateString(dz.data.countdown) ..')', dz.LOG_DEBUG)
            else
                dz.log('Countdown target is not in the future', dz.LOG_DEBUG)
            end
            resetLevel()
        end

        local function setName(timestamp)
            dz.data.countdown = 0
            if item.levelName == 'reset to now'  then
                item.rename('Countdown: ' .. timeStamp2dateString())
            elseif item.levelName == 'set idle'  then
                item.rename('Countdown off')
            else
                item.rename('Countdown: ' .. timeStamp2dateString(timestamp))
                dz.data.countdown = timestamp
            end
            resetLevel()
        end

        -- main code
        if item.isDevice and item.levelName == 'set idle' then
            dz.data.countdown = 0
            setName(0)
        elseif item.isDevice and item.levelName == 'start Countdown' then
            emitCountdown()
        elseif item.isDevice and item.levelName ~='Choose' then

            -- get Multiplier
            local multiplier = minutesTable[item.levelName] or 0

            -- current timestamp
            local currentTimestamp = os.time()
            local startStr, endStr = item.name:find(datePattern)
            if startStr then
                currentTimestamp = date2Timestamp(item.name:sub(startStr, endStr))
                if currentTimestamp < os.time() then currentTimestamp = os.time() end
            end

            local newTimestamp = currentTimestamp + multiplier * 60
            setName(newTimestamp)

        elseif item.isCustomEvent then
            if closeEnough() then
                dz.log('Put your required actions for countdown ended here', dz.LOG_DEBUG)
                dz.data.countdown = 0
            else
                dz.log('This is not the customEvent we are looking for', dz.LOG_DEBUG)
            end
        elseif item.isSystemEvent and dz.data.countdown ~= 0 then
            if dz.data.countdown > os.time() then
                dz.log('domoticz was restarted ==>> rescheduling the countdown', dz.LOG_DEBUG)
                emitCountdown()
            else
                dz.log('Countdown time already passed. Check if rescheduling is needed', dz.LOG_FORCE)
            end
        end
    end
}
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
Patricen
Posts: 121
Joined: Tuesday 06 February 2018 18:48
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta rel
Contact:

Re: Countdown timer

Post by Patricen »

Tried, Working pretty well!
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest