示例#1
0
        protected override Task WriteNativeAsync(Byte[] data)
        {
            return(TaskBuilder.FromEvent <Boolean, EventHandler <DescriptorCallbackEventArgs>, EventHandler>(
                       () => this.InternalWrite(data),
                       (complete, reject) => (sender, args) =>
            {
                if (args.Descriptor.Uuid != this._nativeDescriptor.Uuid)
                {
                    return;
                }

                if (args.Exception != null)
                {
                    reject(args.Exception);
                }
                else
                {
                    complete(true);
                }
            },
                       handler => this._gattCallback.DescriptorValueWritten += handler,
                       handler => this._gattCallback.DescriptorValueWritten -= handler,
                       reject => (sender, args) =>
            {
                reject(new Exception(
                           $"Device '{this.Characteristic.Service.Device.Id}' disconnected while writing descriptor with {this.Id}."));
            },
                       handler => this._gattCallback.ConnectionInterrupted += handler,
                       handler => this._gattCallback.ConnectionInterrupted -= handler));
        }
        public static async Task <IDevice> DiscoverDeviceAsync(this IAdapter adapter, Func <IDevice, bool> deviceFilter, CancellationToken cancellationToken = default)
        {
            var device = adapter.DiscoveredDevices.FirstOrDefault(deviceFilter);

            if (device != null)
            {
                return(device);
            }

            if (adapter.IsScanning)
            {
                await adapter.StopScanningForDevicesAsync();
            }

            return(await TaskBuilder.FromEvent <IDevice, EventHandler <DeviceEventArgs>, EventHandler>(
                       execute : () => adapter.StartScanningForDevicesAsync(deviceFilter, cancellationToken),

                       getCompleteHandler : (complete, reject) => ((sender, args) =>
            {
                complete(args.Device);
                adapter.StopScanningForDevicesAsync();
            }),
                       subscribeComplete : handler => adapter.DeviceDiscovered += handler,
                       unsubscribeComplete : handler => adapter.DeviceDiscovered -= handler,

                       getRejectHandler : reject => ((sender, args) => { reject(new DeviceDiscoverException()); }),
                       subscribeReject : handler => adapter.ScanTimeoutElapsed += handler,
                       unsubscribeReject : handler => adapter.ScanTimeoutElapsed -= handler,

                       token : cancellationToken));
        }
示例#3
0
 protected override Task <IEnumerable <IService> > GetServicesNativeAsync()
 {
     return(TaskBuilder.FromEvent <IEnumerable <IService>, EventHandler <NSErrorEventArgs> >(
                execute: () => _nativeDevice.DiscoverServices(),
                getCompleteHandler: (complete, reject) => (sender, args) =>
     {
         // If args.Error was not null then the Service might be null
         if (args.Error != null)
         {
             reject(new Exception($"Error while discovering services {args.Error.LocalizedDescription}"));
         }
         else if (_nativeDevice.Services == null)
         {
             // No service discovered.
             reject(new Exception($"Error while discovering services: returned list is null"));
         }
         else
         {
             var services = _nativeDevice.Services
                            .Select(nativeService => new Service(nativeService, this))
                            .Cast <IService>().ToList();
             complete(services);
         }
     },
                subscribeComplete: handler => _nativeDevice.DiscoveredService += handler,
                unsubscribeComplete: handler => _nativeDevice.DiscoveredService -= handler));
 }
 private Task <bool> UpdateRssiNativeAsync()
 {
     return(TaskBuilder.FromEvent <bool, EventHandler <CBRssiEventArgs>, EventHandler <CBPeripheralErrorEventArgs> >(
                execute: () => NativeDevice.ReadRSSI(),
                getCompleteHandler: (complete, reject) => (sender, args) =>
     {
         if (args.Error != null)
         {
             reject(new Exception($"Error while reading rssi services {args.Error.LocalizedDescription}"));
         }
         else
         {
             Rssi = args.Rssi?.Int32Value ?? 0;
             complete(true);
         }
     },
                subscribeComplete: handler => NativeDevice.RssiRead += handler,
                unsubscribeComplete: handler => NativeDevice.RssiRead -= handler,
                getRejectHandler: reject => ((sender, args) =>
     {
         if (args.Peripheral.Identifier == NativeDevice.Identifier)
         {
             reject(new Exception($"Device {Name} disconnected while reading RSSI."));
         }
     }),
                subscribeReject: handler => _bleCentralManagerDelegate.DisconnectedPeripheral += handler,
                unsubscribeReject: handler => _bleCentralManagerDelegate.DisconnectedPeripheral -= handler));
 }
示例#5
0
        public override async Task <Boolean> UpdateRssiAsync()
        {
            if (this._gatt == null || this._gattCallback == null)
            {
                Trace.Message(
                    "You can't read the RSSI value for disconnected devices except on discovery on Android. Device is {0}",
                    this.State);
                return(false);
            }

            return(await TaskBuilder.FromEvent <Boolean, EventHandler <RssiReadCallbackEventArgs>, EventHandler>(
                       () => this._gatt.ReadRemoteRssi(),
                       (complete, reject) => (sender, args) =>
            {
                if (args.Error == null)
                {
                    Trace.Message("Read RSSI for {0} {1}: {2}", this.Id, this.Name, args.Rssi);
                    this.Rssi = args.Rssi;
                    complete(true);
                }
                else
                {
                    Trace.Message($"Failed to read RSSI for device {this.Id}-{this.Name}. {args.Error.Message}");
                    complete(false);
                }
            },
                       handler => this._gattCallback.RemoteRssiRead += handler,
                       handler => this._gattCallback.RemoteRssiRead -= handler,
                       reject => (sender, args) =>
            {
                reject(new Exception($"Device {this.Name} disconnected while updating rssi."));
            },
                       handler => this._gattCallback.ConnectionInterrupted += handler,
                       handler => this._gattCallback.ConnectionInterrupted -= handler));
        }
        protected override Task <bool> WriteNativeAsync(byte[] data)
        {
            Task <bool> task;

            if (CharacteristicWriteType == CBCharacteristicWriteType.WithResponse)
            {
                task = TaskBuilder.FromEvent <bool, EventHandler <CBCharacteristicEventArgs> >(
                    execute: () => { },
                    getCompleteHandler: complete => (sender, args) =>
                {
                    if (args.Characteristic.UUID != _nativeCharacteristic.UUID)
                    {
                        return;
                    }

                    complete(args.Error == null);
                },
                    subscribeComplete: handler => _parentDevice.WroteCharacteristicValue   += handler,
                    unsubscribeComplete: handler => _parentDevice.WroteCharacteristicValue -= handler);
            }
            else
            {
                task = Task.FromResult(true);
            }

            var nsdata = NSData.FromArray(data);

            _parentDevice.WriteValue(nsdata, _nativeCharacteristic, CharacteristicWriteType);

            return(task);
        }
示例#7
0
        protected override Task WriteNativeAsync(byte[] data)
        {
            return(TaskBuilder.FromEvent <bool, EventHandler <DescriptorCallbackEventArgs>, EventHandler>(
                       execute: () => InternalWrite(data),
                       getCompleteHandler: (complete, reject) => ((sender, args) =>
            {
                if (args.Descriptor.Uuid != _nativeDescriptor.Uuid)
                {
                    return;
                }

                if (args.Exception != null)
                {
                    reject(args.Exception);
                }
                else
                {
                    complete(true);
                }
            }),
                       subscribeComplete: handler => _gattCallback.DescriptorValueWritten += handler,
                       unsubscribeComplete: handler => _gattCallback.DescriptorValueWritten -= handler,
                       getRejectHandler: reject => ((sender, args) =>
            {
                reject(new Exception($"Device '{Characteristic.Service.Device.Id}' disconnected while writing descriptor with {Id}."));
            }),
                       subscribeReject: handler => _gattCallback.ConnectionInterrupted += handler,
                       unsubscribeReject: handler => _gattCallback.ConnectionInterrupted -= handler));
        }
示例#8
0
        public Task DisconnectDeviceAsync(IDevice device)
        {
            if (!ConnectedDevices.Contains(device))
            {
                Trace.Message("Disconnect async: device {0} not in the list of connected devices.", device.Name);
                return(Task.FromResult(false));
            }

            return(TaskBuilder.FromEvent <bool, EventHandler <DeviceEventArgs>, EventHandler <DeviceErrorEventArgs> >(
                       execute: () => DisconnectDeviceNative(device),

                       getCompleteHandler: (complete, reject) => ((sender, args) =>
            {
                if (args.Device.Id == device.Id)
                {
                    Trace.Message("DisconnectAsync Disconnected: {0} {1}", args.Device.Id, args.Device.Name);
                    complete(true);
                }
            }),
                       subscribeComplete: handler => DeviceDisconnected += handler,
                       unsubscribeComplete: handler => DeviceDisconnected -= handler,

                       getRejectHandler: reject => ((sender, args) =>
            {
                if (args.Device.Id == device.Id)
                {
                    Trace.Message("DisconnectAsync", "Disconnect Error: {0} {1}", args.Device?.Id, args.Device?.Name);
                    reject(new Exception("Disconnect operation exception"));
                }
            }),
                       subscribeReject: handler => DeviceConnectionError += handler,
                       unsubscribeReject: handler => DeviceConnectionError -= handler));
        }
示例#9
0
        protected override Task StopUpdatesNativeAsync()
        {
            _parentDevice.UpdatedCharacterteristicValue -= UpdatedNotify;

            // JTS Added this if-statement. We found that on iOS, when you turn off Bluetooth during a connection it gets the characteristic into a stale state
            // and the IsNotifying property remains True. Then attempting to reset it does not trigger the callback thus resulting in a deadlock.
            if (_parentDevice.State == CBPeripheralState.Disconnected)
            {
                return(Task.FromResult(true));
            }

            return(TaskBuilder.FromEvent <bool, EventHandler <CBCharacteristicEventArgs> >(
                       execute: () => _parentDevice.SetNotifyValue(false, _nativeCharacteristic),
                       getCompleteHandler: (complete, reject) => (sender, args) =>
            {
                if (args.Characteristic.UUID != _nativeCharacteristic.UUID)
                {
                    return;
                }

                if (args.Error != null)
                {
                    reject(new Exception($"Stop Notifications: Error {args.Error.Description}"));
                }
                else
                {
                    Trace.Message($"StopUpdates IsNotifying: {args.Characteristic.IsNotifying}");
                    complete(args.Characteristic.IsNotifying);
                }
            },
                       subscribeComplete: handler => _parentDevice.UpdatedNotificationState += handler,
                       unsubscribeComplete: handler => _parentDevice.UpdatedNotificationState -= handler));
        }
示例#10
0
        public override async Task <bool> UpdateRssiAsync()
        {
            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));
        }
示例#11
0
 protected override Task <IList <ICharacteristic> > GetCharacteristicsNativeAsync()
 {
     return(TaskBuilder.FromEvent <IList <ICharacteristic>, EventHandler <CBServiceEventArgs> >(
                execute: () => _device.DiscoverCharacteristics(_service),
                getCompleteHandler: (complete, reject) => (sender, args) =>
     {
         if (args.Error != null)
         {
             reject(new Exception($"Discover characteristics error: {args.Error.Description}"));
         }
         else
         if (args.Service?.Characteristics == null)
         {
             reject(new Exception($"Discover characteristics error: returned list is null"));
         }
         else
         {
             var characteristics = args.Service.Characteristics
                                   .Select(characteristic => new Characteristic(characteristic, _device, this))
                                   .Cast <ICharacteristic>().ToList();
             complete(characteristics);
         }
     },
                subscribeComplete: handler => _device.DiscoveredCharacteristic += handler,
                unsubscribeComplete: handler => _device.DiscoveredCharacteristic -= handler));
 }
        protected override Task StopUpdatesNativeAsync()
        {
            _parentDevice.UpdatedCharacterteristicValue -= UpdatedNotify;
            return(TaskBuilder.FromEvent <bool, EventHandler <CBCharacteristicEventArgs> >(
                       execute: () => _parentDevice.SetNotifyValue(false, _nativeCharacteristic),
                       getCompleteHandler: (complete, reject) => (sender, args) =>
            {
                if (args.Characteristic.UUID != _nativeCharacteristic.UUID)
                {
                    return;
                }

                if (args.Error != null)
                {
                    reject(new Exception($"Stop Notifications: Error {args.Error.Description}"));
                }
                else
                {
                    Trace.Message($"StopUpdates IsNotifying: {args.Characteristic.IsNotifying}");
                    complete(args.Characteristic.IsNotifying);
                }
            },
                       subscribeComplete: handler => _parentDevice.UpdatedNotificationState += handler,
                       unsubscribeComplete: handler => _parentDevice.UpdatedNotificationState -= handler));
        }
        protected override Task StartUpdatesNativeAsync()
        {
            _parentDevice.UpdatedCharacterteristicValue -= UpdatedNotify;
            _parentDevice.UpdatedCharacterteristicValue += UpdatedNotify;

            //https://developer.apple.com/reference/corebluetooth/cbperipheral/1518949-setnotifyvalue
            return(TaskBuilder.FromEvent <bool, EventHandler <CBCharacteristicEventArgs> >(
                       execute: () => _parentDevice.SetNotifyValue(true, _nativeCharacteristic),
                       getCompleteHandler: (complete, reject) => (sender, args) =>
            {
                if (args.Characteristic.UUID != _nativeCharacteristic.UUID)
                {
                    return;
                }

                if (args.Error != null)
                {
                    reject(new Exception($"Start Notifications: Error {args.Error.Description}"));
                }
                else
                {
                    Trace.Message($"StartUpdates IsNotifying: {args.Characteristic.IsNotifying}");
                    complete(args.Characteristic.IsNotifying);
                }
            },
                       subscribeComplete: handler => _parentDevice.UpdatedNotificationState += handler,
                       unsubscribeComplete: handler => _parentDevice.UpdatedNotificationState -= handler));
        }
示例#14
0
        public static async Task <IDevice> DiscoverDeviceAsync(this IAdapter adapter,
                                                               Func <IDevice, Boolean> deviceFilter, CancellationToken cancellationToken = default(CancellationToken))
        {
            IDevice device = adapter.DiscoveredDevices.FirstOrDefault(deviceFilter);

            if (device != null)
            {
                return(device);
            }

            if (adapter.IsScanning)
            {
                await adapter.StopScanningForDevicesAsync();
            }

            return(await TaskBuilder.FromEvent <IDevice, EventHandler <DeviceEventArgs>, EventHandler>(
                       () => adapter.StartScanningForDevicesAsync(deviceFilter, cancellationToken),
                       (complete, reject) => (sender, args) =>
            {
                complete(args.Device);
                adapter.StopScanningForDevicesAsync();
            },
                       handler => adapter.DeviceDiscovered += handler,
                       handler => adapter.DeviceDiscovered -= handler,
                       reject => (sender, args) => { reject(new DeviceDiscoverException()); },
                       handler => adapter.ScanTimeoutElapsed += handler,
                       handler => adapter.ScanTimeoutElapsed -= handler,
                       cancellationToken));
        }
        protected override async Task <bool> WriteNativeAsync(byte[] data, CharacteristicWriteType writeType)
        {
            _nativeCharacteristic.WriteType = writeType.ToNative();

            if (writeType == CharacteristicWriteType.WithoutResponse)
            {
                return(InternalWrite(data));
            }

            return(await TaskBuilder.FromEvent <bool, EventHandler <CharacteristicWriteCallbackEventArgs>, EventHandler>(
                       execute : () => InternalWrite(data),
                       getCompleteHandler : (complete, reject) => ((sender, args) =>
            {
                if (args.Characteristic.Uuid == _nativeCharacteristic.Uuid)
                {
                    complete(args.Exception == null);
                }
            }),
                       subscribeComplete : handler => _gattCallback.CharacteristicValueWritten += handler,
                       unsubscribeComplete : handler => _gattCallback.CharacteristicValueWritten -= handler,
                       getRejectHandler : reject => ((sender, args) =>
            {
                reject(new Exception($"Device '{Service.Device.Id}' disconnected while writing characteristic with {Id}."));
            }),
                       subscribeReject : handler => _gattCallback.ConnectionInterrupted += handler,
                       unsubscribeReject : handler => _gattCallback.ConnectionInterrupted -= handler));
        }
        private Task <IReadOnlyList <Service> > GetServicesInternal(CBUUID id = null)
        {
            var exception = new Exception($"Device {Name} disconnected while fetching services.");

            return(TaskBuilder.FromEvent <IReadOnlyList <Service>, EventHandler <NSErrorEventArgs>, EventHandler <CBPeripheralErrorEventArgs> >(
                       execute: () =>
            {
                if (NativeDevice.State != CBPeripheralState.Connected)
                {
                    throw exception;
                }

                if (id != null)
                {
                    NativeDevice.DiscoverServices(new[] { id });
                }
                else
                {
                    NativeDevice.DiscoverServices();
                }
            },
                       getCompleteHandler: (complete, reject) => (sender, args) =>
            {
                // If args.Error was not null then the Service might be null
                if (args.Error != null)
                {
                    reject(new Exception($"Error while discovering services {args.Error.LocalizedDescription}"));
                }
                else if (NativeDevice.Services == null)
                {
                    // No service discovered.
                    reject(new Exception($"Error while discovering services: returned list is null"));
                }
                else
                {
                    var services = NativeDevice.Services
                                   .Select(nativeService => new Service(nativeService, this, _bleCentralManagerDelegate))
                                   .Cast <Service>().ToList();
                    complete(services);
                }
            },
                       subscribeComplete: handler => NativeDevice.DiscoveredService += handler,
                       unsubscribeComplete: handler => NativeDevice.DiscoveredService -= handler,
                       getRejectHandler: reject => ((sender, args) =>
            {
                if (args.Peripheral.Identifier == NativeDevice.Identifier)
                {
                    reject(exception);
                }
            }),
                       subscribeReject: handler => _bleCentralManagerDelegate.DisconnectedPeripheral += handler,
                       unsubscribeReject: handler => _bleCentralManagerDelegate.DisconnectedPeripheral -= handler));
        }
示例#17
0
        protected override Task <Boolean> WriteNativeAsync(Byte[] data, CharacteristicWriteType writeType)
        {
            Exception exception =
                new Exception(
                    $"Device {this.Service.Device.Id} disconnected while writing characteristic with {this.Id}.");

            Task <Boolean> task;

            if (writeType.ToNative() == CBCharacteristicWriteType.WithResponse)
            {
                task = TaskBuilder
                       .FromEvent <Boolean, EventHandler <CBCharacteristicEventArgs>,
                                   EventHandler <CBPeripheralErrorEventArgs> >(
                    () =>
                {
                    if (this._parentDevice.State != CBPeripheralState.Connected)
                    {
                        throw exception;
                    }
                },
                    (complete, reject) => (sender, args) =>
                {
                    if (args.Characteristic.UUID != this._nativeCharacteristic.UUID)
                    {
                        return;
                    }

                    complete(args.Error == null);
                },
                    handler => this._parentDevice.WroteCharacteristicValue += handler,
                    handler => this._parentDevice.WroteCharacteristicValue -= handler,
                    reject => (sender, args) =>
                {
                    if (args.Peripheral.Identifier == this._parentDevice.Identifier)
                    {
                        reject(exception);
                    }
                },
                    handler => this._centralManager.DisconnectedPeripheral += handler,
                    handler => this._centralManager.DisconnectedPeripheral -= handler);
            }
            else
            {
                task = Task.FromResult(true);
            }

            NSData nsdata = NSData.FromArray(data);

            this._parentDevice.WriteValue(nsdata, this._nativeCharacteristic, writeType.ToNative());

            return(task);
        }
示例#18
0
        protected override Task StartUpdatesNativeAsync()
        {
            Exception exception =
                new Exception(
                    $"Device {this.Service.Device.Id} disconnected while starting updates for characteristic with {this.Id}.");

            this._parentDevice.UpdatedCharacterteristicValue -= this.UpdatedNotify;
            this._parentDevice.UpdatedCharacterteristicValue += this.UpdatedNotify;

            //https://developer.apple.com/reference/corebluetooth/cbperipheral/1518949-setnotifyvalue
            return(TaskBuilder
                   .FromEvent <Boolean, EventHandler <CBCharacteristicEventArgs>, EventHandler <CBPeripheralErrorEventArgs> >(
                       () =>
            {
                if (this._parentDevice.State != CBPeripheralState.Connected)
                {
                    throw exception;
                }

                this._parentDevice.SetNotifyValue(true, this._nativeCharacteristic);
            },
                       (complete, reject) => (sender, args) =>
            {
                if (args.Characteristic.UUID != this._nativeCharacteristic.UUID)
                {
                    return;
                }

                if (args.Error != null)
                {
                    reject(new Exception($"Start Notifications: Error {args.Error.Description}"));
                }
                else
                {
                    Trace.Message($"StartUpdates IsNotifying: {args.Characteristic.IsNotifying}");
                    complete(args.Characteristic.IsNotifying);
                }
            },
                       handler => this._parentDevice.UpdatedNotificationState += handler,
                       handler => this._parentDevice.UpdatedNotificationState -= handler,
                       reject => (sender, args) =>
            {
                if (args.Peripheral.Identifier == this._parentDevice.Identifier)
                {
                    reject(new Exception(
                               $"Device {this.Service.Device.Id} disconnected while starting updates for characteristic with {this.Id}."));
                }
            },
                       handler => this._centralManager.DisconnectedPeripheral += handler,
                       handler => this._centralManager.DisconnectedPeripheral -= handler));
        }
示例#19
0
        protected override Task <IList <ICharacteristic> > GetCharacteristicsNativeAsync()
        {
            Exception exception =
                new Exception(
                    $"Device '{this.Device.Id}' disconnected while fetching characteristics for service with {this.Id}.");

            return(TaskBuilder
                   .FromEvent <IList <ICharacteristic>, EventHandler <CBServiceEventArgs>,
                               EventHandler <CBPeripheralErrorEventArgs> >(
                       () =>
            {
                if (this._device.State != CBPeripheralState.Connected)
                {
                    throw exception;
                }

                this._device.DiscoverCharacteristics(this._service);
            },
                       (complete, reject) => (sender, args) =>
            {
                if (args.Error != null)
                {
                    reject(new Exception($"Discover characteristics error: {args.Error.Description}"));
                }
                else if (args.Service?.Characteristics == null)
                {
                    reject(new Exception("Discover characteristics error: returned list is null"));
                }
                else
                {
                    List <ICharacteristic> characteristics = args.Service.Characteristics
                                                             .Select(characteristic =>
                                                                     new Characteristic(characteristic, this._device, this, this._centralManager))
                                                             .Cast <ICharacteristic>().ToList();
                    complete(characteristics);
                }
            },
                       handler => this._device.DiscoveredCharacteristic += handler,
                       handler => this._device.DiscoveredCharacteristic -= handler,
                       reject => (sender, args) =>
            {
                if (args.Peripheral.Identifier == this._device.Identifier)
                {
                    reject(exception);
                }
            },
                       handler => this._centralManager.DisconnectedPeripheral += handler,
                       handler => this._centralManager.DisconnectedPeripheral -= handler));
        }
示例#20
0
        protected override Task <IEnumerable <IService> > GetServicesNativeAsync()
        {
            Exception exception = new Exception($"Device {this.Name} disconnected while fetching services.");

            return(TaskBuilder
                   .FromEvent <IEnumerable <IService>, EventHandler <NSErrorEventArgs>,
                               EventHandler <CBPeripheralErrorEventArgs> >(
                       () =>
            {
                if (this._nativeDevice.State != CBPeripheralState.Connected)
                {
                    throw exception;
                }

                this._nativeDevice.DiscoverServices();
            },
                       (complete, reject) => (sender, args) =>
            {
                // If args.Error was not null then the Service might be null
                if (args.Error != null)
                {
                    reject(new Exception(
                               $"Error while discovering services {args.Error.LocalizedDescription}"));
                }
                else if (this._nativeDevice.Services == null)
                {
                    // No service discovered.
                    reject(new Exception("Error while discovering services: returned list is null"));
                }
                else
                {
                    List <IService> services = this._nativeDevice.Services
                                               .Select(nativeService => new Service(nativeService, this, this._centralManager))
                                               .Cast <IService>().ToList();
                    complete(services);
                }
            },
                       handler => this._nativeDevice.DiscoveredService += handler,
                       handler => this._nativeDevice.DiscoveredService -= handler,
                       reject => (sender, args) =>
            {
                if (args.Peripheral.Identifier == this._nativeDevice.Identifier)
                {
                    reject(exception);
                }
            },
                       handler => this._centralManager.DisconnectedPeripheral += handler,
                       handler => this._centralManager.DisconnectedPeripheral -= handler));
        }
示例#21
0
 protected override async Task <byte[]> ReadNativeAsync()
 {
     return(await TaskBuilder.FromEvent <byte[], EventHandler <DescriptorCallbackEventArgs> >(
                execute : ReadInternal,
                getCompleteHandler : (complete, reject) => ((sender, args) =>
     {
         if (args.Descriptor.Uuid == _nativeDescriptor.Uuid)
         {
             complete(args.Descriptor.GetValue());
         }
     }),
                subscribeComplete : handler => _gattCallback.DescriptorValueRead += handler,
                unsubscribeComplete : handler => _gattCallback.DescriptorValueRead -= handler
                ));
 }
        protected override Task StartUpdatesNativeAsync(CancellationToken cancellationToken = default)
        {
            var exception = new Exception($"Device {Service.Device.Id} disconnected while starting updates for characteristic with {Id}.");

            _parentDevice.UpdatedCharacterteristicValue -= UpdatedNotify;
            _parentDevice.UpdatedCharacterteristicValue += UpdatedNotify;

            //https://developer.apple.com/reference/corebluetooth/cbperipheral/1518949-setnotifyvalue
            return(TaskBuilder.FromEvent <bool, EventHandler <CBCharacteristicEventArgs>, EventHandler <CBPeripheralErrorEventArgs> >(
                       execute: () =>
            {
                if (_parentDevice.State != CBPeripheralState.Connected)
                {
                    throw exception;
                }

                _parentDevice.SetNotifyValue(true, _nativeCharacteristic);
            },
                       getCompleteHandler: (complete, reject) => (sender, args) =>
            {
                if (args.Characteristic.UUID != _nativeCharacteristic.UUID)
                {
                    return;
                }

                if (args.Error != null)
                {
                    reject(new Exception($"Start Notifications: Error {args.Error.Description}"));
                }
                else
                {
                    Trace.Message($"StartUpdates IsNotifying: {args.Characteristic.IsNotifying}");
                    complete(args.Characteristic.IsNotifying);
                }
            },
                       subscribeComplete: handler => _parentDevice.UpdatedNotificationState += handler,
                       unsubscribeComplete: handler => _parentDevice.UpdatedNotificationState -= handler,
                       getRejectHandler: reject => ((sender, args) =>
            {
                if (args.Peripheral.Identifier == _parentDevice.Identifier)
                {
                    reject(new Exception($"Device {Service.Device.Id} disconnected while starting updates for characteristic with {Id}."));
                }
            }),
                       subscribeReject: handler => _bleCentralManagerDelegate.DisconnectedPeripheral += handler,
                       unsubscribeReject: handler => _bleCentralManagerDelegate.DisconnectedPeripheral -= handler,
                       token: cancellationToken));
        }
示例#23
0
        protected override Task <bool> WriteNativeAsync(byte[] data, CharacteristicWriteType writeType)
        {
            var exception = new Exception($"Device {Service.Device.Id} disconnected while writing characteristic with {Id}.");

            Task <bool> task;

            if (writeType.ToNative() == CBCharacteristicWriteType.WithResponse)
            {
                task = TaskBuilder.FromEvent <bool, EventHandler <CBCharacteristicEventArgs>, EventHandler <CBPeripheralErrorEventArgs> >(
                    execute: () =>
                {
                    if (_parentDevice.State != CBPeripheralState.Connected)
                    {
                        throw exception;
                    }
                },
                    getCompleteHandler: (complete, reject) => (sender, args) =>
                {
                    if (args.Characteristic.UUID != _nativeCharacteristic.UUID)
                    {
                        return;
                    }

                    complete(args.Error == null);
                },
                    subscribeComplete: handler => _parentDevice.WroteCharacteristicValue   += handler,
                    unsubscribeComplete: handler => _parentDevice.WroteCharacteristicValue -= handler,
                    getRejectHandler: reject => ((sender, args) =>
                {
                    if (args.Peripheral.Identifier == _parentDevice.Identifier)
                    {
                        reject(exception);
                    }
                }),
                    subscribeReject: handler => _bleCentralManagerDelegate.DisconnectedPeripheral   += handler,
                    unsubscribeReject: handler => _bleCentralManagerDelegate.DisconnectedPeripheral -= handler);
            }
            else
            {
                task = Task.FromResult(true);
            }

            var nsdata = NSData.FromArray(data);

            _parentDevice.WriteValue(nsdata, _nativeCharacteristic, writeType.ToNative());

            return(task);
        }
示例#24
0
        protected override Task <IList <IDescriptor> > GetDescriptorsNativeAsync()
        {
            Exception exception =
                new Exception(
                    $"Device '{this.Service.Device.Id}' disconnected while fetching descriptors for characteristic with {this.Id}.");

            return(TaskBuilder
                   .FromEvent <IList <IDescriptor>, EventHandler <CBCharacteristicEventArgs>,
                               EventHandler <CBPeripheralErrorEventArgs> >(
                       () =>
            {
                if (this._parentDevice.State != CBPeripheralState.Connected)
                {
                    throw exception;
                }

                this._parentDevice.DiscoverDescriptors(this._nativeCharacteristic);
            },
                       (complete, reject) => (sender, args) =>
            {
                if (args.Characteristic.UUID != this._nativeCharacteristic.UUID)
                {
                    return;
                }

                if (args.Error != null)
                {
                    reject(new Exception($"Discover descriptors error: {args.Error.Description}"));
                }
                else
                {
                    complete(args.Characteristic.Descriptors.Select(descriptor =>
                                                                    new Descriptor(descriptor, this._parentDevice, this, this._centralManager))
                             .Cast <IDescriptor>().ToList());
                }
            },
                       handler => this._parentDevice.DiscoveredDescriptor += handler,
                       handler => this._parentDevice.DiscoveredDescriptor -= handler,
                       reject => (sender, args) =>
            {
                if (args.Peripheral.Identifier == this._parentDevice.Identifier)
                {
                    reject(exception);
                }
            },
                       handler => this._centralManager.DisconnectedPeripheral += handler,
                       handler => this._centralManager.DisconnectedPeripheral -= handler));
        }
示例#25
0
        protected override async Task <IEnumerable <IService> > GetServicesNativeAsync()
        {
            if (_gattCallback == null || _gatt == null)
            {
                return(Enumerable.Empty <IService>());
            }

            return(await TaskBuilder.FromEvent <IEnumerable <IService>, EventHandler <ServicesDiscoveredCallbackEventArgs> >(
                       execute : () => _gatt.DiscoverServices(),
                       getCompleteHandler : (complete, reject) => ((sender, args) =>
            {
                complete(_gatt.Services.Select(service => new Service(service, _gatt, _gattCallback, this)));
            }),
                       subscribeComplete : handler => _gattCallback.ServicesDiscovered += handler,
                       unsubscribeComplete : handler => _gattCallback.ServicesDiscovered -= handler));
        }
示例#26
0
        protected override async Task <bool> WriteNativeAsync(byte[] data, CharacteristicWriteType writeType)
        {
            _nativeCharacteristic.WriteType = writeType.ToNative();

            return(await TaskBuilder.FromEvent <bool, EventHandler <CharacteristicWriteCallbackEventArgs> >(
                       execute : () => InternalWrite(data),
                       getCompleteHandler : (complete, reject) => ((sender, args) =>
            {
                if (args.Characteristic.Uuid == _nativeCharacteristic.Uuid)
                {
                    complete(args.Exception == null);
                }
            }),
                       subscribeComplete : handler => _gattCallback.CharacteristicValueWritten += handler,
                       unsubscribeComplete : handler => _gattCallback.CharacteristicValueWritten -= handler
                       ));
        }
示例#27
0
        protected override Task <Byte[]> ReadNativeAsync()
        {
            Exception exception =
                new Exception(
                    $"Device '{this.Service.Device.Id}' disconnected while reading characteristic with {this.Id}.");

            return(TaskBuilder
                   .FromEvent <Byte[], EventHandler <CBCharacteristicEventArgs>, EventHandler <CBPeripheralErrorEventArgs> >(
                       () =>
            {
                if (this._parentDevice.State != CBPeripheralState.Connected)
                {
                    throw exception;
                }

                this._parentDevice.ReadValue(this._nativeCharacteristic);
            },
                       (complete, reject) => (sender, args) =>
            {
                if (args.Characteristic.UUID != this._nativeCharacteristic.UUID)
                {
                    return;
                }

                if (args.Error != null)
                {
                    reject(new CharacteristicReadException($"Read async error: {args.Error.Description}"));
                }
                else
                {
                    Trace.Message($"Read characterteristic value: {this.Value?.ToHexString()}");
                    complete(this.Value);
                }
            },
                       handler => this._parentDevice.UpdatedCharacterteristicValue += handler,
                       handler => this._parentDevice.UpdatedCharacterteristicValue -= handler,
                       reject => (sender, args) =>
            {
                if (args.Peripheral.Identifier == this._parentDevice.Identifier)
                {
                    reject(exception);
                }
            },
                       handler => this._centralManager.DisconnectedPeripheral += handler,
                       handler => this._centralManager.DisconnectedPeripheral -= handler));
        }
示例#28
0
        public async Task ConnectToDeviceAsync(IDevice device, bool autoconnect = false, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (device == null)
            {
                throw new ArgumentNullException(nameof(device));
            }

            if (device.State == DeviceState.Connected)
            {
                return;
            }

            using (var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
            {
                await TaskBuilder.FromEvent <bool, EventHandler <DeviceEventArgs>, EventHandler <DeviceErrorEventArgs> >(
                    execute : () =>
                {
                    ConnectToDeviceNativeAsync(device, autoconnect, cts.Token);
                },

                    getCompleteHandler : (complete, reject) => (sender, args) =>
                {
                    if (args.Device.Id == device.Id)
                    {
                        Trace.Message("ConnectToDeviceAsync Connected: {0} {1}", args.Device.Id, args.Device.Name);
                        complete(true);
                    }
                },
                    subscribeComplete : handler => DeviceConnected   += handler,
                    unsubscribeComplete : handler => DeviceConnected -= handler,

                    getRejectHandler : reject => (sender, args) =>
                {
                    if (args.Device?.Id == device.Id)
                    {
                        Trace.Message("ConnectAsync Error: {0} {1}", args.Device?.Id, args.Device?.Name);
                        reject(new DeviceConnectionException((Guid)args.Device?.Id, args.Device?.Name,
                                                             args.ErrorMessage));
                    }
                },

                    subscribeReject : handler => DeviceConnectionError   += handler,
                    unsubscribeReject : handler => DeviceConnectionError -= handler,
                    token : cts.Token);
            }
        }
示例#29
0
        protected override Task WriteNativeAsync(Byte[] data)
        {
            Exception exception =
                new Exception(
                    $"Device '{this.Characteristic.Service.Device.Id}' disconnected while writing descriptor with {this.Id}.");

            return(TaskBuilder
                   .FromEvent <Boolean, EventHandler <CBDescriptorEventArgs>, EventHandler <CBPeripheralErrorEventArgs> >(
                       () =>
            {
                if (this._parentDevice.State != CBPeripheralState.Connected)
                {
                    throw exception;
                }

                this._parentDevice.WriteValue(NSData.FromArray(data), this._nativeDescriptor);
            },
                       (complete, reject) => (sender, args) =>
            {
                if (args.Descriptor.UUID != this._nativeDescriptor.UUID)
                {
                    return;
                }

                if (args.Error != null)
                {
                    reject(new Exception(args.Error.Description));
                }
                else
                {
                    complete(true);
                }
            },
                       handler => this._parentDevice.WroteDescriptorValue += handler,
                       handler => this._parentDevice.WroteDescriptorValue -= handler,
                       reject => (sender, args) =>
            {
                if (args.Peripheral.Identifier == this._parentDevice.Identifier)
                {
                    reject(exception);
                }
            },
                       handler => this._centralManager.DisconnectedPeripheral += handler,
                       handler => this._centralManager.DisconnectedPeripheral -= handler));
        }
示例#30
0
        protected override Task StopUpdatesNativeAsync()
        {
            var exception = new Exception($"Device {Service.Device.Id} disconnected while stopping updates for characteristic with {Id}.");

            _parentDevice.UpdatedCharacterteristicValue -= UpdatedNotify;

            return(TaskBuilder.FromEvent <bool, EventHandler <CBCharacteristicEventArgs>, EventHandler <CBPeripheralErrorEventArgs> >(
                       execute: () =>
            {
                if (_parentDevice.State != CBPeripheralState.Connected)
                {
                    throw exception;
                }

                _parentDevice.SetNotifyValue(false, _nativeCharacteristic);
            },
                       getCompleteHandler: (complete, reject) => (sender, args) =>
            {
                if (args.Characteristic.UUID != _nativeCharacteristic.UUID)
                {
                    return;
                }

                if (args.Error != null)
                {
                    reject(new Exception($"Stop Notifications: Error {args.Error.Description}"));
                }
                else
                {
                    Trace.Message($"StopUpdates IsNotifying: {args.Characteristic.IsNotifying}");
                    complete(args.Characteristic.IsNotifying);
                }
            },
                       subscribeComplete: handler => _parentDevice.UpdatedNotificationState += handler,
                       unsubscribeComplete: handler => _parentDevice.UpdatedNotificationState -= handler,
                       getRejectHandler: reject => ((sender, args) =>
            {
                if (args.Peripheral.Identifier == _parentDevice.Identifier)
                {
                    reject(exception);
                }
            }),
                       subscribeReject: handler => _bleCentralManagerDelegate.DisconnectedPeripheral += handler,
                       unsubscribeReject: handler => _bleCentralManagerDelegate.DisconnectedPeripheral -= handler));
        }