如何使用 AT 命令通过数据卡以编程方式连接互联网?

How to programmatically connect internet via datacard with AT commands?

我有一张数据卡中兴MF190。我想用AT命令注册2G或3G网络,通过数据卡上网。找到这篇关于 how to make data call 的文章:

AT+cgatt=1
AT+CGDCONT=1,”IP”,”epc.tmobile.com” //I used my operator PDP context
AT+CGACT=1,1

但是 OS 终端的 ping 显示 100% 包丢失。 我试过 Ubuntu 14 和 Windows 7.

如何在 Ubuntu 上使用数据卡通过 AT 命令连接互联网?

更新

我悬赏了@tripleee 的回答,因为它比第一个更完整,并且回答了我所有的问题。但是我对答案不满意,所以我会在一周内回答我自己的问题。

在我的回答中,我将展示如何使用 Java 处理这个过程。所以,请不要将此问题移至其他 Stack Exchange 网站。

I tried to sniff USB port but on this case dashboard can not connect because of busy port

当然可以。参见 this question

Found this article about how to make data call

那篇文章是关于如何设置呼叫的,而不是如何进行呼叫的。 进行正确设置后,使用以下命令连接到互联网: ATD*99***1#

UPDATE1:经过一番研究,我认为这篇文章只是为了推广他们的软件而写的,没有实际用途。实际上拨号是用 pppdwvdial

UPDATE2:我们在a chat room (in Russian). It turned out cnetworkmanager中讨论了解决问题的方法将是

在卡和您的提供商之间建立连接是不够的。您需要某种机制从该连接创建网络接口,并设置您的网络堆栈以通过该接口路由数据包。

传统上,pppd 守护程序一直是此任务的流行选择。您将使用用于建立数据调用的命令创建一个 "chat script"(如今,pppd 可能与合适的固定脚本打包在一起)并且守护进程将处理发出调用、验证、在电路上设置网络接口,配置系统在其上路由数据包,以及配置 DNS 等以将其用于解析器查询等。

据我所知wvdial uses ppp daemon使用调制解调器连接到互联网。 wvdial 已预装在桌面版 Ubuntu 上。

wvdial 使用位于 /etc/wvdial.conf 的配置文件。让我们编辑这个文件。输入您的终端

sudo nano /etc/wvdial.conf

你会看到这样的东西

[Dialer Defaults]
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2
Stupid Mode = yes
ISDN = 0
Modem Type = Analog Modem
New PPPD = yes
Phone = *99#
Modem = /dev/ttyUSB2
Username = ''
Password = ''
Baud = 9600
Dial Timeout = 30
Dial Attempts = 3

您可以在 wvdial.conf(5) - Linux man page 中找到的所有键的说明。如果您需要更改提供商的拨号号码、用户名、密码或任何其他有关连接和设备的信息,您可以更改文件内容并保存。

ZTE MF190有3个串口。通常为 ttyUSB0ttyUSB1ttyUSB2。在我的例子中 ttyUSB2 用于互联网连接。它不适用于其他端口。所以你需要为你的调制解调器找到正确的串口。

有一个自动配置器可以编辑wvdial.conf文件,设置串口波特率等。因为它并不总是配置正确我会不推荐使用:

sudo wvdialconf /etc/wvdial.conf

手动配置wvdial会更好。

现在,当您的设备已连接并且 wvdial 配置为与设备一起工作时,您可以从终端执行此行:

wvdial

你会看到很多行。但是,如果您看到这些行 - 您就成功了。

local  IP address XX.XX.XX.XX
remote IP address XX.XX.XX.XX
primary   DNS address XX.XX.XX.XX
secondary DNS address XX.XX.XX.XX

现在,我们如何在编程中使用它?我将在 Java 上提供一些代码来使用它。您可以使用此代码拨号。

public int dialer() { 
    // status for debug. If status == 4 then you connected successfully
    int status; 
    // create process of wvdial
    ProcessBuilder builder = new ProcessBuilder("wvdial");

    try {
        // start wvdial
        final Process process = builder.start();

        // wvdial listener thread
        final Thread ioThread = new Thread() {
            @Override
            public void run() {
                try {

                    final BufferedReader reader = new BufferedReader(
                            new InputStreamReader(process.getErrorStream()));
                    // wvdial output line
                    String line;

                    while ((line = reader.readLine()) != null) {
                        // if "local  IP address" line detected set status 1
                        if (line.contains("local  IP address")) {
                            status = 1;
                        }
                        if (line.contains("remote IP address")) {
                            status = 2;
                        }
                        if (line.contains("primary   DNS address")) {
                            status = 3;
                        }
                        if (line.contains("secondary DNS address")) {
                            status = 4;
                        }
                    }

                    reader.close();
                } catch (final Exception e) {
                }
            }
        };
        // start listener
        ioThread.start();
        // wait 6 secs and return status. Some kind of timeout
        Thread.sleep(6000);
    } catch (Exception e) {
    }
    return status;
}

这是一种断开连接的方法。您只需要杀死 wvdial 进程,线程就会被销毁:

public boolean disconnect() { 

    ProcessBuilder builder = new ProcessBuilder("pkill", "wvdial");
    try {
        builder.start();
        return true;
    } catch (IOException e) {
        return false;
    }
}