[synopanalyzer] Incorrect octa reported (#12541)
* 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>
This commit is contained in:
parent
3520621c1b
commit
94301eee8c
|
@ -12,7 +12,9 @@ There is exactly one supported thing, which represents a Synop message. It has t
|
||||||
|
|
||||||
## Discovery
|
## 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
|
## Thing Configuration
|
||||||
|
|
||||||
|
@ -26,7 +28,7 @@ The weather information that is retrieved is available as these channels:
|
||||||
|
|
||||||
| Channel Type ID | Item Type | Description |
|
| Channel Type ID | Item Type | Description |
|
||||||
|-----------------------|--------------------|--------------------------------------------|
|
|-----------------------|--------------------|--------------------------------------------|
|
||||||
| temperature | Number:Temperature | Current temperature |
|
| temperature | Number:Temperature | Current outdoor temperature |
|
||||||
| pressure | Number:Pressure | Current pressure |
|
| pressure | Number:Pressure | Current pressure |
|
||||||
| wind-speed | Number:Speed | Current wind speed |
|
| wind-speed | Number:Speed | Current wind speed |
|
||||||
| wind-speed-beaufort | Number | Wind speed according to Beaufort scale |
|
| wind-speed-beaufort | Number | Wind speed according to Beaufort scale |
|
||||||
|
|
|
@ -25,14 +25,13 @@ import org.openhab.core.library.unit.Units;
|
||||||
import org.openhab.core.thing.ThingTypeUID;
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link SynopAnalyzerBinding} class defines common constants, which are
|
* The {@link SynopAnalyzerBinding} class defines common constants used across the whole binding.
|
||||||
* used across the whole binding.
|
|
||||||
*
|
*
|
||||||
* @author Gaël L'hopital - Initial contribution
|
* @author Gaël L'hopital - Initial contribution
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class SynopAnalyzerBindingConstants {
|
public class SynopAnalyzerBindingConstants {
|
||||||
public static final String BINDING_ID = "synopanalyzer";
|
private static final String BINDING_ID = "synopanalyzer";
|
||||||
|
|
||||||
// List of all Thing Type UIDs
|
// List of all Thing Type UIDs
|
||||||
public static final ThingTypeUID THING_SYNOP = new ThingTypeUID(BINDING_ID, "synopanalyzer");
|
public static final ThingTypeUID THING_SYNOP = new ThingTypeUID(BINDING_ID, "synopanalyzer");
|
||||||
|
|
|
@ -14,38 +14,25 @@ package org.openhab.binding.synopanalyzer.internal;
|
||||||
|
|
||||||
import static org.openhab.binding.synopanalyzer.internal.SynopAnalyzerBindingConstants.THING_SYNOP;
|
import static org.openhab.binding.synopanalyzer.internal.SynopAnalyzerBindingConstants.THING_SYNOP;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.util.List;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
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.handler.SynopAnalyzerHandler;
|
||||||
import org.openhab.binding.synopanalyzer.internal.synop.StationDB;
|
import org.openhab.binding.synopanalyzer.internal.stationdb.Station;
|
||||||
import org.openhab.core.config.discovery.DiscoveryService;
|
import org.openhab.binding.synopanalyzer.internal.stationdb.StationDbService;
|
||||||
import org.openhab.core.i18n.LocationProvider;
|
import org.openhab.core.i18n.LocationProvider;
|
||||||
import org.openhab.core.thing.Thing;
|
import org.openhab.core.thing.Thing;
|
||||||
import org.openhab.core.thing.ThingTypeUID;
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||||
import org.openhab.core.thing.binding.ThingHandler;
|
import org.openhab.core.thing.binding.ThingHandler;
|
||||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
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.Activate;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
import org.osgi.service.component.annotations.Reference;
|
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
|
* The {@link SynopAnalyzerHandlerFactory} is responsible for creating things and thing handlers.
|
||||||
* handlers.
|
|
||||||
*
|
*
|
||||||
* @author Gaël L'hopital - Initial contribution
|
* @author Gaël L'hopital - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
@ -53,15 +40,14 @@ import com.google.gson.Gson;
|
||||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.synopanalyzer")
|
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.synopanalyzer")
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class SynopAnalyzerHandlerFactory extends BaseThingHandlerFactory {
|
public class SynopAnalyzerHandlerFactory extends BaseThingHandlerFactory {
|
||||||
private final Logger logger = LoggerFactory.getLogger(SynopAnalyzerHandlerFactory.class);
|
|
||||||
private final LocationProvider locationProvider;
|
private final LocationProvider locationProvider;
|
||||||
private final Gson gson = new Gson();
|
private final List<Station> stationDB;
|
||||||
private @Nullable StationDB stationDB;
|
|
||||||
private @Nullable ServiceRegistration<?> serviceReg;
|
|
||||||
|
|
||||||
@Activate
|
@Activate
|
||||||
public SynopAnalyzerHandlerFactory(@Reference LocationProvider locationProvider) {
|
public SynopAnalyzerHandlerFactory(@Reference StationDbService stationDBService,
|
||||||
|
@Reference LocationProvider locationProvider) {
|
||||||
this.locationProvider = locationProvider;
|
this.locationProvider = locationProvider;
|
||||||
|
this.stationDB = stationDBService.getStations();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -74,40 +60,4 @@ public class SynopAnalyzerHandlerFactory extends BaseThingHandlerFactory {
|
||||||
return supportsThingType(thing.getThingTypeUID()) ? new SynopAnalyzerHandler(thing, locationProvider, stationDB)
|
return supportsThingType(thing.getThingTypeUID()) ? new SynopAnalyzerHandler(thing, locationProvider, stationDB)
|
||||||
: null;
|
: 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,11 +13,9 @@
|
||||||
package org.openhab.binding.synopanalyzer.internal.config;
|
package org.openhab.binding.synopanalyzer.internal.config;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.openhab.binding.synopanalyzer.internal.handler.SynopAnalyzerHandler;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link SynopAnalyzerConfiguration} is responsible for holding configuration
|
* The {@link SynopAnalyzerConfiguration} holds configuration informations needed for the Synop thing
|
||||||
* informations needed for {@link SynopAnalyzerHandler}
|
|
||||||
*
|
*
|
||||||
* @author Gaël L'hopital - Initial contribution
|
* @author Gaël L'hopital - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -14,49 +14,50 @@ package org.openhab.binding.synopanalyzer.internal.discovery;
|
||||||
|
|
||||||
import static org.openhab.binding.synopanalyzer.internal.SynopAnalyzerBindingConstants.THING_SYNOP;
|
import static org.openhab.binding.synopanalyzer.internal.SynopAnalyzerBindingConstants.THING_SYNOP;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Iterator;
|
||||||
import java.util.Comparator;
|
import java.util.List;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Map.Entry;
|
||||||
import java.util.stream.Collectors;
|
import java.util.Set;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.openhab.binding.synopanalyzer.internal.config.SynopAnalyzerConfiguration;
|
import org.openhab.binding.synopanalyzer.internal.config.SynopAnalyzerConfiguration;
|
||||||
import org.openhab.binding.synopanalyzer.internal.synop.StationDB;
|
import org.openhab.binding.synopanalyzer.internal.stationdb.Station;
|
||||||
import org.openhab.binding.synopanalyzer.internal.synop.StationDB.Station;
|
import org.openhab.binding.synopanalyzer.internal.stationdb.StationDbService;
|
||||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||||
|
import org.openhab.core.config.discovery.DiscoveryService;
|
||||||
import org.openhab.core.i18n.LocationProvider;
|
import org.openhab.core.i18n.LocationProvider;
|
||||||
import org.openhab.core.library.types.DecimalType;
|
|
||||||
import org.openhab.core.library.types.PointType;
|
import org.openhab.core.library.types.PointType;
|
||||||
import org.openhab.core.thing.ThingUID;
|
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.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
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
|
* @author Gaël L'hopital - Initial Contribution
|
||||||
*/
|
*/
|
||||||
|
@Component(service = DiscoveryService.class)
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class SynopAnalyzerDiscoveryService extends AbstractDiscoveryService {
|
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 Logger logger = LoggerFactory.getLogger(SynopAnalyzerDiscoveryService.class);
|
||||||
private final Map<Integer, Double> distances = new HashMap<>();
|
|
||||||
private final LocationProvider locationProvider;
|
private final LocationProvider locationProvider;
|
||||||
private final StationDB stationDB;
|
private final List<Station> stations;
|
||||||
|
private double radius = 0;
|
||||||
|
|
||||||
/**
|
@Activate
|
||||||
* Creates a SynopAnalyzerDiscoveryService with enabled autostart.
|
public SynopAnalyzerDiscoveryService(@Reference StationDbService dBService,
|
||||||
*
|
@Reference LocationProvider locationProvider) {
|
||||||
*/
|
super(Set.of(THING_SYNOP), DISCOVER_TIMEOUT_SECONDS);
|
||||||
public SynopAnalyzerDiscoveryService(StationDB stationDB, LocationProvider locationProvider) {
|
|
||||||
super(Collections.singleton(THING_SYNOP), DISCOVER_TIMEOUT_SECONDS);
|
|
||||||
this.locationProvider = locationProvider;
|
this.locationProvider = locationProvider;
|
||||||
this.stationDB = stationDB;
|
this.stations = dBService.getStations();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -71,23 +72,29 @@ public class SynopAnalyzerDiscoveryService extends AbstractDiscoveryService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createResults(PointType serverLocation) {
|
public void createResults(PointType serverLocation) {
|
||||||
distances.clear();
|
Map<Double, Station> distances = new TreeMap<>();
|
||||||
|
|
||||||
stationDB.stations.forEach(s -> {
|
stations.forEach(station -> {
|
||||||
PointType stationLocation = new PointType(s.getLocation());
|
PointType stationLocation = new PointType(station.getLocation());
|
||||||
DecimalType distance = serverLocation.distanceFrom(stationLocation);
|
double distance = serverLocation.distanceFrom(stationLocation).doubleValue();
|
||||||
distances.put(s.idOmm, distance.doubleValue());
|
if (distance > radius) {
|
||||||
|
distances.put(distance, station);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Map<Integer, Double> result = distances.entrySet().stream()
|
Iterator<Entry<Double, Station>> stationIterator = distances.entrySet().iterator();
|
||||||
.sorted(Map.Entry.comparingByValue(Comparator.naturalOrder())).collect(Collectors.toMap(
|
if (stationIterator.hasNext()) {
|
||||||
Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));
|
Entry<Double, Station> nearest = stationIterator.next();
|
||||||
|
Station station = nearest.getValue();
|
||||||
|
radius = nearest.getKey();
|
||||||
|
|
||||||
Integer nearestId = result.entrySet().iterator().next().getKey();
|
thingDiscovered(DiscoveryResultBuilder.create(new ThingUID(THING_SYNOP, Integer.toString(station.idOmm)))
|
||||||
Optional<Station> station = stationDB.stations.stream().filter(s -> s.idOmm == nearestId).findFirst();
|
.withLabel(String.format("Synop : %s", station.usualName))
|
||||||
thingDiscovered(DiscoveryResultBuilder.create(new ThingUID(THING_SYNOP, nearestId.toString()))
|
.withProperty(SynopAnalyzerConfiguration.STATION_ID, station.idOmm)
|
||||||
.withLabel(String.format("Synop : %s", station.get().usualName))
|
.withRepresentationProperty(SynopAnalyzerConfiguration.STATION_ID).build());
|
||||||
.withProperty(SynopAnalyzerConfiguration.STATION_ID, nearestId)
|
} else {
|
||||||
.withRepresentationProperty(SynopAnalyzerConfiguration.STATION_ID).build());
|
logger.info("No Synop station available at a radius higher than {} m - resetting to 0 m", radius);
|
||||||
|
radius = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,8 @@ import javax.ws.rs.HttpMethod;
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.synopanalyzer.internal.config.SynopAnalyzerConfiguration;
|
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.Overcast;
|
||||||
import org.openhab.binding.synopanalyzer.internal.synop.StationDB;
|
|
||||||
import org.openhab.binding.synopanalyzer.internal.synop.Synop;
|
import org.openhab.binding.synopanalyzer.internal.synop.Synop;
|
||||||
import org.openhab.binding.synopanalyzer.internal.synop.SynopLand;
|
import org.openhab.binding.synopanalyzer.internal.synop.SynopLand;
|
||||||
import org.openhab.binding.synopanalyzer.internal.synop.SynopMobile;
|
import org.openhab.binding.synopanalyzer.internal.synop.SynopMobile;
|
||||||
|
@ -51,6 +51,7 @@ import org.openhab.core.library.unit.SIUnits;
|
||||||
import org.openhab.core.thing.ChannelUID;
|
import org.openhab.core.thing.ChannelUID;
|
||||||
import org.openhab.core.thing.Thing;
|
import org.openhab.core.thing.Thing;
|
||||||
import org.openhab.core.thing.ThingStatus;
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.thing.ThingStatusDetail;
|
||||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||||
import org.openhab.core.types.Command;
|
import org.openhab.core.types.Command;
|
||||||
import org.openhab.core.types.RefreshType;
|
import org.openhab.core.types.RefreshType;
|
||||||
|
@ -75,16 +76,16 @@ public class SynopAnalyzerHandler extends BaseThingHandler {
|
||||||
private static final double OCTA_MAX = 8.0;
|
private static final double OCTA_MAX = 8.0;
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(SynopAnalyzerHandler.class);
|
private final Logger logger = LoggerFactory.getLogger(SynopAnalyzerHandler.class);
|
||||||
|
|
||||||
private @Nullable ScheduledFuture<?> executionJob;
|
|
||||||
private @NonNullByDefault({}) String formattedStationId;
|
|
||||||
private final LocationProvider locationProvider;
|
private final LocationProvider locationProvider;
|
||||||
private final @Nullable StationDB stationDB;
|
private final List<Station> stations;
|
||||||
|
|
||||||
public SynopAnalyzerHandler(Thing thing, LocationProvider locationProvider, @Nullable StationDB stationDB) {
|
private Optional<ScheduledFuture<?>> refreshJob = Optional.empty();
|
||||||
|
private @NonNullByDefault({}) String formattedStationId;
|
||||||
|
|
||||||
|
public SynopAnalyzerHandler(Thing thing, LocationProvider locationProvider, List<Station> stations) {
|
||||||
super(thing);
|
super(thing);
|
||||||
this.locationProvider = locationProvider;
|
this.locationProvider = locationProvider;
|
||||||
this.stationDB = stationDB;
|
this.stations = stations;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -94,26 +95,23 @@ public class SynopAnalyzerHandler extends BaseThingHandler {
|
||||||
logger.info("Scheduling Synop update thread to run every {} minute for Station '{}'",
|
logger.info("Scheduling Synop update thread to run every {} minute for Station '{}'",
|
||||||
configuration.refreshInterval, formattedStationId);
|
configuration.refreshInterval, formattedStationId);
|
||||||
|
|
||||||
StationDB stations = stationDB;
|
if (thing.getProperties().isEmpty()) {
|
||||||
if (thing.getProperties().isEmpty() && stations != null) {
|
discoverAttributes(configuration.stationId, locationProvider.getLocation());
|
||||||
discoverAttributes(stations, configuration.stationId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStatus(ThingStatus.UNKNOWN);
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
|
||||||
executionJob = scheduler.scheduleWithFixedDelay(this::updateSynopChannels, 0, configuration.refreshInterval,
|
refreshJob = Optional.of(scheduler.scheduleWithFixedDelay(this::updateChannels, 0,
|
||||||
TimeUnit.MINUTES);
|
configuration.refreshInterval, TimeUnit.MINUTES));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void discoverAttributes(StationDB stations, int stationId) {
|
private void discoverAttributes(int stationId, @Nullable PointType serverLocation) {
|
||||||
stations.stations.stream().filter(s -> stationId == s.idOmm).findFirst().ifPresent(s -> {
|
stations.stream().filter(s -> stationId == s.idOmm).findFirst().ifPresent(station -> {
|
||||||
Map<String, String> properties = new HashMap<>();
|
Map<String, String> properties = new HashMap<>(
|
||||||
properties.put("Usual name", s.usualName);
|
Map.of("Usual name", station.usualName, "Location", station.getLocation()));
|
||||||
properties.put("Location", s.getLocation());
|
|
||||||
|
|
||||||
PointType stationLocation = new PointType(s.getLocation());
|
|
||||||
PointType serverLocation = locationProvider.getLocation();
|
|
||||||
if (serverLocation != null) {
|
if (serverLocation != null) {
|
||||||
|
PointType stationLocation = new PointType(station.getLocation());
|
||||||
DecimalType distance = serverLocation.distanceFrom(stationLocation);
|
DecimalType distance = serverLocation.distanceFrom(stationLocation);
|
||||||
|
|
||||||
properties.put("Distance", new QuantityType<>(distance, SIUnits.METRE).toString());
|
properties.put("Distance", new QuantityType<>(distance, SIUnits.METRE).toString());
|
||||||
|
@ -149,33 +147,35 @@ public class SynopAnalyzerHandler extends BaseThingHandler {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSynopChannels() {
|
private void updateChannels() {
|
||||||
logger.debug("Updating device channels");
|
logger.debug("Updating device channels");
|
||||||
|
|
||||||
Optional<Synop> synop = getLastAvailableSynop();
|
getLastAvailableSynop().ifPresentOrElse(synop -> {
|
||||||
updateStatus(synop.isPresent() ? ThingStatus.ONLINE : ThingStatus.OFFLINE);
|
updateStatus(ThingStatus.ONLINE);
|
||||||
synop.ifPresent(theSynop -> {
|
|
||||||
getThing().getChannels().forEach(channel -> {
|
getThing().getChannels().forEach(channel -> {
|
||||||
String channelId = channel.getUID().getId();
|
String channelId = channel.getUID().getId();
|
||||||
if (isLinked(channelId)) {
|
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) {
|
private State getChannelState(String channelId, Synop synop) {
|
||||||
|
int octa = synop.getOcta();
|
||||||
switch (channelId) {
|
switch (channelId) {
|
||||||
case HORIZONTAL_VISIBILITY:
|
case HORIZONTAL_VISIBILITY:
|
||||||
return new StringType(synop.getHorizontalVisibility().name());
|
return new StringType(synop.getHorizontalVisibility().name());
|
||||||
case OCTA:
|
case OCTA:
|
||||||
return new DecimalType(Math.max(0, synop.getOcta()));
|
return octa >= 0 ? new DecimalType(octa) : UnDefType.NULL;
|
||||||
case ATTENUATION_FACTOR:
|
case ATTENUATION_FACTOR:
|
||||||
double kc = Math.max(0, Math.min(synop.getOcta(), OCTA_MAX)) / OCTA_MAX;
|
if (octa >= 0) {
|
||||||
kc = 1 - 0.75 * Math.pow(kc, KASTEN_POWER);
|
double kc = Math.max(0, Math.min(octa, OCTA_MAX)) / OCTA_MAX;
|
||||||
return new DecimalType(kc);
|
kc = 1 - 0.75 * Math.pow(kc, KASTEN_POWER);
|
||||||
|
return new DecimalType(kc);
|
||||||
|
}
|
||||||
|
return UnDefType.NULL;
|
||||||
case OVERCAST:
|
case OVERCAST:
|
||||||
int octa = synop.getOcta();
|
|
||||||
Overcast overcast = Overcast.fromOcta(octa);
|
Overcast overcast = Overcast.fromOcta(octa);
|
||||||
return overcast == Overcast.UNDEFINED ? UnDefType.NULL : new StringType(overcast.name());
|
return overcast == Overcast.UNDEFINED ? UnDefType.NULL : new StringType(overcast.name());
|
||||||
case PRESSURE:
|
case PRESSURE:
|
||||||
|
@ -190,15 +190,14 @@ public class SynopAnalyzerHandler extends BaseThingHandler {
|
||||||
return getWindStrength(synop);
|
return getWindStrength(synop);
|
||||||
case WIND_SPEED_BEAUFORT:
|
case WIND_SPEED_BEAUFORT:
|
||||||
QuantityType<Speed> wsKpH = getWindStrength(synop).toUnit(SIUnits.KILOMETRE_PER_HOUR);
|
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;
|
: UnDefType.NULL;
|
||||||
case TIME_UTC:
|
case TIME_UTC:
|
||||||
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
|
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
|
||||||
int year = synop.getYear() == 0 ? now.getYear() : synop.getYear();
|
int year = synop.getYear() == 0 ? now.getYear() : synop.getYear();
|
||||||
int month = synop.getMonth() == 0 ? now.getMonth().getValue() : synop.getMonth();
|
int month = synop.getMonth() == 0 ? now.getMonth().getValue() : synop.getMonth();
|
||||||
ZonedDateTime zdt = ZonedDateTime.of(year, month, synop.getDay(), synop.getHour(), 0, 0, 0,
|
return new DateTimeType(
|
||||||
ZoneOffset.UTC);
|
ZonedDateTime.of(year, month, synop.getDay(), synop.getHour(), 0, 0, 0, ZoneOffset.UTC));
|
||||||
return new DateTimeType(zdt);
|
|
||||||
default:
|
default:
|
||||||
logger.error("Unsupported channel Id '{}'", channelId);
|
logger.error("Unsupported channel Id '{}'", channelId);
|
||||||
return UnDefType.UNDEF;
|
return UnDefType.UNDEF;
|
||||||
|
@ -232,17 +231,14 @@ public class SynopAnalyzerHandler extends BaseThingHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
ScheduledFuture<?> job = this.executionJob;
|
refreshJob.ifPresent(job -> job.cancel(true));
|
||||||
if (job != null && !job.isCancelled()) {
|
refreshJob = Optional.empty();
|
||||||
job.cancel(true);
|
|
||||||
}
|
|
||||||
executionJob = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
if (command == RefreshType.REFRESH) {
|
if (command == RefreshType.REFRESH) {
|
||||||
updateSynopChannels();
|
updateChannels();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,11 +12,14 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.synopanalyzer.internal.synop;
|
package org.openhab.binding.synopanalyzer.internal.synop;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link WindDirections} enum possible overcast descriptions
|
* The {@link WindDirections} enum possible overcast descriptions
|
||||||
*
|
*
|
||||||
* @author Gaël L'hopital - Initial contribution
|
* @author Gaël L'hopital - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public enum Overcast {
|
public enum Overcast {
|
||||||
UNDEFINED,
|
UNDEFINED,
|
||||||
CLEAR_SKY,
|
CLEAR_SKY,
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
|
@ -30,14 +30,14 @@ import org.openhab.core.library.unit.Units;
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public abstract class Synop {
|
public abstract class Synop {
|
||||||
protected static final int INITIAL_VALUE = -1000;
|
protected static final int INITIAL_VALUE = -1000;
|
||||||
protected static final char PLUS_SIGN_TEMPERATURE = '0';
|
private static final char PLUS_SIGN_TEMPERATURE = '0';
|
||||||
protected static final char MINUS_SIGN_TEMPERATURE = '1';
|
private static final char MINUS_SIGN_TEMPERATURE = '1';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WS - WIND SPEED
|
* WS - WIND SPEED
|
||||||
*/
|
*/
|
||||||
protected static final int WS_WILDTYPE_IN_MPS = 0;
|
private static final int WS_WILDTYPE_IN_MPS = 0;
|
||||||
protected static final int WS_ANEMOMETER_IN_MPS = 1;
|
private static final int WS_ANEMOMETER_IN_MPS = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* HV - HORIZONTAL VISIBILITY [IN KILOMETERS]
|
* HV - HORIZONTAL VISIBILITY [IN KILOMETERS]
|
||||||
|
@ -59,12 +59,12 @@ public abstract class Synop {
|
||||||
* 99 - > 50 km
|
* 99 - > 50 km
|
||||||
* HP - high precision
|
* HP - high precision
|
||||||
*/
|
*/
|
||||||
protected static final int HV_LESS_THAN_1_LIMIT = 10;
|
private static final int HV_LESS_THAN_1_LIMIT = 10;
|
||||||
protected static final int HV_LESS_THAN_10_LIMIT = 60;
|
private static final int HV_LESS_THAN_10_LIMIT = 60;
|
||||||
protected static final int HV_LESS_THAN_50_LIMIT = 84;
|
private static final int HV_LESS_THAN_50_LIMIT = 84;
|
||||||
protected static final int HV_LESS_THAN_1_HP_LIMIT = 93;
|
private static final int HV_LESS_THAN_1_HP_LIMIT = 93;
|
||||||
protected static final int HV_LESS_THAN_10_HP_LIMIT = 96;
|
private 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_50_HP_LIMIT = 98;
|
||||||
|
|
||||||
public static enum HorizontalVisibility {
|
public static enum HorizontalVisibility {
|
||||||
UNDEFINED,
|
UNDEFINED,
|
||||||
|
@ -74,7 +74,7 @@ public abstract class Synop {
|
||||||
MORE_THAN_50
|
MORE_THAN_50
|
||||||
}
|
}
|
||||||
|
|
||||||
private final int VALID_STRING_LENGTH = 5;
|
private static final int VALID_STRING_LENGTH = 5;
|
||||||
|
|
||||||
protected final List<String> stringArray;
|
protected final List<String> stringArray;
|
||||||
|
|
||||||
|
@ -107,6 +107,14 @@ public abstract class Synop {
|
||||||
setPressure();
|
setPressure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract void setTemperatureString();
|
||||||
|
|
||||||
|
protected abstract void setHorizontalVisibilityInt();
|
||||||
|
|
||||||
|
protected abstract void setPressureString();
|
||||||
|
|
||||||
|
protected abstract void setWindString();
|
||||||
|
|
||||||
private void setDateHourAndWindIndicator() {
|
private void setDateHourAndWindIndicator() {
|
||||||
String dayHourAndWindIndicator = "";
|
String dayHourAndWindIndicator = "";
|
||||||
|
|
||||||
|
@ -147,9 +155,7 @@ public abstract class Synop {
|
||||||
|
|
||||||
private void setHorizontalVisibility() {
|
private void setHorizontalVisibility() {
|
||||||
setHorizontalVisibilityInt();
|
setHorizontalVisibilityInt();
|
||||||
|
|
||||||
if (horizontalVisibilityInt != INITIAL_VALUE) {
|
if (horizontalVisibilityInt != INITIAL_VALUE) {
|
||||||
|
|
||||||
if (horizontalVisibilityInt < HV_LESS_THAN_1_LIMIT || horizontalVisibilityInt < HV_LESS_THAN_1_HP_LIMIT) {
|
if (horizontalVisibilityInt < HV_LESS_THAN_1_LIMIT || horizontalVisibilityInt < HV_LESS_THAN_1_HP_LIMIT) {
|
||||||
horizontalVisibility = HorizontalVisibility.LESS_THAN_1;
|
horizontalVisibility = HorizontalVisibility.LESS_THAN_1;
|
||||||
} else if (horizontalVisibilityInt < HV_LESS_THAN_10_LIMIT
|
} else if (horizontalVisibilityInt < HV_LESS_THAN_10_LIMIT
|
||||||
|
@ -166,8 +172,6 @@ public abstract class Synop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void setHorizontalVisibilityInt();
|
|
||||||
|
|
||||||
private void setTemperature() {
|
private void setTemperature() {
|
||||||
setTemperatureString();
|
setTemperatureString();
|
||||||
temperature = INITIAL_VALUE;
|
temperature = INITIAL_VALUE;
|
||||||
|
@ -183,12 +187,11 @@ public abstract class Synop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void setTemperatureString();
|
|
||||||
|
|
||||||
private void setWindAndOvercast() {
|
private void setWindAndOvercast() {
|
||||||
setWindString();
|
setWindString();
|
||||||
if (windString != null) {
|
String localWind = windString;
|
||||||
String gustyFlag = windString.substring(0, 2);
|
if (localWind != null) {
|
||||||
|
String gustyFlag = localWind.substring(0, 2);
|
||||||
if ("00".equals(gustyFlag)) {
|
if ("00".equals(gustyFlag)) {
|
||||||
setWindSpeed(true);
|
setWindSpeed(true);
|
||||||
} else {
|
} else {
|
||||||
|
@ -203,18 +206,20 @@ public abstract class Synop {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setOcta() {
|
private void setOcta() {
|
||||||
if (windString != null) {
|
String localWind = windString;
|
||||||
octa = Character.getNumericValue(windString.charAt(0));
|
if (localWind != null) {
|
||||||
|
octa = Character.getNumericValue(localWind.charAt(0));
|
||||||
} else {
|
} else {
|
||||||
octa = -1;
|
octa = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setWindDirection() {
|
private void setWindDirection() {
|
||||||
if (windString != null) {
|
String localWind = windString;
|
||||||
String windDirectionString = windString.substring(1, 3);
|
if (localWind != null) {
|
||||||
|
String windDirectionString = localWind.substring(1, 3);
|
||||||
|
|
||||||
if (windDirectionString.equals("99") || windDirectionString.equals("||")) {
|
if ("99".equals(windDirectionString) || "||".equals(windDirectionString)) {
|
||||||
windDirection = INITIAL_VALUE;
|
windDirection = INITIAL_VALUE;
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
|
@ -228,8 +233,9 @@ public abstract class Synop {
|
||||||
|
|
||||||
private void setWindSpeed(boolean gustyWind) {
|
private void setWindSpeed(boolean gustyWind) {
|
||||||
String speedString = null;
|
String speedString = null;
|
||||||
if (windString != null) {
|
String localWind = windString;
|
||||||
speedString = windString.substring(gustyWind ? 2 : 3, 5);
|
if (localWind != null) {
|
||||||
|
speedString = localWind.substring(gustyWind ? 2 : 3, 5);
|
||||||
try {
|
try {
|
||||||
windSpeed = Integer.parseInt(speedString);
|
windSpeed = Integer.parseInt(speedString);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
|
@ -238,19 +244,14 @@ public abstract class Synop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void setWindString();
|
|
||||||
|
|
||||||
private void setPressure() {
|
private void setPressure() {
|
||||||
setPressureString();
|
setPressureString();
|
||||||
|
String localPressure = pressureString;
|
||||||
if (pressureString != null) {
|
if (localPressure != null) {
|
||||||
|
String pressureTemp = localPressure.substring(1, 5);
|
||||||
String pressureTemp = pressureString.substring(1, 5);
|
|
||||||
|
|
||||||
if (pressureTemp.charAt(0) == '0') {
|
if (pressureTemp.charAt(0) == '0') {
|
||||||
pressureTemp = '1' + pressureTemp;
|
pressureTemp = '1' + pressureTemp;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
pressure = (float) Integer.parseInt(pressureTemp) / 10;
|
pressure = (float) Integer.parseInt(pressureTemp) / 10;
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
|
@ -259,8 +260,6 @@ public abstract class Synop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void setPressureString();
|
|
||||||
|
|
||||||
protected boolean isValidString(String str) {
|
protected boolean isValidString(String str) {
|
||||||
return (str.length() == VALID_STRING_LENGTH);
|
return (str.length() == VALID_STRING_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,14 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.synopanalyzer.internal.synop;
|
package org.openhab.binding.synopanalyzer.internal.synop;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link WindDirections} enum possible wind directions
|
* The {@link WindDirections} enum possible wind directions
|
||||||
*
|
*
|
||||||
* @author Gaël L'hopital - Initial contribution
|
* @author Gaël L'hopital - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public enum WindDirections {
|
public enum WindDirections {
|
||||||
N,
|
N,
|
||||||
NNE,
|
NNE,
|
||||||
|
@ -39,8 +42,8 @@ public enum WindDirections {
|
||||||
* Returns the wind direction based on degree.
|
* Returns the wind direction based on degree.
|
||||||
*/
|
*/
|
||||||
public static WindDirections getWindDirection(int 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);
|
double b = Math.floor((degree + (step / 2.0)) / step);
|
||||||
return WindDirections.values()[(int) (b % WindDirections.values().length)];
|
return values()[(int) (b % values().length)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
{
|
[
|
||||||
"stations":[
|
|
||||||
{
|
{
|
||||||
"country":"FR",
|
"country":"FR",
|
||||||
"pack":"RADOME",
|
"pack":"RADOME",
|
||||||
|
@ -2420,5 +2419,4 @@
|
||||||
"elevation":1133,
|
"elevation":1133,
|
||||||
"station_type":1
|
"station_type":1
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue