Remontée complete des informations

Bonjour;
J’aimerais débattre d’un point avec les dév…
Je suis assez frustré depuis mon passage sur les plugins zig Bee de la non remontée de certaines infos de module.
Je pense que cela vient du fait d’une mauvaise description du module lors de sa demande d’intégration, ou de l’évolution de son firmware (j’attends vos avis)

Mais prenons pour exemple le module xiaomi aquara vibration

Une fois inclus, nous avons 6 commandes de crées :

Hors le module renvoi bien plus d’info que cela. On les vois dans les logs zigbee:

0113|[2022-01-27 23:28:36]DEBUG : Reception{"devices":{"00:15:8d:00:03:1c:e0:75":{"1":{"257":{"1288":{"value":"4535512202944","cluster_name":"MultistateInputCluster"}},"1280":{"event":{"current_orientation":{"value":[{"rawValueX":65216,"rawValueY":407,"rawValueZ":1056,"X":89,"Y":0,"Z":1}],"cluster_name":"IAS Zone"}}}}}}}

Je trouves dommage (je suis pret à en discuter) que ces commandes ne soit pas créés automatiquement.
J’ai donc fait les modification suivante dans le fichier jeeZigbee.php:

ajout d’une fonction :

function checkCreateAndUpdateCmd($zigbee,$_cmdName,$value) {
	$cmd = $zigbee->getCmd(null, $_cmdName);
	if (!is_object($cmd)) {
		$cmd = new zigbeeCmd();
		$cmd->setLogicalId($_cmdName . '::raw');
		$cmd->setIsVisible(1);
		$cmd->setName(__($_cmdName . '::raw', __FILE__));
		$cmd->setType('info');
		$cmd->setSubType('string');
		$cmd->setDisplay('generic_type','GENERIC');
		$cmd->setEqLogic_id($zigbee->getId());
		$cmd->save();
		
		$cmd = new zigbeeCmd();
		$cmd->setLogicalId($_cmdName);
		$cmd->setIsVisible(1);
		$cmd->setName(__($_cmdName, __FILE__));
		$cmd->setType('info');
		$cmd->setSubType('string');
		$cmd->setDisplay('generic_type','GENERIC');
		$cmd->setEqLogic_id($zigbee->getId());
		$cmd->save();
	}
	$zigbee->checkAndUpdateCmd($_cmdName, convertValue($value));
	$zigbee->checkAndUpdateCmd($_cmdName . '::raw', $value);

}

et j’ai remplacé tous les appels

$zigbee->checkAndUpdateCmd($endpoint_id . '::' . $cluster_id . '::' . $attribut_id . '::' . $cmd_id, convertValue($cmd_value));

par

checkCreateAndUpdateCmd($zigbee,$endpoint_id . '::' . $cluster_id . '::' . $attribut_id . '::' . $cmd_id,$cmd_value);

J’ai aussi rajouter un « étage » de recherche ceux qui me donne le code suivant:

/* 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/>.
*/
require_once dirname(__FILE__) . "/../../../../core/php/core.inc.php";
if (!jeedom::apiAccess(init('apikey'), 'zigbee')) {
	echo __('Vous n\'etes pas autorisé à effectuer cette action', __FILE__);
	die();
}
if (isset($_GET['test'])) {
	echo 'OK';
	die();
}
$result = json_decode(file_get_contents("php://input"), true);

log::add('zigbee', 'debug', "Reception".json_encode($result));
if (!is_array($result)) {
	die();
}

if (isset($result['device_left'])) {
	event::add('jeedom::alert', array(
		'level' => 'warning',
		'page' => 'zigbee',
		'message' => __('Un périphérique Zigbee a quitté le réseaux', __FILE__),
	));
	$zigbee = zigbee::byLogicalId($result['device_left'], 'zigbee');
	if (is_object($zigbee) && config::byKey('autoRemoveExcludeDevice', 'zigbee') == 1) {
		$zigbee->remove();
		event::add('zigbee::includeDevice', '');
	}
	die();
}

if (isset($result['device_removed'])) {
	event::add('jeedom::alert', array(
		'level' => 'warning',
		'page' => 'zigbee',
		'message' => __('Un périphérique Zigbee a été supprimé du réseaux', __FILE__),
	));
	$zigbee = zigbee::byLogicalId($result['device_removed'], 'zigbee');
	if (is_object($zigbee) && config::byKey('autoRemoveExcludeDevice', 'zigbee') == 1) {
		$zigbee->remove();
		event::add('zigbee::includeDevice', '');
	}
	die();
}

