Esempio n. 1
0
        /// <summary>
        /// Used for writing blobs
        /// </summary>
        /// <param name="ch">The characteristic to write on</param>
        /// <param name="stream">The stream to send</param>
        /// <param name="reliableWrite">Use reliable write atomic writing if available (windows and android)</param>
        public static IObservable <BleWriteSegment> BlobWrite(this IGattCharacteristic ch, Stream stream, bool reliableWrite)
        => Observable.Create <BleWriteSegment>(async ob =>
        {
            var cts   = new CancellationTokenSource();
            var trans = reliableWrite
                    ? ch.Service.Device.BeginReliableWriteTransaction()
                    : new VoidGattReliableWriteTransaction();

            using (trans)
            {
                var mtu    = ch.Service.Device.MtuSize;
                var buffer = new byte[mtu];
                var read   = stream.Read(buffer, 0, buffer.Length);
                var pos    = read;
                var len    = Convert.ToInt32(stream.Length);

                while (!cts.IsCancellationRequested && read > 0)
                {
                    await trans
                    .Write(ch, buffer)
                    .ToTask(cts.Token)
                    .ConfigureAwait(false);

                    //if (this.Value != buffer)
                    //{
                    //    trans.Abort();
                    //    throw new GattReliableWriteTransactionException("There was a mismatch response");
                    //}
                    var seg = new BleWriteSegment(buffer, pos, len);
                    ob.OnNext(seg);

                    read = stream.Read(buffer, 0, buffer.Length);

                    if (read > 0 && read < buffer.Length)
                    {
                        for (var index = read; index < buffer.Length; index++)
                        {
                            buffer[index] = 0;
                        }
                    }

                    pos += read;
                }
                await trans.Commit();
            }
            ob.OnCompleted();

            return(() =>
            {
                cts.Cancel();
                trans.Dispose();
            });
        });
Esempio n. 2
0
 public WriteRequest(IGattCharacteristic characteristic,
                     IPeripheral peripheral,
                     byte[] data,
                     int offset,
                     bool isReplyNeeded)
 {
     this.Characteristic = characteristic;
     this.Peripheral     = peripheral;
     this.Offset         = offset;
     this.IsReplyNeeded  = isReplyNeeded;
     this.Data           = data;
 }
Esempio n. 3
0
        public static void AssertWrite(this IGattCharacteristic characteristic, bool withResponse)
        {
            if (!characteristic.CanWrite())
            {
                throw new ArgumentException($"This characteristic '{characteristic.Uuid}' does not support writes");
            }

            if (withResponse && !characteristic.CanWriteWithResponse())
            {
                throw new ArgumentException($"This characteristic '{characteristic.Uuid}' does not support writes with response");
            }
        }
Esempio n. 4
0
 public static IObservable <byte[]> ReadInterval(this IGattCharacteristic character, TimeSpan timeSpan)
 {
     return(Observable.Create <byte[]>(ob =>
                                       Observable
                                       .Interval(timeSpan)
                                       .Subscribe(async _ =>
     {
         var read = await character.Read();
         ob.OnNext(read);
     })
                                       ));
 }
Esempio n. 5
0
        public override IObservable <GattCharacteristicResult> Write(IGattCharacteristic characteristic, byte[] value)
        {
            this.AssertAction();

            if (!(characteristic is GattCharacteristic platform))
            {
                throw new ArgumentException("Characteristic must be UWP type");
            }

            this.native.WriteValue(platform.Native, value.AsBuffer());
            return(Observable.Return(new GattCharacteristicResult(characteristic, value, GattCharacteristicResultType.Write)));
        }
Esempio n. 6
0
        public override IObservable <CharacteristicGattResult> Write(IGattCharacteristic characteristic, byte[] value)
        {
            this.AssertAction();

            if (!(characteristic is GattCharacteristic platform))
            {
                throw new ArgumentException("Characteristic must be UWP type");
            }

            // TODO: need write observable
            this.native.WriteValue(platform.Native, null);
            return(null);
        }
Esempio n. 7
0
        protected override async Task <bool> ValidateServicesAsync(IEnumerable <IGattService> services, CancellationToken token)
        {
            var service = services?.FirstOrDefault(s => s.Uuid == SERVICE_UUID);

            _characteristic = service?.Characteristics?.FirstOrDefault(c => c.Uuid == CHARACTERISTIC_UUID);

            if (_characteristic != null)
            {
                return(await _bleDevice?.EnableNotificationAsync(_characteristic, token));
            }

            return(false);
        }
Esempio n. 8
0
        protected override Task <bool> ValidateServicesAsync(IEnumerable <IGattService> services, CancellationToken token)
        {
            var service = services?.FirstOrDefault(s => s.Uuid == SERVICE_UUID);

            _characteristic = service?.Characteristics?.FirstOrDefault(c => c.Uuid == CHARACTERISTIC_UUID);

            var deviceInformationService = services?.FirstOrDefault(s => s.Uuid == SERVICE_UUID_DEVICE_INFORMATION);

            _firmwareRevisionCharacteristic = deviceInformationService?.Characteristics?.FirstOrDefault(c => c.Uuid == CHARACTERISTIC_UUID_FIRMWARE_REVISION);
            _modelNumberCharacteristic      = deviceInformationService?.Characteristics?.FirstOrDefault(c => c.Uuid == CHARACTERISTIC_UUID_MODEL_NUMBER);

            return(Task.FromResult(_characteristic != null && _firmwareRevisionCharacteristic != null && _modelNumberCharacteristic != null));
        }
Esempio n. 9
0
        public bool WriteNoResponse(IGattCharacteristic characteristic, byte[] data)
        {
            if (State != BluetoothLEDeviceState.Connected)
            {
                return(false);
            }

            var nativeCharacteristic = ((GattCharacteristic)characteristic).Characteristic;
            var nativeData           = NSData.FromArray(data);

            _peripheral.WriteValue(nativeData, nativeCharacteristic, CBCharacteristicWriteType.WithoutResponse);
            return(true);
        }
Esempio n. 10
0
        private static async Task SendChallengeResponse(IGattCharacteristic authCharacteristic, byte[] challenge)
        {
            var challengePayload = new byte[ChallengePayloadLength];

            Buffer.BlockCopy(challenge, ChallengeHeaderLength, challengePayload, 0, challengePayload.Length);
            var responsePayload = Encrypt(StaticEncryptionKey, challengePayload);

            var responseHeader = new byte[] { 0x03, 0x00 };
            var response       = new byte[responseHeader.Length + responsePayload.Length];

            Buffer.BlockCopy(responseHeader, 0, response, 0, responseHeader.Length);
            Buffer.BlockCopy(responsePayload, 0, response, responseHeader.Length, responsePayload.Length);
            await authCharacteristic.WriteWithoutResponse(response);
        }
Esempio n. 11
0
        /// <summary>
        /// Called when a new characteristic is discovered
        /// </summary>
        /// <param name="characteristic">The characteristic</param>
        private void OnCharacteristicDiscovered(IGattCharacteristic characteristic)
        {
            var id = characteristic.Uuid;

            if (id == Constants.ImageCharacteristic)
            {
                this.imageCharacteristic = characteristic;
                this.NotifyCanSendImages?.Invoke();
            }
            else if (id == Constants.ImageReceivedCharacteristic)
            {
                this.imageReceivedCharacteristic = characteristic;
            }
        }
Esempio n. 12
0
        public static IObservable <byte[]> WhenReadOrNotify(this IGattCharacteristic character, TimeSpan readInterval)
        {
            if (character.CanNotify())
            {
                return(character.SubscribeToNotifications());
            }

            if (character.CanRead())
            {
                return(character.ReadInterval(readInterval));
            }

            throw new ArgumentException($"Characteristic {character.Uuid} does not have read or notify permissions");
        }
Esempio n. 13
0
        public override IObservable <CharacteristicResult> Write(IGattCharacteristic characteristic, byte[] value)
        {
            this.AssertAction();

            var platform = characteristic as GattCharacteristic;

            if (platform == null)
            {
                throw new ArgumentException("");
            }

            // TODO: need write observable
            this.native.WriteValue(platform.Native, null);
            return(null);
        }
        private async Task <IGattCharacteristic> GetGattCharacteristicAsync(Tuple <Guid, Guid> gattChar)
        {
            IGattCharacteristic characteristic = null;

            if (gattChar.Item1 == MbientLab.MetaWear.Constants.METAWEAR_GATT_SERVICE && _advertisementCharacteristics != null)
            {
                characteristic = _advertisementCharacteristics.FirstOrDefault(x => x.Uuid == gattChar.Item2);
            }
            else
            {
                characteristic = await device.GetKnownCharacteristics(gattChar.Item1, gattChar.Item2).FirstAsync();
            }

            return(characteristic);
        }
Esempio n. 15
0
        public Task <bool> WriteNoResponseAsync(IGattCharacteristic characteristic, byte[] data, CancellationToken token)
        {
            lock (_lock)
            {
                if (State != BluetoothLEDeviceState.Connected)
                {
                    return(Task.FromResult(false));
                }

                var nativeCharacteristic = ((GattCharacteristic)characteristic).Characteristic;
                var nativeData           = NSData.FromArray(data);

                _peripheral.WriteValue(nativeData, nativeCharacteristic, CBCharacteristicWriteType.WithoutResponse);
                return(Task.FromResult(true));
            }
        }
Esempio n. 16
0
 /// <summary>
 /// Enables notifications and hooks it for discovered characteristic.  When subscription is disposed, it will also clean up.
 /// </summary>
 /// <param name="characteristic"></param>
 /// <param name="useIndicationIfAvailable"></param>
 /// <returns></returns>
 public static IObservable <CharacteristicGattResult> RegisterAndNotify(this IGattCharacteristic characteristic, bool useIndicationIfAvailable = false)
 => characteristic
 .EnableNotifications(useIndicationIfAvailable)
 .Select(x => x.Characteristic.WhenNotificationReceived())
 .Switch()
 .Finally(() => characteristic
          .DisableNotifications()
          .Where(x => x.Characteristic.Service.Device.Status == ConnectionStatus.Connected)
          .Subscribe(
              _ => {},
              ex => Log.Warn(
                  BleLogCategory.Characteristic,
                  "Could not cleanly disable notifications in RegisterAndNotify - " + ex
                  )
              )
          );
Esempio n. 17
0
        protected override Task <bool> ValidateServicesAsync(IEnumerable <IGattService> services, CancellationToken token)
        {
            var deviceInformationService = services?.FirstOrDefault(s => s.Uuid == SERVICE_UUID_DEVICE_INFORMATION);

            _firmwareRevisionCharacteristic = deviceInformationService?.Characteristics?.FirstOrDefault(c => c.Uuid == CHARACTERISTIC_UUID_FIRMWARE_REVISION);
            _hardwareRevisionCharacteristic = deviceInformationService?.Characteristics?.FirstOrDefault(c => c.Uuid == CHARACTERISTIC_UUID_HARDWARE_REVISION);

            var remoteControlService = services?.FirstOrDefault(s => s.Uuid == SERVICE_UUID_REMOTE_CONTROL);

            _remoteControlCharacteristic = remoteControlService?.Characteristics?.FirstOrDefault(c => c.Uuid == CHARACTERISTIC_UUID_REMOTE_CONTROL);
            _quickDriveCharacteristic    = remoteControlService?.Characteristics?.FirstOrDefault(c => c.Uuid == CHARACTERISTIC_UUID_QUICK_DRIVE);

            return(Task.FromResult(
                       _firmwareRevisionCharacteristic != null &&
                       _hardwareRevisionCharacteristic != null &&
                       _remoteControlCharacteristic != null &&
                       _quickDriveCharacteristic != null));
        }
Esempio n. 18
0
        public static IObservable <CharacteristicResult> WhenReadOrNotify(this IGattCharacteristic character, TimeSpan readInterval)
        {
            if (character.CanNotify())
            {
                return(character
                       .EnableNotifications()
                       .Where(x => x)
                       .Select(x => character.WhenNotificationReceived())
                       .Switch());
            }

            if (character.CanRead())
            {
                return(character.ReadInterval(readInterval));
            }

            throw new ArgumentException($"Characteristic {character.Uuid} does not have read or notify permissions");
        }
Esempio n. 19
0
        /// <summary>
        /// Write bytes through communication interface
        /// </summary>
        public override void WriteBytes(byte[] buffer, int offset, int count)
        {
            if (_bleDevice == null)
            {
                throw new ArgumentNullException("_bleDevice");
            }

            _cmdTx = buffer[2];

            int loopCnt = 0;

            while (loopCnt <= _maxAutoRetries)
            {
                loopCnt++;
                try
                {
                    IGattCharacteristic characteristic = _bleDevice.GetCharacteristicsForService(ServiceUuid)
                                                         .FirstOrDefaultAsync(x => x.Uuid == TxCharacteristicUuid).Wait();

                    if (null != characteristic)
                    {
                        Stopwatch watch = Stopwatch.StartNew();
                        characteristic.WriteWithoutResponse(buffer).Wait();
                        watch.Stop();
                        _stopWatch.Restart();

                        lock (_lockDebugInfo)
                        {
                            if (_writeTimeMs.Count >= 1000)
                            {
                                _writeTimeMs.RemoveAt(0);
                            }
                            _writeTimeMs.Add(watch.ElapsedMilliseconds);
                        }

                        break;
                    }
                }
                catch (Exception)
                {
                    Thread.Sleep(75);
                }
            }
        }
        protected override async Task <bool> ValidateServicesAsync(IEnumerable <IGattService> services, CancellationToken token)
        {
            var service = services?.FirstOrDefault(s => s.Uuid == SERVICE_UUID);

            _writeCharacteristic = service?.Characteristics?.FirstOrDefault(c => c.Uuid == CHARACTERISTIC_UUID_WRITE);

            var deviceInformationService = services?.FirstOrDefault(s => s.Uuid == SERVICE_UUID_DEVICE_INFORMATION);

            _firmwareRevisionCharacteristic = deviceInformationService?.Characteristics?.FirstOrDefault(c => c.Uuid == CHARACTERISTIC_UUID_FIRMWARE_REVISION);
            _hardwareRevisionCharacteristic = deviceInformationService?.Characteristics?.FirstOrDefault(c => c.Uuid == CHARACTERISTIC_UUID_HARDWARE_REVISION);

            _notifyCharacteristic = service?.Characteristics?.FirstOrDefault(c => c.Uuid == CHARACTERISTIC_UUID_NOTIFY);
            if (_notifyCharacteristic != null)
            {
                await _bleDevice?.EnableNotificationAsync(_notifyCharacteristic, token);
            }

            return(_writeCharacteristic != null && _firmwareRevisionCharacteristic != null && _hardwareRevisionCharacteristic != null);
        }
Esempio n. 21
0
        public void ConnectPrinter(IPeripheral selectedPeripheral)
        {
            if (!selectedPeripheral.IsConnected())
            {
                selectedPeripheral.Connect();
            }

            _perifDisposable = selectedPeripheral.WhenAnyCharacteristicDiscovered().Subscribe((characteristic) =>
            {
                if (characteristic.CanWrite() && !characteristic.CanRead() && !characteristic.CanNotify())
                {
                    _savedCharacteristic = characteristic;

                    IsReady = true;

                    _perifDisposable.Dispose();
                }
            });
        }
Esempio n. 22
0
        public void Disconnect()
        {
            if (ConnectState != DeviceState.Disconnecting || ConnectState != DeviceState.Disconnected)
            {
                try
                {
                    readCharacteristicObserver?.Dispose();
                }
                catch (Exception e)
                {
                    // Crashes.TrackError(e);
                }
                try
                {
                    chararacteristicListener?.Dispose();
                }
                catch (Exception e)
                {
                    //  Crashes.TrackError(e);
                }
                try
                {
                    stateListener?.Dispose();
                }
                catch (Exception e)
                {
                    //   Crashes.TrackError(e);
                }

                try
                {
                    device.CancelConnection();
                }
                catch (Exception e)
                {
                    //  Crashes.TrackError(e);
                }


                readCharacteristic  = null;
                writeCharacteristic = null;
            }
        }
Esempio n. 23
0
        /// <summary>
        /// Set Packet Receipt Notification (PRN) value.
        /// Sets the number of packets to be sent before receiving a Packet Receipt Notification. The default is 0.
        /// </summary>
        /// <param name="device"></param>
        /// <param name="prn"></param>
        /// <returns></returns>
        private async Task SetPRN(IGattCharacteristic controlPoint, int prn)
        {
            // PRN value should be LSB
            byte[] data = new byte[] {
                CSetPRN,
                0,
                0
            };
            SetUint16LSB(data, 1, prn);

            var notif = GetTimedNotification(controlPoint);
            await controlPoint.Write(data).Timeout(OperationTimeout);

            var result = await notif.Task;

            Debug.WriteLineIf(LogLevelDebug, String.Format("Received PRN set response: {0}", BitConverter.ToString(result.Data)));

            AssertSuccess(result);
        }
Esempio n. 24
0
        private void Button_ScanService(object sender, RoutedEventArgs e)
        {
            currdev.DiscoverServices().Subscribe(mService =>
            {
                IGattService findServ = mService;
                findServ.DiscoverCharacteristics().Subscribe(mCharacter =>
                {
                    Debug.WriteLine("FindCharacter OK:" + mCharacter.Uuid);
                    if (mCharacter.Uuid == (new Guid("48EB9002-F352-5FA0-9B06-8FCAA22602CF")))
                    {
                        Debug.WriteLine("找到了 OK:");
                        FindCharacter = mCharacter;
                    }
                }
                                                             );

                //Debug.WriteLine("mService OK");
            });
        }
Esempio n. 25
0
        public async Task <bool> WriteAsync(IGattCharacteristic characteristic, byte[] data, CancellationToken token)
        {
            using (token.Register(() =>
            {
                lock (_lock)
                {
                    _writeCompletionSource?.TrySetResult(false);
                }
            }))
            {
                lock (_lock)
                {
                    if (_bluetoothGatt == null || State != BluetoothLEDeviceState.Connected)
                    {
                        return(false);
                    }

                    var nativeCharacteristic = ((GattCharacteristic)characteristic).BluetoothGattCharacteristic;
                    nativeCharacteristic.WriteType = GattWriteType.Default;

                    if (!nativeCharacteristic.SetValue(data))
                    {
                        return(false);
                    }

                    _writeCompletionSource = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);

                    if (!_bluetoothGatt.WriteCharacteristic(nativeCharacteristic))
                    {
                        _writeCompletionSource = null;
                        return(false);
                    }
                }

                var result = await _writeCompletionSource.Task.ConfigureAwait(false);

                lock (_lock)
                {
                    _writeCompletionSource = null;
                    return(result);
                }
            }
        }
Esempio n. 26
0
        public Device(Plugin.BluetoothLE.IDevice dev)
        {
            device = dev;
            Name   = dev.Name;

            chararacteristicListener = device.WhenAnyCharacteristicDiscovered().Subscribe(characteristic =>
            {
                if (characteristic.Uuid.ToString() == BleService.CharacteristictReadUuid)
                {
                    readCharacteristic = characteristic;
                    OnStateChanged(DeviceState.Connected);
                    RaisePropertyChanged(nameof(ConnectState));
                    if (readCharacteristic.CanNotify())
                    {
                        readCharacteristicObserver = characteristic.RegisterAndNotify(true).Subscribe(r =>
                        {
                            Read?.Invoke(r.Data);
                        },
                                                                                                      exception =>
                        {
                            //   Crashes.TrackError(exception);
                        });
                    }
                }

                if (characteristic.Uuid.ToString() == BleService.CharacteristicWriteUuid)
                {
                    if (characteristic.CanWrite())
                    {
                        writeCharacteristic = characteristic;
                        OnStateChanged(DeviceState.Connected);
                        RaisePropertyChanged(nameof(ConnectState));
                    }
                }
            }, exception =>
            {
                //  Crashes.TrackError(exception);
            });
            stateListener = device.WhenStatusChanged().Subscribe(f =>
            {
                OnStateChanged(ConnectState);
            });
        }
Esempio n. 27
0
        public static IObservable <BleWriteSegment> WriteBlobTransaction(this IGattCharacteristic ch, Stream stream) => Observable.Create <BleWriteSegment>(async(ob, ct) =>
        {
            var trans = ch.Service.Peripheral.TryBeginTransaction();
            using (trans)
            {
                var mtu       = ch.Service.Peripheral.MtuSize;
                var buffer    = new byte[mtu];
                var read      = stream.Read(buffer, 0, buffer.Length);
                var pos       = read;
                var len       = Convert.ToInt32(stream.Length);
                var remaining = 0;

                while (!ct.IsCancellationRequested && read > 0)
                {
                    await trans
                    .Write(ch, buffer)
                    .ToTask(ct)
                    .ConfigureAwait(false);

                    //if (this.Value != buffer)
                    //{
                    //    trans.Abort();
                    //    throw new GattReliableWriteTransactionException("There was a mismatch response");
                    //}
                    var seg = new BleWriteSegment(buffer, pos, len);
                    ob.OnNext(seg);

                    remaining = len - pos;
                    if (remaining > 0 && remaining < mtu)
                    {
                        // readjust buffer -- we don't want to send extra garbage
                        buffer = new byte[remaining];
                    }

                    read = stream.Read(buffer, 0, buffer.Length);
                    pos += read;
                }
                await trans.Commit();
            }
            ob.OnCompleted();

            return(trans);
        });
Esempio n. 28
0
        void ConnectPrinter(IPeripheral selectedPeripheral)
        {
            if (!selectedPeripheral.IsConnected())
            {
                selectedPeripheral.Connect();
            }

            _perifDisposable = selectedPeripheral.WhenAnyCharacteristicDiscovered().Subscribe((characteristic) =>
            {
                //System.Diagnostics.Debug.WriteLine(characteristic.Description); //this is not suppported at this momment, and no neccesary I guess
                if (characteristic.CanWrite() && !characteristic.CanRead() && !characteristic.CanNotify())
                {
                    IsReadyToPrint       = true;
                    _savedCharacteristic = characteristic;
                    System.Diagnostics.Debug.WriteLine($"Writing {characteristic.Uuid} - {characteristic.CanRead()} - {characteristic.CanIndicate()} - {characteristic.CanNotify()}");
                    _perifDisposable.Dispose();
                }
            });
        }
Esempio n. 29
0
        /// <summary>
        /// Request and read DFU checksum from control point after data have been sent
        /// </summary>
        /// <param name="device"></param>
        /// <returns></returns>
        private async Task <ObjectChecksum> ReadChecksum(IGattCharacteristic controlPoint)
        {
            Debug.WriteLineIf(LogLevelDebug, String.Format("Begin read checksum"));
            ObjectChecksum checksum = new ObjectChecksum();

            CharacteristicGattResult result = null;

            for (var retry = 0; retry < MaxRetries; retry++)
            {
                try
                {
                    // Request checksum
                    var notif = GetTimedNotification(controlPoint);

                    var re = await controlPoint.Write(CCalculateCRC).Timeout(OperationTimeout);

                    Debug.WriteLine(re);
                    result = await notif.Task;
                    break;
                }
                catch (Exception)
                {
                    await Task.Delay(100);
                }
                finally
                {
                    if (retry == MaxRetries)
                    {
                        throw new DFUTimeout();
                    }
                }
            }

            Debug.WriteLineIf(LogLevelDebug, String.Format("Check Sum Response {0}", BitConverter.ToString(result.Data)));

            AssertSuccess(result);

            SetChecksum(checksum, result.Data);

            Debug.WriteLineIf(LogLevelDebug, String.Format("End read checksum"));
            return(checksum);
        }
Esempio n. 30
0
        private void ListView_ItemTapped(object sender, ItemTappedEventArgs e)
        {
            var select = (CharacteristicsList)e.Item;

            foreach (var c in AllCharacteristics)
            {
                if (c.Uuid == select.Uuid)
                {
                    SelectCharacteristic = c;
                    info_uuid.Text       = "UUID:" + SelectCharacteristic.Uuid;
                    info_read.Text       = "CallBack UUID:";
                    notify_btn.Text      = "Notify";
                    if (SelectCharacteristic.CanRead())
                    {
                        read_btn.IsVisible = true;
                    }
                    else
                    {
                        read_btn.IsVisible = false;
                    }
                    if (SelectCharacteristic.CanWrite())
                    {
                        write_btn.IsVisible = true;
                    }
                    else
                    {
                        write_btn.IsVisible = false;
                    }
                    if (SelectCharacteristic.CanNotify())
                    {
                        notify_btn.IsVisible = true;
                    }
                    else
                    {
                        notify_btn.IsVisible = false;
                    }
                    background.IsVisible = true;
                    info.IsVisible       = true;
                    break;
                }
            }
        }