private string FormatValueByPresentation(IBuffer buffer, GattPresentationFormat format) { // BT_Code: For the purpose of this sample, this function converts only UInt32 and // UTF-8 buffers to readable text. It can be extended to support other formats if your app needs them. byte[] data; CryptographicBuffer.CopyToByteArray(buffer, out data); if (false && format.FormatType == GattPresentationFormatTypes.UInt32 && data.Length >= 4) { return(BitConverter.ToInt32(data, 0).ToString()); } //else if (format.FormatType == GattPresentationFormatTypes.Utf8) else { try { return(Encoding.UTF8.GetString(data)); } catch (ArgumentException) { return("(error: Invalid UTF-8 string)"); } } return(null); }
/// <summary> /// Asynchronous initialization /// </summary> /// <returns>Initialization Task</returns> public override async Task Init() { await CreateServiceProvider(GattServiceUuids.Battery); // Preparing the Battery Level characteristics GattLocalCharacteristicParameters batteryCharacteristicsParameters = PlainReadNotifyParameters; // Set the user descriptions batteryCharacteristicsParameters.UserDescription = "Battery Level percentage remaining"; // Add presentation format - 16-bit integer, with exponent 0, the unit is percentage, defined per Bluetooth SIG with Microsoft as descriptor batteryCharacteristicsParameters.PresentationFormats.Add( GattPresentationFormat.FromParts( Convert.ToByte(PresentationFormats.FormatTypes.Unsigned8BitInteger), PresentationFormats.Exponent, Convert.ToUInt16(PresentationFormats.Units.Percentage), Convert.ToByte(PresentationFormats.NamespaceId.BluetoothSigAssignedNumber), PresentationFormats.Description)); // Create the characteristic for the service GattLocalCharacteristicResult result = await ServiceProvider.Service.CreateCharacteristicAsync( GattCharacteristicUuids.BatteryLevel, batteryCharacteristicsParameters); // Grab the characterist object from the service set it to the BatteryLevel property which is of a specfic Characteristic type GattLocalCharacteristic baseBatteryLevel = null; GattServicesHelper.GetCharacteristicsFromResult(result, ref baseBatteryLevel); if (baseBatteryLevel != null) { BatteryLevel = new Characteristics.BatteryLevelCharacteristic(baseBatteryLevel, this); } }
private async Task CreateCharacteristics(GattServiceProvider gattServiceProvider) { var statusCharacteristicParams = new GattLocalCharacteristicParameters { CharacteristicProperties = GattCharacteristicProperties.Read | GattCharacteristicProperties.Notify, WriteProtectionLevel = GattProtectionLevel.Plain, UserDescription = "Status Characteristic" }; statusCharacteristicParams.PresentationFormats.Add(GattPresentationFormat.FromParts(GattPresentationFormatTypes.Utf8, GattPresentationFormatExponent, GattPresentationFormatUnitless, GattPresentationFormatNamespaceId, GattPresentationFormatDescription)); var statusCharacteristicResult = await gattServiceProvider.Service.CreateCharacteristicAsync( BluetoothConstants.StatusCharacteristicUuid, statusCharacteristicParams); if (statusCharacteristicResult.Error != BluetoothError.Success) { throw new InvalidOperationException($"Failed to create GATT status characteristic with error {statusCharacteristicResult.Error}"); } _statusCharacteristic = statusCharacteristicResult.Characteristic; var commandCharacteristicResult = await gattServiceProvider.Service.CreateCharacteristicAsync( BluetoothConstants.CommandCharacteristicUuid, new GattLocalCharacteristicParameters { CharacteristicProperties = GattCharacteristicProperties.Write | GattCharacteristicProperties.WriteWithoutResponse, WriteProtectionLevel = GattProtectionLevel.Plain, UserDescription = "Command Characteristic" }); if (commandCharacteristicResult.Error != BluetoothError.Success) { throw new InvalidOperationException($"Failed to create GATT command characteristic with error {commandCharacteristicResult.Error}"); } var brightnessCharacteristicResult = await gattServiceProvider.Service.CreateCharacteristicAsync( BluetoothConstants.BrightnessCharacteristicUuid, new GattLocalCharacteristicParameters { CharacteristicProperties = GattCharacteristicProperties.Write | GattCharacteristicProperties.WriteWithoutResponse, WriteProtectionLevel = GattProtectionLevel.Plain, UserDescription = "Brightness Characteristic" }); if (brightnessCharacteristicResult.Error != BluetoothError.Success) { throw new InvalidOperationException($"Failed to create GATT brightness characteristic with error {brightnessCharacteristicResult.Error}"); } _statusCharacteristic.ReadRequested += StatusCharacteristic_ReadRequested; commandCharacteristicResult.Characteristic.WriteRequested += CommandCharacteristic_WriteRequested; brightnessCharacteristicResult.Characteristic.WriteRequested += BrightnessCharacteristic_WriteRequested; }
/// <summary> /// Starts the Heart rate service /// </summary> public override async Task Init() { await CreateServiceProvider(GattServiceUuids.HeartRate); // Preparing the Blood pressure characteristics var heartRateCharacteristics = PlainNotifyParameters; heartRateCharacteristics.UserDescription = "Heart Rates in Beats per Minute"; heartRateCharacteristics.PresentationFormats.Add( GattPresentationFormat.FromParts( Convert.ToByte(PresentationFormats.FormatTypes.Unsigned16BitInteger), PresentationFormats.Exponent, Convert.ToUInt16(PresentationFormats.Units.PeriodBeatsPerMinute), Convert.ToByte(PresentationFormats.NamespaceId.BluetoothSigAssignedNumber), PresentationFormats.Description)); // Create the heart rate characteristic for the service GattLocalCharacteristicResult result = await ServiceProvider.Service.CreateCharacteristicAsync( GattCharacteristicUuids.HeartRateMeasurement, PlainNotifyParameters); // Grab the characterist object from the service set it to the HeartRate property which is of a specfic Characteristic type GattLocalCharacteristic baseHeartRateMeasurement = null; GattServicesHelper.GetCharacteristicsFromResult(result, ref baseHeartRateMeasurement); if (baseHeartRateMeasurement != null) { HeartRateMeasurement = new Characteristics.HeartRateMeasurementCharacteristic(baseHeartRateMeasurement, this); } }
private async void CharacteristicList_SelectedIndexChanged(object sender, EventArgs e) { if (CharacteristicList.Items.Count == 0) { return; } selectedCharacteristic = null; int num = CharacteristicList.SelectedIndex; var attributeInfoDisp = (BluetoothLEAttributeDisplay)CharacteristicCollection[num]; if (attributeInfoDisp == null) { //EnableCharacteristicPanels(GattCharacteristicProperties.None); return; } selectedCharacteristic = attributeInfoDisp.characteristic; if (selectedCharacteristic == null) { strDevName = "No characteristic selected"; printToLog(strDevName); return; } // Get all the child descriptors of a characteristics. Use the cache mode to specify uncached descriptors only // and the new Async functions to get the descriptors of unpaired devices as well. var result = await selectedCharacteristic.GetDescriptorsAsync(BluetoothCacheMode.Uncached); if (result.Status != GattCommunicationStatus.Success) { strDevName = "Descriptor read failure: " + result.Status.ToString(); printToLog(strDevName); } // BT_Code: There's no need to access presentation format unless there's at least one. presentationFormat = null; if (selectedCharacteristic.PresentationFormats.Count > 0) { if (selectedCharacteristic.PresentationFormats.Count.Equals(1)) { // Get the presentation format since there's only one way of presenting it presentationFormat = selectedCharacteristic.PresentationFormats[0]; } else { // It's difficult to figure out how to split up a characteristic and encode its different parts properly. // In this case, we'll just encode the whole thing to a string to make it easy to print out. } } // Enable/disable operations based on the GattCharacteristicProperties. //EnableCharacteristicPanels(selectedCharacteristic.CharacteristicProperties); }
private string FormatValueByPresentation(IBuffer buffer, GattPresentationFormat format) { // BT_Code: For the purpose of this sample, this function converts only UInt32 and // UTF-8 buffers to readable text. It can be extended to support other formats if your app needs them. byte[] data; CryptographicBuffer.CopyToByteArray(buffer, out data); if (format != null) { if (format.FormatType == GattPresentationFormatTypes.UInt32 && data.Length >= 4) { return(BitConverter.ToInt32(data, 0).ToString()); } else if (format.FormatType == GattPresentationFormatTypes.Utf8) { try { return(Encoding.UTF8.GetString(data)); } catch (ArgumentException) { return("(error: Invalid UTF-8 string)"); } } else { // Add support for other format types as needed. return("Unsupported format: " + CryptographicBuffer.EncodeToHexString(buffer)); } } else { // We don't know what format to use. Let's try a well-known profile, or default back to UTF-8. if (selectedCharacteristic.Uuid.Equals(GattCharacteristicUuids.HeartRateMeasurement)) { try { return("Heart Rate: " + ParseHeartRateValue(data).ToString()); } catch (ArgumentException) { return("Heart Rate: (unable to parse)"); } } else { try { return("Unknown format: " + Encoding.UTF8.GetString(data)); } catch (ArgumentException) { return("Unknown format"); } } } }
private async void CharacteristicList_SelectionChanged() { selectedCharacteristic = null; CharacteristicList.SelectedIndex = 0; var attributeInfoDisp = (BluetoothLEAttributeDisplay)CharacteristicList.SelectedItem; if (attributeInfoDisp == null) { EnableCharacteristicPanels(GattCharacteristicProperties.None); return; } selectedCharacteristic = attributeInfoDisp.characteristic; if (selectedCharacteristic == null) { rootPage.NotifyUser("No characteristic selected", NotifyType.ErrorMessage); return; } // Get all the child descriptors of a characteristics. Use the cache mode to specify uncached descriptors only // and the new Async functions to get the descriptors of unpaired devices as well. var result = await selectedCharacteristic.GetDescriptorsAsync(BluetoothCacheMode.Uncached); if (result.Status != GattCommunicationStatus.Success) { rootPage.NotifyUser("Descriptor read failure: " + result.Status.ToString(), NotifyType.ErrorMessage); } // BT_Code: There's no need to access presentation format unless there's at least one. presentationFormat = null; if (selectedCharacteristic.PresentationFormats.Count > 0) { if (selectedCharacteristic.PresentationFormats.Count.Equals(1)) { // Get the presentation format since there's only one way of presenting it presentationFormat = selectedCharacteristic.PresentationFormats[0]; } else { // It's difficult to figure out how to split up a characteristic and encode its different parts properly. // In this case, we'll just encode the whole thing to a string to make it easy to print out. } } // Enable/disable operations based on the GattCharacteristicProperties. EnableCharacteristicPanels(selectedCharacteristic.CharacteristicProperties); ValueChangedSubscribeToggle_Click(); }
/// <summary> /// Converts GenericGattCharacteristic.Value to a string based on the presentation format /// </summary> /// <param name="characteristic"></param> /// <returns>value as a string</returns> public static string ConvertGattCharacteristicValueToString(GenericGattCharacteristic characteristic) { if (characteristic.Value == null) { return(String.Empty); } GattPresentationFormat format = null; if (characteristic.Characteristic.PresentationFormats.Count > 0) { format = characteristic.Characteristic.PresentationFormats[0]; } return(ConvertValueBufferToString(characteristic.Value, format)); }
private async void EnumerationReadDescriptor(GattCharacteristic chara) { var result = await chara.GetDescriptorsAsync(BluetoothCacheMode.Uncached); if (result.Status != GattCommunicationStatus.Success) { NotifyUser("Descripter read failure:" + result.Status.ToString(), NotifyType.ErrorMessage); } presentationFormat = null; if (chara.PresentationFormats.Count > 0) { if (chara.PresentationFormats.Count.Equals(1)) { presentationFormat = chara.PresentationFormats[0]; } } SetVisibility(CharacteristicReadPanel, chara.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Read)); }
// public async void SelectBateryLeveServicesAsync(Guid gd) { foreach (GattCharacteristic c in characteristics) { // string characteristicname = DisplayHelpers.GetCharacteristicName(c); if (c.AttributeHandle == 1296) { BateryLevelCharacteristic = c; break; } } if (BateryLevelCharacteristic == null) { SendConnectionStatusmessageToMCC("BloodPressureMeasurement Characteristic not found."); NotifyStatusMessage?.Invoke("BloodPressureMeasurement Characteristic not found.", 1); return; } var resultch = await BateryLevelCharacteristic.GetDescriptorsAsync(BluetoothCacheMode.Uncached); if (resultch.Status != GattCommunicationStatus.Success) { SendConnectionStatusmessageToMCC("Descriptor read failure: " + resultch.Status.ToString()); NotifyStatusMessage?.Invoke("Descriptor read failure: " + resultch.Status.ToString(), 1); return; } presentationFormat = null; if (BateryLevelCharacteristic.PresentationFormats.Count > 0) { if (BateryLevelCharacteristic.PresentationFormats.Count.Equals(1)) { // Get the presentation format since there's only one way of presenting it presentationFormat = BateryLevelCharacteristic.PresentationFormats[0]; } else { // It's difficult to figure out how to split up a characteristic and encode its different parts properly. // In this case, we'll just encode the whole thing to a string to make it easy to print out. } } SubscribeBateryLevelService(); }
private string FormatValueByPresentation(IBuffer buffer, GattPresentationFormat format) { // BT_Code: For the purpose of this sample, this function converts only UInt32 and // UTF-8 buffers to readable text. It can be extended to support other formats if your app needs them. byte[] data; CryptographicBuffer.CopyToByteArray(buffer, out data); if (format != null) { if (format.FormatType == GattPresentationFormatTypes.UInt32 && data.Length >= 4) { return(BitConverter.ToInt32(data, 0).ToString()); } else if (format.FormatType == GattPresentationFormatTypes.Utf8) { try { return(Encoding.UTF8.GetString(data)); } catch (ArgumentException) { return("(error: Invalid UTF-8 string)"); } } else { // Add support for other format types as needed. return("Unsupported format: " + CryptographicBuffer.EncodeToHexString(buffer)); } } else if (data != null) { try { return("Unknown format: " + Encoding.UTF8.GetString(data)); } catch (ArgumentException ex) { return("Unknown format1" + ex.Message); } } return("Empty data received"); }
private void CharacteristicList_SelectionChanged() { ClearSelectedCharacteristic(); var attributeInfoDisp = (BluetoothLEAttributeDisplay)CharacteristicList.SelectedItem; if (attributeInfoDisp == null) { EnableCharacteristicPanels(GattCharacteristicProperties.None); return; } selectedCharacteristic = attributeInfoDisp.characteristic; isValueChangedHandlerRegistered = false; // BT_Code: There's no need to get presentation format unless there's at least one descriptor. presentationFormat = null; var descriptors = selectedCharacteristic.GetAllDescriptors(); if (descriptors.Count > 0) { if (selectedCharacteristic.PresentationFormats.Count > 1) { // It's difficult to figure out how to split up a characteristic and encode its different parts propertly. // In this case, we'll just encode the whole thing to a string to make it easy to print out. } else if (selectedCharacteristic.PresentationFormats.Count == 1) { // Get the presentation format since there's only one way of presenting it presentationFormat = selectedCharacteristic.PresentationFormats[0]; } } // Enable/disable operations based on the GattCharacteristicProperties. EnableCharacteristicPanels(selectedCharacteristic.CharacteristicProperties); }
private string FormatValueByPresentation(IBuffer buffer, GattPresentationFormat format) { // BT_Code: For the purpose of this sample, this function converts only UInt32 and // UTF-8 buffers to readable text. It can be extended to support other formats if your app needs them. byte[] data; CryptographicBuffer.CopyToByteArray(buffer, out data); if (data != null) { // We don't know what format to use. Let's try some well-known profiles, or default back to UTF-8. if (selectedCharacteristic.Uuid.Equals(GattCharacteristicUuids.HeartRateMeasurement)) { try { return("Heart Rate:\t" + ParseHeartRateValue(data)); //.ToString(); } catch (ArgumentException) { return("Heart Rate: (unable to parse)"); } } else if (selectedCharacteristic.Uuid.Equals(GattCharacteristicUuids.BatteryLevel)) { try { // battery level is encoded as a percentage value in the first byte return("Battery Level: " + data[0].ToString() + "%"); } catch (ArgumentException) { return("Battery Level: (unable to parse)"); } } // This is our custom calc service Result UUID. Format it like an Int else if (selectedCharacteristic.Uuid.Equals(Constants.ResultCharacteristicUuid)) { return(BitConverter.ToInt32(data, 0).ToString()); } // No guarantees on if a characteristic is registered for notifications. else if (registeredCharacteristic != null) { // This is our custom calc service Result UUID. Format it like an Int if (registeredCharacteristic.Uuid.Equals(Constants.ResultCharacteristicUuid)) { return(BitConverter.ToInt32(data, 0).ToString()); } } else { try { return("Unknown format: " + Encoding.UTF8.GetString(data)); } catch (ArgumentException) { return("Unknown format"); } } } else { return("Empty data received"); } return("Unknown format"); }
/// <summary> /// Uses the relevant Service/Characteristic UUIDs to initialize, hook up event handlers and start a service on the local system. /// </summary> /// <returns></returns> private async Task <bool> ServiceProviderInitAsync() { // BT_Code: Initialize and starting a custom GATT Service using GattServiceProvider. GattServiceProviderResult serviceResult = await GattServiceProvider.CreateAsync(Constants.CalcServiceUuid); if (serviceResult.Error == BluetoothError.Success) { serviceProvider = serviceResult.ServiceProvider; } else { rootPage.NotifyUser($"Could not create service provider: {serviceResult.Error}", NotifyType.ErrorMessage); return(false); } GattLocalCharacteristicResult result = await serviceProvider.Service.CreateCharacteristicAsync(Constants.Op1CharacteristicUuid, Constants.gattOperandParameters); if (result.Error == BluetoothError.Success) { op1Characteristic = result.Characteristic; } else { rootPage.NotifyUser($"Could not create operand1 characteristic: {result.Error}", NotifyType.ErrorMessage); return(false); } op1Characteristic.WriteRequested += Op1Characteristic_WriteRequestedAsync; result = await serviceProvider.Service.CreateCharacteristicAsync(Constants.Op2CharacteristicUuid, Constants.gattOperandParameters); if (result.Error == BluetoothError.Success) { op2Characteristic = result.Characteristic; } else { rootPage.NotifyUser($"Could not create operand2 characteristic: {result.Error}", NotifyType.ErrorMessage); return(false); } op2Characteristic.WriteRequested += Op2Characteristic_WriteRequestedAsync; result = await serviceProvider.Service.CreateCharacteristicAsync(Constants.OperatorCharacteristicUuid, Constants.gattOperatorParameters); if (result.Error == BluetoothError.Success) { operatorCharacteristic = result.Characteristic; } else { rootPage.NotifyUser($"Could not create operator characteristic: {result.Error}", NotifyType.ErrorMessage); return(false); } operatorCharacteristic.WriteRequested += OperatorCharacteristic_WriteRequestedAsync; // Add presentation format - 32-bit unsigned integer, with exponent 0, the unit is unitless, with no company description GattPresentationFormat intFormat = GattPresentationFormat.FromParts( GattPresentationFormatTypes.UInt32, PresentationFormats.Exponent, Convert.ToUInt16(PresentationFormats.Units.Unitless), Convert.ToByte(PresentationFormats.NamespaceId.BluetoothSigAssignedNumber), PresentationFormats.Description); Constants.gattResultParameters.PresentationFormats.Add(intFormat); result = await serviceProvider.Service.CreateCharacteristicAsync(Constants.ResultCharacteristicUuid, Constants.gattResultParameters); if (result.Error == BluetoothError.Success) { resultCharacteristic = result.Characteristic; } else { rootPage.NotifyUser($"Could not create result characteristic: {result.Error}", NotifyType.ErrorMessage); return(false); } resultCharacteristic.ReadRequested += ResultCharacteristic_ReadRequestedAsync; resultCharacteristic.SubscribedClientsChanged += ResultCharacteristic_SubscribedClientsChanged; // BT_Code: Indicate if your sever advertises as connectable and discoverable. GattServiceProviderAdvertisingParameters advParameters = new GattServiceProviderAdvertisingParameters { // IsConnectable determines whether a call to publish will attempt to start advertising and // put the service UUID in the ADV packet (best effort) IsConnectable = peripheralSupported, // IsDiscoverable determines whether a remote device can query the local device for support // of this service IsDiscoverable = true }; serviceProvider.AdvertisementStatusChanged += ServiceProvider_AdvertisementStatusChanged; serviceProvider.StartAdvertising(advParameters); return(true); }
private string FormatValueByPresentation(IBuffer buffer, GattPresentationFormat format) { // BT_Code: For the purpose of this sample, this function converts only UInt32 and // UTF-8 buffers to readable text. It can be extended to support other formats if your app needs them. byte[] data; CryptographicBuffer.CopyToByteArray(buffer, out data); if (format != null) { if (format.FormatType == GattPresentationFormatTypes.UInt32 && data.Length >= 4) { return(BitConverter.ToInt32(data, 0).ToString()); } else if (format.FormatType == GattPresentationFormatTypes.Utf8) { try { return(Encoding.UTF8.GetString(data)); } catch (ArgumentException) { return("(error: Invalid UTF-8 string)"); } } else { // Add support for other format types as needed. return("Unsupported format: " + CryptographicBuffer.EncodeToHexString(buffer)); } } else if (data != null) { // We don't know what format to use. Let's try some well-known profiles, or default back to UTF-8. if (selectedCharacteristic.Uuid.Equals(GattCharacteristicUuids.HeartRateMeasurement)) { try { return("Heart Rate: " + ParseHeartRateValue(data).ToString()); } catch (ArgumentException) { return("Heart Rate: (unable to parse)"); } } else if (selectedCharacteristic.Uuid.Equals(GattCharacteristicUuids.BatteryLevel)) { try { // battery level is encoded as a percentage value in the first byte according to // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.battery_level.xml return("Battery Level: " + data[0].ToString() + "%"); } catch (ArgumentException) { return("Battery Level: (unable to parse)"); } } // This is our custom calc service Result UUID. Format it like an Int else if (selectedCharacteristic.Uuid.Equals(Constants.ResultCharacteristicUuid)) { string hexString = CryptographicBuffer.EncodeToHexString(buffer); if (hexString.Length >= 10) { int dataLength = Convert.ToInt16(hexString.Substring(2, 2), 16); String dataPageNumber = hexString.Substring(8, 2); if (dataPageNumber == "19") { int cadence = Convert.ToInt16(hexString.Substring(12, 2), 16); int instPower = Convert.ToInt16((hexString.Substring(21, 1) + hexString.Substring(18, 2)), 16); int accPower = Convert.ToInt16((hexString.Substring(16, 2) + hexString.Substring(14, 2)), 16); RiderData reading = new RiderData(); reading.Iteration = count; count++; reading.Power = instPower; riderData.Add(reading); return("Cadence: " + cadence + " " + "Instantaneous Power: " + instPower + " " + "Accumulated Power: " + accPower); } } } // No guarantees on if a characteristic is registered for notifications. else if (registeredCharacteristic != null) { // This is our custom calc service Result UUID. Format it like an Int if (registeredCharacteristic.Uuid.Equals(Constants.ResultCharacteristicUuid)) { return(BitConverter.ToInt32(data, 0).ToString()); } else { try { return("Hex format: " + CryptographicBuffer.EncodeToHexString(buffer)); } catch (ArgumentException) { return("Unknown format"); } } } } else { return("Empty data received"); } return("Unknown format"); }
public async void SelectBPMeasureServicesAsync(BLEDeviceInfo dv) { try { var service = GTTServicelist[dv.DeviceTypeInfo.ServiceID.ToLower()]; // Ensure we have access to the device. var accessStatus = await service.RequestAccessAsync(); if (accessStatus == DeviceAccessStatus.Allowed) { var result = await service.GetCharacteristicsAsync(BluetoothCacheMode.Uncached); if (result.Status == GattCommunicationStatus.Success) { characteristics = result.Characteristics; } else { SendConnectionStatusmessageToMCC("Error accessing service " + result.Status.ToString()); NotifyStatusMessage?.Invoke("Error accessing service " + result.Status.ToString(), 1); return; } } else { SendConnectionStatusmessageToMCC("Error accessing service " + accessStatus.ToString()); NotifyStatusMessage?.Invoke("Error accessing service " + accessStatus.ToString(), 1); return; } } catch (Exception ex) { SendConnectionStatusmessageToMCC("Exception " + ex.Message); NotifyStatusMessage?.Invoke("Exception " + ex.Message, 2); return; } //BloodPressureMeasurement foreach (GattCharacteristic c in characteristics) { string characteristicname = DisplayHelpers.GetCharacteristicName(c); if ((string.Compare(characteristicname, MainPage.TestresultModel.BPCharacteristicName, true) == 0)) { BloodPressureMeasurementCharacteristic = c; break; } } if (BloodPressureMeasurementCharacteristic == null) { SendConnectionStatusmessageToMCC("BloodPressureMeasurement Characteristic not found."); NotifyStatusMessage?.Invoke("BloodPressureMeasurement Characteristic not found.", 1); return; } // BloodPressureMeasurementCharacteristic = selectedCharacteristic; var resultch = await BloodPressureMeasurementCharacteristic.GetDescriptorsAsync(BluetoothCacheMode.Uncached); if (resultch.Status != GattCommunicationStatus.Success) { SendConnectionStatusmessageToMCC("Descriptor read failure: " + resultch.Status.ToString()); NotifyStatusMessage?.Invoke("Descriptor read failure: " + resultch.Status.ToString(), 1); return; } presentationFormat = null; if (BloodPressureMeasurementCharacteristic.PresentationFormats.Count > 0) { if (BloodPressureMeasurementCharacteristic.PresentationFormats.Count.Equals(1)) { // Get the presentation format since there's only one way of presenting it presentationFormat = BloodPressureMeasurementCharacteristic.PresentationFormats[0]; } else { // It's difficult to figure out how to split up a characteristic and encode its different parts properly. // In this case, we'll just encode the whole thing to a string to make it easy to print out. } } SubscribeBPMeasureService(); }
/// <summary> /// Converts GenericGattCharacteristic.Value to a string based on the presentation format /// </summary> /// <param name="value">value to convert</param> /// <param name="format">presentation format to use</param> /// <returns>value as string</returns> public static string ConvertValueBufferToString(IBuffer value, GattPresentationFormat format = null) { // no format, return bytes if (format == null) { return(GattConvert.ToHexString(value)); } // Bool if (format.FormatType == GattPresentationFormatTypes.Boolean) { // Previous implementation was incorrect. Need to implement in GattHelper. throw new NotImplementedException(); } else if (format.FormatType == GattPresentationFormatTypes.Bit2 || format.FormatType == GattPresentationFormatTypes.Nibble) { // 2bit or nibble - no exponent // Previous implementation was incorrect. Need to implement in GattHelper. return(GattConvert.ToHexString(value)); } else if (format.FormatType == GattPresentationFormatTypes.UInt8 || format.FormatType == GattPresentationFormatTypes.UInt12 || format.FormatType == GattPresentationFormatTypes.UInt16) { // Previous implementation was incorrect. Need to implement in GattHelper. return(GattConvert.ToHexString(value)); } else if (format.FormatType == GattPresentationFormatTypes.UInt24 || format.FormatType == GattPresentationFormatTypes.UInt32) { // Previous implementation was incorrect. Need to implement in GattHelper. return(GattConvert.ToHexString(value)); } else if (format.FormatType == GattPresentationFormatTypes.UInt48 || format.FormatType == GattPresentationFormatTypes.UInt64) { // Previous implementation was incorrect. Need to implement in GattHelper. return(GattConvert.ToHexString(value)); } else if (format.FormatType == GattPresentationFormatTypes.SInt8 || format.FormatType == GattPresentationFormatTypes.SInt12 || format.FormatType == GattPresentationFormatTypes.SInt16) { // Previous implementation was incorrect. Need to implement in GattHelper. return(GattConvert.ToHexString(value)); } else if (format.FormatType == GattPresentationFormatTypes.SInt24 || format.FormatType == GattPresentationFormatTypes.SInt32) { return(GattConvert.ToInt32(value).ToString()); } else if (format.FormatType == GattPresentationFormatTypes.Utf8) { return(GattConvert.ToUTF8String(value)); } else if (format.FormatType == GattPresentationFormatTypes.Utf16) { return(GattConvert.ToUTF16String(value)); } else { // format.FormatType == GattPresentationFormatTypes.UInt128 || // format.FormatType == GattPresentationFormatTypes.SInt128 || // format.FormatType == GattPresentationFormatTypes.DUInt16 || // format.FormatType == GattPresentationFormatTypes.SInt64 || // format.FormatType == GattPresentationFormatTypes.Struct || // format.FormatType == GattPresentationFormatTypes.Float || // format.FormatType == GattPresentationFormatTypes.Float32 || // format.FormatType == GattPresentationFormatTypes.Float64 return(GattConvert.ToHexString(value)); } }
/// <summary> /// Asynchronous initialization /// </summary> /// <returns>Initialization Task</returns> public override async Task Init() { var serviceData = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, }; ServiceData = WindowsRuntimeBuffer.Create(serviceData, 0, serviceData.Length, serviceData.Length); await CreateServiceProvider(MSFTServiceUuid); GattLocalCharacteristicResult result = null; // Prepare the Read Characteristic GattLocalCharacteristicParameters readParam = PlainReadParameter; readParam.UserDescription = "Microsoft Read characteristic"; // Add presentation format - 16-bit integer, with exponent 0, the unit is percentage, defined per Bluetooth SIG with Microsoft as descriptor readParam.PresentationFormats.Add( GattPresentationFormat.FromParts( Convert.ToByte(PresentationFormats.FormatTypes.Signed32BitInteger), PresentationFormats.Exponent, Convert.ToUInt16(PresentationFormats.Units.Unitless), Convert.ToByte(PresentationFormats.NamespaceId.BluetoothSigAssignedNumber), PresentationFormats.Description)); GattLocalCharacteristic baseReadChar = null; result = await ServiceProvider.Service.CreateCharacteristicAsync(MSFTReadChar, readParam); GattServicesHelper.GetCharacteristicsFromResult(result, ref baseReadChar); if (baseReadChar != null) { ReadCharacteristic = new Characteristics.MicrosoftReadCharacteristic(baseReadChar, this); } result = null; // Prepare the Write Characteristic GattLocalCharacteristicParameters writeParam = PlainWriteOrWriteWithoutRespondsParameter; writeParam.UserDescription = "Microsoft Write characteristic"; // Add presentation format - 16-bit integer, with exponent 0, the unit is percentage, defined per Bluetooth SIG with Microsoft as descriptor writeParam.PresentationFormats.Add( GattPresentationFormat.FromParts( Convert.ToByte(PresentationFormats.FormatTypes.UTF8String), PresentationFormats.Exponent, Convert.ToUInt16(PresentationFormats.Units.Unitless), Convert.ToByte(PresentationFormats.NamespaceId.BluetoothSigAssignedNumber), PresentationFormats.Description)); GattLocalCharacteristic baseWriteChar = null; result = await ServiceProvider.Service.CreateCharacteristicAsync(MSFTWriteChar, writeParam); GattServicesHelper.GetCharacteristicsFromResult(result, ref baseWriteChar); if (baseWriteChar != null) { WriteCharacteristic = new Characteristics.MicrosoftWriteCharacteristic(baseWriteChar, this); } result = null; // Prepare the Notify Characteristic GattLocalCharacteristicParameters notifyParam = PlainReadNotifyParameters; notifyParam.UserDescription = "Microsoft Notify characteristic"; // Add presentation format - string, the unit is percentage, defined per Bluetooth SIG with Microsoft as descriptor notifyParam.PresentationFormats.Add( GattPresentationFormat.FromParts( Convert.ToByte(PresentationFormats.FormatTypes.UTF8String), PresentationFormats.Exponent, Convert.ToUInt16(PresentationFormats.Units.Unitless), Convert.ToByte(PresentationFormats.NamespaceId.BluetoothSigAssignedNumber), PresentationFormats.Description)); GattLocalCharacteristic baseNotifyChar = null; result = await ServiceProvider.Service.CreateCharacteristicAsync(MSFTNotifyChar, notifyParam); GattServicesHelper.GetCharacteristicsFromResult(result, ref baseNotifyChar); if (baseNotifyChar != null) { NotifyCharacteristic = new Characteristics.MicrosoftNotifyCharacteristic(baseNotifyChar, this); } result = null; // Prepare the Indicate Characteristic GattLocalCharacteristicParameters indicateParam = new GattLocalCharacteristicParameters { CharacteristicProperties = GattCharacteristicProperties.Read | GattCharacteristicProperties.Indicate, WriteProtectionLevel = GattProtectionLevel.Plain, ReadProtectionLevel = GattProtectionLevel.Plain }; indicateParam.UserDescription = "Microsoft Indicate characteristic"; // Add presentation format - 16-bit integer, with exponent 0, the unit is percentage, defined per Bluetooth SIG with Microsoft as descriptor indicateParam.PresentationFormats.Add( GattPresentationFormat.FromParts( Convert.ToByte(PresentationFormats.FormatTypes.UTF8String), PresentationFormats.Exponent, Convert.ToUInt16(PresentationFormats.Units.Unitless), Convert.ToByte(PresentationFormats.NamespaceId.BluetoothSigAssignedNumber), PresentationFormats.Description)); GattLocalCharacteristic baseIndicateChar = null; result = await ServiceProvider.Service.CreateCharacteristicAsync(MSFTIndicateChar, indicateParam); GattServicesHelper.GetCharacteristicsFromResult(result, ref baseIndicateChar); if (baseIndicateChar != null) { IndicateCharacteristic = new Characteristics.MicrosoftNotifyCharacteristic(baseIndicateChar, this); } result = null; // Prepare the Read Long Characteristic GattLocalCharacteristicParameters longParam = new GattLocalCharacteristicParameters { CharacteristicProperties = GattCharacteristicProperties.Read, WriteProtectionLevel = GattProtectionLevel.Plain, ReadProtectionLevel = GattProtectionLevel.Plain }; longParam.UserDescription = "Microsoft Read Long characteristic"; // Add presentation format - 16-bit integer, with exponent 0, the unit is percentage, defined per Bluetooth SIG with Microsoft as descriptor longParam.PresentationFormats.Add( GattPresentationFormat.FromParts( Convert.ToByte(PresentationFormats.FormatTypes.OpaqueStructure), PresentationFormats.Exponent, Convert.ToUInt16(PresentationFormats.Units.Unitless), Convert.ToByte(PresentationFormats.NamespaceId.BluetoothSigAssignedNumber), PresentationFormats.Description)); GattLocalCharacteristic baseLongReadChar = null; result = await ServiceProvider.Service.CreateCharacteristicAsync(MSFTLongChar, longParam); GattServicesHelper.GetCharacteristicsFromResult(result, ref baseLongReadChar); if (baseLongReadChar != null) { ReadLongCharacteristic = new Characteristics.MicrosoftReadLongCharacteristic(baseLongReadChar, this); } result = null; }
private string FormatValueByPresentation(IBuffer buffer, GattPresentationFormat format) { // BT_Code: For the purpose of this sample, this function converts only UInt32 and // UTF-8 buffers to readable text. It can be extended to support other formats if your app needs them. byte[] data; CryptographicBuffer.CopyToByteArray(buffer, out data); if (format != null) { if (format.FormatType == GattPresentationFormatTypes.UInt32 && data.Length >= 4) { return BitConverter.ToInt32(data, 0).ToString(); } else if (format.FormatType == GattPresentationFormatTypes.Utf8) { try { return Encoding.UTF8.GetString(data); } catch (ArgumentException) { return "(error: Invalid UTF-8 string)"; } } else { // Add support for other format types as needed. return "Unsupported format: " + CryptographicBuffer.EncodeToHexString(buffer); } } else { // We don't know what format to use. Let's try a well-known profile, or default back to UTF-8. if (selectedCharacteristic.Uuid.Equals(GattCharacteristicUuids.HeartRateMeasurement)) { try { return "Heart Rate: " + ParseHeartRateValue(data).ToString(); } catch (ArgumentException) { return "Heart Rate: (unable to parse)"; } } else { try { return "Unknown format: " + Encoding.UTF8.GetString(data); } catch (ArgumentException) { return "Unknown format"; } } } }
/// <summary> /// Sets the value of this characteristic based on the display type /// </summary> private void SetValue() { if (data == null) { Value = "NULL"; return; } GattPresentationFormat format = null; if (Characteristic.PresentationFormats.Count > 0) { format = Characteristic.PresentationFormats[0]; } // Determine what to set our DisplayType to if (format == null && DisplayType == DisplayTypes.NotSet) { if (Name == "DeviceName") { // All devices have DeviceName so this is a special case. DisplayType = DisplayTypes.UTF8; } else { string buffer = string.Empty; bool isString = true; try { buffer = GattConvert.ToUTF8String(rawData); } catch (Exception) { isString = false; } if (isString == true) { // if buffer is only 1 char or 2 char with 0 at end then let's assume it's hex if (buffer.Length == 1) { isString = false; } else if (buffer.Length == 2 && buffer[1] == 0) { isString = false; } else { foreach (char b in buffer) { // if within the reasonable range of used characters and not null, let's assume it's a UTF8 string by default, else hex if ((b < ' ' || b > '~') && b != 0) { isString = false; break; } } } } if (isString) { DisplayType = DisplayTypes.UTF8; } else { // By default, display as Hex DisplayType = DisplayTypes.Hex; } } } else if (format != null && DisplayType == DisplayTypes.NotSet) { if (format.FormatType == GattPresentationFormatTypes.Boolean || format.FormatType == GattPresentationFormatTypes.Bit2 || format.FormatType == GattPresentationFormatTypes.Nibble || format.FormatType == GattPresentationFormatTypes.UInt8 || format.FormatType == GattPresentationFormatTypes.UInt12 || format.FormatType == GattPresentationFormatTypes.UInt16 || format.FormatType == GattPresentationFormatTypes.UInt24 || format.FormatType == GattPresentationFormatTypes.UInt32 || format.FormatType == GattPresentationFormatTypes.UInt48 || format.FormatType == GattPresentationFormatTypes.UInt64 || format.FormatType == GattPresentationFormatTypes.SInt8 || format.FormatType == GattPresentationFormatTypes.SInt12 || format.FormatType == GattPresentationFormatTypes.SInt16 || format.FormatType == GattPresentationFormatTypes.SInt24 || format.FormatType == GattPresentationFormatTypes.SInt32) { DisplayType = DisplayTypes.Decimal; } else if (format.FormatType == GattPresentationFormatTypes.Utf8) { DisplayType = DisplayTypes.UTF8; } else if (format.FormatType == GattPresentationFormatTypes.Utf16) { DisplayType = DisplayTypes.UTF16; } else if (format.FormatType == GattPresentationFormatTypes.UInt128 || format.FormatType == GattPresentationFormatTypes.SInt128 || format.FormatType == GattPresentationFormatTypes.DUInt16 || format.FormatType == GattPresentationFormatTypes.SInt64 || format.FormatType == GattPresentationFormatTypes.Struct || format.FormatType == GattPresentationFormatTypes.Float || format.FormatType == GattPresentationFormatTypes.Float32 || format.FormatType == GattPresentationFormatTypes.Float64) { DisplayType = DisplayTypes.Unsupported; } else { DisplayType = DisplayTypes.Unsupported; } } // Decode the value into the right display type if (DisplayType == DisplayTypes.Hex || DisplayType == DisplayTypes.Unsupported) { try { Value = GattConvert.ToHexString(rawData); } catch (Exception) { Value = "Error: Invalid hex value"; } } else if (DisplayType == DisplayTypes.Decimal) { try { Value = GattConvert.ToInt64(rawData).ToString(); } catch (Exception) { Value = "Error: Invalid Int64 Value"; } } else if (DisplayType == DisplayTypes.UTF8) { try { Value = GattConvert.ToUTF8String(rawData); } catch (Exception) { Value = "Error: Invalid UTF8 String"; } } else if (DisplayType == DisplayTypes.UTF16) { try { Value = GattConvert.ToUTF16String(rawData); } catch (Exception) { Value = "Error: Invalid UTF16 String"; } } }
private string FormatValueByPresentation(IBuffer buffer, GattPresentationFormat format) { // BT_Code: For the purpose of this sample, this function converts only UInt32 and // UTF-8 buffers to readable text. It can be extended to support other formats if your app needs them. //JGW ################################################################################################## byte[] data; CryptographicBuffer.CopyToByteArray(buffer, out data); if (data == null) { //to nothing } if (data != null) { try { char dataChar = (char)data[0]; //double dataDouble = Char.GetNumericValue(dataChar); double dataDouble = (double)dataChar; Debug.WriteLine("got input"); //dataDouble.ToString() if (dataDouble >= 0 && dataDouble <= 100) //NOTE this presume we're working with a 0-10 range of data { if (dataDouble > 18) { Debug.WriteLine("trigger now"); TimedKeyboardManager.newestTimeSesorAboveThreshold = TimedKeyboardManager.globalStopwatch.ElapsedMilliseconds; //uncomment this line to return input injecion } return(dataDouble.ToString()); } } catch { } } if (format != null) { if (format.FormatType == GattPresentationFormatTypes.UInt32 && data.Length >= 4) { Int32 XyzMagReceived = BitConverter.ToInt32(data, 0); if (XyzMagReceived > 40) { //StrikeUp(); //this function called to send keyboard strikes. May need to modify timing and key release } return(BitConverter.ToInt32(data, 0).ToString()); } else if (format.FormatType == GattPresentationFormatTypes.Utf8) { try { return(Encoding.UTF8.GetString(data)); } catch (ArgumentException) { return("(error: Invalid UTF-8 string)"); } } else { // Add support for other format types as needed. return("Unsupported format: " + CryptographicBuffer.EncodeToHexString(buffer)); } } else { return("Empty data received"); } return("Unknown"); }
/// <summary> /// Asynchronous initialization /// </summary> /// <returns>Initialization Task</returns> public override async Task Init() { await CreateServiceProvider(GattServiceUuids.BloodPressure); // Preparing the Blood pressure characteristics var bloodPressureCharacteristics = PlainIndicateParameters; bloodPressureCharacteristics.UserDescription = "Blood Pressure in mm Hg"; bloodPressureCharacteristics.PresentationFormats.Add( GattPresentationFormat.FromParts( Convert.ToByte(PresentationFormats.FormatTypes.OpaqueStructure), PresentationFormats.Exponent, Convert.ToUInt16(PresentationFormats.Units.PressureMilliMetreofmercury), Convert.ToByte(PresentationFormats.NamespaceId.BluetoothSigAssignedNumber), PresentationFormats.Description)); // Create the blood pressure measurement characteristic for the service GattLocalCharacteristicResult result = await ServiceProvider.Service.CreateCharacteristicAsync( GattCharacteristicUuids.BloodPressureMeasurement, bloodPressureCharacteristics); // Grab the characterist object from the service GattLocalCharacteristic baseBloodPressureMeasurement = null; GattServicesHelper.GetCharacteristicsFromResult(result, ref baseBloodPressureMeasurement); if (baseBloodPressureMeasurement != null) { BloodPressureMeasurement = new Characteristics.BloodPressureMeasurementCharacteristic(baseBloodPressureMeasurement, this); } result = null; // Preparing the Blood pressure feature characteristics var bloodPressureFeatureCharacteristics = PlainReadParameter; bloodPressureFeatureCharacteristics.UserDescription = "The Blood Pressure Feature characteristic is used to describe the supported features of the Blood Pressure Sensor."; bloodPressureFeatureCharacteristics.PresentationFormats.Add( GattPresentationFormat.FromParts( Convert.ToByte(PresentationFormats.FormatTypes.Unsigned16BitInteger), PresentationFormats.Exponent, Convert.ToUInt16(PresentationFormats.Units.Unitless), Convert.ToByte(PresentationFormats.NamespaceId.BluetoothSigAssignedNumber), PresentationFormats.Description)); // Create the blood pressure measurement characteristic for the service result = await ServiceProvider.Service.CreateCharacteristicAsync( GattCharacteristicUuids.BloodPressureFeature, bloodPressureFeatureCharacteristics); // Grab the characterist object from the service GattLocalCharacteristic baseBloodPressureFeature = null; GattServicesHelper.GetCharacteristicsFromResult(result, ref baseBloodPressureFeature); if (baseBloodPressureFeature != null) { BloodPressureFeature = new Characteristics.BloodPressureFeatureCharacteristic(baseBloodPressureFeature, this); } }
async void SelectService(BLEDeviceInfo dev) { try { var service = GTTServicelist[dev.DeviceTypeInfo.ServiceID.ToString().ToLower()]; // Ensure we have access to the device. var accessStatus = await service.RequestAccessAsync(); if (accessStatus == DeviceAccessStatus.Allowed) { var result = await service.GetCharacteristicsAsync(BluetoothCacheMode.Uncached); if (result.Status == GattCommunicationStatus.Success) { characteristics = result.Characteristics; } else { MainPage.mainPage.commChannel.SendMessageToMCC(string.Format(CommunicationCommands.PUSLEOXIMETERCONNECTIONMSG, "Error accessing service " + result.Status.ToString())); MainPage.TestresultModel.NotifyStatusMessage?.Invoke("Error accessing service " + result.Status.ToString(), 1); return; } } else { MainPage.mainPage.commChannel.SendMessageToMCC(string.Format(CommunicationCommands.PUSLEOXIMETERCONNECTIONMSG, "Error accessing service " + accessStatus.ToString())); MainPage.TestresultModel.NotifyStatusMessage?.Invoke("Error accessing service " + accessStatus.ToString(), 1); return; } } catch (Exception ex) { MainPage.mainPage.commChannel.SendMessageToMCC(string.Format(CommunicationCommands.PUSLEOXIMETERCONNECTIONMSG, "Exception " + ex.Message)); MainPage.TestresultModel.NotifyStatusMessage?.Invoke("Exception " + ex.Message, 2); return; } foreach (GattCharacteristic c in characteristics) { string characteristicname = DisplayHelpers.GetCharacteristicName(c); if (c.AttributeHandle.ToString().Equals(dev.DeviceTypeInfo.CharacteristicAttributeid)) //MainPage.TestresultModel.OximeterHandleid) { oxymeterCharacteristic = c; break; } } if (oxymeterCharacteristic == null) { MainPage.mainPage.commChannel.SendMessageToMCC(string.Format(CommunicationCommands.PUSLEOXIMETERCONNECTIONMSG, "OxyMeter Characteristic not found.")); MainPage.TestresultModel.NotifyStatusMessage?.Invoke("OxyMeter Characteristic not found.", 1); return; } // BloodPressureMeasurementCharacteristic = selectedCharacteristic; var resultch = await oxymeterCharacteristic.GetDescriptorsAsync(BluetoothCacheMode.Uncached); if (resultch.Status != GattCommunicationStatus.Success) { MainPage.mainPage.commChannel.SendMessageToMCC(string.Format(CommunicationCommands.PUSLEOXIMETERCONNECTIONMSG, "Descriptor read failure: " + resultch.Status.ToString())); MainPage.TestresultModel.NotifyStatusMessage?.Invoke("Descriptor read failure: " + resultch.Status.ToString(), 1); return; } presentationFormat = null; if (oxymeterCharacteristic.PresentationFormats.Count > 0) { if (oxymeterCharacteristic.PresentationFormats.Count.Equals(1)) { // Get the presentation format since there's only one way of presenting it presentationFormat = oxymeterCharacteristic.PresentationFormats[0]; } else { // It's difficult to figure out how to split up a characteristic and encode its different parts properly. // In this case, we'll just encode the whole thing to a string to make it easy to print out. } } SubscribeDeviceReading(); }///
public static object ToValue(this GattReadResult result, GattPresentationFormat presentationFormat) { return(result.ToValue(presentationFormat?.FormatType)); }
private async void Connect() { int i = 0; if (!await ClearBluetoothLEDeviceAsync()) { this.NotifyUser("Error: Unable to reset state, try again.", NotifyType.ErrorMessage); return; } while (bluetoothLeDevice == null || bluetoothLeDevice != null) { try { bluetoothLeDevice = await BluetoothLEDevice.FromIdAsync(this.SelectedBleDeviceId); if (bluetoothLeDevice == null) { continue; } } catch (Exception ex) when(ex.HResult == E_DEVICE_NOT_AVAILABLE) { this.NotifyUser("Bluetooth radio is not on.", NotifyType.ErrorMessage); } if (bluetoothLeDevice != null) { GattDeviceServicesResult resultx = await bluetoothLeDevice.GetGattServicesAsync(BluetoothCacheMode.Uncached); if (resultx.Status == GattCommunicationStatus.Success) { var services = resultx.Services; foreach (var service in services) { //System.Diagnostics.Debug.WriteLine("service: " + service.Uuid.ToString()); if (service.Uuid.ToString() == "0000fff0-0000-1000-8000-00805f9b34fb") { selectedService = service; } } break; } else { this.NotifyUser($"Device unreachable, let's try it for {i} time, again...", NotifyType.ErrorMessage); } if (i < 3) { await Task.Delay(1000); i++; } else { this.NotifyUser("Ok, I give up. Maybe next time...", NotifyType.ErrorMessage); return; } } } var attributeInfoDisp = selectedService; CharacteristicCollection.Clear(); IReadOnlyList <GattCharacteristic> characteristics = null; try { var accessStatus = await attributeInfoDisp.RequestAccessAsync(); if (accessStatus == DeviceAccessStatus.Allowed) { var resulty = await attributeInfoDisp.GetCharacteristicsAsync(BluetoothCacheMode.Uncached); if (resulty.Status == GattCommunicationStatus.Success) { characteristics = resulty.Characteristics; } } else { this.NotifyUser("Error accessing service.", NotifyType.ErrorMessage); characteristics = new List <GattCharacteristic>(); } } catch (Exception ex) { this.NotifyUser("Restricted service. Can't read characteristics: " + ex.Message, NotifyType.ErrorMessage); characteristics = new List <GattCharacteristic>(); } foreach (GattCharacteristic c in characteristics) { if (c.Uuid.ToString() == "0000fff1-0000-1000-8000-00805f9b34fb") { selectedCharacteristic = c; } if (c.Uuid.ToString() == "0000fff2-0000-1000-8000-00805f9b34fb") { writeCharacteristic = c; } //System.Diagnostics.Debug.WriteLine("characteristic: " + c.Uuid.ToString()); } var result = await selectedCharacteristic.GetDescriptorsAsync(BluetoothCacheMode.Uncached); if (result.Status != GattCommunicationStatus.Success) { this.NotifyUser("Descriptor read failure: " + result.Status.ToString(), NotifyType.ErrorMessage); } presentationFormat = null; if (selectedCharacteristic.PresentationFormats.Count > 0) { if (selectedCharacteristic.PresentationFormats.Count.Equals(1)) { presentationFormat = selectedCharacteristic.PresentationFormats[0]; this.NotifyUser(presentationFormat.ToString(), NotifyType.StatusMessage); } } ValueChangedSubscribeToggle(); AddValueChangedHandler(); HoldButton.IsEnabled = true; TareButton.IsEnabled = true; UnitsButton.IsEnabled = true; loaded = 1; return; }
public async Task <bool> ConnectAsync(string id) { try { // BT_Code: BluetoothLEDevice.FromIdAsync must be called from a UI thread because it may prompt for consent. bluetoothLeDevice = await BluetoothLEDevice.FromIdAsync(id); if (bluetoothLeDevice == null) { CSLibrary.DeviceFinder.SearchOnce(); bluetoothLeDevice = await BluetoothLEDevice.FromIdAsync(id); if (bluetoothLeDevice == null) { Debug.WriteLine("Failed to connect to device."); return(false); } } } catch (Exception ex) when(ex.HResult == E_DEVICE_NOT_AVAILABLE) { Debug.WriteLine("Bluetooth radio is not on."); return(false); } GattDeviceServicesResult result = await bluetoothLeDevice.GetGattServicesAsync(BluetoothCacheMode.Uncached); if (result.Status == GattCommunicationStatus.Success) { services = result.Services; Debug.WriteLine(String.Format("Found {0} services", services.Count)); } else { Debug.WriteLine("Device unreachable"); } if (services.Count < 2) { return(false); } foreach (GattDeviceService service in services) { if (service.Uuid == Guid.Parse("00009800-0000-1000-8000-00805f9b34fb")) { characteristics = null; try { // Ensure we have access to the device. var accessStatus = await service.RequestAccessAsync(); if (accessStatus == Windows.Devices.Enumeration.DeviceAccessStatus.Allowed) { // BT_Code: Get all the child characteristics of a service. Use the cache mode to specify uncached characterstics only // and the new Async functions to get the characteristics of unpaired devices as well. var result1 = await service.GetCharacteristicsAsync(BluetoothCacheMode.Uncached); if (result1.Status == GattCommunicationStatus.Success) { characteristics = result1.Characteristics; } else { // On error, act as if there are no characteristics. return(false); } } else { // Not granted access // On error, act as if there are no characteristics. return(false); } } catch (Exception ex) { // On error, act as if there are no characteristics. //characteristics = new List<GattCharacteristic>(); return(false); } } } // Find notification characteristic notificationCharacteristic = null; foreach (GattCharacteristic characteristic in characteristics) { if (characteristic.Uuid == Guid.Parse("00009901-0000-1000-8000-00805f9b34fb")) { notificationCharacteristic = characteristic; break; } } if (notificationCharacteristic == null) { return(false); } // Turn notification on GattCommunicationStatus status = GattCommunicationStatus.Unreachable; var cccdValue = GattClientCharacteristicConfigurationDescriptorValue.None; if (notificationCharacteristic.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Indicate)) { cccdValue = GattClientCharacteristicConfigurationDescriptorValue.Indicate; } else if (notificationCharacteristic.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Notify)) { cccdValue = GattClientCharacteristicConfigurationDescriptorValue.Notify; } // Set notification call back try { // BT_Code: Must write the CCCD in order for server to send indications. // We receive them in the ValueChanged event handler. status = await notificationCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(cccdValue); if (status == GattCommunicationStatus.Success) { notificationCharacteristic.ValueChanged += BLE_Recv; } else { return(false); } } catch (UnauthorizedAccessException ex) { // This usually happens when a device reports that it support indicate, but it actually doesn't. //rootPage.NotifyUser(ex.Message, NotifyType.ErrorMessage); return(false); } // Find write characteristic writeCharacteristic = null; foreach (GattCharacteristic characteristic in characteristics) { if (characteristic.Uuid == Guid.Parse("00009900-0000-1000-8000-00805f9b34fb")) { writeCharacteristic = characteristic; break; } } if (writeCharacteristic == null) { return(false); } presentationFormat = null; if (writeCharacteristic.PresentationFormats.Count > 0) { if (writeCharacteristic.PresentationFormats.Count.Equals(1)) { // Get the presentation format since there's only one way of presenting it presentationFormat = writeCharacteristic.PresentationFormats[0]; } else { // It's difficult to figure out how to split up a characteristic and encode its different parts properly. // In this case, we'll just encode the whole thing to a string to make it easy to print out. return(false); } } // Jump to CS108 Connect _handleSiliconLabIC.GetVersion(); HardwareInit(); return(true); }
private void CharacteristicList_SelectionChanged() { ClearSelectedCharacteristic(); var attributeInfoDisp = (BluetoothLEAttributeDisplay)CharacteristicList.SelectedItem; if (attributeInfoDisp == null) { EnableCharacteristicPanels(GattCharacteristicProperties.None); return; } selectedCharacteristic = attributeInfoDisp.characteristic; isValueChangedHandlerRegistered = false; // BT_Code: There's no need to get presentation format unless there's at least one descriptor. presentationFormat = null; var descriptors = selectedCharacteristic.GetAllDescriptors(); if (descriptors.Count > 0) { if (selectedCharacteristic.PresentationFormats.Count > 1) { // It's difficult to figure out how to split up a characteristic and encode its different parts propertly. // In this case, we'll just encode the whole thing to a string to make it easy to print out. } else { // Get the presentation format since there's only one way of presenting it presentationFormat = selectedCharacteristic.PresentationFormats[0]; } } // Enable/disable operations based on the GattCharacteristicProperties. EnableCharacteristicPanels(selectedCharacteristic.CharacteristicProperties); }
/// <summary> /// Sets the value of this characteristic based on the display type /// </summary> private void SetValue() { if (data == null) { Value = "NULL"; return; } GattPresentationFormat format = null; if (characteristic.PresentationFormats.Count > 0) { format = characteristic.PresentationFormats[0]; } // Determine what to set our DisplayType to if (format == null && DisplayType == DisplayTypes.NotSet) { if (name == "DeviceName") { // All devices have DeviceName so this is a special case. DisplayType = DisplayTypes.UTF8; } else { string buffer = string.Empty; bool isString = true; try { buffer = GattConvert.ToUTF8String(rawData); } catch (Exception) { isString = false; } if (isString == true) { // if buffer is only 1 char or 2 char with 0 at end then let's assume it's hex if (buffer.Length == 1) { isString = false; } else if (buffer.Length == 2 && buffer[1] == 0) { isString = false; } else { foreach (char b in buffer) { // if within the reasonable range of used characters and not null, let's assume it's a UTF8 string by default, else hex if ((b < ' ' || b > '~') && b != 0) { isString = false; break; } } } } if (isString) { DisplayType = DisplayTypes.UTF8; } else { // By default, display as Hex DisplayType = DisplayTypes.Hex; } } } else if (format != null && DisplayType == DisplayTypes.NotSet) { if (format.FormatType == GattPresentationFormatTypes.Boolean || format.FormatType == GattPresentationFormatTypes.Bit2 || format.FormatType == GattPresentationFormatTypes.Nibble || format.FormatType == GattPresentationFormatTypes.UInt8 || format.FormatType == GattPresentationFormatTypes.UInt12 || format.FormatType == GattPresentationFormatTypes.UInt16 || format.FormatType == GattPresentationFormatTypes.UInt24 || format.FormatType == GattPresentationFormatTypes.UInt32 || format.FormatType == GattPresentationFormatTypes.UInt48 || format.FormatType == GattPresentationFormatTypes.UInt64 || format.FormatType == GattPresentationFormatTypes.SInt8 || format.FormatType == GattPresentationFormatTypes.SInt12 || format.FormatType == GattPresentationFormatTypes.SInt16 || format.FormatType == GattPresentationFormatTypes.SInt24 || format.FormatType == GattPresentationFormatTypes.SInt32) { DisplayType = DisplayTypes.Decimal; } else if (format.FormatType == GattPresentationFormatTypes.Utf8) { DisplayType = DisplayTypes.UTF8; } else if (format.FormatType == GattPresentationFormatTypes.Utf16) { DisplayType = DisplayTypes.UTF16; } else if (format.FormatType == GattPresentationFormatTypes.UInt128 || format.FormatType == GattPresentationFormatTypes.SInt128 || format.FormatType == GattPresentationFormatTypes.DUInt16 || format.FormatType == GattPresentationFormatTypes.SInt64 || format.FormatType == GattPresentationFormatTypes.Struct || format.FormatType == GattPresentationFormatTypes.Float || format.FormatType == GattPresentationFormatTypes.Float32 || format.FormatType == GattPresentationFormatTypes.Float64) { DisplayType = DisplayTypes.Unsupported; } else { DisplayType = DisplayTypes.Unsupported; } } // Decode the value into the right display type if (DisplayType == DisplayTypes.Hex || DisplayType == DisplayTypes.Unsupported) { try { Value = GattConvert.ToHexString(rawData); string timestamp = DateTime.UtcNow.ToString("mm:ss.fff", System.Globalization.CultureInfo.InvariantCulture); Debug.WriteLine(timestamp + ":" + Value); } catch (Exception) { Value = "Error: Invalid hex value"; } } else if (DisplayType == DisplayTypes.Decimal) { try { Value = GattConvert.ToInt64(rawData).ToString(); } catch (Exception) { Value = "Error: Invalid Int64 Value"; } } else if (DisplayType == DisplayTypes.UTF8) { try { Value = GattConvert.ToUTF8String(rawData); } catch (Exception) { Value = "Error: Invalid UTF8 String"; } } else if (DisplayType == DisplayTypes.UTF16) { try { Value = GattConvert.ToUTF16String(rawData); } catch (Exception) { Value = "Error: Invalid UTF16 String"; } } else if (DisplayType == DisplayTypes.Stream) { try { //Value = rawData; //Debug.WriteLine(UUID); DataReader dataReader = DataReader.FromBuffer(rawData); byte[] bytes1 = new byte[rawData.Length]; dataReader.ReadBytes(bytes1); string rawString = BitConverter.ToString(bytes1, 0); string timestamp = DateTime.UtcNow.ToString("mm:ss.fff", System.Globalization.CultureInfo.InvariantCulture); Debug.WriteLine(timestamp + ":" + rawString); for (int i = 0; i < bytes1.Length; i = i + 2) { byte[] p = new byte[2]; Array.Copy(bytes1, i, p, 0, 2); // Debug.WriteLine(BitConverter.ToString(p,0)); Array.Reverse(p); int value = BitConverter.ToUInt16(p, 0); qt.Enqueue(value); //Debug.WriteLine(qt.Count); } //PrintValues(qt); // byte[] p1 = new byte[4]; // byte[] p2 = new byte[4]; // byte[] p3 = new byte[4]; // byte[] p4 = new byte[4]; // byte[] p5 = new byte[4]; // byte[] p6 = new byte[4]; // byte[] p7 = new byte[4]; // byte[] p8 = new byte[4]; // byte[] p9 = new byte[4]; // byte[] p10 = new byte[4]; // byte[] rp1 = new byte[4]; // byte[] rp2 = new byte[4]; // byte[] rp3 = new byte[4]; // byte[] rp4 = new byte[4]; // byte[] rp5 = new byte[4]; // byte[] rp6 = new byte[4]; // byte[] rp7 = new byte[4]; // byte[] rp8 = new byte[4]; // byte[] rp9 = new byte[4]; // byte[] rp10 = new byte[4]; // Array.Copy(bytes1, 0, p1, 0, 3); // Array.Copy(bytes1, 3, p2, 0, 3); // Array.Copy(bytes1, 6, p3, 0, 3); // Array.Copy(bytes1, 9, p4, 0, 3); // Array.Copy(bytes1, 12, p5, 0, 3); // Array.Copy(bytes1, 15, p6, 0, 3); // Array.Copy(bytes1, 18, p7, 0, 3); // Array.Copy(bytes1, 21, p8, 0, 3); // Array.Copy(bytes1, 24, p9, 0, 3); // Array.Copy(bytes1, 27, p10, 0, 3); // Array.Reverse(p1); // Array.Reverse(p2); // Array.Reverse(p3); // Array.Reverse(p4); // Array.Reverse(p5); // Array.Reverse(p6); // Array.Reverse(p7); // Array.Reverse(p8); // Array.Reverse(p9); // Array.Reverse(p10); // Array.Copy(p1, rp1, 4); // Array.Copy(p2, rp2, 4); // Array.Copy(p3, rp3, 4); // Array.Copy(p4, rp4, 4); // Array.Copy(p5, rp5, 4); // Array.Copy(p6, rp6, 4); // Array.Copy(p7, rp7, 4); // Array.Copy(p8, rp8, 4); // Array.Copy(p9, rp9, 4); // Array.Copy(p10, rp10, 4); // uint k1 = BitConverter.ToUInt32(rp1, 0); // int m1 = (int)k1; // m1 = (int)(m1 >> 8); // uint k2 = BitConverter.ToUInt32(rp2, 0); // int m2 = (int)k2; // m2 = (int)(m2 >> 8); // uint k3 = BitConverter.ToUInt32(rp3, 0); // int m3 = (int)k3; // m3 = (int)(m3 >> 8); // uint k4 = BitConverter.ToUInt32(rp4, 0); // int m4 = (int)k4; // m4 = (int)(m4 >> 8); // uint k5 = BitConverter.ToUInt32(rp5, 0); // int m5 = (int)k5; // m5 = (int)(m5 >> 8); // uint k6 = BitConverter.ToUInt32(rp6, 0); // int m6 = (int)k6; // m6 = (int)(m6 >> 8); // uint k7 = BitConverter.ToUInt32(rp7, 0); // int m7 = (int)k7; // m7 = (int)(m7 >> 8); // uint k8 = BitConverter.ToUInt32(rp8, 0); // int m8 = (int)k8; // m8 = (int)(m8 >> 8); // uint k9 = BitConverter.ToUInt32(rp9, 0); // int m9 = (int)k9; // m9 = (int)(m9 >> 8); // uint k10 = BitConverter.ToUInt32(rp10, 0); // int m10 = (int)k10; // m10 = (int)(m10 >> 8); /* * Value = GattConvert.ToHexString(rawData); * String v1 = Value.Substring(0, 2); * String v2 = Value.Substring(3, 2); * String v3 = Value.Substring(6, 2); * String v4 = Value.Substring(9, 2); * String v5 = Value.Substring(12, 2); * String v6 = Value.Substring(15, 2); * String v7 = Value.Substring(18, 2); * String v8 = Value.Substring(21, 2); * String v9 = Value.Substring(24, 2); * String v10 = Value.Substring(27, 2); * String v11 = Value.Substring(30, 2); * String v12 = Value.Substring(33, 2); * String v13 = Value.Substring(36, 2); * String v14 = Value.Substring(39, 2); * String v15 = Value.Substring(42, 2); * String v16 = Value.Substring(45, 2); * String v17 = Value.Substring(48, 2); * String v18 = Value.Substring(51, 2); * String v19 = Value.Substring(54, 2); * String v20 = Value.Substring(57, 2); * String v21 = Value.Substring(60, 2); * String v22 = Value.Substring(63, 2); * String v23 = Value.Substring(66, 2); * String v24 = Value.Substring(69, 2); * String v25 = Value.Substring(72, 2); * String v26 = Value.Substring(75, 2); * String v27 = Value.Substring(78, 2); * String v28 = Value.Substring(81, 2); * String v29 = Value.Substring(84, 2); * String v30 = Value.Substring(87, 2); * * * String S1 = String.Concat(v1 + v2 + v3); * String S2 = String.Concat(v4 + v5 + v6); * String S3 = String.Concat(v7 + v8 + v9); * String S4 = String.Concat(v10 + v11 + v12); * String S5 = String.Concat(v13 + v14 + v15); * String S6 = String.Concat(v16 + v17 + v18); * String S7 = String.Concat(v19 + v20 + v21); * String S8 = String.Concat(v22 + v23 + v24); * String S9 = String.Concat(v25 + v26 + v27); * String S10 = String.Concat(v28 + v29 + v30); * * /* * String S1 = String.Concat(v3 + v2 + v1); * String S2 = String.Concat(v6 + v5 + v4); * String S3 = String.Concat(v9 + v8 + v7); * String S4 = String.Concat(v12 + v11 + v10); * String S5 = String.Concat(v15 + v14 + v13); * String S6 = String.Concat(v18 + v17 + v16); * String S7 = String.Concat(v21 + v20 + v19); * String S8 = String.Concat(v24 + v23 + v22); * String S9 = String.Concat(v27 + v26 + v25); * String S10 = String.Concat(v30 + v29 + v28); */ /* * long n1 = Int64.Parse(S1, System.Globalization.NumberStyles.HexNumber); * long n2 = Int64.Parse(S2, System.Globalization.NumberStyles.HexNumber); * long n3 = Int64.Parse(S3, System.Globalization.NumberStyles.HexNumber); * long n4 = Int64.Parse(S4, System.Globalization.NumberStyles.HexNumber); * long n5 = Int64.Parse(S5, System.Globalization.NumberStyles.HexNumber); * long n6 = Int64.Parse(S6, System.Globalization.NumberStyles.HexNumber); * long n7 = Int64.Parse(S7, System.Globalization.NumberStyles.HexNumber); * long n8 = Int64.Parse(S8, System.Globalization.NumberStyles.HexNumber); * long n9 = Int64.Parse(S9, System.Globalization.NumberStyles.HexNumber); * long n10 = Int64.Parse(S10, System.Globalization.NumberStyles.HexNumber); */ // string timestamp = DateTime.UtcNow.ToString("mm:ss.fff", System.Globalization.CultureInfo.InvariantCulture); //Value = (timestamp + ":" + n1.ToString() + "," + n2.ToString() + "," + n3.ToString() + "," + n4.ToString() + "," + n5.ToString() + "," + n6.ToString() + "," + n7.ToString() + "," + n8.ToString() + "," + n9.ToString() + "," + n10.ToString()); // Value = (timestamp + ":" + m1.ToString() + "," + m2.ToString() + "," + m3.ToString() + "," + m4.ToString() + "," + m5.ToString() + "," + m6.ToString() + "," + m7.ToString() + "," + m8.ToString() + "," + m9.ToString() + "," + m10.ToString()); // Debug.WriteLine(Value); /*qt.Enqueue(n1); * qt.Enqueue(n2); * qt.Enqueue(n3); * qt.Enqueue(n4); * qt.Enqueue(n5); * qt.Enqueue(n6); * qt.Enqueue(n7); * qt.Enqueue(n8); * qt.Enqueue(n9); * qt.Enqueue(n10);*/ // qt.Enqueue(m1); // qt.Enqueue(m2); // qt.Enqueue(m3); // qt.Enqueue(m4); // qt.Enqueue(m5); // qt.Enqueue(m6); // qt.Enqueue(m7); // qt.Enqueue(m8); // qt.Enqueue(m9); // qt.Enqueue(m10); //if (SocketAlready) //{ Send("100,200,300"); // Send("\n"); } } catch (Exception) { Value = "Error: Invalid CUSTOM String"; } // try // { // //Value = GattConvert.ToInt64(rawData).ToString(); // Value = GattConvert.ToHexString(rawData); // Debug.WriteLine(Value); // if (SocketAlready) // { // Send(Value + "\n"); // *MOD* Send data as soon as recieved from BLE device // } // // *MOD* optionaly you can add value to queue and send the data at a desired interval using timer // // qt.Enqueue(Value); // *MOD*uncomment this to add value to queue // } // catch (Exception) // { // Value = "Error: Invalid Custom String"; // } } }
private string FormatValueByPresentation(IBuffer buffer, GattPresentationFormat format) { // BT_Code: For the purpose of this sample, this function converts only UInt32 and // UTF-8 buffers to readable text. It can be extended to support other formats if your app needs them. byte[] data; CryptographicBuffer.CopyToByteArray(buffer, out data); if (format != null) { if (format.FormatType == GattPresentationFormatTypes.UInt32 && data.Length >= 4) { return(BitConverter.ToInt32(data, 0).ToString()); } else if (format.FormatType == GattPresentationFormatTypes.Utf8) { try { return(Encoding.UTF8.GetString(data)); } catch (ArgumentException) { return("(error: Invalid UTF-8 string)"); } } else { // Add support for other format types as needed. return("Unsupported format: " + CryptographicBuffer.EncodeToHexString(buffer)); } } else if (data != null) { // We don't know what format to use. Let's try some well-known profiles, or default back to UTF-8. if (selectedCharacteristic.Uuid.Equals(GattCharacteristicUuids.HeartRateMeasurement)) { try { return("Heart Rate: " + ParseHeartRateValue(data).ToString()); } catch (ArgumentException) { return("Heart Rate: (unable to parse)"); } } else if (selectedCharacteristic.Uuid.Equals(GattCharacteristicUuids.BatteryLevel)) { try { // battery level is encoded as a percentage value in the first byte according to // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.battery_level.xml return("Battery Level: " + data[0].ToString() + "%"); } catch (ArgumentException) { return("Battery Level: (unable to parse)"); } } // This is our custom calc service Result UUID. Format it like an Int else if (selectedCharacteristic.Uuid.Equals(Constants.ResultCharacteristicUuid)) { return(BitConverter.ToInt32(data, 0).ToString()); } // No guarantees on if a characteristic is registered for notifications. else if (registeredCharacteristic != null) { // This is our custom calc service Result UUID. Format it like an Int if (registeredCharacteristic.Uuid.Equals(Constants.ResultCharacteristicUuid)) { return(BitConverter.ToInt32(data, 0).ToString()); } } else { try { return("Unknown format: " + Encoding.UTF8.GetString(data)); } catch (ArgumentException) { return("Unknown format"); } } } else { return("Empty data received"); } return(BitConverter.ToString(data).Replace("-", string.Empty)); //return "Unknown format"; }
private string FormatValueByPresentation(IBuffer buffer, GattPresentationFormat format) { byte[] data; CryptographicBuffer.CopyToByteArray(buffer, out data); if (format != null) { if (format.FormatType == GattPresentationFormatTypes.UInt32 && data.Length >= 4) { return(BitConverter.ToInt32(data, 0).ToString()); } else if (format.FormatType == GattPresentationFormatTypes.Utf8) { try { return(Encoding.UTF8.GetString(data)); } catch (ArgumentException) { return("(error: Invalid UTF-8 string)"); } } else { return("Unsupported format: " + CryptographicBuffer.EncodeToHexString(buffer)); } } else if (data != null) { if (selectedCharacteristic.Uuid.Equals(GattCharacteristicUuids.BatteryLevel)) { try { return("Battery Level: " + data[0].ToString() + "%"); } catch (ArgumentException) { return("Battery Level: (unable to parse)"); } } else if (selectedCharacteristic.Uuid.Equals(Constants.ResultCharacteristicUuid)) { return(BitConverter.ToInt32(data, 0).ToString()); } else if (registeredCharacteristic != null) { if (registeredCharacteristic.Uuid.Equals(Constants.ResultCharacteristicUuid)) { return(BitConverter.ToInt32(data, 0).ToString()); } } else { try { return("Unknown format: " + Encoding.UTF8.GetString(data)); } catch (ArgumentException) { return(Encoding.UTF8.GetString(data)); } } } else { return("Empty data received"); } return(Encoding.UTF8.GetString(data)); }