OmniRoam
OmniRoam 是 Omnitouch 为漫游运营商提供的全面批发收入管理解决方案。它处理漫游数据 CDR(通话详细记录)的完整生命周期,从摄取到计费,再到 TAP3 文件生成和报告。
目录
概述
OmniRoam 处理来自移动网络运营商的漫游 CDR,使用 OmniCharge 计费引擎进行计费,生成符合 GSMA 标准的 TAP3 文件,并提供全面的监控和报告能力。

CDR 导入和计费过程
TAP3 导出过程
操作指南
运行 TAP3 导出
# 为特定合作伙伴导出
python3 export_TAP3.py VZW_Live
# 交互模式(提示输入合作伙伴)
python3 export_TAP3.py
导出过程:
- 查询过去 30 天的 CDR(GSMA 要求)
- 过滤掉标记为已处理的 CDR
- 排除结束时间少于 1 小时的 CDR(防止不完整会话)
- 按漫游合作伙伴对 CDR 进行分组
- 为每个合作伙伴生成 TAP3 文件
- 在数据库中将 CDR 标记为已处理
- 增加序列计数器
- 将指标推送到 InfluxDB
监控与报告
OmniRoam 将实时指标推送到 InfluxDB 进行监控和分析。
收集的指标
原始 CDR 指标 在 CDR 导入和计费过程中推送:
- operator: 漫游合作伙伴标识符
- input_file: 源 CSV 文件名
- apn: 接入点名称(数据服务标识符)
- cellId: 基站标识符
- imsi: 订阅者身份
- tac: 跟踪区域代码
- sGWAddress: 服务网关 IP 地址
- pGWAddress: PDN 网关 IP 地址
- chargeableUnits: 使用的总字节数
- chargedUnits: 计算的费用
TAP 导出指标 在 TAP3 文件生成过程中推送:
- operator: 漫游合作伙伴标识符
- filename: 生成的 TAP3 文件名
- totalcharge: TAP3 文件中的总费用
- totalconsumed: TAP3 文件中的总字节数
- cdr_count: TAP3 文件中的 CDR 数量
仪表板查询
用于监控的示例 InfluxDB 查询:
按运营商的收入
SELECT sum("totalcharge")
FROM "tap_cdr"
WHERE time > now() - 30d
GROUP BY "operator"
按 TAC 的数据使用
SELECT sum("chargeableUnits")
FROM "raw_cdr"
WHERE time > now() - 7d
GROUP BY "tac"
按小时的 CDR 量
SELECT count("chargeableUnits")
FROM "raw_cdr"
WHERE time > now() - 24h
GROUP BY time(1h)
按 APN 的收入
SELECT sum("chargedUnits")
FROM "raw_cdr"
WHERE time > now() - 7d
GROUP BY "apn"
Grafana 集成
使用这些指标创建 Grafana 仪表板,以实现:
- 实时收入监控
- 流量模式分析
- 合作伙伴绩效跟踪
- 网络资源利用
- 异常检测
- 账单对账
故障排除

CDR 导入问题
检查日志 /tmp/import_CDR_Logger_Marben_*.log
常见问题:
- 无效的 IMSI 格式
- 缺少必填字段
- 时区转换错误
- 重复的计费 ID
TAP3 导出问题
检查日志 /tmp/tap3_export_*.log
常见问题:
- 最近 30 天内没有 CDR
- 缺少 TAC 配置
- 无效的序列号
- 数据库连接错误
OmniCharge 计费错误
查看 OmniCharge 日志以查找:
- 缺少费率计划
- 找不到账户
- 无效的使用值
- 货币转换错误
InfluxDB 连接问题
验证:
- InfluxDB URL 是否可达
- 有效的身份验证令牌
- 桶是否存在
- 网络连接
支持与维护
日志位置
- CDR 导入:
/tmp/import_CDR_Logger_Marben_*.log - TAP 导出:
/tmp/tap3_export_*.log
关键配置文件
- config.yaml - 主要配置(合作伙伴费率、网络设置、InfluxDB 连接)
- counters.yaml - TAP3 文件序列计数器
定期维护任务
- 监控序列计数器 - 确保它们不超过 99999
- 归档旧 TAP 文件 - 移动超过保留期的文件
- 监控 InfluxDB 磁盘使用 - 配置保留策略
- 审查费率配置 - 当合作伙伴费率变化时更新
- 备份配置文件 - config.yaml 和 counters.yaml
- 监控 CDR 积压 - 确保及时处理
系统架构
高层架构
CDR 导入过程
OmniRoam 使用两阶段导入过程,缓存作为临时聚合层,将部分 CDR 记录组装为完整的可计费 CDR。
理解部分 CDR
移动网络元素(S-GW/P-GW)不会为数据会话生成单个 CDR。相反,它们在会话生命周期内生成 多个部分 CDR 记录:
- 开始记录: 当数据会话开始时生成
- 更新记录: 在会话期间定期生成(例如,每 15 分钟或每 100 MB 数据使用)
- 停止记录: 当会话结束时生成
每个部分记录包含增量使用数据。为了准确计费,OmniRoam 必须��
- 识别 哪些部分记录属于同一数据会话
- 聚合 所有部分记录的使用数据
- 计算 总会话持续时间
- 组装 一个完整的 CDR,代表整个会话
为什么使用缓存进行 CDR 聚合?
缓存作为高性能的临时存储区域,部分 CDR 在会话完成之前在此处积累。缓存提供:
- 快速键值查找 - 立即找到会话的现有部分 CDR
- 内存存储 - 实时聚合的高速读写操作
- 原子操作 - 安全的并发更新来自多个导入过程
- 持久性 - CDR 在聚合窗口期间在系统重启时存活
两阶段导入架构
阶段 1: CSV 解析和部分 CDR 聚合
第一阶段持续读取来自 S-GW 网络元素的 CSV 文件,并在缓存中聚合部分 CDR。
如何识别和匹配部分 CDR
OmniRoam 必须确定哪些部分记录属于同一数据会话。每个会话由一个复合 会话 ID 唯一标识,由以下组成:
- 计费 ID: 网络元素提供的唯一会话标识符
- IMSI: 订阅者身份(手机号码标识符)
- 日期: 服务网络时区中的会话日期
- P-GW IP 地址: 处理会话的网关
- TAC: 跟踪区域代码(基站位置)
- QCI: 服务质量类
这种组合确保来自同一数据会话��所有部分记录被分组在一起,即使多个文件的到达顺序不同。
如何聚合部分 CDR
当 CSV 解析器处理每个部分 CDR 时:
- 从 CDR 字段生成会话 ID
- 检查缓存 以查看此会话是否已存在
- 如果会话存在于缓存中:
- 检索累计的 CDR 数据
- 验证此文件是否未被处理过(防止重复)
- 添加新的使用数据:传入字节 + 传出字节
- 使用最早和最新的时间戳更新会话持续时间
- 存储有关此部分记录的元数据以供审计
- 将更新的 CDR 保存回缓存
- 如果是新会话:
- 在缓存中创建新的 CDR 条目
- 初始化使用计数器和会话元数据
- 记录第一个部分记录的时间戳
审计跟踪和元数据
每个对 CDR 贡献的部分记录都通过全面的元数据进行跟踪:
- 源文件名: 哪个 CSV 文件包含此部分记录
- 时间戳: 网络元素生成此记录的时间
- 处理时间: OmniRoam 接收和处理它的时间
- 使用贡献: 此部分添加了多少数据(传入/传出字节)
- 事件类型: 这是开始、更新还是停止记录
- 服务网络时区: 以便准确的时间戳转换
为什么元数据对会计至关重要:
此审计跟踪允许 OmniRoam 追踪单个费���在每个处理阶段的端到端流动,这对于:
- 争议解决: 当合作伙伴质疑费用时,运营商可以准确显示哪些源文件对此作出了贡献
- 收入对账: 验证所有可计费的使用是否被捕获,并且没有遗漏或重复
- 合规性: 演示对账单记录的适当处理,以便审计
- 调试: 通过追踪完整数据流快速识别 CDR 聚合过程中的问题
- 财务准确性: 确保每一美元收费都可以追溯到特定的网络事件
会话持续时间计算
总会话持续时间通过查找以下内容计算:
- 所有部分记录中的最早时间戳(会话开始)
- 所有部分记录中的最新时间戳(会话结束)
- 持续时间 = 最新 - 最早
对于仅存在更新记录的会话(缺少开始/停止),持续时间默认为 24 小时。
阶段 2: CDR 组装和计费
第二阶段定期扫描缓存以查找完成的会话,组装最终 CDR,并提交给 OmniCharge 进行计费。
如何从缓存中选择完整 CDR
CDR 组装过程持续运行,检查缓存中存储的所有会话:
- 扫描缓存 以查找所有累计的 CDR 会话
- 按批处理 每次处理 1,000 个会话
- 对于每个会话:
- 从会话 ID 中提取会话日期
- 如果太旧则跳过(> 30 天):从缓存中删除(防止陈旧数据积累)
- 如果太新则跳过(< 24 小时):留在缓存中以便更多部分记录到达
- 加载完整的 CDR,包含所有累计的数据
24 小时等待期
为什么 OmniRoam 在计费 CDR 之前等待 24 小时?
- 部分记录的到达顺序不一致:网络拥堵可能会延迟 CSV 文件的交付数小时
- 会话跨越午夜:在 11:50 PM 开始的会话会在两个不同的日期生成文件。相同的计费 ID 可以跨越多天,部分记录的日期不同
- 更新记录被延迟:定期更新记录可能在会话结束后很久才到达
- 异步文件生成:不同的网络元素在不同的时间表上导出文件
- 长时间运行的会话:数据会话可以持续数小时或数天,更新记录可能会在整个过程中不断到达
通过等待 24 小时,OmniRoam 确保所有部分记录都已到达,并且 CDR 在计费前确实完整。
CDR 验证和丰富化
在计费之前,每个组装的 CDR 都会经过验证和丰富化:
-
验证完整性:
- 检查是否存在开始/停止记录
- 如果仅存在更新记录,则将持续时间设置为 24 小时(默认)
-
丢弃无效 CDR:
- 删除零使用会话(没有可计费活动)
-
计算最终使用:
- 汇总所有传入和传出字节
- 应用合作伙伴特定的四舍五入规则(例如,四舍五入到最近的 1 KB)
-
丰富位置数据:
- 将 TAC(跟踪区域代码)映射到服务网络位置
- 添加时区信息以确保时间戳准确
- 添加地理位置描述
-
提交给 OmniCharge:
- 将完整、丰富的 CDR 提交进行计费
- 接收计算的费用
-
存储和清理:
- 将计费 CDR 保存到数据库
- 将指标推送到 InfluxDB 进行报告
- 从缓存中删除已处理的 CDR
CDR 数据结构
每个聚合的 CDR 包含:
- 订阅者信息: IMSI, MSISDN, IMEI
- 网络信息: 服务网关 (S-GW), PDN 网关 (P-GW), 基站 ID, TAC (跟踪区域代码)
- 会话详情: 开始/结束时间戳, 持续时间, APN (接入点名称)
- 使用数据: 传入/传出数据量, 总可计费单位
- 位置信息: 服务 BID (网络 ID), 地理位置
- QoS 信息: QCI (服务质量类标识符)
数据处理规则
使用四舍五入
CDR 根据 config.yaml 中的合作伙伴特定配置进行四舍五入:
partners:
Example_Live:
round_up_to: 1024 # 四舍五入使用到最近的 1KB
系统:
- 计算总使用量:
dataVolumeIncoming + dataVolumeOutgoing - 四舍五入到配置的单位(例如,1024 字节)
- 保留原始值以供审计
基于 TAC 的本地化
系统根据 TAC(跟踪区域代码)确定服务网络位置:
config:
tac_config:
Global:
tac_list: ['1101', '10000', '10100']
servingBid: 72473
servingLocationDescription: 'Smallville USA'
timezone: 'America/Smallville'
这使得:
- 时间戳的正确时区转换
- 地理位置的分配
- 服务网络的识别
OmniCharge 计费引擎
OmniRoam 将 CDR 发送到 OmniCharge,这是一个强大的计费引擎,根据可配置的费率计划计算费用。

计费过程
费率配置
费率在配置文件中按漫游合作伙伴配置:
partners:
Example_Live:
imsi_prefixes:
- 99901
rates:
unit_price: 0.000476800 # 每单位的价格
unit_bytes: 1024 # 每单位的字节数
batch_info:
sender: AUSIE
recipient: AAA00
accountingInfo:
localCurrency: 'USD'
tapCurrency: 'USD'
roundingAction: 'Simple'
tapDecimalPlaces: 5
IMSI 前缀匹配
OmniRoam 使用 IMSI 前缀匹配的最长匹配优先逻辑 将 CDR 匹配到漫游合作伙伴。这允许运营商为测试 SIM 创建特定配置,同时为生产流量保持一般配置。
前缀匹配的工作原理
在计费 CDR 时,OmniRoam:
- 从 CDR 中提取 IMSI(例如,
310410123456789) - 按顺序评估所有合作伙伴配置
- 找到最长的匹配前缀
- 应用该合作伙伴的费率和配置
示例:测试 SIM 配置
此功能对于 TADIG/IREG 测试特别有用,其中测试 SIM 需要不同的处理:
partners:
Demo_Test:
imsi_prefixes:
- 0010112345123 # 测试 SIM 范围(9 位前缀)
rates:
unit_price: 0.0 # 测试流量不收费
batch_info:
sender: AUSIE
recipient: AAA00TEST
Demo_Production:
imsi_prefixes:
- 001011 # 生产范围(6 位前缀)
rates:
unit_price: 0.000476800
batch_info:
sender: AUSIE
recipient: AAA00
匹配行为:
- IMSI
00101123451234→ 匹配Demo_Test(9 位前缀更长) - IMSI
00101023456789��� 匹配Demo_Production(6 位前缀)
这确保测试流量进入测试 TAP 文件,使用测试 TADIG 代码,而生产流量正常计费,使用生产 TADIG 代码。
计费计算
对于每个 CDR:
- 匹配合作伙伴: 通过 IMSI 前缀识别漫游合作伙伴
- 计算单位:
totalBytes / unit_bytes - 应用费率:
units × unit_price = charge - 应用四舍五入: 根据
roundingAction(向上/向下/简单)进行四舍五入 - 转换为 TAP 单位: 乘以 1000 以符合 TAP3 格式
示例:
使用量: 52,428,800 字节 (50 MB)
单位大小: 1024 字节
单位: 51,200
费率: $0.000476800 每 1KB
费用: 51,200 × $0.000476800 = $24.41
TAP 单位: 24,410 (24.41 × 1000)
基于 QCI 的呼叫类型分配
服务质量类 (QCI) 被映射到 TAP3 呼叫类型级别:
call_type_level:
qci_1: 20 # 对话(语音)
qci_2: 22 # 对话(视频)
qci_3: 23 # 实时游戏
qci_4: 24 # 缓冲流
qci_5: 20 # IMS 信令
qci_6: 26 # 互动(浏览)
qci_7: 27 # 互动(游戏)
qci_8: 28 # 背景
qci_9: 29 # 背景(低优先级)
default: 20
TAP3 文件生成
在 CDR 被 OmniCharge 计费后,OmniRoam 生成符合 GSMA 标准的 TAP3 文件以进行批发计费。
TAP3 导出流程
TAP3 文件结构
文件命名约定
TAP3 文件遵循 GSMA 命名标准:
<FileType><Sender><Recipient><SequenceNumber>
示例:
CDAUSIEAAA0000001 - 从 AUSIE 到 AAA00 的商业数据文件,序列 1
TDAUSIEAAA0000001 - 从 AUSIE 到 AAA00 的测试数据文件,序列 1
其中:
- FileType:
CD(商业)或TD(测试) - Sender: 5 字符 TADIG 代码
- Recipient: 5 字符 TADIG 代码
- SequenceNumber: 5 位序列(来自 counters.yaml)
配置指南
合作伙伴配置
在 config.yaml 中添加漫游合作伙伴:
partners:
ONS_Live:
imsi_prefixes: # 此合作伙伴的 IMSI 前缀列表
- 505057
accessPointNameOI: mnc057.mcc505.gprs
rates:
unit_price: 0.000476800 # 每单位的价格(美元)
unit_bytes: 1024 # 每单位的字节数
batch_info:
sender: AUSIE # 您的 TADIG 代码
recipient: AAA00 # 合作伙伴 TADIG 代码
specificationVersionNumber: 3
releaseVersionNumber: 12
accountingInfo:
localCurrency: 'USD'
tapCurrency: 'USD'
roundingAction: 'Simple' # 向上/向下/简单
tapDecimalPlaces: 5
round_up_to: 1024 # 四舍五入使用到最近的 N 字节
call_type_level: # QCI 到呼叫类型级别的映射
qci_1: 20
qci_2: 22
default: 20
序列计数器配置
在 counters.yaml 中初始化序列计数器:
AAA00:
CD: 1 # 商业数据序列
TD: 1 # 测试数据序列
AAA01:
CD: 1
TD: 1
序列在每次生成 TAP 文件时自动递增。
网络配置
配置 TAC 到位置的映射:
config:
tac_config:
LocationName:
tac_list: ['1101', '10000']
servingBid: 72473
servingLocationDescription: '网络位置'
timezone: 'America/New_York'
InfluxDB 配置
在 config.yaml 中配置 InfluxDB 连接:
config:
influx_db:
influxDbUrl: 'http://10.3.0.135:8086'
influxDbOrg: 'omnitouch'
influxDbBucket: 'Omnicharge_TAP3'
influxDbToken: 'your-token-here'
输出路径
配置文件输出位置:
config:
tap_output_path: '/etc/pytap3/OutputFiles'
tap_human_readable_output_path: '/etc/pytap3/OutputFiles_Human'
tap_in_path: '/home/user/TAP_In/'
架构决策
为什么选择 OmniCharge?
OmniCharge 提供:
- 强大的计费引擎,具有灵活的费率计划
- 实时计费能力
- CDR 去重
- 全面的审计跟踪
- 基于 API 的集成
为什么选择 InfluxDB?
优势:
- 针对 CDR 指标优化的时间序列
- 高写入吞吐量
- 高效的存储与压缩
- 内置降采样
- 原生 Grafana 集成
工作流程摘要
OmniRoam - Omnitouch 提供的专业漫游收入管理。