Commande Arrêter/Stop type Portail, Volet, Store

Bonjour à tous,

Je viens vers vous car je suis embêter avec le sujet suivant :

  • les commandes Stop ou Arrêter venant de Jeedom ne remontent pas dans Google Home.

Je sais qu’il existe une solution en passant par une scène/scénario.

Cependant il est souvent dit à tord que google home ne gèrent pas les commande Stop.
Alors que moi j’ai le cloud AirSend par exemple m’affiche bien la commande Stop de mon portail dans google Home.

Quand je remonte ce même portail (virtuel) via le plugins GSH la commande Stop ne s’affiche pas dans mon appli GoogleHome (avec les bon types et types génériques de définis).

Voici des images pour vous monter ce que je veux dire :

Ci-dessous, le même portail (AirSend) remonté dans GoogleHome via

  • Cloud AirSend
  • via Cloud Jeedom :
    Les deux sont du même types (même icone = même type)

La on voit la différence bien la différence alors que les types d’appareils sont les mêmes!

Et voici ma configuration de types coté Jeedom GSH :

Même chose avec type portail et volet : Bouton stop n’apparait pas sur Google Home
Qu’en pensez-vous?

Merci.

ps : svp ne dite pas que GoogleHome ne gèrent pas les commandes stop et que ce n’est pas la faute de Jeedom.

En plus le service est payant sur Jeedom (mais avec commande stop manquantes)
Service gratuit chez AirSend avec tout les commandes bien remontées.

Ce que je veux dire c’est que le bouton est dispo chez Google donc Jeedom devrait pouvoir nous l’afficher dans GoogleHome :wink:
:pray:

Bonjour,
Je viens de regarder et je pense qu’ils font une bidouille car la documentation officiel de google ne dit pas que c’est possible. Voila pour les volet : Cloud-to-cloud  |  Google Home Developers il recommande 2 traits :

Dans aucun des 2 cas il n’y a de commande type stop possible que je peux soit indiqué soit lui dire que c’est possible.

Je vois donc pas trop comment répondre a ta demande…

Et pour info le prix du service (1€ par mois) ca paye a peine les serveurs coté jeedom car google l’impose. Ca ne permet donc absolument pas de financer le moindre developpement et c’est vendu tel quel. Donc si une fonction n’y ait pas elle n’y ait pas tout simplement, on peut la faire si on veut mais le faite de payer ne vous donne absolument pas le droit d’exiger une fonction…

Bonjour Loïc,

merci pour ton retour et d’avoir pris la peine de regarder.

Je vais éviter de faire des posts la nuit, la fatigue ça me rend aigri :sweat_smile:.

Merci pour les sources je vais regarder par curiosité et pour essayer de comprendre comment airSend gère la chose.

:pray:

Je pense airsend triche et doit rajouter un traits pour le stop, ce que Google ne recommande pas

Je sais pas si il triche, mais c’est pas impossible!
Google dit aussi qu’on peut rajouter les trait nécessaires selon les besoins du devices.

Du coup ça reste un peu contradictoire.

Maintenant c’est sûr que ça demande un certain temps et des tests réels avant de trouver le bon trait et de l’afficher correctement…

Je viens juste de comprendre le principe grâce à tes sources mais après je ne maîtrise pas donc je ferai mon stop par une scène.

Merci pour l’échange.

Après ajouter des traits c’est rapide ya un fichier a éditer la class principal au début. Si les tests sont ok je le ferais en stable. Par contre je vois pas le traits a ajouter peut être le stop start

Ha ok c’est top!!

Je savais pas que les traits étaient définis dans la class.

C’est bien pensé ça nous permet de garder la main côté Jeedom💪
(Je m’étais mis en tête que c’était géré dans le cloud :face_with_hand_over_mouth:).

Bon bien franchement merci je vais pouvoir faire des tests.

Je ferai signe si j’ai des résultats intéressants.

Salut Loïc,

Je suis content j’ai réussis à faire ce dont j’avais besoin grâce à notre échange.
J’ai réussis à me faire un truc sympa avec une option dans le class gsh_OpenClose.class.php

Mon principe est d’ajouté une option dans la classe OpenClose qui propose d’afficher le bouton Arrêter.

