ifttvar script  [Solved]

Easy to use, 100% Lua-based event scripting framework.

Moderator: leecollings

Post Reply
pvklink
Posts: 822
Joined: Wednesday 12 November 2014 15:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest b
Contact:

ifttvar script

Post by pvklink »

Some years ago, the forum made a script for me (many thanks to waaren) so i can send json data from the internet (google via IFTT) via a post to a domoticz uservariable.
The below script handles these json data and translate this data to domoticz actions, it works perfect for years.

I recently made a security configuration and i like to managed this by speak commands.

The json data for this script should be (i think)
[{"obj":"1728","act":"Disarm"}] or
[{"obj":1728,"act":"Disarm"}] ...

1728 is the idx of my securitypanel.

I get the msg that this isnt a device....
2021-02-18 19:18:57.856 Status: dzVents: Info: Handling variable-events for: "IFTTTvar", value: "[{"obj":1728,"act":"Disarm"}]"
2021-02-18 19:18:57.857 Status: dzVents: Info: ------ Start internal script: DZ_service_ifttt: Variable: "IFTTTvar" Index: 13
2021-02-18 19:18:57.870 Status: dzVents: Info: ------ Finished DZ_service_ifttt
2021-02-18 19:18:57.870 Error: dzVents: Error: (3.1.4) no device, scene, group or var found

Code: Select all

--[[
syntax of JSON in uservar:  
[
{"obj":"IFvar","set":"TestString"},
{"obj":"IFswitch","act":"On","fS":10,"aS":10,"si":true},
{"obj":IFswitchID,"type":"device","act":"On"},   if IFswitchID = numeric , type = device, group, etc mandatory
{"obj":"IFSelector","lbl":"Level1"},
{"obj":"IFScene","act":"On"}]

or 
[
{"obj":"IFvar","set":"TestString"},
{"obj":"message from ifttt","msg":["message to all"]},
{"obj":"IFSelector","lbl":"Level1"},
{"obj":"IFScene","act":"On"}
]

max. number of chars = 200
  
every action request in the json should have obj/object and max. one of (act/action, lbl/label, msg/message, set or upd/update, ). 
Other controls (aS/afterSec, fS/ forSec, rAS/repeatAfterSec, si/silent are optional.


if message/msg is the requested action the object field is used as subject and subtable [{}]

            mandatory       line.object    message subject
            mandatory       line.message[1] message body
            optional or nil line.message[2] message priority  (-2=LOW, -1=MODERATE, 0=NORMAL, 1=HIGH, 2=EMERGENCY)
            optional or nil line.message[3] message sound (string like 'pushover','bike','none')
            optional or nil line.message[4] extra 
            optional or nil line.message[5] subsystem or table with subsystems
            
            examples 
            [{"obj":"message from ifttt","msg":["message to all notification systems with default priority"]}]
            [{"obj":"message from ifttt","msg":["message to pushover with high priority",1,null,null,"pushover"]}]
            [{"obj":"message from ifttt","msg":["message to pushover and gcm with low priority",-2,null,null,["pushover","gcm"] ]}]

if OSCommand/os is the requested action, the object field is used program / scriptname. name must be full qualified e.g. "/home/pi/scripts/myScript.sh"

]]--
local iftttvar = "IFTTTvar"  

return 
{
    on =    
        { 
        variables = { iftttvar },   
        },
                    
    execute = function(dz, item)
    _G.logLevel = dz.helpers.get_logtype(dz)    -- dz.log('debug test',dz.LOG_DEBUG) this will only make it to the log when LOG_DEBUG is set  AND dz.log('blabla',dz.LOG_FORCE) -- this will allways make it tp the log
    _G.logMarker = _G.moduleLabel -- marker wordt scriptnaam, _G.logMarker = info.scriptName is idem

    -- HIER START DE EXECUTIE

        local function makeLongKeys(str)
            local shortNames = {    
                                    act="action",  -- optional: Can be On, Off or OS/OScommand: 
                                                   -- On; valid for switches and groups and scenes and scenes; Off; valid for switches and groups
                                    aS="afterSec", -- optional: 
                                    fS="forSec",   -- optional: Only valid for standard (On/Off) switches 
                                    lbl="label",   -- optional: levelName or number for selector type switches
                                    msg="message", -- Optional: obj must be set to subject 
                                    obj="object",  -- Mandatory and must be unique in domoticz: name for device, scene, group or uservariable.  
                                    os="OSCommand", -- if os / OSCommand is the requested action, obj must be set to full qualified script /program. 
                                    rAS="repeatAfterSec", -- optional: Only valid for standard (On/Off) switches 
                                    set="set",  -- Optional: update uservariable 
                                    si="silent",  -- Optional: use "si":true in JSON
                                    upd="update", -- Optional: Only valid for devices (set nValue, sValue)
                                    
                               }
 
            for short, long in pairs(shortNames) do
                str = str:gsub('%f[%a]' .. short .. '%f[%A]' ,long) -- this will only replace short with long if short is a whole word
            end
            return str  
        end
        
        local function getBaseType(line)
            if line.type then return line.type, line.object end
            for i, tuple in ipairs(_G.domoticzData) do 
                if tuple.name == line.object then 
                    return tuple.baseType, tuple.id 
                end
            end
        end
        
        local function makeTarget(baseType, identifier)
            if baseType == 'device' then 
                return dz.devices(identifier)
            elseif baseType == 'group' then 
                return dz.groups(identifier)
            elseif baseType == 'scene' then 
                return dz.scenes(identifier) 
            elseif baseType == 'uservariable' then 
                return dz.variables(identifier)
            end
        end

        local function doLabelVariant(line, target)
            if line.afterSec and line.silent then 
                target.switchSelector(line.label).silent().afterSec(line.afterSec)
            elseif line.afterSec then
                target.switchSelector(line.label).afterSec(line.afterSec)
           elseif line.silent then
                target.switchSelector(line.label).silent()
           else
                target.switchSelector(line.label)
           end
        end
        
        local function doUpdateVariant(line, target)
            if line.afterSec and line.silent then 
                target.update(line.update).silent().afterSec(line.afterSec)
            elseif line.silent then
                target.update(line.update).silent()
            elseif line.afterSec then
                target.update(line.update).afterSec(line.afterSec)
            else
                target.update(line.update)
            end
        end
        
        local function doSetVariant(line, target)
            if line.afterSec and line.silent then 
                target.set(line.set).silent().afterSec(line.afterSec)
            elseif line.silent then
                target.set(line.set).silent()
            elseif line.afterSec then
                target.set(line.set).afterSec(line.afterSec)
            else
                target.set(line.set)
            end
        end
        
        local function doOnVariant(line, target)
            if line.afterSec and line.forSec and line.silent then 
                target.switchOn().silent().afterSec(line.afterSec).forSec(line.forSec)
            elseif line.afterSec and line.repeatAfterSec and line.silent then 
                target.switchOn().silent().afterSec(line.afterSec).repeatAfterSec(line.repeatAfterSec)
            elseif line.afterSec and line.silent then
                target.switchOn().silent().afterSec(line.afterSec)
            -- start pvk

            elseif line.afterSec and line.forSec then 
                target.switchOn().afterSec(line.afterSec).forSec(line.forSec)
            elseif line.forSec then
                target.switchOn().forSec(line.forSec)
            -- einde pvk 

            elseif line.afterSec then
                target.switchOn().afterSec(line.afterSec)

            elseif line.silent then
                target.switchOn().silent()
            else
                target.switchOn()
           end
        end

        local function doArmVariant(line, target)
            
            target.armAway().checkFirst()

        end
        
        local function doOffVariant(line, target)
            if line.afterSec and line.forSec and line.silent then 
                target.switchOff().silent().afterSec(line.afterSec).forSec(line.forSec)
            elseif line.afterSec and line.repeatAfterSec and line.silent then 
                target.switchOff().silent().afterSec(line.afterSec).repeatAfterSec(line.repeatAfterSec)
            elseif line.afterSec and line.silent then
                target.switchOff().silent().afterSec(line.afterSec)
                
            -- pvk start
            elseif line.afterSec and line.forSec then 
                target.switchOff().afterSec(line.afterSec).forSec(line.forSec)
            elseif line.forSec then
                target.switchOff().forSec(line.forSec)
            -- pvk stop

            elseif line.afterSec then
                target.switchOff().afterSec(line.afterSec)
            elseif line.silent then
                target.switchOff().silent()
            else
                target.switchOff()
            end
        end

        local function doDisarmVariant(line, target)

            target.disarm()

        end

        local function doStopVariant(line, target)
            if line.afterSec and line.silent then 
                target.stop().silent().afterSec(line.afterSec)
            elseif line.afterSec then
                target.stop().afterSec(line.afterSec)
            elseif line.silent then
                target.stop().silent()
            else
                target.stop()
            end
        end
        
        local function doNotificationVariant(line)
            dz.notify(line.object,line.message[1],line.message[2] or nil,line.message[3] or nil,line.message[4] or nil,line.message[5] or nil)
        end

        local function doOSVariant(osCommand)
            os.execute('sudo ' .. osCommand .. ' &')
            dz.utils.dumpTable(result)
        end

        local function doTasks(result)
            for _, line in ipairs(result) do
                if line.message then
                    doNotificationVariant(line)
                elseif line.action == 'OSCommand' then
                    doOSVariant(line.object)
                else
                    local baseType, idx = getBaseType(line)
                    target = makeTarget(baseType, line.object)
                    if not(target) then 
                       dz.log('no device, scene, group or var found',dz.LOG_ERROR)
                       return 
                    end 
                    if line.action and line.action == 'Off' then -- for switch type devices and groups
                        doOffVariant(line, target)
                    elseif line.action and line.action == 'On' then -- for switch type devices, scenes and groups
                        doOnVariant(line, target)
                    elseif line.action and line.action == 'Arm' then -- for switch type devices, scenes and groups
                        doArmVariant(line, target)
                    elseif line.action and line.action == 'Disarm' then -- for switch type devices, scenes and groups
                        doDisarmVariant(line, target)
                    elseif line.action and line.action == 'OSCommand' then 
                        doOSVariant(line, target)
                    elseif line.action and line.action == 'Stop' then -- for type blinds 
                        doStopVariant(line, target)
                    elseif line.label then -- for selector type devices
                        doLabelVariant(line, target) 
                    elseif line.set then -- for uservariables
                        doSetVariant(line, target)
                    elseif line.update then -- for devices to set nValu, sValue
                        doUpdateVariant(line, target)
                    end
                end
            end
        end

        -- main 
        local result = dz.utils.fromJSON(makeLongKeys(item.value))
        doTasks(result)
        
    end 
}
Raspberry (raspbian on rpi 3) , Domoticz Beta, dzVents , RFXtrx433e, P1, Hue, Yeelight, Zwave+, X10, ESP(easy), MQTT,Weather Underground, System Alive Checker, Domoticz Remote Server to RPI with Google Assistant,
Jablotron connection, Ikea
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: ifttvar script

Post by waaren »

pvklink wrote: Thursday 18 February 2021 19:38 I recently made a security configuration and i like to managed this by speak commands.

The json data for this script should be (i think)
[{"obj":"1728","act":"Disarm"}] or
[{"obj":1728,"act":"Disarm"}] ...
The script does not work with idx but only with names. To control the security panel The var should look like

[{"obj":"Secure","act":"armAway" }] -- Replace "Secure" with the name of your securirity panel device, "act" can be disarm, armAway or armHome

Code: Select all

--[[
syntax of JSON in uservar:  
[
{"obj":"IFvar","set":"TestString"},
{"obj":"IFswitch","act":"On","fS":10,"aS":10,"si":true},
{"obj":IFswitchID,"type":"device","act":"On"},   if IFswitchID = numeric , type = device, group, etc mandatory
{"obj":"IFSelector","lbl":"Level1"},
{"obj":"IFScene","act":"On"}]

or 
[
{"obj":"IFvar","set":"TestString"},
{"obj":"message from ifttt","msg":["message to all"]},
{"obj":"IFSelector","lbl":"Level1"},
{"obj":"IFScene","act":"On"}
]

or
[
{"obj":"Secure","act":"armAway"}   -- "obj" is name of securirity panel device, "act"  is disarm, armAway or armHome 
]

max. number of chars = 200
  
every action request in the json should have obj/object and max. one of (act/action, lbl/label, msg/message, set or upd/update, ). 
Other controls (aS/afterSec, fS/ forSec, rAS/repeatAfterSec, si/silent are optional.


if message/msg is the requested action the object field is used as subject and subtable [{}]

            mandatory       line.object    message subject
            mandatory       line.message[1] message body
            optional or nil line.message[2] message priority  (-2=LOW, -1=MODERATE, 0=NORMAL, 1=HIGH, 2=EMERGENCY)
            optional or nil line.message[3] message sound (string like 'pushover','bike','none')
            optional or nil line.message[4] extra 
            optional or nil line.message[5] subsystem or table with subsystems
            
            examples 
            [{"obj":"message from ifttt","msg":["message to all notification systems with default priority"]}]
            [{"obj":"message from ifttt","msg":["message to pushover with high priority",1,null,null,"pushover"]}]
            [{"obj":"message from ifttt","msg":["message to pushover and gcm with low priority",-2,null,null,["pushover","gcm"] ]}]

if OSCommand/os is the requested action, the object field is used program / scriptname. name must be full qualified e.g. "/home/pi/scripts/myScript.sh"

]]--
local iftttvar = "IFTTTvar"  

return 
{
    on =    
        { 
        variables = { iftttvar },   
        },
                    
    execute = function(dz, item)
     _G.logLevel = dz.helpers.get_logtype(dz)    -- dz.log('debug test',dz.LOG_DEBUG) this will only make it to the log when LOG_DEBUG is set  AND dz.log('blabla',dz.LOG_FORCE) -- this will allways make it tp the log
    _G.logMarker = _G.moduleLabel -- marker wordt scriptnaam, _G.logMarker = info.scriptName is idem

    -- HIER START DE EXECUTIE

        local function makeLongKeys(str)
            local shortNames = {    
                                    act="action",  -- optional: Can be On, Off or OS/OScommand: 
                                                   -- On; valid for switches and groups and scenes and scenes; Off; valid for switches and groups
                                    aS="afterSec", -- optional: 
                                    fS="forSec",   -- optional: Only valid for standard (On/Off) switches 
                                    lbl="label",   -- optional: levelName or number for selector type switches
                                    msg="message", -- Optional: obj must be set to subject 
                                    obj="object",  -- Mandatory and must be unique in domoticz: name for device, scene, group or uservariable.  
                                    os="OSCommand", -- if os / OSCommand is the requested action, obj must be set to full qualified script /program. 
                                    rAS="repeatAfterSec", -- optional: Only valid for standard (On/Off) switches 
                                    set="set",  -- Optional: update uservariable 
                                    si="silent",  -- Optional: use "si":true in JSON
                                    upd="update", -- Optional: Only valid for devices (set nValue, sValue)
                                    
                               }
 
            for short, long in pairs(shortNames) do
                str = str:gsub('%f[%a]' .. short .. '%f[%A]' ,long) -- this will only replace short with long if short is a whole word
            end
            return str  
        end
        
        local function getBaseType(line)
            if line.type then return line.type, line.object end
            for i, tuple in ipairs(_G.domoticzData) do 
                if tuple.name == line.object then 
                    return tuple.baseType, tuple.id 
                end
            end
        end
        
        local function makeTarget(baseType, identifier)
            if baseType == 'device' then 
                return dz.devices(identifier)
            elseif baseType == 'group' then 
                return dz.groups(identifier)
            elseif baseType == 'scene' then 
                return dz.scenes(identifier) 
            elseif baseType == 'uservariable' then 
                return dz.variables(identifier)
            end
        end

        local function doLabelVariant(line, target)
            if line.afterSec and line.silent then 
                target.switchSelector(line.label).silent().afterSec(line.afterSec)
            elseif line.afterSec then
                target.switchSelector(line.label).afterSec(line.afterSec)
           elseif line.silent then
                target.switchSelector(line.label).silent()
           else
                target.switchSelector(line.label)
           end
        end
        
        local function doUpdateVariant(line, target)
            if line.afterSec and line.silent then 
                target.update(line.update).silent().afterSec(line.afterSec)
            elseif line.silent then
                target.update(line.update).silent()
            elseif line.afterSec then
                target.update(line.update).afterSec(line.afterSec)
            else
                target.update(line.update)
            end
        end
        
        local function doSetVariant(line, target)
            if line.afterSec and line.silent then 
                target.set(line.set).silent().afterSec(line.afterSec)
            elseif line.silent then
                target.set(line.set).silent()
            elseif line.afterSec then
                target.set(line.set).afterSec(line.afterSec)
            else
                target.set(line.set)
            end
        end
        
        local function doOnVariant(line, target)
            if line.afterSec and line.forSec and line.silent then 
                target.switchOn().silent().afterSec(line.afterSec).forSec(line.forSec)
            elseif line.afterSec and line.repeatAfterSec and line.silent then 
                target.switchOn().silent().afterSec(line.afterSec).repeatAfterSec(line.repeatAfterSec)
            elseif line.afterSec and line.silent then
                target.switchOn().silent().afterSec(line.afterSec)
            -- start pvk

            elseif line.afterSec and line.forSec then 
                target.switchOn().afterSec(line.afterSec).forSec(line.forSec)
            elseif line.forSec then
                target.switchOn().forSec(line.forSec)
            -- einde pvk 

            elseif line.afterSec then
                target.switchOn().afterSec(line.afterSec)

            elseif line.silent then
                target.switchOn().silent()
            else
                target.switchOn()
           end
        end

        local function doArmVariant(line, target)
            
            target.armAway().checkFirst()

        end
        
        local function doOffVariant(line, target)
            if line.afterSec and line.forSec and line.silent then 
                target.switchOff().silent().afterSec(line.afterSec).forSec(line.forSec)
            elseif line.afterSec and line.repeatAfterSec and line.silent then 
                target.switchOff().silent().afterSec(line.afterSec).repeatAfterSec(line.repeatAfterSec)
            elseif line.afterSec and line.silent then
                target.switchOff().silent().afterSec(line.afterSec)
                
            -- pvk start
            elseif line.afterSec and line.forSec then 
                target.switchOff().afterSec(line.afterSec).forSec(line.forSec)
            elseif line.forSec then
                target.switchOff().forSec(line.forSec)
            -- pvk stop

            elseif line.afterSec then
                target.switchOff().afterSec(line.afterSec)
            elseif line.silent then
                target.switchOff().silent()
            else
                target.switchOff()
            end
        end

        local function doSecurityVariant(line, target)
            if line.action == 'disarm' then target.disarm()
            elseif line.action == 'armAway' then target.armAway()
            elseif line.action == 'armHome' then target.armHome()
            
            end
        end

        local function doStopVariant(line, target)
            if line.afterSec and line.silent then 
                target.stop().silent().afterSec(line.afterSec)
            elseif line.afterSec then
                target.stop().afterSec(line.afterSec)
            elseif line.silent then
                target.stop().silent()
            else
                target.stop()
            end
        end
        
        local function doNotificationVariant(line)
            dz.notify(line.object,line.message[1],line.message[2] or nil,line.message[3] or nil,line.message[4] or nil,line.message[5] or nil)
        end

        local function doOSVariant(osCommand)
            os.execute('sudo ' .. osCommand .. ' &')
            dz.utils.dumpTable(result)
        end

        local function doTasks(result)
            for _, line in ipairs(result) do
                if line.message then
                    doNotificationVariant(line)
                elseif line.action == 'OSCommand' then
                    doOSVariant(line.object)
                else
                    local baseType, idx = getBaseType(line)
                    target = makeTarget(baseType, line.object)
                    if not(target) then 
                       dz.log('no device, scene, group or var found',dz.LOG_ERROR)
                       return 
                    end 
                    if line.action and line.action == 'Off' then -- for switch type devices and groups
                        doOffVariant(line, target)
                    elseif line.action and line.action == 'On' then -- for switch type devices, scenes and groups
                        doOnVariant(line, target)
                    elseif line.action and ( line.action == 'armAway' or line.action == 'disarm' or line.action == 'armHome' ) then -- for Security panel
                        doSecurityVariant(line, target)
                    elseif line.action and line.action == 'OSCommand' then 
                        doOSVariant(line, target)
                    elseif line.action and line.action == 'Stop' then -- for type blinds 
                        doStopVariant(line, target)
                    elseif line.label then -- for selector type devices
                        doLabelVariant(line, target) 
                    elseif line.set then -- for uservariables
                        doSetVariant(line, target)
                    elseif line.update then -- for devices to set nValu, sValue
                        doUpdateVariant(line, target)
                    else
                        dz.log('eehhhhhhh',dz.LOG_FORCE)
                    end
                end
            end
        end

        -- main 
        local result = dz.utils.fromJSON(makeLongKeys(item.value))
        doTasks(result)
        
    end 
}
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
pvklink
Posts: 822
Joined: Wednesday 12 November 2014 15:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest b
Contact:

Re: ifttvar script

Post by pvklink »

thanks!
i will test it and describe this in the script!
Raspberry (raspbian on rpi 3) , Domoticz Beta, dzVents , RFXtrx433e, P1, Hue, Yeelight, Zwave+, X10, ESP(easy), MQTT,Weather Underground, System Alive Checker, Domoticz Remote Server to RPI with Google Assistant,
Jablotron connection, Ikea
pvklink
Posts: 822
Joined: Wednesday 12 November 2014 15:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest b
Contact:

Re: ifttvar script

Post by pvklink »

ok, it works, but a little bit different, but it helped me enough !, thanks!

[{"obj":"Domoticz Security Panel","act":"Disarm"}] works
[{"obj":"Domoticz Security Panel","act":"Arm"}] works
armAway armHome dont
Raspberry (raspbian on rpi 3) , Domoticz Beta, dzVents , RFXtrx433e, P1, Hue, Yeelight, Zwave+, X10, ESP(easy), MQTT,Weather Underground, System Alive Checker, Domoticz Remote Server to RPI with Google Assistant,
Jablotron connection, Ikea
pvklink
Posts: 822
Joined: Wednesday 12 November 2014 15:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest b
Contact:

Re: ifttvar script

Post by pvklink »

changed this
local function doarmHomeVariant(line, target)

target.armHome().checkFirst()

end

local function doarmAwayVariant(line, target)

target.armAway().checkFirst()

and this part
elseif line.action and line.action == 'armHome' then -- for switch type devices, scenes and groups
doarmHomeVariant(line, target)
elseif line.action and line.action == 'armAway' then -- for switch type devices, scenes and groups
doarmAwayVariant(line, target)
Raspberry (raspbian on rpi 3) , Domoticz Beta, dzVents , RFXtrx433e, P1, Hue, Yeelight, Zwave+, X10, ESP(easy), MQTT,Weather Underground, System Alive Checker, Domoticz Remote Server to RPI with Google Assistant,
Jablotron connection, Ikea
pvklink
Posts: 822
Joined: Wednesday 12 November 2014 15:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest b
Contact:

Re: ifttvar script  [Solved]

Post by pvklink »

Case closed!
Thanks again waaren.
This script is by far the most important part of my speech infra!
still very happy with it...
I used it icm with IFTT and NODE-RED
Raspberry (raspbian on rpi 3) , Domoticz Beta, dzVents , RFXtrx433e, P1, Hue, Yeelight, Zwave+, X10, ESP(easy), MQTT,Weather Underground, System Alive Checker, Domoticz Remote Server to RPI with Google Assistant,
Jablotron connection, Ikea
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest