gattc/*: DeviceCharacteristic Read() implementation
Signed-off-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
parent
c27b1cb3be
commit
266de9824a
7 changed files with 110 additions and 5 deletions
2
Makefile
2
Makefile
|
@ -11,6 +11,8 @@ smoketest-tinygo:
|
|||
@md5sum test.hex
|
||||
$(TINYGO) build -o test.uf2 -size=short -target=circuitplay-bluefruit ./examples/circuitplay
|
||||
@md5sum test.hex
|
||||
$(TINYGO) build -o test.uf2 -size=short -target=circuitplay-bluefruit ./examples/discover
|
||||
@md5sum test.hex
|
||||
$(TINYGO) build -o test.hex -size=short -target=pca10040-s132v6 ./examples/heartrate
|
||||
@md5sum test.hex
|
||||
$(TINYGO) build -o test.hex -size=short -target=reelboard-s140v7 ./examples/ledcolor
|
||||
|
|
|
@ -219,6 +219,17 @@ func handleEvent() {
|
|||
}
|
||||
}
|
||||
}
|
||||
case C.BLE_GATTC_EVT_READ_RSP:
|
||||
readEvent := gattcEvent.params.unionfield_read_rsp()
|
||||
if debug {
|
||||
println("evt: read response, data length", readEvent.len)
|
||||
}
|
||||
readingCharacteristic.handle_value.Set(readEvent.handle)
|
||||
readingCharacteristic.offset = readEvent.offset
|
||||
readingCharacteristic.length = readEvent.len
|
||||
|
||||
// copy read event data into Go slice
|
||||
copy(readingCharacteristic.value, (*[255]byte)(unsafe.Pointer(&readEvent.data[0]))[:readEvent.len:readEvent.len])
|
||||
case C.BLE_GATTC_EVT_HVX:
|
||||
hvxEvent := gattcEvent.params.unionfield_hvx()
|
||||
switch hvxEvent._type {
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"tinygo.org/x/bluetooth"
|
||||
)
|
||||
|
||||
|
@ -59,6 +61,9 @@ func main() {
|
|||
srvcs, err := device.DiscoverServices(nil)
|
||||
must("discover services", err)
|
||||
|
||||
// buffer to retrieve characteristic data
|
||||
buf := make([]byte, 255)
|
||||
|
||||
for _, srvc := range srvcs {
|
||||
println("- service", srvc.UUID().String())
|
||||
|
||||
|
@ -68,6 +73,13 @@ func main() {
|
|||
}
|
||||
for _, char := range chars {
|
||||
println("-- characteristic", char.UUID().String())
|
||||
n, err := char.Read(buf)
|
||||
if err != nil {
|
||||
println(" ", err.Error())
|
||||
} else {
|
||||
println(" data bytes", strconv.Itoa(n))
|
||||
println(" value =", string(buf[:n]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -156,12 +156,17 @@ func (pd *peripheralDelegate) DidDiscoverCharacteristics(prph cbgo.Peripheral, s
|
|||
}
|
||||
|
||||
// DidUpdateValueForCharacteristic is called when the characteristic for a Service
|
||||
// for a Peripheral receives a notification with a new value.
|
||||
// for a Peripheral receives a notification with a new value,
|
||||
// or receives a value for a read request.
|
||||
func (pd *peripheralDelegate) DidUpdateValueForCharacteristic(prph cbgo.Peripheral, chr cbgo.Characteristic, err error) {
|
||||
uuid, _ := ParseUUID(chr.UUID().String())
|
||||
if char, ok := pd.d.characteristics[uuid]; ok {
|
||||
if char != nil && char.callback != nil {
|
||||
if err == nil && char.callback != nil {
|
||||
go char.callback(chr.Value())
|
||||
}
|
||||
|
||||
if char.readChan != nil {
|
||||
char.readChan <- err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,9 +92,11 @@ func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacter
|
|||
for _, dchar := range s.service.Characteristics() {
|
||||
uuid, _ := ParseUUID(dchar.UUID().String())
|
||||
char := DeviceCharacteristic{
|
||||
uuidWrapper: uuid,
|
||||
service: s,
|
||||
characteristic: dchar,
|
||||
deviceCharacteristic: &deviceCharacteristic{
|
||||
uuidWrapper: uuid,
|
||||
service: s,
|
||||
characteristic: dchar,
|
||||
},
|
||||
}
|
||||
chars = append(chars, char)
|
||||
s.device.characteristics[char.uuidWrapper] = &char
|
||||
|
@ -108,12 +110,17 @@ func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacter
|
|||
// DeviceCharacteristic is a BLE characteristic on a connected peripheral
|
||||
// device.
|
||||
type DeviceCharacteristic struct {
|
||||
*deviceCharacteristic
|
||||
}
|
||||
|
||||
type deviceCharacteristic struct {
|
||||
uuidWrapper
|
||||
|
||||
service *DeviceService
|
||||
|
||||
characteristic cbgo.Characteristic
|
||||
callback func(buf []byte)
|
||||
readChan chan error
|
||||
}
|
||||
|
||||
// UUID returns the UUID for this DeviceCharacteristic.
|
||||
|
@ -145,3 +152,24 @@ func (c DeviceCharacteristic) EnableNotifications(callback func(buf []byte)) err
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read reads the current characteristic value.
|
||||
func (c *deviceCharacteristic) Read(data []byte) (n int, err error) {
|
||||
c.readChan = make(chan error)
|
||||
c.service.device.prph.ReadCharacteristic(c.characteristic)
|
||||
|
||||
// wait for result
|
||||
select {
|
||||
case err := <-c.readChan:
|
||||
c.readChan = nil
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
case <-time.NewTimer(10 * time.Second).C:
|
||||
c.readChan = nil
|
||||
return 0, errors.New("timeout on Read()")
|
||||
}
|
||||
|
||||
copy(data, c.characteristic.Value())
|
||||
return len(c.characteristic.Value()), nil
|
||||
}
|
||||
|
|
|
@ -231,3 +231,14 @@ func (c DeviceCharacteristic) EnableNotifications(callback func(buf []byte)) err
|
|||
}()
|
||||
return c.characteristic.StartNotify()
|
||||
}
|
||||
|
||||
// Read reads the current characteristic value.
|
||||
func (c *DeviceCharacteristic) Read(data []byte) (int, error) {
|
||||
options := make(map[string]interface{})
|
||||
result, err := c.characteristic.ReadValue(options)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
copy(data, result)
|
||||
return len(result), nil
|
||||
}
|
||||
|
|
36
gattc_sd.go
36
gattc_sd.go
|
@ -414,3 +414,39 @@ func (c DeviceCharacteristic) EnableNotifications(callback func(buf []byte)) err
|
|||
})
|
||||
return makeError(errCode)
|
||||
}
|
||||
|
||||
// A global used to pass information from the event handler back to the
|
||||
// Read function below.
|
||||
var readingCharacteristic struct {
|
||||
handle_value volatile.Register16
|
||||
offset uint16
|
||||
length uint16
|
||||
value []byte
|
||||
}
|
||||
|
||||
// Read reads the current characteristic value up to MTU length.
|
||||
// A future enhancement would be to be able to retrieve a longer
|
||||
// value by making multiple calls.
|
||||
func (c *DeviceCharacteristic) Read(data []byte) (n int, err error) {
|
||||
// global will copy bytes from read operation into data slice
|
||||
readingCharacteristic.value = data
|
||||
|
||||
errCode := C.sd_ble_gattc_read(c.connectionHandle, c.valueHandle, 0)
|
||||
if errCode != 0 {
|
||||
return 0, Error(errCode)
|
||||
}
|
||||
|
||||
// wait for response with data
|
||||
for readingCharacteristic.handle_value.Get() == 0 {
|
||||
arm.Asm("wfe")
|
||||
}
|
||||
|
||||
// how much data was read into buffer
|
||||
n = int(readingCharacteristic.length)
|
||||
|
||||
// prepare for next read
|
||||
readingCharacteristic.handle_value.Set(0)
|
||||
readingCharacteristic.length = 0
|
||||
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue