Check Sensors script (dzVents)  [Solved]

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

Moderator: leecollings

renerene
Posts: 351
Joined: Wednesday 03 August 2016 11:36
Target OS: -
Domoticz version:
Contact:

Check Sensors script (dzVents)

Post by renerene »

I wanted to share my first dzVents program with you. It is a checkSensor variant.
Allthough it's a mix of Dutch and English, I'm sure you will be able to understand it.

Functions:
1)check every 5 minutes if last signal time exceeds limit
2) time limit per sensor adjustable (some sensors update every minute, others once a day); simply adjust the table in the code
3) special 'On holiday' modus . Make sure you create a string variable 'opVakantie' with values 'ja' or 'nee'
4) receive a notification if a sensor passes out. (just once, no mail bomb as seen in other CheckSensor scripts)
5) receive a reminder once a day of passed out sensors. Just to make sure you don't forget to put in new batteries
6) receive a notification when the sensor is up again

Log example:
2017-07-27 19:00:00.528 dzVents: Info: ------ Start internal script: dzCheckSensors:, trigger: every 5 minutes
2017-07-27 19:00:00.533 dzVents: Info: dzCheckSensors: start
2017-07-27 19:00:00.719 dzVents: Info: dzCheckSensors: Device PIR_woonkamer is 9.75 uren niet gezien. Batterij leeg?
2017-07-27 19:00:00.733 dzVents: Info: dzCheckSensors: OKAY: Stroom: 2 seconden geen reactie, grenswaarde=5 minuten
2017-07-27 19:00:00.740 dzVents: Info: dzCheckSensors: OKAY: badkamer thermo hygro sensor: 26 seconden geen reactie, grenswaarde=5 minuten
2017-07-27 19:00:00.760 dzVents: Info: dzCheckSensors: OKAY: regenmeter: 29 seconden geen reactie, grenswaarde=5 minuten
2017-07-27 19:00:00.767 dzVents: Info: ------ Finished dzCheckSensors


Update version 3, 2019-01-19

Code: Select all

--version 3
--http://www.domoticz.com/forum/viewtopic.php?f=23&t=18566
--thanks to dannybloe

return {
	active = true,
	
	logging = {
		level = domoticz.LOG_DEBUG, -- comment to use the dzVents global logging setting
		marker = 'dzChecksensors'
	},
	on = {
	    timer = {'every 15 minutes'}
	    --,devices = {'triggerhulp'}
	},
    data = {
        notified = {initial={}}
    },
	execute = function(dz)
	    
        function schrijfTijd(secs)
            local t
            secs=tonumber(secs)
            if secs == nil then t='NIL'
                elseif secs >= 259200 then t=string.sub(tostring(secs/24/3600),1,4)..' days'  
                elseif secs >= 10800    then t=string.sub(tostring(secs/3600),1,4)..' hours'  -- meer dan 3 uur? 
                elseif secs >= 180      then t=string.sub(tostring(secs/60),1,4)..' minutes'
                else t=secs..' seconds' 
            end
            return t 
        end
	    
	    local notifyTime='at 18:30' --you can add multiple notification times, i.e. 'at 12:00, at 20:00'
	    local notifyHead='dzCheckSensors3'
	    local notifyMessageType=30 --log + pushover 
	    local notified = dz.data.notified -- short reference
	    	    
	    meld ('start', 99)
        if dz.devices('opVakantie').level==30 then
            -- timeout for each  device, in secondsAgo (during holiday)
            --holiday
            toCheck = {    -- timeout for each  device, in seconde.
                ['PIR_woonkamer'] = 1209600,          -- 2 weken
                ['PIR_keuken']=1206600,      -- 2 weken
                ['buitentemperatuur'] = 14400,           -- 4 uur
                ['Stroom'] = 300,                         -- 5 minuten
                ['schemerschakelaar'] = 172800,             -- 2dagen
                ['LUX'] = 54000 -- 15 uur
            }
        else
            toCheck = {    
                -- timeout for each  device, in secondsAgo (no holiday)
                ['PIR_woonkamer']       =172800,               -- 2 dagen
                ['PIR badkamer']        =172800,                -- 2 dagen
                ['pirTuin']            =340000,                    -- ca 3 dagen
                ['PIR_garage']          =172800,                  -- 2 dagen
                --['PIR_zolder']          =172800,                  -- 2 dagen
                ['PIR_keuken']          =172800,                  -- 2 dagen
                ['buitentemperatuur']   = 3600,           -- 1 uur
                ['schemerschakelaar']   = 172800, -- 2dagen
                ['LUX']                 = 54000, -- 15 uur
                ['LUXtuin']             = 54000, -- 15 uur 
                ['keukenLux']           = 54000, -- 15 uur
                ['Woonkamer Temperature'] = 7200 --2 uur; iets ruimer gezet, want sensor geeft geen update bij constante temperatuur
            }
        end
     	
     	--purge notified table, in case there was a switch from holiday variable to a "toCheck" table with less entrie
     	for deviceName, lastUpdate in pairs(notified) do
     	    if toCheck[deviceName]==nil then
     	            notified[deviceName]=nil
     	            meld (deviceName.. ' was removed from the notified table, '..schrijfTijd(treshold),99)
     	            dz.helpers.managedNotify(dz, notifyHead, deviceName..' was removed from the notified table, ', 0, 2, 0) --write to LOG
 	        end
        end
        
        --the main routine:
        for deviceName, treshold in pairs(toCheck) do
            local lastUpdate = dz.devices(deviceName).lastUpdate.secondsAgo
            if lastUpdate < treshold then
                --device is alive
                if notified[deviceName] == nil then
                    dz.helpers.managedNotify(dz, notifyHead,deviceName ..": "..schrijfTijd(lastUpdate).. ' no response, treshold='..schrijfTijd(treshold)..'--> ok', 0, 2, 0) --write to LOG:
                else
                    dz.helpers.managedNotify(dz, notifyHead,'Signal back from sensor'..deviceName, 0, notifyMessageType, 0)
                    notified[deviceName] = nil  --remove from notified list
                end
            --'opVakantie': 0=werk / 10 = vrij thuis, laat wakker / 20=vrij thuis, vroeg wakker/ 30=op vakantie  / 40=babysit
            else --lost signal:
                if 
                    notified[deviceName] == nil 
                then
                    --immediate notification after signal lost:
                    dz.helpers.managedNotify(dz, notifyHead,'Signal lost: '..deviceName .."sent "..schrijfTijd(lastUpdate).. '  the last signal, treshold='..schrijfTijd(treshold)..'. Battery empty?', 0, notifyMessageType, 1)
                elseif
                    --sent reminders on daily basis:
                    dz.time.matchesRule(notifyTime) and  --time slot to notify
                    dz.devices('opVakantie').level~=30 -- not on holiday
                then
                    dz.helpers.managedNotify(dz, notifyHead,'Reminder, '..deviceName .." sent "..schrijfTijd(lastUpdate).. ' the last signal. Battery empty?', 0, notifyMessageType, 1)
                end
            end    
        end
    end
    }
