🌴 Sync 2026-03-05 23:51:42

This commit is contained in:
github-actions[bot] committed 2026-03-05 23:51:42 +08:00
1 parent 97c049ed0a
commit 0acff03804
14253 files changed
+3893239

No files matched your search

+4
View File
@@ -0,0 +1,4 @@
#指定换行符
/luasrc/** text eol=lf
# /old/* text eol=lf
/root/** text eol=lf
+49
View File
@@ -0,0 +1,49 @@
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
+674
View File
@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
+37
View File
@@ -0,0 +1,37 @@
# Copyright (C) 2023 Siriling <siriling@qq.com>
# This is free software, licensed under the GNU General Public License v3.
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-modem
LUCI_TITLE:=LuCI support for Modem
LUCI_PKGARCH:=all
PKG_VERSION:=1.4.4
PKG_RELEASE:=1
PKG_LICENSE:=GPLv3
PKG_LINCESE_FILES:=LICENSE
PKF_MAINTAINER:=Siriling <siriling@qq.com>
LUCI_DEPENDS:=+luci-compat \
+kmod-usb2 +kmod-usb3 \
+kmod-usb-net-sierrawireless +kmod-usb-ohci \
+kmod-usb-serial-option +kmod-usb-serial +kmod-usb-serial-qualcomm \
+kmod-usb-net +kmod-usb-acm \
+kmod-usb-net-cdc-ether \
+kmod-usb-net-cdc-mbim \
+kmod-usb-net-rndis \
+kmod-usb-net-cdc-ncm +kmod-usb-net-huawei-cdc-ncm \
+usbutils \
+kmod-pcie_mhi \
+pciutils \
+quectel-cm \
+sms-tool \
+ndisc6 +rdisc6 \
+bc +jq
define Package/luci-app-modem/conffiles
/etc/config/modem
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature
+54
View File
@@ -0,0 +1,54 @@
# 中文 | [English](https://github.com/Siriling/5G-Modem-Support/blob/main/EngLish.md)
# luci-app-modem
# 目录
[一、说明](#一说明)
[二、模组支持](#二模组支持)
# 一、说明
- 支持USB和PCI两种通信方式的通信模组
- 支持配置多个通信模组进行拨号
- 支持IPv6
- 支持高通,紫光展锐,联发科等平台的通信模组
- 支持常见厂商的通信模组(例如:移远,广和通等)
# 二、模组支持
下面列出插件支持的模组
| 厂家名称 | 模组名称 | 平台 | 数据传输模式 | 端口模式 |
| -------- | -------------------------------------------------- | -------- | ------------ | ---------------------------- |
| 华为 | MH5000-31 | 华为 | USB | ECM,NCM |
| 移远通信 | RG200U-CN(DONGLE版) | 紫光展锐 | USB | ECM,MBIM,RNDIS,NCM |
| 移远通信 | RM500U-CN | 紫光展锐 | USB | ECM,MBIM,RNDIS,NCM |
| 移远通信 | RM500U-EA | 紫光展锐 | USB | ECM,MBIM,RNDIS,NCM |
| 移远通信 | RM500U-CNV | 紫光展锐 | USB | ECM,MBIM,RNDIS,NCM |
| 移远通信 | RM500Q-CN | 高通 | USB | RMNET,ECM,MBIM,RNDIS,NCM |
| 移远通信 | RM500Q-AE | 高通 | USB | RMNET,ECM,MBIM,RNDIS,NCM |
| 移远通信 | RM500Q-GL | 高通 | USB | RMNET,ECM,MBIM,RNDIS,NCM |
| 移远通信 | RM502Q-AE | 高通 | USB | RMNET,ECM,MBIM,RNDIS,NCM |
| 移远通信 | RM502Q-GL | 高通 | USB | RMNET,ECM,MBIM,RNDIS,NCM |
| 移远通信 | RM505Q-AE | 高通 | USB | RMNET,ECM,MBIM,RNDIS,NCM |
| 移远通信 | RM520N-CN | 高通 | USB | RMNET,ECM,MBIM,RNDIS,NCM |
| 移远通信 | RM520N-GL | 高通 | USB | RMNET,ECM,MBIM,RNDIS,NCM |
| 移远通信 | RM500Q-GL | 高通 | PCI | RMNET,MBIM |
| 移远通信 | RG500Q-EA | 高通 | PCI | RMNET,MBIM |
| 移远通信 | RM502Q-GL | 高通 | PCI | RMNET,MBIM |
| 移远通信 | RM520N-GL | 高通 | PCI | RMNET,MBIM |
| 移远通信 | RG520N-EU | 高通 | PCI | RMNET,MBIM |
| 广和通 | FM650-CN | 紫光展锐 | USB | ECM,MBIM,RNDIS,NCM |
| 广和通 | FM350-GL | 联发科 | USB | RNDIS |
| 广和通 | FM150-AE-01,FM150-AE-11,FM150-AE-21,FM150-NA-01 | 高通 | USB | RMNET,ECM,MBIM,RNDIS,NCM |
| 广和通 | FM350-GL | 联发科 | PCI | MBIM |
| 广和通 | FM150-AE-00,FM150-AE-10,FM150-AE-20,FM150-NA-00 | 高通 | PCI | RMNET |
| 美格智能 | SRM815 | 高通 | USB | RMNET,ECM,MBIM,RNDIS,NCM |
| 美格智能 | SRM825 | 高通 | USB | RMNET,ECM,MBIM,RNDIS,NCM |
| 美格智能 | SRM825N | 高通 | USB | RMNET,ECM,MBIM,RNDIS,NCM |
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

+988
View File
@@ -0,0 +1,988 @@
-- Copyright 2024 Siriling <siriling@qq.com>
module("luci.controller.modem", package.seeall)
local http = require "luci.http"
local fs = require "nixio.fs"
local json = require("luci.jsonc")
uci = luci.model.uci.cursor()
local script_path="/usr/share/modem/"
local run_path="/tmp/run/modem/"
function index()
if not nixio.fs.access("/etc/config/modem") then
return
end
entry({"admin", "network", "modem"}, alias("admin", "network", "modem", "modem_info"), translate("Modem"), 100).dependent = true
--模块信息
entry({"admin", "network", "modem", "modem_info"}, template("modem/modem_info"), translate("Modem Information"),10).leaf = true
entry({"admin", "network", "modem", "get_at_port"}, call("getATPort"), nil).leaf = true
entry({"admin", "network", "modem", "get_modem_info"}, call("getModemInfo")).leaf = true
--拨号配置
entry({"admin", "network", "modem", "dial_overview"},cbi("modem/dial_overview"),translate("Dial Overview"),20).leaf = true
entry({"admin", "network", "modem", "dial_config"}, cbi("modem/dial_config")).leaf = true
entry({"admin", "network", "modem", "get_modems"}, call("getModems"), nil).leaf = true
entry({"admin", "network", "modem", "get_dial_log_info"}, call("getDialLogInfo"), nil).leaf = true
entry({"admin", "network", "modem", "clean_dial_log"}, call("cleanDialLog"), nil).leaf = true
entry({"admin", "network", "modem", "status"}, call("act_status")).leaf = true
--模块调试
entry({"admin", "network", "modem", "modem_debug"},template("modem/modem_debug"),translate("Modem Debug"),30).leaf = true
entry({"admin", "network", "modem", "quick_commands_config"}, cbi("modem/quick_commands_config")).leaf = true
entry({"admin", "network", "modem", "get_mode_info"}, call("getModeInfo"), nil).leaf = true
entry({"admin", "network", "modem", "set_mode"}, call("setMode"), nil).leaf = true
entry({"admin", "network", "modem", "get_network_prefer_info"}, call("getNetworkPreferInfo"), nil).leaf = true
entry({"admin", "network", "modem", "set_network_prefer"}, call("setNetworkPrefer"), nil).leaf = true
entry({"admin", "network", "modem", "set_band_prefer"}, call("setBandPrefer"), nil).leaf = true
entry({"admin", "network", "modem", "get_self_test_info"}, call("getSelfTestInfo"), nil).leaf = true
entry({"admin", "network", "modem", "get_quick_commands"}, call("getQuickCommands"), nil).leaf = true
entry({"admin", "network", "modem", "send_at_command"}, call("sendATCommand"), nil).leaf = true
-- entry({"admin", "network", "modem", "get_modem_debug_info"}, call("getModemDebugInfo"), nil).leaf = true
--插件设置
entry({"admin", "network", "modem", "plugin_config"},cbi("modem/plugin_config"),translate("Plugin Config"),40).leaf = true
entry({"admin", "network", "modem", "modem_config"}, cbi("modem/modem_config")).leaf = true
entry({"admin", "network", "modem", "modem_scan"}, call("modemScan"), nil).leaf = true
--插件信息
entry({"admin", "network", "modem", "plugin_info"},template("modem/plugin_info"),translate("Plugin Info"),50).leaf = true
entry({"admin", "network", "modem", "get_plugin_info"}, call("getPluginInfo"), nil).leaf = true
--AT命令旧界面
entry({"admin", "network", "modem", "at_command_old"},template("modem/at_command_old")).leaf = true
end
--[[
@Description 判断字符串是否含有字母
@Params
str 字符串
]]
function hasLetters(str)
local pattern = "%a" -- 匹配字母的正则表达式
return string.find(str, pattern) ~= nil
end
--[[
@Description 执行Shell脚本
@Params
command sh命令
]]
function shell(command)
local odpall = io.popen(command)
local odp = odpall:read("*a")
odpall:close()
return odp
end
--[[
@Description 执行AT命令
@Params
at_port AT串口
at_command AT命令
]]
function at(at_port,at_command)
local command="source "..script_path.."modem_debug.sh && at "..at_port.." "..at_command
local result=shell(command)
result=string.gsub(result, "\r", "")
return result
end
--[[
@Description 获取制造商
@Params
at_port AT串口
]]
function getManufacturer(at_port)
local manufacturer
uci:foreach("modem", "modem-device", function (modem_device)
if at_port == modem_device["at_port"] then
manufacturer=modem_device["manufacturer"]
return true --跳出循环
end
end)
return manufacturer
end
--[[
@Description 获取模组拨号模式
@Params
at_port AT串口
manufacturer 制造商
platform 平台
]]
function getMode(at_port,manufacturer,platform)
local mode="unknown"
if at_port and manufacturer~="unknown" then
local command="source "..script_path..manufacturer..".sh && "..manufacturer.."_get_mode "..at_port.." "..platform
local result=shell(command)
mode=string.gsub(result, "\n", "")
end
return mode
end
--[[
@Description 获取模组支持的拨号模式
@Params
at_port AT串口
]]
function getModes(at_port)
local modes
uci:foreach("modem", "modem-device", function (modem_device)
if at_port == modem_device["at_port"] then
modes=modem_device["modes"]
return true --跳出循环
end
end)
return modes
end
--[[
@Description 获取模组连接状态
@Params
at_port AT串口
manufacturer 制造商
define_connect 连接定义
]]
function getModemConnectStatus(at_port,manufacturer,define_connect)
local connect_status="unknown"
if at_port and manufacturer~="unknown" then
local command="source "..script_path..manufacturer..".sh && "..manufacturer.."_get_connect_status "..at_port.." "..define_connect
local result=shell(command)
connect_status=string.gsub(result, "\n", "")
end
return connect_status
end
--[[
@Description 获取模组设备信息
@Params
at_port AT串口
]]
function getModemDeviceInfo(at_port)
local modem_device_info={}
uci:foreach("modem", "modem-device", function (modem_device)
if at_port == modem_device["at_port"] then
--获取数据接口
local data_interface=modem_device["data_interface"]:upper()
--获取网络驱动
local net_driver=modem_device["net_driver"]
--获取连接状态
local connect_status=getModemConnectStatus(modem_device["at_port"],modem_device["manufacturer"],modem_device["define_connect"])
--设置值
modem_device_info=modem_device
modem_device_info["data_interface"]=data_interface
modem_device_info["net_driver"]=net_driver
modem_device_info["connect_status"]=connect_status
return true
end
end)
return modem_device_info
end
--[[
@Description 获取模组更多信息
@Params
at_port AT串口
manufacturer 制造商
]]
function getModemMoreInfo(at_port,manufacturer,platform,define_connect)
--获取模组信息
local command="sh "..script_path.."modem_info.sh".." "..at_port.." "..manufacturer.." "..platform.." "..define_connect
local result=shell(command)
--设置值
local modem_more_info=json.parse(result)
return modem_more_info
end
--[[
@Description 模块状态获取
]]
function getModemInfo()
--获取AT串口
local at_port = http.formvalue("port")
--获取信息
local modem_device_info
local modem_more_info
if at_port then
modem_device_info=getModemDeviceInfo(at_port)
modem_more_info=getModemMoreInfo(at_port,modem_device_info["manufacturer"],modem_device_info["platform"],modem_device_info["define_connect"])
end
--设置信息
local modem_info={}
modem_info["device_info"]=modem_device_info
modem_info["more_info"]=modem_more_info
--设置翻译
local translation={}
--设备信息翻译
-- if modem_device_info then
-- local name=modem_device_info["name"]
-- translation[name]=luci.i18n.translate(name)
-- local manufacturer=modem_device_info["manufacturer"]
-- translation[manufacturer]=luci.i18n.translate(manufacturer)
-- local mode=modem_device_info["mode"]
-- translation[mode]=luci.i18n.translate(mode)
-- local data_interface=modem_device_info["data_interface"]
-- translation[data_interface]=luci.i18n.translate(data_interface)
-- local network=modem_device_info["network"]
-- translation[network]=luci.i18n.translate(network)
-- end
--基本信息翻译
-- if modem_more_info["base_info"] then
-- for key in pairs(modem_more_info["base_info"]) do
-- local value=modem_more_info["base_info"][key]
-- --翻译值
-- translation[value]=luci.i18n.translate(value)
-- end
-- end
--SIM卡信息翻译
if modem_more_info["sim_info"] then
local sim_info=modem_more_info["sim_info"]
for i = 1, #sim_info do
local info = sim_info[i]
for key in pairs(info) do
--翻译键
translation[key]=luci.i18n.translate(key)
-- local value=info[key]
-- if hasLetters(value) then
-- --翻译值
-- translation[value]=luci.i18n.translate(value)
-- end
end
end
end
--网络信息翻译
if modem_more_info["network_info"] then
local network_info=modem_more_info["network_info"]
for i = 1, #network_info do
local info = network_info[i]
for key in pairs(info) do
--翻译键
translation[key]=luci.i18n.translate(key)
-- local value=info[key]
-- if hasLetters(value) then
-- --翻译值
-- translation[value]=luci.i18n.translate(value)
-- end
end
end
end
--小区信息翻译
if modem_more_info["cell_info"] then
for network_mode_key in pairs(modem_more_info["cell_info"]) do
--翻译网络模式
translation[network_mode_key]=luci.i18n.translate(network_mode_key)
if network_mode_key == "EN-DC Mode" then
local network_mode=modem_more_info["cell_info"][network_mode_key]
for i = 1, #network_mode do
for key in pairs(network_mode[i]) do
--获取每个网络类型信息
local network_type=network_mode[i][key]
for j = 1, #network_type do
local info = network_type[j]
for key in pairs(info) do
translation[key]=luci.i18n.translate(key)
end
end
end
end
else
--获取网络类型信息
local network_type=modem_more_info["cell_info"][network_mode_key]
for i = 1, #network_type do
local info = network_type[i]
for key in pairs(info) do
translation[key]=luci.i18n.translate(key)
end
end
end
end
end
--添加额外翻译
translation["Unknown"]=luci.i18n.translate("Unknown")
translation["Excellent"]=luci.i18n.translate("Excellent")
translation["Good"]=luci.i18n.translate("Good")
translation["Fair"]=luci.i18n.translate("Fair")
translation["Bad"]=luci.i18n.translate("Bad")
--整合数据
local data={}
data["modem_info"]=modem_info
data["translation"]=translation
-- 写入Web界面
luci.http.prepare_content("application/json")
luci.http.write_json(data)
end
--[[
@Description 获取模组信息
]]
function getModems()
-- 获取所有模组
local modems={}
local translation={}
uci:foreach("modem", "modem-device", function (modem_device)
-- 获取连接状态
local connect_status=getModemConnectStatus(modem_device["at_port"],modem_device["manufacturer"],modem_device["define_connect"])
-- 获取拨号模式
local mode=getMode(modem_device["at_port"],modem_device["manufacturer"],modem_device["platform"])
-- 获取翻译
translation[connect_status]=luci.i18n.translate(connect_status)
if modem_device["name"] then
translation[modem_device["name"]]=luci.i18n.translate(modem_device["name"])
end
translation[mode]=luci.i18n.translate(mode)
-- 设置值
local modem=modem_device
modem["connect_status"]=connect_status
modem["mode"]=mode
local modem_tmp={}
modem_tmp[modem_device[".name"]]=modem
table.insert(modems,modem_tmp)
end)
-- 设置值
local data={}
data["modems"]=modems
data["translation"]=translation
-- 写入Web界面
luci.http.prepare_content("application/json")
luci.http.write_json(data)
end
--[[
@Description 获取拨号日志信息
]]
function getDialLogInfo()
local command="find "..run_path.." -name \"modem*_dial.cache\""
local result=shell(command)
local log_paths=string.split(result, "\n")
table.sort(log_paths)
local logs={}
local names={}
local translation={}
for key in pairs(log_paths) do
local log_path=log_paths[key]
if log_path ~= "" then
-- 获取模组
local tmp=string.gsub(log_path, run_path, "")
local modem=string.gsub(tmp, "_dial.cache", "")
local modem_name=uci:get("modem", modem, "name")
-- 获取日志内容
local command="cat "..log_path
log=shell(command)
-- 排序插入
modem_log={}
modem_log[modem]=log
table.insert(logs, modem_log)
--设置模组名
names[modem]=modem_name
-- 设置翻译
translation[modem_name]=luci.i18n.translate(modem_name)
end
end
-- 设置值
local data={}
data["dial_log_info"]=logs
data["modem_name_info"]=names
data["translation"]=translation
-- 写入Web界面
luci.http.prepare_content("application/json")
luci.http.write_json(data)
end
--[[
@Description 清空拨号日志
]]
function cleanDialLog()
-- 获取拨号日志路径
local dial_log_path = http.formvalue("path")
-- 清空拨号日志
local command=": > "..dial_log_path
shell(command)
-- 设置值
local data={}
data["clean_result"]="clean dial log"
-- 写入Web界面
luci.http.prepare_content("application/json")
luci.http.write_json(data)
end
--[[
@Description 模块列表状态函数
]]
function act_status()
local e = {}
e.index = luci.http.formvalue("index")
e.status = luci.sys.call(string.format("busybox ps -w | grep -v 'grep' | grep '/var/etc/socat/%s' >/dev/null", luci.http.formvalue("id"))) == 0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
--[[
@Description 获取模组的备注
@Params
network 移动网络
]]
function getModemRemarks(network)
local remarks=""
uci:foreach("modem", "dial-config", function (config)
---配置启用,且备注存在
if network == config["network"] and config["enable"] == "1" then
if config["remarks"] then
remarks=" ("..config["remarks"]..")" --" (备注)"
return true --跳出循环
end
end
end)
return remarks
end
--[[
@Description 获取AT串口
]]
function getATPort()
local at_ports={}
local translation={}
uci:foreach("modem", "modem-device", function (modem_device)
--获取模组的备注
local network=modem_device["network"]
local remarks=getModemRemarks(network)
--设置模组AT串口
if modem_device["name"] and modem_device["at_port"] then
local name=modem_device["name"]:upper()..remarks
if modem_device["name"] == "unknown" then
translation[modem_device["name"]]=luci.i18n.translate(modem_device["name"])
name=modem_device["name"]..remarks
end
local at_port = modem_device["at_port"]
--排序插入
at_port_tmp={}
at_port_tmp[at_port]=name
table.insert(at_ports, at_port_tmp)
end
end)
-- 设置值
local data={}
data["at_ports"]=at_ports
data["translation"]=translation
-- 写入Web界面
luci.http.prepare_content("application/json")
luci.http.write_json(data)
end
--[[
@Description 获取拨号模式信息
]]
function getModeInfo()
local at_port = http.formvalue("port")
--获取值
local mode_info={}
uci:foreach("modem", "modem-device", function (modem_device)
if at_port == modem_device["at_port"] then
--获取制造商
local manufacturer=modem_device["manufacturer"]
if manufacturer=="unknown" then
return true --跳出循环
end
--获取支持的拨号模式
local modes=modem_device["modes"]
--获取模组拨号模式
local mode=getMode(at_port,manufacturer,modem_device["platform"])
--设置模式信息
mode_info["mode"]=mode
mode_info["modes"]=modes
return true --跳出循环
end
end)
--设置值
local modem_debug_info={}
modem_debug_info["mode_info"]=mode_info
-- 写入Web界面
luci.http.prepare_content("application/json")
luci.http.write_json(modem_debug_info)
end
--[[
@Description 设置拨号模式
]]
function setMode()
local at_port = http.formvalue("port")
local mode_config = http.formvalue("mode_config")
--获取制造商
local manufacturer=getManufacturer(at_port)
--设置模组拨号模式
local command="source "..script_path..manufacturer..".sh && "..manufacturer.."_set_mode "..at_port.." "..mode_config
shell(command)
--获取设置好后的模组拨号模式
local mode
if at_port and manufacturer and manufacturer~="unknown" then
local command="source "..script_path..manufacturer..".sh && "..manufacturer.."_get_mode "..at_port
local result=shell(command)
mode=string.gsub(result, "\n", "")
end
-- 写入Web界面
luci.http.prepare_content("application/json")
luci.http.write_json(mode)
end
--[[
@Description 获取网络偏好信息
]]
function getNetworkPreferInfo()
local at_port = http.formvalue("port")
--获取制造商,数据接口,模组名称
local manufacturer
local data_interface
local name
uci:foreach("modem", "modem-device", function (modem_device)
if at_port == modem_device["at_port"] then
manufacturer=modem_device["manufacturer"]
data_interface=modem_device["data_interface"]
name=modem_device["name"]
return true --跳出循环
end
end)
--获取值
local network_prefer_info
if manufacturer~="unknown" then
--获取模组网络偏好
local command="source "..script_path..manufacturer..".sh && "..manufacturer.."_get_network_prefer "..at_port.." "..data_interface.." "..name
local result=shell(command)
network_prefer_info=json.parse(result)
end
--设置值
local modem_debug_info={}
modem_debug_info["network_prefer_info"]=network_prefer_info
-- 写入Web界面
luci.http.prepare_content("application/json")
luci.http.write_json(modem_debug_info)
end
--[[
@Description 设置网络偏好
]]
function setNetworkPrefer()
local at_port = http.formvalue("port")
local network_prefer_config = json.stringify(http.formvalue("prefer_config"))
--获取制造商,数据接口,模组名称
local manufacturer
local data_interface
local name
uci:foreach("modem", "modem-device", function (modem_device)
if at_port == modem_device["at_port"] then
manufacturer=modem_device["manufacturer"]
data_interface=modem_device["data_interface"]
name=modem_device["name"]
return true --跳出循环
end
end)
--设置模组网络偏好
local command="source "..script_path..manufacturer..".sh && "..manufacturer.."_set_network_prefer "..at_port.." "..network_prefer_config
shell(command)
--获取设置好后的模组网络偏好
local network_prefer={}
-- if at_port and manufacturer and manufacturer~="unknown" then
-- local command="source "..script_path..manufacturer..".sh && "..manufacturer.."_get_network_prefer "..at_port.." "..data_interface.." "..name
-- local result=shell(command)
-- network_prefer=json.parse(result)
-- end
-- 写入Web界面
luci.http.prepare_content("application/json")
luci.http.write_json(network_prefer)
end
--[[
@Description 设置频段偏好
]]
function setBandPrefer()
local at_port = http.formvalue("port")
local network_prefer_config = json.stringify(http.formvalue("prefer_config"))
--获取制造商,数据接口,模组名称
local manufacturer
local data_interface
local name
uci:foreach("modem", "modem-device", function (modem_device)
if at_port == modem_device["at_port"] then
manufacturer=modem_device["manufacturer"]
data_interface=modem_device["data_interface"]
name=modem_device["name"]
return true --跳出循环
end
end)
--设置模组网络偏好
local command="source "..script_path..manufacturer..".sh && "..manufacturer.."_set_band_prefer "..at_port.." "..network_prefer_config
shell(command)
--获取设置好后的模组网络偏好
local network_prefer={}
-- if at_port and manufacturer and manufacturer~="unknown" then
-- local command="source "..script_path..manufacturer..".sh && "..manufacturer.."_get_network_prefer "..at_port.." "..data_interface.." "..name
-- local result=shell(command)
-- network_prefer=json.parse(result)
-- end
-- 写入Web界面
luci.http.prepare_content("application/json")
luci.http.write_json(network_prefer)
end
--[[
@Description 获取自检信息
]]
function getSelfTestInfo()
local at_port = http.formvalue("port")
--获取制造商
local manufacturer=getManufacturer(at_port)
--获取值
local self_test_info={}
if manufacturer~="unknown" then
--获取模组电压
local command="source "..script_path..manufacturer..".sh && "..manufacturer.."_get_voltage "..at_port
local result=shell(command)
self_test_info["voltage"]=json.parse(result)
--获取模组温度
command="source "..script_path..manufacturer..".sh && "..manufacturer.."_get_temperature "..at_port
result=shell(command)
self_test_info["temperature"]=json.parse(result)
end
--设置值
local modem_debug_info={}
modem_debug_info["self_test_info"]=self_test_info
-- 写入Web界面
luci.http.prepare_content("application/json")
luci.http.write_json(modem_debug_info)
end
--[[
@Description 获取快捷命令
]]
function getQuickCommands()
--获取快捷命令选项
local quick_option = http.formvalue("option")
--获取AT串口
local at_port = http.formvalue("port")
local manufacturer
local platform
uci:foreach("modem", "modem-device", function (modem_device)
if at_port == modem_device["at_port"] then
--获取制造商
manufacturer=modem_device["manufacturer"]
--获取平台
platform=modem_device["platform"]
return true --跳出循环
end
end)
--未适配模组时,快捷命令选项为自定义
if manufacturer=="unknown" or manufacturer=="unknown" then
quick_option="custom"
end
local quick_commands={}
local commands={}
if quick_option=="auto" then
--获取通用模组AT命令
local command="jq '.quick_commands.general' \""..script_path.."at_commands.json\""
local result=shell(command)
local general_commands=json.parse(result)
--获取特殊模组AT命令
command="jq '.quick_commands."..manufacturer.."."..platform.."' \""..script_path.."at_commands.json\""
result=shell(command)
local special_commands=json.parse(result)
--把通用命令和特殊命令整合到一起
for i = 1, #special_commands do
local special_command = special_commands[i]
table.insert(general_commands,special_command)
end
quick_commands["quick_commands"]=general_commands
else
uci:foreach("custom_at_commands", "custom-commands", function (custom_commands)
local command={}
command[custom_commands["description"]]=custom_commands["command"]
table.insert(commands,command)
end)
quick_commands["quick_commands"]=commands
end
-- 写入Web界面
luci.http.prepare_content("application/json")
luci.http.write_json(quick_commands)
end
--[[
@Description 发送AT命令
]]
function sendATCommand()
local at_port = http.formvalue("port")
local at_command = http.formvalue("command")
local response={}
if at_port and at_command then
response["response"]=at(at_port,at_command)
response["time"]=os.date("%Y-%m-%d %H:%M:%S")
end
-- 写入Web界面
luci.http.prepare_content("application/json")
luci.http.write_json(response)
end
--[[
@Description 获取模组调试信息
]]
-- function getModemDebugInfo()
-- local at_port = http.formvalue("port")
-- --获取制造商
-- local manufacturer=getManufacturer(at_port)
-- --获取值
-- local mode_info={}
-- local network_prefer_info={}
-- local self_test_info={}
-- if manufacturer~="unknown" then
-- mode_info=getModeInfo(at_port,manufacturer)
-- network_prefer_info=getNetworkPreferInfo(at_port,manufacturer)
-- self_test_info=getSelfTestInfo(at_port,manufacturer)
-- end
-- -- 设置值
-- local modem_debug_info={}
-- modem_debug_info["mode_info"]=mode_info
-- modem_debug_info["network_prefer_info"]=network_prefer_info
-- modem_debug_info["self_test_info"]=self_test_info
-- -- 写入Web界面
-- luci.http.prepare_content("application/json")
-- luci.http.write_json(modem_debug_info)
-- end
--[[
@Description 模组扫描
]]
function modemScan()
local command="source "..script_path.."modem_scan.sh && modem_scan"
local result=shell(command)
-- 写入Web界面
luci.http.prepare_content("application/json")
luci.http.write_json(result)
end
--[[
@Description 设置插件版本信息
@Params
info 信息
]]
function setPluginVersionInfo(info)
-- 正则表达式
local version_regular_expression="[0-9]+.[0-9]+.[0-9]+"
for key in pairs(info) do
-- 获取插件版本
local command="opkg list-installed | grep -oE '"..key.." - "..version_regular_expression.."' | awk -F' ' '{print $3}' | tr -d '\n'"
local plugin_version=shell(command)
if plugin_version~="" then
info[key]=plugin_version
end
end
end
--[[
@Description 获取内核模块状态
@Params
result 命令返回值
]]
function getModelStatus(result)
local model_status="Not loaded"
if result~="" then
model_status="Loaded"
end
return model_status
end
--[[
@Description 设置内核模块状态
@Params
info 信息
]]
function setModelStatus(info)
for key in pairs(info) do
-- 获取内核模块名
local model_name=key:gsub(".ko","")
local command="lsmod | grep -oE '"..model_name.." '"
local result=shell(command)
local model_status=getModelStatus(result)
-- 修改信息表
info[key]=model_status
end
end
--[[
@Description 获取插件信息
]]
function getPluginInfo()
-- 设置翻译
translation={}
translation["Unknown"]=luci.i18n.translate("Unknown")
translation["Not installed"]=luci.i18n.translate("Not installed")
translation["Loaded"]=luci.i18n.translate("Loaded")
translation["Not loaded"]=luci.i18n.translate("Not loaded")
-- 获取插件信息
local plugin_info={}
plugin_info["luci-app-modem"]="Unknown"
setPluginVersionInfo(plugin_info)
-- 获取拨号工具信息
local dial_tool_info={}
dial_tool_info["modemmanager"]="Not installed"
dial_tool_info["quectel-cm"]="Not installed"
dial_tool_info["fibocom-dial"]="Not installed"
dial_tool_info["meig-cm"]="Not installed"
setPluginVersionInfo(dial_tool_info)
-- 获取通用驱动信息
local general_driver_info={}
general_driver_info["usbnet.ko"]="Not loaded"
general_driver_info["option.ko"]="Not loaded"
-- general_driver_info["qcserial.ko"]="Not loaded"
setModelStatus(general_driver_info)
-- 获取模组USB驱动信息
local usb_driver_info={}
--通用驱动
usb_driver_info["qmi_wwan.ko"]="Not loaded"
usb_driver_info["GobiNet.ko"]="Not loaded"
usb_driver_info["cdc_ether.ko"]="Not loaded"
usb_driver_info["cdc_mbim.ko"]="Not loaded"
usb_driver_info["rndis_host.ko"]="Not loaded"
usb_driver_info["cdc_ncm.ko"]="Not loaded"
--制造商私有驱动
usb_driver_info["qmi_wwan_q.ko"]="Not loaded"
usb_driver_info["qmi_wwan_f.ko"]="Not loaded"
usb_driver_info["qmi_wwan_m.ko"]="Not loaded"
usb_driver_info["qmi_wwan_t.ko"]="Not loaded"
usb_driver_info["meig_cdc_driver.ko"]="Not loaded"
setModelStatus(usb_driver_info)
-- 获取模组PCI驱动信息
local pci_driver_info={}
--通用驱动
pci_driver_info["mhi_net.ko"]="Not loaded"
pci_driver_info["qrtr_mhi.ko"]="Not loaded"
pci_driver_info["mhi_pci_generic.ko"]="Not loaded"
pci_driver_info["mhi_wwan_mbim.ko"]="Not loaded"
pci_driver_info["mhi_wwan_ctrl.ko"]="Not loaded"
--制造商私有驱动
pci_driver_info["pcie_mhi.ko"]="Not loaded"
pci_driver_info["mtk_pcie_wwan_m80.ko"]="Not loaded"
setModelStatus(pci_driver_info)
-- 设置值
local data={}
data["translation"]=translation
data["plugin_info"]=plugin_info
data["dial_tool_info"]=dial_tool_info
data["general_driver_info"]=general_driver_info
data["usb_driver_info"]=usb_driver_info
data["pci_driver_info"]=pci_driver_info
-- 写入Web界面
luci.http.prepare_content("application/json")
luci.http.write_json(data)
end
@@ -0,0 +1,189 @@
local dispatcher = require "luci.dispatcher"
local uci = require "luci.model.uci".cursor()
local http = require "luci.http"
m = Map("modem", translate("Dial Config"))
m.redirect = dispatcher.build_url("admin", "network", "modem","dial_overview")
s = m:section(NamedSection, arg[1], "dial-config", "")
s.addremove = false
s.dynamic = false
s:tab("general", translate("General Settings"))
s:tab("advanced", translate("Advanced Settings"))
--[[
@Description 执行Shell脚本
@Params
command sh命令
]]
function shell(command)
local odpall = io.popen(command)
local odp = odpall:read("*a")
odpall:close()
return odp
end
--[[
@Description 插件是否存在
@Params
name 插件名称
]]
function isPluginExist(name)
local isExist=false
-- 正则表达式
local version_regular_expression="[0-9]+.[0-9]+.[0-9]+"
-- 获取插件版本
local command="opkg list-installed | grep -oE '"..name.." - "..version_regular_expression.."' | awk -F' ' '{print $3}' | tr -d '\n'"
local plugin_version=shell(command)
if plugin_version~="" then
isExist=true
end
return isExist
end
--------general--------
-- 是否启用
enable = s:taboption("general", Flag, "enable", translate("Enable"))
enable.default = "0"
enable.rmempty = false
-- 备注
remarks = s:taboption("general", Value, "remarks", translate("Remarks"))
remarks.rmempty = true
-- 移动网络
-- network = s:taboption("general", Value, "network", translate("Mobile Network"))
network = s:taboption("general", ListValue, "network", translate("Mobile Network"))
-- network.default = ""
network.rmempty = false
-- 获取移动网络,并显示设备名
function getMobileNetwork()
local modem_number=uci:get('modem','global','modem_number')
if modem_number == "0" then
network:value("",translate("Mobile network not found"))
end
return
-- for i=0,modem_number-1 do
-- --获取模块名
-- local modem_name = uci:get('modem','modem'..i,'name')
-- if modem_name == nil then
-- modem_name = "unknown"
-- end
-- --设置网络
-- modem_network = uci:get('modem','modem'..i,'network')
-- if modem_network ~= nil then
-- network:value(modem_network,modem_network.." ("..translate(modem_name:upper())..")")
-- end
-- end
uci:foreach("modem", "modem-device", function (modem_device)
--获取模块名
local modem_name=modem_device["name"]
--获取网络
local modem_network=modem_device["network"]
--设置网络值
network:value(modem_network,modem_network.." ("..translate(modem_name:upper())..")")
end)
end
getMobileNetwork()
-- 拨号模式
-- mode = s:taboption("general", ListValue, "mode", translate("Mode"))
-- mode.rmempty = false
-- mode.description = translate("Only display the modes available for the adaptation modem")
-- local modes = {"qmi","gobinet","ecm","mbim","rndis","ncm"}
-- for i in ipairs(modes) do
-- mode:value(modes[i],string.upper(modes[i]))
-- end
-- 添加获取拨号模式信息
-- m:append(Template("modem/mode_info"))
--------advanced--------
-- 拨号工具
dial_tool = s:taboption("advanced", ListValue, "dial_tool", translate("Dial Tool"))
dial_tool.description = translate("After switching the dialing tool, it may be necessary to restart the module or restart the router to recognize the module.")
dial_tool.rmempty = true
dial_tool:value("", translate("Auto Choose"))
if isPluginExist("quectel-cm") then
dial_tool:value("quectel-CM", translate("quectel-CM"))
end
if isPluginExist("fibocom-dial") then
dial_tool:value("fibocom-dial", translate("fibocom-dial"))
end
if isPluginExist("meig-cm") then
dial_tool:value("meig-cm", translate("meig-cm"))
end
if isPluginExist("modemmanager") then
dial_tool:value("mmcli", translate("mmcli"))
end
-- 网络类型
pdp_type= s:taboption("advanced", ListValue, "pdp_type", translate("PDP Type"))
pdp_type.default = "ipv4v6"
pdp_type.rmempty = false
pdp_type:value("ipv4", translate("IPv4"))
pdp_type:value("ipv6", translate("IPv6"))
pdp_type:value("ipv4v6", translate("IPv4/IPv6"))
-- 网络桥接
network_bridge = s:taboption("advanced", Flag, "network_bridge", translate("Network Bridge"))
network_bridge.description = translate("After checking, enable network interface bridge.")
network_bridge.default = "0"
network_bridge.rmempty = false
-- 接入点
apn = s:taboption("advanced", Value, "apn", translate("APN"))
apn.default = ""
apn.rmempty = true
apn:value("", translate("Auto Choose"))
apn:value("cmnet", translate("China Mobile"))
apn:value("3gnet", translate("China Unicom"))
apn:value("ctnet", translate("China Telecom"))
apn:value("cbnet", translate("China Broadcast"))
apn:value("5gscuiot", translate("Skytone"))
auth = s:taboption("advanced", ListValue, "auth", translate("Authentication Type"))
auth.default = "none"
auth.rmempty = false
auth:value("none", translate("NONE"))
auth:value("both", translate("PAP/CHAP (both)"))
auth:value("pap", "PAP")
auth:value("chap", "CHAP")
username = s:taboption("advanced", Value, "username", translate("PAP/CHAP Username"))
username.rmempty = true
username:depends("auth", "both")
username:depends("auth", "pap")
username:depends("auth", "chap")
password = s:taboption("advanced", Value, "password", translate("PAP/CHAP Password"))
password.rmempty = true
password.password = true
password:depends("auth", "both")
password:depends("auth", "pap")
password:depends("auth", "chap")
-- 配置ID
id = s:taboption("advanced", ListValue, "id", translate("Config ID"))
id.rmempty = false
id:value(arg[1])
-- uci:set('modem',arg[1],'id',arg[1])
-- 隐藏配置ID
m:append(Template("modem/hide_dial_config_id"))
return m
@@ -0,0 +1,102 @@
local d = require "luci.dispatcher"
local uci = luci.model.uci.cursor()
local sys = require "luci.sys"
m = Map("modem")
m.title = translate("Dial Overview")
m.description = translate("Check and add modem dialing configurations")
--全局配置
s = m:section(NamedSection, "global", "global", translate("Global Config"))
s.anonymous = true
s.addremove = false
o = s:option(Flag, "enable_dial", translate("Enable"))
o.rmempty = false
o.description = translate("Enable dial configurations")
-- 添加模块状态
m:append(Template("modem/modem_status"))
s = m:section(TypedSection, "dial-config", translate("Config List"))
s.anonymous = true
s.addremove = true
s.template = "modem/tblsection"
s.extedit = d.build_url("admin", "network", "modem", "dial_config", "%s")
function s.create(uci, t)
local uuid = string.gsub(luci.sys.exec("echo -n $(cat /proc/sys/kernel/random/uuid)"), "-", "")
t = uuid
TypedSection.create(uci, t)
luci.http.redirect(uci.extedit:format(t))
end
function s.remove(uci, t)
uci.map.proceed = true
uci.map:del(t)
luci.http.redirect(d.build_url("admin", "network", "modem","dial_overview"))
end
o = s:option(Flag, "enable", translate("Enable"))
o.width = "5%"
o.rmempty = false
-- o = s:option(DummyValue, "status", translate("Status"))
-- o.template = "modem/status"
-- o.value = translate("Collecting data...")
o = s:option(DummyValue, "remarks", translate("Remarks"))
o = s:option(DummyValue, "network", translate("Mobile Network"))
o.cfgvalue = function(t, n)
-- 检测移动网络是否存在
local network = (Value.cfgvalue(t, n) or "")
local odpall = io.popen("ls /sys/class/net/ | grep -w "..network.." | wc -l")
local odp = odpall:read("*a"):gsub("\n","")
odpall:close()
if odp ~= "0" then
return network
else
return translate("The network device was not found")
end
end
o = s:option(DummyValue, "dial_tool", translate("Dial Tool"))
o.cfgvalue = function(t, n)
local dial_tool = (Value.cfgvalue(t, n) or "")
if dial_tool == "" then
dial_tool = translate("Auto Choose")
end
return translate(dial_tool)
end
o = s:option(DummyValue, "pdp_type", translate("PDP Type"))
o.cfgvalue = function(t, n)
local pdp_type = (Value.cfgvalue(t, n) or "")
if pdp_type == "ipv4v6" then
pdp_type = translate("IPv4/IPv6")
else
pdp_type = pdp_type:gsub("_","/"):upper():gsub("V","v")
end
return pdp_type
end
o = s:option(Flag, "network_bridge", translate("Network Bridge"))
o.width = "5%"
o.rmempty = false
o = s:option(DummyValue, "apn", translate("APN"))
o.cfgvalue = function(t, n)
local apn = (Value.cfgvalue(t, n) or "")
if apn == "" then
apn = translate("Auto Choose")
end
return apn
end
-- 添加模块拨号日志
m:append(Template("modem/modem_dial_log"))
-- m:append(Template("modem/list_status"))
return m
@@ -0,0 +1,167 @@
local dispatcher = require "luci.dispatcher"
local uci = require "luci.model.uci".cursor()
local sys = require "luci.sys"
local json = require("luci.jsonc")
local script_path="/usr/share/modem/"
--[[
@Description 执行Shell脚本
@Params
command sh命令
]]
function shell(command)
local odpall = io.popen(command)
local odp = odpall:read("*a")
odpall:close()
return odp
end
--[[
@Description 获取支持的模组信息
@Params
data_interface 数据接口
]]
function getSupportModems(data_interface)
local command="cat "..script_path.."modem_support.json"
local result=json.parse(shell(command))
return result["modem_support"][data_interface]
end
--[[
@Description 按照制造商给模组分类
]]
function getManufacturers()
local manufacturers={}
-- 获取支持的模组
local support_modem=getSupportModems("usb")
-- USB
for modem in pairs(support_modem) do
local manufacturer=support_modem[modem]["manufacturer"]
if manufacturers[manufacturer] then
-- 直接插入
table.insert(manufacturers[manufacturer],modem)
else
-- 不存在先创建一个空表
local tmp={}
table.insert(tmp,modem)
manufacturers[manufacturer]=tmp
end
end
-- 获取支持的模组
local support_modem=getSupportModems("pci")
-- PCI
for modem in pairs(support_modem) do
local manufacturer=support_modem[modem]["manufacturer"]
if manufacturers[manufacturer] then
-- 直接插入
table.insert(manufacturers[manufacturer],modem)
else
-- 不存在先创建一个空表
local tmp={}
table.insert(tmp,modem)
manufacturers[manufacturer]=tmp
end
end
return manufacturers
end
m = Map("modem", translate("Modem Config"))
m.redirect = dispatcher.build_url("admin", "network", "modem","plugin_config")
s = m:section(NamedSection, arg[1], "modem-device", "")
s.addremove = false
s.dynamic = false
-- 手动配置
manual = s:option(Flag, "manual", translate("Manual"))
manual.default = "1"
manual.rmempty = false
-- uci:set('modem','modem-device','manual',1)
-- 隐藏手动配置
m:append(Template("modem/hide_manual_config_modem"))
-- 移动网络
mobile_network = s:option(ListValue, "network", translate("Mobile Network"))
mobile_network.rmempty = true
-- 获取移动网络
function getMobileNetwork()
--获取所有的网络接口
local networks = sys.exec("ls -l /sys/class/net/ 2>/dev/null |awk '{print $9}' 2>/dev/null")
--遍历所有网络接口
for network in string.gmatch(networks, "%S+") do
-- 获取网络设备路径
local command="readlink -f /sys/class/net/"..network
local network_path=shell(command)
-- 判断路径是否带有usb(排除其他eth网络设备)
local flag="0"
if network_path:find("eth") and not network_path:find("usb") then
flag="1"
end
-- 只处理最上级的网络设备(wwan0.1,rmnet_mhi0.1)
-- local count=0
-- for _ in network_path:gmatch("/net") do
-- count = count + 1
-- end
-- if count > 1 then
-- flag="1"
-- end
if network:find("%.") then
flag="1"
end
if flag=="0" then
if network:find("usb") or network:find("wwan") or network:find("eth") then
--设置USB移动网络
mobile_network:value(network)
elseif network:find("mhi_hwip") or network:find("rmnet_mhi") then
--设置PCI移动网络
mobile_network:value(network)
end
end
end
end
getMobileNetwork()
-- 模组名称
name = s:option(ListValue, "name", translate("Modem Name"))
name.placeholder = translate("Not null")
name.rmempty = false
-- 按照制造商给模组分类
local manufacturers=getManufacturers()
for key in pairs(manufacturers) do
local modems=manufacturers[key]
-- 排序
table.sort(modems)
for i in pairs(modems) do
-- 首字母大写
local first_str=string.sub(key, 1, 1)
local manufacturer = string.upper(first_str)..string.sub(key, 2)
-- 设置值
name:value(modems[i],manufacturer.." "..modems[i]:upper())
end
end
-- AT串口
at_port = s:option(Value, "at_port", translate("AT Port"))
at_port.placeholder = translate("Not null")
at_port.rmempty = false
return m
@@ -0,0 +1,91 @@
local d = require "luci.dispatcher"
local uci = luci.model.uci.cursor()
local sys = require "luci.sys"
local script_path="/usr/share/modem/"
m = Map("modem")
m.title = translate("Plugin Config")
m.description = translate("Check and modify the plugin configuration")
font_red = [[<b style=color:red>]]
font_off = [[</b>]]
bold_on = [[<strong>]]
bold_off = [[</strong>]]
--全局配置
s = m:section(TypedSection, "global", translate("Global Config"))
s.anonymous = true
s.addremove = false
-- 模组扫描
o = s:option(Button, "modem_scan", translate("Modem Scan"))
o.template = "modem/modem_scan"
-- 启用USB扫描
o = s:option(Flag, "usb_scan", translate("Enable USB Device Scan"))
o.rmempty = false
o.description = translate("Enable scanning of USB devices for modems").." "..font_red..bold_on.. translate("(After disable, the automatic scanning and configuration function for USB modem information will be stopped)")..bold_off..font_off
-- 启用PCI扫描
o = s:option(Flag, "pci_scan", translate("Enable PCI Device Scan"))
o.rmempty = false
o.description = translate("Enable scanning of PCI devices for modems").." "..font_red..bold_on.. translate("(After disable, the automatic scanning and configuration function for PCI modem information will be stopped)")..bold_off..font_off
-- 启用手动配置
o = s:option(Flag, "manual_configuration", font_red..bold_on..translate("Manual Configuration")..bold_off..font_off)
o.rmempty = false
o.description = translate("Enable the manual configuration of modem information").." "..font_red..bold_on.. translate("(After enable, the automatic scanning and configuration function for modem information will be disabled)")..bold_off..font_off
-- 启用网络接口别名
o = s:option(Flag, "network_interface_alias", translate("Network Interface Alias"))
o.rmempty = false
o.description = translate("Enable automatic creation of network interface alias (Effective upon reinstatement of dialing configuration)")
-- 配置模组信息
s = m:section(TypedSection, "modem-device", translate("Modem Config"))
s.anonymous = true
s.addremove = true
-- s.sortable = true
s.template = "modem/tblsection"
s.extedit = d.build_url("admin", "network", "modem", "modem_config", "%s")
function s.create(uci, t)
-- 获取模组序号
-- local modem_no=tonumber(uci.map:get("@global[0]","modem_number")) -- 将字符串转换为数字类型
local modem_no=0
local uci_tmp=luci.model.uci.cursor()
uci_tmp:foreach("modem", "modem-device", function (modem_device)
modem_no=modem_no+1
end)
t="modem"..modem_no
TypedSection.create(uci, t)
-- 设置手动配置
-- uci.map:set(t,"manual","1")
luci.http.redirect(uci.extedit:format(t))
end
function s.remove(uci, t)
uci.map.proceed = true
uci.map:del(t)
luci.http.redirect(d.build_url("admin", "network", "modem","plugin_config"))
end
-- 移动网络
o = s:option(DummyValue, "network", translate("Network"))
-- 模组名称
o = s:option(DummyValue, "name", translate("Modem Name"))
o.cfgvalue = function(t, n)
local name = (Value.cfgvalue(t, n) or "")
return translate(name:upper())
end
-- AT串口
o = s:option(DummyValue, "at_port", translate("AT Port"))
-- o = s:option(Value, "at_port", translate("AT Port"))
-- o.placeholder = translate("Not null")
-- o.rmempty = false
-- o.optional = false
return m
@@ -0,0 +1,30 @@
-- Copyright 2024 Siriling <siriling@qq.com>
local dispatcher = require "luci.dispatcher"
local fs = require "nixio.fs"
local http = require "luci.http"
local uci = require "luci.model.uci".cursor()
m = Map("custom_at_commands")
m.title = translate("Custom quick commands")
m.description = translate("Customize your quick commands")
m.redirect = dispatcher.build_url("admin", "network", "modem","modem_debug")
-- 自定义命令 --
s = m:section(TypedSection, "custom-commands", translate("Custom Commands"))
s.anonymous = true
s.addremove = true
s.sortable = true
s.template = "modem/tblsection_command"
description = s:option(Value, "description", translate("Description"))
description.placeholder = translate("Not null")
description.rmempty = true
description.optional = false
command = s:option(Value, "command", translate("Command"))
command.placeholder = translate("Not null")
command.rmempty = true
command.optional = false
return m
@@ -0,0 +1,290 @@
<%+header%>
<style type="text/css">
/* 消息样式 */
#info_message {
text-align: left;
font-size: 1.8em;
}
#info_message img {
vertical-align: middle;
}
#info_message a {
color: rgb(61, 143, 173);
font-size: 50%;
}
#modem_status_view > div {
display: inline-block;
margin: 1rem;
padding: 1rem;
width: 15rem;
float: left;
line-height: 125%;
}
</style>
<script type="text/javascript">
window.onload=function()
{
//获取快捷AT命令选择框元素
var command_select = document.getElementById('command_select');
//更换快捷AT命令时触发
command_select.addEventListener("change", function() {
//自动填写到命令输入框
copy_to_input();
});
//获取快捷AT命令选择框元素
command_select = document.getElementById('command_select');
//点击快捷AT命令时触发(解决选择第一条命令的问题)
command_select.addEventListener("click", function() {
//选择框不为空,且选中的为第一个
if (command_select.options.length != 0 && command_select.selectedIndex == 0) {
//自动填写到命令输入框
copy_to_input();
}
});
}
//自动填写到命令输入框
function copy_to_input()
{
var node = document.getElementById('response');
node.style.visibility = 'hidden';
var command_select = document.getElementById("command_select").value;
document.getElementById("at_command").value = command_select;
document.getElementById("response").innerHTML = "";
}
//第一次打开界面
first_start=1;
// 获取快捷命令
function get_quick_commands()
{
//获取快捷选项
var quick_option = "custom";
//获取选中的模组
var at_port = document.getElementById("modem_select").value;
//获取AT命令
XHR.get('<%=luci.dispatcher.build_url("admin", "network", "modem", "get_quick_commands")%>', {"option":quick_option,"port":at_port},
function(x, data)
{
//获取模组选择框元素
var command_select = document.getElementById('command_select');
//获取快捷命令
var quick_commands=data["quick_commands"];
//遍历每一条信息
for (var info of quick_commands)
{
//遍历每一条信息里的键
for (var key in info)
{
var option = document.createElement('option');
option.text = key;
option.value = info[key];
command_select.appendChild(option);
}
}
}
);
}
// 定时触发更新AT串口
XHR.poll(5,'<%=luci.dispatcher.build_url("admin", "network", "modem", "get_at_port")%>', null,
function(x, data)
{
var at_ports=data["at_ports"];
//获取模块选择框元素
var modem_select = document.getElementById('modem_select');
// 记录所选
var selected=modem_select.value;
// 删除原来的选项
modem_select.options.length=0;
//遍历每一个AT串口
for (var port of at_ports)
{
//更新(key:AT串口,value:模块名称)
for (var key in port)
{
var option = document.createElement('option');
option.value = key;
var language=navigator.language;
if (port[key].includes("unknown"))
{
option.text = port[key].replace("unknown", key);
}
else
{
option.text = port[key];
}
modem_select.appendChild(option);
}
}
// 恢复原来的选择
for (let i = 0; i < modem_select.options.length; i++)
{
if(modem_select.options[i].value == selected)
{
modem_select.selectedIndex=i;
break;
}
}
// 界面显示控制
if (Object.keys(at_ports).length==0)
{
// 更新提示信息
document.getElementById("info_message").innerHTML='<strong><%:No modems found%></strong> <a href="https://blog.siriling.com:1212/2023/03/18/openwrt-5g-modem/#zi-dong-sao-miao-shi-bie-gong-neng" target="_blank"><%:(Check the reason)%></a>';
// 显示提示信息
document.getElementById("cbi-info").style.display="block";
// 隐藏AT命令界面
document.getElementById("at_command_view").style.display="none";
}
else
{
//获取快捷命令
if (first_start)
{
get_quick_commands();
first_start=0
}
// 显示AT命令界面
document.getElementById("at_command_view").style.display="block";
// 隐藏提示信息
document.getElementById("cbi-info").style.display="none";
}
}
);
function post_command(at_port,at_command)
{
XHR.post('<%=luci.dispatcher.build_url("admin", "network", "modem", "send_at_command")%>', {"port":at_port,"command":at_command},
function(x, data)
{
responseElement=document.getElementById("response");
if ("response" in data) {
//显示当前时间
// responseElement.value+=data["time"];
//显示返回值
responseElement.innerHTML+=data["response"];
}
}
);
return false;
}
document.addEventListener('DOMContentLoaded', function (ev) {
var button = document.getElementById("sendcmd");
button.addEventListener("click", function () {
//获取AT串口
var at_port = document.getElementById("modem_select").value;
if ( at_port.length == 0 )
{
document.getElementById("response").innerHTML = "";
alert("<%:Please choose a Modem%>");
return false;
}
//获取AT命令
var at_command = document.getElementById("at_command").value;
if ( at_command.length == 0 )
{
document.getElementById("response").innerHTML = "";
alert("<%:Please enter a AT Command%>");
return false;
}
//发送AT命令
post_command(at_port,at_command);
at_command = "";
var node = document.getElementById('response');
if (node.style.visibility=='visible') {
node.style.visibility = 'hidden';
}
else
node.style.visibility = 'visible'
return true;
});
}, true);
</script>
<h2 name="content"><%:AT Commands%></h2>
<div class="cbi-map-descr"><%:Debug Your Module%></div>
<fieldset class="cbi-section" id="cbi-info" style="display: block;">
<div class="cbi-section fade-in">
<h3><%:Message%></h3>
<table class="table" id="message">
<tr class="tr">
<td colspan="2" class="td left">
<div id="info_message">
<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>"/>
<%:Loading modem%>...
</div>
</td>
</tr>
</table>
</div>
</fieldset>
<div id="at_command_view" style="display: none;">
<h4><br/></h4>
<div class="table" width="100%">
<div class="tr">
<div class="td left" style="width:25%;"><%:Modem Select%></div>
<div class="td left" style="width:50%;">
<select name="modem_select" id="modem_select"></select>
</div>
<!-- <div class="td left" style="width:50%;"></div> -->
</div>
<div class="tr">
<div class="td left" style="width:25%;"><%:Quick Commands%></div>
<div class="td left" style="width:50%;">
<select name="command_select" id="command_select"></select>
</div>
<!-- <div class="td left" style="width:50%;"></div> -->
</div>
<div class="tr">
<div class="td left" style="width:25%;"><%:Enter Command%></div>
<div class="td left" style="width:50%;">
<input type="text" id="at_command" required size="20" >
</div>
<!-- <div class="td left" style="width:50%;"></div> -->
</div>
</div>
<div class="table" width="100%">
<div class="td left" style="width:25%;"><%:Response%>:
<pre id="response" style="visibility: hidden; width:100%;"></pre>
</div>
<div class="tr cbi-rowstyle-2">
<div class="td right"><input type="button" style="margin-right: 26%"; id="sendcmd" class="btn cbi-button cbi-button-neutral" value="<%:Send Command%>" /></div>
</div>
</div>
<div class="cbi-page-actions">
<input class="btn cbi-button cbi-button-link" type="button" value="<%:Return to modem debug%>" onclick="location.href='/cgi-bin/luci/admin/network/modem/modem_debug'">
</div>
</div>
<%+footer%>
@@ -0,0 +1,20 @@
<script type="text/javascript">//<![CDATA[
window.onload=function()
{
// 获取高级设置标签元素
var str="advanced"
var advanced_element = document.querySelector('div[data-tab="'+str+'"]');
// 适配老版luci(lede)
if (advanced_element==null) {
advanced_element = document.querySelectorAll('div[id*="'+str+'"]')[0];
}
//隐藏拨号配置ID元素
var dial_config_id_element = advanced_element.lastElementChild;
dial_config_id_element.style.display="none";
}
//]]>
</script>
@@ -0,0 +1,19 @@
<script type="text/javascript">//<![CDATA[
window.onload=function()
{
// 获取高级设置标签元素
var str="manual"
var manual_element = document.querySelector('div[data-tab="'+str+'"]');
// 适配老版luci(lede)
if (manual_element==null) {
manual_element = document.querySelectorAll('div[id*="'+str+'"]')[0];
}
//隐藏拨号配置ID元素
manual_element.style.display="none";
}
//]]>
</script>
@@ -0,0 +1,19 @@
<script type="text/javascript">
//<![CDATA[
var _status = document.getElementsByClassName('_status');
for(var i = 0; i < _status.length; i++) {
var id = _status[i].parentElement.parentElement.parentElement.id;
id = id.substr(id.lastIndexOf("-") + 1);
XHR.poll(1,'<%=url([[admin]], [[network]], [[modem]], [[status]])%>', {
index: i,
id: id
},
function(x, result) {
_status[result.index].setAttribute("style","font-weight:bold;");
_status[result.index].setAttribute("color",result.status ? "green":"red");
_status[result.index].innerHTML = (result.status ? '✓' : 'X');
}
);
}
//]]>
</script>
@@ -0,0 +1,51 @@
<script type="text/javascript">
window.onload=function()
{
var url=window.location.pathname
var lastSlashIndex = url.lastIndexOf("/");
var uuid = url.substring(lastSlashIndex + 1);
// 查询network元素
var network = document.getElementById("widget.cbid.modem."+uuid+".network");
if (network===null)
{
// 查询所有以.network结尾的元素
var elements = document.querySelectorAll('[id$=".network"]');
network=elements[0];
}
//页面加载完成时触发
getMode(network,uuid);
// 更换移动网络时触发
network.addEventListener('change', function() {
// 获取对应的拨号模式,并设置到页面选项中
getMode(network,uuid);
});
};
// 获取对应的拨号模式,并设置到页面选项中
function getMode(network,uuid)
{
// 获取当前选中的值
var selected=network.options[network.selectedIndex].value;
XHR.get('<%=luci.dispatcher.build_url("admin", "network", "modem", "mode_info")%>', {"network":selected},
function(x, json)
{
modeSelect = document.getElementById("widget.cbid.modem."+uuid+".mode");
if (modeSelect===null)
{
// 查询所有以.network结尾的元素
var elements = document.querySelectorAll('[id$=".mode"]');
modeSelect=elements[0];
}
// 删除原来的选项
modeSelect.options.length=0;
for (var key in json) {
modeSelect.add(new Option(json[key].toUpperCase(),json[key]));
}
}
);
}
</script>
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,283 @@
<script type="text/javascript">//<![CDATA[
function set_tab_event()
{
var tab_menu = document.getElementById("tab_menu");
//获取子元素
var childElements = tab_menu.children;
//获取需要禁用的元素
for (var i = 0; i < childElements.length; i++)
{
childElements[i].addEventListener('click', function(event) {
tab_event(this);
});
}
}
//获取需要禁用的元素
function get_enable_element(parent_element)
{
var enable_element;
//获取子元素
var childElements = parent_element.children;
//获取已启用的元素
for (var i = 0; i < childElements.length; i++)
{
// 检查当前子元素的class属性是否为cbi-tab
if (childElements[i].classList.contains('cbi-tab'))
{
enable_element=childElements[i];
break;
}
}
return enable_element;
}
// 设置标签显示
function set_tab_view(disenable_element,enable_element)
{
//获取tab内容父元素
var tab_context = document.getElementById('dial_log_view');
//禁用tab
disenable_element.classList.remove('cbi-tab');
disenable_element.classList.add('cbi-tab-disabled');
//禁用tab内容
var data_tab_disenable = disenable_element.getAttribute('data-tab');
var tab_context_disenable_element = tab_context.querySelector('div[data-tab="'+data_tab_disenable+'"]');
tab_context_disenable_element.setAttribute('data-tab-active','false');
tab_context_disenable_element.style.display="none";
//启用tab
enable_element.classList.remove('cbi-tab-disabled');
enable_element.classList.add('cbi-tab');
//启用tab内容
var data_tab_enable = enable_element.getAttribute('data-tab');
var tab_context_enable_element = tab_context.querySelector('div[data-tab="'+data_tab_enable+'"]');
tab_context_enable_element.setAttribute('data-tab-active','true');
tab_context_enable_element.style.display="block";
}
// 标签事件处理(更新选中的标签及标签内容)
function tab_event(tab_element)
{
//获取需要禁用的tab元素
var tab_menu = document.getElementById("tab_menu");
var disenable_element=get_enable_element(tab_menu);
if (tab_element != disenable_element) {
set_tab_view(disenable_element,tab_element);
}
}
// 设置滚动条
function set_scroll_top(log_ids)
{
for(var log_id in log_ids)
{
var log_element=document.getElementById(log_id);
if (log_ids[log_id]==-1)
{
log_element.scrollTop = log_element.scrollHeight;
}
else
{
log_element.scrollTop = log_ids[log_id];
}
}
}
// 下载日志
function download_dial_log()
{
// 获取启用的标签名
var enable_element=get_enable_element(tab_menu);
var enable_tab=enable_element.getAttribute("data-tab");
var enable_tab_name=enable_tab.replace("_tab","");
// 获取拨号日志
var log_element=document.getElementById(enable_tab_name+"_log");
var log=log_element.value
// 创建下载链接
var file = new Blob([log], {type: 'text/plain'});
var fileURL = URL.createObjectURL(file);
// 创建超链接并触发点击
var download_link = document.createElement("a");
download_link.href = fileURL;
download_link.download = enable_tab_name+"_dial_log.txt";
download_link.click();
}
// 清理拨号日志
function clean_dial_log()
{
// 获取启用的标签名
var enable_element=get_enable_element(tab_menu);
var enable_tab=enable_element.getAttribute("data-tab");
var enable_tab_name=enable_tab.replace("_tab","");
// 清空页面拨号日志
var log_element=document.getElementById(enable_tab_name+"_log");
log_element.value="";
// 获取拨号日志路径
var path="/tmp/run/modem/"+enable_tab_name+"_dial.cache";
// 清空文件拨号日志
XHR.get('<%=luci.dispatcher.build_url("admin", "network", "modem", "clean_dial_log")%>', {"path":path},
function(x, data)
{
// console.log(data);
}
);
}
XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "network", "modem", "get_dial_log_info")%>', null,
function(x, data)
{
var dial_log_info=data["dial_log_info"];
var modem_name_info=data["modem_name_info"];
var translation=data["translation"];
var tab_menu=document.getElementById("tab_menu");
var dial_log_div=document.getElementById('dial_log_view');
if (Object.keys(dial_log_info).length!=0)
{
// 新添加标签或覆盖标签
var tab_view = "";
var dial_log_view = "";
var log_ids={};
var enable_tab_name_cache=""; // 缓存已启用标签名
for (var dial_log of dial_log_info)
{
//遍历拨号日志的信息
for ( var key in dial_log)
{
var class_name="cbi-tab-disabled";
var active="false";
var display="none";
var log_style="";
if (tab_menu.hasChildNodes())
{
// 获取启用的标签元素
var enable_element=get_enable_element(tab_menu);
// 设置启用的标签为上一次的启用标签
enable_tab=enable_element.getAttribute("data-tab");
enable_tab_name_cache=enable_tab.replace("_tab","");
if (enable_tab_name_cache==key)
{
class_name="cbi-tab";
active="true";
display="block";
}
var log_element=document.getElementById(key+'_log');
if (log_element!=null)
{
// 设置样式
log_style=log_element.getAttribute("style");
// 判断日志是否更新
var log=log_element.value;
if (dial_log[key]!=log)
{
// 更新的移动滚动条到最下面
log_ids[key+'_log']=-1;
}
else
{
// 记录滚到条位置
log_ids[key+'_log']=log_element.scrollTop;
}
}
}
// 设置拨号日志标签
var modem_name=translation[modem_name_info[key]].toUpperCase();
tab_view+='<li class="'+class_name+'" data-tab="'+key+'_tab"><a>'+modem_name+' ('+key.replace("modem","")+')</a></li>';
// 设置拨号日志
dial_log_view += '<div class="cbi-section" data-tab="'+key+'_tab" data-tab-title="'+key+'" data-tab-active="'+active+'" style="display: '+display+';">';
dial_log_view += '<div><textarea readonly="readonly" id="'+key+'_log" rows="20" maxlength="160" style="'+log_style+'">'+dial_log[key]+'</textarea></div>';
dial_log_view += '</div>'
}
}
// 添加到页面中
tab_menu.innerHTML=tab_view;
dial_log_div.innerHTML=dial_log_view;
// 设置默认启用的标签(上次启用标签已删除)
var enable_element=document.getElementById(enable_tab_name_cache+"_log");
if (enable_element==null)
{
//设置启用的为第一个标签
enable_element=tab_menu.firstChild;
enable_element.classList.remove('cbi-tab-disabled');
enable_element.classList.add('cbi-tab');
enable_element=dial_log_div.firstChild;
enable_element.setAttribute('data-tab-active','true');
enable_element.style.display="block";
}
//设置滚动条
set_scroll_top(log_ids);
// 设置标签事件
set_tab_event();
// 显示拨号日志(标签、日志内容、滚动条、标签事件加载完成才显示)
document.getElementById("modem_dial_log_field").style.display="block";
}
else
{
var log_view="<strong><%:No dial log%></strong>";
dial_log_div.innerHTML=log_view;
// 隐藏拨号日志
document.getElementById("modem_dial_log_field").style.display="none";
}
}
);
//]]>
</script>
<style type="text/css">
/* AT命令响应 */
textarea {
background:#373737;
border:none;
color:#FFF;
width: 100%;
border-top-width: 2px;
padding-top: 12px;
}
</style>
<fieldset id="modem_dial_log_field" class="cbi-section" style="display: none;">
<div class="cbi-section fade-in">
<!-- <legend><%:Dial Log%></legend> -->
<h3 id="dial_log_title"><%:Dial Log%></h3>
</div>
<!-- <div id="response_label"><%:Response%></div><br/> -->
<table class="table" id="at_command_info">
<tbody>
<tr class="tr">
<td colspan="2" class="td left">
<ul class="cbi-tabmenu" id="tab_menu"></ul>
<div id="dial_log_view">
<!-- <div class="cbi-section" data-tab="modem0_tab" data-tab-title="<%:Modem0%>" data-tab-active="true" style="display: block;">
<div><textarea readonly="readonly" id="response" rows="20" maxlength="160"></textarea></div>
</div> -->
</div>
<div class="cbi-page-actions">
<input class="btn cbi-button cbi-button-link" type="button" value="<%:Download Log%>" onclick="download_dial_log()" alt="<%:Download Log%>" title="<%:Download Log%>">
<input class="cbi-button cbi-button-reset" type="button" value="<%:Clean%>" onclick="clean_dial_log()" alt="<%:Clean%>" title="<%:Clean%>">
</div>
</td>
</tr>
</tbody>
</table>
</fieldset>
@@ -0,0 +1,950 @@
<%+header%>
<%
local fs = require "nixio.fs"
local uci = luci.model.uci.cursor()
nosms = 1
if not fs.stat("/etc/nosim") then
nosms = 0
end
havegps = 0
if fs.stat("/etc/havegps") then
havegps = 1
end
%>
<style>
g {color:grey; font-size:75%; vertical-align: super;}
/*移动端显示优化*/
/* @media (max-width: 768px) {
tr td:first-child {
width: 30%;
}
} */
/* 消息样式 */
#info_message {
text-align: left;
font-size: 1.8em;
}
#info_message img {
vertical-align: middle;
}
#info_message a {
color: rgb(61, 143, 173);
font-size: 50%;
}
/* 信号样式 */
.signal-view {
position: relative;
min-width: 11rem;
height: 1.5rem;
margin: 0 0;
border: thin solid #999;
background: #eee;
border-radius: 4px;
overflow: hidden;
}
/* 信号百分比样式 */
.signal-percent {
width: 0;
height: 100%;
/* transition: width .25s ease-in; */
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
/* border-top-right-radius: 4px;
border-bottom-right-radius: 4px; */
}
/* 信号文字内容样式 */
.signal-context{
font-family: monospace;
/* font-size: 1em; */
font-weight: bold;
font-size-adjust: .38;
line-height: 1.5rem;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: hidden;
content: attr(title);
text-align: center;
white-space: pre;
text-overflow: ellipsis;
/* color:#000000; */
}
.signal-context small{
font-family: monospace;
/* font-size: 1em; */
font-weight: bold;
font-size-adjust: .38;
line-height: 1.5rem;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: hidden;
content: attr(title);
text-align: center;
white-space: pre;
text-overflow: ellipsis;
/* color:#000000; */
}
table {
width: 100%;
border-spacing: 10px;
border: 0px;
}
tr td:first-child {
width: 33%;
}
/* 清除表格标题的样式 */
/* caption {
all: unset;
} */
</style>
<script type="text/javascript" src="<%=resource%>/xhr.js"></script>
<script type="text/javascript">//<![CDATA[
window.onload=function()
{
//获取模组选择框元素
var modem_select = document.getElementById('modem_select');
//更换模组(AT串口)时触发
modem_select.addEventListener('change', function() {
//更新数据
update();
});
}
//获取SIM卡信息视图
function get_rate_view(rate)
{
const b=parseFloat(rate);
const kb=b/1024;
const mb=kb/1024;
var rate_view;
if (mb>=1) {
rate_view=mb.toFixed(2)+" MB/s";
}
else if (kb>=1) {
rate_view=kb.toFixed(2)+" KB/s";
}
else {
rate_view=b+" B/s";
}
return rate_view;
}
//获取SIM卡信息视图
function get_sim_info_view(sim_info,translation)
{
//初始化视图
var sim_info_view='';
//遍历每一条信息
for (var info of sim_info)
{
//遍历每一条信息里的键
for (var key in info)
{
//跳过全名
if (key=="full_name")
{
continue;
}
//获取全名
var full_name=info["full_name"];
if (full_name==null)
{
full_name='';
}
//写入视图(不显示空的信息)
var value=info[key];
if (value!="-"&&value!=""&&value!="ready")
{
// value=translation[value]; //是否翻译
sim_info_view+='<tr class="tr"><td class="td left" title="'+full_name+'">'+translation[key]+'</td><td class="td left" id="'+key+'">'+value+'</td></tr>';
break;
}
}
}
return sim_info_view;
}
//设置SIM卡信息
function set_sim_info(sim_info,translation)
{
//获取SIM卡信息视图
var sim_info_view=get_sim_info_view(sim_info,translation);
//获取SIM卡信息表格
var sim_info_Element=document.getElementById("sim_info");
sim_info_Element.innerHTML=sim_info_view;
}
//获取网络信息视图
function get_network_info_view(network_info,translation)
{
//初始化视图
var network_info_view='';
//遍历每一条信息
for (var info of network_info)
{
//遍历每一条信息里的键
for (var key in info)
{
//跳过全名
if (key=="full_name")
{
continue;
}
//获取全名
var full_name=info["full_name"];
if (full_name==null)
{
full_name='';
}
//写入视图(不显示空的信息)
var value=info[key];
if (value!="-"&&value!="")
{
//添加单位
if (key=="AMBR UL"||key=="AMBR DL") {
value=value+" Mbps";
}
else if (key=="Tx Rate"||key=="Rx Rate")
{
value=get_rate_view(value);
}
// value=translation[value]; //是否翻译
network_info_view+='<tr class="tr"><td class="td left" title="'+full_name+'">'+translation[key]+'</td><td class="td left" id="'+key+'">'+value+'</td></tr>';
break;
}
}
}
return network_info_view;
}
//设置网络信息
function set_network_info(network_info,translation)
{
//获取网络信息视图
var network_info_view=get_network_info_view(network_info,translation);
//获取网络信息表格
var network_info_Element=document.getElementById("network_info");
network_info_Element.innerHTML=network_info_view;
}
// 获取一个范围的百分比
function get_percent(value, min, max)
{
var percent;
if (value <= min) {
percent=0;
} else if (value >= max) {
percent=100;
} else {
percent=((value - min) / (max - min)) * 100;
}
return percent.toFixed(2);
}
// 获取参考信号的信息视图
function get_signal_info_view(network_type,key,value) {
value=parseFloat(value);
var signal_info_view={percent:100,quality:"Unknown",style:"width:100.00%;background-color: gray;"};
// 获取参考信号接收功率(RSRP)的信息视图'
if (key=="RSRP") {
set_rsrp_info_view(network_type,value,signal_info_view);
}
else if (key=="RSRQ") {
set_rsrq_info_view(network_type,value,signal_info_view);
}
else if (key=="SINR") {
set_sinr_info_view(network_type,value,signal_info_view);
}
else if (key=="RxLev") {
set_rxlev_info_view(network_type,value,signal_info_view);
}
//添加100%时候的样式
if (signal_info_view.percent==100) {
signal_info_view.style+="border-top-right-radius: 4px;border-bottom-right-radius: 4px;";
}
return signal_info_view;
}
// 获取参考信号接收功率(RSRP)的信息视图
function set_rsrp_info_view(network_type,value,signal_info_view)
{
// 获取百分比
if (network_type.includes("NR"))
{
signal_info_view.percent=get_percent(value,-153,31);
}
else if (network_type.includes("LTE"))
{
signal_info_view.percent=get_percent(value,-140,-44);
}
else if (network_type.includes("WCDMA"))
{
// signal_info_view.percent=get_percent(value,-140,-44);
}
// 获取样式
var color="gray";
if (value>=-70)
{
signal_info_view.quality="Excellent";
color="limegreen";
}
else if (value>=-80&&value<-70)
{
signal_info_view.quality="Good";
color="lime";
}
else if (value>=-90&&value<-80)
{
signal_info_view.quality="Fair";
color="gold";
}
else if (value<-90)
{
signal_info_view.quality="Bad";
color="red";
}
signal_info_view.style='width:'+signal_info_view.percent+'%;background-color: '+color+';';
}
// 获取参考信号接收质量(RSRQ)的信息视图
function set_rsrq_info_view(network_type,value,signal_info_view)
{
// 获取百分比
if (network_type.includes("NR"))
{
signal_info_view.percent=get_percent(value,-43,20);
}
else if (network_type.includes("LTE"))
{
signal_info_view.percent=get_percent(value,-19.5,-3);
}
else if (network_type.includes("WCDMA"))
{
// signal_info_view.percent=get_percent(value,-19.5,-3);
}
// 获取样式
var color="gray";
if (value>=-10)
{
signal_info_view.quality="Excellent";
color="limegreen";
}
else if (value>=-15&&value<-10)
{
signal_info_view.quality="Good";
color="lime";
}
else if (value>=-20&&value<-15)
{
signal_info_view.quality="Fair";
color="gold";
}
else if (value<-20)
{
signal_info_view.quality="Bad";
color="red";
}
signal_info_view.style='width:'+signal_info_view.percent+'%;background-color: '+color+';';
}
// 获取信噪比(SINR)的信息视图
function set_sinr_info_view(network_type,value,signal_info_view)
{
// 获取百分比
if (network_type.includes("NR"))
{
signal_info_view.percent=get_percent(value,-23,40);
}
else if (network_type.includes("LTE"))
{
signal_info_view.percent=get_percent(value,-20,-30);
}
else if (network_type.includes("WCDMA"))
{
// signal_info_view.percent=get_percent(value,-20,-30);
}
// 获取样式
var color="gray";
if (value>=25)
{
signal_info_view.quality="Excellent";
color="limegreen";
}
else if (value>=15&&value<25)
{
signal_info_view.quality="Good";
color="lime";
}
else if (value>=10&&value<15)
{
signal_info_view.quality="Fair";
color="gold";
}
else if (value<10)
{
signal_info_view.quality="Bad";
color="red";
}
signal_info_view.style='width:'+signal_info_view.percent+'%;background-color: '+color+';';
}
// 获取接收信号功率(RxLev)的信息视图
function set_rxlev_info_view(network_type,value,signal_info_view)
{
// 获取百分比
if (network_type.includes("NR"))
{
signal_info_view.percent=get_percent(value,-153,31);
}
else if (network_type.includes("LTE"))
{
signal_info_view.percent=get_percent(value,-140,-44);
}
else if (network_type.includes("WCDMA"))
{
signal_info_view.percent=get_percent(value,-120,-25);
}
else if (network_type.includes("GSM"))
{
signal_info_view.percent=get_percent(value,-110,-48);
}
// 获取样式
var color="gray";
if (value>=-70)
{
signal_info_view.quality="Excellent";
color="limegreen";
}
else if (value>=-80&&value<-70)
{
signal_info_view.quality="Good";
color="lime";
}
else if (value>=-90&&value<-80)
{
signal_info_view.quality="Fair";
color="gold";
}
else if (value<-90)
{
signal_info_view.quality="Bad";
color="red";
}
signal_info_view.style='width:'+signal_info_view.percent+'%;background-color: '+color+';';
}
//获取小区信息视图
function get_cell_info_view(network_mode_info,network_type,translation)
{
//初始化视图
var cell_info_view='';
//遍历每一条信息
for (var info of network_mode_info)
{
//遍历每一条信息里的键
for (var key in info)
{
//跳过全名
if (key=="full_name")
{
continue;
}
//获取全名
var full_name=info["full_name"];
if (full_name==null)
{
full_name='';
}
//写入视图(不显示空的信息)
var value=info[key];
if (value!="-"&&value!="")
{
//添加单位
if (key=="Band") {
if (network_type.includes("NR")) {
value="N"+value;
}
else if (network_type.includes("LTE")) {
value="B"+value;
}
else if (network_type.includes("WCDMA")) {
value="B"+value;
}
}
else if (key=="UL Bandwidth"||key=="DL Bandwidth") {
value=value+" MHz";
}
else if (key=="RSRP"||key=="TX Power"||key=="RxLev") {
if (key=="RSRP")
{
var unit="dBm";
var signal_info_view=get_signal_info_view(network_type,"RSRP",value);
// value='<div class="cbi-progressbar" title="'+value+' dBm | '+translation[signal_info_view.quality]+' ('+signal_info_view.percent+'%)"><div style="'+signal_info_view.style+'"></div></div>';
value='<div class="signal-view"><div class="signal-percent" style="'+signal_info_view.style+'"><div class="signal-context"><small title="'+value+' '+unit+' | '+translation[signal_info_view.quality]+' ('+signal_info_view.percent+'%)"><div style="'+signal_info_view.style+'">'+value+' dB | '+translation[signal_info_view.quality]+' ('+signal_info_view.percent+'%)</small></div></div></div>';
}
else if (key=="RxLev")
{
var unit="dBm";
var signal_info_view=get_signal_info_view(network_type,"RxLev",value);
value='<div class="signal-view"><div class="signal-percent" style="'+signal_info_view.style+'"><div class="signal-context"><small title="'+value+' '+unit+' | '+translation[signal_info_view.quality]+' ('+signal_info_view.percent+'%)"><div style="'+signal_info_view.style+'">'+value+' dB | '+translation[signal_info_view.quality]+' ('+signal_info_view.percent+'%)</small></div></div></div>';
}
else
{
value=value+" dBm";
}
}
else if (key=="RSRQ"||key=="SINR"||key=="RSSNR"||key=="Srxlev"||key=="Ec/Io") {
if (key=="RSRQ")
{
var unit="dB";
var signal_info_view=get_signal_info_view(network_type,"RSRQ",value);
value='<div class="signal-view"><div class="signal-percent" style="'+signal_info_view.style+'"><div class="signal-context"><small title="'+value+' '+unit+' | '+translation[signal_info_view.quality]+' ('+signal_info_view.percent+'%)"><div style="'+signal_info_view.style+'">'+value+' dB | '+translation[signal_info_view.quality]+' ('+signal_info_view.percent+'%)</small></div></div></div>';
}
else if (key=="SINR")
{
var unit="dB";
var signal_info_view=get_signal_info_view(network_type,"SINR",value);
value='<div class="signal-view"><div class="signal-percent" style="'+signal_info_view.style+'"><div class="signal-context"><small title="'+value+' '+unit+' | '+translation[signal_info_view.quality]+' ('+signal_info_view.percent+'%)"><div style="'+signal_info_view.style+'">'+value+' dB | '+translation[signal_info_view.quality]+' ('+signal_info_view.percent+'%)</small></div></div></div>';
}
else
{
value=value+" dB";
}
}
else if (key=="SCS") {
value=value+" kHz";
}
cell_info_view+='<tr class="tr"><td class="td left" title="'+full_name+'">'+translation[key]+'</td><td class="td left" id="'+key+'">'+value+'</td></tr>';
break;
}
}
}
return cell_info_view;
}
//设置小区信息
function set_cell_info(cell_info,translation)
{
//获取网络模式
var network_mode=Object.keys(cell_info)[0];
//获取视图
var cell_info_view='<caption>'+translation[network_mode]+'</caption>'; //网络模式视图
// var cell_info_view='<tr class="tr"><td class="td center" colspan="2">'+translation[network_mode]+'</td></tr>'; //网络模式视图
//获取网络模式下的信息
var network_mode_info=cell_info[network_mode];
if (network_mode=="EN-DC Mode")
{
var lte=network_mode_info[0]["LTE"];
cell_info_view+='<tr class="tr"><td class="td left" colspan="2">LTE</td></tr>';
cell_info_view+=get_cell_info_view(lte,"LTE",translation);
var nsa=network_mode_info[1]["NR5G-NSA"];
cell_info_view+='<tr class="tr"><td class="td left" colspan="2">NR5G-NSA</td></tr>';
cell_info_view+=get_cell_info_view(nsa,"NR",translation);
}
else
{
// cell_info_view+='<tr><td colspan="3">NR5G-NSA</td></tr>';
cell_info_view+=get_cell_info_view(network_mode_info,network_mode,translation);
}
//获取表格
var cell_info_Element=document.getElementById("cell_info");
cell_info_Element.innerHTML=cell_info_view;
}
//显示信息
function set_info(info)
{
for (var key in info)
{
var info_Element=document.getElementById(key);
if (info_Element!=null)
{
info_Element.innerHTML=info[key];
}
}
}
//基本信息界面
function base_info_view(manufacturer)
{
if (manufacturer!="unknown")
{
// 隐藏提示信息
document.getElementById("cbi-info").style.display="none";
// 显示基本信息
document.getElementById("cbi-baseinfo").style.display="block";
}
else //未适配模组
{
// 更新提示信息
document.getElementById("info_message").innerHTML='<strong><%:Not adapted to this modem%></strong> <a href="https://github.com/Siriling/5G-Modem-Support/blob/main/luci-app-modem/README.md" target="_blank"><%:(Check adapted modem)%></a>';
// 显示提示信息
document.getElementById("cbi-info").style.display="block";
// 显示基本信息
document.getElementById("cbi-baseinfo").style.display="block";
// 隐藏SIM卡信息
document.getElementById("cbi-siminfo").style.display="none";
// 隐藏网络信息
document.getElementById("cbi-networkinfo").style.display="none";
// 隐藏小区信息
document.getElementById("cbi-cellinfo").style.display="none";
}
}
//SIM卡信息界面
function sim_info_view(sim_status,connect_status)
{
//SIM卡状态未知
if (sim_status=="unknown")
{
// 更新提示信息
document.getElementById("info_message").innerHTML="<strong><%:Unknown SIM card status%></strong>";
// 显示提示信息
document.getElementById("cbi-info").style.display="block";
// 显示SIM卡信息
document.getElementById("cbi-siminfo").style.display="block";
}
//未插入SIM卡
else if (sim_status=="miss")
{
// 更新提示信息
document.getElementById("info_message").innerHTML="<strong><%:SIM card not inserted%></strong>";
// 显示提示信息
document.getElementById("cbi-info").style.display="block";
// 显示SIM卡信息
document.getElementById("cbi-siminfo").style.display="block";
}
//SIM卡就绪
else if (sim_status=="ready")
{
// 隐藏提示信息
document.getElementById("cbi-info").style.display="none";
// 显示SIM卡信息
document.getElementById("cbi-siminfo").style.display="block";
}
//SIM卡其他状态(锁定等)
else
{
// 更新提示信息
document.getElementById("info_message").innerHTML="<strong>"+sim_status+"</strong>";
// 显示提示信息
document.getElementById("cbi-info").style.display="block";
// 显示SIM卡信息
document.getElementById("cbi-siminfo").style.display="block";
}
//SIM卡未准备或网络未连接
if (sim_status!="ready"||connect_status!="connect")
{
// 隐藏网络信息
document.getElementById("cbi-networkinfo").style.display="none";
// 隐藏小区信息
document.getElementById("cbi-cellinfo").style.display="none";
}
}
//网络信息界面和小区信息界面
function network_info_view(connect_status)
{
//已连接
if (connect_status=="connect")
{
// 显示网络信息
document.getElementById("cbi-networkinfo").style.display="block";
// 显示小区信息
document.getElementById("cbi-cellinfo").style.display="block";
}
//未连接
else
{
// 隐藏网络信息
document.getElementById("cbi-networkinfo").style.display="none";
// 隐藏小区信息
document.getElementById("cbi-cellinfo").style.display="none";
}
}
// 更新模组信息
function update()
{
//获取选中的AT串口
var at_port=modem_select.options[modem_select.selectedIndex].value;
//获取模组信息
XHR.get('<%=luci.dispatcher.build_url("admin", "network", "modem", "get_modem_info")%>', {"port":at_port},
function(x, data)
{
console.log(data);
var modem_info=data["modem_info"];
var translation=data["translation"];
// 设备信息
var device_info=modem_info["device_info"];
set_info(device_info);
// 更多信息
var more_info=modem_info["more_info"];
//基本信息
var base_info=more_info["base_info"];
set_info(base_info);
//基本信息界面控制
base_info_view(base_info["manufacturer"]);
//未适配模组
if (base_info["manufacturer"]=="unknown") {
return
}
//SIM卡信息
var sim_info=more_info["sim_info"];
set_sim_info(sim_info,translation);
//SIM卡信息显示控制
var sim_status=sim_info[0]["SIM Status"];
sim_info_view(sim_status,device_info["connect_status"]);
//SIM卡未插入或SIM卡被锁定
if (sim_status!="ready"||device_info["connect_status"]!="connect") {
return
}
//网络信息
var network_info=more_info["network_info"];
set_network_info(network_info,translation);
//小区信息
var cell_info=more_info["cell_info"];
set_cell_info(cell_info,translation);
//网络信息和小区信息界面显示控制
network_info_view(device_info["connect_status"]);
}
);
}
// 设置AT串口选项
function set_at_port(at_ports,translation)
{
//获取模块选择框元素
var modem_select = document.getElementById('modem_select');
// 记录所选
var selected=modem_select.value;
// 删除原来的选项
modem_select.options.length=0;
//遍历每一个AT串口
for (var port of at_ports)
{
//更新(key:AT串口,value:模块名称)
for (var key in port)
{
var option = document.createElement('option');
option.value = key;
var language=navigator.language;
if (port[key].includes("unknown"))
{
option.text = translation[port[key]];
}
else
{
option.text = port[key];
}
modem_select.appendChild(option);
}
}
// 恢复原来的选择
for (let i = 0; i < modem_select.options.length; i++)
{
if(modem_select.options[i].value == selected)
{
modem_select.selectedIndex=i;
break;
}
}
}
// 定时触发更新AT串口和模组数据
XHR.poll(5,'<%=luci.dispatcher.build_url("admin", "network", "modem", "get_at_port")%>', null,
function(x, data)
{
var at_ports=data["at_ports"];
var translation=data["translation"];
//设置AT串口选项
set_at_port(at_ports,translation);
//更新模组信息
if (Object.keys(at_ports).length==0)
{
no_modems_view();
}
else
{
update();
}
}
);
//无模组界面
function no_modems_view()
{
// 更新提示信息
document.getElementById("info_message").innerHTML='<strong><%:No modems found%></strong> <a href="https://blog.siriling.com:1212/2023/03/18/openwrt-5g-modem/#zi-dong-sao-miao-shi-bie-gong-neng" target="_blank"><%:(Check the reason)%></a>';
// 显示提示信息
document.getElementById("cbi-info").style.display="block";
// 隐藏基本信息
document.getElementById("cbi-baseinfo").style.display="none";
// 隐藏SIM卡信息
document.getElementById("cbi-siminfo").style.display="none";
// 隐藏网络信息
document.getElementById("cbi-networkinfo").style.display="none";
// 隐藏小区信息
document.getElementById("cbi-cellinfo").style.display="none";
}
//]]>
</script>
<div class="cbi-map" id="cbi-modem">
<h2 name="content"><%:Modem Information%></h2>
<div class="cbi-map-descr"><%:Check the information of the adapted modem%></div>
<fieldset class="cbi-section" id="cbi-info" style="display: block;">
<div class="cbi-section fade-in">
<h3><%:Message%></h3>
<table class="table">
<tbody id="message">
<tr class="tr">
<td class="td left">
<div id="info_message">
<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>"/>
<%:Loading modem information%>...
</div>
</td>
<td class="td left"></td>
</tr>
</tbody>
</table>
</div>
</fieldset>
<fieldset class="cbi-section" id="cbi-baseinfo" style="display: none;">
<div class="cbi-section fade-in">
<h3><%:Base Information%></h3>
<table class="table" id="base_info">
<tbody>
<tr class="tr">
<td class="td left"><%:Modem Name%></td>
<td class="td left" id="modem_name">
<select name="modem_select" id="modem_select"></select>
</td>
</tr>
<tr class="tr"><td class="td left"><%:Manufacturer%></td><td class="td left" id="manufacturer"></td></tr>
<tr class="tr"><td class="td left"><%:Revision%></td><td class="td left" id="revision"></td></tr>
<tr class="tr"><td class="td left"><%:Data Interface%></td><td class="td left" id="data_interface"></td></tr>
<tr class="tr"><td class="td left"><%:Network Driver%></td><td class="td left" id="net_driver"></td></tr>
<tr class="tr"><td class="td left"><%:Mode%></td><td class="td left" id="mode"></td></tr>
<tr class="tr"><td class="td left"><%:AT Port%></td><td class="td left" id="at_port"></td></tr>
<tr class="tr"><td class="td left"><%:Mobile Network%></td><td class="td left" id="network"></td></tr>
<tr class="tr"><td class="td left"><%:Temperature%></td><td class="td left" id="temperature"></td></tr>
<tr class="tr"><td class="td left"><%:Update Time%></td><td class="td left" id="update_time"></td></tr>
</tbody>
</table>
</div>
</fieldset>
<% if nosms == 0 then %>
<% end %>
<fieldset class="cbi-section" id="cbi-siminfo" style="display: none;">
<div class="cbi-section fade-in">
<h3><%:SIM Information%></h3>
<table class="table" id="sim_info"></table>
</div>
</fieldset>
<fieldset class="cbi-section" id="cbi-networkinfo" style="display: none;">
<div class="cbi-section fade-in">
<h3><%:Network Information%></h3>
<table id="network_info" class="table"></table>
</div>
</fieldset>
<fieldset class="cbi-section" id="cbi-cellinfo" style="display: none;">
<div class="cbi-section fade-in">
<h3><%:Cell Information%></h3>
<table class="table" id="cell_info"></table>
</div>
</fieldset>
<!-- <fieldset class="cbi-section" id="cbi-stationinfo" style="display: none;">
<h3><%:基站信息%></h3>
<table width="100%" cellspacing="10">
<tr><td width="20%"><%:MCC/MNC 国家码/网络码 %> :</td><td id="mcc"></td><td id="mnc"></td></tr>
<tr><td width="20%"><%:eNB ID : %></td><td><ul><span id="rnc" class="r"></span><span id="rncn" class="r"></span></ul></td><td></td></tr>
<tr><td width="20%"><%:TAC : %></td><td><ul><span id="lac" class="r"></span><span id="lacn" class="r"></span></ul></td><td></td></tr>
<tr><td width="20%"><%:Cell ID : %></td><td><ul><span id="cid" class="r"></span><span id="cidn" class="r"></span></ul></td><td></td></tr>
<tr><td width="20%"><%:Band 频段 : %></td><td id="lband"></td><td></td></tr>
<tr><td width="20%"><%:Channel 频点 : %></td><td id="channel"></td><td></td></tr>
<tr><td width="20%"><%:PCI 物理小区标识 : %></td><td id="pci"></td><td></td></tr>
<tr><td width="20%"><%:Maximum Qos 最大Qos级别 : %></td><td><ul><span id="down" class="r"></span><span id="up" class="r"></span></ul></td><td></td></tr>
</table>
</fieldset> -->
<% if havegps == 1 then %>
<!-- <fieldset class="cbi-section" id="cbi-gpsinfo">
<h3><%:GPS 定位%></h3>
<table>
<tr>
<td width="30%"><div align="right"><%:纬度 %> :</div></td>
<td><ul id="lat"></ul></td>
<td width="1%">&nbsp;</td>
</tr>
<tr>
<td><div align="right"><%:经度 %> :</div></td>
<td><ul id="long"></ul></td>
<td>&nbsp;</td>
</tr>
</table>
</fieldset> -->
<% end %>
</div>
<%+footer%>
@@ -0,0 +1,51 @@
<%+cbi/valueheader%>
<script type="text/javascript">//<![CDATA[
// 禁用功能
function disabled_function(function_name,status)
{
//模组扫描
if (function_name=="modem_scan")
{
//模组扫描按钮
document.getElementById('modem_scan_button').disabled=status;
}
}
// 模组扫描
function modem_scan()
{
//禁用功能
disabled_function("modem_scan",true);
//修改描述信息
var description='<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>"/><%:Scaning modem...%>'
document.getElementById('modem_scan_description').innerHTML=description;
XHR.get('<%=luci.dispatcher.build_url("admin", "network", "modem", "modem_scan")%>', null,
function(x, data)
{
// console.log(data);
location.href='/cgi-bin/luci/admin/network/modem/plugin_config'
//启用功能
// disabled_function("modem_scan",false);
}
);
}
//]]>
</script>
<style type="text/css">
/* 加载中样式 */
#modem_scan_description img {
vertical-align: middle;
}
</style>
<input class="btn cbi-button cbi-button-apply" type="button" id="modem_scan_button" value="<%:Scan%>" onclick="modem_scan()" alt="<%:Scan%>" title="<%:Scan%>"/>
<div class="cbi-value-description" id="modem_scan_description">
<%:The automatic configuration modem is triggered only at modem startup, otherwise, manual scanning is necessary%>
</div>
<%+cbi/valuefooter%>
@@ -0,0 +1,160 @@
<script type="text/javascript">//<![CDATA[
XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "network", "modem", "get_modems")%>', null,
function(x, data)
{
var modems=data["modems"];
var translation=data["translation"];
var modems_div=document.getElementById('modem_status_view');
if (Object.keys(modems).length!=0)
{
var modem_view = "";
//遍历每一个模组
for (var modem of modems)
{
//遍历模组里面的信息
for ( var key in modem)
{
var modem=modem[key];
var language=navigator.language;
// 检查模组名
var name=modem["name"];
if (name==null)
{
continue;
}
else if (name=="unknown")
{
language=="en" ? name=name.toUpperCase() : name=translation[name];
}
else
{
name=name.toUpperCase();
}
// 检查拨号模式
var mode=modem["mode"]
if (mode==null)
{
continue;
}
else if (mode=="unknown")
{
language=="en" ? mode=mode.toUpperCase() : mode=translation[mode];
}
else
{
mode=mode.toUpperCase();
}
// 获取连接状态
var connect_status=modem["connect_status"];
if (modem["connect_status"]!=null)
{
if (language=="en") {
// 首字母大写
connect_status=connect_status.charAt(0).toUpperCase() + modem["connect_status"].slice(1);
}
else if (language=="zh-CN"||language=="zh") {
connect_status=translation[connect_status];
}
}
// 设置显示样式
var state = '';
var css = '';
switch (modem["connect_status"])
{
case 'connect':
state = '<%:Connect%>';
css = 'success';
break;
case 'disconnect':
state = '<%:Disconnect%>';
css = 'danger';
break;
default:
state = '<%:unknown%>';
css = 'warning';
break;
}
// 设置显示内容
modem_view += String.format(
'<div class="alert-message %s">',
css
);
modem_view += String.format(
'<div><strong>No: </strong>%s</div>',
modem[".name"].slice(-1)
);
modem_view += String.format(
'<div><strong><%:Modem Name%>: </strong>%s</div>',
name
);
modem_view += String.format(
'<div><strong><%:Data Interface%>: </strong>%s</div>',
modem.data_interface.toUpperCase()
);
modem_view += String.format(
'<div><strong><%:Mode%>: </strong>%s</div>',
mode
);
modem_view += String.format(
'<div><strong><%:Mobile Network%>: </strong>%s</div>',
modem.network
);
modem_view += String.format(
'<div><strong><%:Connect Status%>: </strong>%s</div>',
connect_status
);
modem_view += '</div>';
}
}
// 有参数不存在,则不显示模块状态
if (modem_view != "")
{
modems_div.innerHTML=modem_view;
// 显示模块状态(状态加载完成才显示)
document.getElementById("modem_status_field").style.display="block";
}
}
else
{
var modem_view="<strong><%:No modems found%></strong>";
modems_div.innerHTML=modem_view;
// 隐藏模块状态
document.getElementById("modem_status_field").style.display="none";
}
}
);
//]]>
</script>
<style type="text/css">
/* 加载中样式 */
#modem_status_view img {
vertical-align: middle;
}
#modem_status_view > div {
display: inline-block;
margin: 1rem;
padding: 1rem;
width: 15rem;
float: left;
line-height: 125%;
}
</style>
<!-- 默认隐藏模块状态 -->
<fieldset id="modem_status_field" class="cbi-section" style="display: none;">
<!-- <legend><%:Modem Status%></legend> -->
<h3><%:Modem Status%></h3>
<div id="modem_status_view">
<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>"/>
<%:Loading modem status%>...
</div>
</fieldset>
@@ -0,0 +1,335 @@
<%+header%>
<script type="text/javascript" src="<%=resource%>/xhr.js"></script>
<script type="text/javascript">//<![CDATA[
// 设置状态页面
function set_status_view(status,status_element,translation)
{
if (status=="Loaded") {
status_element.style.color = "green";
}
else if (status=="Not loaded") {
status_element.style.color = "red";
}
status_element.innerHTML=translation[status];
}
// 设置状态
function set_status(info,translation)
{
//遍历信息里面的内核模块
for (var model in info)
{
//获取状态元素
var status_element=document.getElementById(model.toLowerCase().replace(".ko","_status"));
// 设置状态页面
set_status_view(info[model],status_element,translation);
}
}
// 设置版本
function set_version(info,translation)
{
//遍历信息里面的插件版本
for (var plugin in info)
{
//获取版本元素
var version_element=document.getElementById(plugin+"_version");
if (info[plugin]=="Unknown") {
version_element.innerHTML=translation[info[plugin]];
version_element.style.color = "goldenrod";
}
else if (info[plugin]=="Not installed") {
version_element.innerHTML=translation[info[plugin]];
version_element.style.color = "red";
}
else
{
version_element.innerHTML="v"+info[plugin];
version_element.style.color = "green";
}
}
}
XHR.get('<%=luci.dispatcher.build_url("admin", "network", "modem", "get_plugin_info")%>', {},
function(x, data)
{
// 获取翻译
var translation=data["translation"];
// 获取插件信息
var plugin_info=data["plugin_info"];
set_version(plugin_info,translation);
// 获取拨号工具信息
var dial_tool_info=data["dial_tool_info"];
set_version(dial_tool_info,translation);
// 设置通用驱动信息的状态
var general_driver_info=data["general_driver_info"];
set_status(general_driver_info,translation);
// 设置模组USB驱动信息的状态
var usb_driver_info=data["usb_driver_info"];
set_status(usb_driver_info,translation);
// 设置模组PCI驱动信息的状态
var pci_driver_info=data["pci_driver_info"];
set_status(pci_driver_info,translation);
}
);
//]]>
</script>
<div class="cbi-map" id="cbi-modem-debug">
<h2 id="content" name="content"><%:Plugin Info%></h2>
<div class="cbi-map-descr"><%:Check the version information of the plugin%></div>
<head>
<style type="text/css">
div .version {
margin-top: 5px;
}
</style>
</head>
<fieldset class="cbi-section" id="cbi-modem" style="display: block;">
<div class="cbi-section fade-in">
<!-- <legend><%:Plugin Info%></legend> -->
<h3><%:Plugin Info%></h3>
<div class="cbi-section-node">
<div class="cbi-value cbi-value-last">
<label class="cbi-value-title"><%:Plugin Version%></label>
<div class="cbi-value-field">
<div class="version">
<strong id="luci-app-modem_version"></strong>
</div>
<!-- <div class="cbi-value-description">
<%:Select a modem for debugging%>
</div> -->
</div>
</div>
</div>
</div>
</fieldset>
<fieldset class="cbi-section" id="cbi-modem" style="display: block;">
<div class="cbi-section fade-in">
<!-- <legend><%:Dial Tool Info%></legend> -->
<h3><%:Dial Tool Info%></h3>
<div class="cbi-section-node">
<div class="cbi-value">
<label class="cbi-value-title">modemmanager <%:Version%></label>
<div class="cbi-value-field">
<div class="version">
<strong id="modemmanager_version"></strong>
</div>
<!-- <div class="cbi-value-description">
<%:Select a modem for debugging%>
</div> -->
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title">quectel-CM <%:Version%></label>
<div class="cbi-value-field">
<div class="version">
<strong id="quectel-cm_version"></strong>
</div>
<!-- <div class="cbi-value-description">
<%:Select a modem for debugging%>
</div> -->
</div>
</div>
<div class="cbi-value cbi-value-last">
<label class="cbi-value-title">fibocom-dial <%:Version%></label>
<div class="cbi-value-field">
<div class="version">
<strong id="fibocom-dial_version"></strong>
</div>
<!-- <div class="cbi-value-description">
<%:Select a modem for debugging%>
</div> -->
</div>
</div>
<div class="cbi-value cbi-value-last">
<label class="cbi-value-title">meig-cm <%:Version%></label>
<div class="cbi-value-field">
<div class="version">
<strong id="meig-cm_version"></strong>
</div>
<!-- <div class="cbi-value-description">
<%:Select a modem for debugging%>
</div> -->
</div>
</div>
</div>
</div>
</fieldset>
<fieldset class="cbi-section" id="cbi-modem" style="display: block;">
<div class="cbi-section fade-in">
<!-- <legend><%:Modem General Driver Info%></legend> -->
<h3><%:Modem General Driver Info%></h3>
<table class="table cbi-section-table">
<tbody>
<tr class="tr cbi-section-table-titles anonymous">
<th class="th cbi-section-table-cell"><%:Driver Type%></th>
<th class="th cbi-section-table-cell"><%:Kernel Model%></th>
<th class="th cbi-section-table-cell"><%:Status%></th>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-1">
<td class="td cbi-value-field" data-title="<%:Driver Type%>" id="usb_network"><%:USB Network%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="usb_net_kernel_model_name">usbnet.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="usbnet_status">-</td>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-2">
<td class="td cbi-value-field" data-title="<%:Driver Type%>" id="serial_port"><%:Serial Port%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="serial_port_kernel_model_name">option.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="option_status">-</td>
</tr>
<!-- <tr class="tr cbi-section-table-row cbi-rowstyle-2">
<td class="td cbi-value-field" data-title="<%:Driver Type%>" id="serial_port"><%:Serial Port%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="serial_port_kernel_model_name">qcserial.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="qcserial_status">-</td>
</tr> -->
</tbody>
</table>
</div>
</fieldset>
<fieldset class="cbi-section" id="cbi-modem" style="display: block;">
<div class="cbi-section fade-in">
<!-- <legend><%:Modem USB Driver Info%></legend> -->
<h3><%:Modem USB Driver Info%></h3>
<table class="table cbi-section-table">
<tbody>
<tr class="tr cbi-section-table-titles anonymous">
<th class="th cbi-section-table-cell"><%:Driver Type%></th>
<th class="th cbi-section-table-cell"><%:Mode%></th>
<th class="th cbi-section-table-cell"><%:Kernel Model%></th>
<th class="th cbi-section-table-cell"><%:Status%></th>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-1">
<td class="td cbi-value-field" data-title="<%:Driver Type%>" id="qmi_wwan"><%:General%></td>
<td class="td cbi-value-field" data-title="<%:Mode%>" id="qmi"><%:QMI%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="qmi_kernel_model_name">qmi_wwan.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="qmi_wwan_status">-</td>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-2">
<td class="td cbi-value-field" data-title="<%:Driver Type%>" id="gobinet"><%:General%></td>
<td class="td cbi-value-field" data-title="<%:Mode%>" id="gobinet"><%:GobiNet%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="gobinet_kernel_model_name">GobiNet.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="gobinet_status">-</td>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-1">
<td class="td cbi-value-field" data-title="<%:Driver Type%>" id="cdc_ether"><%:General%></td>
<td class="td cbi-value-field" data-title="<%:Mode%>" id="ecm"><%:ECM%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="ecm_kernel_model_name">cdc_ether.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="cdc_ether_status">-</td>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-2">
<td class="td cbi-value-field" data-title="<%:Driver Type%>" id="cdc_mbim"><%:General%></td>
<td class="td cbi-value-field" data-title="<%:Mode%>" id="mbim"><%:MBIM%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="mbim_kernel_model_name">cdc_mbim.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="cdc_mbim_status">-</td>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-1">
<td class="td cbi-value-field" data-title="<%:Driver Type%>" id="rndis_host"><%:General%></td>
<td class="td cbi-value-field" data-title="<%:Mode%>" id="rndis"><%:RNDIS%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="rndis_kernel_model_name">rndis_host.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="rndis_host_status">-</td>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-2">
<td class="td cbi-value-field" data-title="<%:Driver Type%>" id="cdc_ncm"><%:General%></td>
<td class="td cbi-value-field" data-title="<%:Mode%>" id="ecm"><%:NCM%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="ncm_kernel_model_name">cdc_ncm.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="cdc_ncm_status">-</td>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-1">
<td class="td cbi-value-field" data-title="<%:Driver Type%>"><%:Private (Quectel)%></td>
<td class="td cbi-value-field" data-title="<%:Mode%>"><%:QMI%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="qmi_wwan_q_kernel_model_name">qmi_wwan_q.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="qmi_wwan_q_status">-</td>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-2">
<td class="td cbi-value-field" data-title="<%:Driver Type%>"><%:Private (Fibocom)%></td>
<td class="td cbi-value-field" data-title="<%:Mode%>"><%:QMI%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="qmi_wwan_f_kernel_model_name">qmi_wwan_f.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="qmi_wwan_f_status">-</td>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-1">
<td class="td cbi-value-field" data-title="<%:Driver Type%>"><%:Private (Meig)%></td>
<td class="td cbi-value-field" data-title="<%:Mode%>"><%:QMI%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="qmi_wwan_m_kernel_model_name">qmi_wwan_m.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="qmi_wwan_m_status">-</td>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-2">
<td class="td cbi-value-field" data-title="<%:Driver Type%>"><%:Private (T&W)%></td>
<td class="td cbi-value-field" data-title="<%:Mode%>"><%:QMI%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="qmi_wwan_t_kernel_model_name">qmi_wwan_t.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="qmi_wwan_t_status">-</td>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-1">
<td class="td cbi-value-field" data-title="<%:Driver Type%>"><%:Private (Meig)%></td>
<td class="td cbi-value-field" data-title="<%:Mode%>"><%:NCM%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="meig_cdc_driver_kernel_model_name">meig_cdc_driver.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="meig_cdc_driver_status">-</td>
</tr>
</tbody>
</table>
</div>
</fieldset>
<fieldset class="cbi-section" id="cbi-modem" style="display: block;">
<div class="cbi-section fade-in">
<!-- <legend><%:Modem PCI Driver Info%></legend> -->
<h3><%:Modem PCI Driver Info%></h3>
<table class="table cbi-section-table">
<tbody>
<tr class="tr cbi-section-table-titles anonymous">
<th class="th cbi-section-table-cell"><%:Driver Type%></th>
<th class="th cbi-section-table-cell"><%:Kernel Model%></th>
<th class="th cbi-section-table-cell"><%:Status%></th>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-1">
<td class="td cbi-value-field" data-title="<%:Driver Type%>" id="mhi_net"><%:General%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="mhi_net_kernel_model_name">mhi_net.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="mhi_net_status">-</td>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-2">
<td class="td cbi-value-field" data-title="<%:Driver Type%>" id="qrtr_mhi"><%:General%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="qrtr_kernel_model_name">qrtr_mhi.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="qrtr_mhi_status">-</td>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-1">
<td class="td cbi-value-field" data-title="<%:Driver Type%>" id="mhi_pci_generic"><%:General%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="mhi_pci_kernel_model_name">mhi_pci_generic.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="mhi_pci_generic_status">-</td>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-2">
<td class="td cbi-value-field" data-title="<%:Driver Type%>" id="mhi_wwan_mbim"><%:General%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="mhi_mbim_kernel_model_name">mhi_wwan_mbim.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="mhi_wwan_mbim_status">-</td>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-1">
<td class="td cbi-value-field" data-title="<%:Driver Type%>" id="mhi_wwan_ctrl"><%:General%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="mhi_wwan_kernel_model_name">mhi_wwan_ctrl.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="mhi_wwan_ctrl_status">-</td>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-2">
<td class="td cbi-value-field" data-title="<%:Driver Type%>" id="private_q"><%:Private%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="pcie_mhi_kernel_model_name">pcie_mhi.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="pcie_mhi_status">-</td>
</tr>
<tr class="tr cbi-section-table-row cbi-rowstyle-1">
<td class="td cbi-value-field" data-title="<%:Driver Type%>" id="private_mtk"><%:Private%></td>
<td class="td cbi-value-field" data-title="<%:Kernel Model%>" id="mtk_pcie_wwan_m80_kernel_model_name">mtk_pcie_wwan_m80.ko</td>
<td class="td cbi-value-field" data-title="<%:Status%>" id="mtk_pcie_wwan_m80_status">-</td>
</tr>
</tbody>
</table>
</div>
</fieldset>
</div>
<%+footer%>
@@ -0,0 +1,3 @@
<%+cbi/valueheader%>
<font class="_status" hint="<%=self:cfgvalue(section)%>">--</font>
<%+cbi/valuefooter%>
@@ -0,0 +1,203 @@
<%-
local rowcnt = 0
function rowstyle()
rowcnt = rowcnt + 1
if rowcnt % 2 == 0 then
return " cbi-rowstyle-1"
else
return " cbi-rowstyle-2"
end
end
function width(o)
if o.width then
if type(o.width) == 'number' then
return ' style="width:%dpx"' % o.width
end
return ' style="width:%s"' % o.width
end
return ''
end
local has_titles = false
local has_descriptions = false
local anonclass = (not self.anonymous or self.sectiontitle) and "named" or "anonymous"
local titlename = ifattr(not self.anonymous or self.sectiontitle, "data-title", translate("Name"))
local i, k
for i, k in pairs(self.children) do
if not k.typename then
k.typename = k.template and k.template:gsub("^.+/", "") or ""
end
if not has_titles and k.title and #k.title > 0 then
has_titles = true
end
if not has_descriptions and k.description and #k.description > 0 then
has_descriptions = true
end
end
function render_titles()
if not has_titles then
return
end
%><tr class="tr cbi-section-table-titles <%=anonclass%>"<%=titlename%>><%
local i, k
for i, k in ipairs(self.children) do
if not k.optional then
%><th class="th cbi-section-table-cell"<%=
width(k) .. attr('data-widget', k.typename) %>><%
if k.titleref then
%><a title="<%=self.titledesc or translate('Go to relevant configuration page')%>" class="cbi-title-ref" href="<%=k.titleref%>"><%
end
write(k.title)
if k.titleref then
%></a><%
end
%></th><%
end
end
if self.sortable or self.extedit or self.addremove then
%><th class="th cbi-section-table-cell cbi-section-actions"></th><%
end
%></tr><%
rowcnt = rowcnt + 1
end
function render_descriptions()
if not has_descriptions then
return
end
%><tr class="tr cbi-section-table-descr <%=anonclass%>"><%
local i, k
for i, k in ipairs(self.children) do
if not k.optional then
%><th class="th cbi-section-table-cell"<%=
width(k) .. attr("data-widget", k.typename) %>><%
write(k.description)
%></th><%
end
end
if self.sortable or self.extedit or self.addremove then
%><th class="th cbi-section-table-cell cbi-section-actions"></th><%
end
%></tr><%
rowcnt = rowcnt + 1
end
-%>
<!-- tblsection -->
<div class="cbi-section cbi-tblsection" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
<% if self.title and #self.title > 0 then -%>
<h3><%=self.title%></h3>
<%- end %>
<%- if self.sortable then -%>
<input type="hidden" id="cbi.sts.<%=self.config%>.<%=self.sectiontype%>" name="cbi.sts.<%=self.config%>.<%=self.sectiontype%>" value="" />
<%- end -%>
<div class="cbi-section-descr"><%=self.description%></div>
<table class="table cbi-section-table">
<%-
render_titles()
render_descriptions()
local isempty, section, i, k = true, nil, nil
for i, k in ipairs(self:cfgsections()) do
isempty = false
section = k
local sectionname = striptags((type(self.sectiontitle) == "function") and self:sectiontitle(section) or k)
local sectiontitle = ifattr(sectionname and (not self.anonymous or self.sectiontitle), "data-title", sectionname, true)
local colorclass = (self.extedit or self.rowcolors) and rowstyle() or ""
local scope = {
valueheader = "cbi/cell_valueheader",
valuefooter = "cbi/cell_valuefooter"
}
-%>
<tr class="tr cbi-section-table-row<%=colorclass%>" id="cbi-<%=self.config%>-<%=section%>"<%=sectiontitle%>>
<%-
local node
for k, node in ipairs(self.children) do
if not node.optional then
node:render(section, scope or {})
end
end
-%>
<%- if self.sortable or self.extedit or self.addremove then -%>
<td class="td cbi-section-table-cell nowrap cbi-section-actions">
<div>
<%- if self.sortable then -%>
<input class="btn cbi-button cbi-button-up" type="button" value="<%:Up%>" onclick="return cbi_row_swap(this, true, 'cbi.sts.<%=self.config%>.<%=self.sectiontype%>')" title="<%:Move up%>" />
<input class="btn cbi-button cbi-button-down" type="button" value="<%:Down%>" onclick="return cbi_row_swap(this, false, 'cbi.sts.<%=self.config%>.<%=self.sectiontype%>')" title="<%:Move down%>" />
<% end; if self.extedit then -%>
<input class="btn cbi-button cbi-button-edit" type="button" value="<%:Edit%>"
<%- if type(self.extedit) == "string" then
%> onclick="location.href='<%=self.extedit:format(section)%>'"
<%- elseif type(self.extedit) == "function" then
%> onclick="location.href='<%=self:extedit(section)%>'"
<%- end
%> alt="<%:Edit%>" title="<%:Edit%>" />
<% end; if self.addremove then %>
<input class="btn cbi-button cbi-button-remove" type="submit" value="<%:Delete%>" onclick="this.form.cbi_state='del-section'; return true" name="cbi.rts.<%=self.config%>.<%=k%>" alt="<%:Delete%>" title="<%:Delete%>" />
<%- end -%>
</div>
</td>
<%- end -%>
</tr>
<%- end -%>
<%- if isempty then -%>
<tr class="tr cbi-section-table-row placeholder">
<td class="td"><em><%:This section contains no values yet%></em></td>
</tr>
<%- end -%>
</table>
<% if self.error then %>
<div class="cbi-section-error">
<ul><% for _, c in pairs(self.error) do for _, e in ipairs(c) do -%>
<li><%=pcdata(e):gsub("\n","<br />")%></li>
<%- end end %></ul>
</div>
<% end %>
<%- if self.addremove then -%>
<% if self.template_addremove then include(self.template_addremove) else -%>
<div class="cbi-section-create cbi-tblsection-create">
<% if self.anonymous then %>
<input class="btn cbi-button cbi-button-add" type="submit" value="<%:Add%>" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" title="<%:Add%>" />
<% else %>
<% if self.invalid_cts then -%>
<div class="cbi-section-error"><%:Invalid%></div>
<%- end %>
<div>
<input type="text" class="cbi-section-create-name" id="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" data-type="uciname" data-optional="true" onkeyup="cbi_validate_named_section_add(this)"/>
</div>
<input class="btn cbi-button cbi-button-add" type="submit" onclick="this.form.cbi_state='add-section'; return true" value="<%:Add%>" title="<%:Add%>" disabled="" />
<% end %>
</div>
<%- end %>
<%- end -%>
</div>
<!-- /tblsection -->
@@ -0,0 +1,208 @@
<%-
local rowcnt = 0
function rowstyle()
rowcnt = rowcnt + 1
if rowcnt % 2 == 0 then
return " cbi-rowstyle-1"
else
return " cbi-rowstyle-2"
end
end
function width(o)
if o.width then
if type(o.width) == 'number' then
return ' style="width:%dpx"' % o.width
end
return ' style="width:%s"' % o.width
end
return ''
end
local has_titles = false
local has_descriptions = false
local anonclass = (not self.anonymous or self.sectiontitle) and "named" or "anonymous"
local titlename = ifattr(not self.anonymous or self.sectiontitle, "data-title", translate("Name"))
local i, k
for i, k in pairs(self.children) do
if not k.typename then
k.typename = k.template and k.template:gsub("^.+/", "") or ""
end
if not has_titles and k.title and #k.title > 0 then
has_titles = true
end
if not has_descriptions and k.description and #k.description > 0 then
has_descriptions = true
end
end
function render_titles()
if not has_titles then
return
end
%><tr class="tr cbi-section-table-titles <%=anonclass%>"<%=titlename%>>
<th class="th cbi-section-table-cell"><%:Serial Number%></th>
<%
local i, k
for i, k in ipairs(self.children) do
if not k.optional then
%><th class="th cbi-section-table-cell"<%=
width(k) .. attr('data-widget', k.typename) %>><%
if k.titleref then
%><a title="<%=self.titledesc or translate('Go to relevant configuration page')%>" class="cbi-title-ref" href="<%=k.titleref%>"><%
end
write(k.title)
if k.titleref then
%></a><%
end
%></th><%
end
end
if self.sortable or self.extedit or self.addremove then
%><th class="th cbi-section-table-cell cbi-section-actions"></th><%
end
%></tr><%
rowcnt = rowcnt + 1
end
function render_descriptions()
if not has_descriptions then
return
end
%><tr class="tr cbi-section-table-descr <%=anonclass%>"><%
local i, k
for i, k in ipairs(self.children) do
if not k.optional then
%><th class="th cbi-section-table-cell"<%=
width(k) .. attr("data-widget", k.typename) %>><%
write(k.description)
%></th><%
end
end
if self.sortable or self.extedit or self.addremove then
%><th class="th cbi-section-table-cell cbi-section-actions"></th><%
end
%></tr><%
rowcnt = rowcnt + 1
end
-%>
<!-- tblsection -->
<div class="cbi-section cbi-tblsection" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
<% if self.title and #self.title > 0 then -%>
<h3><%=self.title%></h3>
<%- end %>
<%- if self.sortable then -%>
<input type="hidden" id="cbi.sts.<%=self.config%>.<%=self.sectiontype%>" name="cbi.sts.<%=self.config%>.<%=self.sectiontype%>" value="" />
<%- end -%>
<div class="cbi-section-descr"><%=self.description%></div>
<table class="table cbi-section-table">
<%-
render_titles()
render_descriptions()
local num = 1
local isempty, section, i, k = true, nil, nil
for i, k in ipairs(self:cfgsections()) do
isempty = false
section = k
local sectionname = striptags((type(self.sectiontitle) == "function") and self:sectiontitle(section) or k)
local sectiontitle = ifattr(sectionname and (not self.anonymous or self.sectiontitle), "data-title", sectionname, true)
local colorclass = (self.extedit or self.rowcolors) and rowstyle() or ""
local scope = {
valueheader = "cbi/cell_valueheader",
valuefooter = "cbi/cell_valuefooter"
}
-%>
<tr class="tr cbi-section-table-row<%=colorclass%>" id="cbi-<%=self.config%>-<%=section%>"<%=sectiontitle%>>
<td class="td cbi-value-field" data-title="<%:Serial Number%>">
<p><%=num%></p>
<% num = num + 1 -%>
</td>
<%-
local node
for k, node in ipairs(self.children) do
if not node.optional then
node:render(section, scope or {})
end
end
-%>
<%- if self.sortable or self.extedit or self.addremove then -%>
<td class="td cbi-section-table-cell nowrap cbi-section-actions">
<div>
<%- if self.sortable then -%>
<input class="btn cbi-button cbi-button-up" type="button" value="<%:Up%>" onclick="return cbi_row_swap(this, true, 'cbi.sts.<%=self.config%>.<%=self.sectiontype%>')" title="<%:Move up%>" />
<input class="btn cbi-button cbi-button-down" type="button" value="<%:Down%>" onclick="return cbi_row_swap(this, false, 'cbi.sts.<%=self.config%>.<%=self.sectiontype%>')" title="<%:Move down%>" />
<% end; if self.extedit then -%>
<input class="btn cbi-button cbi-button-edit" type="button" value="<%:Edit%>"
<%- if type(self.extedit) == "string" then
%> onclick="location.href='<%=self.extedit:format(section)%>'"
<%- elseif type(self.extedit) == "function" then
%> onclick="location.href='<%=self:extedit(section)%>'"
<%- end
%> alt="<%:Edit%>" title="<%:Edit%>" />
<% end; if self.addremove then %>
<input class="btn cbi-button cbi-button-remove" type="submit" value="<%:Delete%>" onclick="this.form.cbi_state='del-section'; return true" name="cbi.rts.<%=self.config%>.<%=k%>" alt="<%:Delete%>" title="<%:Delete%>" />
<%- end -%>
</div>
</td>
<%- end -%>
</tr>
<%- end -%>
<%- if isempty then -%>
<tr class="tr cbi-section-table-row placeholder">
<td class="td"><em><%:This section contains no values yet%></em></td>
</tr>
<%- end -%>
</table>
<% if self.error then %>
<div class="cbi-section-error">
<ul><% for _, c in pairs(self.error) do for _, e in ipairs(c) do -%>
<li><%=pcdata(e):gsub("\n","<br />")%></li>
<%- end end %></ul>
</div>
<% end %>
<%- if self.addremove then -%>
<% if self.template_addremove then include(self.template_addremove) else -%>
<div class="cbi-section-create cbi-tblsection-create">
<% if self.anonymous then %>
<input class="btn cbi-button cbi-button-add" type="submit" value="<%:Add%>" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" title="<%:Add%>" />
<% else %>
<% if self.invalid_cts then -%>
<div class="cbi-section-error"><%:Invalid%></div>
<%- end %>
<div>
<input type="text" class="cbi-section-create-name" id="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" data-type="uciname" data-optional="true" onkeyup="cbi_validate_named_section_add(this)"/>
</div>
<input class="btn cbi-button cbi-button-add" type="submit" onclick="this.form.cbi_state='add-section'; return true" value="<%:Add%>" title="<%:Add%>" disabled="" />
<% end %>
</div>
<%- end %>
<%- end -%>
</div>
<!-- /tblsection -->
+707
View File
@@ -0,0 +1,707 @@
#
# Siriling <siriling@qq.com>, 2023.
#
msgid ""
msgstr ""
"Project-Id-Version: luci-app-modem 1.4.6-1\n"
"POT-Creation-Date: 2024-04-20 12:07+0100\n"
"PO-Revision-Date: 2024-04-24 18:08+0000\n"
"Last-Translator: Siriling <siriling@gmail.com>\n"
"Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/"
"openwrt/luciapplicationsmodem/zh_Hans/>\n"
"Language: zh_Hans\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 5.5-dev\n"
msgid "Base Setting"
msgstr "基本设置"
msgid "Modem"
msgstr "移动通信模组"
msgid "Modem Config"
msgstr "模组配置"
msgid "Modem Status"
msgstr "模组状态"
msgid "Modem Name"
msgstr "模组名称"
msgid "Modem Debug"
msgstr "模组调试"
msgid "Modem Select"
msgstr "模组选择"
msgid "Check the information of the adapted modem"
msgstr "查看已适配模组的信息"
msgid "Not adapted to this modem"
msgstr "未适配该模组"
msgid "(Check adapted modem)"
msgstr "(查看已适配模组)"
msgid "Loading modem information"
msgstr "正在加载模组信息"
msgid "Loading modem status"
msgstr "正在加载模组状态"
msgid "Loading modem"
msgstr "正在加载模组"
msgid "Dial Overview"
msgstr "拨号总览"
msgid "Check and add modem dialing configurations"
msgstr "查看和添加模组拨号配置"
msgid "Global Config"
msgstr "全局配置"
msgid "Dial Log"
msgstr "拨号日志"
msgid "Download Log"
msgstr "下载日志"
msgid "connect"
msgstr "已连接"
msgid "disconnect"
msgstr "未连接"
msgid "disabled"
msgstr "未启用"
msgid "Data Interface"
msgstr "数据接口"
msgid "Network Driver"
msgstr "网络驱动"
msgid "Mode"
msgstr "模式"
msgid "Connect Status"
msgstr "连接状态"
msgid "Dial Config"
msgstr "拨号配置"
msgid "Config List"
msgstr "配置列表"
msgid "Debug Your Module"
msgstr "调试你的模组"
msgid "Select a modem for debugging"
msgstr "选择一个模组进行调试"
msgid "Network Preferences"
msgstr "网络偏好"
msgid "Apply Network Prefer"
msgstr "应用网络偏好"
msgid "Apply Band Prefer"
msgstr "应用频段偏好"
msgid "2G Band Preferences"
msgstr "2G 频段偏好"
msgid "3G Band Preferences"
msgstr "3G 频段偏好"
msgid "4G Band Preferences"
msgstr "4G 频段偏好"
msgid "5G Band Preferences"
msgstr "5G 频段偏好"
msgid "Self Test"
msgstr "自检"
msgid "Current"
msgstr "当前"
msgid "Option"
msgstr "选项"
msgid "Config"
msgstr "配置"
msgid "Item"
msgstr "项目"
msgid "Voltage"
msgstr "电压"
msgid "Status"
msgstr "状态"
msgid "Abnormal"
msgstr "异常"
msgid "Normal"
msgstr "正常"
msgid "Low"
msgstr "偏低"
msgid "Somewhat High"
msgstr "偏高"
msgid "Excessively High"
msgstr "过高"
msgid "AT Command"
msgstr "AT命令"
msgid "Quick Option"
msgstr "快捷选项"
msgid "Auto"
msgstr "自动"
msgid "Custom"
msgstr "自定义"
msgid "Quick Commands"
msgstr "快捷命令"
msgid "Enter Command"
msgstr "输入命令"
msgid "Apply"
msgstr "应用"
msgid "Send"
msgstr "发送"
msgid "Clean"
msgstr "清空"
msgid "Response"
msgstr "响应"
msgid "Return to old page"
msgstr "返回旧界面"
msgid "Return to modem debug"
msgstr "返回模组调试界面"
msgid "Custom quick commands"
msgstr "自定义快捷命令"
msgid "Customize your quick commands"
msgstr "自定义你的快捷命令"
msgid "Custom Commands"
msgstr "自定义命令"
msgid "Serial Number"
msgstr "序号"
msgid "Description"
msgstr "描述"
msgid "Command"
msgstr "命令"
msgid "Modem Information"
msgstr "模组信息"
msgid "No modems found"
msgstr "没有找到模组"
msgid "(Check the reason)"
msgstr "(查看原因)"
msgid "Enable dial configurations"
msgstr "启用拨号配置"
msgid "General Settings"
msgstr "通用配置"
msgid "Advanced Settings"
msgstr "高级配置"
msgid "Remarks"
msgstr "备注"
msgid "Mobile Network"
msgstr "移动网络"
msgid "UNKNOWN"
msgstr "未知"
msgid "Unknown"
msgstr "未知"
msgid "unknown"
msgstr "未知"
msgid "Mobile network not found"
msgstr "未发现移动网络"
msgid "The network device was not found"
msgstr "找不到网络设备"
msgid "Only display the modes available for the adaptation modem"
msgstr "仅显示适配模组可用的拨号模式"
msgid "Config ID"
msgstr "配置 ID"
msgid "Dial Tool"
msgstr "拨号工具"
msgid "After switching the dialing tool, it may be necessary to restart the module or restart the router to recognize the module."
msgstr "切换拨号工具后,可能需要重启模组或重启路由器才能识别模组。"
msgid "Auto Choose"
msgstr "自动选择"
msgid "quectel-CM"
msgstr "移远模组拨号工具"
msgid "fibocom-dial"
msgstr "广和通模组拨号工具"
msgid "meig-cm"
msgstr "美格模组拨号工具"
msgid "mmcli"
msgstr "调制解调器管理工具"
msgid "PDP Type"
msgstr "网络类型"
msgid "Network Bridge"
msgstr "网络桥接"
msgid "After checking, enable network interface bridge."
msgstr "勾选后,启用网络接口桥接。"
msgid "APN"
msgstr "接入点"
msgid "China Mobile"
msgstr "中国移动"
msgid "China Unicom"
msgstr "中国联通"
msgid "China Telecom"
msgstr "中国电信"
msgid "China Broadcast"
msgstr "中国广电"
msgid "Skytone"
msgstr "天际通"
msgid "Authentication Type"
msgstr "认证类型"
msgid "PAP/CHAP (both)"
msgstr "PAP/CHAP (均使用)"
msgid "NONE"
msgstr "无"
msgid "PAP/CHAP Username"
msgstr "PAP/CHAP 用户名"
msgid "PAP/CHAP Password"
msgstr "PAP/CHAP 密码"
msgid "Message"
msgstr "信息"
msgid "Base Information"
msgstr "基本信息"
msgid "Manufacturer"
msgstr "制造商"
msgid "Revision"
msgstr "固件版本"
msgid "AT Port"
msgstr "AT串口"
msgid "Temperature"
msgstr "温度"
msgid "Update Time"
msgstr "更新时间"
msgid "SIM Information"
msgstr "SIM卡信息"
msgid "Unknown SIM card status"
msgstr "未知SIM卡状态"
msgid "SIM card not inserted"
msgstr "SIM卡未插入"
msgid "ISP"
msgstr "运营商"
msgid "SIM Status"
msgstr "SIM卡状态"
msgid "miss"
msgstr "未插入"
msgid "locked"
msgstr "锁定"
msgid "SIM Slot"
msgstr "SIM卡卡槽"
msgid "SIM Number"
msgstr "SIM卡号码"
msgid "IMEI"
msgstr "国际移动设备识别码"
msgid "IMSI"
msgstr "国际移动用户识别码"
msgid "ICCID"
msgstr "集成电路卡识别码"
msgid "Network Information"
msgstr "网络信息"
msgid "Network Type"
msgstr "网络类型"
msgid "CQI UL"
msgstr "上行信道质量指示"
msgid "CQI DL"
msgstr "下行信道质量指示"
msgid "AMBR UL"
msgstr "上行访问最大比特率"
msgid "AMBR DL"
msgstr "下行访问最大比特率"
msgid "Tx Rate"
msgstr "上传速率"
msgid "Rx Rate"
msgstr "下载速率"
msgid "RSSI"
msgstr "接收信号强度指示"
msgid "BER"
msgstr "信道误码率"
msgid "Cell Information"
msgstr "小区信息"
msgid "Network Mode"
msgstr "网络模式"
msgid "NR5G-SA Mode"
msgstr "NR5G-SA 模式"
msgid "EN-DC Mode"
msgstr "EN-DC 模式"
msgid "LTE Mode"
msgstr "LTE 模式"
msgid "WCDMA Mode"
msgstr "WCDMA 模式"
msgid "GSM Mode"
msgstr "GSM 模式"
msgid "MCC"
msgstr "移动国家代码 (MCC)"
msgid "MNC"
msgstr "移动网络代码 (MNC)"
msgid "Duplex Mode"
msgstr "双工模式 (Duplex Mode)"
msgid "LAC"
msgstr "位置区码 (LAC)"
msgid "Cell ID"
msgstr "小区ID (Cell ID)"
msgid "Physical Cell ID"
msgstr "物理小区ID (Physical Cell ID)"
msgid "TAC"
msgstr "跟踪区编码 (TAC)"
msgid "ARFCN"
msgstr "绝对射频信道号 (ARFCN)"
msgid "EARFCN"
msgstr "E-UTRA绝对射频信道号 (EARFCN)"
msgid "UARFCN"
msgstr "UTRA绝对射频信道号 (UARFCN)"
msgid "Band"
msgstr "频段 (Band)"
msgid "Freq band indicator"
msgstr "频带指示 (Freq band indicator)"
msgid "UL Bandwidth"
msgstr "上行带宽 (UL Bandwidth)"
msgid "DL Bandwidth"
msgstr "下行带宽 (DL Bandwidth)"
msgid "RSRP"
msgstr "参考信号接收功率 (RSRP)"
msgid "RSRQ"
msgstr "参考信号接收质量 (RSRQ)"
msgid "RSSI"
msgstr "接收信号强度指示 (RSSI)"
msgid "SINR"
msgstr "信号与干扰加噪声比 (SINR)"
msgid "RxLev"
msgstr "接收信号功率 (RxLev)"
msgid "RSSNR"
msgstr "信号干扰比 (RSSNR)"
msgid "SCS"
msgstr "NR子载波间隔 (SCS)"
msgid "CQI"
msgstr "信道质量指示 (CQI)"
msgid "TX Power"
msgstr "TX 功率 (TX Power)"
msgid "Srxlev"
msgstr "服务小区接收信号功率 (Srxlev)"
msgid "PSC"
msgstr "主扰码 (PSC)"
msgid "RAC"
msgstr "路由区域码 (RAC)"
msgid "RSCP"
msgstr "接收信号码功率 (RSCP)"
msgid "Eb/Io"
msgstr "每比特能量与干扰功率密度(干扰比)之比"
msgid "Eb/No"
msgstr "每比特能量与噪声功率密度(噪声比)之比"
msgid "Ec/Io"
msgstr "每码片能量与干扰功率密度(干扰比)之比"
msgid "Ec/No"
msgstr "每码片能量与噪声功率密度(噪声比)之比"
msgid "Physical Channel"
msgstr "物理信道 (Physical Channel)"
msgid "Spreading Factor"
msgstr "扩频因子 (Spreading Factor)"
msgid "Slot"
msgstr "插槽格式 (Slot)"
msgid "Speech Code"
msgstr "语音编码 (Speech Code)"
msgid "Compression Mode"
msgstr "压缩模式 (Compression Mode)"
msgid "CHN-CMCC"
msgstr "中国移动"
msgid "CMCC"
msgstr "中国移动"
msgid "46000"
msgstr "中国移动"
msgid "CHN-UNICOM"
msgstr "中国联通"
msgid "UNICOM"
msgstr "中国联通"
msgid "CUCC"
msgstr "中国联通"
msgid "46001"
msgstr "中国联通"
msgid "CHN-CT"
msgstr "中国电信"
msgid "CHN-TELECOM"
msgstr "中国电信"
msgid "CTCC"
msgstr "中国电信"
msgid "CT"
msgstr "中国电信"
msgid "46011"
msgstr "中国电信"
msgid "Excellent"
msgstr "优秀"
msgid "Good"
msgstr "良好"
msgid "Fair"
msgstr "一般"
msgid "Bad"
msgstr "较差"
msgid "Plugin Config"
msgstr "插件配置"
msgid "Check and modify the plugin configuration"
msgstr "查看和修改插件配置"
msgid "Modem Scan"
msgstr "模组扫描"
msgid "Scan"
msgstr "扫描"
msgid "Scaning modem..."
msgstr "正在扫描中..."
msgid "The automatic configuration modem is triggered only at modem startup, otherwise, manual scanning is necessary"
msgstr "自动配置模组只有在模组启动的时候才会触发,其他情况需要手动点击扫描"
msgid "Enable USB Device Scan"
msgstr "启用USB设备扫描"
msgid "Enable scanning of USB devices for modems"
msgstr "启用对USB模组设备的扫描"
msgid "(After disable, the automatic scanning and configuration function for USB modem information will be stopped)"
msgstr "(禁用后将停止自动扫描并配置USB模组信息功能)"
msgid "Enable PCI Device Scan"
msgstr "启用PCI设备扫描"
msgid "Enable scanning of PCI devices for modems"
msgstr "启用对PCI模组设备的扫描"
msgid "(After disable, the automatic scanning and configuration function for PCI modem information will be stopped)"
msgstr "(禁用后将停止自动扫描并配置PCI模组信息功能)"
msgid "Manual Configuration"
msgstr "手动配置"
msgid "Enable the manual configuration of modem information"
msgstr "启用手动配置模组信息"
msgid "(After enable, the automatic scanning and configuration function for modem information will be disabled)"
msgstr "(启用后将禁用自动扫描并配置模组信息功能)"
msgid "Network Interface Alias"
msgstr "网络接口别名"
msgid "Enable automatic creation of network interface alias (Effective upon reinstatement of dialing configuration)"
msgstr "启用自动创建网络接口别名(重新启用拨号配置后生效)"
msgid "Not null"
msgstr "不能为空"
msgid "missing"
msgstr "有必填选项为空值"
msgid "Plugin Info"
msgstr "插件信息"
msgid "Check the version information of the plugin"
msgstr "查看插件的版本信息"
msgid "Plugin Version"
msgstr "插件版本"
msgid "Dial Tool Info"
msgstr "拨号工具信息"
msgid "Version"
msgstr "版本"
msgid "Not installed"
msgstr "未安装"
msgid "Modem General Driver Info"
msgstr "模组通用驱动信息"
msgid "Driver Type"
msgstr "驱动类型"
msgid "Kernel Model"
msgstr "内核模块"
msgid "USB Network"
msgstr "USB网络"
msgid "Serial Port"
msgstr "串口"
msgid "Loaded"
msgstr "已加载"
msgid "Not loaded"
msgstr "未加载"
msgid "Modem USB Driver Info"
msgstr "模组USB驱动信息"
msgid "Modem PCI Driver Info"
msgstr "模组PCI驱动信息"
msgid "General"
msgstr "通用"
msgid "Private"
msgstr "私有"
msgid "Private (Quectel)"
msgstr "私有(移远)"
msgid "Private (Fibocom)"
msgstr "私有(广和通)"
msgid "Private (Meig)"
msgstr "私有(美格)"
msgid "Private (T&W)"
msgstr "私有(同维)"
+707
View File
@@ -0,0 +1,707 @@
#
# Siriling <siriling@qq.com>, 2023.
#
msgid ""
msgstr ""
"Project-Id-Version: luci-app-modem 1.4.6-1\n"
"POT-Creation-Date: 2024-04-20 12:07+0100\n"
"PO-Revision-Date: 2024-04-24 18:08+0000\n"
"Last-Translator: Siriling <siriling@gmail.com>\n"
"Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/"
"openwrt/luciapplicationsmodem/zh_Hans/>\n"
"Language: zh_Hans\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 5.5-dev\n"
msgid "Base Setting"
msgstr "基本设置"
msgid "Modem"
msgstr "移动通信模组"
msgid "Modem Config"
msgstr "模组配置"
msgid "Modem Status"
msgstr "模组状态"
msgid "Modem Name"
msgstr "模组名称"
msgid "Modem Debug"
msgstr "模组调试"
msgid "Modem Select"
msgstr "模组选择"
msgid "Check the information of the adapted modem"
msgstr "查看已适配模组的信息"
msgid "Not adapted to this modem"
msgstr "未适配该模组"
msgid "(Check adapted modem)"
msgstr "(查看已适配模组)"
msgid "Loading modem information"
msgstr "正在加载模组信息"
msgid "Loading modem status"
msgstr "正在加载模组状态"
msgid "Loading modem"
msgstr "正在加载模组"
msgid "Dial Overview"
msgstr "拨号总览"
msgid "Check and add modem dialing configurations"
msgstr "查看和添加模组拨号配置"
msgid "Global Config"
msgstr "全局配置"
msgid "Dial Log"
msgstr "拨号日志"
msgid "Download Log"
msgstr "下载日志"
msgid "connect"
msgstr "已连接"
msgid "disconnect"
msgstr "未连接"
msgid "disabled"
msgstr "未启用"
msgid "Data Interface"
msgstr "数据接口"
msgid "Network Driver"
msgstr "网络驱动"
msgid "Mode"
msgstr "模式"
msgid "Connect Status"
msgstr "连接状态"
msgid "Dial Config"
msgstr "拨号配置"
msgid "Config List"
msgstr "配置列表"
msgid "Debug Your Module"
msgstr "调试你的模组"
msgid "Select a modem for debugging"
msgstr "选择一个模组进行调试"
msgid "Network Preferences"
msgstr "网络偏好"
msgid "Apply Network Prefer"
msgstr "应用网络偏好"
msgid "Apply Band Prefer"
msgstr "应用频段偏好"
msgid "2G Band Preferences"
msgstr "2G 频段偏好"
msgid "3G Band Preferences"
msgstr "3G 频段偏好"
msgid "4G Band Preferences"
msgstr "4G 频段偏好"
msgid "5G Band Preferences"
msgstr "5G 频段偏好"
msgid "Self Test"
msgstr "自检"
msgid "Current"
msgstr "当前"
msgid "Option"
msgstr "选项"
msgid "Config"
msgstr "配置"
msgid "Item"
msgstr "项目"
msgid "Voltage"
msgstr "电压"
msgid "Status"
msgstr "状态"
msgid "Abnormal"
msgstr "异常"
msgid "Normal"
msgstr "正常"
msgid "Low"
msgstr "偏低"
msgid "Somewhat High"
msgstr "偏高"
msgid "Excessively High"
msgstr "过高"
msgid "AT Command"
msgstr "AT命令"
msgid "Quick Option"
msgstr "快捷选项"
msgid "Auto"
msgstr "自动"
msgid "Custom"
msgstr "自定义"
msgid "Quick Commands"
msgstr "快捷命令"
msgid "Enter Command"
msgstr "输入命令"
msgid "Apply"
msgstr "应用"
msgid "Send"
msgstr "发送"
msgid "Clean"
msgstr "清空"
msgid "Response"
msgstr "响应"
msgid "Return to old page"
msgstr "返回旧界面"
msgid "Return to modem debug"
msgstr "返回模组调试界面"
msgid "Custom quick commands"
msgstr "自定义快捷命令"
msgid "Customize your quick commands"
msgstr "自定义你的快捷命令"
msgid "Custom Commands"
msgstr "自定义命令"
msgid "Serial Number"
msgstr "序号"
msgid "Description"
msgstr "描述"
msgid "Command"
msgstr "命令"
msgid "Modem Information"
msgstr "模组信息"
msgid "No modems found"
msgstr "没有找到模组"
msgid "(Check the reason)"
msgstr "(查看原因)"
msgid "Enable dial configurations"
msgstr "启用拨号配置"
msgid "General Settings"
msgstr "通用配置"
msgid "Advanced Settings"
msgstr "高级配置"
msgid "Remarks"
msgstr "备注"
msgid "Mobile Network"
msgstr "移动网络"
msgid "UNKNOWN"
msgstr "未知"
msgid "Unknown"
msgstr "未知"
msgid "unknown"
msgstr "未知"
msgid "Mobile network not found"
msgstr "未发现移动网络"
msgid "The network device was not found"
msgstr "找不到网络设备"
msgid "Only display the modes available for the adaptation modem"
msgstr "仅显示适配模组可用的拨号模式"
msgid "Config ID"
msgstr "配置 ID"
msgid "Dial Tool"
msgstr "拨号工具"
msgid "After switching the dialing tool, it may be necessary to restart the module or restart the router to recognize the module."
msgstr "切换拨号工具后,可能需要重启模组或重启路由器才能识别模组。"
msgid "Auto Choose"
msgstr "自动选择"
msgid "quectel-CM"
msgstr "移远模组拨号工具"
msgid "fibocom-dial"
msgstr "广和通模组拨号工具"
msgid "meig-cm"
msgstr "美格模组拨号工具"
msgid "mmcli"
msgstr "调制解调器管理工具"
msgid "PDP Type"
msgstr "网络类型"
msgid "Network Bridge"
msgstr "网络桥接"
msgid "After checking, enable network interface bridge."
msgstr "勾选后,启用网络接口桥接。"
msgid "APN"
msgstr "接入点"
msgid "China Mobile"
msgstr "中国移动"
msgid "China Unicom"
msgstr "中国联通"
msgid "China Telecom"
msgstr "中国电信"
msgid "China Broadcast"
msgstr "中国广电"
msgid "Skytone"
msgstr "天际通"
msgid "Authentication Type"
msgstr "认证类型"
msgid "PAP/CHAP (both)"
msgstr "PAP/CHAP (均使用)"
msgid "NONE"
msgstr "无"
msgid "PAP/CHAP Username"
msgstr "PAP/CHAP 用户名"
msgid "PAP/CHAP Password"
msgstr "PAP/CHAP 密码"
msgid "Message"
msgstr "信息"
msgid "Base Information"
msgstr "基本信息"
msgid "Manufacturer"
msgstr "制造商"
msgid "Revision"
msgstr "固件版本"
msgid "AT Port"
msgstr "AT串口"
msgid "Temperature"
msgstr "温度"
msgid "Update Time"
msgstr "更新时间"
msgid "SIM Information"
msgstr "SIM卡信息"
msgid "Unknown SIM card status"
msgstr "未知SIM卡状态"
msgid "SIM card not inserted"
msgstr "SIM卡未插入"
msgid "ISP"
msgstr "运营商"
msgid "SIM Status"
msgstr "SIM卡状态"
msgid "miss"
msgstr "未插入"
msgid "locked"
msgstr "锁定"
msgid "SIM Slot"
msgstr "SIM卡卡槽"
msgid "SIM Number"
msgstr "SIM卡号码"
msgid "IMEI"
msgstr "国际移动设备识别码"
msgid "IMSI"
msgstr "国际移动用户识别码"
msgid "ICCID"
msgstr "集成电路卡识别码"
msgid "Network Information"
msgstr "网络信息"
msgid "Network Type"
msgstr "网络类型"
msgid "CQI UL"
msgstr "上行信道质量指示"
msgid "CQI DL"
msgstr "下行信道质量指示"
msgid "AMBR UL"
msgstr "上行访问最大比特率"
msgid "AMBR DL"
msgstr "下行访问最大比特率"
msgid "Tx Rate"
msgstr "上传速率"
msgid "Rx Rate"
msgstr "下载速率"
msgid "RSSI"
msgstr "接收信号强度指示"
msgid "BER"
msgstr "信道误码率"
msgid "Cell Information"
msgstr "小区信息"
msgid "Network Mode"
msgstr "网络模式"
msgid "NR5G-SA Mode"
msgstr "NR5G-SA 模式"
msgid "EN-DC Mode"
msgstr "EN-DC 模式"
msgid "LTE Mode"
msgstr "LTE 模式"
msgid "WCDMA Mode"
msgstr "WCDMA 模式"
msgid "GSM Mode"
msgstr "GSM 模式"
msgid "MCC"
msgstr "移动国家代码 (MCC)"
msgid "MNC"
msgstr "移动网络代码 (MNC)"
msgid "Duplex Mode"
msgstr "双工模式 (Duplex Mode)"
msgid "LAC"
msgstr "位置区码 (LAC)"
msgid "Cell ID"
msgstr "小区ID (Cell ID)"
msgid "Physical Cell ID"
msgstr "物理小区ID (Physical Cell ID)"
msgid "TAC"
msgstr "跟踪区编码 (TAC)"
msgid "ARFCN"
msgstr "绝对射频信道号 (ARFCN)"
msgid "EARFCN"
msgstr "E-UTRA绝对射频信道号 (EARFCN)"
msgid "UARFCN"
msgstr "UTRA绝对射频信道号 (UARFCN)"
msgid "Band"
msgstr "频段 (Band)"
msgid "Freq band indicator"
msgstr "频带指示 (Freq band indicator)"
msgid "UL Bandwidth"
msgstr "上行带宽 (UL Bandwidth)"
msgid "DL Bandwidth"
msgstr "下行带宽 (DL Bandwidth)"
msgid "RSRP"
msgstr "参考信号接收功率 (RSRP)"
msgid "RSRQ"
msgstr "参考信号接收质量 (RSRQ)"
msgid "RSSI"
msgstr "接收信号强度指示 (RSSI)"
msgid "SINR"
msgstr "信号与干扰加噪声比 (SINR)"
msgid "RxLev"
msgstr "接收信号功率 (RxLev)"
msgid "RSSNR"
msgstr "信号干扰比 (RSSNR)"
msgid "SCS"
msgstr "NR子载波间隔 (SCS)"
msgid "CQI"
msgstr "信道质量指示 (CQI)"
msgid "TX Power"
msgstr "TX 功率 (TX Power)"
msgid "Srxlev"
msgstr "服务小区接收信号功率 (Srxlev)"
msgid "PSC"
msgstr "主扰码 (PSC)"
msgid "RAC"
msgstr "路由区域码 (RAC)"
msgid "RSCP"
msgstr "接收信号码功率 (RSCP)"
msgid "Eb/Io"
msgstr "每比特能量与干扰功率密度(干扰比)之比"
msgid "Eb/No"
msgstr "每比特能量与噪声功率密度(噪声比)之比"
msgid "Ec/Io"
msgstr "每码片能量与干扰功率密度(干扰比)之比"
msgid "Ec/No"
msgstr "每码片能量与噪声功率密度(噪声比)之比"
msgid "Physical Channel"
msgstr "物理信道 (Physical Channel)"
msgid "Spreading Factor"
msgstr "扩频因子 (Spreading Factor)"
msgid "Slot"
msgstr "插槽格式 (Slot)"
msgid "Speech Code"
msgstr "语音编码 (Speech Code)"
msgid "Compression Mode"
msgstr "压缩模式 (Compression Mode)"
msgid "CHN-CMCC"
msgstr "中国移动"
msgid "CMCC"
msgstr "中国移动"
msgid "46000"
msgstr "中国移动"
msgid "CHN-UNICOM"
msgstr "中国联通"
msgid "UNICOM"
msgstr "中国联通"
msgid "CUCC"
msgstr "中国联通"
msgid "46001"
msgstr "中国联通"
msgid "CHN-CT"
msgstr "中国电信"
msgid "CHN-TELECOM"
msgstr "中国电信"
msgid "CTCC"
msgstr "中国电信"
msgid "CT"
msgstr "中国电信"
msgid "46011"
msgstr "中国电信"
msgid "Excellent"
msgstr "优秀"
msgid "Good"
msgstr "良好"
msgid "Fair"
msgstr "一般"
msgid "Bad"
msgstr "较差"
msgid "Plugin Config"
msgstr "插件配置"
msgid "Check and modify the plugin configuration"
msgstr "查看和修改插件配置"
msgid "Modem Scan"
msgstr "模组扫描"
msgid "Scan"
msgstr "扫描"
msgid "Scaning modem..."
msgstr "正在扫描中..."
msgid "The automatic configuration modem is triggered only at modem startup, otherwise, manual scanning is necessary"
msgstr "自动配置模组只有在模组启动的时候才会触发,其他情况需要手动点击扫描"
msgid "Enable USB Device Scan"
msgstr "启用USB设备扫描"
msgid "Enable scanning of USB devices for modems"
msgstr "启用对USB模组设备的扫描"
msgid "(After disable, the automatic scanning and configuration function for USB modem information will be stopped)"
msgstr "(禁用后将停止自动扫描并配置USB模组信息功能)"
msgid "Enable PCI Device Scan"
msgstr "启用PCI设备扫描"
msgid "Enable scanning of PCI devices for modems"
msgstr "启用对PCI模组设备的扫描"
msgid "(After disable, the automatic scanning and configuration function for PCI modem information will be stopped)"
msgstr "(禁用后将停止自动扫描并配置PCI模组信息功能)"
msgid "Manual Configuration"
msgstr "手动配置"
msgid "Enable the manual configuration of modem information"
msgstr "启用手动配置模组信息"
msgid "(After enable, the automatic scanning and configuration function for modem information will be disabled)"
msgstr "(启用后将禁用自动扫描并配置模组信息功能)"
msgid "Network Interface Alias"
msgstr "网络接口别名"
msgid "Enable automatic creation of network interface alias (Effective upon reinstatement of dialing configuration)"
msgstr "启用自动创建网络接口别名(重新启用拨号配置后生效)"
msgid "Not null"
msgstr "不能为空"
msgid "missing"
msgstr "有必填选项为空值"
msgid "Plugin Info"
msgstr "插件信息"
msgid "Check the version information of the plugin"
msgstr "查看插件的版本信息"
msgid "Plugin Version"
msgstr "插件版本"
msgid "Dial Tool Info"
msgstr "拨号工具信息"
msgid "Version"
msgstr "版本"
msgid "Not installed"
msgstr "未安装"
msgid "Modem General Driver Info"
msgstr "模组通用驱动信息"
msgid "Driver Type"
msgstr "驱动类型"
msgid "Kernel Model"
msgstr "内核模块"
msgid "USB Network"
msgstr "USB网络"
msgid "Serial Port"
msgstr "串口"
msgid "Loaded"
msgstr "已加载"
msgid "Not loaded"
msgstr "未加载"
msgid "Modem USB Driver Info"
msgstr "模组USB驱动信息"
msgid "Modem PCI Driver Info"
msgstr "模组PCI驱动信息"
msgid "General"
msgstr "通用"
msgid "Private"
msgstr "私有"
msgid "Private (Quectel)"
msgstr "私有(移远)"
msgid "Private (Fibocom)"
msgstr "私有(广和通)"
msgid "Private (Meig)"
msgstr "私有(美格)"
msgid "Private (T&W)"
msgstr "私有(同维)"
@@ -0,0 +1,392 @@
config custom-commands
option description '****************通用****************'
option command 'ATI'
config custom-commands
option description '模组信息 > ATI'
option command 'ATI'
config custom-commands
option description '查询SIM卡状态 > AT+CPIN?'
option command 'AT+CPIN?'
config custom-commands
option description '查询网络信号质量(4G) > AT+CSQ'
option command 'AT+CSQ'
config custom-commands
option description '查询网络信号质量(5G) > AT+CESQ'
option command 'AT+CESQ'
config custom-commands
option description '查询网络信息 > AT+COPS?'
option command 'AT+COPS?'
config custom-commands
option description '查询PDP信息 > AT+CGDCONT?'
option command 'AT+CGDCONT?'
config custom-commands
option description '查询PDP地址 > AT+CGPADDR'
option command 'AT+CGPADDR'
config custom-commands
option description '查询模组IMEI > AT+CGSN'
option command 'AT+CGSN'
config custom-commands
option description '查询模组IMEI > AT+GSN'
option command 'AT+GSN'
config custom-commands
option description '查看当前电压'
option command 'AT+CBC'
config custom-commands
option description '最小功能模式 > AT+CFUN=0'
option command 'AT+CFUN=0'
config custom-commands
option description '全功能模式 > AT+CFUN=1'
option command 'AT+CFUN=1'
config custom-commands
option description '重启模组 > AT+CFUN=1,1'
option command 'AT+CFUN=1,1'
config custom-commands
option description '****************移远****************'
option command 'ATI'
config custom-commands
option description 'SIM卡状态上报 > AT+QSIMSTAT?'
option command 'AT+QSIMSTAT?'
config custom-commands
option description '设置当前使用的为卡1 > AT+QUIMSLOT=1'
option command 'AT+QUIMSLOT=1'
config custom-commands
option description '设置当前使用的为卡2 > AT+QUIMSLOT=2'
option command 'AT+QUIMSLOT=2'
config custom-commands
option description '查询网络信息 > AT+QNWINFO'
option command 'AT+QNWINFO'
config custom-commands
option description '查询SIM卡签约速率 > AT+QNWCFG="nr5g_ambr"'
option command 'AT+QNWCFG="nr5g_ambr"'
config custom-commands
option description '查询载波聚合参数 > AT+QCAINFO'
option command 'AT+QCAINFO'
config custom-commands
option description '查询当前拨号模式 > AT+QCFG="usbnet"'
option command 'AT+QCFG="usbnet"'
config custom-commands
option description 'QMI/GobiNet拨号 > AT+QCFG="usbnet",0'
option command 'AT+QCFG="usbnet",0'
config custom-commands
option description 'ECM拨号 > AT+QCFG="usbnet",1'
option command 'AT+QCFG="usbnet",1'
config custom-commands
option description 'MBIM拨号 > AT+QCFG="usbnet",2'
option command 'AT+QCFG="usbnet",2'
config custom-commands
option description 'RNDIS拨号 > AT+QCFG="usbnet",3'
option command 'AT+QCFG="usbnet",3'
config custom-commands
option description 'NCM拨号 > AT+QCFG="usbnet",5'
option command 'AT+QCFG="usbnet",5'
config custom-commands
option description '锁4G > AT+QNWPREFCFG="mode_pref",LTE'
option command 'AT+QNWPREFCFG="mode_pref",LTE'
config custom-commands
option description '锁5G > AT+QNWPREFCFG="mode_pref",NR5G'
option command 'AT+QNWPREFCFG="mode_pref",NR5G'
config custom-commands
option description '锁5G NSA > AT+QNWPREFCFG="mode_pref",NR5G-NSA'
option command 'AT+QNWPREFCFG="mode_pref",NR5G-NSA'
config custom-commands
option description '锁5G SA > AT+QNWPREFCFG="mode_pref",NR5G-SA'
option command 'AT+QNWPREFCFG="mode_pref",NR5G-SA'
config custom-commands
option description '恢复自动搜索网络 > AT+QNWPREFCFG="mode_pref",AUTO'
option command 'AT+QNWPREFCFG="mode_pref",AUTO'
config custom-commands
option description '查询模组IMEI > AT+EGMR=0,7'
option command 'AT+EGMR=0,7'
config custom-commands
option description '更改模组IMEI > AT+EGMR=1,7,"IMEI"'
option command 'AT+EGMR=1,7,"在此设置IMEI"'
config custom-commands
option description '获取模组温度 > AT+QTEMP'
option command 'AT+QTEMP'
config custom-commands
option description '切换为USB通信端口 > AT+QCFG="data_interface",0,0'
option command 'AT+QCFG="data_interface",0,0'
config custom-commands
option description '切换为PCI通信端口 > AT+QCFG="data_interface",1,0'
option command 'AT+QCFG="data_interface",1,0'
config custom-commands
option description '查看当前USB速率 > AT+QCFG="usbspeed"'
option command 'AT+QCFG="usbspeed"'
config custom-commands
option description '切换为USB2.0 > AT+QCFG="usbspeed","20"'
option command 'AT+QCFG="usbspeed","20"'
config custom-commands
option description '切换为USB3.1 Gen1(5Gbps) > AT+QCFG="usbspeed","311"'
option command 'AT+QCFG="usbspeed","311"'
config custom-commands
option description '切换为USB3.1 Gen1(10Gbps) > AT+QCFG="usbspeed","312"'
option command 'AT+QCFG="usbspeed","312"'
config custom-commands
option description '重置模组 > AT+QCFG="ResetFactory"'
option command 'AT+QCFG="ResetFactory"'
config custom-commands
option description '****************广和通****************'
option command 'ATI'
config custom-commands
option description '设置当前使用的为卡1 > AT+GTDUALSIM=0'
option command 'AT+GTDUALSIM=0'
config custom-commands
option description '设置当前使用的为卡2 > AT+GTDUALSIM=1'
option command 'AT+GTDUALSIM=1'
config custom-commands
option description 'ECM手动拨号 > AT+GTRNDIS=1,1'
option command 'AT+GTRNDIS=1,1'
config custom-commands
option description 'ECM拨号断开 > AT+GTRNDIS=0,1'
option command 'AT+GTRNDIS=0,1'
config custom-commands
option description '查询当前端口模式 > AT+GTUSBMODE?'
option command 'AT+GTUSBMODE?'
config custom-commands
option description 'QMI/GobiNet拨号 > AT+GTUSBMODE=32'
option command 'AT+GTUSBMODE=32'
config custom-commands
option description 'ECM拨号 > AT+GTUSBMODE=18'
option command 'AT+GTUSBMODE=18'
config custom-commands
option description 'MBIM拨号 > AT+GTUSBMODE=30'
option command 'AT+GTUSBMODE=30'
config custom-commands
option description 'RNDIS拨号 > AT+GTUSBMODE=24'
option command 'AT+GTUSBMODE=24'
config custom-commands
option description 'NCM拨号 > AT+GTUSBMODE=18'
option command 'AT+GTUSBMODE=18'
config custom-commands
option description '锁4G > AT+GTACT=2'
option command 'AT+GTACT=2'
config custom-commands
option description '锁5G > AT+GTACT=14'
option command 'AT+GTACT=14'
config custom-commands
option description '恢复自动搜索网络 > AT+GTACT=20'
option command 'AT+GTACT=20'
config custom-commands
option description '查询当前连接的网络类型 > AT+PSRAT?'
option command 'AT+PSRAT?'
config custom-commands
option description '查询模组IMEI > AT+GTSN=0,7'
option command 'AT+GTSN=0,7'
config custom-commands
option description '更改模组IMEI > AT+GTSN=1,7,"IMEI"'
option command 'AT+GTSN=1,7,"在此设置IMEI"'
config custom-commands
option description '报告一次当前BBIC的温度 > AT+MTSM=1,6'
option command 'AT+MTSM=1,6'
config custom-commands
option description '报告一次当前射频的温度 > AT+MTSM=1,7'
option command 'AT+MTSM=1,7'
config custom-commands
option description '获取当前温度 > AT+GTLADC'
option command 'AT+GTLADC'
config custom-commands
option description '重启模组 > AT+CFUN=15'
option command 'AT+CFUN=15'
config custom-commands
option description '****************美格****************'
option command 'ATI'
config custom-commands
option description 'SIM卡状态上报 > AT^SIMSLOTURC=1'
option command 'AT^SIMSLOTURC=1'
config custom-commands
option description '获取SIM卡卡槽状态 > AT^SIMSLOT?'
option command 'AT^SIMSLOT?'
config custom-commands
option description '设置当前使用的为卡1 > AT^SIMSLOT=1'
option command 'AT^SIMSLOT=1'
config custom-commands
option description '设置当前使用的为卡2 > AT^SIMSLOT=2'
option command 'AT^SIMSLOT=2'
config custom-commands
option description '查询网络信息 > AT^SYSINFOEX'
option command 'AT^SYSINFOEX'
config custom-commands
option description '查询载波聚合小区信息 > AT^CELLINFO=1'
option command 'AT^CELLINFO=1'
config custom-commands
option description '查询当前拨号模式 > AT+SER?'
option command 'AT+SER?'
config custom-commands
option description 'QMI/GobiNet拨号 > AT+SER=1,1'
option command 'AT+SER=1,1'
config custom-commands
option description 'ECM拨号 > AT+SER=2,1'
option command 'AT+SER=2,1'
config custom-commands
option description 'MBIM拨号 > AT+SER=3,1'
option command 'AT+SER=3,1'
config custom-commands
option description 'RNDIS拨号 > AT+SER=3,1'
option command 'AT+SER=3,1'
config custom-commands
option description 'NCM拨号 > AT+SER=2,1'
option command 'AT+SER=2,1'
config custom-commands
option description '锁4G > AT^SYSCFGEX="03",all,0,2,all,all,all,all,1'
option command 'AT^SYSCFGEX="03",all,0,2,all,all,all,all,1'
config custom-commands
option description '锁5G > AT^SYSCFGEX="04",all,0,2,all,all,all,all,1'
option command 'AT^SYSCFGEX="04",all,0,2,all,all,all,all,1'
config custom-commands
option description '恢复自动搜索网络 > AT^SYSCFGEX="00",all,0,2,all,all,all,all,1'
option command 'AT^SYSCFGEX="00",all,0,2,all,all,all,all,1'
config custom-commands
option description '查询模组IMEI > AT+LCTSN=0,7'
option command 'AT+LCTSN=0,7'
config custom-commands
option description '更改模组IMEI > AT+LCTSN=1,7,"IMEI"'
option command 'AT+LCTSN=1,7,"在此设置IMEI"'
config custom-commands
option description '获取模组温度 > AT+TEMP'
option command 'AT+TEMP'
config custom-commands
option description '重启模组 > AT+RESET'
option command 'AT+RESET'
config custom-commands
option description '****************华为****************'
option command 'ATI'
config custom-commands
option description '获取SIM卡卡槽状态 > AT^SIMSLOT?'
option command 'AT^SIMSLOT?'
config custom-commands
option description '设置当前使用的为卡1 > AT^SIMSWITCH=1'
option command 'AT^SIMSWITCH=1'
config custom-commands
option description '设置当前使用的为卡2 > AT^SIMSWITCH=0'
option command 'AT^SIMSWITCH=0'
config custom-commands
option description '查询网络信息 > AT^SYSINFOEX'
option command 'AT^SYSINFOEX'
config custom-commands
option description '查询当前拨号模式 > AT^SETMODE?'
option command 'AT^SETMODE?'
config custom-commands
option description 'ECM拨号模式(Linux) > AT^SETMODE=0'
option command 'AT^SETMODE=0'
config custom-commands
option description 'NCM拨号模式(Windows) > AT^SETMODE=1'
option command 'AT^SETMODE=1'
config custom-commands
option description 'ECM拨号模式(Linux,Debug) > AT^SETMODE=2'
option command 'AT^SETMODE=2'
config custom-commands
option description 'NCM拨号模式(Windows,Debug) > AT^SETMODE=3'
option command 'AT^SETMODE=3'
config custom-commands
option description '锁4G > AT^SYSCFGEX="03",40000000,1,2,7FFFFFFFFFFFFFFF,,'
option command 'AT^SYSCFGEX="03",40000000,1,2,7FFFFFFFFFFFFFFF,,'
config custom-commands
option description '锁5G > AT^SYSCFGEX="08",40000000,1,2,7FFFFFFFFFFFFFFF,,'
option command 'AT^SYSCFGEX="08",40000000,1,2,7FFFFFFFFFFFFFFF,,'
config custom-commands
option description '恢复自动搜索网络 > AT^SYSCFGEX="00",3FFFFFFF,1,2,7FFFFFFFFFFFFFFF,,'
option command 'AT^SYSCFGEX="00",3FFFFFFF,1,2,7FFFFFFFFFFFFFFF,,'
config custom-commands
option description '获取模组温度 > AT^CHIPTEMP?'
option command 'AT^CHIPTEMP?'
config custom-commands
option description '重启模组 > AT^RESET'
option command 'AT^RESET'
+8
View File
@@ -0,0 +1,8 @@
config global 'global'
option enable_dial '1'
option modem_number '0'
option usb_scan '1'
option pci_scan '1'
option manual_configuration '0'
option network_interface_alias '1'
@@ -0,0 +1,37 @@
#!/bin/sh
# Copyright (C) 2023 Siriling <siriling@qq.com>
#导入组件工具
source "/usr/share/modem/modem_util.sh"
#网络设备名称不存在,退出
[ -z "${INTERFACE}" ] && exit
#网络设备路径不存在,退出
[ -z "${DEVPATH}" ] && exit
#始终确保存在运行目录
mkdir -m 0755 -p "${MODEM_RUNDIR}"
#初始化模组配置
# [[ "${INTERFACE}" = *"ip6tnl0"* ]] && {
# sh "${SCRIPT_DIR}/modem_init.sh"
# }
if [[ "${INTERFACE}" = *"usb"* ]] || [[ "${INTERFACE}" = *"wwan"* ]] || [[ "${INTERFACE}" = *"eth"* ]]; then
#USB扫描
usb_scan=$(uci -q get modem.@global[0].usb_scan)
[ "${usb_scan}" = "0" ] && exit
#配置网络设备
m_set_network_device "${ACTION}" "${INTERFACE}" "/sys${DEVPATH}" "usb"
elif [[ "${INTERFACE}" = *"mhi_hwip"* ]] || [[ "${INTERFACE}" = *"rmnet_mhi"* ]]; then
#PCI扫描
pci_scan=$(uci -q get modem.@global[0].pci_scan)
[ "${pci_scan}" = "0" ] && exit
#配置网络设备
m_set_network_device "${ACTION}" "${INTERFACE}" "/sys${DEVPATH}" "pci"
else
exit
fi
@@ -0,0 +1,23 @@
#!/bin/sh
# Copyright (C) 2023 Siriling <siriling@qq.com>
#导入组件工具
source "/usr/share/modem/modem_util.sh"
#只在添加和移除的时候执行
# [ "$ACTION" != "add" ] && [ "$ACTION" != "remove" ] && exit
#设备号不存在,退出(去掉多余的tty设备)
[ -z "${DEVNUM}" ] && exit
#测试
# test_usb_hotplug
#始终确保存在运行目录
mkdir -m 0755 -p "${MODEM_RUNDIR}"
#USB扫描
usb_scan=$(uci -q get modem.@global[0].usb_scan)
[ "${usb_scan}" = "0" ] && exit
#检查USB设备
m_check_usb_device "${ACTION}" "${DEVNUM}" "${PRODUCT}" "/sys${DEVPATH}"
+780
View File
@@ -0,0 +1,780 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2023 Siriling <siriling@qq.com>
START=90
STOP=13
USE_PROCD=1
#脚本目录
SCRIPT_DIR="/usr/share/modem"
#运行目录
MODEM_RUNDIR="/var/run/modem"
MODEM_RUN_CONFIG="${MODEM_RUNDIR}/config.cache"
#导入组件工具
source "${SCRIPT_DIR}/modem_scan.sh"
#设置防火墙
# $1:网络接口名称
set_firewall()
{
local interface_name="$1"
local num=$(uci show firewall | grep "name='wan'" | wc -l)
local wwan_num=$(uci -q get firewall.@zone[$num].network | grep -w "${interface_name}" | wc -l)
if [ "$wwan_num" = "0" ]; then
uci add_list firewall.@zone[$num].network="${interface_name}"
fi
uci commit firewall
}
#设置IPv4网络接口
# $1:网络接口名称
# $2:网络接口
set_ipv4_interface()
{
local interface_name="$1"
local network_interface="$2"
#删除原网络配置
uci -q del network.${interface_name}.ipaddr
uci -q del network.${interface_name}.netmask
uci -q del network.${interface_name}.gateway
uci -q del network.${interface_name}.peerdns
uci -q del network.${interface_name}.dns
#添加或修改网络配置
uci set network.${interface_name}='interface'
uci set network.${interface_name}.proto='dhcp'
uci set network.${interface_name}.device="${network_interface}"
uci set network.${interface_name}.device="${network_interface}"
uci commit network
#加入WAN防火墙
set_firewall "${interface_name}"
#启动网络接口
ifup "${interface_name}"
}
#设置IPv6网络接口
# $1:网络接口名称
# $2:网络接口
set_ipv6_interface()
{
local interface_name="$1"
local network_interface="$2"
#添加或修改网络配置
uci set network.${interface_name}='interface'
uci set network.${interface_name}.proto='dhcpv6'
uci set network.${interface_name}.extendprefix='1'
uci set network.${interface_name}.device="${network_interface}"
uci set network.${interface_name}.device="${network_interface}"
uci commit network
#加入WAN防火墙
set_firewall "${interface_name}"
#启动网络接口
ifup "${interface_name}"
}
#设置IPV4和IPv6网络接口
# $1:IPV4网络接口名称
# $2:IPv6网络接口名称
# $3:网络接口
set_ipv4v6_interface()
{
local ipv4_interface_name="$1"
local ipv6_interface_name="$2"
local network_interface="$3"
#设置IPV4网络接口
set_ipv4_interface "${ipv4_interface_name}" "${network_interface}"
#设置IPV6网络接口
local network_interface_alias=$(uci -q get modem.@global[0].network_interface_alias)
case $network_interface_alias in
"0") set_ipv6_interface "${ipv6_interface_name}" "${network_interface}" ;;
"1") set_ipv6_interface "${ipv6_interface_name}" "@${ipv4_interface_name}" ;; #别名
esac
}
#设置网络接口
# $1:模块序号
# $2:网络接口
set_interface()
{
local modem_no="$1"
local network_interface="$2"
case $pdp_type in
"ipv4") set_ipv4_interface "wwan_5g_${modem_no}" "${network_interface}" ;;
"ipv6") set_ipv6_interface "wwan6_5g_${modem_no}" "${network_interface}" ;;
"ipv4v6") set_ipv4v6_interface "wwan_5g_${modem_no}" "wwan6_5g_${modem_no}" "${network_interface}" ;;
*) set_ipv4v6_interface "wwan_5g_${modem_no}" "wwan6_5g_${modem_no}" "${network_interface}" ;;
esac
}
#设置移远模组MAC地址
set_quectel_mac()
{
local mac_address="$(cat /sys/class/net/${network}/address)"
local null_mac="00:00:00:00:00:00"
[ -z "$mac_address" ] || [ "$mac_address" = "$null_mac" ] && {
#方法一(lua)
# local mac_address=$(lua -e 'math.randomseed(os.time()); for i=1,6 do io.write(string.format("%02X", math.random(0, 255))); if i < 6 then io.write(":") end; end')
#方法二(shell)
mac_address="$(m_generate_mac_address)"
ifconfig "${network}" hw ether "${mac_address}"
}
}
#移远拨号工具
quectel_cm()
{
#获取制造商
local manufacturer=$(uci -q get modem.modem${modem_no}.manufacturer)
#移远500系列模组特殊处理(解决在6.x内核下缺失MAC地址使用制造商驱动导致拨号异常问题)
[ "$manufacturer" = "quectel" ] && set_quectel_mac
#拨号
procd_open_instance
procd_set_param command "quectel-CM"
case $pdp_type in
"ipv4") procd_append_param command "-4" ;;
"ipv6") procd_append_param command "-6" ;;
"ipv4v6") procd_append_param command "-4" "-6" ;;
*) procd_append_param command "-4" "-6" ;;
esac
if [ "$network_bridge" = "1" ]; then
procd_append_param command "-b"
fi
if [ "$apn" != "" ]; then
procd_append_param command "-s" "$apn"
fi
if [ "$username" != "" ]; then
procd_append_param command "$username"
fi
if [ "$password" != "" ]; then
procd_append_param command "$password"
fi
if [ "$auth" != "none" ]; then
procd_append_param command "$auth"
fi
if [ "$network" != "" ]; then
procd_append_param command "-i" "$network"
fi
#日志
procd_append_param command "-f" "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
procd_set_param respawn
procd_set_param procd_pid "${MODEM_RUNDIR}/modem${modem_no}.pid"
procd_close_instance
}
#设置网络接口(Modem Manager)
# $1:接口名称
# $2:模组路径
set_interface_modemmanager()
{
local interface_name="$1"
local path="$2"
if [ "$(uci -q get network.${interface_name}.device)" != "${path}" ] ; then
uci set network.${interface_name}='interface'
uci set network.${interface_name}.proto='modemmanager'
uci set network.${interface_name}.device="${path}"
uci set network.${interface_name}.auth="$auth"
uci set network.${interface_name}.iptype="$pdp_type"
if [ "$apn" != "" ]; then
uci set network.${interface_name}.apn="$apn"
fi
if [ "$pincode" != "" ]; then
uci set network.${interface_name}.pincode="$pincode"
fi
if [ "$username" != "" ]; then
uci set network.${interface_name}.username="$username"
fi
if [ "$password" != "" ]; then
uci set network.${interface_name}.password="$password"
fi
uci commit network
#加入WAN防火墙
set_firewall "${interface_name}"
fi
#启动网络接口
ifup "${interface_name}"
}
#模块管理
modemmanager()
{
#获取接口名称
local interface_name="wwan_5g_${modem_no}"
#获取调制解调器设备(模组路径)
local path=$(uci -q get modem.modem${modem_no}.path)
#设置Modem Manager网络接口
set_interface_modemmanager "$interface_name" "$path"
#拨号
procd_open_instance
procd_set_param command sh ${SCRIPT_DIR}/modem_network_task.sh "${id}" "${modem_no}" "modemmanager"
procd_set_param respawn
procd_close_instance
}
qmi()
{
#选择拨号工具
case $dial_tool in
"quectel-CM") quectel_cm ;;
"mmcli") modemmanager ;;
"") quectel_cm ;;
*) quectel_cm ;;
esac
}
gobinet()
{
#获取制造商
local manufacturer=$(uci -q get modem.modem${modem_no}.manufacturer)
#拨号
case $manufacturer in
"quectel") qmi ;;
*)
procd_open_instance
procd_set_param command sh ${SCRIPT_DIR}/modem_network_task.sh "${id}" "${modem_no}" "gobinet"
procd_set_param respawn
procd_close_instance
;;
esac
}
ecm()
{
#拨号
procd_open_instance
procd_set_param command sh ${SCRIPT_DIR}/modem_network_task.sh "${id}" "${modem_no}" "ecm"
procd_set_param respawn
procd_close_instance
}
mbim()
{
qmi
}
rndis()
{
#拨号
procd_open_instance
procd_set_param command sh ${SCRIPT_DIR}/modem_network_task.sh "${id}" "${modem_no}" "rndis"
procd_set_param respawn
procd_close_instance
}
ncm()
{
ecm
}
stop_qmi()
{
#获取modem的实例信息
local response=$(ubus call service list '{"name": "modem"}')
local instance_number=$(echo "$response" | jq -r '.modem.instances | length')
for i in $(seq 1 $((instance_number))); do
#获取拨号命令
local command=$(echo "$response" | jq -r ".modem.instances.instance$i.command")
#移远拨号工具
if [[ "$command" = *"$network"* ]]; then
local pid=$(echo "$response" | jq -r ".modem.instances.$i.pid")
kill $pid >/dev/null 2>&1
fi
#Modem Manager
#获取接口名称
local interface_name="wwan_5g_${modem_no}"
if [[ "$command" = *"$interface_name"* ]]; then
local pid=$(echo "$response" | jq -r ".modem.instances.$i.pid")
kill $pid >/dev/null 2>&1
#获取调制解调器设备(模组路径)
local path=$(uci -q get modem.modem${modem_no}.path)
mmcli -m "$path" --simple-disconnect
#删除网络接口
uci -q del network.${interface_name}
uci commit network
fi
done
}
stop_gobinet()
{
#获取AT串口、制造商
local at_port=$(uci -q get modem.modem${modem_no}.at_port)
local manufacturer=$(uci -q get modem.modem${modem_no}.manufacturer)
#停止拨号
local at_command
if [ "$manufacturer" = "quectel" ]; then
stop_qmi
elif [ "$manufacturer" = "fibocom" ]; then
at_command='AT$QCRMCALL=0,1'
elif [ "$manufacturer" = "meig" ]; then
at_command="AT$QCRMCALL=0,1,${define_connect},2,1"
else
at_command='ATI'
fi
tmp=$(at "${at_port}" "${at_command}")
}
stop_ecm()
{
#获取名称、AT串口、制造商、平台、连接定义
local name=$(uci -q get modem.modem${modem_no}.name)
local at_port=$(uci -q get modem.modem${modem_no}.at_port)
local manufacturer=$(uci -q get modem.modem${modem_no}.manufacturer)
local platform=$(uci -q get modem.modem${modem_no}.platform)
local define_connect=$(uci -q get modem.modem${modem_no}.define_connect)
#停止拨号
local at_command
if [ "$manufacturer" = "quectel" ]; then
at_command="AT+QNETDEVCTL=${define_connect},0,1"
elif [ "$manufacturer" = "fibocom" ]; then
#联发科平台(广和通FM350-GL)
if [ "$platform" = "mediatek" ]; then
at_command="AT+CGACT=0,${define_connect}"
else
at_command="AT+GTRNDIS=0,${define_connect}"
fi
elif [ "$manufacturer" = "meig" ]; then
at_command="AT^NDISDUP=${define_connect},0"
elif [ "$manufacturer" = "huawei" ]; then
at_command="AT^NDISDUP=${define_connect},0"
elif [ "$manufacturer" = "tdtech" ]; then
at_command="AT^NDISDUP=${define_connect},0"
else
at_command='ATI'
fi
tmp=$(at "${at_port}" "${at_command}")
}
stop_mbim()
{
stop_qmi
}
stop_rndis()
{
stop_ecm
#广和通的rndis和ecm不同,后续再测试
}
stop_ncm()
{
stop_ecm
}
#获取模块序号
# $1:移动网络
get_modem_no()
{
local modem_number=$(uci -q get modem.@global[0].modem_number)
local modem_network
for i in $(seq 0 $((modem_number-1))); do
modem_network=$(uci -q get modem.modem${i}.network)
if [ "$modem_network" = "$1" ]; then
#模块序号
modem_no=${i}
break
fi
done
}
#获取实例运行状态(未使用)
# $1:配置ID
get_instance_status()
{
local config_id="$1"
#获取modem的实例信息
local response=$(ubus call service list '{"name": "modem"}')
local instance_number=$(echo "$response" | jq -r ".modem.instances | length")
for i in $(seq 1 $((instance_number))); do
#获取运行状态和拨号命令
local running_status=$(echo "$response" | jq -r ".modem.instances.instance$i.running")
local command=$(echo "$response" | jq -r ".modem.instances.instance$i.command")
if [ "$running_status" = "true" ] && [[ "$command" = *"$network"* ]]; then
#查看配置ID是否记录在已运行的文件里
local run_config="/var/run/modem"
local run_config_id=$(grep -n "$network" "$run_config" | cut -d ',' -f 2)
if [ "${config_id}" = "$run_config_id" ]; then
status=2
break
else
status=1
break
fi
fi
done
}
#通过AT命令获取拨号模式
# $1:模组序号
get_mode_by_at_command()
{
local modem_no="$1"
local manufacturer=$(uci -q get modem.modem${modem_no}.manufacturer)
local at_port=$(uci -q get modem.modem${modem_no}.at_port)
local platform=$(uci -q get modem.modem${modem_no}.platform)
mode=$(${manufacturer}_get_mode ${at_port} ${platform})
echo "$mode"
}
#获取拨号模式
# $1:模组序号
get_mode()
{
local modem_no="$1"
#获取模组驱动
local driver=$(uci -q get modem.modem${modem_no}.net_driver)
local mode
if [[ "$driver" = *"qmi_wwan"* ]] || [ "$driver" = "mhi_wwan_ctrl" ] || [ "$driver" = "mhi_net" ] || [ "$driver" = "mhi_netdev" ]; then
mode="qmi"
elif [[ "$driver" = *"GobiNet"* ]]; then
mode="gobinet"
elif [ "$driver" = "cdc_ether" ]; then
mode="ecm"
elif [ "$driver" = "cdc_mbim" ] || ["$driver" = "mhi_wwan_mbim"]; then
mode="mbim"
elif [ "$driver" = "rndis_host" ]; then
mode="rndis"
elif [ "$driver" = "cdc_ncm" ]; then
mode="ncm"
else
mode="unknown"
fi
echo "$mode"
}
#网络预设
connect_presets()
{
local at_port=$(uci -q get modem.modem${modem_no}.at_port)
#运营商选择设置
local at_command='AT+COPS=0,0'
tmp=$(at "${at_port}" "${at_command}")
#获取连接定义
local define_connect=$(uci -q get modem.modem${modem_no}.define_connect)
#获取PDP类型和APN
local pdp_type_tmp="IPV4V6"
if [ -n "$pdp_type" ]; then
pdp_type_tmp=$(echo $pdp_type | tr 'a-z' 'A-Z')
fi
local apn_tmp=""
if [ -n "$apn" ]; then
apn_tmp=$(echo $apn | tr 'a-z' 'A-Z')
fi
#PDP设置
at_command="AT+CGDCONT=$define_connect,\"$pdp_type_tmp\",\"$apn_tmp\""
tmp=$(at "${at_port}" "${at_command}")
#制造商私有预设
# quectel_presets
# fibocom_presets
}
#停止拨号
# $1:配置ID
stop_dial()
{
local id="$1" #配置ID
local network=$(uci -q get modem.$1.network) #移动网络
#把配置ID从临时列表中移除
if [ -f "${MODEM_RUN_CONFIG}" ] && grep -q "${network}" "${MODEM_RUN_CONFIG}"; then
#该配置ID在运行,需要删除记录
sed -i "/${id}/d" "${MODEM_RUN_CONFIG}"
#获取模块序号
get_modem_no "${network}"
#获取模组的拨号模式
[ -z "${modem_no}" ] && return 0
local mode=$(get_mode ${modem_no})
[ -z "$mode" ] || [ "$mode" = "unknown" ] && return
#根据不同的拨号模式停止拨号
if [ "$mode" = "qmi" ]; then
stop_qmi
elif [ "$mode" = "gobinet" ]; then
stop_gobinet
elif [ "$mode" = "ecm" ]; then
stop_ecm
elif [ "$mode" = "mbim" ]; then
stop_mbim
elif [ "$mode" = "rndis" ]; then
stop_rndis
elif [ "$mode" = "ncm" ]; then
stop_ncm
fi
fi
}
dial()
{
local enable #启用
local id #ID
config_get enable $1 enable
config_get id $1 id
#停止拨号配置
[ "$enable" = "0" ] && {
stop_dial "$id"
return 0
}
local remarks #备注
local network #移动网络
local dial_tool #拨号工具
local pdp_type #网络类型(IP类型)
local network_bridge #网络桥接
local apn #接入点
local username #用户名
local password #密码
local auth #认证类型
config_get remarks $1 remarks
config_get network $1 network
config_get dial_tool $1 dial_tool
config_get pdp_type $1 pdp_type
config_get network_bridge $1 network_bridge
config_get apn $1 apn
config_get username $1 username
config_get password $1 password
config_get auth $1 auth
#获取模块序号
get_modem_no "${network}"
[ -z "${modem_no}" ] && return 0
#获取模组的拨号模式
local time=20
local mode
for i in $(seq 1 ${time}); do
mode=$(get_mode ${modem_no})
[ -n "$mode" ] && [ "$mode" != "unknown" ] && break
sleep 5s
done
#获取不到拨号模式
[ -z "$mode" ] || [ "$mode" = "unknown" ] && {
uci set modem.$1.enable=0
uci commit modem
return 0
}
#查看该移动网络是否已经有拨号配置在运行
mkdir -m 0755 -p "${MODEM_RUNDIR}"
if [ ! -f "${MODEM_RUN_CONFIG}" ] || ! grep -q "${network}" "${MODEM_RUN_CONFIG}"; then
#文件不存在或者未记录该移动网络
echo "${network},${id}" >> "${MODEM_RUN_CONFIG}"
#获取网络接口
local network_interface=$(uci -q get modem.modem${modem_no}.network_interface)
#设置网络接口
set_interface "${modem_no}" "${network_interface}"
else
local config_id=$(awk -v network="${network}" -F',' '!/^#/ && $0 ~ network { print $2 }' "${MODEM_RUN_CONFIG}")
#该移动网络已存在,且已有其他拨号配置在运行
if [ "$id" != "$config_id" ]; then
uci set modem.$1.enable=0
uci commit modem
return 0
fi
fi
#设置网络预设
connect_presets
#根据不同的拨号模式拨号
if [ "$mode" = "qmi" ]; then
qmi
elif [ "$mode" = "gobinet" ]; then
gobinet
elif [ "$mode" = "ecm" ]; then
ecm
elif [ "$mode" = "mbim" ]; then
mbim
elif [ "$mode" = "rndis" ]; then
rndis
elif [ "$mode" = "ncm" ]; then
ncm
fi
# sleep 15
}
#手动设置模组信息
manual_set_modem_config()
{
local manual #手动配置
local network #移动网络
# local name #模组名称
# local at_port #AT串口
config_get manual $1 manual
config_get network $1 network
# config_get name $1 name
# config_get at_port $1 at_port
[ -z "$manual" ] || [ "$manual" = "0" ] && return
#获取网络设备路径
local network_path="$(readlink -f /sys/class/net/${network})"
#只处理最上级的网络设备
local count=$(echo "${network_path}" | grep -o "/net" | wc -l)
[ "$count" -ge "2" ] && return
#判断路径是否带有usb(排除其他eth网络设备)
[[ "$network" = *"eth"* ]] && [[ "$network_path" != *"usb"* ]] && return
#获取物理路径
local physical_path=$(m_get_device_physical_path ${network_path})
#获取当前模组数量(下面新增配置会导致多一个,这里需要减掉一个)
local modem_number=$(uci -q get modem.@global[0].modem_number)
uci set modem.@global[0].modem_number=$((modem_number-1))
#设置模组硬件配置
local modem_no=$(m_set_modem_hardware_config "${physical_path}")
[ -z "$modem_no" ] && return
#设置模组网络配置
# m_set_network_config "${modem_no}" "${network}"
#设置模组子设备配置(网络和串口)
m_set_subdevice_config "${modem_no}" "1"
#设置模组配置
m_set_modem_more_config "${modem_no}"
uci commit modem
}
#删除拨号配置
del_dial_config()
{
#运行配置是否存在
if [ -f "${MODEM_RUN_CONFIG}" ]; then
local configs=$(cat ${MODEM_RUN_CONFIG})
for config in $configs; do
#设置标志位
local flag="0"
local id=$(echo "$config" | awk -F',' '{print $2}')
local config_number=2
for i in $(seq 0 $((config_number-1))); do
local config_id=$(uci -q get modem.@dial-config[${i}].id)
[ "$config_id" = "$id" ] && {
flag="1"
}
done
#删除运行配置
[ "$flag" = "0" ] && {
sed -i "/${id}/d" "${MODEM_RUN_CONFIG}"
}
done
fi
}
#统计模组数量
count_modem_number()
{
local network #移动网络
config_get network $1 network
modem_count=$((modem_count+1))
}
service_triggers()
{
procd_add_reload_trigger "modem"
}
start_service() {
#加载模组配置
config_load modem
#统计模组数量
modem_count=0
config_foreach count_modem_number "modem-device"
#设置模组数量
uci set modem.@global[0].modem_number=${modem_count}
uci commit modem
#手动设置模组信息
config_foreach manual_set_modem_config "modem-device"
local enable_dial=$(uci -q get modem.@global[0].enable_dial)
if [ "$enable_dial" = "0" ]; then
stop_service
else
#删除拨号配置
del_dial_config
#加载拨号配置
config_foreach dial "dial-config"
fi
}
stop_service()
{
#删除记录文件
rm -rf ${MODEM_RUN_CONFIG}
#停止qmi、mbim拨号
killall quectel-CM >/dev/null 2>&1
#停止gobinet、ecm、rndis、ncm拨号
local modem_number=$(uci -q get modem.@global[0].modem_number)
for i in $(seq 0 $((modem_number-1))); do
modem_no=$i
local mode=$(uci -q get modem.modem${modem_no}.mode)
case $mode in
"gobinet") stop_gobinet ;;
"ecm") stop_ecm ;;
"rndis") stop_rndis ;;
"ncm") stop_ncm ;;
*) stop_ecm ;;
esac
done
}
reload_service() {
restart
}
+20
View File
@@ -0,0 +1,20 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2023 Siriling <siriling@qq.com>
START=70
STOP=13
USE_PROCD=1
#脚本目录
SCRIPT_DIR="/usr/share/modem"
start_service()
{
# 暂时弃用
# /bin/sh ${SCRIPT_DIR}/modem_init.sh
echo "init"
# procd_open_instance #启动实例
# procd_set_param command /bin/sh /usr/share/modem/modem_init.sh
# procd_set_param respawn # 定义respawn参数,告知procd当task程序退出后尝试进行重启
# procd_close_instance #关闭实例
}
@@ -0,0 +1,34 @@
#!/bin/sh
[ ! -f "/usr/share/ucitrack/luci-app-modem.json" ] && {
cat > /usr/share/ucitrack/luci-app-modem.json << EEOF
{
"config": "modem",
"init": "modem"
}
EEOF
}
# Copyright (C) 2023 Siriling <siriling@qq.com>
uci -q get modem.global >/dev/null || uci -q batch <<-EOF >/dev/null
set modem.global=global
set modem.@global[0].enable_dial=1
set modem.@global[0].modem_number=0
set modem.@global[0].usb_scan=1
set modem.@global[0].pci_scan=1
set modem.@global[0].manual_configuration=0
set modem.@global[0].network_interface_alias=1
commit modem
EOF
/etc/init.d/modeminit enable
/etc/init.d/modem enable
uci -q batch <<-EOF >/dev/null
delete ucitrack.@modem[-1]
add ucitrack modem
set ucitrack.@modem[-1].init=modem
commit ucitrack
EOF
rm -rf /tmp/luci-*cache
exit 0
@@ -0,0 +1,182 @@
{
"quick_commands":{
"general":[
{"模组信息 > ATI":"ATI"},
{"查询SIM卡状态 > AT+CPIN?":"AT+CPIN?"},
{"查询网络信号质量(4G) > AT+CSQ":"AT+CSQ"},
{"查询网络信号质量(5G) > AT+CESQ":"AT+CESQ"},
{"查询网络信息 > AT+COPS?":"AT+COPS?"},
{"查询PDP信息 > AT+CGDCONT?":"AT+CGDCONT?"},
{"查询PDP地址 > AT+CGPADDR":"AT+CGPADDR"},
{"查询模组IMEI > AT+CGSN":"AT+CGSN"},
{"查询模组IMEI > AT+GSN":"AT+GSN"},
{"查看当前电压 > AT+CBC":"AT+CBC"},
{"最小功能模式 > AT+CFUN=0":"AT+CFUN=0"},
{"全功能模式 > AT+CFUN=1":"AT+CFUN=1"},
{"重启模组 > AT+CFUN=1,1":"AT+CFUN=1,1"}
],
"quectel":{
"qualcomm":[
{"SIM卡状态上报 > AT+QSIMSTAT?":"AT+QSIMSTAT?"},
{"设置当前使用的为卡1 > AT+QUIMSLOT=1":"AT+QUIMSLOT=1"},
{"设置当前使用的为卡2 > AT+QUIMSLOT=2":"AT+QUIMSLOT=2"},
{"查询网络信息 > AT+QNWINFO":"AT+QNWINFO"},
{"查询载波聚合参数 > AT+QCAINFO":"AT+QCAINFO"},
{"查询当前拨号模式 > AT+QCFG=\"usbnet\"":"AT+QCFG=\"usbnet\""},
{"QMI/GobiNet拨号模式 > AT+QCFG=\"usbnet\",0":"AT+QCFG=\"usbnet\",0"},
{"ECM拨号模式 > AT+QCFG=\"usbnet\",1":"AT+QCFG=\"usbnet\",1"},
{"MBIM拨号模式 > AT+QCFG=\"usbnet\",2":"AT+QCFG=\"usbnet\",2"},
{"RNDIS拨号模式 > AT+QCFG=\"usbnet\",3":"AT+QCFG=\"usbnet\",3"},
{"NCM拨号模式 > AT+QCFG=\"usbnet\",5":"AT+QCFG=\"usbnet\",5"},
{"锁4G > AT+QNWPREFCFG=\"mode_pref\",LTE":"AT+QNWPREFCFG=\"mode_pref\",LTE"},
{"锁5G > AT+QNWPREFCFG=\"mode_pref\",NR5G":"AT+QNWPREFCFG=\"mode_pref\",NR5G"},
{"锁5G NSA > AT+QNWPREFCFG=\"mode_pref\",NR5G-NSA":"AT+QNWPREFCFG=\"mode_pref\",NR5G-NSA"},
{"锁5G SA > AT+QNWPREFCFG=\"mode_pref\",NR5G-SA":"AT+QNWPREFCFG=\"mode_pref\",NR5G-SA"},
{"恢复自动搜索网络 > AT+QNWPREFCFG=\"mode_pref\",AUTO":"AT+QNWPREFCFG=\"mode_pref\",AUTO"},
{"查询模组IMEI > AT+EGMR=0,7":"AT+EGMR=0,7"},
{"更改模组IMEI > AT+EGMR=1,7,\"IMEI\"":"AT+EGMR=1,7,\"在此设置IMEI\""},
{"获取模组温度 > AT+QTEMP":"AT+QTEMP"},
{"切换为USB通信端口 > AT+QCFG=\"data_interface\",0,0":"AT+QCFG=\"data_interface\",0,0"},
{"切换为PCI通信端口 > AT+QCFG=\"data_interface\",1,0":"AT+QCFG=\"data_interface\",1,0"},
{"查看当前USB速率 > AT+QCFG=\"usbspeed\"":"AT+QCFG=\"usbspeed\""},
{"切换为USB2.0 > AT+QCFG=\"usbspeed\",\"20\"":"AT+QCFG=\"usbspeed\",\"20\""},
{"切换为USB3.1 Gen1(5Gbps) > AT+QCFG=\"usbspeed\",\"311\"":"AT+QCFG=\"usbspeed\",\"311\""},
{"切换为USB3.1 Gen1(10Gbps) > AT+QCFG=\"usbspeed\",\"312\"":"AT+QCFG=\"usbspeed\",\"312\""},
{"重置模组 > AT+QCFG=\"ResetFactory\"":"AT+QCFG=\"ResetFactory\""}
],
"unisoc":[
{"SIM卡状态上报 > AT+QSIMSTAT?":"AT+QSIMSTAT?"},
{"设置当前使用的为卡1 > AT+QUIMSLOT=1":"AT+QUIMSLOT=1"},
{"设置当前使用的为卡2 > AT+QUIMSLOT=2":"AT+QUIMSLOT=2"},
{"查询网络信息 > AT+QNWINFO":"AT+QNWINFO"},
{"查询载波聚合参数 > AT+QCAINFO":"AT+QCAINFO"},
{"查询当前拨号模式 > AT+QCFG=\"usbnet\"":"AT+QCFG=\"usbnet\""},
{"ECM拨号模式 > AT+QCFG=\"usbnet\",1":"AT+QCFG=\"usbnet\",1"},
{"MBIM拨号模式 > AT+QCFG=\"usbnet\",2":"AT+QCFG=\"usbnet\",2"},
{"RNDIS拨号模式 > AT+QCFG=\"usbnet\",3":"AT+QCFG=\"usbnet\",3"},
{"NCM拨号模式 > AT+QCFG=\"usbnet\",5":"AT+QCFG=\"usbnet\",5"},
{"锁4G > AT+QNWPREFCFG=\"mode_pref\",LTE":"AT+QNWPREFCFG=\"mode_pref\",LTE"},
{"锁5G > AT+QNWPREFCFG=\"mode_pref\",NR5G":"AT+QNWPREFCFG=\"mode_pref\",NR5G"},
{"锁5G NSA > AT+QNWPREFCFG=\"mode_pref\",NR5G-NSA":"AT+QNWPREFCFG=\"mode_pref\",NR5G-NSA"},
{"锁5G SA > AT+QNWPREFCFG=\"mode_pref\",NR5G-SA":"AT+QNWPREFCFG=\"mode_pref\",NR5G-SA"},
{"恢复自动搜索网络 > AT+QNWPREFCFG=\"mode_pref\",AUTO":"AT+QNWPREFCFG=\"mode_pref\",AUTO"},
{"查询模组IMEI > AT+EGMR=0,7":"AT+EGMR=0,7"},
{"更改模组IMEI > AT+EGMR=1,7,\"IMEI\"":"AT+EGMR=1,7,\"在此设置IMEI\""},
{"获取模组温度 > AT+QTEMP":"AT+QTEMP"},
{"切换为USB通信端口 > AT+QCFG=\"data_interface\",0,0":"AT+QCFG=\"data_interface\",0,0"},
{"切换为PCI通信端口 > AT+QCFG=\"data_interface\",1,0":"AT+QCFG=\"data_interface\",1,0"},
{"查看当前USB速率 > AT+QCFG=\"usbspeed\"":"AT+QCFG=\"usbspeed\""},
{"切换为USB2.0 > AT+QCFG=\"usbspeed\",\"20\"":"AT+QCFG=\"usbspeed\",\"20\""},
{"切换为USB3.1 Gen1(5Gbps) > AT+QCFG=\"usbspeed\",\"311\"":"AT+QCFG=\"usbspeed\",\"311\""},
{"切换为USB3.1 Gen1(10Gbps) > AT+QCFG=\"usbspeed\",\"312\"":"AT+QCFG=\"usbspeed\",\"312\""},
{"重置模组 > AT+QCFG=\"ResetFactory\"":"AT+QCFG=\"ResetFactory\""}
]
},
"fibocom":{
"qualcomm":[
{"设置当前使用的为卡1 > AT+GTDUALSIM=0":"AT+GTDUALSIM=0"},
{"设置当前使用的为卡2 > AT+GTDUALSIM=1":"AT+GTDUALSIM=1"},
{"ECM手动拨号 > AT+GTRNDIS=1,1":"AT+GTRNDIS=1,1"},
{"ECM拨号断开 > AT+GTRNDIS=0,1":"AT+GTRNDIS=0,1"},
{"查询当前端口模式 > AT+GTUSBMODE?":"AT+GTUSBMODE?"},
{"QMI/GobiNet拨号模式 > AT+GTUSBMODE=32":"AT+GTUSBMODE=32"},
{"ECM拨号模式 > AT+GTUSBMODE=18":"AT+GTUSBMODE=18"},
{"MBIM拨号模式 > AT+GTUSBMODE=30":"AT+GTUSBMODE=30"},
{"RNDIS拨号模式 > AT+GTUSBMODE=24":"AT+GTUSBMODE=24"},
{"NCM拨号模式 > AT+GTUSBMODE=18":"AT+GTUSBMODE=18"},
{"锁4G > AT+GTACT=2":"AT+GTACT=2"},
{"锁5G > AT+GTACT=14":"AT+GTACT=14"},
{"恢复自动搜索网络 > AT+GTACT=20":"AT+GTACT=20"},
{"查询当前连接的网络类型 > AT+PSRAT?":"AT+PSRAT?"},
{"查询模组IMEI > AT+GTSN=0,7":"AT+GTSN=0,7"},
{"更改模组IMEI > AT+GTSN=1,7,\"IMEI\"":"AT+GTSN=1,7,\"在此设置IMEI\""},
{"报告一次当前BBIC的温度 > AT+MTSM=1,6":"AT+MTSM=1,6"},
{"报告一次当前射频的温度 > AT+MTSM=1,7":"AT+MTSM=1,7"},
{"重启模组 > AT+CFUN=15":"AT+CFUN=15"}
],
"unisoc":[
{"设置当前使用的为卡1 > AT+GTDUALSIM=0":"AT+GTDUALSIM=0"},
{"设置当前使用的为卡2 > AT+GTDUALSIM=1":"AT+GTDUALSIM=1"},
{"ECM手动拨号 > AT+GTRNDIS=1,1":"AT+GTRNDIS=1,1"},
{"ECM拨号断开 > AT+GTRNDIS=0,1":"AT+GTRNDIS=0,1"},
{"查询当前端口模式 > AT+GTUSBMODE?":"AT+GTUSBMODE?"},
{"ECM拨号模式 > AT+GTUSBMODE=18":"AT+GTUSBMODE=18"},
{"MBIM拨号模式 > AT+GTUSBMODE=30":"AT+GTUSBMODE=30"},
{"RNDIS拨号模式 > AT+GTUSBMODE=24":"AT+GTUSBMODE=24"},
{"NCM拨号模式 > AT+GTUSBMODE=18":"AT+GTUSBMODE=18"},
{"锁4G > AT+GTACT=2":"AT+GTACT=2"},
{"锁5G > AT+GTACT=14":"AT+GTACT=14"},
{"恢复自动搜索网络 > AT+GTACT=20":"AT+GTACT=20"},
{"查询当前连接的网络类型 > AT+PSRAT?":"AT+PSRAT?"},
{"查询模组IMEI > AT+GTSN=0,7":"AT+GTSN=0,7"},
{"更改模组IMEI > AT+GTSN=1,7,\"IMEI\"":"AT+GTSN=1,7,\"在此设置IMEI\""},
{"报告一次当前BBIC的温度 > AT+MTSM=1,6":"AT+MTSM=1,6"},
{"报告一次当前射频的温度 > AT+MTSM=1,7":"AT+MTSM=1,7"},
{"重启模组 > AT+CFUN=15":"AT+CFUN=15"}
],
"mediatek":[
{"设置当前使用的为卡1 > AT+GTDUALSIM=0":"AT+GTDUALSIM=0"},
{"设置当前使用的为卡2 > AT+GTDUALSIM=1":"AT+GTDUALSIM=1"},
{"手动设置接入点 > AT+CGDCONT=3,\"IPV4V6\",\"APN\"":"AT+CGDCONT=3,\"IPV4V6\",\"在此设置APN\""},
{"手动拨号 > AT+CGACT=1,3":"AT+CGACT=1,3"},
{"停止拨号 > AT+CGACT=0,3":"AT+CGACT=0,3"},
{"查询当前端口模式 > AT+GTUSBMODE?":"AT+GTUSBMODE?"},
{"RNDIS拨号模式(40) > AT+GTUSBMODE=40":"AT+GTUSBMODE=40"},
{"RNDIS拨号模式(41) > AT+GTUSBMODE=41":"AT+GTUSBMODE=41"},
{"锁4G > AT+GTACT=2":"AT+GTACT=2"},
{"锁5G > AT+GTACT=14":"AT+GTACT=14"},
{"恢复自动搜索网络 > AT+GTACT=20":"AT+GTACT=20"},
{"查询当前连接的网络类型 > AT+PSRAT?":"AT+PSRAT?"},
{"查询载波聚合小区信息 > AT+GTCAINFO?":"AT+GTCAINFO?"},
{"查询模组IMEI > AT+GTSN=0,7":"AT+GTSN=0,7"},
{"更改模组IMEI > AT+GTSN=1,7,\"IMEI\"":"AT+GTSN=1,7,\"在此设置IMEI\""},
{"解锁FCC > AT+GTFCCLOCKMODE=0":"AT+GTFCCLOCKMODE=0"},
{"解除ESIM锁定 > AT+GTESIMCFG=0,0,0":"AT+GTESIMCFG=0,0,0"},
{"解除温控 > AT+GTTHERMAL=0":"AT+GTTHERMAL=0"},
{"获取当前温度 > AT+GTSENRDTEMP=0":"AT+GTSENRDTEMP=0"},
{"重启模组 > AT+CFUN=15":"AT+CFUN=15"}
]
},
"meig":{
"qualcomm":[
{"SIM卡状态上报 > AT^SIMSLOTURC=1":"AT^SIMSLOTURC=1"},
{"获取SIM卡卡槽状态 > AT^SIMSLOT?":"AT^SIMSLOT?"},
{"设置当前使用的为卡1 > AT^SIMSLOT=1":"AT^SIMSLOT=1"},
{"设置当前使用的为卡2 > AT^SIMSLOT=2":"AT^SIMSLOT=2"},
{"查询网络信息 > AT^SYSINFOEX":"AT^SYSINFOEX"},
{"查询载波聚合小区信息 > AT^CELLINFO=1":"AT^CELLINFO=1"},
{"查询当前拨号模式 > AT+SER?":"AT+SER?"},
{"QMI/GobiNet拨号模式 > AT+SER=1,1":"AT+SER=1,1"},
{"ECM拨号模式 > AT+SER=2,1":"AT+SER=2,1"},
{"MBIM拨号模式 > AT+SER=3,1":"AT+SER=3,1"},
{"RNDIS拨号模式 > AT+SER=3,1":"AT+SER=3,1"},
{"NCM拨号模式 > AT+SER=2,1":"AT+SER=2,1"},
{"锁4G > AT^SYSCFGEX=\"03\",all,0,2,all,all,all,all,1":"AT^SYSCFGEX=\"03\",all,0,2,all,all,all,all,1"},
{"锁5G > AT^SYSCFGEX=\"04\",all,0,2,all,all,all,all,1":"AT^SYSCFGEX=\"04\",all,0,2,all,all,all,all,1"},
{"恢复自动搜索网络 > AT^SYSCFGEX=\"00\",all,0,2,all,all,all,all,1":"AT^SYSCFGEX=\"00\",all,0,2,all,all,all,all,1"},
{"查询模组IMEI > AT+LCTSN=0,7":"AT+LCTSN=0,7"},
{"更改模组IMEI > AT+LCTSN=1,7,\"IMEI\"":"AT+LCTSN=1,7,\"在此设置IMEI\""},
{"获取模组温度 > AT+TEMP":"AT+TEMP"},
{"重启模组 > AT+RESET":"AT+RESET"}
]
},
"huawei":{
"hisilicon":[
{"获取SIM卡卡槽状态 > AT^SIMSLOT?":"AT^SIMSLOT?"},
{"设置当前使用的为卡1 > AT^SIMSWITCH=1":"AT^SIMSWITCH=1"},
{"设置当前使用的为卡2 > AT^SIMSWITCH=0":"AT^SIMSWITCH=0"},
{"查询网络信息 > AT^SYSINFOEX":"AT^SYSINFOEX"},
{"查询当前拨号模式 > AT^SETMODE?":"AT^SETMODE?"},
{"ECM拨号模式(Linux) > AT^SETMODE=0":"AT^SETMODE=0"},
{"NCM拨号模式(Windows) > AT^SETMODE=1":"AT^SETMODE=1"},
{"ECM拨号模式(Linux,Debug) > AT^SETMODE=2":"AT^SETMODE=2"},
{"NCM拨号模式(Windows,Debug) > AT^SETMODE=3":"AT^SETMODE=3"},
{"锁4G > AT^SYSCFGEX=\"03\",40000000,1,2,7FFFFFFFFFFFFFFF,,":"AT^SYSCFGEX=\"03\",40000000,1,2,7FFFFFFFFFFFFFFF,,"},
{"锁5G > AT^SYSCFGEX=\"08\",40000000,1,2,7FFFFFFFFFFFFFFF,,":"AT^SYSCFGEX=\"08\",40000000,1,2,7FFFFFFFFFFFFFFF,,"},
{"恢复自动搜索网络 > AT^SYSCFGEX=\"00\",3FFFFFFF,1,2,7FFFFFFFFFFFFFFF,,":"AT^SYSCFGEX=\"00\",3FFFFFFF,1,2,7FFFFFFFFFFFFFFF,,"},
{"获取模组温度 > AT^CHIPTEMP?":"AT^CHIPTEMP?"},
{"重启模组 > AT^RESET":"AT^RESET"}
]
}
}
}
File diff suppressed because it is too large. Load diff
+928
View File
@@ -0,0 +1,928 @@
#!/bin/sh
# Copyright (C) 2023 Siriling <siriling@qq.com>
#脚本目录
SCRIPT_DIR="/usr/share/modem"
#预设
huawei_presets()
{
#关闭模组主动上报
at_command='AT^CURC=0'
sh "${SCRIPT_DIR}/modem_at.sh" "$at_port" "$at_command"
#开启5G NA NSA接入
at_command='AT^C5GOPTION=1,3,3'
sh "${SCRIPT_DIR}/modem_at.sh" "$at_port" "$at_command"
}
#获取DNS
# $1:AT串口
# $2:连接定义
huawei_get_dns()
{
local at_port="$1"
local define_connect="$2"
[ -z "$define_connect" ] && {
define_connect="1"
}
local public_dns1_ipv4="223.5.5.5"
local public_dns2_ipv4="119.29.29.29"
local public_dns1_ipv6="2400:3200::1" #下一代互联网北京研究中心:240C::6666,阿里:2400:3200::1,腾讯:2402:4e00::
local public_dns2_ipv6="2402:4e00::"
#获取DNS地址(IPv4)
at_command="AT^DHCP=${define_connect}"
local response=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "\^DHCP:" | sed -n '1p')
local ipv4_dns1=$(echo "${response}" | awk -F',' '{print $5}')
if [ -z "$ipv4_dns1" ]; then
ipv4_dns1="${public_dns1_ipv4}"
else
#按字节(byte)将十六进制拆分并转换为对应的十进制表示
ipv4_dns1=$(echo "$ipv4_dns1" | awk '{
for (i = length; i >= 1; i -= 2) {
printf "%d.", "0x" substr($0, i-1, 2)
}
}')
ipv4_dns1="${ipv4_dns1%?}"
fi
local ipv4_dns2=$(echo "${response}" | awk -F',' '{print $6}')
if [ -z "$ipv4_dns2" ]; then
ipv4_dns2="${public_dns1_ipv4}"
else
#按字节(byte)将十六进制拆分并转换为对应的十进制表示
ipv4_dns2=$(echo "$ipv4_dns2" | awk '{
for (i = length; i >= 1; i -= 2) {
printf "%d.", "0x" substr($0, i-1, 2)
}
}')
ipv4_dns2="${ipv4_dns2%?}"
fi
#获取DNS地址(IPv6)
at_command="AT^DHCPV6=${define_connect}"
local response=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "\^DHCPV6:" | sed -n '1p')
local ipv6_dns1=$(echo "${response}" | awk -F',' '{print $5}')
[ -z "$ipv6_dns1" ] && {
ipv6_dns1="${public_dns1_ipv6}"
}
local ipv6_dns2=$(echo "${response}" | awk -F',' '{print $6}')
[ -z "$ipv6_dns2" ] && {
ipv6_dns2="${public_dns2_ipv6}"
}
dns="{
\"dns\":{
\"ipv4_dns1\":\"$ipv4_dns1\",
\"ipv4_dns2\":\"$ipv4_dns2\",
\"ipv6_dns1\":\"$ipv6_dns1\",
\"ipv6_dns2\":\"$ipv6_dns2\"
}
}"
echo "$dns"
}
#获取拨号模式
# $1:AT串口
# $2:平台
huawei_get_mode()
{
local at_port="$1"
local platform="$2"
at_command="AT^SETMODE?"
local mode_num=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "\^SETMODE:" | awk -F': ' '{print $2}' | sed 's/\r//g')
if [ -z "$mode_num" ]; then
echo "unknown"
return
fi
#获取芯片平台
if [ -z "$platform" ]; then
local modem_number=$(uci -q get modem.@global[0].modem_number)
for i in $(seq 0 $((modem_number-1))); do
local at_port_tmp=$(uci -q get modem.modem$i.at_port)
if [ "$at_port" = "$at_port_tmp" ]; then
platform=$(uci -q get modem.modem$i.platform)
break
fi
done
fi
local mode
case "$platform" in
"hisilicon")
case "$mode_num" in
"0"|"2") mode="ecm" ;;
"1"|"3"|"4"|"5") mode="ncm" ;;
"6") mode="rndis" ;;
"7") mode="mbim" ;;
"8") mode="ppp" ;;
*) mode="$mode_num" ;;
esac
;;
*)
mode="$mode_num"
;;
esac
echo "${mode}"
}
#设置拨号模式
# $1:AT串口
# $2:拨号模式配置
huawei_set_mode()
{
local at_port="$1"
local mode_config="$2"
#获取芯片平台
local platform
local modem_number=$(uci -q get modem.@global[0].modem_number)
for i in $(seq 0 $((modem_number-1))); do
local at_port_tmp=$(uci -q get modem.modem$i.at_port)
if [ "$at_port" = "$at_port_tmp" ]; then
platform=$(uci -q get modem.modem$i.platform)
break
fi
done
#获取拨号模式配置
local mode_num
case "$platform" in
"hisilicon")
case "$mode_config" in
"ecm") mode_num="0" ;;
"ncm") mode_num="4" ;;
*) mode_num="0" ;;
esac
;;
*)
mode_num="0"
;;
esac
#设置模组
at_command="AT^SETMODE=${mode_num}"
sh ${SCRIPT_DIR}/modem_at.sh ${at_port} "${at_command}"
}
#获取位
# $1:频段名称
huawei_get_bit()
{
local band_name="$1"
local bit
case "$band_name" in
"DCS_1800") bit="8" ;;
"E-GSM_900"|"E_GSM_900") bit="9" ;;
"P-GSM_900"|"P_GSM_900") bit="10" ;;
"GSM_450") bit="17" ;;
"GSM_480") bit="18" ;;
"GSM_750") bit="19" ;;
"GSM_850") bit="20" ;;
"R-GSM_900"|"R_GSM_900") bit="21" ;;
"PCS_1900") bit="22" ;;
esac
echo "${bit}"
}
#获取频段信息
# $1:频段二进制数
# $2:支持的频段
# $3:频段类型(2G,3G,4G,5G)
huawei_get_band_info()
{
local band_bin="$1"
local support_band="$2"
local band_type="$3"
local band_info=""
local support_band=$(echo "$support_band" | sed 's/,/ /g')
if [ "$band_type" = "2G" ]; then
for band in $support_band; do
#获取bit位
local bit=$(huawei_get_bit ${band})
#获取值
local enable="${band_bin: $((-bit)):1}"
[ -z "$enable" ] && enable="0"
#设置频段信息
# band_info=$(echo ${band_info} | jq '. += [{"'$band'":'$enable'}]')
band_info="${band_info},{\"$band\":$enable}"
done
else
#频段频段起始,前缀位置
local start_bit
local band_prefix
case "$band_type" in
"3G")
start_bit="23"
band_prefix="WCDMA_B"
;;
"4G")
start_bit="1"
band_prefix="LTE_BC"
;;
"5G")
start_bit="1"
band_prefix="NR5G_N"
;;
esac
for band in $support_band; do
#获取值(从start_bit位开始)
local enable="${band_bin: $((-band-start_bit+1)):1}"
[ -z "$enable" ] && enable="0"
#设置频段信息
# band_info=$(echo ${band_info} | jq '. += [{'$band_prefix$band':'$enable'}]')
band_info="${band_info},{\"$band_prefix$band\":$enable}"
done
fi
#去掉第一个,
band_info="["${band_info/,/}"]"
# band_info="[${band_info%?}]"
echo "${band_info}"
}
#获取网络偏好
# $1:AT串口
# $2:数据接口
# $3:模组名称
huawei_get_network_prefer()
{
local at_port="$1"
local data_interface="$2"
local modem_name="$3"
at_command="AT^SYSCFGEX?"
local response=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "\^SYSCFGEX:" | sed 's/\^SYSCFGEX://g')
local network_type_num=$(echo "$response" | awk -F'"' '{print $2}')
#获取网络类型
local network_prefer_2g="0";
local network_prefer_3g="0";
local network_prefer_4g="0";
local network_prefer_5g="0";
#匹配不同的网络类型
local auto=$(echo "${network_type_num}" | grep "00")
if [ -n "$auto" ]; then
network_prefer_2g="1"
network_prefer_3g="1"
network_prefer_4g="1"
network_prefer_5g="1"
else
local gsm=$(echo "${network_type_num}" | grep "01")
local wcdma=$(echo "${network_type_num}" | grep "02")
local lte=$(echo "${network_type_num}" | grep "03")
local nr=$(echo "${network_type_num}" | grep "08")
if [ -n "$gsm" ]; then
network_prefer_2g="1"
fi
if [ -n "$wcdma" ]; then
network_prefer_3g="1"
fi
if [ -n "$lte" ]; then
network_prefer_4g="1"
fi
if [ -n "$nr" ]; then
network_prefer_5g="1"
fi
fi
#获取模组信息
local modem_info=$(jq '.modem_support.'$data_interface'."'$modem_name'"' ${SCRIPT_DIR}/modem_support.json)
#获取模组支持的频段
local support_2g_band=$(echo "$modem_info" | jq -r '.band_2g')
local support_3g_band=$(echo "$modem_info" | jq -r '.band_3g')
local support_4g_band=$(echo "$modem_info" | jq -r '.band_4g')
local support_5g_band=$(echo "$modem_info" | jq -r '.band_5g')
#获取频段信息
local band_hex_2g_3g=$(echo "$response" | awk -F',' '{print $2}')
#十六进制转二进制
local bin_2g_3g=$(echo "obase=2; ibase=16; $band_hex_2g_3g" | bc)
local band_2g_info=$(huawei_get_band_info "${bin_2g_3g}" "${support_2g_band}" "2G")
local band_3g_info=$(huawei_get_band_info "${bin_2g_3g}" "${support_3g_band}" "3G")
local band_hex_4g_5g=$(echo "$response" | awk -F',' '{print $5}' | sed 's/\r//g')
#十六进制转二进制
local bin_4g_5g=$(echo "obase=2; ibase=16; $band_hex_4g_5g" | bc)
local band_4g_info=$(huawei_get_band_info "${bin_4g_5g}" "${support_4g_band}" "4G")
local band_5g_info=$(huawei_get_band_info "${bin_4g_5g}" "${support_5g_band}" "5G")
#生成网络偏好
local network_prefer="{
\"network_prefer\":[
{\"2G\":{
\"enable\":$network_prefer_2g,
\"band\":$band_2g_info
}},
{\"3G\":{
\"enable\":$network_prefer_3g,
\"band\":$band_3g_info
}},
{\"4G\":{
\"enable\":$network_prefer_4g,
\"band\":$band_4g_info
}},
{\"5G\":{
\"enable\":$network_prefer_5g,
\"band\":$band_5g_info
}}
]
}"
echo "${network_prefer}"
}
#设置网络偏好
# $1:AT串口
# $2:网络偏好配置
huawei_set_network_prefer()
{
local at_port="$1"
local network_prefer="$2"
#获取启用的网络偏好
local enable_5g=$(echo "$network_prefer" | jq -r '.["5G"].enable')
local enable_4g=$(echo "$network_prefer" | jq -r '.["4G"].enable')
local enable_3g=$(echo "$network_prefer" | jq -r '.["3G"].enable')
local enable_2g=$(echo "$network_prefer" | jq -r '.["2G"].enable')
#获取网络偏好配置
local network_prefer_config
[ "$enable_5g" = "1" ] && network_prefer_config="${network_prefer_config}08"
[ "$enable_4g" = "1" ] && network_prefer_config="${network_prefer_config}03"
[ "$enable_3g" = "1" ] && network_prefer_config="${network_prefer_config}02"
[ "$enable_2g" = "1" ] && network_prefer_config="${network_prefer_config}01"
[ -z "$network_prefer_config" ] && network_prefer_config="99"
#设置模组
at_command='AT^SYSCFGEX="'${network_prefer_config}'",40000000,1,2,40000000,,'
sh ${SCRIPT_DIR}/modem_at.sh "${at_port}" "${at_command}"
}
#设置频段
# $1:AT串口
# $2:频段偏好配置
huawei_set_band_prefer()
{
local at_port="$1"
local network_prefer="$2"
#获取选中的数量
local count=$(echo "$network_prefer" | grep -o "1" | wc -l)
#获取每个偏好的值
local network_prefer_5g=$(echo "$network_prefer" | jq -r '.["5G"]')
local network_prefer_4g=$(echo "$network_prefer" | jq -r '.["4G"]')
local network_prefer_3g=$(echo "$network_prefer" | jq -r '.["3G"]')
local network_prefer_2g=$(echo "$network_prefer" | jq -r '.["2G"]')
#获取启用的网络偏好
local enable_5g=$(echo "$network_prefer_5g" | jq -r '.enable')
local enable_4g=$(echo "$network_prefer_4g" | jq -r '.enable')
local enable_3g=$(echo "$network_prefer_3g" | jq -r '.enable')
local enable_2g=$(echo "$network_prefer_2g" | jq -r '.enable')
#获取网络偏好配置和频段偏好配置
local network_prefer_config
local band_hex_2g_3g=0
local band_hex_4g_5g=0
[ "$enable_5g" = "1" ] && {
network_prefer_config="${network_prefer_config}08"
local band_tmp=$(echo "$network_prefer_5g" | jq -r '.band[]')
local i=0
local bands=$(echo "$band_tmp" | jq -r 'to_entries | .[] | .key')
#遍历band的值
for band in $bands; do
local value=$(echo "$network_prefer_5g" | jq -r '.band'"[$i].$band")
[ "$value" = "1" ] && {
#获取bit位
local bit=$(echo "$band" | sed 's/NR5G_N//g')
#获取值
local result=$(echo "obase=16; ibase=10; 2^($bit-1)" | bc)
band_hex_4g_5g=$(echo "obase=16; ibase=16; $band_hex_4g_5g + $result" | bc)
}
i=$((i+1))
done
}
[ "$enable_4g" = "1" ] && {
network_prefer_config="${network_prefer_config}03"
local band_tmp=$(echo "$network_prefer_4g" | jq -r '.band[]')
local i=0
local bands=$(echo "$band_tmp" | jq -r 'to_entries | .[] | .key')
#遍历band的值
for band in $bands; do
local value=$(echo "$network_prefer_4g" | jq -r '.band'"[$i].$band")
[ "$value" = "1" ] && {
#获取bit位
local bit=$(echo "$band" | sed 's/LTE_BC//g')
#获取值
local result=$(echo "obase=16; ibase=10; 2^($bit-1)" | bc)
band_hex_4g_5g=$(echo "obase=16; ibase=16; $band_hex_4g_5g + $result" | bc)
}
i=$((i+1))
done
}
[ "$enable_3g" = "1" ] && {
network_prefer_config="${network_prefer_config}02"
local band_tmp=$(echo "$network_prefer_3g" | jq -r '.band[]')
local i=0
local bands=$(echo "$band_tmp" | jq -r 'to_entries | .[] | .key')
#遍历band的值
for band in $bands; do
local value=$(echo "$network_prefer_3g" | jq -r '.band'"[$i].$band")
[ "$value" = "1" ] && {
#获取bit位
local bit=$(echo "$band" | sed 's/WCDMA_B//g')
#获取值
local result=$(echo "obase=16; ibase=10; 2^($bit+22-1)" | bc)
band_hex_2g_3g=$(echo "obase=16; ibase=16; $band_hex_2g_3g + $result" | bc)
}
i=$((i+1))
done
}
[ "$enable_2g" = "1" ] && {
network_prefer_config="${network_prefer_config}01"
local band_tmp=$(echo "$network_prefer_2g" | jq -r '.band[]')
local i=0
local bands=$(echo "$band_tmp" | jq -r 'to_entries | .[] | .key')
#遍历band的值
for band in $bands; do
# band_format=$(echo "$band" | sed 's/-/_/g')
local value=$(echo "$network_prefer_2g" | jq -r '.band'"[$i].$band")
[ "$value" = "1" ] && {
#获取bit位
local bit=$(huawei_get_bit ${band})
#获取值
local result=$(echo "obase=16; ibase=10; 2^($bit-1)" | bc)
band_hex_2g_3g=$(echo "obase=16; ibase=16; $band_hex_2g_3g + $result" | bc)
}
i=$((i+1))
done
}
[ -z "$network_prefer_config" ] && network_prefer_config="99"
#设置模组
at_command='AT^SYSCFGEX="'${network_prefer_config}'",'"${band_hex_2g_3g},1,2,${band_hex_4g_5g},,"
sh ${SCRIPT_DIR}/modem_at.sh "${at_port}" "${at_command}"
}
#获取电压
# $1:AT串口
huawei_get_voltage()
{
local at_port="$1"
# #Voltage(电压)
# at_command="AT+ADCREAD=0"
# local voltage=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | grep "+ADCREAD:" | awk -F' ' '{print $2}' | sed 's/\r//g')
# voltage=$(awk "BEGIN{ printf \"%.2f\", $voltage / 1000000 }" | sed 's/\.*0*$//')
# echo "${voltage}"
}
#获取温度
# $1:AT串口
huawei_get_temperature()
{
local at_port="$1"
#Temperature(温度)
at_command="AT^CHIPTEMP?"
response=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | grep "\^CHIPTEMP" | awk -F',' '{print $6}' | sed 's/\r//g')
local temperature
if [ -n "$response" ]; then
response=$(awk "BEGIN{ printf \"%.2f\", $response / 10 }" | sed 's/\.*0*$//')
temperature="${response}$(printf "\xc2\xb0")C"
else
temperature="NaN $(printf "\xc2\xb0")C"
fi
echo "${temperature}"
}
#获取连接状态
# $1:AT串口
# $2:连接定义
huawei_get_connect_status()
{
local at_port="$1"
local define_connect="$2"
#默认值为1
[ -z "$define_connect" ] && {
define_connect="1"
}
at_command="AT+CGPADDR=${define_connect}"
local ipv4=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "+CGPADDR: " | awk -F'"' '{print $2}')
local not_ip="0.0.0.0"
#设置连接状态
local connect_status
if [ -z "$ipv4" ] || [[ "$ipv4" = *"$not_ip"* ]]; then
connect_status="disconnect"
else
connect_status="connect"
fi
echo "${connect_status}"
}
#基本信息
huawei_base_info()
{
debug "Huawei base info"
#Name(名称)
at_command="AT+CGMM"
name=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | grep "+CGMM: " | awk -F': ' '{print $2}' | sed 's/\r//g')
#Manufacturer(制造商)
at_command="AT+CGMI"
manufacturer=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | sed -n '2p' | sed 's/\r//g')
#Revision(固件版本)
at_command="AT+CGMR"
revision=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | sed -n '2p' | sed 's/\r//g')
#Mode(拨号模式)
mode=$(huawei_get_mode ${at_port} ${platform} | tr 'a-z' 'A-Z')
#Temperature(温度)
temperature=$(huawei_get_temperature ${at_port})
}
#获取SIM卡状态
# $1:SIM卡状态标志
huawei_get_sim_status()
{
local sim_status
case $1 in
"") sim_status="miss" ;;
*"ERROR"*) sim_status="miss" ;;
*"READY"*) sim_status="ready" ;;
*"SIM PIN"*) sim_status="MT is waiting SIM PIN to be given" ;;
*"SIM PUK"*) sim_status="MT is waiting SIM PUK to be given" ;;
*"PH-FSIM PIN"*) sim_status="MT is waiting phone-to-SIM card password to be given" ;;
*"PH-FSIM PIN"*) sim_status="MT is waiting phone-to-very first SIM card password to be given" ;;
*"PH-FSIM PUK"*) sim_status="MT is waiting phone-to-very first SIM card unblocking password to be given" ;;
*"SIM PIN2"*) sim_status="MT is waiting SIM PIN2 to be given" ;;
*"SIM PUK2"*) sim_status="MT is waiting SIM PUK2 to be given" ;;
*"PH-NET PIN"*) sim_status="MT is waiting network personalization password to be given" ;;
*"PH-NET PUK"*) sim_status="MT is waiting network personalization unblocking password to be given" ;;
*"PH-NETSUB PIN"*) sim_status="MT is waiting network subset personalization password to be given" ;;
*"PH-NETSUB PUK"*) sim_status="MT is waiting network subset personalization unblocking password to be given" ;;
*"PH-SP PIN"*) sim_status="MT is waiting service provider personalization password to be given" ;;
*"PH-SP PUK"*) sim_status="MT is waiting service provider personalization unblocking password to be given" ;;
*"PH-CORP PIN"*) sim_status="MT is waiting corporate personalization password to be given" ;;
*"PH-CORP PUK"*) sim_status="MT is waiting corporate personalization unblocking password to be given" ;;
*) sim_status="unknown" ;;
esac
echo "${sim_status}"
}
#SIM卡信息
huawei_sim_info()
{
debug "Huawei sim info"
#SIM Slot(SIM卡卡槽)
# at_command="AT^SIMSLOT?"
# response=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "\^SIMSLOT:" | awk -F': ' '{print $2}' | awk -F',' '{print $2}')
# if [ "$response" != "0" ]; then
# sim_slot="1"
# else
# sim_slot="2"
# fi
sim_slot="1"
#IMEI(国际移动设备识别码)
at_command="AT+CGSN"
imei=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | sed -n '2p' | sed 's/\r//g')
#SIM Status(SIM状态)
at_command="AT+CPIN?"
sim_status_flag=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "+CPIN: ")
sim_status=$(huawei_get_sim_status "$sim_status_flag")
if [ "$sim_status" != "ready" ]; then
return
fi
#ISP(互联网服务提供商)
at_command="AT+COPS?"
isp=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "+COPS" | awk -F'"' '{print $2}')
# if [ "$isp" = "CHN-CMCC" ] || [ "$isp" = "CMCC" ] || [ "$isp" = "46000" ]; then
# isp="中国移动"
# elif [ "$isp" = "CHN-UNICOM" ] || [ "$isp" = "UNICOM" ] || [ "$isp" = "46001" ]; then
# isp="中国联通"
# elif [ "$isp" = "CHN-CT" ] || [ "$isp" = "CT" ] || [ "$isp" = "46011" ]; then
# isp="中国电信"
# fi
#SIM Number(SIM卡号码,手机号)
at_command="AT+CNUM"
sim_number=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "+CNUM: " | awk -F'"' '{print $2}')
[ -z "$sim_number" ] && {
sim_number=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "+CNUM: " | awk -F'"' '{print $4}')
}
#IMSI(国际移动用户识别码)
at_command="AT+CIMI"
imsi=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | sed -n '2p' | sed 's/\r//g')
#ICCID(集成电路卡识别码)
at_command="AT+ICCID"
iccid=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep -o "+ICCID:[ ]*[-0-9]\+" | grep -o "[-0-9]\{1,4\}")
}
#获取网络类型
# $1:网络类型数字
huawei_get_rat()
{
local rat
case $1 in
"0"|"1"|"3"|"8") rat="GSM" ;;
"2"|"4"|"5"|"6"|"9"|"10") rat="WCDMA" ;;
"7") rat="LTE" ;;
"11"|"12") rat="NR" ;;
esac
echo "${rat}"
}
#获取信号强度指示(4G)
# $1:信号强度指示数字
huawei_get_rssi()
{
local rssi
case $1 in
"99") rssi="unknown" ;;
* ) rssi=$((2 * $1 - 113)) ;;
esac
echo "$rssi"
}
#网络信息
huawei_network_info()
{
debug "Huawei network info"
#Connect Status(连接状态)
connect_status=$(huawei_get_connect_status ${at_port} ${define_connect})
if [ "$connect_status" != "connect" ]; then
return
fi
#Network Type(网络类型)
at_command="AT^SYSINFOEX"
network_type=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "\^SYSINFOEX:" | awk -F'"' '{print $4}')
[ -z "$network_type" ] && {
at_command='AT+COPS?'
local rat_num=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "+COPS:" | awk -F',' '{print $4}' | sed 's/\r//g')
network_type=$(huawei_get_rat ${rat_num})
}
#设置网络类型为5G时,信号强度指示用RSRP代替
# at_command="AT+GTCSQNREN=1"
# sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command
#CSQ(信号强度)
at_command="AT+CSQ"
response=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | grep "+CSQ:" | sed 's/+CSQ: //g' | sed 's/\r//g')
#RSSI(4G信号强度指示)
# rssi_num=$(echo $response | awk -F',' '{print $1}')
# rssi=$(huawei_get_rssi $rssi_num)
#BER(4G信道误码率)
# ber=$(echo $response | awk -F',' '{print $2}')
# #PER(信号强度)
# if [ -n "$csq" ]; then
# per=$(($csq * 100/31))"%"
# fi
#AMBR(最大比特率)
at_command="AT^DHCP?"
response=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | grep "\^DHCP:" | sed 's/\^DHCP: //g' | sed 's/\r//g')
ambr_ul_tmp=$(echo "$response" | awk -F',' '{print $8}')
ambr_dl_tmp=$(echo "$response" | awk -F',' '{print $7}')
[ -z "$ambr_ul_tmp" ] && {
at_command="AT^DHCPV6?"
response=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | grep "\^DHCPV6:" | sed 's/\^DHCPV6: //g' | sed 's/\r//g')
ambr_ul_tmp=$(echo "$response" | awk -F',' '{print $8}')
ambr_dl_tmp=$(echo "$response" | awk -F',' '{print $7}')
}
#AMBR UL(上行签约速率,单位,Mbps)
ambr_ul=$(awk "BEGIN{ printf \"%.2f\", $ambr_ul_tmp / 1000000 }" | sed 's/\.*0*$//')
#AMBR DL(下行签约速率,单位,Mbps)
ambr_dl=$(awk "BEGIN{ printf \"%.2f\", $ambr_dl_tmp / 1000000 }" | sed 's/\.*0*$//')
# #速率统计
# at_command='AT^DSFLOWQRY'
# response=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | grep "\^DSFLOWRPT:" | sed 's/\^DSFLOWRPT: //g' | sed 's/\r//g')
# #当前上传速率(单位,Byte/s)
# tx_rate=$(echo $response | awk -F',' '{print $1}')
# #当前下载速率(单位,Byte/s)
# rx_rate=$(echo $response | awk -F',' '{print $2}')
}
#获取NR子载波间隔
# $1:NR子载波间隔数字
huawei_get_scs()
{
local scs
case $1 in
"0") scs="15" ;;
"1") scs="30" ;;
"2") scs="60" ;;
"3") scs="120" ;;
"4") scs="240" ;;
*) scs=$(awk "BEGIN{ print 2^$1 * 15 }") ;;
esac
echo "$scs"
}
#获取频段
# $1:网络类型
# $2:频段数字
huawei_get_band()
{
local band
case $1 in
"GSM")
case $2 in
"0") band="850" ;;
"1") band="900" ;;
"2") band="1800" ;;
"3") band="1900" ;;
esac
;;
"WCDMA") band="$2" ;;
"LTE") band="$(($2-100))" ;;
"NR") band="$2" band="${band#*50}" ;;
esac
echo "$band"
}
#小区信息
huawei_cell_info()
{
debug "Huawei cell info"
at_command="AT^MONSC"
response=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | grep "\^MONSC:" | sed 's/\^MONSC: //')
local rat=$(echo "$response" | awk -F',' '{print $1}')
case $rat in
"NR")
network_mode="NR5G-SA Mode"
nr_mcc=$(echo "$response" | awk -F',' '{print $2}')
nr_mnc=$(echo "$response" | awk -F',' '{print $3}')
nr_arfcn=$(echo "$response" | awk -F',' '{print $4}')
nr_scs_num=$(echo "$response" | awk -F',' '{print $5}')
nr_scs=$(tdtech_get_scs ${nr_scs_num})
nr_cell_id_hex=$(echo "$response" | awk -F',' '{print $6}')
nr_cell_id=$(echo "ibase=16; $nr_cell_id_hex" | bc)
nr_physical_cell_id_hex=$(echo "$response" | awk -F',' '{print $7}')
nr_physical_cell_id=$(echo "ibase=16; $nr_physical_cell_id_hex" | bc)
nr_tac=$(echo "$response" | awk -F',' '{print $8}')
nr_rsrp=$(echo "$response" | awk -F',' '{print $9}')
nr_rsrq=$(echo "$response" | awk -F',' '{print $10}')
nr_sinr=$(echo "$response" | awk -F',' '{print $11}' | sed 's/\r//g')
;;
"LTE-NR")
network_mode="EN-DC Mode"
#LTE
endc_lte_mcc=$(echo "$response" | awk -F',' '{print $2}')
endc_lte_mnc=$(echo "$response" | awk -F',' '{print $3}')
endc_lte_earfcn=$(echo "$response" | awk -F',' '{print $4}')
endc_lte_cell_id_hex=$(echo "$response" | awk -F',' '{print $5}')
endc_lte_cell_id=$(echo "ibase=16; $endc_lte_cell_id_hex" | bc)
endc_lte_physical_cell_id_hex=$(echo "$response" | awk -F',' '{print $6}')
endc_lte_physical_cell_id=$(echo "ibase=16; $endc_lte_physical_cell_id_hex" | bc)
endc_lte_tac=$(echo "$response" | awk -F',' '{print $7}')
endc_lte_rsrp=$(echo "$response" | awk -F',' '{print $8}')
endc_lte_rsrq=$(echo "$response" | awk -F',' '{print $9}')
endc_lte_rxlev=$(echo "$response" | awk -F',' '{print $10}' | sed 's/\r//g')
#NR5G-NSA
endc_nr_mcc=$(echo "$response" | awk -F',' '{print $2}')
endc_nr_mnc=$(echo "$response" | awk -F',' '{print $3}')
endc_nr_arfcn=$(echo "$response" | awk -F',' '{print $4}')
endc_nr_scs_num=$(echo "$response" | awk -F',' '{print $5}')
endc_nr_scs=$(tdtech_get_scs ${nr_scs_num})
endc_nr_cell_id_hex=$(echo "$response" | awk -F',' '{print $6}')
endc_nr_cell_id=$(echo "ibase=16; $endc_nr_cell_id_hex" | bc)
endc_nr_physical_cell_id_hex=$(echo "$response" | awk -F',' '{print $7}')
endc_nr_physical_cell_id=$(echo "ibase=16; $endc_nr_physical_cell_id_hex" | bc)
endc_nr_tac=$(echo "$response" | awk -F',' '{print $8}')
endc_nr_rsrp=$(echo "$response" | awk -F',' '{print $9}')
endc_nr_rsrq=$(echo "$response" | awk -F',' '{print $10}')
endc_nr_sinr=$(echo "$response" | awk -F',' '{print $11}' | sed 's/\r//g')
;;
"LTE"|"eMTC"|"NB-IoT")
network_mode="LTE Mode"
lte_mcc=$(echo "$response" | awk -F',' '{print $2}')
lte_mnc=$(echo "$response" | awk -F',' '{print $3}')
lte_earfcn=$(echo "$response" | awk -F',' '{print $4}')
lte_cell_id_hex=$(echo "$response" | awk -F',' '{print $5}')
lte_cell_id=$(echo "ibase=16; $lte_cell_id_hex" | bc)
lte_physical_cell_id_hex=$(echo "$response" | awk -F',' '{print $6}')
lte_physical_cell_id=$(echo "ibase=16; $lte_physical_cell_id_hex" | bc)
lte_tac=$(echo "$response" | awk -F',' '{print $7}')
lte_rsrp=$(echo "$response" | awk -F',' '{print $8}')
lte_rsrq=$(echo "$response" | awk -F',' '{print $9}')
lte_rxlev=$(echo "$response" | awk -F',' '{print $10}' | sed 's/\r//g')
;;
"WCDMA"|"TD-SCDMA"|"UMTS")
network_mode="WCDMA Mode"
wcdma_mcc=$(echo "$response" | awk -F',' '{print $2}')
wcdma_mnc=$(echo "$response" | awk -F',' '{print $3}')
wcdma_arfcn=$(echo "$response" | awk -F',' '{print $4}')
wcdma_psc=$(echo "$response" | awk -F',' '{print $5}')
wcdma_cell_id_hex=$(echo "$response" | awk -F',' '{print $6}')
wcdma_cell_id=$(echo "ibase=16; $wcdma_cell_id_hex" | bc)
wcdma_lac=$(echo "$response" | awk -F',' '{print $7}')
wcdma_rscp=$(echo "$response" | awk -F',' '{print $8}')
wcdma_rxlev=$(echo "$response" | awk -F',' '{print $9}')
wcdma_ecn0=$(echo "$response" | awk -F',' '{print $10}')
wcdma_drx=$(echo "$response" | awk -F',' '{print $11}')
wcdma_ura=$(echo "$response" | awk -F',' '{print $12}' | sed 's/\r//g')
;;
"GSM")
network_mode="GSM Mode"
gsm_mcc=$(echo "$response" | awk -F',' '{print $2}')
gsm_mnc=$(echo "$response" | awk -F',' '{print $3}')
gsm_band_num=$(echo "$response" | awk -F',' '{print $4}')
gsm_band=$(tdtech_get_band "GSM" ${gsm_band_num})
gsm_arfcn=$(echo "$response" | awk -F',' '{print $5}')
gsm_bsic=$(echo "$response" | awk -F',' '{print $6}')
gsm_cell_id_hex=$(echo "$response" | awk -F',' '{print $7}')
gsm_cell_id=$(echo "ibase=16; $gsm_cell_id_hex" | bc)
gsm_lac=$(echo "$response" | awk -F',' '{print $8}')
gsm_rxlev=$(echo "$response" | awk -F',' '{print $9}')
gsm_rx_quality=$(echo "$response" | awk -F',' '{print $10}')
gsm_ta=$(echo "$response" | awk -F',' '{print $11}' | sed 's/\r//g')
;;
esac
}
#获取华为模组信息
# $1:AT串口
# $2:平台
# $3:连接定义
get_huawei_info()
{
debug "get huawei info"
#设置AT串口
at_port="$1"
platform="$2"
define_connect="$3"
#基本信息
huawei_base_info
#SIM卡信息
huawei_sim_info
if [ "$sim_status" != "ready" ]; then
return
fi
#网络信息
huawei_network_info
if [ "$connect_status" != "connect" ]; then
return
fi
#小区信息
huawei_cell_info
}
+959
View File
@@ -0,0 +1,959 @@
#!/bin/sh
# Copyright (C) 2023 Siriling <siriling@qq.com>
#脚本目录
SCRIPT_DIR="/usr/share/modem"
#预设
meig_presets()
{
#关闭自动上报系统模式变化
at_command='AT^MODE=0'
sh "${SCRIPT_DIR}/modem_at.sh" "$at_port" "$at_command"
#关闭自动上报DS流量
at_command='AT^DSFLOWRPT=0,0,1'
sh "${SCRIPT_DIR}/modem_at.sh" "$at_port" "$at_command"
}
#获取DNS
# $1:AT串口
# $2:连接定义
meig_get_dns()
{
local at_port="$1"
local define_connect="$2"
[ -z "$define_connect" ] && {
define_connect="1"
}
local public_dns1_ipv4="223.5.5.5"
local public_dns2_ipv4="119.29.29.29"
local public_dns1_ipv6="2400:3200::1" #下一代互联网北京研究中心:240C::6666,阿里:2400:3200::1,腾讯:2402:4e00::
local public_dns2_ipv6="2402:4e00::"
#获取DNS地址
at_command="AT+CGCONTRDP=${define_connect}"
local response=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "+CGCONTRDP: " | grep -E '[0-9]+.[0-9]+.[0-9]+.[0-9]+' | sed -n '1p')
local ipv4_dns1=$(echo "${response}" | awk -F',' '{print $7}' | awk -F' ' '{print $1}')
[ -z "$ipv4_dns1" ] && {
ipv4_dns1="${public_dns1_ipv4}"
}
local ipv4_dns2=$(echo "${response}" | awk -F',' '{print $8}' | awk -F' ' '{print $1}')
[ -z "$ipv4_dns2" ] && {
ipv4_dns2="${public_dns2_ipv4}"
}
local ipv6_dns1=$(echo "${response}" | awk -F',' '{print $7}' | awk -F' ' '{print $2}')
[ -z "$ipv6_dns1" ] && {
ipv6_dns1="${public_dns1_ipv6}"
}
local ipv6_dns2=$(echo "${response}" | awk -F',' '{print $8}' | awk -F' ' '{print $2}' | sed 's/\r//g')
[ -z "$ipv6_dns2" ] && {
ipv6_dns2="${public_dns2_ipv6}"
}
dns="{
\"dns\":{
\"ipv4_dns1\":\"$ipv4_dns1\",
\"ipv4_dns2\":\"$ipv4_dns2\",
\"ipv6_dns1\":\"$ipv6_dns1\",
\"ipv6_dns2\":\"$ipv6_dns2\"
}
}"
echo "$dns"
}
#获取拨号模式
# $1:AT串口
# $2:平台
meig_get_mode()
{
local at_port="$1"
local platform="$2"
at_command="AT+SER?"
local mode_num=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "+SER:" | sed 's/+SER: //g' | sed 's/\r//g')
if [ -z "$mode_num" ]; then
echo "unknown"
return
fi
#获取芯片平台
if [ -z "$platform" ]; then
local modem_number=$(uci -q get modem.@global[0].modem_number)
for i in $(seq 0 $((modem_number-1))); do
local at_port_tmp=$(uci -q get modem.modem$i.at_port)
if [ "$at_port" = "$at_port_tmp" ]; then
platform=$(uci -q get modem.modem$i.platform)
break
fi
done
fi
local mode
case "$platform" in
"qualcomm")
case "$mode_num" in
"1") mode="qmi" ;;
# "1") mode="gobinet" ;;
"2") mode="ecm" ;;
"7") mode="mbim" ;;
"3") mode="rndis" ;;
"2") mode="ncm" ;;
"8") mode="unknown" ;;
*) mode="$mode_num" ;;
esac
;;
*)
mode="$mode_num"
;;
esac
echo "${mode}"
}
#设置拨号模式
# $1:AT串口
# $2:拨号模式配置
meig_set_mode()
{
local at_port="$1"
local mode_config="$2"
#获取芯片平台
local platform
local modem_number=$(uci -q get modem.@global[0].modem_number)
for i in $(seq 0 $((modem_number-1))); do
local at_port_tmp=$(uci -q get modem.modem$i.at_port)
if [ "$at_port" = "$at_port_tmp" ]; then
platform=$(uci -q get modem.modem$i.platform)
break
fi
done
#获取拨号模式配置
local mode_num
case "$platform" in
"qualcomm")
case "$mode_config" in
"qmi") mode_num="1" ;;
# "gobinet") mode_num="1" ;;
"ecm") mode_num="2" ;;
"mbim") mode_num="7" ;;
"rndis") mode_num="3" ;;
"ncm") mode_num="2" ;;
*) mode_num="1" ;;
esac
;;
*)
mode_num="1"
;;
esac
#设置模组
at_command="AT+SER=${mode_num},1"
sh ${SCRIPT_DIR}/modem_at.sh ${at_port} "${at_command}"
}
#获取位
# $1:频段名称
meig_get_bit()
{
local band_name="$1"
local bit
case "$band_name" in
"DCS_1800") bit="8" ;;
"E-GSM_900") bit="9" ;;
"P-GSM_900") bit="10" ;;
"GSM_450") bit="17" ;;
"GSM_480") bit="18" ;;
"GSM_750") bit="19" ;;
"GSM_850") bit="20" ;;
"R-GSM_900") bit="21" ;;
"PCS_1900") bit="22" ;;
esac
echo "${bit}"
}
#获取频段信息
# $1:频段二进制数
# $2:支持的频段
# $3:频段类型(2G,3G,4G,5G)
meig_get_band_info()
{
local band_bin="$1"
local support_band="$2"
local band_type="$3"
local band_info=""
local support_band=$(echo "$support_band" | sed 's/,/ /g')
if [ "$band_type" = "2G" ]; then
for band in $support_band; do
#获取bit位
local bit=$(meig_get_bit ${band})
#获取值
local enable="${band_bin: $((-bit)):1}"
[ -z "$enable" ] && enable="0"
#设置频段信息
# band_info=$(echo ${band_info} | jq '. += [{"'$band'":'$enable'}]')
band_info="${band_info},{\"$band\":$enable}"
done
else
#频段频段起始,前缀位置
local start_bit
local band_prefix
case "$band_type" in
"3G")
start_bit="23"
band_prefix="WCDMA_B"
;;
"4G")
start_bit="1"
band_prefix="LTE_BC"
;;
"5G")
start_bit="1"
band_prefix="NR5G_N"
;;
esac
for band in $support_band; do
#获取值(从start_bit位开始)
local enable="${band_bin: $((-band-start_bit+1)):1}"
[ -z "$enable" ] && enable="0"
#设置频段信息
# band_info=$(echo ${band_info} | jq '. += [{'$band_prefix$band':'$enable'}]')
band_info="${band_info},{\"$band_prefix$band\":$enable}"
done
fi
#去掉第一个,
band_info="["${band_info/,/}"]"
# band_info="[${band_info%?}]"
echo "${band_info}"
}
#获取网络偏好
# $1:AT串口
# $2:数据接口
# $3:模组名称
meig_get_network_prefer()
{
local at_port="$1"
local data_interface="$2"
local modem_name="$3"
at_command="AT^SYSCFGEX?"
local response=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "\^SYSCFGEX:" | sed 's/\^SYSCFGEX://g')
local network_type_num=$(echo "$response" | awk -F'"' '{print $2}')
#获取网络类型
local network_prefer_2g="0";
local network_prefer_3g="0";
local network_prefer_4g="0";
local network_prefer_5g="0";
#匹配不同的网络类型
local auto=$(echo "${network_type_num}" | grep "00")
if [ -n "$auto" ]; then
network_prefer_2g="1"
network_prefer_3g="1"
network_prefer_4g="1"
network_prefer_5g="1"
else
local gsm=$(echo "${network_type_num}" | grep "01")
local wcdma=$(echo "${network_type_num}" | grep "02")
local lte=$(echo "${network_type_num}" | grep "03")
local nr=$(echo "${network_type_num}" | grep "04")
if [ -n "$gsm" ]; then
network_prefer_2g="1"
fi
if [ -n "$wcdma" ]; then
network_prefer_3g="1"
fi
if [ -n "$lte" ]; then
network_prefer_4g="1"
fi
if [ -n "$nr" ]; then
network_prefer_5g="1"
fi
fi
#获取模组信息
local modem_info=$(jq '.modem_support.'$data_interface'."'$modem_name'"' ${SCRIPT_DIR}/modem_support.json)
#获取模组支持的频段
local support_2g_band=$(echo "$modem_info" | jq -r '.band_2g')
local support_3g_band=$(echo "$modem_info" | jq -r '.band_3g')
local support_4g_band=$(echo "$modem_info" | jq -r '.band_4g')
local support_5g_band=$(echo "$modem_info" | jq -r '.band_5g')
#获取2G,3G频段信息
local band_hex_2g_3g=$(echo "$response" | awk -F',' '{print $2}')
#十六进制转二进制
local bin_2g_3g=$(echo "obase=2; ibase=16; $band_hex_2g_3g" | bc)
local band_2g_info=$(meig_get_band_info "${bin_2g_3g}" "${support_2g_band}" "2G")
local band_3g_info=$(meig_get_band_info "${bin_2g_3g}" "${support_3g_band}" "3G")
#获取4G频段信息
local band_hex_4g_1=$(echo "$response" | awk -F',' '{print $5}' | sed 's/\r//g')
local band_hex_4g_2=$(echo "$response" | awk -F',' '{print $7}' | sed 's/\r//g')
#十六进制转二进制
local bin_4g=$(echo "obase=2; ibase=16; $band_hex_4g_1 + $band_hex_4g_2" | bc)
local band_4g_info=$(meig_get_band_info "${bin_4g}" "${support_4g_band}" "4G")
#获取5G频段信息
local band_hex_5g_1=$(echo "$response" | awk -F',' '{print $8}' | sed 's/\r//g')
local band_hex_5g_2=$(echo "$response" | awk -F',' '{print $9}' | sed 's/\r//g')
#十六进制转二进制
local bin_5g=$(echo "obase=2; ibase=16; $band_hex_5g_1 + $band_hex_5g_2" | bc)
local band_5g_info=$(meig_get_band_info "${bin_5g}" "${support_5g_band}" "5G")
#生成网络偏好
local network_prefer="{
\"network_prefer\":[
{\"2G\":{
\"enable\":$network_prefer_2g,
\"band\":$band_2g_info
}},
{\"3G\":{
\"enable\":$network_prefer_3g,
\"band\":$band_3g_info
}},
{\"4G\":{
\"enable\":$network_prefer_4g,
\"band\":$band_4g_info
}},
{\"5G\":{
\"enable\":$network_prefer_5g,
\"band\":$band_5g_info
}}
]
}"
echo "${network_prefer}"
}
#设置网络偏好
# $1:AT串口
# $2:网络偏好配置
meig_set_network_prefer()
{
local at_port="$1"
local network_prefer="$2"
#获取网络偏好配置
local network_prefer_config
#获取启用的网络偏好
local enable_5g=$(echo "$network_prefer" | jq -r '.["5G"].enable')
local enable_4g=$(echo "$network_prefer" | jq -r '.["4G"].enable')
local enable_3g=$(echo "$network_prefer" | jq -r '.["3G"].enable')
#获取网络偏好配置
local network_prefer_config
[ "$enable_5g" = "1" ] && network_prefer_config="${network_prefer_config}04"
[ "$enable_4g" = "1" ] && network_prefer_config="${network_prefer_config}03"
[ "$enable_3g" = "1" ] && network_prefer_config="${network_prefer_config}02"
[ -z "$network_prefer_config" ] && network_prefer_config="00"
#设置模组
at_command='AT^SYSCFGEX="'${network_prefer_config}'",all,0,2,all,all,all,all,1'
sh ${SCRIPT_DIR}/modem_at.sh "${at_port}" "${at_command}"
}
#获取电压
# $1:AT串口
meig_get_voltage()
{
local at_port="$1"
# #Voltage(电压)
# at_command="AT+ADCREAD=0"
# local voltage=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | grep "+ADCREAD:" | awk -F' ' '{print $2}' | sed 's/\r//g')
# voltage=$(awk "BEGIN{ printf \"%.2f\", $voltage / 1000000 }" | sed 's/\.*0*$//')
# echo "${voltage}"
}
#获取温度
# $1:AT串口
meig_get_temperature()
{
local at_port="$1"
#Temperature(温度)
at_command="AT+TEMP"
response=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | grep 'TEMP: "cpu0-0-usr"' | awk -F'"' '{print $4}')
local temperature
if [ -n "$response" ]; then
temperature="${response}$(printf "\xc2\xb0")C"
else
temperature="NaN $(printf "\xc2\xb0")C"
fi
echo "${temperature}"
}
#获取连接状态
# $1:AT串口
# $2:连接定义
meig_get_connect_status()
{
local at_port="$1"
local define_connect="$2"
#默认值为1
[ -z "$define_connect" ] && {
define_connect="1"
}
at_command="AT+CGPADDR=${define_connect}"
local ipv4=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "+CGPADDR: " | awk -F',' '{print $2}')
local not_ip="0.0.0.0"
#设置连接状态
local connect_status
if [ -z "$ipv4" ] || [[ "$ipv4" = *"$not_ip"* ]]; then
connect_status="disconnect"
else
connect_status="connect"
fi
echo "${connect_status}"
}
#基本信息
meig_base_info()
{
debug "Meig base info"
#Name(名称)
at_command="AT+CGMM"
name=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | grep "+CGMM: " | awk -F': ' '{print $2}' | sed 's/\r//g')
#Manufacturer(制造商)
at_command="AT+CGMI"
manufacturer=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | grep "+CGMI: " | awk -F': ' '{print $2}' | sed 's/\r//g')
#Revision(固件版本)
at_command="AT+CGMR"
revision=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | grep "+CGMR: " | awk -F': ' '{print $2}' | sed 's/\r//g')
#Mode(拨号模式)
mode=$(meig_get_mode ${at_port} ${platform} | tr 'a-z' 'A-Z')
#Temperature(温度)
temperature=$(meig_get_temperature ${at_port})
}
#获取SIM卡状态
# $1:SIM卡状态标志
meig_get_sim_status()
{
local sim_status
case $1 in
"") sim_status="miss" ;;
*"ERROR"*) sim_status="miss" ;;
*"READY"*) sim_status="ready" ;;
*"SIM PIN"*) sim_status="MT is waiting SIM PIN to be given" ;;
*"SIM PUK"*) sim_status="MT is waiting SIM PUK to be given" ;;
*"PH-FSIM PIN"*) sim_status="MT is waiting phone-to-SIM card password to be given" ;;
*"PH-FSIM PIN"*) sim_status="MT is waiting phone-to-very first SIM card password to be given" ;;
*"PH-FSIM PUK"*) sim_status="MT is waiting phone-to-very first SIM card unblocking password to be given" ;;
*"SIM PIN2"*) sim_status="MT is waiting SIM PIN2 to be given" ;;
*"SIM PUK2"*) sim_status="MT is waiting SIM PUK2 to be given" ;;
*"PH-NET PIN"*) sim_status="MT is waiting network personalization password to be given" ;;
*"PH-NET PUK"*) sim_status="MT is waiting network personalization unblocking password to be given" ;;
*"PH-NETSUB PIN"*) sim_status="MT is waiting network subset personalization password to be given" ;;
*"PH-NETSUB PUK"*) sim_status="MT is waiting network subset personalization unblocking password to be given" ;;
*"PH-SP PIN"*) sim_status="MT is waiting service provider personalization password to be given" ;;
*"PH-SP PUK"*) sim_status="MT is waiting service provider personalization unblocking password to be given" ;;
*"PH-CORP PIN"*) sim_status="MT is waiting corporate personalization password to be given" ;;
*"PH-CORP PUK"*) sim_status="MT is waiting corporate personalization unblocking password to be given" ;;
*) sim_status="unknown" ;;
esac
echo "${sim_status}"
}
#SIM卡信息
meig_sim_info()
{
debug "Meig sim info"
#SIM Slot(SIM卡卡槽)
at_command="AT^SIMSLOT?"
response=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "\^SIMSLOT:" | awk -F': ' '{print $2}' | awk -F',' '{print $2}')
if [ "$response" != "0" ]; then
sim_slot="1"
else
sim_slot="2"
fi
#IMEI(国际移动设备识别码)
at_command="AT+CGSN"
imei=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | sed -n '2p' | sed 's/\r//g')
#SIM Status(SIM状态)
at_command="AT+CPIN?"
sim_status_flag=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "+CPIN: ")
sim_status=$(meig_get_sim_status "$sim_status_flag")
if [ "$sim_status" != "ready" ]; then
return
fi
#ISP(互联网服务提供商)
at_command="AT+COPS?"
isp=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "+COPS" | awk -F'"' '{print $2}')
# if [ "$isp" = "CHN-CMCC" ] || [ "$isp" = "CMCC" ] || [ "$isp" = "46000" ]; then
# isp="中国移动"
# elif [ "$isp" = "CHN-UNICOM" ] || [ "$isp" = "UNICOM" ] || [ "$isp" = "46001" ]; then
# isp="中国联通"
# elif [ "$isp" = "CHN-CT" ] || [ "$isp" = "CT" ] || [ "$isp" = "46011" ]; then
# isp="中国电信"
# fi
#SIM Number(SIM卡号码,手机号)
at_command="AT+CNUM"
sim_number=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "+CNUM: " | awk -F'"' '{print $2}')
[ -z "$sim_number" ] && {
sim_number=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "+CNUM: " | awk -F'"' '{print $4}')
}
#IMSI(国际移动用户识别码)
at_command="AT+CIMI"
imsi=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | sed -n '2p' | sed 's/\r//g')
#ICCID(集成电路卡识别码)
at_command="AT+ICCID"
iccid=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep -o "+ICCID:[ ]*[-0-9]\+" | grep -o "[-0-9]\{1,4\}")
}
#获取网络类型
# $1:网络类型数字
meig_get_rat()
{
local rat
case $1 in
"0"|"1"|"3"|"8") rat="GSM" ;;
"2"|"4"|"5"|"6"|"9"|"10") rat="WCDMA" ;;
"7") rat="LTE" ;;
"11"|"12") rat="NR" ;;
esac
echo "${rat}"
}
#获取信号强度指示(4G)
# $1:信号强度指示数字
meig_get_rssi()
{
local rssi
case $1 in
"99") rssi="unknown" ;;
* ) rssi=$((2 * $1 - 113)) ;;
esac
echo "$rssi"
}
#获取4G签约速率
# $1:AT响应
# $2:上行或下行标志
meig_get_lte_ambr()
{
local response="$1"
local flag="$2"
local ambr
case $flag in
"ul")
#使用awk拆分字符串
ambr=$(echo "$response" | awk -F',' '{
#使用split()函数将字符串拆分为数组
n = split($0, arr, ",")
#循环遍历每个值
for (i = 1; i <= n-2; i=i+2)
{
if (arr[i] != "0") {
tmp = arr[i]
}
else {
break
}
}
print tmp
}')
;;
"dl")
#使用awk拆分字符串
ambr=$(echo "$response" | awk -F',' '{
#使用split()函数将字符串拆分为数组
n = split($0, arr, ",")
#循环遍历每个值
for (i = 2; i <= n-2; i=i+2)
{
if (arr[i] != "0") {
tmp = arr[i]
}
else {
break
}
}
print tmp
}')
;;
* )
#使用awk拆分字符串
ambr=$(echo "$response" | awk -F',' '{
#使用split()函数将字符串拆分为数组
n = split($0, arr, ",")
#循环遍历每个值
for (i = 2; i <= n-2; i=i+2)
{
if (arr[i] != "0") {
tmp = arr[i]
}
else {
break
}
}
print tmp
}')
;;
esac
echo "$ambr"
}
#网络信息
meig_network_info()
{
debug "Meig network info"
#Connect Status(连接状态)
connect_status=$(meig_get_connect_status ${at_port} ${define_connect})
if [ "$connect_status" != "connect" ]; then
return
fi
#Network Type(网络类型)
at_command="AT^SYSINFOEX"
network_type=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "\^SYSINFOEX:" | awk -F'"' '{print $4}')
[ -z "$network_type" ] && {
at_command='AT+COPS?'
local rat_num=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "+COPS:" | awk -F',' '{print $4}' | sed 's/\r//g')
network_type=$(meig_get_rat ${rat_num})
}
#设置网络类型为5G时,信号强度指示用RSRP代替
# at_command="AT+GTCSQNREN=1"
# sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command
#CSQ(信号强度)
at_command="AT+CSQ"
response=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | grep "+CSQ:" | sed 's/+CSQ: //g' | sed 's/\r//g')
#RSSI(4G信号强度指示)
# rssi_num=$(echo $response | awk -F',' '{print $1}')
# rssi=$(meig_get_rssi $rssi_num)
#BER(4G信道误码率)
# ber=$(echo $response | awk -F',' '{print $2}')
# #PER(信号强度)
# if [ -n "$csq" ]; then
# per=$(($csq * 100/31))"%"
# fi
#最大比特率,信道质量指示
at_command="AT^DSAMBR=${define_connect}"
response=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | grep "\^DSAMBR:" | awk -F': ' '{print $2}')
at_command='AT+COPS?'
local rat_num=$(sh ${SCRIPT_DIR}/modem_at.sh ${at_port} ${at_command} | grep "+COPS:" | awk -F',' '{print $4}' | sed 's/\r//g')
local network_type_tmp=$(meig_get_rat ${rat_num})
case $network_type_tmp in
"LTE")
ambr_ul_tmp=$(meig_get_lte_ambr ${response} "ul")
ambr_dl_tmp=$(meig_get_lte_ambr ${response} "dl")
;;
"NR")
ambr_ul_tmp=$(echo "$response" | awk -F',' '{print $9}')
ambr_dl_tmp=$(echo "$response" | awk -F',' '{print $10}' | sed 's/\r//g')
;;
*)
ambr_ul_tmp=$(meig_get_lte_ambr ${response} "ul")
ambr_dl_tmp=$(meig_get_lte_ambr ${response} "dl")
;;
esac
#AMBR UL(上行签约速率,单位,Mbps)
ambr_ul=$(awk "BEGIN{ printf \"%.2f\", $ambr_ul_tmp / 1024 }" | sed 's/\.*0*$//')
#AMBR DL(下行签约速率,单位,Mbps)
ambr_dl=$(awk "BEGIN{ printf \"%.2f\", $ambr_dl_tmp / 1024 }" | sed 's/\.*0*$//')
# #速率统计
# at_command='AT^DSFLOWQRY'
# response=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | grep "\^DSFLOWRPT:" | sed 's/\^DSFLOWRPT: //g' | sed 's/\r//g')
# #当前上传速率(单位,Byte/s)
# tx_rate=$(echo $response | awk -F',' '{print $1}')
# #当前下载速率(单位,Byte/s)
# rx_rate=$(echo $response | awk -F',' '{print $2}')
}
#获取频段
# $1:网络类型
# $2:频段数字
meig_get_band()
{
local band
case $1 in
"WCDMA") band="$2" ;;
"LTE") band="$2" ;;
"NR") band="$2" ;;
esac
echo "$band"
}
#获取带宽
# $1:网络类型
# $2:带宽数字
meig_get_bandwidth()
{
local network_type="$1"
local bandwidth_num="$2"
local bandwidth
case $network_type in
"LTE") bandwidth=$(( $bandwidth_num / 5 )) ;;
"NR") bandwidth="$bandwidth_num" ;;
esac
echo "$bandwidth"
}
#获取参考信号接收功率
# $1:网络类型
# $2:参考信号接收功率数字
meig_get_rsrp()
{
local rsrp
case $1 in
"LTE") rsrp=$(($2-141)) ;;
"NR") rsrp=$(($2-157)) ;;
esac
echo "$rsrp"
}
#获取参考信号接收质量
# $1:网络类型
# $2:参考信号接收质量数字
meig_get_rsrq()
{
local rsrq
case $1 in
"LTE") rsrq=$(awk "BEGIN{ printf \"%.2f\", $2 * 0.5 - 20 }" | sed 's/\.*0*$//') ;;
"NR") rsrq=$(awk -v num="$2" "BEGIN{ printf \"%.2f\", (num+1) * 0.5 - 44 }" | sed 's/\.*0*$//') ;;
esac
echo "$rsrq"
}
#获取信噪比
# $1:信噪比数字
meig_get_sinr()
{
local sinr=$(awk "BEGIN{ printf \"%.2f\", $1 / 10 }" | sed 's/\.*0*$//')
echo "$sinr"
}
#小区信息
meig_cell_info()
{
debug "Meig cell info"
at_command="AT^CELLINFO=${define_connect}"
response=$(sh ${SCRIPT_DIR}/modem_at.sh $at_port $at_command | grep "\^CELLINFO:" | sed 's/\^CELLINFO://')
local rat=$(echo "$response" | awk -F',' '{print $1}')
case $rat in
"5G")
network_mode="NR5G-SA Mode"
nr_duplex_mode=$(echo "$response" | awk -F',' '{print $2}')
nr_mcc=$(echo "$response" | awk -F',' '{print $3}')
nr_mnc=$(echo "$response" | awk -F',' '{print $4}')
nr_cell_id=$(echo "$response" | awk -F',' '{print $5}')
nr_physical_cell_id=$(echo "$response" | awk -F',' '{print $6}')
nr_tac=$(echo "$response" | awk -F',' '{print $7}')
nr_band_num=$(echo "$response" | awk -F',' '{print $8}')
nr_band=$(meig_get_band "NR" ${nr_band_num})
nr_dl_bandwidth_num=$(echo "$response" | awk -F',' '{print $9}')
nr_dl_bandwidth=$(meig_get_bandwidth "NR" ${nr_dl_bandwidth_num})
nr_scs=$(echo "$response" | awk -F',' '{print $10}')
nr_fr_type=$(echo "$response" | awk -F',' '{print $11}')
nr_dl_channel=$(echo "$response" | awk -F',' '{print $12}')
nr_ul_channel=$(echo "$response" | awk -F',' '{print $13}')
nr_rssi=$(echo "$response" | awk -F',' '{print $14}')
nr_rsrp=$(echo "$response" | awk -F',' '{print $15}')
nr_rsrq=$(echo "$response" | awk -F',' '{print $16}')
nr_sinr_num=$(echo "$response" | awk -F',' '{print $17}')
nr_sinr=$(meig_get_sinr ${nr_sinr_num})
nr_vonr=$(echo "$response" | awk -F',' '{print $18}' | sed 's/\r//g')
;;
"LTE-NR")
network_mode="EN-DC Mode"
#LTE
endc_lte_duplex_mode=$(echo "$response" | awk -F',' '{print $2}')
endc_lte_mcc=$(echo "$response" | awk -F',' '{print $3}')
endc_lte_mnc=$(echo "$response" | awk -F',' '{print $4}')
endc_lte_global_cell_id=$(echo "$response" | awk -F',' '{print $5}')
endc_lte_physical_cell_id=$(echo "$response" | awk -F',' '{print $6}')
# endc_lte_eNBID=$(echo "$response" | awk -F',' '{print $7}')
endc_lte_cell_id=$(echo "$response" | awk -F',' '{print $8}')
endc_lte_tac=$(echo "$response" | awk -F',' '{print $9}')
endc_lte_band_num=$(echo "$response" | awk -F',' '{print $10}')
endc_lte_band=$(meig_get_band "LTE" ${endc_lte_band_num})
ul_bandwidth_num=$(echo "$response" | awk -F',' '{print $11}')
endc_lte_ul_bandwidth=$(meig_get_bandwidth "LTE" ${ul_bandwidth_num})
endc_lte_dl_bandwidth="$endc_lte_ul_bandwidth"
endc_lte_dl_channel=$(echo "$response" | awk -F',' '{print $12}')
endc_lte_ul_channel=$(echo "$response" | awk -F',' '{print $13}')
endc_lte_rssi=$(echo "$response" | awk -F',' '{print $14}')
endc_lte_rsrp=$(echo "$response" | awk -F',' '{print $15}')
endc_lte_rsrq=$(echo "$response" | awk -F',' '{print $16}')
endc_lte_sinr_num=$(echo "$response" | awk -F',' '{print $17}')
endc_lte_sinr=$(meig_get_sinr ${endc_lte_sinr_num})
endc_lte_rssnr=$(echo "$response" | awk -F',' '{print $18}')
# endc_lte_ue_category=$(echo "$response" | awk -F',' '{print $19}')
# endc_lte_pathloss=$(echo "$response" | awk -F',' '{print $20}')
# endc_lte_cqi=$(echo "$response" | awk -F',' '{print $21}')
endc_lte_tx_power=$(echo "$response" | awk -F',' '{print $22}')
# endc_lte_tm=$(echo "$response" | awk -F',' '{print $23}')
# endc_lte_qci=$(echo "$response" | awk -F',' '{print $24}')
# endc_lte_volte=$(echo "$response" | awk -F',' '{print $25}')
# endc_lte_ims_sms=$(echo "$response" | awk -F',' '{print $26}')
# endc_lte_sib2_plmn_r15_info_present=$(echo "$response" | awk -F',' '{print $27}')
# endc_lte_sib2_upr_layer_ind=$(echo "$response" | awk -F',' '{print $28}')
# endc_lte_restrict_dcnr=$(echo "$response" | awk -F',' '{print $29}')
#NR5G-NSA
endc_nr_mcc=$(echo "$response" | awk -F',' '{print $3}')
endc_nr_mnc=$(echo "$response" | awk -F',' '{print $4}')
endc_nr_global_cell_id=$(echo "$response" | awk -F',' '{print $5}')
endc_nr_physical_cell_id=$(echo "$response" | awk -F',' '{print $6}')
endc_nr_cell_id=$(echo "$response" | awk -F',' '{print $8}')
endc_nr_tac=$(echo "$response" | awk -F',' '{print $9}')
endc_nr_rsrp=$(echo "$response" | awk -F',' '{print $30}')
endc_nr_rsrq=$(echo "$response" | awk -F',' '{print $31}')
endc_nr_sinr_num=$(echo "$response" | awk -F',' '{print $32}')
endc_nr_sinr=$(meig_get_sinr ${endc_nr_sinr_num})
endc_nr_band_num=$(echo "$response" | awk -F',' '{print $33}')
endc_nr_band=$(meig_get_band "NR" ${endc_nr_band_num})
endc_nr_freq=$(echo "$response" | awk -F',' '{print $34}')
nr_dl_bandwidth_num=$(echo "$response" | awk -F',' '{print $35}')
endc_nr_dl_bandwidth=$(meig_get_bandwidth "NR" ${nr_dl_bandwidth_num})
# endc_nr_pci=$(echo "$response" | awk -F',' '{print $36}')
endc_nr_scs=$(echo "$response" | awk -F',' '{print $37}' | sed 's/\r//g')
;;
"LTE"|"eMTC"|"NB-IoT")
network_mode="LTE Mode"
lte_duplex_mode=$(echo "$response" | awk -F',' '{print $2}')
lte_mcc=$(echo "$response" | awk -F',' '{print $3}')
lte_mnc=$(echo "$response" | awk -F',' '{print $4}')
lte_global_cell_id=$(echo "$response" | awk -F',' '{print $5}')
lte_physical_cell_id=$(echo "$response" | awk -F',' '{print $6}')
lte_eNBID=$(echo "$response" | awk -F',' '{print $7}')
lte_cell_id=$(echo "$response" | awk -F',' '{print $8}')
let_tac=$(echo "$response" | awk -F',' '{print $9}')
# lte_earfcn=$(echo "$response" | awk -F',' '{print $7}')
lte_band_num=$(echo "$response" | awk -F',' '{print $10}')
lte_band=$(meig_get_band "LTE" ${lte_band_num})
ul_bandwidth_num=$(echo "$response" | awk -F',' '{print $11}')
lte_ul_bandwidth=$(meig_get_bandwidth "LTE" ${ul_bandwidth_num})
lte_dl_bandwidth="$lte_ul_bandwidth"
lte_dl_channel=$(echo "$response" | awk -F',' '{print $12}')
lte_ul_channel=$(echo "$response" | awk -F',' '{print $13}')
lte_rssi=$(echo "$response" | awk -F',' '{print $14}')
lte_rsrp=$(echo "$response" | awk -F',' '{print $15}')
lte_rsrq=$(echo "$response" | awk -F',' '{print $16}')
lte_sinr_num=$(echo "$response" | awk -F',' '{print $17}')
lte_sinr=$(meig_get_sinr ${lte_sinr_num})
lte_rssnr=$(echo "$response" | awk -F',' '{print $18}')
# lte_ue_category=$(echo "$response" | awk -F',' '{print $19}')
# lte_pathloss=$(echo "$response" | awk -F',' '{print $20}')
# lte_cqi=$(echo "$response" | awk -F',' '{print $21}')
lte_tx_power=$(echo "$response" | awk -F',' '{print $22}')
# lte_tm=$(echo "$response" | awk -F',' '{print $23}')
# lte_qci=$(echo "$response" | awk -F',' '{print $24}')
# lte_volte=$(echo "$response" | awk -F',' '{print $25}')
# lte_ims_sms=$(echo "$response" | awk -F',' '{print $26}')
# lte_sib2_plmn_r15_info_present=$(echo "$response" | awk -F',' '{print $27}')
# lte_sib2_upr_layer_ind=$(echo "$response" | awk -F',' '{print $28}')
# lte_restrict_dcnr=$(echo "$response" | awk -F',' '{print $29}' | sed 's/\r//g')
;;
"WCDMA"|"UMTS")
network_mode="WCDMA Mode"
wcdma_mcc=$(echo "$response" | awk -F',' '{print $2}')
wcdma_mnc=$(echo "$response" | awk -F',' '{print $3}')
wcdma_global_cell_id=$(echo "$response" | awk -F',' '{print $4}')
wcdma_psc=$(echo "$response" | awk -F',' '{print $5}')
wcdma_NodeB=$(echo "$response" | awk -F',' '{print $6}')
wcdma_cell_id=$(echo "$response" | awk -F',' '{print $7}')
wcdma_lac=$(echo "$response" | awk -F',' '{print $8}')
wcdma_band_num=$(echo "$response" | awk -F',' '{print $9}')
wcdma_band=$(meig_get_band "WCDMA" ${wcdma_band_num})
wcdma_dl_channel=$(echo "$response" | awk -F',' '{print $10}')
wcdma_ul_channel=$(echo "$response" | awk -F',' '{print $11}')
wcdma_rssi=$(echo "$response" | awk -F',' '{print $12}')
wcdma_ecio=$(echo "$response" | awk -F',' '{print $13}')
# wcdma_sir=$(echo "$response" | awk -F',' '{print $14}')
wcdma_rscp=$(echo "$response" | awk -F',' '{print $15}' | sed 's/\r//g')
;;
"GSM")
network_mode="GSM Mode"
gsm_mcc=$(echo "$response" | awk -F',' '{print $3}')
gsm_mnc=$(echo "$response" | awk -F',' '{print $4}')
;;
esac
}
#获取美格模组信息
# $1:AT串口
# $2:平台
# $3:连接定义
get_meig_info()
{
debug "get meig info"
#设置AT串口
at_port="$1"
platform="$2"
define_connect="$3"
#基本信息
meig_base_info
#SIM卡信息
meig_sim_info
if [ "$sim_status" != "ready" ]; then
return
fi
#网络信息
meig_network_info
if [ "$connect_status" != "connect" ]; then
return
fi
#小区信息
meig_cell_info
}
+11
View File
@@ -0,0 +1,11 @@
#!/bin/sh
# Copyright (C) 2023 Siriling <siriling@qq.com>
#脚本目录
SCRIPT_DIR="/usr/share/modem"
source "${SCRIPT_DIR}/modem_debug.sh"
#发送at命令
# $1 AT串口
# $2 AT命令
at "$1" "$2"
+94
View File
@@ -0,0 +1,94 @@
#!/bin/sh
# Copyright (C) 2023 Siriling <siriling@qq.com>
#脚本目录
SCRIPT_DIR="/usr/share/modem"
source "${SCRIPT_DIR}/modem_debug.sh"
#初始化模组频段
init_modem_band()
{
#2G
DCS_1800="-"
E-GSM_900="-"
P-GSM_900="-"
GSM_450="-"
GSM_480="-"
GSM_750="-"
GSM_850="-"
R-GSM_900="-"
PCS_1900="-"
#3G
#4G
B1="-"
B2="-"
B3="-"
B4="-"
B5="-"
B6="-"
B7="-"
B8="-"
B9="-"
B10="-"
B11="-"
B12="-"
B13="-"
B14="-"
B17="-"
B18="-"
B19="-"
B20="-"
B21="-"
B25="-"
B26="-"
B28="-"
B29="-"
B30="-"
B32="-"
B34="-"
B38="-"
B39="-"
B40="-"
B41="-"
B42="-"
B66="-"
B71="-"
#5G
N1="-"
N2="-"
N3="-"
N5="-"
N7="-"
N8="-"
N12="-"
N20="-"
N25="-"
N28="-"
N38="-"
N40="-"
N41="-"
N48="-"
N66="-"
N71="-"
N77="-"
N78="-"
N79="-"
}
#获取模组数据信息
# $1:AT串口
# $2:制造商
# $3:平台
# $4:连接定义
modem_band()
{
#初始化模组频段
debug "初始化模组频段"
init_modem_band
debug "初始化模组频段完成"
}
modem_band "$1" "$2" "$3" "$4"
+78
View File
@@ -0,0 +1,78 @@
#!/bin/sh
# Copyright (C) 2023 Siriling <siriling@qq.com>
#脚本目录
SCRIPT_DIR="/usr/share/modem"
source "${SCRIPT_DIR}/quectel.sh"
source "${SCRIPT_DIR}/fibocom.sh"
source "${SCRIPT_DIR}/meig.sh"
source "${SCRIPT_DIR}/huawei.sh"
# source "${SCRIPT_DIR}/simcom.sh"
#调试开关
# 0关闭
# 1打开
# 2输出到文件
switch=0
out_file="/tmp/modem.log" #输出文件
#日志信息
debug()
{
time=$(date "+%Y-%m-%d %H:%M:%S") #获取系统时间
if [ $switch = 1 ]; then
echo $time $1 #打印输出
elif [ $switch = 2 ]; then
echo $time $1 >> $outfile #输出到文件
fi
}
#发送at命令
# $1 AT串口
# $2 AT命令
at()
{
local at_port="$1"
local new_str="${2/[$]/$}"
local at_command="${new_str/\"/\"}"
#echo
# echo -e "${at_command}"" > "${at_port}" 2>&1
#sms_tool
sms_tool -d "${at_port}" at "${at_command}" 2>&1
}
#测试时打开
# debug $1
# at $1 $2
#获取快捷命令
# $1:快捷选项
# $2:制造商
get_quick_commands()
{
local quick_option="$1"
local manufacturer="$2"
local quick_commands
case "$quick_option" in
"auto") quick_commands=$(cat ${SCRIPT_DIR}/${manufacturer}_at_commands.json) ;;
"custom") quick_commands=$(cat /etc/modem/custom_at_commands.json) ;;
*) quick_commands=$(cat ${SCRIPT_DIR}/${manufacturer}_at_commands.json) ;;
esac
echo "$quick_commands"
}
#拨号日志
# $1:AT命令
# $2:日志路径
dial_log()
{
local at_command="$1"
local path="$2"
#打印日志
local update_time=$(date +"%Y-%m-%d %H:%M:%S")
echo "[${update_time}] Send AT command ${at_command} to modem" >> "${path}"
}
+412
View File
@@ -0,0 +1,412 @@
#!/bin/sh
# Copyright (C) 2023 Siriling <siriling@qq.com>
#脚本目录
SCRIPT_DIR="/usr/share/modem"
source "${SCRIPT_DIR}/modem_debug.sh"
#初值化数据结构
init_modem_info()
{
#基本信息
name='unknown' #名称
manufacturer='unknown' #制造商
revision='-' #固件版本
at_port='-' #AT串口
mode='unknown' #拨号模式
temperature="NaN $(printf "\xc2\xb0")C" #温度
update_time='-' #更新时间
#SIM卡信息
sim_status="unknown" #SIM卡状态
sim_slot="-" #SIM卡卡槽
isp="-" #运营商(互联网服务提供商)
sim_number='-' #SIM卡号码(手机号)
imei='-' #IMEI
imsi='-' #IMSI
iccid='-' #ICCID
#网络信息
connect_status="disconnect" #SIM卡状态
network_type="-" #蜂窝网络类型
cqi_ul="-" #上行信道质量指示
cqi_dl="-" #下行信道质量指示
ambr_ul="-" #上行签约速率
ambr_dl="-" #下行签约速率
tx_rate="-" #上传速率
rx_rate="-" #下载速率
#小区信息
network_mode="-" #网络模式
#NR5G-SA模式
nr_mcc=''
nr_mnc=''
nr_duplex_mode=''
nr_cell_id=''
nr_physical_cell_id=''
nr_tac=''
nr_arfcn=''
nr_band=''
nr_dl_bandwidth=''
nr_rsrp=''
nr_rsrq=''
nr_sinr=''
nr_rxlev=''
nr_scs=''
nr_srxlev=''
#EN-DC模式(LTE)
endc_lte_mcc=''
endc_lte_mnc=''
endc_lte_duplex_mode=''
endc_lte_cell_id=''
endc_lte_physical_cell_id=''
endc_lte_earfcn=''
endc_lte_freq_band_ind=''
endc_lte_ul_bandwidth=''
endc_lte_dl_bandwidth=''
endc_lte_tac=''
endc_lte_rsrp=''
endc_lte_rsrq=''
endc_lte_rssi=''
endc_lte_sinr=''
endc_lte_rxlev=''
endc_lte_cql=''
endc_lte_tx_power=''
endc_lte_srxlev=''
#EN-DC模式(NR5G-NSA)
endc_nr_mcc=''
endc_nr_mnc=''
endc_nr_physical_cell_id=''
endc_nr_arfcn=''
endc_nr_band=''
endc_nr_dl_bandwidth=''
endc_nr_rsrp=''
endc_nr_rsrq=''
endc_nr_sinr=''
endc_nr_scs=''
#LTE模式
lte_mcc=''
lte_mnc=''
lte_duplex_mode=''
lte_cell_id=''
lte_physical_cell_id=''
lte_earfcn=''
lte_freq_band_ind=''
lte_band=''
lte_ul_bandwidth=''
lte_dl_bandwidth=''
lte_tac=''
lte_rsrp=''
lte_rsrq=''
lte_rssi=''
lte_sinr=''
lte_rxlev=''
lte_cql=''
lte_tx_power=''
lte_srxlev=''
#WCDMA模式
wcdma_mcc=''
wcdma_mnc=''
wcdma_lac=''
wcdma_cell_id=''
wcdma_uarfcn=''
wcdma_psc=''
wcdma_rac=''
wcdma_band=''
wcdma_rssi=''
wcdma_rscp=''
wcdma_ecio=''
wcdma_phych=''
wcdma_sf=''
wcdma_slot=''
wcdma_speech_code=''
wcdma_com_mod=''
}
#设置基本信息
set_base_info()
{
base_info="\"base_info\":{
\"manufacturer\":\"$manufacturer\",
\"revision\":\"$revision\",
\"at_port\":\"$at_port\",
\"mode\":\"$mode\",
\"temperature\":\"$temperature\",
\"update_time\":\"$update_time\"
},"
}
#设置SIM卡信息
set_sim_info()
{
if [ "$sim_status" = "ready" ]; then
sim_info="\"sim_info\":[
{\"SIM Status\":\"$sim_status\", \"full_name\":\"SIM Status\"},
{\"ISP\":\"$isp\", \"full_name\":\"Internet Service Provider\"},
{\"SIM Slot\":\"$sim_slot\", \"full_name\":\"SIM Slot\"},
{\"SIM Number\":\"$sim_number\", \"full_name\":\"SIM Number\"},
{\"IMEI\":\"$imei\", \"full_name\":\"International Mobile Equipment Identity\"},
{\"IMSI\":\"$imsi\", \"full_name\":\"International Mobile Subscriber Identity\"},
{\"ICCID\":\"$iccid\", \"full_name\":\"Integrate Circuit Card Identity\"}
],"
elif [ "$sim_status" = "miss" ]; then
sim_info="\"sim_info\":[
{\"SIM Status\":\"$sim_status\", \"full_name\":\"SIM Status\"},
{\"IMEI\":\"$imei\", \"full_name\":\"International Mobile Equipment Identity\"}
],"
elif [ "$sim_status" = "unknown" ]; then
sim_info="\"sim_info\":[
{\"SIM Status\":\"$sim_status\", \"full_name\":\"SIM Status\"}
],"
else
sim_info="\"sim_info\":[
{\"SIM Status\":\"$sim_status\", \"full_name\":\"SIM Status\"},
{\"SIM Slot\":\"$sim_slot\", \"full_name\":\"SIM Slot\"},
{\"IMEI\":\"$imei\", \"full_name\":\"International Mobile Equipment Identity\"},
{\"IMSI\":\"$imsi\", \"full_name\":\"International Mobile Subscriber Identity\"},
{\"ICCID\":\"$iccid\", \"full_name\":\"Integrate Circuit Card Identity\"}
],"
fi
}
#设置网络信息
set_network_info()
{
network_info="\"network_info\":[
{\"Network Type\":\"$network_type\", \"full_name\":\"Network Type\"},
{\"CQI UL\":\"$cqi_ul\", \"full_name\":\"Channel Quality Indicator for Uplink\"},
{\"CQI DL\":\"$cqi_dl\", \"full_name\":\"Channel Quality Indicator for Downlink\"},
{\"AMBR UL\":\"$ambr_ul\", \"full_name\":\"Access Maximum Bit Rate for Uplink\"},
{\"AMBR DL\":\"$ambr_dl\", \"full_name\":\"Access Maximum Bit Rate for Downlink\"},
{\"Tx Rate\":\"$tx_rate\", \"full_name\":\"Transmit Rate\"},
{\"Rx Rate\":\"$rx_rate\", \"full_name\":\"Receive Rate\"}
],"
}
#设置信号信息
set_cell_info()
{
if [ "$network_mode" = "NR5G-SA Mode" ]; then
cell_info="\"cell_info\":{
\"NR5G-SA Mode\":[
{\"MCC\":\"$nr_mcc\", \"full_name\":\"Mobile Country Code\"},
{\"MNC\":\"$nr_mnc\", \"full_name\":\"Mobile Network Code\"},
{\"Duplex Mode\":\"$nr_duplex_mode\", \"full_name\":\"Duplex Mode\"},
{\"Cell ID\":\"$nr_cell_id\", \"full_name\":\"Cell ID\"},
{\"Physical Cell ID\":\"$nr_physical_cell_id\", \"full_name\":\"Physical Cell ID\"},
{\"TAC\":\"$nr_tac\", \"full_name\":\"Tracking area code of cell servedby neighbor Enb\"},
{\"ARFCN\":\"$nr_arfcn\", \"full_name\":\"Absolute Radio-Frequency Channel Number\"},
{\"Band\":\"$nr_band\", \"full_name\":\"Band\"},
{\"DL Bandwidth\":\"$nr_dl_bandwidth\", \"full_name\":\"DL Bandwidth\"},
{\"RSRP\":\"$nr_rsrp\", \"full_name\":\"Reference Signal Received Power\"},
{\"RSRQ\":\"$nr_rsrq\", \"full_name\":\"Reference Signal Received Quality\"},
{\"SINR\":\"$nr_sinr\", \"full_name\":\"Signal to Interference plus Noise Ratio Bandwidth\"},
{\"RxLev\":\"$nr_rxlev\", \"full_name\":\"Received Signal Level\"},
{\"SCS\":\"$nr_scs\", \"full_name\":\"SCS\"},
{\"Srxlev\":\"$nr_srxlev\", \"full_name\":\"Serving Cell Receive Level\"}
]
}"
elif [ "$network_mode" = "EN-DC Mode" ]; then
cell_info="\"cell_info\":{
\"EN-DC Mode\":[
{\"LTE\":[
{\"MCC\":\"$endc_lte_mcc\", \"full_name\":\"Mobile Country Code\"},
{\"MNC\":\"$endc_lte_mnc\", \"full_name\":\"Mobile Network Code\"},
{\"Duplex Mode\":\"$endc_lte_duplex_mode\", \"full_name\":\"Duplex Mode\"},
{\"Cell ID\":\"$endc_lte_cell_id\", \"full_name\":\"Cell ID\"},
{\"Physical Cell ID\":\"$endc_lte_physical_cell_id\", \"full_name\":\"Physical Cell ID\"},
{\"EARFCN\":\"$endc_lte_earfcn\", \"full_name\":\"E-UTRA Absolute Radio Frequency Channel Number\"},
{\"Freq band indicator\":\"$endc_lte_freq_band_ind\", \"full_name\":\"Freq band indicator\"},
{\"Band\":\"$endc_lte_band\", \"full_name\":\"Band\"},
{\"UL Bandwidth\":\"$endc_lte_ul_bandwidth\", \"full_name\":\"UL Bandwidth\"},
{\"DL Bandwidth\":\"$endc_lte_dl_bandwidth\", \"full_name\":\"DL Bandwidth\"},
{\"TAC\":\"$endc_lte_tac\", \"full_name\":\"Tracking area code of cell servedby neighbor Enb\"},
{\"RSRP\":\"$endc_lte_rsrp\", \"full_name\":\"Reference Signal Received Power\"},
{\"RSRQ\":\"$endc_lte_rsrq\", \"full_name\":\"Reference Signal Received Quality\"},
{\"RSSI\":\"$endc_lte_rssi\", \"full_name\":\"Received Signal Strength Indicator\"},
{\"SINR\":\"$endc_lte_sinr\", \"full_name\":\"Signal to Interference plus Noise Ratio Bandwidth\"},
{\"RxLev\":\"$endc_lte_rxlev\", \"full_name\":\"Received Signal Level\"},
{\"RSSNR\":\"$endc_lte_rssnr\", \"full_name\":\"Radio Signal Strength Noise Ratio\"},
{\"CQI\":\"$endc_lte_cql\", \"full_name\":\"Channel Quality Indicator\"},
{\"TX Power\":\"$endc_lte_tx_power\", \"full_name\":\"TX Power\"},
{\"Srxlev\":\"$endc_lte_srxlev\", \"full_name\":\"Serving Cell Receive Level\"}
]
},
{\"NR5G-NSA\":[
{\"MCC\":\"$endc_nr_mcc\", \"full_name\":\"Mobile Country Code\"},
{\"MNC\":\"$endc_nr_mnc\", \"full_name\":\"Mobile Network Code\"},
{\"Physical Cell ID\":\"$endc_nr_physical_cell_id\", \"full_name\":\"Physical Cell ID\"},
{\"ARFCN\":\"$endc_nr_arfcn\", \"full_name\":\"Absolute Radio-Frequency Channel Number\"},
{\"Band\":\"$endc_nr_band\", \"full_name\":\"Band\"},
{\"DL Bandwidth\":\"$endc_nr_dl_bandwidth\", \"full_name\":\"DL Bandwidth\"},
{\"RSRP\":\"$endc_nr_rsrp\", \"full_name\":\"Reference Signal Received Power\"},
{\"RSRQ\":\"$endc_nr_rsrq\", \"full_name\":\"Reference Signal Received Quality\"},
{\"SINR\":\"$endc_nr_sinr\", \"full_name\":\"Signal to Interference plus Noise Ratio Bandwidth\"},
{\"SCS\":\"$endc_nr_scs\", \"full_name\":\"SCS\"}
]
}
]
}"
elif [ "$network_mode" = "LTE Mode" ]; then
cell_info="\"cell_info\":{
\"LTE Mode\":[
{\"MCC\":\"$lte_mcc\", \"full_name\":\"Mobile Country Code\"},
{\"MNC\":\"$lte_mnc\", \"full_name\":\"Mobile Network Code\"},
{\"Duplex Mode\":\"$lte_duplex_mode\", \"full_name\":\"Duplex Mode\"},
{\"Cell ID\":\"$lte_cell_id\", \"full_name\":\"Cell ID\"},
{\"Physical Cell ID\":\"$lte_physical_cell_id\", \"full_name\":\"Physical Cell ID\"},
{\"EARFCN\":\"$lte_earfcn\", \"full_name\":\"E-UTRA Absolute Radio Frequency Channel Number\"},
{\"Freq band indicator\":\"$lte_freq_band_ind\", \"full_name\":\"Freq band indicator\"},
{\"Band\":\"$lte_band\", \"full_name\":\"Band\"},
{\"UL Bandwidth\":\"$lte_ul_bandwidth\", \"full_name\":\"UL Bandwidth\"},
{\"DL Bandwidth\":\"$lte_dl_bandwidth\", \"full_name\":\"DL Bandwidth\"},
{\"TAC\":\"$lte_tac\", \"full_name\":\"Tracking area code of cell servedby neighbor Enb\"},
{\"RSRP\":\"$lte_rsrp\", \"full_name\":\"Reference Signal Received Power\"},
{\"RSRQ\":\"$lte_rsrq\", \"full_name\":\"Reference Signal Received Quality\"},
{\"RSSI\":\"$lte_rssi\", \"full_name\":\"Received Signal Strength Indicator\"},
{\"SINR\":\"$lte_sinr\", \"full_name\":\"Signal to Interference plus Noise Ratio Bandwidth\"},
{\"RxLev\":\"$lte_rxlev\", \"full_name\":\"RxLev\"},
{\"RSSNR\":\"$lte_rssnr\", \"full_name\":\"Radio Signal Strength Noise Ratio\"},
{\"CQI\":\"$lte_cql\", \"full_name\":\"Channel Quality Indicator\"},
{\"TX Power\":\"$lte_tx_power\", \"full_name\":\"TX Power\"},
{\"Srxlev\":\"$lte_srxlev\", \"full_name\":\"Serving Cell Receive Level\"}
]
}"
elif [ "$network_mode" = "WCDMA Mode" ]; then
cell_info="\"cell_info\":{
\"WCDMA Mode\":[
{\"MCC\":\"$wcdma_mcc\", \"full_name\":\"Mobile Country Code\"},
{\"MNC\":\"$wcdma_mnc\", \"full_name\":\"Mobile Network Code\"},
{\"LAC\":\"$wcdma_lac\", \"full_name\":\"Location Area Code\"},
{\"Cell ID\":\"$wcdma_cell_id\", \"full_name\":\"Cell ID\"},
{\"UARFCN\":\"$wcdma_uarfcn\", \"full_name\":\"UTRA Absolute Radio Frequency Channel Number\"},
{\"PSC\":\"$wcdma_psc\", \"full_name\":\"Primary Scrambling Code\"},
{\"RAC\":\"$wcdma_rac\", \"full_name\":\"Routing Area Code\"},
{\"Band\":\"$wcdma_band\", \"full_name\":\"Band\"},
{\"RSSI\":\"$wcdma_rssi\", \"full_name\":\"Received Signal Strength Indicator\"},
{\"RSCP\":\"$wcdma_rscp\", \"full_name\":\"Received Signal Code Power\"},
{\"Ec/Io\":\"$wcdma_ecio\", \"full_name\":\"Ec/Io\"},
{\"Ec/No\":\"$wcdma_ecno\", \"full_name\":\"Ec/No\"},
{\"Physical Channel\":\"$wcdma_phych\", \"full_name\":\"Physical Channel\"},
{\"Spreading Factor\":\"$wcdma_sf\", \"full_name\":\"Spreading Factor\"},
{\"Slot\":\"$wcdma_slot\", \"full_name\":\"Slot\"},
{\"Speech Code\":\"$wcdma_speech_code\", \"full_name\":\"Speech Code\"},
{\"Compression Mode\":\"$wcdma_com_mod\", \"full_name\":\"Compression Mode\"},
{\"RxLev\":\"$wcdma_rxlev\", \"full_name\":\"RxLev\"}
]
}"
fi
}
#以Json格式保存模组信息
info_to_json()
{
base_info="\"base_info\":{},"
sim_info="\"sim_info\":{},"
network_info="\"network_info\":{},"
cell_info="\"cell_info\":{}"
#设置基本信息
set_base_info
#判断是否适配
if [ "$manufacturer" != "unknown" ]; then
#设置SIM卡信息
set_sim_info
fi
#判断插卡和连接状态
if [ "$sim_status" = "ready" ] && [ "$connect_status" = "connect" ]; then
#设置网络信息
set_network_info
#设置小区信息
set_cell_info
fi
#拼接所有信息(不要漏掉最后一个})
modem_info="{$base_info$modem_info$sim_info$network_info$cell_info}"
}
# echo $ECIO #参考信号接收质量 RSRQ ecio
# echo $ECIO1 #参考信号接收质量 RSRQ ecio1
# echo $RSCP #参考信号接收功率 RSRP rscp0
# echo $RSCP1 #参考信号接收功率 RSRP rscp1
# echo $SINR #信噪比 SINR rv["sinr"]
# #基站信息
# 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 $MODTYPE
# echo $QTEMP
#获取模组信息
get_modem_info()
{
update_time=$(date +"%Y-%m-%d %H:%M:%S")
debug "检查模组的AT串口"
#获取模块AT串口
if [ -z "$at_port" ]; then
debug "模组没有AT串口"
return
fi
#检查模块状态(是否处于重启,重置,串口异常状态)
local at_command="ATI"
local response=$(at ${at_port} ${at_command})
if [[ "$response" = *"failed"* ]] || [[ "$response" = *"$at_port"* ]]; then
debug "模组AT串口未就绪"
return
fi
debug "根据模组的制造商获取信息"
#更多信息获取
case $manufacturer in
"quectel") get_quectel_info "${at_port}" "${platform}" "${define_connect}" ;;
"fibocom") get_fibocom_info "${at_port}" "${platform}" "${define_connect}" ;;
"meig") get_meig_info "${at_port}" "${platform}" "${define_connect}" ;;
"simcom") get_simcom_info "${at_port}" "${platform}" "${define_connect}" ;;
"huawei") get_huawei_info "${at_port}" "${platform}" "${define_connect}" ;;
*) debug "未适配该模组" ;;
esac
#获取更新时间
update_time=$(date +"%Y-%m-%d %H:%M:%S")
}
#获取模组数据信息
# $1:AT串口
# $2:制造商
# $3:平台
# $4:连接定义
modem_info()
{
#初值化模组信息
debug "初值化模组信息"
init_modem_info
debug "初值化模组信息完成"
#获取模组信息
at_port="$1"
manufacturer="$2"
platform="$3"
define_connect="$4"
debug "获取模组信息"
get_modem_info
#整合模块信息
info_to_json
echo $modem_info
}
modem_info "$1" "$2" "$3" "$4"
+23
View File
@@ -0,0 +1,23 @@
#!/bin/sh
# Copyright (C) 2023 Siriling <siriling@qq.com>
#脚本目录
SCRIPT_DIR="/usr/share/modem"
source "${SCRIPT_DIR}/modem_util.sh"
#模组配置初始化
modem_init()
{
m_log "info" "Clearing all modem configurations"
#清空模组配置
local modem_count=$(uci -q get modem.@global[0].modem_number)
for i in $(seq 0 $((modem_count-1))); do
#删除该模组的配置
uci -q del modem.modem${i}
done
uci set modem.@global[0].modem_number=0
uci commit modem
m_log "info" "All module configurations cleared"
}
modem_init
+326
View File
@@ -0,0 +1,326 @@
#!/bin/sh
# Copyright (C) 2023 Siriling <siriling@qq.com>
#脚本目录
SCRIPT_DIR="/usr/share/modem"
#运行目录
MODEM_RUNDIR="/var/run/modem"
#导入组件工具
source "${SCRIPT_DIR}/modem_debug.sh"
#重设网络接口
# $1:AT串口
# $4:连接定义
# $5:模组序号
reset_network_interface()
{
local at_port="$1"
local define_connect="$2"
local modem_no="$3"
local interface_name="wwan_5g_${modem_no}"
local interface_name_ipv6="wwan6_5g_${modem_no}"
#获取IPv4地址
local at_command="AT+CGPADDR=${define_connect}"
local ipv4=$(at ${at_port} ${at_command} | grep "+CGPADDR: " | sed -n '1p' | awk -F',' '{print $2}' | sed 's/"//g')
#输出日志
# echo "[$(date +"%Y-%m-%d %H:%M:%S")] Get Modem new IPv4 address : ${ipv4}" >> "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
#获取DNS地址
local dns=$(fibocom_get_dns ${at_port} ${define_connect})
local ipv4_dns1=$(echo "${dns}" | jq -r '.dns.ipv4_dns1')
local ipv4_dns2=$(echo "${dns}" | jq -r '.dns.ipv4_dns2')
#输出日志
echo "[$(date +"%Y-%m-%d %H:%M:%S")] Get Modem IPv4 DNS1: ${ipv4_dns1}" >> "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
echo "[$(date +"%Y-%m-%d %H:%M:%S")] Get Modem IPv4 DNS2: ${ipv4_dns2}" >> "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
#比较的网络接口中的IPv4地址
local ipv4_config=$(uci -q get network.${interface_name}.ipaddr)
if [ "$ipv4_config" == "$ipv4" ]; then
#输出日志
echo "[$(date +"%Y-%m-%d %H:%M:%S")] IPv4 address is the same as in the network interface, skip" >> "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
else
#输出日志
echo "[$(date +"%Y-%m-%d %H:%M:%S")] Reset network interface ${interface_name}" >> "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
#设置静态地址
uci set network.wan.metric='2'
uci set network.wan6.metric='2'
uci set network.${interface_name}.proto='static'
uci set network.${interface_name}.ipaddr="${ipv4}"
uci set network.${interface_name}.netmask='255.255.255.0'
uci set network.${interface_name}.gateway="${ipv4%.*}.1"
uci set network.${interface_name}.peerdns='0'
uci set network.${interface_name}.metric='1'
uci set network.${interface_name_ipv6}.metric='1'
uci -q del network.${interface_name}.dns
uci add_list network.${interface_name}.dns="${ipv4_dns1}"
uci add_list network.${interface_name}.dns="${ipv4_dns2}"
uci commit network
service network reload
#输出日志
echo "[$(date +"%Y-%m-%d %H:%M:%S")] Reset network interface successful" >> "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
fi
}
#GobiNet拨号
# $1:AT串口
# $2:制造商
# $3:连接定义
gobinet_dial()
{
local at_port="$1"
local manufacturer="$2"
local define_connect="$3"
#激活
local at_command="AT+CGACT=1,${define_connect}"
#打印日志
dial_log "${at_command}" "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
at "${at_port}" "${at_command}"
#拨号
local at_command
if [ "$manufacturer" = "quectel" ]; then
#移远不走该分支
at_command='ATI'
elif [ "$manufacturer" = "fibocom" ]; then
at_command='AT$QCRMCALL=1,3'
elif [ "$manufacturer" = "meig" ]; then
at_command="AT$QCRMCALL=1,1,${define_connect},2,1"
else
at_command='ATI'
fi
#打印日志
dial_log "${at_command}" "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
at "${at_port}" "${at_command}"
}
#ECM拨号
# $1:AT串口
# $2:制造商
# $3:连接定义
# $4:模组序号
ecm_dial()
{
local at_port="$1"
local manufacturer="$2"
local define_connect="$3"
local modem_no="$4"
name=$(uci -q get modem.modem${modem_no}.name)
#激活
# local at_command="AT+CGACT=1,${define_connect}"
# #打印日志
# dial_log "${at_command}" "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
# at "${at_port}" "${at_command}"
#拨号
local at_command
if [ "$manufacturer" = "quectel" ]; then
at_command="AT+QNETDEVCTL=${define_connect},1,1"
elif [ "$manufacturer" = "fibocom" ]; then
at_command="AT+GTRNDIS=1,${define_connect}"
elif [ "$manufacturer" = "meig" ]; then
at_command="AT^NDISDUP=${define_connect},1"
elif [ "$manufacturer" = "huawei" ]; then
at_command="AT^NDISDUP=${define_connect},1"
elif [ "$manufacturer" = "tdtech" ]; then
at_command="AT^NDISDUP=${define_connect},1"
else
at_command='ATI'
fi
#打印日志
dial_log "${at_command}" "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
at "${at_port}" "${at_command}"
sleep 2s
}
#RNDIS拨号
# $1:AT串口
# $2:制造商
# $3:平台
# $4:连接定义
# $5:模组序号
rndis_dial()
{
local at_port="$1"
local manufacturer="$2"
local platform="$3"
local define_connect="$4"
local modem_no="$5"
#手动拨号(广和通FM350-GL)
if [ "$manufacturer" = "fibocom" ] && [ "$platform" = "mediatek" ]; then
local at_command="AT+CGACT=1,${define_connect}"
#打印日志
dial_log "${at_command}" "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
#激活并拨号
at "${at_port}" "${at_command}"
sleep 3s
else
#拨号
ecm_dial "${at_port}" "${manufacturer}" "${define_connect}"
fi
}
#Modem Manager拨号
# $1:接口名称
# $2:连接定义
modemmanager_dial()
{
local interface_name="$1"
local define_connect="$2"
# #激活
# local at_command="AT+CGACT=1,${define_connect}"
# #打印日志
# dial_log "${at_command}" "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
# at "${at_port}" "${at_command}"
#启动网络接口
ifup "${interface_name}";
}
#检查模组网络连接
# $1:配置ID
# $2:模组序号
# $3:拨号模式
modem_network_task()
{
local config_id="$1"
local modem_no="$2"
local mode="$3"
#获取AT串口,制造商,平台,连接定义,接口名称
local at_port=$(uci -q get modem.modem${modem_no}.at_port)
local manufacturer=$(uci -q get modem.modem${modem_no}.manufacturer)
local platform=$(uci -q get modem.modem${modem_no}.platform)
local define_connect=$(uci -q get modem.modem${modem_no}.define_connect)
local network=$(uci -q get modem.modem${modem_no}.network)
local interface_name="wwan_5g_${modem_no}"
local interface_name_ipv6="wwan6_5g_${modem_no}"
#AT串口未获取到重新获取(解决模组还在识别中,就已经开始拨号的问题)
while [ -z "$manufacturer" ] || [ "$manufacturer" = "unknown" ]; do
at_port=$(uci -q get modem.modem${modem_no}.at_port)
manufacturer=$(uci -q get modem.modem${modem_no}.manufacturer)
platform=$(uci -q get modem.modem${modem_no}.platform)
define_connect=$(uci -q get modem.modem${modem_no}.define_connect)
sleep 1s
done
#重载配置(解决AT命令发不出去的问题)
# service modem reload
#IPv4地址缓存
local ipv4_cache
#输出日志
echo "[$(date +"%Y-%m-%d %H:%M:%S")] Start network task" >> "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
while true; do
#全局
local enable_dial=$(uci -q get modem.@global[0].enable_dial)
if [ "$enable_dial" != "1" ]; then
#输出日志
echo "[$(date +"%Y-%m-%d %H:%M:%S")] The dialing configuration has been disabled, this network task quit" >> "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
break
fi
#单个模组
enable=$(uci -q get modem.${config_id}.enable)
if [ "$enable" != "1" ]; then
#输出日志
echo "[$(date +"%Y-%m-%d %H:%M:%S")] The modem has disabled dialing, this network task quit" >> "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
break
fi
#网络连接检查
local at_command="AT+CGPADDR=${define_connect}"
local ipv4=$(at ${at_port} ${at_command} | grep "+CGPADDR: " | sed -n '1p' | awk -F',' '{print $2}' | sed 's/"//g')
if [ -z "$ipv4" ]; then
[ "$mode" = "modemmanager" ] && {
#拨号工具为modemmanager时,不需要重新设置连接定义
continue
}
#输出日志
echo "[$(date +"%Y-%m-%d %H:%M:%S")] Unable to get IPv4 address" >> "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
echo "[$(date +"%Y-%m-%d %H:%M:%S")] Redefine connect to ${define_connect}" >> "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
service modem reload
#输出日志
echo "[$(date +"%Y-%m-%d %H:%M:%S")] Modem dial" >> "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
#拨号(针对获取IPv4返回为空的模组)
case "$mode" in
"gobinet") gobinet_dial "${at_port}" "${manufacturer}" "${define_connect}" ;;
"ecm") ecm_dial "${at_port}" "${manufacturer}" "${define_connect}" "${modem_no}" ;;
"rndis") rndis_dial "${at_port}" "${manufacturer}" "${platform}" "${define_connect}" "${modem_no}" ;;
"modemmanager") modemmanager_dial "${interface_name}" "${define_connect}" ;;
*) ecm_dial "${at_port}" "${manufacturer}" "${define_connect}" ;;
esac
elif [[ "$ipv4" = *"0.0.0.0"* ]]; then
#输出日志
echo "[$(date +"%Y-%m-%d %H:%M:%S")] Modem${modem_no} current IPv4 address : ${ipv4}" >> "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
#输出日志
echo "[$(date +"%Y-%m-%d %H:%M:%S")] Modem dial" >> "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
#拨号
case "$mode" in
"gobinet") gobinet_dial "${at_port}" "${manufacturer}" "${define_connect}" ;;
"ecm") ecm_dial "${at_port}" "${manufacturer}" "${define_connect}" ;;
"rndis") rndis_dial "${at_port}" "${manufacturer}" "${platform}" "${define_connect}" "${modem_no}" ;;
"modemmanager") modemmanager_dial "${interface_name}" "${define_connect}" ;;
*) ecm_dial "${at_port}" "${manufacturer}" "${define_connect}" ;;
esac
elif [ "$ipv4" != "$ipv4_cache" ]; then
#第一次缓存IP为空时不输出日志
[ -n "$ipv4_cache" ] && {
#输出日志
echo "[$(date +"%Y-%m-%d %H:%M:%S")] Modem${modem_no} IPv4 address has changed" >> "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
}
#输出日志
echo "[$(date +"%Y-%m-%d %H:%M:%S")] Modem${modem_no} current IPv4 address : ${ipv4}" >> "${MODEM_RUNDIR}/modem${modem_no}_dial.cache"
#缓存当前IP
ipv4_cache="${ipv4}"
#重新设置网络接口(广和通FM350-GL)
if [ "$manufacturer" = "fibocom" ] && [ "$platform" = "mediatek" ]; then
reset_network_interface "${at_port}" "${define_connect}" "${modem_no}"
sleep 3s
fi
[ "$mode" != "modemmanager" ] && {
#重新启动网络接口
ifup "${interface_name}"
ifup "${interface_name_ipv6}"
}
fi
rdisc6 "${network}" &
ndisc6 fe80::1 "${network}" &
sleep 5s
done
}
modem_network_task "$1" "$2" "$3"
+144
View File
@@ -0,0 +1,144 @@
#!/bin/sh
# Copyright (C) 2023 Siriling <siriling@qq.com>
#脚本目录
SCRIPT_DIR="/usr/share/modem"
source "${SCRIPT_DIR}/modem_util.sh"
#################################################################################旧扫描方法#################################################################################
#获取设备物理地址
# $1:网络设备或串口
get_device_physical_path()
{
local device_name="$(basename "$1")"
local device_path="$(find /sys/class/ -name $device_name)"
local device_physical_path="$(readlink -f $device_path/device/)"
echo "$device_physical_path"
}
#设置模组配置
# $1:网络设备
# $2:网络设备系统路径
set_modem_config()
{
local network="$(basename $sys_network)"
local network_path="$(readlink -f $sys_network)"
#只处理最上级的网络设备
local count=$(echo "${network_path}" | grep -o "/net" | wc -l)
[ "$count" -ge "2" ] && return
#判断路径是否带有usb(排除其他eth网络设备)
if [[ "$network" = *"eth"* ]] && [[ "$network_path" != *"usb"* ]]; then
return
fi
#获取物理路径
local device_physical_path=$(m_get_device_physical_path ${network_path})
#设置物理设备
m_set_physical_device "scan" "${device_physical_path}"
#启用拨号
m_enable_dial "${network}"
}
#设置系统网络设备
# $1:系统网络设备列表
set_sys_network_config()
{
local sys_networks="$1"
for sys_network in $sys_networks; do
local network="$(basename $sys_network)"
set_modem_config "${network}" "${sys_network}"
done
}
#通过网络扫描模组
modem_scan_by_network()
{
#模组配置初始化
sh "${SCRIPT_DIR}/modem_init.sh"
#发起模组添加事件
#USB
local sys_network
sys_network="$(find /sys/class/net -name usb*)" #ECM RNDIS NCM
set_sys_network_config "$sys_network"
sys_network="$(find /sys/class/net -name wwan*)" #QMI MBIM
set_sys_network_config "$sys_network"
sys_network="$(find /sys/class/net -name eth*)" #RNDIS
set_sys_network_config "$sys_network"
#PCI
sys_network="$(find /sys/class/net -name mhi_hwip*)" #(通用mhi驱动)
set_sys_network_config "$sys_network"
sys_network="$(find /sys/class/net -name rmnet_mhi*)" #(制造商mhi驱动)
set_sys_network_config "$sys_network"
echo "modem scan complete"
}
#################################################################################新扫描方法#################################################################################
#扫描USB设备
scan_usb_device()
{
echo "scan USB device"
local devices_path="/sys/bus/usb/devices"
for device in ${devices_path}/*; do
# 跳过非目录文件
[[ ! -d "$device" ]] && continue
local device_name=$(basename "$device")
# 跳过USB总线控制器 (以usb开头)
[[ "$device_name" == usb* ]] && continue
# 设置物理设备
m_set_physical_device "scan" "${device}"
# 启用拨号
# m_enable_dial "${network}"
done
}
#扫描PCI设备
scan_pci_device()
{
echo "scan PCI device"
local devices_path="/sys/bus/pci/devices"
for device in ${devices_path}/*; do
# 跳过非目录文件
[[ ! -d "$device" ]] && continue
# 设置物理设备
m_set_physical_device "scan" "${device}"
# 启用拨号
# m_enable_dial "${network}"
done
}
#扫描模组
modem_scan()
{
# 模组配置初始化
sh "${SCRIPT_DIR}/modem_init.sh"
#USB
local usb_scan=$(uci -q get modem.@global[0].usb_scan)
[ "${usb_scan}" = "1" ] && scan_usb_device
#PCI
local pci_scan=$(uci -q get modem.@global[0].pci_scan)
[ "${pci_scan}" = "1" ] && scan_pci_device
echo "modem scan complete"
}
#测试时打开
# modem_scan
# modem_scan_by_network
@@ -0,0 +1,283 @@
{
"modem_support":{
"usb":{
"rg200u-cn":{
"manufacturer_id":"2c7c",
"manufacturer":"quectel",
"platform":"unisoc",
"data_interface":"usb",
"define_connect":"1",
"modes":["ecm","mbim","rndis","ncm"]
},
"rm500u-cn":{
"manufacturer_id":"2c7c",
"manufacturer":"quectel",
"platform":"unisoc",
"data_interface":"usb",
"define_connect":"1",
"modes":["ecm","mbim","rndis","ncm"]
},
"rm500u-ea":{
"manufacturer_id":"2c7c",
"manufacturer":"quectel",
"platform":"unisoc",
"data_interface":"usb",
"define_connect":"1",
"modes":["ecm","mbim","rndis","ncm"]
},
"rm500u-cnv":{
"manufacturer_id":"2c7c",
"manufacturer":"quectel",
"platform":"unisoc",
"data_interface":"usb",
"define_connect":"1",
"modes":["ecm","mbim","rndis","ncm"]
},
"rm500q-cn":{
"manufacturer_id":"2c7c",
"manufacturer":"quectel",
"platform":"qualcomm",
"data_interface":"usb",
"define_connect":"1",
"modes":["qmi","gobinet","ecm","mbim","rndis","ncm"]
},
"rm500q-ae":{
"manufacturer_id":"2c7c",
"manufacturer":"quectel",
"platform":"qualcomm",
"data_interface":"usb",
"define_connect":"1",
"modes":["qmi","gobinet","ecm","mbim","rndis","ncm"]
},
"rm500q-gl":{
"manufacturer_id":"2c7c",
"manufacturer":"quectel",
"platform":"qualcomm",
"data_interface":"usb",
"define_connect":"1",
"modes":["qmi","gobinet","ecm","mbim","rndis","ncm"],
"band_5g":"1,2,3,5,7,8,12,20,25,28,38,40,41,48,66,71,77,78,79,257,258,260,261"
},
"rm502q-ae":{
"manufacturer_id":"2c7c",
"manufacturer":"quectel",
"platform":"qualcomm",
"data_interface":"usb",
"define_connect":"1",
"modes":["qmi","gobinet","ecm","mbim","rndis","ncm"]
},
"rm502q-gl":{
"manufacturer_id":"2c7c",
"manufacturer":"quectel",
"platform":"qualcomm",
"data_interface":"usb",
"define_connect":"1",
"modes":["qmi","gobinet","ecm","mbim","rndis","ncm"]
},
"rm505q-ae":{
"manufacturer_id":"2c7c",
"manufacturer":"quectel",
"platform":"qualcomm",
"data_interface":"usb",
"define_connect":"1",
"modes":["qmi","gobinet","ecm","mbim","rndis","ncm"]
},
"rm520n-cn":{
"manufacturer_id":"2c7c",
"manufacturer":"quectel",
"platform":"qualcomm",
"data_interface":"usb",
"define_connect":"1",
"modes":["qmi","gobinet","ecm","mbim","rndis","ncm"]
},
"rm520n-gl":{
"manufacturer_id":"2c7c",
"manufacturer":"quectel",
"platform":"qualcomm",
"data_interface":"usb",
"define_connect":"1",
"modes":["qmi","gobinet","ecm","mbim","rndis","ncm"]
},
"fm650-cn":{
"manufacturer_id":"2cb7",
"manufacturer":"fibocom",
"platform":"unisoc",
"data_interface":"usb",
"define_connect":"1",
"modes":["ecm","mbim","rndis","ncm"]
},
"fm350-gl":{
"manufacturer_id":"0e8d",
"manufacturer":"fibocom",
"platform":"mediatek",
"data_interface":"usb",
"define_connect":"3",
"modes":["rndis"]
},
"fm150-ae":{
"manufacturer_id":"2cb7",
"manufacturer":"fibocom",
"platform":"qualcomm",
"data_interface":"usb",
"define_connect":"1",
"modes":["qmi","gobinet","ecm","mbim","rndis","ncm"]
},
"fm160-cn":{
"manufacturer_id":"2cb7",
"manufacturer":"fibocom",
"platform":"qualcomm",
"data_interface":"usb",
"define_connect":"1",
"modes":["qmi","gobinet","ecm","mbim","rndis","ncm"]
},
"srm815":{
"manufacturer_id":"2dee",
"manufacturer":"meig",
"platform":"qualcomm",
"data_interface":"usb",
"define_connect":"1",
"modes":["qmi","gobinet","ecm","rndis","ncm"]
},
"srm825":{
"manufacturer_id":"2dee",
"manufacturer":"meig",
"platform":"qualcomm",
"data_interface":"usb",
"define_connect":"1",
"modes":["qmi","gobinet","ecm","rndis","ncm"]
},
"srm825n":{
"manufacturer_id":"2dee",
"manufacturer":"meig",
"platform":"qualcomm",
"data_interface":"usb",
"define_connect":"1",
"modes":["qmi","gobinet","ecm","rndis","ncm"]
},
"mh5000-31":{
"manufacturer_id":"12d1",
"manufacturer":"huawei",
"platform":"hisilicon",
"data_interface":"usb",
"define_connect":"1",
"modes":["ecm","ncm"],
"band_2g":"DCS_1800,E-GSM_900,P-GSM_900,GSM_850,R-GSM_900,PCS_1900",
"band_3g":"1,2,5,6,8,9,19",
"band_4g":"1,2,3,4,5,6,7,8,9,10,11,12,13,14,17,18,19,20,21,25,26,28,33,34,35,36,37,38,39,40,41,42,43",
"band_5g":"1,2,3,5,7,8,12,20,25,28,38,40,41,78,79"
}
},
"pci":{
"rm500q-cn":{
"manufacturer":"quectel",
"platform":"qualcomm",
"data_interface":"pci",
"define_connect":"1",
"modes":["qmi","gobinet","mbim"]
},
"rm500q-gl":{
"manufacturer":"quectel",
"platform":"qualcomm",
"data_interface":"pci",
"define_connect":"1",
"modes":["qmi","gobinet","mbim"]
},
"rg500q-ea":{
"manufacturer":"quectel",
"platform":"qualcomm",
"data_interface":"pci",
"define_connect":"1",
"modes":["qmi","gobinet","mbim"]
},
"rm502q-gl":{
"manufacturer":"quectel",
"platform":"qualcomm",
"data_interface":"pci",
"define_connect":"1",
"modes":["qmi","gobinet","mbim"]
},
"rm520n-gl":{
"manufacturer":"quectel",
"platform":"qualcomm",
"data_interface":"pci",
"define_connect":"1",
"modes":["qmi","gobinet","mbim"]
},
"rg520n-eu":{
"manufacturer":"quectel",
"platform":"qualcomm",
"data_interface":"pci",
"define_connect":"1",
"modes":["qmi","gobinet","mbim"]
},
"fm350-gl":{
"manufacturer":"fibocom",
"platform":"mediatek",
"data_interface":"pci",
"define_connect":"1",
"modes":["mbim"]
},
"fm150-ae":{
"manufacturer":"fibocom",
"platform":"qualcomm",
"data_interface":"pci",
"define_connect":"1",
"modes":["qmi","mbim"]
}
},
"device":{
"quectel":{
"unisoc":{
"vendor_id":["2c7c"],
"product_id":["6001","6002","6004","6005","6006","6007","0900","0901","0902","0903","0904"]
},
"qualcomm":{
"vendor_id":["2c7c"],
"product_id":["0121","0125","0191","0195","0296","0306","030b","0435","0452","0455","0512","0620","0800","0801","600b"]
},
"mediatek":{
"vendor_id":["2c7c"],
"product_id":["0700","7001","7003"]
}
},
"fibocom":{
"unisoc":{
"vendor_id":["2cb7","3763","3c93"],
"product_id":["0a04","0a05","0a06","0a07","3c93","ffff"]
},
"qualcomm":{
"vendor_id":["2cb7"],
"product_id":["0104","0105","0106","0107","0108","0109","010A","010B","010F","0110","0111"]
},
"mediatek":{
"vendor_id":["0e8d"],
"product_id":["7126","7127"]
}
},
"meig":{
"unisoc":{
"vendor_id":["2dee"],
"product_id":["4d50","4d51","4d52","4d53"]
},
"qualcomm":{
"vendor_id":["2dee","05c6"],
"product_id":["4d22","4d23","4d38","4d45","f601"]
},
"hisilicon":{
"vendor_id":["2dee"],
"product_id":["4d20"]
},
"asrmicro":{
"vendor_id":["2dee"],
"product_id":["4d57","4d58","4d59"]
}
},
"huawei":{
"hisilicon":{
"vendor_id":["12d1"],
"product_id":["15c3"]
}
}
}
}
}
+25
View File
@@ -0,0 +1,25 @@
#!/bin/sh
# Copyright (C) 2023 Siriling <siriling@qq.com>
#脚本目录
SCRIPT_DIR="/usr/share/modem"
source "${SCRIPT_DIR}/modem_debug.sh"
source "${SCRIPT_DIR}/modem_scan.sh"
#模组扫描任务
modem_scan_task()
{
sleep 8s #刚开机需要等待移动网络出来
while true; do
enable_dial=$(uci -q get modem.@global[0].enable_dial)
if [ "$enable_dial" = "1" ]; then
#扫描模块
debug "开启模块扫描任务"
modem_scan
debug "结束模块扫描任务"
fi
sleep 10s
done
}
modem_scan_task
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,96 @@
{
"network_prefer":{
"2G":{
"enable":1,
"band":[
{"DCS 1800":1},
{"E-GSM 900":1},
{"P-GSM 900":1},
{"GSM 450":1},
{"GSM 480":1},
{"GSM 750":1},
{"GSM 850":1},
{"R-GSM 900":1},
{"PCS 1900":1}
]
},
"3G":{
"enable":1,
"band":[
{"B1":1,"full_name":"WCDMA IMT EUROPE JAPAN & CHINA 2100"},
{"B2":1,"full_name":"WCDMA US PCS 1900"},
{"B3":1,"full_name":"WCDMA Europe and China DCS 1800"},
{"B4":1,"full_name":"WCDMA US 1700"},
{"B5":1,"full_name":"WCDMA US 850"},
{"B6":1,"full_name":"WCDMA Japan 800"},
{"B7":1,"full_name":"WCDMA Europe 2600"},
{"B8":1,"full_name":"WCDMA Europe and Japan 900"},
{"B9":1,"full_name":"WCDMA Japan 1700"},
{"B11":1,"full_name":"WCDMA 1500"},
{"B19":1,"full_name":"WCDMA Japan 850"}
]
},
"4G":{
"enable":1,
"band":[
{"B1":1},
{"B2":1},
{"B3":1},
{"B4":1},
{"B5":1},
{"B6":1},
{"B7":1},
{"B8":1},
{"B9":1},
{"B10":1},
{"B11":1},
{"B12":1},
{"B13":1},
{"B14":1},
{"B17":1},
{"B18":1},
{"B19":1},
{"B20":1},
{"B21":1},
{"B25":1},
{"B26":1},
{"B28":1},
{"B29":1},
{"B30":1},
{"B32":1},
{"B34":1},
{"B38":1},
{"B39":1},
{"B40":1},
{"B41":1},
{"B42":1},
{"B66":1},
{"B71":1}
]
},
"5G":{
"enable":1,
"band":[
{"N1":1},
{"N2":1},
{"N3":1},
{"N5":1},
{"N7":1},
{"N8":1},
{"N12":1},
{"N20":1},
{"N25":1},
{"N28":1},
{"N38":1},
{"N40":1},
{"N41":1},
{"N48":1},
{"N66":1},
{"N71":1},
{"N77":1},
{"N78":1},
{"N79":1}
]
}
}
}
File diff suppressed because it is too large. Load diff
+303
View File
@@ -0,0 +1,303 @@
#!/bin/sh
# Copyright (C) 2023 Siriling <siriling@qq.com>
#脚本目录
SCRIPT_DIR="/usr/share/modem"
#查询信息强度
All_CSQ()
{
debug "All_CSQ"
#信号
OX=$( sh modem_at.sh $at_port "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=$( sh modem_at.sh 2 "ATI")
OX=$( sh modem_at.sh 2 "AT+CGEQNEG=1")
#cellinfo0.gcom
OX1=$( sh modem_at.sh 2 "AT+COPS=3,0;+COPS?")
OX2=$( sh modem_at.sh 2 "AT+COPS=3,2;+COPS?")
OX=$OX1" "$OX2
#cellinfo.gcom
OY1=$( sh modem_at.sh 2 "AT+CREG=2;+CREG?;+CREG=0")
OY2=$( sh modem_at.sh 2 "AT+CEREG=2;+CEREG?;+CEREG=0")
OY3=$( sh modem_at.sh 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<br />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=$( sh modem_at.sh $at_port "AT+CGSN" | sed -n '2p' )
# 获取IMSI
IMSI=$( sh modem_at.sh $at_port "AT+CIMI" | sed -n '2p' )
# 获取ICCID
ICCID=$( sh modem_at.sh $at_port "AT+ICCID" | grep -o "+ICCID:[ ]*[-0-9]\+" | grep -o "[-0-9]\{1,4\}" )
# 获取电话号码
phone=$( sh modem_at.sh $at_port "AT+CNUM" | grep "+CNUM:" )
}
#simcom查找基站AT
get_simcom_data()
{
debug "get simcom data"
#设置AT串口
at_port=$1
All_CSQ
SIMCOM_SIMINFO
SIMCOM_Cellinfo
#温度
OX=$( sh modem_at.sh $at_port "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=$( sh modem_at.sh $at_port "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=$( sh modem_at.sh $at_port "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=$( sh modem_at.sh $at_port "AT+CMGRMI=4")
CAINFO=$(echo "$OX" | grep -o "$REGXz" | tr ' ' ':')
if [ -n "$CAINFO" ]; then
for CASV in $(echo "$CAINFO"); do
LBAND=$LBAND"<br />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
}
@@ -0,0 +1,14 @@
{
"vendor_support":{
"2c7c":"quectel",
"2cb7":"fibocom",
"3763":"fibocom",
"3c93":"fibocom",
"0e8d":"fibocom",
"2dee":"meig",
"05c6":"meig",
"4d20":"meig",
"12d1":"huawei",
"17cb":"qualcomm"
}
}
@@ -0,0 +1,11 @@
{
"luci-app-modem": {
"description": "Grant UCI access for luci-app-modem",
"read": {
"uci": [ "modem" ]
},
"write": {
"uci": [ "modem" ]
}
}
}