# QVSIM ***Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.*** --- # 概述 QVSIM是移远通信提供的一套 **虚拟SIM(vSIM)管理与业务控制框架**,用于在模组侧实现实体SIM与虚拟SIM之间的统一管理与灵活切换。 通过QVSIM,终端设备无需更换实体卡,即可按需启停虚拟SIM业务,满足多运营商、多区域和动态配置的通信需求。 QVSIM支持通过 **远程服务平台** 对虚拟SIM Profile 进行集中管理,包括Profile的下载、删除、更新及切换等操作。模组侧通过OTA机制与平台建立连接,并以事件方式实时上报业务进度和结果,应用层可据此完成自动化控制与状态监测。 在运行过程中,QVSIM负责选择合适的Profile并完成 **实体SIM与虚拟SIM之间的业务切换**,对上层应用屏蔽底层实现细节。应用只需调用标准API,即可完成虚拟SIM业务的启动、停止和状态查询,无需关心具体卡类型或网络接入差异。 通过QVSIM,设备能够实现 **更灵活的联网策略、更低的运维成本以及更高的部署效率**,适用于跨区域部署、批量设备管理以及对SIM灵活性要求较高的场景。 ```{figure} images/board_Ry1TwTyvrhogXEbxqVecBzUGnfc.jpg :align: center :alt: image ``` # API说明 ## 头文件 `qosa_qvsim.h` ## 函数列表 | **函数** | **描述** | | --- | --- | | `qosa_qvsim_start()` | 启动QVSIM服务 | | `qosa_qvsim_stop()` | 停止QVSIM服务 | | `qosa_qvsim_get_status()` | 获取QVSIM运行状态 | | `qosa_qvsim_get_version()` | 获取QVSIM主版本号 | | `qosa_qvsim_get_sub_version()` | 获取子版本号 | | `qosa_qvsim_get_uid()` | 获取设备UID | | `qosa_qvsim_list_profiles()` | 获取Profile列表 | | `qosa_qvsim_get_current_profile()` | 获取当前Profile | | `qosa_qvsim_select_profile()` | 切换Profile | | `qosa_qvsim_set_ota_config()` | 配置OTA服务器认证信息及访问地址 | | `qosa_qvsim_get_ota_config()` | 查询OTA服务器认证信息及访问地址 | | `qosa_qvsim_start_ota()` | 启动OTA流程,进行远程Profile下载与激活 | | `qosa_qvsim_switch_ir()` | 切换IR | | `qosa_qvsim_get_current_ir()` | 查询当前IR | | `qosa_qvsim_register_callback()` | 注册事件回调 | --- ## 函数定义 ### QVSIM基础控制接口 #### qosa_qvsim_start ##### 函数原型 ```c qosa_qvsim_err_e qosa_qvsim_start(void); ``` ##### 功能描述 启动QVSIM服务并进入虚拟SIM工作状态。该接口用于根据当前配置和运行环境,**选择并激活合适的vSIM Profile**,在需要时完成 **实体SIM向虚拟SIM的业务切换**,并初始化虚拟卡相关业务流程,使系统进入基于虚拟SIM的通信工作模式。 ##### 参数说明 无 ##### 返回值说明 - `QOSA_QVSIM_ERR_OK`:启动成功 - `QOSA_QVSIM_ERR_ALREADY_STARTED`:服务已启动 - `QOSA_QVSIM_ERR_NO_PROFILE`:没有可用的Profile ```{note} **注意:** 1. 本接口是异步接口,实际select是否成功,通过 `QOSA_QVSIM_EVENT_START_PROFILE` 事件返回。 2. 配置保存到NV。 ``` #### qosa_qvsim_stop ##### 函数原型 ```c qosa_qvsim_err_e qosa_qvsim_stop(void); ``` ##### 功能描述 停止QVSIM服务并退出虚拟SIM工作状态。该接口用于 **关闭虚拟SIM相关业务功能**,在需要时完成 **虚拟SIM向实体SIM的业务回切**,释放虚拟SIM运行过程中占用的相关资源,使系统恢复至实体SIM工作模式。 ##### 返回值说明 - `QOSA_QVSIM_ERR_OK`:停止成功 - `QOSA_QVSIM_ERR_ALREADY_STARTED`:服务未启动 ```{note} **注意:** 1. 本接口是异步接口, 实际select是否成功,通过 `QOSA_QVSIM_EVENT_START_PROFILE` 事件返回。 ``` #### qosa_qvsim_get_status ##### 函数原型 ```c qosa_qvsim_status_e qosa_qvsim_get_status(void); ``` ##### 功能描述 获取当前QVSIM是否为启用状态。 ##### 返回值说明 - `QOSA_QVSIM_STATUS_DISABLED`:QVSIM为停用状态 - `QOSA_QVSIM_STATUS_ENABLED`:QVSIM为启用状态 --- ### Profile管理接口 #### qosa_qvsim_list_profiles ##### 函数原型 ```c qosa_qvsim_err_e qosa_qvsim_list_profiles( qosa_qvsim_profile_t *profiles, qosa_uint8_t *profile_count, qosa_uint8_t max_count ); ``` ##### 功能描述 获取设备中已存储的全部vSIM Profile信息列表。 QVSIM会在不超过 `max_count` 的前提下,将当前已存储的Profile信息写入 `profiles` 数组,实际写入数量通过 `profile_count` 返回。 若设备中Profile数量超过 `max_count`,仅返回前 `max_count` 个Profile。 ##### 参数说明 | **参数名** | **类型** | **是否必填** | **范围/单位** | **说明** | | --- | --- | --- | --- | --- | | profiles | `qosa_qvsim_profile_t` * | 是 | 参考 `qosa_qvsim_profile_t` | Profile数组缓冲区 | | profile_count | qosa_uint8_t * | 是 | 0~10 | 返回Profile数量 | | max_count | qosa_uint8_t | 是 | 1~10 | 最大可写入数量 | ##### 返回值说明 - `QOSA_QVSIM_ERR_OK`:获取Profile列表成功 - `QOSA_QVSIM_ERR_INVAL_PARM`:参数非法 ```{note} **注意:** 1. **调用方需自行分配Profile数组缓存空间。**`profiles` 参数用于承载QVSIM返回的Profile列表数据,调用前必须提供有效的数组指针,并确保数组容量不少于 `max_count` 所指定的数量。 ``` --- #### qosa_qvsim_get_current_profile ##### 函数原型 ```c qosa_qvsim_err_e qosa_qvsim_get_current_profile( qosa_qvsim_profile_t *profile ); ``` ##### 功能描述 获取当前激活使用中的vSIM Profile信息。 ##### 参数说明 | **参数名** | **类型** | **是否必填** | **范围/单位** | **说明** | | --- | --- | --- | --- | --- | | profile | `qosa_qvsim_profile_t` * | 是 | 参考 `qosa_qvsim_profile_t` | Profile返回数据 | ##### 返回值说明 - `QOSA_QVSIM_ERR_OK`:成功获取当前使用的vSIM Profile信息 - `QOSA_QVSIM_ERR_INVAL_PARM`:参数非法 ```{note} **注意:** 1. 如果当前未启用vSIM功能, 调用本接口会报错。 ``` --- #### qosa_qvsim_select_profile ##### 函数原型 ```c qosa_qvsim_err_e qosa_qvsim_select_profile( int type, int value_slot, const char *iccid ); ``` ##### 功能描述 切换当前激活使用的虚拟SIM Profile。 ##### 参数说明 | **参数名** | **类型** | **是否必填** | **范围/单位** | **说明** | | --- | --- | --- | --- | --- | | type | int | 是 | 0:按Slot切换
1:按ICCID切换 | 选择类型 | | value_slot | int | 否 | 0~9 | type为0时有效 | | iccid | const char * | 否 | 字符串类型, 如"89860010127495514284" | type为1时有效 | ##### 返回值说明 - `QOSA_QVSIM_ERR_OK`:接口调用成功 - `QOSA_QVSIM_ERR_INVAL_PARM`:参数非法 ```{note} **注意:** 1. 本接口是异步接口,实际select是否成功,通过 `QOSA_QVSIM_EVENT_SELECT_PROFILE` 事件返回。 2. 调用本接口前,需要确保已经通过 `qosa_qvsim_start` 启动QVSIM功能。 ``` --- ### OTA管理接口 #### **qosa_qvsim_set_ota_config** ##### 函数原型 ```c qosa_qvsim_err_e qosa_qvsim_set_ota_config( const qosa_qvsim_ota_config_t *config ); ``` ##### 功能描述 配置OTA服务器认证信息及访问地址。 ##### 参数说明 | **参数名** | **类型** | **是否必填** | **范围/单位** | **说明** | | --- | --- | --- | --- | --- | | config | `qosa_qvsim_ota_config_t` * | 是 | 参考 `qosa_qvsim_ota_config_t` | OTA服务器相关信息 | ##### 返回值说明 - `QOSA_QVSIM_ERR_OK`:配置成功 - `QOSA_QVSIM_ERR_INVAL_PARM`:参数非法 ```{note} **注意:** 1. 配置参数保存到NV中。 ``` --- #### **qosa_qvsim_get_ota_config** ##### 函数原型 ```c qosa_qvsim_err_e qosa_qvsim_get_ota_config(qosa_qvsim_ota_config_t *config); ``` ##### 功能描述 查询OTA服务器认证信息及访问地址。 ##### 参数说明 | **参数名** | **类型** | **是否必填** | **范围/单位** | **说明** | | --- | --- | --- | --- | --- | | config | `qosa_qvsim_ota_config_t` * | 是 | 参考 `qosa_qvsim_ota_config_t` | OTA服务器相关信息 | ##### 返回值说明 - `QOSA_QVSIM_ERR_OK`:查询成功 - `QOSA_QVSIM_ERR_INVAL_PARM`:参数非法 --- #### **qosa_qvsim_start_ota** ##### 函数原型 ```c qosa_qvsim_err_e qosa_qvsim_start_ota(void); ``` ##### 功能描述 启动OTA流程,进行远程Profile下载与激活。 ##### 参数说明 无 ##### 返回值说明 - `QOSA_QVSIM_ERR_OK`:接口调用成功 - `QOSA_QVSIM_ERR_INVAL_PARM`:参数非法 ```{note} **注意:** 1. OTA业务采用事件驱动方式返回执行结果。QVSIM会在OTA各关键阶段通过 `QOSA_QVSIM_EVENT_OTA_xxx` 事件向上层上报状态与结果; 2. 无论是否存在Profile任务或是否发生错误,最终均会上报 `QOSA_QVSIM_EVENT_OTA_FINISHED` 事件。 ``` ```{image} images/image_Jn6abdDwPo7oXRxHnu7cFek2n9d.webp :width: 923px :height: 609px :align: center ``` 具体事件说明如下: - **`QOSA_QVSIM_EVENT_OTA_ERROR`** OTA过程中发生任意错误时上报,用于指示OTA业务异常终止或执行失败。 - **`QOSA_QVSIM_EVENT_OTA_CONNECTED`** 成功连接远程管理平台后上报,表示OTA通信链路已建立。 - **`QOSA_QVSIM_EVENT_OTA_ADD_PROFILE`** 当远程管理平台下发新增Profile任务时上报, 事件中携带新增Profile对应的ICCID信息。 - **`QOSA_QVSIM_EVENT_OTA_DELETE_PROFILE`** 当远程管理平台下发删除Profile任务时上报, 事件中携带被删除Profile对应的ICCID信息。 - **`QOSA_QVSIM_EVENT_OTA_SWITCH_PROFILE`** 当远程管理平台下发Profile切换任务时上报, 事件中携带目标Profile对应的ICCID信息。 - **`QOSA_QVSIM_EVENT_OTA_NO_TASK`** 当成功连接远程管理平台但未获取到任何Profile相关任务时上报。 - **`QOSA_QVSIM_EVENT_OTA_FINISHED`** OTA业务结束时上报,用于标识OTA流程完成。 事件中返回最终执行结果,包括成功信息或错误原因。 --- ### IR管理接口 #### qosa_qvsim_switch_ir ##### 函数原型 ```c qosa_qvsim_err_e qosa_qvsim_switch_ir(char *ir); ``` ##### 功能描述 切换当前使用的vSIM标识。 ##### 参数说明 | **参数名** | **类型** | **是否必填** | **范围/单位** | **说明** | | --- | --- | --- | --- | --- | | ir | char * | 是 | 3字节 | IR编号,如"IR1" | ##### 返回值说明 - `QOSA_QVSIM_ERR_OK`:接口调用成功 - `QOSA_QVSIM_ERR_INVAL_PARM`:参数非法 ```{note} **注意:** 1. IR当前仅支持4组,如"IR1" "IR2" "IR3" "IR4"。 2. 在vSIM启动后才可以调用本API。 ``` --- #### qosa_qvsim_get_current_ir ##### 函数原型 ```c qosa_qvsim_err_e qosa_qvsim_get_current_ir(char *ir, qosa_uint8_t len); ``` ##### 功能描述 获取当前使用中的IR标识。 ##### 参数说明 | **参数名** | **类型** | **是否必填** | **范围/单位** | **说明** | | --- | --- | --- | --- | --- | | ir | char * | 是 | 3字节 | IR编号,如"IR1" | ##### 返回值说明 - `QOSA_QVSIM_ERR_OK`:接口调用成功 - `QOSA_QVSIM_ERR_INVAL_PARM`:参数非法 ```{note} **注意:** 1. IR当前仅支持4组, 如"IR1" "IR2" "IR3" "IR4"。 2. 在vSIM启动后才可以调用本API。 ``` --- ### 版本与设备信息接口 #### qosa_qvsim_get_version ##### 函数原型 ```c qosa_qvsim_err_e qosa_qvsim_get_version(char *version, qosa_uint8_t len); ``` ##### 功能描述 获取QVSIM主版本号。 ##### 参数说明 | **参数名** | **类型** | **是否必填** | **范围/单位** | **说明** | | --- | --- | --- | --- | --- | | version | char * | 是 | 13字节 | 返回主版本号信息 | | len | qosa_uint8_t | 是 | 13 | 主版本号信息buffer大小 | #### qosa_qvsim_get_sub_version ##### 函数原型 ```c qosa_qvsim_err_e qosa_qvsim_get_sub_version(char *sub_version, qosa_uint8_t len); ``` ##### 功能描述 获取QVSIM次版本号。 ##### 参数说明 | **参数名** | **类型** | **是否必填** | **范围/单位** | **说明** | | --- | --- | --- | --- | --- | | sub_version | char * | 是 | 25字节 | 返回次版本号信息 | | len | qosa_uint8_t | 是 | 25 | 次版本号信息buffer大小 | --- ### 回调管理 #### qosa_qvsim_register_callback ##### 函数原型 ```c qosa_qvsim_err_e qosa_qvsim_register_callback( qosa_qvsim_event_cb_t callback, void *user_data ); ``` ##### 功能描述 注册QVSIM事件回调,用于接收OTA、Profile切换、异常等事件。 ##### 参数说明 | **参数名** | **类型** | **是否必填** | **范围/单位** | **说明** | | --- | --- | --- | --- | --- | | callback | `qosa_qvsim_event_cb_t` | 是 | 参考 `qosa_qvsim_event_cb_t` | 回调函数 | | user_data | void * | 否 |   | 用户数据,可以为空 | ```{note} **注意:** 1. QVSIM模块仅支持注册 **一个回调函数实例**。 2. 当再次调用回调注册接口时,新注册的回调函数将 **覆盖并替换** 之前已注册的回调函数。 ``` --- ## 数据结构定义 本章节定义QVSIM功能模块相关的数据结构,用于描述Profile信息、OTA配置等内容。 所有数据结构均用于QVSIM API接口参数传递及事件回调。 ### qosa_qvsim_profile_t结构体定义 ```c typedef struct { int slot; /*!< Slot number */ char iccid[32]; /*!< ICCID string */ } qosa_qvsim_profile_t; ``` **Profile结构说明** QVSIM中的 **Profile** 用于描述一张虚拟SIM卡实例,是虚拟SIM业务的最小管理单元。 每个Profile都对应一个唯一的 **slot**,并绑定一组明确的身份信息,其中最核心的是 **ICCID**。 系统内部最多同时维护 **10个Profile**,按slot顺序进行管理: - **slot 0**:固定作为 **种子卡(Seed Profile)** 该Profile在出厂或首次初始化时预置,用于保障虚拟SIM业务的基础可用性,通常不可删除。 - **slot 1**:通常作为 **白卡(Blank Profile)** 该Profile作为后续OTA下载和配置的承载对象。 - **slot 2 ~ slot 9**:用于存放通过OTA动态下载的业务Profile。 每个Profile至少包含以下关键信息: - **slot id**:Profile所在的逻辑位置,用于区分和索引不同Profile - **ICCID**:Profile的唯一标识,用于OTA管理、选择和切换操作 在运行过程中,系统通过Profile的slot和ICCID完成Profile的 **查询、添加、删除和切换**,并确保同一时刻仅有一个Profile处于激活状态。 ```{image} images/image_SznNbR03EoPzHKxbxP4cvj9dnVd.webp :width: 602px :height: 511px :align: center ``` ### qosa_qvsim_ota_config_t结构体定义 ```cpp typedef struct { char username[QVSIM_OTA_HTTP_USERNAME_LEN_MAX]; /*!< Cloud server username */ char password[QVSIM_OTA_HTTP_PASSWORD_LEN_MAX]; /*!< Cloud server password */ char url[QVSIM_OTA_HTTP_URL_LEN_MAX]; /*!< Cloud server address */ qosa_uint16_t ota_time; /*!< Maximum waiting time for OTA completion, range 100-1200 seconds, default 120 seconds */ } qosa_qvsim_ota_config_t; ``` ## 枚举类型定义 ### qosa_qvsim_event_e ```sql typedef enum { QOSA_QVSIM_EVENT_INIT_DONE, /*!< VSIM init done event */ QOSA_QVSIM_EVENT_SELECT_PROFILE, /*!< VSIM select profile event, data: qosa_qvsim_result_select_profile_t */ QOSA_QVSIM_EVENT_START_PROFILE, /*!< VSIM start profile event, data: qosa_qvsim_result_start_profile_t */ QOSA_QVSIM_EVENT_SWITCH_IR, /*!< VSIM switch IR event, data: qosa_qvsim_result_switch_ir_t */ QOSA_QVSIM_EVENT_OTA_ADD_PROFILE, /*!< VSIM OTA add profile event, data: qosa_qvsim_ota_event_data_t */ QOSA_QVSIM_EVENT_OTA_DELETE_PROFILE, /*!< VSIM OTA delete profile event, data: qosa_qvsim_ota_event_data_t */ QOSA_QVSIM_EVENT_OTA_SWITCH_PROFILE, /*!< VSIM OTA switch profile event, data: qosa_qvsim_ota_event_data_t */ QOSA_QVSIM_EVENT_OTA_NO_TASK, /*!< VSIM OTA no task event, data: qosa_qvsim_ota_event_data_t */ QOSA_QVSIM_EVENT_OTA_CONNECTED, /*!< VSIM OTA connected event, data: qosa_qvsim_ota_event_data_t */ QOSA_QVSIM_EVENT_OTA_FINISHED, /*!< VSIM OTA finished event, data: qosa_qvsim_ota_event_data_t */ QOSA_QVSIM_EVENT_OTA_ERROR, /*!< VSIM OTA error event, data: qosa_qvsim_ota_event_data_t */ } qosa_qvsim_event_e; ``` # 应用示例 ## Demo流程 ```{image} images/image_DP1bbM6XOo8bPJxdV66cMW1Ind2.webp :width: 2105px :height: 4574px :align: center ``` ## 示例Demo #### 1. 准备工作 在使用QVSIM Demo验证相关功能前,请完成以下准备工作: - 准备一套支持QVSIM功能的测试模组; - 准备一张可正常进行数据业务的实体SIM卡; - 提前联系移远FAE申请QVSIM测试Profile; - 申请时需提供测试模组的 **IMEI信息**; - 向FAE获取 **QVSIM OTA测试账号信息**(包括服务器地址及认证参数)。 --- #### 2. OTA账号配置 在获取QVSIM OTA测试账号信息后,需要在Demo工程中配置OTA相关参数: - 修改 `business_trigger_ota()` 函数中的OTA账号及服务器相关信息; - 确保配置内容与FAE提供的测试账号信息保持一致。 --- #### 3. SDK配置说明 在SDK根目录下修改 `.config` 文件,启用QVSIM Demo功能: ```bash CONFIG_QCM_QVSIM_FUNC=y CONFIG_QAPP_QVSIM_DEMO_FUNC=y ``` 修改完成后,请重新编译SDK,以确保QVSIM Demo功能生效。 --- 源码请查看 https://github.com/UniRTOS/UniRTOS-Doc-Examples/blob/main/network/qvsim/qvsim_demo.c