Generic auto-off

Moderator: leecollings

rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Generic auto-off

Post by rrozema »

UPDATE: I have written 2 more scripts since I wrote this article: Auto-On and Auto-OnOff. All updates on all 3 of these scripts are now presented in this thread: https://www.domoticz.com/forum/viewtopi ... 72&t=32031.

In my house I have multiple switches that are either manually or automatically by some mechanism switched on and that I want to switch off after some time. Initially I had a separate script for each such device. But the amount of scripts kept on growing and it was not very clear anymore which script controlled what switch and when I wanted to change a setting change or a add switch I had to go into the scripts and alter them. Rather tedious and error prone. So came up with a generic solution to specify per device if it was to switched off automatically and if so, after how much time. Once I had this working I added the possibility to delay switching the light off for as long as someone is still in the room, as detected by a motion detector (a PIR). I wanted my switches to be easy configurable, and I don't think having to go into a script and add, update or remove devices names or even index values is very easy. So I wrote a single script that is executed once a minute and checks all devices to see if it needs to be switched off. This script reads for each device a setting, stored in the devices' description field, to see what to do for this device. If a device's description does not contain the values, that device is not switched off automatically. If it contains only an "auto_off_minutes" value, the device will be switched off if its state = 'On' and its LastUpdate is older than the number of minutes specified in the value. If it contains also a value for "auto_off_motion_device" and the switch is on for at least the "auto_off_minutes" value, the motion device by the name specified is interrogated to see if is currently off and its last update is more than the amount in auto_off_minutes old. If the motion is indeed off with lastupdate being old, the switch is switched off. If the motion device is On or lastUpdate is less than auto_off_minutes old, there must still be someone in the room and the switch is not switched off.

Here's an example of what to put in a device's description field to make it switch off automatically after two minutes:

Code: Select all

{
"auto_off_minutes": 2
}
And here's an example of how to make a switch go off 1 minute after the last person has left the room:

Code: Select all

{
"auto_off_minutes": 1,
"auto_off_motion_device": "Overloop 1: Motion"
}
Another example to show how to use multiple motion sensors for a single light. If either of the sensors still shows activity, the light remains on (thanks @waaren!):

Code: Select all

{
"auto_off_minutes": 1,
"auto_off_motion_device": ["Overloop 1: Motion 1", "Overloop 1: Motion 2"]
}
device.JPG
device.JPG (73.36 KiB) Viewed 8089 times
If I want to make a new switch go off automatically, I don't need to go into my scripts any more, I simply enter the proper values in the device's description field and it will use the new settings.

Here's the script I wrote for this.

Code: Select all

-- This script will run every minute and can automatically send an 'Off' command to turn off any device after
-- it has been on for some specified time. Each device can be individually configured by putting json coded 
-- settings into the device's description field. The settings currently supported are:
-- - "auto_off_minutes" : <time in minutes>
-- - "auto_off_motion_device" : "<name of a motion detection device>"
-- If "auto_off_minutes" is not set, the device will never be turned off by this script. If 
-- "auto_off_minutes" is set and <time in minutes> is a valid number, the device will be turned off when it 
-- is found to be on plus the device's lastUpdate is at least <time in minutes> minutes old. This behavior 
-- can be further modified by specifying a valid device name after "auto_off_motion_device". When a motion 
-- device is specified and the device's lastUpdate is at least <time in minutes> old, the device will not 
-- be turned off until the motion device is off and it's lastUpdate is also <time in minutes> old. 
-- Specifying "auto_off_motion_device" without specifying "auto_off_minutes" does nothing.
--
-- Example 1: turn off the device after 2 minutes:
-- {
-- "auto_off_minutes": 2
-- }
--
-- Example 2: turn off the device when it has been on for 5 minutes and no motion has been detected for 
-- at least 5 minutes:
-- {
-- "auto_off_minutes": 5,
-- "auto_off_motion_device": "Overloop: Motion"
-- }

return {
	on = {

		-- timer triggers
		timer = {
			'every minute'
		}
	},

	execute = function(domoticz, triggeredItem, info)
	    local cnt = 0

		domoticz.devices().forEach(
	        function(device)
	            cnt = cnt + 1
	            if device.state ~= 'Off' then
    	            local description = device.description
    	            if description ~= nil and description ~= '' then
    	                local ok, settings = pcall( domoticz.utils.fromJSON, description)
    	                if ok and settings ~= nil then
    	                    if settings.auto_off_minutes ~= nil and device.lastUpdate.minutesAgo >= settings.auto_off_minutes then
	                            if settings.auto_off_motion_device == nil then
            		                domoticz.log(device.name .. ' is switched off because it has been on for ' .. settings.auto_off_minutes .. ' minutes.', domoticz.LOG_INFO)
	                                device.switchOff()
	                            elseif type(settings.auto_off_motion_device) == "string" then
	                                local motion_device = domoticz.devices(settings.auto_off_motion_device)
                                    if motion_device.state == 'Off' and motion_device.lastUpdate.minutesAgo >= settings.auto_off_minutes then
                		                domoticz.log(device.name .. ' is switched off because no one was in the room for ' .. settings.auto_off_minutes .. ' minutes.', domoticz.LOG_INFO)
    	                                device.switchOff()
                                    end
                                elseif type(settings.auto_off_motion_device) == "table" then
                                    local off = true
                                    for i,v in ipairs(settings.auto_off_motion_device) do
                                        local d = domoticz.devices(v)
                                        if d.state ~= 'Off' or d.lastUpdate.minutesAgo < settings.auto_off_minutes then
                                            off = false
                                        end
                                    end
                                    if off then
                		                domoticz.log(device.name .. ' is switched off because no one was in the room for ' .. settings.auto_off_minutes .. ' minutes.', domoticz.LOG_INFO)
                                        device.switchOff()
                                    end
	                            end
                            end 
                        else
                            domoticz.log( 'Device description for '.. device.name ..' is not in json format. Ignoring this device.', domoticz.LOG_ERROR)
                        end
                    end
                end
            end
        )
    
        domoticz.log('Scanned ' .. tostring(cnt) .. ' devices.', domoticz.LOG_INFO)
	end
}
Edit: updated to the latest version of the script. Plus pcall is now used correctly to catch invalid json description texts.
Last edited by rrozema on Sunday 05 April 2020 0:43, edited 3 times in total.
dizzeenl
Posts: 31
Joined: Wednesday 14 November 2018 23:57
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Dordrecht
Contact:

Re: Generic auto-off

Post by dizzeenl »

Thanks a lot, it works like a charm!
Stief
Posts: 11
Joined: Sunday 22 April 2018 7:36
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Generic auto-off

Post by Stief »

@rrozema Thanks man!
Was looking for something like this.
I'm not that knowledgeable in scripting, so this is a great help.
Any updates since your first post?

I'll try is later this week.

User avatar
emme
Posts: 909
Joined: Monday 27 June 2016 11:02
Target OS: Raspberry Pi / ODroid
Domoticz version: latest
Location: Milano, Italy
Contact:

Re: Generic auto-off

Post by emme »

pure genius! :o
The most dangerous phrase in any language is:
"We always done this way"
MarcoC
Posts: 4
Joined: Wednesday 05 December 2018 2:44
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Sydney, Australia
Contact:

Re: Generic auto-off

Post by MarcoC »

Thanks for this script, which was a great starting point for what I needed to do.
If anyone can tell me how to properly use pcall() to catch the error, I will be very thankful.

I found that you can use functions in the lodash utilities to make this work properly('_') here is an extract from my script where they are used - it should be easy to adapt to what you need. Hope this helps someone.

Code: Select all

    local _ = dz.utils._
    
    dz.devices().forEach(function(device)
      local description = device.description
      if (_.isString(description) and description ~= '') then
        local settings = dz.utils.fromJSON(description)
        if (_.isTable(settings) and _.isNumber(settings.offline_timeout)) then
wobbenl
Posts: 6
Joined: Friday 18 December 2015 21:26
Target OS: Raspberry Pi / ODroid
Domoticz version: v2020.2
Location: Friesland
Contact:

Re: Generic auto-off

Post by wobbenl »

Thanks man!
1x raspberry pi 3b+, 1x arduino mega rflink print from nodo-shop
1x P1 Smart Meter Energy, 1x DIY S0-pulsecounter(Arduino based)
https://www.huizebruin.nl ( Dutch blog from me about domoticz an other stuff)
rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Re: Generic auto-off

Post by rrozema »

I've made some minor modifications to the auto-off script since my first post.
- fixed error handling when a devices description is not a json format,
- made it possible to specify multiple motion devices per switch; if at least one device has seen motion, the light will not be switched off yet.
I'm not completely sure if I should check the lastupdate on the motion device against the timeout period too. This version only checks if the motion device is 'Off' without an additional delay because the motion devices themselves also have a period they remain on, so adding my own period to that period would make the delay too long in my opinion. I've had this running for some weeks now and I like this best. Please see for yourself which version you like best.

Code: Select all

-- This script will run every minute and can automatically send an 'Off' command to turn off any device after
-- it has been on for some specified time. Each device can be individually configured by putting json coded 
-- settings into the device's description field. The settings currently supported are:
-- - "auto_off_minutes" : <time in minutes>
-- - "auto_off_motion_device" : "<name of a motion detection device>"
-- If "auto_off_minutes" is not set, the device will never be turned off by this script. If 
-- "auto_off_minutes" is set and <time in minutes> is a valid number, the device will be turned off when it 
-- is found to be on plus the device's lastUpdate is at least <time in minutes> minutes old. This behavior 
-- can be further modified by specifying a valid device name after "auto_off_motion_device". When a motion 
-- device is specified and the device's lastUpdate is at least <time in minutes> old, the device will not 
-- be turned off until the motion device is off and it's lastUpdate is also <time in minutes> old. 
-- Specifying "auto_off_motion_device" without specifying "auto_off_minutes" does nothing.
--
-- Example 1: turn off the device after 2 minutes:
-- {
-- "auto_off_minutes": 2
-- }
--
-- Example 2: turn off the device when it has been on for 5 minutes and no motion has been detected by 
-- the "Overloop: Motion" device:
-- {
-- "auto_off_minutes": 5,
-- "auto_off_motion_device": "Overloop: Motion"
-- }
-- Example 3: turn off the device when it has been on for 2 minutes and no motion has been detected by 
-- either of the "Overloop: Motion" or the "Trap: Motion" devices:
-- {
-- "auto_off_minutes": 2,
-- "auto_off_motion_device": ["Overloop: Motion", "Trap: Motion"]
-- }

return {
	on = {

		-- timer triggers
		timer = {
			'every minute'
		}
	},

	-- custom logging level for this script
--	logging = {
--        level = domoticz.LOG_INFO,
--        marker = 'Auto Off'
--    },

	execute = function(domoticz, triggeredItem, info)
	    local cnt = 0

		domoticz.devices().forEach(
	        function(device)
	            cnt = cnt + 1
                --domoticz.log( 'Device "' .. device.name .. '" is "' .. tostring(device.state) .. '".', domoticz.LOG_INFO)
	            if device.state ~= 'Off' then
    	            local description = device.description
    	            if description ~= nil and description ~= '' then
    	                --domoticz.log( 'description = ' .. description .. '.', domoticz.LOG_INFO)
    	                local ok, settings = pcall( domoticz.utils.fromJSON, description)
    	                if ok and settings ~= nil then
    	                    if settings.auto_off_minutes ~= nil and device.lastUpdate.minutesAgo >= settings.auto_off_minutes then
	                            if settings.auto_off_motion_device == nil then
            		                domoticz.log(device.name .. ' is switched off because it has been on for ' .. settings.auto_off_minutes .. ' minutes.', domoticz.LOG_INFO)
	                                device.switchOff()
	                            elseif type(settings.auto_off_motion_device) == "string" then
	                                local motion_device = domoticz.devices(settings.auto_off_motion_device)
                                    if motion_device.state == 'Off' then
                		                domoticz.log(device.name .. ' is switched off because no one was in the room for ' .. settings.auto_off_minutes .. ' minutes.', domoticz.LOG_INFO)
    	                                device.switchOff()
                                    end
                                elseif type(settings.auto_off_motion_device) == "table" then
                                    local off = true
                                    for i,v in ipairs(settings.auto_off_motion_device) do
                                        if domoticz.devices(v).state ~= 'Off' then
                                            off = false
                                        end
                                    end
                                    if off then
                		                domoticz.log(device.name .. ' is switched off because no one was in the room for ' .. settings.auto_off_minutes .. ' minutes.', domoticz.LOG_INFO)
                                        device.switchOff()
                                    end
	                            end
                            end 
                        else
                            domoticz.log( 'Device description for '.. device.name ..' is not in json format. Ignoring this device.', domoticz.LOG_ERROR)
                        end
                    end
                end
            end
        )
    
        domoticz.log('Scanned ' .. tostring(cnt) .. ' devices.', domoticz.LOG_INFO)
	end
}
User avatar
papoo
Posts: 126
Joined: Friday 22 January 2016 22:14
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10
Location: France
Contact:

Re: Generic auto-off

Post by papoo »

emme wrote: Thursday 15 November 2018 8:20 pure genius! :o
yes, great!
raq24
Posts: 3
Joined: Wednesday 28 November 2018 20:27
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Generic auto-off

Post by raq24 »

is it possible to set the time after which it is supposed to switch off the last movement or only 1 minute
rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Re: Generic auto-off

Post by rrozema »

If you specify a motion detector, the light will not turn off for as long as the motion detector sees motion. The light will turn off x minutes after the motion detector has gone off or x minutes after the light was switched on, whichever is last.
User avatar
papoo
Posts: 126
Joined: Friday 22 January 2016 22:14
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10
Location: France
Contact:

Re: Generic auto-off

Post by papoo »

for my personal use I added news notifications features to this great script. If it helps someone

high, low, on, off and timeout threshold notification with quiet hours management and frequency notification for switch, temperature, hygrometry, percentage, custom and alert devices

Code: Select all



--[[
original script by rrozema Generic auto-off : https://www.domoticz.com/forum/viewtopic.php?f=72&t=23717&p=205159&hilit=auto+off#p201976
author = papoo
maj : 06/05/2019
this version need a waaren script, Universal function notification :
https://www.domoticz.com/forum/viewtopic.php?f=59&t=26542#p204958
https://pon.fr/dzvents-fonction-de-notification-universelle/

blog url : https://pon.fr/dzvents-script-de-notification-ultime-mais-pas-que
forum url : https://easydomoticz.com/forum/viewtopic.php?f=17&t=8167
github url : https://github.com/papo-o/domoticz_scripts/blob/master/dzVents/scripts/JsonDescription.lua


This script will run every minute and can automatically send an 'Off' command to turn off any device after
it has been on for some specified time. Each device can be individually configured by putting json coded
settings into the device's description field. The settings currently supported are:
- "auto_off_minutes" : <time in minutes>
- "auto_off_motion_device" : "<name of a motion detection device>"
If "auto_off_minutes" is not set, the device will never be turned off by this script. If
"auto_off_minutes" is set and <time in minutes> is a valid number, the device will be turned off when it
is found to be on plus the device's lastUpdate is at least <time in minutes> minutes old. This behavior
can be further modified by specifying a valid device name after "auto_off_motion_device". When a motion
device is specified and the device's lastUpdate is at least <time in minutes> old, the device will not
be turned off until the motion device is off and it's lastUpdate is also <time in minutes> old.
Specifying "auto_off_motion_device" without specifying "auto_off_minutes" does nothing.

Example 1:
turn off the device after 2 minutes :
Exemple 1 :
éteindre l'appareil après 2 minutes :
{
"auto_off_minutes": 2
}

Example 2:
turn off the device when it has been on for 5 minutes and no motion has been detected by
    the "Overloop: Motion" device :
Exemple 2 : éteindre l'appareil lorsqu'il est allumé depuis 5 minutes et qu'aucun mouvement n'a été détecté par
    le dispositif "Overloop: Motion":

{
"auto_off_minutes": 5,
"auto_off_motion_device": "Overloop: Motion"
}

Example 3: turn off the device when it has been on for 2 minutes and no motion has been detected by
    either of the "Overloop: Motion" or the "Trap: Motion" devices:
exemple 3: éteindre l'appareil lorsqu'il est allumé depuis 2 minutes et qu'aucun mouvement n'a été détecté par
    l’un des dispositifs "Overloop: Motion" ou "Trap: Motion":

{
"auto_off_minutes": 2,
"auto_off_motion_device": ["Overloop": "Motion", "Trap": "Motion"]
}

With this new version you can :
    - be notified if temperature and or hygrometry exceed min or max threshold.
    - be notified if device is on, off or out
    you can mix the desired notifications, such as only the maximum temperature rise,
    or the minimum and maximum humidity, or do not set quiet hours, or minimum temperature and timout
    if you want to use the notification functions, the frequency of notifications is necessary
Avec cette nouvelle version vous pouvez :
    - être averti après le délai défini si la température et / ou l'hygrométrie dépassent le seuil minimal ou maximal.
    - être averti si un périphérique est allumé, éteint ou hors service
    vous pouvez mélanger les notifications souhaitées, telles que uniquement le dépassement de température maxi,
    ou  l'hygrométrie mini et maxi, ou ne pas définir d'heures calmes, ou température mini et timeout
    si vous souhaitez utiliser les fonctions de notification,  la fréquence de notifications est nécessaire


Example 4 : be notified if temperature or hygrometry exceed min or max threshold for a number of minutes
    with notifications frequency in minutes and quiet hours notification
Exemple 4 : être averti si la température ou l'hygrométrie dépasse les seuils minimal ou maximal pendant un certain nombre de minutes
    avec fréquence de notifications en minutes et notification des heures calmes

{
 "low_threshold_temp": 10,
 "high_threshold_temp": 40,
 "duration_exceeded_temp": 20,
 "low_threshold_hr": 25,
 "high_threshold_hr": 75,
 "duration_exceeded_hr": 20,
 "frequency_notifications": 60,
 "quiet_hours":"23:00-07:15"
  }

Example 5 : be notified if device is on since x minutes
    with notifications frequency in minutes and quiet hours notification
Exemple 5 : être averti si le périphérique est allumé depuis x minutes
    avec fréquence de notifications en minutes et notification des heures calmes

  {
 "time_active_notification": 120,
 "frequency_notifications": 60,
 "quiet_hours":"23:00-07:15"
  }

Example 6 : be notified if device is off since x minutes
    with notifications frequency in minutes and quiet hours notification
Exemple 6 : être averti si le périphérique est éteint depuis x minutes
    avec fréquence de notifications en minutes et notification des heures calmes

  {
 "time_inactive_notification": 2,
 "frequency_notifications": 60,
 "quiet_hours":"23:00-07:15"
  }

Example 7 : be notified if device is out since x minutes
    with notifications frequency in minutes and quiet hours notification
Exemple 7 : être averti si le périphérique est hors service depuis x minutes
    avec fréquence de notifications en minutes et notification des heures calmes

 {
"timeout_notification": 1440,
"frequency_notifications": 60,
"quiet_hours":"23:00-07:15"
  }

Example 8 : be notified if a device% exceeds the minimum or maximum thresholds
    with frequency of notifications in minutes and notification of quiet hours
Exemple 8 : être averti si un périphérique % dépasse les seuils minimal ou maximal
    avec fréquence de notifications en minutes et notification des heures calmes

  {
 "low_threshold_percent": 10,
 "high_threshold_percent": 40,
 "duration_exceeded_percent": 20,
 "frequency_notifications": 60,
 "quiet_hours":"23:00-07:15"
  }

Example 9 : be notified if a Custom Sensor device exceeds the minimum or maximum thresholds
    with frequency of notifications in minutes and notification of quiet hours
Exemple 9 :être averti si un périphérique Custom Sensor dépasse les seuils minimal ou maximal
    avec fréquence de notifications en minutes et notification des heures calmes

  {
 "low_threshold_custom": 1000,
 "high_threshold_custom": 4000,
 "frequency_notifications": 60,
 "quiet_hours":"23:00-07:15"
  }


Example 10: Be notified if an Alert device exceeds a predefined threshold (1,2,3 or 4)
    with frequency of notifications in minutes and notification of quiet hours
Exemple 10 : être averti si un périphérique Alert dépasse un seuil prédéfini (1,2,3 ou 4)
    avec fréquence de notifications en minutes et notification des heures calmes

  {
 "high_threshold_color": 4,
 "frequency_notifications": 60,
 "quiet_hours":"23:00-07:15"
  }
========================================================
Fonctionnalités proposées par denis_brasseur

Example 11: Be notified if a device's battery is below a low threshold
    with frequency of notifications in minutes and notification of quiet hour
Exemple 11 : être averti si la batterie d'un périphérique est inférieure un seuil bas
    avec fréquence de notifications en minutes et notification des heures calmes

  {
 "low_battery_level": 30,
 "high_threshold_temp": -15,
 "frequency_notifications": 60,
 "quiet_hours":"23:00-07:15"
  }


Example 12: Be notified if the signal level (zwave, rfxcom) of a device is below a low threshold
    with frequency of notifications in minutes and notification of quiet hour
Exemple 12 : être averti si le niveau de signal (zwave, rfxcom) d'un périphérique est inférieure un seuil bas
    avec fréquence de notifications en minutes et notification des heures calmes

  {
 "low_signal_level": 2,
 "frequency_notifications": 60,
 "quiet_hours":"23:00-07:15"
  }


Example 13: Be notified if a power device exceeds a high threshold or a low threshold set
Exemple 13 : être averti si un périphérique puissance dépasse un seuil haut ou un seuil bas défini

  {
 "low_watt_usage": 0,
 "high_watt_usage": 10000,
 "frequency_notifications": 60,
 "quiet_hours":"23:00-07:15"
  }

 Example 14: Be notified if an intensity device exceeds a high threshold or a low threshold set
 Exemple 14 : être averti si un périphérique intensité dépasse un seuil haut ou un seuil bas défini

  {
 "low_current_usage": 0,
 "high_current_usage": 60,
 "frequency_notifications": 60,
 "quiet_hours":"23:00-07:15"
  }

  Example 15 : turn on the device after x minutes:
  Exemple 15 : allumer l'appareil après x minutes:

{
"auto_on_minutes": 1
}
========================================================

Example 16 : be notified if device is off since x minutes
    with notifications frequency in minutes and quiet hours notification only on telegram notifications
    Notification systems available:
    GOOGLE_CLOUD_MESSAGING, HTTP, KODI, LOGITECH_MEDIASERVER, NMA, PROWL, PUSHALOT, PUSHBULLET,PUSHOVER, PUSHSAFER, TELEGRAM
Exemple 16 : être averti si le périphérique est éteint depuis x minutes
    avec fréquence de notifications en minutes et notification des heures calmes seulement via les notifications TELEGRAM
    Systèmes de notification disponibles :
    GOOGLE_CLOUD_MESSAGING, HTTP, KODI, LOGITECH_MEDIASERVER, NMA, PROWL, PUSHALOT, PUSHBULLET,PUSHOVER, PUSHSAFER, TELEGRAM

  {
  "subsystems" : "TELEGRAM",
 "time_inactive_notification": 2,
 "frequency_notifications": 60,
 "quiet_hours":"23:00-07:15"
  }

Example 17 : be notified if device is off since x minutes
    with notifications frequency in minutes and quiet hours notification only on TELEGRAM and PUSHBULLET notifications
    Notification systems available:
    GOOGLE_CLOUD_MESSAGING, HTTP, KODI, LOGITECH_MEDIASERVER, NMA, PROWL, PUSHALOT, PUSHBULLET,PUSHOVER, PUSHSAFER, TELEGRAM
    For multi-system notification, separate the systems with a comma.
Exemple 17 : être averti si le périphérique est éteint depuis x minutes
    avec fréquence de notifications en minutes et notification des heures calmes seulement via les notifications TELEGRAM et PUSHBULLET
    Systèmes de notification disponibles :
    GOOGLE_CLOUD_MESSAGING, HTTP, KODI, LOGITECH_MEDIASERVER, NMA, PROWL, PUSHALOT, PUSHBULLET,PUSHOVER, PUSHSAFER, TELEGRAM
    Pour une notification sur plusieurs systèmes, séparez les systèmes par une virgule.

  {
  "subsystems" : "TELEGRAM,PUSHBULLET",
 "time_inactive_notification": 2,
 "frequency_notifications": 60,
 "quiet_hours":"23:00-07:15"
  }

--]]

--permet de lire les valeurs des périphériques avec "duration_exceeded_temp", "low_threshold_hr", "high_threshold_hr" ou  "duration_exceeded_hr"
function managed(dz, id, duration_exceeded, high_threshold, low_threshold)
    test_high_threshold = true
    test_low_threshold = true
    x = 0
    dz.data.managedId.forEach(
        function(item)
            x = x + 1
            if item.data == id then
                timeNotif = tonumber(item.time.minutesAgo)
                local value = dz.data.managedValue.get(x)
                if timeNotif < duration_exceeded then -- on test si l'ancienneté de la valeur est < à la valeur duration_exceeded_temp
                    if high_threshold ~= nil then -- si la value est < à la valeur de ref, on passe la variable à false => pas d'envoi de notification
                        if value.data <= high_threshold then test_high_threshold = false end
                    end
                    if low_threshold ~= nil then -- si la value est > à la valeur de ref, on passe la variable à false => pas d'envoi de notification
                        if value.data >= low_threshold then test_low_threshold = false end
                    end
                end
            end
        end
    )
    return test_high_threshold, test_low_threshold

end
local scriptName = 'Json Description'
local scriptVersion = '1.01'

return {
    active = true,
    on = {

        -- timer triggers
        timer = {
            'every minute'
        }
    },

    -- custom logging level for this script
    logging = {
                -- level    =   domoticz.LOG_DEBUG,
                -- level    =   domoticz.LOG_INFO,             -- Seulement un niveau peut être actif; commenter les autres
                -- level    =   domoticz.LOG_ERROR,            -- Only one level can be active; comment others
                -- level    =   domoticz.LOG_MODULE_EXEC_INFO,
                marker = scriptName..' v'..scriptVersion
   },
    -- permet de stocker les valeurs des périphériques avec "duration_exceeded_" sous /home/pi/domoticz/scripts/dzVents/data/__data_JsonDescription.lua
   data = {
        managedValue = { history = true, maxItems = 3600, maxHours = 6 },
        managedId = { history = true, maxItems = 3600, maxHours = 6 },
    },
    execute = function(domoticz, triggeredItem, info)
        local cnt = 0

        function split(s, delimiter)
        if s ~= nil then
            result = {};
            for match in (s..delimiter):gmatch("(.-)"..delimiter) do
                table.insert(result, match);
            end
        else
            result = {""};
        end
        return result;
        end

        function notificationTable(str)
        --NSS_GOOGLE_CLOUD_MESSAGING, NSS_HTTP, NSS_KODI, NSS_LOGITECH_MEDIASERVER, NSS_NMA,NSS_PROWL, NSS_PUSHALOT, NSS_PUSHBULLET, NSS_PUSHOVER, NSS_PUSHSAFER, NSS_TELEGRAM
            if (str) then
            str = string.gsub (str,"GCM", domoticz.NSS_GOOGLE_CLOUD_MESSAGING)
            str = string.gsub (str,"GOOGLE_CLOUD_MESSAGING", domoticz.NSS_GOOGLE_CLOUD_MESSAGING)
            str = string.gsub (str,"HTTP", domoticz.NSS_HTTP)
            str = string.gsub (str,"LMS", domoticz.NSS_LOGITECH_MEDIASERVER)
            str = string.gsub (str,"LOGITECH_MEDIASERVER", domoticz.NSS_LOGITECH_MEDIASERVER)
            str = string.gsub (str,"NMA", domoticz.NSS_NMA)
            str = string.gsub (str,"PROWL", domoticz.NSS_PROWL)
            str = string.gsub (str,"PUSHALOT", domoticz.NSS_PUSHALOT)
            str = string.gsub (str,"PUSHOVER", domoticz.NSS_PUSHOVER)
            str = string.gsub (str,"PUSHSAFER", domoticz.NSS_PUSHSAFER)
            str = string.gsub (str,"PUSHBULLET", domoticz.NSS_PUSHBULLET)
            str = string.gsub (str,"TELEGRAM", domoticz.NSS_TELEGRAM)
            end
        return (split(str,','))
        end

        local subject               = "/!\\ Attention /!\\"           -- sujet des notifications

        domoticz.devices().forEach(
            function(device)
                cnt = cnt + 1
                local frequency_notifications = nil
                local quiet_hours = nil
                local message = nil
                local subSystems = nil

                local description = device.description
                local j = string.find(tostring(description), '^{.*}$')

                if description ~= nil and description ~= '' and j ~= nil then

                    local ok, settings = pcall( domoticz.utils.fromJSON, description)
                    if ok and settings then

                        if settings.subsystems ~= nil then -- systeme(s) de notification
                            subSystems = settings.subsystems
                            domoticz.log('le(s) systeme(s) de notification pour '.. device.name .. ' est(sont)  ' .. subSystems, domoticz.LOG_INFO)
                        end


                        if settings.frequency_notifications ~= nil then -- fréquence de notification
                            frequency_notifications = settings.frequency_notifications
                            domoticz.log('la fréquence de notification pour '.. device.name .. ' est de  ' .. settings.frequency_notifications.." minutes", domoticz.LOG_INFO)
                        end

                        if settings.quiet_hours ~= nil then -- période silencieuse
                            quiet_hours = settings.quiet_hours
                            domoticz.log('la période silencieuse de notification pour '.. device.name .. ' est définie entre  ' .. quiet_hours, domoticz.LOG_INFO)
                        end

                        if device.temperature ~= nil and settings.high_threshold_temp ~= nil then  -- seuil haut température
                            domoticz.log(device.name .. ' a un seuil temperature haute défini à  ' .. settings.high_threshold_temp..'°C', domoticz.LOG_INFO)
                        end

                        if device.temperature ~= nil and settings.low_threshold_temp ~= nil then  -- seuil bas température
                            domoticz.log(device.name .. ' a un seuil temperature basse défini à  ' .. settings.low_threshold_temp..'°C', domoticz.LOG_INFO)
                        end

                        if device.percentage ~= nil and settings.high_threshold_percent ~= nil then  -- seuil haut %
                            domoticz.log(device.name .. ' a un seuil % haut défini à  ' .. settings.high_threshold_percent..'%', domoticz.LOG_INFO)
                        end

                        if device.percentage ~= nil and settings.low_threshold_percent ~= nil then  -- seuil bas %
                            domoticz.log(device.name .. ' a un seuil % bas défini à  ' .. settings.low_threshold_percent..'%', domoticz.LOG_INFO)
                        end

                        --sensorType
                        if device.sensorType ~= nil and settings.high_threshold_custom ~= nil then  -- seuil haut sensorType
                            domoticz.log(device.name .. ' a un seuil haut défini à  ' .. settings.high_threshold_custom..' '..device.sensorUnit, domoticz.LOG_INFO)
                        end

                        if device.sensorType ~= nil and settings.low_threshold_custom ~= nil then  -- seuil bas sensorType
                            domoticz.log(device.name .. ' a un seuil bas défini à  ' .. settings.low_threshold_custom..' '..device.sensorUnit, domoticz.LOG_INFO)
                        end

                        --low_watt_usage
                        if device.WhActual ~= nil and settings.low_watt_usage ~= nil then  -- seuil bas sensorType
                            domoticz.log(device.name .. ' a un seuil bas défini à  ' .. settings.low_watt_usage..' Wh', domoticz.LOG_INFO)
                        end

                        if device.WhActual ~= nil and settings.high_watt_usage ~= nil then  -- seuil bas sensorType
                            domoticz.log(device.name .. ' a un seuil haut défini à  ' .. settings.high_watt_usage..' Wh', domoticz.LOG_INFO)
                        end

                        if device.current ~= nil and settings.low_current_usage ~= nil then  -- seuil bas sensorType
                            domoticz.log(device.name .. ' a un seuil bas défini à  ' .. settings.low_current_usage..' A', domoticz.LOG_INFO)
                        end

                        if device.current ~= nil and settings.high_current_usage ~= nil then  -- seuil bas sensorType
                            domoticz.log(device.name .. ' a un seuil haut défini à  ' .. settings.high_current_usage..' A', domoticz.LOG_INFO)
                        end

                        if device.state == 'Off' or device.state == 'Close' then    -- Alarme dispositif inactif
                            if settings.time_active_notification ~= nil then
                                domoticz.log('Le délai est fixé à '.. settings.time_active_notification.. ' minutes.', domoticz.LOG_INFO)
                            end
                        elseif device.state == 'On' or device.state == 'Open' then   -- Alarme dispositif actif
                            if settings.time_inactive_notification ~= nil then
                                domoticz.log('Le délai est fixé à '.. settings.time_inactive_notification.. ' minutes.', domoticz.LOG_INFO)
                            end
                        end

                        -- Alarme dispositif injoignable
                        if settings.timeout_notification and device.timedOut then
                            domoticz.log(device.name .. ' est injoignable. Sa dernière activité remonte à ' .. device.lastUpdate.minutesAgo .. ' minutes.', domoticz.LOG_INFO)
                            message = device.name .. ' est injoignable depuis '.. tostring(settings.timeout_notification) ..' minutes'
                            domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
                        end

                        --batterie
                        if device.batteryLevel ~= nil and device.batteryLevel ~= 255 and settings.low_battery_level ~= nil then
                            domoticz.log('Le niveau de batterie de '.. device.name .. ' est de  ' .. device.batteryLevel .. '%', domoticz.LOG_INFO)
                            if settings.low_battery_level ~= nil and device.batteryLevel < settings.low_battery_level then  -- seuil bas batterie
                                domoticz.log(device.name .. ' a un niveau de batterie de ' .. device.batteryLevel..'%', domoticz.LOG_INFO)
                                message = 'Le niveau de batterie '.. device.name .. ' est inférieur au seuil défini ('..settings.low_battery_level..'%). Valeur : '..tostring(domoticz.utils.round(device.batteryLevel, 1)) ..'%'
                                --domoticz.log(message, domoticz.LOG_INFO)
                                domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
                            end
                        end

                        --low_signal_level
                        if device.signalLevel ~= nil and settings.low_signal_level ~= nil then
                            domoticz.log('Le niveau de signal de '.. device.name .. ' est de  ' .. device.signalLevel, domoticz.LOG_INFO)
                            if settings.low_signal_level ~= nil and device.signalLevel < settings.low_signal_level then  -- seuil bas signal
                                domoticz.log(device.name .. ' a un niveau de signal de ' .. device.signalLevel, domoticz.LOG_INFO)
                                message = 'Le niveau de signal '.. device.name .. ' est inférieur au seuil défini ('..settings.low_signal_level..'). Valeur : '..device.signalLevel
                                --domoticz.log(message, domoticz.LOG_INFO)
                                domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
                            end
                        end

                        --low_watt_usage
                        if device.WhActual ~= nil and settings.low_watt_usage ~= nil then
                            domoticz.log('Le niveau de puissance de '.. device.name .. ' est de  ' .. device.WhActual..' Wh', domoticz.LOG_INFO)
                            if settings.low_watt_usage ~= nil and device.WhActual < settings.low_watt_usage then  -- seuil bas puissance
                                domoticz.log(device.name .. ' a un niveau de puissance de ' .. device.WhActual..' Wh', domoticz.LOG_INFO)
                                message = 'Le niveau de puissance '.. device.name .. ' est inférieur au seuil défini ('..settings.low_watt_usage..'). Valeur : '..device.WhActual..' Wh'
                                --domoticz.log(message, domoticz.LOG_INFO)
                                domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
                            end
                        end

                        if device.WhActual ~= nil and settings.high_watt_usage ~= nil then
                            domoticz.log('Le niveau de puissance de '.. device.name .. ' est de  ' .. device.WhActual..' Wh', domoticz.LOG_INFO)
                            if settings.high_watt_usage ~= nil and device.WhActual > settings.high_watt_usage then  -- seuil haut puissance
                                domoticz.log(device.name .. ' a un niveau de puissance de ' .. device.WhActual..' Wh', domoticz.LOG_INFO)
                                message = 'Le niveau de puissance '.. device.name .. ' est superieur au seuil défini ('..settings.high_watt_usage..'). Valeur : '..device.WhActual..' Wh'
                                --domoticz.log(message, domoticz.LOG_INFO)
                                domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
                            end
                        end

                        --low_current_usage
                        if device.current ~= nil and settings.low_current_usage ~= nil then
                            domoticz.log('Le niveau de '.. device.name .. ' est de  ' .. tostring(domoticz.utils.round(device.current, 0))..' A', domoticz.LOG_INFO)
                            if settings.low_current_usage ~= nil and device.current < settings.low_current_usage then  -- seuil bas intensite
                                domoticz.log(device.name .. ' a un niveau de ' .. tostring(domoticz.utils.round(device.current, 0)), domoticz.LOG_INFO)
                                message = 'Le niveau de '.. device.name .. ' est inférieur au seuil défini ('..settings.low_current_usage..'). Valeur : '..tostring(domoticz.utils.round(device.current, 0))..' A'
                                --domoticz.log(message, domoticz.LOG_INFO)
                                domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
                            end
                        end

                        --current
                        if device.current ~= nil and settings.high_current_usage ~= nil then
                            domoticz.log('Le niveau de '.. device.name .. ' est de  ' .. tostring(domoticz.utils.round(device.current, 0))..' A', domoticz.LOG_INFO)
                            if settings.high_current_usage ~= nil and device.current > settings.high_current_usage then  -- seuil haut intensite
                                domoticz.log(device.name .. ' a un niveau de ' .. tostring(domoticz.utils.round(device.current, 0)), domoticz.LOG_INFO)
                                message = 'Le niveau '.. device.name .. ' est superieur au seuil défini ('..settings.high_current_usage..'). Valeur : '..tostring(domoticz.utils.round(device.current, 0))..' A'
                                --domoticz.log(message, domoticz.LOG_INFO)
                                domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
                            end
                        end
                        if device.state == 'Off' or device.state == 'Close' then
                         -- Alarme dispositif inactif
                            domoticz.log(device.name .. ' est à l\'état ' .. device.state, domoticz.LOG_INFO)
                            if settings.time_inactive_notification ~= nil and device.lastUpdate.minutesAgo >= settings.time_inactive_notification then
                                domoticz.log(device.name .. ' est inactif depuis ' .. device.lastUpdate.minutesAgo .. ' minutes. Le délai est fixé à '.. settings.time_inactive_notification.. ' minutes.', domoticz.LOG_INFO)
                                message = 'Le délai d\'inactivité fixé à '.. settings.time_inactive_notification .. ' minutes pour '.. device.name .. ' est dépassé'
                                domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
                            end

                        elseif device.temperature ~= nil or device.humidity ~= nil then
                        -- Alarme température
                            if device.temperature ~= nil and (settings.low_threshold_temp ~= nil or settings.high_threshold_temp ~= nil)  then
                                --test settings.duration_exceeded_temp
                                test_high_threshold = true
                                test_low_threshold = true
                                if settings.duration_exceeded_temp ~= nil then
                                    domoticz.data.managedValue.add(domoticz.utils.round(device.temperature, 2))
                                    domoticz.data.managedId.add(device.id)
                                    if settings.high_threshold_temp ~= nil then high_threshold_temp = settings.high_threshold_temp else high_threshold_temp = nil end
                                    if settings.low_threshold_temp ~= nil then low_threshold_temp = settings.low_threshold_temp else low_threshold_temp = nil end
                                    --test_high_threshold, test_low_threshold = managed(dz, id, duration_exceeded, high_threshold, low_threshold)
                                    test_high_threshold, test_low_threshold = managed(domoticz, device.id, settings.duration_exceeded_temp, high_threshold_temp, low_threshold_temp)
                                end
                                domoticz.log('La température mesurée par '.. device.name .. ' est de  ' .. tostring(domoticz.utils.round(device.temperature, 1)) ..'°C', domoticz.LOG_INFO)
                                if settings.low_threshold_temp ~= nil and device.temperature < settings.low_threshold_temp and test_low_threshold == true then  -- seuil bas température
                                    domoticz.log(device.name .. ' a un seuil temperature basse défini à  ' .. settings.low_threshold_temp..'°C', domoticz.LOG_INFO)
                                    message = 'La température mesurée par '.. device.name .. ' est inférieure au seuil défini ('..settings.low_threshold_temp..'°C). Valeur : '..tostring(domoticz.utils.round(device.temperature, 1)) ..'°C'
                                    if settings.duration_exceeded_temp ~= nil then
                                        domoticz.data.managedValue.add(settings.low_threshold_temp)
                                        domoticz.data.managedId.add(device.id)
                                    end
                                    domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
                                end
                                if settings.high_threshold_temp ~= nil and device.temperature > settings.high_threshold_temp and test_high_threshold == true then  -- seuil haut température
                                    domoticz.log(device.name .. ' a un seuil temperature haute défini à  ' .. settings.high_threshold_temp..'°C', domoticz.LOG_INFO)
                                    message = 'La température mesurée par '.. device.name ..' est supérieure au seuil défini ('..settings.high_threshold_temp..'°C). Valeur : '..tostring(domoticz.utils.round(device.temperature, 1)) ..'°C'
                                    if settings.duration_exceeded_temp ~= nil then
                                        domoticz.data.managedValue.add(settings.high_threshold_temp)
                                        domoticz.data.managedId.add(device.id)
                                    end
                                    domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
                                end
                            end
                        -- alarme hygrométrie
                            if device.humidity ~= nil and (settings.low_threshold_hr ~= nil or settings.high_threshold_hr ~= nil)  then
                                --test settings.duration_exceeded_hr
                                test_high_threshold = true
                                test_low_threshold = true
                                if settings.duration_exceeded_hr ~= nil then
                                    domoticz.data.managedValue.add(device.humidity)
                                    domoticz.data.managedId.add(device.id)

                                    if settings.high_threshold_hr ~= nil then high_threshold_hr = settings.high_threshold_hr else high_threshold_hr = nil end
                                    if settings.low_threshold_hr ~= nil then low_threshold_hr = settings.low_threshold_hr else low_threshold_hr = nil end
                                    --test_high_threshold, test_low_threshold = managed(dz, id, duration_exceeded, high_threshold, low_threshold)
                                    test_high_threshold, test_low_threshold = managed(domoticz, device.id, settings.duration_exceeded_hr, high_threshold_hr, low_threshold_hr)
                                end
                                domoticz.log('L\'hygrometrie mesurée par '.. device.name .. ' est de  ' .. tostring(device.humidity)..'%hr', domoticz.LOG_INFO)
                                if settings.low_threshold_hr ~= nil and device.humidity < settings.low_threshold_hr and test_low_threshold == true then -- seuil bas hygrométrie
                                    domoticz.log(device.name .. ' a un seuil hygrometrie bassse défini à  ' .. settings.low_threshold_hr..'%hr', domoticz.LOG_INFO)
                                    message = 'L\'humidité mesurée par '.. device.name .. ' est inférieure au seuil défini ('..settings.low_threshold_hr..'%hr). Valeur : '..tostring(device.humidity)..'%hr'
                                    if settings.duration_exceeded_hr ~= nil then
                                        domoticz.data.managedValue.add(settings.low_threshold_hr)
                                        domoticz.data.managedId.add(device.id)
                                    end
                                    domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
                                end
                                if settings.high_threshold_hr and device.humidity > settings.high_threshold_hr and test_high_threshold == true then -- seuil haut hygrométrie
                                    domoticz.log(device.name .. ' a un seuil hygrometrie haute défini à  ' .. settings.high_threshold_hr..'%hr', domoticz.LOG_INFO)
                                    message = 'L\'humidité mesurée par '.. device.name .. ' est supérieure au seuil défini ('..settings.high_threshold_hr..'%hr). Valeur : '..tostring(device.humidity)..'%hr'
                                    if settings.duration_exceeded_hr ~= nil then
                                        domoticz.data.managedValue.add(settings.high_threshold_hr)
                                        domoticz.data.managedId.add(device.id)
                                    end
                                    domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
                                end
                            end

                        elseif device.state == 'On' or device.state == 'Open' then
                        -- Alarme dispositif actif
                            domoticz.log(device.name .. ' est à l\'état ' .. device.state, domoticz.LOG_INFO)
                            if settings.time_active_notification ~= nil and device.lastUpdate.minutesAgo >= settings.time_active_notification then
                                domoticz.log(device.name .. ' est actif depuis ' .. device.lastUpdate.minutesAgo .. ' minutes. Le délai est fixé à '.. settings.time_active_notification.. ' minutes.', domoticz.LOG_INFO)
                                message = 'Le délai fixé à '.. settings.time_active_notification .. ' minutes pour '.. device.name .. ' est dépassé'
                                domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
                            end
                        -- auto on
                            if settings.auto_on_minutes ~= nil and device.lastUpdate.minutesAgo >= settings.auto_on_minutes then
                                if settings.state == 'Off' then
                                    domoticz.log('Allumage de '..device.name .. ' car inactif depuis ' .. settings.auto_on_minutes .. ' minutes.', domoticz.LOG_INFO)
                                    device.switchOn()
                                end
                            end
                            --auto off
                            if settings.auto_off_minutes ~= nil and device.lastUpdate.minutesAgo >= settings.auto_off_minutes then
                                if settings.auto_off_motion_device == nil then
                                    domoticz.log('Extinction de '..device.name .. ' car actif depuis ' .. settings.auto_off_minutes .. ' minutes.', domoticz.LOG_INFO)
                                    device.switchOff()
                                elseif type(settings.auto_off_motion_device) == "string" then
                                    local motion_device = domoticz.devices(settings.auto_off_motion_device)
                                    if motion_device.state == 'Off' then
                                        domoticz.log('Extinction de '.. device.name .. ' car aucune détection de mouvement dans la piece depuis ' .. settings.auto_off_minutes .. ' minutes.', domoticz.LOG_INFO)
                                        device.switchOff()
                                    end
                                elseif type(settings.auto_off_motion_device) == "table" then
                                    local off = true
                                    for i,v in ipairs(settings.auto_off_motion_device) do
                                        if domoticz.devices(v).state ~= 'Off' then
                                            off = false
                                        end
                                    end
                                    if off then
                                        domoticz.log('Extinction de '.. device.name .. ' car aucune détection de mouvement dans la piece depuis  ' .. settings.auto_off_minutes .. ' minutes.', domoticz.LOG_INFO)
                                        device.switchOff()
                                    end
                                end
                            end

                       elseif device.sensorType ~= nil and (settings.high_threshold_custom ~= nil or settings.low_threshold_custom ~= nil)  then
                        --alarme custom sensor
                            domoticz.log('La valeur mesurée par '.. device.name .. ' est de  ' .. tostring(domoticz.utils.round(device.state, 1)) .. device.sensorUnit, domoticz.LOG_INFO)
                            if settings.low_threshold_custom ~= nil and tonumber(device.state) < settings.low_threshold_custom then -- seuil bas %
                                domoticz.log(device.name .. ' a un seuil bas défini à  ' .. settings.low_threshold_custom..device.sensorUnit, domoticz.LOG_INFO)
                                message = 'La valeur mesurée par '.. device.name .. ' est inférieure au seuil défini ('..settings.low_threshold_custom..device.sensorUnit..'). Valeur : '..tostring(domoticz.utils.round(device.state, 1))..device.sensorUnit
                                domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
                            end
                            if settings.high_threshold_custom ~= nil and tonumber(device.state) > settings.high_threshold_custom then -- seuil haut %
                                domoticz.log(device.name .. ' a un seuil haut défini à  ' .. settings.high_threshold_custom..device.sensorUnit, domoticz.LOG_INFO)
                                message = 'La valeur mesurée par '.. device.name ..' est supérieure au seuil défini ('..settings.high_threshold_custom..device.sensorUnit..'). Valeur : '..tostring(domoticz.utils.round(device.state, 1))..device.sensorUnit
                                domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
                            end

                        elseif device.percentage ~= nil and (settings.high_threshold_percent ~= nil or settings.low_threshold_percent ~= nil)  then
                            -- test settings.duration_exceeded_hr
                            test_high_threshold = true
                            test_low_threshold = true
                            if settings.duration_exceeded_percent ~= nil then
                                domoticz.data.managedValue.add(device.percentage)
                                domoticz.data.managedId.add(device.id)

                                if settings.high_threshold_percent ~= nil then high_threshold_percent = settings.high_threshold_percent else high_threshold_percent = nil end
                                if settings.low_threshold_percent ~= nil then low_threshold_percent = settings.low_threshold_percent else low_threshold_percent = nil end
                                test_high_threshold, test_low_threshold = managed(domoticz, device.id, settings.duration_exceeded_percent, high_threshold_percent, low_threshold_percent)
                            end
                            -- alarme pourcentage
                            domoticz.log('La valeur mesurée par '.. device.name .. ' est de  ' .. tostring(domoticz.utils.round(device.percentage, 1)) ..'%', domoticz.LOG_INFO)
                            if settings.low_threshold_percent ~= nil and device.percentage < settings.low_threshold_percent and test_low_threshold == true then  -- seuil bas %
                                domoticz.log(device.name .. ' a un seuil % bas défini à  ' .. settings.low_threshold_percent..'%', domoticz.LOG_INFO)
                                message = 'La valeur mesurée par '.. device.name .. ' est inférieure au seuil défini ('..settings.low_threshold_percent..'%). Valeur : '.. tostring(domoticz.utils.round(device.percentage, 1)) ..'%'
                                if settings.duration_exceeded_percent ~= nil then
                                    domoticz.data.managedValue.add(settings.low_threshold_percent)
                                    domoticz.data.managedId.add(device.id)
                                end
                                domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
                            end
                            if settings.high_threshold_percent ~= nil and device.percentage > settings.high_threshold_percent and test_high_threshold == true then  -- seuil haut %
                                domoticz.log(device.name .. ' a un seuil % haut défini à  ' .. settings.high_threshold_percent..'%', domoticz.LOG_INFO)
                                message = 'La valeur mesurée par '.. device.name ..' est supérieure au seuil défini ('..settings.high_threshold_percent..'%). Valeur : '.. tostring(domoticz.utils.round(device.percentage, 1)) ..'%'

                                if settings.duration_exceeded_percent ~= nil then
                                    domoticz.data.managedValue.add(settings.high_threshold_percent)
                                    domoticz.data.managedId.add(device.id)
                                end
                                domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
                            end

                        elseif device.color ~= nil and settings.high_threshold_color ~= nil and device.color > settings.high_threshold_color then
                            -- notification alerte
                            domoticz.log('Le seuil d\'alerte de '.. device.name .. ' est de  ' .. tostring(device.color), domoticz.LOG_INFO)
                            message = 'Le seuil d\'alerte de  '.. device.name ..' est supérieur au seuil défini ('..settings.high_threshold_color..'). Valeur : '.. tostring(device.color) ..' alerte : '.. tostring(device.text)
                            domoticz.helpers.managedNotify(domoticz, subject, message, notificationTable(subSystems), frequency_notifications , quiet_hours)
            end
                        else
                            domoticz.log( 'la description de '.. device.name ..' n\'est pas au format json. Ignorer cet appareil.', domoticz.LOG_ERROR)
                        end
                            domoticz.log('--------------------------------------------------------------------------------------------------', domoticz.LOG_INFO)
                    end
                end
            )

        domoticz.log(tostring(cnt) .. ' devices scannés.', domoticz.LOG_INFO)
    end
}

Last edited by papoo on Wednesday 08 May 2019 23:04, edited 2 times in total.
User avatar
papoo
Posts: 126
Joined: Friday 22 January 2016 22:14
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10
Location: France
Contact:

Re: Generic auto-off

Post by papoo »

script update (in previous post)
already in v0.9:
- low and high threshold temp notifications
- low and high threshold Hr notifications
- low and high threshold percent notifications
- low and high threshold custom device notifications
- high threshold alert device notifications
- duration exceeded temp and Hr notifications
- frequency notifications
- quiet Hours notifications
- time active and inactive notifications
- timeout notifications

adding in v1.01:
- low battery level
- low signal level
- low and high watt usage
- low and high current usage
- auto on device
- personalized notification system(s) for each device
rinyheuvelman
Posts: 15
Joined: Wednesday 19 December 2018 14:40
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10427
Contact:

Re: Generic auto-off

Post by rinyheuvelman »

I knew I am not the most talented person when it comes to scripting, but...
Would someone please be so kind to explain it is done in case of multiple motion sensors?
Followed the gives examples which resulted in errors:

2019-12-23 23:12:00.199 Error: dzVents: Error: (2.5.3) Error parsing json to LUA table: /home/pi/domoticz/scripts/dzVents/../lua/JSON.lua:1009: /home/pi/domoticz/scripts/dzVents/../lua/JSON.lua:660: expected colon at char 66 of: {
2019-12-23 23:12:00.199 "auto_off_minutes": 5,
2019-12-23 23:12:00.199 "auto_off_motion_device": {"PIRBadkamer", "XiaomiBadPIR"}
2019-12-23 23:12:00.199 }
2019-12-23 23:12:00.199 Error: dzVents: Error: (2.5.3) Device description for Bad ambiance spot 1 is not in json format. Ignoring this device.

I can't figure out te correct way (most probably quit obvious to others) to list multiple sensors...
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: Generic auto-off

Post by waaren »

rinyheuvelman wrote: Monday 23 December 2019 23:28 Would someone please be so kind to explain it is done in case of multiple motion sensors?
I can't figure out te correct way (most probably quit obvious to others) to list multiple sensors...
Not sure what your question is.

Which version of the script do you use ? Can you post the script you are using now and also what you entered in the description field of your devices controlled by the script ?
Maybe that will help finding what is causing your error(s)
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Re: Generic auto-off

Post by rrozema »

rinyheuvelman wrote: Monday 23 December 2019 23:28 I knew I am not the most talented person when it comes to scripting, but...
Would someone please be so kind to explain it is done in case of multiple motion sensors?
Followed the gives examples which resulted in errors:

2019-12-23 23:12:00.199 Error: dzVents: Error: (2.5.3) Error parsing json to LUA table: /home/pi/domoticz/scripts/dzVents/../lua/JSON.lua:1009: /home/pi/domoticz/scripts/dzVents/../lua/JSON.lua:660: expected colon at char 66 of: {
2019-12-23 23:12:00.199 "auto_off_minutes": 5,
2019-12-23 23:12:00.199 "auto_off_motion_device": {"PIRBadkamer", "XiaomiBadPIR"}
2019-12-23 23:12:00.199 }
2019-12-23 23:12:00.199 Error: dzVents: Error: (2.5.3) Device description for Bad ambiance spot 1 is not in json format. Ignoring this device.

I can't figure out te correct way (most probably quit obvious to others) to list multiple sensors...
Given that you have 2 motion sensors "Overloop: Motion 1" and "Overloop: Motion 2" and want your light to go off 5 minutes after the last motion was detected on either sensor, this would be the text you would need to put in your light's description field:

Code: Select all

{
   "auto_off_minutes": 5,
   "auto_off_motion_device": ["Overloop: Motion 1","Overloop: Motion 2"]
}
Last edited by rrozema on Tuesday 24 December 2019 9:56, edited 1 time in total.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: Generic auto-off

Post by waaren »

rrozema wrote: Tuesday 24 December 2019 9:09 Given that you have 2 motion sensors "Overloop: Motion 1" and "Overloop: Motion 2" and want your light to go off 5 minutes after the last motion was detected on either sensor, this would be the text you would need to put in your light's description field:

Code: Select all

{
   "auto_off_minutes": 5,
   "auto_off_motion_device": "Overloop: Motion 1",
   "auto_off_motion_device": "Overloop: Motion 2"
}

Are you sure ? Tested with this

Code: Select all

return {
    on = {
        timer = { 'every minute' }},
        
    execute = function(dz)
        dz.log('-------- first auto_off_motion_device will be overwritten by 2nd')
        description = '{ "auto_off_minutes": 5,   "auto_off_motion_device": "Overloop: Motion 1",   "auto_off_motion_device": "Overloop: Motion 2"}'
        dz.utils.dumpTable(dz.utils.fromJSON(description))
        
        dz.log('------ should it not be this ?')
        description = '{"auto_off_minutes":5,"auto_off_motion_device":["Overloop: Motion 1","Overloop: Motion 2"]}'
        dz.utils.dumpTable(dz.utils.fromJSON(description))
        
    end
}
I get this

Code: Select all

2019-12-24 09:37:00.312 Status: dzVents: Info: -------- first auto_off_motion_device will be overwritten by 2nd
2019-12-24 09:37:00.314 Status: dzVents: > auto_off_minutes: 5
2019-12-24 09:37:00.314 Status: dzVents: > auto_off_motion_device: Overloop: Motion 2
2019-12-24 09:37:00.314 Status: dzVents: Info: ------ should it not be this ?
2019-12-24 09:37:00.315 Status: dzVents: > auto_off_minutes: 5
2019-12-24 09:37:00.315 Status: dzVents: > auto_off_motion_device:
2019-12-24 09:37:00.315 Status: dzVents: > 1: Overloop: Motion 1
2019-12-24 09:37:00.315 Status: dzVents: > 2: Overloop: Motion 2
2019-12-24 09:37:00.315 Status: dzVents: Info: ------ Finished Script #1
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Re: Generic auto-off

Post by rrozema »

:oops: You're right. I t has been a long time since I last did anything with the scripts (they work, so why fix it ;) ) I will correct my post accordingly.

Also added the example to the opening post.
rinyheuvelman
Posts: 15
Joined: Wednesday 19 December 2018 14:40
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10427
Contact:

Re: Generic auto-off

Post by rinyheuvelman »

Thanks rrozema and Waarren.
The .rext fin the description field can be read in the errors I copied from the log-file.
I made a copied from the script above, replaced the names with my sensor names.
Only this type of description kept returning errors
My original (as still in the 2nd script rrozema posted aswell in the bi-lingual script papoo posted.

"auto_off_minutes": 5,
"auto_off_motion_device": {"PIRBadkamer", "XiaomiBadPIR"}

Rrozema's original post, the one he updates,a tiny detail is changed:
{ went to the gym and became [

"auto_off_minutes": 5,
"auto_off_motion_device": ["PIRBadkamer", "XiaomiBadPIR"]

No errors this time.

[20200103 EDIT] (waaren) also corrected in earlier examples
Vondee
Posts: 30
Joined: Sunday 12 January 2020 19:06
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Generic auto-off

Post by Vondee »

The script runs perfectly. Is it possible instead of turning devices off, set a certain level. I have dimmable lights in the kitchen, and want to turn them to 20% after a certain time when no motion is detected. I tried to do this in lua but I cannot make it work.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: Generic auto-off

Post by waaren »

Vondee wrote: Sunday 26 January 2020 22:07 The script runs perfectly. Is it possible instead of turning devices off, set a certain level. I have dimmable lights in the kitchen, and want to turn them to 20% after a certain time when no motion is detected. I tried to do this in lua but I cannot make it work.
Warning: [Quick and Dirty way]
If you do not need to control other lights with this script, you could try to change device.switchOff() to device.dimTo(20) on the three lines in the script where you see this command. You also need to change line with

Code: Select all

if device.state ~= 'Off' then 
to

Code: Select all

if device.level and device.level ~= 20 then
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest