Merging Beta 2.0.0 Release Candidate
This commit is contained in:
@@ -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"
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
Reference in New Issue
Block a user