Bluetooth.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  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. if (_devicemap.ContainsKey(e.Device.NativeDevice.ToString()))
  137. _devicemap[e.Device.NativeDevice.ToString()] = e.Device;
  138. else
  139. return;
  140. if (KnownBlueToothMACAddresses.Count == 0)
  141. return;
  142. string deviceID = e.Device.NativeDevice.ToString();
  143. if (KnownBlueToothMACAddresses.Contains(deviceID))
  144. {
  145. if (!DetectedBlueToothMACAddresses.Contains(deviceID))
  146. {
  147. DetectedBlueToothMACAddresses.Add(deviceID);
  148. }
  149. if (!SavedBlueToothMACAddresses.Contains(deviceID))
  150. {
  151. SavedBlueToothMACAddresses.Add(deviceID);
  152. }
  153. }
  154. });
  155. }
  156. catch
  157. { }
  158. #region OLD
  159. //if (_keys != null)
  160. //{
  161. // String address = e.Device.NativeDevice?.ToString();
  162. // if (_keys.ContainsKey(address))
  163. // {
  164. // //bool result = await UnlockDevice(e.Device, _keys[address]);
  165. // //if (result)
  166. // //{
  167. // // await bluetooth.Adapter.StopScanningForDevicesAsync();
  168. // // IsScanning = false;
  169. // //}
  170. // }
  171. //}
  172. //var record = e.Device.AdvertisementRecords.FirstOrDefault(X => X.Type == Plugin.BLE.Abstractions.AdvertisementRecordType.ServiceData);
  173. //if (record != null)
  174. //{
  175. // byte[] id = record.Data.TakeLast(record.Data.Length == 14 ? 6 : 4).ToArray();
  176. // String sid = "";
  177. // foreach (byte bs in id)
  178. // sid = sid + Convert.ToChar(bs);
  179. // DiscoveredDevices[sid] = record.Data.Length >= 7 ? (int)record.Data[6] : -1;
  180. //}
  181. #endregion
  182. }
  183. public bool RecentlyScanned
  184. {
  185. get
  186. {
  187. return (DateTime.Now.Subtract(TimeStamp).Ticks < ScanDelay.Ticks);
  188. }
  189. }
  190. public void ScanForDevices(Dictionary<String, String> keys = null)
  191. {
  192. if (_disabled)
  193. return;
  194. try
  195. {
  196. if (bluetooth.Adapter.IsScanning)
  197. {
  198. if (keys != null)
  199. {
  200. StopScanning();
  201. }
  202. else
  203. return;
  204. }
  205. SavedBlueToothMACAddresses.Clear();
  206. if (!bluetooth.IsAvailable)
  207. {
  208. ScanFinished(this, new EventArgs());
  209. IsScanning = false;
  210. }
  211. else
  212. {
  213. IsScanning = true;
  214. bluetooth.Adapter.StartScanningForDevicesAsync();
  215. }
  216. }
  217. catch (Exception e)
  218. { }
  219. }
  220. private void StopScanning()
  221. {
  222. bluetooth.Adapter.StopScanningForDevicesAsync().ConfigureAwait(false);
  223. IsScanning = false;
  224. }
  225. private void ScanFinished(object sender, EventArgs e)
  226. {
  227. try
  228. {
  229. _keys = null;
  230. TimeStamp = DateTime.Now;
  231. //List<String> devices = new List<String>();
  232. //List<int> levels = new List<int>();
  233. //foreach (var key in DiscoveredDevices.Keys)
  234. //{
  235. // devices.Add(key);
  236. // levels.Add(DiscoveredDevices[key]);
  237. //}
  238. Devices = SavedBlueToothMACAddresses.ToArray();
  239. //BatteryLevels = levels.ToArray();
  240. OnScanFinished?.Invoke(this);
  241. IsScanning = false;
  242. }
  243. catch
  244. { }
  245. }
  246. }
  247. }