Everything in the environment affects the growth of crops and plants. Growers can build greenhouses and other environmental housing to control the environment, but no one can truly control the weather – which is why forecasting and weather data and intelligence is so critical. Crops are subject to weather changes, and severe changes affect optimized yields negatively in most cases.
The Tomorrow.io weather API helps growers identify weather changes and patterns so that growers can take necessary actions to preserve their product. In this article, we’ll explain the importance of humidity and give you small code snippets to help you develop a monitoring solution and make weather data a core part of your agricultural operations.
Humidity and its Impact on Crop Growth
Before getting into the code that queries the Tomorrow.io Weather API, it’s important to understand the way humidity affects crops. Once you know the way humidity affects plant growth, you can better craft your queries against the API to find the right information. The weather data you gather from the API can be used to better plan future farming activity.
Humidity plays a huge role in plant growth with different plant types favoring different conditions, and humidity percentages tell you the amount of water vapor content contained in 1 kilogram of air at a specific temperature. For example, Florida summers are known for high humidity and heat. It’s not uncommon for Floridians to experience 80% or more humidity levels during the summer months. When the weather forecast says that there will be 80% humidity at 90oF the next day, it means that 80% of every kilogram of air will be water vapor. Of course, 80% water vapor is a large percentage, which is why your body feels “wet” when you walk outside in the Florida summer heat.
We may not like high humidity, but tropical plants thrive in it. Each species of plant thrives in a particular environment, and it’s the responsibility of the grower to understand their crop’s most effective environmental factors that facilitate optimal growth and production so that they can get the best harvesting yields. In short, basic weather forecasts are not enough for farmers to optimize their crop yield with.
Plants have pores on their leaves called stomata that will open and close based on ambient levels of light intensity, humidity, and carbon dioxide. When temperatures are too high, the plant will close their stomata to preserve water. When light intensity is high, the plant stomata opens and photosynthesis occurs using carbon dioxide, water, and sunlight to produce energy in the form of glucose, water, and oxygen. Growers take advantage of this process to enrich plant growth and produce optimal conditions for the best results. Efficient humidity levels lead to better crop production, and ultimately better revenue for the grower. But it’s a tricky balance – too much humidity can lead to rot from unwanted bacterial growth. To achieve that balance, farmers need highly accurate and intelligent weather data.
Leveraging Weather Data to Gauge Future Humidity Patterns and Maximize Plant Yields
Humidity and temperature are important, but you can’t control the weather. You can, however, know what the weather will bring day-to-day and hour-to-hour using weather data. Knowing humidity changes and trends in advance gives growers plenty of time to take action that will preserve optimal yields.
Plenty of sensors and monitoring systems exist to determine current humidity levels, but they do not tell the grower future weather changes. This leaves the grower in a reactionary state that can be avoidable by leveraging weather data from a source such as Tomorrow.io. The data and queries that can be performed with the Tomorrow.io weather API can give growers the tools and information necessary to control a greenhouse environment or schedule planting and harvesting.
With the API, you can query weather data to find humidity data points for each specified interval (e.g., every hour, day, or minute). For example, you can find humidity values for every hour based on a custom timeframe. We’ll show you how to retrieve humidity data using a GET request against the Tomorrow.io weather API.
Before you query the API, it’s more convenient to set up a location from the web interface. Click the “Locations” icon on the left navigation panel, then “Add Location” and type an address into the popup. With this address, the Tomorrow.io API will retrieve the right latitude and longitude coordinates for your location, or you can use the locationId variable created and available after you save the location in your account dashboard.
With the account created and the location set up, you can now query for humidity values based on location, timesteps, and a given start and stop date in UTC format. Before you write your code, you can also test your queries in the Tomorrow documentation library.
The timeline endpoint has several available data points that can be queried. In this example, we’ll query only humidity and temperature, but the endpoint offers more than 80 data points for various weather conditions.
The basic steps in querying the timeline endpoint is to set up your query string parameters, include your API keys (available from your account dashboard in the development section), and send a GET request to the server. In this code example, we’ll use C# to query the API, but you can port this to your language of choice. Let’s first set up the variables in our code.
// the API endpoint string getTimelineURL = "https://api.tomorrow.io/v4/timelines"; // your API key string apikey = "[YOUR API KEYS]"; // we're using locationID to query a location set up in the account dashboard string location = "607f3e4188a6a60007947b82"; //locationId // units can either be imperial (US-based measurements) or metric string units = "imperial"; //timesteps is set to every hour string[] timesteps = { "1h" }; // time zone will be ET string timezone = "America/New_York"; // configuring the query to pull for the next day // first set the start time to the current date and time, ensuring that it's in UTC format (ISO 8601) string now = DateTime.UtcNow.ToString(); string startTime = DateTime.UtcNow.AddMinutes(0).ToString("o", CultureInfo.InvariantCulture); // the end time is 1 day ahead of the current time in UTC format (ISO 8601) as well string endTime = DateTime.UtcNow.AddDays(1).ToString("o", CultureInfo.InvariantCulture); // set up the fields to - return form the API string[] fields = { "temperature", "humidity" };
The code above sets up the variables necessary to query the API. Now you need to build the URL that will be used in the GET request to send a call to the API.
// set up the query string string getTimelineParameters = "apikey=" + apikey + "&location=" + location + "&fields=" + fields[0] + "&fields=" + fields[1] + "&units=" + units + "×teps=" + timesteps[0] + "&timezone=" + timezone + "&startTime=" + startTime + "&endTime=" + endTime; // the ful URL ready to query string fullUrl = "https://api.tomorrow.io/v4/timelines?" + getTimelineParameters;
This code uses a separate asynchronous call to the API. We use an asynchronous call to ensure that the browser does not lock up while making the call. This call only takes a few milliseconds, but larger queries could take longer. In a desktop application, the query could lock the computer, so you should always use an asynchronous call for remote web requests.
var apiResult = CallApi(fullUrl); JObject result = JObject.Parse(apiResult.Result);
The CallAPI function is the following:
private static async Task CallApi(string fullUrl) { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; HttpClient client = new HttpClient(); var response = client.GetStringAsync(fullUrl); return await response; }
Since the API requires a GET request, you can query in your browser to test your values. Copy and paste the full URL into your web browser, and you should see a JSON object containing a value for each hour interval similar to the following:
Notice that for each one hour interval, the data point indicates the date and time with the two values set up in the fields variable. For each hour, we now have the humidity value and the temperature.
The humidity number that you see is a percentage. Remember that humidity is the amount of water vapor present in each kilogram of air. In this example, the humidity value is 40.25% at 4/21/2021 4:27pm ET. The next humidity value of 36.83% is an hour later at 5:27pm.
Setting Alerts for Specific Thresholds Using Insights
Retrieving weather location data is useful, but it doesn’t take into account the unique thresholds and values that would concern a grower. The Tomorrow.io API has an “insights” endpoint where you can query specific events such as floods, thunderstorms, fires, winter, etc. For humidity changes, highs and lows affect crops differently, so growers need a way to customize alerts based on their own unique requirements. Custom insights are available to give growers a way to retrieve only the data that they should be concerned with.
For this example, suppose that we’re growing corn, which thrives efficiently at 50% humidity levels. If humidity rises above the 50.0% threshold, our corn could be damaged and the yield suffers. With the insights endpoint, you can create a custom query that finds all instances where humidity levels are over the 50.0% threshold. You can then create an alert that sends a message to the grower warning them of upcoming humidity changes that could affect their crops.
The easiest way to create a custom insight is using the Tomorrow.io web interface. The most difficult part of creating a custom insight is building the JSON object that defines your parameters. The following JSON object defines an operator that retrieves humidity events when the value is over 50.0.
{ "type": "OPERATOR", "content": { "operator": "GREATER" }, "children": [ { "type": "PARAMETER", "content": { "parameter": "humidity" } }, { "type": "CONST", "content": { "const": 50 } } ] }
You can also automate creation of a custom insight using a POST request against the insight endpoint. The following code will create a custom insight named “Humidity.” Note that there are limitations to the number of custom insights that can be created based on your subscription tier. If you reach the maximum number of custom insights, you will receive a 403 Forbidden response that looks like the following:
{ "code":403002 "type":"Account Limit" "message":"The plan limit for account has been reached. Examine your API plan restrictions." }
We created a function that sends a POST message to the endpoint to create the custom insight.
void CreateInsight() { string apikey = "YOUR API KEY"; Uri url = new Uri("https://api.tomorrow.io/v4/insights" + "?apikey=" + apikey); string payload = "{ " + " \"severity\": \"severe\", " + " \"name\": \"Humidity\", " + " \"conditions\": { " + " \"type\": \"OPERATOR\", " + " \"content\": { \"operator\": \"GREATER\"}, " + " \"children\": [ " + " { " + " \"type\": \"PARAMETER\", " + " \"content\": { \"parameter\": \"humidity\"} " + " }, " + " { " + " \"type\": \"CONST\", " + " \"content\": { \"const\": 50} " + " } " + " ] " + " }, " + " \"description\": \"testing\" " + " } "; HttpContent content = new StringContent(payload, Encoding.UTF8, "application/json"); var result = PostNewInsight(url, content); } private static async Task PostNewInsight(Uri fullUrl, HttpContent httpContent) { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; HttpClient client = new HttpClient(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); HttpResponseMessage result = await client.PostAsync(fullUrl, httpContent); return result; }
Creating an insight assigns it a unique identification value. You can see a list of your insights using the get-insights endpoint web interface. In code, you can retrieve your insights using a GET request, which will list your insights.
A JSON object is returned listing the identification values for each custom insight created.
{ "data":{ "insights":[ { "id":"82450235-bd3b-4c69-9c17-ebf923c35aee" "conditions":{...} "name":"Humidity" "description":"testing" "severity":"severe" "tags":[ "humidity_high" ] "createdAt":"2021-04-21T21:26:16.748Z" "updatedAt":"2021-04-21T21:26:16.748Z" } ] } "meta":{ "totalItems":1 } "links":{ "self":"/v4/insights?offset=0&limit=10" } }
With the insight created, you can now set up an alert. Alerts will tell the grower when the insight condition is met, in this case when humidity reaches levels over 50.0%.
The alerts endpoint web interface can be used to create an alert, or you can create one using the same POST code. Note that you need the “id” from the previously shown JSON object retrieved from the endpoint. This ID is used to create the new alert record. The code to create an alert:
void CreateAlert() { string apikey = "YOUR API KEY"; Uri url = new Uri("https://api.tomorrow.io/v4/alerts" + "?apikey=" + apikey); string payload = "{\"isActive\": true, \"insight\": \"82450235-bd3b-4c69-9c17-ebf923c35aee\", \"name\":\"humidity_alert\"}" ; HttpContent content = new StringContent(payload, Encoding.UTF8, "application/json"); var result = PostNewAlert(url, content); } private static async Task PostNewAlert(Uri fullUrl, HttpContent httpContent) { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; HttpClient client = new HttpClient(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); HttpResponseMessage result = await client.PostAsync(fullUrl, httpContent); return result; }
With your alert created, you can now customize your code to poll your alerts. When you find an alert that indicates humidity is over 50.0%, you can then warn the growers. Once again, you can test and view your alerts using the API web interface for the alerts endpoint. To retrieve an alert, you use a simple GET request to the endpoint with only the apikey parameter. The following function will retrieve alerts:
private static async Task GetAlerts() { string alertsUrl = "https://api.tomorrow.io/v4/timelines?apikey=YOUR_API_KEYS"; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; HttpClient client = new HttpClient(); var response = client.GetStringAsync(alertsUrl); return await response; }
You receive a JSON object that looks like the following:
{ "data":{ "alerts":[ { "id":"910723dd-1d80-464c-977c-352686f5a5db" "insight":"82450235-bd3b-4c69-9c17-ebf923c35aee" "name":"humidity_alert" "isActive":true "createdAt":"2021-04-22T16:57:05.131Z" "updatedAt":"2021-04-22T16:57:05.131Z" "createdBy":"607f0febdfda6000086cbc09" "updatedBy":"607f0febdfda6000086cbc09" "notifications":[ { "type":"START" } { "type":"END" } ] } ] } "meta": { "totalItems":1 } "links":{ "self":"/v4/alerts?offset=0&limit=10" } }
The way you use the alerts and the number of times you poll alerts depend on your own use case and subscription limitations, but this implementation can be used in your own programs to determine severe weather changes and warn agricultural businesses and growers on upcoming events that could affect their crops, and essentially their revenue. For example, by pulling alerts every hour, you could send an alert either in email, SMS text message, or on a custom dashboard that displays a warning that humidity changes are coming in the next few days.
We focused on humidity, but you can use insights from the Tomorrow.io API to poll for any severe weather conditions that could affect agriculture anywhere in the world. Alerts give you an easy way to track thresholds saving you computing resources locally. In this use case scenario, a farmer, grower, or agricultural business would know up to 15 days in advance of any upcoming weather changes. With the power of weather data through an API in their hands, farmers and agriculture companies can truly optimize their crop yields.