sicpaconnexions / SICPA_Connexions / Model / GestionnaireBLE.cs @ 03682d21
Historique | Voir | Annoter | Télécharger (10,761 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 | 03682d21 | ajournaux | private String retourBLE; |
24 | public event EventHandler RetourBlEMofifiee; |
||
25 | 87e7d061 | ajournaux | public IDevice DeviceConnected { get; set; } |
26 | public IService SelectedService { get; set; } |
||
27 | 03682d21 | ajournaux | public String RetourBLE |
28 | { |
||
29 | get |
||
30 | { |
||
31 | return retourBLE; |
||
32 | } |
||
33 | set |
||
34 | { |
||
35 | if (retourBLE != value) |
||
36 | { |
||
37 | retourBLE = value; |
||
38 | OnRetourBLEMofifiee(EventArgs.Empty); |
||
39 | } |
||
40 | } |
||
41 | } |
||
42 | |||
43 | public void OnRetourBLEMofifiee(EventArgs e) |
||
44 | { |
||
45 | RetourBlEMofifiee?.Invoke(this, e); |
||
46 | } |
||
47 | 87e7d061 | ajournaux | |
48 | public GestionnaireBLE() |
||
49 | { |
||
50 | gattDevices = new List<IDevice>(); |
||
51 | servicesList = new List<IService>(); |
||
52 | charList = new List<ICharacteristic>(); // List for the available Characteristics on the BLE Device |
||
53 | bluetoothAdapter = CrossBluetoothLE.Current.Adapter; // Point bluetoothAdapter to the current adapter on the phone |
||
54 | bluetoothAdapter.DeviceDiscovered += (sender, foundBleDevice) => // When a BLE Device is found, run the small function below to add it to our list |
||
55 | { |
||
56 | if (foundBleDevice.Device != null && !string.IsNullOrEmpty(foundBleDevice.Device.Name)) |
||
57 | gattDevices.Add(foundBleDevice.Device); |
||
58 | }; |
||
59 | } |
||
60 | |||
61 | |||
62 | public async Task ScanBLE() |
||
63 | { |
||
64 | |||
65 | if (!await PermissionsGrantedAsync()) // Make sure there is permission to use Bluetooth |
||
66 | { |
||
67 | await Application.Current.MainPage.DisplayAlert("Persmission requise", "L'application a besoin des permissions locales", "OK"); |
||
68 | return; |
||
69 | } |
||
70 | |||
71 | gattDevices.Clear(); // Also clear the _gattDevices list |
||
72 | |||
73 | if (!bluetoothAdapter.IsScanning) // Make sure that the Bluetooth adapter is scanning for devices |
||
74 | { |
||
75 | await bluetoothAdapter.StartScanningForDevicesAsync(); |
||
76 | } |
||
77 | |||
78 | foreach (var device in bluetoothAdapter.ConnectedDevices) // Make sure BLE devices are added to the _gattDevices list |
||
79 | gattDevices.Add(device); |
||
80 | |||
81 | foreach (var device in bluetoothAdapter.BondedDevices) |
||
82 | gattDevices.Add(device); |
||
83 | |||
84 | foreach (IDevice item in gattDevices) |
||
85 | { |
||
86 | if (item.Name.Contains("SICPA")) |
||
87 | { |
||
88 | if (item.State == DeviceState.Connected) // Check first if we are already connected to the BLE Device |
||
89 | { |
||
90 | await RecuperationServices(item); |
||
91 | } |
||
92 | else |
||
93 | { |
||
94 | try |
||
95 | { |
||
96 | var connectParameters = new ConnectParameters(false, true); |
||
97 | await bluetoothAdapter.ConnectToDeviceAsync(item, connectParameters); // if we are not connected, then try to connect to the BLE Device selected |
||
98 | await RecuperationServices(item); |
||
99 | } |
||
100 | catch |
||
101 | { |
||
102 | await Application.Current.MainPage.DisplayAlert("Erreur de connexion", "Erreur de connexion au BLE " + item.Name, "OK"); |
||
103 | } |
||
104 | } |
||
105 | } |
||
106 | } |
||
107 | } |
||
108 | |||
109 | private async Task<bool> PermissionsGrantedAsync() // Function to make sure that all the appropriate approvals are in place |
||
110 | { |
||
111 | var status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>(); |
||
112 | |||
113 | if (status != PermissionStatus.Granted) |
||
114 | { |
||
115 | status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>(); |
||
116 | } |
||
117 | |||
118 | return status == PermissionStatus.Granted; |
||
119 | } |
||
120 | |||
121 | private async Task RecuperationServices(IDevice device) |
||
122 | { |
||
123 | try |
||
124 | { |
||
125 | var servicesListReadOnly = await device.GetServicesAsync(); // Read in the Services available |
||
126 | |||
127 | servicesList.Clear(); |
||
128 | for (int i = 0; i < servicesListReadOnly.Count; i++) // Cycle through the found interfaces |
||
129 | { |
||
130 | servicesList.Add(servicesListReadOnly[i]); // Write to a list of service interfaces |
||
131 | if (servicesListReadOnly[i].Id.ToString().Substring(0, 8) == "6e400001") |
||
132 | { |
||
133 | SelectedService = servicesListReadOnly[i]; |
||
134 | } |
||
135 | } |
||
136 | if (SelectedService != null) |
||
137 | { |
||
138 | var charListReadOnly = await SelectedService.GetCharacteristicsAsync(); // Read in available Characteristics |
||
139 | |||
140 | charList.Clear(); |
||
141 | for (int i = 0; i < charListReadOnly.Count; i++) // Cycle through available interfaces |
||
142 | { |
||
143 | charList.Add(charListReadOnly[i]); // Write to a list of Chars |
||
144 | // 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. |
||
145 | if (charListReadOnly[i].CanRead || charListReadOnly[i].CanUpdate) |
||
146 | { |
||
147 | characRead = charListReadOnly[i]; |
||
148 | characRead.ValueUpdated += CharacRead_ValueUpdated; |
||
149 | } |
||
150 | if (charListReadOnly[i].CanWrite) characWrite = charListReadOnly[i]; |
||
151 | } |
||
152 | DeviceConnected = device; |
||
153 | } |
||
154 | else |
||
155 | { |
||
156 | await Application.Current.MainPage.DisplayAlert("Erreur récupération Characteristics", "Erreur récupération Characteristics", "OK"); |
||
157 | } |
||
158 | } |
||
159 | catch |
||
160 | { |
||
161 | await Application.Current.MainPage.DisplayAlert("Erreur d'initialisation", "Erreur d'initialisation aux services", "OK"); |
||
162 | } |
||
163 | } |
||
164 | |||
165 | private void CharacRead_ValueUpdated(object sender, CharacteristicUpdatedEventArgs args) |
||
166 | { |
||
167 | var receivedBytes = args.Characteristic.Value; // read in received bytes |
||
168 | Console.WriteLine("byte array: " + BitConverter.ToString(receivedBytes)); // write to the console for debugging |
||
169 | |||
170 | |||
171 | string charStrBytes = ""; // in the following section the received bytes will be displayed in different ways (you can select the method you need) |
||
172 | string charStrUTF8 = ""; |
||
173 | if (receivedBytes != null) |
||
174 | { |
||
175 | charStrBytes = "Bytes : " + BitConverter.ToString(receivedBytes); // by directly converting the bytes to strings we see the bytes themselves as they are received |
||
176 | charStrUTF8 = Encoding.UTF8.GetString(receivedBytes, 0, receivedBytes.Length); // This code interprets the bytes received as ASCII characters |
||
177 | } |
||
178 | |||
179 | if (receivedBytes.Length <= 4) |
||
180 | { // 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 |
||
181 | int char_val = 0; |
||
182 | for (int i = 0; i < receivedBytes.Length; i++) |
||
183 | { |
||
184 | char_val |= (receivedBytes[i] << i * 8); |
||
185 | } |
||
186 | charStrBytes += " | int: " + char_val.ToString(); |
||
187 | } |
||
188 | RetourBLE = RetourBLE + charStrUTF8; |
||
189 | //_charStr += Environment.NewLine; // the NewLine command is added to go to the next line |
||
190 | |||
191 | //MainThread.BeginInvokeOnMainThread(() => // as this is a callback function, the "MainThread" needs to be invoked to update the GUI |
||
192 | //{ |
||
193 | // Output.Text += _charStr; |
||
194 | //}); |
||
195 | } |
||
196 | |||
197 | 03682d21 | ajournaux | public async Task LectureTag(IDevice deviceConnected) |
198 | { |
||
199 | try |
||
200 | { |
||
201 | String cmd = "READ"; |
||
202 | |||
203 | List<byte> local_frame = new List<byte>(); |
||
204 | CRC crcProcess = new CRC(); |
||
205 | byte local_crc; |
||
206 | |||
207 | local_frame.Add(BytesPrtc.STX); //add STX byte |
||
208 | local_frame.Add(BytesPrtc.DST_TX); //add DST byte |
||
209 | local_frame.Add(BytesPrtc.SRC_TX); //add SRC byte |
||
210 | for (int i = 0; i < cmd.Length; i++) |
||
211 | { |
||
212 | local_frame.Add((byte)cmd[i]); //add cmd string |
||
213 | } |
||
214 | crcProcess.putBytes(local_frame.ToArray()); //send that buffer (without "the CRC" and ETX bytes !) |
||
215 | local_crc = crcProcess.getCRC(); //calculate CRC with that buffer |
||
216 | |||
217 | local_frame.Add(local_crc); //add CRC byte |
||
218 | local_frame.Add(BytesPrtc.ETX); //add ETX byte |
||
219 | |||
220 | ///////////////////////////////////////////// |
||
221 | //And now send buffer ! |
||
222 | await characWrite.WriteAsync(local_frame.ToArray()); |
||
223 | await characRead.StartUpdatesAsync(); |
||
224 | } |
||
225 | catch |
||
226 | { |
||
227 | await Application.Current.MainPage.DisplayAlert("Erreur de lecture", "Erreur de lecture du Tag", "OK"); |
||
228 | } |
||
229 | } |
||
230 | |||
231 | 87e7d061 | ajournaux | } |
232 | } |