Bluetooth Rfcomm dans Windows 8.1 et Windows Phone 8

Windows 8.1 introduit une prise en charge complète de la communication Bluetooth Rfcomm via l'espace de noms Windows.Devices.Bluetooth.Rfcomm. Ce protocole permet d'établir des connexions persistantes entre appareils, similaire à TCP sur un réseau, en utilisant des sockets pour les flux de données continus. Cette fonctionnalité est idéale pour les applications telles que le contrôle à distance ou l'intégration de périphériques personnalisés.

Pour établir une connexion Rfcomm, les appareils doivent être préalablement appairés, ce qui simplifie l'authentification. Le processus implique deux rôles : un serveur (A) qui écoute les connexions et un client (B) qui initie la conneixon. Le serveur annonce sa disponibilité en mode "advertising", tandis que le client scanne les appareils appairés et établit une socket vers le serveur.

Exemple de connexion entre Windows Phone 8 et Windows 8.1

L'exemple suivant montre comment connecter un Lumia 925 (Windows Phone 8) à un ASUS VivoTab (Windows 8.1). Le VivoTab agit comme serveur, et le Lumia comme client. Les taps sur le téléphone sont transmis via Bluetooth pour déplacer un élément sur le tablette.

Côté serveur (Windows 8.1)

Commencez par configurer les capacités dans le manifeste de l'application :

<Capabilities>
    <Capability Name="privateNetworkClientServer" />
    <Capability Name="internetClientServer" />
    <m2:DeviceCapability Name="bluetooth.rfcomm">
        <m2:Device Id="any">
            <m2:Function Type="serviceId:A7EA96BB-4F95-4A91-9FDD-3CE3CFF1D8DA" />
        </m2:Device>
    </m2:DeviceCapability>
</Capabilities>

Ensuite, initialisez l'écoute Bluetooth :

private async Task ConfigurerServeur()
{
    var fournisseur = await RfcommServiceProvider.CreateAsync(
        RfcommServiceId.FromUuid(new Guid("A7EA96BB-4F95-4A91-9FDD-3CE3CFF1D8DA")));
    var ecouteur = new StreamSocketListener();
    ecouteur.ConnectionReceived += SurConnexionRecue;
    await ecouteur.BindServiceNameAsync(
        fournisseur.ServiceId.AsString(),
        SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication);
    var redacteurSdp = new DataWriter();
    redacteurSdp.WriteByte(0x01); // Type d'attribut de version
    redacteurSdp.WriteUInt32(1);  // Numéro de version
    var tamponSdp = redacteurSdp.DetachBuffer();
    fournisseur.SdpRawAttributes.Add(0x0100, tamponSdp); // Identifiant d'attribut
    fournisseur.StartAdvertising(ecouteur);
}

Lorqsu'une connexion est détectée, l'événement ConnectionReceived arrête l'annonce et stocke la socket :

private void SurConnexionRecue(StreamSocketListener ecouteur, StreamSocketListenerConnectionReceivedEventArgs args)
{
    fournisseur.StopAdvertising();
    ecouteur.Dispose();
    socketConnectee = args.Socket;
    lecteurDonnees = new DataReader(socketConnectee.InputStream);
    TraiterFlux();
}

Côté client (Windows Phone 8)

Scannez les appareils appairés et connectez-vous :

private async Task SeConnecter()
{
    PeerFinder.AlternateIdentities["Bluetooth:PAIRED"] = "";
    var appareils = await PeerFinder.FindAllPeersAsync();
    var cible = appareils.FirstOrDefault();
    if (cible != null)
    {
        socketClient = new StreamSocket();
        await socketClient.ConnectAsync(cible.HostName, "1");
        redacteurClient = new DataWriter(socketClient.OutputStream);
        boutonConnecter.Visibility = Visibility.Collapsed;
        zoneTactile.Tap += SurTapZoneTactile;
    }
}

Envoyez les coordonnées des taps via Bluetooth :

private async void SurTapZoneTactile(object sender, System.Windows.Input.GestureEventArgs e)
{
    if (redacteurClient != null)
    {
        var position = e.GetPosition(zoneTactile);
        redacteurClient.WriteInt32(0x02); // Commande pour tap
        redacteurClient.WriteInt32((int)position.X);
        redacteurClient.WriteInt32((int)position.Y);
        await redacteurClient.StoreAsync();
    }
}

Sur le serveur, le flux de données est traité en continu pour lire les commandes :

private async void TraiterFlux()
{
    while (true)
    {
        try
        {
            int commande = await LireEntierAsync(lecteurDonnees);
            switch (commande)
            {
                case 0x02: // Commande tap
                    await TraiterCommandeTap();
                    break;
            }
        }
        catch (PeerDisconnectedException)
        {
            break;
        }
    }
}

private async Task TraiterCommandeTap()
{
    int x = await LireEntierAsync(lecteurDonnees);
    int y = await LireEntierAsync(lecteurDonnees);
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        Canvas.SetLeft(elementEllipse, x);
        Canvas.SetTop(elementEllipse, y);
    });
}

Une méthode d'extension pour lire les entiers :

public static async Task<int> LireEntierAsync(this DataReader lecteur)
{
    uint charge = await lecteur.LoadAsync(sizeof(int));
    if (charge < sizeof(int))
        throw new PeerDisconnectedException();
    return lecteur.ReadInt32();
}

Étiquettes: Windows 8.1 Windows Phone 8 Bluetooth Rfcomm CSharp StreamSocket

Publié le 11 juin à 21h34