/// <summary> /// Get Paired or Connected devices. /// </summary> /// <returns></returns> public List <GoPlus> GetBondedDevices() { _devicesFound.Clear(); List <IDevice> devices = _adapter.GetSystemConnectedOrPairedDevices(); List <GoPlus> pgpList = new List <GoPlus>(); foreach (var device in devices) { if (device.Name == Constants.GoPlusName) { var androidDev = (Android.Bluetooth.BluetoothDevice)device.NativeDevice; GoPlus pgp = new GoPlus() { Name = androidDev.Name, BtAddress = androidDev.Address }; _devicesFound.Add(pgp, device); pgpList.Add(pgp); } } if (pgpList.Count == 0) { _notifyManager.ShowShortToast("No paired Pokemon GO Plus found. Please make sure it's connected via Pokemon GO."); } return(pgpList); }
/// <summary> /// Restore the Original PGP Firmware. /// </summary> /// <param name="device"></param> /// <returns></returns> public async Task RestoreDevice(GoPlus device) { _device = device ?? throw new ArgumentNullException("device"); if (_stateManager.State != AppState.Idle) { return; } try { _stateManager.State = AppState.Restoring; await _bleManager.ConnectDevice(device); await _bleManager.NotifyRegister(device, Constants.RestoreCharacteristicStatusUuid); await _bleManager.WriteCharacteristic(device, Constants.RestoreCharacteristicUuid, (byte)0x01); } catch (Exception e) { _notifyManager.ShowDialogInfoBox($"Unable to restore. Error: {e.Message}"); _stateManager.State = AppState.Idle; } }
/// <summary> /// Write to a BLE Characteristic. /// </summary> /// <param name="device"></param> /// <param name="charUuid"></param> /// <param name="value"></param> /// <returns></returns> public async Task WriteCharacteristic(GoPlus device, Guid charUuid, short value, bool noResponse = false) { byte[] b = new byte[2]; b[0] = (byte)value; b[1] = (byte)(((uint)value >> 8) & 0xFF); await WriteCharacteristic(device, charUuid, b, noResponse); }
/// <summary> /// Connect to a Go+ device. /// </summary> /// <param name="device">Go+ to connect.</param> public async Task ConnectDevice(GoPlus device) { if (device == null) { throw new ArgumentNullException("device"); } if (!_devicesFound.ContainsKey(device)) { throw new ArgumentException("This device does not exist in discovered devices"); } // There should only be one connection at a time. foreach (IDevice connectedDevice in _adapter.ConnectedDevices) { _logger.Log("Connected device already exists! Disconnecting.", Category.Info, Priority.None); await _adapter.DisconnectDeviceAsync(connectedDevice); } _charCache.Clear(); _logger.Log("Connecting to Pokemon GO Plus.", Category.Info, Priority.None); // Wait a bit before connecting. await Task.Delay(Constants.DelayMS); for (int i = 0; i < Constants.RetryCount; i++) { try { await _adapter.ConnectToDeviceAsync(_devicesFound[device]); _logger.Log("Successfully connected to Pokemon GO Plus.", Category.Info, Priority.None); return; } catch (Exception e) { if (i < Constants.RetryCount - 1) { _logger.Log($"Error connecting to Pokemon GO Plus: {e.Message}. Trying Again.", Category.Exception, Priority.High); await Task.Delay(Constants.DelayMS); } else { _logger.Log($"Error connecting to Pokemon GO Plus: {e.Message}.", Category.Exception, Priority.High); _notifyManager.ShowShortToast("Unable to connect to Pokemon GO Plus."); } } } _logger.Log($"Unable to Connect to Pokemon GO Plus.", Category.Exception, Priority.High); throw new Exception("Unable to Connect to Pokemon GO Plus"); }
private void _adapter_DeviceDiscovered(object sender, Plugin.BLE.Abstractions.EventArgs.DeviceEventArgs e) { IDevice device = e.Device; var androidDev = (Android.Bluetooth.BluetoothDevice)device.NativeDevice; string name = string.IsNullOrWhiteSpace(androidDev.Name) ? "<No Name>" : androidDev.Name; _logger.Log($"Device discovered. Name: {name} Address: {androidDev.Address}", Category.Debug, Priority.None); foreach (var record in device.AdvertisementRecords) { if (record.Type == AdvertisementRecordType.UuidsComplete128Bit) { Guid guid = Helper.ByteArrayToGuid(record.Data); if (Constants.ExtractorServiceUuid.Equals(guid) || Constants.GoPlusServiceUuuid.Equals(guid) || Constants.SpotaServiceUuid.Equals(guid)) { _logger.Log($"GO Plus Discovered!", Category.Info, Priority.None); GoPlus pgp = new GoPlus() { Name = androidDev.Name, BtAddress = androidDev.Address }; _devicesFound.Add(pgp, device); _aggregator.GetEvent <PrismEvents.GoPlusFoundEvent>().Publish(pgp); } } else if (record.Type == AdvertisementRecordType.UuidsComplete16Bit) { if (string.Compare(Constants.GoPlusName, androidDev.Name) == 0) { if (record.Data != null && record.Data.Length > 1 && record.Data[0] == Constants.SuotaAdvertisementUuid[0] && record.Data[1] == Constants.SuotaAdvertisementUuid[1]) { _logger.Log($"GO Plus SUOTA Discovered!", Category.Info, Priority.None); GoPlus pgp = new GoPlus() { Name = androidDev.Name, BtAddress = androidDev.Address }; _devicesFound.Add(pgp, device); _aggregator.GetEvent <PrismEvents.GoPlusFoundEvent>().Publish(pgp); } } } } }
/// <summary> /// /// </summary> /// <param name="device"></param> /// <param name="charUuid"></param> /// <returns></returns> public async Task NotifyRegister(GoPlus device, Guid charUuid) { if (device == null) { throw new ArgumentNullException("device"); } if (charUuid == null) { throw new ArgumentNullException("charUuid"); } if (!_devicesFound.ContainsKey(device)) { throw new Exception("This device does not exist in discovered devices"); } IDevice pgp = _devicesFound[device]; if (!_adapter.ConnectedDevices.Contains(pgp)) { throw new Exception("This device is not connected"); } ICharacteristic characteristic; // Wait a delay first await Task.Delay(1000); if (_charCache.ContainsKey(charUuid)) { characteristic = _charCache[charUuid]; } else { Guid serviceUuid = Constants.Char2ServiceMap[charUuid]; IService service = await pgp.GetServiceAsync(serviceUuid); characteristic = await service.GetCharacteristicAsync(charUuid); _charCache.Add(charUuid, characteristic); } _registeredNotifyChar.Add(characteristic); characteristic.ValueUpdated += KeyChar_ValueUpdated; await characteristic.StartUpdatesAsync(); }
/// <summary> /// Remove an existing bond. /// </summary> /// <param name="device">Go+ to unbond.</param> public void RemoveBond(GoPlus device) { if (device == null) { throw new ArgumentNullException("device"); } if (!_devicesFound.ContainsKey(device)) { throw new ArgumentException("This device does not exist in discovered devices"); } var androidDev = (Android.Bluetooth.BluetoothDevice)_devicesFound[device].NativeDevice; var mi = androidDev.Class.GetMethod("removeBond", null); mi.Invoke(androidDev, null); }
/// <summary> /// Disconnect from a Go+ device. /// </summary> /// <param name="device">Go+ to disconnect from.</param> public async Task DisconnectDevice(GoPlus device) { if (device == null) { throw new ArgumentNullException("device"); } if (!_devicesFound.ContainsKey(device)) { throw new ArgumentException("This device does not exist in discovered devices"); } await Task.Delay(Constants.DelayMS); // Disconnect the device if connected. if (_adapter.ConnectedDevices.Contains(_devicesFound[device])) { _logger.Log("Disconnecting from Go+ device.", Category.Info, Priority.None); await _adapter.DisconnectDeviceAsync(_devicesFound[device]); } }
/// <summary> /// Get the GO+ key and blob. /// </summary> /// <returns>Async task to await.</returns> public async Task GetDeviceInfo(GoPlus device) { if (device == null) { throw new ArgumentNullException("device"); } if (_stateManager.State != AppState.Idle) { return; } try { _stateManager.State = AppState.Getting; await _bleManager.ConnectDevice(device); byte[] key = await _bleManager.ReadCharacteristic(device, Constants.DeviceKeyCharacteristicUuid); device.DeviceKey = Helper.ByteArrayToString(key); byte[] blob = await _bleManager.ReadCharacteristic(device, Constants.BlobKeyCharacteristicUuid); device.BlobKey = Helper.ByteArrayToString(blob); await _bleManager.DisconnectDevice(device); } catch (Exception e) { _notifyManager.ShowDialogInfoBox($"Unable to get Device Information. Please try again. Error: {e.Message}"); } finally { _stateManager.State = AppState.Idle; } }
/// <summary> /// Read a BLE Characteristic. /// </summary> /// <param name="device"></param> /// <param name="charUuid"></param> /// <param name="value"></param> public async Task <byte[]> ReadCharacteristic(GoPlus device, Guid charUuid) { if (device == null) { throw new ArgumentNullException("device"); } if (charUuid == null) { throw new ArgumentNullException("charUuid"); } if (!_devicesFound.ContainsKey(device)) { throw new Exception("This device does not exist in discovered devices"); } IDevice pgp = _devicesFound[device]; if (!_adapter.ConnectedDevices.Contains(pgp)) { throw new Exception("This device is not connected"); } ICharacteristic characteristic; // Wait a bit before reading. await Task.Delay(Constants.DelayMS); if (_charCache.ContainsKey(charUuid)) { characteristic = _charCache[charUuid]; } else { Guid serviceUuid = Constants.Char2ServiceMap[charUuid]; IService service = await pgp.GetServiceAsync(serviceUuid); characteristic = await service.GetCharacteristicAsync(charUuid); _charCache.Add(charUuid, characteristic); } if (characteristic.CanRead) { for (int i = 0; i < Constants.RetryCount; i++) { try { byte[] result = await characteristic.ReadAsync(); return(result); } catch (Exception e) { if (i < Constants.RetryCount - 1) { _logger.Log($"Error reading characteristic: {e.Message}. Trying again.", Category.Exception, Priority.High); _aggregator.GetEvent <PrismEvents.ProgressUpdateEvent>().Publish(new Progress($"Error reading characteristic: {e.Message}. Trying again.")); await Task.Delay(1000); } } } } else { throw new Exception("Characteristic is not readable"); } throw new Exception("Unable to read characteristic"); }
/// <summary> /// Write to a BLE Characteristic. /// </summary> /// <param name="device"></param> /// <param name="charUuid"></param> /// <param name="value"></param> public async Task WriteCharacteristic(GoPlus device, Guid charUuid, byte[] value, bool noResponse = false) { if (device == null) { throw new ArgumentNullException("device"); } if (charUuid == null) { throw new ArgumentNullException("charUuid"); } if (value == null || value.Length == 0) { throw new ArgumentNullException("value"); } if (!_devicesFound.ContainsKey(device)) { throw new Exception("This device does not exist in discovered devices"); } if (value.Length > Constants.ChunkSize) { throw new ArgumentException($"Length must be less than {Constants.ChunkSize}", "value"); } IDevice pgp = _devicesFound[device]; if (!_adapter.ConnectedDevices.Contains(pgp)) { throw new Exception("This device is not connected"); } // Wait a bit before reading. await Task.Delay(Constants.DelayMS); ICharacteristic characteristic; if (_charCache.ContainsKey(charUuid)) { characteristic = _charCache[charUuid]; } else { Guid serviceUuid = Constants.Char2ServiceMap[charUuid]; IService service = await pgp.GetServiceAsync(serviceUuid); characteristic = await service.GetCharacteristicAsync(charUuid); _charCache.Add(charUuid, characteristic); } if (!characteristic.CanWrite) { throw new Exception("Characteristic is not writable"); } characteristic.WriteType = (noResponse) ? CharacteristicWriteType.WithoutResponse : CharacteristicWriteType.Default; for (int i = 0; i < Constants.RetryCount; i++) { try { bool success = await characteristic.WriteAsync(value); if (success) { return; } else { if (i < Constants.RetryCount - 1) { _aggregator.GetEvent <PrismEvents.ProgressUpdateEvent>().Publish(new Progress($"Write to characteristic unsuccessful, trying again.")); _logger.Log($"Write to characteristic unsuccessful, trying again.", Category.Exception, Priority.High); } } } catch (Exception e) { _logger.Log($"Error writing characteristic: {e.Message}. Trying again.", Category.Exception, Priority.High); _aggregator.GetEvent <PrismEvents.ProgressUpdateEvent>().Publish(new Progress($"Error writing characteristic: {e.Message}. Trying again.")); } await Task.Delay(1000); } throw new Exception("Unable to write to characteristic"); }
/// <summary> /// Write to a BLE Characteristic. /// </summary> /// <param name="device"></param> /// <param name="charUuid"></param> /// <param name="value"></param> /// <returns></returns> public async Task WriteCharacteristic(GoPlus device, Guid charUuid, byte value, bool noResponse = false) { await WriteCharacteristic(device, charUuid, new byte[] { value }, noResponse); }