[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:
Gaël L'hopital 2021-10-21 21:10:00 +02:00 committed by GitHub
parent 054518e345
commit 48fd525dea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 473 additions and 358 deletions

View File

@ -12,6 +12,8 @@
*/
package org.openhab.binding.sagercaster.internal;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
@ -35,7 +37,6 @@ public class SagerCasterBindingConstants {
public static final String CONFIG_PERIOD = "observation-period";
// List of all Channel Groups Group Channel ids
public static final String GROUP_INPUT = "input";
public static final String GROUP_OUTPUT = "output";
// Output channel ids
@ -55,4 +56,8 @@ public class SagerCasterBindingConstants {
public static final String CHANNEL_TEMPERATURE = "temperature";
public static final String CHANNEL_PRESSURE = "pressure";
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");
}

View File

@ -58,9 +58,8 @@ public class SagerCasterHandlerFactory extends BaseThingHandlerFactory {
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (thingTypeUID.equals(THING_TYPE_SAGERCASTER)) {
return new SagerCasterHandler(thing, stateDescriptionProvider, sagerWeatherCaster);
}
return null;
return thingTypeUID.equals(THING_TYPE_SAGERCASTER)
? new SagerCasterHandler(thing, stateDescriptionProvider, sagerWeatherCaster)
: null;
}
}

View File

@ -76,8 +76,6 @@ import org.slf4j.LoggerFactory;
@Component(service = SagerWeatherCaster.class, scope = ServiceScope.SINGLETON)
@NonNullByDefault
public class SagerWeatherCaster {
private final Properties forecaster = new Properties();
// Northern Polar Zone & Northern Tropical Zone
private final static String[] NPZDIRECTIONS = { "S", "SW", "W", "NW", "N", "NE", "E", "SE" };
// 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 Logger logger = LoggerFactory.getLogger(SagerWeatherCaster.class);
private final Properties forecaster = new Properties();
private Optional<Prevision> prevision = Optional.empty();
private @NonNullByDefault({}) String[] usedDirections;
private String[] usedDirections = NTZDIRECTIONS; // Defaulted to Northern Zone
private int currentBearing = -1;
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
public SagerWeatherCaster() {
InputStream input = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("/sagerForecaster.properties");
try {
try (InputStream input = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("/sagerForecaster.properties")) {
forecaster.load(input);
} catch (IOException e) {
logger.warn("Error during Sager Forecaster startup", e);
@ -120,9 +118,9 @@ public class SagerWeatherCaster {
public void setBearing(int newBearing, int oldBearing) {
int windEvol = sagerWindTrend(oldBearing, newBearing);
if ((windEvol != this.windEvolution) || (newBearing != currentBearing)) {
this.currentBearing = newBearing;
this.windEvolution = windEvol;
if ((windEvol != windEvolution) || (newBearing != currentBearing)) {
currentBearing = newBearing;
windEvolution = windEvol;
updatePrediction();
}
}
@ -130,40 +128,40 @@ public class SagerWeatherCaster {
public void setPressure(double newPressure, double oldPressure) {
int newSagerPressure = sagerPressureLevel(newPressure);
int pressEvol = sagerPressureTrend(newPressure, oldPressure);
if ((pressEvol != this.pressureEvolution) || (newSagerPressure != sagerPressure)) {
this.sagerPressure = newSagerPressure;
this.pressureEvolution = pressEvol;
if ((pressEvol != pressureEvolution) || (newSagerPressure != sagerPressure)) {
sagerPressure = newSagerPressure;
pressureEvolution = pressEvol;
updatePrediction();
}
}
public void setCloudLevel(int cloudiness) {
this.cloudLevel = cloudiness;
cloudLevel = cloudiness;
sagerNubesUpdate();
}
public void setRaining(boolean raining) {
this.raining = raining;
public void setRaining(boolean isRaining) {
raining = isRaining;
sagerNubesUpdate();
}
public void setBeaufort(int beaufortIndex) {
if (currentBeaufort != beaufortIndex) {
this.currentBeaufort = beaufortIndex;
currentBeaufort = beaufortIndex;
updatePrediction();
}
}
public int getBeaufort() {
return this.currentBeaufort;
return currentBeaufort;
}
public int getWindEvolution() {
return this.windEvolution;
return windEvolution;
}
public int getPressureEvolution() {
return this.pressureEvolution;
return pressureEvolution;
}
private void sagerNubesUpdate() {
@ -182,50 +180,43 @@ public class SagerWeatherCaster {
result = 5; // raining
}
if (result != nubes) {
this.nubes = result;
nubes = result;
updatePrediction();
}
}
private static int sagerPressureLevel(double current) {
int result = 1;
if (current > 1029.46) {
result = 1;
return 1;
} else if (current > 1019.3) {
result = 2;
return 2;
} else if (current > 1012.53) {
result = 3;
return 3;
} else if (current > 1005.76) {
result = 4;
return 4;
} else if (current > 999) {
result = 5;
return 5;
} else if (current > 988.8) {
result = 6;
return 6;
} else if (current > 975.28) {
result = 7;
} else {
result = 8;
return 7;
}
return result;
return 8;
}
private static int sagerPressureTrend(double current, double historic) {
double evol = current - historic;
int result = 0;
if (evol > 1.4) {
result = 1; // Rising Rapidly
return 1; // Rising Rapidly
} else if (evol > 0.68) {
result = 2; // Rising Slowly
return 2; // Rising Slowly
} else if (evol > -0.68) {
result = 3; // Normal
return 3; // Normal
} else if (evol > -1.4) {
result = 4; // Decreasing Slowly
} else {
result = 5; // Decreasing Rapidly
return 4; // Decreasing Slowly
}
return result;
return 5; // Decreasing Rapidly
}
private static int sagerWindTrend(double historic, double position) {
@ -241,7 +232,7 @@ public class SagerWeatherCaster {
private String getCompass() {
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)];
}
@ -335,36 +326,32 @@ public class SagerWeatherCaster {
if (prevision.isPresent()) {
char forecast = prevision.get().zForecast;
return Character.toString(forecast);
} else {
return "-";
}
return "-";
}
public String getWindVelocity() {
if (prevision.isPresent()) {
char windVelocity = prevision.get().zWindVelocity;
return Character.toString(windVelocity);
} else {
return "-";
}
return "-";
}
public String getWindDirection() {
if (prevision.isPresent()) {
int direction = prevision.get().zWindDirection;
return String.valueOf(direction);
} else {
return "-";
}
return "-";
}
public String getWindDirection2() {
if (prevision.isPresent()) {
int direction = prevision.get().zWindDirection2;
return String.valueOf(direction);
} else {
return "-";
}
return "-";
}
public void setLatitude(double latitude) {

View File

@ -14,10 +14,9 @@ package org.openhab.binding.sagercaster.internal.discovery;
import static org.openhab.binding.sagercaster.internal.SagerCasterBindingConstants.*;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ScheduledFuture;
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.DiscoveryResultBuilder;
import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.i18n.LocaleProvider;
import org.openhab.core.i18n.LocationProvider;
import org.openhab.core.i18n.TranslationProvider;
import org.openhab.core.library.types.PointType;
import org.openhab.core.thing.ThingTypeUID;
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;
@ -43,20 +44,26 @@ import org.slf4j.LoggerFactory;
@NonNullByDefault
@Component(service = DiscoveryService.class, configurationPid = "discovery.sagercaster")
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 LOCATION_CHANGED_CHECK_INTERVAL = 60;
private @NonNullByDefault({}) LocationProvider locationProvider;
private @NonNullByDefault({}) ScheduledFuture<?> sagerCasterDiscoveryJob;
private @Nullable PointType previousLocation;
private static final ThingUID SAGER_CASTER_THING = new ThingUID(THING_TYPE_SAGERCASTER, LOCAL);
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.
*/
public SagerCasterDiscoveryService() {
super(new HashSet<>(Arrays.asList(new ThingTypeUID(BINDING_ID, "-"))), DISCOVER_TIMEOUT_SECONDS, true);
@Activate
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
@ -82,8 +89,8 @@ public class SagerCasterDiscoveryService extends AbstractDiscoveryService {
@Override
protected void startBackgroundDiscovery() {
if (sagerCasterDiscoveryJob == null) {
sagerCasterDiscoveryJob = scheduler.scheduleWithFixedDelay(() -> {
if (discoveryJob == null) {
discoveryJob = scheduler.scheduleWithFixedDelay(() -> {
PointType currentLocation = locationProvider.getLocation();
if (currentLocation != null && !Objects.equals(currentLocation, previousLocation)) {
logger.debug("Location has been changed from {} to {}: Creating new discovery results",
@ -99,28 +106,19 @@ public class SagerCasterDiscoveryService extends AbstractDiscoveryService {
@Override
protected void stopBackgroundDiscovery() {
ScheduledFuture<?> localJob = discoveryJob;
logger.debug("Stopping Sager Weathercaster background discovery");
if (sagerCasterDiscoveryJob != null && !sagerCasterDiscoveryJob.isCancelled()) {
if (sagerCasterDiscoveryJob.cancel(true)) {
sagerCasterDiscoveryJob = null;
if (localJob != null && !localJob.isCancelled()) {
if (localJob.cancel(true)) {
discoveryJob = null;
logger.debug("Stopped SagerCaster device background discovery");
}
}
}
public void createResults(PointType location) {
String propGeolocation;
propGeolocation = String.format("%s,%s", location.getLatitude(), location.getLongitude());
thingDiscovered(DiscoveryResultBuilder.create(sagerCasterThing).withLabel("Local Sager Weathercaster")
String propGeolocation = String.format("%s,%s", location.getLatitude(), location.getLongitude());
thingDiscovered(DiscoveryResultBuilder.create(SAGER_CASTER_THING).withLabel("Local Weather Forecast")
.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;
}
}

View File

@ -37,11 +37,10 @@ class ExpiringMap<T> {
public void put(T newValue) {
long now = System.currentTimeMillis();
values.put(now, newValue);
Optional<Long> eldestKey = values.keySet().stream().filter(key -> key < now - eldestAge).findFirst();
if (eldestKey.isPresent()) {
agedValue = Optional.ofNullable(values.get(eldestKey.get()));
values.entrySet().removeIf(map -> map.getKey() <= eldestKey.get());
}
values.keySet().stream().filter(key -> key < now - eldestAge).findFirst().ifPresent(eldest -> {
agedValue = Optional.ofNullable(values.get(eldest));
values.entrySet().removeIf(map -> map.getKey() <= eldest);
});
}
public Optional<T> getAgedValue() {

View File

@ -17,16 +17,11 @@ import static org.openhab.core.library.unit.MetricPrefix.HECTO;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.measure.quantity.Angle;
import javax.measure.quantity.Dimensionless;
import javax.measure.quantity.Pressure;
import javax.measure.quantity.Temperature;
@ -56,19 +51,19 @@ import org.slf4j.LoggerFactory;
*/
@NonNullByDefault
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 SagerWeatherCaster sagerWeatherCaster;
private final WindDirectionStateDescriptionProvider stateDescriptionProvider;
private int currentTemp = 0;
private final ExpiringMap<QuantityType<Pressure>> pressureCache = new ExpiringMap<>();
private final ExpiringMap<QuantityType<Temperature>> temperatureCache = new ExpiringMap<>();
private final ExpiringMap<QuantityType<Angle>> bearingCache = new ExpiringMap<>();
private int currentTemp = 0;
public SagerCasterHandler(Thing thing, WindDirectionStateDescriptionProvider stateDescriptionProvider,
SagerWeatherCaster sagerWeatherCaster) {
super(thing);
@ -82,7 +77,7 @@ public class SagerCasterHandler extends BaseThingHandler {
int observationPeriod = ((BigDecimal) getConfig().get(CONFIG_PERIOD)).intValue();
String latitude = location.split(",")[0];
sagerWeatherCaster.setLatitude(Double.parseDouble(latitude));
long period = TimeUnit.SECONDS.toMillis(observationPeriod);
long period = TimeUnit.HOURS.toMillis(observationPeriod);
pressureCache.setObservationPeriod(period);
bearingCache.setObservationPeriod(period);
temperatureCache.setObservationPeriod(period);
@ -116,8 +111,7 @@ public class SagerCasterHandler extends BaseThingHandler {
case CHANNEL_CLOUDINESS:
logger.debug("Octa cloud level changed, updating forecast");
if (command instanceof QuantityType) {
@SuppressWarnings("unchecked")
QuantityType<Dimensionless> cloudiness = (QuantityType<Dimensionless>) command;
QuantityType<?> cloudiness = (QuantityType<?>) command;
scheduler.submit(() -> {
sagerWeatherCaster.setCloudLevel(cloudiness.intValue());
postNewForecast();
@ -127,7 +121,7 @@ public class SagerCasterHandler extends BaseThingHandler {
case CHANNEL_IS_RAINING:
logger.debug("Rain status updated, updating forecast");
if (command instanceof OnOffType) {
OnOffType isRaining = ((OnOffType) command);
OnOffType isRaining = (OnOffType) command;
scheduler.submit(() -> {
sagerWeatherCaster.setRaining(isRaining == OnOffType.ON);
postNewForecast();
@ -139,13 +133,13 @@ public class SagerCasterHandler extends BaseThingHandler {
case CHANNEL_RAIN_QTTY:
logger.debug("Rain status updated, updating forecast");
if (command instanceof QuantityType) {
QuantityType<?> newQtty = ((QuantityType<?>) command);
QuantityType<?> newQtty = (QuantityType<?>) command;
scheduler.submit(() -> {
sagerWeatherCaster.setRaining(newQtty.doubleValue() > 0);
postNewForecast();
});
} else if (command instanceof DecimalType) {
DecimalType newQtty = ((DecimalType) command);
DecimalType newQtty = (DecimalType) command;
scheduler.submit(() -> {
sagerWeatherCaster.setRaining(newQtty.doubleValue() > 0);
postNewForecast();
@ -175,18 +169,12 @@ public class SagerCasterHandler extends BaseThingHandler {
.toUnit(HECTO(SIUnits.PASCAL));
if (newPressure != null) {
pressureCache.put(newPressure);
Optional<QuantityType<Pressure>> agedPressure = pressureCache.getAgedValue();
if (agedPressure.isPresent()) {
scheduler.submit(() -> {
sagerWeatherCaster.setPressure(newPressure.doubleValue(),
agedPressure.get().doubleValue());
pressureCache.getAgedValue().ifPresentOrElse(pressure -> scheduler.submit(() -> {
sagerWeatherCaster.setPressure(newPressure.doubleValue(), pressure.doubleValue());
updateChannelString(GROUP_OUTPUT, CHANNEL_PRESSURETREND,
String.valueOf(sagerWeatherCaster.getPressureEvolution()));
postNewForecast();
});
} else {
updateChannelString(GROUP_OUTPUT, CHANNEL_FORECAST, FORECAST_PENDING);
}
}), () -> updateChannelString(GROUP_OUTPUT, CHANNEL_FORECAST, FORECAST_PENDING));
}
}
break;
@ -200,12 +188,12 @@ public class SagerCasterHandler extends BaseThingHandler {
temperatureCache.put(newTemperature);
currentTemp = newTemperature.intValue();
Optional<QuantityType<Temperature>> agedTemperature = temperatureCache.getAgedValue();
if (agedTemperature.isPresent()) {
double delta = newTemperature.doubleValue() - agedTemperature.get().doubleValue();
agedTemperature.ifPresent(temperature -> {
double delta = newTemperature.doubleValue() - temperature.doubleValue();
String trend = (delta > 3) ? "1"
: (delta > 0.3) ? "2" : (delta > -0.3) ? "3" : (delta > -3) ? "4" : "5";
updateChannelString(GROUP_OUTPUT, CHANNEL_TEMPERATURETREND, trend);
}
});
}
}
break;
@ -216,14 +204,14 @@ public class SagerCasterHandler extends BaseThingHandler {
QuantityType<Angle> newAngle = (QuantityType<Angle>) command;
bearingCache.put(newAngle);
Optional<QuantityType<Angle>> agedAngle = bearingCache.getAgedValue();
if (agedAngle.isPresent()) {
agedAngle.ifPresent(angle -> {
scheduler.submit(() -> {
sagerWeatherCaster.setBearing(newAngle.intValue(), agedAngle.get().intValue());
sagerWeatherCaster.setBearing(newAngle.intValue(), angle.intValue());
updateChannelString(GROUP_OUTPUT, CHANNEL_WINDEVOLUTION,
String.valueOf(sagerWeatherCaster.getWindEvolution()));
postNewForecast();
});
}
});
}
break;
default:
@ -270,14 +258,14 @@ public class SagerCasterHandler extends BaseThingHandler {
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);
if (isLinked(id)) {
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);
if (isLinked(id)) {
updateState(id, new DecimalType(value));

View File

@ -3,7 +3,7 @@
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">
<name>SagerCaster Binding</name>
<description>The Sager Weathercaster is a scientific instrument for accurate prediction of the weather.</description>
<name>@text/bindingName</name>
<description>@text/bindingDescription</description>
</binding:binding>

View File

@ -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

View File

@ -1,63 +1,66 @@
# binding
binding.sagercaster.name = SagerCaster Binding
binding.sagercaster.description = Die SagerCaster-Erweiterung wird zur Erstellung von Wettervorhersagen verwendet.
bindingName = SagerCaster Binding
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-type.sagercaster.forecast.state.option.0 = Warten Sie etwas länger auf eine Vorhersage
channel-type.sagercaster.forecast.state.option.A = Gutes Wetter
channel-type.sagercaster.forecast.state.option.B = Gutes Wetter und Erwärmung
channel-type.sagercaster.forecast.state.option.C = Gutes Wetter und Abkühlung
channel-type.sagercaster.forecast.state.option.D = Instabil
channel-type.sagercaster.forecast.state.option.E = Instabil und Erwärmung
channel-type.sagercaster.forecast.state.option.F = Instabil und Abkühlung
channel-type.sagercaster.forecast.state.option.G = 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
channel-type.sagercaster.forecast.state.option.G2 = 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
channel-type.sagercaster.forecast.state.option.J = Regengüsse
channel-type.sagercaster.forecast.state.option.K = Regengüsse / Schnee und Erwärmung
channel-type.sagercaster.forecast.state.option.K1 = Regengüsse und Erwärmung
channel-type.sagercaster.forecast.state.option.K2 = Schnee und Erwärmung
channel-type.sagercaster.forecast.state.option.L = Regengüsse / Schnee und Abkühlung
channel-type.sagercaster.forecast.state.option.L1 = Regengüsse und Abkühlung
channel-type.sagercaster.forecast.state.option.L2 = Regengüsse und Abkühlung
channel-type.sagercaster.forecast.state.option.M = Niederschlag
channel-type.sagercaster.forecast.state.option.N = Niederschlag und Erwärmung
channel-type.sagercaster.forecast.state.option.P = 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
channel-type.sagercaster.forecast.state.option.R1 = 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
channel-type.sagercaster.forecast.state.option.S = 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
channel-type.sagercaster.forecast.state.option.S2 = 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
channel-type.sagercaster.forecast.state.option.T1 = 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
channel-type.sagercaster.forecast.state.option.U = 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
channel-type.sagercaster.forecast.state.option.U2 = 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
channel-type.sagercaster.forecast.state.option.W1 = 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
channel-type.sagercaster.forecast.state.option.X = Instabil, gefolgt von gutem Wetter
channel-type.sagercaster.forecast.state.option.Y = Instabil, gefolgt von gutem Wetter innerhalb von 6 Stunden und Erfrischung
forecast0 = Warten Sie etwas länger auf eine Vorhersage
forecastA = Gutes Wetter
forecastB = Gutes Wetter und Erwärmung
forecastC = Gutes Wetter und Abkühlung
forecastD = Instabil
forecastE = Instabil und Erwärmung
forecastF = Instabil und Abkühlung
forecastG = Zunehmende Bewölkung oder sehr bewölkt, gefolgt von Niederschlag oder Schauern / Schnee
forecastG1 = Zunehmende oder sehr trübe Bewölkung, gefolgt von Niederschlag oder Schauern
forecastG2 = Zunehmende Bewölkung oder sehr bewölkt, gefolgt von Niederschlag oder Schnee
forecastH = Zunehmende Bewölkung oder sehr bewölkt, gefolgt von Niederschlag oder Schauern und Erwärmung
forecastJ = Regengüsse
forecastK = Regengüsse / Schnee und Erwärmung
forecastK1 = Regengüsse und Erwärmung
forecastK2 = Schnee und Erwärmung
forecastL = Regengüsse / Schnee und Abkühlung
forecastL1 = Regengüsse und Abkühlung
forecastL2 = Regengüsse und Abkühlung
forecastM = Niederschlag
forecastN = Niederschlag und Erwärmung
forecastP = Niederschlag und Abkühlung dann wahrscheinliche Besserung innerhalb von 24 Stunden
forecastR = Niederschlag oder Schauer / Schnee und Besserung innerhalb von 12 Stunden
forecastR1 = Niederschlag oder Schauer und Besserung innerhalb von 12 Stunden
forecastR2 = Niederschlag oder Schnee und Besserung innerhalb von 12 Stunden
forecastS = Niederschlag oder Schauer / Schnee und Verbesserung innerhalb von 12 Stunden und Abkühlung
forecastS1 = Niederschlag oder Regengüsse und Besserung innerhalb von 12 Stunden und Erfrischung
forecastS2 = Niederschlag oder Schnee und Verbesserung innerhalb von 12 Stunden und Abkühlung
forecastT = Niederschlag oder Schauer / Schnee und schnelle Besserung innerhalb von 6 Stunden
forecastT1 = Niederschlag oder Schauer und schnelle Besserung innerhalb von 6 Stunden
forecastT2 = Niederschlag oder Schnee und schnelle Besserung innerhalb von 6 Stunden
forecastU = Niederschlag oder Schauer / Schnee und schnelle Besserung innerhalb von 6 Stunden, dann Abkühlung
forecastU1 = Niederschlag oder Schauer und schnelle Besserung innerhalb von 6 Stunden, dann Abkühlung
forecastU2 = Niederschlag oder Schnee und schnelle Besserung innerhalb von 6 Stunden, dann Abkühlung
forecastW = Niederschlag oder Schauer / Schnee, gefolgt von gutem Wetter innerhalb von 6 Stunden und Erfrischung
forecastW1 = Niederschlag oder Schauer, gefolgt von gutem Wetter innerhalb von 6 Stunden und Erfrischung
forecastW2 = Niederschlag oder Schnee, gefolgt von gutem Wetter innerhalb von 6 Stunden und Abkühlung
forecastX = Instabil, gefolgt von gutem Wetter
forecastY = Instabil, gefolgt von gutem Wetter innerhalb von 6 Stunden und Erfrischung
channel-type.sagercaster.velocity.state.option.N = Wahrscheinlich steigend
channel-type.sagercaster.velocity.state.option.F = Mäßig bis frisch
channel-type.sagercaster.velocity.state.option.S = Starke Winde können dem Sturm im offenen Raum vorausgehen
channel-type.sagercaster.velocity.state.option.G = Sturm
channel-type.sagercaster.velocity.state.option.W = Gefährlicher Sturm
channel-type.sagercaster.velocity.state.option.H = Orkan
channel-type.sagercaster.velocity.state.option.D = 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.
velocityN = Wahrscheinlich steigend
velocityF = Mäßig bis frisch
velocityS = Starke Winde können dem Sturm im offenen Raum vorausgehen
velocityG = Sturm
velocityW = Gefährlicher Sturm
velocityH = Orkan
velocityD = Abkühlend oder moderat, wenn die aktuellen Winde kühl oder stark sind
velocityU = Keine wesentliche Änderung. Tendenz zur Zunahme während des Tages, Abnahme am Abend.
channel-type.sagercaster.wind-evolution.state.option.1 = Stabil
channel-type.sagercaster.wind-evolution.state.option.2 = Stätig
channel-type.sagercaster.wind-evolution.state.option.3 = 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
evolution1 = Stabil
evolution2 = Stätig
evolution3 = Variabel
trend1 = Schneller Anstieg
trend2 = Langsamer Anstieg
trend3 = Stabil
trend4 = Mäßiger Rückgang
trend5 = Schneller Rückgang

View File

@ -1,64 +1,108 @@
# binding
binding.sagercaster.name = Extension SagerCaster
binding.sagercaster.description = L'extension SagerCaster permet d'établir des prévisions météo.
bindingName = Extension SagerCaster
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-type.sagercaster.forecast.state.option.0 = Patientez encore un peu pour une prédiction
channel-type.sagercaster.forecast.state.option.A = Beau-temps
channel-type.sagercaster.forecast.state.option.B = Beau-temps et réchauffement
channel-type.sagercaster.forecast.state.option.C = Beau-temps et rafraichissement
channel-type.sagercaster.forecast.state.option.D = Instable
channel-type.sagercaster.forecast.state.option.E = Instable et réchauffement
channel-type.sagercaster.forecast.state.option.F = Instable et rafraichissement
channel-type.sagercaster.forecast.state.option.G = Nébulosité croissante ou très nuageux suivi de précititations ou averses / neige
channel-type.sagercaster.forecast.state.option.G1 = Nébulosité croissante ou très nuageux suivi de précititations ou averses
channel-type.sagercaster.forecast.state.option.G2 = Nébulosité croissante ou très nuageux suivi de précititations 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
channel-type.sagercaster.forecast.state.option.J = Averses
channel-type.sagercaster.forecast.state.option.K = Averses / neige et réchauffement
channel-type.sagercaster.forecast.state.option.K1 = Averses et réchauffement
channel-type.sagercaster.forecast.state.option.K2 = Neige et réchauffement
channel-type.sagercaster.forecast.state.option.L = Averses / neige et rafraichissement
channel-type.sagercaster.forecast.state.option.L1 = Averses et rafraichissement
channel-type.sagercaster.forecast.state.option.L2 = Neige et rafraichissement
channel-type.sagercaster.forecast.state.option.M = Précipitations
channel-type.sagercaster.forecast.state.option.N = Précipitations et réchauffement
channel-type.sagercaster.forecast.state.option.P = 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
channel-type.sagercaster.forecast.state.option.R1 = 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
channel-type.sagercaster.forecast.state.option.S = 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
channel-type.sagercaster.forecast.state.option.S2 = 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
channel-type.sagercaster.forecast.state.option.T1 = 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
channel-type.sagercaster.forecast.state.option.U = 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
channel-type.sagercaster.forecast.state.option.U2 = 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
channel-type.sagercaster.forecast.state.option.W1 = 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
channel-type.sagercaster.forecast.state.option.X = Instable suivi de beau temps
channel-type.sagercaster.forecast.state.option.Y = Instable suivi de beau temps rapide dans les 6 heures et rafraichissement
forecast0 = Patientez encore un peu pour une prédiction
forecastA = Beau-temps
forecastB = Beau-temps et réchauffement
forecastC = Beau-temps et rafraichissement
forecastD = Instable
forecastE = Instable et réchauffement
forecastF = Instable et rafraichissement
forecastG = Nébulosité croissante ou très nuageux suivi de précipitations ou averses / neige
forecastG1 = Nébulosité croissante ou très nuageux suivi de précipitations ou averses
forecastG2 = Nébulosité croissante ou très nuageux suivi de précipitations ou neige
forecastH = Nébulosité croissante ou très nuageux suivi de précipitations ou averses et réchauffement
forecastJ = Averses
forecastK = Averses / neige et réchauffement
forecastK1 = Averses et réchauffement
forecastK2 = Neige et réchauffement
forecastL = Averses / neige et rafraichissement
forecastL1 = Averses et rafraichissement
forecastL2 = Neige et rafraichissement
forecastM = Précipitations
forecastN = Précipitations et réchauffement
forecastP = Précipitations et rafraichissement puis amélioration probable dans les 24 heures
forecastR = Précipitations ou averses / neige et amélioration dans les 12 heures
forecastR1 = Précipitations ou averses et amélioration dans les 12 heures
forecastR2 = Précipitations ou neige et amélioration dans les 12 heures
forecastS = Précipitations ou averses / neige et amélioration dans les 12 heures et rafraichissement
forecastS1 = Précipitations ou averses et amélioration dans les 12 heures et rafraichissement
forecastS2 = Précipitations ou neige et amélioration dans les 12 heures et rafraichissement
forecastT = Précipitations ou averses / neige et amélioration rapide dans les 6 heures
forecastT1 = Précipitations ou averses et amélioration rapide dans les 6 heures
forecastT2 = Précipitations ou neige et amélioration rapide dans les 6 heures
forecastU = Précipitations ou averses / neige 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
forecastU2 = Précipitations ou neige et amélioration rapide dans les 6 heures puis rafraichissement
forecastW = Précipitations ou averses / neige 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
forecastW2 = Précipitations ou neige suivi de beau temps rapide dans les 6 heures et rafraichissement
forecastX = Instable suivi de beau temps
forecastY = Instable suivi de beau temps rapide dans les 6 heures et rafraichissement
channel-type.sagercaster.velocity.state.option.N = Probablement en augmentation
channel-type.sagercaster.velocity.state.option.F = Modéré à frais
channel-type.sagercaster.velocity.state.option.S = Vents forts pouvant précéder tempête en espace ouvert
channel-type.sagercaster.velocity.state.option.G = Tempête
channel-type.sagercaster.velocity.state.option.W = Tempête dangereuse
channel-type.sagercaster.velocity.state.option.H = Ouragan
channel-type.sagercaster.velocity.state.option.D = 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.
velocityN = Probablement en augmentation
velocityF = Modéré à frais
velocityS = Vents forts pouvant précéder tempête en espace ouvert
velocityG = Tempête
velocityW = Tempête dangereuse
velocityH = Ouragan
velocityD = Décroissant ou en modération si les vents actuels sont frais ou forts
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
channel-type.sagercaster.wind-evolution.state.option.2 = Horaire
channel-type.sagercaster.wind-evolution.state.option.3 = Anti-horaire
evolution1 = Stable
evolution2 = Horaire
evolution3 = Anti-horaire
channel-type.sagercaster.trend.state.option.1 = Augmentation rapide
channel-type.sagercaster.trend.state.option.2 = Augmentation lente
channel-type.sagercaster.trend.state.option.3 = Stable
channel-type.sagercaster.trend.state.option.4 = Baisse modérée
channel-type.sagercaster.trend.state.option.5 = Baisse rapide
trend1 = Augmentation rapide
trend2 = Augmentation lente
trend3 = Stable
trend4 = Baisse modérée
trend5 = Baisse rapide
# Discovery result
discovery.sagercaster.sagercaster.local.label = Prévision Météo Locale

View File

@ -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">
<thing-type id="sagercaster">
<label>SagerCaster Thing</label>
<description>This thing represents a forecast for a given location</description>
<label>@text/sagercasterLabel</label>
<description>@text/sagercasterDescription</description>
<channel-groups>
<channel-group id="input" typeId="input"/>
@ -19,226 +18,211 @@
<config-description>
<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+)?)$">
<label>Location</label>
<label>@text/locationLabel</label>
<context>location</context>
<description>Your geo coordinates separated with comma (e.g. "37.8,-122.4").</description>
<description>@text/locationDescription</description>
</parameter>
<parameter name="observation-period" type="integer" min="0" max="6" required="true">
<label>Observation Period</label>
<description>SagerWeatherCaster needs a minimum representative period of time to produce meaningfull results.
Defaults to 6 hours</description>
<label>@text/observationLabel</label>
<description>@text/observationDescription</description>
<default>6</default>
</parameter>
</config-description>
</thing-type>
<channel-group-type id="input">
<label>Inputs</label>
<description>The channels used to build the forecast results</description>
<label>@text/inputLabel</label>
<description>@text/inputDescription</description>
<channels>
<channel id="cloudiness" typeId="cloudiness"/>
<channel id="is-raining" typeId="is-raining"/>
<channel id="rain-qtty" typeId="rain-qtty"/>
<channel id="wind-speed-beaufort" typeId="wind-speed-beaufort"/>
<channel id="pressure" typeId="pressure"/>
<channel id="temperature" typeId="temperature"/>
<channel id="wind-angle" typeId="wind-angle-rw"/>
<channel id="pressure" typeId="system.barometric-pressure">
<label>@text/pressureDescription</label>
</channel>
<channel id="temperature" typeId="system.outdoor-temperature"/>
<channel id="wind-angle" typeId="system.wind-direction"/>
</channels>
</channel-group-type>
<channel-group-type id="output">
<label>Results</label>
<description>Results of the Sager Weathercaster algorithm</description>
<label>@text/outputLabel</label>
<description>@text/outputDescription</description>
<channels>
<channel id="forecast" typeId="forecast"/>
<channel id="velocity" typeId="velocity"/>
<channel id="velocity-beaufort" typeId="wind-speed-beaufort">
<label>Wind Velocity</label>
<label>@text/windVelocity</label>
</channel>
<channel id="wind-from" typeId="wind-direction">
<label>Wind From</label>
<label>@text/windFrom</label>
</channel>
<channel id="wind-to" typeId="wind-direction">
<label>Wind To</label>
<label>@text/windTo</label>
</channel>
<channel id="wind-evolution" typeId="wind-evolution"/>
<channel id="pressure-trend" typeId="trend">
<label>Pressure Trend</label>
<description>Pressure Evolution trend over observation delay</description>
<label>@text/pressureTrendLabel</label>
<description>@text/pressureTrendDescription</description>
</channel>
<channel id="temperature-trend" typeId="trend">
<label>Temperature Trend</label>
<description>Temperature Evolution trend over observation delay</description>
<label>@text/tempTrendLabel</label>
<description>@text/tempTrendDescription</description>
</channel>
</channels>
</channel-group-type>
<channel-type id="forecast">
<item-type>String</item-type>
<label>Weather Forecast</label>
<label>@text/forecastLabel</label>
<state readOnly="true" pattern="%s">
<options>
<option value="0">Not enough historic data to study pressure evolution, wait a bit ...</option>
<option value="A">Fair</option>
<option value="B">Fair and warmer</option>
<option value="C">Fair and cooler</option>
<option value="D">Unsettled</option>
<option value="E">Unsettled and warmer</option>
<option value="F">Unsettled and cooler</option>
<option value="G">Increasing cloudiness or overcast followed by Precipitation or showers/Flurries</option>
<option value="G1">Increasing cloudiness or overcast followed by Precipitation or showers</option>
<option value="G2">Increasing cloudiness or overcast followed by Precipitation or Flurries</option>
<option value="H">Increasing cloudiness or overcast followed by Precipitation or showers and warmer</option>
<option value="J">Showers</option>
<option value="K">Showers/Flurries and warmer</option>
<option value="K1">Showers and warmer</option>
<option value="K2">Flurries and warmer</option>
<option value="L">Showers/Flurries and cooler</option>
<option value="L1">Showers and cooler</option>
<option value="L2">Flurries and cooler</option>
<option value="M">Precipitation</option>
<option value="N">Precipitation and warmer</option>
<option value="P">Precipitation and turning cooler; then improvement likely in 24 hours</option>
<option value="R">Precipitation or showers/Flurries followed by improvement (within 12 hours)</option>
<option value="R1">Precipitation or showers followed by improvement (within 12 hours)</option>
<option value="R2">Precipitation or flurries followed by improvement (within 12 hours)</option>
<option value="S">Precipitation or showers/Flurries followed by improvement (within 12 hours) and becoming cooler</option>
<option value="S1">Precipitation or showers followed by improvement (within 12 hours) and becoming cooler</option>
<option value="S2">Precipitation or flurries followed by improvement (within 12 hours) and becoming cooler</option>
<option value="T">Precipitation or showers/Flurries followed by improvement early in period (within 6 hours)</option>
<option value="T1">Precipitation or showers followed by improvement early in period (within 6 hours)</option>
<option value="T2">Precipitation or flurries followed by improvement early in period (within 6 hours)</option>
<option value="U">Precipitation or showers/Flurries by improvement early in period (within 6 hours) and becoming
cooler</option>
<option value="U1">Precipitation or showers by improvement early in period (within 6 hours) and becoming cooler</option>
<option value="U2">Precipitation or flurries by improvement early in period (within 6 hours) and becoming cooler</option>
<option value="W">Precipitation or showers/Flurries followed by fair early in period (within 6 hours) and
becoming cooler</option>
<option value="W1">Precipitation or showers followed by fair early in period (within 6 hours) and becoming cooler</option>
<option value="W2">Precipitation or flurries followed by fair early in period (within 6 hours) and becoming cooler</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>
<option value="0">@text/forecast0</option>
<option value="A">@text/forecastA</option>
<option value="B">@text/forecastB</option>
<option value="C">@text/forecastC</option>
<option value="D">@text/forecastD</option>
<option value="E">@text/forecastE</option>
<option value="F">@text/forecastF</option>
<option value="G">@text/forecastG</option>
<option value="G1">@text/forecastG1</option>
<option value="G2">@text/forecastG2</option>
<option value="H">@text/forecastH</option>
<option value="J">@text/forecastJ</option>
<option value="K">@text/forecastK</option>
<option value="K1">@text/forecastK1</option>
<option value="K2">@text/forecastK2</option>
<option value="L">@text/forecastL</option>
<option value="L1">@text/forecastL1</option>
<option value="L2">@text/forecastL2</option>
<option value="M">@text/forecastM</option>
<option value="N">@text/forecastN</option>
<option value="P">@text/forecastP</option>
<option value="R">@text/forecastR</option>
<option value="R1">@text/forecastR1</option>
<option value="R2">@text/forecastR2</option>
<option value="S">@text/forecastS</option>
<option value="S1">@text/forecastS1</option>
<option value="S2">@text/forecastS2</option>
<option value="T">@text/forecastT</option>
<option value="T1">@text/forecastT1</option>
<option value="T2">@text/forecastT2</option>
<option value="U">@text/forecastU</option>
<option value="U1">@text/forecastU1</option>
<option value="U2">@text/forecastU2</option>
<option value="W">@text/forecastW</option>
<option value="W1">@text/forecastW1</option>
<option value="W2">@text/forecastW2</option>
<option value="X">@text/forecastX</option>
<option value="Y">@text/forecastY</option>
</options>
</state>
</channel-type>
<channel-type id="velocity">
<item-type>String</item-type>
<label>Wind Velocity</label>
<label>@text/windVelocity</label>
<state readOnly="true" pattern="%s">
<options>
<option value="N">Probably increasing</option>
<option value="F">Moderate to fresh</option>
<option value="S">Strong winds may precede gales over open water)</option>
<option value="G">Gale</option>
<option value="W">Dangerous gale (whole gale)</option>
<option value="H">Hurricane</option>
<option value="D">Diminishing, or moderating somewhat if current winds are of fresh to strong velocity</option>
<option value="U">No important change. Some tendency for slight increase in winds during day, diminishing in
evening</option>
<option value="N">@text/velocityN</option>
<option value="F">@text/velocityF</option>
<option value="S">@text/velocityS</option>
<option value="G">@text/velocityG</option>
<option value="W">@text/velocityW</option>
<option value="H">@text/velocityH</option>
<option value="D">@text/velocityD</option>
<option value="U">@text/velocityU</option>
</options>
</state>
</channel-type>
<channel-type id="wind-direction">
<item-type>String</item-type>
<label>Wind Direction</label>
<description>Wind direction</description>
<label>@text/windDirectionLabel</label>
<category>Wind</category>
<state readOnly="true" pattern="%s"/>
</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">
<item-type>String</item-type>
<label>Wind Evolution</label>
<description>Wind bearing evolution trend over observation delay</description>
<label>@text/windEvolutionLabel</label>
<description>@text/windEvolutionDescription</description>
<state readOnly="true" pattern="%s">
<options>
<option value="1">Steady</option>
<option value="2">Veering</option>
<option value="3">Backing</option>
<option value="1">@text/evolution1</option>
<option value="2">@text/evolution2</option>
<option value="3">@text/evolution3</option>
</options>
</state>
</channel-type>
<channel-type id="trend" advanced="true">
<item-type>String</item-type>
<label>Measure Trend</label>
<description>Measure evolution trend over observation delay</description>
<label>@text/trendLabel</label>
<description>@text/trendDescription</description>
<state readOnly="true" pattern="%s">
<options>
<option value="1">Rising Rapidly</option>
<option value="2">Rising Slowly</option>
<option value="3">Normal</option>
<option value="4">Decreasing Slowly</option>
<option value="5">Decreasing Rapidly</option>
<option value="1">@text/trend1</option>
<option value="2">@text/trend2</option>
<option value="3">@text/trend3</option>
<option value="4">@text/trend4</option>
<option value="5">@text/trend5</option>
</options>
</state>
</channel-type>
<channel-type id="timestamp" advanced="true">
<item-type>DateTime</item-type>
<label>Calculation Time</label>
<description>Weather forecast calculation date and time</description>
<label>@text/timestampLabel</label>
<description>@text/timestampDescription</description>
<category>Observation time</category>
<state readOnly="true"></state>
</channel-type>
<channel-type id="cloudiness">
<item-type>Number:Dimensionless</item-type>
<label>Cloudiness</label>
<description>Current cloudiness.</description>
<label>@text/cloudinessLabel</label>
<description>@text/cloudinessDescription</description>
<category>Clouds</category>
<state min="0" max="100" pattern="%d %%"/>
</channel-type>
<channel-type id="rain-qtty" advanced="true">
<item-type>Number</item-type>
<label>Rain Quantity</label>
<description>Current rain quantity</description>
<label>@text/rainQttyLabel</label>
<description>@text/rainQttyDescription</description>
<category>Rain</category>
<tags>
<tag>Measurement</tag>
<tag>Rain</tag>
</tags>
<state pattern="%.2f %unit%"/>
</channel-type>
<channel-type id="is-raining">
<item-type>Switch</item-type>
<label>Raining</label>
<description>Is it currently raining ?</description>
<label>@text/rainingLabel</label>
<description>@text/rainingDescription</description>
<category>Rain</category>
<tags>
<tag>Status</tag>
<tag>Rain</tag>
</tags>
</channel-type>
<channel-type id="wind-speed-beaufort">
<item-type>Number</item-type>
<label>Beaufort</label>
<description>Wind speed using Beaufort Scale</description>
<label>@text/beaufortLabel</label>
<description>@text/beaufortDescription</description>
<category>Wind</category>
<tags>
<tag>Measurement</tag>
<tag>Wind</tag>
</tags>
<state min="0" max="12" pattern="%d"/>
</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>