if (isset($result['device_joined'])) {
	event::add('jeedom::alert', array(
		'level' => 'warning',
		'page' => 'zigbee',
		'message' => __('Un périphérique Zigbee est en cours d\'inclusion : ', __FILE__) . $result['device_joined'],
	));
	die();
}

if (isset($result['device_initialized'])) {
	event::add('jeedom::alert', array(
		'level' => 'warning',
		'page' => 'zigbee',
		'message' => __('Un périphérique Zigbee a été inclus : ', __FILE__) . $result['device_initialized'] . '. ' . __('Pause de 30s avant synchronisation', __FILE__),
		'ttl' => 30000
	));
	sleep(30);
	$id = zigbee::sync();
	event::add('zigbee::includeDevice', $id);
	try {
		$zigbee = zigbee::byId($id);
		if (is_object($zigbee)) {
			$zigbee->setTime();
		}
	} catch (\Exception $e) {
	}
	die();
}

$CONVERT_VALUE = array(
	'ZoneStatus.Alarm_1' => 1,
	'ZoneStatus.Restore_reports' => 0,
	'ZoneStatus.0' => 0,
	'bitmap8.1' => 1,
	'bitmap8.0' => 0,
	'Bool.true' => 1,
	'Bool.false' => 0,
	'LockState.Locked' => 1,
	'LockState.Unocked' => 0,
	'SystemMode.Off' => __('Arrêt', __FILE__),
	'SystemMode.Auto' => __('Automatique', __FILE__),
	'SystemMode.Cool' => __('Climatisation', __FILE__),
	'SystemMode.Heat' => __('Chauffage', __FILE__),
	'SystemMode.Emergency_Heating' => __('Chauffage d\'urgence', __FILE__),
	'SystemMode.Pre_cooling' => __('Pré-Climatisation', __FILE__),
	'SystemMode.Fan_only' => __('Ventilation', __FILE__),
	'SystemMode.Dry' => __('Séchage', __FILE__),
	'SystemMode.Sleep' => __('En veille', __FILE__),
	'KeypadLockout.Level_1_lockout' => 1,
	'KeypadLockout.No_lockout' => 0
);

$FIND_VALUE = array(
	'Alarm_1' => 1,
	'Alarm_2' => 1
);

function convertValue($_value) {
	global $CONVERT_VALUE;
	if (isset($CONVERT_VALUE[$_value])) {
		return $CONVERT_VALUE[$_value];
	}
	global $FIND_VALUE;
	foreach ($FIND_VALUE as $key => $value) {
		if (strpos($_value, $key) !== false) {
			return $value;
		}
	}
	if (strpos($_value, 'enum8.undefined_') !== false) {
		return hexdec(str_replace('enum8.undefined_', '', $_value));
	}
	return $_value;
}

function checkCreateAndUpdateCmd($zigbee,$_cmdName,$value) {
	$cmd = $zigbee->getCmd(null, $_cmdName);
	if (!is_object($cmd)) {
		$cmd = new zigbeeCmd();
		$cmd->setLogicalId($_cmdName . '::raw');
		$cmd->setIsVisible(1);
		$cmd->setName(__($_cmdName . '::raw', __FILE__));
		$cmd->setType('info');
		$cmd->setSubType('string');
		$cmd->setDisplay('generic_type','GENERIC');
		$cmd->setEqLogic_id($zigbee->getId());
		$cmd->save();
		
		$cmd = new zigbeeCmd();
		$cmd->setLogicalId($_cmdName);
		$cmd->setIsVisible(1);
		$cmd->setName(__($_cmdName, __FILE__));
		$cmd->setType('info');
		$cmd->setSubType('string');
		$cmd->setDisplay('generic_type','GENERIC');
		$cmd->setEqLogic_id($zigbee->getId());
		$cmd->save();
	}
	$zigbee->checkAndUpdateCmd($_cmdName, convertValue($value));
	$zigbee->checkAndUpdateCmd($_cmdName . '::raw', $value);

}

