Added missing cgi-bin directory

This commit is contained in:
Russel Yasol
2025-03-13 20:51:47 +08:00
parent 54e6407507
commit a0301f4cd2
104 changed files with 46764 additions and 71 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -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

View File

@@ -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"

View 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

View File

@@ -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

View File

@@ -0,0 +1,266 @@
#!/bin/sh
# AT Queue Client for OpenWRT
# Located in /www/cgi-bin/services/at_queue_client
QUEUE_DIR="/tmp/at_queue"
RESULTS_DIR="$QUEUE_DIR/results"
QUEUE_MANAGER="/www/cgi-bin/services/at_queue_manager.sh"
POLL_INTERVAL=0.01
usage() {
echo "Usage: $0 [options] <AT command>"
echo "Options:"
echo " -w Wait for command completion"
echo " -t Timeout in seconds (default: 240)"
echo " -h Show this help message"
exit 1
}
# Output JSON response
output_json() {
local content="$1"
local headers="${2:-1}" # Default to showing headers
echo "$content"
}
# URL decode function
urldecode() {
local encoded="$1"
logger -t at_queue -p daemon.debug "urldecode: input='$encoded'"
# Handle %2B -> + and %22 -> " conversions
local decoded="${encoded//%2B/+}"
decoded="${decoded//%22/\"}"
# Then handle other encoded characters
decoded=$(printf '%b' "${decoded//%/\\x}")
logger -t at_queue -p daemon.debug "urldecode: output='$decoded'"
echo "$decoded"
}
# Extract command ID from response with improved error handling
get_command_id() {
local response="$1"
echo "DEBUG: Raw response: '$response'" >&2
# Strip any headers from response
local json_response=$(echo "$response" | sed -n '/^{/,$p')
echo "DEBUG: JSON portion: '$json_response'" >&2
# Try to extract command_id using grep and sed instead of jsonfilter
local cmd_id=$(echo "$json_response" | grep -o '"command_id":"[^"]*"' | sed 's/"command_id":"//;s/"$//')
if [ -n "$cmd_id" ]; then
echo "$cmd_id"
return 0
fi
# Fallback to jsonfilter if available
echo "DEBUG: Trying jsonfilter as fallback" >&2
local cmd_id_jsonfilter=$(echo "$json_response" | jsonfilter -e '@.command_id' 2>/dev/null)
if [ -n "$cmd_id_jsonfilter" ]; then
echo "$cmd_id_jsonfilter"
return 0
fi
echo "ERROR: Failed to extract command ID from response" >&2
return 1
}
# Normalize AT command
normalize_at_command() {
local cmd="$1"
logger -t at_queue -p daemon.debug "normalize: input='$cmd'"
# URL decode the command
cmd=$(urldecode "$cmd")
logger -t at_queue -p daemon.debug "normalize: after urldecode='$cmd'"
# Remove any carriage returns or newlines
cmd=$(echo "$cmd" | tr -d '\r\n')
logger -t at_queue -p daemon.debug "normalize: after cleanup='$cmd'"
# Trim leading/trailing whitespace while preserving quotes
cmd=$(echo "$cmd" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
logger -t at_queue -p daemon.debug "normalize: final output='$cmd'"
echo "$cmd"
}
# Submit command with priority handling
submit_command() {
local cmd="$1"
local priority=10
# Set high priority for QSCAN commands for faster processing
if echo "$cmd" | grep -qi "AT+QSCAN"; then
priority=1
fi
# Submit using appropriate method
if [ "${SCRIPT_NAME}" != "" ]; then
# CGI mode - direct execution
local escaped_cmd=$(echo "$cmd" | sed 's/"/\\"/g')
QUERY_STRING="action=enqueue&command=${escaped_cmd}&priority=$priority" "$QUEUE_MANAGER"
else
# CLI mode
"$QUEUE_MANAGER" enqueue "$cmd" "$priority"
fi
}
# Check if result exists with proper error handling
check_result() {
local cmd_id="$1"
local show_headers="${2:-1}" # Add parameter for header control
if [ -f "$RESULTS_DIR/$cmd_id.json" ]; then
local result_content=$(cat "$RESULTS_DIR/$cmd_id.json")
if [ -z "$result_content" ]; then
logger -t at_queue -p daemon.error "Empty result file for command ID: $cmd_id"
local error_json="{\"error\":\"Empty result file\",\"command_id\":\"$cmd_id\"}"
output_json "$error_json" "$show_headers"
return 1
fi
output_json "$result_content" "$show_headers"
return 0
fi
local error_json="{\"error\":\"Result not found\",\"command_id\":\"$cmd_id\"}"
output_json "$error_json" "$show_headers"
return 1
}
# Wait for command completion with optimized polling and better error handling
wait_for_completion() {
local cmd_id="$1"
local timeout="$2"
local show_headers="${3:-1}"
local result_file="$RESULTS_DIR/$cmd_id.json"
if [ -z "$cmd_id" ]; then
local error_json="{\"error\":\"Invalid command ID\"}"
output_json "$error_json" "$show_headers"
return 1
fi
# First quick check
if [ -f "$result_file" ]; then
output_json "$(cat "$result_file")" "$show_headers"
return 0
fi
# Wait with shorter polling interval
local start_time=$(date +%s)
local current_time
while true; do
if [ -f "$result_file" ]; then
output_json "$(cat "$result_file")" "$show_headers"
return 0
fi
current_time=$(date +%s)
if [ $((current_time - start_time)) -ge "$timeout" ]; then
break
fi
sleep $POLL_INTERVAL
done
local error_json=$(cat << EOF
{
"error": "Timeout waiting for completion",
"command_id": "$cmd_id",
"timeout": $timeout
}
EOF
)
output_json "$error_json" "$show_headers"
return 1
}
# CGI request handling
if [ "${SCRIPT_NAME}" != "" ]; then
# Output headers only once at the beginning
echo "Content-Type: application/json"
echo ""
# Parse query string
eval $(echo "$QUERY_STRING" | sed 's/&/;/g')
# Handle different actions
if [ -n "$command_id" ]; then
# Get result for specific command ID
check_result "$command_id" "0" # Don't show headers
elif [ -n "$command" ]; then
# URL decode and normalize the command
command=$(urldecode "$command")
command=$(normalize_at_command "$command")
# Check if it's a valid AT command
if echo "$command" | grep -qi "^AT"; then
# Submit command and get response
response=$(submit_command "$command")
cmd_id=$(get_command_id "$response")
if [ "$wait" = "1" ]; then
if [ -n "$cmd_id" ]; then
wait_for_completion "$cmd_id" "${timeout:-180}" "0" # Don't show headers
else
output_json "{\"error\":\"Failed to get command ID from response\",\"response\":\"$response\"}" "0"
fi
else
output_json "$response" "0" # Don't show headers
fi
else
output_json "{\"error\":\"Invalid AT command format\"}" "0"
fi
else
output_json "{\"error\":\"No command or command_id specified\"}" "0"
fi
exit 0
fi
# CLI processing
wait_mode=0
timeout=180
while getopts "wt:h" opt; do
case $opt in
w) wait_mode=1 ;;
t) timeout="$OPTARG" ;;
h) usage ;;
?) usage ;;
esac
done
shift $((OPTIND-1))
if [ $# -eq 0 ]; then
usage
fi
# Combine remaining arguments into AT command
command="$*"
# Validate AT command format
if ! echo "$command" | grep -qi "^AT"; then
echo "Error: Command must start with 'AT'"
exit 1
fi
# Submit command and get response
response=$(submit_command "$command")
cmd_id=$(get_command_id "$response")
if [ -z "$cmd_id" ]; then
echo "Error: Failed to get command ID"
echo "Response: $response"
exit 1
fi
if [ $wait_mode -eq 1 ]; then
wait_for_completion "$cmd_id" "$timeout"
else
echo "$response"
fi

View File

@@ -0,0 +1,195 @@
#!/bin/sh
# Set content-type for JSON response
echo "Content-type: application/json"
echo ""
# Define paths and constants to match queue system
QUEUE_DIR="/tmp/at_queue"
QUEUE_MANAGER="/www/cgi-bin/services/at_queue_manager"
LOCK_ID="FETCH_DATA_$(date +%s)_$$"
TOKEN_FILE="$QUEUE_DIR/token"
# Logging function (minimized)
log_message() {
# Only log errors and critical info
if [ "$1" = "error" ] || [ "$1" = "crit" ]; then
logger -t at_queue -p "daemon.$1" "$2"
fi
}
# Enhanced JSON string escaping function
escape_json() {
printf '%s' "$1" | awk '
BEGIN { RS="\n"; ORS="\\n" }
{
gsub(/\\/, "\\\\")
gsub(/"/, "\\\"")
gsub(/\r/, "")
gsub(/\t/, "\\t")
gsub(/\f/, "\\f")
gsub(/\b/, "\\b")
print
}
' | sed 's/\\n$//'
}
# Acquire token directly (avoid CGI overhead)
acquire_token() {
local priority="${1:-10}"
local max_attempts=10
local attempt=0
while [ $attempt -lt $max_attempts ]; do
# Check if token file exists
if [ -f "$TOKEN_FILE" ]; then
local current_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id' 2>/dev/null)
local current_priority=$(cat "$TOKEN_FILE" | jsonfilter -e '@.priority' 2>/dev/null)
local timestamp=$(cat "$TOKEN_FILE" | jsonfilter -e '@.timestamp' 2>/dev/null)
local current_time=$(date +%s)
# Check for expired token (> 30 seconds old)
if [ $((current_time - timestamp)) -gt 30 ] || [ -z "$current_holder" ]; then
# Remove expired token
rm -f "$TOKEN_FILE" 2>/dev/null
elif [ $priority -lt $current_priority ]; then
# Preempt lower priority token
rm -f "$TOKEN_FILE" 2>/dev/null
else
# Try again
sleep 0.1
attempt=$((attempt + 1))
continue
fi
fi
# Try to create token file
echo "{\"id\":\"$LOCK_ID\",\"priority\":$priority,\"timestamp\":$(date +%s)}" > "$TOKEN_FILE" 2>/dev/null
chmod 644 "$TOKEN_FILE" 2>/dev/null
# Verify we got the token
local holder=$(cat "$TOKEN_FILE" 2>/dev/null | jsonfilter -e '@.id' 2>/dev/null)
if [ "$holder" = "$LOCK_ID" ]; then
return 0
fi
sleep 0.1
attempt=$((attempt + 1))
done
return 1
}
# Release token directly
release_token() {
# Only remove if it's our token
if [ -f "$TOKEN_FILE" ]; then
local current_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id' 2>/dev/null)
if [ "$current_holder" = "$LOCK_ID" ]; then
rm -f "$TOKEN_FILE" 2>/dev/null
fi
fi
}
# Direct AT command execution with minimal overhead
execute_at_command() {
local CMD="$1"
sms_tool at "$CMD" -t 3 2>/dev/null
}
# Batch process all commands with a single token
process_all_commands() {
local commands="$1"
local priority="${2:-10}"
local first=1
# Acquire a single token for all commands
if ! acquire_token "$priority"; then
log_message "error" "Failed to acquire token for batch processing"
# Return all failed responses
printf '['
first=1
for cmd in $commands; do
[ $first -eq 0 ] && printf ','
first=0
ESCAPED_CMD=$(escape_json "$cmd")
printf '{"command":"%s","response":"Failed to acquire token","status":"error"}' "${ESCAPED_CMD}"
done
printf ']\n'
return 1
fi
# Process all commands with the single token
printf '['
for cmd in $commands; do
[ $first -eq 0 ] && printf ','
first=0
OUTPUT=$(execute_at_command "$cmd")
local CMD_STATUS=$?
ESCAPED_CMD=$(escape_json "$cmd")
ESCAPED_OUTPUT=$(escape_json "$OUTPUT")
if [ $CMD_STATUS -eq 0 ] && [ -n "$OUTPUT" ]; then
printf '{"command":"%s","response":"%s","status":"success"}' \
"${ESCAPED_CMD}" \
"${ESCAPED_OUTPUT}"
else
printf '{"command":"%s","response":"Command failed","status":"error"}' \
"${ESCAPED_CMD}"
fi
done
printf ']\n'
# Release token after all commands are done
release_token
return 0
}
# Main execution with timeout and proper cleanup
trap 'release_token; exit 1' INT TERM
# 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? AT+CFUN=?'
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"'
# 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
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
# Set priority based on content
PRIORITY=10
if echo "$COMMANDS" | grep -qi "AT+QSCAN"; then
PRIORITY=1
fi
# Process commands with timeout protection
( sleep 60; kill -TERM $$ 2>/dev/null ) &
TIMEOUT_PID=$!
process_all_commands "$COMMANDS" "$PRIORITY"
# Clean up
kill $TIMEOUT_PID 2>/dev/null
release_token

View File

@@ -0,0 +1,62 @@
#!/bin/sh
# Set Content-Type for CGI script
echo "Content-type: application/json"
echo ""
# Read POST data
read -r 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" | grep -o 'password=[^&]*' | cut -d= -f2-)
# URL-decode the password while preserving most special characters
# First decode percent-encoded sequences
urldecode() {
local encoded="${1//+/ }"
printf '%b' "${encoded//%/\\x}"
}
# Decode the password
INPUT_PASSWORD=$(urldecode "$INPUT_PASSWORD")
# Basic validation to reject & and $ characters
if echo "$INPUT_PASSWORD" | grep -q '[&$]'; then
echo '{"state":"failed", "message":"Password contains forbidden characters (& or $)"}'
exit 1
fi
# Sanitize the password for shell usage
INPUT_PASSWORD=$(printf '%s' "$INPUT_PASSWORD" | sed 's/[\"]/\\&/g')
# 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
# Use printf to avoid issues with special characters in echo
GENERATED_HASH=$(printf '%s' "$INPUT_PASSWORD" | openssl passwd -1 -salt "$SALT" -stdin)
# Log generated hash for debugging
printf "Generated hash: %s\n" "$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", "message":"Authentication failed"}'
fi

View File

@@ -0,0 +1,113 @@
#!/bin/sh
# Set headers for JSON response
echo "Content-type: application/json"
echo ""
# Load UCI functions
. /lib/functions.sh
# Function to safely get UCI value with default
get_uci_value() {
local value
config_get value cell_lock "$1" "$2"
echo "${value:-$2}"
}
# Function to check if daemon is running
check_service_status() {
if [ -f "/var/run/cell_lock_scheduler.pid" ]; then
pid=$(cat /var/run/cell_lock_scheduler.pid 2>/dev/null)
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
echo "running"
return
fi
fi
echo "stopped"
}
# Function to get current status with proper JSON handling
get_current_status() {
local STATUS_FILE="/tmp/cell_lock_status.json"
local status="unknown"
local message="Status not available"
local active="0"
local locked="0"
local timestamp=$(date +%s)
if [ -f "$STATUS_FILE" ]; then
# Try to extract values from status file
if grep -q "status" "$STATUS_FILE"; then
status=$(cat "$STATUS_FILE" | jsonfilter -e '@.status' 2>/dev/null)
# Extract message and remove any surrounding quotes
message=$(cat "$STATUS_FILE" | jsonfilter -e '@.message' 2>/dev/null | sed 's/^"//;s/"$//')
active=$(cat "$STATUS_FILE" | jsonfilter -e '@.active' 2>/dev/null)
locked=$(cat "$STATUS_FILE" | jsonfilter -e '@.locked' 2>/dev/null)
timestamp=$(cat "$STATUS_FILE" | jsonfilter -e '@.timestamp' 2>/dev/null)
fi
fi
# Escape quotes and special characters in message
message=$(echo "$message" | sed 's/\\/\\\\/g; s/"/\\"/g')
# Return the status as a JSON object with properly quoted message
echo "{\"status\":\"$status\",\"message\":\"$message\",\"active\":$active,\"locked\":$locked,\"timestamp\":$timestamp}"
}
# Load configuration
config_load quecmanager
# Check if cell lock section exists
if ! uci -q get quecmanager.cell_lock >/dev/null; then
echo '{"status":"inactive","message":"Cell lock is not configured","enabled":false,"startTime":"","endTime":"","active":false,"locked":false}'
exit 0
fi
# Get service status
service_status=$(check_service_status)
# Get current status
current_status=$(get_current_status)
# Get configuration values
enabled=$(get_uci_value "enabled" "0")
start_time=$(get_uci_value "start_time" "")
end_time=$(get_uci_value "end_time" "")
active=$(get_uci_value "active" "0")
lte_params=$(get_uci_value "lte_params" "")
nr5g_params=$(get_uci_value "nr5g_params" "")
lte_persist=$(get_uci_value "lte_persist" "0")
nr5g_persist=$(get_uci_value "nr5g_persist" "0")
# Convert numeric values to boolean for JSON
enabled_bool="false"
active_bool="false"
locked_bool="false"
[ "$enabled" = "1" ] && enabled_bool="true"
[ "$active" = "1" ] && active_bool="true"
# Get locked status from current_status
locked=$(echo "$current_status" | jsonfilter -e '@.locked' 2>/dev/null)
[ "$locked" = "1" ] && locked_bool="true"
# Extract the message properly from current status
message_value=$(echo "$current_status" | jsonfilter -e '@.message' 2>/dev/null | sed 's/^"//;s/"$//')
# Prepare JSON response in format expected by the component
cat <<EOF
{
"enabled": $enabled_bool,
"start_time": "$start_time",
"end_time": "$end_time",
"active": $active_bool,
"status": "$(echo "$current_status" | jsonfilter -e '@.status')",
"message": "$message_value",
"locked": $locked_bool,
"serviceStatus": "$service_status",
"lteParams": "$lte_params",
"nr5gParams": "$nr5g_params",
"ltePersist": "$lte_persist",
"nr5gPersist": "$nr5g_persist"
}
EOF

View File

@@ -0,0 +1,205 @@
#!/bin/sh
# Set content type to JSON
echo "Content-type: application/json"
echo ""
# Configuration
UCI_CONFIG="quecmanager"
STATUS_FILE="/tmp/cell_lock_status.json"
QUEUE_DIR="/tmp/at_queue"
TOKEN_FILE="$QUEUE_DIR/token"
LOG_DIR="/tmp/log/cell_lock"
LOG_FILE="$LOG_DIR/cell_lock.log"
DEBUG_FILE="$LOG_DIR/debug.log"
# Ensure log directory exists
mkdir -p "$LOG_DIR"
# Function to log messages
log_message() {
local level="${2:-info}"
local message="$1"
local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
# Log to file
echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
# Debug logging
echo "[$timestamp] [$level] $message" >> "$DEBUG_FILE"
# Log to system log
logger -t cell_lock -p "daemon.$level" "$message"
}
# Log request details for debugging
log_request_info() {
echo "==== NEW REQUEST ====" >> "$DEBUG_FILE"
echo "METHOD: $REQUEST_METHOD" >> "$DEBUG_FILE"
echo "QUERY_STRING: $QUERY_STRING" >> "$DEBUG_FILE"
echo "CONTENT_LENGTH: $CONTENT_LENGTH" >> "$DEBUG_FILE"
echo "CONTENT_TYPE: $CONTENT_TYPE" >> "$DEBUG_FILE"
}
# Function to validate time format (HH:MM)
validate_time_format() {
local time="$1"
local name="$2"
if ! echo "$time" | grep -q '^[0-2][0-9]:[0-5][0-9]$'; then
echo "{\"status\":\"error\",\"message\":\"$name must be in format HH:MM (24-hour)\"}"
log_message "$name has invalid format: $time" "error"
return 1
fi
# Further validate hour (00-23)
local hour=$(echo "$time" | cut -d':' -f1)
if [ "$hour" -gt 23 ]; then
echo "{\"status\":\"error\",\"message\":\"Hour in $name must be between 00-23\"}"
log_message "$name has invalid hour: $hour" "error"
return 1
fi
return 0
}
# Log request info for debugging
log_request_info
# Handle GET requests for status
if [ "$REQUEST_METHOD" = "GET" ]; then
log_message "Handling GET request" "debug"
# Load UCI configuration
if [ -f "/etc/config/quecmanager" ]; then
ENABLED=$(uci -q get "$UCI_CONFIG.cell_lock.enabled" || echo "0")
START_TIME=$(uci -q get "$UCI_CONFIG.cell_lock.start_time" || echo "")
END_TIME=$(uci -q get "$UCI_CONFIG.cell_lock.end_time" || echo "")
ACTIVE=$(uci -q get "$UCI_CONFIG.cell_lock.active" || echo "0")
# Convert to JSON boolean format
[ "$ENABLED" = "1" ] && ENABLED="true" || ENABLED="false"
[ "$ACTIVE" = "1" ] && ACTIVE="true" || ACTIVE="false"
# Get current status from status file
STATUS="disabled"
MESSAGE="\"Scheduler is disabled\""
if [ -f "$STATUS_FILE" ]; then
STATUS=$(cat "$STATUS_FILE" | jsonfilter -e '@.status' 2>/dev/null)
MESSAGE=$(cat "$STATUS_FILE" | jsonfilter -e '@.message' 2>/dev/null)
if [ -n "$MESSAGE" ]; then
MESSAGE="\"$MESSAGE\""
else
MESSAGE="\"Status not available\""
fi
fi
# Output JSON response
echo "{\"enabled\":$ENABLED,\"start_time\":\"$START_TIME\",\"end_time\":\"$END_TIME\",\"active\":$ACTIVE,\"status\":\"$STATUS\",\"message\":$MESSAGE}"
log_message "Returned status response" "debug"
else
echo "{\"enabled\":false,\"start_time\":\"\",\"end_time\":\"\",\"active\":false,\"status\":\"unknown\",\"message\":\"Configuration not found\"}"
log_message "No configuration found" "warn"
fi
exit 0
fi
# Handle POST requests for enabling/disabling scheduling
if [ "$REQUEST_METHOD" = "POST" ]; then
log_message "Handling POST request" "debug"
# Read POST data
CONTENT_LENGTH=${CONTENT_LENGTH:-0}
if [ $CONTENT_LENGTH -gt 0 ]; then
POST_DATA=$(dd bs=1 count=$CONTENT_LENGTH 2>/dev/null)
echo "POST_DATA: $POST_DATA" >> "$DEBUG_FILE"
else
POST_DATA=""
echo "No POST_DATA (empty)" >> "$DEBUG_FILE"
fi
# Try to parse JSON data
if [ -n "$POST_DATA" ] && command -v jsonfilter >/dev/null 2>&1; then
log_message "Attempting to parse JSON data" "debug"
# Try to extract values from JSON - allow for differently named fields
ENABLED=$(echo "$POST_DATA" | jsonfilter -e '@.enabled' 2>/dev/null)
if [ -z "$ENABLED" ]; then
ENABLED=$(echo "$POST_DATA" | jsonfilter -e '@.enable' 2>/dev/null)
fi
START_TIME=$(echo "$POST_DATA" | jsonfilter -e '@.startTime' 2>/dev/null)
if [ -z "$START_TIME" ]; then
START_TIME=$(echo "$POST_DATA" | jsonfilter -e '@.start_time' 2>/dev/null)
fi
END_TIME=$(echo "$POST_DATA" | jsonfilter -e '@.endTime' 2>/dev/null)
if [ -z "$END_TIME" ]; then
END_TIME=$(echo "$POST_DATA" | jsonfilter -e '@.end_time' 2>/dev/null)
fi
echo "Parsed JSON: enabled=$ENABLED, start=$START_TIME, end=$END_TIME" >> "$DEBUG_FILE"
# Handle enable/disable logic
if [ "$ENABLED" = "true" ] || [ "$ENABLED" = "1" ]; then
# Validate times for enable request
if [ -z "$START_TIME" ] || [ -z "$END_TIME" ]; then
echo "{\"status\":\"error\",\"message\":\"Start time and end time are required\"}"
log_message "Missing start or end time" "error"
exit 1
fi
# Validate time formats
validate_time_format "$START_TIME" "Start time" || exit 1
validate_time_format "$END_TIME" "End time" || exit 1
# Update configuration
log_message "Enabling scheduling with start=$START_TIME, end=$END_TIME" "info"
uci -q set "$UCI_CONFIG.cell_lock=scheduler"
uci set "$UCI_CONFIG.cell_lock.enabled=1"
uci set "$UCI_CONFIG.cell_lock.start_time=$START_TIME"
uci set "$UCI_CONFIG.cell_lock.end_time=$END_TIME"
uci commit "$UCI_CONFIG"
# Ensure service is running
if [ -x "/etc/init.d/quecmanager_cell_locking" ]; then
/etc/init.d/quecmanager_cell_locking enable
/etc/init.d/quecmanager_cell_locking restart
log_message "Started scheduler service" "info"
else
log_message "Service script not found" "error"
echo "{\"status\":\"error\",\"message\":\"Service script not found\"}"
exit 1
fi
echo "{\"status\":\"success\",\"message\":\"Scheduling enabled\",\"startTime\":\"$START_TIME\",\"endTime\":\"$END_TIME\"}"
log_message "Successfully enabled scheduling" "info"
else
# Disable scheduling
log_message "Disabling scheduling" "info"
uci -q set "$UCI_CONFIG.cell_lock=scheduler"
uci set "$UCI_CONFIG.cell_lock.enabled=0"
uci commit "$UCI_CONFIG"
# Stop service
if [ -x "/etc/init.d/quecmanager_cell_locking" ]; then
/etc/init.d/quecmanager_cell_locking stop
/etc/init.d/quecmanager_cell_locking disable
log_message "Stopped scheduler service" "info"
fi
echo "{\"status\":\"success\",\"message\":\"Scheduling disabled\"}"
log_message "Successfully disabled scheduling" "info"
fi
else
log_message "Failed to parse JSON data or no JSON data received" "error"
echo "{\"status\":\"error\",\"message\":\"Invalid request or missing JSON data\"}"
fi
exit 0
fi
# If no valid method was handled
echo "{\"status\":\"error\",\"message\":\"Invalid request method\"}"
log_message "Invalid request method: $REQUEST_METHOD" "error"
exit 1

View File

@@ -0,0 +1,127 @@
#!/bin/sh
echo "Content-type: application/json"
echo ""
# Initialize error tracking
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
}
# Function to log cleanup events
log_message() {
local level="$1"
local message="$2"
local LOG_DIR="/tmp/log/apnprofile"
local LOG_FILE="${LOG_DIR}/apnprofile.log"
# Ensure log directory exists
mkdir -p "${LOG_DIR}"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "${timestamp} - [${level}] ${message}" >> "$LOG_FILE"
logger -t apnprofile "${level}: ${message}"
}
log_message "INFO" "Starting APN Profile cleanup process"
# Stop and disable the service
if [ -f "/etc/init.d/apnprofile-service" ]; then
if /etc/init.d/apnprofile-service stop; then
log_message "INFO" "APN Profile service stopped"
else
append_error "Failed to stop APN Profile service"
log_message "ERROR" "Failed to stop APN Profile service"
fi
if /etc/init.d/apnprofile-service disable; then
log_message "INFO" "APN Profile service disabled"
else
append_error "Failed to disable APN Profile service"
log_message "ERROR" "Failed to disable APN Profile service"
fi
# Remove the init.d script
if rm -f "/etc/init.d/apnprofile-service"; then
log_message "INFO" "Removed init.d script"
else
append_error "Failed to remove init.d script"
log_message "ERROR" "Failed to remove init.d script"
fi
fi
# Remove service script
if [ -f "/www/cgi-bin/services/apnprofile.sh" ]; then
if rm -f "/www/cgi-bin/services/apnprofile.sh"; then
log_message "INFO" "Removed service script"
else
append_error "Failed to remove service script"
log_message "ERROR" "Failed to remove service script"
fi
fi
# Remove symlinks in rc.d if they exist
for link in /etc/rc.d/S??apnprofile-service /etc/rc.d/K??apnprofile-service; do
if [ -L "$link" ]; then
if rm -f "$link"; then
log_message "INFO" "Removed rc.d symlink: $link"
else
append_error "Failed to remove rc.d symlink: $link"
log_message "ERROR" "Failed to remove rc.d symlink: $link"
fi
fi
done
# Remove UCI configuration (only removes apn_profile section, leaves other sections intact)
if uci -q get quecmanager.apn_profile >/dev/null; then
if uci delete quecmanager.apn_profile && uci commit quecmanager; then
log_message "INFO" "Removed UCI configuration"
else
append_error "Failed to remove UCI configuration"
log_message "ERROR" "Failed to remove UCI configuration"
fi
fi
# Kill any remaining processes
if pkill -f "/www/cgi-bin/services/apnprofile.sh"; then
log_message "INFO" "Killed remaining APN Profile processes"
fi
# Clean up temporary files
for file in \
"/tmp/at_pipe.txt" \
"/var/run/apnprofile.pid" \
"/tmp/apn_result.txt" \
"/tmp/debug.log" \
"/tmp/inputICCID.txt" \
"/tmp/outputICCID.txt" \
"/tmp/inputAPN.txt" \
"/tmp/outputAPN.txt"
do
if [ -f "$file" ]; then
if rm -f "$file"; then
log_message "INFO" "Removed temporary file: $file"
else
append_error "Failed to remove temporary file: $file"
log_message "ERROR" "Failed to remove temporary file: $file"
fi
fi
done
log_message "INFO" "APN Profile cleanup completed"
# Return appropriate JSON response
if [ "$has_error" = true ]; then
echo "{\"status\": \"error\", \"message\": \"$error_message\"}"
else
echo "{\"status\": \"success\", \"message\": \"APN Profile service successfully removed\"}"
fi

View File

@@ -0,0 +1,144 @@
#!/bin/sh
# Set headers for JSON response
echo "Content-type: application/json"
echo ""
# Load UCI functions
. /lib/functions.sh
# Function to safely get UCI value with default
get_uci_value() {
local value
config_get value apn_profile "$1" "$2"
echo "${value:-$2}"
}
# Function to check if service is running
check_service_status() {
if [ -f "/var/run/apnprofile.pid" ]; then
pid=$(cat /var/run/apnprofile.pid)
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
echo "running"
return
fi
fi
# Double check using process search
if pgrep -f "/www/cgi-bin/services/apnprofile.sh" >/dev/null; then
echo "running"
return
fi
echo "stopped"
}
# Function to get last log entry
get_last_log() {
local LOG_FILE="/tmp/log/apnprofile/apnprofile.log"
if [ -f "$LOG_FILE" ]; then
tail -n 1 "$LOG_FILE"
else
echo "No log entries found"
fi
}
# Function to check if init.d service is enabled
check_service_enabled() {
if [ -f "/etc/init.d/apnprofile-service" ]; then
if /etc/init.d/apnprofile-service enabled; then
echo "true"
return
fi
fi
echo "false"
}
# Load QuecManager configuration
config_load quecmanager
# Check if APN Profile section exists
if ! uci -q get quecmanager.apn_profile >/dev/null; then
echo '{"status": "inactive", "message": "APN Profile service is not configured"}'
exit 0
fi
# Get enabled status from UCI
enabled=$(get_uci_value "enabled" "0")
if [ "$enabled" != "1" ]; then
echo '{"status": "inactive", "message": "APN Profile service is disabled"}'
exit 0
fi
# Check if service script exists
if [ ! -f "/www/cgi-bin/services/apnprofile.sh" ]; then
echo '{"status": "error", "message": "Service script is missing"}'
exit 0
fi
# Get service status information
service_status=$(check_service_status)
service_enabled=$(check_service_enabled)
last_log=$(get_last_log)
# Fetch all configuration values from UCI
iccid_profile1=$(get_uci_value "iccid_profile1" "")
apn_profile1=$(get_uci_value "apn_profile1" "")
pdp_type1=$(get_uci_value "pdp_type1" "")
iccid_profile2=$(get_uci_value "iccid_profile2" "")
apn_profile2=$(get_uci_value "apn_profile2" "")
pdp_type2=$(get_uci_value "pdp_type2" "")
# Function to check if profile data exists
validate_profile_data() {
local iccid="$1"
local apn="$2"
local pdp="$3"
[ -n "$iccid" ] && [ -n "$apn" ] && [ -n "$pdp" ]
}
# Build JSON response
cat <<EOF
{
"status": "active",
"service": {
"status": "${service_status}",
"enabled": ${service_enabled},
"script": "$([ -f "/www/cgi-bin/services/apnprofile.sh" ] && echo "present" || echo "missing")",
"initScript": "$([ -f "/etc/init.d/apnprofile-service" ] && echo "present" || echo "missing")"
},
"profiles": {
EOF
# Add Profile 1 if it exists
if validate_profile_data "$iccid_profile1" "$apn_profile1" "$pdp_type1"; then
cat <<EOF
"profile1": {
"iccid": "${iccid_profile1}",
"apn": "${apn_profile1}",
"pdpType": "${pdp_type1}"
}
EOF
fi
# Add Profile 2 if it exists
if validate_profile_data "$iccid_profile2" "$apn_profile2" "$pdp_type2"; then
# Add comma if Profile 1 was added
[ -n "$iccid_profile1" ] && echo ","
cat <<EOF
"profile2": {
"iccid": "${iccid_profile2}",
"apn": "${apn_profile2}",
"pdpType": "${pdp_type2}"
}
EOF
fi
# Close the profiles object and add last activity
cat <<EOF
},
"lastActivity": "${last_log}"
}
EOF

View File

@@ -0,0 +1,345 @@
#!/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

View File

@@ -0,0 +1,127 @@
#!/bin/sh
echo "Content-type: application/json"
echo ""
# Initialize error tracking
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
}
# Function to log cleanup events
log_message() {
local level="$1"
local message="$2"
local LOG_DIR="/tmp/log/imeiprofile"
local LOG_FILE="${LOG_DIR}/imeiprofile.log"
# Ensure log directory exists
mkdir -p "${LOG_DIR}"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "${timestamp} - [${level}] ${message}" >> "$LOG_FILE"
logger -t imeiprofile "${level}: ${message}"
}
log_message "INFO" "Starting IMEI Profile cleanup process"
# Stop and disable the service
if [ -f "/etc/init.d/imeiprofile-service" ]; then
if /etc/init.d/imeiprofile-service stop; then
log_message "INFO" "IMEI Profile service stopped"
else
append_error "Failed to stop IMEI Profile service"
log_message "ERROR" "Failed to stop IMEI Profile service"
fi
if /etc/init.d/imeiprofile-service disable; then
log_message "INFO" "IMEI Profile service disabled"
else
append_error "Failed to disable IMEI Profile service"
log_message "ERROR" "Failed to disable IMEI Profile service"
fi
# Remove the init.d script
if rm -f "/etc/init.d/imeiprofile-service"; then
log_message "INFO" "Removed init.d script"
else
append_error "Failed to remove init.d script"
log_message "ERROR" "Failed to remove init.d script"
fi
fi
# Remove service script
if [ -f "/www/cgi-bin/services/imeiprofile.sh" ]; then
if rm -f "/www/cgi-bin/services/imeiprofile.sh"; then
log_message "INFO" "Removed service script"
else
append_error "Failed to remove service script"
log_message "ERROR" "Failed to remove service script"
fi
fi
# Remove symlinks in rc.d if they exist
for link in /etc/rc.d/S??imeiprofile-service /etc/rc.d/K??imeiprofile-service; do
if [ -L "$link" ]; then
if rm -f "$link"; then
log_message "INFO" "Removed rc.d symlink: $link"
else
append_error "Failed to remove rc.d symlink: $link"
log_message "ERROR" "Failed to remove rc.d symlink: $link"
fi
fi
done
# Remove UCI configuration
if uci -q get quecmanager.imei_profile >/dev/null; then
if uci delete quecmanager.imei_profile && uci commit quecmanager; then
log_message "INFO" "Removed UCI configuration"
else
append_error "Failed to remove UCI configuration"
log_message "ERROR" "Failed to remove UCI configuration"
fi
fi
# Kill any remaining processes
if pkill -f "/www/cgi-bin/services/imeiprofile.sh"; then
log_message "INFO" "Killed remaining IMEI Profile processes"
fi
# Clean up temporary files
for file in \
"/tmp/at_pipe.txt" \
"/var/run/imeiprofile.pid" \
"/tmp/imei_result.txt" \
"/tmp/debug.log" \
"/tmp/inputICCID.txt" \
"/tmp/outputICCID.txt" \
"/tmp/inputIMEI.txt" \
"/tmp/outputIMEI.txt"
do
if [ -f "$file" ]; then
if rm -f "$file"; then
log_message "INFO" "Removed temporary file: $file"
else
append_error "Failed to remove temporary file: $file"
log_message "ERROR" "Failed to remove temporary file: $file"
fi
fi
done
log_message "INFO" "IMEI Profile cleanup completed"
# Return appropriate JSON response
if [ "$has_error" = true ]; then
echo "{\"status\": \"error\", \"message\": \"$error_message\"}"
else
echo "{\"status\": \"success\", \"message\": \"IMEI Profile service successfully removed\"}"
fi

View File

@@ -0,0 +1,138 @@
#!/bin/sh
# Set headers for JSON response
echo "Content-type: application/json"
echo ""
# Load UCI functions
. /lib/functions.sh
# Function to safely get UCI value with default
get_uci_value() {
local value
config_get value imei_profile "$1" "$2"
echo "${value:-$2}"
}
# Function to check if service is running
check_service_status() {
if [ -f "/var/run/imeiprofile.pid" ]; then
pid=$(cat /var/run/imeiprofile.pid)
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
echo "running"
return
fi
fi
# Double check using process search
if pgrep -f "/www/cgi-bin/services/imeiprofile.sh" >/dev/null; then
echo "running"
return
fi
echo "stopped"
}
# Function to get last log entry
get_last_log() {
local LOG_FILE="/tmp/log/imeiprofile/imeiprofile.log"
if [ -f "$LOG_FILE" ]; then
tail -n 1 "$LOG_FILE"
else
echo "No log entries found"
fi
}
# Function to check if init.d service is enabled
check_service_enabled() {
if [ -f "/etc/init.d/imeiprofile-service" ]; then
if /etc/init.d/imeiprofile-service enabled; then
echo "true"
return
fi
fi
echo "false"
}
# Load QuecManager configuration
config_load quecmanager
# Check if IMEI Profile section exists
if ! uci -q get quecmanager.imei_profile >/dev/null; then
echo '{"status": "inactive", "message": "IMEI Profile service is not configured"}'
exit 0
fi
# Get enabled status from UCI
enabled=$(get_uci_value "enabled" "0")
if [ "$enabled" != "1" ]; then
echo '{"status": "inactive", "message": "IMEI Profile service is disabled"}'
exit 0
fi
# Check if service script exists
if [ ! -f "/www/cgi-bin/services/imeiprofile.sh" ]; then
echo '{"status": "error", "message": "Service script is missing"}'
exit 0
fi
# Get service status information
service_status=$(check_service_status)
service_enabled=$(check_service_enabled)
last_log=$(get_last_log)
# Fetch configuration values from UCI
iccid_profile1=$(get_uci_value "iccid_profile1" "")
imei_profile1=$(get_uci_value "imei_profile1" "")
iccid_profile2=$(get_uci_value "iccid_profile2" "")
imei_profile2=$(get_uci_value "imei_profile2" "")
# Function to check if profile data exists
validate_profile_data() {
local iccid="$1"
local imei="$2"
[ -n "$iccid" ] && [ -n "$imei" ]
}
# Build JSON response
cat <<EOF
{
"status": "active",
"service": {
"status": "${service_status}",
"enabled": ${service_enabled},
"script": "$([ -f "/www/cgi-bin/services/imeiprofile.sh" ] && echo "present" || echo "missing")",
"initScript": "$([ -f "/etc/init.d/imeiprofile-service" ] && echo "present" || echo "missing")"
},
"profiles": {
EOF
# Add Profile 1 if it exists
if validate_profile_data "$iccid_profile1" "$imei_profile1"; then
cat <<EOF
"profile1": {
"iccid": "${iccid_profile1}",
"imei": "${imei_profile1}"
}
EOF
fi
# Add Profile 2 if it exists
if validate_profile_data "$iccid_profile2" "$imei_profile2"; then
# Add comma if Profile 1 was added
[ -n "$iccid_profile1" ] && echo ","
cat <<EOF
"profile2": {
"iccid": "${iccid_profile2}",
"imei": "${imei_profile2}"
}
EOF
fi
# Close the profiles object and add last activity
cat <<EOF
},
"lastActivity": "${last_log}"
}
EOF

View File

@@ -0,0 +1,291 @@
#!/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 "'")
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
# Function to log messages
log_message() {
local level="$1"
local message="$2"
local LOG_DIR="/tmp/log/imeiprofile"
local LOG_FILE="${LOG_DIR}/imeiprofile.log"
mkdir -p "${LOG_DIR}"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "${timestamp} - [${level}] ${message}" >> "$LOG_FILE"
logger -t imeiprofile "${level}: ${message}"
}
# Create required directories
mkdir -p /www/cgi-bin/services
# Function to create service script
create_service_script() {
cat > /www/cgi-bin/services/imeiprofile.sh <<'EOL'
#!/bin/sh
# Load UCI functions
. /lib/functions.sh
# Define file paths
QUEUE_FILE="/tmp/at_pipe.txt"
LOG_DIR="/tmp/log/imeiprofile"
LOG_FILE="${LOG_DIR}/imeiprofile.log"
PID_FILE="/var/run/imeiprofile.pid"
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 imeiprofile "${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
}
# Get current IMEI
get_current_imei() {
local result=$(execute_at_command "AT+CGSN")
if [ $? -eq 0 ]; then
echo "$result" | grep -v "AT+CGSN" | grep -v "OK" | tr -d '\r\n[:space:]'
return 0
fi
return 1
}
# Set IMEI
set_imei() {
local imei="$1"
if execute_at_command "AT+EGMR=1,7,\"$imei\";+QPOWD=1"; then
return 0
fi
return 1
}
# Function to safely get UCI value with default
get_uci_value() {
local value
config_get value imei_profile "$1" "$2"
echo "${value:-$2}"
}
# Main service loop
while true; do
# Load current configuration
config_load quecmanager
# Get Profile 1
iccid_profile1=$(get_uci_value "iccid_profile1")
imei_profile1=$(get_uci_value "imei_profile1")
# Get Profile 2
iccid_profile2=$(get_uci_value "iccid_profile2")
imei_profile2=$(get_uci_value "imei_profile2")
# Get current ICCID and IMEI
current_iccid=$(get_current_iccid)
current_imei=$(get_current_imei)
if [ $? -eq 0 ] && [ -n "$current_iccid" ] && [ -n "$current_imei" ]; then
if [ "${current_iccid}" = "${iccid_profile1}" ]; then
if [ "${current_imei}" != "${imei_profile1}" ]; then
if set_imei "${imei_profile1}"; then
log_message "INFO" "Successfully applied Profile 1 IMEI"
else
log_message "ERROR" "Failed to apply Profile 1 IMEI"
fi
fi
elif [ -n "$iccid_profile2" ] && [ "${current_iccid}" = "${iccid_profile2}" ]; then
if [ "${current_imei}" != "${imei_profile2}" ]; then
if set_imei "${imei_profile2}"; then
log_message "INFO" "Successfully applied Profile 2 IMEI"
else
log_message "ERROR" "Failed to apply Profile 2 IMEI"
fi
fi
else
log_message "INFO" "No matching ICCID profile found"
fi
else
log_message "ERROR" "Failed to get current ICCID or IMEI"
fi
sleep 30
done
EOL
chmod 755 /www/cgi-bin/services/imeiprofile.sh
}
# Function to create init.d script
create_init_script() {
cat > /etc/init.d/imeiprofile-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 imei_profile enabled '0'
[ "$enabled" != "1" ] && return 0
procd_open_instance
procd_set_param command /www/cgi-bin/services/imeiprofile.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/imeiprofile-service
}
# Initialize UCI configuration
touch /etc/config/quecmanager
# Remove existing IMEI profile section if it exists
uci -q delete quecmanager.imei_profile
# Create new IMEI profile section
uci set quecmanager.imei_profile=service
uci set quecmanager.imei_profile.enabled=1
# Set Profile 1 configuration
uci set quecmanager.imei_profile.iccid_profile1="$iccidProfile1"
uci set quecmanager.imei_profile.imei_profile1="$imeiProfile1"
# Set Profile 2 configuration if provided
if [ -n "$iccidProfile2" ]; then
uci set quecmanager.imei_profile.iccid_profile2="$iccidProfile2"
uci set quecmanager.imei_profile.imei_profile2="$imeiProfile2"
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/imeiprofile.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/imeiprofile-service" ]; then
create_init_script
log_message "INFO" "Created init.d script"
fi
# Enable and start the service
/etc/init.d/imeiprofile-service enable
if /etc/init.d/imeiprofile-service restart; then
log_message "INFO" "Service started successfully"
echo '{"status": "success", "message": "IMEI profiles saved and service started"}'
else
log_message "ERROR" "Failed to start service"
echo '{"status": "error", "message": "Failed to start service"}'
fi

View File

@@ -0,0 +1,262 @@
#!/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"
QUEUE_FILE="/tmp/at_pipe.txt"
LOG_FILE="/tmp/cell_lock.log"
# Function to log messages
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 cell_lock "${level}: ${message}"
}
# Function to handle AT command queue
handle_lock() {
log_message "DEBUG" "Checking queue file status before lock"
if [ ! -f "$QUEUE_FILE" ]; then
log_message "DEBUG" "Queue file does not exist, creating it"
touch "$QUEUE_FILE"
fi
# Clean any stale entries
if grep -q "\"command\":\"AT_COMMAND\"" "$QUEUE_FILE"; then
local wait_count=0
while [ $wait_count -lt 6 ]; do
if ! grep -q "\"command\":\"AT_COMMAND\"" "$QUEUE_FILE"; then
break
fi
sleep 1
wait_count=$((wait_count + 1))
done
[ $wait_count -eq 6 ] && sed -i "/\"command\":\"AT_COMMAND\"/d" "$QUEUE_FILE"
fi
printf '{"command":"AT_COMMAND","pid":"%s","timestamp":"%s"}\n' \
"$$" \
"$(date '+%H:%M:%S')" >> "$QUEUE_FILE"
}
# Function to execute AT command
execute_at_command() {
local command="$1"
local result=""
log_message "DEBUG" "Executing AT command: ${command}"
handle_lock
result=$(sms_tool at "$command" -t 4 2>&1)
local status=$?
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
}
# Function to create set_cell_lock.sh script
create_cell_lock_script() {
if [ ! -f "$CELL_LOCK_SCRIPT" ]; then
cat >"$CELL_LOCK_SCRIPT" <<'EOL'
#!/bin/sh
ACTION=$1
LTE_PARAMS=$2
NR5G_PARAMS=$3
QUEUE_FILE="/tmp/at_pipe.txt"
LOG_FILE="/tmp/cell_lock.log"
# Import common functions
. /etc/quecmanager/imei_profile/common_functions.sh || {
echo "Failed to import common functions"
exit 1
}
case "$ACTION" in
enable)
# Enable LTE lock if parameters exist
if [ -n "$LTE_PARAMS" ]; then
execute_at_command "AT+QNWLOCK=\"common/4g\",$LTE_PARAMS"
fi
# Enable NR5G lock if parameters exist
if [ -n "$NR5G_PARAMS" ]; then
execute_at_command "AT+QNWLOCK=\"common/5g\",$NR5G_PARAMS"
fi
;;
disable)
# Disable LTE lock
execute_at_command "AT+QNWLOCK=\"common/4g\",0"
# Disable NR5G lock
execute_at_command "AT+QNWLOCK=\"common/5g\",0"
;;
*)
log_message "ERROR" "Invalid action: $ACTION"
exit 1
;;
esac
# Restart network registration to apply changes
execute_at_command "AT+COPS=2"
sleep 2
execute_at_command "AT+COPS=0"
exit 0
EOL
chmod +x "$CELL_LOCK_SCRIPT"
log_message "INFO" "Created cell lock script at $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"
log_message "INFO" "Removed 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"
log_message "INFO" "Saved configuration - Start: $1, End: $2"
}
# Function to disable scheduling
disable_scheduling() {
if [ -f "$CONFIG_FILE" ]; then
sed -i 's/ENABLED=1/ENABLED=0/' "$CONFIG_FILE"
log_message "INFO" "Disabled scheduling"
fi
crontab -l | grep -v "set_cell_lock.sh" | crontab -
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 -r POST_DATA
if echo "$POST_DATA" | grep -q "disable=true"; then
disable_scheduling
echo "Status: 200 OK"
echo "Content-Type: application/json"
echo ""
echo "{\"status\":\"success\",\"message\":\"Scheduling disabled\"}"
exit 0
fi
START_TIME=$(echo "$POST_DATA" | grep -o 'start_time=[^&]*' | cut -d'=' -f2)
END_TIME=$(echo "$POST_DATA" | grep -o 'end_time=[^&]*' | cut -d'=' -f2)
START_TIME=$(urldecode "$START_TIME")
END_TIME=$(urldecode "$END_TIME")
if [ -z "$START_TIME" ] || [ -z "$END_TIME" ]; then
log_message "ERROR" "Missing start or end time"
echo "Status: 400 Bad Request"
echo "Content-Type: application/json"
echo ""
echo "{\"error\":\"Missing start or end time\"}"
exit 1
fi
create_cell_lock_script
CRON_START=$(convert_to_cron_time "$START_TIME")
CRON_END=$(convert_to_cron_time "$END_TIME")
save_config "$START_TIME" "$END_TIME"
# Check current cell lock status and get parameters
LTE_STATUS=$(execute_at_command 'AT+QNWLOCK="common/4g"')
NR5G_STATUS=$(execute_at_command 'AT+QNWLOCK="common/5g"')
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-)
TEMP_CRON=$(mktemp)
crontab -l 2>/dev/null | grep -v "set_cell_lock.sh" >"$TEMP_CRON"
echo "$CRON_START * * * $CELL_LOCK_SCRIPT enable \"$LTE_PARAMS\" \"$NR5G_PARAMS\"" >>"$TEMP_CRON"
echo "$CRON_END * * * $CELL_LOCK_SCRIPT disable" >>"$TEMP_CRON"
crontab "$TEMP_CRON"
rm "$TEMP_CRON"
log_message "INFO" "Scheduling enabled with start time $START_TIME and end time $END_TIME"
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
log_message "ERROR" "Invalid request received"
echo "Status: 400 Bad Request"
echo "Content-Type: application/json"
echo ""
echo "{\"error\":\"Invalid request\"}"
exit 1

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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

View File

@@ -0,0 +1,63 @@
#!/bin/sh
# Set headers for JSON response
echo "Content-type: application/json"
echo ""
# Disable the service in UCI
uci set quecmanager.quecwatch.enabled='0'
if ! uci commit quecmanager; then
echo '{"status":"error","message":"Failed to update configuration"}'
exit 1
fi
# Function to log cleanup events
log_message() {
local level="$1"
local message="$2"
local LOG_DIR="/tmp/log/quecwatch"
local LOG_FILE="${LOG_DIR}/quecwatch.log"
# Ensure log directory exists
mkdir -p "${LOG_DIR}"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "${timestamp} - [${level}] ${message}" >> "$LOG_FILE"
logger -t quecwatch "${level}: ${message}"
}
# Stop the service
if [ -x "/etc/init.d/quecwatch" ]; then
if ! /etc/init.d/quecwatch stop; then
log_message "ERROR" "Failed to stop service cleanly"
# Force kill any remaining processes
if pkill -f "/www/cgi-bin/services/quecwatch.sh"; then
log_message "INFO" "Forced termination of QuecWatch processes"
fi
else
log_message "INFO" "Service stopped successfully"
fi
# Disable the service
if ! /etc/init.d/quecwatch disable; then
log_message "WARN" "Failed to disable service"
else
log_message "INFO" "Service disabled successfully"
fi
fi
# Clean up temporary files
for file in "/tmp/quecwatch_status.json" "/tmp/quecwatch_retry_count" "/var/run/quecwatch.pid"; do
if [ -f "$file" ]; then
if rm -f "$file"; then
log_message "INFO" "Removed temporary file: $file"
else
log_message "WARN" "Failed to remove temporary file: $file"
fi
fi
done
# Return success
echo '{"status":"success","message":"QuecWatch disabled successfully"}'

View File

@@ -0,0 +1,137 @@
#!/bin/sh
# Set content type to JSON
echo "Content-type: application/json"
echo ""
# Read POST data
read -r POST_DATA
# Function to extract value from JSON post data
extract_json_value() {
local key="$1"
local default="$2"
# Try with jsonfilter
if command -v jsonfilter >/dev/null 2>&1; then
local value=$(echo "$POST_DATA" | jsonfilter -e "@.$key" 2>/dev/null)
[ -n "$value" ] && echo "$value" && return 0
fi
# Fallback to grep
local value=$(echo "$POST_DATA" | grep -o "\"$key\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" | cut -d'"' -f4)
[ -n "$value" ] && echo "$value" && return 0
# Fallback to grep for numbers and booleans
local value=$(echo "$POST_DATA" | grep -o "\"$key\"[[:space:]]*:[[:space:]]*[0-9a-zA-Z]*" | cut -d':' -f2 | tr -d '[:space:]')
[ -n "$value" ] && echo "$value" && return 0
# Return default value
echo "$default"
return 0
}
# Extract parameters from POST data
ping_target=$(extract_json_value "pingTarget" "8.8.8.8")
ping_interval=$(extract_json_value "pingInterval" "60")
ping_failures=$(extract_json_value "pingFailures" "3")
max_retries=$(extract_json_value "maxRetries" "5")
connection_refresh=$(extract_json_value "connectionRefresh" "false")
auto_sim_failover=$(extract_json_value "autoSimFailover" "false")
sim_failover_schedule=$(extract_json_value "simFailoverSchedule" "0")
# Validate numeric values
validate_number() {
local value="$1"
local min="$2"
local max="$3"
local name="$4"
if ! echo "$value" | grep -q '^[0-9]\+$'; then
echo '{"status":"error","message":"'"$name must be a number"'"}'
exit 1
fi
if [ "$value" -lt "$min" ] || [ "$value" -gt "$max" ]; then
echo '{"status":"error","message":"'"$name must be between $min and $max"'"}'
exit 1
fi
}
# Validate boolean values
validate_boolean() {
local value="$1"
local name="$2"
if [ "$value" != "true" ] && [ "$value" != "false" ]; then
echo '{"status":"error","message":"'"$name must be true or false"'"}'
exit 1
fi
}
# Validate parameters
validate_number "$ping_interval" 5 3600 "Ping interval"
validate_number "$ping_failures" 1 10 "Ping failures"
validate_number "$max_retries" 1 20 "Max retries"
validate_number "$sim_failover_schedule" 0 1440 "SIM failover schedule"
validate_boolean "$connection_refresh" "Connection refresh"
validate_boolean "$auto_sim_failover" "Auto SIM failover"
# Function to setup UCI configuration
setup_uci_config() {
# Create section if it doesn't exist
touch /etc/config/quecmanager
if ! uci -q get quecmanager.quecwatch >/dev/null; then
uci set quecmanager.quecwatch=service
fi
# Set UCI values
uci set quecmanager.quecwatch.enabled='1'
uci set quecmanager.quecwatch.ping_target="$ping_target"
uci set quecmanager.quecwatch.ping_interval="$ping_interval"
uci set quecmanager.quecwatch.ping_failures="$ping_failures"
uci set quecmanager.quecwatch.max_retries="$max_retries"
uci set quecmanager.quecwatch.current_retries='0'
uci set quecmanager.quecwatch.connection_refresh="$connection_refresh"
uci set quecmanager.quecwatch.refresh_count='3'
uci set quecmanager.quecwatch.auto_sim_failover="$auto_sim_failover"
uci set quecmanager.quecwatch.sim_failover_schedule="$sim_failover_schedule"
# Commit changes
if ! uci commit quecmanager; then
echo '{"status":"error","message":"Failed to save configuration"}'
exit 1
fi
return 0
}
# Setup configuration
if ! setup_uci_config; then
exit 1
fi
# Enable and start the service
if [ ! -f "/etc/init.d/quecwatch" ]; then
echo '{"status":"error","message":"QuecWatch service script not found"}'
exit 1
fi
# Make sure the service script is executable
chmod +x /etc/init.d/quecwatch
# Enable the service
if ! /etc/init.d/quecwatch enable; then
echo '{"status":"error","message":"Failed to enable QuecWatch service"}'
exit 1
fi
# Start the service
if ! /etc/init.d/quecwatch start; then
echo '{"status":"error","message":"Failed to start QuecWatch service"}'
exit 1
fi
# Return success response
echo '{"status":"success","message":"QuecWatch enabled successfully"}'

View File

@@ -0,0 +1,139 @@
#!/bin/sh
# Set headers for JSON response
echo "Content-type: application/json"
echo ""
# Load UCI functions
. /lib/functions.sh
# Function to safely get UCI value with default
get_uci_value() {
local value
config_get value quecwatch "$1" "$2"
echo "${value:-$2}"
}
# Function to format boolean for JSON
format_boolean() {
if [ "$1" = "1" ] || [ "$1" = "true" ]; then
echo "true"
else
echo "false"
fi
}
# Function to check if service is running
check_service_status() {
if [ -f "/var/run/quecwatch.pid" ]; then
pid=$(cat /var/run/quecwatch.pid 2>/dev/null)
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
echo "running"
return
fi
fi
echo "stopped"
}
# Function to get last log entry
get_last_log() {
local LOG_FILE="/tmp/log/quecwatch/quecwatch.log"
if [ -f "$LOG_FILE" ]; then
tail -n 1 "$LOG_FILE" | sed 's/"/\\"/g'
else
echo "No log entries found"
fi
}
# Function to get current status
get_current_status() {
local STATUS_FILE="/tmp/quecwatch_status.json"
local status="unknown"
local message="Status not available"
local retry="0"
local maxRetries="0"
local timestamp=$(date +%s)
if [ -f "$STATUS_FILE" ]; then
# Try to extract values from status file
if grep -q "status" "$STATUS_FILE"; then
status=$(cat "$STATUS_FILE" | jsonfilter -e '@.status' 2>/dev/null)
message=$(cat "$STATUS_FILE" | jsonfilter -e '@.message' 2>/dev/null)
retry=$(cat "$STATUS_FILE" | jsonfilter -e '@.retry' 2>/dev/null)
maxRetries=$(cat "$STATUS_FILE" | jsonfilter -e '@.maxRetries' 2>/dev/null)
timestamp=$(cat "$STATUS_FILE" | jsonfilter -e '@.timestamp' 2>/dev/null)
fi
fi
# Use defaults if extraction failed
[ -z "$status" ] && status="unknown"
[ -z "$message" ] && message="Status not available"
[ -z "$retry" ] && retry="0"
[ -z "$maxRetries" ] && maxRetries="0"
[ -z "$timestamp" ] && timestamp=$(date +%s)
echo "{\"status\":\"$status\",\"message\":\"$message\",\"retry\":$retry,\"maxRetries\":$maxRetries,\"timestamp\":$timestamp}"
}
# Load QuecManager configuration
config_load quecmanager
# Check if QuecWatch section exists
if ! uci -q get quecmanager.quecwatch >/dev/null; then
echo '{"status":"inactive","message":"QuecWatch is not configured"}'
exit 0
fi
# Get enabled status
enabled=$(get_uci_value "enabled" "0")
# Get service status
service_status=$(check_service_status)
# Get current status
current_status=$(get_current_status)
# Get last log entry
last_log=$(get_last_log)
# Fetch all configuration values
ping_target=$(get_uci_value "ping_target" "8.8.8.8")
ping_interval=$(get_uci_value "ping_interval" "60")
ping_failures=$(get_uci_value "ping_failures" "3")
max_retries=$(get_uci_value "max_retries" "5")
current_retries=$(get_uci_value "current_retries" "0")
connection_refresh=$(format_boolean $(get_uci_value "connection_refresh" "false"))
refresh_count=$(get_uci_value "refresh_count" "3")
auto_sim_failover=$(format_boolean $(get_uci_value "auto_sim_failover" "false"))
sim_failover_schedule=$(get_uci_value "sim_failover_schedule" "0")
# Determine the overall status
status="inactive"
if [ "$enabled" = "1" ]; then
if [ "$service_status" = "running" ]; then
status="active"
else
status="error"
fi
fi
# Prepare JSON response
cat <<EOF
{
"status": "$status",
"serviceStatus": "$service_status",
"currentStatus": $current_status,
"config": {
"pingTarget": "$ping_target",
"pingInterval": $ping_interval,
"pingFailures": $ping_failures,
"maxRetries": $max_retries,
"currentRetries": $current_retries,
"connectionRefresh": $connection_refresh,
"refreshCount": $refresh_count,
"autoSimFailover": $auto_sim_failover,
"simFailoverSchedule": $sim_failover_schedule
},
"lastActivity": "$last_log"
}
EOF

View File

@@ -0,0 +1,57 @@
#!/bin/sh
# Set headers for JSON response
echo "Content-type: application/json"
echo ""
# Function to log message
log_message() {
local level="$1"
local message="$2"
local LOG_DIR="/tmp/log/quecwatch"
local LOG_FILE="${LOG_DIR}/quecwatch.log"
# Ensure log directory exists
mkdir -p "${LOG_DIR}"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "${timestamp} - [${level}] ${message}" >> "$LOG_FILE"
logger -t quecwatch "${level}: ${message}"
}
# Reset retry counter
if uci -q get quecmanager.quecwatch >/dev/null; then
# Reset retry counter in UCI
uci set quecmanager.quecwatch.current_retries='0'
# Make sure service is enabled
uci set quecmanager.quecwatch.enabled='1'
# Commit changes
if uci commit quecmanager; then
log_message "INFO" "Retry counter reset to 0 and service enabled"
# Also update the retry count file for immediate effect
echo "0" > "/tmp/quecwatch_retry_count"
chmod 644 "/tmp/quecwatch_retry_count"
# Restart the service if it exists
if [ -x "/etc/init.d/quecwatch" ]; then
if /etc/init.d/quecwatch restart; then
log_message "INFO" "Service restarted successfully"
echo '{"status":"success","message":"Retry counter reset and service restarted successfully"}'
else
log_message "ERROR" "Failed to restart service"
echo '{"status":"warning","message":"Retry counter reset but failed to restart service"}'
fi
else
log_message "ERROR" "Service init script not found"
echo '{"status":"warning","message":"Retry counter reset but service init script not found"}'
fi
else
log_message "ERROR" "Failed to update configuration"
echo '{"status":"error","message":"Failed to update configuration"}'
fi
else
echo '{"status":"error","message":"QuecWatch configuration not found"}'
fi

View File

@@ -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}'

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,95 @@
#!/bin/sh
# Location: /www/cgi-bin/quecmanager/profiles/check_status.cgi
# Set content type to JSON
echo "Content-type: application/json"
echo ""
# Configuration
STATUS_FILE="/tmp/quecprofiles_status.json"
TRACK_FILE="/tmp/quecprofiles_active"
# Function to log messages
log_message() {
local level="${2:-info}"
logger -t quecprofiles -p "daemon.$level" "status_check: $1"
}
# Function to output default "idle" JSON
output_idle_json() {
cat <<EOF
{
"status": "idle",
"message": "No active profile operations",
"profile": "unknown",
"progress": 0,
"timestamp": $(date +%s)
}
EOF
exit 0
}
# Check if status file exists
if [ -f "$STATUS_FILE" ]; then
# Check if file is not empty
if [ -s "$STATUS_FILE" ]; then
# Cat the entire file content (more reliable than grep)
status_content=$(cat "$STATUS_FILE")
# Log content for debugging
log_message "Status file content: $status_content" "debug"
# Check if it looks like valid JSON
if echo "$status_content" | grep -q "status"; then
# Output the status file content
cat "$STATUS_FILE"
# Extract status for logging only
status=$(echo "$status_content" | sed -n 's/.*"status":"\([^"]*\)".*/\1/p')
log_message "Status from file: $status" "info"
exit 0
else
log_message "Status file exists but not valid JSON" "warn"
fi
else
log_message "Status file exists but empty" "warn"
fi
fi
# If we get here, either no file exists or it's invalid/old
# Check if track file exists (as a fallback)
if [ -f "$TRACK_FILE" ]; then
status_info=$(cat "$TRACK_FILE")
status=$(echo "$status_info" | cut -d':' -f1)
profile=$(echo "$status_info" | cut -d':' -f2)
progress=$(echo "$status_info" | cut -d':' -f3)
# Make sure the message reflects the actual status
if [ "$status" = "success" ]; then
message="Profile successfully applied"
elif [ "$status" = "applying" ]; then
message="Profile operation in progress"
elif [ "$status" = "error" ]; then
message="Profile operation failed"
elif [ "$status" = "rebooting" ]; then
message="Device is rebooting to apply changes"
else
message="Profile operation status: $status"
fi
# Output JSON based on track file
cat <<EOF
{
"status": "$status",
"message": "$message",
"profile": "$profile",
"progress": $progress,
"timestamp": $(date +%s)
}
EOF
log_message "Retrieved status from track file: $status" "info"
exit 0
fi
# If no valid files found, output idle state
output_idle_json

View File

@@ -0,0 +1,154 @@
#!/bin/sh
# Location: /www/cgi-bin/quecmanager/profiles/list_profiles.sh
# Set content type to JSON and ensure blank line is output
echo "Content-type: application/json"
echo ""
# Function to log messages
log_message() {
local level="${2:-info}"
logger -t quecprofiles -p "daemon.$level" "list_profiles: $1"
# Also log to our error file
echo "[$(date)] $level: $1" >>/tmp/list_profiles_error.log
}
# Function to output JSON error response
output_error() {
local message="$1"
echo "{\"status\":\"error\",\"message\":\"$message\",\"profiles\":[]}"
log_message "$message" "error"
exit 1
}
# Function to sanitize string for JSON
sanitize_for_json() {
echo "$1" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed 's/\t/\\t/g' | tr -d '\r\n'
}
# Check if UCI command exists
if ! which uci >/dev/null 2>&1; then
output_error "UCI command not found"
fi
# Function to extract profiles from UCI config
get_profiles() {
log_message "Fetching profiles from UCI config"
# Check if UCI config exists
if [ ! -f /etc/config/quecprofiles ]; then
log_message "No profiles config found" "warn"
echo "{\"status\":\"success\",\"profiles\":[]}"
return 0
fi
# Start JSON output
local json_output=""
local first=1
local count=0
# Get all profile indices - make sure this succeeds
local indices=$(uci -q show quecprofiles | grep -o '@profile\[[0-9]*\]' | sort -u)
# Debug output
echo "Found indices: $indices" >>/tmp/list_profiles_error.log
if [ -z "$indices" ]; then
log_message "No profile indices found" "warn"
echo "{\"status\":\"success\",\"profiles\":[]}"
return 0
fi
# Process each profile
for idx in $indices; do
log_message "Processing profile index: $idx"
# Try different UCI get approaches
local name
name=$(uci -q get "quecprofiles.$idx.name" 2>/dev/null)
if [ -z "$name" ]; then
log_message "Failed to get name for $idx, trying alternative method" "warn"
local section=${idx#@profile[}
section=${section%]}
name=$(uci -q get "quecprofiles.@profile[$section].name" 2>/dev/null)
fi
# Get profile details
local iccid=$(uci -q get "quecprofiles.$idx.iccid" 2>/dev/null)
local imei=$(uci -q get "quecprofiles.$idx.imei" 2>/dev/null)
local apn=$(uci -q get "quecprofiles.$idx.apn" 2>/dev/null)
local pdp_type=$(uci -q get "quecprofiles.$idx.pdp_type" 2>/dev/null)
local lte_bands=$(uci -q get "quecprofiles.$idx.lte_bands" 2>/dev/null)
local sa_nr5g_bands=$(uci -q get "quecprofiles.$idx.sa_nr5g_bands" 2>/dev/null)
local nsa_nr5g_bands=$(uci -q get "quecprofiles.$idx.nsa_nr5g_bands" 2>/dev/null)
local network_type=$(uci -q get "quecprofiles.$idx.network_type" 2>/dev/null)
local ttl=$(uci -q get "quecprofiles.$idx.ttl" 2>/dev/null)
# Debug output
log_message "Retrieved for $idx: name=$name, iccid=$iccid, apn=$apn"
# Skip if missing required fields
if [ -z "$name" ] || [ -z "$iccid" ] || [ -z "$apn" ]; then
log_message "Skipping invalid profile: $idx (missing required fields)" "warn"
continue
fi
# Sanitize all values to ensure valid JSON
name=$(sanitize_for_json "$name")
iccid=$(sanitize_for_json "$iccid")
imei=$(sanitize_for_json "${imei:-""}")
apn=$(sanitize_for_json "$apn")
pdp_type=$(sanitize_for_json "${pdp_type:-"IPV4V6"}")
lte_bands=$(sanitize_for_json "${lte_bands:-""}")
sa_nr5g_bands=$(sanitize_for_json "${sa_nr5g_bands:-""}")
nsa_nr5g_bands=$(sanitize_for_json "${nsa_nr5g_bands:-""}")
network_type=$(sanitize_for_json "${network_type:-"LTE"}")
ttl=$(sanitize_for_json "${ttl:-0}")
# Create profile JSON
local profile_json="{"
profile_json="${profile_json}\"name\":\"${name}\","
profile_json="${profile_json}\"iccid\":\"${iccid}\","
profile_json="${profile_json}\"imei\":\"${imei}\","
profile_json="${profile_json}\"apn\":\"${apn}\","
profile_json="${profile_json}\"pdp_type\":\"${pdp_type}\","
profile_json="${profile_json}\"lte_bands\":\"${lte_bands}\","
profile_json="${profile_json}\"sa_nr5g_bands\":\"${sa_nr5g_bands}\","
profile_json="${profile_json}\"nsa_nr5g_bands\":\"${nsa_nr5g_bands}\","
profile_json="${profile_json}\"network_type\":\"${network_type}\","
profile_json="${profile_json}\"ttl\":\"${ttl}\""
profile_json="${profile_json}}"
# Add comma if not first
if [ $first -eq 0 ]; then
json_output="${json_output},"
else
first=0
fi
# Add profile to output
json_output="${json_output}${profile_json}"
count=$((count+1))
done
# Complete the JSON response
local response="{\"status\":\"success\",\"profiles\":[${json_output}]}"
# Save the response for debugging
echo "$response" > /tmp/list_profiles_response.json
echo "$response"
log_message "Found and returned $count profiles"
return 0
}
# Start fresh error log
echo "=== List Profiles Run $(date) ===" > /tmp/list_profiles_error.log
# Main execution
{
get_profiles
} || {
# Error handler
output_error "Failed to retrieve profiles"
}

View File

@@ -0,0 +1,355 @@
#!/bin/sh
# Location: /www/cgi-bin/quecmanager/profiles/quec_profile_create.sh
# Set content type to JSON
echo -n ""
echo "Content-type: application/json"
echo ""
# Function to log messages
log_message() {
local level="${2:-info}"
logger -t quecprofiles -p "daemon.$level" "create: $1"
}
# Function to output JSON response
output_json() {
local status="$1"
local message="$2"
local data="${3:-{}}"
printf '{"status":"%s","message":"%s","data":%s}\n' "$status" "$message" "$data"
exit 0
}
# Function to sanitize input
sanitize() {
echo "$1" | tr -d '\r\n' | sed 's/[^a-zA-Z0-9,.:_-]//g'
}
# Function to validate ICCID (simple check)
validate_iccid() {
local iccid="$1"
if [ -z "$iccid" ] || [ ${#iccid} -lt 10 ] || [ ${#iccid} -gt 20 ]; then
return 1
fi
# Check that it's only digits
if ! echo "$iccid" | grep -q '^[0-9]\+$'; then
return 1
fi
return 0
}
# Function to validate IMEI (simple check)
validate_imei() {
local imei="$1"
if [ -z "$imei" ]; then
return 0 # IMEI is optional
fi
if [ ${#imei} -ne 15 ] || ! echo "$imei" | grep -q '^[0-9]\+$'; then
return 1
fi
return 0
}
# Function to validate band list
validate_bands() {
local bands="$1"
if [ -z "$bands" ]; then
return 0 # Empty is valid
fi
# Check format (comma-separated numbers)
if ! echo "$bands" | grep -q '^[0-9]\+\(,[0-9]\+\)*$'; then
return 1
fi
return 0
}
# Function to validate network type
validate_network_type() {
local net_type="$1"
case "$net_type" in
"LTE" | "NR5G" | "LTE:NR5G")
return 0
;;
*)
return 1
;;
esac
}
# Function to validate PDP type
validate_pdp_type() {
local pdp_type="$1"
case "$pdp_type" in
"IP" | "IPV6" | "IPV4V6")
return 0
;;
*)
return 1
;;
esac
}
# Add function to validate TTL
validate_ttl() {
local ttl="$1"
if [ -z "$ttl" ]; then
return 0 # Empty is valid (will be treated as 0/disabled)
fi
# Check that TTL is a number between 0 and 255
if ! echo "$ttl" | grep -q '^[0-9]\+$' || [ "$ttl" -gt 255 ]; then
return 1
fi
return 0
}
# Function to check if a profile with the same name or ICCID already exists
check_duplicate_profile() {
local name="$1"
local iccid="$2"
# Check for duplicate name
local existing_name=$(uci -q show quecprofiles | grep ".name='$name'" | head -n 1)
if [ -n "$existing_name" ]; then
return 1
fi
# Check for duplicate ICCID
local existing_iccid=$(uci -q show quecprofiles | grep ".iccid='$iccid'" | head -n 1)
if [ -n "$existing_iccid" ]; then
return 2
fi
return 0
}
# Function to create new profile
create_profile() {
local name="$1"
local iccid="$2"
local imei="$3"
local apn="$4"
local pdp_type="$5"
local lte_bands="$6"
local sa_nr5g_bands="$7"
local nsa_nr5g_bands="$8"
local network_type="$9"
local ttl="${10}"
# Generate a unique ID for the profile
local profile_id="profile_$(date +%s)_$(head -c 4 /dev/urandom | hexdump -e '"%x"')"
# Add to UCI config
uci -q batch <<EOF
add quecprofiles profile
set quecprofiles.@profile[-1].name='$name'
set quecprofiles.@profile[-1].iccid='$iccid'
set quecprofiles.@profile[-1].imei='$imei'
set quecprofiles.@profile[-1].apn='$apn'
set quecprofiles.@profile[-1].pdp_type='$pdp_type'
set quecprofiles.@profile[-1].lte_bands='$lte_bands'
set quecprofiles.@profile[-1].sa_nr5g_bands='$sa_nr5g_bands'
set quecprofiles.@profile[-1].nsa_nr5g_bands='$nsa_nr5g_bands'
set quecprofiles.@profile[-1].network_type='$network_type'
set quecprofiles.@profile[-1].ttl='$ttl'
commit quecprofiles
EOF
# Check if the operation was successful
if [ $? -eq 0 ]; then
log_message "Successfully created profile '$name' for ICCID $iccid"
return 0
else
log_message "Failed to create profile '$name'" "error"
return 1
fi
}
# Output debug info
log_message "Received create profile request" "debug"
# Ensure UCI config exists
if [ ! -f /etc/config/quecprofiles ]; then
# Create initial config file
cat >/etc/config/quecprofiles <<EOF
config quecprofiles 'settings'
option check_interval '60'
option enable_autoswitch '1'
option apply_priority '20'
EOF
log_message "Created initial quecprofiles config file"
fi
# Get POST data
if [ "$REQUEST_METHOD" = "POST" ]; then
# Get content length
CONTENT_LENGTH=$(echo "$CONTENT_LENGTH" | tr -cd '0-9')
if [ -n "$CONTENT_LENGTH" ]; then
# Read POST data
POST_DATA=$(dd bs=1 count=$CONTENT_LENGTH 2>/dev/null)
# Debug log
log_message "Received POST data: $POST_DATA" "debug"
# Parse JSON with jsonfilter if available
if command -v jsonfilter >/dev/null 2>&1; then
name=$(echo "$POST_DATA" | jsonfilter -e '@.name' 2>/dev/null)
iccid=$(echo "$POST_DATA" | jsonfilter -e '@.iccid' 2>/dev/null)
imei=$(echo "$POST_DATA" | jsonfilter -e '@.imei' 2>/dev/null)
apn=$(echo "$POST_DATA" | jsonfilter -e '@.apn' 2>/dev/null)
pdp_type=$(echo "$POST_DATA" | jsonfilter -e '@.pdp_type' 2>/dev/null)
lte_bands=$(echo "$POST_DATA" | jsonfilter -e '@.lte_bands' 2>/dev/null)
sa_nr5g_bands=$(echo "$POST_DATA" | jsonfilter -e '@.sa_nr5g_bands' 2>/dev/null)
nsa_nr5g_bands=$(echo "$POST_DATA" | jsonfilter -e '@.nsa_nr5g_bands' 2>/dev/null)
network_type=$(echo "$POST_DATA" | jsonfilter -e '@.network_type' 2>/dev/null)
ttl=$(echo "$POST_DATA" | jsonfilter -e '@.ttl' 2>/dev/null)
log_message "Parsed JSON data for profile: $name" "debug"
else
# If jsonfilter is not available, try basic parsing
# This is less reliable but might work for simple cases
name=$(echo "$POST_DATA" | grep -o '"name":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
iccid=$(echo "$POST_DATA" | grep -o '"iccid":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
imei=$(echo "$POST_DATA" | grep -o '"imei":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
apn=$(echo "$POST_DATA" | grep -o '"apn":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
pdp_type=$(echo "$POST_DATA" | grep -o '"pdp_type":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
lte_bands=$(echo "$POST_DATA" | grep -o '"lte_bands":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
sa_nr5g_bands=$(echo "$POST_DATA" | grep -o '"sa_nr5g_bands":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
nsa_nr5g_bands=$(echo "$POST_DATA" | grep -o '"nsa_nr5g_bands":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
network_type=$(echo "$POST_DATA" | grep -o '"network_type":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
ttl=$(echo "$POST_DATA" | grep -o '"ttl":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
log_message "Basic parsing for profile: $name" "warn"
fi
else
log_message "No content length specified" "error"
output_json "error" "No data received"
fi
else
# URL parameters for GET requests (less secure, but supported for testing)
name=$(echo "$QUERY_STRING" | grep -o 'name=[^&]*' | cut -d'=' -f2)
iccid=$(echo "$QUERY_STRING" | grep -o 'iccid=[^&]*' | cut -d'=' -f2)
imei=$(echo "$QUERY_STRING" | grep -o 'imei=[^&]*' | cut -d'=' -f2)
apn=$(echo "$QUERY_STRING" | grep -o 'apn=[^&]*' | cut -d'=' -f2)
pdp_type=$(echo "$QUERY_STRING" | grep -o 'pdp_type=[^&]*' | cut -d'=' -f2)
lte_bands=$(echo "$QUERY_STRING" | grep -o 'lte_bands=[^&]*' | cut -d'=' -f2)
sa_nr5g_bands=$(echo "$QUERY_STRING" | grep -o 'sa_nr5g_bands=[^&]*' | cut -d'=' -f2)
nsa_nr5g_bands=$(echo "$QUERY_STRING" | grep -o 'nsa_nr5g_bands=[^&]*' | cut -d'=' -f2)
network_type=$(echo "$QUERY_STRING" | grep -o 'network_type=[^&]*' | cut -d'=' -f2)
ttl=$(echo "$QUERY_STRING" | grep -o 'ttl=[^&]*' | cut -d'=' -f2)
# URL decode values
name=$(echo "$name" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
iccid=$(echo "$iccid" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
imei=$(echo "$imei" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
apn=$(echo "$apn" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
pdp_type=$(echo "$pdp_type" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
lte_bands=$(echo "$lte_bands" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
sa_nr5g_bands=$(echo "$sa_nr5g_bands" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
nsa_nr5g_bands=$(echo "$nsa_nr5g_bands" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
network_type=$(echo "$network_type" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
ttl=$(echo "$ttl" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
log_message "Using URL parameters" "warn"
fi
# Sanitize inputs
name=$(sanitize "${name:-}")
iccid=$(sanitize "${iccid:-}")
imei=$(sanitize "${imei:-}")
apn=$(sanitize "${apn:-}")
pdp_type=$(sanitize "${pdp_type:-IP}")
lte_bands=$(sanitize "${lte_bands:-}")
sa_nr5g_bands=$(sanitize "${sa_nr5g_bands:-}")
nsa_nr5g_bands=$(sanitize "${nsa_nr5g_bands:-}")
network_type=$(sanitize "${network_type:-LTE}")
ttl=$(sanitize "${ttl:-0}") # Default to 0 (disabled)
# Output debug info
log_message "Creating profile: $name, ICCID: $iccid, IMEI: $imei, APN: $apn" "debug"
# Validate required inputs
if [ -z "$name" ]; then
log_message "Profile name is missing" "error"
output_json "error" "Profile name is required"
fi
if [ -z "$iccid" ]; then
log_message "ICCID is missing" "error"
output_json "error" "ICCID is required"
fi
if [ -z "$apn" ]; then
log_message "APN is missing" "error"
output_json "error" "APN is required"
fi
# Validate input formats
if ! validate_iccid "$iccid"; then
log_message "Invalid ICCID format: $iccid" "error"
output_json "error" "Invalid ICCID format. It should be 10-20 digits."
fi
if ! validate_imei "$imei"; then
log_message "Invalid IMEI format: $imei" "error"
output_json "error" "Invalid IMEI format. It should be exactly 15 digits."
fi
if ! validate_bands "$lte_bands"; then
log_message "Invalid LTE bands format: $lte_bands" "error"
output_json "error" "Invalid LTE bands format. Use comma-separated numbers (e.g., 1,3,7)"
fi
if ! validate_bands "$sa_nr5g_bands"; then
log_message "Invalid SA NR5G bands format: $sa_nr5g_bands" "error"
output_json "error" "Invalid SA NR5G bands format. Use comma-separated numbers (e.g., 41,78)"
fi
if ! validate_bands "$nsa_nr5g_bands"; then
log_message "Invalid NSA NR5G bands format: $nsa_nr5g_bands" "error"
output_json "error" "Invalid NSA NR5G bands format. Use comma-separated numbers (e.g., 1,79)"
fi
if ! validate_network_type "$network_type"; then
log_message "Invalid network type: $network_type" "error"
output_json "error" "Invalid network type. Use 'LTE', 'NR5G', or 'LTE:NR5G'"
fi
if ! validate_pdp_type "$pdp_type"; then
log_message "Invalid PDP type: $pdp_type" "error"
output_json "error" "Invalid PDP type. Use 'IP', 'IPV6', or 'IPV4V6'"
fi
if ! validate_ttl "$ttl"; then
log_message "Invalid TTL value: $ttl" "error"
output_json "error" "Invalid TTL value. It should be a number between 0 and 255."
fi
# Check for duplicates
check_duplicate_profile "$name" "$iccid"
dup_status=$?
if [ $dup_status -eq 1 ]; then
log_message "Duplicate profile name: $name" "error"
output_json "error" "A profile with this name already exists"
elif [ $dup_status -eq 2 ]; then
log_message "Duplicate ICCID: $iccid" "error"
output_json "error" "A profile with this ICCID already exists"
fi
# Create the profile
if create_profile "$name" "$iccid" "$imei" "$apn" "$pdp_type" "$lte_bands" "$sa_nr5g_bands" "$nsa_nr5g_bands" "$network_type" "$ttl"; then
# Trigger immediate profile application
touch "/tmp/quecprofiles_check"
chmod 644 "/tmp/quecprofiles_check"
log_message "Triggered immediate profile check after creation" "info"
# Create profile data JSON for return - WITHOUT outer curly braces
profile_data="\"name\":\"$name\",\"iccid\":\"$iccid\",\"imei\":\"$imei\",\"apn\":\"$apn\",\"pdp_type\":\"$pdp_type\",\"lte_bands\":\"$lte_bands\",\"sa_nr5g_bands\":\"$sa_nr5g_bands\",\"nsa_nr5g_bands\":\"$nsa_nr5g_bands\",\"network_type\":\"$network_type\",\"ttl\":\"$ttl\""
# Wrap the data field in curly braces inside output_json
output_json "success" "Profile created successfully" "{$profile_data}"
else
output_json "error" "Failed to create profile. Please check system logs."
fi

View File

@@ -0,0 +1,138 @@
#!/bin/sh
# Location: /www/cgi-bin/quecmanager/profiles/quec_profile_delete.sh
# Set content type to JSON
echo -n ""
echo "Content-type: application/json"
echo ""
# Function to log messages
log_message() {
local level="${2:-info}"
logger -t quecprofiles -p "daemon.$level" "delete: $1"
}
# Function to output JSON response
output_json() {
local status="$1"
local message="$2"
local data="${3:-{}}"
printf '{"status":"%s","message":"%s","data":%s}\n' "$status" "$message" "$data"
exit 0
}
# Function to sanitize input
sanitize() {
echo "$1" | tr -d '\r\n' | sed 's/[^a-zA-Z0-9,.:_-]//g'
}
# Function to find profile by ICCID
find_profile_by_iccid() {
local iccid="$1"
# Get all profile indices
local profile_indices=$(uci show quecprofiles | grep -o '@profile\[[0-9]\+\]' | sort -u)
for profile_index in $profile_indices; do
local current_iccid=$(uci -q get quecprofiles.$profile_index.iccid)
if [ "$current_iccid" = "$iccid" ]; then
echo "$profile_index"
return 0
fi
done
return 1
}
# Function to delete a profile
delete_profile() {
local profile_index="$1"
local profile_name=$(uci -q get quecprofiles.$profile_index.name)
# Delete the profile from UCI config
uci -q batch <<EOF
delete quecprofiles.$profile_index
commit quecprofiles
EOF
# Check if the operation was successful
if [ $? -eq 0 ]; then
log_message "Successfully deleted profile '$profile_name'" "info"
return 0
else
log_message "Failed to delete profile '$profile_name'" "error"
return 1
fi
}
# Output debug info
log_message "Received delete profile request" "debug"
# Ensure UCI config exists
if [ ! -f /etc/config/quecprofiles ]; then
log_message "quecprofiles config does not exist" "error"
output_json "error" "Configuration file not found"
fi
# Get ICCID from request
iccid=""
if [ "$REQUEST_METHOD" = "POST" ]; then
# Get content length
CONTENT_LENGTH=$(echo "$CONTENT_LENGTH" | tr -cd '0-9')
if [ -n "$CONTENT_LENGTH" ]; then
# Read POST data
POST_DATA=$(dd bs=1 count=$CONTENT_LENGTH 2>/dev/null)
# Debug log
log_message "Received POST data: $POST_DATA" "debug"
# Parse JSON with jsonfilter if available
if command -v jsonfilter >/dev/null 2>&1; then
iccid=$(echo "$POST_DATA" | jsonfilter -e '@.iccid' 2>/dev/null)
else
# If jsonfilter is not available, try basic parsing
iccid=$(echo "$POST_DATA" | grep -o '"iccid":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
fi
else
log_message "No content length specified" "error"
output_json "error" "No data received"
fi
elif [ -n "$QUERY_STRING" ]; then
# URL parameters for GET or DELETE requests
iccid=$(echo "$QUERY_STRING" | grep -o 'iccid=[^&]*' | cut -d'=' -f2)
# URL decode value
iccid=$(echo "$iccid" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
log_message "Using URL parameter: iccid=$iccid" "debug"
fi
# Sanitize input
iccid=$(sanitize "${iccid:-}")
# Validate ICCID
if [ -z "$iccid" ]; then
log_message "ICCID is missing" "error"
output_json "error" "ICCID is required to identify the profile"
fi
# Find profile to delete
profile_index=$(find_profile_by_iccid "$iccid")
if [ $? -ne 0 ]; then
log_message "Profile with ICCID $iccid not found" "error"
output_json "error" "Profile not found"
fi
# Get profile info for response
profile_name=$(uci -q get quecprofiles.$profile_index.name)
# Delete the profile
if delete_profile "$profile_index"; then
log_message "Profile deleted successfully: $profile_name" "info"
output_json "success" "Profile deleted successfully" "{\"iccid\":\"$iccid\",\"name\":\"$profile_name\"}"
else
log_message "Failed to delete profile: $profile_name" "error"
output_json "error" "Failed to delete profile. Please check system logs."
fi

View File

@@ -0,0 +1,392 @@
#!/bin/sh
# Location: /www/cgi-bin/quecmanager/profiles/quec_profile_edit.sh
# Set content type to JSON
echo -n ""
echo "Content-type: application/json"
echo ""
# Configuration
CHECK_TRIGGER="/tmp/quecprofiles_check"
APPLIED_FLAG="/tmp/quecprofiles_applied"
# Function to log messages
log_message() {
local level="${2:-info}"
logger -t quecprofiles -p "daemon.$level" "edit: $1"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] edit: $1" >>/tmp/quec_profile_edit.log
}
# Function to output JSON response
output_json() {
local status="$1"
local message="$2"
local data="${3:-{}}"
# Debug log to file only
echo "Generating JSON response: status=$status, message=$message" >>/tmp/quec_profile_debug.log
echo "Data payload: $data" >>/tmp/quec_profile_debug.log
# Use printf for consistent output without newlines or extra characters
printf '{"status":"%s","message":"%s","data":%s}' "$status" "$message" "$data"
# Add debug marker at end of JSON
echo "" >>/tmp/quec_profile_debug.log
echo "JSON response generated at $(date)" >>/tmp/quec_profile_debug.log
exit 0
}
# Function to sanitize input
sanitize() {
echo "$1" | tr -d '\r\n' | sed 's/[^a-zA-Z0-9,.:_-]//g'
}
# Function to validate ICCID (simple check)
validate_iccid() {
local iccid="$1"
if [ -z "$iccid" ] || [ ${#iccid} -lt 10 ] || [ ${#iccid} -gt 20 ]; then
return 1
fi
# Check that it's only digits
if ! echo "$iccid" | grep -q '^[0-9]\+$'; then
return 1
fi
return 0
}
# Function to validate IMEI (simple check)
validate_imei() {
local imei="$1"
if [ -z "$imei" ]; then
return 0 # IMEI is optional
fi
if [ ${#imei} -ne 15 ] || ! echo "$imei" | grep -q '^[0-9]\+$'; then
return 1
fi
return 0
}
# Function to validate band list
validate_bands() {
local bands="$1"
if [ -z "$bands" ]; then
return 0 # Empty is valid
fi
# Check format (comma-separated numbers)
if ! echo "$bands" | grep -q '^[0-9]\+\(,[0-9]\+\)*$'; then
return 1
fi
return 0
}
# Function to validate network type
validate_network_type() {
local net_type="$1"
case "$net_type" in
"LTE" | "NR5G" | "LTE:NR5G")
return 0
;;
*)
return 1
;;
esac
}
# Function to validate PDP type
validate_pdp_type() {
local pdp_type="$1"
case "$pdp_type" in
"IP" | "IPV6" | "IPV4V6")
return 0
;;
*)
return 1
;;
esac
}
validate_ttl() {
local ttl="$1"
if [ -z "$ttl" ]; then
return 0 # Empty is valid (will be treated as 0/disabled)
fi
# Check that TTL is a number between 0 and 255
if ! echo "$ttl" | grep -q '^[0-9]\+$' || [ "$ttl" -gt 255 ]; then
return 1
fi
return 0
}
# Function to check if a profile with given ICCID exists
find_profile_by_iccid() {
local iccid="$1"
# Get all profile indices
local profile_indices=$(uci show quecprofiles | grep -o '@profile\[[0-9]\+\]' | sort -u)
for profile_index in $profile_indices; do
local current_iccid=$(uci -q get quecprofiles.$profile_index.iccid)
if [ "$current_iccid" = "$iccid" ]; then
echo "$profile_index"
return 0
fi
done
return 1
}
# Function to check for duplicate name (excluding current profile)
check_duplicate_name() {
local name="$1"
local current_iccid="$2"
local profile_indices=$(uci show quecprofiles | grep -o '@profile\[[0-9]\+\]' | sort -u)
for profile_index in $profile_indices; do
local iccid=$(uci -q get quecprofiles.$profile_index.iccid)
local profile_name=$(uci -q get quecprofiles.$profile_index.name)
# Skip the current profile we're editing
if [ "$iccid" = "$current_iccid" ]; then
continue
fi
if [ "$profile_name" = "$name" ]; then
return 0 # Found duplicate
fi
done
return 1 # No duplicate
}
# Function to update an existing profile
update_profile() {
local profile_index="$1"
local name="$2"
local imei="$3"
local apn="$4"
local pdp_type="$5"
local lte_bands="$6"
local sa_nr5g_bands="$7"
local nsa_nr5g_bands="$8"
local network_type="$9"
local ttl="${10}"
# Update the profile in UCI config
uci -q batch <<EOF
set quecprofiles.$profile_index.name='$name'
set quecprofiles.$profile_index.imei='$imei'
set quecprofiles.$profile_index.apn='$apn'
set quecprofiles.$profile_index.pdp_type='$pdp_type'
set quecprofiles.$profile_index.lte_bands='$lte_bands'
set quecprofiles.$profile_index.sa_nr5g_bands='$sa_nr5g_bands'
set quecprofiles.$profile_index.nsa_nr5g_bands='$nsa_nr5g_bands'
set quecprofiles.$profile_index.network_type='$network_type'
set quecprofiles.$profile_index.ttl='$ttl'
commit quecprofiles
EOF
# Check if the operation was successful
if [ $? -eq 0 ]; then
log_message "Successfully updated profile '$name'" "info"
# Remove the applied flag file to force reapplication on next check
rm -f "$APPLIED_FLAG"
# Touch the check trigger file to force daemon to check ASAP
touch "$CHECK_TRIGGER"
log_message "Triggered profile check for updated profile '$name'" "info"
return 0
else
log_message "Failed to update profile '$name'" "error"
return 1
fi
}
# Output debug info
log_message "Received edit profile request" "debug"
# Ensure UCI config exists
if [ ! -f /etc/config/quecprofiles ]; then
log_message "quecprofiles config does not exist" "error"
output_json "error" "Configuration file not found"
fi
# Get POST data
if [ "$REQUEST_METHOD" = "POST" ]; then
# Get content length
CONTENT_LENGTH=$(echo "$CONTENT_LENGTH" | tr -cd '0-9')
if [ -n "$CONTENT_LENGTH" ]; then
# Read POST data
POST_DATA=$(dd bs=1 count=$CONTENT_LENGTH 2>/dev/null)
# Debug log
log_message "Received POST data: $POST_DATA" "debug"
# Parse JSON with jsonfilter if available
if command -v jsonfilter >/dev/null 2>&1; then
iccid=$(echo "$POST_DATA" | jsonfilter -e '@.iccid' 2>/dev/null)
name=$(echo "$POST_DATA" | jsonfilter -e '@.name' 2>/dev/null)
imei=$(echo "$POST_DATA" | jsonfilter -e '@.imei' 2>/dev/null)
apn=$(echo "$POST_DATA" | jsonfilter -e '@.apn' 2>/dev/null)
pdp_type=$(echo "$POST_DATA" | jsonfilter -e '@.pdp_type' 2>/dev/null)
lte_bands=$(echo "$POST_DATA" | jsonfilter -e '@.lte_bands' 2>/dev/null)
sa_nr5g_bands=$(echo "$POST_DATA" | jsonfilter -e '@.sa_nr5g_bands' 2>/dev/null)
nsa_nr5g_bands=$(echo "$POST_DATA" | jsonfilter -e '@.nsa_nr5g_bands' 2>/dev/null)
network_type=$(echo "$POST_DATA" | jsonfilter -e '@.network_type' 2>/dev/null)
ttl=$(echo "$POST_DATA" | jsonfilter -e '@.ttl' 2>/dev/null)
log_message "Parsed JSON data for profile: $name" "debug"
else
# If jsonfilter is not available, try basic parsing
# This is less reliable but might work for simple cases
iccid=$(echo "$POST_DATA" | grep -o '"iccid":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
name=$(echo "$POST_DATA" | grep -o '"name":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
imei=$(echo "$POST_DATA" | grep -o '"imei":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
apn=$(echo "$POST_DATA" | grep -o '"apn":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
pdp_type=$(echo "$POST_DATA" | grep -o '"pdp_type":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
lte_bands=$(echo "$POST_DATA" | grep -o '"lte_bands":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
sa_nr5g_bands=$(echo "$POST_DATA" | grep -o '"sa_nr5g_bands":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
nsa_nr5g_bands=$(echo "$POST_DATA" | grep -o '"nsa_nr5g_bands":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
network_type=$(echo "$POST_DATA" | grep -o '"network_type":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
ttl=$(echo "$POST_DATA" | grep -o '"ttl":"[^"]*"' | head -1 | cut -d':' -f2 | tr -d '"')
log_message "Basic parsing for profile: $name" "warn"
fi
else
log_message "No content length specified" "error"
output_json "error" "No data received"
fi
else
# URL parameters for GET requests (less secure, but supported for testing)
iccid=$(echo "$QUERY_STRING" | grep -o 'iccid=[^&]*' | cut -d'=' -f2)
name=$(echo "$QUERY_STRING" | grep -o 'name=[^&]*' | cut -d'=' -f2)
imei=$(echo "$QUERY_STRING" | grep -o 'imei=[^&]*' | cut -d'=' -f2)
apn=$(echo "$QUERY_STRING" | grep -o 'apn=[^&]*' | cut -d'=' -f2)
pdp_type=$(echo "$QUERY_STRING" | grep -o 'pdp_type=[^&]*' | cut -d'=' -f2)
lte_bands=$(echo "$QUERY_STRING" | grep -o 'lte_bands=[^&]*' | cut -d'=' -f2)
sa_nr5g_bands=$(echo "$QUERY_STRING" | grep -o 'sa_nr5g_bands=[^&]*' | cut -d'=' -f2)
nsa_nr5g_bands=$(echo "$QUERY_STRING" | grep -o 'nsa_nr5g_bands=[^&]*' | cut -d'=' -f2)
network_type=$(echo "$QUERY_STRING" | grep -o 'network_type=[^&]*' | cut -d'=' -f2)
ttl=$(echo "$QUERY_STRING" | grep -o 'ttl=[^&]*' | cut -d'=' -f2)
# URL decode values
iccid=$(echo "$iccid" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
name=$(echo "$name" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
imei=$(echo "$imei" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
apn=$(echo "$apn" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
pdp_type=$(echo "$pdp_type" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
lte_bands=$(echo "$lte_bands" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
sa_nr5g_bands=$(echo "$sa_nr5g_bands" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
nsa_nr5g_bands=$(echo "$nsa_nr5g_bands" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
network_type=$(echo "$network_type" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
ttl=$(echo "$ttl" | sed 's/+/ /g;s/%\(..\)/\\x\1/g;' | xargs -0 printf "%b")
log_message "Using URL parameters" "warn"
fi
# Sanitize inputs
iccid=$(sanitize "${iccid:-}")
name=$(sanitize "${name:-}")
imei=$(sanitize "${imei:-}")
apn=$(sanitize "${apn:-}")
pdp_type=$(sanitize "${pdp_type:-IP}")
lte_bands=$(sanitize "${lte_bands:-}")
sa_nr5g_bands=$(sanitize "${sa_nr5g_bands:-}")
nsa_nr5g_bands=$(sanitize "${nsa_nr5g_bands:-}")
network_type=$(sanitize "${network_type:-LTE}")
ttl=$(sanitize "${ttl:-0}") # Default to 0 (disabled)
# Output debug info
log_message "Editing profile: $name, ICCID: $iccid, IMEI: $imei, APN: $apn" "debug"
# Validate required inputs
if [ -z "$iccid" ]; then
log_message "ICCID is missing" "error"
output_json "error" "ICCID is required to identify the profile"
fi
if [ -z "$name" ]; then
log_message "Profile name is missing" "error"
output_json "error" "Profile name is required"
fi
if [ -z "$apn" ]; then
log_message "APN is missing" "error"
output_json "error" "APN is required"
fi
# Validate input formats
if ! validate_iccid "$iccid"; then
log_message "Invalid ICCID format: $iccid" "error"
output_json "error" "Invalid ICCID format. It should be 10-20 digits."
fi
if ! validate_imei "$imei"; then
log_message "Invalid IMEI format: $imei" "error"
output_json "error" "Invalid IMEI format. It should be exactly 15 digits."
fi
if ! validate_bands "$lte_bands"; then
log_message "Invalid LTE bands format: $lte_bands" "error"
output_json "error" "Invalid LTE bands format. Use comma-separated numbers (e.g., 1,3,7)"
fi
if ! validate_bands "$sa_nr5g_bands"; then
log_message "Invalid SA NR5G bands format: $sa_nr5g_bands" "error"
output_json "error" "Invalid SA NR5G bands format. Use comma-separated numbers (e.g., 41,78)"
fi
if ! validate_bands "$nsa_nr5g_bands"; then
log_message "Invalid NSA NR5G bands format: $nsa_nr5g_bands" "error"
output_json "error" "Invalid NSA NR5G bands format. Use comma-separated numbers (e.g., 1,79)"
fi
if ! validate_network_type "$network_type"; then
log_message "Invalid network type: $network_type" "error"
output_json "error" "Invalid network type. Use 'LTE', 'NR5G', or 'LTE:NR5G'"
fi
if ! validate_pdp_type "$pdp_type"; then
log_message "Invalid PDP type: $pdp_type" "error"
output_json "error" "Invalid PDP type. Use 'IP', 'IPV6', or 'IPV4V6'"
fi
if ! validate_ttl "$ttl"; then
log_message "Invalid TTL value: $ttl" "error"
output_json "error" "Invalid TTL value. It should be a number between 0 and 255."
fi
# Find profile to edit
profile_index=$(find_profile_by_iccid "$iccid")
if [ $? -ne 0 ]; then
log_message "Profile with ICCID $iccid not found" "error"
output_json "error" "Profile not found"
fi
# Check for duplicate name
if check_duplicate_name "$name" "$iccid"; then
log_message "Duplicate profile name: $name" "error"
output_json "error" "A profile with this name already exists"
fi
# Update profile
if update_profile "$profile_index" "$name" "$imei" "$apn" "$pdp_type" "$lte_bands" "$nr5g_bands" "$network_type"; then
# Trigger immediate profile application
touch "/tmp/quecprofiles_check"
chmod 644 "/tmp/quecprofiles_check"
log_message "Triggered immediate profile check after update" "info"
# Create a clean JSON response with properly escaped quotes
printf '{"status":"success","message":"Profile updated successfully","data":{"name":"%s","iccid":"%s","imei":"%s","apn":"%s","pdp_type":"%s","lte_bands":"%s","nr5g_bands":"%s","network_type":"%s"}}' \
"$name" "$iccid" "$imei" "$apn" "$pdp_type" "$lte_bands" "$nr5g_bands" "$network_type"
log_message "Profile updated successfully: $name" "info"
# Note: The conditional trigger is replaced with the direct trigger above
else
printf '{"status":"error","message":"Failed to update profile. Please check system logs."}'
log_message "Failed to update profile: $name" "error"
fi

View File

@@ -0,0 +1,38 @@
#!/bin/sh
# Set content type for JSON response
echo "Content-type: application/json"
echo ""
# Get system uptime in seconds from /proc/uptime
read uptime idle < /proc/uptime
uptime=${uptime%.*} # Remove decimal part
# Calculate days, hours, minutes, seconds
days=$((uptime/86400))
hours=$(((uptime%86400)/3600))
minutes=$(((uptime%3600)/60))
seconds=$((uptime%60))
# Format uptime string
uptime_str=""
[ $days -gt 0 ] && uptime_str="${days}d "
[ $hours -gt 0 ] && uptime_str="${uptime_str}${hours}h "
[ $minutes -gt 0 ] && uptime_str="${uptime_str}${minutes}m "
uptime_str="${uptime_str}${seconds}s"
# Create and output JSON response
cat << EOF
{
"status": "success",
"timestamp": "$(date -Iseconds)",
"uptime": {
"total_seconds": $uptime,
"days": $days,
"hours": $hours,
"minutes": $minutes,
"seconds": $seconds,
"formatted": "${uptime_str}"
}
}
EOF

View File

@@ -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

View File

@@ -0,0 +1,672 @@
#!/bin/sh
# AT Queue Manager for OpenWRT with Preemption Support and Token System
# Located in /www/cgi-bin/services/at_queue_manager
# Constants
QUEUE_DIR="/tmp/at_queue"
QUEUE_FILE="$QUEUE_DIR/queue"
ACTIVE_FILE="$QUEUE_DIR/active"
RESULTS_DIR="$QUEUE_DIR/results"
LOCK_DIR="$QUEUE_DIR/lock"
TOKEN_FILE="$QUEUE_DIR/token"
MAX_TIMEOUT=240
CLEANUP_INTERVAL=300 # 5 minutes in seconds
RESULTS_MAX_AGE=3600 # 1 hour in seconds
POLL_INTERVAL=0.01
PREEMPTION_THRESHOLD=2 # 3 seconds threshold for preemption
TOKEN_TIMEOUT=30 # seconds before token expires
# Utility function for JSON escaping
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$//'
}
# Exclusive lock functions
acquire_lock() {
local timeout=10
local attempt=0
while [ $attempt -lt $timeout ]; do
if mkdir "$LOCK_DIR" 2>/dev/null; then
logger -t at_queue -p daemon.debug "Lock acquired"
return 0
fi
sleep 0.1
attempt=$((attempt + 1))
done
logger -t at_queue -p daemon.error "Failed to acquire lock after $timeout attempts"
return 1
}
release_lock() {
if [ -d "$LOCK_DIR" ]; then
rmdir "$LOCK_DIR" 2>/dev/null
logger -t at_queue -p daemon.debug "Lock released"
return 0
fi
logger -t at_queue -p daemon.error "Lock directory doesn't exist"
return 1
}
# Ensure required directories exist
init_queue_system() {
mkdir -p "$QUEUE_DIR" "$RESULTS_DIR"
touch "$QUEUE_FILE"
chmod 755 "$QUEUE_DIR"
chmod 644 "$QUEUE_FILE"
chmod 755 "$RESULTS_DIR"
logger -t at_queue -p daemon.info "Queue system initialized"
}
# Cleanup old results and tracking files
cleanup_old_results() {
local current_time=$(date +%s)
# Clean up old execution tracking files
find "$QUEUE_DIR" -name "pid.*" -type f -mmin +60 -delete 2>/dev/null
find "$QUEUE_DIR" -name "*.exit" -type f -mmin +60 -delete 2>/dev/null
find "$QUEUE_DIR" -name "start_time.*" -type f -mmin +60 -delete 2>/dev/null
logger -t at_queue -p daemon.debug "Cleaned up old tracking files"
# Use find with -delete and basic timestamp check for OpenWRT
find "$RESULTS_DIR" -name "*.json" -type f -mmin +60 -delete 2>/dev/null || {
# Fallback method if find fails
for file in "$RESULTS_DIR"/*.json; do
[ -f "$file" ] || continue
local file_time=$(stat -c %Y "$file")
if [ $((current_time - file_time)) -gt $RESULTS_MAX_AGE ]; then
rm -f "$file"
fi
done
}
# Check for expired token
if [ -f "$TOKEN_FILE" ]; then
local token_time=$(cat "$TOKEN_FILE" | jsonfilter -e '@.timestamp')
if [ $((current_time - token_time)) -gt $TOKEN_TIMEOUT ]; then
local token_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id')
logger -t at_queue -p daemon.warn "Removing expired token from $token_holder"
rm -f "$TOKEN_FILE"
fi
fi
logger -t at_queue -p daemon.info "Cleanup: Removed files older than 1 hour"
}
# Generate unique command ID
generate_command_id() {
echo "$(date +%s)_$(head -c 8 /dev/urandom | hexdump -v -e '1/1 "%02x"')"
}
# Start tracking command execution time
start_execution_tracking() {
local cmd_id="$1"
local pid="$2"
local start_time=$(date +%s)
echo "$start_time" > "$QUEUE_DIR/start_time.$cmd_id"
echo "$pid" > "$QUEUE_DIR/pid.$cmd_id"
chmod 644 "$QUEUE_DIR/start_time.$cmd_id"
chmod 644 "$QUEUE_DIR/pid.$cmd_id"
logger -t at_queue -p daemon.debug "Started tracking command $cmd_id (PID: $pid)"
}
# Check if running command should be preempted
should_preempt() {
local current_cmd_id="$1"
local new_priority="$2"
if [ ! -f "$QUEUE_DIR/start_time.$current_cmd_id" ]; then
logger -t at_queue -p daemon.debug "No start time found for $current_cmd_id"
return 1
fi
local start_time=$(cat "$QUEUE_DIR/start_time.$current_cmd_id")
local current_time=$(date +%s)
local execution_time=$((current_time - start_time))
# Get current command's priority
local current_priority
if [ -f "$ACTIVE_FILE" ]; then
current_priority=$(cat "$ACTIVE_FILE" | jsonfilter -e '@.priority')
else
logger -t at_queue -p daemon.debug "No active command found"
return 1
fi
if [ $execution_time -gt $PREEMPTION_THRESHOLD ] && [ $new_priority -lt $current_priority ]; then
logger -t at_queue -p daemon.info "Command $current_cmd_id (priority $current_priority) running for ${execution_time}s is eligible for preemption by priority $new_priority"
return 0
fi
logger -t at_queue -p daemon.debug "Command $current_cmd_id not eligible for preemption (time: ${execution_time}s, current priority: $current_priority, new priority: $new_priority)"
return 1
}
# Handle command preemption
preempt_command() {
local cmd_id="$1"
local pid_file="$QUEUE_DIR/pid.$cmd_id"
if [ -f "$pid_file" ]; then
local pid=$(cat "$pid_file")
logger -t at_queue -p daemon.info "Preempting command $cmd_id (PID: $pid)"
# Send SIGTERM first
kill -TERM $pid 2>/dev/null
# Brief wait for graceful termination
sleep 0.1
# Force kill if still running
if kill -0 $pid 2>/dev/null; then
kill -KILL $pid 2>/dev/null
logger -t at_queue -p daemon.warn "Forced termination of command $cmd_id"
fi
# Record preemption result
write_preemption_result "$cmd_id"
# Cleanup command files
rm -f "$pid_file" "$QUEUE_DIR/start_time.$cmd_id" "$QUEUE_DIR/$cmd_id.exit"
[ -f "$ACTIVE_FILE" ] && rm -f "$ACTIVE_FILE"
logger -t at_queue -p daemon.info "Command $cmd_id preemption complete"
return 0
fi
logger -t at_queue -p daemon.warn "No PID file found for command $cmd_id"
return 1
}
# Record result for preempted command
write_preemption_result() {
local cmd_id="$1"
local end_time=$(date +%s%3N)
local start_time
if [ -f "$QUEUE_DIR/start_time.$cmd_id" ]; then
start_time=$(cat "$QUEUE_DIR/start_time.$cmd_id")000
else
start_time=$end_time
fi
local duration=$((end_time - start_time))
local command_text=$(cat "$ACTIVE_FILE" | jsonfilter -e '@.command')
local response=$(cat << EOF
{
"command": {
"id": "$cmd_id",
"text": "$(escape_json "$command_text")",
"timestamp": "$(date -Iseconds)"
},
"response": {
"status": "preempted",
"raw_output": "Command preempted by higher priority task",
"completion_time": "$end_time",
"duration_ms": $duration
}
}
EOF
)
printf "%s" "$response" > "$RESULTS_DIR/$cmd_id.json"
chmod 644 "$RESULTS_DIR/$cmd_id.json"
logger -t at_queue -p daemon.info "Recorded preemption result for command $cmd_id (duration: ${duration}ms)"
}
# Request a token for direct sms_tool execution
request_token() {
local requestor_id="$1"
local priority="${2:-10}"
local timeout="${3:-10}"
# Acquire lock first
if ! acquire_lock; then
logger -t at_queue -p daemon.error "Failed to acquire lock for token request"
echo "{\"error\":\"Could not acquire lock\",\"status\":\"denied\"}"
return 1
fi
# Check if token file exists (someone else has the token)
if [ -f "$TOKEN_FILE" ]; then
local current_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id')
local current_priority=$(cat "$TOKEN_FILE" | jsonfilter -e '@.priority')
local timestamp=$(cat "$TOKEN_FILE" | jsonfilter -e '@.timestamp')
local current_time=$(date +%s)
# Check for expired token (> TOKEN_TIMEOUT seconds old)
if [ $((current_time - timestamp)) -gt $TOKEN_TIMEOUT ]; then
logger -t at_queue -p daemon.warn "Found expired token from $current_holder, releasing"
rm -f "$TOKEN_FILE"
# Check for priority preemption
elif [ $priority -lt $current_priority ]; then
logger -t at_queue -p daemon.info "Preempting token from $current_holder (priority: $current_priority) for $requestor_id (priority: $priority)"
rm -f "$TOKEN_FILE"
else
# Token in use and cannot be preempted
release_lock
echo "{\"status\":\"denied\",\"holder\":\"$current_holder\",\"priority\":$current_priority}"
return 1
fi
fi
# Also check if there's an active command from the queue
if [ -f "$ACTIVE_FILE" ]; then
local active_id=$(cat "$ACTIVE_FILE" | jsonfilter -e '@.id')
local active_priority=$(cat "$ACTIVE_FILE" | jsonfilter -e '@.priority')
# Only preempt if priority is higher
if [ $priority -ge $active_priority ]; then
release_lock
echo "{\"status\":\"denied\",\"holder\":\"$active_id\",\"priority\":$active_priority}"
return 1
fi
logger -t at_queue -p daemon.info "Direct execution with higher priority than active queue command"
fi
# Grant token
local token_data="{\"id\":\"$requestor_id\",\"priority\":$priority,\"timestamp\":$(date +%s)}"
echo "$token_data" > "$TOKEN_FILE"
chmod 644 "$TOKEN_FILE"
release_lock
echo "{\"status\":\"granted\",\"id\":\"$requestor_id\",\"timeout\":$timeout}"
return 0
}
# Release a previously acquired token
release_token() {
local requestor_id="$1"
if ! acquire_lock; then
logger -t at_queue -p daemon.error "Failed to acquire lock for token release"
return 1
fi
if [ -f "$TOKEN_FILE" ]; then
local current_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id')
if [ "$current_holder" = "$requestor_id" ]; then
rm -f "$TOKEN_FILE"
logger -t at_queue -p daemon.debug "Token released by $requestor_id"
release_lock
echo "{\"status\":\"released\"}"
return 0
else
logger -t at_queue -p daemon.warn "Token release attempted by $requestor_id but held by $current_holder"
fi
else
logger -t at_queue -p daemon.warn "Token release attempted but no token exists"
fi
release_lock
echo "{\"status\":\"not_found\"}"
return 1
}
# Add command to queue with preemption support
enqueue_command() {
local cmd="$1"
local priority="${2:-10}"
local cmd_id=$(generate_command_id)
local timestamp=$(date -Iseconds)
# Ensure queue directory exists
[ ! -d "$QUEUE_DIR" ] && init_queue_system
logger -t at_queue -p daemon.info "Enqueuing command: $cmd (priority: $priority, id: $cmd_id)"
# Acquire lock for queue modification
if ! acquire_lock; then
logger -t at_queue -p daemon.error "Failed to acquire lock for enqueuing command"
echo "{\"error\":\"Queue lock acquisition failed\",\"command\":\"$cmd\"}"
return 1
fi
# Check for active command that can be preempted
if [ -f "$ACTIVE_FILE" ]; then
local active_cmd_id=$(cat "$ACTIVE_FILE" | jsonfilter -e '@.id')
if should_preempt "$active_cmd_id" "$priority"; then
preempt_command "$active_cmd_id"
fi
fi
# Create command entry
local entry="{\"id\":\"$cmd_id\",\"command\":\"$(escape_json "$cmd")\",\"priority\":$priority,\"timestamp\":\"$timestamp\"}"
if [ "$priority" = "1" ]; then
# High priority - prepend to queue
local temp_file=$(mktemp)
echo "$entry" > "$temp_file"
cat "$QUEUE_FILE" >> "$temp_file"
mv "$temp_file" "$QUEUE_FILE"
chmod 644 "$QUEUE_FILE"
logger -t at_queue -p daemon.info "Added high priority command to front of queue"
else
# Normal priority - append to queue
echo "$entry" >> "$QUEUE_FILE"
logger -t at_queue -p daemon.info "Added normal priority command to end of queue"
fi
# Release lock
release_lock
echo "{\"command_id\":\"$cmd_id\",\"status\":\"queued\"}"
}
# Get next command from queue
dequeue_command() {
if [ ! -s "$QUEUE_FILE" ]; then
return 1
fi
# Acquire lock
if ! acquire_lock; then
logger -t at_queue -p daemon.error "Failed to acquire lock for dequeuing command"
return 1
fi
local cmd_entry=$(head -n 1 "$QUEUE_FILE")
local temp_file=$(mktemp)
tail -n +2 "$QUEUE_FILE" > "$temp_file"
mv "$temp_file" "$QUEUE_FILE"
chmod 644 "$QUEUE_FILE"
echo "$cmd_entry" > "$ACTIVE_FILE"
chmod 644 "$ACTIVE_FILE"
# Release lock
release_lock
logger -t at_queue -p daemon.debug "Dequeued command: $(echo "$cmd_entry" | jsonfilter -e '@.command')"
echo "$cmd_entry"
}
# Clean and format AT command output
clean_output() {
local output="$1"
# First format AT command responses for readability
output=$(echo "$output" | sed -E '
# Add newline after AT commands
s/(AT\+[A-Z0-9]+[^ ]*) +/\1\n/g
# Add newline before +RESPONSE lines
s/ +(\+[A-Z0-9]+:)/\n\1/g
# Add newline before OK/ERROR
s/ +(OK|ERROR)$/\n\1/g
')
# Then escape the formatted output for JSON
output=$(escape_json "$output")
echo "$output"
}
# Execute AT command with optimized timeout handling
execute_with_timeout() {
local command="$1"
local timeout="$2"
local cmd_id="$3"
local output_file=$(mktemp)
# Start command in background with immediate output
(sms_tool -D at "$command" > "$output_file" 2>&1; echo $? > "$QUEUE_DIR/$cmd_id.exit") &
local pid=$!
# Start execution tracking
start_execution_tracking "$cmd_id" "$pid"
logger -t at_queue -p daemon.debug "Started command execution: $command (PID: $pid)"
# Wait for completion with shorter polling interval
local start_time=$(date +%s)
local elapsed=0
while [ $elapsed -lt "$timeout" ]; do
if [ -f "$QUEUE_DIR/$cmd_id.exit" ]; then
local exit_code=$(cat "$QUEUE_DIR/$cmd_id.exit")
local output=$(cat "$output_file")
# Cleanup
rm -f "$QUEUE_DIR/pid.$cmd_id" "$QUEUE_DIR/$cmd_id.exit" "$output_file" "$QUEUE_DIR/start_time.$cmd_id"
logger -t at_queue -p daemon.debug "Command completed with exit code $exit_code"
echo "$output"
return $exit_code
fi
elapsed=$(($(date +%s) - start_time))
sleep $POLL_INTERVAL
done
# Handle timeout
if [ -f "$QUEUE_DIR/pid.$cmd_id" ]; then
local pid=$(cat "$QUEUE_DIR/pid.$cmd_id")
kill $pid 2>/dev/null
sleep 0.1
# Force kill if still running
if kill -0 $pid 2>/dev/null; then
kill -KILL $pid 2>/dev/null
fi
local partial_output=$(cat "$output_file" 2>/dev/null || echo "")
# Cleanup
rm -f "$QUEUE_DIR/pid.$cmd_id" "$QUEUE_DIR/$cmd_id.exit" "$output_file" "$QUEUE_DIR/start_time.$cmd_id"
logger -t at_queue -p daemon.warn "Command timed out after $timeout seconds"
echo "${partial_output:-Command timed out after $timeout seconds}"
fi
return 124
}
# Execute AT command and handle response
execute_command() {
local cmd_entry="$1"
local cmd_id=$(echo "$cmd_entry" | jsonfilter -e '@.id')
local cmd_text=$(echo "$cmd_entry" | jsonfilter -e '@.command')
local priority=$(echo "$cmd_entry" | jsonfilter -e '@.priority')
local start_time=$(date +%s%3N)
logger -t at_queue -p daemon.info "Executing command $cmd_id: $cmd_text (priority: $priority)"
# Execute command with timeout
local result=$(execute_with_timeout "$cmd_text" $MAX_TIMEOUT "$cmd_id")
local exit_code=$?
local end_time=$(date +%s%3N)
local duration=$((end_time - start_time))
# Determine status and log level
local status="error"
local log_level="error"
if [ $exit_code -eq 124 ]; then
status="timeout"
logger -t at_queue -p daemon.error "Command $cmd_id timed out after ${duration}ms"
elif echo "$result" | grep -q "OK"; then
status="success"
log_level="info"
logger -t at_queue -p daemon.info "Command $cmd_id completed successfully in ${duration}ms"
elif echo "$result" | grep -q "CME ERROR"; then
status="cme_error"
logger -t at_queue -p daemon.error "Command $cmd_id failed with CME ERROR in ${duration}ms"
else
logger -t at_queue -p daemon.error "Command $cmd_id failed with general error in ${duration}ms"
fi
# Clean and escape the output
local clean_result=$(clean_output "$result")
# Create JSON response
local response=$(cat << EOF
{
"command": {
"id": "$cmd_id",
"text": "$(escape_json "$cmd_text")",
"timestamp": "$(date -Iseconds)"
},
"response": {
"status": "$status",
"raw_output": "$clean_result",
"completion_time": "$end_time",
"duration_ms": $duration
}
}
EOF
)
# Acquire lock for writing result
if ! acquire_lock; then
logger -t at_queue -p daemon.error "Failed to acquire lock for writing result"
else
# Save response
printf "%s" "$response" > "$RESULTS_DIR/$cmd_id.json"
chmod 644 "$RESULTS_DIR/$cmd_id.json"
# Clean up active file
rm -f "$ACTIVE_FILE"
# Release lock
release_lock
fi
echo "$response"
}
# Main queue processing function
process_queue() {
init_queue_system
local last_cleanup=$(date +%s)
local last_log=$(date +%s) # Add a timestamp for less frequent logging
# Make sure the lock directory doesn't exist at startup
[ -d "$LOCK_DIR" ] && rmdir "$LOCK_DIR" 2>/dev/null
logger -t at_queue -p daemon.info "Started queue processing daemon"
while true; do
# Quick cleanup check
local current_time=$(date +%s)
if [ $((current_time - last_cleanup)) -ge $CLEANUP_INTERVAL ]; then
cleanup_old_results
last_cleanup=$current_time
fi
# Skip processing if token is granted to someone
if [ -f "$TOKEN_FILE" ]; then
local token_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id')
local token_time=$(cat "$TOKEN_FILE" | jsonfilter -e '@.timestamp')
local current_time=$(date +%s)
# Check for expired token
if [ $((current_time - token_time)) -gt $TOKEN_TIMEOUT ]; then
logger -t at_queue -p daemon.warn "Removing expired token from $token_holder"
rm -f "$TOKEN_FILE"
else
# Log pause status only every 5 seconds to reduce log spam
if [ $((current_time - last_log)) -ge 5 ]; then
logger -t at_queue -p daemon.debug "Queue processing paused, token held by $token_holder"
last_log=$current_time
fi
sleep $POLL_INTERVAL
continue
fi
fi
# Process queue if not empty and no active command
if [ -s "$QUEUE_FILE" ] && [ ! -f "$ACTIVE_FILE" ]; then
local cmd_entry=$(dequeue_command)
if [ -n "$cmd_entry" ]; then
execute_command "$cmd_entry"
fi
fi
sleep $POLL_INTERVAL
done
}
# CGI command handling
if [ "${SCRIPT_NAME}" != "" ]; then
# Output headers
if [ "$HTTP_HEADERS" != "0" ]; then
echo "Content-Type: application/json"
echo ""
fi
# Parse query string for CGI mode
eval $(echo "$QUERY_STRING" | sed 's/&/;/g')
case "$action" in
"enqueue")
if [ -n "$command" ]; then
logger -t at_queue -p daemon.info "CGI: Received enqueue request for command: $command"
enqueue_command "$command" "$priority"
else
logger -t at_queue -p daemon.error "CGI: Empty command received"
echo "{\"error\":\"No command specified\"}"
fi
;;
"status")
if [ -f "$ACTIVE_FILE" ]; then
logger -t at_queue -p daemon.debug "CGI: Status request - queue active"
cat "$ACTIVE_FILE"
else
logger -t at_queue -p daemon.debug "CGI: Status request - queue idle"
echo "{\"status\":\"idle\"}"
fi
;;
"request_token")
if [ -n "$id" ]; then
logger -t at_queue -p daemon.info "Token request from $id (priority: ${priority:-10})"
request_token "$id" "${priority:-10}" "${timeout:-10}"
else
logger -t at_queue -p daemon.error "Token request missing ID"
echo "{\"error\":\"No requestor ID specified\",\"status\":\"denied\"}"
fi
;;
"release_token")
if [ -n "$id" ]; then
logger -t at_queue -p daemon.info "Token release from $id"
release_token "$id"
else
logger -t at_queue -p daemon.error "Token release missing ID"
echo "{\"error\":\"No requestor ID specified\",\"status\":\"denied\"}"
fi
;;
*)
logger -t at_queue -p daemon.error "CGI: Invalid action received: $action"
echo "{\"error\":\"Invalid action\"}"
;;
esac
exit 0
fi
# CLI command handling
if [ "$1" = "enqueue" ] && [ -n "$2" ]; then
enqueue_command "$2" "${3:-10}"
exit $?
fi
# If not run as CGI, start queue processing
if [ "${SCRIPT_NAME}" = "" ] && [ -z "$1" ]; then
process_queue
fi

View File

@@ -0,0 +1,198 @@
#!/bin/sh
# Configuration
LOGDIR="/www/signal_graphs"
MAX_ENTRIES=10
INTERVAL=60
QUEUE_DIR="/tmp/at_queue"
TOKEN_FILE="$QUEUE_DIR/token"
LOCK_FILE="/tmp/signal_metrics.lock"
METRICS_PID_FILE="/tmp/signal_metrics.pid"
MAX_TOKEN_WAIT=5 # seconds to wait for token acquisition
# Ensure required directories exist
mkdir -p "$LOGDIR" "$QUEUE_DIR"
# Check if another instance is running
check_running() {
if [ -f "$METRICS_PID_FILE" ]; then
pid=$(cat "$METRICS_PID_FILE")
if kill -0 "$pid" 2>/dev/null; then
return 0
fi
rm -f "$METRICS_PID_FILE" 2>/dev/null
fi
return 1
}
# Acquire token directly (minimized version)
acquire_token() {
local metrics_id="METRICS_$(date +%s)_$$"
local priority=20 # Lowest priority for metrics
local max_attempts=20
local attempt=0
while [ $attempt -lt $max_attempts ]; do
# Check if token exists
if [ -f "$TOKEN_FILE" ]; then
# Check current token
local current_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id' 2>/dev/null)
local current_priority=$(cat "$TOKEN_FILE" | jsonfilter -e '@.priority' 2>/dev/null)
local timestamp=$(cat "$TOKEN_FILE" | jsonfilter -e '@.timestamp' 2>/dev/null)
local current_time=$(date +%s)
# Check for expired token
if [ $((current_time - timestamp)) -gt 30 ] || [ -z "$current_holder" ]; then
rm -f "$TOKEN_FILE" 2>/dev/null
elif [ $priority -lt $current_priority ]; then
rm -f "$TOKEN_FILE" 2>/dev/null
else
# Wait and try again
sleep 0.5
attempt=$((attempt + 1))
continue
fi
fi
# Try to create token
echo "{\"id\":\"$metrics_id\",\"priority\":$priority,\"timestamp\":$(date +%s)}" > "$TOKEN_FILE" 2>/dev/null
chmod 644 "$TOKEN_FILE" 2>/dev/null
# Verify we got it
local holder=$(cat "$TOKEN_FILE" 2>/dev/null | jsonfilter -e '@.id' 2>/dev/null)
if [ "$holder" = "$metrics_id" ]; then
echo "$metrics_id"
return 0
fi
sleep 0.5
attempt=$((attempt + 1))
done
return 1
}
# Release token directly
release_token() {
local metrics_id="$1"
if [ -f "$TOKEN_FILE" ]; then
local current_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id' 2>/dev/null)
if [ "$current_holder" = "$metrics_id" ]; then
rm -f "$TOKEN_FILE" 2>/dev/null
fi
fi
}
# Execute AT command directly
execute_at_command() {
local CMD="$1"
sms_tool at "$CMD" -t 3 2>/dev/null
}
# Process all metrics commands with a single token
process_all_metrics() {
# Try to get token
local metrics_id=$(acquire_token)
if [ -z "$metrics_id" ]; then
logger -t at_queue -p daemon.warn "Could not acquire token for metrics - will try again later"
return 1
fi
logger -t at_queue -p daemon.info "Processing all metrics with token $metrics_id"
# Execute all metrics commands with the single token
local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
# RSRP
local rsrp_output=$(execute_at_command "AT+QRSRP")
if [ -n "$rsrp_output" ] && echo "$rsrp_output" | grep -q "QRSRP"; then
local logfile="$LOGDIR/rsrp.json"
[ ! -s "$logfile" ] && echo "[]" > "$logfile"
local temp_file="${logfile}.tmp.$$"
jq --arg dt "$timestamp" \
--arg out "$rsrp_output" \
'. + [{"datetime": $dt, "output": $out}] | .[-'"$MAX_ENTRIES"':]' \
"$logfile" > "$temp_file" 2>/dev/null && mv "$temp_file" "$logfile"
chmod 644 "$logfile"
fi
sleep 0.5
# RSRQ
local rsrq_output=$(execute_at_command "AT+QRSRQ")
if [ -n "$rsrq_output" ] && echo "$rsrq_output" | grep -q "QRSRQ"; then
local logfile="$LOGDIR/rsrq.json"
[ ! -s "$logfile" ] && echo "[]" > "$logfile"
local temp_file="${logfile}.tmp.$$"
jq --arg dt "$timestamp" \
--arg out "$rsrq_output" \
'. + [{"datetime": $dt, "output": $out}] | .[-'"$MAX_ENTRIES"':]' \
"$logfile" > "$temp_file" 2>/dev/null && mv "$temp_file" "$logfile"
chmod 644 "$logfile"
fi
sleep 0.5
# SINR
local sinr_output=$(execute_at_command "AT+QSINR")
if [ -n "$sinr_output" ] && echo "$sinr_output" | grep -q "QSINR"; then
local logfile="$LOGDIR/sinr.json"
[ ! -s "$logfile" ] && echo "[]" > "$logfile"
local temp_file="${logfile}.tmp.$$"
jq --arg dt "$timestamp" \
--arg out "$sinr_output" \
'. + [{"datetime": $dt, "output": $out}] | .[-'"$MAX_ENTRIES"':]' \
"$logfile" > "$temp_file" 2>/dev/null && mv "$temp_file" "$logfile"
chmod 644 "$logfile"
fi
sleep 0.5
# Data usage
local usage_output=$(execute_at_command "AT+QGDCNT?;+QGDNRCNT?")
if [ -n "$usage_output" ] && echo "$usage_output" | grep -q "QGDCNT\|QGDNRCNT"; then
local logfile="$LOGDIR/data_usage.json"
[ ! -s "$logfile" ] && echo "[]" > "$logfile"
local temp_file="${logfile}.tmp.$$"
jq --arg dt "$timestamp" \
--arg out "$usage_output" \
'. + [{"datetime": $dt, "output": $out}] | .[-'"$MAX_ENTRIES"':]' \
"$logfile" > "$temp_file" 2>/dev/null && mv "$temp_file" "$logfile"
chmod 644 "$logfile"
fi
# Release token
release_token "$metrics_id"
logger -t at_queue -p daemon.info "Metrics processing completed"
return 0
}
# Main continuous logging function with proper locking
start_continuous_logging() {
# Check if already running
if check_running; then
logger -t at_queue -p daemon.error "Signal metrics logging already running"
exit 1
fi
# Store PID
echo "$$" > "$METRICS_PID_FILE"
chmod 644 "$METRICS_PID_FILE"
sleep 20 # Initial delay to allow system startup
logger -t at_queue -p daemon.info "Starting continuous signal metrics logging (PID: $$)"
trap 'logger -t at_queue -p daemon.info "Stopping signal metrics logging"; rm -f "$METRICS_PID_FILE"; exit 0' INT TERM
while true; do
process_all_metrics
sleep "$INTERVAL"
done
}
# Start the continuous logging
start_continuous_logging

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,544 @@
#!/bin/sh
# QuecWatch Daemon
# Monitors cellular connectivity and performs recovery actions
# Load UCI configuration functions
. /lib/functions.sh
# Configuration
QUEUE_DIR="/tmp/at_queue"
TOKEN_FILE="$QUEUE_DIR/token"
LOG_DIR="/tmp/log/quecwatch"
LOG_FILE="$LOG_DIR/quecwatch.log"
PID_FILE="/var/run/quecwatch.pid"
STATUS_FILE="/tmp/quecwatch_status.json"
RETRY_COUNT_FILE="/tmp/quecwatch_retry_count"
UCI_CONFIG="quecmanager"
MAX_TOKEN_WAIT=10 # Maximum seconds to wait for token acquisition
TOKEN_PRIORITY=15 # Medium priority (between profiles and metrics)
# Ensure directories exist
mkdir -p "$LOG_DIR" "$QUEUE_DIR"
# Store PID
echo "$$" > "$PID_FILE"
chmod 644 "$PID_FILE"
# Function to log messages
log_message() {
local level="${2:-info}"
local message="$1"
local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
# Log to file
echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
# Log to system log
logger -t quecwatch -p "daemon.$level" "$message"
}
# Function to update status
update_status() {
local status="$1"
local message="$2"
local retry="${3:-$CURRENT_RETRIES}"
local max="${4:-$MAX_RETRIES}"
# Create JSON status
cat > "$STATUS_FILE" <<EOF
{
"status": "$status",
"message": "$message",
"retry": $retry,
"maxRetries": $max,
"timestamp": $(date +%s)
}
EOF
chmod 644 "$STATUS_FILE"
log_message "Status updated: $status - $message" "debug"
}
# Function to acquire token for AT commands
acquire_token() {
local requestor_id="QUECWATCH_$(date +%s)_$$"
local priority="$TOKEN_PRIORITY"
local max_attempts=$MAX_TOKEN_WAIT
local attempt=0
log_message "Attempting to acquire token with priority $priority" "debug"
while [ $attempt -lt $max_attempts ]; do
# Check if token file exists
if [ -f "$TOKEN_FILE" ]; then
local current_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id' 2>/dev/null)
local current_priority=$(cat "$TOKEN_FILE" | jsonfilter -e '@.priority' 2>/dev/null)
local timestamp=$(cat "$TOKEN_FILE" | jsonfilter -e '@.timestamp' 2>/dev/null)
local current_time=$(date +%s)
# Check for expired token (> 30 seconds old)
if [ $((current_time - timestamp)) -gt 30 ] || [ -z "$current_holder" ]; then
# Remove expired token
log_message "Found expired token from $current_holder, removing" "debug"
rm -f "$TOKEN_FILE" 2>/dev/null
elif [ $priority -lt $current_priority ]; then
# Preempt lower priority token
log_message "Preempting token from $current_holder (priority: $current_priority)" "debug"
rm -f "$TOKEN_FILE" 2>/dev/null
else
# Check if the token is held by a QuecProfile or cell scan
if echo "$current_holder" | grep -q "CELL_SCAN"; then
log_message "Token held by cell scan (priority: $current_priority), waiting..." "debug"
elif echo "$current_holder" | grep -q "QUECPROFILES"; then
log_message "Token held by profile application (priority: $current_priority), waiting..." "debug"
else
log_message "Token held by $current_holder with priority $current_priority, retrying..." "debug"
fi
sleep 0.5
attempt=$((attempt + 1))
continue
fi
fi
# Try to create token file
echo "{\"id\":\"$requestor_id\",\"priority\":$priority,\"timestamp\":$(date +%s)}" > "$TOKEN_FILE" 2>/dev/null
chmod 644 "$TOKEN_FILE" 2>/dev/null
# Verify we got the token
local holder=$(cat "$TOKEN_FILE" 2>/dev/null | jsonfilter -e '@.id' 2>/dev/null)
if [ "$holder" = "$requestor_id" ]; then
log_message "Successfully acquired token with ID $requestor_id" "debug"
echo "$requestor_id"
return 0
fi
sleep 0.5
attempt=$((attempt + 1))
done
log_message "Failed to acquire token after $max_attempts attempts" "error"
return 1
}
# Function to release token
release_token() {
local requestor_id="$1"
if [ -f "$TOKEN_FILE" ]; then
local current_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id' 2>/dev/null)
if [ "$current_holder" = "$requestor_id" ]; then
rm -f "$TOKEN_FILE" 2>/dev/null
log_message "Released token $requestor_id" "debug"
return 0
fi
log_message "Token held by $current_holder, not by us ($requestor_id)" "warn"
else
log_message "Token file doesn't exist, nothing to release" "debug"
fi
return 1
}
# Function to execute AT command with token
execute_at_command() {
local cmd="$1"
local timeout="${2:-5}"
local token_id="$3"
if [ -z "$token_id" ]; then
log_message "No valid token provided for command: $cmd" "error"
return 1
fi
log_message "Executing AT command: $cmd (timeout: ${timeout}s)" "debug"
# Execute the command with proper timeout
local output
local status=1
output=$(sms_tool at "$cmd" -t "$timeout" 2>&1)
status=$?
if [ $status -ne 0 ]; then
log_message "AT command failed: $cmd (exit code: $status)" "error"
return 1
fi
echo "$output"
return 0
}
# Function to check internet connectivity
check_internet() {
local ping_target
local ping_count=3
# Get ping target from UCI
config_load "$UCI_CONFIG"
config_get ping_target quecwatch ping_target
if [ -z "$ping_target" ]; then
log_message "No ping target configured" "error"
return 1
fi
log_message "Checking internet connectivity to $ping_target" "debug"
if ping -c $ping_count "$ping_target" > /dev/null 2>&1; then
log_message "Internet connectivity check successful" "debug"
return 0
else
log_message "Internet connectivity check failed" "warn"
return 1
fi
}
# Function to get current SIM slot
get_current_sim() {
local token_id=$(acquire_token)
if [ -z "$token_id" ]; then
log_message "Failed to acquire token for SIM slot check" "error"
return 1
fi
log_message "Checking current SIM slot" "debug"
local result=$(execute_at_command "AT+QUIMSLOT?" 5 "$token_id")
local status=$?
# Release token
release_token "$token_id"
if [ $status -eq 0 ] && [ -n "$result" ]; then
# Extract SIM slot number from response
local current_sim=$(echo "$result" | grep -o '+QUIMSLOT: [0-9]' | cut -d' ' -f2)
if [ -n "$current_sim" ]; then
log_message "Current SIM slot: $current_sim" "debug"
echo "$current_sim"
return 0
fi
fi
log_message "Failed to get current SIM slot" "error"
return 1
}
# Function to switch SIM card
switch_sim_card() {
local current_sim
local target_sim
local token_id
log_message "Starting SIM card switch operation" "info"
# Get current SIM slot
current_sim=$(get_current_sim)
if [ $? -ne 0 ]; then
log_message "Failed to get current SIM slot, cannot switch" "error"
return 1
fi
# Determine target SIM
if [ "$current_sim" = "1" ]; then
target_sim=2
else
target_sim=1
fi
log_message "Attempting to switch from SIM $current_sim to SIM $target_sim" "info"
# Get token for AT commands
token_id=$(acquire_token)
if [ -z "$token_id" ]; then
log_message "Failed to acquire token for SIM switch" "error"
return 1
fi
# Detach from network
log_message "Detaching from network" "debug"
execute_at_command "AT+COPS=2" 10 "$token_id"
sleep 2
# Switch SIM slot
log_message "Switching to SIM slot $target_sim" "debug"
local switch_result=$(execute_at_command "AT+QUIMSLOT=$target_sim" 10 "$token_id")
local switch_status=$?
# If switch failed, return error
if [ $switch_status -ne 0 ]; then
log_message "Failed to switch to SIM $target_sim" "error"
release_token "$token_id"
return 1
fi
sleep 5
# Reattach to network
log_message "Reattaching to network" "debug"
execute_at_command "AT+COPS=0" 10 "$token_id"
# Release token
release_token "$token_id"
# Verify switch
sleep 10
local new_sim=$(get_current_sim)
if [ "$new_sim" = "$target_sim" ]; then
log_message "Successfully switched to SIM $target_sim" "info"
return 0
else
log_message "Failed to verify SIM switch, current SIM is $new_sim" "error"
return 1
fi
}
# Function to perform connection recovery
perform_connection_recovery() {
local token_id
log_message "Starting connection recovery" "info"
# Get token for AT commands
token_id=$(acquire_token)
if [ -z "$token_id" ]; then
log_message "Failed to acquire token for connection recovery" "error"
return 1
fi
# Detach from network
log_message "Detaching from network" "debug"
execute_at_command "AT+COPS=2" 10 "$token_id"
sleep 2
# Reattach to network
log_message "Reattaching to network" "debug"
execute_at_command "AT+COPS=0" 15 "$token_id"
# Release token
release_token "$token_id"
# Verify recovery
sleep 10
if check_internet; then
log_message "Connection recovery successful" "info"
return 0
else
log_message "Connection recovery failed" "error"
return 1
fi
}
# Load configuration
load_config() {
# Initialize variables
PING_TARGET=""
PING_INTERVAL=60
PING_FAILURES=3
MAX_RETRIES=5
CURRENT_RETRIES=0
CONNECTION_REFRESH=0
REFRESH_COUNT=3
AUTO_SIM_FAILOVER=0
SIM_FAILOVER_SCHEDULE=0
# Load from UCI
config_load "$UCI_CONFIG"
# Get settings with defaults
config_get PING_TARGET quecwatch ping_target
config_get PING_INTERVAL quecwatch ping_interval 60
config_get PING_FAILURES quecwatch ping_failures 3
config_get MAX_RETRIES quecwatch max_retries 5
config_get CURRENT_RETRIES quecwatch current_retries 0
config_get_bool CONNECTION_REFRESH quecwatch connection_refresh 0
config_get REFRESH_COUNT quecwatch refresh_count 3
config_get_bool AUTO_SIM_FAILOVER quecwatch auto_sim_failover 0
config_get SIM_FAILOVER_SCHEDULE quecwatch sim_failover_schedule 0
# Validate required settings
if [ -z "$PING_TARGET" ]; then
log_message "No ping target configured, using default (8.8.8.8)" "warn"
PING_TARGET="8.8.8.8"
uci set "$UCI_CONFIG.quecwatch.ping_target=$PING_TARGET"
uci commit "$UCI_CONFIG"
fi
# Load persisted retry count if available
if [ -f "$RETRY_COUNT_FILE" ]; then
CURRENT_RETRIES=$(cat "$RETRY_COUNT_FILE")
fi
log_message "Configuration loaded: ping_target=$PING_TARGET, interval=$PING_INTERVAL, failures=$PING_FAILURES, max_retries=$MAX_RETRIES, current_retries=$CURRENT_RETRIES" "info"
}
# Save retry count to both UCI and file
save_retry_count() {
local count=$1
# Update UCI
uci set "$UCI_CONFIG.quecwatch.current_retries=$count"
uci commit "$UCI_CONFIG"
# Update file for crash recovery
echo "$count" > "$RETRY_COUNT_FILE"
chmod 644 "$RETRY_COUNT_FILE"
log_message "Updated retry count to $count" "debug"
}
# Main monitoring function
main() {
log_message "QuecWatch daemon starting (PID: $$)" "info"
# Load configuration
load_config
# Initial status update
update_status "active" "Monitoring started"
# Track consecutive failures
local failure_count=0
# For scheduled SIM failover
local sim_failover_interval=0
local initial_sim=""
# If auto SIM failover is enabled, store initial SIM slot
if [ "$AUTO_SIM_FAILOVER" -eq 1 ]; then
initial_sim=$(get_current_sim)
if [ -n "$initial_sim" ]; then
log_message "Auto SIM failover enabled, initial SIM slot: $initial_sim" "info"
fi
fi
# Main monitoring loop
while true; do
log_message "Starting monitoring cycle" "debug"
# Check internet connectivity
if ! check_internet; then
failure_count=$((failure_count + 1))
log_message "Connectivity check failed ($failure_count/$PING_FAILURES)" "warn"
# Update status
update_status "warning" "Connection check failed: $failure_count/$PING_FAILURES failures"
# Check if failure threshold is reached
if [ $failure_count -ge $PING_FAILURES ]; then
# Reset failure counter
failure_count=0
# Increment retry counter
CURRENT_RETRIES=$((CURRENT_RETRIES + 1))
save_retry_count $CURRENT_RETRIES
log_message "Failure threshold reached. Current retry: $CURRENT_RETRIES/$MAX_RETRIES" "warn"
update_status "error" "Connection lost, attempt $CURRENT_RETRIES/$MAX_RETRIES to recover"
# Check if max retries reached
if [ $CURRENT_RETRIES -ge $MAX_RETRIES ]; then
log_message "Maximum retries reached" "error"
# Try SIM failover if enabled
if [ "$AUTO_SIM_FAILOVER" -eq 1 ]; then
log_message "Attempting SIM failover" "info"
update_status "failover" "Maximum retries reached, attempting SIM failover"
if switch_sim_card && check_internet; then
log_message "SIM failover successful, connection restored" "info"
update_status "recovered" "Connection restored via SIM failover"
# Reset retry counter
CURRENT_RETRIES=0
save_retry_count $CURRENT_RETRIES
else
log_message "SIM failover failed, system will reboot" "error"
update_status "rebooting" "SIM failover failed, system will reboot"
# Wait briefly and reboot
sleep 5
reboot
fi
else
log_message "Auto SIM failover disabled, system will reboot" "error"
update_status "rebooting" "Maximum retries reached, system will reboot"
# Wait briefly and reboot
sleep 5
reboot
fi
else
# Try connection recovery
log_message "Attempting connection recovery" "info"
update_status "recovering" "Attempting to restore connection"
if perform_connection_recovery; then
log_message "Connection recovery successful" "info"
update_status "recovered" "Connection restored"
# Reset retry counter
CURRENT_RETRIES=0
save_retry_count $CURRENT_RETRIES
fi
fi
fi
else
# Connection is good
if [ $failure_count -gt 0 ] || [ $CURRENT_RETRIES -gt 0 ]; then
log_message "Connection restored" "info"
update_status "stable" "Connection restored"
# Reset counters
failure_count=0
CURRENT_RETRIES=0
save_retry_count $CURRENT_RETRIES
fi
# Scheduled SIM failover check
if [ "$AUTO_SIM_FAILOVER" -eq 1 ] && [ "$SIM_FAILOVER_SCHEDULE" -gt 0 ] && [ -n "$initial_sim" ]; then
# Get current SIM to check if we're on the backup
local current_sim=$(get_current_sim)
# If we're on backup SIM, check if it's time to try primary again
if [ -n "$current_sim" ] && [ "$current_sim" != "$initial_sim" ]; then
sim_failover_interval=$((sim_failover_interval + 1))
# Check if we've reached the scheduled time
if [ $((sim_failover_interval * PING_INTERVAL)) -ge $((SIM_FAILOVER_SCHEDULE * 60)) ]; then
log_message "Scheduled check: attempting to switch back to primary SIM $initial_sim" "info"
update_status "switchback" "Attempting to switch back to primary SIM"
# Try switching back
if switch_sim_card && check_internet; then
log_message "Successfully switched back to primary SIM" "info"
update_status "stable" "Successfully switched back to primary SIM"
else
log_message "Failed to switch back to primary SIM, staying on backup" "warn"
update_status "stable" "Staying on backup SIM - primary SIM check failed"
# Switch back to backup SIM
current_sim=$(get_current_sim)
if [ -n "$current_sim" ] && [ "$current_sim" = "$initial_sim" ]; then
switch_sim_card
fi
fi
# Reset failover interval
sim_failover_interval=0
fi
fi
fi
fi
# Sleep for the configured interval
sleep $PING_INTERVAL
done
}
# Set up trap for clean shutdown
trap 'log_message "Received signal, exiting" "info"; update_status "stopped" "Daemon stopped"; rm -f "$PID_FILE"; exit 0' INT TERM
# Start the main function
main

View File

@@ -0,0 +1,429 @@
#!/bin/sh
# Cell Lock Scheduler Daemon
# Monitors schedule and applies/restores cell locks as needed
# Load UCI configuration functions
. /lib/functions.sh
# Configuration
QUEUE_DIR="/tmp/at_queue"
TOKEN_FILE="$QUEUE_DIR/token"
LOG_DIR="/tmp/log/cell_lock"
LOG_FILE="$LOG_DIR/cell_lock.log"
PID_FILE="/var/run/cell_lock_scheduler.pid"
STATUS_FILE="/tmp/cell_lock_status.json"
UCI_CONFIG="quecmanager"
CHECK_INTERVAL=60 # Check schedule every minute
MAX_TOKEN_WAIT=15 # Maximum seconds to wait for token acquisition
TOKEN_PRIORITY=5 # Higher priority than QuecWatch (which is 15)
# Ensure directories exist
mkdir -p "$LOG_DIR" "$QUEUE_DIR"
# Store PID
echo "$$" > "$PID_FILE"
chmod 644 "$PID_FILE"
# Function to log messages
log_message() {
local level="${2:-info}"
local message="$1"
local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
# Log to file
echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
# Log to system log
logger -t cell_lock -p "daemon.$level" "$message"
}
# Function to update status
update_status() {
local status="$1"
local message="$2"
local active="${3:-0}"
local locked="${4:-0}"
# Create JSON status
cat > "$STATUS_FILE" <<EOF
{
"status": "$status",
"message": "$message",
"active": $active,
"locked": $locked,
"timestamp": $(date +%s)
}
EOF
chmod 644 "$STATUS_FILE"
log_message "Status updated: $status - $message" "debug"
}
# Function to acquire token for AT commands
acquire_token() {
local requestor_id="CELLLOCK_$(date +%s)_$$"
local priority="$TOKEN_PRIORITY"
local max_attempts=$MAX_TOKEN_WAIT
local attempt=0
log_message "Attempting to acquire token with priority $priority" "debug"
while [ $attempt -lt $max_attempts ]; do
# Check if token file exists
if [ -f "$TOKEN_FILE" ]; then
local current_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id' 2>/dev/null)
local current_priority=$(cat "$TOKEN_FILE" | jsonfilter -e '@.priority' 2>/dev/null)
local timestamp=$(cat "$TOKEN_FILE" | jsonfilter -e '@.timestamp' 2>/dev/null)
local current_time=$(date +%s)
# Check for expired token (> 30 seconds old)
if [ $((current_time - timestamp)) -gt 30 ] || [ -z "$current_holder" ]; then
# Remove expired token
log_message "Found expired token from $current_holder, removing" "debug"
rm -f "$TOKEN_FILE" 2>/dev/null
elif [ $priority -lt $current_priority ]; then
# Preempt lower priority token
log_message "Preempting token from $current_holder (priority: $current_priority)" "debug"
rm -f "$TOKEN_FILE" 2>/dev/null
else
# Check if the token is held by a cell scan
if echo "$current_holder" | grep -q "CELL_SCAN"; then
log_message "Token held by cell scan (priority: $current_priority), waiting..." "debug"
else
log_message "Token held by $current_holder with priority $current_priority, retrying..." "debug"
fi
sleep 0.5
attempt=$((attempt + 1))
continue
fi
fi
# Try to create token file
echo "{\"id\":\"$requestor_id\",\"priority\":$priority,\"timestamp\":$(date +%s)}" > "$TOKEN_FILE" 2>/dev/null
chmod 644 "$TOKEN_FILE" 2>/dev/null
# Verify we got the token
local holder=$(cat "$TOKEN_FILE" 2>/dev/null | jsonfilter -e '@.id' 2>/dev/null)
if [ "$holder" = "$requestor_id" ]; then
log_message "Successfully acquired token with ID $requestor_id" "debug"
echo "$requestor_id"
return 0
fi
sleep 0.5
attempt=$((attempt + 1))
done
log_message "Failed to acquire token after $max_attempts attempts" "error"
return 1
}
# Function to release token
release_token() {
local requestor_id="$1"
if [ -f "$TOKEN_FILE" ]; then
local current_holder=$(cat "$TOKEN_FILE" | jsonfilter -e '@.id' 2>/dev/null)
if [ "$current_holder" = "$requestor_id" ]; then
rm -f "$TOKEN_FILE" 2>/dev/null
log_message "Released token $requestor_id" "debug"
return 0
fi
log_message "Token held by $current_holder, not by us ($requestor_id)" "warn"
else
log_message "Token file doesn't exist, nothing to release" "debug"
fi
return 1
}
# Function to execute AT command with token
execute_at_command() {
local cmd="$1"
local timeout="${2:-10}"
local token_id="$3"
if [ -z "$token_id" ]; then
log_message "No valid token provided for command: $cmd" "error"
return 1
fi
log_message "Executing AT command: $cmd (timeout: ${timeout}s)" "debug"
# Execute the command with proper timeout
local output
local status=1
output=$(sms_tool at "$cmd" -t "$timeout" 2>&1)
status=$?
if [ $status -ne 0 ]; then
log_message "AT command failed: $cmd (exit code: $status)" "error"
return 1
fi
echo "$output"
return 0
}
# Function to check current lock status
check_lock_status() {
local token_id="$1"
log_message "Checking current cell lock status" "debug"
# Check LTE lock status
local lte_status=$(execute_at_command 'AT+QNWLOCK="common/4g"' 5 "$token_id")
local nr5g_status=$(execute_at_command 'AT+QNWLOCK="common/5g"' 5 "$token_id")
# Check if any lock is active
if echo "$lte_status" | grep -q '"common/4g",0'; then
if echo "$nr5g_status" | grep -q '"common/5g",0'; then
log_message "No active cell locks detected" "debug"
return 1
fi
fi
log_message "Active cell locks detected" "debug"
return 0
}
# Function to get current lock parameters and save to UCI
store_current_lock_params() {
local token_id="$1"
log_message "Storing current lock parameters" "debug"
# Get LTE lock status
local lte_status=$(execute_at_command 'AT+QNWLOCK="common/4g"' 5 "$token_id")
if [ $? -eq 0 ]; then
# Extract parameters
local lte_params=$(echo "$lte_status" | grep -o '"common/4g",[^[:space:]]*' | cut -d',' -f2-)
# Save to UCI
uci set "$UCI_CONFIG.cell_lock.lte_params='$lte_params'"
log_message "Stored LTE parameters: $lte_params" "debug"
fi
# Get NR5G lock status
local nr5g_status=$(execute_at_command 'AT+QNWLOCK="common/5g"' 5 "$token_id")
if [ $? -eq 0 ]; then
# Extract parameters
local nr5g_params=$(echo "$nr5g_status" | grep -o '"common/5g",[^[:space:]]*' | cut -d',' -f2-)
# Save to UCI
uci set "$UCI_CONFIG.cell_lock.nr5g_params='$nr5g_params'"
log_message "Stored NR5G parameters: $nr5g_params" "debug"
fi
# Get persist settings
local persist_status=$(execute_at_command 'AT+QNWLOCK="save_ctrl"' 5 "$token_id")
if [ $? -eq 0 ]; then
# Extract parameters (LTE persist is at index 1, NR5G persist is at index 2)
local persist_params=$(echo "$persist_status" | grep -o '"save_ctrl",[^[:space:]]*' | cut -d',' -f2-)
local lte_persist=$(echo "$persist_params" | cut -d',' -f1)
local nr5g_persist=$(echo "$persist_params" | cut -d',' -f2)
# Save to UCI
uci set "$UCI_CONFIG.cell_lock.lte_persist='$lte_persist'"
uci set "$UCI_CONFIG.cell_lock.nr5g_persist='$nr5g_persist'"
log_message "Stored persist settings: LTE=$lte_persist, NR5G=$nr5g_persist" "debug"
fi
# Commit changes
uci commit "$UCI_CONFIG"
return 0
}
# Function to check if time is in range
is_time_in_range() {
local current_time_minutes=$1
local start_time_minutes=$2
local end_time_minutes=$3
# Handle case where end time is on the next day
if [ $end_time_minutes -lt $start_time_minutes ]; then
if [ $current_time_minutes -ge $start_time_minutes ] || [ $current_time_minutes -lt $end_time_minutes ]; then
return 0
fi
else
if [ $current_time_minutes -ge $start_time_minutes ] && [ $current_time_minutes -lt $end_time_minutes ]; then
return 0
fi
fi
return 1
}
# Function to convert HH:MM to minutes
time_to_minutes() {
local time="$1"
local hours=$(echo "$time" | cut -d':' -f1)
local minutes=$(echo "$time" | cut -d':' -f2)
echo $((hours * 60 + minutes))
}
# Function to check schedule and manage cell locks
check_schedule() {
local enabled
local start_time
local end_time
local current_active
# Get current scheduler state from UCI
config_load "$UCI_CONFIG"
config_get_bool enabled cell_lock enabled 0
if [ "$enabled" -ne 1 ]; then
log_message "Cell lock scheduler is disabled" "debug"
update_status "disabled" "Scheduler is disabled" 0 0
return 0
fi
# Get schedule from UCI
config_get start_time cell_lock start_time
config_get end_time cell_lock end_time
config_get current_active cell_lock active 0
if [ -z "$start_time" ] || [ -z "$end_time" ]; then
log_message "Missing start or end time in configuration" "error"
update_status "error" "Missing schedule configuration" 0 0
return 1
}
# Get current time
local current_time=$(date "+%H:%M")
# Convert times to minutes for comparison
local current_minutes=$(time_to_minutes "$current_time")
local start_minutes=$(time_to_minutes "$start_time")
local end_minutes=$(time_to_minutes "$end_time")
# Get token for AT commands
local token_id=$(acquire_token)
if [ -z "$token_id" ]; then
log_message "Failed to acquire token for checking schedule" "error"
update_status "error" "Failed to acquire token for checking schedule" 0 0
return 1
}
# Check if any cell lock is currently active
local lock_active=0
check_lock_status "$token_id" && lock_active=1
# Check if current time is in the scheduled range
if is_time_in_range "$current_minutes" "$start_minutes" "$end_minutes"; then
# We're in the active window
if [ "$current_active" -ne 1 ]; then
# We just entered the window, need to save current state
log_message "Entering scheduled window" "info"
# Store current lock parameters if a lock is active
if [ $lock_active -eq 1 ]; then
log_message "Storing current cell lock parameters" "info"
store_current_lock_params "$token_id"
else
log_message "No active cell locks to store" "info"
update_status "inactive" "Schedule active but no cell locks configured" 1 0
release_token "$token_id"
return 0
}
# Update status
uci set "$UCI_CONFIG.cell_lock.active=1"
uci commit "$UCI_CONFIG"
update_status "active" "Cell lock scheduler is active" 1 $lock_active
else
update_status "active" "Cell lock scheduler is active" 1 $lock_active
}
else
# We're outside the active window
if [ "$current_active" -eq 1 ]; then
# We just exited the window
log_message "Exiting scheduled window" "info"
# Update status
uci set "$UCI_CONFIG.cell_lock.active=0"
uci commit "$UCI_CONFIG"
update_status "inactive" "Outside scheduled hours" 0 $lock_active
} else {
update_status "inactive" "Outside scheduled hours" 0 $lock_active
}
fi
# Release token
release_token "$token_id"
return 0
}
# Main function
main() {
log_message "Cell lock scheduler daemon starting (PID: $$)" "info"
# Ensure UCI section exists
if ! uci -q get "$UCI_CONFIG.cell_lock" >/dev/null; then
uci set "$UCI_CONFIG.cell_lock=scheduler"
uci set "$UCI_CONFIG.cell_lock.enabled=0"
uci set "$UCI_CONFIG.cell_lock.active=0"
uci commit "$UCI_CONFIG"
log_message "Created cell lock UCI configuration" "info"
fi
# Initialize status
update_status "starting" "Cell lock scheduler daemon starting" 0 0
# Get token and check if any locks are active
local token_id=$(acquire_token)
if [ -n "$token_id" ]; then
local lock_active=0
check_lock_status "$token_id" && lock_active=1
release_token "$token_id"
# Update status based on current state
local enabled=$(uci -q get "$UCI_CONFIG.cell_lock.enabled")
if [ "$enabled" = "1" ]; then
# Get schedule from UCI
local start_time=$(uci -q get "$UCI_CONFIG.cell_lock.start_time")
local end_time=$(uci -q get "$UCI_CONFIG.cell_lock.end_time")
if [ -n "$start_time" ] && [ -n "$end_time" ]; then
# Check if we're currently in the schedule window
local current_time=$(date "+%H:%M")
local current_minutes=$(time_to_minutes "$current_time")
local start_minutes=$(time_to_minutes "$start_time")
local end_minutes=$(time_to_minutes "$end_time")
if is_time_in_range "$current_minutes" "$start_minutes" "$end_minutes"; then
update_status "active" "Cell lock scheduler is active" 1 $lock_active
uci set "$UCI_CONFIG.cell_lock.active=1"
uci commit "$UCI_CONFIG"
} else {
update_status "inactive" "Cell lock scheduler is enabled but outside scheduled hours" 0 $lock_active
uci set "$UCI_CONFIG.cell_lock.active=0"
uci commit "$UCI_CONFIG"
}
} else {
update_status "error" "Missing schedule configuration" 0 $lock_active
}
} else {
update_status "disabled" "Cell lock scheduler is disabled" 0 $lock_active
}
} else {
log_message "Failed to acquire token for initial status check" "error"
}
# Main monitoring loop
while true; do
check_schedule
sleep $CHECK_INTERVAL
done
}
# Set up trap for clean shutdown
trap 'log_message "Received signal, exiting" "info"; update_status "stopped" "Daemon stopped" 0 0; rm -f "$PID_FILE"; exit 0' INT TERM
# Start the main function
main

File diff suppressed because one or more lines are too long

View File

@@ -12,8 +12,8 @@ e:I[99165,[],"OutletBoundary"]
10:I[99165,[],"MetadataBoundary"]
12:I[99165,[],"ViewportBoundary"]
14:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","about",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["about",{"children":["__PAGE__",{}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["about",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","about","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$La",null,{"Component":"$b","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@c","$@d"]}],null,["$","$Le",null,{"children":"$Lf"}]]}],{},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","BSKC_qZkYyipuB2zOenkG",{"children":[["$","$L10",null,{"children":"$L11"}],["$","$L12",null,{"children":"$L13"}],null]}]]}],false]],"m":"$undefined","G":["$14","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","about",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["about",{"children":["__PAGE__",{}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["about",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","about","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$La",null,{"Component":"$b","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@c","$@d"]}],null,["$","$Le",null,{"children":"$Lf"}]]}],{},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","RZohU-9AWPF-9t-zmaIRM",{"children":[["$","$L10",null,{"children":"$L11"}],["$","$L12",null,{"children":"$L13"}],null]}]]}],false]],"m":"$undefined","G":["$14","$undefined"],"s":false,"S":true}
9:{}
c:{}
d:{}

View File

@@ -13,8 +13,8 @@ d:I[30233,["7780","static/chunks/7780-d44d1f6d676771d4.js","8885","static/chunks
12:I[99165,[],"MetadataBoundary"]
14:I[99165,[],"ViewportBoundary"]
16:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","advanced-settings","at-terminal",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["advanced-settings",{"children":["at-terminal",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["advanced-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","advanced-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["at-terminal",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","advanced-settings","children","at-terminal","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","bj2A73QxjlYnOYfFw8cO4",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","advanced-settings","at-terminal",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["advanced-settings",{"children":["at-terminal",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["advanced-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","advanced-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["at-terminal",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","advanced-settings","children","at-terminal","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","hm9QRsQDmkQ3tAbrgPcdY",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
9:{}
b:{}
e:{}

View File

@@ -13,8 +13,8 @@ d:I[39966,["9980","static/chunks/7b0cf0b7-aa73cc75e53c5793.js","7780","static/ch
12:I[99165,[],"MetadataBoundary"]
14:I[99165,[],"ViewportBoundary"]
16:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","advanced-settings","connectivity",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["advanced-settings",{"children":["connectivity",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["advanced-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","advanced-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["connectivity",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","advanced-settings","children","connectivity","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","DTnEPxio4LFqOIRh4jg54",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","advanced-settings","connectivity",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["advanced-settings",{"children":["connectivity",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["advanced-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","advanced-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["connectivity",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","advanced-settings","children","connectivity","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","w8TAMqIS2JBthNV_YVtwR",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
9:{}
b:{}
e:{}

File diff suppressed because one or more lines are too long

View File

@@ -13,8 +13,8 @@ d:I[34819,["9980","static/chunks/7b0cf0b7-aa73cc75e53c5793.js","7780","static/ch
12:I[99165,[],"MetadataBoundary"]
14:I[99165,[],"ViewportBoundary"]
16:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","advanced-settings","mtu",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["advanced-settings",{"children":["mtu",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["advanced-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","advanced-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["mtu",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","advanced-settings","children","mtu","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","ScZBASEMrtUqrI39H0niV",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","advanced-settings","mtu",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["advanced-settings",{"children":["mtu",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["advanced-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","advanced-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["mtu",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","advanced-settings","children","mtu","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","cA5c4vNH7cwC7Joq-Y4Yd",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
9:{}
b:{}
e:{}

View File

@@ -13,8 +13,8 @@ d:I[83143,["7780","static/chunks/7780-d44d1f6d676771d4.js","1630","static/chunks
12:I[99165,[],"MetadataBoundary"]
14:I[99165,[],"ViewportBoundary"]
16:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","advanced-settings","ttl-settings",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["advanced-settings",{"children":["ttl-settings",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["advanced-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","advanced-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["ttl-settings",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","advanced-settings","children","ttl-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","llJFJ7mfZbQX4KYjHnA13",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","advanced-settings","ttl-settings",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["advanced-settings",{"children":["ttl-settings",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["advanced-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","advanced-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["ttl-settings",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","advanced-settings","children","ttl-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","HdT6-waxZQsLw7x1rwFLT",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
9:{}
b:{}
e:{}

View File

@@ -13,8 +13,8 @@ d:I[75808,["9980","static/chunks/7b0cf0b7-aa73cc75e53c5793.js","7780","static/ch
12:I[99165,[],"MetadataBoundary"]
14:I[99165,[],"ViewportBoundary"]
16:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","cell-settings","band-locking",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["cell-settings",{"children":["band-locking",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["cell-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["band-locking",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children","band-locking","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","2Y24FMa69p9yW_OKggC-6",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","cell-settings","band-locking",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["cell-settings",{"children":["band-locking",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["cell-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["band-locking",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children","band-locking","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","I5l4teEHIa5cqKxE86yKb",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
9:{}
b:{}
e:{}

View File

@@ -13,8 +13,8 @@ d:I[46142,["9980","static/chunks/7b0cf0b7-aa73cc75e53c5793.js","7780","static/ch
12:I[99165,[],"MetadataBoundary"]
14:I[99165,[],"ViewportBoundary"]
16:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","cell-settings","basic-settings",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["cell-settings",{"children":["basic-settings",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["cell-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["basic-settings",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children","basic-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","TWo8kQLQAE_sIuiA-dq55",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","cell-settings","basic-settings",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["cell-settings",{"children":["basic-settings",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["cell-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["basic-settings",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children","basic-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","rn7mp_whi-jobAxB20m3t",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
9:{}
b:{}
e:{}

View File

@@ -13,8 +13,8 @@ d:I[19496,["9980","static/chunks/7b0cf0b7-aa73cc75e53c5793.js","7780","static/ch
12:I[99165,[],"MetadataBoundary"]
14:I[99165,[],"ViewportBoundary"]
16:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","cell-settings","cell-locking",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["cell-settings",{"children":["cell-locking",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["cell-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["cell-locking",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children","cell-locking","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","rx4uHCwkz952NZVSiHHzU",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","cell-settings","cell-locking",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["cell-settings",{"children":["cell-locking",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["cell-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["cell-locking",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children","cell-locking","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","phyXo461-jaRS48xx1Jkp",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
9:{}
b:{}
e:{}

View File

@@ -13,8 +13,8 @@ d:I[70231,["7780","static/chunks/7780-d44d1f6d676771d4.js","8885","static/chunks
12:I[99165,[],"MetadataBoundary"]
14:I[99165,[],"ViewportBoundary"]
16:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","cell-settings","imei-mangling",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["cell-settings",{"children":["imei-mangling",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["cell-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["imei-mangling",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children","imei-mangling","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","NJz0A4i3VoodXZwAtTIsu",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","cell-settings","imei-mangling",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["cell-settings",{"children":["imei-mangling",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["cell-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["imei-mangling",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children","imei-mangling","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","k1fgfTjUyxtiLVHjAy59c",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
9:{}
b:{}
e:{}

File diff suppressed because one or more lines are too long

View File

@@ -13,8 +13,8 @@ d:I[33776,["9980","static/chunks/7b0cf0b7-aa73cc75e53c5793.js","7780","static/ch
12:I[99165,[],"MetadataBoundary"]
14:I[99165,[],"ViewportBoundary"]
16:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","cell-settings","sms",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["cell-settings",{"children":["sms",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["cell-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["sms",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children","sms","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","Ma0Wa-HkTE40td21wg4-O",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","cell-settings","sms",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["cell-settings",{"children":["sms",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["cell-settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["sms",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","cell-settings","children","sms","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","5G7-X9ijwG_lbiG668Bul",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
9:{}
b:{}
e:{}

View File

@@ -8,13 +8,13 @@
8:I[96609,["9980","static/chunks/7b0cf0b7-aa73cc75e53c5793.js","7780","static/chunks/7780-d44d1f6d676771d4.js","8885","static/chunks/8885-1b9ab3cbb10cf437.js","7563","static/chunks/7563-33b7de2a93dcbe27.js","9464","static/chunks/9464-f5c3c85ad60907ac.js","9477","static/chunks/9477-215fa25b7251af44.js","6357","static/chunks/6357-9bebe3918fcef1e5.js","7414","static/chunks/7414-d6480d4dfb8a2ef8.js","4767","static/chunks/4767-88886265e4e59e78.js","1954","static/chunks/app/dashboard/layout-5311362b3a63fe81.js"],"default"]
a:I[31753,["9477","static/chunks/9477-215fa25b7251af44.js","3075","static/chunks/app/dashboard/experimental/layout-6508e2a223029fa4.js"],"default"]
c:I[5329,[],"ClientPageRoot"]
d:I[37277,["9980","static/chunks/7b0cf0b7-aa73cc75e53c5793.js","2101","static/chunks/b1b46485-5c61721f784038c7.js","7780","static/chunks/7780-d44d1f6d676771d4.js","8885","static/chunks/8885-1b9ab3cbb10cf437.js","7563","static/chunks/7563-33b7de2a93dcbe27.js","9679","static/chunks/9679-e42f7aaecc29c6da.js","3048","static/chunks/3048-a6b509fac24a1f29.js","7231","static/chunks/7231-9bf29e950cdd6225.js","5014","static/chunks/app/dashboard/experimental/cell-scanner/page-a4709c7977b627a1.js"],"default"]
d:I[88388,["9980","static/chunks/7b0cf0b7-aa73cc75e53c5793.js","2101","static/chunks/b1b46485-5c61721f784038c7.js","7780","static/chunks/7780-d44d1f6d676771d4.js","8885","static/chunks/8885-1b9ab3cbb10cf437.js","7563","static/chunks/7563-33b7de2a93dcbe27.js","9679","static/chunks/9679-e42f7aaecc29c6da.js","3048","static/chunks/3048-a6b509fac24a1f29.js","3453","static/chunks/3453-59569df86cb1327e.js","2394","static/chunks/2394-bec269701e2d0c16.js","5014","static/chunks/app/dashboard/experimental/cell-scanner/page-2c4956be7a457748.js"],"default"]
10:I[99165,[],"OutletBoundary"]
12:I[99165,[],"MetadataBoundary"]
14:I[99165,[],"ViewportBoundary"]
16:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","experimental","cell-scanner",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["experimental",{"children":["cell-scanner",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["experimental",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["cell-scanner",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children","cell-scanner","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","-VsjM1sVW_65u4kXCmmrZ",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","experimental","cell-scanner",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["experimental",{"children":["cell-scanner",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["experimental",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["cell-scanner",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children","cell-scanner","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","7hjQOimHf9dxD0FQquY-1",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
9:{}
b:{}
e:{}

View File

@@ -8,13 +8,13 @@
8:I[96609,["9980","static/chunks/7b0cf0b7-aa73cc75e53c5793.js","7780","static/chunks/7780-d44d1f6d676771d4.js","8885","static/chunks/8885-1b9ab3cbb10cf437.js","7563","static/chunks/7563-33b7de2a93dcbe27.js","9464","static/chunks/9464-f5c3c85ad60907ac.js","9477","static/chunks/9477-215fa25b7251af44.js","6357","static/chunks/6357-9bebe3918fcef1e5.js","7414","static/chunks/7414-d6480d4dfb8a2ef8.js","4767","static/chunks/4767-88886265e4e59e78.js","1954","static/chunks/app/dashboard/layout-5311362b3a63fe81.js"],"default"]
a:I[31753,["9477","static/chunks/9477-215fa25b7251af44.js","3075","static/chunks/app/dashboard/experimental/layout-6508e2a223029fa4.js"],"default"]
c:I[5329,[],"ClientPageRoot"]
d:I[3099,["7780","static/chunks/7780-d44d1f6d676771d4.js","9007","static/chunks/9007-7f45a2e4a42c9be9.js","666","static/chunks/app/dashboard/experimental/freq-calculator/page-72839bc94c5707d7.js"],"default"]
d:I[14332,["7780","static/chunks/7780-d44d1f6d676771d4.js","3453","static/chunks/3453-59569df86cb1327e.js","5755","static/chunks/5755-b330e14a84ee51bb.js","666","static/chunks/app/dashboard/experimental/freq-calculator/page-76fc91defa16e132.js"],"default"]
10:I[99165,[],"OutletBoundary"]
12:I[99165,[],"MetadataBoundary"]
14:I[99165,[],"ViewportBoundary"]
16:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","experimental","freq-calculator",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["experimental",{"children":["freq-calculator",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["experimental",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["freq-calculator",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children","freq-calculator","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","o7VWYjimCCCFZCRLxFY0B",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","experimental","freq-calculator",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["experimental",{"children":["freq-calculator",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["experimental",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["freq-calculator",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children","freq-calculator","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","WFkxhM9vtqBB8f3DnNJXD",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
9:{}
b:{}
e:{}

View File

@@ -13,8 +13,8 @@ d:I[53302,["7780","static/chunks/7780-d44d1f6d676771d4.js","3376","static/chunks
12:I[99165,[],"MetadataBoundary"]
14:I[99165,[],"ViewportBoundary"]
16:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","experimental","keep-alive",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["experimental",{"children":["keep-alive",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["experimental",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["keep-alive",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children","keep-alive","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","Jc6BKIfIAvXV2gGVtiA7o",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","experimental","keep-alive",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["experimental",{"children":["keep-alive",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["experimental",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["keep-alive",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children","keep-alive","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","nNAnT0dUxnVk-Ph9jYfei",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
9:{}
b:{}
e:{}

View File

@@ -13,8 +13,8 @@ d:I[22256,["9980","static/chunks/7b0cf0b7-aa73cc75e53c5793.js","7780","static/ch
12:I[99165,[],"MetadataBoundary"]
14:I[99165,[],"ViewportBoundary"]
16:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","experimental","quecprofiles",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["experimental",{"children":["quecprofiles",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["experimental",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["quecprofiles",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children","quecprofiles","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","mX9IoPGvofCyUh35BvXKU",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","experimental","quecprofiles",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["experimental",{"children":["quecprofiles",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["experimental",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["quecprofiles",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children","quecprofiles","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","8vIgfmEVWfTGJjm3M-nNQ",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
9:{}
b:{}
e:{}

File diff suppressed because one or more lines are too long

View File

@@ -13,8 +13,8 @@ d:I[79824,["9980","static/chunks/7b0cf0b7-aa73cc75e53c5793.js","7780","static/ch
12:I[99165,[],"MetadataBoundary"]
14:I[99165,[],"ViewportBoundary"]
16:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","experimental","quecwatch",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["experimental",{"children":["quecwatch",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["experimental",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["quecwatch",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children","quecwatch","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","F6_JxCamNLO0up-1ooNFl",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","experimental","quecwatch",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["experimental",{"children":["quecwatch",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["experimental",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["quecwatch",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","experimental","children","quecwatch","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","ElzUMD5BvsKfchaBLPpgj",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
9:{}
b:{}
e:{}

File diff suppressed because one or more lines are too long

View File

@@ -12,8 +12,8 @@ e:I[99165,[],"OutletBoundary"]
10:I[99165,[],"MetadataBoundary"]
12:I[99165,[],"ViewportBoundary"]
14:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","home",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["home",{"children":["__PAGE__",{}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["home",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","home","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$La",null,{"Component":"$b","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@c","$@d"]}],null,["$","$Le",null,{"children":"$Lf"}]]}],{},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","GYJHm61crn73UefHwIPLZ",{"children":[["$","$L10",null,{"children":"$L11"}],["$","$L12",null,{"children":"$L13"}],null]}]]}],false]],"m":"$undefined","G":["$14","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","home",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["home",{"children":["__PAGE__",{}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["home",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","home","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$La",null,{"Component":"$b","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@c","$@d"]}],null,["$","$Le",null,{"children":"$Lf"}]]}],{},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","U3UvBGQEqKu6QhYa39Aeu",{"children":[["$","$L10",null,{"children":"$L11"}],["$","$L12",null,{"children":"$L13"}],null]}]]}],false]],"m":"$undefined","G":["$14","$undefined"],"s":false,"S":true}
9:{}
c:{}
d:{}

File diff suppressed because one or more lines are too long

View File

@@ -13,8 +13,8 @@ d:I[69835,["5293","static/chunks/app/dashboard/settings/games/tetris/page-e289ae
12:I[99165,[],"MetadataBoundary"]
14:I[99165,[],"ViewportBoundary"]
16:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","settings","games","tetris",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["settings",{"children":["games",{"children":["tetris",{"children":["__PAGE__",{}]}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["games",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","settings","children","games","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["tetris",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","settings","children","games","children","tetris","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","H1PNDKs2SrYf3O9ZBQBcb",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","settings","games","tetris",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["settings",{"children":["games",{"children":["tetris",{"children":["__PAGE__",{}]}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["games",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","settings","children","games","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["tetris",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","settings","children","games","children","tetris","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","6vtC0dcYv-bf4zHwoY17i",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
9:{}
b:{}
e:{}

File diff suppressed because one or more lines are too long

View File

@@ -13,8 +13,8 @@ d:I[16212,["7780","static/chunks/7780-d44d1f6d676771d4.js","2162","static/chunks
12:I[99165,[],"MetadataBoundary"]
14:I[99165,[],"ViewportBoundary"]
16:I[25339,[],""]
:HL["/_next/static/css/562f52882551f4eb.css","style"]
0:{"P":null,"b":"Kt0Xe6YYT_RuYVm3o2asX","p":"","c":["","dashboard","settings","security",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["settings",{"children":["security",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/562f52882551f4eb.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["security",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","settings","children","security","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","OEnv4zQg6abQWeUBOn0ly",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
:HL["/_next/static/css/2adbd6ec1a3f6224.css","style"]
0:{"P":null,"b":"xeZlQ8jLyR2FPwewgDcLc","p":"","c":["","dashboard","settings","security",""],"i":false,"f":[[["",{"children":["dashboard",{"children":["settings",{"children":["security",{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2adbd6ec1a3f6224.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"antialiased __className_9dae3d","children":[["$","$L2",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L3",null,{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[],[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}],["$","$L6",null,{}]]}]}]]}],{"children":["dashboard",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":{},"promise":"$@9"}]]}],{"children":["settings",["$","$1","c",{"children":[null,["$","$L7",null,{"Component":"$a","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","settings","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promise":"$@b"}]]}],{"children":["security",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","dashboard","children","settings","children","security","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lc",null,{"Component":"$d","searchParams":{},"params":"$0:f:0:1:2:children:1:props:children:1:props:params","promises":["$@e","$@f"]}],null,["$","$L10",null,{"children":"$L11"}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","RQdZxJ6HUnmyI7JAynOFO",{"children":[["$","$L12",null,{"children":"$L13"}],["$","$L14",null,{"children":"$L15"}],null]}]]}],false]],"m":"$undefined","G":["$16","$undefined"],"s":false,"S":true}
9:{}
b:{}
e:{}

Some files were not shown because too many files have changed in this diff Show More