跳转至

04 SIM 双卡切换

作者:拓毅恒 | 最后修改:2026-01-22

一、概述

SIM 卡切换功能是 Air780EGP/Air780EGG 核心板的一项重要移动通信功能,用于在当前使用的 SIM 卡网络异常时,切换到另一张 SIM 卡,确保设备始终保持网络连接。

对于需要高可靠性网络连接的物联网应用来说,SIM 卡切换功能尤为重要。当主 SIM 卡因信号弱、网络故障或其他原因导致网络连接中断时,设备可以切换到备用 SIM 卡,避免因网络中断造成的数据丢失或业务中断。

主要特点:

  • 实时检测:实时监控当前 SIM 卡的网络状态
  • 智能切换:当网络连接失败时,切换到另一张 SIM 卡
  • 无缝连接:切换过程中自动处理飞行模式和网络重新连接
  • 稳定性高:内置合理的超时控制和重试机制

SIM 卡切换功能是构建高可用性物联网设备的重要保障,特别适合在网络环境不稳定或需要连续运行的场景中使用。

二、准备硬件环境

参考:Air780EGP/Air780EGG 核心板使用说明,准备好硬件环境。

2.1 Air780EGP/Air780EGG 核心板

测试本 demo 需要在 nano-sim 卡座上插入 sim 卡

并且需要如下图方式,在核心板背面自行焊上 5mm*6mm 的贴片卡,方可进行测试

三、准备软件环境

3.1 文章内容应用

在开始实践本示例之前,先筹备一下软件环境:

1. 烧录工具:Luatools 工具

2. 内核固件:https://docs.openluat.com/air780egh/luatos/firmware/version/

3. 脚本文件:https://gitee.com/openLuat/LuatOS/tree/master/module/Air780EHM_Air780EHV_Air780EGH/demo/mobile

4. LuatOS 运行所需要的 lib 文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件。

准备好软件环境之后,接下来查看如何烧录项目文件到 780EGG/EGP/EGH 中,将本篇文章中演示使用的项目文件烧录到 Air780EGP/Air780EGG 核心板中。

3.2 API 介绍

这里仅介绍本篇文档所使用的 API,详情请查看:mobile - API

mobile.simid(id, auto)

设置或获取当前使用的 SIM 卡

mobile.status()

获取移动网络状态

mobile.flymode(simid, enable)

设置飞行模式

mobile.setAuto(try_time, search_time, try_cnt)

设置 SIM 卡自动恢复参数

四、mobile 功能实现概述

本小节详细介绍 Air780EGP/Air780EGG 核心板上移动网络各种功能的实现方法和核心代码逻辑。

SIM 卡切换功能提供三种实现方式,满足不同应用场景的需求:

4.1 轮询主动指定 simid 切换 sim 卡

4.1.1 功能定义

定期检查网络状态,当网络异常时主动切换到指定 SIM 卡。

4.1.2 代码示例

-- 开启SIM暂时脱离后自动恢复,30秒搜索一次周围小区信息
mobile.setAuto(10000, 30000, 5, nil, 30000) -- 此函数仅需要配置一次

-- 轮询主动指定simid切换sim卡
local function sim_switch_task()
    -- 当前使用的SIM卡索引(0或1)
    local current_sim = 0
    -- 初始选择SIM0
    mobile.simid(current_sim)
    log.info("sim_switch", "初始SIM卡:", current_sim)

    while true do
        -- 获取当前网络状态
        local status = mobile.status()
        log.info("sim_switch", "当前SIM卡:", current_sim, "网络状态:", status)

        -- 如果网络状态不是REGISTERED或REGISTERED_ROAMING,则等待一段时间后检查是否联网成功
        if status ~= mobile.REGISTERED and status ~= mobile.REGISTERED_ROAMING then
            log.info("sim_switch", "正在等待网络连接...")
            -- 联网超时时间(15秒)
            sys.wait(15000)

            -- 再次检查网络状态
            status = mobile.status()
            if status ~= mobile.REGISTERED and status ~= mobile.REGISTERED_ROAMING then
                -- 网络连接失败,切换到另一张SIM卡
                current_sim = current_sim == 0 and 1 or 0
                log.info("sim_switch", "网络连接失败,切换到SIM卡", current_sim)
                -- 切换SIM卡
                mobile.simid(current_sim)
            else
                log.info("sim_switch", "网络连接成功")
            end
        else
            log.info("sim_switch", "网络已经连接")
        end
        sys.wait(10000) -- 每10秒检查一次网络状态
    end
end

4.2 轮询自适应切换 sim 卡

4.2.1 功能定义

系统自动选择最优 SIM 卡,无需手动指定。

4.2.2 代码示例

-- 开启SIM暂时脱离后自动恢复,30秒搜索一次周围小区信息
mobile.setAuto(10000, 30000, 5, nil, 30000) -- 此函数仅需要配置一次

-- 轮询自适应切换sim卡
-- 注:自适应模式需要设备使用V2022及以上固件才可以使用!!!
local function sim_switch_adaptive_task()
    -- 自适应方式切换SIM卡(设置mobile.simid(2)启用自适应模式)
    mobile.simid(2)
    -- 等待设置完毕
    sys.wait(3000)
    -- 获取当前使用的SIM卡索引
    local current_sim = mobile.simid()
    log.info("sim_switch", "初始SIM卡:", current_sim)

    while true do
        -- 获取当前网络状态
        local status = mobile.status()
        current_sim = mobile.simid()
        log.info("sim_switch", "当前SIM卡:", current_sim, "网络状态:", status)

        -- 如果网络状态不是REGISTERED或REGISTERED_ROAMING,则等待一段时间后检查是否联网成功
        if status ~= mobile.REGISTERED and status ~= mobile.REGISTERED_ROAMING then
            log.info("sim_switch", "正在等待网络连接...")
            -- 联网超时时间(15秒)
            sys.wait(15000)

            -- 再次检查网络状态
            status = mobile.status()
            if status ~= mobile.REGISTERED and status ~= mobile.REGISTERED_ROAMING then
                -- 网络连接失败,系统将自动选择最优SIM卡
                log.info("sim_switch", "网络连接失败,系统将自动选择最优SIM卡")
            else
                log.info("sim_switch", "网络连接成功")
            end
        else
            log.info("sim_switch", "网络已经连接")
        end
        sys.wait(10000) -- 每10秒检查一次网络状态
    end
end

4.3 中断方式切换 sim 卡

4.3.1 功能定义

通过按键触发(WAKEUP0 引脚)中断切换 SIM 卡。

4.3.2 代码示例

-- 开启SIM暂时脱离后自动恢复,30秒搜索一次周围小区信息
mobile.setAuto(10000, 30000, 5, nil, 30000) -- 此函数仅需要配置一次

-- 全局变量:中断方式切换SIM卡时的当前SIM卡索引
local current_sim_irq = 0

-- 设置中断触发回调函数
local function sim_switch_callback()
    -- 按键触发后,切换到另一张SIM卡
    current_sim_irq = current_sim_irq == 0 and 1 or 0
    log.info("sim_switch", "按键触发,开始切换到SIM卡:", current_sim_irq)

    -- 指定simid切换SIM卡
    local result = mobile.simid(current_sim_irq)
    if result then
        log.info("sim_switch", "SIM卡切换成功,当前使用SIM卡:", current_sim_irq)
    else
        log.error("sim_switch", "SIM卡切换失败")
    end
end

-- 中断方式主动指定simid切换sim卡
local function sim_switch_irq_task()
    -- 初始化全局变量
    current_sim_irq = 0
    log.info("sim_switch", "初始SIM卡:", current_sim_irq)
    -- 设置默认使用SIM0
    mobile.simid(current_sim_irq)

    -- 配置WAKEUP0引脚防抖(500ms)
    gpio.debounce(gpio.WAKEUP0, 500)

    -- 配置WAKEUP0引脚为下降沿触发中断
    gpio.setup(gpio.WAKEUP0, sim_switch_callback, gpio.PULLUP, gpio.FALLING)

    -- 定时打印当前状态的循环
    while true do
        local status = mobile.status()
        log.info("sim_switch", "当前SIM卡:", current_sim_irq, "网络状态:", status)
        sys.wait(10000) -- 每10秒打印一次
    end
end

五、功能演示

5.1 轮询主动指定 simid 切换 sim 卡

功能介绍

定期检查网络状态,网络异常时主动切换到指定 SIM 卡,使用 mobile.simid() 直接指定 SIM 卡索引进行切换,切换逻辑明确可控。

配置说明

sim_switch_test.lua 文件末尾,启用轮询主动指定 simid 切换 sim 卡功能:

-- 启动双卡切换任务(三选一)
-- 轮询主动指定simid切换sim卡
sys.taskInit(sim_switch_task)
-- 轮询自适应切换sim卡
-- sys.taskInit(sim_switch_adaptive_task)
-- 中断方式主动指定simid切换sim卡
-- sys.taskInit(sim_switch_irq_task)

演示步骤

  1. main.lua 中将功能启动

  1. 使用 Luatools 将代码烧录到 Air780EGP/Air780EGG 核心板

  1. 设备启动后,日志中会打印初始选择的 SIM 卡信息,如图下图所示:

  1. 设备会定期检查当前 SIM 卡的网络状态,如图下图所示:

  1. 当前 SIM 卡网络连接失败时,设备会切换到另一张 SIM 卡,如图下图所示:

  1. 切换 SIM 卡后,设备会重新建立网络连接,如图下图所示:

5.2 轮询自适应切换 sim 卡

功能介绍

系统自动选择最优 SIM 卡,无需手动指定,设置 mobile.simid(2) 启用自适应模式,由系统智能选择最佳 SIM 卡。

配置说明

sim_switch_test.lua 文件末尾,启用轮询自适应切换 sim 卡功能:

-- 启动双卡切换任务(三选一)
-- 轮询主动指定simid切换sim卡
-- sys.taskInit(sim_switch_task)
-- 轮询自适应切换sim卡
sys.taskInit(sim_switch_adaptive_task)
-- 中断方式主动指定simid切换sim卡
-- sys.taskInit(sim_switch_irq_task)

注意事项:自适应模式需要设备使用 V2022 及以上固件才可以使用!!!

演示步骤

  1. main.lua 中将功能启动

  1. 使用 Luatools 将代码烧录到 Air780EGP/Air780EGG 核心板

  1. 烧录完毕后,设备将选择最优 SIM 卡进行连接。这里为了演示,就先将一张坏卡放入 SIM0,等待设备识别后再将一张好卡放入 SIM1,来模拟 SIM0 使用过程中出现异常,切换 SIM1 的过程。

  1. 设备会定期检查当前 SIM 卡的网络状态,检测到当前 SIM 卡网络异常时,设备会切换到最优 SIM 卡

  1. 切换后设备重新建立网络连接,可以看到当 SIM1 卡状态正常的时候,成功切换到 SIM1 的网络

5.3 中断方式主动指定 simid 切换 sim 卡

功能介绍

按键触发(WAKEUP0 引脚)中断切换 SIM 卡,下降沿触发中断,带有 500ms 防抖,实时打印当前 SIM 卡状态和网络状态。

硬件要求

需将 WAKEUP0 短接 GND,模拟按键触发中断。

配置说明

sim_switch_test.lua 文件末尾,启用中断方式主动指定 simid 切换 sim 卡功能:

-- 启动双卡切换任务(三选一)
-- 轮询主动指定simid切换sim卡
-- sys.taskInit(sim_switch_task)
-- 轮询自适应切换sim卡
-- sys.taskInit(sim_switch_adaptive_task)
-- 中断方式主动指定simid切换sim卡
sys.taskInit(sim_switch_irq_task)

演示步骤

  1. main.lua 中将功能启动

  1. 使用 Luatools 将代码烧录到 Air780EGP/Air780EGG 核心板

  1. 设备会定期打印当前 SIM 卡状态和网络状态

  1. 将 WAKEUP0 短接 GND,模拟按键触发中断,设备切换到另一张 SIM 卡

  1. 切换后设备重新建立网络连接

六、总结

本 demo 实现了 SIM 卡切换功能,当当前使用的 SIM 卡网络异常时,设备会切换到另一张 SIM 卡并重新建立网络连接,确保设备始终保持网络连接。