Skip to content

Commit 266de98

Browse files
authored
gattc/*: DeviceCharacteristic Read() implementation
Signed-off-by: deadprogram <[email protected]>
1 parent c27b1cb commit 266de98

File tree

7 files changed

+110
-5
lines changed

7 files changed

+110
-5
lines changed

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ smoketest-tinygo:
1111
@md5sum test.hex
1212
$(TINYGO) build -o test.uf2 -size=short -target=circuitplay-bluefruit ./examples/circuitplay
1313
@md5sum test.hex
14+
$(TINYGO) build -o test.uf2 -size=short -target=circuitplay-bluefruit ./examples/discover
15+
@md5sum test.hex
1416
$(TINYGO) build -o test.hex -size=short -target=pca10040-s132v6 ./examples/heartrate
1517
@md5sum test.hex
1618
$(TINYGO) build -o test.hex -size=short -target=reelboard-s140v7 ./examples/ledcolor

adapter_nrf528xx.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,17 @@ func handleEvent() {
219219
}
220220
}
221221
}
222+
case C.BLE_GATTC_EVT_READ_RSP:
223+
readEvent := gattcEvent.params.unionfield_read_rsp()
224+
if debug {
225+
println("evt: read response, data length", readEvent.len)
226+
}
227+
readingCharacteristic.handle_value.Set(readEvent.handle)
228+
readingCharacteristic.offset = readEvent.offset
229+
readingCharacteristic.length = readEvent.len
230+
231+
// copy read event data into Go slice
232+
copy(readingCharacteristic.value, (*[255]byte)(unsafe.Pointer(&readEvent.data[0]))[:readEvent.len:readEvent.len])
222233
case C.BLE_GATTC_EVT_HVX:
223234
hvxEvent := gattcEvent.params.unionfield_hvx()
224235
switch hvxEvent._type {

examples/discover/main.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package main
1818

1919
import (
20+
"strconv"
21+
2022
"tinygo.org/x/bluetooth"
2123
)
2224

@@ -59,6 +61,9 @@ func main() {
5961
srvcs, err := device.DiscoverServices(nil)
6062
must("discover services", err)
6163

64+
// buffer to retrieve characteristic data
65+
buf := make([]byte, 255)
66+
6267
for _, srvc := range srvcs {
6368
println("- service", srvc.UUID().String())
6469

@@ -68,6 +73,13 @@ func main() {
6873
}
6974
for _, char := range chars {
7075
println("-- characteristic", char.UUID().String())
76+
n, err := char.Read(buf)
77+
if err != nil {
78+
println(" ", err.Error())
79+
} else {
80+
println(" data bytes", strconv.Itoa(n))
81+
println(" value =", string(buf[:n]))
82+
}
7183
}
7284
}
7385

gap_darwin.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,17 @@ func (pd *peripheralDelegate) DidDiscoverCharacteristics(prph cbgo.Peripheral, s
156156
}
157157

158158
// DidUpdateValueForCharacteristic is called when the characteristic for a Service
159-
// for a Peripheral receives a notification with a new value.
159+
// for a Peripheral receives a notification with a new value,
160+
// or receives a value for a read request.
160161
func (pd *peripheralDelegate) DidUpdateValueForCharacteristic(prph cbgo.Peripheral, chr cbgo.Characteristic, err error) {
161162
uuid, _ := ParseUUID(chr.UUID().String())
162163
if char, ok := pd.d.characteristics[uuid]; ok {
163-
if char != nil && char.callback != nil {
164+
if err == nil && char.callback != nil {
164165
go char.callback(chr.Value())
165166
}
167+
168+
if char.readChan != nil {
169+
char.readChan <- err
170+
}
166171
}
167172
}

gattc_darwin.go

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,11 @@ func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacter
9292
for _, dchar := range s.service.Characteristics() {
9393
uuid, _ := ParseUUID(dchar.UUID().String())
9494
char := DeviceCharacteristic{
95-
uuidWrapper: uuid,
96-
service: s,
97-
characteristic: dchar,
95+
deviceCharacteristic: &deviceCharacteristic{
96+
uuidWrapper: uuid,
97+
service: s,
98+
characteristic: dchar,
99+
},
98100
}
99101
chars = append(chars, char)
100102
s.device.characteristics[char.uuidWrapper] = &char
@@ -108,12 +110,17 @@ func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacter
108110
// DeviceCharacteristic is a BLE characteristic on a connected peripheral
109111
// device.
110112
type DeviceCharacteristic struct {
113+
*deviceCharacteristic
114+
}
115+
116+
type deviceCharacteristic struct {
111117
uuidWrapper
112118

113119
service *DeviceService
114120

115121
characteristic cbgo.Characteristic
116122
callback func(buf []byte)
123+
readChan chan error
117124
}
118125

119126
// UUID returns the UUID for this DeviceCharacteristic.
@@ -145,3 +152,24 @@ func (c DeviceCharacteristic) EnableNotifications(callback func(buf []byte)) err
145152

146153
return nil
147154
}
155+
156+
// Read reads the current characteristic value.
157+
func (c *deviceCharacteristic) Read(data []byte) (n int, err error) {
158+
c.readChan = make(chan error)
159+
c.service.device.prph.ReadCharacteristic(c.characteristic)
160+
161+
// wait for result
162+
select {
163+
case err := <-c.readChan:
164+
c.readChan = nil
165+
if err != nil {
166+
return 0, err
167+
}
168+
case <-time.NewTimer(10 * time.Second).C:
169+
c.readChan = nil
170+
return 0, errors.New("timeout on Read()")
171+
}
172+
173+
copy(data, c.characteristic.Value())
174+
return len(c.characteristic.Value()), nil
175+
}

gattc_linux.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,14 @@ func (c DeviceCharacteristic) EnableNotifications(callback func(buf []byte)) err
231231
}()
232232
return c.characteristic.StartNotify()
233233
}
234+
235+
// Read reads the current characteristic value.
236+
func (c *DeviceCharacteristic) Read(data []byte) (int, error) {
237+
options := make(map[string]interface{})
238+
result, err := c.characteristic.ReadValue(options)
239+
if err != nil {
240+
return 0, err
241+
}
242+
copy(data, result)
243+
return len(result), nil
244+
}

gattc_sd.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,3 +414,39 @@ func (c DeviceCharacteristic) EnableNotifications(callback func(buf []byte)) err
414414
})
415415
return makeError(errCode)
416416
}
417+
418+
// A global used to pass information from the event handler back to the
419+
// Read function below.
420+
var readingCharacteristic struct {
421+
handle_value volatile.Register16
422+
offset uint16
423+
length uint16
424+
value []byte
425+
}
426+
427+
// Read reads the current characteristic value up to MTU length.
428+
// A future enhancement would be to be able to retrieve a longer
429+
// value by making multiple calls.
430+
func (c *DeviceCharacteristic) Read(data []byte) (n int, err error) {
431+
// global will copy bytes from read operation into data slice
432+
readingCharacteristic.value = data
433+
434+
errCode := C.sd_ble_gattc_read(c.connectionHandle, c.valueHandle, 0)
435+
if errCode != 0 {
436+
return 0, Error(errCode)
437+
}
438+
439+
// wait for response with data
440+
for readingCharacteristic.handle_value.Get() == 0 {
441+
arm.Asm("wfe")
442+
}
443+
444+
// how much data was read into buffer
445+
n = int(readingCharacteristic.length)
446+
447+
// prepare for next read
448+
readingCharacteristic.handle_value.Set(0)
449+
readingCharacteristic.length = 0
450+
451+
return
452+
}

0 commit comments

Comments
 (0)