if (isset($result['devices'])) {
	foreach ($result['devices'] as $ieee => $endpoints) {
		$masterzigbee = zigbee::byLogicalId($ieee, 'zigbee');
		if (!is_object($masterzigbee) || !$masterzigbee->getIsEnable()) {
			continue;
		}
		foreach ($endpoints as $endpoint_id => $clusters) {
			$deviceArray = [$masterzigbee];
			$childzigbee = zigbee::byLogicalId($ieee . '|' . $endpoint_id, 'zigbee');
			if (is_object($childzigbee) && $childzigbee->getIsEnable()) {
				$deviceArray[] = $childzigbee;
			}
			foreach ($deviceArray as $zigbee) {
				if ($zigbee->getConfiguration('decode_file') != '' && file_exists(__DIR__ . '/../' . $zigbee->getConfiguration('decode_file'))) {
					try {
						require_once __DIR__ . '/../' . $zigbee->getConfiguration('decode_file');
						$function = 'decode_' . str_replace('.', '_', $zigbee->getConfiguration('device'));
						if (function_exists($function)) {
							log::add('zigbee', 'debug', 'Use specific decode file for ' . $zigbee->getHumanName() . ' => ' . __DIR__ . '/../' . $zigbee->getConfiguration('decode_file'));
							if ($function($zigbee, $endpoint_id, $clusters)) {
								continue;
							}
						}
					} catch (\Exception $e) {
						log::add('zigbee', 'error', $e->getMessage());
					}
				}
				foreach ($clusters as $cluster_id => $attributs) {
  					foreach ($attributs as $attribut_id => $value) {
 						if (!is_array($value) && $value === '[]') {
							continue;
						}
  						if ($cluster_id == 1) {
							if ($attribut_id == 33) {
								$zigbee->batteryStatus(round($value['value']));
							} else if ($zigbee->getConfiguration('maxBatteryVoltage', 0) != 0 && $attribut_id == 32 && $value['value'] > 0) {
								$zigbee->batteryStatus(round($value['value'] / $zigbee->getConfiguration('maxBatteryVoltage', 0) * 100));
							}
						} else if (strcmp($attribut_id, 'cmd') === 0) {
							foreach ($value as $cmd_id => $cmd_value) {
								if ($cmd_value['value'] === '[]') {
									continue;
								}
								log::add('zigbee', 'debug', 'Search command for ' . $ieee . ' logicalId : ' . $endpoint_id . '::' . $cluster_id . '::' . $attribut_id . '::' . $cmd_id . ' => ' . $cmd_value['value'] . ' convert to ' . convertValue($cmd_value['value']));
                              	checkCreateAndUpdateCmd($zigbee,$endpoint_id . '::' . $cluster_id . '::' . $attribut_id . '::' . $cmd_id,$cmd_value['value']);
							}
						} else if (strcmp($attribut_id, 'gcmd') === 0) {
							foreach ($value as $cmd_id => $cmd_value) {
								if ($cmd_value['value'] === '[]') {
									continue;
								}
								log::add('zigbee', 'debug', 'Search general command for ' . $ieee . ' logicalId : ' . $endpoint_id . '::' . $cluster_id . '::' . $attribut_id . '::' . $cmd_id . ' => ' . $cmd_value['value'] . ' convert to ' . convertValue($cmd_value['value']));
                            	checkCreateAndUpdateCmd($zigbee,$endpoint_id . '::' . $cluster_id . '::' . $attribut_id . '::' . $cmd_id,$cmd_value['value']);
							}
						} else if (strcmp($attribut_id, 'event') === 0) {
    						foreach ($value as $cmd_id => $cmd_value) {
     							if (is_array($cmd_value['value'])) {
									foreach ($cmd_value['value'] as $sub_cmd_id => $sub_cmd_value) {
 										if ($sub_cmd_value === '[]') {
   											$sub_cmd_value = 1;
										}
                                      	if (is_array($sub_cmd_value)) {
                                          foreach ($sub_cmd_value as $sub_detailID => $sub_detailValue) {
                                          checkCreateAndUpdateCmd($zigbee,$endpoint_id . '::' . $cluster_id . '::' . $attribut_id . '::' . $cmd_id . '::' . $sub_cmd_id.'::'.$sub_detailID,$sub_detailValue);
                                         }   
                                        }
                                        else
                                        {
                                          log::add('zigbee', 'debug', 'Search event command for ' . $ieee . ' logicalId : ' . $endpoint_id . '::' . $cluster_id . '::' . $attribut_id . '::' . $cmd_id . '::' . $sub_cmd_id . ' => ' . $sub_cmd_value . ' convert to ' . convertValue($sub_cmd_value));
                                          checkCreateAndUpdateCmd($zigbee,$endpoint_id . '::' . $cluster_id . '::' . $attribut_id . '::' . $cmd_id . '::' . $sub_cmd_id,$sub_cmd_value);
                                       }
									}
								} else {
									if ($cmd_value === '[]') {
										$cmd_value = 1;
									}
									log::add('zigbee', 'debug', 'Search event command for ' . $ieee . ' logicalId : ' . $endpoint_id . '::' . $cluster_id . '::' . $attribut_id . '::' . $cmd_id . ' => ' . $cmd_value . ' convert to ' . convertValue($cmd_value));
                                    checkCreateAndUpdateCmd($zigbee,$endpoint_id . '::' . $cluster_id . '::' . $attribut_id . '::' . $cmd_id,$cmd_value);
 								}
							}
						} else {
							log::add('zigbee', 'debug', 'Search attribut for ' . $ieee . ' logicalId : ' . $endpoint_id . '::' . $cluster_id . '::' . $attribut_id . ' => ' . $value['value'] . ' convert to ' . convertValue($value['value']));
                          checkCreateAndUpdateCmd($zigbee,$endpoint_id . '::' . $cluster_id . '::' . $attribut_id,$value['value']);
						}
					}
				}
			}
		}
	}
}

Sur l’equipement, j’ai maintenant accé à toutes les commandes

En conclusion je pense qu’il serait inrérréssant de laisser via une option la possibilité de générer automatiquement les commandes.

J’attends vos réactions

Bonjour @lefilliatre
Ça m’intéresse, le plugin officiel est basé sur Zigpy et perso j’ai beaucoup de mal à créer les commandes pour les modules…
Je vais essayer ta modif sur les modules qui posent problème.
Après faut voir avec @Loic le boss

Cette modif n’est pas faite pour corriger des problèmes d’inclusion mais seulement pour pallier une mauvaise définition d’un module. Et je pense qu’il faudrait la gérer avec une option sur chaque module.
Genre on l’active après l’intégration, ça creer les commandes manquantes (s’il y en a) on désactive après et a trie les commandes à garder et à supprimer.

Bonjour,
C’est un sujet sur lequel je travails depuis quelques mois mais c’est pas si simple. La ca va creer enormement de commande qui seront souvent incompréhensible, notamment pour tous ce qui est tuya. En soit ca me générais pas si j’étais pas sur d’avoir un ticket de chaques utilisateurs pour chaques commandes au support (autant dire qu’avec ce genre de modification même en faisant du support 24/24h et 7/7 je n’arriverais pas a encaisser la charge).

Il faut donc le faire de manière plus intelligente et surtout ça ne concerne que les modules n’ayant pas de configuration (ce qui arrive de moins en moins). De plus la beta intègre depuis quelques jours un systeme automatique de création de commande si il n’y a aucun configuration (valable que pour certain type de module comme les relay/switch/lumiere/thermostat/… enfin ceux qui ont suivent la norme zigbee officiel).

Donc pour résumé ce que tu as fait va arriver mais sous une autre forme : un bouton a presser dans jeedom ou le module va autoriser la création de commande pendant X secondes en demandant a l’utilisateur de jouer avec le module, tout en ayant une liste de cluster exclus automatiquement pour eviter la profusion de commande. Par contre ca sera pas avant quelques temps (j’ai la 4.2 du core a faire avant, ainsi que tous les plugins liée et je voudrais passer deja la 1er étape de la création automatique qui est en beta en stable).

3 « J'aime »

@Loic, moi cela me va parfaitement!
Je comprends très bien les contraintes que tu évoques. Et la solution que tu propose correspond parfaitement à mes attentes (en mieux). Comme je le disais dans mon post précédent je penses aussi que cela doit rester en ONE shot et sur demande de l’utilisateur!

Effectivement, pour éviter les tickets et demandes en quantité, il faut que ce soit une option activable par l’utilisateur avec un gros message d’avertissement précisant que cela reste pour les utilisateurs avertis et que aucune demande de support ne pourra être possible pour les éléments généré avec cette option.

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