[fineoffsetweatherstation] Add support for the new GW2001 weather station (#13283)

* [fineoffsetweatherstation] add support for the new GW2001 weather station with its WH90 sensor
* [fineoffsetweatherstation] add missing channel labels
* [fineoffsetweatherstation] remove redundant translations
* [fineoffsetweatherstation] add test data + fix for WH90
* [fineoffsetweatherstation] fix wrong size for `CMD_READ_RAIN`

Signed-off-by: Andreas Berger <andreas@berger-freelancer.com>
This commit is contained in:
Andreas Berger 2022-08-31 15:27:18 +02:00 committed by GitHub
parent a2e0d23297
commit 4331c5f3ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 519 additions and 441 deletions

View File

@ -23,7 +23,7 @@ This binding works offline by [implementing the wire protocol](https://osswww.ec
## Supported Things ## Supported Things
- `weatherstation`: A Fine Offset gateway device with the ThingTypeUID `fineoffsetweatherstation:weatherstation` wich supports the [wire protocol](https://osswww.ecowitt.net/uploads/20210716/WN1900%20GW1000,1100%20WH2680,2650%20telenet%20v1.6.0%20.pdf) e.g.: - `weatherstation`: A Fine Offset gateway device with the ThingTypeUID `fineoffsetweatherstation:weatherstation` which supports the [wire protocol](https://osswww.ecowitt.net/uploads/20220407/WN1900%20GW1000,1100%20WH2680,2650%20telenet%20v1.6.4.pdf) e.g.:
- HP2550 - HP2550
- HP3500 - HP3500
- GW1000 - GW1000
@ -31,6 +31,7 @@ This binding works offline by [implementing the wire protocol](https://osswww.ec
- GW1002 - GW1002
- GW1003 - GW1003
- GW1100 - GW1100
- GW2001
- WN1900 - WN1900
- WN1910 - WN1910
- WH2350 - WH2350
@ -42,6 +43,7 @@ This binding works offline by [implementing the wire protocol](https://osswww.ec
- WH2900 - WH2900
- WH2950 - WH2950
- WS980 ELV (tested) - WS980 ELV (tested)
- WittBoy (tested)
- `sensor`: A Fine Offset sensor which is connected to the bridge with the ThingTypeUID `fineoffsetweatherstation:sensor`. - `sensor`: A Fine Offset sensor which is connected to the bridge with the ThingTypeUID `fineoffsetweatherstation:sensor`.
Since the gateway collects all the sensor data and harmonizes them, the sensor thing itself will only hold information about the signal and battery status. Since the gateway collects all the sensor data and harmonizes them, the sensor thing itself will only hold information about the signal and battery status.
This is a list of sensors supported by the protocol: This is a list of sensors supported by the protocol:
@ -60,7 +62,7 @@ This binding works offline by [implementing the wire protocol](https://osswww.ec
- WH65 - 7-in-1 weather station for wind speed & direction, solar radiation & light, temperature, humidity and rainfall - WH65 - 7-in-1 weather station for wind speed & direction, solar radiation & light, temperature, humidity and rainfall
- WH68 - 4-in-1 weather station - Solar-powered sensor for wind speed & direction, solar radiation & light - WH68 - 4-in-1 weather station - Solar-powered sensor for wind speed & direction, solar radiation & light
- WH80 - 6-in-1 weather station - Ultrasonic sensor for wind speed & direction, solar radiation & light, temperature & humidity - WH80 - 6-in-1 weather station - Ultrasonic sensor for wind speed & direction, solar radiation & light, temperature & humidity
- WH90 - A new weather station - WH90 - 7-in-1 weather station - Ultrasonic sensor for wind speed & direction, solar radiation & light, temperature, humidity and haptic rainfall Sensor
### Unsupported Devices ### Unsupported Devices
@ -263,6 +265,13 @@ Valid sensors:
| leaf-wetness-channel-6 | Number:Dimensionless | R | Leaf Moisture Channel 6 | | leaf-wetness-channel-6 | Number:Dimensionless | R | Leaf Moisture Channel 6 |
| leaf-wetness-channel-7 | Number:Dimensionless | R | Leaf Moisture Channel 7 | | leaf-wetness-channel-7 | Number:Dimensionless | R | Leaf Moisture Channel 7 |
| leaf-wetness-channel-8 | Number:Dimensionless | R | Leaf Moisture Channel 8 | | leaf-wetness-channel-8 | Number:Dimensionless | R | Leaf Moisture Channel 8 |
| piezo-rain-rate | Number:VolumetricFlowRate | R | Piezo - Rainfall Rate |
| piezo-rain-event | Number:Length | R | Piezo - Amount of Rainfall At the last Rain |
| piezo-rain-hour | Number:Length | R | Piezo - Rainfall Current Hour |
| piezo-rain-day | Number:Length | R | Piezo - Rainfall Today |
| piezo-rain-week | Number:Length | R | Piezo - Rainfall this Week |
| piezo-rain-month | Number:Length | R | Piezo - Rainfall this Month |
| piezo-rain-year | Number:Length | R | Piezo - Rainfall this Year |
### `sensor` Channels ### `sensor` Channels

View File

@ -26,11 +26,6 @@
<name>openHAB Add-ons :: Bundles :: Fine Offset Weather Station</name> <name>openHAB Add-ons :: Bundles :: Fine Offset Weather Station</name>
<dependencies> <dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.9.0</version>
</dependency>
<dependency> <dependency>
<groupId>org.assertj</groupId> <groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId> <artifactId>assertj-core</artifactId>

View File

@ -26,7 +26,6 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -200,7 +199,7 @@ public class FineOffsetGatewayDiscoveryService extends AbstractDiscoveryService
for (Protocol protocol : Protocol.values()) { for (Protocol protocol : Protocol.values()) {
try (GatewayQueryService gatewayQueryService = protocol.getGatewayQueryService(config, null, try (GatewayQueryService gatewayQueryService = protocol.getGatewayQueryService(config, null,
conversionContext)) { conversionContext)) {
List<MeasuredValue> result = gatewayQueryService.getMeasuredValues(); Collection<MeasuredValue> result = gatewayQueryService.getMeasuredValues();
logger.trace("found {} measured values via protocol {}", result.size(), protocol); logger.trace("found {} measured values via protocol {}", result.size(), protocol);
if (!result.isEmpty()) { if (!result.isEmpty()) {
return protocol; return protocol;

View File

@ -231,7 +231,17 @@ public enum Command {
/** /**
* write back rain reset time * write back rain reset time
*/ */
CMD_WRITE_RSTRAIN_TIME((byte) 0x56, 1); CMD_WRITE_RSTRAIN_TIME((byte) 0x56, 1),
/**
* read rain data including piezo (wh90)
*/
CMD_READ_RAIN((byte) 0x57, 2),
/**
* write rain data
*/
CMD_WRITE_RAIN((byte) 0x58, 1);
private final byte code; private final byte code;
private final int sizeBytes; private final int sizeBytes;

View File

@ -0,0 +1,344 @@
/**
* Copyright (c) 2010-2022 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.fineoffsetweatherstation.internal.domain;
import static org.openhab.binding.fineoffsetweatherstation.internal.FineOffsetWeatherStationBindingConstants.CHANNEL_TYPE_MAX_WIND_SPEED;
import static org.openhab.binding.fineoffsetweatherstation.internal.FineOffsetWeatherStationBindingConstants.CHANNEL_TYPE_MOISTURE;
import static org.openhab.binding.fineoffsetweatherstation.internal.FineOffsetWeatherStationBindingConstants.CHANNEL_TYPE_UV_INDEX;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.response.MeasuredValue;
import org.openhab.core.thing.DefaultSystemChannelTypeProvider;
import org.openhab.core.thing.type.ChannelTypeUID;
import org.openhab.core.types.State;
/**
* The measurands of supported by the gateway.
*
* @author Andreas Berger - Initial contribution
*/
@NonNullByDefault
public enum Measurand {
INTEMP("temperature-indoor", 0x01, "Indoor Temperature", MeasureType.TEMPERATURE,
DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_TYPE_UID_INDOOR_TEMPERATURE),
OUTTEMP("temperature-outdoor", 0x02, "Outdoor Temperature", MeasureType.TEMPERATURE,
DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_TYPE_UID_OUTDOOR_TEMPERATURE),
DEWPOINT("temperature-dew-point", 0x03, "Dew point", MeasureType.TEMPERATURE),
WINDCHILL("temperature-wind-chill", 0x04, "Wind chill", MeasureType.TEMPERATURE),
HEATINDEX("temperature-heat-index", 0x05, "Heat index", MeasureType.TEMPERATURE),
INHUMI("humidity-indoor", 0x06, "Indoor Humidity", MeasureType.PERCENTAGE),
OUTHUMI("humidity-outdoor", 0x07, "Outdoor Humidity", MeasureType.PERCENTAGE,
DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_TYPE_UID_ATMOSPHERIC_HUMIDITY),
ABSBARO("pressure-absolute", 0x08, "Absolutely pressure", MeasureType.PRESSURE),
RELBARO("pressure-relative", 0x09, "Relative pressure", MeasureType.PRESSURE,
DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_TYPE_UID_BAROMETRIC_PRESSURE),
WINDDIRECTION("direction-wind", 0x0A, "Wind Direction", MeasureType.DEGREE,
DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_TYPE_UID_WIND_DIRECTION),
WINDSPEED("speed-wind", 0x0B, "Wind Speed", MeasureType.SPEED,
DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_TYPE_UID_WIND_SPEED),
GUSTSPEED("speed-gust", 0x0C, "Gust Speed", MeasureType.SPEED,
DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_TYPE_UID_WIND_SPEED),
RAINEVENT("rain-event", 0x0D, "Rain Event", MeasureType.HEIGHT,
new ParserCustomization(ParserCustomizationType.ELV, MeasureType.HEIGHT_BIG)),
RAINRATE("rain-rate", 0x0E, "Rain Rate", MeasureType.HEIGHT_PER_HOUR,
new ParserCustomization(ParserCustomizationType.ELV, MeasureType.HEIGHT_PER_HOUR_BIG)),
RAINHOUR("rain-hour", 0x0F, "Rain hour", MeasureType.HEIGHT,
new ParserCustomization(ParserCustomizationType.ELV, MeasureType.HEIGHT_BIG)),
RAINDAY("rain-day", 0x10, "Rain Day", MeasureType.HEIGHT,
new ParserCustomization(ParserCustomizationType.ELV, MeasureType.HEIGHT_BIG),
new ParserCustomization(ParserCustomizationType.RAIN_READING, MeasureType.HEIGHT_BIG)),
RAINWEEK("rain-week", 0x11, "Rain Week", MeasureType.HEIGHT,
new ParserCustomization(ParserCustomizationType.ELV, MeasureType.HEIGHT_BIG),
new ParserCustomization(ParserCustomizationType.RAIN_READING, MeasureType.HEIGHT_BIG)),
RAINMONTH("rain-month", 0x12, "Rain Month", MeasureType.HEIGHT_BIG),
RAINYEAR("rain-year", 0x13, "Rain Year", MeasureType.HEIGHT_BIG),
RAINTOTALS("rain-total", 0x14, "Rain Totals", MeasureType.HEIGHT_BIG),
LIGHT("illumination", 0x15, "Light", MeasureType.LUX),
UV("irradiation-uv", 0x16, "UV", MeasureType.MILLIWATT_PER_SQUARE_METRE),
UVI("uv-index", 0x17, "UV index", MeasureType.BYTE, CHANNEL_TYPE_UV_INDEX),
TIME("time", 0x18, "Date and time", MeasureType.DATE_TIME2),
DAYLWINDMAX("wind-max-day", 0X19, "Day max wind", MeasureType.SPEED, CHANNEL_TYPE_MAX_WIND_SPEED),
TEMPX("temperature-channel", new int[] { 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21 }, "Temperature",
MeasureType.TEMPERATURE),
HUMIX("humidity-channel", new int[] { 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29 }, "Humidity",
MeasureType.PERCENTAGE),
SOILTEMPX("temperature-soil-channel",
new int[] { 0x2B, 0x2D, 0x2F, 0x31, 0x33, 0x35, 0x37, 0x39, 0x3B, 0x3D, 0x3F, 0x41, 0x43, 0x45, 0x47,
0x49 },
"Soil Temperature", MeasureType.TEMPERATURE),
SOILMOISTUREX("moisture-soil-channel",
new int[] { 0x2C, 0x2E, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E, 0x40, 0x42, 0x44, 0x46, 0x48,
0x4A },
"Soil Moisture", MeasureType.PERCENTAGE, CHANNEL_TYPE_MOISTURE),
// will no longer be used
// skip battery-level, since it is read via Command.CMD_READ_SENSOR_ID_NEW
LOWBATT(0x4C, new Skip(1)),
PM25_24HAVGX("air-quality-24-hour-average-channel", new int[] { 0x4D, 0x4E, 0x4F, 0x50 },
"PM2.5 Air Quality 24 hour average", MeasureType.PM25),
PM25_CHX("air-quality-channel", new int[] { 0x2A, 0x51, 0x52, 0x53 }, "PM2.5 Air Quality", MeasureType.PM25),
LEAK_CHX("water-leak-channel", new int[] { 0x58, 0x59, 0x5A, 0x5B }, "Leak", MeasureType.WATER_LEAK_DETECTION),
// `LIGHTNING` is the name in the spec, so we keep it here as it
LIGHTNING("lightning-distance", 0x60, "lightning distance 1~40KM", MeasureType.LIGHTNING_DISTANCE),
LIGHTNING_TIME("lightning-time", 0x61, "lightning happened time", MeasureType.LIGHTNING_TIME),
// `LIGHTNING_POWER` is the name in the spec, so we keep it here as it
LIGHTNING_POWER("lightning-counter", 0x62, "lightning counter for the day", MeasureType.LIGHTNING_COUNTER),
TF_USRX("temperature-external-channel", new int[] { 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A },
"Soil or Water temperature", MeasureType.TEMPERATURE),
ITEM_SENSOR_CO2(0x70,
new MeasurandParser("sensor-co2-temperature", "Temperature (CO₂-Sensor)", MeasureType.TEMPERATURE),
new MeasurandParser("sensor-co2-humidity", "Humidity (CO₂-Sensor)", MeasureType.PERCENTAGE),
new MeasurandParser("sensor-co2-pm10", "PM10 Air Quality (CO₂-Sensor)", MeasureType.PM10),
new MeasurandParser("sensor-co2-pm10-24-hour-average", "PM10 Air Quality 24 hour average (CO₂-Sensor)",
MeasureType.PM10),
new MeasurandParser("sensor-co2-pm25", "PM2.5 Air Quality (CO₂-Sensor)", MeasureType.PM25),
new MeasurandParser("sensor-co2-pm25-24-hour-average", "PM2.5 Air Quality 24 hour average (CO₂-Sensor)",
MeasureType.PM25),
new MeasurandParser("sensor-co2-co2", "CO₂", MeasureType.CO2),
new MeasurandParser("sensor-co2-co2-24-hour-average", "CO₂ 24 hour average", MeasureType.CO2),
// skip battery-level, since it is read via Command.CMD_READ_SENSOR_ID_NEW
new Skip(1)),
LEAF_WETNESS_CHX("leaf-wetness-channel", new int[] { 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79 },
"Leaf Moisture", MeasureType.PERCENTAGE, CHANNEL_TYPE_MOISTURE),
PIEZO_RAIN_RATE("piezo-rain-rate", 0x80, "Rain Rate", MeasureType.HEIGHT_PER_HOUR),
PIEZO_EVENT_RAIN("piezo-rain-event", 0x81, "Rain Event", MeasureType.HEIGHT),
PIEZO_HOURLY_RAIN("piezo-rain-hour", 0x82, "Rain hour", MeasureType.HEIGHT),
PIEZO_DAILY_RAIN("piezo-rain-day", 0x83, "Rain Day", MeasureType.HEIGHT_BIG),
PIEZO_WEEKLY_RAIN("piezo-rain-week", 0x84, "Rain Week", MeasureType.HEIGHT_BIG),
PIEZO_MONTHLY_RAIN("piezo-rain-month", 0x85, "Rain Month", MeasureType.HEIGHT_BIG),
PIEZO_YEARLY_RAIN("piezo-rain-year", 0x86, "Rain Year", MeasureType.HEIGHT_BIG),
PIEZO_GAIN10(0x87, new Skip(2)),
RST_RAIN_TIME(0x88, new Skip(3)),
;
private static final Map<Byte, SingleChannelMeasurand> MEASURANDS = new HashMap<>();
static {
for (Measurand measurand : values()) {
for (int i = 0; i < measurand.codes.length; i++) {
int code = measurand.codes[i];
// if we get more than one code this measurand has multiple channels
Integer channel = measurand.codes.length == 1 ? null : i + 1;
MEASURANDS.put((byte) code, new SingleChannelMeasurand(measurand, channel));
}
}
}
private final int[] codes;
private final Parser[] parsers;
Measurand(String channelId, int code, String name, MeasureType measureType, ParserCustomization... customizations) {
this(channelId, code, name, measureType, null, customizations);
}
Measurand(String channelId, int[] codes, String name, MeasureType measureType,
ParserCustomization... customizations) {
this(channelId, codes, name, measureType, null, customizations);
}
Measurand(String channelId, int code, String name, MeasureType measureType, @Nullable ChannelTypeUID channelTypeUID,
ParserCustomization... customizations) {
this(code, new MeasurandParser(channelId, name, measureType, channelTypeUID, customizations));
}
Measurand(String channelId, int[] codes, String name, MeasureType measureType,
@Nullable ChannelTypeUID channelTypeUID, ParserCustomization... customizations) {
this(codes, new MeasurandParser(channelId, name, measureType, channelTypeUID, customizations));
}
Measurand(int code, Parser... parsers) {
this(new int[] { code }, parsers);
}
Measurand(int[] codes, Parser... parsers) {
this.codes = codes;
this.parsers = parsers;
}
public static @Nullable SingleChannelMeasurand getByCode(byte code) {
return MEASURANDS.get(code);
}
private int extractMeasuredValues(byte[] data, int offset, @Nullable Integer channel, ConversionContext context,
@Nullable ParserCustomizationType customizationType, List<MeasuredValue> result) {
int subOffset = 0;
for (Parser parser : parsers) {
subOffset += parser.extractMeasuredValues(data, offset + subOffset, channel, context, customizationType,
result);
}
return subOffset;
}
private interface Parser {
int extractMeasuredValues(byte[] data, int offset, @Nullable Integer channel, ConversionContext context,
@Nullable ParserCustomizationType customizationType, List<MeasuredValue> result);
}
private static class Skip implements Parser {
private final int skip;
public Skip(int skip) {
this.skip = skip;
}
@Override
public int extractMeasuredValues(byte[] data, int offset, @Nullable Integer channel, ConversionContext context,
@Nullable ParserCustomizationType customizationType, List<MeasuredValue> result) {
return skip;
}
}
public enum ParserCustomizationType {
ELV,
RAIN_READING
}
private static class ParserCustomization {
private final ParserCustomizationType type;
private final MeasureType measureType;
public ParserCustomization(ParserCustomizationType type, MeasureType measureType) {
this.type = type;
this.measureType = measureType;
}
public ParserCustomizationType getType() {
return type;
}
public MeasureType getMeasureType() {
return measureType;
}
}
public static class SingleChannelMeasurand {
private final Measurand measurand;
private final @Nullable Integer channel;
public SingleChannelMeasurand(Measurand measurand, @Nullable Integer channel) {
this.measurand = measurand;
this.channel = channel;
}
public int extractMeasuredValues(byte[] data, int offset, ConversionContext context,
@Nullable ParserCustomizationType customizationType, List<MeasuredValue> result) {
return measurand.extractMeasuredValues(data, offset, channel, context, customizationType, result);
}
}
private static class MeasurandParser implements Parser {
private final String name;
private final String channelPrefix;
private final MeasureType measureType;
private final @Nullable Map<ParserCustomizationType, ParserCustomization> customizations;
private final @Nullable ChannelTypeUID channelTypeUID;
MeasurandParser(String channelPrefix, String name, MeasureType measureType,
ParserCustomization... customizations) {
this(channelPrefix, name, measureType, null, customizations);
}
MeasurandParser(String channelPrefix, String name, MeasureType measureType,
@Nullable ChannelTypeUID channelTypeUID, ParserCustomization... customizations) {
this.channelPrefix = channelPrefix;
this.name = name;
this.measureType = measureType;
this.channelTypeUID = channelTypeUID;
if (customizations.length == 0) {
this.customizations = null;
} else {
this.customizations = Collections.unmodifiableMap(
Arrays.stream(customizations).collect(Collectors.toMap(ParserCustomization::getType,
customization -> customization, (a, b) -> b, HashMap::new)));
}
}
public int extractMeasuredValues(byte[] data, int offset, @Nullable Integer channel, ConversionContext context,
@Nullable ParserCustomizationType customizationType, List<MeasuredValue> result) {
MeasureType measureType = getMeasureType(customizationType);
State state = measureType.toState(data, offset, context);
if (state != null) {
ChannelTypeUID channelType = channelTypeUID == null ? measureType.getChannelTypeId() : channelTypeUID;
result.add(new MeasuredValue(measureType, channelPrefix, channel, channelType, state, name));
}
return measureType.getByteSize();
}
public MeasureType getMeasureType(@Nullable ParserCustomizationType customizationType) {
if (customizationType == null)
return measureType;
return Optional.ofNullable(customizations).map(m -> m.get(customizationType))
.map(ParserCustomization::getMeasureType).orElse(measureType);
}
}
}

View File

@ -1,171 +0,0 @@
/**
* Copyright (c) 2010-2022 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.fineoffsetweatherstation.internal.domain;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.fineoffsetweatherstation.internal.FineOffsetWeatherStationBindingConstants;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.response.MeasuredValue;
import org.openhab.core.thing.type.ChannelTypeUID;
import org.openhab.core.types.State;
/**
* Holds all the measurands supported by the gateway.
*
* @author Andreas Berger - Initial contribution
*/
@NonNullByDefault
public class Measurands {
private static final Map<Protocol, Measurands> INSTANCES = new HashMap<>();
private final Map<Byte, List<Parser>> parsersPerCode = new HashMap<>();
private Measurands(Protocol protocol) {
try (InputStream data = Measurands.class.getResourceAsStream("/measurands.csv")) {
if (data == null) {
throw new IllegalStateException("Missing measurands.csv");
}
CSVFormat csvFormat = CSVFormat.Builder.create().setHeader().setSkipHeaderRecord(true).build();
CSVParser.parse(new InputStreamReader(data), csvFormat).forEach(row -> {
byte code = Byte.valueOf(row.get("Code").replace("0x", ""), 16);
Optional<Integer> skip = Optional.ofNullable(row.get("Skip")).filter(Predicate.not(String::isBlank))
.map(Integer::valueOf);
int index = Optional.ofNullable(row.get("Index")).filter(Predicate.not(String::isBlank))
.map(Integer::valueOf).orElse(0);
Parser parser;
if (skip.isPresent()) {
parser = new Skip(skip.get(), index);
} else {
String name = row.get("Name");
String channel = row.get("Channel");
ChannelTypeUID channelType = Optional.ofNullable(row.get("ChannelType"))
.filter(Predicate.not(String::isBlank)).map(s -> {
if (s.contains(":")) {
return new ChannelTypeUID(s);
} else {
return new ChannelTypeUID(FineOffsetWeatherStationBindingConstants.BINDING_ID, s);
}
}).orElse(null);
String measurandString = protocol == Protocol.DEFAULT ? row.get("MeasureType_DEFAULT")
: Optional.ofNullable(row.get("MeasureType_" + protocol.name()))
.filter(Predicate.not(String::isBlank))
.orElseGet(() -> row.get("MeasureType_DEFAULT"));
parser = new MeasurandParser(channel, name, MeasureType.valueOf(measurandString), index,
channelType);
}
List<Parser> parsers = parsersPerCode.computeIfAbsent(code, aByte -> new ArrayList<>());
// noinspection ConstantConditions
if (parsers != null) {
parsers.add(parser);
}
});
for (List<Parser> parsers : parsersPerCode.values()) {
parsers.sort(Comparator.comparing(Parser::getIndex));
}
} catch (IOException e) {
throw new IllegalStateException("Failed to read measurands.csv", e);
}
}
public static Measurands getInstance(Protocol protocol) {
synchronized (INSTANCES) {
return Objects.requireNonNull(INSTANCES.computeIfAbsent(protocol, Measurands::new));
}
}
private abstract static class Parser {
private final int index;
public Parser(int index) {
this.index = index;
}
public abstract int extractMeasuredValues(byte[] data, int offset, ConversionContext context,
List<MeasuredValue> result);
public int getIndex() {
return index;
}
}
private static class Skip extends Parser {
private final int skip;
public Skip(int skip, int index) {
super(index);
this.skip = skip;
}
@Override
public int extractMeasuredValues(byte[] data, int offset, ConversionContext context,
List<MeasuredValue> result) {
return skip;
}
}
private static class MeasurandParser extends Parser {
private final String name;
private final String channelId;
private final MeasureType measureType;
private final @Nullable ChannelTypeUID channelTypeUID;
MeasurandParser(String channelId, String name, MeasureType measureType, int index,
@Nullable ChannelTypeUID channelTypeUID) {
super(index);
this.channelId = channelId;
this.name = name;
this.measureType = measureType;
this.channelTypeUID = channelTypeUID == null ? measureType.getChannelTypeId() : channelTypeUID;
}
public int extractMeasuredValues(byte[] data, int offset, ConversionContext context,
List<MeasuredValue> result) {
State state = measureType.toState(data, offset, context);
if (state != null) {
result.add(new MeasuredValue(measureType, channelId, channelTypeUID, state, name));
}
return measureType.getByteSize();
}
}
public int extractMeasuredValues(byte code, byte[] data, int offset, ConversionContext context,
List<MeasuredValue> result) {
List<Parser> parsers = parsersPerCode.get(code);
if (parsers == null) {
throw new IllegalArgumentException("No measurement for code 0x" + Integer.toHexString(code) + " defined");
}
int subOffset = 0;
for (Parser parser : parsers) {
subOffset += parser.extractMeasuredValues(data, offset + subOffset, context, result);
}
return subOffset;
}
}

View File

@ -27,13 +27,20 @@ import org.openhab.binding.fineoffsetweatherstation.internal.service.GatewayQuer
*/ */
@NonNullByDefault @NonNullByDefault
public enum Protocol { public enum Protocol {
DEFAULT(FineOffsetGatewayQueryService::new), DEFAULT(FineOffsetGatewayQueryService::new, null),
ELV(ELVGatewayQueryService::new); ELV(ELVGatewayQueryService::new, Measurand.ParserCustomizationType.ELV);
private final GatewayQueryServiceFactory queryServiceFactory; private final GatewayQueryServiceFactory queryServiceFactory;
private final Measurand.@Nullable ParserCustomizationType parserCustomizationType;
Protocol(GatewayQueryServiceFactory queryServiceFactory) { Protocol(GatewayQueryServiceFactory queryServiceFactory,
Measurand.@Nullable ParserCustomizationType parserCustomizationType) {
this.queryServiceFactory = queryServiceFactory; this.queryServiceFactory = queryServiceFactory;
this.parserCustomizationType = parserCustomizationType;
}
public Measurand.@Nullable ParserCustomizationType getParserCustomizationType() {
return parserCustomizationType;
} }
public GatewayQueryService getGatewayQueryService(FineOffsetGatewayConfiguration config, public GatewayQueryService getGatewayQueryService(FineOffsetGatewayConfiguration config,

View File

@ -26,26 +26,32 @@ import org.openhab.core.types.State;
@NonNullByDefault @NonNullByDefault
public class MeasuredValue { public class MeasuredValue {
private final MeasureType measureType; private final MeasureType measureType;
private final String channelId; private final String channelPrefix;
private final @Nullable Integer channelNumber;
private final @Nullable ChannelTypeUID channelTypeUID; private final @Nullable ChannelTypeUID channelTypeUID;
private final State state; private final State state;
private final String debugName; private final String debugName;
public MeasuredValue(MeasureType measureType, String channelId, @Nullable ChannelTypeUID channelTypeUID, public MeasuredValue(MeasureType measureType, String channelPrefix, @Nullable Integer channelNumber,
State state, String debugName) { @Nullable ChannelTypeUID channelTypeUID, State state, String debugName) {
this.measureType = measureType; this.measureType = measureType;
this.channelId = channelId; this.channelPrefix = channelPrefix;
this.channelNumber = channelNumber;
this.channelTypeUID = channelTypeUID; this.channelTypeUID = channelTypeUID;
this.state = state; this.state = state;
this.debugName = debugName; this.debugName = debugName;
} }
public MeasureType getMeasureType() { public String getChannelId() {
return measureType; return channelNumber == null ? channelPrefix : (channelPrefix + "-" + channelNumber);
} }
public String getChannelId() { public String getChannelPrefix() {
return channelId; return channelPrefix;
}
public @Nullable Integer getChannelNumber() {
return channelNumber;
} }
public @Nullable ChannelTypeUID getChannelTypeUID() { public @Nullable ChannelTypeUID getChannelTypeUID() {
@ -62,7 +68,7 @@ public class MeasuredValue {
@Override @Override
public String toString() { public String toString() {
return "MeasuredValue{" + "measureType=" + measureType + ", channelId='" + channelId + '\'' return "MeasuredValue{" + "measureType=" + measureType + ", channelId='" + getChannelId() + '\''
+ ", channelTypeUID=" + channelTypeUID + ", state=" + state + ", debugName='" + debugName + '\'' + '}'; + ", channelTypeUID=" + channelTypeUID + ", state=" + state + ", debugName='" + debugName + '\'' + '}';
} }
} }

View File

@ -17,6 +17,7 @@ import static org.openhab.binding.fineoffsetweatherstation.internal.FineOffsetWe
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -30,7 +31,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.fineoffsetweatherstation.internal.FineOffsetGatewayConfiguration; import org.openhab.binding.fineoffsetweatherstation.internal.FineOffsetGatewayConfiguration;
import org.openhab.binding.fineoffsetweatherstation.internal.FineOffsetSensorConfiguration; import org.openhab.binding.fineoffsetweatherstation.internal.FineOffsetSensorConfiguration;
import org.openhab.binding.fineoffsetweatherstation.internal.FineOffsetWeatherStationBindingConstants;
import org.openhab.binding.fineoffsetweatherstation.internal.discovery.FineOffsetGatewayDiscoveryService; import org.openhab.binding.fineoffsetweatherstation.internal.discovery.FineOffsetGatewayDiscoveryService;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.ConversionContext; import org.openhab.binding.fineoffsetweatherstation.internal.domain.ConversionContext;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.SensorGatewayBinding; import org.openhab.binding.fineoffsetweatherstation.internal.domain.SensorGatewayBinding;
@ -156,7 +156,7 @@ public class FineOffsetGatewayHandler extends BaseBridgeHandler {
if (disposed) { if (disposed) {
return; return;
} }
List<MeasuredValue> data = query(GatewayQueryService::getMeasuredValues); Collection<MeasuredValue> data = query(GatewayQueryService::getMeasuredValues);
if (data == null) { if (data == null) {
getThing().getChannels().forEach(c -> updateState(c.getUID(), UnDefType.UNDEF)); getThing().getChannels().forEach(c -> updateState(c.getUID(), UnDefType.UNDEF));
return; return;
@ -189,15 +189,14 @@ public class FineOffsetGatewayHandler extends BaseBridgeHandler {
} }
ChannelBuilder builder = ChannelBuilder.create(new ChannelUID(thing.getUID(), measuredValue.getChannelId())) ChannelBuilder builder = ChannelBuilder.create(new ChannelUID(thing.getUID(), measuredValue.getChannelId()))
.withKind(ChannelKind.STATE).withType(channelTypeId); .withKind(ChannelKind.STATE).withType(channelTypeId);
String channelKey = "thing-type." + FineOffsetWeatherStationBindingConstants.BINDING_ID + "." String channelKey = THING_TYPE_GATEWAY.getId() + ".dynamic-channel." + measuredValue.getChannelPrefix();
+ THING_TYPE_GATEWAY.getId() + ".channel." + measuredValue.getChannelId();
String label = translationProvider.getText(bundle, channelKey + ".label", measuredValue.getDebugName(), String label = translationProvider.getText(bundle, channelKey + ".label", measuredValue.getDebugName(),
localeProvider.getLocale()); localeProvider.getLocale(), measuredValue.getChannelNumber());
if (label != null) { if (label != null) {
builder.withLabel(label); builder.withLabel(label);
} }
String description = translationProvider.getText(bundle, channelKey + ".description", null, String description = translationProvider.getText(bundle, channelKey + ".description", null,
localeProvider.getLocale()); localeProvider.getLocale(), measuredValue.getChannelNumber());
if (description != null) { if (description != null) {
builder.withDescription(description); builder.withDescription(description);
} }

View File

@ -22,6 +22,7 @@ import org.openhab.binding.fineoffsetweatherstation.internal.domain.response.Sen
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;
import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.Channel; import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing; import org.openhab.core.thing.Thing;
@ -31,8 +32,6 @@ import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.types.Command; import org.openhab.core.types.Command;
import org.openhab.core.types.UnDefType; import org.openhab.core.types.UnDefType;
import tech.units.indriya.unit.Units;
/** /**
* The {@link FineOffsetSensorHandler} keeps track of the signal and battery of the sensor attached to the gateway. * The {@link FineOffsetSensorHandler} keeps track of the signal and battery of the sensor attached to the gateway.
* *

View File

@ -27,7 +27,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.fineoffsetweatherstation.internal.Utils; import org.openhab.binding.fineoffsetweatherstation.internal.Utils;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.ConversionContext; import org.openhab.binding.fineoffsetweatherstation.internal.domain.ConversionContext;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.Measurands; import org.openhab.binding.fineoffsetweatherstation.internal.domain.Measurand;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.Protocol; import org.openhab.binding.fineoffsetweatherstation.internal.domain.Protocol;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.SensorGatewayBinding; import org.openhab.binding.fineoffsetweatherstation.internal.domain.SensorGatewayBinding;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.response.BatteryStatus; import org.openhab.binding.fineoffsetweatherstation.internal.domain.response.BatteryStatus;
@ -174,17 +174,25 @@ public class FineOffsetDataParser {
if (protocol == Protocol.ELV) { if (protocol == Protocol.ELV) {
idx++; // at index 5 there is an additional Byte being set to 0x04 idx++; // at index 5 there is an additional Byte being set to 0x04
} }
return readMeasuredValues(data, idx, context, protocol.getParserCustomizationType());
}
List<MeasuredValue> getRainData(byte[] data, ConversionContext context) {
return readMeasuredValues(data, 5, context, Measurand.ParserCustomizationType.RAIN_READING);
}
private List<MeasuredValue> readMeasuredValues(byte[] data, int idx, ConversionContext context,
Measurand.@Nullable ParserCustomizationType protocol) {
var size = toUInt16(data, 3); var size = toUInt16(data, 3);
List<MeasuredValue> result = new ArrayList<>(); List<MeasuredValue> result = new ArrayList<>();
Measurands measurands = Measurands.getInstance(protocol);
while (idx < size) { while (idx < size) {
byte code = data[idx++]; byte code = data[idx++];
try { Measurand.SingleChannelMeasurand measurand = Measurand.getByCode(code);
idx += measurands.extractMeasuredValues(code, data, idx, context, result); if (measurand == null) {
} catch (IllegalArgumentException e) { logger.warn("failed to get measurand 0x{}", Integer.toHexString(code));
logger.warn("", e);
return result; return result;
} }
idx += measurand.extractMeasuredValues(data, idx, context, protocol, result);
} }
return result; return result;
} }

View File

@ -12,7 +12,8 @@
*/ */
package org.openhab.binding.fineoffsetweatherstation.internal.service; package org.openhab.binding.fineoffsetweatherstation.internal.service;
import java.util.Collections; import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -86,12 +87,26 @@ public class FineOffsetGatewayQueryService extends GatewayQueryService {
} }
@Override @Override
public List<MeasuredValue> getMeasuredValues() { public Collection<MeasuredValue> getMeasuredValues() {
Map<String, MeasuredValue> valuePerChannel = new LinkedHashMap<>();
byte[] data = executeCommand(Command.CMD_GW1000_LIVEDATA); byte[] data = executeCommand(Command.CMD_GW1000_LIVEDATA);
if (data == null) { if (data != null) {
return Collections.emptyList(); List<MeasuredValue> measuredValues = fineOffsetDataParser.getMeasuredValues(data, conversionContext);
for (MeasuredValue measuredValue : measuredValues) {
valuePerChannel.put(measuredValue.getChannelId(), measuredValue);
}
} }
return fineOffsetDataParser.getMeasuredValues(data, conversionContext);
data = executeCommand(Command.CMD_READ_RAIN);
if (data != null) {
List<MeasuredValue> measuredRainValues = fineOffsetDataParser.getRainData(data, conversionContext);
for (MeasuredValue measuredValue : measuredRainValues) {
valuePerChannel.put(measuredValue.getChannelId(), measuredValue);
}
}
return valuePerChannel.values();
} }
protected byte @Nullable [] executeCommand(Command command) { protected byte @Nullable [] executeCommand(Command command) {

View File

@ -16,7 +16,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.Socket; import java.net.Socket;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
@ -63,7 +63,7 @@ public abstract class GatewayQueryService implements AutoCloseable {
@Nullable @Nullable
public abstract SystemInfo fetchSystemInfo(); public abstract SystemInfo fetchSystemInfo();
public abstract List<MeasuredValue> getMeasuredValues(); public abstract Collection<MeasuredValue> getMeasuredValues();
public GatewayQueryService(FineOffsetGatewayConfiguration config, public GatewayQueryService(FineOffsetGatewayConfiguration config,
@Nullable ThingStatusListener thingStatusListener) { @Nullable ThingStatusListener thingStatusListener) {

View File

@ -76,119 +76,63 @@ thing.sensor.WH68.description = Solar-powered Sensor for Wind Speed & Direction,
thing.sensor.WH80.label = Weather Station - outdoor unit thing.sensor.WH80.label = Weather Station - outdoor unit
thing.sensor.WH80.description = Ultrasonic Sensor for Wind Speed & Direction, Solar Radiation & Light, Temperature & Humidity thing.sensor.WH80.description = Ultrasonic Sensor for Wind Speed & Direction, Solar Radiation & Light, Temperature & Humidity
thing.sensor.WH90.label = Weather Station - outdoor unit thing.sensor.WH90.label = Weather Station - outdoor unit
thing.sensor.WH90.description = Ultrasonic sensor for wind speed & direction, solar radiation & light, temperature, humidity and haptic rainfall Sensor
# channels # channels
thing-type.fineoffsetweatherstation.gateway.channel.temperature-indoor.label = Indoor Temperature
thing-type.fineoffsetweatherstation.gateway.channel.temperature-outdoor.label = Outdoor Temperature
thing-type.fineoffsetweatherstation.gateway.channel.temperature-dew-point.label = Dew Point
thing-type.fineoffsetweatherstation.gateway.channel.temperature-wind-chill.label = Perceived Temperature
thing-type.fineoffsetweatherstation.gateway.channel.temperature-heat-index.label = Heat Index
thing-type.fineoffsetweatherstation.gateway.channel.humidity-indoor.label = Humidity Inside
thing-type.fineoffsetweatherstation.gateway.channel.humidity-outdoor.label = Humidity Outside
thing-type.fineoffsetweatherstation.gateway.channel.pressure-absolute.label = Absolute Pressure
thing-type.fineoffsetweatherstation.gateway.channel.pressure-relative.label = Relative Pressure
thing-type.fineoffsetweatherstation.gateway.channel.direction-wind.label = Wind Direction
thing-type.fineoffsetweatherstation.gateway.channel.speed-wind.label = Wind Speed
thing-type.fineoffsetweatherstation.gateway.channel.speed-gust.label = Gust Speed
thing-type.fineoffsetweatherstation.gateway.channel.rain-event.label = Amount of Rainfall At the last Rain
thing-type.fineoffsetweatherstation.gateway.channel.rain-rate.label = Rainfall Rate
thing-type.fineoffsetweatherstation.gateway.channel.rain-hour.label = Rainfall Current Hour
thing-type.fineoffsetweatherstation.gateway.channel.rain-day.label = Rainfall Today
thing-type.fineoffsetweatherstation.gateway.channel.rain-week.label = Rainfall this Week
thing-type.fineoffsetweatherstation.gateway.channel.rain-month.label = Rainfall this Month
thing-type.fineoffsetweatherstation.gateway.channel.rain-year.label = Rainfall this Year
thing-type.fineoffsetweatherstation.gateway.channel.rain-total.label = Rainfall Total
thing-type.fineoffsetweatherstation.gateway.channel.illumination.label = Light Intensity
thing-type.fineoffsetweatherstation.gateway.channel.irradiation-uv.label = UV Irradiation
thing-type.fineoffsetweatherstation.gateway.channel.uv-index.label = UV Index
thing-type.fineoffsetweatherstation.gateway.channel.time.label = Date and Time
thing-type.fineoffsetweatherstation.gateway.channel.wind-max-day.label = Maximum Wind Speed Today
thing-type.fineoffsetweatherstation.gateway.channel.temperature-channel-1.label = Temperature Channel 1
thing-type.fineoffsetweatherstation.gateway.channel.temperature-channel-2.label = Temperature Channel 2
thing-type.fineoffsetweatherstation.gateway.channel.temperature-channel-3.label = Temperature Channel 3
thing-type.fineoffsetweatherstation.gateway.channel.temperature-channel-4.label = Temperature Channel 4
thing-type.fineoffsetweatherstation.gateway.channel.temperature-channel-5.label = Temperature Channel 5
thing-type.fineoffsetweatherstation.gateway.channel.temperature-channel-6.label = Temperature Channel 6
thing-type.fineoffsetweatherstation.gateway.channel.temperature-channel-7.label = Temperature Channel 7
thing-type.fineoffsetweatherstation.gateway.channel.temperature-channel-8.label = Temperature Channel 8
thing-type.fineoffsetweatherstation.gateway.channel.humidity-channel-1.label = Humidity Channel 1
thing-type.fineoffsetweatherstation.gateway.channel.humidity-channel-2.label = Humidity Channel 2
thing-type.fineoffsetweatherstation.gateway.channel.humidity-channel-3.label = Humidity Channel 3
thing-type.fineoffsetweatherstation.gateway.channel.humidity-channel-4.label = Humidity Channel 4
thing-type.fineoffsetweatherstation.gateway.channel.humidity-channel-5.label = Humidity Channel 5
thing-type.fineoffsetweatherstation.gateway.channel.humidity-channel-6.label = Humidity Channel 6
thing-type.fineoffsetweatherstation.gateway.channel.humidity-channel-7.label = Humidity Channel 7
thing-type.fineoffsetweatherstation.gateway.channel.humidity-channel-8.label = Humidity Channel 8
thing-type.fineoffsetweatherstation.gateway.channel.temperature-soil-channel-1.label = Soil Temperature Channel 1
thing-type.fineoffsetweatherstation.gateway.channel.temperature-soil-channel-2.label = Soil Temperature Channel 2
thing-type.fineoffsetweatherstation.gateway.channel.temperature-soil-channel-3.label = Soil Temperature Channel 3
thing-type.fineoffsetweatherstation.gateway.channel.temperature-soil-channel-4.label = Soil Temperature Channel 4
thing-type.fineoffsetweatherstation.gateway.channel.temperature-soil-channel-5.label = Soil Temperature Channel 5
thing-type.fineoffsetweatherstation.gateway.channel.temperature-soil-channel-6.label = Soil Temperature Channel 6
thing-type.fineoffsetweatherstation.gateway.channel.temperature-soil-channel-7.label = Soil Temperature Channel 7
thing-type.fineoffsetweatherstation.gateway.channel.temperature-soil-channel-8.label = Soil Temperature Channel 8
thing-type.fineoffsetweatherstation.gateway.channel.temperature-soil-channel-9.label = Soil Temperature Channel 9
thing-type.fineoffsetweatherstation.gateway.channel.temperature-soil-channel-10.label = Soil Temperature Channel 10
thing-type.fineoffsetweatherstation.gateway.channel.temperature-soil-channel-11.label = Soil Temperature Channel 11
thing-type.fineoffsetweatherstation.gateway.channel.temperature-soil-channel-12.label = Soil Temperature Channel 12
thing-type.fineoffsetweatherstation.gateway.channel.temperature-soil-channel-13.label = Soil Temperature Channel 13
thing-type.fineoffsetweatherstation.gateway.channel.temperature-soil-channel-14.label = Soil Temperature Channel 14
thing-type.fineoffsetweatherstation.gateway.channel.temperature-soil-channel-15.label = Soil Temperature Channel 15
thing-type.fineoffsetweatherstation.gateway.channel.temperature-soil-channel-16.label = Soil Temperature Channel 16
thing-type.fineoffsetweatherstation.gateway.channel.moisture-soil-channel-1.label = Soil Moisture Channel 1
thing-type.fineoffsetweatherstation.gateway.channel.moisture-soil-channel-2.label = Soil Moisture Channel 2
thing-type.fineoffsetweatherstation.gateway.channel.moisture-soil-channel-3.label = Soil Moisture Channel 3
thing-type.fineoffsetweatherstation.gateway.channel.moisture-soil-channel-4.label = soil Moisture Channel 4
thing-type.fineoffsetweatherstation.gateway.channel.moisture-soil-channel-5.label = Soil Moisture Channel 5
thing-type.fineoffsetweatherstation.gateway.channel.moisture-soil-channel-6.label = Soil Moisture Channel 6
thing-type.fineoffsetweatherstation.gateway.channel.moisture-soil-channel-7.label = Soil Moisture Channel 7
thing-type.fineoffsetweatherstation.gateway.channel.moisture-soil-channel-8.label = Soil Moisture Channel 8
thing-type.fineoffsetweatherstation.gateway.channel.moisture-soil-channel-9.label = Soil Moisture Channel 9
thing-type.fineoffsetweatherstation.gateway.channel.moisture-soil-channel-10.label = Soil Moisture Channel 10
thing-type.fineoffsetweatherstation.gateway.channel.moisture-soil-channel-11.label = Soil Moisture Channel 11
thing-type.fineoffsetweatherstation.gateway.channel.moisture-soil-channel-12.label = Soil Moisture Channel 12
thing-type.fineoffsetweatherstation.gateway.channel.moisture-soil-channel-13.label = soil Moisture Channel 13
thing-type.fineoffsetweatherstation.gateway.channel.moisture-soil-channel-14.label = Soil Moisture Channel 14
thing-type.fineoffsetweatherstation.gateway.channel.moisture-soil-channel-15.label = Soil Moisture Channel 15
thing-type.fineoffsetweatherstation.gateway.channel.moisture-soil-channel-16.label = Soil Moisture Channel 16
thing-type.fineoffsetweatherstation.gateway.channel.air-quality-24-hour-average-channel-1.label = PM2.5 Air Quality 24 Hour Average Channel 1
thing-type.fineoffsetweatherstation.gateway.channel.air-quality-24-hour-average-channel-2.label = PM2.5 Air Quality 24 Hour Average Channel 2
thing-type.fineoffsetweatherstation.gateway.channel.air-quality-24-hour-average-channel-3.label = PM2.5 Air Quality 24 Hour Average Channel 3
thing-type.fineoffsetweatherstation.gateway.channel.air-quality-24-hour-average-channel-4.label = PM2.5 Air Quality 24 Hour Average Channel 4
thing-type.fineoffsetweatherstation.gateway.channel.air-quality-channel-1.label = PM2.5 Air Quality Channel 1
thing-type.fineoffsetweatherstation.gateway.channel.air-quality-channel-2.label = PM2.5 Air Quality Channel 2
thing-type.fineoffsetweatherstation.gateway.channel.air-quality-channel-3.label = PM2.5 Air Quality Channel 3
thing-type.fineoffsetweatherstation.gateway.channel.air-quality-channel-4.label = PM2.5 Air Quality Channel 4
thing-type.fineoffsetweatherstation.gateway.channel.water-leak-channel-1.label = Water Leak Detection Channel 1
thing-type.fineoffsetweatherstation.gateway.channel.water-leak-channel-2.label = Water Leak Detection Channel 2
thing-type.fineoffsetweatherstation.gateway.channel.water-leak-channel-3.label = Water Leak Detection Channel 3
thing-type.fineoffsetweatherstation.gateway.channel.water-leak-channel-4.label = Water Leak Detection Channel 4
thing-type.fineoffsetweatherstation.gateway.channel.lightning-distance.label = Lightning Distance
thing-type.fineoffsetweatherstation.gateway.channel.lightning-time.label = Time of last Lightning Strike
thing-type.fineoffsetweatherstation.gateway.channel.lightning-counter.label = Lightning Strikes Today
thing-type.fineoffsetweatherstation.gateway.channel.temperature-external-channel-1.label = External Temperature Sensor Channel 1
thing-type.fineoffsetweatherstation.gateway.channel.temperature-external-channel-2.label = External Temperature Sensor Channel 2
thing-type.fineoffsetweatherstation.gateway.channel.temperature-external-channel-3.label = External Temperature Sensor Channel 3
thing-type.fineoffsetweatherstation.gateway.channel.temperature-external-channel-4.label = External Temperature Sensor Channel 4
thing-type.fineoffsetweatherstation.gateway.channel.temperature-external-channel-5.label = External Temperature Sensor Channel 5
thing-type.fineoffsetweatherstation.gateway.channel.temperature-external-channel-6.label = External Temperature Sensor Channel 6
thing-type.fineoffsetweatherstation.gateway.channel.temperature-external-channel-7.label = External Temperature Sensor Channel 7
thing-type.fineoffsetweatherstation.gateway.channel.temperature-external-channel-8.label = External Temperature Sensor Channel 8
thing-type.fineoffsetweatherstation.gateway.channel.sensor-co2-temperature.label = Temperature (CO2-Sensor)
thing-type.fineoffsetweatherstation.gateway.channel.sensor-co2-humidity.label = Humidity (CO2-Sensor)
thing-type.fineoffsetweatherstation.gateway.channel.sensor-co2-pm10.label = PM10 Air Quality (CO2-Sensor)
thing-type.fineoffsetweatherstation.gateway.channel.sensor-co2-pm10-24-hour-average.label = PM10 Air Quality 24 Hour Average (CO2-Sensor)
thing-type.fineoffsetweatherstation.gateway.channel.sensor-co2-pm25.label = PM2.5 Air Quality (CO2-Sensor)
thing-type.fineoffsetweatherstation.gateway.channel.sensor-co2-pm25-24-hour-average.label = PM2.5 Air Quality 24 Hour Average (CO2-Sensor)
thing-type.fineoffsetweatherstation.gateway.channel.sensor-co2-co2.label = CO2
thing-type.fineoffsetweatherstation.gateway.channel.sensor-co2-co2-24-hour-average.label = CO2 24 Hour Average
thing-type.fineoffsetweatherstation.gateway.channel.leaf-wetness-channel-1.label = Leaf Moisture Channel 1
thing-type.fineoffsetweatherstation.gateway.channel.leaf-wetness-channel-2.label = Leaf Moisture Channel 2
thing-type.fineoffsetweatherstation.gateway.channel.leaf-wetness-channel-3.label = Leaf Moisture Channel 3
thing-type.fineoffsetweatherstation.gateway.channel.leaf-wetness-channel-4.label = Leaf Moisture Channel 4
thing-type.fineoffsetweatherstation.gateway.channel.leaf-wetness-channel-5.label = Leaf Moisture Channel 5
thing-type.fineoffsetweatherstation.gateway.channel.leaf-wetness-channel-6.label = Leaf Moisture Channel 6
thing-type.fineoffsetweatherstation.gateway.channel.leaf-wetness-channel-7.label = Leaf Moisture Channel 7
thing-type.fineoffsetweatherstation.gateway.channel.leaf-wetness-channel-8.label = Leaf Moisture Channel 8
thing-type.fineoffsetweatherstation.sensor.channel.batteryVoltage.label = Battery Voltage thing-type.fineoffsetweatherstation.sensor.channel.batteryVoltage.label = Battery Voltage
# dynamic channels
gateway.dynamic-channel.temperature-indoor.label = Indoor Temperature
gateway.dynamic-channel.temperature-outdoor.label = Outdoor Temperature
gateway.dynamic-channel.temperature-dew-point.label = Dew Point
gateway.dynamic-channel.temperature-wind-chill.label = Perceived Temperature
gateway.dynamic-channel.temperature-heat-index.label = Heat Index
gateway.dynamic-channel.humidity-indoor.label = Humidity Inside
gateway.dynamic-channel.humidity-outdoor.label = Humidity Outside
gateway.dynamic-channel.pressure-absolute.label = Absolute Pressure
gateway.dynamic-channel.pressure-relative.label = Relative Pressure
gateway.dynamic-channel.direction-wind.label = Wind Direction
gateway.dynamic-channel.speed-wind.label = Wind Speed
gateway.dynamic-channel.speed-gust.label = Gust Speed
gateway.dynamic-channel.rain-event.label = Amount of Rainfall At the last Rain
gateway.dynamic-channel.rain-rate.label = Rainfall Rate
gateway.dynamic-channel.rain-hour.label = Rainfall Current Hour
gateway.dynamic-channel.rain-day.label = Rainfall Today
gateway.dynamic-channel.rain-week.label = Rainfall this Week
gateway.dynamic-channel.rain-month.label = Rainfall this Month
gateway.dynamic-channel.rain-year.label = Rainfall this Year
gateway.dynamic-channel.rain-total.label = Rainfall Total
gateway.dynamic-channel.illumination.label = Light Intensity
gateway.dynamic-channel.irradiation-uv.label = UV Irradiation
gateway.dynamic-channel.uv-index.label = UV Index
gateway.dynamic-channel.time.label = Date and Time
gateway.dynamic-channel.wind-max-day.label = Maximum Wind Speed Today
gateway.dynamic-channel.temperature-channel.label = Temperature Channel {0}
gateway.dynamic-channel.humidity-channel.label = Humidity Channel {0}
gateway.dynamic-channel.temperature-soil-channel.label = Soil Temperature Channel {0}
gateway.dynamic-channel.moisture-soil-channel.label = Soil Moisture Channel {0}
gateway.dynamic-channel.air-quality-24-hour-average-channel.label = PM2.5 Air Quality 24 Hour Average Channel {0}
gateway.dynamic-channel.air-quality-channel.label = PM2.5 Air Quality Channel {0}
gateway.dynamic-channel.water-leak-channel.label = Water Leak Detection Channel {0}
gateway.dynamic-channel.lightning-distance.label = Lightning Distance
gateway.dynamic-channel.lightning-time.label = Time of last Lightning Strike
gateway.dynamic-channel.lightning-counter.label = Lightning Strikes Today
gateway.dynamic-channel.temperature-external-channel.label = External Temperature Sensor Channel {0}
gateway.dynamic-channel.sensor-co2-temperature.label = Temperature (CO2-Sensor)
gateway.dynamic-channel.sensor-co2-humidity.label = Humidity (CO2-Sensor)
gateway.dynamic-channel.sensor-co2-pm10.label = PM10 Air Quality (CO2-Sensor)
gateway.dynamic-channel.sensor-co2-pm10-24-hour-average.label = PM10 Air Quality 24 Hour Average (CO2-Sensor)
gateway.dynamic-channel.sensor-co2-pm25.label = PM2.5 Air Quality (CO2-Sensor)
gateway.dynamic-channel.sensor-co2-pm25-24-hour-average.label = PM2.5 Air Quality 24 Hour Average (CO2-Sensor)
gateway.dynamic-channel.sensor-co2-co2.label = CO2
gateway.dynamic-channel.sensor-co2-co2-24-hour-average.label = CO2 24 Hour Average
gateway.dynamic-channel.leaf-wetness-channel.label = Leaf Moisture Channel {0}
gateway.dynamic-channel.piezo-rain-rate.label = Rain Rate
gateway.dynamic-channel.piezo-rain-event.label = Rain Event
gateway.dynamic-channel.piezo-rain-hour.label = Rain hour
gateway.dynamic-channel.piezo-rain-day.label = Rain Day
gateway.dynamic-channel.piezo-rain-week.label = Rain Week
gateway.dynamic-channel.piezo-rain-month.label = Rain Month
gateway.dynamic-channel.piezo-rain-year.label = Rain Year

View File

@ -1,115 +0,0 @@
ManufacturerName,Name,Channel,Code,Index,Skip,ChannelType,MeasureType_DEFAULT,MeasureType_ELV
INTEMP,Indoor Temperature,temperature-indoor,0x1,,,system:indoor-temperature,TEMPERATURE,
OUTTEMP,Outdoor Temperature,temperature-outdoor,0x2,,,system:outdoor-temperature,TEMPERATURE,
DEWPOINT,Dew point,temperature-dew-point,0x3,,,,TEMPERATURE,
WINDCHILL,Wind chill,temperature-wind-chill,0x4,,,,TEMPERATURE,
HEATINDEX,Heat index,temperature-heat-index,0x5,,,,TEMPERATURE,
INHUMI,Indoor Humidity,humidity-indoor,0x6,,,,PERCENTAGE,
OUTHUMI,Outdoor Humidity,humidity-outdoor,0x7,,,system:atmospheric-humidity,PERCENTAGE,
ABSBARO,Absolutely pressure,pressure-absolute,0x8,,,,PRESSURE,
RELBARO,Relative pressure,pressure-relative,0x9,,,system:barometric-pressure,PRESSURE,
WINDDIRECTION,Wind Direction,direction-wind,0xa,,,system:wind-direction,DEGREE,
WINDSPEED,Wind Speed,speed-wind,0xb,,,system:wind-speed,SPEED,
GUSTSPEED,Gust Speed,speed-gust,0xc,,,system:wind-speed,SPEED,
RAINEVENT,Rain Event,rain-event,0xd,,,,HEIGHT,HEIGHT_BIG
RAINRATE,Rain Rate,rain-rate,0xe,,,,HEIGHT_PER_HOUR,HEIGHT_PER_HOUR_BIG
RAINHOUR,Rain hour,rain-hour,0xf,,,,HEIGHT,HEIGHT_BIG
RAINDAY,Rain Day,rain-day,0x10,,,,HEIGHT,HEIGHT_BIG
RAINWEEK,Rain Week,rain-week,0x11,,,,HEIGHT,HEIGHT_BIG
RAINMONTH,Rain Month,rain-month,0x12,,,,HEIGHT_BIG,
RAINYEAR,Rain Year,rain-year,0x13,,,,HEIGHT_BIG,
RAINTOTALS,Rain Totals,rain-total,0x14,,,,HEIGHT_BIG,
LIGHT,Light,illumination,0x15,,,,LUX,
UV,UV,irradiation-uv,0x16,,,,MILLIWATT_PER_SQUARE_METRE,
UVI,UV index,uv-index,0x17,,,uv-index,BYTE,
TIME,Date and time,time,0x18,,,,DATE_TIME2,
DAYLWINDMAX,Day max wind,wind-max-day,0x19,,,max-wind-speed,SPEED,
TEMP1,Temperature 1,temperature-channel-1,0x1a,,,,TEMPERATURE,
TEMP2,Temperature 2,temperature-channel-2,0x1b,,,,TEMPERATURE,
TEMP3,Temperature 3,temperature-channel-3,0x1c,,,,TEMPERATURE,
TEMP4,Temperature 4,temperature-channel-4,0x1d,,,,TEMPERATURE,
TEMP5,Temperature 5,temperature-channel-5,0x1e,,,,TEMPERATURE,
TEMP6,Temperature 6,temperature-channel-6,0x1f,,,,TEMPERATURE,
TEMP7,Temperature 7,temperature-channel-7,0x20,,,,TEMPERATURE,
TEMP8,Temperature 8,temperature-channel-8,0x21,,,,TEMPERATURE,
HUMI1,Humidity 1,humidity-channel-1,0x22,,,,PERCENTAGE,
HUMI2,Humidity 2,humidity-channel-2,0x23,,,,PERCENTAGE,
HUMI3,Humidity 3,humidity-channel-3,0x24,,,,PERCENTAGE,
HUMI4,Humidity 4,humidity-channel-4,0x25,,,,PERCENTAGE,
HUMI5,Humidity 5,humidity-channel-5,0x26,,,,PERCENTAGE,
HUMI6,Humidity 6,humidity-channel-6,0x27,,,,PERCENTAGE,
HUMI7,Humidity 7,humidity-channel-7,0x28,,,,PERCENTAGE,
HUMI8,Humidity 8,humidity-channel-8,0x29,,,,PERCENTAGE,
SOILTEMP1,Soil Temperature 1,temperature-soil-channel-1,0x2b,,,,TEMPERATURE,
SOILTEMP2,Soil Temperature 2,temperature-soil-channel-2,0x2d,,,,TEMPERATURE,
SOILTEMP3,Soil Temperature 3,temperature-soil-channel-3,0x2f,,,,TEMPERATURE,
SOILTEMP4,Soil Temperature 4,temperature-soil-channel-4,0x31,,,,TEMPERATURE,
SOILTEMP5,Soil Temperature 5,temperature-soil-channel-5,0x33,,,,TEMPERATURE,
SOILTEMP6,Soil Temperature 6,temperature-soil-channel-6,0x35,,,,TEMPERATURE,
SOILTEMP7,Soil Temperature 7,temperature-soil-channel-7,0x37,,,,TEMPERATURE,
SOILTEMP8,Soil Temperature 8,temperature-soil-channel-8,0x39,,,,TEMPERATURE,
SOILTEMP9,Soil Temperature 9,temperature-soil-channel-9,0x3b,,,,TEMPERATURE,
SOILTEMP10,Soil Temperature 10,temperature-soil-channel-10,0x3d,,,,TEMPERATURE,
SOILTEMP11,Soil Temperature 11,temperature-soil-channel-11,0x3f,,,,TEMPERATURE,
SOILTEMP12,Soil Temperature 12,temperature-soil-channel-12,0x41,,,,TEMPERATURE,
SOILTEMP13,Soil Temperature 13,temperature-soil-channel-13,0x43,,,,TEMPERATURE,
SOILTEMP14,Soil Temperature 14,temperature-soil-channel-14,0x45,,,,TEMPERATURE,
SOILTEMP15,Soil Temperature 15,temperature-soil-channel-15,0x47,,,,TEMPERATURE,
SOILTEMP16,Soil Temperature 16,temperature-soil-channel-16,0x49,,,,TEMPERATURE,
SOILMOISTURE1,Soil Moisture 1,moisture-soil-channel-1,0x2c,,,moisture,PERCENTAGE,
SOILMOISTURE2,Soil Moisture 2,moisture-soil-channel-2,0x2e,,,moisture,PERCENTAGE,
SOILMOISTURE3,Soil Moisture 3,moisture-soil-channel-3,0x30,,,moisture,PERCENTAGE,
SOILMOISTURE4,Soil Moisture 4,moisture-soil-channel-4,0x32,,,moisture,PERCENTAGE,
SOILMOISTURE5,Soil Moisture 5,moisture-soil-channel-5,0x34,,,moisture,PERCENTAGE,
SOILMOISTURE6,Soil Moisture 6,moisture-soil-channel-6,0x36,,,moisture,PERCENTAGE,
SOILMOISTURE7,Soil Moisture 7,moisture-soil-channel-7,0x38,,,moisture,PERCENTAGE,
SOILMOISTURE8,Soil Moisture 8,moisture-soil-channel-8,0x3a,,,moisture,PERCENTAGE,
SOILMOISTURE9,Soil Moisture 9,moisture-soil-channel-9,0x3c,,,moisture,PERCENTAGE,
SOILMOISTURE10,Soil Moisture 10,moisture-soil-channel-10,0x3e,,,moisture,PERCENTAGE,
SOILMOISTURE11,Soil Moisture 11,moisture-soil-channel-11,0x40,,,moisture,PERCENTAGE,
SOILMOISTURE12,Soil Moisture 12,moisture-soil-channel-12,0x42,,,moisture,PERCENTAGE,
SOILMOISTURE13,Soil Moisture 13,moisture-soil-channel-13,0x44,,,moisture,PERCENTAGE,
SOILMOISTURE14,Soil Moisture 14,moisture-soil-channel-14,0x46,,,moisture,PERCENTAGE,
SOILMOISTURE15,Soil Moisture 15,moisture-soil-channel-15,0x48,,,moisture,PERCENTAGE,
SOILMOISTURE16,Soil Moisture 16,moisture-soil-channel-16,0x4a,,,moisture,PERCENTAGE,
LOWBATT,Low Battery,,0x4c,,1,,,
PM25_24HAVG1,PM2.5 Air Quality 24 hour average channel 1,air-quality-24-hour-average-channel-1,0x4d,,,,PM25,
PM25_24HAVG2,PM2.5 Air Quality 24 hour average channel 2,air-quality-24-hour-average-channel-2,0x4e,,,,PM25,
PM25_24HAVG3,PM2.5 Air Quality 24 hour average channel 3,air-quality-24-hour-average-channel-3,0x4f,,,,PM25,
PM25_24HAVG4,PM2.5 Air Quality 24 hour average channel 4,air-quality-24-hour-average-channel-4,0x50,,,,PM25,
PM25_CH1,PM2.5 Air Quality channel 1,air-quality-channel-1,0x2a,,,,PM25,
PM25_CH2,PM2.5 Air Quality channel 2,air-quality-channel-2,0x51,,,,PM25,
PM25_CH3,PM2.5 Air Quality channel 3,air-quality-channel-3,0x52,,,,PM25,
PM25_CH4,PM2.5 Air Quality channel 4,air-quality-channel-4,0x53,,,,PM25,
LEAK_CH1,Leak channel 1,water-leak-channel-1,0x58,,,,WATER_LEAK_DETECTION,
LEAK_CH2,Leak channel 2,water-leak-channel-2,0x59,,,,WATER_LEAK_DETECTION,
LEAK_CH3,Leak channel 3,water-leak-channel-3,0x5a,,,,WATER_LEAK_DETECTION,
LEAK_CH4,Leak channel 4,water-leak-channel-4,0x5b,,,,WATER_LEAK_DETECTION,
LIGHTNING,lightning distance 1~40KM,lightning-distance,0x60,,,,LIGHTNING_DISTANCE,
LIGHTNING_TIME,lightning happened time,lightning-time,0x61,,,,LIGHTNING_TIME,
LIGHTNING_POWER,lightning counter for the day,lightning-counter,0x62,,,,LIGHTNING_COUNTER,
TF_USR1,Soil or Water temperature channel 1,temperature-external-channel-1,0x63,,,,TEMPERATURE,
TF_USR2,Soil or Water temperature channel 2,temperature-external-channel-2,0x64,,,,TEMPERATURE,
TF_USR3,Soil or Water temperature channel 3,temperature-external-channel-3,0x65,,,,TEMPERATURE,
TF_USR4,Soil or Water temperature channel 4,temperature-external-channel-4,0x66,,,,TEMPERATURE,
TF_USR5,Soil or Water temperature channel 5,temperature-external-channel-5,0x67,,,,TEMPERATURE,
TF_USR6,Soil or Water temperature channel 6,temperature-external-channel-6,0x68,,,,TEMPERATURE,
TF_USR7,Soil or Water temperature channel 7,temperature-external-channel-7,0x69,,,,TEMPERATURE,
TF_USR8,Soil or Water temperature channel 8,temperature-external-channel-8,0x6a,,,,TEMPERATURE,
ITEM_SENSOR_CO2,Temperature (CO₂-Sensor),sensor-co2-temperature,0x70,0,,,TEMPERATURE,
ITEM_SENSOR_CO2,Humidity (CO₂-Sensor),sensor-co2-humidity,0x70,1,,,PERCENTAGE,
ITEM_SENSOR_CO2,PM10 Air Quality (CO₂-Sensor),sensor-co2-pm10,0x70,2,,,PM10,
ITEM_SENSOR_CO2,PM10 Air Quality 24 hour average (CO₂-Sensor),sensor-co2-pm10-24-hour-average,0x70,3,,,PM10,
ITEM_SENSOR_CO2,PM2.5 Air Quality (CO₂-Sensor),sensor-co2-pm25,0x70,4,,,PM25,
ITEM_SENSOR_CO2,PM2.5 Air Quality 24 hour average (CO₂-Sensor),sensor-co2-pm25-24-hour-average,0x70,5,,,PM25,
ITEM_SENSOR_CO2,CO₂,sensor-co2-co2,0x70,6,,,CO2,
ITEM_SENSOR_CO2,CO₂ 24 hour average,sensor-co2-co2-24-hour-average,0x70,7,,,CO2,
ITEM_SENSOR_CO2,Battery Level,,0x70,8,1,,,
ITEM_LEAF_WETNESS_CH1,Leaf Moisture channel 1,leaf-wetness-channel-1,0x72,,,moisture,PERCENTAGE,
ITEM_LEAF_WETNESS_CH2,Leaf Moisture channel 2,leaf-wetness-channel-2,0x73,,,moisture,PERCENTAGE,
ITEM_LEAF_WETNESS_CH3,Leaf Moisture channel 3,leaf-wetness-channel-3,0x74,,,moisture,PERCENTAGE,
ITEM_LEAF_WETNESS_CH4,Leaf Moisture channel 4,leaf-wetness-channel-4,0x75,,,moisture,PERCENTAGE,
ITEM_LEAF_WETNESS_CH5,Leaf Moisture channel 5,leaf-wetness-channel-5,0x76,,,moisture,PERCENTAGE,
ITEM_LEAF_WETNESS_CH6,Leaf Moisture channel 6,leaf-wetness-channel-6,0x77,,,moisture,PERCENTAGE,
ITEM_LEAF_WETNESS_CH7,Leaf Moisture channel 7,leaf-wetness-channel-7,0x78,,,moisture,PERCENTAGE,
ITEM_LEAF_WETNESS_CH8,Leaf Moisture channel 8,leaf-wetness-channel-8,0x79,,,moisture,PERCENTAGE,
1 ManufacturerName Name Channel Code Index Skip ChannelType MeasureType_DEFAULT MeasureType_ELV
2 INTEMP Indoor Temperature temperature-indoor 0x1 system:indoor-temperature TEMPERATURE
3 OUTTEMP Outdoor Temperature temperature-outdoor 0x2 system:outdoor-temperature TEMPERATURE
4 DEWPOINT Dew point temperature-dew-point 0x3 TEMPERATURE
5 WINDCHILL Wind chill temperature-wind-chill 0x4 TEMPERATURE
6 HEATINDEX Heat index temperature-heat-index 0x5 TEMPERATURE
7 INHUMI Indoor Humidity humidity-indoor 0x6 PERCENTAGE
8 OUTHUMI Outdoor Humidity humidity-outdoor 0x7 system:atmospheric-humidity PERCENTAGE
9 ABSBARO Absolutely pressure pressure-absolute 0x8 PRESSURE
10 RELBARO Relative pressure pressure-relative 0x9 system:barometric-pressure PRESSURE
11 WINDDIRECTION Wind Direction direction-wind 0xa system:wind-direction DEGREE
12 WINDSPEED Wind Speed speed-wind 0xb system:wind-speed SPEED
13 GUSTSPEED Gust Speed speed-gust 0xc system:wind-speed SPEED
14 RAINEVENT Rain Event rain-event 0xd HEIGHT HEIGHT_BIG
15 RAINRATE Rain Rate rain-rate 0xe HEIGHT_PER_HOUR HEIGHT_PER_HOUR_BIG
16 RAINHOUR Rain hour rain-hour 0xf HEIGHT HEIGHT_BIG
17 RAINDAY Rain Day rain-day 0x10 HEIGHT HEIGHT_BIG
18 RAINWEEK Rain Week rain-week 0x11 HEIGHT HEIGHT_BIG
19 RAINMONTH Rain Month rain-month 0x12 HEIGHT_BIG
20 RAINYEAR Rain Year rain-year 0x13 HEIGHT_BIG
21 RAINTOTALS Rain Totals rain-total 0x14 HEIGHT_BIG
22 LIGHT Light illumination 0x15 LUX
23 UV UV irradiation-uv 0x16 MILLIWATT_PER_SQUARE_METRE
24 UVI UV index uv-index 0x17 uv-index BYTE
25 TIME Date and time time 0x18 DATE_TIME2
26 DAYLWINDMAX Day max wind wind-max-day 0x19 max-wind-speed SPEED
27 TEMP1 Temperature 1 temperature-channel-1 0x1a TEMPERATURE
28 TEMP2 Temperature 2 temperature-channel-2 0x1b TEMPERATURE
29 TEMP3 Temperature 3 temperature-channel-3 0x1c TEMPERATURE
30 TEMP4 Temperature 4 temperature-channel-4 0x1d TEMPERATURE
31 TEMP5 Temperature 5 temperature-channel-5 0x1e TEMPERATURE
32 TEMP6 Temperature 6 temperature-channel-6 0x1f TEMPERATURE
33 TEMP7 Temperature 7 temperature-channel-7 0x20 TEMPERATURE
34 TEMP8 Temperature 8 temperature-channel-8 0x21 TEMPERATURE
35 HUMI1 Humidity 1 humidity-channel-1 0x22 PERCENTAGE
36 HUMI2 Humidity 2 humidity-channel-2 0x23 PERCENTAGE
37 HUMI3 Humidity 3 humidity-channel-3 0x24 PERCENTAGE
38 HUMI4 Humidity 4 humidity-channel-4 0x25 PERCENTAGE
39 HUMI5 Humidity 5 humidity-channel-5 0x26 PERCENTAGE
40 HUMI6 Humidity 6 humidity-channel-6 0x27 PERCENTAGE
41 HUMI7 Humidity 7 humidity-channel-7 0x28 PERCENTAGE
42 HUMI8 Humidity 8 humidity-channel-8 0x29 PERCENTAGE
43 SOILTEMP1 Soil Temperature 1 temperature-soil-channel-1 0x2b TEMPERATURE
44 SOILTEMP2 Soil Temperature 2 temperature-soil-channel-2 0x2d TEMPERATURE
45 SOILTEMP3 Soil Temperature 3 temperature-soil-channel-3 0x2f TEMPERATURE
46 SOILTEMP4 Soil Temperature 4 temperature-soil-channel-4 0x31 TEMPERATURE
47 SOILTEMP5 Soil Temperature 5 temperature-soil-channel-5 0x33 TEMPERATURE
48 SOILTEMP6 Soil Temperature 6 temperature-soil-channel-6 0x35 TEMPERATURE
49 SOILTEMP7 Soil Temperature 7 temperature-soil-channel-7 0x37 TEMPERATURE
50 SOILTEMP8 Soil Temperature 8 temperature-soil-channel-8 0x39 TEMPERATURE
51 SOILTEMP9 Soil Temperature 9 temperature-soil-channel-9 0x3b TEMPERATURE
52 SOILTEMP10 Soil Temperature 10 temperature-soil-channel-10 0x3d TEMPERATURE
53 SOILTEMP11 Soil Temperature 11 temperature-soil-channel-11 0x3f TEMPERATURE
54 SOILTEMP12 Soil Temperature 12 temperature-soil-channel-12 0x41 TEMPERATURE
55 SOILTEMP13 Soil Temperature 13 temperature-soil-channel-13 0x43 TEMPERATURE
56 SOILTEMP14 Soil Temperature 14 temperature-soil-channel-14 0x45 TEMPERATURE
57 SOILTEMP15 Soil Temperature 15 temperature-soil-channel-15 0x47 TEMPERATURE
58 SOILTEMP16 Soil Temperature 16 temperature-soil-channel-16 0x49 TEMPERATURE
59 SOILMOISTURE1 Soil Moisture 1 moisture-soil-channel-1 0x2c moisture PERCENTAGE
60 SOILMOISTURE2 Soil Moisture 2 moisture-soil-channel-2 0x2e moisture PERCENTAGE
61 SOILMOISTURE3 Soil Moisture 3 moisture-soil-channel-3 0x30 moisture PERCENTAGE
62 SOILMOISTURE4 Soil Moisture 4 moisture-soil-channel-4 0x32 moisture PERCENTAGE
63 SOILMOISTURE5 Soil Moisture 5 moisture-soil-channel-5 0x34 moisture PERCENTAGE
64 SOILMOISTURE6 Soil Moisture 6 moisture-soil-channel-6 0x36 moisture PERCENTAGE
65 SOILMOISTURE7 Soil Moisture 7 moisture-soil-channel-7 0x38 moisture PERCENTAGE
66 SOILMOISTURE8 Soil Moisture 8 moisture-soil-channel-8 0x3a moisture PERCENTAGE
67 SOILMOISTURE9 Soil Moisture 9 moisture-soil-channel-9 0x3c moisture PERCENTAGE
68 SOILMOISTURE10 Soil Moisture 10 moisture-soil-channel-10 0x3e moisture PERCENTAGE
69 SOILMOISTURE11 Soil Moisture 11 moisture-soil-channel-11 0x40 moisture PERCENTAGE
70 SOILMOISTURE12 Soil Moisture 12 moisture-soil-channel-12 0x42 moisture PERCENTAGE
71 SOILMOISTURE13 Soil Moisture 13 moisture-soil-channel-13 0x44 moisture PERCENTAGE
72 SOILMOISTURE14 Soil Moisture 14 moisture-soil-channel-14 0x46 moisture PERCENTAGE
73 SOILMOISTURE15 Soil Moisture 15 moisture-soil-channel-15 0x48 moisture PERCENTAGE
74 SOILMOISTURE16 Soil Moisture 16 moisture-soil-channel-16 0x4a moisture PERCENTAGE
75 LOWBATT Low Battery 0x4c 1
76 PM25_24HAVG1 PM2.5 Air Quality 24 hour average channel 1 air-quality-24-hour-average-channel-1 0x4d PM25
77 PM25_24HAVG2 PM2.5 Air Quality 24 hour average channel 2 air-quality-24-hour-average-channel-2 0x4e PM25
78 PM25_24HAVG3 PM2.5 Air Quality 24 hour average channel 3 air-quality-24-hour-average-channel-3 0x4f PM25
79 PM25_24HAVG4 PM2.5 Air Quality 24 hour average channel 4 air-quality-24-hour-average-channel-4 0x50 PM25
80 PM25_CH1 PM2.5 Air Quality channel 1 air-quality-channel-1 0x2a PM25
81 PM25_CH2 PM2.5 Air Quality channel 2 air-quality-channel-2 0x51 PM25
82 PM25_CH3 PM2.5 Air Quality channel 3 air-quality-channel-3 0x52 PM25
83 PM25_CH4 PM2.5 Air Quality channel 4 air-quality-channel-4 0x53 PM25
84 LEAK_CH1 Leak channel 1 water-leak-channel-1 0x58 WATER_LEAK_DETECTION
85 LEAK_CH2 Leak channel 2 water-leak-channel-2 0x59 WATER_LEAK_DETECTION
86 LEAK_CH3 Leak channel 3 water-leak-channel-3 0x5a WATER_LEAK_DETECTION
87 LEAK_CH4 Leak channel 4 water-leak-channel-4 0x5b WATER_LEAK_DETECTION
88 LIGHTNING lightning distance 1~40KM lightning-distance 0x60 LIGHTNING_DISTANCE
89 LIGHTNING_TIME lightning happened time lightning-time 0x61 LIGHTNING_TIME
90 LIGHTNING_POWER lightning counter for the day lightning-counter 0x62 LIGHTNING_COUNTER
91 TF_USR1 Soil or Water temperature channel 1 temperature-external-channel-1 0x63 TEMPERATURE
92 TF_USR2 Soil or Water temperature channel 2 temperature-external-channel-2 0x64 TEMPERATURE
93 TF_USR3 Soil or Water temperature channel 3 temperature-external-channel-3 0x65 TEMPERATURE
94 TF_USR4 Soil or Water temperature channel 4 temperature-external-channel-4 0x66 TEMPERATURE
95 TF_USR5 Soil or Water temperature channel 5 temperature-external-channel-5 0x67 TEMPERATURE
96 TF_USR6 Soil or Water temperature channel 6 temperature-external-channel-6 0x68 TEMPERATURE
97 TF_USR7 Soil or Water temperature channel 7 temperature-external-channel-7 0x69 TEMPERATURE
98 TF_USR8 Soil or Water temperature channel 8 temperature-external-channel-8 0x6a TEMPERATURE
99 ITEM_SENSOR_CO2 Temperature (CO₂-Sensor) sensor-co2-temperature 0x70 0 TEMPERATURE
100 ITEM_SENSOR_CO2 Humidity (CO₂-Sensor) sensor-co2-humidity 0x70 1 PERCENTAGE
101 ITEM_SENSOR_CO2 PM10 Air Quality (CO₂-Sensor) sensor-co2-pm10 0x70 2 PM10
102 ITEM_SENSOR_CO2 PM10 Air Quality 24 hour average (CO₂-Sensor) sensor-co2-pm10-24-hour-average 0x70 3 PM10
103 ITEM_SENSOR_CO2 PM2.5 Air Quality (CO₂-Sensor) sensor-co2-pm25 0x70 4 PM25
104 ITEM_SENSOR_CO2 PM2.5 Air Quality 24 hour average (CO₂-Sensor) sensor-co2-pm25-24-hour-average 0x70 5 PM25
105 ITEM_SENSOR_CO2 CO₂ sensor-co2-co2 0x70 6 CO2
106 ITEM_SENSOR_CO2 CO₂ 24 hour average sensor-co2-co2-24-hour-average 0x70 7 CO2
107 ITEM_SENSOR_CO2 Battery Level 0x70 8 1
108 ITEM_LEAF_WETNESS_CH1 Leaf Moisture channel 1 leaf-wetness-channel-1 0x72 moisture PERCENTAGE
109 ITEM_LEAF_WETNESS_CH2 Leaf Moisture channel 2 leaf-wetness-channel-2 0x73 moisture PERCENTAGE
110 ITEM_LEAF_WETNESS_CH3 Leaf Moisture channel 3 leaf-wetness-channel-3 0x74 moisture PERCENTAGE
111 ITEM_LEAF_WETNESS_CH4 Leaf Moisture channel 4 leaf-wetness-channel-4 0x75 moisture PERCENTAGE
112 ITEM_LEAF_WETNESS_CH5 Leaf Moisture channel 5 leaf-wetness-channel-5 0x76 moisture PERCENTAGE
113 ITEM_LEAF_WETNESS_CH6 Leaf Moisture channel 6 leaf-wetness-channel-6 0x77 moisture PERCENTAGE
114 ITEM_LEAF_WETNESS_CH7 Leaf Moisture channel 7 leaf-wetness-channel-7 0x78 moisture PERCENTAGE
115 ITEM_LEAF_WETNESS_CH8 Leaf Moisture channel 8 leaf-wetness-channel-8 0x79 moisture PERCENTAGE

View File

@ -20,6 +20,7 @@ import org.assertj.core.groups.Tuple;
import org.bouncycastle.util.encoders.Hex; import org.bouncycastle.util.encoders.Hex;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.Command;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.ConversionContext; import org.openhab.binding.fineoffsetweatherstation.internal.domain.ConversionContext;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.Protocol; import org.openhab.binding.fineoffsetweatherstation.internal.domain.Protocol;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.response.MeasuredValue; import org.openhab.binding.fineoffsetweatherstation.internal.domain.response.MeasuredValue;
@ -74,6 +75,34 @@ class FineOffsetDataParserTest {
new Tuple("irradiation-uv", "215.3 mW/m²"), new Tuple("uv-index", "5")); new Tuple("irradiation-uv", "215.3 mW/m²"), new Tuple("uv-index", "5"));
} }
@Test
void testRainData() {
byte[] data = Hex
.decode("FFFF5700290E000010000000001100000024120000003113000005030D00000F0064880000017A017B0030");
List<MeasuredValue> measuredValues = new FineOffsetDataParser(Protocol.DEFAULT).getRainData(data,
new ConversionContext(ZoneOffset.UTC));
Assertions.assertThat(measuredValues)
.extracting(MeasuredValue::getChannelId, measuredValue -> measuredValue.getState().toString())
.containsExactly(new Tuple("rain-rate", "0 mm/h"), new Tuple("rain-day", "0 mm"),
new Tuple("rain-week", "3.6 mm"), new Tuple("rain-month", "4.9 mm"),
new Tuple("rain-year", "128.3 mm"), new Tuple("rain-event", "0 mm"),
new Tuple("rain-hour", "10 mm"));
}
@Test
void testRainDataW90() {
byte[] data = Hex.decode(
"FFFF5700398000008300000009840000000985000000C786000000C7810000870064006400640064006400640064006400640064880900007A02BF");
Assertions.assertThat(Command.CMD_READ_RAIN.isResponseValid(data)).isTrue();
List<MeasuredValue> measuredValues = new FineOffsetDataParser(Protocol.DEFAULT).getRainData(data,
new ConversionContext(ZoneOffset.UTC));
Assertions.assertThat(measuredValues)
.extracting(MeasuredValue::getChannelId, measuredValue -> measuredValue.getState().toString())
.containsExactly(new Tuple("piezo-rain-rate", "0 mm/h"), new Tuple("piezo-rain-day", "0.9 mm"),
new Tuple("piezo-rain-week", "0.9 mm"), new Tuple("piezo-rain-month", "19.9 mm"),
new Tuple("piezo-rain-year", "19.9 mm"), new Tuple("piezo-rain-event", "0 mm"));
}
@Test @Test
void testFirmware() { void testFirmware() {
byte[] data = Hex.decode("FFFF501511456173795765617468657256312E362E3400"); byte[] data = Hex.decode("FFFF501511456173795765617468657256312E362E3400");