mardi 21 novembre 2017

Domotique: camera, mes choix !

En fait, je ne vais pas vous exposer toutes les solutions du marché cela serait trop voir impossible...

En fait, mon choix a été de me dire que je préfère multiplier le nombre et donc payer peu... même si j'ai acheté une par une pour tester ;-)

Donc je me suis tournée vers des solutions low costs avec des besoins simples et par priorité:

     1) avoir des images claires (voir HD ;-)

     2) pouvoir les consulter avec un smartphone (voir avec un PC en option).

    3) avoir la possibilité d'être alerté en cas de détection de mouvement (besoin de voir dans la nuit aussi dans ce cas)

    4) avoir la possibilité d’interagir avec ma domotique si possible (récupération d'image/vidéo, déclencher un scénario sur une detection de mouvement).

Donc mon premier choix a été une marque peu connu (depuis Xiaomi propose aussi des versions pas chers aussi) :

Zmodo ZM - SH75D001 Mini WiFi Camera:

Résultat de recherche d'images pour "zmodo"

J'avais acheté cela moins de 30€ (28.55€) à l'époque en November 2015 mais maintenant on l'a trouve au dessus de 35 € ici , on doit pouvoir la trouver moins cher :-). N'oublié pas de commander un adaptateur EU ici (mais il peut aussi être fourni, à voir ou à demander ;-)

Les plus :
- Facile à installer (pas de port à ouvrir ou firewall à bidouiller ;-)
- Application dédiée et rapide pour afficher les images même en 3G et en HD. (j'ai testé que iOS)
- Bonne qualité d'image.
- Sauvegarde des dernières alertes
- Notification des alertes.
- Detection de bruit
- Marche la nuit aussi ;-)
- Vraiment petite et discrète
- Fonction interphone ;-)

Les moins:
- Son moyen.
- Utilise le cloud :-(cela ne séduit pas tout le monde, moi inclu).
- Commande uniquement par l'app ou par un ocx dans IE :-(. Pas de commande possible pour Jeedom.
- Pas de flux http ou onvif donc pas intégrable facilement dans Jeedom ou un NAS mais j'ai un script pour prendre des photos et l'afficher dans Jeedom avec un taux de raffraichissement de 2 à 5 s.
Voici le script php qui va généré une image à chaque appel par le plugin camera de Jeedom:

//PHP Script permettant de faire un snapshot (qualité SD - PNG image data, 320 x 240, 8-bit/color RGB, non-interlaced) 
//de votre camera ZMODO HD 720P Wifi (ex: zm-sh75d001) et de retourner l'image pour le plug-in standard Jeedom
//il faudra bien mettre l'IP, PORT, URL dans le plug-in Camera Jeedom par rapport à votre configuration.
//Vous devez être de la même forme que celle sous votre navigateur internet:
// Ex: http://192.168.0.1/jeedom ou bien http://192.168.0.1:435/jeedom
//    -> Il faudra bien mettre dans l'URL du plug-in Camera: /jeedom/plugins/script/core/ressources/ZMODO_Snapshot_SD.php  
// ou encore http://192.168.0.1 ou encore http://192.168.0.1:2345
//   -> Il faudra bien mettre dans l'URL du plug-in Camera: /plugins/script/core/ressources/ZMODO_Snapshot_SD.php  
  
header('Content-Type: image/png');

//Il faudra aussi mettre votre IP locale de votre camera ZMODO
$IP_LOCAL_ZMODO = '192.168.0.XXX';
echo shell_exec('sudo rm /var/www/html/plugins/script/core/ressources/SD.png');
echo shell_exec('sudo echo -e "\x55\x55\xaa\xaa\x00\x00\x00\x00\x00\x00\x02\x90" | sudo netcat -w 2 ' . $IP_LOCAL_ZMODO .' 8000 | sudo avconv -i pipe:0 -q:v 1 -vframes 1 /var/www/html/plugins/script/core/ressources/SD.png');
$im = imagecreatefrompng("/var/www/html/plugins/script/core/ressources/SD.png");
imagepng($im);
imagedestroy($im);
?>
Qualité SD


//PHP Script permettant de faire un snapshot (qualité HD - PNG image data, 1280 x 720, 8-bit/color RGB, non-interlaced) //de votre camera ZMODO HD 720P Wifi (ex: zm-sh75d001) et de retourner l'image pour le plug-in standard Jeedom //il faudra bien mettre l'IP, PORT, URL dans le plug-in Camera Jeedom par rapport à votre configuration. //Vous devez être de la même forme que celle sous votre navigateur internet: // Ex: http://192.168.0.1/jeedom ou bien http://192.168.0.1:435/jeedom // -> Il faudra bien mettre dans l'URL du plug-in Camera: /jeedom/plugins/script/core/ressources/ZMODO_Snapshot_HD.php // ou encore http://192.168.0.1 ou encore http://192.168.0.1:2345 // -> Il faudra bien mettre dans l'URL du plug-in Camera: /plugins/script/core/ressources/ZMODO_Snapshot_HD.php header('Content-Type: image/png'); //Il faudra aussi mettre votre IP locale de votre camera ZMODO $IP_LOCAL_ZMODO = '192.168.0.XXX'; echo shell_exec('sudo rm /var/www/html/plugins/script/core/ressources/HD.png'); echo shell_exec('sudo echo -e "\x55\x55\xaa\xaa\x00\x00\x00\x00\x00\x00\x00\x50" | sudo netcat -w 2 ' . $IP_LOCAL_ZMODO .' 8000 | sudo avconv -i pipe:0 -q:v 1 -vframes 1 /var/www/html/plugins/script/core/ressources/HD.png'); $im = imagecreatefrompng("/var/www/html/plugins/script/core/ressources/HD.png"); imagepng($im); imagedestroy($im);
?>
Qualité HD
Configuration du plugin "Caméra"  dans Jeedom (rien de compliqué) :



Configuration d'utilisation des script dans Jeedom (rien de compliqué) :


Donc suite à ma première expérience, j'ai fait mon second choix avec une marque plus connue et plus éprouvée :


WANSCAM HW0049 WiFi:

WANSCAM HW0049 WiFi IP Camera Night Vision


 J'avais acheté cela moins de 20€ (€17.08) à l'époque en Avril 2017 mais maintenant on l'a trouve au dessus de 20 € ici , on doit pouvoir la trouver moins cher :-). N'oublié pas aussi de commander un adaptateur EU ici (mais il peut aussi être fourni, à voir ou à demander ;-) comme pour l'autre caméra.

Les plus :
- Bonne qualité d'image.
- Pas de cloud (donc pas d'image perso qui parte sur le net)
- Marche la nuit aussi ;-)
- Vraiment petite et discrète
- Flux/Commande http disponible donc intégrable super facilement dans le plugin caméra de Jeedom.
- Elle est motorisé, c'est sympa.
- On peut stocker image/vidéo sur microSD et c'est consultable par FTP.

