fix: delay added to ensure tcp commands dont talk over eachother

This commit is contained in:
serversdwn
2026-02-16 02:42:41 +00:00
parent e6ac80df6c
commit 005e0091fe
2 changed files with 18 additions and 8 deletions

View File

@@ -545,12 +545,6 @@ async def stop_measurement(unit_id: str, db: Session = Depends(get_db)):
try: try:
await client.stop() await client.stop()
logger.info(f"Stopped measurement on unit {unit_id}") logger.info(f"Stopped measurement on unit {unit_id}")
# Query device status to update database with "Stop" state
snap = await client.request_dod()
snap.unit_id = unit_id
persist_snapshot(snap, db)
except ConnectionError as e: except ConnectionError as e:
logger.error(f"Failed to stop measurement on {unit_id}: {e}") logger.error(f"Failed to stop measurement on {unit_id}: {e}")
raise HTTPException(status_code=502, detail="Failed to communicate with device") raise HTTPException(status_code=502, detail="Failed to communicate with device")
@@ -560,6 +554,15 @@ async def stop_measurement(unit_id: str, db: Session = Depends(get_db)):
except Exception as e: except Exception as e:
logger.error(f"Unexpected error stopping measurement on {unit_id}: {e}") logger.error(f"Unexpected error stopping measurement on {unit_id}: {e}")
raise HTTPException(status_code=500, detail="Internal server error") raise HTTPException(status_code=500, detail="Internal server error")
# Query device status to update database — non-fatal if this fails
try:
snap = await client.request_dod()
snap.unit_id = unit_id
persist_snapshot(snap, db)
except Exception as e:
logger.warning(f"Stop succeeded but failed to update status for {unit_id}: {e}")
return {"status": "ok", "message": "Measurement stopped"} return {"status": "ok", "message": "Measurement stopped"}

View File

@@ -245,7 +245,12 @@ class NL43Client:
self.device_key = f"{host}:{port}" self.device_key = f"{host}:{port}"
async def _enforce_rate_limit(self): async def _enforce_rate_limit(self):
"""Ensure ≥1 second between commands to the same device.""" """Ensure ≥1 second between commands to the same device.
NL43 protocol requires ≥1s after the device responds before sending
the next command. The timestamp is recorded after each command completes
(connection closed), so we measure from completion, not from send time.
"""
async with _rate_limit_lock: async with _rate_limit_lock:
last_time = _last_command_time.get(self.device_key, 0) last_time = _last_command_time.get(self.device_key, 0)
elapsed = time.time() - last_time elapsed = time.time() - last_time
@@ -253,7 +258,6 @@ class NL43Client:
wait_time = 1.0 - elapsed wait_time = 1.0 - elapsed
logger.debug(f"Rate limiting: waiting {wait_time:.2f}s for {self.device_key}") logger.debug(f"Rate limiting: waiting {wait_time:.2f}s for {self.device_key}")
await asyncio.sleep(wait_time) await asyncio.sleep(wait_time)
_last_command_time[self.device_key] = time.time()
async def _send_command(self, cmd: str) -> str: async def _send_command(self, cmd: str) -> str:
"""Send ASCII command to NL43 device via TCP. """Send ASCII command to NL43 device via TCP.
@@ -334,6 +338,9 @@ class NL43Client:
writer.close() writer.close()
with contextlib.suppress(Exception): with contextlib.suppress(Exception):
await writer.wait_closed() await writer.wait_closed()
# Record completion time for rate limiting — NL43 requires ≥1s
# after response before next command, so measure from connection close
_last_command_time[self.device_key] = time.time()
async def request_dod(self) -> NL43Snapshot: async def request_dod(self) -> NL43Snapshot:
"""Request DOD (Data Output Display) snapshot from device. """Request DOD (Data Output Display) snapshot from device.