Water monitoring and anomaly alerting for hydroponic greenhouses.
Companies run greenhouses with hydroponic stations, each equipped with a Hermes IoT device and water sensors (flow in, flow out, pH). The system watches the water and warns people before a problem ruins a crop:
- Collects sensor readings — Hermes devices publish measurements through the Midfield platform, which delivers them to this API via webhook (
/midfield). Each reading batch becomes a "collect" tied to a station. - Detects anomalies — during each station's configured operating hours, water flow readings are sent to an ML prediction service that flags abnormal flow, typically a clog (insufficient flow) or a leak. Stations track consecutive warnings so one noisy reading doesn't trigger an alarm.
- Alerts operators via WhatsApp — when an anomaly is confirmed, alert messages (critical/warning templates) go to the phone numbers registered on the greenhouse. Operators reply through WhatsApp buttons ("CONFIRMAR" / "NÃO É ENTUPIMENTO"); replies come back via the Meta webhook (
/messages/webhook) and are recorded as human feedback on each measurement — which also feeds retraining of the prediction model. - Serves the dashboard — REST endpoints expose companies, greenhouses, stations, and paginated collect history for a frontend.
The product targets Brazilian operations: alert numbers follow the +55 format and timestamps use America/Sao_Paulo.
Spring Boot (Kotlin) API: collects sensor data, detects anomalies via a prediction service, and sends WhatsApp alerts.
- Kotlin / Spring Boot 3.5, Java 21
- PostgreSQL + jOOQ (generated Kotlin classes) + Liquibase migrations
- OpenFeign integrations: WhatsApp (Meta Graph API), prediction service, Midfield webhooks
- JDK 21
- Docker (for local Postgres)
- GitHub credentials with access to the
folhastech/midfieldpackage registry
-
Copy
.env-exampleto.envand fill inGITHUB_USER/GITHUB_TOKEN(needed to resolve thecom.folhastech.midfield:modelsdependency). -
Start the database:
docker compose up -d
-
Run the app:
./gradlew bootRun
The API is served at http://localhost:8082/api/.
Everything is env-var driven with local defaults (see src/main/resources/application.yml):
| Variable | Default | Purpose |
|---|---|---|
DATABASE_URL |
jdbc:postgresql://localhost:5432/hidros_db |
Postgres connection |
DATABASE_USERNAME / DATABASE_PASSWORD |
hidros / hidros |
DB credentials |
LIQUIBASE_ENABLED |
false |
Run migrations on startup |
WHATSAPP_URL / WHATSAPP_TOKEN / WHATSAPP_PHONE_NUMBER_ID |
— | WhatsApp alert integration |
PREDICT_URL |
http://localhost:8000 |
Anomaly prediction service |
-
Migrations live in
src/main/resources/db/changelog/(Liquibase). -
After schema changes, regenerate jOOQ classes:
./gradlew jooqCodegen
Generated code goes to
src/main/kotlin/.../resources/jooq/generated.
./gradlew test # unit tests
./gradlew integrationTest # integration tests (Testcontainers, needs Docker)
./gradlew check # bothdocker build --build-arg GITHUB_USER=... --build-arg GITHUB_TOKEN=... -t hidros .The container exposes port 8082. ./gradlew bootBuildImage builds and publishes an image using IMAGE_NAME, DOCKER_USERNAME, DOCKER_PASSWORD.
src/main/kotlin/com/folhastech/hidros/
├── application/ # controllers, DTOs, config, scheduled jobs
├── domain/ # entities, services, gateways (Feign clients)
└── resources/ # jOOQ generated code, repositories