You need to add this function to your global_data:

Code: Select all

managedNotify = function (dz, header, message, prio, messageType, muteTimeMin) 
            --thanks to Waaren, https://www.domoticz.com/forum/viewtopic.php?f=59&t=26542&p=203675#p203630
            --messageType 2=log, 3=pushover, 5=speak, 7=siren; multiply values for combinations i.e. 15=pushover and speak
            local now = os.time(os.date('*t'))                  -- seconds since 1/1/1970 00:00:01
            if ( not dz.globalData.managedNotifications[message] ) or 
                (( dz.globalData.managedNotifications[message] + muteTimeMin * 60 ) <= now )
            then
                if messageType % 2 == 0 then dz.log(message ,dz.LOG_FORCE) end
                if messageType % 3 == 0 then dz.notify(header..'#'..message..'#'..prio) end
                if messageType % 5 == 0 then 
                    dz.openURL ('http://192.168.0.xxx:xxxx/jarvis?jKey=s829kuifd77tpe35ab&action=execute&type=TTS&data={"text":"'..dz.utils.urlEncode(message,'%20')..'","volume":"50"}')
                end
                if messageType % 7 == 0 then domoticz.devices('Sirene').switchOn().forSec(3) end
                --dz.notify("managedNotification", message,nil,nil,nil,messageType)      
                dz.globalData.managedNotifications[message] = now
            end
        end,
   
Last edited by renerene on Saturday 19 January 2019 21:03, edited 7 times in total.
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: Check Sensors script (dzVents)

Post by dannybloe »

Hi renerene,

Thanks for sharing. I do see quite some areas where you can optimize or simplify your code. Some tips:
  • Don't use the 'old' Lua tables like uservariables. dzVents has support for that as well (domoticz.variables) and the 'old' tables may disappear some day when running dzVents scripts.
  • Do declare all your variables as local instead of global. That way you know for sure you don't have undesired side-effects.
  • Move your helper functions outside the execute block (just above the return { .. } (and declare them with local function meld() ... end. That keeps your execute logic cleaner and shorter. Easier to read and maintain.
  • Create a shortcut for long structures: something like: 'local data = domoticz.data.reportTime' and from then on use 'data'. That's much shorter and easier to read. (data is just an example name)
  • You don't really need the schrijfTijd function as the time object already has almost anything you need. Check the documentation for dzVents regarding time object.
  • But mostly you can benefit from a much easier data structure for reportTime. You create an indexed table and use things like index+2 to access datapoints. Way too complicated. You can use a table as a key/value lookup as well. While filling the table you can do this: domoticz.data.reportTime[ <deviceName> ]={ something=1, somethingElse=2, andMore=3}. Then later on you can access this like: domoticz.data.reportTime[ <deviceName> ].something. That makes your code a lot easier to read and better to maintain. (<deviceName> is just a placeholder for a variable holding the name of your device). Check out the documentation about Lua tables.
  • Always write your code in english. No matter how hard it is. ;)
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
snuiter
Posts: 67
Joined: Saturday 17 June 2017 12:30
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Contact:

Re: Check Sensors script (dzVents)

Post by snuiter »

interesting script, I am seeing some new things like "domoticz.log ('<font color="purple">" which I probably will use apart from the overall script usability. Great work.

Minor comment this one set me off at first you want to change the comment as 800 sec is not one week ;)

--'PIR_woonkamer',604800, -- 1 week
'PIR_woonkamer',800, -- 1 week

Keep sharing these script
renerene
Posts: 351
Joined: Wednesday 03 August 2016 11:36
Target OS: -
Domoticz version:
Contact:

Re: Check Sensors script (dzVents)

Post by renerene »

Wow, thanks for the extensive review and suggestions. Gonna look into it, version 2 is on it's way
renerene
Posts: 351
Joined: Wednesday 03 August 2016 11:36
Target OS: -
Domoticz version:
Contact:

Re: Check Sensors script (dzVents)

Post by renerene »

Move your helper functions outside the execute block (just above the return { .. } (and declare them with local function meld() ... end. That keeps your execute logic cleaner and shorter. Easier to read and maintain.
I started that way, in the top with print commands. However it turns out the 'meld' function with the domoticz.log and domoticz.notify commands can only function within the execute part, otherwise:
2017-07-27 23:54:00.463 Error: dzVents: Error: ...cz/scripts/dzVents/generated_scripts/dzCheckSensors2.lua:3: attempt to index global 'domoticz' (a nil value)
Last edited by renerene on Friday 28 July 2017 9:00, edited 1 time in total.
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: Check Sensors script (dzVents)

Post by dannybloe »

No, you just have to pass it the domoticz object or even the log function. I'd take some time and read about local and global variables and scoping

Anyway, there are several ways how to do this:

Code: Select all

local function log(domoticz, message, priority)
	-- your code here
	domoticz.log(message, priority)
end

return {
	execute = function(domoticz, device)
		log(domoticz, "dzVents r0cks!", domoticz.LOG_INFO)
	end
}
Another way that should work:

Code: Select all

-- create a local dz than can be used in this entire module.
-- set this in your execute function
local dz

local function log(message, priority)
	-- your code here
	dz.log(message, priority)
end

return {
	execute = function(domoticz, device)
		dz = domoticz  -- initialize the dz variable
		log("dzVents r0cks!", dz.LOG_INFO)
		
		-- from now on we can use dz
		dz.notify(...) 
	end
}
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: Check Sensors script (dzVents)

Post by dannybloe »

Ok, I looked at your code a bit more and discovered that it was almost like a script that I wrote for myself. I adapted it a bit to match yours more. Like I said earlier I think you overcomplicate things quite a bit. All you want to know (I guess ;) ) is if a device hasn't been responding for a certain threshold. If that threshold is exceeded you want to be notified but only once a day at 19:00. So, first of all, why check every 5 minutes? If you just check all your devices at 19:00 then you will catch devices that stopped reporting earlier that day as well. So, here is my take on it (untested though).

Code: Select all

local devicesToCheck = {
	['deviceA'] = 800, -- threshold in seconds
	['deviceB'] = 900,
	['deviceC'] = 900
}

local devicesToCheckHolliday = {
	['deviceA'] = 3800,
	['deviceC'] = 1900
}

return {
	active = true,
	on = { timer = { 'at 19:00' } },
	data = { notified = { initial = {} } },
	execute = function(dz)
	
		local notified = dz.data.notified -- short reference
		local toCheck = dz.variables('holiday') and devicesToCheckHolliday or devicesToCheck
		
		for deviceName, threshold in pairs(toCheck) do
			local lastUpdate = dz.devices(deviceName).lastUpdate.secondsAgo
			if (lastUpdate > threshold and notified[deviceName] == nil) then
				dz.log(deviceName .. 'is inactive for ' .. lastUpdate .. 's. Threshold=' .. threshold, dz.LOG_ERROR)
				notified[deviceName] = lastUpdate -- mark as notified
			else
				notified[deviceName] = nil -- remove from notified list
			end
		end
	end
}
As you can see I have created a persistent variable notified. That's just a lookup list. If a device has become active again then its lastUpdate will be below the threshold and at 19:00 it will be removed from the notified list.
Maybe you have to add a check to make sure dz.devices(deviceName) is not nil and send out a notification properly.
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
renerene
Posts: 351
Joined: Wednesday 03 August 2016 11:36
Target OS: -
Domoticz version:
Contact:

Re: Check Sensors script (dzVents)

Post by renerene »

1) yes it has no use to set treshold to 5 min or to run the script every 5 mins if you only send reminder at 19:00 hr. That was my old LUA. This was the main reason to rewrite it in dzVents. With the global variables it is easy to send a notification immediatly, but also one at 19:00 hr
2) thank you for the script. Very helpful learning aid.
3) I've addad a purge section for the notified table.
4) "notified[deviceName] = lastUpdate" does not work (?as first entry?)
2017-07-28 13:00:01.999 Error: dzVents: Error: ...cz/scripts/dzVents/generated_scripts/dzCheckSensors2.lua:83: attempt to index global 'notified' (a nil value)

