/** * i-net software provides programming examples for illustration only, without warranty * either expressed or implied, including, but not limited to, the implied warranties * of merchantability and/or fitness for a particular purpose. This programming example * assumes that you are familiar with the programming language being demonstrated and * the tools used to create and debug procedures. i-net software support professionals * can help explain the functionality of a particular procedure, but they will not modify * these examples to provide added functionality or construct procedures to meet your * specific needs. * * Copyright © 1999-2025 i-net software GmbH, Berlin, Germany. **/ package com.inet.taskplanner.openweathermap; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.Map; import com.inet.http.servlet.ClientLocale; import com.inet.lib.json.Json; import com.inet.lib.util.EncodingFunctions; import com.inet.taskplanner.server.api.error.TaskExecutionException; import com.inet.taskplanner.server.api.job.ConditionDefinition; import com.inet.taskplanner.server.api.job.Job; import com.inet.taskplanner.server.api.job.JobResultContainer; import com.inet.taskplanner.server.api.job.ResultContainer; import com.inet.taskplanner.server.api.result.StringTextResult; /** * A handler that connects to the open weather map API and queries the current weather information.
* This instance is created by the according factory and executes the job. */ public class OpenWeatherMapJob extends Job { // The URL to the openweathermap.org API private static final String API_URL = "https://api.openweathermap.org/data/2.5/"; // Value, defined by the user private String apiKey; private String location; private Units units = Units.DEFAULT; // current temperature is stored as member in this instance to allow the condition to be evaluated afterwards private double currentTemperature = 0d; // Will be set to true if the user requested a stopping of the job private boolean stopRequested = false; /** * Creates the job. * @param apiKey the open weather map api key * @param location the set location to get the weather data for * @param units the selected unit setting * @param condition the optional condition that can be applies */ public OpenWeatherMapJob( String apiKey, String location, String units, ConditionDefinition condition ) { super( condition ); this.apiKey = apiKey; this.location = location; if( units != null ) { try { this.units = Units.valueOf( units ); } catch( IllegalArgumentException iae ) { // Fallback to DEFAULT } } } /** * {@inheritDoc} */ @Override protected JobResultContainer run() throws TaskExecutionException { try { String cityAndCountry = "q=" + EncodingFunctions.encodeUrlParameter( location ); // Location as City,CountryCode as search query String appID = "appid=" + EncodingFunctions.encodeUrlParameter( apiKey ); // App ID, entered by the user String language = "lang=" + EncodingFunctions.encodeUrlParameter( ClientLocale.getThreadLocale().getLanguage().toLowerCase() ); // Current language settings retrieved from the client locale String unitSettings = "units=" + EncodingFunctions.encodeUrlParameter( units.name().toLowerCase() ); // The units, selected by the user // Create the target URL URL target = new URL( API_URL + "weather?" + cityAndCountry + "&" + appID + "&" + language + "&" + unitSettings ); if( stopRequested ) { return null; } // Open the connection and read the data from the input stream URLConnection connection = target.openConnection(); try (InputStream inputStream = connection.getInputStream()) { if( stopRequested ) { return null; } // Read the data with the JSON-Parser into a WeatherData instance. // the HashMap for extraFields is set, to allow additional fields int the response data that can be ignored. Values that do not match a field, will be added to this map. WeatherData weatherData = new Json().fromJson( inputStream, WeatherData.class, new HashMap>(), null ); if( weatherData.getCod() != 200 ) { // If the code os not 200 OK, throw exception throw new TaskExecutionException( new IllegalArgumentException( TaskPlannerOpenWeatherMapServerPlugin.MSG.getMsg( "taskplanner.openweathermap.errorcode", Integer.valueOf( weatherData.getCod() ) ) ) ); } // Get and remeber the current temperature currentTemperature = weatherData.getMain().getTemp(); DateFormat dateTimeFormat = SimpleDateFormat.getTimeInstance( SimpleDateFormat.SHORT ); // Get all details and format them String weather = weatherData.getWeather().get( 0 ).getDescription(); String temperature = String.format( "%.2f", Double.valueOf( weatherData.getMain().getTemp() ) ) + " " + units.getTemperatureUnit(); String pressure = weatherData.getMain().getPressure() + " hPa"; String humidity = weatherData.getMain().getHumidity() + "%"; String windSpeed = weatherData.getWind().getSpeed() + " " + units.getSpeedUnit(); String sunrise = dateTimeFormat.format( new Date( weatherData.getSys().getSunrise() * 1000 ) ); String sunset = dateTimeFormat.format( new Date( weatherData.getSys().getSunset() * 1000 ) ); // Create a text result with the formatted information StringBuilder text = new StringBuilder(); text.append( TaskPlannerOpenWeatherMapServerPlugin.MSG.getMsg( "taskplanner.openweathermap.details.weather" ) + ": " + weather ); text.append( "\r\n" ); text.append( TaskPlannerOpenWeatherMapServerPlugin.MSG.getMsg( "taskplanner.openweathermap.details.temp" ) + ": " + temperature ); text.append( "\r\n" ); text.append( TaskPlannerOpenWeatherMapServerPlugin.MSG.getMsg( "taskplanner.openweathermap.details.pressure" ) + ": " + pressure ); text.append( "\r\n" ); text.append( TaskPlannerOpenWeatherMapServerPlugin.MSG.getMsg( "taskplanner.openweathermap.details.humidity" ) + ": " + humidity ); text.append( "\r\n" ); text.append( TaskPlannerOpenWeatherMapServerPlugin.MSG.getMsg( "taskplanner.openweathermap.details.wind" ) + ": " + windSpeed ); text.append( "\r\n" ); text.append( TaskPlannerOpenWeatherMapServerPlugin.MSG.getMsg( "taskplanner.openweathermap.details.sunrise" ) + ": " + sunrise ); text.append( "\r\n" ); text.append( TaskPlannerOpenWeatherMapServerPlugin.MSG.getMsg( "taskplanner.openweathermap.details.sunset" ) + ": " + sunset ); text.append( "\r\n" ); StringTextResult result = new StringTextResult( text.toString(), "text/plain" ); // Set the weather details as meta properties so that the placeholder keys from the factory have values. Map metaProperties = new HashMap(); metaProperties.put( "weather.city", weatherData.getName() ); metaProperties.put( "weather.country", weatherData.getSys().getCountry() ); metaProperties.put( "weather.description", weather ); metaProperties.put( "weather.temperature", temperature ); metaProperties.put( "weather.pressure", pressure ); metaProperties.put( "weather.humidity", humidity ); metaProperties.put( "weather.windspeed", windSpeed ); metaProperties.put( "weather.sunrise", sunrise ); metaProperties.put( "weather.sunset", sunset ); // Return the result and meta properties return new ResultContainer( Arrays.asList( result ), metaProperties ); } } catch( Throwable t ) { TaskPlannerOpenWeatherMapServerPlugin.LOGGER.error( t ); throw new TaskExecutionException( t ); } } /** * {@inheritDoc} */ @Override protected boolean evaluateCondition( ConditionDefinition conditionDefinition ) { // Check whether the temperature condition is fulfilled. String temperature = conditionDefinition.getProperty( OpenWeatherMapJobFactory.PROPERTY_TEMPERATURE ); try { double temp = Double.parseDouble( temperature ); return currentTemperature > temp; } catch( NumberFormatException nfe ) { return false; } }; /** * {@inheritDoc} */ @Override public void stopRequested() { this.stopRequested = true; } }