diff --git a/meshterm/core/device_config.py b/meshterm/core/device_config.py index 1d86e8b..81445b7 100644 --- a/meshterm/core/device_config.py +++ b/meshterm/core/device_config.py @@ -331,7 +331,7 @@ _PATH_HASH_CHOICES = { def _telemetry_spec(key: str, label: str) -> SettingSpec: """Build a telemetry-mode setting spec (shared shape for base/loc/env).""" return SettingSpec( - key=key, label=label, help="Telemetry reporting mode", category="Behavior", + key=key, label=label, help="Who may read this node's sensor readings", category="Behavior", value_type="enum", choices=_TELEMETRY_CHOICES, minimum=0, maximum=3, getter=_get(key), apply=_telemetry_apply(key), ) @@ -452,16 +452,16 @@ def current_preset(snapshot: dict[str, Any]) -> Optional[RadioPreset]: DEVICE_SETTINGS: list[SettingSpec] = [ # Identity SettingSpec( - "name", "Node name", "Advertised node name", "Identity", "str", + "name", "Node name", "The name other nodes see", "Identity", "str", getter=_get("name"), apply=lambda d, v, s: d.set_name(v), ), SettingSpec( - "adv_lat", "Latitude", "Advertised latitude, degrees", "Identity", + "adv_lat", "Latitude", "How far north or south this node says it is", "Identity", "float", minimum=-90.0, maximum=90.0, getter=_get("adv_lat"), apply=_coords_apply("adv_lat"), ), SettingSpec( - "adv_lon", "Longitude", "Advertised longitude, degrees", "Identity", + "adv_lon", "Longitude", "How far east or west this node says it is", "Identity", "float", minimum=-180.0, maximum=180.0, getter=_get("adv_lon"), apply=_coords_apply("adv_lon"), ), @@ -472,34 +472,36 @@ DEVICE_SETTINGS: list[SettingSpec] = [ # backups still restore; reading the firmware's own name means the row shows a # value instead of "?" on real hardware. The fallback keeps the canonical key # working for anything that reports it directly. - "device_pin", "Device PIN", "BLE pairing PIN", "Identity", "int", + "device_pin", "Device PIN", "Code a phone needs to pair over Bluetooth", "Identity", "int", minimum=0, maximum=999999, getter=lambda snapshot: snapshot.get("ble_pin", snapshot.get("device_pin")), apply=lambda d, v, s: d.set_device_pin(v), ), # Radio SettingSpec( - "radio_freq", "Frequency (MHz)", "Carrier frequency in MHz", "Radio", "float", + "radio_freq", "Frequency (MHz)", "Must match every other node on your mesh", + "Radio", "float", minimum=100.0, maximum=1000.0, getter=_get("radio_freq"), apply=_radio_apply("freq"), ), SettingSpec( - "radio_bw", "Bandwidth (kHz)", "Channel bandwidth in kHz", "Radio", "float", + "radio_bw", "Bandwidth (kHz)", "Wider is faster, narrower reaches further", + "Radio", "float", minimum=1.0, maximum=1000.0, getter=_get("radio_bw"), apply=_radio_apply("bw"), ), SettingSpec( - "radio_sf", "Spreading factor", "LoRa spreading factor", "Radio", "int", + "radio_sf", "Spreading factor", "Higher reaches further but sends slower", "Radio", "int", minimum=5, maximum=12, getter=_get("radio_sf"), apply=_radio_apply("sf"), ), SettingSpec( - "radio_cr", "Coding rate", "LoRa coding-rate denominator (4/5–4/8)", + "radio_cr", "Coding rate", "Higher survives noise better, sends slower", "Radio", "int", minimum=5, maximum=8, getter=_get("radio_cr"), apply=_radio_apply("cr"), ), SettingSpec( - "tx_power", "TX power (dBm)", "Transmit power, up to this board's reported max", + "tx_power", "TX power (dBm)", "How loud this radio transmits", "Radio", "int", minimum=1, maximum=30, max_key="max_tx_power", getter=_get("tx_power"), apply=lambda d, v, s: d.set_tx_power(v), ), @@ -508,44 +510,44 @@ DEVICE_SETTINGS: list[SettingSpec] = [ # here: companion firmware ignores them — they are remote-CLI settings on repeaters.) SettingSpec( "airtime_factor", "Airtime factor", - "Airtime budget: duty cycle = 100 / (factor + 1) %, so 0 = unlimited", "Tuning", + "Caps how much of the air we use; 0 = no cap", "Tuning", "float", minimum=0.0, maximum=9.0, getter=_get("airtime_factor"), apply=_tuning_apply("airtime_factor"), ), SettingSpec( "rx_delay", "RX delay", - "Base delay before handling received packets, seconds", "Tuning", + "Wait this long before acting on what we hear", "Tuning", "float", minimum=0.0, maximum=20.0, getter=_get("rx_delay"), apply=_tuning_apply("rx_delay"), ), # Behavior SettingSpec( - "manual_add_contacts", "Manual add contacts", - "Require adding contacts manually", "Behavior", "bool", + "manual_add_contacts", "Add contacts by hand", + "Only save a node when you say so", "Behavior", "bool", getter=_get("manual_add_contacts"), apply=lambda d, v, s: d.set_manual_add_contacts(v), ), SettingSpec( - "autoadd_config", "Contact auto-add", - "Bitmask of advert types auto-added as contacts (0 = none)", "Behavior", "int", + "autoadd_config", "Auto-add contacts", + "Which kinds of node get saved on their own; 0 = none", "Behavior", "int", minimum=0, maximum=255, getter=_get("autoadd_config"), apply=lambda d, v, s: d.set_autoadd_config(v), ), SettingSpec( "flood_scope", "Flood scope", - "Limit flood routing to one #scope; empty reaches the whole mesh", "Behavior", + "Keep traffic to one group; empty reaches everyone", "Behavior", "str", max_length=30, getter=_get("flood_scope"), apply=lambda d, v, s: d.set_default_flood_scope(v), ), SettingSpec( - "adv_loc_policy", "Advert location policy", - "Share location in adverts", "Behavior", "enum", + "adv_loc_policy", "Share location", + "Tell other nodes where this one is", "Behavior", "enum", choices=_ADV_LOC_CHOICES, minimum=0, strict_choices=False, getter=_get("adv_loc_policy"), apply=lambda d, v, s: d.set_adv_loc_policy(v), ), SettingSpec( "multi_acks", "Multi-acks", - "Extra acknowledgements for reliability", "Behavior", + "Send extra receipts so replies get through", "Behavior", "enum", choices=_MULTI_ACKS_CHOICES, minimum=0, strict_choices=False, getter=_get("multi_acks"), apply=lambda d, v, s: d.set_multi_acks(v), ), @@ -555,7 +557,7 @@ DEVICE_SETTINGS: list[SettingSpec] = [ # Experimental SettingSpec( "path_hash_mode", "Path-hash mode", - "Per-hop path-hash size; larger resists collisions, adds overhead", + "Longer hop ids mix up fewer nodes, but cost space", "Experimental", "enum", choices=_PATH_HASH_CHOICES, minimum=0, maximum=3, getter=_get("path_hash_mode"), apply=lambda d, v, s: d.set_path_hash_mode(v), ), diff --git a/meshterm/core/preferences.py b/meshterm/core/preferences.py index 235bbd9..062c43e 100644 --- a/meshterm/core/preferences.py +++ b/meshterm/core/preferences.py @@ -54,7 +54,7 @@ GROUPS: tuple[str, ...] = ( "Transmit power", "Watchtower", "Map", - "History kept", + "History", "Display", ) @@ -127,8 +127,8 @@ PREFERENCES: tuple[PrefSpec, ...] = ( # --- Sending ----------------------------------------------------------------- PrefSpec( key="trace_cooldown_s", - label="Transmit cooldown", - help="Pause between our own transmissions, for duty-cycle safety", + label="Pause between sends", + help="Wait this long before transmitting again", group="Sending", value_type="float", default=5.0, @@ -139,7 +139,7 @@ PREFERENCES: tuple[PrefSpec, ...] = ( PrefSpec( key="direct_message_soft_retries", label="Message retries", - help="Automatic re-sends of an unacknowledged direct message", + help="Times to resend a message that gets no reply", group="Sending", value_type="int", default=0, # one shot: a re-send is a second transmission on a shared mesh @@ -149,8 +149,8 @@ PREFERENCES: tuple[PrefSpec, ...] = ( # --- Transmit power ---------------------------------------------------------- PrefSpec( key="tx_opt_min", - label="Sweep floor", - help="Lowest power the transmit-power optimizer explores", + label="Lowest power", + help="Weakest setting the power search tries", group="Transmit power", value_type="int", default=18, @@ -160,8 +160,8 @@ PREFERENCES: tuple[PrefSpec, ...] = ( ), PrefSpec( key="tx_opt_max", - label="Sweep ceiling", - help="Highest power the transmit-power optimizer explores", + label="Highest power", + help="Strongest setting the power search tries", group="Transmit power", value_type="int", default=28, @@ -171,8 +171,8 @@ PREFERENCES: tuple[PrefSpec, ...] = ( ), PrefSpec( key="tx_snr_tolerance_db", - label="Tie tolerance", - help="Within this much SNR of the best, the lower power wins", + label="Tie margin", + help="Signals this close are a tie, so less power wins", group="Transmit power", value_type="float", default=1.0, @@ -183,8 +183,8 @@ PREFERENCES: tuple[PrefSpec, ...] = ( # --- Watchtower -------------------------------------------------------------- PrefSpec( key="watch_silence_hours", - label="Silence alarm", - help="Silence a newly watched node is allowed before the alarm", + label="Alert after", + help="Warn when a watched node goes quiet this long", group="Watchtower", value_type="enum", default=DEFAULT_SILENCE_HOURS, @@ -193,7 +193,7 @@ PREFERENCES: tuple[PrefSpec, ...] = ( PrefSpec( key="watch_alerts_kept", label="Alerts kept", - help="Alerts the Watchtower log retains, oldest dropped first", + help="How many past alerts to keep", group="Watchtower", value_type="int", default=200, @@ -203,8 +203,8 @@ PREFERENCES: tuple[PrefSpec, ...] = ( # --- Map --------------------------------------------------------------------- PrefSpec( key="map_view_fraction", - label="Opening frame", - help="Fraction of nodes a map frames, so outliers don't zoom it out", + label="Map fit", + help="Share of nodes to fit on screen; 1 shows them all", group="Map", value_type="float", default=0.5, @@ -213,8 +213,8 @@ PREFERENCES: tuple[PrefSpec, ...] = ( ), PrefSpec( key="basemap_tilejson_url", - label="Basemap source", - help="TileJSON the map's vector tiles are fetched from", + label="Map tiles", + help="Where map images come from", group="Map", value_type="str", default="https://tiles.openfreemap.org/planet", @@ -223,9 +223,9 @@ PREFERENCES: tuple[PrefSpec, ...] = ( # --- History kept ------------------------------------------------------------ PrefSpec( key="history_days", - label="Packet history", - help="Days of overheard history kept; 0 keeps everything forever", - group="History kept", + label="Keep packets for", + help="Older ones are deleted; 0 keeps everything", + group="History", value_type="int", default=365, minimum=0, @@ -234,9 +234,9 @@ PREFERENCES: tuple[PrefSpec, ...] = ( ), PrefSpec( key="chat_history_limit", - label="Transcript depth", - help="Past messages loaded when a conversation opens", - group="History kept", + label="Chat history", + help="Old messages to load when you open a chat", + group="History", value_type="int", default=200, minimum=20, @@ -245,8 +245,8 @@ PREFERENCES: tuple[PrefSpec, ...] = ( PrefSpec( key="courier_history_kept", label="Courier history", - help="Delivered and given-up outbox entries kept for the screen", - group="History kept", + help="Finished outbox messages to keep", + group="History", value_type="int", default=100, minimum=10, @@ -256,7 +256,7 @@ PREFERENCES: tuple[PrefSpec, ...] = ( PrefSpec( key="fast_render", label="Fast redraw", - help="Write rows straight to the terminal instead of through the stock renderer", + help="Faster screen updates; turn off if it looks wrong", group="Display", value_type="bool", default=True, @@ -265,7 +265,7 @@ PREFERENCES: tuple[PrefSpec, ...] = ( PrefSpec( key="full_width", label="Last column", - help="Use the column a terminal that under-reports its width hides", + help="Use the extra column some terminals hide", group="Display", value_type="enum", default="auto", diff --git a/tests/test_preferences.py b/tests/test_preferences.py index 484e171..522d579 100644 --- a/tests/test_preferences.py +++ b/tests/test_preferences.py @@ -158,8 +158,8 @@ def test_the_file_reads_the_way_the_page_does(tmp_path: Path) -> None: prefs = Preferences(tmp_path / "preferences.yaml") prefs.set("history_days", 30) text = prefs.as_yaml() - assert "# --- History kept ---" in text - assert "# Days of overheard history kept" in text + assert "# --- History ---" in text + assert "# Older ones are deleted; 0 keeps everything" in text assert "# default: 365 days" in text # A group with nothing changed in it earns no heading. assert "# --- Display ---" not in text @@ -298,9 +298,9 @@ def test_a_staged_change_shows_its_arrow_and_the_save_action() -> None: def test_a_long_value_is_capped_so_the_descriptions_keep_their_lane() -> None: """The basemap URL is shortened in the lane rather than eating the prose column.""" _, rows = _rows(Preferences()) - basemap = next(row for row in rows if "Basemap source" in row) + basemap = next(row for row in rows if "Map tiles" in row) assert "https://tiles.openf…" in basemap - assert "TileJSON" in basemap # its description still made it onto the row + assert "Where map images" in basemap # its description still made it onto the row def _table_lines(prefs: Preferences, width: int) -> list[str]: @@ -345,8 +345,8 @@ def test_the_printed_table_names_every_value_and_its_default() -> None: body = "\n".join(_table_lines(prefs, 160)) assert "https://tiles.openfreemap.org/planet" in body # never capped here assert "30 days" in body and "365 days" in body # value beside its default - assert "── History kept ──" in body - assert "Days of overheard history kept" in body # the description lane, at this width + assert "── History ──" in body + assert "Older ones are deleted" in body # the description lane, at this width def test_the_printed_table_never_elides_a_key() -> None: