Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/diarpicu2022-commits/backend-AgroPulse/llms.txt

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

AgroPulse Backend is a Spring Boot REST API organized into discrete layers that separate concerns cleanly: HTTP controllers handle incoming requests, services hold business logic, repositories mediate all database access, and JPA entities model the domain. Design patterns—Observer, Abstract Factory, and State—are applied deliberately to keep components decoupled and extensible as the number of greenhouses and sensor types grows.

Layered architecture

Requests flow top-to-bottom through four layers. Each layer depends only on the one below it; nothing in a lower layer reaches upward.
Clients (IoT devices, web dashboard)


API Controllers  (@RestController)
        │   Validate requests, delegate to services

Services  (@Service)
        │   Business logic, anomaly detection, notifications

DAOs / Repositories  (Spring Data JPA)
        │   CRUD against the database

Database  (SQLite locally, PostgreSQL in production)

Dual-database setup

The database driver and dialect are controlled entirely by environment variables, so the same JAR runs locally with no extra setup and in production without code changes.
EnvironmentDriverConnection
Local / devorg.sqlite.JDBCjdbc:sqlite:agropulse.db (file on disk)
Productionorg.postgresql.DriverSet via SPRING_DATASOURCE_URL
Override the defaults by setting SPRING_DATASOURCE_URL, SPRING_DATASOURCE_DRIVER_CLASS_NAME, and SPRING_JPA_DATABASE_PLATFORM in your deployment environment (for example, Render environment variables).

Sensor auto-registration

IoT devices do not need to be manually enrolled before they start sending data. When a reading arrives for a sensor ID that does not yet exist in the database, the API creates the sensor record automatically and assigns it to the correct greenhouse. Subsequent readings update lastValue and lastTimestamp on the existing record.

Design patterns

Observer

GreenhouseMonitor is the subject. Every time a sensor reading is saved, processSensorReading() fans the event out to all registered IGreenhouseObserver beans—such as AlertObserver—without the controller knowing which observers exist.

Abstract Factory

SensorType defines the product families (TEMPERATURE, HUMIDITY, SOIL_MOISTURE, LIGHT, CO2, PH, WIND_SPEED, TEMPERATURE_INTERNAL, TEMPERATURE_EXTERNAL). The factory creates the correct sensor configuration for each type.

State

Sensor anomalies move through states: detected (no resolvedAt), notified (notified = true), and resolved (resolvedAt set). The AnomalyDetectionService drives these transitions on each 2-minute cycle.

Stateless API

Spring Security is configured with SessionCreationPolicy.STATELESS. There are no server-side sessions; every request carries its own identity context (user object or X-Admin-Email header).

Data flow: device POST to anomaly detection

1

Device POSTs a reading

An IoT device sends a POST request to /api/readings with sensor ID, value, and timestamp. If the sensor is not yet registered, it is created automatically at this point.
2

ReadingController persists the data

The controller validates the payload, saves the SensorReading record to the database, and updates the parent Sensor’s lastValue and lastTimestamp fields.
3

GreenhouseMonitor is notified

ReadingController calls GreenhouseMonitor.processSensorReading(reading), which immediately calls onSensorReading() on every registered observer bean. This happens synchronously before the HTTP response is returned.
4

AnomalyDetectionService runs on schedule

Independently of the reading flow, AnomalyDetectionService.detect() runs every 2 minutes. It loads all active SensorThreshold configs and checks each sensor for OUT_OF_RANGE, NO_DATA, STUCK, and SPIKE conditions.
5

Alerts and notifications are dispatched

New anomalies are written to sensor_anomalies and an Alert record is inserted for the dashboard feed. NotificationService then sends email (SendGrid) and WhatsApp (CallMeBot) messages to all active recipients for that greenhouse.

Build docs developers (and LLMs) love