diff --git a/general/package/wifibroadcast-ext/files/bitrate_calculator.sh b/general/package/wifibroadcast-ext/files/bitrate_calculator.sh new file mode 100644 index 00000000..751d6f85 --- /dev/null +++ b/general/package/wifibroadcast-ext/files/bitrate_calculator.sh @@ -0,0 +1,326 @@ +#!/bin/sh +# +# bitrate_calculator.sh +# +# This script supports two modes: +# +# 1. Normal (default) mode: +# Usage: +# bitrate_calculator.sh [fec_ratio] [max_mcs (0-7)] [--cap ] [--gi ] [--max_bw <20|40>] +# +# If fec_ratio is not provided, it defaults to "8/12". +# The script searches (in fixed order: 20 MHz long, 20 MHz short, then 40 MHz long, 40 MHz short) +# for the lowest MCS (0..max_mcs, default max_mcs=7) whose computed forward rate is ≥ target. +# If the optional "--gi" is provided, only that guard interval is used. +# If the optional "--max_bw" is provided, it limits the search to that maximum bandwidth. +# +# The computed rate is given by: +# +# final = ( base_rate * 3 * fec_n + (4*fec_k)/2 ) / (4*fec_k) +# +# where base_rate (in kbps) is looked up from hardcoded tables. +# The computed rate is capped at a maximum value (default cap is 20000 kbps, +# overrideable via --cap). +# +# Output is a single line in the format: +# ::: +# +# 2. Backwards mode: +# Usage: +# bitrate_calculator.sh --backwards [--cap ] +# +# It computes (and outputs) the forward rate (capped) for the given parameters. +# + +# ------------------------- +# Parse optional global arguments +# ------------------------- +# Default cap is 20000 kbps. +CAP=20000 +backwards_mode=0 +locked_gi="" +MAX_BW=40 # new: default maximum bandwidth for candidate search is 40MHz (i.e. search both 20 & 40) +other_args="" + +while [ "$#" -gt 0 ]; do + case "$1" in + --cap) + shift + if [ "$#" -eq 0 ]; then + echo "Error: --cap requires a value" + exit 1 + fi + CAP="$1" + shift + ;; + --backwards) + backwards_mode=1 + shift + ;; + --gi) + shift + if [ "$#" -eq 0 ]; then + echo "Error: --gi requires a value (long or short)" + exit 1 + fi + locked_gi="$1" + case "$locked_gi" in + long|short) ;; + *) echo "Error: --gi must be 'long' or 'short'." ; exit 1 ;; + esac + shift + ;; + --max_bw) + shift + if [ "$#" -eq 0 ]; then + echo "Error: --max_bw requires a value (20 or 40)" + exit 1 + fi + if [ "$1" != "20" ] && [ "$1" != "40" ]; then + echo "Error: --max_bw must be either 20 or 40" + exit 1 + fi + MAX_BW="$1" + shift + ;; + *) + other_args="$other_args $1" + shift + ;; + esac +done + +set -- $other_args + +# ------------------------- +# Function: compute_final +# ------------------------- +# Given: +# bw : Bandwidth (20 or 40) +# gi : Guard interval ("long" or "short") +# mcs : MCS index (0-7) +# fec_n : FEC numerator +# fec_k : FEC denominator +# +# Looks up the base_rate (in kbps) from hardcoded tables: +# +# 20 MHz: +# Long GI: 6500, 13000, 19500, 26000, 39000, 52000, 58500, 65000 +# Short GI: 7200, 14400, 21700, 28900, 43300, 57800, 65000, 72200 +# +# 40 MHz: +# Long GI: (20% reduced) 10800, 21600, 32400, 43200, 64800, 86400, 97200, 108000 +# Short GI: (20% reduced) 12000, 24000, 36000, 48000, 72000, 96000, 108000, 120000 +# +# Then computes: +# +# final = ( base_rate * 3 * fec_n + (4*fec_k)/2 ) / (4*fec_k) +# +# If final > CAP, it is set to CAP. +compute_final() { + bw="$1" + gi="$2" + mcs="$3" + fec_n="$4" + fec_k="$5" + + if [ "$bw" -eq 20 ]; then + if [ "$gi" = "long" ]; then + case "$mcs" in + 0) base=6500 ;; + 1) base=12000 ;; + 2) base=15500 ;; + 3) base=20000 ;; + 4) base=25000 ;; + 5) base=42000 ;; + 6) base=47500 ;; + 7) base=55000 ;; + esac + else + case "$mcs" in + 0) base=7200 ;; + 1) base=13400 ;; + 2) base=18700 ;; + 3) base=21900 ;; + 4) base=28300 ;; + 5) base=43800 ;; + 6) base=50000 ;; + 7) base=55200 ;; + esac + fi + elif [ "$bw" -eq 40 ]; then + if [ "$gi" = "long" ]; then + case "$mcs" in + 0) base=9800 ;; + 1) base=18600 ;; + 2) base=30400 ;; + 3) base=40200 ;; + 4) base=55800 ;; + 5) base=80400 ;; + 6) base=90200 ;; + 7) base=97000 ;; + esac + else + case "$mcs" in + 0) base=12000 ;; + 1) base=24000 ;; + 2) base=36000 ;; + 3) base=48000 ;; + 4) base=60000 ;; + 5) base=91000 ;; + 6) base=980000 ;; + 7) base=100000 ;; + esac + fi + else + echo "Error: unsupported bandwidth $bw" >&2 + exit 1 + fi + + denom=$(( 3 * fec_k )) + half_denom=$(( denom / 2 )) + num=$(( base * 2 * fec_n )) + final=$(( (num + half_denom) / denom )) + if [ "$final" -gt "$CAP" ]; then + final="$CAP" + fi + echo "$final" +} + +# ------------------------- +# Mode Selection +# ------------------------- +if [ "$backwards_mode" -eq 1 ]; then + # Backwards mode: Expect exactly 4 arguments: bw, mcs, guard, fec. + if [ "$#" -ne 4 ]; then + echo "Usage: $0 --backwards [--cap ]" + exit 1 + fi + + bw="$1" + mcs="$2" + guard="$3" + fec="$4" + + if [ "$bw" -ne 20 ] && [ "$bw" -ne 40 ]; then + echo "Error: bandwidth must be 20 or 40." + exit 1 + fi + + case "$mcs" in + [0-7]) ;; + *) echo "Error: mcs must be between 0 and 7." ; exit 1 ;; + esac + + if [ "$guard" != "long" ] && [ "$guard" != "short" ]; then + echo "Error: guard must be 'long' or 'short'." + exit 1 + fi + + fec_n=$(echo "$fec" | cut -d'/' -f1) + fec_k=$(echo "$fec" | cut -d'/' -f2) + if [ -z "$fec_n" ] || [ -z "$fec_k" ]; then + echo "Error: fec ratio must be in the form x/y." + exit 1 + fi + + final=$(compute_final "$bw" "$guard" "$mcs" "$fec_n" "$fec_k") + echo "$final" + exit 0 +fi + +# ------------------------- +# Normal Mode (Forward Search) +# ------------------------- +# Usage: +# bitrate_calculator.sh [fec_ratio] [max_mcs (0-7)] [--cap ] [--gi ] +# +# If fec_ratio is not provided, default is "8/12". If max_mcs is not provided, default is 7. +if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then + echo "Usage: $0 [fec_ratio] [max_mcs (0-7)] [--cap ] [--gi ] [--max_bw <20|40>]" + exit 1 +fi + +target="$1" +shift + +case "$target" in + ''|*[!0-9]*) + echo "Error: target must be a positive integer." >&2 + exit 1 + ;; +esac + +if [ "$#" -ge 1 ]; then + case "$1" in + */*) fec="$1"; shift;; + *) fec="8/12" ;; + esac +else + fec="8/12" +fi + +fec_n=$(echo "$fec" | cut -d'/' -f1) +fec_k=$(echo "$fec" | cut -d'/' -f2) +if [ -z "$fec_n" ] || [ -z "$fec_k" ]; then + echo "Error: fec ratio must be in the form x/y." >&2 + exit 1 +fi + +if [ "$#" -ge 1 ]; then + max_mcs="$1" + shift + case "$max_mcs" in + [0-7]) ;; + *) echo "Error: max_mcs must be between 0 and 7." >&2; exit 1 ;; + esac +else + max_mcs=7 +fi + +# Define which bandwidth values to search based on the --max_bw option. +if [ "$MAX_BW" -eq 20 ]; then + BW_VALUES="20" +else + BW_VALUES="20 40" +fi + +candidate_found=0 +if [ -n "$locked_gi" ]; then + for bw in $BW_VALUES; do + for mcs in $(seq 0 $max_mcs); do + final=$(compute_final "$bw" "$locked_gi" "$mcs" "$fec_n" "$fec_k") + if [ "$final" -ge "$target" ]; then + candidate_mcs="$mcs" + candidate_bw="$bw" + candidate_gi="$locked_gi" + candidate_fec="$fec" + candidate_found=1 + break 2 + fi + done + done +else + for bw in $BW_VALUES; do + for gi in long short; do + for mcs in $(seq 0 $max_mcs); do + final=$(compute_final "$bw" "$gi" "$mcs" "$fec_n" "$fec_k") + if [ "$final" -ge "$target" ]; then + candidate_mcs="$mcs" + candidate_bw="$bw" + candidate_gi="$gi" + candidate_fec="$fec" + candidate_found=1 + break 3 + fi + done + done + done +fi + +if [ "$candidate_found" -eq 1 ]; then + echo "${candidate_mcs}:${candidate_bw}:${candidate_gi}:${candidate_fec}" +else + echo "No combination found." >&2 + exit 1 +fi diff --git a/general/package/wifibroadcast-ext/files/channels.sh b/general/package/wifibroadcast-ext/files/channels.sh new file mode 100644 index 00000000..5c3c2a0e --- /dev/null +++ b/general/package/wifibroadcast-ext/files/channels.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +if [ "$1" -eq 5 ]; then + echo "Channel5 change." + + # Retrieve the telemetry setting from the YAML file + tx_on_arm=$(yaml-cli -i /etc/wfb.yaml -g .telemetry.tx_on_arm) + + # Only run the TX ON ARM code if the setting is "enabled" + if [ "$tx_on_arm" = "enabled" ]; then + ##TX ON ARM BEGIN + if [ "$2" -lt 1200 ]; then + echo "Disarm detected, setting low power" + set_alink_tx_pwr.sh 1 + elif [ "$2" -gt 1800 ]; then + echo "ARM detected, setting high power" + set_alink_tx_pwr.sh 9 + fi + ##TX ON ARM END + fi +fi +exit 0 diff --git a/general/package/wifibroadcast-ext/files/detect_redundancy.sh b/general/package/wifibroadcast-ext/files/detect_redundancy.sh new file mode 100644 index 00000000..0d60aa30 --- /dev/null +++ b/general/package/wifibroadcast-ext/files/detect_redundancy.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +echo "8 12" + +exit 0 diff --git a/general/package/wifibroadcast-ext/files/firstboot.sh b/general/package/wifibroadcast-ext/files/firstboot.sh new file mode 100644 index 00000000..3c773e0a --- /dev/null +++ b/general/package/wifibroadcast-ext/files/firstboot.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +firstboot diff --git a/general/package/wifibroadcast-ext/files/generate_backup.sh b/general/package/wifibroadcast-ext/files/generate_backup.sh new file mode 100644 index 00000000..7148aac8 --- /dev/null +++ b/general/package/wifibroadcast-ext/files/generate_backup.sh @@ -0,0 +1,116 @@ +#!/bin/sh +# +# Script: generate_backup.sh +# Purpose: Read one or more file/directory paths (from a file list or a single argument), +# copy them into a staging area preserving their relative paths, +# remove unwanted subdirectories (specifically /overlay/root/root if backing up /overlay/root), +# and then generate a SHA1 checksum file where the filenames are shown relative to the staging root. +# +# Usage: +# ./generate_backup.sh file_list.txt +# - Reads absolute paths (files or directories) from file_list.txt. +# +# ./generate_backup.sh /some/path +# - Backs up the specified path recursively. +# +# ./generate_backup.sh +# - Defaults to backing up /overlay/root. +# + +# --- Determine Input Mode --- +found_overlay_root=0 + +if [ $# -lt 1 ]; then + mode="single" + single_path="/overlay/root" +elif [ -f "$1" ]; then + mode="list" + list_file="$1" +elif [ -d "$1" ]; then + mode="single" + single_path="$1" +else + echo "Error: Provided argument is neither a file list nor a directory." + exit 1 +fi + +# --- Directories and File Names --- +BACKUP_STAGING_DIR="/tmp/backup/staging" +FINAL_BACKUP_DIR="/tmp/backup" +TAR_FILE="$FINAL_BACKUP_DIR/backup.tar" +TAR_GZ_FILE="$FINAL_BACKUP_DIR/backup.tar.gz" +CHECKSUM_FILE="$BACKUP_STAGING_DIR/checksum.txt" + +# --- Prepare Staging Area --- +rm -rf "$BACKUP_STAGING_DIR" 2>/dev/null +mkdir -p "$BACKUP_STAGING_DIR" || { echo "Error: Could not create staging directory '$BACKUP_STAGING_DIR'."; exit 1; } + +# --- Function: process_path --- +# Copies a file or directory into the staging area preserving its relative path. +process_path() { + filepath="$1" + [ -z "$filepath" ] && return + + # Remove trailing slashes (unless the path is just "/") + if [ "$filepath" != "/" ]; then + filepath=$(echo "$filepath" | sed 's:/*$::') + fi + + # Mark if the backup source is exactly /overlay/root + if [ "$filepath" = "/overlay/root" ]; then + found_overlay_root=1 + fi + + if [ -f "$filepath" ]; then + REL_PATH=$(echo "$filepath" | sed 's|^/||') + DEST_DIR="$BACKUP_STAGING_DIR/$(dirname "$REL_PATH")" + mkdir -p "$DEST_DIR" || { echo "Error: Could not create subdirectory for '$REL_PATH' in staging."; exit 1; } + cp "$filepath" "$DEST_DIR" || { echo "Error: Could not copy '$filepath' to staging area."; exit 1; } + elif [ -d "$filepath" ]; then + REL_PATH=$(echo "$filepath" | sed 's|^/||') + DEST_PARENT="$BACKUP_STAGING_DIR/$(dirname "$REL_PATH")" + mkdir -p "$DEST_PARENT" || { echo "Error: Could not create parent directory '$DEST_PARENT'."; exit 1; } + cp -r "$filepath" "$DEST_PARENT" || { echo "Error: Could not copy directory '$filepath' to staging area."; exit 1; } + else + echo "Error: File or directory '$filepath' does not exist." + exit 1 + fi +} + +# --- Process Input --- +if [ "$mode" = "list" ]; then + while IFS= read -r line; do + process_path "$line" + done < "$list_file" +elif [ "$mode" = "single" ]; then + process_path "$single_path" +fi + +# --- Remove Unwanted Subfolder --- +# If /overlay/root was among the sources, then in the staging area the files are under "overlay/root". +# Remove the extra "root" folder (i.e. /tmp/backup/staging/overlay/root/root) if it exists. +if [ $found_overlay_root -eq 1 ]; then + unwanted_dir="$BACKUP_STAGING_DIR/overlay/root/root" + if [ -d "$unwanted_dir" ]; then + rm -rf "$unwanted_dir" || { echo "Error: Could not remove unwanted folder '$unwanted_dir' from staging area."; exit 1; } + fi +fi + +# --- Generate Checksum File with Relative Paths --- +# We walk the staging directory and, for each file, remove the staging prefix. +# (This sed substitution technique is a common method for converting absolute paths to relative ones :contentReference[oaicite:0]{index=0}.) +> "$CHECKSUM_FILE" || { echo "Error: Cannot write to checksum file '$CHECKSUM_FILE'."; exit 1; } +find "$BACKUP_STAGING_DIR" -type f ! -name "$(basename "$CHECKSUM_FILE")" | while IFS= read -r file; do + # Remove the staging prefix to get the relative path. + rel=$(echo "$file" | sed "s|^$BACKUP_STAGING_DIR/||") + checksum=$(sha1sum "$file" | awk '{print $1}') + echo "$checksum $rel" +done > "$CHECKSUM_FILE" || { echo "Error: Failed to generate checksums."; exit 1; } + +# --- Create Tar Archive and Compress --- +mkdir -p "$FINAL_BACKUP_DIR" || { echo "Error: Could not create final backup directory '$FINAL_BACKUP_DIR'."; exit 1; } +tar -C "$BACKUP_STAGING_DIR" -cvf "$TAR_FILE" . || { echo "Error: Failed to create tar file from staging directory."; exit 1; } +gzip -f "$TAR_FILE" || { echo "Error: Failed to compress tar file."; exit 1; } + +echo "Backup archive successfully created at: $TAR_GZ_FILE" +exit 0 diff --git a/general/package/wifibroadcast-ext/files/generate_vtx_info.sh b/general/package/wifibroadcast-ext/files/generate_vtx_info.sh new file mode 100644 index 00000000..3fcd856e --- /dev/null +++ b/general/package/wifibroadcast-ext/files/generate_vtx_info.sh @@ -0,0 +1,235 @@ +#!/bin/sh +# +# build_vtx_info.sh – Build the /etc/vtx_info.yaml configuration file +# +# This script gathers system values, reads Wi‑Fi parameters (bw, ldpc, +# stbc, and TX power settings) from /etc/wifi_profiles.yaml based on wifi_profile, +# and determines the Wi‑Fi adapter (raw driver name) solely by scanning lsusb. +# +# If the wifi_profile is not found in /etc/wifi_profiles.yaml, it falls back +# to the "default" profile. +# +# It then uses the external tool "yaml-cli" (which supports -i, -s, -g, -d) +# to set keys in /etc/vtx_info.yaml. +# + +# Path to the YAML file to be built. +YAML_FILE="/etc/vtx_info.yaml" + +# Create the file if it does not exist. +[ ! -f "$YAML_FILE" ] && touch "$YAML_FILE" + +######################################## +# Fetch dynamic values from the system # +######################################## + +# 1. vtx_id: use the output of ipcinfo -i; default to "UNKNOWN" +vtx_id=$(ipcinfo -i 2>/dev/null) +[ -z "$vtx_id" ] && vtx_id="UNKNOWN" + +# 2. soc: read fw_printenv soc and extract the value; default to "ssc338q" +soc=$(fw_printenv soc 2>/dev/null | awk -F '=' '{print $2}') +[ -z "$soc" ] && soc="ssc338q" + +# 3. sensor: read fw_printenv sensor; default to "imx335" +sensor=$(fw_printenv sensor 2>/dev/null | awk -F '=' '{print $2}') +[ -z "$sensor" ] && sensor="imx335" + +# 4. build_option: extract from /etc/os-release; default "fpv" +build_option=$(grep "^BUILD_OPTION=" /etc/os-release 2>/dev/null | cut -d'=' -f2 | tr -d '"') +[ -z "$build_option" ] && build_option="fpv" + +# 5. wifi_profile: use fw_printenv wifi_profile; if not defined, set default. +wifi_profile_raw=$(fw_printenv wifi_profile 2>&1) +if echo "$wifi_profile_raw" | grep -qi "not defined"; then + wifi_profile="default" +else + wifi_profile=$(echo "$wifi_profile_raw" | awk -F '=' '{print $2}') +fi + +# 5. vtx_name: use fw_printenv vtx_name:; if not defined, set default. +vtx_name_raw=$(fw_printenv vtx_name 2>&1) +if echo "$vtx_name_raw" | grep -qi "not defined"; then + vtx_name="default" +else + vtx_name=$(echo "$vtx_name_raw" | awk -F '=' '{print $2}') +fi + +# 6. master_groundstation: use fw_printenv master_groundstation:; if not defined, set default. +master_groundstation_raw=$(fw_printenv master_groundstation 2>&1) +if echo "$master_groundstation_raw" | grep -qi "not defined"; then + master_groundstation="none" +else + master_groundstation=$(echo "$master_groundstation_raw" | awk -F '=' '{print $2}') +fi + + +######################################## +# Validate or set default wifi_profile # +######################################## + +# If no wifi_profile was provided OR if the profile is not found in /etc/wifi_profiles.yaml, +# then use the "default" profile. +if [ -f /etc/wifi_profiles.yaml ]; then + # Try to query a key (e.g. bw) from the given profile. + test_profile=$(yaml-cli -i /etc/wifi_profiles.yaml -g profiles."$wifi_profile".bw 2>/dev/null) + if [ -z "$wifi_profile" ] || [ "$test_profile" = "Node not found." ] || [ -z "$test_profile" ]; then + echo "Profile '$wifi_profile' not found in /etc/wifi_profiles.yaml, falling back to default." >&2 + wifi_profile="default" + fi +else + echo "/etc/wifi_profiles.yaml not found; proceeding without profile parameters." >&2 +fi + +######################################## +# Determine Wi‑Fi adapter via lsusb # +######################################## + +# Use lsusb to extract the raw driver name. +# The loop goes over unique USB IDs (field 6 from lsusb output) and +# sets wifi_adapter based on known card IDs. +wifi_adapter="none" +for card in $(lsusb | awk '{print $6}' | sort -u); do + case "$card" in + "0bda:8812" | "0bda:881a" | "0b05:17d2" | "2357:0101" | "2604:0012") + wifi_adapter="88XXau" + break + ;; + "0bda:a81a") + wifi_adapter="8812eu" + break + ;; + "0bda:f72b" | "0bda:b733") + wifi_adapter="8733bu" + break + ;; + esac +done + +######################################## +# Read Wi‑Fi parameters from profiles # +######################################## + +# Read bandwidth (bw), LDPC, and STBC from /etc/wifi_profiles.yaml using wifi_profile. +if [ -n "$wifi_profile" ] && [ -f /etc/wifi_profiles.yaml ]; then + wifi_bw=$(yaml-cli -i /etc/wifi_profiles.yaml -g profiles."$wifi_profile".bw 2>/dev/null) + wifi_ldpc_rx=$(yaml-cli -i /etc/wifi_profiles.yaml -g profiles."$wifi_profile".ldpc_rx 2>/dev/null) + wifi_ldpc_tx=$(yaml-cli -i /etc/wifi_profiles.yaml -g profiles."$wifi_profile".ldpc_tx 2>/dev/null) + wifi_stbc=$(yaml-cli -i /etc/wifi_profiles.yaml -g profiles."$wifi_profile".stbc 2>/dev/null) +fi + +# Fallback defaults if any parameter is missing. +[ -z "$wifi_bw" ] && wifi_bw="[20]" +[ -z "$wifi_ldpc_rx" ] && wifi_ldpc_rx="[0]" +[ -z "$wifi_ldpc_tx" ] && wifi_ldpc_tx="[0]" +[ -z "$wifi_stbc" ] && wifi_stbc="[0]" + +######################################## +# TX Power Settings from profiles # +######################################## + +# For a given wifi_profile, read TX power lists. +if [ -n "$wifi_profile" ] && [ -f /etc/wifi_profiles.yaml ]; then + tx_mcs0=$(yaml-cli -i /etc/wifi_profiles.yaml -g profiles."$wifi_profile".tx_power.mcs0 2>/dev/null) + tx_mcs1=$(yaml-cli -i /etc/wifi_profiles.yaml -g profiles."$wifi_profile".tx_power.mcs1 2>/dev/null) + tx_mcs2=$(yaml-cli -i /etc/wifi_profiles.yaml -g profiles."$wifi_profile".tx_power.mcs2 2>/dev/null) + tx_mcs3=$(yaml-cli -i /etc/wifi_profiles.yaml -g profiles."$wifi_profile".tx_power.mcs3 2>/dev/null) + tx_mcs4=$(yaml-cli -i /etc/wifi_profiles.yaml -g profiles."$wifi_profile".tx_power.mcs4 2>/dev/null) + tx_mcs5=$(yaml-cli -i /etc/wifi_profiles.yaml -g profiles."$wifi_profile".tx_power.mcs5 2>/dev/null) + tx_mcs6=$(yaml-cli -i /etc/wifi_profiles.yaml -g profiles."$wifi_profile".tx_power.mcs6 2>/dev/null) + tx_mcs7=$(yaml-cli -i /etc/wifi_profiles.yaml -g profiles."$wifi_profile".tx_power.mcs7 2>/dev/null) +fi + +# Fallback TX power defaults if any list is empty. +[ -z "$tx_mcs0" ] && tx_mcs0="[1,5,10,10,10,10,10,10,10,10,10]" +[ -z "$tx_mcs1" ] && tx_mcs1="[1,5,10,10,10,10,10,10,10,10,10]" +[ -z "$tx_mcs2" ] && tx_mcs2="[1,5,10,10,10,10,10,10,10,10,10]" +[ -z "$tx_mcs3" ] && tx_mcs3="[1,5,10,10,10,10,10,10,10,10,10]" +[ -z "$tx_mcs4" ] && tx_mcs4="[1,5,10,10,10,10,10,10,10,10,10]" +[ -z "$tx_mcs5" ] && tx_mcs5="[1,5,10,10,10,10,10,10,10,10,10]" +[ -z "$tx_mcs6" ] && tx_mcs6="[1,5,10,10,10,10,10,10,10,10,10]" +[ -z "$tx_mcs7" ] && tx_mcs7="[1,5,10,10,10,10,10,10,10,10,10]" + +######################################## +# Video Modes (Static Tables) # +######################################## + +if [ "$sensor" = "imx415" ]; then + mode_30fps="[3840x2160,2880x1620,1920x1080,1440x810,1280x720]" + mode_60fps="[2720x1528,1920x1080,1440x810,1360x764,1280x720]" + mode_90fps="[1920x1080,1600x900,1440x810,1280x720,960x540]" + mode_120fps="[1920x1080,1440x810,1280x720,1104x612,736x408]" +else + # Default to imx335 video modes. + mode_59fps="[1440x1080]" + mode_60fps="[2560x1440,1920x1080,1600x900,1440x810,1280x720]" + mode_90fps="[2208x1248,1920x1080,1440x810,1280x720,1104x624]" + mode_120fps="[1920x1080,1600x900,1440x810,1280x720,960x540]" +fi + +######################################## +# Bitrate List (Based on soc) # +######################################## + +if [ "$soc" = "ssc338q" ]; then + bitrate="[4096,6144,8192,10240,12288,14336,16384]" +elif [ "$soc" = "ssc30kq" ]; then + bitrate="[4096,6144,8192,10240,12288]" +else + bitrate="[4096,6144,8192,10240]" +fi + +######################################## +# IMU Sensor detection # +######################################## + +if i2cdetect -y -r 1 2>/dev/null | grep -q "68"; then + imu_sensor="BMI270" +else + imu_sensor="none" +fi + +######################################## +# Build the YAML file using yaml-cli # +######################################## + +# Top-level keys. +yaml-cli -i "$YAML_FILE" -s vtx_id "$vtx_id" +yaml-cli -i "$YAML_FILE" -s vtx_name $vtx_name +yaml-cli -i "$YAML_FILE" -s build_option "$build_option" +yaml-cli -i "$YAML_FILE" -s soc "$soc" +yaml-cli -i "$YAML_FILE" -s master_groundstation "$master_groundstation" + + + +# Wi‑Fi section. +yaml-cli -i "$YAML_FILE" -s wifi.wifi_adapter "$wifi_adapter" +yaml-cli -i "$YAML_FILE" -s wifi.wifi_profile "$wifi_profile" +yaml-cli -i "$YAML_FILE" -s wifi.bw "$wifi_bw" +yaml-cli -i "$YAML_FILE" -s wifi.ldpc_rx "$wifi_ldpc_rx" +yaml-cli -i "$YAML_FILE" -s wifi.ldpc_tx "$wifi_ldpc_tx" +yaml-cli -i "$YAML_FILE" -s wifi.stbc "$wifi_stbc" +# TX power settings (nested mapping). +yaml-cli -i "$YAML_FILE" -s wifi.tx_power.mcs0 "$tx_mcs0" +yaml-cli -i "$YAML_FILE" -s wifi.tx_power.mcs1 "$tx_mcs1" +yaml-cli -i "$YAML_FILE" -s wifi.tx_power.mcs2 "$tx_mcs2" +yaml-cli -i "$YAML_FILE" -s wifi.tx_power.mcs3 "$tx_mcs3" +yaml-cli -i "$YAML_FILE" -s wifi.tx_power.mcs4 "$tx_mcs4" +yaml-cli -i "$YAML_FILE" -s wifi.tx_power.mcs5 "$tx_mcs5" +yaml-cli -i "$YAML_FILE" -s wifi.tx_power.mcs6 "$tx_mcs6" +yaml-cli -i "$YAML_FILE" -s wifi.tx_power.mcs7 "$tx_mcs7" + +# Video section. +yaml-cli -i "$YAML_FILE" -s video.alink "[disabled,simple_alink,greg_alink]" +yaml-cli -i "$YAML_FILE" -s video.sensor "$sensor" +yaml-cli -i "$YAML_FILE" -s video.bitrate "$bitrate" +yaml-cli -i "$YAML_FILE" -s video.imu_sensor "$imu_sensor" +if [ "$sensor" = "imx415" ]; then + yaml-cli -i "$YAML_FILE" -s video.modes."30fps" "$mode_30fps" +fi +yaml-cli -i "$YAML_FILE" -s video.modes."60fps" "$mode_60fps" +yaml-cli -i "$YAML_FILE" -s video.modes."90fps" "$mode_90fps" +yaml-cli -i "$YAML_FILE" -s video.modes."120fps" "$mode_120fps" + +# Finished. +exit 0 diff --git a/general/package/wifibroadcast-ext/files/get_www_info.sh b/general/package/wifibroadcast-ext/files/get_www_info.sh new file mode 100644 index 00000000..a399176a --- /dev/null +++ b/general/package/wifibroadcast-ext/files/get_www_info.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +##Add code to print out temp etc for the web interface. +#soc temp, wifi temp, current wfb settings, current wifi tx_pwr +ipcinfo -t >> /tmp/vtx.log +ipcinfo -t > /tmp/www_info diff --git a/general/package/wifibroadcast-ext/files/provision_bind.sh b/general/package/wifibroadcast-ext/files/provision_bind.sh new file mode 100644 index 00000000..fc3f80c2 --- /dev/null +++ b/general/package/wifibroadcast-ext/files/provision_bind.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +# ---------------------------------------------------------- +# Exit code definitions (for readability/reference) +# ---------------------------------------------------------- +# #define EXIT_ERR 1 # (Fatal errors) +# #define EXIT_BIND 2 # (File received/bind operation) + +# ---------------------------------------------------------- +# Cleanup function +# ---------------------------------------------------------- +cleanup() { + echo "[CLEANUP] Stopping wifibroadcast, wfb_rx, wfb_tx, wfb_tun." + wifibroadcast stop + killall -q wfb_rx + killall -q wfb_tx + killall -q wfb_tun + sleep 1 + wifibroadcast start +} + +# ---------------------------------------------------------- +# Trap signals +# ---------------------------------------------------------- +# - INT covers Ctrl+C +# - EXIT covers *any* exit (normal or error) +trap cleanup INT EXIT + +# ---------------------------------------------------------- +# (Optional) Initial cleanup to stop anything already running +# ---------------------------------------------------------- +wifibroadcast stop +killall -q wfb_rx +killall -q wfb_tx +killall -q wfb_tun +sleep 1 + +# ---------------------------------------------------------- +# Setup commands +# ---------------------------------------------------------- +iw wlan0 set monitor none +iw wlan0 set channel 165 HT20 +iw reg set US +sleep 1 + +echo "- Starting bind process..." + +if ! [ -f /etc/bind.key ] +then + echo "OoLVgEYyFofg9zdhfYPks8/L8fqWaF9Jk8aEnynFPsXNqhSpRCMbVKBFP4fCEOv5DGcbXmUHV5eSykAbFB70ew==" \ + | base64 -d > /etc/bind.key +fi + +echo "- Starting wfb_rx, wfb_tx, wfb_tun" +wfb_rx -p 255 -u 5800 -K /etc/bind.key -i 10531917 wlan0 &> /dev/null & +wfb_tx -p 127 -u 5801 -K /etc/bind.key -M 1 -S 0 -L 0 \ + -k 1 -n 2 -i 10531917 wlan0 &> /dev/null & +wfb_tun -a 10.5.99.2/24 & + +# Sleep needed for wfb_tun to initialize +sleep 8 + diff --git a/general/package/wifibroadcast-ext/files/provision_listen.sh b/general/package/wifibroadcast-ext/files/provision_listen.sh new file mode 100644 index 00000000..8de41762 --- /dev/null +++ b/general/package/wifibroadcast-ext/files/provision_listen.sh @@ -0,0 +1,171 @@ +#!/bin/sh +# +# Enhanced script that: +# - Runs drone_provisioner in an infinite loop +# - Traps Ctrl+C (SIGINT) and other signals +# - Acts based on exit codes from drone_provisioner, including 5 for BACKUP +# - Always runs cleanup steps on exit + +# ---------------------------------------------------------- +# Cleanup function (called on exit or signal) +# ---------------------------------------------------------- +cleanup() { + echo "[CLEANUP] Removing temporary directories..." + rm -rf /tmp/flash + rm -rf /tmp/bind + rm -rf /tmp/backup +} + +# ---------------------------------------------------------- +# Trap signals for graceful shutdown +# ---------------------------------------------------------- +trap "echo 'Received SIGINT (Ctrl+C). Exiting gracefully...'; exit 130" INT +trap "echo 'Received SIGTERM. Exiting gracefully...'; exit 143" TERM +# You can add more traps for other signals if desired: +# trap "echo 'Received SIGHUP. Exiting gracefully...'; exit 129" HUP + +# This trap ensures cleanup is *always* done upon exit (any exit). +trap cleanup EXIT + +# ---------------------------------------------------------- +# Main loop +# ---------------------------------------------------------- +while true; do + + # -------------------------------------------------------- + # Run drone_provisioner and capture its exit code + # -------------------------------------------------------- + drone_provisioner --ip 0.0.0.0 --listen-duration 99999 + EXIT_CODE=$? + + echo "drone_provisioner exited with code $EXIT_CODE." + + # -------------------------------------------------------- + # Handle exit codes + # -------------------------------------------------------- + case $EXIT_CODE in + 0) + echo "Listen period ended. Exiting with code 0." + exit 0 + ;; + + 1) + echo "Fatal errors. Exiting with code 1." + exit 1 + ;; + + 2) + echo "File received and saved successfully (BIND). Continuing execution..." + + cd /tmp/bind || exit 2 + + # Decompress the .tar.gz + gunzip bind.tar.gz + + # Optional: validate that bind.tar now exists + if [ ! -f bind.tar ]; then + echo "ERR: bind.tar not found after gunzip." + exit 2 + fi + + # Extract the tar + tar x -f bind.tar + + # Detect the top-level directory name (assuming exactly one) + extracted_dir="$(tar -tf bind.tar | head -n1 | cut -d/ -f1)" + + # Check that the directory exists + if [ -n "$extracted_dir" ] && [ -d "$extracted_dir" ]; then + cd "$extracted_dir" || exit 2 + echo "Changed directory to: $extracted_dir" + else + echo "ERR: Could not identify a single top-level directory from bind.tar" + exit 2 + fi + + # Validate checksums + if ! [ -f checksum.txt ] || ! sha1sum -c checksum.txt + then + echo "ERR: Checksum failed." + exit 2 + fi + + # ----------------------------------------------------- + # Copy system files, as needed + # ----------------------------------------------------- + if [ -d overlay/ ]; then + cp -r overlay/root/* / + echo "Overlay files copied to root." + fi + + if [ -f etc/wfb.yaml ]; then + cp etc/wfb.yaml /etc/wfb.yaml + echo "Copy success: /etc/wfb.yaml" + fi + + if [ -d etc/sensors/ ]; then + cp etc/sensors/* /etc/sensors/ + echo "Copy success: Sensor bins" + fi + + if [ -f etc/majestic.yaml ]; then + cp etc/majestic.yaml /etc/majestic.yaml + /etc/init.d/S95majestic restart + echo "Copy & restart success: /etc/majestic.yaml" + fi + + if [ -f lib/modules/4.9.84/sigmastar/sensor_imx335_mipi.ko ]; then + cp lib/modules/4.9.84/sigmastar/sensor_imx335_mipi.ko \ + /lib/modules/4.9.84/sigmastar/sensor_imx335_mipi.ko + echo "Copy success (restart required): sensor_imx335_mipi.ko" + fi + + #Set various settings + wifi_profile_name=$(yaml-cli -i /etc/wfb.yaml -g .wireless.wifi_module) + fw_setenv wifi_profile ${wifi_profile_name:-default} + + vtx_name=$(yaml-cli -i /etc/wfb.yaml -g .wireless.vtx_name) + fw_setenv vtx_name ${vtx_name:-default} + + #Usage: /usr/bin/set_bitrate.sh [max_mcs] [--cap ] [--max_bw <20|40>] + set_bitrate.sh $(yaml-cli -i /etc/majestic.yaml -g .video0.bitrate) 5 --max_bw $(yaml-cli -i /etc/wfb.yaml -g .wireless.max_bw) + + #if passphrase is set, generate /etc/drone.key + pass="$(yaml-cli -i /etc/wfb.conf -g .wireless.passhrase)" && [ -n "$pass" ] && keygen "$pass" + + if [ -f ./custom_script.sh ]; then + chmod +x ./custom_script.sh + ./custom_script.sh + echo "Copy success and executed: custom_script.sh" + fi + + # Cleanup BIND dir before continuing the loop + rm -rf /tmp/bind + + continue + ;; + + 3) + echo "UNBIND command received. Executing firstboot..." + firstboot + exit 3 + ;; + + 4) + echo "FLASH command received. Exiting with code 4." + # (Insert your FLASH code here, currently not implemented) + exit 4 + ;; + + 5) + echo "Backup completed. Continuing execution..." + continue + ;; + + *) + echo "Unexpected error occurred. Exiting with code $EXIT_CODE." + exit "$EXIT_CODE" + ;; + esac + +done diff --git a/general/package/wifibroadcast-ext/files/set_benchtesting.sh b/general/package/wifibroadcast-ext/files/set_benchtesting.sh new file mode 100644 index 00000000..53d69a3e --- /dev/null +++ b/general/package/wifibroadcast-ext/files/set_benchtesting.sh @@ -0,0 +1,4 @@ +#!/bin/sh +echo "Set benchtest parameters" +#Decrease TX power to lowest allowed +set_alink_tx_pwr.sh 0 diff --git a/general/package/wifibroadcast-ext/files/set_bitrate.sh b/general/package/wifibroadcast-ext/files/set_bitrate.sh new file mode 100644 index 00000000..0b2ed107 --- /dev/null +++ b/general/package/wifibroadcast-ext/files/set_bitrate.sh @@ -0,0 +1,192 @@ +#!/bin/sh +# +# set_bitrate.sh +# +# Usage: +# set_bitrate.sh [max_mcs] [--cap ] [--max_bw <20|40>] +# +# This script reads FEC settings from /etc/wfb.yaml and allowed bandwidths +# from /etc/vtx_info.yaml, then calls bitrate_calculator.sh (with the given +# target, FEC ratio, max_mcs, and maximum bandwidth limit) to compute the best +# settings (MCS, BW, GI). +# +# The FEC ratio is constructed by swapping the YAML values so that a file with: +# +# broadcast: +# fec_n: 12 +# fec_k: 8 +# +# produces a ratio "8/12" as expected by bitrate_calculator.sh. +# +# The output from bitrate_calculator.sh is expected in the format: +# ::: +# +# Then the script updates the YAML configuration files and sets the radio +# settings in the running session. +# +# Note: If the candidate BW is 40, and the system’s allowed maximum bandwidth +# (read from /etc/vtx_info.yaml) is 40, then wireless.mode is forced to "HT40+". +# + +# --- Parse arguments --- +if [ "$#" -lt 1 ]; then + echo "Usage: $0 [max_mcs] [--cap ] [--max_bw <20|40>]" + exit 1 +fi + +TARGET="$1" +shift + +# Default max_mcs is 5. +max_mcs=5 +if [ "$#" -gt 0 ]; then + case "$1" in + --*) ;; # if next arg starts with -- + *) max_mcs="$1"; shift;; + esac +fi + +# Default cap is 20000 kbps unless overridden. +CAP=20000 +# Default max_bw for candidate search is 40 (both 20 and 40 will be searched). +MAX_BW=40 + +while [ "$#" -gt 0 ]; do + case "$1" in + --cap) + shift + if [ -z "$1" ]; then + echo "Error: --cap requires a value." + exit 1 + fi + CAP="$1" + shift + ;; + --max_bw) + shift + if [ -z "$1" ]; then + echo "Error: --max_bw requires a value (20 or 40)." + exit 1 + fi + if [ "$1" != "20" ] && [ "$1" != "40" ]; then + echo "Error: --max_bw must be either 20 or 40." + exit 1 + fi + MAX_BW="$1" + shift + ;; + *) + echo "Unknown argument: $1" + exit 1 + ;; + esac +done + +# --- Read FEC settings from /etc/wfb.yaml --- +# Example YAML: +# broadcast: +# fec_n: 12 +# fec_k: 8 +fec_n=$(yaml-cli -i /etc/wfb.yaml -g .broadcast.fec_n) +fec_k=$(yaml-cli -i /etc/wfb.yaml -g .broadcast.fec_k) +if [ -z "$fec_n" ] || [ -z "$fec_k" ]; then + echo "Error: Could not read FEC settings from /etc/wfb.yaml." + exit 1 +fi +# Swap the order so that a YAML with fec_n:12 and fec_k:8 produces "8/12". +fec_ratio="${fec_k}/${fec_n}" + +# --- Read allowed bandwidths from /etc/vtx_info.yaml --- +# Expected format: [5,10,20,40] +bw_array=$(yaml-cli -i /etc/vtx_info.yaml -g .wifi.bw) +max_bw_allowed=$(echo "$bw_array" | sed 's/[][]//g' | awk -F, '{print $NF}' | tr -d ' ') +if [ -z "$max_bw_allowed" ]; then + echo "Error: Could not read allowed bandwidths from /etc/vtx_info.yaml." + exit 1 +fi +# Our bitrate_calculator.sh supports 20 and 40 MHz. +if [ "$max_bw_allowed" -ge 40 ]; then + ALLOWED_BW="40" +else + ALLOWED_BW="20" +fi + +# --- Call bitrate_calculator.sh --- +# We now pass the optional --max_bw parameter. +RESULT=$(bitrate_calculator.sh "$TARGET" "$fec_ratio" "$max_mcs" --cap "$CAP" --gi long --max_bw "$MAX_BW") +#echo ""$TARGET" "$fec_ratio" "$max_mcs" --cap "$CAP" --gi long --max_bw "$MAX_BW" and exit code $?" +if [ $? -ne 0 ]; then + echo "Error: bitrate_calculator.sh failed. Setting fallback, please retry with a lower bitrate." + #Fallback + set_bitrate.sh 2800 0 --max_bw 20 + exit 1 +fi + +# RESULT is expected in the format: ::: +candidate_mcs=$(echo "$RESULT" | cut -d: -f1) +candidate_bw=$(echo "$RESULT" | cut -d: -f2) +candidate_gi=$(echo "$RESULT" | cut -d: -f3) +candidate_fec=$(echo "$RESULT" | cut -d: -f4) + +# --- Adjust candidate if its bandwidth exceeds allowed maximum --- +if [ "$candidate_bw" -gt "$max_bw_allowed" ]; then + echo "Warning: Candidate BW ${candidate_bw} MHz exceeds allowed maximum (${max_bw_allowed} MHz)." + candidate_bw="$max_bw_allowed" +fi + +echo "Setting new configuration:" +echo " Target bitrate: ${TARGET} kbps" +echo " Selected settings: MCS=${candidate_mcs}, BW=${candidate_bw} MHz, GI=${candidate_gi}, FEC=${candidate_fec}" +echo " Bitrate cap: ${CAP} kbps" +echo " Allowed max BW: ${max_bw_allowed} MHz" + +# --- Update YAML configuration --- +# Update /etc/wfb.yaml: +yaml-cli -i /etc/wfb.yaml -s .broadcast.mcs_index "$candidate_mcs" > /dev/null +yaml-cli -i /etc/wfb.yaml -s .broadcast.fec_k "$fec_k" > /dev/null +yaml-cli -i /etc/wfb.yaml -s .broadcast.fec_n "$fec_n" > /dev/null +yaml-cli -i /etc/wfb.yaml -s .broadcast.guard_interval "$candidate_gi" > /dev/null + +# Determine wireless mode: +# If the allowed maximum BW is 40, then force mode "HT40+" +if [ "$max_bw_allowed" -eq 40 ]; then + mode="HT40+" +else + mode="HT${candidate_bw}" +fi + +yaml-cli -i /etc/wfb.yaml -s .wireless.mode "$mode" > /dev/null +yaml-cli -i /etc/wfb.yaml -s .broadcast.bw "$candidate_bw" > /dev/null +yaml-cli -i /etc/majestic.yaml -s .video0.bitrate "$TARGET" > /dev/null + +set +e +/etc/init.d/S98wifibroadcast stop +ret=$? + +if [ $ret -ne 0 ]; then + echo "wifibroadcast stop failed (exit code $ret), sleeping 5 seconds before retrying..." + sleep 5 + /etc/init.d/S98wifibroadcast stop +fi +set -e + +curl -s localhost/api/v1/set?video0.bitrate=$TARGET 2> /dev/null + +if ! pgrep -f majestic >/dev/null 2>&1; then + echo "Majestic is not running. Starting majestic..." + /etc/init.d/S95majestic start +else + echo "Majestic is running." +fi + +set +e +/etc/init.d/S98wifibroadcast start +ret=$? +if [ $ret -ne 0 ]; then + echo "wifibroadcast start failed (exit code $ret), sleeping 5 seconds before retrying..." + sleep 5 + /etc/init.d/S98wifibroadcast start +fi +set -e + +echo "Bitrate settings applied successfully." diff --git a/general/package/wifibroadcast-ext/files/set_live_bitrate.sh b/general/package/wifibroadcast-ext/files/set_live_bitrate.sh new file mode 100644 index 00000000..2a44472e --- /dev/null +++ b/general/package/wifibroadcast-ext/files/set_live_bitrate.sh @@ -0,0 +1,186 @@ +#!/bin/sh +# +# set_bitrate.sh +# +# Usage: +# set_bitrate.sh [max_mcs] [--cap ] [--max_bw <20|40>] [--direction ] [--tx_pwr ] +# +# (Additional usage info…) +# + +# --- Parse arguments --- +if [ "$#" -lt 1 ]; then + echo "Usage: $0 [max_mcs] [--cap ] [--max_bw <20|40>] [--direction ] [--tx_pwr ]" + exit 1 +fi + +TARGET="$1" +shift + +# Default max_mcs is 5. +max_mcs=5 +if [ "$#" -gt 0 ]; then + case "$1" in + --*) ;; # if next arg starts with -- + *) max_mcs="$1"; shift;; + esac +fi + +# Default cap is 20000 kbps unless overridden. +CAP=20000 +# Default max_bw for candidate search is 40 (both 20 and 40 will be searched). +MAX_BW=40 + +# Default direction. If not provided, we assume "initial" +DIRECTION="initial" + +# Default TX_PWR is set to 5 unless overridden. +TX_PWR=5 + +while [ "$#" -gt 0 ]; do + case "$1" in + --cap) + shift + if [ -z "$1" ]; then + echo "Error: --cap requires a value." + exit 1 + fi + CAP="$1" + shift + ;; + --max_bw) + shift + if [ -z "$1" ]; then + echo "Error: --max_bw requires a value (20 or 40)." + exit 1 + fi + if [ "$1" != "20" ] && [ "$1" != "40" ]; then + echo "Error: --max_bw must be either 20 or 40." + exit 1 + fi + MAX_BW="$1" + shift + ;; + --direction) + shift + if [ -z "$1" ]; then + echo "Error: --direction requires a value (initial, increased, decreased, or unchanged)." + exit 1 + fi + case "$1" in + initial|increased|decreased|unchanged) + DIRECTION="$1" + ;; + *) + echo "Error: Unknown direction: $1. Valid options are: initial, increased, decreased, or unchanged." + exit 1 + ;; + esac + shift + ;; + --tx_pwr) + shift + if [ -z "$1" ]; then + echo "Error: --tx_pwr requires a value." + exit 1 + fi + TX_PWR="$1" + shift + ;; + *) + echo "Unknown argument: $1" + exit 1 + ;; + esac +done + +# --- Read FEC settings from /etc/wfb.yaml --- +fec_n=$(yaml-cli -i /etc/wfb.yaml -g .broadcast.fec_n) +fec_k=$(yaml-cli -i /etc/wfb.yaml -g .broadcast.fec_k) +if [ -z "$fec_n" ] || [ -z "$fec_k" ]; then + echo "Error: Could not read FEC settings from /etc/wfb.yaml." + exit 1 +fi +fec_ratio="${fec_k}/${fec_n}" + +# --- Read allowed bandwidths from /etc/vtx_info.yaml --- +bw_array=$(yaml-cli -i /etc/vtx_info.yaml -g .wifi.bw) +max_bw_allowed=$(echo "$bw_array" | sed 's/[][]//g' | awk -F, '{print $NF}' | tr -d ' ') +if [ -z "$max_bw_allowed" ]; then + echo "Error: Could not read allowed bandwidths from /etc/vtx_info.yaml." + exit 1 +fi +if [ "$max_bw_allowed" -ge 40 ]; then + ALLOWED_BW="40" +else + ALLOWED_BW="20" +fi + +# --- Call bitrate_calculator.sh --- +RESULT=$(bitrate_calculator.sh "$TARGET" "$fec_ratio" "$max_mcs" --cap "$CAP" --gi long --max_bw "$MAX_BW") +if [ $? -ne 0 ]; then + echo "Error: bitrate_calculator.sh failed. Setting fallback, please retry with a lower bitrate." + set_bitrate.sh 3000 0 --max_bw 20 + exit 1 +fi + +# RESULT is expected in the format: ::: +candidate_mcs=$(echo "$RESULT" | cut -d: -f1) +candidate_bw=$(echo "$RESULT" | cut -d: -f2) +candidate_gi=$(echo "$RESULT" | cut -d: -f3) +candidate_fec=$(echo "$RESULT" | cut -d: -f4) + +# --- Adjust candidate if its bandwidth exceeds allowed maximum --- +if [ "$candidate_bw" -gt "$max_bw_allowed" ]; then + echo "Warning: Candidate BW ${candidate_bw} MHz exceeds allowed maximum (${max_bw_allowed} MHz)." + candidate_bw="$max_bw_allowed" +fi + +echo "Setting new configuration:" +echo " Target bitrate: ${TARGET} kbps" +echo " Selected settings: MCS=${candidate_mcs}, BW=${candidate_bw} MHz, GI=${candidate_gi}, FEC=${candidate_fec}" +echo " Bitrate cap: ${CAP} kbps" +echo " Allowed max BW: ${max_bw_allowed} MHz" +echo " Update direction: ${DIRECTION}" +echo " Transmitter Power: ${TX_PWR}" + + +# --- Execute update blocks based on --direction --- +if [ "$DIRECTION" = "decreased" ]; then + # If "decreased", update Majestic Online first + ## --- Update Majestic Online --- + curl -s localhost/api/v1/set?video0.bitrate=$TARGET 2> /dev/null + sleep 1 + + + # Then update WFB_NG Online + # --- Update WFB_NG Online --- + wfb_tx_cmd 8000 set_radio -B ${candidate_bw} -G ${candidate_gi} \ + -S $(yaml-cli -i /etc/wfb.yaml -g .broadcast.stbc) \ + -L $(yaml-cli -i /etc/wfb.yaml -g .broadcast.ldpc_tx) \ + -M ${candidate_mcs} + wfb_tx_cmd 8000 set_fec -k ${fec_k} -n ${fec_n} + + # --- Set transmitter power --- + echo "Setting transmitter power to ${TX_PWR}." + set_alink_tx_pwr.sh "$TX_PWR" --mcs $candidate_mcs + +else + + # --- Set transmitter power --- + echo "Setting transmitter power to ${TX_PWR}." + set_alink_tx_pwr.sh "$TX_PWR" --mcs $candidate_mcs + + # Otherwise, update WFB_NG Online first + # --- Update WFB_NG Online --- + wfb_tx_cmd 8000 set_radio -B ${candidate_bw} -G ${candidate_gi} \ + -S $(yaml-cli -i /etc/wfb.yaml -g .broadcast.stbc) \ + -L $(yaml-cli -i /etc/wfb.yaml -g .broadcast.ldpc_tx) \ + -M ${candidate_mcs} + wfb_tx_cmd 8000 set_fec -k ${fec_k} -n ${fec_n} + sleep 0.2 + ## --- Update Majestic Online --- + curl -s localhost/api/v1/set?video0.bitrate=$TARGET 2> /dev/null +fi + +echo "Bitrate settings applied successfully." diff --git a/general/package/wifibroadcast-ext/files/set_live_tx_pwr.sh b/general/package/wifibroadcast-ext/files/set_live_tx_pwr.sh new file mode 100644 index 00000000..d45344ba --- /dev/null +++ b/general/package/wifibroadcast-ext/files/set_live_tx_pwr.sh @@ -0,0 +1,130 @@ +#!/bin/sh +# +# Usage: set_tx_power.sh [direction] [--mcs <0-7>] +# +# This script: +# 1. Checks if TX power throttling is enabled. +# 2. Retrieves the current mcs_index from wfb_tx_cmd (or uses provided --mcs value). +# 3. Uses yaml-cli to get the TX power table for that mcs_index. +# 4. Interpolates the provided value (0–10) to select one of the table entries. +# 5. Checks the wifi adapter type and, if it is "88XXau", prepends a negative sign to the TX power. +# 6. Sets the TX power via iw. +# + +# --- Argument Parsing --- +TX_INPUT="" +DIRECTION="" +MCS_OVERRIDE="" + +while [ "$#" -gt 0 ]; do + case "$1" in + --mcs) + shift + if [ "$#" -gt 0 ]; then + MCS_OVERRIDE="$1" + else + echo "Error: --mcs requires a value." + exit 1 + fi + ;; + *) + if [ -z "$TX_INPUT" ]; then + TX_INPUT="$1" + elif [ -z "$DIRECTION" ]; then + DIRECTION="$1" + else + echo "Unknown argument: $1" + exit 1 + fi + ;; + esac + shift +done + +if [ -z "$TX_INPUT" ]; then + echo "Usage: $0 [direction] [--mcs <0-7>]" + exit 1 +fi + +if [ -z "$DIRECTION" ]; then + DIRECTION="initiated" +fi + +# --- Throttling Check --- +# For now, throttling is set to "disabled". (Update this logic as needed.) +TEMP_THROTTLE="disabled" +if [ "$TEMP_THROTTLE" = "enabled" ]; then + echo "TX power throttling is enabled. Aborting TX power change." + exit 0 +fi + +# --- Determine mcs_index --- +if [ -n "$MCS_OVERRIDE" ]; then + # Sanity check: ensure MCS_OVERRIDE is between 0 and 7, else default to 7. + if [ "$MCS_OVERRIDE" -ge 0 ] 2>/dev/null && [ "$MCS_OVERRIDE" -le 7 ] 2>/dev/null; then + MCS_INDEX="$MCS_OVERRIDE" + else + MCS_INDEX=7 + fi +else + # --- Get current mcs_index from wfb_tx_cmd --- + MCS_INDEX=$(wfb_tx_cmd 8000 get_radio | grep '^mcs_index=' | cut -d '=' -f2) + if [ -z "$MCS_INDEX" ]; then + echo "Error: Unable to retrieve mcs_index." + exit 1 + fi +fi + +# --- Retrieve TX power table from YAML --- +# Expected output: e.g., mcs1: [1,5,10,15,20,25,30,35,40,45,50] +TABLE_OUTPUT=$(yaml-cli -i /etc/vtx_info.yaml -g ".wifi.tx_power.mcs${MCS_INDEX}") +# Remove the "mcsX:" prefix and the surrounding brackets. +POWER_LIST=$(echo "$TABLE_OUTPUT" | sed -e "s/^mcs${MCS_INDEX}:[[:space:]]*//" -e 's/[][]//g') + +# --- Parse list into individual values --- +OLD_IFS="$IFS" +IFS=, +set -- $POWER_LIST +IFS="$OLD_IFS" +NUM_VALUES=$# + +# --- Interpolate to select TX power --- +# Map TX_INPUT (0–10) to an index in the list. +DESIRED_INDEX=$(awk -v inVal="$TX_INPUT" -v n="$NUM_VALUES" 'BEGIN { print int(inVal/10*(n-1)+0.5) }') +ARRAY_INDEX=$((DESIRED_INDEX + 1)) + +# Retrieve the selected TX power value. +eval "MCS_TX_PWR=\${$ARRAY_INDEX}" +if [ -z "$MCS_TX_PWR" ]; then + echo "Error: Could not determine TX power from table." + exit 1 +fi + +# --- Parameters for TX power multiplier --- +DEFAULT_MULT=50 # Used for non-88XXau adapters +ALT_MULT=100 # Used for 88XXau adapter (TX power will be negative) + +# --- Check wifi adapter type --- +WIFI_ADAPTER=$(yaml-cli -i /etc/vtx_info.yaml -g .wifi.wifi_adapter) +if [ "$WIFI_ADAPTER" = "88XXau" ]; then + MULTIPLIER=$ALT_MULT + # Force MCS_TX_PWR to be negative if not already. + case "$MCS_TX_PWR" in + -*) + # Already negative. + ;; + *) + MCS_TX_PWR="-${MCS_TX_PWR}" + ;; + esac +else + MULTIPLIER=$DEFAULT_MULT +fi + +# --- Set the TX power --- +# Multiplication in shell arithmetic handles negatives correctly. +TXPOWER=$(( MCS_TX_PWR * MULTIPLIER )) +echo "Setting TX power to $MCS_TX_PWR ($TXPOWER) (mcs${MCS_INDEX}, adapter: $WIFI_ADAPTER, direction: $DIRECTION)" +iw wlan0 set txpower fixed "$TXPOWER" + +exit 0 diff --git a/general/package/wifibroadcast-ext/files/temperature_check.sh b/general/package/wifibroadcast-ext/files/temperature_check.sh new file mode 100644 index 00000000..ec1b7d73 --- /dev/null +++ b/general/package/wifibroadcast-ext/files/temperature_check.sh @@ -0,0 +1,148 @@ +#!/bin/sh +# Threshold definitions: +WARNING1_THRESHOLD=80 # First warning threshold +WARNING2_THRESHOLD=90 # Second warning threshold (warning: VTX will soon throttle) +THROTTLE_THRESHOLD=100 # Throttle Level 1 threshold (100–104°C) +THROTTLE2_THRESHOLD=105 # Throttle Level 2 threshold (105–109°C) +REBOOT_THRESHOLD=110 # Reboot threshold (>=110°C) + +# Define persistent state flag: +# 0 = Normal (<80°C) +# 1 = Warning level 1 (80–89°C) +# 2 = Warning level 2 (90–99°C) +# 3 = Throttle Level 1 (100–104°C) +# 4 = Throttle Level 2 (105–109°C) +# 5 = Reboot (>=110°C) +current_state=0 +# Record the timestamp when the current state started +state_start_time=$(date +%s) + +while true; do + # --- Get VTX Temperature --- + # Example output from ipcinfo --temp: "39.00" + vtx_temp=$(ipcinfo --temp) + vtx_int=$(echo "$vtx_temp" | cut -d. -f1) + + # --- Get Adapter Temperature --- + wifi_adapter=$(yaml-cli -i /etc/vtx_info.yaml -g .wifi.wifi_adapter) + adapter_temp=0 + if [ "$wifi_adapter" = "8733bu" ]; then + # Expected file format: "rf_path: 0, thermal_value: 37, offset: 45, temperature: 20" + adapter_temp=$(grep -o 'temperature: [0-9]*' /proc/net/rtl8733bu/wlan0/thermal_state | awk '{print $2}') + elif [ "$wifi_adapter" = "88XXau" ]; then + echo "Adapter 88XXau temperature extraction not implemented yet." + adapter_temp=0 + elif [ "$wifi_adapter" = "8812eu" ]; then + echo "Adapter 8812eu temperature extraction not implemented yet." + adapter_temp=0 + else + echo "Unknown adapter type: $wifi_adapter" + fi + + # Fallback if adapter_temp is empty + if [ -z "$adapter_temp" ]; then + adapter_temp=0 + fi + + echo "VTX temperature: ${vtx_temp}°C, Adapter temperature: ${adapter_temp}°C" + + # --- Determine the Highest Temperature --- + max_temp=$vtx_int + if [ "$adapter_temp" -gt "$max_temp" ]; then + max_temp=$adapter_temp + fi + + # --- Map max_temp to a state --- + if [ "$max_temp" -lt "$WARNING1_THRESHOLD" ]; then + new_state=0 + elif [ "$max_temp" -lt "$WARNING2_THRESHOLD" ]; then + new_state=1 + elif [ "$max_temp" -lt "$THROTTLE_THRESHOLD" ]; then + new_state=2 + elif [ "$max_temp" -lt "$THROTTLE2_THRESHOLD" ]; then + new_state=3 + elif [ "$max_temp" -lt "$REBOOT_THRESHOLD" ]; then + new_state=4 + else + new_state=5 + fi + + # --- Check for state change and take actions accordingly --- + if [ "$new_state" -ne "$current_state" ]; then + # Save previous state before updating + old_state=$current_state + current_state=$new_state + state_start_time=$(date +%s) + + if [ "$current_state" -eq 0 ]; then + # Recovery: only run if coming from a throttling state (3 or 4) + if [ "$old_state" -eq 3 ] || [ "$old_state" -eq 4 ]; then + echo "Recovered from throttling state. Running recovery commands..." + /etc/init.d/S95majestic stop + wifibroadcast stop + wifibroadcast start + /etc/init.d/S95majestic start + fi + echo "Normal: VTX Temp:&T WifiTemp:&W" + + elif [ "$current_state" -eq 1 ]; then + echo "Warning: High temperature detected. VTX Temp:&T WifiTemp:&W" > /tmp/msposd.msg + + elif [ "$current_state" -eq 2 ]; then + echo "Warning: High temperature detected. VTX will soon thermal throttle...VTX Temp:&T WifiTemp:&W" > /tmp/msposd.msg + + elif [ "$current_state" -eq 3 ]; then + # Throttle Level 1 commands only if moving upward (old_state < new_state) + if [ "$current_state" -gt "$old_state" ]; then + if [ "$wifi_adapter" = "88XXau" ]; then + txpower_value="-500" + else + txpower_value="500" + fi + iw dev wlan0 set txpower fixed $txpower_value + echo setfps 0 30 > /proc/mi_modules/mi_sensor/mi_sensor0 + fi + echo "Throttling VTX (level 1). Reboot imminent, return to home..VTX Temp:&T WifiTemp:&W" > /tmp/msposd.msg + + elif [ "$current_state" -eq 4 ]; then + # Throttle Level 2 commands only if moving upward (old_state < new_state) + if [ "$current_state" -gt "$old_state" ]; then + echo "Severe throttling VTX (level 2). Video will stop in 10sec, return to home..VTX Temp:&T WifiTemp:&W" > /tmp/msposd.msg + sleep 10 + /etc/init.d/S95majestic stop + fi + + + elif [ "$current_state" -eq 5 ]; then + echo "VTX will reboot due to thermal state...VTX Temp:&T WifiTemp:&W. Rebooting in 5 seconds..." + sleep 5 + reboot + fi + + else + # State remains the same; update the message with elapsed time. + elapsed=$(($(date +%s) - state_start_time)) + case $current_state in + 0) + echo "Normal: VTX Temp:&T WifiTemp:&W (State for ${elapsed} seconds)" > /tmp/msposd.msg + ;; + 1) + echo "Warning: High temperature detected. VTX Temp:&T WifiTemp:&W (State for ${elapsed} seconds)" > /tmp/msposd.msg + ;; + 2) + echo "Warning: High temperature detected. VTX will soon thermal throttle...VTX Temp:&T WifiTemp:&W (State for ${elapsed} seconds)" > /tmp/msposd.msg + ;; + 3) + echo "Throttling VTX (level 1). Reboot imminent, return to home..VTX Temp:&T WifiTemp:&W (State for ${elapsed} seconds)" > /tmp/msposd.msg + ;; + 4) + echo "Severe throttling VTX (level 2). Reboot imminent, return to home..VTX Temp:&T WifiTemp:&W (State for ${elapsed} seconds)" > /tmp/msposd.msg + ;; + 5) + # Reboot state should not linger. + ;; + esac + fi + + sleep 5 +done diff --git a/general/package/wifibroadcast-ext/files/wifibroadcast b/general/package/wifibroadcast-ext/files/wifibroadcast new file mode 100644 index 00000000..8a736ceb --- /dev/null +++ b/general/package/wifibroadcast-ext/files/wifibroadcast @@ -0,0 +1,207 @@ +#!/bin/sh +wfb_key=/etc/drone.key +wfb_dev=wlan0 + +wfb_yaml() { + if [ -e "$1" ]; then + local CONFIG_FILE="$1" + + wireless_keys="txpower channel wifi_mode passphrase video_key tunnel_key bind_key link_id" + for key in $wireless_keys; do + val="$(yaml-cli -i "$CONFIG_FILE" -g ".wireless.$key" 2>/dev/null)" + if [ -n "$val" ]; then + varname="WIRELESS_$(echo "$key" | tr '[:lower:]' '[:upper:]')" + eval "$varname='$val'" + # echo "$varname=$val" + fi + done + + broadcast_keys="mcs_index fec_k fec_n force_vht ldpc stbc guard_interval bw" + for key in $broadcast_keys; do + val="$(yaml-cli -i "$CONFIG_FILE" -g ".broadcast.$key" 2>/dev/null)" + if [ -n "$val" ]; then + varname="BROADCAST_$(echo "$key" | tr '[:lower:]' '[:upper:]')" + eval "$varname='$val'" + # echo "$varname=$val" + fi + done + + # Check for broadcast redundancy setting. + # If .wireless.broadcast_redundancy returns "auto", then run detect_redundancy.sh. + # Its output should be two numbers (e.g. "8 12"). If either number is empty, default to 8 and 12. + redundancy_val="$(yaml-cli -i "$CONFIG_FILE" -g .wireless.broadcast_redundancy 2>/dev/null)" + if [ "$redundancy_val" = "auto" ]; then + result="$(detect_redundancy.sh)" + fec_k=$(echo "$result" | awk '{print $1}') + fec_n=$(echo "$result" | awk '{print $2}') + [ -z "$fec_k" ] && fec_k=8 + [ -z "$fec_n" ] && fec_n=12 + BROADCAST_FEC_K="$fec_k" + BROADCAST_FEC_N="$fec_n" + fi + + tunnel_keys="mcs_index fec_k fec_n force_vht ldpc stbc" + for key in $tunnel_keys; do + val="$(yaml-cli -i "$CONFIG_FILE" -g ".tunnel.$key" 2>/dev/null)" + if [ -n "$val" ]; then + varname="TUNNEL_$(echo "$key" | tr '[:lower:]' '[:upper:]')" + eval "$varname='$val'" + # echo "$varname=$val" + fi + done + + telemetry_keys="router serial osd_fps channels" + for key in $telemetry_keys; do + val="$(yaml-cli -i "$CONFIG_FILE" -g ".telemetry.$key" 2>/dev/null)" + if [ -n "$val" ]; then + varname="TELEMETRY_$(echo "$key" | tr '[:lower:]' '[:upper:]')" + eval "$varname='$val'" + # echo "$varname=$val" + fi + done + fi +} + +load_config() { + wfb_yaml /etc/wfb.yaml + + if [ ! -e "$wfb_key" ]; then + wfb_key="/rom/etc/drone.key" + fi +} + +load_modules() { + for card in $(lsusb | awk '{print $6}' | sort | uniq); do + case "$card" in + "0bda:8812" | "0bda:881a" | "0b05:17d2" | "2357:0101" | "2604:0012") + driver=88XXau + modprobe "$driver" + ;; + "0bda:a81a") + driver=8812eu + modprobe "$driver" rtw_regd_src=1 rtw_tx_pwr_by_rate=0 rtw_tx_pwr_lmt_enable=0 + ;; + "0bda:f72b" | "0bda:b733") + driver=8733bu + modprobe "$driver" rtw_regd_src=1 rtw_tx_pwr_by_rate=0 rtw_tx_pwr_lmt_enable=0 + ;; + esac + done + + if [ -z "$driver" ]; then + echo "- Wireless module not detected!" + exit 1 + else + echo "- Detected driver: $driver" + fi + + if ! ifconfig "$wfb_dev" up; then + echo "- Wireless driver not found!" + exit 1 + fi +} + +load_interface() { + iw "$wfb_dev" set monitor none + iw "$wfb_dev" set channel "$WIRELESS_CHANNEL" "$WIRELESS_WIFI_MODE" + iw reg set 00 + + if [ "$driver" = "88XXau" ]; then + iw "$wfb_dev" set txpower fixed "$((WIRELESS_TXPOWER * -100))" + else + iw "$wfb_dev" set txpower fixed "$((WIRELESS_TXPOWER * 50))" + fi +} + +start_broadcast() { + echo "- Starting wfb_tx" + wfb_tx -K "$WIRELESS_VIDEO_KEY" -M "$BROADCAST_MCS_INDEX" -G "$BROADCAST_GUARD_INTERVAL" -B "$BROADCAST_BW" -C 8000 \ + -k "$BROADCAST_FEC_K" -n "$BROADCAST_FEC_N" -i "$WIRELESS_LINK_ID" "$wfb_dev" &> /dev/null & +} + +start_tunnel() { + echo "- Starting wfb_tun" + wfb_rx -p 160 -u 5800 -K "$WIRELESS_TUNNEL_KEY" -i "$WIRELESS_LINK_ID" "$wfb_dev" &> /dev/null & + wfb_tx -p 32 -u 5801 -K "$WIRELESS_TUNNEL_KEY" -M "$TUNNEL_MCS_INDEX" \ + -k "$TUNNEL_FEC_K" -n "$TUNNEL_FEC_N" -i "$WIRELESS_LINK_ID" "$wfb_dev" &> /dev/null & + wfb_tun -a 10.5.0.10/24 > /dev/null & +} + +start_telemetry() { + if [ "$(ipcinfo -c)" = "ssc33x" ]; then + devmem 0x1F207890 16 0x8 + fi + + + if [ "$TELEMETRY_ROUTER" = "msposd" ]; then + echo "- Starting $TELEMETRY_ROUTER" + size=$(yaml-cli -i /etc/majestic.yaml -g .video0.size) + msposd --baudrate 115200 --channels 8 --ahi 0 -osd -r "$TELEMETRY_OSD_FPS" \ + --master "$TELEMETRY_SERIAL" --out 10.5.0.1:14551 --size "${size:-1280x720}" > /dev/null & + elif [ "$TELEMETRY_ROUTER" = "mavfwd" ]; then + echo "- Starting $TELEMETRY_ROUTER" + mavfwd --baudrate 115200 --channels $TELEMETRY_CHANNELS -p 100 -a 15 -t \ + --master "$TELEMETRY_SERIAL" --in 0.0.0.0:14550 --out 10.5.0.1:14551 > /dev/null & + fi +} + +video_settings() { + if [ "$(ipcinfo -s)" = "imx415" ]; then + cli -s .isp.sensorConfig /etc/sensors/imx415_fpv.bin + fi + cli -s .isp.exposure 5 + cli -s .video0.fps 60 + cli -s .video0.codec h265 + cli -s .video0.rcMode cbr + cli -s .outgoing.enabled true + cli -s .outgoing.server udp://0.0.0.0:5600 +} + +start() { + load_config + load_modules + load_interface + + if [ ! -e /etc/system.ok ]; then + sleep 1 + video_settings + touch /etc/system.ok + killall -1 majestic + fi + + stop + start_broadcast + start_tunnel + start_telemetry +} + +bind() { + provision_bind.sh +} + +stop() { + for process in wfb_rx wfb_tx wfb_tun msposd mavfwd; do + if [ -n "$(pidof $process)" ]; then + echo "- Stopping $process" + killall -q "$process" + fi + done +} + +case "$1" in + start|stop) + $1 + ;; + bind) + provision_bind.sh + ;; + reset) + cp -f /rom/etc/majestic.yaml /etc/majestic.yaml + cp -f /rom/etc/wfb.yaml /etc/wfb.yaml + video_settings + ;; + *) + echo "Usage: $0 {start|stop|reset|bind}" + exit 1 + ;; +esac