$eqLogic->getCmd => Conserver le typage

Bonjour à tous!

Ca fait longtemps que je n’ai pas mis les mains dans jeedom, j’aime beaucoup les changements!

Je suis sur un nouveau besoin (plugin weenect en cours) pour lequel j’aimerai proposer un PR sur le plugin-gsl pour y ajouter une fonctionnalité.

J’ai une machine de dev sous la v4.4.2.

Je cherche à conserver le type quand j’appelle une commande à partir de l’eqLogic :

dans postsave de l’eqLogic j’ai :

if($this->getConfiguration('type') == 'fix' && $this->getConfiguration('coordinatesType') == 'cmd'){
            $cmdPrecName = $this->getConfiguration('coordinated_precision');
            $cmd = $this->getCmd(null, 'accuracy');
            if($cmdPrecName != null && trim($cmdPrecName) != ''){
                if (!is_object($cmd)) {
                    $cmd = new gslContextualCmd();
                    $cmd->setName('precision');
                    $cmd->setEqLogic_id($this->getId());
                    $cmd->setLogicalId('accuracy');
                    $cmd->setType('info');
                    $cmd->setSubType('string');
                    $cmd->save();
                }

                $cmdPrec = cmd::byId(str_replace('#','',$cmdPrecName));
                if(!is_object($cmdLoc)){
                	log::add(__CLASS__, 'debug', 'cmd coordianted precision error : cmd not found');
                }else{
                    $cmd->event($cmdPrec->execCmd());
                }
            } elseif (is_object($cmd)){
                $cmd->event('');
                $cmd->save();
            }            
        }

et ma class de commande gslContextualCmd :

[edit]
Note importante : j’ai deux class de commande gslCmd et gslContextualCmd
=> seule gslCmd est casté au save de commande ???

class gslContextualCmd extends cmd{

    public function postSave(){
        if($this->getLogicalId()=='accuracy'){
            $eqLogic =  $this->getEqLogic();
            if(!is_object($eqLogic)){
                log::add('gsl', 'debug', 'Error Checking "accuracy" command, no logicalId found');
                return;
            }
            if($eqLogic->getConfiguration('type') == 'fix' && $eqLogic->getConfiguration('coordinatesType') == 'cmd'){
                $cmdPrecName = $eqLogic->getConfiguration('coordinated_precision');
                if($cmdPrecName == null || trim($cmdPrecName) == ''){
                    log::add('gsl', 'debug', 'removing cmd : '.$this->getId());
                   $this->remove();
                }
            }
        }

    }
}

le but est de supprimer la commande dans les contextes ou elle n’est pas utile, sans lever d’erreur au save de l’équipement parent.

Problème :

Lors de la création de la commande, je passe bien dans le gslContextualCmd ->postSave

mais quand elle la commande existe, l’appel au $cmd->save ne passe pas par gslContextualCmd ->postSave.

Mes tests montre que $cmd n’est pas une instance de gslContextualCmd :$cmd = $this->getCmd(null, 'accuracy'); ne renvoi pas une instance de gslContextualCmd.

Y’a t’il un moyen de conserver le typage ou de caster, encapusler ou je ne sais quoi la commande pour retrouver le postSave de la commande?

Y’a un truc qui m’échappe.

Mon objectif reste le ->remove de la commande. qui me déclenche une erreur sur l’arc du save de l’équipement (suis parti de cette discussion qui date un peu )

quand je place mes conditions avec le remove dans le postUpdate de l’équipement, j’ai l’erreur attendue :

[localisation][G-Track_GSL][precision] Le type de la commande ne peut pas être vide :gslCmd Object

La première chose qui m’interpelle : le type : gslCmd ?

La seconde, pour le plugin prixcarburant, ça fonctionne sans erreur : lien postUpdate de prixcarburant

=> quelle est la différence?

[edit] j’ai poussé le wip sur mon fork de gsl : GitHub - Bbillyben/jeedom_gsl
pour repoduire il faut un équipement type « Commande » renseigner la commande et la commande de précision → save → vidage de la configuration de la commande de précision → save → error

[edit 2]
juste avant le remove, quand je log la class :
log::add(__CLASS__, 'debug', 'post save cmd remove de type :'.get_class($cmd));
j’ai bien

post save cmd remove de type :gslCmd

[edit 3] j’ai les deux class de commande gslCmd et gslContextualCmd, mais toutes les commandes sont casté en gslCmd ?? comment se fait-ce ?

Note : ça ne résoud pas le pb du remove ceci dit

Salut,

Désolé moi j’y comprend rien à ce code, c’est tordu, ca ne m’étonne pas que ca fonctionne pas: un save pour finalement supprimer la commande dedans??

si ton but est ce qui est écrit au dessus, dans le postSave de eqLogic tu créés ou supprimes les commandes voulues et basta.

de même je ne comprend pas pq appeler ->event() encore moins dans le postSave

oui, ca n’existe pas pour le core ton gslContextualCmd; si eqLogic c’est gsl, la class de la commande c’est gslCmd.

Salut @Mips,

Pas si tordu je t’assure,
le ->event ce sont des reste de mes tests…
si dans le postSave (ou postUpdate ou preSave ou preUpdate) de l’eqLogic je fait :

if($this->getConfiguration('type') == 'fix' && $this->getConfiguration('coordinatesType') == 'cmd'){
                $cmdPrecName = $this->getConfiguration('coordinated_precision');
                $cmd = $this->getCmd(null, 'accuracy');
                if(($cmdPrecName == null || trim($cmdPrecName) == '') && is_object($cmd)){
                    $cmd->remove();
                }
            }

(c’est le bloc que j’ai baladé partout pour tests avec les bonnes conditions pour le remove)

je lève l’erreur cité ci dessus.
(vu la même ici par exemple)

la solution à l’époque a été pour moi de passer par le preSave pour le changement de nom de la commande (qui levait le même type d’erreur), puis l’update du plugin au final.

J’ai fini par comprendre le coup du nommage de la classe de commande… et j’ai mergé les deux dans :

class gslCmd extends cmd {
    public function execute($_options = array()) {
        if ($this->getLogicalId() == 'refresh') {
            gsl::pull(true);
        }
    }
    public function preUpdate(){
    
        if($this->getLogicalId()=='accuracy'){
            $eqLogic =  $this->getEqLogic();
            if(!is_object($eqLogic)){
                log::add('gsl', 'debug', 'Error Checking "accuracy" command, no logicalId found');
                return;
            }
            if($eqLogic->getConfiguration('type') == 'fix' && $eqLogic->getConfiguration('coordinatesType') == 'cmd'){
                $cmdPrecName = $eqLogic->getConfiguration('coordinated_precision');
                if($cmdPrecName == null || trim($cmdPrecName) == ''){
                    log::add('gsl', 'debug', 'removing cmd : '.$this->getId());
                   $this->remove();
    
                }
            
            }
        }

    }
}

et là ça fonctionne sans erreur !!
Je ne comprends pas pourquoi ça ne fonctionne pas dans le postSave de l’eqLogic…

Bonsoir, j’ai essayé de suivre :grin:

Peut-être une idée …

etant dans la class gslContextualCmd → gslContextualCmd->remove() n’existe pas.

sans doute qu’il faut ajouter un getTableName dans la class gslContextualCmd qui pointe vers cmd ?

1 « J'aime »

Salut Phpvarious,
Merci pour l’essai.

Plusieurs question se sont téléscopées sur le sujet :
1/ Impossible de typer la commande autrement que monplugidCmd => résolu, nomenclature nécessaire au Core

2/ impossible de supprimer une commande au cours du processus du save quand on effectue la sauvegarde depuis la page de l’équipement :

si on met dans le preSave, postSave, preUpdate, postUpdate de l’eqLogic/équipement :

$cmd = $this->getCmd(null, 'accuracy');
if(is_object($cmd))$cmd->remove();

je lève l’erreur, uniquement si la commande a été affichée au préalable* :

Le type de la commande ne peut pas être vide :gslCmd Object

[Aucun][Track][precision] Le type de la commande ne peut pas être vide :gslCmd Object
(
[id:protected] => 507
[logicalId:protected] =>
[generic_type:protected] =>
[eqType:protected] =>
[name:protected] => precision
[order:protected] => 1
[type:protected] =>
[subType:protected] =>
[eqLogic_id:protected] => 37
[isHistorized:protected] => 0
[unite:protected] =>
[configuration:protected] =>
[template:protected] =>
[display:protected] =>
[value:protected] =>
[isVisible:protected] => 1
[alert:protected] =>
[_collectDate:protected] =>
[_valueDate:protected] =>
[_eqLogic:protected] => gsl Object
(
[id:protected] => 37
[name:protected] => Gab Track
[logicalId:protected] =>
[generic_type:protected] =>
[object_id:protected] =>
[eqType_name:protected] => gsl
[isVisible:protected] => 1
[isEnable:protected] => 1
[configuration:protected] => {« createtime »:« 2024-02-20 15:24:30 »,« isVisiblePanel »:« 0 »,« isVisibleGlobal »:« 1 »,« type »:« fix »,« cmdgeoloc »:«  »,« history »:«  »,« historyGlobal »:«  »,« coordinatesType »:« cmd »,« coordinated »:« #369# »,« coordinated_precision »:« #339# »,« color »:« #14af18 »,« precisionFiltre »:« 0 »,« precision »:«  »,« updatetime »:« 2024-02-20 19:04:38 »}
[timeout:protected] =>
[category:protected] => {« heating »:« 0 »,« security »:« 0 »,« energy »:« 0 »,« light »:« 0 »,« opening »:« 0 »,« automatism »:« 0 »,« multimedia »:« 0 »,« default »:« 0 »}
[display:protected] => {« backGraph::info »:0}
[order:protected] => 9999
[comment:protected] =>
[tags:protected] =>
[_debug:protected] =>
[_object:protected] =>
[_needRefreshWidget:protected] =>
[_timeoutUpdated:protected] =>
[_batteryUpdated:protected] =>
[_changed:protected] =>
[_cmds:protected] => Array
(
)

    )

[_needRefreshWidget:protected] => 1
[_needRefreshAlert:protected] => 
[_changed:protected] => 1

)

*si je la supprime juste après l’avoir enregistré, ça ne lève pas l’erreur.

Le truc, c’est que dans le plugin prixcarburant de floman (auquel j’ai pu participer, surement plein d’autre), il y a toute une suppression de commandes surnuméraires dans le postUpdate, sans que ça ne lève d’erreur. (lien git sur la fonction)

C’est normale, lors du save par le plugin.template tout est envoyé , l’EqLogic ainsi que les commandes (cmdAttr), donc si tu supprime une commande au cours du processus de part la class eqLogic, lors de l’étape de save des commandes (qui intervient après), le array contient toujours ta commande supprimé.
Et le Core dans ca conception tentera de créer la commande si elle n’existe pas :

N’ayant pas d’attribut type dans ton table_cmd tu te retrouve dans cette condition lors du save :

Dans le table_cmd (addCmdToTable) le type et sous-type pour ce plugin sont définis, ils passent donc les Exception, c’est ensuite dans DB::save que tout ce joue, je pense que comme un id est passé en paramètre, il essai de faire un UPDATE, mais comme cette ID n’existe plus, aucun UPDATE n’est fait.

Test en rajoutant dans le addCmdToTable

tr += '<td>'
tr += '<span class="type" type="' + init(_cmd.type) + '">' + jeedom.cmd.availableType() + '</span>'
tr += '<span class="subType" subType="' + init(_cmd.subType) + '"></span>'
tr += '</td>'

Tu ne devrait plus lever d’erreur…

1 « J'aime »

Salut Phpvarious,

J’ai tenté de modifier le js, j’ai même virer les appel aux _cmd.type et _cmd.subType. mais toujours l’erreur (au remove dans le postSave)

En logant l’appel à addCmdToTable, On voit que l’erreur est lancé avant l’appel à la fonction.
Et comme tu le note, ça coince coté serveur, sur le save de la commande, qui intervient après le postSave de l’eqLogic.

Ce qui est marrant, c’est que ça ne coince pas sur le getName?

note, le addCmdToTbale est tel que :
function addCmdToTable(_cmd) {
    if (!isset(_cmd)) {
        var _cmd = {configuration: {}};
    }
    if (!isset(_cmd.configuration)) {
        _cmd.configuration = {};
    }
    var tr = '<tr class="cmd" data-cmd_id="' + init(_cmd.id) + '">';
    tr += '<td>';
    tr += '<span class="cmdAttr" data-l1key="id" style="display:none;"></span>';
    tr += '<input class="cmdAttr form-control input-sm" data-l1key="name" style="width : 100%;" placeholder="{{Nom}}">';
    tr += '</td>';
	tr += '<td>';
    tr += '<span class="cmdAttr" data-l1key="htmlstate"></span>'; 
    tr += '</td>';
    tr += '<td>';
    if (is_numeric(_cmd.id)) {
        tr += '<a class="btn btn-default btn-xs cmdAction" data-action="configure"><i class="fa fa-cogs"></i></a> ';
        tr += '<a class="btn btn-default btn-xs cmdAction" data-action="test"><i class="fa fa-rss"></i> {{Tester}}</a>';
    }
    tr += '<i class="fa fa-minus-circle pull-right cmdAction cursor" data-action="remove"></i>';
    tr += '</td>';
    tr += '</tr>';
    $('#table_cmd tbody').append(tr);
    $('#table_cmd tbody tr:last').setValues(_cmd, '.cmdAttr');
    if (isset(_cmd.type)) {
        $('#table_cmd tbody tr:last .cmdAttr[data-l1key=type]').value(init(_cmd.type));
    }
    jeedom.cmd.changeType($('#table_cmd tbody tr:last'), init(_cmd.subType));
}

Je suis partie du plugin sur ton fork :

  • J’ai commenté la partie preUpdate() de la class cmd

  • Au tout début du postSave() de la class eqLogic j’ai ajouté ceci :

      if($this->getConfiguration('type') == 'fix' && $this->getConfiguration('coordinatesType') == 'cmd'){
        $cmdPrecName = $this->getConfiguration('coordinated_precision');
        $cmd = $this->getCmd(null, 'accuracy');
        if(($cmdPrecName == null || trim($cmdPrecName) == '') && is_object($cmd)){
          $cmd->remove();
        }
      }

A cette étape je peut sans problème reproduire l’erreur : Le type de commande ne peut pas être vide

Ensuite dans le js j’ajoute l’affichage du type et subtype :

tr += '<td>'
tr += '<input class="cmdAttr form-control type input-sm" data-l1key="type" value="info" disabled style="margin-bottom:5px;">'
tr += '<span class="subType" subType="' + init(_cmd.subType) + '"></span>'
tr += '</td>'

j’ajoute aussi un th pour le visuel dans gsl.php :

Et voila, plus aucune erreur au save si je supprime la commande de précision …


Normal aussi, car dans le table_cmd tu affiche le nom (precision), donc lors du save celui ci est défini, mais comme tu n’affiche pas le type et subtype c’est la que sa bloc lors du save.

Je vais tenter d’expliquer par un petit schéma :

1 « J'aime »

Grand Merci Phpvarious pour cette réponse très complète !
et ++++ pour ce schéma du flow du save de l’équipement!

Normal aussi, car dans le table_cmd tu affiche le nom (precision), donc lors du save celui ci est défini, > mais comme tu n’affiche pas le type et subtype c’est la que sa bloc lors du save.

C’est exactemant ce que je prenais à l’envers dans ton explication initiale.

Ce sujet a été automatiquement fermé après 24 heures suivant le dernier commentaire. Aucune réponse n’est permise dorénavant.