Realistic fake telemetry streams for testing, simulation & IoT development.
Zero dependencies. Pure Python 3.7+.
PyPI • GitHub • Quickstart • CLI • Features • API Reference
pip install faketelemetryfrom faketelemetry import TelemetryGenerator, WaveformType
gen = TelemetryGenerator(WaveformType.SINE, frequency=1.0, amplitude=5.0)
# Real-time stream (blocking, with sleep)
for ts, val in gen.stream(sampling_rate=10, duration=2):
print(ts, round(val, 2))
# Instant batch (no sleeping -- great for tests & pipelines)
points = gen.batch(num_samples=100, sampling_rate=50)| 12 Waveforms | Sine, cosine, square, sawtooth, triangle, pulse, random noise, random walk, step, exponential decay, chirp, and custom user-defined functions |
| 6 Noise Types | Gaussian, uniform, pink (1/f), Brownian, impulse spikes, and quantization noise |
| 6 Anomaly Types | Spikes, dropouts, drift, flatline, stuck-at, and jitter -- all probabilistic with configurable duration |
| 19 Sensor Presets | One-liner generators for temperature, pressure, humidity, battery voltage, RPM, CPU, latency, heart rate, accelerometer, GPS, light, CO2, wind, memory, disk I/O, flow rate, vibration, pH, and RSSI |
| Signal Composition | Combine generators with + - * operators -- build harmonics, AM signals, or complex waveforms from simple parts |
| Signal Control | Amplitude, frequency, offset, phase, duty cycle, exponential damping, and value clamping |
| Batch & Stream | Real-time stream(), instant batch(), and async-native astream() |
| Multi-Channel | Synchronised named channels with dict or list input |
| Export | CSV, JSON, NDJSON -- plus InfluxDB line protocol, MQTT JSON, and Prometheus exposition format |
| Statistics | Built-in describe() for min, max, mean, std, percentiles on generated data |
| Reproducible | Seed support across generators, noise, and anomalies; to_config() / from_config() for saving and replaying setups |
| CLI | Full command-line interface -- generate data, stream, export, and inspect without writing Python |
| DataFrame-Ready | to_dict() and batch() plug directly into pandas.DataFrame() |
pip install faketelemetryOr from source:
git clone https://github.com/adkvi/faketelemetry.git
cd faketelemetry
pip install -e .Requirements: Python 3.7+ — no external dependencies.
After installing, the faketelemetry command is available in your terminal (or use python -m faketelemetry).
faketelemetry preset temperature -n 10 --rate 1
faketelemetry preset cpu_usage -n 100 --rate 10 -f csv -o cpu.csvfaketelemetry generate -w sine --freq 2 --amp 5 --offset 10 -n 50 --rate 10
faketelemetry generate -w square --duty-cycle 0.3 -n 20 -f jsonfaketelemetry multi temperature,pressure,cpu_usage -n 100 --rate 10 -f csvfaketelemetry stream --preset heart_rate --rate 2 --duration 30
faketelemetry stream -w sine --rate 10 # Ctrl+C to stopfaketelemetry from-config config.json -n 500 -f ndjson -o data.ndjsonfaketelemetry list presets
faketelemetry list waveforms
faketelemetry list noise
faketelemetry list anomaliesfaketelemetry describe --preset temperature -n 1000 --rate 10
faketelemetry describe -w sine -n 5000 --rate 100All batch commands support --format / -f with: table (default), csv, json, ndjson, influxdb.
| Flag | Description |
|---|---|
-n / --samples |
Number of data points |
--rate |
Sampling rate in Hz |
-f / --format |
Output format |
-o / --output |
Write to file instead of stdout |
--seed |
Random seed for reproducibility |
--noise-level |
Add Gaussian noise |
--no-header |
Omit header row in table/csv |
--version |
Print version and exit |
Six noise distributions, all with optional seed for reproducibility.
from faketelemetry import TelemetryGenerator, WaveformType, NoiseInjector, NoiseType
# Gaussian noise
gen = TelemetryGenerator(
WaveformType.SINE,
noise_injector=NoiseInjector(noise_level=0.5, noise_type=NoiseType.GAUSSIAN, seed=42),
)
# Brownian (random-walk) noise
gen = TelemetryGenerator(
WaveformType.SINE,
noise_injector=NoiseInjector(noise_level=0.1, noise_type=NoiseType.BROWNIAN),
)
# Quantization noise (simulates low-resolution ADC)
gen = TelemetryGenerator(
WaveformType.SINE,
amplitude=5.0,
noise_injector=NoiseInjector(noise_type=NoiseType.QUANTIZATION, quantization_step=0.25),
)Stack multiple anomaly behaviours -- each fires independently per sample.
from faketelemetry import (
TelemetryGenerator, WaveformType,
AnomalyInjector, AnomalyConfig, AnomalyType,
)
gen = TelemetryGenerator(
WaveformType.SINE,
frequency=1.0,
amplitude=5.0,
anomaly_injector=AnomalyInjector(
configs=[
AnomalyConfig(AnomalyType.SPIKE, probability=0.05, magnitude=20.0),
AnomalyConfig(AnomalyType.DRIFT, probability=1.0, drift_rate=0.01),
AnomalyConfig(AnomalyType.DROPOUT, probability=0.02, duration_samples=5),
],
seed=42,
),
)
values = gen.batch_values(num_samples=500, sampling_rate=100)19 realistic sensor simulators, each returns a ready-to-use TelemetryGenerator.
from faketelemetry.presets import SensorPreset
temp = SensorPreset.temperature(seed=1) # ~22 C +/- 3 C
press = SensorPreset.pressure(seed=1) # ~1013 hPa
humid = SensorPreset.humidity(seed=1) # 0-100 %
battery = SensorPreset.battery_voltage(seed=1) # 4.2 V decaying
rpm = SensorPreset.rpm(seed=1) # ~800 RPM idle
cpu = SensorPreset.cpu_usage(seed=1) # 0-100 %
latency = SensorPreset.network_latency(seed=1) # ~25 ms
hr = SensorPreset.heart_rate(seed=1) # ~72 BPM
accel = SensorPreset.accelerometer(seed=1) # +/- 1 g
gps = SensorPreset.gps_coordinate(seed=1) # wandering lat/lon
light = SensorPreset.light_lux(seed=1) # ~400 lux
co2 = SensorPreset.co2_ppm(seed=1) # ~420 ppm
wind = SensorPreset.wind_speed(seed=1) # ~12 m/s
mem = SensorPreset.memory_usage(seed=1) # 0-100 %
disk = SensorPreset.disk_io(seed=1) # MB/s bursts
flow = SensorPreset.flow_rate(seed=1) # ~50 l/min
vib = SensorPreset.vibration(seed=1) # mm/s
ph = SensorPreset.ph_level(seed=1) # 0-14
rssi = SensorPreset.signal_strength(seed=1) # -120..0 dBm
data = temp.batch(num_samples=1000, sampling_rate=10)Fine-tune signal shape and bounds.
import math
from faketelemetry import TelemetryGenerator, WaveformType
gen = TelemetryGenerator(
WaveformType.SINE,
frequency=2.0,
amplitude=10.0,
phase=math.pi / 4, # 45-degree phase shift
damping=0.3, # exponential decay envelope
clamp_min=-5.0, # hard floor
clamp_max=5.0, # hard ceiling
)
values = gen.batch_values(200, sampling_rate=100)Synchronise multiple signals on the same time base.
from faketelemetry import TelemetryGenerator, WaveformType, MultiChannelTelemetryGenerator
multi = MultiChannelTelemetryGenerator({
"temperature": TelemetryGenerator(WaveformType.SINE, frequency=0.1, offset=22.0, name="temp"),
"pressure": TelemetryGenerator(WaveformType.COSINE, frequency=0.05, offset=1013.0, name="press"),
})
# Batch -> list of dicts (pandas-ready)
import pandas as pd
df = pd.DataFrame(multi.batch(num_samples=1000, sampling_rate=10))
print(df.head())
# Or raw arrays for plotting
arrays = multi.batch_arrays(num_samples=500, sampling_rate=50)Write to file or get back a string -- CSV, JSON, or NDJSON.
from faketelemetry import TelemetryGenerator, WaveformType, to_csv, to_json, to_ndjson
gen = TelemetryGenerator(WaveformType.SINE, name="sensor_a")
data = gen.batch(num_samples=500, sampling_rate=100)
# To file
to_csv(data, "output.csv")
to_json(data, "output.json")
to_ndjson(data, "output.ndjson")
# To string
csv_string = to_csv(data)
json_string = to_json(data)Combine generators with +, -, * to build complex signals.
from faketelemetry import TelemetryGenerator, WaveformType, compose
# Sum of harmonics (approximate square wave via Fourier series)
fundamental = TelemetryGenerator(WaveformType.SINE, frequency=1.0, amplitude=1.0)
harmonic3 = TelemetryGenerator(WaveformType.SINE, frequency=3.0, amplitude=1/3)
harmonic5 = TelemetryGenerator(WaveformType.SINE, frequency=5.0, amplitude=1/5)
approx_square = fundamental + harmonic3 + harmonic5
# Amplitude modulation
carrier = TelemetryGenerator(WaveformType.SINE, frequency=100.0)
envelope = TelemetryGenerator(WaveformType.SINE, frequency=1.0, amplitude=0.5, offset=0.5)
am_signal = carrier * envelope
# Scalar offset
biased = TelemetryGenerator(WaveformType.SINE) + 10.0
# compose() for many generators
signal = compose(fundamental, harmonic3, harmonic5) # same as +
values = signal.batch_values(500, sampling_rate=200)Native async for support for asyncio applications.
import asyncio
from faketelemetry import TelemetryGenerator, WaveformType
async def main():
gen = TelemetryGenerator(WaveformType.SINE, frequency=1.0, amplitude=5.0)
async for ts, val in gen.astream(sampling_rate=10, duration=3):
print(f"{ts}: {val:.2f}")
asyncio.run(main())Output data in InfluxDB, MQTT, or Prometheus format -- ready for ingestion.
from faketelemetry import TelemetryGenerator, WaveformType
from faketelemetry.formatters import to_influxdb, to_mqtt_json, to_prometheus
gen = TelemetryGenerator(WaveformType.SINE, name="temp")
data = gen.batch(10, sampling_rate=1)
# InfluxDB line protocol
for line in to_influxdb(data, measurement="sensors", tags={"room": "lab"}):
print(line)
# sensors,room=lab value=0.123 1706745600000000000
# MQTT JSON payloads
for payload in to_mqtt_json(data, sensor_id="temp-01"):
print(payload)
# {"timestamp": "...", "value": 0.123, "sensor_id": "temp-01"}
# Prometheus exposition format
print(to_prometheus(data, metric_name="room_temp", labels={"room": "lab"}))Built-in summary stats -- no pandas required.
from faketelemetry import TelemetryGenerator, WaveformType, describe, describe_values
gen = TelemetryGenerator(WaveformType.SINE, amplitude=5.0)
data = gen.batch(1000, sampling_rate=100)
stats = describe(data)
print(stats)
# {'count': 1000, 'mean': 0.01, 'std': 3.54, 'min': -5.0, 'max': 5.0,
# 'range': 10.0, 'p25': ..., 'p50': ..., 'p75': ..., ...}
# Or from raw values
stats = describe_values(gen.batch_values(1000, sampling_rate=100))Save and replay generator setups as JSON.
import json
from faketelemetry import TelemetryGenerator, WaveformType, NoiseInjector
gen = TelemetryGenerator(
WaveformType.SINE, frequency=2.0, amplitude=5.0,
noise_injector=NoiseInjector(noise_level=0.3), name="sensor_x",
)
# Save config
config = gen.to_config()
json.dump(config, open("config.json", "w"))
# Reload later
gen2 = TelemetryGenerator.from_config(json.load(open("config.json")))Same seed = identical data every run.
from faketelemetry import TelemetryGenerator, WaveformType, NoiseInjector
gen = TelemetryGenerator(
WaveformType.SINE,
noise_injector=NoiseInjector(noise_level=0.5, seed=42),
seed=42,
)
run1 = gen.batch_values(100, sampling_rate=50)
gen.reset()
run2 = gen.batch_values(100, sampling_rate=50)
# run1 == run2import pandas as pd
from faketelemetry import TelemetryGenerator, WaveformType
gen = TelemetryGenerator(WaveformType.SINE, frequency=1.0, name="vibration")
df = pd.DataFrame(gen.to_dict(num_samples=1000, sampling_rate=100))
print(df.describe())| Class | Description |
|---|---|
TelemetryGenerator |
Single-channel generator with stream(), astream(), batch(), to_config(), and + - * operators |
CompositeGenerator |
Compound signal from combining generators with arithmetic operators |
MultiChannelTelemetryGenerator |
Synchronised multi-channel generator with stream(), astream(), and batch() |
NoiseInjector |
6 noise types: Gaussian, uniform, pink, Brownian, impulse, quantization |
AnomalyInjector |
Fault injection engine processing one or more AnomalyConfig rules |
AnomalyConfig |
Configuration for a single anomaly behaviour |
SensorPreset |
Factory with 19 ready-made realistic sensor generators |
| Enum | Values |
|---|---|
WaveformType |
SINE COSINE SQUARE SAWTOOTH TRIANGLE PULSE RANDOM_NOISE RANDOM_WALK STEP EXPONENTIAL_DECAY CHIRP CUSTOM |
NoiseType |
GAUSSIAN UNIFORM PINK BROWNIAN IMPULSE QUANTIZATION |
AnomalyType |
SPIKE DROPOUT DRIFT FLATLINE JITTER STUCK_AT |
| Function | Description |
|---|---|
to_csv(data, path) |
Single-channel to CSV (file or string) |
to_json(data, path) |
Single-channel to JSON array (file or string) |
to_ndjson(data, path) |
Single-channel to newline-delimited JSON |
to_multichannel_csv(rows, path) |
Multi-channel batch output to CSV |
to_influxdb(data, ...) |
InfluxDB line protocol |
to_influxdb_multi(rows, ...) |
Multi-channel InfluxDB line protocol |
to_mqtt_json(data, ...) |
MQTT JSON payloads |
to_prometheus(data, ...) |
Prometheus exposition format |
| Function | Description |
|---|---|
describe(data) |
Summary stats (count, mean, std, min, max, percentiles) for single-channel batch |
describe_values(values) |
Same, from a raw list of floats |
describe_multi(rows) |
Per-channel stats for multi-channel batch |
python -m pytest tests/ -vSee CONTRIBUTING.md for guidelines.
For questions or issues, please open a GitHub Issue.
MIT -- see LICENSE for details.
