Artisan Numérique

/système/réseau/voip/ Automatiser la conversation avec son téléphone BlueTooth

Les temps où il fallait trifouiller la configuration de bluez sont aujourd'hui lointains et l'intégration Gnome/BlueTooth marche à merveille. Du coup le contrôle du téléphone passe entièrement par le mode graphique du parcours des fichiers à la réception des objets, en passant par la composition des SMS via gnome-phone-manager.

Malgré tout comprendre un peu comment la mécanique interne permet une chose que le graphique ne remplacera jamais, la création de petit scripts pratiques d'automatisation. Ici les automatisations en question sont assez simple, à savoir comment récupérer un lot de photos prises avec l'appareil et comment injecter dans le mobile mes contacts évolution.

Découverte des services

La gestion du bluetooth passe par deux services

  • HCI (Host Controller Interface) qui gère la communication avec la couche matériel.
  • SDP (Service Discovery Protocol) qui gère les services attachée à une périphérique BlueTooth.

Dans l'ancien temps, chacun de ces deux services étaient pris en charge par son démon. Aujourd'hui c'est hcid qui occupe les deux rôles. Ce démon est donc forcement lancée sur votre système, si ce n'est pas le cas, tentez un /etc/init.d/bluetooth start.

Maintenant, nous pouvons déjà vérifier que la périphérique est bien reconnue dans le système :

roothciconfig
hci0:  Type: USB
BD Address: 00:03:7A:86:22:0C ACL MTU: 384:8 SCO MTU: 64:8
UP RUNNING PSCAN
RX bytes:1215 acl:0 sco:0 events:27 errors:0
TX bytes:601 acl:0 sco:0 commands:26 errors:0

Ok, notre périphérique est bien visible (hci0), vérifions donc les périphériques clientes visibles (ici le téléphone) :

roothcitool scan
Scanning ...
00:1D:25:FB:A2:76       SGH-D840

Parfait, mobile en vue, son adresse bluetooth est donc 00:1D:25:FB:A2:76. Voyons maintenant ce que ce téléphone sait faire en interrogeant sont serveur SDP. La commande suivante sans le grep donnerait plus d'information, mais là nous cherchons à obtenir la liste des services disponibles, et surtout le canal bluetooth associé à chaque service. En effet en blutooth c'est comme en TCP/IP, à l'adresse IP correspond notre adresse bluetooth, les services du périphériques peuvent être vu comme des serveurs et enfin les ports qu'écouteraient ces serveurs sont appelés des canaux (Channels).

rootsdptool records 00:1D:25:FB:A2:76 | grep -P 'Service Name|Channel'
Service Name: Dial-up networking
Channel: 1
Service Name: Voice GW
Channel: 2
Service Name: Bluetooth Serial Port
Channel: 5
Service Name: Voice Gateway
Channel: 6
Service Name: OBEX FileTransfer
Channel: 9
Service Name: OPP
Channel: 3

Dans cette liste, pour l'instant, deux services nous intéressent particulièrement : OOP et OBEX File Transfert qui sont respectivement sur les canaux 9 et 3.

Récupération des fichiers du mobile

Le OBEX FileTransfert, disponible ici sur le canal 9, est un protocole permettant l'échange de fichiers. A ce titre il est à rapprocher d'un serveur FTP. Il est grâce à lui possible de lire les dossiers présent sur le périphérique, de se déplacer dans l'arborescence, et enfin d'envoyer et recevoir des fichiers. Et comme OBEX FT est une sorte de serveur FTP, il y existe pour lui un client OBEX FT. Il faut pour cela installer le paquet obexftp

Première chose à faire est donc de récupérer la liste des dossiers à la racine du téléphone :

gastonobexftp -b 00:1D:25:FB:A2:76 --list
Browsing 00:1D:25:FB:A2:76 ...
Connecting...done
Receiving ...
<?xml version="1.0"?>
<!DOCTYPE folder-listing SYSTEM "obex-folder-listing.dtd">
<folder-listing version="1.0">
<folder name="Favorites Images" modified="20040927172336Z"/>
...
<folder name="Other Files" modified="20040927172336Z"/>
</folder-listing>
done
Disconnecting...done