this my halfway tested script, version 2:

Code: Select all

function schrijfTijd(secs)
    local t
    secs=tonumber(secs)
    if secs == nil then t='NIL'
        elseif secs >= 259200 then t=string.sub(tostring(secs/24/3600),1,4)..' dagen'  
        elseif secs >= 10800    then t=string.sub(tostring(secs/3600),1,4)..' uren'  -- meer dan 3 uur? 
        elseif secs >= 180      then t=string.sub(tostring(secs/60),1,4)..' minuten'
        else t=secs..' seconden' 
    end
    return t 
end

function meld (dz, melding, prio)
    if debug==1 then dz.log ('<font color="purple">dzCheckSensors: '..melding) end
--    if prio==-1 then dz.notify('dzCheckSensors',melding, dz.PRIORITY_LOW)
--        elseif prio==1 then dz.notify('dzCheckSensors',melding, dz.PRIORITY_HIGH)
--        elseif prio~=99 then dz.notify('dzCheckSensors',melding, dz.PRIORITY_NORMAL) 
--    end
end 

return {
	active = true,
	on = {
	    timer = {'every minute'}
	},
    data = {
        notified = {initial={}}
    },
	execute = function(dz)
	    
	    debug=1
	    local reporthour=19
	    local reportmin=0 --> send a daily remninder at 19:00 
	    local toCheck
	    	    
	    meld (dz, 'start', 99)
        if dz.variables('opVakantie').value== 'ja' then
            toCheck = {    -- timeout for each  device, in seconde.
                ['PIR_woonkamer'] = 800,               -- 1 week
                ['Stroom'] = 300,                         -- 5 minuten
                ['badkamer thermo hygro sensor'] = 300,   -- 5 minuten
                ['regenmeter'] = 300   -- 5 minuten
            }
        else
            toCheck = {    -- timeout for each  device, in seconde.
                ['PIR_woonkamer']       =80,               -- 2 dagen
                ['PIR badkamer']        =172800,                -- 2 dagen
                ['PIR_tuin']            =340000,                    -- ca 3 dagen
                ['PIR_garage']          =172800,                  -- 2 dagen
                ['PIR_zolder']          =172800,                  -- 2 dagen
                ['deurBrittO']          =172800,                  -- 2 dagen
                ['deurLynnO']           =172800,                   -- 2 dagen
                ['deurZolderO']         =172800,                 -- 2 dagen
                ['Stroom']              =300,                         -- 5 minuten
                ['badkamer thermo hygro sensor']=300,           -- 5 minuten
                ['regenmeter']          =300                    -- 1 uur
            }
        end
     	
     	--purge notified table, in case there was a switch from holiday variable to a "toCheck" table with less entries
     	if notified then
     	    for deviceName, lastUpdate in pairs(notified) do
     	        if toCheck[deviceName]==nil then
     	            notified[deviceName]=nil
     	            meld (dz,deviceName.. ' was removed from the notified table'..schrijfTijd(treshold),99)
 	            end
             end
        end
 
        for deviceName, treshold in pairs(toCheck) do
            local lastUpdate = dz.devices(deviceName).lastUpdate.secondsAgo
            if lastUpdate < treshold then
                if notified == nil  or notified[deviceName] == nil then
                    meld (dz,'OKAY: '..deviceName ..": "..schrijfTijd(lastUpdate).. ' geen reactie, grenswaarde='..schrijfTijd(treshold),99)
                else
                    meld (dz,'SIGNAL BACK van sensor'..deviceName ..", "..schrijfTijd(lastUpdate).. ' geleden laatste reactie, grenswaarde='..schrijfTijd(treshold),0)
                    notified[deviceName] = nil  --remove from notified list
                end
            elseif notified == nil or notified[deviceName] == nil or (dz.time.hour==reporthour and dz.time.min==reportmin) then 
                meld (dz,'Device '..deviceName..' is '..schrijfTijd(lastUpdate)..' niet gezien. Batterij leeg?',0) 
                notified[deviceName] = lastUpdate
            else
                meld (dz,'NOK (reported): '..deviceName ..": "..schrijfTijd(t).. ' geen reactie, grenswaarde='..schrijfTijd(treshold),99)
            end
        end

    end
    }
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: Check Sensors script (dzVents)

