mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
Agent-Logs-Url: https://github.com/meshtastic/Meshtastic-Android/sessions/b9b68633-39b3-466b-b40c-e3a6bdd92e99 Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
488 lines
24 KiB
Markdown
488 lines
24 KiB
Markdown
# Settings Screen Validation Reference
|
||
|
||
This document describes the validation rules enforced on each radio configuration and module
|
||
configuration settings screen. Constraints are sourced from two layers:
|
||
|
||
1. **Protobuf schema** — field types, enums, and `max_size` annotations defined in the
|
||
`meshtastic/protobufs` submodule.
|
||
2. **UI form layer** — additional range checks, conditional visibility, and interval pickers
|
||
implemented in `feature/settings/src/commonMain/.../radio/component/`.
|
||
|
||
> **Reusable components** live in `core/ui/.../component/`. Each component enforces its own
|
||
> validation strategy (see [UI Component Validation](#ui-component-validation) at the bottom).
|
||
|
||
---
|
||
|
||
## Table of Contents
|
||
|
||
- [Device Config Screens](#device-config-screens)
|
||
- [User](#user-configuserconfig)
|
||
- [Device](#device-configdeviceconfig)
|
||
- [Position](#position-configpositionconfig)
|
||
- [Power](#power-configpowerconfig)
|
||
- [Network](#network-confignetworkconfig)
|
||
- [Display](#display-configdisplayconfig)
|
||
- [LoRa](#lora-configloraconfig)
|
||
- [Bluetooth](#bluetooth-configbluetoothconfig)
|
||
- [Security](#security-configsecurityconfig)
|
||
- [Module Config Screens](#module-config-screens)
|
||
- [MQTT](#mqtt-moduleconfigmqttconfig)
|
||
- [Serial](#serial-moduleconfigserialconfig)
|
||
- [External Notification](#external-notification-moduleconfigexternalnotificationconfig)
|
||
- [Store & Forward](#store--forward-moduleconfigstoreforwardconfig)
|
||
- [Range Test](#range-test-moduleconfigrangetestconfig)
|
||
- [Telemetry](#telemetry-moduleconfigtelemetryconfig)
|
||
- [Canned Message](#canned-message-moduleconfigcannedmessageconfig)
|
||
- [Audio](#audio-moduleconfigaudioconfig)
|
||
- [Remote Hardware](#remote-hardware-moduleconfigremotehardwareconfig)
|
||
- [Neighbor Info](#neighbor-info-moduleconfigneighborinfoconfig)
|
||
- [Ambient Lighting](#ambient-lighting-moduleconfigambientlightingconfig)
|
||
- [Detection Sensor](#detection-sensor-moduleconfigdetectionsensorconfig)
|
||
- [Paxcounter](#paxcounter-moduleconfigpaxcounterconfig)
|
||
- [Status Message](#status-message-moduleconfigstatusmessageconfig)
|
||
- [Traffic Management](#traffic-management-moduleconfigtrafficmanagementconfig)
|
||
- [TAK](#tak-moduleconfigtakconfig)
|
||
- [Channel Config](#channel-config)
|
||
- [Interval Configurations](#interval-configurations)
|
||
- [UI Component Validation](#ui-component-validation)
|
||
|
||
---
|
||
|
||
## Device Config Screens
|
||
|
||
### User (`Config.UserConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `long_name` | String | maxSize: 39 bytes (proto max_size: 40) | Required (non-blank) |
|
||
| `short_name` | String | maxSize: 4 bytes (proto max_size: 5) | Required (non-blank) |
|
||
| `is_licensed` | Boolean | Toggle | — |
|
||
| `is_unmessagable` | Boolean | Toggle | Enabled only when device capability `canToggleUnmessageable` is true or role is unmessageable |
|
||
|
||
### Device (`Config.DeviceConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `role` | Enum | Dropdown: `DeviceConfig.Role` entries | Router/ROUTER_LATE/REPEATER roles trigger a confirmation dialog |
|
||
| `rebroadcast_mode` | Enum | Dropdown: `RebroadcastMode` entries | ALL, ALL_SKIP_DECODING, LOCAL_ONLY, KNOWN_ONLY, NONE, CORE_PORTNUMS_ONLY |
|
||
| `node_info_broadcast_secs` | Interval | Dropdown: `NODE_INFO_BROADCAST` intervals | See [Interval Configurations](#interval-configurations) |
|
||
| `double_tap_as_button_press` | Boolean | Toggle | — |
|
||
| `disable_triple_click` | Boolean | Toggle (inverted) | UI shows "enabled" when proto field is `false` |
|
||
| `led_heartbeat_disabled` | Boolean | Toggle (inverted) | UI shows "enabled" when proto field is `false` |
|
||
| `tzdef` | String | maxSize: 64 bytes (proto max_size: 65) | Clearable |
|
||
| `button_gpio` | Integer | Numeric input | — |
|
||
| `buzzer_gpio` | Integer | Numeric input | — |
|
||
|
||
### Position (`Config.PositionConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `position_broadcast_secs` | Interval | Dropdown: `POSITION_BROADCAST` intervals | — |
|
||
| `position_broadcast_smart_enabled` | Boolean | Toggle | Controls visibility of smart broadcast fields |
|
||
| `broadcast_smart_minimum_interval_secs` | Interval | Dropdown: `SMART_BROADCAST_MINIMUM` intervals | Visible only when smart broadcast enabled |
|
||
| `broadcast_smart_minimum_distance` | Integer | Numeric input | Visible only when smart broadcast enabled |
|
||
| `fixed_position` | Boolean | Toggle | Controls visibility of lat/lon/alt vs GPS fields |
|
||
| `latitude` | Double | Range: −90.0 to +90.0 | Visible only when `fixed_position = true` |
|
||
| `longitude` | Double | Range: −180.0 to +180.0 | Visible only when `fixed_position = true` |
|
||
| `altitude` | Integer | Numeric input | Visible only when `fixed_position = true` |
|
||
| `gps_mode` | Enum | Dropdown: `GpsMode` entries | Visible only when `fixed_position = false` |
|
||
| `gps_update_interval` | Interval | Dropdown: `GPS_UPDATE` intervals | Visible only when `fixed_position = false` |
|
||
| `position_flags` | Bitwise | Checkbox set: `PositionFlags` entries (excl. UNSET) | Bitwise OR of selected flags |
|
||
| `rx_gpio` | Integer | Dropdown: GPIO pins 0–48 | — |
|
||
| `tx_gpio` | Integer | Dropdown: GPIO pins 0–48 | — |
|
||
| `gps_en_gpio` | Integer | Dropdown: GPIO pins 0–48 | — |
|
||
|
||
### Power (`Config.PowerConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `is_power_saving` | Boolean | Toggle | — |
|
||
| `on_battery_shutdown_after_secs` | Interval | Dropdown: `ALL` intervals | — |
|
||
| `adc_multiplier_override` | Float | Must be > 0.0 when enabled | Checkbox + float input; float visible only when enabled |
|
||
| `wait_bluetooth_secs` | Interval | Dropdown: `NAG_TIMEOUT` intervals | 0s–60s |
|
||
| `sds_secs` | Interval | Dropdown: `ALL` intervals | — |
|
||
| `min_wake_secs` | Interval | Dropdown: `NAG_TIMEOUT` intervals | 0s–60s |
|
||
| `device_battery_ina_address` | Integer | Numeric input (I2C address) | — |
|
||
|
||
### Network (`Config.NetworkConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `wifi_enabled` | Boolean | Toggle | Controls visibility of Wi-Fi fields |
|
||
| `wifi_ssid` | String | maxSize: 32 bytes (proto max_size: 33) | Visible when `wifi_enabled = true` |
|
||
| `wifi_psk` | Password | maxSize: 64 bytes (proto max_size: 65) | Visible when `wifi_enabled = true` |
|
||
| `eth_enabled` | Boolean | Toggle | Visible only when device `hasEthernet = true` |
|
||
| `ntp_server` | String | maxSize: 32 bytes (proto max_size: 33) | — |
|
||
| `rsyslog_server` | String | maxSize: 32 bytes (proto max_size: 33) | — |
|
||
| `address_mode` | Enum | Dropdown: `AddressMode` (DHCP, STATIC) | Controls visibility of IPv4 fields |
|
||
| `ipv4_config.ip` | IPv4 | Regex: `\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}` | Visible when `address_mode = STATIC` |
|
||
| `ipv4_config.gateway` | IPv4 | Same regex | Visible when `address_mode = STATIC` |
|
||
| `ipv4_config.subnet` | IPv4 | Same regex | Visible when `address_mode = STATIC` |
|
||
| `ipv4_config.dns` | IPv4 | Same regex | Visible when `address_mode = STATIC` |
|
||
|
||
### Display (`Config.DisplayConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `screen_on_secs` | Interval | Dropdown: `DISPLAY_SCREEN_ON` intervals | 15s – Always On |
|
||
| `auto_screen_carousel_secs` | Interval | Dropdown: `DISPLAY_CAROUSEL` intervals | 0 (disabled) – 15 min |
|
||
| `compass_north_top` | Boolean | Toggle | — |
|
||
| `use_12h_clock` | Boolean | Toggle | — |
|
||
| `heading_bold` | Boolean | Toggle | — |
|
||
| `units` | Enum | Dropdown: `DisplayUnits` entries | Metric / Imperial |
|
||
| `wake_on_tap_or_motion` | Boolean | Toggle | — |
|
||
| `flip_screen` | Boolean | Toggle | — |
|
||
| `displaymode` | Enum | Dropdown: `DisplayMode` entries | — |
|
||
| `oled` | Enum | Dropdown: `OledType` entries | — |
|
||
| `compass_orientation` | Enum | Dropdown: `CompassOrientation` entries | — |
|
||
|
||
### LoRa (`Config.LoRaConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `region` | Enum | Dropdown: `RegionInfo` entries | Regional frequency plans |
|
||
| `use_preset` | Boolean | Toggle | Controls manual vs preset LoRa settings visibility |
|
||
| `modem_preset` | Enum | Dropdown: `ChannelOption` entries | Visible only when `use_preset = true` |
|
||
| `bandwidth` | Integer | Numeric input | Visible only when `use_preset = false` |
|
||
| `spread_factor` | Integer | Numeric input | Visible only when `use_preset = false` |
|
||
| `coding_rate` | Integer | Numeric input | Visible only when `use_preset = false` |
|
||
| `hop_limit` | Integer | Dropdown: 0–7 | — |
|
||
| `channel_num` | Integer | Numeric input; must be ≤ `numChannels` | — |
|
||
| `tx_enabled` | Boolean | Toggle | — |
|
||
| `tx_power` | Integer | Signed integer input (dBm) | — |
|
||
| `override_duty_cycle` | Boolean | Toggle | — |
|
||
| `override_frequency` | Float | MHz value | — |
|
||
| `sx126x_rx_boosted_gain` | Boolean | Toggle | — |
|
||
| `ignore_mqtt` | Boolean | Toggle | — |
|
||
| `config_ok_to_mqtt` | Boolean | Toggle | — |
|
||
| `pa_fan_disabled` | Boolean | Toggle | Visible only when device `hasPaFan = true` |
|
||
|
||
### Bluetooth (`Config.BluetoothConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `enabled` | Boolean | Toggle | — |
|
||
| `mode` | Enum | Dropdown: `PairingMode` entries (excl. UNRECOGNIZED) | — |
|
||
| `fixed_pin` | String | Exactly 6 digits | — |
|
||
|
||
### Security (`Config.SecurityConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `public_key` | Base64 | 32 bytes; read-only | Auto-derived from private key |
|
||
| `private_key` | Base64 | 32 bytes | Key generation applies bit masking: `f[0] &= 0xF8`, `f[31] = (f[31] & 0x7F) ǀ 0x40` |
|
||
| `admin_key` | Base64 list | maxCount: 3; each entry 32 bytes | — |
|
||
| `serial_enabled` | Boolean | Toggle | — |
|
||
| `debug_log_api_enabled` | Boolean | Toggle | — |
|
||
| `admin_channel_enabled` | Boolean | Toggle | — |
|
||
| `is_managed` | Boolean | Toggle | Enabled only when `admin_key` list is non-empty |
|
||
|
||
---
|
||
|
||
## Module Config Screens
|
||
|
||
### MQTT (`ModuleConfig.MQTTConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `enabled` | Boolean | Toggle | — |
|
||
| `address` | String | maxSize: 63 bytes (proto max_size: 64) | Non-blank required for connection test |
|
||
| `username` | String | maxSize: 63 bytes (proto max_size: 64) | — |
|
||
| `password` | Password | maxSize: 63 bytes (proto max_size: 64) | — |
|
||
| `encryption_enabled` | Boolean | Toggle | — |
|
||
| `json_enabled` | Boolean | Toggle | — |
|
||
| `tls_enabled` | Boolean | Toggle | Auto-enforced when using default server with proxy |
|
||
| `root` | String | maxSize: 31 bytes (proto max_size: 32) | MQTT root topic |
|
||
| `proxy_to_client_enabled` | Boolean | Toggle | — |
|
||
| `map_reporting_enabled` | Boolean | Toggle | Controls visibility of map report fields |
|
||
| `map_report_settings.publish_interval_secs` | Integer | Minimum: 3600 seconds (1 hour) | — |
|
||
| `map_report_settings.position_precision` | Integer | Slider: 12–15 bits | — |
|
||
|
||
### Serial (`ModuleConfig.SerialConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `enabled` | Boolean | Toggle | — |
|
||
| `echo` | Boolean | Toggle | — |
|
||
| `rxd` | Integer | Numeric input (GPIO) | — |
|
||
| `txd` | Integer | Numeric input (GPIO) | — |
|
||
| `baud` | Enum | Dropdown: `Serial_Baud` entries | — |
|
||
| `timeout` | Integer | Numeric input | — |
|
||
| `mode` | Enum | Dropdown: `Serial_Mode` entries | — |
|
||
| `override_console_serial_port` | Boolean | Toggle | — |
|
||
|
||
### External Notification (`ModuleConfig.ExternalNotificationConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `enabled` | Boolean | Toggle | — |
|
||
| `alert_message` | Boolean | Toggle | — |
|
||
| `alert_message_buzzer` | Boolean | Toggle | — |
|
||
| `alert_message_vibra` | Boolean | Toggle | — |
|
||
| `alert_bell` | Boolean | Toggle | — |
|
||
| `alert_bell_buzzer` | Boolean | Toggle | — |
|
||
| `alert_bell_vibra` | Boolean | Toggle | — |
|
||
| `output` | Integer | Dropdown: GPIO pins 0–48 | Shows `active` field when ≠ 0 |
|
||
| `active` | Boolean | Toggle | Visible when `output ≠ 0` |
|
||
| `output_buzzer` | Integer | Dropdown: GPIO pins 0–48 | Shows `use_pwm` field when ≠ 0 |
|
||
| `use_pwm` | Boolean | Toggle | Visible when `output_buzzer ≠ 0` |
|
||
| `output_vibra` | Integer | Dropdown: GPIO pins 0–48 | — |
|
||
| `output_ms` | Interval | Dropdown: `OUTPUT` intervals | 0s–10s |
|
||
| `nag_timeout` | Interval | Dropdown: `NAG_TIMEOUT` intervals | 0s–60s |
|
||
| `ringtone` | String | maxSize: 230 bytes | RTTTL format |
|
||
| `use_i2s_as_buzzer` | Boolean | Toggle | — |
|
||
|
||
### Store & Forward (`ModuleConfig.StoreForwardConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `enabled` | Boolean | Toggle | — |
|
||
| `heartbeat` | Boolean | Toggle | — |
|
||
| `records` | Integer | Numeric input | — |
|
||
| `history_return_max` | Integer | Numeric input | — |
|
||
| `history_return_window` | Integer | Numeric input (seconds) | — |
|
||
| `is_server` | Boolean | Toggle | — |
|
||
|
||
### Range Test (`ModuleConfig.RangeTestConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `enabled` | Boolean | Toggle | — |
|
||
| `sender` | Interval | Dropdown: `RANGE_TEST_SENDER` intervals | 0 (disabled) – 1 hour |
|
||
| `save` | Boolean | Toggle | — |
|
||
|
||
### Telemetry (`ModuleConfig.TelemetryConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `device_telemetry_enabled` | Boolean | Toggle | Visible only when `canToggleTelemetryEnabled` capability |
|
||
| `device_update_interval` | Interval | Dropdown: `BROADCAST_SHORT` intervals | 30 min – 72 hours |
|
||
| `environment_measurement_enabled` | Boolean | Toggle | — |
|
||
| `environment_update_interval` | Interval | Dropdown: `BROADCAST_SHORT` intervals | 30 min – 72 hours |
|
||
| `environment_screen_enabled` | Boolean | Toggle | — |
|
||
| `environment_display_fahrenheit` | Boolean | Toggle | — |
|
||
| `air_quality_enabled` | Boolean | Toggle | — |
|
||
| `air_quality_interval` | Interval | Dropdown: `BROADCAST_SHORT` intervals | 30 min – 72 hours |
|
||
| `power_measurement_enabled` | Boolean | Toggle | — |
|
||
| `power_update_interval` | Interval | Dropdown: `BROADCAST_SHORT` intervals | 30 min – 72 hours |
|
||
| `power_screen_enabled` | Boolean | Toggle | — |
|
||
|
||
### Canned Message (`ModuleConfig.CannedMessageConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `enabled` | Boolean | Toggle | — |
|
||
| `rotary1_enabled` | Boolean | Toggle | — |
|
||
| `inputbroker_pin_a` | Integer | Numeric input (GPIO) | — |
|
||
| `inputbroker_pin_b` | Integer | Numeric input (GPIO) | — |
|
||
| `inputbroker_pin_press` | Integer | Numeric input (GPIO) | — |
|
||
| `inputbroker_event_press` | Enum | Dropdown: `InputEventChar` entries | — |
|
||
| `inputbroker_event_cw` | Enum | Dropdown: `InputEventChar` entries | — |
|
||
| `inputbroker_event_ccw` | Enum | Dropdown: `InputEventChar` entries | — |
|
||
| `updown1_enabled` | Boolean | Toggle | — |
|
||
| `allow_input_source` | String | maxSize: 63 bytes (proto max_size: 16; UI intentionally allows more) | — |
|
||
| `send_bell` | Boolean | Toggle | — |
|
||
| `messages` | String | maxSize: 200 bytes (proto max_size: 201) | Pipe-delimited canned messages |
|
||
|
||
### Audio (`ModuleConfig.AudioConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `codec2_enabled` | Boolean | Toggle | — |
|
||
| `ptt_pin` | Integer | Numeric input (GPIO) | — |
|
||
| `bitrate` | Enum | Dropdown: `Audio_Baud` entries | — |
|
||
| `i2s_ws` | Integer | Numeric input (GPIO) | — |
|
||
| `i2s_sd` | Integer | Numeric input (GPIO) | — |
|
||
| `i2s_din` | Integer | Numeric input (GPIO) | — |
|
||
| `i2s_sck` | Integer | Numeric input (GPIO) | — |
|
||
|
||
### Remote Hardware (`ModuleConfig.RemoteHardwareConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `enabled` | Boolean | Toggle | — |
|
||
| `allow_undefined_pin_access` | Boolean | Toggle | — |
|
||
| `available_pins` | Pin list | maxCount: 4 | Each pin: gpio 0–255, name maxSize 14 bytes, type `RemoteHardwarePinType` enum |
|
||
|
||
### Neighbor Info (`ModuleConfig.NeighborInfoConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `enabled` | Boolean | Toggle | — |
|
||
| `update_interval` | Integer | Numeric input (seconds) | — |
|
||
| `transmit_over_lora` | Boolean | Toggle | — |
|
||
|
||
### Ambient Lighting (`ModuleConfig.AmbientLightingConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `led_state` | Boolean | Toggle | — |
|
||
| `current` | Integer | Numeric input | — |
|
||
| `red` | Integer | Numeric input (0–255) | — |
|
||
| `green` | Integer | Numeric input (0–255) | — |
|
||
| `blue` | Integer | Numeric input (0–255) | — |
|
||
|
||
### Detection Sensor (`ModuleConfig.DetectionSensorConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `enabled` | Boolean | Toggle | — |
|
||
| `minimum_broadcast_secs` | Interval | Dropdown: `DETECTION_SENSOR_MINIMUM` intervals | 0 (unset) – 72 hours |
|
||
| `state_broadcast_secs` | Interval | Dropdown: `DETECTION_SENSOR_STATE` intervals | 0 (unset) – 72 hours |
|
||
| `send_bell` | Boolean | Toggle | — |
|
||
| `name` | String | maxSize: 19 bytes (proto max_size: 20) | — |
|
||
| `monitor_pin` | Integer | Dropdown: GPIO pins 0–48 | — |
|
||
| `detection_trigger_type` | Enum | Dropdown: `TriggerType` entries | — |
|
||
| `use_pullup` | Boolean | Toggle | — |
|
||
|
||
### Paxcounter (`ModuleConfig.PaxcounterConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `enabled` | Boolean | Toggle | — |
|
||
| `paxcounter_update_interval` | Interval | Dropdown: `PAX_COUNTER` intervals | 15 min – 72 hours |
|
||
| `wifi_threshold` | Integer | Signed integer (RSSI dBm) | Default: −80 |
|
||
| `ble_threshold` | Integer | Signed integer (RSSI dBm) | Default: −80 |
|
||
|
||
### Status Message (`ModuleConfig.StatusMessageConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `node_status` | String | maxSize: 80 bytes | Clearable; requires `supportsStatusMessage` capability |
|
||
|
||
### Traffic Management (`ModuleConfig.TrafficManagementConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `enabled` | Boolean | Toggle | Requires `supportsTrafficManagementConfig` capability |
|
||
| `position_dedup_enabled` | Boolean | Toggle | — |
|
||
| `position_precision_bits` | Integer | Numeric input | — |
|
||
| `position_min_interval_secs` | Integer | Numeric input (seconds) | — |
|
||
| `nodeinfo_direct_response` | Boolean | Toggle | — |
|
||
| `nodeinfo_direct_response_max_hops` | Integer | Numeric input | — |
|
||
| `rate_limit_enabled` | Boolean | Toggle | — |
|
||
| `rate_limit_window_secs` | Integer | Numeric input (seconds) | — |
|
||
| `rate_limit_max_packets` | Integer | Numeric input | — |
|
||
| `drop_unknown_enabled` | Boolean | Toggle | — |
|
||
| `unknown_packet_threshold` | Integer | Numeric input | — |
|
||
| `exhaust_hop_telemetry` | Boolean | Toggle | — |
|
||
| `exhaust_hop_position` | Boolean | Toggle | — |
|
||
| `router_preserve_hops` | Boolean | Toggle | — |
|
||
|
||
### TAK (`ModuleConfig.TAKConfig`)
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `team` | Enum | Dropdown with custom colors/labels | Only shown when device role is `TAK` or `TAK_TRACKER` |
|
||
| `role` | Enum | Dropdown with custom labels | Only shown when device role is `TAK` or `TAK_TRACKER` |
|
||
|
||
---
|
||
|
||
## Channel Config
|
||
|
||
Channel editing is handled by `EditChannelDialog`.
|
||
|
||
| Field | Type | Validation | Notes |
|
||
|-------|------|------------|-------|
|
||
| `name` | String | maxSize: 11 bytes | Empty name falls back to modem preset name |
|
||
| `psk` | ByteString | Must be exactly 0, 16, or 32 bytes | Pre-shared key for encryption |
|
||
|
||
---
|
||
|
||
## Interval Configurations
|
||
|
||
Time-based fields use predefined interval sets from `IntervalConfiguration`. Each configuration
|
||
context restricts the available choices to a specific subset of `FixedUpdateIntervals`.
|
||
|
||
| Configuration | Range | Values (seconds) |
|
||
|---------------|-------|------------------|
|
||
| `ALL` | 0 – 2147483647 | 0, 1, 2, 3, 4, 5, 8, 10, 15, 20, 30, 40, 45, 60, 80, 90, 120, 300, 600, 900, 1800, 3600, 7200, 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200, 2147483647 |
|
||
| `BROADCAST_SHORT` | 30 min – 72 hr | 1800, 3600, 7200, 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200 |
|
||
| `BROADCAST_MEDIUM` | 1 hr – 72 hr | 3600, 7200, 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200 |
|
||
| `BROADCAST_LONG` | 3 hr – 72 hr | 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200 |
|
||
| `NODE_INFO_BROADCAST` | 0 (unset), 3 hr – 72 hr | 0, 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200 |
|
||
| `NAG_TIMEOUT` | 0 – 60 s | 0, 1, 5, 10, 15, 30, 60 |
|
||
| `OUTPUT` | 0 – 10 s | 0, 1, 2, 3, 4, 5, 10 |
|
||
| `PAX_COUNTER` | 15 min – 72 hr | 900, 1800, 3600, 7200, 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200 |
|
||
| `POSITION` | 1 s – 1 hr | 1, 2, 5, 10, 15, 20, 30, 45, 60, 120, 300, 600, 900, 1800, 3600 |
|
||
| `POSITION_BROADCAST` | 0 (unset), 1 min – 72 hr | 0, 60, 90, 300, 900, 3600, 7200, 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200 |
|
||
| `GPS_UPDATE` | 0 (unset), 8 s – 24 hr | 0, 8, 20, 40, 60, 80, 120, 300, 600, 900, 1800, 3600, 21600, 43200, 86400 |
|
||
| `RANGE_TEST_SENDER` | 0 (disabled) – 1 hr | 0, 15, 30, 45, 60, 300, 600, 900, 1800, 3600 |
|
||
| `SMART_BROADCAST_MINIMUM` | 15 s – 1 hr | 15, 30, 45, 60, 300, 600, 900, 1800, 3600 |
|
||
| `DETECTION_SENSOR_MINIMUM` | 0 (unset), 15 s – 72 hr | 0, 15, 30, 60, 120, 300, 600, 900, 1800, 3600, 7200, 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200 |
|
||
| `DETECTION_SENSOR_STATE` | 0 (unset), 15 min – 72 hr | 0, 900, 1800, 3600, 7200, 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200 |
|
||
| `DISPLAY_SCREEN_ON` | 15 s – Always On | 15, 30, 60, 300, 600, 900, 1800, 3600, 2147483647 |
|
||
| `DISPLAY_CAROUSEL` | 0 (disabled) – 15 min | 0, 15, 30, 60, 300, 600, 900 |
|
||
|
||
### Shared Constants
|
||
|
||
- **GPIO Pins:** 0–48 (inclusive)
|
||
- **Hop Limits:** 0–7 (inclusive)
|
||
|
||
---
|
||
|
||
## UI Component Validation
|
||
|
||
The reusable Compose components in `core/ui/.../component/` provide the actual enforcement
|
||
layer. Each component accepts validation parameters and rejects or flags invalid input.
|
||
|
||
### EditTextPreference
|
||
|
||
- **String mode:** Enforces `maxSize` in UTF-8 bytes via `encodeToByteArray().size <= maxSize`.
|
||
Shows a live byte counter when focused.
|
||
- **Int mode:** Validates with `toIntOrNull()`; sets error icon on failure.
|
||
- **Float mode:** Validates with `toFloatOrNull()`.
|
||
- **Double mode:** Validates with `toDoubleOrNull()`; supports international decimal separators
|
||
(`.`, `,`, `٫`, `、`, `·`).
|
||
|
||
### SignedIntegerEditTextPreference
|
||
|
||
- Validates with `toIntOrNull()`; shows error icon on invalid input.
|
||
|
||
### DropDownPreference
|
||
|
||
- Closed-set selection only — no free-form input.
|
||
- Automatically filters `UNRECOGNIZED` and deprecated enum entries.
|
||
|
||
### SwitchPreference
|
||
|
||
- Binary toggle; inherently valid. Disabled state shown at reduced opacity.
|
||
|
||
### SliderPreference
|
||
|
||
- Discrete steps only; values clamped with `coerceIn()` and rounded to the nearest valid index.
|
||
|
||
### EditIPv4Preference
|
||
|
||
- Regex validation: `\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}`.
|
||
- Stored as a little-endian `Int`; displayed as dotted-decimal.
|
||
|
||
### EditPasswordPreference
|
||
|
||
- Delegates to `EditTextPreference` with `maxSize` enforcement and password visibility toggle.
|
||
|
||
### EditBase64Preference
|
||
|
||
- Validates Base64 encoding on input.
|
||
- Flags all-zero 32-byte values as errors (empty/unset key).
|
||
|
||
### BitwisePreference
|
||
|
||
- Closed checkbox set; toggles individual bit flags via XOR.
|
||
- "Clear" button resets to 0.
|
||
|
||
### EditListPreference
|
||
|
||
- Enforces `maxCount` for list length.
|
||
- Per-element validation varies by type: `Int` range 0–255 for GPIO pins,
|
||
`ByteString` via Base64 parsing, composite `RemoteHardwarePin` with nested field rules.
|
||
|
||
### PositionPrecisionPreference
|
||
|
||
- State machine with three modes: disabled (0), precision range (10–19), full precision (32).
|
||
- Slider constrained to 10–19 with 8 discrete steps.
|
||
|
||
### ConfigState
|
||
|
||
- Generic wrapper that tracks `isDirty` (current value ≠ initial value).
|
||
- Changes are only persisted on explicit save; cancel reverts to the initial snapshot.
|