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())