diff --git a/src/main/java/no/nibio/vips/logic/service/WeatherProxyService.java b/src/main/java/no/nibio/vips/logic/service/WeatherProxyService.java index a42071b41fd418f952c5542ec9a57c2e28d91d9d..6bd8b9605e63ca59d979ebcc0044e9d226eda0d3 100755 --- a/src/main/java/no/nibio/vips/logic/service/WeatherProxyService.java +++ b/src/main/java/no/nibio/vips/logic/service/WeatherProxyService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 NIBIO <http://www.nibio.no/>. + * Copyright (c) 2019 NIBIO <http://www.nibio.no/>. * * This file is part of VIPSLogic. * VIPSLogic is free software: you can redistribute it and/or modify @@ -48,6 +48,7 @@ import no.nibio.vips.entity.WeatherObservation; import no.nibio.vips.logic.util.SystemTime; import no.nibio.vips.util.XDate; import no.nibio.vips.util.weather.ALabDataParser; +import no.nibio.vips.util.weather.CebaowangDataParser; import no.nibio.vips.util.weather.FruitWebDavisDataParser; import no.nibio.vips.util.weather.MetosAPIDataParser; import no.nibio.vips.util.weather.MetosRIMProDataParser; @@ -60,7 +61,7 @@ import no.nibio.vips.util.weather.metnothredds.TooMuchDataToAskForException; import org.jboss.resteasy.annotations.GZIP; /** - * @copyright 2016 <a href="http://www.nibio.no/">NIBIO</a> + * @copyright 2019 <a href="http://www.nibio.no/">NIBIO</a> * @author Tor-Einar Skog <tor-einar.skog@nibio.no> */ @Path("rest/weather/proxy") @@ -191,6 +192,50 @@ public class WeatherProxyService { return Response.ok().entity(observations).build(); } + /** + * Fetches data from the Chinese Cebaowang weather data service + * Used in the SINOGRAIN project(s) + * + * @param stationId + * @param timeZonePOST + * @param timeZoneGET + * @param startDatePOST + * @param startDateGET + * @param endDatePOST + * @param endDateGET + * @return + */ + @GET + @POST + @Path("cebaowang/{stationId}") + @GZIP + @Produces("application/json;charset=UTF-8") + public Response getCebaowangWeatherData( + @PathParam("stationId") String stationId, + @FormParam("timeZone") String timeZonePOST, + @QueryParam("timeZone") String timeZoneGET, + @FormParam("startDate") String startDatePOST, + @QueryParam("startDate") String startDateGET, + @FormParam("endDate") String endDatePOST, + @QueryParam("endDate") String endDateGET + ) + { + List<WeatherObservation> weatherObservations; + TimeZone timeZone = TimeZone.getTimeZone(timeZonePOST != null ? timeZonePOST : timeZoneGET); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); + format.setTimeZone(timeZone); + try + { + Date startDate = format.parse(startDatePOST != null ? startDatePOST : startDateGET); + Date endDate = format.parse(endDatePOST != null ? endDatePOST : endDateGET); + weatherObservations = new CebaowangDataParser().getWeatherObservations(stationId, timeZone, startDate, endDate); + } + catch(ParseException | ParseWeatherDataException ex) + { + return Response.serverError().entity(ex).build(); + } + return Response.ok().entity(weatherObservations).build(); + } @GET @POST diff --git a/src/main/java/no/nibio/vips/util/weather/CebaowangDataParser.java b/src/main/java/no/nibio/vips/util/weather/CebaowangDataParser.java new file mode 100644 index 0000000000000000000000000000000000000000..9b5fcdab73be658358d8b37a3885e70175784d62 --- /dev/null +++ b/src/main/java/no/nibio/vips/util/weather/CebaowangDataParser.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2019 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.nibio.vips.util.weather; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ibm.icu.text.MessageFormat; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.AbstractMap.SimpleEntry; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import no.nibio.vips.entity.WeatherObservation; +import no.nibio.vips.util.WeatherElements; + +/** + * Parses data from the Chinese weather service http://www.cebaowang.com:8089, used in the + * SINOGRAIN2 project + * + * @copyright 2019 <a href="http://www.nibio.no/">NIBIO</a> + * @author Tor-Einar Skog <tor-einar.skog@nibio.no> + */ +public class CebaowangDataParser { + public final static String CEBAOWANG_URL_PATH = "http://www.cebaowang.com:8089/external/data/upload"; + public final static String CEBAOWANG_URL_QUERY_TEMPLATE = "?startDate={0}&endDate={1}&{2}"; + private Map<String, String> parameters = Collections.unmodifiableMap((Map<String,String>) Stream.of + ( + new SimpleEntry<>("kongQiWenDu", WeatherElements.TEMPERATURE_MEAN), + new SimpleEntry<>("xiangDuiShiDu", WeatherElements.RELATIVE_HUMIDITY_MEAN), + new SimpleEntry<>("luDianWenDu",WeatherElements.DEW_POINT_TEMPERATURE), + //new SimpleEntry<>("tianJiangYuLiang", null), // Daily rainfall + new SimpleEntry<>("xiaoShiJiangYuLiang", WeatherElements.PRECIPITATION), + //new SimpleEntry<>("dianChiDianYa", null), // Voltage + new SimpleEntry<>("shiRunShiJian", WeatherElements.LEAF_WETNESS_DURATION), + //new SimpleEntry<>("riZhaoShiShu", null), // Sunshine hours the current day + new SimpleEntry<>("fiveTuRangHanShuiLiang", WeatherElements.SOIL_WATER_CONTENT_5CM), + new SimpleEntry<>("tenTuRangHanShuiLiang", WeatherElements.SOIL_WATER_CONTENT_10CM), + new SimpleEntry<>("twentyFiveTuRangHanShuiLiang", WeatherElements.SOIL_WATER_CONTENT_25CM), + new SimpleEntry<>("fiftyTuRangHanShuiLiang", WeatherElements.SOIL_WATER_CONTENT_50CM), + new SimpleEntry<>("fiveTuRangWenDu", WeatherElements.SOIL_TEMPERATURE_5CM_MEAN), + new SimpleEntry<>("tenTuRangWenDu", WeatherElements.SOIL_TEMPERATURE_10CM_MEAN), + new SimpleEntry<>("twentyFiveTuRangWenDu", WeatherElements.SOIL_TEMPERATURE_25CM_MEAN), + new SimpleEntry<>("fiftyTuRangWenDu", WeatherElements.SOIL_TEMPERATURE_50CM_MEAN), + new SimpleEntry<>("tuRangDaoDianLv", WeatherElements.SOIL_CONDUCTIVITY_5CM) + ) + .collect(Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue())) + ); + + private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + public List<WeatherObservation> getWeatherObservations(String stationID, TimeZone timeZone, Date startDate, Date endDate) throws ParseWeatherDataException + { + format.setTimeZone(timeZone); + List<WeatherObservation> retVal = null; + try + { + URL cebaowangURL = new URL(CEBAOWANG_URL_PATH + MessageFormat.format( + CEBAOWANG_URL_QUERY_TEMPLATE, + URLEncoder.encode(format.format(startDate),"UTF-8"), + URLEncoder.encode(format.format(endDate),"UTF-8"), + stationID + ) + ); + //System.out.println(cebaowangURL); + BufferedReader in = new BufferedReader( + new InputStreamReader(cebaowangURL.openStream()) + ); + String inputLine; + Date testTimestamp; + String all = new String(); + // Reading data into String of JSON data + while ((inputLine = in.readLine()) != null) + { + all += inputLine; + } + // Get objects from JSON parser method + retVal = getParsedObservations(all, timeZone); + } + catch(ParseException | IOException ex) + {ex.printStackTrace(); + throw new ParseWeatherDataException(ex.getMessage()); + } + + return retVal; + } + + public List<WeatherObservation> getParsedObservations(String jsonTxt, TimeZone timeZone) throws IOException, ParseException + { + ObjectMapper oMapper = new ObjectMapper(); + JsonNode jNode = oMapper.readTree(jsonTxt); + List<WeatherObservation> retVal = new ArrayList<>(); + JsonNode data = jNode.get("data"); + + for(JsonNode dataForAGivenTime:data) + { + Date timeMeasured = this.format.parse(dataForAGivenTime.get("collectTime").asText()); + //System.out.println(timeMeasured + "=" + dataForAGivenTime.get("collectTime").asText()); + this.parameters.keySet().forEach(paramName->{ + WeatherObservation obs = new WeatherObservation(); + obs.setTimeMeasured(timeMeasured); + obs.setElementMeasurementTypeId(this.parameters.get(paramName)); + obs.setLogIntervalId(WeatherObservation.LOG_INTERVAL_ID_1H); // TODO: Check this!! Is every 2nd hour as of now + obs.setValue(dataForAGivenTime.get(paramName).asDouble()); + retVal.add(obs); + }); + } + + return retVal; + } +} diff --git a/src/test/java/no/nibio/vips/util/weather/CebaowangDataParserTest.java b/src/test/java/no/nibio/vips/util/weather/CebaowangDataParserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..443e3e84dcb4e262e0ea09bed8ff82f58a54208d --- /dev/null +++ b/src/test/java/no/nibio/vips/util/weather/CebaowangDataParserTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2019 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.nibio.vips.util.weather; + +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; +import no.nibio.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 CebaowangDataParserTest { + + public CebaowangDataParserTest() { + } + + @BeforeClass + public static void setUpClass() { + } + + @AfterClass + public static void tearDownClass() { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + /** + * Test of getWeatherObservations method, of class CebaowangDataParser. + */ + @Test + public void testGetWeatherObservations() throws Exception { + System.out.println("getWeatherObservations"); + String stationID = "token=0819208daf3684b6e1b2f7d9b0e1bc64&deviceId=YBQ0000053"; + TimeZone timeZone = TimeZone.getTimeZone("Asia/Shanghai"); + Calendar cal = Calendar.getInstance(timeZone); + cal.set(2019, Calendar.JANUARY, 10, 0,0); + Date startDate = cal.getTime(); + cal.add(Calendar.DATE, 20); + Date endDate = cal.getTime(); + CebaowangDataParser instance = new CebaowangDataParser(); + List<WeatherObservation> expResult = null; + List<WeatherObservation> result = instance.getWeatherObservations(stationID, timeZone, startDate, endDate); + //assertEquals(expResult, result); + assertNotNull(result); + result.forEach(obs->System.out.println(obs)); + + } + +}