feat: retain last recorded patient vitals on dashboard (Option B)
This commit is contained in:
+26
-6
@@ -202,14 +202,14 @@ def list_patients(db: Session = Depends(get_db)):
|
||||
except Exception as e:
|
||||
logger.debug(f"Could not read from device_cache: {e}")
|
||||
|
||||
# Fallback or cloud/Render mode: query DB strictly within recent time window
|
||||
# Fallback or cloud/Render mode: query DB
|
||||
if merged_vitals is None:
|
||||
patient_filters = or_(
|
||||
VitalReading.patient_id == p.mrn,
|
||||
VitalReading.patient_id == p.patient_id,
|
||||
(VitalReading.device_id == p.device_id) if p.device_id else False
|
||||
)
|
||||
# Find readings within the live cutoff window (last 25 seconds)
|
||||
# 1. Try to find readings within the live cutoff window (last 25 seconds)
|
||||
recent_readings = (
|
||||
db.query(VitalReading)
|
||||
.filter(patient_filters, VitalReading.timestamp >= live_cutoff)
|
||||
@@ -217,8 +217,20 @@ def list_patients(db: Session = Depends(get_db)):
|
||||
.limit(20)
|
||||
.all()
|
||||
)
|
||||
# 2. Option B: If no live reading in last 25s, retain latest recorded readings from DB
|
||||
if not recent_readings:
|
||||
recent_readings = (
|
||||
db.query(VitalReading)
|
||||
.filter(patient_filters)
|
||||
.order_by(VitalReading.timestamp.desc())
|
||||
.limit(20)
|
||||
.all()
|
||||
)
|
||||
|
||||
if recent_readings:
|
||||
ts_iso = recent_readings[0].timestamp.isoformat() if recent_readings[0].timestamp else None
|
||||
if ts_iso and not ts_iso.endswith('Z') and '+' not in ts_iso:
|
||||
ts_iso += 'Z'
|
||||
merged_vitals = {
|
||||
"heart_rate": None,
|
||||
"spo2": None,
|
||||
@@ -229,7 +241,7 @@ def list_patients(db: Session = Depends(get_db)):
|
||||
"temperature": None,
|
||||
"temperature2": None,
|
||||
"temperature_diff": None,
|
||||
"timestamp": recent_readings[0].timestamp.isoformat() if recent_readings[0].timestamp else None,
|
||||
"timestamp": ts_iso,
|
||||
}
|
||||
for r in reversed(recent_readings):
|
||||
if r.heart_rate is not None: merged_vitals["heart_rate"] = r.heart_rate
|
||||
@@ -238,25 +250,33 @@ def list_patients(db: Session = Depends(get_db)):
|
||||
if r.temperature is not None: merged_vitals["temperature"] = r.temperature
|
||||
if getattr(r, 'temperature2', None) is not None: merged_vitals["temperature2"] = r.temperature2
|
||||
if getattr(r, 'temperature_diff', None) is not None: merged_vitals["temperature_diff"] = r.temperature_diff
|
||||
if r.systolic_bp is not None: merged_vitals["systolic_bp"] = r.systolic_bp
|
||||
if r.diastolic_bp is not None: merged_vitals["diastolic_bp"] = r.diastolic_bp
|
||||
if r.map_bp is not None: merged_vitals["map_bp"] = r.map_bp
|
||||
|
||||
# Check NIBP separately within 15 minute window
|
||||
# Check NIBP separately if not already populated
|
||||
if not merged_vitals or merged_vitals.get("systolic_bp") is None:
|
||||
r_bp = (
|
||||
db.query(VitalReading.systolic_bp, VitalReading.diastolic_bp, VitalReading.map_bp, VitalReading.timestamp)
|
||||
.filter(patient_filters, VitalReading.systolic_bp != None, VitalReading.timestamp >= nibp_cutoff)
|
||||
.filter(patient_filters, VitalReading.systolic_bp != None)
|
||||
.order_by(VitalReading.timestamp.desc())
|
||||
.first()
|
||||
)
|
||||
if r_bp:
|
||||
if merged_vitals is None:
|
||||
ts_bp = r_bp[3].isoformat() if r_bp[3] else None
|
||||
if ts_bp and not ts_bp.endswith('Z') and '+' not in ts_bp:
|
||||
ts_bp += 'Z'
|
||||
merged_vitals = {
|
||||
"heart_rate": None, "spo2": None, "respiratory_rate": None,
|
||||
"temperature": None, "temperature2": None, "temperature_diff": None,
|
||||
"timestamp": r_bp[3].isoformat() if r_bp[3] else None
|
||||
"timestamp": ts_bp
|
||||
}
|
||||
merged_vitals["systolic_bp"] = r_bp[0]
|
||||
merged_vitals["diastolic_bp"] = r_bp[1]
|
||||
merged_vitals["map_bp"] = r_bp[2]
|
||||
|
||||
|
||||
device = db.query(Device).filter(Device.device_id == p.device_id).first() if p.device_id else None
|
||||
|
||||
results.append({
|
||||
|
||||
@@ -3144,20 +3144,15 @@
|
||||
const now = Date.now();
|
||||
for (let i = readings.length - 1; i >= 0; i--) {
|
||||
const r = readings[i];
|
||||
const rAge = getTimestampAgeMs(r.timestamp);
|
||||
if (rAge <= 25000) {
|
||||
if (r.heart_rate != null) merged.heart_rate = r.heart_rate;
|
||||
if (r.spo2 != null) merged.spo2 = r.spo2;
|
||||
if (r.respiratory_rate != null) merged.respiratory_rate = r.respiratory_rate;
|
||||
if (r.temperature != null) merged.temperature = r.temperature;
|
||||
if (r.temperature2 != null) merged.temperature2 = r.temperature2;
|
||||
if (r.temperature_diff != null) merged.temperature_diff = r.temperature_diff;
|
||||
}
|
||||
if (rAge <= 900000) {
|
||||
if (r.systolic_bp != null) merged.systolic_bp = r.systolic_bp;
|
||||
if (r.diastolic_bp != null) merged.diastolic_bp = r.diastolic_bp;
|
||||
if (r.map_bp != null) merged.map_bp = r.map_bp;
|
||||
}
|
||||
if (r.patient_name) merged.patient_name = r.patient_name;
|
||||
if (r.mrn || r.patient_id) merged.mrn = r.mrn || r.patient_id;
|
||||
if (r.bed_id) merged.bed_id = r.bed_id;
|
||||
@@ -3237,20 +3232,15 @@
|
||||
const now = Date.now();
|
||||
for (let i = readings.length - 1; i >= 0; i--) {
|
||||
const r = readings[i];
|
||||
const rAge = getTimestampAgeMs(r.timestamp);
|
||||
if (rAge <= 25000) {
|
||||
if (r.heart_rate != null) merged.heart_rate = r.heart_rate;
|
||||
if (r.spo2 != null) merged.spo2 = r.spo2;
|
||||
if (r.respiratory_rate != null) merged.respiratory_rate = r.respiratory_rate;
|
||||
if (r.temperature != null) merged.temperature = r.temperature;
|
||||
if (r.temperature2 != null) merged.temperature2 = r.temperature2;
|
||||
if (r.temperature_diff != null) merged.temperature_diff = r.temperature_diff;
|
||||
}
|
||||
if (rAge <= 900000) {
|
||||
if (r.systolic_bp != null) merged.systolic_bp = r.systolic_bp;
|
||||
if (r.diastolic_bp != null) merged.diastolic_bp = r.diastolic_bp;
|
||||
if (r.map_bp != null) merged.map_bp = r.map_bp;
|
||||
}
|
||||
if (r.patient_name) merged.patient_name = r.patient_name;
|
||||
if (r.mrn || r.patient_id) merged.mrn = r.mrn || r.patient_id;
|
||||
if (r.bed_id) merged.bed_id = r.bed_id;
|
||||
@@ -3669,20 +3659,6 @@
|
||||
if (readings.length > 0) {
|
||||
const now = Date.now();
|
||||
readings.forEach(r => {
|
||||
const rAge = getTimestampAgeMs(r.timestamp);
|
||||
if (rAge > 25000) {
|
||||
r.heart_rate = null;
|
||||
r.spo2 = null;
|
||||
r.respiratory_rate = null;
|
||||
r.temperature = null;
|
||||
r.temperature2 = null;
|
||||
r.temperature_diff = null;
|
||||
}
|
||||
if (rAge > 900000) {
|
||||
r.systolic_bp = null;
|
||||
r.diastolic_bp = null;
|
||||
r.map_bp = null;
|
||||
}
|
||||
if (r.id !== lastReadingId) {
|
||||
lastReadingId = r.id;
|
||||
readingCount++;
|
||||
@@ -3761,17 +3737,13 @@
|
||||
if (devKey && connectedDevices[devKey]) {
|
||||
const dev = connectedDevices[devKey];
|
||||
const rAge = getTimestampAgeMs(r.timestamp);
|
||||
if (rAge <= 25000) {
|
||||
if ((dev.heart_rate === undefined || dev.heart_rate === null) && r.heart_rate != null) dev.heart_rate = r.heart_rate;
|
||||
if ((dev.spo2 === undefined || dev.spo2 === null) && r.spo2 != null) dev.spo2 = r.spo2;
|
||||
if ((dev.respiratory_rate === undefined || dev.respiratory_rate === null) && r.respiratory_rate != null) dev.respiratory_rate = r.respiratory_rate;
|
||||
if ((dev.temperature === undefined || dev.temperature === null) && r.temperature != null) dev.temperature = r.temperature;
|
||||
}
|
||||
if (rAge <= 900000) {
|
||||
if ((dev.systolic_bp === undefined || dev.systolic_bp === null) && r.systolic_bp != null) dev.systolic_bp = r.systolic_bp;
|
||||
if ((dev.diastolic_bp === undefined || dev.diastolic_bp === null) && r.diastolic_bp != null) dev.diastolic_bp = r.diastolic_bp;
|
||||
if ((dev.map_bp === undefined || dev.map_bp === null) && r.map_bp != null) dev.map_bp = r.map_bp;
|
||||
}
|
||||
if (!dev.lastSeen && r.timestamp) dev.lastSeen = new Date(r.timestamp);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user