using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Plugin.BLE; using Plugin.BLE.Abstractions.Contracts; namespace InABox.Mobile { public class Bluetooth { public delegate void BluetoothEvent(Bluetooth sender); public event BluetoothEvent OnScanFinished; public TimeSpan ScanDelay { get; set; } public String[] Devices { get; private set; } public int[] BatteryLevels { get; private set; } public DateTime TimeStamp { get; private set; } public string[] KnownBlueToothMACAddresses { get; set; } public List DetectedBlueToothMACAddresses { get; set; } public List SavedBlueToothMACAddresses { get; set; } private Dictionary _devicemap = new Dictionary(); IBluetoothLE bluetooth = null; private bool bScanning = false; private Dictionary DiscoveredDevices = new Dictionary(); private Dictionary _keys = null; private bool _disabled = false; public bool Disabled { get { return _disabled; } set { if (IsScanning) StopScanning(); _disabled = true; } } ////List devices = new List(); //List bluetoothdevices = new List(); public Bluetooth() : base() { TimeStamp = DateTime.MinValue; ScanDelay = new TimeSpan(0, 6, 0); //ScanDelay = new TimeSpan(0, 0, 0); bluetooth = CrossBluetoothLE.Current; bluetooth.Adapter.DeviceDiscovered += Adapter_DeviceDiscovered; bluetooth.Adapter.ScanMode = Plugin.BLE.Abstractions.Contracts.ScanMode.LowLatency; bluetooth.Adapter.ScanTimeout = 5000; bluetooth.Adapter.ScanTimeoutElapsed += ScanFinished; Devices = new String[] { }; BatteryLevels = new int[] { }; DetectedBlueToothMACAddresses = new List(); KnownBlueToothMACAddresses = new String[] { }; SavedBlueToothMACAddresses = new List(); } public async Task UnlockDigitalKey(String macaddress, Guid serviceid, Guid characteristicid, String key) { if (!_disabled) throw new Exception("BT Scanning must be disabled!"); _devicemap.TryGetValue(macaddress, out IDevice device); if (device == null) throw new Exception("Device not Found!"); try { await bluetooth.Adapter.ConnectToDeviceAsync(device); if (!bluetooth.Adapter.ConnectedDevices.Contains(device)) throw new Exception("Cannot Connect to Device!"); var service = await device.GetServiceAsync(serviceid); if (service == null) throw new Exception("Service Not Found!"); var characteristic = await service.GetCharacteristicAsync(characteristicid); if (characteristic == null) throw new Exception("Characteristic Not Found!"); var write = await characteristic.WriteAsync(Encoding.ASCII.GetBytes(key.ToUpper())); await bluetooth.Adapter.DisconnectDeviceAsync(device); } catch { if (bluetooth.Adapter.ConnectedDevices.Contains(device)) await bluetooth.Adapter.DisconnectDeviceAsync(device); throw; } } public bool IsScanning { get; private set; } private async Task UnlockDevice(IDevice idevice, String key) { bool result = false; //Console.WriteLine(String.Format("** Found Device: {0} {1}", idevice.Name, idevice.Rssi)); if (idevice.Rssi < -65) { //Console.WriteLine(String.Format("** Device RSSI is too low: {0}", idevice.Rssi)); return false; } try { await bluetooth.Adapter.ConnectToDeviceAsync(idevice); IService service = await idevice.GetServiceAsync(Guid.Parse("3317F54C-1C7E-EBE7-026E-3C819FD35476")); if (service != null) { //Console.WriteLine("** Found Service 3317F54C-1C7E-EBE7-026E-3C819FD35476"); ICharacteristic chr = await service.GetCharacteristicAsync(Guid.Parse("20852B39-4455-EE15-089B-D1629FE76927")); if (chr != null) { //Console.WriteLine("** Found Characteristic 20852B39-4455-EE15-089B-D1629FE76927"); //var data = await chr.ReadAsync(); //Console.WriteLine("- Found Data: " + String.Join("-", data.Select(x => String.Format("{0:X2}", x)))); var newdata = Encoding.ASCII.GetBytes(key); bool bWrite = await chr.WriteAsync(newdata); if (bWrite) { //Console.WriteLine("** Wrote Data " + String.Join("-", newdata.Select(x => String.Format("{0:X2}", x)))); //var confdata = await chr.ReadAsync(); //Console.WriteLine("- Read Data: " + String.Join("-", confdata.Select(x => String.Format("{0:X2}", x)))); result = true; } } } await bluetooth.Adapter.DisconnectDeviceAsync(idevice); } catch (Exception err) { // ... could not connect to device } return result; } private async void Adapter_DeviceDiscovered(object sender, Plugin.BLE.Abstractions.EventArgs.DeviceEventArgs e) { try { await Task.Run(() => { if (string.IsNullOrWhiteSpace(e.Device.NativeDevice.ToString())) return; if (_devicemap.ContainsKey(e.Device.NativeDevice.ToString())) _devicemap[e.Device.NativeDevice.ToString()] = e.Device; else return; if (KnownBlueToothMACAddresses?.Any() == false) return; string deviceID = e.Device.NativeDevice.ToString(); if (KnownBlueToothMACAddresses.Contains(deviceID)) { if (!DetectedBlueToothMACAddresses.Contains(deviceID)) { DetectedBlueToothMACAddresses.Add(deviceID); } if (!SavedBlueToothMACAddresses.Contains(deviceID)) { SavedBlueToothMACAddresses.Add(deviceID); } } }); } catch { } #region OLD //if (_keys != null) //{ // String address = e.Device.NativeDevice?.ToString(); // if (_keys.ContainsKey(address)) // { // //bool result = await UnlockDevice(e.Device, _keys[address]); // //if (result) // //{ // // await bluetooth.Adapter.StopScanningForDevicesAsync(); // // IsScanning = false; // //} // } //} //var record = e.Device.AdvertisementRecords.FirstOrDefault(X => X.Type == Plugin.BLE.Abstractions.AdvertisementRecordType.ServiceData); //if (record != null) //{ // byte[] id = record.Data.TakeLast(record.Data.Length == 14 ? 6 : 4).ToArray(); // String sid = ""; // foreach (byte bs in id) // sid = sid + Convert.ToChar(bs); // DiscoveredDevices[sid] = record.Data.Length >= 7 ? (int)record.Data[6] : -1; //} #endregion } public bool RecentlyScanned { get { return (DateTime.Now.Subtract(TimeStamp).Ticks < ScanDelay.Ticks); } } public void ScanForDevices(Dictionary keys = null) { if (_disabled) return; try { if (bluetooth.Adapter.IsScanning) { if (keys != null) { StopScanning(); } else return; } DetectedBlueToothMACAddresses.Clear(); SavedBlueToothMACAddresses.Clear(); if (!bluetooth.IsAvailable) { ScanFinished(this, new EventArgs()); IsScanning = false; } else { IsScanning = true; bluetooth.Adapter.StartScanningForDevicesAsync().ConfigureAwait(true); } } catch (Exception e) { } } private void StopScanning() { bluetooth.Adapter.StopScanningForDevicesAsync().ConfigureAwait(true); IsScanning = false; } private void ScanFinished(object sender, EventArgs e) { try { _keys = null; TimeStamp = DateTime.Now; //List devices = new List(); //List levels = new List(); //foreach (var key in DiscoveredDevices.Keys) //{ // devices.Add(key); // levels.Add(DiscoveredDevices[key]); //} Devices = SavedBlueToothMACAddresses.ToArray(); //BatteryLevels = levels.ToArray(); OnScanFinished?.Invoke(this); IsScanning = false; } catch { } } } }