Actualiser inter en fonction d'un planning

Forum dédié aux problématiques concernant les scripts pour DomoticZ.
Entourez votre code et les logs avec les balises nommées code grâce au bouton <\>.
skarab22
Messages : 101
Inscription : 14 nov. 2019, 09:18

Actualiser inter en fonction d'un planning

Message par skarab22 »

Bonjour à tous,

Je gère l'ensemble de mes chauffage avec des planning. Lorsque je suis à la maison hors des heures de planning, il m'arrive de modifier l'état d'un interrupteur et j'aimerai qu'au d'un temps défini (2h par ex.) l'inter repasse dans l'état prévu par le planning.

Je pensais faire cela avec un script qui vérifie l'heure de modif de l'inter par contre je ne sais pas comment récupérer l'état défini dans le planning. Savez vous comment faire ?

Merci d'avance
Keros
Messages : 6638
Inscription : 23 juil. 2019, 20:57

Re: Actualiser inter en fonction d'un planning

Message par Keros »

Tu peux aussi créer un planning dans un device virtuel séparé. Ce serait une horloge pour ton device que tu peux facilement appeler pour connaitre l'état.
Comment bien utiliser le forum : Poser une question, Mettre un script, un fichier, une image ou des logs
Mes petits guides : Débuter en programmation, Le débogage, Le choix de matériel, Les sauvegardes
Ma présentation - Mes Tutos
skarab22
Messages : 101
Inscription : 14 nov. 2019, 09:18

Re: Actualiser inter en fonction d'un planning

Message par skarab22 »

Keros a écrit : 22 déc. 2019, 23:35 Tu peux aussi créer un planning dans un device virtuel séparé. Ce serait une horloge pour ton device que tu peux facilement appeler pour connaitre l'état.
Pardon, mais je ne comprend pas vraiment en quoi ça me permet d'actualiser mes autres devices.

Pour illustrer mon soucis, aujourd'hui je m'absente de la maison. Les chauffages étaient en mode confort et doivent passer en mode hg. Lorsque j'ai changé de calendrier, mes inter n'ont pas changé et ne changerons que ce soir à minuit (prochaine entrée dans le planning )
Keros
Messages : 6638
Inscription : 23 juil. 2019, 20:57

Re: Actualiser inter en fonction d'un planning

Message par Keros »

J'essayais de répondre à ta question :
je ne sais pas comment récupérer l'état défini dans le planning.
Je pensais que tu avais un planning directement sur ton device de commande et que tu cherchais à retrouver cette info.

Et désolé je ne comprends pas :
Lorsque j'ai changé de calendrier
Comment bien utiliser le forum : Poser une question, Mettre un script, un fichier, une image ou des logs
Mes petits guides : Débuter en programmation, Le débogage, Le choix de matériel, Les sauvegardes
Ma présentation - Mes Tutos
skarab22
Messages : 101
Inscription : 14 nov. 2019, 09:18

Re: Actualiser inter en fonction d'un planning

Message par skarab22 »

Keros a écrit : 23 déc. 2019, 21:42
Je pensais que tu avais un planning directement sur ton device de commande et que tu cherchais à retrouver cette info.
Effectivement, j'ai défini plusieurs planning pour chaque interrupteur directement dans domoticz (pas de script). Pour cela, on peut utiliser la fonction calendrier (Réglages -> paramètre -> Calandrier -> Plan, cf : liens).
Keros a écrit : 23 déc. 2019, 21:42 que tu cherchais à retrouver cette info
C'est bien ça, je cherche à connaitre l'état dans lequel devrait être mon interrupteur et s'il y a un écart avec le planning, basculer l'interrupteur.
Keros
Messages : 6638
Inscription : 23 juil. 2019, 20:57

Re: Actualiser inter en fonction d'un planning

Message par Keros »

Je ne connaissais pas cette fonction de contexte. Mais je comprend que se soit délicat de retrouver une valeur qui se trouve hors du contexte. Désolé, je ne peux pas t'aider plus.

Ce que j'ai fait : j'ai plusieurs "horloge" et en fonction de mes cas, j'utilise l'une ou l'autre.

Par exemple : je passe un device en manuel on. Si je le repasse en auto, il récupère la valeur de l'horloge et suivra les changements de l'horloge.
Comment bien utiliser le forum : Poser une question, Mettre un script, un fichier, une image ou des logs
Mes petits guides : Débuter en programmation, Le débogage, Le choix de matériel, Les sauvegardes
Ma présentation - Mes Tutos
skarab22
Messages : 101
Inscription : 14 nov. 2019, 09:18

