Warning
Deprecated (Legacy Stack A Reference Implementation)
This repository contains the legacy Stack A (v1.0) crop simulator implemented in Python with asyncio and paho-mqtt. It has been deprecated and superseded in production by the canonical modern Stack B simulator: SmartPot-DataGenerator (Rust, Tokio, Axum, rumqttc with compact binary v2 support). Preserved solely for historical reference.
SmartPot-DataGenerator-Python was the crop simulation service of SmartPot Stack A: an asynchronous Python service simulating environmental thermodynamics and biological dynamics, streaming telemetry via MQTT, and reacting to actuation commands.
SmartPot-DataGenerator/
├── simulator/
│ ├── __main__.py # Arranca los cultivos fijos, el hilo de publicación y la API de control
│ ├── api.py # API interna (FastAPI) para crear, cambiar y retirar cultivos virtuales
│ ├── config.py # Variables de entorno y lista de cultivos fijos
│ ├── device.py # Cliente MQTT: telemetría, comandos, ACK y estado
│ ├── environment.py # Modelo físico del cultivo, modos y efecto de los actuadores
│ ├── pots.py # Administrador de cultivos: altas y cambios en caliente, clima y publicación
│ └── weather.py # Clima actual y buscador de lugares (Open-Meteo)
├── tests/ # Física, modos, clima, contrato de tópicos, comandos y API de control
├── Dockerfile # Imagen sin privilegios con uv y chequeo de salud
├── pyproject.toml / uv.lock
└── .env.example
Es interna: solo SmartPot-API la consume, con
Authorization: Bearer <SIMULATOR_TOKEN>, y nunca se publica en Internet. La PWA habla con la API de SmartPot, que
comprueba que el cultivo sea virtual y de quien lo pide, y descifra su clave antes de pedir la simulación.
| Método | Ruta | Descripción |
|---|---|---|
| GET | /health |
Pública: cultivos simulados y conexiones |
| GET | /v1/pots |
Todos los cultivos simulados y su estado |
| GET | /v1/pots/{cropId} |
Estado: modo, última lectura, medidores, clima, actuadores encendidos y último comando |
| PUT | /v1/pots/{cropId} |
Crea o cambia un cultivo simulado: key, cropType, mode, manual, location, setting, exposure, intervalSeconds |
| DELETE | /v1/pots/{cropId} |
Retira el cultivo simulado (publica offline) |
| GET | /v1/places?q= |
Busca lugares para el modo clima |
| GET | /v1/weather?latitude=&longitude= |
Clima actual de un punto |
{
"key": "<clave del cultivo>",
"cropType": "LETTUCE",
"mode": "WEATHER",
"location": {
"name": "Medellín",
"latitude": 6.245,
"longitude": -75.5715
},
"intervalSeconds": 30
}Los cultivos de SIMULATOR_DEVICES son fijos (no se pueden cambiar por la API); los que crea la API son administrados:
si el simulador se reinicia, la API vuelve a crear los activos en menos de un minuto.
| Variable | Por defecto | Descripción |
|---|---|---|
MQTT_HOST |
localhost |
Broker |
MQTT_PORT |
1883 (8883 con TLS) |
Puerto |
MQTT_TLS |
false |
Conexión TLS |
MQTT_CA_FILE |
— | CA que firma el certificado del broker (ca.crt) |
MQTT_TOPIC_PREFIX |
smartpot/v1 |
Prefijo del contrato |
SIMULATOR_DEVICES |
— | Cultivos fijos: cropId:clave:ESPECIE separados por comas (opcional si hay SIMULATOR_TOKEN) |
SIMULATOR_INTERVAL_SECONDS |
30 |
Segundos entre lecturas de los cultivos fijos |
SIMULATOR_UTC_OFFSET |
-5 |
Diferencia horaria con UTC para el ciclo de día y noche |
SIMULATOR_TOKEN |
— | Token de la API de control (mínimo 24 caracteres); sin él la API responde 503 |
SIMULATOR_PORT |
8081 |
Puerto de la API de control |
El usuario MQTT de cada cultivo es su id. En un cultivo fijo la clave es la que entrega la API al crear un cultivo
real (POST /api/v1/crops) o al rotarla (POST /api/v1/crops/{id}/device/key); en uno virtual la API la entrega por la
red interna. Los datos demo de SmartPot-DB traen dos cultivos reales listos para simular.
La imagen es pública: ghcr.io/smartpottech/smartpot-datagenerator. La plataforma completa, con este servicio incluido, se
levanta con un solo comando y sin descargar el código:
curl -fsSL https://raw.githubusercontent.com/SmartPotTech/.github/main/docker/demo/compose.yaml | docker compose -f - up -d --waitAbre http://localhost:5173 e ingresa con demo@smartpot.app / SmartPot2026. Se detiene con
docker compose -p smartpot-demo down (con -v borra también los datos). Más detalle en la
demo.
- uv
- Un broker de SmartPot con las cuentas de dispositivo aprovisionadas por la API
uv sync
set -a; . ./.env.example; set +a # o exporta las variables a mano
uv run python -m simulatorContra producción, como el dispositivo de un cultivo real:
MQTT_HOST=mqtt.smartpot.app MQTT_TLS=true MQTT_CA_FILE=ca.crt \
SIMULATOR_DEVICES=<cropId>:<clave>:LETTUCE uv run python -m simulatoruv run ruff check .
uv run pytestdocker pull ghcr.io/smartpottech/smartpot-datagenerator:latestLa imagen corre como el usuario 1000, admite sistema de archivos de solo lectura y trae chequeo de salud. Necesita
salida a Internet solo para el modo clima.
Cada cambio en main pasa por el CI, publica la imagen en GHCR (y en Docker Hub como réplica cuando el repositorio
tiene credenciales) y pide el despliegue al workflow central
de SmartPotTech/.github, que actualiza producción de a uno y verifica
/health.
El simulador corre siempre junto a la plataforma y solo la API le habla. Su documentación propia está en
docs/ (también
en DOCX y PDF), con
sus diagramas en docs/diagrams: el general del componente, la vida de un cultivo virtual y el modelo
físico.
La documentación técnica
explica los cultivos reales y virtuales, los modos de la simulación y cómo la administra la API. Los diagramas generales
muestran la plataforma completa en una sola imagen ampliable:
- Operación completa: la escena del cultivo virtual con clima real y su pausa
- Máquinas de estado: los estados de la simulación de un cultivo virtual
- Arquitectura completa: dónde corre el simulador y con quién habla
Este proyecto está bajo la licencia MIT. Consulta el archivo LICENSE para más detalles.