Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0030aec8dd | ||
|
|
675e40575d | ||
|
|
f88c6c64e5 | ||
|
|
eaea32fcc6 | ||
|
|
0e477426f5 | ||
|
|
c1683e333f | ||
|
|
6693dba8cf | ||
|
|
a2f51253d8 | ||
|
|
af08c02a00 | ||
|
|
378925638b | ||
|
|
3963048226 | ||
|
|
0be4c7488c | ||
|
|
8c698dc2d1 | ||
|
|
9ce2a076eb | ||
|
|
a31b19ed8a | ||
|
|
3e0ce84486 | ||
|
|
015a3e8e05 | ||
|
|
6b3f7df4d0 | ||
|
|
f62cc7b527 | ||
|
|
a52059e603 | ||
|
|
3d3d5827ba | ||
|
|
331ba22a90 | ||
|
|
cbafd44047 | ||
|
|
926238123d | ||
|
|
f304b8ff77 | ||
|
|
41f48344bd | ||
|
|
32a994e838 | ||
|
|
3e8c637866 | ||
|
|
33204b768a | ||
|
|
a43f48f63c | ||
|
|
f7b8777e9a | ||
|
|
584fc9a4d7 | ||
|
|
d11bf3615d | ||
|
|
937f8610c7 | ||
|
|
5a031f7674 | ||
|
|
ef80f29337 | ||
|
|
7acc637468 | ||
|
|
9a176964dd | ||
|
|
4606f3da60 | ||
|
|
0eb1d03a16 | ||
|
|
5cb8367d12 | ||
|
|
04f98ea44c | ||
|
|
894d033503 | ||
|
|
d031609f26 | ||
|
|
a2a63ea5cc | ||
|
|
6e4b501dd6 | ||
|
|
7bdd9adec1 | ||
|
|
6b7812bfc2 | ||
|
|
ddf625e9d0 | ||
|
|
f79a316da8 | ||
|
|
466eb008c7 | ||
|
|
fdad79eaf7 | ||
|
|
d74a0f8b44 | ||
|
|
89f26fe1c9 | ||
|
|
b0c02b1e47 | ||
|
|
d83fa7cf8e | ||
|
|
a14bbdc58f | ||
|
|
7a463937ca | ||
|
|
df88a6ef95 | ||
|
|
57036b1d66 | ||
|
|
396474bf9c | ||
|
|
c07d16e398 | ||
|
|
4bbd613417 | ||
|
|
d2b6244ae0 |
No files matched your search
@@ -10,6 +10,43 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
nrf52-companion-smoke:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Build Environment
|
||||
uses: ./.github/actions/setup-build-environment
|
||||
- name: Qualify RAK4631 Full Companion with linked Meshtext support
|
||||
run: >-
|
||||
bash build.sh build-firmware RAK_4631_companion_radio_full
|
||||
--firmware-version v1.17.1.10-halo-keymind-cascade-dev
|
||||
--radio-preset usa-cascade-fixed --profile cascade --require-ota
|
||||
|
||||
- name: Verify linked Companion crypto, retained Reader and ARM stack use
|
||||
run: |
|
||||
python3 -m pip install unicorn==2.1.4
|
||||
python3 -B scripts/check_nrf52_companion_crypto.py .pio/build/RAK_4631_companion_radio_full/firmware.elf
|
||||
|
||||
nrf52-sensor-smoke:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Build Environment
|
||||
uses: ./.github/actions/setup-build-environment
|
||||
- name: Verify nRF52 HEX packaging with installed build dependencies
|
||||
run: python3 -B test/test_nrf52_endf_hex.py -v
|
||||
- name: Compile GPS Sensor tracker on nRF52 boards
|
||||
run: pio run -e t1000e_sensor -e RAK_WisMesh_Tag_sensor
|
||||
|
||||
esp32-sensor-smoke:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Build Environment
|
||||
uses: ./.github/actions/setup-build-environment
|
||||
- name: Compile GPS-capable Sensor tracker on ESP32-S3
|
||||
run: pio run -e heltec_v4_sensor
|
||||
|
||||
management-reports:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -27,6 +64,7 @@ jobs:
|
||||
python3 -B test/test_management_report.py -v
|
||||
python3 -B test/test_management_cli_wrapper.py -v
|
||||
node test/test_management_decoder.js
|
||||
node scripts/test_telemetry_decoder.js
|
||||
|
||||
stm32-companion-smoke:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -37,6 +75,11 @@ jobs:
|
||||
- name: Setup Build Environment
|
||||
uses: ./.github/actions/setup-build-environment
|
||||
|
||||
- name: Verify compact STM32 signature arithmetic
|
||||
run: |
|
||||
python3 -B test/test_ed25519_compact_scalar.py -v
|
||||
python3 -B test/test_ed25519_compact.py -v
|
||||
|
||||
- name: Compile ordinary STM32 USB Companion with pinned core and RadioLib
|
||||
run: pio run -e RAK_3x72_companion_radio_usb
|
||||
|
||||
@@ -90,16 +133,71 @@ jobs:
|
||||
uses: ./.github/actions/setup-build-environment
|
||||
|
||||
- name: Install signed-package verification dependency
|
||||
run: python3 -m pip install cryptography
|
||||
run: |
|
||||
python3 -m pip install cryptography
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libssl-dev
|
||||
mkdir -p .pio/libdeps/room-mail-test
|
||||
pio pkg install --global --library 'rweather/Crypto@0.4.0' --storage-dir .pio/libdeps/room-mail-test
|
||||
|
||||
- name: Verify ArduinoJson pin
|
||||
run: |
|
||||
python3 -B scripts/check_arduinojson_pin.py --self-test
|
||||
python3 -B scripts/check_arduinojson_pin.py
|
||||
|
||||
- name: Verify build-size diagnostics and nRF52 optimizer recipes
|
||||
run: |
|
||||
bash test/test_build_size_detection.sh
|
||||
python3 -B test/test_nrf52_size_profile.py -v
|
||||
python3 -B test/test_rak_combined_build_config.py -v
|
||||
|
||||
- name: Run Unit Tests
|
||||
run: pio test -e native -e native_kiss_modem -e native_ota_channel -vv
|
||||
|
||||
- name: Verify parser, delivery, storage, permissions, clock and radio stability
|
||||
run: |
|
||||
python3 -B test/test_protocol_parser_bounds.py -v
|
||||
python3 -B test/test_cli_error_bounds.py -v
|
||||
python3 -B test/test_ota_security.py -v
|
||||
python3 -B test/test_companion_offline_delivery.py -v
|
||||
python3 -B test/test_room_receive_admission.py -v
|
||||
python3 -B test/test_companion_lfs_traversal.py -v
|
||||
python3 -B test/test_room_post_permissions.py -v
|
||||
python3 -B test/test_room_login_authorization.py -v
|
||||
python3 -B test/test_room_login_integration.py -v
|
||||
python3 -B test/test_room_client_paths.py -v
|
||||
python3 -B test/test_client_acl_infrastructure.py -v
|
||||
python3 -B test/test_stored_client_reply_routes.py -v
|
||||
python3 -B test/test_room_catchup.py -v
|
||||
python3 -B test/test_room_catchup_transport.py -v
|
||||
python3 -B test/test_room_topic_store.py -v
|
||||
python3 -B test/test_room_topic_delivery.py -v
|
||||
python3 -B test/test_room_acl_persistence.py -v
|
||||
python3 -B test/test_room_access_policy.py -v
|
||||
python3 -B test/test_room_history_store.py -v
|
||||
python3 -B test/test_room_history_integration.py -v
|
||||
python3 -B test/test_room_board_store.py -v
|
||||
python3 -B test/test_room_board_protocol.py -v
|
||||
python3 -B test/test_room_mail_store.py -v
|
||||
python3 -B test/test_room_mail_protocol.py -v
|
||||
python3 -B test/test_room_web_mailbox.py -v
|
||||
python3 -B test/test_room_web_http.py -v
|
||||
python3 -B test/test_room_web_service.py -v
|
||||
python3 -B test/test_contact_clock_bootstrap.py -v
|
||||
python3 -B test/test_rtc_discovery.py -v
|
||||
python3 -B test/test_radio_interrupt_recovery.py -v
|
||||
python3 -B test/test_bridge_recovery.py -v
|
||||
|
||||
- name: Verify signed private fleet management
|
||||
run: |
|
||||
python3 -B test/test_fleet_command_crypto.py -v
|
||||
python3 -B test/test_companion_fleet_control.py -v
|
||||
python3 -B test/test_fleet_channel_runtime.py -v
|
||||
python3 -B test/test_fleet_role_wiring.py -v
|
||||
python3 -B test/test_fleet_location.py -v
|
||||
python3 -B test/test_fleet_radio_schedules.py -v
|
||||
python3 -B test/test_fleet_clock_control.py -v
|
||||
|
||||
- name: Verify OTA channel persistence and published image tags
|
||||
run: |
|
||||
python3 -B test/test_ota_channel_persistence.py -v
|
||||
@@ -111,7 +209,9 @@ jobs:
|
||||
run: python3 -B test/test_build_output_safety.py -v
|
||||
|
||||
- name: Verify serial mOTA response deadlines and RX fairness
|
||||
run: python3 -B test/test_mota_serial_deadline.py -v
|
||||
run: |
|
||||
python3 -B test/test_mota_serial_deadline.py -v
|
||||
python3 -B test/test_mota_folder_deadline.py -v
|
||||
|
||||
- name: Verify filter playground modes and built-in defaults
|
||||
run: node scripts/test_filter_tool.js
|
||||
@@ -122,6 +222,9 @@ jobs:
|
||||
python3 -B test/test_rs232_runtime.py -v
|
||||
python3 -B test/test_rs232_mqtt_runtime.py -v
|
||||
python3 -B test/test_rs232_driver_lifecycle.py -v
|
||||
python3 -B test/test_rs232_heartbeat.py -v
|
||||
python3 -B test/test_rs232_heartbeat_owner.py -v
|
||||
python3 -B test/test_rs232_power_settings.py -v
|
||||
|
||||
- name: Verify saved repeat-off trace exception and relay guards
|
||||
run: |
|
||||
@@ -134,16 +237,38 @@ jobs:
|
||||
- name: Verify transactional telemetry preferences and legacy route recovery
|
||||
run: python3 -B test/test_telemetry_tx_persistence.py -v
|
||||
|
||||
- name: Verify MQTT start results and connection-attempt accounting
|
||||
run: python3 -B test/test_mqtt_transport_results.py -v
|
||||
- name: Verify MQTT and WiFi ownership, recovery and power policy
|
||||
run: |
|
||||
python3 -B test/test_mqtt_transport_results.py -v
|
||||
python3 -B test/test_mqtt_tls_security.py -v
|
||||
python3 -B test/test_mqtt_network_timeout.py -v
|
||||
python3 -B test/test_mqtt_disconnect.py -v
|
||||
python3 -B test/test_mqtt_connection_admission.py -v
|
||||
python3 -B test/test_mqtt_handshake_scheduler.py -v
|
||||
python3 -B test/test_mqtt_diagnostics.py -v
|
||||
python3 -B test/test_mqtt_publish_ack.py -v
|
||||
python3 -B test/test_wifi_network_power_policy.py -v
|
||||
python3 -B test/test_mqtt_wifi_network_power.py -v
|
||||
python3 -B test/test_companion_wifi_network_power.py -v
|
||||
python3 -B test/test_webconfig_network_power.py -v
|
||||
python3 -B test/test_companion_ap_ownership.py -v
|
||||
python3 -B test/test_heltec_v4_wifi_setup_page.py -v
|
||||
|
||||
- name: Verify DNS lease restoration and bounded diagnostics
|
||||
run: python3 -B test/test_network_dns.py -v
|
||||
|
||||
- name: Verify Sensor dog tracker ownership, routes, storage, GPS and sleep
|
||||
run: |
|
||||
python3 -B test/test_tracker_route_policy.py -v
|
||||
python3 -B test/test_sensor_tracker_store.py -v
|
||||
python3 -B test/test_tracker_owner_response.py -v
|
||||
python3 -B test/test_sensor_tracker_client.py -v
|
||||
python3 -B test/test_sensor_tracker_gps.py -v
|
||||
python3 -B test/test_sensor_tracker_sleep.py -v
|
||||
|
||||
- name: Verify Companion contact and channel TX routing
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libssl-dev
|
||||
python3 -B test/test_companion_channel_alias.py -v
|
||||
python3 -B test/test_companion_tx_routing.py -v
|
||||
python3 -B test/test_companion_discovery.py -v
|
||||
python3 -B test/test_repeater_discovery.py -v
|
||||
@@ -158,6 +283,7 @@ jobs:
|
||||
python3 -B test/test_companion_primary_radio_persistence.py -v
|
||||
python3 -B test/test_companion_response_bounds.py -v
|
||||
python3 -B test/test_companion_ack_delivery.py -v
|
||||
python3 -B test/test_companion_lost_reply.py -v
|
||||
python3 -B test/test_companion_delayed_reply_delivery.py -v
|
||||
python3 -B test/test_companion_hardware_serial.py -v
|
||||
python3 -B test/test_companion_hardware_serial_gps.py -v
|
||||
@@ -173,10 +299,23 @@ jobs:
|
||||
python3 -B test/test_common_prefs_commit.py -v
|
||||
python3 -B test/test_common_prefs_legacy_rxgain.py -v
|
||||
python3 -B test/test_flood_policy_capacity.py -v
|
||||
python3 -B test/test_flood_rule_layout.py -v
|
||||
python3 -B test/test_mqtt_prefs_commit.py -v
|
||||
python3 -B test/test_identity_and_settings_recovery.py -v
|
||||
python3 -B test/test_contact_cache.py -v
|
||||
|
||||
- name: Verify Meshtext chat codec, transport and Companion integration
|
||||
run: |
|
||||
python3 -B test/test_meshtext_chat.py -v
|
||||
python3 -B test/test_meshtext_config.py -v
|
||||
python3 -B test/test_meshtext_transport.py -v
|
||||
python3 -B test/test_meshtext_license.py -v
|
||||
python3 -B test/test_radio_profile_auto.py -v
|
||||
python3 -B test/test_companion_meshtext.py -v
|
||||
python3 -B test/test_companion_meshtext_storage.py -v
|
||||
python3 -B test/test_meshtext_auto_radio2_hil.py -v
|
||||
python3 -B test/test_meshtext_auto_radio2_hil_sdk.py -v
|
||||
|
||||
- name: Verify receive recovery and pinned radio status transport
|
||||
run: |
|
||||
python3 -B test/test_dispatcher_startup_watchdog.py -v
|
||||
@@ -196,6 +335,22 @@ jobs:
|
||||
- name: Verify temporary-radio timing and exact reply delivery
|
||||
run: |
|
||||
python3 -B test/test_carrier_wave.py
|
||||
python3 -B test/test_morse_tx.py -v
|
||||
python3 -B test/test_morse_rx.py -v
|
||||
python3 -B test/test_morse_rx_timing.py -v
|
||||
python3 -B test/test_morse_rx_gap_bias.py -v
|
||||
python3 -B test/test_morse_rx_human.py -v
|
||||
python3 -B test/test_morse_hil_timing.py -v
|
||||
python3 -B test/test_morse_hil_production.py -v
|
||||
python3 -B test/test_morse_rx_squelch.py -v
|
||||
python3 -B test/test_morse_hil_squelch.py -v
|
||||
python3 -B test/test_morse_cli.py -v
|
||||
python3 -B test/test_morse_auth.py -v
|
||||
python3 -B test/test_morse_reply_handoff.py -v
|
||||
python3 -B test/test_morse_remote.py -v
|
||||
python3 -B test/test_morse_hil_safety.py -v
|
||||
python3 -B test/test_morse_loop_policy.py -v
|
||||
python3 -B test/test_morse_terminal_input.py -v
|
||||
python3 -B test/test_radio_profile_cli.py
|
||||
python3 -B test/test_radio_profile_spiffs_missing.py -v
|
||||
python3 -B test/test_radio_reply_mutation.py
|
||||
@@ -219,7 +374,7 @@ jobs:
|
||||
working-directory: test
|
||||
run: >-
|
||||
python3 -B -m unittest -v
|
||||
test_sx1262_profile_switch test_sx1262_batched_modulation
|
||||
test_sx1262_profile_switch test_sx1262_batched_modulation test_sx1262_protocol_batching
|
||||
test_radio_chirp_math
|
||||
|
||||
- name: Verify radio lab collectors and compiled experiment contracts
|
||||
@@ -242,11 +397,10 @@ jobs:
|
||||
python3 -B test/test_ota_device_deflate_encoder.py -v
|
||||
python3 -B test/test_ota_device_deflate_role.py -v
|
||||
python3 -B test/test_client_acl_spiffs.py
|
||||
python3 -B test/test_client_acl_role.py -v
|
||||
python3 -B test/test_client_acl_metadata.py -v
|
||||
python3 -B test/test_client_acl_cli.py -v
|
||||
python3 -B test/test_client_acl_response.py -v
|
||||
python3 -B test/test_client_acl_infrastructure.py -v
|
||||
python3 -B test/test_stored_client_reply_routes.py -v
|
||||
|
||||
- name: Setup Node for official app compatibility tests
|
||||
uses: actions/setup-node@v4
|
||||
@@ -259,10 +413,11 @@ jobs:
|
||||
path: ~/.cache/meshcore-tests
|
||||
key: official-clients-84bc39a950735aaffa93d912556852a4c22e235d0cc4e4d04790113207f13a68-aff42ad8ef2b332f24d644ff6a783f8272a88ff2
|
||||
|
||||
- name: Verify stock app radio and Access Control compatibility
|
||||
- name: Verify stock app radio, Access Control and room compatibility
|
||||
run: |
|
||||
node --version
|
||||
python3 -B test/test_official_app_compatibility.py -v
|
||||
python3 -B test/test_official_room_app_compatibility.py -v
|
||||
|
||||
- name: Verify ESP32 USB reboot sleep grace and G3 button wake
|
||||
run: |
|
||||
@@ -273,6 +428,7 @@ jobs:
|
||||
|
||||
- name: Verify official web console framing and power-saving idle sessions
|
||||
run: |
|
||||
python3 -B test/test_cpp_source.py -v
|
||||
python3 -B test/test_official_web_console.py -v
|
||||
python3 -B test/test_hil_linux_web_serial.py -v
|
||||
python3 -B test/test_hil_slowfi_guard.py -v
|
||||
@@ -289,6 +445,7 @@ jobs:
|
||||
run: |
|
||||
python3 -B test/test_wifi_ota_start.py -v
|
||||
python3 -B test/test_webconfig_ap_start.py -v
|
||||
python3 -B test/test_webconfig_recovery_auth.py -v
|
||||
python3 -B test/test_esp32_wifi_scan_fix.py -v
|
||||
python3 -B test/test_esp32_wifi_scan_recipes.py -v
|
||||
|
||||
@@ -302,6 +459,8 @@ jobs:
|
||||
python3 -B test/test_esp32_gps_discovery.py -v
|
||||
python3 -B test/test_gps_sync_interval.py -v
|
||||
python3 -B test/test_gps_sync_preferences.py -v
|
||||
python3 -B test/test_rak_gps_power.py -v
|
||||
python3 -B test/test_peripheral_mode_prefs.py -v
|
||||
python3 -B test/test_t1000e_sensor_power.py -v
|
||||
python3 -B test/test_sensor_battery_alerts.py -v
|
||||
python3 -B test/test_sensor_subscriptions.py -v
|
||||
@@ -365,6 +524,7 @@ jobs:
|
||||
run: |
|
||||
python3 -B test/test_wireless_control.py -v
|
||||
python3 -B test/test_serial_wifi_sessions.py -v
|
||||
python3 -B test/test_companion_wifi_listener.py -v
|
||||
python3 -B test/test_serial_ethernet_sessions.py -v
|
||||
python3 -B test/test_companion_wifi_session.py -v
|
||||
python3 -B test/test_espnow_radio_lifecycle.py -v
|
||||
@@ -410,6 +570,8 @@ jobs:
|
||||
python3 -B test/test_firmware_build_recipe.py -v
|
||||
python3 -B test/test_firmware_capabilities.py
|
||||
MESHCORE_TEST_REAL_PIO_PATHS=1 python3 -B test/test_esp32_partition_migration_build_dir.py -v
|
||||
python3 -B test/test_esp32_partition_migration_usb.py -v
|
||||
python3 -B test/test_usb_partition_bridge_set.py -v
|
||||
bash test/test_build_profiles.sh
|
||||
bash test/test_full_infrastructure_selection.sh
|
||||
bash test/test_nrf52_ota_profiles.sh
|
||||
@@ -427,9 +589,12 @@ jobs:
|
||||
python3 -B test/test_replay_reset_integration.py -v
|
||||
|
||||
- name: Verify firmware memory budgets and nRF52 Bluetooth startup
|
||||
env:
|
||||
MESHCORE_REQUIRE_ARM_COMPILER: '1'
|
||||
run: |
|
||||
bash test/test_build_size_detection.sh
|
||||
python3 -B test/test_firmware_ram.py
|
||||
python3 -B test/test_recent_repeater_storage.py -v
|
||||
python3 -B test/test_ota_cold_buffers.py -v
|
||||
python3 -B test/test_neighbor_scope_storage.py
|
||||
python3 -B test/test_ed25519_compact.py
|
||||
python3 -B test/test_cascade_release_package.py
|
||||
@@ -443,11 +608,18 @@ jobs:
|
||||
python3 -B test/test_nrf52_usb_power.py
|
||||
python3 -B test/test_shared_mota_queue.py
|
||||
|
||||
- name: Verify opt-in RAK4631 combined Ethernet and OTA modes
|
||||
run: |
|
||||
python3 -B test/test_rak_combined_ota.py -v
|
||||
python3 -B test/test_rak_ethernet_transmit.py -v
|
||||
python3 -B test/test_rak4631_ethernet_runtime.py -v
|
||||
|
||||
- name: Verify nRF52 infrastructure trims and unchanged Companion scope
|
||||
run: |
|
||||
python3 -B test/test_nrf52_flash_trim.py -v
|
||||
python3 -B test/test_nrf52_tft_font_trim.py -v
|
||||
python3 -B test/test_ota_target_names.py -v
|
||||
python3 -B test/test_ota_cli_listing.py -v
|
||||
|
||||
- name: Verify compact same-size fonts and lossless rendering
|
||||
run: |
|
||||
@@ -487,10 +659,11 @@ jobs:
|
||||
python3 -B test/test_webconfig_station_ownership.py -v
|
||||
python3 -B test/test_mqtt_canonical_wifi.py -v
|
||||
python3 -B test/test_mqtt_ap_ownership.py -v
|
||||
python3 -B test/test_companion_ap_ownership.py -v
|
||||
python3 -B test/test_heltec_v4_wifi_setup_page.py -v
|
||||
python3 -B test/test_sensor_webconfig_capabilities.py -v
|
||||
python3 -B test/test_webconfig_ui_runtime.py
|
||||
python3 -B test/test_webconfig_lost_reply.py -v
|
||||
MESHCORE_REQUIRE_ROOM_BROWSER=1 python3 -B test/test_room_web_ui.py -v
|
||||
MESHCORE_REQUIRE_ROOM_BROWSER=1 python3 -B test/test_room_mail_web_ui.py -v
|
||||
|
||||
- name: Upload Test Results
|
||||
# Upload test results even if the test step failed.
|
||||
@@ -499,3 +672,17 @@ jobs:
|
||||
with:
|
||||
name: test-results
|
||||
path: .pio/build/native/
|
||||
|
||||
hosted-doc-links:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: '3.13'
|
||||
- name: Install the documentation renderer
|
||||
run: python3 -m pip install mkdocs==1.6.1 mkdocs-material==9.7.7
|
||||
- name: Verify source links and published page routes
|
||||
run: python3 -B test/test_hosted_doc_links.py -v
|
||||
- name: Verify hosted-link visibility and navigation
|
||||
run: node test/test_hosted_doc_links.js
|
||||
+34
-1
@@ -137,6 +137,37 @@ acknowledged cleanly in about 11.7 seconds within its 21-second budget. The
|
||||
residual Section 1/Section 2 instance-pointer reads remain deferred, so those
|
||||
consumers can still touch live or torn-down bridge state as tracked above.
|
||||
|
||||
The 2026-10-10 connection-timeout fix restores the SDK network budget to
|
||||
10 seconds. The stop deadline now also allows the owner to finish one blocked
|
||||
publish and each client to finish a network operation: `5 s + 10 s +
|
||||
max(8 s, 10 s) * enabled_slots` (35 seconds for two slots). A clean
|
||||
acknowledgment still returns immediately. This deadline change is covered by
|
||||
synthetic tests; no new physical teardown measurement is claimed.
|
||||
|
||||
Connection admission reads SDK initialization and task-start state on the
|
||||
bridge owner task. `PsychicMqttClient::isInitialized()` reports whether its SDK
|
||||
handle still owns configuration, transport objects and MQTT buffers;
|
||||
`isStarted()` separately reports whether its SDK task is running. Callbacks
|
||||
change connection state but do not assign or clear the SDK handle.
|
||||
`MQTTConnectionAdmission::ClientMemoryState` uses those distinct lifetimes:
|
||||
uninitialized clients require 32 KiB free DMA heap and an 8 KiB block,
|
||||
initialized stopped clients require 24 KiB and an 8 KiB block, and started
|
||||
clients require 16 KiB and a 4 KiB block. The stopped-client allowance reserves
|
||||
8 KiB for recreating the explicit 6,144-byte SDK task stack plus TCB and
|
||||
allocator overhead while retaining the 16 KiB AES reserve. WiFi-loss shutdown
|
||||
still stops the SDK task and retains its handle; this admission distinction
|
||||
permits its restart without charging initialization buffers twice. A failed
|
||||
initialization that discards the SDK handle continues to use the full cold
|
||||
allowance. Internal-only TLS keeps its additional 60 KiB/17,408-byte thresholds.
|
||||
|
||||
All ESP32 clients use 896-byte MQTT buffers from their first initialization,
|
||||
including non-JWT slots on internal-only boards. The SDK does not resize those
|
||||
buffers when applying configuration, and the wrapper reassembly buffer also
|
||||
keeps its initial capacity. Uniform sizing therefore permits later JWT
|
||||
reconfiguration while retaining the client, its callbacks and the slot's token
|
||||
storage. Explicit reconfiguration and WiFi recovery keep the existing client
|
||||
lifetime; neither introduces deletion while Core 1 diagnostics may read it.
|
||||
|
||||
## Remaining target primitives
|
||||
|
||||
- **Task notifications or a command queue** for one-way lifecycle / reconfigure
|
||||
@@ -174,7 +205,9 @@ Phase 5 as a pure state machine plus a narrow injected `Ops` seam
|
||||
### Hardware characterization result
|
||||
|
||||
WSS teardown was measured as roughly 5-6 seconds per slot and is sequential.
|
||||
Production now sets the coordinator timeout to `5 s + 8 s * enabled_slots`.
|
||||
That characterization used the coordinator timeout `5 s + 8 s * enabled_slots`.
|
||||
The current deadline also includes the SDK network and blocked-publish budgets
|
||||
described above.
|
||||
Representative non-PSRAM and PSRAM start/stop matrices found no downward heap
|
||||
or largest-block trend; multi-day soak, task-stack high-water, and exhaustive
|
||||
callback ordering remain outside that run.
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
* **[Two LoRa profiles on one device](https://mikecarper.github.io/MeshCore/radio_profiles/).** Time-share one transceiver between two frequencies and/or modulation settings. Choose transmission profiles per contact or channel, enable or isolate crossover traffic, schedule profiles, and use a temporary update profile alongside the normal network. Includes timing calibration and separate R2 screen pages.
|
||||
* **[Firmware updates over LoRa](https://mikecarper.github.io/MeshCore/lora_ota_automation/).** Update repeaters, room servers, and sensors over LoRa on supported firmware and storage layouts.
|
||||
* **[Repeater forwarding policies](https://mikecarper.github.io/MeshCore/flood_filtering/).** Actions include dropping, rate limiting, assigning scopes, selecting retries, and controlling forwarding priority. Separate policies cover ordinary radio forwarding, bridges, and profile crossover.
|
||||
* **[Private fleet management](https://mikecarper.github.io/MeshCore/fleet_management/).** Deploy filtering, secondary-radio changes, radio schedules, and clock updates to a whole fleet, existing configured or home regions, a GPS center and radius, one node, or a semicolon-separated target list. The publisher signs each complete command once, splitting longer requests across two packets; receivers hold its public verification key, with replay protection and acknowledgements before radio handoff.
|
||||
* **[Flood retries that account for network topology](https://mikecarper.github.io/MeshCore/halo_keymind_settings/#flood-and-advert-settings).** Configure retry counts, path limits, packet-type limits, target prefixes, ignored repeaters, and channel-specific eligibility. Bridge buckets keep retrying until traffic is heard on the intended sides of a relay or the retry budget expires. Qualifying echoes cancel unnecessary attempts.
|
||||
* **[Enhanced direct messages and direct-route retries](https://mikecarper.github.io/MeshCore/halo_keymind_settings/#direct-retry-settings).** Adapt the coding rate across bounded retry attempts and cancel unnecessary retries when a qualifying echo is heard. [Single Key DMs](https://mikecarper.github.io/MeshCore/companion_protocol/#private-text-when-only-the-sender-knows-the-recipient) let compatible Companions send private text when only the sender knows the recipient's key, using a signed, encrypted introduction. The recipient accepts the sender through the app or opts into automatic acceptance; compact STM32WL builds omit this feature.
|
||||
* **[Enhanced direct messages and direct-route retries](https://mikecarper.github.io/MeshCore/halo_keymind_settings/#direct-retry-settings).** Adapt the coding rate across bounded retry attempts and cancel unnecessary retries when a qualifying echo is heard. [Single Key DMs](https://mikecarper.github.io/MeshCore/companion_protocol/#private-text-when-only-the-sender-knows-the-recipient) let compatible Companions send private text when only the sender knows the recipient's key, using a signed, encrypted introduction. The recipient accepts the sender through the app or opts into automatic acceptance; compact STM32WL builds omit this feature. An optional [Companion lost-status responder](https://mikecarper.github.io/MeshCore/companion_lost_reply/) answers private "Am I lost?" questions with a saved Yes or No.
|
||||
* **[Enhanced telemetry history](https://mikecarper.github.io/MeshCore/telemetry_decoder/).** Send compact temperature and battery-voltage snapshots of up to 165 samples per packet, plus external-voltage history in chunks. Read retained GPS history through the CLI; GPS history is not included in the automatic telemetry packets. Decode snapshots and CLI history in the browser.
|
||||
* **[Room topics, mailboxes, history, and access controls](https://mikecarper.github.io/MeshCore/room_services/).** Save an announcement and optionally retain the newest 32 chat posts across reboots. Regular users manage personal mailboxes with public or selected-sender access, explicit receipts, and mailbox-only delivery for sleeping trackers. Room users can manage their own return routes and skip older unread chat by date or keep the newest N messages. Explicit ACL roles persist; full-key bans and per-user post/request limits apply to room sessions. ESP32 images with WebConfig provide local Wi-Fi chat, an information board, and an admin dashboard for mailboxes, routes, delivery, activity, catch-up and access. The existing app's chat and catch-up formats remain supported.
|
||||
* **[Full firmware profiles, Companion transports, and ESP32 bridges](https://mikecarper.github.io/MeshCore/full_profiles/).** Full combines the exact board and role's supported features with runtime controls: Companion transports and firmware serving, or qualified ESP32 infrastructure services and MQTT/ESP-NOW/RS-232 bridges. Includes capacity exceptions, matching application slots, exact-board/role partition migration packages, and nRF52 Full/Reduced supported-sensor packages with LoRa OTA. The picker links supported migration routes; USB layout changes use the matching merged image, since an app-only image cannot change the partition table.
|
||||
* **[Operational reporting and alerts](https://mikecarper.github.io/MeshCore/management_reports/).** Adds optional management reports with firmware version, bootloader version, LoRa update capabilities, uptime, and historical voltage and temperature ranges.
|
||||
* **[Set time using the LoRa network](https://mikecarper.github.io/MeshCore/cli_commands/#estimate-and-correct-infrastructure-node-time-after-startup).** Infrastructure nodes can estimate time from fresh mesh evidence and correct their clocks when a consensus is available. Successful manual, GPS, or NTP synchronization takes precedence until reboot.
|
||||
@@ -72,7 +74,7 @@ For developers:
|
||||
|
||||
- Install [PlatformIO](https://docs.platformio.org) in [Visual Studio Code](https://code.visualstudio.com).
|
||||
- Clone and open the MeshCore repository in Visual Studio Code.
|
||||
- Install the pinned build-time compressors with `python -m pip install -r requirements-build.txt`.
|
||||
- Install the pinned build-time dependencies in PlatformIO's Python environment with `python -m pip install -r requirements-build.txt`.
|
||||
- See the example applications you can modify and run:
|
||||
- [Companion Radio](./examples/companion_radio) - For use with an external chat app, over BLE, USB or Wi-Fi.
|
||||
- [KISS Modem](./examples/kiss_modem) - Serial KISS protocol bridge for host applications. ([protocol docs](./docs/kiss_modem_protocol.md))
|
||||
|
||||
@@ -39,6 +39,13 @@ names, sizes and checksums before switching the catalogs. Regenerate the
|
||||
downloadable picker from the same family and update its checksum on every
|
||||
page. Documentation-only follow-up commits do not move firmware tags.
|
||||
|
||||
Include the [1.17.1.9 release notes](docs/releases/1.17.1.9.md) and
|
||||
[1.17.1.8 WiFi upgrade guide](docs/upgrading_1.17.1.8_to_1.17.1.9.md) in the
|
||||
publication review. Replace the release notes' final package-validation gate
|
||||
with the completed inventory only after packaging passes. Keep the firmware
|
||||
source separate from a later documentation-only commit, and retain the
|
||||
measured hardware scope and old-updater completion limitation.
|
||||
|
||||
For the USA Cascade 1.17.1.5 matrix, use
|
||||
[the option 3 release instructions](docs/old-releases/1.17.1.5.md).
|
||||
Package the qualified outputs with `scripts/package_cascade_release.py`.
|
||||
|
||||
+18
-12
@@ -3835,18 +3835,13 @@ apply_nrf52_size_profile() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
# The Adafruit nRF52 platform defaults release builds to -Ofast. Once the
|
||||
# runtime software Ed25519 fallback is linked alongside CC310, that setting
|
||||
# fully expands repeated Curve25519 arithmetic and wastes tens of kilobytes.
|
||||
# Keep hardware crypto, RNG mixing, the software fallback, and board features;
|
||||
# select the size optimizer for repeaters, constrained self-updating images
|
||||
# and Full Companion source images, especially their diagnostic profile.
|
||||
# Full-sensor repeaters also need this after adding the second radio profile;
|
||||
# changing optimization preserves their sensors and protocol features.
|
||||
# The legacy RAK4631 Ethernet Companion also needs -Os to fit its declared
|
||||
# application limit; keep its sensors, transports, OTA and layout unchanged.
|
||||
# The framework defaults to -Ofast, which expands repeated Curve25519
|
||||
# arithmetic when software Ed25519 is linked alongside CC310. Inherit the
|
||||
# canonical nrf52_base -Oz optimizer rather than appending a weaker -Os
|
||||
# override for repeaters, Full Companion, Ethernet, and constrained OTA
|
||||
# recipes. Keep hardware crypto, software fallback, sensors, transports,
|
||||
# OTA, the 8 KiB loop stack, and each board's application/storage layout.
|
||||
append_platformio_build_unflags "-Ofast"
|
||||
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -Os"
|
||||
|
||||
# These color-display repeaters reserve a 64 KiB reset-retained OTA arena
|
||||
# plus a 25 KiB framebuffer. With the 8 KiB loop stack, the complete sensor
|
||||
@@ -4180,6 +4175,9 @@ apply_companion_radio_full_profile() {
|
||||
# Apply the proven bootstrap to every nRF52 Full Companion rather than
|
||||
# making a board-specific Bluetooth reliability promise.
|
||||
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -DOTA_FOLDER_SERIAL=1 -DCOMPANION_FEATURE_USB_MOTA_SOURCE=1 -DCOMPANION_FEATURE_BLE_MOTA_SOURCE=1 -DMESH_DEBUG=1 -DMESH_PACKET_LOGGING=1 -DCFG_DEBUG=1 -DRECOVERABLE_EXTERNAL_RADIO=1"
|
||||
# Lossless name compression retains every seeder target and its wire ID
|
||||
# while recovering flash headroom; reuse the existing bounded OTA decoder.
|
||||
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -DOTA_TARGET_NAME_FRONT_CODED=1"
|
||||
if [ "$env_name" = "t1000e_companion_radio_full" ]; then
|
||||
# The T1000-E's primary CDC transport is the only USB interface. Its
|
||||
# `usb.logging on` selects an input-capable ASCII logging terminal on
|
||||
@@ -4194,7 +4192,7 @@ apply_companion_radio_full_profile() {
|
||||
# Every nRF52 Full Companion lends the upper half of its offline queue
|
||||
# to the cold mOTA context. Keep 256 slots for everyday use and reserve
|
||||
# runtime space for Bluetooth, displays, tasks and filesystem buffers.
|
||||
append_platformio_build_unflags "-DOFFLINE_QUEUE_SIZE=512 -DOFFLINE_QUEUE_SIZE=128 -DOFFLINE_QUEUE_SIZE=16"
|
||||
append_platformio_build_unflags "-DOFFLINE_QUEUE_SIZE=512 -DOFFLINE_QUEUE_SIZE=240 -DOFFLINE_QUEUE_SIZE=128 -DOFFLINE_QUEUE_SIZE=16"
|
||||
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -DOFFLINE_QUEUE_SIZE=256 -DOTA_SHARED_COMPANION_QUEUE=1"
|
||||
case "$env_name" in
|
||||
Heltec_t096_companion_radio_full_*)
|
||||
@@ -4475,6 +4473,11 @@ write_build_capability_manifest() {
|
||||
|| is_xiao_qspi_canonical_repeater_build "$env_name"; then
|
||||
checker_args+=(--require-ota)
|
||||
fi
|
||||
if [ "$env_name" = "RAK_4631_companion_radio_full" ]; then
|
||||
# This profile is offered for MeshTalk testing. Check executable codec and
|
||||
# Companion transport definitions, not a channel name or CLI help string.
|
||||
checker_args+=(--require-meshtext)
|
||||
fi
|
||||
if [ "$env_platform" = "ESP32_PLATFORM" ]; then
|
||||
checker_args+=(--firmware-bin "${build_output_dir}/firmware.bin"
|
||||
--partitions "${build_output_dir}/partitions.bin")
|
||||
@@ -4745,6 +4748,9 @@ collect_build_artifacts() {
|
||||
;;
|
||||
esac
|
||||
|
||||
python3 scripts/package_meshtext_license.py collect "$build_output_dir" \
|
||||
--stem "${OUTPUT_DIR}/${firmware_filename}" || return $?
|
||||
|
||||
python3 scripts/firmware_memory_manifest.py package "$build_output_dir" \
|
||||
--stem "${OUTPUT_DIR}/${firmware_filename}" || return $?
|
||||
}
|
||||
|
||||
+82
-9
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/WiFi/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# WiFi and MQTT by Firmware Type
|
||||
|
||||
MeshCore itself does not require WiFi or the internet. LoRa packet exchange,
|
||||
@@ -98,6 +102,32 @@ best effort rather than durable storage. Each enabled slot publishes
|
||||
independently, so one failed broker does not intentionally stop the other
|
||||
slots.
|
||||
|
||||
## Automatic network outage power saving
|
||||
|
||||
ESP32 MQTT firmware uses one shared outage timer for MQTT and NTP. If no broker
|
||||
demonstrates a working connection for five minutes, the MQTT worker stops its
|
||||
clients and NTP request before suspending background WiFi. Saved WiFi and broker
|
||||
settings remain enabled. Failed requests, a WiFi association, and NTP replies
|
||||
alone do not restart the outage timer or keep a failed MQTT uplink awake.
|
||||
|
||||
After 30 minutes, the firmware opens a recovery window lasting up to two
|
||||
minutes. A broker acknowledgment or a connection that stays up for 30 seconds
|
||||
returns the node to normal operation. Otherwise WiFi is suspended for another
|
||||
30 minutes. An explicit management request can ask for an earlier probe.
|
||||
Automatic NTP requests have a 15-second timeout; failed requests wait 30 minutes
|
||||
instead of repeatedly running a blocking server search. Successful NTP retains
|
||||
the daily refresh schedule.
|
||||
|
||||
Active browser administration, setup/OTA access points, connected Companion
|
||||
clients, and an attached WiFi OTA seeder protect their network access. An idle
|
||||
WebConfig listener does not prevent the cooldown. An enabled SNMP agent keeps a
|
||||
working LAN connection available. ESP-NOW keeps its radio and channel; only the
|
||||
failed infrastructure connection is suspended. LoRa continues operating, and
|
||||
when CPU power saving is enabled, its normal sleep eligibility returns after
|
||||
background WiFi shuts down. USB console and logging sleep rules still apply
|
||||
separately. This policy does not automatically turn off working services or
|
||||
expire an active setup access point.
|
||||
|
||||
See [MQTT_IMPLEMENTATION.md](https://github.com/mikecarper/MeshCore/blob/keymindCascade/MQTT_IMPLEMENTATION.md) for the complete preset
|
||||
list, custom broker configuration, topic formats, authentication, diagnostics,
|
||||
and memory limits.
|
||||
@@ -159,8 +189,35 @@ reboot
|
||||
```
|
||||
|
||||
The SSID and password values are the rest of the command line. Spaces are
|
||||
allowed and quotes must not be added. SSIDs may contain at most 31 characters
|
||||
and passwords at most 63. Leave the password value empty for an open network.
|
||||
allowed and quotes must not be added. SSIDs may contain at most 31 characters.
|
||||
ESP32 infrastructure MQTT builds with WebConfig share one canonical WiFi
|
||||
configuration between this CLI and the browser portal. Passwords accept
|
||||
0-63 characters or exactly 64 hexadecimal characters for a raw WPA PSK.
|
||||
Leave the password value empty for an open network. Reboot after changing
|
||||
credentials to apply them; an already-running MQTT worker keeps its current
|
||||
connection settings until it stops and restarts.
|
||||
|
||||
Older observer-only credentials remain usable until canonical WiFi settings
|
||||
are saved. The first CLI edit preserves the other legacy credential while
|
||||
saving the complete pair. Once canonical settings exist, empty, incomplete or
|
||||
unreadable canonical settings do not revive old observer credentials. Historical
|
||||
SSID-only canonical settings continue to represent an open network. Builds
|
||||
without this WebConfig integration retain their legacy 63-character password
|
||||
limit; this change does not add MQTT support to currently disabled Pico targets.
|
||||
|
||||
On these ESP32 MQTT/WebConfig builds, an empty CLI SSID clears the configured
|
||||
network while retaining saved broker settings:
|
||||
|
||||
```text
|
||||
set wifi.ssid
|
||||
reboot
|
||||
```
|
||||
|
||||
Use this to return the node to unconfigured provisioning. The WebConfig setup
|
||||
form still requires a nonempty SSID. After saving a new network, verify
|
||||
`get wifi.status`, `get mqtt.config.valid` and `get mqtt.running`; credentials
|
||||
alone do not prove a broker connection. A local `get wifi.pwd` can inspect the
|
||||
password, while an authenticated remote command returns only set/unset.
|
||||
|
||||
Useful checks are:
|
||||
|
||||
@@ -192,8 +249,9 @@ set mqtt.enabled off
|
||||
start webconfig ap
|
||||
```
|
||||
|
||||
After provisioning, use **Save & Reboot**, or stop the temporary portal and
|
||||
restart the bridge:
|
||||
After changing WiFi credentials, use **Save & Reboot** or `reboot`. For
|
||||
broker-only changes that keep the existing network, stop the temporary portal
|
||||
and restart the bridge:
|
||||
|
||||
```text
|
||||
stop webconfig
|
||||
@@ -307,6 +365,15 @@ modem sleep can miss ESP-NOW broadcasts; use `min` for coexistence. The primary
|
||||
mesh transport holds the driver's RF wake reference continuously, so `min`
|
||||
does not suspend its ESP-NOW receiver.
|
||||
|
||||
Espressif long-range WiFi (LR) trades speed for reach: its raw rates are
|
||||
250 or 500 kbit/s, with up to about 1 km in suitable line-of-sight conditions.
|
||||
LR traffic needs compatible Espressif hardware at both ends. An LR-enabled
|
||||
access point sends LR beacons that ordinary phones, routers and Raspberry Pis
|
||||
cannot receive. A mixed b/g/n+LR station can still join an ordinary router,
|
||||
using normal WiFi rates for that connection. MeshCore's setup and OTA access
|
||||
points therefore use ordinary b/g/n. See
|
||||
[Espressif's LR compatibility guide](https://docs.espressif.com/projects/esp-idf/en/v4.4.7/esp32s3/api-guides/wifi.html#long-range-lr).
|
||||
|
||||
ESP-NOW compatibility also depends on the bytes and PHY used above the common
|
||||
Espressif transport. The historical `*_repeater_bridge_espnow` firmware wraps
|
||||
each MeshCore packet with a magic value, checksum, and secret-based XOR, while
|
||||
@@ -423,6 +490,11 @@ direct browser uploader on HTTP port 80. A FULL role without WebConfig but with
|
||||
browser OTA support can use the `MeshCore-OTA` access point raised by
|
||||
`start ota`; its seeder address is `192.168.4.1:5001`.
|
||||
|
||||
For browser uploads from an existing 1.17.1.8 ESP32 node, see the
|
||||
[1.17.1.9 WiFi upgrade guide](upgrading_1.17.1.8_to_1.17.1.9.md).
|
||||
It covers the node AP, old-page completion behavior, and choosing an
|
||||
application-only image or the exact partition-migration package.
|
||||
|
||||
Only one external folder link can be active. A TCP client is rejected while
|
||||
`ota folder on` is using USB serial, and disconnecting `motatool` automatically
|
||||
removes the TCP folder. Port 5001 has no login layer, so expose it only on a
|
||||
@@ -675,11 +747,12 @@ Common causes are:
|
||||
For a WiFi companion, find its station IP in the router, connect the client to
|
||||
TCP port 5000, and use the open `MeshCore-Setup-XXXX` AP at
|
||||
`http://192.168.4.1/` if it cannot join the saved network. Current firmware
|
||||
normalizes both ESP32 WiFi interfaces to standard b/g/n before advertising the
|
||||
setup AP. Full Companion targets whose primary mesh radio is ESP-NOW use
|
||||
b/g/n+LR instead and keep the setup AP, infrastructure station, and mesh on the
|
||||
persisted `espnow.channel` (channel 1 by default). Their configured 2.4 GHz
|
||||
router and every other primary ESP-NOW node must use that same channel.
|
||||
uses standard b/g/n for the setup AP, including ESP-NOW-capable targets.
|
||||
A running LR mesh conflicts with a conventional access point; current firmware
|
||||
refuses that AP startup and defers LR startup while an AP is active. A primary
|
||||
ESP-NOW target keeps its infrastructure station and mesh on the persisted
|
||||
`espnow.channel` (channel 1 by default). Its configured 2.4 GHz router and every
|
||||
other primary ESP-NOW node must use that same channel.
|
||||
MQTT-capable Companions also accept `get mqtt.enabled`, `get mqtt.running`,
|
||||
and `get mqtt.status` in their USB/TCP and browser terminals. Extended slot
|
||||
and NTP diagnostics remain infrastructure features.
|
||||
+5639
-4151
File diff suppressed because it is too large.
Load diff
@@ -23,6 +23,11 @@
|
||||
]);
|
||||
|
||||
const FACET_FIELDS = Object.freeze(FILTER_FIELDS.concat(["install"]));
|
||||
// Versioned picker selections stay self-contained as release catalogs change.
|
||||
const SHORT_SELECTION_FIELDS = Object.freeze({
|
||||
c: "chipFamily", g: "hardwareFamily", h: "hardware", r: "role",
|
||||
l: "logging", o: "ota", m: "mode", f: "feature", v: "variant", i: "install",
|
||||
});
|
||||
const PROFILE_FIELDS = Object.freeze(["ota", "feature", "variant"]);
|
||||
const CHOICE_FIELDS = Object.freeze([
|
||||
"chipFamily", "hardwareFamily", "hardware", "role", "logging",
|
||||
@@ -482,6 +487,11 @@
|
||||
if (/^RAK_(?:3401|4631)_repeater_unified_lora_ota(?:-(?:full|reduced)(?:-ota)?)?$/i.test(target)) {
|
||||
variant = "default";
|
||||
}
|
||||
if (/^RAK_4631_repeater_ethernet(?:-(?:full|reduced)(?:-ota)?)?$/i.test(target)) {
|
||||
// The RAK13800 Ethernet image is a real hardware choice, separate from
|
||||
// adaptive storage. Label it consistently for both sensor policies.
|
||||
variant = "ethernet";
|
||||
}
|
||||
if (sourceHardware === "Station_G2_logging") {
|
||||
variant = variant === "default"
|
||||
? "rx-boosted"
|
||||
@@ -571,11 +581,13 @@
|
||||
heltec_t096_repeater_bridge_rs232_lora_ota_no_external_sensors:
|
||||
"heltec_t096_repeater_lora_ota_no_external_sensors",
|
||||
rak_4631_repeater_bridge_rs232_serial1_lora_ota_no_external_sensors:
|
||||
"rak_4631_repeater_lora_ota_no_external_sensors",
|
||||
["rak_4631_repeater_unified_lora_ota", "rak_4631_repeater_lora_ota_no_external_sensors"],
|
||||
rak_4631_repeater_bridge_rs232_serial2_lora_ota_no_external_sensors:
|
||||
"rak_4631_repeater_lora_ota_no_external_sensors",
|
||||
rak_4631_repeater_bridge_rs232_serial1: "rak_4631_repeater",
|
||||
rak_4631_repeater_bridge_rs232_serial2: "rak_4631_repeater",
|
||||
["rak_4631_repeater_unified_lora_ota", "rak_4631_repeater_lora_ota_no_external_sensors"],
|
||||
rak_4631_repeater_bridge_rs232_serial1:
|
||||
["rak_4631_repeater_unified_lora_ota", "rak_4631_repeater"],
|
||||
rak_4631_repeater_bridge_rs232_serial2:
|
||||
["rak_4631_repeater_unified_lora_ota", "rak_4631_repeater"],
|
||||
promicro_repeater_bridge_rs232_serial1: "promicro_repeater",
|
||||
heltec_t114_without_display_repeater_bridge_rs232:
|
||||
"heltec_t114_without_display_repeater",
|
||||
@@ -603,11 +615,19 @@
|
||||
combinedUsbBleKeys.has(key);
|
||||
const replacedTerminal = profile.role === "terminal" &&
|
||||
terminalReplacementKeys.has(key);
|
||||
const rs232Replacement = mergedRs232Targets[
|
||||
String(profile.target || "").toLowerCase()
|
||||
];
|
||||
const target = String(profile.target || "").toLowerCase();
|
||||
const sensorSuffix = (target.match(/-(?:full|reduced)$/) || [""])[0];
|
||||
const baseTarget = sensorSuffix ? target.slice(0, -sensorSuffix.length) : target;
|
||||
const rs232Replacement = mergedRs232Targets[baseTarget];
|
||||
// Recommendations prefer the combined UART2 image on RAK4631. Exact
|
||||
// Serial1 files remain in raw rows for existing GPS-free installations;
|
||||
// this preference does not migrate their wiring or OTA identity.
|
||||
// Preserve the exact sensor policy: a Full image does not replace a
|
||||
// missing Reduced image, or an older unsuffixed compatibility image.
|
||||
const replacedRs232 = Boolean(rs232Replacement &&
|
||||
targets.has(rs232Replacement));
|
||||
[].concat(rs232Replacement).some(function (replacement) {
|
||||
return targets.has(replacement + sensorSuffix);
|
||||
}));
|
||||
return !(replacedAttachedTransport && fullKeys.has(key)) &&
|
||||
!replacedByUsbBle && !replacedTerminal && !replacedRs232;
|
||||
});
|
||||
@@ -644,8 +664,8 @@
|
||||
}));
|
||||
return (profiles || []).filter(function (profile) {
|
||||
const target = String(profile && profile.target || "").toLowerCase();
|
||||
const match = /^rak_(3401|4631)_repeater_(?:lora_ota_no_external_sensors|w25q16_lora_ota|rak15001_slot_c_lora_ota|rak13302_w25q16_lora_ota)$/.exec(target);
|
||||
return !match || !targets.has("rak_" + match[1] + "_repeater_unified_lora_ota");
|
||||
const match = /^rak_(3401|4631)_repeater_(?:lora_ota_no_external_sensors|w25q16_lora_ota|rak15001_slot_c_lora_ota|rak13302_w25q16_lora_ota)(-(?:full|reduced))?$/.exec(target);
|
||||
return !match || !targets.has("rak_" + match[1] + "_repeater_unified_lora_ota" + (match[2] || ""));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -668,10 +688,7 @@
|
||||
function applyMergedRak4631RepeaterCapabilities(profiles) {
|
||||
return (profiles || []).map(function (profile) {
|
||||
const target = String(profile && profile.target || "").toLowerCase();
|
||||
if (
|
||||
target !== "rak_4631_repeater" &&
|
||||
target !== "rak_4631_repeater_lora_ota_no_external_sensors"
|
||||
) {
|
||||
if (!/^rak_4631_repeater(?:_lora_ota_no_external_sensors|_unified_lora_ota)?(?:-(?:full|reduced))?$/.test(target)) {
|
||||
return profile;
|
||||
}
|
||||
|
||||
@@ -1195,6 +1212,7 @@
|
||||
|
||||
function selectionUrl(url, filters, automaticChipFamily) {
|
||||
const result = new URL(url);
|
||||
result.searchParams.delete("s");
|
||||
FACET_FIELDS.forEach(function (field) {
|
||||
result.searchParams.delete(field);
|
||||
if (filters[field]) result.searchParams.set(field, filters[field]);
|
||||
@@ -1206,8 +1224,61 @@
|
||||
return result.href;
|
||||
}
|
||||
|
||||
function shortSelectionUrl(url, filters, automaticChipFamily) {
|
||||
const result = new URL(url);
|
||||
FACET_FIELDS.concat(["chipAuto", "s"]).forEach(function (field) {
|
||||
result.searchParams.delete(field);
|
||||
});
|
||||
const parts = ["1"];
|
||||
Object.keys(SHORT_SELECTION_FIELDS).forEach(function (key) {
|
||||
const field = SHORT_SELECTION_FIELDS[key];
|
||||
const value = filters[field];
|
||||
if (!value || (field === "chipFamily" && automaticChipFamily) ||
|
||||
(field === "hardwareFamily" && value === filters.hardware)) return;
|
||||
// Dots delimit fields; escape them even though encodeURIComponent does not.
|
||||
parts.push(key + encodeURIComponent(value).replace(/\./g, "%2E"));
|
||||
});
|
||||
if ((filters.hardwareFamily || filters.hardware) && !automaticChipFamily) {
|
||||
parts.push("a0");
|
||||
}
|
||||
if (parts.length > 1) result.searchParams.set("s", parts.join("."));
|
||||
return result.href;
|
||||
}
|
||||
|
||||
function shortSelectionParams(params) {
|
||||
const parts = params.get("s").split(".");
|
||||
const result = new URLSearchParams();
|
||||
if (params.getAll("s").length !== 1 || parts.shift() !== "1" || !parts.length) {
|
||||
throw new Error("unsupported or incomplete short picker link");
|
||||
}
|
||||
const seen = new Set();
|
||||
parts.forEach(function (part) {
|
||||
const key = part.charAt(0);
|
||||
if (seen.has(key) || (key !== "a" &&
|
||||
!Object.prototype.hasOwnProperty.call(SHORT_SELECTION_FIELDS, key))) {
|
||||
throw new Error("duplicate or unknown short picker field");
|
||||
}
|
||||
seen.add(key);
|
||||
const value = decodeURIComponent(part.slice(1));
|
||||
if (!value || (key === "a" && value !== "0" && value !== "1")) {
|
||||
throw new Error("invalid short picker field");
|
||||
}
|
||||
result.set(key === "a" ? "chipAuto" : SHORT_SELECTION_FIELDS[key], value);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function selectionFromUrl(url, profiles) {
|
||||
const params = new URL(url).searchParams;
|
||||
let params = new URL(url).searchParams;
|
||||
if (params.has("s")) {
|
||||
try {
|
||||
// The versioned selection is authoritative over any legacy fields.
|
||||
params = shortSelectionParams(params);
|
||||
} catch (error) {
|
||||
return { filters: {}, automaticChipFamily: false,
|
||||
unavailable: ["short link: " + error.message] };
|
||||
}
|
||||
}
|
||||
const requested = {};
|
||||
const filters = {};
|
||||
const unavailable = [];
|
||||
@@ -1667,6 +1738,11 @@
|
||||
if (profile.role === "repeater") toggle("Repeat mesh traffic", "set repeat", "get repeat");
|
||||
if (info.rs232 && infrastructure) {
|
||||
const mode = chosen.mode;
|
||||
const uartNote = /^RAK_4631_repeater_unified_lora_ota-(?:full|reduced)$/i.test(profile.target) && profile.sensorProfile
|
||||
? "Unified RAK4631 uses UART2 for the RS-232 bridge; select it with set bridge.uart 2 while the bridge is stopped. GPS safety guards reserve UART1 even when no GPS was detected. Use UART2 for new installations. Legacy Serial1 downloads remain available by exact filename for existing GPS-free wiring."
|
||||
: /^RAK_4631_repeater_bridge_rs232_serial1(?:_lora_ota_no_external_sensors)?-(?:full|reduced)$/i.test(profile.target)
|
||||
? "This GPS-free Serial1 image uses UART1. Do not fit a powered UART GPS or header-connected W25 flash on the same UART1 pins. Use the unified UART2 image when those pins are occupied."
|
||||
: "Use the UART and pin map for this exact board. Canonical GPS-enabled RAK4631 uses UART2; select it with set bridge.uart 2 while the bridge is stopped. UART1 needs a compatible GPS-free image.";
|
||||
// MQTT images keep the historical bridge.enabled ESP-NOW alias.
|
||||
// Their independently saved UART uses the transport-specific controls.
|
||||
const uartSetting = info.mqtt ? "rs232.enabled" : "bridge.enabled";
|
||||
@@ -1677,7 +1753,7 @@
|
||||
{ label: "Set baud", commands: ["set " + uartSetting + " off", "set bridge.baud 115200", "set " + uartSetting + " on"] },
|
||||
].sort(function (a, b) {
|
||||
return mode === "standard" ? Number(b.label === "Off") - Number(a.label === "Off") : 0;
|
||||
}), "Use the UART and pin map for this exact board. Canonical GPS-enabled RAK4631 uses UART2; select it with set bridge.uart 2 while the bridge is stopped. UART1 needs a compatible GPS-free image.");
|
||||
}), uartNote);
|
||||
}
|
||||
if (info.espnowBridge && infrastructure) {
|
||||
// Combined images need the transport-specific switch: bridge.enabled
|
||||
@@ -1935,7 +2011,7 @@
|
||||
}
|
||||
|
||||
function updateSelectionUrl() {
|
||||
const url = selectionUrl(global.location.href, filters, automaticChipFamily);
|
||||
const url = shortSelectionUrl(global.location.href, filters, automaticChipFamily);
|
||||
if (url !== global.location.href) {
|
||||
try {
|
||||
global.history.replaceState(global.history.state, "", url);
|
||||
@@ -1945,9 +2021,11 @@
|
||||
}
|
||||
}
|
||||
if (shareLink) {
|
||||
const base = global.location.protocol === "file:"
|
||||
? root.getAttribute("data-share-url") : url;
|
||||
shareLink.href = selectionUrl(base || url, filters, automaticChipFamily);
|
||||
const base = new URL(global.location.protocol === "file:"
|
||||
? root.getAttribute("data-share-url") || url : url);
|
||||
base.pathname = base.pathname.replace(/\/firmware_picker\/$/, "/p/");
|
||||
if (global.location.protocol === "file:") base.hash = global.location.hash;
|
||||
shareLink.href = shortSelectionUrl(base.href, filters, automaticChipFamily);
|
||||
shareLink.hidden = false;
|
||||
}
|
||||
if (copyLinkButton) copyLinkButton.disabled = false;
|
||||
@@ -1970,13 +2048,13 @@
|
||||
if (copyLinkButton && shareLink) copyLinkButton.addEventListener("click", function () {
|
||||
const copy = global.navigator.clipboard && global.navigator.clipboard.writeText;
|
||||
if (!copy) {
|
||||
linkStatus.textContent = "Copy the address bar, or copy the 'Link to these settings' link.";
|
||||
linkStatus.textContent = "Copy the address bar, or copy the 'Short link to these settings' link.";
|
||||
return;
|
||||
}
|
||||
global.navigator.clipboard.writeText(shareLink.href).then(function () {
|
||||
linkStatus.textContent = "Link copied.";
|
||||
}).catch(function () {
|
||||
linkStatus.textContent = "Copy the address bar, or copy the 'Link to these settings' link.";
|
||||
linkStatus.textContent = "Copy the address bar, or copy the 'Short link to these settings' link.";
|
||||
});
|
||||
});
|
||||
global.addEventListener("popstate", restoreSelectionUrl);
|
||||
@@ -2496,6 +2574,7 @@
|
||||
choicesUseSameFirmware: choicesUseSameFirmware,
|
||||
selectionRequirements: selectionRequirements,
|
||||
selectionUrl: selectionUrl,
|
||||
shortSelectionUrl: shortSelectionUrl,
|
||||
selectionFromUrl: selectionFromUrl,
|
||||
canonicalAsset: canonicalAsset,
|
||||
resolveProfileAssets: resolveProfileAssets,
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/* Source links help GitHub readers; the hosted page is already their destination. */
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
const hostedHostname = "mikecarper.github.io";
|
||||
const bannerSelector = ".meshcore-hosted-doc-link";
|
||||
|
||||
function hideHostedDocLinks(doc, hostname) {
|
||||
if (hostname !== hostedHostname) return 0;
|
||||
const banners = doc.querySelectorAll(bannerSelector);
|
||||
for (const banner of banners) banner.hidden = true;
|
||||
return banners.length;
|
||||
}
|
||||
|
||||
if (typeof module === "object" && module.exports) {
|
||||
module.exports = { hideHostedDocLinks };
|
||||
}
|
||||
if (typeof window === "undefined" || typeof document === "undefined") return;
|
||||
|
||||
const hide = function () {
|
||||
hideHostedDocLinks(document, window.location.hostname);
|
||||
};
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", hide, { once: true });
|
||||
} else {
|
||||
hide();
|
||||
}
|
||||
// Material can replace article content without loading the page again.
|
||||
if (typeof document$ !== "undefined" && document$ && typeof document$.subscribe === "function") {
|
||||
document$.subscribe(hide);
|
||||
}
|
||||
})();
|
||||
@@ -17,6 +17,59 @@
|
||||
const METERS_PER_DEGREE = 111320;
|
||||
const DEGREES_TO_RADIANS = Math.PI / 180;
|
||||
|
||||
// Keep the browser form out of GitHub's Markdown preview.
|
||||
const DECODER_MARKUP = `
|
||||
<div class="telemetry-examples" aria-label="Load an example reply">
|
||||
<strong>Try an analyzer example:</strong>
|
||||
<button type="button" data-telemetry-example="packetTemperature">Temperature packet</button>
|
||||
<button type="button" data-telemetry-example="packetVoltage">Voltage packet</button>
|
||||
<button type="button" data-telemetry-example="packetExternalVoltage">I2C voltage packet</button>
|
||||
<button type="button" data-telemetry-example="externalVoltage">I2C voltage CLI page</button>
|
||||
</div>
|
||||
|
||||
<label for="telemetry-reply-input">Raw packet or payload hex</label>
|
||||
<textarea
|
||||
id="telemetry-reply-input"
|
||||
data-role="input"
|
||||
spellcheck="false"
|
||||
autocomplete="off"
|
||||
placeholder="Paste hexadecimal Raw Data from the analyzer packet page"
|
||||
aria-describedby="telemetry-input-help"
|
||||
></textarea>
|
||||
<p class="telemetry-tool-help" id="telemetry-input-help">
|
||||
Spaces, line breaks, colons, dashes, a leading <code>0x</code>, and a quoted
|
||||
JSON field are accepted. CLI Base64 replies are also auto-detected. Paste
|
||||
multiple compatible packet or reply lines together to merge them by
|
||||
timestamp before downloading one CSV. Press Ctrl/Command+Enter to decode.
|
||||
</p>
|
||||
|
||||
<div class="telemetry-actions">
|
||||
<button class="telemetry-primary-action" type="button" data-role="decode">Decode telemetry</button>
|
||||
<button type="button" data-role="clear">Clear</button>
|
||||
<label class="telemetry-local-time">
|
||||
<input type="checkbox" data-role="local-time">
|
||||
Show browser-local time
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="telemetry-error" data-role="error" role="alert" aria-live="polite" hidden></div>
|
||||
|
||||
<section class="telemetry-results" data-role="results" aria-live="polite" hidden>
|
||||
<div class="telemetry-results-header">
|
||||
<h2 data-role="result-title">Decoded telemetry</h2>
|
||||
<button type="button" data-role="download">Download CSV</button>
|
||||
</div>
|
||||
<dl class="telemetry-summary" data-role="summary"></dl>
|
||||
<div class="telemetry-warnings" data-role="warnings" hidden>
|
||||
<strong>Decode notes</strong>
|
||||
<ul data-role="warning-list"></ul>
|
||||
</div>
|
||||
<div class="telemetry-table-wrap">
|
||||
<table class="telemetry-table" data-role="table"></table>
|
||||
</div>
|
||||
</section>
|
||||
`;
|
||||
|
||||
const EXAMPLES = Object.freeze({
|
||||
packetTemperature: Object.freeze({
|
||||
label: "Analyzer temperature packet",
|
||||
@@ -976,6 +1029,9 @@
|
||||
const root = document.querySelector("[data-telemetry-decoder]");
|
||||
if (!root) return;
|
||||
|
||||
// This is trusted, static markup; pasted telemetry is rendered as text below.
|
||||
root.innerHTML = DECODER_MARKUP;
|
||||
|
||||
const input = root.querySelector("[data-role='input']");
|
||||
const decodeButton = root.querySelector("[data-role='decode']");
|
||||
const clearButton = root.querySelector("[data-role='clear']");
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/bootloader_version_stock_audit/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/bootloader_version_stock_audit/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/cad_scan_validation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/cad_scan_validation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,5 +1,187 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/carrier_wave/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Carrier-wave RF checks
|
||||
|
||||
## TX-only Morse messages
|
||||
|
||||
Morse TX mode keys an unmodulated carrier into dots and dashes. It does not send
|
||||
LoRa packets or automatically retransmit channel chat or
|
||||
private messages. **The default is 902.100 MHz at 25 words per minute (WPM).**
|
||||
Nothing transmits until an explicit `morse send` command is accepted.
|
||||
|
||||
| Command | Action |
|
||||
| --- | --- |
|
||||
| `morse send TEST DE N0CALL` | Send the text once using the saved Morse frequency and speed. |
|
||||
| `morse stop` | Stop Morse immediately and restore packet reception. |
|
||||
| `get morse` | Show idle/active state, frequency, WPM and remaining time. |
|
||||
| `get morse.freq` | Show the Morse TX frequency in MHz. |
|
||||
| `set morse.freq 902.100` | Save the separate Morse TX frequency, rounded to 1 kHz. |
|
||||
| `get morse.wpm` | Show the saved sending speed. |
|
||||
| `set morse.wpm 12` | Slow transmission for easier hand decoding; supported range is 1–60 WPM. |
|
||||
|
||||
The default 25 WPM can be changed; for an easy-to-copy test, set 10–12 WPM.
|
||||
Standard timing uses one unit for a dot, three for a dash, one between elements,
|
||||
three between letters and seven between words, with a dot of `1200 / WPM`
|
||||
milliseconds. Letters are sent case-insensitively. Messages are bounded to
|
||||
80 ASCII characters, must contain supported Morse characters, and must fit
|
||||
within 180 seconds at the chosen speed. Supported punctuation is
|
||||
`. , ? ' ! / ( ) & : ; = + - _ " $ @`; tabs, newlines and non-ASCII text are
|
||||
rejected. Invalid messages are rejected before
|
||||
the transmitter is keyed. There is no automatic callsign insertion.
|
||||
|
||||
The Morse frequency is independent of `radio`, `tempradio`, `radio2` and
|
||||
`tempradio2`. Before sending, the firmware rejects a frequency that overlaps
|
||||
either packet-radio profile, including a guard outside its occupied bandwidth.
|
||||
It does **not** automatically find another channel or change your mesh settings.
|
||||
Choose another `morse.freq` if 902.100 MHz overlaps either profile. A frequency
|
||||
accepted as a saved value must still be supported by the actual radio at send
|
||||
time. Morse frequency/speed changes are rejected while Morse or CW is active.
|
||||
|
||||
There is one physical transceiver: packet reception and transmission pause
|
||||
throughout the message, including the spaces between dots and dashes. Normal
|
||||
receive/profile scanning is restored afterward. Use local USB/BLE for immediate
|
||||
status and stopping; a reply to a remote LoRa CLI command waits until the
|
||||
message finishes. Changing either packet profile during Morse can abort it to
|
||||
preserve the frequency-separation safety checks.
|
||||
|
||||
An unmodulated carrier has no selectable LoRa bandwidth. This uses native CW
|
||||
on SX1262/SX1268/LLCC68/STM32WLx and LR1110/LR1121/LR2021 radios, and
|
||||
zero-deviation FSK CW on SX1276-family radios with reset/recovery support, rather
|
||||
than pretending the narrowest receive filter sets the transmitted bandwidth.
|
||||
Morse sidebands depend on keying speed and transmitter edges. This is not a
|
||||
guarantee of a particular occupied RF bandwidth or freedom from interference.
|
||||
Unsupported radios reject the command without beginning transmission.
|
||||
The chips' configured TX ramps use 3400 microseconds on the SX126x-family and
|
||||
304 microseconds on the LR-family to reduce keying splatter. These are driver
|
||||
settings, not measured occupied-bandwidth results. Direct FEM gain changes are
|
||||
blocked while Morse owns the radio.
|
||||
|
||||
Frequency and speed are saved in a separate checked `/morse_prefs` file;
|
||||
identity, contacts and existing radio preferences are unchanged. An active
|
||||
message is never restored after reboot. TX uses the board's existing `set tx`
|
||||
power setting and hardware power limits.
|
||||
Unreadable or corrupt saved Morse settings without a usable backup block
|
||||
sending rather than silently
|
||||
transmitting on the default frequency. After storage recovers, verify and save
|
||||
`morse.freq` (and the desired WPM); a verified save makes sending available again.
|
||||
|
||||
Use an appropriate antenna or dummy load, lawful frequency/power and any
|
||||
required operator identification. The default frequency is a convenience, not
|
||||
permission to transmit or a claim that the channel is clear. Check the local
|
||||
band plan and listen first.
|
||||
|
||||
## Timed Morse reception and retained captures
|
||||
|
||||
Supported radios can temporarily listen for keyed carriers and decode the
|
||||
power envelope into text. This is a separate manual session, not another
|
||||
MeshCore packet channel or an authenticated sender. Nothing decoded is
|
||||
automatically transmitted, relayed or inserted into a channel/DM inbox.
|
||||
|
||||
| Command | Action |
|
||||
| --- | --- |
|
||||
| `morse listen 1` | Listen for one minute at the saved `morse.freq`, using `morse.wpm` as the timing hint. |
|
||||
| `morse listen 0.5` | Listen for 30 seconds. Fractions are allowed. |
|
||||
| `morse listen 5` | Listen for the maximum five minutes, then restore packet reception. |
|
||||
| `morse stop` | End TX or listening early. A received capture is retained. |
|
||||
| `get morse` | Show TX/RX state, actual RX filter bandwidth, remaining time and capture length/truncation. |
|
||||
| `morse stats` | Show retained receiver sample counts, noise/min/max/last power, timing unit, largest sample gap and read failures. |
|
||||
| `morse read` | Read the first retained capture page. |
|
||||
| `morse read 128` | Read beginning at character offset 128; use the offset returned by your previous page. |
|
||||
| `morse clear` | Clear the retained capture when no Morse session is active. |
|
||||
|
||||
Listening is bounded to **1–300 seconds** for every role. Keep the first
|
||||
0.5 seconds quiet while the receiver learns its noise floor; start the sending
|
||||
radio at least one second after listening begins. Start with matching WPM on
|
||||
the sender and receiver. Noise, fading, interference and timing mismatch can
|
||||
produce errors; decoded text has no sender identity or integrity check.
|
||||
|
||||
The receiver uses a continuous native FSK receive filter and live received
|
||||
signal strength (RSSI) to follow the carrier's on/off envelope. It does not
|
||||
transmit or require a packet preamble, sync word, CRC or direct-data pin:
|
||||
|
||||
| Radio family | Current Morse RX filter |
|
||||
| --- | ---: |
|
||||
| SX1276-family | 2.6 kHz |
|
||||
| SX1262/SX1268/STM32WLx, LLCC68 | 4.8 kHz |
|
||||
| LR1110/LR1121, LR2021 | 4.8 kHz |
|
||||
|
||||
Small-flash STM32 production builds disable Morse reception by default
|
||||
(`MESH_ENABLE_MORSE_RX=0`) because the receiver does not fit alongside their
|
||||
existing features. Morse TX, frequency/WPM settings and stopping remain
|
||||
available. Their listen/read/stats/clear commands return an unsupported-RX
|
||||
error. The STM32 filter above describes an explicitly enabled custom build,
|
||||
not RX support in those default production images.
|
||||
|
||||
`get morse` reports the actual configured bandwidth; this is not a measured
|
||||
selectivity or decoder-speed guarantee. Unsupported hardware rejects listening
|
||||
without changing the radio. A board also needs a proven complete LoRa-modem
|
||||
restoration path before native FSK RX is enabled. Narrow filters require
|
||||
sufficiently aligned oscillator frequencies. Passive listening may use either packet profile's
|
||||
frequency because it does not transmit; TX overlap protections still apply.
|
||||
FEM and saved Morse settings cannot be changed while a session owns the radio.
|
||||
|
||||
Morse sessions defer periodic sensor/GPS processing, screen redraws and
|
||||
background storage work so they do not interrupt envelope timing. Pending
|
||||
work and its deadlines are retained and resume when the session ends. Buttons,
|
||||
command connections, watchdogs and battery shutdown checks remain active.
|
||||
`morse stats` reports `gap` in milliseconds: the largest observed gap between
|
||||
receiver samples, including unavoidable safety work. Large gaps can limit
|
||||
reliable speed even when the RF signal is strong.
|
||||
|
||||
Repeater, Room, Sensor and Companion roles retain a bounded **4096-character
|
||||
RAM capture** after their normal packet receiver resumes. A successful new
|
||||
listening session replaces it; a failed start does not. `morse clear` or a
|
||||
reboot removes it. If the capture fills, listening stops early and
|
||||
`truncated=1`/capture-quota status is shown instead of continuing to discard
|
||||
incoming text. This does not change node keys, ACLs, stored radio
|
||||
settings or other files.
|
||||
|
||||
Capture replies fit one CLI response and begin with a page header such as
|
||||
`> 0000/0250 next=0125 truncated=0 ` followed by text. Send `morse read 125` to
|
||||
continue at the returned offset; `next=END` means the last page. Exact page
|
||||
length depends on the requesting transport's reply capacity, so follow `next`
|
||||
rather than assuming a fixed page size. Captures remain readable until you
|
||||
start another listening session or clear them.
|
||||
|
||||
A Full Companion's owned buffered USB ASCII terminal or browser terminal shows
|
||||
decoded progress as `[Morse RX] ...`, paused while USB input is being edited or
|
||||
an earlier reply is draining. Complete records use that terminal's existing
|
||||
ordered output queue. Raw UART/HWCDC/TCP terminals use `get morse`/`morse read`
|
||||
instead of unsolicited progress. Binary Companion USB/BLE frames never receive
|
||||
raw text.
|
||||
Companion apps and other clients can request the same capture through their
|
||||
CLI using `morse read`; it is not presented as an authenticated chat message.
|
||||
There is no automatic LCD/inbox injection.
|
||||
|
||||
One transceiver cannot listen for Morse and MeshCore LoRa simultaneously.
|
||||
During listening, normal packet reception/transmission is paused. An authorized
|
||||
remote `morse listen` first queues its reply on the existing packet-radio
|
||||
settings and starts only after the exact reply copies finish transmitting,
|
||||
with at least one successful transmission. It does not infer that the remote
|
||||
client received the reply. Failed queue admission/all-copy failure, permission
|
||||
revocation, changed Morse settings or a 30-second handoff deadline cancel the
|
||||
request without starting RX. A briefly busy radio can retry admission for up
|
||||
to 10 seconds after reply transmission, within that same handoff deadline.
|
||||
For remote captures, send `morse listen 1`, start the Morse sender after the
|
||||
queued reply and initial quiet learning interval, wait beyond the selected
|
||||
minute (plus any admission delay), then request
|
||||
`get morse` and `morse read` over LoRa. Use a local console to stop early.
|
||||
Hardware recovery failures hold exclusive ownership until the receiver can
|
||||
be safely restored; `get morse` reports recovery pending.
|
||||
|
||||
Lab images compiled with `MESH_MORSE_HIL=1` additionally provide
|
||||
`morse trace [offset]`. A page begins `> offset/length t=total n=next x=wrapped`
|
||||
and contains up to eight `elapsed_ms,rssi_dbm,flags;` records. `n=END` ends the
|
||||
retained window; `x=1` means earlier entries were overwritten. Offsets address
|
||||
the oldest of the latest 512 retained records; retrieve after stopping or
|
||||
check that `t` stays unchanged between pages. Flags are raw key 1, committed
|
||||
key 2, debounce candidate 4 and noise learning 8. This diagnostic command and
|
||||
its trace storage are absent from ordinary production builds.
|
||||
|
||||
## Continuous carrier checks
|
||||
|
||||
`cw` and `cw2` transmit a continuous, unmodulated carrier at the selected
|
||||
profile's frequency and the configured TX power. They are available in the
|
||||
shared ASCII CLI on SX1276-family, SX1262-family, and LR1110 builds, including repeaters,
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/carrier_wave_validation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/carrier_wave_validation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/charge_voltage/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Battery charge voltage
|
||||
|
||||
The `charge.voltage` commands change the battery charger's constant-voltage
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/cli_build_matrix/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# CLI Availability by Firmware Build
|
||||
|
||||
MeshCore command availability is determined in three layers:
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/cli_command_availability/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# CLI Command Availability Matrix
|
||||
|
||||
This page is the command-by-command companion to
|
||||
@@ -15,6 +19,15 @@ Infrastructure `get password` is available locally in every profile; LoRa
|
||||
requests cannot read it. `get acl` and stored packet `log` are infrastructure
|
||||
features, not Companion contact or live USB-logging commands.
|
||||
|
||||
Room users also have an owner-only command set described in
|
||||
[Personal mailboxes](room_services.md#personal-mailboxes): `mail settings`,
|
||||
`mail mode`, `mail allow`, `mail deny`, `mail delivery`, `mail check`,
|
||||
`mail inbox`/`mail list`, `mail read`, `mail ack`, and `mail delete`.
|
||||
Authenticated room writers can use `mail send`; readers cannot send.
|
||||
These work as encrypted CLI requests or ordinary direct `!mail ...` messages
|
||||
to the room. Regular users can also read `get room.board` and
|
||||
`get room.board.read`; board publishing and deletion remain administrative.
|
||||
|
||||
Build columns mean:
|
||||
|
||||
- **Standard** - the ordinary non-MQTT artifact, without an explicit `ota`
|
||||
@@ -70,6 +83,12 @@ fix, no WiFi connection, an inactive bridge, or an nRF52 bootloader without
|
||||
|
||||
## Companion framed CLI
|
||||
|
||||
GPS-equipped Sensor builds also provide the local-only
|
||||
[dog tracker settings](sensor_tracker.md): `get tracker`,
|
||||
`get/set tracker.owner`, `get/set tracker.mode`, `get/set tracker.interval`,
|
||||
`get/set tracker.lost.interval`, `get/set tracker.path`, and `tracker check`.
|
||||
They are excluded from compact STM32 defaults. LoRa CLI cannot change them.
|
||||
|
||||
Companion builds are not represented by the role/profile matrices below. Their
|
||||
local terminal and command `0x42` (`CMD_RUN_CLI_COMMAND`) expose these settings
|
||||
over the normal binary USB, BLE, or TCP connection:
|
||||
@@ -82,6 +101,7 @@ over the normal binary USB, BLE, or TCP connection:
|
||||
| [`get public.key`](cli_commands.md#view-this-nodes-public-key) | Companion text terminal and binary command `0x42`; read-only, no private-key export feature required |
|
||||
| `get prv.key` | Local terminal and binary command `0x42`; requires private key export enabled |
|
||||
| `get password` | Reports that Companion has no admin password; infrastructure returns its password locally |
|
||||
| [`get/set lost.reply`](companion_lost_reply.md) | Local Companion CLI and framed command `0x42` when `MESH_ENABLE_LOST_REPLY` is enabled; saved `off`, `no` or `yes` private-message auto response |
|
||||
| `get wifi.pwd`, `get mqttN.password`, `get mqttN.token` | Local terminal and binary command `0x42`; corresponding WiFi/MQTT feature required |
|
||||
| [`board`](cli_commands.md#show-the-hardware-name) | Every Companion text terminal and command `0x42` |
|
||||
| [`version`](cli_commands.md#get-the-version) | Every Companion text terminal and protocol-v14 command `0x42`; returns the untruncated build identity |
|
||||
@@ -189,11 +209,12 @@ should use command `0x42`. See [Companion radio binary protocol](companion_proto
|
||||
| Routing | [`get/set/del flood.channel.scope.require*`](cli_commands.md#require-valid-incoming-scopes-only-on-selected-channels) | Repeater | Yes | Yes | Yes |
|
||||
| Routing | [`get/set/del flood.rule*`; `get/set/del flood.filter*`; `get/set/del flood.filter.blacklist*`](cli_commands.md#change-persistent-flood-rules-in-the-field) | Repeater; `flood.rule`/`flood.filter` also on FULL ESP32 room server (no blacklist) | Yes | Yes | Yes |
|
||||
| Routing | [`get/set/del flood.moderation*`](cli_commands.md#moderate-flood-group-text-by-channel-sender-and-source-path) | Repeater | Yes | Yes | Yes |
|
||||
| Routing | [`get/set outpath`](halo_keymind_settings.md#direct-path-overrides) | Repeater remote-client context | Yes | Yes | Yes |
|
||||
| Routing | [`get/set altpath`](halo_keymind_settings.md#direct-path-overrides) | Repeater remote-client context | Yes | Yes | Yes |
|
||||
| Routing | [`get/set outpath`](halo_keymind_settings.md#direct-path-overrides) | Repeater or [room user](room_services.md#your-own-return-routes), own remote-client context | Yes | Yes | Yes |
|
||||
| Routing | [`get/set altpath`](halo_keymind_settings.md#direct-path-overrides) | Repeater or [room user](room_services.md#your-own-return-routes), own remote-client context | Yes | Yes | Yes |
|
||||
| ACL | [`setperm <pubkey> <permissions>`](cli_commands.md#add-update-or-remove-permissions-for-a-companion) | Repeater, room server, or sensor | Yes | Yes | Yes |
|
||||
| ACL | [`get acl [page]`](cli_commands.md#view-the-current-acl) | Repeater, room server, or sensor; admin over LoRa | Yes | Yes | Yes |
|
||||
| ACL | [`get/set allow.read.only`](cli_commands.md#view-or-change-this-room-servers-read-only-flag) | Room server | Yes | Yes | No |
|
||||
| Room | [`get/set topic`](cli_commands.md#view-or-change-the-room-topic) | Room server | Yes | Yes | No |
|
||||
| Regions | [`region load`](cli_commands.md#bulk-load-region-lists); [`region save`](cli_commands.md#save-any-changes-to-regions-made-since-reboot) | Role with region storage | Yes | Yes | Yes |
|
||||
| Regions | [`region allowf`](cli_commands.md#allow-a-region); [`region denyf`](cli_commands.md#block-a-region) | Role with region storage | Yes | Yes | Yes |
|
||||
| Regions | [`region get`](cli_commands.md#show-information-for-a-region); [`region list`](cli_commands.md#view-all-regions); [`region`](cli_commands.md#dump-all-defined-regions-and-flood-permissions) | Role with region storage | Yes | Yes | Yes |
|
||||
@@ -364,11 +385,12 @@ should use command `0x42`. See [Companion radio binary protocol](companion_proto
|
||||
| Routing | [`get/set/del flood.channel.scope.require*`](cli_commands.md#require-valid-incoming-scopes-only-on-selected-channels) | Repeater role handler | Yes | Yes | Yes | Yes | Yes |
|
||||
| Routing | [`get/set/del flood.rule*`; `get/set/del flood.filter*`; `get/set/del flood.filter.blacklist*`](cli_commands.md#change-persistent-flood-rules-in-the-field) | Repeater role handler; `flood.rule`/`flood.filter` also on FULL ESP32 room server (no blacklist) | Yes | Yes | Yes | Yes | Yes |
|
||||
| Routing | [`get/set/del flood.moderation*`](cli_commands.md#moderate-flood-group-text-by-channel-sender-and-source-path) | Repeater role handler | Yes | Yes | Yes | Yes | Yes |
|
||||
| Routing | [`get/set outpath`](halo_keymind_settings.md#direct-path-overrides) | Repeater remote-client context | Yes | Yes | Yes | Yes | Yes |
|
||||
| Routing | [`get/set altpath`](halo_keymind_settings.md#direct-path-overrides) | Repeater remote-client context | Yes | Yes | Yes | Yes | Yes |
|
||||
| Routing | [`get/set outpath`](halo_keymind_settings.md#direct-path-overrides) | Repeater or [room user](room_services.md#your-own-return-routes), own remote-client context | Yes | Yes | Yes | Yes | Yes |
|
||||
| Routing | [`get/set altpath`](halo_keymind_settings.md#direct-path-overrides) | Repeater or [room user](room_services.md#your-own-return-routes), own remote-client context | Yes | Yes | Yes | Yes | Yes |
|
||||
| ACL | [`setperm <pubkey> <permissions>`](cli_commands.md#add-update-or-remove-permissions-for-a-companion) | Repeater, room server, or sensor | Yes | Yes | Yes | Yes | Yes |
|
||||
| ACL | [`get acl [page]`](cli_commands.md#view-the-current-acl) | Repeater, room server, or sensor; admin over LoRa | Yes | Yes | Yes | Yes | Yes |
|
||||
| ACL | [`get/set allow.read.only`](cli_commands.md#view-or-change-this-room-servers-read-only-flag) | Room server | Yes | Yes | No | Yes | Yes |
|
||||
| Room | [`get/set topic`](cli_commands.md#view-or-change-the-room-topic) | Room server | Yes | Yes | No | Yes | Yes |
|
||||
| Regions | [`region load`](cli_commands.md#bulk-load-region-lists); [`region save`](cli_commands.md#save-any-changes-to-regions-made-since-reboot) | Role with region storage | Yes | Yes | Yes | Yes | Yes |
|
||||
| Regions | [`region allowf`](cli_commands.md#allow-a-region); [`region denyf`](cli_commands.md#block-a-region) | Role with region storage | Yes | Yes | Yes | Yes | Yes |
|
||||
| Regions | [`region get`](cli_commands.md#show-information-for-a-region); [`region list`](cli_commands.md#view-all-regions); [`region`](cli_commands.md#dump-all-defined-regions-and-flood-permissions) | Role with region storage | Yes | Yes | Yes | Yes | Yes |
|
||||
|
||||
+235
-4
@@ -1,11 +1,40 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/cli_commands/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# CLI Commands
|
||||
|
||||
See [two LoRa profiles](radio_profiles.md) for `radio2`, `tempradio2`, scheduling,
|
||||
RX-only mode, cross-transmission policy, and optional radio preambles.
|
||||
|
||||
For supported Full Companions, see [Meshtext channel chat](radio_profiles.md#meshtext-channel-chat)
|
||||
for `mt-` channels and the explicit `send mt.nodeinfo <channel slot>` command.
|
||||
Chat remains plain text; NodeInfo is sent only when that command is requested.
|
||||
|
||||
See [carrier-wave RF checks](carrier_wave.md) for `cw on [seconds]`,
|
||||
`cw2 on [seconds]`, and stopping a carrier with `off`.
|
||||
|
||||
For keyed Morse TX, use `morse send TEST DE N0CALL` and `morse stop`.
|
||||
Defaults are **902.100 MHz and 25 WPM**; `set morse.freq <MHz>` and
|
||||
`set morse.wpm <1–60>` save separate frequency/speed settings.
|
||||
Small-flash STM32 production builds retain Morse TX but do not include Morse
|
||||
RX by default; listen/read/stats/clear return an unsupported-RX error there.
|
||||
`get morse` shows status. See [TX-only Morse messages](carrier_wave.md#tx-only-morse-messages)
|
||||
for supported characters, limits, overlap checks and the temporary pause in
|
||||
packet reception. Nothing transmits automatically.
|
||||
|
||||
For timed Morse RX, use `morse listen <minutes>` (fractions allowed, 1 second
|
||||
through 5 minutes). `morse stop` ends TX or RX. All roles retain the bounded
|
||||
capture in RAM for `morse read [offset]`; follow each page's `next` value until
|
||||
`next=END`. `morse clear` removes it when idle. A new successful session or
|
||||
reboot replaces/removes the capture. Buffered USB/browser Full Companion ASCII
|
||||
terminals show decoded progress; other terminals and binary clients request it
|
||||
through the CLI, without adding
|
||||
unidentified text to authenticated channel/chat messages. Normal LoRa is paused
|
||||
during listening, so a remote administrator must wait for the selected session
|
||||
to end before reading the capture over LoRa. See [timed reception](carrier_wave.md#timed-morse-reception-and-retained-captures)
|
||||
for arming time, real chip bandwidths and truncation behavior.
|
||||
|
||||
For copy/paste on/off recipes and the differences from Full Companion, see
|
||||
[feature switches by role](role_feature_switches.md). The
|
||||
[USB web console](https://flasher.meshcore.io/console) opens the default ASCII
|
||||
@@ -284,6 +313,13 @@ them entirely. Sign in with the node's admin password. If the node has no saved
|
||||
WiFi SSID, the command starts the open `MeshCore-Setup-XXXX` captive AP at
|
||||
<http://192.168.4.1/> instead.
|
||||
|
||||
If a saved WiFi network is unavailable and the node falls back to its setup
|
||||
AP, sign in with the existing admin password before changing settings. Joining
|
||||
that AP does not grant permission to replace the password. First-time setup
|
||||
without a saved SSID keeps its AP provisioning flow. Images deliberately
|
||||
configured without an admin password, including passwordless Companions,
|
||||
retain their local no-password policy; use them only on a trusted network.
|
||||
|
||||
`start webconfig ap` forces captive-AP mode. It will not interrupt an active
|
||||
MQTT bridge, so run `set mqtt.enabled off` first. Use `stop webconfig` to
|
||||
close either mode for the current boot. (`stop webconfig` does not change a
|
||||
@@ -386,6 +422,35 @@ credentials alone do not turn it on. ESP32 simultaneous-transport builds apply
|
||||
the change from the main loop; exclusive-transport builds and Pico W apply it
|
||||
after reboot. This does not disable a primary ESP-NOW mesh radio or add Bluetooth
|
||||
to a WiFi-only build.
|
||||
|
||||
ESP32 WiFi Companions also accept `get wifi.tcp` over USB, BLE, or the browser
|
||||
CLI. This checks the app's TCP listener (normally port `5000`), not just the
|
||||
WiFi association. `listening` means the socket is open; `waiting-ip` means no
|
||||
usable station or setup-AP address yet; `retrying` means listener startup
|
||||
failed and will be retried automatically; `off` means no enabled listener
|
||||
request. `reg=1` confirms the interface is registered for Companion commands.
|
||||
`client=1` means a TCP client is connected. `acc`, `rx`, and `tx` count accepted
|
||||
clients, complete received frames, and complete transmitted frames since boot;
|
||||
the value after `/` is the last frame's hexadecimal opcode. `fail`, `err`, and
|
||||
`retry` show listener failures, the last listener-start socket error, and seconds until retry.
|
||||
`drop` gives the last client-disconnect reason. These counters contain no
|
||||
message contents or credentials. An open listener does not prove a router or
|
||||
guest-network firewall permits access from the phone.
|
||||
|
||||
Listener retries wait 1, 2, 4, 8, 16, then at most 30 seconds. They do not
|
||||
reconnect WiFi, interrupt BLE/WebConfig/OTA, replace a healthy app connection,
|
||||
or re-enable explicitly disabled WiFi. `get display.wifi` includes `tcp=1`
|
||||
only when the listener is actually open; `services=1` alone is not proof.
|
||||
|
||||
The ESP32 TCP transport services input even while radio logs or other outgoing
|
||||
frames are pending, so unsolicited traffic cannot starve the app handshake.
|
||||
Socket sends are non-blocking. A client that makes no outbound progress for
|
||||
10 seconds while data is pending is disconnected (`drop=tx-timeout`), without
|
||||
blocking the other transports. `drop=tx-error` identifies a fatal send error.
|
||||
Commands wait when all reply slots hold delivery-required data, rather than
|
||||
executing with nowhere to return their reply. A partly sent frame stays pinned
|
||||
until it finishes; input and output remain separate TCP streams.
|
||||
|
||||
See [local maintenance commands](terminal_chat_cli.md#local-maintenance-commands)
|
||||
for the complete access rules. WiFi-only Companions accept
|
||||
all three modes. A Full Companion that runs BLE and infrastructure WiFi
|
||||
@@ -2355,6 +2420,8 @@ on battery. `set powersaving on` still enables sensor/GPS power-saving policies;
|
||||
the CPU continues normal idle yielding while keeping the console available.
|
||||
A running MQTT, RS232 or ESP-NOW bridge keeps infrastructure awake even when
|
||||
`get powersaving` reports `on`; that readback alone does not prove MCU sleep.
|
||||
Negotiated RS232 standby can stop an unresponsive UART owner without changing
|
||||
its saved enabled flag; see `rs232.autosleep` below. Other sleep blockers still apply.
|
||||
Adding UART wake alone would still discard the characters that trigger wake,
|
||||
so it cannot preserve an unmodified web console's first command. See the
|
||||
[ESP-IDF UART wake documentation](https://docs.espressif.com/projects/esp-idf/en/v4.4.7/esp32s3/api-reference/system/sleep_modes.html#uart-wakeup-light-sleep-only).
|
||||
@@ -2441,6 +2508,9 @@ The pin number is the Arduino pin number used by that target (the normal GPIO nu
|
||||
|
||||
**Notes:**
|
||||
- These commands require remote client context and update the caller's ACL entry.
|
||||
- Room Server readers and writers may manage their own `outpath` and `altpath`
|
||||
without administrator permission. See [room return routes](room_services.md#your-own-return-routes)
|
||||
for the command list, session persistence and alternate delivery behavior.
|
||||
- `get outpath path` reports the reciprocal `PAYLOAD_TYPE_PATH` received after
|
||||
the caller's latest flood login without changing the selected output route.
|
||||
Because that packet is asynchronous, an immediate query can report
|
||||
@@ -3759,16 +3829,65 @@ setperm <PUBKEY_USER_1> 2
|
||||
```
|
||||
|
||||
With read-only mode on, a client without a valid room password can join as a
|
||||
read-only guest. Permission `2` gives the specified public key read-write
|
||||
read-only guest, including with a blank password. Empty configured admin and
|
||||
room passwords disable those password credentials; they never grant Admin or
|
||||
Read-Write access. Permission `2` gives the specified public key read-write
|
||||
access. Replace `<PUBKEY_USER_1>` with the user's full public key and repeat
|
||||
`setperm` for every approved writer.
|
||||
|
||||
An existing ACL identity keeps its assigned role when logging in with a blank,
|
||||
stale, or room password. A valid nonempty admin password can explicitly upgrade
|
||||
it to Admin. This prevents a guest-password login from demoting an admin, and
|
||||
prevents a room password from overriding an explicit read-only assignment.
|
||||
Only Read-Write (`2`) and Admin (`3`) clients can post.
|
||||
|
||||
This does not remove write access from clients that already know the room
|
||||
password. Keep that password private, or replace it, if write access should be
|
||||
limited to the explicitly permitted users.
|
||||
|
||||
---
|
||||
|
||||
#### View or change the room topic
|
||||
|
||||
**Availability:** Room Server firmware. Local consoles and authenticated remote
|
||||
admins can use these commands.
|
||||
|
||||
```text
|
||||
set topic Welcome to the Bellevue room. Please keep posts local.
|
||||
get topic
|
||||
set topic
|
||||
```
|
||||
|
||||
`set topic <text>` saves an announcement of up to 151 UTF-8 bytes. Individual
|
||||
command transports can impose a smaller input limit. `get topic` returns the
|
||||
current text prefixed with `> `. `set topic` with no text clears it.
|
||||
|
||||
The topic survives reboot and appears as a normal room post authored by the
|
||||
server, using the existing app message format. It does not require an app
|
||||
update or provide a separate pinned-header display. Older unread retained posts
|
||||
are delivered before the topic, so the companion's automatic catch-up cursor
|
||||
cannot jump past them. A topic ACK updates only topic delivery state, leaving
|
||||
the server's message-history cursor unchanged.
|
||||
|
||||
The server waits six seconds before delivering a new topic and attempts an
|
||||
unacknowledged announcement up to three times per client. It then continues
|
||||
ordinary post delivery; reconnecting or changing the topic renews that budget.
|
||||
Changing a topic while its predecessor is awaiting an ACK does not mark the
|
||||
replacement as received. Clearing the topic stops further announcement pushes;
|
||||
a packet already queued for transmission can still arrive.
|
||||
|
||||
Topic saves are verified before publication. A failed save reports an error
|
||||
and retains the previous live topic. Corrupt, unreadable, or unsupported stored
|
||||
topic files are preserved and block replacement until their storage issue is
|
||||
repaired. Ordinary room history uses the bounded RAM ring by default. Enable
|
||||
optional retention of the newest 32 posts with `set room.history on`.
|
||||
|
||||
See [Room history, moderation, and information board](room_services.md) for
|
||||
persistent history, saved ACL roles, full-key bans, per-user post/request
|
||||
limits, the ESP32 `/room` browser page, and versioned article downloads.
|
||||
|
||||
---
|
||||
|
||||
### Region Management (v1.10.+)
|
||||
|
||||
#### Bulk-load region lists
|
||||
@@ -4625,12 +4744,51 @@ clear recent.repeater
|
||||
|
||||
**Note:** These command names are shared with GPS-capable Companion builds.
|
||||
Companion reports `on` or `off`; infrastructure includes receiver details:
|
||||
- `off` when the GPS hardware is disabled
|
||||
- `on, {active|deactivated}, {fix|no fix}, {sat count} sats` when the GPS hardware is enabled
|
||||
- `off, {powered|unpowered}` when GPS is manually disabled
|
||||
- `on, {powered|unpowered}, {fix|no fix}, {sat count} sats` when GPS is enabled
|
||||
|
||||
`powered` describes the supply, not proof that the receiver is tracking or
|
||||
asleep. Shared-power hardware can remain powered while GPS processing is off.
|
||||
|
||||
On repeaters, `gps off` cancels any acquisition already in progress. A later
|
||||
authorized location-telemetry request may wake the receiver, but only until its
|
||||
first valid fix is cached; the receiver then powers down again.
|
||||
first valid fix is cached; GPS processing then stops again. Whether its supply
|
||||
can also turn off depends on the board's power policy below.
|
||||
|
||||
---
|
||||
|
||||
#### RAK4631 shared peripheral power
|
||||
|
||||
**Usage:**
|
||||
|
||||
```text
|
||||
get peripherals.mode
|
||||
set peripherals.mode gps-only
|
||||
set peripherals.mode shared
|
||||
reboot
|
||||
```
|
||||
|
||||
**Default:** `gps-only` on RAK4631. The saved mode takes effect only after
|
||||
reboot; setting it does not switch power immediately. `get peripherals.mode`
|
||||
reports the saved choice, which may differ from the current boot's mode.
|
||||
|
||||
- `gps-only`: when no protected power owner exists, GPS-off and GPS sleep can
|
||||
turn off the shared WisBlock `3V3_S` supply. Select this only when other
|
||||
attached peripherals do not need that supply.
|
||||
- `shared`: keeps `3V3_S` powered for other peripherals. Save this mode and
|
||||
reboot when using other WisBlock modules; firmware does not infer this choice
|
||||
from an I2C scan.
|
||||
|
||||
Ethernet/PoE builds and detected external NOR storage automatically keep the
|
||||
rail on, even in `gps-only` mode or when the network service is disabled.
|
||||
RAK3401 permanently protects the same rail because its radio frontend needs
|
||||
it; `peripherals.mode` is a RAK4631 setting, not an override of that protection.
|
||||
|
||||
On a powered shared rail, RAK12501/L76K cannot be independently switched off:
|
||||
GPS-off stops MCU parsing, not physical GNSS operation. Other receivers may use
|
||||
internal power-saving commands, but `shared` does not promise physical sleep.
|
||||
UART1 bridge ownership remains protected; changing this mode does not grant
|
||||
permission to connect two transmitters to the GPS UART.
|
||||
|
||||
---
|
||||
|
||||
@@ -4786,6 +4944,72 @@ MQTT preferences and retains explicit settings across reboots.
|
||||
|
||||
---
|
||||
|
||||
#### RS232 heartbeat and automatic standby
|
||||
|
||||
Available on repeater builds with an RS232 bridge. This is a UART-local control
|
||||
exchange, not an advert or a LoRa packet. Room builds without RS232 are unaffected.
|
||||
|
||||
**Usage:**
|
||||
|
||||
- `get rs232.status`
|
||||
- `get rs232.heartbeat`
|
||||
- `set rs232.heartbeat on|off`
|
||||
- `get rs232.autosleep`
|
||||
- `set rs232.autosleep on|off|force`
|
||||
- `get rs232.idle`
|
||||
- `set rs232.idle <seconds>` (60 through 3600; default 300)
|
||||
|
||||
Heartbeat and negotiated automatic standby are **on by default**, including
|
||||
upgrades. An active UART pings every 30 seconds (52 bytes per ping).
|
||||
Stock bridges ignore that traffic and still receive the original data frames;
|
||||
they are not automatically put to sleep: standby is armed only after a fresh
|
||||
heartbeat reply proves support. Fresh, session/challenge-matched replies
|
||||
prove a bidirectional peer;
|
||||
ordinary valid incoming data can keep a legacy link awake but cannot prove
|
||||
heartbeat support. The status separates saved intent, actual UART state,
|
||||
standby/probe phase, and confirmed versus legacy/unknown peer liveness.
|
||||
|
||||
Enable on both updated peers:
|
||||
|
||||
```text
|
||||
set rs232.enabled on
|
||||
set rs232.heartbeat on
|
||||
set powersaving on
|
||||
set rs232.idle 300
|
||||
set rs232.autosleep on
|
||||
get rs232.status
|
||||
```
|
||||
|
||||
With heartbeat, autosleep, and global powersaving all on and the peer's heartbeat
|
||||
support confirmed, when no peer responds for the idle interval the UART is soft-stopped while
|
||||
`rs232.enabled` stays `on`. It wakes after 30 seconds for a 2-second probe;
|
||||
every eighth probe listens for 40 seconds. That longer window spans the other
|
||||
side's sleep interval, so two sleeping updated peers can reconnect without
|
||||
manual intervention (normally within about five minutes with working wiring
|
||||
and timely loop servicing). Healthy peers remain running; this is dead-link
|
||||
power saving, not an idle-data duty cycle.
|
||||
|
||||
Stock receivers ignore these control frames; they are deliberately invalid
|
||||
zero-length stock frames with an ASCII-only remainder. They do not allocate a
|
||||
mesh packet or enter LoRa forwarding. Stock peers do **not** answer heartbeats,
|
||||
so default negotiated standby never arms on a stock-only link. Valid legacy
|
||||
data after heartbeat replies cease also disarms negotiated standby, allowing
|
||||
a replacement stock peer to stay awake. Use `set rs232.autosleep force` only
|
||||
to sleep an absent/unconfirmed UART peer; this explicitly bypasses stock
|
||||
protection and can miss one-off stock packets.
|
||||
If a previously confirmed updated peer is silently replaced with stock while
|
||||
the local UART is already sleeping, its first packet can be missed before
|
||||
replacement is detected. Set autosleep off before that change, or restart the
|
||||
local bridge to clear the old negotiated session.
|
||||
While the UART is stopped it cannot receive a wake byte; mesh traffic
|
||||
during standby is not queued for later UART delivery. Turning autosleep or
|
||||
global powersaving off resumes the saved-enabled UART; `rs232.enabled off`
|
||||
remains an explicit off and never automatically wakes.
|
||||
`rs232.heartbeat off` stops initiating heartbeats and prevents standby. An
|
||||
updated active peer can still answer a valid incoming ping in passive mode.
|
||||
|
||||
---
|
||||
|
||||
#### Add a delay to packets routed through this bridge
|
||||
**Usage:**
|
||||
- `get bridge.delay`
|
||||
@@ -4834,6 +5058,13 @@ brokers to reconnect. `get mqtt.running` checks the service's runtime state;
|
||||
`get mqtt.status` reports individual broker connections. Enabling MQTT does
|
||||
not imply that a broker is connected.
|
||||
|
||||
Custom `mqtts://` and `wss://` brokers require an image with the embedded CA
|
||||
bundle. Without it, the slot stays disconnected and sends no credentials;
|
||||
use a build with the bundle or a supported preset with its pinned CA.
|
||||
Portable MQTT images retain those presets but do not include the general
|
||||
bundle for custom TLS brokers. Explicit `mqtt://` and `ws://` configurations
|
||||
remain available for trusted networks and use plaintext transport.
|
||||
|
||||
On ESP32 Repeater and Room Server images, `set mqtt.enabled off` acknowledges
|
||||
the stop request while the MQTT task disconnects and destroys its clients.
|
||||
`get mqtt.stopping` stays `on` until that cleanup completes; `mqtt.running`
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/cli_settings_audit/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/cli_settings_audit/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/companion_contact_cache/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../research/companion_contact_cache/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/companion_contact_cache_results/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/companion_contact_cache_results/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/companion_lost_reply/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Companion lost-status auto response
|
||||
|
||||
Development Companion builds containing this feature can automatically answer a private `Am I lost?` message with `Yes`
|
||||
or `No`. You choose the saved answer. The default is `off`, and the firmware
|
||||
does not infer lost status from GPS, distance, or a missing phone connection.
|
||||
|
||||
This is included in nRF52, ESP32 and RP2040 Companion profiles, including
|
||||
T1000-E and RAK Tag. Compact STM32 Companion images omit it to preserve their
|
||||
existing application and filesystem boundaries. A custom build can explicitly
|
||||
enable `MESH_ENABLE_LOST_REPLY=1` when its flash budget permits; the normal
|
||||
flash and RAM checks still apply.
|
||||
|
||||
Configure it through a directly connected local Companion CLI:
|
||||
|
||||
~~~text
|
||||
get lost.reply
|
||||
set lost.reply no
|
||||
set lost.reply yes
|
||||
set lost.reply off
|
||||
~~~
|
||||
|
||||
The setting survives reboot and takes effect immediately. USB, BLE and other
|
||||
local Companion transports can use framed command `0x42`. Builds with a text
|
||||
terminal also accept these commands there. LoRa CLI cannot read or change this
|
||||
local setting. A failed save restores the previous answer and reports an error.
|
||||
Older saved preference images load the new setting as `off`.
|
||||
|
||||
ESP32 Companions with WebConfig also have a **Lost-status auto reply**
|
||||
selection on the radio configuration page. Choose Off, Reply No or Reply Yes
|
||||
and save. The control is shown only on Companion firmware with this capability.
|
||||
The existing mobile app protocol needs no new message type; a native app toggle
|
||||
is not added by this firmware change.
|
||||
|
||||
## Dog tracker example
|
||||
|
||||
The owner's Companion stores the tracker as a normal radio contact. Set the
|
||||
answer to `no` during normal operation. If the dog is lost, set it to `yes`.
|
||||
When the tracker sends `Am I lost?` privately to that reachable Companion, it
|
||||
receives the selected answer, even when the owner's phone is disconnected.
|
||||
The same configured answer applies to all eligible contacts on this Companion.
|
||||
|
||||
The opt-in [Sensor dog tracker](sensor_tracker.md) implements periodic fresh
|
||||
GPS acquisition, low power sleep, and owner check-ins. It uses a tagged encrypted
|
||||
request and response rather than parsing plain `Yes` or `No` text, so old answers
|
||||
cannot change a newer check-in. Store the Sensor as a persistent Sensor contact
|
||||
on the owner's Companion. The same saved `lost.reply` setting answers those
|
||||
checks; `off` returns Unknown. A fresh accepted GPS position updates the contact
|
||||
location through normal contact notifications.
|
||||
|
||||
Other clients can still use the plain text question. They must stay awake for
|
||||
the separate private answer; a delivery ACK is not that answer. Plain text
|
||||
answers have no request ID. The responding Companion must be powered on and
|
||||
reachable. [Personal room mailboxes](room_services.md#sleeping-tracker-example)
|
||||
provide store-and-forward mail; automatic mailbox polling is not yet implemented
|
||||
in the Sensor tracker.
|
||||
|
||||
## Matching and traffic limits
|
||||
|
||||
Only an authenticated ordinary private message from a known persistent radio
|
||||
contact is eligible. The contact must be an ordinary Companion/chat contact;
|
||||
room-server and repeater contacts are excluded. Temporary unknown senders,
|
||||
public channels, room chat posts and CLI messages do not trigger a response.
|
||||
|
||||
The exact phrase `am I lost` is matched without regard to ASCII letter case,
|
||||
with an optional final question mark and surrounding whitespace. Extra words
|
||||
or commands do not match. The reply is ordinary encrypted private text, `Yes`
|
||||
or `No`, and neither answer can trigger another automatic reply.
|
||||
|
||||
Automatic responses are limited to one per contact per minute and one globally
|
||||
per ten seconds. A bounded four-peer cache uses full public keys and the
|
||||
incoming request timestamp to suppress retries. Its state clears on reboot.
|
||||
The same retained request is not answered again; a fresh check uses a new
|
||||
timestamp. An old retry can receive another answer after a newer request
|
||||
replaces its saved timestamp or its peer slot is evicted. Queueing an answer
|
||||
records the request even if later delivery fails. An unanswered poll means
|
||||
unknown, and the tracker should trust replies only from its configured
|
||||
Companion's full public key.
|
||||
|
||||
The responder leaves packet capacity for normal receive/ACK work, uses a free
|
||||
ACK-tracking entry, and does not replace pending user messages or their
|
||||
delivery deadlines. Busy packet or ACK capacity, or a failed send, can prevent an answer;
|
||||
the tracker should retry later. A full offline app inbox does not disable the
|
||||
responder. Normal message reception and notification behavior remain in place.
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/companion_offline_queue/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Companion Offline Message Queue
|
||||
|
||||
Companion firmware keeps received channel data, channel messages, and direct
|
||||
@@ -13,6 +17,7 @@ A reboot clears it.
|
||||
| ESP32 without PSRAM | 256 |
|
||||
| nRF52840 with at most 300 contact slots | 256 |
|
||||
| nRF52840 with more than 300 contacts and the contact cache (non-mOTA-shared queue) | 256 total: up to 15 held DMs use slots until accepted |
|
||||
| RAK WisMesh Tag ordinary BLE Companion | 240 total: up to 15 held DMs use slots until accepted |
|
||||
| nRF52840 with more than 300 contacts but no contact cache | 208 ordinary frames plus a separate 15-DM queue |
|
||||
| nRF52 Full Companion with the memory correction | 256 normally; 128 while mOTA owns shared storage |
|
||||
| RP2040 | 256 |
|
||||
@@ -56,6 +61,13 @@ Uncached high-contact profiles keep the conservative 208-frame default and
|
||||
separate held queue. An explicit target `OFFLINE_QUEUE_SIZE` still takes
|
||||
precedence.
|
||||
|
||||
The ordinary RAK WisMesh Tag BLE profile uses 240 frames to retain the runtime
|
||||
RAM reserve for Bluetooth, filesystem buffers, and the main task. It keeps
|
||||
350 contact slots and 40 group channels. All 240 slots are available when no
|
||||
DMs are held; 15 held DMs leave 225 ordinary slots. This saves 2,832 bytes
|
||||
compared with 256 frames. The Tag Full Companion retains 256 frames normally
|
||||
and 128 while mOTA borrows queue storage.
|
||||
|
||||
Each queue slot currently costs 177 bytes. A 256-frame queue reserves 45,312
|
||||
bytes, while a 512-frame queue reserves 90,624 bytes. There is no 256-frame
|
||||
protocol limit: the queue length and indexes can represent 512 or more. The
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/companion_protocol/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Companion Protocol
|
||||
|
||||
- **Last Updated**: 2026-08-26
|
||||
@@ -310,6 +314,11 @@ WiFi store, and enablement is saved in node preferences. WiFi/BLE builds apply
|
||||
enablement from the main loop; exclusive WiFi/BLE builds apply it after reboot.
|
||||
`get wifi.status` reports the connection state and `get wifi.ip` reports the
|
||||
station address, the setup AP address, or `(not connected)`.
|
||||
`get wifi.tcp` reports the actual app listener, interface registration, client
|
||||
connection and completed frame counters. It is read-only and available through
|
||||
the same binary CLI command over BLE or USB when TCP is unreachable. Listener
|
||||
startup failures recover automatically without resetting a healthy client or
|
||||
the WiFi connection; see [the CLI diagnostics](cli_commands.md#browser-configuration-portal-esp32-repeater-and-room-server).
|
||||
`set freq <MHz>` works through command `0x42` and authorized LoRa CLI, like
|
||||
`set radio`; it saves the frequency and requires reboot to apply. See
|
||||
[local maintenance commands](terminal_chat_cli.md#local-maintenance-commands)
|
||||
@@ -541,6 +550,11 @@ Byte 1: Channel index (0 through max_channels - 1)
|
||||
|
||||
**Response**: `PACKET_CHANNEL_INFO` (0x12) with channel details
|
||||
|
||||
On builds with `MESH_ENABLE_MESHTEXT_CHAT=1`, a capable client can append a
|
||||
third request byte of `32` (`1F <index> 20`) to retrieve the complete 32-byte
|
||||
secret for an `mt-` channel. Ordinary two-byte requests, and requests for
|
||||
MeshCore channels, retain the original 16-byte secret response.
|
||||
|
||||
---
|
||||
|
||||
### 4. Set Channel
|
||||
@@ -579,7 +593,27 @@ Bytes 34-49: Secret (16 bytes)
|
||||
[16 bytes of secret]
|
||||
```
|
||||
|
||||
**Note**: The 32-byte secret variant is unsupported and returns `PACKET_ERROR`.
|
||||
**Meshtext-only extension**: With `MESH_ENABLE_MESHTEXT_CHAT=1`, a 66-byte
|
||||
`SET_CHANNEL` frame can supply 32 secret bytes at offsets 34–65 for an `mt-`
|
||||
channel. Non-MT channels and feature-disabled builds reject this variant with
|
||||
`PACKET_ERROR`; the standard 50-byte MeshCore command is unchanged. The MT
|
||||
backend uses AES-256 when the upper 16 bytes are nonzero, otherwise AES-128.
|
||||
|
||||
A legacy 50-byte SET of an existing MT channel preserves its upper 16 key
|
||||
bytes when the supplied lower half is unchanged. This permits an old client's
|
||||
GET/edit/SET round trip without silently truncating a provisioned AES-256 key.
|
||||
To explicitly replace or downgrade that key, send the full 32-byte variant
|
||||
(zero the upper half for AES-128). A client using only the legacy GET cannot
|
||||
export a complete AES-256 key. Stock app editors do not gain 256-bit
|
||||
provisioning or sharing from this firmware extension.
|
||||
|
||||
For local CLI provisioning without implementing the binary extension, use
|
||||
`set mt.channel` with a 32- or 64-digit hexadecimal PSK; see the
|
||||
[private-channel commands](radio_profiles.md#meshtext-channel-chat).
|
||||
|
||||
MT channel changes can also fail with a bad-state error for conflicting
|
||||
presets, an unsuitable manual radio2 profile, ambiguous region or a busy
|
||||
automatic owner. See [Meshtext channel chat](radio_profiles.md#meshtext-channel-chat).
|
||||
|
||||
**Response**: `PACKET_OK` (0x00) on success, `PACKET_ERROR` (0x01) on failure
|
||||
|
||||
@@ -1031,7 +1065,9 @@ Bytes 2-33: Channel Name (32 bytes, null-terminated)
|
||||
Bytes 34-49: Secret (16 bytes)
|
||||
```
|
||||
|
||||
**Note**: The device returns the 16-byte channel secret in this response.
|
||||
**Note**: The normal response contains the 16-byte channel secret. An opt-in
|
||||
32-byte MT GET described above extends the secret through byte 65; response
|
||||
code, index and name fields remain unchanged.
|
||||
|
||||
**PACKET_DEVICE_INFO** (0x0D):
|
||||
```
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/companion_radio_full/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Full Companion
|
||||
|
||||
Configure message alerts with the [Companion notification builder](notifications.md).
|
||||
@@ -521,6 +525,26 @@ their views. Companion session state is device-wide, so use one active
|
||||
Companion application at a time. On nRF52, BLE remains available while USB is
|
||||
in terminal or mOTA mode.
|
||||
|
||||
The Companion TCP listener starts only after a usable WiFi station or setup-AP
|
||||
address exists. If opening the socket fails, it closes any failed-start socket
|
||||
and retries with a delay capped at 30 seconds, without restarting the WiFi
|
||||
connection or disturbing BLE, WebConfig, OTA, or a healthy accepted TCP client.
|
||||
Turning WiFi off or suspending it cancels the listener request; retry service
|
||||
cannot turn it back on. Use `get wifi.tcp` through BLE, USB, or the browser CLI
|
||||
to inspect listener state, registration, accepted clients, completed RX/TX
|
||||
frames, and errors without a PC port probe. `get display.wifi` also shows the
|
||||
actual `tcp` listener flag independently of the network-services flag. A
|
||||
listening socket alone cannot detect LAN firewall or guest-network isolation.
|
||||
|
||||
ESP32 TCP sends are non-blocking, and inbound commands are serviced alongside
|
||||
outgoing data rather than waiting for an empty transmit queue. Unsolicited
|
||||
radio logs therefore cannot keep the app handshake unread. A live client with
|
||||
pending output is disconnected after 10 seconds without write progress;
|
||||
other transports continue running. Required replies retain their queue slots,
|
||||
so a new command waits if no reply can be admitted. Partially sent frames
|
||||
remain pinned to preserve framing, while already queued replies keep the same
|
||||
reconnection rules below.
|
||||
|
||||
On WiFi TCP port 5000, reconnecting from the same IP retains queued outgoing
|
||||
frames. A different IP takes over immediately, but never receives the previous
|
||||
IP's replies: up to four queued frames are parked separately for 30 seconds
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/companion_usb_ascii_validation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/companion_usb_ascii_validation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/companion_usb_client_validation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/companion_usb_client_validation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/docs/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Local Documentation
|
||||
|
||||
This document explains how to build and view the MeshCore documentation locally.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/double_frequency_v4_validation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/double_frequency_v4_validation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/esp32_memory_budget/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../research/esp32_memory_budget/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/esp32_partition_catalog/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# ESP32 release partition lookup table
|
||||
|
||||
The canonical LUT is `firmware/esp32_partition_catalog.json` in this fork.
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
# ESP32 legacy-partition migration over Wi-Fi or LoRa
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/esp32_wifi_partition_migration/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# ESP32 legacy-partition migration over USB, Wi-Fi or LoRa
|
||||
|
||||
The partition-migration bridge lets a supported ESP32 node move from a small
|
||||
dual-OTA layout to a verified larger dual-OTA layout without cable flashing or
|
||||
@@ -8,6 +12,20 @@ verified old OTA receiver so it can fetch the Full image into the expanded
|
||||
inactive slot. On 8/16 MiB flash the bridge restores identity before handing
|
||||
off; the 4 MiB route keeps identity staged until the Full image's first boot.
|
||||
|
||||
The distinct USB version performs verified identity/configuration restoration
|
||||
before the host writes the final app. It keeps application USB CDC disabled
|
||||
during flash operations and prevents Arduino startup from automatically
|
||||
erasing damaged/full NVS. S3/C3 return to ROM download automatically once
|
||||
restoration settles; original ESP32 reports matching-MAC settled UART status
|
||||
before the host uses DTR/RTS. Neither route needs physical BOOT access, but
|
||||
classic boards require their working USB-UART automatic-reset circuit.
|
||||
|
||||
The host must verify the same physical USB device and original chip MAC, the
|
||||
exact target table, CRC-valid NVS restored/no-pending markers, and current OTA
|
||||
metadata before flashing the unchanged final app. USB reappearance, a timer,
|
||||
or settled status alone is not recovery proof. An interrupted migration retains
|
||||
its pending host record and device-side restoration markers for a safe retry.
|
||||
|
||||
It has explicit, byte-for-byte generated target plans for the 4 MiB MeshCore
|
||||
dual-OTA Full table and Arduino ESP32 `default_8MB.csv` and
|
||||
`default_16MB.csv`. It does not guess a table for other flash sizes. Adding a
|
||||
@@ -101,6 +119,42 @@ ZIPs appear under `.releases/esp32-expanded-<commit>/packages/`. The recipe
|
||||
requires a clean checkout so each ZIP identifies the firmware commit it was
|
||||
built from. It creates files only; it does not flash a device or erase flash.
|
||||
|
||||
## Independent USB firmware set
|
||||
|
||||
The USB intermediate firmware has six distinct chip/flash-capacity builds:
|
||||
|
||||
| Chip | Flash capacities | USB completion |
|
||||
| --- | --- | --- |
|
||||
| Original ESP32 | 4, 8 MiB | Settled UART status, then host DTR/RTS |
|
||||
| ESP32-C3 | 4 MiB | Automatic ROM return |
|
||||
| ESP32-S3 | 4, 8, 16 MiB | Automatic ROM return |
|
||||
|
||||
To build only this complete set, without rebuilding or relabeling any Full
|
||||
firmware release, run serially in WSL/Linux:
|
||||
|
||||
```bash
|
||||
python3 -B scripts/build_esp32_partition_migration.py --usb-only
|
||||
```
|
||||
|
||||
This creates `meshcore-usb-partition-bridges.zip` under
|
||||
`.releases/esp32-usb-bridges-<commit>/`. Its manifest records each binary's chip,
|
||||
capacity, bytes and SHA-256, plus the utility source commit, dirty-tree state
|
||||
and runtime/configuration source hashes. All six are mandatory, and both the
|
||||
USB migration and NVS no-autoerase guard markers are verified. Existing Wi-Fi
|
||||
and LoRa artifacts remain unchanged. Exact new board/role migration packages
|
||||
also include their matching `usb-bridge.bin`.
|
||||
|
||||
A host can pair this standalone set with an older, exact Full migration ZIP;
|
||||
the Full image retains its original release/source identity. Meshfirmware
|
||||
downloads a versioned, checksum-pinned published USB set when a qualified
|
||||
older package has no USB bridge. It does not use an untested `latest` bridge,
|
||||
and an ordinary update that fits does not download migration utilities.
|
||||
For an offline or explicitly selected set, use `MESHFIRMWARE_USB_MIGRATION_SET`,
|
||||
or place the ZIP beside the flasher at `tools/meshcore-usb-partition-bridges.zip`.
|
||||
The original Full
|
||||
package must still match the selected final image and prove the target layout.
|
||||
No app-only upload or manual partition-table write substitutes for that proof.
|
||||
|
||||
The catalog covers canonical ESP32 repeater, room-server, and sensor roles on
|
||||
4, 8, and 16 MiB chip-family plans, including historical 1.25 MiB candidates
|
||||
now built with expanded tables. This includes ESP32-S3, original ESP32, and
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/espnow_bridge_setup/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# ESP-NOW bridge: simple setup
|
||||
|
||||
Use two ESP32 LoRa boards to join two MeshCore networks with different radio
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/faq/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Frequently Asked Questions
|
||||
|
||||
For this fork's **1.17.1.5 USA Cascade** release, start with
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/filter_tool/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Filter policy playground
|
||||
|
||||
Build a forwarding policy, see its readable definition, and simulate how a
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/firmware_memory_budget/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../research/firmware_memory_budget/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
+40
-16
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/firmware_picker/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Firmware picker
|
||||
|
||||
Each result now includes **Restore your settings after flashing**. Its commands
|
||||
@@ -21,11 +25,23 @@ Chip family and hardware are the only dropdowns. All remaining choices use
|
||||
buttons. **Firmware profile** combines OTA support, Full/standard, and sensor
|
||||
or storage differences when a choice between different images is needed.
|
||||
|
||||
RAK3401 and RAK4631 repeaters use one unified image per sensor policy for
|
||||
supported internal and external OTA storage. **Full** and **Reduced** choose
|
||||
optional sensor drivers; they do not select a storage module. The unified
|
||||
RAK4631 image also includes RS-232 on UART2, which is recommended for new
|
||||
installations. The unified image reserves UART1 for potentially powered GPS
|
||||
hardware; header-connected W25 flash also occupies UART1 pins. Legacy GPS-free
|
||||
Serial1 downloads remain available through exact-filename search for existing
|
||||
wiring, but are omitted from normal choices when the matching unified sensor
|
||||
profile is available. Ethernet remains a separate RAK4631 hardware image.
|
||||
LoRa OTA still requires the matching
|
||||
OTAFIX bootloader and a package compatible with the installed target.
|
||||
|
||||
The picker reads public release metadata from GitHub. It does not upload device
|
||||
information. Hardware names, target names, and download links come directly
|
||||
from the published firmware assets.
|
||||
|
||||
<div class="firmware-picker" data-firmware-picker data-release-repo="mikecarper/MeshCore" data-controls-url="../_data/firmware_controls.json?v=1.17.1.8-runtime-1" data-bootloaders-url="../_data/bootloader_manifest.json?v=20261002-1" data-share-url="https://mikecarper.github.io/MeshCore/firmware_picker/">
|
||||
<div class="firmware-picker" data-firmware-picker data-release-repo="mikecarper/MeshCore" data-controls-url="../_data/firmware_controls.json?v=1.17.1.9-88c85108" data-bootloaders-url="../_data/bootloader_manifest.json?v=20261002-1" data-share-url="https://mikecarper.github.io/MeshCore/p/">
|
||||
<div class="firmware-picker-intro" role="note">
|
||||
<strong>Current release set</strong>
|
||||
<p data-role="release-set">Loading release information...</p>
|
||||
@@ -54,7 +70,7 @@ from the published firmware assets.
|
||||
<p class="firmware-picker-order-note">
|
||||
Pick in any order. Use <strong>Any</strong> to clear one choice, or clear
|
||||
everything with the button below. The address bar updates with your choices;
|
||||
copy its URL to reopen or share the same selection.
|
||||
use <strong>Copy link to settings</strong> for a shorter link to the same selection.
|
||||
</p>
|
||||
|
||||
<form class="firmware-picker-form" data-role="form">
|
||||
@@ -130,7 +146,7 @@ from the published firmware assets.
|
||||
<div class="firmware-picker-form-actions firmware-picker-wide">
|
||||
<button type="reset" data-action="clear" disabled>Clear all choices</button>
|
||||
<button type="button" data-action="copy-link" disabled>Copy link to settings</button>
|
||||
<a data-role="share-link" hidden>Link to these settings</a>
|
||||
<a data-role="share-link" hidden>Short link to these settings</a>
|
||||
<p data-role="link-status" aria-live="polite"></p>
|
||||
</div>
|
||||
</form>
|
||||
@@ -233,30 +249,38 @@ changing roles or partition layouts.
|
||||
|
||||
## Share a selection
|
||||
|
||||
Select any combination of choices, then copy the address bar or use **Copy link
|
||||
to settings**. Opening the link restores those choices after the release
|
||||
Select any combination of choices, then use **Copy link to settings** for a
|
||||
short URL under `https://mikecarper.github.io/MeshCore/p/`. Opening the link
|
||||
restores those choices after the release
|
||||
catalog loads. Partial selections work too, so you can share a board and role
|
||||
while leaving other choices open. **Clear all choices** removes the picker
|
||||
parameters from the URL. Changes update the current browser-history entry
|
||||
without reloading the page or adding a Back-button entry for every click.
|
||||
|
||||
For example, [RAK3401 repeater with internal storage](?hardware=RAK_3401&role=repeater&ota=lora-receiver&variant=no-external-sensors)
|
||||
preselects that board, role, OTA capability, and storage profile.
|
||||
For example, [RAK3401 unified Full repeater](https://mikecarper.github.io/MeshCore/p/?s=1.hRAK_3401.rrepeater.olora-receiver.ffull.vdefault)
|
||||
preselects that board, role, OTA capability, and Full sensor policy. Supported
|
||||
internal or external storage is detected by the unified image.
|
||||
|
||||
The query parameters are `chipFamily`, `hardwareFamily`, `hardware`, `role`,
|
||||
Short links encode only the selected choices in a versioned `s` parameter.
|
||||
Hardware identifiers stay readable, and the link omits redundant hardware-family
|
||||
and automatically selected chip-family values. It keeps profile and install
|
||||
choices explicitly rather than relying on the current catalog's defaults.
|
||||
The address bar also uses the compact selection format; copying it works too.
|
||||
|
||||
Existing long links still work. Their query parameters are `chipFamily`, `hardwareFamily`, `hardware`, `role`,
|
||||
`logging`, `ota`, `mode`, `feature`, `variant`, and `install`. Values use the
|
||||
picker's internal identifiers rather than the displayed labels. One Firmware
|
||||
profile button sets `ota`, `feature`, and `variant` together. Existing links
|
||||
with only some of those choices still work and show their partial selection.
|
||||
The generated
|
||||
link also records `chipAuto` so automatic chip-family selection or an explicit
|
||||
The selection also records when chip-family filtering was chosen manually so
|
||||
automatic chip-family selection or an explicit
|
||||
**Any** choice behaves the same after reopening. Existing section anchors and
|
||||
unrelated query parameters are preserved.
|
||||
|
||||
Links use the current release catalog. If a linked choice is no longer available
|
||||
or conflicts with another choice, the picker identifies it and asks you to
|
||||
review the remaining selections. The downloadable HTML's **Copy link to
|
||||
settings** button creates a public website link that other people can open.
|
||||
settings** button creates a short public website link that other people can open.
|
||||
|
||||
## FULL versus standard
|
||||
|
||||
@@ -271,7 +295,7 @@ capacity and sensor-profile choices.
|
||||
Moving an older ESP32 installation to an expanded Full layout requires a
|
||||
partition migration.
|
||||
Use the exact-board merged image over USB, or a supported exact board and role
|
||||
staged migration ZIP from the [utility release](https://github.com/mikecarper/MeshCore/releases/tag/utility-v1.17.1.8-halo-keymind-cascade-dev-9053038f).
|
||||
staged migration ZIP from the [utility release](https://github.com/mikecarper/MeshCore/releases/tag/utility-v1.17.1.9-halo-keymind-cascade-dev-88c85108).
|
||||
Read that ZIP's README before choosing the Wi-Fi or LoRa route. Do not send a
|
||||
loose app-only Full `.bin` directly to an older layout: the running application
|
||||
cannot move its own active and inactive partitions. Run
|
||||
@@ -465,7 +489,7 @@ pin map, and other physical differences without crowding the Hardware dropdown.
|
||||
that need a different image or wiring, such as serial port or external storage.
|
||||
The picker skips this step when all available profile choices lead to the
|
||||
same firmware file.
|
||||
Future nRF52 repeater, room-server and sensor releases publish two separately
|
||||
The 1.17.1.9 nRF52 repeater, room-server and sensor releases publish two separately
|
||||
qualified choices: **Reduced sensors + LoRa OTA** and
|
||||
**Full supported sensors + LoRa OTA**, with `-reduced-ota` and `-full-ota` artifact suffixes. Each keeps
|
||||
its exact board/role OTA identity and storage layout; the suffix is not a new
|
||||
@@ -512,7 +536,7 @@ retains its optional dedicated interface `02`.
|
||||
Exact filename search finds compatibility images included in the selected
|
||||
release family. For older releases, open their GitHub release pages.
|
||||
|
||||
The 1.17.1.8 public matrix keeps one ESP32 Full image per board and role.
|
||||
The current public matrix keeps one ESP32 Full image per board and role.
|
||||
Some richer images, including Station G2 Full, retain an observer-named OTA
|
||||
identity. Exact older identities needed by a partition migration are packaged
|
||||
inside that board and role's migration ZIP instead of adding a second ordinary
|
||||
@@ -520,8 +544,8 @@ Full download. A deliberate target-ID override does not make a different
|
||||
partition layout or physical board compatible.
|
||||
|
||||
Some normal ESP32 roles begin in the legacy 1.25 MiB dual-OTA layout but have
|
||||
a Full image with larger slots. The 1.17.1.8 utility release contains 94 exact
|
||||
board and role migration ZIPs. Each package checks its source layout and target
|
||||
a Full image with larger slots. The utility release lists the exact
|
||||
board and role migration ZIPs available for that release. Each package checks its source layout and target
|
||||
identity, contains the bridge and Full application files for its supported
|
||||
routes, and documents what saved data it preserves. Use the package's own Full
|
||||
application after the bridge; do not substitute a loose Full image with a
|
||||
|
||||
@@ -0,0 +1,396 @@
|
||||
---
|
||||
layout: default
|
||||
title: Private fleet management
|
||||
---
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/fleet_management/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
|
||||
# Private fleet management
|
||||
|
||||
Fleet control lets one publisher send filtering, radio schedules, secondary-radio
|
||||
changes, and clock commands to
|
||||
all enrolled infrastructure nodes, regions, a geographic radius, one node, or a list of targets over a
|
||||
private LoRa channel.
|
||||
It is disabled until configured. It is supported on repeaters and room servers;
|
||||
fixed-size STM32 images omit it because of their flash limit.
|
||||
Both the publishing Companion and receivers need firmware built with fleet-control
|
||||
support; the existing app can use its local Command Line screen.
|
||||
|
||||
## Read-only receivers
|
||||
|
||||
Commands use two separate credentials:
|
||||
|
||||
- A random **128-bit channel key** encrypts the traffic. Receivers need this key
|
||||
to read the private channel.
|
||||
- The publisher's **Ed25519 public key** verifies commands. Only the publisher
|
||||
holds the corresponding private key and can authorize changes.
|
||||
|
||||
Giving a repeater the channel key and publisher public key does **not** give it
|
||||
the publisher's signing key. An ordinary channel message, a copied display name,
|
||||
or possession of the channel key cannot authorize a fleet command. Each command
|
||||
signature also binds the channel, target, sequence, expiry, and exact command.
|
||||
|
||||
This makes management commands read-only for receivers. It does not turn ordinary
|
||||
MeshCore chat into a signed, read-only announcement channel: stock apps do not
|
||||
verify signatures on ordinary channel text. Fleet acknowledgements are convenient
|
||||
channel text, not authenticated inventory evidence. Use existing individually
|
||||
authenticated administration for sensitive confirmation.
|
||||
|
||||
## Enroll nodes
|
||||
|
||||
Use an existing authenticated admin connection or the local console. Generate a
|
||||
random private channel key; for example, `openssl rand -hex 16`. Do not use Public
|
||||
or a predictable hashtag key. Add that same key as a private channel on the
|
||||
publishing Companion, and note its channel index.
|
||||
|
||||
Get the publishing Companion's full public identity key from its device information
|
||||
or existing identity command. On every managed repeater or room server, run:
|
||||
|
||||
```text
|
||||
set fleet.controller <publisher-public-key-64-hex>
|
||||
set fleet.channel <private-channel-key-32-hex>
|
||||
get fleet.channel
|
||||
get fleet.controller
|
||||
get fleet.stats
|
||||
```
|
||||
|
||||
`get fleet.channel` reports enrollment, storage health, a channel hash, and the
|
||||
last accepted sequence. It does not reveal the channel key. `set fleet.channel
|
||||
off` disables reception; `set fleet.controller off` revokes the publisher. Key
|
||||
changes use the existing individually authenticated admin path, never fleet
|
||||
commands.
|
||||
`get fleet.stats` includes `parts`, the number of fragments currently buffered
|
||||
across the two bounded, incomplete two-packet command slots.
|
||||
|
||||
Nodes need a clock set to current UTC. Commands expire after ten minutes and may
|
||||
be at most one minute ahead of a receiver's clock. A bad clock fails closed;
|
||||
correct it through the normal administration path.
|
||||
|
||||
## Send commands from the app
|
||||
|
||||
On the publishing Companion, use the existing local Command Line screen. The
|
||||
Companion signs with its own identity. No publisher private key is copied to a
|
||||
repeater, and no app protocol change is required.
|
||||
|
||||
Examples use private channel index `3`:
|
||||
|
||||
```text
|
||||
fleet send 3 get radio2
|
||||
fleet send 3 set tempradio2 910.5,500,8,5,rxtx,120
|
||||
fleet send 3 set radio2.cross auto
|
||||
fleet send 3 set flood.rule.4 type=grp_txt hops=6+ drop
|
||||
fleet send 3 del flood.rule.4
|
||||
```
|
||||
|
||||
Targets are optional: omitting the target sends to **all enrolled nodes** on the
|
||||
private fleet channel. Explicit `all` still works, for example
|
||||
`fleet send 3 all get radio2`.
|
||||
|
||||
To address particular nodes, insert **8 or 12 hexadecimal characters from the
|
||||
start of a node's public key**, or its **complete 64-character public key**, before
|
||||
the command. Separate multiple targets with semicolons, without spaces. Lengths can
|
||||
be mixed:
|
||||
|
||||
```text
|
||||
fleet send 3 1257aee5 get radio2
|
||||
fleet send 3 1257aee5a754;9abc0123 get radio2
|
||||
fleet send 3 1257aee5;9abc01234567 set radio2.cross auto
|
||||
```
|
||||
|
||||
These are example public-key prefixes; substitute your nodes' actual keys.
|
||||
**A prefix addresses every enrolled node whose public key starts with it.**
|
||||
Use all 64 characters when you need one exact identity, especially in a large
|
||||
fleet. Names and short LoRa path IDs are not accepted as target identities.
|
||||
`all` must appear alone. A node that matches several entries still executes the
|
||||
command only once, and the signature protects the entire list.
|
||||
|
||||
### Target existing regions
|
||||
|
||||
Fleet commands read each receiver's **existing region map**. Two selectors are
|
||||
available, and they can be mixed with public-key targets:
|
||||
|
||||
| Selector | Which receivers execute |
|
||||
| --- | --- |
|
||||
| `sea` or `region:sea` | Receivers with an exact `sea` entry in their configured region list |
|
||||
| `home:sea` | Receivers whose home region is `sea`, or whose home has `sea` as a parent or ancestor |
|
||||
|
||||
```text
|
||||
fleet send 3 sea get radio2
|
||||
fleet send 3 sea;pdx clock sync
|
||||
fleet send 3 region:sea set radio2.cross auto
|
||||
fleet send 3 home:sea get tempradio2
|
||||
fleet send 3 home:sea;home:pdx clock sync
|
||||
fleet send 3 sea;home:pdx;1257aee5 get radio2
|
||||
```
|
||||
|
||||
The semicolon-separated list is an **OR**: a receiver that matches any entry executes
|
||||
once, even if it matches several entries. Names match exactly and are case
|
||||
sensitive; `sea` does not match `seattle`. One leading `#` is an alias, as in the
|
||||
existing region commands. `$` remains significant for private region names.
|
||||
Names may contain up to 30 printable ASCII bytes using region-name characters.
|
||||
Use `region:` or `home:` explicitly for names with 8 or 12 characters, names
|
||||
made entirely of hexadecimal characters, or reserved command words such as
|
||||
`get`, `set`, `del`, `time` and `clock`. Bare `all` still means the entire fleet;
|
||||
`region:all` selects a region actually named `all`.
|
||||
|
||||
Inspect the existing configuration with `region` and `region home`. To choose a
|
||||
home from regions already defined on that receiver, use:
|
||||
|
||||
```text
|
||||
region home sea
|
||||
region save
|
||||
```
|
||||
|
||||
List matching includes a configured region even when forwarding for it is
|
||||
denied. Home matching follows the selected home's ancestry; a wildcard or unset
|
||||
home matches no named home target. The default transmit scope and the incoming
|
||||
packet's scope do not determine target membership. Region selection is checked
|
||||
against the live map when the complete command is received.
|
||||
|
||||
Targets select which nodes execute. Delivery still follows the Companion's
|
||||
channel scope and the intervening forwarding rules. Unknown names match no
|
||||
receivers and never become a whole-fleet request.
|
||||
|
||||
### Target a GPS center and radius
|
||||
|
||||
Use `gps:latitude,longitude:radius-km` to select receivers within a circle. For
|
||||
example, this selects nodes within **25 km** of the given Seattle coordinates:
|
||||
|
||||
```text
|
||||
fleet send 3 gps:47.6062,-122.3321:25 get radio2
|
||||
fleet send 3 gps:47.6062,-122.3321:25 set radio2.cross auto
|
||||
fleet send 3 sea;home:pdx;gps:47.6062,-122.3321:25;1257aee5 clock sync
|
||||
```
|
||||
|
||||
GPS, region, home and key selectors can share the same semicolon-separated list.
|
||||
They use the same OR rule: any matching entry selects the node, and the command
|
||||
executes once. The center, radius and complete target list are signed.
|
||||
The comma is only for the coordinate pair; `;` is the only target-list separator.
|
||||
|
||||
Coordinates use ordinary decimal degrees, with latitude from -90 to 90 and
|
||||
longitude from -180 to 180, and at most six decimal places. Radius is in
|
||||
kilometers, from **0.001 to 20050**, with at most three decimal places. For
|
||||
example, `0.5` means 500 meters. Scientific notation, excess decimal places,
|
||||
missing fields and out-of-range values are rejected without sending. Distance
|
||||
uses the great-circle calculation, including across the date line and near the
|
||||
poles; a node on the radius boundary is included.
|
||||
|
||||
Each receiver prefers its configured `lat` and `lon`. A stationary radio can
|
||||
have a fixed position even without GPS hardware; configure it through its
|
||||
normal administration connection:
|
||||
|
||||
```text
|
||||
set lat 47.6062
|
||||
set lon -122.3321
|
||||
get lat
|
||||
get lon
|
||||
```
|
||||
|
||||
When both configured coordinates are zero, the receiver can use an existing
|
||||
valid GPS cache no older than 12 hours. Matching never wakes GPS, takes a UART
|
||||
or requests telemetry. A missing, expired, invalid or default `(0,0)` position
|
||||
matches no GPS selector; it can still match another entry in the list. Invalid
|
||||
nonzero configured coordinates are rejected rather than falling back to GPS.
|
||||
For a stationary radio that lets GPS sleep for longer than 12 hours, configure
|
||||
its fixed coordinates.
|
||||
|
||||
Private fleet matching uses this position even when location is hidden from
|
||||
public adverts. It reads the position when the complete command arrives,
|
||||
including after the second fragment of a two-packet command, so a moving node
|
||||
is selected using its position at completion.
|
||||
|
||||
On air, full keys use a 128-bit SHA-256 digest; prefixes use their original
|
||||
public-key bytes. Whole-fleet commands use the compact FMC2 format with no target
|
||||
records, whether the CLI target is omitted or explicitly `all`. This reduces the
|
||||
header from 29 to 14 bytes. A single complete key uses the smaller fixed-target
|
||||
FMC1 format. Region, home and GPS selectors use separate signed record types in FMC2.
|
||||
Separate fleets use separate channel keys.
|
||||
|
||||
Only local commands on the publishing Companion can originate fleet sends. A
|
||||
remote CLI command cannot turn that Companion into a multicast signing proxy.
|
||||
An `OK` means the Companion queued the command, not that every receiver applied
|
||||
it. Wait for acknowledgements and confirm the result on important nodes.
|
||||
|
||||
Use at most one new command per second. The publishing Companion remembers its
|
||||
last queued sequence for the current boot; its clock supplies the next sequence.
|
||||
Each receiving node reserves the Unix-second sequence in durable storage
|
||||
**before** dispatch. That receiver never executes the same sequence twice,
|
||||
including after reboot or a lost reply. Retry an uncertain command with a fresh
|
||||
sequence; the operation should be chosen to be idempotent.
|
||||
|
||||
## Supported controls
|
||||
|
||||
The Companion automatically uses **one or two LoRa packets**, depending on the
|
||||
signed command's size. Whole-fleet commands fit **87 ASCII bytes** in one packet
|
||||
or **230 bytes** across two. Targets consume some of that allowance:
|
||||
|
||||
| Targets | One packet: command bytes | Two packets: command bytes |
|
||||
| --- | ---: | ---: |
|
||||
| Omitted or `all` | 87 | 230 |
|
||||
| One 8-character public-key prefix | 82 | 225 |
|
||||
| One 12-character public-key prefix | 80 | 223 |
|
||||
| One complete 64-character public key | 72 | 215 |
|
||||
| One three-character region or home name, such as `sea` | 82 | 225 |
|
||||
| Two three-character region or home names, such as `sea;pdx` | 77 | 220 |
|
||||
| One GPS center and radius | 74 | 217 |
|
||||
| Two 8-character public-key prefixes | 77 | 220 |
|
||||
| Two complete public keys | 53 | 196 |
|
||||
|
||||
Each prefix in a list uses 5 or 7 bytes; each complete key in a list uses 17.
|
||||
Each region or home selector uses two bytes plus its canonical name length.
|
||||
Each GPS selector uses 13 bytes: its type, latitude and longitude in millionths
|
||||
of a degree, and radius in meters.
|
||||
A single complete key uses the smaller fixed-target format with a 29-byte header,
|
||||
so its limits come from packet space. Lists are capped at 17 entries and 86 bytes
|
||||
of encoded target records; for example, at most six GPS selectors fit. Requests
|
||||
exceeding their target-specific budget are rejected before signing or sending,
|
||||
with no partial target list.
|
||||
|
||||
The existing app/console input limit also applies. The app's normal 176-byte
|
||||
command frame fits **161 command bytes** after `fleet send 3 `; a correlated
|
||||
request uses three more bytes, and explicit targets reduce the space further.
|
||||
The shorter USB rescue console has an 80-byte input buffer. The 230-byte limit
|
||||
is the fleet protocol's capacity, rather than a promise that every console can
|
||||
enter that much text. Oversized or invalid lists are rejected as a whole,
|
||||
without sending or truncating any targets.
|
||||
|
||||
### Two-packet delivery
|
||||
|
||||
Longer commands keep **one 64-byte signature over the entire command**, including
|
||||
its channel, targets, sequence and expiry. The signed envelope is split into two
|
||||
`FMP1` fragments. Each fragment has an 11-byte collection header and up to 154
|
||||
envelope bytes, within the existing 165-byte group-data limit. Together they can
|
||||
carry a 308-byte signed envelope. No third packet is used.
|
||||
|
||||
The Companion reserves both packets before sending. If either cannot be queued,
|
||||
it cancels the queued part and any radio copy, reports an error, and leaves the
|
||||
sequence available for a retry. Successful queueing still does not guarantee
|
||||
delivery over LoRa.
|
||||
|
||||
A receiver accepts either arrival order and identical duplicates. It executes
|
||||
and acknowledges **only after both parts arrive and the complete signature,
|
||||
target, clock and replay checks pass**. Missing or altered parts cannot execute
|
||||
a partial command. Two bounded assemblies are kept for up to five minutes
|
||||
from their respective first parts; duplicates do not extend those deadlines.
|
||||
Unverified fragment sequences cannot grant priority over another transfer. A
|
||||
third transfer replaces the oldest collection. A complete, valid signed command
|
||||
clears the partial collections, and durable replay checks remain authoritative.
|
||||
Reboot or changing enrollment discards the partial transfers.
|
||||
|
||||
| Control | Fleet commands |
|
||||
| --- | --- |
|
||||
| Saved second profile | `get radio2`, `set radio2 <tuple|off>` |
|
||||
| Temporary second profile | `get tempradio2`, `set tempradio2 <tuple|off>` |
|
||||
| Scheduled primary profile | `get/set/del radioat`, `get/set/del tempradioat` |
|
||||
| Scheduled second profile | `get/set/del radioat2`, `get/set/del tempradioat2` |
|
||||
| UTC clock | `clock`, `clock sync`, `time <epoch-seconds>` |
|
||||
| Profile diagnostics | `get radio2.status`, `get radio2.timing` |
|
||||
| Crossover | `get radio2.cross`, `set radio2.cross <auto|on|off>` |
|
||||
| Filter rules | `get/set/del flood.filter[.n]`, `flood.rule[.n]` |
|
||||
| Path blacklist | `get/set/del flood.filter.blacklist[.n]` |
|
||||
| Channel moderation | `get/set/del flood.moderation[.n]` |
|
||||
| Scope policy | `get/set/del flood.channel.scope[.n]`, `flood.channel.scope.require[.n]` |
|
||||
| Group-data forwarding | `get/set flood.channel.data`, `flood.channel.data.hops` |
|
||||
| Flood hop limits | `get/set flood.max`, `flood.max.unscoped`, `flood.max.advert` |
|
||||
|
||||
Each role still checks whether it supports the requested setting. Immediate
|
||||
primary radio changes, identity export, passwords, ACL edits, filesystem operations, firmware
|
||||
installation, reboot, and unrestricted CLI are outside fleet capability.
|
||||
|
||||
## Schedule radio changes and set clocks
|
||||
|
||||
Use the normal schedule syntax, with UTC epoch seconds or `+N` whole minutes.
|
||||
Primary schedules are supported by repeaters; a role without a primary scheduler
|
||||
replies that the command is unsupported. Second-profile schedules use `rx` or
|
||||
`rxtx` after the coding rate:
|
||||
|
||||
```text
|
||||
fleet send 3 clock
|
||||
fleet send 3 clock sync
|
||||
fleet send 3 set radioat 910.5,500,8,5,+5
|
||||
fleet send 3 set tempradioat 910.5,500,8,5,+5,+15
|
||||
fleet send 3 set radioat2 910.5,500,8,5,rxtx,+5
|
||||
fleet send 3 set tempradioat2 910.5,500,8,5,rxtx,+5,+15
|
||||
fleet send 3 1257aee5 get tempradioat2 1
|
||||
fleet send 3 1257aee5 del tempradioat2 all
|
||||
```
|
||||
|
||||
Both relative endpoints use the receiver's clock at command acceptance. For a
|
||||
coordinated fleet switch, use the same absolute UTC start/end timestamps on all
|
||||
nodes. An optional final preamble value or `auto` uses the existing radio syntax.
|
||||
Schedule capacity, radio-range validation, and overlap checks remain unchanged;
|
||||
pending schedules still do not survive reboot.
|
||||
|
||||
`clock sync` advances a receiver to the publishing Companion's signed timestamp
|
||||
plus one second. `time <epoch-seconds>` sets an explicit UTC timestamp. Both use
|
||||
the existing forward-only clock rule. Initial setup or a clock far out of sync
|
||||
still requires local or individually authenticated clock correction: fleet clock
|
||||
commands retain the signature, expiry, replay, and maximum-clock-lead checks.
|
||||
|
||||
Radio mutations and schedule edits keep the old state until their exact acknowledgement
|
||||
packets drain, with at least one successful physical transmission. Queue failure,
|
||||
failed transmissions, or an acknowledgement timeout cancels the staged mutation.
|
||||
Temporary-radio leases and scheduled windows retain their original monotonic end time; waiting for an
|
||||
acknowledgement does not lengthen them.
|
||||
|
||||
Exact single-node acknowledgements use 0.5-1.5 seconds of random delay; prefix,
|
||||
multiple-target, region, GPS and whole-fleet replies use 0.5-10 seconds, including
|
||||
radio mutations. Queuing, airtime and forwarding can add delivery time.
|
||||
This reduces simultaneous responses but is not a reliable
|
||||
delivery protocol for an arbitrarily large fleet. Use individual requests for
|
||||
confirmation and divide very large fleets into separately keyed channels.
|
||||
|
||||
## Filtering and recovery
|
||||
|
||||
Local fleet reception happens before a node's forwarding decision, so that node
|
||||
can still process an authenticated command when a filter or `repeat off` blocks
|
||||
forwarding. **Intermediate nodes can still block delivery to downstream nodes.**
|
||||
Management traffic has no automatic exemption from forwarding filters. Preserve
|
||||
an appropriate group-data/channel forwarding rule and an existing direct-admin
|
||||
recovery path before changing network-wide filters. Primary-radio schedules can
|
||||
move nodes off the normal network; use a temporary window or a planned recovery
|
||||
path for experiments. A forwarding policy can also partition the fleet.
|
||||
|
||||
The receiver is allocated lazily when fleet settings are present or queried, with
|
||||
one bounded mailbox and two 308-byte fragment assemblies, plus bounded metadata.
|
||||
Cryptographic work and storage writes occur after the receive stack unwinds.
|
||||
Signature-validation attempts are bounded after private-channel MAC verification,
|
||||
complete framing, replay, target, time and command checks. Keyless matching-hash
|
||||
junk, already-used requests, other nodes' requests and incomplete fragments do not
|
||||
spend that signature budget. A corrupt or unreadable fleet store denies commands
|
||||
rather than discarding its replay state.
|
||||
|
||||
## Ideas for packet-abuse containment
|
||||
|
||||
A packet-count chart can show a burst, but cannot establish intent, an authenticated
|
||||
source, or the airtime consumed. A large Trace spike deserves investigation;
|
||||
MeshCore already rejects flood-form Trace and Control packets. Valid direct Trace
|
||||
requests need different treatment from flood forwarding rules.
|
||||
|
||||
Useful next additions, rather than features already implemented here:
|
||||
|
||||
- **Temporary containment with automatic rollback:** deploy a drop/rate policy
|
||||
for a bounded period and restore the previous policy unless confirmed.
|
||||
- **Direct-request rate limits:** separately bound Trace, anonymous requests,
|
||||
discovery, login, and expensive response generation without breaking legitimate
|
||||
management, ACKs, or ongoing OTA exchanges.
|
||||
- **Policy preview and revisions:** validate complete rule bundles, detect board
|
||||
limitations, apply atomically, and report the active revision before rollout.
|
||||
- **Better evidence:** report per-type receive/drop counts, airtime, queue pressure,
|
||||
invalid signatures, duplicate rate, and radio recoveries. Truncated path IDs
|
||||
remain observations, not authenticated attacker identities.
|
||||
- **Authenticated inventory:** stagger signed status replies with firmware version,
|
||||
uptime/reset reason, battery, memory/storage headroom, and radio errors.
|
||||
- **Maintenance windows:** coordinated secondary-profile experiments and OTA
|
||||
readiness checks, keeping existing firmware-signing policy intact.
|
||||
- **Per-controller roles and revocation:** multiple public verification keys with
|
||||
separate filter-only/radio permissions and independent replay state.
|
||||
|
||||
Start with observation, then a narrow temporary rule, then verify neighboring
|
||||
nodes still communicate. Software filtering can reduce forwarding and response
|
||||
amplification; it cannot recover airtime already occupied by an RF transmitter.
|
||||
|
||||
See [flood filtering](flood_filtering.md), [radio profiles](radio_profiles.md), and
|
||||
[ACL administration](cli_commands.md#acl).
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/flood_filtering/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Flood Filtering and Moderation
|
||||
|
||||
This guide explains the Keymind forwarding filters. Repeaters expose the full
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/four_fixed_tx_dwell_validation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/four_fixed_tx_dwell_validation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/four_fixed_tx_single_pass_validation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/four_fixed_tx_single_pass_validation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/full_companion_features/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Full Companion: turn features on and off
|
||||
|
||||
For side-by-side Companion and infrastructure commands, see
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/full_companion_usb_switcher/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Companion USB CLI and binary switcher
|
||||
|
||||
USB Companion uses one primary USB serial interface for two incompatible wire
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/full_profiles/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Full firmware profiles
|
||||
|
||||
Full combines the features supported by an exact board and firmware role in
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/full_usb_logging_validation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/full_usb_logging_validation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
+40
-2
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/gps_tracking/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# GPS Tracking
|
||||
|
||||
This document describes how GPS telemetry works for companion/client nodes and
|
||||
@@ -46,10 +50,11 @@ GPS on, and manual GPS-on still keeps the cache updated.
|
||||
|
||||
Repeaters use a shorter on-demand policy when GPS is manually off. An authorized
|
||||
location-telemetry request wakes the receiver only when its cached position is
|
||||
stale. The first valid fix is cached and the receiver immediately powers down;
|
||||
stale. The first valid fix is cached and GPS processing immediately stops;
|
||||
the next request can return that fix without another wake. `gps off` also
|
||||
cancels an acquisition already in progress. An acquisition that never obtains a
|
||||
fix retains the normal 15-minute safety timeout.
|
||||
fix retains the normal 15-minute safety timeout. Physical supply switching
|
||||
depends on the board and its shared peripheral policy.
|
||||
|
||||
When GPS and device power saving are both enabled, a repeater wakes GPS for up
|
||||
to 10 minutes to obtain a valid time and then sleeps it for seven days. A valid
|
||||
@@ -57,6 +62,39 @@ GPS time may correct the RTC either forward or backward. With device power
|
||||
saving off, an enabled GPS remains active and refreshes the RTC every 30
|
||||
minutes.
|
||||
|
||||
## RAK WisBlock Power Supply
|
||||
|
||||
RAK4631 defaults to saved peripheral mode `gps-only`. With no protected power
|
||||
owner, stopping or sleeping GPS can turn off the shared `3V3_S` rail. If other
|
||||
attached modules need that rail, explicitly select shared mode:
|
||||
|
||||
```text
|
||||
get peripherals.mode
|
||||
set peripherals.mode shared
|
||||
reboot
|
||||
```
|
||||
|
||||
Use `set peripherals.mode gps-only` and reboot to return to the default.
|
||||
Changes are saved for the next boot, not applied live; the query reports the
|
||||
saved choice. Other peripheral requirements are not guessed from an I2C scan.
|
||||
Boot and discovery keep the rail on until the power policy is established.
|
||||
|
||||
This saved setting is available in Companion and Common CLI roles (repeater,
|
||||
room server, and sensor). Raw KISS and legacy Terminal Chat do not configure
|
||||
it and retain the powered rail. Shared mode controls the supply; it does not
|
||||
add Ethernet support to a non-Ethernet firmware target.
|
||||
|
||||
Ethernet/PoE builds and detected external NOR storage automatically retain
|
||||
power regardless of this setting. RAK3401 always retains the rail for its radio
|
||||
frontend and does not offer this override.
|
||||
|
||||
In shared mode, GPS-off does not mean the supply is off. In particular, the
|
||||
[RAK12501/L76K module](https://docs.rakwireless.com/product-categories/wisblock/rak12501/datasheet/)
|
||||
has no independent power switch: stopping MCU parsing leaves the receiver
|
||||
powered. Internal sleep support on other GNSS modules is receiver-dependent.
|
||||
This setting does not remove the UART1 bridge conflict or authorize another
|
||||
transmitter on the GPS wiring.
|
||||
|
||||
## Companion/Client Nodes
|
||||
|
||||
Companion/client telemetry uses the existing companion telemetry permission
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/halo_keymind_settings/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Halo and Keymind Branch Settings
|
||||
|
||||
This file covers only CLI settings and helper commands added by the Halo or
|
||||
@@ -199,6 +203,10 @@ rows; an unpaged local serial query prints the full table.
|
||||
`outpath` and `altpath` apply to the current remote client ACL entry. They need
|
||||
remote client context, so they are not useful from the local serial CLI.
|
||||
|
||||
Room Server also supports these commands for readers and writers, restricted
|
||||
to the caller's own routes. See [room return routes](room_services.md#your-own-return-routes)
|
||||
for session persistence, alternate chat delivery and client requirements.
|
||||
|
||||
Set paths with comma-separated hop hashes. Each hop must be `2`, `4`, or `6`
|
||||
hex characters, and all hops in one path must use the same width. Hex input is
|
||||
case-insensitive. Replies use uppercase hex and retain the commas, so the value
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/hardware_validation_bluetooth_stealth_2026-09-07/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Report moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/hardware_validation_bluetooth_stealth_2026-09-07/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/hardware_validation_checklist/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/hardware_validation_checklist/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/heltec_v4_wifi_partition_migration/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Heltec V4 legacy-partition migration over Wi-Fi
|
||||
|
||||
Heltec V4/V4.3 OLED repeaters with their normal 16 MiB flash use the shared
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/home_text_spacing/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/home_text_spacing/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/host_cli_service/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# LoRa CLI Host Service
|
||||
|
||||
The repeater `host <text>` command lets an authenticated LoRa administrator
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# MeshCore documentation
|
||||
|
||||
Choose firmware with the [firmware picker](firmware_picker.md). For help with a device already in service, start with the [FAQ](faq.md).
|
||||
@@ -12,6 +16,8 @@ Choose firmware with the [firmware picker](firmware_picker.md). For help with a
|
||||
- [Feature switches by role](role_feature_switches.md) and [Full Companion features](full_companion_features.md)
|
||||
- [Firmware update guide](ota_user_guide.md), [easy LoRa OTA](ota_easy.md), and [scripted LoRa OTA](lora_ota_automation.md)
|
||||
- [CLI commands](cli_commands.md), [availability by build](cli_build_matrix.md), and [radio profiles](radio_profiles.md)
|
||||
- [Private fleet management](fleet_management.md): signed filtering and secondary-radio commands for a fleet or one node
|
||||
- [Room history, moderation, and information board](room_services.md): optional persistent chat and local Wi-Fi room access
|
||||
- [Companion protocol](companion_protocol.md), [packet format](packet_format.md), and [QR codes](qr_codes.md)
|
||||
|
||||
The navigation groups the remaining guides under Documentation, including board-specific updates, networking, power, and protocol references.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/kiss_modem_protocol/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# MeshCore KISS Modem Protocol
|
||||
|
||||
Standard KISS TNC firmware for MeshCore LoRa radios. Compatible with any KISS client (Direwolf, APRSdroid, YAAC, etc.) for sending and receiving raw packets. MeshCore-specific extensions (cryptography, radio configuration, telemetry) are available through the standard SetHardware (0x06) command.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/lora_ota_automation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Scripted LoRa OTA from start to finish
|
||||
|
||||
For **1.17.1.5**, use the exact board/storage profile from
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/management_decoder/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Management report decoder
|
||||
|
||||
Paste MGR1 or MGR2 management-report payloads or complete GroupData packets from a
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/management_reports/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Management reports (MGR1/MGR2)
|
||||
|
||||
Available on repeater (including observer), room-server and sensor firmware.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/mbedtls-tls-footprint/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/mbedtls-tls-footprint/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/mixed_scan_validation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/mixed_scan_validation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/mixed_sf_bw_validation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/mixed_sf_bw_validation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/nimble_companion_trial/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/nimble_companion_trial/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/nimble_companion_trial_results/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/nimble_companion_trial_results/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/notifications/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Companion notification builder
|
||||
|
||||
Make a rule, preview it here, then copy the CLI commands or apply and test it
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/nrf52-usb-ready-fix/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/nrf52-usb-ready-fix/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/nrf52_bluetooth_debug/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../research/nrf52_bluetooth_debug/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/nrf52_companion_storage_recovery/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/nrf52_companion_storage_recovery/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/nrf52_power_management/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# nRF52 Power Management
|
||||
|
||||
## Overview
|
||||
@@ -221,6 +225,10 @@ DEBUG: PWRMGT: LPCOMP wake configured (AIN7, ref=3/8 VDD)
|
||||
|
||||
## Further power-management work (Planned)
|
||||
|
||||
For the opt-in Sensor check-in workflow using System ON idle sleep and bounded
|
||||
GPS acquisition, see [Sensor dog tracker](sensor_tracker.md). It is separate
|
||||
from the battery-protection SYSTEMOFF shutdown described here.
|
||||
|
||||
- A voltage state machine (Normal -> Warning -> Critical -> Shutdown)
|
||||
- Configurable wake comparator thresholds
|
||||
- Load shedding callbacks for power reduction
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/number_allocations/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Number Allocations
|
||||
|
||||
This document lists unique numbers/identifiers used in various MeshCore protocol payloads.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/old-releases/1.17.1.5-doc-audit/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Markdown audit — 1.17.1.5 USA Cascade
|
||||
|
||||
Audited on 2026-09-05 against firmware source `26303793`, the resolved build
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/old-releases/1.17.1.5/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# MeshCore 1.17.1.5 Dev - USA Cascade
|
||||
|
||||
Use [feature switches by role](../role_feature_switches.md) for exact on/off
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/old-releases/1.17.1.6/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# MeshCore 1.17.1.6 Dev - USA Cascade
|
||||
|
||||
This release builds the current `keymindCascade` source after repairing the
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/old-releases/1.17.1.7/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# MeshCore 1.17.1.7 USA Cascade
|
||||
|
||||
This development release uses 910.525 MHz, 62.5 kHz bandwidth, SF7, and CR5 with Cascade defaults. Saved radio settings take precedence. The firmware source is `2d03e098cf75d58adcf35fe3d4dbbeaf0af114e1`.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/old-releases/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Old Releases
|
||||
|
||||
Historical release notes and their supporting files are kept here for reference. Use the [current 1.17.1.8 release notes](../releases/1.17.1.8.md) for current firmware.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/ota_easy/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Easy firmware updates over LoRa
|
||||
|
||||
For **1.17.1.5**, use the exact board/storage profile from
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/ota_meshtower_v2_sdcard/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# MeshTower V2 microSD LoRa OTA
|
||||
|
||||
`Heltec_tower_v2_sdcard_repeater_lora_ota_no_external_sensors` is the one
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/ota_nrf52_bootloader_update/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# nRF52 bootloader updates over LoRa
|
||||
|
||||
For **1.17.1.5**, use the exact board/storage profile from
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/ota_nrf52_qspi/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# nRF52 repeater LoRa OTA with external QSPI
|
||||
|
||||
For **1.17.1.5**, use the exact board/storage profile from
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/ota_protocol/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# MeshCore OTA - `.mota` container & LoRa protocol
|
||||
|
||||
This is the **single source of truth** for MeshCore's over-the-air firmware update system ("mOTA"). It is
|
||||
|
||||
+31
-6
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/ota_user_guide/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Updating your node over the air (OTA) - user guide
|
||||
|
||||
For **1.17.1.5**, use the exact board/storage profile from
|
||||
@@ -420,6 +424,10 @@ and packet loss; `3` does not guarantee three times the throughput.
|
||||
|
||||
The factor covers OTA requests and responses (catalog, manifest, leaves, DATA,
|
||||
and proofs), OTA relay delays, discovery jitter, and automatic OTA adverts.
|
||||
Sources queue manifest and leaf replies and admit their fragments one at a
|
||||
time through the paced transmit queue. Repeated requests merge pending
|
||||
fragments; a full response queue leaves the request available for another
|
||||
source or a later retry. This preserves packet space for other mesh traffic.
|
||||
Below `1`, the transmit queue also spaces out **every OTA packet**, including
|
||||
both profile copies, while letting ordinary messages run. Recovery waits grow
|
||||
for slower transfers; faster settings retain the existing retry allowance so
|
||||
@@ -465,7 +473,7 @@ automation (e.g. for a remote node you can't easily reach), you can opt in. Thes
|
||||
|
||||
```
|
||||
ota config autofetch any # auto-DOWNLOAD any compatible update for this node (still won't install)
|
||||
ota config autofetch signed # auto-download only signed updates
|
||||
ota config autofetch signed # auto-download verified updates from allowlisted signers
|
||||
ota config autofetch off # back to manual (default)
|
||||
|
||||
ota config autoinstall trusted # auto-INSTALL only a trusted signed version newer than the running EndF
|
||||
@@ -480,9 +488,18 @@ ota config hops 0 # only exchange OTA with directly-connected node
|
||||
ota config # show the current settings
|
||||
```
|
||||
|
||||
These policies also govern automatic adoption of an interrupted staged download after reboot. `off` leaves
|
||||
it untouched, `signed` requires the stored manifest's signed flag, and automatic resume requires the stored
|
||||
target to match this node and its version to be newer than the running valid EndF. Reissuing an explicit
|
||||
With `autofetch signed`, add the author's public key using `ota key add` before
|
||||
expecting an automatic download. The node verifies the manifest's signature
|
||||
against that allowlist before planning, erasing, or writing staging storage.
|
||||
`autofetch any` remains the deliberate option for automatically downloading
|
||||
unsigned compatible packages; it does not authorize installation.
|
||||
|
||||
These policies also govern automatic adoption of an interrupted staged
|
||||
download after reboot. `off` leaves it untouched; `signed` requires the same
|
||||
allowlisted signature verification. Automatic resume also requires the stored
|
||||
target to match this node and its version to be newer than the running valid
|
||||
EndF. The signature check applies when an automatic download resumes after
|
||||
discovering a source or reconnecting its storage. Reissuing an explicit
|
||||
`ota pull <MID8>` remains the deliberate override for an older or unsigned partial.
|
||||
For bring-up/debugging, `ota dev resume <MID8>` performs the same explicit MID-bound re-adoption without
|
||||
starting a new network fetch. After reboot it requires the MID; bare `ota dev resume` is accepted only while
|
||||
@@ -492,6 +509,13 @@ guessing which is newest. Specify the intended MID to select its unique checkpoi
|
||||
rejected. Temporary storage read failures no longer consume a download slot indefinitely: host storage
|
||||
pauses for reconnection, while non-reconnectable storage reports a storage error and can be retried.
|
||||
|
||||
A failed automatic download starts a cooldown before other automatic candidates
|
||||
are considered: one minute initially, doubling after further failures up to
|
||||
15 minutes. Changing the offered image or source does not skip this wait.
|
||||
The timer uses elapsed uptime, and a completed download clears it. Manual
|
||||
`ota pull`, explicit resume, and archive captures keep their existing operator
|
||||
controls and are not restricted by this automatic-download cooldown.
|
||||
|
||||
Recommended for most people: leave both **off** and update by hand. Use `autoinstall trusted` only once
|
||||
you've added the signer's key (next section) and you trust them to push updates unattended. Automatic
|
||||
admission and final apply both reject zero, equal, or older signed versions; a dishonest catalog version
|
||||
@@ -509,8 +533,9 @@ for the required `/mota/<manifest-id>.mota` filenames and the complete TempRadio
|
||||
|
||||
## Optional: only trust updates from specific people
|
||||
|
||||
If you'll use auto-install, tell your node which signing keys to trust. The firmware author shares their
|
||||
**public** key (a hex string); you add it:
|
||||
If you'll use signed auto-download or auto-install, tell your node which
|
||||
signing keys to trust. The firmware author shares their **public** key (a hex
|
||||
string); you add it:
|
||||
|
||||
```
|
||||
ota key add <public-key-hex> # trust this signer
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>MeshCore firmware picker</title>
|
||||
<link rel="canonical" href="../firmware_picker/">
|
||||
</head>
|
||||
<body>
|
||||
<p>Opening the firmware picker. <a id="picker-link" href="../firmware_picker/">Continue to the picker</a>.</p>
|
||||
<script>
|
||||
(function () {
|
||||
"use strict";
|
||||
const target = new URL("../firmware_picker/", window.location.href);
|
||||
target.search = window.location.search;
|
||||
target.hash = window.location.hash;
|
||||
document.getElementById("picker-link").href = target.href;
|
||||
window.location.replace(target.href);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/packet_format/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Packet Format
|
||||
|
||||
This document describes the MeshCore packet format.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/pair_4p6_300us_validation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/pair_4p6_300us_validation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/pair_preamble32_validation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/pair_preamble32_validation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/payloads/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Payload Format
|
||||
|
||||
Inside each [MeshCore Packet](./packet_format.md) is a payload, identified by the payload type in the packet header. The types of payloads are:
|
||||
@@ -112,6 +116,7 @@ For the common chat/server helpers in `BaseChatMesh`, the current request type v
|
||||
| `0x06` | get neighbors | node neighbors query |
|
||||
| `0x08` | subscribe | subscribe to telemetry push |
|
||||
| `0x09` | ubsubscribe | unsubscribe from telemetry push |
|
||||
| `0x0C` | tracker status | encrypted Sensor dog tracker check to a configured owner's Companion; [wire format](sensor_tracker.md#encrypted-check-format) |
|
||||
|
||||
#### Get stats
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/pr7_review_validation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/pr7_review_validation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/preamble_detection_investigation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/preamble_detection_investigation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/preset_test/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# <span data-role="preset-test-page-title">Temporary radio test builder</span>
|
||||
|
||||
<span data-role="preset-test-page-summary">Choose a window and radio tuple to
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/qr_codes/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# QR Codes
|
||||
|
||||
This document provides an overview of QR Code formats that can be used for sharing MeshCore channels and contacts. The formats described below are supported by the MeshCore mobile app.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/radio_chirp_math_validation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/radio_chirp_math_validation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/radio_dwell_policy_validation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/radio_dwell_policy_validation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/radio_profile_switch_validation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/radio_profile_switch_validation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/radio_profiles/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Two LoRa profiles on one radio
|
||||
|
||||
`radio2` lets one LoRa transceiver alternate between two frequencies or modulation
|
||||
@@ -237,6 +241,272 @@ its choice. They use reserved bytes in existing saved records, so record
|
||||
sizes and the phone protocol are unchanged. Older firmware ignores these
|
||||
bytes and may reset the choices when it saves the records.
|
||||
|
||||
## Companion channel-name routing aliases
|
||||
|
||||
Companions recognize the case-sensitive prefixes `r2-` and `mt-`, immediately
|
||||
after the optional leading `#`. Keep the prefix in the app's displayed name.
|
||||
For MeshCore aliases, the firmware strips exactly one prefix when deriving an
|
||||
automatic hashtag key:
|
||||
|
||||
```text
|
||||
#emergency -> hashtag key for #emergency
|
||||
#r2-emergency -> the same key for #emergency
|
||||
#mt-emergency -> the same key for #emergency only in MeshCore fallback mode
|
||||
```
|
||||
|
||||
Only the app's automatic, name-derived hashtag key is normalized; a supplied
|
||||
private key is not replaced. Non-hashtag names such as `r2-Private` also retain
|
||||
their supplied key. Empty or nested prefixes (`r2-`, `#r2-mt-emergency`) are
|
||||
rejected. MeshCore hashtag names remain case-sensitive.
|
||||
|
||||
When radio2 is configured (`rx` or `rxtx`), `r2-` binds the channel to radio2 for
|
||||
both send and receive, including emergency retransmissions. It overrides global
|
||||
crossing and cannot be changed with `set tx.channel`; rename the channel to
|
||||
remove the binding. RX-only radio2 cannot send. If radio2 is off/unconfigured,
|
||||
ignore the routing prefix and use ordinary MeshCore routing instead. The key
|
||||
stays the same as radio2 is enabled, disabled, or a temporary window expires.
|
||||
|
||||
If both the ordinary and `r2-` slots have the same key, a packet received on
|
||||
radio2 selects the `r2-` slot; a packet received on radio1 selects the ordinary
|
||||
slot. Global packet deduplication still delivers each packet once, not once in
|
||||
each slot. Receiving a radio2-only channel on the wrong profile does not mark
|
||||
that authenticated packet seen, so it can still arrive later on radio2.
|
||||
|
||||
The saved channel record retains the original displayed name and app-supplied
|
||||
key for editing and sharing. Runtime copies resolve the actual wire key.
|
||||
Repeater/room/sensor hashtag behavior is unchanged; those nodes can join the
|
||||
canonical MeshCore channel (`#emergency`). Older Companion firmware does not
|
||||
recognize these aliases.
|
||||
|
||||
### Meshtext channel chat
|
||||
|
||||
`MESH_ENABLE_MESHTEXT_CHAT` enables the text-only Meshtext backend in the
|
||||
Companion. It defaults on for ESP32-S3 **Full Companion** builds using
|
||||
SX1262 LoRa and for the RAK4631 **Full Companion** starting with 1.17.1.10
|
||||
preview3. An ESP-NOW primary and other builds default off. RAK4631 1.17.1.10
|
||||
preview2 and earlier builds did not include this backend. This is not
|
||||
a replacement for stock peer firmware or a cross-protocol bridge.
|
||||
|
||||
In an enabled build, an `mt-` name always requests Meshtext, even if radio2 is
|
||||
off or setup is blocked. It never falls back to sending MeshCore frames. In a
|
||||
feature-disabled build, `mt-` remains an ordinary MeshCore naming alias while
|
||||
radio2 is off; with radio2 configured, MT channel changes/sends are unsupported.
|
||||
The `r2-` MeshCore behavior above is unchanged in either build.
|
||||
|
||||
With the region configured, join `#mt-longfast`, for example, through the app's
|
||||
normal hashtag-channel editor. A recognized preset name selects the stock
|
||||
peer channel name (`LongFast`) and, **only for an automatically
|
||||
name-derived hashtag key**, the expanded public `AQ==` key. This public key is
|
||||
not a secret. An explicitly
|
||||
supplied private AES-128 or AES-256 key stays private and unchanged. A custom
|
||||
name such as `mt-Private` uses the exact tail (`Private`) as its wire name and
|
||||
the supplied key; custom wire names are limited to 11 bytes and need a manual
|
||||
radio2 profile or another MT channel with a recognized preset. Preset names
|
||||
are ASCII case-insensitive; the `mt-` marker is still case-sensitive.
|
||||
|
||||
Recognized aliases and modulation are:
|
||||
|
||||
| Alias tail | Stock wire name | BW (kHz) | SF | CR |
|
||||
| --- | --- | ---: | ---: | ---: |
|
||||
| `shortturbo` | `ShortTurbo` | 500 | 7 | 5 |
|
||||
| `shortfast` | `ShortFast` | 250 | 7 | 5 |
|
||||
| `shortslow` | `ShortSlow` | 250 | 8 | 5 |
|
||||
| `mediumturbo` | `MediumTurbo` | 500 | 9 | 5 |
|
||||
| `mediumfast` | `MediumFast` | 250 | 9 | 5 |
|
||||
| `mediumslow` | `MediumSlow` | 250 | 10 | 5 |
|
||||
| `longturbo` | `LongTurbo` | 500 | 11 | 8 |
|
||||
| `longfast` | `LongFast` | 250 | 11 | 5 |
|
||||
| `longmod` or `longmoderate` | `LongMod` | 125 | 11 | 8 |
|
||||
| `longslow` | `LongSlow` | 125 | 12 | 8 |
|
||||
|
||||
The selected region must have room for the bandwidth; for example, 500 kHz
|
||||
presets are unavailable in the supported EU868 plan. Use these CLI commands:
|
||||
|
||||
```text
|
||||
get mt.status
|
||||
get mt.region
|
||||
get mt.slot
|
||||
get mt.hops
|
||||
get mt.node
|
||||
get mt.shortname
|
||||
set mt.node !12345678
|
||||
set mt.node default
|
||||
set mt.region auto
|
||||
set mt.region us
|
||||
set mt.slot 0
|
||||
set mt.hops 7
|
||||
set mt.shortname HALO
|
||||
set mt.shortname default
|
||||
send mt.nodeinfo 0
|
||||
get radio2
|
||||
set radio2 auto
|
||||
```
|
||||
|
||||
`mt.region` accepts `auto`, `us`, `eu868`, `eu433`, or `anz`. `auto` infers US
|
||||
only from a primary frequency at least 902 MHz and below 915 MHz, EU868 from
|
||||
869.4–869.65 MHz, and EU433 from 433–434 MHz. The US/ANZ overlap at 915–928 MHz
|
||||
is ambiguous: explicitly select `us` or `anz`. `mt.slot` is a 1-based frequency
|
||||
slot, or `0` for the stock preset-name-derived slot; unavailable slots are
|
||||
blocked. Check `get mt.status` after configuration; a successful settings save
|
||||
does not mean the MT backend is active.
|
||||
|
||||
Outgoing MT messages default to a hop limit of **7**. `set mt.hops <0..7>`
|
||||
changes this budget, and `get mt.hops` or `get mt.status` shows it. `0` sends
|
||||
only the initial over-air hop with no forwarding budget; larger values permit
|
||||
protocol-compatible peers to forward within that budget. The Companion itself still
|
||||
does not relay MT packets.
|
||||
|
||||
`get mt.node` shows the effective Meshtext sender node ID. By default it is
|
||||
SHA-derived from the MeshCore public identity and remains stable for that
|
||||
identity. `set mt.node !12345678` sets a saved override; exactly eight hexadecimal
|
||||
digits are required, with or without the leading `!`. Input is hexadecimal,
|
||||
not decimal, and is never silently truncated. IDs `00000000` through `00000003`
|
||||
and `ffffffff` are reserved and rejected. `set mt.node default` clears the
|
||||
override and restores the identity-derived ID.
|
||||
|
||||
The example ID is illustrative: choose an ID unique among your protocol-compatible
|
||||
peers. Collisions can merge different senders into one identity and interfere
|
||||
with packet deduplication. Changing the MT ID does not alter the MeshCore
|
||||
private key, reset the outgoing packet-ID sequence or send automatic traffic.
|
||||
Settings changes are refused while an MT transmission is
|
||||
pending. Neither node IDs nor text labels are authenticated.
|
||||
|
||||
`set mt.shortname <label>` saves a Meshtext-only NodeInfo name of 1–4 Unicode
|
||||
scalar characters, with valid UTF-8 and at most 16 encoded bytes. Combining
|
||||
characters count separately. `get mt.shortname` shows the saved/effective
|
||||
name. Stock NodeInfo accepts only four UTF-8 **bytes**, so the effective wire
|
||||
name is the longest complete UTF-8 prefix that fits. The saved value is not
|
||||
changed. `set mt.shortname default` clears the override and uses the last four
|
||||
hexadecimal digits of the effective MT node ID. This does not change the
|
||||
MeshCore node name, add a label to chat text or transmit anything.
|
||||
|
||||
`send mt.nodeinfo <channel slot>` explicitly queues **one** standard
|
||||
`NODEINFO_APP` broadcast on the selected configured MT channel. The slot is
|
||||
the Companion channel index, not `mt.slot` (the frequency slot). The packet
|
||||
contains the actual sender ID, the global MeshCore node name as its long name
|
||||
(UTF-8-safe truncated to 24 bytes), the effective short name, `CLIENT_MUTE`
|
||||
(no relaying), and the no-DM flag. It omits MAC, public keys and unsupported
|
||||
metadata. The usual radio2 TX-mode, pending-TX, airtime and profile guards
|
||||
apply. The reply says **queued**, not delivered or acknowledged.
|
||||
|
||||
There are no automatic NodeInfo advertisements: not at boot, on a timer, when
|
||||
names change, when chat is sent, or in response to received packets. Received
|
||||
NodeInfo is still ignored; this backend does not maintain a node database.
|
||||
|
||||
Region, frequency slot, hop limit, shortname and node-ID override are saved
|
||||
atomically together; changing one preserves the others. Current 40-byte `MT03`
|
||||
settings include both overrides. New firmware accepts valid legacy
|
||||
`MT01`/`MT02` settings and defaults the shortname to the sender-ID suffix and
|
||||
the node ID to the MeshCore identity; `MT01` also defaults the hop limit to 7.
|
||||
Older MT firmware cannot read `MT03`, so downgrading does not preserve access
|
||||
to these settings. Invalid or unsupported stored settings block MT operation
|
||||
rather than silently selecting another network.
|
||||
|
||||
Private channels can be provisioned directly through the Companion CLI:
|
||||
|
||||
```text
|
||||
set mt.preset <longfast|shortturbo|...>
|
||||
set mt.channel <slot> <mt-name> <32/64 hex digits|AQ==>
|
||||
get mt.channel <slot>
|
||||
delete mt.channel <slot>
|
||||
```
|
||||
|
||||
`set mt.preset` accepts the recognized presets above and explicitly saves a
|
||||
manual `rxtx` radio2 RF tuple using the current region and frequency slot. It
|
||||
is not an automatic owner: deleting the channel does not remove that saved RF
|
||||
configuration. Set region/slot first; changing them later does not overwrite
|
||||
the manual frequency, so rerun `set mt.preset` if you intend to retune it.
|
||||
|
||||
`set mt.channel` accepts a 32-digit hexadecimal AES-128 PSK, a 64-digit
|
||||
hexadecimal AES-256 PSK, or the literal `AQ==` for the public key. It does not
|
||||
accept arbitrary Base64 private keys. The stored format interprets an all-zero
|
||||
upper 16-byte half as AES-128, including in a 64-digit input; use a nonzero
|
||||
upper half for AES-256. Slot numbers are zero-based and build-specific, as in
|
||||
the app. `get mt.channel` reports name, wire name and AES size, never the PSK.
|
||||
The firmware console masks key input echo; keep your client-side logs and
|
||||
stored keys private as well. SET and DELETE save transactionally and restore
|
||||
the previous channel if storage fails. DELETE applies only to an MT channel,
|
||||
not a MeshCore slot.
|
||||
|
||||
For a private channel named `Team` on a protocol-compatible peer:
|
||||
|
||||
```text
|
||||
set mt.region us
|
||||
set mt.preset longfast
|
||||
set mt.channel 1 mt-Team <your-32-or-64-hex-digit-key>
|
||||
get mt.channel 1
|
||||
get mt.node
|
||||
set mt.shortname HALO
|
||||
get mt.status
|
||||
send mt.nodeinfo 1
|
||||
channel 1 Hello
|
||||
```
|
||||
|
||||
Replace the key placeholder with your actual hexadecimal PSK and send after
|
||||
`get mt.status` reports active. The peer must use the same preset, frequency,
|
||||
PSK and exact case-sensitive wire name `Team`; `mt-` is only the local marker.
|
||||
Alternatively, `set mt.channel 1 mt-longfast <your-key>` preserves a private
|
||||
PSK but uses wire name `LongFast` and can acquire automatic RF without
|
||||
`set mt.preset`, provided radio2 automatic ownership is permitted. This route
|
||||
is available for both 128-bit and 256-bit private keys even when the stock app
|
||||
cannot provision or export the latter.
|
||||
|
||||
When radio2 was never manually configured, a recognized preset can acquire an
|
||||
automatic `rxtx` profile. Its RF tuple is RAM-only and stays available for RX
|
||||
while the required channels exist. Removing the last MT channel, losing its
|
||||
last recognized-preset dependency, or detecting a conflict releases only the
|
||||
automatic profile. Explicit manual RF settings are retained: named aliases
|
||||
must match their BW/SF/CR and fit the selected region, but do not overwrite
|
||||
their frequency. The runtime MT overlay uses its required 16-symbol preamble;
|
||||
the saved manual preamble is retained.
|
||||
|
||||
`set radio2 off` is an explicit manual veto, including after reboot. Older
|
||||
saved off profiles are conservatively treated as manual. Local
|
||||
`set radio2 auto` clears the saved manual RF/off choice and permits automatic
|
||||
ownership after two seconds; it rejects pending changes, leases and schedules
|
||||
rather than cancelling them. `get radio2` distinguishes `auto-owned`, `off (manual)`
|
||||
and `off (automatic allowed)`. Temporary profiles, scheduled changes and reply
|
||||
commit barriers take precedence and can suspend MT operation. Automatic
|
||||
cleanup does not undo later manual edits.
|
||||
|
||||
All MT channels share this one secondary modem profile. Different recognized
|
||||
presets, or mixing any MT and `r2-` channels, are rejected instead of selecting
|
||||
whichever channel was edited last. Loaded conflicts also block MT traffic.
|
||||
Neither `radio2.cross on` nor MeshCore channel routes cross MT frames between
|
||||
protocols.
|
||||
|
||||
The app uses its existing channel index/text commands and receive events.
|
||||
Outgoing MT chat is plain text exactly as entered, with the sender node ID in
|
||||
the standard radio header. It contains no custom name envelope or NodeInfo.
|
||||
Incoming text uses the exact sender-ID prefix `!12345678: ` before the received
|
||||
payload when passed to the MeshCore app. Changing the shortname only changes
|
||||
future manually requested NodeInfo, not chat or the packet's sender ID;
|
||||
`set mt.node` changes the actual Meshtext sender ID. Neither setting change
|
||||
emits advertisements. A successful
|
||||
send response means **queued**, not acknowledged by a remote node. This backend
|
||||
does not relay MT packets or provide ACKs, administrative commands, direct
|
||||
messages, automatic node-info adverts or a node database. MeshCore emergency forwarding
|
||||
does not apply to MT traffic. Interoperability is with stock peers' PSK channel
|
||||
text using AES-CTR, not AES-CCM. AES-CTR channel traffic is not authenticated;
|
||||
successful decoding is not proof of sender identity.
|
||||
|
||||
The codec supports AES-128 and AES-256 and up to 228 UTF-8 bytes of wire text,
|
||||
without an added label/node-ID prefix. The standard app channel editor
|
||||
still provisions 16-byte keys. An MT-only 32-byte binary SET/opt-in GET
|
||||
extension is available for capable clients, with protection against legacy
|
||||
16-byte edits truncating an existing 256-bit key; see
|
||||
[Companion protocol](companion_protocol.md#4-set-channel). This does not give
|
||||
stock apps seamless 256-bit provisioning or sharing. Current V3 Companion
|
||||
receive events carry at most 165 text bytes **including the node-ID prefix**;
|
||||
longer incoming MT text is UTF-8-safe truncated for the app.
|
||||
|
||||
Radio1 and radio2 still time-share **one physical radio**. The device cannot
|
||||
receive either network while tuned to the other or transmitting; long MT
|
||||
airtime, particularly LongFast, can leave substantial MeshCore receive gaps.
|
||||
The compatible protocol's fixed short preamble also does not provide the scan-aware long
|
||||
preamble described below. Do not treat this as continuous coverage of both
|
||||
networks or guaranteed message delivery.
|
||||
|
||||
## Choose whether traffic crosses between profiles
|
||||
|
||||
```text
|
||||
@@ -253,6 +523,9 @@ set radio2.cross off
|
||||
| `radio` | `tempradio2` | Isolated | Cross | Isolated |
|
||||
| `tempradio` | `radio2` | Isolated | Cross | Isolated |
|
||||
|
||||
This table describes MeshCore profiles. A Meshtext secondary profile is
|
||||
always isolated, including with `radio2.cross on`.
|
||||
|
||||
These are the global rules used by Companion targets set to `auto`; an explicit
|
||||
contact/channel choice above overrides crossing for its own outbound packets.
|
||||
Ordinary crossing respects `rx`. The infrastructure-only `tx.reply ... force`
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/radio_profiles_validation/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/radio_profiles_validation/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/radio_receive_calibration/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../test-results/radio_receive_calibration/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/rak3401_1.17.1.7_legacy24/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../research/rak3401_1.17.1.7_legacy24/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/rak3401_mota_chain/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Document moved
|
||||
|
||||
<script>window.location.replace(new URL("../research/rak3401_mota_chain/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/releases/1.17.1.5-doc-audit/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Release notes moved
|
||||
|
||||
<script>window.location.replace(new URL("../../old-releases/1.17.1.5-doc-audit/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/releases/1.17.1.5/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Release notes moved
|
||||
|
||||
<script>window.location.replace(new URL("../../old-releases/1.17.1.5/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/releases/1.17.1.6/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Release notes moved
|
||||
|
||||
<script>window.location.replace(new URL("../../old-releases/1.17.1.6/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/releases/1.17.1.7/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# Release notes moved
|
||||
|
||||
<script>window.location.replace(new URL("../../old-releases/1.17.1.7/" + window.location.hash, window.location.href));</script>
|
||||
|
||||
Loaded 100 of 726 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user