Python UDP协议发送指定格式报文
import struct import time import socket import threading # udp 发送数据 def send_data(udp_socket, target_ip, target_port,send_msg): try: udp_socket.sendto(send_msg, (target_ip, target_port)) except Exception as e: print(f"发送数据时出错: {e}") # udp 接收数据 def receive_data(udp_socket): while True: try: recv_data, addr = udp_socket.recvfrom(1024) recv_msg = recv_data.decode('utf-8') print(f"从 {addr} 收到数据: {recv_msg}") except Exception as e: print(f"接收数据时出错: {e}") # 计算校验位 def calculate_checksum(data): # 计算校验字节,即所有字节按位异或 checksum = 0 for byte in data: checksum ^= byte return bytes([checksum]) # 交通参与者类型 # 请参照算法方输出与协议规定将字典完善 def switch_participant_type(case_value): switch_dict = { 'car': bytes([0x02]), 'truck': bytes([0x03]), 'default': bytes([0x00]), } return switch_dict.get(case_value, switch_dict['default']) # 车辆颜色 # 请参照算法方输出与协议规定将字典完善 def switch_car_color(case_value): switch_dict = { 'red': struct.pack('<8s', '红'.encode('utf-8')), 'white': struct.pack('<8s', '白'.encode('utf-8')), 'gray': struct.pack('<8s', '灰'.encode('utf-8')), 'yellow': struct.pack('<8s', '黄'.encode('utf-8')), 'pink': struct.pack('<8s', '粉'.encode('utf-8')), 'purple': struct.pack('<8s', '紫'.encode('utf-8')), 'green': struct.pack('<8s', '绿'.encode('utf-8')), 'blue': struct.pack('<8s', '蓝'.encode('utf-8')), 'brown': struct.pack('<8s', '棕'.encode('utf-8')), 'black': struct.pack('<8s', '黑'.encode('utf-8')), 'default': struct.pack('<8s', '无'.encode('utf-8')), } return switch_dict.get(case_value, switch_dict['default']) # 车辆类型细分 # 请参照算法方输出与协议规定将字典完善 def switch_car_type_detail(case_value): switch_dict = { 'car': struct.pack('<3s', 'K33'.encode('utf-8')), 'truck': struct.pack('<3s', 'H51'.encode('utf-8')), } return switch_dict.get(case_value) # 车道方向 # 请参照算法方输出与协议规定将字典完善 def switch_direction(case_value): switch_dict = { 'w': bytes([0x40]), 'e': bytes([0x04]), 'n': bytes([0x01]), 's': bytes([0x10]), 'default': bytes([0x00]), } return switch_dict.get(case_value, switch_dict['default']) # 数据打包 def pack_data_frame(data): # 定义常量值 FRAME_START = bytes([0xC0]) # 帧开始 VERSION = bytes([0x01]) # 版本号 SENDER_ID = bytes([0x02]) # 发送方ID RECEIVER_ID = bytes([0x01]) # 接收方ID DATA_LINK_CODE = bytes([0x03]) # 数据链路码 OPERATION_TYPE = bytes([0x82]) # 操作类型-主动发送 OBJECT_ID = bytes([0x01]) # 对象标识:目标检测结果 RESERVED = bytes([0x01] * 5) # 保留字段 # 计算数据帧长度 data_length = 21 + 1 * 61 # 数据包长度为 固定长度 + 参与者*固定长度 data_length_bytes = struct.pack('<H', data_length) # 其他字段初始化 data_frame_number = bytes([0x00]) # 数据包序号,初始值为0 total_frame_count = bytes([0x00]) # 数据帧总数量,初始值为0 current_frame_number = bytes([0x00]) # 当前数据帧序号,初始值为0 # 构造识别帧时间,使用系统当前时间 current_time = int(time.time() * 1000) # 获取当前时间戳(毫秒级) minutes = (current_time // (1000 * 60)) % 60 # 分钟 seconds = (current_time // 1000) % 60 # 秒 milliseconds = current_time % 1000 # 毫秒 recognition_frame_time = struct.pack('<BBHH', minutes, seconds, milliseconds, 0) # 交通参与者,默认1个 num_participants = bytes([0x01]) # 构造数据内容 # '<I': 是格式字符串,表示不同字段的数据类型和顺序。每个字符对应一个字段的数据类型。具体解释如下: # <: 小端字节序 # I: 无符号整型(4字节) # B: 无符号字节(1字节) # H: 无符号短整型(2字节) # f: 浮点数 (4字节) # 5s: 字符串,5个字节 participant_id = struct.pack('<I', 0) # 交通参与者id world_x = struct.pack('<I', 0) # 统一坐标系 x 坐标 world_y = struct.pack('<I', 0) # 统一坐标系 y 坐标 participant_type = bytes([0x00]) # 交通参与者类型 longitude = struct.pack('<f', 0.0) # 经度坐标 latitude = struct.pack('<f', 0.0) # 纬度坐标 lane_no = bytes([0x00]) # 车道号 lane_attribute = bytes([0x00]) # 车道属性 direction = bytes([0x00]) # 车道方向 participant_length = bytes([0x00]) # 交通参与者长度 participant_width = bytes([0x00]) # 交通参与者宽度 participant_height = bytes([0x00]) # 交通参与者高度 participant_v = struct.pack('<H', 0) # 交通参与者速度 participant_a = struct.pack('<H', 0) # 交通参与者加速度 participant_angle = struct.pack('<H', 0) # 交通参与者航向角 plate_no = struct.pack('<8s', '00000000'.encode('utf-8')) # 车牌号 plate_color = bytes([0x01]) # 号牌颜色 car_color = struct.pack('<8s', '无'.encode('utf-8')) # 车辆颜色 car_type_detail = struct.pack('<3s', 'K33'.encode('utf-8')) # 车辆类型细分 for index, value in enumerate(data): # 交通参与者id if index == 1: participant_id = struct.pack('<I', value) # 统一坐标系 x 坐标 if index == 2: world_x = struct.pack('<I', value) # 统一坐标系 y 坐标 if index == 3: world_y = struct.pack('<I', value) # 车道方向 if index == 4: direction = switch_direction(value) # 交通参与者类型 if index == 5: participant_type = switch_participant_type(value) car_type_detail = switch_car_type_detail(value) # 车辆颜色 if index == 6: car_color = switch_car_color(value) # 交通参与者航向角 if index == 7: participant_angle = struct.pack('<H', 0) # 数据合并 data_content = ( participant_id + world_x + world_y + participant_type + longitude + latitude + lane_no + lane_attribute + direction + participant_length + participant_width + participant_height + participant_v + participant_a + participant_angle + plate_no + plate_color + car_color + car_type_detail ) # 计算校验字节 checksum_data = VERSION + SENDER_ID + RECEIVER_ID + DATA_LINK_CODE + \ OPERATION_TYPE + OBJECT_ID + data_length_bytes + \ data_frame_number + total_frame_count + current_frame_number + \ RESERVED + recognition_frame_time + num_participants + data_content frame_checksum = calculate_checksum(checksum_data) # 帧结束 frame_end = bytes([0xC0]) # 组装数据帧 data_frame = ( FRAME_START + VERSION + SENDER_ID + RECEIVER_ID + DATA_LINK_CODE + OPERATION_TYPE + OBJECT_ID + data_length_bytes + data_frame_number + total_frame_count + current_frame_number + RESERVED + recognition_frame_time + data_content + frame_checksum + frame_end ) return data_frame def main(): # 创建一个UDP套接字 udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 将套接字绑定到特定的地址和端口 local_address = ('192.168.124.28', 10050) udp_socket.bind(local_address) # 设置发送数据的目标地址和端口 target_ip = '192.168.124.34' target_port = 6666 # 启动一个线程用于接收数据 receive_thread = threading.Thread(target=receive_data, args=(udp_socket)) receive_thread.start() # 示例数据 input_data = [ [1, 3, 1426, 1438, "w", "truck", "red", "init"], [1, 5, 1274, 1263, "w", "car", "blue", "init"], [1, 7, 3099, 872, "w", "car", "blue", "init"], [1, 2030, 2618, 634, "w", "car", "blue", "init"], [1, 2029, 2352, 402, "w", "car", "black", "init"] ] # 声明一个空数组,用于存储每次循环生成的数据帧二进制表示 data_frames_binary = [] # 转换并输出每条数据的二进制表示 for entry in input_data: data_frame_binary = pack_data_frame([entry]) data_frames_binary.append(data_frame_binary) # 在主线程中发送所有数据 for data_frame_binary in data_frames_binary: send_data(udp_socket,target_ip,target_port,data_frame_binary) if __name__ == '__main__': main()