"; } echo "Router Monitor Started: " . date('Y-m-d H:i:s') . "\n"; use PEAR2\Net\RouterOS; use RouterOS\Exceptions\Socket\TimeoutException; use RouterOS\Exceptions\Socket\ConnectionException; class RouterMonitor { private $config; private $db; public function __construct() { global $config; $this->config = $config; } /** * Monitor all enabled routers */ public function monitorAllRouters() { $routers = ORM::for_table('tbl_routers')->where('enabled', '1')->find_many(); echo "Monitoring " . count($routers) . " routers...\n"; foreach ($routers as $router) { $this->monitorRouter($router); } echo "Router monitoring completed: " . date('Y-m-d H:i:s') . "\n"; } /** * Monitor individual router */ private function monitorRouter($router) { $routerId = $router['id']; $routerName = $router['name']; $ipAddress = $router['ip_address']; echo "Checking router: $routerName ($ipAddress)...\n"; // Check if router is in circuit breaker state if ($this->isCircuitBreakerActive($routerId)) { echo " - Circuit breaker active, skipping\n"; $this->updateRouterStatus($router, 'Offline', 'Circuit breaker active'); return; } // Perform comprehensive check $monitoringData = $this->performRouterCheck($router); // Update database with results $this->updateRouterData($router, $monitoringData); // Check for alerts $this->checkAlerts($router, $monitoringData); } /** * Perform comprehensive router check */ private function performRouterCheck($router) { $data = [ 'timestamp' => date('Y-m-d H:i:s'), 'ping_status' => false, 'api_status' => false, 'uptime' => null, 'free_memory' => null, 'total_memory' => null, 'cpu_load' => null, 'temperature' => null, 'voltage' => null, 'error' => null ]; // Step 1: Ping check $data['ping_status'] = $this->pingRouter($router['ip_address']); if (!$data['ping_status']) { $data['error'] = 'Ping failed'; return $data; } // Step 2: RouterOS API check try { $client = Mikrotik::getClient($router['ip_address'], $router['username'], $router['password'], 8); if (!$client) { $data['error'] = 'Failed to create RouterOS client'; return $data; } // Get system resource data $resourceRequest = new RouterOS\Request('/system resource print'); $resourceResponse = $client->sendSync($resourceRequest, 5); $resourceData = $resourceResponse->getAllOfType(RouterOS\Response::TYPE_DATA)[0]; // Get system health data $healthRequest = new RouterOS\Request('/system health print'); $healthResponse = $client->sendSync($healthRequest, 5); $healthData = $healthResponse->getAllOfType(RouterOS\Response::TYPE_DATA)[0]; // Extract data $data['api_status'] = true; $data['uptime'] = $resourceData->getProperty('uptime'); $data['free_memory'] = (int)$resourceData->getProperty('free-memory'); $data['total_memory'] = (int)$resourceData->getProperty('total-memory'); $data['cpu_load'] = (int)$resourceData->getProperty('cpu-load'); $data['temperature'] = $healthData->getProperty('temperature'); $data['voltage'] = $healthData->getProperty('voltage'); // Clear circuit breaker on successful connection $this->clearCircuitBreaker($router['id']); } catch (TimeoutException $e) { $data['error'] = 'API timeout'; $this->incrementCircuitBreaker($router['id']); } catch (ConnectionException $e) { $data['error'] = 'API connection failed'; $this->incrementCircuitBreaker($router['id']); } catch (Exception $e) { $data['error'] = 'API error: ' . $e->getMessage(); $this->incrementCircuitBreaker($router['id']); } return $data; } /** * Ping router */ private function pingRouter($ipAddress, $timeout = 5, $count = 3) { $ipParts = explode(':', $ipAddress); $ip = $ipParts[0]; $escapedIp = escapeshellarg($ip); exec("ping -c $count -W $timeout $escapedIp 2>&1", $output, $returnVar); return $returnVar === 0; } /** * Update router status in database */ private function updateRouterStatus($router, $status, $error = null) { $router->status = $status; $router->last_check = date('Y-m-d H:i:s'); if ($error) { $router->last_error = $error; } $router->save(); } /** * Update router data in database */ private function updateRouterData($router, $data) { // Update main router table $router->status = ($data['api_status'] && $data['ping_status']) ? 'Online' : 'Offline'; $router->last_check = $data['timestamp']; $router->last_error = $data['error']; $router->save(); // Store detailed monitoring data $this->storeMonitoringData($router['id'], $data); } /** * Store detailed monitoring data */ private function storeMonitoringData($routerId, $data) { // Create monitoring record $monitoring = ORM::for_table('tbl_router_monitoring')->create(); $monitoring->router_id = $routerId; $monitoring->timestamp = $data['timestamp']; $monitoring->ping_status = $data['ping_status'] ? 1 : 0; $monitoring->api_status = $data['api_status'] ? 1 : 0; $monitoring->uptime = $data['uptime']; $monitoring->free_memory = $data['free_memory']; $monitoring->total_memory = $data['total_memory']; $monitoring->cpu_load = $data['cpu_load']; $monitoring->temperature = $data['temperature']; $monitoring->voltage = $data['voltage']; $monitoring->error = $data['error']; $monitoring->save(); // Clean up old records (keep last 7 days) $cutoffDate = date('Y-m-d H:i:s', strtotime('-7 days')); ORM::for_table('tbl_router_monitoring') ->where('timestamp', '<', $cutoffDate) ->delete_many(); } /** * Check for alerts */ private function checkAlerts($router, $data) { $alerts = []; // CPU load alert if ($data['cpu_load'] && $data['cpu_load'] > 80) { $alerts[] = "High CPU load: {$data['cpu_load']}%"; } // Memory usage alert if ($data['free_memory'] && $data['total_memory']) { $memoryUsage = (($data['total_memory'] - $data['free_memory']) / $data['total_memory']) * 100; if ($memoryUsage > 90) { $alerts[] = "High memory usage: " . round($memoryUsage, 1) . "%"; } } // Temperature alert if ($data['temperature'] && $data['temperature'] > 60) { $alerts[] = "High temperature: {$data['temperature']}°C"; } // Send alerts if any if (!empty($alerts)) { $this->sendAlerts($router, $alerts); } } /** * Send alerts */ private function sendAlerts($router, $alerts) { $message = "Router {$router['name']} alerts:\n" . implode("\n", $alerts); // Send to admin users $users = ORM::for_table('tbl_users')->where('user_type', 'Admin')->find_many(); foreach ($users as $user) { $this->sendSMS($user['phone'], $message); $this->sendWhatsApp($user['phone'], $message); } } /** * Circuit breaker methods */ private function isCircuitBreakerActive($routerId) { if (!function_exists('apcu_fetch')) return false; $key = "router_failures_$routerId"; $timeKey = "router_failures_{$routerId}_time"; $failureCount = apcu_fetch($key) ?: 0; $lastFailure = apcu_fetch($timeKey) ?: 0; return $failureCount >= 3 && (time() - $lastFailure) < 300; // 5 minutes } private function incrementCircuitBreaker($routerId) { if (!function_exists('apcu_store')) return; $key = "router_failures_$routerId"; $timeKey = "router_failures_{$routerId}_time"; $failureCount = apcu_fetch($key) ?: 0; apcu_store($key, $failureCount + 1, 300); apcu_store($timeKey, time(), 300); } private function clearCircuitBreaker($routerId) { if (!function_exists('apcu_delete')) return; $key = "router_failures_$routerId"; $timeKey = "router_failures_{$routerId}_time"; apcu_delete($key); apcu_delete($timeKey); } /** * Send SMS */ private function sendSMS($phone, $message) { // Implementation depends on your SMS provider // This is a placeholder echo "SMS to $phone: $message\n"; } /** * Send WhatsApp */ private function sendWhatsApp($phone, $message) { // Implementation depends on your WhatsApp provider // This is a placeholder echo "WhatsApp to $phone: $message\n"; } } // Run the monitor $monitor = new RouterMonitor(); $monitor->monitorAllRouters(); ?>