You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Adafruit LoRa RFM96W分块传输numpy数组后重塑失败求助

分块传输numpy数组时的接收异常解决方法

问题场景

我有一个shape为(8,64)的numpy数组,经array.tobytes()转换后长度为512字节,但adafruit_rfm9x库的send()函数存在252字节的payload限制。尝试分块传输后,接收端抛出异常:

ValueError: cannot reshape array of size 8 into shape (8,64)

错误原因

当前的传输逻辑存在两个核心问题:

  • 接收端仅通过当前数据包长度是否小于252判断传输结束,若出现丢包(比如只收到最后一块8字节的数据包),会提前终止接收,导致数据不完整。
  • 无线传输可能出现丢包、乱序,现有逻辑没有块序号和总块数标识,无法确认是否收齐所有数据。

修复方案:添加块序号与总块数标识

在每个数据包中嵌入总块数和当前块序号,让接收端明确知道需要接收的块数量,同时通过字典存储块解决乱序问题,结合ACK机制确保每块传输可靠。

1. 发送端代码修改

预留2字节用于存储块信息(总块数+当前块序号),将有效数据块大小设为250,确保整个数据包(2+250=252)不超过payload限制,并添加重试逻辑:

import time

def send_message(key, value):
    print(f"Sending {key} to Dev 2...")
    if not isinstance(value, bytes):
        value = bytes(value, 'utf-8')
    
    MAX_CHUNK_SIZE = 250  # 预留2字节头部,有效数据块设为250
    total_len = len(value)
    num_chunks = (total_len + MAX_CHUNK_SIZE - 1) // MAX_CHUNK_SIZE  # 向上取整计算总块数
    
    for i in range(num_chunks):
        chunk_data = value[i * MAX_CHUNK_SIZE: (i + 1) * MAX_CHUNK_SIZE]
        # 构造头部:第1字节总块数,第2字节当前块序号(从1开始)
        header = bytes([num_chunks, i+1])
        packet = header + chunk_data
        
        # 发送并等待ACK,失败则重试
        success = rfm9x.send_with_ack(packet)
        if not success:
            print(f"Chunk {i+1} send failed, retrying...")
            i -= 1
            time.sleep(0.5)
            continue
        print(f"Sent chunk {i+1}/{num_chunks}")
    print(f"{key} has been sent")

2. 接收端代码修改

解析每个数据包的头部信息,用字典按序号存储块,确认收齐所有块后再合并数据:

def receive_message(key):
    print(f"Receiving {key} from Dev 1 ...")
    MAX_CHUNK_SIZE = 250
    received_chunks = {}
    total_chunks = None
    
    while True:
        data = rfm9x.receive(with_ack=True)
        if data is not None and len(data) >= 2:
            # 解析头部信息
            total_chunks = data[0]
            current_chunk_idx = data[1]
            chunk_data = data[2:]
            
            # 仅存储有效范围内的块
            if 1 <= current_chunk_idx <= total_chunks:
                received_chunks[current_chunk_idx] = chunk_data
                print(f"Received chunk {current_chunk_idx}/{total_chunks}")
            
            # 检查是否收齐所有块
            if len(received_chunks) == total_chunks:
                # 按序号排序合并数据
                received_data = b''
                for idx in range(1, total_chunks+1):
                    received_data += received_chunks[idx]
                print(f"Received {key} completely")
                return received_data
        time.sleep(0.1)

3. 验证步骤

  1. 发送端执行:
    send_message("Data", nparray.tobytes())
    
  2. 接收端执行:
    Data = receive_message("Data")
    result = np.frombuffer(Data, dtype=np.int8).reshape(8, 64)
    

此时接收端能完整获取512字节数据,正常重构为(8,64)的numpy数组。

内容的提问来源于stack exchange,提问作者a15600712

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 16:25:31