Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions Meshtastic/Enums/DeviceEnums.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,23 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
case router = 2
case routerLate = 11
case clientBase = 12
/// Deprecated (firmware v2.7.15). Retained only so existing nodes still
/// reporting REPEATER (rawValue 4) can be displayed and reconfigured.
/// Not offered as a newly selectable role — see `isDeprecated`.
case repeater = 4

var id: Int { self.rawValue }

/// Roles that are retired upstream and must not be offered for new selection,
/// but may still appear on existing nodes that need migrating to a supported role.
var isDeprecated: Bool {
switch self {
case .repeater:
return true
default:
return false
}
}
var name: String {
switch self {
case .client:
Expand All @@ -48,6 +63,8 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
return "Router Late".localized
case .clientBase:
return "Client Base".localized
case .repeater:
return "Repeater (Deprecated)".localized
}

}
Expand Down Expand Up @@ -75,6 +92,8 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
return "Infrastructure node that always rebroadcasts packets once but only after all other modes. Visible in Nodes list. Not a good choice for rooftop nodes.".localized
case .clientBase:
return "Used for rooftop nodes to distribute messages more widely from multiple nearby client mute nodes.".localized
case .repeater:
return "Deprecated infrastructure role that creates gaps in the mesh rebroadcast chain. Switch this node to a Router-based role (Router or Router Late).".localized
}
}

Expand All @@ -100,6 +119,8 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
return "map"
case .clientBase:
return "house"
case .repeater:
return "wifi.router"
}
}
func protoEnumValue() -> Config.DeviceConfig.Role {
Expand Down Expand Up @@ -127,6 +148,8 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
return Config.DeviceConfig.Role.routerLate
case .clientBase:
return Config.DeviceConfig.Role.clientBase
case .repeater:
return Config.DeviceConfig.Role.repeater
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions Meshtastic/Resources/docs/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -409,9 +409,9 @@
"traffic",
"nodes",
"translation",
"set",
"rate",
"translated",
"set",
"only",
"management",
"enable",
Expand All @@ -426,7 +426,7 @@
"packets",
"module"
],
"charCount": 8930
"charCount": 9177
},
{
"id": "signal-meter",
Expand Down
2 changes: 2 additions & 0 deletions Meshtastic/Resources/docs/markdown/user/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ BLE radio settings including PIN mode and power saving. Changes apply on next ra

Device role, serial output, debug log streaming, and node info broadcast interval.

The **Repeater** role is deprecated and can no longer be selected for new configurations. If a node is still set to Repeater it is shown as "Repeater (Deprecated)" with a reminder to switch it to a Router-based role (Router or Router Late).

### Display

Screen timeout, auto-carousel of screens, flip screen for alternate mounting orientations, and OLED contrast.
Expand Down
1 change: 1 addition & 0 deletions Meshtastic/Resources/docs/user/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ <h3>Bluetooth</h3>
<p>BLE radio settings including PIN mode and power saving. Changes apply on next radio restart.</p>
<h3>Device</h3>
<p>Device role, serial output, debug log streaming, and node info broadcast interval.</p>
<p>The <strong>Repeater</strong> role is deprecated and can no longer be selected for new configurations. If a node is still set to Repeater it is shown as &quot;Repeater (Deprecated)&quot; with a reminder to switch it to a Router-based role (Router or Router Late).</p>
<h3>Display</h3>
<p>Screen timeout, auto-carousel of screens, flip screen for alternate mounting orientations, and OLED contrast.</p>
<h4>Compass Orientation</h4>
Expand Down
14 changes: 13 additions & 1 deletion Meshtastic/Views/Settings/Config/DeviceConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ struct DeviceConfig: View {
Section(header: Text("Options")) {
VStack(alignment: .leading) {
Picker("Device Role", selection: $deviceRole ) {
ForEach(DeviceRoles.allCases) { dr in
ForEach(availableDeviceRoles) { dr in
Text(dr.name).tag(dr.rawValue as Int)
}
}
Expand Down Expand Up @@ -75,6 +75,11 @@ struct DeviceConfig: View {
Text(DeviceRoles(rawValue: deviceRole)?.description ?? "")
.foregroundColor(.gray)
.font(.callout)
if DeviceRoles(rawValue: deviceRole)?.isDeprecated ?? false {
Label("This role is deprecated. Select a Router-based role to keep this node on a supported configuration.", systemImage: "exclamationmark.triangle")
.foregroundColor(.orange)
.font(.callout)
}
}
.pickerStyle(DefaultPickerStyle())

Expand Down Expand Up @@ -398,6 +403,13 @@ struct DeviceConfig: View {
hasChanges = false
}

/// Roles offered in the picker. Deprecated roles (e.g. Repeater) are hidden
/// from new selection, but the node's current role stays visible so an
/// existing deprecated node can be seen and reconfigured to a supported role.
private var availableDeviceRoles: [DeviceRoles] {
DeviceRoles.allCases.filter { !$0.isDeprecated || $0.rawValue == deviceRole }
}

private func specialRoleWarningMessage(newRole: Int) -> String {
if [DeviceRoles.router.rawValue, DeviceRoles.routerLate.rawValue].contains(newRole) {
return "The Router roles are only for high vantage locations like mountaintops and towers with few nearby nodes, not for use in urban areas. Improper use will hurt your local mesh."
Expand Down
13 changes: 12 additions & 1 deletion MeshtasticTests/EnumComprehensiveTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,18 @@ import MapKit
struct DeviceRolesEnumTests {

@Test func allCases_count() {
#expect(DeviceRoles.allCases.count == 11)
#expect(DeviceRoles.allCases.count == 12)
}

@Test func repeater_isDeprecated() {
#expect(DeviceRoles.repeater.rawValue == 4)
#expect(DeviceRoles.repeater.isDeprecated)
#expect(DeviceRoles(rawValue: 4) == .repeater)
}

@Test func onlyRepeaterIsDeprecated() {
let deprecated = DeviceRoles.allCases.filter { $0.isDeprecated }
#expect(deprecated == [.repeater])
}

@Test func allCases_haveNames() {
Expand Down
2 changes: 1 addition & 1 deletion MeshtasticTests/LoraDeviceEnumTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ struct DeviceRolesTests {
}

@Test func totalCaseCount() {
#expect(DeviceRoles.allCases.count == 11)
#expect(DeviceRoles.allCases.count == 12)
}
}

Expand Down
2 changes: 2 additions & 0 deletions docs/user/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ BLE radio settings including PIN mode and power saving. Changes apply on next ra

Device role, serial output, debug log streaming, and node info broadcast interval.

The **Repeater** role is deprecated and can no longer be selected for new configurations. If a node is still set to Repeater it is shown as "Repeater (Deprecated)" with a reminder to switch it to a Router-based role (Router or Router Late).

### Display

Screen timeout, auto-carousel of screens, flip screen for alternate mounting orientations, and OLED contrast.
Expand Down
Loading