kiwi Posté(e) le 14 décembre 2014 Signaler Posté(e) le 14 décembre 2014 Bonjour à tous, Cette solution, différente des autres, se base sur le fait que les objets wifi disposent d'un adresse "MAC" (ou ARP en anglais). Cette adresse est obligatoire et a le grand avantage de ne nécessiter aucun port ouvert sur l'appareil a tester. Prérequis : Une machine *nix (Linux : Raspberry, Synology, FreeBSD, ...). Une HC2 (une version spécifique HCL viendra plus tard). Du Perl avec la bibliothèque CGI sur la machine hôte. Avoir un baux DHCP fixe (aka configurer une IP fixe) pour les appareils a surveiller. La solution se décompose en deux parties :Un script CGI qui se met sur un serveur *nix. Un virtual module qui s'occupe de faire des demandes toutes les 10 minutes sur ce script CGI. Installation du CGI sur un serveur *nix.Je prends pour référence mon Raspberry PI qui fait tourner mon domoticz. Ayant eu la flemme d'installer un PI "à la main" j'avais déjà pris la "Domoticz RaspberryPI SD Image", que vous pouvez trouver à l'adresse suivante : http://www.domoticz.com/wiki/Domoticz_RaspberryPi_SD_Image. Accessoirement j'ai installé avahi afin de le trouver via bonjour sur mon Mac. Commandes a executer en root : aptitude install avahi-daemon Normalement l'image PI pour domoticz dispose déjà d'un nginx préinstallé, il reste donc plus à ajouter fcgiwrap pour que le CGI soit executable depuis nginx. aptitude install fcgiwrap Puis copier le fichier de configuration dans /etc/nginx : cp /usr/share/doc/fcgiwrap/examples/nginx.conf /etc/nginx/fcgiwrap.conf Il suffit de créer un répertoire cgi-bin et downloader le script arp.pl : mkdir -p /usr/lib/cgi-bin cd /usr/lib/cgi-bin wget --no-check-certificate https://redmine.oav.net/projects/kiwi/repository/revisions/master/raw/fibaro/arp/arp.pl chmod +x arp.pl Il reste à configurer le nginx pour qu'on puisse donc executer le CGI qui vas nous servir a trouver si le matériel fonctionne ou pas, créez le fichier /etc/nginx/sites-available/cgi avec le contenu suivant : server { #listen 80; ## listen for ipv4; this line is default and implied #listen [::]:80 default_server ipv6only=on; ## listen for ipv6 listen 8000; root /usr/share/nginx/www; index index.html index.htm; # Make site accessible from http://localhost/ server_name localhost; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. try_files $uri $uri/ /index.html; # Uncomment to enable naxsi on this location # include /etc/nginx/naxsi.rules } include /etc/nginx/fcgiwrap.conf; } Puis activez le site : cd /etc/nginx/sites-enabled && ln -s ../sites-available/cgi nginx -t Au "nginx -t" un test de syntaxe du fichier de conf vas être effectuée normalement si vous avez autre chose que : nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful C'est qu'il y a un erreur quelque part dans votre configuration.Dans le cas où tout vas bien, relancez le service nginx : service nginx restart Puis nous pouvons passer au test CGI.Exemple avec une ip en 192.168.0.50, mettez dans votre navigateur : http://ip.du.pi.lan:8000/cgi-bin/arp.pl?host=192.168.0.50, devrait vous donner le JSON suivant (si cette machine existe et que vous arrivez a pinger cette machine depuis le PI) : { hostname: "192.168.0.50", ipv4: "192.168.0.50", MAC: "aa:bb:cc:dd:ee:ff" } La partie *nix est donc finie.Installation de la partie HC2. Téléchargez le virtual module à l'adresse : https://redmine.oav.net/projects/kiwi/repository/revisions/master/raw/fibaro/arp/presence.vfib (Si le certificat SSL fais la tronche c'est pas grave, je le mettrais à jour bientôt). Dans la configuration du modules, mettez l'ip correspondant au PI et le Port correspondant a celui que vous avez ouvert précédemment (dans mon exemple : 8000). Dans le code du bouton 1, complétez les lignes suivantes avec *vos* paramètres : local cgi = "/cgi-bin/arp.pl"; local what = "192.168.0.50"; Pour aller avec l'exemple ci dessus.A noter que vous avez besoin de créer une variable locale qui s'appelle : Phone_<valeurdewhat>, par exemple : Phone_192.168.0.50 avec comme 2 valeurs 1 ou 0. Après laissez le reste se faire, normalement les icônes changent tout seul et la ligne de status affiche correctement les bonnes infos. Enjoy et informez moi des pb ou evolutions. Xavier PS1: License du module : MPL1.1, URL de mon git : https://redmine.oav.net/projects/kiwi/repository/revisions/master/show/fibaro/arp PS2: Si bug utilisez l'option "Nouvelle demande" afin que je corrige/adapte Edits: 22/12 : corrections de carfnann 3
TonyC Posté(e) le 14 décembre 2014 Signaler Posté(e) le 14 décembre 2014 Salut Kiwi! Je vois que tu n'as pas chaumé, et ta soluce super bien pensée! Je l'installe dés que j'ai quelques minutes et j'ai hâte!
pepite Posté(e) le 15 décembre 2014 Signaler Posté(e) le 15 décembre 2014 Bonjour, Super ce detecteur de présence, Question bete : QUID des smart à la pomme qui se mettent en veille et perdent le WIFI ? Merci, j'ai hate de l'installer
kiwi Posté(e) le 15 décembre 2014 Auteur Signaler Posté(e) le 15 décembre 2014 @pepite: Justement je n'ai que ça àla maison iPhone 5S et 4S... Donc tu peux considérer que ça marche
yassinex Posté(e) le 15 décembre 2014 Signaler Posté(e) le 15 décembre 2014 Bonjour Kiwi, Ta raquette concerne la table ARP ? si c'est le cas, pourquoi ne pas faire référence à l'adresse MAC directement ( quelque soit l'adresse IP ) ?
pepite Posté(e) le 15 décembre 2014 Signaler Posté(e) le 15 décembre 2014 @kiwi Yes, je mets ca en place sur le RPI dès que possible hihihi
kiwi Posté(e) le 15 décembre 2014 Auteur Signaler Posté(e) le 15 décembre 2014 @yassinex: le perl cgi est capable de manger des adresses MAC, donc normalement ça doit marcher. Pourquoi des ip / nom d'hosts? parce que c'est plus facile de se souvenir de ça que d'une adresse MAC (Ok je parles pas d'IPv6 encore)
yassinex Posté(e) le 15 décembre 2014 Signaler Posté(e) le 15 décembre 2014 Oui mais du coup ton script ne fonctionnera pas en mode DHCP car l'IP change ( et non l'adresse MAC ). Il y'a des cas ou l'on souhaite pas forcement réserver une IP (Invités, voisins...) mais on souhaite quand même activer des scénarios/action en leur présence. Example avec GEA : GEA.add(id["Sonnerie_Porte"], -1 , "Les Lutins Arrivent", {{"Repeat"}, {"Time", "08:00", "18:00"}, {"Global", "LesRelous", "Oui"}, {"VirtualDevice", id["Cage-Pitbull"],"1"}, {"Value", id["Portail_Jardin"], 0} }) ... 1
kiwi Posté(e) le 15 décembre 2014 Auteur Signaler Posté(e) le 15 décembre 2014 Sisi il fonctionne en mettant une adresse MAC (grep power !) : http://ip.du.ras.pi:8080/cgi-bin/arp.pl?host=aa:af:bb:cf:de:ad me retourne : { hostname: "aa:af:bb:cf:de:ad", ipv4: "192.168.0.40", MAC: "aa:af:bb:cf:de:ad" } Donc l'effet kiss cool, c'est que tu peux retrouver comme ça quelle adresse IP appartient l'adresse MAC que tu précises...
pepite Posté(e) le 15 décembre 2014 Signaler Posté(e) le 15 décembre 2014 (modifié) Bonsoir @kiwi Alors je teste et voila mes premiers retours (c'est peut-etre moi le boulet) 1- Impossible de créer une variable globale avec le contenu de "what" si what est numerique comme dans le tuto --> Si what = 192.168.0.50 (adresse du smartphone si j'ai bien compris ???) alors impossible de creer la variable en "Phone_192.168.0.50" 2- Variable globale crée en mettant en "what" : le nom recup du DHCP fixe de la box : OK donc pour moi par exemple : --> local what = "iphonepepite"; donc variable globale : Phone_iphonepepite sans mettre de valeurs 3- Test de la verif presence en cliquant sur le bouton : message : iphonepepite is not at home alors que je suis bien wifi Me suis-je trompé quelque part ? J'oubliais : Pour tester une autre smartphone, on rajoute bien un bouton en changeant "what" et en rajoutant une variable globale correspondante ? 4- Test avec variable predefinie avec valeur 0 et 1, pas mieux, meme message "...is not at home" 5- dans le main loop il reste cela que j'ai modifié aussi avec le nom de la variable predefinie local status = fibaro:getGlobal("Phone_ikiwi") 6- idem avec Variable globale sans valeur : idem : meme message ..is not at home Quelquechose me dit que c'est moi qui fait une erreur quelquepart ;-) AU fait ..heu...what is it ? "PS2: Si bug utilisez l'option "Nouvelle demande" afin que je corrige/adapte" Modifié le 16 décembre 2014 par pepite
kiwi Posté(e) le 17 décembre 2014 Auteur Signaler Posté(e) le 17 décembre 2014 @pepite: sur ton pi si peux tu me donner ce que fait la commande : arp -a en MP ?J'ai une configuration particulière chez moi (avec des DNS / reverse DNS / plutôt proche de l'état de l'art dans un datacenter que des "choses" normales chez mr tout le monde). Sur le point 1, je vais modifier le virtual module pour qu'il prenne autre chose de le contenu de la variable what. Sur le point 5, j'ai oublié de dire cette partie, doc àmettre a jour (ca sera fait bientôt) Sur le dernier point, j'ai un bug tracker sur le redmine ou est hébergé le GIT... Mais c'est pas grave
carfnann Posté(e) le 17 décembre 2014 Signaler Posté(e) le 17 décembre 2014 Bonjour, Désolé mais je ne suis pas sur de comprendre en quoi cette méthode différe… Est ce l’équivalent d’un ping? Si oui pourquoi avoir besoin de l’adresse mac? Sinon ta méthode fonctionne même si l’iPhone est en veille? Merci en tout cas
kiwi Posté(e) le 17 décembre 2014 Auteur Signaler Posté(e) le 17 décembre 2014 @carfman: le concept d'adresse MAC est que toute carte ethernet (y compris wifi) en as une et est obligée de l'annoncer. Le ping quand a lui n'est même pas obligatoire et des fois même certains matériels ne répondent pas au ping alors que l'adresse MAC réponds (je ne vais pas décrire comment ca marche, mais la carte wifi du téléphone réponds directement aux requêtes MAC alors que le ping dois passer dans le CPU du smartphone, donc on est plus bas niveau dans les couches OSI : niveau 1 : câbles / wifi, niveau 2 : MAC, niveau 3: ping / tcp...en gros). Sur les machines *nix (linux, ...) la table MAC -> IP est gardée en cache un certain nombre de temps (sur FreeBSD j'arrive a tuner ça sur linux, je recherche encore la bonne commande a mettre), donc partant de ce fait que les iBidules ne se présente que une fois très courte sur le réseau, en utilisant ca cache on peux savoir, sans encombrer le réseau wifi (qui est partagé par tous les clients wifi, donc limité en bande passante) si un téléphone est la depuis peu de temps (peu = dans mes versions de tests environ 30 minutes), de façon "passive". Mon code n'est pas encore parfait, mais je vais corriger le virtual module pour qu'on puisse mettre ip / mac / nom (si, comme moi, on a mis un DNS propre a la maison).
pepite Posté(e) le 17 décembre 2014 Signaler Posté(e) le 17 décembre 2014 @kiwi : merci je te fais ca ce soir
MasterBT Posté(e) le 17 décembre 2014 Signaler Posté(e) le 17 décembre 2014 Je vais suivre ça, et attendre de voir une version qui tourne sur HCL. J'utilise la version de Tony depuis un peu moins d'une semaine et j'avoue n'avoir aucun raté. Par contre je rencontre une défaut à utiliser ce système pour par exemple allumer mes Hue quand j'arrives chez moi. Explication: Je contrôle les Hue avec un Virtual Device qui balance une requête en PUT et donc avec un paramètre définie. A coté de ça j'ai une scène qui regarde la valeur de la variable Présence, Si Présent = Allume Hue (avec le parcmètre du Virtual Device) Dans une autre scène Si absent = Stop Hue donc à chaque cycle de scène ca me remet les paramètres de l'ampoule du Virtual Device. Donc si j'avais changé par exemple la couleur ou luminosité, ca reset :/ Je ne peut par exemple donc pas faire d'annonce vocal par exemple quand un tél entre sous le wifi, car ça le ferait à chaque cycle de vérification de la variable et non seulement à son changement d'état ce qui serait l'idéal. Rappel: Je suis sur une HCL
carfnann Posté(e) le 19 décembre 2014 Signaler Posté(e) le 19 décembre 2014 je viens de mettre ton pgm en place, c'est au poil! juste quelques remarques : * il y a des erreurs de typo dans le tuto, quand on fait un copier coller bêtement comme moi... créez le fichier /etc/nginx/site-available/cgi avec le contenu suivant : il y a un s à site => créez le fichier /etc/nginx/site-available/cgi avec le contenu suivant : cd /etc/nginx/site-enabled && ln -s ../sites-available/cgi idem cd /etc/nginx/sites-enabled && ln -s ../sites-available/cgi et juste une chose, j'ai rajouter une gestion du what local pour y mettre mon prénom car je n'ai pas mis de dns chez moi... juste avant if(response.MAC == "unknown") le 1er local what lui je l'ai gardé pour l'@ mac merci encore
pepite Posté(e) le 19 décembre 2014 Signaler Posté(e) le 19 décembre 2014 @carfnann ah zut, kiwi le pauvre essaie de me debugger par MP. Pour moi cela ne fonctionne pas, cela t'embeterait de partager ton code qui tourne stp ? en MP ? ca peut aussi aider kiwi a ne pas s'arracher les cheveux avec moi ;-) merci.... pepite
carfnann Posté(e) le 19 décembre 2014 Signaler Posté(e) le 19 décembre 2014 voila le contenu de mon bouton action local thismodule = fibaro:getSelfId(); local ip = fibaro:get(thismodule, 'IPAddress'); local port = fibaro:get(thismodule, 'TCPPort'); local cgi = "/cgi-bin/arp.pl"; local what = "80:be:xx:xx:xx:xx"; -- DON'T FORGET to create global variable Phone_ with "what" content -- ie if what="ikiwi", then the GV will be : Phone_ikiwi fibaro:debug("ARP : http://"..ip..":"..port..cgi); local arpstuff = pcall(function() local ARP = Net.FHttp(ip,port); local response, status, errorCode = ARP:GET(cgi.."?host="..what); --fibaro:debug("Debug : r : "..response.."\n"); --fibaro:debug("Debug : s : "..status.."\n"); --fibaro:debug("Debug : e : "..errorCode.."\n"); if(tonumber(status)==200) then -- enregistrement du retour de l API dans une table response = json.decode(response); fibaro:debug(response.hostname); fibaro:debug(response.MAC); what = "Julien"; if(response.MAC == "unknown") then fibaro:debug(what.." is not at home"); if (fibaro:getGlobalValue("Phone_"..what)=="1") then fibaro:setGlobal("Phone_"..what,"0"); end; fibaro:log(what.." is not at home"); else fibaro:debug(what.." is at home"); if (fibaro:getGlobalValue("Phone_"..what)=="0") then fibaro:setGlobal("Phone_"..what,"1"); end fibaro:log(what.." is at home"); end; else fibaro:debug("status: " .. tostring(status or "")); fibaro:debug("error code: " .. tostring(errorCode or "")); end; end); if (not arpstuff) then fibaro:debug("ARP polling failed"); end; d'abord j'affecte mon adresse mac à la variable locale what (ligne 5), pour faire la requête puis ensuite j'affecte mon nom (ligne 25), pour mettre à jour ma variable globale "phone_Julien" c'est tout ce que j'ai fait (plus la variable global dans le main loop pour avoir phone_Julien)
pepite Posté(e) le 19 décembre 2014 Signaler Posté(e) le 19 décembre 2014 bonsoir, Pas mieux..hihihi voila le debug [DEBUG] 23:51:35: ARP : http://192.168.0.16:8000/cgi-bin/arp.pl [DEBUG] 23:51:46: 40:xx:xx:xx:xx:xx [DEBUG] 23:51:46: unknown [DEBUG] 23:51:46: iphonepepite is not at home merciiii
carfnann Posté(e) le 20 décembre 2014 Signaler Posté(e) le 20 décembre 2014 bizarrement, je fais maintenant la meme requête http pour l'iPhone de ma femme et cela ne passe plus...
pepite Posté(e) le 20 décembre 2014 Signaler Posté(e) le 20 décembre 2014 j'espere que je ne t'ai pas porté la poisse.. Kiwi vient de me demander de faire d'autres manips.mais toujours pas ;-) merki
kiwi Posté(e) le 22 décembre 2014 Auteur Signaler Posté(e) le 22 décembre 2014 Hello, Attention j'ai modifié le code du bouton (et pas encore mis àjour le code du virtual module), le voici : local thismodule = fibaro:getSelfId(); local ip = fibaro:get(thismodule, 'IPAddress'); local port = fibaro:get(thismodule, 'TCPPort'); local cgi = "/kiwi/arp.pl"; local what = "ikiwi"; -- DON'T FORGET to create global variable Phone_ with "what" content -- ie if what="ikiwi", then the GV will be : Phone_ikiwi or change the -- following local gbname = "Phone_"..what; fibaro:debug("ARP : http://"..ip..":"..port..cgi); local arpstuff = pcall(function() -- Create the global variable name local gbname = "Phone_"..what; local ARP = Net.FHttp(ip,port); local response, status, errorCode = ARP:GET(cgi.."?host="..what); --fibaro:debug("Debug : r : "..response.."\n"); --fibaro:debug("Debug : s : "..status.."\n"); --fibaro:debug("Debug : e : "..errorCode.."\n"); if(tonumber(status)==200) then -- enregistrement du retour de l API dans une table response = json.decode(response); fibaro:debug(response.hostname); fibaro:debug(response.MAC); if(response.MAC == "unknown") then fibaro:debug(what.." is not at home"); if (fibaro:getGlobalValue(gbname)=="1") then fibaro:setGlobal(gbname,"0"); end; fibaro:log(what.." is not at home"); else fibaro:debug(what.." is at home"); if (fibaro:getGlobalValue(gbname)=="0") then fibaro:setGlobal(gbname,"1"); end fibaro:log(what.." is at home"); end; else fibaro:debug("status: " .. tostring(status or "")); fibaro:debug("error code: " .. tostring(errorCode or "")); end; end); if (not arpstuff) then fibaro:debug("ARP polling failed"); end; D'autre part, le problèmes viennent du fait chez certains que la machine qui héberge le CGI ne vois pas assez souvent les iDevices.De mon coté, sur mon PI j'ai deux choses : - un resolveur dns (serveur dns) qui remplace celui de mon FAI (comme ça je n'ai pas accès a la censure d'état), qui peux être installé a avec "aptitude install unbound". Le serveur DHCP alors annonce ce serveur comme serveur DNS de la maison. - j'ai aussi installé avahi... Ce qui me permet d'avoir accès via bonjour a mes matériels. D'autre part d'après les échanges que j'ai eu avec pepite, un sysctl -w net.ipv4.neigh.default.base_reachable_time_ms=1800000 en root permet de garder le cache ARP de facon plus longue. Il est vrai que mon code est très "unix" centric, et donc dépend aussi un peu de ma configuration personnelle qui peux ne pas être la même partout.
Ez3kiel Posté(e) le 26 décembre 2014 Signaler Posté(e) le 26 décembre 2014 Salut Kiwi, Merci pour ce module virtuel et tout le boulot qui va avec ! Une question, j'ai installé le tout et je me demandais combien de temps faut-il pour être notifié absent ? Si j'ai bien suivit , c'est le temps que l'on ne soit plus dans la table arp ? Par contre, impossible de savoir quelle est sa durée de vie.
kiwi Posté(e) le 26 décembre 2014 Auteur Signaler Posté(e) le 26 décembre 2014 @Ez3kiel: le TTL de la table ARP dépends de pas mal de choses mais beaucoup de la variable kernel "net.ipv4.neigh.default.base_reachable_time_ms", d'ailleurs dans le post précédent au tiens, j'ai donné une méthode pour le mettre plus haut. Il est vrai que par contre Linux n'est pas "ultra" cool sur cette méthode car il y a d'autres paramètres (a la con) qui rentrent en compte. Sur FreeBSD (que je préfère de loin à Linux) la command arp -a montre bien le TTL de la table ARP : $ arp -a ikiwi.home.oav.net (192.2.0.40) at aa:af:ee:ff:de:ad on em0 expires in 2331 seconds [ethernet] (...) A noter et j'insiste la dessus, que mon PI ou Serveur FreeBSD est LE serveur sur lequel tous les appareils se connectent, en effet, il fait : Serveur DNS (ipv4 et ipv6) Serveur Proxy (configuré sur tous les idevices) Serveur web qui réponds aux requêtes wpad (pour l'auto conf des proxy). Rien que ces paramètres permettent une demande régulière de data a ce serveur et garantis que l'expiration de la table ARP corresponds bien au fait que l'utilisateur n'est plus dans les parages depuis "quelques temps". 1
Ez3kiel Posté(e) le 26 décembre 2014 Signaler Posté(e) le 26 décembre 2014 @Kiwi, OK, je comprends mieux pourquoi ça marche chez toi et pas chez moi. En fin de compte, tous tes devices passent par le pi chez toi. du coup, ta table arp est cohérente avec la présence des devices. chez moi la table est complètement désynchronisée de la présence. je vois des périphériques connectés qui ne le sont pas et d'autres qui devraient l’être mais qui sont invisibles. par exemple mon tel android est éteint depuis 2h du mat et mon pc fixe depuis 6h et je les vois toujours present chez moi. Une question, est ce que la mise en place du pi en tant que passerelle pour tous les devices est compliquée a faire ?
Messages recommandés