7.9 位置服务组件
7.9 位置服务组件
📚 本节导读
学习时长:约 20 分钟
难度级别:⭐⭐⭐☆☆
前置知识:第 7.2 节网络协议栈、AT 指令基础
🎯 学习目标
- 理解 OneOS 位置服务组件(onepos)的定位与架构
- 掌握平台适配层
onepos_adapter.h的作用 - 掌握网络定位与 GNSS 定位两类 API
- 掌握
oneposShell 命令与 Kconfig 配置
一、概述
OneOS 位置服务组件(components/position/,代号 onepos)提供定位能力的统一框架,支持两类定位方式:
- 网络定位(
ONEPOS_USING_NET_POS):通过基站/网络上报位置到定位服务,由onepos_start_server/onepos_stop_server等服务管理接口控制; - GNSS 定位(
ONEPOS_USING_GNSS_POS/GNSS_USING_RCVR):接入 GNSS 接收机(ublox/icofchina/unicorecomm/techtotop/MX 等),通过rcvr_object_t对象抽象读取 NMEA 0183 定位数据。
一句话核心:onepos_adapter.h 把 OneOS 平台能力(任务/信号量/互斥量/定时器/设备/内存)映射成 onepos 统一接口,上层用 onepos_start_server(网络)或 rcvr_object_get_default(GNSS)获取服务/接收机,再 onepos_get_latest_position/get_rcvr_data 取定位数据。
关键理解(线上组件):与 OTA/CMS 类似,位置服务组件的核心定位源码(
source/,含onepos_net_pos_if.h、rcvr_object.h、nmea_0183.h等)为线上管理组件,当前工程components/position/仅含port/(适配层)与sample/(Shell 命令)。使用前需通过 OneOS Studio /oos命令远程下载补齐核心源码,否则编译onepos_cmd.c时会因缺失核心头文件而报错。
目录结构
components/position/
├── port/
│ ├── onepos_adapter.h # 平台适配层(类型与宏映射)
│ └── weave.yaml
├── sample/
│ ├── onepos_cmd.c # onepos Shell 命令(需核心源码配合)
│ ├── Kconfig # ONEPOS_CMD 配置
│ └── weave.yaml
├── Kconfig # OS_USING_ONEPOS 总开关
└── weave.yaml二、平台适配层(onepos_adapter.h)
port/onepos_adapter.h 是位置服务组件的系统适配层——它把 OneOS 的平台能力映射为 onepos 统一抽象(类型别名 + 宏),使核心定位代码与具体 OS 解耦。完整源码(节选):
typedef os_err_t err_t;
typedef os_tick_t tick_t;
typedef os_bool_t bool_t;
typedef os_slist_node_t slist_node_t;
typedef os_task_id onepos_task_t;
typedef os_mutex_id onepos_mutex_t;
typedef os_timer_id onepos_timer_t;
typedef os_device_t onepos_device_t;
typedef os_semaphore_id onepos_sem_t;
#define ONEPOS_EOK OS_SUCCESS
#define ONEPOS_EIO OS_EIO
#define ONEPOS_ERROR OS_FAILURE
#define ONEPOS_EBUSY OS_BUSY
#define ONEPOS_EPERM OS_EPERM
#define ONEPOS_ENOMEM OS_NOMEM
#define onepos_task_create os_task_create
#define onepos_task_msleep os_task_msleep
#define onepos_sem_post os_semaphore_post
#define onepos_sem_wait os_semaphore_wait
#define onepos_mutex_create os_mutex_create
#define onepos_device_open os_device_open
#define onepos_device_control os_device_control
#define onepos_printf os_kprintf
#define onepos_malloc os_malloc
#define onepos_free os_free关键理解:此文件定义的是平台抽象(任务/信号量/互斥量/定时器/设备/内存/链表/打印),不是定位数据结构(onepos_pos_t 等在核心源码 source/ 中)。注释标明各能力依赖:gnss依赖: driver、网络定位依赖: cms、molink、cjson、agnss/rtk/rtd依赖: driver、cms、onepos_cmd: shell。
三、网络定位 API(ONEPOS_USING_NET_POS)
网络定位把位置上报到定位服务,核心接口在核心源码 onepos_net_pos_if.h 中(当前为线上组件,sample/onepos_cmd.c 中的调用方式可确认其形态):
3.1 服务管理
| 接口 | 说明 |
|---|---|
onepos_start_server() | 启动定位服务(状态为 ONEPOS_CLOSING 时调用) |
onepos_stop_server() | 停止定位服务(状态为 ONEPOS_RUNING 时调用) |
onepos_get_server_sta() | 获取服务状态(ONEPOS_CLOSING/ONEPOS_RUNING/ONEPOS_SIG_RUNING/ONEPOS_WILL_CLOSE) |
onepos_get_server_type() / onepos_set_server_type(type) | 获取/设置服务类型(circulation 循环 / single 单次) |
onepos_get_pos_interval() / onepos_set_pos_interval(sec) | 获取/设置定位上报间隔(秒,不小于 ONEPOS_MIN_INTERVAL) |
服务状态常量:
| 常量 | 含义 |
|---|---|
ONEPOS_CLOSING | 已关闭 |
ONEPOS_RUNING | 运行中 |
ONEPOS_SIG_RUNING | 单次服务运行中(将自动停止) |
ONEPOS_WILL_CLOSE | 即将关闭(等待中) |
3.2 位置数据获取
onepos_pos_t pos_info = {0};
memset(&pos_info, 0, sizeof(onepos_pos_t));
onepos_get_latest_position(&pos_info); /* 获取最近一次定位结果 */
onepos_info_print(&pos_info); /* 打印定位信息 */关键理解:onepos_get_latest_position(onepos_pos_t *pos) 把定位结果填到 onepos_pos_t;onepos_info_print 打印。onepos_pos_t 在核心源码 onepos_net_pos_if.h 定义(线上组件补齐后可见)。
四、GNSS 定位 API(ONEPOS_USING_GNSS_POS / GNSS_USING_RCVR)
GNSS 定位通过 rcvr_object_t(接收机对象)抽象不同 GNSS 模块,支持 NMEA 0183 协议。
4.1 接收机对象
| 接口 | 说明 |
|---|---|
rcvr_object_get_default() | 获取默认接收机对象(rcvr_object_t*) |
rcvr_object_get_by_name(name) | 按名称获取接收机对象 |
rcvr_object_deinit(rcvr) | 反初始化接收机 |
rcvr_object_destroy(rcvr) | 销毁接收机 |
支持的接收机创建函数(GNSS_USING_xxx 条件编译,核心源码提供):
| 宏 | 创建函数 |
|---|---|
GNSS_USING_ICOFCHINA | icofchina_rcvr_creat() |
GNSS_USING_UNICORECOMM | unicorecomm_rcvr_creat() |
GNSS_USING_TECHTOTOP | techtotop_rcvr_creat() |
GNSS_USING_UBLOX | ublox_rcvr_creat() |
GNSS_USING_UBLOX7 | ublox7_rcvr_creat() |
GNSS_USING_MX | mx_rcvr_creat() |
4.2 读取定位数据(NMEA 0183)
nmea_t nmea_data = {0};
memset(&nmea_data, 0, sizeof(nmea_t));
if (ONEPOS_EOK == get_rcvr_data(rcvr, (void *)&nmea_data, sizeof(nmea_t), RCVR_NMEA_0183_PROT))
{
/* RMC 帧字段 */
onepos_printf("date : 20%02d-%d-%d\r\n",
nmea_data.rmc_frame.date.year,
nmea_data.rmc_frame.date.month,
nmea_data.rmc_frame.date.day);
onepos_printf("latitude : %lld, %d; %f\r\n",
nmea_data.rmc_frame.latitude.value,
nmea_data.rmc_frame.latitude.dec_len,
rcvr_data_to_wgs84(nmea_data.rmc_frame.latitude));
}关键理解:
get_rcvr_data(rcvr, data, len, RCVR_NMEA_0183_PROT)读取一帧 GNSS 数据到nmea_t(内含rmc_frame,date/time/latitude/longitude/speed等);rcvr_data_to_wgs84(coord)把坐标原始值转 WGS84 经纬度;tras_loca_float(speed)把速度转浮点;- 还有
rcvr_reset(rcvr, RCVR_COLD_START)(复位)、rcvr_agnss(rcvr, lat, lon, alt)(A-GNSS 辅助定位)、RTK 相关(rov_sta_get_src_node/rov_sta_set_coord_sys)。
五、onepos Shell 命令
核心命令由 sample/onepos_cmd.c 定义,SH_CMD_EXPORT(onepos, onepos_cmd, ...) 注册:
5.1 网络定位命令(ONEPOS_USING_NET_POS)
| 命令 | 说明 |
|---|---|
onepos status | 查询服务状态(closing/runing/sig_sev_runing/will_close) |
onepos interval <sec> | 读取/设置定位上报间隔(秒) |
onepos sev_type <0/1> | 读取/设置服务类型(0=循环 1=单次) |
onepos start | 启动定位服务 |
onepos stop | 停止定位服务 |
onepos pos | 获取并打印最近定位结果 |
5.2 GNSS 命令(GNSS_USING_RCVR)
| 命令 | 说明 |
|---|---|
onepos gnss_test | 创建并注册所有已编译的 GNSS 接收机,打印默认接收机名 |
onepos ops_test <case> <rcvr name> | 接收机操作测试:0 读 NMEA 数据、1 复位(RCVR_SUPP_RESET)、2 A-GNSS(RCVR_SUPP_AGNSS)、3/4 RTK 坐标(RCVR_SUPP_RTK) |
onepos gnss_close | 关闭并销毁指定接收机 |
关键理解:
onepos_cmd.c中这些命令大量引用核心源码头文件(onepos_net_pos_if.h/rcvr_object.h/nmea_0183.h),核心源码缺失时这些命令无法编译——需先远程下载补齐。
六、Kconfig 配置
完整源码(components/position/Kconfig):
menu "Position"
config OS_USING_ONEPOS
bool "enable position support"
select OS_USING_HEAP
default n
if OS_USING_ONEPOS
source "$OS_ROOT/components/position/*/Kconfig"
endif
endmenu配置项:
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
OS_USING_ONEPOS | bool | n | 启用位置服务组件(自动 select OS_USING_HEAP) |
ONEPOS_CMD | bool | n | 启用 onepos Shell 命令(sample/Kconfig) |
ONEPOS_USING_NET_POS | bool | n | 启用网络定位(核心源码,需远程下载) |
ONEPOS_USING_GNSS_POS / GNSS_USING_RCVR | bool | n | 启用 GNSS 定位(核心源码,需远程下载) |
GNSS_USING_UBLOX/GNSS_USING_ICOFCHINA 等 | bool | n | 选择 GNSS 接收机型号 |
关键理解:总开关是
OS_USING_ONEPOS(不是OS_USING_POSITION);ONEPOS_USING_NET_POS/GNSS_USING_*等子开关在核心源码的*_if.h/rcvr_*的 Kconfig 中,需核心源码下载后通过source "$OS_ROOT/components/position/*/Kconfig"引入才可见。
📝 本节小结
核心要点回顾
- 定位:位置服务组件(onepos)提供网络定位 + GNSS 定位两类定位能力统一框架,位于
components/position/。 - 适配层:
onepos_adapter.h是平台抽象层(err_t/tick_t/onepos_task_t/onepos_sem_t等类型别名 + os_xxx 宏映射),不是定位数据结构。 - 网络定位:
onepos_start_server/stop_server/get_server_sta(ONEPOS_CLOSING/RUNING/SIG_RUNING/WILL_CLOSE)/set_pos_interval/get_latest_position/info_print。 - GNSS 定位:
rcvr_object_get_default/get_by_name/deinit/destroy,get_rcvr_data(NMEA 0183,nmea_t)、rcvr_reset/rcvr_agnss/rcvr_data_to_wgs84,支持 ublox/icofchina/unicorecomm/techtotop/MX 接收机。 - Shell 命令:
onepos status/interval/sev_type/start/stop/pos(网络定位)+onepos gnss_test/ops_test/gnss_close(GNSS)。 - Kconfig:
OS_USING_ONEPOS(select OS_USING_HEAP)→ONEPOS_CMD/ONEPOS_USING_NET_POS/ONEPOS_USING_GNSS_POS/GNSS_USING_xxx。 - 线上组件:核心定位源码(
source/)为线上管理组件,当前工程仅port/+sample/骨架,需远程下载补齐后才能编译使用。
关键易错点速查
| 易错点 | 正确做法 |
|---|---|
用 OS_USING_POSITION / POSITION_USING_GPS 配置 | 不存在 → 用 OS_USING_ONEPOS(总开关)+ ONEPOS_USING_NET_POS/ONEPOS_USING_GNSS_POS |
用 onepos_data_t/onepos_ops_t 结构体 | 不存在 → 位置数据用 onepos_pos_t(网络)/nmea_t(GNSS);适配层是平台类型映射 |
以为 onepos_adapter.h 含定位 API | 它只是平台抽象(任务/信号量/设备/内存映射)→ 定位 API 在核心源码 |
直接编译 onepos_cmd.c | 核心头文件缺失编译失败 → 先远程下载核心源码 |
用 mqtt_publish() 上报位置 | OneOS MQTT 无此 API → 用 MQTTClient/m_mqtt_publish(见 7.2.3) |
os_device_read(dev, buf, len, timeout) 4 参 | os_device_read 签名是 (dev, pos, buffer, size) 无 timeout → 用 os_device_read_nonblock/串口读 |
调用 onepos_start_server 不判状态 | 已运行时调用无效 → 先 onepos_get_server_sta() 判 ONEPOS_CLOSING |
| GNSS 命令不指定接收机 | ops_test 可用 rcvr_object_get_default → 指定 rcvr name 用 get_by_name |
| 混淆网络/ GNSS 两类 API | 网络定位用 onepos_*_server/onepos_pos_t;GNSS 用 rcvr_object_*/nmea_t → 按 ONEPOS_USING_NET_POS/GNSS_USING_RCVR 区分 |
下一步
- 本节已覆盖位置服务组件(onepos)的适配层、两类定位 API 与命令。需要实际使用定位功能时,先通过 OneOS Studio /
oos命令下载补齐核心源码;如需联网上报位置,可结合 7.6 OneNET 组件 或 7.2 网络协议栈 完成数据上传。