Les moins:
- Pas d'application vraiment dédiée mais pas forcement rapide pour afficher les images. (j'ai testé que iOS avec l'appli E-View 7 qui est conseillé par le fabricant)
- Son moyen.
- Notification des alertes/mouvements possible mais j'ai du mal à le faire fonctionner. il faut bidouiller.
- Pas de Fonction interphone ou j'ai pas trouvé :-(
- Pas de Detection de bruit... je crois.

Voici ma configuration dans jeedom de l'équipement :



Ainsi que les commandes HTTP, que j'avais adapté mais maintenant le plugin donne aussi des commandes par défaut, dites moi si vous avez besoin que je vous liste les commandes pour les avoir pour vous aussi ;-)



CONCLUSION:
C'est pas facile et je n'ai pas encore trouvé la caméra idéale mais pour Jeedom, je trouve la Wanscam HW0049 pas mal pour commencer même si je dois voir comment je peux résoudre le problème des alertes (j'ai l'impression que la caméra détecte trop de changement de lumière ou de changement de couleur)
Donc si j'avais un conseil à vous donner, allez voir les Wanscam. De plus, On trouve de super tuto ici par exemple avec aussi des infos sur les apis ici.

Bon courage ;-)


vendredi 26 mai 2017

Domotique: les protocoles ! Comment choisir ?

En fait, je vais vraiment vous donner mon expérience sur les protocoles que j'ai déjà expérimenté en domotique et sur ces 4 dernières années. Je ne vais pas vous parlez des protocoles que j'ai jamais utilisé parce que la théorie n'est pas suffisant :-( c'est le message le plus important qu'il faudra retenir malheureusement. La configuration de votre appartement ou maison change l'intérêt et les usages possibles de chaque protocole. Je sais c'est pas trés positifs :-( mais c'est ainsi. En fait, j'ai l'impression qu'en fait, j'ai presque un protocole par type de besoin :-(. Donc le protocole pour tout les usages n'existe pas... C'est pour cela que j'ai aussi fini par choisir d'aller vers des solutions adaptables et multi-protocoles comme jeedom :-).

2 grandes familles qui s'opposent

Il y a  les protocoles basés sur la communication RF (radio-fréquence) mais aussi il ne faut pas oublier ce qui existe aussi en communication Filaire.

En filaire:


Résultat de recherche d'images pour "fil"

Généralement, on va s'en servir pour récupérer un contact ouvert ou fermé, commander un relai ou lire une donnée comme la température, l'humidité, etc...

Usage (les miens ;-): lecture de température, commande de relai (et à terme aussi pour faire de la lecture de contact d'ouverture pour l'alarme), communication avec des appareils connectés au réseau local.

Les protocoles de communication utilisés (pour mes usages):

J'en utilise que 3 principalement parce que cela suffit à mes besoins pour l'instant. Mais je pense que c'est les plus pratique à ce jour pour faire du "Do It Yourself".

Il y donc :
- Réseau Ethernet (IP): protocole que l'on utilise pour notre informatique généralement mais qui finalement maintenant peut être utiliser avec nos appareils "domotisables" branchés sur le réseau local de l'habitation et pouvant servir à se connecter à terme à Internet (via l'ADSL, le câble, etc..).
Résultat de recherche d'images pour "réseau IP"


1-Wire: protocol de bus simple sur "1 fil" où on peut y mettre facilement des composants pour la prise de température (DS18B20), détection d'ouverture (DS2401), etc...
Câblage d'un capteur DS18B20


    - GPIO (General Purpose Input/Output) du RaspBerryPi ou de l'ESP8266. C'est pas un protocol vraiment mais c'est une usage répandu ! Justement on utilise le GPIO pour communiquer avec le Bus 1-Wire par exemple.
Résultat de recherche d'images pour "gpio raspberry pi 3"

Résultat de recherche d'images pour "nodemcu"


Les plus:
- La robustesse: pas de perte de signal comme en RF même si on peut aussi avoir des interférences)
- Les coûts: techno simple, pas de pile à changer.
- Très large bande passante pour l'ethernet.


Les moins:
- Besoin de passer des fils: difficilement discret, difficile à changer de place.
- Applicable dans un garage ou sous-sol voir au rez de chaussé d'une maison avec sous-sol peut être mais plus difficile pour monter au 1er d'une maison sans impact sur les murs si votre "datacenter" ;-) est dans le sous-sol comme moi.


En RF (on parle aussi de sans-fil):



Résultat de recherche d'images pour "antenne"


C'est ce qui se fait le plus maintenant, c'est la mode ;-). On peut s'en servir pour tous.. commande d'ampoule, prise, d'interrupteur, volets, détection d'ouverture, mouvement, relevé température, humidité, qualité de l'aire, commande télévision, etc... pas vraiment de limite en fait...

Usage (les miens ;-): Commande de la lumière, des interrupteurs, détection de mouvement, détection d'ouverture, flux vidéos camera IP, utilisation de module IoT comme l'ESP8266, détection de présence d'appareil mobile (mais pas forcement que des téléphones).

Les protocoles de communication utilisés (pour mes usages):

Attention, dans mon cas, ils sont multiples parce que j'ai voulu tester mais finalement, je n'ai pas réussi à en choisir un seul...

Réseau Wifi (IP): 
Protocole le plus répandu dans les foyers parce que fourni par nos box et routeurs Wifi qui est finalement commun avec le réseau Ethernet local de l'habitation. Mais c'est applicable surtout pour les appareils branchés sur le secteur ou possédant des batteries rechargés régulièrement comme pour les téléphones portables.



Les plus:
- Disponible pour le plus grand nombre.
- Installation des appareils dans le réseau.
- Large bande passante (moindre que l'Ethernet).
- Pratique pour détecter un appareil mobile ou fixe connecté sur le réseau par son adresse IP ou Mac.
- Accès à des APIs "riches": DLNA, Bonjour, AirPlay, Chromcast, Service Internet, API HTTP/REST, ...
- De plus en plus utilisé dans les "IoT" comme les stations météos, prise commandée, ampoule,etc..
- Bonne portée (si on a un bon routeur ou si il est bien placé dans l'habitation ;-).
- Retour d'état possible.

Les moins:
- Sécurité dépendante de celle du réseau Wifi. Brouillage possible.
- Consommation d’énergie important, pas applicable à des appareils sur pile non changeable régulièrement.
- La multiplication des appareils Wifi peut engendrer des problèmes d'interférence, de débit et de disponibilité du réseau Wifi. Demande dans certains cas d'avoir des réseaux wifi dédiés et multipliés pour fournir un bon niveau de service.


Bluetooth:
C'est le concurrent direct du Wifi parce que disponible aussi dans les appareils mobiles comme les téléphones portables mais qui finalement ne fonctionne pas forcement avec un réseau IP comme ethernet et wifi.



Les plus:

- Disponible pour le plus grand nombre (surtout dans les téléphones portables).
- Consommation réduite (mais pas plus de 6 mois sur batterie généralement)
- Bande passante acceptable (surtout pour la musique)
- Pratique pour détecter un appareil mobile sans qu'il soit connecté à un réseau IP.
- "Bluetooth Advertisement" permet d'aller plus loin et faire de la détection de présence.
- Retour d'état possible.

Les moins:
- Sécurité relative. Brouillage possible.
- L’appairage Bluetooth est pratique mais finalement oblige à être lié à un seul device dans certains cas.
- Peut de service disponible en bluetooth (rare sont les APIs en fait).
- Portée limitée qui explique que les capteurs et actionneurs bluetooth se font rare même si avec Homekit (solution Apple), des fabricants (comme Fibaro ou Eve) commencent à sortir des appareils. Des répéteurs bluetooth sont envisageables.

Z-Wave:
C'est un des protocoles les plus répandu en domotique et surtout en Europe. C'est un protocole qui a été fait spécialement pour répondre au besoin d'installation d'appareils pour les habitations.
C'est un standard controllé et licencié. Beaucoup de box du marché sont basées sur ce protocole (eedomus, zibase, fibaro, jeedom center, orange, etc..) même si en générale elle supporte aussi 1 ou 2 autres protocoles en plus.



Les plus:
- Beaucoup d'appareils sont Z-wave maintenant (même des electro-vannes, vannes thermostatiques, prise commandées, sirènes, capteurs en tout genre, etc..). Standard bien respecté et maitrisé.
- Consommation très réduite (marche sur batterie entre 6 mois à 1 ans au mieux)
- Retour d'état implémenté dans le protocole.
- Protocole sécurisé en comparaison de certains autres protocoles en 868 Mhz ou en 433 Mhz.


Les moins
- Prix (entre 50-60€ pour la plupart !)
- Bande passante réduit, pas fait pour communiquer de grandes quantités de Data.
- Inclusion/Exclusion des appareils complexes au premier abords, pas toujours simple :-(.
- A cause de la sécurité, l'appareil n'est lié qu'à la box domotique et une seule (clustering actif/actif de la box difficile voir impossible si on ne passe pas par une gateway).
- Portée finalement limitée, les portées constatées chez moi (maison en brique) sont aux alentours de 8-10 m en intérieur en utilisant un dongle usb sur un raspberry pi. J'utilise des prises connectés sur secteur qui dans ce cas font répéteur Z-Wave pour fiabiliser le signal.

Zigbee:
C'est le deuxième protocole le plus répandu aussi en domotique, mais plus au US ou en Asie. C'est un protocole aussi qui a été fait spécialement pour répondre au besoin d'installation d'appareils pour les habitations.
C'est un standard plus ouvert que le Z-Wave. Des box ou gateway du marché sont basées aussi sur ce protocol (Philips hue, ampoule ikea, xiaomi home, etc..).

Les plus:
- Beaucoup d'appareils sont Zigbee aussi maintenant, c'est le concurrent du Z-Wave ;-)
- Consommation réduite, peut être un peu moins bon que le z-wave  (marche sur batterie 6 mois mais peut être pas un an)
- Retour d'état implémenté dans le protocole.
- Portée semble meilleure que le Z-Wave, on est en 2,4 Ghz !
- Pas vraiment d'Inclusion/Exclusion comme le Z-Wave, c'est pas plus mal ;-).
- Prix par rapport au Z-Wave (on trouve des devices avec gateway chinoise pas cher, Xiaomi Home pour ne pas la citer -> 10 fois moins cher pour certains capteurs !!! ;-)

Les moins:
- Besoin de passer par une gateway dans le cas du Zigbee, pas de solution facile par dongle usb, mais c'est peut être pas plus mal ;-).
- Protocole qui peut être compatible entre les marques mais ce n'est pas aussi bien maitrisé que le z-wave.
- Faille de sécurité connu. (pas forcement corrigé par les constructeurs).


Bluetooth:
C'est le concurrent direct du Wifi parce que disponible aussi dans les appareils mobiles comme les téléphones portables mais qui finalement ne fonctionne pas forcement avec un réseau IP comme ethernet et wifi.



Les plus:

- Disponible pour le plus grand nombre (surtout dans les téléphones portables).
- Consommation réduite (mais pas plus de 6 mois sur batterie généralement)
- Bande passante acceptable (surtout pour la musique)
- Pratique pour détecter un appareil mobile sans qu'il soit connecté à un réseau IP.
- "Bluetooth Advertisement" permet d'aller plus loin et faire de la détection de présence.
- Retour d'état possible.

Les moins:
- Sécurité relative. Brouillage possible.
- L’appairage Bluetooth est pratique mais finalement oblige à être lié à un seul device dans certains cas.
- Peut de service disponible en bluetooth (rare sont les APIs en fait).
- Portée limitée qui explique que les capteurs et actionneurs bluetooth se font rare même si avec Homekit (solution Apple), des fabricants (comme Fibaro ou Eve) commencent à sortir des appareils. Des répéteurs bluetooth sont envisageables.

433 Mhz :
C'est un des protocoles les plus anciens utilisé en radio-fréquence et en domotique/alarme et  le 868 Mhz (que je n'utilise pas encore à ce jour).
Il y a plusieurs déclinaisons finalement supporter par les marques comme Chacon, DIO, etc...
Dans mon cas, j'ai utilisé essentiellement du chacon ou DIO pour des prises commandés, des modules d'intérrupteurs et j'ai prévu aussi de l'utiliser pour des capteurs basics de detection de mouvement ou d'ouverture.




Les plus:
- Prix, vraiment peu cher par rapport à certains module Wifi ou Z-Wave du marché.
- Beaucoup d'appareils sont en 433Mhz (prise commandées, modules d’interrupteur, capteurs de mouvement, ouverture).
- On peut facilement et à moindre cout avoir un recepteur et un emetteur 433 Mhz pluggé à un Raspberry Pi.
- Portée finalement bonne si on y mets le prix en terme d'électronique. Mais on peut faire du bon DIY à moins de 10€ et pas forcement acheter les modules tout fait à 100€ comme le RFXCOM !

Les moins
- Bande passante réduit, pas fait pour communiquer de grandes quantités de Data.
- Pas de sécurité :-(facilement "espionnable" et reproductible).
- Pas de retour d'état :-( dans la plus part des cas pour la commande de prise ou d’interrupteur :-(


La conclusion:


On n'a pas tout vu, je n'ai pas parlé des nouveaux protocoles comme l'EnOCean ou d'autre plus anciens comme le X10 parce que je n'ai pas d'expérience...

Pourquoi je jure que par l'expérience ??? Parce que j'ai eu des mauvaises surprises comme pour le Z-Wave où finalement c'est pas le protocole parfait que certains mettaient sur un piédestal !

Finalement, j'ai l'impression que les solutions multi-protocoles restent les meilleurs pour  la domotique "fait maison" parce qu'ainsi on a le plus large choix des appareils et du prix en fonction de nos besoins. Cela me confirme que le choix Jeedom peut m'aider dans ce sens ;-).





mercredi 8 mars 2017

Domotique: Présence et Localisation

Comme vous l'avez compris, j'utilise Jeedom pour ma domotique mais la problématique que je vais expliquer dans cet article est générale quand on veut faire de détection de présence d'une personne connue avec notre domotique (je précise "connue" parce que pour de la détection de présence d’intrus/inconnu, c'est presque plus simple et cela reste du domaine de l'alarme ;-).

Il y a plusieurs solutions en fait que j'ai déjà investigué et expérimenté. Et finalement, la conclusion est simple... il faut considérer plusieurs technologies et de les intégrer ensemble pour un meilleur résultat. (ex: bluetooth + wifi + geo-fencing)

Dans Jeedom, on a plusieurs outils pour intégrer. On peut utiliser des scripts, des scénarios ou des plugins.


Les scripts :
     - Cela permet surtout d'avoir des fonctions unitaires bas niveau proche du système où l'on peut rapidement intégrer dans nos scénarios. Cela reste compliqué dans certains cas pour les droits d'accès mais cela permet de ne pas avoir de limite et on trouve beaucoup de chose sur internet à base de script bash, python, php, perl, etc...




Les scénarios:
    - Cela permet finalement de faire le lien avec les objets/script/plugin déclarer dans Jeedom pour faire des actions spécifiques et c'est un des points forts de Jeedom. On peut gérer des variables, déclencher des actions en fonction de changement d'état ou en fonction d'une expression cron pour déclencher de manière régulière par minutes, jour, semaine, etc..


Les Plugins:
    -  Point fort aussi ;-), Cela permet d'avoir des fonctions très spécifiques pour intégrer les objets et aussi pour faciliter certains traitement qui serait aussi compliquer par un simple scénario.




Donc pour commencer, la localisation:
      J'avais donc utilisé pour commencer des plugins comme "geoloc" ou "geoloc_ios".


Mais la conclusion était que cela pouvais fonctionner mais cela me posait des problèmes de consommations de batteries mêmes en réduisant la fréquence de rafraichissement, dommage :-(.
De plus sur iOS, c'était dépendant du iCloud d'Apple qui change ses APIs régulièrement :-(. Sur Android, il faudrait réessayer surement, on peut peut être réduire ou mieux gérer la consommation de la batterie mais je ne suis pas le seul à avoir constater des problèmes de consommation de batterie et cela sur tout les OS.

J'ai donc découvert le "geo-fencing", le geo-fencing est à l'origine fait pour le marketing geolocalisé mais on peut aussi l'utiliser pour nous ;-).
Le principe est que l'on défini une zone et en fonction de la sortie ou l'entrée dans cette zone le téléphone prend la décision de faire une action.
Dans notre cas, avec Jeedom, on va envoyer une commande HTTP à Jeedom à chaque fois que l'on rentre ou sort d'une zone.
J'ai expérimenté surtout sur iOS mais je pense que sur Android on a la même chose (je ferais un update de l'article par la suite ;-).
Donc pour iOS, j'utilise "Locative" (https://itunes.apple.com/fr/app/locative/id725198453?mt=8)





Mais il faut installer l'app sur chaque téléphone.
J'ai donc créé une zone autour de chez moi et de mon boulot ainsi que celui de ma femme, ainsi on peux savoir quand ma femme ou moi-même arrivons ou partons de la maison ou quand on part ou arrive du boulot. Ainsi, on peut diriger un scénario ou un plugin avec une commande HTTP/HTTPS vers Jeedom.

Dans mon cas, j'ai envoyé une commande à mon plugin présence :



Pour atteindre un plugin, l'url est de ce type en http ou https (conseillé mais besoin d'avoir un certificat SSL sur votre Jeedom):
https://11.222.33.444/core/api/jeeApi.php?apikey=kdjflsdkfghskliksjgklsj&type=cmd&id=158

On trouve l'URL dans le plugin "Présence" dans votre Jeedom que vous aurait installé.

Il faut choisir la roue cranté (entouré d'un carré rouge dans mon screenshot) pour la personne ou l'objet que l'on track:


puis choisir le "mode" que l'on veut sélectionner par la roue cranté qui va bien (sur cette exemple, dans la case rouge, je veux le cas où ma femme est "présent") :


puis il faudra ensuite récupérer la valeur de l'url comme j'ai entouré en rouge sur mon screenshot:



 Ainsi vous allez pouvoir demander à Locative d'envoyer la bonne URL pour commander le plugin "Présence" en fonction si vous sortez ou entrez dans une zone.

Petite astuce: j'ai finalement défini  une zone pour gérer l'arrivé à la maison et une zone pour gérer le départ de la maison. Pourquoi ? pour éviter les variations de la position GPS et ainsi ne pas avoir de mauvais effets de bords avec les notifications (j'utilise pushbullet dans mon cas).


Donc la zone de départ (rayon de 200m) est plus grande que la zone d'arrivée (rayon de 50m). Ainsi quand vous êtes à la maison avec une mauvaise reception GPS, le système ne va pas être sensible au faite que vous pouvez être localisé à plus de 100 mètres de chez vous à cause de la triangulation GSM ;-). Je fais ainsi depuis plusieurs mois, et j'en suis super content.

Pour gérer la présence, vous pouvez aussi complémentez comme je le disais avec le wifi:
Dans ce cas, vous devez faire attention au fait que le téléphone ou autre appareil peut se mettre en veille voir même s'éteindre et donc le wifi peut disparaitre même si la personne est toujours présente.
On peut contourner en regardant cela que dans certaines plages horaires ou en notifiant qu'une fois par période longue de plusieurs heures. Vous pouvez aussi le jumeler à un capteur de présence/mouvement et/ou un capteur d'ouverture de porte, mais le scénario est de plus en plus complexe et j'ai finalement choisi le geo-fencing parce que pas assez fiable finalement (par exemple: quelqu'un peut couper son wifi et là, c'est le drame !!!)

Si vous ne pouvez pas utiliser le GPS ou le wifi, comme pour un chien ou un gosse qui n'a pas encore de mobile ;-), il y a aussi le bluetooth mais il faudra investir dans une clé bluetooth pour votre raspberry pi, comme celui-ci: Mini-USB-Bluetooth-V4



Dans mon cas, j'ai commencé d'experimenter le bluetooth avec mes téléphones mais cela n'était pas vraiment mon besoin, mais voici le script que j'utilise pour le Bluetooth que j'appel ainsi dans Jeedom avec la mac adresse en paramètre, exemple: presenceBT.py 11:22:33:44:55:66


#!/usr/bin/python

# need to install that previously:
# sudo apt-get install bluetooth bluez bluez-utils bluez-alsa
# sudo apt-get install python-bluez


import bluetooth
import time
import sys

for arg in sys.argv:
    #TO GET LAST PARAMETER AS MAC ADDRESS of BLUETOOTH DEVICE TO CHECK PRESENCE
    BTaddress_mac = arg
    
result = bluetooth.lookup_name(BTaddress_mac, timeout=5)
if (result != None):
    print "1"
else:
    print "0"

Regardez bien mes commentaires au début du script pour voir ce que vous devez installer avant toutes choses en terme de librairies linux.

Et donc si on n'a pas de téléphone, il y a les tags, j'ai donc testé les iTags que l'on peut trouver ici: iTag

Pour cela, on a un nouveau plugin Jeedom qui est super ! c'est "BLEA" :




Ce plugin permet d'avoir la présence mais on peut aussi aller plus loin jusqu'à faire de la triangulation en rajoutant des antennes bluetooth, c'est énorme ;-). Je vous propose d'aller voir les tutos du développeur sur son propre blog ;-): 
et

Donc voilà, vous avez une vue d'ensemble de mon expérience sur le sujet.






lundi 6 mars 2017

Domotique: script pour plex

Je ne sais pas si vous connaissez plex mais moi j'utilise pour mes films et séries. C'est du tonnerre. J'ai eu donc besoin de savoir quel film était en lecture a tout moment (pour surveiller l'usage, il faut avouer ;-) Donc j'ai cherché un script et j'ai fini par utiliser celui-ci que j'ai testé avec succès sous jeedom. Comme vous le verrez surement c'est un script Python Domoticz à l'origine que j'ai adapté. Le voici: enjoy ! (depuis l'update le script ne ressemble plus du tout à celui de Domoticz)

Mise à jour du 26/05/2017: j'ai mis à jour le script parce que Plex demande maintenant un token pour faire cela et utilise votre login/password plex en plus.Il faudra changer dans le script comme l'adresse ip voir le port si vous serveur en utilise un autre que celui en 32400.


#!/usr/bin/python
import urllib, urllib2, hashlib
import httplib, base64
import json
import sys

#config plex url (à modifier pour vos besoins ;-)
plexURL          = '192.168.0.XXX:32400' #base url (default port = 32400)
username = "votre login a mettre ici"
password = "votre password a mettre ici"

base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
txdata = ""

headers={'Authorization': "Basic %s" % base64string,
                'X-Plex-Client-Identifier': "Test script",
                'X-Plex-Product': "Test script 356546545",
                'X-Plex-Version': "0.001"}

conn = httplib.HTTPSConnection("plex.tv")
conn.request("POST","/users/sign_in.json",txdata,headers)
response = conn.getresponse()
resp = json.load(response);

#extract an element in the response
plexToken = resp["user"]["authToken"]
conn.close()

#building url
requestURL = 'http://'+plexURL+'/status/sessions?X-Plex-Token='+plexToken

from xml.etree import ElementTree as ET

try:
  #call session url
  test = urllib.urlopen(requestURL).read()
  root = ET.XML(test)
  videotitle = root.find('Video').attrib['title']
  print videotitle.encode('utf8')
except Exception:
  print 'N/A'
  pass

Et dans jeedom je l'ai intégré ainsi pour la partie script: (cliquez sur l'image pour zoomer)


Puis dans la partie scénario et avec l'aide de pushbullet (plugin pour recevoir des notification:
(cliquez sur l'image pour zoomer)



Et voilà, j'ai juste voulu partager cela avec vous parce que c'est vraiment sympa surtout pour ceux qui utilise Plex. Pour plus d'info sur plex, allez voir ici: https://www.plex.tv/fr/

Domotique: oups j'ai oublié un truc

Je vous ai parlé de code mais j'ai oublié de parler de l'IDE.

En fait, j'utilise ESPExplorer, pour charger le lua et compiler en .lc quand c'est nécessaire.


Vous la trouverez ici: https://esp8266.ru/esplorer/

Domotique: un peu beaucoup de code lua ;-)

Bon... aujourd'hui on va parler de code (je vais tout vous mettre ;-), je vais vous partager ce que j'utilise pour mon code .lua dans le NodeMCU.

Tout d'abord je dois dire ce que je fais avec ;-)
Mon but: avoir un composant wifi utilisable avec Jeedom pouvant piloter un relais, lire la température avec un ds18b20 (utilisant le protocol "one-wire"), lire le courant consommé (utilisant une petite pince ampèremétrique), vérifier la présence avec un capteur PIR (Passive Infrared Sensor) et lire une commande comme un interrupteur. Et pour finir, j'ai décider de faire un code commun pour la maintenance.
De plus, mon but est de pouvoir mettre cela dans une boite encastrable dans un mur pour par exemple être au dessus d'un bouton existant et ainsi le commander (avec retour d'état). Je metterais des photos plus tard ;-)

Donc dans le nodeMCU, j'ai organisé ainsi :

1) Avec le init.lua qui me sert juste à lancer la config du node, la config du wifi et du "main.lc" (version compilé du .lua pour gagner de la place) avec la possibilité de faire du telnet en option pour avoir un accès remote au code du nodemcu mais c'est encore de l'expérimentale ;-) :

-- init.lua --

-- Network Variables
--list files in NODEMCU
l = file.list();
    for k,v in pairs(l) do
      --print("name:"..k..", size:"..v)
      --print(string.find(k, "_conf.lua", 1))
      if((string.find(k, "_conf.lua", 1) ~= nil) and (string.find(k, "wifi_node", 1) ~= nil))then
        -- Load conf Jeedom
        --print("load file:"..string.sub(k, 1,string.find(k, ".lua", 1)-1));
        require(string.sub(k, 1,string.find(k, ".lua", 1)-1));
      end
    end

-- Mode Variables ("telnet" or "web")
require("mode_conf"); 

-- Configure Wireless Internet
wifi.setmode(wifi.STATION);
--print('set mode=STATION (mode='..wifi.getmode()..')\n')
--print('MAC Address: ',wifi.sta.getmac())
--print('Chip ID: ',node.chipid())
--print('Heap Size: ',node.heap(),'\n')

-- Configure WiFi
wifi.sta.config(ssid,pass);

tmr.alarm(0, 1000, 1, function() 
   if wifi.sta.getip()==nil then
      print("Connect AP, Waiting...") 
   else
      print("Wifi AP connected. IP:")
      print(wifi.sta.getip())
      tmr.stop(0)
      if(telnet_server_mode == "true")then
      -- Load telnet server
        dofile("telnet.lc");
      else
      -- Load main
        dofile("main.lc");
      end
   end
end)

2) avec le configuration wifi dans un fichier dédié pour gérer plusieurs nodes par la suite :
    (moi je les mets en IP fixe à partir de ma freebox pour ne pas avoir de soucis et en fonction de leur adresse Mac) - wifi_nodeX_conf.lua (X étant le numéro de votre node sur le réseau, juste si vous voulez utiliser des points wifi différent ;-)

-- config wifi
ssid = "votre ssid à mettre ici"
pass = "et le password ici bien sur ;-)"

2 bis) avec le mode choisi (pour faire du telnet ou pas) - mode_conf.lua


telnet_server_mode = "false"; -- to activate "telnet" server when necessary (11/05/2015) because only one TCP server supported on NodeMCU firmware

