123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- 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<string> DetectedBlueToothMACAddresses { get; set; }
- public List<string> SavedBlueToothMACAddresses { get; set; }
- private Dictionary<String, IDevice> _devicemap = new Dictionary<string, IDevice>();
- IBluetoothLE bluetooth = null;
- private bool bScanning = false;
- private Dictionary<String, int> DiscoveredDevices = new Dictionary<string, int>();
- private Dictionary<String, String> _keys = null;
- private bool _disabled = false;
- public bool Disabled
- {
- get { return _disabled; }
- set
- {
- if (IsScanning)
- StopScanning();
- _disabled = true;
- }
- }
- ////List<IDevice> devices = new List<IDevice>();
- //List<GPSTrackerLocation> bluetoothdevices = new List<GPSTrackerLocation>();
- 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<string>();
- KnownBlueToothMACAddresses = new String[] { };
- SavedBlueToothMACAddresses = new List<string>();
- }
- 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<bool> 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<String, String> 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<String> devices = new List<String>();
- //List<int> levels = new List<int>();
- //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
- { }
- }
- }
- }
|