# LitoralRegas Backend Spring Boot backend for the LitoralRegas agricultural monitoring and control platform. This backend communicates with agricultural controllers through Modbus, builds dynamic acquisition plans based on installed modules, collects live telemetry, stores historical data, and exposes APIs consumed by the frontend dashboard. --- # Features * Modbus TCP communication * Dynamic controller capability discovery * Sensor definition import system * Live telemetry acquisition * Telemetry cache layer * Historical telemetry storage * Climate module API * Meteorology module API * Irrigation module foundation * Historical chart aggregation endpoints * SQLite persistence --- # Technology Stack * Java 21 * Spring Boot * Spring Web * Spring Data JPA * SQLite * Maven * Modbus TCP --- # Architecture Overview ```txt Sensor Definitions ↓ Controller Capabilities ↓ Acquisition Plan Builder ↓ Telemetry Acquisition Scheduler ↓ Telemetry Cache ↓ Historian + Module APIs ↓ Frontend Dashboard ``` --- # Core Concepts ## Sensor Definitions The `sensor_definition` table contains the full catalog of known sensors. A controller installation may not use every sensor present in the catalog. The acquisition plan decides which sensors are actually polled. --- ## Controller Capabilities Controller capabilities are read directly from Modbus registers. Current capability model: ```txt Register 6 → irrigationControllerCount Register 7 → fertilizerChannelCount Register 8 → feature flags Register 9 → climateGreenhouseCount ``` Feature flags: ```txt bit 0 → climateEnabled bit 1 → irrigationEnabled bit 2 → lightingEnabled ``` --- ## Acquisition Plan The acquisition plan dynamically selects sensors based on: * Installed controller modules * Greenhouse count * Irrigation controller count * Sensor category * Modbus address ranges This prevents polling sensors that do not exist in a specific installation. --- ## Telemetry Cache The telemetry cache stores the latest acquired value for each sensor. Module APIs read from the cache instead of directly querying Modbus. --- ## Historian The historian stores telemetry over time. It supports: * historical chart series * accumulated values * time range queries * future workspace/chart persistence --- # Project Structure ```txt src/main/java/com/litoralregas/backend ├── acquisition ├── historian ├── modbus ├── modules │ ├── climate │ ├── irrigation │ ├── meteo │ └── shared ├── sensor ├── telemetry └── config ``` --- # Running the Backend ## Requirements * Java 21+ * Maven * SQLite * Reachable controller or Modbus simulator --- ## Start Backend ```bash mvn spring-boot:run ``` Default backend URL: ```txt http://localhost:18450 ``` --- # Configuration Main configuration file: ```txt src/main/resources/application.yaml ``` Example acquisition scheduler configuration: ```yaml litoralregas: acquisition: scheduler: enabled: true fixed-delay-millis: 10000 ``` Important: YAML comments must be on a separate line. Correct: ```yaml fixed-delay-millis: 10000 # Longer delay between acquisition cycles ``` Wrong: ```yaml fixed-delay-millis: 10000 // comment ``` --- # Database Current database engine: ```txt SQLite ``` Main table: ```sql CREATE TABLE sensor_definition ( id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(255) NOT NULL, modbus_address INTEGER NOT NULL, bit_offset INTEGER, value_type VARCHAR(50) NOT NULL, unit VARCHAR(50), decimal_places INTEGER NOT NULL DEFAULT 0, category VARCHAR(100) NOT NULL, source_type VARCHAR(50) NOT NULL, polling_interval_seconds INTEGER NOT NULL DEFAULT 1, enabled BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMP NOT NULL ); ``` --- # Sensor Definition Import Sensor definitions are imported from: ```txt src/main/resources/config/sensor-map.txt ``` Run import manually: ```bash curl -X POST http://localhost:18450/api/sensor-definition-import/run ``` The importer: * imports missing sensors * updates safe metadata * skips duplicates safely * supports clean reimports during development --- # Clean Development Reimport To completely reset sensor definitions during development: ```sql DELETE FROM sensor_definition; DELETE FROM sqlite_sequence WHERE name = 'sensor_definition'; ``` Then re-run: ```bash curl -X POST http://localhost:18450/api/sensor-definition-import/run ``` --- # Main API Endpoints ## Acquisition Plan ```http GET /api/acquisition/plan ``` Returns: * module availability * greenhouse count * irrigation controller count * selected sensor IDs --- ## Latest Telemetry ```http GET /api/telemetry/latest ``` Returns latest cached telemetry values. --- ## Meteo Module ```http GET /api/modules/meteo ``` Provides: * exterior temperature * exterior humidity * wind speed * wind direction * radiation * rain sensors * CO2 overview --- ## Climate Module ```http GET /api/modules/climate ``` Provides: * greenhouse temperature * greenhouse humidity * CO2 * ventilation * extractors * screens * windows * lighting sectors * soil humidity * soil temperature --- ## Historical Accumulation ```http GET /api/historian/accumulated ``` Example: ```http GET /api/historian/accumulated?key=meteo.chuva.1&range=30d ``` Supported ranges: ```txt 7d 30d month year ``` --- # Dynamic Module Strategy Module availability is determined dynamically through: ```txt ControllerCapabilities ↓ AcquisitionPlan ↓ TelemetryCache ``` This means: * climate sensors are only acquired if climate exists * irrigation sensors are only acquired if irrigation exists * lighting sensors are only acquired if lighting exists The frontend should eventually use acquisition plan data to decide which sections to render. --- # Derived Sensors Some sensors are virtual/computed values. Examples: ```txt DPV Estufa 1 → -121 Hum. Absoluta 1 → -141 ``` These are NOT real Modbus registers. Correct pipeline: ```txt Raw temperature + humidity ↓ DerivedClimateService ↓ DPV / Absolute Humidity ↓ TelemetryCache + Historian ``` Negative Modbus addresses should never be polled directly. --- # Current Development Notes Disconnected sensors may return unrealistic values. Examples: * invalid temperature values * unrealistic humidity values * disconnected soil probes This is expected in partially installed environments. The backend currently exposes all acquired sensors. The frontend chart builder will later allow users to choose only relevant variables. --- # Planned Improvements ## Chart Variables API Planned endpoint: ```http GET /api/charts/variables?module=climate ``` Expected response: ```json { "sensorId": 13, "name": "Temperatura estufa 1", "key": "temperatura.estufa.1", "historianKey": "climate.temperatura.estufa.1", "module": "climate", "unit": "C", "category": "CLIMATE" } ``` --- ## Derived Climate Values Future derived telemetry: * DPV * absolute humidity * dew point * climate alarms * sensor health --- ## Workspace System Planned chart workspace support: * save layouts * detachable charts * multi-monitor support * reusable chart presets * draggable variables --- # Useful Development Commands ## Import Sensors ```bash curl -X POST http://localhost:18450/api/sensor-definition-import/run ``` ## Check Acquisition Plan ```bash curl http://localhost:18450/api/acquisition/plan ``` ## Check Meteo Module ```bash curl http://localhost:18450/api/modules/meteo ``` ## Check Climate Module ```bash curl http://localhost:18450/api/modules/climate ``` ## Check Latest Telemetry ```bash curl http://localhost:18450/api/telemetry/latest ``` --- # Current Status The backend foundation is currently stable for: * sensor catalog import * Modbus acquisition * capability-based acquisition planning * telemetry cache * meteorology module * climate module * historical accumulation * frontend integration Next major milestone: ```txt Chart Variables API + Derived Climate Telemetry ```