package main import ( "encoding/binary" "fmt" "math" "os/exec" "time" "github.com/google/gousb" "tinygo.org/x/bluetooth" ) func oldMain() { var vendorId gousb.ID = 0x0fcf var productId gousb.ID = 0x1008 var deviceNumber uint32 = 3001 listenForAntDevice(vendorId, productId, deviceNumber) fmt.Println("channel closed") } var adapter = bluetooth.DefaultAdapter func main() { exec.Command("hciconfig", "hci0", "down").Run() exec.Command("hciconfig", "hci0", "up").Run() must(adapter.Enable()) var powerChar bluetooth.Characteristic must(adapter.AddService(&bluetooth.Service{ UUID: bluetooth.New16BitUUID(0x1818), Characteristics: []bluetooth.CharacteristicConfig{ { UUID: bluetooth.New16BitUUID(0x2A65), // Cycling Power Feature Flags: bluetooth.CharacteristicReadPermission, Value: []byte{0, 0, 0, 0}, }, { UUID: bluetooth.New16BitUUID(0x2A63), // Cycling Power Measurement Flags: bluetooth.CharacteristicNotifyPermission, Handle: &powerChar, }, }, })) must(adapter.DefaultAdvertisement().Configure(bluetooth.AdvertisementOptions{ LocalName: "LinuxAntBtBridge", ServiceUUIDs: []bluetooth.UUID{bluetooth.New16BitUUID(0x1818)}, })) must(adapter.DefaultAdvertisement().Start()) fmt.Println("BLE advertising...") var totalRevs float64 var lastCompletedRev float64 // time in 1/1024s of last completed revolution lastUpdate := time.Now() var elapsedTicks float64 for { now := time.Now() deltaT := now.Sub(lastUpdate).Seconds() lastUpdate = now sec := now.Second() watts := uint16(100 + sec) rpm := float64(50 + sec) totalRevs += rpm / 60.0 * deltaT elapsedTicks += deltaT * 1024.0 completedRevs := math.Floor(totalRevs) // time at which the last completed revolution occurred // = current time - fractional part of revolution * time per revolution fracRev := totalRevs - completedRevs timePerRev := 1024.0 * 60.0 / rpm lastCompletedRev = elapsedTicks - fracRev*timePerRev payload := make([]byte, 8) binary.LittleEndian.PutUint16(payload[0:], 0x20) binary.LittleEndian.PutUint16(payload[2:], watts) binary.LittleEndian.PutUint16(payload[4:], uint16(completedRevs)) binary.LittleEndian.PutUint16(payload[6:], uint16(lastCompletedRev)) powerChar.Write(payload) fmt.Printf("watts: %d rpm: %.0f completedRevs: %.0f lastRevTime: %.0f\n", watts, rpm, completedRevs, lastCompletedRev) time.Sleep(250 * time.Millisecond) } } func must(err error) { if err != nil { panic(err) } }