Fan Timer

Discussion in 'C-Bus Automation Controllers' started by pspeirs, Nov 8, 2019.

  1. pspeirs

    pspeirs

    Joined:
    Nov 23, 2013
    Messages:
    185
    Likes Received:
    10
    Location:
    Sydney
    Had a need to turn on a fan after a period of the light being on then turn it off at some point after the light has been turned off. Came up with the following to do it and seems to work fine for me. Logic on the output unit wasn't an option. Add the mappings to the table in the below script and it should be good to go.

    Resident 1 second script

    Code:
    -- Script runs each second (or whatever you want) and checks for stored values based on the timer_mappings table
    -- Add an entry for each light and fan combination needing to be controlled
    
    
    on_delay = 60                                                                -- Set the time period from light ON to fan ON
    off_delay = 120                                                                -- Set the time period from light OFF to fan OFF
    
    if not timer_mappings then                                                        -- set up light to fan mappings table
        timer_mappings = {
            {input = 'test_light', output = 'test_fan', status='idle'},
            {input = 'downstairs_bath_light', output = 'downstairs_bath_fan', status='idle'},
            {input = 'upstairs_toilet_light', output = 'upstairs_toilet_fan', status='idle'},
        }
    end
    
    
    for _, timer in ipairs(timer_mappings) do                                        -- Loop through each line in the table
    
        
        keyval = storage.get(timer.input, 0)                                        -- Get the stored value matching the input if it exists
        now = os.time()
    
    
        if (keyval > 0) then                                                        -- If the storage key exists (ie, greater than a value of zero)
    
            delta = now - keyval                                                    -- Calculate the difference between now and the stored value
            
            objLight = GetCBusByKW(timer.input, 'or')                                    -- Get the lighting object and extract the current state into light_state
            light_state = objLight[1].value
    
            objFan = GetCBusByKW(timer.input, 'or')
            local send_to_log = objFan[1].log                                        -- Get the groups 'log' flag
    
            
            if (delta >= on_delay and timer.status == 'idle') then                -- Turn on the fan if required
                if(light_state == 255) then                                            -- Check if the light is still on and if so, turn ON the fan
                    SetCBusByKW({timer.output}, 'or', {target = 255, ramprate = 0})    -- Set the fan ON
                    timer.status = 'fan_on'                                        -- Set OFF delay time
                    storage.set(timer.input, os.time())                                -- Save current time and light keyword to storage
                    
                    if(send_to_log) then
                        log(string.format('FAN CONTROL: Turning Fan \'%s\' ON', timer.output))
                    end
                    
                else
                    -- Set op back to idle if light if now OFF
                    timer.op = 'idle'
                    storage.delete(timer.input)
                    
                end
                
            elseif (timer.status == 'fan_on' and light_state == 255) then                -- If light and fan are both ON
                storage.set(timer.input, os.time())                                    -- Keep resetting the current time for when light goes OFF
                
            elseif (delta >= off_delay and timer.status == 'fan_on' and light_state == 0) then
                SetCBusByKW({timer.output}, 'or', {target = 0, ramprate = 0})        -- Light off, timer expired, turn fan OFF
                storage.delete(timer.input)                                            -- Delete the storage variable
                timer.status = 'idle'                                                        -- Set timer op back to nothing
                
                if(send_to_log) then
                    log(string.format('FAN CONTROL: Turning Fan \'%s\' OFF', timer.output))
                end
            else
            
            end
        
        elseif (keyval == 0 and timer.status ~= 'idle') then                                -- In case something messes up and gets out of sync
            timer.op = 'idle'
        else
        end
    end
    Lighting Group Event Script

    Code:
    value = event.getvalue()
    
    -- DB Call to return object based on the raw id number
    local objLight = db_GetObjectById(event.dstraw)
    
    if (objLight == false) then
        log(string.format('FAN TIMER: Object \'%s\' was not found', event.dstraw))
    else
    
        -- Pull out tagcache table
        local tagcache = split(objLight[1].tagcache, ',')
        local light_keyword = tagcache[1]
    
        -- Substitute the tags to get the fan keyword
        fan_keyword = string.gsub(light_keyword, "_light", "_fan")
    
        -- Get CBUS Level
        objFan = GetCBusByKW(fan_keyword, 'or')
    
        key = light_keyword
    
        -- If the light is switched on AND the fan is currently off, add to the storage variable
        if (value == 255 and objFan[1].value == 0) then
            log(string.format('FAN CONTROL: Light \'%s\' ON', light_keyword))
            storage.set(key, os.time())
        
        elseif (value == 0) then
            log(string.format('FAN CONTROL: Light \'%s\' OFF', light_keyword))
    
        end
    
    end
    
    

    And a couple of user library functions that didn't seem to already exist.
    Code:
    function db_GetObjectById(id)
    
        -- Return a table of object parameters based on the id
        local query = string.format('SELECT * FROM objects WHERE id = "%u"', id)
        liste = db:getall(query)
    
        if (table.maxn(liste) ~= 0) then
            return liste
        else
            return false
        end
        
    end
    
    
    function db_GetObjectTagById(id)
    
        -- Return a table of object parameters based on the id
        local query = string.format('SELECT * FROM objecttags WHERE object = "%u"', id)
        liste = db:getall(query)
    
        if (table.maxn(liste) ~= 0) then
            return liste
        else
            return false
        end
        
    end
    Only limitation of this is that the fan and lighting groups require that the first keyword aligns with the format of *_light and *.fan. Would be easy enough to add some logic to pull out a keyword with an identifier prefixed to enable it to be placed at any position but I really couldn't be bothered.

    upload_2019-11-8_13-17-12.png
     
    pspeirs, Nov 8, 2019
    #1
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.