setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Fetch the last 30 records $stmt = $db->query("SELECT timestamp, PM1, PM25, PM10 FROM data_NPM ORDER BY timestamp DESC LIMIT 30"); $data = $stmt->fetchAll(PDO::FETCH_ASSOC); $reversedData = array_reverse($data); // Reverse the order echo json_encode($reversedData); } catch (PDOException $e) { echo json_encode(["error" => $e->getMessage()]); } } //GETING data from config_table (SQLite DB) if ($type == "get_config_sqlite") { try { $db = new PDO("sqlite:$database_path"); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Get all main configuration entries $config_query = $db->query("SELECT key, value, type FROM config_table"); $config_data = $config_query->fetchAll(PDO::FETCH_ASSOC); // Convert data types according to their 'type' field $result = []; foreach ($config_data as $item) { $key = $item['key']; $value = $item['value']; $type = $item['type']; // Convert value based on its type switch ($type) { case 'bool': $parsed_value = ($value == '1' || $value == 'true') ? true : false; break; case 'int': $parsed_value = intval($value); break; case 'float': $parsed_value = floatval($value); break; default: $parsed_value = $value; } $result[$key] = $parsed_value; } // Return JSON response header('Content-Type: application/json'); echo json_encode($result, JSON_PRETTY_PRINT); } catch (PDOException $e) { // Return error as JSON header('Content-Type: application/json'); echo json_encode(['error' => 'Database error: ' . $e->getMessage()]); } } //GETING data from config_scrips_table (SQLite DB) if ($type == "get_config_scripts_sqlite") { try { $db = new PDO("sqlite:$database_path"); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Get all main configuration entries $config_query = $db->query("SELECT * FROM config_scripts_table"); $config_data = $config_query->fetchAll(PDO::FETCH_ASSOC); // Convert data types according to their 'type' field $result = []; foreach ($config_data as $item) { $script_path = $item['script_path']; $enabled = $item['enabled']; // Convert the enabled field to a proper boolean $result[$script_path] = ($enabled == 1); } // Return JSON response header('Content-Type: application/json'); echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); } catch (PDOException $e) { // Return error as JSON header('Content-Type: application/json'); echo json_encode(['error' => 'Database error: ' . $e->getMessage()]); } } //UPDATING the config_table from SQLite DB if ($type == "update_config_sqlite") { $param = $_GET['param'] ?? null; $value = $_GET['value'] ?? null; if ($param === null || $value === null) { echo json_encode(["error" => "Missing parameter or value"]); exit; } try { $db = new PDO("sqlite:$database_path"); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // First, check if parameter exists and get its type $checkStmt = $db->prepare("SELECT type FROM config_table WHERE key = :param"); $checkStmt->bindParam(':param', $param); $checkStmt->execute(); $result = $checkStmt->fetch(PDO::FETCH_ASSOC); if ($result) { // Parameter exists, determine type and update $type = $result['type']; // Convert value according to type if needed $convertedValue = $value; if ($type == "bool") { // Convert various boolean representations to 0/1 $convertedValue = (filter_var($value, FILTER_VALIDATE_BOOLEAN)) ? "1" : "0"; } elseif ($type == "int") { $convertedValue = (string)intval($value); } elseif ($type == "float") { $convertedValue = (string)floatval($value); } // Update the value $updateStmt = $db->prepare("UPDATE config_table SET value = :value WHERE key = :param"); $updateStmt->bindParam(':value', $convertedValue); $updateStmt->bindParam(':param', $param); $updateStmt->execute(); echo json_encode([ "success" => true, "message" => "Configuration updated successfully", "param" => $param, "value" => $convertedValue, "type" => $type ]); } else { echo json_encode([ "error" => "Parameter not found in configuration", "param" => $param ]); } } catch (PDOException $e) { echo json_encode(["error" => $e->getMessage()]); } } //UPDATING the config_scripts table from SQLite DB if ($type == "update_config_scripts_sqlite") { $script_path = $_GET['param'] ?? null; $enabled = $_GET['value'] ?? null; if ($script_path === null || $enabled === null) { echo json_encode(["error" => "Missing parameter or value"]); exit; } try { $db = new PDO("sqlite:$database_path"); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // First, check if parameter exists and get its type $checkStmt = $db->prepare("SELECT enabled FROM config_scripts_table WHERE script_path = :script_path"); $checkStmt->bindParam(':script_path', $script_path); $checkStmt->execute(); $result = $checkStmt->fetch(PDO::FETCH_ASSOC); if ($result) { // Convert enabled value to 0 or 1 $enabledValue = (filter_var($enabled, FILTER_VALIDATE_BOOLEAN)) ? 1 : 0; // Update the enabled status $updateStmt = $db->prepare("UPDATE config_scripts_table SET enabled = :enabled WHERE script_path = :script_path"); $updateStmt->bindParam(':enabled', $enabledValue, PDO::PARAM_INT); $updateStmt->bindParam(':script_path', $script_path); $updateStmt->execute(); echo json_encode([ "success" => true, "message" => "Script configuration updated successfully", "script_path" => $script_path, "enabled" => (bool)$enabledValue ], JSON_UNESCAPED_SLASHES); // Prevent escaping forward slashes } else { echo json_encode([ "error" => "Script path not found in configuration", "script_path" => $script_path ], JSON_UNESCAPED_SLASHES); // Prevent escaping forward slashes } } catch (PDOException $e) { echo json_encode(["error" => $e->getMessage()]); } } //old JSON way if ($type == "update_config") { echo "updating...."; $param=$_GET['param']; $value=$_GET['value']; $configFile = '../config.json'; // Convert value to boolean, integer, or string if ($value === "true") { $value = true; // Convert "true" string to boolean true } elseif ($value === "false") { $value = false; // Convert "false" string to boolean false } elseif (is_numeric($value)) { $value = $value + 0; // Convert numeric strings to int or float } $configData = json_decode(file_get_contents($configFile), true); $configData[$param] = $value; file_put_contents($configFile, json_encode($configData, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); echo "Config updated!"; } if ($type == "getModem_busy") { $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/check_running.py'; $output = shell_exec($command); echo $output; } if ($type == "RTC_time") { $time = shell_exec("date '+%d/%m/%Y %H:%M:%S'"); echo $time; } if ($type == "sys_RTC_module_time") { $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/RTC/read.py'; $output = shell_exec($command); echo $output; } if ($type == "git_pull") { $command = 'sudo git pull'; $output = shell_exec($command); echo $output; } if ($type == "set_RTC_withNTP") { $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/RTC/set_with_NTP.py'; $output = shell_exec($command); echo $output; } if ($type == "set_RTC_withBrowser") { $time = $_GET['time']; // Validate time format if (!strtotime($time)) { echo json_encode(['success' => false, 'message' => 'Invalid time format']); exit; } // Convert to RTC-compatible format (e.g., 'YYYY-MM-DD HH:MM:SS') $rtc_time = date('Y-m-d H:i:s', strtotime($time)); // Execute Python script to update the RTC $command = escapeshellcmd("sudo /usr/bin/python3 /var/www/moduleair_pro_4g/RTC/set_with_browserTime.py '$rtc_time'"); $output = shell_exec($command); if ($output === null) { echo json_encode(['success' => false, 'message' => 'Failed to update RTC']); } else { echo json_encode(['success' => true, 'message' => 'RTC updated successfully']); } } if ($type == "clear_loopLogs") { $command = 'truncate -s 0 /var/www/moduleair_pro_4g/logs/loop.log'; $output = shell_exec($command); echo $output; } if ($type == "database_size") { // Path to the SQLite database file $databasePath = '/var/www/moduleair_pro_4g/sqlite/sensors.db'; // Check if the file exists if (file_exists($databasePath)) { try { // Connect to the SQLite database $db = new PDO("sqlite:$databasePath"); // Get the file size in bytes $fileSizeBytes = filesize($databasePath); // Convert the file size to human-readable formats $fileSizeKilobytes = $fileSizeBytes / 1024; // KB $fileSizeMegabytes = $fileSizeKilobytes / 1024; // MB // Prepare the JSON response $data = [ 'path' => $databasePath, 'size_bytes' => $fileSizeBytes, 'size_kilobytes' => round($fileSizeKilobytes, 2), 'size_megabytes' => round($fileSizeMegabytes, 2), ]; // Output the JSON response echo json_encode($data, JSON_PRETTY_PRINT); } catch (PDOException $e) { // Handle database connection errors echo json_encode([ 'error' => 'Database query failed: ' . $e->getMessage() ]); } } else { // Handle error if the file doesn't exist echo json_encode([ 'error' => 'Database file not found', 'path' => $databasePath ]); } } if ($type == "linux_disk") { $command = 'df -h /'; $output = shell_exec($command); echo $output; } if ($type == "linux_memory") { $command = 'free -h'; $output = shell_exec($command); echo $output; } if ($type == "sshTunnel") { $ssh_port=$_GET['ssh_port']; $command = 'sudo ssh -i /var/www/.ssh/id_rsa -f -N -R "'.$ssh_port.':localhost:22" -p 50221 -o StrictHostKeyChecking=no "airlab_server1@aircarto.fr"'; $output = shell_exec($command); echo $output; } if ($type == "reboot") { $command = 'sudo reboot'; $output = shell_exec($command); } if ($type == "npm") { $port=$_GET['port']; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/NPM/get_data.py ' . $port; $output = shell_exec($command); echo $output; } if ($type == "mhz19") { $command = '/usr/bin/python3 /var/www/moduleair_pro_4g/MH-Z19/get_data.py ttyAMA4'; $output = shell_exec($command); echo $output; } if ($type == "envea") { $port=$_GET['port']; $name=$_GET['name']; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/envea/read_value.py ' . $port; $output = shell_exec($command); echo $output; } if ($type == "noise") { $command = '/var/www/moduleair_pro_4g/sound_meter/sound_meter'; $output = shell_exec($command); echo $output; } if ($type == "BME280") { $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/BME280/read.py'; $output = shell_exec($command); echo $output; } if ($type == "table_mesure") { $table=$_GET['table']; $limit=$_GET['limit']; $download=$_GET['download']; if ($download==="false") { $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/sqlite/read.py '.$table.' '.$limit; $output = shell_exec($command); echo $output; } else{ $start_date=$_GET['start_date']; $end_date=$_GET['end_date']; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/sqlite/read_select_date.py '.$table.' '.$start_date.' '.$end_date; $output = shell_exec($command); echo $output; } } # SARA R4 COMMANDS if ($type == "sara") { $port=$_GET['port']; $sara_command=$_GET['command']; $sara_command = escapeshellcmd($sara_command); $timeout=$_GET['timeout']; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara.py ' . $port . ' ' . $sara_command . ' ' . $timeout; $output = shell_exec($command); echo $output; } # SARA R4 COMMANDS (MQTT) if ($type == "sara_getMQTT_config") { $port=$_GET['port']; $timeout=$_GET['timeout']; $command = '/usr/bin/python3 /var/www/moduleair_pro_4g/SARA/MQTT/get_config.py ' . $port . ' ' . $timeout; $output = shell_exec($command); echo $output; } # SARA R4 COMMANDS (MQTT) if ($type == "sara_getMQTT_login_logout") { $port=$_GET['port']; $timeout=$_GET['timeout']; $login_logout=$_GET['login_logout']; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/MQTT/login_logout.py ' . $port . ' ' . $login_logout . ' ' . $timeout; $output = shell_exec($command); echo $output; } # SARA R4 COMMANDS (MQTT -> publish) if ($type == "sara_MQTT_publish") { $port=$_GET['port']; $timeout=$_GET['timeout']; $message=$_GET['message']; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/MQTT/publish.py ' . $port . ' ' . $message . ' ' . $timeout; $output = shell_exec($command); echo $output; } #Connect to network if ($type == "sara_connectNetwork") { $port=$_GET['port']; $timeout=$_GET['timeout']; $networkID=$_GET['networkID']; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara_connectNetwork.py ' . $port . ' ' . $networkID . ' ' . $timeout; $output = shell_exec($command); echo $output; #save to config.json $configFile = '/var/www/moduleair_pro_4g/config.json'; // Read the JSON file $jsonData = file_get_contents($configFile); // Decode JSON data into an associative array $config = json_decode($jsonData, true); // Check if decoding was successful if ($config === null) { die("Error: Could not decode JSON file."); } // Update the value of SARA_R4_networkID $config['SARA_R4_neworkID'] = $networkID; // Replace 42 with the desired value // Encode the array back to JSON with pretty printing $newJsonData = json_encode($config, JSON_PRETTY_PRINT); // Check if encoding was successful if ($newJsonData === false) { die("Error: Could not encode JSON data."); } // Write the updated JSON back to the file if (file_put_contents($configFile, $newJsonData) === false) { die("Error: Could not write to JSON file."); } echo "SARA_R4_networkID updated successfully."; } #SET THE URL for messaging (profile id 2) if ($type == "sara_setURL") { $port=$_GET['port']; $url=$_GET['url']; $profile_id = 2; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara_setURL.py ' . $port . ' ' . $url . ' ' . $profile_id; $output = shell_exec($command); echo $output; } #SET APN if ($type == "sara_APN") { $port=$_GET['port']; $timeout=$_GET['timeout']; $APN_address=$_GET['APN_address']; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara_setAPN.py ' . $port . ' ' . $APN_address . ' ' . $timeout; $output = shell_exec($command); echo $output; } #TO WRITE MESSAGE TO MEMORY if ($type == "sara_writeMessage") { $port=$_GET['port']; $message=$_GET['message']; $message = escapeshellcmd($message); $type2=$_GET['type2']; if ($type2 === "write") { $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara_writeMessage.py ' . $port . ' ' . $message; $output = shell_exec($command); } if ($type2 === "read") { $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara_readMessage.py ' . $port . ' ' . $message; $output = shell_exec($command); } if ($type2 === "erase") { $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara_eraseMessage.py ' . $port . ' ' . $message; $output = shell_exec($command); } echo $output; } #Send the typed message to server (for ntfy notification) if ($type == "sara_sendMessage") { $port=$_GET['port']; $endpoint=$_GET['endpoint']; $endpoint = escapeshellcmd($endpoint); $profile_id = 2; $command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/SARA/sara_sendMessage.py ' . $port . ' ' . $endpoint. ' ' . $profile_id; $output = shell_exec($command); echo $output; } if ($type == "internet") { //eth0 $command = 'nmcli -g GENERAL.STATE device show eth0'; $eth0_connStatus = shell_exec($command); $eth0_connStatus = str_replace("\n", "", $eth0_connStatus); $command = 'nmcli -g IP4.ADDRESS device show eth0'; $eth0_IPAddr = shell_exec($command); $eth0_IPAddr = str_replace("\n", "", $eth0_IPAddr); //wlan0 $command = 'nmcli -g GENERAL.STATE device show wlan0'; $wlan0_connStatus = shell_exec($command); $wlan0_connStatus = str_replace("\n", "", $wlan0_connStatus); $command = 'nmcli -g IP4.ADDRESS device show wlan0'; $wlan0_IPAddr = shell_exec($command); $wlan0_IPAddr = str_replace("\n", "", $wlan0_IPAddr); $data= array( "ethernet" => array( "connection" => $eth0_connStatus, "IP" => $eth0_IPAddr ), "wifi" => array( "connection" => $wlan0_connStatus, "IP" => $wlan0_IPAddr ) ); $json_data = json_encode($data); echo $json_data; } # IMPORTANT # c'est ici que la connexion vers le WIFI du client s'effectue. if ($type == "wifi_connect") { $SSID=$_GET['SSID']; $PASS=$_GET['pass']; echo "will try to connect to
"; echo "SSID: " . $SSID; echo "
"; echo "Password: " . $PASS; echo "
"; echo "
"; echo "You will be disconnected. If connection is successfull you can find the device on your local network."; $script_path = '/var/www/moduleair_pro_4g/connexion.sh'; $log_file = '/var/www/moduleair_pro_4g/logs/app.log'; shell_exec("$script_path $SSID $PASS >> $log_file 2>&1 &"); #on passe ici en argument le nom du réseau WIFI et le Password #$output = shell_exec('sudo nmcli connection down Hotspot'); #$output2 = shell_exec('sudo nmcli device wifi connect "AirLab" password "123plouf"'); } if ($type == "wifi_scan") { // Set the path to your CSV file $csvFile = '/var/www/moduleair_pro_4g/wifi_list.csv'; // Initialize an array to hold the JSON data $jsonData = []; // Open the CSV file for reading if (($handle = fopen($csvFile, 'r')) !== false) { // Get the headers from the first row $headers = fgetcsv($handle); // Loop through the rest of the rows while (($row = fgetcsv($handle)) !== false) { // Combine headers with row data to create an associative array $jsonData[] = array_combine($headers, $row); } // Close the file handle fclose($handle); } // Set the content type to JSON header('Content-Type: application/json'); // Convert the array to JSON format and output it echo json_encode($jsonData, JSON_PRETTY_PRINT); } if ($type == "wifi_scan_old") { $output = shell_exec('nmcli device wifi list ifname wlan0'); // Split the output into lines $lines = explode("\n", trim($output)); // Initialize an array to hold the results $wifiNetworks = []; // Loop through each line and extract the relevant information foreach ($lines as $index => $line) { // Skip the header line if ($index === 0) { continue; } // Split the line by whitespace and filter empty values $columns = preg_split('/\s+/', $line); // If the line has enough columns, store the relevant data if (count($columns) >= 5) { $wifiNetworks[] = [ 'SSID' => $columns[2], // Network name 'BARS' => $columns[8], 'SIGNAL' => $columns[7], // Signal strength ]; } } $json_data = json_encode($wifiNetworks); echo $json_data; } /* ____ _ ____ _ __ __ _ / ___| _ _ ___| |_ ___ _ __ ___ | _ \ / ___| ___ _ ____ _(_) ___ ___| \/ | __ _ _ __ __ _ __ _ ___ _ __ ___ ___ _ __ | |_ \___ \| | | / __| __/ _ \ '_ ` _ \| | | | \___ \ / _ \ '__\ \ / / |/ __/ _ \ |\/| |/ _` | '_ \ / _` |/ _` |/ _ \ '_ ` _ \ / _ \ '_ \| __| ___) | |_| \__ \ || __/ | | | | | |_| | ___) | __/ | \ V /| | (_| __/ | | | (_| | | | | (_| | (_| | __/ | | | | | __/ | | | |_ |____/ \__, |___/\__\___|_| |_| |_|____/ |____/ \___|_| \_/ |_|\___\___|_| |_|\__,_|_| |_|\__,_|\__, |\___|_| |_| |_|\___|_| |_|\__| |___/ |___/ */ // Get systemd services status if ($type == "get_systemd_services") { try { // List of NebuleAir services to monitor with descriptions and frequencies $services = [ 'moduleair-npm-data.timer' => [ 'description' => 'Collects particulate matter data from NextPM sensor', 'frequency' => 'Every 10 seconds' ], 'moduleair-co2-data.timer' => [ 'description' => 'Reads environmental data from Envea sensors', 'frequency' => 'Every 10 seconds' ], 'moduleair-sara-data.timer' => [ 'description' => 'Transmits collected data via 4G cellular modem', 'frequency' => 'Every 60 seconds' ], 'moduleair-bme280-data.timer' => [ 'description' => 'Monitors temperature and humidity (BME280)', 'frequency' => 'Every 2 minutes' ], 'moduleair-db-cleanup-data.timer' => [ 'description' => 'Cleans up old data from database', 'frequency' => 'Daily' ] ]; $serviceStatus = []; foreach ($services as $service => $serviceInfo) { // Get service active status $activeCmd = "systemctl is-active " . escapeshellarg($service) . " 2>/dev/null"; $activeStatus = trim(shell_exec($activeCmd)); $isActive = ($activeStatus === 'active'); // Get service enabled status $enabledCmd = "systemctl is-enabled " . escapeshellarg($service) . " 2>/dev/null"; $enabledStatus = trim(shell_exec($enabledCmd)); $isEnabled = ($enabledStatus === 'enabled'); // Clean up service name for display $displayName = str_replace(['.timer', 'nebuleair-', '-data'], '', $service); $displayName = ucfirst(str_replace('-', ' ', $displayName)); $serviceStatus[] = [ 'name' => $service, 'display_name' => $displayName, 'description' => $serviceInfo['description'], 'frequency' => $serviceInfo['frequency'], 'active' => $isActive, 'enabled' => $isEnabled ]; } echo json_encode([ 'success' => true, 'services' => $serviceStatus ], JSON_PRETTY_PRINT); } catch (Exception $e) { echo json_encode([ 'success' => false, 'error' => $e->getMessage() ]); } } // Restart a systemd service if ($type == "restart_systemd_service") { $service = $_GET['service'] ?? null; if (empty($service)) { echo json_encode([ 'success' => false, 'error' => 'No service specified' ]); exit; } // Validate service name (security check) $allowedServices = [ 'moduleair-npm-data.timer', 'moduleair-sara-data.timer', 'nebuleair-bme280-data.timer', 'moduleair-co2-data.timer', 'moduleair-db-cleanup-data.timer' ]; if (!in_array($service, $allowedServices)) { echo json_encode([ 'success' => false, 'error' => 'Invalid service name' ]); exit; } try { // Restart the service $command = "sudo systemctl restart " . escapeshellarg($service) . " 2>&1"; $output = shell_exec($command); // Check if restart was successful $statusCmd = "systemctl is-active " . escapeshellarg($service) . " 2>/dev/null"; $status = trim(shell_exec($statusCmd)); if ($status === 'active' || empty($output)) { echo json_encode([ 'success' => true, 'message' => "Service $service restarted successfully" ]); } else { echo json_encode([ 'success' => false, 'error' => "Failed to restart service: $output" ]); } } catch (Exception $e) { echo json_encode([ 'success' => false, 'error' => $e->getMessage() ]); } } // Enable/disable a systemd service if ($type == "toggle_systemd_service") { $service = $_GET['service'] ?? null; $enable = $_GET['enable'] ?? null; if (empty($service) || $enable === null) { echo json_encode([ 'success' => false, 'error' => 'Missing service name or enable parameter' ]); exit; } // Validate service name (security check) $allowedServices = [ 'moduleair-npm-data.timer', 'moduleair-sara-data.timer', 'nebuleair-bme280-data.timer', 'moduleair-co2-data.timer', 'moduleair-db-cleanup-data.timer' ]; if (!in_array($service, $allowedServices)) { echo json_encode([ 'success' => false, 'error' => 'Invalid service name' ]); exit; } try { $enable = filter_var($enable, FILTER_VALIDATE_BOOLEAN); $action = $enable ? 'enable' : 'disable'; // Enable/disable the service $command = "sudo systemctl $action " . escapeshellarg($service) . " 2>&1"; $output = shell_exec($command); // If disabling, also stop the service if (!$enable) { $stopCommand = "sudo systemctl stop " . escapeshellarg($service) . " 2>&1"; $stopOutput = shell_exec($stopCommand); } // If enabling, also start the service if ($enable) { $startCommand = "sudo systemctl start " . escapeshellarg($service) . " 2>&1"; $startOutput = shell_exec($startCommand); } // Check if the operation was successful $statusCmd = "systemctl is-enabled " . escapeshellarg($service) . " 2>/dev/null"; $status = trim(shell_exec($statusCmd)); $expectedStatus = $enable ? 'enabled' : 'disabled'; if ($status === $expectedStatus) { echo json_encode([ 'success' => true, 'message' => "Service $service " . ($enable ? 'enabled and started' : 'disabled and stopped') . " successfully" ]); } else { echo json_encode([ 'success' => false, 'error' => "Failed to $action service: $output" ]); } } catch (Exception $e) { echo json_encode([ 'success' => false, 'error' => $e->getMessage() ]); } }