| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 | using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;using Plugin.BLE;using Plugin.BLE.Abstractions;using Plugin.BLE.Abstractions.Contracts;using Xamarin.Forms;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 List<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 List<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.Count == 0)                        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;                }                SavedBlueToothMACAddresses.Clear();                if (!bluetooth.IsAvailable)                {                    ScanFinished(this, new EventArgs());                    IsScanning = false;                }                else                {                    IsScanning = true;                    bluetooth.Adapter.StartScanningForDevicesAsync();                }            }            catch (Exception e)            { }        }        private void StopScanning()        {            bluetooth.Adapter.StopScanningForDevicesAsync().ConfigureAwait(false);            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            { }        }    }}
 |