sicpaconnexions / SICPA_Connexions / Model / GestionnaireBLE.cs @ 35f65dee
Historique | Voir | Annoter | Télécharger (10,976 ko)
1 | 87e7d061 | ajournaux | 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 | 35f65dee | ajournaux | private String tempoLecture; |
24 | 03682d21 | ajournaux | private String retourBLE; |
25 | public event EventHandler RetourBlEMofifiee; |
||
26 | 87e7d061 | ajournaux | public IDevice DeviceConnected { get; set; } |
27 | public IService SelectedService { get; set; } |
||
28 | 03682d21 | ajournaux | 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 | 87e7d061 | ajournaux | |
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 | 35f65dee | ajournaux | tempoLecture = tempoLecture + charStrUTF8; |
190 | if (args.Characteristic.StringValue.EndsWith("\r\n")) |
||
191 | { |
||
192 | RetourBLE = tempoLecture; |
||
193 | tempoLecture = ""; |
||
194 | } |
||
195 | 87e7d061 | ajournaux | //_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 | 03682d21 | ajournaux | 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 | 87e7d061 | ajournaux | } |
238 | } |