[V4] Intégration Zigbee2mqtt

Comment tu connais à l’avance toutes les clés Z-Wave? C’est ça que je ne comprends pas en fait…

J’ai créé un sujet pour parler de ce débat assez important qu’est la gestion des instances déployées sur long terme =>

Via le vendor ID , il faudra prendre en compte les nouvelles clés , donc c’est à maintenir, mais l’avantage c’est que même s’il n y’a pas de rule pour une clé , elle reste dispo sur /dev/ttyACM*

C’est juste un lien symbolique beaucoup plus parlant

Ok je comprend, mais du coup pour rebondir sur l’autre sujet, c’est à maintenir dans l’image docker, ou c’est à maintenir sur le système? ( ce qu’on ne peut pas trop faire… )

C’est sur le système hôte ( on est en train de pourrir le topic de @Reno :smiley: )

Je penses que ça coute pas grand chose de le faire, c’est un + à disposition

Ça ne me dérange pas car c’est une vraie question que je me pose depuis quelques temps et que je n’ai pas pris le temps de poster.

Je suis d’accord qu’il y a plusieurs sujets.
Aussi, ok pour le fait qu’on laisse /dev en partage mais je ne suis pas trop pour le ‘–privileged’ mais c’est @pierre-gilles qui décide.
Mon exemple perso est que j’utilise d’autre containers Docker, sur RPi ou sur NAS, qui utilisent également des périphériques (carte son USB, cart tuner TNT, …) et j’ai peur que ça génère des conflits si plusieurs containers ont accès aux mêmes devices. J’essaierai de trouver le temps pour tester.

J’ai modifié le service usb de Gladys pour faire remonter le ‘manufacturer’, le ‘VendorID’ et le ‘ProducID’ pour aider l’utilisateur à choisir la bonne interface lorsqu’il a plusieurs dongles USB. Pour Zigbee2mqtt, ça marche bien puisque le dongle est affiché ‘Texas Instrument’. Par contre, je me suis rendu compte que la clé Zwave que je possède fait remonter un VendorID à la place du Manufacturer, ce qui n’est pas très parlant pour l’utilisateur.
Du coup, il serait effectivement intéressant d’afficher le type de dongle dans Gladys (Zwave ou Z2M ou …). Ça nécessite de référencer tous les dongles mais je ne pense pas qu’il y en ait tant que ça. Dans tous les cas, si on laisse afficher le VendorID dans l’interface, dans le cas d’un dongle non géré, on pourra demander aux testeurs de faire remonter cette info pour le prendre en compte.

Pour la règle udev, soit elle sera intégrée dans l’image distrib Gladys, soit il faudra fournir, dans tous les cas, un script de lancement du container, avec les options nécessaires, si l’utilisateur préfère l’image Docker.
Dans ce cas là, on pourrait ajouter une ligne (ou plusieurs) pour la création des règles udev.
Du coup, on pourrait également ajouter une ligne pour la création d’un network Docker pour Gladys, pour l’échange avec les containers de ces services (autre débat que l’on a par ailleurs avec @VonOx et @AlexTrovato) :wink:

1 « J'aime »

Dans l’image raspbian gladys tourne sous docker.

Je vais faire les modifications pour ajouter les règles udev dans l’image raspbian . ( et la mise à disposition dans la doc)
Par contre le network je suis vraiment pas chaud car on se limite au raspberry et à ceux qui l’auront créer manuellement.

Ce qui fait qu’un utilisateur qui utilise un autre network a un service inutilisable car c’est hard coded.

Pour les services qui doivent créér des conteneurs, le mieux est de les créer sur le même network que gladys. C’est ce que tente de faire @AlexTrovato avec le mqtt ( on croise les doigts :crossed_fingers:)
Si ça marche on pourra créer le network sans problème car plus de contraintes

Et je pense que c’est bon pour le partager du network entre Gladys et les containers créés par Gladys. Ne reste qu’à tester :slight_smile: (mais j’ai laissé localhost comme url)

Je ne comprends pas pourquoi tu dis qu’avec le network, on se limite au Rpi.

J’utilise beaucoup Docker (sur Arm et Intel) et je définis toujours des networks entre les services pour mieux maitriser les communications entre containers.
C’est d’ailleurs préconisé par Docker, en production :

Use user-defined bridge networks shows how to create and use your own custom bridge networks, to connect containers running on the same Docker host. This is recommended for standalone containers running in production.

De plus, il est possible de créer plusieurs networks pour un container et il est même possible de créer un network pendant qu’un container tourne pour ensuite l’attacher à ce network, à chaud.

Pour exemple, sur le service Zigbee2mqtt, j’ai créé un network ‹ gladys-net › sur lequel gladys est attaché et j’y connecte également les containers ‹ mqtt › et ‹ zigbee2mqtt ›. Pour suivre ce que j’applique habituellement, j’aurai même du créer un network spécifique entre les containers zigbee2mqtt et mqtt puisque le container zigbee2mqtt n’a pas vocation à communiquer directement avec Gladys.
Chez moi, j’ai également un container InfluxDB pour sauvegarder toutes les données qui passent par le broker MQTT dans une base de données. Pour cela, je définis un réseau supplémentaire spécifique entre mqtt et influxdb.
Cela n’empêche pas de définir également le network host ou de laisser le -p 80:80 pour permettre de s’y connecter depuis une machine distante.

De plus, ce paramétrage n’empêchera pas un utilisateur qui s’y connait de définir un autre network ‹ gladys-external › attaché à Gladys pour y connecter ses propres containers…

Parce qu’on ne fourni qu’une image raspbian, donc faut pas hard-coder dans les services.

Encore une fois je remet pas en cause le bien fondé des networks ( je le fait moi même avec une quinzaine de conteneur) et l’isolation. Je veux juste une solution qui contente tout le monde.

Là dessus encore une fois j’aimerais un peu plus d’explications quand même ! Je ne comprend toujours pas ce que ça apporte

Exemple:

Tu as un dongle zigbee et zwave, zigbee sur /dev/ttyACM0 et zwave sur /dev/ttyACM1

Tu décide de reboot, après celui ci le mount est inversé , tes services côté gladys ne fonctionne plus.

Les règles udev vont faire un alias, le zwave sera toujours dispo sur /dev/zwave et le dongle zigbee sur /dev/zigbee.

ça n’empeche en rien d’utiliser /dev/ttyACM* ( qui peut le plus peut le moins )

ça j’ai compris, mais je n’ai pas compris comment fonctionne cette magie :smiley:

Qui décide quel périphérique atterrit sur /dev/zwave? :slight_smile: En tout cas c’est génial !

Ah excuse moi, bah c’est nous qui décidons, les périphériques usb ont un id vendor et un id product ( et ça ça change pas )

J’ai identifié ça pour le moment ( y’a rien de définitif dans cet exemple ! )

# Aeotec Zwave S2
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", SYMLINK+="tty-usb-zwave"
# Aeotec Zwave Gen5
SUBSYSTEM=="tty", ATTRS{idVendor}=="0658", ATTRS{idProduct}=="0200", SYMLINK+="tty-usb-zwave"
# ZWave.me UZB1 stick
SUBSYSTEM=="tty", ATTRS{idVendor}=="0658", ATTRS{idProduct}=="0280", SYMLINK+="tty-usb-zwave"
# Nortek Security & Control HUSBZB-1
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8a2a", SYMLINK+="tty-usb-zwave-zigbee"
# zigbee2mqtt
SUBSYSTEM=="tty", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="16a8", SYMLINK+="tty-usb-zigbee"

Ok je vois, merci pour l’explication :slight_smile: Et ça, est-ce qu’il y aurait moyen de faire ça dans l’image Docker directement? Comme ça on peut le mettre à jour au fur et à mesure?

Il y’a un equivalent pour alpine linux : Alpine Linux packages
J’ai envie de dire oui mais faut que je teste.

Si ça fonctionne effectivement c’est mieux dans l’image docker directement

Edit ça marche:

image

1 « J'aime »

Je suis du même avis que @Reno concernant l’option --privileged. En sécurité, il faut travailler avec le principe « du moindre privilège ».
Pour du débug et du développement, pas de soucis. Mais en production, surtout sur une image que Gladys distribuera, c’est important de considérer la sécurité à tous les niveaux.

Plusieurs personnes se sont déjà posé la question : Docker - a way to give access to a host USB or serial device? - Stack Overflow
En gros la meilleure manière en terme de sécurité c’est de partager seulement l’équipement voulu (lien vers la documentation Docker qui le confirme) sans utiliser l’option --privileged :

docker run -t -i --device=/dev/ttyUSB0 ubuntu bash

Pour donner accès à tout le dossier /dev l’option --privileged doit être utilisée, mais donne aussi tous les droits sur l’hôte !
Docker l’explique très bien :

In other words, the container can then do almost everything that the host can do.

Rien ne nous empêche de monter tous les devices qui nous intéresse :

docker run -t -i \
--device=/dev/ttyACM0 \
--device=/dev/ttyACM1 \
 ubuntu bash

Dans /dev se trouvent tous les périphériques du système, pourquoi Gladys aurait besoin d’accéder aux partitions des disques, loopback, etc ?
En étant installé sur l’hôte, l’OS aurait empêché l’accès à ces périphériques (sauf avec root évidemment), mais avec l’option --privileged je pense ce ne sera pas le cas.



Totalement d’accord avec toi, si Gladys est compliquée à déployer, maintenir et demande du temps à l’utilisateur final, ça ne fonctionnera pas.

Gladys utilise Docker pour faciliter les mises à jour, donc à chaque nouvelle version, le conteneur est supprimé puis créé à nouveau, non ?

Ce fonctionnement nous permettra donc facilement de modifier les paramètres de lancement de Gladys pour ajouter de nouveaux accès au RPi et suivre les évolutions. La sécurité et la facilité d’utilisation sont donc bien pris en compte :wink:



Dernière remarque niveau sécurité, une fois le travaille de développement terminé, on pourrait se pencher sur les Linux Capabilities. Ce sont des paramètres à passer au conteneur pour forcer Docker à limiter les droits d’accès sur l’hôte. Gladys n’a pas nécessairement besoin de créer une nouvelle carte réseau, d’interagir avec le kernel, d’accéder à des fichiers systèmes (sauf périphériques), modifier les partitions, déboguer un processus, etc.

Ces options sont très utiles pour s’assurer qu’en cas de compromission du conteneur (via un module malveillant ou si un utilisateur a directement exposé son RPi contrairement aux bonnes pratiques par exemple), celui-ci ne puisse pas exploiter l’hôte et faire plus de dégât (Ransomware sur le réseau, espionnage, etc.).

J’ai essayé de limiter les droits des conteneurs que j’utilise sur mon serveur perso, si ça vous intéresse voici la documentation et les exemples :

Exemple tiré de la documentation Docker :

For interacting with the network stack, instead of using --privileged they should use --cap-add=NET_ADMIN to modify the network interfaces.

$ docker run -it --rm  ubuntu:14.04 ip link add dummy0 type dummy

RTNETLINK answers: Operation not permitted

$ docker run -it --rm --cap-add=NET_ADMIN ubuntu:14.04 ip link add dummy0 type dummy

Merci et bravo si vous avez tout lu :sweat_smile:
Désolé de pas encore vous aider niveau dev, dès que j’ai un peu plus de temps je me lance dans mon projet domotique et je vous donne un coup de main !

Impossible de savoir d’avance combien de périphériques a l’utilisateur.
Je creuse le sujet avec des règles udev

Alors non c’est pas comme ça que ça se passe, le conteneur est recréé avec les même commandes. On utilise Watchtower

Vraiment intéressant tout ça ( j’ai un peu de lecture à faire ), mais attention y’ pas que des hotes linux.

ça n’existe plus les modules :wink: tout est intégré.

Merci pour tes propositions. Toute aide est la bienvenue.

Oups, effectivement je ne suis pas encore au point sur tout le fonctionnement de Gladys v4 :sweat_smile:

Concernant les périphériques c’est vrai qu’il y a matière à creuser pour savoir quoi monter. Les environnements des utilisateurs seront tous différents, difficile de prévoir ce qu’il aura.

Pour terminer, mes remarques pour Docker sont bien applicables à Linux et pas Windows :wink:

Hello,

Voila un petit retour de mes tests :

  • Le process de configuration est top (après avoir passé la petite difficulté liée à la détection du stick Zigbee), par contre toujours besoin de faire un force refresh pour faire apparaître mes devices sur la page discover après qu’ils aient été détectés par le stick
  • Si on navigue directement sur l’onglet discover (par exemple en tapant dans l’URL), les devices détectés n’apparaissent pas, il faut passer par l’onglet devices puis retourner sur l’onglet discover pour les voir
  • Sur le dashboard, si je passe en mode édition, je ne peux pas ajouter de box et ne peux plus changer de page : tout bug. (J’ai vérifié, je n’ai pas ce problème sur la version “normale” de Gladys)
    J’ai l’erreur suivante dans la console :
Console
RoomSelector.jsx:21 Uncaught (in promise) TypeError: Cannot read property 'map' of undefined
    at RoomSelector.jsx:21
    at Array.map (<anonymous>)
    at t.o.componentWillReceiveProps (RoomSelector.jsx:18)
    at b (preact.min.js:1)
    at preact.min.js:1
    at p (preact.min.js:1)
    at h (preact.min.js:1)
    at b (preact.min.js:1)
    at d (preact.min.js:1)

En dehors de ça, mes devices sont bien détectés et les valeurs remontent bien, j’ai testé les devices suivant :

  • Xiaomi magic cube
  • Xiaomi capteur de température
  • Xiaomi capteur ouverture de porte
  • Xiaomi capteur fuite d’eau
  • Ikea prise E1603/E1702
  • Ikea télécommande E1810
  • Ikea ampoule couleur LED1624G9 → reconnu avec fonctionnalités switch/light brightness, pas reconnu en tant que lumière, et pas d’option concernant le choix de couleur (mais il me semble que c’est une discussion en cours à plus haut niveau pour savoir comment gérer un color picker ?)

(J’aurais bientôt de nouveaux devices à tester, j’updaterai dès que possible)

Merci beaucoup pour ce service, ça va être top :smile:

PS : j’ai mis à jour les devices testés :wink:

2 « J'aime »

Je remonte un peu le topic pour avoir des infos.

Quel stick “clef-en-main” est utilisable ?