Re: Actualiser inter en fonction d'un planning

Message par skarab22 »

Hello, petit UP sur le sujet. Je n'ai toujours pas trouvé d'autre solution que de passé en lua et je ne trouve pas cela super pratique d'avoir à modifier le code pour modifier mes plages horaires. Quelqu'un à une meilleur idée ?
skarab22
Messages : 101
Inscription : 14 nov. 2019, 09:18

Re: Actualiser inter en fonction d'un planning

Message par skarab22 »

Rebonjour à tous,

Comme le froid revient, mes soucis de chauffage avec... Comme je le disais précédemment, je gère mes radiateur et poele à granule à l'aide d'interrupteur avec un planning.
Lorsque je m'absente je désactive les différents planning et les passe en mode HG ou eco selon la durée de l'absence. Quand je reviens, je réactive tout mes planing et j'aimerai que chacun des inter repasse dans le bon mode de manière automatique.

Ne serait il pas possible de faire cela avec un commande json pour vérifier quel est le dernier planing activé ?

Merci d'avance
Flying Domotic
Messages : 772
Inscription : 10 mars 2020, 15:26

Re: Actualiser inter en fonction d'un planning

Message par Flying Domotic »

Je partage l'idée de Keros. Il n'est pas facile de "bricoler" un planning (même si c'est possible).

Par contre, il est simple de créer un device virtuel auquel on associe un planning, et de commander une sortie en fonction d'un état/contexte.

Tu peux assez simplement dire : si je suis dehors, je suis off, sinon j'utilise l'état du device virtuel planning, ou si ce switch a été modifié il y a moins de 2 heures, j'utilise sa valeur, sinon celle du planning.
lost
Messages : 1511
Inscription : 12 nov. 2016, 11:01

Re: Actualiser inter en fonction d'un planning

Message par lost »

skarab22 a écrit : 11 oct. 2020, 21:33 Quand je reviens, je réactive tout mes planing et j'aimerai que chacun des inter repasse dans le bon mode de manière automatique.

Ne serait il pas possible de faire cela avec un commande json pour vérifier quel est le dernier planing activé ?
Pouvoir récupérer la consigne du planning courant pour la tranche horaire dans laquelle on est, c'est une fonctionnalité réclamée régulièrement sur le forum anglophone à la rubrique suggestion. Idéalement, cela pourrait s'appliquer automatiquement au changement de planning.

De même, pouvoir invalider/valider globalement les plannings d'un switch (ou d'un plan de planning complet) n'ont jamais été implémentés nativement. On n'a qu'un truc assez inutile (voir stupide!) pour valider/invalider par ID de timer associé à une entrée de planning d'un switch donné.

Il y a 2 ou 3 ans, la possibilité de créer autant de plannings que l'on veut avait néanmoins arrangé l'affaire: Pour ma part j'ai désormais un planning normal (prenant en compte les jours/heures de présence habituels avec travail parents/cours enfants), un planning vacance-maison (présence quasi constante), un planning absence (qui pourrait être vacances-ailleurs!).

On peut en switcher avec une commande type (du localhost, avec un serveur web sur le port 8080; on peut aussi tester d'un navigateur de son PC en mettant l'IP du PI ou autre hébergeant Domoticz):
http://127.0.0.1:8080/json.htm?type=com ... imerPlan=1

On se fait un switch selecteur avec 1 commande par planning et roule...

Pour avoir des infos sur le planning actif, par contre, ne reste que la commande qui permet de tous les récupérer, même entête de commande avec:
json.htm?type=schedules

Il y a une version filtrant par nom de device...

Pour ma part, j'avais fait un script python pour valider/dévalider toutes les entrées planning d'un (ou plusieurs, via wildcards, si on respecte une convention de nommage) switch donné qui peut service d'exemple de parsing JSON (pour les ID timers de la stupiderie évoquée au préalable) à reprendre/compéter pour récupérer l'ordre du début de la tranche horaire active:

Code : Tout sélectionner

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Schedule activation modification for device (with wildcards support)
# Date for state change, if an 'hour' parameter is given, is stored in
# a user var than can be checked by a lua time script that'll reverse current state...
#
# Changelog : 17/12/2016, YL, 1st version.

