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"; } }); }); }
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; } }