好的,我们继续启程,向3GPP TS 29.515规范中技术密度最高、内容最丰富的第六章腹地进发。在上一篇文章中,我们已经为Ngmlc_Location API搭建了坚实的骨架,理解了它的URI结构、通信协议和核心交互机制。现在,是时候为这个骨架注入灵魂了——我们将逐一解剖API交互中的“血液”,即承载所有信息的数据模型(Data Models)。
由于6.1.5节内容浩瀚,我们将分篇章进行精讲。本文作为第六章的第二部分,将聚焦于API的“请求篇”,深入剖析当应用向GMLC发起定位或取消定位时,其请求体(Request Body)中到底包含了哪些信息,以及每个字段的精确含义和用法。
深度解析 3GPP TS 29.515:第六章 (Part 2) - 核心数据模型之“请求篇” (InputData & CancelLocData)
本文技术原理深度参考了3GPP TS 29.515 V18.8.0 (2025-03) Release 18规范中,关于**第六章“API定义”**的核心内容,重点剖析
6.1.5.2节中用于发起ProvideLocation和CancelLocation操作的核心数据类型:InputData和CancelLocData。本文旨在让开发者彻底掌握如何构建一个功能强大、参数精确的5G定位服务API请求。
故事新阶段:从“知道做什么”到“知道怎么说”
应急调度员小李的技术团队士气高昂。通过对前序章节的学习,他们已经知道了GMLC的API地址、通信协议(HTTP/2)、数据格式(JSON)以及安全机制(OAuth2.0)。他们甚至有了一本“API速查手册”(Table 6.1.3.1-1),清晰地指明了“追踪救护车”需要调用/provide-location端点。
现在,首席架构师向团队提出了一个终极问题:“我们要发送给/provide-location的那个HTTP POST请求,它的JSON消息体(Body)应该长什么样?要追踪‘生命卫士-01’,需要填supi还是gpsi?如何指定精度必须达到5米?又如何告诉GMLC把结果每10秒推送给我们一次?”
这些问题的答案,就隐藏在6.1.5节“Data Model”之中。这一节是整个规范中代码相关性最强、细节最繁复的部分,它定义了API交互中所有数据载体(Payload)的结构。今天,我们就将化身“JSON工匠”,精雕细琢ProvideLocation和CancelLocation这两个核心操作的请求体。
1. 6.1.5 Data Model (数据模型):API的“通用语”
在进入具体的数据类型之前,规范首先通过两个总览表,为我们描绘了Ngmlc_Location API数据世界的版图。
1.1 本规范定义的数据类型 (Ngmlc_Location specific Data Types)
Table 6.1.5.1-1列出了所有由TS 29.515规范原生定义的数据类型。这个表格就像是本规范数据模型的“目录”。
InputData:用于ProvideLocation操作的输入参数,是我们今天的重点。LocationData:包含定位结果的核心数据,我们将在下一篇文章“响应篇”中详述。CancelLocData:用于CancelLocation操作的输入参数,也是今天的重点。EventNotifyData:用于EventNotify通知的数据。- …等等。
1.2 重用的数据类型 (Ngmlc_Location re-used Data Types)
Table 6.1.5.1-2则列出了从其他3GPP规范(如TS 29.571通用数据类型、TS 29.572 LMF接口数据类型)中**“引用”或“重用”**的数据类型。这体现了3GPP规范设计的模块化和标准化思想,避免重复造轮子。
Gpsi,Supi,Uri(from TS 29.571)LocationQoS,CivicAddress,GeographicArea(from TS 29.572)
这意味着,当我们稍后在InputData中看到locationQoS这个字段时,要理解其详细结构,就需要去查阅TS 29.572规范。
2. 6.1.5.2.2 Type: InputData (输入数据) - 构建ProvideLocation的请求
InputData是ProvideLocation操作的请求体,是整个定位服务的“指令书”。它的设计目标是让消费者能够以最大的灵活性和精确性,向GMLC下达各种复杂的定位任务。
原文引用 (Table 6.1.5.2.2-1: Definition of type InputData):
(规范此处为一个巨大的表格,定义了InputData的所有属性)
我们将1:1重绘这个核心表格,并将其参数按逻辑功能进行分组,结合小李的应急场景进行“逐行注释”式深度解读。
表 6.1.5.2.2-1: InputData类型定义 (Definition of type InputData)
(注:为便于阅读,下表对原表进行了重新分组和排序,但保留了所有核心字段)
| 属性名 (Attribute name) | 数据类型 (Data type) | P | Card. | 描述与深度解读 |
|---|---|---|---|---|
| --- Group 1: 目标是谁? (Target Identification) --- | ||||
gpsi | Gpsi | O | 0..1 | 通用公共签约标识符。通常是用户的手机号码(MSISDN)。这是最常用的、对外部应用友好的标识符。场景:小李的系统使用“生命卫士-01”的gpsi来发起定位。 |
supi | Supi | O | 0..1 | 签约永久标识符。通常是IMSI。这是网络内部使用的、唯一的、更安全的标识符。注意:对于单个UE定位,gpsi、supi、appLayerId三者至少要提供一个。 |
appLayerId | ApplicationLayerId | O | 0..1 | 应用层ID。可以是任何应用自定义的标识,如车牌号、设备序列号。这需要GMLC或上游的NEF/AF有能力将其映射为网络可识别的supi或gpsi。 |
extGroupId | ExternalGroupId | O | 0..1 | 外部群组ID。用于标识一个预定义的UE群组,如“第一消防小队”。这个ID对外部应用有意义。 |
intGroupId | GroupId | O | 0..1 | 内部群组ID。网络核心网内部使用的群组ID。注意:群组ID和单个UE的ID是互斥的。请求中要么是定位群组,要么是定位单个UE。 |
| --- Group 2: 定位质量要求? (Quality of Service) --- | ||||
locationQos | LocationQoS | O | 0..1 | 定位服务质量。这是一个结构体,包含了对定位结果的详细要求。核心子字段包括:hAccuracy (水平精度,米)、vAccuracy (垂直精度,米)、responseTime (响应时间要求,如LOW_DELAY或HIGH_ACCURACY)。场景:小李需要区分救护车在立交桥上还是桥下,他会设置一个较高的vAccuracy,如3米。 |
| --- Group 3: 如何与何时定位? (Deferred Location Control) --- | ||||
ldrType | LdrType | C | 0..1 | 延迟定位请求类型。这是启动非立即定位的关键。C表示条件必选,即如果想发起延迟定位,此字段必须存在。枚举值包括:PERIODIC (周期性), ENTERING_INTO_AREA (进入区域), LEAVING_FROM_AREA (离开区域), MOTION (运动检测)等。 |
periodicEventInfo | PeriodicEventInfo | C | 0..1 | 周期性事件信息。当ldrType为PERIODIC时必须提供。包含reportingInterval (上报间隔,秒) 和 reportingAmount (总上报次数)。场景:小李设置reportingInterval: 10, reportingAmount: 360,实现未来一小时内每10秒上报一次。 |
areaEventInfo | AreaEventInfoExt | C | 0..1 | 区域事件信息。当ldrType为区域相关事件时必须提供。包含areaDefinition (定义区域的形状,如圆形、多边形) 和 occurrenceInfo (是一次性还是多次触发)。 |
| --- Group 4: 结果送到哪? (Notification Control) --- | ||||
eventNotificationUri | Uri | O | 0..1 | 事件通知URI。延迟定位的回调地址。当订阅的事件触发时,GMLC会向这个地址POST一个EventNotify通知。对于所有延迟定位请求,此字段事实상必须提供。 |
| --- Group 5: 谁在请求? (Client Identity) --- | ||||
externalClientType | ExternalClientType | M | 1 | 外部客户端类型。M表示强制必选。请求者必须声明自己的身份。枚举值如EMERGENCY_SERVICES, COMMERCIAL_LCS_CLIENT等。这直接影响GMLC的隐私和优先级策略。场景:小李的系统必须声明自己是EMERGENCY_SERVICES,才能获得最高定位优先级和隐私超越权。 |
externalClientIdentification | ExternalClientIdentification | O | 0..1 | 外部客户端标识。更具体的客户端身份信息。 |
afId | string | O | 0..1 | 应用功能(AF)ID。标识了哪个后端应用发起了请求。 |
| --- Group 6: 高级/特定场景参数 --- | ||||
reliableLocReq | boolean | C | 0..1 | 可靠定位请求。用于UAS(无人机系统)等高安全场景,值为true时表示需要一次经过完整性保护的定位。 |
requestedRangingSlResult | array(RangingSlResult) | O | 1..N | 请求的Sidelink定位结果类型。用于V2X/Sidelink场景,指定需要获取的是绝对位置、相对位置、距离还是方向。 |
relatedUes | array(RelatedUe) | O | 1..N | 相关的UEs。在Sidelink相对定位中,用于列出参与定位的其他UEs的信息。 |
mbsrPosInd | boolean | C | 0..1 | MBSR定位指示。true表示本次定位是为了确定移动基站中继(MBSR)的位置,以便定位其下的终端。 |
原文引用 (Note 3 in Table 6.1.5.2.2-1):
If retrieving the location for a target UE, the UE identification (attributes gpsi and/or supi or appLayerId) shall be included, if retrieving the UE locations for a target group, the group identification (attributes extGroupId and/or intGroupId), UE identification and group identification shall be included exclusively.
这个附注(NOTE)非常关键,它强调了目标标识的互斥性:一次ProvideLocation请求,要么是针对一个或多个具体UE的,要么是针对一个群组的,不能混用。
场景代入与代码构建: 小李的技术团队现在可以精确地构建出追踪“生命卫士-01”的JSON请求体了:
// POST https://.../ngmlc-loc/v1/provide-location
{
"gpsi": "msisdn-8613800100119", // 目标: "生命卫士-01"的手机号
"externalClientType": "EMERGENCY_SERVICES", // 身份: 紧急服务
"locationQos": {
"hAccuracy": 5, // 水平精度要求5米
"vAccuracy": 3, // 垂直精度要求3米,用于立交桥场景
"responseTime": "LOW_DELAY" // 响应时间要求低延迟
},
"ldrType": "PERIODIC", // 类型: 周期性定位
"periodicEventInfo": {
"reportingInterval": 10, // 间隔: 10秒
"reportingAmount": 360 // 次数: 360次 (1小时)
},
"eventNotificationUri": "https://emergency.city.gov/api/updates" // 结果送达地址
}
```这份`InputData`就像一份滴水不漏的“作战指令”,清晰、明确、毫无歧义。
## 3. 6.1.5.2.4 Type: CancelLocData (取消定位数据) - 构建`CancelLocation`的请求
当任务结束,需要终止持续定位时,就需要调用`CancelLocation`操作。其请求体`CancelLocData`的设计目标只有一个:**精确地告诉GMLC要取消的是哪一个定位任务**。
> **原文引用 (Table 6.1.5.2.4-1: Definition of type CancelLocData):**
>
> (规范此处为CancelLocData的属性定义表格)
我们同样1:1重绘并解读这个表格。
**表 6.1.5.2.4-1: `CancelLocData`类型定义 (Definition of type CancelLocData)**
| 属性名 (Attribute name) | 数据类型 (Data type) | P | Card. | 描述与深度解读 |
| :--- | :--- | :--- | :--- | :--- |
| `supi` | Supi | O | 0..1 | **终端标识 (SUPI)**。可选,用于校验。 |
| `gpsi` | Gpsi | O | 0..1 | **终端标识 (GPSI)**。可选,用于校验。 |
| `extGroupId` | ExternalGroupId | O | 0..1 | **群组标识 (外部)**。可选,用于校验。 |
| `intGroupId` | GroupId | O | 0..1 | **群组标识 (内部)**。可选,用于校验。 |
| **`hgmlcCallBackUri`** | Uri | M | 1 | **H-GMLC回调地址**。在漫游场景下,由H-GMLC发起的取消请求,需要提供此参数,用于V-GMLC向其返回取消结果的确认。对于非漫游场景或由V-GMLC发起的取消,此参数可能不是强制的,但规范定义为M,体现了其在漫游流程中的重要性。 |
| **`ldrReference`** | LdrReference | M | 1 | **延迟定位请求参考号**。**`M`表示强制必选,这是`CancelLocData`中最核心、最重要的字段**。它是在`ProvideLocation`发起订阅时,由GMLC返回的唯一任务ID。GMLC正是通过这个ID来精确识别并终止一个特定的延迟定位会话。 |
| `lmfIdentification` | LmfIdentification | O | 0..1 | **LMF标识**。可选,提供服务该UE的LMF的ID,可以帮助GMLC更快地将取消指令路由到正确的LMF。 |
| `amfId` | AmfId | O | 0..1 | **AMF标识**。可选,提供服务该UE的AMF的ID,同样有助于加速取消流程。 |
> **原文引用 (Note in Table 6.1.5.2.4-1):**
>
> If cancelling the location for a target UE, the UE identification ... shall be included, if cancelling the UE locations for a target group, the group identification ... shall be included, ... UE identification and group identification shall be included exclusively.
这个附注再次强调了目标标识的互斥性,与`InputData`中的逻辑一致。
**场景代入与代码构建**:
“生命卫士-01”的救援任务圆满结束。小李的系统需要终止对它的追踪。在发起追踪时,GMLC的`200 OK`响应中返回了一个`ldrReference`,例如`"LDR-REF-ABC-789"`。现在,系统将使用这个ID来取消任务。
```json
// POST https://.../ngmlc-loc/v1/cancel-location
{
"gpsi": "msisdn-8613800100119", // 可选,用于校验
"ldrReference": "LDR-REF-ABC-789" // 核心,强制必选的任务ID
}GMLC收到这个请求后,会在其会话列表中查找LDR-REF-ABC-789,找到后便终止该任务,并释放相关资源。
FAQ 环节
Q1:在InputData中,gpsi、supi和appLayerId都是可选的(O),但注释说至少要提供一个,这是为什么?
A1:这里的“可选”(Optional)是相对于数据模型结构而言的。在InputData这个JSON对象的定义中,这三个字段本身都不是强制必须存在的。但是,从业务逻辑上讲,一个定位请求必须要有定位目标,否则就是无效请求。因此,规范通过文字附注的方式,补充了业务层面的约束:“你必须至少告诉我一个你要定位的目标是谁”。这种做法在3GPP规范中很常见,即通过数据模型的灵活性和文字描述的业务约束相结合,来完整定义一个API的行为。
Q2:ldrReference(延迟定位请求参考号)是在哪个环节产生的,又是在哪里返回给我的应用?
A2:ldrReference是由GMLC在成功受理一个延迟定位请求(LDR)时生成的。具体流程是:1) 您的应用构造一个包含ldrType的InputData对象,调用ProvideLocation。2) GMLC收到请求,验证通过后,会为这个即将开始的长期定位任务创建一个唯一的ID,即ldrReference。3) GMLC会立即返回一个200 OK响应给您的应用,这个响应的消息体(LocationData或LocationDataExt)中就会包含这个ldrReference字段。您的应用必须立刻解析并存储这个ID,因为它是后续管理(取消)和关联(接收通知)这个任务的唯一凭证。
Q3:InputData中的ldrReference和CancelLocData中的ldrReference是同一个东西吗?为什么InputData中也有这个字段?
A3:它们指向的是同一种东西(任务ID),但使用场景不同。CancelLocData中的ldrReference是输入参数,用于告诉GMLC要取消哪个任务。而InputData中也定义了ldrReference字段,但它的作用不同。根据TS 23.273的流程,在某些复杂的延迟定位场景中(如由NEF发起的群组定位),NEF可能会自己先生成一个初始的ldrReference(作为事务ID)传递给GMLC,GMLC在处理后可能会使用这个ID或生成一个新的ID。但在绝大多数情况下,InputData中的ldrReference是由消费者(如NEF)在特定流程中提供的,而任务的最终权威ID,是以GMLC在ProvideLocation响应中返回的为准。对于大多数应用开发者,可以认为ldrReference是GMLC的输出,CancelLocData的输入。
Q4:locationQos参数看起来非常强大,如果我请求一个网络无法达到的QoS(比如在室内要求1米GPS精度),会发生什么?
A4:网络会尽力而为,并如实报告结果。GMLC在收到请求后,会尝试执行定位。如果最终的定位结果无法满足您请求的locationQos,它不会直接返回失败。它仍然会返回一个200 OK的成功响应,并在响应体LocationData中包含实际达到的定位结果(例如,实际精度是20米)。但是,LocationData中会有一个名为accuracyFulfilmentIndicator的字段,其值会被设为"NOT_FULFILLED"。这等于是在告诉您:“我努力了,但没达到你要求那么高的精度,这是我能给出的最好结果,你自己判断是否可用。” 这种设计使得应用可以根据实际情况进行降级处理,而不是因为QoS不达标就完全获取不到任何位置信息。
Q5:CancelLocData中的hgmlcCallBackUri字段为什么是强制的(M)?如果我不是漫游场景,也需要填吗?
A5:这是一个很好的问题,反映了规范定义的严谨性。将hgmlcCallBackUri定义为强制(Mandatory),主要是为了确保在最复杂的漫游场景下协议的完备性。在H-GMLC发起取消,通过V-GMLC执行的流程中,V-GMLC必须知道如何将取消操作的结果回调给H-GMLC。然而,在实际的非漫游场景下,或者由消费者直接向服务GMLC发起取消时,这个字段的业务逻辑意义不大。实际的API实现中,GMLC可能会根据请求的来源和上下文,对这个字段的强制性进行灵活处理。对于应用开发者来说,最佳实践是遵循规范,如果字段被定义为M,就应该提供。但在与运营商对接时,可以就具体场景下该字段如何填写进行沟通确认。