345 lines
9.9 KiB
Bash
Executable File
345 lines
9.9 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
# Read POST data
|
|
read -r QUERY_STRING
|
|
|
|
# Function to urldecode
|
|
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
|
|
|
|
# Function to log messages
|
|
log_message() {
|
|
local level="$1"
|
|
local message="$2"
|
|
local LOG_DIR="/tmp/log/apnprofile"
|
|
local LOG_FILE="${LOG_DIR}/apnprofile.log"
|
|
|
|
mkdir -p "${LOG_DIR}"
|
|
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
|
echo "${timestamp} - [${level}] ${message}" >> "$LOG_FILE"
|
|
logger -t apnprofile "${level}: ${message}"
|
|
}
|
|
|
|
# Create required directories
|
|
mkdir -p /www/cgi-bin/services
|
|
mkdir -p /etc/init.d
|
|
|
|
# Function to create service script
|
|
create_service_script() {
|
|
cat > /www/cgi-bin/services/apnprofile.sh <<'EOL'
|
|
#!/bin/sh
|
|
|
|
# Load UCI functions
|
|
. /lib/functions.sh
|
|
|
|
# Define file paths
|
|
QUEUE_FILE="/tmp/at_pipe.txt"
|
|
LOG_DIR="/tmp/log/apnprofile"
|
|
LOG_FILE="${LOG_DIR}/apnprofile.log"
|
|
PID_FILE="/var/run/apnprofile.pid"
|
|
STATE_FILE="/tmp/apnprofile_state.json"
|
|
|
|
mkdir -p "${LOG_DIR}"
|
|
[ ! -f "${QUEUE_FILE}" ] && touch "${QUEUE_FILE}"
|
|
|
|
# Save PID
|
|
echo $$ > "${PID_FILE}"
|
|
|
|
# Enhanced logging function
|
|
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 apnprofile "${level}: ${message}"
|
|
}
|
|
|
|
# AT command handling with locking
|
|
handle_lock() {
|
|
local max_wait=30
|
|
local wait_count=0
|
|
|
|
while [ -f "$QUEUE_FILE" ] && grep -q "AT_COMMAND" "$QUEUE_FILE" && [ $wait_count -lt $max_wait ]; do
|
|
sleep 1
|
|
wait_count=$((wait_count + 1))
|
|
done
|
|
|
|
printf '{"command":"AT_COMMAND","pid":"%s","timestamp":"%s"}\n' "$$" "$(date '+%H:%M:%S')" >> "$QUEUE_FILE"
|
|
}
|
|
|
|
# Execute AT command with retries
|
|
execute_at_command() {
|
|
local command="$1"
|
|
local result=""
|
|
local retry_count=0
|
|
local max_retries=3
|
|
|
|
while [ $retry_count -lt $max_retries ]; do
|
|
handle_lock
|
|
result=$(sms_tool at "$command" -t 4 2>&1)
|
|
local status=$?
|
|
sed -i "/\"pid\":\"$$\"/d" "$QUEUE_FILE"
|
|
|
|
if [ $status -eq 0 ] && [ -n "$result" ]; then
|
|
echo "$result"
|
|
return 0
|
|
fi
|
|
|
|
retry_count=$((retry_count + 1))
|
|
[ $retry_count -lt $max_retries ] && sleep 2
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
# Get current ICCID
|
|
get_current_iccid() {
|
|
local result=$(execute_at_command "AT+ICCID")
|
|
if [ $? -eq 0 ] && echo "$result" | grep -q "+ICCID:"; then
|
|
echo "$result" | grep "+ICCID:" | cut -d' ' -f2 | tr -d '[:space:]'
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
# Set APN with error handling
|
|
set_apn() {
|
|
local pdp_type="$1"
|
|
local apn="$2"
|
|
|
|
if [ -z "$pdp_type" ] || [ -z "$apn" ]; then
|
|
return 1
|
|
fi
|
|
|
|
if execute_at_command "AT+CGDCONT=1,\"$pdp_type\",\"$apn\";+COPS=2;+COPS=0"; then
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
# Function to get current configuration hash
|
|
get_config_hash() {
|
|
config_load quecmanager
|
|
local hash_input=""
|
|
|
|
# Get Profile 1
|
|
config_get ICCID_PROFILE1 apn_profile iccid_profile1
|
|
config_get APN_PROFILE1 apn_profile apn_profile1
|
|
config_get PDP_TYPE1 apn_profile pdp_type1
|
|
|
|
# Get Profile 2
|
|
config_get ICCID_PROFILE2 apn_profile iccid_profile2
|
|
config_get APN_PROFILE2 apn_profile apn_profile2
|
|
config_get PDP_TYPE2 apn_profile pdp_type2
|
|
|
|
hash_input="${ICCID_PROFILE1}${APN_PROFILE1}${PDP_TYPE1}${ICCID_PROFILE2}${APN_PROFILE2}${PDP_TYPE2}"
|
|
echo "$hash_input" | md5sum | cut -d' ' -f1
|
|
}
|
|
|
|
# Function to read state file
|
|
read_state() {
|
|
if [ -f "$STATE_FILE" ]; then
|
|
cat "$STATE_FILE"
|
|
else
|
|
echo "{}"
|
|
fi
|
|
}
|
|
|
|
# Function to write state file
|
|
write_state() {
|
|
local current_iccid="$1"
|
|
local config_hash="$2"
|
|
local status="$3"
|
|
|
|
printf '{"iccid":"%s","config_hash":"%s","status":"%s","timestamp":"%s"}' \
|
|
"$current_iccid" "$config_hash" "$status" "$(date '+%Y-%m-%d %H:%M:%S')" > "$STATE_FILE"
|
|
}
|
|
|
|
# Main service loop
|
|
while true; do
|
|
# Get current state
|
|
current_state=$(read_state)
|
|
current_iccid=$(get_current_iccid)
|
|
config_hash=$(get_config_hash)
|
|
|
|
# Extract values from current state
|
|
state_iccid=$(echo "$current_state" | sed -n 's/.*"iccid":"\([^"]*\)".*/\1/p')
|
|
state_hash=$(echo "$current_state" | sed -n 's/.*"config_hash":"\([^"]*\)".*/\1/p')
|
|
|
|
needs_update=0
|
|
|
|
# Check if update is needed
|
|
if [ ! -f "$STATE_FILE" ]; then
|
|
log_message "INFO" "No state file found, will apply profile"
|
|
needs_update=1
|
|
elif [ "$current_iccid" != "$state_iccid" ]; then
|
|
log_message "INFO" "ICCID changed from $state_iccid to $current_iccid"
|
|
needs_update=1
|
|
elif [ "$config_hash" != "$state_hash" ]; then
|
|
log_message "INFO" "Configuration changed"
|
|
needs_update=1
|
|
fi
|
|
|
|
if [ $needs_update -eq 1 ] && [ -n "$current_iccid" ]; then
|
|
config_load quecmanager
|
|
|
|
# Get Profile 1
|
|
config_get ICCID_PROFILE1 apn_profile iccid_profile1
|
|
config_get APN_PROFILE1 apn_profile apn_profile1
|
|
config_get PDP_TYPE1 apn_profile pdp_type1
|
|
|
|
# Get Profile 2
|
|
config_get ICCID_PROFILE2 apn_profile iccid_profile2
|
|
config_get APN_PROFILE2 apn_profile apn_profile2
|
|
config_get PDP_TYPE2 apn_profile pdp_type2
|
|
|
|
if [ "${current_iccid}" = "${ICCID_PROFILE1}" ]; then
|
|
if set_apn "$PDP_TYPE1" "$APN_PROFILE1"; then
|
|
log_message "INFO" "Successfully applied Profile 1"
|
|
write_state "$current_iccid" "$config_hash" "success"
|
|
else
|
|
log_message "ERROR" "Failed to apply Profile 1"
|
|
write_state "$current_iccid" "$config_hash" "error"
|
|
fi
|
|
elif [ -n "$ICCID_PROFILE2" ] && [ "${current_iccid}" = "${ICCID_PROFILE2}" ]; then
|
|
if set_apn "$PDP_TYPE2" "$APN_PROFILE2"; then
|
|
log_message "INFO" "Successfully applied Profile 2"
|
|
write_state "$current_iccid" "$config_hash" "success"
|
|
else
|
|
log_message "ERROR" "Failed to apply Profile 2"
|
|
write_state "$current_iccid" "$config_hash" "error"
|
|
fi
|
|
else
|
|
log_message "INFO" "No matching ICCID profile found"
|
|
write_state "$current_iccid" "$config_hash" "no_match"
|
|
fi
|
|
fi
|
|
|
|
sleep 10
|
|
done
|
|
EOL
|
|
|
|
chmod 755 /www/cgi-bin/services/apnprofile.sh
|
|
}
|
|
|
|
# Function to create init.d script
|
|
create_init_script() {
|
|
cat > /etc/init.d/apnprofile-service <<'EOL'
|
|
#!/bin/sh /etc/rc.common
|
|
|
|
START=99
|
|
STOP=10
|
|
USE_PROCD=1
|
|
|
|
start_service() {
|
|
local enabled
|
|
|
|
# Check if service is enabled in UCI
|
|
config_load quecmanager
|
|
config_get enabled apn_profile enabled '0'
|
|
|
|
[ "$enabled" != "1" ] && return 0
|
|
|
|
procd_open_instance
|
|
procd_set_param command /www/cgi-bin/services/apnprofile.sh
|
|
procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
|
|
procd_set_param stdout 1
|
|
procd_set_param stderr 1
|
|
procd_set_param nice 19
|
|
procd_close_instance
|
|
}
|
|
|
|
service_triggers() {
|
|
procd_add_reload_trigger "quecmanager"
|
|
}
|
|
|
|
reload_service() {
|
|
stop
|
|
start
|
|
}
|
|
EOL
|
|
|
|
chmod 755 /etc/init.d/apnprofile-service
|
|
}
|
|
|
|
# Initialize UCI configuration
|
|
touch /etc/config/quecmanager
|
|
|
|
# Remove existing APN profile section if it exists
|
|
uci -q delete quecmanager.apn_profile
|
|
|
|
# Create new APN profile section
|
|
uci set quecmanager.apn_profile=service
|
|
uci set quecmanager.apn_profile.enabled=1
|
|
|
|
# Set Profile 1 configuration
|
|
uci set quecmanager.apn_profile.iccid_profile1="$iccidProfile1"
|
|
uci set quecmanager.apn_profile.apn_profile1="$apnProfile1"
|
|
uci set quecmanager.apn_profile.pdp_type1="$pdpType1"
|
|
|
|
# Set Profile 2 configuration if provided
|
|
if [ -n "$iccidProfile2" ]; then
|
|
uci set quecmanager.apn_profile.iccid_profile2="$iccidProfile2"
|
|
uci set quecmanager.apn_profile.apn_profile2="$apnProfile2"
|
|
uci set quecmanager.apn_profile.pdp_type2="$pdpType2"
|
|
fi
|
|
|
|
# Commit UCI changes
|
|
if ! uci commit quecmanager; then
|
|
log_message "ERROR" "Failed to save UCI configuration"
|
|
echo '{"status": "error", "message": "Failed to save UCI configuration"}'
|
|
exit 1
|
|
fi
|
|
|
|
log_message "INFO" "UCI configuration saved successfully"
|
|
|
|
# Create service script if it doesn't exist
|
|
if [ ! -f "/www/cgi-bin/services/apnprofile.sh" ]; then
|
|
create_service_script
|
|
log_message "INFO" "Created service script"
|
|
fi
|
|
|
|
# Create init.d script if it doesn't exist
|
|
if [ ! -f "/etc/init.d/apnprofile-service" ]; then
|
|
create_init_script
|
|
log_message "INFO" "Created init.d script"
|
|
fi
|
|
|
|
# Enable and start the service
|
|
/etc/init.d/apnprofile-service enable
|
|
if /etc/init.d/apnprofile-service restart; then
|
|
log_message "INFO" "Service started successfully"
|
|
echo '{"status": "success", "message": "APN profiles saved and service started"}'
|
|
else
|
|
log_message "ERROR" "Failed to start service"
|
|
echo '{"status": "error", "message": "Failed to start service"}'
|
|
fi |