Precision farming

Precision farming – also called precision agriculture, smart farming or smart agriculture – has been around since the late 90s and stems from a simple observation: over the past few decades, in order to cope with ever expanding demand on productivity, farmers have been dealing with fields that grew larger and larger. Most of the time however, the latter are treated as single uniform areas, without taking into consideration potential local variations of different factors such as soil types, availability of nutrient, temperature, etc. This often results in non-optimized use of resources such as water, fertilizers, or pesticides, which increases production costs because of excessive and unnecessary use. Conversely, this also sometimes leads to insufficient crops yields due to a lack of resources where they were most needed.

Precision farming is thus an approach that fosters the adoption of “site-specific” methods to manage crop fields. This basically consists in considering the smallest possible field parcels as single units (from a few square meters to a single plant), taking their specific characteristics into consideration in order to determine, as accurately as possible, their requirements in terms of resources. It is worth mentioning that precision farming is applicable to all the agricultural production system, not only to crops. In the remainder of this document, we will however stick to the cropping system (“site specific crop management”).

The purpose of precision farming is hence to allow farmers to produce more efficiently, while optimizing costs, preserving resources and reducing the impact of their usage on the environment. In addition to improving farmers’ profit, precision farming is also seen as a way to face the challenges raised handling a rising world population (the Food and Agriculture Organization estimates that food production will have to increase by 70% by 2050).

Leveraging the IoT

Precision farming heavily relies on extended and accurate knowledge of the multiple factors – weather, soil composition, humidity, temperature, light, crop behavior, machine status, etc. – which influence the yield of a given field parcel. This knowledge can be obtained by combining data stemming from different sources, notably sensors, APIs, GPS, drones, satellites, etc. and can be utilized at two complementary levels:

  • Real time data can be used to drive ad-hoc and “smart” decision making, based on observed opportunities (or threats),
  • Statistical data, resulting from the analysis of historical data, allows for producing predictive models, planning and continuous improvement of farm management and techniques.

Precision farming therefore needs to resort to connected objects (notably sensors and cameras) to extract local data, and resort to Big Data and analytics tools to store the huge volume of generated data, process it, and turn it into actionable information and events.

Precision farming also needs to be able to integrate the services offered by the former components into structured and organized orchestrations:

  • Data that is extracted from heterogeneous sensors needs to be pre-processed, in order to eliminate any insignificant data and therefore reduce the volume of data to be stored, or in order to enrich it with other data obtained from different sources and/or through calculations
  • Extracted data also needs to be transformed into a “normalized” form in order to enable interoperability among the different stakeholders of a precision farming solution (this is notably due to the lack of standards in this field)
  • Data needs to be conveyed to stakeholders of different types (human actors, systems such as Geographic
    Information Systems or other third party APIs). This implies the availability of multiple communication means and protocols (push notifications, email, HTTP calls, web sockets, messaging, etc.)
  • Rules need to be defined in order to determine the actions to execute upon the occurrence of certain events and unfold the corresponding procedures. More generally, processes have to be defined in order to integrate and orchestrate the multiple participants of the Precision Farming solution

Providing the above features, while guaranteeing the scalability and the security of the system, and notably data privacy, is the job of IoT platforms, such as scriptr.io.

A simple example using scriptr.io and Parrot’s Flower Power

In this section we give a short demonstration of how a collaboration between connected devices, APIs and an IoT platform, as scriptr.io, can be leveraged to implement a smart farming solution. To keep things simple though, we only focus on determining the best daily water volume needed to irrigate the plants of a given garden (applying simplified formulas).

The plants are monitored using Parrot Flower Power devices, to which we connect using scriptr.io’s Flower Power connector. The Flower Power device is a very interesting set of sensors that analyze the moisture of the soil, the fertilizer ratio, the light exposure and air temperature of a nearby plant. Using the companion mobile app, an end user can create “virtual” gardens by specifying the type of plants they contain and their corresponding Flower Power device. The device communicates with the app via Bluetooth.

Because of their limited range due to the Bluetooth connectivity and to their price, Flower Power devices are not the best candidates for a real precision farming solution. Yet, the features they provide make them very interesting for individual use, and also for implementing a demonstration prototype as in our case.

In the following lines, we implement a script that elaborates the irrigation plan of all the plants of a given garden. Based on a predefined volume of water, the script takes into consideration the moisture ratio of each plant’s soil, as well as the forecast maximum temperature expected at the plant’s location. The former is directly obtained from the Flower Power device that is monitoring the given plant, while the latter is obtained by interrogating the OpenWeatherMap API. In order to determine the adjustment needed depending on the soil’s moisture ratio, the script uses historical data (average moisture depletion) stored in scriptr.io’s store. Once the plan is established (all plants have a specified water volume for the current day), it is send by email to a predefined user (the farmer) and returned by the script.

// import scriptr.io's connector to the flower power APIs
var flowerPowerModule = require("modules/parrot/flowerpower/client.js");
var http = require("http");

// Default water volume to use when watering a plant 
var WATERING_VOLUME = 0.2;
// Average moisture ratio of soils (in case not available)
var AVERAGE_MOISTURE_RATIO = 33;
// Average air temperature
var AVERAGE_TEMP = 25;

var username = "smart_farmer@smartfarm.com"; // replace with your email

// create an instance of the FlowerPower connector
var flowerpower = new flowerPowerModule.FlowerPower({username: username});

/* 
 * MAIN PROCESS *
 */

var irrigationPlan = [];

// Get the current soil mosture, light, temperature and fertilizer status of all locations of our garden
var locations = flowerpower.getGardenLocationsStatus().locations;

// List all locations of the garden to obtain data such as coordinates and plant name
var locationsData = flowerpower.listLocations();

// Loop through the list of locations. For each location, determine water adjustments depending
// on the current soil moisture ratio and the forecast max temperature at this location
for (var i = 0;  i < locations.length; i++) { var water = WATERING_VOLUME; var waterDelta = getWaterAdjustmentFromSoilMoisture(locations[i]); var water = water * (1 + waterDelta); var currentLocationData = locationsData[locations[i].location_identifier]; waterDelta = getWaterAdjustmentFromWeatherForecast(currentLocationData); water = water * (1 + waterDelta); // Create irrigation instructions for the current plant var irrigationInstruction = { location: locations[i].location_identifier, plant: currentLocationData.plant_nickname, coordinates: currentLocationData.latitude + "," + currentLocationData.longitude, water: water }; // add the instructions to the plan irrigationPlan.push(irrigationInstruction); } // send today's irrigation plan to the user sendWateringPlan(irrigationPlan, username); // return the plan to the caller return irrigationPlan; /* * Determine the needed adjustment of the water volume depending on the soil moisture * @param {Object} location : the location status (current values of soil moisture, light, fertilizer, temperature) * @return {float} the percentage of water to add to or to remove from the nominal volume */ function getWaterAdjustmentFromSoilMoisture(location) { var waterDelta = 0; // Get the current soil moisture ratio var currentMoistureRatio = location.soil_moisture.gauge_values.current_value; // Get the expected soil moisture based on the average depletion for this location as the same time of day (stored in scriptr.io's store) var currentTime = new Date().getHours(); var expectedMoistureRatio = AVERAGE_MOISTURE_RATIO - storage.flowerpower[location_identifier][currentTime].averageDepletion; // we assume here that we already calculated and stored the average depletion // if the current soil moisture ratio is higher than expected, decrease the volume of water to use proportionally // otherwise, increase it proportionally if (currentMoistureRatio > expectedMoistureRatio) {
    return waterDelta - (1 - currentMoistureRatio / expectedMoistureRatio);
  }else {
    return waterDelta + (1 - currentMoistureRatio / expectedMoistureRatio);
  }
}

/**
 * Determine the needed adjustment of the water volume depending on the forecast 
 * max temperature of the day
 * @param {Object} currentLocationData: a location object containing data about the current location
 * such as its coordinates, the plant's name, etc.
 * @return {float} the percentage of water to add to the nominal volume
 */
function getWaterAdjustmentFromWeatherForecast(currentLocationData) {

  // We invoke the openweathermap API, asking for weather forecast
  // for these coordinates
  var weatherApiParams = {
    
    url: "http://api.openweathermap.org/data/2.5/forecast",
    params: {
    	lat: currentLocationData.latitude,
    	lon: currentLocationData.longitude,
    	appid: "23e9f6f9104625520f7l3eje6eb8fr3x" // Replace with the API key you obtain from OpenWeatherMap
    }
  }
  
  // Parse the response obtained from the API
  var response = http.request(weatherApiParams);
  var weatherForecast = JSON.parse(response.body);
  var forecastForToday = weatherForecast.list[0];
  
  // Get the difference between the average, ideal, temperature and the forecast max temperature
  // use it to determine the percentage of water to add to the nominal volume
  var currentDayMaxTemperature = forecastForToday.main.temp_max / 10;
  if (currentDayMaxTemperature > AVERAGE_TEMP) {
    return (1 - AVERAGE_TEMP / currentDayMaxTemperature);
  }else {
  	return 0;  
  }
}

/**
 * Send the watering plan by email to the given user
 * @param {Array} irrigationPlan : an array of irrigation instructions per plant
 * @param {String} username: the email address of the user to send the plan to
 */
function sendWateringPlan(irrigationplan, username) {
  
  var prettyInstructions = JSON.stringify(irrigationPlan);
  prettyInstructions = prettyInstructions.replace(/\[/g, "");
  prettyInstructions = prettyInstructions.replace(/\{/g, "");
  prettyInstructions = prettyInstructions.replace(/\]/g, "");
  prettyInstructions = prettyInstructions.replace(/\}/g, ",\n");
  sendMail(username, "Smart Watering System", "Today's irrigation plan", prettyInstructions);
}