Calcul mathématique d'angle sur une donnée d'un capteur de vibration Aqara

Bonjour,

Je souhaite réaliser le calcul pour récupérer les informations x,y et z provenant d’un capteur Aqara Vibration. Je me dis que cela doit être réalisable avec un virtuel, mais je n’y connais pas grand chose en programmation.

Est-ce qu’on peut:

  • découper la donnée comme ci-dessous
  • et faire des fonctions mathématiques atan, acos, sqrt ?
const data = msg.data['1288'];

 // array interpretation:
 // 12 bit two's complement sign extended integer
 // data[1][bit0..bit15] : x
 // data[1][bit16..bit31]: y
 // data[0][bit0..bit15] : z
 // left shift first to preserve sign extension for 'x'
 const x = ((data['1'] << 16) >> 16);
 const y = (data['1'] >> 16);
 // left shift first to preserve sign extension for 'z'
 const z = ((data['0'] << 16) >> 16);

 // calculate angle
result.angle_x = Math.round(Math.atan(x/Math.sqrt(y*y+z*z)) * 180 / Math.PI);
result.angle_y = Math.round(Math.atan(y/Math.sqrt(x*x+z*z)) * 180 / Math.PI);
result.angle_z = Math.round(Math.atan(z/Math.sqrt(x*x+y*y)) * 180 / Math.PI);

 // calculate absolulte angle
const R = Math.sqrt(x * x + y * y + z * z);
result.angle_x_absolute = Math.round((Math.acos(x / R)) * 180 / Math.PI);
result.angle_y_absolute = Math.round((Math.acos(y / R)) * 180 / Math.PI);

Source: https://github.com/Koenkk/zigbee-herdsman-converters/blob/c2998f8792c99163328195efdea4b06c65cca296/converters/fromZigbee.js#L1350

Bonjour,

Ca doit surement pouvoir se faire comme tu veux mais je ne peux pas t’aider.
Concernant le capteur et suivant ce que tu veux en faire, peut être juste dans un scénario faire cela:
si valeur > position « repos » + delta alors faire une action
Que veux tu en faire ou tu t’en sers pour faire quoi si ce n’est pas indiscret ?
Moi il est un peu capricieux donc je l’ai laissé tombé et là je réessaye de le faire fonctionner sans succès pour le moment…

Intéressant, tu utilises quel champ du capteur pour obtenir cette valeur?

C’est un capteur qui peut avoir de très nombreuses utilisations pour peu qu’on puisse récupérer des informations lisible dans Jeedom.
Voici des usages intéressant qui peuvent être réalisés:

  • Capteur d’allumage/éteignage de la lumière de l’escalier à partir du moment où l’on marche sur la première marche. C’est beaucoup plus fiable qu’un capteur de mouvement en bas d’escalier qui génère beaucoup de faux positifs.
  • Comme sonnette
  • Sur les fenêtres pour obtenir 2 informations: bris de glace et si on ouvre/ferme fenêtre
    image
  • Savoir qu’un tiroir a été ouvert (utile quand on a un bébé)

Bonjour,

Je ne sais pas à quoi correspond ton tableau msg.data dans ce code, mais pour la partie des calculs cos sin tan c’est possible en php (ton code est en javascript la traduction est simple)

<?php
// définition de la classe résult
class result {
    public $angle_x = 0;
    public $angle_y = 0;
    public $angle_z = 0;
    public $angle_x_abs = 0;
    public $angle_y_abs = 0;
    public $angle_z_abs = 0;
}

// fonction de calcul des angles
function calculer_angles_capteur_aqara($x, $y, $z) {
    // calculate angle
    $result = new result();
    $result->angle_x = round( atan( $x / sqrt($y**2 + $z**2)) * 180 / M_PI);
    $result->angle_y = round( atan( $y / sqrt($x**2 + $z**2)) * 180 / M_PI);
    $result->angle_z = round( atan( $z / sqrt($x**2 + $y**2)) * 180 / M_PI);
    
     // calculate absolulte angle
    $r = sqrt( $x ** 2 + $y ** 2 + $z ** 2);
    $result->angle_x_abs = round((acos($x / $r)) * 180 / M_PI);
    $result->angle_y_abs = round((acos($y / $r)) * 180 / M_PI);
    $result->angle_z_abs = round((acos($y / $r)) * 180 / M_PI);
    return $result;
}

// test
$test = calculer_angles_capteur_aqara( 2, 3, 4);
var_dump($test);
print("angles: x = {$test->angle_x},  y = {$test->angle_y} ,  z = {$test->angle_z}  deg");

J’ai testé ce code online dans un bac à sable php :

OK pour les utilisations, moi je souhaite m’en servir pour ma Boite aux lettres pour le moment (rotation dans un sens=lettre et l’autre=colis) mais je pense avoir un problème de portée, faut que je me remette dessus et fasse des tests.
En fait, si tu le mets sur une porte (par ex), l’orientation x (par ex) va passer de 20 à 80 (par ex) au moment de l’ouverture. C’est pour cela que je te proposais: si valeur>repos+delta alors…, ce qui donne dans l’exemple ci-dessus 80>20+30 par ex alors la porte est ouverte…
C’est comme cela que je comptais m’en sortir avec ce capteur mais il était capricieux lors de mes tests.

