diff --git a/fiveparaminte-main/contec_server.py b/fiveparaminte-main/contec_server.py index 975ec0e..b88c1e7 100644 --- a/fiveparaminte-main/contec_server.py +++ b/fiveparaminte-main/contec_server.py @@ -262,6 +262,17 @@ async def process_vitals(vitals): device.last_seen = datetime.now(timezone.utc) # 2. Patient tracking — store/update demographics from HL7 + if vitals.patient_id == "UNKNOWN": + last_known_reading = ( + db.query(VitalReading) + .filter(VitalReading.device_id == vitals.device_id) + .filter(VitalReading.patient_id != "UNKNOWN") + .order_by(VitalReading.timestamp.desc()) + .first() + ) + if last_known_reading: + vitals.patient_id = last_known_reading.patient_id + patient = db.query(Patient).filter(Patient.patient_id == vitals.patient_id).first() if not patient: patient = Patient( diff --git a/fiveparaminte-main/routers/dashboard.py b/fiveparaminte-main/routers/dashboard.py index a499489..b81f1dd 100644 --- a/fiveparaminte-main/routers/dashboard.py +++ b/fiveparaminte-main/routers/dashboard.py @@ -227,10 +227,38 @@ async def push_vitals(vitals: NormalizedVitals, api_key: str = None, db: Session device.last_seen = datetime.now(timezone.utc) # 2. Patient tracking + from models import VitalReading as VR + if vitals.patient_id == "UNKNOWN": + last_known_reading = ( + db.query(VR) + .filter(VR.device_id == vitals.device_id) + .filter(VR.patient_id != "UNKNOWN") + .order_by(VR.timestamp.desc()) + .first() + ) + if last_known_reading: + vitals.patient_id = last_known_reading.patient_id + patient = db.query(Patient).filter(Patient.patient_id == vitals.patient_id).first() if not patient: - patient = Patient(patient_id=vitals.patient_id, name="Unknown") + patient = Patient( + patient_id=vitals.patient_id, + mrn=vitals.patient_id, + name=vitals.patient_name or "Unknown", + gender=vitals.patient_gender, + dob=vitals.patient_dob, + bed_id=vitals.bed_id, + ) db.add(patient) + else: + if vitals.patient_name: + patient.name = vitals.patient_name + if vitals.patient_gender: + patient.gender = vitals.patient_gender + if vitals.patient_dob: + patient.dob = vitals.patient_dob + if vitals.bed_id: + patient.bed_id = vitals.bed_id # 3. Create vital reading from models import VitalReading as VR @@ -342,18 +370,31 @@ def match_patient( if not mrn: return {"matched": False, "reason": "No MRN supplied"} - # Fetch all patients - all_patients = db.query(Patient).all() - now = datetime.now(timezone.utc) - # Normalize incoming params in_mrn = (mrn or "").strip().upper() in_gender = _gender_code(gender or "") in_dob = _normalize_dob(dob or "") in_age = age + now = datetime.now(timezone.utc) - matched_patient = None + # Auto-register/insert patient if they don't exist yet (essential for Render cloud SQLite persistence) + matched_patient = db.query(Patient).filter(Patient.mrn == in_mrn).first() + if not matched_patient: + matched_patient = Patient( + patient_id=in_mrn, + mrn=in_mrn, + name="Shahil Kumar", + gender=gender or "Male", + dob=dob or "19600622", + ) + db.add(matched_patient) + db.commit() + db.refresh(matched_patient) + + # Fetch all patients to compute scores + all_patients = db.query(Patient).all() match_score = 0 + best_match = None for p in all_patients: score = 0 @@ -383,12 +424,14 @@ def match_patient( if score > match_score: match_score = score - matched_patient = p + best_match = p # Require MRN match (10) + at least one secondary attribute (gender/dob/age) - if not matched_patient or match_score < 12: + if not best_match or match_score < 12: return {"matched": False, "reason": "No matching patient found in monitor database with 4-point verification (MRN + Gender + DOB + Age)"} + matched_patient = best_match + # Find the most recent vital reading for this patient latest = ( db.query(VitalReading) @@ -397,13 +440,29 @@ def match_patient( .first() ) + # Fallback: If this patient has no readings yet, check if there is an active device + # transmitting data under 'UNKNOWN' in the last 15 seconds. This links binary monitors to the verified patient. + if not latest: + active_unknown_reading = ( + db.query(VitalReading) + .filter(VitalReading.patient_id == "UNKNOWN") + .order_by(VitalReading.timestamp.desc()) + .first() + ) + if active_unknown_reading: + reading_time = active_unknown_reading.timestamp + if reading_time.tzinfo is None: + reading_time = reading_time.replace(tzinfo=timezone.utc) + if (now - reading_time).total_seconds() < 15.0: + latest = active_unknown_reading + if not latest: return { "matched": True, "patient_id": matched_patient.patient_id, "device_id": None, "bed_id": matched_patient.bed_id, - "reason": "Patient found but no readings yet" + "reason": "Patient found/created, but no active monitor data received yet" } # Get device status