Skip to content

Commit

Permalink
[fineoffsetweatherstation] Improve tracing
Browse files Browse the repository at this point in the history
Signed-off-by: Andreas Berger <[email protected]>
  • Loading branch information
Andy2003 committed Nov 6, 2023
1 parent 6196de7 commit 2a9a67f
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -275,4 +275,8 @@ public boolean isHeaderValid(byte[] data) {
public boolean isResponseValid(byte[] data) {
return isHeaderValid(data) && Utils.validateChecksum(data, sizeBytes);
}

public int getSizeBytes() {
return sizeBytes;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Copyright (c) 2010-2023 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.util.Arrays;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.openhab.binding.fineoffsetweatherstation.internal.Utils;

public class DebugDetails {

Check failure on line 23 in bundles/org.openhab.binding.fineoffsetweatherstation/src/main/java/org/openhab/binding/fineoffsetweatherstation/internal/domain/DebugDetails.java

View workflow job for this annotation

GitHub Actions / Build (Java 17, ubuntu-22.04)

An author tag is missing
final byte[] data;

private final Map<Integer, DebugSegment> segments = new TreeMap<>();

public DebugDetails(byte[] data, Command command, Protocol protocol) {
this.data = data;
addDebugDetails(0, 2, "header");
addDebugDetails(2, 1, "command: " + command.name());
addDebugDetails(3, command.getSizeBytes(), "size");
if (protocol == Protocol.ELV) {
addDebugDetails(data.length - 2, 1, "ELV checksum");
}
addDebugDetails(data.length - 1, 1, "checksum");
}

public void addDebugDetails(int start, int length, String description) {
segments.put(start, new DebugSegment(start, length, description));
}

@Override
public String toString() {
int padding = segments.values().stream().mapToInt(value -> value.length).max().orElse(0) * 2;
return "0x" + Utils.toHexString(data, data.length, "") + "\n" + segments.values().stream()
.map(debugSegment -> debugSegment.toDebugString(padding)).collect(Collectors.joining("\n"));
}

private class DebugSegment {
final int start;
final int length;
final String description;

DebugSegment(int start, int length, String description) {
this.start = start;
this.length = length;
this.description = description;
}

@Override
public String toString() {
return toDebugString(0);
}

private String toDebugString(int padding) {
String result = "0x";
String hexString = Utils.toHexString(Arrays.copyOfRange(data, start, start + length), length, "");
result += StringUtils.rightPad(hexString, padding, " ");
result += ": " + description;
return result;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -240,18 +240,20 @@ public enum Measurand {
}

private int extractMeasuredValues(byte[] data, int offset, @Nullable Integer channel, ConversionContext context,
@Nullable ParserCustomizationType customizationType, List<MeasuredValue> result) {
@Nullable ParserCustomizationType customizationType, List<MeasuredValue> result,
DebugDetails debugDetails) {
int subOffset = 0;
for (Parser parser : parsers) {
subOffset += parser.extractMeasuredValues(data, offset + subOffset, channel, context, customizationType,
result);
result, debugDetails);
}
return subOffset;
}

private interface Parser {
int extractMeasuredValues(byte[] data, int offset, @Nullable Integer channel, ConversionContext context,
@Nullable ParserCustomizationType customizationType, List<MeasuredValue> result);
@Nullable ParserCustomizationType customizationType, List<MeasuredValue> result,
DebugDetails debugDetails);
}

private static class Skip implements Parser {
Expand All @@ -263,7 +265,9 @@ public Skip(int skip) {

@Override
public int extractMeasuredValues(byte[] data, int offset, @Nullable Integer channel, ConversionContext context,
@Nullable ParserCustomizationType customizationType, List<MeasuredValue> result) {
@Nullable ParserCustomizationType customizationType, List<MeasuredValue> result,
DebugDetails debugDetails) {
debugDetails.addDebugDetails(offset, skip, "skipped");
return skip;
}
}
Expand Down Expand Up @@ -302,8 +306,14 @@ public SingleChannelMeasurand(Measurand measurand, @Nullable Integer 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);
@Nullable ParserCustomizationType customizationType, List<MeasuredValue> result,
DebugDetails debugDetails) {
return measurand.extractMeasuredValues(data, offset, channel, context, customizationType, result,
debugDetails);
}

public String getDebugString() {
return measurand.name() + (channel == null ? "" : " channel " + channel);
}
}

Expand Down Expand Up @@ -337,12 +347,17 @@ private static class MeasurandParser implements Parser {

@Override
public int extractMeasuredValues(byte[] data, int offset, @Nullable Integer channel, ConversionContext context,
@Nullable ParserCustomizationType customizationType, List<MeasuredValue> result) {
@Nullable ParserCustomizationType customizationType, List<MeasuredValue> result,
DebugDetails debugDetails) {
MeasureType measureType = getMeasureType(customizationType);
State state = measureType.toState(data, offset, context);
if (state != null) {
debugDetails.addDebugDetails(offset, measureType.getByteSize(),
measureType.name() + ": " + state.toFullString());
ChannelTypeUID channelType = channelTypeUID == null ? measureType.getChannelTypeId() : channelTypeUID;
result.add(new MeasuredValue(measureType, channelPrefix, channel, channelType, state, name));
} else {
debugDetails.addDebugDetails(offset, measureType.getByteSize(), measureType.name() + ": null");
}
return measureType.getByteSize();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/**
* Copyright (c) 2010-2023 Contributors to the openHAB project
*
* <p>

Check failure on line 3 in bundles/org.openhab.binding.fineoffsetweatherstation/src/main/java/org/openhab/binding/fineoffsetweatherstation/internal/service/ELVGatewayQueryService.java

View workflow job for this annotation

GitHub Actions / Build (Java 17, ubuntu-22.04)

Header line doesn't match pattern ^ \*$
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* <p>
* 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
*
* <p>
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fineoffsetweatherstation.internal.service;
Expand All @@ -21,6 +21,7 @@
import org.openhab.binding.fineoffsetweatherstation.internal.FineOffsetGatewayConfiguration;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.Command;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.ConversionContext;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.DebugDetails;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.Protocol;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.SensorGatewayBinding;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.response.MeasuredValue;
Expand Down Expand Up @@ -79,6 +80,10 @@ public List<MeasuredValue> getMeasuredValues() {
if (data == null) {
return Collections.emptyList();
}
return fineOffsetDataParser.getMeasuredValues(data, conversionContext);
DebugDetails debugDetails = new DebugDetails(data, Command.CMD_WS980_LIVEDATA, Protocol.ELV);
List<MeasuredValue> measuredValues = fineOffsetDataParser.getMeasuredValues(data, conversionContext,
debugDetails);
logger.trace("{}", debugDetails);
return measuredValues;
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/**
* Copyright (c) 2010-2023 Contributors to the openHAB project
*
* <p>

Check failure on line 3 in bundles/org.openhab.binding.fineoffsetweatherstation/src/main/java/org/openhab/binding/fineoffsetweatherstation/internal/service/FineOffsetDataParser.java

View workflow job for this annotation

GitHub Actions / Build (Java 17, ubuntu-22.04)

Header line doesn't match pattern ^ \*$
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* <p>
* 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
*
* <p>
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fineoffsetweatherstation.internal.service;
Expand All @@ -27,6 +27,7 @@
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.fineoffsetweatherstation.internal.Utils;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.ConversionContext;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.DebugDetails;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.Measurand;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.Protocol;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.SensorGatewayBinding;
Expand Down Expand Up @@ -151,7 +152,7 @@ public Map<SensorGatewayBinding, SensorDevice> getRegisteredSensors(byte[] data,
return new SystemInfo(frequency, date, dst, useWh24);
}

List<MeasuredValue> getMeasuredValues(byte[] data, ConversionContext context) {
List<MeasuredValue> getMeasuredValues(byte[] data, ConversionContext context, DebugDetails debugDetails) {
/*
* Pos| Length | Description
* -------------------------------------------------
Expand All @@ -173,26 +174,31 @@ List<MeasuredValue> getMeasuredValues(byte[] data, ConversionContext context) {
var idx = 5;
if (protocol == Protocol.ELV) {
idx++; // at index 5 there is an additional Byte being set to 0x04
debugDetails.addDebugDetails(5, 1, "ELV extra byte");
}
return readMeasuredValues(data, idx, context, protocol.getParserCustomizationType());
return readMeasuredValues(data, idx, context, protocol.getParserCustomizationType(), debugDetails);
}

List<MeasuredValue> getRainData(byte[] data, ConversionContext context) {
return readMeasuredValues(data, 5, context, Measurand.ParserCustomizationType.RAIN_READING);
List<MeasuredValue> getRainData(byte[] data, ConversionContext context, DebugDetails debugDetails) {
return readMeasuredValues(data, 5, context, Measurand.ParserCustomizationType.RAIN_READING, debugDetails);
}

private List<MeasuredValue> readMeasuredValues(byte[] data, int idx, ConversionContext context,
Measurand.@Nullable ParserCustomizationType protocol) {
Measurand.@Nullable ParserCustomizationType protocol, DebugDetails debugDetails) {
var size = toUInt16(data, 3);

List<MeasuredValue> result = new ArrayList<>();
while (idx < size) {
byte code = data[idx++];
Measurand.SingleChannelMeasurand measurand = Measurand.getByCode(code);
if (measurand == null) {
logger.warn("failed to get measurand 0x{}", Integer.toHexString(code));
debugDetails.addDebugDetails(idx - 1, 1, "unknown measurand");
return result;
} else {
debugDetails.addDebugDetails(idx - 1, 1, "measurand " + measurand.getDebugString());
}
idx += measurand.extractMeasuredValues(data, idx, context, protocol, result);
idx += measurand.extractMeasuredValues(data, idx, context, protocol, result, debugDetails);
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.openhab.binding.fineoffsetweatherstation.internal.FineOffsetGatewayConfiguration;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.Command;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.ConversionContext;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.DebugDetails;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.Protocol;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.SensorGatewayBinding;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.response.MeasuredValue;
Expand All @@ -38,6 +39,7 @@
*/
@NonNullByDefault
public class FineOffsetGatewayQueryService extends GatewayQueryService {
private static final Protocol PROTOCOL = Protocol.DEFAULT;
private final Logger logger = LoggerFactory.getLogger(FineOffsetGatewayQueryService.class);

private final FineOffsetDataParser fineOffsetDataParser;
Expand All @@ -47,7 +49,7 @@ public class FineOffsetGatewayQueryService extends GatewayQueryService {
public FineOffsetGatewayQueryService(FineOffsetGatewayConfiguration config,
@Nullable ThingStatusListener thingStatusListener, ConversionContext conversionContext) {
super(config, thingStatusListener);
this.fineOffsetDataParser = new FineOffsetDataParser(Protocol.DEFAULT);
this.fineOffsetDataParser = new FineOffsetDataParser(PROTOCOL);
this.conversionContext = conversionContext;
}

Expand Down Expand Up @@ -92,18 +94,24 @@ public Collection<MeasuredValue> getMeasuredValues() {

byte[] data = executeCommand(Command.CMD_GW1000_LIVEDATA);
if (data != null) {
List<MeasuredValue> measuredValues = fineOffsetDataParser.getMeasuredValues(data, conversionContext);
DebugDetails debugDetails = new DebugDetails(data, Command.CMD_GW1000_LIVEDATA, PROTOCOL);
List<MeasuredValue> measuredValues = fineOffsetDataParser.getMeasuredValues(data, conversionContext,
debugDetails);
for (MeasuredValue measuredValue : measuredValues) {
valuePerChannel.put(measuredValue.getChannelId(), measuredValue);
}
logger.trace("{}", debugDetails);
}

data = executeCommand(Command.CMD_READ_RAIN);
if (data != null) {
List<MeasuredValue> measuredRainValues = fineOffsetDataParser.getRainData(data, conversionContext);
DebugDetails debugDetails = new DebugDetails(data, Command.CMD_READ_RAIN, PROTOCOL);
List<MeasuredValue> measuredRainValues = fineOffsetDataParser.getRainData(data, conversionContext,
debugDetails);
for (MeasuredValue measuredValue : measuredRainValues) {
valuePerChannel.put(measuredValue.getChannelId(), measuredValue);
}
logger.trace("{}", debugDetails);
}

return valuePerChannel.values();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
*/
@NonNullByDefault
public abstract class GatewayQueryService implements AutoCloseable {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
protected final Logger logger = LoggerFactory.getLogger(this.getClass());

private static final Lock REQUEST_LOCK = new ReentrantLock();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
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.DebugDetails;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.Protocol;
import org.openhab.binding.fineoffsetweatherstation.internal.domain.response.MeasuredValue;
import org.openhab.core.util.HexUtils;
Expand All @@ -32,9 +33,11 @@
class FineOffsetDataParserTest {
@Test
void testLiveDataWH45() {
List<MeasuredValue> data = new FineOffsetDataParser(Protocol.DEFAULT).getMeasuredValues(HexUtils.hexToBytes(
"FFFF2700510100D306280827EF0927EF020045074F0A00150B00000C0000150000000016000117001900000E0000100000110021120000002113000005850D00007000D12E0060005A005B005502AE028F0633"),
new ConversionContext(ZoneOffset.UTC));
byte[] bytes = HexUtils.hexToBytes(
"FFFF2700510100D306280827EF0927EF020045074F0A00150B00000C0000150000000016000117001900000E0000100000110021120000002113000005850D00007000D12E0060005A005B005502AE028F0633");
DebugDetails debugDetails = new DebugDetails(bytes, Command.CMD_GW1000_LIVEDATA, Protocol.DEFAULT);
List<MeasuredValue> data = new FineOffsetDataParser(Protocol.DEFAULT).getMeasuredValues(bytes,
new ConversionContext(ZoneOffset.UTC), debugDetails);
Assertions.assertThat(data)
.extracting(MeasuredValue::getChannelId, measuredValue -> measuredValue.getState().toString())
.containsExactly(new Tuple("temperature-indoor", "21.1 °C"), new Tuple("humidity-indoor", "40 %"),
Expand All @@ -58,8 +61,9 @@ void testLiveDataWH45() {
void testLiveDataELV() {
byte[] data = HexUtils.hexToBytes(
"FFFF0B00500401010B0201120300620401120501120629072108254B09254B0A01480B00040C000A0E000000001000000021110000002E120000014F130000100714000012FD15000B4BB816086917056D35");
DebugDetails debugDetails = new DebugDetails(data, Command.CMD_WS980_LIVEDATA, Protocol.ELV);
List<MeasuredValue> measuredValues = new FineOffsetDataParser(Protocol.ELV).getMeasuredValues(data,
new ConversionContext(ZoneOffset.UTC));
new ConversionContext(ZoneOffset.UTC), debugDetails);
Assertions.assertThat(measuredValues)
.extracting(MeasuredValue::getChannelId, measuredValue -> measuredValue.getState().toString())
.containsExactly(new Tuple("temperature-indoor", "26.7 °C"),
Expand All @@ -79,8 +83,9 @@ void testLiveDataELV() {
void testRainData() {
byte[] data = HexUtils
.hexToBytes("FFFF5700290E000010000000001100000024120000003113000005030D00000F0064880000017A017B0030");
DebugDetails debugDetails = new DebugDetails(data, Command.CMD_READ_RAIN, Protocol.DEFAULT);
List<MeasuredValue> measuredValues = new FineOffsetDataParser(Protocol.DEFAULT).getRainData(data,
new ConversionContext(ZoneOffset.UTC));
new ConversionContext(ZoneOffset.UTC), debugDetails);
Assertions.assertThat(measuredValues)
.extracting(MeasuredValue::getChannelId, measuredValue -> measuredValue.getState().toString())
.containsExactly(new Tuple("rain-rate", "0 mm/h"), new Tuple("rain-day", "0 mm"),
Expand All @@ -94,8 +99,9 @@ void testRainDataW90() {
byte[] data = HexUtils.hexToBytes(
"FFFF5700398000008300000009840000000985000000C786000000C7810000870064006400640064006400640064006400640064880900007A02BF");
Assertions.assertThat(Command.CMD_READ_RAIN.isResponseValid(data)).isTrue();
DebugDetails debugDetails = new DebugDetails(data, Command.CMD_READ_RAIN, Protocol.DEFAULT);
List<MeasuredValue> measuredValues = new FineOffsetDataParser(Protocol.DEFAULT).getRainData(data,
new ConversionContext(ZoneOffset.UTC));
new ConversionContext(ZoneOffset.UTC), debugDetails);
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"),
Expand Down

0 comments on commit 2a9a67f

Please sign in to comment.