QuecManger 1.0.0

Release Notes:

Enhanced Web App Architecture:

- Optimized the structure for better scalability and maintainability.

- Refined Data Fetching Logic:
Improved the efficiency and reliability of data retrieval processes.

- Optimized AT Terminal: Enhanced functionality for smoother interaction with AT commands.

- Revamped UI/UX Design: Streamlined user interface and experience for improved accessibility and usability.

New Features:

- MTU Settings: Added customizable Maximum Transmission Unit (MTU) settings.

- APN and IMEI Profiles: Introduced the ability to configure APN and IMEI profiles for better device management.

- Persistent Cell Locking: Added native support for persistent cell locking, ensuring consistent network connections.

- QuecWatch: Connection monitoring with auto reconnect and reboot settable

Co-Authored-By: Russel Yasol <73575327+dr-dolomite@users.noreply.github.com>
This commit is contained in:
Cameron Thompson
2024-12-11 23:11:41 -05:00
parent 46f8e1af8b
commit bb4d75f560
271 changed files with 1791 additions and 108040 deletions

View File

@@ -0,0 +1,66 @@
#!/bin/sh
echo "Content-type: application/json"
echo ""
# Initialize error flag
has_error=false
error_message=""
# Function to append to error message
append_error() {
if [ -z "$error_message" ]; then
error_message="$1"
else
error_message="$error_message; $1"
fi
has_error=true
}
# Remove the entire quecmanager directory
if [ -d "/etc/quecmanager/apn_profile/" ]; then
rm -rf /etc/quecmanager/apn_profile/
if [ $? -ne 0 ]; then
append_error "Failed to remove quecmanager directory"
fi
else
append_error "quecmanager directory not found"
fi
# Remove the line from rc.local
if [ -f "/etc/rc.local" ]; then
# Create a temporary file
temp_file=$(mktemp)
# Remove the apnProfiles.sh line and copy to temp file
sed '/\/etc\/quecmanager\/apnProfiles.sh/d' /etc/rc.local > "$temp_file"
# Check if sed command was successful
if [ $? -eq 0 ]; then
# Replace original file with modified version
mv "$temp_file" /etc/rc.local
if [ $? -ne 0 ]; then
append_error "Failed to update rc.local"
fi
else
append_error "Failed to modify rc.local"
rm -f "$temp_file"
fi
else
append_error "rc.local file not found"
fi
# Remove temporary files that might have been created
rm -f /tmp/apn_result.txt
rm -f /tmp/debug.log
rm -f /tmp/inputICCID.txt
rm -f /tmp/outputICCID.txt
rm -f /tmp/inputAPN.txt
rm -f /tmp/outputAPN.txt
# Return appropriate JSON response
if [ "$has_error" = true ]; then
echo "{\"status\": \"error\", \"message\": \"$error_message\"}"
else
echo "{\"status\": \"success\", \"message\": \"APN profiles and configuration successfully removed\"}"
fi

View File

@@ -0,0 +1,45 @@
#!/bin/sh
echo "Content-type: application/json"
echo ""
CONFIG_FILE="/etc/quecmanager/apn_profile/apn_config.txt"
if [ ! -f "$CONFIG_FILE" ]; then
echo "{}"
exit 0
fi
# Read the configuration file
iccidProfile1=$(grep "^iccidProfile1=" "$CONFIG_FILE" | cut -d'=' -f2)
apnProfile1=$(grep "^apnProfile1=" "$CONFIG_FILE" | cut -d'=' -f2)
pdpType1=$(grep "^pdpType1=" "$CONFIG_FILE" | cut -d'=' -f2)
iccidProfile2=$(grep "^iccidProfile2=" "$CONFIG_FILE" | cut -d'=' -f2)
apnProfile2=$(grep "^apnProfile2=" "$CONFIG_FILE" | cut -d'=' -f2)
pdpType2=$(grep "^pdpType2=" "$CONFIG_FILE" | cut -d'=' -f2)
# Build the JSON response
echo "{"
# Add Profile 1 if it exists
if [ -n "$iccidProfile1" ]; then
echo " \"profile1\": {"
echo " \"iccid\": \"$iccidProfile1\","
echo " \"apn\": \"$apnProfile1\","
echo " \"pdpType\": \"$pdpType1\""
echo " }"
# Add comma if Profile 2 exists
[ -n "$iccidProfile2" ] && echo " ,"
fi
# Add Profile 2 if it exists
if [ -n "$iccidProfile2" ]; then
echo " \"profile2\": {"
echo " \"iccid\": \"$iccidProfile2\","
echo " \"apn\": \"$apnProfile2\","
echo " \"pdpType\": \"$pdpType2\""
echo " }"
fi
echo "}"

View File

@@ -33,11 +33,12 @@ if [ -z "$iccidProfile1" ] || [ -z "$apnProfile1" ] || [ -z "$pdpType1" ]; then
exit 1
fi
# Create the directory structure
mkdir -p /etc/quecmanager
if [ ! -d /etc/quecmanager/apn_profile ]; then
mkdir -p /etc/quecmanager/apn_profile
fi
# Create a configuration file to store APN profiles (as plain text)
cat > /etc/quecmanager/apn_config.txt << EOF
cat > /etc/quecmanager/apn_profile/apn_config.txt << EOF
iccidProfile1=$iccidProfile1
apnProfile1=$apnProfile1
pdpType1=$pdpType1
@@ -45,7 +46,7 @@ EOF
# Add second profile only if ICCID is provided
if [ -n "$iccidProfile2" ]; then
cat >> /etc/quecmanager/apn_config.txt << EOF
cat >> /etc/quecmanager/apn_profile/apn_config.txt << EOF
iccidProfile2=$iccidProfile2
apnProfile2=$apnProfile2
pdpType2=$pdpType2
@@ -53,13 +54,13 @@ EOF
fi
# Create the apnProfiles.sh script
cat > /etc/quecmanager/apnProfiles.sh << 'EOF'
cat > /etc/quecmanager/apn_profile/apnProfiles.sh << 'EOF'
#!/bin/sh
# Function to read config values
get_config_value() {
local key=$1
grep "^${key}=" /etc/quecmanager/apn_config.txt | cut -d'=' -f2
grep "^${key}=" /etc/quecmanager/apn_profile/apn_config.txt | cut -d'=' -f2
}
# Read configuration
@@ -70,13 +71,48 @@ iccidProfile2=$(get_config_value "iccidProfile2")
apnProfile2=$(get_config_value "apnProfile2")
pdpType2=$(get_config_value "pdpType2")
# Debug logging
DEBUG_LOG="/tmp/debug.log"
echo "Starting script at $(date)" > "$DEBUG_LOG"
CONFIG_FILE="/etc/quecManager.conf"
# Check config file
if [ ! -f "$CONFIG_FILE" ]; then
echo "Config file not found: $CONFIG_FILE" >> "$DEBUG_LOG"
echo '{"error": "Config file not found"}'
exit 1
fi
# Get AT_PORT with debug logging
AT_PORT=$(head -n 1 "$CONFIG_FILE" | cut -d'=' -f2 | tr -d ' \n\r' | sed 's|^dev/||')
echo "Raw config line: $(head -n 1 "$CONFIG_FILE")" >> "$DEBUG_LOG"
echo "Extracted AT_PORT: '$AT_PORT'" >> "$DEBUG_LOG"
# List available devices for debugging
ls -l /dev/smd* >> "$DEBUG_LOG" 2>&1
if [ -z "$AT_PORT" ]; then
echo "AT_PORT is empty" >> "$DEBUG_LOG"
echo '{"error": "Failed to read AT_PORT from config"}'
exit 1
fi
# Check if AT_PORT exists
if [ ! -c "/dev/$AT_PORT" ]; then
echo "AT_PORT device not found: /dev/$AT_PORT" >> "$DEBUG_LOG"
echo "Available smd devices:" >> "$DEBUG_LOG"
ls -l /dev/smd* >> "$DEBUG_LOG" 2>&1
echo '{"error": "AT_PORT device not found"}'
exit 1
fi
# Function to get current ICCID
get_current_iccid() {
local input_file="/tmp/inputICCID.txt"
local output_file="/tmp/outputICCID.txt"
echo "AT+ICCID" > "$input_file"
atinout "$input_file" /dev/smd11 "$output_file"
atinout "$input_file" "/dev/$AT_PORT" "$output_file"
iccid=$(cat "$output_file" | grep "+ICCID:" | cut -d' ' -f2)
@@ -92,7 +128,7 @@ set_apn() {
local output_file="/tmp/outputAPN.txt"
echo "AT+CGDCONT=1,\"$pdp_type\",\"$apn\";+COPS=2;+COPS=0" > "$input_file"
atinout "$input_file" /dev/smd11 "$output_file"
atinout "$input_file" "/dev/$AT_PORT" "$output_file"
local result=$(cat "$output_file")
rm -f "$input_file" "$output_file"
@@ -128,15 +164,15 @@ fi
EOF
# Make the script executable
chmod +x /etc/quecmanager/apnProfiles.sh
chmod +x /etc/quecmanager/apn_profile/apnProfiles.sh
# Add to rc.local if not already present
if ! grep -q "/etc/quecmanager/apnProfiles.sh" /etc/rc.local; then
sed -i '/^exit 0/i /etc/quecmanager/apnProfiles.sh' /etc/rc.local
if ! grep -q "/etc/quecmanager/apn_profile/apnProfiles.sh" /etc/rc.local; then
sed -i '/^exit 0/i /etc/quecmanager/apn_profile/apnProfiles.sh' /etc/rc.local
fi
# Run the script immediately
/etc/quecmanager/apnProfiles.sh
/etc/quecmanager/apn_profile/apnProfiles.sh
# Check the result
if [ -f /tmp/apn_result.txt ]; then

View File

@@ -1,66 +0,0 @@
#!/bin/sh
# Set content-type for JSON response
echo "Content-type: application/json"
echo ""
# Define the lock file
LOCK_FILE="/tmp/home_data.lock"
# Acquire the lock (wait if needed)
exec 200>$LOCK_FILE
flock -x 200
# Temporary files for input/output and AT port
INPUT_FILE="/tmp/input_$$.txt"
OUTPUT_FILE="/tmp/output_$$.txt"
AT_PORT="/dev/smd11"
# Debug file path
DEBUG_FILE="/tmp/debug-json-result.txt"
# Function to escape JSON strings (handling quotes and newlines)
escape_json() {
# Escape newlines and double quotes
echo "$1" | sed ':a;N;$!ba;s/\n/\\n/g; s/"/\\"/g'
}
# Initialize JSON response array
JSON_RESPONSE="["
# List of AT commands to run, one by one
for COMMAND in 'AT+CGDCONT?' 'AT+QNWPREFCFG="mode_pref"' 'AT+QNWPREFCFG="nr5g_disable_mode"' 'AT+QUIMSLOT?'; do
# Write the command to the input file
echo "$COMMAND" > "$INPUT_FILE"
# Run the command using atinout
atinout "$INPUT_FILE" "$AT_PORT" "$OUTPUT_FILE"
# Read the output from the output file
OUTPUT=$(cat "$OUTPUT_FILE")
# Escape special characters for JSON (escape only output)
ESCAPED_OUTPUT=$(escape_json "$OUTPUT")
# Append the response as an object to the JSON response array
JSON_RESPONSE="${JSON_RESPONSE}{\"response\":\"$ESCAPED_OUTPUT\"},"
done
# Remove the trailing comma and close the JSON array
if [ "${JSON_RESPONSE: -1}" = "," ]; then
JSON_RESPONSE="${JSON_RESPONSE%,}]"
else
JSON_RESPONSE="${JSON_RESPONSE}]"
fi
# Write the JSON response to the debug file for troubleshooting
echo "$JSON_RESPONSE" > "$DEBUG_FILE"
# Return the output as a valid JSON response
echo "$JSON_RESPONSE"
# Clean up temporary files
rm "$INPUT_FILE" "$OUTPUT_FILE"
# Release the lock
flock -u 200

View File

@@ -1,45 +0,0 @@
#!/bin/sh
echo "Content-type: application/json"
echo ""
CONFIG_FILE="/etc/quecmanager/apn_config.txt"
if [ ! -f "$CONFIG_FILE" ]; then
echo '{"status": "error", "message": "No APN profiles found", "profiles": {}}'
exit 0
fi
# Function to read config values
get_config_value() {
local key=$1
local value=$(grep "^${key}=" "$CONFIG_FILE" | cut -d'=' -f2)
echo "$value"
}
# Read all profile values
iccidProfile1=$(get_config_value "iccidProfile1")
apnProfile1=$(get_config_value "apnProfile1")
pdpType1=$(get_config_value "pdpType1")
iccidProfile2=$(get_config_value "iccidProfile2")
apnProfile2=$(get_config_value "apnProfile2")
pdpType2=$(get_config_value "pdpType2")
# Construct JSON response
cat << EOF
{
"status": "success",
"profiles": {
"profile1": {
"iccid": "${iccidProfile1:-}",
"apn": "${apnProfile1:-}",
"pdpType": "${pdpType1:-}"
},
"profile2": {
"iccid": "${iccidProfile2:-}",
"apn": "${apnProfile2:-}",
"pdpType": "${pdpType2:-}"
}
}
}
EOF

View File

@@ -0,0 +1,66 @@
#!/bin/sh
echo "Content-type: application/json"
echo ""
# Initialize error flag
has_error=false
error_message=""
# Function to append to error message
append_error() {
if [ -z "$error_message" ]; then
error_message="$1"
else
error_message="$error_message; $1"
fi
has_error=true
}
# Remove the entire quecmanager directory
if [ -d "/etc/quecmanager/imei_profile/" ]; then
rm -rf /etc/quecmanager/imei_profile/
if [ $? -ne 0 ]; then
append_error "Failed to remove quecmanager directory"
fi
else
append_error "quecmanager directory not found"
fi
# Remove the line from rc.local
if [ -f "/etc/rc.local" ]; then
# Create a temporary file
temp_file=$(mktemp)
# Remove the imeiProfiles.sh line and copy to temp file
sed '/\/etc\/quecmanager\/imeiProfiles.sh/d' /etc/rc.local > "$temp_file"
# Check if sed command was successful
if [ $? -eq 0 ]; then
# Replace original file with modified version
mv "$temp_file" /etc/rc.local
if [ $? -ne 0 ]; then
append_error "Failed to update rc.local"
fi
else
append_error "Failed to modify rc.local"
rm -f "$temp_file"
fi
else
append_error "rc.local file not found"
fi
# Remove temporary files that might have been created
rm -f /tmp/imei_result.txt
rm -f /tmp/debug.log
rm -f /tmp/inputICCID.txt
rm -f /tmp/outputICCID.txt
rm -f /tmp/inputIMEI.txt
rm -f /tmp/outputIMEI.txt
# Return appropriate JSON response
if [ "$has_error" = true ]; then
echo "{\"status\": \"error\", \"message\": \"$error_message\"}"
else
echo "{\"status\": \"success\", \"message\": \"IMEI profiles and configuration successfully removed\"}"
fi

View File

@@ -0,0 +1,39 @@
#!/bin/sh
echo "Content-type: application/json"
echo ""
CONFIG_FILE="/etc/quecmanager/imei_profile/imei_config.txt"
if [ ! -f "$CONFIG_FILE" ]; then
echo "{}"
exit 0
fi
# Read the configuration file
iccidProfile1=$(grep "^iccidProfile1=" "$CONFIG_FILE" | cut -d'=' -f2)
imeiProfile1=$(grep "^imeiProfile1=" "$CONFIG_FILE" | cut -d'=' -f2)
iccidProfile2=$(grep "^iccidProfile2=" "$CONFIG_FILE" | cut -d'=' -f2)
imeiProfile2=$(grep "^imeiProfile2=" "$CONFIG_FILE" | cut -d'=' -f2)
# Build the JSON response
echo "{"
# Add Profile 1 if it exists
if [ -n "$iccidProfile1" ]; then
echo " \"profile1\": {"
echo " \"iccid\": \"$iccidProfile1\","
echo " \"imei\": \"$imeiProfile1\""
echo " }"
# Add comma if Profile 2 exists
[ -n "$iccidProfile2" ] && echo " ,"
fi
# Add Profile 2 if it exists
if [ -n "$iccidProfile2" ]; then
echo " \"profile2\": {"
echo " \"iccid\": \"$iccidProfile2\","
echo " \"imei\": \"$imeiProfile2\""
echo " }"
fi
echo "}"

View File

@@ -0,0 +1,209 @@
#!/bin/sh
# Parse POST data
read -r QUERY_STRING
# Function to urldecode
urldecode() {
echo -e "$(echo "$1" | sed 's/+/ /g;s/%\([0-9A-F][0-9A-F]\)/\\x\1/g')"
}
# Extract values from POST data
iccidProfile1=$(echo "$QUERY_STRING" | grep -o 'iccidProfile1=[^&]*' | cut -d= -f2)
imeiProfile1=$(echo "$QUERY_STRING" | grep -o 'imeiProfile1=[^&]*' | cut -d= -f2)
iccidProfile2=$(echo "$QUERY_STRING" | grep -o 'iccidProfile2=[^&]*' | cut -d= -f2)
imeiProfile2=$(echo "$QUERY_STRING" | grep -o 'imeiProfile2=[^&]*' | cut -d= -f2)
# 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
# Check the directory if it exists, if not create it
if [ ! -d /etc/quecmanager/imei_profile ]; then
mkdir -p /etc/quecmanager/imei_profile
fi
# Create a configuration file to store IMEI profiles
cat >/etc/quecmanager/imei_profile/imei_config.txt <<EOF
iccidProfile1=$iccidProfile1
imeiProfile1=$imeiProfile1
EOF
# Add second profile only if ICCID is provided
if [ -n "$iccidProfile2" ]; then
cat >>/etc/quecmanager/imei_profile/imei_config.txt <<EOF
iccidProfile2=$iccidProfile2
imeiProfile2=$imeiProfile2
EOF
fi
# Create the imeiProfiles.sh script
cat >/etc/quecmanager/imei_profile/imeiProfiles.sh <<'EOF'
#!/bin/sh
# Function to read config values
get_config_value() {
local key=$1
grep "^${key}=" /etc/quecmanager/imei_profile/imei_config.txt | cut -d'=' -f2
}
# Read configuration
iccidProfile1=$(get_config_value "iccidProfile1")
imeiProfile1=$(get_config_value "imeiProfile1")
iccidProfile2=$(get_config_value "iccidProfile2")
imeiProfile2=$(get_config_value "imeiProfile2")
# Debug logging
DEBUG_LOG="/tmp/debug.log"
echo "Starting IMEI profile script at $(date)" > "$DEBUG_LOG"
CONFIG_FILE="/etc/quecManager.conf"
# Check config file
if [ ! -f "$CONFIG_FILE" ]; then
echo "Config file not found: $CONFIG_FILE" >> "$DEBUG_LOG"
echo '{"error": "Config file not found"}'
exit 1
fi
# Get AT_PORT with debug logging
AT_PORT=$(head -n 1 "$CONFIG_FILE" | cut -d'=' -f2 | tr -d ' \n\r' | sed 's|^dev/||')
echo "Raw config line: $(head -n 1 "$CONFIG_FILE")" >> "$DEBUG_LOG"
echo "Extracted AT_PORT: '$AT_PORT'" >> "$DEBUG_LOG"
if [ -z "$AT_PORT" ]; then
echo "AT_PORT is empty" >> "$DEBUG_LOG"
echo '{"error": "Failed to read AT_PORT from config"}'
exit 1
fi
# Check if AT_PORT exists
if [ ! -c "/dev/$AT_PORT" ]; then
echo "AT_PORT device not found: /dev/$AT_PORT" >> "$DEBUG_LOG"
echo '{"error": "AT_PORT device not found"}'
exit 1
fi
# Function to get current ICCID
get_current_iccid() {
local input_file="/tmp/inputICCID.txt"
local output_file="/tmp/outputICCID.txt"
echo "AT+ICCID" > "$input_file"
atinout "$input_file" "/dev/$AT_PORT" "$output_file"
iccid=$(cat "$output_file" | grep "+ICCID:" | cut -d' ' -f2)
rm -f "$input_file" "$output_file"
echo "$iccid"
}
# Function to get current IMEI
get_current_imei() {
local input_file="/tmp/inputCGSN.txt"
local output_file="/tmp/outputCGSN.txt"
echo "AT+CGSN" > "$input_file"
atinout "$input_file" "/dev/$AT_PORT" "$output_file"
# Extract IMEI from the response, removing any whitespace or newlines
imei=$(cat "$output_file" | grep -v "AT+CGSN" | grep -v "OK" | tr -d '\r\n[:space:]')
rm -f "$input_file" "$output_file"
echo "$imei"
}
# Function to set IMEI
set_imei() {
local imei="$1"
local input_file="/tmp/inputIMEI.txt"
local output_file="/tmp/outputIMEI.txt"
echo "AT+EGMR=1,7,\"$imei\";+QPOWD=1" > "$input_file"
atinout "$input_file" "/dev/$AT_PORT" "$output_file"
local result=$(cat "$output_file")
rm -f "$input_file" "$output_file"
if echo "$result" | grep -q "OK"; then
return 0
else
return 1
fi
}
# Get current ICCID and IMEI
current_iccid=$(get_current_iccid)
current_imei=$(get_current_imei)
success=false
echo "Current ICCID: $current_iccid" >> "$DEBUG_LOG"
echo "Current IMEI: $current_imei" >> "$DEBUG_LOG"
echo "Profile 1 - ICCID: $iccidProfile1, IMEI: $imeiProfile1" >> "$DEBUG_LOG"
echo "Profile 2 - ICCID: $iccidProfile2, IMEI: $imeiProfile2" >> "$DEBUG_LOG"
# Check ICCID against profile 1 (required)
if [ "$current_iccid" = "$iccidProfile1" ]; then
if [ "$current_imei" != "$imeiProfile1" ]; then
echo "ICCID matches profile 1, but IMEI needs updating" >> "$DEBUG_LOG"
if set_imei "$imeiProfile1"; then
success=true
fi
else
echo "ICCID and IMEI already match profile 1, no action needed" >> "$DEBUG_LOG"
success=true
fi
# Check ICCID against profile 2 (optional)
elif [ -n "$iccidProfile2" ] && [ "$current_iccid" = "$iccidProfile2" ]; then
if [ "$current_imei" != "$imeiProfile2" ]; then
echo "ICCID matches profile 2, but IMEI needs updating" >> "$DEBUG_LOG"
if set_imei "$imeiProfile2"; then
success=true
fi
else
echo "ICCID and IMEI already match profile 2, no action needed" >> "$DEBUG_LOG"
success=true
fi
fi
if [ "$success" = "true" ]; then
echo "IMEI check/update completed successfully" > /tmp/imei_result.txt
else
echo "Failed to check/update IMEI" > /tmp/imei_result.txt
fi
EOF
# Make the script executable
chmod +x /etc/quecmanager/imei_profile/imeiProfiles.sh
# Add to rc.local if not already present
if ! grep -q "/etc/quecmanager/imei_profile/imeiProfiles.sh" /etc/rc.local; then
sed -i '/^exit 0/i /etc/quecmanager/imei_profile/imeiProfiles.sh' /etc/rc.local
fi
# Run the script immediately
/etc/quecmanager/imei_profile/imeiProfiles.sh
# Check the result
if [ -f /tmp/imei_result.txt ]; then
result=$(cat /tmp/imei_result.txt)
rm -f /tmp/imei_result.txt
if [ "$result" = "IMEI set successfully" ]; then
echo '{"status": "success", "message": "IMEI profiles saved and applied successfully"}'
else
echo '{"status": "error", "message": "IMEI profiles saved but failed to apply"}'
fi
else
echo '{"status": "error", "message": "Something went wrong while processing IMEI profiles"}'
fi