Statistiques
| Branche: | Révision:

sicpaconnexions / SICPA_Connexions / Model / GestionnaireBLE.cs @ 35f65dee

Historique | Voir | Annoter | Télécharger (10,976 ko)

1
using Plugin.BLE;
2
using Plugin.BLE.Abstractions;
3
using Plugin.BLE.Abstractions.Contracts;
4
using Plugin.BLE.Abstractions.EventArgs;
5
using System;
6
using System.Collections.Generic;
7
using System.Linq;
8
using System.Text;
9
using System.Threading.Tasks;
10

    
11
namespace SICPA_Connexions.Model
12
{
13
    public class GestionnaireBLE
14
    {
15
        // Class for the Bluetooth adapter
16
        private readonly IAdapter bluetoothAdapter;
17
        // Empty list to store BLE devices that can be detected by the Bluetooth adapter
18
        private List<IDevice> gattDevices;
19
        private List<IService> servicesList;
20
        private List<ICharacteristic> charList;
21
        private ICharacteristic characRead;
22
        private ICharacteristic characWrite;
23
        private String tempoLecture;
24
        private String retourBLE;
25
        public event EventHandler RetourBlEMofifiee;
26
        public IDevice DeviceConnected { get; set; }
27
        public IService SelectedService { get; set; }
28
        public String RetourBLE
29
        {
30
            get
31
            {
32
                return retourBLE;
33
            }
34
            set
35
            {
36
                if (retourBLE != value)
37
                {
38
                    retourBLE = value;
39
                    OnRetourBLEMofifiee(EventArgs.Empty);
40
                }
41
            }
42
        }
43

    
44
        public void OnRetourBLEMofifiee(EventArgs e)
45
        {
46
            RetourBlEMofifiee?.Invoke(this, e);
47
        }
48

    
49
        public GestionnaireBLE()
50
        {
51
            gattDevices = new List<IDevice>();
52
            servicesList = new List<IService>();
53
            charList = new List<ICharacteristic>(); // List for the available Characteristics on the BLE Device
54
            bluetoothAdapter = CrossBluetoothLE.Current.Adapter;               // Point bluetoothAdapter to the current adapter on the phone
55
            bluetoothAdapter.DeviceDiscovered += (sender, foundBleDevice) =>   // When a BLE Device is found, run the small function below to add it to our list
56
            {
57
                if (foundBleDevice.Device != null && !string.IsNullOrEmpty(foundBleDevice.Device.Name))
58
                    gattDevices.Add(foundBleDevice.Device);
59
            };
60
        }
61

    
62
     
63
        public async Task ScanBLE()
64
        {
65

    
66
            if (!await PermissionsGrantedAsync())                                                           // Make sure there is permission to use Bluetooth
67
            {
68
                await Application.Current.MainPage.DisplayAlert("Persmission requise", "L'application a besoin des permissions locales", "OK");
69
                return;
70
            }
71

    
72
            gattDevices.Clear();                                                                           // Also clear the _gattDevices list
73

    
74
            if (!bluetoothAdapter.IsScanning)                                                              // Make sure that the Bluetooth adapter is scanning for devices
75
            {
76
                await bluetoothAdapter.StartScanningForDevicesAsync();
77
            }
78

    
79
            foreach (var device in bluetoothAdapter.ConnectedDevices)                                      // Make sure BLE devices are added to the _gattDevices list
80
                gattDevices.Add(device);
81

    
82
            foreach (var device in bluetoothAdapter.BondedDevices)
83
                gattDevices.Add(device);
84

    
85
            foreach (IDevice item in gattDevices)
86
            {
87
                if (item.Name.Contains("SICPA"))
88
                {
89
                    if (item.State == DeviceState.Connected)                                                // Check first if we are already connected to the BLE Device 
90
                    {
91
                        await RecuperationServices(item);
92
                    }
93
                    else
94
                    {
95
                        try
96
                        {
97
                            var connectParameters = new ConnectParameters(false, true);
98
                            await bluetoothAdapter.ConnectToDeviceAsync(item, connectParameters);          // if we are not connected, then try to connect to the BLE Device selected
99
                            await RecuperationServices(item);
100
                        }
101
                        catch
102
                        {
103
                            await Application.Current.MainPage.DisplayAlert("Erreur de connexion", "Erreur de connexion au BLE " + item.Name, "OK");
104
                        }
105
                    }
106
                }
107
            }
108
        }
109

    
110
        private async Task<bool> PermissionsGrantedAsync()      // Function to make sure that all the appropriate approvals are in place
111
        {
112
            var status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
113

    
114
            if (status != PermissionStatus.Granted)
115
            {
116
                status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
117
            }
118

    
119
            return status == PermissionStatus.Granted;
120
        }
121

    
122
        private async Task RecuperationServices(IDevice device)
123
        {
124
            try
125
            {
126
                var servicesListReadOnly = await device.GetServicesAsync();           // Read in the Services available
127

    
128
                servicesList.Clear();
129
                for (int i = 0; i < servicesListReadOnly.Count; i++)                             // Cycle through the found interfaces
130
                {
131
                    servicesList.Add(servicesListReadOnly[i]);                                 // Write to a list of service interfaces
132
                    if (servicesListReadOnly[i].Id.ToString().Substring(0, 8) == "6e400001")
133
                    {
134
                        SelectedService = servicesListReadOnly[i];
135
                    }
136
                }
137
                if (SelectedService != null)
138
                {
139
                    var charListReadOnly = await SelectedService.GetCharacteristicsAsync();       // Read in available Characteristics
140

    
141
                    charList.Clear();
142
                    for (int i = 0; i < charListReadOnly.Count; i++)                               // Cycle through available interfaces
143
                    {
144
                        charList.Add(charListReadOnly[i]);                                        // Write to a list of Chars
145
                        // IMPORTANT: listview cannot cope with entries that have the exact same name. That is why I added "i" to the beginning of the name. If you add the UUID you can delete "i" again.
146
                        if (charListReadOnly[i].CanRead || charListReadOnly[i].CanUpdate)
147
                        {
148
                            characRead = charListReadOnly[i];
149
                            characRead.ValueUpdated += CharacRead_ValueUpdated;
150
                        }
151
                        if (charListReadOnly[i].CanWrite) characWrite = charListReadOnly[i];
152
                    }
153
                    DeviceConnected = device;
154
                }
155
                else
156
                {
157
                    await Application.Current.MainPage.DisplayAlert("Erreur récupération Characteristics", "Erreur récupération Characteristics", "OK");
158
                }
159
            }
160
            catch
161
            {
162
                await Application.Current.MainPage.DisplayAlert("Erreur d'initialisation", "Erreur d'initialisation aux services", "OK");
163
            }
164
        }
165

    
166
        private void CharacRead_ValueUpdated(object sender, CharacteristicUpdatedEventArgs args)
167
        {
168
            var receivedBytes = args.Characteristic.Value;                              // read in received bytes
169
            Console.WriteLine("byte array: " + BitConverter.ToString(receivedBytes));   // write to the console for debugging
170

    
171

    
172
            string charStrBytes = "";                                                                           // in the following section the received bytes will be displayed in different ways (you can select the method you need)
173
            string charStrUTF8 = "";
174
            if (receivedBytes != null)
175
            {
176
                charStrBytes = "Bytes : " + BitConverter.ToString(receivedBytes);                                // by directly converting the bytes to strings we see the bytes themselves as they are received
177
                charStrUTF8 = Encoding.UTF8.GetString(receivedBytes, 0, receivedBytes.Length);  // This code interprets the bytes received as ASCII characters
178
            }
179

    
180
            if (receivedBytes.Length <= 4)
181
            {                                                                                               // If only 4 or less bytes were received than it could be that an INT was sent. The code here combines the 4 bytes back to an INT
182
                int char_val = 0;
183
                for (int i = 0; i < receivedBytes.Length; i++)
184
                {
185
                    char_val |= (receivedBytes[i] << i * 8);
186
                }
187
                charStrBytes += " | int: " + char_val.ToString();
188
            }
189
            tempoLecture = tempoLecture + charStrUTF8;
190
            if (args.Characteristic.StringValue.EndsWith("\r\n"))
191
            {
192
                RetourBLE = tempoLecture;
193
                tempoLecture = "";
194
            }
195
            //_charStr += Environment.NewLine;                                                                // the NewLine command is added to go to the next line
196

    
197
            //MainThread.BeginInvokeOnMainThread(() =>                                      // as this is a callback function, the "MainThread" needs to be invoked to update the GUI
198
            //{
199
            //    Output.Text += _charStr;
200
            //});
201
        }
202

    
203
        public  async Task LectureTag(IDevice deviceConnected)
204
        {
205
            try
206
            {
207
                String cmd = "READ";
208

    
209
                List<byte> local_frame = new List<byte>();
210
                CRC crcProcess = new CRC();
211
                byte local_crc;
212

    
213
                local_frame.Add(BytesPrtc.STX); //add STX byte
214
                local_frame.Add(BytesPrtc.DST_TX); //add DST byte
215
                local_frame.Add(BytesPrtc.SRC_TX); //add SRC byte
216
                for (int i = 0; i < cmd.Length; i++)
217
                {
218
                    local_frame.Add((byte)cmd[i]); //add cmd string 
219
                }
220
                crcProcess.putBytes(local_frame.ToArray()); //send that buffer (without "the CRC" and ETX bytes !)
221
                local_crc = crcProcess.getCRC(); //calculate CRC with that buffer
222

    
223
                local_frame.Add(local_crc); //add CRC byte
224
                local_frame.Add(BytesPrtc.ETX); //add ETX byte
225

    
226
                /////////////////////////////////////////////
227
                //And now send buffer !
228
                await characWrite.WriteAsync(local_frame.ToArray());
229
                await characRead.StartUpdatesAsync();
230
            }
231
            catch
232
            {
233
                await Application.Current.MainPage.DisplayAlert("Erreur de lecture", "Erreur de lecture du Tag", "OK");
234
            }
235
        }
236

    
237
    }
238
}