3) et avant de parler du principal, voici aussi le code du telnet.lua à tester ;-) parce que encore expérimentale comme je l'ai déjà dis (qu'il faudra aussi compiler en .lc):


print("====a LUA console over wifi.==========")
print("Telnet Server starting ......")

   sv=net.createServer(net.TCP, 180)
   sv:listen(8080,   function(conn)
      print("Wifi console connected.")
   
      function s_output(str)
         if (conn~=nil)    then
            conn:send(str)
         end
      end
      node.output(s_output,0)

      conn:on("receive", function(conn, pl) 
         node.input(pl) 
         if (conn==nil)    then 
            print("conn is nil.") 
         end
      end)
      conn:on("disconnection",function(conn) 
         node.output(nil) 
      end)
   end)   
   print("Telnet Server running at :8080")
   print("===Now,Using ESPlorer and input LUA.====")

4) et donc un main.lua (qu'il faudra compiler en .lc) où l'on retrouve le serveur web que je peux interroger en http mais aussi des commandes qui peuvent être envoyé vers jeedom :

version = "v0.0.8";

-- global variables
SendingData = false;
--

-- global functions
function sendDataToVirtual (id,state)
            if SendingData then  -- don't allow new sending data during process of sending data
                return
            else 
                SendingData = true
            end
            --print("id: "..id);
            --print("state: "..state);
            -- A simple http client -> to send last/new state to jeedom
            if(httpreq == nil) then
            --print("initial create connection"); 
              httpreq=net.createConnection(net.TCP, false);
            else
            --print("connect close"); 
              httpreq:close();
              collectgarbage();
              --print("create connection"); 
              httpreq=net.createConnection(net.TCP, false);
            end 
            httpreq:on("receive", function(httpreq, pl) 
            --print(pl) 
            end)
            --print("connect connection"); 
            httpreq:connect(80,jeedom_ip)
            httpreq:send("GET /jeedom/core/api/jeeApi.php?apikey="..api_key
            .."&type=virtual&id="..id
            .."&value="..state
            .." HTTP/1.1\r\nHost: "..jeedom_ip
            .."\r\n".."Connection: keep-alive\r\nAccept: */*\r\n\r\n")
            SendingData = false;
end

function Sleep(delay)
     local start= tmr.time();
     while tmr.time() - start < delay do end
end
--

--list files in NODEMCU
l = file.list();
    for k,v in pairs(l) do
      --print("name:"..k..", size:"..v)
      --print(string.find(k, "_conf.lua", 1))
      if((string.find(k, "_conf.lua", 1) ~= nil) and (string.find(k, "node", 1) ~= nil))then
        -- Load conf Jeedom
        --print("load file:"..string.sub(k, 1,string.find(k, ".lua", 1)-1));
        require(string.sub(k, 1,string.find(k, ".lua", 1)-1));
      end
    end
-- for check of conf:
 --print("jeedom_ip:"..jeedom_ip)
 --print("api_key:"..api_key)
 --print("jeedom_virtual_relay_id:"..jeedom_virtual_relay_id)
 --print("jeedom_virtual_pir_id:"..jeedom_virtual_pir_id)

-- led of Wemos D1 Mini on D4 (GPIO2)
if(wemos_led ~= nil) then
  gpio.mode(wemos_led, gpio.OUTPUT);
end
--

-- relay command on D1 (GPIO5)
if(relay1 ~= nil) then
  gpio.mode(relay1,gpio.OUTPUT);
end
--

-- switch 
if(switch1 ~= nil) then
  inInt = false;
  --Send initial state after reboot
  sendDataToVirtual (jeedom_virtual_relay_id, "0");
  --
  
  gpio.mode(switch1,gpio.INPUT,gpio.PULLUP);
  gpio.trig(switch1, "both", function(level)
    if inInt then                   -- don't allow interrupt in interrupt
        return
    else 
        inInt = true
    end
    tmr.delay(100000)               -- 100ms debounce
    if(gpio.read(relay1) == 0)then
      gpio.write(relay1, gpio.HIGH)
      localnewstate = 1
    else
       gpio.write(relay1, gpio.LOW)
       localnewstate = 0
    end
    sendDataToVirtual (jeedom_virtual_relay_id, localnewstate);
    inInt = false                   -- all done, allow interrupts again
 end)
end
--

-- pir 
if(pir1 ~= nil) then
  inIntMotion = false;
  gpio.mode(pir1,gpio.INT,gpio.FLOAT);
  gpio.trig(pir1, "both", function(level)
    if inIntMotion then                   -- don't allow interrupt in interrupt
        return
    else 
        inIntMotion = true
    end
    PirNewstate = gpio.read(pir1);
    tmr.delay(100000)               -- 100ms debounce

    sendDataToVirtual (jeedom_virtual_pir_id, PirNewstate);
 
    inIntMotion = false                   -- all done, allow interrupts again
 end)
--print("pir state:"..gpio.read(pir1));
end
--

-- DS18B20 reading on D4 (GPIO2)
if(OneWirePin ~= nil) then
  -- setup to read temperature
  t = require("ds18b20")
  t.setup(OneWirePin)
  --addrs = t.addrs()
  --if (addrs ~= nil) then
  --   print("Total DS18B20 sensors: "..table.getn(addrs))
  --end
end
--

-- MCP3008 library loading (D5 to D8 is allocated in all cases).
if(MCP3008 ~= nil) then
  -- setup
  require("MCP3008")
end
--

-- CTSensor library loading
if(CTSensor ~= nil) then
  -- setup
  require("CTSensor")
end
--

-- create web server
srv=net.createServer(net.TCP)
srv:listen(80,function(conn)
    conn:on("receive", function(client,request)
        local buf = "";
        local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
        if(method == nil)then
            _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");
        end
        local _GET = {}
        if (vars ~= nil)then
            for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do
                _GET[k] = v
            end
        end
        --print(_GET.pin);
        --print(_GET.state);
        -- to read GPIO
        buf = "<!DOCTYPE HTML>\n";
        buf = buf.."<html>\n";

     if(_GET.state ~= nil)then
         if((_GET.state == "relay1") and (relay1 ~=nil))then
            buf = buf.."<div>"..gpio.read(relay1).."</div>".."\n";
         elseif((_GET.state == "switch1") and (switch1 ~=nil))then
            buf = buf..gpio.read(switch1);
         elseif((_GET.state == "pir1") and (pir1 ~=nil))then
            buf = buf..gpio.read(pir1);       
         elseif((_GET.state == "temp1") and (OneWirePin ~=nil))then
            if(t == nil) then
              -- setup to read temperature
              t = require("ds18b20")
              t.setup(OneWirePin)
            end   
            temperature = t.read();
            if(temperature ~=nil)then
              buf = buf.."<div>"..temperature.."</div>".."\n";
              --buf = buf..temperature.."\n";
            end
         elseif((string.find(_GET.state,"analog") ~= nil) and (MCP3008 ~=nil))then
            channel = tonumber(string.sub(_GET.state,7));
            --print("Debug: Channel value found:"..tostring(channel));
            analogvalue = readMCP3008(channel);
            if(analogvalue ~=nil)then
                buf = buf.."<div>"..analogvalue.."</div>".."\n";
            end
         elseif((string.find(_GET.state,"power") ~= nil) and (MCP3008 ~=nil) and (CTSensor ~=nil))then
            channel = tonumber(string.sub(_GET.state,6));
            --print("Debug: Channel value found:"..tostring(channel));
            power = getPower(channel);
            if(power ~=nil)then
                buf = buf.."<div>"..power.."</div>".."\n";
            end
         end      
      end
      if(_GET.pin ~=nil)then
         -- else write GPIO
        if((_GET.pin == "wemosledon") and (wemos_led ~=nil))then
            gpio.write(wemos_led, gpio.HIGH);
            buf = buf.."1";
        elseif((_GET.pin == "wemosledoff") and (wemos_led ~=nil))then
            gpio.write(wemos_led, gpio.LOW);
            buf = buf.."0";
        elseif((_GET.pin == "relay1on") and (relay1 ~=nil))then
            gpio.write(relay1, gpio.HIGH);
            buf = buf.."1";
            newstate=gpio.read(relay1);
            sendDataToVirtual (jeedom_virtual_relay_id, newstate);
        elseif((_GET.pin == "relay1off") and (relay1 ~=nil))then
            gpio.write(relay1, gpio.LOW);
            buf = buf.."0";
            newstate=gpio.read(relay1);
            sendDataToVirtual (jeedom_virtual_relay_id, newstate);
        end
      end
        -- display web page or not 
        if(web_server_ui == "true")then
            buf = buf.."<head><meta charset=\"UTF-8\"><title>My ESP8266 "..version.."</title></head>\n";
            buf = buf.."<body>\n";
            
            -- to display full web page
            buf = buf.."<h1> ESP8266 Web Server</h1>";
            if(wemos_led ~= nil) then
                buf = buf.."<p>GPIO2 (D4) wemos led   <a href=\"?pin=wemosledoff\"><button>ON</button></a>&nbsp;<a href=\"?pin=wemosledon\"><button>OFF</button></a>";
                buf = buf.." status: "..gpio.read(wemos_led).."</p>\n";
            end
            if(relay1 ~= nil) then
                buf = buf.."<p>GPIO5 (D1) relai <a href=\"?pin=relay1on\"><button>ON</button></a>&nbsp;<a href=\"?pin=relay1off\"><button>OFF</button></a>";
                buf = buf.." status: "..gpio.read(relay1).."</p>\n";
            end    
            if(pir1 ~= nil) then
                buf = buf.."<p>GPIO4 (D2) pir";
                buf = buf.." status: "..gpio.read(pir1).."</p>\n";
            end
            if(switch1 ~= nil) then
                buf = buf.."<p>GPIO0 (D3) switch";
                buf = buf.." status: "..gpio.read(switch1).."</p>\n";
            end
            -- Just read temperature
            --print("Temperature: "..t.read().."'C")
            if(OneWirePin ~= nil) then
                buf = buf.."<p>GPIO2 (D4) OneWire";
                buf = buf.." status: "..t.read().."°C</p>\n";
            end
            if(MCP3008 ~= nil) then
                buf = buf.."<p>GPIO? (D6) MCP3008";
                buf = buf.." status: "..readMCP3008(0).."</p>\n";
                buf = buf.." status: "..readMCP3008(1).."</p>\n";
                buf = buf.." status: "..readMCP3008(2).."</p>\n";
                buf = buf.." status: "..readMCP3008(3).."</p>\n";
                buf = buf.." status: "..readMCP3008(4).."</p>\n";
                buf = buf.." status: "..readMCP3008(5).."</p>\n";
                buf = buf.." status: "..readMCP3008(6).."</p>\n";
                buf = buf.." status: "..readMCP3008(7).."</p>\n"; 
            end
            -- Don't forget to release it after use
            --t = nil
            --ds18b20 = nil
            --package.loaded["ds18b20"]=nil
            buf = buf.."</body>\n";  
        end 
        buf = buf.."</html>\n";
        
        --local _on,_off = "",""
        client:send(buf);
        client:close();
        collectgarbage();
        -- reboot capacity ;-)
        if(_GET.reboot == "on")then
               node.restart();
        end
    end)
end)

