From 3b414253c4854b0e7c32490c380f81d052e99467 Mon Sep 17 00:00:00 2001 From: Alexis Couvreur Date: Mon, 9 Feb 2026 17:53:31 -0500 Subject: [PATCH 1/2] fix: Windows characteristic ordering in DiscoverCharacteristics The characteristics will now appear on the expected order --- gattc_windows.go | 49 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/gattc_windows.go b/gattc_windows.go index 2d8119fc..419be7c1 100644 --- a/gattc_windows.go +++ b/gattc_windows.go @@ -196,6 +196,13 @@ func (s DeviceService) DiscoverCharacteristics(filterUUIDs []UUID) ([]DeviceChar } var characteristics []DeviceCharacteristic + + if len(filterUUIDs) > 0 { + // The caller wants to get a list of characteristics in a specific + // order. + characteristics = make([]DeviceCharacteristic, len(filterUUIDs)) + } + for i := uint32(0); i < characteristicsSize; i++ { c, err := charVector.GetAt(i) if err != nil { @@ -217,33 +224,55 @@ func (s DeviceService) DiscoverCharacteristics(filterUUIDs []UUID) ([]DeviceChar // only include characteristics that are included in the input filter if len(filterUUIDs) > 0 { - found := false for _, uuid := range filterUUIDs { + if characteristics[i] != (DeviceCharacteristic{}) { + // To support multiple identical characteristics, we + // need to ignore the characteristics that are already + // found. See: + // https://github.com/tinygo-org/bluetooth/issues/131 + continue + } if characteristicUUID.String() == uuid.String() { // One of the characteristics we're looking for. - found = true + characteristics[i] = s.makeCharacteristic(characteristicUUID, characteristic, properties) break } } - if !found { - continue - } + } else { + // The caller wants to get all characteristics, in any order. + characteristics = append(characteristics, s.makeCharacteristic(characteristicUUID, characteristic, properties)) } + } - characteristics = append(characteristics, DeviceCharacteristic{ - uuidWrapper: characteristicUUID, + for _, char := range characteristics { + if char == (DeviceCharacteristic{}) { + return nil, errors.New("bluetooth: did not find all requested characteristic") + } + } + + return characteristics, nil +} + +// Small helper to create a DeviceCharacteristic object. +func (s DeviceService) makeCharacteristic(uuid UUID, characteristic *genericattributeprofile.GattCharacteristic, properties genericattributeprofile.GattCharacteristicProperties) DeviceCharacteristic { + char := DeviceCharacteristic{ + deviceCharacteristic: &deviceCharacteristic{ + uuidWrapper: uuid, service: s, characteristic: characteristic, properties: properties, - }) + }, } - - return characteristics, nil + return char } // DeviceCharacteristic is a BLE characteristic on a connected peripheral // device. type DeviceCharacteristic struct { + *deviceCharacteristic +} + +type deviceCharacteristic struct { uuidWrapper characteristic *genericattributeprofile.GattCharacteristic From ede8b6c028e5bdf5b337ecdbab91fcc2e920e7f5 Mon Sep 17 00:00:00 2001 From: Alexis Couvreur Date: Wed, 25 Feb 2026 19:31:09 -0500 Subject: [PATCH 2/2] range over filterUUIDs --- gattc_windows.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/gattc_windows.go b/gattc_windows.go index 419be7c1..f0f69ac8 100644 --- a/gattc_windows.go +++ b/gattc_windows.go @@ -3,6 +3,7 @@ package bluetooth import ( "errors" "fmt" + "slices" "syscall" "unsafe" @@ -224,8 +225,8 @@ func (s DeviceService) DiscoverCharacteristics(filterUUIDs []UUID) ([]DeviceChar // only include characteristics that are included in the input filter if len(filterUUIDs) > 0 { - for _, uuid := range filterUUIDs { - if characteristics[i] != (DeviceCharacteristic{}) { + for j, uuid := range filterUUIDs { + if characteristics[j] != (DeviceCharacteristic{}) { // To support multiple identical characteristics, we // need to ignore the characteristics that are already // found. See: @@ -234,7 +235,7 @@ func (s DeviceService) DiscoverCharacteristics(filterUUIDs []UUID) ([]DeviceChar } if characteristicUUID.String() == uuid.String() { // One of the characteristics we're looking for. - characteristics[i] = s.makeCharacteristic(characteristicUUID, characteristic, properties) + characteristics[j] = s.makeCharacteristic(characteristicUUID, characteristic, properties) break } } @@ -244,10 +245,8 @@ func (s DeviceService) DiscoverCharacteristics(filterUUIDs []UUID) ([]DeviceChar } } - for _, char := range characteristics { - if char == (DeviceCharacteristic{}) { - return nil, errors.New("bluetooth: did not find all requested characteristic") - } + if slices.Contains(characteristics, (DeviceCharacteristic{})) { + return nil, errors.New("bluetooth: did not find all requested characteristic") } return characteristics, nil