import time from datetime import datetime recvData = bytearray() #接收的数据存放此数组 startTime = time.time() # 将bytearray以字为单位转换成16进制字符串,方便显示 def wordData2HexStr(data): ret = ' '.join(data[i:i+2].hex() for i in range(0, len(data), 2)) return ret.upper() # 获取当前时间字符串 def nowStr(): now = datetime.now() ret = now.strftime('%H:%M:%S.') + f"{now.microsecond // 1000:03d}" return ret def checkValue(data: bytes) -> int: # 初始化crc为0xFFFF crc = 0xFFFF length = len(data) if length % 2 != 0: return 0 for i in range(0, length, 2): val = data[i] * 256 + data[i + 1] crc = crc ^ val # 返回最终的crc值 return crc # 启动函数,命令开始会调用此函数 def start(): log_i('----------------- ' + cmdInfo['name'] + ' ----------------') #log(f"[{devInfo['name']}]{cmdInfo['name']}") startTime = time.time() #记录启动时间 recvData = bytearray() #清空接收数组 attr = cmdInfo['attr'] cmdStr = attr['cmd'] + attr['data'] #组合要发送的报文,十六进制字符串 data = bytearray().fromhex(cmdStr) #将十六进制字符串转成字节数据发送 if attr['req_is_check'] == True: crc = checkValue(data) data = data + bytearray(crc.to_bytes(2, 'big')) send(data) log_d(f"[{nowStr()}] Sent:{wordData2HexStr(data)}") return True # 接收数据处理函数,当收到数据会调用此函数 def recvDataHandler(data): global recvData recvData = recvData + data attr = cmdInfo['attr'] rsp_len = int(attr['rsp_len']) * 2 if len(recvData) >= rsp_len: #TBUS指令rsp_len以字为单位 log_d(f"[{nowStr()}] Echo:{wordData2HexStr(recvData)}") if attr['rsp_is_check'] == True: # 校验数据正确性 crc = int.from_bytes(recvData[rsp_len - 2:rsp_len], byteorder='big') calc_value = checkValue(recvData[0:rsp_len - 2]) if crc != calc_value: log_w("CRC error:" + "should be " + '{:04X}'.format(calc_value) + ",got " + '{:04X}'.format(crc)) finish() return log_i("success") finish() # 此函数会被重复调用,间隔10毫秒,直到finish() def loop(): global recvData if time.time() > startTime + int(cmdInfo['attr']['rsp_timeout']) / 1000.0: if len(recvData) > 0: log_w(f"[{nowStr()}]RX timeout:{wordData2HexStr(recvData)}") else: log_w(f"[{nowStr()}]RX timeout") log_e(f"[{devInfo['name']}]{cmdInfo['name']} fail.") finish()