jeedom-zigate / jeedom-plugin-zigate

Plugin Jeedom for ZiGate key.
MIT License
29 stars 12 forks source link

Heiman WarningDevice (8804) #240

Open pickwick86 opened 4 years ago

pickwick86 commented 4 years ago

Description du bug Toutes les commandes gérées par la sirène Heiman ne sont pas reconnues. Les commandes détectées ne fonctionnent pas toutes

Pour Reproduire Etapes pour reproduire le problème: Sur un jeedom à jour (dernière version stable + dernier plugin zigate stable), j'ai mis le plugin en mode inclusion et appuyé sur le bouton de ma sirène pour l’appairer.

Toutes les commandes ne sont pas affichées (pas de gestion du strobe alors que lors d'une précédente tentative elles étaient là). Les commandes de type "Buzzer X secondes" ne fonctionnent pas. (Seule la commande "Armed" fait buzzer pendant une seconde)

Screenshots image

Informations:

pickwick86 commented 4 years ago

Après un peu de gratouille dans l'histo Git, c'est le commit 1bd04fa6b08efc06be8674b7ccfd36a30fd2a559 qui pose problème.

Les commandes strobe_ON_Buzzer_ON et STROBE_ON marchaient bien, mais elles ont été supprimées dans la dernière version du plugin.

Je ne connais pas les dessous de la lib et je suis une buse en PHP mais est-ce qu'il serait possible de faire en sorte que ce pilotage du device redevienne possible ?

Fonctions de bases attendues :

Si on a ces 4 commandes, on peut ensuite faire faire ce qu'on veut au device et recréer d'éventuels "buzzer_2sec" via un scenario.

doudz commented 4 years ago

Il faut supprimer les commandes qui ne fonctionnent plus à l'aide du bouton "-" à droite de la ligne de commande. Puis faire une synchronisation pour que les nouvelles commandes soient créées correctement

pickwick86 commented 4 years ago

Ça c'est effectivement la solution si j'avais créé mon équipement avec l'ancienne version et si j'essayais de m'en servir avec la nouvelle, mais là c'est pas le cas. J'ai bien recréé mon équipement "from scratch" avec la nouvelle version. Ce que je cherche à obtenir, c'est un moyen de faire clignoter mon alarme (un temps donné, pour prévenir qu'elle va bientôt sonner) et un moyen de la faire sonner (idéalement, jusqu'à ce qu'on lui dise Stop)

J'ai regardé un peu le contenu de la zigate.class.php et les specs Zigbee, est-ce que tu peux me confirmer 2-3 trucs ?

D'après ce que je comprends, la commande zigbee est créée à l'aide de la méthode "public function _create_action($endpoint_id, $action, $name, $subtype, $value = null)" et les valeurs "utiles" sont :

Suivant si on est warning ou squawk, le struct utilisé comme payload n'est pas le même :

En warning, les huits premiers bits définissent le signal (mode, clignotement, volume sonore), les 16 suivants la durée en secondes, les 8 d'après je sais pas trop ( uStrobeDutyCycle) et les 8 derniers le niveau de clignotement :

typedef struct { uint8 u8WarningModeStrobeAndSirenLevel; uint16 u16WarningDuration; uint8 uStrobeDutyCycle; enum8 eStrobeLevel; }tsCLD_IASWD_StartWarningReqPayload;

En alerte c'est plus simple, la payload est sur 8 bits :

typedef struct { uint8 u8SquawkModeStrobeAndLevel; }tsCLD_IASWD_SquawkReqPayload;

Le premier bit correspond au On/Off de la sirène, le bits 4 au On/Off du clignotement et les bits 6 et 7 au volume sonore.

C'est bien sur ce principe là que tu t'es basé aussi ?

Si c'est bien le cas je ne comprends pas trop les lignes (surtout les $value 'armed' et 'disarmed') : _create_action($endpoint_id, 'ias_squawk', 'Disarmed', 'other', 'disarmed'); _create_action($endpoint_id, 'ias_squawk', 'Armed', 'other', 'armed');

Je m'attendrais plutôt une payload de type 11010001 pour Armed et 00000000 pour Disarmed

Et pour les commandes de type warning, on dirait que tu ne passes en $value que la durée (60 pour 'buzzer_60sec' par exemple) alors que je m'attendais à y voir une payload plus complexe.

Du coup j'y comprends rien :) Pour info, j'ai basé mon raisonnement sur la spec JN-UG-3115-1 (pages 879 à 881)

doudz commented 4 years ago

Ce n'est pas directement le payload de la zigate qui est utilisé par le plugin, on utilise une bibliothèque intermédiaire pour simplifier les choses. pour la fonction ias_squawk par exemple

 def action_ias_squawk(self, addr, endpoint,
                          mode='armed',
                          strobe=True,
                          level='low',
                          direction=0, manufacturer_code=0):
        '''
        mode: armed or disarmed
        strobe: True or False
        level: low, medium, high, veryhigh
        '''

https://github.com/doudz/zigate/blob/master/zigate/core.py#L2213-L2222

pour le warning

def action_ias_warning(self, addr, endpoint,
                           mode='burglar', strobe=True, level='low',
                           duration=60, strobe_cycle=10, strobe_level='low',
                           direction=0, manufacturer_code=0):
        '''
        mode: stop, burglar, fire, emergency, policepanic, firepanic, emergencypanic
        duration: seconds
        level: low, medium, high, veryhigh
        strobe_cycle: duty-cycle of the strobe pulse, expressed as a percentage in 10% steps
        strobe_level: level of the strobe (pulse) low, medium, high, veryhigh
        '''
pickwick86 commented 4 years ago

OK, au temps pour moi, j'avais zappé la bibliothèque intermédiaire. Mais par contre vous avez validé le fonctionnement sur quel modèle de sirène ? Je n'ai trouvé que la Heiman en zigbee et elle ne réagit pas du tout aux commandes comme attendu :

doudz commented 4 years ago

J'ai ce même modèle de sirène. Je ferai des tests

doudz commented 4 years ago

ça pourrait m'aider de lancer les commandes et de me fournir le log en mettant le démon en mode debug

doudz commented 4 years ago

Je confirme la présence d'un bug

doudz commented 4 years ago

https://github.com/doudz/zigate/issues/157

pickwick86 commented 4 years ago

OK ça me rassure, je comprenais plus rien.

Tant qu'à mettre le nez dedans, est-ce qu'il serait possible :

  1. d'avoir une commande qui ne fait que clignoter l'alarme un temps donné (sans son), du genre ias_warning avec la payload qui va bien. (Mode = Stop, Strobe = UseStrobe)

  2. de pouvoir choisir l'intensité sonore du squawk (une commande différente par niveau Low / Medium / High / VeryHigh), ou a minima s'il n'y en a qu'une seule qu'elle soit en VeryHigh histoire de faire le plus de bruit possible

doudz commented 4 years ago

Après vérif pour squawk Armed : Sirène + Flash pendant 2 sec Disarmed : Flash uniquement pendant 2 sec dans les 2 cas, le volume est sur low mais la sirène Heiman ne semble pas avoir de réglage de volume car pas de différence, peut importe la valeur

pickwick86 commented 4 years ago

Moi j'ai pas tout à fait ça : Disarmed : la sirène se met à clignoter rapidement et longtemps (potentiellement sans fin). Et si ensuite j'envoie la commande Off elle se met à clignoter plus lentement pendant une dizaine de secondes avant de s'arrêter. Ce que tu décris c'est le résultat de tes tests en l'état actuel du code ?

pickwick86 commented 4 years ago

Bonjour,

une idée (à la louche) d'une date de résolution ?

doudz commented 4 years ago

Le code de base fonctionne, mais ce que je souhaiterai faire c'est donner la possibilité à l'utilisateur de modifier les commandes proposées par défaut pour ajuster par exemple le durée de fonctionnement de la sirène, etc. Je n'ai pas trop le temps en ce moment pour me consacrer à ce projet donc à la louche je dirais dans un mois Je suis désolé pour le délai, toute aide est la bienvenue

sytosoim commented 4 years ago

Bonjour, j'ai également cette sirène utilisée avec la Zigate et Jeedom sur Raspberry Pi3B+. En effet, j'ai les mêmes résultats de commande que @pickwick86 . Est-ce qu'il y a eu une correction du code depuis ? J'ai essayé de faire une boucle afin que la sirène clignote x fois plus longtemps. Eh bien ça clignote beaucoup plus longtemps que ça ne devrait selon le nombre de répétition spécifiée.

fredericbcv commented 4 years ago

Hello, Je suis pas sur Jeedom mais sur Home Assistant, je pense pas que ça change grand chose au final. Avant de commencer l'intégration dans Home Assistant, j'ai voulu jouer avec le python pour essayer de faire sonner l'alarme. Une fois l'alarme appairé. voici ce que je fais:

import zigate z = zigate.connect('/dev/ttyUSB0') z.devices

[Device (5d4a) 00158d0003a4077f, Device (1ec5) 00158d0003fb74dd, Heiman WarningDevice (5d95) 000d6f0014f70d33]

Il me retourne une liste de devices, je suis content :D

z.devices[-1]

Heiman WarningDevice (5d95) 000d6f0014f70d33

import inspect inspect.getmembers(z.devices[-1])

En regardant les méthodes du device, je suis tombé sur action_ias_warning et action_ias_squawk

z.devices[-1].action_ias_warning()

Il se passe rien...

z.devices[-1].action_ias_squawk()

Outch mes oreilles !

J'essaye de faire clignoter la lumière sans la sirène avec action_ias_warning

z.devices[-1].action_ias_warning('stop',1,'low',3,30,'low')

Il se passe rien encore une fois, je cherche sur google et je tombe sur le forum zigate.fr, cette sirène est évoqué et un patch du firmware rend possible son utilisation la version 3.1a. J'imagine que mon firmware est à jour sinon la sirène n'aurait pas sonnée. Mais lorsqu'on regarde les derniers post, ils parlent que cela est fonctionnel sur Domoticz.

lien: https://zigate.fr/forum/topic/sirene-compatible-zigate-zigbee/?part=4

Je regarde le code de Domoticz en me disant que les fonctions doivent être proche et c'est le cas effectivement !

lien: https://github.com/pipiche38/Domoticz-Zigate/blob/e4af40c771657b6afd3397e5a80ace6ac76f18a5/Classes/IAS.py

Et effectivement y'as des fonctions cool, dont strobe_only, qui fait appel à

warningmode( nwkid, ep, 'stop' )

qui lui même appel à

self._write_IASWD( nwkid, ep, warning_mode, warning_duration, strobe_duty, strobe_level)

Par contre si on regarde le code de la fonction warningMode le calcul de warning_mode est différent que celui dont fait référence @doudz. Si notre device est un WarningDevice le calcul est différent:

if self.ListOfDevices[nwkid]['Model'] == 'WarningDevice': strobe_duty = 0x00 strobe_level = 0x01 if mode == 'both': warning_mode = 0b00010111 elif mode == 'siren': warning_mode = 0b00010011 elif mode == 'strobe': warning_mode = 0b00000100 elif mode == 'stop': warning_mode = 0b00000000

Dans les autres cas le calcul est celui qui est fait par @doudz

STROBE_LEVEL = { 'Low':0x00, 'Medium': 0x01 }

WARNING_MODE = { 'Stop': 0b00000000, 'Burglar': 0b00000001, 'Fire': 0b00000010, 'Emergency': 0b00000011, 'Police Panic': 0b00000100, 'Fire Panic': 0b00000101, 'Emergency': 0b00000110 } STROBE_MODE = { 'No Strobe':0b00000000, 'Use Strobe':0b00010000 }

SIRENE_MODE = ( 'both', 'siren', 'strobe', 'stop')

warning_duration = 0x00 strobe_duty = 0x00 strobe_level = 0x00 warning_duration = 0x01 # 1 seconde

elif mode in SIRENE_MODE: if mode == 'both': warning_mode = WARNING_MODE['Fire'] + STROBE_MODE['Use Strobe'] strobe_duty = 0x1E # % duty cycle in 10% steps strobe_level = STROBE_LEVEL['Low'] elif mode == 'siren': warning_mode = WARNING_MODE['Fire'] + STROBE_MODE['No Strobe'] elif mode == 'strobe': warning_mode = WARNING_MODE['Stop'] + STROBE_MODE['Use Strobe'] strobe_duty = 0x1E # % duty cycle in 10% steps strobe_level = STROBE_LEVEL['Low'] elif mode == 'stop': warning_mode = WARNING_MODE['Stop']

Alors je tente, je met un gros magic number dans le code pour tester. Et miracle, ça clignote sans que ça sonne. On peut jouer sur la durée du clignotement, son rapport cyclique, etc.

Voici ma modif en crade pour tester:

@register_actions(ACTIONS_IAS) def action_ias_warning(self, addr, endpoint, mode='burglar', strobe=True, level='low', duration=60, strobe_cycle=10, strobe_level='low', direction=0, manufacturer_code=0): ''' mode: stop, burglar, fire, emergency, policepanic, firepanic, emergencypanic duration: seconds level: low, medium, high, veryhigh strobe_cycle: duty-cycle of the strobe pulse, expressed as a percentage in 10% steps strobe_level: level of the strobe (pulse) low, medium, high, veryhigh ''' addr = self._translate_addr(addr) addr_mode, addr_fmt = self._choose_addr_mode(addr) addr = self.__addr(addr) manufacturer_specific = int(manufacturer_code != 0) mode = {'stop': '0000', 'burglar': '1000', 'fire': '0100', 'emergency': '1100', 'policepanic': '0010', 'firepanic': '1010', 'emergencypanic': '0110' }.get(mode, '0000') strobe = '10' if strobe else '00' level = {'low': '00', 'medium': '10', 'high': '01', 'veryhigh': '11'}.get(level, '00') warning_mode_strobe_level = int(mode + strobe + level, 2) warning_mode_strobe_level = 4 strobe_level = {'low': 0, 'medium': 1, 'high': 2, 'veryhigh': 3}.get(strobe_level, 0) data = struct.pack('!B' + addr_fmt + 'BBBBHBHBB', addr_mode, addr, 1, endpoint, direction, manufacturer_specific, manufacturer_code, warning_mode_strobe_level, duration, strobe_cycle, strobe_level) print('###############') print(addr_fmt) print(addr_mode) print(addr) print(endpoint) print(direction) print(manufacturer_specific) print(manufacturer_code) print(warning_mode_strobe_level) print(duration) print(strobe_cycle) print(strobe_level) print('###############') self.send_data(0x0111, data)

Petite explication pour les arguments de la fonctions

z.devices[-1].action_ias_warning(mode,strobe,level,duration,strobe_cycle,strobe_level)

J'essayerais pour l'alarme plus tard y'as pas de raison. Si jamais, j'ai un code propre qui fonctionne correctement, je proposerais l'évol à @doudz

doudz commented 4 years ago

Merci pour les essais warning_mode_strobe_level = 4 4 en binaire c'est 00000100 soit 0000 : stop sirène 01 : ? strobe ? 00 : level low (pas d'importance puisqu'on dit pas de sirène)

mais le code actuel dit stop : 0000 strobe : 10 level low : 00 soit 8 et non 4, l'erreur est peut être là il faudrait tester en modifiant la ligne strobe = '10' if strobe else '00'

comme ceci strobe = '01' if strobe else '00'

fredericbcv commented 4 years ago

En effet, je teste ça ce soir ^^

Par contre pour ceux qui se pose la question, c'est normal que l'alarme se coupe avec la fonction action_ias_squawk. Voici ce que dit la doc de NXP:

The IAS WD cluster allows a device which detects warning conditions (e.g. fire) to trigger a warning on an IAS Warning Device which, in turn, initiates a physical alarm such as a siren and/or strobe. The IAS Warning Device hosts the cluster server and the triggering device hosts the cluster client. Two types of warning can be initiated:

Pour ceux qui ont la flemme de lire Squawk mode c'est pour émettre un son court typiquement lorsqu'on active ou désactive l'alarme. Et Warning c'est pour la faire sonner en continue, la durée est un uint_16 en secondes ce qui fait pratiquement 18h à sonner. Je pense que tu auras eu le temps de rentrer chez toi.

fredericbcv commented 4 years ago

@doudz Je viens de tester en effet ceci corrige le strobe strobe = '01' if strobe else '00'

Par contre, je n'arrive pas à activer l'alarme. J'ai refais une passe sur la datasheet de NXP JN-UG-3077 v2.1 chapitre 28 page 558 dans le tableau, on voit les valeurs suivantes :

Par rapport à ce qu'on voit dans le code je pense que les msb et lsb ont été inversés.

En modifiant la ligne mode = {'stop': '0000', 'burglar': '1000', 'fire': '0100', 'emergency': '1100', 'policepanic': '0010', 'firepanic': '1010', 'emergencypanic': '0110' }.get(mode, '0000') par mode = {'stop': '0000', 'burglar': '0001', 'fire': '0010', 'emergency': '0011', 'policepanic': '0100', 'firepanic': '0101', 'emergencypanic': '0110' }.get(mode, '0000')

J'ai les modes burglar, fire, emergency qui font bien sonner l'alarme, c'est gagné :). Par contre, c'est la même à chaque fois, j'ai pas vu de différence. Les modes panic ne font pas sonner l'alarme, je pense que c'est pas implémenté dans la sirène tout comme le niveau sonore qui n'a aucun effet.

Il me reste plus qu'a faire le faire marcher dans home assistant :s

fredericbcv commented 4 years ago

En faite c'est assez simple, voici ce que j'ai fais si ça intéresse du monde:

data:
  addr: 5d95 (verifiez l'adresse dans la partie administration du zigate)
  duration: 1
  endpoint: '1'
  entity_id: zigate.0000000000000000 (verifiez l'id dans la partie administration du zigate)
  level: low
  mode: fire
  strobe: true
  strobe_cycle: 10
  strobe_level: low
service: zigate.ias_warning

Et voilà, je peux me créer autant de script que je veux avec des valeurs prédéfinies.

Merci @doudz pour ton taff c'est cool 👍

doudz commented 4 years ago

@fredericbcv c'est un peu off topic puisque ça concerne home assistant, mais tu ne peux pas indiquer le paramètre addr et le paramètre entity_id Le plus efficace est d'indiquer uniquement entity_id, ainsi l'adresse addr sera récupérée en interne.

fredericbcv commented 4 years ago

Ok c'est bon à savoir, merci

pickwick86 commented 4 years ago

Et du coup pour utiliser la sirène dans Jeedom ?

fredericbcv commented 4 years ago

J'utilise pas Jeedom mais Home Assistant, mais je pense que si tu appliques les même modifs que moi, il y'a moyen que cela corriges tes commandes prédéfinies dans Jeedom.

fredericbcv commented 4 years ago

@pickwick86 Hello, j'ai regardé doudz à pris en compte le correctif que j'avais proposé. Il manquait une partie sur ias_sqwak et warning mais c'est mineur. Si ça se trouve si tu met à jour le package python zigate, tu corriges ton problème.

@doudz J'ai créé une pull request sur le reste de la modif