资讯详情

资讯详情

行业资讯

POCSAG解码实战:从FSK信号到寻呼消息的完整链路

简介本资源是一套面向无线电通信、嵌入式开发及复古寻呼技术爱好者POCSAG编码解码实践工具集聚焦低带宽数字寻呼协议的原理理解与工程实现。压缩包含29个文件以C源码3个.c、2个._c、汇编文件3个.s、2个.lst、Hex固件3个.hex、项目工程.prj、.mak、.cof、.dbg及头文件.h为主覆盖从UART驱动、POCSAG帧同步、BCH纠错到字符映射解码的完整链路适合具备单片机基础的中级开发者开展实操验证。资源仅60KB轻量紧凑便于快速导入Keil/IAR等传统嵌入式开发环境调试。目前已有196人学习下载可直接获取可编译的POS解码核心代码、配套硬件接口说明如iot2313v.h/iom128v.h、多版本汇编与链接脚本以及含调试标记的源码备份.bak和中间产物.o、.lis、.lk显著降低POCSAG协议逆向与复现门槛。1. POCSAG解码不是“古董考古”它仍在应急广播、工业遥测和低功耗信标中真实跑着你可能在Wireshark里见过一串以0x7E开头、夹杂0x00和0xFF的十六进制流或者在某次频谱扫描中捕获到一段25Hz/50Hz重复的FSK信号——别急着关掉这大概率是POCSAG协议正在工作。它不是博物馆展品而是至今仍在电力巡检终端、地下管网压力传感器、偏远气象站等场景中稳定传输关键状态数据的“哑巴信使”。POCSAG_pocsag_pocsag解码这个标题本质是在说如何把一段原始射频采样数据如poc.rar解压出的.wav或.sdr文件经载波恢复、符号同步、帧解析最终还原成可读的数字/字母寻呼消息。它不依赖互联网、不谈加密握手、不卷模型参数只讲信号链路上最朴素的“采样→判决→校验→输出”四步闭环。适合嵌入式开发者调试LoRaWAN回传链路、无线电爱好者复现老式寻呼台日志、或是工控安全人员做协议层流量审计。如果你手头有RTL-SDR、HackRF或USRP且能拿到一段中心频率在138MHz/152MHz/450MHz附近的FSK录音这篇就是为你写的实操笔记。2. 从原始音频到二进制比特流用GNU Radio完成POCSAG基带解调POCSAG信号本质是AFSKAudio Frequency Shift Keying用两个不同音频频率代表0和1典型为512Hz/400Hz或1200Hz/600Hz。解码第一步不是写Python而是确保输入信号已正确转为干净的基带比特流。GNU Radio是最可靠的选择——它把射频前端、滤波器设计、时钟恢复这些黑匣子封装成可视化模块避免手动调参翻车。2.1 搭建最小可行流图核心模块与参数含义新建GNU Radio Companion工程按顺序连接以下模块所有模块均来自gr-uhd或gr-digital库# 模块连接逻辑非代码仅说明 Audio Source → Low Pass Filter → Binary Slicer → Clock Recovery MM → Unpacked to Packed关键参数设置以138MHz频段、512/400Hz AFSK为例模块名参数名推荐值为什么这么设Low Pass FilterCutoff Freq1200 Hz滤除高频噪声保留AFSK双音带宽512400≈912Hz留余量Binary SlicerThreshold0.0直接过零判决若音频幅值偏小可设为0.10.3需先用QT GUI Time Sink观察波形Clock Recovery MMOmega2.0每个符号采样点数假设音频采样率48kHz符号率1200波特 → 48000/120040点/符号Omega2.0即每2个采样点输出1比特Clock Recovery MMGain Omega0.25控制相位误差收敛速度过大易震荡过小同步慢血泪经验从0.1起步试提示若输入是.wav文件用Audio Source模块若是.sdrIQ采样必须先用RTL-SDR Source或File SourceComplex to Mag转为幅度信号再进滤波器。跳过这步直接喂IQ数据会彻底失败。2.2 输出验证用QT GUI工具确认比特流质量在Unpacked to Packed后接QT GUI Time Sink和QT GUI Frequency SinkTime Sink应显示清晰的方波序列高电平1低电平0无毛刺或粘连Frequency Sink应呈现两个尖锐峰512Hz和400Hz峰间距≈112Hz若峰宽过宽说明滤波器带宽太大需收紧Low Pass Filter截止频率。若波形杂乱不要立刻改解码脚本——90%的问题出在基带环节。此时打开Audio Source的Repeat选项反复播放同一段音频用Time Sink逐帧拖动定位噪声爆发点如开关机瞬态、电源哼声在Low Pass Filter前加DC Blocker模块消除直流偏移。2.3 导出比特流供后续解码生成.bin文件在流图末尾添加File Sink模块设置File Path:pocsag_bits.binType:Byte注意不是Complex或FloatVLen:1运行流图10秒停止后检查pocsag_bits.bin大小若为0字节说明File Sink未触发写入常见于流图未真正运行或Audio Source无数据若大小异常如每秒增长48KB说明VLen设错应为1不是48000。3. 从比特流到可读消息用pocsag-decode工具解析帧结构POCSAG帧结构严格每帧含1个同步字0x7C7C7C7C、1个地址字含功能码寻呼地址、若干消息字含校验。手工解析极易出错推荐使用成熟工具链——pocsag-decodeC语言实现轻量无依赖或multimon-ng支持多协议但POCSAG解析更稳定。3.1 编译安装pocsag-decode绕过包管理器的直装法该工具未收录于主流发行版仓库需源码编译。从GitHub获取注意仅克隆可信镜像避免fork恶意修改# 下载并解压假设已从可信源获取pocsag-decode-master.zip unzip pocsag-decode-master.zip cd pocsag-decode-master # 修改Makefile将CCgcc改为CCclang若gcc报undefined reference to clock_gettime sed -i s/CC gcc/CC clang/g Makefile # 编译无需sudo make # 验证安装 ./pocsag-decode --help # 应输出Usage: ./pocsag-decode [options] input_file参数说明pocsag-decode默认输入为原始比特流即上节生成的pocsag_bits.bin而非音频文件。它内部已固化POCSAG标准25/50/1200波特率自适应、BCH(31,21)校验、地址/消息字段解析无需额外配置。3.2 执行解码并理解输出格式# 基础命令自动检测波特率 ./pocsag-decode pocsag_bits.bin # 强制指定波特率当自动检测失败时 ./pocsag-decode -b 1200 pocsag_bits.bin # 输出示例 # [2024-06-15 14:22:31] ADDR: 1234567 FUNCTION: 0 MESSAGE: TEMP:23.5C # [2024-06-15 14:22:32] ADDR: 1234567 FUNCTION: 0 MESSAGE: BATT:3.2V输出字段含义ADDR: 7位十进制寻呼地址POCSAG标准为21位二进制转为10^7范围整数FUNCTION: 功能码0普通消息1紧急2优先3扩展MESSAGE: ASCII文本若为数字消息会显示为NUMERIC: 1234567890。注意若输出全为[ERROR] Invalid sync word说明输入文件不是有效比特流——返回第2章检查File Sink输出是否为纯0/1字节可用xxd -c 16 pocsag_bits.bin | head查看前几行应只有00和01。3.3 解析失败时的三步定位法当pocsag-decode输出大量错误但偶有正确帧按此顺序排查查同步字完整性用hexdump -C pocsag_bits.bin | grep 7c 7c 7c 7c搜索同步字。若完全找不到说明基带解调未恢复出正确比特回到2.2节重调Clock Recovery MM参数查BCH校验通过率添加-v参数运行观察BCH errors corrected计数。若每帧都报告corrected 0但uncorrectable高说明比特误码率1需加强滤波或提升信噪比查地址字段有效性POCSAG地址字第21位恒为0第20位为奇偶校验位。用Python快速验证# 读取地址字假设地址字位于比特流偏移0x10处4字节 with open(pocsag_bits.bin, rb) as f: f.seek(0x10) addr_bytes f.read(4) addr_int int.from_bytes(addr_bytes, big) # 检查第21位最高位是否为0第20位是否匹配奇偶 if (addr_int 0x100000) ! 0: # 0x100000 2^20即第21位 print(地址字高位错误非标准POCSAG格式)4. 避坑指南POCSAG解码中5个让工程师凌晨三点删库的典型问题POCSAG协议看似简单但信号链路上每个环节都埋着隐性地雷。以下是我在模拟项目X中踩过的5个真实坑按发生频率排序附带现象、根因和可立即执行的解决方案。4.1 现象pocsag-decode输出全为[ERROR] Invalid sync word但Time Sink显示方波完美原因File Sink模块输出的是字节流每个字节8比特而pocsag-decode期望输入是单比特流每个字节代表1个0或1。GNU Radio默认Unpacked to Packed输出为8-bit packed导致一个字节存8个比特解码器误读为8个符号。解决在Unpacked to Packed模块后添加Packed to Unpacked模块设置Bits per Chunk 1再接File Sink。或更简单——改用File Sink的Type ByteVLen 1已在2.3节强调此处再次警告。4.2 现象解码出地址和功能码但MESSAGE为空或乱码原因POCSAG消息字段采用BCD编码非ASCII。例如数字123存储为0x12 0x30高位在前低位补0而工具默认按ASCII打印。解决用-n参数强制数字模式解析./pocsag-decode -n pocsag_bits.bin。若仍乱码检查消息长度字段——POCSAG规定消息字数必须为偶数若奇数会导致后续字节错位需在流图中加Keep M In N模块丢弃冗余比特。4.3 现象同一段音频用multimon-ng能解出消息pocsag-decode却失败原因multimon-ng内置AGC自动增益控制对幅值波动容忍度高pocsag-decode要求输入比特流电平稳定。当音频存在缓慢衰减如电池供电设备信号变弱Binary Slicer阈值失效。解决在Binary Slicer前插入Automatic Gain Control CC模块设置Reference为0.5Alpha为0.001慢速跟踪。或手动归一化音频用Audacity将.wav文件“标准化”至-1dB。4.4 现象解码结果中地址频繁跳变如1234567→1234568→1234566原因地址字校验位第20位计算错误。POCSAG规定地址字21位中第20位为奇偶校验位使整个21位中1的个数为偶数若基带误码恰好翻转该校验位解码器会接受错误地址。解决启用pocsag-decode的-c参数校验模式它会丢弃所有校验失败的地址字./pocsag-decode -c pocsag_bits.bin。代价是降低解码率但保证地址绝对正确。4.5 现象Clock Recovery MM模块输出波形正常但pocsag-decode报[ERROR] Invalid frame length原因POCSAG帧长固定为32字128比特但Clock Recovery MM的Omega参数若设为非整数如2.1会导致输出比特数非整数倍帧边界错乱。解决严格保证Omega为整数。计算公式Omega Audio_Sample_Rate / Baud_Rate。例如48kHz音频/1200波特 →Omega 40非2.02.0是旧版文档误传。重新计算并修正见2.1节表格。5. 进阶技巧用Python构建实时POCSAG监控看板把解码结果变成运维资产解码成功只是起点。真正的价值在于让POCSAG消息进入业务系统——比如当温度传感器地址1234567发来TEMP:28.5C时自动触发告警或把所有BATT消息聚合生成设备电量热力图。这里分享一个轻量级Python方案不依赖数据库50行代码搞定实时监控。5.1 构建消息管道用命名管道FIFO桥接GNU Radio与Python避免轮询文件带来的延迟用Linux FIFO实现零拷贝通信# 创建管道一次执行 mkfifo /tmp/pocsag_pipe # 启动GNU Radio流图输出重定向到管道 ./top_block.py --output-file /tmp/pocsag_pipe # Python脚本读取管道 python3 poc_monitor.pypoc_monitor.py核心逻辑import sys import time from datetime import datetime def parse_pocsag_line(line): 解析pocsag-decode单行输出返回字典 if ADDR: not in line: return None try: parts line.strip().split() addr parts[2].split(:)[1] func parts[3].split(:)[1] msg .join(parts[4:]).split(:, 1)[1].strip() return { timestamp: datetime.now().isoformat(), address: addr, function: func, message: msg } except Exception as e: return None # 主循环实时读取管道 with open(/tmp/pocsag_pipe, r) as pipe: buffer while True: chunk pipe.read(1024) if not chunk: time.sleep(0.1) continue buffer chunk # 按换行分割处理完整行 lines buffer.split(\n) buffer lines[-1] # 保留不完整行 for line in lines[:-1]: data parse_pocsag_line(line) if data: # 此处插入业务逻辑写入InfluxDB、发企业微信、存CSV print(f[{data[timestamp]}] {data[address]} → {data[message]}) # 示例温度超限告警 if TEMP: in data[message]: temp float(data[message].split(TEMP:)[1].split(C)[0]) if temp 30.0: print(f⚠️ 温度告警{data[address]} {temp}°C)5.2 协议层安全审计用统计特征识别异常POCSAG流量POCSAG本身无认证但正常设备有行为指纹。我们可基于解码结果做轻量审计特征正常值范围异常含义检测代码片段地址重复率95%同一设备周期发送地址伪造if address not in known_addrs: alert(new_address)消息间隔方差5秒²工业设备周期稳定时钟漂移或恶意重放np.var(intervals) 25功能码分布99%为01%为1紧急功能码滥用func_counts[1] / total 0.05我的习惯在poc_monitor.py中增加collections.Counter统计上述指标每5分钟打印一次摘要。曾靠消息间隔方差突增发现某传感器电池接触不良——电压不稳导致FSK调制失真解码器误判符号触发虚假告警。这种“用协议行为反推硬件状态”的思路比单纯看消息内容更有价值。希望帮到你。本文还有配套的精品资源点击获取

准备好开启您的数字化征程了吗?

专业团队为您量身定制,让您的企业网站脱颖而出

立即咨询