Niveau script, les miens vont peut-être au delà de certains besoins mais y'a moyen au besoin d'élaguer. Ils permettent en effet de changer de planning de manière automatique (un peu avant les heures de bascule HP/HC afin de ne pas louper des ordres éventuels ou en avoir du planning précédent), à noter que je fais le passage la veille un peu avant 22h00 au lieu du jour de bascule 6h00 afin que les plannings HC renforcés en rouge soient actifs sur la tranche nuit/HC d'une couleur restant encore moins chère.
Le switch planning est fait chez moi par un switch virtuel, permettant d'éviter de passer par plusieurs onglets/menus, avec chaque niveau du selecteur ayant une action du genre:
Code : Tout sélectionner
http://127.0.0.1:8080/json.htm?type=command¶m=setactivetimerplan&ActiveTimerPlan=1
Les numéros d'ActiveTimerPlan sont ceux de l'endroit ou on les crée.
Et fatalement, pour que ce switch soit synchro avec la sélection automatique, cette dernière passe aussi par lui et il faut décrire dans une table Lua
toTimPlans sa config switch avec le nom donné et niveau correspondant afin de rendre le code derrière générique. Le nom de ce switch slecteur virtuel est dans la variable
timerPlanSw
Evidemment, si on ne gère pas un planning rouge et ne compte pas en créer, on peut virer tout le code de changement de planning et variables liées. Si c'est le cas le nommer 'tempoR'.
Il faut sinon toujours créer 2 variables utilisateur chaîne de caractère pour stocker les couleurs J/J1 (resp.
tempoJ et
tempoJ1) et un device type text qui va afficher les couleurs dans l'onglet mesures, dont le nom est à renseigner dans la variable
tempoName.
Avoir renseigné un compte pour les notifs mail et MAJ l'adresse à notifier (on y reçoit alors un mail annonçant les jours blancs ou rouge) dans la variable
emailNotifyAlarm.
Ceci fait, le script time qui récupère l'info tempo et gère planning/notif est le suivant (~/domoticz/scripts/lua/script_time_tempoMgt.lua):
Code : Tout sélectionner
-- Title: script_time_tempoMgt.lua
--
-- This script manage tempo next-day "color" data retrieve from electricity provider,
-- timer plan switch to/from "red" days and warnings if next day 'color' was
-- not updated since more than 24h.
-- During "red" days, a warning is sent during high price hours (06h00/22h00) if
-- 10mn average power (computed in devMeanPwrVrtSen virtual power-meter) exceed a threshold.
--
-- Changelog:
-- 2023/10/15 : Creation
-- 2023/10/21 : Merge tempo update from all_time script.
-- 2023/10/28 : Extend next day color check max boundary from 14h00->16h00.
-- 2023/10/28 : Add tempoJ user var mgt + mean power drain alert for red days.
-- 2023/11/03 : Removed tempoName Idx explicit setting (use otherdevices_idx).
-- 2023/11/07 : Move mean power drain alert for red days in device script after
-- virtual power meter update changed to allow events triger...
-- 2023/11/28 : Add remaining days count for each price/color.
-- 2023/11/30 : Update tempoVarJ <- tempoVarJ1 at switch from red hours time, for
-- tempoVarJ being valid before daily tempo update hour.
--
--
-- Global settings
--
emailNotifyAlarm = 'TOTO@gmail.com'
--
-- Editable settings :
--
-- TEMPO current/next day "colors" update settings : (tempoName = virtual text switch name),
-- updates check time range must not cross midnight and be ordered (hCheck1 < hCheck2).
jsonLibPath = '/home/domo/domoticz/scripts/lua/JSON.lua' -- UPDATE USER NAME IN PATH !!!
hCheck1 = 11 -- Begin hour for updates check (should be done ~11h00)
hCheck2 = 16 -- End hour for updates check
tempoName = 'Tempo'
-- toTimPlans table string indexes must match names in timer-plan switching device timerPlanSw
-- and index a secondary table that contains 2 values with:
-- 1) Boolean : Define which timer-plan, if currently active, will trigger a "red day(s)" switch.
-- 2) Integer : Must match name level in selector definition.
-- => So we get decision/level data using toTimPlans.Norm[2] or, if VAR contains any
-- index string, toTimPlans[VAR][1] ('.' notation does not work for variables).
tempoVarJ = 'tempoJ' -- User variable that store current day color.
tempoVarJ1 = 'tempoJ1' -- User variable that store next day color for 6h00 timer plan switch.
timerPlanSw = 'PlanningActif'
toRedHour = 21 -- Switch to red timer-plan at 21h50.
toRedMin = 50
fromRedHour = 5 -- Switch from red timer-plan at 05h50.
fromRedMin = 50
toTimPlans = {['Off']={false, 0}, ['Norm']={true, 10}, ['Vacances']={false, 20}, ['VacancesM']={true, 30}, ['TempoR']={false, 40}}
--
-- Internal fct :
-- Get current script exec time & compute last 'device' or 'uservariable' update time.
--
local function timeLastUpdate(devOrVar, isUserVar)
t1 = os.time()
if (isUserVar == true) then
sT0 = uservariables_lastupdate[devOrVar]
else
sT0 = otherdevices_lastupdate[devOrVar]
end
-- Returns a date time like 2016-12-02 15:30:10
-- => Format as os.time & compute diff :
year = string.sub(sT0, 1, 4)
month = string.sub(sT0, 6, 7)
day = string.sub(sT0, 9, 10)
hour = string.sub(sT0, 12, 13)
minutes = string.sub(sT0, 15, 16)
seconds = string.sub(sT0, 18, 19)
t0 = os.time{year=year, month=month, day=day, hour=hour, min=minutes, sec=seconds}
tDiff = os.difftime(t1, t0)
return(tDiff)
end
--
-- Internal fct :
-- Get json answer EDF http/json API.
--
urlTempoColor='https://particulier.edf.fr/services/rest/referentiel/searchTempoStore?dateRelevant='
urlTempoCount='https://particulier.edf.fr/services/rest/referentiel/getNbTempoDays?TypeAlerte=TEMPO'
local function getUrlJson(url)
config = assert(io.popen('curl --retry 1 --connect-timeout 2 -m 4 \"'..url..'\"'))
tempo = config:read('*all')
config:close()
jsonOut = json:decode(tempo)
return(jsonOut)
end
----------
-- MAIN --
----------
commandArray = {}
time = os.date("*t")
-- TEMPO "COLOR" UPDATE:
-- Exec every 10mn in hereupper hours range until next day status is defined,
-- retrying while last update > range to handle tempory fails (EDF site unreachable...).
if ((time.min % 10 == 0) and (time.hour >= hCheck1) and (time.hour < hCheck2) and (timeLastUpdate(tempoName, false) > ((hCheck2 - hCheck1)*3600))) then
jsonLib = assert(loadfile(jsonLibPath))
json = (jsonLib)()
today = tostring(os.date("%Y-%m-%d"))
jsonTempo = getUrlJson(urlTempoColor..today)
--print(jsonTempo.couleurJourJ)
--print(jsonTempo.couleurJourJ1)
if (jsonTempo == nil) then
print("TEMPO : Warning, no data/color received ; Network issue?")
return
end
tempoJ = string.gsub(jsonTempo.couleurJourJ, "TEMPO_", "")
tempoJ1 = string.gsub(jsonTempo.couleurJourJ1, "TEMPO_", "")
dateDay = tostring(os.date("%A"))
dateNextDay = tostring(os.date('%A', (os.time()+ 86400)))
tempoText = dateDay..":"..tempoJ.." - "..dateNextDay..":"..tempoJ1
print("TEMPO : "..tempoText)
-- Only update when next day "color" is defined.
if (tempoJ1 ~= "NON_DEFINI") then
commandArray[#commandArray+1]={['Variable:'..tempoVarJ] = tempoJ}
commandArray[#commandArray+1]={['Variable:'..tempoVarJ1] = tempoJ1}
-- Get/add remaining days count information...
jsonTempo = getUrlJson(urlTempoCount)
--print(jsonTempo.PARAM_NB_J_BLEU)
--print(jsonTempo.PARAM_NB_J_BLANC)
--print(jsonTempo.PARAM_NB_J_ROUGE)
if (jsonTempo == nil) then
print("TEMPO : Warning, no data/count received ; Network issue?")
else
tempoText = tempoText..' ('..jsonTempo.PARAM_NB_J_BLEU..'/'..jsonTempo.PARAM_NB_J_BLANC..'/'..jsonTempo.PARAM_NB_J_ROUGE..')'
end
commandArray[#commandArray+1]={['UpdateDevice'] = otherdevices_idx[tempoName].."|0|"..tempoText}
-- Send notification mail if today or tomorrow prices are high...
if ((tempoJ1 ~= "BLEU") or (tempoJ ~= "BLEU")) then
commandArray[#commandArray+1]={['SendEmail'] = 'TEMPO Demain : '..tempoJ1..'#'..tempoText..'#'..emailNotifyAlarm}
end
print("TEMPO : Updated !")
end
end
-- Warn each hour (at HH:30", as Tempo update is usually done between 11:00 and 11:10),
-- during update hours range, if tempo status update did not work for more than 24h...
if ((time.min == 30) and (time.hour >= hCheck1) and (time.hour <= hCheck2)) then
local lastUpdVarT = timeLastUpdate(tempoVarJ1, true)
if (lastUpdVarT > 86400) then
print('ERROR : No TEMPO update since '..tostring(lastUpdVarT)..'s (>86400s/24h00).')
commandArray[#commandArray+1]={['SendEmail']='TEMPO Warning!#'..tempoVarJ1..' : Last Update > 24h ('..lastUpdVarT..'s)!!!#'..emailNotifyAlarm}
end
end
-- Need to switch to 'red' timerplan?
if ((time.hour == toRedHour) and (time.min == toRedMin)) then
if (uservariables[tempoVarJ1] == "ROUGE") and (toTimPlans[otherdevices[timerPlanSw]][1]) then
-- Switch current timer-plan to "TempoR"
print('Switch current timer-plan '..otherdevices[timerPlanSw]..' -> TempoR.')
commandArray[#commandArray+1]={[timerPlanSw]='Set Level: '..toTimPlans.TempoR[2]}
commandArray[#commandArray+1]={['SendEmail']='TEMPO Switch!#'..uservariables[tempoVarJ1]..' => TempoR!!!#'..emailNotifyAlarm}
end
end
-- Need to switch from 'red' timerplan?
if ((time.hour == fromRedHour) and (time.min == fromRedMin)) then
tempoJ1 = uservariables[tempoVarJ1]
if (tempoJ1 ~= "ROUGE") and (otherdevices[timerPlanSw] == "TempoR") then
-- Switch (back) "TempoR" timer-plan (always) to "Norm"
print('Switch current timer-plan '..otherdevices[timerPlanSw]..' -> Norm.')
commandArray[#commandArray+1]={[timerPlanSw]='Set Level: '..toTimPlans.Norm[2]}
commandArray[#commandArray+1]={['SendEmail']='TEMPO Switch!#'..uservariables[tempoVarJ1]..' => Norm!!!#'..emailNotifyAlarm}
end
-- Change tempoVarJ1 that is now tempoVarJ & may be used by tempoWarn script before daily refresh.
commandArray[#commandArray+1]={['Variable:'..tempoVarJ] = tempoJ1}
end
return commandArray
Au besoin, c'est pas mal commenté pour comprendre.
Et il a un script de type device compagnon chez moi qui n'est pas forcément applicable partout, car il s'appuie (en particulier) sur un power-meter virtuel (dans mon cas, le wattmètre zwave en tête de tableau ne sait calculer des valeurs moyenne et ne renvoyant que des instantanés, néanmoins configurables pour une granularité fine en temps et/ou % de changement de conso) qui calcule des puissances moyennes consommées par tranche de temps (avec un objectif de tranches de 10mn, mais dépendant du dernier report du wattmètre physique passé l'objectif fixé comme ce calcul ne peut être fait que d'un script type device: C'est une intégration discrète sommant 'puissance * temps depuis dernier update wattmètre physique' divisé in-fine par le temps total de la tranche de temps issue du last_update du wattmètre-moyenne virtuel): Cela me permet en l'état d'être averti par mail si une conso moyenne calculée sur 10mn dépasse 1kW (en instantané cela peut être plus, utiliser une moyenne permet de filtrer la mise en marche de la cafetière et limiter les notif), ce qui peut signifier qu'un ordre de consigne de chauffe n'est pas passé pour une raison ou une autre par exemple...
Pour éviter de coller en dur des heures d'avertissement pour limiter aux HP, il utilise aussi l'état d'un switch
SmartMeterSwitch qui est en série sur la commande relais HP/HC, afin de laisser ou non passer cette commande (utilisé par un planning vacances qui coupe le ballon, entre autres, et permet de repasser en planning normal à distance la veille du retour pour avoir de l'eau chaude en arrivant!) venant du Linky.
Fatalement, sans info conso globale fine permettant un calcul de valeur moyenne ni ce switch (tout est en fait dans le même matériel, un Smart-Meter Qubino en zwave installé en tête de tableau), même si on pourrait se passer de ce dernier, pas forcément possible d'utiliser cette partie pour tout le monde...
Je le donne tout de même (~/domoticz/scripts/lua/script_device_tempoWarn.lua)
Code : Tout sélectionner
-- Title: script_device_tempoWarn.lua
--
-- This script warns if power drain during "red" days exceed a limit.
-- CAUTION: Virtual switches update from La does not trigger other "device" scripts
-- but this works using http/Json API, for instance:
-- curl 'http://127.0.1.1:8080/json.htm?type=command¶m=udevice&idx=706&svalue=280'
--
-- Changelog:
-- 2023/11/01 : Creation /don't work as expected as virtuel sensors update
-- through Lua does not trigger events/device scripts...
-- 2023/11/07 : OK after virtual meter update changed to allow event trig.
--
--
-- Global settings
--
emailNotifyAlarm = 'TOTO@gmail.com'
--
-- Editable settings :
--
tempoVarJ='tempoJ' -- User variable that store current day color.
SmartMeterSwitch='Relais Smart-Meter HP/HC Actif' -- 'Off' during high electricity price hours
devMeanPwrVrtSen='Puissance MOY' -- Virtual sensor type "usage/electricity" name.
warnMeanPower=1000
commandArray = {}
if (devicechanged[devMeanPwrVrtSen]) and (uservariables[tempoVarJ] == 'ROUGE') then
local curMeanPwr = tonumber(devicechanged[devMeanPwrVrtSen])
-- DEBUG:
--print(devMeanPwrVrtSen..' : '..tostring(curMeanPwr)..'W.')
-- Log on warn pwr figures during highest electricity price hours...
if (curMeanPwr > warnMeanPower) and (otherdevices[SmartMeterSwitch] == 'Off') then
print('TEMPO : Warning, '..devMeanPwrVrtSen..'/'..uservariables[tempoVarJ]..' : '..curMeanPwr..'W !!!')
commandArray[#commandArray+1]={['SendEmail']='TEMPO Pwr!#'..devMeanPwrVrtSen..'='..curMeanPwr..'W ('..uservariables[tempoVarJ]..')#'..emailNotifyAlarm}
end
end
return commandArray
Avec le 1er script, la MAJ donne ce type de log:
Code : Tout sélectionner
2023-11-15 11:00:00.729 Status: LUA: TEMPO : Wednesday:BLEU - Thursday:NON_DEFINI
2023-11-15 11:02:05.949 Status: LUA: Puissance MOY : New time slice (after 603s) => Record Pmean=574.31W
2023-11-15 11:10:00.407 Status: LUA: TEMPO : Wednesday:BLEU - Thursday:BLEU
2023-11-15 11:10:00.407 Status: LUA: TEMPO : Updated !
A 11h00, un 1er essai est fait et on continue toutes les 10mn (avec une limite à 16h00) tant que le lendemain est à
NON_DEFINI, mais en général a 11h10 c'est bon et arrête la récup d'info. On a ici un log d'update de puissance moyenne qui s'est intercalé dans le grep de logs LUA d'ailleurs, celui dont je parlais au dessus...
EDIT 07/12: Ajout (1er script) comptes jours restant/couleur et recopie J<-J1 a l'heure de commutation matin pour que l'info du jour valide en user var soit OK avant la MAJ de 11h (sinon le second script notifiant de conso "hautes" pouvait déclencher se croyant encore en jour rouge).