M7350 Device Status Monitor
✓ Auto-running status check on page load...
'authenticator', 'action' => 0]);
$ch = curl_init("http://{$host}/cgi-bin/auth_cgi");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $nonceData,
CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded; charset=UTF-8'],
CURLOPT_TIMEOUT => 10,
]);
$response = curl_exec($ch);
if (curl_errno($ch)) {
throw new Exception("Connection failed: " . curl_error($ch));
}
curl_close($ch);
$nonceResult = json_decode($response, true);
if (!$nonceResult || !isset($nonceResult['nonce'])) {
throw new Exception("Failed to get nonce from router.");
}
$nonce = $nonceResult['nonce'];
$n_out = htmlspecialchars($nonce);
// Step 2: Calculate digest and get token
$digest = md5($password . ':' . $nonce);
$loginData = json_encode([
'module' => 'authenticator',
'action' => 1,
'digest' => $digest
]);
$ch = curl_init("http://{$host}/cgi-bin/auth_cgi");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $loginData,
CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded; charset=UTF-8'],
CURLOPT_TIMEOUT => 10,
]);
$response = curl_exec($ch);
if (curl_errno($ch)) {
throw new Exception("Login failed: " . curl_error($ch));
}
curl_close($ch);
$loginResult = json_decode($response, true);
if (!$loginResult || !isset($loginResult['token'])) {
throw new Exception("Login Failed - check password.txt content.");
}
$token = $loginResult['token'];
$t_out = htmlspecialchars($token);
// Step 3: Fetch device status
$status = "Fetching device status...";
$deviceData = json_encode([
'token' => $token,
'module' => 'status',
'action' => 0
]);
$ch = curl_init("http://{$host}/cgi-bin/web_cgi");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $deviceData,
CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded; charset=UTF-8'],
CURLOPT_TIMEOUT => 10,
]);
$rawData = curl_exec($ch);
if (curl_errno($ch)) {
throw new Exception("Failed to fetch status: " . curl_error($ch));
}
curl_close($ch);
// Parse the raw data
$debugHtml = '
Raw response: ' . htmlspecialchars($rawData) . '
';
// Clean and parse the data (same logic as JS version)
$cleanedData = preg_replace('/["{}]/', '', $rawData); // Remove quotes and braces
$cleanedData = str_replace("\t", ' ', $cleanedData); // Replace tabs with spaces
$lines = explode(',', $cleanedData); // Split by commas
$data = [];
foreach ($lines as $line) {
$parts = explode(':', $line, 2);
if (count($parts) >= 2) {
$key = trim($parts[0]);
$value = trim($parts[1]);
$data[$key] = $value;
}
}
if (!empty($data)) {
$model = $data['model'] ?? "Unknown";
$ip = $data['ipv4'] ?? "N/A";
$battery = $data['voltage'] ?? "0";
$sdStatus = isset($data['status']) && $data['status'] == "1" ? "Ready" : "Empty/Not Found";
$totalKB = isset($data['volume']) ? (float)$data['volume'] : 0;
$usedKB = isset($data['used']) ? (float)$data['used'] : 0;
$leftKB = isset($data['left']) ? (float)$data['left'] : 0;
$totalGB = $totalKB / 1048576;
$usedGB = $usedKB / 1048576;
$freeGB = $leftKB / 1048576;
$usedPercentage = $totalGB > 0 ? ($usedGB / $totalGB) * 100 : 0;
$statusHtml = '
IP Address:
' . htmlspecialchars($ip) . '
Battery:
' . htmlspecialchars($battery) . '%
';
if ($totalGB > 0) {
$statusHtml .= '
SD Card Status:
' . htmlspecialchars($sdStatus) . '
Total Size:
' . number_format($totalGB, 2) . ' GB
Used Space:
' . number_format($usedGB, 2) . ' GB (' . number_format($usedPercentage, 1) . '%)
Free Space:
' . number_format($freeGB, 2) . ' GB
';
} else {
$statusHtml .= '
SD Card:
Not Found or Unmounted
';
}
$statusHtml .= '
';
$output = $statusHtml . $debugHtml . '
Done.
';
$status = "✓ Status fetched successfully";
} else {
$status = "No status data received or parsing failed";
$output = $debugHtml;
}
} catch (Exception $e) {
$status = "Error: " . $e->getMessage();
$output = '
' . htmlspecialchars($e->getMessage()) . '
';
}
?>
Reading credentials from password.txt...
Nonce: |
Token: