Skip to content

Commit 7b36b30

Browse files
aykevldeadprogram
authored andcommitted
darwin: fix characteristic scan order
This fixes two bugs actually: 1. The returned characteristics weren't in the order as given in the UUID slice. 2. Duplicate characteristics weren't handled correctly. I tested the first point, and it now works correctly. I did not fully test the second point, it probably doesn't work correctly yet because of the Device.characteristics map that is indexed by UUID. This should be fixed in a separate change.
1 parent 51dff6f commit 7b36b30

File tree

1 file changed

+38
-18
lines changed

1 file changed

+38
-18
lines changed

gattc_darwin.go

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -93,40 +93,60 @@ func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacter
9393
// wait on channel for characteristic discovery
9494
select {
9595
case <-s.device.charsChan:
96-
chars := []DeviceCharacteristic{}
96+
var chars []DeviceCharacteristic
97+
if len(uuids) > 0 {
98+
// The caller wants to get a list of characteristics in a specific
99+
// order.
100+
chars = make([]DeviceCharacteristic, len(uuids))
101+
}
97102
for _, dchar := range s.service.Characteristics() {
98103
dcuuid, _ := ParseUUID(dchar.UUID().String())
99-
// add if in our original list
100104
if len(uuids) > 0 {
101-
found := false
102-
for _, uuid := range uuids {
103-
if dcuuid.String() == uuid.String() {
105+
// The caller wants to get a list of characteristics in a
106+
// specific order. Check whether this is one of those.
107+
for i, uuid := range uuids {
108+
if chars[i] != (DeviceCharacteristic{}) {
109+
// To support multiple identical characteristics, we
110+
// need to ignore the characteristics that are already
111+
// found. See:
112+
// https://github.com/tinygo-org/bluetooth/issues/131
113+
continue
114+
}
115+
if dcuuid == uuid {
104116
// one of the characteristics we're looking for.
105-
found = true
117+
chars[i] = s.makeCharacteristic(dcuuid, dchar)
106118
break
107119
}
108120
}
109-
if !found {
110-
continue
111-
}
121+
} else {
122+
// The caller wants to get all characteristics, in any order.
123+
chars = append(chars, s.makeCharacteristic(dcuuid, dchar))
112124
}
113-
114-
char := DeviceCharacteristic{
115-
deviceCharacteristic: &deviceCharacteristic{
116-
uuidWrapper: dcuuid,
117-
service: s,
118-
characteristic: dchar,
119-
},
125+
}
126+
for _, char := range chars {
127+
if char == (DeviceCharacteristic{}) {
128+
return nil, errors.New("bluetooth: did not find all requested characteristic")
120129
}
121-
chars = append(chars, char)
122-
s.device.characteristics[char.uuidWrapper] = &char
123130
}
124131
return chars, nil
125132
case <-time.NewTimer(10 * time.Second).C:
126133
return nil, errors.New("timeout on DiscoverCharacteristics")
127134
}
128135
}
129136

137+
// Small helper to create a DeviceCharacteristic object.
138+
func (s *DeviceService) makeCharacteristic(uuid UUID, dchar cbgo.Characteristic) DeviceCharacteristic {
139+
char := DeviceCharacteristic{
140+
deviceCharacteristic: &deviceCharacteristic{
141+
uuidWrapper: uuid,
142+
service: s,
143+
characteristic: dchar,
144+
},
145+
}
146+
s.device.characteristics[char.uuidWrapper] = &char
147+
return char
148+
}
149+
130150
// DeviceCharacteristic is a BLE characteristic on a connected peripheral
131151
// device.
132152
type DeviceCharacteristic struct {

0 commit comments

Comments
 (0)