├── .img ├── iperf3.png ├── librespeed.png ├── librespeed_config.png └── speedtest.png ├── .prepare.sh ├── LICENSE ├── Makefile ├── README.md ├── htdocs └── luci-static │ └── resources │ └── view │ └── netspeedtest │ ├── iperf3.js │ ├── librespeed-cfg.js │ ├── librespeed.js │ ├── openspeedtest.js │ └── speedtest.js ├── po ├── templates │ └── netspeedtest.pot ├── zh_Hans │ └── netspeedtest.po └── zh_Hant │ └── netspeedtest.po └── root ├── etc ├── init.d │ └── netspeedtest └── uci-defaults │ └── 99_netspeedtest └── usr ├── lib └── netspeedtest │ └── speedtest └── share ├── luci └── menu.d │ └── luci-app-netspeedtest.json └── rpcd └── acl.d └── luci-app-netspeedtest.json /.img/iperf3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muink/luci-app-netspeedtest/729172b8f208b289ee056e8a0460614e0deb919c/.img/iperf3.png -------------------------------------------------------------------------------- /.img/librespeed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muink/luci-app-netspeedtest/729172b8f208b289ee056e8a0460614e0deb919c/.img/librespeed.png -------------------------------------------------------------------------------- /.img/librespeed_config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muink/luci-app-netspeedtest/729172b8f208b289ee056e8a0460614e0deb919c/.img/librespeed_config.png -------------------------------------------------------------------------------- /.img/speedtest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muink/luci-app-netspeedtest/729172b8f208b289ee056e8a0460614e0deb919c/.img/speedtest.png -------------------------------------------------------------------------------- /.prepare.sh: -------------------------------------------------------------------------------- 1 | PKG_NAME="$1" 2 | CURDIR="$2" 3 | PKG_BUILD_DIR="$3" 4 | 5 | if [ -d "$CURDIR/.git" ]; then 6 | config="$CURDIR/.git/config" 7 | else 8 | config="$(sed "s|^gitdir:\s*|$CURDIR/|;s|$|/config|" "$CURDIR/.git")" 9 | fi 10 | [ -n "$(sed -En '/^\[remote /{h;:top;n;/^\[/b;s,(https?://gitcode\.(com|net)),\1,;T top;H;x;s|\n\s*|: |;p;}' "$config")" ] && { 11 | for d in luasrc ucode htdocs root src; do 12 | rm -rf "$PKG_BUILD_DIR"/$d 13 | done 14 | mkdir -p "$PKG_BUILD_DIR"/htdocs/luci-static/resources/view 15 | touch "$PKG_BUILD_DIR"/htdocs/luci-static/resources/view/$PKG_NAME.js 16 | mkdir -p "$PKG_BUILD_DIR"/root/usr/share/luci/menu.d 17 | touch "$PKG_BUILD_DIR"/root/usr/share/luci/menu.d/$PKG_NAME.json 18 | } 19 | exit 0 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 muink 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | # 3 | # Copyright (C) 2023-2025 muink 4 | 5 | include $(TOPDIR)/rules.mk 6 | 7 | LUCI_NAME:=luci-app-netspeedtest 8 | 9 | LUCI_TITLE:=LuCI Net Speedtest 10 | LUCI_DEPENDS:=+iperf3 +librespeed-go +python3-speedtest-cli +ca-certificates 11 | 12 | LUCI_DESCRIPTION:=Test Net speed 13 | 14 | PKG_MAINTAINER:=Anya Lin 15 | PKG_LICENSE:=MIT 16 | 17 | PKG_UNPACK=$(CURDIR)/.prepare.sh $(PKG_NAME) $(CURDIR) $(PKG_BUILD_DIR) 18 | 19 | define Package/$(LUCI_NAME)/conffiles 20 | /etc/config/netspeedtest 21 | endef 22 | 23 | define Package/$(LUCI_NAME)/postinst 24 | endef 25 | 26 | define Package/$(LUCI_NAME)/prerm 27 | endef 28 | 29 | include $(TOPDIR)/feeds/luci/luci.mk 30 | 31 | # call BuildPackage - OpenWrt buildroot signature 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LuCI Network Speed Test 2 | 3 | ### Screenshots 4 | 5 | ![iperf3](.img/iperf3.png "iperf3")\ 6 | ![librespeed](.img/librespeed.png "librespeed")\ 7 | ![librespeed_config](.img/librespeed_config.png "librespeed_config")\ 8 | ![speedtest](.img/speedtest.png "speedtest") 9 | 10 | ### How to install 11 | 12 | #### Prerequisites 13 | 14 | This package depends on python3-speedtest-cli which in turn depends on python3-base and various other python3 libraries. These packages combined can take up a lot of space on a router so before installing luci-app-netspeedtest, make sure you have enough space to install python3-speedtest-cli. You can check this by searching for python3-speedtest-cli under the software page in LuCI and try to install it, it will tell you how much space it and its dependencies require, just compare that to how much space you have left. 15 | 16 | #### Installation 17 | 18 | 1. Goto ~~[releases](https://github.com/muink/luci-app-netspeedtest/tree/releases)~~ [here](https://fantastic-packages.github.io/packages/) 19 | 2. Download the latest version of ipk 20 | 3. Login router and goto **System --> Software** 21 | 4. Upload and install ipk 22 | 5. Reboot if the app is not automatically added in page 23 | 6. Goto **Network --> SpeedTest** 24 | 25 | ### Build 26 | 27 | - Compile from OpenWrt/LEDE SDK 28 | 29 | ``` 30 | # Take the x86_64 platform as an example 31 | tar xjf openwrt-sdk-21.02.3-x86-64_gcc-8.4.0_musl.Linux-x86_64.tar.xz 32 | # Go to the SDK root dir 33 | cd OpenWrt-sdk-*-x86_64_* 34 | # First run to generate a .config file 35 | make menuconfig 36 | ./scripts/feeds update -a 37 | ./scripts/feeds install -a 38 | # Get Makefile 39 | git clone --depth 1 --branch master --single-branch --no-checkout https://github.com/muink/luci-app-netspeedtest.git package/luci-app-netspeedtest 40 | pushd package/luci-app-netspeedtest 41 | umask 022 42 | git checkout 43 | popd 44 | # Select the package LuCI -> Applications -> luci-app-netspeedtest 45 | make menuconfig 46 | # Start compiling 47 | make package/luci-app-netspeedtest/compile V=99 48 | ``` 49 | 50 | ### License 51 | 52 | - This project is licensed under the MIT License 53 | -------------------------------------------------------------------------------- /htdocs/luci-static/resources/view/netspeedtest/iperf3.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 'require view'; 3 | 'require poll'; 4 | 'require fs'; 5 | 'require rpc'; 6 | 'require uci'; 7 | 'require ui'; 8 | 'require form'; 9 | 10 | const conf = 'netspeedtest'; 11 | const instance = 'iperf3'; 12 | 13 | const callServiceList = rpc.declare({ 14 | object: 'service', 15 | method: 'list', 16 | params: ['name'], 17 | expect: { '': {} } 18 | }); 19 | 20 | function getServiceStatus() { 21 | return L.resolveDefault(callServiceList(conf), {}) 22 | .then((res) => { 23 | let isrunning = false; 24 | try { 25 | isrunning = res[conf]['instances'][instance]['running']; 26 | } catch (e) { } 27 | return isrunning; 28 | }); 29 | } 30 | 31 | return view.extend({ 32 | // handleSaveApply: null, 33 | // handleSave: null, 34 | // handleReset: null, 35 | 36 | load() { 37 | return Promise.all([ 38 | getServiceStatus(), 39 | uci.load('netspeedtest') 40 | ]); 41 | }, 42 | 43 | poll_status(nodes, stat) { 44 | const isRunning = stat[0]; 45 | let view = nodes.querySelector('#service_status'); 46 | 47 | if (isRunning) { 48 | view.innerHTML = "" + instance + " - " + _("SERVER RUNNING") + ""; 49 | } else { 50 | view.innerHTML = "" + instance + " - " + _("SERVER NOT RUNNING") + ""; 51 | } 52 | return; 53 | }, 54 | 55 | render(res) { 56 | const isRunning = res[0]; 57 | 58 | let m, s, o; 59 | 60 | m = new form.Map('netspeedtest', _('iperf3 Bandwidth Performance Test')); 61 | 62 | s = m.section(form.NamedSection, '_status'); 63 | s.anonymous = true; 64 | s.render = function (section_id) { 65 | return E('div', { class: 'cbi-section' }, [ 66 | E('div', { id: 'service_status' }, _('Collecting data ...')) 67 | ]); 68 | }; 69 | 70 | s = m.section(form.NamedSection, 'config', 'netspeedtest'); 71 | s.anonymous = true; 72 | 73 | o = s.option(form.Flag, 'iperf3_enabled', _('Enable')); 74 | o.default = o.disabled; 75 | o.rmempty = false; 76 | 77 | o = s.option(form.Button, '_client_url', _('Download iperf3 client')); 78 | o.inputtitle = _('Official website'); 79 | o.inputstyle = 'apply'; 80 | o.onclick = function () { 81 | window.open("https://iperf.fr/iperf-download.php", '_blank'); 82 | }; 83 | 84 | s = m.section(form.TypedSection, '_cmd_ref'); 85 | s.anonymous = true; 86 | s.render = function (section_id) { 87 | return E('div', { 'class': 'cbi-section' }, [ 88 | E('h3', {}, _('iperf3 Common commands reference')), 89 | E('pre', {}, [ 90 | " -c, --client \n\ 91 | -u, --udp UDP mode\n\ 92 | -b, --bandwidth [KMG] target bandwidth in bits/sec (0 for unlimited)\n\ 93 | -t, --time time in seconds to transmit for (default 10 secs)\n\ 94 | -i, --interval seconds between periodic bandwidth reports\n\ 95 | -P, --parallel number of parallel client streams to run\n\ 96 | -R, --reverse run in reverse mode (server sends, client receives)\n" 97 | ]) 98 | ]); 99 | }; 100 | 101 | return m.render() 102 | .then(L.bind(function(m, nodes) { 103 | poll.add(L.bind(function() { 104 | return Promise.all([ 105 | getServiceStatus() 106 | ]).then(L.bind(this.poll_status, this, nodes)); 107 | }, this), 3); 108 | return nodes; 109 | }, this, m)); 110 | } 111 | }); 112 | -------------------------------------------------------------------------------- /htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 'require view'; 3 | 'require poll'; 4 | 'require fs'; 5 | 'require rpc'; 6 | 'require uci'; 7 | 'require ui'; 8 | 'require form'; 9 | 10 | const conf = 'librespeed-go'; 11 | const instance = 'librespeed-go'; 12 | 13 | const callServiceList = rpc.declare({ 14 | object: 'service', 15 | method: 'list', 16 | params: ['name'], 17 | expect: { '': {} } 18 | }); 19 | 20 | function getServiceStatus() { 21 | return L.resolveDefault(callServiceList(conf), {}) 22 | .then((res) => { 23 | let isrunning = false; 24 | try { 25 | isrunning = res[conf]['instances'][instance]['running']; 26 | } catch (e) { } 27 | return isrunning; 28 | }); 29 | } 30 | 31 | return view.extend({ 32 | // handleSaveApply: null, 33 | // handleSave: null, 34 | // handleReset: null, 35 | 36 | load() { 37 | return Promise.all([ 38 | L.resolveDefault(getServiceStatus(), false), 39 | uci.load('librespeed-go') 40 | ]); 41 | }, 42 | 43 | poll_status(nodes, stat) { 44 | const isRunning = stat[0]; 45 | let view = nodes.querySelector('#service_status'); 46 | 47 | if (isRunning) { 48 | view.innerHTML = "" + instance + " - " + _("SERVER RUNNING") + ""; 49 | } else { 50 | view.innerHTML = "" + instance + " - " + _("SERVER NOT RUNNING") + ""; 51 | } 52 | return; 53 | }, 54 | 55 | render(res) { 56 | const isRunning = res[0]; 57 | 58 | let m, s, o; 59 | 60 | m = new form.Map('librespeed-go', _('librespeed Config')); 61 | 62 | s = m.section(form.NamedSection, '_status'); 63 | s.anonymous = true; 64 | s.render = function (section_id) { 65 | return E('div', { class: 'cbi-section' }, [ 66 | E('div', { id: 'service_status' }, _('Collecting data ...')) 67 | ]); 68 | }; 69 | 70 | s = m.section(form.NamedSection, 'config', 'librespeed-go'); 71 | s.anonymous = true; 72 | 73 | o = s.option(form.Value, 'listen_port', _('Listen Port')); 74 | o.datatype = 'port'; 75 | o.default = 8989; 76 | o.rmempty = false; 77 | 78 | o = s.option(form.Flag, 'enable_http2', _('Enable HTTP2')); 79 | o.default = o.disabled; 80 | o.rmempty = false; 81 | 82 | o = s.option(form.Flag, 'enable_tls', _('Enable TLS')); 83 | o.default = o.disabled; 84 | o.rmempty = false; 85 | o.retain = true; 86 | o.depends('enable_http2', '1'); 87 | 88 | o = s.option(form.Value, 'tls_cert_file', _('TLS Cert file')); 89 | o.placeholder = '/etc/librespeed-go/cert.pem'; 90 | o.rmempty = false; 91 | o.retain = true; 92 | o.depends('enable_tls', '1'); 93 | 94 | o = s.option(form.Value, 'tls_key_file', _('TLS Key file')); 95 | o.placeholder = '/etc/librespeed-go/privkey.pem'; 96 | o.rmempty = false; 97 | o.retain = true; 98 | o.depends('enable_tls', '1'); 99 | 100 | return m.render() 101 | .then(L.bind(function(m, nodes) { 102 | poll.add(L.bind(function() { 103 | return Promise.all([ 104 | L.resolveDefault(getServiceStatus(), false) 105 | ]).then(L.bind(this.poll_status, this, nodes)); 106 | }, this), 3); 107 | return nodes; 108 | }, this, m)); 109 | } 110 | }); 111 | -------------------------------------------------------------------------------- /htdocs/luci-static/resources/view/netspeedtest/librespeed.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 'require view'; 3 | 'require fs'; 4 | 'require rpc'; 5 | 'require uci'; 6 | 'require ui'; 7 | 'require form'; 8 | 9 | return view.extend({ 10 | // handleSaveApply: null, 11 | // handleSave: null, 12 | // handleReset: null, 13 | 14 | load() { 15 | return Promise.all([ 16 | uci.load('netspeedtest'), 17 | uci.load('librespeed-go') 18 | ]); 19 | }, 20 | 21 | render(res) { 22 | const port = uci.get('librespeed-go', 'config', 'listen_port') || '8989'; 23 | const ssl = uci.get('librespeed-go', 'config', 'enable_tls') || '0'; 24 | 25 | let m, s, o; 26 | 27 | m = new form.Map('netspeedtest', _('librespeed Site Speed Test')); 28 | 29 | s = m.section(form.NamedSection, 'config', 'netspeedtest'); 30 | s.anonymous = true; 31 | 32 | o = s.option(form.Flag, 'librespeed_enabled', _('Enable')); 33 | o.default = o.disabled; 34 | o.rmempty = false; 35 | 36 | s = m.section(form.NamedSection, '_iframe'); 37 | s.anonymous = true; 38 | s.render = function (section_id) { 39 | if (port === '0') { 40 | return E('div', { class: 'alert-message warning' }, 41 | _('Random port (port=0) is not supported.
Change to a fixed port and try again.')); 42 | }; 43 | return E('iframe', { 44 | src: (ssl === '1' ? 'https' : 'http') + '://' + window.location.hostname + ':' + port, 45 | style: 'width: 100%; min-height: 100vh; border: none; border-radius: 3px;' 46 | }); 47 | }; 48 | 49 | return m.render(); 50 | } 51 | }); 52 | -------------------------------------------------------------------------------- /htdocs/luci-static/resources/view/netspeedtest/openspeedtest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 'require view'; 3 | 'require uci'; 4 | 'require ui'; 5 | 'require form'; 6 | 7 | return view.extend({ 8 | // handleSaveApply: null, 9 | // handleSave: null, 10 | // handleReset: null, 11 | 12 | load() { 13 | return Promise.all([ 14 | uci.load('netspeedtest') 15 | ]); 16 | }, 17 | 18 | render(res) { 19 | let m, s, o; 20 | 21 | m = new form.Map('netspeedtest', _('OpenSpeedTest')); 22 | 23 | s = m.section(form.NamedSection, '_iframe'); 24 | s.anonymous = true; 25 | s.render = function (section_id) { 26 | return E('iframe', { 27 | src: '//openspeedtest.com/speedtest', 28 | style: 'border:none;width:100%;height:100%;min-height:360px;border:none;overflow:hidden !important;' 29 | }); 30 | }; 31 | 32 | return m.render(); 33 | } 34 | }); 35 | -------------------------------------------------------------------------------- /htdocs/luci-static/resources/view/netspeedtest/speedtest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 'require view'; 3 | 'require poll'; 4 | 'require dom'; 5 | 'require fs'; 6 | 'require rpc'; 7 | 'require uci'; 8 | 'require ui'; 9 | 'require form'; 10 | 11 | const TestTimeout = 240 * 1000; // 4 Minutes 12 | 13 | return view.extend({ 14 | // handleSaveApply: null, 15 | // handleSave: null, 16 | // handleReset: null, 17 | 18 | load() { 19 | return Promise.all([ 20 | L.resolveDefault(fs.stat('/usr/libexec/netspeedtest/speedtest'), {}), 21 | L.resolveDefault(fs.read('/var/speedtest_result'), null), 22 | L.resolveDefault(fs.stat('/var/speedtest_result'), {}), 23 | uci.load('netspeedtest') 24 | ]); 25 | }, 26 | 27 | poll_status(nodes, res) { 28 | const has_ookla = res[0].path; 29 | let result_content = res[1] ? res[1].trim().split("\n") : []; 30 | let ookla_stat = nodes.querySelector('#ookla_status'); 31 | let result_stat = nodes.querySelector('#speedtest_result'); 32 | if (has_ookla) { 33 | ookla_stat.style.color = 'green'; 34 | dom.content(ookla_stat, [ _('Installed') ]); 35 | } else { 36 | ookla_stat.style.color = 'red'; 37 | dom.content(ookla_stat, [ _('Not Installed') ]); 38 | }; 39 | if (result_content.length) { 40 | if (result_content[0] == 'Testing') { 41 | result_stat.innerHTML = "" + 42 | "" + 43 | _('Testing in progress...') + 44 | ""; 45 | }; 46 | if (result_content[0].match(/https?:\S+/)) { 47 | result_stat.innerHTML = "
"; 48 | }; 49 | if (result_content[0] == 'Test failed') { 50 | result_stat.innerHTML = "" + _('Test failed.') + ""; 51 | } 52 | } else { 53 | result_stat.innerHTML = "" + _('No result.') + ""; 54 | }; 55 | return; 56 | }, 57 | 58 | render(res) { 59 | const has_ookla = res[0].path; 60 | const result_content = res[1] ? res[1].trim().split("\n") : []; 61 | const result_mtime = res[2] ? res[2].mtime * 1000 : 0; 62 | const date = new Date(); 63 | 64 | let m, s, o; 65 | 66 | m = new form.Map('netspeedtest', _('Ookla SpeedTest')); 67 | 68 | s = m.section(form.TypedSection, '_result'); 69 | s.anonymous = true; 70 | s.render = function (section_id) { 71 | if (result_content.length) { 72 | if (result_content[0] == 'Testing') { 73 | return E('div', { 'id': 'speedtest_result' }, [ E('span', { 'style': 'color:yellow;font-weight:bold' }, [ 74 | E('img', { 'src': L.resource(['icons/loading.gif']), 'height': '20', 'style': 'vertical-align:middle' }, []), 75 | _('Testing in progress...') 76 | ]) ]) 77 | }; 78 | if (result_content[0].match(/https?:\S+/)) { 79 | return E('div', { 'id': 'speedtest_result' }, [ E('div', { 'style': 'max-width:500px' }, [ 80 | E('a', { 'href': result_content[0], 'target': '_blank' }, [ 81 | E('img', { 'src': result_content[0] + '.png', 'style': 'max-width:100%;max-height:100%;vertical-align:middle' }, []) 82 | ]) ]) ]) 83 | }; 84 | if (result_content[0] == 'Test failed') { 85 | return E('div', { 'id': 'speedtest_result' }, [ E('span', { 'style': 'color:red;font-weight:bold' }, [ _('Test failed.') ]) ]) 86 | } 87 | } else { 88 | return E('div', { 'id': 'speedtest_result' }, [ E('span', { 'style': 'color:red;font-weight:bold;display:none' }, [ _('No result.') ]) ]) 89 | } 90 | }; 91 | 92 | s = m.section(form.NamedSection, 'config', 'netspeedtest'); 93 | s.anonymous = true; 94 | 95 | o = s.option(form.Button, '_start', _('Start Test')); 96 | o.inputtitle = _('Start Test'); 97 | o.inputstyle = 'apply'; 98 | if (result_content.length && result_content[0] == 'Testing' && (date.getTime() - result_mtime) < TestTimeout) 99 | o.readonly = true; 100 | o.onclick = L.bind(function(ev, section_id) { 101 | const ookla_official=uci.get('netspeedtest', section_id, 'ookla_official') || '0' 102 | if (ookla_official === '1') { 103 | return fs.exec('/usr/lib/netspeedtest/speedtest') 104 | .then((res) => { return window.location = window.location.href.split('#')[0] }) 105 | .catch((e) => { ui.addNotification(null, E('p', e.message), 'error') }); 106 | } else { 107 | return fs.exec_direct('/usr/lib/netspeedtest/speedtest') 108 | .then((res) => { return window.location = window.location.href.split('#')[0] }) 109 | .catch((e) => { ui.addNotification(null, E('p', e.message), 'error') }); 110 | } 111 | }, o); 112 | 113 | o = s.option(form.DummyValue, '_ookla_status', _('Ookla® SpeedTest-CLI Status')); 114 | o.rawhtml = true; 115 | o.cfgvalue = function(s) { 116 | if (has_ookla) { 117 | return E('span', { 'id': 'ookla_status', 'style': 'color:green;font-weight:bold' }, [ _('Installed') ]); 118 | } else { 119 | return E('span', { 'id': 'ookla_status', 'style': 'color:red;font-weight:bold' }, [ _('Not Installed') ]); 120 | } 121 | }; 122 | 123 | //o = s.option(form.Button, '_ookla_status', _('Ookla® SpeedTest-CLI Status')); 124 | //o.inputtitle = _('Not Installed'); 125 | //o.inputstyle = 'null'; 126 | //o.readonly = true; 127 | //o.onclick = function() {}; 128 | //o.inputtitle = function() { 129 | // if (has_ookla) { 130 | // return _('Installed') 131 | // } else { 132 | // return _('Not Installed') 133 | // } 134 | //}; 135 | 136 | o = s.option(form.Flag, 'proxy_enabled', _('Enable proxy for downloader and test')); 137 | o.rmempty = false; 138 | 139 | o = s.option(form.ListValue, 'proxy_protocol', _('Proxy Protocol')); 140 | o.value('http', 'HTTP'); 141 | o.value('https', 'HTTPS'); 142 | o.value('socks5', 'SOCKS5'); 143 | o.value('socks5h', 'SOCKS5H'); 144 | o.default = 'socks5'; 145 | o.rmempty = false; 146 | o.retain = true; 147 | o.depends('proxy_enabled', '1'); 148 | 149 | o = s.option(form.Value, 'proxy_server', _('Proxy Server')); 150 | o.datatype = "ipaddrport(1)"; 151 | o.placeholder = '192.168.1.10:1080'; 152 | o.rmempty = false; 153 | o.retain = true; 154 | o.depends('proxy_enabled', '1'); 155 | 156 | o = s.option(form.Flag, 'ookla_official', _('Use Ookla® SpeedTest-CLI')); 157 | o.default = o.disabled; 158 | o.rmempty = false; 159 | 160 | o = s.option(form.ListValue, '_arch', _('System Arch')); 161 | o.value('i386'); 162 | o.value('x86_64'); 163 | o.value('armel'); 164 | o.value('armhf'); 165 | o.value('aarch64'); 166 | o.default = 'x86_64'; 167 | o.depends('ookla_official', '1'); 168 | o.write = function() {}; 169 | 170 | o = s.option(form.Button, '_download', _('Download Ookla® SpeedTest-CLI')); 171 | o.inputtitle = _('Download'); 172 | o.inputstyle = 'apply'; 173 | o.depends('ookla_official', '1'); 174 | o.onclick = function(ev, section_id) { 175 | const arch=this.section.getOption('_arch').formvalue(section_id); 176 | //alert(arch); 177 | return fs.exec_direct('/etc/init.d/netspeedtest', ['download_ookla', arch]) 178 | .catch((e) => { ui.addNotification(null, E('p', e.message), 'error') }); 179 | } 180 | 181 | return m.render() 182 | .then(L.bind(function(m, nodes) { 183 | poll.add(L.bind(function() { 184 | return Promise.all([ 185 | L.resolveDefault(fs.stat('/usr/libexec/netspeedtest/speedtest'), {}), 186 | L.resolveDefault(fs.read('/var/speedtest_result'), null) 187 | ]).then(L.bind(this.poll_status, this, nodes)); 188 | }, this), 5); 189 | return nodes; 190 | }, this, m)); 191 | } 192 | }); 193 | -------------------------------------------------------------------------------- /po/templates/netspeedtest.pot: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "Content-Type: text/plain; charset=UTF-8" 3 | 4 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:66 5 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:66 6 | msgid "Collecting data ..." 7 | msgstr "" 8 | 9 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:156 10 | msgid "Download" 11 | msgstr "" 12 | 13 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:155 14 | msgid "Download Ookla® SpeedTest-CLI" 15 | msgstr "" 16 | 17 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:77 18 | msgid "Download iperf3 client" 19 | msgstr "" 20 | 21 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:73 22 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed.js:32 23 | msgid "Enable" 24 | msgstr "" 25 | 26 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:77 27 | msgid "Enable HTTP2" 28 | msgstr "" 29 | 30 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:81 31 | msgid "Enable TLS" 32 | msgstr "" 33 | 34 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:121 35 | msgid "Enable proxy for downloader and test" 36 | msgstr "" 37 | 38 | #: applications/luci-app-netspeedtest/root/usr/share/rpcd/acl.d/luci-app-netspeedtest.json:3 39 | msgid "Grant access to netspeedtest procedures" 40 | msgstr "" 41 | 42 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:31 43 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:102 44 | msgid "Installed" 45 | msgstr "" 46 | 47 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:73 48 | msgid "Listen Port" 49 | msgstr "" 50 | 51 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:50 52 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:82 53 | msgid "No result." 54 | msgstr "" 55 | 56 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:34 57 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:104 58 | msgid "Not Installed" 59 | msgstr "" 60 | 61 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:78 62 | msgid "Official website" 63 | msgstr "" 64 | 65 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:61 66 | #: applications/luci-app-netspeedtest/root/usr/share/luci/menu.d/luci-app-netspeedtest.json:38 67 | msgid "Ookla SpeedTest" 68 | msgstr "" 69 | 70 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:98 71 | msgid "Ookla® SpeedTest-CLI Status" 72 | msgstr "" 73 | 74 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:124 75 | msgid "Proxy Protocol" 76 | msgstr "" 77 | 78 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:134 79 | msgid "Proxy Server" 80 | msgstr "" 81 | 82 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed.js:41 83 | msgid "" 84 | "Random port (port=0) is not supported.
Change to a fixed port and try " 85 | "again." 86 | msgstr "" 87 | 88 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:50 89 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:50 90 | msgid "SERVER NOT RUNNING" 91 | msgstr "" 92 | 93 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:48 94 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:48 95 | msgid "SERVER RUNNING" 96 | msgstr "" 97 | 98 | #: applications/luci-app-netspeedtest/root/usr/share/luci/menu.d/luci-app-netspeedtest.json:3 99 | msgid "SpeedTest" 100 | msgstr "" 101 | 102 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:89 103 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:90 104 | msgid "Start Test" 105 | msgstr "" 106 | 107 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:145 108 | msgid "System Arch" 109 | msgstr "" 110 | 111 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:87 112 | msgid "TLS Cert file" 113 | msgstr "" 114 | 115 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:92 116 | msgid "TLS Key file" 117 | msgstr "" 118 | 119 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:47 120 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:79 121 | msgid "Test failed." 122 | msgstr "" 123 | 124 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:40 125 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:70 126 | msgid "Testing in progress..." 127 | msgstr "" 128 | 129 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:141 130 | msgid "Use Ookla® SpeedTest-CLI" 131 | msgstr "" 132 | 133 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:60 134 | msgid "iperf3 Bandwidth Performance Test" 135 | msgstr "" 136 | 137 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:88 138 | msgid "iperf3 Common commands reference" 139 | msgstr "" 140 | 141 | #: applications/luci-app-netspeedtest/root/usr/share/luci/menu.d/luci-app-netspeedtest.json:14 142 | msgid "iperf3 Server" 143 | msgstr "" 144 | 145 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:60 146 | #: applications/luci-app-netspeedtest/root/usr/share/luci/menu.d/luci-app-netspeedtest.json:30 147 | msgid "librespeed Config" 148 | msgstr "" 149 | 150 | #: applications/luci-app-netspeedtest/root/usr/share/luci/menu.d/luci-app-netspeedtest.json:22 151 | msgid "librespeed Server" 152 | msgstr "" 153 | 154 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed.js:27 155 | msgid "librespeed Site Speed Test" 156 | msgstr "" 157 | -------------------------------------------------------------------------------- /po/zh_Hans/netspeedtest.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: PACKAGE VERSION\n" 4 | "PO-Revision-Date: 2023-01-09 10:03+0000\n" 5 | "Last-Translator: muink \n" 6 | "Language-Team: Chinese (Simplified) \n" 8 | "Language: zh_Hans\n" 9 | "MIME-Version: 1.0\n" 10 | "Content-Type: text/plain; charset=UTF-8\n" 11 | "Content-Transfer-Encoding: 8bit\n" 12 | "Plural-Forms: nplurals=1; plural=0;\n" 13 | "X-Generator: Weblate 4.12.1-dev\n" 14 | 15 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:66 16 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:66 17 | msgid "Collecting data ..." 18 | msgstr "正在收集数据..." 19 | 20 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:156 21 | msgid "Download" 22 | msgstr "下载" 23 | 24 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:155 25 | msgid "Download Ookla® SpeedTest-CLI" 26 | msgstr "下载 Ookla® SpeedTest-CLI" 27 | 28 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:77 29 | msgid "Download iperf3 client" 30 | msgstr "下载 iperf3 客户端" 31 | 32 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:73 33 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed.js:32 34 | msgid "Enable" 35 | msgstr "启用" 36 | 37 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:77 38 | msgid "Enable HTTP2" 39 | msgstr "启用 HTTP2" 40 | 41 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:81 42 | msgid "Enable TLS" 43 | msgstr "启用 TLS" 44 | 45 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:121 46 | msgid "Enable proxy for downloader and test" 47 | msgstr "为下载器和测试启用代理" 48 | 49 | #: applications/luci-app-netspeedtest/root/usr/share/rpcd/acl.d/luci-app-netspeedtest.json:3 50 | msgid "Grant access to netspeedtest procedures" 51 | msgstr "授予访问 LuCI 应用 netspeedtest 的权限" 52 | 53 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:31 54 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:102 55 | msgid "Installed" 56 | msgstr "已安装" 57 | 58 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:73 59 | msgid "Listen Port" 60 | msgstr "监听端口" 61 | 62 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:50 63 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:82 64 | msgid "No result." 65 | msgstr "无结果." 66 | 67 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:34 68 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:104 69 | msgid "Not Installed" 70 | msgstr "未安装" 71 | 72 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:78 73 | msgid "Official website" 74 | msgstr "官方网站" 75 | 76 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:61 77 | #: applications/luci-app-netspeedtest/root/usr/share/luci/menu.d/luci-app-netspeedtest.json:38 78 | msgid "Ookla SpeedTest" 79 | msgstr "" 80 | 81 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:98 82 | msgid "Ookla® SpeedTest-CLI Status" 83 | msgstr "Ookla® SpeedTest-CLI 状态" 84 | 85 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:124 86 | msgid "Proxy Protocol" 87 | msgstr "代理协议" 88 | 89 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:134 90 | msgid "Proxy Server" 91 | msgstr "代理服务器" 92 | 93 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed.js:41 94 | msgid "" 95 | "Random port (port=0) is not supported.
Change to a fixed port and try " 96 | "again." 97 | msgstr "不支持随机端口 (port=0).
改为固定端口然后再试一次." 98 | 99 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:50 100 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:50 101 | msgid "SERVER NOT RUNNING" 102 | msgstr "服务器未运行" 103 | 104 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:48 105 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:48 106 | msgid "SERVER RUNNING" 107 | msgstr "服务器运行中" 108 | 109 | #: applications/luci-app-netspeedtest/root/usr/share/luci/menu.d/luci-app-netspeedtest.json:3 110 | msgid "SpeedTest" 111 | msgstr "网速测试" 112 | 113 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:89 114 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:90 115 | msgid "Start Test" 116 | msgstr "启动测试" 117 | 118 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:145 119 | msgid "System Arch" 120 | msgstr "系统架构" 121 | 122 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:87 123 | msgid "TLS Cert file" 124 | msgstr "TLS 证书文件" 125 | 126 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:92 127 | msgid "TLS Key file" 128 | msgstr "TLS 密钥文件" 129 | 130 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:47 131 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:79 132 | msgid "Test failed." 133 | msgstr "测试失败." 134 | 135 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:40 136 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:70 137 | msgid "Testing in progress..." 138 | msgstr "测试进行中..." 139 | 140 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:141 141 | msgid "Use Ookla® SpeedTest-CLI" 142 | msgstr "使用 Ookla® SpeedTest-CLI" 143 | 144 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:60 145 | msgid "iperf3 Bandwidth Performance Test" 146 | msgstr "iperf3 带宽性能测试" 147 | 148 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:88 149 | msgid "iperf3 Common commands reference" 150 | msgstr "iperf3 常用命令参考" 151 | 152 | #: applications/luci-app-netspeedtest/root/usr/share/luci/menu.d/luci-app-netspeedtest.json:14 153 | msgid "iperf3 Server" 154 | msgstr "iperf3 服务器" 155 | 156 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:60 157 | #: applications/luci-app-netspeedtest/root/usr/share/luci/menu.d/luci-app-netspeedtest.json:30 158 | msgid "librespeed Config" 159 | msgstr "librespeed 配置" 160 | 161 | #: applications/luci-app-netspeedtest/root/usr/share/luci/menu.d/luci-app-netspeedtest.json:22 162 | msgid "librespeed Server" 163 | msgstr "librespeed 服务器" 164 | 165 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed.js:27 166 | msgid "librespeed Site Speed Test" 167 | msgstr "librespeed 站点速度测试" 168 | -------------------------------------------------------------------------------- /po/zh_Hant/netspeedtest.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: PACKAGE VERSION\n" 4 | "PO-Revision-Date: 2023-01-09 10:03+0000\n" 5 | "Last-Translator: muink \n" 6 | "Language-Team: Chinese (Traditional) \n" 8 | "Language: zh_Hant\n" 9 | "MIME-Version: 1.0\n" 10 | "Content-Type: text/plain; charset=UTF-8\n" 11 | "Content-Transfer-Encoding: 8bit\n" 12 | "Plural-Forms: nplurals=1; plural=0;\n" 13 | "X-Generator: Weblate 4.12.1-dev\n" 14 | 15 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:66 16 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:66 17 | msgid "Collecting data ..." 18 | msgstr "正在收集數據..." 19 | 20 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:156 21 | msgid "Download" 22 | msgstr "下載" 23 | 24 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:155 25 | msgid "Download Ookla® SpeedTest-CLI" 26 | msgstr "下載 Ookla® SpeedTest-CLI" 27 | 28 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:77 29 | msgid "Download iperf3 client" 30 | msgstr "下載 iperf3 用戶端" 31 | 32 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:73 33 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed.js:32 34 | msgid "Enable" 35 | msgstr "啟用" 36 | 37 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:77 38 | msgid "Enable HTTP2" 39 | msgstr "啟用 HTTP2" 40 | 41 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:81 42 | msgid "Enable TLS" 43 | msgstr "HTTP2 TLS" 44 | 45 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:121 46 | msgid "Enable proxy for downloader and test" 47 | msgstr "為下載器和測試啟用代理" 48 | 49 | #: applications/luci-app-netspeedtest/root/usr/share/rpcd/acl.d/luci-app-netspeedtest.json:3 50 | msgid "Grant access to netspeedtest procedures" 51 | msgstr "授予訪問 LuCI 應用 netspeedtest 的權限" 52 | 53 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:31 54 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:102 55 | msgid "Installed" 56 | msgstr "已安裝" 57 | 58 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:73 59 | msgid "Listen Port" 60 | msgstr "監聽埠" 61 | 62 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:50 63 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:82 64 | msgid "No result." 65 | msgstr "無結果." 66 | 67 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:34 68 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:104 69 | msgid "Not Installed" 70 | msgstr "未安裝" 71 | 72 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:78 73 | msgid "Official website" 74 | msgstr "官方網站" 75 | 76 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:61 77 | #: applications/luci-app-netspeedtest/root/usr/share/luci/menu.d/luci-app-netspeedtest.json:38 78 | msgid "Ookla SpeedTest" 79 | msgstr "" 80 | 81 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:98 82 | msgid "Ookla® SpeedTest-CLI Status" 83 | msgstr "Ookla® SpeedTest-CLI 狀態" 84 | 85 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:124 86 | msgid "Proxy Protocol" 87 | msgstr "代理協議" 88 | 89 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:134 90 | msgid "Proxy Server" 91 | msgstr "代理伺服器" 92 | 93 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed.js:41 94 | msgid "" 95 | "Random port (port=0) is not supported.
Change to a fixed port and try " 96 | "again." 97 | msgstr "不支持隨機連接埠 (port=0).
改為固定埠號然後再試一次." 98 | 99 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:50 100 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:50 101 | msgid "SERVER NOT RUNNING" 102 | msgstr "伺服器未運行" 103 | 104 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:48 105 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:48 106 | msgid "SERVER RUNNING" 107 | msgstr "伺服器運行中" 108 | 109 | #: applications/luci-app-netspeedtest/root/usr/share/luci/menu.d/luci-app-netspeedtest.json:3 110 | msgid "SpeedTest" 111 | msgstr "網速測試" 112 | 113 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:89 114 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:90 115 | msgid "Start Test" 116 | msgstr "啟動測試" 117 | 118 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:145 119 | msgid "System Arch" 120 | msgstr "系統架構" 121 | 122 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:87 123 | msgid "TLS Cert file" 124 | msgstr "TLS 憑證檔案" 125 | 126 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:92 127 | msgid "TLS Key file" 128 | msgstr "TLS 密鑰檔案" 129 | 130 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:47 131 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:79 132 | msgid "Test failed." 133 | msgstr "測試失敗." 134 | 135 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:40 136 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:70 137 | msgid "Testing in progress..." 138 | msgstr "測試進行中..." 139 | 140 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/speedtest.js:141 141 | msgid "Use Ookla® SpeedTest-CLI" 142 | msgstr "使用 Ookla® SpeedTest-CLI" 143 | 144 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:60 145 | msgid "iperf3 Bandwidth Performance Test" 146 | msgstr "iperf3 帶寬性能測試" 147 | 148 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/iperf3.js:88 149 | msgid "iperf3 Common commands reference" 150 | msgstr "iperf3 常用命令參考" 151 | 152 | #: applications/luci-app-netspeedtest/root/usr/share/luci/menu.d/luci-app-netspeedtest.json:14 153 | msgid "iperf3 Server" 154 | msgstr "iperf3 伺服器" 155 | 156 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed-cfg.js:60 157 | #: applications/luci-app-netspeedtest/root/usr/share/luci/menu.d/luci-app-netspeedtest.json:30 158 | msgid "librespeed Config" 159 | msgstr "librespeed 組態" 160 | 161 | #: applications/luci-app-netspeedtest/root/usr/share/luci/menu.d/luci-app-netspeedtest.json:22 162 | msgid "librespeed Server" 163 | msgstr "librespeed 伺服器" 164 | 165 | #: applications/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/librespeed.js:27 166 | msgid "librespeed Site Speed Test" 167 | msgstr "librespeed 站點速度測試" 168 | -------------------------------------------------------------------------------- /root/etc/init.d/netspeedtest: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | # Copyright (C) 2023 muink 3 | # 4 | 5 | . "${IPKG_INSTROOT}/lib/functions.sh" 6 | 7 | START=99 8 | USE_PROCD=1 9 | 10 | EXTRA_COMMANDS="download_ookla ookla_verify" 11 | EXTRA_HELP=\ 12 | " download_ookla Download Ookla Speedtest-CLI 13 | ookla_verify Verify Ookla Speedtest-CLI integrity" 14 | 15 | # 16 | OOKLA_SPEEDTEST='/usr/libexec/netspeedtest/speedtest' 17 | # uci 18 | CONFIG_NAME='netspeedtest' 19 | NAMEDDSECTION='config' 20 | 21 | 22 | 23 | iperf3_instance() { 24 | procd_open_instance "iperf3" 25 | procd_set_param command "iperf3" 26 | procd_append_param command -s 27 | procd_set_param respawn 28 | procd_set_param user nobody 29 | procd_set_param stdout 1 30 | procd_set_param stderr 1 31 | procd_close_instance 32 | } 33 | 34 | librespeed_instance() { 35 | local action="$1" 36 | 37 | case "$action" in 38 | start) 39 | uci set librespeed-go.config.enabled='1' 40 | uci commit librespeed-go 41 | /etc/init.d/librespeed-go reload 42 | ;; 43 | stop) 44 | uci set librespeed-go.config.enabled='0' 45 | uci commit librespeed-go 46 | /etc/init.d/librespeed-go reload 47 | ;; 48 | esac 49 | } 50 | 51 | kill_instance() { 52 | local instance="$1" 53 | pgrep -f "$instance" | xargs kill -9 >/dev/null 2>&1 54 | return 0 55 | } 56 | 57 | download_ookla() { 58 | local url arch=$1 59 | [ -z "$arch" ] && return 1 60 | 61 | [ "$(uci -q get $CONFIG_NAME.$NAMEDDSECTION.proxy_enabled)" == "1" ] && \ 62 | export ALL_PROXY=$(uci -q get $CONFIG_NAME.$NAMEDDSECTION.proxy_protocol)://$(uci -q get $CONFIG_NAME.$NAMEDDSECTION.proxy_server) 63 | 64 | UA='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36' 65 | url=$( \ 66 | curl --connect-timeout 10 --retry 3 -sSL 'https://www.speedtest.net/apps/cli' \ 67 | --user-agent "$UA" \ 68 | | grep "Download for Linux" \ 69 | | sed 's|<|\n<|g' \ 70 | | sed -n '/Download for Linux/,/<\/div>/p' \ 71 | | sed -En "s|.*${arch}|\1|p" \ 72 | ) 73 | [ -z "$url" ] && return 1 74 | 75 | [ -n "$url" ] && curl -sSL $url --user-agent "$UA" | tar -xvz -C /tmp 76 | mkdir -p ${OOKLA_SPEEDTEST%/*} 2>/dev/null 77 | cp -f /tmp/speedtest $OOKLA_SPEEDTEST 78 | chmod 755 $OOKLA_SPEEDTEST 79 | ookla_verify || rm -f $OOKLA_SPEEDTEST 80 | unset ALL_PROXY 81 | } 82 | 83 | ookla_verify() { 84 | if [ -x "$OOKLA_SPEEDTEST" ]; then 85 | return 0 86 | else 87 | return 1 88 | fi 89 | } 90 | 91 | start_service() { 92 | local eniperf3 enlibrespeed 93 | 94 | config_load "$CONFIG_NAME" 95 | eval "eniperf3=\$CONFIG_${NAMEDDSECTION}_iperf3_enabled" 96 | eval "enlibrespeed=\$CONFIG_${NAMEDDSECTION}_librespeed_enabled" 97 | 98 | [ "$eniperf3" == "1" ] && iperf3_instance 99 | [ "${enlibrespeed:=0}" == "0" ] && librespeed_instance stop || librespeed_instance start 100 | } 101 | 102 | service_triggers() { 103 | procd_add_reload_trigger "$CONFIG_NAME" 'librespeed-go' 'network' 104 | } 105 | 106 | stop_service() { 107 | uci -q batch <<-EOF 108 | set $CONFIG_NAME.$NAMEDDSECTION.iperf3_enabled='0' 109 | set $CONFIG_NAME.$NAMEDDSECTION.librespeed_enabled='0' 110 | commit $CONFIG_NAME 111 | EOF 112 | librespeed_instance stop 113 | } 114 | 115 | restart() { 116 | start 117 | } 118 | -------------------------------------------------------------------------------- /root/etc/uci-defaults/99_netspeedtest: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | touch /etc/config/netspeedtest 3 | uci -q batch <<-EOF >/dev/null 4 | set netspeedtest.config=netspeedtest 5 | commit netspeedtest 6 | EOF 7 | -------------------------------------------------------------------------------- /root/usr/lib/netspeedtest/speedtest: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright (C) 2023 muink 3 | # 4 | OOKLA_SPEEDTEST='/usr/libexec/netspeedtest/speedtest' 5 | SPEEDTEST_RESULT='/var/speedtest_result' 6 | INIT_SCRIPT='/etc/init.d/netspeedtest' 7 | # uci 8 | CONFIG_NAME='netspeedtest' 9 | NAMEDDSECTION='config' 10 | 11 | 12 | command="speedtest --share" 13 | if [ "$(uci -q get $CONFIG_NAME.$NAMEDDSECTION.ookla_official)" == "1" ]; then 14 | $INIT_SCRIPT ookla_verify 15 | if [ "$?" == "0" ]; then 16 | command="$OOKLA_SPEEDTEST --accept-gdpr --accept-license --progress=no" 17 | else 18 | uci set $CONFIG_NAME.$NAMEDDSECTION.ookla_official=0 19 | uci commit $CONFIG_NAME 20 | fi 21 | fi 22 | 23 | [ -n "$(pgrep -f "$command")" ] && return 1 24 | 25 | [ "$(uci -q get $CONFIG_NAME.$NAMEDDSECTION.proxy_enabled)" == "1" ] && \ 26 | export ALL_PROXY=$(uci -q get $CONFIG_NAME.$NAMEDDSECTION.proxy_protocol)://$(uci -q get $CONFIG_NAME.$NAMEDDSECTION.proxy_server) 27 | 28 | echo "Testing" > "$SPEEDTEST_RESULT" 29 | result=$($command | grep 'www.speedtest.net/result/' | sed -E 's|.+(://www.speedtest.net/\S+).*|https\1|;s|(\.png)$||') 30 | [ -n "$result" ] && echo "$result" > "$SPEEDTEST_RESULT" || echo "Test failed" > "$SPEEDTEST_RESULT" 31 | -------------------------------------------------------------------------------- /root/usr/share/luci/menu.d/luci-app-netspeedtest.json: -------------------------------------------------------------------------------- 1 | { 2 | "admin/network/netspeedtest": { 3 | "title": "SpeedTest", 4 | "order": 55, 5 | "action": { 6 | "type": "firstchild" 7 | }, 8 | "depends": { 9 | "acl": [ "luci-app-netspeedtest" ], 10 | "uci": { "netspeedtest": true } 11 | } 12 | }, 13 | "admin/network/netspeedtest/iperf3": { 14 | "title": "iperf3 Server", 15 | "order": 1, 16 | "action": { 17 | "type": "view", 18 | "path": "netspeedtest/iperf3" 19 | } 20 | }, 21 | "admin/network/netspeedtest/librespeed": { 22 | "title": "librespeed Server", 23 | "order": 2, 24 | "action": { 25 | "type": "view", 26 | "path": "netspeedtest/librespeed" 27 | } 28 | }, 29 | "admin/network/netspeedtest/librespeed-cfg": { 30 | "title": "librespeed Config", 31 | "order": 3, 32 | "action": { 33 | "type": "view", 34 | "path": "netspeedtest/librespeed-cfg" 35 | } 36 | }, 37 | "admin/network/netspeedtest/speedtest": { 38 | "title": "Ookla SpeedTest", 39 | "order": 4, 40 | "action": { 41 | "type": "view", 42 | "path": "netspeedtest/speedtest" 43 | } 44 | }, 45 | "admin/network/netspeedtest/openspeedtest": { 46 | "title": "OpenSpeedTest", 47 | "order": 5, 48 | "action": { 49 | "type": "view", 50 | "path": "netspeedtest/openspeedtest" 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /root/usr/share/rpcd/acl.d/luci-app-netspeedtest.json: -------------------------------------------------------------------------------- 1 | { 2 | "luci-app-netspeedtest": { 3 | "description": "Grant access to netspeedtest procedures", 4 | "read": { 5 | "file": { 6 | "/etc/init.d/netspeedtest": [ "exec" ], 7 | "/usr/lib/netspeedtest/speedtest": [ "exec" ], 8 | "/var/speedtest_result": [ "read" ] 9 | }, 10 | "ubus": { 11 | "service": [ "list" ] 12 | }, 13 | "uci": [ "netspeedtest", "librespeed-go" ] 14 | }, 15 | "write": { 16 | "uci": [ "netspeedtest", "librespeed-go" ] 17 | } 18 | } 19 | } 20 | --------------------------------------------------------------------------------