A lightweight generator of dummy sensor data for IoT and ML testing. Provides a simple Python API and CLI, supports running multiple sensors in parallel, photovoltaic domain sensors, and splitting output streams into files.
From PyPI (recommended):
pip install dummysensorsfrom dummysensors import TemperatureSensor, VibrationSensor
# create sensors
temp = TemperatureSensor(min_val=18, max_val=24, noise=0.2)
vib = VibrationSensor(base_hz=50.0, amp=1.0, noise=0.05)
print(temp.read()) # e.g. 21.3
print(vib.read(t_s=0.123)) # sinusoidal signal with noiseInstead of passing long --spec strings, you can define your setup in a YAML file.
By default, dummy-sensors run --config config.sensors.yaml will look for a file named config.sensors.yaml in the current directory.
rate: 2
count: 5
partition_by: type
outputs:
- type: jsonl
for: temp
path: out/temp.jsonl
- type: csv
for: vibration
path: out/vibration.csv
devices:
- id: engine-A
sensors:
- kind: temp
count: 1
- kind: vibration
count: 1
- id: plant-1
sensors:
- kind: irradiance
count: 1
params: {peak: 900.0, day_period_s: 10.0, sunrise: 0.0, sunset: 10.0}
- kind: pv_power
count: 1
params: {stc_kw: 5.0, inverter_eff: 0.95, p_kw_max: 4.8}
- kind: load
count: 1
params: {base_kw: 0.3, morning_kw: 0.8, evening_kw: 1.2}
- kind: soc
count: 1
params: {capacity_kwh: 10.0, soc0: 50.0}Run with:
dummy-sensors run --config config.sensors.yamlGenerate a single temperature stream to JSONL:
dummy-sensors generate --rate 5 --duration 2 --jsonl out/temp.jsonlRun multiple sensors and devices, split by type into separate files:
dummy-sensors run \
--rate 5 \
--count 30 \
--spec "device=engine-A: temp*1,vibration*2; device=room-101: temp*2" \
--out "temp=out/temp.jsonl" \
--out "vibration=out/vib.jsonl" \
--out "*=stdout"👉 Check out a full demo with live plotting and JSONL logging here: dummysensors demo (ds-test)
The --spec string describes devices and sensors:
device=<ID>: <type>*<count>[, <type>*<count> ...] ; device=<ID2>: ...
Examples:
device=A: temp*3— device A with three temperature sensorsdevice=eng: temp*1,vibration*2; device=room: temp*2
As of
v0.3, supported sensor types:temp,vibration,irradiance,pv_power,load,soc. You can define setups either with--spec(quick inline config) or using a YAML file (--config config.sensors.yaml) for more complex scenarios.
Below is the up‑to‑date API that matches the code. All times are in seconds; pass monotonic time to t_s for stable integration. If t_s=None, sensors start from 0.
Daily temperature: sine wave + OU noise.
Parameters (defaults):
min_val: float = 15.0max_val: float = 30.0period_s: float = 24*3600phase_shift: float = -4*3600— shift so the maximum is in the eveningnoise_theta: float = 0.05— mean‑reversion strength in OUnoise_sigma: float = 0.3— OU noise scale
Methods:
read(t_s: float | None = None) -> float— temperature in °C
Base sine at base_hz + OU noise + rare spikes.
Parameters (defaults):
base_hz: float = 50.0amp: float = 1.0noise_theta: float = 2.0noise_sigma: float = 0.05spike_prob: float = 0.001— spike probability per samplespike_scale: float = 4.0— spike magnitude (×amp)
Methods:
read(t_s: float | None = None) -> float
Solar irradiance (W/m²): half‑sine between sunrise and sunset + slow OU “clouds”.
Parameters (defaults):
peak: float = 900.0— peak W/m²day_period_s: float = 24*3600sunrise: float = 6*3600sunset: float = 18*3600cloud_theta: float = 1/600.0— slow cloud dynamicscloud_sigma: float = 0.05
Methods:
read(t_s: float | None = None) -> float— W/m² (>= 0)
Note: the cloud factor is clamped to 0.2–1.2.
Inverter AC power (kW). Model:
P_dc ≈ (irradiance/1000) * stc_kw,
P_ac = min(p_kw_max, max(0, P_dc * inverter_eff)) + N(0, noise_sigma)
Parameters (defaults):
stc_kw: float = 5.0— STC power at 1000 W/m²inverter_eff: float = 0.95p_kw_max: float = 4.8noise_sigma: float = 0.05
Methods:
-
read(t_s: float | None = None, irradiance: float | None = None) -> float- Returns
0.0ifirradiance is None.
- Returns
Consumption (kW): base + two daily “bumps” (morning & evening) + OU.
Parameters (defaults):
base_kw: float = 0.5morning_kw: float = 0.8evening_kw: float = 1.2day_period_s: float = 24*3600noise_theta: float = 1/120.0noise_sigma: float = 0.05
Methods:
read(t_s: float | None = None) -> float— kW (>= 0)
State‑of‑charge simulator (%), integrating the power balance. Sign convention: positive net_power_kw means an energy deficit → discharge; negative means surplus → charge. Power limits and efficiencies are respected.
Parameters (defaults):
capacity_kwh: float = 10.0soc0: float = 50.0— initial SoC [%]charge_eff: float = 0.95discharge_eff: float = 0.95p_charge_max_kw: float = 3.0p_discharge_max_kw: float = 3.0
Methods:
step(t_s: float, net_power_kw: float) -> float— returns current SoC [%]
Note: this is not a
read(). Callstep(...)each tick with the power balance.
PVPowerSensorneedsirradiance(e.g., fromIrradianceSensor).BatterySoCSensorneedsnet_power_kw = load_kw - pv_kw(or a general balance). Positive → discharge, negative → charge.
dummysensors.registry.SENSOR_REGISTRY— maps stringkind→ classdummysensors.registry.make_sensor(kind: str, **params)— construct by name
dummysensors.orchestrator.run_stream(...)
- Builds instances from a
spec_stror aconfig. - Respects sensor priority and per‑sensor
rate_hz. writer_for_typeis a maptype → callable(sample_dict), with"*"as the default writer.
- OU (Ornstein–Uhlenbeck) uses
dtfrom successive calls; a tiny minimumdtis applied when time does not advance. - Prefer passing monotonic time to
t_s(e.g.,time.monotonic()), especially when chaining sensors in a pipeline.
JSON Lines (one record per line):
{
"ts_ms": 171234,
"device_id": "engine-A",
"sensor_id": "vibration-1",
"type": "vibration",
"value": -0.124
}Also supported: CSV. Planned: Kafka, Redis Stream, WebSocket.
v0.2✅ — CSV writer, partitioning, YAML configv0.3✅ — Smart photovoltaic sensors (irradiance,pv_power,load,soc), per-sensorrate_hz, priority-based orchestrationv0.4🚧 — AnomalyInjector (spike, dropout, drift), new sensors (humidity,rpm,battery_voltage,gps,accel-3axis)v0.5🚧 — Outputs: Kafka, Redis Stream, WebSocket live preview
git clone https://github.com/SculptTechProject/dummysensors
cd dummysensors
pip install -e .
pip install -r requirements.txt- Project layout: src-layout
- Tests:
pytest -q - Lint/format:
ruff check src testsandruff format
MIT © Mateusz Dalke