AgroPulse continuously monitors every sensor that has an active threshold configuration. Every 2 minutes,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.
AnomalyDetectionService runs a scheduled sweep across all configured sensors and evaluates four distinct anomaly conditions. When a condition is first detected, an anomaly record is created and a notification is dispatched. When the condition clears on a later sweep, the anomaly is automatically resolved.
Each new anomaly also creates an
Alert record that appears immediately in the alerts feed. You can view active and historical alerts via /api/alerts.How the scheduler works
The detection sweep is triggered by a Spring@Scheduled annotation with a fixed delay of 120,000 milliseconds (2 minutes). The delay is measured from the end of the previous run, so a slow sweep does not cause overlapping executions.
On each run, the service:
- Loads all
SensorThresholdrecords whereactive = true - Evaluates each sensor against its four anomaly types
- Creates new
SensorAnomalyrecords for any newly detected conditions - Sets
resolvedAton any anomaly whose condition has cleared - Dispatches email and WhatsApp notifications for all unnotified anomalies
Sensor thresholds
Each sensor threshold record controls the parameters used for all four anomaly checks on that sensor.| Field | Type | Used by |
|---|---|---|
minValue | decimal | OUT_OF_RANGE lower bound |
maxValue | decimal | OUT_OF_RANGE upper bound |
noDataMinutes | integer | Minutes of silence before NO_DATA fires |
stuckMinutes | integer | Window size for the STUCK spread check |
spikePercent | decimal | Percentage change threshold for SPIKE |
Anomaly types
OUT_OF_RANGE — value outside configured bounds
OUT_OF_RANGE — value outside configured bounds
Fires when the sensor’s most recent value falls below
minValue or above maxValue. Either bound is optional—if minValue is null only the upper bound is checked, and vice versa.Condition: lastValue < minValue OR lastValue > maxValueExample message: Valor 38.50 fuera de rango [5.0 — 35.0]Alert level: CRITICALThis anomaly is skipped entirely if NO_DATA is currently active for the same sensor, since there is no reliable last value to compare.NO_DATA — sensor has gone silent
NO_DATA — sensor has gone silent
Fires when the most recent reading timestamp is older than
noDataMinutes minutes, or when no reading has ever been recorded for the sensor.Condition: MAX(timestamp) < now() - noDataMinutesExample message: Sin datos desde hace más de 30 minutosAlert level: CRITICALA NO_DATA anomaly suppresses the OUT_OF_RANGE, STUCK, and SPIKE checks for the same sensor on the same sweep, since those checks rely on recent reading data.STUCK — value has not meaningfully changed
STUCK — value has not meaningfully changed
Fires when the last 20 readings within the
stuckMinutes window show a spread (max − min) of less than 0.01. At least 3 readings must be present in the window for the check to activate.Condition: (MAX(value) - MIN(value)) < 0.01 across the last 20 readings in stuckMinutes window, with at least 3 readings presentExample message: Valor constante durante 60 minutos (posible daño en sensor)Alert level: WARNINGA spread below 0.01 across multiple readings usually means the sensor is frozen, disconnected, or physically damaged rather than reporting a legitimately stable environment.SPIKE — sudden large change between readings
SPIKE — sudden large change between readings
Fires when the relative change between the two most recent readings exceeds
spikePercent. The check is skipped if the previous reading’s absolute value is too close to zero (below 0.001) to avoid division errors.Condition: |reading[0] - reading[1]| / |reading[1]| > spikePercent / 100Example message: Cambio brusco: 22.10 → 38.75Alert level: WARNINGA spike may indicate a momentary sensor malfunction, an electrical surge, or a real rapid environmental change. Reviewing the reading history helps distinguish between these cases.Auto-resolution
Anomaly resolution is fully automatic. On each sweep, if a previously detected anomaly condition is no longer true—for example, a value that was out of range has returned within bounds—the service setsresolvedAt to the current timestamp on the existing SensorAnomaly record. No new record is created.
An anomaly is considered active as long as resolvedAt IS NULL. Resolved anomalies are kept in the database for historical review.