Avant toute chose merci de (re)prendre connaissance de la charte et de la respecter.
Pour résumer :
- Avant de poser une question, je cherche si la réponse existe
- Je suis poli, courtois et je respecte tout un chacun sur le forum
- Si un post m'agace : je m'en éloigne plutôt que de répondre d'une façon qui pourrait être mal interprétée


Il n'est jamais du luxe que de rappeler des choses simples :
Courtoisie, amabilité, politesse et bonne humeur sont les maîtres mots pour un forum sympathique, bienveillant et accueillant :)

Toute la communauté vous remercie

[Plugin Tiers][Sujet Principal] Volets Proportionnel

Pour échanger sur les plugins classés en catégorie "Automatisation"
Bashrog
Timide
Messages : 207
Inscription : 24 déc. 2016, 10:29

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par Bashrog » 03 oct. 2018, 12:59

Euh là c'est bizarre, quand je lui demande d'ouvrir les volets à 100% après les avoir baissé à 50%, il baisse les volets !!

Code : Tout sélectionner



[2018-10-03 12:24:15][DEBUG] : [Bureau][Volets Prop Bureau] Temps d'action 7500000µs
[2018-10-03 12:24:15][DEBUG] : [Bureau][Volets Prop Bureau] Nous allons descendre le volet de 50%
[2018-10-03 12:24:22][DEBUG] : [Bureau][Volets Prop Bureau] Le volet est a 100%
[2018-10-03 12:25:12][DEBUG] : [Bureau][Volets Prop Bureau] Temps d'action 2000000µs
[2018-10-03 12:25:12][DEBUG] : [Bureau][Volets Prop Bureau] Nous allons descendre le volet de 1%
[2018-10-03 12:25:14][DEBUG] : [Bureau][Volets Prop Bureau] Le volet est a 100%
[2018-10-03 12:25:28][DEBUG] : [Bureau][Volets Prop Bureau] Temps d'action 2000000µs
[2018-10-03 12:25:28][DEBUG] : [Bureau][Volets Prop Bureau] Nous allons descendre le volet de 1%
[2018-10-03 12:25:30][DEBUG] : [Bureau][Volets Prop Bureau] Le volet est a 100%
[2018-10-03 12:56:35][DEBUG] : [Bureau][Volets Prop Bureau] Temps d'action 7500000µs
[2018-10-03 12:56:35][DEBUG] : [Bureau][Volets Prop Bureau] Nous allons descendre le volet de 50%
[2018-10-03 12:56:42][DEBUG] : [Bureau][Volets Prop Bureau] Le volet est a 100%
[2018-10-03 12:57:14][DEBUG] : [Bureau][Volets Prop Bureau] Temps d'action 2000000µs
[2018-10-03 12:57:14][DEBUG] : [Bureau][Volets Prop Bureau] Nous allons descendre le volet de 1%
[2018-10-03 12:57:16][DEBUG] : [Bureau][Volets Prop Bureau] Le volet est a 100%
[2018-10-03 12:57:22][DEBUG] : [Bureau][Volets Prop Bureau] Temps d'action 2000000µs
[2018-10-03 12:57:22][DEBUG] : [Bureau][Volets Prop Bureau] Nous allons descendre le volet de 1%
[2018-10-03 12:57:24][DEBUG] : [Bureau][Volets Prop Bureau] Le volet est a 100%



Avatar de l’utilisateur
mika-nt28
Actif
Messages : 6101
Inscription : 05 août 2014, 08:58
Localisation : Dreux - France

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par mika-nt28 » 03 oct. 2018, 13:05

En faite il vois toujours 100%
Pour faciliter la compréhension de votre problème, n’oubliez pas de poster
- Des Screenshots de votre configuration
- Le Log au moment du problème constaté

Encouragez-moi https://www.paypal.me/mikant28

Bashrog
Timide
Messages : 207
Inscription : 24 déc. 2016, 10:29

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par Bashrog » 04 oct. 2018, 16:31

J'ai refait des tests et il y'a toujours le même comportement étrange.

J'ai, tout d'abord, fermé le volet à 50%. Puis j'ai demandé à l'ouvrir à 100%, le volet s'est un peu baissé. J'ai de nouveau demandé à l'ouvrir à 100% et il s'est à nouveau baissé ?

Code : Tout sélectionner

[2018-10-03 12:24:15][DEBUG] : [Bureau][Volets Prop Bureau] Temps d'action 7500000µs
[2018-10-03 12:24:15][DEBUG] : [Bureau][Volets Prop Bureau] Nous allons descendre le volet de 50%
[2018-10-03 12:24:22][DEBUG] : [Bureau][Volets Prop Bureau] Le volet est a 100%
[2018-10-03 12:25:12][DEBUG] : [Bureau][Volets Prop Bureau] Temps d'action 2000000µs
[2018-10-03 12:25:12][DEBUG] : [Bureau][Volets Prop Bureau] Nous allons descendre le volet de 1%
[2018-10-03 12:25:14][DEBUG] : [Bureau][Volets Prop Bureau] Le volet est a 100%
[2018-10-03 12:25:28][DEBUG] : [Bureau][Volets Prop Bureau] Temps d'action 2000000µs
[2018-10-03 12:25:28][DEBUG] : [Bureau][Volets Prop Bureau] Nous allons descendre le volet de 1%
[2018-10-03 12:25:30][DEBUG] : [Bureau][Volets Prop Bureau] Le volet est a 100%
[2018-10-03 12:56:35][DEBUG] : [Bureau][Volets Prop Bureau] Temps d'action 7500000µs
[2018-10-03 12:56:35][DEBUG] : [Bureau][Volets Prop Bureau] Nous allons descendre le volet de 50%
[2018-10-03 12:56:42[2018-10-04 16:24:47][DEBUG] : [Bureau][Volets Prop Bureau] Temps d'action 7500000µs
[2018-10-04 16:24:47][DEBUG] : [Bureau][Volets Prop Bureau] Nous allons descendre le volet de 50%
[2018-10-04 16:24:55][DEBUG] : [Bureau][Volets Prop Bureau] Le volet est a 100%
[2018-10-04 16:28:38][DEBUG] : [Bureau][Volets Prop Bureau] Temps d'action 2000000µs
[2018-10-04 16:28:38][DEBUG] : [Bureau][Volets Prop Bureau] Nous allons descendre le volet de 1%
[2018-10-04 16:28:40][DEBUG] : [Bureau][Volets Prop Bureau] Le volet est a 100%
[2018-10-04 16:28:50][DEBUG] : [Bureau][Volets Prop Bureau] Temps d'action 2000000µs
[2018-10-04 16:28:50][DEBUG] : [Bureau][Volets Prop Bureau] Nous allons descendre le volet de 1%
[2018-10-04 16:28:52][DEBUG] : [Bureau][Volets Prop Bureau] Le volet est a 100%

Avatar de l’utilisateur
mika-nt28
Actif
Messages : 6101
Inscription : 05 août 2014, 08:58
Localisation : Dreux - France

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par mika-nt28 » 04 oct. 2018, 18:22

C'est etrange , je vais chercher ca
Pour faciliter la compréhension de votre problème, n’oubliez pas de poster
- Des Screenshots de votre configuration
- Le Log au moment du problème constaté

Encouragez-moi https://www.paypal.me/mikant28

Gautomax
Timide
Messages : 22
Inscription : 01 avr. 2016, 13:22

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par Gautomax » 08 oct. 2018, 21:35

Salut,

Je viens de découvrir ce plugin et il est vraiment génial, merci !!!! Il va me permettre de supprimer une batterie de scripts pour piloter mes Velux.

Une petite question (et honte à moi si elle a déjà été posée) :
- Est-ce qu'il est prévu dans la roadmap de créer une ou des positions mémorisées, pour pouvoir les appeler directement ?

En tous cas bravo et merci !!!

Avatar de l’utilisateur
mika-nt28
Actif
Messages : 6101
Inscription : 05 août 2014, 08:58
Localisation : Dreux - France

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par mika-nt28 » 09 oct. 2018, 08:48

Non se n'est pas prévue, je ne vois vraiment pas l’intérêt.
Que l'on donne un hauteur ou que l'on appuie sur un bouton c'est pareil
Pour faciliter la compréhension de votre problème, n’oubliez pas de poster
- Des Screenshots de votre configuration
- Le Log au moment du problème constaté

Encouragez-moi https://www.paypal.me/mikant28

lanfeuste
Timide
Messages : 96
Inscription : 15 juin 2016, 21:05

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par lanfeuste » 09 oct. 2018, 19:09

Un petit virtuel et c'est bon sinon!

noBru77
Timide
Messages : 335
Inscription : 11 oct. 2016, 00:41

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par noBru77 » 10 oct. 2018, 13:31

C’est exactement ce que j’ai fait avec une apparition par dessus mon design si je clique sur l’icône de mon volet. J’ai alors le choix entre 4 positions prédéterminées.


Envoyé de mon iPhone en utilisant Tapatalk

Bashrog
Timide
Messages : 207
Inscription : 24 déc. 2016, 10:29

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par Bashrog » 10 oct. 2018, 17:32

Sinon, tu as une piste sur le problème que j'ai évoqué.
Aujourd'hui encore, je demande à SIRI d'ouvrir tous les volets à 100% (deux étaient à moitié baissés) et tous les volets se sont fermés à 87% !

justmi
Timide
Messages : 5
Inscription : 02 nov. 2017, 15:11

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par justmi » 10 oct. 2018, 19:39

Bonjour,

Je viens d'installer un fgr222 sur un volet somfy. avec le plugin de base j'arrive a ouvrir proportionnellement le volet mais pas du tout avec ce plugin.
les commandes UP Down fonctionnent correctement mais je n'arrive pas a régler pour faire des commandes proportionnelles.

merci pour votre aide

Avatar de l’utilisateur
mika-nt28
Actif
Messages : 6101
Inscription : 05 août 2014, 08:58
Localisation : Dreux - France

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par mika-nt28 » 11 oct. 2018, 08:15

Il n'y a pas d'interret d'utilisé se plugin si ton module fait deja du proportionnel
Plus on est loin du HW plus on perd en precision (Temps réel)
Pour faciliter la compréhension de votre problème, n’oubliez pas de poster
- Des Screenshots de votre configuration
- Le Log au moment du problème constaté

Encouragez-moi https://www.paypal.me/mikant28

Helethom
Timide
Messages : 15
Inscription : 06 mars 2018, 22:37
Contact :

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par Helethom » 02 nov. 2018, 23:50

tsim79 a écrit :
01 mai 2018, 11:11
Matt25p a écrit :
10 avr. 2018, 20:04
Matt25p a écrit :
10 avr. 2018, 16:17


après vérif le problème persiste toujours j'ai désactivé la gestion volet pour celui ci. a la descente il remonte jusqu'a la limite du décollement du volet et quand je le monte a 100% 3 seconde après etre en haut il redescend met s’arrête a la limite du décollement du volet pourtant dans les log je vois pas de commande de descente ou de monté c'est vraiment bizarre.
Voila j'ai enfin trouvé mon problème si cela peux aidé aussi quelqu'un ma commande stop de mes volets a une position intermédiaire pré-enregistré avant la domotic quand j'avais du soleil j’appuyai sur le bouton stop et mes volets descendais ou montais à la position voulu.
Du coup le souci avec le plugin c'est que quand le volet est demandé a 0 ou 100% il utilise la commande Stop pour arrêté le volet sauf que si mon volet est arrivé en position fin de course avant l'envoie de la commande stop du plugin car celle-ci sont réglé correctement il enclenche du coup ma position intermédiaire.
SI je change ma durée dans le plugin mon volet ne s'ouvre plus en entier.
Solution de mon coté essayé de supprimé ma position intermédiaire dans mes volets
Proposition d'amélioration du plugin: lorsque 0 ou 100% sont demandé utilisé uniquement les commandes monté ou descente sans la commande stop. Autre solution pouvoir réglé au dixième de seconde dans le temps de monté.
Voili voilou si sa peux aidé
Merci a toi mika pour ce boulot ton plugin marche très bien c'est juste que nous avons différentes config
Bonjour merci pour ce plugin qui augure une simplification de la gestion de l'ouverture et fermeture des volets de façons proportionnel. J'avais déjà vu, mais je préférais ma gestion pas l'intermédiaire d'un scénario et des positions connu d'avance.

Pour ce qui me concerne, j'utilise un RFLINK pour commander tous les volets RTS de chez moi. A savoir, ouverture à 100% des volets de chambre et une ouverture interstice pour les volets de ma pièce de vie (position favori MY = appui sur Stop).
J'ai constaté la même chose chez moi en testant ton plugin, lorsque l'on demande une ouverture total à 100% ou fermeture total à 0%, ton plugin utilisant la commande STOP compte-tenu des temps de monter et ou de descente, fait que une fois le volet ouvert ou fermé, il se remets en position favorite (interstice chez ).

Pour pallier à ce soucis de position favori sur volet RTS, l'idéal serait soit :
- lors d'un réglage de curseur >= 97% cela équivaut à une commande UP sans STOP à la suite.
- lors d'un réglage de curseur <= 3% cela équivaut à une commande DOWN sans STOP à la suite.

Sinon c'est à l'utilisateur de penser de façon préalable que:
- Si il veut ouvrir au max 100% il utilise que le bouton UP ou faut qu'il se limite à 97% avec le curseur.
- Si il veut fermer au mini 0% il utilise le bouton DOWN ou faut qu'il se limite à 3% avec le curseur.

On a tendance à vouloir utiliser le curseur systématiquement, alors qu'il devrait intervenir uniquement pour un réglage proportionnel, et les boutons pour ouverture et fermeture total.

Edit:
Tu devrais limiter la plages de réglages des volets par curseur à des valeurs de 10% à 95%
Bonjour,
Merci beaucoup pour ce plugin que j'espère pourvoir réussir à utiliser avec mes volets. J'ai en effet un problème similaire aux deux commentaire cités plus haut.
Je commande mes volets via un RFXCOM et j'ai les trois ordres: MONTER, STOP et DESCENDRE, sans aucun retour d'état.
Le problème est que la commande STOP arrête bien le volet quand il est en mouvement. En revanche, si le volet est déjà à l'arrêt lorsque l'ordre STOP est donné, alors la le volet se met à descendre.
Celà pose problème lorsque que je donne un ordre d'ouverture à 100% avec le plugin. En effet, je crois comprendre que celui-ci envoie une commande STOP au moment où il écrit "Le volet est à 100%"dans les Logs, car c'est exactement à ce moment là que le volet se remet en mouvement et se referme complètement.
Je pense que la solution proposée plus haut pourrait résoudre mon problème:
tsim79 a écrit :
01 mai 2018, 11:11
Pour pallier à ce soucis de position favori sur volet RTS, l'idéal serait soit :
- lors d'un réglage de curseur >= 97% cela équivaut à une commande UP sans STOP à la suite.
- lors d'un réglage de curseur <= 3% cela équivaut à une commande DOWN sans STOP à la suite.
Merci d'avance de votre aide.
Thomas

EDIT: J'ai trouvé la solution. Il suffit de supprimer la position sauvegardée "MY"du volet en suivant la procédure suivante: https://service.somfy.com/downloads/fr_ ... _my_vr.pdf
Thomas

tsim79
Timide
Messages : 486
Inscription : 23 avr. 2015, 11:54

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par tsim79 » 03 nov. 2018, 11:31

EDIT: J'ai trouvé la solution. Il suffit de supprimer la position sauvegardée "MY"du volet en suivant la procédure suivante: https://service.somfy.com/downloads/fr_ ... _my_vr.pdf
Bonjour cette solution n'est pas si intéressante.
Mes enfants, ma femme utilisent la position favorite des volets depuis la télécommande, tout les occupants de la maison ne peuvent pas systématiquement passer par Jeedom pour régler l'ouverture proportionnel d'un volet!

Dans une chambre lorsque l'on veut ouvrir un volet à moitié, c'est possible grâce à cette fonction de position favorite depuis la télécommande physique!
Dans mon séjour, lorsque je veux une ouverture avec interstices la position favorite est là pour cela!

🤔?

Helethom
Timide
Messages : 15
Inscription : 06 mars 2018, 22:37
Contact :

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par Helethom » 03 nov. 2018, 15:52

tsim79 a écrit :
03 nov. 2018, 11:31
EDIT: J'ai trouvé la solution. Il suffit de supprimer la position sauvegardée "MY"du volet en suivant la procédure suivante: https://service.somfy.com/downloads/fr_ ... _my_vr.pdf
Bonjour cette solution n'est pas si intéressante.
Mes enfants, ma femme utilisent la position favorite des volets depuis la télécommande, tout les occupants de la maison ne peuvent pas systématiquement passer par Jeedom pour régler l'ouverture proportionnel d'un volet!

Dans une chambre lorsque l'on veut ouvrir un volet à moitié, c'est possible grâce à cette fonction de position favorite depuis la télécommande physique!
Dans mon séjour, lorsque je veux une ouverture avec interstices la position favorite est là pour cela!

🤔?
Bonjour,
De mon côté j'évite d'utiliser les télécommandes Somfy car je n'ai pas de retour d'état de leur utilisation avec RFXcom... Tu arrives à avoir ces infos?

Maintenant que j'arrive à utiliser le plugin j'ai de nombreux soucis:
-Le temps de décollement n'est jamais pris en compte dans le temps d'action. Par exemple, Lorsque le volet est fermé (0%), il fait temps_total/2 pour une commande à 50% alors qu'il devrait faire (temps_total - temps_décollement)/2 + temps_décollement. Est ce que c'est à cause de l'absence de capteurs de fin de course?
-Les boutons Up, Down et Stop fonctionnent mais ne mettent pas à jour la hauteur du volet.

Avez-vous rencontré des problèmes similaires?
Merci d'avance
Thomas

Helethom
Timide
Messages : 15
Inscription : 06 mars 2018, 22:37
Contact :

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par Helethom » 03 nov. 2018, 16:16

Pour être plus précis, voici un exemple de logs en enchainant les commandes suivantes :
-Ordre de montée à 50% avec départ en position fermée (0%)
-Ordre de Montée à 100%
-Ordre de descente à 50%
-Ordre de descente à 0%

Réglages du plugin:
-Temps total: 26s
-Temps décollement 4s
-Aucun retour détat.


Ordre de montée à 50% en commençant en position fermée

Code : Tout sélectionner

[2018-11-03 16:01:56][DEBUG] : [Salon][Salon Volet] Temps d'action 13000000µs 
Normalement ça devrait être (26-4)/2+4=1500000µs

Code : Tout sélectionner

[2018-11-03 16:01:56][DEBUG] : [Salon][Salon Volet] Nous allons monter le volet de 50%
[2018-11-03 16:02:09][DEBUG] : [Salon][Salon Volet] Le volet est a 50% 
Le volet est en réalité plus bas que 50%
Ordre de montée à 100%

Code : Tout sélectionner

[2018-11-03 16:02:15][DEBUG] : [Salon][Salon Volet] Temps d'action 11000000µs 
calcul correct, mais comme on part d'une position plus basse, le volet s'arrête avant d'être arrivé à 100%

Code : Tout sélectionner

[2018-11-03 16:02:15][DEBUG] : [Salon][Salon Volet] Nous allons monter le volet de 50%
[2018-11-03 16:02:26][DEBUG] : [Salon][Salon Volet] Le volet est a 100% 
Ordre de descente à 50%

Code : Tout sélectionner

[2018-11-03 16:02:31][DEBUG] : [Salon][Salon Volet] Temps d'action 11000000µs 
calcul correct, mais comme on part d'une position plus basse, le volet s'arrête plus bas que 50%

Code : Tout sélectionner

[2018-11-03 16:02:31][DEBUG] : [Salon][Salon Volet] Nous allons descendre le volet de 50%
[2018-11-03 16:02:42][DEBUG] : [Salon][Salon Volet] Le volet est a 50%
Ordre de descente à 0%

Code : Tout sélectionner

[2018-11-03 16:02:44][DEBUG] : [Salon][Salon Volet] Temps d'action 13000000µs 
Normalement ça devrait être (26-4)/2+4=1500000µs)

Code : Tout sélectionner

[2018-11-03 16:02:44][DEBUG] : [Salon][Salon Volet] Nous allons descendre le volet de 50%
[2018-11-03 16:02:57][DEBUG] : [Salon][Salon Volet] Le volet est a 0%
Merci d'avance de vos avis
Thomas

Helethom
Timide
Messages : 15
Inscription : 06 mars 2018, 22:37
Contact :

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par Helethom » 04 nov. 2018, 15:55

Bonjour,
Il y a effectivement une erreur de calcul dans le core. Pour la corriger, je propose de faire les modifs suivantes (ca marche nickel chez moi, je suis parti de la version stable):

Remplacer la fonction TpsAction par:

Code : Tout sélectionner

    	public function TpsAction($Hauteur, $Decol) {
		$TpsGlobal=$this->getConfiguration('Ttotal');
		$TpsDecol=$this->getConfiguration('Tdecol');
		$TpsDebattement=$TpsGlobal- $TpsDecol;
		if(!$Decol){
		$tps=round(($TpsDebattement*$Hauteur/100)*1000000);	
		}else{
		$tps=round(($TpsDebattement*$Hauteur/100+$TpsDecol)*1000000);	
		}
		if($tps <= $this->getConfiguration('delaisMini')*1000000) 
			$tps = $this->getConfiguration('delaisMini')*1000000;
		log::add('voletProp','debug',$this->getHumanName().' Temps d\'action '.$tps.'µs');
		return $tps;
	}
Cette modification résoud le problème du mauvais calcul avec le temps de décollement.

Remplacer la fonction UpdateHauteur() par (Aussi une erreur de calcul)

Code : Tout sélectionner

public function UpdateHauteur() {
		$ChangeState = cache::byKey('voletProp::ChangeState::'.$this->getId())->getValue(false);
		$ChangeStateStart = cache::byKey('voletProp::ChangeStateStart::'.$this->getId())->getValue(time());
		$ChangeStateStop = cache::byKey('voletProp::ChangeStateStop::'.$this->getId())->getValue(time());		
		$Tps=$ChangeStateStop-$ChangeStateStart;
		$TpsGlobal=$this->getConfiguration('Ttotal');
        $TpsDecol=$this->getConfiguration('Tdecol');
		$TpsDebattement=$TpsGlobal- $TpsDecol;
		
		$HauteurActuel=$this->getCmd(null,'hauteur')->execCmd();
		if($HauteurActuel != 0){
          $Hauteur=$Tps*100/$TpsDebattement;
        }else{
          $Hauteur=($Tps-$TpsDecol)*100/$TpsDebattement;
        }
		
		if($ChangeState)
			$Hauteur=round($HauteurActuel+$Hauteur);
		else
			$Hauteur=round($HauteurActuel-$Hauteur);
		if($Hauteur<0)
			$Hauteur=0;
		if($Hauteur>100)
			$Hauteur=100;
		log::add('voletProp','debug',$this->getHumanName().' Le volet est a '.$Hauteur.'%');
		$this->checkAndUpdateCmd('hauteur',$Hauteur);
	}

Et de manière générale, remplacer tous les time() par des microtime(true).

Voici le code complet:

Code : Tout sélectionner

<?php
require_once dirname(__FILE__) . '/../../../../core/php/core.inc.php';
class voletProp extends eqLogic {
	public static function cron() {
		foreach(eqLogic::byType('voletProp') as $Volet){ 
			if(cache::byKey('voletProp::Move::'.$Volet->getId())->getValue(false)){
				$ChangeStateStart = cache::byKey('voletProp::ChangeStateStart::'.$Volet->getId())->getValue(microtime(true)+$Volet->getConfiguration('Ttotal'));
				if(time()-$ChangeStateStart >=$Volet->getConfiguration('Ttotal')){
					$cmd=cmd::byId(str_replace('#','',$Volet->getConfiguration('cmdStop')));
					if(is_object($cmd))
						$cmd->execute(null);
					cache::set('voletProp::ChangeStateStop::'.$Volet->getId(),microtime(true), 0);
					$Volet->UpdateHauteur();
				}
			}
		}
	}
	public static function deamon_info() {
		$return = array();
		$return['log'] = 'voletProp';
		$return['launchable'] = 'ok';
		$return['state'] = 'nok';
		foreach(eqLogic::byType('voletProp') as $Volet){
			if($Volet->getIsEnable() && $Volet->getConfiguration('UpStateCmd') != '' && $Volet->getConfiguration('DownStateCmd') != ''&& $Volet->getConfiguration('StopStateCmd') != '' && $Volet->getConfiguration('cmdEnd') != ''){
				$listener = listener::byClassAndFunction('voletProp', 'pull', array('Volets_id' => $Volet->getId()));
				if (!is_object($listener))
					return $return;
			}
		}
		$return['state'] = 'ok';
		return $return;
	}
	public static function deamon_start($_debug = false) {
		log::remove('voletProp');
		self::deamon_stop();
		$deamon_info = self::deamon_info();
		if ($deamon_info['launchable'] != 'ok') 
			return;
		if ($deamon_info['state'] == 'ok') 
			return;
		foreach(eqLogic::byType('voletProp') as $Volet){
			cache::set('voletProp::Move::'.$Volet->getId(),false, 0);
			$Volet->StartListener();
		}
	}
	public static function deamon_stop() {	
		foreach(eqLogic::byType('voletProp') as $Volet){
			$Volet->StopListener();
		}
	}
	public static function Up($_option) {
		log::add('voletProp','debug','Detection sur le listener Up : '.json_encode($_option));
		$Volet = eqLogic::byId($_option['Volets_id']);
		$detectedCmd = cmd::byId($_option['event_id']);
		if (is_object($detectedCmd) && is_object($Volet) && $Volet->getIsEnable()) {
			log::add('voletProp','info',$Volet->getHumanName().$detectedCmd->getHumanName());
			if($this->getConfiguration('cmdStop') == '' && cache::byKey('voletProp::Move::'.$Volet->getId())->getValue(false) && cache::byKey('voletProp::ChangeState::'.$Volet->getId())->getValue(false)){
				cache::set('voletProp::ChangeStateStop::'.$Volet->getId(),strtotime($detectedCmd->getCollectDate(microtime(true))), 0);
				$Volet->UpdateHauteur();
				cache::set('voletProp::Move::'.$Volet->getId(),false, 0);
			}else{
				$isUp=$Volet->getConfiguration('UpStateCmd').$Volet->getConfiguration('UpStateOperande').$Volet->getConfiguration('UpStateValue');
				if($Volet->EvaluateCondition($isUp)){
					cache::set('voletProp::ChangeState::'.$Volet->getId(),true, 0);
					cache::set('voletProp::Move::'.$Volet->getId(),true, 0);
					cache::set('voletProp::ChangeStateStart::'.$Volet->getId(),microtime(true), 0);
				}
			}
		}
	}
	public static function Down($_option) {
		log::add('voletProp','debug','Detection sur le listener Down : '.json_encode($_option));
		$Volet = eqLogic::byId($_option['Volets_id']);
		$detectedCmd = cmd::byId($_option['event_id']);
		if (is_object($detectedCmd) && is_object($Volet) && $Volet->getIsEnable()) {
			log::add('voletProp','info',$Volet->getHumanName().$detectedCmd->getHumanName());
			if($this->getConfiguration('cmdStop') == '' && cache::byKey('voletProp::Move::'.$Volet->getId())->getValue(false) && !cache::byKey('voletProp::ChangeState::'.$Volet->getId())->getValue(false)){
				cache::set('voletProp::ChangeStateStop::'.$Volet->getId(),strtotime($detectedCmd->getCollectDate(microtime(true))), 0);
				$Volet->UpdateHauteur();
				cache::set('voletProp::Move::'.$Volet->getId(),false, 0);
			}else{
				$isDown=$Volet->getConfiguration('DownStateCmd').$Volet->getConfiguration('DownStateOperande').$Volet->getConfiguration('DownStateValue');
				if($Volet->EvaluateCondition($isDown)){
					cache::set('voletProp::ChangeState::'.$Volet->getId(),false, 0);
					cache::set('voletProp::Move::'.$Volet->getId(),true, 0);
					cache::set('voletProp::ChangeStateStart::'.$Volet->getId(),microtime(true), 0);
				}
			}
		}
	}
	public static function Stop($_option) {
		log::add('voletProp','debug','Detection sur le listener Stop : '.json_encode($_option));
		$Volet = eqLogic::byId($_option['Volets_id']);
		$detectedCmd = cmd::byId($_option['event_id']);
		if (is_object($detectedCmd) && is_object($Volet) && $Volet->getIsEnable()) {
			log::add('voletProp','info',$Volet->getHumanName().$detectedCmd->getHumanName());
			$isStop=$Volet->getConfiguration('StopStateCmd').$Volet->getConfiguration('StopStateOperande').$Volet->getConfiguration('StopStateValue');
			if($Volet->EvaluateCondition($isStop)){
				$Move=cache::byKey('voletProp::Move::'.$Volet->getId());
				cache::set('voletProp::ChangeStateStop::'.$Volet->getId(),strtotime($detectedCmd->getCollectDate(microtime(true))), 0);
				if(is_object($Move) && $Move->getValue(false)){
					$Volet->UpdateHauteur();
					cache::set('voletProp::Move::'.$Volet->getId(),false, 0);
				}
			}
		}
	}
	public static function End($_option) {
		log::add('voletProp','debug','Detection sur le listener End : '.json_encode($_option));
		$Volet = eqLogic::byId($_option['Volets_id']);
		$detectedCmd = cmd::byId($_option['event_id']);
		if (is_object($detectedCmd) && is_object($Volet) && $Volet->getIsEnable()) {
			log::add('voletProp','info',$Volet->getHumanName().$detectedCmd->getHumanName());
			if($_option['value'])
				$Volet->checkAndUpdateCmd('hauteur',0);
		}
	}
	public function boolToText($value){
		if (is_bool($value)) {
			if ($value) 
				return __('Vrai', __FILE__);
			else 
				return __('Faux', __FILE__);
		} else 
			return $value;
	}
	public function EvaluateCondition($Condition){
		$_scenario = null;
		$expression = scenarioExpression::setTags($Condition, $_scenario, true);
		$message = __('Evaluation de la condition : ['.jeedom::toHumanReadable($Condition).'][', __FILE__) . trim($expression) . '] = ';
		$result = evaluate($expression);
		$message .=$this->boolToText($result);
		log::add('voletProp','info',$this->getHumanName().$message);
		if(!$result)
			return false;		
		return true;
	}
public function UpdateHauteur() {
		$ChangeState = cache::byKey('voletProp::ChangeState::'.$this->getId())->getValue(false);
		$ChangeStateStart = cache::byKey('voletProp::ChangeStateStart::'.$this->getId())->getValue(microtime(true));
		$ChangeStateStop = cache::byKey('voletProp::ChangeStateStop::'.$this->getId())->getValue(microtime(true));		
		$Tps=$ChangeStateStop-$ChangeStateStart;
		$TpsGlobal=$this->getConfiguration('Ttotal');
        $TpsDecol=$this->getConfiguration('Tdecol');
		$TpsDebattement=$TpsGlobal- $TpsDecol;
		
		$HauteurActuel=$this->getCmd(null,'hauteur')->execCmd();
		if($HauteurActuel != 0){
          $Hauteur=$Tps*100/$TpsDebattement;
        }else{
          $Hauteur=($Tps-$TpsDecol)*100/$TpsDebattement;
          
        }
		
		if($ChangeState)
			$Hauteur=round($HauteurActuel+$Hauteur);
		else
			$Hauteur=round($HauteurActuel-$Hauteur);
		if($Hauteur<0)
			$Hauteur=0;
		if($Hauteur>100)
			$Hauteur=100;
		log::add('voletProp','debug',$this->getHumanName().' Le volet est a '.$Hauteur.'%');
		$this->checkAndUpdateCmd('hauteur',$Hauteur);
	}
    	public function CheckSynchro($Hauteur) {
		if($this->getConfiguration('Synchronisation') == "")
			return true;
		if($this->getConfiguration('cmdStop') != ''){
			$Stop=cmd::byId(str_replace('#','',$this->getConfiguration('cmdStop')));
			if(!is_object($Stop))
				return false;
		}
		$Down=cmd::byId(str_replace('#','',$this->getConfiguration('cmdDown')));
		if(!is_object($Down))
			return false;
		$Up=cmd::byId(str_replace('#','',$this->getConfiguration('cmdUp')));
		if(!is_object($Up))
			return false;
		foreach($this->getConfiguration('Synchronisation') as $Synchronisation){
			if($Synchronisation == '100' && $Hauteur == 100){
				log::add('voletProp','info',$this->getHumanName().'[Synchronisation] Montée complete');
				$Up->execute(null);
				if(!isset($Stop))
					$Stop=$Down;
				sleep($this->getConfiguration('Ttotal'));
				$Stop->execute(null);		
				if($this->getConfiguration('UpStateCmd') == '' && $this->getConfiguration('DownStateCmd') == '')
					$this->checkAndUpdateCmd('hauteur',100);
				return false;
			}
			if($Synchronisation == '0' && $Hauteur == 0){
				log::add('voletProp','info',$this->getHumanName().'[Synchronisation] Descente complete');
				$Down->execute(null);
				if(!isset($Stop))
					$Stop=$Up;
				sleep($this->getConfiguration('Ttotal'));
				$Stop->execute(null);		
				if($this->getConfiguration('UpStateCmd') == '' && $this->getConfiguration('DownStateCmd') == '')
					$this->checkAndUpdateCmd('hauteur',0);
				return false;
			}
			if($Synchronisation == 'all'){
				log::add('voletProp','info',$this->getHumanName().'[Synchronisation] Montée complete');
				$Up->execute(null);
				if(!isset($Stop))
					$Stop=$Down;
				sleep($this->getConfiguration('Ttotal'));
				$Stop->execute(null);		
				if($this->getConfiguration('UpStateCmd') == '' && $this->getConfiguration('DownStateCmd') == '')
					$this->checkAndUpdateCmd('hauteur',100);
				return true;
			}
		}
		return true;
	}
    	public function execPropVolet($Hauteur) {
		if(!$this->CheckSynchro($Hauteur))
			return false;
		if($this->getConfiguration('cmdStop') != ''){
			$Stop=cmd::byId(str_replace('#','',$this->getConfiguration('cmdStop')));
			if(!is_object($Stop))
				return false;
		}
		$Down=cmd::byId(str_replace('#','',$this->getConfiguration('cmdDown')));
		if(!is_object($Down))
			return false;
		$Up=cmd::byId(str_replace('#','',$this->getConfiguration('cmdUp')));
		if(!is_object($Up))
			return false;
		$HauteurVolet=$this->getCmd(null,'hauteur')->execCmd();
		if($HauteurVolet == $Hauteur)
			return;
		$Decol=false;
		if($Hauteur == 0 || $HauteurVolet == 0)
			$Decol=true;
		cache::set('voletProp::Move::'.$this->getId(),true, 0);
		cache::set('voletProp::ChangeStateStart::'.$this->getId(),microtime(true), 0);
		if($HauteurVolet > $Hauteur){
			$Delta=$HauteurVolet-$Hauteur;
			$temps=$this->TpsAction($Delta,$Decol);
			cache::set('voletProp::ChangeState::'.$this->getId(),false, 0);
			$Down->execute(null);
			if(!isset($Stop))
				$Stop=$Down;
			log::add('voletProp','debug',$this->getHumanName().' Nous allons descendre le volet de '.$Delta.'%');
		}else{
			$Delta=$Hauteur-$HauteurVolet;
			$temps=$this->TpsAction($Delta,$Decol);
			cache::set('voletProp::ChangeState::'.$this->getId(),true, 0);
			$Up->execute(null);
			if(!isset($Stop))
				$Stop=$Up;
			log::add('voletProp','debug',$this->getHumanName().' Nous allons monter le volet de '.$Delta.'%');
		}
		usleep($temps);
		$Stop->execute(null);
		if($this->getConfiguration('UpStateCmd') == '' && $this->getConfiguration('DownStateCmd') == ''){		
			cache::set('voletProp::ChangeStateStop::'.$this->getId(),microtime(true), 0);
			$this->UpdateHauteur();
		}
		cache::set('voletProp::Move::'.$this->getId(),false, 0);
	}
    	public function TpsAction($Hauteur, $Decol) {
		$TpsGlobal=$this->getConfiguration('Ttotal');
		$TpsDecol=$this->getConfiguration('Tdecol');
		$TpsDebattement=$TpsGlobal- $TpsDecol;
		if(!$Decol){
		$tps=round(($TpsDebattement*$Hauteur/100)*1000000);	
		}else{
		$tps=round(($TpsDebattement*$Hauteur/100+$TpsDecol)*1000000);	
		}
		if($tps <= $this->getConfiguration('delaisMini')*1000000) 
			$tps = $this->getConfiguration('delaisMini')*1000000;
		log::add('voletProp','debug',$this->getHumanName().' Temps d\'action '.$tps.'µs');
		return $tps;
	}
	public function StopListener() {
		$listener = listener::byClassAndFunction('voletProp', 'pull', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'Up', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'Down', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'Stop', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'End', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
	}
	public function StartListener() {
		if($this->getIsEnable()){
			$listener = listener::byClassAndFunction('voletProp', 'Up', array('Volets_id' => $this->getId()));
			$UpStateCmd=$this->getConfiguration('UpStateCmd');
			if ($UpStateCmd != ''){
				if (!is_object($listener))
				    $listener = new listener();
				$listener->setClass('voletProp');
				$listener->setFunction('Up');
				$listener->setOption(array('Volets_id' => $this->getId()));
				$listener->emptyEvent();	
				$listener->addEvent($UpStateCmd);
				$listener->save();			
			}
			$listener = listener::byClassAndFunction('voletProp', 'Down', array('Volets_id' => $this->getId()));
			$DownStateCmd=$this->getConfiguration('DownStateCmd');
			if ($DownStateCmd != ''){
				if (!is_object($listener))
				    $listener = new listener();
				$listener->setClass('voletProp');
				$listener->setFunction('Down');
				$listener->setOption(array('Volets_id' => $this->getId()));
				$listener->emptyEvent();	
					$listener->addEvent($DownStateCmd);
				$listener->save();			
			}
			$listener = listener::byClassAndFunction('voletProp', 'Stop', array('Volets_id' => $this->getId()));
			$StopStateCmd=$this->getConfiguration('StopStateCmd');
			if ($StopStateCmd != ''){
				if (!is_object($listener))
				    $listener = new listener();
				$listener->setClass('voletProp');
				$listener->setFunction('Stop');
				$listener->setOption(array('Volets_id' => $this->getId()));
				$listener->emptyEvent();	
				$listener->addEvent($StopStateCmd);
				$listener->save();				
			}
			$listener = listener::byClassAndFunction('voletProp', 'End', array('Volets_id' => $this->getId()));
			if ($this->getConfiguration('cmdEnd') != ''){
				if (!is_object($listener))
				    $listener = new listener();
				$listener->setClass('voletProp');
				$listener->setFunction('End');
				$listener->setOption(array('Volets_id' => $this->getId()));
				$listener->emptyEvent();	
					$listener->addEvent($this->getConfiguration('cmdEnd'));
				$listener->save();
			}
		}
	}
	public function AddCommande($Name,$_logicalId,$Type="info", $SubType='binary',$visible,$Value=null,$Template=null,$icon=null,$generic_type=null) {
		$Commande = $this->getCmd(null,$_logicalId);
		if (!is_object($Commande))
		{
			$Commande = new voletPropCmd();
			$Commande->setId(null);
			$Commande->setName($Name);
			$Commande->setIsVisible($visible);
			$Commande->setLogicalId($_logicalId);
			$Commande->setEqLogic_id($this->getId());
			$Commande->setType($Type);
			$Commande->setSubType($SubType);
		}
		if($Value != null)
			$Commande->setValue($Value);
		if($Template != null){
			$Commande->setTemplate('dashboard',$Template );
			$Commande->setTemplate('mobile', $Template);
		}
		if($icon != null)
			$Commande->setDisplay('icon', $icon);
		if($generic_type != null)
			$Commande->setDisplay('generic_type', $generic_type);
		$Commande->save();
		return $Commande;
	}
	public function postSave() {
		$this->StopListener();
		$hauteur=$this->AddCommande("Hauteur","hauteur","info",'numeric',0,null,null,null,'FLAP_STATE');
		$this->AddCommande("Position","position","action",'slider',1,$hauteur->getId(),'Volet',null,'FLAP_SLIDER');
		$this->AddCommande("Up","up","action", 'other',1,null,null,'<i class="fa fa-arrow-up"></i>','FLAP_UP');
		$this->AddCommande("Down","down","action", 'other',1,null,null,'<i class="fa fa-arrow-down"></i>','FLAP_DOWN');
		$this->AddCommande("Stop","stop","action", 'other',1,null,null,'<i class="fa fa-stop"></i>','FLAP_STOP');
		$this->StartListener();
	}	
	
	public function preRemove() {
		$listener = listener::byClassAndFunction('voletProp', 'Up', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'Down', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'Stop', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'End', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
	}
}
class voletPropCmd extends cmd {
    public function execute($_options = null) {
		switch($this->getLogicalId()){
			case "up":
				$cmd=cmd::byId(str_replace('#','',$this->getEqLogic()->getConfiguration('cmdUp')));
				if(!is_object($cmd))
					return;
				$cmd->execute(null);
				cache::set('voletProp::ChangeStateStart::'.$this->getEqLogic()->getId(),microtime(true), 0);
				cache::set('voletProp::Move::'.$this->getEqLogic()->getId(),true, 0);
				cache::set('voletProp::ChangeState::'.$this->getEqLogic()->getId(),true, 0);
			break;
			case "down":
				$cmd=cmd::byId(str_replace('#','',$this->getEqLogic()->getConfiguration('cmdDown')));
				if(!is_object($cmd))
					return;
				$cmd->execute(null);
				cache::set('voletProp::ChangeStateStart::'.$this->getEqLogic()->getId(),microtime(true), 0);
				cache::set('voletProp::Move::'.$this->getEqLogic()->getId(),true, 0);
				cache::set('voletProp::ChangeState::'.$this->getEqLogic()->getId(),false, 0);
			break;
			case "stop":
				if($this->getEqLogic()->getConfiguration('cmdStop') != ''){
					$cmd=cmd::byId(str_replace('#','',$this->getEqLogic()->getConfiguration('cmdStop')));
					if(is_object($cmd))
						$cmd->execute(null);
				}else{
					if(cache::byKey('voletProp::ChangeState::'.$this->getEqLogic()->getId())->getValue(false))
						$cmd=cmd::byId(str_replace('#','',$this->getEqLogic()->getConfiguration('cmdUp')));
					else
						$cmd=cmd::byId(str_replace('#','',$this->getEqLogic()->getConfiguration('cmdDown')));
					if(is_object($cmd))
						$cmd->execute(null);
				}				
				if($this->getEqLogic()->getConfiguration('UpStateCmd') == '' && $this->getEqLogic()->getConfiguration('DownStateCmd') == ''){		
					if(cache::byKey('voletProp::Move::'.$this->getEqLogic()->getId())->getValue(false)){
						cache::set('voletProp::ChangeStateStop::'.$this->getEqLogic()->getId(),microtime(true), 0);
						$this->getEqLogic()->UpdateHauteur();
					}
				}
				cache::set('voletProp::Move::'.$this->getEqLogic()->getId(),false, 0);
			break;
			case "position":
				$this->getEqLogic()->execPropVolet($_options['slider']);
			break;
		}
	}
}
?>
Thomas

Helethom
Timide
Messages : 15
Inscription : 06 mars 2018, 22:37
Contact :

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par Helethom » 04 nov. 2018, 16:50

Et voici une nouvelle proposition de modification du script pour résoudre le problème évoqué par tsim79, à savoir ne pas faire de stop si on a donné un ordre à o% ou à 100%. Ca marche chez moi.

Code : Tout sélectionner

<?php
require_once dirname(__FILE__) . '/../../../../core/php/core.inc.php';
class voletProp extends eqLogic {
	public static function cron() {
		foreach(eqLogic::byType('voletProp') as $Volet){ 
			if(cache::byKey('voletProp::Move::'.$Volet->getId())->getValue(false)){
				$ChangeStateStart = cache::byKey('voletProp::ChangeStateStart::'.$Volet->getId())->getValue(microtime(true)+$Volet->getConfiguration('Ttotal'));
				if(time()-$ChangeStateStart >=$Volet->getConfiguration('Ttotal')){
					$cmd=cmd::byId(str_replace('#','',$Volet->getConfiguration('cmdStop')));
					if(is_object($cmd))
						$cmd->execute(null);
					cache::set('voletProp::ChangeStateStop::'.$Volet->getId(),microtime(true), 0);
                  	cache::set('voletProp::Move::'.$Volet->getId(),false, 0);
					$Volet->UpdateHauteur();
				}
			}
		}
	}
	public static function deamon_info() {
		$return = array();
		$return['log'] = 'voletProp';
		$return['launchable'] = 'ok';
		$return['state'] = 'nok';
		foreach(eqLogic::byType('voletProp') as $Volet){
			if($Volet->getIsEnable() && $Volet->getConfiguration('UpStateCmd') != '' && $Volet->getConfiguration('DownStateCmd') != ''&& $Volet->getConfiguration('StopStateCmd') != '' && $Volet->getConfiguration('cmdEnd') != ''){
				$listener = listener::byClassAndFunction('voletProp', 'pull', array('Volets_id' => $Volet->getId()));
				if (!is_object($listener))
					return $return;
			}
		}
		$return['state'] = 'ok';
		return $return;
	}
	public static function deamon_start($_debug = false) {
		log::remove('voletProp');
		self::deamon_stop();
		$deamon_info = self::deamon_info();
		if ($deamon_info['launchable'] != 'ok') 
			return;
		if ($deamon_info['state'] == 'ok') 
			return;
		foreach(eqLogic::byType('voletProp') as $Volet){
			$Volet->StartListener();
		}
	}
	public static function deamon_stop() {	
		foreach(eqLogic::byType('voletProp') as $Volet){
			$Volet->StopListener();
		}
	}
	public static function Up($_option) {
		log::add('voletProp','debug','Detection sur le listener Up : '.json_encode($_option));
		$Volet = eqLogic::byId($_option['Volets_id']);
		$detectedCmd = cmd::byId($_option['event_id']);
		if (is_object($detectedCmd) && is_object($Volet) && $Volet->getIsEnable()) {
			log::add('voletProp','info',$Volet->getHumanName().$detectedCmd->getHumanName());
			if($this->getConfiguration('cmdStop') == '' && cache::byKey('voletProp::Move::'.$Volet->getId())->getValue(false) && cache::byKey('voletProp::ChangeState::'.$Volet->getId())->getValue(false)){
				cache::set('voletProp::ChangeStateStop::'.$Volet->getId(),strtotime($detectedCmd->getCollectDate(microtime(true))), 0);
				$Volet->UpdateHauteur();
				cache::set('voletProp::Move::'.$Volet->getId(),false, 0);
			}else{
				$isUp=$Volet->getConfiguration('UpStateCmd').$Volet->getConfiguration('UpStateOperande').$Volet->getConfiguration('UpStateValue');
				if($Volet->EvaluateCondition($isUp)){
					cache::set('voletProp::ChangeState::'.$Volet->getId(),true, 0);
					cache::set('voletProp::Move::'.$Volet->getId(),true, 0);
					cache::set('voletProp::ChangeStateStart::'.$Volet->getId(),microtime(true), 0);
				}
			}
		}
	}
	public static function Down($_option) {
		log::add('voletProp','debug','Detection sur le listener Down : '.json_encode($_option));
		$Volet = eqLogic::byId($_option['Volets_id']);
		$detectedCmd = cmd::byId($_option['event_id']);
		if (is_object($detectedCmd) && is_object($Volet) && $Volet->getIsEnable()) {
			log::add('voletProp','info',$Volet->getHumanName().$detectedCmd->getHumanName());
			if($this->getConfiguration('cmdStop') == '' && cache::byKey('voletProp::Move::'.$Volet->getId())->getValue(false) && !cache::byKey('voletProp::ChangeState::'.$Volet->getId())->getValue(false)){
				cache::set('voletProp::ChangeStateStop::'.$Volet->getId(),strtotime($detectedCmd->getCollectDate(microtime(true))), 0);
				$Volet->UpdateHauteur();
				cache::set('voletProp::Move::'.$Volet->getId(),false, 0);
			}else{
				$isDown=$Volet->getConfiguration('DownStateCmd').$Volet->getConfiguration('DownStateOperande').$Volet->getConfiguration('DownStateValue');
				if($Volet->EvaluateCondition($isDown)){
					cache::set('voletProp::ChangeState::'.$Volet->getId(),false, 0);
					cache::set('voletProp::Move::'.$Volet->getId(),true, 0);
					cache::set('voletProp::ChangeStateStart::'.$Volet->getId(),microtime(true), 0);
				}
			}
		}
	}
	public static function Stop($_option) {
		log::add('voletProp','debug','Detection sur le listener Stop : '.json_encode($_option));
		$Volet = eqLogic::byId($_option['Volets_id']);
		$detectedCmd = cmd::byId($_option['event_id']);
		if (is_object($detectedCmd) && is_object($Volet) && $Volet->getIsEnable()) {
			log::add('voletProp','info',$Volet->getHumanName().$detectedCmd->getHumanName());
			$isStop=$Volet->getConfiguration('StopStateCmd').$Volet->getConfiguration('StopStateOperande').$Volet->getConfiguration('StopStateValue');
			if($Volet->EvaluateCondition($isStop)){
				$Move=cache::byKey('voletProp::Move::'.$Volet->getId());
				cache::set('voletProp::ChangeStateStop::'.$Volet->getId(),strtotime($detectedCmd->getCollectDate(microtime(true))), 0);
				if(is_object($Move) && $Move->getValue(false)){
					$Volet->UpdateHauteur();
					cache::set('voletProp::Move::'.$Volet->getId(),false, 0);
				}
			}
		}
	}
	public static function End($_option) {
		log::add('voletProp','debug','Detection sur le listener End : '.json_encode($_option));
		$Volet = eqLogic::byId($_option['Volets_id']);
		$detectedCmd = cmd::byId($_option['event_id']);
		if (is_object($detectedCmd) && is_object($Volet) && $Volet->getIsEnable()) {
			log::add('voletProp','info',$Volet->getHumanName().$detectedCmd->getHumanName());
			if($_option['value'])
				$Volet->checkAndUpdateCmd('hauteur',0);
		}
	}
	public function boolToText($value){
		if (is_bool($value)) {
			if ($value) 
				return __('Vrai', __FILE__);
			else 
				return __('Faux', __FILE__);
		} else 
			return $value;
	}
	public function EvaluateCondition($Condition){
		$_scenario = null;
		$expression = scenarioExpression::setTags($Condition, $_scenario, true);
		$message = __('Evaluation de la condition : ['.jeedom::toHumanReadable($Condition).'][', __FILE__) . trim($expression) . '] = ';
		$result = evaluate($expression);
		$message .=$this->boolToText($result);
		log::add('voletProp','info',$this->getHumanName().$message);
		if(!$result)
			return false;		
		return true;
	}
public function UpdateHauteur() {
		$ChangeState = cache::byKey('voletProp::ChangeState::'.$this->getId())->getValue(false);
		$ChangeStateStart = cache::byKey('voletProp::ChangeStateStart::'.$this->getId())->getValue(microtime(true));
		$ChangeStateStop = cache::byKey('voletProp::ChangeStateStop::'.$this->getId())->getValue(microtime(true));		
		$Tps=$ChangeStateStop-$ChangeStateStart;
		$TpsGlobal=$this->getConfiguration('Ttotal');
        $TpsDecol=$this->getConfiguration('Tdecol');
		$TpsDebattement=$TpsGlobal- $TpsDecol;
		
		$HauteurActuel=$this->getCmd(null,'hauteur')->execCmd();
		if($HauteurActuel != 0){
          $Hauteur=$Tps*100/$TpsDebattement;
        }else{
          $Hauteur=($Tps-$TpsDecol)*100/$TpsDebattement;
          
        }
		
		if($ChangeState)
			$Hauteur=round($HauteurActuel+$Hauteur);
		else
			$Hauteur=round($HauteurActuel-$Hauteur);
		if($Hauteur<0)
			$Hauteur=0;
		if($Hauteur>100)
			$Hauteur=100;
		log::add('voletProp','debug',$this->getHumanName().' Le volet est a '.$Hauteur.'%');
		$this->checkAndUpdateCmd('hauteur',$Hauteur);
	}
    	public function CheckSynchro($Hauteur) {
		if($this->getConfiguration('Synchronisation') == "")
			return true;
		if($this->getConfiguration('cmdStop') != ''){
			$Stop=cmd::byId(str_replace('#','',$this->getConfiguration('cmdStop')));
			if(!is_object($Stop))
				return false;
		}
		$Down=cmd::byId(str_replace('#','',$this->getConfiguration('cmdDown')));
		if(!is_object($Down))
			return false;
		$Up=cmd::byId(str_replace('#','',$this->getConfiguration('cmdUp')));
		if(!is_object($Up))
			return false;
		foreach($this->getConfiguration('Synchronisation') as $Synchronisation){
			if($Synchronisation == '100' && $Hauteur == 100){
				log::add('voletProp','info',$this->getHumanName().'[Synchronisation] Montée complete');
				$Up->execute(null);
				if(!isset($Stop))
					$Stop=$Down;
				sleep($this->getConfiguration('Ttotal'));
				$Stop->execute(null);		
				if($this->getConfiguration('UpStateCmd') == '' && $this->getConfiguration('DownStateCmd') == '')
					$this->checkAndUpdateCmd('hauteur',100);
				return false;
			}
			if($Synchronisation == '0' && $Hauteur == 0){
				log::add('voletProp','info',$this->getHumanName().'[Synchronisation] Descente complete');
				$Down->execute(null);
				if(!isset($Stop))
					$Stop=$Up;
				sleep($this->getConfiguration('Ttotal'));
				$Stop->execute(null);		
				if($this->getConfiguration('UpStateCmd') == '' && $this->getConfiguration('DownStateCmd') == '')
					$this->checkAndUpdateCmd('hauteur',0);
				return false;
			}
			if($Synchronisation == 'all'){
				log::add('voletProp','info',$this->getHumanName().'[Synchronisation] Montée complete');
				$Up->execute(null);
				if(!isset($Stop))
					$Stop=$Down;
				sleep($this->getConfiguration('Ttotal'));
				$Stop->execute(null);		
				if($this->getConfiguration('UpStateCmd') == '' && $this->getConfiguration('DownStateCmd') == '')
					$this->checkAndUpdateCmd('hauteur',100);
				return true;
			}
		}
		return true;
	}
    	public function execPropVolet($Hauteur) {
		if(!$this->CheckSynchro($Hauteur))
			return false;
		if($this->getConfiguration('cmdStop') != ''){
			$Stop=cmd::byId(str_replace('#','',$this->getConfiguration('cmdStop')));
			if(!is_object($Stop))
				return false;
		}
		$Down=cmd::byId(str_replace('#','',$this->getConfiguration('cmdDown')));
		if(!is_object($Down))
			return false;
		$Up=cmd::byId(str_replace('#','',$this->getConfiguration('cmdUp')));
		if(!is_object($Up))
			return false;
		$HauteurVolet=$this->getCmd(null,'hauteur')->execCmd();
		if($HauteurVolet == $Hauteur AND $Hauteur!=0 AND $Hauteur!=100)
			return;
		$Decol=false;
		if($Hauteur == 0 || $HauteurVolet == 0)
			$Decol=true;
		cache::set('voletProp::Move::'.$this->getId(),true, 0);
		cache::set('voletProp::ChangeStateStart::'.$this->getId(),microtime(true), 0);
		$ChangeStateStart = cache::byKey('voletProp::ChangeStateStart::'.$this->getId())->getValue(microtime(true));
		$ChangeStateStop = cache::byKey('voletProp::ChangeStateStop::'.$this->getId())->getValue(microtime(true));		
		if($HauteurVolet > $Hauteur or $Hauteur==0){
			$Delta=$HauteurVolet-$Hauteur;
			$temps=$this->TpsAction($Delta,$Decol);
			cache::set('voletProp::ChangeState::'.$this->getId(),false, 0);
			$Down->execute(null);
			if(!isset($Stop))
				$Stop=$Down;
			log::add('voletProp','debug',$this->getHumanName().' Nous allons descendre le volet de '.$Delta.'%');
		}else{
			$Delta=$Hauteur-$HauteurVolet;
			$temps=$this->TpsAction($Delta,$Decol);
			cache::set('voletProp::ChangeState::'.$this->getId(),true, 0);
			$Up->execute(null);
			if(!isset($Stop))
				$Stop=$Up;
			log::add('voletProp','debug',$this->getHumanName().' Nous allons monter le volet de '.$Delta.'%');
		}
		usleep($temps);
          if($ChangeStateStart >= cache::byKey('voletProp::ChangeStateStart::'.$this->getId())->getValue(microtime(true)) AND $ChangeStateStop >= cache::byKey('voletProp::ChangeStateStop::'.$this->getId())->getValue(microtime(true))	){

            if($Hauteur>1 AND $Hauteur<99) {$Stop->execute(null);}
		if($this->getConfiguration('UpStateCmd') == '' && $this->getConfiguration('DownStateCmd') == ''){		
			cache::set('voletProp::ChangeStateStop::'.$this->getId(),microtime(true), 0);
			$this->UpdateHauteur();
		}
		cache::set('voletProp::Move::'.$this->getId(),false, 0);
          }
	}
    	public function TpsAction($Hauteur, $Decol) {
		$TpsGlobal=$this->getConfiguration('Ttotal');
		$TpsDecol=$this->getConfiguration('Tdecol');
		$TpsDebattement=$TpsGlobal- $TpsDecol;
		if(!$Decol){
		$tps=round(($TpsDebattement*$Hauteur/100)*1000000);	
		}else{
		$tps=round(($TpsDebattement*$Hauteur/100+$TpsDecol)*1000000);	
		}
		if($tps <= $this->getConfiguration('delaisMini')*1000000) 
			$tps = $this->getConfiguration('delaisMini')*1000000;
		log::add('voletProp','debug',$this->getHumanName().' Temps d\'action '.$tps.'µs');
		return $tps;
	}
	public function StopListener() {
		$listener = listener::byClassAndFunction('voletProp', 'pull', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'Up', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'Down', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'Stop', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'End', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
	}
	public function StartListener() {
		if($this->getIsEnable()){
			$listener = listener::byClassAndFunction('voletProp', 'Up', array('Volets_id' => $this->getId()));
			$UpStateCmd=$this->getConfiguration('UpStateCmd');
			if ($UpStateCmd != ''){
				if (!is_object($listener))
				    $listener = new listener();
				$listener->setClass('voletProp');
				$listener->setFunction('Up');
				$listener->setOption(array('Volets_id' => $this->getId()));
				$listener->emptyEvent();	
				$listener->addEvent($UpStateCmd);
				$listener->save();			
			}
			$listener = listener::byClassAndFunction('voletProp', 'Down', array('Volets_id' => $this->getId()));
			$DownStateCmd=$this->getConfiguration('DownStateCmd');
			if ($DownStateCmd != ''){
				if (!is_object($listener))
				    $listener = new listener();
				$listener->setClass('voletProp');
				$listener->setFunction('Down');
				$listener->setOption(array('Volets_id' => $this->getId()));
				$listener->emptyEvent();	
					$listener->addEvent($DownStateCmd);
				$listener->save();			
			}
			$listener = listener::byClassAndFunction('voletProp', 'Stop', array('Volets_id' => $this->getId()));
			$StopStateCmd=$this->getConfiguration('StopStateCmd');
			if ($StopStateCmd != ''){
				if (!is_object($listener))
				    $listener = new listener();
				$listener->setClass('voletProp');
				$listener->setFunction('Stop');
				$listener->setOption(array('Volets_id' => $this->getId()));
				$listener->emptyEvent();	
				$listener->addEvent($StopStateCmd);
				$listener->save();				
			}
			$listener = listener::byClassAndFunction('voletProp', 'End', array('Volets_id' => $this->getId()));
			if ($this->getConfiguration('cmdEnd') != ''){
				if (!is_object($listener))
				    $listener = new listener();
				$listener->setClass('voletProp');
				$listener->setFunction('End');
				$listener->setOption(array('Volets_id' => $this->getId()));
				$listener->emptyEvent();	
					$listener->addEvent($this->getConfiguration('cmdEnd'));
				$listener->save();
			}
		}
	}
	public function AddCommande($Name,$_logicalId,$Type="info", $SubType='binary',$visible,$Value=null,$Template=null,$icon=null,$generic_type=null) {
		$Commande = $this->getCmd(null,$_logicalId);
		if (!is_object($Commande))
		{
			$Commande = new voletPropCmd();
			$Commande->setId(null);
			$Commande->setName($Name);
			$Commande->setIsVisible($visible);
			$Commande->setLogicalId($_logicalId);
			$Commande->setEqLogic_id($this->getId());
			$Commande->setType($Type);
			$Commande->setSubType($SubType);
		}
		if($Value != null)
			$Commande->setValue($Value);
		if($Template != null){
			$Commande->setTemplate('dashboard',$Template );
			$Commande->setTemplate('mobile', $Template);
		}
		if($icon != null)
			$Commande->setDisplay('icon', $icon);
		if($generic_type != null)
			$Commande->setDisplay('generic_type', $generic_type);
		$Commande->save();
		return $Commande;
	}
	public function postSave() {
		$this->StopListener();
		$hauteur=$this->AddCommande("Hauteur","hauteur","info",'numeric',0,null,null,null,'FLAP_STATE');
		$this->AddCommande("Position","position","action",'slider',1,$hauteur->getId(),'Volet',null,'FLAP_SLIDER');
		$this->AddCommande("Up","up","action", 'other',1,null,null,'<i class="fa fa-arrow-up"></i>','FLAP_UP');
		$this->AddCommande("Down","down","action", 'other',1,null,null,'<i class="fa fa-arrow-down"></i>','FLAP_DOWN');
		$this->AddCommande("Stop","stop","action", 'other',1,null,null,'<i class="fa fa-stop"></i>','FLAP_STOP');
		$this->StartListener();
	}	
	
	public function preRemove() {
		$listener = listener::byClassAndFunction('voletProp', 'Up', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'Down', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'Stop', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'End', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
	}
}
class voletPropCmd extends cmd {
    public function execute($_options = null) {
		switch($this->getLogicalId()){
			case "up":
                cache::set('voletProp::Move::'.$this->getId(),false, 0);
				$this->getEqLogic()->execPropVolet(100);
			break;
			case "down":
            cache::set('voletProp::Move::'.$this->getId(),false, 0);
            $this->getEqLogic()->execPropVolet(0);
			break;
			case "stop":
				if($this->getEqLogic()->getConfiguration('cmdStop') != ''){
					$cmd=cmd::byId(str_replace('#','',$this->getEqLogic()->getConfiguration('cmdStop')));
					if(is_object($cmd))
						$cmd->execute(null);
				}else{
					if(cache::byKey('voletProp::ChangeState::'.$this->getEqLogic()->getId())->getValue(false))
						$cmd=cmd::byId(str_replace('#','',$this->getEqLogic()->getConfiguration('cmdUp')));
					else
						$cmd=cmd::byId(str_replace('#','',$this->getEqLogic()->getConfiguration('cmdDown')));
					if(is_object($cmd))
						$cmd->execute(null);
				}				
				if($this->getEqLogic()->getConfiguration('UpStateCmd') == '' && $this->getEqLogic()->getConfiguration('DownStateCmd') == ''){		
					if(cache::byKey('voletProp::Move::'.$this->getEqLogic()->getId())->getValue(false)){
						cache::set('voletProp::ChangeStateStop::'.$this->getEqLogic()->getId(),microtime(true), 0);
						$this->getEqLogic()->UpdateHauteur();
					}
				}
				cache::set('voletProp::Move::'.$this->getEqLogic()->getId(),false, 0);
			break;
			case "position":
				$this->getEqLogic()->execPropVolet($_options['slider']);
			break;
		}
	}
}
?>
Dernière édition par Helethom le 05 nov. 2018, 16:54, édité 1 fois.
Thomas

variamus
Timide
Messages : 29
Inscription : 13 mars 2018, 22:38

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par variamus » 05 nov. 2018, 15:26

Bonjour,
Je viens de découvrir ce plugin qui est top!
Par contre, petits détails que j'aimerai appliquer à ma configuration mais je n'y parviens pas:
- Le bouton "down" apparaît au-dessus du volet --> Est-il possible de le positionner en-dessous du volet comme c'est le cas pour les boutons "up" et "stop" ?
- Le % apparaît sur la gauche vraiment collé au volet, est-ce possible de le mettre sur le volet directement ou au-dessus pour plus de visibilité ?
(Pièce jointe pour la capture)

Aussi, est-il possible d'ajouter une action si le volet est à plus de 50% et moins de 50% ? (Sur mon design, j'affiche une autre image lorsque le volet est fermé et j'aimerai faire de même si il est fermé à plus de 50% par exemple)
Pièces jointes
propvol.jpg
propvol.jpg (5.48 Kio) Consulté 53 fois
NUC7I5BNH - ESXi 6.7
VM Debian 9

tsim79
Timide
Messages : 486
Inscription : 23 avr. 2015, 11:54

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par tsim79 » 05 nov. 2018, 19:21

Helethom a écrit :
03 nov. 2018, 15:52
tsim79 a écrit :
03 nov. 2018, 11:31
EDIT: J'ai trouvé la solution. Il suffit de supprimer la position sauvegardée "MY"du volet en suivant la procédure suivante: https://service.somfy.com/downloads/fr_ ... _my_vr.pdf
Bonjour cette solution n'est pas si intéressante.
Mes enfants, ma femme utilisent la position favorite des volets depuis la télécommande, tout les occupants de la maison ne peuvent pas systématiquement passer par Jeedom pour régler l'ouverture proportionnel d'un volet!

Dans une chambre lorsque l'on veut ouvrir un volet à moitié, c'est possible grâce à cette fonction de position favorite depuis la télécommande physique!
Dans mon séjour, lorsque je veux une ouverture avec interstices la position favorite est là pour cela!

🤔?
Bonjour,
De mon côté j'évite d'utiliser les télécommandes Somfy car je n'ai pas de retour d'état de leur utilisation avec RFXcom... Tu arrives à avoir ces infos?

Maintenant que j'arrive à utiliser le plugin j'ai de nombreux soucis:
-Le temps de décollement n'est jamais pris en compte dans le temps d'action. Par exemple, Lorsque le volet est fermé (0%), il fait temps_total/2 pour une commande à 50% alors qu'il devrait faire (temps_total - temps_décollement)/2 + temps_décollement. Est ce que c'est à cause de l'absence de capteurs de fin de course?
-Les boutons Up, Down et Stop fonctionnent mais ne mettent pas à jour la hauteur du volet.

Avez-vous rencontré des problèmes similaires?
Merci d'avance
Merci pour la remarque ou conseil, mais je ne peux pas contraindre ma famille à utiliser une tablette ou des smartphones, avec des enfants 😕.

L'ouverture proportionnelle pour moi permettrait définir le taux de luminosité que je souhaite dans la pièce de vie, genre le matin, lorsque la luminosité est trop forte vers les 11h00 pour profité ensuite du couché de soleil. Sachant que je fais déjà l'ouverture et la fermeture en fonction du lever et coucher de soleil!

tsim79
Timide
Messages : 486
Inscription : 23 avr. 2015, 11:54

Re: [Plugin Tiers][Sujet Principal] Volets Proportionnel

Message par tsim79 » 05 nov. 2018, 19:23

Helethom a écrit :
04 nov. 2018, 16:50
Et voici une nouvelle proposition de modification du script pour résoudre le problème évoqué par tsim79, à savoir ne pas faire de stop si on a donné un ordre à o% ou à 100%. Ca marche chez moi.

Code : Tout sélectionner

<?php
require_once dirname(__FILE__) . '/../../../../core/php/core.inc.php';
class voletProp extends eqLogic {
	public static function cron() {
		foreach(eqLogic::byType('voletProp') as $Volet){ 
			if(cache::byKey('voletProp::Move::'.$Volet->getId())->getValue(false)){
				$ChangeStateStart = cache::byKey('voletProp::ChangeStateStart::'.$Volet->getId())->getValue(microtime(true)+$Volet->getConfiguration('Ttotal'));
				if(time()-$ChangeStateStart >=$Volet->getConfiguration('Ttotal')){
					$cmd=cmd::byId(str_replace('#','',$Volet->getConfiguration('cmdStop')));
					if(is_object($cmd))
						$cmd->execute(null);
					cache::set('voletProp::ChangeStateStop::'.$Volet->getId(),microtime(true), 0);
                  	cache::set('voletProp::Move::'.$Volet->getId(),false, 0);
					$Volet->UpdateHauteur();
				}
			}
		}
	}
	public static function deamon_info() {
		$return = array();
		$return['log'] = 'voletProp';
		$return['launchable'] = 'ok';
		$return['state'] = 'nok';
		foreach(eqLogic::byType('voletProp') as $Volet){
			if($Volet->getIsEnable() && $Volet->getConfiguration('UpStateCmd') != '' && $Volet->getConfiguration('DownStateCmd') != ''&& $Volet->getConfiguration('StopStateCmd') != '' && $Volet->getConfiguration('cmdEnd') != ''){
				$listener = listener::byClassAndFunction('voletProp', 'pull', array('Volets_id' => $Volet->getId()));
				if (!is_object($listener))
					return $return;
			}
		}
		$return['state'] = 'ok';
		return $return;
	}
	public static function deamon_start($_debug = false) {
		log::remove('voletProp');
		self::deamon_stop();
		$deamon_info = self::deamon_info();
		if ($deamon_info['launchable'] != 'ok') 
			return;
		if ($deamon_info['state'] == 'ok') 
			return;
		foreach(eqLogic::byType('voletProp') as $Volet){
			$Volet->StartListener();
		}
	}
	public static function deamon_stop() {	
		foreach(eqLogic::byType('voletProp') as $Volet){
			$Volet->StopListener();
		}
	}
	public static function Up($_option) {
		log::add('voletProp','debug','Detection sur le listener Up : '.json_encode($_option));
		$Volet = eqLogic::byId($_option['Volets_id']);
		$detectedCmd = cmd::byId($_option['event_id']);
		if (is_object($detectedCmd) && is_object($Volet) && $Volet->getIsEnable()) {
			log::add('voletProp','info',$Volet->getHumanName().$detectedCmd->getHumanName());
			if($this->getConfiguration('cmdStop') == '' && cache::byKey('voletProp::Move::'.$Volet->getId())->getValue(false) && cache::byKey('voletProp::ChangeState::'.$Volet->getId())->getValue(false)){
				cache::set('voletProp::ChangeStateStop::'.$Volet->getId(),strtotime($detectedCmd->getCollectDate(microtime(true))), 0);
				$Volet->UpdateHauteur();
				cache::set('voletProp::Move::'.$Volet->getId(),false, 0);
			}else{
				$isUp=$Volet->getConfiguration('UpStateCmd').$Volet->getConfiguration('UpStateOperande').$Volet->getConfiguration('UpStateValue');
				if($Volet->EvaluateCondition($isUp)){
					cache::set('voletProp::ChangeState::'.$Volet->getId(),true, 0);
					cache::set('voletProp::Move::'.$Volet->getId(),true, 0);
					cache::set('voletProp::ChangeStateStart::'.$Volet->getId(),microtime(true), 0);
				}
			}
		}
	}
	public static function Down($_option) {
		log::add('voletProp','debug','Detection sur le listener Down : '.json_encode($_option));
		$Volet = eqLogic::byId($_option['Volets_id']);
		$detectedCmd = cmd::byId($_option['event_id']);
		if (is_object($detectedCmd) && is_object($Volet) && $Volet->getIsEnable()) {
			log::add('voletProp','info',$Volet->getHumanName().$detectedCmd->getHumanName());
			if($this->getConfiguration('cmdStop') == '' && cache::byKey('voletProp::Move::'.$Volet->getId())->getValue(false) && !cache::byKey('voletProp::ChangeState::'.$Volet->getId())->getValue(false)){
				cache::set('voletProp::ChangeStateStop::'.$Volet->getId(),strtotime($detectedCmd->getCollectDate(microtime(true))), 0);
				$Volet->UpdateHauteur();
				cache::set('voletProp::Move::'.$Volet->getId(),false, 0);
			}else{
				$isDown=$Volet->getConfiguration('DownStateCmd').$Volet->getConfiguration('DownStateOperande').$Volet->getConfiguration('DownStateValue');
				if($Volet->EvaluateCondition($isDown)){
					cache::set('voletProp::ChangeState::'.$Volet->getId(),false, 0);
					cache::set('voletProp::Move::'.$Volet->getId(),true, 0);
					cache::set('voletProp::ChangeStateStart::'.$Volet->getId(),microtime(true), 0);
				}
			}
		}
	}
	public static function Stop($_option) {
		log::add('voletProp','debug','Detection sur le listener Stop : '.json_encode($_option));
		$Volet = eqLogic::byId($_option['Volets_id']);
		$detectedCmd = cmd::byId($_option['event_id']);
		if (is_object($detectedCmd) && is_object($Volet) && $Volet->getIsEnable()) {
			log::add('voletProp','info',$Volet->getHumanName().$detectedCmd->getHumanName());
			$isStop=$Volet->getConfiguration('StopStateCmd').$Volet->getConfiguration('StopStateOperande').$Volet->getConfiguration('StopStateValue');
			if($Volet->EvaluateCondition($isStop)){
				$Move=cache::byKey('voletProp::Move::'.$Volet->getId());
				cache::set('voletProp::ChangeStateStop::'.$Volet->getId(),strtotime($detectedCmd->getCollectDate(microtime(true))), 0);
				if(is_object($Move) && $Move->getValue(false)){
					$Volet->UpdateHauteur();
					cache::set('voletProp::Move::'.$Volet->getId(),false, 0);
				}
			}
		}
	}
	public static function End($_option) {
		log::add('voletProp','debug','Detection sur le listener End : '.json_encode($_option));
		$Volet = eqLogic::byId($_option['Volets_id']);
		$detectedCmd = cmd::byId($_option['event_id']);
		if (is_object($detectedCmd) && is_object($Volet) && $Volet->getIsEnable()) {
			log::add('voletProp','info',$Volet->getHumanName().$detectedCmd->getHumanName());
			if($_option['value'])
				$Volet->checkAndUpdateCmd('hauteur',0);
		}
	}
	public function boolToText($value){
		if (is_bool($value)) {
			if ($value) 
				return __('Vrai', __FILE__);
			else 
				return __('Faux', __FILE__);
		} else 
			return $value;
	}
	public function EvaluateCondition($Condition){
		$_scenario = null;
		$expression = scenarioExpression::setTags($Condition, $_scenario, true);
		$message = __('Evaluation de la condition : ['.jeedom::toHumanReadable($Condition).'][', __FILE__) . trim($expression) . '] = ';
		$result = evaluate($expression);
		$message .=$this->boolToText($result);
		log::add('voletProp','info',$this->getHumanName().$message);
		if(!$result)
			return false;		
		return true;
	}
public function UpdateHauteur() {
		$ChangeState = cache::byKey('voletProp::ChangeState::'.$this->getId())->getValue(false);
		$ChangeStateStart = cache::byKey('voletProp::ChangeStateStart::'.$this->getId())->getValue(microtime(true));
		$ChangeStateStop = cache::byKey('voletProp::ChangeStateStop::'.$this->getId())->getValue(microtime(true));		
		$Tps=$ChangeStateStop-$ChangeStateStart;
		$TpsGlobal=$this->getConfiguration('Ttotal');
        $TpsDecol=$this->getConfiguration('Tdecol');
		$TpsDebattement=$TpsGlobal- $TpsDecol;
		
		$HauteurActuel=$this->getCmd(null,'hauteur')->execCmd();
		if($HauteurActuel != 0){
          $Hauteur=$Tps*100/$TpsDebattement;
        }else{
          $Hauteur=($Tps-$TpsDecol)*100/$TpsDebattement;
          
        }
		
		if($ChangeState)
			$Hauteur=round($HauteurActuel+$Hauteur);
		else
			$Hauteur=round($HauteurActuel-$Hauteur);
		if($Hauteur<0)
			$Hauteur=0;
		if($Hauteur>100)
			$Hauteur=100;
		log::add('voletProp','debug',$this->getHumanName().' Le volet est a '.$Hauteur.'%');
		$this->checkAndUpdateCmd('hauteur',$Hauteur);
	}
    	public function CheckSynchro($Hauteur) {
		if($this->getConfiguration('Synchronisation') == "")
			return true;
		if($this->getConfiguration('cmdStop') != ''){
			$Stop=cmd::byId(str_replace('#','',$this->getConfiguration('cmdStop')));
			if(!is_object($Stop))
				return false;
		}
		$Down=cmd::byId(str_replace('#','',$this->getConfiguration('cmdDown')));
		if(!is_object($Down))
			return false;
		$Up=cmd::byId(str_replace('#','',$this->getConfiguration('cmdUp')));
		if(!is_object($Up))
			return false;
		foreach($this->getConfiguration('Synchronisation') as $Synchronisation){
			if($Synchronisation == '100' && $Hauteur == 100){
				log::add('voletProp','info',$this->getHumanName().'[Synchronisation] Montée complete');
				$Up->execute(null);
				if(!isset($Stop))
					$Stop=$Down;
				sleep($this->getConfiguration('Ttotal'));
				$Stop->execute(null);		
				if($this->getConfiguration('UpStateCmd') == '' && $this->getConfiguration('DownStateCmd') == '')
					$this->checkAndUpdateCmd('hauteur',100);
				return false;
			}
			if($Synchronisation == '0' && $Hauteur == 0){
				log::add('voletProp','info',$this->getHumanName().'[Synchronisation] Descente complete');
				$Down->execute(null);
				if(!isset($Stop))
					$Stop=$Up;
				sleep($this->getConfiguration('Ttotal'));
				$Stop->execute(null);		
				if($this->getConfiguration('UpStateCmd') == '' && $this->getConfiguration('DownStateCmd') == '')
					$this->checkAndUpdateCmd('hauteur',0);
				return false;
			}
			if($Synchronisation == 'all'){
				log::add('voletProp','info',$this->getHumanName().'[Synchronisation] Montée complete');
				$Up->execute(null);
				if(!isset($Stop))
					$Stop=$Down;
				sleep($this->getConfiguration('Ttotal'));
				$Stop->execute(null);		
				if($this->getConfiguration('UpStateCmd') == '' && $this->getConfiguration('DownStateCmd') == '')
					$this->checkAndUpdateCmd('hauteur',100);
				return true;
			}
		}
		return true;
	}
    	public function execPropVolet($Hauteur) {
		if(!$this->CheckSynchro($Hauteur))
			return false;
		if($this->getConfiguration('cmdStop') != ''){
			$Stop=cmd::byId(str_replace('#','',$this->getConfiguration('cmdStop')));
			if(!is_object($Stop))
				return false;
		}
		$Down=cmd::byId(str_replace('#','',$this->getConfiguration('cmdDown')));
		if(!is_object($Down))
			return false;
		$Up=cmd::byId(str_replace('#','',$this->getConfiguration('cmdUp')));
		if(!is_object($Up))
			return false;
		$HauteurVolet=$this->getCmd(null,'hauteur')->execCmd();
		if($HauteurVolet == $Hauteur AND $Hauteur!=0 AND $Hauteur!=100)
			return;
		$Decol=false;
		if($Hauteur == 0 || $HauteurVolet == 0)
			$Decol=true;
		cache::set('voletProp::Move::'.$this->getId(),true, 0);
		cache::set('voletProp::ChangeStateStart::'.$this->getId(),microtime(true), 0);
		$ChangeStateStart = cache::byKey('voletProp::ChangeStateStart::'.$this->getId())->getValue(microtime(true));
		$ChangeStateStop = cache::byKey('voletProp::ChangeStateStop::'.$this->getId())->getValue(microtime(true));		
		if($HauteurVolet > $Hauteur or $Hauteur==0){
			$Delta=$HauteurVolet-$Hauteur;
			$temps=$this->TpsAction($Delta,$Decol);
			cache::set('voletProp::ChangeState::'.$this->getId(),false, 0);
			$Down->execute(null);
			if(!isset($Stop))
				$Stop=$Down;
			log::add('voletProp','debug',$this->getHumanName().' Nous allons descendre le volet de '.$Delta.'%');
		}else{
			$Delta=$Hauteur-$HauteurVolet;
			$temps=$this->TpsAction($Delta,$Decol);
			cache::set('voletProp::ChangeState::'.$this->getId(),true, 0);
			$Up->execute(null);
			if(!isset($Stop))
				$Stop=$Up;
			log::add('voletProp','debug',$this->getHumanName().' Nous allons monter le volet de '.$Delta.'%');
		}
		usleep($temps);
          if($ChangeStateStart >= cache::byKey('voletProp::ChangeStateStart::'.$this->getId())->getValue(microtime(true)) AND $ChangeStateStop >= cache::byKey('voletProp::ChangeStateStop::'.$this->getId())->getValue(microtime(true))	){

            if($Hauteur>1 AND $Hauteur<99) {$Stop->execute(null);}
		if($this->getConfiguration('UpStateCmd') == '' && $this->getConfiguration('DownStateCmd') == ''){		
			cache::set('voletProp::ChangeStateStop::'.$this->getId(),microtime(true), 0);
			$this->UpdateHauteur();
		}
		cache::set('voletProp::Move::'.$this->getId(),false, 0);
          }
	}
    	public function TpsAction($Hauteur, $Decol) {
		$TpsGlobal=$this->getConfiguration('Ttotal');
		$TpsDecol=$this->getConfiguration('Tdecol');
		$TpsDebattement=$TpsGlobal- $TpsDecol;
		if(!$Decol){
		$tps=round(($TpsDebattement*$Hauteur/100)*1000000);	
		}else{
		$tps=round(($TpsDebattement*$Hauteur/100+$TpsDecol)*1000000);	
		}
		if($tps <= $this->getConfiguration('delaisMini')*1000000) 
			$tps = $this->getConfiguration('delaisMini')*1000000;
		log::add('voletProp','debug',$this->getHumanName().' Temps d\'action '.$tps.'µs');
		return $tps;
	}
	public function StopListener() {
		$listener = listener::byClassAndFunction('voletProp', 'pull', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'Up', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'Down', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'Stop', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'End', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
	}
	public function StartListener() {
		if($this->getIsEnable()){
			$listener = listener::byClassAndFunction('voletProp', 'Up', array('Volets_id' => $this->getId()));
			$UpStateCmd=$this->getConfiguration('UpStateCmd');
			if ($UpStateCmd != ''){
				if (!is_object($listener))
				    $listener = new listener();
				$listener->setClass('voletProp');
				$listener->setFunction('Up');
				$listener->setOption(array('Volets_id' => $this->getId()));
				$listener->emptyEvent();	
				$listener->addEvent($UpStateCmd);
				$listener->save();			
			}
			$listener = listener::byClassAndFunction('voletProp', 'Down', array('Volets_id' => $this->getId()));
			$DownStateCmd=$this->getConfiguration('DownStateCmd');
			if ($DownStateCmd != ''){
				if (!is_object($listener))
				    $listener = new listener();
				$listener->setClass('voletProp');
				$listener->setFunction('Down');
				$listener->setOption(array('Volets_id' => $this->getId()));
				$listener->emptyEvent();	
					$listener->addEvent($DownStateCmd);
				$listener->save();			
			}
			$listener = listener::byClassAndFunction('voletProp', 'Stop', array('Volets_id' => $this->getId()));
			$StopStateCmd=$this->getConfiguration('StopStateCmd');
			if ($StopStateCmd != ''){
				if (!is_object($listener))
				    $listener = new listener();
				$listener->setClass('voletProp');
				$listener->setFunction('Stop');
				$listener->setOption(array('Volets_id' => $this->getId()));
				$listener->emptyEvent();	
				$listener->addEvent($StopStateCmd);
				$listener->save();				
			}
			$listener = listener::byClassAndFunction('voletProp', 'End', array('Volets_id' => $this->getId()));
			if ($this->getConfiguration('cmdEnd') != ''){
				if (!is_object($listener))
				    $listener = new listener();
				$listener->setClass('voletProp');
				$listener->setFunction('End');
				$listener->setOption(array('Volets_id' => $this->getId()));
				$listener->emptyEvent();	
					$listener->addEvent($this->getConfiguration('cmdEnd'));
				$listener->save();
			}
		}
	}
	public function AddCommande($Name,$_logicalId,$Type="info", $SubType='binary',$visible,$Value=null,$Template=null,$icon=null,$generic_type=null) {
		$Commande = $this->getCmd(null,$_logicalId);
		if (!is_object($Commande))
		{
			$Commande = new voletPropCmd();
			$Commande->setId(null);
			$Commande->setName($Name);
			$Commande->setIsVisible($visible);
			$Commande->setLogicalId($_logicalId);
			$Commande->setEqLogic_id($this->getId());
			$Commande->setType($Type);
			$Commande->setSubType($SubType);
		}
		if($Value != null)
			$Commande->setValue($Value);
		if($Template != null){
			$Commande->setTemplate('dashboard',$Template );
			$Commande->setTemplate('mobile', $Template);
		}
		if($icon != null)
			$Commande->setDisplay('icon', $icon);
		if($generic_type != null)
			$Commande->setDisplay('generic_type', $generic_type);
		$Commande->save();
		return $Commande;
	}
	public function postSave() {
		$this->StopListener();
		$hauteur=$this->AddCommande("Hauteur","hauteur","info",'numeric',0,null,null,null,'FLAP_STATE');
		$this->AddCommande("Position","position","action",'slider',1,$hauteur->getId(),'Volet',null,'FLAP_SLIDER');
		$this->AddCommande("Up","up","action", 'other',1,null,null,'<i class="fa fa-arrow-up"></i>','FLAP_UP');
		$this->AddCommande("Down","down","action", 'other',1,null,null,'<i class="fa fa-arrow-down"></i>','FLAP_DOWN');
		$this->AddCommande("Stop","stop","action", 'other',1,null,null,'<i class="fa fa-stop"></i>','FLAP_STOP');
		$this->StartListener();
	}	
	
	public function preRemove() {
		$listener = listener::byClassAndFunction('voletProp', 'Up', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'Down', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'Stop', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
		$listener = listener::byClassAndFunction('voletProp', 'End', array('Volets_id' => $this->getId()));
		if (is_object($listener))
			$listener->remove();
	}
}
class voletPropCmd extends cmd {
    public function execute($_options = null) {
		switch($this->getLogicalId()){
			case "up":
                cache::set('voletProp::Move::'.$this->getId(),false, 0);
				$this->getEqLogic()->execPropVolet(100);
			break;
			case "down":
            cache::set('voletProp::Move::'.$this->getId(),false, 0);
            $this->getEqLogic()->execPropVolet(0);
			break;
			case "stop":
				if($this->getEqLogic()->getConfiguration('cmdStop') != ''){
					$cmd=cmd::byId(str_replace('#','',$this->getEqLogic()->getConfiguration('cmdStop')));
					if(is_object($cmd))
						$cmd->execute(null);
				}else{
					if(cache::byKey('voletProp::ChangeState::'.$this->getEqLogic()->getId())->getValue(false))
						$cmd=cmd::byId(str_replace('#','',$this->getEqLogic()->getConfiguration('cmdUp')));
					else
						$cmd=cmd::byId(str_replace('#','',$this->getEqLogic()->getConfiguration('cmdDown')));
					if(is_object($cmd))
						$cmd->execute(null);
				}				
				if($this->getEqLogic()->getConfiguration('UpStateCmd') == '' && $this->getEqLogic()->getConfiguration('DownStateCmd') == ''){		
					if(cache::byKey('voletProp::Move::'.$this->getEqLogic()->getId())->getValue(false)){
						cache::set('voletProp::ChangeStateStop::'.$this->getEqLogic()->getId(),microtime(true), 0);
						$this->getEqLogic()->UpdateHauteur();
					}
				}
				cache::set('voletProp::Move::'.$this->getEqLogic()->getId(),false, 0);
			break;
			case "position":
				$this->getEqLogic()->execPropVolet($_options['slider']);
			break;
		}
	}
}
?>
merci pour ce code j'essaierai ce week end, si j'y arrive en modifiant le plugin. Comme pour beaucoup d'amateur que nous sommes la bidouille ça va mais quand c'est trop poussé et que le besoin est justifié l'idéal serait qu'il soit intégré dans le produit fini. Mais Jeedom fait parti du DIY. 😉

Répondre

Revenir vers « [Catégorie] Automatisation »

Qui est en ligne ?

Utilisateurs parcourant ce forum : Idaho947 et 2 invités