private bool UpdateConnectionIntervalNative(ConnectionInterval interval)
        {
            if (_gatt == null || _gattCallback == null)
            {
                Trace.Message("You can't update a connection interval for disconnected devices. Device is {0}", State);
                return(false);
            }

            if (Build.VERSION.SdkInt < BuildVersionCodes.Lollipop)
            {
                Trace.Message($"Update connection interval paramter in this Android API level");
                return(false);
            }

            try
            {
                // map to android gattConnectionPriorities
                // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#CONNECTION_PRIORITY_BALANCED
                return(_gatt.RequestConnectionPriority((GattConnectionPriority)(int)interval));
            }
            catch (Exception ex)
            {
                throw new Exception($"Update Connection Interval fails with error. {ex.Message}");
            }
        }
        private async Task <bool> UpdateRssiNativeAsync()
        {
            if (_gatt == null || _gattCallback == null)
            {
                Trace.Message("You can't read the RSSI value for disconnected devices except on discovery on Android. Device is {0}", State);
                return(false);
            }

            return(await TaskBuilder.FromEvent <bool, EventHandler <RssiReadCallbackEventArgs>, EventHandler>(
                       execute : () => _gatt.ReadRemoteRssi(),
                       getCompleteHandler : (complete, reject) => ((sender, args) =>
            {
                if (args.Error == null)
                {
                    Trace.Message("Read RSSI for {0} {1}: {2}", Id, Name, args.Rssi);
                    Rssi = args.Rssi;
                    complete(true);
                }
                else
                {
                    Trace.Message($"Failed to read RSSI for device {Id}-{Name}. {args.Error.Message}");
                    complete(false);
                }
            }),
                       subscribeComplete : handler => _gattCallback.RemoteRssiRead += handler,
                       unsubscribeComplete : handler => _gattCallback.RemoteRssiRead -= handler,
                       getRejectHandler : reject => ((sender, args) =>
            {
                reject(new Exception($"Device {Name} disconnected while updating rssi."));
            }),
                       subscribeReject : handler => _gattCallback.ConnectionInterrupted += handler,
                       unsubscribeReject : handler => _gattCallback.ConnectionInterrupted -= handler));
        }
示例#3
0
        private void StartScanningOld(Guid[] serviceUuids)
        {
            var hasFilter = serviceUuids?.Any() ?? false;

            UUID[] uuids = null;
            if (hasFilter)
            {
                uuids = serviceUuids.Select(u => UUID.FromString(u.ToString())).ToArray();
            }
            Trace.Message("Adapter < 21: Starting a scan for devices.");
#pragma warning disable 618
            _bluetoothAdapter.StartLeScan(uuids, _api18ScanCallback);
#pragma warning restore 618
        }
示例#4
0
        public IReadOnlyList <Device> GetSystemConnectedOrPairedDevices(Guid[] services = null)
        {
            if (services != null)
            {
                Trace.Message("Caution: GetSystemConnectedDevices does not take into account the 'services' parameter on Android.");
            }

            //add dualMode type too as they are BLE too ;)
            var connectedDevices = _bluetoothManager.GetConnectedDevices(ProfileType.Gatt).Where(d => d.Type == BluetoothDeviceType.Le || d.Type == BluetoothDeviceType.Dual);

            var bondedDevices = _bluetoothAdapter.BondedDevices.Where(d => d.Type == BluetoothDeviceType.Le || d.Type == BluetoothDeviceType.Dual);

            return(connectedDevices.Union(bondedDevices, new DeviceComparer()).Select(d => new Device(this, d, null, 0)).Cast <Device>().ToList());
        }
示例#5
0
        protected void StopScanNative()
        {
            if (Build.VERSION.SdkInt < BuildVersionCodes.Lollipop)
            {
                Trace.Message("Adapter < 21: Stopping the scan for devices.");
#pragma warning disable 618
                _bluetoothAdapter.StopLeScan(_api18ScanCallback);
#pragma warning restore 618
            }
            else
            {
                Trace.Message("Adapter >= 21: Stopping the scan for devices.");
                _bluetoothAdapter.BluetoothLeScanner?.StopScan(_api21ScanCallback);
            }
        }
        /// <summary>
        /// This method is only called by a user triggered disconnect.
        /// A user will first trigger _gatt.disconnect -> which in turn will trigger _gatt.Close() via the gattCallback
        /// </summary>
        internal void Disconnect()
        {
            if (_gatt != null)
            {
                IsOperationRequested = true;

                ClearServices();

                _gatt.Disconnect();
            }
            else
            {
                Trace.Message("[Warning]: Can't disconnect {0}. Gatt is null.", Name);
            }
        }
示例#7
0
        private void StartScanningNew(Guid[] serviceUuids)
        {
            var hasFilter = serviceUuids?.Any() ?? false;
            List <ScanFilter> scanFilters = null;

            if (hasFilter)
            {
                scanFilters = new List <ScanFilter>();
                foreach (var serviceUuid in serviceUuids)
                {
                    var sfb = new ScanFilter.Builder();
                    sfb.SetServiceUuid(ParcelUuid.FromString(serviceUuid.ToString()));
                    scanFilters.Add(sfb.Build());
                }
            }

            var ssb = new ScanSettings.Builder();

            ssb.SetScanMode(ScanMode.ToNative());
            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {
                // enable Bluetooth 5 Advertisement Extensions on Android 8.0 and above
                ssb.SetLegacy(false);
            }
            //ssb.SetCallbackType(ScanCallbackType.AllMatches);

            if (_bluetoothAdapter.BluetoothLeScanner != null)
            {
                Trace.Message($"Adapter >=21: Starting a scan for devices. ScanMode: {ScanMode}");
                if (hasFilter)
                {
                    Trace.Message($"ScanFilters: {string.Join(", ", serviceUuids)}");
                }
                _bluetoothAdapter.BluetoothLeScanner.StartScan(scanFilters, ssb.Build(), _api21ScanCallback);
            }
            else
            {
                Trace.Message("Adapter >= 21: Scan failed. Bluetooth is probably off");
            }
        }
        private async Task <int> RequestMtuNativeAsync(int requestValue)
        {
            if (_gatt == null || _gattCallback == null)
            {
                Trace.Message("You can't request a MTU for disconnected devices. Device is {0}", State);
                return(-1);
            }

            if (Build.VERSION.SdkInt < BuildVersionCodes.Lollipop)
            {
                Trace.Message($"Request MTU not supported in this Android API level");
                return(-1);
            }

            return(await TaskBuilder.FromEvent <int, EventHandler <MtuRequestCallbackEventArgs>, EventHandler>(
                       execute : () => { _gatt.RequestMtu(requestValue); },
                       getCompleteHandler : (complete, reject) => ((sender, args) =>
            {
                if (args.Error != null)
                {
                    Trace.Message($"Failed to request MTU ({requestValue}) for device {Id}-{Name}. {args.Error.Message}");
                    reject(new Exception($"Request MTU error: {args.Error.Message}"));
                }
                else
                {
                    complete(args.Mtu);
                }
            }),
                       subscribeComplete : handler => _gattCallback.MtuRequested += handler,
                       unsubscribeComplete : handler => _gattCallback.MtuRequested -= handler,
                       getRejectHandler : reject => ((sender, args) =>
            {
                reject(new Exception($"Device {Name} disconnected while requesting MTU."));
            }),
                       subscribeReject : handler => _gattCallback.ConnectionInterrupted += handler,
                       unsubscribeReject : handler => _gattCallback.ConnectionInterrupted -= handler
                       ));
        }
示例#9
0
 public override void OnScanFailed(ScanFailure errorCode)
 {
     Trace.Message("Adapter: Scan failed with code {0}", errorCode);
     base.OnScanFailed(errorCode);
 }
示例#10
0
            public void OnLeScan(BluetoothDevice bleDevice, int rssi, byte[] scanRecord)
            {
                Trace.Message("Adapter.LeScanCallback: " + bleDevice.Name);

                _adapter.HandleDiscoveredDevice(new Device(_adapter, bleDevice, null, rssi, scanRecord));
            }
        private static List <AdvertisementRecord> ParseScanRecord(byte[] scanRecord)
        {
            var records = new List <AdvertisementRecord>();

            if (scanRecord == null)
            {
                return(records);
            }

            int index = 0;

            while (index < scanRecord.Length)
            {
                byte length = scanRecord[index++];
                //Done once we run out of records
                // 1 byte for type and length-1 bytes for data
                if (length == 0)
                {
                    break;
                }

                int type = scanRecord[index];
                //Done if our record isn't a valid type
                if (type == 0)
                {
                    break;
                }

                if (!Enum.IsDefined(typeof(AdvertisementRecordType), type))
                {
                    Trace.Message("Advertisment record type not defined: {0}", type);
                    break;
                }

                //data length is length -1 because type takes the first byte
                byte[] data = new byte[length - 1];
                Array.Copy(scanRecord, index + 1, data, 0, length - 1);

                // don't forget that data is little endian so reverse
                // Supplement to Bluetooth Core Specification 1
                // NOTE: all relevant devices are already little endian, so this is not necessary for any type except UUIDs
                //var record = new AdvertisementRecord((AdvertisementRecordType)type, data.Reverse().ToArray());

                switch ((AdvertisementRecordType)type)
                {
                case AdvertisementRecordType.ServiceDataUuid32Bit:
                case AdvertisementRecordType.SsUuids128Bit:
                case AdvertisementRecordType.SsUuids16Bit:
                case AdvertisementRecordType.SsUuids32Bit:
                case AdvertisementRecordType.UuidCom32Bit:
                case AdvertisementRecordType.UuidsComplete128Bit:
                case AdvertisementRecordType.UuidsComplete16Bit:
                case AdvertisementRecordType.UuidsIncomple16Bit:
                case AdvertisementRecordType.UuidsIncomplete128Bit:
                    Array.Reverse(data);
                    break;
                }
                var record = new AdvertisementRecord((AdvertisementRecordType)type, data);

                Trace.Message(record.ToString());

                records.Add(record);

                //Advance
                index += length;
            }

            return(records);
        }