invole c++

This commit is contained in:
gcw_4spBpAfv
2026-01-22 17:55:11 +08:00
parent 945077a453
commit 42bfdd033c
15 changed files with 25424 additions and 1041 deletions

View File

@@ -15,6 +15,7 @@ import os
import threading
import socket
import config
from hardware import hardware_manager
from power import get_bus_voltage, voltage_to_percent
# from laser import laser_manager
@@ -56,6 +57,23 @@ class NetworkManager:
self._prefer_wifi = True # 是否优先使用WiFi
self._wifi_recv_buffer = b"" # WiFi接收缓冲区
self._initialized = True
# 导入 archery_netcore 模块,并检查是否存在 parse_packet 和 make_packet 函数
try:
import archery_netcore as _netcore
self._netcore = _netcore
if hasattr(self._netcore, "parse_packet") and hasattr(self._netcore, "make_packet") and hasattr(self._netcore, "actions_for_inner_cmd"):
print("[NET] archery_netcore found")
else:
print("[NET] archery_netcore not found parse_packet or make_packet")
exit(1)
except Exception:
print("[NET] import archery_netcore failed")
exit(1)
# 服务器相关
self._server_ip = self._netcore.get_config().get("SERVER_IP")
self._server_port = self._netcore.get_config().get("SERVER_PORT")
# ==================== 状态访问(只读属性)====================
@@ -287,7 +305,7 @@ class NetworkManager:
# 策略1如果指定优先WiFi且WiFi可用使用WiFi
if prefer_wifi and self.is_wifi_connected():
# 检查WiFi是否能连接到服务器
if self.is_server_reachable(config.SERVER_IP, config.SERVER_PORT, timeout=3):
if self.is_server_reachable(self._server_ip, self._server_port, timeout=3):
self._network_type = "wifi"
self.logger.info(f"[NET] 选择WiFi网络IP: {self._wifi_ip}")
return "wifi"
@@ -296,7 +314,7 @@ class NetworkManager:
# 策略2如果WiFi可用使用WiFi
if self.is_wifi_connected():
if self.is_server_reachable(config.SERVER_IP, config.SERVER_PORT, timeout=3):
if self.is_server_reachable(self._server_ip, self._server_port, timeout=3):
self._network_type = "wifi"
self.logger.info(f"[NET] 选择WiFi网络IP: {self._wifi_ip}")
return "wifi"
@@ -324,6 +342,27 @@ class NetworkManager:
if len(data) < 12:
return None, None
body_len, msg_type, checksum = struct.unpack(">III", data[:12])
expected_len = 12 + body_len
# 防御性检查:如果 data 比预期长,说明可能有粘包
if len(data) > expected_len:
self.logger.warning(
f"[TCP] parse_packet: data length ({len(data)}) > expected ({expected_len}), "
f"possible packet concatenation. body_len={body_len}, msg_type={msg_type}"
)
# 只解析第一个包,忽略多余数据(或者可以返回剩余部分)
# data = data[:expected_len]
# TODO 是否需要解析剩余部分?
# 如果 data 比预期短,说明包不完整(半包)
if len(data) < expected_len:
self.logger.warning(
f"[TCP] parse_packet: data length ({len(data)}) < expected ({expected_len}), "
f"incomplete packet. body_len={body_len}, msg_type={msg_type}"
)
return None, None
body = data[12:12 + body_len]
try:
return msg_type, json.loads(body.decode())
@@ -395,7 +434,7 @@ class NetworkManager:
link_id = getattr(config, "TCP_LINK_ID", 0)
use_ssl = getattr(config, "USE_TCP_SSL", False)
host = config.SERVER_IP
host = self._server_ip
port = getattr(config, "TCP_SSL_PORT", 443) if use_ssl else config.SERVER_PORT
tail = getattr(config, "MIPOPEN_TAIL", "")
with self.get_uart_lock():
@@ -641,31 +680,6 @@ class NetworkManager:
SALT = "shootMessageFire"
SALT2 = "shoot"
return "Arrow_" + hmac.new((SALT + device_id).encode(), SALT2.encode(), hashlib.sha256).hexdigest()
def send_http_cmd(self, cmd_str, timeout_ms=3000):
"""发送 HTTP 相关 AT 指令(调试用)"""
self.logger.debug(f"[HTTP AT] => {cmd_str}")
return hardware_manager.at_client.send(cmd_str, "OK", timeout_ms)
def upload_shoot_event(self,json_data):
"""通过 4G 模块上报射击事件到 HTTP 接口(备用通道)"""
token = self.generate_token(self.device_id)
if not self.send_http_cmd(f'AT+MHTTPCREATE="{config.HTTP_URL}"'):
return False
instance_id = 0
self.send_http_cmd(f'AT+MHTTPCFG="header",{instance_id},"Content-Type: application/json"')
self.send_http_cmd(f'AT+MHTTPCFG="header",{instance_id},"Authorization: {token}"')
self.send_http_cmd(f'AT+MHTTPCFG="header",{instance_id},"DeviceId: {self.device_id}"')
json_str = ujson.dumps(json_data)
if not self.send_http_cmd(f'AT+MHTTPCONTENT={instance_id},0,0,"{json_str}"'):
return False
if self.send_http_cmd(f'AT+MHTTPREQUEST={instance_id},2,0,"{config.HTTP_API_PATH}"'):
time.sleep_ms(5000)
return True
return False
def tcp_main(self):
"""TCP 主通信循环:登录、心跳、处理指令、发送数据"""
@@ -709,7 +723,8 @@ class NetworkManager:
"vol": vol_val,
"vol_per": voltage_to_percent(vol_val)
}
if not self.tcp_send_raw(self.make_packet(1, login_data)):
# if not self.tcp_send_raw(self.make_packet(1, login_data)):
if not self.tcp_send_raw(self._netcore.make_packet(1, login_data)):
self._tcp_connected = False
time.sleep_ms(2000)
continue
@@ -777,7 +792,8 @@ class NetworkManager:
except:
pass
msg_type, body = self.parse_packet(payload)
# msg_type, body = self.parse_packet(payload)
msg_type, body = self._netcore.parse_packet(payload)
# 处理登录响应
if not logged_in and msg_type == 1:
@@ -845,8 +861,12 @@ class NetworkManager:
if not laser_manager.calibration_active:
laser_manager.turn_on_laser()
time.sleep_ms(100)
laser_manager.start_calibration()
self.safe_enqueue({"result": "calibrating"}, 2)
if not config.HARDCODE_LASER_POINT:
laser_manager.start_calibration()
self.safe_enqueue({"result": "calibrating"}, 2)
else:
# 写死的逻辑,不需要校准激光点
self.safe_enqueue({"result": "laser pos set by hard code"}, 2)
elif inner_cmd == 3: # 关闭激光
from laser_manager import laser_manager
laser_manager.turn_off_laser()
@@ -962,7 +982,8 @@ class NetworkManager:
self.get_queue_lock().release()
if msg_type is not None and data_dict is not None:
pkt = self.make_packet(msg_type, data_dict)
pkt = self._netcore.make_packet(msg_type, data_dict)
# pkt = self.make_packet(msg_type, data_dict)
if not self.tcp_send_raw(pkt):
self._tcp_connected = False
break
@@ -979,7 +1000,8 @@ class NetworkManager:
current_time = time.ticks_ms()
if logged_in and current_time - last_heartbeat_send_time > config.HEARTBEAT_INTERVAL * 1000:
vol_val = get_bus_voltage()
if not self.tcp_send_raw(self.make_packet(4, {"vol": vol_val, "vol_per": voltage_to_percent(vol_val)})):
if not self.tcp_send_raw(self._netcore.make_packet(4, {"vol": vol_val, "vol_per": voltage_to_percent(vol_val)})):
# if not self.tcp_send_raw(self.make_packet(4, {"vol": vol_val, "vol_per": voltage_to_percent(vol_val)})):
self.logger.error("心跳发送失败")
time.sleep_ms(3000)
send_hartbeat_fail_count += 1