[Sagercaster] Reintroducing timestamp channel (#11665)

[Sagercaster] Reintroducing timestamp channel 

Signed-off-by: clinique <gael@lhopital.org>
This commit is contained in:
Gaël L'hopital 2021-12-04 16:55:48 +01:00 committed by GitHub
parent 13bae622ac
commit 4605edeb29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 190 additions and 131 deletions

View File

@ -6,7 +6,8 @@ The Sager Weathercaster is a scientific instrument for accurate prediction of th
* To operate, this binding will need to use channel values provided by other means (e.g. Weather Binding, Netatmo, a 1-Wire personal weather station...) * To operate, this binding will need to use channel values provided by other means (e.g. Weather Binding, Netatmo, a 1-Wire personal weather station...)
* This binding buffers readings for some hours before producing weather forecasts(wind direction and sea level pressure). SagerWeatherCaster needs an observation period of minimum 6 hours. * This binding buffers readings for some hours before producing weather forecasts(wind direction and sea level pressure).
SagerWeatherCaster needs an observation period of minimum 6 hours.
For these reasons, this binding is not a binding in the usual sense. For these reasons, this binding is not a binding in the usual sense.
@ -24,9 +25,11 @@ The binding itself does not require any configuration.
| Name | Type | Description | | Name | Type | Description |
|--------------------|----------|--------------------------------------------------------------------------| |--------------------|----------|--------------------------------------------------------------------------|
| location | Location | Latitude and longitude of the desired weather forecast. | | location (*) | Location | Latitude and longitude of the desired weather forecast. |
| observation-period | int | Minimum delay (in hours) before producing forecasts. Defaulted to 6. | | observation-period | int | Minimum delay (in hours) before producing forecasts. Defaulted to 6. |
(*) Only latitude is used by the algorithm.
## Channels ## Channels
The binding will use some input channels, that can be configured directly with profiles (sample below). The binding will use some input channels, that can be configured directly with profiles (sample below).
@ -41,6 +44,8 @@ The binding will use some input channels, that can be configured directly with p
| wind-speed-beaufort | input |Number | Wind speed expressed using the Beaufort scale | | wind-speed-beaufort | input |Number | Wind speed expressed using the Beaufort scale |
| pressure | input |Number:Pressure | Sea level pressure | | pressure | input |Number:Pressure | Sea level pressure |
| wind-angle | input |Number:Angle | Wind direction | | wind-angle | input |Number:Angle | Wind direction |
| temperature | input |Number:Temperature | Outside temperature |
| timestamp | output |DateTime | Timestamp of the last forecast update |
| forecast | output |String | Description of the weather forecast | | forecast | output |String | Description of the weather forecast |
| velocity | output |String | Description of the expected wind evolution | | velocity | output |String | Description of the expected wind evolution |
| velocity-beaufort | output |Number | Expected wind evolution using the Beaufort scale | | velocity-beaufort | output |Number | Expected wind evolution using the Beaufort scale |

View File

@ -48,6 +48,8 @@ public class SagerCasterBindingConstants {
public static final String CHANNEL_WINDEVOLUTION = "wind-evolution"; public static final String CHANNEL_WINDEVOLUTION = "wind-evolution";
public static final String CHANNEL_PRESSURETREND = "pressure-trend"; public static final String CHANNEL_PRESSURETREND = "pressure-trend";
public static final String CHANNEL_TEMPERATURETREND = "temperature-trend"; public static final String CHANNEL_TEMPERATURETREND = "temperature-trend";
public static final String CHANNEL_TIMESTAMP = "timestamp";
// Input channel ids // Input channel ids
public static final String CHANNEL_CLOUDINESS = "cloudiness"; public static final String CHANNEL_CLOUDINESS = "cloudiness";
public static final String CHANNEL_IS_RAINING = "is-raining"; public static final String CHANNEL_IS_RAINING = "is-raining";

View File

@ -19,6 +19,7 @@ import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.sagercaster.internal.caster.SagerWeatherCaster;
import org.openhab.binding.sagercaster.internal.handler.SagerCasterHandler; import org.openhab.binding.sagercaster.internal.handler.SagerCasterHandler;
import org.openhab.core.thing.Thing; import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.ThingTypeUID;

View File

@ -0,0 +1,49 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.sagercaster.internal.caster;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* This class holds the result of the SagerCaster algorithm
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public class SagerPrediction {
private final String prediction;
public SagerPrediction(String sagerCode) {
this.prediction = sagerCode;
}
public String getSagerCode() {
return prediction;
}
public String getForecast() {
return Character.toString(prediction.charAt(0));
}
public String getWindVelocity() {
return Character.toString(prediction.charAt(1));
}
public String getWindDirection() {
return Character.toString(prediction.charAt(2));
}
public String getWindDirection2() {
return prediction.length() > 3 ? Character.toString(prediction.charAt(3)) : SagerWeatherCaster.UNDEF;
}
}

View File

@ -53,7 +53,7 @@
* 378 possible forecasts determined from 4996 dial codes. * 378 possible forecasts determined from 4996 dial codes.
*/ */
package org.openhab.binding.sagercaster.internal; package org.openhab.binding.sagercaster.internal.caster;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -76,6 +76,7 @@ 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 {
public final static String UNDEF = "-";
// 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,7 +89,7 @@ public class SagerWeatherCaster {
private final Logger logger = LoggerFactory.getLogger(SagerWeatherCaster.class); private final Logger logger = LoggerFactory.getLogger(SagerWeatherCaster.class);
private final Properties forecaster = new Properties(); private final Properties forecaster = new Properties();
private Optional<Prevision> prevision = Optional.empty(); private Optional<SagerPrediction> prevision = Optional.empty();
private String[] usedDirections = NTZDIRECTIONS; // Defaulted to Northern Zone private String[] usedDirections = NTZDIRECTIONS; // Defaulted to Northern Zone
private int currentBearing = -1; private int currentBearing = -1;
@ -238,7 +239,7 @@ public class SagerWeatherCaster {
private void updatePrediction() { private void updatePrediction() {
int zWind = Arrays.asList(usedDirections).indexOf(getCompass()); int zWind = Arrays.asList(usedDirections).indexOf(getCompass());
String d1 = "-"; String d1 = UNDEF;
switch (zWind) { switch (zWind) {
case 0: case 0:
if (windEvolution == 3) { if (windEvolution == 3) {
@ -319,39 +320,27 @@ public class SagerWeatherCaster {
} }
String forecast = forecaster.getProperty( String forecast = forecaster.getProperty(
d1 + String.valueOf(sagerPressure) + String.valueOf(pressureEvolution) + String.valueOf(nubes)); d1 + String.valueOf(sagerPressure) + String.valueOf(pressureEvolution) + String.valueOf(nubes));
prevision = (forecast != null) ? Optional.of(new Prevision(forecast)) : Optional.empty(); prevision = Optional.ofNullable(forecast != null ? new SagerPrediction(forecast) : null);
} }
public String getForecast() { public String getForecast() {
if (prevision.isPresent()) { return prevision.map(p -> p.getForecast()).orElse(UNDEF);
char forecast = prevision.get().zForecast;
return Character.toString(forecast);
}
return "-";
} }
public String getWindVelocity() { public String getWindVelocity() {
if (prevision.isPresent()) { return prevision.map(p -> p.getWindVelocity()).orElse(UNDEF);
char windVelocity = prevision.get().zWindVelocity;
return Character.toString(windVelocity);
}
return "-";
} }
public String getWindDirection() { public String getWindDirection() {
if (prevision.isPresent()) { return prevision.map(p -> p.getWindDirection()).orElse(UNDEF);
int direction = prevision.get().zWindDirection;
return String.valueOf(direction);
}
return "-";
} }
public String getWindDirection2() { public String getWindDirection2() {
if (prevision.isPresent()) { return prevision.map(p -> p.getWindDirection2()).orElse(UNDEF);
int direction = prevision.get().zWindDirection2;
return String.valueOf(direction);
} }
return "-";
public String getSagerCode() {
return prevision.map(p -> p.getSagerCode()).orElse(UNDEF);
} }
public void setLatitude(double latitude) { public void setLatitude(double latitude) {
@ -370,17 +359,31 @@ public class SagerWeatherCaster {
} }
} }
private class Prevision { public int getPredictedBeaufort() {
public final char zForecast; int result = currentBeaufort;
public final char zWindVelocity; switch (getWindVelocity()) {
public final int zWindDirection; case "N":
public final int zWindDirection2; result += 1;
break;
public Prevision(String forecast) { case "F":
zForecast = forecast.charAt(0); result = 4;
zWindVelocity = forecast.charAt(1); break;
zWindDirection = Character.getNumericValue(forecast.charAt(2)); case "S":
zWindDirection2 = (forecast.length() > 3) ? Character.getNumericValue(forecast.charAt(3)) : -1; result = 6;
} break;
case "G":
result = 8;
break;
case "W":
result = 10;
break;
case "H":
result = 12;
break;
case "D":
result -= 1;
break;
}
return result;
} }
} }

View File

@ -16,9 +16,9 @@ import static org.openhab.binding.sagercaster.internal.SagerCasterBindingConstan
import static org.openhab.core.library.unit.MetricPrefix.HECTO; import static org.openhab.core.library.unit.MetricPrefix.HECTO;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.ZonedDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.measure.quantity.Angle; import javax.measure.quantity.Angle;
@ -26,8 +26,9 @@ import javax.measure.quantity.Pressure;
import javax.measure.quantity.Temperature; import javax.measure.quantity.Temperature;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.sagercaster.internal.SagerWeatherCaster;
import org.openhab.binding.sagercaster.internal.WindDirectionStateDescriptionProvider; import org.openhab.binding.sagercaster.internal.WindDirectionStateDescriptionProvider;
import org.openhab.binding.sagercaster.internal.caster.SagerWeatherCaster;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.QuantityType;
@ -36,6 +37,7 @@ import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing; import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.BaseThingHandler; import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.types.Command; import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType; import org.openhab.core.types.RefreshType;
@ -58,11 +60,12 @@ public class SagerCasterHandler extends BaseThingHandler {
private final WindDirectionStateDescriptionProvider stateDescriptionProvider; private final WindDirectionStateDescriptionProvider stateDescriptionProvider;
private final ExpiringMap<QuantityType<Pressure>> pressureCache = new ExpiringMap<>(); private final ExpiringMap<Double> pressureCache = new ExpiringMap<>();
private final ExpiringMap<QuantityType<Temperature>> temperatureCache = new ExpiringMap<>(); private final ExpiringMap<Double> temperatureCache = new ExpiringMap<>();
private final ExpiringMap<QuantityType<Angle>> bearingCache = new ExpiringMap<>(); private final ExpiringMap<Integer> bearingCache = new ExpiringMap<>();
private int currentTemp = 0; private double currentTemp = 0;
private String currentSagerCode = SagerWeatherCaster.UNDEF;
public SagerCasterHandler(Thing thing, WindDirectionStateDescriptionProvider stateDescriptionProvider, public SagerCasterHandler(Thing thing, WindDirectionStateDescriptionProvider stateDescriptionProvider,
SagerWeatherCaster sagerWeatherCaster) { SagerWeatherCaster sagerWeatherCaster) {
@ -73,15 +76,17 @@ public class SagerCasterHandler extends BaseThingHandler {
@Override @Override
public void initialize() { public void initialize() {
String location = (String) getConfig().get(CONFIG_LOCATION);
int observationPeriod = ((BigDecimal) getConfig().get(CONFIG_PERIOD)).intValue(); int observationPeriod = ((BigDecimal) getConfig().get(CONFIG_PERIOD)).intValue();
String latitude = location.split(",")[0];
sagerWeatherCaster.setLatitude(Double.parseDouble(latitude));
long period = TimeUnit.HOURS.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);
String location = (String) getConfig().get(CONFIG_LOCATION);
String latitude = location.split(",")[0];
sagerWeatherCaster.setLatitude(Double.parseDouble(latitude));
defineWindDirectionStateDescriptions(); defineWindDirectionStateDescriptions();
updateStatus(ThingStatus.ONLINE); updateStatus(ThingStatus.ONLINE);
} }
@ -95,10 +100,9 @@ public class SagerCasterHandler extends BaseThingHandler {
} }
options.add(new StateOption("9", "Shifting / Variable winds")); options.add(new StateOption("9", "Shifting / Variable winds"));
stateDescriptionProvider.setStateOptions(new ChannelUID(getThing().getUID(), GROUP_OUTPUT, CHANNEL_WINDFROM), ThingUID thingUID = getThing().getUID();
options); stateDescriptionProvider.setStateOptions(new ChannelUID(thingUID, GROUP_OUTPUT, CHANNEL_WINDFROM), options);
stateDescriptionProvider.setStateOptions(new ChannelUID(getThing().getUID(), GROUP_OUTPUT, CHANNEL_WINDTO), stateDescriptionProvider.setStateOptions(new ChannelUID(thingUID, GROUP_OUTPUT, CHANNEL_WINDTO), options);
options);
} }
@Override @Override
@ -109,7 +113,7 @@ public class SagerCasterHandler extends BaseThingHandler {
String id = channelUID.getIdWithoutGroup(); String id = channelUID.getIdWithoutGroup();
switch (id) { switch (id) {
case CHANNEL_CLOUDINESS: case CHANNEL_CLOUDINESS:
logger.debug("Octa cloud level changed, updating forecast"); logger.debug("Cloud level changed, updating forecast");
if (command instanceof QuantityType) { if (command instanceof QuantityType) {
QuantityType<?> cloudiness = (QuantityType<?>) command; QuantityType<?> cloudiness = (QuantityType<?>) command;
scheduler.submit(() -> { scheduler.submit(() -> {
@ -127,26 +131,17 @@ public class SagerCasterHandler extends BaseThingHandler {
postNewForecast(); postNewForecast();
}); });
} else { } else {
logger.debug("Channel '{}' can only accept Switch type commands.", channelUID); logger.debug("Channel '{}' accepts Switch commands.", channelUID);
} }
break; break;
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; updateRain((QuantityType<?>) command);
scheduler.submit(() -> {
sagerWeatherCaster.setRaining(newQtty.doubleValue() > 0);
postNewForecast();
});
} else if (command instanceof DecimalType) { } else if (command instanceof DecimalType) {
DecimalType newQtty = (DecimalType) command; updateRain((DecimalType) command);
scheduler.submit(() -> {
sagerWeatherCaster.setRaining(newQtty.doubleValue() > 0);
postNewForecast();
});
} else { } else {
logger.debug("Channel '{}' can accept Number, Number:Speed, Number:Length type commands.", logger.debug("Channel '{}' accepts Number, Number:(Speed|Length) commands.", channelUID);
channelUID);
} }
break; break;
case CHANNEL_WIND_SPEED: case CHANNEL_WIND_SPEED:
@ -165,12 +160,13 @@ public class SagerCasterHandler extends BaseThingHandler {
logger.debug("Sea-level pressure updated, updating forecast"); logger.debug("Sea-level pressure updated, updating forecast");
if (command instanceof QuantityType) { if (command instanceof QuantityType) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
QuantityType<Pressure> newPressure = ((QuantityType<Pressure>) command) QuantityType<Pressure> pressQtty = ((QuantityType<Pressure>) command)
.toUnit(HECTO(SIUnits.PASCAL)); .toUnit(HECTO(SIUnits.PASCAL));
if (newPressure != null) { if (pressQtty != null) {
pressureCache.put(newPressure); double newPressureValue = pressQtty.doubleValue();
pressureCache.getAgedValue().ifPresentOrElse(pressure -> scheduler.submit(() -> { pressureCache.put(newPressureValue);
sagerWeatherCaster.setPressure(newPressure.doubleValue(), pressure.doubleValue()); pressureCache.getAgedValue().ifPresentOrElse(oldPressure -> scheduler.submit(() -> {
sagerWeatherCaster.setPressure(newPressureValue, oldPressure);
updateChannelString(GROUP_OUTPUT, CHANNEL_PRESSURETREND, updateChannelString(GROUP_OUTPUT, CHANNEL_PRESSURETREND,
String.valueOf(sagerWeatherCaster.getPressureEvolution())); String.valueOf(sagerWeatherCaster.getPressureEvolution()));
postNewForecast(); postNewForecast();
@ -182,14 +178,13 @@ public class SagerCasterHandler extends BaseThingHandler {
logger.debug("Temperature updated"); logger.debug("Temperature updated");
if (command instanceof QuantityType) { if (command instanceof QuantityType) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
QuantityType<Temperature> newTemperature = ((QuantityType<Temperature>) command) QuantityType<Temperature> tempQtty = ((QuantityType<Temperature>) command)
.toUnit(SIUnits.CELSIUS); .toUnit(SIUnits.CELSIUS);
if (newTemperature != null) { if (tempQtty != null) {
temperatureCache.put(newTemperature); currentTemp = tempQtty.doubleValue();
currentTemp = newTemperature.intValue(); temperatureCache.put(currentTemp);
Optional<QuantityType<Temperature>> agedTemperature = temperatureCache.getAgedValue(); temperatureCache.getAgedValue().ifPresent(oldTemperature -> {
agedTemperature.ifPresent(temperature -> { double delta = currentTemp - oldTemperature;
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);
@ -201,12 +196,12 @@ public class SagerCasterHandler extends BaseThingHandler {
logger.debug("Updated wind direction, updating forecast"); logger.debug("Updated wind direction, updating forecast");
if (command instanceof QuantityType) { if (command instanceof QuantityType) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
QuantityType<Angle> newAngle = (QuantityType<Angle>) command; QuantityType<Angle> angleQtty = (QuantityType<Angle>) command;
bearingCache.put(newAngle); int newAngleValue = angleQtty.intValue();
Optional<QuantityType<Angle>> agedAngle = bearingCache.getAgedValue(); bearingCache.put(newAngleValue);
agedAngle.ifPresent(angle -> { bearingCache.getAgedValue().ifPresent(oldAngle -> {
scheduler.submit(() -> { scheduler.submit(() -> {
sagerWeatherCaster.setBearing(newAngle.intValue(), angle.intValue()); sagerWeatherCaster.setBearing(newAngleValue, oldAngle);
updateChannelString(GROUP_OUTPUT, CHANNEL_WINDEVOLUTION, updateChannelString(GROUP_OUTPUT, CHANNEL_WINDEVOLUTION,
String.valueOf(sagerWeatherCaster.getWindEvolution())); String.valueOf(sagerWeatherCaster.getWindEvolution()));
postNewForecast(); postNewForecast();
@ -220,7 +215,19 @@ public class SagerCasterHandler extends BaseThingHandler {
} }
} }
private void updateRain(Number newQtty) {
scheduler.submit(() -> {
sagerWeatherCaster.setRaining(newQtty.doubleValue() > 0);
postNewForecast();
});
}
private void postNewForecast() { private void postNewForecast() {
String newSagerCode = sagerWeatherCaster.getSagerCode();
if (!newSagerCode.equals(currentSagerCode)) {
logger.debug("Sager prediction changed to {}", newSagerCode);
currentSagerCode = newSagerCode;
updateChannelTimeStamp(GROUP_OUTPUT, CHANNEL_TIMESTAMP, ZonedDateTime.now());
String forecast = sagerWeatherCaster.getForecast(); String forecast = sagerWeatherCaster.getForecast();
// Sharpens forecast if current temp is below 2 degrees, likely to be flurries rather than shower // Sharpens forecast if current temp is below 2 degrees, likely to be flurries rather than shower
forecast += SHOWERS.contains(forecast) ? (currentTemp > 2) ? "1" : "2" : ""; forecast += SHOWERS.contains(forecast) ? (currentTemp > 2) ? "1" : "2" : "";
@ -228,34 +235,16 @@ public class SagerCasterHandler extends BaseThingHandler {
updateChannelString(GROUP_OUTPUT, CHANNEL_FORECAST, forecast); updateChannelString(GROUP_OUTPUT, CHANNEL_FORECAST, forecast);
updateChannelString(GROUP_OUTPUT, CHANNEL_WINDFROM, sagerWeatherCaster.getWindDirection()); updateChannelString(GROUP_OUTPUT, CHANNEL_WINDFROM, sagerWeatherCaster.getWindDirection());
updateChannelString(GROUP_OUTPUT, CHANNEL_WINDTO, sagerWeatherCaster.getWindDirection2()); updateChannelString(GROUP_OUTPUT, CHANNEL_WINDTO, sagerWeatherCaster.getWindDirection2());
updateChannelString(GROUP_OUTPUT, CHANNEL_VELOCITY, sagerWeatherCaster.getWindVelocity());
String velocity = sagerWeatherCaster.getWindVelocity(); updateChannelDecimal(GROUP_OUTPUT, CHANNEL_VELOCITY_BEAUFORT, sagerWeatherCaster.getPredictedBeaufort());
updateChannelString(GROUP_OUTPUT, CHANNEL_VELOCITY, velocity); }
int predictedBeaufort = sagerWeatherCaster.getBeaufort(); }
switch (velocity) {
case "N": private void updateChannelTimeStamp(String group, String channelId, ZonedDateTime zonedDateTime) {
predictedBeaufort += 1; ChannelUID id = new ChannelUID(getThing().getUID(), group, channelId);
break; if (isLinked(id)) {
case "F": updateState(id, new DateTimeType(zonedDateTime));
predictedBeaufort = 4;
break;
case "S":
predictedBeaufort = 6;
break;
case "G":
predictedBeaufort = 8;
break;
case "W":
predictedBeaufort = 10;
break;
case "H":
predictedBeaufort = 12;
break;
case "D":
predictedBeaufort -= 1;
break;
} }
updateChannelDecimal(GROUP_OUTPUT, CHANNEL_VELOCITY_BEAUFORT, predictedBeaufort);
} }
private void updateChannelString(String group, String channelId, String value) { private void updateChannelString(String group, String channelId, String value) {

View File

@ -43,6 +43,8 @@ rainingDescription = Is it currently raining ?
beaufortLabel = Beaufort beaufortLabel = Beaufort
beaufortDescription = Wind speed using Beaufort Scale beaufortDescription = Wind speed using Beaufort Scale
pressureDescription = Barometric pressure at sea level. pressureDescription = Barometric pressure at sea level.
timestampChannelLabel = Timestamp
timestampChannelDescription = Timestamp of the last weather forecast update.
# channel options # channel options
forecast0 = Not enough historic data to study pressure evolution, wait a bit ... forecast0 = Not enough historic data to study pressure evolution, wait a bit ...
@ -52,33 +54,33 @@ forecastC = Fair and cooler
forecastD = Unsettled forecastD = Unsettled
forecastE = Unsettled and warmer forecastE = Unsettled and warmer
forecastF = Unsettled and cooler forecastF = Unsettled and cooler
forecastG = Increasing cloudiness or overcast followed by Precipitation or showers/Flurries forecastG = Increasing cloudiness or overcast followed by precipitation or showers/flurries
forecastG1 = Increasing cloudiness or overcast followed by Precipitation or showers forecastG1 = Increasing cloudiness or overcast followed by precipitation or showers
forecastG2 = Increasing cloudiness or overcast followed by Precipitation or Flurries forecastG2 = Increasing cloudiness or overcast followed by precipitation or flurries
forecastH = Increasing cloudiness or overcast followed by Precipitation or showers and warmer forecastH = Increasing cloudiness or overcast followed by precipitation or showers and warmer
forecastJ = Showers forecastJ = Showers
forecastK = Showers/Flurries and warmer forecastK = Showers/flurries and warmer
forecastK1 = Showers and warmer forecastK1 = Showers and warmer
forecastK2 = Flurries and warmer forecastK2 = Flurries and warmer
forecastL = Showers/Flurries and cooler forecastL = Showers/flurries and cooler
forecastL1 = Showers and cooler forecastL1 = Showers and cooler
forecastL2 = Flurries and cooler forecastL2 = Flurries and cooler
forecastM = Precipitation forecastM = Precipitation
forecastN = Precipitation and warmer forecastN = Precipitation and warmer
forecastP = Precipitation and turning cooler; then improvement likely in 24 hours forecastP = Precipitation and turning cooler; then improvement likely in 24 hours
forecastR = Precipitation or showers/Flurries followed by improvement (within 12 hours) forecastR = Precipitation or showers/flurries followed by improvement (within 12 hours)
forecastR1 = Precipitation or showers 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) forecastR2 = Precipitation or flurries followed by improvement (within 12 hours)
forecastS = Precipitation or showers/Flurries followed by improvement (within 12 hours) and becoming cooler 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 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 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) 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) 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) 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 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 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 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 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 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 forecastW2 = Precipitation or flurries followed by fair early in period (within 6 hours) and becoming cooler
forecastX = Unsettled followed by fair forecastX = Unsettled followed by fair

View File

@ -43,6 +43,8 @@ rainingDescription = Pleut-il actuellement ?
beaufortLabel = Beaufort beaufortLabel = Beaufort
beaufortDescription = Force du vent mesurée sur l'échelle Beaufort beaufortDescription = Force du vent mesurée sur l'échelle Beaufort
pressureDescription = Pression barométrique au niveau de la mer. pressureDescription = Pression barométrique au niveau de la mer.
timestampChannelLabel = Horodatage
timestampChannelDescription = Horodatage de la dernière mise à jour de la prévision météo.
# channel options # channel options
forecast0 = Patientez encore un peu pour une prédiction forecast0 = Patientez encore un peu pour une prédiction

View File

@ -72,6 +72,7 @@
<label>@text/tempTrendLabel</label> <label>@text/tempTrendLabel</label>
<description>@text/tempTrendDescription</description> <description>@text/tempTrendDescription</description>
</channel> </channel>
<channel id="timestamp" typeId="timestamp"/>
</channels> </channels>
</channel-group-type> </channel-group-type>
@ -163,6 +164,7 @@
<item-type>String</item-type> <item-type>String</item-type>
<label>@text/trendLabel</label> <label>@text/trendLabel</label>
<description>@text/trendDescription</description> <description>@text/trendDescription</description>
<category>Line</category>
<state readOnly="true" pattern="%s"> <state readOnly="true" pattern="%s">
<options> <options>
<option value="1">@text/trend1</option> <option value="1">@text/trend1</option>
@ -174,19 +176,23 @@
</state> </state>
</channel-type> </channel-type>
<channel-type id="timestamp" advanced="true"> <channel-type id="timestamp">
<item-type>DateTime</item-type> <item-type>DateTime</item-type>
<label>@text/timestampLabel</label> <label>@text/timestampChannelLabel</label>
<description>@text/timestampDescription</description> <description>@text/timestampChannelDescription</description>
<category>Observation time</category> <category>Time</category>
<state readOnly="true"></state> <tags>
<tag>Status</tag>
<tag>Timestamp</tag>
</tags>
<state readOnly="true"/>
</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>@text/cloudinessLabel</label> <label>@text/cloudinessLabel</label>
<description>@text/cloudinessDescription</description> <description>@text/cloudinessDescription</description>
<category>Clouds</category> <category>Sun_Clouds</category>
<state min="0" max="100" pattern="%d %%"/> <state min="0" max="100" pattern="%d %%"/>
</channel-type> </channel-type>