Bluetooth.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. using Plugin.BLE;
  8. using Plugin.BLE.Abstractions;
  9. using Plugin.BLE.Abstractions.Contracts;
  10. using Xamarin.Forms;
  11. namespace InABox.Mobile
  12. {
  13. public class Bluetooth
  14. {
  15. public delegate void BluetoothEvent(Bluetooth sender);
  16. public event BluetoothEvent OnScanFinished;
  17. public TimeSpan ScanDelay { get; set; }
  18. public String[] Devices { get; private set; }
  19. public int[] BatteryLevels { get; private set; }
  20. public DateTime TimeStamp { get; private set; }
  21. public List<string> KnownBlueToothMACAddresses { get; set; }
  22. public List<string> DetectedBlueToothMACAddresses { get; set; }
  23. public List<string> SavedBlueToothMACAddresses { get; set; }
  24. private Dictionary<String, IDevice> _devicemap = new Dictionary<string, IDevice>();
  25. IBluetoothLE bluetooth = null;
  26. private bool bScanning = false;
  27. private Dictionary<String, int> DiscoveredDevices = new Dictionary<string, int>();
  28. private Dictionary<String, String> _keys = null;
  29. private bool _disabled = false;
  30. public bool Disabled
  31. {
  32. get { return _disabled; }
  33. set
  34. {
  35. if (IsScanning)
  36. StopScanning();
  37. _disabled = true;
  38. }
  39. }
  40. ////List<IDevice> devices = new List<IDevice>();
  41. //List<GPSTrackerLocation> bluetoothdevices = new List<GPSTrackerLocation>();
  42. public Bluetooth() : base()
  43. {
  44. TimeStamp = DateTime.MinValue;
  45. ScanDelay = new TimeSpan(0, 6, 0);
  46. //ScanDelay = new TimeSpan(0, 0, 0);
  47. bluetooth = CrossBluetoothLE.Current;
  48. bluetooth.Adapter.DeviceDiscovered += Adapter_DeviceDiscovered;
  49. bluetooth.Adapter.ScanMode = Plugin.BLE.Abstractions.Contracts.ScanMode.LowLatency;
  50. bluetooth.Adapter.ScanTimeout = 5000;
  51. bluetooth.Adapter.ScanTimeoutElapsed += ScanFinished;
  52. Devices = new String[] { };
  53. BatteryLevels = new int[] { };
  54. DetectedBlueToothMACAddresses = new List<string>();
  55. KnownBlueToothMACAddresses = new List<string>();
  56. SavedBlueToothMACAddresses = new List<string>();
  57. }
  58. public async Task UnlockDigitalKey(String macaddress, Guid serviceid, Guid characteristicid, String key)
  59. {
  60. if (!_disabled)
  61. throw new Exception("BT Scanning must be disabled!");
  62. _devicemap.TryGetValue(macaddress,out IDevice device);
  63. if (device == null)
  64. throw new Exception("Device not Found!");
  65. try
  66. {
  67. await bluetooth.Adapter.ConnectToDeviceAsync(device);
  68. if (!bluetooth.Adapter.ConnectedDevices.Contains(device))
  69. throw new Exception("Cannot Connect to Device!");
  70. var service = await device.GetServiceAsync(serviceid);
  71. if (service == null)
  72. throw new Exception("Service Not Found!");
  73. var characteristic = await service.GetCharacteristicAsync(characteristicid);
  74. if (characteristic == null)
  75. throw new Exception("Characteristic Not Found!");
  76. var write = await characteristic.WriteAsync(Encoding.ASCII.GetBytes(key.ToUpper()));
  77. await bluetooth.Adapter.DisconnectDeviceAsync(device);
  78. }
  79. catch
  80. {
  81. if (bluetooth.Adapter.ConnectedDevices.Contains(device))
  82. await bluetooth.Adapter.DisconnectDeviceAsync(device);
  83. throw;
  84. }
  85. }
  86. public bool IsScanning { get; private set; }
  87. private async Task<bool> UnlockDevice(IDevice idevice, String key)
  88. {
  89. bool result = false;
  90. Console.WriteLine(String.Format("** Found Device: {0} {1}", idevice.Name, idevice.Rssi));
  91. if (idevice.Rssi < -65)
  92. {
  93. Console.WriteLine(String.Format("** Device RSSI is too low: {0}", idevice.Rssi));
  94. return false;
  95. }
  96. try
  97. {
  98. await bluetooth.Adapter.ConnectToDeviceAsync(idevice);
  99. IService service = await idevice.GetServiceAsync(Guid.Parse("3317F54C-1C7E-EBE7-026E-3C819FD35476"));
  100. if (service != null)
  101. {
  102. Console.WriteLine("** Found Service 3317F54C-1C7E-EBE7-026E-3C819FD35476");
  103. ICharacteristic chr = await service.GetCharacteristicAsync(Guid.Parse("20852B39-4455-EE15-089B-D1629FE76927"));
  104. if (chr != null)
  105. {
  106. Console.WriteLine("** Found Characteristic 20852B39-4455-EE15-089B-D1629FE76927");
  107. //var data = await chr.ReadAsync();
  108. //Console.WriteLine("- Found Data: " + String.Join("-", data.Select(x => String.Format("{0:X2}", x))));
  109. var newdata = Encoding.ASCII.GetBytes(key);
  110. bool bWrite = await chr.WriteAsync(newdata);
  111. if (bWrite)
  112. {
  113. Console.WriteLine("** Wrote Data " + String.Join("-", newdata.Select(x => String.Format("{0:X2}", x))));
  114. //var confdata = await chr.ReadAsync();
  115. //Console.WriteLine("- Read Data: " + String.Join("-", confdata.Select(x => String.Format("{0:X2}", x))));
  116. result = true;
  117. }
  118. }
  119. }
  120. await bluetooth.Adapter.DisconnectDeviceAsync(idevice);
  121. }
  122. catch (Exception err)
  123. {
  124. // ... could not connect to device
  125. }
  126. return result;
  127. }
  128. private async void Adapter_DeviceDiscovered(object sender, Plugin.BLE.Abstractions.EventArgs.DeviceEventArgs e)
  129. {
  130. try
  131. {
  132. await Task.Run(() =>
  133. {
  134. if (string.IsNullOrWhiteSpace(e.Device.NativeDevice.ToString()))
  135. return;
  136. _devicemap[e.Device.NativeDevice.ToString()] = e.Device;
  137. if (KnownBlueToothMACAddresses.Count == 0)
  138. return;
  139. string deviceID = e.Device.NativeDevice.ToString();
  140. if (KnownBlueToothMACAddresses.Contains(deviceID))
  141. {
  142. if (!DetectedBlueToothMACAddresses.Contains(deviceID))
  143. {
  144. DetectedBlueToothMACAddresses.Add(deviceID);
  145. }
  146. if (!SavedBlueToothMACAddresses.Contains(deviceID))
  147. {
  148. SavedBlueToothMACAddresses.Add(deviceID);
  149. }
  150. }
  151. });
  152. }
  153. catch
  154. { }
  155. #region OLD
  156. //if (_keys != null)
  157. //{
  158. // String address = e.Device.NativeDevice?.ToString();
  159. // if (_keys.ContainsKey(address))
  160. // {
  161. // //bool result = await UnlockDevice(e.Device, _keys[address]);
  162. // //if (result)
  163. // //{
  164. // // await bluetooth.Adapter.StopScanningForDevicesAsync();
  165. // // IsScanning = false;
  166. // //}
  167. // }
  168. //}
  169. //var record = e.Device.AdvertisementRecords.FirstOrDefault(X => X.Type == Plugin.BLE.Abstractions.AdvertisementRecordType.ServiceData);
  170. //if (record != null)
  171. //{
  172. // byte[] id = record.Data.TakeLast(record.Data.Length == 14 ? 6 : 4).ToArray();
  173. // String sid = "";
  174. // foreach (byte bs in id)
  175. // sid = sid + Convert.ToChar(bs);
  176. // DiscoveredDevices[sid] = record.Data.Length >= 7 ? (int)record.Data[6] : -1;
  177. //}
  178. #endregion
  179. }
  180. public bool RecentlyScanned
  181. {
  182. get
  183. {
  184. return (DateTime.Now.Subtract(TimeStamp).Ticks < ScanDelay.Ticks);
  185. }
  186. }
  187. public void ScanForDevices(Dictionary<String, String> keys = null)
  188. {
  189. if (_disabled)
  190. return;
  191. try
  192. {
  193. if (bluetooth.Adapter.IsScanning)
  194. {
  195. if (keys != null)
  196. {
  197. StopScanning();
  198. }
  199. else
  200. return;
  201. }
  202. SavedBlueToothMACAddresses.Clear();
  203. if (!bluetooth.IsAvailable)
  204. {
  205. ScanFinished(this, new EventArgs());
  206. IsScanning = false;
  207. }
  208. else
  209. {
  210. IsScanning = true;
  211. bluetooth.Adapter.StartScanningForDevicesAsync();
  212. }
  213. }
  214. catch (Exception e)
  215. { }
  216. }
  217. private void StopScanning()
  218. {
  219. bluetooth.Adapter.StopScanningForDevicesAsync().ConfigureAwait(false);
  220. IsScanning = false;
  221. }
  222. private void ScanFinished(object sender, EventArgs e)
  223. {
  224. try
  225. {
  226. _keys = null;
  227. TimeStamp = DateTime.Now;
  228. //List<String> devices = new List<String>();
  229. //List<int> levels = new List<int>();
  230. //foreach (var key in DiscoveredDevices.Keys)
  231. //{
  232. // devices.Add(key);
  233. // levels.Add(DiscoveredDevices[key]);
  234. //}
  235. Devices = SavedBlueToothMACAddresses.ToArray();
  236. //BatteryLevels = levels.ToArray();
  237. OnScanFinished?.Invoke(this);
  238. IsScanning = false;
  239. }
  240. catch
  241. { }
  242. }
  243. }
  244. }