5) Le main utilisant aussi une url avec l'IP et la clé api qui va bien mais qui est défini dans un "nodeX_conf.lua(X étant le numéro de votre node sur le réseau, pour pouvoir utiliser des confs de nodes différents ;-). Dans ce fichier on peut aussi activer ou pas des fonctionnalités en fonction de la demande et jouer sur les numéros des entrées-sorties en affectant la valeur du pin ou par 'nil' si non activé :

-- jeedom
api_key = "votre clé api jeedom à mettre ici";
jeedom_ip = "votre ip local de jeedom au format xxx.xxx.xxx.xxx, exemple: 192.168.0.100";

-- virtual jeedom device link to this node (please set to nil if not activated/used)
jeedom_virtual_relay_id = 123; 
jeedom_virtual_pir_id = 234;

-- gpio confs (please set to nil if not activated/used)
-- led of Wemos D1 Mini on D4 (GPIO2)
wemos_led = nil;
-- relay command on D1 (GPIO5)
relay1 = 1;

-- switch reading on D3 (GPIO0)
switch1 = 3;
-- pir reading on D2 (GPIO4)
pir1 = 2;
-- DS18B20 reading on D4 (GPIO2)
OneWirePin = 4;

-- MCP3008 reading (D5 to D8 is allocated in all cases)
MCP3008 = true; -- value nil or different of nil to activate the ressource loading. 
-- to access: http://192.168.0.XXX/?state=analogY where Y is the channel of MCP3008
CTSensor = true; -- value nil or different of nil to activate the ressource loading. 
-- to read CTSensor power: http://192.168.0.XXX/?state=powerY where Y is the channel of the CT Sensor.

-- web server activation (to deactivate and to win memory)
web_server_ui="false";

6) en option si la variable OneWirePin n'est pas à 'nil': le main utilise une libraire pour le ds18b20, ds18b20.lua (qu'il faudra aussi compiler en .lc)


--------------------------------------------------------------------------------
-- DS18B20 one wire module for NODEMCU
-- NODEMCU TEAM
-- LICENCE: http://opensource.org/licenses/MIT
-- Vowstar <vowstar@nodemcu.com>
-- 2015/02/14 sza2 <sza2trash@gmail.com> Fix for negative values
--------------------------------------------------------------------------------

-- Set module name as parameter of require
local modname = ...
local M = {}
_G[modname] = M
--------------------------------------------------------------------------------
-- Local used variables
--------------------------------------------------------------------------------
-- DS18B20 dq pin
local pin = nil
-- DS18B20 default pin
local defaultPin = 9
--------------------------------------------------------------------------------
-- Local used modules
--------------------------------------------------------------------------------
-- Table module
local table = table
-- String module
local string = string
-- One wire module
local ow = ow
-- Timer module
local tmr = tmr
-- Limited to local environment
setfenv(1,M)
--------------------------------------------------------------------------------
-- Implementation
--------------------------------------------------------------------------------
C = 0
F = 1
K = 2
function setup(dq)
  pin = dq
  if(pin == nil) then
    pin = defaultPin
  end
  ow.setup(pin)
end

function addrs()
  setup(pin)
  tbl = {}
  ow.reset_search(pin)
  repeat
    addr = ow.search(pin)
    if(addr ~= nil) then
      table.insert(tbl, addr)
    end
    tmr.wdclr()
  until (addr == nil)
  ow.reset_search(pin)
  return tbl
end

function readNumber(addr, unit)
  result = nil
  setup(pin)
  flag = false
  if(addr == nil) then
    ow.reset_search(pin)
    count = 0
    repeat
      count = count + 1
      addr = ow.search(pin)
      tmr.wdclr()
    until((addr ~= nil) or (count > 100))
    ow.reset_search(pin)
  end
  if(addr == nil) then
    return result
  end
  crc = ow.crc8(string.sub(addr,1,7))
  if (crc == addr:byte(8)) then
    if ((addr:byte(1) == 0x10) or (addr:byte(1) == 0x28)) then
      -- print("Device is a DS18S20 family device.")
      ow.reset(pin)
      ow.select(pin, addr)
      ow.write(pin, 0x44, 1)
      -- tmr.delay(1000000)
      present = ow.reset(pin)
      ow.select(pin, addr)
      ow.write(pin,0xBE,1)
      -- print("P="..present)
      data = nil
      data = string.char(ow.read(pin))
      for i = 1, 8 do
        data = data .. string.char(ow.read(pin))
      end
      -- print(data:byte(1,9))
      crc = ow.crc8(string.sub(data,1,8))
      -- print("CRC="..crc)
      if (crc == data:byte(9)) then
        t = (data:byte(1) + data:byte(2) * 256)
        if (t > 32767) then
          t = t - 65536
        end

        if (addr:byte(1) == 0x28) then
          t = t * 625  -- DS18B20, 4 fractional bits
        else
          t = t * 5000 -- DS18S20, 1 fractional bit
        end

        if(unit == nil or unit == 'C') then
          -- do nothing
        elseif(unit == 'F') then
          t = t * 1.8 + 320000
        elseif(unit == 'K') then
          t = t + 2731500
        else
          return nil
        end
        t = t / 10000
        return t
      end
      tmr.wdclr()
    else
    -- print("Device family is not recognized.")
    end
  else
  -- print("CRC is not valid!")
  end
  return result
end

function read(addr, unit)
  t = readNumber(addr, unit)
  if (t == nil) then
    return nil
  else
    return t
  end
end

-- Return module table
return M

7) en option si la variable MCP3008 est égale à 'true': le main utilise une libraire pour le MCP3008 (convertiseur analogique/numérique), MCP3008.lua (qu'il faudra aussi compiler en .lc)


MISO = 6           --> D6
MOSI =  7         --> D7
CLK = 5            --> D5
CS = 8              --> D8

-- Pin Initialization
gpio.mode(CS, gpio.OUTPUT)
gpio.mode(CLK, gpio.OUTPUT)
gpio.mode(MOSI, gpio.OUTPUT)
gpio.mode(MISO, gpio.INPUT)

-- Function to read MCP3008
function readMCP3008(adc_ch)
   
   if (tonumber(adc_ch) >=0) and (tonumber(adc_ch) < 8) then
      -- MCP3008 has eight channels 0-8

      gpio.write(CS,gpio.HIGH)
       tmr.delay(5)  
        
       gpio.write(CLK, gpio.LOW)  
          gpio.write(CS, gpio.LOW)      -->Activate the chip 
       tmr.delay(1)                  -->1us Delay
      
       commandout = adc_ch
       commandout=bit.bor(commandout, 0x18) 
        commandout=bit.lshift(commandout, 3)
        for i=1,5 do
          if bit.band(commandout,0x80) >0 then
               gpio.write(MOSI, gpio.HIGH)    
          else   
               gpio.write(MOSI, gpio.LOW) 
           end   
            commandout=bit.lshift(commandout,1)
            
            gpio.write(CLK, gpio.HIGH)
            tmr.delay(1)
            gpio.write(CLK, gpio.LOW)
            tmr.delay(1)       
      end
      adcout = 0
      for i=1,12 do
            gpio.write(CLK, gpio.HIGH)
            tmr.delay(1)  
            gpio.write(CLK, gpio.LOW)
            tmr.delay(1)  
             adcout = bit.lshift(adcout,1);
             if gpio.read(MISO)>0 then
                 adcout = bit.bor(adcout, 0x1)
            end
        end 
        gpio.write(CS, gpio.HIGH)
        adcout = bit.rshift(adcout,1)     
        return adcout
     else 
        return -1
     end
end


8) en option  si la variable CTSencor égale à 'true': le main utilise une libraire pour le capteur de courant (convertiseur analogique/numérique), CTSensor.lua (qu'il faudra aussi compiler en .lc)


BURDEN_R = 22.9     --> Resistance in Ohms of Burden Resistor
CT_RATIO  = 2000.0  --> Ratio of Primary:Secondary coils/current
AC_VOLTAGE = 230.0  --> AC Supply Voltage
NUM_SAMPLES = 100  --> Number of samples to take
supplyVoltage = 3.30 --> Get current Vcc voltage (this is applied to AREF on the MCP3008)
 
-- Calculate apparent power from current sensor
function getPower(MCP3008_channel)
  -- Calculate the ratio of ADC step to measured current
  ratio = (CT_RATIO / BURDEN_R) * (supplyVoltage / 1024)
  Irms = 0
  sample = 0
  filtered = 0
  squared = 0
  sum = 0

  -- For 10bit ADC offset = 512 (i.e. half of 1024)
  offset = 512
  
 for i=1,NUM_SAMPLES do
    sample = readMCP3008(MCP3008_channel)
    -- Digital low pass filter extracts the 2.5 V or 1.65 V dc offset,
    --  then subtract this - signal is now centered on 0 counts.
    offset = (offset + (sample - offset) / 1024)
    filtered = sample - offset
    squared = filtered * filtered
    sum = sum + squared
 end
  
  -- Calculate average RMS current
  Irms = ratio * math.sqrt(sum / NUM_SAMPLES)
  
  -- Return output power in KWatts.
  return ((AC_VOLTAGE * Irms)/1000);
end

Bon c'est tout, désolé, cela fait beaucoup pour une première fois mais j'ai préféré faire ainsi et tout vous mettre. A vous de prendre que ce qui est utile pour vous ;-)

Je vous parlerais de hard ;-) plus tard mais manque de temps cela sera pour une prochaine fois :-(
Je peux juste dire pour 'teaser' que j'en suis dans les 15 € pour mon "IoT" multi-capteurs !