Reverzní inženýrství protokolu pro zobrazovač elektronické fronty: BCD4 kódování a přenosová aritmetika
Inženýr rozebral proprietární protokol zobrazovače elektronické fronty bez dokumentace. Protokol používá BCD4 kódování, kde každý bit dat zabírá celý bajt pro odolnost proti rušení na dlouhých linkách RS-232 při 1200 bodech. Struktura paketu je 33 bajtů s markerem, číslicemi čísla, číslem okna a kontrolními poli s přenosem.
BCD4: kódování pro spolehlivý přenos
Protokol využívá hardwarovou metodu ochrany proti rušení: každý bit čísla (0–15) je zakódován bajtem. 0x7F označuje 1 (sedm jedniček pro jasný impuls), 0x00 — 0. Tím se 4bitová hodnota roztaží na 4 bajty.
Příklady kódování:
| Číslo | Bity | BCD4-bajty |
|-------|--------|------------------|
| 0 | 0000 | 00 00 00 00 |
| 1 | 0001 | 7F 00 00 00 |
| 2 | 0010 | 00 7F 00 00 |
| 5 | 0101 | 7F 00 7F 00 |
| 9 | 1001 | 7F 00 00 7F |
| 12 | 1100 | 00 00 7F 7F |
Implementace v Pythonu:
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
Rychlost 1200 bodů zajišťuje spolehlivost na úkor propustnosti.
Struktura paketu pro zobrazení čísla
Paket o délce 33 bajtů pro zobrazení čísla na okně:
- Bajt 0:
0x55— startovní marker. - Bajty 1–4: hlavička režimu.
- Bajty 5–8: BCD4(jednotky čísla).
- Bajty 9–12: BCD4(desítky čísla).
- Bajty 13–16: BCD4(stovky čísla).
- Bajty 17–20: BCD4(jednotky okna).
- Bajty 21–24: BCD4(desítky okna).
- Bajty 25–28: BCD4(c1) — nižší část kontrolního součtu.
- Bajty 29–32: BCD4(c2) — vyšší část s přihlédnutím k přenosu.
Příklad pro číslo 487 na okně 19:
55 00 7F 00 00 # hlavička
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)
[kontrolní pole]
Výpočet kontrolního součtu s přenosem
Kontrolní pole c1 a c2 tvoří 8bitovou hodnotu s přenosovou mechanikou:
- Vypočte se raw_c1 jako lineární kombinace polí paketu.
- Pokud raw_c1 >= 16: přenos = 1, c1 = raw_c1 - 16.
- Jinak: přenos = 0, c1 = raw_c1.
- c2 se vypočte s účastí přenosu z jiných polí.
Přenos se projevuje na číslech jako 80–90 v závislosti na okně. AI (Claude) odhalil zákonitost na 30 příkladech paketů po upřesnění hypotézy: dva 4bitové nibbly s přenosem jako v aritmetice.
Pro režim "všechna okna" (25 bajtů) přenos chybí, vzorec je jednodušší.
Režim programování okna využívá dvě nezávislé přenosové řetězce s násobením a konstantami:
- Řetězec A: raw_A od W_lo, přenos_A = raw_A >> 4, pole_A1 = raw_A & 0xF, pole_A2 od W_hi a přenos_A.
- Řetězec B: podobně pro jinou lineární funkci.
Sestavení a odeslání paketu
Funkce sestavení paketu:
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)
Paket se odešle do COM portu.
Integrace do webového systému
Python server přijímá HTTP POST:
POST / {"window": 5, "ticket": "487"}
Rozebírá JSON, sestaví paket, zapíše do portu. Heartbeat mechanismus obnovuje spojení:
- 60 sekund interval při OK.
- 10 sekund při chybě.
def _heartbeat_loop():
while True:
ok = _try_register(...)
was = _server_state['connected']
_server_state['connected'] = ok
if not was and ok:
print("[OK] Spojení obnoveno")
elif was and not ok:
print("[WARN] Spojení ztraceno")
time.sleep(60 if ok else 10)
Co je důležité
- BCD4 kódování roztahuje 1 bit na bajt pro odolnost proti rušení na 1200 bodech.
- Kontrolní součet využívá přenos mezi nibbly c1/c2.
- Reverzní inženýrství s AI je efektivní při přesné hypotéze a příkladech paketů.
- Server zajišťuje bezproblémovou integraci zastaralého zařízení s webem.
- Protokol: 33 bajtů, marker 0x55, číslice + okno + checksum.
— Editorial Team
Zatím žádné komentáře.