去队列
This commit is contained in:
@@ -384,15 +384,13 @@ class BtSerial:
|
||||
class MobileService:
|
||||
"""
|
||||
手机通信主服务。
|
||||
- 后台线程处理串口读写 + 协议解析
|
||||
- 手机发 ?0100 轮询时自动发送排队测量数据
|
||||
- 后台线程处理串口读写 + 协议解析 (握手/控制码自动响应)
|
||||
- 收到 send 命令时直接发送数据,不等手机轮询
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.serial: Optional[BtSerial] = None
|
||||
self.proto = ProtocolHandler()
|
||||
self._pending: list[tuple[bytes, bytes]] = [] # 待发送测量数据
|
||||
self._sent_count = 0
|
||||
self._poll_thread: Optional[threading.Thread] = None
|
||||
self._log_cb = None
|
||||
|
||||
@@ -408,14 +406,6 @@ class MobileService:
|
||||
def phone_connected(self) -> bool:
|
||||
return self.serial is not None and self.serial.phone_connected
|
||||
|
||||
@property
|
||||
def sent_count(self) -> int:
|
||||
return self._sent_count
|
||||
|
||||
@property
|
||||
def pending_count(self) -> int:
|
||||
return len(self._pending)
|
||||
|
||||
# ── 连接 ──
|
||||
|
||||
def connect(self, port: str) -> bool:
|
||||
@@ -449,64 +439,38 @@ class MobileService:
|
||||
self._poll_thread = None
|
||||
|
||||
def _poll_loop(self):
|
||||
"""后台轮询 — 处理收数据 + 自动响应"""
|
||||
"""后台轮询 — 处理收数据 + 自动响应握手/控制码"""
|
||||
while self.serial and self.serial.running:
|
||||
try:
|
||||
data = self.serial.read_all()
|
||||
if data:
|
||||
responses, has_query = self.proto.feed(data)
|
||||
responses, _ = self.proto.feed(data)
|
||||
|
||||
# 发送协议响应 (握手/控制码)
|
||||
for rsp in responses:
|
||||
self.serial.write(rsp)
|
||||
|
||||
# 手机轮询 (±0100) + 有待发送数据 → 发送
|
||||
if has_query and self._pending:
|
||||
self._send_data()
|
||||
|
||||
time.sleep(0.05)
|
||||
except Exception:
|
||||
time.sleep(0.1)
|
||||
|
||||
# ── 数据发送 ──
|
||||
# ── 数据发送 (直接发,不等轮询) ──
|
||||
|
||||
def send_measurement(self, staff_reading: float, distance: float) -> bool:
|
||||
"""直接构建 M5 两帧并通过串口发送"""
|
||||
if not self.serial or not self.serial.running:
|
||||
self._log("⚠ 串口未打开")
|
||||
return False
|
||||
|
||||
def queue_measurement(self, staff_reading: float, distance: float):
|
||||
"""将测量数据加入发送队列"""
|
||||
line1, line2 = MeasurementBuilder.build(staff_reading, distance)
|
||||
self._pending.append((line1, line2))
|
||||
self._log(f"+ 队列: R={staff_reading:.5f}m HD={distance:.3f}m "
|
||||
f"(共{len(self._pending)}条)")
|
||||
|
||||
def _send_data(self):
|
||||
"""发送队列中第一条 (由轮询触发)"""
|
||||
if not self._pending or not self.serial:
|
||||
return
|
||||
line1, line2 = self._pending.pop(0)
|
||||
|
||||
self.serial.write(line1)
|
||||
time.sleep(0.03) # 两帧间隔 (模拟水准仪)
|
||||
self.serial.write(line2)
|
||||
|
||||
self._sent_count += 1
|
||||
self._log(f"↑ 发送 #{self._sent_count}")
|
||||
|
||||
def force_send(self, ignore_phone: bool = False) -> bool:
|
||||
"""强制发送 (不等轮询)"""
|
||||
if not self.serial or not self.serial.running:
|
||||
self._log("⚠ 串口未打开")
|
||||
return False
|
||||
if not self.serial.phone_connected and not ignore_phone:
|
||||
self._log("⚠ 手机未连接")
|
||||
return False
|
||||
if not self._pending:
|
||||
self._log("⚠ 无待发送数据")
|
||||
return False
|
||||
self._send_data()
|
||||
self._log(f"↑ 直接发送: R={staff_reading:.5f}m HD={distance:.3f}m")
|
||||
return True
|
||||
|
||||
def clear_queue(self):
|
||||
self._pending.clear()
|
||||
|
||||
|
||||
# ════════════════════════════════════════════════════════════════
|
||||
# FastAPI — 全局状态
|
||||
@@ -563,8 +527,6 @@ async def status():
|
||||
info = {
|
||||
"connected": svc.connected,
|
||||
"phone_connected": svc.phone_connected,
|
||||
"pending_count": svc.pending_count,
|
||||
"sent_count": svc.sent_count,
|
||||
}
|
||||
if svc.serial:
|
||||
info["port"] = svc.serial.port
|
||||
@@ -587,8 +549,6 @@ async def test():
|
||||
"connected": True,
|
||||
"port": svc.serial.port,
|
||||
"phone_connected": svc.phone_connected,
|
||||
"pending_count": svc.pending_count,
|
||||
"sent_count": svc.sent_count,
|
||||
"total_rx": svc.serial.total_rx,
|
||||
"total_tx": svc.serial.total_tx,
|
||||
}
|
||||
@@ -633,9 +593,7 @@ async def send_command(req: CommandRequest):
|
||||
发送命令。
|
||||
|
||||
支持的命令:
|
||||
send <R> <HD> → 添加测量到队列 如: "send 0.89182 3.323"
|
||||
force → 强制发送队列中数据 (不等轮询)
|
||||
clear → 清空待发送队列
|
||||
send <R> <HD> → 直接发送测量数据 如: "send 0.89182 3.323"
|
||||
disconnect → 断开蓝牙连接
|
||||
"""
|
||||
cmd = req.cmd.strip()
|
||||
@@ -663,37 +621,20 @@ async def send_command(req: CommandRequest):
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=400, detail="参数必须是数字")
|
||||
|
||||
def _queue():
|
||||
def _send():
|
||||
with svc_lock:
|
||||
if not svc.connected:
|
||||
raise HTTPException(status_code=400,
|
||||
detail="未连接, 请先 POST /connect")
|
||||
svc.queue_measurement(r, hd)
|
||||
ok = svc.send_measurement(r, hd)
|
||||
return {
|
||||
"command": "send",
|
||||
"staff_reading": r,
|
||||
"distance": hd,
|
||||
"pending_count": svc.pending_count,
|
||||
"status": "ok" if ok else "error",
|
||||
}
|
||||
loop = asyncio.get_running_loop()
|
||||
return await loop.run_in_executor(None, _queue)
|
||||
|
||||
if action == "force":
|
||||
def _force():
|
||||
with svc_lock:
|
||||
ok = svc.force_send(ignore_phone=False)
|
||||
return {
|
||||
"command": "force",
|
||||
"status": "ok" if ok else "skipped",
|
||||
"pending_count": svc.pending_count,
|
||||
}
|
||||
loop = asyncio.get_running_loop()
|
||||
return await loop.run_in_executor(None, _force)
|
||||
|
||||
if action == "clear":
|
||||
with svc_lock:
|
||||
svc.clear_queue()
|
||||
return {"command": "clear", "pending_count": svc.pending_count}
|
||||
return await loop.run_in_executor(None, _send)
|
||||
|
||||
# ── 原始数据发送 ──
|
||||
if not svc.connected:
|
||||
|
||||
Reference in New Issue
Block a user