Fix group monitoring: per-group 15s idle timeout, drop priority lock

This commit is contained in:
ua1zbe
2026-08-18 15:42:52 +03:00
parent b0bf837a92
commit e53186ea52
3 changed files with 33 additions and 24 deletions

View File

@@ -77,9 +77,13 @@ class MainActivity : Activity(), SvxService.Listener {
private var connected = false private var connected = false
private var monitoring = false private var monitoring = false
private var connectedSettings: ConnectionSettings? = null private var connectedSettings: ConnectionSettings? = null
private var priorityActive = false
private var settings: ConnectionSettings = ConnectionSettings("", 5300, "", "", 11) private var settings: ConnectionSettings = ConnectionSettings("", 5300, "", "", 11)
// Динамический мониторинг: если на группе нет голоса 15 секунд,
// возвращаемся к мониторингу всех групп (базовая группа).
private val MONITOR_IDLE_MS = 15_000L
private var monitorIdleTask: Runnable? = null
private var svc: SvxService? = null private var svc: SvxService? = null
private val svcConn = object : ServiceConnection { private val svcConn = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName, binder: IBinder) { override fun onServiceConnected(name: ComponentName, binder: IBinder) {
@@ -259,7 +263,6 @@ class MainActivity : Activity(), SvxService.Listener {
if (prev != settings && connectedSettings != null) { if (prev != settings && connectedSettings != null) {
if (settings.host.isBlank() || settings.callsign.isBlank()) { if (settings.host.isBlank() || settings.callsign.isBlank()) {
monitoring = false monitoring = false
priorityActive = false
updateMonitorButton() updateMonitorButton()
updatePttEnabled() updatePttEnabled()
svc?.disconnect() svc?.disconnect()
@@ -397,20 +400,13 @@ class MainActivity : Activity(), SvxService.Listener {
while (talkLog.size > TALK_LOG_MAX) { while (talkLog.size > TALK_LOG_MAX) {
talkLog.removeFirst() talkLog.removeFirst()
} }
val priority = monitoring && settings.groups.firstOrNull() == tg // Мониторинг: переключаемся на группу, где началась передача,
if (priority) { // и даём ей 15 секунд; после тишины вернёмся ко всем группам.
priorityActive = true if (monitoring) {
}
if (priority || !priorityActive) {
svc?.selectGroup(tg) svc?.selectGroup(tg)
lblTalkerTitle.text = when { resetMonitorIdle()
priority -> getString(R.string.talker_mon_priority, callsign, tg) lblTalkerTitle.text = getString(R.string.talker_mon, callsign, tg)
monitoring -> getString(R.string.talker_mon, callsign, tg) lblTalkerTitle.setTextColor(getColor(R.color.text_secondary))
else -> getString(R.string.talker_now, callsign)
}
lblTalkerTitle.setTextColor(
if (priority) getColor(R.color.danger) else getColor(R.color.text_secondary)
)
lblTalker.text = callsign lblTalker.text = callsign
} }
} }
@@ -418,11 +414,6 @@ class MainActivity : Activity(), SvxService.Listener {
override fun onTalkerStop(tg: Long, callsign: String) { override fun onTalkerStop(tg: Long, callsign: String) {
// последний говоривший остаётся на экране // последний говоривший остаётся на экране
mainHandler.post {
if (monitoring && settings.groups.firstOrNull() == tg) {
priorityActive = false
}
}
} }
override fun onNodeJoined(callsign: String, tg: Long?) { override fun onNodeJoined(callsign: String, tg: Long?) {
@@ -484,9 +475,25 @@ class MainActivity : Activity(), SvxService.Listener {
micMeter.setLevel(level) micMeter.setLevel(level)
} else { // SRC_SPEAKER } else { // SRC_SPEAKER
rxMeter.setLevel(level) rxMeter.setLevel(level)
// Голос на текущей группе — откладываем возврат ко всем группам
if (monitoring && connected && level > 0.03f) {
resetMonitorIdle()
} }
} }
} }
}
/** Сбросить таймер молчания: группа жива — продолжаем её слушать. */
private fun resetMonitorIdle() {
monitorIdleTask?.let { mainHandler.removeCallbacks(it) }
val task = Runnable {
if (monitoring && connected) {
svc?.selectGroup(settings.talkGroup)
}
}
monitorIdleTask = task
mainHandler.postDelayed(task, MONITOR_IDLE_MS)
}
override fun onError(detail: String) { override fun onError(detail: String) {
mainHandler.post { mainHandler.post {
@@ -537,7 +544,6 @@ class MainActivity : Activity(), SvxService.Listener {
showToast(R.string.monitor_off) showToast(R.string.monitor_off)
} }
monitoring = enabling monitoring = enabling
priorityActive = false
updateMonitorButton() updateMonitorButton()
updatePttEnabled() updatePttEnabled()
if (connected) { if (connected) {
@@ -578,7 +584,6 @@ class MainActivity : Activity(), SvxService.Listener {
Prefs.setActiveProfile(this, which) Prefs.setActiveProfile(this, which)
settings = Prefs.load(this) settings = Prefs.load(this)
monitoring = false monitoring = false
priorityActive = false
updateMonitorButton() updateMonitorButton()
updatePttEnabled() updatePttEnabled()
refreshUi() refreshUi()
@@ -615,6 +620,8 @@ class MainActivity : Activity(), SvxService.Listener {
svc?.selectGroup(tg) svc?.selectGroup(tg)
if (!monitoring) { if (!monitoring) {
svc?.setMonitorTgs(listOf(tg)) svc?.setMonitorTgs(listOf(tg))
} else {
resetMonitorIdle()
} }
} }

View File

@@ -410,7 +410,10 @@ class ReflectorClient(
sendTcp(socket, MsgBuilder.selectTg(s.talkGroup)) sendTcp(socket, MsgBuilder.selectTg(s.talkGroup))
sendTcp(socket, MsgBuilder.tgMonitor(listOf(s.talkGroup))) sendTcp(socket, MsgBuilder.tgMonitor(listOf(s.talkGroup)))
} else { } else {
sendTcp(socket, MsgBuilder.selectTg(monitor.first())) // Мониторинг: сидим на базовой группе и слушаем
// уведомления обо всех группах (аудио идёт только
// с выбранной, поэтому переключение — в MainActivity).
sendTcp(socket, MsgBuilder.selectTg(s.talkGroup))
sendTcp(socket, MsgBuilder.tgMonitor(monitor)) sendTcp(socket, MsgBuilder.tgMonitor(monitor))
} }
openUdp(s) openUdp(s)

View File

@@ -42,7 +42,6 @@
<string name="btn_monitor_on">Мониторинг групп включен (нажмите, чтобы выключить)</string> <string name="btn_monitor_on">Мониторинг групп включен (нажмите, чтобы выключить)</string>
<string name="status_monitoring">Мониторинг: %1$s</string> <string name="status_monitoring">Мониторинг: %1$s</string>
<string name="talker_mon">Говорит: %1$s · TG%2$d</string> <string name="talker_mon">Говорит: %1$s · TG%2$d</string>
<string name="talker_mon_priority">ПРИОРИТЕТ: %1$s · TG%2$d</string>
<string name="status_big_disconnected">DISCONNECTED</string> <string name="status_big_disconnected">DISCONNECTED</string>
<string name="status_big_connected">CONNECTED</string> <string name="status_big_connected">CONNECTED</string>
<string name="status_big_talking">ПЕРЕДАЧА</string> <string name="status_big_talking">ПЕРЕДАЧА</string>