Merci pour ton lien. Je n’y connais pas grand chose en code, mais je comprends que c’est un moyen de tester.
La valeur de msg.data correspond à l’input de la fonction que je souhaite réaliser. Dans mon cas cette information vient du capteur Aqara Vibration. Voici une valeur concrète retourné par ce capteur: 670012865619

670012865619 est donc mon input, où est-ce que je dois la mettre dans la webpage PHP sandbox pour obtenir le résultat?

Dans l’appel de la fonction ici par exemple :slight_smile: 2 3 et 4 sont les valeurs concrètes que tu peux remplacer par des variables $x $y $z ou bien des infos de ton objet jeedom.
Dans le bac à sable tu ne pourra pas récupérer les valeurs jeedom par contre, c’est juste pour l’exemple.

Le soucis c’est que je ne reçois pas directement les valeurs x, y, z du capteur.
Je reçois juste: 670012865619 et on obtient x, y, z à partir du code suivant

 // array interpretation:
 // 12 bit two's complement sign extended integer
 // data[1][bit0..bit15] : x
 // data[1][bit16..bit31]: y
 // data[0][bit0..bit15] : z
 // left shift first to preserve sign extension for 'x'
 const x = ((data['1'] << 16) >> 16);
 const y = (data['1'] >> 16);
 // left shift first to preserve sign extension for 'z'
 const z = ((data['0'] << 16) >> 16);

Mais je ne comprends ce que fait:

  • ((data[‹ 1 ›] << 16) >> 16);
  • (data[‹ 1 ›] >> 16);
  • ((data[‹ 0 ›] << 16) >> 16);

Ha mince je m’attendais pas à ça :expressionless:
data contient donc 2 valeurs, tu devrais en avoir une 2e non?
data[1] contient à la fois x et y, c’est une opération sur les bits pour les « séparer » (c’est pas très pratique)
https://www.php.net/manual/en/language.operators.bitwise.php
Heureusement c’est possible en php mais je ne suis pas sur du résultat…

j’ai mis à jour le bac à sable :slight_smile: mais je suis curieux de comprendre, quelle valeur doit retourner 670012865619 pour x et y ? et tu a bien une autre input pour z ?

Une petite mise à jour. Ton « 670012865619 » est la représentation en décimal de l’ensemble des axes. Il faut passer par une conversion en binaire (sur 12 bits), puis extraire les positions de chacun.

J’ai fait l’exercice de façon incomplète avec un virtuel (ici appelé « angles aqara »)

Si ta valeur est #[capteur][aqara][Position]#, alors tu peux créer un virtuel avec les commandes info suivantes (entre parenthèses le sous-type).

ValeurHexa (autre)

dechex(#[capteur][aqara][Position]#)

Valeur X (numérique)

hexdec(substr(#[capteur][angles aqara][ValeurHexa]#,-3))

Valeur Y (numérique)

hexdec(substr(#[capteur][angles aqara][ValeurHexa]#,-6,-3))

Valeur Z (numérique)

hexdec(substr(#[capteur][angles aqara][ValeurHexa]#,-9,3))

Au final, ça retourne bien 3 valeurs qui reflètent assez bien la position du capteur, sauf que … j’ai pris des tonnes de raccourcis à cause de mes compétences limitées, et du fait que Jeedom ne sache pas gérer toutes les fonctions native de PHP dans un virtuel sauf erreur. Et je n’avais pas l’envie ni le bagage pour aller plus loin …

Les limites de mon approche bien crade sont donc que :

  • Les valeurs sont normalement des compléments à deux (avec un signe, donc) et je ne prends pas DU TOUT ça en compte. Mes valeurs sont donc fondamentalement fausses ! Mais fonctionnellement ça permet déjà d’avancer (à une position donnée, une valeur).
  • A position identique, on peut avoir des valeurs très proches (à 5-10% près), mais pas toujours strictement identiques. Attention à tester sur des plages, donc (ce serait vrai même avec les calculs faits dans les règles de l’art, j’ai testé avec Deconz/Phoscon).
  • Si un jour quelqu’un le fait bien (et ça arrivera), il faudra reconfigurer les test :slight_smile:

Si quelqu’un de motivé (et compétent) veut se plonger dans les détails d’implémentation, il y a beaucoup à lire sur cette page.

Si ça peut aider … je me contente de ça en attendant mieux (comprendre : ça répond à mon usage mais je ne peux rien garantir pour d’autres).

J’ajoute que Pifou est certainement sur une meilleure voie que la mienne (en plus d’être beaucoup plus compétent) :wink:

haha :slight_smile: merci je l’avais pas vu le commentaire, conversion 12 bits avec le signe
je me suis inspiré des fonctions sur php.net pour modifier:
PHP: bindec - Manual
le résultat:
PHP Sandbox - Execute PHP code online through your browser
ça donne ceci, ce que je ne comprends pas c’est que la conversion du nombre donne 40 bits or je m’attendrais à n’avoir que 36 ( parce que 3x12)

670012865619 = '1001101111111111111000001111110001010011' lg=40
x = '110001010011', y = '111000001111', z = '101111111111'
x = '-941', y = '-497', z = '-1025'

Du coup je suis parti comme toi de la fin, et les 4 premiers bits sont inutilisés…

Pas mal du tout ! Je n’avais pas trouvé la doc sur _bin12dec, bravo!
Ca semble tout à fait cohérent, merci! :+1: