[ambientweather] Add WS-2902B weather station (#8954)

Signed-off-by: Mark Hilbush <mark@hilbush.com>
This commit is contained in:
Mark Hilbush 2020-11-09 12:13:26 -05:00 committed by GitHub
parent 94245b627d
commit 4579fae00a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 225 additions and 6 deletions

View File

@ -12,7 +12,8 @@ The binding currently supports weather data from these weather stations.
| Account | bridge |
| WS-0900-IP | ws0900ip |
| WS-1400-IP / WS-1401-IP | ws1400ip |
| WS-2902A | ws2902a |
| WS-2902A / WS2902C | ws2902a |
| WS-2902B | ws2902b |
| WS-8482 | ws8482 |
| WS-0265 | ws0265 |
@ -234,16 +235,20 @@ Adding support for a new weather station type involves changes to the source cod
Define a new `ThingTypeUID` for the new station and add it to the `SUPPORTED_THING_TYPES_UIDS` Collection.
Add a channel group for the new station.
#### Create OH-INF/thing/\<station-model\>.xml
Add thing type and channel group specific to the data elements supported by this weather station.
Modeling this after an existing thing type that shares many of the channels is the easiest starting point.
You can determine the weather data elements returned for the weather station by putting the binding into debug mode and reviewing the JSON object returned by the Ambient Weather API.
#### Create Processor Class AmbientWeather<StationModel>Processor
#### Create Processor Class <StationModel>Processor
Add a class in `org.openhab.binding.ambientweather.internal.processor` that defines the channels supported by this station type.
Add the following two methods.
Again, the easiest approach is to model this class after a class for a similar weather station type.
##### Method: processInfoUpdate
@ -254,6 +259,6 @@ Updates the channels for station name and location.
Updates channels for weather data.
#### Update AmbientWeatherProcessorFactory.java
#### Update ProcessorFactory.java
Add new Processor class definition to `AmbientWeatherProcessorFactory.java`, and add a new case to the switch statement to return the new processor.
Add new Processor class definition to `ProcessorFactory.java`, and add a new case to the switch statement to return the new processor.

View File

@ -45,6 +45,10 @@ public class AmbientWeatherBindingConstants {
public static final String THING_TYPE_WS2902A = "ws2902a";
public static final ThingTypeUID UID_WS2902A = new ThingTypeUID(BINDING_ID, THING_TYPE_WS2902A);
// WS-2902B series weather stations
public static final String THING_TYPE_WS2902B = "ws2902b";
public static final ThingTypeUID UID_WS2902B = new ThingTypeUID(BINDING_ID, THING_TYPE_WS2902B);
// WS-8482 weather station
public static final String THING_TYPE_WS8482 = "ws8482";
public static final ThingTypeUID UID_WS8482 = new ThingTypeUID(BINDING_ID, THING_TYPE_WS8482);
@ -58,8 +62,9 @@ public class AmbientWeatherBindingConstants {
public static final ThingTypeUID UID_WS0265 = new ThingTypeUID(BINDING_ID, THING_TYPE_WS0265);
// Collection of weather station thing types
public static final Set<ThingTypeUID> SUPPORTED_STATION_THING_TYPES_UIDS = Collections.unmodifiableSet(
Stream.of(UID_WS1400IP, UID_WS2902A, UID_WS8482, UID_WS0900IP, UID_WS0265).collect(Collectors.toSet()));
public static final Set<ThingTypeUID> SUPPORTED_STATION_THING_TYPES_UIDS = Collections
.unmodifiableSet(Stream.of(UID_WS1400IP, UID_WS2902A, UID_WS2902B, UID_WS8482, UID_WS0900IP, UID_WS0265)
.collect(Collectors.toSet()));
// Collection of all supported thing types
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(
@ -69,6 +74,7 @@ public class AmbientWeatherBindingConstants {
// Channel groups for specific weather stations
public static final String CHGRP_WS1400IP = "weatherDataWs1400ip";
public static final String CHGRP_WS2902A = "weatherDataWs2902a";
public static final String CHGRP_WS2902B = "weatherDataWs2902b";
public static final String CHGRP_WS8482 = "weatherDataWs8482";
public static final String CHGRP_WS0900IP = "weatherDataWs0900ip";
public static final String CHGRP_WS0265 = "weatherDataWs0265";

View File

@ -37,6 +37,7 @@ public class ProcessorFactory {
// Supported weather stations
private @Nullable static Ws1400ipProcessor WS1400IP_PROCESSOR;
private @Nullable static Ws2902aProcessor WS2902A_PROCESSOR;
private @Nullable static Ws2902bProcessor WS2902B_PROCESSOR;
private @Nullable static Ws8482Processor WS8482_PROCESSOR;
private @Nullable static Ws0900ipProcessor WS0900IP_PROCESSOR;
private @Nullable static Ws0265Processor WS0265_PROCESSOR;
@ -78,6 +79,14 @@ public class ProcessorFactory {
}
return processor;
}
case "ambientweather:ws2902b": {
Ws2902bProcessor processor = WS2902B_PROCESSOR;
if (processor == null) {
processor = new Ws2902bProcessor();
WS2902B_PROCESSOR = processor;
}
return processor;
}
case "ambientweather:ws8482": {
Ws8482Processor processor = WS8482_PROCESSOR;
if (processor == null) {

View File

@ -0,0 +1,102 @@
/**
* Copyright (c) 2010-2020 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.ambientweather.internal.processor;
import static org.openhab.binding.ambientweather.internal.AmbientWeatherBindingConstants.*;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.ambientweather.internal.handler.AmbientWeatherStationHandler;
import org.openhab.binding.ambientweather.internal.model.EventDataJson;
import org.openhab.core.library.unit.ImperialUnits;
import org.openhab.core.library.unit.SmartHomeUnits;
/**
* The {@link Ws2902bProcessor} is responsible for updating
* the channels associated with the WS-2902A weather stations in
* response to the receipt of a weather data update from the Ambient
* Weather real-time API.
*
* @author Mark Hilbush - Initial contribution
*/
@NonNullByDefault
public class Ws2902bProcessor extends AbstractProcessor {
@Override
public void setChannelGroupId() {
channelGroupId = CHGRP_WS2902B;
}
@Override
public void setNumberOfSensors() {
remoteSensor.setNumberOfSensors(8);
}
@Override
public void processInfoUpdate(AmbientWeatherStationHandler handler, String station, String name, String location) {
// Update name and location channels
handler.updateString(CHGRP_STATION, CH_NAME, name);
handler.updateString(CHGRP_STATION, CH_LOCATION, location);
}
@Override
public void processWeatherData(AmbientWeatherStationHandler handler, String station, String jsonData) {
EventDataJson data = parseEventData(station, jsonData);
if (data == null) {
return;
}
// Update the weather data channels
handler.updateDate(channelGroupId, CH_OBSERVATION_TIME, data.date);
handler.updateString(channelGroupId, CH_BATTERY_INDICATOR, NOT_APPLICABLE);
handler.updateQuantity(channelGroupId, CH_TEMPERATURE, data.tempf, ImperialUnits.FAHRENHEIT);
handler.updateQuantity(channelGroupId, CH_FEELING_TEMPERATURE, data.feelsLike, ImperialUnits.FAHRENHEIT);
handler.updateQuantity(channelGroupId, CH_DEW_POINT, data.dewPoint, ImperialUnits.FAHRENHEIT);
handler.updateQuantity(channelGroupId, CH_HUMIDITY, data.humidity, SmartHomeUnits.PERCENT);
handler.updateQuantity(channelGroupId, CH_PRESSURE_ABSOLUTE, data.baromabsin, ImperialUnits.INCH_OF_MERCURY);
handler.updateQuantity(channelGroupId, CH_PRESSURE_RELATIVE, data.baromrelin, ImperialUnits.INCH_OF_MERCURY);
handler.updateQuantity(channelGroupId, CH_WIND_SPEED, data.windspeedmph, ImperialUnits.MILES_PER_HOUR);
handler.updateQuantity(channelGroupId, CH_WIND_DIRECTION_DEGREES, data.winddir, SmartHomeUnits.DEGREE_ANGLE);
handler.updateQuantity(channelGroupId, CH_WIND_GUST, data.windgustmph, ImperialUnits.MILES_PER_HOUR);
handler.updateQuantity(channelGroupId, CH_WIND_GUST_MAX_DAILY, data.maxdailygust, ImperialUnits.MILES_PER_HOUR);
handler.updateQuantity(channelGroupId, CH_SOLAR_RADIATION, data.solarradiation, SmartHomeUnits.IRRADIANCE);
handler.updateNumber(channelGroupId, CH_UV_INDEX, data.uv);
handler.updateQuantity(channelGroupId, CH_RAIN_HOURLY_RATE, data.hourlyrainin, SmartHomeUnits.INCHES_PER_HOUR);
handler.updateQuantity(channelGroupId, CH_RAIN_DAY, data.dailyrainin, ImperialUnits.INCH);
handler.updateQuantity(channelGroupId, CH_RAIN_WEEK, data.weeklyrainin, ImperialUnits.INCH);
handler.updateQuantity(channelGroupId, CH_RAIN_MONTH, data.monthlyrainin, ImperialUnits.INCH);
handler.updateQuantity(channelGroupId, CH_RAIN_YEAR, data.yearlyrainin, ImperialUnits.INCH);
handler.updateQuantity(channelGroupId, CH_RAIN_TOTAL, data.totalrainin, ImperialUnits.INCH);
handler.updateQuantity(channelGroupId, CH_RAIN_EVENT, data.eventrainin, ImperialUnits.INCH);
handler.updateDate(channelGroupId, CH_RAIN_LAST_TIME, data.lastRain);
// Update calculated channels
if (data.baromrelin != null) {
pressureTrend.put(data.baromrelin);
handler.updateString(channelGroupId, CH_PRESSURE_TREND, pressureTrend.getPressureTrend());
}
if (data.winddir != null) {
handler.updateString(channelGroupId, CH_WIND_DIRECTION, convertWindDirectionToString(data.winddir));
}
if (data.uv != null) {
handler.updateString(channelGroupId, CH_UV_DANGER, convertUVIndexToString(data.uv));
}
// Update indoor sensor channels
handler.updateQuantity(CHGRP_INDOOR_SENSOR, CH_TEMPERATURE, data.tempinf, ImperialUnits.FAHRENHEIT);
handler.updateQuantity(CHGRP_INDOOR_SENSOR, CH_HUMIDITY, data.humidityin, SmartHomeUnits.PERCENT);
handler.updateString(CHGRP_INDOOR_SENSOR, CH_BATTERY_INDICATOR, NOT_APPLICABLE);
// Update channels for the remote sensors
remoteSensor.updateChannels(handler, jsonData);
}
}

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="ambientweather"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<!-- Ambient Weather WS-2902B -->
<thing-type id="ws2902b">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
</supported-bridge-type-refs>
<label>WS-2902B</label>
<description>Ambient Weather Station WS-2902B</description>
<channel-groups>
<channel-group id="station" typeId="station">
<label>Weather Station</label>
<description></description>
</channel-group>
<channel-group id="weatherDataWs2902b" typeId="weatherDataWs2902b">
<label>Weather Data</label>
<description></description>
</channel-group>
<channel-group id="indoorSensor" typeId="indoorSensor">
<label>Indoor Sensor</label>
<description></description>
</channel-group>
<channel-group id="remoteSensor1" typeId="remoteSensor">
<label>Remote Sensor 1</label>
<description></description>
</channel-group>
<channel-group id="remoteSensor2" typeId="remoteSensor">
<label>Remote Sensor 2</label>
<description></description>
</channel-group>
<channel-group id="remoteSensor3" typeId="remoteSensor">
<label>Remote Sensor 3</label>
<description></description>
</channel-group>
<channel-group id="remoteSensor4" typeId="remoteSensor">
<label>Remote Sensor 4</label>
<description></description>
</channel-group>
<channel-group id="remoteSensor5" typeId="remoteSensor">
<label>Remote Sensor 5</label>
<description></description>
</channel-group>
<channel-group id="remoteSensor6" typeId="remoteSensor">
<label>Remote Sensor 6</label>
<description></description>
</channel-group>
<channel-group id="remoteSensor7" typeId="remoteSensor">
<label>Remote Sensor 7</label>
<description></description>
</channel-group>
<channel-group id="remoteSensor8" typeId="remoteSensor">
<label>Remote Sensor 8</label>
<description></description>
</channel-group>
</channel-groups>
<config-description-ref uri="thing-type:ambientweather:station"/>
</thing-type>
<!-- Channel group type specific to WS-2902B -->
<channel-group-type id="weatherDataWs2902b">
<label>Weather Data</label>
<description>Weather Data</description>
<channels>
<channel id="observationTime" typeId="observationTime"/>
<channel id="batteryIndicator" typeId="batteryIndicator"/>
<channel id="temperature" typeId="temperature"/>
<channel id="dewPoint" typeId="dewPoint"/>
<channel id="feelingTemperature" typeId="feelingTemperature"/>
<channel id="relativeHumidity" typeId="relativeHumidity"/>
<channel id="pressureAbsolute" typeId="pressure"/>
<channel id="pressureRelative" typeId="pressure"/>
<channel id="pressureTrend" typeId="pressureTrend"/>
<channel id="windDirectionDegrees" typeId="windDirectionDegrees"/>
<channel id="windDirection" typeId="windDirection"/>
<channel id="windSpeed" typeId="windSpeed"/>
<channel id="windGust" typeId="windGust"/>
<channel id="windGustMaxDaily" typeId="windGustMaxDaily"/>
<channel id="rainHourlyRate" typeId="rainHourlyRate"/>
<channel id="rainDay" typeId="rainDay"/>
<channel id="rainWeek" typeId="rainWeek"/>
<channel id="rainMonth" typeId="rainMonth"/>
<channel id="rainYear" typeId="rainYear"/>
<channel id="rainTotal" typeId="rainTotal"/>
<channel id="rainEvent" typeId="rainEvent"/>
<channel id="rainLastTime" typeId="rainLastTime"/>
<channel id="solarRadiation" typeId="solarRadiation"/>
<channel id="uvIndex" typeId="uvIndex"/>
<channel id="uvDanger" typeId="uvDanger"/>
</channels>
</channel-group-type>
</thing:thing-descriptions>