mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-02 19:03:56 +08:00
🎁 Sync 2026-06-01 20:30:44
This commit is contained in:
1 parent
676f7c1ef7
commit
1366ad1bbb
26 files changed
+606
-140
No files matched your search
@@ -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 <lwb1978@gmail.com>
|
||||||
|
|
||||||
|
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)))
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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") .. "<br>" .. 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") .. "<br>" .. 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
|
||||||
@@ -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
|
||||||
|
-%>
|
||||||
|
<script type="text/javascript">//<![CDATA[
|
||||||
|
var Port = "<%=port%>"
|
||||||
|
var Http = "<%=http%>"
|
||||||
|
XHR.poll(3, '<%=url([[admin]], [[services]], [[gecoosac]], [[status]])%>', null,
|
||||||
|
function(x, data) {
|
||||||
|
var tb = document.getElementById('gecoosac_status');
|
||||||
|
if (data && tb) {
|
||||||
|
if (data.running) {
|
||||||
|
var links = '<font color=green><%:The GecoosAC service is running.%></font> <input class="cbi-button cbi-button-reload " type="button" value="<%:Open the mgmt page%>" onclick="openClient();" />';
|
||||||
|
tb.innerHTML = links;
|
||||||
|
} else {
|
||||||
|
tb.innerHTML = '<font color=red><%:The GecoosAC service is not running.%></font>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
function openClient() {
|
||||||
|
var url = Http + window.location.hostname + ":" + Port;
|
||||||
|
window.open(url);
|
||||||
|
}
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
|
<style>.mar-10 {margin-left: 50px; margin-right: 10px;}</style>
|
||||||
|
<fieldset class="cbi-section">
|
||||||
|
<p id="gecoosac_status">
|
||||||
|
<em><%:Collecting data...%></em>
|
||||||
|
</p>
|
||||||
|
</fieldset>
|
||||||
@@ -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 "清理上传目录"
|
||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
zh-cn
|
||||||
@@ -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'
|
||||||
|
|
||||||
@@ -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-----
|
||||||
@@ -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-----
|
||||||
Executable
+70
@@ -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"
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"luci-app-gecoosac": {
|
||||||
|
"description": "Grant UCI access for luci-app-gecoosac",
|
||||||
|
"read": {
|
||||||
|
"uci": [ "gecoosac" ]
|
||||||
|
},
|
||||||
|
"write": {
|
||||||
|
"uci": [ "gecoosac" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ LUCI_TITLE:=Information dashboard for 3G/LTE dongle
|
|||||||
LUCI_DEPENDS:=+modeminfo
|
LUCI_DEPENDS:=+modeminfo
|
||||||
PKG_LICENSE:=GPLv3
|
PKG_LICENSE:=GPLv3
|
||||||
PKG_VERSION:=0.4.7
|
PKG_VERSION:=0.4.7
|
||||||
PKG_RELEASE:=7
|
PKG_RELEASE:=8
|
||||||
|
|
||||||
include $(TOPDIR)/feeds/luci/luci.mk
|
include $(TOPDIR)/feeds/luci/luci.mk
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
Licensed to the GNU General Public License v3.0.
|
Licensed to the GNU General Public License v3.0.
|
||||||
|
|
||||||
Refactored: bug fixes, performance improvements, code deduplication.
|
Refactored: bug fixes, performance improvements, code deduplication.
|
||||||
|
Modified: 5G NR support with combined band display
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const REGISTERED_STATUSES = [1, 6, 9];
|
const REGISTERED_STATUSES = [1, 6, 9];
|
||||||
@@ -39,37 +40,30 @@ const REG_STATUSES = new Map([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
// Progress bar configuration
|
// 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 = {
|
const PROGRESS_CONFIG = {
|
||||||
rssi: {
|
rssi: {
|
||||||
selector: '#rssi',
|
selector: '#rssi',
|
||||||
min: -110, max: -50,
|
min: -110, max: -50,
|
||||||
// Linear map from [-110..-50] → [0..100]
|
|
||||||
calc: (vn, mn) => Math.floor(100 * (1 - (-50 - vn) / (-50 - mn))),
|
calc: (vn, mn) => Math.floor(100 * (1 - (-50 - vn) / (-50 - mn))),
|
||||||
},
|
},
|
||||||
rsrp: {
|
rsrp: {
|
||||||
selector: '#rsrp',
|
selector: '#rsrp',
|
||||||
min: -140, max: -50,
|
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))),
|
calc: (vn, mn) => Math.floor(120 * (1 - (-50 - vn) / (-70 - mn))),
|
||||||
},
|
},
|
||||||
sinr: {
|
sinr: {
|
||||||
selector: '#sinr',
|
selector: '#sinr',
|
||||||
min: -20, max: 30,
|
min: -20, max: 30,
|
||||||
// Linear map from [-20..30] → [0..100]
|
|
||||||
calc: (vn, mn) => Math.floor(100 - (100 * (1 - ((mn - vn) / (mn - 30))))),
|
calc: (vn, mn) => Math.floor(100 - (100 * (1 - ((mn - vn) / (mn - 30))))),
|
||||||
},
|
},
|
||||||
rsrq: {
|
rsrq: {
|
||||||
selector: '#rsrq',
|
selector: '#rsrq',
|
||||||
min: -20, max: 0,
|
min: -20, max: 0,
|
||||||
// Proportional map from [-20..0] → [0..100]
|
|
||||||
calc: (vn, mn) => Math.floor(115 - (100 / mn) * vn),
|
calc: (vn, mn) => Math.floor(115 - (100 / mn) * vn),
|
||||||
},
|
},
|
||||||
ecio: {
|
ecio: {
|
||||||
selector: '#sinr',
|
selector: '#sinr',
|
||||||
min: -24, max: 0,
|
min: -24, max: 0,
|
||||||
// Same shape as rsrq but for EC/IO range [-24..0]
|
|
||||||
calc: (vn, mn) => Math.floor(100 - (100 / mn) * vn),
|
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' },
|
{ 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
|
// Non-LTE (UMTS/GSM) ARFCN band/frequency table
|
||||||
const NON_LTE_BANDS = [
|
const NON_LTE_BANDS = [
|
||||||
{
|
{
|
||||||
@@ -117,34 +125,16 @@ const NON_LTE_BANDS = [
|
|||||||
|
|
||||||
const UMTS_MODES = /(HS|3G|UMTS|WCDMA)/i;
|
const UMTS_MODES = /(HS|3G|UMTS|WCDMA)/i;
|
||||||
|
|
||||||
// Helpers
|
// Helper functions
|
||||||
|
|
||||||
/**
|
|
||||||
* Safe getElementById wrapper.
|
|
||||||
* @param {string} id
|
|
||||||
* @returns {HTMLElement|null}
|
|
||||||
*/
|
|
||||||
function getEl(id) {
|
function getEl(id) {
|
||||||
return document.getElementById(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) {
|
function setRowVisible(el, show) {
|
||||||
const row = el && el.parentElement && el.parentElement.parentElement;
|
const row = el && el.parentElement && el.parentElement.parentElement;
|
||||||
if (row) row.style.display = show ? '' : 'none';
|
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) {
|
function updateProgressBar(type, value, max, idx) {
|
||||||
const config = PROGRESS_CONFIG[type];
|
const config = PROGRESS_CONFIG[type];
|
||||||
if (!config) return;
|
if (!config) return;
|
||||||
@@ -156,28 +146,16 @@ function updateProgressBar(type, value, max, idx) {
|
|||||||
const mn = parseInt(max) || 100;
|
const mn = parseInt(max) || 100;
|
||||||
const pc = Math.min(100, Math.max(0, config.calc(vn, mn)));
|
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.firstElementChild.style.animationDirection = 'reverse';
|
||||||
pg.setAttribute('title', String(value));
|
pg.setAttribute('title', String(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Format distance string, returns empty string when unavailable.
|
|
||||||
* @param {string|number} dist
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
function formatDistance(dist) {
|
function formatDistance(dist) {
|
||||||
if (!dist || dist === '--' || dist === '' || dist === '0.00') return '';
|
if (!dist || dist === '--' || dist === '' || dist === '0.00') return '';
|
||||||
return ' ~' + dist + ' km';
|
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) {
|
function formatModemStatus(modem, icon, reg) {
|
||||||
const rg = parseInt(modem.reg) || 0;
|
const rg = parseInt(modem.reg) || 0;
|
||||||
const p = modem.csq_per || 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) {
|
function resolveSignalIcon(pct) {
|
||||||
const { icn } = SIGNAL_ICONS.find(({ max }) => pct <= max) || SIGNAL_ICONS[SIGNAL_ICONS.length - 1];
|
const { icn } = SIGNAL_ICONS.find(({ max }) => pct <= max) || SIGNAL_ICONS[SIGNAL_ICONS.length - 1];
|
||||||
return L.resource(`view/modem/icons/${icn}`);
|
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) {
|
function calcLteBand(rfcn) {
|
||||||
const b = LTE_BANDS.find(b => rfcn >= b.min && rfcn <= b.max);
|
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 dlfreq = b.frdl + (rfcn - b.offset) / 10;
|
||||||
const ulfreq = b.frul + (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) {
|
function calcNonLteBand(rfcn) {
|
||||||
const match = NON_LTE_BANDS.find(b => b.condition(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) {
|
function buildCellId(modem) {
|
||||||
const { enbid, cell, pci, lac, cid } = modem;
|
const { enbid, cell, pci, lac, cid } = modem;
|
||||||
const parts = [lac, cid];
|
const parts = [lac, cid];
|
||||||
@@ -263,16 +228,8 @@ function buildCellId(modem) {
|
|||||||
return { namecid, lactac };
|
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) {
|
function buildModeInfo(modem, netmode, band, bw) {
|
||||||
let carrier = '';
|
let carrier = '';
|
||||||
let bcc, bca, bwDisplay, namech, namesnr, namecid, lactac;
|
let bcc, bca, bwDisplay, namech, namesnr, namecid, lactac;
|
||||||
|
|
||||||
if (netmode === 'LTE' || netmode === 'LTE+NR') {
|
if (netmode === 'LTE' || netmode === 'LTE+NR') {
|
||||||
@@ -280,15 +237,29 @@ function buildModeInfo(modem, netmode, band, bw) {
|
|||||||
carrier = (netmode === 'LTE' && calte > 0) ? '+' : '';
|
carrier = (netmode === 'LTE' && calte > 0) ? '+' : '';
|
||||||
namech = 'EARFCN';
|
namech = 'EARFCN';
|
||||||
namesnr = 'SINR';
|
namesnr = 'SINR';
|
||||||
|
|
||||||
if (calte > 0) {
|
if (calte > 0) {
|
||||||
bwDisplay = modem.bwca;
|
bwDisplay = modem.bwca;
|
||||||
bcc = ` B${band}${modem.scc}`;
|
let sccFormatted = modem.scc || '';
|
||||||
bca = bwDisplay ? ` / ${bwDisplay} MHz` : '';
|
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 {
|
} else {
|
||||||
bwDisplay = bw;
|
bwDisplay = bw;
|
||||||
bcc = ` B${band}`;
|
bcc = ` ${band}`;
|
||||||
bca = bw ? ` / ${bw} MHz` : '';
|
if (netmode === 'LTE+NR' && bw) {
|
||||||
|
bca = ` / ${bw} MHz`;
|
||||||
|
} else if (bw) {
|
||||||
|
bca = ` / ${bw} MHz`;
|
||||||
|
} else {
|
||||||
|
bca = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const cellInfo = buildCellId(modem);
|
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 };
|
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) {
|
function setText(id, text) {
|
||||||
const el = getEl(id);
|
const el = getEl(id);
|
||||||
if (el) el.textContent = text;
|
if (el) el.textContent = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set innerHTML of element by id (if it exists).
|
|
||||||
* @param {string} id
|
|
||||||
* @param {string} html
|
|
||||||
*/
|
|
||||||
function setHtml(id, html) {
|
function setHtml(id, html) {
|
||||||
const el = getEl(id);
|
const el = getEl(id);
|
||||||
if (el) el.innerHTML = html;
|
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) {
|
function updateSignalBar(elId, idx, rawVal, unit, type, boundary) {
|
||||||
const el = getEl(elId + idx);
|
const el = getEl(elId + idx);
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
@@ -357,7 +309,6 @@ function updateSignalBar(elId, idx, rawVal, unit, type, boundary) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Main view
|
// Main view
|
||||||
|
|
||||||
return view.extend({
|
return view.extend({
|
||||||
|
|
||||||
load: function() {
|
load: function() {
|
||||||
@@ -381,20 +332,66 @@ return view.extend({
|
|||||||
const modem = json.modem[i];
|
const modem = json.modem[i];
|
||||||
const netmode = modem.mode || '';
|
const netmode = modem.mode || '';
|
||||||
const rfcn = modem.arfcn || 0;
|
const rfcn = modem.arfcn || 0;
|
||||||
|
const nrArfcn = modem.nr_arfcn || 0;
|
||||||
|
|
||||||
// Band / Frequency
|
// 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') {
|
if (netmode === 'LTE' || netmode === 'LTE+NR') {
|
||||||
({ dlfreq, ulfreq, band } = calcLteBand(rfcn));
|
const lte = calcLteBand(rfcn);
|
||||||
const bandwidths = [1.4, 3, 5, 10, 15, 20];
|
lteBand = `B${lte.band}`;
|
||||||
bw = bandwidths[modem.bwdl] || '';
|
lteDlfreq = lte.dlfreq;
|
||||||
} else {
|
|
||||||
({ dlfreq, ulfreq, band } = calcNonLteBand(rfcn));
|
|
||||||
bw = '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// Registration
|
||||||
const rg = Number(modem.reg);
|
const rg = Number(modem.reg);
|
||||||
@@ -403,16 +400,15 @@ return view.extend({
|
|||||||
// Signal icon
|
// Signal icon
|
||||||
const icon = resolveSignalIcon(modem.csq_per || 0);
|
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 } =
|
const { carrier, bcc, bca, namech, namesnr, namecid, lactac, namebnd } =
|
||||||
buildModeInfo(modem, netmode, band, bw);
|
buildModeInfo(modem, netmode, bandDisplay, bw);
|
||||||
|
|
||||||
// DOM updates
|
// DOM updates
|
||||||
setHtml('status' + i, formatModemStatus(modem, icon, reg));
|
setHtml('status' + i, formatModemStatus(modem, icon, reg));
|
||||||
|
|
||||||
const modeEl = getEl('mode' + i);
|
const modeEl = getEl('mode' + i);
|
||||||
if (modeEl) {
|
if (modeEl) {
|
||||||
// FIX: was `signal = 0` (assignment), must be `=== 0`
|
|
||||||
if (modem.signal === 0 || modem.signal === '' || !netmode) {
|
if (modem.signal === 0 || modem.signal === '' || !netmode) {
|
||||||
modeEl.textContent = '--';
|
modeEl.textContent = '--';
|
||||||
} else {
|
} else {
|
||||||
@@ -424,11 +420,10 @@ return view.extend({
|
|||||||
setText('chname' + i, namech);
|
setText('chname' + i, namech);
|
||||||
setText('namecid' + i, namecid);
|
setText('namecid' + i, namecid);
|
||||||
setText('snrname' + i, namesnr);
|
setText('snrname' + i, namesnr);
|
||||||
setHtml('arfcn' + i, arfcnStr);
|
setHtml('arfcn' + i, arfcnDisplay);
|
||||||
setHtml('lac' + i, lactac);
|
setHtml('lac' + i, lactac);
|
||||||
|
|
||||||
// Progress bars
|
// Progress bars
|
||||||
// RSSI always visible if element exists
|
|
||||||
if (getEl('rssi' + i)) {
|
if (getEl('rssi' + i)) {
|
||||||
if (!modem.rssi || modem.rssi === '') {
|
if (!modem.rssi || modem.rssi === '') {
|
||||||
setText('rssi' + i, '--');
|
setText('rssi' + i, '--');
|
||||||
@@ -437,17 +432,13 @@ return view.extend({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SINR / ECIO (shared element, hidden when unavailable)
|
|
||||||
updateSignalBar(
|
updateSignalBar(
|
||||||
'sinr', i, modem.sinr, ' dB',
|
'sinr', i, modem.sinr, ' dB',
|
||||||
netmode === 'LTE' ? 'sinr' : 'ecio',
|
netmode === 'LTE' ? 'sinr' : 'ecio',
|
||||||
netmode === 'LTE' ? -20 : -24
|
netmode === 'LTE' ? -20 : -24
|
||||||
);
|
);
|
||||||
|
|
||||||
// RSRP (hidden when unavailable)
|
|
||||||
updateSignalBar('rsrp', i, modem.rsrp, ' dBm', 'rsrp', -140);
|
updateSignalBar('rsrp', i, modem.rsrp, ' dBm', 'rsrp', -140);
|
||||||
|
|
||||||
// RSRQ (hidden when unavailable)
|
|
||||||
updateSignalBar('rsrq', i, modem.rsrq, ' dB', 'rsrq', -20);
|
updateSignalBar('rsrq', i, modem.rsrq, ' dB', 'rsrq', -20);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
|
|||||||
|
|
||||||
PKG_NAME:=luci-app-passwall
|
PKG_NAME:=luci-app-passwall
|
||||||
PKG_VERSION:=26.5.20
|
PKG_VERSION:=26.5.20
|
||||||
PKG_RELEASE:=144
|
PKG_RELEASE:=145
|
||||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||||
|
|
||||||
PKG_CONFIG_DEPENDS:= \
|
PKG_CONFIG_DEPENDS:= \
|
||||||
|
|||||||
@@ -1804,13 +1804,14 @@ function gen_config(var)
|
|||||||
-- remote dns outbound rules
|
-- remote dns outbound rules
|
||||||
if value.outboundTag == "blackhole" then
|
if value.outboundTag == "blackhole" then
|
||||||
table.insert(remote_dns_out_rules, {
|
table.insert(remote_dns_out_rules, {
|
||||||
action = "reject",
|
action = "return",
|
||||||
|
rCode = 0,
|
||||||
domain = api.clone(value.domain)
|
domain = api.clone(value.domain)
|
||||||
})
|
})
|
||||||
else
|
else
|
||||||
table.insert(remote_dns_out_rules, {
|
table.insert(remote_dns_out_rules, {
|
||||||
action = "hijack",
|
action = "hijack",
|
||||||
qtype = "1,28",
|
qType = "1,28",
|
||||||
domain = api.clone(value.domain)
|
domain = api.clone(value.domain)
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
@@ -1877,7 +1878,7 @@ function gen_config(var)
|
|||||||
if remote_dns_outbound.settings.rules then
|
if remote_dns_outbound.settings.rules then
|
||||||
table.insert(remote_dns_out_rules, {
|
table.insert(remote_dns_out_rules, {
|
||||||
action = "hijack",
|
action = "hijack",
|
||||||
qtype = "1,28"
|
qType = "1,28"
|
||||||
})
|
})
|
||||||
table.insert(remote_dns_out_rules, {
|
table.insert(remote_dns_out_rules, {
|
||||||
action = "direct"
|
action = "direct"
|
||||||
|
|||||||
@@ -734,7 +734,7 @@ filter_haproxy() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
filter_vpsip() {
|
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
|
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]直连完成"
|
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
|
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
|
||||||
|
|||||||
@@ -785,7 +785,7 @@ filter_vps_addr() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
filter_vpsip() {
|
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"
|
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]直连完成"
|
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"
|
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"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ LUCI_DEPENDS:=+luci-nginx +quickfile
|
|||||||
|
|
||||||
PKG_LICENSE:=Apache-2.0
|
PKG_LICENSE:=Apache-2.0
|
||||||
PKG_VERSION:=1.0.0
|
PKG_VERSION:=1.0.0
|
||||||
PKG_RELEASE:=4
|
PKG_RELEASE:=5
|
||||||
PKG_MAINTAINER:=sbwml <admin@cooluc.com>
|
PKG_MAINTAINER:=sbwml <admin@cooluc.com>
|
||||||
|
|
||||||
include $(TOPDIR)/feeds/luci/luci.mk
|
include $(TOPDIR)/feeds/luci/luci.mk
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ return view.extend({
|
|||||||
s.anonymous = true;
|
s.anonymous = true;
|
||||||
|
|
||||||
s.render = function () {
|
s.render = function () {
|
||||||
const host = window.location.origin;
|
|
||||||
|
|
||||||
const iframeContainer = E('div', {
|
const iframeContainer = E('div', {
|
||||||
'class': 'iframe-container',
|
'class': 'iframe-container',
|
||||||
'style': `
|
'style': `
|
||||||
@@ -26,7 +24,7 @@ return view.extend({
|
|||||||
`
|
`
|
||||||
}, [
|
}, [
|
||||||
E('iframe', {
|
E('iframe', {
|
||||||
'src': `/cgi-bin/luci/quickfile?host=${encodeURIComponent(host)}`,
|
'src': `/cgi-bin/luci/quickfile`,
|
||||||
'style': `
|
'style': `
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -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 ""
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
msgid ""
|
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"
|
msgid "Quick File Manager"
|
||||||
msgstr "文件管理"
|
msgstr "文件管理"
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"luci-app-quickfile": {
|
|
||||||
"description": "Grant UCI access for luci-app-openlist",
|
|
||||||
"read": {
|
|
||||||
"file": {
|
|
||||||
"/usr/bin/quickfile": [ "exec" ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-1
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
|||||||
|
|
||||||
PKG_NAME:=qminfo
|
PKG_NAME:=qminfo
|
||||||
PKG_VERSION=0.0.3
|
PKG_VERSION=0.0.3
|
||||||
PKG_RELEASE:=6
|
PKG_RELEASE:=7
|
||||||
|
|
||||||
include $(INCLUDE_DIR)/package.mk
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -299,8 +299,8 @@ static void emit_results(void)
|
|||||||
printf(" NR SNR : %d dB\n", (int)roundf(info.nr_snr / 10.0f));
|
printf(" NR SNR : %d dB\n", (int)roundf(info.nr_snr / 10.0f));
|
||||||
}
|
}
|
||||||
if (info.has_ca) {
|
if (info.has_ca) {
|
||||||
printf(" LTE-A SCC : %d — %s\n", info.lte_ca, info.scc_bands);
|
printf(" SCC : %dxCA — %s\n", info.lte_ca, info.scc_bands);
|
||||||
printf(" BW CA : %.1f MHz\n", info.bw_ca_total / 1000.0f);
|
printf(" BW CA : %.1f MHz\n", (info.bw_ca_total - bw_index_to_khz(info.bw_dl)) / 1000.0f);
|
||||||
}
|
}
|
||||||
printf("=================================================\n");
|
printf("=================================================\n");
|
||||||
return;
|
return;
|
||||||
@@ -348,7 +348,7 @@ static void emit_results(void)
|
|||||||
if (info.nr_nsa && !info.dcnr_restricted)
|
if (info.nr_nsa && !info.dcnr_restricted)
|
||||||
json_mode_str = "LTE+NR";
|
json_mode_str = "LTE+NR";
|
||||||
else if (info.nr_sa)
|
else if (info.nr_sa)
|
||||||
json_mode_str = "5G NR";
|
json_mode_str = "5GNR";
|
||||||
else
|
else
|
||||||
json_mode_str = info.mode[0] ? info.mode : "";
|
json_mode_str = info.mode[0] ? info.mode : "";
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user