BMS/simulators/bots/particles.py
2026-03-19 11:32:17 +00:00

41 lines
1.3 KiB
Python

import math
import random
from bots.base import BaseBot
# ISO 14644-1 Class 8 limits
ISO8_0_5UM = 3_520_000 # particles/m³ ≥0.5 µm
ISO8_5UM = 29_300 # particles/m³ ≥5 µm
class ParticleBot(BaseBot):
"""Air quality / particle count sensor — one per room."""
interval = 60 # publish every 60 s
def __init__(self, site_id: str, room_id: str) -> None:
super().__init__()
self.site_id = site_id
self.room_id = room_id
# Normal operating baseline — well below ISO 8
self._base_0_5 = random.uniform(60_000, 120_000)
self._base_5 = random.uniform(200, 600)
def get_topic(self) -> str:
return f"bms/{self.site_id}/{self.room_id}/particles"
def get_payload(self) -> dict:
drift = math.sin(self._scenario_step * 0.05) * 0.1
p0_5 = self._base_0_5 * (1 + drift) + random.gauss(0, 3_000)
p5 = self._base_5 * (1 + drift) + random.gauss(0, 20)
if self._scenario == "PARTICLE_SPIKE":
spike = min(self._scenario_step * 50_000, ISO8_0_5UM * 1.5)
p0_5 += spike
p5 += spike * (ISO8_5UM / ISO8_0_5UM)
return {
"particles_0_5um": max(0, round(p0_5)),
"particles_5um": max(0, round(p5)),
}