import time from serial import Serial from . import tools from . import function class DeviceSerial: """ 串口通信设备原型 Note: 串口资源释放与重复开启 """ def __init__(self, com_name="COM1", **kwargs): """ 初始化设备 """ if com_name is not None: com_config = {} com_config['baudrate'] = kwargs['baudrate'] if 'baudrate' in kwargs.keys() else 115200 com_config['parity'] = kwargs['parity'] if 'parity' in kwargs.keys() else 'N' com_config['bytesize'] = kwargs['bytesize'] if 'bytesize' in kwargs.keys() else 8 com_config['stopbits'] = kwargs['stopbits'] if 'stopbits' in kwargs.keys() else 1 self.__com = Serial(com_name, timeout=0, **com_config) else: self.__com = None self.flag_print = kwargs['frame_print'] if 'frame_print' in kwargs.keys() else False self.time_out = kwargs['time_out'] if 'time_out' in kwargs.keys() else 1 self.time_gap = kwargs['time_gap'] if 'time_gap' in kwargs.keys() else 0.01 self.retry = kwargs['retry'] if 'retry' in kwargs.keys() else 1 self.output = { 'result': False, 'code_func': 0x00, } self.log = { 'send': 0, 'read': 0, 'keep-fail': 0, 'record': { 'config': None, 'data': None, }, } def __read_frame(self) -> bool: """ 使用帧字节超时策略读报文帧, 并进行解析数据, 打印异常 """ frame_recv = b'' time_start, time_current, flag_frame = time.time(), time.time(), False while (time_current - time_start) < self.time_out: time.sleep(self.time_gap) bytes_read = self.__com.read_all() time_current = time.time() if flag_frame and len(bytes_read) == 0: break elif len(bytes_read): flag_frame = True frame_recv += bytes_read try: self.output = function.frame.check_frame_modbus(frame_recv, self.block['data']) if self.flag_print: print("Read Frame: ", tools.ByteConv.trans_list_to_str(frame_recv)) except Exception as ex: print("Error Info: ", ex) if self.flag_print and frame_recv: print("Fail Data: " , tools.ByteConv.trans_list_to_str(frame_recv)) self.output['result'] = False return self.output['result'] def __transfer_data(self, frame: bytearray) -> bool: """ 串口收发报文, 包含重试逻辑与数据打印 """ if self.__com is None: print(tools.ByteConv.trans_list_to_str(frame)) return False fail_count = 0 while fail_count < self.retry: frame_discard = self.__com.read_all() self.__com.write(frame) self.log['send'] += 1 if self.flag_print and frame_discard: print("Discard Data: " , frame_discard) if self.flag_print: print("Send Frame: ", tools.ByteConv.trans_list_to_str(frame)) time.sleep(10 * self.time_gap) if self.__read_frame(): if (self.flag_print is not None) and 'Regs' in self.output.keys(): function.frame.print_display(self.output['Regs']) self.log['read'] += 1 break else: fail_count += 1 if fail_count >= self.log['keep-fail']: self.log['keep-fail'] = fail_count time.sleep(2*self.time_out) return fail_count < self.retry