diff --git a/cmd/bridge/ant.go b/cmd/bridge/ant.go index 62669b5..edc6d8a 100644 --- a/cmd/bridge/ant.go +++ b/cmd/bridge/ant.go @@ -34,7 +34,6 @@ func resetAndWait(drv io.ReadWriter) error { func ListenForTrainer(vendorId uint16, productId uint16, deviceNumber uint32, events chan<- Event) { - defer close(events) drv, err := usb.GetDevice(gousb.ID(vendorId), gousb.ID(productId)) if err != nil { @@ -53,36 +52,47 @@ func ListenForTrainer(vendorId uint16, productId uint16, deviceNumber uint32, logMsg("ant: scan mode started") msgs := make(chan ant.BroadcastMessage, 100) - go device.DumpBroadcastMessages(context.Background(), drv, msgs) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + go func() { + device.DumpBroadcastMessages(ctx, drv, msgs) + logMsg("ant: dump broadcast messages ended") + }() logMsg("ant: listening...") - for msg := range msgs { - if deviceNumber != 0 && msg.DeviceNumber() != deviceNumber { - logPrintf("ant: received msg from ignored device %v\n", msg.DeviceNumber()) - continue - } - //fmt.Printf("raw msg: device type=0x%02x device number=%d content=%x\n", - // msg.DeviceType(), msg.DeviceNumber(), msg.Content()) - - switch msg.DeviceType() { - case ant.DEVICE_TYPE_POWER: - // Check data page first - page := msg[4] & antDataPageMask - if page != antDataPageCyclingPower { + for { + select { + case msg := <-msgs: + if deviceNumber != 0 && msg.DeviceNumber() != deviceNumber { + logPrintf("ant: received msg from ignored device %v\n", msg.DeviceNumber()) continue } - cur := ant.PowerMessage(msg) - logPrintf("ant: %v: power: %dW cadence: %d rpm\n", - msg.DeviceNumber(), cur.InstantaneousPower(), cur.InstantaneousCadence()) - select { - case events <- Event{ - Power: cur.InstantaneousPower(), - Cadence: cur.InstantaneousCadence(), - Now: time.Now(), - }: - default: - logPrintf("ant: dropped event, buffer full\n") + //fmt.Printf("raw msg: device type=0x%02x device number=%d content=%x\n", + // msg.DeviceType(), msg.DeviceNumber(), msg.Content()) + + switch msg.DeviceType() { + case ant.DEVICE_TYPE_POWER: + // Check data page first + page := msg[4] & antDataPageMask + if page != antDataPageCyclingPower { + continue + } + cur := ant.PowerMessage(msg) + logPrintf("ant: %v: power: %dW cadence: %d rpm\n", + msg.DeviceNumber(), cur.InstantaneousPower(), cur.InstantaneousCadence()) + select { + case events <- Event{ + Power: cur.InstantaneousPower(), + Cadence: cur.InstantaneousCadence(), + Now: time.Now(), + }: + default: + logPrintf("ant: dropped event, buffer full\n") + } } + case <-time.After(10 * time.Second): + logMsg("ant: no more messages arrived, restarting") + return } } } diff --git a/cmd/bridge/cli.go b/cmd/bridge/cli.go index 8dc3bd8..4d9e13e 100644 --- a/cmd/bridge/cli.go +++ b/cmd/bridge/cli.go @@ -81,7 +81,11 @@ This allows these trainers to be used with modern devices that don't support ANT } events := make(chan Event, 1) - go ListenForTrainer(uint16(c.vendorID), uint16(c.productID), c.deviceNumber, events) + go func() { + for { + ListenForTrainer(uint16(c.vendorID), uint16(c.productID), c.deviceNumber, events) + } + }() ExposeBluetooth(events) return nil