Skip to content
Snippets Groups Projects
Commit 31336b9c authored by Tor-Einar Skog's avatar Tor-Einar Skog
Browse files

Adding parsing of weather data from Finnish A-Lab weather stattions

parent 99c47e0a
No related branches found
No related tags found
No related merge requests found
...@@ -155,6 +155,11 @@ ...@@ -155,6 +155,11 @@
<groupId>com.ibm.icu</groupId> <groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId> <artifactId>icu4j</artifactId>
<version>52.1</version> <version>52.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.1</version>
</dependency> </dependency>
</dependencies> </dependencies>
......
...@@ -56,7 +56,7 @@ import org.hibernate.annotations.Type; ...@@ -56,7 +56,7 @@ import org.hibernate.annotations.Type;
@NamedQuery(name = "Observation.findByTimeOfObservation", query = "SELECT o FROM Observation o WHERE o.timeOfObservation = :timeOfObservation"), @NamedQuery(name = "Observation.findByTimeOfObservation", query = "SELECT o FROM Observation o WHERE o.timeOfObservation = :timeOfObservation"),
@NamedQuery(name = "Observation.findByObservedValue", query = "SELECT o FROM Observation o WHERE o.observedValue = :observedValue"), @NamedQuery(name = "Observation.findByObservedValue", query = "SELECT o FROM Observation o WHERE o.observedValue = :observedValue"),
@NamedQuery(name = "Observation.findByDenominator", query = "SELECT o FROM Observation o WHERE o.denominator = :denominator")}) @NamedQuery(name = "Observation.findByDenominator", query = "SELECT o FROM Observation o WHERE o.denominator = :denominator")})
public class Observation implements Serializable { public class Observation implements Serializable, no.bioforsk.vips.observation.Observation {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private Integer observationId; private Integer observationId;
...@@ -215,4 +215,22 @@ public class Observation implements Serializable { ...@@ -215,4 +215,22 @@ public class Observation implements Serializable {
this.organism = organism; this.organism = organism;
} }
@Override
@Transient
public Double getLatitude() {
return this.getLocationCoordinate().y;
}
@Override
@Transient
public Double getLongitude() {
return this.getLocationCoordinate().x;
}
@Override
@Transient
public String getName() {
return this.getOrganism().getLatinName();
}
} }
...@@ -60,6 +60,7 @@ import no.bioforsk.vips.logic.entity.VipsLogicUser; ...@@ -60,6 +60,7 @@ import no.bioforsk.vips.logic.entity.VipsLogicUser;
import no.bioforsk.vips.logic.util.SessionControllerGetter; import no.bioforsk.vips.logic.util.SessionControllerGetter;
import no.bioforsk.vips.logic.util.SystemTime; import no.bioforsk.vips.logic.util.SystemTime;
import no.bioforsk.vips.util.ServletUtil; import no.bioforsk.vips.util.ServletUtil;
import no.bioforsk.vips.util.weather.ALabDataParser;
import no.bioforsk.vips.util.weather.MetosDataParser; import no.bioforsk.vips.util.weather.MetosDataParser;
import no.bioforsk.vips.util.weather.ParseWeatherDataException; import no.bioforsk.vips.util.weather.ParseWeatherDataException;
import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget; import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
...@@ -356,6 +357,40 @@ public class LogicService { ...@@ -356,6 +357,40 @@ public class LogicService {
return Response.ok().entity(observations).build(); return Response.ok().entity(observations).build();
} }
@GET
@POST
@Path("weather/proxy/alab/{stationId}")
@Produces("application/json;charset=UTF-8")
public Response getALabWeatherData(
@PathParam("stationId") String stationId,
@FormParam("timeZone") String timeZonePOST,
@QueryParam("timeZone") String timeZoneGET,
@FormParam("startDate") String startDatePOST,
@QueryParam("startDate") String startDateGET,
@FormParam("userName") String userNamePOST,
@QueryParam("userName") String userNameGET,
@FormParam("password") String passwordPOST,
@QueryParam("password") String passwordGET
)
{
List<WeatherObservation> observations;
try
{
String timeZoneParam = timeZonePOST != null ? timeZonePOST : timeZoneGET != null ? timeZoneGET : "UTC";
TimeZone timeZone = TimeZone.getTimeZone(timeZoneParam);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
format.setTimeZone(timeZone);
String startDateParam = startDatePOST != null ? startDatePOST : startDateGET;
Date startDate1 = format.parse(startDateParam);
String userName = userNamePOST != null ? userNamePOST:userNameGET;
String password = passwordPOST != null ? passwordPOST:passwordGET;
observations = new ALabDataParser().getWeatherObservations(stationId, timeZone, startDate1, userName, password);
} catch (ParseException | ParseWeatherDataException | NullPointerException ex) {
return Response.serverError().entity(ex).build();
}
return Response.ok().entity(observations).build();
}
private ManagerResource getManagerResource() private ManagerResource getManagerResource()
{ {
Client client = ClientBuilder.newClient(); Client client = ClientBuilder.newClient();
......
/*
* Copyright (c) 2015 NIBIO <http://www.nibio.no/>.
*
* This file is part of VIPSLogic.
* VIPSLogic is free software: you can redistribute it and/or modify
* it under the terms of the NIBIO Open Source License as published by
* NIBIO, either version 1 of the License, or (at your option) any
* later version.
*
* VIPSLogic is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* NIBIO Open Source License for more details.
*
* You should have received a copy of the NIBIO Open Source License
* along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>.
*
*/
package no.bioforsk.vips.util.weather;
import java.io.IOException;
import java.net.URL;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import no.bioforsk.vips.entity.WeatherObservation;
import no.bioforsk.vips.util.InvalidAggregationTypeException;
import no.bioforsk.vips.util.WeatherObservationListException;
import no.bioforsk.vips.util.WeatherUtil;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
/**
* Reads/parses data from A-Lab weather stations
* @copyright 2015 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/
public class ALabDataParser {
private static final Map<String, String> parameters;
static {
Map<String, String> staticMap = new HashMap<>();
staticMap.put("119", "TM");
staticMap.put("120", "UM");
staticMap.put("121", "RRACC"); // Accumulated rain over an unkown amount of time!
staticMap.put("122", "DD2");
staticMap.put("123", "FF2");
staticMap.put("124", "PPP");
staticMap.put("125", "TJM10");
staticMap.put("126", "VAN10p");
parameters = Collections.unmodifiableMap(staticMap);
}
//
public final static String ALAB_URL_TEMPLATE = "http://xml.a-log.net/xml-export.cgi?devid={0}&username={1}&password={2}&measurements=all&from={3}&to={4}";
public List<WeatherObservation> getWeatherObservations(String stationID, TimeZone timeZone, Date startDate, String userName, String password) throws ParseWeatherDataException
{
List<WeatherObservation> retVal = new ArrayList<>();
DateFormat timeParseFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
timeParseFormat.setTimeZone(timeZone);
WeatherUtil wUtil = new WeatherUtil();
startDate = wUtil.normalizeToExactDate(startDate, timeZone);
Date endDate = wUtil.normalizeToExactDate(new Date(), timeZone);
DateFormat urlDateFormat = new SimpleDateFormat("yyyy-MM-dd");
urlDateFormat.setTimeZone(timeZone);
String from = urlDateFormat.format(startDate);
String to = urlDateFormat.format(endDate);
// Get the raw data from service, serialize into WeatherObservations
Map<String, List<WeatherObservation>> serialized = new HashMap<>();
try {
URL aLabURL = new URL(MessageFormat.format(ALabDataParser.ALAB_URL_TEMPLATE, stationID,userName,password,from,to));
Document doc = this.getDocument(aLabURL);
// Get all measurements at 15 min intervals
// Must aggregate afterwards
List<Node> list = doc.selectNodes("//Measurement");
for(Node node:list)
{
Date timeMeasured = timeParseFormat.parse(node.valueOf("@Time"));
List<Node> valueNodes = node.selectNodes("Value");
for(Node valueNode : valueNodes)
{
WeatherObservation obs = new WeatherObservation();
obs.setTimeMeasured(timeMeasured);
obs.setElementMeasurementTypeId(ALabDataParser.parameters.get(valueNode.valueOf("@Type")));
// Set logInterval to 15min
obs.setLogIntervalId(WeatherObservation.LOG_INTERVAL_ID_15M);
obs.setValue(Double.valueOf(valueNode.getText()));
if(!serialized.containsKey(obs.getElementMeasurementTypeId()))
{
serialized.put(obs.getElementMeasurementTypeId(), new ArrayList<WeatherObservation>());
}
serialized.get(obs.getElementMeasurementTypeId()).add(obs);
}
//System.out.println(timeMeasured);
}
}
catch(IOException | DocumentException | ParseException ex)
{
throw new ParseWeatherDataException(ex.getMessage());
}
try
{
// Convert from 15 min intervals to hourly intervals
// Bear in mind that RRACC must be converted to RR
for(String param:serialized.keySet())
{
List<WeatherObservation> paramObs = serialized.get(param);
paramObs = wUtil.removeDuplicateWeatherObservations(paramObs, 0.05);
if(!param.equals("RRACC"))
{
retVal.addAll(wUtil.getAggregateHourlyValues(paramObs, timeZone, WeatherObservation.LOG_INTERVAL_ID_15M, WeatherUtil.AGGREGATION_TYPE_AVERAGE));
}
else
{
//System.out.println("RRACC being calculated");
retVal.addAll(wUtil.getIncrementalValuesFromAccumulated(paramObs, timeZone, WeatherObservation.LOG_INTERVAL_ID_1H));
}
}
}catch (WeatherObservationListException | InvalidAggregationTypeException ex)
{
throw new ParseWeatherDataException(ex.getMessage());
}
Collections.sort(retVal);
return retVal;
}
private Document getDocument(URL url) throws IOException, DocumentException
{
//System.out.println("URL=" + url.toString());
/*BufferedReader in = new BufferedReader(
new InputStreamReader(url.openStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
{
System.out.println(inputLine);
}*/
Document doc = new SAXReader().read(url);
return doc;
}
}
...@@ -139,7 +139,7 @@ public class MetosDataParser { ...@@ -139,7 +139,7 @@ public class MetosDataParser {
} }
} }
in.close(); in.close();
} catch (IOException ex) { } catch (IOException ex) {
throw new ParseWeatherDataException(ex.getMessage()); throw new ParseWeatherDataException(ex.getMessage());
} }
......
/*
* Copyright (c) 2015 NIBIO <http://www.nibio.no/>.
*
* This file is part of VIPSLogic.
* VIPSLogic is free software: you can redistribute it and/or modify
* it under the terms of the NIBIO Open Source License as published by
* NIBIO, either version 1 of the License, or (at your option) any
* later version.
*
* VIPSLogic is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* NIBIO Open Source License for more details.
*
* You should have received a copy of the NIBIO Open Source License
* along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>.
*
*/
package no.bioforsk.vips.util.weather;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import no.bioforsk.vips.entity.WeatherObservation;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
/**
*
* @author treinar
*/
public class ALabDataParserTest {
public ALabDataParserTest() {
}
@BeforeClass
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
/**
* Test of getWeatherObservations method, of class ALabDataParser.
*/
//@Test
public void testGetWeatherObservations_5args() throws Exception {
System.out.println("getWeatherObservations");
String stationID = "000000000010FDC62301";
TimeZone timeZone = TimeZone.getTimeZone("Europe/Helsinki");
DateFormat dFormat = new SimpleDateFormat("yyyy-MM-dd");
dFormat.setTimeZone(timeZone);
Date startDate = dFormat.parse("2015-01-01");
String userName = "fmi";
String password = "ectoncha";
ALabDataParser instance = new ALabDataParser();
List<WeatherObservation> expResult = null;
List<WeatherObservation> result = instance.getWeatherObservations(stationID, timeZone, startDate, userName, password);
assertNotNull(result);
/**for(WeatherObservation obs: result)
{
if(obs.getElementMeasurementTypeId().equals("RR"))
{
System.out.println(obs);
}
}*/
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment