diff --git a/applications/luci-app-speedtest/Makefile b/applications/luci-app-speedtest/Makefile new file mode 100644 index 000000000000..0c6faa930e91 --- /dev/null +++ b/applications/luci-app-speedtest/Makefile @@ -0,0 +1,17 @@ +# This is free software, licensed under the Apache License, Version 2.0 +# +# Copyright (C) 2024 Hilman Maulana + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=LuCI for speedtest +LUCI_DEPENDS:=+speedtestcpp +LUCI_DESCRIPTION:=LuCI support for Speedtestcpp + +PKG_MAINTAINER:=Hilman Maulana +PKG_VERSION:=1.1 +PKG_LICENSE:=Apache-2.0 + +include ../../luci.mk + +# call BuildPackage - OpenWrt buildroot signature \ No newline at end of file diff --git a/applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js b/applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js new file mode 100644 index 000000000000..cf6a3765a0e6 --- /dev/null +++ b/applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js @@ -0,0 +1,133 @@ +/* This is free software, licensed under the Apache License, Version 2.0 + * + * Copyright (C) 2024 Hilman Maulana + */ + +'use strict'; +'require view'; +'require fs'; + +return view.extend({ + handleSaveApply: null, + handleSave: null, + handleReset: null, + render: function() { + var select = [ + E('label', { 'class': 'cbi-input-label', 'for': 'speedtest-type', 'style': 'margin-right: 8px;'}, _('Test')), + E('select', { 'id': 'speedtest-type', 'style': 'width:80%;'}, [ + E('option', { 'value': 'all', 'selected': 'selected'}, _('All')), + E('option', { 'value': 'latency' }, _('Latency')), + E('option', { 'value': 'download' }, _('Download')), + E('option', { 'value': 'upload' }, _('Upload')) + ]) + ]; + var status = [ + E('label', { 'class': 'cbi-input-label', 'style': 'margin-right: 8px;'}, _('Status')), + E('em', { 'id': 'speedtest-status'}, _('Available')) + ]; + var running = false; + var button = [ + E('button', { + 'class': 'btn cbi-button cbi-button-action', + 'click': function() { + if (!running) { + running = true; + var dropdown = document.getElementById('speedtest-type'); + var value = dropdown.options[dropdown.selectedIndex].value; + var command = ['--output', 'json']; + if (value !== 'all') { + command.push('--' + value); + } + + var status = document.getElementById('speedtest-status'); + status.textContent = _('Running'); + + fs.exec_direct('speedtest', command) + .then(function(response) { + var result = JSON.parse(response); + document.getElementById('client-ip').textContent = result.client.ip; + document.getElementById('client-isp').textContent = result.client.isp + ' [' + result.client.lat + ', ' + result.client.lon + ']'; + document.getElementById('server-name').textContent = result.server.sponsor; + document.getElementById('server-id').textContent = result.server.id; + document.getElementById('server-location').textContent = result.server.name + ' (' + result.server.distance + ' km)'; + document.getElementById('server-host').textContent = result.server.host; + document.getElementById('ping').textContent = result.ping + ' ms'; + document.getElementById('jitter').textContent = result.jitter + ' ms'; + document.getElementById('download').textContent = result.download_mbit ? result.download_mbit + ' Mbit/s' : '-'; + document.getElementById('upload').textContent = result.upload_mbit ? result.upload_mbit + ' Mbit/s' : '-'; + status.textContent = _('Finished'); + running = false; + }) + .catch(function(err) { + status.textContent = err; + running = false; + }); + } + } + }, _('Run Speedtest')) + ]; + var table = [ + E('h3', {'class': 'section-title'}, _('Results')), + E('table', {'class': 'table cbi-section-table'}, [ + E('tr', {'class': 'tr table-title'}, [ + E('th', {'class': 'th ', 'style': 'display: none;'}) + ]), + E('tr', {'class': 'tr cbi-rowstyle-1'},[ + E('td', {'class': 'td left', 'width': '50%'}, _('IP Address')), + E('td', {'class': 'td', 'id': 'client-ip'}, '-') + ]), + E('tr', {'class': 'tr cbi-rowstyle-2'},[ + E('td', {'class': 'td left', 'width': '50%'}, _('Provider')), + E('td', {'class': 'td', 'id': 'client-isp'}, '-') + ]), + E('tr', {'class': 'tr cbi-rowstyle-1'},[ + E('td', {'class': 'td left', 'width': '50%'}, _('Server')), + E('td', {'class': 'td', 'id': 'server-name'}, '-') + ]), + E('tr', {'class': 'tr cbi-rowstyle-2'},[ + E('td', {'class': 'td left', 'width': '50%'}, _('ID')), + E('td', {'class': 'td', 'id': 'server-id'}, '-') + ]), + E('tr', {'class': 'tr cbi-rowstyle-1'},[ + E('td', {'class': 'td left', 'width': '50%'}, _('Location')), + E('td', {'class': 'td', 'id': 'server-location'}, '-') + ]), + E('tr', {'class': 'tr cbi-rowstyle-2'},[ + E('td', {'class': 'td left', 'width': '50%'}, _('Server Host')), + E('td', {'class': 'td', 'id': 'server-host'}, '-') + ]), + E('tr', {'class': 'tr cbi-rowstyle-1'},[ + E('td', {'class': 'td left', 'width': '50%'}, _('Ping')), + E('td', {'class': 'td', 'id': 'ping'}, '-') + ]), + E('tr', {'class': 'tr cbi-rowstyle-2'},[ + E('td', {'class': 'td left', 'width': '50%'}, _('Jitter')), + E('td', {'class': 'td', 'id': 'jitter'}, '-') + ]), + E('tr', {'class': 'tr cbi-rowstyle-1'},[ + E('td', {'class': 'td left', 'width': '50%'}, _('Download Speed')), + E('td', {'class': 'td', 'id': 'download'}, '-') + ]), + E('tr', {'class': 'tr cbi-rowstyle-2'},[ + E('td', {'class': 'td left', 'width': '50%'}, _('Upload Speed')), + E('td', {'class': 'td', 'id': 'upload'}, '-') + ]) + ]) + ]; + var body = E('div', {'class': 'cbi-map'}, [ + E('h2', {'class': 'section-title'}, _('Speedtest')), + E('div', {'class': 'cbi-map-descr'}, _('Here you can perform a speedtest to measure the basic aspects of your network connection.')), + E('table', {'class': 'table'}, [ + E('tr', {'class': 'tr'}, [ + E('td', {'class': 'td', 'style': 'overflow:initial;'}, select), + E('td', {'class': 'td', 'style': 'overflow:initial;'}, button), + E('td', {'class': 'td'}, status) + ]) + ]), + E('div', {'class': 'cbi-section'}, [ + E('div', {'class': 'speedtest-info'}, table) + ]) + ]); + return body + } +}) diff --git a/applications/luci-app-speedtest/po/templates/speedtest.pot b/applications/luci-app-speedtest/po/templates/speedtest.pot new file mode 100644 index 000000000000..f067d3274a56 --- /dev/null +++ b/applications/luci-app-speedtest/po/templates/speedtest.pot @@ -0,0 +1,99 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: applications/luci-app-speedtest/root/usr/share/luci/menu.d/luci-app-speedtest.json:3 +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:118 +msgid "Speedtest" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:119 +msgid "Here you can perform a speedtest to measure the basic aspects of your network connection." +msgstr "" + +#: applications/luci-app-speedtest/root/usr/share/rpcd/acl.d/luci-app-speedtest.json:3 +msgid "Grant access to speedtest" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:16 +msgid "Test" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:18 +msgid "All" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:19 +msgid "Latency" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:20 +msgid "Download" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:21 +msgid "Upload" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:25 +msgid "Status" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:26 +msgid "Available" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:43 +msgid "Running" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:58 +msgid "Finished" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:67 +msgid "Run Speedtest" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:70 +msgid "Results" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:76 +msgid "IP Address" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:80 +msgid "Provider" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:84 +msgid "Server" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:88 +msgid "ID" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:92 +msgid "Location" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:96 +msgid "Server Host" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:100 +msgid "Ping" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:104 +msgid "Jitter" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:100 +msgid "Download Speed" +msgstr "" + +#: applications/luci-app-speedtest/htdocs/luci-static/resources/view/speedtest.js:112 +msgid "Upload Speed" +msgstr "" diff --git a/applications/luci-app-speedtest/root/usr/share/luci/menu.d/luci-app-speedtest.json b/applications/luci-app-speedtest/root/usr/share/luci/menu.d/luci-app-speedtest.json new file mode 100644 index 000000000000..042176995402 --- /dev/null +++ b/applications/luci-app-speedtest/root/usr/share/luci/menu.d/luci-app-speedtest.json @@ -0,0 +1,13 @@ +{ + "admin/network/speedtest": { + "title": "Speedtest", + "order": 50, + "action": { + "type": "view", + "path": "speedtest" + }, + "depends": { + "acl": [ "luci-app-speedtest" ] + } + } +} diff --git a/applications/luci-app-speedtest/root/usr/share/rpcd/acl.d/luci-app-speedtest.json b/applications/luci-app-speedtest/root/usr/share/rpcd/acl.d/luci-app-speedtest.json new file mode 100644 index 000000000000..d423a1c03c93 --- /dev/null +++ b/applications/luci-app-speedtest/root/usr/share/rpcd/acl.d/luci-app-speedtest.json @@ -0,0 +1,10 @@ +{ + "luci-app-speedtest": { + "description": "Grant access to speedtest", + "write": { + "file": { + "/usr/bin/speedtest": [ "exec"] + } + } + } +}