Added cgi-bin scripts
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set content type for JSON response
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
|
||||
# Check if the file exists
|
||||
if [ -f "/etc/config/atcommands.user" ]; then
|
||||
# Start JSON object
|
||||
printf "{\n"
|
||||
awk -F';' '
|
||||
BEGIN { first = 1 }
|
||||
{
|
||||
gsub(/\r/, "", $0)
|
||||
if (!first) printf ",\n "
|
||||
else printf " "
|
||||
gsub(/"/, "\\\"", $1)
|
||||
gsub(/"/, "\\\"", $2)
|
||||
printf "\"%s\": \"%s\"", $1, $2
|
||||
first = 0
|
||||
}
|
||||
' /etc/config/atcommands.user
|
||||
printf "\n}"
|
||||
else
|
||||
echo '{"error": "No Data"}'
|
||||
fi
|
||||
@@ -0,0 +1,49 @@
|
||||
#!/bin/sh
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Create a temporary file to store the processed data
|
||||
temp_file=$(mktemp)
|
||||
|
||||
# Process ARP entries and store in temporary file
|
||||
arp -a | while IFS= read -r line; do
|
||||
if [ -n "$line" ]; then
|
||||
# Extract hostname (or IP if hostname is "?"), IP, and MAC
|
||||
hostname=$(echo "$line" | awk '{print $1}')
|
||||
ip=$(echo "$line" | awk -F '[()]' '{print $2}')
|
||||
mac=$(echo "$line" | awk '{print $4}')
|
||||
|
||||
# Skip entries without valid MAC addresses
|
||||
if [ "$mac" = "<incomplete>" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# If hostname is "?", use the IP address instead
|
||||
if [ "$hostname" = "?" ]; then
|
||||
hostname="$ip"
|
||||
fi
|
||||
|
||||
# Store each entry in the temp file
|
||||
echo "$hostname:$ip:$mac" >> "$temp_file"
|
||||
fi
|
||||
done
|
||||
|
||||
# Initialize JSON array
|
||||
echo -n "["
|
||||
|
||||
# Process the temporary file to create JSON
|
||||
first=true
|
||||
while IFS=: read -r hostname ip mac; do
|
||||
if [ "$first" = true ]; then
|
||||
first=false
|
||||
else
|
||||
echo -n ","
|
||||
fi
|
||||
echo -n "{\"hostname\":\"$hostname\",\"ip\":\"$ip\",\"mac\":\"$mac\"}"
|
||||
done < "$temp_file"
|
||||
|
||||
# Close the JSON array
|
||||
echo "]"
|
||||
|
||||
# Clean up
|
||||
rm -f "$temp_file"
|
||||
@@ -0,0 +1,90 @@
|
||||
#!/bin/sh
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
mtu_firewall_file="/etc/firewall.user.mtu"
|
||||
network_interface="rmnet_data0"
|
||||
lan_utils_script="/etc/data/lanUtils.sh"
|
||||
|
||||
get_current_mtu() {
|
||||
ip link show "$network_interface" | grep -o "mtu [0-9]*" | cut -d' ' -f2
|
||||
}
|
||||
|
||||
update_lanutils_mtu_config() {
|
||||
local action="$1"
|
||||
if [ "$action" = "add" ]; then
|
||||
# Add the MTU firewall file line if not already present
|
||||
if ! grep -q "local mtu_firewall_file=/etc/firewall.user.mtu" "$lan_utils_script"; then
|
||||
sed -i '/local ttl_firewall_file=\/etc\/firewall.user.ttl/a local mtu_firewall_file=/etc/firewall.user.mtu' "$lan_utils_script"
|
||||
fi
|
||||
elif [ "$action" = "remove" ]; then
|
||||
# Remove the MTU firewall file line if present
|
||||
sed -i '/local mtu_firewall_file=\/etc\/firewall.user.mtu/d' "$lan_utils_script"
|
||||
fi
|
||||
}
|
||||
|
||||
case "$REQUEST_METHOD" in
|
||||
GET)
|
||||
# Fetch current MTU
|
||||
current_mtu=$(get_current_mtu)
|
||||
current_mtu=${current_mtu:-1500}
|
||||
|
||||
# Check if custom MTU is configured
|
||||
if [ -f "$mtu_firewall_file" ]; then
|
||||
echo "{\"isEnabled\": true, \"currentValue\": $current_mtu}"
|
||||
else
|
||||
echo "{\"isEnabled\": false, \"currentValue\": $current_mtu}"
|
||||
fi
|
||||
;;
|
||||
|
||||
POST)
|
||||
read -r post_data
|
||||
mtu_value=$(echo "$post_data" | sed 's/mtu=//')
|
||||
|
||||
# Check for disable functionality
|
||||
if [ "$mtu_value" = "disable" ]; then
|
||||
# Remove the MTU configuration file
|
||||
rm -f "$mtu_firewall_file"
|
||||
|
||||
# Remove the MTU configuration line from lanUtils.sh
|
||||
update_lanutils_mtu_config "remove"
|
||||
|
||||
# Get the default MTU
|
||||
default_mtu=$(get_current_mtu)
|
||||
default_mtu=${default_mtu:-1500}
|
||||
|
||||
echo "{\"success\": true, \"message\": \"MTU configuration disabled\", \"currentValue\": $default_mtu}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Validate MTU input
|
||||
if ! [[ "$mtu_value" =~ ^[0-9]+$ ]]; then
|
||||
echo "{\"success\": false, \"error\": \"Invalid MTU value\"}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create firewall MTU configuration file with individual interface commands
|
||||
> "$mtu_firewall_file" # Clear the file
|
||||
for iface in $(ls /sys/class/net | grep '^rmnet_data'); do
|
||||
echo "ip link set $iface mtu $mtu_value" >> "$mtu_firewall_file"
|
||||
done
|
||||
|
||||
# Immediately apply MTU change
|
||||
for iface in $(ls /sys/class/net | grep '^rmnet_data'); do
|
||||
ip link set "$iface" mtu "$mtu_value"
|
||||
done
|
||||
|
||||
# Add the MTU configuration line to lanUtils.sh
|
||||
update_lanutils_mtu_config "add"
|
||||
|
||||
# Run lanUtils.sh to update network configuration
|
||||
if [ -f "$lan_utils_script" ]; then
|
||||
. "$lan_utils_script"
|
||||
fi
|
||||
|
||||
echo "{\"success\": true, \"message\": \"MTU configuration updated to $mtu_value\", \"currentValue\": $mtu_value}"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "{\"success\": false, \"error\": \"Invalid request method\"}"
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,94 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
ttl_file="/etc/firewall.user.ttl"
|
||||
lan_utils_script="/etc/data/lanUtils.sh"
|
||||
|
||||
setup_persistent_config() {
|
||||
if [ ! -f "$lan_utils_script" ]; then
|
||||
echo "{\"success\": false, \"error\": \"lanUtils.sh not found\"}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Backup the original script if not already done
|
||||
if [ ! -f "${lan_utils_script}.bak" ]; then
|
||||
cp "$lan_utils_script" "${lan_utils_script}.bak"
|
||||
fi
|
||||
|
||||
# Add the local ttl_firewall_file line if it's not already present
|
||||
if ! grep -q "local ttl_firewall_file" "$lan_utils_script"; then
|
||||
sed -i '/local tcpmss_firewall_filev6/a \ local ttl_firewall_file=/etc/firewall.user.ttl' "$lan_utils_script"
|
||||
fi
|
||||
|
||||
# Add the condition to include the ttl_firewall_file if it's not already present
|
||||
if ! grep -q "if \[ -f \"\$ttl_firewall_file\" \]; then" "$lan_utils_script"; then
|
||||
sed -i '/if \[ -f "\$tcpmss_firewall_filev6" \]; then/i \ if [ -f "\$ttl_firewall_file" ]; then\n cat \$ttl_firewall_file >> \$firewall_file\n fi' "$lan_utils_script"
|
||||
fi
|
||||
}
|
||||
|
||||
clear_existing_rules() {
|
||||
local current_ttl=$1
|
||||
if [ -n "$current_ttl" ]; then
|
||||
iptables -t mangle -D POSTROUTING -o rmnet+ -j TTL --ttl-set "$current_ttl" 2>/dev/null
|
||||
ip6tables -t mangle -D POSTROUTING -o rmnet+ -j HL --hl-set "$current_ttl" 2>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
case "$REQUEST_METHOD" in
|
||||
GET)
|
||||
# Ensure consistent JSON format for GET requests
|
||||
if [ -s "$ttl_file" ]; then
|
||||
ttl_value=$(grep 'iptables -t mangle -A POSTROUTING' "$ttl_file" | awk '{for(i=1;i<=NF;i++){if($i=="--ttl-set"){print $(i+1)}}}')
|
||||
# Ensure ttl_value is a number, default to 0 if not
|
||||
if ! [[ "$ttl_value" =~ ^[0-9]+$ ]]; then
|
||||
ttl_value=0
|
||||
fi
|
||||
echo "{\"isEnabled\": true, \"currentValue\": $ttl_value}"
|
||||
else
|
||||
echo "{\"isEnabled\": false, \"currentValue\": 0}"
|
||||
fi
|
||||
;;
|
||||
POST)
|
||||
read -r post_data
|
||||
ttl_value=$(echo "$post_data" | sed 's/ttl=//')
|
||||
|
||||
# Ensure ttl_file exists
|
||||
touch "$ttl_file" 2>/dev/null
|
||||
if [ ! -f "$ttl_file" ]; then
|
||||
echo "{\"success\": false, \"error\": \"Cannot create TTL file\"}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Setup persistent configuration
|
||||
setup_persistent_config
|
||||
|
||||
# Get current TTL value for cleanup
|
||||
current_ttl=$(grep 'iptables -t mangle -A POSTROUTING' "$ttl_file" | awk '{for(i=1;i<=NF;i++){if($i=="--ttl-set"){print $(i+1)}}}')
|
||||
|
||||
if ! [[ "$ttl_value" =~ ^[0-9]+$ ]]; then
|
||||
echo "{\"success\": false, \"error\": \"Invalid TTL value\"}"
|
||||
elif [ "$ttl_value" = "0" ]; then
|
||||
clear_existing_rules "$current_ttl"
|
||||
> "$ttl_file"
|
||||
echo "{\"success\": true}"
|
||||
else
|
||||
# Clear existing rules
|
||||
clear_existing_rules "$current_ttl"
|
||||
|
||||
# Set new rules
|
||||
echo "iptables -t mangle -A POSTROUTING -o rmnet+ -j TTL --ttl-set $ttl_value" > "$ttl_file"
|
||||
echo "ip6tables -t mangle -A POSTROUTING -o rmnet+ -j HL --hl-set $ttl_value" >> "$ttl_file"
|
||||
|
||||
# Apply the rules
|
||||
iptables -t mangle -A POSTROUTING -o rmnet+ -j TTL --ttl-set "$ttl_value"
|
||||
ip6tables -t mangle -A POSTROUTING -o rmnet+ -j HL --hl-set "$ttl_value"
|
||||
|
||||
echo "{\"success\": true}"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "{\"success\": false, \"error\": \"Invalid request method\"}"
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,74 @@
|
||||
#!/bin/sh
|
||||
# CGI header
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Queue file
|
||||
QUEUE_FILE="/tmp/at_pipe.txt"
|
||||
RESULT_FILE="/tmp/at_results.json"
|
||||
LOG_FILE="/var/log/at_commands.log"
|
||||
|
||||
# Create queue file if it doesn't exist
|
||||
touch "${QUEUE_FILE}"
|
||||
|
||||
# Function to log messages
|
||||
log_message() {
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "${LOG_FILE}"
|
||||
}
|
||||
|
||||
# Function to generate random ID
|
||||
generate_random_id() {
|
||||
# Combine multiple sources of randomness
|
||||
local timestamp=$(date +%s%N)
|
||||
local random1=$(head -c 4 /dev/urandom | xxd -p)
|
||||
local random2=$(echo $$ $RANDOM | md5sum | head -c 8)
|
||||
echo "${timestamp}-${random1}-${random2}"
|
||||
}
|
||||
|
||||
# Function to escape special characters for JSON
|
||||
escape_json() {
|
||||
echo "$1" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g'
|
||||
}
|
||||
|
||||
# Function to decode URL
|
||||
decode_url() {
|
||||
local encoded="$1"
|
||||
# First handle percent-encoded characters
|
||||
printf '%b' "${encoded}" | sed -e 's/%\([0-9A-Fa-f][0-9A-Fa-f]\)/\\x\1/g' | xargs -0 echo -e |
|
||||
# Then handle plus signs separately (preserve them for AT commands)
|
||||
sed 's/[+]/%2B/g' | sed 's/%2B/+/g'
|
||||
}
|
||||
|
||||
# Get command from query string
|
||||
QUERY_STRING="${QUERY_STRING:-}"
|
||||
RAW_COMMAND=$(echo "${QUERY_STRING}" | sed 's/^command=//')
|
||||
|
||||
if [ -n "${RAW_COMMAND}" ]; then
|
||||
# Decode URL-encoded command with fixed plus sign handling
|
||||
AT_COMMAND=$(decode_url "${RAW_COMMAND}")
|
||||
|
||||
# Generate unique random ID
|
||||
CMD_ID=$(generate_random_id)
|
||||
|
||||
# Create timestamp
|
||||
TIMESTAMP=$(date '+%H:%M:%S')
|
||||
|
||||
# Escape command for JSON
|
||||
ESCAPED_COMMAND=$(escape_json "${AT_COMMAND}")
|
||||
|
||||
# Create JSON entry for queue (all in one line)
|
||||
QUEUE_ENTRY=$(printf '{"id":"%s","timestamp":"%s","command":"%s","status":"pending"}\n' \
|
||||
"${CMD_ID}" "${TIMESTAMP}" "${ESCAPED_COMMAND}")
|
||||
|
||||
# Add to queue file
|
||||
echo "${QUEUE_ENTRY}" >> "${QUEUE_FILE}"
|
||||
log_message "Queued command: ${AT_COMMAND} with ID: ${CMD_ID}"
|
||||
|
||||
# Return immediate response
|
||||
printf '{"status":"queued","message":"Command has been queued","command":"%s","id":"%s","queued_at":"%s"}\n' \
|
||||
"${ESCAPED_COMMAND}" "${CMD_ID}" "${TIMESTAMP}"
|
||||
else
|
||||
# Return error response
|
||||
printf '{"status":"error","message":"No command provided","timestamp":"%s"}\n' "$(date '+%H:%M:%S')"
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1,97 @@
|
||||
#!/bin/sh
|
||||
echo "Content-type: application/json"
|
||||
echo "Access-Control-Allow-Origin: *"
|
||||
echo "Access-Control-Allow-Methods: GET, POST, OPTIONS"
|
||||
echo "Access-Control-Allow-Headers: Content-Type"
|
||||
echo ""
|
||||
|
||||
# Configuration
|
||||
RESULT_FILE="/tmp/at_results.json"
|
||||
LOG_FILE="/var/log/at_commands.log"
|
||||
|
||||
# Function to log messages
|
||||
log_message() {
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "${LOG_FILE}"
|
||||
}
|
||||
|
||||
# Function to return error response
|
||||
send_error() {
|
||||
local message="$1"
|
||||
jq -n \
|
||||
--arg msg "${message}" \
|
||||
--arg time "$(date '+%H:%M:%S')" \
|
||||
'{
|
||||
status: "error",
|
||||
message: $msg,
|
||||
timestamp: $time
|
||||
}'
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Parse query parameters
|
||||
eval $(echo "${QUERY_STRING}" | tr '&' '\n' | sed 's/\([^=]*\)=\([^=]*\)/\1="\2"/')
|
||||
|
||||
# Check if results file exists
|
||||
if [ ! -f "${RESULT_FILE}" ]; then
|
||||
send_error "No results found"
|
||||
fi
|
||||
|
||||
# Validate results file contains valid JSON
|
||||
if ! cat "${RESULT_FILE}" | jq . >/dev/null 2>&1; then
|
||||
log_message "Invalid JSON in results file"
|
||||
send_error "Invalid results data"
|
||||
fi
|
||||
|
||||
# Handle different query types
|
||||
case "${action}" in
|
||||
"get_by_id")
|
||||
# Fetch specific result by ID
|
||||
if [ -z "${id}" ]; then
|
||||
send_error "No ID provided"
|
||||
fi
|
||||
|
||||
result=$(cat "${RESULT_FILE}" | jq --arg id "${id}" '. | map(select(.id == $id)) | .[0]')
|
||||
|
||||
if [ "${result}" = "null" ]; then
|
||||
send_error "No result found for ID: ${id}"
|
||||
else
|
||||
echo "${result}"
|
||||
fi
|
||||
;;
|
||||
|
||||
"get_latest")
|
||||
# Fetch the most recent N results (default to 10)
|
||||
limit=${limit:-10}
|
||||
cat "${RESULT_FILE}" | jq --arg limit "${limit}" 'reverse | limit(($limit|tonumber); .)'
|
||||
;;
|
||||
|
||||
"get_by_status")
|
||||
# Fetch results by status
|
||||
if [ -z "${status}" ]; then
|
||||
send_error "No status provided"
|
||||
fi
|
||||
|
||||
cat "${RESULT_FILE}" | jq --arg status "${status}" '. | map(select(.status == $status))'
|
||||
;;
|
||||
|
||||
"clear")
|
||||
# Clear all results (optional)
|
||||
if [ "${confirm}" = "true" ]; then
|
||||
echo "[]" > "${RESULT_FILE}"
|
||||
jq -n \
|
||||
--arg time "$(date '+%H:%M:%S')" \
|
||||
'{
|
||||
status: "success",
|
||||
message: "Results cleared",
|
||||
timestamp: $time
|
||||
}'
|
||||
else
|
||||
send_error "Confirmation required to clear results"
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
# Default: return all results
|
||||
cat "${RESULT_FILE}"
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Function to URL-decode the input
|
||||
urldecode() {
|
||||
local data="$1"
|
||||
echo -e "$(echo "$data" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;')"
|
||||
}
|
||||
|
||||
# Set content-type for JSON response
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Read the input from POST data
|
||||
read INPUT_DATA
|
||||
|
||||
# Extract the command from the input data (format: command=AT+COMMAND)
|
||||
RAW_COMMAND=$(echo "$INPUT_DATA" | sed 's/command=//g')
|
||||
|
||||
# URL-decode the command
|
||||
COMMAND=$(urldecode "$RAW_COMMAND")
|
||||
|
||||
# Define unique input/output files and AT port
|
||||
INPUT_FILE="/tmp/custom_input_$$.txt"
|
||||
OUTPUT_FILE="/tmp/custom_output_$$.txt"
|
||||
|
||||
# Debug logging
|
||||
DEBUG_LOG="/tmp/debug.log"
|
||||
echo "Starting at_handler script at $(date)" > "$DEBUG_LOG"
|
||||
|
||||
CONFIG_FILE="/etc/quecManager.conf"
|
||||
# Check config file
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "Config file not found: $CONFIG_FILE" >> "$DEBUG_LOG"
|
||||
echo '{"error": "Config file not found"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get AT_PORT with debug logging
|
||||
AT_PORT=$(head -n 1 "$CONFIG_FILE" | cut -d'=' -f2 | tr -d ' \n\r' | sed 's|^dev/||')
|
||||
echo "Raw config line: $(head -n 1 "$CONFIG_FILE")" >> "$DEBUG_LOG"
|
||||
echo "Extracted AT_PORT: '$AT_PORT'" >> "$DEBUG_LOG"
|
||||
|
||||
if [ -z "$AT_PORT" ]; then
|
||||
echo "AT_PORT is empty" >> "$DEBUG_LOG"
|
||||
output_error "Failed to read AT_PORT from config"
|
||||
fi
|
||||
|
||||
# Check if AT_PORT exists
|
||||
if [ ! -c "/dev/$AT_PORT" ]; then
|
||||
echo "AT_PORT device not found: /dev/$AT_PORT" >> "$DEBUG_LOG"
|
||||
echo "Available smd devices:" >> "$DEBUG_LOG"
|
||||
ls -l /dev/smd* >> "$DEBUG_LOG" 2>&1
|
||||
output_error "AT_PORT device not found"
|
||||
fi
|
||||
|
||||
# Write the command directly to the input file
|
||||
echo "$COMMAND" > "$INPUT_FILE"
|
||||
|
||||
# Run the command using atinout
|
||||
atinout "$INPUT_FILE" "/dev/$AT_PORT" "$OUTPUT_FILE"
|
||||
|
||||
# Read the output from output.txt
|
||||
OUTPUT=$(cat "$OUTPUT_FILE")
|
||||
|
||||
# Escape special characters (like newlines and double quotes) for JSON compatibility
|
||||
ESCAPED_OUTPUT=$(echo "$OUTPUT" | sed ':a;N;$!ba;s/\n/\\n/g; s/"/\\"/g')
|
||||
|
||||
# Escape double quotes in the command for JSON compatibility
|
||||
ESCAPED_COMMAND=$(echo "$COMMAND" | sed 's/"/\\"/g')
|
||||
|
||||
# Create the JSON response
|
||||
JSON_RESPONSE=$(printf "{\"command\":\"%s\",\"output\":\"%s\"}" "$ESCAPED_COMMAND" "$ESCAPED_OUTPUT")
|
||||
|
||||
# Return the output as a valid JSON response
|
||||
echo "$JSON_RESPONSE"
|
||||
|
||||
# Clean up temporary files
|
||||
rm "$INPUT_FILE" "$OUTPUT_FILE"
|
||||
45
ipk-source/sdxpinn-quecmanager-beta/root/www/cgi-bin/auth.sh
Normal file
45
ipk-source/sdxpinn-quecmanager-beta/root/www/cgi-bin/auth.sh
Normal file
@@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set Content-Type for CGI script
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Read POST data
|
||||
read POST_DATA
|
||||
|
||||
# Debug log for generated hash
|
||||
DEBUG_LOG = "/tmp/auth.log"
|
||||
|
||||
# Extract the password from POST data (URL encoded)
|
||||
USER="root"
|
||||
INPUT_PASSWORD=$(echo "$POST_DATA" | sed -n 's/^.*password=\([^&]*\).*$/\1/p')
|
||||
|
||||
# URL-decode the password (replace + with space and decode %XX)
|
||||
INPUT_PASSWORD=$(echo "$INPUT_PASSWORD" | sed 's/+/ /g;s/%\(..\)/\\x\1/g' | xargs -0 printf "%b")
|
||||
|
||||
# Extract the hashed password from /etc/shadow for the specified user
|
||||
USER_SHADOW_ENTRY=$(grep "^$USER:" /etc/shadow)
|
||||
|
||||
if [ -z "$USER_SHADOW_ENTRY" ]; then
|
||||
echo '{"state":"failed", "message":"User not found"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract the password hash (it's the second field, colon-separated)
|
||||
USER_HASH=$(echo "$USER_SHADOW_ENTRY" | cut -d: -f2)
|
||||
|
||||
# Extract the salt (MD5 uses the $1$ prefix followed by the salt)
|
||||
SALT=$(echo "$USER_HASH" | cut -d'$' -f3)
|
||||
|
||||
# Generate a hash from the input password using the same salt
|
||||
GENERATED_HASH=$(echo "$INPUT_PASSWORD" | openssl passwd -1 -salt "$SALT" -stdin)
|
||||
|
||||
# Log generated hash for debugging
|
||||
echo "Generated hash: $GENERATED_HASH" >> $DEBUG_LOG
|
||||
|
||||
# Compare the generated hash with the one in the shadow file
|
||||
if [ "$GENERATED_HASH" = "$USER_HASH" ]; then
|
||||
echo '{"state":"success"}'
|
||||
else
|
||||
echo '{"state":"failed"}'
|
||||
fi
|
||||
@@ -0,0 +1,66 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Initialize error flag
|
||||
has_error=false
|
||||
error_message=""
|
||||
|
||||
# Function to append to error message
|
||||
append_error() {
|
||||
if [ -z "$error_message" ]; then
|
||||
error_message="$1"
|
||||
else
|
||||
error_message="$error_message; $1"
|
||||
fi
|
||||
has_error=true
|
||||
}
|
||||
|
||||
# Remove the entire quecmanager directory
|
||||
if [ -d "/etc/quecmanager/apn_profile/" ]; then
|
||||
rm -rf /etc/quecmanager/apn_profile/
|
||||
if [ $? -ne 0 ]; then
|
||||
append_error "Failed to remove quecmanager directory"
|
||||
fi
|
||||
else
|
||||
append_error "quecmanager directory not found"
|
||||
fi
|
||||
|
||||
# Remove the line from rc.local
|
||||
if [ -f "/etc/rc.local" ]; then
|
||||
# Create a temporary file
|
||||
temp_file=$(mktemp)
|
||||
|
||||
# Remove the apnProfiles.sh line and copy to temp file
|
||||
sed '/\/etc\/quecmanager\/apnProfiles.sh/d' /etc/rc.local > "$temp_file"
|
||||
|
||||
# Check if sed command was successful
|
||||
if [ $? -eq 0 ]; then
|
||||
# Replace original file with modified version
|
||||
mv "$temp_file" /etc/rc.local
|
||||
if [ $? -ne 0 ]; then
|
||||
append_error "Failed to update rc.local"
|
||||
fi
|
||||
else
|
||||
append_error "Failed to modify rc.local"
|
||||
rm -f "$temp_file"
|
||||
fi
|
||||
else
|
||||
append_error "rc.local file not found"
|
||||
fi
|
||||
|
||||
# Remove temporary files that might have been created
|
||||
rm -f /tmp/apn_result.txt
|
||||
rm -f /tmp/debug.log
|
||||
rm -f /tmp/inputICCID.txt
|
||||
rm -f /tmp/outputICCID.txt
|
||||
rm -f /tmp/inputAPN.txt
|
||||
rm -f /tmp/outputAPN.txt
|
||||
|
||||
# Return appropriate JSON response
|
||||
if [ "$has_error" = true ]; then
|
||||
echo "{\"status\": \"error\", \"message\": \"$error_message\"}"
|
||||
else
|
||||
echo "{\"status\": \"success\", \"message\": \"APN profiles and configuration successfully removed\"}"
|
||||
fi
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
CONFIG_FILE="/etc/quecmanager/apn_profile/apn_config.txt"
|
||||
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "{}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Read the configuration file
|
||||
iccidProfile1=$(grep "^iccidProfile1=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
apnProfile1=$(grep "^apnProfile1=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
pdpType1=$(grep "^pdpType1=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
iccidProfile2=$(grep "^iccidProfile2=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
apnProfile2=$(grep "^apnProfile2=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
pdpType2=$(grep "^pdpType2=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
|
||||
# Build the JSON response
|
||||
echo "{"
|
||||
|
||||
# Add Profile 1 if it exists
|
||||
if [ -n "$iccidProfile1" ]; then
|
||||
echo " \"profile1\": {"
|
||||
echo " \"iccid\": \"$iccidProfile1\","
|
||||
echo " \"apn\": \"$apnProfile1\","
|
||||
echo " \"pdpType\": \"$pdpType1\""
|
||||
echo " }"
|
||||
|
||||
# Add comma if Profile 2 exists
|
||||
[ -n "$iccidProfile2" ] && echo " ,"
|
||||
fi
|
||||
|
||||
# Add Profile 2 if it exists
|
||||
if [ -n "$iccidProfile2" ]; then
|
||||
echo " \"profile2\": {"
|
||||
echo " \"iccid\": \"$iccidProfile2\","
|
||||
echo " \"apn\": \"$apnProfile2\","
|
||||
echo " \"pdpType\": \"$pdpType2\""
|
||||
echo " }"
|
||||
fi
|
||||
|
||||
echo "}"
|
||||
@@ -0,0 +1,292 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Parse POST data (using busybox compatible method)
|
||||
read -r QUERY_STRING
|
||||
|
||||
# Function to urldecode (busybox compatible version)
|
||||
urldecode() {
|
||||
local value="$1"
|
||||
value="${value//+/ }"
|
||||
value="${value//%/\\x}"
|
||||
printf '%b' "$value"
|
||||
}
|
||||
|
||||
# Extract values from POST data
|
||||
iccidProfile1=$(echo "$QUERY_STRING" | sed -n 's/.*iccidProfile1=\([^&]*\).*/\1/p' | tr -d "'")
|
||||
apnProfile1=$(echo "$QUERY_STRING" | sed -n 's/.*apnProfile1=\([^&]*\).*/\1/p' | tr -d "'")
|
||||
pdpType1=$(echo "$QUERY_STRING" | sed -n 's/.*pdpType1=\([^&]*\).*/\1/p' | tr -d "'")
|
||||
iccidProfile2=$(echo "$QUERY_STRING" | sed -n 's/.*iccidProfile2=\([^&]*\).*/\1/p' | tr -d "'")
|
||||
apnProfile2=$(echo "$QUERY_STRING" | sed -n 's/.*apnProfile2=\([^&]*\).*/\1/p' | tr -d "'")
|
||||
pdpType2=$(echo "$QUERY_STRING" | sed -n 's/.*pdpType2=\([^&]*\).*/\1/p' | tr -d "'")
|
||||
|
||||
# URL decode the values
|
||||
iccidProfile1=$(urldecode "$iccidProfile1")
|
||||
apnProfile1=$(urldecode "$apnProfile1")
|
||||
pdpType1=$(urldecode "$pdpType1")
|
||||
iccidProfile2=$(urldecode "$iccidProfile2")
|
||||
apnProfile2=$(urldecode "$apnProfile2")
|
||||
pdpType2=$(urldecode "$pdpType2")
|
||||
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Validate required first profile
|
||||
if [ -z "$iccidProfile1" ] || [ -z "$apnProfile1" ] || [ -z "$pdpType1" ]; then
|
||||
echo '{"status": "error", "message": "Profile 1 is required"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create directory with proper permissions
|
||||
mkdir -p /etc/quecmanager/apn_profile
|
||||
chmod 755 /etc/quecmanager/apn_profile
|
||||
|
||||
# Create a configuration file to store APN profiles (with proper permissions)
|
||||
cat > /etc/quecmanager/apn_profile/apn_config.txt <<EOF
|
||||
iccidProfile1=${iccidProfile1}
|
||||
apnProfile1=${apnProfile1}
|
||||
pdpType1=${pdpType1}
|
||||
EOF
|
||||
|
||||
# Add second profile only if ICCID is provided
|
||||
if [ -n "$iccidProfile2" ]; then
|
||||
cat >> /etc/quecmanager/apn_profile/apn_config.txt <<EOF
|
||||
iccidProfile2=${iccidProfile2}
|
||||
apnProfile2=${apnProfile2}
|
||||
pdpType2=${pdpType2}
|
||||
EOF
|
||||
fi
|
||||
chmod 644 /etc/quecmanager/apn_profile/apn_config.txt
|
||||
|
||||
# Create the apnProfiles.sh script with proper locking mechanism and logging
|
||||
cat > /etc/quecmanager/apn_profile/apnProfiles.sh <<'EOF'
|
||||
#!/bin/sh
|
||||
|
||||
# Define file paths
|
||||
QUEUE_FILE="/tmp/at_pipe.txt"
|
||||
LOG_FILE="/tmp/apn_profiles.log"
|
||||
[ ! -f "${QUEUE_FILE}" ] && touch "${QUEUE_FILE}"
|
||||
|
||||
# Enhanced logging function with debug level
|
||||
log_message() {
|
||||
local level="$1"
|
||||
local message="$2"
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
echo "${timestamp} - [${level}] ${message}" >> "$LOG_FILE"
|
||||
logger -t apn_profiles "${level}: ${message}"
|
||||
}
|
||||
|
||||
# Check for stale entries and clean them
|
||||
check_and_clean_stale() {
|
||||
local command_type="$1"
|
||||
local wait_count=0
|
||||
|
||||
while [ $wait_count -lt 6 ]; do
|
||||
if grep -q "\"command\":\"${command_type}\"" "$QUEUE_FILE"; then
|
||||
log_message "DEBUG" "Waiting for ${command_type} to clear (attempt ${wait_count})"
|
||||
sleep 1
|
||||
wait_count=$((wait_count + 1))
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
log_message "WARN" "Removing stale ${command_type} entry after ${wait_count}s"
|
||||
sed -i "/\"command\":\"${command_type}\"/d" "$QUEUE_FILE"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Simplified lock handling with debug
|
||||
handle_lock() {
|
||||
log_message "DEBUG" "Checking queue file status before lock"
|
||||
if [ -f "$QUEUE_FILE" ]; then
|
||||
log_message "DEBUG" "Current queue content: $(cat $QUEUE_FILE)"
|
||||
else
|
||||
log_message "DEBUG" "Queue file does not exist, creating it"
|
||||
touch "$QUEUE_FILE"
|
||||
fi
|
||||
|
||||
check_and_clean_stale "FETCH_LOCK"
|
||||
|
||||
log_message "DEBUG" "Adding AT_COMMAND entry to queue"
|
||||
printf '{"command":"AT_COMMAND","pid":"%s","timestamp":"%s"}\n' \
|
||||
"$$" \
|
||||
"$(date '+%H:%M:%S')" >> "$QUEUE_FILE"
|
||||
|
||||
check_and_clean_stale "AT_COMMAND"
|
||||
}
|
||||
|
||||
# Execute AT command without timeout dependency
|
||||
execute_at_command() {
|
||||
local command="$1"
|
||||
local result=""
|
||||
|
||||
log_message "DEBUG" "Executing AT command: ${command}"
|
||||
handle_lock
|
||||
|
||||
# Execute command and capture all output
|
||||
result=$(sms_tool at "$command" -t 4 2>&1)
|
||||
local status=$?
|
||||
|
||||
log_message "DEBUG" "Removing our entry from queue"
|
||||
sed -i "/\"pid\":\"$$\"/d" "$QUEUE_FILE"
|
||||
|
||||
if [ $status -ne 0 ]; then
|
||||
log_message "ERROR" "Command failed with status $status: $command"
|
||||
log_message "ERROR" "Command output: $result"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_message "DEBUG" "Command successful. Output: $result"
|
||||
echo "$result"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Get current ICCID with enhanced debug
|
||||
get_current_iccid() {
|
||||
local result
|
||||
local retry_count=0
|
||||
local max_retries=3
|
||||
|
||||
log_message "INFO" "Attempting to get current ICCID"
|
||||
|
||||
while [ $retry_count -lt $max_retries ]; do
|
||||
log_message "DEBUG" "ICCID attempt ${retry_count}"
|
||||
result=$(execute_at_command "AT+ICCID")
|
||||
local cmd_status=$?
|
||||
|
||||
log_message "DEBUG" "AT+ICCID command returned status: ${cmd_status}"
|
||||
log_message "DEBUG" "AT+ICCID raw output: ${result}"
|
||||
|
||||
if [ $cmd_status -eq 0 ] && echo "$result" | grep -q "+ICCID:"; then
|
||||
local iccid=$(echo "$result" | grep "+ICCID:" | cut -d' ' -f2 | tr -d '[:space:]')
|
||||
log_message "INFO" "Retrieved current ICCID: ${iccid}"
|
||||
echo "${iccid}"
|
||||
return 0
|
||||
else
|
||||
log_message "WARN" "Attempt ${retry_count} failed to get valid ICCID"
|
||||
log_message "WARN" "Result: ${result}"
|
||||
fi
|
||||
|
||||
retry_count=$((retry_count + 1))
|
||||
if [ $retry_count -lt $max_retries ]; then
|
||||
log_message "INFO" "Waiting 2 seconds before retry"
|
||||
sleep 2
|
||||
fi
|
||||
done
|
||||
|
||||
log_message "ERROR" "Failed to get ICCID after $max_retries attempts"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Set APN with modified error handling - removed strict OK check
|
||||
set_apn() {
|
||||
local pdp_type="$1"
|
||||
local apn="$2"
|
||||
local result
|
||||
local retry_count=0
|
||||
local max_retries=3
|
||||
|
||||
if [ -z "$pdp_type" ] || [ -z "$apn" ]; then
|
||||
log_message "ERROR" "Invalid PDP type or APN"
|
||||
return 1
|
||||
fi
|
||||
|
||||
while [ $retry_count -lt $max_retries ]; do
|
||||
result=$(execute_at_command "AT+CGDCONT=1,\"$pdp_type\",\"$apn\";+COPS=2;+COPS=0")
|
||||
if [ $? -eq 0 ]; then
|
||||
log_message "INFO" "Successfully set APN: $apn with PDP type: $pdp_type"
|
||||
return 0
|
||||
fi
|
||||
retry_count=$((retry_count + 1))
|
||||
[ $retry_count -lt $max_retries ] && sleep 2
|
||||
done
|
||||
|
||||
log_message "ERROR" "Failed to set APN: $apn after $max_retries attempts"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Load configuration
|
||||
if [ -f /etc/quecmanager/apn_profile/apn_config.txt ]; then
|
||||
. /etc/quecmanager/apn_profile/apn_config.txt
|
||||
log_message "INFO" "Loaded configuration - Profile1 ICCID: ${iccidProfile1}, Profile2 ICCID: ${iccidProfile2:-none}"
|
||||
else
|
||||
log_message "ERROR" "Configuration file not found"
|
||||
echo "Configuration file not found" > /tmp/apn_result.txt
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get current ICCID and trim any whitespace
|
||||
current_iccid=$(get_current_iccid | tr -d '[:space:]')
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
log_message "ERROR" "Failed to get current ICCID"
|
||||
echo "Failed to get current ICCID" > /tmp/apn_result.txt
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Trim any whitespace from profile ICCIDs
|
||||
iccidProfile1=$(echo "${iccidProfile1}" | tr -d '[:space:]')
|
||||
[ -n "$iccidProfile2" ] && iccidProfile2=$(echo "${iccidProfile2}" | tr -d '[:space:]')
|
||||
|
||||
# Log the comparison values
|
||||
log_message "INFO" "Comparing ICCIDs:"
|
||||
log_message "INFO" "Current ICCID: ${current_iccid}"
|
||||
log_message "INFO" "Profile1 ICCID: ${iccidProfile1}"
|
||||
[ -n "$iccidProfile2" ] && log_message "INFO" "Profile2 ICCID: ${iccidProfile2}"
|
||||
|
||||
# Match ICCID and apply corresponding profile
|
||||
if [ "${current_iccid}" = "${iccidProfile1}" ]; then
|
||||
log_message "INFO" "Matched with Profile1, applying settings..."
|
||||
if set_apn "$pdpType1" "$apnProfile1"; then
|
||||
echo "APN set successfully" > /tmp/apn_result.txt
|
||||
else
|
||||
echo "Failed to set APN" > /tmp/apn_result.txt
|
||||
fi
|
||||
elif [ -n "$iccidProfile2" ] && [ "${current_iccid}" = "${iccidProfile2}" ]; then
|
||||
log_message "INFO" "Matched with Profile2, applying settings..."
|
||||
if set_apn "$pdpType2" "$apnProfile2"; then
|
||||
echo "APN set successfully" > /tmp/apn_result.txt
|
||||
else
|
||||
echo "Failed to set APN" > /tmp/apn_result.txt
|
||||
fi
|
||||
else
|
||||
log_message "WARN" "No matching ICCID profile found"
|
||||
echo "No matching ICCID profile found" > /tmp/apn_result.txt
|
||||
fi
|
||||
EOF
|
||||
|
||||
# Make the script executable
|
||||
chmod 755 /etc/quecmanager/apn_profile/apnProfiles.sh
|
||||
|
||||
# Add to rc.local if not already present
|
||||
if ! grep -q "^[^#]*\/etc\/quecmanager\/apn_profile\/apnProfiles.sh" /etc/rc.local; then
|
||||
sed -i '/^exit 0/i /etc/quecmanager/apn_profile/apnProfiles.sh' /etc/rc.local
|
||||
fi
|
||||
|
||||
# Run the script immediately
|
||||
/etc/quecmanager/apn_profile/apnProfiles.sh
|
||||
|
||||
# Check the result
|
||||
if [ -f /tmp/apn_result.txt ]; then
|
||||
result=$(cat /tmp/apn_result.txt)
|
||||
rm -f /tmp/apn_result.txt
|
||||
case "$result" in
|
||||
"APN set successfully")
|
||||
echo '{"status": "success", "message": "APN profiles saved and applied successfully"}'
|
||||
;;
|
||||
"No matching ICCID profile found")
|
||||
echo '{"status": "warning", "message": "APN profiles saved but no matching ICCID found"}'
|
||||
;;
|
||||
"Configuration file not found")
|
||||
echo '{"status": "error", "message": "Configuration file not found"}'
|
||||
;;
|
||||
"Failed to get current ICCID")
|
||||
echo '{"status": "error", "message": "Failed to get current ICCID"}'
|
||||
;;
|
||||
*)
|
||||
echo '{"status": "error", "message": "APN profiles saved but failed to apply"}'
|
||||
;;
|
||||
esac
|
||||
else
|
||||
echo '{"status": "error", "message": "Something went wrong while processing APN profiles"}'
|
||||
fi
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
# handle_sms.sh - CGI script to handle SMS web requests
|
||||
# Content type declaration for CGI
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Check if atinout and jq are installed
|
||||
if ! command -v atinout &> /dev/null || ! command -v jq &> /dev/null; then
|
||||
echo '{"error": "Required tools (atinout or jq) are not installed"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if the device exists
|
||||
if [ ! -c "/dev/smd7" ]; then
|
||||
echo '{"error": "Device /dev/smd7 not found"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# # Fetch all SMS messages and update the JSON file
|
||||
# Disabled until the atinout bug is fixed
|
||||
# if ! echo "AT+CMGL=\"ALL\"" | atinout - /dev/smd7 - | jq -R -s '
|
||||
# split("\n") |
|
||||
# map(select(length > 0)) |
|
||||
# map(
|
||||
# select(startswith("+CMGL:") or (. != "OK" and . != "ERROR"))
|
||||
# ) |
|
||||
# {messages: .}
|
||||
# ' > /tmp/sms_inbox.json; then
|
||||
# echo '{"error": "Failed to fetch SMS messages"}'
|
||||
# exit 1
|
||||
# fi
|
||||
|
||||
# Return the contents of the JSON file
|
||||
if [ -f "/tmp/sms_inbox.json" ]; then
|
||||
cat /tmp/sms_inbox.json
|
||||
else
|
||||
echo '{"error": "SMS inbox file not found"}'
|
||||
fi
|
||||
@@ -0,0 +1,66 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Initialize error flag
|
||||
has_error=false
|
||||
error_message=""
|
||||
|
||||
# Function to append to error message
|
||||
append_error() {
|
||||
if [ -z "$error_message" ]; then
|
||||
error_message="$1"
|
||||
else
|
||||
error_message="$error_message; $1"
|
||||
fi
|
||||
has_error=true
|
||||
}
|
||||
|
||||
# Remove the entire quecmanager directory
|
||||
if [ -d "/etc/quecmanager/imei_profile/" ]; then
|
||||
rm -rf /etc/quecmanager/imei_profile/
|
||||
if [ $? -ne 0 ]; then
|
||||
append_error "Failed to remove quecmanager directory"
|
||||
fi
|
||||
else
|
||||
append_error "quecmanager directory not found"
|
||||
fi
|
||||
|
||||
# Remove the line from rc.local
|
||||
if [ -f "/etc/rc.local" ]; then
|
||||
# Create a temporary file
|
||||
temp_file=$(mktemp)
|
||||
|
||||
# Remove the imeiProfiles.sh line and copy to temp file
|
||||
sed '/\/etc\/quecmanager\/imeiProfiles.sh/d' /etc/rc.local > "$temp_file"
|
||||
|
||||
# Check if sed command was successful
|
||||
if [ $? -eq 0 ]; then
|
||||
# Replace original file with modified version
|
||||
mv "$temp_file" /etc/rc.local
|
||||
if [ $? -ne 0 ]; then
|
||||
append_error "Failed to update rc.local"
|
||||
fi
|
||||
else
|
||||
append_error "Failed to modify rc.local"
|
||||
rm -f "$temp_file"
|
||||
fi
|
||||
else
|
||||
append_error "rc.local file not found"
|
||||
fi
|
||||
|
||||
# Remove temporary files that might have been created
|
||||
rm -f /tmp/imei_result.txt
|
||||
rm -f /tmp/debug.log
|
||||
rm -f /tmp/inputICCID.txt
|
||||
rm -f /tmp/outputICCID.txt
|
||||
rm -f /tmp/inputIMEI.txt
|
||||
rm -f /tmp/outputIMEI.txt
|
||||
|
||||
# Return appropriate JSON response
|
||||
if [ "$has_error" = true ]; then
|
||||
echo "{\"status\": \"error\", \"message\": \"$error_message\"}"
|
||||
else
|
||||
echo "{\"status\": \"success\", \"message\": \"IMEI profiles and configuration successfully removed\"}"
|
||||
fi
|
||||
@@ -0,0 +1,39 @@
|
||||
#!/bin/sh
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
CONFIG_FILE="/etc/quecmanager/imei_profile/imei_config.txt"
|
||||
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "{}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Read the configuration file
|
||||
iccidProfile1=$(grep "^iccidProfile1=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
imeiProfile1=$(grep "^imeiProfile1=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
iccidProfile2=$(grep "^iccidProfile2=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
imeiProfile2=$(grep "^imeiProfile2=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
|
||||
# Build the JSON response
|
||||
echo "{"
|
||||
|
||||
# Add Profile 1 if it exists
|
||||
if [ -n "$iccidProfile1" ]; then
|
||||
echo " \"profile1\": {"
|
||||
echo " \"iccid\": \"$iccidProfile1\","
|
||||
echo " \"imei\": \"$imeiProfile1\""
|
||||
echo " }"
|
||||
# Add comma if Profile 2 exists
|
||||
[ -n "$iccidProfile2" ] && echo " ,"
|
||||
fi
|
||||
|
||||
# Add Profile 2 if it exists
|
||||
if [ -n "$iccidProfile2" ]; then
|
||||
echo " \"profile2\": {"
|
||||
echo " \"iccid\": \"$iccidProfile2\","
|
||||
echo " \"imei\": \"$imeiProfile2\""
|
||||
echo " }"
|
||||
fi
|
||||
|
||||
echo "}"
|
||||
@@ -0,0 +1,333 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Parse POST data (using busybox compatible method)
|
||||
read -r QUERY_STRING
|
||||
|
||||
# Function to urldecode (busybox compatible version)
|
||||
urldecode() {
|
||||
local value="$1"
|
||||
value="${value//+/ }"
|
||||
value="${value//%/\\x}"
|
||||
printf '%b' "$value"
|
||||
}
|
||||
|
||||
# Extract values from POST data
|
||||
iccidProfile1=$(echo "$QUERY_STRING" | sed -n 's/.*iccidProfile1=\([^&]*\).*/\1/p' | tr -d "'")
|
||||
imeiProfile1=$(echo "$QUERY_STRING" | sed -n 's/.*imeiProfile1=\([^&]*\).*/\1/p' | tr -d "'")
|
||||
iccidProfile2=$(echo "$QUERY_STRING" | sed -n 's/.*iccidProfile2=\([^&]*\).*/\1/p' | tr -d "'")
|
||||
imeiProfile2=$(echo "$QUERY_STRING" | sed -n 's/.*imeiProfile2=\([^&]*\).*/\1/p' | tr -d "'")
|
||||
|
||||
# URL decode the values
|
||||
iccidProfile1=$(urldecode "$iccidProfile1")
|
||||
imeiProfile1=$(urldecode "$imeiProfile1")
|
||||
iccidProfile2=$(urldecode "$iccidProfile2")
|
||||
imeiProfile2=$(urldecode "$imeiProfile2")
|
||||
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Validate required first profile
|
||||
if [ -z "$iccidProfile1" ] || [ -z "$imeiProfile1" ]; then
|
||||
echo '{"status": "error", "message": "Profile 1 is required"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create directory with proper permissions
|
||||
mkdir -p /etc/quecmanager/imei_profile
|
||||
chmod 755 /etc/quecmanager/imei_profile
|
||||
|
||||
# Create a configuration file to store IMEI profiles
|
||||
cat > /etc/quecmanager/imei_profile/imei_config.txt <<EOF
|
||||
iccidProfile1=${iccidProfile1}
|
||||
imeiProfile1=${imeiProfile1}
|
||||
EOF
|
||||
|
||||
# Add second profile only if ICCID is provided
|
||||
if [ -n "$iccidProfile2" ]; then
|
||||
cat >> /etc/quecmanager/imei_profile/imei_config.txt <<EOF
|
||||
iccidProfile2=${iccidProfile2}
|
||||
imeiProfile2=${imeiProfile2}
|
||||
EOF
|
||||
fi
|
||||
chmod 644 /etc/quecmanager/imei_profile/imei_config.txt
|
||||
|
||||
# Create the imeiProfiles.sh script with proper locking mechanism and logging
|
||||
cat > /etc/quecmanager/imei_profile/imeiProfiles.sh <<'EOF'
|
||||
#!/bin/sh
|
||||
|
||||
# Define file paths
|
||||
QUEUE_FILE="/tmp/at_pipe.txt"
|
||||
LOG_FILE="/tmp/imei_profiles.log"
|
||||
[ ! -f "${QUEUE_FILE}" ] && touch "${QUEUE_FILE}"
|
||||
|
||||
# Enhanced logging function with debug level
|
||||
log_message() {
|
||||
local level="$1"
|
||||
local message="$2"
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
echo "${timestamp} - [${level}] ${message}" >> "$LOG_FILE"
|
||||
logger -t imei_profiles "${level}: ${message}"
|
||||
}
|
||||
|
||||
# Check for stale entries and clean them
|
||||
check_and_clean_stale() {
|
||||
local command_type="$1"
|
||||
local wait_count=0
|
||||
|
||||
while [ $wait_count -lt 6 ]; do
|
||||
if grep -q "\"command\":\"${command_type}\"" "$QUEUE_FILE"; then
|
||||
log_message "DEBUG" "Waiting for ${command_type} to clear (attempt ${wait_count})"
|
||||
sleep 1
|
||||
wait_count=$((wait_count + 1))
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
log_message "WARN" "Removing stale ${command_type} entry after ${wait_count}s"
|
||||
sed -i "/\"command\":\"${command_type}\"/d" "$QUEUE_FILE"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Simplified lock handling with debug
|
||||
handle_lock() {
|
||||
log_message "DEBUG" "Checking queue file status before lock"
|
||||
if [ -f "$QUEUE_FILE" ]; then
|
||||
log_message "DEBUG" "Current queue content: $(cat $QUEUE_FILE)"
|
||||
else
|
||||
log_message "DEBUG" "Queue file does not exist, creating it"
|
||||
touch "$QUEUE_FILE"
|
||||
fi
|
||||
|
||||
check_and_clean_stale "FETCH_LOCK"
|
||||
|
||||
log_message "DEBUG" "Adding AT_COMMAND entry to queue"
|
||||
printf '{"command":"AT_COMMAND","pid":"%s","timestamp":"%s"}\n' \
|
||||
"$$" \
|
||||
"$(date '+%H:%M:%S')" >> "$QUEUE_FILE"
|
||||
|
||||
check_and_clean_stale "AT_COMMAND"
|
||||
}
|
||||
|
||||
# Execute AT command without timeout dependency
|
||||
execute_at_command() {
|
||||
local command="$1"
|
||||
local result=""
|
||||
|
||||
log_message "DEBUG" "Executing AT command: ${command}"
|
||||
handle_lock
|
||||
|
||||
# Execute command and capture all output
|
||||
result=$(sms_tool at "$command" -t 4 2>&1)
|
||||
local status=$?
|
||||
|
||||
log_message "DEBUG" "Removing our entry from queue"
|
||||
sed -i "/\"pid\":\"$$\"/d" "$QUEUE_FILE"
|
||||
|
||||
if [ $status -ne 0 ]; then
|
||||
log_message "ERROR" "Command failed with status $status: $command"
|
||||
log_message "ERROR" "Command output: $result"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_message "DEBUG" "Command successful. Output: $result"
|
||||
echo "$result"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Get current ICCID with enhanced debug
|
||||
get_current_iccid() {
|
||||
local result
|
||||
local retry_count=0
|
||||
local max_retries=3
|
||||
|
||||
log_message "INFO" "Attempting to get current ICCID"
|
||||
|
||||
while [ $retry_count -lt $max_retries ]; do
|
||||
log_message "DEBUG" "ICCID attempt ${retry_count}"
|
||||
result=$(execute_at_command "AT+ICCID")
|
||||
local cmd_status=$?
|
||||
|
||||
log_message "DEBUG" "AT+ICCID command returned status: ${cmd_status}"
|
||||
log_message "DEBUG" "AT+ICCID raw output: ${result}"
|
||||
|
||||
if [ $cmd_status -eq 0 ] && echo "$result" | grep -q "+ICCID:"; then
|
||||
local iccid=$(echo "$result" | grep "+ICCID:" | cut -d' ' -f2 | tr -d '[:space:]')
|
||||
log_message "INFO" "Retrieved current ICCID: ${iccid}"
|
||||
echo "${iccid}"
|
||||
return 0
|
||||
else
|
||||
log_message "WARN" "Attempt ${retry_count} failed to get valid ICCID"
|
||||
log_message "WARN" "Result: ${result}"
|
||||
fi
|
||||
|
||||
retry_count=$((retry_count + 1))
|
||||
if [ $retry_count -lt $max_retries ]; then
|
||||
log_message "INFO" "Waiting 2 seconds before retry"
|
||||
sleep 2
|
||||
fi
|
||||
done
|
||||
|
||||
log_message "ERROR" "Failed to get ICCID after $max_retries attempts"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Get current IMEI with enhanced debug
|
||||
get_current_imei() {
|
||||
local result
|
||||
local retry_count=0
|
||||
local max_retries=3
|
||||
|
||||
log_message "INFO" "Attempting to get current IMEI"
|
||||
|
||||
while [ $retry_count -lt $max_retries ]; do
|
||||
log_message "DEBUG" "IMEI attempt ${retry_count}"
|
||||
result=$(execute_at_command "AT+CGSN")
|
||||
local cmd_status=$?
|
||||
|
||||
log_message "DEBUG" "AT+CGSN command returned status: ${cmd_status}"
|
||||
log_message "DEBUG" "AT+CGSN raw output: ${result}"
|
||||
|
||||
if [ $cmd_status -eq 0 ]; then
|
||||
local imei=$(echo "$result" | grep -v "AT+CGSN" | grep -v "OK" | tr -d '\r\n[:space:]')
|
||||
if [ -n "$imei" ]; then
|
||||
log_message "INFO" "Retrieved current IMEI: ${imei}"
|
||||
echo "${imei}"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
log_message "WARN" "Attempt ${retry_count} failed to get valid IMEI"
|
||||
retry_count=$((retry_count + 1))
|
||||
[ $retry_count -lt $max_retries ] && sleep 2
|
||||
done
|
||||
|
||||
log_message "ERROR" "Failed to get IMEI after $max_retries attempts"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Set IMEI with enhanced debug
|
||||
set_imei() {
|
||||
local imei="$1"
|
||||
local retry_count=0
|
||||
local max_retries=3
|
||||
|
||||
log_message "INFO" "Attempting to set IMEI: ${imei}"
|
||||
|
||||
while [ $retry_count -lt $max_retries ]; do
|
||||
log_message "DEBUG" "IMEI set attempt ${retry_count}"
|
||||
result=$(execute_at_command "AT+EGMR=1,7,\"$imei\";+QPOWD=1")
|
||||
local cmd_status=$?
|
||||
|
||||
log_message "DEBUG" "AT+EGMR command returned status: ${cmd_status}"
|
||||
log_message "DEBUG" "AT+EGMR raw output: ${result}"
|
||||
|
||||
if [ $cmd_status -eq 0 ] && echo "$result" | grep -q "OK"; then
|
||||
log_message "INFO" "Successfully set IMEI: ${imei}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
retry_count=$((retry_count + 1))
|
||||
[ $retry_count -lt $max_retries ] && sleep 2
|
||||
done
|
||||
|
||||
log_message "ERROR" "Failed to set IMEI after $max_retries attempts"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Load configuration
|
||||
if [ -f /etc/quecmanager/imei_profile/imei_config.txt ]; then
|
||||
. /etc/quecmanager/imei_profile/imei_config.txt
|
||||
log_message "INFO" "Loaded configuration - Profile1 ICCID: ${iccidProfile1}, IMEI: ${imeiProfile1}"
|
||||
[ -n "$iccidProfile2" ] && log_message "INFO" "Profile2 ICCID: ${iccidProfile2}, IMEI: ${imeiProfile2}"
|
||||
else
|
||||
log_message "ERROR" "Configuration file not found"
|
||||
echo "Configuration file not found" > /tmp/imei_result.txt
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get current ICCID and IMEI
|
||||
current_iccid=$(get_current_iccid)
|
||||
current_imei=$(get_current_imei)
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
log_message "ERROR" "Failed to get current ICCID or IMEI"
|
||||
echo "Failed to get current ICCID or IMEI" > /tmp/imei_result.txt
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_message "INFO" "Current ICCID: ${current_iccid}"
|
||||
log_message "INFO" "Current IMEI: ${current_imei}"
|
||||
|
||||
# Match ICCID and apply corresponding profile
|
||||
if [ "${current_iccid}" = "${iccidProfile1}" ]; then
|
||||
log_message "INFO" "Matched with Profile1"
|
||||
if [ "${current_imei}" != "${imeiProfile1}" ]; then
|
||||
log_message "INFO" "IMEI needs updating for Profile1"
|
||||
if set_imei "${imeiProfile1}"; then
|
||||
echo "IMEI set successfully" > /tmp/imei_result.txt
|
||||
else
|
||||
echo "Failed to set IMEI" > /tmp/imei_result.txt
|
||||
fi
|
||||
else
|
||||
log_message "INFO" "IMEI already matches Profile1"
|
||||
echo "IMEI already correct" > /tmp/imei_result.txt
|
||||
fi
|
||||
elif [ -n "${iccidProfile2}" ] && [ "${current_iccid}" = "${iccidProfile2}" ]; then
|
||||
log_message "INFO" "Matched with Profile2"
|
||||
if [ "${current_imei}" != "${imeiProfile2}" ]; then
|
||||
log_message "INFO" "IMEI needs updating for Profile2"
|
||||
if set_imei "${imeiProfile2}"; then
|
||||
echo "IMEI set successfully" > /tmp/imei_result.txt
|
||||
else
|
||||
echo "Failed to set IMEI" > /tmp/imei_result.txt
|
||||
fi
|
||||
else
|
||||
log_message "INFO" "IMEI already matches Profile2"
|
||||
echo "IMEI already correct" > /tmp/imei_result.txt
|
||||
fi
|
||||
else
|
||||
log_message "WARN" "No matching ICCID profile found"
|
||||
echo "No matching ICCID profile found" > /tmp/imei_result.txt
|
||||
fi
|
||||
EOF
|
||||
|
||||
# Make the script executable
|
||||
chmod 755 /etc/quecmanager/imei_profile/imeiProfiles.sh
|
||||
|
||||
# Add to rc.local if not already present
|
||||
if ! grep -q "^[^#]*\/etc\/quecmanager\/imei_profile\/imeiProfiles.sh" /etc/rc.local; then
|
||||
sed -i '/^exit 0/i /etc/quecmanager/imei_profile/imeiProfiles.sh' /etc/rc.local
|
||||
fi
|
||||
|
||||
# Run the script immediately
|
||||
/etc/quecmanager/imei_profile/imeiProfiles.sh
|
||||
|
||||
# Check the result
|
||||
if [ -f /tmp/imei_result.txt ]; then
|
||||
result=$(cat /tmp/imei_result.txt)
|
||||
rm -f /tmp/imei_result.txt
|
||||
|
||||
case "$result" in
|
||||
"IMEI set successfully")
|
||||
echo '{"status": "success", "message": "IMEI profiles saved and applied successfully"}'
|
||||
;;
|
||||
"IMEI already correct")
|
||||
echo '{"status": "success", "message": "IMEI profiles saved, no changes needed"}'
|
||||
;;
|
||||
"No matching ICCID profile found")
|
||||
echo '{"status": "warning", "message": "IMEI profiles saved but no matching ICCID found"}'
|
||||
;;
|
||||
"Configuration file not found")
|
||||
echo '{"status": "error", "message": "Configuration file not found"}'
|
||||
;;
|
||||
"Failed to get current ICCID or IMEI")
|
||||
echo '{"status": "error", "message": "Failed to get current ICCID or IMEI"}'
|
||||
;;
|
||||
*)
|
||||
echo '{"status": "error", "message": "IMEI profiles saved but failed to apply"}'
|
||||
;;
|
||||
esac
|
||||
else
|
||||
echo '{"status": "error", "message": "Something went wrong while processing IMEI profiles"}'
|
||||
fi
|
||||
@@ -0,0 +1,201 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Configuration
|
||||
CONFIG_FILE="/etc/cell_lock_schedule.conf"
|
||||
STATUS_FILE="/tmp/cell_lock_status"
|
||||
CELL_LOCK_SCRIPT="/usr/bin/set_cell_lock.sh"
|
||||
|
||||
# Function to create set_cell_lock.sh script
|
||||
create_cell_lock_script() {
|
||||
# Only create the script if it doesn't exist
|
||||
if [ ! -f "$CELL_LOCK_SCRIPT" ]; then
|
||||
cat >"$CELL_LOCK_SCRIPT" <<'EOL'
|
||||
#!/bin/sh
|
||||
ACTION=$1
|
||||
LTE_PARAMS=$2
|
||||
NR5G_PARAMS=$3
|
||||
|
||||
case "$ACTION" in
|
||||
enable)
|
||||
# Enable LTE lock if parameters exist
|
||||
if [ -n "$LTE_PARAMS" ]; then
|
||||
echo "AT+QNWLOCK=\"common/4g\",$LTE_PARAMS" | atinout - /dev/smd11 -
|
||||
fi
|
||||
|
||||
# Enable NR5G lock if parameters exist
|
||||
if [ -n "$NR5G_PARAMS" ]; then
|
||||
echo "AT+QNWLOCK=\"common/5g\",$NR5G_PARAMS" | atinout - /dev/smd11 -
|
||||
fi
|
||||
;;
|
||||
|
||||
disable)
|
||||
# Disable LTE lock
|
||||
echo 'AT+QNWLOCK="common/4g",0' | atinout - /dev/smd11 -
|
||||
|
||||
# Disable NR5G lock
|
||||
echo 'AT+QNWLOCK="common/5g",0' | atinout - /dev/smd11 -
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Invalid action"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Restart network registration to apply changes
|
||||
echo "AT+COPS=2" | atinout - /dev/smd11 -
|
||||
sleep 2
|
||||
echo "AT+COPS=0" | atinout - /dev/smd11 -
|
||||
exit 0
|
||||
EOL
|
||||
|
||||
# Make the script executable
|
||||
chmod +x "$CELL_LOCK_SCRIPT"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to remove set_cell_lock.sh script
|
||||
remove_cell_lock_script() {
|
||||
if [ -f "$CELL_LOCK_SCRIPT" ]; then
|
||||
rm "$CELL_LOCK_SCRIPT"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to urldecode
|
||||
urldecode() {
|
||||
echo -e "$(echo "$1" | sed 's/+/ /g;s/%\([0-9A-F][0-9A-F]\)/\\x\1/g')"
|
||||
}
|
||||
|
||||
# Function to convert HH:MM to cron format
|
||||
convert_to_cron_time() {
|
||||
echo "$1" | awk -F: '{print $2, $1}'
|
||||
}
|
||||
|
||||
# Function to save configuration
|
||||
save_config() {
|
||||
echo "START_TIME=$1" >"$CONFIG_FILE"
|
||||
echo "END_TIME=$2" >>"$CONFIG_FILE"
|
||||
echo "ENABLED=1" >>"$CONFIG_FILE"
|
||||
}
|
||||
|
||||
# Function to disable scheduling
|
||||
disable_scheduling() {
|
||||
if [ -f "$CONFIG_FILE" ]; then
|
||||
sed -i 's/ENABLED=1/ENABLED=0/' "$CONFIG_FILE"
|
||||
fi
|
||||
# Remove any existing cron jobs
|
||||
crontab -l | grep -v "set_cell_lock.sh" | crontab -
|
||||
# Remove the set_cell_lock.sh script
|
||||
remove_cell_lock_script
|
||||
}
|
||||
|
||||
# Function to get current status
|
||||
get_status() {
|
||||
if [ -f "$CONFIG_FILE" ]; then
|
||||
ENABLED=$(grep "ENABLED=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
START_TIME=$(grep "START_TIME=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
END_TIME=$(grep "END_TIME=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
|
||||
echo "Status: 200 OK"
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
echo "{\"enabled\":$ENABLED,\"start_time\":\"$START_TIME\",\"end_time\":\"$END_TIME\"}"
|
||||
else
|
||||
echo "Status: 200 OK"
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
echo "{\"enabled\":0,\"start_time\":\"\",\"end_time\":\"\"}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Handle POST requests
|
||||
if [ "$REQUEST_METHOD" = "POST" ]; then
|
||||
# Read POST data
|
||||
read -r POST_DATA
|
||||
|
||||
# Check if disabling is requested
|
||||
echo "$POST_DATA" | grep -q "disable=true"
|
||||
if [ $? -eq 0 ]; then
|
||||
disable_scheduling
|
||||
echo "Status: 200 OK"
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
echo "{\"status\":\"success\",\"message\":\"Scheduling disabled\"}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Extract start and end times
|
||||
START_TIME=$(echo "$POST_DATA" | grep -o 'start_time=[^&]*' | cut -d'=' -f2)
|
||||
END_TIME=$(echo "$POST_DATA" | grep -o 'end_time=[^&]*' | cut -d'=' -f2)
|
||||
|
||||
# Decode times
|
||||
START_TIME=$(urldecode "$START_TIME")
|
||||
END_TIME=$(urldecode "$END_TIME")
|
||||
|
||||
# Validate times
|
||||
if [ -z "$START_TIME" ] || [ -z "$END_TIME" ]; then
|
||||
echo "Status: 400 Bad Request"
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
echo "{\"error\":\"Missing start or end time\"}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create set_cell_lock.sh script
|
||||
create_cell_lock_script
|
||||
|
||||
# Convert times to cron format
|
||||
CRON_START=$(convert_to_cron_time "$START_TIME")
|
||||
CRON_END=$(convert_to_cron_time "$END_TIME")
|
||||
|
||||
# Save configuration
|
||||
save_config "$START_TIME" "$END_TIME"
|
||||
|
||||
# Check current cell lock status and get parameters
|
||||
LTE_STATUS=$(echo 'AT+QNWLOCK="common/4g"' | atinout - /dev/smd11 -)
|
||||
NR5G_STATUS=$(echo 'AT+QNWLOCK="common/5g"' | atinout - /dev/smd11 -)
|
||||
|
||||
# Extract LTE parameters if locked
|
||||
LTE_PARAMS=$(echo "$LTE_STATUS" | grep -o '"common/4g",[^[:space:]]*' | cut -d',' -f2-)
|
||||
NR5G_PARAMS=$(echo "$NR5G_STATUS" | grep -o '"common/5g",[^[:space:]]*' | cut -d',' -f2-)
|
||||
|
||||
# Create temporary file for new crontab
|
||||
TEMP_CRON=$(mktemp)
|
||||
|
||||
# Get existing crontab entries (excluding our script)
|
||||
crontab -l 2>/dev/null | grep -v "set_cell_lock.sh" >"$TEMP_CRON"
|
||||
|
||||
# Add new entries
|
||||
echo "$CRON_START * * * $CELL_LOCK_SCRIPT enable \"$LTE_PARAMS\" \"$NR5G_PARAMS\"" >>"$TEMP_CRON"
|
||||
echo "$CRON_END * * * $CELL_LOCK_SCRIPT disable" >>"$TEMP_CRON"
|
||||
|
||||
# Install new crontab
|
||||
crontab "$TEMP_CRON"
|
||||
rm "$TEMP_CRON"
|
||||
|
||||
echo "Status: 200 OK"
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
echo "{\"status\":\"success\",\"message\":\"Scheduling enabled\"}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Parse query string for GET requests
|
||||
if [ "$REQUEST_METHOD" = "GET" ]; then
|
||||
QUERY_STRING=$(echo "$QUERY_STRING" | sed 's/&/\n/g')
|
||||
for param in $QUERY_STRING; do
|
||||
case "$param" in
|
||||
status=*)
|
||||
get_status
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
# If no valid request is made
|
||||
echo "Status: 400 Bad Request"
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
echo "{\"error\":\"Invalid request\"}"
|
||||
exit 1
|
||||
@@ -0,0 +1,50 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set content type
|
||||
printf "Content-Type: application/json\n\n"
|
||||
|
||||
# URL decode function
|
||||
urldecode() {
|
||||
echo "$*" | sed 's/+/ /g;s/%\([0-9A-F][0-9A-F]\)/\\\\x\1/g' | xargs -0 printf '%b'
|
||||
}
|
||||
|
||||
# Extract indexes from query string
|
||||
query=$(echo "$QUERY_STRING" | grep -o 'indexes=[^&]*' | cut -d= -f2)
|
||||
indexes=$(urldecode "$query")
|
||||
|
||||
# Function to output JSON response
|
||||
send_json() {
|
||||
printf '{"status":"%s","message":"%s"}\n' "$1" "$2"
|
||||
}
|
||||
|
||||
# Validate input
|
||||
if [ -z "$indexes" ]; then
|
||||
send_json "error" "No indexes provided"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Initialize counters
|
||||
success=0
|
||||
failure=0
|
||||
|
||||
# Process each index
|
||||
echo "$indexes" | tr ',' '\n' | while read -r index; do
|
||||
if [ -n "$index" ] && [ "$index" -eq "$index" ] 2>/dev/null; then
|
||||
if sms_tool delete "$index" 2>/dev/null; then
|
||||
success=$((success + 1))
|
||||
else
|
||||
failure=$((failure + 1))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Send response
|
||||
if [ $success -gt 0 ]; then
|
||||
if [ $failure -eq 0 ]; then
|
||||
send_json "success" "Successfully deleted $success message(s)"
|
||||
else
|
||||
send_json "partial" "Deleted $success message(s), failed to delete $failure message(s)"
|
||||
fi
|
||||
else
|
||||
send_json "error" "Failed to delete messages"
|
||||
fi
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
printf "Content-type: application/json\r\n\r\n"
|
||||
|
||||
# Execute the command and return the JSON response
|
||||
if command -v sms_tool > /dev/null 2>&1; then
|
||||
sms_tool -j recv
|
||||
else
|
||||
printf '{"error": "sms_tool not found"}\n'
|
||||
fi
|
||||
@@ -0,0 +1,57 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Content-Type: application/json"
|
||||
echo "Cache-Control: no-cache"
|
||||
echo ""
|
||||
|
||||
# Function to URL decode the string
|
||||
urldecode() {
|
||||
local url_encoded="${1//+/ }"
|
||||
printf '%b' "${url_encoded//%/\\x}"
|
||||
}
|
||||
|
||||
# Function to escape JSON string
|
||||
escape_json() {
|
||||
printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\n/\\n/g; s/\r/\\r/g; s/\t/\\t/g'
|
||||
}
|
||||
|
||||
# Read POST data
|
||||
read -r QUERY_STRING
|
||||
|
||||
# Extract phone and message from POST data
|
||||
phone=$(echo "$QUERY_STRING" | grep -o 'phone=[^&]*' | cut -d= -f2)
|
||||
message=$(echo "$QUERY_STRING" | grep -o 'message=[^&]*' | cut -d= -f2)
|
||||
|
||||
# URL decode the message
|
||||
decoded_message=$(urldecode "$message")
|
||||
|
||||
# Validate inputs
|
||||
if [ -z "$phone" ] || [ -z "$message" ]; then
|
||||
echo '{"success":false,"error":"Phone number and message are required"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Validate phone number (only numbers allowed)
|
||||
if ! echo "$phone" | grep -q '^[0-9]\+$'; then
|
||||
echo '{"success":false,"error":"Invalid phone number format"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Try to send SMS and capture output
|
||||
result=$(sms_tool send "$phone" "$decoded_message" 2>&1)
|
||||
escaped_result=$(escape_json "$result")
|
||||
|
||||
# Check if SMS was sent successfully by looking for "sms sent sucessfully"
|
||||
if echo "$result" | grep -q "sms sent sucessfully"; then
|
||||
# Extract the message ID if present
|
||||
message_id=$(echo "$result" | grep -o '[0-9]*$')
|
||||
echo "{\"success\":true,\"message\":\"SMS sent successfully\",\"messageId\":\"$message_id\",\"raw\":\"$escaped_result\"}"
|
||||
elif echo "$result" | grep -q "sms not sent, code 350"; then
|
||||
# Kill any hanging sms_tool process
|
||||
pkill -f "sms_tool send"
|
||||
echo '{"success":false,"error":"No prepaid credit available"}'
|
||||
else
|
||||
# Kill any hanging sms_tool process
|
||||
pkill -f "sms_tool send"
|
||||
echo "{\"success\":false,\"error\":\"Failed to send SMS\",\"raw\":\"$escaped_result\"}"
|
||||
fi
|
||||
@@ -0,0 +1,195 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Configuration
|
||||
CONFIG_FILE="/etc/keep_alive_schedule.conf"
|
||||
STATUS_FILE="/tmp/keep_alive_status"
|
||||
SPEEDTEST_SCRIPT="/www/cgi-bin/home/speedtest/speedtest.sh"
|
||||
|
||||
# Function to convert HH:MM to minutes since midnight
|
||||
time_to_minutes() {
|
||||
echo "$1" | awk -F: '{print $1 * 60 + $2}'
|
||||
}
|
||||
|
||||
# Function to validate time interval
|
||||
validate_interval() {
|
||||
START_TIME=$1
|
||||
END_TIME=$2
|
||||
INTERVAL_MINUTES=$3
|
||||
|
||||
# Convert times to minutes
|
||||
START_MINUTES=$(time_to_minutes "$START_TIME")
|
||||
END_MINUTES=$(time_to_minutes "$END_TIME")
|
||||
|
||||
# Calculate duration between start and end time
|
||||
if [ $END_MINUTES -lt $START_MINUTES ]; then
|
||||
# Handle case where end time is on the next day
|
||||
DURATION=$((1440 - START_MINUTES + END_MINUTES))
|
||||
else
|
||||
DURATION=$((END_MINUTES - START_MINUTES))
|
||||
fi
|
||||
|
||||
# Check if interval is longer than duration
|
||||
if [ $INTERVAL_MINUTES -gt $DURATION ]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to generate cron time expression
|
||||
generate_cron_time() {
|
||||
START_TIME=$1
|
||||
END_TIME=$2
|
||||
INTERVAL=$3
|
||||
|
||||
START_HOUR=$(echo "$START_TIME" | cut -d: -f1 | sed 's/^0//')
|
||||
START_MIN=$(echo "$START_TIME" | cut -d: -f2)
|
||||
END_HOUR=$(echo "$END_TIME" | cut -d: -f1 | sed 's/^0//')
|
||||
END_MIN=$(echo "$END_TIME" | cut -d: -f2)
|
||||
|
||||
# If end time is less than start time, it means we cross midnight
|
||||
if [ $(time_to_minutes "$END_TIME") -lt $(time_to_minutes "$START_TIME") ]; then
|
||||
# Create two cron entries for before and after midnight
|
||||
echo "*/$INTERVAL $START_HOUR-23 * * * $SPEEDTEST_SCRIPT"
|
||||
echo "*/$INTERVAL 0-$((END_HOUR - 1)) * * * $SPEEDTEST_SCRIPT"
|
||||
else
|
||||
echo "*/$INTERVAL $START_HOUR-$((END_HOUR - 1)) * * * $SPEEDTEST_SCRIPT"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to urldecode
|
||||
urldecode() {
|
||||
echo -e "$(echo "$1" | sed 's/+/ /g;s/%\([0-9A-F][0-9A-F]\)/\\x\1/g')"
|
||||
}
|
||||
|
||||
# Function to save configuration
|
||||
save_config() {
|
||||
echo "START_TIME=$1" >"$CONFIG_FILE"
|
||||
echo "END_TIME=$2" >>"$CONFIG_FILE"
|
||||
echo "INTERVAL=$3" >>"$CONFIG_FILE"
|
||||
echo "ENABLED=1" >>"$CONFIG_FILE"
|
||||
}
|
||||
|
||||
# Function to disable scheduling
|
||||
disable_scheduling() {
|
||||
if [ -f "$CONFIG_FILE" ]; then
|
||||
sed -i 's/ENABLED=1/ENABLED=0/' "$CONFIG_FILE"
|
||||
fi
|
||||
# Remove any existing cron jobs
|
||||
crontab -l | grep -v "$SPEEDTEST_SCRIPT" | crontab -
|
||||
}
|
||||
|
||||
# Function to get current status
|
||||
get_status() {
|
||||
if [ -f "$CONFIG_FILE" ]; then
|
||||
ENABLED=$(grep "ENABLED=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
START_TIME=$(grep "START_TIME=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
END_TIME=$(grep "END_TIME=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
INTERVAL=$(grep "INTERVAL=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
|
||||
echo "Status: 200 OK"
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
echo "{\"enabled\":$ENABLED,\"start_time\":\"$START_TIME\",\"end_time\":\"$END_TIME\",\"interval\":$INTERVAL}"
|
||||
else
|
||||
echo "Status: 200 OK"
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
echo "{\"enabled\":0,\"start_time\":\"\",\"end_time\":\"\",\"interval\":0}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Handle POST requests
|
||||
if [ "$REQUEST_METHOD" = "POST" ]; then
|
||||
# Read POST data
|
||||
read -r POST_DATA
|
||||
|
||||
# Check if disabling is requested
|
||||
echo "$POST_DATA" | grep -q "disable=true"
|
||||
if [ $? -eq 0 ]; then
|
||||
disable_scheduling
|
||||
echo "Status: 200 OK"
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
echo "{\"status\":\"success\",\"message\":\"Scheduling disabled\"}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Extract times and interval
|
||||
START_TIME=$(echo "$POST_DATA" | grep -o 'start_time=[^&]*' | cut -d'=' -f2)
|
||||
END_TIME=$(echo "$POST_DATA" | grep -o 'end_time=[^&]*' | cut -d'=' -f2)
|
||||
INTERVAL=$(echo "$POST_DATA" | grep -o 'interval=[^&]*' | cut -d'=' -f2)
|
||||
|
||||
# Decode times
|
||||
START_TIME=$(urldecode "$START_TIME")
|
||||
END_TIME=$(urldecode "$END_TIME")
|
||||
INTERVAL=$(urldecode "$INTERVAL")
|
||||
|
||||
# Validate times
|
||||
if [ -z "$START_TIME" ] || [ -z "$END_TIME" ] || [ -z "$INTERVAL" ]; then
|
||||
echo "Status: 400 Bad Request"
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
echo "{\"error\":\"Missing start time, end time, or interval\"}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validate interval is a number
|
||||
if ! echo "$INTERVAL" | grep -q '^[0-9]\+$'; then
|
||||
echo "Status: 400 Bad Request"
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
echo "{\"error\":\"Interval must be a number in minutes\"}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validate interval
|
||||
if ! validate_interval "$START_TIME" "$END_TIME" "$INTERVAL"; then
|
||||
echo "Status: 400 Bad Request"
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
echo "{\"error\":\"Interval is longer than the time between start and end time\"}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create temporary file for new crontab
|
||||
TEMP_CRON=$(mktemp)
|
||||
|
||||
# Get existing crontab entries (excluding our script)
|
||||
crontab -l 2>/dev/null | grep -v "$SPEEDTEST_SCRIPT" >"$TEMP_CRON"
|
||||
|
||||
# Generate and add cron entries
|
||||
generate_cron_time "$START_TIME" "$END_TIME" "$INTERVAL" >>"$TEMP_CRON"
|
||||
|
||||
# Install new crontab
|
||||
crontab "$TEMP_CRON"
|
||||
rm "$TEMP_CRON"
|
||||
|
||||
# Save configuration
|
||||
save_config "$START_TIME" "$END_TIME" "$INTERVAL"
|
||||
|
||||
echo "Status: 200 OK"
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
echo "{\"status\":\"success\",\"message\":\"Keep-alive scheduling enabled\"}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Parse query string for GET requests
|
||||
if [ "$REQUEST_METHOD" = "GET" ]; then
|
||||
QUERY_STRING=$(echo "$QUERY_STRING" | sed 's/&/\n/g')
|
||||
for param in $QUERY_STRING; do
|
||||
case "$param" in
|
||||
status=*)
|
||||
get_status
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
# If no valid request is made
|
||||
echo "Status: 400 Bad Request"
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
echo "{\"error\":\"Invalid request\"}"
|
||||
exit 1
|
||||
@@ -0,0 +1,61 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Configuration and log directories
|
||||
CONFIG_DIR="/etc/quecmanager/quecwatch"
|
||||
QUECWATCH_SCRIPT="${CONFIG_DIR}/quecwatch.sh"
|
||||
RCLOCAL="/etc/rc.local"
|
||||
LOG_DIR="/tmp/log/quecwatch"
|
||||
DEBUG_LOG_FILE="${LOG_DIR}/debug.log"
|
||||
|
||||
# Log directory for cleaning process
|
||||
CLEANUP_LOG_FILE="${LOG_DIR}/cleanup.log"
|
||||
|
||||
# Ensure log directory exists
|
||||
mkdir -p "${LOG_DIR}"
|
||||
|
||||
# Function to log cleanup events
|
||||
log_cleanup() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "${CLEANUP_LOG_FILE}"
|
||||
}
|
||||
|
||||
# Default response headers
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Cleanup function
|
||||
cleanup_quecwatch() {
|
||||
# Start logging cleanup process
|
||||
log_cleanup "Starting QuecWatch cleanup process"
|
||||
|
||||
# Stop any running QuecWatch processes
|
||||
log_cleanup "Stopping QuecWatch processes"
|
||||
pkill -f "${QUECWATCH_SCRIPT}" >> "${CLEANUP_LOG_FILE}" 2>&1
|
||||
|
||||
# Remove QuecWatch script from rc.local
|
||||
if [ -f "${RCLOCAL}" ]; then
|
||||
log_cleanup "Removing QuecWatch entries from rc.local"
|
||||
sed -i '\|/etc/quecmanager/quecwatch/quecwatch.sh|d' "${RCLOCAL}" >> "${CLEANUP_LOG_FILE}" 2>&1
|
||||
fi
|
||||
|
||||
# Remove configuration directory
|
||||
if [ -d "${CONFIG_DIR}" ]; then
|
||||
log_cleanup "Removing configuration directory: ${CONFIG_DIR}"
|
||||
rm -rf "${CONFIG_DIR}" >> "${CLEANUP_LOG_FILE}" 2>&1
|
||||
fi
|
||||
|
||||
# Remove log directory
|
||||
if [ -d "${LOG_DIR}" ]; then
|
||||
log_cleanup "Removing log directory: ${LOG_DIR}"
|
||||
rm -rf "${LOG_DIR}" >> "${CLEANUP_LOG_FILE}" 2>&1
|
||||
fi
|
||||
|
||||
log_cleanup "QuecWatch cleanup completed successfully"
|
||||
|
||||
# Optional: Output JSON response
|
||||
echo '{"status": "success", "message": "QuecWatch disabled and removed"}'
|
||||
}
|
||||
|
||||
# Execute cleanup
|
||||
cleanup_quecwatch
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,411 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Read POST data
|
||||
read -r QUERY_STRING
|
||||
|
||||
# Function to urldecode
|
||||
urldecode() {
|
||||
echo -e "$(echo "$1" | sed 's/+/ /g;s/%\([0-9A-F][0-9A-F]\)/\\x\1/g')"
|
||||
}
|
||||
|
||||
# Configuration directory
|
||||
CONFIG_DIR="/etc/quecmanager/quecwatch"
|
||||
QUECWATCH_CONFIG="${CONFIG_DIR}/quecwatch.conf"
|
||||
QUECWATCH_SCRIPT="${CONFIG_DIR}/quecwatch.sh"
|
||||
RCLOCAL="/etc/rc.local"
|
||||
LOG_DIR="/tmp/log/quecwatch"
|
||||
DEBUG_LOG_FILE="${LOG_DIR}/debug.log"
|
||||
|
||||
# Ensure log directory exists
|
||||
mkdir -p "${LOG_DIR}"
|
||||
|
||||
# Extract values from POST data
|
||||
action=$(echo "$QUERY_STRING" | grep -o 'action=[^&]*' | cut -d= -f2)
|
||||
ping_target=$(echo "$QUERY_STRING" | grep -o 'ping_target=[^&]*' | cut -d= -f2)
|
||||
ping_interval=$(echo "$QUERY_STRING" | grep -o 'ping_interval=[^&]*' | cut -d= -f2)
|
||||
ping_failures=$(echo "$QUERY_STRING" | grep -o 'ping_failures=[^&]*' | cut -d= -f2)
|
||||
max_retries=$(echo "$QUERY_STRING" | grep -o 'max_retries=[^&]*' | cut -d= -f2)
|
||||
connection_refresh=$(echo "$QUERY_STRING" | grep -o 'connection_refresh=[^&]*' | cut -d= -f2)
|
||||
auto_sim_failover=$(echo "$QUERY_STRING" | grep -o 'auto_sim_failover=[^&]*' | cut -d= -f2)
|
||||
sim_failover_schedule=$(echo "$QUERY_STRING" | grep -o 'sim_failover_schedule=[^&]*' | cut -d= -f2)
|
||||
|
||||
# URL decode the values
|
||||
action=$(urldecode "$action")
|
||||
ping_target=$(urldecode "$ping_target")
|
||||
ping_interval=$(urldecode "$ping_interval")
|
||||
ping_failures=$(urldecode "$ping_failures")
|
||||
max_retries=$(urldecode "$max_retries")
|
||||
connection_refresh=$(urldecode "$connection_refresh")
|
||||
auto_sim_failover=$(urldecode "$auto_sim_failover")
|
||||
sim_failover_schedule=$(urldecode "$sim_failover_schedule")
|
||||
|
||||
# Default response headers
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Validate inputs
|
||||
if [ -z "$ping_target" ]; then
|
||||
echo '{"status": "error", "message": "Ping target is required"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Initialize configuration function
|
||||
initialize_config() {
|
||||
# Create config directory if not exists
|
||||
mkdir -p "${CONFIG_DIR}"
|
||||
|
||||
# Write configuration with defaults and user-provided values
|
||||
cat >"${QUECWATCH_CONFIG}" <<EOL
|
||||
# QuecWatch Configuration File
|
||||
# Ping Target (IP or domain to ping)
|
||||
PING_TARGET=${ping_target}
|
||||
# Interval between ping checks (in seconds)
|
||||
PING_INTERVAL=${ping_interval:-30}
|
||||
# Number of consecutive ping failures before taking action
|
||||
PING_FAILURES=${ping_failures:-3}
|
||||
# Maximum number of retry attempts
|
||||
MAX_RETRIES=${max_retries:-5}
|
||||
# Current retry count (should start at 0)
|
||||
CURRENT_RETRIES=0
|
||||
# Enable/Disable Connection Refresh
|
||||
CONNECTION_REFRESH=${connection_refresh:-false}
|
||||
# Number of connection refresh attempts
|
||||
REFRESH_COUNT=${connection_refresh:+3}
|
||||
# Enable/Disable Auto SIM Failover
|
||||
AUTO_SIM_FAILOVER=${auto_sim_failover:-false}
|
||||
# Schedule for checking initial SIM (in minutes)
|
||||
# 0 means no scheduled check
|
||||
SIM_FAILOVER_SCHEDULE=${sim_failover_schedule:-0}
|
||||
# Indicate that QuecWatch is enabled
|
||||
ENABLED=true
|
||||
EOL
|
||||
|
||||
chmod 644 "${QUECWATCH_CONFIG}"
|
||||
}
|
||||
|
||||
# Generate monitoring script function
|
||||
generate_monitoring_script() {
|
||||
cat >"${QUECWATCH_SCRIPT}" <<'EOL'
|
||||
#!/bin/sh
|
||||
|
||||
# Load configuration
|
||||
. /etc/quecmanager/quecwatch/quecwatch.conf
|
||||
|
||||
# Define file paths
|
||||
QUEUE_FILE="/tmp/at_pipe.txt"
|
||||
LOG_FILE="/tmp/log/quecwatch/quecwatch.log"
|
||||
[ ! -f "${QUEUE_FILE}" ] && touch "${QUEUE_FILE}"
|
||||
|
||||
# Enhanced logging function with debug level
|
||||
log_message() {
|
||||
local level="$1"
|
||||
local message="$2"
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
echo "${timestamp} - [${level}] ${message}" >> "$LOG_FILE"
|
||||
logger -t quecwatch "${level}: ${message}"
|
||||
}
|
||||
|
||||
# Check for stale entries and clean them
|
||||
check_and_clean_stale() {
|
||||
local command_type="$1"
|
||||
local wait_count=0
|
||||
|
||||
while [ $wait_count -lt 6 ]; do
|
||||
if grep -q "\"command\":\"${command_type}\"" "$QUEUE_FILE"; then
|
||||
log_message "DEBUG" "Waiting for ${command_type} to clear (attempt ${wait_count})"
|
||||
sleep 1
|
||||
wait_count=$((wait_count + 1))
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
log_message "WARN" "Removing stale ${command_type} entry after ${wait_count}s"
|
||||
sed -i "/\"command\":\"${command_type}\"/d" "$QUEUE_FILE"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Handle lock with debug logging
|
||||
handle_lock() {
|
||||
log_message "DEBUG" "Checking queue file status before lock"
|
||||
if [ -f "$QUEUE_FILE" ]; then
|
||||
log_message "DEBUG" "Current queue content: $(cat $QUEUE_FILE)"
|
||||
else
|
||||
log_message "DEBUG" "Queue file does not exist, creating it"
|
||||
touch "$QUEUE_FILE"
|
||||
fi
|
||||
|
||||
check_and_clean_stale "FETCH_LOCK"
|
||||
|
||||
log_message "DEBUG" "Adding AT_COMMAND entry to queue"
|
||||
printf '{"command":"AT_COMMAND","pid":"%s","timestamp":"%s"}\n' \
|
||||
"$$" \
|
||||
"$(date '+%H:%M:%S')" >> "$QUEUE_FILE"
|
||||
|
||||
check_and_clean_stale "AT_COMMAND"
|
||||
}
|
||||
|
||||
# Execute AT command with enhanced error handling
|
||||
execute_at_command() {
|
||||
local command="$1"
|
||||
local result=""
|
||||
local retry_count=0
|
||||
local max_retries=3
|
||||
|
||||
log_message "DEBUG" "Executing AT command: ${command}"
|
||||
|
||||
while [ $retry_count -lt $max_retries ]; do
|
||||
handle_lock
|
||||
|
||||
result=$(sms_tool at "$command" -t 4 2>&1)
|
||||
local status=$?
|
||||
|
||||
log_message "DEBUG" "Removing our entry from queue"
|
||||
sed -i "/\"pid\":\"$$\"/d" "$QUEUE_FILE"
|
||||
|
||||
if [ $status -eq 0 ] && [ -n "$result" ]; then
|
||||
log_message "DEBUG" "Command successful. Output: $result"
|
||||
echo "$result"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_message "WARN" "Command failed (attempt $((retry_count + 1))): $result"
|
||||
retry_count=$((retry_count + 1))
|
||||
[ $retry_count -lt $max_retries ] && sleep 2
|
||||
done
|
||||
|
||||
log_message "ERROR" "Command failed after $max_retries attempts: $command"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Function to update retry count in config
|
||||
update_retry_count() {
|
||||
local new_retry_count=$1
|
||||
sed -i "s/CURRENT_RETRIES=[0-9]*/CURRENT_RETRIES=${new_retry_count}/" /etc/quecmanager/quecwatch/quecwatch.conf
|
||||
# Reload config to ensure latest values
|
||||
. /etc/quecmanager/quecwatch/quecwatch.conf
|
||||
}
|
||||
|
||||
# Function to get current SIM slot with enhanced error handling
|
||||
get_current_sim() {
|
||||
local output
|
||||
local retry_count=0
|
||||
local max_retries=3
|
||||
|
||||
while [ $retry_count -lt $max_retries ]; do
|
||||
output=$(execute_at_command "AT+QUIMSLOT?")
|
||||
if [ $? -eq 0 ] && echo "$output" | grep -q "+QUIMSLOT:"; then
|
||||
echo "$output" | grep "+QUIMSLOT:" | awk '{print $2}'
|
||||
return 0
|
||||
fi
|
||||
retry_count=$((retry_count + 1))
|
||||
[ $retry_count -lt $max_retries ] && sleep 2
|
||||
done
|
||||
|
||||
log_message "ERROR" "Failed to get current SIM slot after $max_retries attempts"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Function to switch SIM card with enhanced error handling
|
||||
switch_sim_card() {
|
||||
log_message "INFO" "Attempting to switch SIM card"
|
||||
|
||||
# Get current SIM slot
|
||||
current_sim_slot=$(get_current_sim)
|
||||
if [ $? -ne 0 ]; then
|
||||
log_message "ERROR" "Failed to get current SIM slot"
|
||||
return 1
|
||||
fi # Changed from } to fi
|
||||
|
||||
# Toggle between SIM slots
|
||||
new_sim_slot=$((current_sim_slot % 2 + 1))
|
||||
|
||||
log_message "INFO" "Switching from SIM slot ${current_sim_slot} to SIM slot ${new_sim_slot}"
|
||||
if ! execute_at_command "AT+QUIMSLOT=${new_sim_slot}"; then
|
||||
log_message "ERROR" "Failed to switch to SIM slot ${new_sim_slot}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
sleep 10 # Allow time for SIM switch and network registration
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to check internet connectivity
|
||||
check_internet() {
|
||||
ping -c 3 ${PING_TARGET} > /dev/null 2>&1
|
||||
return $?
|
||||
}
|
||||
|
||||
# Function to perform connection recovery
|
||||
perform_connection_recovery() {
|
||||
local recovery_attempted=0
|
||||
local recovery_successful=0
|
||||
|
||||
if [ "${CONNECTION_REFRESH}" = "true" ] && [ "${retry_trigger}" -eq 1 ] && [ "${REFRESH_COUNT}" -gt 0 ]; then
|
||||
log_message "INFO" "Attempting connection refresh"
|
||||
|
||||
if ! execute_at_command "AT+COPS=2"; then
|
||||
log_message "ERROR" "Failed to detach from network"
|
||||
return 1
|
||||
fi
|
||||
|
||||
sleep 2
|
||||
|
||||
if ! execute_at_command "AT+COPS=0"; then
|
||||
log_message "ERROR" "Failed to reattach to network"
|
||||
return 1
|
||||
fi # <-- Changed from } to fi
|
||||
|
||||
sleep 5
|
||||
|
||||
if check_internet; then
|
||||
log_message "INFO" "Connection refresh successful"
|
||||
recovery_successful=1
|
||||
return 0
|
||||
fi
|
||||
|
||||
REFRESH_COUNT=$((REFRESH_COUNT - 1))
|
||||
sed -i "s/REFRESH_COUNT=.*/REFRESH_COUNT=${REFRESH_COUNT}/" /etc/quecmanager/quecwatch/quecwatch.conf
|
||||
recovery_attempted=1
|
||||
fi
|
||||
|
||||
[ ${recovery_successful} -eq 1 ] && return 0 || return 1
|
||||
}
|
||||
|
||||
# Store initial SIM slot
|
||||
initial_sim_slot=""
|
||||
if [ "${AUTO_SIM_FAILOVER}" = "true" ]; then
|
||||
initial_sim_slot=$(get_current_sim)
|
||||
if [ $? -eq 0 ]; then
|
||||
log_message "INFO" "Auto SIM failover enabled. Initial SIM slot: ${initial_sim_slot}"
|
||||
else
|
||||
log_message "ERROR" "Failed to get initial SIM slot"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Main monitoring loop
|
||||
failure_count=0
|
||||
retry_trigger=0
|
||||
sim_failover_interval=0
|
||||
|
||||
while true; do
|
||||
if ! check_internet; then
|
||||
failure_count=$((failure_count + 1))
|
||||
log_message "INFO" "Ping failed. Failure count: ${failure_count}"
|
||||
|
||||
if [ ${failure_count} -ge ${PING_FAILURES} ]; then
|
||||
failure_count=0
|
||||
retry_trigger=$((retry_trigger + 1))
|
||||
update_retry_count ${retry_trigger}
|
||||
|
||||
log_message "INFO" "Failure threshold reached. Retry trigger: ${retry_trigger}"
|
||||
|
||||
if [ ${retry_trigger} -ge ${MAX_RETRIES} ]; then
|
||||
if [ "${AUTO_SIM_FAILOVER}" = "true" ]; then
|
||||
log_message "INFO" "Max retries exhausted. Attempting SIM failover."
|
||||
if switch_sim_card && check_internet; then
|
||||
log_message "INFO" "SIM failover successful"
|
||||
retry_trigger=0
|
||||
failure_count=0
|
||||
update_retry_count 0
|
||||
else
|
||||
log_message "ERROR" "SIM failover failed. Performing system reboot."
|
||||
reboot
|
||||
fi
|
||||
else
|
||||
log_message "INFO" "Max retries exhausted. Auto SIM failover disabled. Removing QuecWatch."
|
||||
sed -i '\|/etc/quecmanager/quecwatch/quecwatch.sh|d' /etc/rc.local
|
||||
reboot
|
||||
exit 0
|
||||
fi
|
||||
else
|
||||
if perform_connection_recovery; then
|
||||
retry_trigger=0
|
||||
failure_count=0
|
||||
update_retry_count 0
|
||||
else
|
||||
log_message "ERROR" "Recovery failed. Performing system reboot."
|
||||
reboot
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
else
|
||||
failure_count=0
|
||||
retry_trigger=0
|
||||
update_retry_count 0
|
||||
log_message "INFO" "Modem is connected to the internet"
|
||||
|
||||
if [ "${AUTO_SIM_FAILOVER}" = "true" ] && [ "${SIM_FAILOVER_SCHEDULE}" -gt 0 ]; then
|
||||
current_sim_slot=$(get_current_sim)
|
||||
|
||||
if [ -n "${initial_sim_slot}" ] && [ "${current_sim_slot}" != "${initial_sim_slot}" ]; then
|
||||
sim_failover_interval=$((sim_failover_interval + 1))
|
||||
|
||||
if [ $((sim_failover_interval * PING_INTERVAL)) -ge $((SIM_FAILOVER_SCHEDULE * 60)) ]; then
|
||||
log_message "INFO" "Scheduled check: Attempting to switch back to initial SIM ${initial_sim_slot}"
|
||||
|
||||
if execute_at_command "AT+QUIMSLOT=${initial_sim_slot}"; then
|
||||
sleep 10
|
||||
|
||||
if check_internet; then
|
||||
log_message "INFO" "Initial SIM restored successfully"
|
||||
retry_trigger=0
|
||||
failure_count=0
|
||||
update_retry_count 0
|
||||
else
|
||||
log_message "WARN" "Initial SIM still not working. Switching back to backup SIM."
|
||||
execute_at_command "AT+QUIMSLOT=${current_sim_slot}"
|
||||
sleep 10
|
||||
fi
|
||||
else
|
||||
log_message "ERROR" "Failed to switch to initial SIM"
|
||||
fi
|
||||
|
||||
sim_failover_interval=0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
sleep ${PING_INTERVAL}
|
||||
done
|
||||
EOL
|
||||
|
||||
chmod +x "${QUECWATCH_SCRIPT}"
|
||||
|
||||
# Run the script
|
||||
"${QUECWATCH_SCRIPT}" &
|
||||
}
|
||||
|
||||
# Enable QuecWatch
|
||||
enable_quecwatch() {
|
||||
initialize_config
|
||||
generate_monitoring_script
|
||||
|
||||
if ! grep -q "${QUECWATCH_SCRIPT}" "${RCLOCAL}"; then
|
||||
[ -f "${RCLOCAL}" ] || touch "${RCLOCAL}"
|
||||
chmod +x "${RCLOCAL}"
|
||||
sed -i '$i'"${QUECWATCH_SCRIPT} &" "${RCLOCAL}"
|
||||
fi
|
||||
|
||||
# Output success JSON
|
||||
echo '{"status": "success", "message": "QuecWatch enabled", "config": "'${QUECWATCH_CONFIG}'"}'
|
||||
}
|
||||
|
||||
# Log debug information
|
||||
{
|
||||
echo "Timestamp: $(date)"
|
||||
echo "Script Path: $0"
|
||||
echo "Ping Target: $ping_target"
|
||||
echo "Ping Interval: $ping_interval"
|
||||
echo "Ping Failures: $ping_failures"
|
||||
echo "Max Retries: $max_retries"
|
||||
echo "Connection Refresh: $connection_refresh"
|
||||
echo "Auto SIM Failover: $auto_sim_failover"
|
||||
echo "SIM Failover Schedule: $sim_failover_schedule"
|
||||
} >>"$DEBUG_LOG_FILE" 2>&1
|
||||
|
||||
# Enable QuecWatch
|
||||
enable_quecwatch
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,79 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set headers for JSON response
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Configuration file path
|
||||
CONFIG_FILE="/etc/quecmanager/quecwatch/quecwatch.conf"
|
||||
|
||||
# Check if configuration file exists
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo '{"status": "inactive", "message": "QuecWatch is not configured"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Function to safely get config value
|
||||
get_config_value() {
|
||||
grep "^$1=" "$CONFIG_FILE" | cut -d'=' -f2
|
||||
}
|
||||
|
||||
# Check if QuecWatch is enabled
|
||||
enabled=$(get_config_value "ENABLED")
|
||||
if [ "$enabled" != "true" ]; then
|
||||
echo '{"status": "inactive", "message": "QuecWatch is disabled"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Fetch configuration values
|
||||
ping_target=$(get_config_value "PING_TARGET")
|
||||
ping_interval=$(get_config_value "PING_INTERVAL")
|
||||
ping_failures=$(get_config_value "PING_FAILURES")
|
||||
max_retries=$(get_config_value "MAX_RETRIES")
|
||||
current_retries=$(get_config_value "CURRENT_RETRIES")
|
||||
connection_refresh=$(get_config_value "CONNECTION_REFRESH")
|
||||
refresh_count=$(get_config_value "REFRESH_COUNT")
|
||||
|
||||
# New configuration options
|
||||
mobile_data_reconnect=$(get_config_value "MOBILE_DATA_RECONNECT")
|
||||
auto_sim_failover=$(get_config_value "AUTO_SIM_FAILOVER")
|
||||
sim_failover_schedule=$(get_config_value "SIM_FAILOVER_SCHEDULE")
|
||||
|
||||
# Default values if not set
|
||||
mobile_data_reconnect=${mobile_data_reconnect:-false}
|
||||
auto_sim_failover=${auto_sim_failover:-false}
|
||||
sim_failover_schedule=${sim_failover_schedule:-30}
|
||||
|
||||
# Check monitoring script existence
|
||||
QUECWATCH_SCRIPT="/etc/quecmanager/quecwatch/quecwatch.sh"
|
||||
if [ ! -f "$QUECWATCH_SCRIPT" ]; then
|
||||
echo '{"status": "error", "message": "Monitoring script is missing"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check log file for recent activity
|
||||
LOG_FILE="/tmp/log/quecwatch/quecwatch.log"
|
||||
last_log=""
|
||||
if [ -f "$LOG_FILE" ]; then
|
||||
last_log=$(tail -n 1 "$LOG_FILE")
|
||||
fi
|
||||
|
||||
# Prepare JSON response
|
||||
cat <<EOF
|
||||
{
|
||||
"status": "active",
|
||||
"config": {
|
||||
"pingTarget": "${ping_target}",
|
||||
"pingInterval": ${ping_interval},
|
||||
"pingFailures": ${ping_failures},
|
||||
"maxRetries": ${max_retries},
|
||||
"currentRetries": ${current_retries},
|
||||
"connectionRefresh": ${connection_refresh},
|
||||
"refreshCount": ${refresh_count:-0},
|
||||
"mobileDataReconnect": ${mobile_data_reconnect},
|
||||
"autoSimFailover": ${auto_sim_failover},
|
||||
"simFailoverSchedule": ${sim_failover_schedule}
|
||||
},
|
||||
"lastActivity": "${last_log}"
|
||||
}
|
||||
EOF
|
||||
@@ -0,0 +1,195 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set content-type for JSON response
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Define file paths and configuration
|
||||
QUEUE_FILE="/tmp/at_pipe.txt"
|
||||
LOCK_KEYWORD="FETCH_DATA_LOCK"
|
||||
MAX_WAIT=6 # Maximum seconds to wait for lock
|
||||
|
||||
# Function to output error in JSON format
|
||||
output_error() {
|
||||
printf '{"error": "%s"}\n' "$1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Function to clean and add lock with simplified timeout logic
|
||||
add_clean_lock() {
|
||||
local TIMESTAMP=$(date +%s)
|
||||
local WAIT_START=$(date +%s)
|
||||
|
||||
while true; do
|
||||
local CURRENT_TIME=$(date +%s)
|
||||
|
||||
# After MAX_WAIT seconds, forcibly remove any existing lock
|
||||
if [ $((CURRENT_TIME - WAIT_START)) -ge $MAX_WAIT ]; then
|
||||
# Remove any existing lock entries regardless of owner
|
||||
sed -i "/${LOCK_KEYWORD}/d" "$QUEUE_FILE"
|
||||
logger -t at_commands "Removed existing lock after $MAX_WAIT seconds timeout"
|
||||
fi
|
||||
|
||||
# Add our lock entry
|
||||
printf '{"id":"%s","timestamp":"%s","command":"%s","status":"lock","pid":"%s","start_time":"%s"}\n' \
|
||||
"${LOCK_KEYWORD}" \
|
||||
"$(date '+%H:%M:%S')" \
|
||||
"${LOCK_KEYWORD}" \
|
||||
"$$" \
|
||||
"$TIMESTAMP" >> "$QUEUE_FILE"
|
||||
|
||||
# Verify our lock was written
|
||||
if grep -q "\"pid\":\"$$\".*\"start_time\":\"$TIMESTAMP\"" "$QUEUE_FILE"; then
|
||||
logger -t at_commands "Lock created by PID $$ at $TIMESTAMP"
|
||||
# Register cleanup handler
|
||||
trap 'remove_lock; exit' INT TERM EXIT
|
||||
return 0
|
||||
fi
|
||||
|
||||
# If we haven't exceeded MAX_WAIT, sleep and try again
|
||||
if [ $((CURRENT_TIME - WAIT_START)) -lt $MAX_WAIT ]; then
|
||||
sleep 1
|
||||
else
|
||||
logger -t at_commands "Failed to acquire lock after $MAX_WAIT seconds"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Simple remove lock function that only removes our entry
|
||||
remove_lock() {
|
||||
sed -i "/\"pid\":\"$$\"/d" "$QUEUE_FILE"
|
||||
logger -t at_commands "Lock removed by PID $$"
|
||||
}
|
||||
|
||||
# Improved 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$//'
|
||||
}
|
||||
|
||||
# Enhanced AT command execution with retries
|
||||
execute_at_command() {
|
||||
local CMD="$1"
|
||||
local RETRY_COUNT=0
|
||||
local MAX_RETRIES=3
|
||||
local OUTPUT=""
|
||||
|
||||
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
|
||||
OUTPUT=$(sms_tool at "$CMD" -t 4 2>/dev/null)
|
||||
if [ $? -eq 0 ] && [ -n "$OUTPUT" ]; then
|
||||
echo "$OUTPUT"
|
||||
return 0
|
||||
fi
|
||||
RETRY_COUNT=$((RETRY_COUNT + 1))
|
||||
[ $RETRY_COUNT -lt $MAX_RETRIES ] && sleep 1
|
||||
done
|
||||
|
||||
logger -t at_commands "Command failed after $MAX_RETRIES attempts: $CMD"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Enhanced command processing function
|
||||
process_commands() {
|
||||
local commands="$1"
|
||||
local first=1
|
||||
|
||||
# Start JSON array
|
||||
printf '['
|
||||
|
||||
# Process each command
|
||||
for cmd in $commands; do
|
||||
# Add comma separator if not first item
|
||||
[ $first -eq 0 ] && printf ','
|
||||
first=0
|
||||
|
||||
# Execute command with retries
|
||||
OUTPUT=$(execute_at_command "$cmd")
|
||||
local CMD_STATUS=$?
|
||||
|
||||
# Properly escape both command and output for JSON
|
||||
ESCAPED_CMD=$(escape_json "$cmd")
|
||||
ESCAPED_OUTPUT=$(escape_json "$OUTPUT")
|
||||
|
||||
# Format JSON object with proper escaping
|
||||
if [ $CMD_STATUS -eq 0 ]; then
|
||||
printf '{"command":"%s","response":"%s","status":"success"}' \
|
||||
"${ESCAPED_CMD}" \
|
||||
"${ESCAPED_OUTPUT}"
|
||||
else
|
||||
printf '{"command":"%s","response":"Command failed","status":"error"}' \
|
||||
"${ESCAPED_CMD}"
|
||||
fi
|
||||
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
# Close JSON array
|
||||
printf ']\n'
|
||||
}
|
||||
|
||||
# Main process wrapper with automatic lock handling
|
||||
main_with_clean_lock() {
|
||||
# Set timeout for the entire script
|
||||
( sleep 60; kill -TERM $$ 2>/dev/null ) &
|
||||
TIMEOUT_PID=$!
|
||||
|
||||
if ! add_clean_lock; then
|
||||
output_error "Failed to acquire lock for command processing"
|
||||
kill $TIMEOUT_PID 2>/dev/null
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Process commands
|
||||
process_commands "$COMMANDS"
|
||||
|
||||
# Clean up
|
||||
remove_lock
|
||||
kill $TIMEOUT_PID 2>/dev/null
|
||||
}
|
||||
|
||||
# Define command sets
|
||||
define_command_sets() {
|
||||
COMMAND_SET_1='AT+QUIMSLOT? AT+CNUM AT+COPS? AT+CIMI AT+ICCID AT+CGSN AT+CPIN? AT+CGDCONT? AT+CREG? AT+CFUN? AT+QENG="servingcell" AT+QTEMP AT+CGCONTRDP AT+QCAINFO AT+QRSRP AT+QMAP="WWAN" AT+C5GREG=2;+C5GREG? AT+CGREG=2;+CGREG? AT+QRSRQ AT+QSINR'
|
||||
COMMAND_SET_2='AT+CGDCONT? AT+CGCONTRDP AT+QNWPREFCFG="mode_pref" AT+QNWPREFCFG="nr5g_disable_mode" AT+QUIMSLOT?'
|
||||
COMMAND_SET_3='AT+CGMI AT+CGMM AT+QGMR AT+CNUM AT+CIMI AT+ICCID AT+CGSN AT+QMAP="LANIP" AT+QMAP="WWAN" AT+QGETCAPABILITY'
|
||||
COMMAND_SET_4='AT+QMAP="MPDN_RULE" AT+QMAP="DHCPV4DNS" AT+QCFG="usbnet"'
|
||||
COMMAND_SET_5='AT+QRSRP AT+QRSRQ AT+QSINR AT+QCAINFO AT+QSPN'
|
||||
COMMAND_SET_6='AT+CEREG=2;+CEREG? AT+C5GREG=2;+C5GREG? AT+CPIN? AT+CGDCONT? AT+CGCONTRDP AT+QMAP="WWAN" AT+QRSRP AT+QTEMP AT+QNETRC?'
|
||||
COMMAND_SET_7='AT+QNWPREFCFG="policy_band" AT+QNWPREFCFG="lte_band";+QNWPREFCFG="nsa_nr5g_band";+QNWPREFCFG="nr5g_band"'
|
||||
COMMAND_SET_8='AT+QNWLOCK="common/4g" AT+QNWLOCK="common/5g" AT+QNWLOCK="save_ctrl"'
|
||||
}
|
||||
|
||||
# Main execution
|
||||
define_command_sets
|
||||
|
||||
# Get command set from query string with validation
|
||||
COMMAND_SET=$(echo "$QUERY_STRING" | grep -o 'set=[1-8]' | cut -d'=' -f2 | tr -cd '0-9')
|
||||
if [ -z "$COMMAND_SET" ] || [ "$COMMAND_SET" -lt 1 ] || [ "$COMMAND_SET" -gt 8 ]; then
|
||||
COMMAND_SET=1 # Default to set 1 if invalid or no set specified
|
||||
fi
|
||||
|
||||
# Select the appropriate command set
|
||||
case "$COMMAND_SET" in
|
||||
1) COMMANDS="$COMMAND_SET_1";;
|
||||
2) COMMANDS="$COMMAND_SET_2";;
|
||||
3) COMMANDS="$COMMAND_SET_3";;
|
||||
4) COMMANDS="$COMMAND_SET_4";;
|
||||
5) COMMANDS="$COMMAND_SET_5";;
|
||||
6) COMMANDS="$COMMAND_SET_6";;
|
||||
7) COMMANDS="$COMMAND_SET_7";;
|
||||
8) COMMANDS="$COMMAND_SET_8";;
|
||||
esac
|
||||
|
||||
# Execute main process with clean lock handling
|
||||
main_with_clean_lock
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Content-Type: application/json"
|
||||
echo "Cache-Control: no-cache, no-store, must-revalidate"
|
||||
echo "Pragma: no-cache"
|
||||
echo "Expires: 0"
|
||||
echo ""
|
||||
|
||||
# Basic response indicating the server is up
|
||||
echo '{"alive": true}'
|
||||
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set the content type to JSON
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
|
||||
# Ping 8.8.8.8 with 2 packets and capture the result
|
||||
if ping -c 2 8.8.8.8 > /dev/null 2>&1; then
|
||||
# Ping was successful
|
||||
echo '{"connection": "ACTIVE"}'
|
||||
else
|
||||
# Ping failed
|
||||
echo '{"connection": "INACTIVE"}'
|
||||
fi
|
||||
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set the content type to JSON
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
|
||||
# Run ethtool on eth0 and capture the output
|
||||
ethtool_output=$(ethtool eth0)
|
||||
|
||||
# Extract Link Speed
|
||||
speed=$(echo "$ethtool_output" | grep "Speed:" | awk '{print $2}')
|
||||
|
||||
# Extract Link Status
|
||||
link_status=$(echo "$ethtool_output" | grep "Link detected:" | awk '{print $3}')
|
||||
|
||||
# Extract Auto-negotiation status
|
||||
auto_negotiation=$(echo "$ethtool_output" | grep "Auto-negotiation:" | awk '{print $2}')
|
||||
|
||||
# Create JSON output
|
||||
echo "{\"link_speed\": \"$speed\", \"link_status\": \"$link_status\", \"auto_negotiation\": \"$auto_negotiation\"}"
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set content type to JSON
|
||||
echo "Content-Type: application/json"
|
||||
echo
|
||||
|
||||
# Read the JSON file and get only the last entry using jq
|
||||
jq 'last' /www/signal_graphs/data_usage.json
|
||||
@@ -0,0 +1,119 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set common headers
|
||||
echo "Content-Type: application/json"
|
||||
echo "Access-Control-Allow-Origin: *"
|
||||
echo "Cache-Control: no-cache, no-store, must-revalidate"
|
||||
echo ""
|
||||
|
||||
# Lock file path
|
||||
LOCK_FILE="/tmp/hw_details.lock"
|
||||
LOCK_TIMEOUT=10 # Maximum wait time in seconds
|
||||
|
||||
# Function to acquire lock
|
||||
acquire_lock() {
|
||||
local start_time=$(date +%s)
|
||||
while [ -e "$LOCK_FILE" ]; do
|
||||
# Check if lock is stale (older than LOCK_TIMEOUT seconds)
|
||||
if [ -f "$LOCK_FILE" ]; then
|
||||
local lock_time=$(stat -c %Y "$LOCK_FILE" 2>/dev/null)
|
||||
local current_time=$(date +%s)
|
||||
if [ $((current_time - lock_time)) -gt $LOCK_TIMEOUT ]; then
|
||||
rm -f "$LOCK_FILE"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if we've waited too long
|
||||
if [ $(($(date +%s) - start_time)) -gt $LOCK_TIMEOUT ]; then
|
||||
error_response "Timeout waiting for lock"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
# Create lock file with current PID
|
||||
echo $$ > "$LOCK_FILE"
|
||||
}
|
||||
|
||||
# Function to release lock
|
||||
release_lock() {
|
||||
rm -f "$LOCK_FILE"
|
||||
}
|
||||
|
||||
# Function to handle errors and return JSON
|
||||
error_response() {
|
||||
echo "{\"error\": \"$1\"}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Function to cleanup on exit
|
||||
cleanup() {
|
||||
release_lock
|
||||
exit $?
|
||||
}
|
||||
|
||||
# Set trap for cleanup
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
# Function to get memory information
|
||||
get_memory_info() {
|
||||
free_output=$(free -b)
|
||||
memory_info=$(echo "$free_output" | awk '/Mem:/ {print "{\"total\": " $2 ", \"used\": " $3 ", \"available\": " $7 "}"}')
|
||||
echo "$memory_info"
|
||||
}
|
||||
|
||||
# Function to get ethernet information
|
||||
get_ethernet_info() {
|
||||
interface=${1:-eth0}
|
||||
# Check if ethtool is installed
|
||||
if ! which ethtool >/dev/null 2>&1; then
|
||||
error_response "ethtool not found"
|
||||
fi
|
||||
|
||||
# Check if interface exists
|
||||
if ! ip link show "$interface" >/dev/null 2>&1; then
|
||||
error_response "Interface $interface not found"
|
||||
fi
|
||||
|
||||
# Run ethtool and capture output
|
||||
ethtool_output=$(ethtool "$interface" 2>/dev/null) || error_response "Failed to get ethernet information"
|
||||
|
||||
# Extract values using sed instead of grep -P
|
||||
speed=$(echo "$ethtool_output" | sed -n 's/.*Speed: \([^[:space:]]*\).*/\1/p' || echo "Unknown")
|
||||
link_status=$(echo "$ethtool_output" | sed -n 's/.*Link detected: \(yes\|no\).*/\1/p' || echo "unknown")
|
||||
auto_negotiation=$(echo "$ethtool_output" | sed -n 's/.*Auto-negotiation: \(on\|off\).*/\1/p' || echo "unknown")
|
||||
|
||||
# Output JSON
|
||||
echo "{\"link_speed\":\"$speed\",\"link_status\":\"$link_status\",\"auto_negotiation\":\"$auto_negotiation\"}"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
# Acquire lock before proceeding
|
||||
acquire_lock
|
||||
|
||||
# Parse query string for type and interface
|
||||
type=$(echo "$QUERY_STRING" | sed -n 's/.*type=\([^&]*\).*/\1/p')
|
||||
interface=$(echo "$QUERY_STRING" | sed -n 's/.*interface=\([^&]*\).*/\1/p')
|
||||
|
||||
# Default interface if not specified
|
||||
[ -z "$interface" ] && interface="eth0"
|
||||
|
||||
# Convert type to lowercase using tr
|
||||
type=$(echo "$type" | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
# Check type parameter and call appropriate function
|
||||
case "$type" in
|
||||
"memory")
|
||||
get_memory_info
|
||||
;;
|
||||
"eth")
|
||||
get_ethernet_info "$interface"
|
||||
;;
|
||||
*)
|
||||
error_response "Invalid type. Use 'memory' or 'eth'"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Lock will be automatically released by the cleanup trap
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Ensure the script outputs proper CGI headers
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
|
||||
# Directory where JSON files are stored (adjust as needed)
|
||||
JSON_DIR="/www/signal_graphs/"
|
||||
|
||||
# Function to safely read JSON file
|
||||
read_json_file() {
|
||||
local file="$1"
|
||||
if [ -f "$file" ]; then
|
||||
cat "$file"
|
||||
else
|
||||
echo "[]" # Return empty array if file doesn't exist
|
||||
fi
|
||||
}
|
||||
|
||||
# Collect signal metrics from JSON files
|
||||
RSRP=$(read_json_file "${JSON_DIR}/rsrp.json")
|
||||
RSRQ=$(read_json_file "${JSON_DIR}/rsrq.json")
|
||||
SINR=$(read_json_file "${JSON_DIR}/sinr.json")
|
||||
|
||||
# Combine metrics into a single JSON object
|
||||
printf '{
|
||||
"rsrp": %s,
|
||||
"rsrq": %s,
|
||||
"sinr": %s
|
||||
}' "$RSRP" "$RSRQ" "$SINR"
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set the content type to JSON
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
|
||||
# Run free command and capture the output, using -b for bytes
|
||||
free_output=$(free -b)
|
||||
|
||||
# Extract memory information using awk
|
||||
# Skip the header, take the Mem: line, and extract total, used, and available
|
||||
memory_info=$(echo "$free_output" | awk '/Mem:/ {print "{\"total\": " $2 ", \"used\": " $3 ", \"available\": " $7 "}"}')
|
||||
|
||||
# Output the JSON
|
||||
echo "$memory_info"
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set the content type to JSON
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
|
||||
# Ping 8.8.8.8 with 5 packets and capture the full output
|
||||
ping_result=$(ping -c 5 8.8.8.8)
|
||||
|
||||
# Check if ping was successful
|
||||
if [ $? -eq 0 ]; then
|
||||
# Extract the average latency using awk
|
||||
avg_latency=$(echo "$ping_result" | awk '/avg/ {split($4, a, "/"); print int(a[2])}')
|
||||
|
||||
# If average latency was extracted, return it
|
||||
if [ ! -z "$avg_latency" ]; then
|
||||
echo "{\"connection\": \"ACTIVE\", \"latency\": $avg_latency}"
|
||||
else
|
||||
echo '{"connection": "ACTIVE", "latency": 0}'
|
||||
fi
|
||||
else
|
||||
# Ping failed
|
||||
echo '{"connection": "INACTIVE", "latency": 0}'
|
||||
fi
|
||||
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
export HOME=/tmp/home
|
||||
|
||||
# Create named pipe for speedtest output if it doesn't exist
|
||||
[ ! -p /tmp/realtime_spd.json ] && mkfifo /tmp/realtime_spd.json
|
||||
|
||||
# Run speedtest in background
|
||||
/usr/bin/speedtest --accept-license -f json -p yes --progress-update-interval=100 > /tmp/realtime_spd.json
|
||||
|
||||
# Remove named pipe
|
||||
rm /tmp/realtime_spd.json
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Content-Type: text/event-stream"
|
||||
echo "Cache-Control: no-cache"
|
||||
echo "Connection: keep-alive"
|
||||
echo ""
|
||||
|
||||
# Use cat to read from the FIFO
|
||||
cat /tmp/realtime_spd.json | while read line; do
|
||||
echo "data: $line"
|
||||
echo
|
||||
sleep 0.1
|
||||
done
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
# /www/cgi-bin/start_speedtest.sh
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
|
||||
# Run speedtest in background
|
||||
/www/cgi-bin/home/speedtest/speedtest.sh
|
||||
|
||||
# Immediately return a success response
|
||||
echo '{"status":"started"}'
|
||||
@@ -0,0 +1,37 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=99
|
||||
STOP=10
|
||||
|
||||
USE_PROCD=1
|
||||
|
||||
start_service() {
|
||||
# echo "Starting QuecManager services"
|
||||
procd_open_instance
|
||||
procd_set_param command /www/cgi-bin/services/log_signal_metrics.sh
|
||||
procd_set_param respawn
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_close_instance
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command /www/cgi-bin/services/at_queue_processor.sh
|
||||
procd_set_param respawn
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_close_instance
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command /www/cgi-bin/services/clear_logs.sh
|
||||
procd_set_param respawn
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_close_instance
|
||||
echo "Signal Metrics Logger Running"
|
||||
echo "All QuecManager services Running"
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
# procd will handle stopping all instances automatically
|
||||
echo "Stopping QuecManager services."
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
#!/bin/sh
|
||||
|
||||
QUEUE_FILE="/tmp/at_pipe.txt"
|
||||
RESULT_FILE="/tmp/at_results.json"
|
||||
LOG_FILE="/var/log/at_commands.log"
|
||||
# Define all lock keywords
|
||||
FETCH_LOCK_KEYWORD="FETCH_DATA_LOCK"
|
||||
SIGNAL_LOCK_KEYWORD="SIGNAL_METRICS_LOCK"
|
||||
# Combine keywords for pattern matching
|
||||
ALL_LOCK_KEYWORDS="${FETCH_LOCK_KEYWORD}\\|${SIGNAL_LOCK_KEYWORD}"
|
||||
|
||||
# Create or clear necessary files
|
||||
touch "${QUEUE_FILE}"
|
||||
[ ! -f "${RESULT_FILE}" ] && echo '[]' > "${RESULT_FILE}"
|
||||
|
||||
# Log messages to the log file
|
||||
log_message() {
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "${LOG_FILE}"
|
||||
}
|
||||
|
||||
# Escape special characters for JSON
|
||||
escape_json() {
|
||||
echo "$1" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g'
|
||||
}
|
||||
|
||||
# Function to check if any lock is present
|
||||
is_system_locked() {
|
||||
grep -q "\"command\":\"\\(${ALL_LOCK_KEYWORDS}\\)\"" "${QUEUE_FILE}"
|
||||
return $?
|
||||
}
|
||||
|
||||
# Process a single command
|
||||
process_command() {
|
||||
local command="$1"
|
||||
local timestamp="$2"
|
||||
local cmd_id="$3"
|
||||
|
||||
log_message "Processing command: ${command} (ID: ${cmd_id})"
|
||||
|
||||
# Check if sms_tool exists and is executable
|
||||
if ! which sms_tool >/dev/null 2>&1; then
|
||||
log_message "Error: sms_tool not found in PATH"
|
||||
result="sms_tool not found"
|
||||
exit_code=1
|
||||
else
|
||||
# Execute the AT command using sms_tool
|
||||
result=$(sms_tool at "${command}" 2>&1)
|
||||
exit_code=$?
|
||||
log_message "Command output: ${result}"
|
||||
log_message "Exit code: ${exit_code}"
|
||||
fi
|
||||
|
||||
# Escape the command and result for JSON
|
||||
escaped_command=$(escape_json "${command}")
|
||||
escaped_result=$(echo "${result}" | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g' | tr -d '\r')
|
||||
|
||||
# Generate the result JSON
|
||||
if [ ${exit_code} -eq 0 ]; then
|
||||
log_message "Command successful: ${command}"
|
||||
RESULT_JSON=$(printf '{"id":"%s","status":"success","command":"%s","response":"%s","queued_at":"%s","executed_at":"%s"}' \
|
||||
"${cmd_id}" "${escaped_command}" "${escaped_result}" "${timestamp}" "$(date '+%H:%M:%S')")
|
||||
else
|
||||
log_message "Command failed: ${command}"
|
||||
RESULT_JSON=$(printf '{"id":"%s","status":"error","command":"%s","error":"%s","queued_at":"%s","executed_at":"%s"}' \
|
||||
"${cmd_id}" "${escaped_command}" "${escaped_result}" "${timestamp}" "$(date '+%H:%M:%S')")
|
||||
fi
|
||||
|
||||
# Update the results file safely
|
||||
if ! current_results=$(cat "${RESULT_FILE}" 2>/dev/null); then
|
||||
log_message "Error reading results file, initializing new one"
|
||||
echo '[]' > "${RESULT_FILE}"
|
||||
current_results='[]'
|
||||
fi
|
||||
|
||||
# Append the result JSON to the results file
|
||||
if ! echo "${current_results}" | jq --argjson new "${RESULT_JSON}" '. + [$new]' > "${RESULT_FILE}.tmp"; then
|
||||
log_message "Error updating results file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
mv "${RESULT_FILE}.tmp" "${RESULT_FILE}"
|
||||
log_message "Successfully updated results file"
|
||||
return ${exit_code}
|
||||
}
|
||||
|
||||
# Check if an entry is a lock entry
|
||||
is_lock_entry() {
|
||||
local line="$1"
|
||||
echo "${line}" | grep -q "\"command\":\"\\(${ALL_LOCK_KEYWORDS}\\)\""
|
||||
return $?
|
||||
}
|
||||
|
||||
# Process pending commands in the queue
|
||||
process_pending_commands() {
|
||||
while true; do
|
||||
# Check if any lock is present
|
||||
if is_system_locked; then
|
||||
local lock_type=$(grep -o "\"command\":\"[^\"]*\"" "${QUEUE_FILE}" | grep "${ALL_LOCK_KEYWORDS}")
|
||||
log_message "System is locked: ${lock_type}, waiting..."
|
||||
sleep 0.5
|
||||
continue
|
||||
fi
|
||||
|
||||
# Read the first line from the queue
|
||||
line=$(head -n 1 "${QUEUE_FILE}" 2>/dev/null)
|
||||
|
||||
if [ -n "${line}" ]; then
|
||||
log_message "Processing queue entry: ${line}"
|
||||
|
||||
# Skip processing if it's a lock entry
|
||||
if is_lock_entry "${line}"; then
|
||||
log_message "Found lock entry, skipping"
|
||||
sed -i '1d' "${QUEUE_FILE}"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Validate JSON before processing
|
||||
if ! echo "${line}" | jq empty 2>/dev/null; then
|
||||
log_message "Invalid JSON in queue, skipping line"
|
||||
sed -i '1d' "${QUEUE_FILE}"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Parse the command, timestamp, and ID from the JSON entry
|
||||
command=$(echo "${line}" | jq -r '.command // empty')
|
||||
timestamp=$(echo "${line}" | jq -r '.timestamp // empty')
|
||||
cmd_id=$(echo "${line}" | jq -r '.id // empty')
|
||||
|
||||
if [ -z "${command}" ] || [ -z "${timestamp}" ] || [ -z "${cmd_id}" ]; then
|
||||
log_message "Missing required fields in JSON, skipping"
|
||||
sed -i '1d' "${QUEUE_FILE}"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Process the command
|
||||
process_command "${command}" "${timestamp}" "${cmd_id}"
|
||||
|
||||
# Remove the processed line from the queue
|
||||
sed -i '1d' "${QUEUE_FILE}"
|
||||
|
||||
# Add a small delay between commands
|
||||
sleep 0.1
|
||||
else
|
||||
# No commands in queue, wait briefly before checking again
|
||||
sleep 0.5
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Main queue monitoring loop
|
||||
process_queue() {
|
||||
log_message "Starting queue processor with multiple lock support"
|
||||
|
||||
while true; do
|
||||
# Process any pending commands
|
||||
process_pending_commands
|
||||
|
||||
# Wait for changes to the queue file
|
||||
inotifywait -q -e modify,create "${QUEUE_FILE}" >/dev/null 2>&1
|
||||
|
||||
# Small delay to allow file to stabilize
|
||||
sleep 0.1
|
||||
done
|
||||
}
|
||||
|
||||
# Start processing the queue
|
||||
log_message "Queue processor started with file monitoring and multiple lock support"
|
||||
process_queue
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
# Script for SMS initialization and initial fetch
|
||||
# Check if atinout and jq are installed
|
||||
if ! command -v atinout &> /dev/null || ! command -v jq &> /dev/null; then
|
||||
echo "Error: Required tools (atinout or jq) are not installed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if the device exists
|
||||
if [ ! -c "/dev/smd7" ]; then
|
||||
echo "Error: Device /dev/smd7 not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set SMS text mode
|
||||
if ! echo "AT+CMGF=1" | atinout - /dev/smd7 -; then
|
||||
echo "Error: Failed to set SMS text mode"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Wait for 2 seconds
|
||||
sleep 2
|
||||
|
||||
# Fetch initial SMS messages
|
||||
if ! echo "AT+CMGL=\"ALL\"" | atinout - /dev/smd7 - | jq -R -s '
|
||||
split("\n") |
|
||||
map(select(length > 0)) |
|
||||
map(
|
||||
select(startswith("+CMGL:") or (. != "OK" and . != "ERROR"))
|
||||
) |
|
||||
{messages: .}
|
||||
' > /tmp/sms_inbox.json; then
|
||||
echo "Error: Failed to fetch SMS messages"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Exit successfully
|
||||
exit 0
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Script path
|
||||
SCRIPT_PATH=$(readlink -f "$0")
|
||||
# Fix the spacing in the cron line to ensure exactly 5 fields
|
||||
CRON_LINE="0 0 * * * $SCRIPT_PATH"
|
||||
|
||||
# Install crontab if not already present
|
||||
if ! crontab -l | grep -Fq "$SCRIPT_PATH"; then
|
||||
# Get existing crontab - ensuring clean formatting
|
||||
(crontab -l 2>/dev/null | grep -v "$SCRIPT_PATH" || true; echo "$CRON_LINE") | crontab -
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
logger -t log_cleanup "Successfully installed crontab job"
|
||||
else
|
||||
logger -t log_cleanup "Failed to install crontab job"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Clean specified log files using echo redirection
|
||||
echo "" > /tmp/apn_profiles.log
|
||||
echo "" > /tmp/imei_profiles.log
|
||||
echo "" > /var/log/at_commands.log
|
||||
|
||||
# Add error handling
|
||||
if [ $? -ne 0 ]; then
|
||||
logger -t log_cleanup "Failed to clean one or more log files"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
logger -t log_cleanup "Successfully cleaned log files"
|
||||
@@ -0,0 +1,130 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Configuration
|
||||
LOGDIR="/www/signal_graphs"
|
||||
MAX_ENTRIES=10
|
||||
INTERVAL=60
|
||||
QUEUE_FILE="/tmp/at_pipe.txt"
|
||||
FETCH_LOCK_KEYWORD="FETCH_LOCK"
|
||||
PAUSE_FILE="/tmp/signal_logging.pause"
|
||||
|
||||
# Ensure the directory exists
|
||||
mkdir -p "$LOGDIR"
|
||||
|
||||
# Check for stale entries and clean them
|
||||
check_and_clean_stale() {
|
||||
local command_type="$1" # Either "FETCH_LOCK" or "AT_COMMAND"
|
||||
local wait_count=0
|
||||
|
||||
while [ $wait_count -lt 6 ]; do
|
||||
# Check if our type of entry exists
|
||||
if grep -q "\"command\":\"${command_type}\"" "$QUEUE_FILE"; then
|
||||
sleep 1
|
||||
wait_count=$((wait_count + 1))
|
||||
else
|
||||
# Entry is gone, we can proceed
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
# If we get here, entry is stale - remove it
|
||||
logger -t signal_metrics "Removing stale ${command_type} entry after ${wait_count}s"
|
||||
sed -i "/\"command\":\"${command_type}\"/d" "$QUEUE_FILE"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Simplified lock handling
|
||||
handle_lock() {
|
||||
# First check and clean any FETCH_LOCK entries
|
||||
check_and_clean_stale "FETCH_LOCK"
|
||||
|
||||
# Add our own entry
|
||||
printf '{"command":"AT_COMMAND","pid":"%s","timestamp":"%s"}\n' \
|
||||
"$$" \
|
||||
"$(date '+%H:%M:%S')" >>"$QUEUE_FILE"
|
||||
|
||||
# Then check and clean our own entry if it gets stuck
|
||||
check_and_clean_stale "AT_COMMAND"
|
||||
}
|
||||
|
||||
# Clean output function
|
||||
clean_output() {
|
||||
local output=""
|
||||
read -r line
|
||||
|
||||
while read -r line; do
|
||||
case "$line" in
|
||||
"OK" | "")
|
||||
continue
|
||||
;;
|
||||
*)
|
||||
if [ -n "$output" ]; then
|
||||
output="$output\\n$line"
|
||||
else
|
||||
output="$line"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "$output"
|
||||
}
|
||||
|
||||
# Execute AT command
|
||||
execute_at_command() {
|
||||
local COMMAND="$1"
|
||||
handle_lock
|
||||
local OUTPUT=$(sms_tool at "$COMMAND" -t 4 2>/dev/null | clean_output)
|
||||
sed -i "/\"pid\":\"$$\"/d" "$QUEUE_FILE" # Remove our entry
|
||||
echo "$OUTPUT"
|
||||
}
|
||||
|
||||
# Log signal metric
|
||||
log_signal_metric() {
|
||||
[ -f "$PAUSE_FILE" ] && return
|
||||
|
||||
local COMMAND="$1"
|
||||
local FILENAME="$2"
|
||||
local LOGFILE="$LOGDIR/$FILENAME"
|
||||
|
||||
mkdir -p "$(dirname "$LOGFILE")"
|
||||
|
||||
local TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
|
||||
local SIGNAL_OUTPUT=$(execute_at_command "$COMMAND")
|
||||
|
||||
[ ! -s "$LOGFILE" ] && echo "[]" >"$LOGFILE"
|
||||
|
||||
if [ -n "$SIGNAL_OUTPUT" ]; then
|
||||
local TEMP_FILE="${LOGFILE}.tmp.$$"
|
||||
if jq --arg dt "$TIMESTAMP" \
|
||||
--arg out "$SIGNAL_OUTPUT" \
|
||||
'. + [{"datetime": $dt, "output": $out}] | .[-'"$MAX_ENTRIES"':]' \
|
||||
"$LOGFILE" >"$TEMP_FILE"; then
|
||||
mv "$TEMP_FILE" "$LOGFILE"
|
||||
else
|
||||
rm -f "$TEMP_FILE"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Main continuous logging function
|
||||
start_continuous_logging() {
|
||||
sleep 20
|
||||
logger -t signal_metrics "Starting continuous signal metrics logging (PID: $$)"
|
||||
|
||||
trap 'logger -t signal_metrics "Stopping signal metrics logging"; exit 0' INT TERM
|
||||
|
||||
while true; do
|
||||
if [ ! -f "$PAUSE_FILE" ]; then
|
||||
log_signal_metric "AT+QRSRP" "rsrp.json"
|
||||
log_signal_metric "AT+QRSRQ" "rsrq.json"
|
||||
log_signal_metric "AT+QSINR" "sinr.json"
|
||||
log_signal_metric "AT+QGDCNT?;+QGDNRCNT?" "data_usage.json"
|
||||
fi
|
||||
sleep "$INTERVAL"
|
||||
done
|
||||
}
|
||||
|
||||
# Start the continuous logging
|
||||
start_continuous_logging
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set Content-Type for CGI script
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Read POST data
|
||||
read POST_DATA
|
||||
|
||||
# Debug log
|
||||
DEBUG_LOG="/tmp/password_change.log"
|
||||
|
||||
# Extract the passwords from POST data
|
||||
OLD_PASSWORD=$(echo "$POST_DATA" | sed -n 's/^.*oldPassword=\([^&]*\).*$/\1/p')
|
||||
NEW_PASSWORD=$(echo "$POST_DATA" | sed -n 's/^.*newPassword=\([^&]*\).*$/\1/p')
|
||||
|
||||
# URL-decode the passwords
|
||||
OLD_PASSWORD=$(echo "$OLD_PASSWORD" | sed 's/+/ /g;s/%\(..\)/\\x\1/g' | xargs -0 printf "%b")
|
||||
NEW_PASSWORD=$(echo "$NEW_PASSWORD" | sed 's/+/ /g;s/%\(..\)/\\x\1/g' | xargs -0 printf "%b")
|
||||
|
||||
# User to change password for
|
||||
USER="root"
|
||||
|
||||
# Verify old password first
|
||||
USER_SHADOW_ENTRY=$(grep "^$USER:" /etc/shadow)
|
||||
if [ -z "$USER_SHADOW_ENTRY" ]; then
|
||||
echo '{"state":"failed", "message":"User not found"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract current password hash and salt
|
||||
USER_HASH=$(echo "$USER_SHADOW_ENTRY" | cut -d: -f2)
|
||||
SALT=$(echo "$USER_HASH" | cut -d'$' -f3)
|
||||
|
||||
# Generate hash from old password
|
||||
OLD_GENERATED_HASH=$(echo "$OLD_PASSWORD" | openssl passwd -1 -salt "$SALT" -stdin)
|
||||
|
||||
# Verify old password
|
||||
if [ "$OLD_GENERATED_HASH" != "$USER_HASH" ]; then
|
||||
echo '{"state":"failed", "message":"Current password is incorrect"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Change password using passwd command
|
||||
# We need to pass both the new password and its confirmation
|
||||
(echo "$NEW_PASSWORD"; echo "$NEW_PASSWORD") | passwd $USER 2>> $DEBUG_LOG
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo '{"state":"success", "message":"Password changed successfully"}'
|
||||
else
|
||||
echo '{"state":"failed", "message":"Failed to change password"}'
|
||||
fi
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
# Script for SMS initialization and initial fetch
|
||||
# Check if atinout and jq are installed
|
||||
if ! command -v atinout &> /dev/null || ! command -v jq &> /dev/null; then
|
||||
echo "Error: Required tools (atinout or jq) are not installed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if the device exists
|
||||
if [ ! -c "/dev/smd7" ]; then
|
||||
echo "Error: Device /dev/smd7 not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set SMS text mode
|
||||
if ! echo "AT+CMGF=1" | atinout - /dev/smd7 -; then
|
||||
echo "Error: Failed to set SMS text mode"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Wait for 2 seconds
|
||||
sleep 2
|
||||
|
||||
# Fetch initial SMS messages
|
||||
if ! echo "AT+CMGL=\"ALL\"" | atinout - /dev/smd7 - | jq -R -s '
|
||||
split("\n") |
|
||||
map(select(length > 0)) |
|
||||
map(
|
||||
select(startswith("+CMGL:") or (. != "OK" and . != "ERROR"))
|
||||
) |
|
||||
{messages: .}
|
||||
' > /tmp/sms_inbox.json; then
|
||||
echo "Error: Failed to fetch SMS messages"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Exit successfully
|
||||
exit 0
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
# Set the content type to JSON
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
|
||||
# Configuration file path
|
||||
CONFIG_FILE="/etc/quecManager.conf"
|
||||
|
||||
# Check if the config file exists
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo '{"error": "Configuration file not found"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Initialize variables
|
||||
AT_PORT=""
|
||||
AT_PORT_CUSTOM=""
|
||||
DATA_REFRESH_RATE=""
|
||||
|
||||
# Read the config file line by line and extract values
|
||||
while IFS='=' read -r key value; do
|
||||
# Remove leading/trailing whitespace
|
||||
key=$(echo "$key" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||
value=$(echo "$value" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||
|
||||
case "$key" in
|
||||
"AT_port") AT_PORT="$value" ;;
|
||||
"AT_port_custom") AT_PORT_CUSTOM="$value" ;;
|
||||
"data_refresh_rate") DATA_REFRESH_RATE="$value" ;;
|
||||
esac
|
||||
done <"$CONFIG_FILE"
|
||||
|
||||
# Output JSON
|
||||
echo "{"
|
||||
echo " \"AT_port\": \"$AT_PORT\","
|
||||
echo " \"AT_port_custom\": \"$AT_PORT_CUSTOM\","
|
||||
echo " \"data_refresh_rate\": $DATA_REFRESH_RATE"
|
||||
echo "}"
|
||||
@@ -0,0 +1,64 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Send CGI headers first
|
||||
echo "Content-Type: application/json"
|
||||
echo "Cache-Control: no-cache"
|
||||
echo
|
||||
|
||||
# Initialize variables for file paths
|
||||
APN_SCRIPT="/etc/quecmanager/apn_profile/apnProfiles.sh"
|
||||
IMEI_SCRIPT="/etc/quecmanager/imei_profile/imeiProfiles.sh"
|
||||
|
||||
# Function to output JSON
|
||||
output_json() {
|
||||
local status="$1"
|
||||
local message="$2"
|
||||
echo "{\"status\": \"$status\", \"message\": \"$message\"}"
|
||||
}
|
||||
|
||||
# Function to execute script if it exists
|
||||
execute_if_exists() {
|
||||
local script_path="$1"
|
||||
|
||||
if [ -f "$script_path" ] && [ -x "$script_path" ]; then
|
||||
$script_path >/dev/null 2>&1
|
||||
return $?
|
||||
fi
|
||||
return 2
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
scripts_executed=0
|
||||
has_error=0
|
||||
|
||||
# Try to execute APN script
|
||||
execute_if_exists "$APN_SCRIPT"
|
||||
apn_result=$?
|
||||
if [ $apn_result -eq 0 ]; then
|
||||
scripts_executed=$(($scripts_executed + 1))
|
||||
elif [ $apn_result -eq 1 ]; then
|
||||
has_error=1
|
||||
fi
|
||||
|
||||
# Try to execute IMEI script
|
||||
execute_if_exists "$IMEI_SCRIPT"
|
||||
imei_result=$?
|
||||
if [ $imei_result -eq 0 ]; then
|
||||
scripts_executed=$(($scripts_executed + 1))
|
||||
elif [ $imei_result -eq 1 ]; then
|
||||
has_error=1
|
||||
fi
|
||||
|
||||
# Output appropriate message based on results
|
||||
if [ $scripts_executed -eq 0 ]; then
|
||||
output_json "info" "No scripts to restart"
|
||||
elif [ $has_error -eq 1 ]; then
|
||||
output_json "error" "Error executing one or more scripts"
|
||||
else
|
||||
output_json "success" "Scripts restarted successfully"
|
||||
fi
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main
|
||||
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set the content type to JSON
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
|
||||
# Get the IP address of the br-lan interface
|
||||
brlan_ip=$(ip route | grep 'dev br-lan proto kernel scope link' | awk '{print $9}')
|
||||
|
||||
# Output the IP in JSON format
|
||||
echo "{\"br_lan_ip\": \"$brlan_ip\"}"
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
# save-config.sh
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
|
||||
# Read POST data
|
||||
read -n $CONTENT_LENGTH POST_DATA
|
||||
|
||||
# Configuration file path
|
||||
CONFIG_FILE="/etc/quecManager.conf"
|
||||
|
||||
# Parse JSON input and update config file
|
||||
AT_PORT=$(echo "$POST_DATA" | grep -o '"AT_port":"[^"]*"' | cut -d'"' -f4)
|
||||
AT_PORT_CUSTOM=$(echo "$POST_DATA" | grep -o '"AT_port_custom":"[^"]*"' | cut -d'"' -f4)
|
||||
DATA_REFRESH_RATE=$(echo "$POST_DATA" | grep -o '"data_refresh_rate":"[^"]*"' | cut -d'"' -f4)
|
||||
|
||||
# Create new config content
|
||||
cat > "$CONFIG_FILE" << EOF
|
||||
AT_port = $AT_PORT
|
||||
AT_port_custom = $AT_PORT_CUSTOM
|
||||
data_refresh_rate = $DATA_REFRESH_RATE
|
||||
EOF
|
||||
|
||||
# Check if write was successful
|
||||
if [ $? -eq 0 ]; then
|
||||
echo '{"success": true, "message": "Configuration saved successfully"}'
|
||||
else
|
||||
echo '{"success": false, "error": "Failed to save configuration"}'
|
||||
fi
|
||||
Reference in New Issue
Block a user