### meteostick_davis_iss Configuration Options
-| Option | Description |
-|---------|-------------------------------------------|
-| channel | Sets the RF channel used for this sensor |
-| spoon | Size of rain spoon assembly for this sensor in mm. Default value is 0.254 (0.01") for use with Davis part number 7345.280. Set to 0.2 for use with Davis part number 7345.319 |
+| Option | Description |
+|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| channel | Sets the RF channel used for this sensor |
+| spoon | Size of rain spoon assembly for this sensor in mm. Default value is 0.254 (0.01") for use with Davis part number 7345.280. Set to 0.2 for use with Davis part number 7345.319 |
+| deltaWindDirection | For Davis 6410, 7911 & 7914 anemometers, if your anemometer cannot be mounted aiming true North set the direction it is aiming here (0 to 359 degrees). Default is 0 (for North) |
## Channels
| rain-raw | Number | Raw rain counter from the tipping spoon sensor |
| rain-currenthour | Number:Length | The rainfall in the last 60 minutes |
| rain-lasthour | Number:Length | The rainfall in the previous hour |
+| rain-today | Number:Length | Accumulated rainfall for today
| solar-power | Number | Solar power from the sensor station |
| signal-strength | Number | Received signal strength |
| low-battery | Switch | Low battery warning |
#### Rainfall
-There are three channels associated with rainfall.
+There are four channels associated with rainfall.
The raw counter from the tipping bucket is provided, the rainfall in the last 60 minutes is updated on each received rainfall and provides the past 60 minutes of rainfall.
The rainfall in the previous hour is the rainfall for each hour of the day and is updated on the hour.
+The accumulated rainfall for today provides the amount of rain for the current date and will reset to 0 at timezone's midnight.
## Full Example
```java
meteostick:meteostick_bridge:receiver [ port="/dev/tty.usbserial-AI02XA60", mode=1 ]
-meteostick:meteostick_davis_iss:iss (meteostick:meteostick_bridge:receiver) [ channel=1, spoon=0.2 ]
+meteostick:meteostick_davis_iss:iss (meteostick:meteostick_bridge:receiver) [ channel=1, spoon=0.2, deltaWindDirection=0 ]
```
-Note the configuration options for `port`, `mode`, `channel` and `spoon` above and adjust as needed for your specific hardware.
+Note the configuration options for `port`, `mode`, `channel`, `deltaWindDirection` and `spoon` above and adjust as needed for your specific hardware.
### items/meteostick.items
Number:Speed DavisVantageVueWindSpeedAverage "ISS Average Wind Speed [%.1f m/s]" { channel="meteostick:meteostick_davis_iss:iss:wind-speed-last2min-average" }
Number:Speed DavisVantageVueWindSpeedMaximum "ISS Maximum Wind Speed [%.1f m/s]" { channel="meteostick:meteostick_davis_iss:iss:wind-speed-last2min-maximum" }
Number:Length DavisVantageVueRainCurrentHour "ISS Rain Current Hour [%.1f mm]" { channel="meteostick:meteostick_davis_iss:iss:rain-currenthour" }
+Number:Length DavisVantageVueRainToday "ISS Rain Today [%.1f mm]" { channel="meteostick:meteostick_davis_iss:iss:rain-today" }
```
### rules/meteostick.rules
'dewptf' -> dewptf,
'tempf' -> DavisVantageVueOutdoorTemperature.getStateAs(QuantityType).toUnit('°F').doubleValue,
'rainin' -> DavisVantageVueRainCurrentHour.getStateAs(QuantityType).toUnit('in').doubleValue,
+ 'dailyrainin' -> DavisVantageVueRainToday.getStateAs(QuantityType).toUnit('in').doubleValue,
'baromin' -> MeteoStickPressure.getStateAs(QuantityType).toUnit('inHg').doubleValue,
'softwaretype' -> 'openHAB 2.4')
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.QuantityType;
+import org.openhab.core.scheduler.CronScheduler;
+import org.openhab.core.scheduler.ScheduledCompletableFuture;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
*
* @author Chris Jackson - Initial contribution
* @author John Cocula - Added variable spoon size, UoM, wind stats, bug fixes
+ * @author Cor Hoogendoorn - Added option for wind vanes not facing North and cumulative rainfall for today
*/
public class MeteostickSensorHandler extends BaseThingHandler implements MeteostickEventListener {
+ private static final String DAILY_MIDNIGHT = "1 0 0 * * ? *";
+ private final CronScheduler cronScheduler;
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_DAVIS);
private final Logger logger = LoggerFactory.getLogger(MeteostickSensorHandler.class);
private int channel = 0;
+ private int deltawinddir = 0;
+ private int rainspoonold = -1;
+ private BigDecimal rainfallToday = BigDecimal.ZERO;
private BigDecimal spoon = new BigDecimal(PARAMETER_SPOON_DEFAULT);
private MeteostickBridgeHandler bridgeHandler;
private RainHistory rainHistory = new RainHistory(HOUR_IN_MSEC);
private WindHistory windHistory = new WindHistory(2 * 60 * 1000); // 2 minutes
private ScheduledFuture<?> rainHourlyJob;
+ private ScheduledCompletableFuture<?> rainMidnightJob;
private ScheduledFuture<?> wind2MinJob;
private ScheduledFuture<?> offlineTimerJob;
private Date lastData;
- public MeteostickSensorHandler(Thing thing) {
+ public MeteostickSensorHandler(Thing thing, final CronScheduler scheduler) {
super(thing);
+ this.cronScheduler = scheduler;
}
@Override
if (spoon == null) {
spoon = new BigDecimal(PARAMETER_SPOON_DEFAULT);
}
- logger.debug("Initializing MeteoStick handler - Channel {}, Spoon size {} mm.", channel, spoon);
+
+ deltawinddir = ((BigDecimal) getConfig().get(PARAMETER_WINDVANE)).intValue();
+
+ logger.debug("Initializing MeteoStick handler - Channel {}, Spoon size {} mm, Wind vane offset {} °", channel,
+ spoon, deltawinddir);
Runnable rainRunnable = () -> {
- BigDecimal rainfall = rainHistory.getTotal(spoon);
+ BigDecimal rainfall = rainHistory.getTotal();
rainfall.setScale(1, RoundingMode.DOWN);
updateState(new ChannelUID(getThing().getUID(), CHANNEL_RAIN_LASTHOUR),
new QuantityType<>(rainfall, MILLI(METRE)));
long start = HOUR_IN_SEC - ((System.currentTimeMillis() % HOUR_IN_MSEC) / 1000);
rainHourlyJob = scheduler.scheduleWithFixedDelay(rainRunnable, start, HOUR_IN_SEC, TimeUnit.SECONDS);
+ // Scheduling a job at midnight to reset today's rainfall to 0
+ rainMidnightJob = cronScheduler.schedule(this::dailyJob, DAILY_MIDNIGHT);
+
Runnable windRunnable = () -> {
WindStats stats = windHistory.getStats();
updateState(new ChannelUID(getThing().getUID(), CHANNEL_WIND_SPEED_LAST2MIN_AVERAGE),
rainHourlyJob.cancel(true);
}
+ if (rainMidnightJob != null) {
+ rainMidnightJob.cancel(true);
+ }
+
if (wind2MinJob != null) {
wind2MinJob.cancel(true);
}
processSignalStrength(data[3]);
processBattery(data.length == 5);
- rainHistory.put(rain);
+ rain &= 0x7F;
+ int totalspoon = 0;
+ if (rainspoonold < 0) {
+ rainspoonold = rain;
+ }
+ if (rain < rainspoonold) {
+ totalspoon = 128 - rainspoonold + rain;
+ } else {
+ totalspoon = rain - rainspoonold;
+ }
+
+ BigDecimal rainincrease = BigDecimal.valueOf(totalspoon).multiply(spoon);
+ rainHistory.put(rainincrease);
- BigDecimal rainfall = rainHistory.getTotal(spoon);
+ BigDecimal rainfall = rainHistory.getTotal();
rainfall.setScale(1, RoundingMode.DOWN);
updateState(new ChannelUID(getThing().getUID(), CHANNEL_RAIN_CURRENTHOUR),
new QuantityType<>(rainfall, MILLI(METRE)));
+
+ rainfallToday = rainfallToday.add(rainincrease);
+ rainfallToday.setScale(1, RoundingMode.DOWN);
+ updateState(new ChannelUID(getThing().getUID(), CHANNEL_RAIN_TODAY),
+ new QuantityType<>(rainfallToday, MILLI(METRE)));
+ rainspoonold = rain;
break;
case "W": // Wind
BigDecimal windSpeed = new BigDecimal(data[2]);
int windDirection = Integer.parseInt(data[3]);
updateState(new ChannelUID(getThing().getUID(), CHANNEL_WIND_SPEED),
new QuantityType<>(windSpeed, METRE_PER_SECOND));
+ if (deltawinddir != 0) {
+ if (windDirection < (360 - deltawinddir)) {
+ windDirection += deltawinddir;
+ } else {
+ windDirection -= (360 - deltawinddir);
+ }
+ }
updateState(new ChannelUID(getThing().getUID(), CHANNEL_WIND_DIRECTION),
new QuantityType<>(windDirection, DEGREE_ANGLE));
}
}
- class RainHistory extends SlidingTimeWindow<Integer> {
+ class RainHistory extends SlidingTimeWindow<BigDecimal> {
public RainHistory(long period) {
super(period);
}
- public BigDecimal getTotal(BigDecimal spoon) {
+ public BigDecimal getTotal() {
removeOldEntries();
-
- int least = -1;
- int total = 0;
-
+ BigDecimal raintotalmap = BigDecimal.ZERO;
synchronized (storage) {
- for (int value : storage.values()) {
-
- /*
- * Rain counters have been seen to wrap at 127 and also at 255.
- * The Meteostick documentation only mentions 255 at the time of
- * this writing. This potential difference is solved by having
- * all rain counters wrap at 127 (0x7F) by removing the high bit.
- */
- value &= 0x7F;
-
- if (least == -1) {
- least = value;
- continue;
- }
+ for (BigDecimal value : storage.values()) {
+
+ raintotalmap = raintotalmap.add(value);
- if (value < least) {
- total = 128 - least + value;
- } else {
- total = value - least;
- }
}
}
- return BigDecimal.valueOf(total).multiply(spoon);
+ return raintotalmap;
}
}
// Scheduling a job on each hour to update the last hour rainfall
offlineTimerJob = scheduler.schedule(pollingRunnable, 90, TimeUnit.SECONDS);
}
+
+ private void dailyJob() {
+ // Daily job to reset the daily rain accumulation
+ rainfallToday = BigDecimal.ZERO;
+ updateState(new ChannelUID(getThing().getUID(), CHANNEL_RAIN_TODAY),
+ new QuantityType<>(rainfallToday, MILLI(METRE)));
+ }
}