Révision 0875d625

Voir les différences:

TestTeoBluetooth/TestTeoBluetooth.Android/Connection/BluetoothConnection.cs
1 1
using Android.App;
2
using Android.Bluetooth;
2 3
using Android.Content;
3 4
using Android.OS;
4 5
using Android.Runtime;
5 6
using Android.Views;
6 7
using Android.Widget;
8
using Java.Util;
7 9
using System;
8 10
using System.Collections.Generic;
11
using System.IO;
9 12
using System.Linq;
10 13
using System.Text;
14
using System.Threading;
15
using System.Threading.Tasks;
16
using TeoTestBluetooth.Droid.Utils;
17
using TeoTestBluetooth.Models;
18
using TestTeoBluetooth.Connection;
11 19

  
12 20
namespace TestBLE.Droid.Connection
13 21
{
14 22
    /* Classe permettant d'établir une connection Bluetooth
15 23
     * Avec socket RFCOMM connecté au SPP
16 24
     */
17
    public class BluetoothConnection
25
    public class BluetoothConnection : IBluetoothConnectionService
18 26
    {
19 27

  
28
        private readonly BluetoothAdapter bluetoothAdapter;
29
        private Thread listeningThread;
30
        private BluetoothSocket socket;
31
        private readonly string sppUUID = "00001101-0000-1000-8000-00805f9b34fb";
32

  
33
        public BluetoothConnection()
34
        { 
35
            bluetoothAdapter = BluetoothAdapter.DefaultAdapter;
36
        }
37
        public async Task<bool> Connect(Device btDevice)
38
        {
39
            try
40
            {
41
                // Si jamais on est en train de scanner
42
                // On annule le scan
43
                if (bluetoothAdapter.IsDiscovering)
44
                {
45
                    bluetoothAdapter.CancelDiscovery();
46
                }
47

  
48
                BluetoothDevice droidBtDevice = bluetoothAdapter.GetRemoteDevice(btDevice.MACAddress);
49
                //Android.Bluetooth.BluetoothDevice droidBtDevice = adapter.BondedDevices.FirstOrDefault(x => (x.Address == bluetoothDevice.Address));
50
                if (droidBtDevice != null)
51
                {
52
                    // Si le socket est occupé pour une autre connexion
53
                    // On ferme la connexion existante
54
                    if (socket != null)
55
                    {
56
                        await CloseConnection();
57
                    }
58

  
59
                    // Creation du canal RFCOMM (non sécurisé)
60
                    socket = droidBtDevice.CreateInsecureRfcommSocketToServiceRecord(UUID.FromString(sppUUID));
61

  
62
                    CancellationTokenSource cts = new CancellationTokenSource();
63

  
64
                    cts.CancelAfter(50000);
65
                    await socket.ConnectAsync().WithCancellation(cts.Token);
66

  
67
                    if (listeningThread != null) listeningThread.Abort();
68
                    listeningThread = new Thread(async delagate => await ListeningAsync());
69
                    listeningThread.Start();
70

  
71
                    return true;
72
                }
73
            }
74
            catch (Exception ex)
75
            {
76
                System.Diagnostics.Debug.WriteLine(ex);
77
            }
78

  
79
            return false;
80
        }
81

  
82
        // Fonction d'écoute pour le Thread d'écoute
83
        private async Task ListeningAsync()
84
        {
85
            try
86
            {
87
                byte[] buffer = new byte[1024];
88
                while (socket.IsConnected)
89
                {
90
                    int byteAvailable = await socket.InputStream.ReadAsync(buffer, 0, buffer.Length);
91
                    // Resize the byte array 
92
                    byte[] filledBuffer = buffer.Take(byteAvailable).ToArray();
93
                    Application.SynchronizationContext.Post(_ => { OnDataReceived(filledBuffer); }, null);
94
                }
95
            }
96
            catch (IOException ex)
97
            {
98
                System.Diagnostics.Debug.WriteLine(ex);
99
            }
100
            catch (ThreadAbortException taEx)
101
            {
102
                System.Diagnostics.Debug.WriteLine(taEx);
103
            }
104
            catch (Exception ex)
105
            {
106
                System.Diagnostics.Debug.WriteLine(ex);
107
            }
108
        }
109

  
110
        public EventHandler<string> DataReceivedEvent { get; set; }
111
        private string _bufferedData;
112

  
113
        /* 
114
         * Fonction appelée à la reception de données
115
         * Trigger l'evenement DataReceivedEvent
116
         * 
117
         * IMPORTANT: Les trames peuvent arriver découpées,
118
         * Donc les données sont gardées dans un buffer d'envoi
119
         * nommé _bufferedData
120
         */
121
        private void OnDataReceived(byte[] buffer)
122
        {
123
            // Si le premier character est 2 (ASCII: STX)
124
            // Alors c'est le début de la trame.
125
            if (buffer[0] == 2)
126
            {
127
                _bufferedData = "";
128
                // Si character seul on quitte
129
                if (buffer.Length == 1)
130
                {
131
                    return;
132
                }
133
                // On enlève STX
134
                buffer = buffer.Skip(1).ToArray();
135
                // On mets le début de la trame dans buffer d'envoi
136
                _bufferedData += Encoding.ASCII.GetString(buffer);
137
            }
138

  
139
            // Si le dernier character est 13 (ASCII: CR)
140
            // Alors la trame est terminée
141
            if (buffer[^1] == 13)
142
            {
143
                // On enlève CR
144
                buffer = buffer.SkipLast(1).ToArray();
145
                // Conversion en chaîne de caractères
146
                // Et on complète le buffer d'envoi
147
                _bufferedData += Encoding.ASCII.GetString(buffer);
148
                // Trigger evènement
149
                DataReceivedEvent.Invoke(this, _bufferedData);
150
            }
151
        }
152

  
153
        private Task<bool> CloseConnection()
154
        {
155
            while (socket.IsConnected) socket.Close();
156
            return Task.FromResult(true);
157
        }
158

  
159
        public Task<bool> SendCommand(byte[] hexValues)
160
        {
161
            if (socket.IsConnected == false)
162
            {
163
                return Task.FromResult(false);
164
            }
165
            else
166
            {
167
                // Envoi de la commande
168
                socket.OutputStream.Write(hexValues, 0, hexValues.Length);
169
                socket.OutputStream.Flush();
170
            }
171
            return Task.FromResult(true);
172
        }
173

  
20 174
    }
21 175
}
TestTeoBluetooth/TestTeoBluetooth.Android/Connection/InternConnection.cs
8 8
using System.Collections.Generic;
9 9
using System.Linq;
10 10
using System.Text;
11
using System.Threading.Tasks;
12
using TeoTestBluetooth.Models;
13
using TestTeoBluetooth.Connection;
11 14

  
12 15
namespace TestBLE.Droid.Connection
13 16
{
......
15 18
     * Pré-installée sur l'appareil
16 19
     * Basée sur filtrage d'intent sur BroadcastReceiver
17 20
     */
18
    public class InternConnection
21
    public class InternConnection : IConnectionService
19 22
    {
23
        public EventHandler<string> DataReceivedEvent { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
24

  
25
        public Task<bool> Connect(Device device)
26
        {
27
            throw new NotImplementedException();
28
        }
29

  
30
        public Task<bool> SendCommand(byte[] hexValues)
31
        {
32
            throw new NotImplementedException();
33
        }
20 34
    }
21 35
}
TestTeoBluetooth/TestTeoBluetooth.Android/MainActivity.cs
6 6
using Android.OS;
7 7
using Xamarin.Forms;
8 8
using TeoTestBluetooth.Services;
9
using TestBLE.Droid.Connection;
10
using TestTeoBluetooth.Connection;
9 11

  
10 12
namespace TeoTestBluetooth.Droid
11 13
{
......
17 19
            base.OnCreate(savedInstanceState);
18 20

  
19 21
            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
20
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
21
            DependencyService.RegisterSingleton<IBluetoothService>(new Services.BluetoothService());
22
            Forms.Init(this, savedInstanceState);
23
            DependencyService.Register<IConnectionService, BluetoothConnection>();
24
            DependencyService.Register<IConnectionService, InternConnection>();
22 25
            LoadApplication(new App());
23 26
        }
24 27
        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
TestTeoBluetooth/TestTeoBluetooth.Android/Receivers/BluetoothReceiver.cs
23 23
                BluetoothDevice foundDevice = intent.GetParcelableExtra(BluetoothDevice.ExtraDevice) as BluetoothDevice;
24 24
                if (foundDevice != null)
25 25
                {
26
                    var btDevice = new Models.BTDevice
26
                    var btDevice = new Models.Device
27 27
                    {
28 28
                        MACAddress = foundDevice.Address,
29 29
                        Name = foundDevice.Name
TestTeoBluetooth/TestTeoBluetooth.Android/Services/BluetoothService.cs
33 33
        private BluetoothSocket socket;
34 34
        private readonly string sppUUID = "00001101-0000-1000-8000-00805f9b34fb";
35 35

  
36
        public ObservableCollection<BTDevice> FoundDevices = new ObservableCollection<BTDevice>();
36
        public ObservableCollection<Device> FoundDevices = new ObservableCollection<Device>();
37 37
        public BluetoothService()
38 38
        {
39
            FoundDevices = new ObservableCollection<BTDevice>();
39
            FoundDevices = new ObservableCollection<Device>();
40 40
            bluetoothAdapter = BluetoothAdapter.DefaultAdapter;
41 41
            bluetoothReceiver = new BluetoothReceiver();
42 42
            bluetoothReceiver.OnBluetoothDeviceDiscovered += DeviceDiscovered;
......
50 50
            Application.Context.RegisterReceiver(bluetoothReceiver, intentFilter);
51 51
        }
52 52

  
53
        public async Task<bool> Connect(BTDevice btDevice)
53
        public async Task<bool> Connect(Device btDevice)
54 54
        {
55 55
            try
56 56
            {
......
96 96
        }
97 97

  
98 98
        // Fonction d'écoute pour le Thread d'écoute
99
        private async Task ListeningAsync(BTDevice btDevice)
99
        private async Task ListeningAsync(Device btDevice)
100 100
        {
101 101
            try
102 102
            {
......
176 176
            if (discoveredDevices.FirstOrDefault(x => x.Address == e.Address) is null)
177 177
            {
178 178
                discoveredDevices.Add(e);
179
                FoundDevices.Add(new BTDevice() { Name = e.Name, MACAddress = e.Address });
179
                FoundDevices.Add(new Device() { Name = e.Name, MACAddress = e.Address });
180 180
            }
181 181
        }
182 182

  
183
        public ObservableCollection<BTDevice> DeviceList { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
183
        public ObservableCollection<Device> DeviceList { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
184 184

  
185 185
        public Task StartScan()
186 186
        {
......
199 199
            return scanCompletionSource.Task;
200 200
        }
201 201

  
202
        public Task<bool> Pair(BTDevice bluetoothDevice)
202
        public Task<bool> Pair(Device bluetoothDevice)
203 203
        {
204 204
            throw new NotImplementedException();
205 205
        }
206 206

  
207
        public Task<bool> Disconnect(BTDevice bluetoothDevice)
207
        public Task<bool> Disconnect(Device bluetoothDevice)
208 208
        {
209 209
            while (socket.IsConnected) socket.Close();
210 210
            return Task.FromResult(true);
......
225 225
            return Task.FromResult(true);
226 226
        }
227 227

  
228
        public ICollection<BTDevice> GetBondedDevices()
228
        public ICollection<Device> GetBondedDevices()
229 229
        {
230
            ICollection<BTDevice> ret = new ObservableCollection<BTDevice>();
230
            ICollection<Device> ret = new ObservableCollection<Device>();
231 231
            foreach (BluetoothDevice bondedDevice in bluetoothAdapter.BondedDevices)
232 232
            {
233
                BTDevice toAddItem = new BTDevice
233
                Device toAddItem = new Device
234 234
                {
235 235
                    MACAddress = bondedDevice.Address,
236 236
                    Name = bondedDevice.Name
TestTeoBluetooth/TestTeoBluetooth/Connection/IBluetoothConnectionService.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Threading.Tasks;
5
using TeoTestBluetooth.Models;
6

  
7
namespace TestTeoBluetooth.Connection
8
{
9
    public enum ConnectionType
10
    {
11
        Intern,
12
        Bluetooth,
13
        Wifi
14
    }
15

  
16
    public interface IBluetoothConnectionService : IConnectionService
17
    {
18

  
19
    }
20
}
TestTeoBluetooth/TestTeoBluetooth/Connection/IConnectionService.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Threading.Tasks;
5
using TeoTestBluetooth.Models;
6

  
7
namespace TestTeoBluetooth.Connection
8
{
9
    public interface IConnectionService
10
    {
11
        Task<bool> Connect(Device device);
12
        Task<bool> SendCommand(byte[] hexValues);
13
        EventHandler<string> DataReceivedEvent { get; set; }
14
    }
15
}
TestTeoBluetooth/TestTeoBluetooth/Models/BTDevice.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4

  
5
namespace TeoTestBluetooth.Models
6
{
7
    public class BTDevice
8
    {
9
        public string Name { get; set; }
10
        public string MACAddress { get; set; }
11

  
12
        public override string ToString()
13
        {
14
            return Name + ":" + MACAddress;
15
        }
16
    }
17
}
TestTeoBluetooth/TestTeoBluetooth/Models/Device.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4

  
5
namespace TeoTestBluetooth.Models
6
{
7
    public class Device
8
    {
9
        public string Name { get; set; }
10
        public string MACAddress { get; set; }
11

  
12
        public override string ToString()
13
        {
14
            return Name + ":" + MACAddress;
15
        }
16
    }
17
}
TestTeoBluetooth/TestTeoBluetooth/Services/IBluetoothService.cs
10 10
    public interface IBluetoothService
11 11
    {
12 12
        Task StartScan();
13
        Task<bool> Pair(BTDevice bluetoothDevice);
14
        Task<bool> Connect(BTDevice bluetoothDevice);
15
        Task<bool> Disconnect(BTDevice bluetoothDevice);
13
        Task<bool> Pair(Device bluetoothDevice);
14
        Task<bool> Connect(Device bluetoothDevice);
15
        Task<bool> Disconnect(Device bluetoothDevice);
16 16
        Task<bool> SendHexValues(byte[] hexValues);
17
        ICollection<BTDevice> GetBondedDevices();
17
        ICollection<Device> GetBondedDevices();
18 18
        EventHandler<string> DataReceivedEvent { get; set; }
19
        ObservableCollection<BTDevice> DeviceList { get; set; }
19
        ObservableCollection<Device> DeviceList { get; set; }
20 20
    }
21 21
}
TestTeoBluetooth/TestTeoBluetooth/ViewModels/AccueilViewModel.cs
39 39
        {
40 40
            ShowBondedDevices = true;
41 41
            BondedDevicesList.Clear();
42
            foreach (BTDevice bondedDevice in BluetoothService.GetBondedDevices())
42
            foreach (Models.Device bondedDevice in BluetoothService.GetBondedDevices())
43 43
            {
44 44
                DeviceItemViewModel toAddItem = new DeviceItemViewModel(bondedDevice);
45 45
                BondedDevicesList.Add(toAddItem);
TestTeoBluetooth/TestTeoBluetooth/ViewModels/DeviceItemViewModel.cs
13 13
{
14 14
    public class DeviceItemViewModel : ViewModelBase
15 15
    {
16
        private BTDevice device;
17
        public BTDevice Device
16
        private Models.Device device;
17
        public Models.Device Device
18 18
        {
19 19

  
20 20
            get => device;
......
29 29

  
30 30
        public ICommand NavigateToDeviceViewCommand { private set; get; }
31 31

  
32
        public DeviceItemViewModel(BTDevice device)
32
        public DeviceItemViewModel(Models.Device device)
33 33
        {
34 34
            Device = device;
35 35
            NavigateToDeviceViewCommand = new Command(async () => await NavigateToDevice());
36 36
        }
37 37

  
38
        public void Update(BTDevice newDevice = null)
38
        public void Update(Models.Device newDevice = null)
39 39
        {
40 40
            if (newDevice != null)
41 41
            {
TestTeoBluetooth/TestTeoBluetooth/ViewModels/DeviceViewModel.cs
15 15
    {
16 16
        private bool isConnected;
17 17
        private string data;
18
        private BTDevice device;
18
        private Models.Device device;
19 19

  
20 20
        private bool isVisibleData;
21 21

  
......
31 31
            set { SetProperty(ref isConnected, value); }
32 32
        }
33 33

  
34
        public BTDevice Device
34
        public Models.Device Device
35 35
        {
36 36
            get { return device; }
37 37
            set { SetProperty(ref device, value); }
......
55 55
        }
56 56
        public ICommand ConnectToDeviceCommand { private set; get; }
57 57

  
58
        public DeviceViewModel(BTDevice device)
58
        public DeviceViewModel(Models.Device device)
59 59
        {
60 60
            Device = device;
61 61
            IsConnected = false;
TestTeoBluetooth/TestTeoBluetooth/Views/DeviceView.xaml.cs
13 13
    [XamlCompilation(XamlCompilationOptions.Compile)]
14 14
    public partial class DeviceView : ContentPage
15 15
    {
16
        public DeviceView(BTDevice device)
16
        public DeviceView(Models.Device device)
17 17
        {
18 18
            InitializeComponent();
19 19
            BindingContext = new DeviceViewModel(device);

Formats disponibles : Unified diff