Automatic switch off the IKEA bulb after power outage recovery - ZigBee2MQTT

Xiaomi, Ikea TRÅDFRI, Philips Hue and more.

Moderator: leecollings

Post Reply
ljanosi
Posts: 3
Joined: Wednesday 17 June 2020 20:32
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: Romania
Contact:

Automatic switch off the IKEA bulb after power outage recovery - ZigBee2MQTT

Post by ljanosi »

Hello, after a shorter or longer 230V power outage the IKEA LED bulbs are turning ON automatically. This is quite annoying especially during night or during day when nobody is at home, remaining with the lights ON. I am trying to find a way to detect an unexpected turn on of the lights turning them off via a dzventz script. Note: the raspberry is UPS backed up, the bulbs not, so the Domoticz together with the Zigbee2MQTT module is continuously running even during power outage and there is no Ikea switch or dzventz script based trigger comming from Domoticz during this time. Any ideea, suggestion how to deal with this? Thanks!
ronaldbro
Posts: 327
Joined: Thursday 15 November 2018 21:38
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: Netherlands
Contact:

Re: Automatic switch off the IKEA bulb after power outage recovery - ZigBee2MQTT

Post by ronaldbro »

I created some scripts which also cover this problem. As example see the script below.

Normally the lights are switched through domotics and then I store the "initiator" who initiated that the lights go on.
For example the lights can go on because of the switch, a door sensor, a PIR, etc. If the lights go on and nothing initiated this then it must be a power on. In that case the initiator is set to 'power' and the lights go off after some time.

Hope this helps.

Code: Select all

 local DIMLEVEL_ACTIVITY             = 25
local DIMLEVEL_DEFAULT              = 50
local LUX_THRESHOLD                 = 8
local SECONDS_ACTIVITY_LEVEL        = 300
local SECONDS_ACTIVITY_LEVEL_LONG   = 3600

local INITIATOR_OFF         = 'INITIATOR_OFF'
local INITIATOR_POWER       = 'INITIATOR_POWER'
local INITIATOR_SWITCH      = 'INITIATOR_SWITCH'
local INITIATOR_DOOR        = 'INITIATOR_DOOR'
local INITIATOR_DOOR_CLOSED = 'INITIATOR_DOOR_CLOSED'
local INITIATOR_PIR         = 'INITIATOR_PIR'

local idx_beweging              = idx_hal_beweging
local idx_bewegingLux           = idx_hal_bewegingLux
local idx_voordeur              = idx_hal_voordeur
local idx_spots                 = idx_hal_spots
local idx_opple_hal_links       = idx_hal_opple_knop5
local idx_opple_hal_rechts      = idx_hal_opple_knop6
local idx_opple_overloop_links  = 0
local idx_opple_overloop_rechts = 0
local idx_opple_zolder_links    = 0
local idx_opple_zolder_rechts   = 0
local var_dagNacht              = var_idx_dagNacht

