diff --git a/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/root/.dialogrc b/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/root/.dialogrc index 1774a38..0dc0ac3 100644 --- a/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/root/.dialogrc +++ b/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/root/.dialogrc @@ -27,7 +27,7 @@ form_text_color = (WHITE,CYAN,ON) form_item_readonly_color = (BLUE,WHITE,ON) # Item help-text color -itemhelp_color = (BLACK,BLUE,OFF) +itemhelp_color = (WHITE,BLUE,OFF) # Selected tag color (menu items) tag_selected_color = (WHITE,BLUE,ON) diff --git a/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-config b/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-config index 572a1ae..e9e6d69 100755 --- a/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-config +++ b/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-config @@ -260,7 +260,7 @@ utilities() { sysinfo_choice="" # zero the choice before loading the submenu while true; do echo $sysinfo_choice - sysinfo_choice=$(dialog --no-collapse --help-button --cancel-label "Back" --default-item "$sysinfo_choice" --item-help --menu "System info" 17 40 5 \ + sysinfo_choice=$(dialog --no-collapse --help-button --backtitle "$(femto-utils.sh -v)" --cancel-label "Back" --default-item "$sysinfo_choice" --item-help --menu "System info" 17 40 5 \ 1 "Operating system" "" \ 2 "CPU" "" \ 3 "Storage & memory" "" \ @@ -379,67 +379,6 @@ utilities() { done } -#set lora radio -set_lora_radio() { - choice="" # zero the choice before loading the submenu - while true; do - echo "Checking LoRa radio..." - #Display filename, if exists: $(files=$(ls /etc/meshtasticd/config.d/* 2>/dev/null) && [ -n "$files" ] && echo "\n\nConfiguration files in use:\n$files" | paste -sd, -)) - choice=$(dialog --no-collapse --colors --cancel-label "Cancel" --default-item "$choice" --title "Meshtastic LoRa radio" --item-help --menu "Currently configured LoRa radio:\n$(femto-utils.sh -R "$(femto-meshtasticd-config.sh -k)")$(ls -1 /etc/meshtasticd/config.d 2>/dev/null | paste -sd ', ' - | sed 's/^/ (/; s/$/)/; s/,/, /g' | grep -v '^ ()$')" 22 50 10 \ - "Radio name:" "Configuration:" "" \ - "" "" "" \ - "Ebyte e22-900m30s" "(SX1262_TCXO)" "Included in Femtofox Pro" \ - "Ebyte e22-900m22s" "(SX1262_TCXO)" "" \ - "Ebyte e80-900m22s" "(SX1262_XTAL)" "" \ - "Heltec ht-ra62" "(SX1262_TCXO)" "" \ - "Seeed wio-sx1262" "(SX1262_TCXO)" "" \ - "Waveshare sx126x-xxxm" "(SX1262_XTAL)" "Not recommended due issues with sending longer messages" \ - "AI Thinker ra-01sh" "(SX1262_XTAL)" "" \ - "LoRa Meshstick 1262" "(meshstick-1262)" "USB based LoRa radio from Mark Birss. https://github.com/markbirss/MESHSTICK" \ - "Simulated radio" "(none)" "" \ - " " "" "" \ - "Skip" "" "" 3>&1 1>&2 2>&3) - [ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog - local radio="" - case $choice in - "Ebyte e22-900m30s") - radio="sx1262_tcxo" - ;; - "Ebyte e22-900m22s") - radio="sx1262_tcxo" - ;; - "Ebyte e80-900m22s") - radio="sx1262_xtal" - ;; - "Heltec ht-ra62") - radio="sx1262_tcxo" - ;; - "Seeed wio-sx1262") - radio="sx1262_tcxo" - ;; - "Waveshare sx126x-xxxm") - radio="sx1262_xtal" - ;; - "AI Thinker ra-01sh") - radio="femto_sx1262_xtal" - ;; - "LoRa Meshstick 1262") - radio="lora-meshstick-1262" - ;; - "Simulated radio") - radio="none" - ;; - "Skip") - return - ;; - esac - if [ -n "$radio" ]; then #if a radio was selected - femto-meshtasticd-config.sh -l "$radio" -s # set the radio, then restart meshtasticd - return - fi - done -} - legacy_admin() { choice="" # zero the choice before loading the submenu while true; do @@ -481,18 +420,17 @@ meshtastic_settings() { local title="Meshtastic Settings" while true; do echo "Checking Meshtasticd service state..." - meshtastic_choice=$(dialog --no-collapse --colors --title "$title" --cancel-label "Back" --default-item "$meshtastic_choice" --item-help --menu "Meshtasticd service is $(femto-utils.sh -R "$(femto-utils.sh -C "meshtasticd")")$(femto-meshtasticd-config.sh -k | grep -q 'simulated' && echo '\n\Z1Warning: using simulated radio\Zn')" 19 50 4 \ + meshtastic_choice=$(dialog --no-collapse --colors --title "$title" --cancel-label "Back" --default-item "$meshtastic_choice" --item-help --menu "Meshtasticd service is $(femto-utils.sh -R "$(femto-utils.sh -C "meshtasticd")")$(femto-meshtasticd-config.sh -k | grep -q 'simulated' && echo '\n\Z1Warning: using simulated radio\Zn')" 18 50 4 \ 1 "View node info" "" \ 2 "View configuration URL & QR code" "" \ - 3 "Set new configuration URL" "" \ - 4 "Set LoRa radio" "" \ - 5 "Security settings" "" \ - 6 "Mesh connectivity test" "" \ - 7 "Manage Meshtasticd service" "" \ - 8 "Upgrade/install Meshtasticd" "" \ - 9 "Uninstall Meshtasticd" "" \ + 3 "LoRa settings" "" \ + 4 "Security settings" "" \ + 5 "Mesh connectivity test" "" \ + 6 "Manage Meshtasticd service" "" \ + 7 "Upgrade/install Meshtasticd" "" \ + 8 "Uninstall Meshtasticd" "" \ " " "" "" \ - 10 "Back to main menu" "" 3>&1 1>&2 2>&3) + 9 "Back to main menu" "" 3>&1 1>&2 2>&3) [ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog case $meshtastic_choice in 1) # view node info) @@ -508,24 +446,10 @@ meshtastic_settings() { pause ) ;; - 3) # set URL) - check_meshtasticd_running && ( - newurl=$(dialog --no-collapse --title "Meshtastic URL" --inputbox "New Meshtastic LoRa configuration URL (SHIFT+INS to paste):" 8 63 3>&1 1>&2 2>&3) - if [ -n "$newurl" ]; then #if a URL was entered - dialog --no-collapse --title "$title" --yesno "New Meshtastic LoRa configuration URL:\n$newurl\n\nConfirm?" 15 60 - if [ $? -eq 0 ]; then #unless cancel/no - loading "Sending command..." - dialog --no-collapse --colors --title "Meshtastic URL" --msgbox "$(femto-meshtasticd-config.sh -q "$newurl" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0 - fi - fi - ) + 3) # LoRa settings) + femto-meshtasticd-lora-dialogs.sh ;; - 4) # set radio) - check_meshtasticd_running && ( - set_lora_radio - ) - ;; - 5) # remote admin) + 4) # remote admin) check_meshtasticd_running && ( choice="" # zero the choice before loading the submenu while true; do @@ -601,7 +525,7 @@ meshtastic_settings() { done ) ;; - 6) #test mesh connectivity) + 5) #test mesh connectivity) check_meshtasticd_running && ( dialog --no-collapse --title "Meshtastic Connectivity Test" --yesno "Will send \"test\" to channel 0 and wait for acknowledgement. Will try up to 3 times.\n\nPerform test?" 10 45 if [ $? -eq 0 ]; then #unless cancel/no @@ -610,7 +534,7 @@ meshtastic_settings() { fi ) ;; - 7) #manage meshtasticd service) + 6) #manage meshtasticd service) choice="" # zero the choice before loading the submenu while true; do echo "Checking Meshtasticd service state..." @@ -663,21 +587,21 @@ meshtastic_settings() { esac done ;; - 8) #Upgrade meshtasticd) + 7) #Upgrade meshtasticd) dialog --no-collapse --title "$title" --yesno "Upgrade Meshtasticd?\nRequires internet connection." 0 0 if [ $? -eq 0 ]; then #unless cancel/no femto-meshtasticd-config.sh -z pause fi ;; - 9) #uninstall meshtasticd) + 8) #uninstall meshtasticd) dialog --no-collapse --colors --title "$title" --yesno "Uninstall Meshtasticd?\n\nFoxbuntu was designed with Meshtasticd integration in mind, and may behave unexpectedly if Meshtasticd is removed.\n\nThis will take the node \Zu\Z1OFFLINE\Zn and will not restart!" 0 0 if [ $? -eq 0 ]; then femto-meshtasticd-config.sh -x dialog --no-collapse --colors --msgbox "Meshtasticd uninstalled. To purge all remnants, run \`\Zusudo apt purge\Zn\`." 8 40 fi ;; - 10) + 9) return ;; esac @@ -754,14 +678,15 @@ Options are:\n\ -l Set LoRa radio model menu\n\ -L Meshtastic legacy admin menu\n\ -w Set Wi-Fi config menu\ +-c Check if Meshtasticd is running and warn the user if not\ " -while getopts ":hlwLi" opt; do +while getopts ":hlLwc" opt; do case ${opt} in h) # Option -h (help) echo -e $help ;; l) # Option -l (set lora radio) - set_lora_radio + femto-meshtasticd-lora-dialogs.sh # this function has moved ;; L) # Option -L (Meshtastic legacy admin menu) legacy_admin @@ -769,6 +694,9 @@ while getopts ":hlwLi" opt; do w) # Option -w (Wi-Fi config) wifi_config ;; + c) # Option -c (Check if Meshtasticd is running and warn the user if not) + check_meshtasticd_running + ;; \?) # Unknown option) echo -e "Unknown argument $1.\n$help" ;; diff --git a/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-install-wizard.sh b/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-install-wizard.sh index bebd104..8d199ae 100755 --- a/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-install-wizard.sh +++ b/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-install-wizard.sh @@ -33,13 +33,7 @@ wizard() { dialog --title "$title" --cancel-label "Skip" --yesno "Configure Meshtastic?" 6 40 if [ $? -eq 0 ]; then #unless cancel/no - femto-config -l #set lora radio model - - newurl=$(dialog --title "Meshtastic URL" --inputbox "New Meshtasticd URL (SHIFT+INS to paste):" 8 50 3>&1 1>&2 2>&3) - if [ -n "$newurl" ]; then #if a URL was entered - loading "Sending URL..." - dialog --no-collapse --colors --title "Meshtastic URL" --msgbox "$(femto-meshtasticd-config.sh -q "$newurl" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0 - fi + femto-meshtasticd-lora-dialogs.sh -w # public key loading "Getting current public key..." diff --git a/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-meshtasticd-config.sh b/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-meshtasticd-config.sh index fe193b0..f647dfc 100755 --- a/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-meshtasticd-config.sh +++ b/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-meshtasticd-config.sh @@ -30,6 +30,23 @@ Options are: -x Uninstall Meshtasticd -m Meshtastic update tool. Syntax: \`femto-meshtasticd-config.sh -m \"--set security.admin_channel_enabled false\" 10 \"Disable legacy admin\"\` Will retry the \`--set security.admin_channel_enabled false\` command until successful or up to 10 times, and tag status reports with \`Disable legacy admin\` via echo and to system log. +Meshtastic LoRa settings: +-e "value" Region (frequency plan). Options are: UNSET, US, EU_433, EU_868, CN, JP, ANZ, KR, TW, RU ,IN, NZ_865, TH, LORA_24, UA_433, UA_868, MY_433, MY_919, SG_923 +-P "true" Use modem preset (true, false) +-E "value" Preset. Options are: LONG_FAST, LONG_SLOW, VERY_LONG_SLOW, MEDIUM_SLOW, MEDIUM_FAST, SHORT_SLOW, SHORT_FAST, SHORT_TURBO +-b "value" Bandwidth (only used if modem preset is disabled) +-f "value" Spread Factor (only used if modem preset is disabled) +-C "value" Coding rate (only used if modem preset is disabled) +-O "value" Frequency offset (MHz) +-H "value" Hop limit (0-7) +-T "true" TX enabled (true/false) +-X "value" TX power (dBm) +-F "value" Frequency slot +-V "false" Override duty cycle (true/false) +-B "true" SX126X RX boosted gain (true/false) +-v "value" Override frequency (MHz) (overrides frequency slot) +-G "false" Ignore MQTT (true/false) +-K "false" OK to MQTT (true/false) EOF ) @@ -45,8 +62,7 @@ meshtastic_update() { local ref="$3: " echo "Submitting to Meshtastic..." for retries in $(seq 1 $attempts); do - local output=$(meshtastic --host $command) #>&2 lets meshtastic's output display on screen - echo $output + local output=$(meshtastic --host $command | tee /dev/tty) #>&2 lets meshtastic's output display on screen logger $output if echo "$output" | grep -qiE "Abort|invalid|Error|refused|Errno"; then if [ "$retries" -lt $attempts ]; then @@ -67,6 +83,7 @@ meshtastic_update() { fi done if [ -z "$success" ]; then + echo -e "$output" msg="${ref:+$ref}Meshtastic command FAILED." echo "$msg" logger "$msg" @@ -75,7 +92,7 @@ meshtastic_update() { } # Parse options -while getopts ":higkl:q:uU:rR:aA:cpo:sM:Stwuxm" opt; do +while getopts ":higkl:q:uU:rR:aA:cpo:sM:StwuxmP:E:b:f:C:O:e:H:T:X:F:V:B:v:G:K:" opt; do case ${opt} in h) # Option -h (help) echo -e "$help" @@ -130,7 +147,7 @@ while getopts ":higkl:q:uU:rR:aA:cpo:sM:Stwuxm" opt; do echo $url ;; k) # Option -k (get current lora radio model) - ls /etc/meshtasticd/config.d 2>/dev/null | xargs -r -n 1 basename | sed 's/^femtofox_//;s/\.yaml$//' | grep . || echo -e "\033[0;31mnone (simulated radio)\033[0m" + ls /etc/meshtasticd/config.d 2>/dev/null | grep '^femtofox_' | xargs -r -n 1 basename | sed 's/^femtofox_//;s/\.yaml$//' | grep . || echo -e "\033[0;31mnone (simulated radio)\033[0m" ;; l) # Option -l (choose lora radio model) prepare="rm -f /etc/meshtasticd/config.d/femtofox* && echo \"Radio type $OPTARG selected.\"" @@ -241,6 +258,149 @@ while getopts ":higkl:q:uU:rR:aA:cpo:sM:Stwuxm" opt; do external="true" # set a variable so the function knows it was called by an an external script and not locally meshtastic_update "$2" $3 "$4" ;; + e) # Option -e (Set region/frequency plan) + regions="UNSET US EU_433 EU_868 CN JP ANZ KR TW RU IN NZ_865 TH LORA_24 UA_433 UA_868 MY_433 MY_919 SG_923" + if [[ ! " $regions " =~ " $OPTARG " ]]; then + echo "Error: Invalid option '$OPTARG'. Must be one of $regions." >&2 + echo -e "$help" + exit 1 + else + meshtastic_update "--set lora.region $OPTARG" 3 "Set region" + fi + ;; + P) # Option -P (Use modem preset: enable/disable) + options="true false" + if [[ ! " $options " =~ " $OPTARG " ]]; then + echo "Error: Invalid option '$OPTARG'. Must be one of $options." >&2 + echo -e "$help" + exit 1 + else + meshtastic_update "--set lora.use_preset $OPTARG" 3 "Set use_preset" + fi + ;; + E) # Option -E (Preset. Options are: LONG_FAST, LONG_SLOW, VERY_LONG_SLOW, MEDIUM_SLOW, MEDIUM_FAST, SHORT_SLOW, SHORT_FAST, SHORT_TURBO) + presets="LONG_FAST LONG_SLOW VERY_LONG_SLOW MEDIUM_SLOW MEDIUM_FAST SHORT_SLOW SHORT_FAST SHORT_TURBO" + if [[ ! " $presets " =~ " $OPTARG " ]]; then + echo "Error: Invalid option '$OPTARG'. Must be one of $presets." >&2 + echo -e "$help" + exit 1 + else + meshtastic_update "--set lora.modem_preset $OPTARG" 3 "Set modem_preset" + fi + ;; + b) # Option -b (Set bandwidth; used if modem preset is disabled) + options="31 62 125 250 500" + if [[ ! " $options " =~ " $OPTARG " ]]; then + echo "Error: Invalid option '$OPTARG'. Must be one of $options." >&2 + echo -e "$help" + exit 1 + else + meshtastic_update "--set lora.bandwidth $OPTARG" 3 "Set bandwidth" + fi + ;; + f) # Option -f (Set spread factor; used if modem preset is disabled) + options="7 8 9 10 11 12" + if [[ ! " $options " =~ " $OPTARG " ]]; then + echo "Error: Invalid option '$OPTARG'. Must be one of $options." >&2 + echo -e "$help" + exit 1 + else + meshtastic_update "--set lora.spread_factor $OPTARG" 3 "Set spread_factor" + fi + ;; + C) # Option -C (Set coding rate; used if modem preset is disabled) + options="5 6 7 8" + if [[ ! " $options " =~ " $OPTARG " ]]; then + echo "Error: Invalid option '$OPTARG'. Must be one of $options." >&2 + echo -e "$help" + exit 1 + else + meshtastic_update "--set lora.coding_rate $OPTARG" 3 "Set coding_rate" + fi + ;; + O) # Option -O (Set frequency offset in MHz) + if ! [[ "$OPTARG" =~ ^[0-1000000]$ ]]; then + echo "Error: Invalid option '$OPTARG'. Must be a number between 0 and 1000000." >&2 + echo -e "$help" + exit 1 + else + meshtastic_update "--set lora.frequency_offset $OPTARG" 3 "Set frequency_offset" + fi + ;; + H) # Option -H (Set hop limit, range 0-7) + if ! [[ "$OPTARG" =~ ^[0-7]$ ]]; then + echo "Error: Invalid option '$OPTARG'. Must be a number between 0 and 7." >&2 + echo -e "$help" + exit 1 + else + meshtastic_update "--set lora.hop_limit $OPTARG" 3 "Set hop limit" + fi + ;; + T) # Option -T (Enable/disable TX) + options="true false" + if [[ ! " $options " =~ " $OPTARG " ]]; then + echo "Error: Invalid option '$OPTARG'. Must be one of $options." >&2 + echo -e "$help" + exit 1 + else + meshtastic_update "--set lora.tx_enabled $OPTARG" 3 "Set hop limit" + fi + ;; + X) # Option -X (Set TX power in dBm) + if ! [[ "$OPTARG" =~ ^([0-9]|1[0-9]|2[0-9]|30)$ ]]; then + echo "Error: Invalid option '$OPTARG'. Must be a number between 0 and 30." >&2 + echo -e "$help" + exit 1 + else + meshtastic_update "--set lora.tx_power $OPTARG" 3 "Set tx_power" + fi + ;; + F) # Option -F (Set frequency slot) + meshtastic_update "--set lora.channel_num $OPTARG" 3 "Set frequency slot" + ;; + V) # Option -V (Enable/disable override duty cycle) + options="true false" + if [[ ! " $options " =~ " $OPTARG " ]]; then + echo "Error: Invalid option '$OPTARG'. Must be one of $options." >&2 + echo -e "$help" + exit 1 + else + meshtastic_update "--set lora.override_duty_cycle $OPTARG" 3 "Set override_duty_cycle" + fi + ;; + B) # Option -B (Enable/disable SX126X RX boosted gain) + options="true false" + if [[ ! " $options " =~ " $OPTARG " ]]; then + echo "Error: Invalid option '$OPTARG'. Must be one of $options." >&2 + echo -e "$help" + exit 1 + else + meshtastic_update "--set lora.sx126x_rx_boosted_gain $OPTARG" 3 "Set sx126x_rx_boosted_gain" + fi + ;; + v) # Option -v (Override frequency in MHz; overrides frequency slot) + meshtastic_update "--set lora.override_frequency $OPTARG" 3 "Set override_frequency" + ;; + G) # Option -G (enable/disable ignore MQTT) + options="true false" + if [[ ! " $options " =~ " $OPTARG " ]]; then + echo "Error: Invalid option '$OPTARG'. Must be one of $options." >&2 + echo -e "$help" + exit 1 + else + meshtastic_update "--set lora.ignore_mqtt $OPTARG" 3 "Set ignore_mqtt" + fi + ;; + K) # Option -K (enable/disable OK to MQTT) + options="true false" + if [[ ! " $options " =~ " $OPTARG " ]]; then + echo "Error: Invalid option '$OPTARG'. Must be one of $options." >&2 + echo -e "$help" + exit 1 + else + meshtastic_update "--set lora.config_ok_to_mqtt $OPTARG" 3 "Set config_ok_to_mqtt" + fi + ;; \?) # Invalid option echo "Invalid option: -$OPTARG" echo -e "$help" diff --git a/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-meshtasticd-lora-dialogs.sh b/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-meshtasticd-lora-dialogs.sh new file mode 100755 index 0000000..0857240 --- /dev/null +++ b/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-meshtasticd-lora-dialogs.sh @@ -0,0 +1,587 @@ +#!/bin/bash + +if [[ $EUID -ne 0 ]]; then + echo "This script must be run as root. Try \`sudo femto-meshtasticd-config\`." + exit 1 +fi + +args=$@ + +config_url() { + echo "argument $1" + echo "args $args" + femto-config -c && ( + newurl=$(dialog --no-collapse --title "Meshtastic URL" --inputbox "The Meshtastic configuration URL allows for automatic configuration of all Meshtastic LoRa settings and channels.\n\nNew Meshtastic LoRa configuration URL (SHIFT+INS to paste):" 11 63 3>&1 1>&2 2>&3) + if [ -n "$newurl" ]; then #if a URL was entered + dialog --no-collapse --title "$title" --yesno "New Meshtastic LoRa configuration URL:\n$newurl\n\nConfirm?" 15 60 + if [ $? -eq 0 ]; then #unless cancel/no + set -o pipefail + output=$(femto-meshtasticd-config.sh -q "$newurl" | tee /dev/tty) + exit_status=$? + set +o pipefail + meshtastic_command_result $exit_status "$output" + fi + fi + # if we're in wizard mode AND there are no script arguments, then display a message + [ "$1" = "wizard" ] && [ -z "$args" ] && dialog --no-collapse --title "$title" --colors --msgbox "Meshtastic LoRa Settings Wizard complete!" 6 50 + return + ) +} + +#set lora radio +set_lora_radio() { + choice="" # zero the choice before loading the submenu + while true; do + echo "Checking LoRa radio..." + #Display filename, if exists: $(files=$(ls /etc/meshtasticd/config.d/* 2>/dev/null) && [ -n "$files" ] && echo "\n\nConfiguration files in use:\n$files" | paste -sd, -)) + choice=$(dialog --no-collapse --colors --cancel-label "Cancel" --default-item "$choice" --title "Meshtastic LoRa radio" --item-help --menu "Currently configured LoRa radio:\n$(femto-utils.sh -R "$(femto-meshtasticd-config.sh -k)")$(ls -1 /etc/meshtasticd/config.d 2>/dev/null | grep -v '^femto_' | paste -sd ', ' - | sed 's/^/ (/; s/$/)/; s/,/, /g' | grep -v '^ ()$')" 22 50 10 \ + "Radio name:" "Configuration:" "" \ + "" "" "" \ + "Ebyte e22-900m30s" "(SX1262_TCXO)" "Included in Femtofox Pro" \ + "Ebyte e22-900m22s" "(SX1262_TCXO)" "" \ + "Ebyte e80-900m22s" "(SX1262_XTAL)" "" \ + "Heltec ht-ra62" "(SX1262_TCXO)" "" \ + "Seeed wio-sx1262" "(SX1262_TCXO)" "" \ + "Waveshare sx126x-xxxm" "(SX1262_XTAL)" "Not recommended due issues with sending longer messages" \ + "AI Thinker ra-01sh" "(SX1262_XTAL)" "" \ + "LoRa Meshstick 1262" "(meshstick-1262)" "USB based LoRa radio from Mark Birss. https://github.com/markbirss/MESHSTICK" \ + "Simulated radio" "(none)" "" \ + " " "" "" \ + "Cancel" "" "" 3>&1 1>&2 2>&3) + [ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog + local radio="" + case $choice in + "Ebyte e22-900m30s") + radio="sx1262_tcxo" + ;; + "Ebyte e22-900m22s") + radio="sx1262_tcxo" + ;; + "Ebyte e80-900m22s") + radio="sx1262_xtal" + ;; + "Heltec ht-ra62") + radio="sx1262_tcxo" + ;; + "Seeed wio-sx1262") + radio="sx1262_tcxo" + ;; + "Waveshare sx126x-xxxm") + radio="sx1262_xtal" + ;; + "AI Thinker ra-01sh") + radio="femto_sx1262_xtal" + ;; + "LoRa Meshstick 1262") + radio="lora-meshstick-1262" + ;; + "Simulated radio") + radio="none" + ;; + "Skip") + return + ;; + esac + if [ -n "$radio" ]; then #if a radio was selected + femto-meshtasticd-config.sh -l "$radio" -s # set the radio, then restart meshtasticd + dialog --no-collapse --colors --title "$title" --msgbox "$(echo -e "Radio \Zu$choice\Zn selected.\nMeshtasticd service restarted.\Zn")" 7 45 + return + fi + done +} + +lora_settings_actions() { + local title="Meshtastic LoRa Settings" + + meshtastic_command_result() { + if [ $1 -eq 1 ]; then + dialog --no-collapse --colors --title "$title" --msgbox "$(echo -e "\Z1Command FAILED!\Zn\n\nLog:\n$2")" 0 0 + elif [ $1 -eq 0 ]; then + dialog --no-collapse --title "$title" --msgbox "$(echo -e "Command Successful!")" 6 45 + fi + } + + if [ "$1" = "set_lora_radio_model" ] || [ "$1" = "wizard" ]; then + femto-config -c && { + set_lora_radio + } + [ "$1" != "wizard" ] && return + fi + + if [ "$1" = "wizard" ]; then + femto-config -c && { + choice="" # zero the choice before loading the submenu + while true; do + choice=$(dialog --no-collapse --title "$title" --cancel-label "Cancel" --default-item "True" --item-help --menu "Meshtastic configuration method" 8 50 0 \ + "Automatic configuration with URL" "x" "" \ + "Manual configuration" "x" "" \ + " " "" "" \ + "Cancel" "" "" 3>&1 1>&2 2>&3) + [ $? -eq 1 ] || [ "$choice" == "Cancel" ] && return # Exit the loop if the user selects "Cancel" or closes the dialog + [ "$choice" == "" ] && continue #restart loop if no choice made + [ "$choice" == "Manual configuration" ] && break + [ "$choice" == "Automatic configuration with URL" ] && config_url "$1" + return + done + } + fi + + if [ "$1" = "region" ] || [ "$1" = "wizard" ]; then + femto-config -c && { + options=("UNSET" "US" "EU_433" "EU_868" "CN" "JP" "ANZ" "KR" "TW" "RU" "IN" "NZ_865" "TH" "LORA_24" "UA_433" "UA_868" "MY_433" "MY_919" "SG_923") + menu_items=() + # Create menu options from the array + for i in "${!options[@]}"; do + if [ $i -eq 0 ]; then + menu_items+=("${options[$i]}" "(default)" "") # First item with "(default)" + else + menu_items+=("${options[$i]}" "" "") # Other items without "(default)" + fi + done + menu_items+=("" "" "" "Cancel" "" "") + while true; do + choice=$(dialog --no-collapse --title "$title" --cancel-label "Cancel" --default-item "LONG_FAST" --item-help --menu "Region (default: UNSET)?" 8 40 0 \ + "${menu_items[@]}" 3>&1 1>&2 2>&3) + [ $? -eq 1 ] || [ "$choice" == "Cancel" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog + [ "$choice" == "" ] && continue # Restart loop if no choice made + set -o pipefail + output=$(femto-meshtasticd-config.sh -e $choice | tee /dev/tty) + exit_status=$? + set +o pipefail + meshtastic_command_result $exit_status "$output" + break + done + } + [ "$1" != "wizard" ] && return + fi + + if [ "$1" = "use_modem_preset" ] || [ "$1" = "wizard" ]; then + femto-config -c && { + choice="" # zero the choice before loading the submenu + while true; do + choice=$(dialog --no-collapse --title "$title" --cancel-label "Cancel" --default-item "True" --item-help --menu "Use modem preset?" 8 40 0 \ + "True" "(default)" "" \ + "False" "" "" \ + " " "" "" \ + "Cancel" "" "" 3>&1 1>&2 2>&3) + [ $? -eq 1 ] || [ "$choice" == "Cancel" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog + [ "$choice" == "" ] && continue #restart loop if no choice made + using_preset="$choice" + set -o pipefail + output=$(femto-meshtasticd-config.sh -P $(echo "$choice" | tr '[:upper:]' '[:lower:]') | tee /dev/tty) # make lower case + exit_status=$? + set +o pipefail + meshtastic_command_result $exit_status "$output" + break + done + } + [ "$1" != "wizard" ] && return + fi + + if [ "$1" = "wizard" ] && [ "$using_preset" = "False" ]; then + dialog --no-collapse --title "$title" --colors --msgbox "Not using preset, so skipping Preset setting." 6 50 + else + if [ "$1" = "preset" ] || [ "$1" = "wizard" ]; then + femto-config -c && { + options=("LONG_FAST" "LONG_SLOW" "VERY_LONG_SLOW" "MEDIUM_SLOW" "MEDIUM_FAST" "SHORT_SLOW" "SHORT_FAST" "SHORT_TURBO") + menu_items=() + # Create menu options from the array + for i in "${!options[@]}"; do + if [ $i -eq 0 ]; then + menu_items+=("${options[$i]}" "(default)" "") # First item with "(default)" + else + menu_items+=("${options[$i]}" "" "") # Other items without "(default)" + fi + done + menu_items+=("" "" "" "Cancel" "" "") + while true; do + choice=$(dialog --no-collapse --title "$title" --cancel-label "Cancel" --default-item "LONG_FAST" --item-help --menu "Preset?" 8 40 0 \ + "${menu_items[@]}" 3>&1 1>&2 2>&3) + [ $? -eq 1 ] || [ "$choice" == "Cancel" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog + [ "$choice" == "" ] && continue # Restart loop if no choice made + set -o pipefail + output=$(femto-meshtasticd-config.sh -E $choice | tee /dev/tty) + exit_status=$? + set +o pipefail + meshtastic_command_result $exit_status "$output" + break + done + } + [ "$1" != "wizard" ] && return + fi + fi + + if [ "$1" = "wizard" ] && [ "$using_preset" = "True" ]; then + dialog --no-collapse --title "$title" --colors --msgbox "Using preset, so skipping Bandwidth, Spread Factor and Coding Rate settings." 7 50 + else + if [ "$1" = "bandwidth" ] || [ "$1" = "wizard" ]; then + femto-config -c && { + options=("31" "62" "125" "250" "500") + menu_items=() + for option in "${options[@]}"; do + menu_items+=("$option" "x" "") + done + menu_items+=("" "" "" "Cancel" "" "") + while true; do + choice=$(dialog --no-collapse --title "$title" --cancel-label "Cancel" --item-help --menu "Bandwidth (only used if modem preset is disabled)?" 8 40 0 \ + "${menu_items[@]}" 3>&1 1>&2 2>&3) + [ $? -eq 1 ] || [ "$choice" == "Cancel" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog + [ "$choice" == "" ] && continue # Restart loop if no choice made + set -o pipefail + output=$(femto-meshtasticd-config.sh -b $choice | tee /dev/tty) + exit_status=$? + set +o pipefail + meshtastic_command_result $exit_status "$output" + break + done + } + [ "$1" != "wizard" ] && return + fi + + if [ "$1" = "spread_factor" ] || [ "$1" = "wizard" ]; then + femto-config -c && { + options=("7" "8" "9" "10" "11" "12") + menu_items=() + for option in "${options[@]}"; do + menu_items+=("$option" "x" "") + done + menu_items+=("" "" "" "Cancel" "" "") + while true; do + choice=$(dialog --no-collapse --title "$title" --cancel-label "Cancel" --item-help --menu "Spread factor (only used if modem preset is disabled)?" 8 40 0 \ + "${menu_items[@]}" 3>&1 1>&2 2>&3) + [ $? -eq 1 ] || [ "$choice" == "Cancel" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog + [ "$choice" == "" ] && continue # Restart loop if no choice made + set -o pipefail + output=$(femto-meshtasticd-config.sh -f $choice | tee /dev/tty) + exit_status=$? + set +o pipefail + meshtastic_command_result $exit_status "$output" + break + done + } + [ "$1" != "wizard" ] && return + fi + + if [ "$1" = "coding_rate" ] || [ "$1" = "wizard" ]; then + femto-config -c && { + options=("5" "6" "7" "8") + menu_items=() + for option in "${options[@]}"; do + menu_items+=("$option" "x" "") + done + menu_items+=("" "" "" "Cancel" "" "") + while true; do + choice=$(dialog --no-collapse --title "$title" --cancel-label "Cancel" --item-help --menu "Coding rate (only used if modem preset is disabled)?" 8 40 0 \ + "${menu_items[@]}" 3>&1 1>&2 2>&3) + [ $? -eq 1 ] || [ "$choice" == "Cancel" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog + [ "$choice" == "" ] && continue # Restart loop if no choice made + set -o pipefail + output=$(femto-meshtasticd-config.sh -C $choice | tee /dev/tty) + exit_status=$? + set +o pipefail + meshtastic_command_result $exit_status "$output" + break + done + } + [ "$1" != "wizard" ] && return + fi + fi + + if [ "$1" = "frequency_offset" ] || [ "$1" = "wizard" ]; then + femto-config -c && { + input=$(dialog --no-collapse --title "$title" --cancel-label "Cancel" --inputbox "Frequency offset (default: 0)" 8 50 3>&1 1>&2 2>&3) + if [ $? -ne 1 ] && [ -n "$input" ]; then + set -o pipefail + output=$(femto-meshtasticd-config.sh -O $input | tee /dev/tty) + exit_status=$? + set +o pipefail + meshtastic_command_result $exit_status "$output" + fi + } + [ "$1" != "wizard" ] && return + fi + + if [ "$1" = "hop_limit" ] || [ "$1" = "wizard" ]; then + femto-config -c && { + input=$(dialog --no-collapse --title "$title" --cancel-label "Cancel" --inputbox "Hop limit (default: 3)\nExcessive hop limit increases congestion!" 9 50 3>&1 1>&2 2>&3) + if [ $? -ne 1 ] && [ -n "$input" ]; then + set -o pipefail + output=$(femto-meshtasticd-config.sh -H $input | tee /dev/tty) + exit_status=$? + set +o pipefail + meshtastic_command_result $exit_status "$output" + fi + } + [ "$1" != "wizard" ] && return + fi + + if [ "$1" = "tx_enabled" ] || [ "$1" = "wizard" ]; then + femto-config -c && { + choice="" # zero the choice before loading the submenu + while true; do + choice=$(dialog --no-collapse --title "$title" --cancel-label "Cancel" --default-item "True" --item-help --menu "Enable TX?" 8 40 0 \ + "True" "(default)" "" \ + "False" "" "" \ + " " "" "" \ + "Cancel" "" "" 3>&1 1>&2 2>&3) + [ $? -eq 1 ] || [ "$choice" == "Cancel" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog + [ "$choice" == "" ] && continue #restart loop if no choice made + set -o pipefail + output=$(femto-meshtasticd-config.sh -T $(echo "$choice" | tr '[:upper:]' '[:lower:]') | tee /dev/tty) # make lower case + exit_status=$? + set +o pipefail + meshtastic_command_result $exit_status "$output" + break + done + } + [ "$1" != "wizard" ] && return + fi + + if [ "$1" = "tx_power" ] || [ "$1" = "wizard" ]; then + femto-config -c && { + input=$(dialog --no-collapse --colors --title "$title" --cancel-label "Cancel" --inputbox "\ +\Z1\ZuWARNING!\Zn\n\ +Setting a 33db radio above 8db will \Zupermanently\Zn damage it.\n\ +ERP above 27db violates EU law.\n\ +ERP above 36db violates US (unlicensed) law.\n\ +\n\ +TX power in db (default: 22)" 13 62 3>&1 1>&2 2>&3) + if [ $? -ne 1 ] && [ -n "$input" ]; then + set -o pipefail + output=$(femto-meshtasticd-config.sh -X $input | tee /dev/tty) + exit_status=$? + set +o pipefail + meshtastic_command_result $exit_status "$output" + fi + } + [ "$1" != "wizard" ] && return + fi + + if [ "$1" = "frequency_slot" ] || [ "$1" = "wizard" ]; then + femto-config -c && { + input=$(dialog --no-collapse --title "$title" --cancel-label "Cancel" --inputbox "Frequency slot (0 for automatic)" 8 50 3>&1 1>&2 2>&3) + if [ $? -ne 1 ] && [ -n "$input" ]; then + set -o pipefail + output=$(femto-meshtasticd-config.sh -F $input | tee /dev/tty) + exit_status=$? + set +o pipefail + meshtastic_command_result $exit_status "$output" + fi + } + [ "$1" != "wizard" ] && return + fi + + if [ "$1" = "override_duty_cycle" ] || [ "$1" = "wizard" ]; then + femto-config -c && { + while true; do + choice=$(dialog --no-collapse --title "$title" --cancel-label "Cancel" --default-item "False" --item-help --menu "Override duty cycle?\nMay have legal ramifications." 9 40 0 \ + "True" "" "" \ + "False" "(default)" "" \ + " " "" "" \ + "Cancel" "" "" 3>&1 1>&2 2>&3) + [ $? -eq 1 ] || [ "$choice" == "Cancel" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog + [ "$choice" == "" ] && continue #restart loop if no choice made + set -o pipefail + output=$(femto-meshtasticd-config.sh -V $(echo "$choice" | tr '[:upper:]' '[:lower:]') | tee /dev/tty) # make lower case + exit_status=$? + set +o pipefail + meshtastic_command_result $exit_status "$output" + break + done + } + [ "$1" != "wizard" ] && return + fi + + if [ "$1" = "sx126x_rx_boosted_gain" ] || [ "$1" = "wizard" ]; then + femto-config -c && { + while true; do + choice=$(dialog --no-collapse --title "$title" --cancel-label "Cancel" --default-item "True" --item-help --menu "Enable SX126X RX boosted gain?" 8 40 0 \ + "True" "(default)" "" \ + "False" "" "" \ + " " "" "" \ + "Cancel" "" "" 3>&1 1>&2 2>&3) + [ $? -eq 1 ] || [ "$choice" == "Cancel" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog + [ "$choice" == "" ] && continue #restart loop if no choice made + set -o pipefail + output=$(femto-meshtasticd-config.sh -B $(echo "$choice" | tr '[:upper:]' '[:lower:]') | tee /dev/tty) # make lower case + exit_status=$? + set +o pipefail + meshtastic_command_result $exit_status "$output" + break + done + } + [ "$1" != "wizard" ] && return + fi + + if [ "$1" = "override_frequency" ] || [ "$1" = "wizard" ]; then + femto-config -c && { + input=$(dialog --no-collapse --title "$title" --cancel-label "Cancel" --inputbox "Override frequency in MHz (0 for none).\nOverrides frequency slot." 9 50 3>&1 1>&2 2>&3) + if [ $? -ne 1 ] && [ -n "$input" ]; then + set -o pipefail + output=$(femto-meshtasticd-config.sh -v $input | tee /dev/tty | tee /dev/tty) + exit_status=$? + set +o pipefail + meshtastic_command_result $exit_status "$output" + fi + } + [ "$1" != "wizard" ] && return + fi + + if [ "$1" = "ignore_mqtt" ] || [ "$1" = "wizard" ]; then + femto-config -c && { + while true; do + choice=$(dialog --no-collapse --title "$title" --cancel-label "Cancel" --default-item "False" --item-help --menu "Ignore MQTT?" 8 40 0 \ + "True" "" "" \ + "False" "(default)" "" \ + " " "" "" \ + "Cancel" "" "" 3>&1 1>&2 2>&3) + [ $? -eq 1 ] || [ "$choice" == "Cancel" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog + [ "$choice" == "" ] && continue #restart loop if no choice made + set -o pipefail + output=$(femto-meshtasticd-config.sh -G $(echo "$choice" | tr '[:upper:]' '[:lower:]') | tee /dev/tty) # make lower case + exit_status=$? + set +o pipefail + meshtastic_command_result $exit_status "$output" + break + done + } + [ "$1" != "wizard" ] && return + fi + + if [ "$1" = "ok_to_mqtt" ] || [ "$1" = "wizard" ]; then + femto-config -c && { + while true; do + choice=$(dialog --no-collapse --title "$title" --cancel-label "Cancel" --default-item "False" --item-help --menu "OK to MQTT?" 8 40 0 \ + "True" "" "" \ + "False" "(default)" "" \ + " " "" "" \ + "Cancel" "" "" 3>&1 1>&2 2>&3) + [ $? -eq 1 ] || [ "$choice" == "Cancel" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog + [ "$choice" == "" ] && continue #restart loop if no choice made + set -o pipefail + output=$(femto-meshtasticd-config.sh -K $(echo "$choice" | tr '[:upper:]' '[:lower:]') | tee /dev/tty) # make lower case + exit_status=$? + set +o pipefail + meshtastic_command_result $exit_status "$output" + break + done + } + [ "$1" != "wizard" ] && return + fi + + # if we're in wizard mode AND there are no script arguments, then display a message + [ "$1" = "wizard" ] && [ -z "$args" ] && dialog --no-collapse --title "$title" --colors --msgbox "Meshtastic LoRa Settings Wizard complete!" 6 50 + + [ "$1" = "wizard" ] && return # quit function if wizard +} + + +# Parse options +help="If script is run without arguments, menu will load.\n\ +Options are:\n\ +-h This message\n\ +-w Wizard mode\ +" +while getopts ":hw" opt; do + case ${opt} in + h) # Option -h (help) + echo -e $help + ;; + w) # Option -w (Wizard mode) + lora_settings_actions "wizard" + ;; + \?) # Unknown option) + echo -e "Unknown argument $1.\n$help" + ;; + esac +done +[ -n "$1" ] && exit # if there were arguments, exit before loading the menu + + +LoRa_menu_choice="" # zero the choice before loading the submenu +while true; do + LoRa_menu_choice=$(dialog --no-collapse --title "Meshtastic LoRa Settings" --default-item "$LoRa_menu_choice" --cancel-label "Back" --item-help --menu "LoRa settings can also be set automatically by entering a Meshtastic configuration URL." 30 50 20 \ + 1 "Wizard (set all)" "" \ + 2 "Set LoRa radio model" "" \ + 3 "Configure automatically with URL" "" \ + 4 "Region" "" \ + 5 "Use modem preset" "" \ + 6 "Preset" "" \ + 7 "Bandwidth" "" \ + 8 "Spread factor" "" \ + 9 "Coding rate" "" \ + 10 "Frequency offset" "" \ + 11 "Hop limit" "" \ + 12 "Enable/disable TX" "" \ + 13 "TX power" "" \ + 14 "Frequency slot" "" \ + 15 "Override duty cycle" "" \ + 16 "SX126X RX boosted gain " "" \ + 17 "Override frequency" "" \ + 18 "Ignore MQTT" "" \ + 19 "OK to MQTT" "" \ + " " "" "" \ + 20 "Back to Meshtastic Menu" "" 3>&1 1>&2 2>&3) + [ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog + case $LoRa_menu_choice in + 1) # Wizard (set all) + lora_settings_actions "wizard" + ;; + 2) # Set LoRa radio model) + lora_settings_actions "set_lora_radio_model" + ;; + 3) # Configure automatically with URL) + config_url + ;; + 4) # Region) + lora_settings_actions "region" + ;; + 5) # Use modem preset) + lora_settings_actions "use_modem_preset" + ;; + 6) # Preset) + lora_settings_actions "preset" + ;; + 7) # Bandwidth) + lora_settings_actions "bandwidth" + ;; + 8) # Spread factor) + lora_settings_actions "spread_factor" + ;; + 9) # Coding rate) + lora_settings_actions "coding_rate" + ;; + 10) # Frequency offset) + lora_settings_actions "frequency_offset" + ;; + 11) # Hop limit) + lora_settings_actions "hop_limit" + ;; + 12) # Enable/disable TX) + lora_settings_actions "tx_enabled" + ;; + 13) # TX power) + lora_settings_actions "tx_power" + ;; + 14) # Frequency slot) + lora_settings_actions "frequency_slot" + ;; + 15) # Override duty cycle) + lora_settings_actions "override_duty_cycle" + ;; + 16) # SX126X RX boosted gain) + lora_settings_actions "sx126x_rx_boosted_gain" + ;; + 17) # Override frequency) + lora_settings_actions "override_frequency" + ;; + 18) # Ignore MQTT) + lora_settings_actions "ignore_mqtt" + ;; + 19) # OK to MQTT) + lora_settings_actions "ok_to_mqtt" + ;; + 20) break ;; + esac +done + diff --git a/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-software.sh b/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-software.sh index 21d635c..4e0ac3d 100755 --- a/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-software.sh +++ b/foxbuntu/sysdrv/out/rootfs_uclibc_rv1106/usr/local/bin/femto-software.sh @@ -19,7 +19,6 @@ install() { output="$truncated_output" fi user_message=$(echo "$output" | awk '/user_message: / {found=1; split($0, arr, "user_message: "); print arr[2]; next} found {print}' | sed '/^$/q') # grab the user_message, if present - echo $user_message output=$(echo -e "$output" | sed '/user_message: /,$d') # remove the user message from the detailed output if [ $install_status -eq 0 ]; then # if the installation was successful @@ -113,7 +112,11 @@ package_menu() { $(if $package_dir/$1.sh -O | grep -q 'e' && $package_dir/$1.sh -I; then echo "Start/restart service x"; fi) \ $(if $package_dir/$1.sh -O | grep -q 'S' && $package_dir/$1.sh -I; then echo "Detailed service status x"; fi)" menu_count=$(( $(echo "$menu_list" | grep -o " x" | wc -l) $(if $package_dir/$1.sh -O | grep -q 'e' && $package_dir/$1.sh -I; then echo "+1"; fi) )) # count the number of menu items by counting how many times " x" shows up, +1 if there's a service. This is a stupid way to do this, but because each menu item only contains one space (the rest being space-sized invisible chars) it works. It's late at night, OKAY?! - choice=$(dialog --no-collapse --colors --title "$($package_dir/$1.sh -N)" $license_button --cancel-label "Back" --default-item "$choice" --menu "$(if $package_dir/$1.sh -O | grep -q 'S' && $package_dir/$1.sh -I; then echo "Service status: $(femto-utils.sh -R "$service_state")"; fi)" $(( menu_count + 9 )) 45 $(( menu_count + 3 )) \ + if $package_dir/$1.sh -O | grep -q 'e' && [ "$($package_dir/$1.sh -E | wc -w)" -gt 1 ]; then + multiple_services_note="\nService will appear as \"running\" if any of the services are active." + menu_count=$((menu_count + 2)) + fi + choice=$(dialog --no-collapse --colors --title "$($package_dir/$1.sh -N)" $license_button --cancel-label "Back" --default-item "$choice" --menu "$(if $package_dir/$1.sh -O | grep -q 'S' && $package_dir/$1.sh -I; then echo "Service status: $(femto-utils.sh -R "$service_state")"; fi)$multiple_services_note" $(( menu_count + 9 )) 45 $(( menu_count + 3 )) \ $menu_list \ " " "" \ "Back to software manager" "" 3>&1 1>&2 2>&3)