9dde7219a6
Fix up the heart rate example so that it conforms to the Heart Rate Service specification: https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=239866 This will let this example work with external clients like exercise equipment and fitness apps. Changes: - Advertise the HR service UUID instead of the HRM characteristic UUID. - Change HRM characteristic to notify only. - HRM payload needs to be two bytes: - 1st byte is flags specifying data type and sensor capabilities: this can be set to zero. - 2nd byte is HR measurement in bpm. Tested on Raspberry Pi with nRF Connect app and exercise bike. Peripheral shows up as HR monitor and data is interpreted correctly.
62 lines
1.5 KiB
Go
62 lines
1.5 KiB
Go
package main
|
|
|
|
import (
|
|
"math/rand"
|
|
"time"
|
|
|
|
"tinygo.org/x/bluetooth"
|
|
)
|
|
|
|
var adapter = bluetooth.DefaultAdapter
|
|
|
|
// TODO: use atomics to access this value.
|
|
var heartRate uint8 = 75 // 75bpm
|
|
|
|
func main() {
|
|
println("starting")
|
|
must("enable BLE stack", adapter.Enable())
|
|
adv := adapter.DefaultAdvertisement()
|
|
must("config adv", adv.Configure(bluetooth.AdvertisementOptions{
|
|
LocalName: "Go HRS",
|
|
ServiceUUIDs: []bluetooth.UUID{bluetooth.New16BitUUID(0x180D)},
|
|
}))
|
|
must("start adv", adv.Start())
|
|
|
|
var heartRateMeasurement bluetooth.Characteristic
|
|
must("add service", adapter.AddService(&bluetooth.Service{
|
|
UUID: bluetooth.New16BitUUID(0x180D), // Heart Rate
|
|
Characteristics: []bluetooth.CharacteristicConfig{
|
|
{
|
|
Handle: &heartRateMeasurement,
|
|
UUID: bluetooth.New16BitUUID(0x2A37), // Heart Rate Measurement
|
|
Value: []byte{0, heartRate},
|
|
Flags: bluetooth.CharacteristicNotifyPermission,
|
|
},
|
|
},
|
|
}))
|
|
|
|
nextBeat := time.Now()
|
|
for {
|
|
nextBeat = nextBeat.Add(time.Minute / time.Duration(heartRate))
|
|
println("tick", time.Now().Format("04:05.000"))
|
|
time.Sleep(nextBeat.Sub(time.Now()))
|
|
|
|
// random variation in heartrate
|
|
heartRate = randomInt(65, 85)
|
|
|
|
// and push the next notification
|
|
heartRateMeasurement.Write([]byte{0, heartRate})
|
|
}
|
|
}
|
|
|
|
func must(action string, err error) {
|
|
if err != nil {
|
|
panic("failed to " + action + ": " + err.Error())
|
|
}
|
|
}
|
|
|
|
// Returns an int >= min, < max
|
|
func randomInt(min, max int) uint8 {
|
|
return uint8(min + rand.Intn(max-min))
|
|
}
|