IJ
Ivan Jovanovski
HomeProjectsLabResumeNowFuture Ideas
IJ
Ivan Jovanovski

Electrical Engineer building practical solutions in energy systems, automotive electronics, and embedded systems.

Navigation

  • Aerospace
  • Projects
  • Lab

Focus Areas

  • Energy Systems
  • Automotive Electronics

Connect

© 2026 Ivan Jovanovski. All rights reserved.

Smart Farm IoT – LoRa Sensor Network & Secure Gateway (Proof of Concept)

IoTLoRaESP32ArduinoKafkaSparkElasticsearchDockersmart-farming
General
Smart Farm IoT – LoRa Sensor Network & Secure Gateway (Proof of Concept) 1

Project Overview

This project is a proof of concept for a modular IoT-based "smart farm" setup. LoRa sensor nodes and ESP32 gateways are fairly common, so the focus here is on getting the whole path working end to end: simple firmware on the nodes and gateway, a secure Java/Kafka backend, and a small web dashboard, all running on real hardware instead of diagrams. The long-term idea is a system that can watch basic soil and weather conditions, help with irrigation and small solar infrastructure, and stream data into a distributed analytics backend so it can be explored and processed later. This first phase keeps the scope intentionally narrow: a low-power LoRa sensor node, an ESP32 gateway that forwards data over Wi-Fi, and a Java server that validates and sends readings into an existing Kafka-based analytics stack. I also have access to a realistic outdoor test area with irrigation and groundwater, which will be useful once the lab setup feels stable enough to take outside. The aim is not to design a full farm controller in one go, but to build a modest, working path from sensor to backend and learn what breaks along the way. If that pipeline behaves well, it becomes a good base for trying more nodes, more sensors, and different control ideas later.

Version:v1.0
Time:~40.0 hours
Cost:~$120
Status:in-progress

Materials

  • ESP32 development board × 1
  • LoRa modules (433 MHz) – gateway and node × 2
  • Arduino Nano boards (sensor nodes) × 1
  • DHT11 temperature and humidity sensors × 1
  • Capacitive soil moisture sensors × 1
  • Prototyping boards / perfboard × 2
  • Jumper wires and connectors × 1
  • Antennas for LoRa modules × 2
  • Low-voltage power supplies or USB power adapters × 2

Tools

  • Soldering station and basic hand tools
  • Multimeter
  • Breadboard for initial testing
  • Laptop with Arduino IDE and Java/Maven
  • Router with port forwarding configuration access

Contents

  1. 1.How It Works
  2. 2.Hardware
    1. 2.1LoRa Sensor Nodes
    2. 2.2ESP32 Gateway
    3. 2.3Sensors
    4. 2.4Future Hardware
  3. 3.Software & Communication
    1. 3.1Node Firmware (Arduino Nano)
    2. 3.2Gateway Firmware (ESP32)
    3. 3.3Java Server & Kafka Integration
    4. 3.4Security Model
    5. 3.5Future Software
  4. 4.Distributed Analytics Backend
    1. 4.1Kafka & Zookeeper
    2. 4.2Kafka Connect & Elasticsearch Sink
    3. 4.3Apache Spark Processing
    4. 4.4Elasticsearch & Kibana
    5. 4.5Monitoring with Prometheus
    6. 4.6Docker Deployment
  5. 5.Web Dashboard (Demo UI)
  6. 6.What I Learned
  7. 7.Resources & References

The goal for this first version was simple: get a basic smart-farm path working from sensor to backend. LoRa sensor nodes sit on one side, an ESP32 gateway bridges them to Wi-Fi, and a Java/Kafka backend receives and stores the data so it can be processed or visualised later. The system is split into three layers: field nodes that measure soil and climate conditions, a gateway that forwards readings over a TLS-encrypted link, and a backend that checks the messages and streams them into Kafka. DuckDNS and router port forwarding are used so the gateway can reach the server even when it’s not on the same local network.

Hardware 1
Hardware 2

The hardware is intentionally modest: standard development boards and off-the-shelf sensors wired into a simple but reproducible topology. The emphasis is on a clean split between low-power field nodes and a slightly more capable gateway device.

2.1

LoRa Sensor Nodes

LoRa Sensor Nodes

Each node uses an Arduino Nano with a LoRa module and a few environmental sensors. The Nano reads the sensors and sends a formatted string over LoRa at fixed intervals. Currently bench-powered, but designed with low power in mind for eventual battery or solar operation.

2.2

ESP32 Gateway

ESP32 Gateway

The gateway uses an ESP32 with a LoRa module. It receives packets from the sensor nodes over LoRa, connects to Wi-Fi, and forwards the data to the Java server over a TLS-encrypted link.

