"""Server-side pH simulation for the real-hardware prototype. The current BioPatch prototype (ESP32-C3 + DHT11) measures temperature and humidity only — it has no pH electrode yet. Rather than block the end-to-end demo, we synthesise a plausible wound pH so the risk engine has all three channels. This is a *labelled simulation*, never presented as a real measurement: every reading it feeds is flagged ``ph_simulated=true`` and the value stays inside a healthy, mildly-acidic granulating-wound band. Deliberately independent of the live temperature/humidity so that warming or breathing on the sensor (which legitimately moves the real channels) can never manufacture a fake alkaline "infection signature" through the pH channel. """ from __future__ import annotations import random # Healing wound surface pH sits slightly acidic; alkaline drift is the # infection marker we do NOT want to counterfeit here. _PH_BASELINE = 6.0 _PH_NOISE_SD = 0.12 _PH_MIN = 5.6 _PH_MAX = 6.6 def simulate_ph(rng: random.Random | None = None) -> float: """Return a plausible, clearly-simulated wound pH (~5.6–6.6).""" r = rng or random value = r.gauss(_PH_BASELINE, _PH_NOISE_SD) return round(max(_PH_MIN, min(_PH_MAX, value)), 2)