Je partage avec vous ce script DZVents de mon cru : un mécanisme pour stocker et restaurer l'état d'une ampoule (tous les types de lumières, y compris les interrupteurs, si je suis passé à côté de quelque chose faites le moi savoir)
Par exemple : Vos ampoules éclairent faiblement en bleu, puis vous voulez les allumer en blanc à 100% parce qu'une porte s'est ouverte ou au passage devant un détecteur de mouvement.
Après quelques instants (minutes / secondes) vous voulez que les ampoules retournent à leur état précédent : éclaire en bleu faiblement.
Le script que je vous propose offre des fonctions partagées globales que vous pouvez utiliser dans vos propres scripts DZVents
Par exemple un script DZVents pour un détecteur de mouvement :
Code : Tout sélectionner
return {
on = {
devices = { 'Détecteur Mouvement' },
},
logging = {
level = domoticz.LOG_INFO,
marker = 'MOTION SENSOR TEST',
},
execute = function(domoticz, device)
-- Passe l'ampoule en blanc à 100% pendant une minute
-- puis restaure l'état qu'elle avait avant le changement
if(device.isDevice) then
-- Stocke l'état actuel de l'ampoule et programme sa restautation dans 1 minutes (60 sec.)
domoticz.helpers.restoreStateAfter(domoticz, 'Mon Ampoule', 60)
-- Change la couleur de l'ampoule (blanc / 100% luminosité)
domoticz.devices('Mon Ampoule').setColor(0,0,0,100,0,0,2,128)
end
end
}Vous avez besoin de l'utilitaire CURL, vous pouvez télécharger CURL ici s'il n'est pas déjà installé sur votre système. CURL est disponible pour de mulitples plateforme (windows / linux). C'est un utilitaire ligne de commande pour faire des requêtes HTTP (entre autres), mon script l'utilise pour faire des requêtes HTTP synchrones (DZVents propose seulement des requêtes asynchrones). Une fois téléchargé, placez CURL dans le dossier de votre choix et notez le chemin vers CURL, on va en avoir besoin.
Vous devez aussi avoir un script DZVents "global_data". Si vous n'avez pas ce "global_data", rendez vous dans Domoticz dans "Configuration" -> "Plus d'Options" -> "Evénements", cliquez sur "+" et sélectionnez "DZVENTS" -> "GLOBAL DATA". Au lieu de "Script #1" tapez "global_data" (sans les guillemets). Copiez le code ci-dessous et cliquez sur "SAUVEGARDER" (vérifiez les logs de Domoticz s'il n'y a pas d'erreur, il y a quelque fois des problèmes de permissions quand Domoticz sauvegarde les scripts)
Si vous avez un script "global_data", alors vous devez ajouter les fonctions et variables globales que vous trouvez dans le code ci-dessous.
Code : Tout sélectionner
-- 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. So if
return {
-- Persistent Global Variables
data = {
-- RESTORE STATE VARS --
previousStates = { initial = { [0] = nil } },
-- END RESTORE STATE VARS
},
-- Global Functions
helpers = {
-- Does the argument is a number
-- x : the value to check
isNumber = function (x)
if tonumber(x) ~= nil then return true end
return false
end,
-- get the color of a light
-- deviceId : IDX or device name
getColor = function(domoticz, deviceId)
local idx = deviceId
if(not domoticz.helpers.isNumber(deviceId)) then idx = domoticz.devices(deviceId).idx end
cmd='"C:\\Program Files (x86)\\Domoticz\\scripts\\lua\\curl.exe" '..domoticz.settings.url..'/json.htm?type=devices^&rid='..idx
local httpRequest = assert(io.popen(cmd))
local html = httpRequest:read('*all')
local json = domoticz.utils.fromJSON(html)
-- adding brigthness to the color object
local color = domoticz.utils.fromJSON(json.result[1].Color)
color.br = domoticz.devices(deviceId).level
-- returning the result
return color
end,
-- RESTORE STATE FUNC --
-- store the state of a light
-- domoticz : domoticz object
-- deviceName : device name
-- holdFor : validity of the state. if nil the state can be restored at anytime, otherwise state can be restored upto the "holdFor" duration (in seconds)
storeState = function(domoticz, deviceName, holdFor)
-- Get the device ID
local device = domoticz.devices(deviceName)
local deviceId = device.id
domoticz.log('Sotring state for device :'..deviceName, domoticz.LOG_INFO)
-- time when the state will expire (ie : when it should be restored)
local validTill
local storeState = true
local checkStates = false
if(holdFor == nil) then validTill = nil else validTill = domoticz.time.addSeconds(holdFor).dDate end
-- should we store this new state
if(validTill ~= nil) then
-- we know when this state must end, we have
-- to check that the previous state should end
-- before this new one
local lastState = domoticz.globalData.previousStates[deviceId]
if(lastState ~= nil) then
if(lastState.value.validTill == nil) then
-- nok : our time is supposed to be past
-- the one already stored
-- we change the date of the stored state by
-- the date of the new state
lastState.value.validTill = validTill
storeState = false
checkStates = true
elseif(lastState.value.validTill > validTill) then
-- ok our date is past the date of the
-- already stored state
storeState = true
elseif(lastState.value.validTill <= validTill) then
-- nok our date is before the date of
-- the already stored state
-- we change the date of the stored state by
-- the one of the new state
lastState.value.validTill = validTill
storeState = false
checkStates = true
end
end
else
-- we dont know the duration of the state we are storing
-- so we cannot store this state if one state is already stored
if(domoticz.globalData.previousStates[deviceId] ~= nil) then storeState = false end
end
-- checking if states are not conflicting
while(checkStates) do
checkStates = false
local lastState = domoticz.globalData.previousStates[deviceId]
while(lastState.next ~= nil) do
if((lastState.next.value.validTill == nill) or
(lastState.next.value.validTill <= lastState.value.validTill)) then
-- current state will expire before next state
-- replacing expiration time of next state by current
lastState.next.value.validTill = lastState.value.validTill
-- deleting current state
lastState.next = lastState.next.next
lastState.value = lastState.next.value
domoticz.globalData.previousStates[deviceId] = lastState
-- need one more pass to check conflicts
checkStates = true
else
-- all is ok no need to continue
break
end
end
end
if(storeState) then
-- storing state (on/off)
local currentState = { ['validTill'] = validTill, ['state'] = 'Off', ['color'] = nil }
currentState.state = device.state
-- storing color (when RGB+ device)
if(device.deviceType == 'Color Switch') then
local color = domoticz.helpers.getColor(domoticz, device.idx)
currentState.color = color
else
if(device.switchType == 'Dimmer') then
--storing brightness level
currentState.color = {['br'] = device.level }
end
end
-- push device state in the states linked list
domoticz.log('Stored state for device '..deviceId..' : '..domoticz.utils.toJSON(currentState), domoticz.LOG_INFO)
domoticz.globalData.previousStates[deviceId] = { next = domoticz.globalData.previousStates[deviceId], value = currentState }
end
end,
-- restore a device state (if a stored state exists)
-- deviceName : idx or device name to restore
restoreState = function(domoticz, deviceName)
-- get device ID
local deviceId = domoticz.devices(deviceName).id
-- ask for device state restoration now (custom event)
domoticz.emitEvent('restoreState', deviceId)
end,
-- store the current state (color / power) of light and schedule its restoration
-- deviceName = idx / device name (light or switch)
-- holdFor = time in seconds before restoring the state
restoreStateAfter = function(domoticz, deviceName, holdFor)
-- get device ID
local deviceId = domoticz.devices(deviceName).id
-- store device state with "holdFor" lifetime
domoticz.helpers.storeState(domoticz, deviceName, holdFor)
-- schedule device restoration in "holdFor" sec.
domoticz.emitEvent('restoreState', deviceId).afterSec(holdFor)
end,
-- clear the stored state of a device, canceling its future restoration
-- this is useful to prevent light to turn back on when you want them
-- to stay off and don't know if a state is about to be restored.
-- deviceName = idx or device name
cancelRestoreState = function(domoticz, deviceName)
-- get device ID
local deviceId = domoticz.devices(deviceName).id
domoticz.log('Cancel stored states for device '..deviceId, domoticz.LOG_INFO)
-- clear all stored device states
domoticz.globalData.previousStates[deviceId] = nil
end
-- END RESTORE STATE FUNC
}
}
cmd='"C:\\Program Files (x86)\\Domoticz\\scripts\\lua\\curl.exe" '..domoticz.settings.url..'/json.htm?type=devices^&rid='..idx
Remplacez ce chemin par le vôtre.
Lorsque c'est fait il faut ensuite créer le script principal : dans l'éditeur de scripts, cliquez sur "+" puis sélectionnez "DZVENTS" -> "CUSTOM EVENTS", donnez lui le nom que vous voulez à la place de "Script #1", par exemple "Restauration Etat" (attention pas d'accents etc.. sinon ça coince), copiez / collez le code ci-dessous et cliquez sur "SAUVEGARDER".
Code : Tout sélectionner
return {
on = { customEvents = { 'restoreState' } },
logging = { level = domoticz.LOG_INFO,
marker = 'RESTORE STATE', },
execute = function(domoticz, item)
-- Restore State
if(item.isCustomEvent) then
-- Custom Event = restoreState
if(item.trigger == 'restoreState') then
-- Get the ID of the device to restore state
local deviceId = tonumber(item.data)
domoticz.log('Restore state for device '..item.data, domoticz.LOG_INFO)
-- if the stored state had a validTill date
-- greater that the current time : we do nothing
-- because we expect to restore this state at a later time
local lastState = nil
if(domoticz.globalData.previousStates[deviceId]) then
lastState = domoticz.globalData.previousStates[deviceId].value
if(lastState.validTill ~= nil and
lastState.validTill > domoticz.time.dDate) then
domoticz.log('State restoration delayed', domoticz.LOG_INFO)
return
end
end
-- we have a state to restore
if(lastState ~= nil) then
-- restoring previous state
domoticz.log('State to restore for device '..deviceId..' : '..domoticz.utils.toJSON(lastState), domoticz.LOG_INFO)
if(lastState.state ~= 'Off') then
if(domoticz.devices(deviceId).deviceType == 'Color Switch' and lastState.color ~= nil) then
-- color device : restoring color / white level as well as brightness
domoticz.devices(deviceId).setColor(lastState.color.r, lastState.color.g, lastState.color.b,
lastState.color.br,
lastState.color.cw, lastState.color.ww,
lastState.color.m, lastState.color.t)
else
-- restoring brightness only
domoticz.devices(deviceId).switchOn()
if(domoticz.devices(deviceId).switchType=='Dimmer' and lastState.color ~= nil) then
domoticz.devices(deviceId).dimTo(lastState.color.br)
end
end
else
-- restoring power state only
domoticz.devices(deviceId).switchOff()
end
-- clean up stored states
domoticz.globalData.previousStates[deviceId] = domoticz.globalData.previousStates[deviceId].next
else
domoticz.log('No stored state found', domoticz.LOG_INFO)
end
end
end
end
}
domoticz.helpers.storeState(domoticz, deviceName, holdFor)
Pour stocker l'état actuel de l'ampoule/switch deviceName, holdFor c'est le temps en secondes au bout duquel l'état doit être restauré. Par exemple si vous stockez l'état d'un ampoule parce que vous changez temporairement sa couleur pendant 1 minute après détection d'un mouvement, holdFor est égal à 60 secondes. Si vous ne savez pas quand l'état doit être restauré alors utilisez nil.
Vous pouvez utiliser cette fonction plusieurs fois pour la même ampoule, car de mulitples états peuvent être stockés. Le script se débrouille tout seul pour savoir si oui ou non l'état doit être stocké (justement en utilisant holdFor)
domoticz.helpers.restoreState(domoticz, deviceName)
Restaure l'état de l'ampoule deviceName. Plusieur étant pouvant être stockés, Le script choisi lui même quelle état restaurer (bien souvent c'est dernier stocké, dernier restaurés mais pas tout le temps)
domoticz.helpers.restoreStateAfter(domoticz, deviceName, holdFor)
Stocke l'état de l'ampoule et programme sa restauration dans holdFor secondes. Habituellement juste après l'appel à cette fonction, vous llez changer l'état de l'ampoule (couleur / luminosité / alimentation)
domoticz.helpers.cancelRestoreState(domoticz, deviceName)
Efface tous les états stockés pour l'ampoule deviceName. Ceci empêche toute restauration d'état pour cette ampoules qui aurait été programmé avant. Cette fonction s'utilise principalement lorsque vous éteignez une ampoule et que vous souhaitez vraiement qu'elle reste éteinte.