build.sh: add optional Cascadia profile overrides
This commit is contained in:
1 parent
c93d907e85
commit
c3712737e9
2 files changed
+368
-7
No files matched your search
@@ -4,6 +4,16 @@ ALL_PIO_ENVS=()
|
||||
PIO_CONFIG_JSON=""
|
||||
MENU_CHOICE=""
|
||||
SELECTED_TARGET=""
|
||||
SELECTED_COMMAND_ARGS=()
|
||||
MESHDEBUG_OVERRIDE=""
|
||||
PACKET_LOGGING_OVERRIDE=""
|
||||
RADIO_SETTINGS_API_URL="https://api.meshcore.nz/api/v1/config"
|
||||
RADIO_SETTING_TITLE=""
|
||||
RADIO_FREQ_OVERRIDE=""
|
||||
RADIO_BW_OVERRIDE=""
|
||||
RADIO_SF_OVERRIDE=""
|
||||
RADIO_CR_OVERRIDE=""
|
||||
FIRMWARE_PROFILE_OVERRIDE=""
|
||||
|
||||
ENV_VARIANT_SUFFIX_PATTERN='companion_radio_serial|companion_radio_wifi|companion_radio_usb|comp_radio_usb|companion_usb|companion_radio_ble|companion_ble|repeater_bridge_rs232_serial1|repeater_bridge_rs232_serial2|repeater_bridge_rs232|repeater_bridge_espnow|terminal_chat|room_server|room_svr|kiss_modem|sensor|repeatr|repeater'
|
||||
BOARD_MODIFIER_WITHOUT_DISPLAY="_without_display"
|
||||
@@ -51,7 +61,7 @@ Examples:
|
||||
Build firmware for the "RAK_4631_repeater" device target
|
||||
$ bash build.sh build-firmware RAK_4631_repeater
|
||||
|
||||
Run without arguments to choose a target from an interactive menu
|
||||
Run without arguments to choose an interactive build action/target, debug options, and radio settings
|
||||
$ bash build.sh
|
||||
|
||||
Build all firmwares for device targets containing the string "RAK_4631"
|
||||
@@ -187,6 +197,277 @@ prompt_menu_choice() {
|
||||
done
|
||||
}
|
||||
|
||||
prompt_on_off_choice() {
|
||||
local prompt_label=$1
|
||||
local default_choice=$2
|
||||
local choice
|
||||
|
||||
while true; do
|
||||
read -r -p "${prompt_label} [on/off] (default: ${default_choice}): " choice
|
||||
choice=${choice,,}
|
||||
if [ -z "$choice" ]; then
|
||||
choice=$default_choice
|
||||
fi
|
||||
|
||||
case "$choice" in
|
||||
on|off)
|
||||
MENU_CHOICE="$choice"
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
echo "Invalid selection. Choose 'on' or 'off'."
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
prompt_for_build_mode() {
|
||||
local options=(
|
||||
"Build one firmware target"
|
||||
"Build all firmwares"
|
||||
"Build all repeater firmwares"
|
||||
"Build all companion firmwares"
|
||||
"Build all chat room server firmwares"
|
||||
)
|
||||
|
||||
echo "No command provided. Select a build action:"
|
||||
while true; do
|
||||
print_numbered_menu "${options[@]}"
|
||||
prompt_menu_choice "Build action" "${#options[@]}"
|
||||
if [ "$MENU_CHOICE" == "QUIT" ]; then
|
||||
echo "Cancelled."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$MENU_CHOICE" in
|
||||
1)
|
||||
prompt_for_board_target
|
||||
SELECTED_COMMAND_ARGS=(build-firmware "$SELECTED_TARGET")
|
||||
return 0
|
||||
;;
|
||||
2)
|
||||
SELECTED_COMMAND_ARGS=(build-firmwares)
|
||||
return 0
|
||||
;;
|
||||
3)
|
||||
SELECTED_COMMAND_ARGS=(build-repeater-firmwares)
|
||||
return 0
|
||||
;;
|
||||
4)
|
||||
SELECTED_COMMAND_ARGS=(build-companion-firmwares)
|
||||
return 0
|
||||
;;
|
||||
5)
|
||||
SELECTED_COMMAND_ARGS=(build-room-server-firmwares)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
prompt_for_debug_build_settings() {
|
||||
echo "Set debug build options:"
|
||||
prompt_on_off_choice "Mesh debug (MESH_DEBUG)" "off"
|
||||
MESHDEBUG_OVERRIDE="$MENU_CHOICE"
|
||||
|
||||
prompt_on_off_choice "Packet logging (MESH_PACKET_LOGGING)" "off"
|
||||
PACKET_LOGGING_OVERRIDE="$MENU_CHOICE"
|
||||
|
||||
echo "Using debug options: meshdebug=${MESHDEBUG_OVERRIDE}, packet_logging=${PACKET_LOGGING_OVERRIDE}"
|
||||
}
|
||||
|
||||
clear_radio_overrides() {
|
||||
RADIO_SETTING_TITLE=""
|
||||
RADIO_FREQ_OVERRIDE=""
|
||||
RADIO_BW_OVERRIDE=""
|
||||
RADIO_SF_OVERRIDE=""
|
||||
RADIO_CR_OVERRIDE=""
|
||||
}
|
||||
|
||||
clear_firmware_profile_overrides() {
|
||||
FIRMWARE_PROFILE_OVERRIDE=""
|
||||
}
|
||||
|
||||
set_radio_overrides() {
|
||||
RADIO_SETTING_TITLE=$1
|
||||
RADIO_FREQ_OVERRIDE=$2
|
||||
RADIO_BW_OVERRIDE=$3
|
||||
RADIO_SF_OVERRIDE=$4
|
||||
RADIO_CR_OVERRIDE=$5
|
||||
}
|
||||
|
||||
fetch_suggested_radio_settings() {
|
||||
python3 - "$RADIO_SETTINGS_API_URL" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
import urllib.request
|
||||
|
||||
url = sys.argv[1]
|
||||
with urllib.request.urlopen(url, timeout=8) as response:
|
||||
payload = json.load(response)
|
||||
|
||||
entries = (
|
||||
payload.get("config", {})
|
||||
.get("suggested_radio_settings", {})
|
||||
.get("entries", [])
|
||||
)
|
||||
|
||||
for entry in entries:
|
||||
title = str(entry.get("title", "")).strip()
|
||||
description = str(entry.get("description", "")).strip()
|
||||
freq = str(entry.get("frequency", "")).strip()
|
||||
sf = str(entry.get("spreading_factor", "")).strip()
|
||||
bw = str(entry.get("bandwidth", "")).strip()
|
||||
cr = str(entry.get("coding_rate", "")).strip()
|
||||
if title and freq and sf and bw and cr:
|
||||
print("\t".join([title, description, freq, bw, sf, cr]))
|
||||
PY
|
||||
}
|
||||
|
||||
is_valid_custom_radio_bandwidth() {
|
||||
python3 - "$1" <<'PY'
|
||||
import sys
|
||||
|
||||
allowed = [7.81, 10.42, 15.63, 20.83, 31.25, 41.67, 62.5, 125.0, 250.0, 500.0]
|
||||
try:
|
||||
value = float(sys.argv[1])
|
||||
except Exception:
|
||||
raise SystemExit(1)
|
||||
|
||||
raise SystemExit(0 if any(abs(value - option) < 1e-6 for option in allowed) else 1)
|
||||
PY
|
||||
}
|
||||
|
||||
prompt_for_custom_radio_setting() {
|
||||
local freq
|
||||
local sf
|
||||
local bw
|
||||
local cr
|
||||
|
||||
echo
|
||||
echo "Custom radio settings:"
|
||||
|
||||
while true; do
|
||||
read -r -p "Center frequency (MHz, e.g. 915.000): " freq
|
||||
if [[ "$freq" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
|
||||
break
|
||||
fi
|
||||
echo "Please enter a numeric MHz value (e.g. 915.000)."
|
||||
done
|
||||
|
||||
echo "Spreading factor options: 5, 6, 7, 8, 9, 10, 11, 12"
|
||||
while true; do
|
||||
read -r -p "SF (5-12): " sf
|
||||
if [[ "$sf" =~ ^[0-9]+$ ]] && [ "$sf" -ge 5 ] && [ "$sf" -le 12 ]; then
|
||||
break
|
||||
fi
|
||||
echo "Please enter 5, 6, 7, 8, 9, 10, 11, or 12."
|
||||
done
|
||||
|
||||
echo "Bandwidth options (kHz): 7.81 10.42 15.63 20.83 31.25 41.67 62.5 125 250 500"
|
||||
while true; do
|
||||
read -r -p "BW (kHz): " bw
|
||||
if [[ "$bw" =~ ^[0-9]+([.][0-9]+)?$ ]] && is_valid_custom_radio_bandwidth "$bw"; then
|
||||
break
|
||||
fi
|
||||
echo "Please enter one of: 7.81 10.42 15.63 20.83 31.25 41.67 62.5 125 250 500."
|
||||
done
|
||||
|
||||
echo "Coding rate options: CR5, CR6, CR7, CR8"
|
||||
while true; do
|
||||
read -r -p "CR (5-8): " cr
|
||||
if [[ "$cr" =~ ^[0-9]+$ ]] && [ "$cr" -ge 5 ] && [ "$cr" -le 8 ]; then
|
||||
break
|
||||
fi
|
||||
echo "Please enter 5, 6, 7, or 8."
|
||||
done
|
||||
|
||||
set_radio_overrides "Custom" "$freq" "$bw" "$sf" "$cr"
|
||||
}
|
||||
|
||||
prompt_for_cascadia_profile_enable() {
|
||||
clear_firmware_profile_overrides
|
||||
echo
|
||||
echo "Cascadia profile changes:"
|
||||
echo " - rxdelay: 1"
|
||||
echo " - agc.reset.interval: 8"
|
||||
echo " - advert.interval: 0"
|
||||
echo " - flood.advert.interval: 83"
|
||||
echo " - multi.acks: 1"
|
||||
echo " - path.hash.mode: 2"
|
||||
echo " - loop.detect: minimal"
|
||||
echo " - powersaving: on"
|
||||
prompt_on_off_choice "Enable Cascadia profile overrides" "on"
|
||||
if [ "$MENU_CHOICE" == "on" ]; then
|
||||
FIRMWARE_PROFILE_OVERRIDE="cascadia"
|
||||
echo "Using firmware profile override: ${FIRMWARE_PROFILE_OVERRIDE}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "Using target default firmware profile settings."
|
||||
return 0
|
||||
}
|
||||
|
||||
prompt_for_radio_build_settings() {
|
||||
local -a preset_rows=()
|
||||
local -a options=("Keep target defaults (no radio override)")
|
||||
local row
|
||||
local title
|
||||
local description
|
||||
local freq
|
||||
local bw
|
||||
local sf
|
||||
local cr
|
||||
local preset_index
|
||||
local choice_index
|
||||
local custom_index
|
||||
|
||||
clear_radio_overrides
|
||||
|
||||
if mapfile -t preset_rows < <(fetch_suggested_radio_settings); then
|
||||
for row in "${preset_rows[@]}"; do
|
||||
IFS=$'\t' read -r title description freq bw sf cr <<< "$row"
|
||||
options+=("${title}: ${description}")
|
||||
done
|
||||
else
|
||||
echo "Could not fetch radio presets from ${RADIO_SETTINGS_API_URL}."
|
||||
preset_rows=()
|
||||
fi
|
||||
|
||||
options+=("Custom")
|
||||
custom_index=${#options[@]}
|
||||
|
||||
echo "Set radio build options:"
|
||||
while true; do
|
||||
print_numbered_menu "${options[@]}"
|
||||
prompt_menu_choice "Radio setting" "${#options[@]}"
|
||||
if [ "$MENU_CHOICE" == "QUIT" ]; then
|
||||
echo "Cancelled."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
choice_index=$MENU_CHOICE
|
||||
if [ "$choice_index" -eq 1 ]; then
|
||||
echo "Using target default radio settings."
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "$choice_index" -eq "$custom_index" ]; then
|
||||
prompt_for_custom_radio_setting
|
||||
echo "Using radio setting: ${RADIO_SETTING_TITLE} (${RADIO_FREQ_OVERRIDE}MHz / SF${RADIO_SF_OVERRIDE} / BW${RADIO_BW_OVERRIDE} / CR${RADIO_CR_OVERRIDE})"
|
||||
return 0
|
||||
fi
|
||||
|
||||
preset_index=$((choice_index - 2))
|
||||
if [ "$preset_index" -ge 0 ] && [ "$preset_index" -lt "${#preset_rows[@]}" ]; then
|
||||
IFS=$'\t' read -r title description freq bw sf cr <<< "${preset_rows[$preset_index]}"
|
||||
set_radio_overrides "$title" "$freq" "$bw" "$sf" "$cr"
|
||||
echo "Using radio setting: ${RADIO_SETTING_TITLE} (${RADIO_FREQ_OVERRIDE}MHz / SF${RADIO_SF_OVERRIDE} / BW${RADIO_BW_OVERRIDE} / CR${RADIO_CR_OVERRIDE})"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
get_env_metadata() {
|
||||
local env_name=$1
|
||||
local trimmed_env_name
|
||||
@@ -394,7 +675,7 @@ prompt_for_board_target() {
|
||||
|
||||
mapfile -t boards < <(printf '%s\n' "${boards[@]}" | sort_lines_case_insensitive)
|
||||
|
||||
echo "No command provided. Select a board family:"
|
||||
echo "Select a board family:"
|
||||
while true; do
|
||||
print_numbered_menu "${boards[@]}"
|
||||
prompt_menu_choice "Board selection" "${#boards[@]}"
|
||||
@@ -523,6 +804,40 @@ disable_debug_flags() {
|
||||
fi
|
||||
}
|
||||
|
||||
apply_debug_overrides() {
|
||||
case "${MESHDEBUG_OVERRIDE,,}" in
|
||||
on)
|
||||
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -UMESH_DEBUG -DMESH_DEBUG=1"
|
||||
;;
|
||||
off)
|
||||
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -UMESH_DEBUG"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "${PACKET_LOGGING_OVERRIDE,,}" in
|
||||
on)
|
||||
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -UMESH_PACKET_LOGGING -DMESH_PACKET_LOGGING=1"
|
||||
;;
|
||||
off)
|
||||
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -UMESH_PACKET_LOGGING"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
apply_radio_overrides() {
|
||||
if [ -n "$RADIO_FREQ_OVERRIDE" ] && [ -n "$RADIO_BW_OVERRIDE" ] && [ -n "$RADIO_SF_OVERRIDE" ] && [ -n "$RADIO_CR_OVERRIDE" ]; then
|
||||
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -ULORA_FREQ -ULORA_BW -ULORA_SF -ULORA_CR -DLORA_FREQ=${RADIO_FREQ_OVERRIDE} -DLORA_BW=${RADIO_BW_OVERRIDE} -DLORA_SF=${RADIO_SF_OVERRIDE} -DLORA_CR=${RADIO_CR_OVERRIDE}"
|
||||
fi
|
||||
}
|
||||
|
||||
apply_firmware_profile_overrides() {
|
||||
case "${FIRMWARE_PROFILE_OVERRIDE,,}" in
|
||||
cascadia)
|
||||
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -DCASCADIA_PROFILE=1 -DDEFAULT_RX_DELAY_BASE=1.0f -DDEFAULT_LOOP_DETECT=1 -DDEFAULT_POWERSAVING_ENABLED=1 -DDEFAULT_AGC_RESET_INTERVAL=2 -DDEFAULT_ADVERT_INTERVAL=0 -DDEFAULT_FLOOD_ADVERT_INTERVAL=83 -DDEFAULT_MULTI_ACKS=1 -DDEFAULT_PATH_HASH_MODE=2"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
copy_build_output() {
|
||||
local source_path=$1
|
||||
local output_path=$2
|
||||
@@ -616,6 +931,9 @@ build_firmware() {
|
||||
|
||||
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -DFIRMWARE_BUILD_DATE='\"${firmware_build_date}\"' -DFIRMWARE_VERSION='\"${firmware_version_string}\"'"
|
||||
disable_debug_flags
|
||||
apply_debug_overrides
|
||||
apply_radio_overrides
|
||||
apply_firmware_profile_overrides
|
||||
|
||||
pio run -e "$env_name"
|
||||
collect_build_artifacts "$env_name" "$env_platform" "$firmware_filename"
|
||||
@@ -734,8 +1052,11 @@ main() {
|
||||
init_project_context
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
prompt_for_board_target
|
||||
set -- build-firmware "$SELECTED_TARGET"
|
||||
prompt_for_build_mode
|
||||
prompt_for_debug_build_settings
|
||||
prompt_for_radio_build_settings
|
||||
prompt_for_cascadia_profile_enable
|
||||
set -- "${SELECTED_COMMAND_ARGS[@]}"
|
||||
fi
|
||||
|
||||
prepare_output_dir
|
||||
|
||||
@@ -20,6 +20,31 @@
|
||||
#define LORA_TX_POWER 20
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_RX_DELAY_BASE
|
||||
#define DEFAULT_RX_DELAY_BASE 0.0f
|
||||
#endif
|
||||
#ifndef DEFAULT_LOOP_DETECT
|
||||
#define DEFAULT_LOOP_DETECT LOOP_DETECT_OFF
|
||||
#endif
|
||||
#ifndef DEFAULT_POWERSAVING_ENABLED
|
||||
#define DEFAULT_POWERSAVING_ENABLED 0
|
||||
#endif
|
||||
#ifndef DEFAULT_AGC_RESET_INTERVAL
|
||||
#define DEFAULT_AGC_RESET_INTERVAL 0
|
||||
#endif
|
||||
#ifndef DEFAULT_ADVERT_INTERVAL
|
||||
#define DEFAULT_ADVERT_INTERVAL 1
|
||||
#endif
|
||||
#ifndef DEFAULT_FLOOD_ADVERT_INTERVAL
|
||||
#define DEFAULT_FLOOD_ADVERT_INTERVAL 12
|
||||
#endif
|
||||
#ifndef DEFAULT_MULTI_ACKS
|
||||
#define DEFAULT_MULTI_ACKS 0
|
||||
#endif
|
||||
#ifndef DEFAULT_PATH_HASH_MODE
|
||||
#define DEFAULT_PATH_HASH_MODE 0
|
||||
#endif
|
||||
|
||||
#ifndef ADVERT_NAME
|
||||
#define ADVERT_NAME "repeater"
|
||||
#endif
|
||||
@@ -2034,7 +2059,7 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
|
||||
// defaults
|
||||
memset(&_prefs, 0, sizeof(_prefs));
|
||||
_prefs.airtime_factor = 1.0;
|
||||
_prefs.rx_delay_base = 0.0f; // turn off by default, was 10.0;
|
||||
_prefs.rx_delay_base = DEFAULT_RX_DELAY_BASE;
|
||||
_prefs.tx_delay_factor = 0.5f; // was 0.25f
|
||||
_prefs.direct_tx_delay_factor = 0.3f; // was 0.2
|
||||
_prefs.direct_retry_recent_enabled = 1;
|
||||
@@ -2063,10 +2088,15 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
|
||||
_prefs.bw = LORA_BW;
|
||||
_prefs.cr = LORA_CR;
|
||||
_prefs.tx_power_dbm = LORA_TX_POWER;
|
||||
_prefs.advert_interval = 1; // default to 2 minutes for NEW installs
|
||||
_prefs.flood_advert_interval = 12; // 12 hours
|
||||
_prefs.advert_interval = DEFAULT_ADVERT_INTERVAL;
|
||||
_prefs.flood_advert_interval = DEFAULT_FLOOD_ADVERT_INTERVAL;
|
||||
_prefs.flood_max = 64;
|
||||
_prefs.interference_threshold = 0; // disabled
|
||||
_prefs.agc_reset_interval = DEFAULT_AGC_RESET_INTERVAL;
|
||||
_prefs.multi_acks = DEFAULT_MULTI_ACKS;
|
||||
_prefs.path_hash_mode = DEFAULT_PATH_HASH_MODE;
|
||||
_prefs.loop_detect = DEFAULT_LOOP_DETECT;
|
||||
_prefs.powersaving_enabled = DEFAULT_POWERSAVING_ENABLED;
|
||||
|
||||
// bridge defaults
|
||||
_prefs.bridge_enabled = 1; // enabled
|
||||
@@ -2105,6 +2135,16 @@ void MyMesh::begin(FILESYSTEM *fs) {
|
||||
_fs = fs;
|
||||
// load persisted prefs
|
||||
_cli.loadPrefs(_fs);
|
||||
#ifdef CASCADIA_PROFILE
|
||||
_prefs.rx_delay_base = DEFAULT_RX_DELAY_BASE;
|
||||
_prefs.agc_reset_interval = DEFAULT_AGC_RESET_INTERVAL;
|
||||
_prefs.advert_interval = DEFAULT_ADVERT_INTERVAL;
|
||||
_prefs.flood_advert_interval = DEFAULT_FLOOD_ADVERT_INTERVAL;
|
||||
_prefs.multi_acks = DEFAULT_MULTI_ACKS;
|
||||
_prefs.path_hash_mode = DEFAULT_PATH_HASH_MODE;
|
||||
_prefs.loop_detect = DEFAULT_LOOP_DETECT;
|
||||
_prefs.powersaving_enabled = DEFAULT_POWERSAVING_ENABLED;
|
||||
#endif
|
||||
acl.load(_fs, self_id);
|
||||
// TODO: key_store.begin();
|
||||
region_map.load(_fs);
|
||||
|
||||
Reference in new issue
Block a user