update 2025-05-14 04:25:50
This commit is contained in:
parent
310e9dd234
commit
445f0b7a67
|
@ -9,8 +9,8 @@ include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=luci-app-netspeedtest
|
PKG_NAME:=luci-app-netspeedtest
|
||||||
|
|
||||||
PKG_VERSION:=5.0.1
|
PKG_VERSION:=5.0.2
|
||||||
PKG_RELEASE:=20250512
|
PKG_RELEASE:=20250513
|
||||||
|
|
||||||
LUCI_TITLE:=LuCI Support for netspeedtest
|
LUCI_TITLE:=LuCI Support for netspeedtest
|
||||||
LUCI_DEPENDS:=+speedtest-cli +homebox +iperf3-ssl
|
LUCI_DEPENDS:=+speedtest-cli +homebox +iperf3-ssl
|
||||||
|
|
|
@ -30,7 +30,7 @@ return view.extend({
|
||||||
|
|
||||||
var iframe = E('iframe', {
|
var iframe = E('iframe', {
|
||||||
src: window.location.origin + ':' + state.port,
|
src: window.location.origin + ':' + state.port,
|
||||||
style: 'width: 100%; min-height: 80vh; border: none; border-radius: 3px;'
|
style: 'border:none;width: 100%; min-height: 80vh; border: none; border-radius: 3px;overflow:hidden !important;'
|
||||||
});
|
});
|
||||||
|
|
||||||
function checkProcess() {
|
function checkProcess() {
|
||||||
|
@ -42,7 +42,7 @@ return view.extend({
|
||||||
|
|
||||||
function controlService(action) {
|
function controlService(action) {
|
||||||
var command = action === 'start'
|
var command = action === 'start'
|
||||||
? 'nohup /usr/bin/homebox > /tmp/homebox.log 2>&1 &'
|
? 'nohup /usr/bin/homebox > /tmp/netspeedtest.log 2>&1 &'
|
||||||
: '/usr/bin/killall homebox';
|
: '/usr/bin/killall homebox';
|
||||||
return fs.exec('/bin/sh', ['-c', command]);
|
return fs.exec('/bin/sh', ['-c', command]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ var state = {
|
||||||
port: null
|
port: null
|
||||||
};
|
};
|
||||||
|
|
||||||
const logPath = '/var/log/iperf3.log';
|
const logPath = '/tmp/netspeedtest.log';
|
||||||
|
|
||||||
function checkProcess() {
|
function checkProcess() {
|
||||||
return fs.exec('/bin/pidof', ['iperf3']).then(res => ({
|
return fs.exec('/bin/pidof', ['iperf3']).then(res => ({
|
||||||
|
@ -172,7 +172,7 @@ const statusSection = E('div', { 'class': 'cbi-section' }, [
|
||||||
return E('div', [
|
return E('div', [
|
||||||
statusSection,
|
statusSection,
|
||||||
E('div', { 'class': 'cbi-section' }, [
|
E('div', { 'class': 'cbi-section' }, [
|
||||||
E('h3', {}, _('Iperf3 Run Log')),
|
E('h3', {}, _('Run Log')),
|
||||||
logTextarea,
|
logTextarea,
|
||||||
E('div', { 'style': 'text-align: right; font-size: small; margin-top: 5px;' },
|
E('div', { 'style': 'text-align: right; font-size: small; margin-top: 5px;' },
|
||||||
_('Refresh every 5 seconds.')
|
_('Refresh every 5 seconds.')
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* Copyright (C) 2021-2025 sirpdboy herboy2008@gmail.com https://github.com/sirpdboy/luci-app-netspeedtest */
|
||||||
'use strict';
|
'use strict';
|
||||||
'require dom';
|
'require dom';
|
||||||
'require fs';
|
'require fs';
|
||||||
|
@ -11,76 +12,87 @@ var logTextarea;
|
||||||
var log_path;
|
var log_path;
|
||||||
|
|
||||||
uci.load('netspeedtest').then(function() {
|
uci.load('netspeedtest').then(function() {
|
||||||
log_path = '/var/log/netspeedtest.log';
|
log_path = '/tmp/netspeedtest.log';
|
||||||
});
|
});
|
||||||
|
|
||||||
function pollLog() {
|
function pollLog() {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
fs.read_direct(log_path, 'text').then(function (res) {
|
fs.read_direct(log_path, 'text').then(function(res) {
|
||||||
return res.trim().split(/\n/).join('\n').replace(/\u001b\[33mWARN\u001b\[0m/g, '').replace(/\u001b\[36mINFO\u001b\[0m/g, '').replace(/\u001b\[31mERRO\u001b\[0m/g, '');
|
return res.trim()
|
||||||
}),
|
.split(/\n/).join('\n')
|
||||||
]).then(function (data) {
|
.replace(/\u001b\[33mWARN\u001b\[0m/g, '')
|
||||||
logTextarea.value = data[0] || _('No log data.');
|
.replace(/\u001b\[36mINFO\u001b\[0m/g, '')
|
||||||
|
.replace(/\u001b\[31mERRO\u001b\[0m/g, '');
|
||||||
|
}),
|
||||||
|
]).then(function(data) {
|
||||||
|
logTextarea.value = data[0] || _('No log data.');
|
||||||
|
|
||||||
if (!userScrolled) {
|
if (!userScrolled) {
|
||||||
logTextarea.scrollTop = logTextarea.scrollHeight;
|
logTextarea.scrollTop = logTextarea.scrollHeight;
|
||||||
} else {
|
} else {
|
||||||
logTextarea.scrollTop = scrollPosition;
|
logTextarea.scrollTop = scrollPosition;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
return view.extend({
|
return view.extend({
|
||||||
handleCleanLogs: function () {
|
handleCleanLogs: function() {
|
||||||
return fs.write(log_path, '')
|
return fs.write(log_path, '')
|
||||||
.catch(function (e) { ui.addNotification(null, E('p', e.message)) });
|
.catch(function(e) {
|
||||||
},
|
ui.addNotification(null, E('p', e.message))
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
render: function () {
|
render: function() {
|
||||||
logTextarea = E('textarea', {
|
logTextarea = E('textarea', {
|
||||||
'class': 'cbi-input-textarea',
|
'class': 'cbi-input-textarea',
|
||||||
'wrap': 'off',
|
'wrap': 'off',
|
||||||
'readonly': 'readonly',
|
'readonly': 'readonly',
|
||||||
'style': 'width: calc(100% - 20px);height: 535px;margin: 10px;overflow-y: scroll;',
|
'style': 'width: calc(100% - 20px); height: 535px; margin: 10px; overflow-y: scroll;'
|
||||||
});
|
});
|
||||||
|
|
||||||
logTextarea.addEventListener('scroll', function () {
|
logTextarea.addEventListener('scroll', function() {
|
||||||
userScrolled = true;
|
userScrolled = true;
|
||||||
scrollPosition = logTextarea.scrollTop;
|
scrollPosition = logTextarea.scrollTop;
|
||||||
});
|
});
|
||||||
|
|
||||||
var log_textarea_wrapper = E('div', { 'id': 'log_textarea' }, logTextarea);
|
var log_textarea_wrapper = E('div', { 'id': 'log_textarea' }, logTextarea);
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function() {
|
||||||
poll.add(pollLog);
|
poll.add(pollLog);
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
var clear_logs_button = E('input', { 'class': 'btn cbi-button-action', 'type': 'button', 'style': 'margin-left: 10px; margin-top: 10px;', 'value': _('Clear logs') });
|
var clear_logs_button = E('input', {
|
||||||
clear_logs_button.addEventListener('click', this.handleCleanLogs.bind(this));
|
'class': 'btn cbi-button-action',
|
||||||
|
'type': 'button',
|
||||||
|
'style': 'margin-left: 20px; margin-top: 10px;',
|
||||||
|
'value': _('Clear logs')
|
||||||
|
});
|
||||||
|
clear_logs_button.addEventListener('click', this.handleCleanLogs.bind(this));
|
||||||
|
|
||||||
return E([
|
return E('div', { 'class': 'cbi-map' }, [
|
||||||
E('div', { 'class': 'cbi-map' }, [
|
E('div', { 'class': 'cbi-section' }, [
|
||||||
E('div', { 'class': 'cbi-section' }, [
|
clear_logs_button,
|
||||||
clear_logs_button,
|
log_textarea_wrapper,
|
||||||
log_textarea_wrapper,
|
E('div', { 'style': 'text-align: right' }, [
|
||||||
E('div', { 'style': 'text-align:right' },
|
E('small', {}, _('Refresh every %s seconds.').format(L.env.pollinterval))
|
||||||
E('small', {}, _('Refresh every %s seconds.').format(L.env.pollinterval)),
|
]),
|
||||||
E('div', { 'class': 'cbi-section-actions cbi-section-actions-right' })
|
E('div', { 'class': 'cbi-section-actions cbi-section-actions-right' })
|
||||||
]),
|
]),
|
||||||
E('div', { 'style': 'text-align: right; font-style: italic;' }, [
|
E('div', { 'style': 'text-align: right; font-style: italic; margin-top: 10px;' }, [
|
||||||
E('span', {}, [
|
E('span', {}, [
|
||||||
_('© github '),
|
_('© github '),
|
||||||
E('a', {
|
E('a', {
|
||||||
'href': 'https://github.com/sirpdboy',
|
'href': 'https://github.com/sirpdboy',
|
||||||
'target': '_blank',
|
'target': '_blank',
|
||||||
'style': 'text-decoration: none;'
|
'style': 'text-decoration: none;'
|
||||||
}, 'by sirpdboy')
|
}, 'by sirpdboy')
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleSaveApply: null,
|
// handleSaveApply: null,
|
||||||
// handleSave: null,
|
// handleSave: null,
|
||||||
// handleReset: null
|
// handleReset: null
|
||||||
});
|
});
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* Copyright (C) 2021-2025 sirpdboy herboy2008@gmail.com https://github.com/sirpdboy/luci-app-netspeedtest */
|
||||||
'use strict';
|
'use strict';
|
||||||
'require view';
|
'require view';
|
||||||
'require uci';
|
'require uci';
|
||||||
|
@ -22,7 +23,7 @@ return view.extend({
|
||||||
s.render = function (section_id) {
|
s.render = function (section_id) {
|
||||||
return E('iframe', {
|
return E('iframe', {
|
||||||
src: '//openspeedtest.com/speedtest',
|
src: '//openspeedtest.com/speedtest',
|
||||||
style: 'border:none;width:100%;height:100%;min-height:360px;border:none;overflow:hidden !important;'
|
style: 'width:100%;height:100%;min-height:360px;border:none;overflow:hidden !important;'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* Copyright (C) 2021-2025 sirpdboy herboy2008@gmail.com https://github.com/sirpdboy/luci-app-netspeedtest */
|
||||||
'use strict';
|
'use strict';
|
||||||
'require view';
|
'require view';
|
||||||
'require poll';
|
'require poll';
|
||||||
|
@ -17,7 +18,7 @@ return view.extend({
|
||||||
// handleSaveApply: null,
|
// handleSaveApply: null,
|
||||||
// handleSave: null,
|
// handleSave: null,
|
||||||
// handleReset: null,
|
// handleReset: null,
|
||||||
load: function () {
|
load() {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
L.resolveDefault(fs.stat(SpeedtestCli), {}),
|
L.resolveDefault(fs.stat(SpeedtestCli), {}),
|
||||||
L.resolveDefault(fs.read(ResultFile), null),
|
L.resolveDefault(fs.read(ResultFile), null),
|
||||||
|
@ -26,76 +27,94 @@ return view.extend({
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|
||||||
poll_status: function (nodes, res) {
|
poll_status(nodes, res) {
|
||||||
var has_ookla = res[0].path,
|
var has_ookla = res[0].path,
|
||||||
result_content = res[1] ? res[1].trim().split("\n") : [];
|
result_content = res[1] ? res[1].trim().split("\n") : [];
|
||||||
var ookla_stat = nodes.querySelector('#ookla_status'),
|
var ookla_stat = nodes.querySelector('#ookla_status'),
|
||||||
result_stat = nodes.querySelector('#speedtest_result');
|
result_stat = nodes.querySelector('#speedtest_result');
|
||||||
|
|
||||||
// Update status indicators
|
// 获取版本号(新增部分)
|
||||||
ookla_stat.style.color = has_ookla ? 'green' : 'red';
|
var version_info = '';
|
||||||
dom.content(ookla_stat, [_(has_ookla ? 'Installed' : 'Not Installed')]);
|
if (has_ookla) {
|
||||||
|
fs.exec_direct('/usr/bin/speedtest', ['--version'])
|
||||||
// Update result display
|
.then(function(res) {
|
||||||
if (result_content.length) {
|
if (res.stdout) {
|
||||||
if (result_content[0] == 'Testing') {
|
var version_match = res.stdout.match(/Speedtest (\d+\.\d+\.\d+)/);
|
||||||
result_stat.innerHTML = "<span style='color:green;font-weight:bold'>" +
|
if (version_match) {
|
||||||
"<img src='/luci-static/resources/icons/loading.gif' height='17' style='vertical-align:middle'/> " +
|
version_info = ' ver:' + version_match[1];
|
||||||
_('Testing in progress...') +
|
}
|
||||||
"</span>";
|
}
|
||||||
} else if (result_content[0].match(/https?:\S+/)) {
|
// 更新状态显示(包含版本号)
|
||||||
result_stat.innerHTML = "<div style='max-width:500px'><a href='" +
|
ookla_stat.style.color = 'green';
|
||||||
result_content[0] + "' target='_blank'><img src='" +
|
dom.content(ookla_stat, [_(has_ookla ? 'Installed' + version_info : 'Not Installed')]);
|
||||||
result_content[0] + '.png' + "' style='max-width:100%'></a></div>";
|
})
|
||||||
} else if (result_content[0] == 'Test failed') {
|
.catch(function() {
|
||||||
result_stat.innerHTML = "<span style='color:red;font-weight:bold'>" +
|
// 如果获取版本失败,仍显示基本状态
|
||||||
_('Test failed.') + "</span>";
|
ookla_stat.style.color = has_ookla ? 'green' : 'red';
|
||||||
}
|
dom.content(ookla_stat, [_(has_ookla ? 'Installed' : 'Not Installed')]);
|
||||||
} else {
|
});
|
||||||
result_stat.innerHTML = "<span style='color:gray'>" +
|
} else {
|
||||||
_('No test results yet.') + "</span>";
|
// 未安装时的显示保持不变
|
||||||
|
ookla_stat.style.color = 'red';
|
||||||
|
dom.content(ookla_stat, [_('Not Installed')]);
|
||||||
|
}
|
||||||
|
if (result_content.length) {
|
||||||
|
if (result_content[0] == 'Testing') {
|
||||||
|
result_stat.innerHTML = "<span style='color:green;font-weight:bold'>" +
|
||||||
|
"<img src='/luci-static/resources/icons/loading.gif' height='17' style='vertical-align:middle ;margin-left:20px'/> " +
|
||||||
|
_('SpeedTesting in progress...') +
|
||||||
|
"</span>";
|
||||||
|
} else if (result_content[0].match(/https?:\S+/)) {
|
||||||
|
result_stat.innerHTML = "<div style='max-width:500px'><a href='" +
|
||||||
|
result_content[0] + "' target='_blank'><img src='" +
|
||||||
|
result_content[0] + '.png' + "' style='max-width:100%;margin-left:20px'></a></div>";
|
||||||
|
} else if (result_content[0] == 'Test failed') {
|
||||||
|
result_stat.innerHTML = "<span style='color:red;font-weight:bold;margin-left:20px'>" +
|
||||||
|
_('Test failed.') + "</span>";
|
||||||
}
|
}
|
||||||
},
|
} else {
|
||||||
|
result_stat.innerHTML = "<span style='color:gray;margin-left:20px'>" +
|
||||||
|
_('No test results yet.') + "</span>";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
render: function (res) {
|
render(res) {
|
||||||
var has_ookla = res[0].path,
|
var has_ookla = res[0].path,
|
||||||
result_content = res[1] ? res[1].trim().split("\n") : [],
|
result_content = res[1] ? res[1].trim().split("\n") : [],
|
||||||
result_mtime = res[2] ? res[2].mtime * 1000 : 0,
|
result_mtime = res[2] ? res[2].mtime * 1000 : 0,
|
||||||
date = new Date();
|
date = new Date();
|
||||||
|
|
||||||
var m, s, o;
|
var m, s, o;
|
||||||
m = new form.Map('netspeedtest', _('WAN Ookla SpeedTest'));
|
m = new form.Map('netspeedtest', _('Wan Ookla SpeedTest'));
|
||||||
|
|
||||||
// Result display section
|
// Result display section
|
||||||
s = m.section(form.TypedSection, '_result');
|
s = m.section(form.TypedSection, '_result');
|
||||||
s.anonymous = true;
|
s.anonymous = true;
|
||||||
s.render = function () {
|
s.render = function (section_id) {
|
||||||
var content;
|
if (result_content.length) {
|
||||||
if (result_content.length) {
|
if (result_content[0] == 'Testing') {
|
||||||
if (result_content[0] == 'Testing') {
|
return E('div', { 'id': 'speedtest_result' }, [ E('span', { 'style': 'color:yellow;font-weight:bold' }, [
|
||||||
content = E('span', { style: 'color:green;font-weight:bold' }, [
|
E('img', { 'src': L.resource(['icons/loading.gif']), 'height': '20', 'style': 'vertical-align:middle' }, []),
|
||||||
E('img', { src: '/luci-static/resources/icons/loading.gif', height: '20' }),
|
_('Testing in progress...')
|
||||||
' ', _('Testing in progress...')
|
]) ])
|
||||||
]);
|
};
|
||||||
} else if (result_content[0].match(/https?:\S+/)) {
|
if (result_content[0].match(/https?:\S+/)) {
|
||||||
content = E('div', { style: 'max-width:500px' }, [
|
return E('div', { 'id': 'speedtest_result' }, [ E('div', { 'style': 'max-width:500px' }, [
|
||||||
E('a', { href: result_content[0], target: '_blank' }, [
|
E('a', { 'href': result_content[0], 'target': '_blank' }, [
|
||||||
E('img', { src: result_content[0] + '.png', style: 'max-width:100%' })
|
E('img', { 'src': result_content[0] + '.png', 'style': 'max-width:100%;max-height:100%;vertical-align:middle' }, [])
|
||||||
])
|
]) ]) ])
|
||||||
]);
|
};
|
||||||
} else {
|
if (result_content[0] == 'Test failed') {
|
||||||
content = E('span', { style: 'color:red;font-weight:bold' },
|
return E('div', { 'id': 'speedtest_result' }, [ E('span', { 'style': 'color:red;font-weight:bold' }, [ _('Test failed.') ]) ])
|
||||||
_('Test failed.'));
|
}
|
||||||
}
|
} else {
|
||||||
} else {
|
return E('div', { 'id': 'speedtest_result' }, [ E('span', { 'style': 'color:red;font-weight:bold;display:none' }, [ _('No result.') ]) ])
|
||||||
content = E('span', { style: 'color:gray' },
|
}
|
||||||
_('No test results yet.'));
|
};
|
||||||
}
|
|
||||||
return E('div', { id: 'speedtest_result' }, content);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Configuration section
|
// Configuration section
|
||||||
s = m.section(form.NamedSection, 'config', 'netspeedtest');
|
s = m.section(form.NamedSection, 'config', 'netspeedtest');
|
||||||
|
s.anonymous = true;
|
||||||
|
|
||||||
// Start test button
|
// Start test button
|
||||||
o = s.option(form.Button, '_start', _('Start Ookla SpeedTest'));
|
o = s.option(form.Button, '_start', _('Start Ookla SpeedTest'));
|
||||||
|
|
|
@ -17,7 +17,7 @@ msgid "NetSpeedtest"
|
||||||
msgstr "网速测试"
|
msgstr "网速测试"
|
||||||
|
|
||||||
msgid "A tool for testing network speed in multiple aspects"
|
msgid "A tool for testing network speed in multiple aspects"
|
||||||
msgstr "一个用于从多方面测试本地和宽带网络速度的工具"
|
msgstr "一个用于从多方面测试本地和宽带网络速度的测速工具"
|
||||||
|
|
||||||
msgid "Lan Speedtest Iperf3"
|
msgid "Lan Speedtest Iperf3"
|
||||||
msgstr "本地iperf3吞吐测速"
|
msgstr "本地iperf3吞吐测速"
|
||||||
|
@ -26,7 +26,7 @@ msgid "Lan Speedtest Homebox"
|
||||||
msgstr "本地homebox网页测速"
|
msgstr "本地homebox网页测速"
|
||||||
|
|
||||||
msgid "Wan Ookla SpeedTest"
|
msgid "Wan Ookla SpeedTest"
|
||||||
msgstr "宽带Ookla网速测速"
|
msgstr "宽带Ookla网速测试"
|
||||||
|
|
||||||
msgid "Wan OpenSpeedTest"
|
msgid "Wan OpenSpeedTest"
|
||||||
msgstr "宽带OpenSpeedTest测速"
|
msgstr "宽带OpenSpeedTest测速"
|
||||||
|
@ -79,8 +79,8 @@ msgstr "开启日志显示"
|
||||||
msgid "Download iperf3 client"
|
msgid "Download iperf3 client"
|
||||||
msgstr "下载iperf3客户端"
|
msgstr "下载iperf3客户端"
|
||||||
|
|
||||||
msgid "Iperf3 Run Log"
|
msgid "Run Log"
|
||||||
msgstr "Iperf3运行日志"
|
msgstr "运行日志"
|
||||||
|
|
||||||
msgid "Refresh Log"
|
msgid "Refresh Log"
|
||||||
msgstr "刷新日志"
|
msgstr "刷新日志"
|
||||||
|
@ -109,8 +109,8 @@ msgstr "开始宽带测速"
|
||||||
msgid "Click to execute"
|
msgid "Click to execute"
|
||||||
msgstr "点击执行"
|
msgstr "点击执行"
|
||||||
|
|
||||||
msgid "Testing in progress..."
|
msgid "SpeedTesting in progress..."
|
||||||
msgstr "测试正在进行中..."
|
msgstr "测速中,请稍候..."
|
||||||
|
|
||||||
msgid "Test failed."
|
msgid "Test failed."
|
||||||
msgstr "测速失败"
|
msgstr "测速失败"
|
||||||
|
|
|
@ -6,67 +6,72 @@
|
||||||
START=99
|
START=99
|
||||||
USE_PROCD=1
|
USE_PROCD=1
|
||||||
|
|
||||||
EXTRA_COMMANDS="download_ookla ookla_verify"
|
EXTRA_COMMANDS="download verify"
|
||||||
EXTRA_HELP=\
|
EXTRA_HELP=\
|
||||||
" download_ookla Download Ookla Speedtest-CLI
|
" download Download Ookla Speedtest-CLI
|
||||||
ookla_verify Verify Ookla Speedtest-CLI integrity"
|
verify Verify Ookla Speedtest-CLI integrity"
|
||||||
|
|
||||||
#
|
|
||||||
OOKLA_SPEEDTEST='/usr/bin/speedtest'
|
OOKLA_SPEEDTEST='/usr/bin/speedtest'
|
||||||
# uci
|
|
||||||
CONFIG='netspeedtest'
|
CONFIG='netspeedtest'
|
||||||
NAMEDDSECTION='config'
|
log='/tmp/netspeedtest.log'
|
||||||
|
|
||||||
get_config() {
|
download() {
|
||||||
config_load netspeedtest
|
. /etc/openwrt_release
|
||||||
config_get "proxy_enabled" "config" "proxy_enabled" "0"
|
local url arch=$1
|
||||||
|
local proxy=$2
|
||||||
|
[ -z "$arch" ] && arch=$DISTRIB_ARCH
|
||||||
|
[ -z "$proxy" ] && proxy='0'
|
||||||
|
|
||||||
|
[ "$proxy" == "1" ] && export ALL_PROXY="http://192.168.10.8:1080"
|
||||||
|
|
||||||
|
UA='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36'
|
||||||
|
url=$( \
|
||||||
|
curl --connect-timeout 10 --retry 3 -sSL 'https://www.speedtest.net/apps/cli' \
|
||||||
|
--user-agent "$UA" \
|
||||||
|
| grep "Download for Linux" \
|
||||||
|
| sed 's|<|\n<|g' \
|
||||||
|
| sed -n '/Download for Linux/,/<\/div>/p' \
|
||||||
|
| sed -En "s|.*<a href=\"([^\"]+)\">${arch}|\1|p" \
|
||||||
|
)
|
||||||
|
[ -z "$url" ] && { echo "Failed to get download URL" >> "$log"; return 1; }
|
||||||
|
|
||||||
|
# Backup existing file
|
||||||
|
[ -f "$OOKLA_SPEEDTEST" ] && mv "$OOKLA_SPEEDTEST" "${OOKLA_SPEEDTEST}.bak"
|
||||||
|
|
||||||
|
if curl -sSL "$url" --user-agent "$UA" | tar -xvz -C /tmp; then
|
||||||
|
mkdir -p "${OOKLA_SPEEDTEST%/*}" 2>/dev/null
|
||||||
|
cp -f /tmp/speedtest "$OOKLA_SPEEDTEST"
|
||||||
|
rm -rf /tmp/speedtest
|
||||||
|
chmod 755 "$OOKLA_SPEEDTEST"
|
||||||
|
|
||||||
|
if verify; then
|
||||||
|
echo "Download successful: $($OOKLA_SPEEDTEST --version | awk '/Speedtest/{print $1" ver:"$4}')" >> "$log"
|
||||||
|
else
|
||||||
|
echo "Download failed: binary verification failed" >> "$log"
|
||||||
|
[ -f "${OOKLA_SPEEDTEST}.bak" ] && mv "${OOKLA_SPEEDTEST}.bak" "$OOKLA_SPEEDTEST"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Download failed: could not retrieve package" >> "$log"
|
||||||
|
[ -f "${OOKLA_SPEEDTEST}.bak" ] && mv "${OOKLA_SPEEDTEST}.bak" "$OOKLA_SPEEDTEST"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
unset ALL_PROXY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
verify() {
|
||||||
download_ookla() {
|
[ -x "$OOKLA_SPEEDTEST" ] && "$OOKLA_SPEEDTEST" --version >/dev/null 2>&1
|
||||||
local url arch=$1
|
|
||||||
[ -z "$arch" ] && return 1
|
|
||||||
|
|
||||||
[ "$(uci -q get $CONFIG.$NAMEDDSECTION.proxy_enabled)" == "1" ] && \
|
|
||||||
export ALL_PROXY=$(uci -q get $CONFIG.$NAMEDDSECTION.proxy_protocol)://$(uci -q get $CONFIG.$NAMEDDSECTION.proxy_server)
|
|
||||||
|
|
||||||
UA='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36'
|
|
||||||
url=$( \
|
|
||||||
curl --connect-timeout 10 --retry 3 -sSL 'https://www.speedtest.net/apps/cli' \
|
|
||||||
--user-agent "$UA" \
|
|
||||||
| grep "Download for Linux" \
|
|
||||||
| sed 's|<|\n<|g' \
|
|
||||||
| sed -n '/Download for Linux/,/<\/div>/p' \
|
|
||||||
| sed -En "s|.*<a href=\"([^\"]+)\">${arch}|\1|p" \
|
|
||||||
)
|
|
||||||
[ -z "$url" ] && return 1
|
|
||||||
|
|
||||||
[ -n "$url" ] && curl -sSL $url --user-agent "$UA" | tar -xvz -C /tmp
|
|
||||||
mkdir -p ${OOKLA_SPEEDTEST%/*} 2>/dev/null
|
|
||||||
cp -f /tmp/speedtest $OOKLA_SPEEDTEST
|
|
||||||
chmod 755 $OOKLA_SPEEDTEST
|
|
||||||
ookla_verify || rm -f $OOKLA_SPEEDTEST
|
|
||||||
unset ALL_PROXY
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ookla_verify() {
|
start() {
|
||||||
if [ -x "$OOKLA_SPEEDTEST" ]; then
|
if ! verify; then
|
||||||
return 0
|
download || {
|
||||||
else
|
echo "Critical: Failed to install Speedtest CLI" >> "$log"
|
||||||
return 1
|
exit 1
|
||||||
fi
|
}
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
restart() {
|
||||||
start_service() {
|
start
|
||||||
ookla_verify
|
|
||||||
|
|
||||||
}
|
|
||||||
service_triggers() {
|
|
||||||
procd_add_reload_trigger "netspeedtest"
|
|
||||||
}
|
|
||||||
|
|
||||||
reload_service() {
|
|
||||||
stop
|
|
||||||
sleep 1
|
|
||||||
start
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,35 +3,54 @@ mkdir -p /etc/speedtest
|
||||||
export HOME='/etc/speedtest'
|
export HOME='/etc/speedtest'
|
||||||
SPEEDTEST_CLI='/usr/bin/speedtest'
|
SPEEDTEST_CLI='/usr/bin/speedtest'
|
||||||
SPEEDTEST_RESULT='/tmp/speedtest_result'
|
SPEEDTEST_RESULT='/tmp/speedtest_result'
|
||||||
|
LOG='/tmp/netspeedtest.log'
|
||||||
|
|
||||||
|
# 记录开始时间
|
||||||
|
echo "=== Speedtest started at $(date) ===" >> "$LOG"
|
||||||
|
|
||||||
[ -n "$(pgrep -f "$SPEEDTEST_CLI")" ] && exit 1
|
[ -n "$(pgrep -f "$SPEEDTEST_CLI")" ] && exit 1
|
||||||
|
|
||||||
echo "Start Testing" > "$SPEEDTEST_RESULT"
|
|
||||||
LOCAL_IP=$(curl -s -4 --connect-timeout 3 http://ip.3322.net)
|
LOCAL_IP=$(curl -s -4 --connect-timeout 3 http://ip.3322.net)
|
||||||
|
echo "Local IP: $LOCAL_IP" >> "$LOG"
|
||||||
|
|
||||||
BAIDU_SK="LHHGlmhcb4ENvIXpR9QQ2tBYa6ooUowX hYCENCEx1nXO0Nt46ldexfG9oI49xBGh 0kKZnWWhXEPfzIkklmzAa3dZ"
|
BAIDU_SK="LHHGlmhcb4ENvIXpR9QQ2tBYa6ooUowX hYCENCEx1nXO0Nt46ldexfG9oI49xBGh 0kKZnWWhXEPfzIkklmzAa3dZ"
|
||||||
if [ -n "$LOCAL_IP" ]; then
|
if [ -n "$LOCAL_IP" ]; then
|
||||||
for SK in $BAIDU_SK
|
for SK in $BAIDU_SK
|
||||||
do
|
do
|
||||||
INFO=$(curl -sk --connect-timeout 3 "https://api.map.baidu.com/location/ip?ip="$LOCAL_IP"&coor=bd09ll&ak=$SK")
|
INFO=$(curl -sk --connect-timeout 3 "https://api.map.baidu.com/location/ip?ip="$LOCAL_IP"&coor=bd09ll&ak=$SK")
|
||||||
if [ "$(echo $INFO | jsonfilter -e "@['status']")" = 0 ]; then
|
if [ "$(echo $INFO | jsonfilter -e "@['status']")" = 0 ]; then
|
||||||
status=0
|
status=0
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
if [ "$status" = 0 ]; then
|
if [ "$status" = 0 ]; then
|
||||||
lon=$(echo $INFO | jsonfilter -e "@['content']['point']['x']")
|
lon=$(echo $INFO | jsonfilter -e "@['content']['point']['x']")
|
||||||
lat=$(echo $INFO | jsonfilter -e "@['content']['point']['y']")
|
lat=$(echo $INFO | jsonfilter -e "@['content']['point']['y']")
|
||||||
server_id=$(curl -sk --connect-timeout 3 "https://www.speedtest.net/api/ios-config.php?lon=$lon&lat=$lat" | grep "server url" | head -n1 | sed 's/.*id="//;s/".*//')
|
server_id=$(curl -sk --connect-timeout 3 "https://www.speedtest.net/api/ios-config.php?lon=$lon&lat=$lat" | grep "server url" | head -n1 | sed 's/.*id="//;s/".*//')
|
||||||
[ -n "$server_id" ] && ARG="-s $server_id"
|
[ -n "$server_id" ] && ARG="-s $server_id"
|
||||||
fi
|
echo "Selected server ID: $server_id" >> "$LOG"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "Testing" > "$SPEEDTEST_RESULT"
|
||||||
RUNTEST=$($SPEEDTEST_CLI --accept-gdpr --accept-license --progress=no $ARG 2>&1)
|
RUNTEST=$($SPEEDTEST_CLI --accept-gdpr --accept-license --progress=no $ARG 2>&1)
|
||||||
if [ $(echo $RUNTEST | grep -c "No servers defined") -ge 1 ] || [ $(echo $RUNTEST | grep -c "error") -ge 1 ]; then
|
if [ $(echo $RUNTEST | grep -c "No servers defined") -ge 1 ] || [ $(echo $RUNTEST | grep -c "error") -ge 1 ]; then
|
||||||
RUNTEST=$($SPEEDTEST_CLI --accept-gdpr --accept-license --progress=no 2>&1)
|
echo "Fallback to default server selection" >> "$LOG"
|
||||||
|
RUNTEST=$($SPEEDTEST_CLI --accept-gdpr --accept-license --progress=no 2>&1)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# 将完整测试结果记录到日志
|
||||||
|
echo "$RUNTEST" >> "$LOG"
|
||||||
|
|
||||||
RESULT=$(echo "$RUNTEST" | grep "Result URL" | awk '{print $NF}')
|
RESULT=$(echo "$RUNTEST" | grep "Result URL" | awk '{print $NF}')
|
||||||
|
|
||||||
[ -n "$RESULT" ] && echo "$RESULT" > "$SPEEDTEST_RESULT" || echo "Test failed" > "$SPEEDTEST_RESULT"
|
if [ -n "$RESULT" ]; then
|
||||||
|
echo "$RESULT" > "$SPEEDTEST_RESULT"
|
||||||
|
else
|
||||||
|
echo "Test failed" > "$SPEEDTEST_RESULT"
|
||||||
|
echo "Test failed" >> "$LOG"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 记录结束时间
|
||||||
|
echo "=== Speedtest completed at $(date) ===" >> "$LOG"
|
||||||
|
echo "" >> "$LOG" # 添加空行分隔不同测试记录
|
||||||
|
|
|
@ -41,5 +41,13 @@
|
||||||
"type": "view",
|
"type": "view",
|
||||||
"path": "netspeedtest/openspeedtest"
|
"path": "netspeedtest/openspeedtest"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"admin/network/netspeedtest/logs": {
|
||||||
|
"title": "Log",
|
||||||
|
"order": 6,
|
||||||
|
"action": {
|
||||||
|
"type": "view",
|
||||||
|
"path": "netspeedtest/logs"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,15 +5,16 @@
|
||||||
"file": {
|
"file": {
|
||||||
"/etc/init.d/netspeedtest": [ "exec" ],
|
"/etc/init.d/netspeedtest": [ "exec" ],
|
||||||
"/usr/lib/netspeedtest/speedtest": [ "exec" ],
|
"/usr/lib/netspeedtest/speedtest": [ "exec" ],
|
||||||
"/tmp/speedtest_result": [ "read" ]
|
"/tmp/speedtest_result": [ "read" ],
|
||||||
|
"/tmp/netspeedtest.log": [ "read" ]
|
||||||
},
|
},
|
||||||
"ubus": {
|
"ubus": {
|
||||||
"service": [ "list" ]
|
"service": [ "list" ]
|
||||||
},
|
},
|
||||||
"uci": [ "netspeedtest" ]
|
"uci": [ "netspeedtest" ,"netspeedtest"]
|
||||||
},
|
},
|
||||||
"write": {
|
"write": {
|
||||||
"uci": [ "netspeedtest" ]
|
"uci": [ "netspeedtest","netspeedtest" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue