Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ricardomb-tech/surqo/llms.txt

Use this file to discover all available pages before exploring further.

The Surqo IoT Simulator is a Python script that generates sensor readings matching the climate patterns of Montería, Córdoba, Colombia and publishes them to the same API endpoints used by a physical ESP32 node. Use it to develop and test the backend, frontend dashboard, and alert thresholds without owning or assembling hardware. In HTTP mode the simulator posts to the same REST endpoint as the firmware; in MQTT mode it publishes to the farm-based topic surqo/farms/{farm_id}/sensors (the firmware uses the device-based topic surqo/devices/{mac}/sensors). The JSON payload structure is identical to real firmware readings, so the backend processes both through the same pipeline.

Installation

cd iot-simulator
pip install httpx paho-mqtt

Usage

HTTP mode posts readings directly to the Surqo REST API. This is the simplest way to get data flowing into a local development environment or the production backend.
python simulator.py \
  --mode http \
  --interval 10 \
  --farm-id <your-farm-uuid> \
  --device-id ESP32-SIM-001

CLI Arguments

ArgumentDefaultDescription
--device-idESP32-SIM-001Device identifier sent with each reading
--farm-idrandom UUIDFarm UUID to associate readings with
--interval30Seconds between readings
--modehttpTransport: http or mqtt
--api-urlhttps://surqo-api.fly.dev/api/v1/sensors/readingHTTP endpoint URL
--mqtt-hostbroker.hivemq.comMQTT broker hostname
--mqtt-port8883MQTT TLS port
--mqtt-user(empty)MQTT username
--mqtt-pass(empty)MQTT password

Climate Model

The simulator implements a physics-inspired model of Córdoba, Colombia’s tropical climate. Every generated value evolves over time — it is not random noise around a fixed mean.

Temperature

Sinusoidal day/night cycle: minimum 22°C at 5 am, maximum 34°C at 2 pm, with ±1°C Gaussian noise added to each reading.

Humidity

Inversely correlated with temperature. Base humidity is 55% + (TEMP_MAX − current_temp) × 2.5, clamped to the range 40–95% RH.

Soil Moisture

Starts at 55% and depletes via evapotranspiration (0.3%/30 min during daytime, 0.05%/30 min at night). Rain events replenish it by 5–25 mm × 0.8.

UV Index

Solar arc model: 0 before 7 am and after 6 pm, peaks at 11 around noon. Formula: 11 × sin(π × (hour − 7) / 11).

Rain Events

Rain is triggered probabilistically based on relative humidity:
  • Humidity > 85% → 25% chance of a rain event per reading
  • Humidity > 78% → 10% chance of a rain event per reading
  • Below 78% → no rain

Example Console Output

✅ [14:35] Suelo: 44.5% | Aire: 31.2°C  70.1%HR | UV:  7.4 | Bat: 3820mV | RSSI: -62dBm
✅ [14:36] Suelo: 44.3% | Aire: 31.5°C  69.8%HR | UV:  7.5 | Bat: 3815mV | RSSI: -58dBm
Each line is printed immediately after a successful publish. A prefix indicates a failed HTTP POST or MQTT publish.

Sample Reading Payload

This is the exact JSON structure sent by the simulator — and by the real ESP32 firmware — on every reading cycle.
{
  "device_id": "ESP32-SIM-001",
  "farm_id": "uuid-de-la-finca",
  "timestamp": "2026-06-28T14:35:00-05:00",
  "sensors": {
    "soil_moisture_pct": 44.5,
    "soil_temp_c": 27.8,
    "air_temp_c": 31.2,
    "air_humidity_pct": 70.1,
    "light_uv_index": 7.4
  },
  "battery_mv": 3820,
  "rssi_dbm": -62,
  "firmware_version": "1.0.0-sim"
}
All numeric fields are rounded to one decimal place. The timestamp uses Colombia’s UTC-5 offset. The firmware_version field is always "1.0.0-sim" for simulator readings, which lets the backend distinguish simulated traffic from real hardware if needed.
Use --interval 5 for rapid testing during frontend or backend development. The backend processes readings asynchronously and broadcasts updated sensor values via WebSocket immediately upon ingestion — clients connected to the live dashboard will see new data within milliseconds of each simulated reading.

Build docs developers (and LLMs) love