add dashboard monitoring interface and dual temperature tracking
This commit is contained in:
+22
-23
@@ -58,13 +58,14 @@ CONTEC_PARAM_MAP = {
|
|||||||
# Temperature
|
# Temperature
|
||||||
"TEMP": "temperature",
|
"TEMP": "temperature",
|
||||||
"TEMP1": "temperature",
|
"TEMP1": "temperature",
|
||||||
"TEMP2": "temperature",
|
"TEMP2": "temperature2",
|
||||||
"T1": "temperature",
|
"T1": "temperature",
|
||||||
"T2": "temperature",
|
"T2": "temperature2",
|
||||||
"BODY_TEMP": "temperature",
|
"BODY_TEMP": "temperature",
|
||||||
"TEMP-1": "temperature",
|
"TEMP-1": "temperature",
|
||||||
"TEMP-2": "temperature",
|
"TEMP-2": "temperature2",
|
||||||
"BODYTEMP": "temperature",
|
"BODYTEMP": "temperature",
|
||||||
|
"TD": "temperature_diff",
|
||||||
}
|
}
|
||||||
|
|
||||||
# Sentinel value used by Contec to mark an invalid/disconnected parameter
|
# Sentinel value used by Contec to mark an invalid/disconnected parameter
|
||||||
@@ -304,7 +305,7 @@ def _parse_45_byte_packet(data: bytes, vitals_dict: dict) -> bool:
|
|||||||
|
|
||||||
def _parse_56_byte_packet(data: bytes, vitals_dict: dict) -> bool:
|
def _parse_56_byte_packet(data: bytes, vitals_dict: dict) -> bool:
|
||||||
"""
|
"""
|
||||||
Parse 56-byte packet (Subtype 23) — contains float32 Temperature values.
|
Parse 56-byte packet (Subtype 23) — contains float32 Temperature values for T1 and T2.
|
||||||
|
|
||||||
Verified layout:
|
Verified layout:
|
||||||
[8-11] Temperature 1 (float32)
|
[8-11] Temperature 1 (float32)
|
||||||
@@ -318,8 +319,6 @@ def _parse_56_byte_packet(data: bytes, vitals_dict: dict) -> bool:
|
|||||||
if "present_fields" not in vitals_dict:
|
if "present_fields" not in vitals_dict:
|
||||||
vitals_dict["present_fields"] = []
|
vitals_dict["present_fields"] = []
|
||||||
|
|
||||||
found = False
|
|
||||||
|
|
||||||
temp1 = read_f32_le(data, 8)
|
temp1 = read_f32_le(data, 8)
|
||||||
temp2 = read_f32_le(data, 12)
|
temp2 = read_f32_le(data, 12)
|
||||||
|
|
||||||
@@ -327,24 +326,24 @@ def _parse_56_byte_packet(data: bytes, vitals_dict: dict) -> bool:
|
|||||||
# Disconnected sentinel is 9999.0 or 3276.7 (0x7FFF)
|
# Disconnected sentinel is 9999.0 or 3276.7 (0x7FFF)
|
||||||
return t is not None and is_valid_f32(t) and abs(t - 3276.7) > 1.0 and 20.0 < t < 45.0
|
return t is not None and is_valid_f32(t) and abs(t - 3276.7) > 1.0 and 20.0 < t < 45.0
|
||||||
|
|
||||||
if is_real_temp(temp1):
|
t1_val = round(temp1, 1) if is_real_temp(temp1) else None
|
||||||
vitals_dict["temperature"] = round(temp1, 1)
|
t2_val = round(temp2, 1) if is_real_temp(temp2) else None
|
||||||
if "temperature" not in vitals_dict["present_fields"]:
|
|
||||||
vitals_dict["present_fields"].append("temperature")
|
|
||||||
found = True
|
|
||||||
elif is_real_temp(temp2):
|
|
||||||
vitals_dict["temperature"] = round(temp2, 1)
|
|
||||||
if "temperature" not in vitals_dict["present_fields"]:
|
|
||||||
vitals_dict["present_fields"].append("temperature")
|
|
||||||
found = True
|
|
||||||
elif temp1 is not None or temp2 is not None:
|
|
||||||
# Sensor disconnected / off
|
|
||||||
vitals_dict["temperature"] = None
|
|
||||||
if "temperature" not in vitals_dict["present_fields"]:
|
|
||||||
vitals_dict["present_fields"].append("temperature")
|
|
||||||
found = True
|
|
||||||
|
|
||||||
return found
|
vitals_dict["temperature"] = t1_val
|
||||||
|
vitals_dict["temperature2"] = t2_val
|
||||||
|
if t1_val is not None and t2_val is not None:
|
||||||
|
vitals_dict["temperature_diff"] = round(abs(t1_val - t2_val), 1)
|
||||||
|
else:
|
||||||
|
vitals_dict["temperature_diff"] = None
|
||||||
|
|
||||||
|
if "temperature" not in vitals_dict["present_fields"]:
|
||||||
|
vitals_dict["present_fields"].append("temperature")
|
||||||
|
if "temperature2" not in vitals_dict["present_fields"]:
|
||||||
|
vitals_dict["present_fields"].append("temperature2")
|
||||||
|
if "temperature_diff" not in vitals_dict["present_fields"]:
|
||||||
|
vitals_dict["present_fields"].append("temperature_diff")
|
||||||
|
|
||||||
|
return (t1_val is not None or t2_val is not None)
|
||||||
|
|
||||||
|
|
||||||
def _parse_spo2_waveform_packet(data: bytes, vitals_dict: dict) -> bool:
|
def _parse_spo2_waveform_packet(data: bytes, vitals_dict: dict) -> bool:
|
||||||
|
|||||||
@@ -598,6 +598,8 @@ async def _persist_and_forward_bg(vitals, should_persist):
|
|||||||
map_bp=vitals.map_bp,
|
map_bp=vitals.map_bp,
|
||||||
respiratory_rate=vitals.respiratory_rate,
|
respiratory_rate=vitals.respiratory_rate,
|
||||||
temperature=vitals.temperature,
|
temperature=vitals.temperature,
|
||||||
|
temperature2=vitals.temperature2,
|
||||||
|
temperature_diff=vitals.temperature_diff,
|
||||||
transmitted=False
|
transmitted=False
|
||||||
)
|
)
|
||||||
db.add(reading)
|
db.add(reading)
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ class VitalReading(Base):
|
|||||||
map_bp = Column(Float, nullable=True)
|
map_bp = Column(Float, nullable=True)
|
||||||
respiratory_rate = Column(Float, nullable=True)
|
respiratory_rate = Column(Float, nullable=True)
|
||||||
temperature = Column(Float, nullable=True)
|
temperature = Column(Float, nullable=True)
|
||||||
|
temperature2 = Column(Float, nullable=True)
|
||||||
|
temperature_diff = Column(Float, nullable=True)
|
||||||
transmitted = Column(Boolean, default=False, index=True)
|
transmitted = Column(Boolean, default=False, index=True)
|
||||||
|
|
||||||
class TransmissionLog(Base):
|
class TransmissionLog(Base):
|
||||||
|
|||||||
@@ -192,6 +192,8 @@ def list_patients(db: Session = Depends(get_db)):
|
|||||||
"map_bp": latest_reading.map_bp if latest_reading else None,
|
"map_bp": latest_reading.map_bp if latest_reading else None,
|
||||||
"respiratory_rate": latest_reading.respiratory_rate if latest_reading else None,
|
"respiratory_rate": latest_reading.respiratory_rate if latest_reading else None,
|
||||||
"temperature": latest_reading.temperature if latest_reading else None,
|
"temperature": latest_reading.temperature if latest_reading else None,
|
||||||
|
"temperature2": getattr(latest_reading, 'temperature2', None) if latest_reading else None,
|
||||||
|
"temperature_diff": getattr(latest_reading, 'temperature_diff', None) if latest_reading else None,
|
||||||
"timestamp": latest_reading.timestamp.isoformat() if (latest_reading and latest_reading.timestamp) else None,
|
"timestamp": latest_reading.timestamp.isoformat() if (latest_reading and latest_reading.timestamp) else None,
|
||||||
} if latest_reading else None
|
} if latest_reading else None
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ class NormalizedVitals(BaseModel):
|
|||||||
map_bp: Optional[float] = None
|
map_bp: Optional[float] = None
|
||||||
respiratory_rate: Optional[float] = None
|
respiratory_rate: Optional[float] = None
|
||||||
temperature: Optional[float] = None
|
temperature: Optional[float] = None
|
||||||
|
temperature2: Optional[float] = None
|
||||||
|
temperature_diff: Optional[float] = None
|
||||||
present_fields: Optional[list] = None
|
present_fields: Optional[list] = None
|
||||||
# Raw waveform sample arrays (8-bit unsigned, 0-255)
|
# Raw waveform sample arrays (8-bit unsigned, 0-255)
|
||||||
ecg_wave: Optional[List[int]] = None # ECG waveform samples from 989-byte packet
|
ecg_wave: Optional[List[int]] = None # ECG waveform samples from 989-byte packet
|
||||||
|
|||||||
+1569
-159
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user