diff --git a/gecoosac/Makefile b/gecoosac/Makefile new file mode 100644 index 000000000..61c99a401 --- /dev/null +++ b/gecoosac/Makefile @@ -0,0 +1,55 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gecoosac +PKG_VERSION:=2.2.20251015 +PKG_RELEASE:=1 + +ifeq ($(ARCH),aarch64) + PKG_ARCH:=ac_linux_arm64 + PKG_HASH:=skip +else ifeq ($(ARCH),arm) + PKG_ARCH:=ac_linux_arm + PKG_HASH:=skip +else ifeq ($(ARCH),mips) + PKG_ARCH:=ac_linux_mips + PKG_HASH:=skip +else ifeq ($(ARCH),mipsel) + PKG_ARCH:=ac_linux_mipsle + PKG_HASH:=skip +else ifeq ($(ARCH),i386) + PKG_ARCH:=ac_linux_386 + PKG_HASH:=skip +else ifeq ($(ARCH),x86_64) + PKG_ARCH:=ac_linux_amd64 + PKG_HASH:=skip +else + PKG_HASH:=skip +endif + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(ARCH_PACKAGES) +PKG_SOURCE_URL:=https://github.com/laipeng668/luci-app-gecoosac/releases/download/V$(PKG_VERSION)/$(PKG_ARCH)? +UNPACK_CMD=$(CP) $(DL_DIR)/$(PKG_SOURCE) $(PKG_BUILD_DIR)/$(PKG_NAME) + +PKG_LICENSE:=AGPL-3.0-only +PKG_LICENSE_FILES:=LICENSE +PKG_MAINTAINER:=lwb1978 + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME) + SECTION:=net + CATEGORY:=Network + TITLE:=gecoosac server (version $(PKG_VERSION)) + URL:=http://www.cnrouter.com/ + DEPENDS:=@(aarch64||arm||i386||mips||mipsel||x86_64) +endef + +define Build/Compile +endef + +define Package/$(PKG_NAME)/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(PKG_NAME) $(1)/usr/bin +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/luci-app-gecoosac/Makefile b/luci-app-gecoosac/Makefile new file mode 100644 index 000000000..fb77581ee --- /dev/null +++ b/luci-app-gecoosac/Makefile @@ -0,0 +1,22 @@ +# Copyright (C) 2024 Openwrt.org +# +# This is free software, licensed under the Apache License, Version 2.0 . +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=luci-app-gecoosac +PKG_VERSION:=2.2 +PKG_RELEASE:=1 + +LUCI_TITLE:=LuCI Support for gecoosac +LUCI_DEPENDS:=+luci-compat +gecoosac +LUCI_PKGARCH:=all + +define Package/$(PKG_NAME)/conffiles +/etc/gecoosac +endef + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-gecoosac/luasrc/controller/gecoosac.lua b/luci-app-gecoosac/luasrc/controller/gecoosac.lua new file mode 100644 index 000000000..6ba9c20db --- /dev/null +++ b/luci-app-gecoosac/luasrc/controller/gecoosac.lua @@ -0,0 +1,29 @@ + +module("luci.controller.gecoosac", package.seeall) + +function index() + if not nixio.fs.access("/etc/config/gecoosac") then + return + end + local page + page = entry({"admin", "services", "gecoosac"}, cbi("gecoosac"), _("Gecoos AC"), 100) + page.dependent = true + page = entry({"admin", "services", "gecoosac", "status"}, call("act_status")) + page.leaf = true +end + +function act_status() + local e = {} + local binpath = "/usr/bin/gecoosac" + e = { + running = luci.sys.call("pgrep " .. binpath .. " >/dev/null") == 0 + } + luci.http.prepare_content("application/json") + luci.http.write_json(e) +end + +function clear_upload() + local path = "/tmp/gecoosac/upload/" + luci.sys.call("rm -rf " .. path .. "/*") + luci.http.status(200, "OK") +end diff --git a/luci-app-gecoosac/luasrc/model/cbi/gecoosac.lua b/luci-app-gecoosac/luasrc/model/cbi/gecoosac.lua new file mode 100644 index 000000000..2e4c649d1 --- /dev/null +++ b/luci-app-gecoosac/luasrc/model/cbi/gecoosac.lua @@ -0,0 +1,74 @@ +function program_exists(program) + local handle = io.popen('which ' .. program) + local result = handle:read('*a') + handle:close() + return result ~= '' +end + +if program_exists("/usr/bin/gecoosac") then + m = Map("gecoosac", translate("Gecoos AC"), translate("Batch management Gecoos AP, Default password: admin") .. "
" .. translatef("The current AC version %s, only supports AP 7.6 and above.","2.2")) +else + m = Map("gecoosac", translate("Gecoos AC"), translate("Batch management Gecoos AP, Default password: admin") .. "
" .. translate("The AC program does not exist, please check.")) +end + +m:section(SimpleSection).template = "gecoosac/gecoosac_status" + +s = m:section(TypedSection, "gecoosac", translate("Global Settings")) +s.addremove = false +s.anonymous = true + +enable = s:option(Flag, "enabled", translate("Enabled AC")) +enable.rmempty = false + +o = s:option(Value, "port", translate("Set interface port")) +o.placeholder = 60650 +o.default = 60650 +o.datatype = "port" +o.rmempty = false + +o = s:option(Flag, "isonlyoneprot", translate("Single Port Mode"), translate("Do not enable the independent management port, only use one port for management.")) +o.default = 1 +o.rmempty = false + +o = s:option(Value, "m_port", translate("Set management port")) +o.placeholder = 8080 +o.default = 8080 +o.datatype = "port" +o:depends("isonlyoneprot", false) + +o = s:option(Flag, "https", translate("Enable HTTPS service"), translate("A certificate file must be specified, otherwise it will fail to start.")) +o.default = 0 +o:depends("isonlyoneprot", false) + +o = s:option(Value, "crt_file", translate("Specify crt certificate file")) +o.placeholder = "/etc/gecoosac/tls/1.crt" +o.default = "/etc/gecoosac/tls/1.crt" +o:depends("https", true) + +o = s:option(Value, "key_file", translate("Specify key certificate file")) +o.placeholder = "/etc/gecoosac/tls/1.key" +o.default = "/etc/gecoosac/tls/1.key" +o:depends("https", true) + +upload_dir = s:option(Value, "upload_dir", translate("Upload dir path"), translate("The path to upload AP upgrade firmware")) +upload_dir.placeholder = "/tmp/gecoosac/upload/" +upload_dir.default = "/tmp/gecoosac/upload/" +upload_dir.rmempty = false + +db_dir = s:option(Value, "db_dir", translate("Database dir path"), translate("The path to store the config database")) +db_dir.placeholder = "/etc/gecoosac/" +db_dir.default = "/etc/gecoosac/" +db_dir.rmempty = false + +log = s:option(Flag, "log", translate("Enable Log")) +log.default = 1 +log.rmempty = false + +clear_upload = s:option(Button, "clear_upload", translate("Clear Upload Directory")) +clear_upload.inputstyle = "remove" +clear_upload.write = function(self, section) + local path = upload_dir:formvalue(section) or "/tmp/gecoosac/upload/" + luci.sys.call("rm -rf " .. path .. "/*") +end + +return m diff --git a/luci-app-gecoosac/luasrc/view/gecoosac/gecoosac_status.htm b/luci-app-gecoosac/luasrc/view/gecoosac/gecoosac_status.htm new file mode 100644 index 000000000..2be732030 --- /dev/null +++ b/luci-app-gecoosac/luasrc/view/gecoosac/gecoosac_status.htm @@ -0,0 +1,44 @@ +<% +local uci=require"luci.model.uci".cursor() + +local isonlyoneprot = uci:get("gecoosac", "config", "isonlyoneprot") or "1" +local https = uci:get("gecoosac", "config", "https") or "0" +local port = uci:get("gecoosac", "config", "port") or "60650" +local m_port = uci:get("gecoosac", "config", "m_port") or "8080" +local http = "http://" +if isonlyoneprot == "0" then + port = m_port + if https == "1" then + http = "https://" + end +end +-%> + + +
+

+ <%:Collecting data...%> +

+
diff --git a/luci-app-gecoosac/po/zh-cn/gecoosac.po b/luci-app-gecoosac/po/zh-cn/gecoosac.po new file mode 100644 index 000000000..b7ca7f7d3 --- /dev/null +++ b/luci-app-gecoosac/po/zh-cn/gecoosac.po @@ -0,0 +1,74 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +msgid "Gecoos AC" +msgstr "集客AC控制器" + +msgid "Batch management Gecoos AP, Default password: admin" +msgstr "批量集中管理集客 AP,默认密码:admin" + +msgid "The current AC version %s, only supports AP 7.6 and above." +msgstr "当前 AC 版本 %s ,仅支持 AP 7.6 及以上版本。" + +msgid "The AC program does not exist, please check." +msgstr "AC 程序不存在,请检查。" + +msgid "Global Settings" +msgstr "全局设置" + +msgid "Enabled AC" +msgstr "启用集客AC" + +msgid "Set interface port" +msgstr "设置接口端口" + +msgid "Single Port Mode" +msgstr "单端口模式" + +msgid "Do not enable the independent management port, only use one port for management." +msgstr "不开启独立管理端口,只使用一个端口进行管理。" + +msgid "Set management port" +msgstr "设置管理端口" + +msgid "Enable HTTPS service" +msgstr "开启 HTTPS 服务" + +msgid "A certificate file must be specified, otherwise it will fail to start." +msgstr "需要指定证书文件,否则开启失败。" + +msgid "Specify crt certificate file" +msgstr "指定 crt 证书文件" + +msgid "Specify key certificate file" +msgstr "指定 key 证书文件" + +msgid "Upload dir path" +msgstr "上传目录" + +msgid "The path to upload AP upgrade firmware" +msgstr "存放AP升级固件的路径" + +msgid "Database dir path" +msgstr "数据库目录" + +msgid "The path to store the config database" +msgstr "存放配置数据库的路径" + +msgid "Enable Log" +msgstr "启用日志" + +msgid "The GecoosAC service is running." +msgstr "集客AC控制器 运行中" + +msgid "The GecoosAC service is not running." +msgstr "集客AC控制器 未运行" + +msgid "Open the mgmt page" +msgstr "打开管理页面" + +msgid "Collecting data..." +msgstr "收集数据..." + +msgid "Clear Upload Directory" +msgstr "清理上传目录" diff --git a/luci-app-gecoosac/po/zh_Hans b/luci-app-gecoosac/po/zh_Hans new file mode 120000 index 000000000..41451e4a1 --- /dev/null +++ b/luci-app-gecoosac/po/zh_Hans @@ -0,0 +1 @@ +zh-cn \ No newline at end of file diff --git a/luci-app-gecoosac/root/etc/config/gecoosac b/luci-app-gecoosac/root/etc/config/gecoosac new file mode 100644 index 000000000..78bd64546 --- /dev/null +++ b/luci-app-gecoosac/root/etc/config/gecoosac @@ -0,0 +1,8 @@ +config gecoosac 'config' + option enabled '0' + option port '60650' + option isonlyoneprot '1' + option upload_dir '/tmp/gecoosac/upload/' + option db_dir '/etc/gecoosac/' + option log '0' + diff --git a/luci-app-gecoosac/root/etc/gecoosac/tls/1.crt b/luci-app-gecoosac/root/etc/gecoosac/tls/1.crt new file mode 100644 index 000000000..982089666 --- /dev/null +++ b/luci-app-gecoosac/root/etc/gecoosac/tls/1.crt @@ -0,0 +1,45 @@ +-----BEGIN CERTIFICATE----- +MIIDljCCAn6gAwIBAgIIeEgcfPZbDC0wDQYJKoZIhvcNAQELBQAwejELMAkGA1UE +BhMCQ04xFzAVBgNVBAoTDktleU1hbmFnZXIub3JnMTEwLwYDVQQLEyhLZXlNYW5h +Z2VyIFRlc3QgUm9vdCAtIEZvciBUZXN0IFVzZSBPbmx5MR8wHQYDVQQDExZLZXlN +YW5hZ2VyIFRlc3QgUlNBIENBMCAXDTI0MTIxMTA0MDUyNloYDzIxMjQxMjExMDQw +NTI2WjAZMQswCQYDVQQGEwJDTjEKMAgGA1UEAwwBKjCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBALM3K/5+yX6H9Dvq8TrKuk0KtFBqmDDP3lKXMpMkWjDn +4OtKGq4QtaPPJfGBjitYecyHLWbqGZlWU2H8ug/kL/PtAFgtTgiFvObePbP4VUVO +lICitAWCSMo7xsvt/XSGLOF3dV1tCoEcjK9GtJEMOyoqHMOgbuZ986wIR4LkgULz +3A2uC5abXP5Exa6phMCv3MojjaVgOFEIuC4371ZeLU/YXja9ssQ0Bs8PzOIjCP7i +pce94hYYSgAH3Ua1ZcWVZVEbCytoaOGWXkrhNTVZ+nAarlFY4fgN3yCi+YgFipKU +1H9oNr4PgLsxhtM3f19wwu9XNY1RF72cfRPS/mPy86sCAwEAAaN/MH0wDgYDVR0P +AQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4E +FgQUOW6TXeYQEZs1tMI05Vx2aSb9dk0wHwYDVR0jBBgwFoAUfzXMx0QcDHIhuynW +4rB+75TRqw8wDAYDVR0RBAUwA4IBKjANBgkqhkiG9w0BAQsFAAOCAQEAl63ixtfN +azLCIvIKGhjhqk2aU9NZtnsjYO729bNSk8SGtqVvCyXO8FJwdhoybtBlSkxjyvrb +nsR+QbeYGu0ZPsSsJJKuwlsM+ZoTOEGRQrhT7AkkXsNQHSalDCWczPW45xWHkg/s +P9xIGeySWMu4CJ1/eZYczT6bzS0eLd05camVCeU2E5N/M7hAO4SnK0agFZnaUEjp +13KZA3MfFNXZ2Q7na9CRjTbpqDCOpsLteP22fwUq7zutwvkQsQQYnQuVlpiUjSsV +MvY7oxkTi9M5BtowdEtVpWkVO2WOMs5dy2kxfgcIJ5KRZLmU+cPsWgsE76fErIYs +FU2leWlNpSvuMw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2jCCAsKgAwIBAgIILz9r/y+4/ZgwDQYJKoZIhvcNAQELBQAwezELMAkGA1UE +BhMCQ04xFzAVBgNVBAoTDktleU1hbmFnZXIub3JnMTEwLwYDVQQLEyhLZXlNYW5h +Z2VyIFRlc3QgUm9vdCAtIEZvciBUZXN0IFVzZSBPbmx5MSAwHgYDVQQDExdLZXlN +YW5hZ2VyIFRlc3QgUm9vdCBDQTAeFw0yNDEyMTEwMzI3MzJaFw0zNDEyMTEwMzI3 +MzJaMHoxCzAJBgNVBAYTAkNOMRcwFQYDVQQKEw5LZXlNYW5hZ2VyLm9yZzExMC8G +A1UECxMoS2V5TWFuYWdlciBUZXN0IFJvb3QgLSBGb3IgVGVzdCBVc2UgT25seTEf +MB0GA1UEAxMWS2V5TWFuYWdlciBUZXN0IFJTQSBDQTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAMa7Tdag8tcvEwqRMD+gVEd4G3XeQyYzSYGLAa9DGji4 +qUDUcBi0Ml2AndHtNNPcAk4vBUsZ10jjpNtOWtsy+r8VivBIlM5PE38JLhlZWao9 +JvT1duxfxss+Q7xdT1oO++CDN/6avPXmDD1dmbTD09/cxcPW8M/3aaHfbI5GWxlr +ZLu8N50yQQxiXLEJad3n7fPjAosGroqa5FcsJ2vDQHuK13mpZG1eBoNZe6/OAzAz +yYkUKyixpS4xc8Agb9BCl7M9Tvkr8VkELGoFPWBMwBsa4BD0OYE7Vc+ZFEqhyzva +mOpicU1xl8mMkNIhiIaSU52fzRgYryZKmxPfYo8JaRUCAwEAAaNjMGEwDgYDVR0P +AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH81zMdEHAxyIbsp +1uKwfu+U0asPMB8GA1UdIwQYMBaAFElv+F66JtNinfmGM1cttCjILv/hMA0GCSqG +SIb3DQEBCwUAA4IBAQDOrqBCHRfVrTC/mfIIXcFn3lB+3kGmAmBVxH5UILljPdl9 +ADjW9iiJtaEYxCOjrnFzpcOvuQnWPC7dbb+cy+DntLy/g6x95kBlAPdp02nYoS42 +mDHmYUx+rIvnAceSTr72R+Vu9LNVzdbvnULT1o/4kW6uwRnrskisoFkAzeMd/4DT +tY71Dkz9faJt4VIE0wF3/jYXbqVhffyu6xXl+mS9mmCw/u9pFXMys2i/5tF90qIx +hpcVLhqFq4+dTnXaohC2DRpd+sCH4wRHMIRpi7gWI+6nXwLg95VSSwRNd+C+tyyh +GXlSB7/9WOGRGv74M5W9im3VFn5Ot3zMruEtl/WA +-----END CERTIFICATE----- diff --git a/luci-app-gecoosac/root/etc/gecoosac/tls/1.key b/luci-app-gecoosac/root/etc/gecoosac/tls/1.key new file mode 100644 index 000000000..4f71cca8d --- /dev/null +++ b/luci-app-gecoosac/root/etc/gecoosac/tls/1.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAszcr/n7Jfof0O+rxOsq6TQq0UGqYMM/eUpcykyRaMOfg60oa +rhC1o88l8YGOK1h5zIctZuoZmVZTYfy6D+Qv8+0AWC1OCIW85t49s/hVRU6UgKK0 +BYJIyjvGy+39dIYs4Xd1XW0KgRyMr0a0kQw7Kiocw6Bu5n3zrAhHguSBQvPcDa4L +lptc/kTFrqmEwK/cyiONpWA4UQi4LjfvVl4tT9heNr2yxDQGzw/M4iMI/uKlx73i +FhhKAAfdRrVlxZVlURsLK2ho4ZZeSuE1NVn6cBquUVjh+A3fIKL5iAWKkpTUf2g2 +vg+AuzGG0zd/X3DC71c1jVEXvZx9E9L+Y/LzqwIDAQABAoIBAELDuAkMdMZFodA8 +m3e6lKMk7L3UqDPvDLUaDMZSUaNMjzc4mS3lnbWT81/AUxWE1YNDjL99UOIWDeRA +QZSv/slRrsIqxppYMGKVwsjsJ+A1AQ/XDVfMDJACqvHIDJc/cTLhzQBsIfCtkR+v +KI+szdHMdIDQoOAPZhrdzr5NoHYvQM7B8HYe5G9dyw5GinRnTNqNUIhFM1HW5Gki +dhLAiqUGj2drSsbRoIWIOIzBbM3+hWZK1mO3q+QhdBEPcwzrOgMaj2722Dea57Hb +duCpdpKH43JfSmQ+f0V8OS/zYNUcyQikQg+Euak6dOuMhFN1ma7bNEug3slJMQ0M +JVG55IECgYEAxNgUXU+ORxCVZjMLxq2Uk2qJxbZspRIQ0ElsvsUpVpw0q0KV7V8K +qnxL4c6khOqWZQ9M7PWG4nJgjNXhYW9PpYdTXkmOZzAq+XU8nUYGHR0ZAlDj0oAd +lC9m9hBZPovxRozjMcRpnJinkZRLB0KEuTBECB6ZKZscLqbMIH81kWsCgYEA6RLd +b1Kk6xUjmUcGnq6bZN4a0spEGLayzgFOA2o/Ma1d94c3NsWsz97KGpCISExBOoPd +e/vryCrgvY50U4989z3mOVlcW9IJxaX5jyLmyG1POMkzwpWSST5u1DqnHpZ1xhzo +qjdd+F9E05PG8YM/2JYUDoCgL+BWvSYUsW/bdsECgYA2LZr9S8ZHPQNBy87z8haw +tGQTLPCeRmimS29I2o9ULU45zOvjF4OiBPAFyJBznPWj/yAXIETt0rlMShnsbWyo +jKSfkPNG53UMj/4M85b/MGEPyB/MckKx5JIcK8fEdVQFLQXjTsIavdFxOjWkW+SX +6/btnS5eyzhohrQsRZcC3QKBgEuzauSLbTFFjmhsX0QO5j3evcuVEoUMYgry9Ym6 +aogSDSEmc9KAZd6mN/Jk2z7QNadxyPBKJIzBEHnA2RuC0U3kdvBNi+fu0mm1vNa2 +uUqD5mVFRGCBACB1/L1Fx53xtJMCNLeEgCr5lns51jX/MS+Bn0YOlPi33rRUuAfh +kuCBAoGAPvxUmDXFnYyt8/3t5dpKt1GEpqDdQfhUDqE6zOPulsv0IkMKCvbyHdKI +iR1EbSvCMP9aVO7BeVRnr9FSrdL10TWNLP4JveSI4Ee1bzy0vvTj5l8CC4MwSdhN +04I8F7UqPhSbdVjsTxw16XrHSkvB5JRZsIAz/K0jVMwZs7fS8Lk= +-----END RSA PRIVATE KEY----- diff --git a/luci-app-gecoosac/root/etc/init.d/gecoosac b/luci-app-gecoosac/root/etc/init.d/gecoosac new file mode 100755 index 000000000..c0ff7d24b --- /dev/null +++ b/luci-app-gecoosac/root/etc/init.d/gecoosac @@ -0,0 +1,70 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2024 ImmortalWrt + +. /lib/functions.sh +. /lib/functions/procd.sh + +USE_PROCD=1 + +START=90 +STOP=10 + +init_conf() { + config_load "gecoosac" + config_get "db_dir" "config" "db_dir" "/etc/gecoosac/" + config_get "upload_dir" "config" "upload_dir" "/tmp/gecoosac/upload/" + config_get "enabled" "config" "enabled" "0" + config_get "port" "config" "port" "60650" + config_get "isonlyoneprot" "config" "isonlyoneprot" "1" + config_get "m_port" "config" "m_port" "8080" + config_get "https" "config" "https" "0" + config_get "crt_file" "config" "crt_file" "/etc/gecoosac/tls/1.crt" + config_get "key_file" "config" "key_file" "/etc/gecoosac/tls/1.key" + config_get "log" "config" "log" "0" +} + +start_service() { + init_conf + [ "${enabled}" = "1" ] || return 0 + procd_open_instance gecoosac + procd_set_param command "/usr/bin/gecoosac" + procd_append_param command -f "${upload_dir}" + procd_append_param command -p "${port}" + procd_append_param command -debug "0" + procd_append_param command -dbpath "${db_dir}" + procd_append_param command -token "1" + if [ "${isonlyoneprot}" = "0" ]; then + procd_append_param command -isonlyoneprot "0" + procd_append_param command -mp "${m_port}" + if [ "${https}" = "1" ]; then + procd_append_param command -https "1" + procd_append_param command -crt "${crt_file}" + procd_append_param command -key "${key_file}" + else + procd_append_param command -https "0" + fi + else + procd_append_param command -isonlyoneprot "1" + fi + procd_append_param command -showtip "0" + procd_set_param env GIN_MODE=release + procd_set_param pidfile /var/run/gecoosac.pid + procd_set_param stdout $log + procd_set_param stderr $log + procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5} + procd_close_instance +} + +stop_service(){ + init_conf +} + +reload_service() +{ + stop + start +} + +service_triggers() { + procd_add_reload_trigger "gecoosac" +} diff --git a/luci-app-gecoosac/root/etc/uci-defaults/luci-gecoosac b/luci-app-gecoosac/root/etc/uci-defaults/luci-gecoosac new file mode 100644 index 000000000..87ec53a6d --- /dev/null +++ b/luci-app-gecoosac/root/etc/uci-defaults/luci-gecoosac @@ -0,0 +1,19 @@ +#!/bin/sh +[ ! -f "/usr/share/ucitrack/luci-app-gecoosac.json" ] && { + cat > /usr/share/ucitrack/luci-app-gecoosac.json << EEOF +{ + "config": "gecoosac", + "init": "gecoosac" +} +EEOF +} + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@gecoosac[-1] + add ucitrack gecoosac + set ucitrack.@gecoosac[-1].init=gecoosac + commit ucitrack +EOF + +rm -rf /tmp/luci-* +exit 0 diff --git a/luci-app-gecoosac/root/usr/share/rpcd/acl.d/luci-app-gecoosac.json b/luci-app-gecoosac/root/usr/share/rpcd/acl.d/luci-app-gecoosac.json new file mode 100644 index 000000000..f75f5a887 --- /dev/null +++ b/luci-app-gecoosac/root/usr/share/rpcd/acl.d/luci-app-gecoosac.json @@ -0,0 +1,11 @@ +{ + "luci-app-gecoosac": { + "description": "Grant UCI access for luci-app-gecoosac", + "read": { + "uci": [ "gecoosac" ] + }, + "write": { + "uci": [ "gecoosac" ] + } + } +} diff --git a/luci-app-modeminfo/Makefile b/luci-app-modeminfo/Makefile index 76ca339c6..5adba11fb 100644 --- a/luci-app-modeminfo/Makefile +++ b/luci-app-modeminfo/Makefile @@ -4,7 +4,7 @@ LUCI_TITLE:=Information dashboard for 3G/LTE dongle LUCI_DEPENDS:=+modeminfo PKG_LICENSE:=GPLv3 PKG_VERSION:=0.4.7 -PKG_RELEASE:=7 +PKG_RELEASE:=8 include $(TOPDIR)/feeds/luci/luci.mk diff --git a/luci-app-modeminfo/htdocs/luci-static/resources/view/modem/main.js b/luci-app-modeminfo/htdocs/luci-static/resources/view/modem/main.js index a49eea53e..da974c075 100644 --- a/luci-app-modeminfo/htdocs/luci-static/resources/view/modem/main.js +++ b/luci-app-modeminfo/htdocs/luci-static/resources/view/modem/main.js @@ -15,6 +15,7 @@ Licensed to the GNU General Public License v3.0. Refactored: bug fixes, performance improvements, code deduplication. + Modified: 5G NR support with combined band display */ const REGISTERED_STATUSES = [1, 6, 9]; @@ -39,37 +40,30 @@ const REG_STATUSES = new Map([ ]); // Progress bar configuration -// calc(vn, mn): vn = clamped signal value, mn = min boundary -// All formulas normalise the value to 0–100% range for the progress bar. const PROGRESS_CONFIG = { rssi: { selector: '#rssi', min: -110, max: -50, - // Linear map from [-110..-50] → [0..100] calc: (vn, mn) => Math.floor(100 * (1 - (-50 - vn) / (-50 - mn))), }, rsrp: { selector: '#rsrp', min: -140, max: -50, - // Slightly expanded scale (×1.2) to better use bar width calc: (vn, mn) => Math.floor(120 * (1 - (-50 - vn) / (-70 - mn))), }, sinr: { selector: '#sinr', min: -20, max: 30, - // Linear map from [-20..30] → [0..100] calc: (vn, mn) => Math.floor(100 - (100 * (1 - ((mn - vn) / (mn - 30))))), }, rsrq: { selector: '#rsrq', min: -20, max: 0, - // Proportional map from [-20..0] → [0..100] calc: (vn, mn) => Math.floor(115 - (100 / mn) * vn), }, ecio: { selector: '#sinr', min: -24, max: 0, - // Same shape as rsrq but for EC/IO range [-24..0] calc: (vn, mn) => Math.floor(100 - (100 / mn) * vn), }, }; @@ -91,6 +85,20 @@ const LTE_BANDS = [ { min: 39650, max: 41589, frdl: 2496, frul: 2496, offset: 39650, band: '41' }, ]; +// 5G NR bands for FR1 (3GPP TS 38.104) +const NR_BANDS = [ + { min: 422000, max: 434000, name: '1', dlLow: 2110, offset: 422000 }, + { min: 361000, max: 376000, name: '3', dlLow: 1805, offset: 361000 }, + { min: 173800, max: 178800, name: '5', dlLow: 869, offset: 173800 }, + { min: 524000, max: 538000, name: '7', dlLow: 2620, offset: 524000 }, + { min: 185000, max: 192000, name: '8', dlLow: 925, offset: 185000 }, + { min: 158200, max: 164200, name: '20', dlLow: 791, offset: 158200 }, + { min: 499200, max: 538000, name: '41', dlLow: 2496, offset: 499200, tdd: true }, + { min: 653333, max: 680000, name: '77', dlLow: 3300, offset: 620000, tdd: true }, + { min: 620000, max: 653332, name: '78', dlLow: 3300, offset: 620000, tdd: true }, + { min: 693334, max: 733333, name: '79', dlLow: 4400, offset: 693334, tdd: true }, +]; + // Non-LTE (UMTS/GSM) ARFCN band/frequency table const NON_LTE_BANDS = [ { @@ -117,34 +125,16 @@ const NON_LTE_BANDS = [ const UMTS_MODES = /(HS|3G|UMTS|WCDMA)/i; -// Helpers - -/** - * Safe getElementById wrapper. - * @param {string} id - * @returns {HTMLElement|null} - */ +// Helper functions function getEl(id) { return document.getElementById(id); } -/** - * Show or hide the grandparent row of a signal element. - * @param {HTMLElement} el - * @param {boolean} show - */ function setRowVisible(el, show) { const row = el && el.parentElement && el.parentElement.parentElement; if (row) row.style.display = show ? '' : 'none'; } -/** - * Update a cbi-progressbar element. - * @param {string} type - Key in PROGRESS_CONFIG - * @param {string} value - Raw signal value string (e.g. "-85 dBm") - * @param {number} max - Boundary value (passed as second calc argument) - * @param {number} idx - Modem index suffix for the element id - */ function updateProgressBar(type, value, max, idx) { const config = PROGRESS_CONFIG[type]; if (!config) return; @@ -156,28 +146,16 @@ function updateProgressBar(type, value, max, idx) { const mn = parseInt(max) || 100; const pc = Math.min(100, Math.max(0, config.calc(vn, mn))); - pg.firstElementChild.style.width = `${pc}%`; + pg.firstElementChild.style.width = `${pc}%`; pg.firstElementChild.style.animationDirection = 'reverse'; pg.setAttribute('title', String(value)); } -/** - * Format distance string, returns empty string when unavailable. - * @param {string|number} dist - * @returns {string} - */ function formatDistance(dist) { if (!dist || dist === '--' || dist === '' || dist === '0.00') return ''; return ' ~' + dist + ' km'; } -/** - * Build the operator status badge HTML safely using LuCI E() helper. - * @param {Object} modem - Single modem entry from JSON - * @param {string} icon - URL to signal icon - * @param {string} reg - Human-readable registration status - * @returns {string} - Safe innerHTML string via dom.content - */ function formatModemStatus(modem, icon, reg) { const rg = parseInt(modem.reg) || 0; const p = modem.csq_per || 0; @@ -201,44 +179,31 @@ function formatModemStatus(modem, icon, reg) { } } -/** - * Derive signal icon URL from signal percentage. - * @param {number} pct - * @returns {string} - */ function resolveSignalIcon(pct) { const { icn } = SIGNAL_ICONS.find(({ max }) => pct <= max) || SIGNAL_ICONS[SIGNAL_ICONS.length - 1]; return L.resource(`view/modem/icons/${icn}`); } -/** - * Calculate DL/UL frequencies and band name for LTE mode. - * @param {number} rfcn - * @returns {{ dlfreq: number, ulfreq: number, band: string, frdl: number, frul: number, offset: number }} - */ function calcLteBand(rfcn) { const b = LTE_BANDS.find(b => rfcn >= b.min && rfcn <= b.max); - if (!b) return { frdl: 0, frul: 0, offset: 0, band: String(rfcn), dlfreq: 0, ulfreq: 0 }; + if (!b) return { band: String(rfcn), dlfreq: 0, ulfreq: 0 }; const dlfreq = b.frdl + (rfcn - b.offset) / 10; const ulfreq = b.frul + (rfcn - b.offset) / 10; - return { ...b, dlfreq, ulfreq }; + return { band: b.band, dlfreq, ulfreq }; +} + +function calcNrBand(nrarfcn) { + const b = NR_BANDS.find(b => nrarfcn >= b.min && nrarfcn <= b.max); + if (!b) return { band: String(nrarfcn), dlfreq: 0 }; + const dlfreq = b.dlLow + (nrarfcn - b.offset) / 1000; + return { band: b.name, dlfreq }; } -/** - * Calculate DL/UL frequencies and band name for non-LTE modes. - * @param {number} rfcn - * @returns {{ dlfreq: number, ulfreq: number, band: string }} - */ function calcNonLteBand(rfcn) { const match = NON_LTE_BANDS.find(b => b.condition(rfcn)); - return match ? match.calc(rfcn) : { ulfreq: 0, dlfreq: 0, band: String(rfcn) }; + return match ? match.calc(rfcn) : { band: String(rfcn), dlfreq: 0, ulfreq: 0 }; } -/** - * Build a LAC/CID/eNB/Cell/PCI label and value string. - * @param {Object} modem - Single modem entry - * @returns {{ namecid: string, lactac: string }} - */ function buildCellId(modem) { const { enbid, cell, pci, lac, cid } = modem; const parts = [lac, cid]; @@ -263,16 +228,8 @@ function buildCellId(modem) { return { namecid, lactac }; } -/** - * Derive mode-specific labels and carrier aggregation info. - * @param {Object} modem - Single modem entry - * @param {string} netmode - * @param {string} band - * @param {number} bw - * @returns {{ carrier, bcc, bca, bwDisplay, namech, namesnr, namecid, lactac, namebnd }} - */ function buildModeInfo(modem, netmode, band, bw) { - let carrier = ''; + let carrier = ''; let bcc, bca, bwDisplay, namech, namesnr, namecid, lactac; if (netmode === 'LTE' || netmode === 'LTE+NR') { @@ -280,15 +237,29 @@ function buildModeInfo(modem, netmode, band, bw) { carrier = (netmode === 'LTE' && calte > 0) ? '+' : ''; namech = 'EARFCN'; namesnr = 'SINR'; - + if (calte > 0) { bwDisplay = modem.bwca; - bcc = ` B${band}${modem.scc}`; - bca = bwDisplay ? ` / ${bwDisplay} MHz` : ''; + let sccFormatted = modem.scc || ''; + if (netmode === '5GNR' && sccFormatted) { + sccFormatted = sccFormatted.replace(/\+(\d+)/g, '+n$1'); + if (sccFormatted.startsWith('+n')) { + sccFormatted = sccFormatted.substring(1); + } + if (sccFormatted) sccFormatted = '+' + sccFormatted; + } + bcc = ` ${band}${sccFormatted}`; + bca = bwDisplay ? ` / ${bwDisplay} MHz` : ''; } else { bwDisplay = bw; - bcc = ` B${band}`; - bca = bw ? ` / ${bw} MHz` : ''; + bcc = ` ${band}`; + if (netmode === 'LTE+NR' && bw) { + bca = ` / ${bw} MHz`; + } else if (bw) { + bca = ` / ${bw} MHz`; + } else { + bca = ''; + } } const cellInfo = buildCellId(modem); @@ -317,35 +288,16 @@ function buildModeInfo(modem, netmode, band, bw) { return { carrier, bcc, bca: bca || '', bwDisplay, namech, namesnr, namecid, lactac, namebnd }; } -/** - * Set textContent of element by id (if it exists). - * @param {string} id - * @param {string} text - */ function setText(id, text) { const el = getEl(id); if (el) el.textContent = text; } -/** - * Set innerHTML of element by id (if it exists). - * @param {string} id - * @param {string} html - */ function setHtml(id, html) { const el = getEl(id); if (el) el.innerHTML = html; } -/** - * Update a signal progress bar, hiding its parent row if value is missing. - * @param {string} elId - Element id (without modem index) - * @param {number} idx - Modem index - * @param {*} rawVal - Raw value from modem JSON - * @param {string} unit - Unit suffix, e.g. ' dBm' - * @param {string} type - Key in PROGRESS_CONFIG - * @param {number} boundary - */ function updateSignalBar(elId, idx, rawVal, unit, type, boundary) { const el = getEl(elId + idx); if (!el) return; @@ -357,7 +309,6 @@ function updateSignalBar(elId, idx, rawVal, unit, type, boundary) { } // Main view - return view.extend({ load: function() { @@ -381,20 +332,66 @@ return view.extend({ const modem = json.modem[i]; const netmode = modem.mode || ''; const rfcn = modem.arfcn || 0; + const nrArfcn = modem.nr_arfcn || 0; // Band / Frequency - let dlfreq, ulfreq, band, bw; + let lteBand = '', nrBand = ''; + let lteDlfreq = 0, nrDlfreq = 0; + let band = '', bw = ''; + // LTE band and frequency (for LTE and LTE+NR) if (netmode === 'LTE' || netmode === 'LTE+NR') { - ({ dlfreq, ulfreq, band } = calcLteBand(rfcn)); - const bandwidths = [1.4, 3, 5, 10, 15, 20]; - bw = bandwidths[modem.bwdl] || ''; - } else { - ({ dlfreq, ulfreq, band } = calcNonLteBand(rfcn)); - bw = ''; + const lte = calcLteBand(rfcn); + lteBand = `B${lte.band}`; + lteDlfreq = lte.dlfreq; } - const arfcnStr = `${rfcn} (${dlfreq} / ${ulfreq} MHz)`; + // NR band (for LTE+NR and 5G NR) + if (netmode === '5GNR' && nrArfcn) { + const nr = calcNrBand(nrArfcn); + nrBand = `n${nr.band}`; + nrDlfreq = nr.dlfreq; + } + + // Combined band display + let bandDisplay = ''; + if (lteBand && nrBand) { + bandDisplay = `${lteBand} + ${nrBand}`; + } else if (lteBand) { + bandDisplay = lteBand; + } else if (nrBand) { + bandDisplay = nrBand; + } else { + // Fallback for UMTS/GSM + const nonLte = calcNonLteBand(rfcn); + bandDisplay = nonLte.band; + lteDlfreq = nonLte.dlfreq; + } + + // Bandwidth handling + const lteBandwidths = [1.4, 3, 5, 10, 15, 20]; + const nrBandwidths = [5, 10, 15, 20, 25, 30, 40, 50, 60, 70, 80, 90, 100]; + if (netmode === 'LTE' || netmode === 'LTE+NR') { + if (modem.bwca && modem.bwca > 0) { + bw = modem.bwca; + } else { + bw = lteBandwidths[modem.bwdl] || ''; + } + } else if (netmode === '5GNR') { + if (modem.bwca && modem.bwca > 0) { + bw = modem.bwca; + } else if (modem.bwdl) { + bw = nrBandwidths[modem.bwdl] || ''; + } + } + + // Frequency display - only primary (LTE or NR) + let arfcnDisplay = ''; + if (lteDlfreq) { + arfcnDisplay = `${rfcn} (${lteDlfreq.toFixed(1)} MHz)`; + } else if (nrDlfreq && nrArfcn) { + arfcnDisplay = `${nrArfcn} (${nrDlfreq.toFixed(1)} MHz)`; + } // Registration const rg = Number(modem.reg); @@ -403,16 +400,15 @@ return view.extend({ // Signal icon const icon = resolveSignalIcon(modem.csq_per || 0); - // Mode-specific labels + // Build mode info for CA and other labels const { carrier, bcc, bca, namech, namesnr, namecid, lactac, namebnd } = - buildModeInfo(modem, netmode, band, bw); + buildModeInfo(modem, netmode, bandDisplay, bw); // DOM updates - setHtml('status' + i, formatModemStatus(modem, icon, reg)); + setHtml('status' + i, formatModemStatus(modem, icon, reg)); const modeEl = getEl('mode' + i); if (modeEl) { - // FIX: was `signal = 0` (assignment), must be `=== 0` if (modem.signal === 0 || modem.signal === '' || !netmode) { modeEl.textContent = '--'; } else { @@ -424,11 +420,10 @@ return view.extend({ setText('chname' + i, namech); setText('namecid' + i, namecid); setText('snrname' + i, namesnr); - setHtml('arfcn' + i, arfcnStr); + setHtml('arfcn' + i, arfcnDisplay); setHtml('lac' + i, lactac); // Progress bars - // RSSI always visible if element exists if (getEl('rssi' + i)) { if (!modem.rssi || modem.rssi === '') { setText('rssi' + i, '--'); @@ -437,17 +432,13 @@ return view.extend({ } } - // SINR / ECIO (shared element, hidden when unavailable) updateSignalBar( 'sinr', i, modem.sinr, ' dB', netmode === 'LTE' ? 'sinr' : 'ecio', netmode === 'LTE' ? -20 : -24 ); - // RSRP (hidden when unavailable) updateSignalBar('rsrp', i, modem.rsrp, ' dBm', 'rsrp', -140); - - // RSRQ (hidden when unavailable) updateSignalBar('rsrq', i, modem.rsrq, ' dB', 'rsrq', -20); } }); diff --git a/luci-app-passwall/Makefile b/luci-app-passwall/Makefile index 5e4a6965e..55f2cf66a 100644 --- a/luci-app-passwall/Makefile +++ b/luci-app-passwall/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall PKG_VERSION:=26.5.20 -PKG_RELEASE:=144 +PKG_RELEASE:=145 PKG_PO_VERSION:=$(PKG_VERSION) PKG_CONFIG_DEPENDS:= \ diff --git a/luci-app-passwall/luasrc/passwall/util_xray.lua b/luci-app-passwall/luasrc/passwall/util_xray.lua index c6e654e32..2e1ccf60e 100644 --- a/luci-app-passwall/luasrc/passwall/util_xray.lua +++ b/luci-app-passwall/luasrc/passwall/util_xray.lua @@ -1804,13 +1804,14 @@ function gen_config(var) -- remote dns outbound rules if value.outboundTag == "blackhole" then table.insert(remote_dns_out_rules, { - action = "reject", + action = "return", + rCode = 0, domain = api.clone(value.domain) }) else table.insert(remote_dns_out_rules, { action = "hijack", - qtype = "1,28", + qType = "1,28", domain = api.clone(value.domain) }) end @@ -1877,7 +1878,7 @@ function gen_config(var) if remote_dns_outbound.settings.rules then table.insert(remote_dns_out_rules, { action = "hijack", - qtype = "1,28" + qType = "1,28" }) table.insert(remote_dns_out_rules, { action = "direct" diff --git a/luci-app-passwall/root/usr/share/passwall/iptables.sh b/luci-app-passwall/root/usr/share/passwall/iptables.sh index 0d28b1865..1f8a11597 100755 --- a/luci-app-passwall/root/usr/share/passwall/iptables.sh +++ b/luci-app-passwall/root/usr/share/passwall/iptables.sh @@ -734,7 +734,7 @@ filter_haproxy() { } filter_vpsip() { - local EXCLUDE_VPSIP="^(127\.0\.0\.1|1\.1\.1\.1|1\.1\.1\.2|8\.8\.8\.8|8\.8\.4\.4|9\.9\.9\.9)$" + local EXCLUDE_VPSIP="^(0\.0\.0\.0|127\.0\.0\.1|1\.1\.1\.1|1\.1\.1\.2|8\.8\.8\.8|8\.8\.4\.4|9\.9\.9\.9)$" uci show $CONFIG | grep -E "(\.address=|\.download_address=)" | cut -d "'" -f 2 | grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}$" | grep -Ev "$EXCLUDE_VPSIP" | sed "s/^/add $IPSET_VPS /" | awk '1; END{print "COMMIT"}' | ipset -! -R echolog " - [$?]加入所有IPv4节点到ipset[$IPSET_VPS]直连完成" uci show $CONFIG | grep -E "(\.address=|\.download_address=)" | cut -d "'" -f 2 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed "s/^/add $IPSET_VPS6 /" | awk '1; END{print "COMMIT"}' | ipset -! -R diff --git a/luci-app-passwall/root/usr/share/passwall/nftables.sh b/luci-app-passwall/root/usr/share/passwall/nftables.sh index 3c54afec4..3944df4e9 100755 --- a/luci-app-passwall/root/usr/share/passwall/nftables.sh +++ b/luci-app-passwall/root/usr/share/passwall/nftables.sh @@ -785,7 +785,7 @@ filter_vps_addr() { } filter_vpsip() { - local EXCLUDE_VPSIP="^(127\.0\.0\.1|1\.1\.1\.1|1\.1\.1\.2|8\.8\.8\.8|8\.8\.4\.4|9\.9\.9\.9)$" + local EXCLUDE_VPSIP="^(0\.0\.0\.0|127\.0\.0\.1|1\.1\.1\.1|1\.1\.1\.2|8\.8\.8\.8|8\.8\.4\.4|9\.9\.9\.9)$" uci show $CONFIG | grep -E "(\.address=|\.download_address=)" | cut -d "'" -f 2 | grep -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}" | grep -Ev "$EXCLUDE_VPSIP" | insert_nftset $NFTSET_VPS "-1" echolog " - [$?]加入所有IPv4节点到nftset[$NFTSET_VPS]直连完成" uci show $CONFIG | grep -E "(\.address=|\.download_address=)" | cut -d "'" -f 2 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | insert_nftset $NFTSET_VPS6 "-1" diff --git a/luci-app-quickfile/Makefile b/luci-app-quickfile/Makefile index 428650bce..314e654ad 100644 --- a/luci-app-quickfile/Makefile +++ b/luci-app-quickfile/Makefile @@ -7,7 +7,7 @@ LUCI_DEPENDS:=+luci-nginx +quickfile PKG_LICENSE:=Apache-2.0 PKG_VERSION:=1.0.0 -PKG_RELEASE:=4 +PKG_RELEASE:=5 PKG_MAINTAINER:=sbwml include $(TOPDIR)/feeds/luci/luci.mk diff --git a/luci-app-quickfile/htdocs/luci-static/resources/view/system/quickfile.js b/luci-app-quickfile/htdocs/luci-static/resources/view/system/quickfile.js index 5a44f8f98..37078d5bb 100644 --- a/luci-app-quickfile/htdocs/luci-static/resources/view/system/quickfile.js +++ b/luci-app-quickfile/htdocs/luci-static/resources/view/system/quickfile.js @@ -10,8 +10,6 @@ return view.extend({ s.anonymous = true; s.render = function () { - const host = window.location.origin; - const iframeContainer = E('div', { 'class': 'iframe-container', 'style': ` @@ -26,7 +24,7 @@ return view.extend({ ` }, [ E('iframe', { - 'src': `/cgi-bin/luci/quickfile?host=${encodeURIComponent(host)}`, + 'src': `/cgi-bin/luci/quickfile`, 'style': ` width: 100%; height: 100%; diff --git a/luci-app-quickfile/po/templates/quickfile.pot b/luci-app-quickfile/po/templates/quickfile.pot new file mode 100644 index 000000000..abc44da38 --- /dev/null +++ b/luci-app-quickfile/po/templates/quickfile.pot @@ -0,0 +1,6 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: luci-app-quickfile/root/usr/share/luci/menu.d/luci-app-quickfile.json:3 +msgid "Quick File Manager" +msgstr "" diff --git a/luci-app-quickfile/po/zh_Hans/quickfile.po b/luci-app-quickfile/po/zh_Hans/quickfile.po index e8a739c63..eadab9ace 100644 --- a/luci-app-quickfile/po/zh_Hans/quickfile.po +++ b/luci-app-quickfile/po/zh_Hans/quickfile.po @@ -1,5 +1,6 @@ msgid "" -msgstr "Content-Type: text/plain; charset=UTF-8" +msgstr "Content-Type: text/plain; charset=UTF-8\n" +#: luci-app-quickfile/root/usr/share/luci/menu.d/luci-app-quickfile.json:3 msgid "Quick File Manager" msgstr "文件管理" diff --git a/luci-app-quickfile/root/usr/share/rpcd/acl.d/luci-app-quickfile.json b/luci-app-quickfile/root/usr/share/rpcd/acl.d/luci-app-quickfile.json deleted file mode 100644 index 44af0efe3..000000000 --- a/luci-app-quickfile/root/usr/share/rpcd/acl.d/luci-app-quickfile.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "luci-app-quickfile": { - "description": "Grant UCI access for luci-app-openlist", - "read": { - "file": { - "/usr/bin/quickfile": [ "exec" ] - } - } - } -} diff --git a/qminfo/Makefile b/qminfo/Makefile index 21582a8d9..6207fa1a3 100644 --- a/qminfo/Makefile +++ b/qminfo/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=qminfo PKG_VERSION=0.0.3 -PKG_RELEASE:=6 +PKG_RELEASE:=7 include $(INCLUDE_DIR)/package.mk diff --git a/qminfo/src/qminfo.c b/qminfo/src/qminfo.c index 871eac4d5..20c8a0587 100644 --- a/qminfo/src/qminfo.c +++ b/qminfo/src/qminfo.c @@ -299,8 +299,8 @@ static void emit_results(void) printf(" NR SNR : %d dB\n", (int)roundf(info.nr_snr / 10.0f)); } if (info.has_ca) { - printf(" LTE-A SCC : %d — %s\n", info.lte_ca, info.scc_bands); - printf(" BW CA : %.1f MHz\n", info.bw_ca_total / 1000.0f); + printf(" SCC : %dxCA — %s\n", info.lte_ca, info.scc_bands); + printf(" BW CA : %.1f MHz\n", (info.bw_ca_total - bw_index_to_khz(info.bw_dl)) / 1000.0f); } printf("=================================================\n"); return; @@ -348,7 +348,7 @@ static void emit_results(void) if (info.nr_nsa && !info.dcnr_restricted) json_mode_str = "LTE+NR"; else if (info.nr_sa) - json_mode_str = "5G NR"; + json_mode_str = "5GNR"; else json_mode_str = info.mode[0] ? info.mode : "";