Si l’option est coché et seulement si l’option est coché:

  • j’envoi le traits StartStop à Google avec option Pausable .
  • j’envoi l’id de le commande de mon équipement qui est de type ‹ FLAP_STOP ›
  • Je surveille que la condition $execution[‹ params ›][‹ start ›] == false( je fais rien quand rien c’est true)
  • Je renvoie toujours dans query un return $return[‹ isRunning ›] = true pour que le bouton affiche bien Arrêter dans Google;

A voir si cette modification te convient?

Bon ok on est très proche de la bidouille. :wink:
Mais bidouille bien utile et qui ne gène pas grâce à l’option à coché.

Pour moi c’est ok sur Google Home avec Bouton Arrêter et commande vocal « Arrête le portail » qui lance bien une commande Stop.

Je re-testerai demain soir voir si rien ne gêne.

Voici le code gsh_OpenClose.class.php modifié :

<?php

/* This file is part of Jeedom.
*
* Jeedom is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Jeedom is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jeedom. If not, see <http://www.gnu.org/licenses/>.
*/

/* * ***************************Includes********************************* */
require_once dirname(__FILE__) . '/../../../../core/php/core.inc.php';

class gsh_OpenClose {
  
  /*     * *************************Attributs****************************** */
  
  private static $_SLIDER = array('FLAP_SLIDER');
  private static $_ON = array('FLAP_BSO_UP', 'FLAP_UP','GB_OPEN');
  private static $_OFF = array('FLAP_BSO_DOWN', 'FLAP_DOWN','GB_CLOSE');
  private static $_STATE = array('FLAP_STATE', 'FLAP_BSO_STATE','GARAGE_STATE','BARRIER_STATE','OPENING', 'OPENING_WINDOW');
  private static $_STOP = array('FLAP_STOP');
  
  /*     * ***********************Methode static*************************** */
  
  public static function discover($_device,$_eqLogic){
    $return = array('traits' => array(),'customData' => array(),'attributes' => array('openDirection' => array('DOWN'),'queryOnlyOpenClose' => true,'discreteOnlyOpenClose' => true));
    if ($_device->getOptions('OpenClose::partial')) {
      $return['attributes']['discreteOnlyOpenClose'] = false;
    }
    foreach ($_eqLogic->getCmd() as $cmd) {
      if (in_array($cmd->getGeneric_type(), self::$_ON)) {
        if (!in_array('action.devices.traits.OpenClose', $return['traits'])) {
          $return['traits'][] = 'action.devices.traits.OpenClose';
        }
        $return['customData']['OpenClose_cmdSetOn'] = $cmd->getId();
        $return['attributes']['queryOnlyOpenClose'] = false;
      }
      if (in_array($cmd->getGeneric_type(), self::$_OFF)) {
        if (!in_array('action.devices.traits.OpenClose', $return['traits'])) {
          $return['traits'][] = 'action.devices.traits.OpenClose';
        }
        $return['customData']['OpenClose_cmdSetOff'] = $cmd->getId();
        $return['attributes']['queryOnlyOpenClose'] = false;
      }
      if (in_array($cmd->getGeneric_type(), self::$_STATE)) {
        if (!in_array('action.devices.traits.OpenClose', $return['traits'])) {
          $return['traits'][] = 'action.devices.traits.OpenClose';
        }
        $return['customData']['OpenClose_cmdGetState'] = $cmd->getId();
      }
      if (in_array($cmd->getGeneric_type(), self::$_SLIDER)) {
        if (!in_array('action.devices.traits.OpenClose', $return['traits'])) {
          $return['traits'][] = 'action.devices.traits.OpenClose';
        }
        $return['customData']['OpenClose_cmdSetSlider'] = $cmd->getId();
        $return['attributes']['queryOnlyOpenClose'] = false;
        $return['attributes']['discreteOnlyOpenClose'] = false;
      }
      
      if ($_device->getOptions('OpenClose::pausableSet', 0) == 1) {        
        if (in_array($cmd->getGeneric_type(), self::$_STOP)) {
          if (!in_array('action.devices.traits.StartStop', $return['traits'])) {
            $return['traits'][] = 'action.devices.traits.StartStop';
          }
          $return['customData']['OpenClose_cmdSetStop'] = $cmd->getId();
        }      
      }
    }
    return $return;
  }
  
  public static function needGenericType(){
    return array(
      __('Position',__FILE__) => self::$_SLIDER,
      __('On',__FILE__) => self::$_ON,
      __('Off',__FILE__) => self::$_OFF,
      __('Etat',__FILE__) => self::$_STATE
    );
  }
  
  public static function exec($_device, $_executions, $_infos){
    $return = array();
    foreach ($_executions as &$execution) {
      try {
        switch ($execution['command']) {
          case 'action.devices.commands.OpenClose':
          if($_device->getOptions('OpenClose::invertSet',0) == 1){
            $execution['params']['openPercent'] = 100 - $execution['params']['openPercent'];
          }
          if (isset($_infos['customData']['OpenClose_cmdSetSlider'])) {
            $cmd = cmd::byId($_infos['customData']['OpenClose_cmdSetSlider']);
            if (!is_object($cmd)) {
              break;
            }
            $value = $cmd->getConfiguration('minValue', 0) + ($execution['params']['openPercent'] / 100 * ($cmd->getConfiguration('maxValue', 100) - $cmd->getConfiguration('minValue', 0)));
            $cmd->execCmd(array('slider' => $value));
            $return = array('status' => 'SUCCESS');
            break;
          } else if ($execution['params']['openPercent'] > 0 && $execution['params']['openPercent'] < 100 && $_device->getOptions('OpenClose::partialCommand','') != '') {
            $cmd = cmd::byId($_device->getOptions('OpenClose::partialCommand',''));
          }else if ($execution['params']['openPercent'] > 50) {
            if (isset($_infos['customData']['OpenClose_cmdSetOn'])) {
              $cmd = cmd::byId($_infos['customData']['OpenClose_cmdSetOn']);
            }
          } else if (isset($_infos['customData']['OpenClose_cmdSetOff'])) {
            $cmd = cmd::byId($_infos['customData']['OpenClose_cmdSetOff']);
          }
          if (!isset($cmd) || !is_object($cmd)) {
            break;
          }
          $cmd->execCmd();
          $return = array('status' => 'SUCCESS');
          break;
            
            
          case 'action.devices.commands.StartStop':
            if($_device->getOptions('OpenClose::pausableSet',0) == 1){
              if($execution['params']['start'] == false){
                if (isset($_infos['customData']['OpenClose_cmdSetStop'])) {
                  $cmd = cmd::byId($_infos['customData']['OpenClose_cmdSetStop']);
                  if (!is_object($cmd)) {
                    break;
                  }
                  $cmd->execCmd();
                  $return = array('status' => 'SUCCESS');
                  break;
                }
              }
            }
            break;
        }
      } catch (Exception $e) {
        log::add('gsh', 'error', $e->getMessage());
        $return = array('status' => 'ERROR');
      }
    }
    return $return;
  }
  
  public static function query($_device, $_infos){
    $return = array();
    $cmd = null;
    if ($_device->getOptions('OpenClose::pausableSet', 0) == 1) {        
    	$return['isRunning'] = true;
    }
    if (isset($_infos['customData']['OpenClose_cmdGetState'])) {
      $cmd = cmd::byId($_infos['customData']['OpenClose_cmdGetState']);
    }
    if (!is_object($cmd)) {
      return $return;
    }
    $value = $cmd->execCmd();
    $openState = array('openPercent' => 0,'openDirection' => 'DOWN');
    if ($cmd->getSubtype() == 'numeric') {
      $openState['openPercent'] = $value;
    } else if ($cmd->getSubtype() == 'binary') {
      $openState['openPercent'] = boolval($value);
      if ($cmd->getDisplay('invertBinary') == 1) {
        $openState['openPercent'] = ($openState['openPercent']) ? false : true;
      }
      $openState['openPercent'] = ($openState['openPercent']) ? 0 : 100;
    }
    if($_device->getOptions('OpenClose::invertGet')){
      $openState['openPercent'] = 100 - $openState['openPercent'];
    }
    $return['openState'] = array($openState,array('openPercent' => $openState['openPercent']));
    return $return;
  }
  
  public static function getHtmlConfiguration($_eqLogic){
    echo '<div class="form-group">';
    echo '<label class="col-sm-3 control-label">{{Afficher le bouton Arrêter}}</label>';
    echo '<div class="col-sm-3">';
    echo '<input type="checkbox" class="deviceAttr" data-l1key="options" data-l2key="OpenClose::pausableSet"></input>';
    echo '</div>';
    echo '</div>';
    echo '<div class="form-group">';
    echo '<label class="col-sm-3 control-label">{{Inverser l\'action}}</label>';
    echo '<div class="col-sm-3">';
    echo '<input type="checkbox" class="deviceAttr" data-l1key="options" data-l2key="OpenClose::invertSet"></input>';
    echo '</div>';
    echo '</div>';
    echo '<div class="form-group">';
    echo '<label class="col-sm-3 control-label">{{Inverser l\'état}}</label>';
    echo '<div class="col-sm-3">';
    echo '<input type="checkbox" class="deviceAttr" data-l1key="options" data-l2key="OpenClose::invertGet"></input>';
    echo '</div>';
    echo '</div>';
    echo '<div class="form-group">';
    echo '<label class="col-sm-3 control-label">{{Autoriser ouverture partielle}}</label>';
    echo '<div class="col-sm-3">';
    echo '<input type="checkbox" class="deviceAttr" data-l1key="options" data-l2key="OpenClose::partial"></input>';
    echo '</div>';
    echo '</div>';
    echo '<div class="form-group">';
    echo '<label class="col-sm-3 control-label">{{Commande partielle}}</label>';
    echo '<div class="col-sm-3">';
    echo '<select class="form-control deviceAttr" data-l1key="options" data-l2key="OpenClose::partialCommand">';
    echo '<option value="">{{Aucun}}</option>';
    foreach ($_eqLogic->getCmd('action', null, null, true) as $cmd) {
      echo '<option value="' . $cmd->getId() . '">' . $cmd->getName() . '</option>';
    }
    echo '</select>';
    echo '</div>';
    echo '</div>';
  }
  
}

Et Voici un aperçu de l’emplacements des ajouts / modifications :

Salut,
Malheureusement ca ne me va pas car tu mets 2 traits dans la meme class, alors qu’une class = un traits. Par contre dans la beta de demain j’ai ajouté sur les device de type shutter, blind et pas mal d’autre le traits StartStop a voir ce que ca donne dans la réalité mais je pense que si ca marche ca sera plus propre.

Ok.

Mais j’avais déjà ajouter le trait startStop a BLIND en haut du fichier de la class.
Mais ça me faisait du on/off pas du stop ou pause.

La propriété pausable n’est pas complètement géré par la class jeedom StartStop.

De plus il manque le type : FLAP_STOP dans la classe StartStop pour qu’il puisse trouver tout seul la commande de pause.

Le PHP du trait de StartStop renvoie un État qui change de valeur donc le bouton arrêter disparaît sur Google selon l’état.

C’est pour ça que j’ai mis l’option.

Car Google a des trait obligatoire puis d’autre qui sont préconise mais il n’empêche pas d’avoir des modèles de store personnalisé qui contient un bouton STOP.

Dans ce cas dans la liste des types d’appareils proposés.
Je me rajoute un type personnalisé qui contient le bouton STOP sans toucher a la au BLIND, SHUTTER, …

Dans la logique « openclose » c’est pour les appareils qui peuvent être mis en pause en cours de route.
Les autres qui n’ont pas de notion de pause devrait avoir le type onOff et pas StartStop alors.

D’ailleurs je vois dans la classe GSH une friteuse utilise start stop par exemple mais on ne démarre pas une friteuse, on l’allume.
Une friteuse ne se met pas en pause donc elle devrait pas avoir la classe startStop.

Après je comprends totalement la volonté de ne pas mélanger.

Du coup je pense que ta modif de juste ajouter StartStop au type shutter etc,… ne donnera pas satisfaction.
Le stop sera forcément une fermeture !

Ok j’ai changé et mis ton code j’aime pas trop mais effectivement comme ca je vois pas comment faire mieux sans tout modifier (je vais quand meme essayé de reintegrer ca dans start/stop ca serait mieux).

Pour la friteuse c’est les recommandation de google Cloud-to-cloud  |  Google Home Developers

Cool !
A garder seulement si ça ne gêne personne.

Oui il faudra prendre du temps pour essayer de l’intégrer nativement dans start stop.

Mais pour avoir un bouton arrêter en permanence il faut forcer un retour d’état isRunning = true.
Donc voir comment on peut gérer ça intelligemment directement dans la classe startStop.

J’aurais dû regarder dans Google avant de parler de la friteuse :sweat_smile:

Bonjour Loic,
merci pour l’ajout de la modification dans la beta.

Pourrais-tu supprimer le StartStop qui traine sur type GATE (Portail) stp?
Car il empêche le bouton stop de fonctionner avec le type portail.

Ce trait n’est pas sur les autres ouvrants, etc…

Merci

Bonjour,
Effectivement j’ai oublié celui la, ca sera bon dans la beta de demain. Désolé.

1 « J'aime »