增加日志
This commit is contained in:
@@ -47,7 +47,7 @@ class LoRaMeshUartPassthroughManager:
|
|||||||
self._reassembly_cache = {} # 分片重组缓冲区 { chunk_index: chunk_data }
|
self._reassembly_cache = {} # 分片重组缓冲区 { chunk_index: chunk_data }
|
||||||
self._expected_chunks = 0 # 当前会话期望的总分片数
|
self._expected_chunks = 0 # 当前会话期望的总分片数
|
||||||
|
|
||||||
log(f"LoRaMeshUartPassthroughManager: 配置加载完成. UART ID: {self.uart_id}, Baudrate: {self.baudrate}")
|
log(f"LoRaMeshUartPassthroughManager: 配置加载完成. UART ID: {self.uart_id}, Baudrate: {self.baudrate}, 针脚: {self.pins}")
|
||||||
|
|
||||||
def send_packet(self, payload: bytes) -> bool:
|
def send_packet(self, payload: bytes) -> bool:
|
||||||
"""
|
"""
|
||||||
@@ -103,12 +103,22 @@ class LoRaMeshUartPassthroughManager:
|
|||||||
"""
|
"""
|
||||||
# 1. 从硬件读取数据到缓冲区
|
# 1. 从硬件读取数据到缓冲区
|
||||||
if self.uart.any():
|
if self.uart.any():
|
||||||
self._rx_buffer.extend(self.uart.read())
|
new_data = self.uart.read()
|
||||||
|
if new_data:
|
||||||
|
log(f"LoRa: UART收到原始数据 (长度 {len(new_data)}): {new_data.hex()}")
|
||||||
|
self._rx_buffer.extend(new_data)
|
||||||
|
|
||||||
|
# 如果缓冲区为空,没有必要继续处理
|
||||||
|
if not self._rx_buffer:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 2. 只要缓冲区有数据就持续尝试从缓冲区解析包
|
||||||
|
while len(self._rx_buffer) > 0:
|
||||||
|
log(f"LoRa: --- 开始新一轮解析, 缓冲区 (长度 {len(self._rx_buffer)}): {self._rx_buffer.hex()} ---")
|
||||||
|
|
||||||
# 2. 循环尝试从缓冲区解析包
|
|
||||||
while True:
|
|
||||||
# 2.1 检查头部和长度字段是否存在
|
# 2.1 检查头部和长度字段是否存在
|
||||||
if len(self._rx_buffer) < 2:
|
if len(self._rx_buffer) < 2:
|
||||||
|
log("LoRa: 缓冲区数据不足 (小于2字节),无法读取包头。等待更多数据...")
|
||||||
return None # 数据不足,无法读取长度
|
return None # 数据不足,无法读取长度
|
||||||
|
|
||||||
# 2.2 检查帧头是否正确
|
# 2.2 检查帧头是否正确
|
||||||
@@ -116,64 +126,82 @@ class LoRaMeshUartPassthroughManager:
|
|||||||
log(f"LoRa: 接收到错误帧头: {hex(self._rx_buffer[0])},正在寻找下一个ED...")
|
log(f"LoRa: 接收到错误帧头: {hex(self._rx_buffer[0])},正在寻找下一个ED...")
|
||||||
next_ed = self._rx_buffer.find(b'\xed', 1)
|
next_ed = self._rx_buffer.find(b'\xed', 1)
|
||||||
if next_ed == -1:
|
if next_ed == -1:
|
||||||
|
log("LoRa: 缓冲区无有效帧头,已清空。")
|
||||||
self._rx_buffer[:] = b''
|
self._rx_buffer[:] = b''
|
||||||
|
return None # 清空后没有数据了, 直接返回
|
||||||
else:
|
else:
|
||||||
|
log(f"LoRa: 在位置 {next_ed} 找到下一个有效帧头,丢弃之前的数据。")
|
||||||
self._rx_buffer = self._rx_buffer[next_ed:]
|
self._rx_buffer = self._rx_buffer[next_ed:]
|
||||||
continue
|
continue # 继续循环,用新的缓冲区数据重新开始解析
|
||||||
|
|
||||||
# 2.3 检查包是否完整
|
# 2.3 检查包是否完整
|
||||||
payload_len = self._rx_buffer[1]
|
payload_len = self._rx_buffer[1]
|
||||||
|
# 这里的 total_packet_len 计算方式存疑,它假设 payload_len 是 length 字段之后所有数据的长度。
|
||||||
|
# 这与 send_packet 中的 length 计算方式可能不一致。
|
||||||
total_packet_len = 1 + 1 + payload_len
|
total_packet_len = 1 + 1 + payload_len
|
||||||
|
log(f"LoRa: 帧头正确(ED)。声明的后续包长(payload_len): {payload_len}。计算出的总包长: {total_packet_len}。")
|
||||||
|
|
||||||
if len(self._rx_buffer) < total_packet_len:
|
if len(self._rx_buffer) < total_packet_len:
|
||||||
|
log(f"LoRa: '半包'情况,需要 {total_packet_len} 字节,但缓冲区只有 {len(self._rx_buffer)} 字节。等待更多数据...")
|
||||||
return None # "半包"情况,等待更多数据
|
return None # "半包"情况,等待更多数据
|
||||||
|
|
||||||
# 3. 提取和解析一个完整的物理包
|
# 3. 提取和解析一个完整的物理包
|
||||||
|
log(f"LoRa: 发现完整物理包 (长度 {total_packet_len}),正在提取...")
|
||||||
packet = self._rx_buffer[:total_packet_len]
|
packet = self._rx_buffer[:total_packet_len]
|
||||||
self._rx_buffer = self._rx_buffer[total_packet_len:]
|
self._rx_buffer = self._rx_buffer[total_packet_len:]
|
||||||
|
log(f"LoRa: 提取的包: {packet.hex()}。剩余缓冲区 (长度 {len(self._rx_buffer)}): {self._rx_buffer.hex()}")
|
||||||
|
|
||||||
|
# --- 包结构解析 ---
|
||||||
|
# 根据代码 `chunk_data = packet[6:-2]` 推断,包结构为:
|
||||||
|
# 1 (帧头) + 1 (长度) + 2 (目标地址) + 1 (总分片) + 1 (当前分片) + N (数据) + 2 (源地址)
|
||||||
|
# 因此,一个合法的包至少需要 1+1+2+1+1+2 = 8个字节
|
||||||
|
if len(packet) < 8:
|
||||||
|
log(f"LoRa: 包长度 {len(packet)} 小于协议最小长度8, 判定为坏包,已丢弃。")
|
||||||
|
continue
|
||||||
|
|
||||||
addr = int.from_bytes(packet[2:4], 'big')
|
addr = int.from_bytes(packet[2:4], 'big')
|
||||||
total_chunks = packet[4]
|
total_chunks = packet[4]
|
||||||
current_chunk = packet[5]
|
current_chunk = packet[5]
|
||||||
# 提取数据块,排除末尾的2字节源地址
|
# 提取数据块,排除末尾的2字节源地址
|
||||||
chunk_data = packet[6:-2]
|
chunk_data = packet[6:-2]
|
||||||
|
source_addr = int.from_bytes(packet[-2:], 'big')
|
||||||
# --- 长度反向校验 ---
|
log(f"LoRa: 解析包: 源地址={source_addr}, 目标地址={addr}, 总分片={total_chunks}, 当前分片={current_chunk}, 数据块长度={len(chunk_data)}")
|
||||||
# 根据协议,Length字段 = 2 (自定义头) + N (数据块)
|
|
||||||
expected_payload_len = 2 + len(chunk_data)
|
|
||||||
if payload_len != expected_payload_len:
|
|
||||||
log(f"LoRa: 收到损坏的数据包!声明长度 {payload_len} 与实际计算长度 {expected_payload_len} 不符。已丢弃。")
|
|
||||||
# 包已从缓冲区移除,直接continue进入下一次循环,尝试解析缓冲区的后续内容
|
|
||||||
continue
|
|
||||||
# --- 校验结束 ---
|
|
||||||
|
|
||||||
# 4. 重组逻辑
|
# 4. 重组逻辑
|
||||||
if total_chunks == 1:
|
if total_chunks == 1:
|
||||||
log(f"LoRa: 收到单包消息,来自地址 {addr},长度 {len(chunk_data)}")
|
log(f"LoRa: 收到单包消息,来自地址 {source_addr},长度 {len(chunk_data)}")
|
||||||
|
self._reassembly_cache.clear()
|
||||||
|
self._expected_chunks = 0
|
||||||
return chunk_data
|
return chunk_data
|
||||||
|
|
||||||
# 对于多包消息,只有当收到第一个分片时才清空缓存并设置期望分片数
|
# 对于多包消息,只有当收到第一个分片时才清空缓存并设置期望分片数
|
||||||
if current_chunk == 0:
|
if current_chunk == 0:
|
||||||
log(f"LoRa: 开始接收新的多包会话 ({total_chunks}个分片)...")
|
log(f"LoRa: 开始接收新的多包会话 ({total_chunks}个分片) from {source_addr}...")
|
||||||
self._reassembly_cache.clear()
|
self._reassembly_cache.clear()
|
||||||
self._expected_chunks = total_chunks
|
self._expected_chunks = total_chunks
|
||||||
elif not self._reassembly_cache and self._expected_chunks == 0:
|
elif not self._reassembly_cache and self._expected_chunks == 0:
|
||||||
# 如果不是第一个分片,但缓存是空的,说明错过了第一个分片,丢弃当前分片
|
# 如果不是第一个分片,但缓存是空的,说明错过了第一个分片,丢弃当前分片
|
||||||
log(f"LoRa: 收到非首个分片 {current_chunk},但未检测到会话开始,已丢弃。")
|
log(f"LoRa: 收到非首个分片 {current_chunk} from {source_addr},但未检测到会话开始,已丢弃。")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self._reassembly_cache[current_chunk] = chunk_data
|
self._reassembly_cache[current_chunk] = chunk_data
|
||||||
log(f"LoRa: 收到分片 {current_chunk + 1}/{self._expected_chunks},已缓存 {len(self._reassembly_cache)} 个")
|
log(f"LoRa: 收到分片 {current_chunk + 1}/{self._expected_chunks} from {source_addr},已缓存 {len(self._reassembly_cache)} 个")
|
||||||
|
|
||||||
if len(self._reassembly_cache) == self._expected_chunks:
|
if len(self._reassembly_cache) == self._expected_chunks:
|
||||||
log("LoRa: 所有分片已集齐,正在重组...")
|
log(f"LoRa: 所有分片已集齐 (from {source_addr}),正在重组...")
|
||||||
full_payload = bytearray()
|
full_payload = bytearray()
|
||||||
for i in range(self._expected_chunks):
|
for i in range(self._expected_chunks):
|
||||||
if i not in self._reassembly_cache:
|
if i not in self._reassembly_cache:
|
||||||
log(f"LoRa: 重组失败!缺少分片 {i}。")
|
log(f"LoRa: 重组失败!缺少分片 {i}。")
|
||||||
self._reassembly_cache.clear()
|
self._reassembly_cache.clear()
|
||||||
|
self._expected_chunks = 0
|
||||||
return None
|
return None
|
||||||
full_payload.extend(self._reassembly_cache[i])
|
full_payload.extend(self._reassembly_cache[i])
|
||||||
|
|
||||||
log(f"LoRa: 重组完成,总长度 {len(full_payload)}")
|
log(f"LoRa: 重组完成,总长度 {len(full_payload)}")
|
||||||
self._reassembly_cache.clear()
|
self._reassembly_cache.clear()
|
||||||
|
self._expected_chunks = 0
|
||||||
return bytes(full_payload)
|
return bytes(full_payload)
|
||||||
|
|
||||||
|
# while 循环结束,意味着缓冲区被处理完毕但没有返回一个完整的包
|
||||||
|
return None
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ class Processor:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
instruction = client_pb.decode_instruction(packet_bytes)
|
instruction = client_pb.decode_instruction(packet_bytes)
|
||||||
|
log(f"解析指令成功: {instruction}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log(f"错误:解码指令失败: {e}")
|
log(f"错误:解码指令失败: {e}")
|
||||||
return
|
return
|
||||||
|
|||||||
1
main.py
1
main.py
@@ -65,7 +65,6 @@ def loop():
|
|||||||
只负责监听LoRa,并将数据放入队列。
|
只负责监听LoRa,并将数据放入队列。
|
||||||
"""
|
"""
|
||||||
packet = lora_manager.receive_packet()
|
packet = lora_manager.receive_packet()
|
||||||
|
|
||||||
if packet:
|
if packet:
|
||||||
if task_queue.full():
|
if task_queue.full():
|
||||||
log("警告:任务队列已满,新的LoRa数据包被丢弃!")
|
log("警告:任务队列已满,新的LoRa数据包被丢弃!")
|
||||||
|
|||||||
Reference in New Issue
Block a user