+++ /dev/null
-/**
- * Copyright (c) 2010-2021 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.synopanalyser.internal.discovery;
-
-import static org.openhab.binding.synopanalyzer.internal.SynopAnalyzerBindingConstants.THING_SYNOP;
-
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Collectors;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.synopanalyser.internal.synop.StationDB;
-import org.openhab.binding.synopanalyser.internal.synop.StationDB.Station;
-import org.openhab.binding.synopanalyzer.internal.config.SynopAnalyzerConfiguration;
-import org.openhab.core.config.discovery.AbstractDiscoveryService;
-import org.openhab.core.config.discovery.DiscoveryResultBuilder;
-import org.openhab.core.i18n.LocationProvider;
-import org.openhab.core.library.types.DecimalType;
-import org.openhab.core.library.types.PointType;
-import org.openhab.core.thing.ThingUID;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The {@link SynopAnalyzerDiscoveryService} creates things based on the configured location.
- *
- * @author Gaël L'hopital - Initial Contribution
- */
-@NonNullByDefault
-public class SynopAnalyzerDiscoveryService extends AbstractDiscoveryService {
- private static final int DISCOVER_TIMEOUT_SECONDS = 5;
-
- private final Logger logger = LoggerFactory.getLogger(SynopAnalyzerDiscoveryService.class);
- private final Map<Integer, Double> distances = new HashMap<>();
- private final LocationProvider locationProvider;
- private final StationDB stationDB;
-
- /**
- * Creates a SynopAnalyzerDiscoveryService with enabled autostart.
- *
- */
- public SynopAnalyzerDiscoveryService(StationDB stationDB, LocationProvider locationProvider) {
- super(Collections.singleton(THING_SYNOP), DISCOVER_TIMEOUT_SECONDS);
- this.locationProvider = locationProvider;
- this.stationDB = stationDB;
- }
-
- @Override
- public void startScan() {
- logger.debug("Starting Synop Analyzer discovery scan");
- PointType location = locationProvider.getLocation();
- if (location == null) {
- logger.debug("LocationProvider.getLocation() is not set -> Will not provide any discovery results");
- return;
- }
- createResults(location);
- }
-
- public void createResults(PointType serverLocation) {
- distances.clear();
-
- stationDB.stations.forEach(s -> {
- PointType stationLocation = new PointType(s.getLocation());
- DecimalType distance = serverLocation.distanceFrom(stationLocation);
- distances.put(s.idOmm, distance.doubleValue());
- });
-
- Map<Integer, Double> result = distances.entrySet().stream()
- .sorted(Map.Entry.comparingByValue(Comparator.naturalOrder())).collect(Collectors.toMap(
- Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));
-
- Integer nearestId = result.entrySet().iterator().next().getKey();
- Optional<Station> station = stationDB.stations.stream().filter(s -> s.idOmm == nearestId).findFirst();
- thingDiscovered(DiscoveryResultBuilder.create(new ThingUID(THING_SYNOP, nearestId.toString()))
- .withLabel(String.format("Synop : %s", station.get().usualName))
- .withProperty(SynopAnalyzerConfiguration.STATION_ID, nearestId)
- .withRepresentationProperty(SynopAnalyzerConfiguration.STATION_ID).build());
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2010-2021 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.synopanalyser.internal.synop;
-
-/**
- * The {@link WindDirections} enum possible overcast descriptions
- *
- * @author Gaël L'hopital - Initial contribution
- */
-public enum Overcast {
- UNDEFINED,
- CLEAR_SKY,
- CLOUDY,
- SKY_NOT_VISIBLE;
-
- /**
- * Returns the overcast level depending upon octa
- */
- public static Overcast fromOcta(int octa) {
- if (octa == 0) {
- return Overcast.CLEAR_SKY;
- } else if (octa > 0 && octa < 9) {
- return Overcast.CLOUDY;
- } else if (octa == 9) {
- return Overcast.SKY_NOT_VISIBLE;
- }
- return Overcast.UNDEFINED;
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2010-2021 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.synopanalyser.internal.synop;
-
-import java.util.List;
-
-import com.google.gson.annotations.SerializedName;
-
-/**
- * The {@link StationDB} creates is a DTO for stations.json database.
- *
- * @author Gaël L'hopital - Initial Contribution
- */
-public class StationDB {
- public class Station {
- public String country;
- public String pack;
- @SerializedName("id_omm")
- public int idOmm;
- @SerializedName("numer_sta")
- public long numerSta;
- @SerializedName("usual_name")
- public String usualName;
- public double latitude;
- public double longitude;
- public double elevation;
- @SerializedName("station_type")
- public int stationType;
-
- public String getLocation() {
- return Double.toString(latitude) + "," + Double.toString(longitude);
- }
- }
-
- public List<Station> stations;
-}
+++ /dev/null
-/**
- * Copyright (c) 2010-2021 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.synopanalyser.internal.synop;
-
-import java.util.List;
-
-import javax.measure.Unit;
-import javax.measure.quantity.Speed;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.library.unit.Units;
-
-/**
- * The {@link Synop} is the ancestor common class for analyzing
- * Synop messages
- *
- * @author Jonarzz - Initial contribution
- */
-@NonNullByDefault
-public abstract class Synop {
- protected static final int INITIAL_VALUE = -1000;
- protected static final char PLUS_SIGN_TEMPERATURE = '0';
- protected static final char MINUS_SIGN_TEMPERATURE = '1';
-
- /*
- * WS - WIND SPEED
- */
- protected static final int WS_WILDTYPE_IN_MPS = 0;
- protected static final int WS_ANEMOMETER_IN_MPS = 1;
-
- /*
- * HV - HORIZONTAL VISIBILITY [IN KILOMETERS]
- * VALUES FROM "00" TO "50" AND FROM "56" TO "99"
- * 00 MEANS HV = BELOW 0,1
- * DECIMAL SCOPE MEANS HV = XX / 10
- * UNIT SCOPE MEANS HV = XX - 50
- * 89 MEANS HV = OVER 70
- * 90-99 ROUGHLY NUMBERING :
- * 90 - < 0,05 km
- * 91 >= 0,05 < 0,2 km
- * 92 >= 0,2 < 0,5 km
- * 93 >= 0,5 < 1,0 km
- * 94 >= 1,0 < 2,0 km
- * 95 >= 2,0 < 4,0 km
- * 96 >= 4,0 < 10,0 km
- * 97 >= 10,0 < 20,0 km
- * 98 >= 20,0 < 50,0 km
- * 99 - > 50 km
- * HP - high precision
- */
- protected static final int HV_LESS_THAN_1_LIMIT = 10;
- protected static final int HV_LESS_THAN_10_LIMIT = 60;
- protected static final int HV_LESS_THAN_50_LIMIT = 84;
- protected static final int HV_LESS_THAN_1_HP_LIMIT = 93;
- protected static final int HV_LESS_THAN_10_HP_LIMIT = 96;
- protected static final int HV_LESS_THAN_50_HP_LIMIT = 98;
-
- public static enum HorizontalVisibility {
- UNDEFINED,
- LESS_THAN_1,
- LESS_THAN_10,
- LESS_THAN_50,
- MORE_THAN_50
- }
-
- private final int VALID_STRING_LENGTH = 5;
-
- protected final List<String> stringArray;
-
- private int year;
- private int month;
- private int day;
- private int hour;
- private int windIndicator;
-
- private HorizontalVisibility horizontalVisibility = HorizontalVisibility.UNDEFINED;
- private float temperature;
-
- private int octa;
- private int windDirection;
- private int windSpeed;
- private float pressure;
-
- protected int horizontalVisibilityInt = INITIAL_VALUE;
- protected @Nullable String temperatureString;
- protected @Nullable String windString;
- protected @Nullable String pressureString;
-
- public Synop(List<String> stringArray) {
- this.stringArray = stringArray;
-
- setDateHourAndWindIndicator();
- setHorizontalVisibility();
- setTemperature();
- setWindAndOvercast();
- setPressure();
- }
-
- private void setDateHourAndWindIndicator() {
- String dayHourAndWindIndicator = "";
-
- if (this instanceof SynopLand && stringArray.size() > 1) {
- dayHourAndWindIndicator = stringArray.get(1);
- } else if (stringArray.size() > 2) {
- dayHourAndWindIndicator = stringArray.get(2);
- }
-
- if (!isValidString(dayHourAndWindIndicator)) {
- return;
- }
-
- setHourOfObservation(dayHourAndWindIndicator);
- setWindIndicator(dayHourAndWindIndicator);
- }
-
- private void setHourOfObservation(String str) {
- try {
- hour = Integer.parseInt(str.substring(2, 4));
- } catch (NumberFormatException e) {
- hour = INITIAL_VALUE;
- }
- try {
- day = Integer.parseInt(str.substring(0, 2));
- } catch (NumberFormatException e) {
- day = INITIAL_VALUE;
- }
- }
-
- private void setWindIndicator(String str) {
- try {
- windIndicator = Character.getNumericValue(str.charAt(4));
- } catch (NumberFormatException e) {
- windIndicator = INITIAL_VALUE;
- }
- }
-
- private void setHorizontalVisibility() {
- setHorizontalVisibilityInt();
-
- if (horizontalVisibilityInt != INITIAL_VALUE) {
-
- if (horizontalVisibilityInt < HV_LESS_THAN_1_LIMIT || horizontalVisibilityInt < HV_LESS_THAN_1_HP_LIMIT) {
- horizontalVisibility = HorizontalVisibility.LESS_THAN_1;
- } else if (horizontalVisibilityInt < HV_LESS_THAN_10_LIMIT
- || horizontalVisibilityInt < HV_LESS_THAN_10_HP_LIMIT) {
- horizontalVisibility = HorizontalVisibility.LESS_THAN_10;
- } else if (horizontalVisibilityInt < HV_LESS_THAN_50_LIMIT
- || horizontalVisibilityInt < HV_LESS_THAN_50_HP_LIMIT) {
- horizontalVisibility = HorizontalVisibility.LESS_THAN_50;
- } else {
- horizontalVisibility = HorizontalVisibility.MORE_THAN_50;
- }
- } else {
- horizontalVisibility = HorizontalVisibility.UNDEFINED;
- }
- }
-
- protected abstract void setHorizontalVisibilityInt();
-
- private void setTemperature() {
- setTemperatureString();
- temperature = INITIAL_VALUE;
- String temperatureString = this.temperatureString;
- if (temperatureString != null) {
- char firstChar = temperatureString.charAt(0);
- try {
- float temp = Float.parseFloat(temperatureString.substring(1, 4)) / 10;
- temperature = firstChar == PLUS_SIGN_TEMPERATURE ? temp
- : firstChar == MINUS_SIGN_TEMPERATURE ? -temp : INITIAL_VALUE;
- } catch (NumberFormatException ignore) {
- }
- }
- }
-
- protected abstract void setTemperatureString();
-
- private void setWindAndOvercast() {
- setWindString();
- if (windString != null) {
- String gustyFlag = windString.substring(0, 2);
- if ("00".equals(gustyFlag)) {
- setWindSpeed(true);
- } else {
- setOcta();
- setWindDirection();
- setWindSpeed(false);
- }
- } else {
- windDirection = INITIAL_VALUE;
- windSpeed = INITIAL_VALUE;
- }
- }
-
- private void setOcta() {
- if (windString != null) {
- octa = Character.getNumericValue(windString.charAt(0));
- } else {
- octa = -1;
- }
- }
-
- private void setWindDirection() {
- if (windString != null) {
- String windDirectionString = windString.substring(1, 3);
-
- if (windDirectionString.equals("99") || windDirectionString.equals("||")) {
- windDirection = INITIAL_VALUE;
- } else {
- try {
- windDirection = Integer.parseInt(windDirectionString) * 10;
- } catch (NumberFormatException e) {
- windDirection = INITIAL_VALUE;
- }
- }
- }
- }
-
- private void setWindSpeed(boolean gustyWind) {
- String speedString = null;
- if (windString != null) {
- speedString = windString.substring(gustyWind ? 2 : 3, 5);
- try {
- windSpeed = Integer.parseInt(speedString);
- } catch (NumberFormatException e) {
- windSpeed = INITIAL_VALUE;
- }
- }
- }
-
- protected abstract void setWindString();
-
- private void setPressure() {
- setPressureString();
-
- if (pressureString != null) {
-
- String pressureTemp = pressureString.substring(1, 5);
-
- if (pressureTemp.charAt(0) == '0') {
- pressureTemp = '1' + pressureTemp;
- }
-
- try {
- pressure = (float) Integer.parseInt(pressureTemp) / 10;
- } catch (NumberFormatException e) {
- pressure = INITIAL_VALUE;
- }
- }
- }
-
- protected abstract void setPressureString();
-
- protected boolean isValidString(String str) {
- return (str.length() == VALID_STRING_LENGTH);
- }
-
- public int getYear() {
- return year;
- }
-
- public int getMonth() {
- return month;
- }
-
- public int getDay() {
- return day;
- }
-
- public int getHour() {
- return hour;
- }
-
- public int getWindIndicator() {
- return windIndicator;
- }
-
- public HorizontalVisibility getHorizontalVisibility() {
- return horizontalVisibility;
- }
-
- public float getTemperature() {
- return temperature;
- }
-
- public int getWindDirection() {
- return windDirection;
- }
-
- public int getWindSpeed() {
- return windSpeed;
- }
-
- public float getPressure() {
- return pressure;
- }
-
- public int getOcta() {
- return octa;
- }
-
- public Unit<Speed> getWindUnit() {
- return (getWindIndicator() == WS_WILDTYPE_IN_MPS || getWindIndicator() == WS_ANEMOMETER_IN_MPS)
- ? Units.METRE_PER_SECOND
- : Units.KNOT;
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2010-2021 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.synopanalyser.internal.synop;
-
-import java.util.List;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * The {@link SynopLand} is responsible for analyzing Land station
- * specifics Synop messages
- *
- * @author Jonarzz - Initial contribution
- */
-@NonNullByDefault
-public class SynopLand extends Synop {
- private int rainfall = INITIAL_VALUE;
-
- public SynopLand(List<String> stringArray) {
- super(stringArray);
-
- if (stringArray.size() >= 11) {
- String rainfallString = stringArray.get(10);
- if (isValidString(rainfallString) && rainfallString.charAt(0) == 6) {
- try {
- rainfall = Integer.parseInt(rainfallString.substring(1, 4));
- if (rainfall >= 990) {
- rainfall = 0;
- }
- } catch (NumberFormatException ignore) {
- }
-
- }
- }
- }
-
- @Override
- protected void setHorizontalVisibilityInt() {
- if (stringArray.size() >= 4) {
- String horizontalVisibility = stringArray.get(3);
- if (isValidString(horizontalVisibility)) {
- try {
- horizontalVisibilityInt = Integer.parseInt(horizontalVisibility.substring(3, 5));
- } catch (NumberFormatException ignore) {
- }
- }
- }
- }
-
- @Override
- protected void setTemperatureString() {
- if (stringArray.size() < 6 || !isValidString(stringArray.get(5))) {
- return;
- }
-
- if (stringArray.get(5).charAt(0) == '0') {
- if (stringArray.size() < 7 || !isValidString(stringArray.get(6))) {
- return;
- }
-
- temperatureString = stringArray.get(6).substring(1, 5);
- } else if (isValidString(stringArray.get(5))) {
- temperatureString = stringArray.get(5).substring(1, 5);
- }
- }
-
- @Override
- protected void setWindString() {
- if (stringArray.size() >= 5) {
- String windString = stringArray.get(4);
- if (isValidString(windString)) {
- this.windString = windString;
- }
- }
- }
-
- @Override
- protected void setPressureString() {
- if (stringArray.size() >= 8) {
- String pressureString = stringArray.get(7);
- if (isValidString(pressureString) && pressureString.charAt(0) == '3') {
- this.pressureString = pressureString;
- }
- }
- }
-
- public int getRainfall() {
- return rainfall;
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2010-2021 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.synopanalyser.internal.synop;
-
-import java.util.List;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * The {@link SynopMobile} is responsible for analyzing Mobile station
- * specifics Synop messages
- *
- * @author Jonarzz - Initial contribution
- */
-@NonNullByDefault
-public class SynopMobile extends Synop {
- private float latitude;
- private float longitude;
-
- private int verticalQuadrantMultiplier;
- private int horizontalQuadrantMultiplier;
-
- public SynopMobile(List<String> stringArray) {
- super(stringArray);
-
- setLatitude();
- setLongitudeAndQuadrant();
- }
-
- @Override
- protected void setHorizontalVisibilityInt() {
- String temp;
- if (stringArray.size() < 6 || !isValidString((temp = stringArray.get(5)))) {
- horizontalVisibilityInt = INITIAL_VALUE;
- return;
- }
-
- try {
- horizontalVisibilityInt = Integer.parseInt(temp.substring(3, 5));
- } catch (NumberFormatException e) {
- horizontalVisibilityInt = INITIAL_VALUE;
- }
- }
-
- @Override
- protected void setTemperatureString() {
- String temp;
- if (stringArray.size() < 8 || !isValidString((temp = stringArray.get(7)))) {
- return;
- }
-
- temperatureString = temp.substring(1, 5);
- }
-
- @Override
- protected void setWindString() {
- String temp;
- if (stringArray.size() < 7 || !isValidString((temp = stringArray.get(6)))) {
- return;
- }
-
- windString = temp;
- }
-
- @Override
- protected void setPressureString() {
- return;
- }
-
- private void setLatitude() {
- String temp;
- if (stringArray.size() < 4 || !isValidString((temp = stringArray.get(3)))) {
- return;
- }
-
- String latitudeString = temp.substring(2, 5);
- int tempInt = 0;
-
- try {
- tempInt = Integer.parseInt(latitudeString);
- } catch (NumberFormatException e) {
- latitude = INITIAL_VALUE;
- return;
- }
-
- latitude = (float) tempInt / 10;
- }
-
- private void setLongitudeAndQuadrant() {
- String temp;
- if (stringArray.size() < 5 || !isValidString((temp = stringArray.get(4)))) {
- return;
- }
-
- setQuadrantMultipliers(temp.charAt(0));
- setLongitude(temp.substring(1, 5));
- }
-
- private void setQuadrantMultipliers(char q) {
- switch (q) {
- case '1':
- verticalQuadrantMultiplier = 1;
- horizontalQuadrantMultiplier = 1;
- break;
- case '3':
- verticalQuadrantMultiplier = -1;
- horizontalQuadrantMultiplier = 1;
- break;
- case '5':
- verticalQuadrantMultiplier = -1;
- horizontalQuadrantMultiplier = -1;
- break;
- case '7':
- verticalQuadrantMultiplier = 1;
- horizontalQuadrantMultiplier = -1;
- break;
- default:
- verticalQuadrantMultiplier = 0;
- horizontalQuadrantMultiplier = 0;
- break;
- }
- }
-
- private void setLongitude(String str) {
- int tempInt = 0;
-
- try {
- tempInt = Integer.parseInt(str);
- } catch (NumberFormatException e) {
- longitude = INITIAL_VALUE;
- return;
- }
-
- longitude = (float) tempInt / 10;
- }
-
- public float getLatitude() {
- return latitude;
- }
-
- public float getLongitude() {
- return longitude;
- }
-
- public int getVerticalQuadrantMultiplier() {
- return verticalQuadrantMultiplier;
- }
-
- public int getHorizontalQuadrantMultiplier() {
- return horizontalQuadrantMultiplier;
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2010-2021 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.synopanalyser.internal.synop;
-
-import java.util.List;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * The {@link SynopMobile} is responsible for analyzing Mobile station
- * specifics Synop messages
- *
- * @author Jonarzz - Initial contribution
- */
-@NonNullByDefault
-public class SynopShip extends SynopMobile {
-
- public SynopShip(List<String> stringArray) {
- super(stringArray);
- }
-
- @Override
- protected void setPressureString() {
- String temp;
- if (stringArray.size() < 10 || !isValidString((temp = stringArray.get(9))) || temp.charAt(0) != '4'
- || temp.charAt(1) != '0' || temp.charAt(1) != '9') {
- return;
- }
-
- pressureString = temp;
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2010-2021 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.synopanalyser.internal.synop;
-
-/**
- * The {@link WindDirections} enum possible wind directions
- *
- * @author Gaël L'hopital - Initial contribution
- */
-public enum WindDirections {
- N,
- NNE,
- NE,
- ENE,
- E,
- ESE,
- SE,
- SSE,
- S,
- SSW,
- SW,
- WSW,
- W,
- WNW,
- NW,
- NNW;
-
- /**
- * Returns the wind direction based on degree.
- */
- public static WindDirections getWindDirection(int degree) {
- double step = 360.0 / WindDirections.values().length;
- double b = Math.floor((degree + (step / 2.0)) / step);
- return WindDirections.values()[(int) (b % WindDirections.values().length)];
- }
-}
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.synopanalyser.internal.discovery.SynopAnalyzerDiscoveryService;
-import org.openhab.binding.synopanalyser.internal.synop.StationDB;
+import org.openhab.binding.synopanalyzer.internal.discovery.SynopAnalyzerDiscoveryService;
import org.openhab.binding.synopanalyzer.internal.handler.SynopAnalyzerHandler;
+import org.openhab.binding.synopanalyzer.internal.synop.StationDB;
import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.i18n.LocationProvider;
import org.openhab.core.thing.Thing;
--- /dev/null
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.synopanalyzer.internal.discovery;
+
+import static org.openhab.binding.synopanalyzer.internal.SynopAnalyzerBindingConstants.THING_SYNOP;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.synopanalyzer.internal.config.SynopAnalyzerConfiguration;
+import org.openhab.binding.synopanalyzer.internal.synop.StationDB;
+import org.openhab.binding.synopanalyzer.internal.synop.StationDB.Station;
+import org.openhab.core.config.discovery.AbstractDiscoveryService;
+import org.openhab.core.config.discovery.DiscoveryResultBuilder;
+import org.openhab.core.i18n.LocationProvider;
+import org.openhab.core.library.types.DecimalType;
+import org.openhab.core.library.types.PointType;
+import org.openhab.core.thing.ThingUID;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@link SynopAnalyzerDiscoveryService} creates things based on the configured location.
+ *
+ * @author Gaël L'hopital - Initial Contribution
+ */
+@NonNullByDefault
+public class SynopAnalyzerDiscoveryService extends AbstractDiscoveryService {
+ private static final int DISCOVER_TIMEOUT_SECONDS = 5;
+
+ private final Logger logger = LoggerFactory.getLogger(SynopAnalyzerDiscoveryService.class);
+ private final Map<Integer, Double> distances = new HashMap<>();
+ private final LocationProvider locationProvider;
+ private final StationDB stationDB;
+
+ /**
+ * Creates a SynopAnalyzerDiscoveryService with enabled autostart.
+ *
+ */
+ public SynopAnalyzerDiscoveryService(StationDB stationDB, LocationProvider locationProvider) {
+ super(Collections.singleton(THING_SYNOP), DISCOVER_TIMEOUT_SECONDS);
+ this.locationProvider = locationProvider;
+ this.stationDB = stationDB;
+ }
+
+ @Override
+ public void startScan() {
+ logger.debug("Starting Synop Analyzer discovery scan");
+ PointType location = locationProvider.getLocation();
+ if (location == null) {
+ logger.debug("LocationProvider.getLocation() is not set -> Will not provide any discovery results");
+ return;
+ }
+ createResults(location);
+ }
+
+ public void createResults(PointType serverLocation) {
+ distances.clear();
+
+ stationDB.stations.forEach(s -> {
+ PointType stationLocation = new PointType(s.getLocation());
+ DecimalType distance = serverLocation.distanceFrom(stationLocation);
+ distances.put(s.idOmm, distance.doubleValue());
+ });
+
+ Map<Integer, Double> result = distances.entrySet().stream()
+ .sorted(Map.Entry.comparingByValue(Comparator.naturalOrder())).collect(Collectors.toMap(
+ Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));
+
+ Integer nearestId = result.entrySet().iterator().next().getKey();
+ Optional<Station> station = stationDB.stations.stream().filter(s -> s.idOmm == nearestId).findFirst();
+ thingDiscovered(DiscoveryResultBuilder.create(new ThingUID(THING_SYNOP, nearestId.toString()))
+ .withLabel(String.format("Synop : %s", station.get().usualName))
+ .withProperty(SynopAnalyzerConfiguration.STATION_ID, nearestId)
+ .withRepresentationProperty(SynopAnalyzerConfiguration.STATION_ID).build());
+ }
+}
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.synopanalyser.internal.synop.Overcast;
-import org.openhab.binding.synopanalyser.internal.synop.StationDB;
-import org.openhab.binding.synopanalyser.internal.synop.Synop;
-import org.openhab.binding.synopanalyser.internal.synop.SynopLand;
-import org.openhab.binding.synopanalyser.internal.synop.SynopMobile;
-import org.openhab.binding.synopanalyser.internal.synop.SynopShip;
-import org.openhab.binding.synopanalyser.internal.synop.WindDirections;
import org.openhab.binding.synopanalyzer.internal.config.SynopAnalyzerConfiguration;
+import org.openhab.binding.synopanalyzer.internal.synop.Overcast;
+import org.openhab.binding.synopanalyzer.internal.synop.StationDB;
+import org.openhab.binding.synopanalyzer.internal.synop.Synop;
+import org.openhab.binding.synopanalyzer.internal.synop.SynopLand;
+import org.openhab.binding.synopanalyzer.internal.synop.SynopMobile;
+import org.openhab.binding.synopanalyzer.internal.synop.SynopShip;
+import org.openhab.binding.synopanalyzer.internal.synop.WindDirections;
import org.openhab.core.i18n.LocationProvider;
import org.openhab.core.io.net.http.HttpUtil;
import org.openhab.core.library.types.DateTimeType;
--- /dev/null
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.synopanalyzer.internal.synop;
+
+/**
+ * The {@link WindDirections} enum possible overcast descriptions
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+public enum Overcast {
+ UNDEFINED,
+ CLEAR_SKY,
+ CLOUDY,
+ SKY_NOT_VISIBLE;
+
+ /**
+ * Returns the overcast level depending upon octa
+ */
+ public static Overcast fromOcta(int octa) {
+ if (octa == 0) {
+ return Overcast.CLEAR_SKY;
+ } else if (octa > 0 && octa < 9) {
+ return Overcast.CLOUDY;
+ } else if (octa == 9) {
+ return Overcast.SKY_NOT_VISIBLE;
+ }
+ return Overcast.UNDEFINED;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.synopanalyzer.internal.synop;
+
+import java.util.List;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * The {@link StationDB} creates is a DTO for stations.json database.
+ *
+ * @author Gaël L'hopital - Initial Contribution
+ */
+public class StationDB {
+ public class Station {
+ public String country;
+ public String pack;
+ @SerializedName("id_omm")
+ public int idOmm;
+ @SerializedName("numer_sta")
+ public long numerSta;
+ @SerializedName("usual_name")
+ public String usualName;
+ public double latitude;
+ public double longitude;
+ public double elevation;
+ @SerializedName("station_type")
+ public int stationType;
+
+ public String getLocation() {
+ return Double.toString(latitude) + "," + Double.toString(longitude);
+ }
+ }
+
+ public List<Station> stations;
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.synopanalyzer.internal.synop;
+
+import java.util.List;
+
+import javax.measure.Unit;
+import javax.measure.quantity.Speed;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.library.unit.Units;
+
+/**
+ * The {@link Synop} is the ancestor common class for analyzing
+ * Synop messages
+ *
+ * @author Jonarzz - Initial contribution
+ */
+@NonNullByDefault
+public abstract class Synop {
+ protected static final int INITIAL_VALUE = -1000;
+ protected static final char PLUS_SIGN_TEMPERATURE = '0';
+ protected static final char MINUS_SIGN_TEMPERATURE = '1';
+
+ /*
+ * WS - WIND SPEED
+ */
+ protected static final int WS_WILDTYPE_IN_MPS = 0;
+ protected static final int WS_ANEMOMETER_IN_MPS = 1;
+
+ /*
+ * HV - HORIZONTAL VISIBILITY [IN KILOMETERS]
+ * VALUES FROM "00" TO "50" AND FROM "56" TO "99"
+ * 00 MEANS HV = BELOW 0,1
+ * DECIMAL SCOPE MEANS HV = XX / 10
+ * UNIT SCOPE MEANS HV = XX - 50
+ * 89 MEANS HV = OVER 70
+ * 90-99 ROUGHLY NUMBERING :
+ * 90 - < 0,05 km
+ * 91 >= 0,05 < 0,2 km
+ * 92 >= 0,2 < 0,5 km
+ * 93 >= 0,5 < 1,0 km
+ * 94 >= 1,0 < 2,0 km
+ * 95 >= 2,0 < 4,0 km
+ * 96 >= 4,0 < 10,0 km
+ * 97 >= 10,0 < 20,0 km
+ * 98 >= 20,0 < 50,0 km
+ * 99 - > 50 km
+ * HP - high precision
+ */
+ protected static final int HV_LESS_THAN_1_LIMIT = 10;
+ protected static final int HV_LESS_THAN_10_LIMIT = 60;
+ protected static final int HV_LESS_THAN_50_LIMIT = 84;
+ protected static final int HV_LESS_THAN_1_HP_LIMIT = 93;
+ protected static final int HV_LESS_THAN_10_HP_LIMIT = 96;
+ protected static final int HV_LESS_THAN_50_HP_LIMIT = 98;
+
+ public static enum HorizontalVisibility {
+ UNDEFINED,
+ LESS_THAN_1,
+ LESS_THAN_10,
+ LESS_THAN_50,
+ MORE_THAN_50
+ }
+
+ private final int VALID_STRING_LENGTH = 5;
+
+ protected final List<String> stringArray;
+
+ private int year;
+ private int month;
+ private int day;
+ private int hour;
+ private int windIndicator;
+
+ private HorizontalVisibility horizontalVisibility = HorizontalVisibility.UNDEFINED;
+ private float temperature;
+
+ private int octa;
+ private int windDirection;
+ private int windSpeed;
+ private float pressure;
+
+ protected int horizontalVisibilityInt = INITIAL_VALUE;
+ protected @Nullable String temperatureString;
+ protected @Nullable String windString;
+ protected @Nullable String pressureString;
+
+ public Synop(List<String> stringArray) {
+ this.stringArray = stringArray;
+
+ setDateHourAndWindIndicator();
+ setHorizontalVisibility();
+ setTemperature();
+ setWindAndOvercast();
+ setPressure();
+ }
+
+ private void setDateHourAndWindIndicator() {
+ String dayHourAndWindIndicator = "";
+
+ if (this instanceof SynopLand && stringArray.size() > 1) {
+ dayHourAndWindIndicator = stringArray.get(1);
+ } else if (stringArray.size() > 2) {
+ dayHourAndWindIndicator = stringArray.get(2);
+ }
+
+ if (!isValidString(dayHourAndWindIndicator)) {
+ return;
+ }
+
+ setHourOfObservation(dayHourAndWindIndicator);
+ setWindIndicator(dayHourAndWindIndicator);
+ }
+
+ private void setHourOfObservation(String str) {
+ try {
+ hour = Integer.parseInt(str.substring(2, 4));
+ } catch (NumberFormatException e) {
+ hour = INITIAL_VALUE;
+ }
+ try {
+ day = Integer.parseInt(str.substring(0, 2));
+ } catch (NumberFormatException e) {
+ day = INITIAL_VALUE;
+ }
+ }
+
+ private void setWindIndicator(String str) {
+ try {
+ windIndicator = Character.getNumericValue(str.charAt(4));
+ } catch (NumberFormatException e) {
+ windIndicator = INITIAL_VALUE;
+ }
+ }
+
+ private void setHorizontalVisibility() {
+ setHorizontalVisibilityInt();
+
+ if (horizontalVisibilityInt != INITIAL_VALUE) {
+
+ if (horizontalVisibilityInt < HV_LESS_THAN_1_LIMIT || horizontalVisibilityInt < HV_LESS_THAN_1_HP_LIMIT) {
+ horizontalVisibility = HorizontalVisibility.LESS_THAN_1;
+ } else if (horizontalVisibilityInt < HV_LESS_THAN_10_LIMIT
+ || horizontalVisibilityInt < HV_LESS_THAN_10_HP_LIMIT) {
+ horizontalVisibility = HorizontalVisibility.LESS_THAN_10;
+ } else if (horizontalVisibilityInt < HV_LESS_THAN_50_LIMIT
+ || horizontalVisibilityInt < HV_LESS_THAN_50_HP_LIMIT) {
+ horizontalVisibility = HorizontalVisibility.LESS_THAN_50;
+ } else {
+ horizontalVisibility = HorizontalVisibility.MORE_THAN_50;
+ }
+ } else {
+ horizontalVisibility = HorizontalVisibility.UNDEFINED;
+ }
+ }
+
+ protected abstract void setHorizontalVisibilityInt();
+
+ private void setTemperature() {
+ setTemperatureString();
+ temperature = INITIAL_VALUE;
+ String temperatureString = this.temperatureString;
+ if (temperatureString != null) {
+ char firstChar = temperatureString.charAt(0);
+ try {
+ float temp = Float.parseFloat(temperatureString.substring(1, 4)) / 10;
+ temperature = firstChar == PLUS_SIGN_TEMPERATURE ? temp
+ : firstChar == MINUS_SIGN_TEMPERATURE ? -temp : INITIAL_VALUE;
+ } catch (NumberFormatException ignore) {
+ }
+ }
+ }
+
+ protected abstract void setTemperatureString();
+
+ private void setWindAndOvercast() {
+ setWindString();
+ if (windString != null) {
+ String gustyFlag = windString.substring(0, 2);
+ if ("00".equals(gustyFlag)) {
+ setWindSpeed(true);
+ } else {
+ setOcta();
+ setWindDirection();
+ setWindSpeed(false);
+ }
+ } else {
+ windDirection = INITIAL_VALUE;
+ windSpeed = INITIAL_VALUE;
+ }
+ }
+
+ private void setOcta() {
+ if (windString != null) {
+ octa = Character.getNumericValue(windString.charAt(0));
+ } else {
+ octa = -1;
+ }
+ }
+
+ private void setWindDirection() {
+ if (windString != null) {
+ String windDirectionString = windString.substring(1, 3);
+
+ if (windDirectionString.equals("99") || windDirectionString.equals("||")) {
+ windDirection = INITIAL_VALUE;
+ } else {
+ try {
+ windDirection = Integer.parseInt(windDirectionString) * 10;
+ } catch (NumberFormatException e) {
+ windDirection = INITIAL_VALUE;
+ }
+ }
+ }
+ }
+
+ private void setWindSpeed(boolean gustyWind) {
+ String speedString = null;
+ if (windString != null) {
+ speedString = windString.substring(gustyWind ? 2 : 3, 5);
+ try {
+ windSpeed = Integer.parseInt(speedString);
+ } catch (NumberFormatException e) {
+ windSpeed = INITIAL_VALUE;
+ }
+ }
+ }
+
+ protected abstract void setWindString();
+
+ private void setPressure() {
+ setPressureString();
+
+ if (pressureString != null) {
+
+ String pressureTemp = pressureString.substring(1, 5);
+
+ if (pressureTemp.charAt(0) == '0') {
+ pressureTemp = '1' + pressureTemp;
+ }
+
+ try {
+ pressure = (float) Integer.parseInt(pressureTemp) / 10;
+ } catch (NumberFormatException e) {
+ pressure = INITIAL_VALUE;
+ }
+ }
+ }
+
+ protected abstract void setPressureString();
+
+ protected boolean isValidString(String str) {
+ return (str.length() == VALID_STRING_LENGTH);
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public int getMonth() {
+ return month;
+ }
+
+ public int getDay() {
+ return day;
+ }
+
+ public int getHour() {
+ return hour;
+ }
+
+ public int getWindIndicator() {
+ return windIndicator;
+ }
+
+ public HorizontalVisibility getHorizontalVisibility() {
+ return horizontalVisibility;
+ }
+
+ public float getTemperature() {
+ return temperature;
+ }
+
+ public int getWindDirection() {
+ return windDirection;
+ }
+
+ public int getWindSpeed() {
+ return windSpeed;
+ }
+
+ public float getPressure() {
+ return pressure;
+ }
+
+ public int getOcta() {
+ return octa;
+ }
+
+ public Unit<Speed> getWindUnit() {
+ return (getWindIndicator() == WS_WILDTYPE_IN_MPS || getWindIndicator() == WS_ANEMOMETER_IN_MPS)
+ ? Units.METRE_PER_SECOND
+ : Units.KNOT;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.synopanalyzer.internal.synop;
+
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link SynopLand} is responsible for analyzing Land station
+ * specifics Synop messages
+ *
+ * @author Jonarzz - Initial contribution
+ */
+@NonNullByDefault
+public class SynopLand extends Synop {
+ private int rainfall = INITIAL_VALUE;
+
+ public SynopLand(List<String> stringArray) {
+ super(stringArray);
+
+ if (stringArray.size() >= 11) {
+ String rainfallString = stringArray.get(10);
+ if (isValidString(rainfallString) && rainfallString.charAt(0) == 6) {
+ try {
+ rainfall = Integer.parseInt(rainfallString.substring(1, 4));
+ if (rainfall >= 990) {
+ rainfall = 0;
+ }
+ } catch (NumberFormatException ignore) {
+ }
+
+ }
+ }
+ }
+
+ @Override
+ protected void setHorizontalVisibilityInt() {
+ if (stringArray.size() >= 4) {
+ String horizontalVisibility = stringArray.get(3);
+ if (isValidString(horizontalVisibility)) {
+ try {
+ horizontalVisibilityInt = Integer.parseInt(horizontalVisibility.substring(3, 5));
+ } catch (NumberFormatException ignore) {
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void setTemperatureString() {
+ if (stringArray.size() < 6 || !isValidString(stringArray.get(5))) {
+ return;
+ }
+
+ if (stringArray.get(5).charAt(0) == '0') {
+ if (stringArray.size() < 7 || !isValidString(stringArray.get(6))) {
+ return;
+ }
+
+ temperatureString = stringArray.get(6).substring(1, 5);
+ } else if (isValidString(stringArray.get(5))) {
+ temperatureString = stringArray.get(5).substring(1, 5);
+ }
+ }
+
+ @Override
+ protected void setWindString() {
+ if (stringArray.size() >= 5) {
+ String windString = stringArray.get(4);
+ if (isValidString(windString)) {
+ this.windString = windString;
+ }
+ }
+ }
+
+ @Override
+ protected void setPressureString() {
+ if (stringArray.size() >= 8) {
+ String pressureString = stringArray.get(7);
+ if (isValidString(pressureString) && pressureString.charAt(0) == '3') {
+ this.pressureString = pressureString;
+ }
+ }
+ }
+
+ public int getRainfall() {
+ return rainfall;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.synopanalyzer.internal.synop;
+
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link SynopMobile} is responsible for analyzing Mobile station
+ * specifics Synop messages
+ *
+ * @author Jonarzz - Initial contribution
+ */
+@NonNullByDefault
+public class SynopMobile extends Synop {
+ private float latitude;
+ private float longitude;
+
+ private int verticalQuadrantMultiplier;
+ private int horizontalQuadrantMultiplier;
+
+ public SynopMobile(List<String> stringArray) {
+ super(stringArray);
+
+ setLatitude();
+ setLongitudeAndQuadrant();
+ }
+
+ @Override
+ protected void setHorizontalVisibilityInt() {
+ String temp;
+ if (stringArray.size() < 6 || !isValidString((temp = stringArray.get(5)))) {
+ horizontalVisibilityInt = INITIAL_VALUE;
+ return;
+ }
+
+ try {
+ horizontalVisibilityInt = Integer.parseInt(temp.substring(3, 5));
+ } catch (NumberFormatException e) {
+ horizontalVisibilityInt = INITIAL_VALUE;
+ }
+ }
+
+ @Override
+ protected void setTemperatureString() {
+ String temp;
+ if (stringArray.size() < 8 || !isValidString((temp = stringArray.get(7)))) {
+ return;
+ }
+
+ temperatureString = temp.substring(1, 5);
+ }
+
+ @Override
+ protected void setWindString() {
+ String temp;
+ if (stringArray.size() < 7 || !isValidString((temp = stringArray.get(6)))) {
+ return;
+ }
+
+ windString = temp;
+ }
+
+ @Override
+ protected void setPressureString() {
+ return;
+ }
+
+ private void setLatitude() {
+ String temp;
+ if (stringArray.size() < 4 || !isValidString((temp = stringArray.get(3)))) {
+ return;
+ }
+
+ String latitudeString = temp.substring(2, 5);
+ int tempInt = 0;
+
+ try {
+ tempInt = Integer.parseInt(latitudeString);
+ } catch (NumberFormatException e) {
+ latitude = INITIAL_VALUE;
+ return;
+ }
+
+ latitude = (float) tempInt / 10;
+ }
+
+ private void setLongitudeAndQuadrant() {
+ String temp;
+ if (stringArray.size() < 5 || !isValidString((temp = stringArray.get(4)))) {
+ return;
+ }
+
+ setQuadrantMultipliers(temp.charAt(0));
+ setLongitude(temp.substring(1, 5));
+ }
+
+ private void setQuadrantMultipliers(char q) {
+ switch (q) {
+ case '1':
+ verticalQuadrantMultiplier = 1;
+ horizontalQuadrantMultiplier = 1;
+ break;
+ case '3':
+ verticalQuadrantMultiplier = -1;
+ horizontalQuadrantMultiplier = 1;
+ break;
+ case '5':
+ verticalQuadrantMultiplier = -1;
+ horizontalQuadrantMultiplier = -1;
+ break;
+ case '7':
+ verticalQuadrantMultiplier = 1;
+ horizontalQuadrantMultiplier = -1;
+ break;
+ default:
+ verticalQuadrantMultiplier = 0;
+ horizontalQuadrantMultiplier = 0;
+ break;
+ }
+ }
+
+ private void setLongitude(String str) {
+ int tempInt = 0;
+
+ try {
+ tempInt = Integer.parseInt(str);
+ } catch (NumberFormatException e) {
+ longitude = INITIAL_VALUE;
+ return;
+ }
+
+ longitude = (float) tempInt / 10;
+ }
+
+ public float getLatitude() {
+ return latitude;
+ }
+
+ public float getLongitude() {
+ return longitude;
+ }
+
+ public int getVerticalQuadrantMultiplier() {
+ return verticalQuadrantMultiplier;
+ }
+
+ public int getHorizontalQuadrantMultiplier() {
+ return horizontalQuadrantMultiplier;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.synopanalyzer.internal.synop;
+
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link SynopMobile} is responsible for analyzing Mobile station
+ * specifics Synop messages
+ *
+ * @author Jonarzz - Initial contribution
+ */
+@NonNullByDefault
+public class SynopShip extends SynopMobile {
+
+ public SynopShip(List<String> stringArray) {
+ super(stringArray);
+ }
+
+ @Override
+ protected void setPressureString() {
+ String temp;
+ if (stringArray.size() < 10 || !isValidString((temp = stringArray.get(9))) || temp.charAt(0) != '4'
+ || temp.charAt(1) != '0' || temp.charAt(1) != '9') {
+ return;
+ }
+
+ pressureString = temp;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.synopanalyzer.internal.synop;
+
+/**
+ * The {@link WindDirections} enum possible wind directions
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+public enum WindDirections {
+ N,
+ NNE,
+ NE,
+ ENE,
+ E,
+ ESE,
+ SE,
+ SSE,
+ S,
+ SSW,
+ SW,
+ WSW,
+ W,
+ WNW,
+ NW,
+ NNW;
+
+ /**
+ * Returns the wind direction based on degree.
+ */
+ public static WindDirections getWindDirection(int degree) {
+ double step = 360.0 / WindDirections.values().length;
+ double b = Math.floor((degree + (step / 2.0)) / step);
+ return WindDirections.values()[(int) (b % WindDirections.values().length)];
+ }
+}