国网 i1协议 python实现

近期应工作需求,使用 python 实现了国网 i1协议,包含大部分功能,没有的可以自己参照国标文件自己添加,i1协议总体还是比较简单的,没有特别复杂的交互。

client 端

python 复制代码
import socket
import struct
import time
import io
import os
from common import *
from threading import Thread


class I1Client(Thread):

    def __init__(self):
        super().__init__()
        self.PARSER_MAP = {
            PTYPE_WEATHER:      'parse_weather',
            PTYPE_ICE:          'parse_ice',
            PTYPE_GALLOP_CHAR:  'parse_gallop_char',
            PTYPE_GALLOP_TRACK: 'parse_gallop_track',
            PTYPE_TOWER_TILT: 'parse_tower_tilt',
            PTYPE_FILTH: 'parse_filth',
            PTYPE_BREEZE_FLUTTER: 'parse_breeze_flutter',
            PTYPE_BREEZE_WAVEFORM: 'parse_breeze_waveform',
            PTYPE_WIRE_TEMP: 'parse_wire_temp',
            PTYPE_WIRE_RADIAN: 'parse_wire_radian',
            PTYPE_WIRE_YAW: 'parse_wire_yaw',
            PTYPE_DEVICE_TIME: 'parse_device_time',
            PTYPE_DEVICE_NETADAPTER: 'parse_device_netadapter',
            PTYPE_MAINSITE_REQUEST: 'parse_mainsite_request',
            PTYPE_COLLECT_PARAMS: 'parse_collect_params',
            PTYPE_MODEL_PARAMS: 'parse_model_params',
            PTYPE_ALARM_THRESHOLDS: 'parse_alarm_thresholds',
            PTYPE_DEVICE_DIRECT: 'parse_device_direct',
            PTYPE_CONTROL_BASE_INFO: 'parse_control_base_info',
            PTYPE_REMOTE_UPGRADE: 'parse_remote_upgrade',
            PTYPE_REMOTE_UPGRADE_END: 'parse_remote_upgrade_finished',
            PTYPE_REMOTE_UPGRADE_SSUE: 'parse_remote_upgrade_ssue',
            PTYPE_CMD_ID: 'parse_cmd_id',
            PTYPE_CMD_RESET: 'parse_cmd_reset',
            PTYPE_CMD_WAKE: 'parse_cmd_wake',
            PTYPE_WEATHER_PARAMS: 'parse_weather_params',
            PTYPE_TOWER_TILT_PARAMS: 'parse_tower_tilt_params',
            PTYPE_BREEZE_FLUTTER_PARAMS: 'parse_breeze_flutter_params',
            PTYPE_WIRE_RADIAN_PARAMS: 'parse_wire_radian_params',
            PTYPE_WIRE_TEMP_PARAMS: 'parse_wire_temp_params',
            PTYPE_ICE_PARAMS: 'parse_ice_params',
            PTYPE_WIRE_YAW_PARAMS: 'parse_wire_yaw_params',
            PTYPE_GALLOP_CHAR_PARAMS: 'parse_gallop_char_params',
            PTYPE_FILTH_PARAMS: 'parse_filth_params',
            PTYPE_IMAGE_COLLECT_PARAMS: 'parse_image_collect_params',
            PTYPE_IMAGE_TIME_TABLE: 'parse_image_time_table',
            PTYPE_IMAGE_TAKE_MANUAL: 'parse_image_take_manual',
            PTYPE_REQUEST_IMAGE_DATA:   'parse_request_image_data',
            PTYPE_IMAGE_DATA:   'parse_image_data',
            PTYPE_IMAGE_END_DATA:   'parse_image_end_data',
            PTYPE_CAMERA_REMOTE_ADJUST: 'parse_camera_remote_adjust',
            PTYPE_CAMERA_UPLOAD_VIDEO: 'parse_camera_upload_video',
            PTYPE_CMD_SAVE_ADRESS: 'parse_cmd_save_address',
            PTYPE_STOP_CONNECT: 'parse_stop_connect',
            PTYPE_CAMERA_BASE_INFO: 'parse_camera_base_info',
            PTYPE_CAMERA_TIME_TABLE: 'parse_camera_time_table',
            PTYPE_CMD_HEARTBEAT: 'parse_cmd_heartbeat',
            PTYPE_CMD_BASE_INFO: 'parse_cmd_base_info',
            PTYPE_CMD_WORK_STATE: 'parse_cmd_work_state',
            PTYPE_CMD_ERR_INFO: 'parse_cmd_err_info',
            PTYPE_CUSTOM_DATA:  'parse_custom_data',
        }

    def make_weather(self):
        """C.5.1 气象监测数据报"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x01监测数据报文
        frame_type = struct.pack("<s",b'\x01')
        #报文类型->0x0B
        ptype= struct.pack("<s",b'\x0B')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        comp_id = b'00000000000000002'
        ts = struct.pack('<I', 1700000000)
        avg_ws   = struct.pack('<f', 3.3)
        avg_wd   = struct.pack('<H', 2)
        max_ws = struct.pack('<f', 2.2)
        extreme_ws = struct.pack('<f', 3.3)
        standard_ws = struct.pack('<f', 4.4)
        temp = struct.pack('<f', 5.6)
        hum  = struct.pack('<H', 5)
        pres = struct.pack('<f', 1.2)
        precipitaton = struct.pack('<f', 3.3)
        precipitaton_intensity = struct.pack('<f', 3.3)
        radiation_intensity = struct.pack('<H', 3)


        #data_len表示 frame_no以后,crc 以前的数据长度
        content = comp_id + ts + avg_ws + avg_wd + max_ws + extreme_ws + standard_ws + temp + hum + pres + precipitaton + precipitaton_intensity + radiation_intensity
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    

    def make_filth(self):
        """C.5.2 现场污秽数据报"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x01监测数据报文
        frame_type = struct.pack("<s",b'\x01')
        #报文类型->0x5C
        ptype= struct.pack("<s",b'\x5C')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        comp_id = b'00000000000000002'
        ts = struct.pack('<I', 1700000000)
        esdd   = struct.pack('<f', 3.2)
        nsdd   = struct.pack('<f', 5.6)
        daily_max_temp = struct.pack('<f', 3.1)
        daily_min_temp = struct.pack('<f', 7.8)
        daily_max_hum = struct.pack('<H', 9)
        daily_min_hum = struct.pack('<H', 8)

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = comp_id + ts + esdd + nsdd + daily_max_temp + daily_min_temp + daily_max_hum + daily_min_hum
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    

    def make_ice(self):
        """C.5.2  覆冰监测数据报"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x01监测数据报文
        frame_type = struct.pack("<s",b'\x01')
        #报文类型->0x22
        ptype= struct.pack("<s",b'\x22')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        comp_id = b'00000000000000002'
        ts = struct.pack('<I', 1700000000)
        eq_icethickness = struct.pack('<f',3.4)
        tension = struct.pack('<f',4.5)
        tension_difference = struct.pack('<f',2.1)
        t_sensor_num = struct.pack('<B',2)
        t_sensor_list = b''
        for i in range(2):
            t_sensor_list += struct.pack('<f',3.2)
            t_sensor_list += struct.pack('<f',2.3)
            t_sensor_list += struct.pack('<f',5.8)
        
        instantaneous_windspeed = struct.pack('<f',3.2)
        instantaneous_winddirection = struct.pack('<H',6)
        air_temperature = struct.pack('<f',2.3)
        humidity = struct.pack('<H',2)

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = comp_id + ts + eq_icethickness + tension + tension_difference + t_sensor_num + t_sensor_list + instantaneous_windspeed + instantaneous_winddirection + air_temperature + humidity
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_breeze_flutter(self):
        """C.5.2  微风振动特征量"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x01监测数据报文
        frame_type = struct.pack("<s",b'\x01')
        #报文类型->0x1E
        ptype= struct.pack("<s",b'\x1E')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        comp_id = b'00000000000000002'
        unit_sum = struct.pack('<B', 1)
        unit_no  = struct.pack('<B', 1)
        ts = struct.pack('<f', 1.1)
        strain_amplitude = struct.pack('<H', 3)
        bending_amplitude = struct.pack('<f', 3.3)
        vibration_frequency = struct.pack('<f', 2.2)

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = comp_id + unit_sum + unit_no + ts + strain_amplitude + bending_amplitude + vibration_frequency
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_breeze_waveform(self):
        """C.5.3 微风振动波形"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x01监测数据报文
        frame_type = struct.pack("<s",b'\x01')
        #报文类型->0x1F
        ptype= struct.pack("<s",b'\x1F')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        comp_id = b'00000000000000002'
        unit_sum = struct.pack('<B', 1)
        unit_no  = struct.pack('<B', 1)
        ts = struct.pack('<f', 3.3)
        samplepack_sum = struct.pack('<B', 1)
        samplepack_no = struct.pack('<B', 1)
        strain_data = b''
        for i in range(2):
            strain_data += struct.pack('<H', 2)

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = comp_id + unit_sum + unit_no + ts + samplepack_sum + samplepack_no + strain_data
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_gallop_char(self):
        """C.5.4 舞动特征"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x01监测数据报文
        frame_type = struct.pack("<s",b'\x01')
        #报文类型->0x24
        ptype= struct.pack("<s",b'\x24')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        comp_id = b'00000000000000002'
        unit_sum = struct.pack('<B', 1)
        unit_no  = struct.pack('<B', 1)
        ts = struct.pack('<f', 3.3)
        u_gallop_amplitude = struct.pack('<f', 3.3)
        u_vertical_amplitude = struct.pack('<f', 2.2)
        u_horizontal_amplitude = struct.pack('<f', 1.4)
        u_angle_vertical = struct.pack('<f', 5.6)
        u_gallop_frequency = struct.pack('<f', 6.6)
        

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = comp_id + unit_sum + unit_no + ts + u_gallop_amplitude + u_vertical_amplitude + u_horizontal_amplitude + u_angle_vertical + u_gallop_frequency
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_gallop_track(self):
        """C.5.5 舞动轨迹"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x01监测数据报文
        frame_type = struct.pack("<s",b'\x01')
        #报文类型->0x25
        ptype= struct.pack("<s",b'\x25')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        comp_id = b'00000000000000002'
        unit_sum = struct.pack('<B', 1)
        unit_no  = struct.pack('<B', 1)
        ts = struct.pack('<f', 3.3)
        pack_sum = struct.pack('<B', 3)
        pack_no  = struct.pack('<B', 3)
        displacement = b''
        for i in range(3):
            displacement += struct.pack('<f', 3.2)
            displacement += struct.pack('<f', 3.2)
            displacement += struct.pack('<f', 3.2)
        

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = comp_id + unit_sum + unit_no + ts + pack_sum + pack_no + displacement
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    

    def make_wire_temp(self):
        """C.5.6 导线温度"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x01监测数据报文
        frame_type = struct.pack("<s",b'\x01')
        #报文类型->0x21
        ptype= struct.pack("<s",b'\x21')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        comp_id = b'00000000000000002'
        unit_sum = struct.pack('<B', 1)
        unit_no  = struct.pack('<B', 1)
        ts = struct.pack('<f', 3.3)
        line_temp1 = struct.pack('<f', 12.2)
        line_temp2 = struct.pack('<f', 14.1)
        

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = comp_id + unit_sum + unit_no + ts + line_temp1 + line_temp2
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_wire_radian(self):
        """C.5.7 导线弧垂"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x01监测数据报文
        frame_type = struct.pack("<s",b'\x01')
        #报文类型->0x20
        ptype= struct.pack("<s",b'\x20')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        comp_id = b'00000000000000002'
        ts = struct.pack('<f', 1700000000)
        conductor_sag = struct.pack('<f', 1.2)
        toground_distance = struct.pack('<f', 2.3)
        angle = struct.pack('<f', 3.3)
        measure_flag = struct.pack('<B', 1)
        

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = comp_id + ts + conductor_sag + toground_distance + angle + measure_flag
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    

    def make_wire_radian(self):
        """C.5.8 风偏"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x01监测数据报文
        frame_type = struct.pack("<s",b'\x01')
        #报文类型->0x23
        ptype= struct.pack("<s",b'\x23')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        comp_id = b'00000000000000002'
        ts = struct.pack('<f', 1700000000)
        windage_yaw_angle = struct.pack('<f', 3.3)
        deflection_angle = struct.pack('<f', 4.5)
        least_clearance = struct.pack('<f', 2.3)
        

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = comp_id + ts + windage_yaw_angle + deflection_angle + least_clearance
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_tower_tilt(self):
        """C.5.9 塔杆倾斜"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x01监测数据报文
        frame_type = struct.pack("<s",b'\x01')
        #报文类型->0x0C
        ptype= struct.pack("<s",b'\x0C')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        comp_id = b'00000000000000002'
        ts = struct.pack('<f', 1700000000)
        inclination = struct.pack('<f', 3.2)
        inclination_x = struct.pack('<f', 1.1)
        inclination_y = struct.pack('<f', 1.4)
        angle_x = struct.pack('<f', 4.5)
        angle_y = struct.pack('<f', 4.4)
        

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = comp_id + ts + inclination + inclination_x + inclination_y + angle_x + angle_y
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    
    def make_device_time(self):
        """C.6.3监测装置时间"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x04控制响应报文
        frame_type = struct.pack("<s",b'\x04')
        #报文类型->0xA1
        ptype= struct.pack("<s",b'\xA1')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        command_status = struct.pack('<B', 0xFF)
        cloctime_stamp = struct.pack('<f', 1700000000)
        

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = command_status + cloctime_stamp
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_device_netadapter(self):
        """C.6.4 监测装置网络适配器"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x04控制响应报文
        frame_type = struct.pack("<s",b'\x04')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xA2')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        command_status = struct.pack('<B', 0xFF)
        request_set_flag = struct.pack('<B', 1)
        request_flag = struct.pack('<B', 1)
        ip = struct.pack('<4s', socket.inet_aton('192.168.232.222'))
        subnet_mask = struct.pack('<f', 2)
        gateway = struct.pack('<f', 2)
        dns_server = struct.pack('<f', 3)
        phone_number = struct.pack('<20s', b'151')
        

        #data_len表示 frame_no以后,crc 以前的数据长度 
        content = command_status + request_set_flag + request_flag + ip + subnet_mask + gateway + dns_server + phone_number
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_mainsite_request(self):
        """C.6.5 主站请求数据"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x04控制响应报文
        frame_type = struct.pack("<s",b'\x04')
        #报文类型->0xA3
        ptype= struct.pack("<s",b'\xA3')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        command_status = struct.pack('<B', 0xFF)
        request_type = struct.pack('<B', 0xB0)
        
        

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = command_status + request_type
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def make_collect_params(self):
        """C.6.6 采样参数设置"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x04控制响应报文
        frame_type = struct.pack("<s",b'\x04')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xA4')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        command_status = struct.pack('<B', 0xFF)
        request_type = struct.pack('<B', 0xB0)
        request_flag = struct.pack('<B', 0xA1)
        main_time = struct.pack('<H', 3)
        sample_count = struct.pack('<H', 2)
        sample_frequency = struct.pack('<H', 2)
        heartbeat_time = struct.pack('<B', 1)
        

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = command_status + request_type + request_flag + main_time + sample_count + sample_frequency + heartbeat_time
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_model_params(self):
        """C.6.7 模型参数设置"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x04控制响应报文
        frame_type = struct.pack("<s",b'\x04')
        #报文类型->0xA5
        ptype= struct.pack("<s",b'\xA5')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        command_status = struct.pack('<B', 0xFF)
        request_set_flag = struct.pack('<B', 0xFF)
        config_total = struct.pack('<B', 2)
        configs = b''
        for i in range(2):
            configs += struct.pack('<6s', b'666666')
            configs += struct.pack('<B', 1)
            configs += struct.pack('<f', 2.2)


        #data_len表示 frame_no以后,crc 以前的数据长度
        content = command_status + request_set_flag + config_total + configs
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def make_alarm_thresholds(self):
        """C.6.8 报警阈值设置"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x04控制响应报文
        frame_type = struct.pack("<s",b'\x04')
        #报文类型->0xA6
        ptype= struct.pack("<s",b'\xA6')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        command_status = struct.pack('<B', 0xFF)
        request_type = struct.pack('<B', 0xFF)
        alarm_total = struct.pack('<B', 0x02)
        thresholds = b''
        for i in range(0x02):
            thresholds += struct.pack('<6s',b'23')
            thresholds += struct.pack('<f', 3.3)



        #data_len表示 frame_no以后,crc 以前的数据长度
        content = command_status + request_type + alarm_total + thresholds
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    

    def make_device_direct(self):
        """C.6.9 监测装置指向信息设置"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x04控制响应报文
        frame_type = struct.pack("<s",b'\x04')
        #报文类型->0xA7
        ptype= struct.pack("<s",b'\xA7')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        command_status = struct.pack('<B', 0xFF)
        request_flag = struct.pack('<B', 1)
        ip_address = struct.pack('<4s', socket.inet_aton("192.168.1.1"))
        port = struct.pack('<H', 22)
        domain_name = struct.pack('<64s', b'www.baidu.com')



        #data_len表示 frame_no以后,crc 以前的数据长度
        content = command_status + request_flag + ip_address + port + domain_name
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_base_info(self):
        """C.6.10 基本信息设置"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x04控制响应报文
        frame_type = struct.pack("<s",b'\x04')
        #报文类型->0xA8
        ptype= struct.pack("<s",b'\xA8')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        command_status = struct.pack('<B', 0xFF)
        request_type = struct.pack('<B', 1)
        info_type = struct.pack('<B', 1)



        #data_len表示 frame_no以后,crc 以前的数据长度
        content = command_status + request_type + info_type
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    

    def make_remote_upgrade_ssue(self):
        """C.6.11.3 软件升级补包"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x04控制响应报文
        frame_type = struct.pack("<s",b'\x04')
        #报文类型->0xAB
        ptype= struct.pack("<s",b'\xAB')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        file_name = struct.pack('<20s', b'sdfafsdf')
        complementpack_sum = struct.pack('<B', 2)
        pack_no_list = [3,4]
        complementpack_no = b''
        for i in range(2):
            complementpack_no += struct.pack('<I', pack_no_list[i])




        #data_len表示 frame_no以后,crc 以前的数据长度
        content = file_name + complementpack_sum + complementpack_no
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content 
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_cmd_id(self):
        """C.6.12 监测装置编码设置"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x04控制响应报文
        frame_type = struct.pack("<s",b'\x04')
        #报文类型->0xAC
        ptype= struct.pack("<s",b'\xAC')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        command_status = struct.pack('<B', 0xFF)
        request_flag = struct.pack('<B', 1)
        new_cmd_id = struct.pack('<17s', b'00000000000000003')
        component_id = struct.pack('<17s', b'00000000000000004')
        original_id = struct.pack('<17s', b'02')

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = command_status + request_flag + new_cmd_id + component_id + original_id
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_cmd_reset(self):
        """C.6.13 监测装置复位"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x04控制响应报文
        frame_type = struct.pack("<s",b'\x04')
        #报文类型->0xAD
        ptype= struct.pack("<s",b'\xAD')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        command_status = struct.pack('<B', 0xFF)

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = command_status
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    

    def make_cmd_wake(self):
        """C.6.14 监测装置苏醒"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x04控制响应报文
        frame_type = struct.pack("<s",b'\x04')
        #报文类型->0xAE
        ptype= struct.pack("<s",b'\xAE')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        command_status = struct.pack('<B', 0xFF)

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = command_status
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    

    def make_image_collect_params(self):
        """C.7.1 图片采集参数"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x08控制报文
        frame_type = struct.pack("<s",b'\x08')
        #报文类型->0xC9
        ptype= struct.pack("<s",b'\xC9')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        command_status = struct.pack('<B', 0xFF)
        request_set_flag = struct.pack('<B', 1)
        request_flag = struct.pack('<B', 1)
        color_select = struct.pack('<B', 1)
        resolution = struct.pack('<B', 1)
        luminance = struct.pack('<B', 1)
        contrast = struct.pack('<B', 1)
        saturation = struct.pack('<B', 1)

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = command_status + request_set_flag + request_flag + color_select + resolution + luminance + contrast + saturation
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_image_time_table(self):
        """C.7.2 拍照时间表"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x08图像控制响应报文
        frame_type = struct.pack("<s",b'\x08')
        #报文类型->0xCA
        ptype= struct.pack("<s",b'\xCA')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        command_status = struct.pack('<B', 0xFF)
        request_set_flag = struct.pack('<B', 1)
        channel_no = struct.pack('<B', 1)
        group_num = struct.pack('<B', 2)
        groups = b''
        for i in range(2):
            groups += struct.pack('<B', 1)
            groups += struct.pack('<B', 1)
            groups += struct.pack('<B', 1)

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = command_status + request_set_flag + channel_no + group_num + groups
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def make_image_take_manual(self):
        """C.7.3 手动请求拍摄照片"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x04控制报文
        frame_type = struct.pack("<s",b'\x04')
        #报文类型->0xCB
        ptype= struct.pack("<s",b'\xCB')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        command_status = struct.pack('<B', 0xFF)
        

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = command_status
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_request_image_pack(self,frame_no=0x01,channel_no=0x01,presetting_no=0x01,packt_no=0x01):
        b_frame = b''
        header = struct.pack('<H',23205)
        
        device_id = struct.pack("<17s",b"00000000000000002")
        frame_type = struct.pack("<s",b'\x05')
        ptype= struct.pack("<s",b'\xCC')
        frame_no = struct.pack("<B",frame_no)

        #数据段
        channel_no = struct.pack("<B",channel_no)
        presetting_no = struct.pack("<B",presetting_no)
        packt_no_hi = struct.pack("<H",packt_no)[0]
        packt_no_lo = struct.pack("<H",packt_no)[1]


        content = channel_no + presetting_no+packt_no_hi.to_bytes() + packt_no_lo.to_bytes()
        data_len = struct.pack("<H",len(content))
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def image_send(self,):

        # 创建socket对象
        client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        # 服务器地址端口
        dest_addr = ('0.0.0.0', 50001)
        # 发送数据
        with open("pic.jpg", "rb") as f:
            image_data = f.read()

        chunk_size = 1024 # 每个数据包大小
        n_chunks = len(image_data) // chunk_size
        frame_img_request = gen_request_image_pack(1,1,1,n_chunks)
        client_socket.sendto(frame_img_request, dest_addr)
        data = client_socket.recv(1024)
        print("data",data)
        pack_dict = {}
        for i in range(0,n_chunks):
            
            chunk = image_data[i * chunk_size: (i + 1) * chunk_size]
            pack_dict[i] = chunk
            
            frame = gen_image_pack(chunk,i+1,1,1,n_chunks,i)
            client_socket.sendto(frame, dest_addr)
        img_end = gen_image_end_pack(n_chunks,1,1,1700000000)
        client_socket.sendto(img_end, dest_addr)
        # 接收数据
        data = client_socket.recv(1024)
        sum = struct.unpack('<H',data[26:28])[0]
        frame_type = data[21]
        ptype = data[22]
        ssue_pack_no_list = []
        print('ptype',ptype)
        if ptype == 0xCF:
            offset = 28
            if len(data) > 33:
                for i in range(sum):
                    no = struct.unpack('<H',data[offset:offset+2])[0]
                    print(no)
                    ssue_pack_no_list.append(no)
                    offset += 2
        for pack_no in ssue_pack_no_list:
            frame = gen_image_pack(pack_dict[pack_no],pack_no,1,1,n_chunks,pack_no)
            client_socket.sendto(frame, dest_addr)
        img_end = gen_image_end_pack(n_chunks,1,1,1700000000)
        client_socket.sendto(img_end, dest_addr)
        # 关闭连接
        client_socket.close()
    
    def gen_image_end_pack(self,frame_no,channel_no,presetting_no,timestamp):
        b_frame = b''
        header = struct.pack('<H',23205)
        
        device_id = struct.pack("<17s",b"00000000000000001")
        frame_type = struct.pack("<s",b'\x05')
        ptype= struct.pack("<s",b'\xCE')
        frame_no = struct.pack("<B",frame_no)
        channel_no = struct.pack("<B",channel_no)
        presetting_no = struct.pack("<B",presetting_no)
        timestamp = struct.pack("<I",timestamp)
        content = channel_no + presetting_no + timestamp
        data_len = struct.pack("<H",len(content))
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_camera_remote_ajust(self):
        """C.7.8 摄像机远程调节"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x08图像控制响应报文
        frame_type = struct.pack("<s",b'\x08')
        #报文类型->0xD0
        ptype= struct.pack("<s",b'\xD0')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        command_status = struct.pack('<B', 0xFF)
        

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = command_status
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def parse_camera_upload_video(self):
        """C.7.9 启动终止摄像视频传输"""
        b_frame = b''
        return b_frame

    def make_camera_time_table(self):
        """C.7.10 摄像机定时工作时间表"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x08')
        #报文类型->0xD5
        ptype= struct.pack("<s",b'\xD5')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        command_status = struct.pack('<B', 0xFF)
        request_set_flag = struct.pack('<B',1)
        t_b = b''
        time_list = [{'start_time':1700000000,'end_time':1700000001},{'start_time':1700000002,'end_time':1700000004},{'start_time':1700000005,'end_time':1700000006},{'start_time':1700000007,'end_time':1700000009}]
        for t in time_list:
            t_b += struct.pack('<f',t['start_time'])
            t_b += struct.pack('<f',t['end_time'])
        

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = command_status + request_set_flag + t_b
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_cmd_heartbeat(self):
        """C.8.1 心跳"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x09')
        #报文类型->0xE6
        ptype= struct.pack("<s",b'\xE6')
        frame_no = struct.pack("<s",b'\x01')

        #数据段

        cloctime_stamp = struct.pack("<f",time.time())
        

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = cloctime_stamp
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_cmd_base_info(self):
        """C.8.2 基本信息报"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x09工作状态报文
        frame_type = struct.pack("<s",b'\x09')
        #报文类型->0xE7
        ptype= struct.pack("<s",b'\xE7')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        smartquip_name = struct.pack('<50s', b'sfsfafs')
        model = struct.pack('<10s', b'sdffd')
        data_trans_protocol_version = struct.pack('<4s', b'sdfd')
        essential_info_version = struct.pack('<4s', b'sdfs')
        bs_manufacture = struct.pack('<50s', b'sdf')
        bs_production_date = struct.pack('<4s', b'sdfd')
        bs_identifier = struct.pack('<20s', b'ererere')
        

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = smartquip_name + model + data_trans_protocol_version + essential_info_version + bs_manufacture + bs_production_date + bs_identifier
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_cmd_work_state(self):
        """C.8.3 工作状态报"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x09工作状态报文
        frame_type = struct.pack("<s",b'\x09')
        #报文类型->0xE8
        ptype= struct.pack("<s",b'\xE8')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        time_stamp = struct.pack('<f', 1700000000)
        operation_temperature = struct.pack('<f', 3.3)
        battery_capacity = struct.pack('<f', 2.3)
        floating_charge = struct.pack('<B', 1)
        total_working_time = struct.pack('<I', 3)
        working_time = struct.pack('<I', 3)
        connection_state = struct.pack('<B', 1)
        

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = time_stamp + operation_temperature + battery_capacity + floating_charge + total_working_time + working_time + connection_state
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_cmd_err_info(self):
        """C.8.4 故障信息报"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        device_id = struct.pack("<17s",b'00000000000000001')
        #帧类型->0x09工作状态报文
        frame_type = struct.pack("<s",b'\x09')
        #报文类型->0xE9
        ptype= struct.pack("<s",b'\xE9')
        frame_no = struct.pack("<s",b'\x01')

        #数据段
        time_stamp = struct.pack('<f', 1700000000)
        fault_desc = "故障描述".encode("utf-8")

        #data_len表示 frame_no以后,crc 以前的数据长度
        content = time_stamp + fault_desc
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    


    def parse_device_time(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.3 监测装置时间查询 解析设备的响应"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        cloctime_stamp = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        return {
            'type':'device_time',
            'command_status':command_status,
            'cloctime_stamp':cloctime_stamp,
        }
    
    def parse_device_netadapter(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.4 监测装置网络适配器查询"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_set_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        ip = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        subnet_mask = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        gateway = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        dns_server = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        phone_number = struct.unpack('<20s', raw[offset:offset+20])[0]; offset += 20
        return {
            'type':'device_netadapter',
            'command_status':command_status,
            'request_set_flag':request_set_flag,
            'request_flag':request_flag,
            'ip':ip,
            'subnet_mask':subnet_mask,
            'gateway':gateway,
            'dns_server':dns_server,
            'phone_number':phone_number,
        }
    
    def parse_mainsite_request(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.5 主站系统请求数据"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_type = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        return {
            'type':'mainsite_request',
            'command_status':command_status,
            'request_type':request_type,
        }
    
    def parse_collect_params(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.6 采样参数设置"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_type = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        main_time = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        sample_count = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        sample_frequency = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        heartbeat_time = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        return {
            'type':'mainsite_request',
            'command_status':command_status,
            'request_type':request_type,
            'request_flag':request_flag,
            'main_time':main_time,
            'sample_count':sample_count,
            'sample_frequency':sample_frequency,
            'heartbeat_time':heartbeat_time,
        }
    
    def parse_model_params(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.7 模型参数查询/设置"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_set_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        config_total = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        configs = []
        for i in range(config_total):
            config = {}
            config['config_name'] = struct.unpack('<6s', raw[offset:offset+6])[0]; offset += 6
            config['config_datatype'] = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
            config['config_data'] = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
            configs.append(config)

        return {
            'type':'model_params',
            'command_status':command_status,
            'request_set_flag':request_set_flag,
            'config_total':config_total,
            'configs':configs,
        }
    
    def parse_alarm_thresholds(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.8 报警阈值查询/设置"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_type = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        alarm_total = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        thresholds = {}
        for i in range(alarm_total):
            key = struct.unpack('<6s', raw[offset:offset+6])[0]; offset += 6
            value = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
            thresholds[key] = value

        return {
            'type':'alarm_thresholds',
            'command_status':command_status,
            'request_type':request_type,
            'alarm_total':alarm_total,
            'threshods':threshods,
        }
    
    def parse_device_direct(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.9 监测装置指向信息查询/设置"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        ip_address = struct.unpack('<4s', raw[offset:offset+4])[0]; offset += 4
        port = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        domain_name = struct.unpack('<64s', raw[offset:offset+64])[0]; offset += 64
        

        return {
            'type':'device_direct',
            'command_status':command_status,
            'request_flag':request_flag,
            'ip_address':ip_address,
            'port':port,
            'domain_name':domain_name,
        }
    
    def parse_control_base_info(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.10 基本信息查询/设置"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_type = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        info_type = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1

        return {
            'type':'base_info',
            'command_status':command_status,
            'request_type':request_type,
            'info_type':info_type,
        }
    
    def parse_remote_upgrade(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.11.3 软件数据报补包上传"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        file_name = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        complementpack_sum = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        
        complementpack_no = []
        for i in range(complementpack_sum):
            complementpack_no.append(struct.unpack('<I', raw[offset:offset+4])[0])
            offset += 4

        return {
            'type':'remote_upgrade',
            'command_status':command_status,
            'file_name':file_name,
            'complementpack_sum':complementpack_sum,
            'complementpack_no':complementpack_no,
        }
    
    def parse_remote_upgrade_finished(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.11.3 软件数据报补包上传"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        file_name = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        complementpack_sum = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        
        complementpack_no = []
        for i in range(complementpack_sum):
            complementpack_no.append(struct.unpack('<I', raw[offset:offset+4])[0])
            offset += 4

        return {
            'type':'remote_upgrade',
            'command_status':command_status,
            'file_name':file_name,
            'complementpack_sum':complementpack_sum,
            'complementpack_no':complementpack_no,
        }
    
    def parse_cmd_id(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.12 监测装置编码设置/查询"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        new_cmd_id = struct.unpack('<17s', raw[offset:offset+17])[0]; offset += 17
        component_id = struct.unpack('<17s', raw[offset:offset+17])[0]; offset += 17
        original_id = struct.unpack('<2s', raw[offset:offset+1])[0]; offset += 2

        return {
            'type':'cmd_id',
            'command_status':command_status,
            'request_flag':request_flag,
            'new_cmd_id':new_cmd_id,
            'component_id':component_id,
            'original_id':original_id,
        }
    
    def parse_cmd_reset(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.13 监测装置复位"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1

        return {
            'type':'cmd_reset',
            'command_status':command_status,
        }
    
    def parse_cmd_wake(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.14 监测装置苏醒"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1

        return {
            'type':'cmd_reset',
            'command_status':command_status,
        }
    
    def parse_image_collect_params(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.7.1 图像采集参数设置"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_set_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        color_select = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        resolution = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        luminance = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        contrast = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        saturation = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        return {
            'type':'image_collect_params',
            'command_status':command_status,
            'request_set_flag':request_set_flag,
            'request_flag':request_flag,
            'color_select':color_select,
            'resolution':resolution,
            'luminance':luminance,
            'contrast':contrast,
            'saturation':saturation,
        }
    
    def parse_image_time_table(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.7.2 拍照时间表设置"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_set_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        channel_no = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        group_num = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        groups = []
        for i in range(group_num):
            group = {}
            group['hour'] = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
            group['minute'] = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
            group['presetting_no'] = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
            groups.append(group)
        
        return {
            'type':'image_collect_params',
            'command_status':command_status,
            'request_set_flag':request_set_flag,
            'channel_no':channel_no,
            'group_num':group_num,
            'groups':groups,
        }
    
    def parse_image_take_manual(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.7.3 手动请求拍摄照片"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1

        
        return {
            'type':'image_take_manual',
            'command_status':command_status,

        }
    
    def parse_camera_remote_adjust(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.7.8 摄像机远程调节"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        
        
        return {
            'type':'camera_remote_adjust',
            'command_status':command_status,

        }
    
    def parse_camera_time_table(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.7.10 摄像机时间表"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        start_time1 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        end_time1 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        start_time2 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        end_time2 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        start_time3 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        end_time3 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        start_time4 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        end_time4 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        
        
        return {
            'type':'camera_time_table',
            'command_status':command_status,
            'start_time1':start_time1,
            'end_time1':end_time1,
            'start_time2':start_time2,
            'end_time2':end_time2,
            'start_time3':start_time3,
            'end_time3':end_time3,
            'start_time4':start_time4,
            'end_time4':end_time4,

        }

    #解包函数,解析通用字段,数据段根据报文类型由专门的解析函数处理
    def parse_frame(self,raw: bytes):
        """返回 dict 或 None"""
        header = struct.unpack("<2s",raw[:2])[0]
        if len(raw) < 10 or raw[:2] != SYNC_HEAD or raw[-1] != SYNC_TAIL:
            print("tail matters")
            return None
        pkt_len = struct.unpack('<H', raw[2:4])[0]
        if len(raw) < 22+pkt_len:
            print("package len  matters")
            return None
        payload = raw[2: 2+ 22 +pkt_len]
        if crc16(payload) != struct.unpack('<H', raw[-3:-1])[0]:
            print("crc matters")
            return None
        cmd_id = raw[4:21].decode()
        frame_type = raw[21]
        ptype = raw[22]
        seq = raw[23]
        content = raw[24:]
        #if frame_type != FRAME_TYPE_DATA:
        #    return None
        print("ptype:",ptype)
        parser = getattr(self,self.PARSER_MAP.get(ptype))
        if not parser:
            return None
        try:
            return parser(cmd_id, seq, raw, 24)
        except Exception as e:
            return None

    def run(self):
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        dest_addr = ('0.0.0.0', 50001)
        for attr in dir(self):
            if attr.startswith("make_"):
                func = getattr(self,attr)
                frame = func()
                print("fuc:",func)
                print("frame:",frame)
                time.sleep(1)
                sock.sendto(frame, dest_addr)
                break
                
        while True:
            data = sock.recv(1024)
            res = self.parse_frame(data)
            print("client parse:",res)


#通用封包
def gen_pack():
    #封包
    content = ice_data_pack()
    print(content,len(content))
    b_frame = b''
    header = struct.pack('<2s',b'\x5A\xA5')
    data_len = struct.pack("<H",len(content))
    device_id = struct.pack("<17s",b"00000000000000001")
    frame_type = struct.pack("<s",b'\x01')
    ptype= struct.pack("<s",b'\x22')
    frame_no = struct.pack("<s",b'\x01')
    content = content
    payload = data_len + device_id + frame_type + ptype + frame_no + content
    crc = crc16(payload)
    crc_b = struct.pack('<H',crc)
    b_frame = header + payload + crc_b + b'\x96'
    parse_frame(b_frame)



def gen_request_image_pack(frame_no,channel_no,presetting_no,packt_no):
    b_frame = b''
    header = struct.pack('<H',23205)
    
    device_id = struct.pack("<17s",b"00000000000000001")
    frame_type = struct.pack("<s",b'\x05')
    ptype= struct.pack("<s",b'\xCC')
    frame_no = struct.pack("<B",frame_no)
    channel_no = struct.pack("<B",channel_no)
    presetting_no = struct.pack("<B",presetting_no)
    packt_no_hi = struct.pack("<H",packt_no)[0]
    packt_no_lo = struct.pack("<H",packt_no)[1]
    content = channel_no + presetting_no+packt_no_hi.to_bytes() + packt_no_lo.to_bytes()
    data_len = struct.pack("<H",len(content))
    payload = data_len + device_id + frame_type + ptype + frame_no + content
    crc = crc16(payload)
    crc_b = struct.pack('<H',crc)
    b_frame = header + payload + crc_b + b'\x96'
    return b_frame


def gen_image_pack(img_bytes,frame_no,channel_no,presetting_no,packt_no,subpacket_no):
    b_frame = b''
    header = struct.pack('<H',23205)
    
    device_id = struct.pack("<17s",b"00000000000000001")
    frame_type = struct.pack("<s",b'\x05')
    ptype= struct.pack("<s",b'\xCD')
    frame_no = struct.pack("<B",frame_no)
    channel_no = struct.pack("<B",channel_no)
    presetting_no = struct.pack("<B",presetting_no)
    packt_no = struct.pack("<H",packt_no)
    subpacket_no = struct.pack("<H",subpacket_no)
    content = channel_no + presetting_no+packt_no + subpacket_no + img_bytes
    data_len = struct.pack("<H",len(content))
    payload = data_len + device_id + frame_type + ptype + frame_no + content
    crc = crc16(payload)
    crc_b = struct.pack('<H',crc)
    b_frame = header + payload + crc_b + b'\x96'
    return b_frame


def gen_image_end_pack(frame_no,channel_no,presetting_no,timestamp):
    b_frame = b''
    header = struct.pack('<H',23205)
    
    device_id = struct.pack("<17s",b"00000000000000001")
    frame_type = struct.pack("<s",b'\x05')
    ptype= struct.pack("<s",b'\xCE')
    frame_no = struct.pack("<B",frame_no)
    channel_no = struct.pack("<B",channel_no)
    presetting_no = struct.pack("<B",presetting_no)
    timestamp = struct.pack("<I",timestamp)
    content = channel_no + presetting_no + timestamp
    data_len = struct.pack("<H",len(content))
    payload = data_len + device_id + frame_type + ptype + frame_no + content
    crc = crc16(payload)
    crc_b = struct.pack('<H',crc)
    b_frame = header + payload + crc_b + b'\x96'
    return b_frame


def append_image_data():
    import os
    if os.path.exists("pic2.jpg"):
        os.remove("/pic2.jpg")
    pic = open("pic.jpg",'rb').read()
    a = pic[:10]
    b = pic[10:]
    f = open("pic2.jpg",'ab')
    f.write(a)
    f.close()
    f = open("pic2.jpg",'ab')
    f.write(b)
    f.close()

def clear_image():
    import os
    if os.path.exists("00000000000000002_1.jpg"):
        os.remove("00000000000000002_1.jpg")

def image_send():

    # 创建socket对象
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 服务器地址端口
    dest_addr = ('0.0.0.0', 50001)
    # 发送数据
    with open("pic.jpg", "rb") as f:
        image_data = f.read()

    chunk_size = 1024 # 每个数据包大小
    n_chunks = len(image_data) // chunk_size
    frame_img_request = gen_request_image_pack(1,1,1,n_chunks)
    client_socket.sendto(frame_img_request, dest_addr)
    data = client_socket.recv(1024)
    print("data",data)
    pack_dict = {}
    for i in range(0,n_chunks):
        
        chunk = image_data[i * chunk_size: (i + 1) * chunk_size]
        pack_dict[i] = chunk
        
        frame = gen_image_pack(chunk,i+1,1,1,n_chunks,i)
        client_socket.sendto(frame, dest_addr)
    img_end = gen_image_end_pack(n_chunks,1,1,1700000000)
    client_socket.sendto(img_end, dest_addr)
    # 接收数据
    data = client_socket.recv(1024)
    '''sum = struct.unpack('<H',data[26:28])[0]
    frame_type = data[21]
    ptype = data[22]
    ssue_pack_no_list = []
    print('ptype',ptype)
    if ptype == 0xCF:
        offset = 28
        if len(data) > 33:
            for i in range(sum):
                no = struct.unpack('<H',data[offset:offset+2])[0]
                print(no)
                ssue_pack_no_list.append(no)
                offset += 2
    for pack_no in ssue_pack_no_list:
        frame = gen_image_pack(pack_dict[pack_no],pack_no,1,1,n_chunks,pack_no)
        client_socket.sendto(frame, dest_addr)
    img_end = gen_image_end_pack(n_chunks,1,1,1700000000)
    client_socket.sendto(img_end, dest_addr)'''
    # 关闭连接
    client_socket.close()


def client_main():
    c = I1Client()
    c.start()

if __name__ == '__main__':
    c = I1Client()
    c.start()

server端

python 复制代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Q/GDW 1242-2015 全数据报解析服务端
支持:气象/覆冰/舞动特征量/舞动轨迹/远程图像数据报
"""
import socket
import struct
import time
import logging
import io
import os
from common import *
from threading import Thread
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s %(levelname)s %(message)s')

class I1Server(Thread):

    def __init__(self):
        super().__init__()
        self.image_pack_no_list = []
        self.image_total_pack = 0
        self.image_pack_dict = {}
        self.image_ssue_list = []
        self.cmd_id = ""
        self.channel_no = 0 
        #解析函数映射
        self.PARSER_MAP = {
            PTYPE_WEATHER:      'parse_weather',
            PTYPE_ICE:          'parse_ice',
            PTYPE_GALLOP_CHAR:  'parse_gallop_char',
            PTYPE_GALLOP_TRACK: 'parse_gallop_track',
            PTYPE_TOWER_TILT: 'parse_tower_tilt',
            PTYPE_FILTH: 'parse_filth',
            PTYPE_BREEZE_FLUTTER: 'parse_breeze_flutter',
            PTYPE_BREEZE_WAVEFORM: 'parse_breeze_waveform',
            PTYPE_WIRE_TEMP: 'parse_wire_temp',
            PTYPE_WIRE_RADIAN: 'parse_wire_radian',
            PTYPE_WIRE_YAW: 'parse_wire_yaw',
            PTYPE_DEVICE_TIME: 'parse_device_time',
            PTYPE_DEVICE_NETADAPTER: 'parse_device_netadapter',
            PTYPE_MAINSITE_REQUEST: 'parse_mainsite_request',
            PTYPE_COLLECT_PARAMS: 'parse_collect_params',
            PTYPE_MODEL_PARAMS: 'parse_model_params',
            PTYPE_ALARM_THRESHOLDS: 'parse_alarm_thresholds',
            PTYPE_DEVICE_DIRECT: 'parse_device_direct',
            PTYPE_CONTROL_BASE_INFO: 'parse_control_base_info',
            PTYPE_REMOTE_UPGRADE__SSUE: 'parse_remote_upgrade',
            PTYPE_CMD_ID: 'parse_cmd_id',
            PTYPE_CMD_RESET: 'parse_cmd_reset',
            PTYPE_CMD_WAKE: 'parse_cmd_wake',
            PTYPE_WEATHER_PARAMS: 'parse_weather_params',
            PTYPE_TOWER_TILT_PARAMS: 'parse_tower_tilt_params',
            PTYPE_BREEZE_FLUTTER_PARAMS: 'parse_breeze_flutter_params',
            PTYPE_WIRE_RADIAN_PARAMS: 'parse_wire_radian_params',
            PTYPE_WIRE_TEMP_PARAMS: 'parse_wire_temp_params',
            PTYPE_ICE_PARAMS: 'parse_ice_params',
            PTYPE_WIRE_YAW_PARAMS: 'parse_wire_yaw_params',
            PTYPE_GALLOP_CHAR_PARAMS: 'parse_gallop_char_params',
            PTYPE_FILTH_PARAMS: 'parse_filth_params',
            PTYPE_IMAGE_COLLECT_PARAMS: 'parse_image_collect_params',
            PTYPE_IMAGE_TIME_TABLE: 'parse_image_time_table',
            PTYPE_IMAGE_TAKE_MANUAL: 'parse_image_take_manual',
            PTYPE_REQUEST_IMAGE_DATA:   'parse_request_image_data',
            PTYPE_IMAGE_DATA:   'parse_image_data',
            PTYPE_IMAGE_END_DATA:   'parse_image_end_data',
            PTYPE_CAMERA_REMOTE_ADJUST: 'parse_camera_remote_adjust',
            PTYPE_CAMERA_UPLOAD_VIDEO: 'parse_camera_upload_video',
            PTYPE_CMD_SAVE_ADRESS: 'parse_cmd_save_address',
            PTYPE_STOP_CONNECT: 'parse_stop_connect',
            PTYPE_CAMERA_BASE_INFO: 'parse_camera_base_info',
            PTYPE_CAMERA_TIME_TABLE: 'parse_camera_time_table',
            PTYPE_CMD_HEARTBEAT: 'parse_cmd_heartbeat',
            PTYPE_CMD_BASE_INFO: 'parse_cmd_base_info',
            PTYPE_CMD_WORK_STATE: 'parse_cmd_work_state',
            PTYPE_CMD_ERR_INFO: 'parse_cmd_err_info',
            PTYPE_CUSTOM_DATA:  'parse_custom_data',
        }

    # -------------------- 通用封包 --------------------
    def make_monitor_resp_frame(self,cmd_id: str, seq: int, ptype: int) -> bytes:
        """构造数据响应报(帧类型 0x02)"""
        payload = struct.pack('<H', 17+6) + cmd_id.encode() + bytes([FRAME_TYPE_RESP, ptype, seq, 0xFF])
        crc = crc16(payload)
        return SYNC_HEAD + payload + struct.pack('<H', crc) + bytes([SYNC_TAIL])
    
    def make_image_resp_frame(self,cmd_id: str, seq: int, ptype: int) -> bytes:
        if ptype == 0xCC:
            return 

    # -------------------- 解析函数群 --------------------
    def parse_weather(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.5.1 气象监测数据报"""
        comp_id = raw[offset:offset+17].decode(); offset += 17
        ts = struct.unpack('<I', raw[offset:offset+4]); offset += 4
        avg_ws   = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        avg_wd   = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        max_ws = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        extreme_ws = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        standard_ws = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        temp     = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        hum      = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        pres     = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        precipitaton     = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        precipitaton_intensity     = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        radiation_intensity     = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        return {
            'type': 'weather',
            'comp_id': comp_id, 
            'ts': ts, 
            'avg_ws': avg_ws, 
            'avg_wd': avg_wd, 
            'max_ws': max_ws, 
            'extreme_ws': extreme_ws, 
            'standard_ws': standard_ws, 
            'temp': temp, 
            'hum': hum, 
            'pres': pres, 
            'precipitaton': precipitaton, 
            'precipitaton_intensity': precipitaton_intensity, 
            'radiation_intensity': radiation_intensity, 
        }
    

    def parse_filth(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.5.2 现场污秽数据报"""
        comp_id = raw[offset:offset+17].decode(); offset += 17
        ts = struct.unpack('<f', raw[offset:offset+4]); offset += 4
        esdd   = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        nsdd   = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        daily_max_temp = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        daily_min_temp = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        daily_max_hum = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        daily_min_hum = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        return {
            'type': 'filth',
            'comp_id': comp_id, 
            'ts': ts, 
            'esdd': esdd, 
            'nsdd': nsdd, 
            'daily_max_temp': daily_max_temp, 
            'daily_min_temp': daily_min_temp, 
            'daily_max_hum': daily_max_hum, 
            'daily_min_hum': daily_min_hum, 
        }

    def parse_ice(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.5.3 覆冰监测数据报"""
        comp_id = raw[offset:offset+17].decode(); offset += 17
        time_stamp = struct.unpack('<I', raw[offset:offset+4]); offset += 4
        eq_icethickness = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        tension  = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        tension_difference  = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        t_sensor_num  = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        t_sensor_list = []
        for i in range(t_sensor_num):
            ts = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
            crossa = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
            forwarda = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
            t_sensor_list.append({'tension':ts,'crosswise_angle':crossa,'forward_tilt_angle':forwarda})

        instantaneous_windspeed  = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        instantaneous_winddirection  = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        air_temperature  = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        humidity  = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        
        ret = {
            'type': 'ice', 
            'comp_id': comp_id, 
            'time_stamp': time_stamp, 
            'eq_icethickness': eq_icethickness,
            'tension': tension, 
            'tension_difference': tension_difference, 
            't_sensor_num': t_sensor_num, 
            't_sensor_list': t_sensor_list, 
            'instantaneous_windspeed': instantaneous_windspeed,
            'instantaneous_winddirection': instantaneous_winddirection,
            'air_temperature': air_temperature,
            'humidity': humidity,
        }
        print(ret)
        return ret

    def parse_breeze_flutter(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C5.4.1 微风振动特征量数据报"""
        comp_id = raw[offset:offset+17].decode(); offset += 17
        unit_sum = struct.unpack('<B', raw[offset:offset+1]); offset += 1
        unit_no  = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        ts = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        strain_amplitude = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        bending_amplitude = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        vibration_frequency = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        return {
            'type': 'breeze_flutter', 
            'comp_id': comp_id, 
            'unit_sum': unit_sum, 
            'unit_no': unit_no,
            'ts': ts, 
            'strain_amplitude': strain_amplitude, 
            'bending_amplitude': bending_amplitude, 
            'vibration_frequency': vibration_frequency, 
        }
    
    def parse_breeze_waveform(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.5.4.2 微风振动波形信号数据报"""
        comp_id = raw[offset:offset+17].decode(); offset += 17
        unit_sum = struct.unpack('<B', raw[offset:offset+1]); offset += 1
        unit_no  = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        ts = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        samplepack_sum = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        samplepack_no = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        strain_data = []
        while offset + 2 < len(raw)-3:
            strain_data.append(struct.unpack('<H', raw[offset:offset+2])[0])
            offset += 2
        return {
            'type': 'breeze_waveform', 
            'comp_id': comp_id, 
            'unit_sum': unit_sum, 
            'unit_no': unit_no,
            'ts': ts, 
            'samplepack_sum': samplepack_sum, 
            'samplepack_no': samplepack_no, 
            'strain_data': strain_data, 
        }

    def parse_gallop_char(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.5.5.1 导线舞动特征量数据报"""
        comp_id = raw[offset:offset+17].decode(); offset += 17
        unit_sum = raw[offset]; offset += 1
        unit_no  = raw[offset]; offset += 1
        ts = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        u_gallop_amplitude = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        u_vertical_amplitude = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        u_horizontal_amplitude = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        u_angle_vertical = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        u_gallop_frequency = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4

        return {
            'type': 'gallop_char',
            'comp_id': comp_id,
            'unit_sum': unit_sum,
            'unit_no': unit_no,
            'ts': ts,
            'u_gallop_amplitude': u_gallop_amplitude,
            'u_vertical_amplitude': u_vertical_amplitude,
            'u_horizontal_amplitude': u_horizontal_amplitude,
            'u_angle_vertical': u_angle_vertical,
            'u_gallop_frequency': u_gallop_frequency,
        }

    def parse_gallop_track(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.5.5.2 导线舞动轨迹数据报"""
        comp_id = raw[offset:offset+17].decode(); offset += 17
        
        unit_sum = raw[offset]; offset += 1
        unit_no  = raw[offset]; offset += 1
        ts, = struct.unpack('<I', raw[offset:offset+4]); offset += 4
        pack_sum = raw[offset]; offset += 1
        pack_no  = raw[offset]; offset += 1
        displacement = []
        while offset+12 < (len(raw)-3):
            x = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
            y = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
            z = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
            displacement.append([x,y,z])         # 剩余全是位移点
        pts = len(sample_bytes) // 12

        return {
            'type': 'gallop_track',
            'comp_id': comp_id,
            'unit_sum': unit_sum,
            'unit_no': unit_no,
            'ts': ts,
            'pack_sum': u_gallop_amplitude,
            'pack_no': u_vertical_amplitude,
            'displacement': u_horizontal_amplitude,
        }
    def gallop_track_pack_count(self):
        pass

    def gallop_grack_pack_merge(self):
        pass

    def parse_wire_temp(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.5.6 导线温度数据报"""
        comp_id = raw[offset:offset+17].decode(); offset += 17
        unit_sum = raw[offset]; offset += 1
        unit_no  = raw[offset]; offset += 1
        ts = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        line_temp1 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        line_temp2 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4

        return {
            'type': 'wire_temp',
            'comp_id': comp_id,
            'unit_sum': unit_sum,
            'unit_no': unit_no,
            'ts': ts,
            'line_temp1': line_temp1,
            'line_temp2': line_temp2,

        }

    def parse_wire_radian(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C5.7 导线弧垂数据报"""
        comp_id = raw[offset:offset+17].decode(); offset += 17
        ts = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        conductor_sag = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        toground_distance = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        angle = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        measure_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1

        return {
            'type': 'wire_radian',
            'comp_id': comp_id,
            'ts': ts,
            'conductor_sag': conductor_sag,
            'toground_distance': toground_distance,
            'angle': angle,
            'measure_flag': measure_flag,
        }
    
    def parse_wire_yaw(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.5.8 导线风偏数据报"""
        comp_id = raw[offset:offset+17].decode(); offset += 17
        ts = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        windage_yaw_angle = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        deflection_angle = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        least_clearance = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4

        return {
            'type': 'wire_yaw',
            'comp_id': comp_id,
            'ts': ts,
            'windage_yaw_angle': conductor_sag,
            'deflection_angle': toground_distance,
            'least_clearance': angle,
        }
    

    
    def parse_tower_tilt(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.5.9 塔杆倾斜数据报"""
        comp_id = raw[offset:offset+17].decode(); offset += 17
        ts = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        inclination = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        inclination_x = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        inclination_y = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        angle_x = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        angle_y = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4

        return {
            'type': 'tower_tilt',
            'comp_id': comp_id,
            'ts': ts,
            'inclination': inclination,
            'inclination_x': inclination_x,
            'inclination_y': inclination_y,
            'angle_x': inclination_y,
            'angle_y': inclination_y,
        }

    #----------------    
    #  C.6 控制报文
    #----------------
    def make_device_time(self,cmd_id: str, request_set_flag,clocktime_stamp):
        """C.6.3 监测装置时间查询 发送给设备"""
        header = struct.pack('<H',23205)
        data_len = struct.pack("<H",5)
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA1
        ptype= struct.pack("<s",b'\xA1')
        frame_no = struct.pack("<s",b'\x01')
        request_set_flag = struct.pack('<B',request_set_flag)
        clocktime_stamp = struct.pack('<f',clocktime_stamp)
        content = request_set_flag + clocktime_stamp
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    

    def parse_device_time(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.3 监测装置时间查询 解析设备的响应"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        cloctime_stamp = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        return {
            'type':'device_time',
            'command_status':command_status,
            'cloctime_stamp':cloctime_stamp,
        }
    


    def make_device_netadapter(self,cmd_id: str, request_set_flag,request_flag,ip,subnet_mask,gateway,dns_server,phone_number):
        """C.6.4 监测装置网络适配器查询 发送给设备"""
        header = struct.pack('<H',23205)
        data_len = struct.pack("<H",38)
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xA2')
        frame_no = struct.pack("<s",b'\x01')
        
        #0x00表示查询,0x01表示设置
        request_set_flag = struct.pack('<B',request_set_flag)
        request_flag = struct.pack('<B',request_flag)
        ip = struct.pack('<4s',socket.inet_aton(ip))
        subnet_mask = struct.pack('<4s',socket.inet_aton(subnet_mask))
        gateway = struct.pack('<4s',socket.inet_aton(gateway))
        dns_server = struct.pack('<4s',socket.inet_aton(dns_server))
        phone_number = struct.pack('<20s',phone_number)
        content = request_set_flag + request_flag + ip + subnet_mask + gateway + dns_server + phone_number
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def parse_device_netadapter(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.4 监测装置网络适配器查询"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_set_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        ip = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        subnet_mask = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        gateway = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        dns_server = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        phone_number = struct.unpack('<20s', raw[offset:offset+20])[0]; offset += 20
        return {
            'type':'device_netadapter',
            'command_status':command_status,
            'request_set_flag':request_set_flag,
            'request_flag':request_flag,
            'ip':ip,
            'subnet_mask':subnet_mask,
            'gateway':gateway,
            'dns_server':dns_server,
            'phone_number':phone_number,
        }

    def make_mainsite_request(self,cmd_id: str, request_type,data_start_time,data_end_time):
        """C.6.5 主站系统请求数据 发送给设备"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",9)
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xA3')
        frame_no = struct.pack("<s",b'\x01')

        #0x00表示查询,0x01表示设置
        request_type = struct.pack('<B',request_type)
        data_start_time = struct.pack('<f',data_start_time)
        data_end_time = struct.pack('<f',socket.data_end_time(ip))
        content = request_type + data_start_time + data_end_time
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def parse_mainsite_request(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.5 主站系统请求数据"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_type = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        return {
            'type':'mainsite_request',
            'command_status':command_status,
            'request_type':request_type,
        }
    


    def make_collect_params(self,cmd_id: str, request_set_flag,request_type,request_flag,main_time,sample_count,sample_frequency,heartbeat_time):
        """C.6.6 采样参数设置 发送给设备"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",10)
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xA4')
        frame_no = struct.pack("<s",b'\x01')

        #0x00表示查询,0x01表示设置
        request_set_flag = struct.pack('<B',request_set_flag)
        request_type = struct.pack('<B',request_type)
        request_flag = struct.pack('<B',request_flag)
        main_time = struct.pack('<H',main_time)
        sample_count = struct.pack('<H',sample_count)
        sample_frequency = struct.pack('<H',sample_frequency)
        heartbeat_time = struct.pack('<B',heartbeat_time)
        content = request_set_flag + request_type + request_flag+ main_time + sample_count + sample_frequency + heartbeat_time
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def parse_collect_params(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.6 采样参数设置"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_type = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        main_time = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        sample_count = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        sample_frequency = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        heartbeat_time = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        return {
            'type':'mainsite_request',
            'command_status':command_status,
            'request_type':request_type,
            'request_flag':request_flag,
            'main_time':main_time,
            'sample_count':sample_count,
            'sample_frequency':sample_frequency,
            'heartbeat_time':heartbeat_time,
        }
    

    def make_model_params(self,cmd_id: str, request_set_flag,config_total,configs):
        """C.6.7 模型参数查询/设置 发送给设备"""
        header = struct.pack('<H',23205)
        
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xA5')
        frame_no = struct.pack("<s",b'\x01')

        #0x00表示查询,0x01表示设置
        request_set_flag = struct.pack('<B',request_set_flag)
        config_total = struct.pack('<B',config_total)
        configs_b = b''
        for i in range(config_total):
            configs_b += struct.pack('<6s',configs['config_name'])
            configs_b += struct.pack('<B',configs['config_datatype'])
            if configs['config_datatype'] == 0x00 or configs['config_datatype'] == 0x01:
                configs_b += struct.pack('<I',configs['config_data'])
            else:
                configs_b += struct.pack('<f',configs['config_data'])
        content = request_set_flag + config_total + configs_b
        #data_len不固定,所以放到 content后面统计
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def parse_model_params(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.7 模型参数查询/设置"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_set_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        config_total = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        configs = []
        for i in range(config_total):
            config = {}
            config['config_name'] = struct.unpack('<6s', raw[offset:offset+6])[0]; offset += 6
            config['config_datatype'] = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
            config['config_data'] = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
            configs.append(config)

        return {
            'type':'model_params',
            'command_status':command_status,
            'request_set_flag':request_set_flag,
            'config_total':config_total,
            'configs':configs,
        }
    

    def make_alarm_thresholds(self,cmd_id: str, request_set_flag,request_type,alarm_total,alarm_para):
        """C.6.8 报警阈值查询/设置 发送给设备"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",9)
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xA6')
        frame_no = struct.pack("<s",b'\x01')

        #0x00表示查询,0x01表示设置
        request_set_flag = struct.pack('<B',request_set_flag)
        request_type = struct.pack('<B',request_type)
        alarm_total = struct.pack('<B',alarm_total)
        params_b = b''
        for key,value in alarm_para.items():
            params_b += struct.pack('<6s',key)
            params_b += struct.pack('<f',value)
            
        content = request_set_flag + request_type + alarm_total + params_b

        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def parse_alarm_thresholds(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.8 报警阈值查询/设置"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_type = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        alarm_total = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        thresholds = {}
        for i in range(config_total):
            key = struct.unpack('<6s', raw[offset:offset+6])[0]; offset += 6
            value = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
            thresholds[key] = value

        return {
            'type':'alarm_thresholds',
            'command_status':command_status,
            'request_type':request_type,
            'alarm_total':alarm_total,
            'threshods':threshods,
        }
    

    def make_device_direct(self,cmd_id: str, request_set_flag,request_flag,ip_address,port,domain_name):
        """C.6.9 监测装置指向信息查询/设置 发送给设备"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",9)
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xA7')
        frame_no = struct.pack("<s",b'\x01')

        #0x00表示查询,0x01表示设置
        request_set_flag = struct.pack('<B',request_set_flag)
        request_flag = struct.pack('<B',request_flag)
        ip_address = struct.pack('<4s',sockt.inet_aton(ip_address))
        port = struct.pack('<H',port)
        domain_name = struct.pack('<64s',domain_name)
            
        content = request_set_flag + request_flag + ip_address + port + domain_name

        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def parse_device_direct(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.9 监测装置指向信息查询/设置"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        ip_address = struct.unpack('<4s', raw[offset:offset+4])[0]; offset += 4
        port = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        domain_name = struct.unpack('<64s', raw[offset:offset+64])[0]; offset += 64
        

        return {
            'type':'device_direct',
            'command_status':command_status,
            'request_flag':request_flag,
            'ip_address':ip_address,
            'port':port,
            'domain_name':domain_name,
        }
    
    def parse_control_base_info(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        pass
    

    def make_base_info(self,cmd_id: str, request_set_flag,request_type,info_type):
        """C.6.10 基本信息查询/设置 发送给设备"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",9)
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xA8')
        frame_no = struct.pack("<s",b'\x01')

        #0x00表示查询,0x01表示设置
        request_set_flag = struct.pack('<B',request_set_flag)
        request_type = struct.pack('<B',request_type)
        info_type = struct.pack('<4s',info_type)
        content = request_set_flag + request_type + info_type

        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def parse_base_info(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.10 基本信息查询/设置"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_type = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        info_type = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1

        return {
            'type':'base_info',
            'command_status':command_status,
            'request_type':request_type,
            'info_type':info_type,
        }
    
    #---------------------
    #  C.6.11 远程升级数据报
    #---------------------

    def make_remote_upgrade(self,cmd_id: str, packet_no,subpacket_no,sample):
        """C.6.11.1 软件数据报 发送给设备"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",9)
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xA9')
        frame_no = struct.pack("<s",b'\x01')

        #0x00表示查询,0x01表示设置
        packet_no = struct.pack('<B',packet_no)
        subpacket_no = struct.pack('<B',subpacket_no)
        sample = struct.pack('<%ds' % len(sample),sample)
        content = packet_no + subpacket_no + sample

        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame
    
    def make_remote_upgrade_finished(self,cmd_id: str, file_name,packet_no,time_stamp):
        """C.6.11.2 软件数据下发结束标记 发送给设备"""
        header = struct.pack('<H',23205)
        
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xAA')
        frame_no = struct.pack("<s",b'\x01')

        #0x00表示查询,0x01表示设置
        file_name = struct.pack('<20s',file_name)
        packet_no = struct.pack('<I',packet_no)
        time_stamp = struct.pack('<f',time_stamp)
        content = file_name + packet_no + time_stamp

        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def parse_remote_upgrade(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.11.3 软件数据报补包上传"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        file_name = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        complementpack_sum = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        
        complementpack_no = []
        for i in range(complementpack_sum):
            complementpack_no.append(struct.unpack('<I', raw[offset:offset+4])[0])
            offset += 4

        return {
            'type':'remote_upgrade',
            'command_status':command_status,
            'file_name':file_name,
            'complementpack_sum':complementpack_sum,
            'complementpack_no':complementpack_no,
        }

    def make_cmd_id(self,cmd_id: str, request_set_flag,request_flag,new_cmd_id,component_id,original_id):
        """C.6.12 监测装置编码设置/查询 发送给设备"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",9)
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xAC')
        frame_no = struct.pack("<s",b'\x01')

        #0x00表示查询,0x01表示设置
        request_set_flag = struct.pack('<B',request_set_flag)
        request_flag = struct.pack('<B',request_flag)
        new_cmd_id = struct.pack('<17s',new_cmd_id)
        component_id = struct.pack('<17s',component_id)
        original_id = struct.pack('<17s',original_id)
        content = request_set_flag + request_flag + new_cmd_id + component_id + original_id

        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def parse_cmd_id(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.12 监测装置编码设置/查询"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        new_cmd_id = struct.unpack('<17s', raw[offset:offset+17])[0]; offset += 17
        component_id = struct.unpack('<17s', raw[offset:offset+17])[0]; offset += 17
        original_id = struct.unpack('<2s', raw[offset:offset+1])[0]; offset += 2

        return {
            'type':'cmd_id',
            'command_status':command_status,
            'request_flag':request_flag,
            'new_cmd_id':new_cmd_id,
            'component_id':component_id,
            'original_id':original_id,
        }
    

    def make_cmd_reset(self,cmd_id: str, reset_mode):
        """C.6.12 监测装置复位 发送给设备"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",9)
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xAD')
        frame_no = struct.pack("<s",b'\x01')

        #0x00表示查询,0x01表示设置
        reset_mode = struct.pack('<B',reset_mode)

        content = reset_mode

        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def parse_cmd_reset(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.13 监测装置复位"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1

        return {
            'type':'cmd_reset',
            'command_status':command_status,
        }
    
    def make_cmd_wake(self,cmd_id: str, reference_revival_time,revival_cycle,duration_time):
        """C.6.14 监测装置苏醒 发送给设备"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",9)
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xAE')
        frame_no = struct.pack("<s",b'\x01')

        #0x00表示查询,0x01表示设置
        reference_revival_time = struct.pack('<f',reference_revival_time)
        revival_cycle = struct.pack('<H',revival_cycle)
        duration_time = struct.pack('<H',duration_time)

        content = reference_revival_time + revival_cycle + duration_time

        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def parse_cmd_wake(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.6.14 监测装置苏醒"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1

        return {
            'type':'cmd_reset',
            'command_status':command_status,
        }

    def parse_weather_params(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        pass
    
    def parse_tower_tilt_params(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        pass
    
    def parse_breeze_flutter_params(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        pass
    

    def parse_wire_radian_params(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        pass
    
    def parse_wire_temp_params(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        pass
    
    def parse_ice_params(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        pass
    
    def parse_wire_yaw_params(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        pass
    
    def parse_gallop_char_params(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        pass
    
    def parse_filth_params(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        pass

    #----------------
    #  远程图像数据报文
    #----------------

    def make_image_collect_params(self,cmd_id: str, request_set_flag,request_flag,color_select,resolution,luminance,contrast,saturation):
        """C.7.1 图像采集参数设置 发送给设备"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",9)
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xC9')
        frame_no = struct.pack("<s",b'\x01')

        #0x00表示查询,0x01表示设置
        request_set_flag = struct.pack('<B',request_set_flag)
        request_flag = struct.pack('<B',request_flag)
        color_select = struct.pack('<B',color_select)
        resolution = struct.pack('<B',resolution)
        luminance = struct.pack('<B',luminance)
        contrast = struct.pack('<B',contrast)
        saturation = struct.pack('<B',saturation)
        content = request_set_flag + request_flag + color_select + resolution + luminance + contrast + saturation

        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def parse_image_collect_params(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.7.1 图像采集参数设置"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_set_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        color_select = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        resolution = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        luminance = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        contrast = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        saturation = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        return {
            'type':'image_collect_params',
            'command_status':command_status,
            'request_set_flag':request_set_flag,
            'request_flag':request_flag,
            'color_select':color_select,
            'resolution':resolution,
            'luminance':luminance,
            'contrast':contrast,
            'saturation':saturation,
        }
    

    def make_image_time_table(self,cmd_id: str, request_set_flag,channel_no,group_num,groups):
        """C.7.2 拍照时间表设置 发送给设备"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",9)
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xCA')
        frame_no = struct.pack("<s",b'\x01')

        #0x00表示查询,0x01表示设置
        request_set_flag = struct.pack('<B',request_set_flag)
        channel_no = struct.pack('<B',channel_no)
        group_num = struct.pack('<B',group_num)
        groups_b = b''
        for i in range(group_num):
            groups_b += struct.pack('<B',groups[i]['hour'])
            groups_b += struct.pack('<B',groups[i]['minute'])
            groups_b += struct.pack('<B',groups[i]['presetting_no'])
        content = request_set_flag + channel_no + group_num + groups_b

        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def parse_image_time_table(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.7.2 拍照时间表设置"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        request_set_flag = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        channel_no = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        group_num = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        groups = []
        for i in range(group_num):
            group = {}
            group['hour'] = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
            group['minute'] = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
            group['presetting_no'] = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
            groups.append(group)
        
        return {
            'type':'image_collect_params',
            'command_status':command_status,
            'request_set_flag':request_set_flag,
            'channel_no':channel_no,
            'group_num':group_num,
            'groups':groups,
        }
    
    def make_image_take_manual(self,cmd_id: str,channel_no,presetting_no):
        """C.7.3 手动请求拍摄照片 发送给设备"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",9)
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xCB')
        frame_no = struct.pack("<s",b'\x01')

        #0x00表示查询,0x01表示设置
        channel_no = struct.pack('<B',channel_no)
        presetting_no = struct.pack('<B',presetting_no)
        content = channel_no + presetting_no

        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def parse_image_take_manual(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.7.3 手动请求拍摄照片"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1

        
        return {
            'type':'image_take_manual',
            'command_status':command_status,

        }


    def parse_request_image_data(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C7.4 监测装置请求上送照片,收到图像请求,直接把原报文再发回客户端"""
        return {'type':'request_image'}



    def parse_image_data(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.7.5 远程图像数据报"""
        channel = raw[offset]; offset += 1
        self.channel_no = channel
        self.cmd_id = cmd_id
        preset = raw[offset]; offset += 1
        total_pack = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        self.image_total_pack = total_pack
        
        pack_no = struct.unpack('<H', raw[offset:offset+2])[0]; offset += 2
        self.image_pack_no_list.append(pack_no)
        img_bytes   = raw[offset:-3]
        self.image_pack_dict[pack_no] = img_bytes
        # 简单拼包示例:按 dev+channel 落盘
        #key = f"{cmd_id}_{channel}"
        #with open(f"{key}_pack{pack_no:03d}.jpg", 'b+') as f:
        #    f.write(img_bytes)
        # 若收完最后一包可尝试合并
        if pack_no == total_pack:
            print("[IMAGE] Last pack received, merge by yourself.")
        return {'type': 'image', 'channel': channel, 'pack': pack_no, 'size': len(img_bytes)}


    def count_image_pack(self):
        """统计图像数据包个数够不够"""
        #if self.count == 0:
        #    self.count += 1
        #    self.image_ssue_list = [2,3]
        #    return [2,3]
        if len(set(self.image_pack_no_list)) == self.image_total_pack:
            self.image_ssue_list = []
            return []
        else:
            self.image_ssue_list = list(set(list(range(1,self.image_total_pack+1))) - set(self.image_pack_no_list))
            return self.image_ssue_list


    def parse_image_end_data(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.7.6 远程图像数据上送结束标记"""
        ssue_pack_nos = self.count_image_pack()
        channel_no = raw[26]
        presetting_no = raw[27]
        if len(ssue_pack_nos) == 0:
            #数据包完整,可以落盘
            print("够了")
            self.save_image()
            self.clear_cache()
        else:
            print("缺包")

        return {'type':'image_end',"channel_no":channel_no,"presetting_no":presetting_no}

    def save_image(self):
        print("save_image")
        path = "/cores/wserver/wxxxx-data/user-data/project01/"
        img_name = str(self.cmd_id) + "_" + str(self.channel_no) +"_" +str(int(time.time())) + ".jpg"
        full_path = os.path.join(path,img_name)
        pack_no_sorted = sorted(self.image_pack_dict)
        sorted_pack_list = [self.image_pack_dict[pack_no] for pack_no in pack_no_sorted]
        img_content = b"".join(sorted_pack_list)
        with open(full_path,'wb') as img_file:
            img_file.write(img_content)


    def clear_cache(self):
        self.image_pack_dict = []
        self.image_pack_no_list = []
        self.image_total_pack = 0

    def make_ssue_image_resp(self,res):
        """C.7.7 远程图像补包数据下发"""
        header = struct.pack("<H",23205)
        cmd_id = struct.pack('<17s',self.cmd_id.encode('utf-8'))
        frame_type = struct.pack('<B',FRAME_TYPE_IMAGE_RESP)
        ptype = b'\xCF'
        frame_no = b'\x01'
        channel_no = struct.pack('<B',res['channel_no'])
        presetting_no = struct.pack('<B',res['presetting_no'])
        complementpack_sum = struct.pack('<H',len(self.image_ssue_list))
        complementpack_no = b''
        for ssue in self.image_ssue_list:
            complementpack_no += struct.pack('<H',ssue)
        data_len = len(channel_no + presetting_no + complementpack_sum + complementpack_no)
        data_len = struct.pack('<H',data_len)
        payload = data_len + cmd_id + frame_type + ptype + frame_no + channel_no + presetting_no +complementpack_sum + complementpack_no
        crc = crc16(payload)
        crc_b = struct.pack("<H",crc)
        frame = header + payload + crc_b + b'\x96'
        return frame


    def make_camera_remote_adjust(self,cmd_id: str,channel_no,presetting_no,action):
        """C.7.8 摄像机远程调节 发送给设备"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",9)
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xD0')
        frame_no = struct.pack("<s",b'\x01')

        #0x00表示查询,0x01表示设置
        channel_no = struct.pack('<B',channel_no)
        presetting_no = struct.pack('<B',presetting_no)
        action = struct.pack('<B',action)
        content = channel_no + presetting_no + action

        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def parse_camera_remote_adjust(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.7.8 摄像机远程调节"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        
        
        return {
            'type':'camera_remote_adjust',
            'command_status':command_status,

        }
    def make_camera_upload_video(self,cmd_id: str,channel_no,control,port):
        """C.7.9 启动视频传输 发送给设备"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",9)
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xD1')
        frame_no = struct.pack("<s",b'\x01')

        #0x00表示查询,0x01表示设置
        channel_no = struct.pack('<B',channel_no)
        control = struct.pack('<B',control)
        port = struct.pack('<H',port)
        

        content = channel_no + control + port

        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def make_camera_time_table(self,cmd_id: str,request_set_flag,time_list):
        """C.7.10 摄像机定时工作时间表 发送给设备"""
        header = struct.pack('<H',23205)
        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",9)
        device_id = struct.pack("<17s",cmd_id.encode('utf-8'))
        #帧类型->0x03控制报文
        frame_type = struct.pack("<s",b'\x03')
        #报文类型->0xA2
        ptype= struct.pack("<s",b'\xD5')
        frame_no = struct.pack("<s",b'\x01')

        #0x00表示查询,0x01表示设置
        request_set_flag = struct.pack('<B',request_set_flag)
        t_b = b''
        for t in time_list:
            t_b += struct.pack('<f',t['start_time'])
            t_b += struct.pack('<f',t['end_time'])
        
        content = request_set_flag + t_b

        #data_len表示 frame_no以后,crc 以前的数据长度
        data_len = struct.pack("<H",len(content))
        #组装payload
        payload = data_len + device_id + frame_type + ptype + frame_no + content
        crc = crc16(payload)
        crc_b = struct.pack('<H',crc)
        b_frame = header + payload + crc_b + b'\x96'
        return b_frame

    def parse_camera_time_table(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.7.10 摄像机时间表"""
        command_status = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        start_time1 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        end_time1 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        start_time2 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        end_time2 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        start_time3 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        end_time3 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        start_time4 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        end_time4 = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        
        
        return {
            'type':'camera_time_table',
            'command_status':command_status,
            'start_time1':start_time1,
            'end_time1':end_time1,
            'start_time2':start_time2,
            'end_time2':end_time2,
            'start_time3':start_time3,
            'end_time3':end_time3,
            'start_time4':start_time4,
            'end_time4':end_time4,

        }

    #-------------------
    # 监测装置工作状态报文
    #-------------------
    def parse_cmd_heartbeat(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.8.1 心跳报"""
        clocktime_stamp = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        return {
            'type':'cmd_heartbeat',
            'clocktime_stamp':clocktime_stamp,

        }
    
    def parse_cmd_base_info(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.8.2 基本信息报"""
        smartquip_name = struct.unpack('<50s', raw[offset:offset+50])[0]; offset += 50
        model = struct.unpack('<10s', raw[offset:offset+10])[0]; offset += 10
        data_trans_protocol_version = struct.unpack('<4s', raw[offset:offset+4])[0]; offset += 4
        essential_info_version = struct.unpack('<4s', raw[offset:offset+4])[0]; offset += 4
        bs_manufacture = struct.unpack('<50s', raw[offset:offset+50])[0]; offset += 50
        bs_production_date = struct.unpack('<4s', raw[offset:offset+4])[0]; offset += 4
        bs_identifier = struct.unpack('<20s', raw[offset:offset+20])[0]; offset += 20
        return {
            'type':'cmd_base_info',
            'smartquip_name':smartquip_name,
            'model':model,
            'data_trans_protocol_version':data_trans_protocol_version,
            'essential_info_version':essential_info_version,
            'bs_manufacture':bs_manufacture,
            'bs_production_date':bs_production_date,
            'bs_identifier':bs_identifier,
        }
    
    def parse_cmd_work_state(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.8.3 工作状态报"""
        time_stamp = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        operation_temperature = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        battery_capacity = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        floating_charge = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        total_working_time = struct.unpack('<I', raw[offset:offset+4])[0]; offset += 4
        working_time = struct.unpack('<I', raw[offset:offset+4])[0]; offset += 4
        connection_state = struct.unpack('<B', raw[offset:offset+1])[0]; offset += 1
        return {
            'type':'cmd_work_state',
            'time_stamp':time_stamp,
            'operation_temperature':operation_temperature,
            'battery_capacity':battery_capacity,
            'floating_charge':floating_charge,
            'total_working_time':total_working_time,
            'working_time':working_time,
            'connection_state':connection_state,
        }
    
    def parse_cmd_err_info(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """C.8.3 工作状态报"""
        time_stamp = struct.unpack('<f', raw[offset:offset+4])[0]; offset += 4
        fault_desc = raw[offset:-3].decode("utf-8")
        
        return {
            'type':'cmd_err_info',
            'time_stamp':time_stamp,
            'fault_desc':fault_desc,
        }


    def parse_custom_data(self,cmd_id: str, seq: int, raw: bytes, offset: int):
        """自定义数据报"""
        data = struct.unpack("<5s",raw[offset:offset+5])
        print(data)

    #解包函数,解析通用字段,数据段根据报文类型由专门的解析函数处理
    def parse_frame(self,raw: bytes):
        """返回 dict 或 None"""
        header = struct.unpack("<2s",raw[:2])[0]
        if len(raw) < 10 or raw[:2] != SYNC_HEAD or raw[-1] != SYNC_TAIL:
            print("tail matters")
            return None
        pkt_len = struct.unpack('<H', raw[2:4])[0]
        if len(raw) < 22+pkt_len:
            print("package len  matters")
            return None
        payload = raw[2: 2+ 22 +pkt_len]
        if crc16(payload) != struct.unpack('<H', raw[-3:-1])[0]:
            print("crc matters")
            return None
        cmd_id = raw[4:21].decode()
        frame_type = raw[21]
        ptype = raw[22]
        seq = raw[23]
        content = raw[24:]
        #if frame_type != FRAME_TYPE_DATA:
        #    return None
        parser = getattr(self,self.PARSER_MAP.get(ptype))
        if not parser:
            return None
        try:
            return parser(cmd_id, seq, raw, 24)
        except Exception as e:
            return None

    # -------------------- 主循环 --------------------
    def run(self,ip='0.0.0.0', port=50001):
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.bind((ip, port))
        while True:
            data, addr = sock.recvfrom(4096)
            res = self.parse_frame(data)
            print("res:",res)
            if res:
                ptype = {
                    'weather': PTYPE_WEATHER,
                    'filth': PTYPE_FILTH,
                    'breeze_flutter': PTYPE_BREEZE_FLUTTER,
                    'breeze_waveform': PTYPE_BREEZE_WAVEFORM,
                    'wire_temp': PTYPE_WIRE_TEMP,
                    'wire_radian': PTYPE_WIRE_RADIAN,
                    'tower_tilt': PTYPE_TOWER_TILT,
                    'device_time': PTYPE_DEVICE_TIME,
                    'device_netadapter': PTYPE_DEVICE_NETADAPTER,
                    'mainsite_request': PTYPE_MAINSITE_REQUEST,
                    'collect_params': PTYPE_COLLECT_PARAMS,
                    'model_params': PTYPE_MODEL_PARAMS,
                    'alarm_thresholds': PTYPE_ALARM_THRESHOLDS,
                    'device_direct': PTYPE_DEVICE_DIRECT,
                    'control_base_info': PTYPE_CONTROL_BASE_INFO,
                    'remote_upgrade': PTYPE_REMOTE_UPGRADE,
                    'cmd_id': PTYPE_CMD_ID,
                    'cmd_reset': PTYPE_CMD_RESET,
                    'cmd_wake': PTYPE_CMD_WAKE,
                    'weather_params': PTYPE_WEATHER_PARAMS,
                    'tower_tilt_params': PTYPE_TOWER_TILT_PARAMS,
                    'breeze_flutter_params': PTYPE_WEATHER,
                    'wire_radian_params': PTYPE_WIRE_RADIAN_PARAMS,
                    'wire_temp_params': PTYPE_WIRE_TEMP_PARAMS,
                    'ice_params': PTYPE_ICE_PARAMS,
                    'wire_yaw_params': PTYPE_WIRE_YAW_PARAMS,
                    'gallop_char_params': PTYPE_GALLOP_CHAR_PARAMS,
                    'filth_params': PTYPE_FILTH_PARAMS,
                    'image_collect_params': PTYPE_IMAGE_COLLECT_PARAMS,
                    'image_time_table': PTYPE_IMAGE_TIME_TABLE,
                    'image_take_manual': PTYPE_IMAGE_TAKE_MANUAL,
                    'camera_remote_adjust': PTYPE_CAMERA_REMOTE_ADJUST,
                    'camera_time_table': PTYPE_CAMERA_TIME_TABLE,
                    'cmd_heartbeat': PTYPE_CMD_HEARTBEAT,
                    'cmd_base_info': PTYPE_CMD_BASE_INFO,
                    'cmd_work_state': PTYPE_CMD_WORK_STATE,
                    'cmd_err_info': PTYPE_CMD_ERR_INFO,
                    'ice': PTYPE_ICE,
                    'gallop_char': PTYPE_GALLOP_CHAR,
                    'gallop_track': PTYPE_GALLOP_TRACK,
                    'request_image': PTYPE_REQUEST_IMAGE_DATA,
                    'image': PTYPE_IMAGE_DATA,
                    'image_end': PTYPE_IMAGE_END_DATA,
                }[res['type']]
                if ptype == 0xCC:
                    resp = data
                    print("resp",resp)
                    sock.sendto(resp, addr)
                    
                if ptype == 0xCE:
                    resp = self.make_ssue_image_resp(res)
                    sock.sendto(resp, addr)
                else:
                    resp = self.make_monitor_resp_frame(data[4:21].decode(), data[23], ptype)
                
                






# 覆冰数据封包
def ice_data_pack():
    
    ice_data = {
        'type': 'ice', 
        'comp_id': '00000000000000002', 
        'time_stamp': 1700000000, 
        'eq_icethickness': 5.2, 
        'tension': 3.3, 
        'tension_difference': 4.4, 
        't_sensor_num': 2, 
        't_sensor_list': [{'tension':3.3,'crosswise_angle':4.4,'forward_tilt_angle':5.5},{'tension':3.3,'crosswise_angle':4.4,'forward_tilt_angle':5.5}], 
        'instantaneous_windspeed': 6.6,
        'instantaneous_winddirection': 4,
        'air_temperature': 3.3,
        'humidity': 3,
    }

    comp_id = struct.pack('<17s',ice_data['comp_id'].encode('utf-8'))
    time_stamp = struct.pack('<I',ice_data['time_stamp'])
    eq_icethickness = struct.pack('<f',ice_data['eq_icethickness'])
    tension = struct.pack('<f',ice_data['tension'])
    tension_difference = struct.pack('<f',ice_data['tension_difference'])
    t_sensor_num = struct.pack('<B',ice_data['t_sensor_num'])
    t_sensor_list = b''
    for i in range(ice_data['t_sensor_num']):
        t_sensor_list += struct.pack('<f',ice_data['t_sensor_list'][i]['tension'])
        t_sensor_list += struct.pack('<f',ice_data['t_sensor_list'][i]['crosswise_angle'])
        t_sensor_list += struct.pack('<f',ice_data['t_sensor_list'][i]['forward_tilt_angle'])
    
    instantaneous_windspeed = struct.pack('<f',ice_data['instantaneous_windspeed'])
    instantaneous_winddirection = struct.pack('<H',ice_data['instantaneous_winddirection'])
    air_temperature = struct.pack('<f',ice_data['air_temperature'])
    humidity = struct.pack('<H',ice_data['humidity'])
    content = comp_id + time_stamp + eq_icethickness+tension+tension_difference+t_sensor_num+t_sensor_list+instantaneous_windspeed+instantaneous_winddirection+air_temperature+humidity
    return content

#通用封包
def gen_pack():
    #封包
    content = ice_data_pack()
    print(content,len(content))
    b_frame = b''
    header = struct.pack('<2s',b'\x5A\xA5')
    data_len = struct.pack("<H",len(content))
    device_id = struct.pack("<17s",b"00000000000000001")
    frame_type = struct.pack("<s",b'\x01')
    ptype= struct.pack("<s",b'\x22')
    frame_no = struct.pack("<s",b'\x01')
    content = content
    payload = data_len + device_id + frame_type + ptype + frame_no + content
    crc = crc16(payload)
    crc_b = struct.pack('<H',crc)
    b_frame = header + payload + crc_b + b'\x96'
    parse_frame(b_frame)



def gen_request_image_pack(frame_no,channel_no,presetting_no,packt_no):
    b_frame = b''
    header = struct.pack('<H',23205)
    
    device_id = struct.pack("<17s",b"00000000000000002")
    frame_type = struct.pack("<s",b'\x05')
    ptype= struct.pack("<s",b'\xCC')
    frame_no = struct.pack("<B",frame_no)
    channel_no = struct.pack("<B",channel_no)
    presetting_no = struct.pack("<B",presetting_no)
    packt_no_hi = struct.pack("<H",packt_no)[0]
    packt_no_lo = struct.pack("<H",packt_no)[1]
    content = channel_no + presetting_no+packt_no_hi.to_bytes() + packt_no_lo.to_bytes()
    data_len = struct.pack("<H",len(content))
    payload = data_len + device_id + frame_type + ptype + frame_no + content
    crc = crc16(payload)
    crc_b = struct.pack('<H',crc)
    b_frame = header + payload + crc_b + b'\x96'
    return b_frame


def gen_image_pack(img_bytes,frame_no,channel_no,presetting_no,packt_no,subpacket_no):
    b_frame = b''
    header = struct.pack('<H',23205)
    
    device_id = struct.pack("<17s",b"00000000000000002")
    frame_type = struct.pack("<s",b'\x05')
    ptype= struct.pack("<s",b'\xCD')
    frame_no = struct.pack("<B",frame_no)
    channel_no = struct.pack("<B",channel_no)
    presetting_no = struct.pack("<B",presetting_no)
    packt_no = struct.pack("<H",packt_no)
    subpacket_no = struct.pack("<H",subpacket_no)
    content = channel_no + presetting_no+packt_no + subpacket_no + img_bytes
    data_len = struct.pack("<H",len(content))
    payload = data_len + device_id + frame_type + ptype + frame_no + content
    crc = crc16(payload)
    crc_b = struct.pack('<H',crc)
    b_frame = header + payload + crc_b + b'\x96'
    return b_frame


def gen_image_end_pack(frame_no,channel_no,presetting_no,timestamp):
    b_frame = b''
    header = struct.pack('<H',23205)
    
    device_id = struct.pack("<17s",b"00000000000000001")
    frame_type = struct.pack("<s",b'\x05')
    ptype= struct.pack("<s",b'\xCE')
    frame_no = struct.pack("<B",frame_no)
    channel_no = struct.pack("<B",channel_no)
    presetting_no = struct.pack("<B",presetting_no)
    timestamp = struct.pack("<I",timestamp)
    content = channel_no + presetting_no + timestamp
    data_len = struct.pack("<H",len(content))
    payload = data_len + device_id + frame_type + ptype + frame_no + content
    crc = crc16(payload)
    crc_b = struct.pack('<H',crc)
    b_frame = header + payload + crc_b + b'\x96'
    return b_frame


def append_image_data():
    import os
    if os.path.exists("pic2.jpg"):
        os.remove("pic2.jpg")
    pic = open("pic.jpg",'rb').read()
    a = pic[:10]
    b = pic[10:]
    f = open("pic2.jpg",'ab')
    f.write(a)
    f.close()
    f = open("pic2.jpg",'ab')
    f.write(b)
    f.close()

def clear_image():
    import os
    if os.path.exists("00000000000000002_1.jpg"):
        os.remove("00000000000000002_1.jpg")

def image_send():

    # 创建socket对象
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 服务器地址端口
    dest_addr = ('0.0.0.0', 50001)
    # 发送数据
    with open("pic.jpg", "rb") as f:
        image_data = f.read()

    chunk_size = 1024 # 每个数据包大小
    n_chunks = len(image_data) // chunk_size
    frame_img_request = gen_request_image_pack(1,1,1,n_chunks)
    client_socket.sendto(frame_img_request, dest_addr)
    data = client_socket.recv(1024)
    print("data",data)
    pack_dict = {}
    for i in range(0,n_chunks):
        
        chunk = image_data[i * chunk_size: (i + 1) * chunk_size]
        pack_dict[i] = chunk
        
        frame = gen_image_pack(chunk,i+1,1,1,n_chunks,i)
        client_socket.sendto(frame, dest_addr)
    img_end = gen_image_end_pack(n_chunks,1,1,1700000000)
    client_socket.sendto(img_end, dest_addr)
    # 接收数据
    data = client_socket.recv(1024)
    sum = struct.unpack('<H',data[26:28])[0]
    frame_type = data[21]
    ptype = data[22]
    ssue_pack_no_list = []
    print('ptype',ptype)
    if ptype == 0xCF:
        offset = 28
        if len(data) > 33:
            for i in range(sum):
                no = struct.unpack('<H',data[offset:offset+2])[0]
                print(no)
                ssue_pack_no_list.append(no)
                offset += 2
    for pack_no in ssue_pack_no_list:
        frame = gen_image_pack(pack_dict[pack_no],pack_no,1,1,n_chunks,pack_no)
        client_socket.sendto(frame, dest_addr)
    img_end = gen_image_end_pack(n_chunks,1,1,1700000000)
    client_socket.sendto(img_end, dest_addr)
    # 关闭连接
    client_socket.close()


def server_main():
    #封包
    content = ice_data_pack()
    print(content,len(content))
    b_frame = b''
    header = struct.pack('<H',23205)
    data_len = struct.pack("<H",len(content))
    device_id = struct.pack("<17s",b"00000000000000001")
    frame_type = struct.pack("<s",b'\x01')
    ptype= struct.pack("<s",b'\x22')
    frame_no = struct.pack("<s",b'\x01')
    content = content
    payload = data_len + device_id + frame_type + ptype + frame_no + content
    crc = crc16(payload)
    crc_b = struct.pack('<H',crc)
    b_frame = header + payload + crc_b + b'\x96'
    s = I1Server()
    s.start()


if __name__ == '__main__':
    main()

common.py

python 复制代码
# -------------------- 协议常量 --------------------
SYNC_HEAD = b'\xA5\x5A'
SYNC_TAIL = 0x96

#帧类型
#数据监测报(监测装置-> 主站系统)
FRAME_TYPE_DATA = 0x01
#数据响应报(主站系统-> 监测装置)
FRAME_TYPE_RESP = 0x02
#控制数据报(主站系统-> 监测装置)
FRAME_TYPE_CONTROL = 0x03
#控制响应报(监测装置-> 主站系统)
FRAME_TYPE_CONTROL_RESP = 0x04
#远程图像数据报(监测装置-> 主站系统)
FRAME_TYPE_IMAGE = 0x05
#图像数据响应报(主站系统-> 监测装置)
FRAME_TYPE_IMAGE_RESP = 0x06
#远程图像控制报(主站系统-> 监测装置)
FRAME_TYPE_IMAGE_CONTROL = 0x07
#图像控制响应报(监测装置-> 主站系统)
FRAME_TYPE_IMAGE_CONTROL_RESP = 0x08
#工作状态报(监测装置-> 主站系统)
FRAME_TYPE_WORK_STATUS = 0x09
#工作状态响应报(主站系统-> 监测装置)
FRAME_TYPE_WORK_STATUS_RESP = 0x0A
#同步数据报(两个监测系统?的数据同步)
FRAME_TYPE_FFH = 0xFF






# 报文类型,只列了部分用到的
PTYPE_WEATHER              = 0x0B
PTYPE_TOWER_TILT          = 0x0C
PTYPE_FILTH          = 0x5C

PTYPE_ICE                  = 0x22
PTYPE_BREEZE_FLUTTER          = 0x1E
PTYPE_BREEZE_WAVEFORM          = 0x1F
PTYPE_GALLOP_CHAR          = 0x24
PTYPE_GALLOP_TRACK          = 0x25
PTYPE_WIRE_TEMP          = 0x21
PTYPE_WIRE_RADIAN         = 0x20
PTYPE_WIRE_YAW         = 0x23
PTYPE_DEVICE_TIME          = 0xA1
PTYPE_DEVICE_NETADAPTER          = 0xA2
PTYPE_MAINSITE_REQUEST          = 0xA3
PTYPE_COLLECT_PARAMS          = 0xA4
PTYPE_MODEL_PARAMS          = 0xA5
PTYPE_ALARM_THRESHOLDS         = 0xA6
PTYPE_DEVICE_DIRECT        = 0xA7
PTYPE_CONTROL_BASE_INFO         = 0xA8
PTYPE_REMOTE_UPGRADE         = 0xA9
PTYPE_REMOTE_UPGRADE_END         = 0xAA
PTYPE_REMOTE_UPGRADE__SSUE         = 0xAB
PTYPE_CMD_ID         = 0xAC
PTYPE_CMD_RESET         = 0xAD
PTYPE_CMD_WAKE         = 0xAE
PTYPE_WEATHER_PARAMS         = 0xAF
PTYPE_TOWER_TILT_PARAMS         = 0xB0
PTYPE_BREEZE_FLUTTER_PARAMS         = 0xB1
PTYPE_WIRE_RADIAN_PARAMS         = 0xB2
PTYPE_WIRE_TEMP_PARAMS         = 0xB3
PTYPE_ICE_PARAMS         = 0xB4
PTYPE_WIRE_YAW_PARAMS         = 0xB5
PTYPE_GALLOP_CHAR_PARAMS         = 0xB6
PTYPE_FILTH_PARAMS         = 0xB7


PTYPE_IMAGE_COLLECT_PARAMS         = 0xC9
PTYPE_IMAGE_TIME_TABLE        = 0xCA
PTYPE_IMAGE_TAKE_MANUAL         = 0xCB
PTYPE_REQUEST_IMAGE_DATA   = 0xCC
PTYPE_IMAGE_DATA           = 0xCD
PTYPE_IMAGE_END_DATA       = 0xCE
PTYPE_IMAGE_SSUE_DATA      = 0xCF
PTYPE_CAMERA_REMOTE_ADJUST         = 0xD0
PTYPE_CAMERA_UPLOAD_VIDEO         = 0xD1
PTYPE_CMD_SAVE_ADRESS         = 0xD2
PTYPE_STOP_CONNECT         = 0xD3
PTYPE_CAMERA_BASE_INFO         = 0xD4
PTYPE_CAMERA_TIME_TABLE         = 0xD5
PTYPE_CMD_HEARTBEAT         = 0xE6
PTYPE_CMD_BASE_INFO         = 0xE7
PTYPE_CMD_WORK_STATE         = 0xE8
PTYPE_CMD_ERR_INFO         = 0xE9
PTYPE_CUSTOM_DATA          = 0x21

# crc16校验表,高位表
crc16_table_h = [
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
]
#crc16校验表,低位表
crc16_table_l = [
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04,
    0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8,
    0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
    0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10,
    0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
    0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
    0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C,
    0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0,
    0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
    0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
    0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C,
    0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
    0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54,
    0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98,
    0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40
]

#校验函数
def crc16(data: bytes) -> int:
    hi, lo = 0xFF, 0xFF
    for b in data:
        idx = hi ^ b
        hi = lo ^ crc16_table_h[idx]
        lo = crc16_table_l[idx]
    return (hi << 8) | lo
相关推荐
weixin_462022358 小时前
RAW-Adapter: Adapting Pre-trained Visual Model to Camera RAW Images
python·计算机视觉
电子硬件笔记8 小时前
Python语言编程导论第三章 编写程序
开发语言·python·编辑器
布谷歌8 小时前
在java中实现c#的int.TryParse方法
java·开发语言·python·c#
cooldream20098 小时前
当代 C++ 的三大技术支柱:资源管理、泛型编程与模块化体系的成熟演进
开发语言·c++
洲星河ZXH8 小时前
Java,集合框架体系
开发语言·windows
宠..9 小时前
写一个感染型病毒
开发语言·安全·安全性测试
wheelmouse77889 小时前
一个优雅、通用、零侵入的 CSV 导出工具类(Java 实战)
java·开发语言
B站计算机毕业设计之家9 小时前
基于大数据热门旅游景点数据分析可视化平台 数据大屏 Flask框架 Echarts可视化大屏
大数据·爬虫·python·机器学习·数据分析·spark·旅游