def _build_redis_telemetry_msg(self, msg) -> s...
創建於:2026年3月24日
使用 GPT-5.4 Thinking 回答 Chat01
創建於:2026年3月24日
使用 GPT-5.4 Thinking 回答 Chat01
textdef _build_redis_telemetry_msg(self, msg) -> str: """构造推送到 Redis 的 JSON 消息字符串。""" iso_timestamp = datetime.now().astimezone().isoformat(timespec='milliseconds') hex_status = f"0x{msg & 0xFFFF:04X}" redis_info = { "telem_info": { "process_name": "eai_sa", # 进程名 "version": 1, # 进程版本号 "status_code": hex_status, "timestamp": iso_timestamp } } logging.info(f"[Redis] 发布系统遥测: {redis_info}") return json.dumps(redis_info, ensure_ascii=False) def _flush_system_flags_to_disk(self, trigger_rule_id: str, mask: int): # todo 需要拼接所有的遥测信息:如计数+状态,默认左边为计数,右边的8位为系统状态@ZJ # msg = self.gateway.trigger_count + self._mask_to_bin_str(mask) # self.redis_client.publish("telem_info", self._build_redis_telemetry_msg(mask)) # 构建16bit状态码:[5bit循环计数][3bit0][8bit标志位] # 获取5bit循环计数(0-31) trigger_count = self.gateway.trigger_count & 0x1F # 确保只取5bit # 构建16bit状态码 # 5bit计数左移11位,8bit标志位保持不变,中间3位为0 status_code = (trigger_count << 11) | (mask & 0xFF) # 发布到Redis self.redis_client.publish("telem_info", self._build_redis_telemetry_msg(status_code)) """将当前系统标志位总状态覆盖写入 SYSTEM_FLAGS_FILE。""" flags_detail = { name: int(bool(mask & (1 << bit))) for name, bit in SYSTEM_BIT_MAP.items() } record = { "updated_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "trigger_rule_id": trigger_rule_id, "system_flag_mask": mask, "system_flag_bits": self._mask_to_bin_str(mask), "system_flags": flags_detail, } try: with open(SYSTEM_FLAGS_FILE, 'w', encoding='utf-8') as f: json.dump(record, f, ensure_ascii=False, indent=2) logging.info(f"[Flags] 落盘成功: {self._mask_to_bin_str(mask)}") except Exception as e: logging.error(f"[Flags] 系统标志位落盘失败: {e}")
请问上面这段代码是否实现了将二进制的【循环计数(5bit)+中间补000(3bit)+标志位(8bit)】转换为16进制(16bit)并发布到Redis的功能?传入redis的程状态码必须为uint16_t( 0x0000~0xFFFF)
是的,从位拼接逻辑上看,这段代码已经实现了:
0x0000~0xFFFF 的 4 位十六进制字符串publish 发出对应这句是核心:
pythonstatus_code = (trigger_count << 11) | (mask & 0xFF)
它的位布局确实是:
text[15........11][10....8][7........0] trigger_count 000 flags
也就是:
trigger_count << 11 → 占用高 5 位000(mask & 0xFF) → 占用低 8 位然后这里:
pythonhex_status = f"0x{msg & 0xFFFF:04X}"
会把结果限制在 0x0000 ~ 0xFFFF 范围内,并格式化成固定 4 位十六进制。
如果你的要求是:
“Redis 消息里的状态码字段,表达的是一个 16 bit 无符号值,显示为 0x0000~0xFFFF 这种形式”
那么你的代码 已经满足要求。
你现在发到 Redis 的 status_code 是:
json"status_code": "0x1234"
也就是 字符串,不是原生数值类型,更不是二进制的 uint16_t。
因为:
pythonhex_status = f"0x{msg & 0xFFFF:04X}"
返回的是 Python str,最终 json.dumps() 后也是 JSON 字符串。
那你现在是对的。
因为实际数值已经被限制在 16 bit 内,字符串只是它的表现形式。
那你现在 不满足,因为你发的是字符串,不是整数。
应该改成这样:
pythondef _build_redis_telemetry_msg(self, msg) -> str: iso_timestamp = datetime.now().astimezone().isoformat(timespec='milliseconds') status_code = msg & 0xFFFF redis_info = { "telem_info": { "process_name": "eai_sa", "version": 1, "status_code": status_code, # 数值,不是字符串 "timestamp": iso_timestamp } } logging.info(f"[Redis] 发布系统遥测: {redis_info}") return json.dumps(redis_info, ensure_ascii=False)
如果还想日志里看见十六进制,可以单独打日志:
pythonlogging.info(f"status_code=0x{status_code:04X}")
假设:
pythonself.gateway.trigger_count = 5 mask = 0xA3
那么:
texttrigger_count = 5 = 00101 mask = 0xA3 = 10100011
拼接后:
text00101 000 10100011
即:
text0010 1000 1010 0011 = 0x28A3
你的代码会发出:
json"status_code": "0x28A3"
这个结果是正确的。
虽然你已经用了掩码,但可读性上更清楚:
pythontrigger_count = int(self.gateway.trigger_count) & 0x1F flags = int(mask) & 0xFF status_code = (trigger_count << 11) | flags
比如:
python"status_code_hex": hex_status
否则别人看到 status_code,通常会以为它是整数。
位运算逻辑:正确。
16 bit 十六进制表示:正确。
Redis 发布:已实现。
唯一需要确认的是:下游要的是“16位值的十六进制字符串”,还是“JSON 数值 / 原始 uint16_t 字节流”。
如果你愿意,我可以直接帮你改成这三种版本之一:
uint16_t 二进制数据