private async Task <bool> Write(byte[] command)
 {
     // NOTE: the last two bytes are not encrypted
     // general idea seems to be that if the last byte of the command indicates an offline key offset (is non-zero), the command is "secure" and encrypted with the offline key
     if (encryptCipher != null)
     {
         encryptCipher.TransformBlock(command, 0, 16, command, 0);
         device.Debug("write (encrypted): " + BitConverter.ToString(command));
     }
     // write the command to the write characteristic
     return(await WriteCharacteristic.WriteAsync(command));
 }
        public DeviceViewModel(ScanResultViewModel result)
        {
            this.device = result.Device;

            Name = result.Name;
            Uuid = result.Uuid;

            BulbStatus = new LEDBulbStatus();

            ColorClickedCommand = new Command <Button>((obj) =>
            {
                BulbStatus.Red   = (int)(obj.BackgroundColor.R * 255);
                BulbStatus.Green = (int)(obj.BackgroundColor.G * 255);
                BulbStatus.Blue  = (int)(obj.BackgroundColor.B * 255);
            });

            this.ConnectionToggle = ReactiveCommand.CreateAsyncTask(
                this.WhenAny(
                    x => x.Status,
                    x => x.Value != ConnectionStatus.Disconnecting
                    ),
                x =>
            {
                if (this.conn == null)
                {
                    this.conn = this.device.CreateConnection().Subscribe();
                }
                else
                {
                    this.conn?.Dispose();
                    this.conn = null;
                }
                return(Task.FromResult(Unit.Default));
            }
                );

            this.QueryCurrentStatus = ReactiveCommand.CreateAsyncTask(
                this.WhenAny(
                    x => x.WriteCharacteristic,
                    x => x.ReadCharacteristic,
                    (write, read) => write.Value.CanWrite() && read.Value.CanNotify()
                    ),
                x =>
            {
                Debug.WriteLine($"Getting current status...");

                WriteCharacteristic.WriteWithoutResponse(LEDBulbManager.Current.CurrentStatus());

                return(Task.FromResult(Unit.Default));
            }
                );

            this.WhenAnyValue(x => x.Status, x => x.WriteCharacteristic, x => x.ReadCharacteristic, (status, write, read) => new { status, write, read }).Where(x => x.status == ConnectionStatus.Connected && x.write != null && x.read != null).Subscribe(connected =>
            {
                QueryCurrentStatus.Execute(null);
            });



            var canPowerToggle = this.WhenAny(x => x.IsConnected, x => x.WriteCharacteristic, (x, w) => x.Value == true && w != null);

            this.PowerToggle = ReactiveCommand.CreateAsyncTask(canPowerToggle,
                                                               x =>
            {
                WriteCharacteristic.WriteWithoutResponse(BulbStatus.PoweredOn ? LEDBulbManager.Current.PowerOff() : LEDBulbManager.Current.PowerOn());

                QueryCurrentStatus.Execute(null);
                return(Task.FromResult(Unit.Default));
            });

            this.SetRGBValue = ReactiveCommand.CreateAsyncTask(x =>
            {
                WriteCharacteristic.WriteWithoutResponse(LEDBulbManager.Current.SetRGBValue(BulbStatus.Red, BulbStatus.Green, BulbStatus.Blue));

                return(Task.FromResult(Unit.Default));
            });

            BulbStatus.WhenAnyValue(x => x.Red, x => x.Green, x => x.Blue).Subscribe(x =>
            {
                SetRGBValue.Execute(null);
            });

            this.device
            .WhenNameUpdated()
            .Subscribe(x => this.Name = this.device.Name);

            this.device
            .WhenStatusChanged()
            .Subscribe(x => Device.BeginInvokeOnMainThread(() =>
            {
                this.Status = x;

                switch (x)
                {
                case ConnectionStatus.Disconnecting:
                case ConnectionStatus.Connecting:
                    this.IsConnected = false;
                    this.ConnectText = x.ToString();
                    break;

                case ConnectionStatus.Disconnected:
                    this.IsConnected = false;
                    this.ConnectText = "Connect";
                    this.readRssiTimer?.Dispose();
                    break;

                case ConnectionStatus.Connected:
                    this.IsConnected   = true;
                    this.ConnectText   = "Disconnect";
                    this.readRssiTimer = this.device
                                         .WhenRssiUpdated()
                                         .Subscribe(rssi => this.Rssi = rssi);
                    break;
                }
            }));

            this.device.WhenAnyCharacteristicDiscovered()
            .Subscribe((IGattCharacteristic obj) =>
            {
                Debug.WriteLine($"+ Characteristic Discovered: {obj.Uuid} {obj.Properties}");

                if (LEDBulbManager.Current.CanInterface(obj))
                {
                    Debug.WriteLine($"++ CanInterface");

                    if (obj.Properties == CharacteristicProperties.WriteNoResponse)
                    {
                        WriteCharacteristic = obj;
                    }
                    else if (obj.Properties == CharacteristicProperties.Notify)
                    {
                        ReadCharacteristic = obj;
                    }
                }
                //Characteristics.Add(obj);
            });

            this.WhenAnyValue(x => x.ReadCharacteristic).Where(x => x != null).Subscribe(x =>
            {
                ReadCharacteristic.SubscribeToNotifications().Subscribe(notification =>
                {
                    Debug.WriteLine($"+ SubscribeToNotifications: {BitConverter.ToString(notification)}");

                    BulbStatus = BulbStatus ?? new LEDBulbStatus();
                    BulbStatus.TrySet(notification);

                    if (BulbStatus.PoweredOn)
                    {
                        PowerButtonImg = "power-button-on.png";
                    }
                    else
                    {
                        PowerButtonImg = "power-button-off.png";
                    }
                });
            });
        }
Exemple #3
0
            public override void OnServicesDiscovered(BluetoothGatt gatt, GattStatus status)
            {
                base.OnServicesDiscovered(gatt, status);

                try
                {
                    foreach (var bluetoothGattService in gatt.Services)
                    {
                        Log.Info(TAG, $"Service Discovered => {bluetoothGattService.Uuid}");
                        foreach (var bluetoothGattCharacteristic in bluetoothGattService.Characteristics)
                        {
                            Log.Info(TAG, $"Characteristic Discovered => {bluetoothGattCharacteristic.Uuid}");
                        }
                    }



                    WriteCharacteristic = gatt.GetService(DEX_SERVICE_SPP)
                                          .GetCharacteristic(DEX_CHARACTERISTIC_DATAWRITE);


                    Log.Info(TAG, $"WriteCharacteristic Properties => {WriteCharacteristic.Properties.ToString()}");


                    DeviceCharacteristic = gatt.GetService(DEX_SERVICE).GetCharacteristic(DEVICE_SETTINGS);


                    Log.Info(TAG, $"DeviceCharacteristic Properties => {DeviceCharacteristic.Properties.ToString()}");


                    StatusCharacteristic = gatt.GetService(DEX_SERVICE_SPP)
                                           .GetCharacteristic(DEX_CHARACTERISTIC_STATUS);


                    Log.Info(TAG, $"StatusCharacteristic Properties => {StatusCharacteristic.Properties.ToString()}");


                    gatt.SetCharacteristicNotification(DeviceCharacteristic, true);

                    var descDevice = DeviceCharacteristic.GetDescriptor(CLIENT_CHARACTERISTIC_CONFIG);

                    Log.Info(TAG, $"descDevice Permissions => {descDevice.Permissions.ToString()}");


                    descDevice.SetValue(BluetoothGattDescriptor.EnableNotificationValue.ToArray());
                    gatt.WriteDescriptor(descDevice);
                    descDevice.SetValue(BluetoothGattDescriptor.EnableIndicationValue.ToArray());
                    gatt.WriteDescriptor(descDevice);


                    if (gatt.SetCharacteristicNotification(WriteCharacteristic, true))
                    {
                        MainActivity.RunOnUiThread(() =>
                        {
                            Log.Info(TAG + DexService.Operation, "Set Write Characteristic succeeded");
                        });
                        DexService.LogMessage2("Set Write Characteristic succeeded", false);
                    }
                    else
                    {
                        MainActivity.RunOnUiThread(() => { Log.Info(TAG + DexService.Operation, "Set Write Characteristic failed"); });
                    }

                    BluetoothGattDescriptor descWrite = WriteCharacteristic.GetDescriptor(CLIENT_CHARACTERISTIC_CONFIG);

                    Log.Info(TAG, $"descWrite Permissions => {descWrite.Permissions.ToString()}");



                    descWrite.SetValue(BluetoothGattDescriptor.EnableNotificationValue.ToArray());
                    gatt.WriteDescriptor(descWrite);
                    descWrite.SetValue(BluetoothGattDescriptor.EnableIndicationValue.ToArray());
                    gatt.WriteDescriptor(descWrite);
                    DexService.Connected = true;
                    DexService.LogMessage2("Device Connected", false);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }
            }