import getopt
import logging
import json
import sys
import requests
import datetime
from   fnmatch  import fnmatch

#####################
# EDITABLE SETTINGS #
#####################

logLevel='INFO' # DEBUG / INFO

# Domoticz json API url
dmtJurl         = 'http://127.0.0.1:8080/json.htm?'

# Command parameters in json format (only change if API change!)
dmtJsonGetSched = {"type":"schedules"}
dmtJsonActTimer = {"type":"command", "param":"enabledisabletimer", "idx":"999"}
dmtJsonUpdVar   = {"type":"command", "param":"updateuservariable",
                   "vname":"reverseSchedule", "vtype":2, "vvalue":0}
                   
# Domoticz time format on LUA side:
dmtLuaTimeFmt   = "%Y-%m-%d %H:%M:%S"
                   
#####################
def usage():
    """
    Display usage
    """
		
    sys.stderr.write( "Usage: ScheduleMod.py [-h] [-s<on/off>] [-t<timeInMn>] -n<device>\n")
    sys.stderr.write( "       If no 's', current state is reversed.\n")
    sys.stderr.write( "       If    't', a time for state reversal (mn) is stored for domoticz.\n")

#####################
def dmtJsonApi(url, jsonApiCmd, logger):
    """
    Send Domoticz json command
    """
		
    try:
        # Connect to Domoticz via JSON API and send data
        dmtRget=requests.get(url, params=jsonApiCmd)
    except requests.exceptions.RequestException as dmtErr:
        logger.log(logging.ERROR, "Unable to connect with URL=%s \nGet requests error %s" % (dmtRget.url, dmtErr))
    finally:
        logger.log(logging.DEBUG, "Sent data: [%s]" % (dmtRget.url))
		
	return dmtRget.json()