Post by dannybloe »

looks like you forgot the initialize 'notified'. See my example. Should be done at the beginning of your execute script.
And I wouldn't bother with cleaning up the notified list. Entries from devices that are active will be removed anyway.
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
renerene
Posts: 351
Joined: Wednesday 03 August 2016 11:36
Target OS: -
Domoticz version:
Contact:

Re: Check Sensors script (dzVents)

Post by renerene »

yes, because I forgot the 'short reference' part, the table acted as a local variable.
Updated script in the original post
R1ch9rd80
Posts: 2
Joined: Wednesday 16 January 2019 18:48
Target OS: NAS (Synology & others)
Domoticz version: 2020.2
Contact:

Re: Check Sensors script (dzVents)

Post by R1ch9rd80 »

This script works great. Dank je wel renerene!

Is it possible to send one notification mail message with all sensors results instead of several separate mails?
And is it possible to send a notification mail at multiple times, like at 10.00 and 19.00?
renerene
Posts: 351
Joined: Wednesday 03 August 2016 11:36
Target OS: -
Domoticz version:
Contact:

Re: Check Sensors script (dzVents)

Post by renerene »

R1ch9rd80 wrote: Wednesday 16 January 2019 18:56 Is it possible to send one notification mail message with all sensors results instead of several separate mails?
And is it possible to send a notification mail at multiple times, like at 10.00 and 19.00?
First request takes some work and is not done, because in normal condition only few sensors lose signal, so no need to combine large amount of notifications.
The second request is in the original post answered in version 3. There is a variable notifyTime which allows you to define multiple notification times.
hoeby
Posts: 531
Joined: Saturday 02 June 2018 11:05
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.1
Location: Echt, Netherlands
Contact:

Re: Check Sensors script (dzVents)

Post by hoeby »

Trying to use this, but don't get what to do with the global_data

When calling that in dzvents, there is already information in the script.
Where in the script do i need to add it?

Just tried to copy the data in this thread and post it there where it writes --code

But when i trigger the script. I get an error on line with info meld ('start', 99), nil value.
Don't know where i did something wrong. I changed the devices to one i have.

Code: Select all

-- this scripts holds all the globally persistent variables and helper functions
-- see the documentation in the wiki
-- NOTE:
-- THERE CAN BE ONLY ONE global_data SCRIPT in your Domoticz install.

return {
	-- global persistent data
	data = {
		myGlobalVar = { initial = 12 }
	},

	-- global helper functions
	helpers = {
		myHelperFunction = function(domoticz)
			-- code
			
		end
	}
}
Thin-client --> Docker Domoticz main environment
Pi3A+ --> Google home (GAssistPi)
Pi3B+ --> Docker (P1monitor, Domoticz test environment, Ubiquity controller)
hoeby
Posts: 531
Joined: Saturday 02 June 2018 11:05
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.1
Location: Echt, Netherlands
Contact:

Re: Check Sensors script (dzVents)

Post by hoeby »

I think i have the global info at the right place.
But in the dzvents script there are some things i don't get.

There needs to be a variable string "opVakantie".
But the script looks for this, that's a device not a variable:

Code: Select all

if dz.devices('opVakantie').level==30 then
This is the error i have:

Code: Select all

2019-06-01 22:18:48.004 Status: dzVents: Info: dzChecksensors: ------ Start internal script: Device-alive-check: Device: "Slide2 (Dummy switches)", Index: 90 
2019-06-01 22:18:48.004 Status: dzVents: Error (2.4.19): dzChecksensors: An error occured when calling event handler Device-alive-check 
2019-06-01 22:18:48.004 Status: dzVents: Error (2.4.19): dzChecksensors: ...scripts/dzVents/generated_scripts/Device-alive-check.lua:39: attempt to call global 'meld' (a nil value) 
2019-06-01 22:18:48.004 Status: dzVents: Info: dzChecksensors: ------ Finished Device-alive-check
Somebody can help me?
Thin-client --> Docker Domoticz main environment
Pi3A+ --> Google home (GAssistPi)
Pi3B+ --> Docker (P1monitor, Domoticz test environment, Ubiquity controller)
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: Check Sensors script (dzVents)

Post by waaren »

hoeby wrote: Saturday 01 June 2019 22:18 There needs to be a variable string "opVakantie".
It seems that the script changed and the description in the first post has not been updated for this.
The script now refers to opVakantie as a selector switch. Hopefully @renerene is still checking the forum and can help
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
hoeby
Posts: 531
Joined: Saturday 02 June 2018 11:05
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.1
Location: Echt, Netherlands
Contact:

Re: Check Sensors script (dzVents)

Post by hoeby »

I just noticed that.

I see these options in the selector switch:

Code: Select all

'opVakantie': 0=werk / 10 = vrij thuis, laat wakker / 20=vrij thuis, vroeg wakker/ 30=op vakantie  / 40=babysit
But could this be the problem, that i gives a nil value?
The word "meld", could that work, or do i need some dictionary, because it is englisch and dutch in 1 scripts?
Thin-client --> Docker Domoticz main environment
Pi3A+ --> Google home (GAssistPi)
Pi3B+ --> Docker (P1monitor, Domoticz test environment, Ubiquity controller)
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: Check Sensors script (dzVents)

Post by waaren »

hoeby wrote: Saturday 01 June 2019 23:06 ...But could this be the problem, that i gives a nil value?
No that is a different one.
The word "meld", could that work, or do i need some dictionary, because it is englisch and dutch in 1 scripts?
It does produce an error because function "meld" nor an equivalent in another language does exist in the script.
If @renerene does no longer maintain / support the script, it is probably better to write your own. The functionality is not very complicated and the required code parts / functions are already on the forum.
Happy to help where needed.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
hoeby
Posts: 531
Joined: Saturday 02 June 2018 11:05
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.1
Location: Echt, Netherlands
Contact:

Re: Check Sensors script (dzVents)

Post by hoeby »

waaren wrote: Sunday 02 June 2019 8:49 If @renerene does no longer maintain / support the script, it is probably better to write your own. The functionality is not very complicated and the required code parts / functions are already on the forum.
Happy to help where needed.
Thanks for your support and help.

It is exactly what i started after the last post from yesterday.
Started small and that works. Now adding the extra functions which @renerene uses in his script. Looks good until now, but not finished. When finished and @renerene doesn't do support on his script, than i can share mine if that's ok
Thin-client --> Docker Domoticz main environment
Pi3A+ --> Google home (GAssistPi)
Pi3B+ --> Docker (P1monitor, Domoticz test environment, Ubiquity controller)
hoeby
Posts: 531
Joined: Saturday 02 June 2018 11:05
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.1
Location: Echt, Netherlands
Contact:

Re: Check Sensors script (dzVents)

Post by hoeby »

Got the script working.

Some attention to everybody who want to use the @renerene script.
There are some little faults in his script. Some are the language difference (don't know if this is fault, @renerene has chosen for this), but the word "threshold" is sometimes writen as "treshold".

I changed the script to my own wishes.
I don't use the global_data.lua. Don't know if this is OK of NOT. Maybe somebody with a very good dzVents knowledge can answer this.

What is the minimum you need to make?
Make a switch (on/off) with the name "opVakantie"
I made the notification for Telegram, fill in you chatID and token, to receive the message
With this switch you can change the threshold if you are on vacation or not. If not wanted, you can cut it out.
And of course your own devices need to be added with the threshold you like

Code: Select all

return {
    on = {
        timer = { 'at 08:00, at 10:00'  }, --Information: your notifyTime needs to be in this timer, to trigger the script
        --timer = { 'every 1 minutes' },
        httpResponses = {
            'smokeInfo'
        }
    },

    data = { notified = { initial = {} } },
    execute = function(dz, item)
  
        function writeTime(secs)
            local t
            secs=tonumber(secs)
            if secs == nil then t='NIL'
                elseif secs >= 86400   then t=string.sub(tostring(secs/24/3600),1,4)..' days'  
                elseif secs >= 3600    then t=string.sub(tostring(secs/3600),1,4)..' hours' 
                elseif secs >= 60      then t=string.sub(tostring(secs/60),1,4)..' minutes'
                else t=secs..' seconds' 
            end
            return t 
        end
        
        local notifyTime = 'at 10:00' --you can add multiple notification times, i.e. 'at 12:00, at 20:00'
	    local notifyHead = 'dzCheckSensors'
	    local notified   = dz.data.notified -- short reference
	    local teleTok    = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
        local chatId     = 'xxxxxxxxxxxxxx'
        
        if dz.devices('opVakantie').state== 'On' then
	        toCheck = {    -- timeout for each device, in seconds (with holiday)
                ['Smoke-801414201509-zigbee']       = 1209600,    -- 2 weken
            }
        else
            toCheck = {    -- timeout for each device, in seconds (no holiday)
                ['Smoke-801414201509-zigbee']       = 172800,     -- 2 dagen
            }
        end
	
        if (item.isTimer) then
            dz.openURL({
                url = 'http://xxx.xxx.xxx.xxx:xxxx/json.htm?type=devices&rid=339',
                method = 'GET',
                callback = 'smokeInfo',
            })
        end
  
        for deviceName, lastUpdate in pairs(notified) do
     	    if toCheck[deviceName]==nil then
     	            notified[deviceName]=nil
     	            dz.log (notifyHead .." ".. deviceName.. ' was removed from the notified table, '..writeTime(threshold),99)
             end
        end

        if (item.isHTTPResponse and item.ok) then
            local Time = require('Time')
            local results = item.json.result

            for i, node in pairs(results) do
                -- dzVents Time object
                local lastSeen = Time(node.LastUpdate)
                local lastUpdate = lastSeen.secondsAgo

                for deviceName, threshold in pairs(toCheck) do
            		if lastUpdate < threshold then
              		    --device is alive
                    if notified[deviceName] == nil then
                        dz.log(notifyHead .." ".. deviceName ..": "..writeTime(lastUpdate).. ' was last response, threshold='..writeTime(threshold))
                    else
                        dz.log(notifyHead .." ".. 'Signal back from sensor '..deviceName)
                        notified[deviceName] = nil  --remove from notified list
                        os.execute('curl -s -X POST "https://api.telegram.org/bot'..teleTok..'/sendMessage?chat_id='..chatId..'&text='..notifyHead .." ".. 'Signal back from sensor '..deviceName ..'."')
                    end
                else 
                        --lost signal:
                    if notified[deviceName] == nil then
                        --immediate notification after signal lost:
                        dz.log (notifyHead .." ".. 'Signal lost: '..deviceName .." sent "..writeTime(lastUpdate).. ' the last signal, threshold='..writeTime(threshold)..'. Battery empty?')
                        notified[deviceName] = 1
                        os.execute('curl -s -X POST "https://api.telegram.org/bot'..teleTok..'/sendMessage?chat_id='..chatId..'&text='..notifyHead..' Signal lost: '..deviceName ..' sent '..writeTime(lastUpdate).. ' the last signal, threshold='..writeTime(threshold)..'. Battery empty?"')
                    elseif
                        --sent reminders on daily basis:
                        dz.time.matchesRule(notifyTime) and  --time slot to notify
                        dz.devices('opVakantie').state == 'Off' -- not on holiday
                    then
                        dz.log(notifyHead .." ".. 'Reminder, '..deviceName .." sent "..writeTime(lastUpdate).. ' the last signal. Battery empty?')
                        local telesignalremind = (notifyHead .." ".. 'Reminder, '..deviceName .." sent "..writeTime(lastUpdate).. ' the last signal. Battery empty?')
                        os.execute('curl -s -X POST "https://api.telegram.org/bot'..teleTok..'/sendMessage?chat_id='..chatId..'&text='..notifyHead .." ".. 'Reminder, '..deviceName .." sent "..writeTime(lastUpdate).. ' the last signal. Battery empty?"')
                    end
                end
            end
        end
    end
end
}
Last edited by hoeby on Monday 03 June 2019 21:21, edited 1 time in total.
Thin-client --> Docker Domoticz main environment
Pi3A+ --> Google home (GAssistPi)
Pi3B+ --> Docker (P1monitor, Domoticz test environment, Ubiquity controller)
hoeby
Posts: 531
Joined: Saturday 02 June 2018 11:05
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.1
Location: Echt, Netherlands
Contact:

Re: Check Sensors script (dzVents)

Post by hoeby »

I hope somebody can help me.

I saw a difference in DZ.LASTUPDATE and the DEVICE RESULT LASTUPDATE.
The device lastupdate is written as LAST SEEN in domoticz.
But i couldn't find anything to do "dz.devices.lastseen.secondsago", i got a nil reaction when doing this.

I need the script working on DEVICE RESULT LASTUPDATE.
Why? I have smokedetectors, but those aren't changing the DZ.LASTUPDATE unless i make a smoke alarm. Therefor the scripts was not usefull, it would for sure trigger the notification that the device has signal lost. Which would not be true, but there was no switch change.
I have a xiaomi smoke detector paired with zigbee2mqtt, that changes the last seen every +/-55 minutes. But no switch change in that +/-55 minutes.

Keep in mind, that the last seen needs to be update without changing switch state. On the zigbee2mqtt this works with the Xiaomi smoke detector. I also have the same type smoke detector on the Xiaomi gateway, on this gateway it looks like it is not working.
Still need to find out, if it is the smoke detector which does the last seen, or it is the zigbee2mqtt that does this.

Hopefully it is clear what i have written, that you understand it.

To make the script working on DEVICE RESULT LASTUPDATE. I used the HTTP-response.
The script itselfs works. But i made it for 1 device, which gives 1 HTTP-response.
It is not the best. Because i used name and IDX of the same device in 1 script. But first would like to find the answers to my questions, before have a look at this, how to clean this up/change it.
But is it possible to make the script working for multi devices, which all give there own HTTP-response?
Or is the only way to do this, to make a new script for every device?

The script:

Code: Select all

return {
    on = {
        --timer = { 'at 08:00, at 10:00' } }, --Information: your notifyTime needs to be in this timer, to trigger the script
        timer = { 'every 1 minutes' },
        httpResponses = {
            'smokeInfo'
        }
    },

    data = { notified = { initial = {} } },
    execute = function(dz, item)
  
        function writeTime(secs)
            local t
            secs=tonumber(secs)
            if secs == nil then t='NIL'
                elseif secs >= 86400   then t=string.sub(tostring(secs/24/3600),1,4)..' days'  
                elseif secs >= 3600    then t=string.sub(tostring(secs/3600),1,4)..' hours' 
                elseif secs >= 60      then t=string.sub(tostring(secs/60),1,4)..' minutes'
                else t=secs..' seconds' 
            end
            return t 
        end
        
        local notifyTime = 'at 10:00' --you can add multiple notification times, i.e. 'at 12:00, at 20:00'
	    local notifyHead = 'dzCheckSensors'
	    local notified   = dz.data.notified -- short reference
	    local teleTok    = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
        local chatId     = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
        
        if dz.devices('opVakantie').state== 'On' then
	        toCheck = {    -- timeout for each device, in seconds (with holiday)
                ['Smoke-801414201509-zigbee']       = 1209600,    -- 2 weken
            }
        else
            toCheck = {    -- timeout for each device, in seconds (no holiday)
                ['Smoke-801414201509-zigbee']       = 172800,     -- 2 dagen
            }
        end
	
        if (item.isTimer) then
            dz.openURL({
                url = 'http://xxx.xxx.xxx.xxx:xxxx/json.htm?type=devices&rid=339',
                method = 'GET',
                callback = 'smokeInfo',
            })
        end
  
        for deviceName, lastUpdate in pairs(notified) do
     	    if toCheck[deviceName]==nil then
     	            notified[deviceName]=nil
     	            dz.log (notifyHead .." ".. deviceName.. ' was removed from the notified table, '..writeTime(threshold),99)
             end
        end

        if (item.isHTTPResponse and item.ok) then
            local Time = require('Time')
            local results = item.json.result

            for i, node in pairs(results) do
                -- dzVents Time object
                local lastSeen = Time(node.LastUpdate)
                local lastUpdate = lastSeen.secondsAgo

                for deviceName, threshold in pairs(toCheck) do
            		if lastUpdate < threshold then
              		    --device is alive
                    if notified[deviceName] == nil then
                        dz.log(notifyHead .." ".. deviceName ..": "..writeTime(lastUpdate).. ' was last response, threshold='..writeTime(threshold))
                    else
                        dz.log(notifyHead .." ".. 'Signal back from sensor '..deviceName)
                        notified[deviceName] = nil  --remove from notified list
                        os.execute('curl -s -X POST "https://api.telegram.org/bot'..teleTok..'/sendMessage?chat_id='..chatId..'&text='..notifyHead .." ".. 'Signal back from sensor '..deviceName ..'."')
                    end
                else 
                        --lost signal:
                    if notified[deviceName] == nil then
                        --immediate notification after signal lost:
                        dz.log (notifyHead .." ".. 'Signal lost: '..deviceName .." sent "..writeTime(lastUpdate).. ' the last signal, threshold='..writeTime(threshold)..'. Battery empty?')
                        notified[deviceName] = 1
                        os.execute('curl -s -X POST "https://api.telegram.org/bot'..teleTok..'/sendMessage?chat_id='..chatId..'&text='..notifyHead..' Signal lost: '..deviceName ..' sent '..writeTime(lastUpdate).. ' the last signal, threshold='..writeTime(threshold)..'. Battery empty?"')
                    elseif
                        --sent reminders on daily basis:
                        dz.time.matchesRule(notifyTime) and  --time slot to notify
                        dz.devices('opVakantie').state == 'Off' -- not on holiday
                    then
                        dz.log(notifyHead .." ".. 'Reminder, '..deviceName .." sent "..writeTime(lastUpdate).. ' the last signal. Battery empty?')
                        local telesignalremind = (notifyHead .." ".. 'Reminder, '..deviceName .." sent "..writeTime(lastUpdate).. ' the last signal. Battery empty?')
                        os.execute('curl -s -X POST "https://api.telegram.org/bot'..teleTok..'/sendMessage?chat_id='..chatId..'&text='..notifyHead .." ".. 'Reminder, '..deviceName .." sent "..writeTime(lastUpdate).. ' the last signal. Battery empty?"')
                    end
                end
            end
        end
    end
end
}
Thin-client --> Docker Domoticz main environment
Pi3A+ --> Google home (GAssistPi)
Pi3B+ --> Docker (P1monitor, Domoticz test environment, Ubiquity controller)
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest