Files
pig-house-controller/app/proto/client_pb.py

306 lines
10 KiB
Python
Raw Normal View History

2025-09-25 20:14:48 +08:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
2025-10-17 10:32:52 +08:00
根据client.proto生成的解析代码 (V2 - 已修复解码逻辑)
2025-09-25 20:14:48 +08:00
适用于ESP32 MicroPython环境
"""
import struct
2025-10-09 14:00:38 +08:00
2025-10-08 15:58:51 +08:00
# --- Protobuf基础类型辅助函数 ---
2025-09-25 20:14:48 +08:00
def encode_varint(value):
buf = bytearray()
while value >= 0x80:
buf.append((value & 0x7F) | 0x80)
value >>= 7
buf.append(value & 0x7F)
return buf
2025-10-09 14:00:38 +08:00
2025-09-25 20:14:48 +08:00
def decode_varint(buf, pos=0):
result = 0
shift = 0
while pos < len(buf):
byte = buf[pos]
pos += 1
result |= (byte & 0x7F) << shift
if not (byte & 0x80):
break
shift += 7
return result, pos
2025-10-09 14:00:38 +08:00
2025-09-25 20:14:48 +08:00
def encode_string(value):
value_bytes = value.encode('utf-8')
length = encode_varint(len(value_bytes))
return length + value_bytes
2025-10-09 14:00:38 +08:00
2025-09-25 20:14:48 +08:00
def decode_string(buf, pos=0):
2025-10-17 10:32:52 +08:00
"""解码字符串 (已修复)"""
length, pos_after_len = decode_varint(buf, pos)
end_pos = pos_after_len + length
value = buf[pos_after_len:end_pos].decode('utf-8')
return value, end_pos
2025-09-25 20:14:48 +08:00
2025-10-09 14:00:38 +08:00
2025-10-08 15:58:51 +08:00
# --- 消息编码/解码函数 ---
2025-10-07 20:11:19 +08:00
def encode_raw_485_command(bus_number, command_bytes):
2025-09-25 20:14:48 +08:00
result = bytearray()
2025-10-07 20:11:19 +08:00
result.extend(encode_varint((1 << 3) | 0))
result.extend(encode_varint(bus_number))
result.extend(encode_varint((2 << 3) | 2))
result.extend(encode_varint(len(command_bytes)))
result.extend(command_bytes)
2025-09-25 20:14:48 +08:00
return result
2025-10-09 14:00:38 +08:00
2025-10-07 20:11:19 +08:00
def decode_raw_485_command(buf):
2025-10-17 10:32:52 +08:00
"""解码Raw485Command消息 (已修复)"""
2025-09-25 20:14:48 +08:00
result = {}
pos = 0
while pos < len(buf):
tag, pos = decode_varint(buf, pos)
field_number = tag >> 3
wire_type = tag & 0x07
2025-10-07 20:11:19 +08:00
if field_number == 1: # bus_number
2025-10-17 10:32:52 +08:00
value, pos = decode_varint(buf, pos)
result['bus_number'] = value
2025-10-07 20:11:19 +08:00
elif field_number == 2: # command_bytes
2025-10-17 10:32:52 +08:00
length, pos_after_len = decode_varint(buf, pos)
end_pos = pos_after_len + length
result['command_bytes'] = buf[pos_after_len:end_pos]
pos = end_pos
2025-09-25 20:14:48 +08:00
else:
# 跳过未知字段
2025-10-09 14:00:38 +08:00
if wire_type == 0:
_, pos = decode_varint(buf, pos)
elif wire_type == 2:
2025-10-17 10:32:52 +08:00
length, pos_after_len = decode_varint(buf, pos)
pos = pos_after_len + length
elif wire_type == 5:
pos += 4
2025-10-09 14:00:38 +08:00
else:
pos += 1
2025-10-07 20:11:19 +08:00
return result
2025-10-09 14:00:38 +08:00
2025-10-07 20:11:19 +08:00
def encode_collect_task(command_msg):
result = bytearray()
encoded_command = encode_raw_485_command(command_msg['bus_number'], command_msg['command_bytes'])
2025-10-17 10:32:52 +08:00
result.extend(encode_varint((1 << 3) | 2))
2025-10-07 20:11:19 +08:00
result.extend(encode_varint(len(encoded_command)))
result.extend(encoded_command)
return result
2025-10-09 14:00:38 +08:00
2025-10-07 20:11:19 +08:00
def decode_collect_task(buf):
2025-10-17 10:32:52 +08:00
"""解码CollectTask消息 (已修复)"""
2025-10-07 20:11:19 +08:00
result = {}
pos = 0
while pos < len(buf):
tag, pos = decode_varint(buf, pos)
field_number = tag >> 3
wire_type = tag & 0x07
2025-10-09 14:00:38 +08:00
if field_number == 1: # command
2025-10-17 10:32:52 +08:00
length, pos_after_len = decode_varint(buf, pos)
end_pos = pos_after_len + length
value_buf = buf[pos_after_len:end_pos]
result['command'] = decode_raw_485_command(value_buf)
pos = end_pos
2025-10-07 20:11:19 +08:00
else:
2025-10-09 14:00:38 +08:00
if wire_type == 0:
_, pos = decode_varint(buf, pos)
elif wire_type == 2:
2025-10-17 10:32:52 +08:00
length, pos_after_len = decode_varint(buf, pos)
pos = pos_after_len + length
elif wire_type == 5:
pos += 4
2025-10-09 14:00:38 +08:00
else:
pos += 1
2025-09-25 20:14:48 +08:00
return result
2025-10-09 14:00:38 +08:00
2025-10-07 20:11:19 +08:00
def encode_batch_collect_command(correlation_id, tasks):
2025-09-25 20:14:48 +08:00
result = bytearray()
2025-10-07 20:11:19 +08:00
result.extend(encode_varint((1 << 3) | 2))
result.extend(encode_string(correlation_id))
for task in tasks:
encoded_task = encode_collect_task(task['command'])
result.extend(encode_varint((2 << 3) | 2))
result.extend(encode_varint(len(encoded_task)))
result.extend(encoded_task)
2025-09-25 20:14:48 +08:00
return result
2025-10-09 14:00:38 +08:00
2025-10-07 20:11:19 +08:00
def decode_batch_collect_command(buf):
2025-10-17 10:32:52 +08:00
"""解码BatchCollectCommand消息 (已修复)"""
2025-10-07 20:11:19 +08:00
result = {'tasks': []}
2025-09-25 20:14:48 +08:00
pos = 0
while pos < len(buf):
tag, pos = decode_varint(buf, pos)
field_number = tag >> 3
wire_type = tag & 0x07
2025-10-07 20:11:19 +08:00
if field_number == 1: # correlation_id
2025-10-17 10:32:52 +08:00
value, pos = decode_string(buf, pos)
result['correlation_id'] = value
2025-10-07 20:11:19 +08:00
elif field_number == 2: # tasks (repeated)
2025-10-17 10:32:52 +08:00
length, pos_after_len = decode_varint(buf, pos)
end_pos = pos_after_len + length
value_buf = buf[pos_after_len:end_pos]
result['tasks'].append(decode_collect_task(value_buf))
pos = end_pos
2025-10-07 20:11:19 +08:00
else:
2025-10-09 14:00:38 +08:00
if wire_type == 0:
_, pos = decode_varint(buf, pos)
elif wire_type == 2:
2025-10-17 10:32:52 +08:00
length, pos_after_len = decode_varint(buf, pos)
pos = pos_after_len + length
elif wire_type == 5:
pos += 4
2025-10-09 14:00:38 +08:00
else:
pos += 1
2025-09-25 20:14:48 +08:00
return result
2025-10-09 14:00:38 +08:00
2025-10-07 20:11:19 +08:00
def encode_collect_result(correlation_id, values):
2025-09-25 20:14:48 +08:00
result = bytearray()
2025-10-07 20:11:19 +08:00
result.extend(encode_varint((1 << 3) | 2))
result.extend(encode_string(correlation_id))
for value in values:
2025-10-17 10:32:52 +08:00
result.extend(encode_varint((2 << 3) | 5))
result.extend(struct.pack('<f', value))
2025-09-25 20:14:48 +08:00
return result
2025-10-09 14:00:38 +08:00
2025-10-07 20:11:19 +08:00
def decode_collect_result(buf):
2025-10-17 10:32:52 +08:00
"""解码CollectResult消息 (已修复)"""
2025-10-07 20:11:19 +08:00
result = {'values': []}
2025-09-25 20:14:48 +08:00
pos = 0
while pos < len(buf):
tag, pos = decode_varint(buf, pos)
field_number = tag >> 3
wire_type = tag & 0x07
2025-10-07 20:11:19 +08:00
if field_number == 1: # correlation_id
2025-10-17 10:32:52 +08:00
value, pos = decode_string(buf, pos)
result['correlation_id'] = value
2025-10-07 20:11:19 +08:00
elif field_number == 2: # values (repeated)
if wire_type == 5: # fixed32
2025-10-09 14:00:38 +08:00
value = struct.unpack('<f', buf[pos:pos + 4])[0]
2025-09-25 20:14:48 +08:00
pos += 4
2025-10-07 20:11:19 +08:00
result['values'].append(value)
2025-09-25 20:14:48 +08:00
else:
2025-10-09 14:00:38 +08:00
if wire_type == 0:
_, pos = decode_varint(buf, pos)
elif wire_type == 2:
2025-10-17 10:32:52 +08:00
length, pos_after_len = decode_varint(buf, pos)
pos = pos_after_len + length
elif wire_type == 5:
pos += 4
2025-10-09 14:00:38 +08:00
else:
pos += 1
2025-10-07 20:11:19 +08:00
return result
2025-10-09 14:00:38 +08:00
2025-10-07 20:11:19 +08:00
def encode_instruction(payload_type, payload_data):
result = bytearray()
encoded_payload = bytearray()
if payload_type == 'raw_485_command':
encoded_payload = encode_raw_485_command(payload_data['bus_number'], payload_data['command_bytes'])
2025-10-17 10:32:52 +08:00
result.extend(encode_varint((1 << 3) | 2))
2025-10-07 20:11:19 +08:00
elif payload_type == 'batch_collect_command':
encoded_payload = encode_batch_collect_command(payload_data['correlation_id'], payload_data['tasks'])
2025-10-17 10:32:52 +08:00
result.extend(encode_varint((2 << 3) | 2))
2025-10-07 20:11:19 +08:00
elif payload_type == 'collect_result':
encoded_payload = encode_collect_result(payload_data['correlation_id'], payload_data['values'])
2025-10-17 10:32:52 +08:00
result.extend(encode_varint((3 << 3) | 2))
2025-10-07 20:11:19 +08:00
else:
2025-10-08 15:58:51 +08:00
raise ValueError("未知的指令负载类型")
2025-10-07 20:11:19 +08:00
result.extend(encode_varint(len(encoded_payload)))
result.extend(encoded_payload)
2025-09-25 20:14:48 +08:00
return result
2025-10-09 14:00:38 +08:00
2025-10-07 20:11:19 +08:00
def decode_instruction(buf):
2025-10-17 10:32:52 +08:00
"""解码Instruction消息 (已修复)"""
2025-10-07 20:11:19 +08:00
result = {}
pos = 0
while pos < len(buf):
tag, pos = decode_varint(buf, pos)
field_number = tag >> 3
wire_type = tag & 0x07
2025-10-17 10:32:52 +08:00
if wire_type == 2:
length, pos_after_len = decode_varint(buf, pos)
end_pos = pos_after_len + length
value_buf = buf[pos_after_len:end_pos]
2025-10-07 20:11:19 +08:00
2025-10-17 10:32:52 +08:00
if field_number == 1:
2025-10-07 20:11:19 +08:00
result['raw_485_command'] = decode_raw_485_command(value_buf)
2025-10-17 10:32:52 +08:00
elif field_number == 2:
2025-10-07 20:11:19 +08:00
result['batch_collect_command'] = decode_batch_collect_command(value_buf)
2025-10-17 10:32:52 +08:00
elif field_number == 3:
2025-10-07 20:11:19 +08:00
result['collect_result'] = decode_collect_result(value_buf)
2025-10-17 10:32:52 +08:00
pos = end_pos
2025-10-07 20:11:19 +08:00
else:
2025-10-09 14:00:38 +08:00
if wire_type == 0:
_, pos = decode_varint(buf, pos)
elif wire_type == 5:
pos += 4
else:
pos += 1
2025-10-07 20:11:19 +08:00
return result
2025-10-09 14:00:38 +08:00
2025-10-08 15:58:51 +08:00
# --- 单元测试与使用范例 ---
2025-09-25 20:14:48 +08:00
if __name__ == "__main__":
2025-10-08 15:58:51 +08:00
print("--- 测试 Raw485Command ---")
2025-10-07 20:11:19 +08:00
raw_cmd_data = {'bus_number': 1, 'command_bytes': b'\x01\x03\x00\x00\x00\x02\xc4\x0b'}
encoded_raw_cmd = encode_raw_485_command(raw_cmd_data['bus_number'], raw_cmd_data['command_bytes'])
decoded_raw_cmd = decode_raw_485_command(encoded_raw_cmd)
2025-10-17 10:32:52 +08:00
assert decoded_raw_cmd == raw_cmd_data, f"Expected {raw_cmd_data}, got {decoded_raw_cmd}"
2025-10-07 20:11:19 +08:00
2025-10-08 15:58:51 +08:00
print("\n--- 测试 CollectTask ---")
2025-10-07 20:11:19 +08:00
collect_task_data = {'command': raw_cmd_data}
encoded_collect_task = encode_collect_task(collect_task_data['command'])
decoded_collect_task = decode_collect_task(encoded_collect_task)
2025-10-17 10:32:52 +08:00
assert decoded_collect_task == collect_task_data, f"Expected {collect_task_data}, got {decoded_collect_task}"
2025-10-07 20:11:19 +08:00
2025-10-08 15:58:51 +08:00
print("\n--- 测试 BatchCollectCommand ---")
2025-10-07 20:11:19 +08:00
batch_collect_data = {
'correlation_id': 'abc-123',
'tasks': [
2025-10-17 10:32:52 +08:00
{'command': {'bus_number': 1, 'command_bytes': b'\x01\x04\x00\x01\x00\x01\x60\x0a'}},
2025-10-07 20:11:19 +08:00
{'command': {'bus_number': 2, 'command_bytes': b'\x02\x03\x00\x01\x00\x01\xd5\xfa'}}
]
}
2025-10-17 10:32:52 +08:00
encoded_batch_collect = encode_batch_collect_command(batch_collect_data['correlation_id'], batch_collect_data['tasks'])
2025-10-07 20:11:19 +08:00
decoded_batch_collect = decode_batch_collect_command(encoded_batch_collect)
2025-10-17 10:32:52 +08:00
assert decoded_batch_collect == batch_collect_data, f"Expected {batch_collect_data}, got {decoded_batch_collect}"
2025-10-07 20:11:19 +08:00
2025-10-08 15:58:51 +08:00
print("\n--- 测试 CollectResult ---")
2025-10-17 10:32:52 +08:00
collect_result_data = {'correlation_id': 'res-456', 'values': [12.34, 56.78]}
2025-10-07 20:11:19 +08:00
encoded_collect_result = encode_collect_result(collect_result_data['correlation_id'], collect_result_data['values'])
decoded_collect_result = decode_collect_result(encoded_collect_result)
assert decoded_collect_result['correlation_id'] == collect_result_data['correlation_id']
for i in range(len(collect_result_data['values'])):
2025-10-17 10:32:52 +08:00
assert abs(decoded_collect_result['values'][i] - collect_result_data['values'][i]) < 1e-5
2025-10-07 20:11:19 +08:00
2025-10-08 15:58:51 +08:00
print("\n--- 测试 Instruction (内含BatchCollectCommand) ---")
2025-10-07 20:11:19 +08:00
instruction_batch_collect = encode_instruction('batch_collect_command', batch_collect_data)
decoded_instruction_batch_collect = decode_instruction(instruction_batch_collect)
2025-10-17 10:32:52 +08:00
assert decoded_instruction_batch_collect == {'batch_collect_command': batch_collect_data}
2025-10-07 20:11:19 +08:00
2025-10-08 15:58:51 +08:00
print("\n所有测试均已通过!")