refactor(settings): remove Traffic Management module config (#5878)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
James Rich
2026-06-20 07:45:13 -05:00
committed by GitHub
parent bf026485d0
commit ea47e01c87
15 changed files with 0 additions and 285 deletions

View File

@@ -1411,23 +1411,6 @@ traceroute_route_towards_dest
traceroute_showing_nodes
track_and_share_locations
track_point
### TRAFFIC ###
traffic_management
traffic_management_config
traffic_management_drop_unknown_enabled
traffic_management_enabled
traffic_management_exhaust_hop_position
traffic_management_exhaust_hop_telemetry
traffic_management_nodeinfo_direct_response
traffic_management_nodeinfo_direct_response_max_hops
traffic_management_position_dedup
traffic_management_position_min_interval
traffic_management_position_precision
traffic_management_rate_limit_enabled
traffic_management_rate_limit_max_packets
traffic_management_rate_limit_window
traffic_management_router_preserve_hops
traffic_management_unknown_packet_threshold
transmit_over_lora
transport_ble
transport_tcp

View File

@@ -103,7 +103,6 @@ open class InstallProfileUseCase constructor(private val radioController: RadioC
lmc.detection_sensor?.let { setModuleConfig(ModuleConfig(detection_sensor = it)) }
lmc.paxcounter?.let { setModuleConfig(ModuleConfig(paxcounter = it)) }
lmc.statusmessage?.let { setModuleConfig(ModuleConfig(statusmessage = it)) }
lmc.traffic_management?.let { setModuleConfig(ModuleConfig(traffic_management = it)) }
lmc.tak?.let { setModuleConfig(ModuleConfig(tak = it)) }
}
}

View File

@@ -42,7 +42,6 @@ import org.meshtastic.proto.ModuleConfig.StatusMessageConfig
import org.meshtastic.proto.ModuleConfig.StoreForwardConfig
import org.meshtastic.proto.ModuleConfig.TAKConfig
import org.meshtastic.proto.ModuleConfig.TelemetryConfig
import org.meshtastic.proto.ModuleConfig.TrafficManagementConfig
import org.meshtastic.proto.User
import kotlin.test.BeforeTest
import kotlin.test.Test
@@ -99,7 +98,6 @@ class InstallProfileUseCaseTest {
detection_sensor = DetectionSensorConfig(),
paxcounter = PaxcounterConfig(),
statusmessage = StatusMessageConfig(),
traffic_management = TrafficManagementConfig(),
tak = TAKConfig(),
),
fixed_position = org.meshtastic.proto.Position(),

View File

@@ -52,9 +52,6 @@ data class Capabilities(val firmwareVersion: String?, internal val forceEnableAl
/** Support for Status Message module. Supported since firmware v2.8.0. */
val supportsStatusMessage = atLeast(V2_8_0)
/** Support for Traffic Management module. Supported since firmware v2.8.0. */
val supportsTrafficManagementConfig = atLeast(V2_8_0)
/** Support for TAK (ATAK) module configuration. Supported since firmware v2.7.19. */
val supportsTakConfig = atLeast(V2_7_19)

View File

@@ -73,12 +73,6 @@ class CapabilitiesTest {
assertTrue(caps("2.8.0").supportsStatusMessage)
}
@Test
fun supportsTrafficManagementConfig_requires_V2_8_0() {
assertFalse(caps("2.7.21").supportsTrafficManagementConfig)
assertTrue(caps("2.8.0").supportsTrafficManagementConfig)
}
@Test
fun supportsTakConfig_requires_V2_7_19() {
assertFalse(caps("2.7.18").supportsTakConfig)
@@ -102,7 +96,6 @@ class CapabilitiesTest {
assertFalse(c.supportsQrCodeSharing)
assertFalse(c.supportsSecondaryChannelLocation)
assertFalse(c.supportsStatusMessage)
assertFalse(c.supportsTrafficManagementConfig)
assertFalse(c.supportsTakConfig)
assertFalse(c.supportsEsp32Ota)
}
@@ -113,7 +106,6 @@ class CapabilitiesTest {
assertTrue(c.canMuteNode)
assertTrue(c.canSendVerifiedContacts)
assertTrue(c.supportsStatusMessage)
assertTrue(c.supportsTrafficManagementConfig)
assertTrue(c.supportsTakConfig)
}
}

View File

@@ -230,7 +230,6 @@ object DeepLinkRouter {
"detection-sensor" to SettingsRoute.DetectionSensor,
"paxcounter" to SettingsRoute.Paxcounter,
"status-message" to SettingsRoute.StatusMessage,
"traffic-management" to SettingsRoute.TrafficManagement,
"tak" to SettingsRoute.TAK,
"clean-node-db" to SettingsRoute.CleanNodeDb,
"debug-panel" to SettingsRoute.DebugPanel,

View File

@@ -150,8 +150,6 @@ sealed interface SettingsRoute : Route {
@Serializable data object StatusMessage : SettingsRoute
@Serializable data object TrafficManagement : SettingsRoute
@Serializable data object TAK : SettingsRoute
// endregion

View File

@@ -321,7 +321,6 @@ class DeepLinkRouterTest {
"detection-sensor" to SettingsRoute.DetectionSensor,
"paxcounter" to SettingsRoute.Paxcounter,
"status-message" to SettingsRoute.StatusMessage,
"traffic-management" to SettingsRoute.TrafficManagement,
"tak" to SettingsRoute.TAK,
"clean-node-db" to SettingsRoute.CleanNodeDb,
"debug-panel" to SettingsRoute.DebugPanel,

View File

@@ -96,7 +96,6 @@ class NavigationConfigTest {
SettingsRoute.DetectionSensor,
SettingsRoute.Paxcounter,
SettingsRoute.StatusMessage,
SettingsRoute.TrafficManagement,
SettingsRoute.TAK,
SettingsRoute.CleanNodeDb,
SettingsRoute.DebugPanel,

View File

@@ -1456,23 +1456,6 @@
<string name="traceroute_showing_nodes">Showing %1$d/%2$d nodes</string>
<string name="track_and_share_locations">Track and Share Locations</string>
<string name="track_point">track point</string>
<!-- TRAFFIC -->
<string name="traffic_management">Traffic Management</string>
<string name="traffic_management_config">Traffic Management Configuration</string>
<string name="traffic_management_drop_unknown_enabled">Drop Unknown Packets</string>
<string name="traffic_management_enabled">Module Enabled</string>
<string name="traffic_management_exhaust_hop_position">Local-only Position (Relays)</string>
<string name="traffic_management_exhaust_hop_telemetry">Local-only Telemetry (Relays)</string>
<string name="traffic_management_nodeinfo_direct_response">NodeInfo Direct Response</string>
<string name="traffic_management_nodeinfo_direct_response_max_hops">Max Hops for Direct Response</string>
<string name="traffic_management_position_dedup">Position Deduplication</string>
<string name="traffic_management_position_min_interval">Min Position Interval (secs)</string>
<string name="traffic_management_position_precision">Position Precision (bits)</string>
<string name="traffic_management_rate_limit_enabled">Rate Limiting</string>
<string name="traffic_management_rate_limit_max_packets">Max Packets in Window</string>
<string name="traffic_management_rate_limit_window">Rate Limit Window (secs)</string>
<string name="traffic_management_router_preserve_hops">Preserve Router Hops</string>
<string name="traffic_management_unknown_packet_threshold">Unknown Packet Threshold</string>
<string name="transmit_over_lora">Transmit over LoRa</string>
<string name="transport_ble">BLE</string>
<string name="transport_tcp">TCP</string>

View File

@@ -21,7 +21,6 @@ import androidx.compose.ui.graphics.vector.ImageVector
import org.jetbrains.compose.resources.vectorResource
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.ic_air
import org.meshtastic.core.resources.ic_alt_route
import org.meshtastic.core.resources.ic_blur_on
import org.meshtastic.core.resources.ic_bolt
import org.meshtastic.core.resources.ic_charging_station
@@ -87,7 +86,5 @@ val MeshtasticIcons.LightMode: ImageVector
@Composable get() = vectorResource(Res.drawable.ic_light_mode)
val MeshtasticIcons.ChargingStation: ImageVector
@Composable get() = vectorResource(Res.drawable.ic_charging_station)
val MeshtasticIcons.TrafficManagement: ImageVector
@Composable get() = vectorResource(Res.drawable.ic_alt_route)
val MeshtasticIcons.VolumeUp: ImageVector
@Composable get() = vectorResource(Res.drawable.ic_volume_up)

View File

@@ -27,7 +27,6 @@ import org.meshtastic.core.resources.audio
import org.meshtastic.core.resources.canned_message
import org.meshtastic.core.resources.detection_sensor
import org.meshtastic.core.resources.external_notification
import org.meshtastic.core.resources.ic_alt_route
import org.meshtastic.core.resources.ic_cloud
import org.meshtastic.core.resources.ic_data_usage
import org.meshtastic.core.resources.ic_group
@@ -51,7 +50,6 @@ import org.meshtastic.core.resources.status_message
import org.meshtastic.core.resources.store_forward
import org.meshtastic.core.resources.tak
import org.meshtastic.core.resources.telemetry
import org.meshtastic.core.resources.traffic_management
import org.meshtastic.proto.AdminMessage
import org.meshtastic.proto.Config
import org.meshtastic.proto.DeviceMetadata
@@ -144,13 +142,6 @@ enum class ModuleRoute(
AdminMessage.ModuleConfigType.STATUSMESSAGE_CONFIG.value,
isSupported = { it.supportsStatusMessage },
),
TRAFFIC_MANAGEMENT(
Res.string.traffic_management,
SettingsRoute.TrafficManagement,
Res.drawable.ic_alt_route,
AdminMessage.ModuleConfigType.TRAFFICMANAGEMENT_CONFIG.value,
isSupported = { it.supportsTrafficManagementConfig },
),
TAK(
Res.string.tak,
SettingsRoute.TAK,
@@ -192,9 +183,6 @@ enum class ModuleRoute(
STATUS_MESSAGE -> 0x0000
// Not excludable yet
TRAFFIC_MANAGEMENT -> 0x0000
// Not excludable yet
TAK -> 0x0000 // Not excludable yet
}

View File

@@ -71,7 +71,6 @@ import org.meshtastic.feature.settings.radio.component.StoreForwardConfigScreen
import org.meshtastic.feature.settings.radio.component.TAKConfigScreen
import org.meshtastic.feature.settings.radio.component.TakServerScreen
import org.meshtastic.feature.settings.radio.component.TelemetryConfigScreen
import org.meshtastic.feature.settings.radio.component.TrafficManagementConfigScreen
import org.meshtastic.feature.settings.radio.component.UserConfigScreen
import kotlin.reflect.KClass
@@ -213,12 +212,6 @@ fun EntryProviderScope<NavKey>.settingsGraph(backStack: NavBackStack<NavKey>) {
ModuleRoute.STATUS_MESSAGE ->
StatusMessageConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
ModuleRoute.TRAFFIC_MANAGEMENT ->
TrafficManagementConfigScreen(
viewModel,
onBack = dropUnlessResumed { backStack.removeLastOrNull() },
)
ModuleRoute.TAK ->
TAKConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
}

View File

@@ -416,7 +416,6 @@ open class RadioConfigViewModel(
detection_sensor = config.detection_sensor ?: state.moduleConfig.detection_sensor,
paxcounter = config.paxcounter ?: state.moduleConfig.paxcounter,
statusmessage = config.statusmessage ?: state.moduleConfig.statusmessage,
traffic_management = config.traffic_management ?: state.moduleConfig.traffic_management,
tak = config.tak ?: state.moduleConfig.tak,
),
)
@@ -796,8 +795,6 @@ open class RadioConfigViewModel(
detection_sensor = response.detection_sensor ?: state.moduleConfig.detection_sensor,
paxcounter = response.paxcounter ?: state.moduleConfig.paxcounter,
statusmessage = response.statusmessage ?: state.moduleConfig.statusmessage,
traffic_management =
response.traffic_management ?: state.moduleConfig.traffic_management,
tak = response.tak ?: state.moduleConfig.tak,
),
)

View File

@@ -1,207 +0,0 @@
/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.meshtastic.feature.settings.radio.component
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.HorizontalDivider
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalFocusManager
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import org.jetbrains.compose.resources.stringResource
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.traffic_management
import org.meshtastic.core.resources.traffic_management_config
import org.meshtastic.core.resources.traffic_management_drop_unknown_enabled
import org.meshtastic.core.resources.traffic_management_enabled
import org.meshtastic.core.resources.traffic_management_exhaust_hop_position
import org.meshtastic.core.resources.traffic_management_exhaust_hop_telemetry
import org.meshtastic.core.resources.traffic_management_nodeinfo_direct_response
import org.meshtastic.core.resources.traffic_management_nodeinfo_direct_response_max_hops
import org.meshtastic.core.resources.traffic_management_position_dedup
import org.meshtastic.core.resources.traffic_management_position_min_interval
import org.meshtastic.core.resources.traffic_management_position_precision
import org.meshtastic.core.resources.traffic_management_rate_limit_enabled
import org.meshtastic.core.resources.traffic_management_rate_limit_max_packets
import org.meshtastic.core.resources.traffic_management_rate_limit_window
import org.meshtastic.core.resources.traffic_management_router_preserve_hops
import org.meshtastic.core.resources.traffic_management_unknown_packet_threshold
import org.meshtastic.core.ui.component.EditTextPreference
import org.meshtastic.core.ui.component.SwitchPreference
import org.meshtastic.core.ui.component.TitledCard
import org.meshtastic.feature.settings.radio.RadioConfigViewModel
import org.meshtastic.proto.ModuleConfig
@Suppress("LongMethod")
@Composable
fun TrafficManagementConfigScreen(viewModel: RadioConfigViewModel, onBack: () -> Unit) {
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
val tmConfig = state.moduleConfig.traffic_management ?: ModuleConfig.TrafficManagementConfig()
val formState = rememberConfigState(initialValue = tmConfig)
val focusManager = LocalFocusManager.current
LaunchedEffect(tmConfig) { formState.value = tmConfig }
RadioConfigScreenList(
title = stringResource(Res.string.traffic_management),
onBack = onBack,
configState = formState,
enabled = state.connected,
responseState = state.responseState,
onDismissPacketResponse = viewModel::clearPacketResponse,
onSave = {
val config = ModuleConfig(traffic_management = it)
viewModel.setModuleConfig(config)
},
) {
item {
TitledCard(title = stringResource(Res.string.traffic_management_config)) {
SwitchPreference(
title = stringResource(Res.string.traffic_management_enabled),
checked = formState.value.enabled,
enabled = state.connected,
onCheckedChange = { formState.value = formState.value.copy(enabled = it) },
containerColor = CardDefaults.cardColors().containerColor,
)
HorizontalDivider()
SwitchPreference(
title = stringResource(Res.string.traffic_management_position_dedup),
checked = formState.value.position_dedup_enabled,
enabled = state.connected,
onCheckedChange = { formState.value = formState.value.copy(position_dedup_enabled = it) },
containerColor = CardDefaults.cardColors().containerColor,
)
HorizontalDivider()
EditTextPreference(
title = stringResource(Res.string.traffic_management_position_precision),
value = formState.value.position_precision_bits,
enabled = state.connected,
keyboardActions =
KeyboardActions(
onNext = { focusManager.moveFocus(androidx.compose.ui.focus.FocusDirection.Down) },
),
onValueChanged = { formState.value = formState.value.copy(position_precision_bits = it) },
)
HorizontalDivider()
EditTextPreference(
title = stringResource(Res.string.traffic_management_position_min_interval),
value = formState.value.position_min_interval_secs,
enabled = state.connected,
keyboardActions =
KeyboardActions(
onNext = { focusManager.moveFocus(androidx.compose.ui.focus.FocusDirection.Down) },
),
onValueChanged = { formState.value = formState.value.copy(position_min_interval_secs = it) },
)
HorizontalDivider()
SwitchPreference(
title = stringResource(Res.string.traffic_management_nodeinfo_direct_response),
checked = formState.value.nodeinfo_direct_response,
enabled = state.connected,
onCheckedChange = { formState.value = formState.value.copy(nodeinfo_direct_response = it) },
containerColor = CardDefaults.cardColors().containerColor,
)
HorizontalDivider()
EditTextPreference(
title = stringResource(Res.string.traffic_management_nodeinfo_direct_response_max_hops),
value = formState.value.nodeinfo_direct_response_max_hops,
enabled = state.connected,
keyboardActions =
KeyboardActions(
onNext = { focusManager.moveFocus(androidx.compose.ui.focus.FocusDirection.Down) },
),
onValueChanged = { formState.value = formState.value.copy(nodeinfo_direct_response_max_hops = it) },
)
HorizontalDivider()
SwitchPreference(
title = stringResource(Res.string.traffic_management_rate_limit_enabled),
checked = formState.value.rate_limit_enabled,
enabled = state.connected,
onCheckedChange = { formState.value = formState.value.copy(rate_limit_enabled = it) },
containerColor = CardDefaults.cardColors().containerColor,
)
HorizontalDivider()
EditTextPreference(
title = stringResource(Res.string.traffic_management_rate_limit_window),
value = formState.value.rate_limit_window_secs,
enabled = state.connected,
keyboardActions =
KeyboardActions(
onNext = { focusManager.moveFocus(androidx.compose.ui.focus.FocusDirection.Down) },
),
onValueChanged = { formState.value = formState.value.copy(rate_limit_window_secs = it) },
)
HorizontalDivider()
EditTextPreference(
title = stringResource(Res.string.traffic_management_rate_limit_max_packets),
value = formState.value.rate_limit_max_packets,
enabled = state.connected,
keyboardActions =
KeyboardActions(
onNext = { focusManager.moveFocus(androidx.compose.ui.focus.FocusDirection.Down) },
),
onValueChanged = { formState.value = formState.value.copy(rate_limit_max_packets = it) },
)
HorizontalDivider()
SwitchPreference(
title = stringResource(Res.string.traffic_management_drop_unknown_enabled),
checked = formState.value.drop_unknown_enabled,
enabled = state.connected,
onCheckedChange = { formState.value = formState.value.copy(drop_unknown_enabled = it) },
containerColor = CardDefaults.cardColors().containerColor,
)
HorizontalDivider()
EditTextPreference(
title = stringResource(Res.string.traffic_management_unknown_packet_threshold),
value = formState.value.unknown_packet_threshold,
enabled = state.connected,
keyboardActions =
KeyboardActions(
onNext = { focusManager.moveFocus(androidx.compose.ui.focus.FocusDirection.Down) },
),
onValueChanged = { formState.value = formState.value.copy(unknown_packet_threshold = it) },
)
HorizontalDivider()
SwitchPreference(
title = stringResource(Res.string.traffic_management_exhaust_hop_telemetry),
checked = formState.value.exhaust_hop_telemetry,
enabled = state.connected,
onCheckedChange = { formState.value = formState.value.copy(exhaust_hop_telemetry = it) },
containerColor = CardDefaults.cardColors().containerColor,
)
HorizontalDivider()
SwitchPreference(
title = stringResource(Res.string.traffic_management_exhaust_hop_position),
checked = formState.value.exhaust_hop_position,
enabled = state.connected,
onCheckedChange = { formState.value = formState.value.copy(exhaust_hop_position = it) },
containerColor = CardDefaults.cardColors().containerColor,
)
HorizontalDivider()
SwitchPreference(
title = stringResource(Res.string.traffic_management_router_preserve_hops),
checked = formState.value.router_preserve_hops,
enabled = state.connected,
onCheckedChange = { formState.value = formState.value.copy(router_preserve_hops = it) },
containerColor = CardDefaults.cardColors().containerColor,
)
}
}
}
}