* Some stations does not report octa dimension, thus leading the binding to incorrect values.
Enhanced discovery process
Code enhancements
SAT corrections
Enhanced Exception catching.
Signed-off-by: clinique <gael@lhopital.org>
## Discovery
-If a system location is set, the nearest availabble Synop station be automatically discovered for this location.
+If a system location is set, the nearest available Synop station be automatically discovered for this location.
+The search radius will expand at each successive scan.
+
## Thing Configuration
| Channel Type ID | Item Type | Description |
|-----------------------|--------------------|--------------------------------------------|
-| temperature | Number:Temperature | Current temperature |
+| temperature | Number:Temperature | Current outdoor temperature |
| pressure | Number:Pressure | Current pressure |
| wind-speed | Number:Speed | Current wind speed |
| wind-speed-beaufort | Number | Wind speed according to Beaufort scale |
import org.openhab.core.thing.ThingTypeUID;
/**
- * The {@link SynopAnalyzerBinding} class defines common constants, which are
- * used across the whole binding.
+ * The {@link SynopAnalyzerBinding} class defines common constants used across the whole binding.
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public class SynopAnalyzerBindingConstants {
- public static final String BINDING_ID = "synopanalyzer";
+ private static final String BINDING_ID = "synopanalyzer";
// List of all Thing Type UIDs
public static final ThingTypeUID THING_SYNOP = new ThingTypeUID(BINDING_ID, "synopanalyzer");
import static org.openhab.binding.synopanalyzer.internal.SynopAnalyzerBindingConstants.THING_SYNOP;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.charset.StandardCharsets;
-import java.util.Hashtable;
+import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-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.binding.synopanalyzer.internal.stationdb.Station;
+import org.openhab.binding.synopanalyzer.internal.stationdb.StationDbService;
import org.openhab.core.i18n.LocationProvider;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.gson.Gson;
/**
- * The {@link SynopAnalyzerHandlerFactory} is responsible for creating things and thing
- * handlers.
+ * The {@link SynopAnalyzerHandlerFactory} is responsible for creating things and thing handlers.
*
* @author Gaël L'hopital - Initial contribution
*/
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.synopanalyzer")
@NonNullByDefault
public class SynopAnalyzerHandlerFactory extends BaseThingHandlerFactory {
- private final Logger logger = LoggerFactory.getLogger(SynopAnalyzerHandlerFactory.class);
private final LocationProvider locationProvider;
- private final Gson gson = new Gson();
- private @Nullable StationDB stationDB;
- private @Nullable ServiceRegistration<?> serviceReg;
+ private final List<Station> stationDB;
@Activate
- public SynopAnalyzerHandlerFactory(@Reference LocationProvider locationProvider) {
+ public SynopAnalyzerHandlerFactory(@Reference StationDbService stationDBService,
+ @Reference LocationProvider locationProvider) {
this.locationProvider = locationProvider;
+ this.stationDB = stationDBService.getStations();
}
@Override
return supportsThingType(thing.getThingTypeUID()) ? new SynopAnalyzerHandler(thing, locationProvider, stationDB)
: null;
}
-
- @Override
- protected void activate(ComponentContext componentContext) {
- super.activate(componentContext);
-
- try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("/db/stations.json");
- Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8);) {
-
- StationDB stations = gson.fromJson(reader, StationDB.class);
- registerDiscoveryService(stations);
- this.stationDB = stations;
- logger.debug("Discovery service for Synop Stations registered.");
- } catch (IOException e) {
- logger.warn("Unable to read synop stations database");
- }
- }
-
- @Override
- protected void deactivate(ComponentContext componentContext) {
- unregisterDiscoveryService();
- super.deactivate(componentContext);
- }
-
- private void registerDiscoveryService(StationDB stations) {
- SynopAnalyzerDiscoveryService discoveryService = new SynopAnalyzerDiscoveryService(stations, locationProvider);
-
- serviceReg = bundleContext.registerService(DiscoveryService.class.getName(), discoveryService,
- new Hashtable<>());
- }
-
- private void unregisterDiscoveryService() {
- if (serviceReg != null) {
- serviceReg.unregister();
- serviceReg = null;
- }
- }
}
package org.openhab.binding.synopanalyzer.internal.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.synopanalyzer.internal.handler.SynopAnalyzerHandler;
/**
- * The {@link SynopAnalyzerConfiguration} is responsible for holding configuration
- * informations needed for {@link SynopAnalyzerHandler}
+ * The {@link SynopAnalyzerConfiguration} holds configuration informations needed for the Synop thing
*
* @author Gaël L'hopital - Initial contribution
*/
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.Iterator;
+import java.util.List;
import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Collectors;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
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.binding.synopanalyzer.internal.stationdb.Station;
+import org.openhab.binding.synopanalyzer.internal.stationdb.StationDbService;
import org.openhab.core.config.discovery.AbstractDiscoveryService;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
+import org.openhab.core.config.discovery.DiscoveryService;
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.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * The {@link SynopAnalyzerDiscoveryService} creates things based on the configured location.
+ * The {@link SynopAnalyzerDiscoveryService} discovers synop stations based on the configured location.
*
* @author Gaël L'hopital - Initial Contribution
*/
+@Component(service = DiscoveryService.class)
@NonNullByDefault
public class SynopAnalyzerDiscoveryService extends AbstractDiscoveryService {
- private static final int DISCOVER_TIMEOUT_SECONDS = 5;
+ private static final int DISCOVER_TIMEOUT_SECONDS = 2;
private final Logger logger = LoggerFactory.getLogger(SynopAnalyzerDiscoveryService.class);
- private final Map<Integer, Double> distances = new HashMap<>();
private final LocationProvider locationProvider;
- private final StationDB stationDB;
+ private final List<Station> stations;
+ private double radius = 0;
- /**
- * Creates a SynopAnalyzerDiscoveryService with enabled autostart.
- *
- */
- public SynopAnalyzerDiscoveryService(StationDB stationDB, LocationProvider locationProvider) {
- super(Collections.singleton(THING_SYNOP), DISCOVER_TIMEOUT_SECONDS);
+ @Activate
+ public SynopAnalyzerDiscoveryService(@Reference StationDbService dBService,
+ @Reference LocationProvider locationProvider) {
+ super(Set.of(THING_SYNOP), DISCOVER_TIMEOUT_SECONDS);
this.locationProvider = locationProvider;
- this.stationDB = stationDB;
+ this.stations = dBService.getStations();
}
@Override
}
public void createResults(PointType serverLocation) {
- distances.clear();
+ Map<Double, Station> distances = new TreeMap<>();
- stationDB.stations.forEach(s -> {
- PointType stationLocation = new PointType(s.getLocation());
- DecimalType distance = serverLocation.distanceFrom(stationLocation);
- distances.put(s.idOmm, distance.doubleValue());
+ stations.forEach(station -> {
+ PointType stationLocation = new PointType(station.getLocation());
+ double distance = serverLocation.distanceFrom(stationLocation).doubleValue();
+ if (distance > radius) {
+ distances.put(distance, station);
+ }
});
- 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));
+ Iterator<Entry<Double, Station>> stationIterator = distances.entrySet().iterator();
+ if (stationIterator.hasNext()) {
+ Entry<Double, Station> nearest = stationIterator.next();
+ Station station = nearest.getValue();
+ radius = nearest.getKey();
- 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());
+ thingDiscovered(DiscoveryResultBuilder.create(new ThingUID(THING_SYNOP, Integer.toString(station.idOmm)))
+ .withLabel(String.format("Synop : %s", station.usualName))
+ .withProperty(SynopAnalyzerConfiguration.STATION_ID, station.idOmm)
+ .withRepresentationProperty(SynopAnalyzerConfiguration.STATION_ID).build());
+ } else {
+ logger.info("No Synop station available at a radius higher than {} m - resetting to 0 m", radius);
+ radius = 0;
+ }
}
}
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.synopanalyzer.internal.config.SynopAnalyzerConfiguration;
+import org.openhab.binding.synopanalyzer.internal.stationdb.Station;
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.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
+import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
private static final double OCTA_MAX = 8.0;
private final Logger logger = LoggerFactory.getLogger(SynopAnalyzerHandler.class);
+ private final LocationProvider locationProvider;
+ private final List<Station> stations;
- private @Nullable ScheduledFuture<?> executionJob;
+ private Optional<ScheduledFuture<?>> refreshJob = Optional.empty();
private @NonNullByDefault({}) String formattedStationId;
- private final LocationProvider locationProvider;
- private final @Nullable StationDB stationDB;
- public SynopAnalyzerHandler(Thing thing, LocationProvider locationProvider, @Nullable StationDB stationDB) {
+ public SynopAnalyzerHandler(Thing thing, LocationProvider locationProvider, List<Station> stations) {
super(thing);
this.locationProvider = locationProvider;
- this.stationDB = stationDB;
+ this.stations = stations;
}
@Override
logger.info("Scheduling Synop update thread to run every {} minute for Station '{}'",
configuration.refreshInterval, formattedStationId);
- StationDB stations = stationDB;
- if (thing.getProperties().isEmpty() && stations != null) {
- discoverAttributes(stations, configuration.stationId);
+ if (thing.getProperties().isEmpty()) {
+ discoverAttributes(configuration.stationId, locationProvider.getLocation());
}
updateStatus(ThingStatus.UNKNOWN);
- executionJob = scheduler.scheduleWithFixedDelay(this::updateSynopChannels, 0, configuration.refreshInterval,
- TimeUnit.MINUTES);
+ refreshJob = Optional.of(scheduler.scheduleWithFixedDelay(this::updateChannels, 0,
+ configuration.refreshInterval, TimeUnit.MINUTES));
}
- protected void discoverAttributes(StationDB stations, int stationId) {
- stations.stations.stream().filter(s -> stationId == s.idOmm).findFirst().ifPresent(s -> {
- Map<String, String> properties = new HashMap<>();
- properties.put("Usual name", s.usualName);
- properties.put("Location", s.getLocation());
+ private void discoverAttributes(int stationId, @Nullable PointType serverLocation) {
+ stations.stream().filter(s -> stationId == s.idOmm).findFirst().ifPresent(station -> {
+ Map<String, String> properties = new HashMap<>(
+ Map.of("Usual name", station.usualName, "Location", station.getLocation()));
- PointType stationLocation = new PointType(s.getLocation());
- PointType serverLocation = locationProvider.getLocation();
if (serverLocation != null) {
+ PointType stationLocation = new PointType(station.getLocation());
DecimalType distance = serverLocation.distanceFrom(stationLocation);
properties.put("Distance", new QuantityType<>(distance, SIUnits.METRE).toString());
return Optional.empty();
}
- private void updateSynopChannels() {
+ private void updateChannels() {
logger.debug("Updating device channels");
- Optional<Synop> synop = getLastAvailableSynop();
- updateStatus(synop.isPresent() ? ThingStatus.ONLINE : ThingStatus.OFFLINE);
- synop.ifPresent(theSynop -> {
+ getLastAvailableSynop().ifPresentOrElse(synop -> {
+ updateStatus(ThingStatus.ONLINE);
getThing().getChannels().forEach(channel -> {
String channelId = channel.getUID().getId();
if (isLinked(channelId)) {
- updateState(channelId, getChannelState(channelId, theSynop));
+ updateState(channelId, getChannelState(channelId, synop));
}
});
- });
+ }, () -> updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "No Synop message available"));
}
private State getChannelState(String channelId, Synop synop) {
+ int octa = synop.getOcta();
switch (channelId) {
case HORIZONTAL_VISIBILITY:
return new StringType(synop.getHorizontalVisibility().name());
case OCTA:
- return new DecimalType(Math.max(0, synop.getOcta()));
+ return octa >= 0 ? new DecimalType(octa) : UnDefType.NULL;
case ATTENUATION_FACTOR:
- double kc = Math.max(0, Math.min(synop.getOcta(), OCTA_MAX)) / OCTA_MAX;
- kc = 1 - 0.75 * Math.pow(kc, KASTEN_POWER);
- return new DecimalType(kc);
+ if (octa >= 0) {
+ double kc = Math.max(0, Math.min(octa, OCTA_MAX)) / OCTA_MAX;
+ kc = 1 - 0.75 * Math.pow(kc, KASTEN_POWER);
+ return new DecimalType(kc);
+ }
+ return UnDefType.NULL;
case OVERCAST:
- int octa = synop.getOcta();
Overcast overcast = Overcast.fromOcta(octa);
return overcast == Overcast.UNDEFINED ? UnDefType.NULL : new StringType(overcast.name());
case PRESSURE:
return getWindStrength(synop);
case WIND_SPEED_BEAUFORT:
QuantityType<Speed> wsKpH = getWindStrength(synop).toUnit(SIUnits.KILOMETRE_PER_HOUR);
- return (wsKpH != null) ? new DecimalType(Math.round(Math.pow(wsKpH.floatValue() / 3.01, 0.666666666)))
+ return wsKpH != null ? new DecimalType(Math.round(Math.pow(wsKpH.floatValue() / 3.01, 0.666666666)))
: UnDefType.NULL;
case TIME_UTC:
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
int year = synop.getYear() == 0 ? now.getYear() : synop.getYear();
int month = synop.getMonth() == 0 ? now.getMonth().getValue() : synop.getMonth();
- ZonedDateTime zdt = ZonedDateTime.of(year, month, synop.getDay(), synop.getHour(), 0, 0, 0,
- ZoneOffset.UTC);
- return new DateTimeType(zdt);
+ return new DateTimeType(
+ ZonedDateTime.of(year, month, synop.getDay(), synop.getHour(), 0, 0, 0, ZoneOffset.UTC));
default:
logger.error("Unsupported channel Id '{}'", channelId);
return UnDefType.UNDEF;
@Override
public void dispose() {
- ScheduledFuture<?> job = this.executionJob;
- if (job != null && !job.isCancelled()) {
- job.cancel(true);
- }
- executionJob = null;
+ refreshJob.ifPresent(job -> job.cancel(true));
+ refreshJob = Optional.empty();
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (command == RefreshType.REFRESH) {
- updateSynopChannels();
+ updateChannels();
}
}
}
--- /dev/null
+/**
+ * Copyright (c) 2010-2022 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.stationdb;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link Station} is a DTO for stations.json database.
+ *
+ * @author Gaël L'hopital - Initial Contribution
+ */
+@NonNullByDefault
+public class Station {
+ public int idOmm;
+ public String usualName = "";
+ private double latitude;
+ private double longitude;
+
+ public String getLocation() {
+ return Double.toString(latitude) + "," + Double.toString(longitude);
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2022 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.stationdb;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonIOException;
+import com.google.gson.JsonSyntaxException;
+
+/**
+ * The {@link StationDbService} makes available a list of known Synop stations.
+ *
+ * @author Gaël L'hopital - Initial Contribution
+ */
+
+@Component(service = StationDbService.class)
+@NonNullByDefault
+public class StationDbService {
+ private final Logger logger = LoggerFactory.getLogger(StationDbService.class);
+
+ private List<Station> stations;
+
+ @Activate
+ public StationDbService() {
+ try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("/db/stations.json");
+ Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8);) {
+ Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
+ stations = Arrays.asList(gson.fromJson(reader, Station[].class));
+ } catch (IOException | JsonSyntaxException | JsonIOException e) {
+ logger.warn("Unable to load station list : {}", e.getMessage());
+ stations = List.of();
+ }
+ }
+
+ public List<Station> getStations() {
+ return stations;
+ }
+}
*/
package org.openhab.binding.synopanalyzer.internal.synop;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
/**
* The {@link WindDirections} enum possible overcast descriptions
*
* @author Gaël L'hopital - Initial contribution
*/
+@NonNullByDefault
public enum Overcast {
UNDEFINED,
CLEAR_SKY,
+++ /dev/null
-/**
- * Copyright (c) 2010-2022 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;
-}
@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';
+ private static final char PLUS_SIGN_TEMPERATURE = '0';
+ private 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;
+ private static final int WS_WILDTYPE_IN_MPS = 0;
+ private static final int WS_ANEMOMETER_IN_MPS = 1;
/*
* HV - HORIZONTAL VISIBILITY [IN KILOMETERS]
* 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;
+ private static final int HV_LESS_THAN_1_LIMIT = 10;
+ private static final int HV_LESS_THAN_10_LIMIT = 60;
+ private static final int HV_LESS_THAN_50_LIMIT = 84;
+ private static final int HV_LESS_THAN_1_HP_LIMIT = 93;
+ private static final int HV_LESS_THAN_10_HP_LIMIT = 96;
+ private static final int HV_LESS_THAN_50_HP_LIMIT = 98;
public static enum HorizontalVisibility {
UNDEFINED,
MORE_THAN_50
}
- private final int VALID_STRING_LENGTH = 5;
+ private static final int VALID_STRING_LENGTH = 5;
protected final List<String> stringArray;
setPressure();
}
+ protected abstract void setTemperatureString();
+
+ protected abstract void setHorizontalVisibilityInt();
+
+ protected abstract void setPressureString();
+
+ protected abstract void setWindString();
+
private void setDateHourAndWindIndicator() {
String dayHourAndWindIndicator = "";
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
}
}
- protected abstract void setHorizontalVisibilityInt();
-
private void setTemperature() {
setTemperatureString();
temperature = INITIAL_VALUE;
}
}
- protected abstract void setTemperatureString();
-
private void setWindAndOvercast() {
setWindString();
- if (windString != null) {
- String gustyFlag = windString.substring(0, 2);
+ String localWind = windString;
+ if (localWind != null) {
+ String gustyFlag = localWind.substring(0, 2);
if ("00".equals(gustyFlag)) {
setWindSpeed(true);
} else {
}
private void setOcta() {
- if (windString != null) {
- octa = Character.getNumericValue(windString.charAt(0));
+ String localWind = windString;
+ if (localWind != null) {
+ octa = Character.getNumericValue(localWind.charAt(0));
} else {
octa = -1;
}
}
private void setWindDirection() {
- if (windString != null) {
- String windDirectionString = windString.substring(1, 3);
+ String localWind = windString;
+ if (localWind != null) {
+ String windDirectionString = localWind.substring(1, 3);
- if (windDirectionString.equals("99") || windDirectionString.equals("||")) {
+ if ("99".equals(windDirectionString) || "||".equals(windDirectionString)) {
windDirection = INITIAL_VALUE;
} else {
try {
private void setWindSpeed(boolean gustyWind) {
String speedString = null;
- if (windString != null) {
- speedString = windString.substring(gustyWind ? 2 : 3, 5);
+ String localWind = windString;
+ if (localWind != null) {
+ speedString = localWind.substring(gustyWind ? 2 : 3, 5);
try {
windSpeed = Integer.parseInt(speedString);
} catch (NumberFormatException e) {
}
}
- protected abstract void setWindString();
-
private void setPressure() {
setPressureString();
-
- if (pressureString != null) {
-
- String pressureTemp = pressureString.substring(1, 5);
-
+ String localPressure = pressureString;
+ if (localPressure != null) {
+ String pressureTemp = localPressure.substring(1, 5);
if (pressureTemp.charAt(0) == '0') {
pressureTemp = '1' + pressureTemp;
}
-
try {
pressure = (float) Integer.parseInt(pressureTemp) / 10;
} catch (NumberFormatException e) {
}
}
- protected abstract void setPressureString();
-
protected boolean isValidString(String str) {
return (str.length() == VALID_STRING_LENGTH);
}
*/
package org.openhab.binding.synopanalyzer.internal.synop;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
/**
* The {@link WindDirections} enum possible wind directions
*
* @author Gaël L'hopital - Initial contribution
*/
+@NonNullByDefault
public enum WindDirections {
N,
NNE,
* Returns the wind direction based on degree.
*/
public static WindDirections getWindDirection(int degree) {
- double step = 360.0 / WindDirections.values().length;
+ double step = 360.0 / values().length;
double b = Math.floor((degree + (step / 2.0)) / step);
- return WindDirections.values()[(int) (b % WindDirections.values().length)];
+ return values()[(int) (b % values().length)];
}
}
-{
- "stations":[
+[
{
"country":"FR",
"pack":"RADOME",
"elevation":1133,
"station_type":1
}
- ]
-}
\ No newline at end of file
+]