返回首页

反向工程 BCD4 队列显示协议

本文描述了专有电子队列显示协议的反向工程,该协议使用 BCD4 编码和校验和中的进位。提供了数据包结构、Python 组装代码以及通过 HTTP 和 COM 端口集成到 Web 系统的内容。适用于处理遗留设备。

队列显示反向中的 BCD4 和进位
Advertisement 728x90

逆向工程解析排队显示协议:BCD4编码与进位校验算法

一位工程师在没有文档的情况下,成功逆向解析了一套专有的排队显示协议。该协议采用BCD4编码,每个数据位占用一个完整字节,以增强在1200波特率长距离RS-232线路上的抗噪能力。数据包结构为33字节,包含起始标记、数字位、窗口号和带进位机制的校验和字段。

BCD4:确保可靠传输的编码方案

该协议采用硬件级抗噪方法:每个数字(0-15)的比特位被编码为一个字节。0x7F表示1(七个1形成清晰脉冲),0x00表示0。这样就将一个4位值扩展为4字节。

编码示例:

Google AdInline article slot

| 数字 | 比特位 | BCD4字节序列 |

|------|--------|--------------|

| 0 | 0000 | 00 00 00 00 |

Google AdInline article slot

| 1 | 0001 | 7F 00 00 00 |

| 2 | 0010 | 00 7F 00 00 |

| 5 | 0101 | 7F 00 7F 00 |

Google AdInline article slot

| 9 | 1001 | 7F 00 00 7F |

| 12 | 1100 | 00 00 7F 7F |

Python实现代码:

def _bcd4(value: int) -> bytes:
    return bytes([0x7F if value & (1 << i) else 0x00 for i in range(4)])

print(_bcd4(5).hex(' '))  # 7f 00 7f 00
print(_bcd4(9).hex(' '))  # 7f 00 00 7f

1200波特率在保证可靠性的同时牺牲了传输速率。

数字显示的数据包结构

33字节数据包用于在窗口显示数字:

  • 字节0:0x55 — 起始标记
  • 字节1-4:模式头
  • 字节5-8:BCD4(个位数字)
  • 字节9-12:BCD4(十位数字)
  • 字节13-16:BCD4(百位数字)
  • 字节17-20:BCD4(窗口个位数字)
  • 字节21-24:BCD4(窗口十位数字)
  • 字节25-28:BCD4(c1) — 校验和低位部分
  • 字节29-32:BCD4(c2) — 带进位的高位部分

示例:在19号窗口显示数字487:

55 00 7F 00 00          # 头部
7F 7F 7F 00             # BCD4(7)
00 00 00 7F             # BCD4(8)
00 00 7F 00             # BCD4(4)
7F 00 00 7F             # BCD4(9)
7F 00 00 00             # BCD4(1)
[校验和字段]

带进位机制的校验和计算

校验和字段c1和c2构成8位值,采用进位机制:

  • 计算原始c1值作为数据包字段的线性组合
  • 如果原始c1 ≥ 16:进位 = 1,c1 = 原始c1 - 16
  • 否则:进位 = 0,c1 = 原始c1
  • c2根据其他字段的进位计算

进位发生在80-90等数字,具体取决于窗口编号。AI(Claude)通过30个数据包样本验证了该模式:两个4位半字节采用类似算术运算的进位机制。

“所有窗口”模式(25字节)无进位,计算公式更简单。

窗口编程模式使用两个独立的进位链,包含乘法和常数:

  • 链A:从W_lo计算原始A,进位_A = 原始A >> 4,字段_A1 = 原始A & 0xF,字段_A2从W_hi和进位_A计算
  • 链B:类似处理另一个线性函数

数据包组装与发送

数据包组装函数:

def build_window_packet(window: int, number: int) -> bytes:
    d1 = number % 10
    d2 = (number // 10) % 10
    d3 = (number // 100) % 10
    w_lo = window % 10
    w_hi = window // 10

    c1, c2 = _checksum(d1, d2, d3, w_lo, w_hi)

    packet = bytearray(b'\x55\x00\x7F\x00\x00')
    packet += _bcd4(d1) + _bcd4(d2) + _bcd4(d3)
    packet += _bcd4(w_lo) + _bcd4(w_hi)
    packet += _bcd4(c1) + _bcd4(c2)

    assert len(packet) == 33
    return bytes(packet)

数据包通过COM端口发送。

集成到Web系统

Python服务器接收HTTP POST请求:

POST / {"window": 5, "ticket": "487"}

服务器解析JSON,构建数据包并写入端口。心跳机制维持连接:

  • 正常时60秒间隔
  • 错误时10秒重试
def _heartbeat_loop():
    while True:
        ok = _try_register(...)
        was = _server_state['connected']
        _server_state['connected'] = ok
        if not was and ok:
            print("[OK] 连接已恢复")
        elif was and not ok:
            print("[警告] 连接丢失")
        time.sleep(60 if ok else 10)

核心要点

  • BCD4编码将1比特扩展为1字节,在1200波特率下提供抗噪能力
  • 校验和采用c1/c2半字节间的进位机制
  • 结合精确假设和数据包样本,AI辅助逆向工程效果显著
  • 服务器实现使传统设备无缝集成到Web系统
  • 协议规范:33字节,起始标记0x55,数字+窗口+校验和

— Editorial Team

Advertisement 728x90

继续阅读