Merging Beta 2.0.0 Release Candidate

This commit is contained in:
Russel Yasol
2025-03-11 15:21:04 +08:00
parent 0ce398b6e5
commit 36874b12f0
169 changed files with 8794 additions and 3057 deletions

View File

@@ -0,0 +1,168 @@
#!/bin/sh
# Set content type to JSON
echo "Content-type: application/json"
echo ""
# Configuration
QUEUE_DIR="/tmp/at_queue"
RESULTS_DIR="$QUEUE_DIR/results"
TOKEN_FILE="$QUEUE_DIR/token"
RESULT_FILE="/tmp/qscan_result.json"
WORKER_SCRIPT="/www/cgi-bin/quecmanager/experimental/cell_scanner/cell_scan_worker.sh"
PID_FILE="/tmp/cell_scan.pid"
SCAN_COMMAND="AT+QSCAN=3,1"
SCAN_TIMEOUT=200
LOCK_ID="CELL_SCAN_$(date +%s)_$$"
# Function to log messages
log_message() {
local level="${2:-info}"
logger -t at_queue -p "daemon.$level" "cell_scan: $1"
}
# Function to output JSON response
output_json() {
local status="$1"
local message="$2"
log_message "Sending response: status=$status, message=$message"
printf '{"status":"%s","message":"%s"}\n' "$status" "$message"
exit 0
}
# Function to check if worker is running
check_worker_running() {
if [ -f "$PID_FILE" ]; then
pid=$(cat "$PID_FILE")
if kill -0 "$pid" 2>/dev/null; then
log_message "Worker process $pid is running"
return 0
fi
log_message "Removing stale PID file for process $pid"
rm -f "$PID_FILE"
fi
return 1
}
# Enhanced JSON string escaping function
escape_json() {
printf '%s' "$1" | awk '
BEGIN { RS="\n"; ORS="\\n" }
{
gsub(/\\/, "\\\\")
gsub(/"/, "\\\"")
gsub(/\r/, "")
gsub(/\t/, "\\t")
gsub(/\f/, "\\f")
gsub(/\b/, "\\b")
print
}
' | sed 's/\\n$//'
}
# Acquire token directly with high priority
acquire_token() {
local priority=1 # Highest priority for cell scan
local max_attempts=10
local attempt=0
while [ $attempt -lt $max_attempts ]; do
# Check if token file exists
if [ -f "$TOKEN_FILE" ]; then
local current_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id' 2>/dev/null)
local current_priority=$(cat "$TOKEN_FILE" | jsonfilter -e '@.priority' 2>/dev/null)
local timestamp=$(cat "$TOKEN_FILE" | jsonfilter -e '@.timestamp' 2>/dev/null)
local current_time=$(date +%s)
# Check for expired token (> 30 seconds old)
if [ $((current_time - timestamp)) -gt 30 ] || [ -z "$current_holder" ]; then
# Remove expired token
rm -f "$TOKEN_FILE" 2>/dev/null
elif [ $priority -lt $current_priority ]; then
# Preempt lower priority token
log_message "Preempting token from $current_holder (priority: $current_priority)" "info"
rm -f "$TOKEN_FILE" 2>/dev/null
else
# Try again - higher priority token exists
log_message "Token held by $current_holder with priority $current_priority, retrying..." "debug"
sleep 0.5
attempt=$((attempt + 1))
continue
fi
fi
# Try to create token file
echo "{\"id\":\"$LOCK_ID\",\"priority\":$priority,\"timestamp\":$(date +%s)}" > "$TOKEN_FILE" 2>/dev/null
chmod 644 "$TOKEN_FILE" 2>/dev/null
# Verify we got the token
local holder=$(cat "$TOKEN_FILE" 2>/dev/null | jsonfilter -e '@.id' 2>/dev/null)
if [ "$holder" = "$LOCK_ID" ]; then
log_message "Successfully acquired token with priority $priority" "info"
return 0
fi
sleep 0.5
attempt=$((attempt + 1))
done
log_message "Failed to acquire token after $max_attempts attempts" "error"
return 1
}
# Main execution
{
# If scan is running, return running status
if check_worker_running; then
output_json "running" "Cell scan is in progress"
fi
# Start new scan
rm -f "$RESULT_FILE"
log_message "Starting new cell scan" "info"
# Ensure worker script is executable
chmod +x "$WORKER_SCRIPT" 2>/dev/null
# Start worker script with proper parameters
log_message "Attempting to start worker script: $WORKER_SCRIPT" "info"
# Check if worker script exists
if [ ! -f "$WORKER_SCRIPT" ]; then
log_message "Worker script not found: $WORKER_SCRIPT" "error"
output_json "error" "Worker script not found"
fi
# Ensure QUEUE_DIR exists
mkdir -p "$QUEUE_DIR" "$RESULTS_DIR"
chmod 755 "$QUEUE_DIR"
chmod 755 "$RESULTS_DIR"
# Start worker with debug logging
WORKER_PID=$
(sh "$WORKER_SCRIPT" >/tmp/cell_scan_worker.log 2>&1) &
WORKER_PID=$!
log_message "Worker script started with PID $WORKER_PID" "info"
# The worker process runs in the background and completes quickly
# We don't need to check if it's still running as it might finish before we check
log_message "Worker process $WORKER_PID started in background" "info"
# Instead of checking if the process is running, check if it created the result file
sleep 2
if [ -f "$RESULT_FILE" ]; then
log_message "Worker successfully created result file" "info"
else
log_message "Waiting for worker to create result file..." "info"
# If no result file yet, check for errors
if [ -f "/tmp/cell_scan_worker.log" ]; then
WORKER_LOG=$(cat "/tmp/cell_scan_worker.log" | head -20)
log_message "Worker log: $WORKER_LOG" "info"
fi
fi
output_json "running" "Started new cell scan"
} || {
# Error handler
log_message "Script failed with error" "error"
output_json "error" "Internal error occurred"
}

View File

@@ -0,0 +1,323 @@
#!/bin/sh
# Configuration
QUEUE_DIR="/tmp/at_queue"
RESULTS_DIR="$QUEUE_DIR/results"
TOKEN_FILE="$QUEUE_DIR/token"
RESULT_FILE="/tmp/qscan_result.json"
PID_FILE="/tmp/cell_scan.pid"
SCAN_COMMAND="AT+QSCAN=3,1"
SCAN_TIMEOUT=200
LOCK_ID="CELL_SCAN_$(date +%s)_$$"
# Enable shell debugging for better logging
set -x
# Function to log messages
log_message() {
local level="${2:-info}"
logger -t at_queue -p "daemon.$level" "cell_scan_worker: $1"
}
# Function to clean up stale temporary files
cleanup_stale_files() {
log_message "Cleaning up stale temporary files" "info"
# Clean up old start_time files (older than 1 hour)
find "$QUEUE_DIR" -name "start_time.qscan_*" -type f -mmin +60 -delete 2>/dev/null
# Clean up any start_time files that match our current process just in case
find "$QUEUE_DIR" -name "start_time.qscan_*_$" -type f -delete 2>/dev/null
log_message "Stale file cleanup completed" "info"
}
# Function to check directories and permissions
check_environment() {
log_message "Checking environment" "info"
# Clean up stale files first
cleanup_stale_files
# Check if directories exist, create if they don't
if [ ! -d "$QUEUE_DIR" ]; then
mkdir -p "$QUEUE_DIR"
log_message "Created queue directory: $QUEUE_DIR" "info"
fi
if [ ! -d "$RESULTS_DIR" ]; then
mkdir -p "$RESULTS_DIR"
log_message "Created results directory: $RESULTS_DIR" "info"
fi
# Check permissions
chmod 755 "$QUEUE_DIR" 2>/dev/null
chmod 755 "$RESULTS_DIR" 2>/dev/null
# Check if sms_tool exists and is executable
if ! which sms_tool >/dev/null 2>&1; then
log_message "sms_tool not found in PATH" "error"
return 1
fi
# Test directory write permissions
if ! touch "$QUEUE_DIR/test_$$" 2>/dev/null; then
log_message "Cannot write to $QUEUE_DIR" "error"
return 1
fi
rm -f "$QUEUE_DIR/test_$$" 2>/dev/null
if ! touch "$RESULTS_DIR/test_$$" 2>/dev/null; then
log_message "Cannot write to $RESULTS_DIR" "error"
return 1
fi
rm -f "$RESULTS_DIR/test_$$" 2>/dev/null
log_message "Environment check passed" "info"
return 0
}
# Function to clean AT command output
clean_output() {
while IFS= read -r line; do
case "$line" in
"OK" | "" | *"ERROR"*)
continue
;;
*)
printf '%s\n' "$line"
;;
esac
done | sed 's/\r//g' | tr '\n' '\r' | sed 's/\r$//' | tr '\r' '\n'
}
# Enhanced JSON string escaping function
escape_json() {
printf '%s' "$1" | awk '
BEGIN { RS="\n"; ORS="\\n" }
{
gsub(/\\/, "\\\\")
gsub(/"/, "\\\"")
gsub(/\r/, "")
gsub(/\t/, "\\t")
gsub(/\f/, "\\f")
gsub(/\b/, "\\b")
print
}
' | sed 's/\\n$//'
}
# Function to check if scan is already running
check_running() {
if [ -f "$PID_FILE" ]; then
pid=$(cat "$PID_FILE")
if kill -0 "$pid" 2>/dev/null; then
log_message "Cell scan already running (PID: $pid)" "warn"
return 0
fi
rm -f "$PID_FILE"
fi
return 1
}
# Acquire token directly with high priority
acquire_token() {
local priority=1 # Highest priority for cell scan
local max_attempts=10
local attempt=0
while [ $attempt -lt $max_attempts ]; do
# Check if token file exists
if [ -f "$TOKEN_FILE" ]; then
local current_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id' 2>/dev/null)
local current_priority=$(cat "$TOKEN_FILE" | jsonfilter -e '@.priority' 2>/dev/null)
local timestamp=$(cat "$TOKEN_FILE" | jsonfilter -e '@.timestamp' 2>/dev/null)
local current_time=$(date +%s)
# Check for expired token (> 30 seconds old)
if [ $((current_time - timestamp)) -gt 30 ] || [ -z "$current_holder" ]; then
# Remove expired token
rm -f "$TOKEN_FILE" 2>/dev/null
elif [ $priority -lt $current_priority ]; then
# Preempt lower priority token
log_message "Preempting token from $current_holder (priority: $current_priority)" "info"
rm -f "$TOKEN_FILE" 2>/dev/null
else
# Try again
sleep 0.5
attempt=$((attempt + 1))
continue
fi
fi
# Try to create token file
echo "{\"id\":\"$LOCK_ID\",\"priority\":$priority,\"timestamp\":$(date +%s)}" > "$TOKEN_FILE" 2>/dev/null
chmod 644 "$TOKEN_FILE" 2>/dev/null
# Verify we got the token
local holder=$(cat "$TOKEN_FILE" 2>/dev/null | jsonfilter -e '@.id' 2>/dev/null)
if [ "$holder" = "$LOCK_ID" ]; then
log_message "Successfully acquired token with priority $priority" "info"
return 0
fi
sleep 0.5
attempt=$((attempt + 1))
done
log_message "Failed to acquire token after $max_attempts attempts" "error"
return 1
}
# Release token directly
release_token() {
if [ -f "$TOKEN_FILE" ]; then
local current_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id' 2>/dev/null)
if [ "$current_holder" = "$LOCK_ID" ]; then
rm -f "$TOKEN_FILE" 2>/dev/null
log_message "Released token" "info"
return 0
fi
log_message "Token held by $current_holder, not by us ($LOCK_ID)" "warn"
fi
return 1
}
# Main execution
main() {
# Start logging
log_message "Worker script started" "info"
# Check if already running
if check_running; then
log_message "Cell scan already running, exiting" "warn"
exit 1
fi
# Create PID file
echo "$$" > "$PID_FILE"
chmod 644 "$PID_FILE" 2>/dev/null
log_message "Created PID file: $$" "info"
# Set up cleanup on exit
trap 'log_message "Cleaning up and exiting" "info"; release_token; rm -f "$PID_FILE"; exit' INT TERM EXIT
# Acquire token for AT command execution
if ! acquire_token; then
log_message "Failed to acquire token, exiting" "error"
rm -f "$PID_FILE"
exit 1
fi
log_message "Token acquired, executing scan command: $SCAN_COMMAND" "info"
# Execute scan with native timeout option (without relying on timeout command)
# Use the -t option of sms_tool instead of the timeout command
log_message "Executing command with timeout: $SCAN_TIMEOUT seconds" "info"
SCAN_OUTPUT=$(sms_tool at "$SCAN_COMMAND" -t $SCAN_TIMEOUT 2>&1 | clean_output)
SCAN_STATUS=$?
log_message "Command execution completed with status: $SCAN_STATUS" "info"
# Process and store result
if [ $SCAN_STATUS -eq 0 ]; then
# Check if output contains valid scan data or error
if echo "$SCAN_OUTPUT" | grep -q "+QSCAN"; then
# Set timestamp
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
# Valid scan data found - don't add the "Scan completed but no valid data" prefix
log_message "Scan completed with valid data" "info"
# Create the result file with proper JSON formatting
printf '{"status":"success","timestamp":"%s","output":%s}\n' \
"$TIMESTAMP" \
"$(printf '%s' "$SCAN_OUTPUT" | sed 's/"/\\"/g' | jq -R -s '.')" > "$RESULT_FILE"
chmod 644 "$RESULT_FILE" 2>/dev/null
else
# No valid scan data, but command completed
log_message "Command completed but no valid scan data found: $SCAN_OUTPUT" "warn"
SCAN_OUTPUT="Scan completed but no valid data returned: $SCAN_OUTPUT"
# Create a result file indicating partial success
printf '{"status":"partial","timestamp":"%s","output":%s}\n' \
"$(date '+%Y-%m-%d %H:%M:%S')" \
"$(printf '%s' "$SCAN_OUTPUT" | sed 's/"/\\"/g' | jq -R -s '.')" > "$RESULT_FILE"
chmod 644 "$RESULT_FILE" 2>/dev/null
fi
# Generate a command ID for the AT queue results format - use actual PID instead of $
local my_pid="$$"
local cmd_id="qscan_$(date +%s)_${my_pid}"
local end_time=$(date +%s)
local start_time=$end_time
local duration=0
# Store start time for future reference
echo "$start_time" > "$QUEUE_DIR/start_time.$cmd_id"
log_message "Creating AT queue result with ID: $cmd_id" "info"
# Create JSON response in the AT queue format
local response=$(cat << EOF
{
"command": {
"id": "$cmd_id",
"text": "$SCAN_COMMAND",
"timestamp": "$(date -Iseconds)"
},
"response": {
"status": "success",
"raw_output": "$(escape_json "$SCAN_OUTPUT")",
"completion_time": "$end_time",
"duration_ms": $duration
}
}
EOF
)
# Save the response to the AT queue results directory
printf "%s" "$response" > "$RESULTS_DIR/$cmd_id.json"
chmod 644 "$RESULTS_DIR/$cmd_id.json"
# Clean up temporary files
rm -f "$QUEUE_DIR/start_time.$cmd_id"
log_message "Cleaned up temporary files" "info"
# Release the token
release_token
return 0
else
log_message "Scan failed with status: $SCAN_STATUS" "error"
printf '{"status":"error","timestamp":"%s","message":"Scan failed"}\n' \
"$(date '+%Y-%m-%d %H:%M:%S')" > "$RESULT_FILE"
chmod 644 "$RESULT_FILE" 2>/dev/null
# Release the token
release_token
return 1
fi
}
# Execute main function with proper error handling
{
log_message "Worker script started with PID $$" "info"
# Check environment before proceeding
check_environment || {
log_message "Environment check failed, aborting" "error"
exit 1
}
# Execute main function
main || {
log_message "Main function failed with error $?" "error"
release_token
rm -f "$PID_FILE"
exit 1
}
} 2>/tmp/cell_scan_worker_debug.log || {
log_message "Script failed with error" "error"
release_token
rm -f "$PID_FILE"
exit 1
}

View File

@@ -0,0 +1,124 @@
#!/bin/sh
# Set content type to JSON
echo "Content-type: application/json"
echo ""
# Configuration
QUEUE_DIR="/tmp/at_queue"
RESULTS_DIR="$QUEUE_DIR/results"
RESULT_FILE="/tmp/qscan_result.json"
PID_FILE="/tmp/cell_scan.pid"
TOKEN_FILE="$QUEUE_DIR/token"
# Function to log messages
log_message() {
local level="${2:-info}"
logger -t at_queue -p "daemon.$level" "check_scan: $1"
}
# Function to output JSON response
output_json() {
local status="$1"
local message="$2"
if [ "$status" = "success" ] && [ -f "$RESULT_FILE" ]; then
# Return the contents of the result file
cat "$RESULT_FILE"
else
printf '{"status":"%s","message":"%s","timestamp":"","output":""}\n' "$status" "$message"
fi
}
# Check for scan token holder
check_token_holder() {
if [ -f "$TOKEN_FILE" ]; then
local current_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id' 2>/dev/null)
if [ -n "$current_holder" ] && echo "$current_holder" | grep -q "CELL_SCAN"; then
log_message "Cell scan token is active: $current_holder" "debug"
return 0
fi
fi
return 1
}
# Check if a scan is already in progress
check_scan_progress() {
# First check PID file
if [ -f "$PID_FILE" ]; then
pid=$(cat "$PID_FILE")
if kill -0 "$pid" 2>/dev/null; then
log_message "Scan in progress (PID: $pid)" "info"
output_json "running" "Scan in progress"
exit 0
else
log_message "Removing stale PID file" "warn"
rm -f "$PID_FILE"
fi
fi
# Also check token holder
if check_token_holder; then
log_message "Scan in progress (Token active)" "info"
output_json "running" "Scan in progress (Token active)"
exit 0
fi
}
# Check for existing results
check_results() {
if [ -f "$RESULT_FILE" ]; then
# Check if the result file contains valid JSON data
local result_content=$(cat "$RESULT_FILE" 2>/dev/null)
if [ -n "$result_content" ] && echo "$result_content" | grep -q "status"; then
# Also check the results directory for AT command results
local cmd_id
cmd_id=$(echo "$result_content" | jsonfilter -e '@.command.id' 2>/dev/null)
# Log the result we found
log_message "Found result file with command ID: $cmd_id" "info"
# Check how old the result file is
local file_time=$(stat -c %Y "$RESULT_FILE" 2>/dev/null || echo "0")
local current_time=$(date +%s)
local age=$((current_time - file_time))
log_message "Result file age: $age seconds" "info"
# If file_time is valid and result is less than 1 hour old
if [ $age -lt 3600 ]; then
log_message "Recent scan results available" "info"
output_json "success" "Scan results available"
exit 0
else
log_message "Scan results too old, suggesting new scan" "info"
output_json "idle" "Previous scan results outdated"
exit 0
fi
else
log_message "Result file exists but contains invalid data" "warn"
rm -f "$RESULT_FILE" # Remove invalid result file
output_json "idle" "Invalid previous scan results"
exit 0
fi
fi
}
# Main execution
{
# First check if a scan is in progress
check_scan_progress
# Then check for existing results
check_results
# If no results and no running scan, indicate idle state
log_message "No active scan or recent results" "info"
output_json "idle" "No active scan"
exit 0
} || {
# Error handler
log_message "Failed to check scan status" "error"
output_json "error" "Failed to check scan status"
exit 1
}

View File

@@ -0,0 +1,40 @@
#!/bin/sh
# Set content type to JSON
echo "Content-type: application/json"
echo ""
# Configuration
JSON_FILE="/www/cgi-bin/quecmanager/mcc-mnc-list.json"
# Function to log messages
log_message() {
logger -t fetch_mccmnc "$1"
}
# Function to output JSON response
output_json() {
local status="$1"
local message="$2"
printf '{"status":"%s","message":"%s"}\n' "$status" "$message"
exit 1
}
# Main execution
{
# Check if file exists
if [ ! -f "$JSON_FILE" ]; then
log_message "MCC-MNC list file not found"
output_json "error" "MCC-MNC list file not found"
fi
# Read and output the file
cat "$JSON_FILE" 2>/dev/null || {
log_message "Failed to read MCC-MNC list file"
output_json "error" "Failed to read MCC-MNC list file"
}
} || {
# Error handler
log_message "Script failed with error"
output_json "error" "Internal error occurred"
}

View File

@@ -0,0 +1,311 @@
#!/bin/sh
# Set content-type for JSON response
echo "Content-type: application/json"
echo ""
# Define paths and constants to match queue system
QUEUE_DIR="/tmp/at_queue"
RESULTS_DIR="$QUEUE_DIR/results"
TOKEN_FILE="$QUEUE_DIR/token"
TEMP_FILE="/tmp/network_info_output.txt"
LOCK_ID="NETWORK_INFO_$(date +%s)_$$"
COMMAND_TIMEOUT=8 # Increased timeout
MAX_TOKEN_WAIT=10
PRIORITY=5 # Medium-high priority (between cell scan and normal commands)
# Function to log messages
log_message() {
local level="${2:-info}"
logger -t at_queue -p "daemon.$level" "network_info: $1"
}
# Function to output JSON error
output_error() {
printf '{"status":"error","message":"%s","timestamp":"%s"}\n' "$1" "$(date '+%H:%M:%S')"
exit 1
}
# Enhanced JSON string escaping function
escape_json() {
printf '%s' "$1" | awk '
BEGIN { RS="\n"; ORS="\\n" }
{
gsub(/\\/, "\\\\")
gsub(/"/, "\\\"")
gsub(/\r/, "")
gsub(/\t/, "\\t")
gsub(/\f/, "\\f")
gsub(/\b/, "\\b")
print
}
' | sed 's/\\n$//'
}
# Acquire token directly with medium-high priority
acquire_token() {
local priority="$PRIORITY" # Medium-high priority for network info
local max_attempts=$MAX_TOKEN_WAIT
local attempt=0
while [ $attempt -lt $max_attempts ]; do
# Check if token file exists
if [ -f "$TOKEN_FILE" ]; then
local current_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id' 2>/dev/null)
local current_priority=$(cat "$TOKEN_FILE" | jsonfilter -e '@.priority' 2>/dev/null)
local timestamp=$(cat "$TOKEN_FILE" | jsonfilter -e '@.timestamp' 2>/dev/null)
local current_time=$(date +%s)
# Check for expired token (> 30 seconds old)
if [ $((current_time - timestamp)) -gt 30 ] || [ -z "$current_holder" ]; then
# Remove expired token
rm -f "$TOKEN_FILE" 2>/dev/null
elif [ $priority -lt $current_priority ]; then
# Preempt lower priority token
log_message "Preempting token from $current_holder (priority: $current_priority)" "info"
rm -f "$TOKEN_FILE" 2>/dev/null
else
# Try again - higher priority token exists
log_message "Token held by $current_holder with priority $current_priority, retrying..." "debug"
sleep 0.5
attempt=$((attempt + 1))
continue
fi
fi
# Try to create token file
echo "{\"id\":\"$LOCK_ID\",\"priority\":$priority,\"timestamp\":$(date +%s)}" > "$TOKEN_FILE" 2>/dev/null
chmod 644 "$TOKEN_FILE" 2>/dev/null
# Verify we got the token
local holder=$(cat "$TOKEN_FILE" 2>/dev/null | jsonfilter -e '@.id' 2>/dev/null)
if [ "$holder" = "$LOCK_ID" ]; then
log_message "Successfully acquired token with priority $priority" "info"
return 0
fi
sleep 0.5
attempt=$((attempt + 1))
done
log_message "Failed to acquire token after $max_attempts attempts" "error"
return 1
}
# Release token directly
release_token() {
if [ -f "$TOKEN_FILE" ]; then
local current_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id' 2>/dev/null)
if [ "$current_holder" = "$LOCK_ID" ]; then
rm -f "$TOKEN_FILE" 2>/dev/null
log_message "Released token" "info"
return 0
fi
log_message "Token held by $current_holder, not by us ($LOCK_ID)" "warn"
fi
return 1
}
# Function to execute AT command with direct output capture
execute_at_command() {
local CMD="$1"
local OUTPUT_FILE="$TEMP_FILE.cmd.$$"
log_message "Executing command: $CMD" "debug"
# Execute command and redirect output to file for reliable capture
sms_tool at "$CMD" -t $COMMAND_TIMEOUT > "$OUTPUT_FILE" 2>&1
local EXIT_CODE=$?
# Read the output regardless of exit code
if [ -f "$OUTPUT_FILE" ]; then
local OUTPUT=$(cat "$OUTPUT_FILE")
rm -f "$OUTPUT_FILE"
if [ -n "$OUTPUT" ]; then
# We have some output
if echo "$OUTPUT" | grep -q "CME ERROR"; then
log_message "Command returned CME ERROR: $OUTPUT" "warn"
return 1
elif echo "$OUTPUT" | grep -q "ERROR"; then
log_message "Command returned ERROR: $OUTPUT" "warn"
return 1
else
# Command produced output that doesn't contain ERROR
log_message "Command executed successfully with output" "debug"
echo "$OUTPUT"
return 0
fi
elif [ $EXIT_CODE -eq 0 ]; then
log_message "Command succeeded but returned empty output" "warn"
echo "Command returned empty output"
return 0
else
log_message "Command failed with exit code $EXIT_CODE and no output" "error"
return 1
fi
else
log_message "Failed to create output file" "error"
return 1
fi
}
# Function to check network mode from serving cell info
check_network_mode() {
local OUTPUT="$1"
# Check for both LTE and NR5G-NSA (NSA mode)
if echo "$OUTPUT" | grep -q "\"LTE\"" && echo "$OUTPUT" | grep -q "\"NR5G-NSA\""; then
log_message "Detected network mode: NRLTE (NSA)" "info"
echo "NRLTE"
# Check for LTE only
elif echo "$OUTPUT" | grep -q "\"LTE\""; then
log_message "Detected network mode: LTE" "info"
echo "LTE"
# Check for NR5G-SA
elif echo "$OUTPUT" | grep -q "\"NR5G-SA\""; then
log_message "Detected network mode: NR5G (SA)" "info"
echo "NR5G"
else
log_message "Detected network mode: UNKNOWN from output: $OUTPUT" "warn"
echo "UNKNOWN"
fi
}
# Function to check NR5G measurement info setting
check_nr5g_meas_info() {
local OUTPUT=$(execute_at_command "AT+QNWCFG=\"nr5g_meas_info\"")
local EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ] && echo "$OUTPUT" | grep -q "\"nr5g_meas_info\",1"; then
log_message "NR5G measurement info is enabled" "debug"
return 0
else
log_message "NR5G measurement info is disabled or check failed" "debug"
return 1
fi
}
# Function to create JSON output safely
format_output_json() {
local MODE="$1"
local SERVING_OUTPUT="$2"
local NEIGHBOR_OUTPUT="$3"
local MEAS_OUTPUT="$4"
# Basic JSON structure - start
printf '{"status":"success","timestamp":"%s","mode":"%s"' "$(date '+%H:%M:%S')" "$MODE"
# Add raw data section
printf ',"raw_data":{'
# Add serving cell output (always present)
printf '"servingCell":%s' "$(printf '%s' "$SERVING_OUTPUT" | jq -R -s '.')"
# Add neighbor cells output if available
if [ -n "$NEIGHBOR_OUTPUT" ]; then
printf ',"neighborCells":%s' "$(printf '%s' "$NEIGHBOR_OUTPUT" | jq -R -s '.')"
fi
# Add measurement info output if available
if [ -n "$MEAS_OUTPUT" ]; then
printf ',"meas":%s' "$(printf '%s' "$MEAS_OUTPUT" | jq -R -s '.')"
fi
# Close raw data section
printf '}'
# Close the whole JSON object
printf '}\n'
}
# Set up trap for cleanup
trap 'log_message "Script interrupted, cleaning up" "warn"; release_token; rm -f "$TEMP_FILE" "$TEMP_FILE.cmd."*; exit 1' INT TERM EXIT
# Main execution
{
# Ensure directories exist
mkdir -p "$QUEUE_DIR" "$RESULTS_DIR"
log_message "Starting network info collection" "info"
# Acquire token for AT command execution before any output
if ! acquire_token; then
output_error "Failed to acquire token for command processing"
fi
# Get the serving cell information first
log_message "Getting serving cell information" "info"
SERVING_OUTPUT=$(execute_at_command "AT+QENG=\"servingcell\"")
EXIT_CODE=$?
# Check if we got valid serving cell info
if [ $EXIT_CODE -ne 0 ] || [ -z "$SERVING_OUTPUT" ]; then
log_message "Failed to get serving cell information, output: $SERVING_OUTPUT" "error"
release_token
output_error "Failed to get serving cell information"
fi
log_message "Successfully got serving cell information" "info"
# Determine network mode from serving cell output
NETWORK_MODE=$(check_network_mode "$SERVING_OUTPUT")
NEIGHBOR_OUTPUT=""
MEAS_OUTPUT=""
case "$NETWORK_MODE" in
"NRLTE")
log_message "Processing NRLTE mode commands" "info"
NEIGHBOR_OUTPUT=$(execute_at_command "AT+QENG=\"neighbourcell\"")
# Try to get measurement info
if ! check_nr5g_meas_info; then
log_message "Enabling NR5G measurement info" "info"
execute_at_command "AT+QNWCFG=\"nr5g_meas_info\",1" > /dev/null
sleep 1 # Give it time to take effect
fi
log_message "Fetching NR5G measurement info" "info"
MEAS_OUTPUT=$(execute_at_command "AT+QNWCFG=\"nr5g_meas_info\"")
;;
"LTE")
log_message "Processing LTE mode commands" "info"
NEIGHBOR_OUTPUT=$(execute_at_command "AT+QENG=\"neighbourcell\"")
;;
"NR5G")
log_message "Processing NR5G mode commands" "info"
# Try to get measurement info
if ! check_nr5g_meas_info; then
log_message "Enabling NR5G measurement info" "info"
execute_at_command "AT+QNWCFG=\"nr5g_meas_info\",1" > /dev/null
sleep 1 # Give it time to take effect
fi
log_message "Fetching NR5G measurement info" "info"
MEAS_OUTPUT=$(execute_at_command "AT+QNWCFG=\"nr5g_meas_info\"")
;;
*)
# Even if we don't recognize the mode, we'll still return the serving cell info
log_message "Unknown network mode, only returning serving cell info" "warn"
;;
esac
# Format and output JSON response
log_message "Formatting JSON response" "info"
format_output_json "$NETWORK_MODE" "$SERVING_OUTPUT" "$NEIGHBOR_OUTPUT" "$MEAS_OUTPUT"
# Release token and clean up
release_token
rm -f "$TEMP_FILE" "$TEMP_FILE.cmd."*
log_message "Network info collection completed" "info"
} || {
# Error handler
log_message "Script failed with error" "error"
release_token
rm -f "$TEMP_FILE" "$TEMP_FILE.cmd."*
output_error "Internal error occurred"
}