Implementing Soil Sensor Monitoring via a Mobile App
Soil sensors output raw data in unreadable formats—binary packets over Modbus RTU, SDI-12, or LoRaWAN protocols. Each sensor requires unique decoding: one manufacturer uses byte offsets, another scaling. Soil type, calibration, and the LoRaWAN stack must be considered, otherwise numbers become noise. We have implemented such projects for agricultural enterprises: integrating ChirpStack, decoding Cayenne LPP, displaying moisture profiles with field capacity (FC). Our experience: over 5 years in IoT, 30+ completed projects—guaranteeing reliable field performance.
An agronomist receives a notification on their smartphone: humidity at 30 cm depth dropped to 15% with a field capacity of 45%—time to start irrigation. Without a mobile app, this would go unnoticed until a visual inspection. That is why a monitoring system with sensors and LoRaWAN pays for itself in a single season, saving up to $5,000 per 100 hectares through optimized water use.
How Does Soil Sensor Monitoring Work via LoRaWAN?
A soil sensor is typically Modbus RTU or SDI-12 on a wired interface, or LoRaWAN/NB-IoT for wireless. Popular models: Sentek Drill & Drop (SDI-12), Vegetronix VH400 (analog 0-3V), TEROS 12 (SDI-12), Decagon 5TM—all with different data output formats. The mobile app receives this data via an IoT gateway or LoRaWAN Network Server—never directly. That is why LoRaWAN has become the standard for field monitoring: it provides range and energy efficiency but requires proper configuration of joiners and frequency plans. According to the LoRaWAN 1.0.4 specification, maximum range in open field reaches 10 km—five times better than Wi-Fi in open areas.
| Protocol | Range | Speed | Application |
|---|---|---|---|
| Modbus RTU | up to 1200 m (wired) | up to 115 kbps | Local greenhouse networks |
| SDI-12 | up to 60 m (wired) | 1200 bps | Weather stations, soil sensors |
| LoRaWAN | up to 10 km (open field) | 0.3-50 kbps | Field agromonitoring |
What Does the Sensor Measure and How to Interpret It
Three main soil parameters:
VWC (Volumetric Water Content) — percentage volumetric moisture. Range 0-100%, in practice for most soils the working range is 10-40%. The sensor measures the dielectric permittivity of the soil; conversion to VWC uses the Topp formula or manufacturer calibration data for a specific soil type.
EC (Electrical Conductivity) — electrical conductivity, mS/cm. Indicates salinity and nutrient concentration. Normal for most crops: 0.5-2.0 mS/cm. Above 4 mS/cm—stress for plants.
Soil temperature — important for seed germination (most crops do not germinate below 8-10°C) and microbial activity.
| Soil type | Normal VWC (%) | Field Capacity (VF, %) |
|---|---|---|
| Sand | 5-10 | 15 |
| Loamy sand | 10-20 | 25 |
| Loam | 20-35 | 45 |
| Clay | 30-45 | 55 |
Without soil type and FC context, the VWC number is meaningless. The app should show not only raw values but also their agronomic interpretation: "Moisture 19% at FC=45% for loamy sand" means dry.
How to Decode TEROS 12 Data via Cayenne LPP?
ChirpStack is an open-source LoRaWAN Network and Application Server. It provides a REST API and gRPC interface:
// Kotlin, Retrofit for ChirpStack API
interface ChirpStackApi {
@GET("api/devices/{devEui}/events")
suspend fun getDeviceEvents(
@Header("Grpc-Metadata-Authorization") token: String,
@Path("devEui") devEui: String,
@Query("limit") limit: Int = 100,
): DeviceEventsResponse
}
data class DeviceEvent(
val publishedAt: String,
val data: String, // Base64-encoded payload
val rxInfo: List<RxInfo>,
)
fun decodePayload(base64Data: String): SoilReading {
val bytes = Base64.decode(base64Data, Base64.DEFAULT)
// Decoding depends on sensor manufacturer encoding
// TEROS 12 Cayenne LPP format:
val vwc = ((bytes[1].toInt() and 0xFF) shl 8 or (bytes[2].toInt() and 0xFF)) / 100.0
val temp = ((bytes[4].toInt() and 0xFF) shl 8 or (bytes[5].toInt() and 0xFF)) / 100.0 - 40
val ec = ((bytes[7].toInt() and 0xFF) shl 8 or (bytes[8].toInt() and 0xFF)) / 100.0
return SoilReading(vwc = vwc, temperature = temp, electricalConductivity = ec)
}
For real-time via MQTT—ChirpStack publishes events to topics like application/{appId}/device/{devEui}/event/up. ChirpStack supports integration with any backend.
Why LoRaWAN Is Suitable for Field Sensors?
LoRaWAN provides a range of up to 10 km in open field with minimal power consumption. Sensors run on batteries for up to 5 years. Combined with ChirpStack and REST API, this offers flexible integration with a mobile app. Compared to cellular, LoRaWAN is 10x cheaper in data costs and 5x better in battery life.
Dashboard: Multiple Sensors in the Field
A standard configuration is 3-5 sensors at depth horizons (10, 30, 60, 90 cm) in one measurement point. The dashboard shows a moisture profile by depth—a vertical bar chart is more effective than a simple list:
Widget buildMoistureProfile(List<SoilLayerReading> layers) {
return Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
// Depth axis
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: layers.map((l) => Text('${l.depthCm} cm')).toList(),
),
const SizedBox(width: 8),
Expanded(
child: Column(
children: layers.map((layer) {
final isLow = layer.vwc < layer.fieldCapacity * 0.5;
return Container(
margin: const EdgeInsets.symmetric(vertical: 2),
height: 32,
child: LinearProgressIndicator(
value: layer.vwc / 60.0, // normalized to 60% max
backgroundColor: Colors.grey.shade200,
color: isLow ? Colors.orange : Colors.blue,
),
);
}).toList(),
),
),
],
),
);
}
How to Configure Irrigation Threshold and Trends?
The main analytical function is to show when moisture dropped to the irrigation threshold and when it returned to the target level after irrigation. This helps the agronomist confirm that the irrigation system worked correctly.
A chart from fl_chart with a horizontal threshold line:
LineChartData buildTrendChart(List<SoilReading> readings, double threshold) {
return LineChartData(
extraLinesData: ExtraLinesData(
horizontalLines: [
HorizontalLine(
y: threshold,
color: Colors.orange,
strokeWidth: 1.5,
dashArray: [5, 5],
label: HorizontalLineLabel(
show: true,
labelResolver: (_) => 'Irrigation threshold',
),
),
],
),
lineBarsData: [
LineChartBarData(
spots: readings
.map((r) => FlSpot(r.timestamp.toDouble(), r.vwc))
.toList(),
isCurved: true,
color: Colors.blue,
dotData: const FlDotData(show: false),
),
],
);
}
What Are Alerts and How to Configure Them?
Two types of alerts for soil sensors: by moisture threshold (below X%—irrigation needed) and by EC (above Y mS/cm—salinization risk). Delivery via FCM. An important nuance: moisture alerts should be filtered by time of day and days—if it just rained, an "irrigation needed" alert is excessive. The backend should account for weather station data or weather forecast.
How to avoid false alerts: expert tips
Always cross-check with recent precipitation. Use a 24-hour rain accumulation filter. Our algorithm reduces false positives by 80% compared to naive threshold alerts.How to Set Up the Monitoring System: Step-by-Step Guide
- Select and install sensors (Modbus RTU for greenhouses, LoRaWAN for the field).
- Configure the gateway and LoRaWAN Network Server (ChirpStack).
- Decode the sensor datasheet into Cayenne LPP or a custom parser.
- Develop the mobile dashboard (Flutter) with moisture profile and trend charts.
- Configure alerts with weather and soil type considerations.
- Test in the field and deploy to app stores.
What's Included in the Work
- Designing data collection architecture (protocol selection, gateways, Network Server)
- Configuring LoRaWAN Network Server (ChirpStack) and REST API
- Developing the mobile app for iOS/Android (SwiftUI / Jetpack Compose)
- Integrating with weather stations and accounting for soil type
- Field testing and deployment to App Store / Google Play
- Documentation and training for agronomists
Typical integration mistakes:
- Confusion with Cayenne LPP encoding (different manufacturers use different offsets)
- Lack of weather filtering for alerts (false triggers after rain)
- Ignoring soil type when interpreting VWC (norms differ for loamy sand and clay)
Developing a soil sensor monitoring app with LoRaWAN integration, moisture profiles, and alerts takes 3-5 weeks. The cost is calculated individually. Contact us for a consultation—we'll prepare an estimate within one day. Get a free consultation and find out how the system will pay off in your farm.