#####################
def main(argv):
    """
    Main
    """
    
    logging.basicConfig()
    logger = logging.getLogger()
    handler = logging.StreamHandler(sys.stdout)

    # Checks the parameters
    try:
        opts, args = getopt.getopt(argv, "h:s:n:t:",["help","state","name","time"])
    except getopt.GetoptError:
        usage()
        sys.exit(2)
    
    # Defaults    
    SchedActivate = 'reverse'
    devName       = 'nil'
    reverseTimeMn = 0
    
    for o, a in opts:
        if o in ("-h", "--help"):
            usage()
            sys.exit()
        if o in ("-s", "--state" ):
            SchedActivate=('disabletimer','enabletimer')[a == 'on']   
        if o in ("-n", "--name" ):
            devName=a
        if o in ("-t", "--time" ):
            reverseTimeMn=int(a)	
    
    # Configure the logger
    handler.setFormatter(
        logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
    logger.setLevel(logLevel)
	
    logger.log(logging.INFO, "Device(s)=%s, update schedules to '%s', reverse after %dmn." %(devName, SchedActivate, reverseTimeMn))
    
    # Get all schedules
    schedules = dmtJsonApi(dmtJurl, dmtJsonGetSched, logger)
    #logger.log(logging.DEBUG, "Schedules: [%s]" % (schedules))

    # Modify active setting for dev name...
    schedNb=len(schedules['result'])
    logger.log(logging.DEBUG, "Found %d schedules, extract those for %s" % (schedNb, devName))
    
    # Change schedule(s) for device(s) matching name (wildcard support): 
    for sched in schedules['result']:
        if (fnmatch(sched['DevName'], devName)):
            logger.log(logging.DEBUG, 'Found : %s , state=%s, idx=%d',
                       sched['DevName'],
                       sched['Active'],
                       sched['TimerID'])
            
            curState = ('disabletimer','enabletimer')[sched['Active'] == 'true']
            revState = ('enabletimer','disabletimer')[sched['Active'] == 'true']
            
            if (curState != SchedActivate):
                # Update domoticz request parameters
                dmtJsonActTimer['param'] = (SchedActivate, revState)[SchedActivate == 'reverse']
                dmtJsonActTimer['idx']   = sched['TimerID']
                
                # Send request...
                dmtJsonApi(dmtJurl, dmtJsonActTimer, logger)
    
    # Set user var to current date + time given for reversal (in mn), if any...
    if (reverseTimeMn != 0):
        revDate = datetime.datetime.now() + datetime.timedelta(minutes=reverseTimeMn)
        revDate = devName + ';' + revDate.strftime(dmtLuaTimeFmt)
        logger.log(logging.DEBUG, "Reverse time stored for Domoticz : %s", revDate)
        dmtJsonUpdVar['vvalue'] = revDate
        dmtJsonApi(dmtJurl, dmtJsonUpdVar, logger)
    else:
        dmtJsonUpdVar['vvalue'] = 'nil'
        dmtJsonApi(dmtJurl, dmtJsonUpdVar, logger)
    
    # Happy ending!
    logger.log(logging.INFO, "DONE !")
    
if __name__ == "__main__":
    main(sys.argv[1:])
Pour ma part, cela ne me sert pas afin de gérer des validations selon absence/présence, mais pour couper temporairement tous les radiateurs pour une durée variable (en heures) quand je mets mon insert en route. Et il y a revalidation automatique au bout de la durée cible (utilisation d'une variable utilisateur stockant l'heure d'invalidation): Cette partie est dans un script time Lua séparé...

Sans ce besoin, la partie user var du script ci dessus peut être retirée (sinon, la variable user "reverseSchedule" doit être crée séparément, le script ne le faisant pas automatiquement si inexistante, encore 1 truc qui serait à amérliorer).

L'appel de ce script est faite via un interrupteur arrêt temporaire qui appelle un script bash qui appelle le script python ci dessus (on ne peut a priori toujours pas appeler du python directement d'un script attaché à un switch).

Exemple (j'ai en réalité plusieurs switch pour arrêt global, par étage, ou salle de bain séparément ; en plus de l'arrêt temporaire ci dessous):

Code : Tout sélectionner

#!/bin/bash

if [ ${1} -ne 0 ];
then
  /home/XXX/domoticz/scripts/scheduleMod.py -nRadiateur* -soff -t${1}
  setLevel=5
else
  /home/XXX/domoticz/scripts/scheduleMod.py -nRadiateur* -son
  setLevel=15
fi

curl "http://127.0.0.1:8080/json.htm?type=command&param=switchlight&idx=20&switchcmd=Set%20Level&level=${setLevel}"
curl "http://127.0.0.1:8080/json.htm?type=command&param=switchlight&idx=5&switchcmd=Set%20Level&level=${setLevel}"
curl "http://127.0.0.1:8080/json.htm?type=command&param=switchlight&idx=7&switchcmd=Set%20Level&level=${setLevel}"
curl "http://127.0.0.1:8080/json.htm?type=command&param=switchlight&idx=70&switchcmd=Set%20Level&level=${setLevel}"
curl "http://127.0.0.1:8080/json.htm?type=command&param=switchlight&idx=11&switchcmd=Set%20Level&level=${setLevel}"
curl "http://127.0.0.1:8080/json.htm?type=command&param=switchlight&idx=24&switchcmd=Set%20Level&level=${setLevel}"
curl "http://127.0.0.1:8080/json.htm?type=command&param=switchlight&idx=238&switchcmd=Set%20Level&level=${setLevel}"
curl "http://127.0.0.1:8080/json.htm?type=command&param=switchlight&idx=242&switchcmd=Set%20Level&level=${setLevel}"
Tous les radiateurs ont un préfixe "Radiateur" dans leur nom, ce qui permet avec wildcard de les cibler tous. Les commandes curl font elles un passage immédiat en stop (invalidation planning) ou hors-gel (re-validation... mais la consigne ne sera reprise qu'a la tranche horaire suivante, plannings re-validés). Les ordres variateur correpondent aux commandes d'un module fil pilote Qubino z-wave (tranche 0/10% = arrêt, 10/20%=hors-gel etc pour les 6 ordres. j'utilise le milieu de chaque tranche d'ou les 5/15 du script).

Appel de ce script bash via un switch selecteur avec des entrées du genre (pour une invalidation de 4h = 240mn):
script:///home/XXX/domoticz/scripts/radiateurStopTime.sh 240

Le script python étant lui aussi sous home/XXX/domoticz/scripts/ (XXX=pi si pas de modif utilisateur par défaut d'un raspberry sous raspbian).

On pourrait sans doute modifier cela afin, selon l'horodatage d'appel du script python, que la consigne active soit remise automatiquement. Pour ma part, l'usage majoritaire est l'insert qui diffuse sa chaleur longtemps après l'arrêt. C'est donc pas à quelques heures près et je l'avais pas fait.
Répondre