diff --git a/luci-app-cpe/Makefile b/luci-app-cpe/Makefile
new file mode 100644
index 0000000..062fbb6
--- /dev/null
+++ b/luci-app-cpe/Makefile
@@ -0,0 +1,34 @@
+#将openwrt顶层目录下的rules.mk文件中的内容导入进来
+include $(TOPDIR)/rules.mk
+#软件包名
+PKG_NAME:=luci-app-cpe
+#软件包版本
+PKG_VERSION:=5.0.1
+#真正编译当前软件包的目录
+PKG_BUILD_DIR:= $(BUILD_DIR)/$(PKG_NAME)
+
+
+ #将$(TOPDIR)/include目录下的package.mk文件中的内容导入进来
+include $(INCLUDE_DIR)/package.mk
+
+define Package/luci-app-cpe
+ PKGARCH:=all
+ SECTION:=wrtnode
+ CATEGORY:=Daocaoren
+ SUBMENU :=CPE
+ TITLE:=luci-app-cpe
+ DEPENDS:=+sendat + luci-compat +kmod-usb-net +kmod-usb-net-cdc-ether +kmod-usb-acm \
+ +kmod-usb-net-qmi-wwan +kmod-usb-net-rndis +kmod-usb-serial-qualcomm \
+ +kmod-usb-net-sierrawireless +kmod-usb-ohci +kmod-usb-serial \
+ +kmod-usb-serial-option +kmod-usb-wdm \
+ +kmod-usb2 +kmod-usb3 \
+ +quectel-CM-5G +kmod-usb-net-cdc-mbim
+endef
+
+PKG_LICENSE:=GPLv3
+PKG_LINCESE_FILES:=LICENSE
+PKF_MAINTAINER:=daocaoren <168620188@qq.com>
+
+include $(TOPDIR)/feeds/luci/luci.mk
+# call BuildPackage - OpenWrt buildroot signature
+
diff --git a/luci-app-cpe/luasrc/controller/admin/cpe.lua b/luci-app-cpe/luasrc/controller/admin/cpe.lua
new file mode 100644
index 0000000..49dad2c
--- /dev/null
+++ b/luci-app-cpe/luasrc/controller/admin/cpe.lua
@@ -0,0 +1,189 @@
+module("luci.controller.admin.cpe", package.seeall)
+
+I18N = require "luci.i18n"
+translate = I18N.translate
+
+function index()
+ entry({"admin", "modem"}, firstchild(), translate("移动数据"), 25).dependent=false
+ entry({"admin", "modem", "nets"}, template("cpe/net_status"), translate("信号状态"), 0)
+ entry({"admin", "modem", "get_csq"}, call("action_get_csq"))
+ entry({"admin", "modem", "send_atcmd"}, call("action_send_atcmd"))
+
+ -- entry({"admin", "modem", "sms"}, template("cpe/sms"), translate("短信信息"), 1)
+ -- entry({"admin", "modem", "band"}, template("cpe/band"), translate("锁频段/锁PCI"), 1)
+ entry({"admin", "modem", "at"}, template("cpe/at"), translate("AT工具"), 98)
+
+ if not nixio.fs.access("/etc/config/modem") then
+ return
+ end
+ entry({"admin", "modem", "modem"}, cbi("cpe/modem"), _("模块设置"), 99)
+
+end
+
+function action_send_atcmd()
+ local rv ={}
+ local file
+ local p = luci.http.formvalue("p")
+ local set = luci.http.formvalue("set")
+ fixed = string.gsub(set, "\"", "~")
+ port= string.gsub(p, "\"", "~")
+ rv["at"] = fixed
+ rv["port"] = port
+
+ os.execute("/usr/share/cpe/atcmd.sh \'" .. port .. "\' \'" .. fixed .. "\'")
+ result = "/tmp/result.at"
+ file = io.open(result, "r")
+ if file ~= nil then
+ rv["result"] = file:read("*all")
+ file:close()
+ else
+ rv["result"] = " "
+ end
+ os.execute("/usr/share/cpe/delatcmd.sh")
+ luci.http.prepare_content("application/json")
+ luci.http.write_json(rv)
+
+end
+
+function action_get_csq()
+ local file
+ stat = "/tmp/cpe_cell.file"
+ file = io.open(stat, "r")
+ local rv ={}
+
+ -- echo 'RM520N-GL'
+ -- echo 'conntype'
+ -- echo '1e0e:9001'
+ -- echo $COPS #运营商
+ -- echo '' #端口
+ -- echo '' #温度
+ -- echo '' #协议
+ rv["modem"] = file:read("*line")
+ rv["conntype"] = file:read("*line")
+ rv["modid"] = file:read("*line")
+ rv["cops"] = file:read("*line")
+ rv["port"] = file:read("*line")
+ rv["tempur"] = file:read("*line")
+ rv["proto"] = file:read("*line")
+ file:read("*line")
+
+
+ -- echo $IMEI #imei
+ -- echo $IMSI #imsi
+ -- echo $ICCID #iccid
+ -- echo $phone #phone
+ rv["imei"] = file:read("*line")
+ rv["imsi"] = file:read("*line")
+ rv["iccid"] =file:read("*line")
+ rv["phone"] = file:read("*line")
+ file:read("*line")
+
+
+ -- echo $MODE
+ -- echo $CSQ
+ -- echo $CSQ_PER
+ -- echo $CSQ_RSSI
+ -- echo '' #参考信号接收质量 RSRQ ecio
+ -- echo '' #参考信号接收质量 RSRQ ecio1
+ -- echo '' #参考信号接收功率 RSRP rscp
+ -- echo '' #参考信号接收功率 RSRP rscp1
+ -- echo '' #信噪比 SINR rv["sinr"]
+ -- echo '' #连接状态监控 rv["netmode"]
+ rv["mode"] = file:read("*line")
+ rv["csq"] = file:read("*line")
+ rv["per"] = file:read("*line")
+ rv["rssi"] = file:read("*line")
+ rv["ecio"] = file:read("*line")
+ rv["ecio1"] = file:read("*line")
+ rv["rscp"] = file:read("*line")
+ rv["rscp1"] = file:read("*line")
+ rv["sinr"] = file:read("*line")
+ rv["netmode"] = file:read("*line")
+ file:read("*line")
+
+ rssi = rv["rssi"]
+ ecio = rv["ecio"]
+ rscp = rv["rscp"]
+ ecio1 = rv["ecio1"]
+ rscp1 = rv["rscp1"]
+ if ecio == nil then
+ ecio = "-"
+ end
+ if ecio1 == nil then
+ ecio1 = "-"
+ end
+ if rscp == nil then
+ rscp = "-"
+ end
+ if rscp1 == nil then
+ rscp1 = "-"
+ end
+
+ if ecio ~= "-" then
+ rv["ecio"] = ecio .. " dB"
+ end
+ if rscp ~= "-" then
+ rv["rscp"] = rscp .. " dBm"
+ end
+ if ecio1 ~= " " then
+ rv["ecio1"] = " (" .. ecio1 .. " dB)"
+ end
+ if rscp1 ~= " " then
+ rv["rscp1"] = " (" .. rscp1 .. " dBm)"
+ end
+
+ rv["mcc"] = file:read("*line")
+ rv["mnc"] = file:read("*line")
+ rv["rnc"] = file:read("*line")
+ rv["rncn"] = file:read("*line")
+ rv["lac"] = file:read("*line")
+ rv["lacn"] = file:read("*line")
+ rv["cid"] = file:read("*line")
+ rv["cidn"] = file:read("*line")
+ rv["lband"] = file:read("*line")
+ rv["channel"] = file:read("*line")
+ rv["pci"] = file:read("*line")
+
+ rv["date"] = file:read("*line")
+
+ -- rv["phonen"] = file:read("*line")
+ --rv["host"] = "0"
+
+ -- rv["simerr"] = "0"
+ --
+ --
+ --
+ --
+ --
+ --
+ --
+ --
+ --
+ --
+
+
+ -- rv["down"] = file:read("*line")
+ -- rv["up"] = file:read("*line")
+ --
+ --
+
+ --
+ -- rv["cell"] = file:read("*line")
+ -- rv["modtype"] = file:read("*line")
+ --
+ --
+ --
+ --
+ --
+ --
+
+
+ -- rv["lat"] = "-"
+ -- rv["long"] = "-"
+
+
+
+ rv["crate"] = translate("快速(每10秒更新一次)")
+ luci.http.prepare_content("application/json")
+ luci.http.write_json(rv)
+end
\ No newline at end of file
diff --git a/luci-app-cpe/luasrc/model/cbi/cpe/modem.lua b/luci-app-cpe/luasrc/model/cbi/cpe/modem.lua
new file mode 100644
index 0000000..376c068
--- /dev/null
+++ b/luci-app-cpe/luasrc/model/cbi/cpe/modem.lua
@@ -0,0 +1,144 @@
+local m, section, m2, s2
+
+m = Map("modem", translate("Mobile Network"))
+m.description = translate("Modem Server For OpenWrt")
+
+
+-------------------------------Fibocom Wireless Inc. FM650 Module----------------------------------
+if (string.gsub(luci.sys.exec('lsusb |grep "ID 2cb7:0a05 " | wc -l'),"%s+","")=="1") then
+ section = m:section(TypedSection, "ndis", translate("FMFM650-CN Settings"), translate("[1]Automatic start upon startup: Check[2] FMFMFM650-CN module default ECM (36) mode. If not, please modify it, otherwise dialing cannot proceed normally"))
+ section.anonymous = true
+ section.addremove = false
+ enable = section:option(Flag, "enabled", translate("Enable"))
+ enable.rmempty = false
+else
+ section = m:section(TypedSection, "ndis", translate("SIM Settings"), translate("Automatic operation upon startup \r\n ooo"))
+ section.anonymous = true
+ section.addremove = false
+ section:tab("general", translate("General Setup"))
+ section:tab("advanced", translate("Advanced Settings"))
+
+
+ enable = section:taboption("general", Flag, "enabled", translate("Enable"))
+ enable.rmempty = false
+
+ device = section:taboption("general",Value, "device", translate("Modem device"))
+ device.rmempty = false
+ local device_suggestions = nixio.fs.glob("/dev/cdc-wdm*")
+ if device_suggestions then
+ local node
+ for node in device_suggestions do
+ device:value(node)
+ end
+ end
+ apn = section:taboption("general", Value, "apn", translate("APN"))
+ username = section:taboption("general", Value, "username", translate("PAP/CHAP Username"))
+ password = section:taboption("general", Value, "password", translate("PAP/CHAP Password"))
+ password.password = true
+ pincode = section:taboption("general", Value, "pincode", translate("PIN Code"))
+ auth = section:taboption("general", Value, "auth", translate("Authentication Type"))
+ auth.rmempty = true
+ auth:value("", translate("-- Please choose --"))
+ auth:value("both", "PAP/CHAP (both)")
+ auth:value("pap", "PAP")
+ auth:value("chap", "CHAP")
+ auth:value("none", "NONE")
+ tool = section:taboption("general", Value, "tool", translate("Tools"))
+ tool:value("quectel-CM", "quectel-CM")
+ tool.rmempty = true
+ PdpType= section:taboption("general", Value, "pdptype", translate("PdpType"))
+ PdpType:value("IPV4", "IPV4")
+ PdpType:value("IPV6", "IPV6")
+ PdpType:value("IPV4V6", "IPV4V6")
+ PdpType.rmempty = true
+
+
+ ---------------------------advanced------------------------------
+ bandlist = section:taboption("advanced", ListValue, "bandlist", translate("Lock Band List"))
+ -- if (string.gsub(luci.sys.exec('uci get system.@system[0].modem |grep lte |wc -l'),"%s+","")=="1") then
+ -- bandlist.default = "0"
+ -- bandlist:value("1", "LTE BAND1")
+ -- bandlist:value("2", "LTE BAND2")
+ -- bandlist:value("3", "LTE BAND3")
+ -- bandlist:value("4", "LTE BAND4")
+ -- bandlist:value("5", "LTE BAND5")
+ -- bandlist:value("7", "LTE BAND7")
+ -- bandlist:value("8", "LTE BAND8")
+ -- bandlist:value("20", "LTE BAND20")
+ -- bandlist:value("38", "LTE BAND38")
+ -- bandlist:value("40", "LTE BAND40")
+ -- bandlist:value("41", "LTE BAND41")
+ -- bandlist:value("28", "LTE BAND28")
+ -- bandlist:value("A", "AUTO")
+ -- end
+ bandlist:value("0", translate("Disable"))
+
+ servertype = section:taboption("advanced", ListValue, "servertype", translate("Server Type"))
+ servertype.default = "0"
+
+ --if (string.gsub(luci.sys.exec('uci get system.@system[0].modem |grep nr5g |wc -l'),"%s+","")=="1") then
+ servertype:value("1", "5G Only")
+ servertype:value("5", "4G/5G Only")
+ --end
+ servertype:value("2", "4G Only")
+ servertype:value("3", "3G Only")
+ servertype:value("4", "2G Only")
+ servertype:value("0", "AUTO")
+
+
+ -- s1 = m:section(TypedSection, "ndis", translate("AT Port Settings"),translate("Set tyyUSB port"))
+ -- s1.anonymous = true
+ -- s1.addremove = false
+ -- tyyusb= s1:option(Value, "tyyusb", translate("tyyUSB port"))
+ -- tyyusb.default = "2"
+ -- tyyusb:value("0", "0")
+ -- tyyusb:value("1", "1")
+ -- tyyusb:value("2", "2")
+ -- tyyusb:value("3", "3")
+ -- tyyusb:value("4", "4")
+ -- tyyusb.rmempty=false
+end
+
+
+
+
+
+
+
+
+
+s2 = m:section(TypedSection, "ndis", translate("Network Diagnostics"),translate("Network exception handling: \
+check the network connection in a loop for 5 seconds. If the Ping IP address is not successful, After the network \
+exceeds the abnormal number, restart and search the registered network again."))
+s2.anonymous = true
+s2.addremove = false
+
+en = s2:option(Flag, "en", translate("Enable"))
+en.rmempty = false
+
+
+
+ipaddress= s2:option(Value, "ipaddress", translate("Ping IP address"))
+ipaddress.default = "114.114.114.114"
+ipaddress.rmempty=false
+
+an = s2:option(Value, "an", translate("Abnormal number"))
+an.default = "15"
+an:value("3", "3")
+an:value("5", "5")
+an:value("10", "10")
+an:value("15", "15")
+an:value("20", "20")
+an:value("25", "25")
+an:value("30", "30")
+an.rmempty=false
+
+
+
+local apply = luci.http.formvalue("cbi.apply")
+if apply then
+ -- io.popen("/etc/init.d/modeminit restart")
+ io.popen("/etc/init.d/modem restart")
+end
+
+return m,m2
diff --git a/luci-app-cpe/luasrc/view/cpe/at.htm b/luci-app-cpe/luasrc/view/cpe/at.htm
new file mode 100644
index 0000000..1c9a8a7
--- /dev/null
+++ b/luci-app-cpe/luasrc/view/cpe/at.htm
@@ -0,0 +1,152 @@
+<%+header%>
+<%
+local sys = require "luci.sys"
+local utl = require "luci.util"
+local fs = require "nixio.fs"
+local uci = require "luci.model.uci".cursor()
+local s = uci:get("custom", "bandlock", "enabled")
+local a = uci:get("custom", "atcmd", "enabled")
+
+local multilock = uci:get("custom", "multiuser", "multi") or "0"
+local rootlock = uci:get("custom", "multiuser", "root") or "0"
+nomulti=1
+if (multilock == "0") or (multilock == "1" and rootlock == "1") then
+ nosms = 1
+ if a == "1" then
+ nosms = 0
+ end
+else
+ nosms = 1
+ nomulti = 0
+end
+block = 1
+if s == "1" then
+ block = 0
+end
+
+function showicon(lck)
+end
+
+-%>
+
+
+
+
+
+
+
<%:AT命令工具%>
+
+
+
+
+
+
+
+
+
+<%+footer%>
diff --git a/luci-app-cpe/luasrc/view/cpe/net_status.htm b/luci-app-cpe/luasrc/view/cpe/net_status.htm
new file mode 100644
index 0000000..96c569e
--- /dev/null
+++ b/luci-app-cpe/luasrc/view/cpe/net_status.htm
@@ -0,0 +1,296 @@
+<%+header%>
+<%
+local fs = require "nixio.fs"
+nosms = 1
+if not fs.stat("/etc/nosim") then
+ nosms = 0
+end
+havegps = 0
+if fs.stat("/etc/havegps") then
+ havegps = 1
+end
+-%>
+
+
+
+
+
+
+
+
请注意该插件所有功能并无适配所有5G模块,不用妄想冷门模块插上就能用(有能力者自行适配)
+
+
+
+
+
+
+
+<% if nosms == 0 then %>
+<% end %>
+
+
+
+
+
+
+
+
+
+<% if havegps == 1 then %>
+
+<% end %>
+
+
+
+<%+footer%>
+
diff --git a/luci-app-cpe/po/zh-cn/modem.po b/luci-app-cpe/po/zh-cn/modem.po
new file mode 100644
index 0000000..25681b8
--- /dev/null
+++ b/luci-app-cpe/po/zh-cn/modem.po
@@ -0,0 +1,73 @@
+msgid ""
+msgstr ""
+
+msgid "Mobile Network"
+msgstr "模块设置"
+
+
+msgid "Automatic operation upon startup ooo"
+msgstr "开机自动启动:勾选"
+
+msgid "Tools"
+msgstr "拨号工具"
+
+msgid "PAP/CHAP Username"
+msgstr "PAP/CHAP 用户"
+
+msgid "PAP/CHAP Password"
+msgstr "PAP/CHAP 密码"
+
+
+msgid "Modem Server For OpenWrt"
+msgstr "4G/5G模块管理"
+
+
+msgid "SIM Settings"
+msgstr "SIM 配置 (联通ANP:3gnet) (电信APN:ctnet) (移动APN:cmnet) (广电APN:cbnet) "
+
+msgid "PdpType"
+msgstr "IP获取方式"
+
+msgid "AT Port Settings"
+msgstr "AT 模块配置"
+
+msgid "Set tyyUSB port"
+msgstr "AT 模块端口配置 (全模块指定端口)"
+
+msgid "tyyUSB port"
+msgstr "ttyUSB 配置ID"
+
+msgid "Network Diagnostics"
+msgstr "网络诊断"
+
+
+msgid "Network Diagnostics"
+msgstr "网络诊断"
+
+
+msgid "Network exception handling: check the network connection in a loop for 5 seconds. If the Ping IP address is not successful, After the network exceeds the abnormal number, restart and search the registered network again."
+msgstr "网络异常处理:循环检查网络连接5秒。如果Ping IP地址不成功,则在网络超过异常数量后,重新启动并搜索已注册的网络。"
+
+msgid "Ping IP address"
+msgstr "Ping IP地址"
+
+msgid "Abnormal number"
+msgstr "异常次数"
+
+msgid "Lock Band List"
+msgstr "锁定频段列表"
+
+msgid "Server Type"
+msgstr "服务类型"
+
+msgid "FMFM650-CN Settings"
+msgstr "FMFM650-CN 设置"
+
+msgid "[1]Automatic start upon startup: Check[2] FMFMFM650-CN module default ECM (36) mode. If not, please modify it, otherwise dialing cannot proceed normally"
+msgstr "【1】 开机自动启动:勾选 【2】 FMFM650-CN 模块默认 ECM (36)模式如果不是请修改 否则不能正常进行拨号 "
+
+
+
+
+
+
diff --git a/luci-app-cpe/po/zh_Hans b/luci-app-cpe/po/zh_Hans
new file mode 100644
index 0000000..41451e4
--- /dev/null
+++ b/luci-app-cpe/po/zh_Hans
@@ -0,0 +1 @@
+zh-cn
\ No newline at end of file
diff --git a/luci-app-cpe/root/etc/config/modem b/luci-app-cpe/root/etc/config/modem
new file mode 100644
index 0000000..3b57bd5
--- /dev/null
+++ b/luci-app-cpe/root/etc/config/modem
@@ -0,0 +1,12 @@
+config ndis
+ option enabled '0'
+ option bandlist '0'
+ option servertype '0'
+ option ipaddress '114.114.114.114'
+ option en '0'
+ option an '5'
+ option model 'nr5g'
+ option tyyusb '2'
+ option tool 'quectel-CM'
+ option device '/dev/cdc-wdm0'
+ option pdptype 'IPV4V6'
diff --git a/luci-app-cpe/root/etc/init.d/cpeinit b/luci-app-cpe/root/etc/init.d/cpeinit
new file mode 100644
index 0000000..c5f2299
--- /dev/null
+++ b/luci-app-cpe/root/etc/init.d/cpeinit
@@ -0,0 +1,7 @@
+#!/bin/sh /etc/rc.common
+
+START=99
+
+start() {
+ /bin/sh /usr/share/cpe/rssi &
+}
\ No newline at end of file
diff --git a/luci-app-cpe/root/etc/init.d/modem b/luci-app-cpe/root/etc/init.d/modem
new file mode 100644
index 0000000..03c4507
--- /dev/null
+++ b/luci-app-cpe/root/etc/init.d/modem
@@ -0,0 +1,103 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006-2014 OpenWrt.org
+
+START=16
+STOP=16
+USE_PROCD=1
+#ʹprocd
+
+
+# start
+# stopֹͣ
+# restart
+# reload¼ļδʵ¼أ
+# enable÷Զ
+# disable÷Զ
+# enabledǷʱ
+# мǷ
+# status״̬
+# traceϵͳøٿʼ
+
+runModem()
+{
+ local enabled
+ config_get_bool enabled $1 enabled
+ echo "run runModem" >> /tmp/log4g
+ if [ "$enabled" = "1" ]; then
+
+
+ local user
+ local password
+ local apn
+ local auth
+ local pincode
+ local device
+ local tool
+ local pdptype
+
+
+ config_get user $1 user
+ config_get password $1 password
+ config_get apn $1 apn
+ config_get auth $1 auth
+ config_get pincode $1 pincode
+ config_get device $1 device
+ config_get tool $1 tool
+ config_get pdptype $1 pdptype
+ config_get tty $1 tty
+ config_get atcmd $1 atcmd
+
+ if [ "$pdptype" = "IPV4V6" ]; then
+ pdptype='-4 -6'
+ elif [ "$pdptype" = "IPV6" ]; then
+ pdptype='-6'
+ else
+ pdptype=''
+ fi
+
+ devname="$(basename "$device")"
+ devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)"
+ ifname="$( ls "$devpath"/net )"
+
+
+ procd_open_instance
+ #һʵ procdһӦóԶʵ\E4\BE?
+ #ubus call service list Բ鿴ʵ
+ procd_set_param command $tool -i $ifname -s $apn $pdptype
+ if [ "$password" != "" ];then
+ procd_append_param command $user $password $auth
+ fi
+ if [ "$pincode" != "" ]; then
+ procd_append_param command -p $pincode
+ fi
+ # procd_append_param command -f /tmp/4g.log
+ procd_set_param respawn
+ echo "quectel-CM has started."
+ procd_close_instance
+ #رʵ
+ fi
+
+
+
+}
+
+
+
+
+service_triggers()
+{
+ procd_add_reload_trigger "modem"
+}
+
+start_service() {
+ config_load modem
+ config_foreach runModem ndis
+}
+
+stop_service()
+{
+ echo "runModem stop" >> /tmp/log4g
+ killall quectel-CM
+ echo "quectel-CM has stoped."
+}
+
diff --git a/luci-app-cpe/root/etc/uci-defaults/luci-modem b/luci-app-cpe/root/etc/uci-defaults/luci-modem
new file mode 100644
index 0000000..3181024
--- /dev/null
+++ b/luci-app-cpe/root/etc/uci-defaults/luci-modem
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+uci -q batch <<-EOF >/dev/null
+ delete ucitrack.@modem[-1]
+ add ucitrack modem
+ set ucitrack.@modem[-1].init=modem
+ commit ucitrack
+EOF
+
+rm -f /tmp/luci-indexcache
+exit 0
diff --git a/luci-app-cpe/root/usr/bin/bmask128 b/luci-app-cpe/root/usr/bin/bmask128
new file mode 100644
index 0000000..bfd5bde
--- /dev/null
+++ b/luci-app-cpe/root/usr/bin/bmask128
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+printf "Band 128-bit bandmask\n"
+LBAND=1
+BBAND=1
+while [ $LBAND -le 48 ]
+do
+ printf "%-6s%016X%016X\n" "$LBAND" "0" "$BBAND"
+ LBAND=$(( $LBAND + 1 ))
+ BBAND=$(( $BBAND * 2 ))
+done
+LBAND=65
+BBAND=1
+while [ $LBAND -le 85 ]
+do
+ printf "%-6s%016X%016X\n" "$LBAND" "$BBAND" "0"
+ LBAND=$(( $LBAND + 1 ))
+ BBAND=$(( $BBAND * 2 ))
+done
diff --git a/luci-app-cpe/root/usr/bin/chan2band.sh b/luci-app-cpe/root/usr/bin/chan2band.sh
new file mode 100644
index 0000000..5b5bff0
--- /dev/null
+++ b/luci-app-cpe/root/usr/bin/chan2band.sh
@@ -0,0 +1,317 @@
+#!/bin/sh
+CHAN=$1
+CHAN=$(echo "$CHAN" | grep -o "[0-9]*")
+
+decode_lte() {
+ if [ $CHAN -lt 600 ]; then
+ BAND="B1"
+ elif [ $CHAN -lt 1200 ]; then
+ BAND="B2"
+ elif [ $CHAN -lt 1950 ]; then
+ BAND="B3"
+ elif [ $CHAN -lt 2400 ]; then
+ BAND="B4"
+ elif [ $CHAN -lt 2650 ]; then
+ BAND="B5"
+ elif [ $CHAN -lt 2750 ]; then
+ BAND="B6"
+ elif [ $CHAN -lt 3450 ]; then
+ BAND="B7"
+ elif [ $CHAN -lt 3800 ]; then
+ BAND="B8"
+ elif [ $CHAN -lt 4150 ]; then
+ BAND="B9"
+ elif [ $CHAN -lt 4750 ]; then
+ BAND="B10"
+ elif [ $CHAN -lt 4950 ]; then
+ BAND="B11"
+ elif [ $CHAN -lt 5010 ]; then
+ BAND="-"
+ elif [ $CHAN -lt 5180 ]; then
+ BAND="B12"
+ elif [ $CHAN -lt 5280 ]; then
+ BAND="B13"
+ elif [ $CHAN -lt 5380 ]; then
+ BAND="B14"
+ elif [ $CHAN -lt 5730 ]; then
+ BAND="-"
+ elif [ $CHAN -lt 5850 ]; then
+ BAND="B17"
+ elif [ $CHAN -lt 6000 ]; then
+ BAND="B18"
+ elif [ $CHAN -lt 6150 ]; then
+ BAND="B19"
+ elif [ $CHAN -lt 6450 ]; then
+ BAND="B20"
+ elif [ $CHAN -lt 6600 ]; then
+ BAND="B21"
+ elif [ $CHAN -lt 7400 ]; then
+ BAND="B22"
+ elif [ $CHAN -lt 7500 ]; then
+ BAND="-"
+ elif [ $CHAN -lt 7700 ]; then
+ BAND="B23"
+ elif [ $CHAN -lt 8040 ]; then
+ BAND="B24"
+ elif [ $CHAN -lt 8690 ]; then
+ BAND="B25"
+ elif [ $CHAN -lt 9040 ]; then
+ BAND="B26"
+ elif [ $CHAN -lt 9210 ]; then
+ BAND="B27"
+ elif [ $CHAN -lt 9660 ]; then
+ BAND="B28"
+ elif [ $CHAN -lt 9770 ]; then
+ BAND="B29"
+ elif [ $CHAN -lt 9870 ]; then
+ BAND="B30"
+ elif [ $CHAN -lt 9920 ]; then
+ BAND="B31"
+ elif [ $CHAN -lt 10400 ]; then
+ BAND="B32"
+ elif [ $CHAN -lt 36000 ]; then
+ BAND="-"
+ elif [ $CHAN -lt 36200 ]; then
+ BAND="B33"
+ elif [ $CHAN -lt 36350 ]; then
+ BAND="B34"
+ elif [ $CHAN -lt 36950 ]; then
+ BAND="B35"
+ elif [ $CHAN -lt 37550 ]; then
+ BAND="B36"
+ elif [ $CHAN -lt 37750 ]; then
+ BAND="B37"
+ elif [ $CHAN -lt 38250 ]; then
+ BAND="B38"
+ elif [ $CHAN -lt 38650 ]; then
+ BAND="B39"
+ elif [ $CHAN -lt 39650 ]; then
+ BAND="B40"
+ elif [ $CHAN -lt 41590 ]; then
+ BAND="B41"
+ elif [ $CHAN -lt 43590 ]; then
+ BAND="B42"
+ elif [ $CHAN -lt 45590 ]; then
+ BAND="B43"
+ elif [ $CHAN -lt 46590 ]; then
+ BAND="B44"
+ elif [ $CHAN -lt 46790 ]; then
+ BAND="B45"
+ elif [ $CHAN -lt 54540 ]; then
+ BAND="B46"
+ elif [ $CHAN -lt 55240 ]; then
+ BAND="B47"
+ elif [ $CHAN -lt 56740 ]; then
+ BAND="B48"
+ elif [ $CHAN -lt 58240 ]; then
+ BAND="B49"
+ elif [ $CHAN -lt 59090 ]; then
+ BAND="B50"
+ elif [ $CHAN -lt 59140 ]; then
+ BAND="B51"
+ elif [ $CHAN -lt 60140 ]; then
+ BAND="B52"
+ elif [ $CHAN -lt 60255 ]; then
+ BAND="B53"
+ elif [ $CHAN -lt 65536 ]; then
+ BAND="-"
+ elif [ $CHAN -lt 66436 ]; then
+ BAND="B65"
+ elif [ $CHAN -lt 67336 ]; then
+ BAND="B66"
+ elif [ $CHAN -lt 67536 ]; then
+ BAND="B67"
+ elif [ $CHAN -lt 67836 ]; then
+ BAND="B68"
+ elif [ $CHAN -lt 68336 ]; then
+ BAND="B69"
+ elif [ $CHAN -lt 68586 ]; then
+ BAND="B70"
+ elif [ $CHAN -lt 68936 ]; then
+ BAND="B71"
+ elif [ $CHAN -lt 68986 ]; then
+ BAND="B72"
+ elif [ $CHAN -lt 69036 ]; then
+ BAND="B73"
+ elif [ $CHAN -lt 69466 ]; then
+ BAND="B74"
+ elif [ $CHAN -lt 70316 ]; then
+ BAND="B75"
+ elif [ $CHAN -lt 70366 ]; then
+ BAND="B76"
+ elif [ $CHAN -lt 70546 ]; then
+ BAND="B85"
+ elif [ $CHAN -lt 70596 ]; then
+ BAND="B87"
+ elif [ $CHAN -lt 70646 ]; then
+ BAND="B88"
+ else
+ BAND="-"
+ fi
+}
+
+decode_nr5g() {
+ if [ $CHAN -lt 123400 ]; then
+ BAND="-"
+ elif [ $CHAN -le 130400 ]; then
+ BAND="n71"
+ elif [ $CHAN -lt 143400 ]; then
+ BAND="-"
+ elif [ $CHAN -lt 145600 ]; then
+ BAND="n29"
+ elif [ $CHAN -eq 145600 ]; then
+ BAND="n29|n85"
+ elif [ $CHAN -lt 145800 ]; then
+ BAND="n85"
+ elif [ $CHAN -eq 145800 ]; then
+ BAND="n12|n85"
+ elif [ $CHAN -lt 147600 ]; then
+ BAND="n12|n85"
+ elif [ $CHAN -lt 149200 ]; then
+ BAND="n12|n67|n85"
+ elif [ $CHAN -eq 149200 ]; then
+ BAND="n12|n13|n67|n85"
+ elif [ $CHAN -le 151200 ]; then
+ BAND="n13|n67"
+ elif [ $CHAN -lt 151600 ]; then
+ BAND="n67"
+ elif [ $CHAN -eq 151600 ]; then
+ BAND="n14|n28|n67"
+ elif [ $CHAN -le 153600 ]; then
+ BAND="n14|n28"
+ elif [ $CHAN -lt 158200 ]; then
+ BAND="n28"
+ elif [ $CHAN -eq 158200 ]; then
+ BAND="n14|n20|n28"
+ elif [ $CHAN -le 160600 ]; then
+ BAND="n20|n28"
+ elif [ $CHAN -le 164200 ]; then
+ BAND="n20"
+ elif [ $CHAN -lt 171800 ]; then
+ BAND="-"
+ elif [ $CHAN -lt 172000 ]; then
+ BAND="n26"
+ elif [ $CHAN -lt 173800 ]; then
+ BAND="n18|n26"
+ elif [ $CHAN -le 175000 ]; then
+ BAND="n5|n18|n26"
+ elif [ $CHAN -le 178800 ]; then
+ BAND="n5|n26"
+ elif [ $CHAN -lt 185000 ]; then
+ BAND="-"
+ elif [ $CHAN -le 192000 ]; then
+ BAND="n8"
+ elif [ $CHAN -lt 285400 ]; then
+ BAND="-"
+ elif [ $CHAN -lt 286400 ]; then
+ BAND="n51|n76|n91|n93"
+ elif [ $CHAN -eq 286400 ]; then
+ BAND="n50|n51|n75|n76|n91|92|n93|94"
+ elif [ $CHAN -lt 295000 ]; then
+ BAND="n50|n75|n92|n94"
+ elif [ $CHAN -eq 295000 ]; then
+ BAND="n50|n74|n75|n92|n94"
+ elif [ $CHAN -le 303400 ]; then
+ BAND="n50|n74|n75|n92|n94"
+ elif [ $CHAN -le 303600 ]; then
+ BAND="n74"
+ elif [ $CHAN -lt 305000 ]; then
+ BAND="-"
+ elif [ $CHAN -le 311800 ]; then
+ BAND="n24"
+ elif [ $CHAN -lt 361000 ]; then
+ BAND="-"
+ elif [ $CHAN -lt 376000 ]; then
+ BAND="n3"
+ elif [ $CHAN -eq 376000 ]; then
+ BAND="n3|n39"
+ elif [ $CHAN -le 384000 ]; then
+ BAND="n39"
+ elif [ $CHAN -lt 386000 ]; then
+ BAND="-"
+ elif [ $CHAN -le 398000 ]; then
+ BAND="n2|n25"
+ elif [ $CHAN -lt 399000 ]; then
+ BAND="n25"
+ elif [ $CHAN -eq 399000 ]; then
+ BAND="n25|n70"
+ elif [ $CHAN -lt 402000 ]; then
+ BAND="n70"
+ elif [ $CHAN -eq 402000 ]; then
+ BAND="n34|n70"
+ elif [ $CHAN -le 404000 ]; then
+ BAND="n34|n70"
+ elif [ $CHAN -le 405000 ]; then
+ BAND="n34"
+ elif [ $CHAN -lt 422000 ]; then
+ BAND="-"
+ elif [ $CHAN -le 434000 ]; then
+ BAND="n1|n65|n66"
+ elif [ $CHAN -le 440000 ]; then
+ BAND="n65|n66"
+ elif [ $CHAN -lt 460000 ]; then
+ BAND="-"
+ elif [ $CHAN -lt 470000 ]; then
+ BAND="n40"
+ elif [ $CHAN -eq 470000 ]; then
+ BAND="n30|n40"
+ elif [ $CHAN -le 472000 ]; then
+ BAND="n30|n40"
+ elif [ $CHAN -le 480000 ]; then
+ BAND="n40"
+ elif [ $CHAN -lt 496700 ]; then
+ BAND="-"
+ elif [ $CHAN -le 499000 ]; then
+ BAND="n53"
+ elif [ $CHAN -lt 499200 ]; then
+ BAND="-"
+ elif [ $CHAN -lt 514000 ]; then
+ BAND="n41|n90"
+ elif [ $CHAN -eq 514000 ]; then
+ BAND="n38|n41|n90"
+ elif [ $CHAN -lt 524000 ]; then
+ BAND="n38|n41|n90"
+ elif [ $CHAN -eq 524000 ]; then
+ BAND="n7|n38|n41|n90"
+ elif [ $CHAN -lt 538000 ]; then
+ BAND="n7|n41|n90"
+ elif [ $CHAN -eq 538000 ]; then
+ BAND="n7|n90"
+ elif [ $CHAN -lt 620000 ]; then
+ BAND="-"
+ elif [ $CHAN -lt 636667 ]; then
+ BAND="n77|n78"
+ elif [ $CHAN -le 646666 ]; then
+ BAND="n48|n77|n78"
+ elif [ $CHAN -le 653333 ]; then
+ BAND="n77|n78"
+ elif [ $CHAN -le 680000 ]; then
+ BAND="n77"
+ elif [ $CHAN -lt 693334 ]; then
+ BAND="-"
+ elif [ $CHAN -le 733333 ]; then
+ BAND="n79"
+ elif [ $CHAN -lt 743333 ]; then
+ BAND="-"
+ elif [ $CHAN -lt 795000 ]; then
+ BAND="n46"
+ elif [ $CHAN -eq 795000 ]; then
+ BAND="n46|n96"
+ elif [ $CHAN -le 875000 ]; then
+ BAND="n96"
+ else
+ BAND="-"
+ fi
+}
+
+if [ -z "$CHAN" ]; then
+ BAND="-"
+elif [ "$CHAN" -lt 123400 ]; then
+ decode_lte
+elif [ "$CHAN" -le 875000 ]; then
+ decode_nr5g
+else
+ BAND="-"
+fi
+echo $BAND
+exit
diff --git a/luci-app-cpe/root/usr/bin/encodemask b/luci-app-cpe/root/usr/bin/encodemask
new file mode 100644
index 0000000..6b3ed14
--- /dev/null
+++ b/luci-app-cpe/root/usr/bin/encodemask
@@ -0,0 +1,24 @@
+#!/usr/bin/lua
+
+mtab = {}
+vtab = {1, 2, 4, 8}
+
+for i = 1, 32 do
+ mtab[i] = 0
+end
+
+numarg = #arg
+for argval = 1, numarg do
+ band = arg[argval]
+ if tonumber(band) <= 128 then
+ idx = math.floor((band - 1) / 4) + 1
+ idxr = 33 - idx
+ val = vtab[(band - ((idx - 1) * 4 ))]
+ mtab[idxr] = mtab[idxr] + val
+ end
+end
+for i = 1, 32 do
+ mtab[i] = string.format("%X", mtab[i])
+end
+
+print(table.concat(mtab))
diff --git a/luci-app-cpe/root/usr/bin/jkillall b/luci-app-cpe/root/usr/bin/jkillall
new file mode 100644
index 0000000..3802082
--- /dev/null
+++ b/luci-app-cpe/root/usr/bin/jkillall
@@ -0,0 +1,9 @@
+#!/bin/sh
+LOOKFOR=$1
+KILLLIST=$(ps | grep $LOOKFOR)
+echo "$KILLLIST" | while read line; do
+ if `echo "$line" | grep "/$LOOKFOR" > /dev/null` ; then
+ PIDV=$(echo $line | grep -o "^[0-9]\{1,5\}" | grep -o "[0-9]\{1,5\}")
+ kill $PIDV
+ fi
+done
\ No newline at end of file
diff --git a/luci-app-cpe/root/usr/bin/rsrp2rssi b/luci-app-cpe/root/usr/bin/rsrp2rssi
new file mode 100644
index 0000000..06ad5b6
--- /dev/null
+++ b/luci-app-cpe/root/usr/bin/rsrp2rssi
@@ -0,0 +1,21 @@
+#!/usr/bin/lua
+
+rsrp = tonumber(arg[1])
+bw = tonumber(arg[2])
+if bw == 1.4 then
+ n = 6
+else
+ n = bw * 5
+end
+
+if tonumber(string.match(_VERSION, "%d+%.%d")) > 5.1 then
+ rssi = rsrp + (10 * math.log(n * 12, 10))
+else
+ rssi = rsrp + (10 * math.log10(n * 12))
+end
+if rssi < -113 then
+ rssi = -113
+elseif rssi > -51 then
+ rssi = -51
+end
+print(math.floor(rssi))
diff --git a/luci-app-cpe/root/usr/bin/set_gpio b/luci-app-cpe/root/usr/bin/set_gpio
new file mode 100644
index 0000000..5fddfa7
--- /dev/null
+++ b/luci-app-cpe/root/usr/bin/set_gpio
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+PIN=$1
+VALUE=$2
+
+PIN_FILE=/sys/class/gpio/gpio$PIN
+
+if [ -z "$PIN" -o -z "$VALUE" ]; then
+ exit 1
+fi
+
+echo $PIN >/sys/class/gpio/export
+
+if [ $(cat $PIN_FILE/direction) = "out" ]; then
+ echo $VALUE >$PIN_FILE/value
+fi
+
+echo $PIN >/sys/class/gpio/unexport
\ No newline at end of file
diff --git a/luci-app-cpe/root/usr/share/cpe/Fibocom b/luci-app-cpe/root/usr/share/cpe/Fibocom
new file mode 100644
index 0000000..72bfe02
--- /dev/null
+++ b/luci-app-cpe/root/usr/share/cpe/Fibocom
@@ -0,0 +1,285 @@
+#!/bin/sh
+ATPORT=1
+
+
+
+# SIMCOM获取基站信息
+Fibocom_Cellinfo()
+{
+ #baseinfo.gcom
+ OX=$( sendat $ATPORT "ATI")
+ OX=$( sendat $ATPORT "AT+CGEQNEG=1")
+
+ #cellinfo0.gcom
+ OX1=$( sendat $ATPORT "AT+COPS=3,0;+COPS?")
+ OX2=$( sendat $ATPORT "AT+COPS=3,2;+COPS?")
+ OX=$OX1" "$OX2
+
+ #cellinfo.gcom
+ OY1=$( sendat $ATPORT "AT+CREG=2;+CREG?;+CREG=0")
+ OY2=$( sendat $ATPORT "AT+CEREG=2;+CEREG?;+CEREG=0")
+ OY3=$( sendat $ATPORT "AT+C5GREG=2;+C5GREG?;+C5GREG=0")
+ OY=$OY1" "$OY2" "$OY3
+
+
+ OXx=$OX
+ OX=$(echo $OX | tr 'a-z' 'A-Z')
+ OY=$(echo $OY | tr 'a-z' 'A-Z')
+ OX=$OX" "$OY
+
+ #Debug "$OX"
+ #Debug "$OY"
+
+ COPS="-"
+ COPS_MCC="-"
+ COPS_MNC="-"
+ COPSX=$(echo $OXx | grep -o "+COPS: [01],0,.\+," | cut -d, -f3 | grep -o "[^\"]\+")
+
+ if [ "x$COPSX" != "x" ]; then
+ COPS=$COPSX
+ fi
+
+ COPSX=$(echo $OX | grep -o "+COPS: [01],2,.\+," | cut -d, -f3 | grep -o "[^\"]\+")
+
+ if [ "x$COPSX" != "x" ]; then
+ COPS_MCC=${COPSX:0:3}
+ COPS_MNC=${COPSX:3:3}
+ if [ "$COPS" = "-" ]; then
+ COPS=$(awk -F[\;] '/'$COPS'/ {print $2}' $ROOTER/signal/mccmnc.data)
+ [ "x$COPS" = "x" ] && COPS="-"
+ fi
+ fi
+
+ if [ "$COPS" = "-" ]; then
+ COPS=$(echo "$O" | awk -F[\"] '/^\+COPS: 0,0/ {print $2}')
+ if [ "x$COPS" = "x" ]; then
+ COPS="-"
+ COPS_MCC="-"
+ COPS_MNC="-"
+ fi
+ fi
+ COPS_MNC=" "$COPS_MNC
+
+ OX=$(echo "${OX//[ \"]/}")
+ CID=""
+ CID5=""
+ RAT=""
+ REGV=$(echo "$OX" | grep -o "+C5GREG:2,[0-9],[A-F0-9]\{2,6\},[A-F0-9]\{5,10\},[0-9]\{1,2\}")
+ if [ -n "$REGV" ]; then
+ LAC5=$(echo "$REGV" | cut -d, -f3)
+ LAC5=$LAC5" ($(printf "%d" 0x$LAC5))"
+ CID5=$(echo "$REGV" | cut -d, -f4)
+ CID5L=$(printf "%010X" 0x$CID5)
+ RNC5=${CID5L:1:6}
+ RNC5=$RNC5" ($(printf "%d" 0x$RNC5))"
+ CID5=${CID5L:7:3}
+ CID5="Short $(printf "%X" 0x$CID5) ($(printf "%d" 0x$CID5)), Long $(printf "%X" 0x$CID5L) ($(printf "%d" 0x$CID5L))"
+ RAT=$(echo "$REGV" | cut -d, -f5)
+ fi
+ REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{5,8\}")
+ REGFMT="3GPP"
+ if [ -z "$REGV" ]; then
+ REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{1,3\},[A-F0-9]\{5,8\}")
+ REGFMT="SW"
+ fi
+ if [ -n "$REGV" ]; then
+ LAC=$(echo "$REGV" | cut -d, -f3)
+ LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))"
+ if [ $REGFMT = "3GPP" ]; then
+ CID=$(echo "$REGV" | cut -d, -f4)
+ else
+ CID=$(echo "$REGV" | cut -d, -f5)
+ fi
+ CIDL=$(printf "%08X" 0x$CID)
+ RNC=${CIDL:1:5}
+ RNC=$RNC" ($(printf "%d" 0x$RNC))"
+ CID=${CIDL:6:2}
+ CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))"
+
+ else
+ REGV=$(echo "$OX" | grep -o "+CREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{2,8\}")
+ if [ -n "$REGV" ]; then
+ LAC=$(echo "$REGV" | cut -d, -f3)
+ CID=$(echo "$REGV" | cut -d, -f4)
+ if [ ${#CID} -gt 4 ]; then
+ LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))"
+ CIDL=$(printf "%08X" 0x$CID)
+ RNC=${CIDL:1:3}
+ CID=${CIDL:4:4}
+ CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))"
+ else
+ LAC=""
+ fi
+ else
+ LAC=""
+ fi
+ fi
+ REGSTAT=$(echo "$REGV" | cut -d, -f2)
+ if [ "$REGSTAT" == "5" -a "$COPS" != "-" ]; then
+ COPS_MNC=$COPS_MNC" (Roaming)"
+ fi
+ if [ -n "$CID" -a -n "$CID5" ] && [ "$RAT" == "13" -o "$RAT" == "10" ]; then
+ LAC="4G $LAC, 5G $LAC5"
+ CID="4G $CID
5G $CID5"
+ RNC="4G $RNC, 5G $RNC5"
+ elif [ -n "$CID5" ]; then
+ LAC=$LAC5
+ CID=$CID5
+ RNC=$RNC5
+ fi
+ if [ -z "$LAC" ]; then
+ LAC="-"
+ CID="-"
+ RNC="-"
+ fi
+}
+Fibocom_SIMINFO()
+{
+ Debug "Fibocom_SIMINFO"
+ # 获取IMEI
+ IMEI=$( sendat $ATPORT "AT+CGSN" | sed -n '2p' )
+ # 获取IMSI
+ IMSI=$( sendat $ATPORT "AT+CIMI" | sed -n '2p' )
+ # 获取ICCID
+ ICCID=$( sendat $ATPORT "AT+ICCID" | grep -o "+ICCID:[ ]*[-0-9]\+" | grep -o "[-0-9]\{1,4\}" )
+ # 获取电话号码
+ phone=$( sendat $ATPORT "AT+CNUM" | grep "+CNUM:" )
+}
+
+#SIMCOM查找基站AT
+Fibocom_AT()
+{
+ Debug "Fibocom_AT"
+ ATPORT
+ All_CSQ
+ Fibocom_SIMINFO
+ Fibocom_Cellinfo
+
+ #温度
+ OX=$( sendat $ATPORT "AT+CPMUTEMP")
+ TEMP=$(echo "$OX" | grep -o "+CPMUTEMP:[ ]*[-0-9]\+" | grep -o "[-0-9]\{1,4\}")
+ if [ -n "$TEMP" ]; then
+ TEMP=$(echo $TEMP)$(printf "\xc2\xb0")"C"
+ fi
+
+
+ #基站信息
+ OX=$( sendat $ATPORT "AT+CPSI?")
+ rec=$(echo "$OX" | grep "+CPSI:")
+ w=$(echo $rec |grep "NO SERVICE"| wc -l)
+ if [ $w -ge 1 ];then
+ Debug "NO SERVICE"
+ return
+ fi
+ w=$(echo $rec |grep "NR5G_"| wc -l)
+ if [ $w -ge 1 ];then
+
+ w=$(echo $rec |grep "32768"| wc -l)
+ if [ $w -ge 1 ];then
+ Debug "-32768"
+ return
+ fi
+
+ Debug "$rec"
+ rec1=${rec##*+CPSI:}
+ #echo "$rec1"
+ MODE="${rec1%%,*}" # MODE="NR5G"
+ rect1=${rec1#*,}
+ rect1s="${rect1%%,*}" #Online
+ rect2=${rect1#*,}
+ rect2s="${rect2%%,*}" #460-11
+ rect3=${rect2#*,}
+ rect3s="${rect3%%,*}" #0xCFA102
+ rect4=${rect3#*,}
+ rect4s="${rect4%%,*}" #55744245764
+ rect5=${rect4#*,}
+ rect5s="${rect5%%,*}" #196
+ rect6=${rect5#*,}
+ rect6s="${rect6%%,*}" #NR5G_BAND78
+ rect7=${rect6#*,}
+ rect7s="${rect7%%,*}" #627264
+ rect8=${rect7#*,}
+ rect8s="${rect8%%,*}" #-940
+ rect9=${rect8#*,}
+ rect9s="${rect9%%,*}" #-110
+ # "${rec1##*,}" #最后一位
+ rect10=${rect9#*,}
+ rect10s="${rect10%%,*}" #最后一位
+ PCI=$rect5s
+ LBAND="n"$(echo $rect6s | cut -d, -f0 | grep -o "BAND[0-9]\{1,3\}" | grep -o "[0-9]\+")
+ CHANNEL=$rect7s
+ RSCP=$(($(echo $rect8s | cut -d, -f0) / 10))
+ ECIO=$(($(echo $rect9s | cut -d, -f0) / 10))
+ if [ "$CSQ_PER" = "-" ]; then
+ CSQ_PER=$((100 - (($RSCP + 31) * 100/-125)))"%"
+ fi
+ SINR=$(($(echo $rect10s | cut -d, -f0) / 10))" dB"
+ fi
+ w=$(echo $rec |grep "LTE"|grep "EUTRAN"| wc -l)
+ if [ $w -ge 1 ];then
+ rec1=${rec#*EUTRAN-}
+ lte_band=${rec1%%,*} #EUTRAN-BAND
+ rec1=${rec1#*,}
+ rec1=${rec1#*,}
+ rec1=${rec1#*,}
+ rec1=${rec1#*,}
+ #rec1=${rec1#*,}
+ rec1=${rec1#*,}
+ lte_rssi=${rec1%%,*} #LTE_RSSI
+ lte_rssi=`expr $lte_rssi / 10` #LTE_RSSI
+ Debug "LTE_BAND=$lte_band LTE_RSSI=$lte_rssi"
+ if [ $rssi == 0 ];then
+ rssi=$lte_rssi
+ fi
+ fi
+ w=$(echo $rec |grep "WCDMA"| wc -l)
+ if [ $w -ge 1 ];then
+ w=$(echo $rec |grep "UNKNOWN"|wc -l)
+ if [ $w -ge 1 ];then
+ Debug "UNKNOWN BAND"
+ return
+ fi
+ fi
+
+
+
+
+
+
+ #CNMP
+ OX=$( sendat $ATPORT "AT+CNMP?")
+ CNMP=$(echo "$OX" | grep -o "+CNMP:[ ]*[0-9]\{1,3\}" | grep -o "[0-9]\{1,3\}")
+ if [ -n "$CNMP" ]; then
+ case $CNMP in
+ "2"|"55" )
+ NETMODE="1" ;;
+ "13" )
+ NETMODE="3" ;;
+ "14" )
+ NETMODE="5" ;;
+ "38" )
+ NETMODE="7" ;;
+ "71" )
+ NETMODE="9" ;;
+ "109" )
+ NETMODE="8" ;;
+ * )
+ NETMODE="0" ;;
+ esac
+ fi
+
+ # CMGRMI 信息
+ OX=$( sendat $ATPORT "AT+CMGRMI=4")
+ CAINFO=$(echo "$OX" | grep -o "$REGXz" | tr ' ' ':')
+ if [ -n "$CAINFO" ]; then
+ for CASV in $(echo "$CAINFO"); do
+ LBAND=$LBAND"
B"$(echo "$CASV" | cut -d, -f4)
+ BW=$(echo "$CASV" | cut -d, -f5)
+ decode_bw
+ LBAND=$LBAND" (CA, Bandwidth $BW MHz)"
+ CHANNEL="$CHANNEL, "$(echo "$CASV" | cut -d, -f2)
+ PCI="$PCI, "$(echo "$CASV" | cut -d, -f7)
+ done
+ fi
+
+}
\ No newline at end of file
diff --git a/luci-app-cpe/root/usr/share/cpe/Quectel b/luci-app-cpe/root/usr/share/cpe/Quectel
new file mode 100644
index 0000000..22974c1
--- /dev/null
+++ b/luci-app-cpe/root/usr/share/cpe/Quectel
@@ -0,0 +1,507 @@
+#!/bin/sh
+ATPORT=1
+#Quectel
+lte_bw() {
+ BW=$(echo $BW | grep -o "[0-5]\{1\}")
+ case $BW in
+ "0")
+ BW="1.4" ;;
+ "1")
+ BW="3" ;;
+ "2"|"3"|"4"|"5")
+ BW=$((($(echo $BW) - 1) * 5)) ;;
+ esac
+}
+#Quectel
+nr_bw() {
+ BW=$(echo $BW | grep -o "[0-9]\{1,2\}")
+ case $BW in
+ "0"|"1"|"2"|"3"|"4"|"5")
+ BW=$((($(echo $BW) + 1) * 5)) ;;
+ "6"|"7"|"8"|"9"|"10"|"11"|"12")
+ BW=$((($(echo $BW) - 2) * 10)) ;;
+ "13")
+ BW="200" ;;
+ "14")
+ BW="400" ;;
+ esac
+}
+
+#ѯϢǿ
+All_CSQ()
+{
+ Debug "All_CSQ"
+ #ź
+ OX=$( sendat $ATPORT "AT+CSQ" |grep "+CSQ:")
+ OX=$(echo $OX | tr 'a-z' 'A-Z')
+ CSQ=$(echo "$OX" | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}")
+ if [ $CSQ = "99" ]; then
+ CSQ=""
+ fi
+ if [ -n "$CSQ" ]; then
+ CSQ_PER=$(($CSQ * 100/31))"%"
+ CSQ_RSSI=$((2 * CSQ - 113))" dBm"
+ else
+ CSQ="-"
+ CSQ_PER="-"
+ CSQ_RSSI="-"
+ fi
+}
+
+Quectel_SIMINFO()
+{
+ Debug "Quectel_SIMINFO"
+ # ȡIMEI
+ IMEI=$( sendat $ATPORT "AT+CGSN" | sed -n '2p' )
+ # ȡIMSI
+ IMSI=$( sendat $ATPORT "AT+CIMI" | sed -n '2p' )
+ # ȡICCID
+ ICCID=$( sendat $ATPORT "AT+ICCID" | grep -o "+ICCID:[ ]*[-0-9]\+" | grep -o "[-0-9]\{1,4\}" )
+ # ȡ绰
+ phone=$( sendat $ATPORT "AT+CNUM" | grep "+CNUM:" )
+
+}
+# SIMCOMȡվϢ
+Quectel_Cellinfo()
+{
+ # return
+ #cellinfo0.gcom
+ OX1=$( sendat $ATPORT "AT+COPS=3,0;+COPS?")
+ OX2=$( sendat $ATPORT "AT+COPS=3,2;+COPS?")
+ OX=$OX1" "$OX2
+
+ #cellinfo.gcom
+ OY1=$( sendat $ATPORT "AT+CREG=2;+CREG?;+CREG=0")
+ OY2=$( sendat $ATPORT "AT+CEREG=2;+CEREG?;+CEREG=0")
+ OY3=$( sendat $ATPORT "AT+C5GREG=2;+C5GREG?;+C5GREG=0")
+ OY=$OY1" "$OY2" "$OY3
+
+
+ OXx=$OX
+ OX=$(echo $OX | tr 'a-z' 'A-Z')
+ OY=$(echo $OY | tr 'a-z' 'A-Z')
+ OX=$OX" "$OY
+
+ #Debug "$OX"
+ #Debug "$OY"
+
+ COPS="-"
+ COPS_MCC="-"
+ COPS_MNC="-"
+ COPSX=$(echo $OXx | grep -o "+COPS: [01],0,.\+," | cut -d, -f3 | grep -o "[^\"]\+")
+
+ if [ "x$COPSX" != "x" ]; then
+ COPS=$COPSX
+ fi
+
+ COPSX=$(echo $OX | grep -o "+COPS: [01],2,.\+," | cut -d, -f3 | grep -o "[^\"]\+")
+
+ if [ "x$COPSX" != "x" ]; then
+ COPS_MCC=${COPSX:0:3}
+ COPS_MNC=${COPSX:3:3}
+ if [ "$COPS" = "-" ]; then
+ COPS=$(awk -F[\;] '/'$COPS'/ {print $2}' $ROOTER/signal/mccmnc.data)
+ [ "x$COPS" = "x" ] && COPS="-"
+ fi
+ fi
+
+ if [ "$COPS" = "-" ]; then
+ COPS=$(echo "$O" | awk -F[\"] '/^\+COPS: 0,0/ {print $2}')
+ if [ "x$COPS" = "x" ]; then
+ COPS="-"
+ COPS_MCC="-"
+ COPS_MNC="-"
+ fi
+ fi
+ COPS_MNC=" "$COPS_MNC
+
+ OX=$(echo "${OX//[ \"]/}")
+ CID=""
+ CID5=""
+ RAT=""
+ REGV=$(echo "$OX" | grep -o "+C5GREG:2,[0-9],[A-F0-9]\{2,6\},[A-F0-9]\{5,10\},[0-9]\{1,2\}")
+ if [ -n "$REGV" ]; then
+ LAC5=$(echo "$REGV" | cut -d, -f3)
+ LAC5=$LAC5" ($(printf "%d" 0x$LAC5))"
+ CID5=$(echo "$REGV" | cut -d, -f4)
+ CID5L=$(printf "%010X" 0x$CID5)
+ RNC5=${CID5L:1:6}
+ RNC5=$RNC5" ($(printf "%d" 0x$RNC5))"
+ CID5=${CID5L:7:3}
+ CID5="Short $(printf "%X" 0x$CID5) ($(printf "%d" 0x$CID5)), Long $(printf "%X" 0x$CID5L) ($(printf "%d" 0x$CID5L))"
+ RAT=$(echo "$REGV" | cut -d, -f5)
+ fi
+ REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{5,8\}")
+ REGFMT="3GPP"
+ if [ -z "$REGV" ]; then
+ REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{1,3\},[A-F0-9]\{5,8\}")
+ REGFMT="SW"
+ fi
+ if [ -n "$REGV" ]; then
+ LAC=$(echo "$REGV" | cut -d, -f3)
+ LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))"
+ if [ $REGFMT = "3GPP" ]; then
+ CID=$(echo "$REGV" | cut -d, -f4)
+ else
+ CID=$(echo "$REGV" | cut -d, -f5)
+ fi
+ CIDL=$(printf "%08X" 0x$CID)
+ RNC=${CIDL:1:5}
+ RNC=$RNC" ($(printf "%d" 0x$RNC))"
+ CID=${CIDL:6:2}
+ CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))"
+
+ else
+ REGV=$(echo "$OX" | grep -o "+CREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{2,8\}")
+ if [ -n "$REGV" ]; then
+ LAC=$(echo "$REGV" | cut -d, -f3)
+ CID=$(echo "$REGV" | cut -d, -f4)
+ if [ ${#CID} -gt 4 ]; then
+ LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))"
+ CIDL=$(printf "%08X" 0x$CID)
+ RNC=${CIDL:1:3}
+ CID=${CIDL:4:4}
+ CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))"
+ else
+ LAC=""
+ fi
+ else
+ LAC=""
+ fi
+ fi
+ REGSTAT=$(echo "$REGV" | cut -d, -f2)
+ if [ "$REGSTAT" == "5" -a "$COPS" != "-" ]; then
+ COPS_MNC=$COPS_MNC" (Roaming)"
+ fi
+ if [ -n "$CID" -a -n "$CID5" ] && [ "$RAT" == "13" -o "$RAT" == "10" ]; then
+ LAC="4G $LAC, 5G $LAC5"
+ CID="4G $CID
5G $CID5"
+ RNC="4G $RNC, 5G $RNC5"
+ elif [ -n "$CID5" ]; then
+ LAC=$LAC5
+ CID=$CID5
+ RNC=$RNC5
+ fi
+ if [ -z "$LAC" ]; then
+ LAC="-"
+ CID="-"
+ RNC="-"
+ fi
+}
+
+#Quectel˾һվAT
+Quectel_AT()
+{
+ Debug "Quectel_AT"
+ ATPORT
+
+ Quectel_SIMINFO
+ All_CSQ
+
+ Quectel_Cellinfo
+
+ #
+ OX=$( sendat $ATPORT 'AT+QENG="servingcell"' | grep "+QENG:" )
+ NR_NSA=$(echo $OX | grep -o -i "+QENG:[ ]\?\"NR5G-NSA\",")
+ NR_SA=$(echo $OX | grep -o -i "+QENG: \"SERVINGCELL\",[^,]\+,\"NR5G-SA\",\"[DFT]\{3\}\",")
+ if [ -n "$NR_NSA" ]; then
+ QENG=",,"$(echo $OX" " | grep -o -i "+QENG: \"LTE\".\+\"NR5G-NSA\"," | tr " " ",")
+ QENG5=$(echo $OX | grep -o -i "+QENG:[ ]\?\"NR5G-NSA\",[0-9]\{3\},[0-9]\{2,3\},[0-9]\{1,5\},-[0-9]\{2,5\},[-0-9]\{1,3\},-[0-9]\{2,3\},[0-9]\{1,7\},[0-9]\{1,3\}.\{1,6\}")
+ if [ -z "$QENG5" ]; then
+ QENG5=$(echo $OX | grep -o -i "+QENG:[ ]\?\"NR5G-NSA\",[0-9]\{3\},[0-9]\{2,3\},[0-9]\{1,5\},-[0-9]\{2,3\},[-0-9]\{1,3\},-[0-9]\{2,3\}")
+ if [ -n "$QENG5" ]; then
+ QENG5=$QENG5",,"
+ fi
+ fi
+ elif [ -n "$NR_SA" ]; then
+ QENG=$(echo $NR_SA | tr " " ",")
+ QENG5=$(echo $OX | grep -o -i "+QENG: \"SERVINGCELL\",[^,]\+,\"NR5G-SA\",\"[DFT]\{3\}\",[ 0-9]\{3,4\},[0-9]\{2,3\},[0-9A-F]\{1,10\},[0-9]\{1,5\},[0-9A-F]\{2,6\},[0-9]\{6,7\},[0-9]\{1,3\},[0-9]\{1,2\},-[0-9]\{2,5\},-[0-9]\{2,3\},[-0-9]\{1,3\}")
+ else
+ QENG=$(echo $OX" " | grep -o -i "+QENG: [^ ]\+ " | tr " " ",")
+ fi
+
+
+ # Debug "$QENG"
+ # Debug "$QENG5"
+
+ RAT=$(echo $QENG | cut -d, -f4 | grep -o "[-A-Z5]\{3,7\}")
+ case $RAT in
+ "GSM")
+ MODE="GSM"
+ ;;
+ "WCDMA")
+ MODE="WCDMA"
+ CHANNEL=$(echo $QENG | cut -d, -f9)
+ RSCP=$(echo $QENG | cut -d, -f12)
+ RSCP="-"$(echo $RSCP | grep -o "[0-9]\{1,3\}")
+ ECIO=$(echo $QENG | cut -d, -f13)
+ ECIO="-"$(echo $ECIO | grep -o "[0-9]\{1,3\}")
+ ;;
+ "LTE"|"CAT-M"|"CAT-NB")
+ MODE=$(echo $QENG | cut -d, -f5 | grep -o "[DFT]\{3\}")
+ if [ -n "$MODE" ]; then
+ MODE="$RAT $MODE"
+ else
+ MODE="$RAT"
+ fi
+ PCI=$(echo $QENG | cut -d, -f9)
+ CHANNEL=$(echo $QENG | cut -d, -f10)
+ LBAND=$(echo $QENG | cut -d, -f11 | grep -o "[0-9]\{1,3\}")
+ BW=$(echo $QENG | cut -d, -f12)
+ lte_bw
+ BWU=$BW
+ BW=$(echo $QENG | cut -d, -f13)
+ lte_bw
+ BWD=$BW
+ if [ -z "$BWD" ]; then
+ BWD="unknown"
+ fi
+ if [ -z "$BWU" ]; then
+ BWU="unknown"
+ fi
+ if [ -n "$LBAND" ]; then
+ LBAND="B"$LBAND" (Bandwidth $BWD MHz Down | $BWU MHz Up)"
+ fi
+ RSRP=$(echo $QENG | cut -d, -f15 | grep -o "[0-9]\{1,3\}")
+ if [ -n "$RSRP" ]; then
+ RSCP="-"$RSRP
+ RSRPLTE=$RSCP
+ fi
+ RSRQ=$(echo $QENG | cut -d, -f16 | grep -o "[0-9]\{1,3\}")
+ if [ -n "$RSRQ" ]; then
+ ECIO="-"$RSRQ
+ fi
+ RSSI=$(echo $QENG | cut -d, -f17 | grep -o "\-[0-9]\{1,3\}")
+ if [ -n "$RSSI" ]; then
+ CSQ_RSSI=$RSSI" dBm"
+ fi
+ SINRR=$(echo $QENG | cut -d, -f18 | grep -o "[0-9]\{1,3\}")
+ if [ -n "$SINRR" ]; then
+ if [ $SINRR -le 25 ]; then
+ SINR=$((($(echo $SINRR) * 2) -20))" dB"
+ fi
+ fi
+
+ if [ -n "$NR_NSA" ]; then
+ MODE="LTE/NR EN-DC"
+ echo "0" > /tmp/modnetwork
+ if [ -n "$QENG5" ] && [ -n "$LBAND" ] && [ "$RSCP" != "-" ] && [ "$ECIO" != "-" ]; then
+ PCI="$PCI, "$(echo $QENG5 | cut -d, -f4)
+ SCHV=$(echo $QENG5 | cut -d, -f8)
+ SLBV=$(echo $QENG5 | cut -d, -f9)
+ BW=$(echo $QENG5 | cut -d, -f10 | grep -o "[0-9]\{1,3\}")
+ if [ -n "$SLBV" ]; then
+ LBAND=$LBAND"
n"$SLBV
+ if [ -n "$BW" ]; then
+ nr_bw
+ LBAND=$LBAND" (Bandwidth $BW MHz)"
+ fi
+ if [ "$SCHV" -ge 123400 ]; then
+ CHANNEL=$CHANNEL", "$SCHV
+ else
+ CHANNEL=$CHANNEL", -"
+ fi
+ else
+ LBAND=$LBAND"
nxx (unknown NR5G band)"
+ CHANNEL=$CHANNEL", -"
+ fi
+ RSCP=$RSCP" dBm
"$(echo $QENG5 | cut -d, -f5)
+ SINRR=$(echo $QENG5 | cut -d, -f6 | grep -o "[0-9]\{1,3\}")
+ if [ -n "$SINRR" ]; then
+ if [ $SINRR -le 30 ]; then
+ SINR=$SINR"
"$((($(echo $SINRR) * 2) -20))" dB"
+ fi
+ fi
+ ECIO=$ECIO" (4G) dB
"$(echo $QENG5 | cut -d, -f7)" (5G) "
+ fi
+ fi
+ if [ -z "$LBAND" ]; then
+ LBAND="-"
+ else
+ if [ -n "$QCA" ]; then
+ QCA=$(echo $QCA | grep -o "\"S[CS]\{2\}\"[-0-9A-Z,\"]\+")
+ for QCAL in $(echo "$QCA"); do
+ if [ $(echo "$QCAL" | cut -d, -f7) = "2" ]; then
+ SCHV=$(echo $QCAL | cut -d, -f2 | grep -o "[0-9]\+")
+ SRATP="B"
+ if [ -n "$SCHV" ]; then
+ CHANNEL="$CHANNEL, $SCHV"
+ if [ "$SCHV" -gt 123400 ]; then
+ SRATP="n"
+ fi
+ fi
+ SLBV=$(echo $QCAL | cut -d, -f6 | grep -o "[0-9]\{1,2\}")
+ if [ -n "$SLBV" ]; then
+ LBAND=$LBAND"
"$SRATP$SLBV
+ BWD=$(echo $QCAL | cut -d, -f3 | grep -o "[0-9]\{1,3\}")
+ if [ -n "$BWD" ]; then
+ UPDOWN=$(echo $QCAL | cut -d, -f13)
+ case "$UPDOWN" in
+ "UL" )
+ CATYPE="CA"$(printf "\xe2\x86\x91") ;;
+ "DL" )
+ CATYPE="CA"$(printf "\xe2\x86\x93") ;;
+ * )
+ CATYPE="CA" ;;
+ esac
+ if [ $BWD -gt 14 ]; then
+ LBAND=$LBAND" ("$CATYPE", Bandwidth "$(($(echo $BWD) / 5))" MHz)"
+ else
+ LBAND=$LBAND" ("$CATYPE", Bandwidth 1.4 MHz)"
+ fi
+ fi
+ LBAND=$LBAND
+ fi
+ PCI="$PCI, "$(echo $QCAL | cut -d, -f8)
+ fi
+ done
+ fi
+ fi
+ if [ $RAT = "CAT-M" ] || [ $RAT = "CAT-NB" ]; then
+ LBAND="B$(echo $QENG | cut -d, -f11) ($RAT)"
+ fi
+ ;;
+ "NR5G-SA")
+ MODE="NR5G-SA"
+ if [ -n "$QENG5" ]; then
+ #AT+qnwcfg="NR5G_AMBR" #ѯٶ
+ MODE="$RAT $(echo $QENG5 | cut -d, -f4)"
+ PCI=$(echo $QENG5 | cut -d, -f8)
+ CHANNEL=$(echo $QENG5 | cut -d, -f10)
+ LBAND=$(echo $QENG5 | cut -d, -f11)
+ BW=$(echo $QENG5 | cut -d, -f12)
+ nr_bw
+ LBAND="n"$LBAND" (Bandwidth $BW MHz)"
+ RSCP=$(echo $QENG5 | cut -d, -f13)
+ ECIO=$(echo $QENG5 | cut -d, -f14)
+ if [ "$CSQ_PER" = "-" ]; then
+ RSSI=$(rsrp2rssi $RSCP $BW)
+ CSQ_PER=$((100 - (($RSSI + 51) * 100/-62)))"%"
+ CSQ=$((($RSSI + 113) / 2))
+ CSQ_RSSI=$RSSI" dBm"
+ fi
+ SINRR=$(echo $QENG5 | cut -d, -f15 | grep -o "[0-9]\{1,3\}")
+ if [ -n "$SINRR" ]; then
+ if [ $SINRR -le 30 ]; then
+ SINR=$((($(echo $SINRR) * 2) -20))" dB"
+ fi
+ fi
+ fi
+ ;;
+ esac
+
+
+
+
+
+ #
+ OX=$( sendat $ATPORT "AT+QCAINFO" | grep "+QCAINFO:" )
+ QCA=$(echo $OX" " | grep -o -i "+QCAINFO: \"S[CS]\{2\}\".\+NWSCANMODE" | tr " " ",")
+
+
+ #
+ OX=$( sendat $ATPORT 'AT+QCFG="nwscanmode"' | grep "+QCAINFO:" )
+ QNSM=$(echo $OX | grep -o -i "+QCFG: \"NWSCANMODE\",[0-9]")
+ QNSM=$(echo "$QNSM" | grep -o "[0-9]")
+ if [ -n "$QNSM" ]; then
+ MODTYPE="6"
+ case $QNSM in
+ "0" )
+ NETMODE="1" ;;
+ "1" )
+ NETMODE="3" ;;
+ "2"|"5" )
+ NETMODE="5" ;;
+ "3" )
+ NETMODE="7" ;;
+ esac
+ fi
+ if [ -n "$QNWP" ]; then
+ MODTYPE="6"
+ case $QNWP in
+ "AUTO" )
+ NETMODE="1" ;;
+ "WCDMA" )
+ NETMODE="5" ;;
+ "LTE" )
+ NETMODE="7" ;;
+ "LTE:NR5G" )
+ NETMODE="8" ;;
+ "NR5G" )
+ NETMODE="9" ;;
+ esac
+ fi
+
+
+ #
+ OX=$( sendat $ATPORT 'AT+QNWPREFCFG="mode_pref"' | grep "+QNWPREFCFG:" )
+ QNWP=$(echo $OX | grep -o -i "+QNWPREFCFG: \"MODE_PREF\",[A-Z5:]\+" | cut -d, -f2)
+
+ #¶
+ OX=$( sendat $ATPORT 'AT+QTEMP' | grep "+QTEMP:" )
+ QTEMP=$(echo $OX | grep -o -i "+QTEMP: [0-9]\{1,3\}")
+ if [ -z "$QTEMP" ]; then
+ QTEMP=$(echo $OX | grep -o -i "+QTEMP:[ ]\?\"XO[_-]THERM[_-][^,]\+,[\"]\?[0-9]\{1,3\}" | grep -o "[0-9]\{1,3\}")
+ fi
+ if [ -z "$QTEMP" ]; then
+ QTEMP=$(echo $OX | grep -o -i "+QTEMP:[ ]\?\"MDM-CORE-USR.\+[0-9]\{1,3\}\"" | cut -d\" -f4)
+ fi
+ if [ -z "$QTEMP" ]; then
+ QTEMP=$(echo $OX | grep -o -i "+QTEMP:[ ]\?\"MDMSS.\+[0-9]\{1,3\}\"" | cut -d\" -f4)
+ fi
+ if [ -n "$QTEMP" ]; then
+ CTEMP=$(echo $QTEMP | grep -o -i "[0-9]\{1,3\}")$(printf "\xc2\xb0")"C"
+ fi
+
+
+
+ #
+ OX=$( sendat $ATPORT "AT+QRSRP" | grep "+QRSRP:" )
+ QRSRP=$(echo "$OX" | grep -o -i "+QRSRP:[^,]\+,-[0-9]\{1,5\},-[0-9]\{1,5\},-[0-9]\{1,5\}[^ ]*")
+ if [ -n "$QRSRP" ] && [ "$RAT" != "WCDMA" ]; then
+ QRSRP1=$(echo $QRSRP | cut -d, -f1 | grep -o "[-0-9]\+")
+ QRSRP2=$(echo $QRSRP | cut -d, -f2)
+ QRSRP3=$(echo $QRSRP | cut -d, -f3)
+ QRSRP4=$(echo $QRSRP | cut -d, -f4)
+ QRSRPtype=$(echo $QRSRP | cut -d, -f5)
+ if [ "$QRSRPtype" == "NR5G" ]; then
+ if [ -n "$NR_SA" ]; then
+ RSCP=$QRSRP1
+ if [ -n "$QRPRP2" -a "$QRSRP2" != "-32768" ]; then
+ RSCP1="RxD "$QRSRP2
+ fi
+ if [ -n "$QRSRP3" -a "$QRSRP3" != "-32768" ]; then
+ RSCP=$RSCP" dBm
"$QRSRP3
+ fi
+ if [ -n "$QRSRP4" -a "$QRSRP4" != "-32768" ]; then
+ RSCP1="RxD "$QRSRP4
+ fi
+ else
+ RSCP=$RSRPLTE
+ if [ -n "$QRSRP1" -a "$QRSRP1" != "-32768" ]; then
+ RSCP=$RSCP" (4G) dBm
"$QRSRP1
+ if [ -n "$QRSRP2" -a "$QRSRP2" != "-32768" ]; then
+ RSCP="$RSCP,$QRSRP2"
+ if [ -n "$QRSRP3" -a "$QRSRP3" != "-32768" ]; then
+ RSCP="$RSCP,$QRSRP3"
+ if [ -n "$QRSRP4" -a "$QRSRP4" != "-32768" ]; then
+ RSCP="$RSCP,$QRSRP4"
+ fi
+ fi
+ RSCP=$RSCP" (5G) "
+ fi
+ fi
+ fi
+ elif [ "$QRSRP2$QRSRP3$QRSRP4" != "-44-44-44" -a -z "$QENG5" ]; then
+ RSCP=$QRSRP1
+ if [ "$QRSRP3$QRSRP4" == "-140-140" -o "$QRSRP3$QRSRP4" == "-44-44" -o "$QRSRP3$QRSRP4" == "-32768-32768" ]; then
+ RSCP1="RxD "$(echo $QRSRP | cut -d, -f2)
+ else
+ RSCP=$RSCP" dBm (RxD "$QRSRP2" dBm)
"$QRSRP3
+ RSCP1="RxD "$QRSRP4
+ fi
+ fi
+ fi
+
+
+}
\ No newline at end of file
diff --git a/luci-app-cpe/root/usr/share/cpe/SIMCOM b/luci-app-cpe/root/usr/share/cpe/SIMCOM
new file mode 100644
index 0000000..4d1cd41
--- /dev/null
+++ b/luci-app-cpe/root/usr/share/cpe/SIMCOM
@@ -0,0 +1,303 @@
+#!/bin/sh
+ATPORT=1
+
+#查询信息强度
+All_CSQ()
+{
+ Debug "All_CSQ"
+ #信号
+ OX=$( sendat $ATPORT "AT+CSQ" |grep "+CSQ:")
+ OX=$(echo $OX | tr 'a-z' 'A-Z')
+ CSQ=$(echo "$OX" | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}")
+ if [ $CSQ = "99" ]; then
+ CSQ=""
+ fi
+ if [ -n "$CSQ" ]; then
+ CSQ_PER=$(($CSQ * 100/31))"%"
+ CSQ_RSSI=$((2 * CSQ - 113))" dBm"
+ else
+ CSQ="-"
+ CSQ_PER="-"
+ CSQ_RSSI="-"
+ fi
+}
+
+# SIMCOM获取基站信息
+SIMCOM_Cellinfo()
+{
+ #baseinfo.gcom
+ OX=$( sendat 2 "ATI")
+ OX=$( sendat 2 "AT+CGEQNEG=1")
+
+ #cellinfo0.gcom
+ OX1=$( sendat 2 "AT+COPS=3,0;+COPS?")
+ OX2=$( sendat 2 "AT+COPS=3,2;+COPS?")
+ OX=$OX1" "$OX2
+
+ #cellinfo.gcom
+ OY1=$( sendat 2 "AT+CREG=2;+CREG?;+CREG=0")
+ OY2=$( sendat 2 "AT+CEREG=2;+CEREG?;+CEREG=0")
+ OY3=$( sendat 2 "AT+C5GREG=2;+C5GREG?;+C5GREG=0")
+ OY=$OY1" "$OY2" "$OY3
+
+
+ OXx=$OX
+ OX=$(echo $OX | tr 'a-z' 'A-Z')
+ OY=$(echo $OY | tr 'a-z' 'A-Z')
+ OX=$OX" "$OY
+
+ #Debug "$OX"
+ #Debug "$OY"
+
+ COPS="-"
+ COPS_MCC="-"
+ COPS_MNC="-"
+ COPSX=$(echo $OXx | grep -o "+COPS: [01],0,.\+," | cut -d, -f3 | grep -o "[^\"]\+")
+
+ if [ "x$COPSX" != "x" ]; then
+ COPS=$COPSX
+ fi
+
+ COPSX=$(echo $OX | grep -o "+COPS: [01],2,.\+," | cut -d, -f3 | grep -o "[^\"]\+")
+
+ if [ "x$COPSX" != "x" ]; then
+ COPS_MCC=${COPSX:0:3}
+ COPS_MNC=${COPSX:3:3}
+ if [ "$COPS" = "-" ]; then
+ COPS=$(awk -F[\;] '/'$COPS'/ {print $2}' $ROOTER/signal/mccmnc.data)
+ [ "x$COPS" = "x" ] && COPS="-"
+ fi
+ fi
+
+ if [ "$COPS" = "-" ]; then
+ COPS=$(echo "$O" | awk -F[\"] '/^\+COPS: 0,0/ {print $2}')
+ if [ "x$COPS" = "x" ]; then
+ COPS="-"
+ COPS_MCC="-"
+ COPS_MNC="-"
+ fi
+ fi
+ COPS_MNC=" "$COPS_MNC
+
+ OX=$(echo "${OX//[ \"]/}")
+ CID=""
+ CID5=""
+ RAT=""
+ REGV=$(echo "$OX" | grep -o "+C5GREG:2,[0-9],[A-F0-9]\{2,6\},[A-F0-9]\{5,10\},[0-9]\{1,2\}")
+ if [ -n "$REGV" ]; then
+ LAC5=$(echo "$REGV" | cut -d, -f3)
+ LAC5=$LAC5" ($(printf "%d" 0x$LAC5))"
+ CID5=$(echo "$REGV" | cut -d, -f4)
+ CID5L=$(printf "%010X" 0x$CID5)
+ RNC5=${CID5L:1:6}
+ RNC5=$RNC5" ($(printf "%d" 0x$RNC5))"
+ CID5=${CID5L:7:3}
+ CID5="Short $(printf "%X" 0x$CID5) ($(printf "%d" 0x$CID5)), Long $(printf "%X" 0x$CID5L) ($(printf "%d" 0x$CID5L))"
+ RAT=$(echo "$REGV" | cut -d, -f5)
+ fi
+ REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{5,8\}")
+ REGFMT="3GPP"
+ if [ -z "$REGV" ]; then
+ REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{1,3\},[A-F0-9]\{5,8\}")
+ REGFMT="SW"
+ fi
+ if [ -n "$REGV" ]; then
+ LAC=$(echo "$REGV" | cut -d, -f3)
+ LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))"
+ if [ $REGFMT = "3GPP" ]; then
+ CID=$(echo "$REGV" | cut -d, -f4)
+ else
+ CID=$(echo "$REGV" | cut -d, -f5)
+ fi
+ CIDL=$(printf "%08X" 0x$CID)
+ RNC=${CIDL:1:5}
+ RNC=$RNC" ($(printf "%d" 0x$RNC))"
+ CID=${CIDL:6:2}
+ CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))"
+
+ else
+ REGV=$(echo "$OX" | grep -o "+CREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{2,8\}")
+ if [ -n "$REGV" ]; then
+ LAC=$(echo "$REGV" | cut -d, -f3)
+ CID=$(echo "$REGV" | cut -d, -f4)
+ if [ ${#CID} -gt 4 ]; then
+ LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))"
+ CIDL=$(printf "%08X" 0x$CID)
+ RNC=${CIDL:1:3}
+ CID=${CIDL:4:4}
+ CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))"
+ else
+ LAC=""
+ fi
+ else
+ LAC=""
+ fi
+ fi
+ REGSTAT=$(echo "$REGV" | cut -d, -f2)
+ if [ "$REGSTAT" == "5" -a "$COPS" != "-" ]; then
+ COPS_MNC=$COPS_MNC" (Roaming)"
+ fi
+ if [ -n "$CID" -a -n "$CID5" ] && [ "$RAT" == "13" -o "$RAT" == "10" ]; then
+ LAC="4G $LAC, 5G $LAC5"
+ CID="4G $CID
5G $CID5"
+ RNC="4G $RNC, 5G $RNC5"
+ elif [ -n "$CID5" ]; then
+ LAC=$LAC5
+ CID=$CID5
+ RNC=$RNC5
+ fi
+ if [ -z "$LAC" ]; then
+ LAC="-"
+ CID="-"
+ RNC="-"
+ fi
+}
+SIMCOM_SIMINFO()
+{
+ Debug "Quectel_SIMINFO"
+ # 获取IMEI
+ IMEI=$( sendat $ATPORT "AT+CGSN" | sed -n '2p' )
+ # 获取IMSI
+ IMSI=$( sendat $ATPORT "AT+CIMI" | sed -n '2p' )
+ # 获取ICCID
+ ICCID=$( sendat $ATPORT "AT+ICCID" | grep -o "+ICCID:[ ]*[-0-9]\+" | grep -o "[-0-9]\{1,4\}" )
+ # 获取电话号码
+ phone=$( sendat $ATPORT "AT+CNUM" | grep "+CNUM:" )
+}
+#SIMCOM查找基站AT
+SIMCOM_AT()
+{
+ Debug "SIMCOM_AT"
+ ATPORT
+ All_CSQ
+ SIMCOM_SIMINFO
+ SIMCOM_Cellinfo
+
+ #温度
+ OX=$( sendat $ATPORT "AT+CPMUTEMP")
+ TEMP=$(echo "$OX" | grep -o "+CPMUTEMP:[ ]*[-0-9]\+" | grep -o "[-0-9]\{1,4\}")
+ if [ -n "$TEMP" ]; then
+ TEMP=$(echo $TEMP)$(printf "\xc2\xb0")"C"
+ fi
+
+
+ #基站信息
+ OX=$( sendat $ATPORT "AT+CPSI?")
+ rec=$(echo "$OX" | grep "+CPSI:")
+ w=$(echo $rec |grep "NO SERVICE"| wc -l)
+ if [ $w -ge 1 ];then
+ Debug "NO SERVICE"
+ return
+ fi
+ w=$(echo $rec |grep "NR5G_"| wc -l)
+ if [ $w -ge 1 ];then
+
+ w=$(echo $rec |grep "32768"| wc -l)
+ if [ $w -ge 1 ];then
+ Debug "-32768"
+ return
+ fi
+
+ Debug "$rec"
+ rec1=${rec##*+CPSI:}
+ #echo "$rec1"
+ MODE="${rec1%%,*}" # MODE="NR5G"
+ rect1=${rec1#*,}
+ rect1s="${rect1%%,*}" #Online
+ rect2=${rect1#*,}
+ rect2s="${rect2%%,*}" #460-11
+ rect3=${rect2#*,}
+ rect3s="${rect3%%,*}" #0xCFA102
+ rect4=${rect3#*,}
+ rect4s="${rect4%%,*}" #55744245764
+ rect5=${rect4#*,}
+ rect5s="${rect5%%,*}" #196
+ rect6=${rect5#*,}
+ rect6s="${rect6%%,*}" #NR5G_BAND78
+ rect7=${rect6#*,}
+ rect7s="${rect7%%,*}" #627264
+ rect8=${rect7#*,}
+ rect8s="${rect8%%,*}" #-940
+ rect9=${rect8#*,}
+ rect9s="${rect9%%,*}" #-110
+ # "${rec1##*,}" #最后一位
+ rect10=${rect9#*,}
+ rect10s="${rect10%%,*}" #最后一位
+ PCI=$rect5s
+ LBAND="n"$(echo $rect6s | cut -d, -f0 | grep -o "BAND[0-9]\{1,3\}" | grep -o "[0-9]\+")
+ CHANNEL=$rect7s
+ RSCP=$(($(echo $rect8s | cut -d, -f0) / 10))
+ ECIO=$(($(echo $rect9s | cut -d, -f0) / 10))
+ if [ "$CSQ_PER" = "-" ]; then
+ CSQ_PER=$((100 - (($RSCP + 31) * 100/-125)))"%"
+ fi
+ SINR=$(($(echo $rect10s | cut -d, -f0) / 10))" dB"
+ fi
+ w=$(echo $rec |grep "LTE"|grep "EUTRAN"| wc -l)
+ if [ $w -ge 1 ];then
+ rec1=${rec#*EUTRAN-}
+ lte_band=${rec1%%,*} #EUTRAN-BAND
+ rec1=${rec1#*,}
+ rec1=${rec1#*,}
+ rec1=${rec1#*,}
+ rec1=${rec1#*,}
+ #rec1=${rec1#*,}
+ rec1=${rec1#*,}
+ lte_rssi=${rec1%%,*} #LTE_RSSI
+ lte_rssi=`expr $lte_rssi / 10` #LTE_RSSI
+ Debug "LTE_BAND=$lte_band LTE_RSSI=$lte_rssi"
+ if [ $rssi == 0 ];then
+ rssi=$lte_rssi
+ fi
+ fi
+ w=$(echo $rec |grep "WCDMA"| wc -l)
+ if [ $w -ge 1 ];then
+ w=$(echo $rec |grep "UNKNOWN"|wc -l)
+ if [ $w -ge 1 ];then
+ Debug "UNKNOWN BAND"
+ return
+ fi
+ fi
+
+
+
+
+
+
+ #CNMP
+ OX=$( sendat $ATPORT "AT+CNMP?")
+ CNMP=$(echo "$OX" | grep -o "+CNMP:[ ]*[0-9]\{1,3\}" | grep -o "[0-9]\{1,3\}")
+ if [ -n "$CNMP" ]; then
+ case $CNMP in
+ "2"|"55" )
+ NETMODE="1" ;;
+ "13" )
+ NETMODE="3" ;;
+ "14" )
+ NETMODE="5" ;;
+ "38" )
+ NETMODE="7" ;;
+ "71" )
+ NETMODE="9" ;;
+ "109" )
+ NETMODE="8" ;;
+ * )
+ NETMODE="0" ;;
+ esac
+ fi
+
+ # CMGRMI 信息
+ OX=$( sendat $ATPORT "AT+CMGRMI=4")
+ CAINFO=$(echo "$OX" | grep -o "$REGXz" | tr ' ' ':')
+ if [ -n "$CAINFO" ]; then
+ for CASV in $(echo "$CAINFO"); do
+ LBAND=$LBAND"
B"$(echo "$CASV" | cut -d, -f4)
+ BW=$(echo "$CASV" | cut -d, -f5)
+ decode_bw
+ LBAND=$LBAND" (CA, Bandwidth $BW MHz)"
+ CHANNEL="$CHANNEL, "$(echo "$CASV" | cut -d, -f2)
+ PCI="$PCI, "$(echo "$CASV" | cut -d, -f7)
+ done
+ fi
+
+}
diff --git a/luci-app-cpe/root/usr/share/cpe/atcmd.sh b/luci-app-cpe/root/usr/share/cpe/atcmd.sh
new file mode 100644
index 0000000..989adab
--- /dev/null
+++ b/luci-app-cpe/root/usr/share/cpe/atcmd.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+rec=$(sendat $1 $2)
+echo $rec >> /tmp/result.at
\ No newline at end of file
diff --git a/luci-app-cpe/root/usr/share/cpe/cpedebug b/luci-app-cpe/root/usr/share/cpe/cpedebug
new file mode 100644
index 0000000..16d59fa
--- /dev/null
+++ b/luci-app-cpe/root/usr/share/cpe/cpedebug
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+en=1 #调试开关:0关闭,1打开 ,2输出到文件
+outfile="/tmp/cpe.log" #输出文件
+#日志信息
+Debug()
+{
+ tim=$(date "+%Y-%m-%d %H:%M:%S") #获取系统时间
+ if [ $en == 1 ]; then
+ echo $tim $1 #打印输出
+ elif [ $en == 2 ]; then
+ echo $tim $1 >> $outfile #输出到文件
+ fi
+}
+ATPORT()
+{
+ MODEMNAME="ALL"
+ # ATPORT=$(uci -q get modem.@ndis[0].tyyusb)
+ lsusb=$( lsusb )
+ RDFM650=$(echo "$lsusb" | grep "ID 2cb7:0a05 " | wc -l)
+ if [ "$RDFM650" == 1 ]; then
+ ATPORT=0
+ MODEMNAME="FM650CN"
+ else
+ ATPORT=2
+ fi
+}
\ No newline at end of file
diff --git a/luci-app-cpe/root/usr/share/cpe/delatcmd.sh b/luci-app-cpe/root/usr/share/cpe/delatcmd.sh
new file mode 100644
index 0000000..dd131f0
--- /dev/null
+++ b/luci-app-cpe/root/usr/share/cpe/delatcmd.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+rm -f /tmp/result.at
\ No newline at end of file
diff --git a/luci-app-cpe/root/usr/share/cpe/rssi b/luci-app-cpe/root/usr/share/cpe/rssi
new file mode 100644
index 0000000..0131323
--- /dev/null
+++ b/luci-app-cpe/root/usr/share/cpe/rssi
@@ -0,0 +1,418 @@
+#!/bin/sh
+source /usr/share/cpe/cpedebug
+source /usr/share/cpe/SIMCOM
+source /usr/share/cpe/Quectel
+source /usr/share/cpe/Fibocom
+
+#初值化数据结构
+InitData()
+{
+ Date=''
+ CHANNEL="-"
+ ECIO="-"
+ RSCP="-"
+ ECIO1=" "
+ RSCP1=" "
+ NETMODE="-"
+ LBAND="-"
+ PCI="-"
+ CTEMP="-"
+ MODE="-"
+ SINR="-"
+ IMEI='-'
+ IMSI='-'
+ ICCID='-'
+ phone='-'
+ conntype=''
+ Model=''
+
+
+}
+#写数据
+SETData()
+{
+ {
+ echo $Model #'RM520N-GL'
+ echo $conntype #'conntype'
+ echo '1e0e:9001'
+ echo $COPS #运营商
+ echo 'ttyUSB2' #端口
+ echo $TEMP #温度
+ echo 'QMI' #协议
+ echo '---------------------------------'
+ echo $IMEI #imei
+ echo $IMSI #imsi
+ echo $ICCID #iccid
+ echo $phone #phone
+ echo '---------------------------------'
+
+ echo $MODE
+ echo $CSQ
+ echo $CSQ_PER
+ echo $CSQ_RSSI
+ echo $ECIO #参考信号接收质量 RSRQ ecio
+ echo $ECIO1 #参考信号接收质量 RSRQ ecio1
+ echo $RSCP #参考信号接收功率 RSRP rscp0
+ echo $RSCP1 #参考信号接收功率 RSRP rscp1
+ echo $SINR #信噪比 SINR rv["sinr"]
+ echo $NETMODE #连接状态监控 rv["netmode"]
+ echo '---------------------------------'
+
+
+ echo $COPS_MCC #MCC
+ echo $$COPS_MNC #MNC
+ echo $LAC #eNB ID
+ echo '' #LAC_NUM
+ echo $RNC #TAC
+ echo '' #RNC_NUM
+ echo $CID
+ echo '' #CID_NUM
+ echo $LBAND
+ echo $CHANNEL
+ echo $PCI
+
+ echo $Date
+
+
+
+ echo $MODTYPE
+ echo $QTEMP
+
+ } > /tmp/cpe_cell.file
+}
+ATPORT=1
+
+# 自动处理模块信号
+AUTO_CPE()
+{
+ Debug "------------------------------端口$ATPORT---------------------------"
+ Debug "AUTO_CPE"
+ Date=$(date "+%Y-%m-%d %H:%M:%S")
+
+
+ #检测设备是否准备好
+ rec=$(sendat $ATPORT "AT" 500 |grep OK |wc -l)
+ if [ $rec == "1" ];then
+ sleep 1s
+ else
+ sleep 5s
+ return
+ fi
+ #读取模块信息
+ # if [ "$conntype" == "" ]; then
+ # {
+ # Debug "计算模块"
+ # ATATI=$( sendat $ATPORT "ATI")
+ # Getconntype=$(echo "$ATATI" | sed -n '2p')
+ # if [ "$Getconntype" == "" ]; then
+ # {
+ # sleep 5s
+ # return
+ # }
+ # fi
+ # Model=$(echo "$ATATI" | sed -n '3p')
+ # conntype=$Getconntype
+ # }
+ # fi
+
+ Debug "读取模块信息 计算模块"
+ ATATI=$( sendat $ATPORT "ATI")
+ Getconntype=$(echo "$ATATI" | sed -n '2p')
+ if [ "$Getconntype" == "" ]; then
+ {
+ sleep 5s
+ return
+ }
+ fi
+ Model=$(echo "$ATATI" | sed -n '3p')
+ conntype=$Getconntype
+
+ cpin=$( sendat $ATPORT "at+cpin?")
+ ERR=$(echo "$cpin" | grep "ERROR")
+ if [ ! -z "$ERR" ]; then # No SIM
+ Debug "No SIM"
+ sleep 5s
+ return
+ fi
+ RDY=$(echo "$cpin" | grep "READY")
+ if [ -z "$RDY" ]; then # SIM Locked
+ Debug "Correct Pin"
+ sleep 5s
+ return
+ else
+ Debug "Not Locked"
+ fi
+ #执行对应模块
+ if [ $(echo $conntype |grep "Quectel"| wc -l) -ge 1 ];then
+ {
+ Quectel_AT
+ }
+ elif [ $(echo $conntype |grep "SIMCOM"| wc -l) -ge 1 ];then
+ {
+ SIMCOM_AT
+ }
+ elif [ $(echo $conntype |grep "Fibocom"| wc -l) -ge 1 ];then
+ {
+ Fibocom_AT
+ }
+ else
+ {
+ Debug "null "
+ }
+ fi
+}
+#重新联网
+modem_reset()
+{
+
+ echo "Abnormal network restart"
+ lsusb=$( lsusb )
+ RDFM650=$(echo "$lsusb" | grep "ID 2cb7:0a05 " | wc -l)
+ echo "RDFM650 $RDFM650"
+ if [ "$RDFM650" == 1 ]; then
+ {
+ GTRNDIS=$(sendat $ATPORT "AT+GTRNDIS=1,1" 500 |grep OK |wc -l)
+ sleep 2s
+ }
+ else
+ {
+ start="$( /etc/init.d/modem stop )"
+ sleep 2s
+ start="$( /etc/init.d/modem start )"
+ sleep 5s
+ }
+ fi
+}
+#检测SIM卡是否插入,10次检测不到则重启模块
+check_sim()
+{
+ while [ 1 ]
+ do
+ enabled=$(uci -q get modem.@ndis[0].enabled)
+ if [ $enabled == '1' ] ;then
+ echo "Check the sim"
+ rec=$( sendat 2 "AT+CPIN?")
+ rec1=$(echo $rec | grep "READY" | wc -l )
+ if [ $rec1 == 1 ]; then
+ x=0
+ echo "SIM is READY"
+ else
+ let x++
+ if [ $x == 10 ]; then
+ echo "SIM abnormal restart"
+ modem_reset #重启模块
+ x=0
+ fi
+ fi
+ fi
+ sleep 6s
+ done
+}
+#检测网络状态第一次开机
+chenk_firstdns()
+{
+ while [ 1 ]
+ do
+ enabled=$(uci -q get modem.@ndis[0].enabled)
+ en1=$(uci -q get modem.@ndis[0].en)
+ if [ $enabled == '1' ] ;then
+ if [ $en1 == '1' ] ;then
+ echo "------------------------------开启任务---------------------------"
+ ipadd=$(uci -q get modem.@ndis[0].ipaddress)
+ ping -c 1 -w 1 $ipadd > /dev/null 2>&1
+ if [ $? -eq 0 ];then
+ echo "网络连接正常"
+ xx=0
+ return
+ else
+ echo "网络连接异常 $ipadd"
+ let xx++
+ let pxx++
+ fi
+ fi
+ if [ $xx == 5 ];then
+ xx=0
+ modem_reset
+ fi
+ if [ $pxx == 10 ];then
+ xx=0
+ pxx=0
+ return
+ fi
+ echo "------------------------------结束任务---------------------------"
+ fi
+ sleep 1s
+ done
+}
+#检测网络状态
+chenk_dns()
+{
+ en1=$(uci -q get modem.@ndis[0].en)
+ if [ $en1 == '1' ] ;then
+ echo "------------------------------开启任务---------------------------"
+ ipadd=$(uci -q get modem.@ndis[0].ipaddress)
+ ping -c 1 -w 1 $ipadd > /dev/null 2>&1
+ if [ $? -eq 0 ];then
+ echo "网络连接正常"
+ xx=0
+ else
+ echo "网络连接异常 $ipadd 次数$xx"
+ let xx++
+ fi
+ fi
+ an=$(uci -q get modem.@ndis[0].an)
+ if [ $xx == $an ];then
+ xx=0
+ modem_reset
+ fi
+ echo "------------------------------结束任务---------------------------"
+
+}
+# 信号任务
+chenk_Task()
+{
+ while [ 1 ]
+ do
+ enabled=$(uci -q get modem.@ndis[0].enabled)
+ if [ $enabled == '1' ] ;then
+ ATPORT
+ Debug "------------------------------开启任务---------------------------"
+ AUTO_CPE
+ SETData
+ chenk_dns
+ Debug "------------------------------结束任务---------------------------"
+ fi
+ sleep 10s
+ done
+}
+
+
+#注册网卡
+RegisterNetwork()
+{
+ # ATPORT
+ Debug "RegisterNetwork 注册网卡 $ $MODEMNAME"
+ # if [ "$MODEMNAME" == "FM650CN" ]; then
+ # getFM650=$(uci -q get network.wwan5g |grep "interface"| wc -l)
+ # if [ $getFM650 == "0" ] ;then
+ # uci set network.wwan5g=interface
+ # uci set network.wwan5g.ifname='usb0'
+ # uci set network.wwan5g.proto=dhcp
+ # uci commit network
+
+ # uci set firewall.@zone[1].network="wan wan6 wwan5g wwan5g6 wlan"
+ # uci commit firewall
+
+ # $(/etc/init.d/network reload)
+ # fi
+ # getFM650=$(uci -q get network.wwan5g6|grep "interface"| wc -l)
+ # if [ $getFM650 == "0" ] ;then
+ # uci set network.wwan5g6=interface
+ # uci set network.wwan5g6.ifname='usb0'
+ # uci set network.wwan5g6.proto='dhcpv6'
+ # uci set network.wwan5g6.reqaddress='try'
+ # uci set network.wwan5g6.reqprefix='auto'
+ # uci set network.wwan5g6._orig_ifname='usb0'
+ # uci set network.wwan5g6._orig_bridge='false'
+ # uci set network.wwan5g6.extendprefix='1'
+ # uci commit network
+ # uci set firewall.@zone[1].network="wan wan6 wwan wwan5g wwan5g6 wlan"
+ # uci commit firewall
+ # $(/etc/init.d/network reload)
+ # fi
+ # fi
+
+
+
+ if [ $(uci -q get network.wwan5g |grep "interface"| wc -l) == "0" ] ;then
+ uci set network.wwan5g=interface
+ if [ "$MODEMNAME" == "FM650CN" ]; then
+ uci set network.wwan5g.ifname='usb0'
+ else
+ uci set network.wwan5g.ifname='wwan0'
+ fi
+ uci set network.wwan5g.proto=dhcp
+ uci commit network
+ uci set firewall.@zone[1].network="wan wan6 wwan5g wwan5g6 wlan"
+ uci commit firewall
+ $(/etc/init.d/network reload)
+ fi
+ if [ $(uci -q get network.wwan5g6 |grep "interface"| wc -l) == "0" ] ;then
+ uci set network.wwan5g6=interface
+ if [ "$MODEMNAME" == "FM650CN" ]; then
+ uci set network.wwan5g6.ifname='usb0'
+ uci set network.wwan5g6._orig_ifname='usb0'
+ else
+ uci set network.wwan5g6.ifname='wwan0'
+ uci set network.wwan5g6._orig_ifname='wwan0'
+ fi
+ uci set network.wwan5g6.proto='dhcpv6'
+ uci set network.wwan5g6.reqaddress='try'
+ uci set network.wwan5g6.reqprefix='auto'
+ uci set network.wwan5g6._orig_bridge='false'
+ uci set network.wwan5g6.extendprefix='1'
+ uci commit network
+ uci set firewall.@zone[1].network="wan wan6 wwan wwan5g wwan5g6 wlan"
+ uci commit firewall
+ $(/etc/init.d/network reload)
+ fi
+ if [ "$MODEMNAME" == "FM650CN" ]; then
+ if [ $(uci -q get network.wwan5g.ifname |grep "usb0"| wc -l) == "0" ] ;then
+ uci set network.wwan5g.ifname='usb0'
+ uci commit network
+ $(/etc/init.d/network reload)
+ fi
+ if [ $(uci -q get network.wwan5g6.ifname |grep "usb0"| wc -l) == "0" ] ;then
+ uci set network.wwan5g6.ifname='usb0'
+ uci commit network
+ $(/etc/init.d/network reload)
+ fi
+ else
+ if [ $(uci -q get network.wwan5g.ifname |grep "wwan0"| wc -l) == "0" ] ;then
+ uci set network.wwan5g.ifname='wwan0'
+ uci commit network
+ $(/etc/init.d/network reload)
+ fi
+ if [ $(uci -q get network.wwan5g6.ifname |grep "wwan0"| wc -l) == "0" ] ;then
+ uci set network.wwan5g6._orig_ifname='wwan0'
+ uci set network.wwan5g6.ifname='wwan0'
+ uci commit network
+ $(/etc/init.d/network reload)
+ fi
+ fi
+
+
+
+}
+
+
+
+# 运行入口
+first()
+{
+ Debug "开启RSSI服务"
+ # 初值化数据结构
+ InitData
+ Debug "初值化数据完成"
+ sleep 1s
+ # 计算模块AT端口号
+ ATPORT
+ # 注册网卡
+ RegisterNetwork
+ # 第一次获取模块信息数据
+ AUTO_CPE
+ # 保存结构数据
+ SETData
+ #开机直接运行网络注册
+ modem_reset
+ # 第一次开机检测是否联网
+ chenk_firstdns
+ chenk_Task
+}
+
+#############################################
+# #
+# 进入主函数 #
+# #
+#############################################
+first
diff --git a/sendat/Makefile b/sendat/Makefile
new file mode 100644
index 0000000..6b25f0d
--- /dev/null
+++ b/sendat/Makefile
@@ -0,0 +1,33 @@
+include $(TOPDIR)/rules.mk#将openwrt顶层目录下的rules.mk文件中的内容导入进来
+
+PKG_NAME:=sendat#软件包名
+PKG_VERSION:=6.8.2#软件包版本
+PKG_BUILD_DIR:= $(BUILD_DIR)/$(PKG_NAME)#真正编译当前软件包的目录
+
+
+include $(INCLUDE_DIR)/package.mk#将$(TOPDIR)/include目录下的package.mk文件中的内容导入进来
+
+define Package/sendat
+ SECTION:=wrtnode#软件包类型
+ CATEGORY:=Daocaoren#menuconfig中软件包所属的一级目录
+ SUBMENU :=CPE#menuconfig中软件包所属的二级目录
+ TITLE:=Sendat AT#软件包标题
+ DEPENDS:=+libpthread#运行本软件依赖的其他包
+endef
+
+define Package/sendat/description #软件包描述
+ A sample for sendat test
+endef
+
+define Build/Prepare #编译之前的准备动作
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+
+define Package/sendat/install #软件包的安装方法,主要就是将一系列编译好的文件、启动脚本、UCI配置文件等拷贝到指定位置
+ $(INSTALL_DIR) $(1)/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/sendat $(1)/bin/
+endef
+
+$(eval $(call BuildPackage,sendat))
\ No newline at end of file
diff --git a/sendat/README.md b/sendat/README.md
new file mode 100644
index 0000000..00fe05c
--- /dev/null
+++ b/sendat/README.md
@@ -0,0 +1,5 @@
+# sendat
+AT 命令工具
+1简化使用AT命令请求方式
+使用命令说明
+sendat 2 'ATI' 2表示 /dev/ttyUSB2 'ATI' 为at命令
diff --git a/sendat/src/Makefile b/sendat/src/Makefile
new file mode 100644
index 0000000..301b189
--- /dev/null
+++ b/sendat/src/Makefile
@@ -0,0 +1,9 @@
+all:sendat
+
+OBJS = sendat.o
+
+sendat:$(OBJS)
+ $(CC) $(CFLAGS) -o $@ $(OBJS) -lpthread
+
+clean:
+ rm -f sendat *.o
\ No newline at end of file
diff --git a/sendat/src/pdu.c b/sendat/src/pdu.c
new file mode 100644
index 0000000..df7d9d4
--- /dev/null
+++ b/sendat/src/pdu.c
@@ -0,0 +1,420 @@
+/*
+ * 2017 - 2021 Cezary Jackiewicz
+ * 2014 lovewilliam
+ */
+// Copyright 2011 The Avalon Project Authors. All rights reserved.
+// Use of this source code is governed by the Apache License 2.0
+// that can be found in the LICENSE file.
+//
+// SMS encoding/decoding functions, which are based on examples from:
+// http://www.dreamfabric.com/sms/
+
+#include "pdu.h"
+
+#include
+#include
+
+enum {
+ BITMASK_7BITS = 0x7F,
+ BITMASK_8BITS = 0xFF,
+ BITMASK_HIGH_4BITS = 0xF0,
+ BITMASK_LOW_4BITS = 0x0F,
+
+ TYPE_OF_ADDRESS_UNKNOWN = 0x81,
+ TYPE_OF_ADDRESS_INTERNATIONAL_PHONE = 0x91,
+ TYPE_OF_ADDRESS_NATIONAL_SUBSCRIBER = 0xC8,
+ TYPE_OF_ADDRESS_ALPHANUMERIC = 0xD0,
+
+ SMS_DELIVER_ONE_MESSAGE = 0x04,
+ SMS_SUBMIT = 0x11,
+
+ SMS_MAX_7BIT_TEXT_LENGTH = 160,
+};
+
+// Swap decimal digits of a number (e.g. 12 -> 21).
+static unsigned char
+SwapDecimalNibble(const unsigned char x)
+{
+ return (x / 16) + ((x % 16) * 10);
+}
+
+// Encode/Decode PDU: Translate ASCII 7bit characters to 8bit buffer.
+// SMS encoding example from: http://www.dreamfabric.com/sms/.
+//
+// 7-bit ASCII: "hellohello"
+// [0]:h [1]:e [2]:l [3]:l [4]:o [5]:h [6]:e [7]:l [8]:l [9]:o
+// 1101000 1100101 1101100 1101100 1101111 1101000 1100101 1101100 1101100 1101111
+// | ||| ||||| | ||||||| ||||||
+// /-------------/ ///-------/// /////-///// \------------\ ||||||| \\\\\\ .
+// | ||| ||||| | ||||||| ||||||
+// input buffer position
+// 10000000 22111111 33322222 44443333 55555333 66666655 77777776 98888888 --999999
+// | ||| ||||| | ||||||| ||||||
+// 8bit encoded buffer
+// 11101000 00110010 10011011 11111101 01000110 10010111 11011001 11101100 00110111
+// E8 32 9B FD 46 97 D9 EC 37
+
+
+// Encode PDU message by merging 7 bit ASCII characters into 8 bit octets.
+int
+EncodePDUMessage(const char* sms_text, int sms_text_length, unsigned char* output_buffer, int buffer_size)
+{
+ // Check if output buffer is big enough.
+ if ((sms_text_length * 7 + 7) / 8 > buffer_size)
+ return -1;
+
+ int output_buffer_length = 0;
+ int carry_on_bits = 1;
+ int i = 0;
+
+ for (; i < sms_text_length - 1; ++i) {
+ output_buffer[output_buffer_length++] =
+ ((sms_text[i] & BITMASK_7BITS) >> (carry_on_bits - 1)) |
+ ((sms_text[i + 1] & BITMASK_7BITS) << (8 - carry_on_bits));
+ carry_on_bits++;
+ if (carry_on_bits == 8) {
+ carry_on_bits = 1;
+ ++i;
+ }
+ }
+
+ if (i <= sms_text_length)
+ output_buffer[output_buffer_length++] = (sms_text[i] & BITMASK_7BITS) >> (carry_on_bits - 1);
+
+ return output_buffer_length;
+}
+
+// Decode PDU message by splitting 8 bit encoded buffer into 7 bit ASCII
+// characters.
+int
+DecodePDUMessage_GSM_7bit(const unsigned char* buffer, int buffer_length, char* output_sms_text, int sms_text_length)
+{
+ int output_text_length = 0;
+ if (buffer_length > 0)
+ output_sms_text[output_text_length++] = BITMASK_7BITS & buffer[0];
+
+ if (sms_text_length > 1) {
+ int carry_on_bits = 1;
+ int i = 1;
+ for (; i < buffer_length; ++i) {
+
+ output_sms_text[output_text_length++] = BITMASK_7BITS & ((buffer[i] << carry_on_bits) | (buffer[i - 1] >> (8 - carry_on_bits)));
+
+ if (output_text_length == sms_text_length) break;
+
+ carry_on_bits++;
+
+ if (carry_on_bits == 8) {
+ carry_on_bits = 1;
+ output_sms_text[output_text_length++] = buffer[i] & BITMASK_7BITS;
+ if (output_text_length == sms_text_length) break;
+ }
+
+ }
+ if (output_text_length < sms_text_length) // Add last remainder.
+ output_sms_text[output_text_length++] = buffer[i - 1] >> (8 - carry_on_bits);
+ }
+
+ return output_text_length;
+}
+
+#define GSM_7BITS_ESCAPE 0x1b
+
+static const unsigned char gsm7bits_to_latin1[128] = {
+ '@', 0xa3, '$', 0xa5, 0xe8, 0xe9, 0xf9, 0xec, 0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
+ 0, '_', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xc6, 0xe6, 0xdf, 0xc9,
+ ' ', '!', '"', '#', 0xa4, '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
+ 0xa1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
+ 0xbf, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0,
+};
+
+static const unsigned char gsm7bits_extend_to_latin1[128] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\f', 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, '^', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, '{', '}', 0, 0, 0, 0, 0,'\\',
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '[', '~', ']', 0,
+ '|', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static int
+G7bitToAscii(char* buffer, int buffer_length)
+{
+ int i;
+
+ for (i = 0; i buffer_size)
+ return -1;
+
+ int i = 0;
+ for (; i < phone_number_length; ++i) {
+
+ if (phone_number[i] < '0' && phone_number[i] > '9')
+ return -1;
+
+ if (i % 2 == 0) {
+ output_buffer[output_buffer_length++] = BITMASK_HIGH_4BITS | (phone_number[i] - '0');
+ } else {
+ output_buffer[output_buffer_length - 1] =
+ (output_buffer[output_buffer_length - 1] & BITMASK_LOW_4BITS) |
+ ((phone_number[i] - '0') << 4);
+ }
+ }
+
+ return output_buffer_length;
+}
+
+// Decode a digit based phone number for SMS based format.
+static int
+DecodePhoneNumber(const unsigned char* buffer, int phone_number_length, char* output_phone_number)
+{
+ int i = 0;
+ for (; i < phone_number_length; ++i) {
+ if (i % 2 == 0)
+ output_phone_number[i] = (buffer[i / 2] & BITMASK_LOW_4BITS) + '0';
+ else
+ output_phone_number[i] = ((buffer[i / 2] & BITMASK_HIGH_4BITS) >> 4) + '0';
+ }
+ output_phone_number[phone_number_length] = '\0'; // Terminate C string.
+ return phone_number_length;
+}
+
+// Encode a SMS message to PDU
+int
+pdu_encode(const char* service_center_number, const char* phone_number, const char* sms_text,
+ unsigned char* output_buffer, int buffer_size)
+{
+ if (buffer_size < 2)
+ return -1;
+
+ int output_buffer_length = 0;
+
+ // 1. Set SMS center number.
+ int length = 0;
+ if (service_center_number && strlen(service_center_number) > 0) {
+ output_buffer[1] = TYPE_OF_ADDRESS_INTERNATIONAL_PHONE;
+ length = EncodePhoneNumber(service_center_number,
+ output_buffer + 2, buffer_size - 2);
+ if (length < 0 && length >= 254)
+ return -1;
+ length++; // Add type of address.
+ }
+ output_buffer[0] = length;
+ output_buffer_length = length + 1;
+ if (output_buffer_length + 4 > buffer_size)
+ return -1; // Check if it has space for four more bytes.
+
+ // 2. Set type of message.
+ output_buffer[output_buffer_length++] = SMS_SUBMIT;
+ output_buffer[output_buffer_length++] = 0x00; // Message reference.
+
+ // 3. Set phone number.
+ output_buffer[output_buffer_length] = strlen(phone_number);
+
+ if (strlen(phone_number) < 6) {
+ output_buffer[output_buffer_length + 1] = TYPE_OF_ADDRESS_UNKNOWN;
+ } else {
+ output_buffer[output_buffer_length + 1] = TYPE_OF_ADDRESS_INTERNATIONAL_PHONE;
+ }
+
+ length = EncodePhoneNumber(phone_number,
+ output_buffer + output_buffer_length + 2,
+ buffer_size - output_buffer_length - 2);
+ output_buffer_length += length + 2;
+ if (output_buffer_length + 4 > buffer_size)
+ return -1; // Check if it has space for four more bytes.
+
+
+ // 4. Protocol identifiers.
+ output_buffer[output_buffer_length++] = 0x00; // TP-PID: Protocol identifier.
+ output_buffer[output_buffer_length++] = 0x00; // TP-DCS: Data coding scheme.
+ output_buffer[output_buffer_length++] = 0xB0; // TP-VP: Validity: 10 days
+
+ // 5. SMS message.
+ int sms_text_length = strlen(sms_text);
+ char sms_text_7bit[2*SMS_MAX_7BIT_TEXT_LENGTH];
+ sms_text_length = AsciiToG7bit(sms_text, sms_text_length, sms_text_7bit);
+ if (sms_text_length > SMS_MAX_7BIT_TEXT_LENGTH)
+ return -1;
+ output_buffer[output_buffer_length++] = sms_text_length;
+ length = EncodePDUMessage(sms_text_7bit, sms_text_length,
+ output_buffer + output_buffer_length,
+ buffer_size - output_buffer_length);
+ if (length < 0)
+ return -1;
+ output_buffer_length += length;
+
+ return output_buffer_length;
+}
+
+int pdu_decode(const unsigned char* buffer, int buffer_length,
+ time_t* output_sms_time,
+ char* output_sender_phone_number, int sender_phone_number_size,
+ char* output_sms_text, int sms_text_size,
+ int* tp_dcs,
+ int* ref_number,
+ int* total_parts,
+ int* part_number,
+ int* skip_bytes)
+{
+
+ if (buffer_length <= 0)
+ return -1;
+
+ const int sms_deliver_start = 1 + buffer[0];
+ if (sms_deliver_start + 1 > buffer_length)
+ return -2;
+
+ const int user_data_header_length = (buffer[sms_deliver_start]>>4);
+
+ const int sender_number_length = buffer[sms_deliver_start + 1];
+ if (sender_number_length + 1 > sender_phone_number_size)
+ return -3; // Buffer too small to hold decoded phone number.
+
+ const int sender_type_of_address = buffer[sms_deliver_start + 2];
+ if (sender_type_of_address == TYPE_OF_ADDRESS_ALPHANUMERIC) {
+ DecodePDUMessage_GSM_7bit(buffer + sms_deliver_start + 3, (sender_number_length + 1) / 2, output_sender_phone_number, sender_number_length);
+ } else {
+ DecodePhoneNumber(buffer + sms_deliver_start + 3, sender_number_length, output_sender_phone_number);
+ }
+
+ const int sms_pid_start = sms_deliver_start + 3 + (buffer[sms_deliver_start + 1] + 1) / 2;
+
+ // Decode timestamp.
+ struct tm sms_broken_time;
+ sms_broken_time.tm_year = 100 + SwapDecimalNibble(buffer[sms_pid_start + 2]);
+ sms_broken_time.tm_mon = SwapDecimalNibble(buffer[sms_pid_start + 3]) - 1;
+ sms_broken_time.tm_mday = SwapDecimalNibble(buffer[sms_pid_start + 4]);
+ sms_broken_time.tm_hour = SwapDecimalNibble(buffer[sms_pid_start + 5]);
+ sms_broken_time.tm_min = SwapDecimalNibble(buffer[sms_pid_start + 6]);
+ sms_broken_time.tm_sec = SwapDecimalNibble(buffer[sms_pid_start + 7]);
+ (*output_sms_time) = timegm(&sms_broken_time);
+
+ const int sms_start = sms_pid_start + 2 + 7;
+ if (sms_start + 1 > buffer_length) return -1; // Invalid input buffer.
+
+ int tmp;
+ if((user_data_header_length&0x04)==0x04) {
+ tmp = buffer[sms_start + 1] + 1;
+ *skip_bytes = tmp;
+ *ref_number = 0x000000FF&buffer[sms_start + tmp - 2];
+ *total_parts = 0x000000FF&buffer[sms_start + tmp - 1];
+ *part_number = 0x000000FF&buffer[sms_start + tmp];
+ } else {
+ tmp = 0;
+ *skip_bytes = tmp;
+ *ref_number = tmp;
+ *total_parts = tmp;
+ *part_number = tmp;
+ }
+
+ int output_sms_text_length = buffer[sms_start];
+ if (sms_text_size < output_sms_text_length) return -1; // Cannot hold decoded buffer.
+
+ const int sms_tp_dcs_start = sms_pid_start + 1;
+ *tp_dcs = buffer[sms_tp_dcs_start];
+
+ switch((*tp_dcs / 4) % 4)
+ {
+ case 0:
+ {
+ // GSM 7 bit
+ int decoded_sms_text_size = DecodePDUMessage_GSM_7bit(buffer + sms_start + 1, buffer_length - (sms_start + 1),
+ output_sms_text, output_sms_text_length);
+ if (decoded_sms_text_size != output_sms_text_length) return -1; // Decoder length is not as expected.
+ output_sms_text_length = G7bitToAscii(output_sms_text, output_sms_text_length);
+ break;
+ }
+ case 2:
+ {
+ // UCS2
+ memcpy(output_sms_text, buffer + sms_start + 1, output_sms_text_length);
+ break;
+ }
+ default:
+ break;
+ }
+
+ // Add a C string end.
+ if (output_sms_text_length < sms_text_size)
+ output_sms_text[output_sms_text_length] = 0;
+ else
+ output_sms_text[sms_text_size-1] = 0;
+
+ return output_sms_text_length;
+}
+
diff --git a/sendat/src/pdu.h b/sendat/src/pdu.h
new file mode 100644
index 0000000..734a393
--- /dev/null
+++ b/sendat/src/pdu.h
@@ -0,0 +1,52 @@
+/*
+ * 2017 - 2021 Cezary Jackiewicz
+ * 2014 lovewilliam
+ */
+// Copyright 2011 The Avalon Project Authors. All rights reserved.
+// Use of this source code is governed by the Apache License 2.0
+// that can be found in the LICENSE file.
+#ifndef SMS_PDU_H_
+#define SMS_PDU_H_
+
+#include
+
+enum { SMS_MAX_PDU_LENGTH = 256 };
+
+/*
+ * Encode an SMS message. Output the encoded message into output pdu buffer.
+ * Returns the length of the SMS encoded message in the output buffer or
+ * a negative number in case encoding failed (for example provided output buffer
+ * does not have enough space).
+ */
+int pdu_encode(const char* service_center_number, const char* phone_number, const char* text,
+ unsigned char* pdu, int pdu_size);
+
+/*
+ * Decode an SMS message. Output the decoded message into the sms text buffer.
+ * Returns the length of the SMS dencoded message or a negative number in
+ * case encoding failed (for example provided output buffer has not enough
+ * space).
+ */
+int pdu_decode(const unsigned char* pdu, int pdu_len,
+ time_t* sms_time,
+ char* phone_number, int phone_number_size,
+ char* text, int text_size,
+ int* tp_dcs,
+ int* ref_number,
+ int* total_parts,
+ int* part_number,
+ int* skip_bytes);
+
+int ucs2_to_utf8 (int ucs2, unsigned char * utf8);
+
+int DecodePDUMessage_GSM_7bit(const unsigned char* buffer,
+ int buffer_length,
+ char* output_sms_text,
+ int sms_text_length);
+
+int EncodePDUMessage(const char* sms_text,
+ int sms_text_length,
+ unsigned char* output_buffer,
+ int buffer_size);
+
+#endif // SMS_SMS_H_
diff --git a/sendat/src/pdu_decoder.c b/sendat/src/pdu_decoder.c
new file mode 100644
index 0000000..9e9e055
--- /dev/null
+++ b/sendat/src/pdu_decoder.c
@@ -0,0 +1,107 @@
+/*
+ * 2014 lovewilliam
+ * SMS PDU Decoder
+ */
+#include "pdu.h"
+
+#include
+#include
+#include
+#include
+#include
+
+int ucs2_to_utf8 (int ucs2, unsigned char * utf8);
+
+int sms_decode()
+{
+ char buffer[2*SMS_MAX_PDU_LENGTH+4];
+ char *p = buffer;
+ char t[2];
+ int d;
+ do
+ {
+ t[0] = getchar();
+ if(t[0]=='\n')
+ {
+ break;
+ }
+ t[1] = getchar();
+ if(t[1]=='\n')
+ {
+ break;
+ }
+ *p = strtol(t,NULL,16);
+ p++;
+ }while(1);
+
+ time_t sms_time;
+ char sms_phone[40];
+ char sms_text[161];
+ int tp_dcs_type;
+ int ref_number;
+ int total_parts;
+ int part_number;
+ int skip_bytes;
+
+ int sms_text_length = pdu_decode((const unsigned char*)buffer,
+ sizeof(buffer),
+ &sms_time,
+ sms_phone, sizeof(sms_phone),
+ sms_text, sizeof(sms_text),
+ &tp_dcs_type,
+ &ref_number,
+ &total_parts,
+ &part_number,
+ &skip_bytes);
+
+ printf("From:%s\n",sms_phone);
+ printf("Textlen=%d\n",sms_text_length);
+ char time_data_str[64];
+ strftime(time_data_str,64,"%D %T", localtime(&sms_time));
+ printf("Date/Time:%s\n",time_data_str);
+
+ if (total_parts > 0) {
+ printf("Reference number: %d\n", ref_number);
+ printf("SMS segment %d of %d\n", part_number, total_parts);
+ }
+
+ switch((tp_dcs_type / 4) % 4)
+ {
+ case 0:
+ {
+ // GSM7 bit
+ int i = skip_bytes;
+ if(skip_bytes > 0) i = (skip_bytes*8+6)/7;
+ for(;i
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+// #include "pdu.h"
+
+
+#define MAX_PORTS 4
+/*this array hold information about each port we have opened */
+struct PortInfo {
+ char name[16];
+ int port_fd;
+};
+int serial_init(int port, int spd, int databits, int parity, \
+ int stopbits, int RTSCTS, int need_line_input);
+int serial_write(int fd, void *src, int len);
+int serial_read(int fd, char *buf, int len);
+int serial_recv(int fd,char *rbuf,int rbuf_len, int timeout);
+//串口常用初始化接口
+#define serial_com_init(port, spd, databits, parity, stopbits)\
+ serial_init(port, spd, databits, parity, stopbits, 0, 0)
+//串口默认初始化接口
+#define serial_def_init(port, spd) serial_init(port, spd, 8, 'n', 1, 0, 1)
+#endif
+
+
+
+/*
+** File: uart.c
+**
+** Description:
+** Provides an RS-232 interface that is very similar to the CVI provided
+** interface library
+*/
+/*this array hold information about each port we have opened */
+struct PortInfo ports[13] =
+{
+ {"/dev/ttyUSB0", 0},
+ {"/dev/ttyUSB1", 0},
+ {"/dev/ttyUSB2", 0},
+ {"/dev/ttyUSB3", 0},
+ {"/dev/ttyUSB4", 0},
+ {"/dev/ttyUSB5", 0},
+ {"/dev/ttyUSB6", 0},
+ {"/dev/ttyUSB7", 0},
+ {"/dev/ttyUSB8", 0},
+ {"/dev/ttyUSB9", 0},
+ {"/dev/ttyUSB10", 0},
+ {"/dev/ttyUSB11", 0},
+ {"/dev/ttyUSB12", 0},
+};
+FILE* pf;
+FILE* pfi;
+int spd_arr[] = {B2000000, B1500000, B576000, B500000, B460800, B230400, B115200, B57600, B38400, B19200, B9600, B4800, B2400};
+int name_arr[] = { 2000000, 1500000, 576000, 500000, 460800, 230400, 115200, 57600, 38400, 19200, 9600, 4800, 2400 };
+/**
+*@brief 设置串口通信速率
+*@param fd 类型 int 打开串口的文件句柄
+*@param speed 类型 int 串口速度
+*@return void
+*/
+int set_speed(int fd, int speed)
+{
+ int i;
+ int status;
+ struct termios Opt;
+ tcgetattr(fd, &Opt);
+ for ( i= 0; i < sizeof(spd_arr) / sizeof(int); i++) {
+ if(speed == name_arr[i]) {
+ tcflush(fd, TCIOFLUSH);
+ cfsetispeed(&Opt, spd_arr[i]);
+ cfsetospeed(&Opt, spd_arr[i]);
+ status = tcsetattr(fd, TCSANOW, &Opt);
+ if (status != 0) {
+ printf("tcsetattr failed");
+ return 1;
+ }
+ tcflush(fd,TCIOFLUSH);
+ }
+ }
+ // printf("set_speed\n");
+ return 0;
+}
+
+/**
+*@brief 设置串口数据位,停止位和效验位
+*@param fd 类型 int 打开的串口文件句柄
+*@param databits 类型 int 数据位 取值为 7 或者8
+*@param stopbits 类型 int 停止位 取值为 1 或者2
+*@param parity 类型 int 效验类型 取值为N,E,O,,S
+*/
+int set_Parity(int fd, int databits, int parity, int stopbits, int RTSCTS)
+{
+ struct termios options;
+ if ( tcgetattr( fd,&options) != 0) {
+ perror("SetupSerial 1");
+ return -1;
+ }
+ options.c_cflag &= ~CSIZE;
+ switch (databits) /*设置数据位数*/
+ {
+ case 7:
+ options.c_cflag |= CS7;
+ break;
+ case 8:
+ options.c_cflag |= CS8;
+ break;
+ default:
+ fprintf(stderr,"Unsupported data size\n");
+ return -1;
+ }
+
+ options.c_iflag |= INPCK;
+ cfmakeraw(&options);
+ //options.c_lflag |= (ICANON | ECHO | ECHOE);
+ //options.c_lflag &= ~(ICANON | ECHO | ECHOE);
+ //options.c_iflag &= ~(IXON | IXOFF);
+ switch (parity)
+ {
+ case 'n':
+ case 'N':
+ options.c_cflag &= ~PARENB; /* Clear parity enable */
+ options.c_iflag &= ~INPCK; /* Enable parity checking */
+ break;
+ case 'o':
+ case 'O':
+ options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
+ break;
+ case 'e':
+ case 'E':
+ options.c_cflag |= PARENB; /* Enable parity */
+ options.c_cflag &= ~PARODD; /* 转换为偶效验*/
+ break;
+ case 'S':
+ case 's': /*as no parity*/
+ options.c_cflag &= ~PARENB;
+ options.c_cflag &= ~CSTOPB;
+ break;
+ default:
+ fprintf(stderr,"Unsupported parity\n");
+ return -1;
+ }
+
+ /* 设置停止位*/
+ switch (stopbits)
+ {
+ case 1:
+ options.c_cflag &= ~CSTOPB;
+ break;
+ case 2:
+ options.c_cflag |= CSTOPB;
+ break;
+ default:
+ fprintf(stderr,"Unsupported stop bits\n");
+ return -1;
+ }
+
+ /* Set rts/cts */
+ if (RTSCTS)
+ {
+ printf("Set rts/cts");
+ options.c_cflag |= CRTSCTS;
+ }
+
+ tcflush(fd,TCIFLUSH);
+ options.c_cc[VTIME] = 150; /* 设置超时15 seconds*/
+ options.c_cc[VMIN] = 0; /* Update the options and do it NOW */
+ if (tcsetattr(fd,TCSANOW,&options) != 0)
+ {
+ printf("SetupSerial failed");
+ return -1;
+ }
+ // printf("set_Parity\n");
+ return 0;
+}
+
+//接收消息结尾加换行符
+int serial_set_line_input(int fd)
+{
+ struct termios options;
+ if ( tcgetattr( fd,&options) != 0) {
+ perror("SetupSerial 1");
+ return -1;
+ }
+
+ options.c_lflag |= ICANON;
+
+ tcflush(fd,TCIFLUSH);
+ options.c_cc[VTIME] = 150; /* 设置超时15 seconds*/
+ options.c_cc[VMIN] = 0; /* Update the options and do it NOW */
+ if (tcsetattr(fd,TCSANOW,&options) != 0)
+ {
+ perror("SetupSerial 3");
+ return -1;
+ }
+ return 0;
+}
+
+/**
+*@brief
+*@param port 串口端口号
+*@param spd 串口速度
+*@param databits,parity,stopbits,RTSCTS,分别为数据位,校验位,停止位,rtscts位
+*@param need_line_input接收数据结尾是否加换行符?
+*/
+int serial_init(int port, int spd, int databits, int parity, int stopbits, int RTSCTS, int need_line_input)
+{
+ int fd;
+ if(port < 13)
+ {
+ // printf("open port:%d\n", port);
+ }
+ else {
+ printf("error: port:%d > MAX_PORTS\n", port);
+ return -1;
+ }
+ //
+ fd = open(ports[port].name, O_RDWR|O_NOCTTY);//O_NONBLOCK 非阻塞, O_WRONLY 只读写, O_RDONLY 只读, O_RDWR 读写,O_NOCTTY 阻塞
+
+ if (-1 == fd) {
+ printf("init %s failed\n", ports[port].name);
+ return -1;
+ }
+ pf = fdopen(port, "w");
+ pfi = fdopen(port, "r");
+ if (!pf || ! pfi)
+ fprintf(stderr,"open port failed\n");
+
+
+
+ set_speed(fd, spd);
+
+ set_Parity(fd, databits, parity, stopbits, RTSCTS);
+
+ if (need_line_input) {
+ serial_set_line_input(fd);
+ }
+
+ ports[port].port_fd = fd;
+
+ return fd;
+}
+
+/**
+*@brief
+*@param fd 串口端口号文件描述符
+*@param src 需要通过串口发送的数据
+*@param len 需要发送的数据长度
+*@param 成功返回0, 否则返回-1
+*/
+int serial_write(int fd, void *src, int len)
+{
+ int ret = write(fd, src, len);
+ if (len != ret) {
+ perror("oh, write serial failed!");
+ return -1;
+ }
+ return 0;
+}
+
+/**
+*@brief
+*@param fd 串口端口号文件描述符
+*@param src 串口接收数据的指针
+*@param len 需要接收的数据长度
+*@param 成功返回0, 否则返回-1
+*/
+int serial_read(int fd, char *buf, int len)
+{
+ int ret = read(fd, buf, len-1);
+ if (-1 == ret) {
+ perror("oh, read serial failed!");
+ return -1;
+ }
+ buf[ret] = '\0';
+ return ret;
+}
+
+int serial_recv(int fd,char *rbuf,int rbuf_len, int timeout)
+{
+ int retval;
+ fd_set rset;
+ struct timeval time_out;
+ if(!rbuf || rbuf_len <= 0)
+ {
+ // printf("serial_recv Invalid parameter.\n");
+ return -1;
+ }
+ if(timeout) //指定延时等待
+ {
+ time_out.tv_sec = (time_t)(timeout / 1000);
+ time_out.tv_usec = 0;
+ FD_ZERO(&rset);
+ FD_SET(fd,&rset);
+
+ retval = select(fd,&rset,NULL,NULL,&time_out);
+ if(retval < 0)
+ {
+ // printf("%s,Select failed:%s\n",strerror(errno));
+ return -2;
+ }
+ else if(0 == retval)
+ {
+ // printf("Time Out.\n");
+ return 0;
+ }
+
+ }
+ // usleep(1000);
+ retval = read(fd, rbuf, rbuf_len);
+ if( retval <= 0)
+ {
+ // printf("Read failed:%s\n",strerror(errno));
+ return -3;
+ }
+ return retval;
+
+}
+
+
+static void timeout()
+{
+ fprintf(stderr,"No response from modem.\n");
+ exit(2);
+}
+/*字符包含判断*/
+static int starts_with(const char* prefix, const char* str)
+{
+ while(*prefix)
+ {
+ if (*prefix++ != *str++)
+ {
+ return 0;
+ }
+ }
+ return 1;
+}
+/*判断是否存在*/
+int FileExist(const char* filename)
+{
+ if (filename && access(filename, F_OK) == 0) {
+ return 1;
+ }
+ return 0;
+}
+/*字符转小写*/
+char* str_tolower(const char* str)
+{
+ size_t len = strlen(str);
+ char *lower = calloc(len+1, sizeof(char));
+ for (size_t i = 0; i < len; ++i) {
+ lower[i] = tolower((unsigned char)str[i]);
+ }
+ /*free(upper);*/
+ return lower;
+}
+/*字符转大写*/
+char* str_toupper(const char* str)
+{
+ size_t len = strlen(str);
+ char *upper = calloc(len+1, sizeof(char));
+ for (size_t i = 0; i < len; ++i) {
+ upper[i] = toupper((unsigned char)str[i]);
+ }
+ /*free(upper);*/
+ return upper;
+}
+/*char*转char[]*/
+char strx_tostrarr(const char* str)
+{
+ return 0;
+}
+
+
+int main(int argc, char **argv)
+{
+ if(argc<3)
+ {
+ printf("ERROR demo: sendat 2 'ATI'\n");
+ exit(1);
+ return 0;
+ }
+ int debug = 1;
+ int port= 0;
+ sscanf(argv[1], "%d", &port);
+ if(FileExist(ports[port].name)==0)
+ {
+ printf("AT ERROR absent.\n");
+ return 0;
+ }
+ char *message= argv[2];
+ char *nty= "\r\n";
+ char buff[1024];
+ signal(SIGALRM,timeout);
+ alarm(2);
+ /*信号超时3秒自动退出*/
+ int fd = serial_def_init(port, 1500000);
+ if(fd < 0) return 0;
+ char *send= strcat(message,nty);
+ serial_write(fd,send, strlen(send));
+ while(1) {
+ int read = serial_read(fd, buff, sizeof(buff));
+ if(starts_with("OK", buff)) {
+ if (debug == 1)
+ printf("%s", buff);
+ close(fd);//关闭串口
+ exit(0);
+ }
+ if(starts_with("ERROR", buff)) {
+ if (debug == 1)
+ printf("%s", buff);
+ close(fd);//关闭串口
+ exit(1);
+ }
+ if(starts_with("COMMAND NOT SUPPORT", buff)) {
+ if (debug == 1)
+ printf("%s", buff);
+ close(fd);//关闭串口
+ exit(1);
+ }
+ if(starts_with("+CME ERROR", buff)) {
+ if (debug == 1)
+ printf("%s", buff);
+ close(fd);//关闭串口
+ exit(1);
+ }
+ printf("%s", buff);
+ }
+
+ exit(1);
+ return 0;
+}
diff --git a/sendat/src/ucs2_to_utf8.c b/sendat/src/ucs2_to_utf8.c
new file mode 100644
index 0000000..5baa433
--- /dev/null
+++ b/sendat/src/ucs2_to_utf8.c
@@ -0,0 +1,53 @@
+/*
+ * 2014 lovewilliam
+ * from http://www.lemoda.net/c/ucs2-to-utf8/ucs2-to-utf8.c
+ */
+/* Input: a Unicode code point, "ucs2".
+
+ Output: UTF-8 characters in buffer "utf8".
+
+ Return value: the number of bytes written into "utf8", or -1 if
+ there was an error.
+
+ This adds a zero byte to the end of the string. It assumes that the
+ buffer "utf8" has at least four bytes of space to write to. */
+
+#define UNICODE_SURROGATE_PAIR -2
+#define UNICODE_BAD_INPUT -1
+
+int ucs2_to_utf8 (int ucs2, unsigned char * utf8)
+{
+ if (ucs2 < 0x80) {
+ utf8[0] = ucs2;
+ utf8[1] = '\0';
+ return 1;
+ }
+ if (ucs2 >= 0x80 && ucs2 < 0x800) {
+ utf8[0] = (ucs2 >> 6) | 0xC0;
+ utf8[1] = (ucs2 & 0x3F) | 0x80;
+ utf8[2] = '\0';
+ return 2;
+ }
+ if (ucs2 >= 0x800 && ucs2 < 0xFFFF) {
+ if (ucs2 >= 0xD800 && ucs2 <= 0xDFFF) {
+ /* Ill-formed. */
+ return UNICODE_SURROGATE_PAIR;
+ }
+ utf8[0] = ((ucs2 >> 12) ) | 0xE0;
+ utf8[1] = ((ucs2 >> 6 ) & 0x3F) | 0x80;
+ utf8[2] = ((ucs2 ) & 0x3F) | 0x80;
+ utf8[3] = '\0';
+ return 3;
+ }
+ if (ucs2 >= 0x10000 && ucs2 < 0x10FFFF) {
+ /* http://tidy.sourceforge.net/cgi-bin/lxr/source/src/utf8.c#L380 */
+ utf8[0] = 0xF0 | (ucs2 >> 18);
+ utf8[1] = 0x80 | ((ucs2 >> 12) & 0x3F);
+ utf8[2] = 0x80 | ((ucs2 >> 6) & 0x3F);
+ utf8[3] = 0x80 | ((ucs2 & 0x3F));
+ utf8[4] = '\0';
+ return 4;
+ }
+ return UNICODE_BAD_INPUT;
+}
+