private async void Characteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args) { string valuestr = ""; lock (this) { var decode = PreferredFormat ?? NC?.Type ?? DefaultFormat; // default is hex var result = ValueParser.Parse(args.CharacteristicValue, decode); valuestr = result.AsString; } await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, () => { AddString(valuestr); }); }
private async Task DoReadAsync(bool ignoreUnreadableValues) { var props = Characteristic.CharacteristicProperties; bool isReadable = false; var valuestr = ""; if (props.HasFlag(GattCharacteristicProperties.Read)) { try { var vresult = await Characteristic.ReadValueAsync(); if (vresult.Status != GattCommunicationStatus.Success) { valuestr = GetStatusString(vresult.Status, vresult.ProtocolError); } else { var decode = NC?.Type ?? "BYTES|HEX"; // default is hex var result = ValueParser.Parse(vresult.Value, decode); valuestr = result.AsString; } } catch (Exception e) { valuestr = $"Exception: {Characteristic.ToString()} {e.Message}"; } isReadable = true; } else if (props.HasFlag(GattCharacteristicProperties.Indicate)) { valuestr = "Tap the 🅸 to get data indications"; } else if (props.HasFlag(GattCharacteristicProperties.Notify)) { valuestr = "Tap the 🄽 to get data notifications"; } else { valuestr = "Not a readable characteristic"; } if (isReadable || ignoreUnreadableValues) { AddString(valuestr); } }
private async Task DoIncrementWriteTapped(GattWriteOption WriteOption) { var oldValue = uiValueShow.Text; var characteristic = Characteristic; try { if (characteristic.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Read)) { var buffer = await characteristic.ReadValueAsync(); if (buffer.Status == GattCommunicationStatus.Success) { var data = buffer.Value.ToArray(); for (int i = data.Length - 1; i >= 0; i--) { if (data[i] < 0xFF) { data[i]++; break; } else { data[i] = 0; // And carry the one to the next byte. } } var dataBuffer = data.AsBuffer(); var newAsString = ValueParser.ConvertToStringHex(dataBuffer); uiValueShow.Text = newAsString; var status = await Characteristic.WriteValueWithResultAsync(dataBuffer, WriteOption); } } } catch (Exception) { ; //TODO: show exception to user! } }
/// <summary> /// Test ValueToString providing a string of bytes in hex format (e.g. "01 02 03") and the expected string results and the decode commands. /// </summary> /// <param name="commands"></param> /// <param name="value"></param> /// <param name="expected"></param> /// <returns></returns> private static int TestOk(string commands, string value, string expected) { int NError = 0; var valueb = Hex(value); var expectedb = Hex(value); var actualResult = ValueParser.Parse(valueb.AsBuffer(), commands); if (actualResult.Result != ValueParserResult.ResultValues.Ok) { System.Diagnostics.Debug.WriteLine($"ERROR: ValueToStringTest:TestOk ({commands}, {value}) failed to parse at all; expected OK"); NError++; } else { if (actualResult.AsString != expected) { System.Diagnostics.Debug.WriteLine($"ERROR: ValueToStringTest:TestOk ({commands}, {value}) actual is {actualResult.AsString} expected {expected}"); NError++; } } return(NError); }
public async Task InitAsync(GattDeviceService service, GattCharacteristic characteristic, string preferredFormat) { uiPreferredFormat.Text = preferredFormat; string str = null; try { AddData("Service", characteristic.Service.Uuid.ToString()); var reg = BluetoothServiceRegistration.FindRegistration(characteristic.Service.Uuid); if (reg != null) { AddData("RegistrationOwner", reg.RegistrationOwner); } AddData("ID", characteristic.Uuid.ToString()); } catch (Exception e1) { System.Diagnostics.Debug.WriteLine($"Exception: CharacteristicDetailViewer: Adding data {e1.Message}"); } try { str = characteristic.UserDescription; } catch (Exception e2) { System.Diagnostics.Debug.WriteLine($"Exception: CharacteristicDetailViewer: Getting user description {e2.Message}"); } if (!String.IsNullOrWhiteSpace(str)) { AddData("Description", str); } try { str = ""; foreach (var format in characteristic.PresentationFormats) { str = $"{format.Description} type={format.FormatType} namespace={format.Namespace} unit={format.Unit} exponent={format.Exponent}"; AddData("Format", str); } } catch (Exception e) { AddData("Format", $"Exception: {e.Message}"); } str = ""; // Don't bother with descriptors try { var dc = DeviceCharacteristic.Create(characteristic); AddData("Methods", dc.PropertiesAsString); // e.g. Read Write etc. } catch (Exception e) { AddData("Methods", $"Exception: {e.Message}"); } try { AddData("Protection Level", characteristic.ProtectionLevel.ToString()); } catch (Exception e) { AddData("Protection Level", $"Exception: {e.Message}"); } try { if (characteristic.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Read)) { var buffer = await characteristic.ReadValueAsync(); if (buffer.Status == GattCommunicationStatus.Success) { var data = ValueParser.ConvertToStringHex(buffer.Value); AddData("Data", data); } else { AddData("Data", $"Error: {buffer.Status}"); } } } catch (Exception e) { AddData("Data", $"Exception: {e.Message}"); } }
private async Task DisplayBluetooth(NameDevice knownDevice, DeviceInformationWrapper di, BluetoothLEDevice ble) { var jsonFormat = Newtonsoft.Json.Formatting.Indented; var jsonSettings = new Newtonsoft.Json.JsonSerializerSettings() { DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore, ContractResolver = IgnoreEmptyEnumerableResolver.Instance, }; var wireAllDevices = new NameAllBleDevices(); WireDevice = new NameDevice(); WireDevice.Name = di.di.Name; WireDevice.Details += $"Id:{di.di.Id}\nCanPair:{di.di.Pairing.CanPair} IsPaired:{di.di.Pairing.IsPaired}"; wireAllDevices.AllDevices.Add(WireDevice); WireDevice.ClassModifiers = knownDevice.ClassModifiers; WireDevice.ClassName = knownDevice.ClassName; WireDevice.Description = knownDevice.Description; uiRawData.Text = Newtonsoft.Json.JsonConvert.SerializeObject(WireDevice, jsonFormat); string raw = null; if (ble == null) { // Happens if another program is trying to use the device! raw = $"BLE: ERROR: Another app is using this device.\n"; } else { // TODO: remove this code which is only here while I investigate the WESCALE scale #if NEVER_EVER_DEFINED { // WESCALE: no gatt services var services = ble.GattServices; var count = services.Count; var devacc = ble.DeviceAccessInformation; var devaccstatus = devacc.CurrentStatus; foreach (var service in services) { var chars = service.GetAllCharacteristics(); } try { var guid = Guid.Parse("0000fff0-0000-1000-8000-00805f9b34fb"); var request = await ble.RequestAccessAsync(); var allservice = await ble.GetGattServicesForUuidAsync(guid); var servicefff0 = ble.GetGattService(guid); var charsfff0 = servicefff0.GetAllCharacteristics(); var countfff0 = charsfff0.Count; foreach (var ch in charsfff0) { ; } } catch (Exception ex) { ; } } #endif var result = await ble.GetGattServicesAsync(); if (result.Status != GattCommunicationStatus.Success) { raw += GetStatusString(result.Status, result.ProtocolError); } else { var header = new BleDeviceHeaderControl(); await header.InitAsync(ble); int serviceCount = 0; foreach (var service in result.Services) { await header.AddServiceAsync(ble, service); var shouldDisplay = ServiceShouldBeEdited(service); var defaultService = knownDevice.GetService(service.Uuid.ToString("D")); var wireService = new NameService(service, defaultService, serviceCount++); WireDevice.Services.Add(wireService); try { var cresult = await service.GetCharacteristicsAsync(); if (cresult.Status != GattCommunicationStatus.Success) { raw += GetStatusString(cresult.Status, cresult.ProtocolError); } else { var characteristicCount = 0; foreach (var characteristic in cresult.Characteristics) { //The descriptors don't seem to be actually interesting. it's how we read and write. var descriptorStatus = await characteristic.GetDescriptorsAsync(); if (descriptorStatus.Status == GattCommunicationStatus.Success) { foreach (var descriptor in descriptorStatus.Descriptors) { ; } } var defaultCharacteristic = defaultService?.GetChacteristic(characteristic.Uuid.ToString("D")); var wireCharacteristic = new NameCharacteristic(characteristic, defaultCharacteristic, characteristicCount++); wireService.Characteristics.Add(wireCharacteristic); if (wireCharacteristic.Suppress) { continue; // don't show a UI for a supressed characteristic. } // // Here are each of the editor children items // var edit = new BleCharacteristicControl(knownDevice, service, characteristic); uiEditor.Children.Add(edit); var dc = DeviceCharacteristic.Create(characteristic); //NOTE: does any device have a presentation format? foreach (var format in characteristic.PresentationFormats) { raw += $" Fmt: Description:{format.Description} Namespace:{format.Namespace} Type:{format.FormatType} Unit: {format.Unit} Exp:{format.Exponent}\n"; } try { if (wireCharacteristic.IsRead) { var vresult = await characteristic.ReadValueAsync(); if (vresult.Status != GattCommunicationStatus.Success) { raw += GetStatusString(vresult.Status, vresult.ProtocolError); } else { var dt = BluetoothLEStandardServices.GetDisplayInfo(service, characteristic); var hexResults = dt.AsString(vresult.Value); wireCharacteristic.ExampleData.Add(hexResults); // And add as a converted value var NC = BleNames.Get(knownDevice, service, characteristic); var decode = NC?.Type; if (decode != null && !decode.StartsWith("BYTES|HEX")) { var decoded = ValueParser.Parse(vresult.Value, decode); wireCharacteristic.ExampleData.Add(decoded.UserString); } } } } catch (Exception e) { raw += $" Exception reading value: {e.HResult} {e.Message}\n"; } // Update the UI with the latest discovery // Later: or not. The raw data isn't super useful. //uiRawData.Text = Newtonsoft.Json.JsonConvert.SerializeObject(WireDevice, jsonFormat); } } } catch (Exception e) { raw += $" Exception reading characteristic: {e.HResult} {e.Message}\n"; } } } } JsonAsList = Newtonsoft.Json.JsonConvert.SerializeObject(wireAllDevices, jsonFormat, jsonSettings); JsonAsSingle = Newtonsoft.Json.JsonConvert.SerializeObject(WireDevice, jsonFormat, jsonSettings); uiProgress.IsActive = false; uiRawData.Text += raw; return; }
public async Task InitAsync(GattDeviceService service, GattCharacteristic characteristic) { Service = service; Characteristic = characteristic; string str; AddData("Service", characteristic.Service.Uuid.ToString()); AddData("ID", characteristic.Uuid.ToString()); str = characteristic.UserDescription; if (!String.IsNullOrWhiteSpace(str)) { AddData("Description", str); } try { str = ""; foreach (var format in characteristic.PresentationFormats) { str = $"{format.Description} type={format.FormatType} namespace={format.Namespace} unit={format.Unit} exponent={format.Exponent}"; AddData("Format", str); } } catch (Exception e) { AddData("Format", $"Exception: {e.Message}"); } str = ""; // Don't bother with descriptors try { var dc = DeviceCharacteristic.Create(characteristic); AddData("Methods", dc.PropertiesAsString); // e.g. Read Write etc. } catch (Exception e) { AddData("Methods", $"Exception: {e.Message}"); } try { AddData("Protection Level", characteristic.ProtectionLevel.ToString()); } catch (Exception e) { AddData("Protection Level", $"Exception: {e.Message}"); } try { if (characteristic.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Read)) { var buffer = await characteristic.ReadValueAsync(); if (buffer.Status == GattCommunicationStatus.Success) { //NOTE: also get the data as the nice version? var data = ValueParser.ConvertToStringHex(buffer.Value); AddData("Data", data); uiEditBox.Text = data; // NOTE: what if I don't want hex? } else { AddData("Data", $"Error: {buffer.Status}"); } } } catch (Exception e) { AddData("Data", $"Exception: {e.Message}"); } AddButtons(); // e.g. for the Skootbot robot controls }