Statistiques
| Branche: | Révision:

teotestbluetooth / TestTeoBluetooth / TestTeoBluetooth.Android / Connection / BluetoothConnectionService.cs @ 91ef3e8c

Historique | Voir | Annoter | Télécharger (5,905 ko)

1 58c56df1 Martin Toutant
using Android.App;
2 0875d625 Martin Toutant
using Android.Bluetooth;
3 58c56df1 Martin Toutant
using Android.Content;
4
using Android.OS;
5
using Android.Runtime;
6
using Android.Views;
7
using Android.Widget;
8 0875d625 Martin Toutant
using Java.Util;
9 58c56df1 Martin Toutant
using System;
10
using System.Collections.Generic;
11 0875d625 Martin Toutant
using System.IO;
12 58c56df1 Martin Toutant
using System.Linq;
13
using System.Text;
14 0875d625 Martin Toutant
using System.Threading;
15
using System.Threading.Tasks;
16 91ef3e8c Martin Toutant
using TestXamConnections.Droid.Utils;
17
using TestXamConnections.Models;
18
using TestXamConnections.Connection;
19 58c56df1 Martin Toutant
20 91ef3e8c Martin Toutant
namespace TestXamConnections.Droid.Connection
21 58c56df1 Martin Toutant
{
22
    /* Classe permettant d'établir une connection Bluetooth
23
     * Avec socket RFCOMM connecté au SPP
24
     */
25 91ef3e8c Martin Toutant
    public class BluetoothConnectionService : IConnectionService
26 58c56df1 Martin Toutant
    {
27
28 0875d625 Martin Toutant
        private readonly BluetoothAdapter bluetoothAdapter;
29
        private Thread listeningThread;
30
        private BluetoothSocket socket;
31
        private readonly string sppUUID = "00001101-0000-1000-8000-00805f9b34fb";
32
33 91ef3e8c Martin Toutant
        public static readonly BluetoothConnectionService Instance = new BluetoothConnectionService();
34
35
        public BluetoothConnectionService()
36 0875d625 Martin Toutant
        { 
37
            bluetoothAdapter = BluetoothAdapter.DefaultAdapter;
38
        }
39 91ef3e8c Martin Toutant
40 0875d625 Martin Toutant
        public async Task<bool> Connect(Device btDevice)
41
        {
42
            try
43
            {
44
                // Si jamais on est en train de scanner
45
                // On annule le scan
46
                if (bluetoothAdapter.IsDiscovering)
47
                {
48
                    bluetoothAdapter.CancelDiscovery();
49
                }
50
51
                BluetoothDevice droidBtDevice = bluetoothAdapter.GetRemoteDevice(btDevice.MACAddress);
52
                //Android.Bluetooth.BluetoothDevice droidBtDevice = adapter.BondedDevices.FirstOrDefault(x => (x.Address == bluetoothDevice.Address));
53
                if (droidBtDevice != null)
54
                {
55
                    // Si le socket est occupé pour une autre connexion
56
                    // On ferme la connexion existante
57
                    if (socket != null)
58
                    {
59
                        await CloseConnection();
60
                    }
61
62
                    // Creation du canal RFCOMM (non sécurisé)
63
                    socket = droidBtDevice.CreateInsecureRfcommSocketToServiceRecord(UUID.FromString(sppUUID));
64
65
                    CancellationTokenSource cts = new CancellationTokenSource();
66
67
                    cts.CancelAfter(50000);
68
                    await socket.ConnectAsync().WithCancellation(cts.Token);
69
70
                    if (listeningThread != null) listeningThread.Abort();
71
                    listeningThread = new Thread(async delagate => await ListeningAsync());
72
                    listeningThread.Start();
73
74
                    return true;
75
                }
76
            }
77
            catch (Exception ex)
78
            {
79
                System.Diagnostics.Debug.WriteLine(ex);
80
            }
81
82
            return false;
83
        }
84
85
        // Fonction d'écoute pour le Thread d'écoute
86
        private async Task ListeningAsync()
87
        {
88
            try
89
            {
90
                byte[] buffer = new byte[1024];
91
                while (socket.IsConnected)
92
                {
93
                    int byteAvailable = await socket.InputStream.ReadAsync(buffer, 0, buffer.Length);
94
                    // Resize the byte array 
95
                    byte[] filledBuffer = buffer.Take(byteAvailable).ToArray();
96
                    Application.SynchronizationContext.Post(_ => { OnDataReceived(filledBuffer); }, null);
97
                }
98
            }
99
            catch (IOException ex)
100
            {
101
                System.Diagnostics.Debug.WriteLine(ex);
102
            }
103
            catch (ThreadAbortException taEx)
104
            {
105
                System.Diagnostics.Debug.WriteLine(taEx);
106
            }
107
            catch (Exception ex)
108
            {
109
                System.Diagnostics.Debug.WriteLine(ex);
110
            }
111
        }
112
113
        public EventHandler<string> DataReceivedEvent { get; set; }
114
        private string _bufferedData;
115
116
        /* 
117
         * Fonction appelée à la reception de données
118
         * Trigger l'evenement DataReceivedEvent
119
         * 
120
         * IMPORTANT: Les trames peuvent arriver découpées,
121
         * Donc les données sont gardées dans un buffer d'envoi
122
         * nommé _bufferedData
123
         */
124
        private void OnDataReceived(byte[] buffer)
125
        {
126
            // Si le premier character est 2 (ASCII: STX)
127
            // Alors c'est le début de la trame.
128
            if (buffer[0] == 2)
129
            {
130
                _bufferedData = "";
131
                // Si character seul on quitte
132
                if (buffer.Length == 1)
133
                {
134
                    return;
135
                }
136
                // On enlève STX
137
                buffer = buffer.Skip(1).ToArray();
138
                // On mets le début de la trame dans buffer d'envoi
139
                _bufferedData += Encoding.ASCII.GetString(buffer);
140
            }
141
142
            // Si le dernier character est 13 (ASCII: CR)
143
            // Alors la trame est terminée
144
            if (buffer[^1] == 13)
145
            {
146
                // On enlève CR
147
                buffer = buffer.SkipLast(1).ToArray();
148
                // Conversion en chaîne de caractères
149
                // Et on complète le buffer d'envoi
150
                _bufferedData += Encoding.ASCII.GetString(buffer);
151
                // Trigger evènement
152
                DataReceivedEvent.Invoke(this, _bufferedData);
153
            }
154
        }
155
156
        private Task<bool> CloseConnection()
157
        {
158
            while (socket.IsConnected) socket.Close();
159
            return Task.FromResult(true);
160
        }
161
162
        public Task<bool> SendCommand(byte[] hexValues)
163
        {
164
            if (socket.IsConnected == false)
165
            {
166
                return Task.FromResult(false);
167
            }
168
            else
169
            {
170
                // Envoi de la commande
171
                socket.OutputStream.Write(hexValues, 0, hexValues.Length);
172
                socket.OutputStream.Flush();
173
            }
174
            return Task.FromResult(true);
175
        }
176
177 58c56df1 Martin Toutant
    }
178
}