first commit
This commit is contained in:
commit
4b98219bf7
144 changed files with 31561 additions and 0 deletions
41
simulators/bots/particles.py
Normal file
41
simulators/bots/particles.py
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
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)),
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue