mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[SagerCaster] binding internals enhancement (#11295)
* Added semantic tags Make it ready for online translation of texts. Small code improvements Signed-off-by: Gaël L'hopital <gael@lhopital.org> * Update sagercaster_fr.properties * Correcting encoding for DE resource file. Signed-off-by: clinique <gael@lhopital.org> * Code review corrections Signed-off-by: clinique <gael@lhopital.org> * Still some code refinings * Corrections following lolodomo feed-backs. Signed-off-by: clinique <gael@lhopital.org> * Still some corrections Signed-off-by: clinique <gael@lhopital.org> * Enhanced discovery Signed-off-by: clinique <gael@lhopital.org>
This commit is contained in:
parent
054518e345
commit
48fd525dea
@ -12,6 +12,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.openhab.binding.sagercaster.internal;
|
package org.openhab.binding.sagercaster.internal;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.openhab.core.thing.ThingTypeUID;
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
|
|
||||||
@ -35,7 +37,6 @@ public class SagerCasterBindingConstants {
|
|||||||
public static final String CONFIG_PERIOD = "observation-period";
|
public static final String CONFIG_PERIOD = "observation-period";
|
||||||
|
|
||||||
// List of all Channel Groups Group Channel ids
|
// List of all Channel Groups Group Channel ids
|
||||||
public static final String GROUP_INPUT = "input";
|
|
||||||
public static final String GROUP_OUTPUT = "output";
|
public static final String GROUP_OUTPUT = "output";
|
||||||
|
|
||||||
// Output channel ids
|
// Output channel ids
|
||||||
@ -55,4 +56,8 @@ public class SagerCasterBindingConstants {
|
|||||||
public static final String CHANNEL_TEMPERATURE = "temperature";
|
public static final String CHANNEL_TEMPERATURE = "temperature";
|
||||||
public static final String CHANNEL_PRESSURE = "pressure";
|
public static final String CHANNEL_PRESSURE = "pressure";
|
||||||
public static final String CHANNEL_WIND_ANGLE = "wind-angle";
|
public static final String CHANNEL_WIND_ANGLE = "wind-angle";
|
||||||
|
|
||||||
|
// Some algorythms constants
|
||||||
|
public final static String FORECAST_PENDING = "0";
|
||||||
|
public final static Set<String> SHOWERS = Set.of("G", "K", "L", "R", "S", "T", "U", "W");
|
||||||
}
|
}
|
||||||
|
@ -58,9 +58,8 @@ public class SagerCasterHandlerFactory extends BaseThingHandlerFactory {
|
|||||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||||
|
|
||||||
if (thingTypeUID.equals(THING_TYPE_SAGERCASTER)) {
|
return thingTypeUID.equals(THING_TYPE_SAGERCASTER)
|
||||||
return new SagerCasterHandler(thing, stateDescriptionProvider, sagerWeatherCaster);
|
? new SagerCasterHandler(thing, stateDescriptionProvider, sagerWeatherCaster)
|
||||||
}
|
: null;
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,8 +76,6 @@ import org.slf4j.LoggerFactory;
|
|||||||
@Component(service = SagerWeatherCaster.class, scope = ServiceScope.SINGLETON)
|
@Component(service = SagerWeatherCaster.class, scope = ServiceScope.SINGLETON)
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class SagerWeatherCaster {
|
public class SagerWeatherCaster {
|
||||||
private final Properties forecaster = new Properties();
|
|
||||||
|
|
||||||
// Northern Polar Zone & Northern Tropical Zone
|
// Northern Polar Zone & Northern Tropical Zone
|
||||||
private final static String[] NPZDIRECTIONS = { "S", "SW", "W", "NW", "N", "NE", "E", "SE" };
|
private final static String[] NPZDIRECTIONS = { "S", "SW", "W", "NW", "N", "NE", "E", "SE" };
|
||||||
// Northern Temperate Zone
|
// Northern Temperate Zone
|
||||||
@ -88,9 +86,10 @@ public class SagerWeatherCaster {
|
|||||||
private final static String[] STZDIRECTIONS = { "S", "SE", "E", "NE", "N", "NW", "W", "SW" };
|
private final static String[] STZDIRECTIONS = { "S", "SE", "E", "NE", "N", "NW", "W", "SW" };
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(SagerWeatherCaster.class);
|
private final Logger logger = LoggerFactory.getLogger(SagerWeatherCaster.class);
|
||||||
|
private final Properties forecaster = new Properties();
|
||||||
|
|
||||||
private Optional<Prevision> prevision = Optional.empty();
|
private Optional<Prevision> prevision = Optional.empty();
|
||||||
private @NonNullByDefault({}) String[] usedDirections;
|
private String[] usedDirections = NTZDIRECTIONS; // Defaulted to Northern Zone
|
||||||
|
|
||||||
private int currentBearing = -1;
|
private int currentBearing = -1;
|
||||||
private int windEvolution = -1; // Whether the wind during the last 6 hours has changed its direction by
|
private int windEvolution = -1; // Whether the wind during the last 6 hours has changed its direction by
|
||||||
@ -105,9 +104,8 @@ public class SagerWeatherCaster {
|
|||||||
|
|
||||||
@Activate
|
@Activate
|
||||||
public SagerWeatherCaster() {
|
public SagerWeatherCaster() {
|
||||||
InputStream input = Thread.currentThread().getContextClassLoader()
|
try (InputStream input = Thread.currentThread().getContextClassLoader()
|
||||||
.getResourceAsStream("/sagerForecaster.properties");
|
.getResourceAsStream("/sagerForecaster.properties")) {
|
||||||
try {
|
|
||||||
forecaster.load(input);
|
forecaster.load(input);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.warn("Error during Sager Forecaster startup", e);
|
logger.warn("Error during Sager Forecaster startup", e);
|
||||||
@ -120,9 +118,9 @@ public class SagerWeatherCaster {
|
|||||||
|
|
||||||
public void setBearing(int newBearing, int oldBearing) {
|
public void setBearing(int newBearing, int oldBearing) {
|
||||||
int windEvol = sagerWindTrend(oldBearing, newBearing);
|
int windEvol = sagerWindTrend(oldBearing, newBearing);
|
||||||
if ((windEvol != this.windEvolution) || (newBearing != currentBearing)) {
|
if ((windEvol != windEvolution) || (newBearing != currentBearing)) {
|
||||||
this.currentBearing = newBearing;
|
currentBearing = newBearing;
|
||||||
this.windEvolution = windEvol;
|
windEvolution = windEvol;
|
||||||
updatePrediction();
|
updatePrediction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,40 +128,40 @@ public class SagerWeatherCaster {
|
|||||||
public void setPressure(double newPressure, double oldPressure) {
|
public void setPressure(double newPressure, double oldPressure) {
|
||||||
int newSagerPressure = sagerPressureLevel(newPressure);
|
int newSagerPressure = sagerPressureLevel(newPressure);
|
||||||
int pressEvol = sagerPressureTrend(newPressure, oldPressure);
|
int pressEvol = sagerPressureTrend(newPressure, oldPressure);
|
||||||
if ((pressEvol != this.pressureEvolution) || (newSagerPressure != sagerPressure)) {
|
if ((pressEvol != pressureEvolution) || (newSagerPressure != sagerPressure)) {
|
||||||
this.sagerPressure = newSagerPressure;
|
sagerPressure = newSagerPressure;
|
||||||
this.pressureEvolution = pressEvol;
|
pressureEvolution = pressEvol;
|
||||||
updatePrediction();
|
updatePrediction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCloudLevel(int cloudiness) {
|
public void setCloudLevel(int cloudiness) {
|
||||||
this.cloudLevel = cloudiness;
|
cloudLevel = cloudiness;
|
||||||
sagerNubesUpdate();
|
sagerNubesUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRaining(boolean raining) {
|
public void setRaining(boolean isRaining) {
|
||||||
this.raining = raining;
|
raining = isRaining;
|
||||||
sagerNubesUpdate();
|
sagerNubesUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBeaufort(int beaufortIndex) {
|
public void setBeaufort(int beaufortIndex) {
|
||||||
if (currentBeaufort != beaufortIndex) {
|
if (currentBeaufort != beaufortIndex) {
|
||||||
this.currentBeaufort = beaufortIndex;
|
currentBeaufort = beaufortIndex;
|
||||||
updatePrediction();
|
updatePrediction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getBeaufort() {
|
public int getBeaufort() {
|
||||||
return this.currentBeaufort;
|
return currentBeaufort;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWindEvolution() {
|
public int getWindEvolution() {
|
||||||
return this.windEvolution;
|
return windEvolution;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPressureEvolution() {
|
public int getPressureEvolution() {
|
||||||
return this.pressureEvolution;
|
return pressureEvolution;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sagerNubesUpdate() {
|
private void sagerNubesUpdate() {
|
||||||
@ -182,50 +180,43 @@ public class SagerWeatherCaster {
|
|||||||
result = 5; // raining
|
result = 5; // raining
|
||||||
}
|
}
|
||||||
if (result != nubes) {
|
if (result != nubes) {
|
||||||
this.nubes = result;
|
nubes = result;
|
||||||
updatePrediction();
|
updatePrediction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int sagerPressureLevel(double current) {
|
private static int sagerPressureLevel(double current) {
|
||||||
int result = 1;
|
|
||||||
if (current > 1029.46) {
|
if (current > 1029.46) {
|
||||||
result = 1;
|
return 1;
|
||||||
} else if (current > 1019.3) {
|
} else if (current > 1019.3) {
|
||||||
result = 2;
|
return 2;
|
||||||
} else if (current > 1012.53) {
|
} else if (current > 1012.53) {
|
||||||
result = 3;
|
return 3;
|
||||||
} else if (current > 1005.76) {
|
} else if (current > 1005.76) {
|
||||||
result = 4;
|
return 4;
|
||||||
} else if (current > 999) {
|
} else if (current > 999) {
|
||||||
result = 5;
|
return 5;
|
||||||
} else if (current > 988.8) {
|
} else if (current > 988.8) {
|
||||||
result = 6;
|
return 6;
|
||||||
} else if (current > 975.28) {
|
} else if (current > 975.28) {
|
||||||
result = 7;
|
return 7;
|
||||||
} else {
|
|
||||||
result = 8;
|
|
||||||
}
|
}
|
||||||
return result;
|
return 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int sagerPressureTrend(double current, double historic) {
|
private static int sagerPressureTrend(double current, double historic) {
|
||||||
double evol = current - historic;
|
double evol = current - historic;
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
if (evol > 1.4) {
|
if (evol > 1.4) {
|
||||||
result = 1; // Rising Rapidly
|
return 1; // Rising Rapidly
|
||||||
} else if (evol > 0.68) {
|
} else if (evol > 0.68) {
|
||||||
result = 2; // Rising Slowly
|
return 2; // Rising Slowly
|
||||||
} else if (evol > -0.68) {
|
} else if (evol > -0.68) {
|
||||||
result = 3; // Normal
|
return 3; // Normal
|
||||||
} else if (evol > -1.4) {
|
} else if (evol > -1.4) {
|
||||||
result = 4; // Decreasing Slowly
|
return 4; // Decreasing Slowly
|
||||||
} else {
|
|
||||||
result = 5; // Decreasing Rapidly
|
|
||||||
}
|
}
|
||||||
|
return 5; // Decreasing Rapidly
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int sagerWindTrend(double historic, double position) {
|
private static int sagerWindTrend(double historic, double position) {
|
||||||
@ -241,7 +232,7 @@ public class SagerWeatherCaster {
|
|||||||
|
|
||||||
private String getCompass() {
|
private String getCompass() {
|
||||||
double step = 360.0 / NTZDIRECTIONS.length;
|
double step = 360.0 / NTZDIRECTIONS.length;
|
||||||
double b = Math.floor((this.currentBearing + (step / 2.0)) / step);
|
double b = Math.floor((currentBearing + (step / 2.0)) / step);
|
||||||
return NTZDIRECTIONS[(int) (b % NTZDIRECTIONS.length)];
|
return NTZDIRECTIONS[(int) (b % NTZDIRECTIONS.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,36 +326,32 @@ public class SagerWeatherCaster {
|
|||||||
if (prevision.isPresent()) {
|
if (prevision.isPresent()) {
|
||||||
char forecast = prevision.get().zForecast;
|
char forecast = prevision.get().zForecast;
|
||||||
return Character.toString(forecast);
|
return Character.toString(forecast);
|
||||||
} else {
|
|
||||||
return "-";
|
|
||||||
}
|
}
|
||||||
|
return "-";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWindVelocity() {
|
public String getWindVelocity() {
|
||||||
if (prevision.isPresent()) {
|
if (prevision.isPresent()) {
|
||||||
char windVelocity = prevision.get().zWindVelocity;
|
char windVelocity = prevision.get().zWindVelocity;
|
||||||
return Character.toString(windVelocity);
|
return Character.toString(windVelocity);
|
||||||
} else {
|
|
||||||
return "-";
|
|
||||||
}
|
}
|
||||||
|
return "-";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWindDirection() {
|
public String getWindDirection() {
|
||||||
if (prevision.isPresent()) {
|
if (prevision.isPresent()) {
|
||||||
int direction = prevision.get().zWindDirection;
|
int direction = prevision.get().zWindDirection;
|
||||||
return String.valueOf(direction);
|
return String.valueOf(direction);
|
||||||
} else {
|
|
||||||
return "-";
|
|
||||||
}
|
}
|
||||||
|
return "-";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWindDirection2() {
|
public String getWindDirection2() {
|
||||||
if (prevision.isPresent()) {
|
if (prevision.isPresent()) {
|
||||||
int direction = prevision.get().zWindDirection2;
|
int direction = prevision.get().zWindDirection2;
|
||||||
return String.valueOf(direction);
|
return String.valueOf(direction);
|
||||||
} else {
|
|
||||||
return "-";
|
|
||||||
}
|
}
|
||||||
|
return "-";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLatitude(double latitude) {
|
public void setLatitude(double latitude) {
|
||||||
|
@ -14,10 +14,9 @@ package org.openhab.binding.sagercaster.internal.discovery;
|
|||||||
|
|
||||||
import static org.openhab.binding.sagercaster.internal.SagerCasterBindingConstants.*;
|
import static org.openhab.binding.sagercaster.internal.SagerCasterBindingConstants.*;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@ -26,10 +25,12 @@ import org.eclipse.jdt.annotation.Nullable;
|
|||||||
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.config.discovery.DiscoveryService;
|
||||||
|
import org.openhab.core.i18n.LocaleProvider;
|
||||||
import org.openhab.core.i18n.LocationProvider;
|
import org.openhab.core.i18n.LocationProvider;
|
||||||
|
import org.openhab.core.i18n.TranslationProvider;
|
||||||
import org.openhab.core.library.types.PointType;
|
import org.openhab.core.library.types.PointType;
|
||||||
import org.openhab.core.thing.ThingTypeUID;
|
|
||||||
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.Component;
|
||||||
import org.osgi.service.component.annotations.Reference;
|
import org.osgi.service.component.annotations.Reference;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@ -43,20 +44,26 @@ import org.slf4j.LoggerFactory;
|
|||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
@Component(service = DiscoveryService.class, configurationPid = "discovery.sagercaster")
|
@Component(service = DiscoveryService.class, configurationPid = "discovery.sagercaster")
|
||||||
public class SagerCasterDiscoveryService extends AbstractDiscoveryService {
|
public class SagerCasterDiscoveryService extends AbstractDiscoveryService {
|
||||||
private final Logger logger = LoggerFactory.getLogger(SagerCasterDiscoveryService.class);
|
|
||||||
private static final int DISCOVER_TIMEOUT_SECONDS = 30;
|
private static final int DISCOVER_TIMEOUT_SECONDS = 30;
|
||||||
private static final int LOCATION_CHANGED_CHECK_INTERVAL = 60;
|
private static final int LOCATION_CHANGED_CHECK_INTERVAL = 60;
|
||||||
private @NonNullByDefault({}) LocationProvider locationProvider;
|
private static final ThingUID SAGER_CASTER_THING = new ThingUID(THING_TYPE_SAGERCASTER, LOCAL);
|
||||||
private @NonNullByDefault({}) ScheduledFuture<?> sagerCasterDiscoveryJob;
|
|
||||||
private @Nullable PointType previousLocation;
|
|
||||||
|
|
||||||
private static final ThingUID sagerCasterThing = new ThingUID(THING_TYPE_SAGERCASTER, LOCAL);
|
private final Logger logger = LoggerFactory.getLogger(SagerCasterDiscoveryService.class);
|
||||||
|
private final LocationProvider locationProvider;
|
||||||
|
|
||||||
|
private @Nullable ScheduledFuture<?> discoveryJob;
|
||||||
|
private @Nullable PointType previousLocation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a SagerCasterDiscoveryService with enabled autostart.
|
* Creates a SagerCasterDiscoveryService with enabled autostart.
|
||||||
*/
|
*/
|
||||||
public SagerCasterDiscoveryService() {
|
@Activate
|
||||||
super(new HashSet<>(Arrays.asList(new ThingTypeUID(BINDING_ID, "-"))), DISCOVER_TIMEOUT_SECONDS, true);
|
public SagerCasterDiscoveryService(final @Reference LocaleProvider localeProvider,
|
||||||
|
final @Reference TranslationProvider i18nProvider, final @Reference LocationProvider locationProvider) {
|
||||||
|
super(Set.of(THING_TYPE_SAGERCASTER), DISCOVER_TIMEOUT_SECONDS, true);
|
||||||
|
this.locationProvider = locationProvider;
|
||||||
|
this.localeProvider = localeProvider;
|
||||||
|
this.i18nProvider = i18nProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -82,8 +89,8 @@ public class SagerCasterDiscoveryService extends AbstractDiscoveryService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void startBackgroundDiscovery() {
|
protected void startBackgroundDiscovery() {
|
||||||
if (sagerCasterDiscoveryJob == null) {
|
if (discoveryJob == null) {
|
||||||
sagerCasterDiscoveryJob = scheduler.scheduleWithFixedDelay(() -> {
|
discoveryJob = scheduler.scheduleWithFixedDelay(() -> {
|
||||||
PointType currentLocation = locationProvider.getLocation();
|
PointType currentLocation = locationProvider.getLocation();
|
||||||
if (currentLocation != null && !Objects.equals(currentLocation, previousLocation)) {
|
if (currentLocation != null && !Objects.equals(currentLocation, previousLocation)) {
|
||||||
logger.debug("Location has been changed from {} to {}: Creating new discovery results",
|
logger.debug("Location has been changed from {} to {}: Creating new discovery results",
|
||||||
@ -99,28 +106,19 @@ public class SagerCasterDiscoveryService extends AbstractDiscoveryService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void stopBackgroundDiscovery() {
|
protected void stopBackgroundDiscovery() {
|
||||||
|
ScheduledFuture<?> localJob = discoveryJob;
|
||||||
logger.debug("Stopping Sager Weathercaster background discovery");
|
logger.debug("Stopping Sager Weathercaster background discovery");
|
||||||
if (sagerCasterDiscoveryJob != null && !sagerCasterDiscoveryJob.isCancelled()) {
|
if (localJob != null && !localJob.isCancelled()) {
|
||||||
if (sagerCasterDiscoveryJob.cancel(true)) {
|
if (localJob.cancel(true)) {
|
||||||
sagerCasterDiscoveryJob = null;
|
discoveryJob = null;
|
||||||
logger.debug("Stopped SagerCaster device background discovery");
|
logger.debug("Stopped SagerCaster device background discovery");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createResults(PointType location) {
|
public void createResults(PointType location) {
|
||||||
String propGeolocation;
|
String propGeolocation = String.format("%s,%s", location.getLatitude(), location.getLongitude());
|
||||||
propGeolocation = String.format("%s,%s", location.getLatitude(), location.getLongitude());
|
thingDiscovered(DiscoveryResultBuilder.create(SAGER_CASTER_THING).withLabel("Local Weather Forecast")
|
||||||
thingDiscovered(DiscoveryResultBuilder.create(sagerCasterThing).withLabel("Local Sager Weathercaster")
|
|
||||||
.withRepresentationProperty(CONFIG_LOCATION).withProperty(CONFIG_LOCATION, propGeolocation).build());
|
.withRepresentationProperty(CONFIG_LOCATION).withProperty(CONFIG_LOCATION, propGeolocation).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Reference
|
|
||||||
protected void setLocationProvider(LocationProvider locationProvider) {
|
|
||||||
this.locationProvider = locationProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void unsetLocationProvider(LocationProvider locationProvider) {
|
|
||||||
this.locationProvider = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -37,11 +37,10 @@ class ExpiringMap<T> {
|
|||||||
public void put(T newValue) {
|
public void put(T newValue) {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
values.put(now, newValue);
|
values.put(now, newValue);
|
||||||
Optional<Long> eldestKey = values.keySet().stream().filter(key -> key < now - eldestAge).findFirst();
|
values.keySet().stream().filter(key -> key < now - eldestAge).findFirst().ifPresent(eldest -> {
|
||||||
if (eldestKey.isPresent()) {
|
agedValue = Optional.ofNullable(values.get(eldest));
|
||||||
agedValue = Optional.ofNullable(values.get(eldestKey.get()));
|
values.entrySet().removeIf(map -> map.getKey() <= eldest);
|
||||||
values.entrySet().removeIf(map -> map.getKey() <= eldestKey.get());
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<T> getAgedValue() {
|
public Optional<T> getAgedValue() {
|
||||||
|
@ -17,16 +17,11 @@ import static org.openhab.core.library.unit.MetricPrefix.HECTO;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.measure.quantity.Angle;
|
import javax.measure.quantity.Angle;
|
||||||
import javax.measure.quantity.Dimensionless;
|
|
||||||
import javax.measure.quantity.Pressure;
|
import javax.measure.quantity.Pressure;
|
||||||
import javax.measure.quantity.Temperature;
|
import javax.measure.quantity.Temperature;
|
||||||
|
|
||||||
@ -56,19 +51,19 @@ import org.slf4j.LoggerFactory;
|
|||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class SagerCasterHandler extends BaseThingHandler {
|
public class SagerCasterHandler extends BaseThingHandler {
|
||||||
private final static String FORECAST_PENDING = "0";
|
|
||||||
private final static Set<String> SHOWERS = Collections
|
|
||||||
.unmodifiableSet(new HashSet<>(Arrays.asList("G", "K", "L", "R", "S", "T", "U", "W")));
|
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(SagerCasterHandler.class);
|
private final Logger logger = LoggerFactory.getLogger(SagerCasterHandler.class);
|
||||||
|
|
||||||
private final SagerWeatherCaster sagerWeatherCaster;
|
private final SagerWeatherCaster sagerWeatherCaster;
|
||||||
|
|
||||||
private final WindDirectionStateDescriptionProvider stateDescriptionProvider;
|
private final WindDirectionStateDescriptionProvider stateDescriptionProvider;
|
||||||
private int currentTemp = 0;
|
|
||||||
|
|
||||||
private final ExpiringMap<QuantityType<Pressure>> pressureCache = new ExpiringMap<>();
|
private final ExpiringMap<QuantityType<Pressure>> pressureCache = new ExpiringMap<>();
|
||||||
private final ExpiringMap<QuantityType<Temperature>> temperatureCache = new ExpiringMap<>();
|
private final ExpiringMap<QuantityType<Temperature>> temperatureCache = new ExpiringMap<>();
|
||||||
private final ExpiringMap<QuantityType<Angle>> bearingCache = new ExpiringMap<>();
|
private final ExpiringMap<QuantityType<Angle>> bearingCache = new ExpiringMap<>();
|
||||||
|
|
||||||
|
private int currentTemp = 0;
|
||||||
|
|
||||||
public SagerCasterHandler(Thing thing, WindDirectionStateDescriptionProvider stateDescriptionProvider,
|
public SagerCasterHandler(Thing thing, WindDirectionStateDescriptionProvider stateDescriptionProvider,
|
||||||
SagerWeatherCaster sagerWeatherCaster) {
|
SagerWeatherCaster sagerWeatherCaster) {
|
||||||
super(thing);
|
super(thing);
|
||||||
@ -82,7 +77,7 @@ public class SagerCasterHandler extends BaseThingHandler {
|
|||||||
int observationPeriod = ((BigDecimal) getConfig().get(CONFIG_PERIOD)).intValue();
|
int observationPeriod = ((BigDecimal) getConfig().get(CONFIG_PERIOD)).intValue();
|
||||||
String latitude = location.split(",")[0];
|
String latitude = location.split(",")[0];
|
||||||
sagerWeatherCaster.setLatitude(Double.parseDouble(latitude));
|
sagerWeatherCaster.setLatitude(Double.parseDouble(latitude));
|
||||||
long period = TimeUnit.SECONDS.toMillis(observationPeriod);
|
long period = TimeUnit.HOURS.toMillis(observationPeriod);
|
||||||
pressureCache.setObservationPeriod(period);
|
pressureCache.setObservationPeriod(period);
|
||||||
bearingCache.setObservationPeriod(period);
|
bearingCache.setObservationPeriod(period);
|
||||||
temperatureCache.setObservationPeriod(period);
|
temperatureCache.setObservationPeriod(period);
|
||||||
@ -116,8 +111,7 @@ public class SagerCasterHandler extends BaseThingHandler {
|
|||||||
case CHANNEL_CLOUDINESS:
|
case CHANNEL_CLOUDINESS:
|
||||||
logger.debug("Octa cloud level changed, updating forecast");
|
logger.debug("Octa cloud level changed, updating forecast");
|
||||||
if (command instanceof QuantityType) {
|
if (command instanceof QuantityType) {
|
||||||
@SuppressWarnings("unchecked")
|
QuantityType<?> cloudiness = (QuantityType<?>) command;
|
||||||
QuantityType<Dimensionless> cloudiness = (QuantityType<Dimensionless>) command;
|
|
||||||
scheduler.submit(() -> {
|
scheduler.submit(() -> {
|
||||||
sagerWeatherCaster.setCloudLevel(cloudiness.intValue());
|
sagerWeatherCaster.setCloudLevel(cloudiness.intValue());
|
||||||
postNewForecast();
|
postNewForecast();
|
||||||
@ -127,7 +121,7 @@ public class SagerCasterHandler extends BaseThingHandler {
|
|||||||
case CHANNEL_IS_RAINING:
|
case CHANNEL_IS_RAINING:
|
||||||
logger.debug("Rain status updated, updating forecast");
|
logger.debug("Rain status updated, updating forecast");
|
||||||
if (command instanceof OnOffType) {
|
if (command instanceof OnOffType) {
|
||||||
OnOffType isRaining = ((OnOffType) command);
|
OnOffType isRaining = (OnOffType) command;
|
||||||
scheduler.submit(() -> {
|
scheduler.submit(() -> {
|
||||||
sagerWeatherCaster.setRaining(isRaining == OnOffType.ON);
|
sagerWeatherCaster.setRaining(isRaining == OnOffType.ON);
|
||||||
postNewForecast();
|
postNewForecast();
|
||||||
@ -139,13 +133,13 @@ public class SagerCasterHandler extends BaseThingHandler {
|
|||||||
case CHANNEL_RAIN_QTTY:
|
case CHANNEL_RAIN_QTTY:
|
||||||
logger.debug("Rain status updated, updating forecast");
|
logger.debug("Rain status updated, updating forecast");
|
||||||
if (command instanceof QuantityType) {
|
if (command instanceof QuantityType) {
|
||||||
QuantityType<?> newQtty = ((QuantityType<?>) command);
|
QuantityType<?> newQtty = (QuantityType<?>) command;
|
||||||
scheduler.submit(() -> {
|
scheduler.submit(() -> {
|
||||||
sagerWeatherCaster.setRaining(newQtty.doubleValue() > 0);
|
sagerWeatherCaster.setRaining(newQtty.doubleValue() > 0);
|
||||||
postNewForecast();
|
postNewForecast();
|
||||||
});
|
});
|
||||||
} else if (command instanceof DecimalType) {
|
} else if (command instanceof DecimalType) {
|
||||||
DecimalType newQtty = ((DecimalType) command);
|
DecimalType newQtty = (DecimalType) command;
|
||||||
scheduler.submit(() -> {
|
scheduler.submit(() -> {
|
||||||
sagerWeatherCaster.setRaining(newQtty.doubleValue() > 0);
|
sagerWeatherCaster.setRaining(newQtty.doubleValue() > 0);
|
||||||
postNewForecast();
|
postNewForecast();
|
||||||
@ -175,18 +169,12 @@ public class SagerCasterHandler extends BaseThingHandler {
|
|||||||
.toUnit(HECTO(SIUnits.PASCAL));
|
.toUnit(HECTO(SIUnits.PASCAL));
|
||||||
if (newPressure != null) {
|
if (newPressure != null) {
|
||||||
pressureCache.put(newPressure);
|
pressureCache.put(newPressure);
|
||||||
Optional<QuantityType<Pressure>> agedPressure = pressureCache.getAgedValue();
|
pressureCache.getAgedValue().ifPresentOrElse(pressure -> scheduler.submit(() -> {
|
||||||
if (agedPressure.isPresent()) {
|
sagerWeatherCaster.setPressure(newPressure.doubleValue(), pressure.doubleValue());
|
||||||
scheduler.submit(() -> {
|
updateChannelString(GROUP_OUTPUT, CHANNEL_PRESSURETREND,
|
||||||
sagerWeatherCaster.setPressure(newPressure.doubleValue(),
|
String.valueOf(sagerWeatherCaster.getPressureEvolution()));
|
||||||
agedPressure.get().doubleValue());
|
postNewForecast();
|
||||||
updateChannelString(GROUP_OUTPUT, CHANNEL_PRESSURETREND,
|
}), () -> updateChannelString(GROUP_OUTPUT, CHANNEL_FORECAST, FORECAST_PENDING));
|
||||||
String.valueOf(sagerWeatherCaster.getPressureEvolution()));
|
|
||||||
postNewForecast();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
updateChannelString(GROUP_OUTPUT, CHANNEL_FORECAST, FORECAST_PENDING);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -200,12 +188,12 @@ public class SagerCasterHandler extends BaseThingHandler {
|
|||||||
temperatureCache.put(newTemperature);
|
temperatureCache.put(newTemperature);
|
||||||
currentTemp = newTemperature.intValue();
|
currentTemp = newTemperature.intValue();
|
||||||
Optional<QuantityType<Temperature>> agedTemperature = temperatureCache.getAgedValue();
|
Optional<QuantityType<Temperature>> agedTemperature = temperatureCache.getAgedValue();
|
||||||
if (agedTemperature.isPresent()) {
|
agedTemperature.ifPresent(temperature -> {
|
||||||
double delta = newTemperature.doubleValue() - agedTemperature.get().doubleValue();
|
double delta = newTemperature.doubleValue() - temperature.doubleValue();
|
||||||
String trend = (delta > 3) ? "1"
|
String trend = (delta > 3) ? "1"
|
||||||
: (delta > 0.3) ? "2" : (delta > -0.3) ? "3" : (delta > -3) ? "4" : "5";
|
: (delta > 0.3) ? "2" : (delta > -0.3) ? "3" : (delta > -3) ? "4" : "5";
|
||||||
updateChannelString(GROUP_OUTPUT, CHANNEL_TEMPERATURETREND, trend);
|
updateChannelString(GROUP_OUTPUT, CHANNEL_TEMPERATURETREND, trend);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -216,14 +204,14 @@ public class SagerCasterHandler extends BaseThingHandler {
|
|||||||
QuantityType<Angle> newAngle = (QuantityType<Angle>) command;
|
QuantityType<Angle> newAngle = (QuantityType<Angle>) command;
|
||||||
bearingCache.put(newAngle);
|
bearingCache.put(newAngle);
|
||||||
Optional<QuantityType<Angle>> agedAngle = bearingCache.getAgedValue();
|
Optional<QuantityType<Angle>> agedAngle = bearingCache.getAgedValue();
|
||||||
if (agedAngle.isPresent()) {
|
agedAngle.ifPresent(angle -> {
|
||||||
scheduler.submit(() -> {
|
scheduler.submit(() -> {
|
||||||
sagerWeatherCaster.setBearing(newAngle.intValue(), agedAngle.get().intValue());
|
sagerWeatherCaster.setBearing(newAngle.intValue(), angle.intValue());
|
||||||
updateChannelString(GROUP_OUTPUT, CHANNEL_WINDEVOLUTION,
|
updateChannelString(GROUP_OUTPUT, CHANNEL_WINDEVOLUTION,
|
||||||
String.valueOf(sagerWeatherCaster.getWindEvolution()));
|
String.valueOf(sagerWeatherCaster.getWindEvolution()));
|
||||||
postNewForecast();
|
postNewForecast();
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -270,14 +258,14 @@ public class SagerCasterHandler extends BaseThingHandler {
|
|||||||
updateChannelDecimal(GROUP_OUTPUT, CHANNEL_VELOCITY_BEAUFORT, predictedBeaufort);
|
updateChannelDecimal(GROUP_OUTPUT, CHANNEL_VELOCITY_BEAUFORT, predictedBeaufort);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateChannelString(String group, String channelId, String value) {
|
private void updateChannelString(String group, String channelId, String value) {
|
||||||
ChannelUID id = new ChannelUID(getThing().getUID(), group, channelId);
|
ChannelUID id = new ChannelUID(getThing().getUID(), group, channelId);
|
||||||
if (isLinked(id)) {
|
if (isLinked(id)) {
|
||||||
updateState(id, new StringType(value));
|
updateState(id, new StringType(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateChannelDecimal(String group, String channelId, int value) {
|
private void updateChannelDecimal(String group, String channelId, int value) {
|
||||||
ChannelUID id = new ChannelUID(getThing().getUID(), group, channelId);
|
ChannelUID id = new ChannelUID(getThing().getUID(), group, channelId);
|
||||||
if (isLinked(id)) {
|
if (isLinked(id)) {
|
||||||
updateState(id, new DecimalType(value));
|
updateState(id, new DecimalType(value));
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||||
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||||
|
|
||||||
<name>SagerCaster Binding</name>
|
<name>@text/bindingName</name>
|
||||||
<description>The Sager Weathercaster is a scientific instrument for accurate prediction of the weather.</description>
|
<description>@text/bindingDescription</description>
|
||||||
|
|
||||||
</binding:binding>
|
</binding:binding>
|
||||||
|
@ -0,0 +1,108 @@
|
|||||||
|
# binding
|
||||||
|
bindingName = SagerCaster Binding
|
||||||
|
bindingDescription = The Sager Weathercaster is a scientific instrument for accurate prediction of the weather.
|
||||||
|
|
||||||
|
# thing
|
||||||
|
sagercasterLabel = SagerCaster Thing
|
||||||
|
sagercasterDescription = This thing represents a forecast for a given location.
|
||||||
|
|
||||||
|
# ting configuration
|
||||||
|
locationLabel = Location
|
||||||
|
locationDescription = Your geo coordinates separated with comma (e.g. "37.8,-122.4").
|
||||||
|
observationLabel = Observation Period
|
||||||
|
observationDescription = Sager WeatherCaster needs a minimum representative period of time to produce meaningfull results (defaults to 6 hours).
|
||||||
|
|
||||||
|
# channel groups
|
||||||
|
inputLabel = Inputs
|
||||||
|
inputDescription = The channels used to build the forecast results
|
||||||
|
outputLabel = Results
|
||||||
|
outputDescription = Results of the Sager Weathercaster algorithm
|
||||||
|
|
||||||
|
# channels
|
||||||
|
windVelocity = Wind Velocity
|
||||||
|
windFrom = Wind from
|
||||||
|
windTo = Wind to
|
||||||
|
pressureTrendLabel = Pressure Trend
|
||||||
|
pressureTrendDescription = Pressure evolution trend over observation delay
|
||||||
|
tempTrendLabel = Temperature Trend
|
||||||
|
tempTrendDescription = Temperature evolution trend over observation delay
|
||||||
|
forecastLabel = Weather Forecast
|
||||||
|
windDirectionLabel = Wind Direction
|
||||||
|
windEvolutionLabel = Wind Evolution
|
||||||
|
windEvolutionDescription = Wind bearing evolution trend over observation delay
|
||||||
|
trendLabel = Measure Trend
|
||||||
|
trendDescription = Measure evolution trend over observation delay
|
||||||
|
timestampLabel = Calculation Time
|
||||||
|
timestampDescription = Weather forecast calculation date and time
|
||||||
|
cloudinessLabel = Cloudiness
|
||||||
|
cloudinessDescription = Current cloudiness.
|
||||||
|
rainQttyLabel = Rain Quantity
|
||||||
|
rainQttyDescription = Current rain quantity
|
||||||
|
rainingLabel = Raining
|
||||||
|
rainingDescription = Is it currently raining ?
|
||||||
|
beaufortLabel = Beaufort
|
||||||
|
beaufortDescription = Wind speed using Beaufort Scale
|
||||||
|
pressureDescription = Barometric pressure at sea level.
|
||||||
|
|
||||||
|
# channel options
|
||||||
|
forecast0 = Not enough historic data to study pressure evolution, wait a bit ...
|
||||||
|
forecastA = Fair
|
||||||
|
forecastB = Fair and warmer
|
||||||
|
forecastC = Fair and cooler
|
||||||
|
forecastD = Unsettled
|
||||||
|
forecastE = Unsettled and warmer
|
||||||
|
forecastF = Unsettled and cooler
|
||||||
|
forecastG = Increasing cloudiness or overcast followed by Precipitation or showers/Flurries
|
||||||
|
forecastG1 = Increasing cloudiness or overcast followed by Precipitation or showers
|
||||||
|
forecastG2 = Increasing cloudiness or overcast followed by Precipitation or Flurries
|
||||||
|
forecastH = Increasing cloudiness or overcast followed by Precipitation or showers and warmer
|
||||||
|
forecastJ = Showers
|
||||||
|
forecastK = Showers/Flurries and warmer
|
||||||
|
forecastK1 = Showers and warmer
|
||||||
|
forecastK2 = Flurries and warmer
|
||||||
|
forecastL = Showers/Flurries and cooler
|
||||||
|
forecastL1 = Showers and cooler
|
||||||
|
forecastL2 = Flurries and cooler
|
||||||
|
forecastM = Precipitation
|
||||||
|
forecastN = Precipitation and warmer
|
||||||
|
forecastP = Precipitation and turning cooler; then improvement likely in 24 hours
|
||||||
|
forecastR = Precipitation or showers/Flurries followed by improvement (within 12 hours)
|
||||||
|
forecastR1 = Precipitation or showers followed by improvement (within 12 hours)
|
||||||
|
forecastR2 = Precipitation or flurries followed by improvement (within 12 hours)
|
||||||
|
forecastS = Precipitation or showers/Flurries followed by improvement (within 12 hours) and becoming cooler
|
||||||
|
forecastS1 = Precipitation or showers followed by improvement (within 12 hours) and becoming cooler
|
||||||
|
forecastS2 = Precipitation or flurries followed by improvement (within 12 hours) and becoming cooler
|
||||||
|
forecastT = Precipitation or showers/Flurries followed by improvement early in period (within 6 hours)
|
||||||
|
forecastT1 = Precipitation or showers followed by improvement early in period (within 6 hours)
|
||||||
|
forecastT2 = Precipitation or flurries followed by improvement early in period (within 6 hours)
|
||||||
|
forecastU = Precipitation or showers/Flurries by improvement early in period (within 6 hours) and becoming cooler
|
||||||
|
forecastU1 = Precipitation or showers by improvement early in period (within 6 hours) and becoming cooler
|
||||||
|
forecastU2 = Precipitation or flurries by improvement early in period (within 6 hours) and becoming cooler
|
||||||
|
forecastW = Precipitation or showers/Flurries followed by fair early in period (within 6 hours) and becoming cooler
|
||||||
|
forecastW1 = Precipitation or showers followed by fair early in period (within 6 hours) and becoming cooler
|
||||||
|
forecastW2 = Precipitation or flurries followed by fair early in period (within 6 hours) and becoming cooler
|
||||||
|
forecastX = Unsettled followed by fair
|
||||||
|
forecastY = Unsettled followed by fair early in period (within 6 hours) and becoming cooler
|
||||||
|
|
||||||
|
velocityN = Probably increasing
|
||||||
|
velocityF = Moderate to fresh
|
||||||
|
velocityS = Strong winds may precede gales over open water
|
||||||
|
velocityG = Gale
|
||||||
|
velocityW = Dangerous gale (whole gale)
|
||||||
|
velocityH = Hurricane
|
||||||
|
velocityD = Diminishing, or moderating somewhat if current winds are of fresh to strong velocity
|
||||||
|
velocityU = No important change. Some tendency for slight increase in winds during day, diminishing in evening
|
||||||
|
|
||||||
|
evolution1 = Steady
|
||||||
|
evolution2 = Veering
|
||||||
|
evolution3 = Backing
|
||||||
|
|
||||||
|
trend1 = Rising Rapidly
|
||||||
|
trend2 = Rising Slowly
|
||||||
|
trend3 = Normal
|
||||||
|
trend4 = Decreasing Slowly
|
||||||
|
trend5 = Decreasing Rapidly
|
||||||
|
|
||||||
|
# Discovery result
|
||||||
|
discovery.sagercaster.sagercaster.local.label = Local Weather Forecast
|
||||||
|
|
@ -1,63 +1,66 @@
|
|||||||
# binding
|
# binding
|
||||||
binding.sagercaster.name = SagerCaster Binding
|
bindingName = SagerCaster Binding
|
||||||
binding.sagercaster.description = Die SagerCaster-Erweiterung wird zur Erstellung von Wettervorhersagen verwendet.
|
bindingDescription = Die SagerCaster-Erweiterung wird zur Erstellung von Wettervorhersagen verwendet.
|
||||||
|
|
||||||
|
# thing
|
||||||
|
sagercasterLabel = SagerCaster Thing
|
||||||
|
sagercasterDescription = Dieses Thing stellt eine Vorhersage für einen bestimmten Standort dar.
|
||||||
|
|
||||||
# channel types
|
# channel types
|
||||||
channel-type.sagercaster.forecast.state.option.0 = Warten Sie etwas länger auf eine Vorhersage
|
forecast0 = Warten Sie etwas länger auf eine Vorhersage
|
||||||
channel-type.sagercaster.forecast.state.option.A = Gutes Wetter
|
forecastA = Gutes Wetter
|
||||||
channel-type.sagercaster.forecast.state.option.B = Gutes Wetter und Erwärmung
|
forecastB = Gutes Wetter und Erwärmung
|
||||||
channel-type.sagercaster.forecast.state.option.C = Gutes Wetter und Abkühlung
|
forecastC = Gutes Wetter und Abkühlung
|
||||||
channel-type.sagercaster.forecast.state.option.D = Instabil
|
forecastD = Instabil
|
||||||
channel-type.sagercaster.forecast.state.option.E = Instabil und Erwärmung
|
forecastE = Instabil und Erwärmung
|
||||||
channel-type.sagercaster.forecast.state.option.F = Instabil und Abkühlung
|
forecastF = Instabil und Abkühlung
|
||||||
channel-type.sagercaster.forecast.state.option.G = Zunehmende Bewölkung oder sehr bewölkt, gefolgt von Niederschlag oder Schauern / Schnee
|
forecastG = Zunehmende Bewölkung oder sehr bewölkt, gefolgt von Niederschlag oder Schauern / Schnee
|
||||||
channel-type.sagercaster.forecast.state.option.G1 = Zunehmende oder sehr trübe Bewölkung, gefolgt von Niederschlag oder Schauern
|
forecastG1 = Zunehmende oder sehr trübe Bewölkung, gefolgt von Niederschlag oder Schauern
|
||||||
channel-type.sagercaster.forecast.state.option.G2 = Zunehmende Bewölkung oder sehr bewölkt, gefolgt von Niederschlag oder Schnee
|
forecastG2 = Zunehmende Bewölkung oder sehr bewölkt, gefolgt von Niederschlag oder Schnee
|
||||||
channel-type.sagercaster.forecast.state.option.H = Zunehmende Bewölkung oder sehr bewölkt, gefolgt von Niederschlag oder Schauern und Erwärmung
|
forecastH = Zunehmende Bewölkung oder sehr bewölkt, gefolgt von Niederschlag oder Schauern und Erwärmung
|
||||||
channel-type.sagercaster.forecast.state.option.J = Regengüsse
|
forecastJ = Regengüsse
|
||||||
channel-type.sagercaster.forecast.state.option.K = Regengüsse / Schnee und Erwärmung
|
forecastK = Regengüsse / Schnee und Erwärmung
|
||||||
channel-type.sagercaster.forecast.state.option.K1 = Regengüsse und Erwärmung
|
forecastK1 = Regengüsse und Erwärmung
|
||||||
channel-type.sagercaster.forecast.state.option.K2 = Schnee und Erwärmung
|
forecastK2 = Schnee und Erwärmung
|
||||||
channel-type.sagercaster.forecast.state.option.L = Regengüsse / Schnee und Abkühlung
|
forecastL = Regengüsse / Schnee und Abkühlung
|
||||||
channel-type.sagercaster.forecast.state.option.L1 = Regengüsse und Abkühlung
|
forecastL1 = Regengüsse und Abkühlung
|
||||||
channel-type.sagercaster.forecast.state.option.L2 = Regengüsse und Abkühlung
|
forecastL2 = Regengüsse und Abkühlung
|
||||||
channel-type.sagercaster.forecast.state.option.M = Niederschlag
|
forecastM = Niederschlag
|
||||||
channel-type.sagercaster.forecast.state.option.N = Niederschlag und Erwärmung
|
forecastN = Niederschlag und Erwärmung
|
||||||
channel-type.sagercaster.forecast.state.option.P = Niederschlag und Abkühlung dann wahrscheinliche Besserung innerhalb von 24 Stunden
|
forecastP = Niederschlag und Abkühlung dann wahrscheinliche Besserung innerhalb von 24 Stunden
|
||||||
channel-type.sagercaster.forecast.state.option.R = Niederschlag oder Schauer / Schnee und Besserung innerhalb von 12 Stunden
|
forecastR = Niederschlag oder Schauer / Schnee und Besserung innerhalb von 12 Stunden
|
||||||
channel-type.sagercaster.forecast.state.option.R1 = Niederschlag oder Schauer und Besserung innerhalb von 12 Stunden
|
forecastR1 = Niederschlag oder Schauer und Besserung innerhalb von 12 Stunden
|
||||||
channel-type.sagercaster.forecast.state.option.R2 = Niederschlag oder Schnee und Besserung innerhalb von 12 Stunden
|
forecastR2 = Niederschlag oder Schnee und Besserung innerhalb von 12 Stunden
|
||||||
channel-type.sagercaster.forecast.state.option.S = Niederschlag oder Schauer / Schnee und Verbesserung innerhalb von 12 Stunden und Abkühlung
|
forecastS = Niederschlag oder Schauer / Schnee und Verbesserung innerhalb von 12 Stunden und Abkühlung
|
||||||
channel-type.sagercaster.forecast.state.option.S1 = Niederschlag oder Regengüsse und Besserung innerhalb von 12 Stunden und Erfrischung
|
forecastS1 = Niederschlag oder Regengüsse und Besserung innerhalb von 12 Stunden und Erfrischung
|
||||||
channel-type.sagercaster.forecast.state.option.S2 = Niederschlag oder Schnee und Verbesserung innerhalb von 12 Stunden und Abkühlung
|
forecastS2 = Niederschlag oder Schnee und Verbesserung innerhalb von 12 Stunden und Abkühlung
|
||||||
channel-type.sagercaster.forecast.state.option.T = Niederschlag oder Schauer / Schnee und schnelle Besserung innerhalb von 6 Stunden
|
forecastT = Niederschlag oder Schauer / Schnee und schnelle Besserung innerhalb von 6 Stunden
|
||||||
channel-type.sagercaster.forecast.state.option.T1 = Niederschlag oder Schauer und schnelle Besserung innerhalb von 6 Stunden
|
forecastT1 = Niederschlag oder Schauer und schnelle Besserung innerhalb von 6 Stunden
|
||||||
channel-type.sagercaster.forecast.state.option.T2 = Niederschlag oder Schnee und schnelle Besserung innerhalb von 6 Stunden
|
forecastT2 = Niederschlag oder Schnee und schnelle Besserung innerhalb von 6 Stunden
|
||||||
channel-type.sagercaster.forecast.state.option.U = Niederschlag oder Schauer / Schnee und schnelle Besserung innerhalb von 6 Stunden, dann Abkühlung
|
forecastU = Niederschlag oder Schauer / Schnee und schnelle Besserung innerhalb von 6 Stunden, dann Abkühlung
|
||||||
channel-type.sagercaster.forecast.state.option.U1 = Niederschlag oder Schauer und schnelle Besserung innerhalb von 6 Stunden, dann Abkühlung
|
forecastU1 = Niederschlag oder Schauer und schnelle Besserung innerhalb von 6 Stunden, dann Abkühlung
|
||||||
channel-type.sagercaster.forecast.state.option.U2 = Niederschlag oder Schnee und schnelle Besserung innerhalb von 6 Stunden, dann Abkühlung
|
forecastU2 = Niederschlag oder Schnee und schnelle Besserung innerhalb von 6 Stunden, dann Abkühlung
|
||||||
channel-type.sagercaster.forecast.state.option.W = Niederschlag oder Schauer / Schnee, gefolgt von gutem Wetter innerhalb von 6 Stunden und Erfrischung
|
forecastW = Niederschlag oder Schauer / Schnee, gefolgt von gutem Wetter innerhalb von 6 Stunden und Erfrischung
|
||||||
channel-type.sagercaster.forecast.state.option.W1 = Niederschlag oder Schauer, gefolgt von gutem Wetter innerhalb von 6 Stunden und Erfrischung
|
forecastW1 = Niederschlag oder Schauer, gefolgt von gutem Wetter innerhalb von 6 Stunden und Erfrischung
|
||||||
channel-type.sagercaster.forecast.state.option.W2 = Niederschlag oder Schnee, gefolgt von gutem Wetter innerhalb von 6 Stunden und Abkühlung
|
forecastW2 = Niederschlag oder Schnee, gefolgt von gutem Wetter innerhalb von 6 Stunden und Abkühlung
|
||||||
channel-type.sagercaster.forecast.state.option.X = Instabil, gefolgt von gutem Wetter
|
forecastX = Instabil, gefolgt von gutem Wetter
|
||||||
channel-type.sagercaster.forecast.state.option.Y = Instabil, gefolgt von gutem Wetter innerhalb von 6 Stunden und Erfrischung
|
forecastY = Instabil, gefolgt von gutem Wetter innerhalb von 6 Stunden und Erfrischung
|
||||||
|
|
||||||
channel-type.sagercaster.velocity.state.option.N = Wahrscheinlich steigend
|
velocityN = Wahrscheinlich steigend
|
||||||
channel-type.sagercaster.velocity.state.option.F = Mäßig bis frisch
|
velocityF = Mäßig bis frisch
|
||||||
channel-type.sagercaster.velocity.state.option.S = Starke Winde können dem Sturm im offenen Raum vorausgehen
|
velocityS = Starke Winde können dem Sturm im offenen Raum vorausgehen
|
||||||
channel-type.sagercaster.velocity.state.option.G = Sturm
|
velocityG = Sturm
|
||||||
channel-type.sagercaster.velocity.state.option.W = Gefährlicher Sturm
|
velocityW = Gefährlicher Sturm
|
||||||
channel-type.sagercaster.velocity.state.option.H = Orkan
|
velocityH = Orkan
|
||||||
channel-type.sagercaster.velocity.state.option.D = Abkühlend oder moderat, wenn die aktuellen Winde kühl oder stark sind
|
velocityD = Abkühlend oder moderat, wenn die aktuellen Winde kühl oder stark sind
|
||||||
channel-type.sagercaster.velocity.state.option.U = Keine wesentliche Änderung. Tendenz zur Zunahme während des Tages, Abnahme am Abend.
|
velocityU = Keine wesentliche Änderung. Tendenz zur Zunahme während des Tages, Abnahme am Abend.
|
||||||
|
|
||||||
channel-type.sagercaster.wind-evolution.state.option.1 = Stabil
|
evolution1 = Stabil
|
||||||
channel-type.sagercaster.wind-evolution.state.option.2 = Stätig
|
evolution2 = Stätig
|
||||||
channel-type.sagercaster.wind-evolution.state.option.3 = Variabel
|
evolution3 = Variabel
|
||||||
|
|
||||||
channel-type.sagercaster.trend.state.option.1 = Schneller Anstieg
|
|
||||||
channel-type.sagercaster.trend.state.option.2 = Langsamer Anstieg
|
|
||||||
channel-type.sagercaster.trend.state.option.3 = Stabil
|
|
||||||
channel-type.sagercaster.trend.state.option.4 = Mäßiger Rückgang
|
|
||||||
channel-type.sagercaster.trend.state.option.5 = Schneller Rückgang
|
|
||||||
|
|
||||||
|
trend1 = Schneller Anstieg
|
||||||
|
trend2 = Langsamer Anstieg
|
||||||
|
trend3 = Stabil
|
||||||
|
trend4 = Mäßiger Rückgang
|
||||||
|
trend5 = Schneller Rückgang
|
||||||
|
@ -1,64 +1,108 @@
|
|||||||
# binding
|
# binding
|
||||||
binding.sagercaster.name = Extension SagerCaster
|
bindingName = Extension SagerCaster
|
||||||
binding.sagercaster.description = L'extension SagerCaster permet d'établir des prévisions météo.
|
bindingDescription = Sager Weathercaster est un instrument scientifique pour produire des prédicitions météo précises.
|
||||||
|
|
||||||
|
# thing
|
||||||
|
sagercasterLabel = SagerCaster Thing
|
||||||
|
sagercasterDescription = Représente la prévision pour une localisation donnée.
|
||||||
|
|
||||||
|
# ting configuration
|
||||||
|
locationLabel = Emplacement
|
||||||
|
locationDescription = Vos coordonnées géographiques séparées par une virgule (p.e. "37.8,-122.4").
|
||||||
|
observationLabel = Période d'observation
|
||||||
|
observationDescription = Sager WeatherCaster requiert une période d'observation minimale pour produire des résultats significatifs (6 heures par défaut).
|
||||||
|
|
||||||
|
# channel groups
|
||||||
|
inputLabel = Entrées
|
||||||
|
inputDescription = Canaux utilisés pour produire des résultats de prévisions
|
||||||
|
outputLabel = Résultats
|
||||||
|
outputDescription = Résultats produits par l'algorithme Sager Weathercaster
|
||||||
|
|
||||||
|
# channels
|
||||||
|
windVelocity = Force du Vent
|
||||||
|
windFrom = Vent de
|
||||||
|
windTo = Vent vers
|
||||||
|
pressureTrendLabel = Tendance Pression
|
||||||
|
pressureTrendDescription = Evolution de la pression au cours de la période d'observation
|
||||||
|
tempTrendLabel = Tendance température
|
||||||
|
tempTrendDescription = Evolution de la température au cours de la période d'observation
|
||||||
|
forecastLabel = Prévision météo
|
||||||
|
windDirectionLabel = Direction du Vent
|
||||||
|
windEvolutionLabel = Evolution du Vent
|
||||||
|
windEvolutionDescription = Tendance de l'évolution du vent au cours de la période d'observation
|
||||||
|
trendLabel = Tendance
|
||||||
|
trendDescription = Evolution de la mesure au cours de la période d'observation
|
||||||
|
timestampLabel = Horodatage de la prévision
|
||||||
|
timestampDescription = Date et heure de calcul de la prévision météo.
|
||||||
|
cloudinessLabel = Nébulosité
|
||||||
|
cloudinessDescription = Qualification de la couverture nuageuse.
|
||||||
|
rainQttyLabel = Quantité de pluie
|
||||||
|
rainQttyDescription = Quantité d'eau tombée
|
||||||
|
rainingLabel = Pluie
|
||||||
|
rainingDescription = Pleut-il actuellement ?
|
||||||
|
beaufortLabel = Beaufort
|
||||||
|
beaufortDescription = Force du vent mesurée sur l'échelle Beaufort
|
||||||
|
pressureDescription = Pression barométrique au niveau de la mer.
|
||||||
|
|
||||||
# channel types
|
# channel types
|
||||||
channel-type.sagercaster.forecast.state.option.0 = Patientez encore un peu pour une prédiction
|
forecast0 = Patientez encore un peu pour une prédiction
|
||||||
channel-type.sagercaster.forecast.state.option.A = Beau-temps
|
forecastA = Beau-temps
|
||||||
channel-type.sagercaster.forecast.state.option.B = Beau-temps et réchauffement
|
forecastB = Beau-temps et réchauffement
|
||||||
channel-type.sagercaster.forecast.state.option.C = Beau-temps et rafraichissement
|
forecastC = Beau-temps et rafraichissement
|
||||||
channel-type.sagercaster.forecast.state.option.D = Instable
|
forecastD = Instable
|
||||||
channel-type.sagercaster.forecast.state.option.E = Instable et réchauffement
|
forecastE = Instable et réchauffement
|
||||||
channel-type.sagercaster.forecast.state.option.F = Instable et rafraichissement
|
forecastF = Instable et rafraichissement
|
||||||
channel-type.sagercaster.forecast.state.option.G = Nébulosité croissante ou très nuageux suivi de précititations ou averses / neige
|
forecastG = Nébulosité croissante ou très nuageux suivi de précipitations ou averses / neige
|
||||||
channel-type.sagercaster.forecast.state.option.G1 = Nébulosité croissante ou très nuageux suivi de précititations ou averses
|
forecastG1 = Nébulosité croissante ou très nuageux suivi de précipitations ou averses
|
||||||
channel-type.sagercaster.forecast.state.option.G2 = Nébulosité croissante ou très nuageux suivi de précititations ou neige
|
forecastG2 = Nébulosité croissante ou très nuageux suivi de précipitations ou neige
|
||||||
channel-type.sagercaster.forecast.state.option.H = Nébulosité croissante ou très nuageux suivi de précititations ou averses et réchauffement
|
forecastH = Nébulosité croissante ou très nuageux suivi de précipitations ou averses et réchauffement
|
||||||
channel-type.sagercaster.forecast.state.option.J = Averses
|
forecastJ = Averses
|
||||||
channel-type.sagercaster.forecast.state.option.K = Averses / neige et réchauffement
|
forecastK = Averses / neige et réchauffement
|
||||||
channel-type.sagercaster.forecast.state.option.K1 = Averses et réchauffement
|
forecastK1 = Averses et réchauffement
|
||||||
channel-type.sagercaster.forecast.state.option.K2 = Neige et réchauffement
|
forecastK2 = Neige et réchauffement
|
||||||
channel-type.sagercaster.forecast.state.option.L = Averses / neige et rafraichissement
|
forecastL = Averses / neige et rafraichissement
|
||||||
channel-type.sagercaster.forecast.state.option.L1 = Averses et rafraichissement
|
forecastL1 = Averses et rafraichissement
|
||||||
channel-type.sagercaster.forecast.state.option.L2 = Neige et rafraichissement
|
forecastL2 = Neige et rafraichissement
|
||||||
channel-type.sagercaster.forecast.state.option.M = Précipitations
|
forecastM = Précipitations
|
||||||
channel-type.sagercaster.forecast.state.option.N = Précipitations et réchauffement
|
forecastN = Précipitations et réchauffement
|
||||||
channel-type.sagercaster.forecast.state.option.P = Précipitations et rafraichissement puis amélioration probable dans les 24 heures
|
forecastP = Précipitations et rafraichissement puis amélioration probable dans les 24 heures
|
||||||
channel-type.sagercaster.forecast.state.option.R = Précipitations ou averses / neige et amélioration dans les 12 heures
|
forecastR = Précipitations ou averses / neige et amélioration dans les 12 heures
|
||||||
channel-type.sagercaster.forecast.state.option.R1 = Précipitations ou averses et amélioration dans les 12 heures
|
forecastR1 = Précipitations ou averses et amélioration dans les 12 heures
|
||||||
channel-type.sagercaster.forecast.state.option.R2 = Précipitations ou neige et amélioration dans les 12 heures
|
forecastR2 = Précipitations ou neige et amélioration dans les 12 heures
|
||||||
channel-type.sagercaster.forecast.state.option.S = Précipitations ou averses / neige et amélioration dans les 12 heures et rafraichissement
|
forecastS = Précipitations ou averses / neige et amélioration dans les 12 heures et rafraichissement
|
||||||
channel-type.sagercaster.forecast.state.option.S1 = Précipitations ou averses et amélioration dans les 12 heures et rafraichissement
|
forecastS1 = Précipitations ou averses et amélioration dans les 12 heures et rafraichissement
|
||||||
channel-type.sagercaster.forecast.state.option.S2 = Précipitations ou neige et amélioration dans les 12 heures et rafraichissement
|
forecastS2 = Précipitations ou neige et amélioration dans les 12 heures et rafraichissement
|
||||||
channel-type.sagercaster.forecast.state.option.T = Précipitations ou averses / neige et amélioration rapide dans les 6 heures
|
forecastT = Précipitations ou averses / neige et amélioration rapide dans les 6 heures
|
||||||
channel-type.sagercaster.forecast.state.option.T1 = Précipitations ou averses et amélioration rapide dans les 6 heures
|
forecastT1 = Précipitations ou averses et amélioration rapide dans les 6 heures
|
||||||
channel-type.sagercaster.forecast.state.option.T2 = Précipitations ou neige et amélioration rapide dans les 6 heures
|
forecastT2 = Précipitations ou neige et amélioration rapide dans les 6 heures
|
||||||
channel-type.sagercaster.forecast.state.option.U = Précipitations ou averses / neige et amélioration rapide dans les 6 heures puis rafraichissement
|
forecastU = Précipitations ou averses / neige et amélioration rapide dans les 6 heures puis rafraichissement
|
||||||
channel-type.sagercaster.forecast.state.option.U1 = Précipitations ou averses et amélioration rapide dans les 6 heures puis rafraichissement
|
forecastU1 = Précipitations ou averses et amélioration rapide dans les 6 heures puis rafraichissement
|
||||||
channel-type.sagercaster.forecast.state.option.U2 = Précipitations ou neige et amélioration rapide dans les 6 heures puis rafraichissement
|
forecastU2 = Précipitations ou neige et amélioration rapide dans les 6 heures puis rafraichissement
|
||||||
channel-type.sagercaster.forecast.state.option.W = Précipitations ou averses / neige suivi de beau temps rapide dans les 6 heures et rafraichissement
|
forecastW = Précipitations ou averses / neige suivi de beau temps rapide dans les 6 heures et rafraichissement
|
||||||
channel-type.sagercaster.forecast.state.option.W1 = Précipitations ou averses suivi de beau temps rapide dans les 6 heures et rafraichissement
|
forecastW1 = Précipitations ou averses suivi de beau temps rapide dans les 6 heures et rafraichissement
|
||||||
channel-type.sagercaster.forecast.state.option.W2 = Précipitations ou neige suivi de beau temps rapide dans les 6 heures et rafraichissement
|
forecastW2 = Précipitations ou neige suivi de beau temps rapide dans les 6 heures et rafraichissement
|
||||||
channel-type.sagercaster.forecast.state.option.X = Instable suivi de beau temps
|
forecastX = Instable suivi de beau temps
|
||||||
channel-type.sagercaster.forecast.state.option.Y = Instable suivi de beau temps rapide dans les 6 heures et rafraichissement
|
forecastY = Instable suivi de beau temps rapide dans les 6 heures et rafraichissement
|
||||||
|
|
||||||
channel-type.sagercaster.velocity.state.option.N = Probablement en augmentation
|
velocityN = Probablement en augmentation
|
||||||
channel-type.sagercaster.velocity.state.option.F = Modéré à frais
|
velocityF = Modéré à frais
|
||||||
channel-type.sagercaster.velocity.state.option.S = Vents forts pouvant précéder tempête en espace ouvert
|
velocityS = Vents forts pouvant précéder tempête en espace ouvert
|
||||||
channel-type.sagercaster.velocity.state.option.G = Tempête
|
velocityG = Tempête
|
||||||
channel-type.sagercaster.velocity.state.option.W = Tempête dangereuse
|
velocityW = Tempête dangereuse
|
||||||
channel-type.sagercaster.velocity.state.option.H = Ouragan
|
velocityH = Ouragan
|
||||||
channel-type.sagercaster.velocity.state.option.D = Décroissant ou en modération si les vents actuels sont frais ou forts
|
velocityD = Décroissant ou en modération si les vents actuels sont frais ou forts
|
||||||
channel-type.sagercaster.velocity.state.option.U = Pas de changement notable. Tendance pour augmentation progressive dans la journée, diminution dans la soirée.
|
velocityU = Pas de changement notable. Tendance pour augmentation progressive dans la journée, diminution dans la soirée.
|
||||||
|
|
||||||
channel-type.sagercaster.wind-evolution.state.option.1 = Stable
|
evolution1 = Stable
|
||||||
channel-type.sagercaster.wind-evolution.state.option.2 = Horaire
|
evolution2 = Horaire
|
||||||
channel-type.sagercaster.wind-evolution.state.option.3 = Anti-horaire
|
evolution3 = Anti-horaire
|
||||||
|
|
||||||
channel-type.sagercaster.trend.state.option.1 = Augmentation rapide
|
trend1 = Augmentation rapide
|
||||||
channel-type.sagercaster.trend.state.option.2 = Augmentation lente
|
trend2 = Augmentation lente
|
||||||
channel-type.sagercaster.trend.state.option.3 = Stable
|
trend3 = Stable
|
||||||
channel-type.sagercaster.trend.state.option.4 = Baisse modérée
|
trend4 = Baisse modérée
|
||||||
channel-type.sagercaster.trend.state.option.5 = Baisse rapide
|
trend5 = Baisse rapide
|
||||||
|
|
||||||
|
# Discovery result
|
||||||
|
discovery.sagercaster.sagercaster.local.label = Prévision Météo Locale
|
||||||
|
|
||||||
|
@ -5,9 +5,8 @@
|
|||||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||||
|
|
||||||
<thing-type id="sagercaster">
|
<thing-type id="sagercaster">
|
||||||
<label>SagerCaster Thing</label>
|
<label>@text/sagercasterLabel</label>
|
||||||
<description>This thing represents a forecast for a given location</description>
|
<description>@text/sagercasterDescription</description>
|
||||||
|
|
||||||
|
|
||||||
<channel-groups>
|
<channel-groups>
|
||||||
<channel-group id="input" typeId="input"/>
|
<channel-group id="input" typeId="input"/>
|
||||||
@ -19,226 +18,211 @@
|
|||||||
<config-description>
|
<config-description>
|
||||||
<parameter name="location" type="text" required="true"
|
<parameter name="location" type="text" required="true"
|
||||||
pattern="^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?)[,]\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$">
|
pattern="^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?)[,]\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$">
|
||||||
<label>Location</label>
|
<label>@text/locationLabel</label>
|
||||||
<context>location</context>
|
<context>location</context>
|
||||||
<description>Your geo coordinates separated with comma (e.g. "37.8,-122.4").</description>
|
<description>@text/locationDescription</description>
|
||||||
</parameter>
|
</parameter>
|
||||||
|
|
||||||
<parameter name="observation-period" type="integer" min="0" max="6" required="true">
|
<parameter name="observation-period" type="integer" min="0" max="6" required="true">
|
||||||
<label>Observation Period</label>
|
<label>@text/observationLabel</label>
|
||||||
<description>SagerWeatherCaster needs a minimum representative period of time to produce meaningfull results.
|
<description>@text/observationDescription</description>
|
||||||
Defaults to 6 hours</description>
|
|
||||||
<default>6</default>
|
<default>6</default>
|
||||||
</parameter>
|
</parameter>
|
||||||
|
|
||||||
</config-description>
|
</config-description>
|
||||||
</thing-type>
|
</thing-type>
|
||||||
|
|
||||||
|
|
||||||
<channel-group-type id="input">
|
<channel-group-type id="input">
|
||||||
<label>Inputs</label>
|
<label>@text/inputLabel</label>
|
||||||
<description>The channels used to build the forecast results</description>
|
<description>@text/inputDescription</description>
|
||||||
<channels>
|
<channels>
|
||||||
<channel id="cloudiness" typeId="cloudiness"/>
|
<channel id="cloudiness" typeId="cloudiness"/>
|
||||||
<channel id="is-raining" typeId="is-raining"/>
|
<channel id="is-raining" typeId="is-raining"/>
|
||||||
<channel id="rain-qtty" typeId="rain-qtty"/>
|
<channel id="rain-qtty" typeId="rain-qtty"/>
|
||||||
<channel id="wind-speed-beaufort" typeId="wind-speed-beaufort"/>
|
<channel id="wind-speed-beaufort" typeId="wind-speed-beaufort"/>
|
||||||
<channel id="pressure" typeId="pressure"/>
|
<channel id="pressure" typeId="system.barometric-pressure">
|
||||||
<channel id="temperature" typeId="temperature"/>
|
<label>@text/pressureDescription</label>
|
||||||
<channel id="wind-angle" typeId="wind-angle-rw"/>
|
</channel>
|
||||||
|
<channel id="temperature" typeId="system.outdoor-temperature"/>
|
||||||
|
<channel id="wind-angle" typeId="system.wind-direction"/>
|
||||||
</channels>
|
</channels>
|
||||||
</channel-group-type>
|
</channel-group-type>
|
||||||
|
|
||||||
<channel-group-type id="output">
|
<channel-group-type id="output">
|
||||||
<label>Results</label>
|
<label>@text/outputLabel</label>
|
||||||
<description>Results of the Sager Weathercaster algorithm</description>
|
<description>@text/outputDescription</description>
|
||||||
<channels>
|
<channels>
|
||||||
<channel id="forecast" typeId="forecast"/>
|
<channel id="forecast" typeId="forecast"/>
|
||||||
<channel id="velocity" typeId="velocity"/>
|
<channel id="velocity" typeId="velocity"/>
|
||||||
<channel id="velocity-beaufort" typeId="wind-speed-beaufort">
|
<channel id="velocity-beaufort" typeId="wind-speed-beaufort">
|
||||||
<label>Wind Velocity</label>
|
<label>@text/windVelocity</label>
|
||||||
</channel>
|
</channel>
|
||||||
<channel id="wind-from" typeId="wind-direction">
|
<channel id="wind-from" typeId="wind-direction">
|
||||||
<label>Wind From</label>
|
<label>@text/windFrom</label>
|
||||||
</channel>
|
</channel>
|
||||||
<channel id="wind-to" typeId="wind-direction">
|
<channel id="wind-to" typeId="wind-direction">
|
||||||
<label>Wind To</label>
|
<label>@text/windTo</label>
|
||||||
</channel>
|
</channel>
|
||||||
<channel id="wind-evolution" typeId="wind-evolution"/>
|
<channel id="wind-evolution" typeId="wind-evolution"/>
|
||||||
<channel id="pressure-trend" typeId="trend">
|
<channel id="pressure-trend" typeId="trend">
|
||||||
<label>Pressure Trend</label>
|
<label>@text/pressureTrendLabel</label>
|
||||||
<description>Pressure Evolution trend over observation delay</description>
|
<description>@text/pressureTrendDescription</description>
|
||||||
</channel>
|
</channel>
|
||||||
<channel id="temperature-trend" typeId="trend">
|
<channel id="temperature-trend" typeId="trend">
|
||||||
<label>Temperature Trend</label>
|
<label>@text/tempTrendLabel</label>
|
||||||
<description>Temperature Evolution trend over observation delay</description>
|
<description>@text/tempTrendDescription</description>
|
||||||
</channel>
|
</channel>
|
||||||
</channels>
|
</channels>
|
||||||
</channel-group-type>
|
</channel-group-type>
|
||||||
|
|
||||||
<channel-type id="forecast">
|
<channel-type id="forecast">
|
||||||
<item-type>String</item-type>
|
<item-type>String</item-type>
|
||||||
<label>Weather Forecast</label>
|
<label>@text/forecastLabel</label>
|
||||||
<state readOnly="true" pattern="%s">
|
<state readOnly="true" pattern="%s">
|
||||||
<options>
|
<options>
|
||||||
<option value="0">Not enough historic data to study pressure evolution, wait a bit ...</option>
|
<option value="0">@text/forecast0</option>
|
||||||
<option value="A">Fair</option>
|
<option value="A">@text/forecastA</option>
|
||||||
<option value="B">Fair and warmer</option>
|
<option value="B">@text/forecastB</option>
|
||||||
<option value="C">Fair and cooler</option>
|
<option value="C">@text/forecastC</option>
|
||||||
<option value="D">Unsettled</option>
|
<option value="D">@text/forecastD</option>
|
||||||
<option value="E">Unsettled and warmer</option>
|
<option value="E">@text/forecastE</option>
|
||||||
<option value="F">Unsettled and cooler</option>
|
<option value="F">@text/forecastF</option>
|
||||||
<option value="G">Increasing cloudiness or overcast followed by Precipitation or showers/Flurries</option>
|
<option value="G">@text/forecastG</option>
|
||||||
<option value="G1">Increasing cloudiness or overcast followed by Precipitation or showers</option>
|
<option value="G1">@text/forecastG1</option>
|
||||||
<option value="G2">Increasing cloudiness or overcast followed by Precipitation or Flurries</option>
|
<option value="G2">@text/forecastG2</option>
|
||||||
<option value="H">Increasing cloudiness or overcast followed by Precipitation or showers and warmer</option>
|
<option value="H">@text/forecastH</option>
|
||||||
<option value="J">Showers</option>
|
<option value="J">@text/forecastJ</option>
|
||||||
<option value="K">Showers/Flurries and warmer</option>
|
<option value="K">@text/forecastK</option>
|
||||||
<option value="K1">Showers and warmer</option>
|
<option value="K1">@text/forecastK1</option>
|
||||||
<option value="K2">Flurries and warmer</option>
|
<option value="K2">@text/forecastK2</option>
|
||||||
<option value="L">Showers/Flurries and cooler</option>
|
<option value="L">@text/forecastL</option>
|
||||||
<option value="L1">Showers and cooler</option>
|
<option value="L1">@text/forecastL1</option>
|
||||||
<option value="L2">Flurries and cooler</option>
|
<option value="L2">@text/forecastL2</option>
|
||||||
<option value="M">Precipitation</option>
|
<option value="M">@text/forecastM</option>
|
||||||
<option value="N">Precipitation and warmer</option>
|
<option value="N">@text/forecastN</option>
|
||||||
<option value="P">Precipitation and turning cooler; then improvement likely in 24 hours</option>
|
<option value="P">@text/forecastP</option>
|
||||||
<option value="R">Precipitation or showers/Flurries followed by improvement (within 12 hours)</option>
|
<option value="R">@text/forecastR</option>
|
||||||
<option value="R1">Precipitation or showers followed by improvement (within 12 hours)</option>
|
<option value="R1">@text/forecastR1</option>
|
||||||
<option value="R2">Precipitation or flurries followed by improvement (within 12 hours)</option>
|
<option value="R2">@text/forecastR2</option>
|
||||||
<option value="S">Precipitation or showers/Flurries followed by improvement (within 12 hours) and becoming cooler</option>
|
<option value="S">@text/forecastS</option>
|
||||||
<option value="S1">Precipitation or showers followed by improvement (within 12 hours) and becoming cooler</option>
|
<option value="S1">@text/forecastS1</option>
|
||||||
<option value="S2">Precipitation or flurries followed by improvement (within 12 hours) and becoming cooler</option>
|
<option value="S2">@text/forecastS2</option>
|
||||||
<option value="T">Precipitation or showers/Flurries followed by improvement early in period (within 6 hours)</option>
|
<option value="T">@text/forecastT</option>
|
||||||
<option value="T1">Precipitation or showers followed by improvement early in period (within 6 hours)</option>
|
<option value="T1">@text/forecastT1</option>
|
||||||
<option value="T2">Precipitation or flurries followed by improvement early in period (within 6 hours)</option>
|
<option value="T2">@text/forecastT2</option>
|
||||||
<option value="U">Precipitation or showers/Flurries by improvement early in period (within 6 hours) and becoming
|
<option value="U">@text/forecastU</option>
|
||||||
cooler</option>
|
<option value="U1">@text/forecastU1</option>
|
||||||
<option value="U1">Precipitation or showers by improvement early in period (within 6 hours) and becoming cooler</option>
|
<option value="U2">@text/forecastU2</option>
|
||||||
<option value="U2">Precipitation or flurries by improvement early in period (within 6 hours) and becoming cooler</option>
|
<option value="W">@text/forecastW</option>
|
||||||
<option value="W">Precipitation or showers/Flurries followed by fair early in period (within 6 hours) and
|
<option value="W1">@text/forecastW1</option>
|
||||||
becoming cooler</option>
|
<option value="W2">@text/forecastW2</option>
|
||||||
<option value="W1">Precipitation or showers followed by fair early in period (within 6 hours) and becoming cooler</option>
|
<option value="X">@text/forecastX</option>
|
||||||
<option value="W2">Precipitation or flurries followed by fair early in period (within 6 hours) and becoming cooler</option>
|
<option value="Y">@text/forecastY</option>
|
||||||
<option value="X">Unsettled followed by fair</option>
|
|
||||||
<option value="Y">Unsettled followed by fair early in period (within 6 hours) and becoming cooler</option>
|
|
||||||
</options>
|
</options>
|
||||||
</state>
|
</state>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
|
||||||
<channel-type id="velocity">
|
<channel-type id="velocity">
|
||||||
<item-type>String</item-type>
|
<item-type>String</item-type>
|
||||||
<label>Wind Velocity</label>
|
<label>@text/windVelocity</label>
|
||||||
<state readOnly="true" pattern="%s">
|
<state readOnly="true" pattern="%s">
|
||||||
<options>
|
<options>
|
||||||
<option value="N">Probably increasing</option>
|
<option value="N">@text/velocityN</option>
|
||||||
<option value="F">Moderate to fresh</option>
|
<option value="F">@text/velocityF</option>
|
||||||
<option value="S">Strong winds may precede gales over open water)</option>
|
<option value="S">@text/velocityS</option>
|
||||||
<option value="G">Gale</option>
|
<option value="G">@text/velocityG</option>
|
||||||
<option value="W">Dangerous gale (whole gale)</option>
|
<option value="W">@text/velocityW</option>
|
||||||
<option value="H">Hurricane</option>
|
<option value="H">@text/velocityH</option>
|
||||||
<option value="D">Diminishing, or moderating somewhat if current winds are of fresh to strong velocity</option>
|
<option value="D">@text/velocityD</option>
|
||||||
<option value="U">No important change. Some tendency for slight increase in winds during day, diminishing in
|
<option value="U">@text/velocityU</option>
|
||||||
evening</option>
|
|
||||||
</options>
|
</options>
|
||||||
</state>
|
</state>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
|
||||||
<channel-type id="wind-direction">
|
<channel-type id="wind-direction">
|
||||||
<item-type>String</item-type>
|
<item-type>String</item-type>
|
||||||
<label>Wind Direction</label>
|
<label>@text/windDirectionLabel</label>
|
||||||
<description>Wind direction</description>
|
|
||||||
<category>Wind</category>
|
<category>Wind</category>
|
||||||
<state readOnly="true" pattern="%s"/>
|
<state readOnly="true" pattern="%s"/>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
|
||||||
<channel-type id="wind-angle-rw">
|
|
||||||
<item-type>Number:Angle</item-type>
|
|
||||||
<label>Wind Angle</label>
|
|
||||||
<description>Wind Angle</description>
|
|
||||||
<category>Wind</category>
|
|
||||||
<state readOnly="false" pattern="%.0f %unit%"/>
|
|
||||||
</channel-type>
|
|
||||||
|
|
||||||
<channel-type id="wind-evolution" advanced="true">
|
<channel-type id="wind-evolution" advanced="true">
|
||||||
<item-type>String</item-type>
|
<item-type>String</item-type>
|
||||||
<label>Wind Evolution</label>
|
<label>@text/windEvolutionLabel</label>
|
||||||
<description>Wind bearing evolution trend over observation delay</description>
|
<description>@text/windEvolutionDescription</description>
|
||||||
<state readOnly="true" pattern="%s">
|
<state readOnly="true" pattern="%s">
|
||||||
<options>
|
<options>
|
||||||
<option value="1">Steady</option>
|
<option value="1">@text/evolution1</option>
|
||||||
<option value="2">Veering</option>
|
<option value="2">@text/evolution2</option>
|
||||||
<option value="3">Backing</option>
|
<option value="3">@text/evolution3</option>
|
||||||
</options>
|
</options>
|
||||||
</state>
|
</state>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
|
||||||
<channel-type id="trend" advanced="true">
|
<channel-type id="trend" advanced="true">
|
||||||
<item-type>String</item-type>
|
<item-type>String</item-type>
|
||||||
<label>Measure Trend</label>
|
<label>@text/trendLabel</label>
|
||||||
<description>Measure evolution trend over observation delay</description>
|
<description>@text/trendDescription</description>
|
||||||
<state readOnly="true" pattern="%s">
|
<state readOnly="true" pattern="%s">
|
||||||
<options>
|
<options>
|
||||||
<option value="1">Rising Rapidly</option>
|
<option value="1">@text/trend1</option>
|
||||||
<option value="2">Rising Slowly</option>
|
<option value="2">@text/trend2</option>
|
||||||
<option value="3">Normal</option>
|
<option value="3">@text/trend3</option>
|
||||||
<option value="4">Decreasing Slowly</option>
|
<option value="4">@text/trend4</option>
|
||||||
<option value="5">Decreasing Rapidly</option>
|
<option value="5">@text/trend5</option>
|
||||||
</options>
|
</options>
|
||||||
</state>
|
</state>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
|
||||||
<channel-type id="timestamp" advanced="true">
|
<channel-type id="timestamp" advanced="true">
|
||||||
<item-type>DateTime</item-type>
|
<item-type>DateTime</item-type>
|
||||||
<label>Calculation Time</label>
|
<label>@text/timestampLabel</label>
|
||||||
<description>Weather forecast calculation date and time</description>
|
<description>@text/timestampDescription</description>
|
||||||
<category>Observation time</category>
|
<category>Observation time</category>
|
||||||
<state readOnly="true"></state>
|
<state readOnly="true"></state>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
|
||||||
<channel-type id="cloudiness">
|
<channel-type id="cloudiness">
|
||||||
<item-type>Number:Dimensionless</item-type>
|
<item-type>Number:Dimensionless</item-type>
|
||||||
<label>Cloudiness</label>
|
<label>@text/cloudinessLabel</label>
|
||||||
<description>Current cloudiness.</description>
|
<description>@text/cloudinessDescription</description>
|
||||||
<category>Clouds</category>
|
<category>Clouds</category>
|
||||||
<state min="0" max="100" pattern="%d %%"/>
|
<state min="0" max="100" pattern="%d %%"/>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
|
||||||
<channel-type id="rain-qtty" advanced="true">
|
<channel-type id="rain-qtty" advanced="true">
|
||||||
<item-type>Number</item-type>
|
<item-type>Number</item-type>
|
||||||
<label>Rain Quantity</label>
|
<label>@text/rainQttyLabel</label>
|
||||||
<description>Current rain quantity</description>
|
<description>@text/rainQttyDescription</description>
|
||||||
<category>Rain</category>
|
<category>Rain</category>
|
||||||
|
<tags>
|
||||||
|
<tag>Measurement</tag>
|
||||||
|
<tag>Rain</tag>
|
||||||
|
</tags>
|
||||||
<state pattern="%.2f %unit%"/>
|
<state pattern="%.2f %unit%"/>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
|
||||||
<channel-type id="is-raining">
|
<channel-type id="is-raining">
|
||||||
<item-type>Switch</item-type>
|
<item-type>Switch</item-type>
|
||||||
<label>Raining</label>
|
<label>@text/rainingLabel</label>
|
||||||
<description>Is it currently raining ?</description>
|
<description>@text/rainingDescription</description>
|
||||||
<category>Rain</category>
|
<category>Rain</category>
|
||||||
|
<tags>
|
||||||
|
<tag>Status</tag>
|
||||||
|
<tag>Rain</tag>
|
||||||
|
</tags>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
|
||||||
<channel-type id="wind-speed-beaufort">
|
<channel-type id="wind-speed-beaufort">
|
||||||
<item-type>Number</item-type>
|
<item-type>Number</item-type>
|
||||||
<label>Beaufort</label>
|
<label>@text/beaufortLabel</label>
|
||||||
<description>Wind speed using Beaufort Scale</description>
|
<description>@text/beaufortDescription</description>
|
||||||
<category>Wind</category>
|
<category>Wind</category>
|
||||||
|
<tags>
|
||||||
|
<tag>Measurement</tag>
|
||||||
|
<tag>Wind</tag>
|
||||||
|
</tags>
|
||||||
<state min="0" max="12" pattern="%d"/>
|
<state min="0" max="12" pattern="%d"/>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
|
||||||
<channel-type id="pressure">
|
|
||||||
<item-type>Number:Pressure</item-type>
|
|
||||||
<label>Sea Level Pressure</label>
|
|
||||||
<description>Sea Level Pressure</description>
|
|
||||||
<category>Pressure</category>
|
|
||||||
<state pattern="%.3f %unit%"/>
|
|
||||||
</channel-type>
|
|
||||||
|
|
||||||
<channel-type id="temperature">
|
|
||||||
<item-type>Number:Temperature</item-type>
|
|
||||||
<label>Temperature</label>
|
|
||||||
<description>Current temperature</description>
|
|
||||||
<category>Temperature</category>
|
|
||||||
<state pattern="%.1f %unit%"/>
|
|
||||||
</channel-type>
|
|
||||||
</thing:thing-descriptions>
|
</thing:thing-descriptions>
|
||||||
|
Loading…
Reference in New Issue
Block a user