From 40c986534ba621a9e01a5b98d4cb563f439fc3f9 Mon Sep 17 00:00:00 2001 From: Luca Haid Date: Tue, 9 Dec 2025 08:21:12 +0100 Subject: [PATCH] fixed speedtest action --- application/Radius/RadiusController.php | 75 +++++++++- public/js/pages/Radius/RadiusRouterManager.js | 131 ++++-------------- 2 files changed, 94 insertions(+), 112 deletions(-) diff --git a/application/Radius/RadiusController.php b/application/Radius/RadiusController.php index 1027fd221..09ac74297 100644 --- a/application/Radius/RadiusController.php +++ b/application/Radius/RadiusController.php @@ -54,18 +54,21 @@ class RadiusController extends mfBaseController { if (!$deviceId) self::sendError("Device ID is required"); $acs = $this->getGenieACS(); - + + // Set speedtest parameters on the device $acs->setParameterValues($deviceId, [ 'InternetGatewayDevice.X_AVM-DE_SpeedtestServer.UDP.Start' => 1, 'InternetGatewayDevice.X_AVM-DE_SpeedtestServer.UDP.StartBidirect' => 1, 'InternetGatewayDevice.X_AVM-DE_SpeedtestServer.UDP.WANAccess' => true ]); + // Get device and extract IP $device = $acs->getDevice($deviceId); $ip = GenieACS::getExternalIP($device); if (!$ip) self::sendError("Could not determine device IP"); + // Trigger speedtest via external API $url = "http://acs.xinon.at:5000/run-speedtest"; $apiKey = "2H9zWrgxPEJL9MZ1yTGtWh16cPCu0AsQ"; $data = json_encode(['ip' => $ip]); @@ -85,9 +88,7 @@ class RadiusController extends mfBaseController { if ($response === false) self::sendError("Failed to connect to speedtest server"); - header("Content-Type: application/json"); - echo $response; - die(); + self::returnJson(['success' => true, 'message' => 'Speedtest started']); } catch (Exception $e) { $this->log->debug("Speedtest Error", ['error' => $e->getMessage()]); self::sendError("Error running speedtest: " . $e->getMessage()); @@ -103,15 +104,77 @@ class RadiusController extends mfBaseController { if (!$deviceId) self::sendError("Device ID is required"); $acs = $this->getGenieACS(); - $value = $acs->getSpeedtestResult($deviceId); - self::returnJson(['success' => true, 'value' => $value]); + // Request parameter refresh + $acs->getParameterValues($deviceId, ['InternetGatewayDevice.X_AVM-DE_SpeedtestServer.UDP.Result']); + + // Get device info with full data + $device = $acs->getDevice($deviceId); + + if (!$device) self::sendError("Device not found"); + + // Extract speedtest result parameter + $paramName = 'InternetGatewayDevice.X_AVM-DE_SpeedtestServer.UDP.Result'; + $rawValue = null; + + if (isset($device[$paramName]) && isset($device[$paramName]['value'][0])) { + $rawValue = $device[$paramName]['value'][0]; + } + + if (!$rawValue || !is_string($rawValue) || !str_contains($rawValue, 'BPS')) { + self::returnJson(['success' => true, 'result' => null]); + return; + } + + // Parse the result string (format: "BPS 12345678 Bytes 9876543 Packets 1234") + $parsed = $this->parseSpeedtestResult($rawValue); + + self::returnJson(['success' => true, 'result' => $parsed]); } catch (Exception $e) { $this->log->debug("Speedtest Result Error", ['error' => $e->getMessage()]); self::sendError($e->getMessage()); } } + private function parseSpeedtestResult($raw) { + try { + preg_match('/BPS\s+(\d+)/', $raw, $bpsMatch); + preg_match('/Bytes\s+(\d+)/', $raw, $bytesMatch); + preg_match('/Packets\s+(\d+)/', $raw, $packetsMatch); + + if (!$bpsMatch) return null; + + $bps = (int)$bpsMatch[1]; + $bytes = $bytesMatch ? (int)$bytesMatch[1] : 0; + $packets = $packetsMatch ? (int)$packetsMatch[1] : 0; + + return [ + 'raw' => $raw, + 'bps' => $bps, + 'bpsFormatted' => $this->formatBits($bps), + 'bytes' => $bytes, + 'bytesFormatted' => $this->formatBytes($bytes), + 'packets' => $packets + ]; + } catch (Exception $e) { + $this->log->debug("Error parsing speedtest result", ['error' => $e->getMessage()]); + return null; + } + } + + private function formatBits($bps) { + if (!$bps) return '0 Mbit/s'; + $mbits = $bps / 1000000; + return number_format($mbits, 2, ',', '.') . ' Mbit/s'; + } + + private function formatBytes($bytes) { + if ($bytes == 0) return '0 B'; + $units = ['B', 'KB', 'MB', 'GB', 'TB']; + $i = floor(log($bytes) / log(1024)); + return number_format($bytes / pow(1024, $i), 2, ',', '.') . ' ' . $units[$i]; + } + private function getGenieACS() { $host = defined('GENIEACS_HOST') ? GENIEACS_HOST : 'http://acs.xinon.at:3000'; $username = defined('GENIEACS_USERNAME') ? GENIEACS_USERNAME : 'admin'; diff --git a/public/js/pages/Radius/RadiusRouterManager.js b/public/js/pages/Radius/RadiusRouterManager.js index 6d0d6c87e..04d63be4d 100644 --- a/public/js/pages/Radius/RadiusRouterManager.js +++ b/public/js/pages/Radius/RadiusRouterManager.js @@ -288,19 +288,6 @@ const RadiusRouterManager = { } this.routerActionLoading = false; }, - async setParameterValues(parameters) { - if (!this.routerDevice || !this.routerDevice.deviceId || !parameters) return false; - try { - const { data } = await axios.post(`${window.TT_CONFIG.BASE_PATH}/Radius/genieacsSetParameters`, { - deviceId: this.routerDevice.deviceId, - parameters: parameters - }); - return data.success; - } catch (error) { - console.error('Error setting parameters:', error); - return false; - } - }, async runSpeedtest() { if (!this.routerDevice || !this.routerDevice.deviceId) return; this.showSpeedtestModal = true; @@ -310,32 +297,23 @@ const RadiusRouterManager = { this.speedtestHasStarted = false; try { - const params = { - 'InternetGatewayDevice.X_AVM-DE_SpeedtestServer.UDP.Start': 1, - 'InternetGatewayDevice.X_AVM-DE_SpeedtestServer.UDP.StartBidirect': 1, - 'InternetGatewayDevice.X_AVM-DE_SpeedtestServer.UDP.WANAccess': true - }; + const { data } = await axios.post(`${window.TT_CONFIG.BASE_PATH}/Radius/genieacsRunSpeedtest`, { + deviceId: this.routerDevice.deviceId + }); - if (!await this.setParameterValues(params)) { - throw new Error("Konnte Speedtest-Parameter nicht setzen"); + if (data.success) { + this.pollSpeedtestResult(); + } else { + throw new Error(data.message || "Speedtest konnte nicht gestartet werden"); } - - const ip = this.routerDevice.ip; - if (!ip) throw new Error("Keine IP-Adresse gefunden"); - - await axios.post(`${window.TT_CONFIG.BASE_PATH}/Radius/genieacsRunSpeedtest`, { ip }); - - this.pollSpeedtestResult(); - } catch (e) { - window.notify('error', e.message); + window.notify('error', e.response?.data?.message || e.message || 'Fehler beim Starten des Speedtests'); this.speedtestLoading = false; } }, async pollSpeedtestResult() { let attempts = 0; const maxAttempts = 240; - const resultParam = 'InternetGatewayDevice.X_AVM-DE_SpeedtestServer.UDP.Result'; const poll = async () => { if (!this.showSpeedtestModal) return; @@ -347,93 +325,34 @@ const RadiusRouterManager = { attempts++; try { - await axios.post(`${window.TT_CONFIG.BASE_PATH}/Radius/genieacsGetParameters`, { - deviceId: this.routerDevice.deviceId, - parameters: [resultParam] + const { data } = await axios.post(`${window.TT_CONFIG.BASE_PATH}/Radius/genieacsGetSpeedtestResult`, { + deviceId: this.routerDevice.deviceId }); - setTimeout(async () => { - try { - const val = await this.fetchDeviceParameterValue(resultParam); - if (val && typeof val === 'string' && val.includes("BPS")) { - const parsed = this.parseSpeedtestResult(val); - if (parsed) { - this.speedtestHistory.push(parsed); - this.$nextTick(() => { - if (this.$refs.speedtestBottom) { - this.$refs.speedtestBottom.scrollIntoView({ behavior: 'smooth' }); - } - }); - - if (parsed.bps > 0) this.speedtestHasStarted = true; - - if (this.speedtestHasStarted && parsed.bps === 0) { - this.speedtestLoading = false; - window.notify('success', 'Speedtest abgeschlossen'); - return; - } - } + if (data.success && data.result) { + this.speedtestHistory.push(data.result); + this.$nextTick(() => { + if (this.$refs.speedtestBottom) { + this.$refs.speedtestBottom.scrollIntoView({ behavior: 'smooth' }); } - } catch(e) { console.error(e); } + }); - if (this.speedtestLoading) setTimeout(poll, 500); - }, 500); + if (data.result.bps > 0) this.speedtestHasStarted = true; + if (this.speedtestHasStarted && data.result.bps === 0) { + this.speedtestLoading = false; + window.notify('success', 'Speedtest abgeschlossen'); + return; + } + } } catch (e) { console.error(e); - if (this.speedtestLoading) setTimeout(poll, 500); } + + if (this.speedtestLoading) setTimeout(poll, 1000); }; poll(); }, - async fetchDeviceParameterValue(paramName) { - if (!this.routerDevice || !this.routerDevice.deviceId) return null; - try { - const { data: deviceInfo } = await axios.get(`${window.TT_CONFIG.BASE_PATH}/Radius/genieacsGetDeviceInfo`, { - params: { deviceId: this.routerDevice.deviceId } - }); - - if (deviceInfo?.success && deviceInfo?.fullData) { - const paramData = deviceInfo.fullData[paramName]; - if (paramData?.value?.[0]) { - return paramData.value[0]; - } - } - } catch (error) { - console.error('Error fetching parameter value:', error); - } - return null; - }, - formatBits(bps) { - if (!bps) return '0 Mbit/s'; - const mbits = bps / 1000000; - return mbits.toFixed(2) + ' Mbit/s'; - }, - parseSpeedtestResult(raw) { - try { - const bpsMatch = raw.match(/BPS\s+(\d+)/); - const bytesMatch = raw.match(/Bytes\s+(\d+)/); - const packetsMatch = raw.match(/Packets\s+(\d+)/); - - if (bpsMatch) { - const bps = parseInt(bpsMatch[1]); - const bytes = bytesMatch ? parseInt(bytesMatch[1]) : 0; - const packets = packetsMatch ? parseInt(packetsMatch[1]) : 0; - - return { - raw: raw, - bps: bps, - bpsFormatted: this.formatBits(bps), - bytes: bytes, - bytesFormatted: window.TT_CORE.formatBytes(bytes), - packets: packets - }; - } - } catch (e) { - console.error("Error parsing speedtest result", e); - } - return null; - }, async runRemoteAccess() { if (!this.routerDevice || !this.routerDevice.deviceId) return; this.showRemoteAccessModal = true;