好的,我们继续深耕3GPP TS 29.515规范的第六章,这也是本章的最后一篇深度解析。我们已经构建了API的宏观架构,并精通了其核心的请求、响应及高级数据模型。现在,我们将深入到构成这些复杂模型的“原子”层面——那些看似简单,却为整个API提供了语法和词汇基础的简单类型与枚举。
深度解析 3GPP TS 29.515:第六章 (Part 5) - API的“通用语”:枚举与简单类型
本文技术原理深度参考了3GPP TS 29.515 V18.8.0 (2025-03) Release 18规范中,关于第六章“API定义”的核心内容,重点剖析
6.1.5.3节定义的简单数据类型和枚举(Simple data types and enumerations)。本文旨在揭示这些API的“词汇表”和“语法规则”,帮助开发者理解每一个API参数背后精确、无歧义的业务逻辑。
故事新视角:构建指挥官的用户界面
在应急指挥中心,小李的技术团队已经进入了最后的冲刺阶段。他们不仅理解了GMLC的业务流程,更掌握了如何构建API请求和解析响应。现在,他们的任务是为小李设计和开发一个功能强大的前端操作界面。
这个界面需要有下拉菜单,让小李可以选择“定位类型”;需要有输入框,让他能设定“告警时间”;还需要有清晰的提示,告诉他定位失败的“具体原因”。团队很快意识到,界面上的每一个选项、每一个输入约束,都精确地对应着TS 29.515规范中定义的枚举(Enumerations)和简单类型(Simple data types)。
这些看似基础的定义,正是连接人类指挥官(小李)的操作意图与机器网络(GMLC)的执行逻辑之间的桥梁。它们是API的“通用语”(Lingua Franca),确保了小李在界面上的每一次点击,都能被转化为网络可以理解并严格执行的、毫无歧义的指令。今天,我们就以构建这个“指挥官UI”的视角,来彻底解读这些基础却至关重要的API“词汇”。
1. 6.1.5.3 Simple data types and enumerations (简单数据类型和枚举)
本节是整个Ngmlc_Location API数据模型的基石。
原文引用 (Chapter 6.1.5.3.1 Introduction):
This clause defines simple data types and enumerations that can be referenced from data structures defined in the previous clauses.
这句话点明了本节的价值:它是前几节定义的复杂数据类型(如InputData, LocationData)的“原材料库”。那些复杂结构中的每一个字段,其最终的数据类型要么是另一个复杂结构,要么就是本节定义的简单类型或枚举。
1.1 为什么需要严格的类型和枚举?
在机器与机器的通信中,消除歧义是第一要务。
-
简单类型定义了数据的格式和边界。例如,将
TimeToAlert定义为一个integer,并规定其最小值为1,最大值为300,就防止了开发者传入"two seconds"这样的无效字符串或-10这样的无效值。 -
枚举则定义了数据的可选值集合。例如,将定位失败原因定义为一个枚举,只允许
"POSITIONING_DENIED"或"UNSUPPORTED_BY_UE"等几个特定的值,就避免了开发者自由发挥,传入"User said no"或"Device is old"这类网络无法理解的描述。
这套严格的“词汇表”是API能够自动化、规模化、可靠运行的根本保障。
2. 6.1.5.3.2 Simple data types (简单数据类型):API的“名词”和“量词”
简单数据类型定义了API中基础数据单元的格式。
原文引用 (Chapter 6.1.5.3.2 Simple data types):
The simple data types defined in table 6.1.5.3.2-1 shall be supported.
现在,我们1:1重绘这张表格,并为小李的UI构建提供“输入验证规则”。
表 6.1.5.3.2-1: 简单数据类型 (Simple data types)
| Type Name | Type Definition | Description & UI/业务逻辑映射 |
| :--- | :--- | :--- |
| Serviceldentity | string | 服务身份。一个字符串,用于标识一种LCS服务。在小李的系统中,他可能会创建一个名为“EmergencyVehicleTracking”的服务身份,并在后台配置中与特定的计费和优先级策略关联。 |
| ExternalClientIdentification| string | 外部客户端标识。标识LCS客户端的身份。UI上可能没有直接输入,但在系统后台配置文件中,小李的应急中心会被赋予一个唯一的ID,如“BEIJING-EOC-01”。 |
| CodeWord | string | 密码。一个字符串。UI上会有一个可选的密码输入框,用于需要额外验证的定位请求。 |
| E164CountryCodeOfGeographicArea| string | 地理区域的E.164国家码。1-3位数字字符串。在设置区域事件时,UI可能会有一个国家选择器,其背后就是这个类型。 |
| LcsServiceTypeId | integer | LCS服务类型ID。一个整数,用于标识UE上报的MO-LR服务类型。这是一个内部标识,通常不由UI直接配置。 |
| TimeToAlert | integer | 告警时间。整数,最小1,最大300。UI映射:在无人机完整性定位的设置界面,会有一个名为“告警窗口(秒)”的输入框,其输入范围被严格限制在之间。 |
| TargetIntegrityRisk | integer | 目标完整性风险。整数,最小10,最大90。这通常不是直接输入的数字,而是UI上几个选项(如“高”、“中”、“低”)的背后映射值。例如,“高可靠”映射为10。 |
| HorizontalProtectionLevel | integer | 水平保护级别。整数,最小0,最大50000。UI映射:完整性定位设置中,“水平安全距离(米)”输入框,范围。 |
| VerticalProtectionLevel | integer | 垂直保护级别。整数,最小0,最大50000。UI映射:完整性定位设置中,“垂直安全距离(米)”输入框,范围。 |
3. 枚举 (Enumerations):API的“选择题”
枚举是API设计中最能体现业务逻辑的部分。它们将复杂的操作意图,固化为几个有限的、标准化的选项。在小李的UI上,它们就是那些至关重要的下拉菜单和单选按钮。
3.1 6.1.5.3.3 PseudonymIndicator: 是否使用假名?
原文引用 (Table 6.1.5.3.3-1: Enumeration PseudonymIndicator):
(规范此处为PseudonymIndicator的枚举值表格)
表 6.1.5.3.3-1: PseudonymIndicator 枚举
| Enumeration value | Description | UI/业务逻辑映射 |
| :--- | :--- | :--- |
| "PSEUDONYM_REQUESTED" | A pseudonym is requested | 请求一个假名 |
| "PSEUDONYM_NOT_REQUESTED" | A pseudonym is not requested | 不请求假名 |
UI映射:在发起定位的高级选项中,会有一个复选框:[ ] 为本次定位请求临时假名以增强隐私。勾选后,API请求中该字段的值即为"PSEUDONYM_REQUESTED"。
3.2 6.1.5.3.4 LocationRequestType: 这是什么性质的定位?
原文引用 (Table 6.1.5.3.4-1: Enumeration LocationRequestType):
(规范此处为LocationRequestType的枚举值表格)
表 6.1.5.3.4-1: LocationRequestType 枚举
| Enumeration value | Description | UI/业务逻辑映射 |
| :--- | :--- | :--- |
| "NI-LR" | Network induced location request | 网络诱发的定位请求 |
| "MT-LR" | Mobile terminated location request | 移动终端终结的定位请求 |
| "MO-LR" | Mobile originated location request | 移动终端发起的定位请求 |
UI映射:这是区分ProvideLocation和LocationUpdate两大类操作的根本。
-
当小李在他的界面上点击“追踪”按钮时,系统在后台构建
InputData时,这个字段在逻辑上就是"MT-LR"(虽然InputData中没有这个字段,但GMLC知道调用/provide-location就是MT-LR)。 -
当系统收到来自隧道中救护车的
LocationUpdate通知时,其载荷LocUpdateNotification中的locationRequestType字段值必定是"MO-LR"。UI可以根据这个值,将地图上的光点标记为“来自终端自主上报”。 -
NI-LR则是一种特殊的网络内部定位,通常不直接由外部应用发起。
3.3 6.1.5.3.5 LocationTypeRequested: 你想要哪种时间点的“快照”?
原文引用 (Table 6.1.5.3.5-1: Enumeration LocationTypeRequested):
(规范此处为LocationTypeRequested的枚举值表格)
表 6.1.5.3.5-1: LocationTypeRequested 枚举
| Enumeration value | Description | UI/业务逻辑映射 |
| :--- | :--- | :--- |
| "CURRENT_LOCATION" | Requesting the current location of the target UE | 请求UE的当前位置 |
| "CURRENT_OR_LAST_KNOWN_LOCATION"| Requesting the current or last known location of the target UE | 请求UE的当前或最后已知位置 |
| "INITIAL_LOCATION" | Requesting the initial location of the target UE | 请求UE的初始位置 |
| "NOTIFICATION_VERIFICATION_ONLY"| Requesting notification verification only | 仅请求通知和验证 |
UI映射:在发起立即定位时,小李会看到一个下拉菜单“定位策略”:
-
选项1:“获取当前精确位置” → API值为
"CURRENT_LOCATION"。网络会启动一次全新的定位流程,耗时稍长但精度高。 -
选项2:“快速获取位置(可接受历史数据)” → API值为
"CURRENT_OR_LAST_KNOWN_LOCATION"。如果网络中正好有该UE最近的位置缓存(例如几秒前另一次定位留下的),就直接返回缓存,速度极快;如果没有,再启动一次新定位。这是速度与精度的平衡。 -
INITIAL_LOCATION用于获取UE开机或进入某区域后的第一个位置。 -
NOTIFICATION_VERIFICATION_ONLY用于隐私处理,如前文所述。
3.4 6.1.5.3.6 EventNotifyDataType: 收到的通知是什么“新闻”?
这是GMLC推送给应用的EventNotifyData中的核心字段,它告诉应用这次通知的“主题”是什么。
表 6.1.5.3.6-1: EventNotifyDataType 枚举
| Enumeration value | Description | UI/业务逻辑映射 |
| :--- | :--- | :--- |
| "UE_AVAILABLE" | UE available event | UE可用事件 |
| "PERIODIC" | Periodic event | 周期性事件 |
| "ENTERING_INTO_AREA" | Entering area event | 进入区域事件 |
| "LEAVING_FROM_AREA" | Leaving area event | 离开区域事件 |
| … | … | … |
| "LOCATION_CANCELLATION_EVENT"| Cancellation of location reporting event | 定位取消事件 |
UI映射:这是小李系统后台事件处理器(Event Handler)的核心switch-case逻辑:
function handleGmlcNotification(data) {
switch (data.eventNotifyDataType) {
case "PERIODIC":
updateMap(data.locationEstimate); // 更新地图
break;
case "ENTERING_INTO_AREA":
triggerAlarm("目标已进入危险区域!"); // 触发告警
break;
case "UE_AVAILABLE":
showToast("失联目标已重新上线!"); // 弹出提示
break;
case "LOCATION_CANCELLATION_EVENT":
archiveTask(data.ldrReference); // 归档任务
break;
// ... other cases
}
}
3.5 6.1.5.3.7 FailureCause: 为什么会失败?
当API调用返回错误时,ProblemDetails中会包含这个枚举,提供应用级的失败原因。
表 6.1.5.3.7-1: FailureCause 枚举
| Enumeration value | Description | UI/业务逻辑映射 |
| :--- | :--- | :--- |
| "POSITIONING_DENIED" | Positioning is denied | 定位被拒绝 |
| "UNSUPPORTED_BY_UE" | Positioning is not supported by UE| UE不支持定位 |
| "NOT_REGISTED_UE" | UE doesn’t register | UE未注册 |
| "UNSPECIFIED" | Unspecified | 未指定原因 |
UI映射:小李的系统在API调用失败时,会解析这个cause值,并向小李显示友好的错误信息:
-
收到
"POSITIONING_DENIED"→ 显示:“操作失败:用户隐私策略拒绝了本次定位请求。” -
收到
"UNSUPPORTED_BY_UE"→ 显示:“操作失败:目标设备不支持所需的定位功能。” -
收到
"NOT_REGISTED_UE"→ 显示:“操作失败:目标设备当前不在网或已关机。”
3.6 其他关键枚举
-
SuccessType(6.1.5.3.8): 用于群体定位响应,表明是"SUCCESS_COMPLETELY"(全部成功)还是"SUCCESS_PARTIALLY"(部分成功)。 -
ReportingInd(6.1.5.3.9): 用于区域事件订阅,"INSIDE_REPORTING"表示只在区域内触发事件,"OUTSIDE_REPORTING"表示即使在区域外也上报(例如,为了持续追踪一个以区域为中心移动的目标)。UI映射:区域事件设置里的一个复选框[ ]目标离开区域后继续追踪。 -
IntegrityComputingEntity(6.1.5.3.10): 在完整性定位的响应中,表明完整性结果是由"UE"、"LMF"还是"BOTH"计算得出的。
学完这些枚举,小李的技术团队发现,他们UI原型上的每一个交互组件,都在规范中找到了其“数据源”。他们设计的不再是一个孤立的界面,而是一个与5G核心网能力精确对话的“遥控器”。
FAQ 环节
Q1:为什么枚举值都是大写字母和下划线,看起来像是编程语言中的常量?
A1:这正是3GPP在Stage 3规范中推荐的命名约定(尽管规范中也提到,为了向后兼容,有些旧的枚举值可能不符合此约定)。将枚举值设计成类似常量的形式(UPPER_WITH_UNDERSCORE)有几个好处:1) 清晰可读:明确表示这是一个固定的、预定义的值,而不是一个变量。2) 避免冲突:与编程语言中常见的变量命名风格(如camelCase或snake_case)区分开,减少混淆。3) 利于解析:这种格式在各种编程语言中都很容易处理,便于代码生成器自动将其转换为语言原生的枚举类型。
Q2:LocationRequestType和LocationTypeRequested这两个枚举名字很像,它们之间到底有什么区别?
A2:这是一个非常容易混淆的点,但区别很关键。LocationRequestType(位置请求类型)定义了定位流程的发起方和方向,即这次交互是网络侧发起的(MT-LR)还是终端侧发起的(MO-LR)。它描述的是整个会话的性质。而LocationTypeRequested(被请求的位置类型)定义了在一次立即定位请求中,你希望获取哪个时间点的位置数据,例如是"CURRENT_LOCATION"(必须是此刻的)还是"CURRENT_OR_LAST_KNOWN_LOCATION"(可以是最近的缓存)。它描述的是数据的时效性要求。前者决定了走哪个大流程,后者决定了在某个流程中具体要拿什么样的数据。
Q3:我能在一个InputData请求中,组合使用多少个这里定义的枚举?
A3:您可以根据业务需求,组合使用多个。一个典型的复杂InputData请求,其背后可能由多个枚举共同定义:例如,您发起一次MT-LR(LocationRequestType的逻辑体现),请求UE的当前位置(LocationTypeRequested="CURRENT_LOCATION"),并要求使用假名(PseudonymIndicator="PSEUDONYM_REQUESTED"),同时订阅一个离开区域的事件(ldrType="LEAVING_FROM_AREA"),并设置该区域事件在区域外也上报(ReportingInd="OUTSIDE_REPORTING")。这些枚举就像乐高积木,共同搭建起一个精确的定位指令。
Q4:如果GMLC返回了一个我代码里没处理过的新的FailureCause枚举值,会发生什么?
A4:这是API版本演进中常见的问题。健壮的客户端代码应该有一个“默认”或“未知错误”的处理逻辑。您的switch-case语句在处理完所有已知的FailureCause后,应该有一个default分支。当收到一个新的、未知的枚举值时(例如,未来版本新增了一个"INSUFFICIENT_NETWORK_COVERAGE"),程序不会崩溃,而是会进入default分支,并可以向用户显示一个通用的错误消息,如“发生未知网络错误,请稍后重试”,同时将这个未知的枚举值记录到日志中,以便开发人员后续更新代码。
Q5:这些简单类型(如TimeToAlert)的取值范围(如1-300)是建议性的还是强制性的?
A5:在规范中,这些取值范围是强制性的。如果一个消费者发送的请求中,TimeToAlert的值为500,那么GMLC(或其前面的NEF/SEPP等网元)在验证请求时,会认为这是一个无效的请求,并会拒绝它,通常会返回一个400 Bad Request或403 Forbidden的HTTP错误,并在ProblemDetails中指明是哪个参数的值超出了范围。因此,客户端(如小李的UI和后端)必须进行严格的输入验证,确保发送给网络的所有参数都符合规范定义的格式和边界。