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

Prepared for Plasmopara viticola model

Added parser for data from Metos service
parent aab08ac7
No related branches found
No related tags found
No related merge requests found
Showing
with 440 additions and 5 deletions
......@@ -46,6 +46,7 @@ public class VIPSLogicApplication extends Application
*/
private void addRestResourceClassesManually(Set<Class<?>> resources) {
resources.add(no.bioforsk.vips.logic.service.LogicService.class);
//resources.add(no.bioforsk.vips.logic.service.JacksonConfig.class);
//resources.add(no.bioforsk.vips.coremanager.service.ManagerResourceImpl.class);
}
......@@ -55,6 +56,7 @@ public class VIPSLogicApplication extends Application
* given list with all resources defined in the project.
*/
private void addRestResourceClasses(Set<Class<?>> resources) {
resources.add(no.bioforsk.vips.logic.service.JacksonConfig.class);
resources.add(no.bioforsk.vips.logic.service.LogicService.class);
}
......
......@@ -209,10 +209,10 @@ public class PointOfInterestController extends HttpServlet {
weatherStation.setWeatherStationRemoteId(formValidation.getFormField("weatherStationRemoteId").getWebValue());
weatherStation.setTimeZone(formValidation.getFormField("timeZone").getWebValue());
weatherStation.setCountryCode(em.find(Country.class, formValidation.getFormField("countryCode").getWebValue()));
if(weatherStation.getPointOfInterestType() == null)
/*if(weatherStation.getPointOfInterestType() == null)
{
weatherStation.setPointOfInterestType(em.find(PointOfInterestType.class, Globals.POI_TYPE_WEATHERSTATION));
}
//weatherStation.setPointOfInterestType(em.find(PointOfInterestType.class, Globals.POI_TYPE_WEATHERSTATION));
}*/
// If userId is set from form, always update
if(user.isSuperUser() && !formValidation.getFormField("userId").isEmpty())
{
......
/*
* Copyright (c) 2015 Bioforsk <http://www.bioforsk.no/>.
*
* This file is part of VIPSLogic.
* VIPSLogic is free software: you can redistribute it and/or modify
* it under the terms of the Bioforsk Open Source License as published by
* Bioforsk, 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
* Bioforsk Open Source License for more details.
*
* You should have received a copy of the Bioforsk Open Source License
* along with VIPSLogic. If not, see <http://www.bioforsk.no/licenses/>.
*
*/
package no.bioforsk.vips.logic.scheduling.model.preprocessor;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import no.bioforsk.vips.entity.ModelConfiguration;
import no.bioforsk.vips.entity.WeatherObservation;
import no.bioforsk.vips.logic.entity.ForecastConfiguration;
import no.bioforsk.vips.logic.entity.PointOfInterestWeatherStation;
import no.bioforsk.vips.logic.scheduling.model.ModelRunPreprocessor;
import no.bioforsk.vips.logic.scheduling.model.PreprocessorException;
import no.bioforsk.vips.logic.util.SystemTime;
import no.bioforsk.vips.model.ConfigValidationException;
import no.bioforsk.vips.util.WeatherElements;
import no.bioforsk.vips.util.WeatherObservationListException;
import no.bioforsk.vips.util.WeatherUtil;
/**
* @copyright 2015 <a href="http://www.bioforsk.no/">Bioforsk</a>
* @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
*/
public class PlasmoparaViticolaModelPreprocessor extends ModelRunPreprocessor{
@Override
public ModelConfiguration getModelConfiguration(ForecastConfiguration configuration) throws PreprocessorException {
PointOfInterestWeatherStation weatherStation = (PointOfInterestWeatherStation) configuration.getWeatherStationPointOfInterestId();
// What timezone is the calculation for
TimeZone timeZone = TimeZone.getTimeZone(weatherStation.getTimeZone());
// Getting January 1st
Calendar cal = Calendar.getInstance(timeZone);
cal.setTime(SystemTime.getSystemTime());
cal.add(Calendar.DATE, 3);
WeatherUtil wUtil = new WeatherUtil();
Date endDate = wUtil.normalizeToExactDate(cal.getTime(), timeZone);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DATE, 1);
Date startDate = wUtil.normalizeToExactDate(cal.getTime(), timeZone);
List<WeatherObservation> observations = getWeatherObservations(
weatherStation.getDataFetchUri(),
WeatherObservation.LOG_INTERVAL_ID_1H,
new String[]{
WeatherElements.TEMPERATURE_MEAN,
WeatherElements.PRECIPITATION
},
startDate,
endDate,
timeZone);
// TODO: weather data validation
ModelConfiguration retVal = new ModelConfiguration();
retVal.setModelId(this.getModelId());
retVal.setConfigParameter("timeZone", timeZone.getID());
retVal.setConfigParameter("observations", observations);
return retVal;
}
@Override
public String getModelId() {
return "PLASMOVITI";
}
}
/*
* Copyright (c) 2015 Bioforsk <http://www.bioforsk.no/>.
*
* This file is part of VIPSLogic.
* VIPSLogic is free software: you can redistribute it and/or modify
* it under the terms of the Bioforsk Open Source License as published by
* Bioforsk, 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
* Bioforsk Open Source License for more details.
*
* You should have received a copy of the Bioforsk Open Source License
* along with VIPSLogic. If not, see <http://www.bioforsk.no/licenses/>.
*
*/
package no.bioforsk.vips.logic.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
/**
* Add this to no.bioforsk.vips.logic.VIPSLogicApplication if you want all
* dates to be serialized as ISO formatted date strings
* @copyright 2015 <a href="http://www.bioforsk.no/">Bioforsk</a>
* @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
*/
@Provider
public class JacksonConfig implements ContextResolver<ObjectMapper>
{
private final ObjectMapper objectMapper;
public JacksonConfig() throws Exception
{
objectMapper = new ObjectMapper().configure(
SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
}
@Override
public ObjectMapper getContext(Class<?> arg0)
{
return objectMapper;
}
}
\ No newline at end of file
......@@ -26,8 +26,11 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
......@@ -38,12 +41,12 @@ import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import no.bioforsk.vips.coremanager.service.ManagerResource;
import no.bioforsk.vips.entity.WeatherObservation;
import no.bioforsk.vips.logic.authenticate.PasswordValidationException;
import no.bioforsk.vips.logic.entity.ForecastResult;
import no.bioforsk.vips.logic.i18n.SessionLocaleUtil;
import no.bioforsk.vips.logic.entity.ForecastConfiguration;
import no.bioforsk.vips.logic.entity.ForecastModelConfiguration;
import no.bioforsk.vips.logic.entity.ForecastSummary;
import no.bioforsk.vips.logic.entity.Message;
import no.bioforsk.vips.logic.entity.MessageTag;
import no.bioforsk.vips.logic.entity.Observation;
......@@ -52,6 +55,8 @@ import no.bioforsk.vips.logic.entity.VipsLogicUser;
import no.bioforsk.vips.logic.util.SessionControllerGetter;
import no.bioforsk.vips.logic.util.SystemTime;
import no.bioforsk.vips.util.ServletUtil;
import no.bioforsk.vips.util.weather.MetosDataParser;
import no.bioforsk.vips.util.weather.ParseWeatherDataException;
import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
import org.jboss.resteasy.spi.HttpRequest;
......@@ -268,6 +273,21 @@ public class LogicService {
return Response.ok().entity(observations).build();
}
@GET
@POST
@Path("weather/proxy/metos/{stationId}")
@Produces("application/json;charset=UTF-8")
public Response getMetosWeatherData(@PathParam("stationId") String stationId)
{
List<WeatherObservation> observations;
try {
observations = new MetosDataParser().getWeatherObservations(stationId);
} catch (ParseWeatherDataException ex) {
return Response.serverError().entity(ex).build();
}
return Response.ok().entity(observations).build();
}
private ManagerResource getManagerResource()
{
Client client = ClientBuilder.newClient();
......
/*
* Copyright (c) 2015 Bioforsk <http://www.bioforsk.no/>.
*
* This file is part of VIPSLogic.
* VIPSLogic is free software: you can redistribute it and/or modify
* it under the terms of the Bioforsk Open Source License as published by
* Bioforsk, 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
* Bioforsk Open Source License for more details.
*
* You should have received a copy of the Bioforsk Open Source License
* along with VIPSLogic. If not, see <http://www.bioforsk.no/licenses/>.
*
*/
package no.bioforsk.vips.util.weather;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import no.bioforsk.vips.entity.WeatherObservation;
/**
* Reads/parses data from a Metos weather station
* For future versions (need authentication per station): http://www.fieldclimate.com/json_manual/
* @copyright 2015 <a href="http://www.bioforsk.no/">Bioforsk</a>
* @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
*/
public class MetosDataParser {
public final static String METOS_URL_TEMPLATE = "http://www.fieldclimate.com/rimpro/all_sensors_csv.php?s={0}";
// Structure of file from Metos, including aggregation type
private final static String[][] elementMeasurementTypes = {
{"Q0","AVG"},
{"RR","SUM"},
{"FM2","AVG"},
{"BATTERY","AVG"},
{"BT","SUM"},
{"TM","AVG"},
{"UM","AVG"}
};
/**
* Using output designed for RIMPro, parsing into WeatherObservations
* @param stationID the METOS station ID
* @return
*/
public List<WeatherObservation> getWeatherObservations(String stationID) throws ParseWeatherDataException
{
List<WeatherObservation> retVal = new ArrayList<>();
SimpleDateFormat dFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
try {
URL metosURL = new URL(MessageFormat.format(MetosDataParser.METOS_URL_TEMPLATE, stationID));
BufferedReader in = new BufferedReader(
new InputStreamReader(metosURL.openStream()));
String inputLine;
Date testTimestamp = null;
Date timestamp = null;
Boolean shouldBe00Now = true;
String[] data00 = null;
String[] data30 = null;
while ((inputLine = in.readLine()) != null)
{
String[] data = inputLine.split(";");
// Skip empty lines
if(data.length <= 1)
{
continue;
}
// Check for valid start of line
try {
testTimestamp = dFormat.parse(data[0] + " " + data[1]);
} catch (ParseException ex) {
continue;
}
// Data comes in half-hour chunks (resolution = 30 minutes)
if(data[1].split(":")[1].equals("00") && shouldBe00Now)
{
data00 = data;
timestamp = testTimestamp;
shouldBe00Now = false;
continue; // So that we summarize only after :30 data has been set too
}
else if(data[1].split(":")[1].equals("30") && !shouldBe00Now)
{
data30 = data;
shouldBe00Now = true;
}
else
{
throw new ParseWeatherDataException("Doesn't make sense!");
}
for(int i=0;i<MetosDataParser.elementMeasurementTypes.length;i++)
{
Double aggregateValue = null;
Double value00 = Double.valueOf(data00[i+2].replaceAll(",","."));
Double value30 = Double.valueOf(data30[i+2].replaceAll(",","."));
if(MetosDataParser.elementMeasurementTypes[i][1].equals("AVG"))
{
aggregateValue = (value00 + value30) / 2;
}
else
{
aggregateValue = (value00 + value30);
}
WeatherObservation obs = new WeatherObservation();
obs.setTimeMeasured(timestamp);
obs.setLogIntervalId(WeatherObservation.LOG_INTERVAL_ID_1H);
obs.setElementMeasurementTypeId(MetosDataParser.elementMeasurementTypes[i][0]);
obs.setValue(aggregateValue);
retVal.add(obs);
}
}
in.close();
} catch (IOException ex) {
throw new ParseWeatherDataException(ex.getMessage());
}
return retVal;
}
}
/*
* Copyright (c) 2015 Bioforsk <http://www.bioforsk.no/>.
*
* This file is part of VIPSLogic.
* VIPSLogic is free software: you can redistribute it and/or modify
* it under the terms of the Bioforsk Open Source License as published by
* Bioforsk, 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
* Bioforsk Open Source License for more details.
*
* You should have received a copy of the Bioforsk Open Source License
* along with VIPSLogic. If not, see <http://www.bioforsk.no/licenses/>.
*
*/
package no.bioforsk.vips.util.weather;
/**
* @copyright 2015 <a href="http://www.bioforsk.no/">Bioforsk</a>
* @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
*/
public class ParseWeatherDataException extends Exception {
/**
* Creates a new instance of <code>ParseWeatherDataException</code> without detail message.
*/
public ParseWeatherDataException() {
}
/**
* Constructs an instance of <code>ParseWeatherDataException</code> with the specified detail message.
* @param msg the detail message.
*/
public ParseWeatherDataException(String msg) {
super(msg);
}
}
{
"_licenseNote": [
"Copyright (c) 2014 Bioforsk <http://www.bioforsk.no/>. ",
"",
"This file is part of VIPSLogic. ",
"VIPSLogic is free software: you can redistribute it and/or modify ",
"it under the terms of the Bioforsk Open Source License as published by ",
"Bioforsk, 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 ",
"Bioforsk Open Source License for more details. ",
"",
"You should have received a copy of the Bioforsk Open Source License ",
"along with VIPSLogic. If not, see <http://www.bioforsk.no/licenses/>. "
],
"_comment" : "Structure of the specific fields for PLASMOVITI",
"fields": [
]
}
\ No newline at end of file
......@@ -58,14 +58,23 @@ function renderModelSpecificFields()
*/
function renderModelSpecificFieldsCallback(modelId)
{
var fieldSet = document.getElementById("modelSpecificFields");
var formDefinition = formDefinitions[modelId];
// If there are no specific fields, erase what was there
if(formDefinition.fields.length === 0)
{
fieldSet.innerHTML = "";
fieldSet.style.display="none";
return;
}
var fieldsHTML = ["<legend>" + getI18nMsg("specificFieldsForX", [getI18nMsg(modelId)])+ "</legend>"];
for(var i in formDefinition.fields){
var fieldDefinition = formDefinition.fields[i];
fieldsHTML.push(createFieldHTML(modelId, fieldDefinition));
}
var fieldSet = document.getElementById("modelSpecificFields");
fieldSet.innerHTML = fieldsHTML.join("\n");
fieldSet.style.display="block";
......
/*
* Copyright (c) 2015 Bioforsk <http://www.bioforsk.no/>.
*
* This file is part of VIPSLogic.
* VIPSLogic is free software: you can redistribute it and/or modify
* it under the terms of the Bioforsk Open Source License as published by
* Bioforsk, 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
* Bioforsk Open Source License for more details.
*
* You should have received a copy of the Bioforsk Open Source License
* along with VIPSLogic. If not, see <http://www.bioforsk.no/licenses/>.
*
*/
package no.bioforsk.vips.util.weather;
import java.util.List;
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 MetosDataParserTest {
public MetosDataParserTest() {
}
@BeforeClass
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
/**
* Test of getWeatherObservations method, of class MetosDataParser.
* Could be time consuming, so we test only when needed
*/
//@Test
public void testGetWeatherObservations() throws Exception {
System.out.println("getWeatherObservations");
String stationID = "00002085";
MetosDataParser instance = new MetosDataParser();
//List<WeatherObservation> expResult = null;
Integer expResult = 0;
List<WeatherObservation> result = instance.getWeatherObservations(stationID);
assertNotNull(result);
assertNotSame(expResult, result.size());
System.out.println("Result sample: " + result.get(0).toString());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment