diff --git a/internal/ble/control/control.go b/internal/ble/control/control.go index f46d58c..8bab185 100644 --- a/internal/ble/control/control.go +++ b/internal/ble/control/control.go @@ -371,6 +371,8 @@ func (bc *BleControl) ExecuteCommand(car *vehicle.Vehicle, command *commands.Com // Wrap ctx with connectionCtx ctx, cancel := context.WithCancel(ctx) defer cancel() + + // Create a single goroutine to handle both context cancellations go func() { select { case <-connectionCtx.Done(): @@ -383,9 +385,13 @@ func (bc *BleControl) ExecuteCommand(car *vehicle.Vehicle, command *commands.Com if i > 0 { log.Warn(lastErr) log.Info(fmt.Sprintf("retrying in %d seconds", sleep/time.Second)) + select { case <-time.After(sleep): case <-ctx.Done(): + if connectionCtx.Err() != nil { + return command, ctx.Err(), ctx + } return nil, ctx.Err(), ctx } sleep *= 2 @@ -393,20 +399,21 @@ func (bc *BleControl) ExecuteCommand(car *vehicle.Vehicle, command *commands.Com retry, err := command.Send(ctx, car) if err == nil { - //Successful log.Info("successfully executed", "command", command.Command, "body", command.Body) return nil, nil, ctx - } else if !retry { + } + + if !retry { return nil, nil, ctx - } else { - //closed pipe - if strings.Contains(err.Error(), "closed pipe") { - //connection lost, returning the command so it can be executed again - return command, err, ctx - } - lastErr = err } + + if strings.Contains(err.Error(), "closed pipe") { + return command, err, ctx + } + + lastErr = err } + log.Error("canceled", "command", command.Command, "body", command.Body, "err", lastErr) return nil, lastErr, ctx } diff --git a/internal/tesla/commands/commands.go b/internal/tesla/commands/commands.go index 53d3d78..ce0a41f 100644 --- a/internal/tesla/commands/commands.go +++ b/internal/tesla/commands/commands.go @@ -166,7 +166,7 @@ func (command *Command) Send(ctx context.Context, car *vehicle.Vehicle) (shouldR log.Debugf("get: %s", endpoint) category, err := GetCategory(endpoint) if err != nil { - return false, fmt.Errorf("unrecognized state category charge") + return false, err } data, err := car.GetState(ctx, category) if err != nil {