return {
	on = {
		devices = {
		    idx_beweging,
			idx_voordeur,
			idx_spots,
			idx_opple_hal_links,
			idx_opple_hal_rechts,
			idx_opple_overloop_links,
			idx_opple_overloop_rechts,
			idx_opple_zolder_links,
			idx_opple_zolder_rechts
		},
	},
	
	data = {
		initiator = { initial = INITIATOR_OFF },
	},

	logging = {
--        level = domoticz.LOG_DEBUG,
--        level = domoticz.LOG_INFO,
        level = domoticz.LOG_ERROR,
        marker = "Hal - Spots"
    },

	execute = function(dz, triggeredItem, info)

        local lamp = dz.devices(idx_spots)
        local dagNacht = dz.variables(var_dagNacht)
        local voordeur = dz.devices(idx_voordeur)
   
        dz.log('Current initiator = ' .. dz.data.initiator)
   
        if triggeredItem.isDevice then
            if triggeredItem.idx == idx_spots and lamp.active then
                if dz.data.initiator == INITIATOR_OFF then
                    dz.data.initiator = INITIATOR_POWER
                    dz.log('Switched on by power.')
                    lamp.cancelQueuedCommands()
                    lamp.switchOff().afterSec(SECONDS_ACTIVITY_LEVEL)
                    dz.log('Switch off after ' .. SECONDS_ACTIVITY_LEVEL .. ' seconds.')
                end
            elseif triggeredItem.idx == idx_spots and lamp.active == false then
                dz.data.initiator = INITIATOR_OFF
                dz.log('Lamp switched off')
            elseif triggeredItem.idx == idx_voordeur and triggeredItem.active and dagNacht.value == CONST_DAGNACHT_NACHT then
                if dz.data.initiator == INITIATOR_OFF or dz.data.initiator == INITIATOR_POWER or dz.data.initiator == INITIATOR_DOOR_CLOSED or dz.data.initiator == INITIATOR_PIR then
                    dz.data.initiator = INITIATOR_DOOR
                    dz.log('Door opened, Set lvl to ' .. DIMLEVEL_ACTIVITY)
                    lamp.cancelQueuedCommands()
                    lamp.dimTo(DIMLEVEL_ACTIVITY)
                end
            elseif triggeredItem.idx == idx_voordeur and triggeredItem.active == false and dagNacht.value == CONST_DAGNACHT_NACHT then
                if dz.data.initiator == INITIATOR_DOOR
                or dz.data.initiator == INITIATOR_POWER then
                    dz.log('Door closed.')
                    lamp.cancelQueuedCommands()
                    lamp.switchOff().afterSec(SECONDS_ACTIVITY_LEVEL)
                    dz.log('Switch off after ' .. SECONDS_ACTIVITY_LEVEL .. ' seconds.')
                end
            elseif triggeredItem.idx == idx_beweging and triggeredItem.active then
                if (dz.data.initiator == INITIATOR_OFF and dz.devices(idx_bewegingLux).lux <= LUX_THRESHOLD)
                or (dz.data.initiator == INITIATOR_POWER and dz.devices(idx_bewegingLux).lux <= LUX_THRESHOLD)
                or dz.data.initiator == INITIATOR_PIR 
                or dz.data.initiator == INITIATOR_DOOR_CLOSED then
                    dz.data.initiator = INITIATOR_PIR    
                    dz.log('Movement detected.')
                    lamp.cancelQueuedCommands()
                    lamp.dimTo(DIMLEVEL_ACTIVITY)
                    lamp.switchOff().afterSec(SECONDS_ACTIVITY_LEVEL)
                    dz.log('Switch off after ' .. SECONDS_ACTIVITY_LEVEL .. ' seconds.')
                end
            elseif triggeredItem.idx == idx_opple_hal_links or triggeredItem.idx == idx_opple_overloop_links or triggeredItem.idx == idx_opple_zolder_links then
                if triggeredItem.level == 10 then
                    dz.log('Knop links click')
                    dz.data.initiator = INITIATOR_OFF
                    lamp.cancelQueuedCommands()
                    lamp.switchOff()
                    dz.log('Switched off')
                elseif triggeredItem.level == 20 then
                    dz.data.initiator = INITIATOR_SWITCH
                    dz.log('Knop links dubbel klik, dim to 33%')
                    lamp.cancelQueuedCommands()
                    lamp.dimTo(33)
                    lamp.switchOff().afterSec(SECONDS_ACTIVITY_LEVEL_LONG)
                    dz.log('Switch off after ' .. SECONDS_ACTIVITY_LEVEL_LONG .. ' seconds.')
                elseif triggeredItem.level == 40 then
                    dz.data.initiator = INITIATOR_SWITCH
                    local dim = lamp.level
                    local t = 0
                    if dim == nil then dim = 100 end
                    while dim > 0 do
                        dim = dim - 5
                        if dim < 0 then dim = 0 end
                        t = t + 0.5
                        lamp.dimTo(dim).afterSec(t).silent()
                    end
                    dz.log('long click: Dim down')
                    lamp.switchOff().afterSec(SECONDS_ACTIVITY_LEVEL_LONG)
                    dz.log('Switch off after ' .. SECONDS_ACTIVITY_LEVEL_LONG .. ' seconds.')
                elseif triggeredItem.level == 50 then
                    dz.data.initiator = INITIATOR_SWITCH
                    lamp.cancelQueuedCommands()
                    dz.log('long click release: Stop dim')
                    lamp.switchOff().afterSec(SECONDS_ACTIVITY_LEVEL_LONG)
                    dz.log('Switch off after ' .. SECONDS_ACTIVITY_LEVEL_LONG .. ' seconds.')
                end
            elseif triggeredItem.idx == idx_opple_hal_rechts or triggeredItem.idx == idx_opple_overloop_rechts or triggeredItem.idx == idx_opple_zolder_rechts then
                if triggeredItem.level == 10 then
                    dz.data.initiator = INITIATOR_SWITCH
                    dz.log('Knop rechts click')
                    lamp.cancelQueuedCommands()
                    lamp.dimTo(DIMLEVEL_DEFAULT).silent()
                    lamp.switchOff().afterSec(SECONDS_ACTIVITY_LEVEL_LONG)
                    dz.log('Switch off after ' .. SECONDS_ACTIVITY_LEVEL_LONG .. ' seconds.')
                elseif triggeredItem.level == 20 then
                    dz.data.initiator = INITIATOR_SWITCH
                    dz.log('Knop rechts dubbel klik')
                    lamp.cancelQueuedCommands()
                    lamp.dimTo(67)
                    lamp.switchOff().afterSec(SECONDS_ACTIVITY_LEVEL_LONG)
                    dz.log('Switch off after ' .. SECONDS_ACTIVITY_LEVEL_LONG .. ' seconds.')
                elseif triggeredItem.level == 40 then
                    dz.data.initiator = INITIATOR_SWITCH
                    local dim = lamp.level
                    local t = 0
                    if dim == nil then dim = 0 end
                    while dim < 100 do
                        dim = dim + 5
                        if dim > 100 then dim = 100 end
                        t = t + 0.5
                        lamp.dimTo(dim).afterSec(t).silent()
                    end
                    lamp.switchOff().afterSec(SECONDS_ACTIVITY_LEVEL_LONG)
                    dz.log('Switch off after ' .. SECONDS_ACTIVITY_LEVEL_LONG .. ' seconds.')
                    dz.log('rechts long click: Dim up')
                elseif triggeredItem.level == 50 then
                    dz.data.initiator = INITIATOR_SWITCH
                    lamp.cancelQueuedCommands()
                    dz.log('long click release: Stop dim')
                    lamp.switchOff().afterSec(SECONDS_ACTIVITY_LEVEL_LONG)
                    dz.log('Switch off after ' .. SECONDS_ACTIVITY_LEVEL_LONG .. ' seconds.')
                end
            end
        end

        dz.log('New initiator = ' .. dz.data.initiator)

    end
}
ljanosi
Posts: 3
Joined: Wednesday 17 June 2020 20:32
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: Romania
Contact:

Re: Automatic switch off the IKEA bulb after power outage recovery - ZigBee2MQTT

Post by ljanosi »

Thanks! Besides checking if the trigger was a switch, a door sensor, a PIR (a device itself), is there a way to identify if the lamp was requested to be turned on as a valid intention by a dzventz script? I have different scripts (for ex. turning them on at a certain time in the morning with certain dim level). Maybe these valid requests can be "memorized" in a user variable (?) or best would be to have an indication that the trigger was a LUA/dzventz script.
ronaldbro
Posts: 327
Joined: Thursday 15 November 2018 21:38
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: Netherlands
Contact:

Re: Automatic switch off the IKEA bulb after power outage recovery - ZigBee2MQTT

Post by ronaldbro »

Don’t think there is way to check this other then making it yourself. And that’s basically what I did.
In this script I stored this in persistent data, but you could also tore it in global data or a user variable.
I think if you switch the light in multiple scripts it can get complex and the this mechanism could help also to determine which initiator has priority...
ljanosi
Posts: 3
Joined: Wednesday 17 June 2020 20:32
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: Romania
Contact:

Re: Automatic switch off the IKEA bulb after power outage recovery - ZigBee2MQTT

Post by ljanosi »

Thanks for the hints! Topic solved, more code but works, optimization will follow after some days of testing! For each bulb I defined a user variable named bulb_enable_X. At each zigbee light switch action this variable is set or reset according to the requested bulb operation. In a different script I am checking periodically the state of these variables and the actual state of the bulbs turning them off with a AfterSec(delay) in case they are not enabled. I am not using anymore the assigned dimmer type switches allocated to each Zigbee bulb, instead other custom defined dimmer switches are used to turn on/off the lights via the Domoticz application and UI.
As an additional measure I have a NodeRed flow to check directly the state of the bulbs via direct Zigbee2Mqtt Gateway periodical calls, in case the Domoticz bulb switch would not be updated accordingly (it happened) after power outage. This check is submitted back to Domoticz for evaluation in a script.
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest