蜂窝基础开发

本章节主要介绍 QuecPython 模组的拨号上网流程,拿到模组后如何注网拨号以及网络异常的处理等

QuecPython 拨号上网流程

设备硬件连接

首先按照上文的硬件准备步骤安装开发板配套的天线(部分开发板型号有板载天线的不需要安装),并将SIM卡插入开发板上的SIM卡座,然后将模组连接电源并开机,开机后模组会自动进行网卡激活。

获取拨号信息

QuecPython的模组默认开机都会自动激活第一路蜂窝无线网卡,只有蜂窝无线网卡激活成功,才能进行socket、http、mqtt等网络业务。

所以在业务动作之前需要先获取拨号信息,包括拨号状态、IP地址、DNS服务器地址等,以此来判断网卡是否激活成功

import dataCall
dataCall.getInfo(profileID, ipType)
# profileID - PDP上下文ID,整型值,范围1~3。
# ipType - IP协议类型,整型值,0:IPV4  1:IPV6  2:IPV4&IPV6

返回值格式为

(profileID, ipType, [state, reconnect, addr, priDNS, secDNS])

查询网卡状态信息这一操作,是用户必须进行的。不管是什么应用场景,只要用户需要进行网络业务操作,就必须先查询网卡激活状态,确认蜂窝无线网卡已经激活成功。具体而言,只要用户有如下需求,都需要使用dataCall.getInfo来查询:

  • 确认蜂窝无线网卡激活是否成功,通过dataCall.getInfo方法返回值的state来确定,为1表示激活成功。
  • 用户使用QuecPython的socket功能时,需要知道模组当前的IP地址。
  • 激活多路蜂窝无线网卡后,需要建立多路socket,不同的socket使用不同的网卡,此时需要获取每一路网卡的IP地址信息,然后与对应的socket进行绑定。
  • 获取蜂窝无线网卡当前使用DNS地址。

如果获取拨号信息发现网卡激活失败则需要手动激活网卡

手动激活网卡

经过上述的查询处理后如果网卡激活失败则需要手动激活网卡,使用如下的API来手动激活网卡

dataCall.activate(profileID)
# profileID - PDP上下文ID,整型值,范围1~3。

QuecPython的模组默认开机都会自动激活蜂窝无线网卡,正常情况无需手动设置激活或者去激活操作,但是一些特殊场景或者用户的特殊需求,需要使用上述方法来手动激活或者去激活蜂窝无线网卡,比如:

用户关闭了开机自动激活蜂窝无线网卡功能,由用户应用程序根据需要在某个时间进行网卡的激活和去激活操作。这种情况下,就需要用户在其应用程序中,根据需要来调用dataCall.activatedataCall.deactivate方法。

获取SIM卡状态

如果模组蜂窝无线网卡手动激活失败,需要依次排查SIM卡和注网状态,查询SIM状态需要使用以下API来获取

import sim
sim.getStatus()

如果sim.getStatus()的返回值为0,说明设备没有检测到SIM卡,此时需要确定是否插入了SIM卡。如果用户已经插入SIM卡并且重启设备后,查询状态值还是0,那可能的原因如下:

  • SIM卡没有插好,比如插反了、没有插紧。可以重新插入SIM卡并重启设备,开机后再次查询SIM卡状态是否为1。
  • SIM卡本身有损坏。可以换一张可以正常使用的SIM卡插入后,重启设备,然后再次查询SIM卡状态是否为1。
  • SIM卡卡槽有损坏。如果确认是这个问题,则需要更换新的卡槽。
  • SIM卡的硬件电路存在问题,比如接触不良,导致设备无法正常识别SIM卡。需要硬件工程师检查电路确认问题。

用户可以依次排查上面几种情况来确认问题。

如果返回值为1,说明已经检测到SIM卡,则需要检测注网状态

其他状态的SIM卡异常参考SIM卡异常处理

获取设备网络注册状态

设备的蜂窝无线网络注册状态是非常重要的参数。成功激活蜂窝无线网卡的前提,就是设备必须先注网成功。QuecPython提供了相关API用来查询设备的注网状态。通过该API可以查询当前设备的网络状态

import net
net.getState()

API返回值为

([voice_state, voice_lac, voice_cid, voice_rat, voice_reject_cause, voice_psc], [data_state, data_lac, data_cid, data_rat, data_reject_cause, data_psc])

其中data_state为网络注册状态,网络注册状态有多种情况,当返回值为1或者5时可视为网络注册成功,具体返回值参考获取网络注册信息,当网络注册状态不为1或5的情况,可视为网络异常,导致网络异常的原因可能有多种,比方说SIM卡欠费、SIM卡只支持特定网络制式或者特定频段等、射频性能不好、没有配置APN等,以上异常的情况的详细处理步骤参考模块网络注册失败

正常情况下,只要模组网卡能激活成功,用户是不需要查询注网状态的。需要查询设备注网状态的场景主要如下:

  • 模组蜂窝无线网卡激活失败,需要依次排查SIM卡和注网状态。此时可以使用net.getState来查询注网状态,确认设备注网有没有成功,如果注册网络状态异常则需要按照上述步骤继续检查。

网络状态检测

QuecPython提供了检测网络状态的API接口,可以用于检测网络状态是否已经就绪。

checkNet.waitNetworkReady(timeout)

等待模组网络就绪。该方法会依次检测SIM卡状态、模组网络注册状态和PDP Context激活状态;在设定的超时时间之内,如果检测到PDP Context激活成功,会立即返回,否则直到超时才会退出。可以直接使用该API接口来检测网络代替上文的检测SIM卡状态、模组网络注册状态和PDP Context激活状态三个步骤,如果检测出对应步骤有异常再去对异常的部分进行检测处理

参数描述:

  • timeout - 超时时间,整型值,范围1~3600秒,默认60秒。

返回值描述:

返回一个元组,格式为:(stage, state)

参数 类型 含义
stage 整型 表示当前正在检测什么状态: 1 - 正在检测SIM卡状态; 2 - 正在检测网络注册状态; 3 - 正在检测PDP Context激活状态。
state 整型 根据stage值,来表示不同的状态,具体如下: stage = 1时,state表示 SIM卡的状态,范围0-21,每个状态值的详细说明,请参考sim.getStatus()方法的返回值说明; stage = 2时,state表示网络注册状态,范围0-11,每个状态值的详细说明,请参考net.getState()方法的返回值说明; stage = 3时,state表示PDP Context激活状态,0表示没有激活成功,1表示激活成功。

异常处理

网络异常分为两种。一种是在开机时发生网络异常,一种是开机已经注网成功,然后在后续的业务处理过程中网络异常

设备开机时的网络异常处理

模组开机时的网络异常,主要包括3种情况,分别是:

  • SIM卡异常
  • 模组网络注册失败
  • 蜂窝无线网卡自动激活失败

这3种情况导致的直接结果,就是模组无法连接到网络。因此我们将这些情况都称之为“网络异常”,以上三种异常情况的检查和处理流程参见上文。

设备运行过程中网络异常处理

蜂窝无线网卡激活成功后,用户的应用程序还需要关注一件事——设备与网络的连接状态。这是因为在设备运行过程中,可能会因为一些异常原因(如网络异常、环境干扰、信号差等)导致模组与网络的连接断开。如果用户应用程序没有关注这种网络事件,很可能导致用户应用程序中和网络相关的业务执行异常,导致出现无法预料的问题。

QuecPython提供了网络事件监听功能,用户应用程序可以通过注册回调函数的方式来监听网络状态变化事件。当设备与无线网络的连接状态发生变化时,系统就会自动将对应的事件通过用户注册的回调函数,推送给用户的应用程序。

注册网络监听回调函数的方法如下:

dataCall.setCallback(fun)

回调函数的示例如下:

def netCallback(args):
    profileID = args[0]
    netState = args[1]
    if netState == 0:
        print('### network {} disconnected.'.format(profileID))
    elif netState == 1:
        print('### network {} connected.'.format(profileID))

该回调函数的参数是一个元组,包含3个元素,目前用户只需要关注前两个元素即可。前两个参数说明如下:

参数 类型 说明
args[0] 整型 蜂窝无线网卡编号,表示当前是哪一路无线网卡的网络连接状态发生了变化。
args[1] 整型 网络状态,0表示网络连接断开,1表示网络连接成功。

建议用户注册该回调函数,用于监听网络连接状态,确保当网络连接状态发生变化时,用户应用程序可以根据网络状态变化进行及时的处理。通常,我们可以参考下面的方式来处理:

  • 回调函数中收到网络连接状态发生变化的事件后,通过消息队列功能将网络事件发送给其他线程去处理。当然,用户也可以使用QuecPython的sys_bus功能来代替消息队列。
  • 其他线程在收到网络事件时,判断如果是网络连接断开事件,则停止socket、mqtt等这类和网络相关的业务。同时,该线程也可以选择启动一个定时器,比如先将定时器时间设定为60s。如果60s后,网络还没有恢复,则执行CFUN0/1切换,然后看网络是否可以恢复。

什么是CFUN0/1切换?

通过《蜂窝网络基础概念》章节中关于CFUN的说明,可以知道,CFUN指的是移动终端的功能模式。CFUN0/1切换是指通过net.setModemFun(0)方法先将设备切换到模式0(最小功能模式),然后再通过net.setModemFun(1)方法将设备切换到模式1(全功能模式)。当切换到模式0,设备的整个射频网络协议栈全部关闭,SIM卡模块停止供电;再次切换到模式1时,会重新恢复对SIM卡的供电并重新进行初始化,同时与射频相关的软硬件功能都会重新开启,此时设备会重新发起网络注册流程。

为什么要进行CFUN0/1切换?

QuecPython具有自动重连功能,如果发生网络异常导致设备与网络的连接断开,异常消失后,不是应该自动恢复吗?为什么上面提到的处理方式中,还要进行CFUN0/1的切换?

我们需要搞清楚,QuecPython的自动重连功能指的是在网络异常恢复后,模组自动重新激活无线网卡,而不是重新注册到网络。设备的网络注册行为是由系统的射频网络协议栈自动控制的,理论上在网络异常因素消失后,射频网络协议栈会自动重新发起网络注册。但是不排除因为一些原因,导致设备没有及时重新进行网络注册的情况。这时因为设备网络注册尚未成功,无线网卡也无法重新激活。因此,我们主动进行了CFUN0/1的切换操作。其实就像是我们平时使用手机时,有时候遇到网络差或者没信号的时候,我们会选择先关闭手机的移动网络,然后再重新打开是一样的道理。当然,用户也可以选择进行重启。