Пример #1
0
        /// <summary>
        /// Run actual filmware upgrade procedure (Secure DFU)
        /// </summary>
        /// <param name="device">Device which is switched to Secure DFU mode</param>
        /// <param name="FirmwarePath"></param>
        /// <param name="InitFilePath"></param>
        /// <returns></returns>
        private async Task RunSecureDFU(IDevice device, Stream FirmwarePacket, Stream InitPacket)
        {
            IGattCharacteristic controlPoint = null;
            IGattCharacteristic packetPoint  = null;

            //await RefreshGattAsync(device);

            device.Connect();
            await device.ConnectWait().Timeout(DeviceConnectionTimeout);

            // Request MTU only once
            await device.RequestMtu(256).Timeout(OperationTimeout);

            controlPoint = await device.GetKnownCharacteristics(DfuService, SecureDFUControlPointCharacteristic).Timeout(OperationTimeout);

            packetPoint = await device.GetKnownCharacteristics(DfuService, SecureDFUPacketCharacteristic).Timeout(OperationTimeout);

            await controlPoint.EnableNotifications(true);

            try {
                await SendInitPacket(device, InitPacket, controlPoint, packetPoint);
                await SendFirmware(device, FirmwarePacket, controlPoint, packetPoint);
            }
            catch (Exception)
            {
                await Cleanup(controlPoint, device);

                throw;
            }
            finally
            {
                await Cleanup(controlPoint, device);
            }
        }
Пример #2
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="characteristic"></param>
 /// <param name="useIndicationIfAvailable"></param>
 /// <returns></returns>
 public static IObservable <CharacteristicResult> RegisterAndNotify(this IGattCharacteristic characteristic, bool useIndicationIfAvailable = false)
 => characteristic
 .EnableNotifications(useIndicationIfAvailable)
 .Where(x => x)
 .Select(x => characteristic.WhenNotificationReceived())
 .Switch()
 .Finally(() => characteristic.DisableNotifications().Subscribe());
Пример #3
0
        public async Task <CharacteristicGattResult> GetNotifyResult(IGattCharacteristic characteristic)
        {
            await characteristic.EnableNotifications();

            var TXN = await characteristic.RegisterAndNotify();

            return(await characteristic.WhenNotificationReceived());
        }
Пример #4
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
                  )
              )
          );
Пример #5
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");
        }
        /// <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>
        /// <param name="autoCleanup"></param>
        /// <returns></returns>
        public static IObservable <CharacteristicGattResult> RegisterAndNotify(this IGattCharacteristic characteristic, bool useIndicationIfAvailable = false, bool autoCleanup = true)
        {
            var ob = characteristic
                     .EnableNotifications(useIndicationIfAvailable)
                     .Select(x => x.Characteristic.WhenNotificationReceived())
                     .Switch();

            if (autoCleanup)
            {
                ob = ob.Finally(() => characteristic
                                .DisableNotifications()
                                .Where(x => x.Characteristic.Service.Peripheral.Status == ConnectionState.Connected)
                                .Subscribe(
                                    _ => { },
                                    ex => Log.Write(ex)
                                    )
                                );
            }

            return(ob);
        }
Пример #7
0
        private async Task CharacteristicsDiscovered(IGattCharacteristic result)
        {
            await result.Read();

            await result.EnableNotifications();

            result.WhenNotificationReceived().Subscribe();

            //Zmiany w interfejsie
            this.RunOnUiThread(() =>
            {
                FindViewById <AppCompatImageButton>(Resource.Id.buttonClear).Click     += buttonClearClicked;
                FindViewById <AppCompatImageButton>(Resource.Id.buttonClear).Visibility = ViewStates.Visible;

                FindViewById <AppCompatImageButton>(Resource.Id.buttonColor).Click     += buttonColorClicked;
                FindViewById <AppCompatImageButton>(Resource.Id.buttonColor).Visibility = ViewStates.Visible;

                FindViewById <AppCompatImageButton>(Resource.Id.buttonText).Click     += buttonAddText;
                FindViewById <AppCompatImageButton>(Resource.Id.buttonText).Visibility = ViewStates.Visible;

                FindViewById <Android.Widget.LinearLayout>(Resource.Id.linearLayout1).AddView(drawView);

                FindViewById <TextInputEditText>(Resource.Id.textInputEditText1).Visibility = ViewStates.Visible;

                FindViewById <FloatingActionButton>(Resource.Id.fab).Click     += FabOnClick;
                FindViewById <FloatingActionButton>(Resource.Id.fab).Visibility = ViewStates.Visible;
            });


            gattCharacteristic = result;
            drawExist          = true;


            Snackbar.Make(FindViewById <Android.Widget.LinearLayout>(Resource.Id.linearLayout), "Połączono", Snackbar.LengthShort)
            .SetAction("Action", (View.IOnClickListener)null).Show();
            this.RGB = drawView.GetColor();
            sendColorToArduino();
        }
Пример #8
0
 public async Task <bool> ToggleNotify(IGattCharacteristic Characteristic)
 {
     if (Characteristic.IsNotifying)
     {
         this.watcher?.Dispose();
         this.IsNotifying = false;
     }
     else
     {
         this.IsNotifying = true;
         //var utf8 = await UserDialogs.Instance.ConfirmAsync(
         //    "Display Value as UTF8 or HEX?",
         //    okText: "UTF8",
         //    cancelText: "HEX"
         //var utf8 = false;
         ////);
         //this.watcher = Characteristic
         //    .RegisterAndNotify()
         //    .Subscribe(x => this.SetReadValue(x, utf8));
         await Characteristic.EnableNotifications();
     }
     return(IsNotifying);
 }
Пример #9
0
 /// <summary>
 /// Enables (and disables) notifications and hooks to listener
 /// </summary>
 /// <param name="characteristic"></param>
 /// <param name="useIndicationsIfAvailable"></param>
 /// <returns></returns>
 public static IObservable <GattCharacteristicResult> Notify(this IGattCharacteristic characteristic, bool useIndicationsIfAvailable = false)
 => characteristic
 .EnableNotifications(true, useIndicationsIfAvailable)
 .Select(_ => characteristic.WhenNotificationReceived())
 .Switch()
 .Finally(() => characteristic.EnableNotifications(false).Subscribe());
Пример #10
0
        /// <summary>
        /// Switch device in Secure DFU state
        /// ! IMPORTANT, assumes that each device has different name !
        /// </summary>
        /// <param name="device"></param>
        /// <returns>Device which is in buttonles state</returns>
        private async Task <IDevice> ButtonlessDFUWithoutBondsToSecureDFU(IDevice device)
        {
            Debug.WriteLineIf(LogLevelDebug, String.Format("Start of Buttonless switching"));

            //await RefreshGattAsync(device);

            IGattCharacteristic buttonlessCharacteristic          = null;
            TaskCompletionSource <CharacteristicGattResult> notif = null;

            device.Connect();
            device = await device.ConnectWait().Timeout(DeviceConnectionTimeout);

            buttonlessCharacteristic = await device.GetKnownCharacteristics(DfuService, DfuButtonlessCharacteristicWithoutBonds).Timeout(OperationTimeout);

            await buttonlessCharacteristic.EnableNotifications(true).Timeout(OperationTimeout);

            // Change device Name

            // Advertisment name should not be longer than 20 symbols
            var newFullName = device.Name + "DFU";
            var newName     = new string(newFullName.Take(20).ToArray());

            byte[] name       = Encoding.ASCII.GetBytes(newName);
            int    newNameLen = name.Length;

            byte[] newNameCommand = new byte[newNameLen + 1 + 1];
            newNameCommand[0] = CChangeAdvertisedName;
            newNameCommand[1] = (byte)(uint)newNameLen;
            name.CopyTo(newNameCommand, 2);

            var nameChangeNotif = GetTimedNotification(buttonlessCharacteristic);
            await buttonlessCharacteristic.Write(newNameCommand).Timeout(OperationTimeout);

            var nameChangeResult = await nameChangeNotif.Task;

            Debug.WriteLineIf(LogLevelDebug, String.Format("Device name change response {0}", nameChangeResult.Data != null ? BitConverter.ToString(nameChangeResult.Data) : "Empty"));

            // Jump from the main application to Secure DFU bootloader (Secure DFU mode)
            notif = GetTimedNotification(buttonlessCharacteristic);
            await buttonlessCharacteristic.Write(CEnterDFU).Timeout(OperationTimeout);

            var result = await notif.Task;

            Debug.WriteLineIf(LogLevelDebug, String.Format("Restart response {0}", result.Data != null ? BitConverter.ToString(result.Data) : "Empty"));

            await buttonlessCharacteristic.DisableNotifications();

            /*
             * The response received from the DFU device contains:
             * +---------+--------+----------------------------------------------------+
             * | byte no | value  | description                                        |
             * +---------+--------+----------------------------------------------------+
             * | 0       | 0x20   | Response code                                      |
             * | 1       | 0x01   | The Op Code of a request that this response is for |
             * | 2       | STATUS | Status code                                        |
             * +---------+--------+----------------------------------------------------+
             */
            int status = result.Data[2];

            if (status != ButtonlessSwitchSuccessCode)
            {
                throw new Exception("Init status not correct " + status);
            }


            bool        alreadyRestarted = false;
            IDisposable dispose          = null;

            dispose = device.WhenStatusChanged().Subscribe(res =>
            {
                if (res == ConnectionStatus.Disconnected || res == ConnectionStatus.Disconnecting)
                {
                    alreadyRestarted = true;
                }
                Debug.WriteLine("###################### STAT {0}", res);
            });


            dispose?.Dispose();
            if (!alreadyRestarted)
            {
                await device.WhenDisconnected().Take(1).Timeout(DeviceRestartTimeout);

                device.CancelConnection();
            }

            IDevice newDevice = await ScanDFUDevice(device, newName);

            Debug.WriteLineIf(LogLevelDebug, String.Format("End of Buttonless switching"));

            return(newDevice);
        }
Пример #11
0
        /// <summary>
        /// Ensures connection status. Connects device if necessary.
        /// </summary>
        public override void EnsureConnection()
        {
            // Stop scan if device gets connected
            EEDeviceManagerFactory.DeviceManager.StopScan();

            if (_bleDevice != null && !_bleDevice.IsConnected())
            {
                bool success = Task.Run(async() =>
                {
                    _bleDevice.Connect(new ConnectionConfig {
                        AutoConnect = true, AndroidConnectionPriority = ConnectionPriority.High
                    });

                    // Change MTU size to at least 256 bytes otherwise protocol might not work
                    int mtu = await _bleDevice.RequestMtu(256);
                    if (mtu < 256)
                    {
                        Diagnostic.Msg(1, "EnsureConnection", "Unable to set MTU size to 256. Communication might not work correctly.");
                    }
                    else
                    {
                        Diagnostic.Msg(1, "EnsureConnection", "Set MTU size to " + mtu);
                    }

                    int loopCnt = 0;
                    while (loopCnt < 100 && !_bleDevice.IsConnected())
                    {
                        loopCnt++;
                        await Task.Delay(100);
                    }
                    if (!_bleDevice.IsConnected())
                    {
                        // Could not connect to device
                        return(false);
                    }

                    await _bleDevice.DiscoverServices();

                    // Check rx Characteristic for notification or indication
                    IGattCharacteristic rxCharacteristic = await _bleDevice.GetCharacteristicsForService(ServiceUuid)
                                                           .FirstOrDefaultAsync(x => x.Uuid == RxCharacteristicUuid);

                    if (!rxCharacteristic.CanNotifyOrIndicate())
                    {
                        return(false);
                    }

                    // Enable notification/indication on device
                    await rxCharacteristic.EnableNotifications(true);
                    rxCharacteristic.WhenNotificationReceived().Subscribe(result =>
                    {
                        _stopWatch.Stop();
                        lock (_lockDebugInfo)
                        {
                            if (_responseTimeMs.Count >= 1000)
                            {
                                _responseTimeMs.RemoveAt(0);
                            }
                            _responseTimeMs.Add(_stopWatch.ElapsedMilliseconds);
                        }
                        foreach (byte b in result.Data)
                        {
                            _queueRx.Enqueue(b);
                        }
                    });

                    return(_bleDevice.IsConnected());
                }).Result;

                Connected = success;

                if (!success)
                {
                    // Could not connect to device
                    Diagnostic.Msg(1, "EnsureConnection", "Could not connect to device");
                    return;
                }
                else
                {
                    // Need to send DIAS to keep connection open
                    var ee31 = new Protocol.EE31Protocol(this);
                    IEECommandResult result = ee31.ExecuteCommand(EE31Command.Discovery,
                                                                  new DiscoveryCmdParams(DiscoveryCmdParams.BuildNewDiscoveryId(), 0, 20, 500, 0xAF));

                    if (result.Code != EECmdResultCode.Success)
                    {
                        Diagnostic.Msg(1, "EnsureConnection", "Failed to send DIAS command (" + result.Code.ToString() + ")");
                    }
                }
            }

            _cmdTx = 0x0;
            while (!_queueRx.IsEmpty)
            {
                _queueRx.TryDequeue(out byte dummy);
            }
        }
Пример #12
0
        private void ConnectToServer()
        {
            server.Connect();
            Server_Name.Text = "Currently connected to " + server.Name;

            server.WhenAnyCharacteristicDiscovered().Subscribe(characteristic =>
            {
                //Debug.WriteLine("Char" + characteristic.Uuid);
            });

            //set up identity management
            server.GetKnownCharacteristics(StaticGuids.buzzerServiceGuid, StaticGuids.identityCharGuid).Subscribe(identityChar =>
            {
                Debug.WriteLine("Found Identity char");
                this.identityChar = identityChar;

                //writing nickname allows server to create association b/w uuid and nickname
                identityChar.Write(Encoding.UTF8.GetBytes(nickname)).Subscribe(write =>
                {
                    Debug.WriteLine("Successful identity write");
                }, error =>
                {
                    Debug.WriteLine(error.GetBaseException());
                });

                identityChar.Read().Subscribe(read =>
                {
                    addOne(LoadLabel);
                    clientGuid = Guid.Parse(Encoding.UTF8.GetString(read.Data));
                    Debug.WriteLine("Found own GUID: " + clientGuid.ToString());
                }, error =>
                {
                    Debug.WriteLine(error.ToString());
                });
            });

            //set up lock status
            server.GetKnownCharacteristics(StaticGuids.buzzerServiceGuid, StaticGuids.lockStatusGuid).Subscribe(lockStatusChar =>
            {
                Debug.WriteLine("Found Lock char");
                lockStatusChar.EnableNotifications();
                lockStatusChar.WhenNotificationReceived().Subscribe(result =>
                {
                    Debug.WriteLine("Notification recieved" + Encoding.UTF8.GetString(result.Data));
                    string reply       = Encoding.UTF8.GetString(result.Data);
                    char tempLockState = reply[0];
                    Debug.WriteLine(reply.Substring(1, 36));
                    Guid buzzDevice = Guid.Parse(reply.Substring(1, 36));

                    //TODO fix risk that client guid is not yet found
                    if (buzzDevice == clientGuid)
                    {
                        tempLockState = 'U';
                    }

                    lockStatus = tempLockState;
                    addOne(LoadLabel);
                });
            });

            //set up buzz char
            server.GetKnownCharacteristics(StaticGuids.buzzerServiceGuid, StaticGuids.buzzCharGuid).Subscribe(buzzerChar =>
            {
                Debug.WriteLine("Found buzzer char");
                this.buzzerChar = buzzerChar;
                addOne(LoadLabel);
            });

            //set up team info
            server.GetKnownCharacteristics(StaticGuids.buzzerServiceGuid, StaticGuids.teamCharGuid).Subscribe(teamChar =>
            {
                Debug.WriteLine("Team char found");
                teamChar.EnableNotifications();
                teamChar.WhenNotificationReceived().Subscribe(result =>
                {
                    Debug.WriteLine("Team info recieved");
                    string teamInfoString = Encoding.UTF8.GetString(result.Data);
                    string[] teamInfo     = teamInfoString.Split(teamSplitter, 2, StringSplitOptions.None);
                    foreach (string teamString in teamInfo)
                    {
                        string[] names = teamString.Split(nameSplitter, 50, StringSplitOptions.None);

                        if (!teams.ContainsKey(names[0]))
                        {
                            teams[names[0]] = new List <Guid>();
                        }
                        List <Guid> teamMembers = teams[names[0]];
                        for (int i = 1; i < names.Length; i++)
                        {
                            teamMembers.Add(Guid.Parse(names[i]));
                        }
                    }
                    addOne(LoadLabel);
                });
            });
        }
 public override IObservable <CharacteristicGattResult> EnableNotifications(bool enableIndicationsIfAvailable)
 {
     return(chs.EnableNotifications());
 }