Récupérons maintenant la liste des fichiers contenus dans le dossier "Favorites Images". Attention, sur mon téléphone il est nécessaire de déclarer les photos comme "visible par bluetooth". De plus, notez le slash final en et les doubles guillemets sans quoi la liste sera vide.

gastonobexftp -b 00:1D:25:FB:A2:75 --list "Favorite Images/"
Browsing 00:1D:25:FB:A2:75 ...
Connecting...done
Receiving "Favorite Images/"... Sending "Favorite Images"... done
/<?xml version="1.0"?>
<!DOCTYPE folder-listing SYSTEM "obex-folder-listing.dtd">
<folder-listing version="1.0">
<parent-folder/>
<file name="SP_A0031.jpg" modified="20090118T131633Z" size="272772" user-perm="RWD"/>
</folder-listing>
done
Disconnecting...done

Maintenant que nous connaissons son nom, nous pouvons soit récupérer ce fichier :

gastonobexftp -b 00:1D:25:FB:A2:76 --get "Favorite Images/SP_A0031.jpg"

Le fichier étant recopié en local, nous pouvons le détruire sur le téléphone :

gastonobexftp -b 00:1D:25:FB:A2:76 --delete "Favorite Images/SP_A0031.jpg"

Maintenant si nous voulons récupère l'ensemble des fichiers de ce dossier, petit script. Il s'utilise simplement en fournissant l'adresse bluetooth en paramètre :

#! /bin/sh
files=$(obexftp -b $1 --list "Favorite Images/" | cut -d\" -f2 | grep jpg)
file in $files ; do 
  obexftp -b $1 --get "Favorite Images/  $file"
done
script de récupération des fichiers du dossier 'Favorites Images'

Copier les contacts évolutions vers le téléphone

L'envoi de fichier est très simple en ligne de commande :

gastonobexftp -b 00:1D:25:FB:A2:76 --put ~/Desktop/sonnerie.mp3

Voilà qui va déjà nous permettre d'échanger photos, sonneries, images, etc, avec le mobile. La moitié du boulot est donc réalisée. Mais il nous reste encore à trouver le moyen d'exporter un carnet d'adresse.

Jusqu'à maintenant nous avons utilisé OBEX pour envoyer nos fichier, maintenant il existe une autre manière de faire la même chose, cette fois en passant par OPP (Object Push Protocol).

Contrairement à OBEX, OPP ne permet que d'envoyer un fichier au mobile à la différence près que le fichier reçu est "interprété" par le téléphone avant d'être stocké. Par exemple, et c'est ce qui va nous servir plus loin, si le fichier poussé est une vCard, il sera analysé par le téléphone et stocké dans le carnet d'adresses.

Comme nous avions un client OBEX TP, il nous faut donc maintenant un client OOP pour pousser nos fichiers. Malheureusement il n'y en a pas d'inclus dans la Mandriva en standard (du moins je n'en ai pas trouvé). La solution est donc de télécharger ussp-push et de le compiler nous-mêmes.

Rien de bien sorcier là dedans, juste décompresser l'archive, aller dans le dossier ./ussp-push/, vérifier que les paquets de développement de bluez et openobex sont installés (libbluez-devel, libopenobex1-devel), et lancer un classique make. Au bout de quelques secondes, un exécutable ussp-push est fabriqué, vous pouvez le déplacer en /usr/bin

ussp-push fonctionne, comme obexftp, avec l'adresse bluetooth du téléphone, un nom de fichier source et le nom du fichier destination. Par exemple pour envoyer un jpeg dans le téléphone. Et comme nous l'avons vu plus haut, le canal OPP est, pour ce téléphone, le 3. Cela nous donnes pour envoyer une photo dans le téléphone :

Notez l'utilisation du canal <kbd>3</kbd> correspondant au canal utilisé par OOP.
gastonussp-push 00:1D:25:FB:A2:75@3 ~/Desktop/photo.jpeg photo.jpeg

Pour envoyer notre carnet d'adresse dans le téléphone, nous allons devoir générer un fichier vCard à partir d'évolution. Ce type de fichier (extension .vcf) contient une ou plusieurs cartes de visite sous la forme d'une suite d'enregistrements composés de champs (nom, adresse, numéros, etc.). Or par chance la majorité des téléphones sont capables de comprendre nativement ce format lorsque la carte leur est envoyée via OPP.

Malheureusement mon téléphone, lui, ne sait pas analyser un fichier vCard comprenant plus d'une entrée. Il va donc falloir introduire une étape supplémentaire en générant plutôt un fichier VCF par contact. Cela se fait très simplement en utilisant l'outil dédié

gastonmkdir contacts; cd contacts
gaston/usr/lib64/evolution/2.24/evolution-addressbook-export --size=1 -a --output contact

Une fois la commande exécutée, nous avons une série de fichiers contactXXX contenant chacun un contact au format VCF. Il ne nous reste plus maintenant qu'à écrire le petit script PERL qui va ouvrir chaque fichier vcf, lire le nom du contact, et envoyer sa fichier avec le bon nom de destination dans le téléphone :

#! /usr/bin/perl

my ($directory,$address)=@ARGV;

print "Les fichiers vCard sont dans :$directory\n";

opendir(DIRHANDLE, "$directory") || die "Impossible d'ouvrir le dossier $directory : $!";
foreach $name (sort readdir(DIRHANDLE)) {
        open(DAT, "$directory/$name") || die("Impossible d'ouvrir le vCard : $!");
        while (<DAT>) {
                my $line=$_;
                if ($line =~ /^FN:.*$/) {
                        print "--== Envoi de $_";
                        system("ussp-push $address \"$directory/$name\" \"$name\"");
                        select(undef, undef, undef, 0.50);
                }
        }

}
closedir(DIRHANDLE);

Notez le 0.50 qui permet de régler un temps de pose pour que le téléphone ne sature pas (ici .5 correspond à 500ms). Vous pouvez l'augmenter si votre téléphone n'est pas assez véloce.

Ce script perl est simple d'utilisation, vous le lancez par la commande suivante :

rootchmod +x export_address_book.pl
root./export_address_book.pl ~/Desktop/phonebook 00:1D:25:FB:A2:76@3

Le premier paramètre est le dossier où se trouvent les vCards exportées, le second la combinaison de l'adresse de votre téléphone et du canal utilisé pour OOP.

Debuggage

hcid en mode debuggage

Pour savoir ce qui se passe lorsque rien ne se passe correctement, il y a toujours moyen de relancer hcid en mode bavard :

rootpkill hcid
roothcid -d -n -s -f /etc/bluetooth/hcid.conf
...

Pas de demande de PIN

La demande du code PIN passe normalement par l'applet gnome-bluetooth. Si la demande n'arrive jamais, il peut-être utile de prendre la main sur ce processus. Pour cela nous allons utiliser l'agent fournit par le projet bluez. Pour que ce dernier puisse fonctionner, il faut d'abord lui fournir un petit script qui va demander le code :

#! /bin/sh

zenity --entry
/home/gaston/pin.sh

Ensuite nous allons arrêter l'applet gnome et lancer notre propre système de demande :

si on lance directement passkey-agent, cela ne passe pas car l'applet Gnome est déjà enregistrée
gastonpasskey-agent --default /home/gaston/pin.sh
Can&039;t register passkey agent
Passkey agent already exists

gastonps -edaf | grep blue
gaston     6886  6706  0 10:34 ?        00:00:00 bluetooth-applet --singleton
gaston    21707 21423  0 10:53 pts/1    00:00:00 grep --color blue
gastonkill -9 6886
gastonpasskey-agent --default /home/gaston/pin.sh

Maintenant nous allons pouvoir voir si le code PIN est effectivement demandé.

Conclusion

Comme souvent la ligne de commande démontre sa capacité à nous permettre d'automatiser des tâches complexes à réaliser en mode graphique.