nov 19

Asterisk, suivi des appels en xPL

Asterisk est un serveur VoIP facilement installable à la maison.

Je ne m’étendrais pas la dessus, il y a pléthore de tutos sur le nain ternet pour vous expliquer ce que c’est et comment le mettre en place.

Je m’en sers tout les jours pour de multiples usages et l’une des fonctions qui me manquait était la possibilité de transmettre en xPL les numéros des appels entrants, et pourquoi pas, le numéro des appels émis.

(Rassurez vous, tout cela dans l’idée de l’intégrer à mon centralisateur xPL).

En fouillant un peu, j’ai d’abord découvert le package d’ iranger, xplast.

Puis l’excellent billet de mon confrère Ma domotique

Tout cela était bien gentil et sympa, mais je voulais un truc plus simple et plus rapide à mettre en oeuvre.

Je me suis donc plongé (avec délicatesse je vous rassure) dans la documentation d’Asterisk et surtout sur la partie AGI.

Vous trouverez également plein d’info sur le site voip-info.org a cette adresse :

http://www.voip-info.org/wiki/view/Asterisk+AGI

Un peu de google derrière et je suis tombé sur un très bon billet d’Andy Ortlieb qui explique comment utiliser les Asterisk Gateway Interface avec python.

Je me suis donc servi de ses exemples pour écrire un simple module AGI qui transmet en xPL les numéros des appels reçus ou émis via Asterisk.

Copier ce script dans le répertoire agi-bin d’Asterisk (généralement /var/lib/asterisk/agi-bin)
Mettre l’utilisateur asterisk propriétaire de ce script et le rendre executable

Pour intercepter les appels, il faut rajouter une entrée dans votre extensions.conf :

Exemple, pour envoyer un message xPL à chaque appel sortant avec le numéro appelé:
dans votre contexte « appel sortant »:

[appelsortant]
exten => _0ZXXXXXXXX,1,AGI(/usr/bin/python,"/var/lib/asterisk/agi-bin/Asterisk2xPL.agi")
exten => _0ZXXXXXXXX,2,Dial(SIP/freephonie-out/${EXTEN})

Exemple, pour envoyer un message xPL à chaque appel entrant avec le numéro appelant :
dans votre contexte « appel entrant »:

[appelentrant]
exten => s,1,Ringing
exten => s,2,AGI(/usr/bin/python,"/var/lib/asterisk/agi-bin/Asterisk2xPL.agi")
...

Attention, par défaut le message « INBOUND » (appel entrant) est produit quand le script voit une extension « s » (comportement le plus souvent rencontré pour les appels entrants)

#!/usr/bin/python
# -*- coding: ISO-8859-1 -*-
#
# Asterisk2xPL
# http://blog.guiguiabloc.fr
import sys,os,socket
 
hostname = socket.gethostname()
xpladdr = ("255.255.255.255",3865)
xplport = 3865
UDPSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
UDPSock.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)
 
 
def get():
  res = sys.stdin.readline()
  res = res.strip()
  response,delim,result=res.partition(' ')
  result=result.split('=')[1].strip()
  result,delim,data = result.partition(' ')
  return response,result,data
 
def send(data):
  sys.stdout.write("%s \n"%data)
  sys.stdout.flush()
 
AGIENV={}
 
env = ""
while(env != "\n"):
 
    env = sys.stdin.readline()
    envdata =  env.split(":")
    if len(envdata)==2:
      AGIENV[envdata[0].strip()]=envdata[1].strip()
 
incomingnumber = AGIENV['agi_callerid']
outgoingnumber = AGIENV['agi_extension']
 
if outgoingnumber == "s":
  body = 'calltype=INBOUND\nphone='+incomingnumber
  msg = "xpl-trig\n{\nhop=1\nsource=guigui-asterisk."+hostname+"\ntarget=*\n}\ncid.basic\n{\n" + body + "\n}\n"
  UDPSock.sendto(msg,xpladdr)
else:
  body = 'calltype=OUTBOUND\nphone='+outgoingnumber
  msg = "xpl-trig\n{\nhop=1\nsource=guigui-asterisk."+hostname+"\ntarget=*\n}\ncid.basic\n{\n" + body + "\n}\n"
  UDPSock.sendto(msg,xpladdr)

Vous trouverez le script en téléchargement sur mon googlecode :

http://code.google.com/p/guiguiabloc/downloads/detail?name=Asterisk2xPL.agi
Bien évidemment, si vous mettez à jour xPL-PyHAL par le SVN, il inclut la possibilité de réagir à la réception ou l’émission d’un numéro de téléphone ;)

Par exemple pour allumer le module « m5″ a la réception d’un appel du 0699999999 :

MODULE: INBOUND
TELNUMBER: "0699999999"
ACTION: command
TARGETXPL: heyu
TARGETCOMMAND: "on"
TARGETMODULE: "m5"

Amusez-vous bien :D

Classé dans domotique, geekerie | Taggé , | 1 Comment
nov 16

Projet xPL-pyHAL, Alpha release 2

Enfin un peu de nouvelles de mon projet xPL-PyHAL (dont vous trouverez le précédent billet ici).

J’y travaille toujours pour mon propre usage et, honte sur moi, je délaissais un peu la mise à jour du dépot SVN et du package sur googlecode.

Mais je me suis vite fait rattraper par des utilisateurs dont xPL-PyHAL avait, à ma grande fierté je l’avoue, intégré leur environnement domotique :)

Donc merci à Olivier de Connecting Stuff  et Johan de Hotfirenet de me secouer un peu les puces :D

Voici donc une mise à jour, la version Alpha 0.2 que vous pouvez dès à présent télécharger ici :
http://code.google.com/p/guiguiabloc/downloads/detail?name=xPL-PyHAL-alpha-0.2.tgz

ou mettre à jour votre SVN.

Au programme des changements :

  • Optimisation du code python

Une des parties qui m’a prit le plus de temps. Les sections de code du Brain devenaient de plus en plus conséquentes et j’ai tout regroupé dans des fonctions bien définies.

  • Choix du module Memcached

A utilisation intensive, je me suis rendu compte que le module « memcached » de python avait des comportements un peu bizarre et gênant (une nouvelle session à chaque fois sans réutiliser une existante), donc si vous disposez de pylibmc, le Brain l’utilisera en priorité, sinon le module Memcached standard.

N’oubliez pas la configuration dans Memcached_pylibmc.py dans ce cas (adresse du serveur et port de connexion, à l’identique de Memcached.py si vous utilisez ce module).

def __init__(self, hostname="127.0.0.1", port="11211"):
  • Correction d’un bug sur les schémas ac.basic

Plutôt une omission qu’un bug, Marc m’a signalé que certaines télécommandes DIO se présentaient avec le schéma ac.basic plutôt que homeeasy.basic et suite à sa correction, ce type de schéma est désormais intégré au Brain. Merci à lui :) (d’ailleurs vous êtes amplement encouragé a me remonter vos bugs !)

  • Ajout du support DawnDusk xPL

Si vous utilisez le client xPL Dawndusk , qui vous permet d’être alerté dans le bus xPL quand le soleil se lève, ou quand il se couche, xPL-PyHAL intègre désormais la possibilité de générer des évènements suite à cette action.

Le format YAML est le suivant (exemple: envoyer un message notifry « il fait nuit » au coucher du soleil) :

MODULE: dawndusk
DAYNIGHT: dusk
ACTION: message
TARGETXPL: notifry
KEY: "b11111223FFFFFzz"
MESSAGE: "il fait nuit"

Le nom du module pour que xPL-PyHAL réagisse: dawndusk

La clé DAYNIGHT sur laquelle réagir : dusk (coucher du soleil) ou dawn (lever du soleil)

et les actions comme d’habitude (TARGETCOMMAND par exemple pour une action command.

J’ai rajouté quelques exemples dans le répertoire yamlrepo.

 

N’hésitez pas à me remonter les bugs, demande d’évolution :)

 

Amusez-vous bien :D

 

 

 

 

 

Classé dans domotique | Taggé , , | 11 Commentaires
oct 12

CloudTrax, gérer l’accès wifi de vos invités

Vous avez sûrement, tout comme moi, la nécessité parfois d’offrir un accès wifi à vos amis ou famille de passage à la maison.

Malheureusement, (surtout côté famille…), les « trucs » qui veulent se connecter à votre réseau Wi-Fi sont parfois très sales ou sentent un peu des pieds.

Si en plus vous avez méchamment blindé votre accès Wi-Fi a coup d’Ipsec et de firewall authentifiant, la soirée risque d’être longue à configurer leurs portables (même si on simplifie un peu le bouzin ), surtout après l’apéro avec le beau-frère…

Je cherchais donc une solution permettant de mettre en place un accès Wi-Fi temporaire un peu à la manière des Hôtels, avec un code d’accès aléatoire ayant une validité restreinte.

Alors bien évidemment, j’aurais pu partir sur une solution à base de Portail Captif, de redirection etc… mais franchement je n’avais pas envie de perdre trop de temps dans sa mise en oeuvre.

Voulant réutiliser le matériel Wi-Fi que j’avais à ma disposition et qui dort dans le placard la majorité du temps, j’avais le choix entre mes Fonera et mes boîtiers Accton Open-Mesh.

J’avais déjà parlé précédemment des petits boîtiers Accton d’Open-Mesh et comme j’avais bien aimé le principe, je décide de refaire un tour sur leur site et là, surprise ! :

« Open-Mesh’s cloud controller, CloudTrax, is a free cloud-based network controller that helps you build, manage and monitor your wireless networks from anywhere in the world. »

CloudTrax ??? Mais, mais, mais…. C’est tout a fait ce que je recherche !

La gestion est identique à ce qui existait avant mais ce qui m’a surtout intéressé, c’est la possibilité de créer des « Vouchers », comprendre des tickets temporaires d’accès au réseau Wi-Fi.

Ni une, ni deux, on s’attèle à mettre cela en place.

- Flasher le (ou les) boitiers Accton avec la version NG du firmware

Vous trouverez les images des firmwares  ici:
http://dev.cloudtrax.com/downloads/testing/firmware-ng/

La procédure de flash est parfaitement expliqué ici :
http://support.open-mesh.com/knowledgebase/12/How-to-Flash-Open-Mesh-Routers.html

La configuration ne change presque pas de mon billet précèdent, a savoir offrir la possibilité pour votre boîtier CloudTrax de se connecter au nain ternet comme un grand :) (donc dhcp toussa), puis saisir l’adresse MAC du boîtier dans l’interface Web de Cloudtrax sur https://cloudtrax.com/dashboard.php

Comme je ne voulais pas que ce « réseau » tripote de ses sales doigts mon LAN perso, j’ai configuré un VLAN dédié pour l’isoler au niveau 2 et j’ai laissé le routeur Cisco faire office de dhcp, et bien sur router/filtrer comme un gros malade (mais pour les gens normaux vous pouvez simplement le brancher dans votre réseau local du moment qu’un serveur DHCP existe (comme la Freeteuse par exemple).

Une fois connecté et mis à jour, votre boîtier se retrouve dans votre administration Cloudtrax

 

Enfin la partie la plus intéressante, a savoir la génération d’un code temporaire pour l’accès wifi.

Quand votre « invité » se connecte à votre réseau Wifi CloudTrax, il n’a pas de clé a entrer, c’est un réseau « ouvert » (qu’il croit le petit padawan !)

Il lance son navigateur et tombe sur le portail captif (qui est totalement modifiable dans l’interface d’administration CloudTrax (la splash page).

C’est à vous de créer ses codes d’accès temporaire sur la page dédiée :

https://lobby.cloudtrax.com/lobby.php

Une page toute simple vous demande de remplir le code désirée (ou laisser le système le générer aléatoirement), la durée de validité, les limites de download/upload en Mbits etc…

Vous validez et hop, vous avez un numéro a communiquer à votre « invité » ou un ticket à imprimer pour lui remettre.

C’est pas génial ?

Une interface générale vous permet de jeter un oeil à vos tickets et les désactiver si besoin.

Toutes les possibilités sont superbement bien documentées sur la page d’accueil  https://cloudtrax.com/

J’ai trouvé le concept absolument génial, je n’ai pas passer du temps à mettre en place un portail type ChilliSpot en réutilisant un vieux boitier wifi « apacher » et cette façon de générer un ticket valable 1h, 6h, 1 week-end répond tout a fait a mes attentes de fournir l’accès Facebook tant convoitée de ma nièce sur son portable sans qu’elle pollue mes sains systèmes.

Bilan, une solution de Wi-fi pour des invités qui a répondu à mes exigences, qui n’est pas là pour être tout le temps en place, mais qui peut se rallumer en quelques minutes et frimer en donnant un ticket avec la « touche » GuiguiAbloc a ma nièce qui désormais ne peut que me vénérer :D

En espérant vous avoir donner des idées ;)

Amusez-vous bien :)

Classé dans geekerie | Taggé , | 4 Commentaires
août 16

Contrôler votre domotique par la voix avec Android

Le contrôle vocal est, vous le savez, un vieux rêve qui nous taraude depuis que l’on regarde des films de filles soumises  science-fiction.

Heureusement pour nous, le concept et les logiciels ont bien évolués depuis ses dernières années et nous sommes bien loin désormais de nos lointains souvenirs où nous passions des heures avec notre microphone a réciter des pages et des pages de phrases abjectes pour obtenir un résultat… désespérant (si toi aussi tu vois de quoi je parle et que tu souris en y repensant, tu ne me contrediras sûrement pas :D )

J’avais depuis longtemps mis de côté l’idée d’utiliser ma voix pour contrôler quoi que ce soit (et encore moins ma femme, cela marche un peu mieux avec les enfants), jusqu’a ses derniers jours après une lecture intéressante sur un site web dont je vous reparlerais plus tard dans ce billet.

Le but de cet article est de vous décrire comment, avec mon téléphone Android, je contrôle par la voix l’extinction ou l’allumage de mes lumières ou la fermeture de la porte du garage. Potentiellement, tout est contrôlable désormais, il faut juste prendre le temps de coder les règles.

Mais n’anticipons pas, tout d’abord de quoi avons nous besoin.

  • Un Webservice pour notre serveur Domotique

Si vous disposez d’une box domotique, vous avez sûrement le moyen de contrôler par une requête http vos prises ou interrupteurs (je vous laisse à la documentation de la dite box), mais si comme moi, vous contrôler tout par des scripts, xPL et j’en passe et des meilleurs, il va pouvoir devenir intéressant de disposer d’une API permettant par une URL de commander vos équipements.

Python (encore lui), est le candidat idéal pour créer ce WebService.

L’exemple de code que je vais vous donner n’est peut-être pas utilisable pour vous dans l’immédiat car il est fortement intégré à mon environnement domotique (xPL), mais il vous donnera sûrement des pistes pour réaliser vous même votre API.

Vous trouverez les classes que j’utilise dans mon projet xPL-PyHAL (xPLmessage par exemple ou Daemon). Donc si vous utilisez mon centralisateur xPL, il y a donc de fortes chances que cela marche tout de suite ;) (pub pub pub)

#!/usr/bin/env python
 
import web
import re,socket,sys,os
from xPLmessage import xPLmessage
import threading
from Daemon import Daemon
 
motdepasse = "1234"
 
#exemple d appel http :
#lynx "http://localhost:8080/x10?cle=1234&module=a1&command=on"
 
web.config.debug = False                                                                                                      
 
urls = (
  '/', 'index',
  '/x10', 'x10',
  '/ipx800', 'ipx800'
)
 
render = web.template.render('templates/', globals={'re':re})
app = web.application(urls, globals())
 
class index:
    def GET(self):
         return web.HTTPError(403)
 
    def POST(self):
         return web.HTTPError(403)
 
class x10:
    def GET(self):
        sendmsg = xPLmessage()
        key = web.input(cle='')
        adress = web.input(module='')
        command = web.input(command='')
        if not key.cle:
            raise web.HTTPError(403)
        if not adress.module:
            raise web.HTTPError(404)
        if not command.command:
            raise web.HTTPError(404)
 
        if key.cle != motdepasse:
            return 'access denied'
        else :
            commandx10 = command.command
            devicex10 = adress.module
            sendmsg.xplmsgcmndx10(commandx10,devicex10)
            return 'accept'
 
class ipx800:
    def GET(self):
        sendmsg = xPLmessage()
        key = web.input(cle='')
        adress = web.input(module='')
        command = web.input(command='')
        if not key.cle:
            raise web.HTTPError(403)
        if not adress.module:
            raise web.HTTPError(404)
        if not command.command:
            raise web.HTTPError(404)
 
        if key.cle != motdepasse:
            return 'access denied'
        else :
            commandipx800 = command.command
            relayipx800 = adress.module
            sendmsg.xplmsgcmndipx800(commandipx800,relayipx800)
            return 'accept'
 
class MyDaemon(Daemon):
        def run(self):
          app.run()
 
if __name__ == "__main__":
 
        service = MyDaemon('/tmp/daemon.pid')
        if len(sys.argv) == 2:
                if 'start' == sys.argv[1]:
                        sys.argv[1] =  '8080'
                        service.start()
                elif 'stop' == sys.argv[1]:
                        service.stop()
                elif 'restart' == sys.argv[1]:
                        service.restart()
                elif 'console' == sys.argv[1]:
                        sys.argv[1] =  '8080'
                        service.console()
 
                else:
                        print "Unknown command"
                        sys.exit(2)
                sys.exit(0)
        else:
                print "usage: %s start|stop|restart|console" % sys.argv[0]
                sys.exit(2)

Comment ca marche ?

Je le dis tout de suite, ce n’est pas « restful compliant » (je réagis sur des GET http et pas des POST) mais pour l’usage personnel que j’en fais, c’est largement suffisant (et je n’ai pas vocation à en faire un produit commercial).

En appelant par votre navigateur (ou par curl ou par lynx (qui est pour moi le nec plus ultra du navigateur web (barbu inside))) l’URL : « http://monserveurdomotique:8080/x10?cle=1234&module=a1&command=on » vous allez demander au module A1 de s’allumer.

Je prend l’exemple X10 uniquement pour la simplicité de compréhension, cela pourrai être IPX800 dans mon code ou n’importe quelle techno domotique du moment qu’elle est « appelable » par le webservice (xPL est encore et toujours votre ami pour centraliser tout cela).

La « clé » est le mot de passe pour executer une requète sur votre serveur domotique, alors évidemment la sécurité est très minimaliste dans cet exemple, mais je vous laisse peaufiner a coup d’https, de certificats, d’iptables et j’en passe.

Le code est suffisamment simple pour que vous en compreniez le fonctionnement et que vous l’adaptiez à vos besoins (les tutos sur les webservice python sont nombreux sur le nain ternet).

Maintenant que nous commes capable de donner des ordres a notre système domotique par de simples requêtes http, il nous reste à pouvoir le faire de vive voix.

  • Tasker, le « must have » d’un téléphone Android

Tasker est sûrement l’un des meilleurs logiciels sous Android existant.

Il vous permet de créer toutes sortes de scénarios ou d’évènements sur votre téléphone (si je met des écouteurs alors joue une musique, si je me trouve à moins de 100m de chez moi, alors ouvre la porte du garage, etc..)

Si sa complexité rebute un peu au premier abord, on en prend vite la main et rapidement, on en arrive à coder des centaines de tâches ou de contextes qui nous facilite la vie au quotidien.

Le prix est dérisoire en comparaison de ses capacités et je ne peux que vous inviter chaudement à l’acheter.

Cerise sur le gâteau (Note inintéressante de l’auteur : Je vous fait grâce des expressions que j’ai voulu écrire ici et qui laisserait sûrement planer la honte sur ma famille durant des décennies), depuis quelques semaines, Tasker inclus désormais la possibilité d’exporter vos « scénarios » en tant qu’application autonome Android !!! C’est pas le top du summum de la geekerie ultime ça ??? (Note inintéréssante de l’auteur (encore) : Là vraiment, vous avez échappé à des expressions qui limite me vaudrait quelques années de prisons …)

Exemple, vous créez un petit scénario qui fait que quand votre téléphone est en charge, vous activez le wifi, si vous le retournez, il coupe tout, et se met en mode silence, s’il détecte votre oreillette bluetooth, il informe votre serveur domotique que vous êtes en mode privé et que les messages d’alerte de votre installation peuvent être envoyé via Notifry en Audio (qui depuis une petite discussion avec Daniel, le développeur de Notifry, a gentiment accepté d’intégrer le choix de la sortie audio des messages Notifry :) Merci à lui pour répondre rapidement à mes demandes d’évolutions, un développeur aussi proche de ses utilisateurs est assez rare pour le souligner.
Et d’un clic, vous exportez votre propre application apk autonome.

Il n’y a quasiment pas de limite à Tasker, a part votre propre imagination.

Et dans toute ses imaginations possibles, je suis tombé sur un fou furieux de Tasker (dans le bon côté du terme :p, ce type fait quand même tourner 474 taches Tasker par jour oOO), Andreas Ødegård.
(alors vu que c’est un norvégien, vous comprendrez les caractères ésotériques dans son nom :D ), qui est ausi un des rédacteur associé pour l’excellent site Pocketables.

Ce geek comme je les aime, outre la qualité de ses billets, nous donne souvent des trucs et astuces pour Tasker et dans son lot de bidouilles, il a décider de créer son propre assistant vocal sous Android avec Tasker.

A la lecture de son billet, j’ai tout de suite accroché sur l’idée et bien sur, je me suis empressé de le mettre en oeuvre pour mon propre usage et en hommage a l’excellent travail d’Andréas, j’ai décidé de garder le même nom pour mon assistante vocale, Nelly (pour la petite histoire du pourquoi du comment ce prénom, je vous invite a lire son billet, a moins que vous ne soyez déjà un lecteur assidu de Mike Shepherd ).

Pour réaliser cet exploit, nous allons tout simplement utiliser la fonction « Obtenir depuis depuis la voix » de Tasker. Cette fonction se base sur le moteur de reconnaissance vocale de Google (une connexion au nain ternet est donc nécessaire)

La phrase analysée est contenue dans la variable %VOICE de Tasker, il ne reste plus qu’a réaliser une tâche s’executant si la variable %VOICE contient tels mots.

Pour appeler notre Webservice Python, nous allons utiliser la fonction « Get HTTP » en spécifiant les paramètres suivants :

Et pour l’analyse des mots sur lesquels réagir :

L’étoile étant bien sur un caractère joker, ce que l’on dit « autour » n’est pas pris en compte (ça vous permet de laisser libre cours a votre imagination devant votre entourage : « Nelly, mon petit, dans ta grande manséutude, si tu éteins le salon que je puisse dragouiller la demoiselle que j’ai invité chez moi pour un soi-disant repas en toute amitié, je t’en serais reconnaissant. »)
Attention quand même, par défaut vous n’avez que 30 secondes… (euh pour donner l’ordre vocal hein, pas pour la demoiselle…)

Pour vous montrer de visu de quoi Tasker est capable avec « Nelly », je vous propose une petite vidéo faite a l’arrache (je l’avoue) mais qui vous donnera les capacités du système.

 

Démonstration de contrôle vocal avec Tasker par Guiguiabloc

Avouez tout de même que cela en jette pas mal (en plus d’être diaboliquement génial :) )

Merci donc à Andréas pour son idée, à Lee Wilmot pour son excellente application Tasker et à Olivier Sannier pour la traduction en français de Tasker ;)

Amusez vous bien :D

 

 

 

 

 

 

Classé dans domotique | Taggé , , | 20 Commentaires