2.3

Sensors

Two sensor types for now: a DHT11 for temperature and humidity, and a capacitive soil moisture probe. Basic and cheap, but good enough to prove the data path works.

2.4

Future Hardware

Coming Soon

The next hardware steps focus on slowly expanding the sensor network and adding simple control modules:

  • More sensor nodes: Deploying additional LoRa nodes to cover different zones and soil types.
  • Solar module: Small panels that can be opened, closed, or reoriented based on weather and load.
  • Weather module: Extra sensors for wind speed, rain, UV index, and pressure.
  • Water module: Pumps and valves that can be switched based on soil moisture and basic schedules.

At the moment the long-range part of the system still relies on regular internet connectivity to reach the backend. A future experiment is to treat LoRa as the only RF link and test a small drone as a relay or “data mule”: it would periodically fly near the nodes, collect buffered readings, and then forward them to a gateway closer to home. This proof of concept keeps the message format and gateway behaviour simple on purpose so the same logic can later run on a mobile relay without large changes.

The software stack spans microcontroller firmware, gateway logic, and a Java server. The goal is to keep each layer simple enough to reason about, while still enforcing basic security on the path from sensor to backend.

3.1

Node Firmware (Arduino Nano)

Written in C++ with the Arduino toolchain. Each node reads its sensors, formats the data into a simple string like ID:T1 T:25.0 H:60.0 S:450, and sends it over LoRa. Supports basic commands from the gateway and can enter sleep mode to save power.

3.2

Gateway Firmware (ESP32)

Also Arduino-based. On startup it connects to Wi-Fi, opens a TLS connection to the server, and then listens for LoRa packets and forwards them as they arrive. Can also send commands back to the nodes.

3.3

Java Server & Kafka Integration

A Java server that accepts TLS connections from the gateway, validates incoming messages, converts them to JSON, and publishes them to Kafka. Config is loaded from a properties file. DuckDNS and port forwarding make it reachable from outside the local network.

3.4

Security Model

Kept simple: TLS on the gateway–server link, a pre-shared key for basic auth, and input validation on the server. Future work includes proper certificate handling and per-node authentication.

3.5

Future Software

Coming Soon

Planned software improvements are mostly about making the system easier to grow and easier to use:

  • Communication optimisation: Tuning LoRa and Wi-Fi settings for better range, lower power, and more stable throughput as more nodes are added.
  • Backend scaling: Tidying up the Java/Kafka backend so it can handle more nodes and longer data histories, with clearer monitoring and alerting.
  • User interface: Extending the UI with historical charts, trend views, and simple control actions (for example, manually triggering an irrigation cycle from the dashboard).
Distributed Analytics Backend 1

The backend is a small, containerised distributed stack used to ingest, process, and visualise sensor data. It runs in Docker on a single development machine and is built around Apache Kafka for event streaming, Apache Spark for batch and stream processing, and Elasticsearch for indexing and search. The architecture was first put together as a separate university project and then adapted to accept the smart-farm data, so this IoT setup is one concrete example of how the stack can be used rather than a full production deployment.

4.1

Kafka & Zookeeper

Kafka handles event streaming. Data from the Java server is published to an iot-data topic, which downstream processors and connectors can consume. Zookeeper coordinates the broker. Single-node setup for now.

4.2

Kafka Connect & Elasticsearch Sink

Kafka Connect streams data from the iot-data topic into Elasticsearch using the Elasticsearch Sink Connector. Indices are created automatically as data arrives.

4.3

Apache Spark Processing

Apache Spark Processing

Spark runs in a master-worker setup inside Docker. Two jobs so far: one cleans raw data and writes it to processed-iot-data, the other computes hourly/daily averages and writes to average-data. Jobs are compiled with Maven and submitted via spark-submit.

4.4

Elasticsearch & Kibana

Elasticsearch & Kibana

Elasticsearch indexes the sensor data; Kibana provides a UI for exploring it. Three indices: iot-data (raw), processed-iot-data (cleaned), and average-data (aggregates).

4.5

Monitoring with Prometheus

Monitoring with Prometheus

Prometheus scrapes metrics from the services. Elasticsearch is fully integrated via an exporter; other services have targets configured but need exporters for full coverage.

4.6

Docker Deployment

Docker Deployment

Everything runs in Docker Compose on a single Windows machine with WSL 2. Ports are mapped to the host, config and JAR files are mounted in, and startup scripts handle service dependencies. Development setup only—production would need proper distribution and replication.

Web Dashboard (Demo UI) 1
Web Dashboard (Demo UI) 2
Web Dashboard (Demo UI) 3

A static web dashboard was built to visualise what the final monitoring interface would look like. The demo includes four pages: a main dashboard with live sensor status, node locations on a map, and quick actions; an analytics page with temperature, humidity, and soil moisture charts over time; a weather forecast page pulling data from the Open-Meteo API; and a solar tracking page showing sun position, panel output, and irradiance curves.

The UI is built with Tailwind CSS, Lucide icons, Chart.js for graphs, and Leaflet.js for the interactive map. All data shown is static or mocked, but the layout and components reflect how a real system would present sensor readings, alerts, and controls. The design uses a dark theme with green accents, card-based layouts, and status indicators that match the overall style of the project.

Key features of the demo:

  • Dashboard: Real-time sensor cards, field map with node markers, node status list, recent alerts, and quick action buttons.
  • Analytics: Temperature trends across all nodes, humidity and soil moisture charts, RSSI signal strength, and battery status bars.
  • Weather: 7-day forecast, hourly breakdown, precipitation chart, and farming recommendations (data via Open-Meteo API).
  • Solar & Sun: Sun position arc with sunrise/sunset times adjusted for local terrain (mountain blocks sun after 18:00), solar panel output for a 5×35W array, irradiance chart, and panel controls.

The demo files are located in the project's /demo folder and can be opened directly in a browser.

This project reinforced that even small IoT setups are really about the whole stack, not just one board or sensor. On the hardware side, working with LoRa, ESP32, and basic sensors showed how sensitive long-range radio links are to wiring quality, antennas, and power. A single loose jumper or bad solder joint can easily masquerade as a protocol bug until you track it down. Soldering LoRa modules and sensor connections turned out to be more fragile than expected, and getting the ESP32 reliably into programming mode meant spending a bit of time understanding its boot pins and reset sequence.

On the software side, keeping the firmware simple and well-structured paid off when debugging. Having clear responsibilities for each layer—nodes, gateway, server—made it easier to isolate problems. Running TLS on the ESP32 pushed its memory harder than expected, and adding validation on the server side helped filter out noise and bad readings from the LoRa link.

The distributed backend brought its own set of lessons. Getting Kafka, Spark, and Elasticsearch to work together in Docker required careful version matching—mismatched connector versions caused cryptic errors that took time to debug. Spark jobs needed to be compiled with the right Java version (8, not 11) to run in the container. Elasticsearch 8.x dropped support for document types, which broke older examples. And coordinating service startup order in Docker Compose required custom health checks and delays. The Prometheus integration also showed that not all services expose metrics out of the box; some need dedicated exporters.

Overall, the main takeaway so far is that building a useful smart-farm platform is less about one clever algorithm and more about a lot of small decisions: sensible wiring, clear message formats, basic security, and a backend that can grow a little as the project does.

The design draws heavily on vendor documentation and existing building blocks:

Hardware & Firmware:

  • LoRa Alliance documentation and module datasheets for radio settings and range assumptions.
  • ESP32 official documentation for Wi-Fi, TLS, and GPIO behaviour.
  • Arduino Nano and DHT11 datasheets and community examples for basic sensor integration.

Distributed Backend:

  • Apache Kafka documentation for event streaming and topic management.
  • Apache Spark documentation for stream and batch processing.
  • Elasticsearch official documentation for indexing, search, and Kibana dashboards.
  • Confluent Kafka Connect documentation for sink connectors.
  • Prometheus and Elasticsearch Exporter documentation for metrics collection.
  • Docker and Docker Compose documentation for container orchestration.
  • Maven documentation for Java build management.

For the server and gateway, Java/Kafka and Arduino/ESP32 examples were adapted to fit the specific message format and security model used here.

Results

The proof of concept shows a full path from a simple field sensor to a distributed analytics backend. A LoRa-enabled sensor node can send temperature, humidity, and soil moisture data to an ESP32 gateway, which forwards it over a TLS-protected link to a Java server that checks and publishes the readings into Kafka. So far this has only been tried with a single node and basic sensors, but the communication and security model look stable enough to experiment with more nodes and data sources in the next iterations.

  • Sensor types supported in PoC: 3 (temperature, humidity, soil moisture)
  • End-to-end path validated: LoRa → ESP32 (TLS) → Java → Kafka

Safety Notes

All electronics in this proof of concept run at low voltage, but standard lab safety still applies: disconnect power before rewiring, avoid short circuits, and keep metal tools away from powered boards. If the system is later connected to pumps, valves, or mains-powered equipment, proper isolation, fusing, and grounding will be essential. Network exposure should also be treated carefully when opening ports through a home router.