🎨 Sync 2021-11-27 23:58:48

This commit is contained in:
github-actions[bot] 2021-11-27 23:58:48 +08:00
parent 9bb3531f31
commit 5ab7c3cad2
86 changed files with 6075 additions and 7 deletions

View File

@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=aliyundrive-webdav
PKG_VERSION:=1.0.0
PKG_RELEASE:=31
PKG_RELEASE:=32
PKG_LICENSE:=MIT
PKG_MAINTAINER:=messense <messense@icloud.com>
@ -28,18 +28,18 @@ PKG_HASH:=skip
include $(INCLUDE_DIR)/package.mk
define Package/aliyundrive-webdav
define Package/$(PKG_NAME)
SECTION:=multimedia
CATEGORY:=Multimedia
TITLE:=WebDAV server for AliyunDrive
URL:=https://github.com/messense/aliyundrive-webdav
endef
define Package/aliyundrive-webdav/description
define Package/$(PKG_NAME)/description
WebDAV server for AliyunDrive.
endef
define Package/aliyundrive-webdav/conffiles
define Package/$(PKG_NAME)/conffiles
/etc/config/aliyundrive-webdav
endef
@ -61,10 +61,10 @@ define Build/Prepare
endef
define Build/Compile
echo "aliyundrive-webdav using precompiled binary."
echo "$(PKG_NAME) using precompiled binary."
endef
define Package/aliyundrive-webdav/install
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/aliyundrive-webdav $(1)/usr/bin/aliyundrive-webdav
$(INSTALL_DIR) $(1)/etc/init.d
@ -73,4 +73,4 @@ define Package/aliyundrive-webdav/install
$(INSTALL_CONF) ./files/aliyundrive-webdav.config $(1)/etc/config/aliyundrive-webdav
endef
$(eval $(call BuildPackage,aliyundrive-webdav))
$(eval $(call BuildPackage,$(PKG_NAME)))

52
app-store-ui/Makefile Normal file
View File

@ -0,0 +1,52 @@
#
# Copyright (C) 2006-2012 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=app-store-ui
PKG_VERSION:=1.0
PKG_RELEASE:=4
PKG_HOST_ONLY=1
HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/${PKG_NAME}
include $(INCLUDE_DIR)/host-build.mk
include $(INCLUDE_DIR)/package.mk
define Package/app-store-ui
SECTION:=libs
CATEGORY:=Libraries
TITLE:=App Store UI
BUILDONLY:=1
endef
define Package/app-store-ui/description
UI for luci-app-store
endef
define Host/Prepare
mkdir -p $(HOST_BUILD_DIR)
$(CP) ./src/. $(HOST_BUILD_DIR)
find $(HOST_BUILD_DIR) -name .svn | $(XARGS) rm -rf
endef
define Host/Configure
endef
define Host/Compile
endef
define Host/Install
endef
define Host/Clean
rm -f $(HOST_BUILD_DIR)/src/dist
endef
$(eval $(call HostBuild))
$(eval $(call BuildPackage,app-store-ui))

16
app-store-ui/src/dist/index.html vendored Normal file
View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<script type="module" crossorigin src="/luci-static/istore/index.js"></script>
<link rel="modulepreload" href="/luci-static/istore/vendor.js">
<link rel="stylesheet" href="/luci-static/istore/style.css">
</head>
<body>
<div id="app"></div>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

42
dpdk/Makefile Normal file
View File

@ -0,0 +1,42 @@
# SPDX-License-Identifier: GPL-2.0-only
#
include $(TOPDIR)/rules.mk
PKG_NAME := dpdk
PKG_VERSION := 21.05
PKG_SOURCE := dpdk-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL := http://static.dpdk.org/rel
PKG_MD5SUM := a78bba290b11d9717d1272cc6bfaf7c3
PKG_BUILD_DEPENDS:= meson/host ninja/host
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/host-build.mk
include $(TOPDIR)/feeds/packages/devel/meson/meson.mk
include $(TOPDIR)/feeds/packages/devel/ninja/ninja.mk
TARGET_CFLAGS += -D_GNU_SOURCE -Wno-unused-result -Wno-format-nonliteral
define Package/dpdk
SECTION := net
CATEGORY := Network
TITLE := Data Plane Development Kit (DPDK)
DEPENDS := @(x86_64||arm||aarch64) +librt +libpthread +libbpf +libpcap +libopenssl
endef
define Package/dpdk/description
DPDK consists of libraries to accelerate packet processing
workloads running on a wide variety of CPU architectures.
endef
define Package/dpdk/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_DIR) $(1)/usr/lib
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dpdk-testpmd $(1)/usr/bin/
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dpdk-proc-info $(1)/usr/bin/
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dpdk-test-flow-perf $(1)/usr/bin/
$(CP) $(PKG_INSTALL_DIR)/usr/lib/lib* $(1)/usr/lib/
endef
$(eval $(call BuildPackage,dpdk))

View File

@ -0,0 +1,40 @@
From afe64bae6d398fc9a194bce2763d6b2ab080f38f Mon Sep 17 00:00:00 2001
From: Chandrakant Sharpa <s.chandrakant@globaledgesoft.com>
Date: Mon, 14 Jun 2021 17:53:16 +0530
Subject: [PATCH] Handling backtrace and execinfo header file
Signed-off-by: Chandrakant Sharpa <s.chandrakant@globaledgesoft.com>
---
lib/eal/linux/eal_debug.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/eal/linux/eal_debug.c b/lib/eal/linux/eal_debug.c
index 64dab4e0d..24b8b23dd 100644
--- a/lib/eal/linux/eal_debug.c
+++ b/lib/eal/linux/eal_debug.c
@@ -2,9 +2,11 @@
* Copyright(c) 2010-2014 Intel Corporation
*/
+#ifdef __GLIBC__
#ifdef RTE_BACKTRACE
#include <execinfo.h>
#endif
+#endif
#include <stdarg.h>
#include <signal.h>
#include <stdlib.h>
@@ -26,8 +28,10 @@ void rte_dump_stack(void)
char **symb = NULL;
int size;
+#ifdef __GLIBC__
size = backtrace(func, BACKTRACE_SIZE);
symb = backtrace_symbols(func, size);
+#endif
if (symb == NULL)
return;
--
2.17.1

View File

@ -1,6 +1,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-aliyundrive-webdav
PKG_PO_VERSION:=$(PKG_VERSION)-$(PKG_RELEASE)
PKG_LICENSE:=MIT
PKG_MAINTAINER:=messense <messense@icloud.com>

16
luci-app-iperf/Makefile Normal file
View File

@ -0,0 +1,16 @@
#
# Copyright (C) 2018-2019 Ycarus (Yannick Chabanois) <ycarus@zugaina.org>
#
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI Support for iPerf3
LUCI_DEPENDS:=+iperf3-ssl
PKG_LICENSE:=GPLv3
#include ../luci/luci.mk
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,56 @@
local uci = luci.model.uci.cursor()
local ut = require "luci.util"
module("luci.controller.iperf", package.seeall)
function index()
--entry({"admin", "openmptcprouter", "iperf"}, cbi("iperf"), _("iperf"))
entry({"admin", "services", "iperf"}, alias("admin", "services", "iperf", "test"), _("iPerf"),8)
entry({"admin", "services", "iperf", "test"}, template("iperf/test"), nil,1)
entry({"admin", "services", "iperf", "run_test"}, post("run_test")).leaf = true
end
function run_test(server,proto,mode,updown,omit,parallel,transmit,bitrate)
luci.http.prepare_content("text/plain")
local iperf
local addr = uci:get("iperf",server,"host")
local ports = uci:get("iperf",server,"ports")
local user = uci:get("iperf",server,"user") or ""
local password = uci:get("iperf",server,"password") or ""
local key = uci:get("iperf",server,"key") or ""
local options = ""
if user ~= "" and password ~= "" and key ~= "" then
luci.sys.call("echo " .. key .. " | base64 -d > /tmp/iperf.pem")
options = options .. " --username " .. user .. " --rsa-public-key-path /tmp/iperf.pem"
end
if mode == "udp" then
options = options .. " -u -b " .. bitrate
end
if mode ~= "upload" then
options = options .. " -R"
end
local ipv = "4"
if proto == "ipv6" then
local ipv = "6"
end
local t={}
for pt in ports:gmatch("([^,%s]+)") do
table.insert(t,pt)
end
local port = t[ math.random( #t ) ]
if password ~= "" then
iperf = io.popen("omr-iperf %s -P %s -%s -O %s -t %s -J -Z %s" % {server,parallel,ipv,omit,transmit,options})
else
iperf = io.popen("iperf3 -c %s -P %s -%s -p %s -O %s -t %s -J -Z %s" % {ut.shellquote(addr),parallel,ipv,port,omit,transmit,options})
end
if iperf then
while true do
local ln = iperf:read("*l")
if not ln then break end
luci.http.write(ln)
luci.http.write("\n")
end
end
return
end

View File

@ -0,0 +1,178 @@
<%+header%>
<%
local uci = require("luci.model.uci").cursor()
%>
<script type="text/javascript" src="<%=resource%>/cbi.js?v=git-18.193.28471-ee087a1"></script>
<script type="text/javascript">//<![CDATA[
var stxhr = new XHR();
function update_speed(field, proto, mode,omit,parallel,transmit,bitrate)
{
update_upload(field,proto,mode,omit,parallel,transmit,bitrate);
}
function update_upload(field, proto, mode,omit,parallel,transmit,bitrate)
{
var tool = field.name;
var addr = field.value;
var upload = document.getElementById('iperf-upload');
if (upload)
{
upload.innerHTML =
'<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> ' + '<%:Upload%> - ' +
'<%:Waiting for command to complete...%>'
;
stxhr.post('<%=url('admin/services/iperf')%>/run_test' + '/' + addr + '/' + proto + '/' + mode + '/upload' + '/' + omit + '/' + parallel + '/' + transmit + '/' + bitrate, { token: '<%=token%>' },
function(x)
{
if (x.responseText)
{
var response = JSON.parse(x.responseText);
if (response.error)
{
upload.innerHTML = String.format('<%:Upload%> - <pre>%s</pre>', response.error );
} else {
var sent_speed = (response.end.sum_sent.bits_per_second/1000000);
var received_speed = (response.end.sum_received.bits_per_second/1000000);
var server = response.start.connecting_to.host;
upload.innerHTML = String.format('<pre><%:Upload%> - Server: %s - Sender: %sMb/s - Receiver: %sMb/s</pre>', server, sent_speed.toFixed(2), received_speed.toFixed(2) );
}
}
else
{
upload.innerHTML = '<%:Upload%> - <span class="error"><%:Bad address specified!%></span>';
}
update_download(field,proto,mode,omit,parallel,transmit,bitrate);
}
);
}
}
function update_download(field, proto, mode,omit,parallel,transmit,bitrate)
{
var tool = field.name;
var addr = field.value;
var download = document.getElementById('iperf-download');
if (download)
{
download.innerHTML =
'<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> ' + '<%:Download%> - ' +
'<%:Waiting for command to complete...%>'
;
stxhr.post('<%=url('admin/services/iperf')%>/run_test' + '/' + addr + '/' + proto + '/' + mode + '/download' + '/' + omit + '/' + parallel + '/' + transmit + '/' + bitrate, { token: '<%=token%>' },
function(x)
{
if (x.responseText)
{
var response = JSON.parse(x.responseText);
if (response.error)
{
download.innerHTML = String.format('<%:Download%> - <pre>%s</pre>', response.error );
} else {
var sent_speed = (response.end.sum_sent.bits_per_second/1000000);
var received_speed = (response.end.sum_received.bits_per_second/1000000);
var server = response.start.connecting_to.host;
download.innerHTML = String.format('<pre><%:Download%> - Server: %s - Sender: %sMb/s - Receiver: %sMb/s</pre>', server, sent_speed.toFixed(2), received_speed.toFixed(2) );
}
}
else
{
download.innerHTML = '<%:Download%> - <span class="error"><%:Bad address specified!%></span>';
}
}
);
}
}
//]]></script>
<% if stderr and #stderr > 0 then %><pre class="error"><%=pcdata(stderr)%></pre><% end %>
<form class="inline" method="post" action="<%=url('admin/services/iperf/run_test')%>">
<div class="cbi-map">
<h2 name="content"><%:iPerf speed tests%></h2>
<div class="cbi-map-descr"><%:This iPerf interface is in bêta. No support for this.%></div>
<fieldset class="cbi-section" id="networks">
<legend><%:Settings%></legend>
<div class="cbi-section-descr"></div>
<div class="cbi-value">
<label class="cbi-value-title"><%:Mode of operation%></label>
<div class="cbi-value-field">
<select class="cbi-input-select" name="mode">
<option value="tcp">TCP</option>
<option value="udp">UDP</option>
</select>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title"><%:Internet protocol%></label>
<div class="cbi-value-field">
<select class="cbi-input-select" name="proto">
<option value="ipv4">IPv4</option>
<option value="ipv6">IPv6</option>
</select>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title"><%:Target bitrate (Mbits/s)%></label>
<div class="cbi-value-field">
<input name="bitrate" data-type="uinteger" type="text" class="cbi-input-text" value="0"/>
<br />
<div class="cbi-value-description">
<%:0 for unlimited. Need to be limited for UDP test%>
</div>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title"><%:Number of parallel client streams to run%></label>
<div class="cbi-value-field">
<input name="parallel" data-type="uinteger" type="text" class="cbi-input-text" value="1"/>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title"><%:Omit the first n seconds%></label>
<div class="cbi-value-field">
<input name="omit" data-type="uinteger" type="text" class="cbi-input-text" value="3"/>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title"><%:Time to transmit for (s)%></label>
<div class="cbi-value-field">
<input name="transmit" data-type="uinteger" type="text" class="cbi-input-text" value="5"/>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title"><%:Server%></label>
<div class="cbi-value-field">
<select class="cbi-input-select" name="addr">
<%
uci:foreach("iperf","server", function(s)
local server = s[".name"]
%>
<option value="<%=server%>"><%=string.gsub(server,"_","-")%></option>
<%
end)
%>
</select>
<br />
<div class="cbi-value-description">
<%:Server VPS IP is bypassed, so this will test only default route speed.%>
</div>
</div>
</div>
<input type="button" value="<%:Test%>" class="cbi-button cbi-button-apply" onclick="update_speed(this.form.addr,this.form.proto.value,this.form.mode.value,this.form.omit.value,this.form.parallel.value,this.form.transmit.value,this.form.bitrate.value)" />
</fieldset>
</div>
</form>
<div class="cbi-section">
<span id="iperf-upload"></span>
<span id="iperf-download"></span>
</div>
<%+footer%>

View File

@ -0,0 +1,108 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2020-08-14 08:04+0000\n"
"Last-Translator: Andreas Dorfer <adorferen@gmail.com>\n"
"Language-Team: German <http://weblate.openmptcprouter.com/projects/omr/"
"luciapplicationsiperf/de/>\n"
"Language: de\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.0.4\n"
#: luci-app-iperf/luasrc/view/iperf/test.htm:128
msgid "0 for unlimited. Need to be limited for UDP test"
msgstr ""
"für 'unbegrenzt' den Wert '0' setzen. (Muss für UDP-Tests eingeschränkt "
"werden)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Bad address specified!"
msgstr "Ungültige Adresse!"
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
#: luci-app-iperf/luasrc/view/iperf/test.htm:78
#: luci-app-iperf/luasrc/view/iperf/test.htm:83
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Download"
msgstr "Downstream"
#: luci-app-iperf/root/usr/share/rpcd/acl.d/luci-app-iperf.json:3
msgid "Grant UCI access for luci-app-iperf"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:114
msgid "Internet protocol"
msgstr "Internet-Protokoll"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
msgid "Loading"
msgstr "Wird geladen"
#: luci-app-iperf/luasrc/view/iperf/test.htm:105
msgid "Mode of operation"
msgstr "Betriebsart"
#: luci-app-iperf/luasrc/view/iperf/test.htm:133
msgid "Number of parallel client streams to run"
msgstr "Anzahl der parallel zu testenden Verbindungen"
#: luci-app-iperf/luasrc/view/iperf/test.htm:139
msgid "Omit the first n seconds"
msgstr "Die ersten n Sekunden nicht berücksichtigen"
#: luci-app-iperf/luasrc/view/iperf/test.htm:151
msgid "Server"
msgstr "Server"
#: luci-app-iperf/luasrc/view/iperf/test.htm:165
msgid "Server VPS IP is bypassed, so this will test only default route speed."
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:102
msgid "Settings"
msgstr "Einstellungen"
#: luci-app-iperf/luasrc/view/iperf/test.htm:123
msgid "Target bitrate (Mbits/s)"
msgstr "Angestrebte Bandbreite (MBit/s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:169
msgid "Test"
msgstr "Test"
#: luci-app-iperf/luasrc/view/iperf/test.htm:100
msgid "This iPerf interface is in bêta. No support for this."
msgstr ""
"Diesese Oberfläche für iPerf ist im Beta-Stadium und ohne offiziellen "
"Support."
#: luci-app-iperf/luasrc/view/iperf/test.htm:145
msgid "Time to transmit for (s)"
msgstr "Übertragungszeit in Sekunden"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:38
#: luci-app-iperf/luasrc/view/iperf/test.htm:43
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
msgid "Upload"
msgstr "Upstream"
#: luci-app-iperf/luasrc/view/iperf/test.htm:27
#: luci-app-iperf/luasrc/view/iperf/test.htm:67
msgid "Waiting for command to complete..."
msgstr "Warte auf Abschluss der Aufgaben"
#: luci-app-iperf/luasrc/controller/iperf.lua:8
#: luci-app-iperf/root/usr/share/luci/menu.d/luci-app-iperf.json:3
msgid "iPerf"
msgstr "iPerf"
#: luci-app-iperf/luasrc/view/iperf/test.htm:99
msgid "iPerf speed tests"
msgstr "iPerf Geschwindigkeitstests"
#~ msgid "iperf"
#~ msgstr "iperf"

View File

@ -0,0 +1,100 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2020-08-14 08:04+0000\n"
"Last-Translator: Andreas Dorfer <adorferen@gmail.com>\n"
"Language-Team: German <http://weblate.openmptcprouter.com/projects/omr/"
"luciapplicationsiperf/de/>\n"
"Language: de\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.0.4\n"
#: luci-app-iperf/luasrc/view/iperf/test.htm:128
msgid "0 for unlimited. Need to be limited for UDP test"
msgstr ""
"für 'unbegrenzt' den Wert '0' setzen. (Muss für UDP-Tests eingeschränkt "
"werden)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Bad address specified!"
msgstr "Ungültige Adresse!"
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
#: luci-app-iperf/luasrc/view/iperf/test.htm:78
#: luci-app-iperf/luasrc/view/iperf/test.htm:83
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Download"
msgstr "Downstream"
#: luci-app-iperf/luasrc/view/iperf/test.htm:114
msgid "Internet protocol"
msgstr "Internet-Protokoll"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
msgid "Loading"
msgstr "Wird geladen"
#: luci-app-iperf/luasrc/view/iperf/test.htm:105
msgid "Mode of operation"
msgstr "Betriebsart"
#: luci-app-iperf/luasrc/view/iperf/test.htm:133
msgid "Number of parallel client streams to run"
msgstr "Anzahl der parallel zu testenden Verbindungen"
#: luci-app-iperf/luasrc/view/iperf/test.htm:139
msgid "Omit the first n seconds"
msgstr "Die ersten n Sekunden nicht berücksichtigen"
#: luci-app-iperf/luasrc/view/iperf/test.htm:151
msgid "Server"
msgstr "Server"
#: luci-app-iperf/luasrc/view/iperf/test.htm:102
msgid "Settings"
msgstr "Einstellungen"
#: luci-app-iperf/luasrc/view/iperf/test.htm:123
msgid "Target bitrate (Mbits/s)"
msgstr "Angestrebte Bandbreite (MBit/s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:165
msgid "Test"
msgstr "Test"
#: luci-app-iperf/luasrc/view/iperf/test.htm:100
msgid "This iPerf interface is in bêta. No support for this."
msgstr ""
"Diesese Oberfläche für iPerf ist im Beta-Stadium und ohne offiziellen "
"Support."
#: luci-app-iperf/luasrc/view/iperf/test.htm:145
msgid "Time to transmit for (s)"
msgstr "Übertragungszeit in Sekunden"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:38
#: luci-app-iperf/luasrc/view/iperf/test.htm:43
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
msgid "Upload"
msgstr "Upstream"
#: luci-app-iperf/luasrc/view/iperf/test.htm:27
#: luci-app-iperf/luasrc/view/iperf/test.htm:67
msgid "Waiting for command to complete..."
msgstr "Warte auf Abschluss der Aufgaben"
#: luci-app-iperf/luasrc/controller/iperf.lua:8
msgid "iPerf"
msgstr "iPerf"
#: luci-app-iperf/luasrc/view/iperf/test.htm:99
msgid "iPerf speed tests"
msgstr "iPerf Geschwindigkeitstests"
#: luci-app-iperf/luasrc/controller/iperf.lua:7
msgid "iperf"
msgstr "iperf"

View File

@ -0,0 +1,109 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2021-05-21 19:20+0000\n"
"Last-Translator: Weblate Admin <contact@openmptcprouter.com>\n"
"Language-Team: French <http://weblate.openmptcprouter.com/projects/omr/"
"luciapplicationsiperf/fr/>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 4.6.1\n"
#: luci-app-iperf/luasrc/view/iperf/test.htm:128
msgid "0 for unlimited. Need to be limited for UDP test"
msgstr "0 pour sans limite. Nécessite d'être limité pour les tests UDP."
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Bad address specified!"
msgstr "Adresse invalide !"
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
#: luci-app-iperf/luasrc/view/iperf/test.htm:78
#: luci-app-iperf/luasrc/view/iperf/test.htm:83
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Download"
msgstr "Téléchargement"
#: luci-app-iperf/root/usr/share/rpcd/acl.d/luci-app-iperf.json:3
msgid "Grant UCI access for luci-app-iperf"
msgstr "Accorder l'accès UCI pour luci-app-iperf"
#: luci-app-iperf/luasrc/view/iperf/test.htm:114
msgid "Internet protocol"
msgstr "Protocole Internet"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
msgid "Loading"
msgstr "Chargement"
#: luci-app-iperf/luasrc/view/iperf/test.htm:105
msgid "Mode of operation"
msgstr "Mode de fonctionnement"
#: luci-app-iperf/luasrc/view/iperf/test.htm:133
msgid "Number of parallel client streams to run"
msgstr "Nombre de client en parallèle"
#: luci-app-iperf/luasrc/view/iperf/test.htm:139
msgid "Omit the first n seconds"
msgstr "Passe les n premières secondes"
#: luci-app-iperf/luasrc/view/iperf/test.htm:151
msgid "Server"
msgstr "Serveur"
#: luci-app-iperf/luasrc/view/iperf/test.htm:165
msgid "Server VPS IP is bypassed, so this will test only default route speed."
msgstr ""
"L'IP du serveur VPS est contournée, donc cela testera uniquement la vitesse "
"de route par défaut."
#: luci-app-iperf/luasrc/view/iperf/test.htm:102
msgid "Settings"
msgstr "Paramètres"
#: luci-app-iperf/luasrc/view/iperf/test.htm:123
msgid "Target bitrate (Mbits/s)"
msgstr "Vitesse souhaitée (Mbits/s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:169
msgid "Test"
msgstr "Teste"
#: luci-app-iperf/luasrc/view/iperf/test.htm:100
msgid "This iPerf interface is in bêta. No support for this."
msgstr "Cette interface pour iPerf est en bêta. Pas de support pour ça."
#: luci-app-iperf/luasrc/view/iperf/test.htm:145
msgid "Time to transmit for (s)"
msgstr "Temps de transmission (s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:38
#: luci-app-iperf/luasrc/view/iperf/test.htm:43
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
msgid "Upload"
msgstr "Téléverser"
#: luci-app-iperf/luasrc/view/iperf/test.htm:27
#: luci-app-iperf/luasrc/view/iperf/test.htm:67
msgid "Waiting for command to complete..."
msgstr "En attente de la réponse de la commande..."
#: luci-app-iperf/luasrc/controller/iperf.lua:8
#: luci-app-iperf/root/usr/share/luci/menu.d/luci-app-iperf.json:3
msgid "iPerf"
msgstr "iPerf"
#: luci-app-iperf/luasrc/view/iperf/test.htm:99
msgid "iPerf speed tests"
msgstr "Tests de vitesse iPerf"
#~ msgid "iperf"
#~ msgstr "iperf"

View File

@ -0,0 +1,99 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2020-09-30 08:50+0000\n"
"Last-Translator: Weblate Admin <contact@openmptcprouter.com>\n"
"Language-Team: French <http://weblate.openmptcprouter.com/projects/omr/"
"luciapplicationsiperf/fr/>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 4.0.4\n"
#: luci-app-iperf/luasrc/view/iperf/test.htm:128
msgid "0 for unlimited. Need to be limited for UDP test"
msgstr "0 pour sans limite. Nécessite d'être limité pour les tests UDP."
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Bad address specified!"
msgstr "Adresse invalide !"
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
#: luci-app-iperf/luasrc/view/iperf/test.htm:78
#: luci-app-iperf/luasrc/view/iperf/test.htm:83
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Download"
msgstr "Téléchargement"
#: luci-app-iperf/luasrc/view/iperf/test.htm:114
msgid "Internet protocol"
msgstr "Protocole Internet"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
msgid "Loading"
msgstr "Chargement"
#: luci-app-iperf/luasrc/view/iperf/test.htm:105
msgid "Mode of operation"
msgstr "Mode de fonctionnement"
#: luci-app-iperf/luasrc/view/iperf/test.htm:133
msgid "Number of parallel client streams to run"
msgstr "Nombre de client en parallèle"
#: luci-app-iperf/luasrc/view/iperf/test.htm:139
msgid "Omit the first n seconds"
msgstr "Passe les n premières secondes"
#: luci-app-iperf/luasrc/view/iperf/test.htm:151
msgid "Server"
msgstr "Serveur"
#: luci-app-iperf/luasrc/view/iperf/test.htm:102
msgid "Settings"
msgstr "Paramètres"
#: luci-app-iperf/luasrc/view/iperf/test.htm:123
msgid "Target bitrate (Mbits/s)"
msgstr "Vitesse souhaitée (Mbits/s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:165
msgid "Test"
msgstr "Teste"
#: luci-app-iperf/luasrc/view/iperf/test.htm:100
msgid "This iPerf interface is in bêta. No support for this."
msgstr "Cette interface pour iPerf est en bêta. Pas de support pour ça."
#: luci-app-iperf/luasrc/view/iperf/test.htm:145
msgid "Time to transmit for (s)"
msgstr "Temps de transmission (s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:38
#: luci-app-iperf/luasrc/view/iperf/test.htm:43
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
msgid "Upload"
msgstr "Envoie"
#: luci-app-iperf/luasrc/view/iperf/test.htm:27
#: luci-app-iperf/luasrc/view/iperf/test.htm:67
msgid "Waiting for command to complete..."
msgstr "En attente de la réponse de la commande..."
#: luci-app-iperf/luasrc/controller/iperf.lua:8
msgid "iPerf"
msgstr "iPerf"
#: luci-app-iperf/luasrc/view/iperf/test.htm:99
msgid "iPerf speed tests"
msgstr "Tests de vitesse iPerf"
#: luci-app-iperf/luasrc/controller/iperf.lua:7
msgid "iperf"
msgstr "iperf"

View File

@ -0,0 +1,104 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2020-09-21 12:51+0000\n"
"Last-Translator: Weblate Admin <contact@openmptcprouter.com>\n"
"Language-Team: Italian <http://weblate.openmptcprouter.com/projects/omr/"
"luciapplicationsiperf/it/>\n"
"Language: it\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.0.4\n"
#: luci-app-iperf/luasrc/view/iperf/test.htm:128
msgid "0 for unlimited. Need to be limited for UDP test"
msgstr "0 per illimitato. Deve essere limitato per il test UDP"
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Bad address specified!"
msgstr "È stato specificato un indirizzo errato!"
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
#: luci-app-iperf/luasrc/view/iperf/test.htm:78
#: luci-app-iperf/luasrc/view/iperf/test.htm:83
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Download"
msgstr "Scarica"
#: luci-app-iperf/root/usr/share/rpcd/acl.d/luci-app-iperf.json:3
msgid "Grant UCI access for luci-app-iperf"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:114
msgid "Internet protocol"
msgstr "Internet Protocol (Protocollo Internet)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
msgid "Loading"
msgstr "Caricamento in corso"
#: luci-app-iperf/luasrc/view/iperf/test.htm:105
msgid "Mode of operation"
msgstr "Modalità di funzionamento"
#: luci-app-iperf/luasrc/view/iperf/test.htm:133
msgid "Number of parallel client streams to run"
msgstr "Numero di flussi client paralleli da eseguire"
#: luci-app-iperf/luasrc/view/iperf/test.htm:139
msgid "Omit the first n seconds"
msgstr "Ometti i primi n secondi"
#: luci-app-iperf/luasrc/view/iperf/test.htm:151
msgid "Server"
msgstr "Server"
#: luci-app-iperf/luasrc/view/iperf/test.htm:165
msgid "Server VPS IP is bypassed, so this will test only default route speed."
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:102
msgid "Settings"
msgstr "Impostazioni"
#: luci-app-iperf/luasrc/view/iperf/test.htm:123
msgid "Target bitrate (Mbits/s)"
msgstr "Bitrate desiderato (Mbits/s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:169
msgid "Test"
msgstr "Test"
#: luci-app-iperf/luasrc/view/iperf/test.htm:100
msgid "This iPerf interface is in bêta. No support for this."
msgstr "Questa interfaccia iPerf è in bêta."
#: luci-app-iperf/luasrc/view/iperf/test.htm:145
msgid "Time to transmit for (s)"
msgstr "È ora di trasmettere per (s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:38
#: luci-app-iperf/luasrc/view/iperf/test.htm:43
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
msgid "Upload"
msgstr "Carica"
#: luci-app-iperf/luasrc/view/iperf/test.htm:27
#: luci-app-iperf/luasrc/view/iperf/test.htm:67
msgid "Waiting for command to complete..."
msgstr "In attesa del completamento del comando ..."
#: luci-app-iperf/luasrc/controller/iperf.lua:8
#: luci-app-iperf/root/usr/share/luci/menu.d/luci-app-iperf.json:3
msgid "iPerf"
msgstr "iPerf"
#: luci-app-iperf/luasrc/view/iperf/test.htm:99
msgid "iPerf speed tests"
msgstr "Prove di velocità iPerf"
#~ msgid "iperf"
#~ msgstr "iPerf"

View File

@ -0,0 +1,96 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2020-09-21 12:51+0000\n"
"Last-Translator: Weblate Admin <contact@openmptcprouter.com>\n"
"Language-Team: Italian <http://weblate.openmptcprouter.com/projects/omr/"
"luciapplicationsiperf/it/>\n"
"Language: it\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.0.4\n"
#: luci-app-iperf/luasrc/view/iperf/test.htm:128
msgid "0 for unlimited. Need to be limited for UDP test"
msgstr "0 per illimitato. Deve essere limitato per il test UDP"
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Bad address specified!"
msgstr "È stato specificato un indirizzo errato!"
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
#: luci-app-iperf/luasrc/view/iperf/test.htm:78
#: luci-app-iperf/luasrc/view/iperf/test.htm:83
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Download"
msgstr "Scarica"
#: luci-app-iperf/luasrc/view/iperf/test.htm:114
msgid "Internet protocol"
msgstr "Internet Protocol (Protocollo Internet)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
msgid "Loading"
msgstr "Caricamento in corso"
#: luci-app-iperf/luasrc/view/iperf/test.htm:105
msgid "Mode of operation"
msgstr "Modalità di funzionamento"
#: luci-app-iperf/luasrc/view/iperf/test.htm:133
msgid "Number of parallel client streams to run"
msgstr "Numero di flussi client paralleli da eseguire"
#: luci-app-iperf/luasrc/view/iperf/test.htm:139
msgid "Omit the first n seconds"
msgstr "Ometti i primi n secondi"
#: luci-app-iperf/luasrc/view/iperf/test.htm:151
msgid "Server"
msgstr "Server"
#: luci-app-iperf/luasrc/view/iperf/test.htm:102
msgid "Settings"
msgstr "Impostazioni"
#: luci-app-iperf/luasrc/view/iperf/test.htm:123
msgid "Target bitrate (Mbits/s)"
msgstr "Bitrate desiderato (Mbits/s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:165
msgid "Test"
msgstr "Test"
#: luci-app-iperf/luasrc/view/iperf/test.htm:100
msgid "This iPerf interface is in bêta. No support for this."
msgstr "Questa interfaccia iPerf è in bêta."
#: luci-app-iperf/luasrc/view/iperf/test.htm:145
msgid "Time to transmit for (s)"
msgstr "È ora di trasmettere per (s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:38
#: luci-app-iperf/luasrc/view/iperf/test.htm:43
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
msgid "Upload"
msgstr "Carica"
#: luci-app-iperf/luasrc/view/iperf/test.htm:27
#: luci-app-iperf/luasrc/view/iperf/test.htm:67
msgid "Waiting for command to complete..."
msgstr "In attesa del completamento del comando ..."
#: luci-app-iperf/luasrc/controller/iperf.lua:8
msgid "iPerf"
msgstr "iPerf"
#: luci-app-iperf/luasrc/view/iperf/test.htm:99
msgid "iPerf speed tests"
msgstr "Prove di velocità iPerf"
#: luci-app-iperf/luasrc/controller/iperf.lua:7
msgid "iperf"
msgstr "iPerf"

View File

@ -0,0 +1,104 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2020-08-21 20:21+0000\n"
"Last-Translator: Quentin PAGÈS <githubou@quentino.fr>\n"
"Language-Team: Occitan <http://weblate.openmptcprouter.com/projects/omr/"
"luciapplicationsiperf/oc/>\n"
"Language: oc\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 4.0.4\n"
#: luci-app-iperf/luasrc/view/iperf/test.htm:128
msgid "0 for unlimited. Need to be limited for UDP test"
msgstr "0 per cap de limit. Requerís un limit pels ensages UDP"
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Bad address specified!"
msgstr "Adreça invalida !"
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
#: luci-app-iperf/luasrc/view/iperf/test.htm:78
#: luci-app-iperf/luasrc/view/iperf/test.htm:83
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Download"
msgstr "Telecargament"
#: luci-app-iperf/root/usr/share/rpcd/acl.d/luci-app-iperf.json:3
msgid "Grant UCI access for luci-app-iperf"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:114
msgid "Internet protocol"
msgstr "Protocòl Internet"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
msgid "Loading"
msgstr "Cargament"
#: luci-app-iperf/luasrc/view/iperf/test.htm:105
msgid "Mode of operation"
msgstr "Mòde de foncionament"
#: luci-app-iperf/luasrc/view/iperf/test.htm:133
msgid "Number of parallel client streams to run"
msgstr "Nombre de clients en parallèl"
#: luci-app-iperf/luasrc/view/iperf/test.htm:139
msgid "Omit the first n seconds"
msgstr "Sautar las primièras n segondas"
#: luci-app-iperf/luasrc/view/iperf/test.htm:151
msgid "Server"
msgstr "Servidor"
#: luci-app-iperf/luasrc/view/iperf/test.htm:165
msgid "Server VPS IP is bypassed, so this will test only default route speed."
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:102
msgid "Settings"
msgstr "Paramètres"
#: luci-app-iperf/luasrc/view/iperf/test.htm:123
msgid "Target bitrate (Mbits/s)"
msgstr "Velocitat desirada (Mbits/s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:169
msgid "Test"
msgstr "Pròva"
#: luci-app-iperf/luasrc/view/iperf/test.htm:100
msgid "This iPerf interface is in bêta. No support for this."
msgstr "Aquesta interfàcia per iPerf es en beta. Cap de support per aquò."
#: luci-app-iperf/luasrc/view/iperf/test.htm:145
msgid "Time to transmit for (s)"
msgstr "Temps de transmission (s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:38
#: luci-app-iperf/luasrc/view/iperf/test.htm:43
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
msgid "Upload"
msgstr "Mandadís"
#: luci-app-iperf/luasrc/view/iperf/test.htm:27
#: luci-app-iperf/luasrc/view/iperf/test.htm:67
msgid "Waiting for command to complete..."
msgstr "En espèra duna responsa de la comanda..."
#: luci-app-iperf/luasrc/controller/iperf.lua:8
#: luci-app-iperf/root/usr/share/luci/menu.d/luci-app-iperf.json:3
msgid "iPerf"
msgstr "iPerf"
#: luci-app-iperf/luasrc/view/iperf/test.htm:99
msgid "iPerf speed tests"
msgstr "Pròva de velocitat iPerf"
#~ msgid "iperf"
#~ msgstr "iperf"

View File

@ -0,0 +1,96 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2020-08-21 20:21+0000\n"
"Last-Translator: Quentin PAGÈS <githubou@quentino.fr>\n"
"Language-Team: Occitan <http://weblate.openmptcprouter.com/projects/omr/"
"luciapplicationsiperf/oc/>\n"
"Language: oc\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 4.0.4\n"
#: luci-app-iperf/luasrc/view/iperf/test.htm:128
msgid "0 for unlimited. Need to be limited for UDP test"
msgstr "0 per cap de limit. Requerís un limit pels ensages UDP"
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Bad address specified!"
msgstr "Adreça invalida !"
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
#: luci-app-iperf/luasrc/view/iperf/test.htm:78
#: luci-app-iperf/luasrc/view/iperf/test.htm:83
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Download"
msgstr "Telecargament"
#: luci-app-iperf/luasrc/view/iperf/test.htm:114
msgid "Internet protocol"
msgstr "Protocòl Internet"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
msgid "Loading"
msgstr "Cargament"
#: luci-app-iperf/luasrc/view/iperf/test.htm:105
msgid "Mode of operation"
msgstr "Mòde de foncionament"
#: luci-app-iperf/luasrc/view/iperf/test.htm:133
msgid "Number of parallel client streams to run"
msgstr "Nombre de clients en parallèl"
#: luci-app-iperf/luasrc/view/iperf/test.htm:139
msgid "Omit the first n seconds"
msgstr "Sautar las primièras n segondas"
#: luci-app-iperf/luasrc/view/iperf/test.htm:151
msgid "Server"
msgstr "Servidor"
#: luci-app-iperf/luasrc/view/iperf/test.htm:102
msgid "Settings"
msgstr "Paramètres"
#: luci-app-iperf/luasrc/view/iperf/test.htm:123
msgid "Target bitrate (Mbits/s)"
msgstr "Velocitat desirada (Mbits/s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:165
msgid "Test"
msgstr "Pròva"
#: luci-app-iperf/luasrc/view/iperf/test.htm:100
msgid "This iPerf interface is in bêta. No support for this."
msgstr "Aquesta interfàcia per iPerf es en beta. Cap de support per aquò."
#: luci-app-iperf/luasrc/view/iperf/test.htm:145
msgid "Time to transmit for (s)"
msgstr "Temps de transmission (s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:38
#: luci-app-iperf/luasrc/view/iperf/test.htm:43
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
msgid "Upload"
msgstr "Mandadís"
#: luci-app-iperf/luasrc/view/iperf/test.htm:27
#: luci-app-iperf/luasrc/view/iperf/test.htm:67
msgid "Waiting for command to complete..."
msgstr "En espèra duna responsa de la comanda..."
#: luci-app-iperf/luasrc/controller/iperf.lua:8
msgid "iPerf"
msgstr "iPerf"
#: luci-app-iperf/luasrc/view/iperf/test.htm:99
msgid "iPerf speed tests"
msgstr "Pròva de velocitat iPerf"
#: luci-app-iperf/luasrc/controller/iperf.lua:7
msgid "iperf"
msgstr "iperf"

View File

@ -0,0 +1,104 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2021-06-16 10:51+0000\n"
"Last-Translator: Dmitry Galenko <d@monteops.com>\n"
"Language-Team: Russian <http://weblate.openmptcprouter.com/projects/omr/"
"luciapplicationsiperf/ru/>\n"
"Language: ru\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 4.6.1\n"
#: luci-app-iperf/luasrc/view/iperf/test.htm:128
msgid "0 for unlimited. Need to be limited for UDP test"
msgstr "0 - без ограничений. Для теста UDP число должно быть больше 0"
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Bad address specified!"
msgstr "Указан не правильный адрес!"
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
#: luci-app-iperf/luasrc/view/iperf/test.htm:78
#: luci-app-iperf/luasrc/view/iperf/test.htm:83
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Download"
msgstr "Получение"
#: luci-app-iperf/root/usr/share/rpcd/acl.d/luci-app-iperf.json:3
msgid "Grant UCI access for luci-app-iperf"
msgstr "Разрешить доступ к UCI для luci-app-iperf"
#: luci-app-iperf/luasrc/view/iperf/test.htm:114
msgid "Internet protocol"
msgstr "Интернет протокол"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
msgid "Loading"
msgstr "Загрузка"
#: luci-app-iperf/luasrc/view/iperf/test.htm:105
msgid "Mode of operation"
msgstr "Режим работы"
#: luci-app-iperf/luasrc/view/iperf/test.htm:133
msgid "Number of parallel client streams to run"
msgstr "Количество параллельных потоковых клиентов"
#: luci-app-iperf/luasrc/view/iperf/test.htm:139
msgid "Omit the first n seconds"
msgstr "Пропустить первые n секунд"
#: luci-app-iperf/luasrc/view/iperf/test.htm:151
msgid "Server"
msgstr "Сервер"
#: luci-app-iperf/luasrc/view/iperf/test.htm:165
msgid "Server VPS IP is bypassed, so this will test only default route speed."
msgstr ""
"Включен режим байпаса для IP VPS, будет проверена скорость только маршрута "
"по умолчанию."
#: luci-app-iperf/luasrc/view/iperf/test.htm:102
msgid "Settings"
msgstr "Настройки"
#: luci-app-iperf/luasrc/view/iperf/test.htm:123
msgid "Target bitrate (Mbits/s)"
msgstr "Целевой битрейт (Mbits/s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:169
msgid "Test"
msgstr "Тест"
#: luci-app-iperf/luasrc/view/iperf/test.htm:100
msgid "This iPerf interface is in bêta. No support for this."
msgstr "Этот iPerf interface в режиме beta. Недоступно."
#: luci-app-iperf/luasrc/view/iperf/test.htm:145
msgid "Time to transmit for (s)"
msgstr "Время передачи (s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:38
#: luci-app-iperf/luasrc/view/iperf/test.htm:43
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
msgid "Upload"
msgstr "Отправка"
#: luci-app-iperf/luasrc/view/iperf/test.htm:27
#: luci-app-iperf/luasrc/view/iperf/test.htm:67
msgid "Waiting for command to complete..."
msgstr "Ожидание завершения команды..."
#: luci-app-iperf/luasrc/controller/iperf.lua:8
#: luci-app-iperf/root/usr/share/luci/menu.d/luci-app-iperf.json:3
msgid "iPerf"
msgstr "iPerf"
#: luci-app-iperf/luasrc/view/iperf/test.htm:99
msgid "iPerf speed tests"
msgstr "iPerf тест скорости"

View File

@ -0,0 +1,92 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
#: luci-app-iperf/luasrc/view/iperf/test.htm:128
msgid "0 for unlimited. Need to be limited for UDP test"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Bad address specified!"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
#: luci-app-iperf/luasrc/view/iperf/test.htm:78
#: luci-app-iperf/luasrc/view/iperf/test.htm:83
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Download"
msgstr ""
#: luci-app-iperf/root/usr/share/rpcd/acl.d/luci-app-iperf.json:3
msgid "Grant UCI access for luci-app-iperf"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:114
msgid "Internet protocol"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
msgid "Loading"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:105
msgid "Mode of operation"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:133
msgid "Number of parallel client streams to run"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:139
msgid "Omit the first n seconds"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:151
msgid "Server"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:165
msgid "Server VPS IP is bypassed, so this will test only default route speed."
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:102
msgid "Settings"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:123
msgid "Target bitrate (Mbits/s)"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:169
msgid "Test"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:100
msgid "This iPerf interface is in bêta. No support for this."
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:145
msgid "Time to transmit for (s)"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:38
#: luci-app-iperf/luasrc/view/iperf/test.htm:43
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
msgid "Upload"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:27
#: luci-app-iperf/luasrc/view/iperf/test.htm:67
msgid "Waiting for command to complete..."
msgstr ""
#: luci-app-iperf/luasrc/controller/iperf.lua:8
#: luci-app-iperf/root/usr/share/luci/menu.d/luci-app-iperf.json:3
msgid "iPerf"
msgstr ""
#: luci-app-iperf/luasrc/view/iperf/test.htm:99
msgid "iPerf speed tests"
msgstr ""

1
luci-app-iperf/po/zh-cn Symbolic link
View File

@ -0,0 +1 @@
zh_Hans

View File

@ -0,0 +1,104 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2021-05-13 21:38+0000\n"
"Last-Translator: justbin <419989953@qq.com>\n"
"Language-Team: Chinese (Simplified) <http://weblate.openmptcprouter.com/"
"projects/omr/luciapplicationsiperf/zh_Hans/>\n"
"Language: zh_Hans\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 4.6.1\n"
#: luci-app-iperf/luasrc/view/iperf/test.htm:128
msgid "0 for unlimited. Need to be limited for UDP test"
msgstr "0代表无限.需要限制UDP测试"
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Bad address specified!"
msgstr "指定地址错误!"
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
#: luci-app-iperf/luasrc/view/iperf/test.htm:78
#: luci-app-iperf/luasrc/view/iperf/test.htm:83
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Download"
msgstr "下载"
#: luci-app-iperf/root/usr/share/rpcd/acl.d/luci-app-iperf.json:3
msgid "Grant UCI access for luci-app-iperf"
msgstr "授予luci-app-iperf UCI访问权限"
#: luci-app-iperf/luasrc/view/iperf/test.htm:114
msgid "Internet protocol"
msgstr "互联网协议"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
msgid "Loading"
msgstr "载入中"
#: luci-app-iperf/luasrc/view/iperf/test.htm:105
msgid "Mode of operation"
msgstr "操作模式"
#: luci-app-iperf/luasrc/view/iperf/test.htm:133
msgid "Number of parallel client streams to run"
msgstr "要运行的并行客户端流的数量"
#: luci-app-iperf/luasrc/view/iperf/test.htm:139
msgid "Omit the first n seconds"
msgstr "忽略前n秒"
#: luci-app-iperf/luasrc/view/iperf/test.htm:151
msgid "Server"
msgstr "服务器"
#: luci-app-iperf/luasrc/view/iperf/test.htm:165
msgid "Server VPS IP is bypassed, so this will test only default route speed."
msgstr "VPS IP被绕过因此这将只测试默认的路由速度。"
#: luci-app-iperf/luasrc/view/iperf/test.htm:102
msgid "Settings"
msgstr "设置"
#: luci-app-iperf/luasrc/view/iperf/test.htm:123
msgid "Target bitrate (Mbits/s)"
msgstr "目标比特率(Mbits/s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:169
msgid "Test"
msgstr "测试"
#: luci-app-iperf/luasrc/view/iperf/test.htm:100
msgid "This iPerf interface is in bêta. No support for this."
msgstr "此iPerf界面位于测试中.对此不支持."
#: luci-app-iperf/luasrc/view/iperf/test.htm:145
msgid "Time to transmit for (s)"
msgstr "传输时间 (秒)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:38
#: luci-app-iperf/luasrc/view/iperf/test.htm:43
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
msgid "Upload"
msgstr "上传"
#: luci-app-iperf/luasrc/view/iperf/test.htm:27
#: luci-app-iperf/luasrc/view/iperf/test.htm:67
msgid "Waiting for command to complete..."
msgstr "等待命令完成..."
#: luci-app-iperf/luasrc/controller/iperf.lua:8
#: luci-app-iperf/root/usr/share/luci/menu.d/luci-app-iperf.json:3
msgid "iPerf"
msgstr "iPerf测速"
#: luci-app-iperf/luasrc/view/iperf/test.htm:99
msgid "iPerf speed tests"
msgstr "iPerf速度测试"
#~ msgid "iperf"
#~ msgstr "iperf测速"

View File

@ -0,0 +1,96 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2021-04-30 16:03+0000\n"
"Last-Translator: niergouge <1150108426@qq.com>\n"
"Language-Team: Chinese (Simplified) <http://weblate.openmptcprouter.com/"
"projects/omr/luciapplicationsiperf/zh_Hans/>\n"
"Language: zh_Hans\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 4.5.2\n"
#: luci-app-iperf/luasrc/view/iperf/test.htm:128
msgid "0 for unlimited. Need to be limited for UDP test"
msgstr "0代表无限.需要限制UDP测试"
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Bad address specified!"
msgstr "指定地址错误!"
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
#: luci-app-iperf/luasrc/view/iperf/test.htm:78
#: luci-app-iperf/luasrc/view/iperf/test.htm:83
#: luci-app-iperf/luasrc/view/iperf/test.htm:88
msgid "Download"
msgstr "下载"
#: luci-app-iperf/luasrc/view/iperf/test.htm:114
msgid "Internet protocol"
msgstr "互联网协议"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:66
msgid "Loading"
msgstr "载入中"
#: luci-app-iperf/luasrc/view/iperf/test.htm:105
msgid "Mode of operation"
msgstr "操作模式"
#: luci-app-iperf/luasrc/view/iperf/test.htm:133
msgid "Number of parallel client streams to run"
msgstr "要运行的并行客户端流的数量"
#: luci-app-iperf/luasrc/view/iperf/test.htm:139
msgid "Omit the first n seconds"
msgstr "忽略前n秒"
#: luci-app-iperf/luasrc/view/iperf/test.htm:151
msgid "Server"
msgstr "服务器"
#: luci-app-iperf/luasrc/view/iperf/test.htm:102
msgid "Settings"
msgstr "设置"
#: luci-app-iperf/luasrc/view/iperf/test.htm:123
msgid "Target bitrate (Mbits/s)"
msgstr "目标比特率(Mbits/s)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:165
msgid "Test"
msgstr "测试"
#: luci-app-iperf/luasrc/view/iperf/test.htm:100
msgid "This iPerf interface is in bêta. No support for this."
msgstr "此iPerf界面位于测试中.对此不支持."
#: luci-app-iperf/luasrc/view/iperf/test.htm:145
msgid "Time to transmit for (s)"
msgstr "传输时间 (秒)"
#: luci-app-iperf/luasrc/view/iperf/test.htm:26
#: luci-app-iperf/luasrc/view/iperf/test.htm:38
#: luci-app-iperf/luasrc/view/iperf/test.htm:43
#: luci-app-iperf/luasrc/view/iperf/test.htm:48
msgid "Upload"
msgstr "上传"
#: luci-app-iperf/luasrc/view/iperf/test.htm:27
#: luci-app-iperf/luasrc/view/iperf/test.htm:67
msgid "Waiting for command to complete..."
msgstr "等待命令完成..."
#: luci-app-iperf/luasrc/controller/iperf.lua:8
msgid "iPerf"
msgstr "iPerf测速"
#: luci-app-iperf/luasrc/view/iperf/test.htm:99
msgid "iPerf speed tests"
msgstr "iPerf速度测试"
#: luci-app-iperf/luasrc/controller/iperf.lua:7
msgid "iperf"
msgstr "iperf测速"

View File

@ -0,0 +1,96 @@
config server 'bouygues'
option host 'bouygues.iperf.fr'
option ipv4 '1'
option ipv6 '1'
option speed '10000'
option ports '5200,5201,5202,5203,5204,5205,5206,5207,5208,5209'
option tcp '1'
option udp '0'
option location 'Europe'
config server 'online_ipv4'
option host 'ping.online.net'
option ipv4 '1'
option ipv6 '0'
option speed '10000'
option ports '5200,5201,5202,5203,5204,5205,5206,5207,5208,5209'
option tcp '1'
option udp '1'
option location 'Europe'
config server 'online_ipv6'
option host 'ping.online.net'
option ipv4 '0'
option ipv6 '1'
option speed '10000'
option ports '5200,5201,5202,5203,5204,5205,5206,5207,5208,5209'
option tcp '1'
option udp '1'
option location 'Europe'
config server 'serverius'
option host 'speedtest.serverius.net'
option ipv4 '1'
option ipv6 '1'
option speed '10000'
option ports '5002'
option tcp '1'
option udp '1'
option location 'Europe'
config server 'eenet'
option host 'iperf.eenet.ee'
option ipv4 '1'
option ipv6 '0'
option ports '5201'
option tcp '1'
option udp '1'
option location 'Europe'
config server 'volia'
option host 'iperf.volia.net'
option ipv4 '1'
option ipv6 '0'
option ports '5201'
option tcp '1'
option udp '1'
option location 'Europe'
config server 'it_north'
option host 'iperf.it-north.net'
option ipv4 '1'
option ipv6 '0'
option speed '1000'
option ports '5200,5201,5202,5203,5204,5205,5206,5207,5208,5209'
option tcp '1'
option udp '1'
option location 'Asia'
config server 'biznet'
option host 'iperf.biznetnetworkds.com'
option ipv4 '1'
option ipv6 '1'
option speed '1000'
option ports '5201,5202,5203'
option tcp '1'
option udp '0'
option location 'Asia'
config server 'scottlinux'
option host 'iperf.scottlinux.com'
option ipv4 '1'
option ipv6 '1'
option speed '1000'
option ports '5201'
option tcp '1'
option udp '1'
option location 'America'
config server 'he'
option host 'iperf.he.net'
option ipv4 '1'
option ipv6 '1'
option ports '5201'
option tcp '1'
option udp '1'
option location 'America'

View File

@ -0,0 +1,13 @@
{
"admin/services/iperf": {
"title": "iPerf",
"order": 10,
"action": {
"type": "template",
"path": "iperf/test"
},
"depends": {
"acl": [ "luci-app-iperf" ]
}
}
}

View File

@ -0,0 +1,11 @@
{
"luci-app-iperf": {
"description": "Grant UCI access for luci-app-iperf",
"read": {
"uci": [ "iperf" ]
},
"write": {
"uci": [ "iperf" ]
}
}
}

View File

@ -0,0 +1,44 @@
#
# Copyright (C) 2020-2021 sirpdboy <herboy2008@gmail.com>
# The LuCI Network diagnosis and speed test <https://github.com/sirpdboy/NetSpeedTest>
# This is free software, licensed under the GNU General Public License v3.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-netspeedtest
PKG_VERSION:=1.6
PKG_RELEASE:=20
PKG_LICENSE:=GPLv2
PKG_MAINTAINER:=sirpdboy
include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME)
SECTION:=luci
CATEGORY:=LuCI
SUBMENU:=3. Applications
TITLE:=LuCI Support for netspeedtest
DEPENDS:=+python3 +iperf3
PKGARCH:=all
endef
define Build/Compile
endef
define Package/$(PKG_NAME)/conffiles
/etc/config/netspeedtest
endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/lib/lua/luci
cp -pR ./luasrc/* $(1)/usr/lib/lua/luci
$(INSTALL_DIR) $(1)/
cp -pR ./root/* $(1)/
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n
po2lmo ./po/zh-cn/netspeedtest.po $(1)/usr/lib/lua/luci/i18n/netspeedtest.zh-cn.lmo
endef
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@ -0,0 +1,123 @@
[![若部分图片无法正常显示,请挂上机场浏览或点这里到末尾看修复教程](https://visitor-badge.glitch.me/badge?page_id=sirpdboy-visitor-badge)](#解决-github-网页上图片显示失败的问题) [![](https://img.shields.io/badge/TG群-点击加入-FFFFFF.svg)](https://t.me/joinchat/AAAAAEpRF88NfOK5vBXGBQ)
<a href="#readme">
<img src="https://img.vim-cn.com/a1/8713845a4aa922ac96619b0d2fb3d6919d37fc.png" alt="图飞了😂" title="NetSpeedTest" align="right" height="180" />
</a>
欢迎来到sirpdboy的源码仓库
=
Welcome to sirpdboy's git source of packages
-
[luci-app-NetSpeedTest — 网络速度测试1.5完整版](https://github.com/sirpdboy/NetSpeedTest)
======================
[![](https://img.shields.io/badge/-目录:-696969.svg)](#readme) [![](https://img.shields.io/badge/-写在前面-F5F5F5.svg)](#写在前面-) [![](https://img.shields.io/badge/-编译说明-F5F5F5.svg)](#编译说明-) [![](https://img.shields.io/badge/-说明-F5F5F5.svg)](#说明-) [![](https://img.shields.io/badge/-捐助-F5F5F5.svg)](#捐助-)
**认真阅读完毕** 本页面,本页面包含注意事项和如何使用。
a new netspeedtest luci app bese luci-app-netspeedtest
-
## 写在前面:[![](https://img.shields.io/badge/-写在前面-F5F5F5.svg)](#写在前面-)
一直在找OPENWRT上测试速度的插件苦寻不到于是有了它!
此插件可进行内外和外网网络速度测试。
1.内网测速基于iperf3 插件服务端路由器如果没有安装请先安装此ipk插件。
2.测速的终端使用机器必须和测速服务器在同一个局域网络中!
3.客户端使用步骤:
启动测速服务器端-->下载测试客户端-->运行测速客户端-->输入服务端IP地址-->查看结果。
5.客户端运行国内端下载中有“iperf3测速客户端”运行它输入服务器IP即可。
国外原版,需要手动进入 CMD命令模式再输入命令iperf3.exe -c 服务器IP
6.网络测速iperf3客户端下载地址https://sipdboy.lanzoui.com/b01c3esih 密码:cpd6
8.外网测速使用speedtest.net测速内核需要依赖speedtest,另外感谢superspeed和user1121114685因为借用了你们的灵感
9.外网测速最后测试阶段感谢佐大:佐须之男 测试查问题!
10.新插件难免有bug 请不要大惊小怪。欢迎提交bug。
11.安装需要依赖: python3 iperf3 。
## 编译说明 [![](https://img.shields.io/badge/-编译说明-F5F5F5.svg)](#编译说明-)
将NetSpeedTest 主题添加至 LEDE/OpenWRT 源码的方法。
## 下载源码方法一:
编辑源码文件夹根目录feeds.conf.default并加入如下内容:
```Brach
# feeds获取源码
src-git netspeedtest https://github.com/sirpdboy/netspeedtest
```
```Brach
# 更新feeds并安装主题
scripts/feeds update netspeedtest
scripts/feeds install luci-app-netspeedtest
```
## 下载源码方法二:
```Brach
# 下载源码
git clone https://github.com/sirpdboy/netspeedtest package/netspeedtest
make menuconfig
```
## 配置菜单
```Brach
make menuconfig
# 找到 LuCI -> Applications, 选择 luci-app-netspeedtest, 保存后退出。
```
## 编译
```Brach
# 编译固件
make package/netspeedtest/luci-app-netspeedtest/{clean,compile} V=s
```
## 说明 [![](https://img.shields.io/badge/-说明-F5F5F5.svg)](#说明-)
源码来源https://github.com/sirpdboy/netspeedtest/luci-app-netspeedtest
你可以随意使用其中的源码,但请注明出处。
============================
# My other project
网络速度测试 https://github.com/sirpdboy/netspeedtest
定时关机重启 : https://github.com/sirpdboy/luci-app-autopoweroff
关机功能插件 : https://github.com/sirpdboy/luci-app-poweroffdevice
opentopd主题 : https://github.com/sirpdboy/luci-theme-opentopd
opentoks 主题: https://github.com/sirpdboy/luci-theme-opentoks [仿KOOLSAHRE主题]
btmob 主题: https://github.com/sirpdboy/luci-theme-btmob
系统高级设置 : https://github.com/sirpdboy/luci-app-advanced
## 捐助 [![](https://img.shields.io/badge/-捐助-F5F5F5.svg)](#捐助-)
**如果你觉得此项目对你有帮助,请捐助我们,以使项目能持续发展,更加完善。··请作者喝杯咖啡~~~**
**你们的支持就是我的动力!**
### 捐助方式
| <img src="https://img.shields.io/badge/-支付宝-F5F5F5.svg" href="#赞助支持本项目-" height="25" alt="图飞了😂"/> | <img src="https://img.shields.io/badge/-微信-F5F5F5.svg" height="25" alt="图飞了😂" href="#赞助支持本项目-"/> |
| :-----------------: | :-------------: |
|<img src="https://img.vim-cn.com/fd/8e2793362ac3510094961b04407beec569b2b4.png" width="150" height="150" alt="图飞了😂" href="#赞助支持本项目-"/>|<img src="https://img.vim-cn.com/c7/675730a88accebf37a97d9e84e33529322b6e9.png" width="150" height="150" alt="图飞了😂" href="#赞助支持本项目-"/>|
<a href="#readme">
<img src="https://img.shields.io/badge/-返回顶部-orange.svg" alt="图飞了😂" title="返回顶部" align="right"/>
</a>
###### [解决 Github 网页上图片显示失败的问题](https://blog.csdn.net/qq_38232598/article/details/91346392)
[![](https://img.shields.io/badge/TG群-点击加入-FFFFFF.svg)](https://t.me/joinchat/AAAAAEpRF88NfOK5vBXGBQ)

View File

@ -0,0 +1,59 @@
module("luci.controller.netspeedtest", package.seeall)
function index()
entry({"admin","network","netspeedtest"},cbi("netspeedtest/netspeedtest", {hideapplybtn=true, hidesavebtn=true, hideresetbtn=true}),_("netspeedtest"),90).dependent=true
entry({"admin", "network","test_iperf0"}, post("test_iperf0"), nil).leaf = true
entry({"admin", "network","test_iperf1"}, post("test_iperf1"), nil).leaf = true
entry({"admin","network","netspeedtest", "run"}, call("run"))
entry({"admin", "network", "netspeedtest", "realtime_log"}, call("get_log"))
end
function testlan(cmd, addr)
luci.http.prepare_content("text/plain")
local util = io.popen(cmd)
if util then
while true do
local ln = util:read("*l")
if not ln then break end
luci.http.write(ln)
luci.http.write("\n")
end
util:close()
end
end
function testwan(cmd)
local util = io.popen(cmd)
util:close()
end
function test_iperf0(addr)
testlan("iperf3 -s ", addr)
end
function test_iperf1(addr)
luci.sys.call("killall iperf3")
end
function get_log()
local fs = require "nixio.fs"
local e = {}
e.running = luci.sys.call("busybox ps -w | grep netspeedtest | grep -v grep >/dev/null") == 0
e.log = fs.readfile("/var/log/netspeedtest.log") or ""
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function run()
testwan("/etc/init.d/netspeedtest nstest ")
luci.http.redirect(luci.dispatcher.build_url("admin","network","netspeedtest"))
end

View File

@ -0,0 +1,32 @@
-- Copyright 2018 sirpdboy (herboy2008@gmail.com)
require("luci.util")
local o,t,e
if luci.sys.call("pidof iperf3 >/dev/null") == 0 then
status = translate("<strong><font color=\"green\">iperf3 服务端运行中</font></strong>")
else
status = translate("<strong><font color=\"red\">iperf3 服务端已停止</font></strong>")
end
o = Map("netspeedtest", "<font color='green'>" .. translate("netspeedtest") .."</font>",translate( "Network speed diagnosis test (including intranet and extranet)") )
t = o:section(TypedSection, "netspeedtest", translate('iperf3 lanspeedtest'))
t.anonymous = true
t.description = translate(string.format("%s<br />", status))
e = t:option(DummyValue, '', '')
e.rawhtml = true
e.template ='netspeedtest/netspeedtest'
t=o:section(TypedSection,"netspeedtest",translate("wanspeedtest"))
t.anonymous=true
e = t:option(DummyValue, '', '')
e.rawhtml = true
e.template ='netspeedtest/speedtest'
e =t:option(DummyValue, '', '')
e.rawhtml = true
e.template = 'netspeedtest/log'
return o

View File

@ -0,0 +1,16 @@
<%+cbi/valueheader%>
<textarea id="logview" class="cbi-input-textarea" style="width: 100%" rows="10" readonly="readonly"></textarea>
<script type="text/javascript">
const LOG_URL = '<%=luci.dispatcher.build_url("admin", "network", "netspeedtest","realtime_log")%>';
XHR.poll(1, LOG_URL, null, (x, d) => {
let logview = document.getElementById("logview");
if (!d.running) {
XHR.halt();
}
logview.value = d.log;
logview.scrollTop = logview.scrollHeight;
});
</script>
<%+cbi/valuefooter%>

View File

@ -0,0 +1,84 @@
<%
local fs = require "nixio.fs"
%>
<script type="text/javascript" src="<%=resource%>/cbi.js?v=1.1"></script>
<script type="text/javascript">//<![CDATA[
var stxhr = new XHR();
function update_status(field, proto)
{
var tool = field.name;
var addr = field.value;
var protocol = proto ;
var legend = document.getElementById('test-rc-legend');
var output = document.getElementById('test-rc-output');
if (legend && output)
{
output.innerHTML =
'<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> ' +
'<%:Waiting for command to complete...%>'
;
legend.parentNode.style.display = 'block';
legend.style.display = 'inline';
stxhr.post('<%=url('admin/network')%>/test_' + tool + protocol + '/' + addr, { token: '<%=token%>' },
function(x)
{
if (x.responseText)
{
legend.style.display = 'none';
output.innerHTML = String.format('<pre>%h</pre>', x.responseText);
}
else
{
legend.style.display = 'none';
output.innerHTML ='</p><%:Operation execution complete%></p>';
}
}
);
}
}
//]]></script>
<form method="post" action="<%=url('admin/network/netspeedtest')%>">
<div style="width:100%; float:left">
<table>
<tr><td class="cbi-value-title" ><input style="margin: 5px 0" type="hidden" value="" name="iperf" />
<select name="iperf_to" style="width:auto">
<option value="0" selected="selected"><%:iperfstart%></option>
<option value="1"><%:iperfstop%></option>
</select></td>
<td class="cbi-value-field" style="width:100%;" >
<input type="button" value="<%:Perform operation%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.iperf,this.form.iperf_to.selectedIndex)" /></td>
</tr>
<tr><td class="cbi-value-title" ><%:iperf3 instructions%></td>
<td class="cbi-value-field" ><%:The speed measurement terminal must be in the same LAN as the router that starts the speed measurement%><br /><%:Operation steps: start router speed measurement service download test client run speed measurement client input IP address of router speed measurement service%></td>
</tr>
<tr>
<td class="cbi-value-title"><%:Iperf3 speed measurement software download%></td>
<td class="cbi-value-field" >
<input type="button" class="cbi-button cbi-input-reload" value="<%:Domestic download password:%>cpd6" onclick="javascript:window.open('https://sipdboy.lanzoui.com/b01c3esih','target');" />
<input type="button" class="cbi-button cbi-input-reload" value="<%:Download from foreign official websites%>" onclick="javascript:window.open('https://iperf.fr/iperf-download.php','target');" /></td>
</tr>
</table>
<fieldset class="cbi-section" style="display:none">
<legend id="test-rc-legend">
<%:Collecting data...%>
</legend>
<span id="test-rc-output"></span>
</fieldset>
</div>
</form>

View File

@ -0,0 +1,31 @@
<%+cbi/valueheader%>
<label class="cbi-value-title"> </label>
<div class="cbi-value-field">
<input class="cbi-button cbi-button-apply" id="update_service" type="button" size="0" onclick="run()" value="<%= translate('Perform wanspeedtest') %>" />
</div>
<script type="text/javascript">
const RUN_URL = '<%=luci.dispatcher.build_url("admin", "network", "netspeedtest","run")%>';
const S_URL = '<%=luci.dispatcher.build_url("admin", "network", "netspeedtest")%>';
function run() {
var legend = document.getElementById('test-rc-legend');
var output = document.getElementById('test-rc-output');
output.innerHTML =
'<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> ' +
'<%:Network speed test, please wait for 1 minutes%>'
;
legend.parentNode.style.display = 'block';
legend.style.display = 'inline';
XHR.get(RUN_URL, null, () => {
setTimeout(() => { window.location = S_URL }, 3000);
});
return false;
}
</script>
<%+cbi/valuefooter%>

View File

@ -0,0 +1,66 @@
#
# Copyright (C) 2020-2021 sirpdboy herboy2008@gmail.com
# This is free software, licensed under the GNU General Public License v3.
#
msgid ""
msgstr ""
"Project-Id-Version: LuCi Chinese Translation\n"
"Report-Msgid-Bugs-To: \n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Pootle 2.0.6\n"
msgid "netspeedtest"
msgstr "网速测试"
msgid "Network speed diagnosis test (including intranet and extranet)"
msgstr "网络速度诊断测试(包括内网和外网)"
msgid "iperf3 lanspeedtest"
msgstr "iperf3 内网测速"
msgid "iperfstart"
msgstr "iperf服务启动"
msgid "iperfstop"
msgstr "iperf服务停止"
msgid "Perform operation"
msgstr "执行操作"
msgid "iperf3 instructions"
msgstr "iperf3 使用说明"
msgid "Test speed service started"
msgstr "测试速度服务已经启动"
msgid "The speed measurement terminal must be in the same LAN as the router that starts the speed measurement"
msgstr "测速终端机必须与启动测速的路由器在同一局域网内"
msgid "Operation steps: start router speed measurement service download test client run speed measurement client input IP address of router speed measurement service"
msgstr "使用步骤A.启动路由器测速服务 B.下载测试客户端 C.运行测速客户端 D.输入路由器测速服务IP地址。 "
msgid "Domestic download password:"
msgstr "国内下密码:"
msgid "Iperf3 speed measurement software download"
msgstr "iperf3测速软件下载"
msgid "wanspeedtest"
msgstr "宽带速率测试"
msgid "Perform wanspeedtest"
msgstr "执行宽带测速"
msgid "Operation execution complete"
msgstr "操作执行完毕"
msgid "Network speed test, please wait for 1 minutes"
msgstr "网速测试中请稍等1分钟"
msgid "Download from foreign official websites"
msgstr "国外官网"

View File

@ -0,0 +1 @@
zh-cn

View File

@ -0,0 +1,8 @@
config netspeedtest
option enabled '0'
config wanspeedtest
option enabled '0'

View File

@ -0,0 +1,55 @@
#!/bin/sh /etc/rc.common
# Copyright 2020 -2021 sirpdboy (herboy2008@gmail.com)
START=95
STOP=10
. /lib/functions.sh
EXTRA_COMMANDS="nstest"
EXTRA_HELP=" netspeedtest"
NS_FILE=/usr/share/netspeedtest/netspeedtest.txt
TMP_T=/tmp/netspeedtest
LOG="/var/log/netspeedtest.log"
limit_log() {
local logf=$1
[ ! -f "$logf" ] && return
local sc=100
[ -n "$2" ] && sc=$2
local count=$(grep -c "" $logf)
if [ $count -gt $sc ];then
let count=count-$sc
sed -i "1,$count d" $logf
fi
}
init_env() {
[ ! -f "$LOG" ] && echo "netspeedtest by sirpdboy" > $LOG
echo 1 > $NS_FILE
}
nstest() {
init_env
[ -f "$TMP_T" ] && return
echo 1 > $TMP_T
echo -ne "\n ————————————————————————————" | tee -a $LOG
/etc/init.d/speedtest | tee -a $NS_FILE
ns_server=`cat $NS_FILE | grep 'Hosted by' | cut -c10-`
ns_down=`cat $NS_FILE | grep 'Download:' |awk -F: '{printf $2}' `
ns_up=`cat $NS_FILE | grep 'Upload:' |awk -F: '{printf $2}' `
echo -ne "\n 测服信息:${ns_server} " | tee -a $LOG
echo -ne "\n 下行速率:${ns_down} ---- 上行速率:${ns_up} " | tee -a $LOG
echo -ne "\n 测试时间: " | tee -a $LOG
echo $(date +%Y-%m-%d" "%H:%M:%S) | tee -a $LOG
rm -rf $TMP_T
}
reload(){
start
}
start() {
limit_log $LOG 200
nstest
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
#!/bin/sh
chmod 755 /etc/init.d/netspeedtest /etc/init.d/speedtest >/dev/null 2>&1
uci -q batch <<-EOF >/dev/null
delete ucitrack.@netspeedtest[-1]
add ucitrack netspeedtest
set ucitrack.@netspeedtest[-1].init=netspeedtest
commit ucitrack
EOF
rm -rf /tmp/luci-modulecache /tmp/luci-indexcache*
exit 0

View File

@ -0,0 +1,11 @@
{
"luci-app-netspeedtest": {
"description": "Grant UCI access for luci-app-netspeedtest",
"read": {
"uci": [ "netspeedtest" ]
},
"write": {
"uci": [ "netspeedtest" ]
}
}
}

View File

@ -0,0 +1,15 @@
# Copyright (C) 2016 Openwrt.org
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI support for NginxManager From sundaqiang
LUCI_DEPENDS:=+luci-nginx +luci-ssl-nginx +luci-ssl-openssl
LUCI_PKGARCH:=all
PKG_MAINTAINER:=sundaqiang
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,39 @@
module("luci.controller.nginx-manager", package.seeall)
function index()
nixio.fs.rename ("/etc/nginx/uci.conf", "/etc/nginx/ucibak.conf")
if not nixio.fs.access("/etc/nginx/nginx.conf") then
nixio.fs.copyr("/var/lib/nginx/uci.conf", "/etc/nginx/nginx.conf")
luci.sys.call("/etc/init.d/nginx restart")
end
file=nixio.fs.readfile("/etc/uwsgi/vassals/luci-webui.ini")
if tonumber(file:match("limit%pas[%p%s]+(%d+)")) < 5000 then
file=file:gsub("limit%pas[%p%s]+(%d+)","limit-as = 5000")
nixio.fs.writefile("/etc/uwsgi/vassals/luci-webui.ini", file)
luci.sys.call("/etc/init.d/uwsgi restart")
end
nixio.fs.writefile("/etc/config/nginx-manager", "")
x = luci.model.uci.cursor()
x:set("nginx-manager", "main", "nginx")
x:set("nginx-manager", "main", "name", "main")
x:set("nginx-manager", "main", "filepath", "/etc/nginx/nginx.conf")
for path in nixio.fs.dir("/etc/nginx/conf.d") do
if path:find(".conf$") ~= nil then
name = path:gsub(".conf", "")
x:set("nginx-manager", name, "nginx")
x:set("nginx-manager", name, "name", name)
x:set("nginx-manager", name, "filepath", "/etc/nginx/conf.d/" .. path)
end
end
x:commit("nginx-manager")
entry({"admin", "services", "nginx-manager"}, cbi("nginx-manager"), _("Nginx Manager"), 95).dependent = true
entry({"admin", "services", "nginx-manager", "setstatus"}, call("setstatus")).leaf = true
end
function setstatus()
local e = {}
local mode = luci.http.formvalue('mode')
e.code=luci.sys.call("/etc/init.d/nginx " .. mode)
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end

View File

@ -0,0 +1,43 @@
local fs = require "nixio.fs"
local m = Map("nginx-manager",translate("Nginx Manager"), translate("A simple Nginx manager") .. [[<br /><br /><a href="https://github.com/sundaqiang/openwrt-packages" target="_blank">Powered by sundaqiang</a>]])
s = m:section(TypedSection, "nginx", translate("Web site list"))
s.template = "nginx-manager/index"
s.addremove = true
s.anonymous = false
s:tab("general", translate("General Info"))
s:tab("server", translate("Configuration File"))
s:taboption("general", DummyValue, "name", translate("name"))
s:taboption("general", DummyValue, "filepath", translate("File Path"))
file=s:taboption("server", TextValue, "")
file.template = "cbi/tvalue"
file.rows = 25
file.wrap = "off"
file.rmempty = true
function s.create(self,section)
path="/etc/nginx/conf.d/" .. section .. ".conf"
fs.copyr("/etc/nginx/conf.d/templates", path)
TypedSection.create(self,section)
self.map:set(section, "name", section)
self.map:set(section, "filepath", path)
return true
end
function s.remove(self,section)
path="/etc/nginx/conf.d/" .. section .. ".conf"
fs.remove(path)
TypedSection.remove(self,section)
end
function sync_value_to_file(value, file)
value = value:gsub("\r\n?", "\n")
local old_value = fs.readfile(file)
if value ~= old_value then
fs.writefile(file, value)
end
end
function file.cfgvalue(self,section)
return fs.readfile(self.map:get(section, "filepath")) or ""
end
function file.write(self, section, value)
sync_value_to_file(value, self.map:get(section, "filepath"))
end
return m

View File

@ -0,0 +1,65 @@
<fieldset class="cbi-section" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
<% if self.title and #self.title > 0 then -%>
<legend><%=self.title%></legend>
<%- end %>
<% if self.description and #self.description > 0 then -%>
<div class="cbi-section-descr"><%=self.description%></div>
<%- end %>
<div class="cbi-value" style="border-bottom: 1px solid #ddd;border-radius: 0px">
<label class="cbi-value-title"><%= translate("Restart the nginx") %></label>
<div class="cbi-value-field" style="padding:unset">
<input class="btn cbi-button cbi-button-reload" id="restart" type="button" size="0" onclick="check_status('restart')" value="<%:Restart%>" />
</div>
<label class="cbi-value-title"><%= translate("Reload the nginx") %></label>
<div class="cbi-value-field" style="padding:unset">
<input class="btn cbi-button cbi-button-reload" id="reload" type="button" size="0" onclick="check_status('reload')" value="<%:Reload%>" />
</div>
</div>
<% local isempty = true for i, k in ipairs(self:cfgsections()) do -%>
<%- section = k; isempty = false -%>
<% if not self.anonymous then -%>
<div class="cbi-section-remove" style="display: flex;flex-flow: row nowrap;justify-content: space-between">
<span style="font-size:1.15rem;color:#32325d;font-weight:bold;letter-spacing:0.1rem;padding:1rem 1.5rem;"><%=section:upper()%></span>
<input type="submit" name="cbi.rts.<%=self.config%>.<%=k%>" onclick="this.form.cbi_state='del-section'; return true" value="<%:Delete%>" class="cbi-button" />
</div>
<%- end %>
<%+cbi/tabmenu%>
<fieldset class="cbi-section-node<% if self.tabs then %> cbi-section-node-tabbed<% end %>" id="cbi-<%=self.config%>-<%=section%>" style="border-bottom: 1px solid #ddd;border-radius: 0px">
<%+cbi/ucisection%>
</fieldset>
<%- end %>
<% if isempty then -%>
<em><%:This section contains no values yet%><br /><br /></em>
<%- end %>
<% if self.addremove then -%>
<% if self.template_addremove then include(self.template_addremove) else -%>
<div class="cbi-section-create">
<% if self.anonymous then -%>
<input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" value="<%:Add%>" />
<%- else -%>
<% if self.invalid_cts then -%><div class="cbi-section-error"><% end %>
<input type="text" class="cbi-section-create-name" id="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" data-type="uciname" data-optional="true" />
<input type="submit" class="cbi-button cbi-button-add" onclick="this.form.cbi_state='add-section'; return true" value="<%:Add%>" />
<% if self.invalid_cts then -%>
<br /><%:Invalid%></div>
<%- end %>
<%- end %>
</div>
<%- end %>
<%- end %>
</fieldset>
<style>.cbi-value-field {padding: 11.2px;}.cbi-tabmenu {border-bottom: unset !important;}</style>
<script type="text/javascript">
function check_status(mode) {
const tb = document.getElementById(mode);
tb.disabled = true;
XHR.get('<%=url([[admin]], [[services]], [[nginx-manager]], [[setstatus]])%>', {mode: mode}, (x, r) => {
tb.disabled = false;
});
}
</script>

View File

@ -0,0 +1,26 @@
msgid "Nginx Manager"
msgstr "Nginx管理器"
msgid "A simple Nginx manager"
msgstr "一个简易的Nginx管理器"
msgid "Web site list"
msgstr "网站列表"
msgid "Restart the nginx"
msgstr "重新启动Nginx"
msgid "Reload the nginx"
msgstr "重新加载Nginx"
msgid "Reload"
msgstr "重新加载"
msgid "Configuration File"
msgstr "配置文件"
msgid "General Info"
msgstr "基础信息"
msgid "File Path"
msgstr "文件路径"

View File

@ -0,0 +1 @@
zh-cn

View File

@ -0,0 +1,17 @@
server {
listen 8080; #bind prot 绑定的端口
root /www; #directory 网站路径
ssl_session_timeout 5m;
gzip on;
gzip_types text/plain application/json application/javascript application/x-javascript text/css application/xml text/javascript;
gzip_proxied any;
gzip_vary on;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.0;
location / {
index index.html index.htm; #默认文件
try_files $uri $uri/ /index.html;
}
}

View File

@ -0,0 +1,11 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@nginx-manager[-1]
add ucitrack nginx-manager
set ucitrack.@nginx-manage[-1].init=nginx
commit ucitrack
EOF
rm -f /tmp/luci-indexcache
exit 0

View File

@ -0,0 +1,11 @@
{
"luci-app-nginx-manager": {
"description": "Grant UCI access for luci-app-nginx-manager",
"read": {
"uci": [ "nginx-manager" ]
},
"write": {
"uci": [ "nginx-manager" ]
}
}
}

121
luci-app-store/API.md Normal file
View File

@ -0,0 +1,121 @@
### 路由器端API
0. 获取csrfToken用于POST请求
```
GET /cgi-bin/luci/admin/store/token
{"token":"xxx"}
```
1. 已安装软件列表
```
GET /cgi-bin/luci/admin/store/installed
[
{
"description": "DDNS.TO内网穿透",
"tags": [
"net",
"tool"
],
"entry": "/cgi-bin/luci/admin/services/ddnsto",
"author": "xiaobao",
"depends": [
"ddnsto",
"luci-app-ddnsto",
"luci-i18n-ddnsto-zh-cn"
],
"title": "DDNS.TO",
"time": 1629356347,
"release": 1,
"website": "https://www.ddnsto.com/",
"name": "ddnsto",
"version": "1.0.0"
}
]
```
2. 安装软件
```
POST /cgi-bin/luci/admin/store/install
token=xxx&package=upnp
{"code":0, "stdout":"", "stderr":""}
```
3. 更新软件
```
POST /cgi-bin/luci/admin/store/upgrade
token=xxx&package=upnp
{"code":0, "stdout":"", "stderr":""}
```
4. 卸载软件
```
POST /cgi-bin/luci/admin/store/remove
token=xxx&package=upnp
{"code":0, "stdout":"", "stderr":""}
```
5. 刷新可用软件列表
```
POST /cgi-bin/luci/admin/store/update
token=xxx
{"code":0, "stdout":"", "stderr":""}
```
6. 查询特定软件状态
```
GET /cgi-bin/luci/admin/store/status?package=ddnsto
{
"description": "DDNS.TO内网穿透",
"tags": [
"net",
"tool"
],
"entry": "/cgi-bin/luci/admin/services/ddnsto",
"author": "xiaobao",
"depends": [
"ddnsto",
"luci-app-ddnsto",
"luci-i18n-ddnsto-zh-cn"
],
"installed": true,
"title": "DDNS.TO",
"time": "1629356347",
"release": 1,
"website": "https://www.ddnsto.com/",
"name": "ddnsto",
"version": "1.0.0"
}
{"installed":false}
```
7. 任务状态(日志)
```
GET /cgi-bin/luci/admin/store/log
{
"stdout": "Installing app-meta-ddnsto (1.0.0) to root...\nDownloading http://192.168.9.168:9999/packages/aarch64_cortex-a53/meta/app-meta-ddnsto_1.0.0_all.ipk\nConfiguring app-meta-ddnsto.\n",
"stderr": "",
"code": 206
}
{"stdout":"","stderr":"","code":0}
```
8. 上传安装
```
POST /cgi-bin/luci/admin/store/upload
(文件上传表单,支持文件扩展名".ipk,.run")
{"code":0, "stdout":"", "stderr":""}
```

25
luci-app-store/Makefile Normal file
View File

@ -0,0 +1,25 @@
# Copyright (C) 2016 Openwrt.org
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI based ipk store
LUCI_DESCRIPTION:=luci-app-store is a ipk store developed by LinkEase team
LUCI_DEPENDS:=+curl
LUCI_PKGARCH:=all
PKG_MAINTAINER:=jjm2473 <jjm2473@gmail.com>
LUCI_BUILD_DEPENDS:=app-store-ui/host
TARGET_CONFIGURE_OPTS = FRONTEND_DIST="$(BUILD_DIR_HOST)/app-store-ui/dist" APP_STORE_VERSION="$(PKG_VERSION)"
define Package/luci-app-store/conffiles
/etc/.app_store.id
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

3
luci-app-store/README.md Normal file
View File

@ -0,0 +1,3 @@
# luci-app-store
OpenWRT应用商店

View File

@ -0,0 +1,222 @@
module("luci.controller.store", package.seeall)
local myopkg = "is-opkg"
local page_index = {"admin", "store", "pages"}
function index()
local function store_api(action, onlypost)
local e = entry({"admin", "store", action}, onlypost and post("store_action", {action = action}) or call("store_action", {action = action}))
e.dependent = false -- 父节点不是必须的
e.leaf = true -- 没有子节点
end
local action
entry({"admin", "store"}, call("redirect_index"), _("iStore"), 31)
entry({"admin", "store", "pages"}, call("store_index")).leaf = true
entry({"admin", "store", "token"}, call("store_token"))
entry({"admin", "store", "log"}, call("store_log"))
entry({"admin", "store", "uid"}, call("action_user_id"))
entry({"admin", "store", "upload"}, post("store_upload"))
for _, action in ipairs({"update", "install", "upgrade", "remove"}) do
store_api(action, true)
end
for _, action in ipairs({"status", "installed"}) do
store_api(action, false)
end
end
local function user_id()
local jsonc = require "luci.jsonc"
local json_parse = jsonc.parse
local fs = require "nixio.fs"
local data = fs.readfile("/etc/.app_store.id")
local id
if data ~= nil then
id = json_parse(data)
end
if id == nil then
fs.unlink("/etc/.app_store.id")
id = {arch="",uid=""}
end
id.version = (fs.readfile("/etc/.app_store.version") or "?"):gsub("[\r\n]", "")
return id
end
function redirect_index()
luci.http.redirect(luci.dispatcher.build_url(unpack(page_index)))
end
function store_index()
luci.template.render("store/main", {prefix=luci.dispatcher.build_url(unpack(page_index)),id=user_id()})
end
function store_log()
local fs = require "nixio.fs"
local code = 0
local e = fs.readfile("/tmp/log/istore.stderr")
local o = fs.readfile("/tmp/log/istore.stdout")
if o ~= nil then
code = 206
end
luci.http.prepare_content("application/json")
luci.http.write_json({code=code,stdout=o or "",stderr=e or ""})
end
function action_user_id()
luci.http.prepare_content("application/json")
luci.http.write_json(user_id())
end
-- Internal action function
local function _action(exe, cmd, ...)
local os = require "os"
local fs = require "nixio.fs"
local pkg = ""
for k, v in pairs({...}) do
pkg = pkg .. " '" .. v:gsub("'", "") .. "'"
end
local c = "%s %s %s >/tmp/log/istore.stdout 2>/tmp/log/istore.stderr" %{ exe, cmd, pkg }
local r = os.execute(c)
local e = fs.readfile("/tmp/log/istore.stderr")
local o = fs.readfile("/tmp/log/istore.stdout")
fs.unlink("/tmp/log/istore.stderr")
fs.unlink("/tmp/log/istore.stdout")
return r, o or "", e or ""
end
function store_action(param)
local metadir = "/usr/lib/opkg/meta"
local metapkgpre = "app-meta-"
local code, out, err, ret, out0, err0
local fs = require "nixio.fs"
local ipkg = require "luci.model.ipkg"
local jsonc = require "luci.jsonc"
local json_parse = jsonc.parse
local action = param.action or ""
if action == "status" then
local pkg = luci.http.formvalue("package")
local metapkg = metapkgpre .. pkg
local meta = {}
local metadata = fs.readfile(metadir .. "/" .. pkg .. ".json")
if metadata ~= nil then
meta = json_parse(metadata)
end
meta.installed = false
local status = ipkg.status(metapkg)
if next(status) ~= nil then
meta.installed=true
meta.time=tonumber(status[metapkg]["Installed-Time"])
end
ret = meta
elseif action == "installed" then
local itr = fs.dir(metadir)
local data = {}
if itr then
local pkg
for pkg in itr do
if pkg:match("^.*%.json$") then
local meta = json_parse(fs.readfile(metadir .. "/" .. pkg))
local metapkg = metapkgpre .. meta.name
local status = ipkg.status(metapkg)
if next(status) ~= nil then
meta.time = tonumber(status[metapkg]["Installed-Time"])
data[#data+1] = meta
end
end
end
end
ret = data
else
local pkg = luci.http.formvalue("package")
local metapkg = metapkgpre .. pkg
if action == "update" or pkg then
if action == "update" or action == "install" then
code, out, err = _action(myopkg, action, metapkg)
else
local meta = json_parse(fs.readfile(metadir .. "/" .. pkg .. ".json"))
if action == "upgrade" then
code, out, err = _action(myopkg, action, unpack(meta.depends), metapkg)
else -- remove
code, out, err = _action(myopkg, action, unpack(meta.depends), metapkg)
if code ~= 0 then
code, out0, err0 = _action(myopkg, action, unpack(meta.depends), metapkg)
out = out .. out0
err = err .. err0
end
fs.unlink("/tmp/luci-indexcache")
end
end
else
code = 400
err = "package is null"
end
ret = {
code = code,
stdout = out,
stderr = err
}
end
luci.http.prepare_content("application/json")
luci.http.write_json(ret)
end
function store_token()
luci.http.prepare_content("application/json")
require "luci.template".render_string("{\"token\":\"<%=token%>\"}")
end
function store_upload()
local fd
local path
local finished = false
local tmpdir = "/tmp/is-root/tmp"
luci.http.setfilehandler(
function(meta, chunk, eof)
if not fd then
path = tmpdir .. "/" .. meta.file
nixio.fs.mkdirr(tmpdir)
fd = io.open(path, "w")
end
if chunk then
fd:write(chunk)
end
if eof then
fd:close()
finished = true
end
end
)
local code, out, err
out = ""
if finished then
if string.lower(string.sub(path, -4, -1)) == ".run" then
code, out, err = _action("sh", "-c", "chmod 755 \"%s\" && \"%s\"" %{ path, path })
else
code, out, err = _action(myopkg, "install", path)
end
else
code = 500
err = "upload failed!"
end
nixio.fs.unlink(path)
local ret = {
code = code,
stdout = out,
stderr = err
}
luci.http.prepare_content("application/json")
luci.http.write_json(ret)
end

View File

@ -0,0 +1,24 @@
<%+header%>
<link rel="stylesheet" href="/luci-static/istore/style.css">
<script>
(function(){
var vue_prefix="<%=prefix%>";
var myurl = window.location.pathname;
window.addEventListener('popstate', () => {
if (myurl != window.location.pathname
&& window.location.pathname != vue_prefix
&& ! window.location.pathname.startsWith(vue_prefix+'/')) {
window.location.href = window.location.pathname;
}
});
window.vue_base = vue_prefix + '/';
window.token = "<%=token%>";
window.device_id = {arch:"<%=id.arch%>",uid:"<%=id.uid%>",version:"<%=id.version%>"};
})();
</script>
<h2 name="content">应用商店 v<%=id.version%></h2>
<div id="app">
</div>
<script type="module" crossorigin src="/luci-static/istore/index.js"></script>
<link rel="modulepreload" href="/luci-static/istore/vendor.js">
<%+footer%>

100
luci-app-store/root/bin/is-opkg Executable file
View File

@ -0,0 +1,100 @@
#!/bin/sh
IS_ROOT=/tmp/is-root
DL_DIR=${IS_ROOT}/tmp/dl
LISTS_DIR_O=/tmp/opkg-lists
LISTS_DIR=${IS_ROOT}${LISTS_DIR_O}
OPKG_CONF_DIR=${IS_ROOT}/etc/opkg
FEEDS_SERVER=https://istore.linkease.com/repo
ARCH=`opkg -f /dev/null print-architecture | grep -v 'arch all' | grep -v 'arch noarch' | cut -d ' ' -f2`
action=${1}
shift
is_init() {
mkdir -p ${DL_DIR} ${LISTS_DIR} ${IS_ROOT}/etc ${IS_ROOT}/var
cat /etc/opkg.conf | grep -v lists_dir | grep -v check_signature > ${IS_ROOT}/etc/opkg.conf
cp ${IS_ROOT}/etc/opkg.conf ${IS_ROOT}/etc/opkg_o.conf
echo >> ${IS_ROOT}/etc/opkg.conf
echo "lists_dir ext ${LISTS_DIR}" >> ${IS_ROOT}/etc/opkg.conf
echo >> ${IS_ROOT}/etc/opkg_o.conf
echo "lists_dir ext ${LISTS_DIR_O}" >> ${IS_ROOT}/etc/opkg_o.conf
[ -e ${IS_ROOT}/var/lock ] || {
cp -a /etc/opkg ${IS_ROOT}/etc/
ln -s /var/lock ${IS_ROOT}/var/lock
}
}
opkg_wrap() {
OPKG_CONF_DIR=${OPKG_CONF_DIR} opkg -f ${IS_ROOT}/etc/opkg.conf "$@"
}
update() {
curl -o ${OPKG_CONF_DIR}/meta.conf "${FEEDS_SERVER}/all/meta.conf" && \
curl -o ${OPKG_CONF_DIR}/all.conf "${FEEDS_SERVER}/all/isfeeds.conf" && \
curl -o ${OPKG_CONF_DIR}/arch.conf "${FEEDS_SERVER}/${ARCH}/isfeeds.conf" && \
opkg -f ${IS_ROOT}/etc/opkg_o.conf --offline-root ${IS_ROOT} update
return 0
}
check_mtime() {
find ${OPKG_CONF_DIR}/arch.conf -mtime -1 2>/dev/null | grep -q . || update
}
wrapped_in_update() {
check_mtime || return 1
opkg_wrap "$@" && return 0
local idle_t=$((`date '+%s'` - `date -r ${IS_ROOT}/.last_force_ts '+%s' 2>/dev/null || echo '0'`))
[ $idle_t -gt 120 ] || return 1
update || return 1
touch ${IS_ROOT}/.last_force_ts
opkg_wrap "$@"
}
new_upgrade() {
local metapkg=`echo "$@" | sed 's/ /\n/g' | grep -F app-meta-`
if [ -n "$metapkg" ] && opkg_wrap info $metapkg | grep -qF not-installed ; then
true
else
local idle_t=$((`date '+%s'` - `date -r ${IS_ROOT}/.last_force_ts '+%s' 2>/dev/null || echo '0'`))
if [ $idle_t -gt 120 ]; then
update && touch ${IS_ROOT}/.last_force_ts
fi
fi
wrapped_in_update upgrade "$@"
}
usage() {
echo "usage: is-opkg sub-command [arguments...]"
echo "where sub-command is one of:"
echo " update Update list of available packages"
echo " upgrade <pkgs> Upgrade packages"
echo " install <pkgs> Install package(s)"
echo " remove <pkgs> Remove package(s)"
}
is_init >/dev/null 2>&1
case $action in
"update")
update
;;
"install")
wrapped_in_update install "$@"
;;
"upgrade")
new_upgrade "$@"
;;
"remove")
opkg_wrap --autoremove --force-removal-of-dependent-packages remove "$@"
;;
*)
usage
;;
esac

View File

@ -0,0 +1,25 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2016 OpenWrt.org
START=45
boot() {
[ -s /etc/.app_store.id ] && return 0
mkdir -p /tmp/is-inst/var/lock
ARCH=`opkg -f /dev/null --offline-root /tmp/is-inst print-architecture | grep -v 'arch all' | grep -v 'arch noarch' | cut -d ' ' -f2`
rm -rf /tmp/is-inst
for iface in eth0 br-lan; do
if [ -e /sys/class/net/$iface/address ]; then
HASH=`md5sum /sys/class/net/$iface/address | cut -d ' ' -f1`
break
fi
done
if [ -z "$HASH" ]; then
HASH=`dd if=/dev/urandom bs=512 count=1 2>/dev/null | md5sum | cut -d ' ' -f1`
fi
echo "{\"arch\":\"${ARCH}\", \"uid\":\"${HASH}\"}" > /etc/.app_store.id
}

View File

@ -0,0 +1,5 @@
#!/bin/sh
/etc/init.d/istore boot
rm -rf /tmp/luci-indexcache /tmp/luci-modulecache

View File

@ -0,0 +1,7 @@
clean:
compile:
install:
mkdir -p "$(DESTDIR)/www/luci-static"
cp -a "$(FRONTEND_DIST)/luci-static/istore" "$(DESTDIR)/www/luci-static/"
mkdir -p "$(DESTDIR)/etc"
echo "$(APP_STORE_VERSION)" > "$(DESTDIR)/etc/.app_store.version"

View File

@ -0,0 +1,14 @@
# Copyright (C) 2016 Openwrt.org
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI support for NginxManager From sundaqiang
LUCI_PKGARCH:=all
PKG_MAINTAINER:=sundaqiang
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,234 @@
module("luci.controller.supervisord", package.seeall)
function index()
if not nixio.fs.access("/etc/config/supervisord") then return end
entry({"admin", "services", "supervisord"}, cbi("supervisord"), _("Supervisord"), 95).dependent = true
entry({"admin", "services", "supervisord", "status"}, call("status")).leaf = true
entry({"admin", "services", "supervisord", "getver"}, call("getver")).leaf = true
entry({"admin", "services", "supervisord", "update"}, call("update")).leaf = true
entry({"admin", "services", "supervisord", "gettask"}, call("gettask")).leaf = true
entry({"admin", "services", "supervisord", "starttask"}, call("starttask")).leaf = true
entry({"admin", "services", "supervisord", "restarttask"}, call("restarttask")).leaf = true
entry({"admin", "services", "supervisord", "stoptask"}, call("stoptask")).leaf = true
entry({"admin", "services", "supervisord", "removetask"}, call("removetask")).leaf = true
entry({"admin", "services", "supervisord", "addtask"}, call("addtask")).leaf = true
entry({"admin", "services", "supervisord", "savetask"}, call("savetask")).leaf = true
entry({"admin", "services", "supervisord", "getlog"}, call("getlog")).leaf = true
end
function Split(str, delim, maxNb)
-- Eliminate bad cases...
if string.find(str, delim) == nil then
return { str }
end
if maxNb == nil or maxNb < 1 then
maxNb = 0 -- No limit
end
local result = {}
local pat = "(.-)" .. delim .. "()"
local nb = 0
local lastPos
for part, pos in string.gfind(str, pat) do
nb = nb + 1
result[nb] = part
lastPos = pos
if nb == maxNb then break end
end
-- Handle the last field
if nb ~= maxNb then
result[nb + 1] = string.sub(str, lastPos)
end
return result
end
function status()
local e = {}
e.running = luci.sys.call("ps | grep supervisord | grep -v grep >/dev/null") == 0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function getver()
local e = {}
local c=luci.model.uci.cursor()
local d=c:get("supervisord", "main", "filepath")
e.nowver=luci.sys.exec(d .. " version")
e.newver=luci.sys.exec("uclient-fetch -qO- 'https://api.github.com/repos/ochinchina/supervisord/releases/latest' | jsonfilter -e '@.tag_name'")
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function update()
local e = {}
local c=luci.model.uci.cursor()
local d=c:get("supervisord", "main", "filepath")
local version = luci.http.formvalue('version')
local arch = nixio.uname().machine or ""
version = version:gsub("\n", "")
if nixio.fs.access("/usr/lib/os-release") then
LEDE_BOARD = luci.sys.exec("echo -n $(grep 'LEDE_BOARD' /usr/lib/os-release | awk -F '[\\042\\047]' '{print $2}')")
end
if nixio.fs.access("/etc/openwrt_release") then
DISTRIB_TARGET = luci.sys.exec("echo -n $(grep 'DISTRIB_TARGET' /etc/openwrt_release | awk -F '[\\042\\047]' '{print $2}')")
end
arch=luci.util.trim(arch)
if arch == "x86_64" then
arch = "64-bit"
end
filename = "supervisord_" .. version:gsub("v", "") .. "_Linux_" .. arch .. ".tar.gz"
nixio.fs.remove("/tmp/" .. filename)
u=c:get("supervisord", "main", "usechinamirror")
if u then
u="https://ghproxy.com/"
else
u=""
end
e.error=luci.sys.call("uclient-fetch -qO- -O '/tmp/" .. filename .. "' '" .. u .. "https://github.com/ochinchina/supervisord/releases/download/" .. version .. "/" .. filename .. "'")
if e.error == 0 then
e.error=luci.sys.exec("tar -xzvf '/tmp/" .. filename .. "' -C /tmp")
if e.error then
e.error=nixio.fs.mover("/tmp/" .. filename:gsub(".tar.gz", "") .. "/supervisord", d)
if e.error then
e.error=0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
else
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
else
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
end
function gettask()
local e = {}
local name = luci.http.formvalue('name')
local data = luci.sys.exec("supervisord ctl status " .. name)
e.status=string.gsub(string.sub(data, 34, 50), " ", "")
e.description=string.sub(data, 51)
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function starttask()
local e = {}
local name = luci.http.formvalue('name')
local data = luci.sys.exec("supervisord ctl start " .. name)
if string.find(data,"started") ~= nil then
e.code=1
else
e.code=0
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function restarttask()
local e = {}
local name = luci.http.formvalue('name')
local data = luci.sys.exec("supervisord ctl stop " .. name .. " && supervisord ctl start " .. name)
if string.find(data,"started") ~= nil then
e.code=1
else
e.code=0
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function stoptask()
local e = {}
local name = luci.http.formvalue('name')
local data = luci.sys.exec("supervisord ctl stop " .. name)
if string.find(data,"stopped") ~= nil then
e.code=1
else
e.code=0
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function removetask()
local e = {}
local name = luci.http.formvalue('name')
e.code=nixio.fs.remove('/etc/supervisord/program/' .. name .. '.ini')
if e.code then
luci.sys.call("supervisord ctl reload")
e.code=1
else
e.code=0
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function addtask()
local e = {}
local name = luci.http.formvalue('name')
if nixio.fs.access('/etc/supervisord/program/' .. name .. '.ini') then
e.code=2
luci.http.prepare_content("application/json")
luci.http.write_json(e)
return
end
file=nixio.fs.readfile("/etc/supervisord/program/templates")
file=file:gsub("demo", name)
e.code=nixio.fs.writefile('/etc/supervisord/program/' .. name .. '.ini', file)
if e.code then
luci.sys.call("supervisord ctl reload")
e.code=1
e.data=file
else
e.code=0
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function savetask()
local e = {}
local name = luci.http.formvalue('name')
local data = luci.http.formvalue('data')
data = data:gsub("\r\n?", "\n")
file = '/etc/supervisord/program/' .. name .. '.ini'
e.code=nixio.fs.writefile (file, data)
if e.code then
sysupgrade=nixio.fs.readfile("/etc/sysupgrade.conf")
if not sysupgrade:find(file) then
sysupgrade=sysupgrade .. '\n' .. file
end
backupfile=data:match("backupfile=([%a%d%p]+)")
backupfile=Split(backupfile, "||")
for k, v in ipairs(backupfile) do
if not sysupgrade:find(v:gsub("%p", "%%%1")) then
sysupgrade=sysupgrade .. '\n' .. v
end
end
nixio.fs.writefile ("/etc/sysupgrade.conf", sysupgrade)
luci.sys.call("supervisord ctl reload")
e.code=1
else
e.code=0
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function getlog()
local e = {}
local name = luci.http.formvalue('name')
if name=="main" then
local data = nixio.fs.readfile ('/etc/supervisord/supervisord.conf')
data = string.match(data, "logfile=([%a%d%p]+)")
e.data=nixio.fs.readfile (data)
else
local data = nixio.fs.readfile ('/etc/supervisord/program/' .. name .. '.ini')
data = string.match(data, "stdout_logfile=([%a%d%p]+)")
e.data=nixio.fs.readfile (data)
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end

View File

@ -0,0 +1,70 @@
local fs = require "nixio.fs"
local sys = require "luci.sys"
local m = Map("supervisord",translate("Supervisord"), translate("A golang development process management") .. [[<br /><br /><a href="https://github.com/sundaqiang/openwrt-packages" target="_blank">Powered by sundaqiang</a>]])
m:section(SimpleSection).template = "supervisord/index"
s = m:section(TypedSection, "supervisord")
s.addremove = false
s.anonymous = true
s:tab("general", translate("General Settings"))
s:tab("advanced", translate("Configuration File"))
s:tab("list", translate("Task List"))
s:tab("log", translate("Log List"))
f = s:taboption("general", Flag, "enabled", translate("Enabled"))
f.rmempty = false
v = s:taboption("general", Value, "filepath", translate("File Path"))
v.rmempty = false
v = s:taboption("general", Flag, "usechinamirror", translate("Use China Mirror"))
v.rmempty = false
b = s:taboption("general", Button, "")
b.template = "supervisord/version"
file=s:taboption("advanced", TextValue, "")
file.template = "cbi/tvalue"
file.rows = 15
file.wrap = "off"
file.rmempty = false
l=s:taboption("list", DummyValue, "")
l.template = "supervisord/list"
l.list={}
index=1
for filelist in fs.dir("/etc/supervisord/program") do
if filelist:find(".ini$") ~= nil then
name=fs.readfile("/etc/supervisord/program/" .. filelist)
l.list[index]={}
l.list[index][1]=name:match("program:(%a+)")
l.list[index][2]="/etc/supervisord/program/" .. filelist
local cmd=name:match("directory=([%a%d%p ]+)") .. "/" .. name:match("getversions=([%a%d%p ]+)")
l.list[index][3]=sys.exec(cmd)
index=index+1
end
end
g=s:taboption("log", DummyValue, "")
g.template = "supervisord/log"
g.list=l.list
function s.create(self,section)
return TypedSection.create(self,section)
end
function s.remove(self,section)
return TypedSection.remove(self,section)
end
function sync_value_to_file(self, section, value, file)
value = value:gsub("\r\n?", "\n")
local old_value = fs.readfile(file)
if value ~= old_value then
fs.writefile(file, value)
self.map:set(section, "amend", "1")
end
end
function file.cfgvalue(self,section)
return fs.readfile("/etc/supervisord/supervisord.conf") or ""
end
function file.write(self, section, value)
sync_value_to_file(self, section, value, "/etc/supervisord/supervisord.conf")
end
return m

View File

@ -0,0 +1,21 @@
<script type="text/javascript">
XHR.poll(3, '<%=url([[admin]], [[services]], [[supervisord]], [[status]])%>', null,
function(x, data) {
var tb = document.getElementById('status');
if (data && tb) {
if (data.running) {
var links = '<em><b><font color=green>Supervisord <%:RUNNING%></font></b></em>';
tb.innerHTML = links;
} else {
tb.innerHTML = '<em><b><font color=red>Supervisord <%:NOT RUNNING%></font></b></em>';
}
}
}
);
</script>
<style></style>
<fieldset class="cbi-section">
<p id="status">
<em><%:Collecting data...%></em>
</p>
</fieldset>

View File

@ -0,0 +1,163 @@
<%local fs = require "nixio.fs"%>
<%+cbi/valueheader%>
<div class="cbi-section-node">
<table class="cbi-section-table" id="task-list">
<tbody>
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell" style="width:120px!important"><%:Name%></th>
<th class="cbi-section-table-cell" style="width:120px!important"><%:Versions%></th>
<th class="cbi-section-table-cell" style="width:100px!important"><%:Status%></th>
<th class="cbi-section-table-cell" style="width:300px!important"><%:Description%></th>
<th class="cbi-section-table-cell"><%:Configuration File%></th>
<th class="cbi-section-table-cell" style="width:355px!important"><%:Action%></th>
</tr>
<% for _,item in pairs(self.list) do %>
<tr class="cbi-section-table-row" id="<%=item[2]:gsub('/etc/supervisord/program/', ""):gsub('.ini', "")%>-main">
<td class="cbi-value-field">
<%=item[1]%>
</td>
<td class="cbi-value-field">
<%=item[3]%>
</td>
<td class="cbi-value-field" id="<%=item[1]%>-status">
</td>
<td class="cbi-value-field" id="<%=item[1]%>-description">
</td>
<td class="cbi-value-field">
<textarea class="cbi-input-textarea" id="<%=item[1]%>-text" rows="15" wrap="off"><%=fs.readfile(item[2])%></textarea>
</td>
<td class="cbi-value-field">
<input class="cbi-button cbi-input-apply" style="font-size: 100%;background-color: green!important;" type="button" id="<%=item[1]%>-start" disabled
onclick="actions('starttask','<%=item[1]%>')" value="<%:Start%>" size="0">
<input class="cbi-button cbi-input-remove" style="font-size: 100%;background-color: #333333!important;" type="button" id="<%=item[1]%>-stop" disabled
onclick="actions('stoptask','<%=item[1]%>')" value="<%:Stop%>" size="0">
<input class="cbi-button cbi-input-apply" style="font-size: 100%;" type="button"
onclick="actions('restarttask','<%=item[1]%>')" value="<%:Reboot%>" size="0">
<input class="cbi-button cbi-input-remove" style="font-size: 100%;" type="button"
onclick="actions('savetask','<%=item[2]:gsub('/etc/supervisord/program/', ''):gsub('.ini', '')%>')" value="<%:Save%>" size="0">
<input class="cbi-button cbi-button-remove" style="font-size: 100%;" type="button"
onclick="actions('removetask','<%=item[2]:gsub('/etc/supervisord/program/', ''):gsub('.ini', '')%>')" value="<%:Delete%>" size="0">
</td>
</tr>
<% end %>
</tbody>
</table>
<div class="cbi-section-create">
<input type="text" class="cbi-section-create-name" id="addtext" value="" maxlength="20" size="0">
<input class="cbi-button cbi-button-add" onclick="addtask()" type="button" value="<%:Add%>" size="0">
</div>
</div>
<script type="text/javascript">
<% for _,item in pairs(self.list) do -%>
XHR.poll(5, '<%=url([[admin]], [[services]], [[supervisord]], [[gettask]])%>', {name: '<%=item[1]%>'},
function(x, data) {
const st = document.getElementById('<%=item[1]%>-status');
const des = document.getElementById('<%=item[1]%>-description');
if (data) {
st.innerHTML = data.status;
if (data.status == "Exited" || data.status == "Backoff"){
st.style.color="red"
document.getElementById('<%=item[1]%>-start').disabled = false;
document.getElementById('<%=item[1]%>-stop').disabled = true;
}else{
st.style.color="green"
document.getElementById('<%=item[1]%>-start').disabled = true;
document.getElementById('<%=item[1]%>-stop').disabled = false;
}
des.innerHTML = data.description;
}
}
)
<% end %>
function addtask(){
const name = document.getElementById("addtext").value
const isletter = /^[a-zA-Z]+$/.test(name);
if (!isletter) {
alert("<%:Only letters can be used for names!%>")
return
}
if (name.length > 20) {
alert("<%:Cannot exceed 20 characters!%>")
return
}
XHR.get('<%=url([[admin]], [[services]], [[supervisord]], [[addtask]])%>', {name: name},
function(x, data) {
if (data.code == 0) {
alert("<%:Creation failed. Please try again!%>")
return
}else if (data.code == 1){
const currentRows = document.getElementById("task-list").rows.length;
const insertTr = document.getElementById("task-list").insertRow(currentRows);
insertTr.className = 'cbi-section-table-row';
insertTr.id = name + '-main';
insertTr.innerHTML = "<td class='cbi-value-field'>"+name+"</td><td class='cbi-value-field' id='"+name+"-status'></td><td class='cbi-value-field' id='"+name+"-description'></td><td class='cbi-value-field'><textarea class='cbi-input-textarea' id='"+name+"-text' rows='15' wrap='off'>"+data.data+"</textarea></td><td class='cbi-value-field'><input class='cbi-button cbi-input-apply' style='font-size: 100%;background-color: green!important;' type='button' id='"+name+"-start' disabled onclick='actions(&quot;starttask&quot;,&quot;"+name+"&quot;)' value='<%:Start%>' size='0'><input class='cbi-button cbi-input-remove' style='font-size: 100%;background-color: #333333!important;' type='button' id='"+name+"-stop' disabled onclick='actions(&quot;stoptask&quot;,&quot;"+name+"&quot;)' value='<%:Stop%>' size='0'><input class='cbi-button cbi-input-apply' style='font-size: 100%;' type='button' onclick='actions(&quot;restarttask&quot;,&quot;"+name+"&quot;)' value='<%:Reboot%>' size='0'><input class='cbi-button cbi-input-remove' style='font-size: 100%;' type='button' onclick='actions(&quot;savetask&quot;,&quot;"+name+"&quot;)' value='<%:Save%>' size='0'><input class='cbi-button cbi-button-remove' style='font-size: 100%;' type='button' onclick='actions(&quot;removetask&quot;,&quot;"+name+"&quot;)' value='<%:Delete%>' size='0'></td>";
document.getElementById("addtext").value="";
XHR.poll(5, '<%=url([[admin]], [[services]], [[supervisord]], [[gettask]])%>', {name: name},
function(x, data) {
const st = document.getElementById(name + '-status');
const des = document.getElementById(name + '-description');
if (data) {
st.innerHTML = data.status;
if (data.status == "Exited" || data.status == "Backoff"){
st.style.color="red"
document.getElementById(name + '-start').disabled = false;
document.getElementById(name + '-stop').disabled = true;
}else{
st.style.color="green"
document.getElementById(name + '-start').disabled = true;
document.getElementById(name + '-stop').disabled = false;
}
des.innerHTML = data.description;
}
}
)
}else if (data.code == 2){
alert("<%:A task with this name already exists!%>")
return
}
}
)
}
function actions(mode,name){
if (mode=="savetask"){
const x = new XHR()
x.post('<%=url([[admin]], [[services]], [[supervisord]], [[savetask]])%>', {name: name, data: $('#' + name + '-text').val()},
function(x) {
if (JSON.parse(x.response).code) {
alert("<%:Save success!%>")
}else{
alert("<%:Save failed!%>")
}
}
)
}else{
if (mode=="removetask") {
const ret=confirm("<%:Are you sure you want to delete this task?%>")
if (!ret) return
}
XHR.get('<%=url([[admin]], [[services]], [[supervisord]], [[mode]])%>'.replace("mode",mode), {name: name},
function(x, data) {
if (data.code) {
if (mode == "starttask"){
document.getElementById(name + '-start').disabled = true;
document.getElementById(name + '-stop').disabled = false;
}
if (mode == "stoptask"){
document.getElementById(name + '-start').disabled = false;
document.getElementById(name + '-stop').disabled = true;
}
if (mode == "removetask"){
document.getElementById(name + '-main').remove();
}
}
}
)
}
}
</script>
<%+cbi/valuefooter%>

View File

@ -0,0 +1,35 @@
<%local fs = require "nixio.fs"%>
<%+cbi/valueheader%>
<div class="cbi-value">
<label class="cbi-value-title">
<p style="color: red">日记列表</p>
</label>
<div class="cbi-value-field">
<select class="cbi-input-select" size="1">
<option value="main">supervisord</option>
<% for _,item in pairs(self.list) do %>
<option value="<%=item[2]:gsub('/etc/supervisord/program/', ''):gsub('.ini', '')%>">
<%=item[2]:gsub('/etc/supervisord/program/', ''):gsub('.ini', '')%>
</option>
<% end %>
</select>
</div>
</div>
<textarea class="cbi-input-textarea" id="log-text" rows="30" wrap="off" readonly></textarea>
<script type="text/javascript">
getlog('main')
$(".cbi-input-select").change(function (e) {
getlog($(this).val())
});
function getlog(name) {
XHR.get('<%=url([[admin]], [[services]], [[supervisord]], [[getlog]])%>', {name: name},
function (x, data) {
if (data.data) {
document.getElementById("log-text").value = data.data;
}
}
)
}
</script>
<%+cbi/valuefooter%>

View File

@ -0,0 +1,56 @@
<%+cbi/valueheader%>
<label class="cbi-value-title"><%= translate("Update the core") %></label>
<div class="cbi-value-field">
<input class="btn cbi-button cbi-button-reload" id="update" type="button" size="0" onclick="check_version()" value="<%:Collecting data...%>" />
<div class="cbi-value-description">
<span class="cbi-value-helpicon"><img src="/luci-static/resources/cbi/help.gif" alt="帮助"></span>
<%:If repeated failures occur, you can download the binaries for the corresponding schemas at the following url.%>
</br>&nbsp;&nbsp;&nbsp;&nbsp;
<%:https://github.com/ochinchina/supervisord/releases%>
</br>&nbsp;&nbsp;&nbsp;&nbsp;
<%:Unpack the package and place it in the top path.%>
</br>&nbsp;&nbsp;&nbsp;&nbsp;
<%:The author binary version number may not have changed.%>
</br>&nbsp;&nbsp;&nbsp;&nbsp;
<%:If you successfully update, the refresh page is still lower than the latest version.%>
</br>&nbsp;&nbsp;&nbsp;&nbsp;
<%:This is normal.%>
</div>
</div>
<script type="text/javascript">
function getver() {
XHR.get('<%=url([[admin]], [[services]], [[supervisord]], [[getver]])%>', null,
function(x, data) {
const tb = document.getElementById('update');
if (data && tb) {
if (data.newver) {
tb.value = '<%:Local version is %>' + data.nowver + '<%:, New version is %>' + data.newver;
tb.setAttribute('newver', data.newver);
}else{
tb.value = '<%:The check failed. Please try again%>';
}
}
}
);
}
getver()
function check_version() {
const tb = document.getElementById('update');
const newver= tb.getAttribute("newver")
if (newver){
tb.disabled = true;
XHR.get('<%=url([[admin]], [[services]], [[supervisord]], [[update]])%>', {version: newver}, (x, r) => {
if (r.error == 0) {
tb.disabled = false;
tb.value = '<%:Local version is %>' + newver + '<%:, New version is %>' + newver;
} else {
tb.disabled = false;
tb.value = '<%:The update failed. Please try again%>';
}
});
}else{
getver()
}
}
</script>
<%+cbi/valuefooter%>

View File

@ -0,0 +1,80 @@
msgid "Supervisord"
msgstr "进程管理器"
msgid "A golang development process management"
msgstr "一款golang开发的进程管理"
msgid "General Settings"
msgstr "基础设置"
msgid "Configuration File"
msgstr "配置文件"
msgid "Task List"
msgstr "任务列表"
msgid "Log List"
msgstr "日志列表"
msgid "Enabled"
msgstr "启用"
msgid "File Path"
msgstr "文件路径"
msgid "Use China Mirror"
msgstr "使用中国镜像"
msgid "Update the core"
msgstr "更新核心"
msgid "If repeated failures occur, you can download the binaries for the corresponding schemas at the following url."
msgstr "如果重复失败您可以从以下url下载对应模式的二进制文件。"
msgid "Unpack the package and place it in the top path."
msgstr "解压后并将其放置在上方设置的路径中。"
msgid "The author binary version number may not have changed."
msgstr "作者二进制版本号可能没有改变。"
msgid "If you successfully update, the refresh page is still lower than the latest version."
msgstr "如果更新成功,刷新页面仍然低于最新版本。"
msgid "This is normal."
msgstr "这是正常的。"
msgid "Local version is"
msgstr "本地版本是"
msgid ", New version is"
msgstr ",最新版本是"
msgid "The check failed. Please try again"
msgstr "检查失败。请再试一次"
msgid "The update failed. Please try again"
msgstr "更新失败。请再试一次"
msgid "Versions"
msgstr "版本"
msgid "Only letters can be used for names!"
msgstr "只有字母可以用来命名!"
msgid "Cannot exceed 20 characters!"
msgstr "不能超过20个字符"
msgid "Creation failed. Please try again!"
msgstr "创建失败了。请再试一次!"
msgid "A task with this name already exists!"
msgstr "已经存在此名称的任务!"
msgid "Save success!"
msgstr "保存成功!"
msgid "Save failed!"
msgstr "保存失败!"
msgid "Are you sure you want to delete this task?"
msgstr "您确定要删除该任务吗?"

View File

@ -0,0 +1 @@
zh-cn

View File

@ -0,0 +1,6 @@
config supervisord 'main'
option filepath '/usr/bin/supervisord'
option enabled '1'
option amend '0'

View File

@ -0,0 +1,42 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2015 OpenWrt.org
START=90
get_config() {
config_get_bool enabled $1 enabled 0
config_get_bool amend $1 amend 0
config_get filepath $1 filepath /usr/bin/supervisord
}
start() {
config_load supervisord
config_foreach get_config supervisord
[ $enabled -eq 0 ] && exit 0
$filepath -c /etc/supervisord/supervisord.conf -d
}
stop() {
config_load supervisord
config_foreach get_config supervisord
$filepath ctl shutdown
}
reload() {
config_load supervisord
config_foreach get_config supervisord
[ $enabled -eq 0 ] && logger -t supervisord disabled to stop && stop && exit 0
status=$(ps | grep supervisord | grep -v grep | grep -v luci | grep -v init | grep -v version | wc -l)
[ $status -eq 0 ] && logger -t supervisord unstarted to start && start && exit 0
if [ $amend -eq 1 ]; then
logger -t supervisord amend to restart
stop
sleep 1
uci set supervisord.main.amend=0
uci commit supervisord
start
else
logger -t supervisord fixed to reload
$filepath ctl reload
fi
}

View File

@ -0,0 +1,60 @@
;更多参数查看https://github.com/ochinchina/supervisord/
;程序名称,没事别乱改
[program:demo]
;程序启动命令,必须
;command=xxxxx
command=
;执行命令的路径,必须
;directory=/usr/bin
directory=
;需要备份文件的完整路径,多个文件以||分割,必须
;backupfile=/usr/bin/xxxxx||/etc/yyyyy
backupfile=
;获取版本号命令,必须
;getversions=xxxxx version
getversions=
;在supervisord启动的时候也自动启动
autostart=true
;启动10秒后没有异常退出就表示进程正常启动了默认为1秒
startsecs=10
;程序退出后自动重启,可选值:[unexpected,true,false]
;默认为unexpected表示进程意外杀死后才重启
autorestart=true
;启动失败自动重试次数默认是3
startretries=3
;用哪个用户启动进程默认是root
user=root
;进程启动优先级默认999值小的优先启动
priority=999
;把stderr重定向到stdout默认false
redirect_stderr=true
;stdout日志文件大小默认1MB
stdout_logfile_maxbytes=1MB
;stdout日志文件备份数默认是10
stdout_logfile_backups=10
;stdout日志文件需要注意当指定目录不存在时无法正常启动所以需手动创建目录
stdout_logfile=/var/log/demo.log
;日志的级别
loglevel=info
;默认为false,进程被杀死时是否向这个进程组发送stop信号包括子进程
stopasgroup=false
;默认为false向进程组发送kill信号包括子进程
killasgroup=false

View File

@ -0,0 +1,40 @@
;更多参数查看https://github.com/ochinchina/supervisord/
[supervisord]
;主日志文件;默认路径是$CWD/supervisord.log
logfile=/var/log/supervisord.log
;最大主日志文件尺寸;默认3MB
logfile_maxbytes=3MB
;主日志文件备份的数量;默认10
logfile_backups=10
;日志等级;默认info;其他:debug,warn,trace
loglevel=debug
;supervisord的pid文件;默认supervisord.pid
pidfile=/var/run/supervisord.pid
;如果为true从前台开始;默认false
nodaemon=false
;最小效用启动文件描述符;默认1024
minfds=1024
;最小效用过程描述符;默认200
minprocs=200
;启用web界面默认仅本地访问且不设置密码
[inet_http_server]
port=127.0.0.1:9001
;username=admin
;password=admin
;启用命令行操作任务需启用web界面且未设置密码
[supervisorctl]
serverurl=http://127.0.0.1:9001
;加载任务配置文件
[include]
files = /etc/supervisord/program/*.ini

View File

@ -0,0 +1,11 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@supervisord[-1]
add ucitrack supervisord
set ucitrack.@supervisord[-1].init=supervisord
commit ucitrack
EOF
rm -f /tmp/luci-indexcache
exit 0

View File

@ -0,0 +1,11 @@
{
"luci-app-supervisord": {
"description": "Grant UCI access for luci-app-supervisord",
"read": {
"uci": [ "supervisord" ]
},
"write": {
"uci": [ "supervisord" ]
}
}
}

15
luci-app-wolplus/Makefile Normal file
View File

@ -0,0 +1,15 @@
# Copyright (C) 2016 Openwrt.org
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI support for wolplus From sundaqiang
LUCI_DEPENDS:=+etherwake
LUCI_PKGARCH:=all
PKG_MAINTAINER:=sundaqiang
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,33 @@
module("luci.controller.wolplus", package.seeall)
local t, a
local x = luci.model.uci.cursor()
function index()
if not nixio.fs.access("/etc/config/wolplus") then return end
entry({"admin", "services", "wolplus"}, cbi("wolplus"), _("wolplus"), 95).dependent = true
entry( {"admin", "services", "wolplus", "awake"}, post("awake") ).leaf = true
end
function awake(sections)
lan = x:get("wolplus",sections,"maceth")
mac = x:get("wolplus",sections,"macaddr")
local e = {}
cmd = "/usr/bin/etherwake -D -i " .. lan .. " -b " .. mac .. " 2>&1"
local p = io.popen(cmd)
local msg = ""
if p then
while true do
local l = p:read("*l")
if l then
if #l > 100 then l = l:sub(1, 100) .. "..." end
msg = msg .. l
else
break
end
end
p:close()
end
e["data"] = msg
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end

View File

@ -0,0 +1,35 @@
local i = require "luci.sys"
local t, e
t = Map("wolplus", translate("wolplus"), translate("Wake up your LAN device") .. [[<br /><br /><a href="https://github.com/sundaqiang/openwrt-packages" target="_blank">Powered by sundaqiang</a>]])
t.template = "wolplus/index"
e = t:section(TypedSection, "macclient", translate("macclient"))
e.template = "cbi/tblsection"
e.anonymous = true
e.addremove = true
a = e:option(Value, "name", translate("name"))
a.optional = false
nolimit_mac = e:option(Value, "macaddr", translate("macaddr"))
nolimit_mac.rmempty = false
i.net.mac_hints(function(e, t) nolimit_mac:value(e, "%s (%s)" % {e, t}) end)
nolimit_eth = e:option(Value, "maceth", translate("maceth"))
nolimit_eth.rmempty = false
for t, e in ipairs(i.net.devices()) do if e ~= "lo" then nolimit_eth:value(e) end end
btn = e:option(Button, "_awake",translate("awake"))
btn.inputtitle = translate("awake")
btn.inputstyle = "apply"
btn.disabled = false
btn.template = "wolplus/awake"
function gen_uuid(format)
local uuid = i.exec("echo -n $(cat /proc/sys/kernel/random/uuid)")
if format == nil then
uuid = string.gsub(uuid, "-", "")
end
return uuid
end
function e.create(e, t)
local uuid = gen_uuid()
t = uuid
TypedSection.create(e, t)
end
return t

View File

@ -0,0 +1,3 @@
<%+cbi/valueheader%>
<input class="cbi-button cbi-input-<%=self.inputstyle or "button" %>" style="font-size: 100%;" type="button" onclick="onclick_awake(this.id)" <%=attr("name", section) .. attr("id", cbid) .. attr("value", self.inputtitle)%> />
<%+cbi/valuefooter%>

View File

@ -0,0 +1,22 @@
<% include("cbi/map") %>
<script type="text/javascript">
function _id2section(id) {
var x = id.split(".");
return x[2];
}
function onclick_awake(id) {
var section = _id2section(id);
var btnXHR = new XHR();
btnXHR.post('<%=url([[admin]], [[services]], [[wolplus]], [[awake]])%>/' + section, { token: '<%=token%>' },
function(x, data) {
if (x.responseText == "_uncommitted_") {
txt="<%:Please [Save & Apply] your changes first%>";
alert( txt.replace(new RegExp("<%:&%>", "g"), "&") );
} else {
alert( JSON.parse(x.response).data );
}
}
);
}
</script>

View File

@ -0,0 +1,23 @@
msgid "wolplus"
msgstr "网络唤醒++"
msgid "Wake up your LAN device"
msgstr "唤醒你的局域网设备"
msgid "macclient"
msgstr "设备列表"
msgid "name"
msgstr "名称"
msgid "macaddr"
msgstr "客户端MAC"
msgid "maceth"
msgstr "网络接口"
msgid "awake"
msgstr "唤醒"
msgid "Please [Save & Apply] your changes first"
msgstr "请先保存并应用您的设置"

1
luci-app-wolplus/po/zh_Hans Symbolic link
View File

@ -0,0 +1 @@
zh-cn

View File

View File

@ -0,0 +1,11 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@wolplus[-1]
add ucitrack wolplus
set ucitrack.@wolplus[-1].init=wolplus
commit ucitrack
EOF
rm -f /tmp/luci-indexcache
exit 0

View File

@ -0,0 +1,11 @@
{
"luci-app-wolplus": {
"description": "Grant UCI access for luci-app-wolplus",
"read": {
"uci": [ "wolplus" ]
},
"write": {
"uci": [ "wolplus" ]
}
}
}