From 699e842fe3d5d1efb2df01ba582d11b1d7e902cf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 10:16:15 +0000 Subject: [PATCH 1/2] feat: add autoconnect min RSSI setting and auto-connect logic Agent-Logs-Url: https://github.com/duhow/ftms-bridge/sessions/ccc0548a-6240-4577-bc16-134c2514146b Co-authored-by: duhow <1145001+duhow@users.noreply.github.com> --- .../net/duhowpi/ftmsbridge/AppSettings.kt | 19 ++++++++ .../net/duhowpi/ftmsbridge/MainActivity.kt | 45 +++++++++++++++++++ app/src/main/res/menu/menu_main.xml | 5 +++ app/src/main/res/values-ca/strings.xml | 5 +++ app/src/main/res/values-es/strings.xml | 5 +++ app/src/main/res/values/strings.xml | 5 +++ .../metadata/android/en-US/changelogs/5.txt | 2 + 7 files changed, 86 insertions(+) create mode 100644 app/src/main/java/net/duhowpi/ftmsbridge/AppSettings.kt diff --git a/app/src/main/java/net/duhowpi/ftmsbridge/AppSettings.kt b/app/src/main/java/net/duhowpi/ftmsbridge/AppSettings.kt new file mode 100644 index 0000000..6414e07 --- /dev/null +++ b/app/src/main/java/net/duhowpi/ftmsbridge/AppSettings.kt @@ -0,0 +1,19 @@ +package net.duhowpi.ftmsbridge + +import android.content.Context +import android.content.SharedPreferences + +class AppSettings(context: Context) { + private val prefs: SharedPreferences = + context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + + var autoconnectMinRssi: Int + get() = prefs.getInt(KEY_AUTOCONNECT_MIN_RSSI, DEFAULT_AUTOCONNECT_MIN_RSSI) + set(value) { prefs.edit().putInt(KEY_AUTOCONNECT_MIN_RSSI, value).apply() } + + companion object { + private const val PREFS_NAME = "app_settings" + private const val KEY_AUTOCONNECT_MIN_RSSI = "autoconnect_min_rssi" + const val DEFAULT_AUTOCONNECT_MIN_RSSI = -40 + } +} diff --git a/app/src/main/java/net/duhowpi/ftmsbridge/MainActivity.kt b/app/src/main/java/net/duhowpi/ftmsbridge/MainActivity.kt index f99298d..0a745fb 100644 --- a/app/src/main/java/net/duhowpi/ftmsbridge/MainActivity.kt +++ b/app/src/main/java/net/duhowpi/ftmsbridge/MainActivity.kt @@ -17,6 +17,7 @@ import android.view.Menu import android.view.MenuItem import android.view.View import android.widget.Button +import android.widget.EditText import android.widget.SeekBar import android.widget.ScrollView import android.widget.TextView @@ -65,6 +66,7 @@ class MainActivity : AppCompatActivity() { private lateinit var hrDebugLogger: BtDebugLogger private lateinit var db: AppDatabase private lateinit var scanAdapter: ScanResultAdapter + private lateinit var appSettings: AppSettings private var ftmsConnectionManager: BleConnectionManager? = null private var hrConnectionManager: BleConnectionManager? = null @@ -228,6 +230,7 @@ class MainActivity : AppCompatActivity() { hrDebugLogger = BtDebugLogger(BuildConfig.DEBUG, this) bleScanner = BleScanner(this) stateMachine = SessionStateMachine(binding, this) + appSettings = AppSettings(this) createDebugSampleDataIfNeeded() @@ -249,6 +252,7 @@ class MainActivity : AppCompatActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.action_history -> { startActivity(Intent(this, WorkoutHistoryActivity::class.java)); true } + R.id.action_settings -> { showSettingsDialog(); true } R.id.action_debug -> { showDebugDialog(); true } R.id.action_about -> { showAboutDialog(); true } else -> super.onOptionsItemSelected(item) @@ -263,6 +267,31 @@ class MainActivity : AppCompatActivity() { .show() } + private fun showSettingsDialog() { + val input = android.widget.EditText(this).apply { + inputType = android.text.InputType.TYPE_CLASS_NUMBER or + android.text.InputType.TYPE_NUMBER_FLAG_SIGNED + setText(appSettings.autoconnectMinRssi.toString()) + hint = AppSettings.DEFAULT_AUTOCONNECT_MIN_RSSI.toString() + } + AlertDialog.Builder(this) + .setTitle(getString(R.string.settings)) + .setMessage(getString(R.string.settings_autoconnect_min_rssi)) + .setView(input) + .setPositiveButton(android.R.string.ok) { _, _ -> + val text = input.text.toString() + val value = text.toIntOrNull() + if (value == null || value >= 0) { + Toast.makeText(this, getString(R.string.settings_invalid_rssi), Toast.LENGTH_LONG).show() + } else { + appSettings.autoconnectMinRssi = value + } + } + .setNegativeButton(android.R.string.cancel, null) + .show() + } + + private fun setupScanList() { scanAdapter = ScanResultAdapter( onConnect = { info -> onDeviceConnectTapped(info) }, @@ -544,6 +573,22 @@ class MainActivity : AppCompatActivity() { ) debugLogger.logMessage("Discovered: $name (${device.address}) FTMS=$isFtms HR=$isHr RSSI=${result.rssi}") } + + // Auto-connect: if this is an FTMS device with strong enough signal and + // no FTMS device is already connected or connecting. + if (isFtms && result.rssi >= appSettings.autoconnectMinRssi) { + runOnUiThread { + if (ftmsConnectionManager?.isConnected != true + && stateMachine.state is SessionState.Idle + && dummyTreadmill == null && dummyBike == null + ) { + val info = scanResultsMap[device.address] ?: return@runOnUiThread + knownDevicesMap[device.address] = info + debugLogger.logMessage("Auto-connecting to $name (${device.address}) RSSI=${result.rssi}") + connectFtmsDevice(device) + } + } + } } override fun onScanFailed(errorCode: Int) { diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml index e321928..0eea74a 100644 --- a/app/src/main/res/menu/menu_main.xml +++ b/app/src/main/res/menu/menu_main.xml @@ -8,6 +8,11 @@ android:title="@string/history" app:showAsAction="always" /> + + Cadència (RPM) Nivell de resistència Control de bici + + + Ajustos + RSSI mín. de connexió automàtica (dBm) + Valor de RSSI no vàlid. Introdueix un nombre negatiu (p. ex. -40). diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 82d725a..96809dc 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -137,4 +137,9 @@ Cadencia (RPM) Nivel de resistencia Control de bici + + + Ajustes + RSSI mín. de conexión automática (dBm) + Valor de RSSI no válido. Introduce un número negativo (p. ej. -40). diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ab33bd8..0aa4855 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -110,6 +110,11 @@ Recent BT Events Log Files + + Settings + Auto-connect min. RSSI (dBm) + Invalid RSSI value. Enter a negative number (e.g. -40). + About About FTMS Bridge diff --git a/fastlane/metadata/android/en-US/changelogs/5.txt b/fastlane/metadata/android/en-US/changelogs/5.txt index 34e6ea1..f3cd47b 100644 --- a/fastlane/metadata/android/en-US/changelogs/5.txt +++ b/fastlane/metadata/android/en-US/changelogs/5.txt @@ -1 +1,3 @@ Add user-facing changes for the next release here. +- Added auto-connect to FTMS devices: the app automatically connects to the nearest FTMS machine when its signal strength meets the configured minimum RSSI threshold. +- Added Settings option in the menu to configure the auto-connect minimum RSSI (default: -40 dBm). From a369efdb82c346ece160687a5c109eb9bb8727c1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 10:17:03 +0000 Subject: [PATCH 2/2] fix: use imported EditText name in showSettingsDialog Agent-Logs-Url: https://github.com/duhow/ftms-bridge/sessions/ccc0548a-6240-4577-bc16-134c2514146b Co-authored-by: duhow <1145001+duhow@users.noreply.github.com> --- app/src/main/java/net/duhowpi/ftmsbridge/MainActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/duhowpi/ftmsbridge/MainActivity.kt b/app/src/main/java/net/duhowpi/ftmsbridge/MainActivity.kt index 0a745fb..843ee74 100644 --- a/app/src/main/java/net/duhowpi/ftmsbridge/MainActivity.kt +++ b/app/src/main/java/net/duhowpi/ftmsbridge/MainActivity.kt @@ -268,7 +268,7 @@ class MainActivity : AppCompatActivity() { } private fun showSettingsDialog() { - val input = android.widget.EditText(this).apply { + val input = EditText(this).apply { inputType = android.text.InputType.TYPE_CLASS_NUMBER or android.text.InputType.TYPE_NUMBER_FLAG_SIGNED setText(appSettings.autoconnectMinRssi.toString())