working server for real mock data
This commit is contained in:
@@ -7,6 +7,7 @@ import asyncio
|
||||
import struct
|
||||
import random
|
||||
import time
|
||||
import aiohttp
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict, List, Optional
|
||||
from enum import IntFlag
|
||||
@@ -347,6 +348,17 @@ class BaseStationSimulator:
|
||||
"checksum": f"0x{checksum:02X}",
|
||||
}
|
||||
|
||||
async def send_to_backend(self, decoded_data: dict):
|
||||
"""Send vitals data to backend API"""
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
await session.post(
|
||||
"http://localhost:8000/api/vitals", json=decoded_data
|
||||
)
|
||||
except Exception as e:
|
||||
# Silently fail if backend not available
|
||||
pass
|
||||
|
||||
async def simulate_band_transmission(self, band_id: str):
|
||||
"""Simulate continuous transmission from one wristband"""
|
||||
band = self.wristbands[band_id]
|
||||
@@ -369,6 +381,9 @@ class BaseStationSimulator:
|
||||
# Log packet
|
||||
self.packet_log.append(decoded)
|
||||
|
||||
# Send to backend API
|
||||
await self.send_to_backend(decoded)
|
||||
|
||||
# Print to console
|
||||
tier_symbol = (
|
||||
"🔴"
|
||||
@@ -384,9 +399,6 @@ class BaseStationSimulator:
|
||||
f"Seq={decoded['seq']}"
|
||||
)
|
||||
|
||||
# Send to backend API (in production)
|
||||
# await self.send_to_api(decoded)
|
||||
|
||||
await asyncio.sleep(interval)
|
||||
|
||||
async def run(self):
|
||||
@@ -402,7 +414,7 @@ class BaseStationSimulator:
|
||||
]
|
||||
|
||||
# Run until stopped
|
||||
await asyncio.gather(*tasks)
|
||||
await asyncio.gather(*tasks, return_exceptions=True)
|
||||
|
||||
def stop(self):
|
||||
"""Stop the simulation"""
|
||||
@@ -428,68 +440,101 @@ class BaseStationSimulator:
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# DEMO / TEST SCENARIOS
|
||||
# AUTO CHECK-IN FUNCTION
|
||||
# ============================================================================
|
||||
|
||||
|
||||
async def demo_scenario_1():
|
||||
"""Demo: Mix of stable and deteriorating patients"""
|
||||
print("\n" + "=" * 80)
|
||||
print("DEMO SCENARIO 1: Mixed Patient Population")
|
||||
print("=" * 80 + "\n")
|
||||
async def auto_checkin_patients():
|
||||
"""Automatically check in patients via API"""
|
||||
patients = [
|
||||
{
|
||||
"firstName": "John",
|
||||
"lastName": "Smith",
|
||||
"dob": "1985-03-15",
|
||||
"symptoms": ["Chest Pain"],
|
||||
"severity": "mild",
|
||||
},
|
||||
{
|
||||
"firstName": "Sarah",
|
||||
"lastName": "Johnson",
|
||||
"dob": "1990-07-22",
|
||||
"symptoms": ["Fever", "Difficulty Breathing"],
|
||||
"severity": "moderate",
|
||||
},
|
||||
{
|
||||
"firstName": "Michael",
|
||||
"lastName": "Chen",
|
||||
"dob": "1978-11-05",
|
||||
"symptoms": ["Severe Headache"],
|
||||
"severity": "severe",
|
||||
},
|
||||
]
|
||||
|
||||
base = BaseStationSimulator()
|
||||
|
||||
# Add various patients
|
||||
base.add_wristband("VitalLink-A1B2", "stable", "P100001")
|
||||
base.add_wristband("VitalLink-C3D4", "mild_anxiety", "P100002")
|
||||
base.add_wristband("VitalLink-E5F6", "deteriorating", "P100003")
|
||||
|
||||
# Run for 30 seconds
|
||||
assigned = []
|
||||
try:
|
||||
await asyncio.wait_for(base.run(), timeout=30.0)
|
||||
except asyncio.TimeoutError:
|
||||
base.stop()
|
||||
async with aiohttp.ClientSession() as session:
|
||||
for patient_data in patients:
|
||||
async with session.post(
|
||||
"http://localhost:8000/api/checkin", json=patient_data
|
||||
) as resp:
|
||||
if resp.status == 200:
|
||||
data = await resp.json()
|
||||
assigned.append(data)
|
||||
print(
|
||||
f"[CHECKIN] {patient_data['firstName']} {patient_data['lastName']} → {data['patient_id']} / {data['band_id']}"
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Could not check in patients: {e}")
|
||||
print("[INFO] Make sure backend is running at http://localhost:8000")
|
||||
return []
|
||||
|
||||
return assigned
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# MAIN - CONTINUOUS MODE
|
||||
# ============================================================================
|
||||
|
||||
|
||||
async def continuous_mode():
|
||||
"""Run simulator continuously, sending data to backend"""
|
||||
print("\n" + "=" * 80)
|
||||
print("SUMMARY:")
|
||||
print(base.get_summary())
|
||||
print("=" * 80)
|
||||
|
||||
|
||||
async def demo_scenario_2():
|
||||
"""Demo: Critical patient arrival"""
|
||||
print("\n" + "=" * 80)
|
||||
print("DEMO SCENARIO 2: Critical Patient Emergency")
|
||||
print("CONTINUOUS MODE: Sending data to backend at http://localhost:8000")
|
||||
print("=" * 80 + "\n")
|
||||
|
||||
# Auto check-in patients first
|
||||
print("Checking in patients...")
|
||||
assigned = await auto_checkin_patients()
|
||||
|
||||
if not assigned:
|
||||
print("\n[ERROR] No patients checked in. Is the backend running?")
|
||||
print("[INFO] Start backend with: python backend/server.py")
|
||||
return
|
||||
|
||||
print()
|
||||
|
||||
base = BaseStationSimulator()
|
||||
|
||||
# Start with stable patients
|
||||
base.add_wristband("VitalLink-1111", "stable", "P200001")
|
||||
base.add_wristband("VitalLink-2222", "stable", "P200002")
|
||||
# Add wristbands using the assigned IDs
|
||||
profiles = ["stable", "mild_anxiety", "deteriorating"]
|
||||
for i, assignment in enumerate(assigned):
|
||||
profile = profiles[i] if i < len(profiles) else "stable"
|
||||
base.add_wristband(assignment["band_id"], profile, assignment["patient_id"])
|
||||
|
||||
# Simulate for 10 seconds
|
||||
async def add_critical_patient():
|
||||
await asyncio.sleep(10)
|
||||
print("\n⚠️ CRITICAL PATIENT ARRIVED ⚠️\n")
|
||||
base.add_wristband("VitalLink-9999", "critical", "P200999")
|
||||
|
||||
# Run both tasks
|
||||
await asyncio.gather(
|
||||
add_critical_patient(), asyncio.wait_for(base.run(), timeout=25.0)
|
||||
)
|
||||
|
||||
base.stop()
|
||||
print("\n" + "=" * 80)
|
||||
print("SUMMARY:")
|
||||
print(base.get_summary())
|
||||
print("\nPress Ctrl+C to stop\n")
|
||||
print("=" * 80)
|
||||
|
||||
# Run indefinitely
|
||||
try:
|
||||
await base.run()
|
||||
except KeyboardInterrupt:
|
||||
base.stop()
|
||||
print("\n" + "=" * 80)
|
||||
print("SUMMARY:")
|
||||
print(base.get_summary())
|
||||
print("=" * 80)
|
||||
print("\n[BASE] Simulator stopped by user")
|
||||
|
||||
# ============================================================================
|
||||
# MAIN
|
||||
# ============================================================================
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("""
|
||||
@@ -504,16 +549,7 @@ Available Patient Profiles:
|
||||
- deteriorating: Gradually worsening condition
|
||||
- critical: Severe vitals, triggers emergency tier
|
||||
- sepsis: Rapid deterioration pattern
|
||||
|
||||
Usage Examples:
|
||||
1. Run demo scenarios (below)
|
||||
2. Create custom scenarios using BaseStationSimulator
|
||||
3. Integrate with FastAPI backend for web portal
|
||||
""")
|
||||
|
||||
# Choose a demo to run
|
||||
print("\nRunning Demo Scenario 1...\n")
|
||||
asyncio.run(demo_scenario_1())
|
||||
|
||||
# Uncomment to run other scenarios:
|
||||
# asyncio.run(demo_scenario_2())
|
||||
# Run continuous mode
|
||||
asyncio.run(continuous_mode())
|
||||
|
||||
Reference in New Issue
Block a user