diff --git a/config/config.go b/config/config.go index 1186f44..b66d185 100644 --- a/config/config.go +++ b/config/config.go @@ -92,6 +92,7 @@ type Config struct { ScanTimeout int // Seconds to scan for BLE devices CacheMaxAge int // Seconds for HTTP Cache-Control header max-age (used for body controller state responses). If set to 0, cache headers are disabled. VehicleDataCacheTime int // Seconds to cache VehicleData endpoint responses in memory. Each endpoint is cached separately per VIN. + ConnectionTimeout int // Seconds to keep the BLE connection open after a command before releasing the adapter to BlueZ. Lower = share adapter sooner; higher = batch follow-up commands. } var AppConfig *Config @@ -145,12 +146,24 @@ func LoadConfig() *Config { } logging.Info("Env:", "vehicleDataCacheTime", vehicleDataCacheTimeInt) + connectionTimeout := os.Getenv("connectionTimeout") + if connectionTimeout == "" { + connectionTimeout = "10" // default value: 10 seconds + } + connectionTimeoutInt, err := strconv.Atoi(connectionTimeout) + if err != nil { + logging.Error("Invalid connectionTimeout value, using default (10)", "error", err) + connectionTimeoutInt = 10 + } + logging.Info("Env:", "connectionTimeout", connectionTimeoutInt) + return &Config{ LogLevel: envLogLevel, HttpListenAddress: addr, CacheMaxAge: cacheMaxAgeInt, ScanTimeout: scanTimeoutInt, VehicleDataCacheTime: vehicleDataCacheTimeInt, + ConnectionTimeout: connectionTimeoutInt, } } diff --git a/internal/ble/control/control.go b/internal/ble/control/control.go index 577bf68..5bd8745 100644 --- a/internal/ble/control/control.go +++ b/internal/ble/control/control.go @@ -75,6 +75,11 @@ func (bc *BleControl) Loop() { logging.Info("Retrying command", "Command", retryCommand.Command, "Body", retryCommand.Body) retryCommand = bc.connectToVehicleAndOperateConnection(retryCommand) } else { + // No pending retry: release the BLE adapter back to BlueZ while idle + // so BlueZ D-Bus and other tools can use it between command sessions. + if err := ble.CloseAdapter(); err != nil { + logging.Debug("Failed to release BLE adapter", "error", err) + } logging.Debug("Waiting for next command ...") // Wait for the next command select { @@ -403,7 +408,7 @@ func (bc *BleControl) TryConnectToVehicle(ctx context.Context, firstCommand *com func (bc *BleControl) operateConnection(car *vehicle.Vehicle, firstCommand *commands.Command) *commands.Command { logging.Debug("Operating connection ...") //defer log.Debug("operating connection done") - connectionCtx, cancel := context.WithTimeout(context.Background(), 29*time.Second) + connectionCtx, cancel := context.WithTimeout(context.Background(), time.Duration(config.AppConfig.ConnectionTimeout)*time.Second) defer cancel() cmd, err, _ := bc.ExecuteCommand(car, firstCommand, connectionCtx)