mrlis1337

Untitled

Jul 12th, 2026
42
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.38 KB | None | 0 0
  1. import json
  2. import re
  3. import socket
  4. from collections import Counter
  5.  
  6. import serial
  7.  
  8.  
  9. SERIAL_PORT = "COM4"
  10. BAUD_RATE = 921600
  11.  
  12. MAC_ZONE_A = "1a:00:00:00:00:00"
  13. MAC_ZONE_B = "1a:00:00:00:00:01"
  14.  
  15. UDP_IP = "127.0.0.1"
  16. PORT_ZONE_A = 5005
  17. PORT_ZONE_B = 5006
  18.  
  19. SEND_METADATA = True
  20.  
  21. EXPECTED_CSI_LENGTHS = {128, 256, 376, 380, 384, 612}
  22. MAX_BUFFER_BYTES = 65536
  23. MAX_FRAME_BYTES = 12000
  24.  
  25. CSI_MARKER = b"CSI_DATA"
  26. MAC_RE = re.compile(r"(?:[0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}")
  27.  
  28.  
  29. def normalize_mac(mac):
  30. return mac.lower()
  31.  
  32.  
  33. def parse_csi_frame(frame_bytes):
  34. line = frame_bytes.replace(b"\x00", b"").decode("utf-8", errors="ignore").strip()
  35. if not line.startswith("CSI_DATA"):
  36. return None, "prefix"
  37.  
  38. array_start = line.rfind("[")
  39. array_end = line.find("]", array_start + 1)
  40. if array_start < 0 or array_end < 0:
  41. return None, "brackets"
  42.  
  43. header = line[:array_start]
  44. csi_text = line[array_start + 1:array_end]
  45.  
  46. macs = [normalize_mac(m.group(0)) for m in MAC_RE.finditer(header)]
  47. if not macs:
  48. return None, "mac"
  49.  
  50. tokens = [token.strip() for token in csi_text.split(",")]
  51. if not tokens or any(token == "" for token in tokens):
  52. return None, "empty_token"
  53.  
  54. csi = []
  55. for token in tokens:
  56. try:
  57. value = int(token)
  58. except ValueError:
  59. return None, "bad_int"
  60. if value < -128 or value > 127:
  61. return None, "byte_range"
  62. csi.append(value)
  63.  
  64. if len(csi) not in EXPECTED_CSI_LENGTHS:
  65. return None, f"bad_len:{len(csi)}"
  66.  
  67. header_without_macs = MAC_RE.sub("", header)
  68. header_numbers = [int(x) for x in re.findall(r"-?\d+", header_without_macs)]
  69. reported_len = header_numbers[-2] if len(header_numbers) >= 2 else None
  70. first_word_invalid = header_numbers[-1] if len(header_numbers) >= 1 else None
  71.  
  72. if reported_len is not None and reported_len != len(csi):
  73. return None, f"len_mismatch:{reported_len}!={len(csi)}"
  74.  
  75. return {
  76. "macs": macs,
  77. "csi": csi,
  78. "len": len(csi),
  79. "first_word_invalid": first_word_invalid,
  80. }, None
  81.  
  82.  
  83. def pop_next_frame(buffer):
  84. start = buffer.find(CSI_MARKER)
  85. if start < 0:
  86. if len(buffer) > MAX_FRAME_BYTES:
  87. del buffer[:-len(CSI_MARKER)]
  88. return None
  89.  
  90. if start > 0:
  91. del buffer[:start]
  92.  
  93. newline = buffer.find(b"\n", len(CSI_MARKER))
  94. next_marker = buffer.find(CSI_MARKER, 1)
  95.  
  96. if next_marker >= 0 and (newline < 0 or next_marker < newline):
  97. frame = bytes(buffer[:next_marker])
  98. del buffer[:next_marker]
  99. return frame
  100.  
  101. if newline >= 0:
  102. frame = bytes(buffer[:newline])
  103. del buffer[:newline + 1]
  104. return frame
  105.  
  106. if len(buffer) > MAX_FRAME_BYTES:
  107. del buffer[:len(CSI_MARKER)]
  108. return b""
  109.  
  110. return None
  111.  
  112.  
  113. def main():
  114. mac_zone_a = normalize_mac(MAC_ZONE_A)
  115. mac_zone_b = normalize_mac(MAC_ZONE_B)
  116.  
  117. sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  118.  
  119. print(f"[*] Запуск Dual Router на порту {SERIAL_PORT}...")
  120. try:
  121. ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=0)
  122. ser.setDTR(False)
  123. ser.setRTS(False)
  124. ser.reset_input_buffer()
  125. print("[+] COM-порт открыт. Ожидание эфира...")
  126. except Exception as exc:
  127. print(f"[-] Ошибка: {exc}")
  128. return
  129.  
  130. buffer = bytearray()
  131. packets_a = 0
  132. packets_b = 0
  133. dropped = Counter()
  134.  
  135. try:
  136. while True:
  137. chunk = ser.read(ser.in_waiting or 4096)
  138. if chunk:
  139. buffer.extend(chunk)
  140. if len(buffer) > MAX_BUFFER_BYTES:
  141. del buffer[: len(buffer) - MAX_BUFFER_BYTES]
  142. dropped["buffer_overflow"] += 1
  143.  
  144. while True:
  145. frame = pop_next_frame(buffer)
  146. if frame is None:
  147. break
  148. if not frame:
  149. dropped["oversized_frame"] += 1
  150. continue
  151.  
  152. packet, error = parse_csi_frame(frame)
  153. if error:
  154. dropped[error] += 1
  155. continue
  156.  
  157. macs = packet["macs"]
  158. if mac_zone_a in macs:
  159. port = PORT_ZONE_A
  160. packets_a += 1
  161. elif mac_zone_b in macs:
  162. port = PORT_ZONE_B
  163. packets_b += 1
  164. else:
  165. dropped["unknown_mac"] += 1
  166. continue
  167.  
  168. payload_obj = packet if SEND_METADATA else packet["csi"]
  169. payload = json.dumps(payload_obj, separators=(",", ":")).encode("utf-8")
  170. sock.sendto(payload, (UDP_IP, port))
  171.  
  172. total = packets_a + packets_b
  173. if total % 50 == 0:
  174. common_drops = ", ".join(f"{k}:{v}" for k, v in dropped.most_common(4))
  175. print(
  176. f"OK A:{packets_a} B:{packets_b} | drop {sum(dropped.values())}"
  177. f" [{common_drops}]",
  178. end="\r",
  179. )
  180. except KeyboardInterrupt:
  181. print("\n[*] Роутер остановлен.")
  182. finally:
  183. ser.close()
  184.  
  185.  
  186. if __name__ == "__main__":
  187. main()
  188.  
Advertisement
Add Comment
Please, Sign In to add comment