Bluetooth.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using Plugin.BLE;
  7. using Plugin.BLE.Abstractions.Contracts;
  8. namespace InABox.Mobile
  9. {
  10. public class Bluetooth
  11. {
  12. public delegate void BluetoothEvent(Bluetooth sender);
  13. public event BluetoothEvent OnScanFinished;
  14. public TimeSpan ScanDelay { get; set; }
  15. public String[] Devices { get; private set; }
  16. public int[] BatteryLevels { get; private set; }
  17. public DateTime TimeStamp { get; private set; }
  18. public string[] KnownBlueToothMACAddresses { get; set; }
  19. public List<string> DetectedBlueToothMACAddresses { get; set; }
  20. public List<string> SavedBlueToothMACAddresses { get; set; }
  21. private Dictionary<String, IDevice> _devicemap = new Dictionary<string, IDevice>();
  22. IBluetoothLE bluetooth = null;
  23. private bool bScanning = false;
  24. private Dictionary<String, int> DiscoveredDevices = new Dictionary<string, int>();
  25. private Dictionary<String, String> _keys = null;
  26. private bool _disabled = false;
  27. public bool Disabled
  28. {
  29. get { return _disabled; }
  30. set
  31. {
  32. if (IsScanning)
  33. StopScanning();
  34. _disabled = true;
  35. }
  36. }
  37. ////List<IDevice> devices = new List<IDevice>();
  38. //List<GPSTrackerLocation> bluetoothdevices = new List<GPSTrackerLocation>();
  39. public Bluetooth() : base()
  40. {
  41. TimeStamp = DateTime.MinValue;
  42. ScanDelay = new TimeSpan(0, 6, 0);
  43. //ScanDelay = new TimeSpan(0, 0, 0);
  44. bluetooth = CrossBluetoothLE.Current;
  45. bluetooth.Adapter.DeviceDiscovered += Adapter_DeviceDiscovered;
  46. bluetooth.Adapter.ScanMode = Plugin.BLE.Abstractions.Contracts.ScanMode.LowLatency;
  47. bluetooth.Adapter.ScanTimeout = 5000;
  48. bluetooth.Adapter.ScanTimeoutElapsed += ScanFinished;
  49. Devices = new String[] { };
  50. BatteryLevels = new int[] { };
  51. DetectedBlueToothMACAddresses = new List<string>();
  52. KnownBlueToothMACAddresses = new String[] { };
  53. SavedBlueToothMACAddresses = new List<string>();
  54. }
  55. public async Task UnlockDigitalKey(String macaddress, Guid serviceid, Guid characteristicid, String key)
  56. {
  57. if (!_disabled)
  58. throw new Exception("BT Scanning must be disabled!");
  59. _devicemap.TryGetValue(macaddress, out IDevice device);
  60. if (device == null)
  61. throw new Exception("Device not Found!");
  62. try
  63. {
  64. await bluetooth.Adapter.ConnectToDeviceAsync(device);
  65. if (!bluetooth.Adapter.ConnectedDevices.Contains(device))
  66. throw new Exception("Cannot Connect to Device!");
  67. var service = await device.GetServiceAsync(serviceid);
  68. if (service == null)
  69. throw new Exception("Service Not Found!");
  70. var characteristic = await service.GetCharacteristicAsync(characteristicid);
  71. if (characteristic == null)
  72. throw new Exception("Characteristic Not Found!");
  73. var write = await characteristic.WriteAsync(Encoding.ASCII.GetBytes(key.ToUpper()));
  74. await bluetooth.Adapter.DisconnectDeviceAsync(device);
  75. }
  76. catch
  77. {
  78. if (bluetooth.Adapter.ConnectedDevices.Contains(device))
  79. await bluetooth.Adapter.DisconnectDeviceAsync(device);
  80. throw;
  81. }
  82. }
  83. public bool IsScanning { get; private set; }
  84. private async Task<bool> UnlockDevice(IDevice idevice, String key)
  85. {
  86. bool result = false;
  87. //Console.WriteLine(String.Format("** Found Device: {0} {1}", idevice.Name, idevice.Rssi));
  88. if (idevice.Rssi < -65)
  89. {
  90. //Console.WriteLine(String.Format("** Device RSSI is too low: {0}", idevice.Rssi));
  91. return false;
  92. }
  93. try
  94. {
  95. await bluetooth.Adapter.ConnectToDeviceAsync(idevice);
  96. IService service = await idevice.GetServiceAsync(Guid.Parse("3317F54C-1C7E-EBE7-026E-3C819FD35476"));
  97. if (service != null)
  98. {
  99. //Console.WriteLine("** Found Service 3317F54C-1C7E-EBE7-026E-3C819FD35476");
  100. ICharacteristic chr = await service.GetCharacteristicAsync(Guid.Parse("20852B39-4455-EE15-089B-D1629FE76927"));
  101. if (chr != null)
  102. {
  103. //Console.WriteLine("** Found Characteristic 20852B39-4455-EE15-089B-D1629FE76927");
  104. //var data = await chr.ReadAsync();
  105. //Console.WriteLine("- Found Data: " + String.Join("-", data.Select(x => String.Format("{0:X2}", x))));
  106. var newdata = Encoding.ASCII.GetBytes(key);
  107. bool bWrite = await chr.WriteAsync(newdata) == 0;
  108. if (bWrite)
  109. {
  110. //Console.WriteLine("** Wrote Data " + String.Join("-", newdata.Select(x => String.Format("{0:X2}", x))));
  111. //var confdata = await chr.ReadAsync();
  112. //Console.WriteLine("- Read Data: " + String.Join("-", confdata.Select(x => String.Format("{0:X2}", x))));
  113. result = true;
  114. }
  115. }
  116. }
  117. await bluetooth.Adapter.DisconnectDeviceAsync(idevice);
  118. }
  119. catch (Exception err)
  120. {
  121. // ... could not connect to device
  122. }
  123. return result;
  124. }
  125. private async void Adapter_DeviceDiscovered(object sender, Plugin.BLE.Abstractions.EventArgs.DeviceEventArgs e)
  126. {
  127. try
  128. {
  129. await Task.Run(() =>
  130. {
  131. if (string.IsNullOrWhiteSpace(e.Device.NativeDevice.ToString()))
  132. return;
  133. if (_devicemap.ContainsKey(e.Device.NativeDevice.ToString()))
  134. _devicemap[e.Device.NativeDevice.ToString()] = e.Device;
  135. else
  136. return;
  137. if (KnownBlueToothMACAddresses?.Any() == false)
  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. DetectedBlueToothMACAddresses.Clear();
  203. SavedBlueToothMACAddresses.Clear();
  204. if (!bluetooth.IsAvailable)
  205. {
  206. ScanFinished(this, new EventArgs());
  207. IsScanning = false;
  208. }
  209. else
  210. {
  211. IsScanning = true;
  212. bluetooth.Adapter.StartScanningForDevicesAsync().ConfigureAwait(true);
  213. }
  214. }
  215. catch (Exception e)
  216. { }
  217. }
  218. private void StopScanning()
  219. {
  220. bluetooth.Adapter.StopScanningForDevicesAsync().ConfigureAwait(true);
  221. IsScanning = false;
  222. }
  223. private void ScanFinished(object sender, EventArgs e)
  224. {
  225. try
  226. {
  227. _keys = null;
  228. TimeStamp = DateTime.Now;
  229. //List<String> devices = new List<String>();
  230. //List<int> levels = new List<int>();
  231. //foreach (var key in DiscoveredDevices.Keys)
  232. //{
  233. // devices.Add(key);
  234. // levels.Add(DiscoveredDevices[key]);
  235. //}
  236. Devices = SavedBlueToothMACAddresses.ToArray();
  237. //BatteryLevels = levels.ToArray();
  238. OnScanFinished?.Invoke(this);
  239. IsScanning = false;
  240. }
  241. catch
  242. { }
  243. }
  244. }
  245. }