Skip to content

Commit

Permalink
[knx] DPT 1 to support Switch and Contact (openhab#16238)
Browse files Browse the repository at this point in the history
* Allow assigning Switch or Contact to most of the DPT 1 subtypes
(exceptions 1.008 UpDownType, 1.010 StopMoveType, 1.022 DecimalType).
* Tests for all published subtypes for DPT 1.
* Fix sending of DPT 1.022.

Signed-off-by: Holger Friedrich <mail@holger-friedrich.de>
Signed-off-by: René Ulbricht <rene_ulbricht@outlook.com>
  • Loading branch information
holgerfriedrich authored and ulbi committed Jan 28, 2024
1 parent 3557c21 commit 721368a
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public class ValueDecoder {

switch (mainType) {
case "1":
return handleDpt1(subType, translator);
return handleDpt1(subType, translator, preferredType);
case "2":
DPTXlator1BitControlled translator1BitControlled = (DPTXlator1BitControlled) translator;
int decValue = (translator1BitControlled.getControlBit() ? 2 : 0)
Expand Down Expand Up @@ -172,13 +172,18 @@ public class ValueDecoder {
return null;
}

private static Type handleDpt1(String subType, DPTXlator translator) {
private static Type handleDpt1(String subType, DPTXlator translator, Class<? extends Type> preferredType) {
DPTXlatorBoolean translatorBoolean = (DPTXlatorBoolean) translator;
switch (subType) {
case "008":
return translatorBoolean.getValueBoolean() ? UpDownType.DOWN : UpDownType.UP;
case "009":
case "019":
// default is OpenClosedType (Contact), but it may be mapped to OnOffType as well
if (OnOffType.class.equals(preferredType)) {
return OnOffType.from(translatorBoolean.getValueBoolean());
}

// This is wrong for DPT 1.009. It should be true -> CLOSE, false -> OPEN, but unfortunately
// can't be fixed without breaking a lot of working installations.
// The documentation has been updated to reflect that. / @J-N-K
Expand All @@ -188,6 +193,11 @@ private static Type handleDpt1(String subType, DPTXlator translator) {
case "022":
return DecimalType.valueOf(translatorBoolean.getValueBoolean() ? "1" : "0");
default:
// default is OnOffType (Switch), but it may be mapped to OpenClosedType as well
if (OpenClosedType.class.equals(preferredType)) {
return translatorBoolean.getValueBoolean() ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
}

return OnOffType.from(translatorBoolean.getValueBoolean());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import tuwien.auto.calimero.dptxlator.DPTXlator2ByteFloat;
import tuwien.auto.calimero.dptxlator.DPTXlator3BitControlled;
import tuwien.auto.calimero.dptxlator.DPTXlator4ByteFloat;
import tuwien.auto.calimero.dptxlator.DPTXlatorBoolean;
import tuwien.auto.calimero.dptxlator.DPTXlatorDate;
import tuwien.auto.calimero.dptxlator.DPTXlatorDateTime;
import tuwien.auto.calimero.dptxlator.DPTXlatorTime;
Expand Down Expand Up @@ -236,6 +237,11 @@ private static String handleNumericTypes(String dptId, String mainNumber, DPT dp
}
}
switch (mainNumber) {
case "1":
if (DPTXlatorBoolean.DPT_SCENE_AB.getID().equals(dptId)) {
return (bigDecimal.intValue() == 0) ? dpt.getLowerValue() : dpt.getUpperValue();
}
return bigDecimal.stripTrailingZeros().toPlainString();
case "2":
DPT valueDPT = ((DPTXlator1BitControlled.DPT1BitControlled) dpt).getValueDPT();
switch (bigDecimal.intValue()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,40 +190,112 @@ void helper(String dpt, byte[] rawData, Type ohReferenceData) {

@Test
void testDpt1() {
// for now only the DPTs for general use, others omitted
// TODO add tests for more subtypes

helper("1.001", new byte[] { 0 }, OnOffType.OFF);
helper("1.001", new byte[] { 1 }, OnOffType.ON);
helper("1.001", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.001", new byte[] { 1 }, OpenClosedType.OPEN);
helper("1.002", new byte[] { 0 }, OnOffType.OFF);
helper("1.002", new byte[] { 1 }, OnOffType.ON);
helper("1.002", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.002", new byte[] { 1 }, OpenClosedType.OPEN);
helper("1.003", new byte[] { 0 }, OnOffType.OFF);
helper("1.003", new byte[] { 1 }, OnOffType.ON);

helper("1.003", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.003", new byte[] { 1 }, OpenClosedType.OPEN);
helper("1.004", new byte[] { 0 }, OnOffType.OFF);
helper("1.004", new byte[] { 1 }, OnOffType.ON);
helper("1.004", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.004", new byte[] { 1 }, OpenClosedType.OPEN);
helper("1.005", new byte[] { 0 }, OnOffType.OFF);
helper("1.005", new byte[] { 1 }, OnOffType.ON);
helper("1.005", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.005", new byte[] { 1 }, OpenClosedType.OPEN);
helper("1.006", new byte[] { 0 }, OnOffType.OFF);
helper("1.006", new byte[] { 1 }, OnOffType.ON);
helper("1.006", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.006", new byte[] { 1 }, OpenClosedType.OPEN);
helper("1.007", new byte[] { 0 }, OnOffType.OFF);
helper("1.007", new byte[] { 1 }, OnOffType.ON);
helper("1.007", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.007", new byte[] { 1 }, OpenClosedType.OPEN);
helper("1.008", new byte[] { 0 }, UpDownType.UP);
helper("1.008", new byte[] { 1 }, UpDownType.DOWN);
// NOTE: This is how DPT 1.009 is defined: 0: open, 1: closed
// For historical reasons it is defined the other way on OH
helper("1.009", new byte[] { 0 }, OnOffType.OFF);
helper("1.009", new byte[] { 1 }, OnOffType.ON);
helper("1.009", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.009", new byte[] { 1 }, OpenClosedType.OPEN);
helper("1.010", new byte[] { 0 }, StopMoveType.STOP);
helper("1.010", new byte[] { 1 }, StopMoveType.MOVE);

helper("1.011", new byte[] { 0 }, OnOffType.OFF);
helper("1.011", new byte[] { 1 }, OnOffType.ON);
helper("1.011", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.011", new byte[] { 1 }, OpenClosedType.OPEN);
helper("1.012", new byte[] { 0 }, OnOffType.OFF);
helper("1.012", new byte[] { 1 }, OnOffType.ON);
helper("1.012", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.012", new byte[] { 1 }, OpenClosedType.OPEN);
helper("1.013", new byte[] { 0 }, OnOffType.OFF);
helper("1.013", new byte[] { 1 }, OnOffType.ON);
helper("1.013", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.013", new byte[] { 1 }, OpenClosedType.OPEN);
helper("1.014", new byte[] { 0 }, OnOffType.OFF);
helper("1.014", new byte[] { 1 }, OnOffType.ON);
helper("1.014", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.014", new byte[] { 1 }, OpenClosedType.OPEN);
helper("1.015", new byte[] { 0 }, OnOffType.OFF);
helper("1.015", new byte[] { 1 }, OnOffType.ON);
helper("1.015", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.015", new byte[] { 1 }, OpenClosedType.OPEN);
helper("1.016", new byte[] { 0 }, OnOffType.OFF);
helper("1.016", new byte[] { 1 }, OnOffType.ON);
helper("1.016", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.016", new byte[] { 1 }, OpenClosedType.OPEN);
// DPT 1.017 is a special case, "trigger" has no "value", both 0 and 1 shall trigger
helper("1.017", new byte[] { 0 }, OnOffType.OFF);
helper("1.017", new byte[] { 0 }, OpenClosedType.CLOSED);
// Calimero maps it always to 0
// helper("1.017", new byte[] { 1 }, OnOffType.ON);
helper("1.018", new byte[] { 0 }, OnOffType.OFF);
helper("1.018", new byte[] { 1 }, OnOffType.ON);
helper("1.018", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.018", new byte[] { 1 }, OpenClosedType.OPEN);
helper("1.019", new byte[] { 0 }, OnOffType.OFF);
helper("1.019", new byte[] { 1 }, OnOffType.ON);
helper("1.019", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.019", new byte[] { 1 }, OpenClosedType.OPEN);

helper("1.021", new byte[] { 0 }, OnOffType.OFF);
helper("1.021", new byte[] { 1 }, OnOffType.ON);
helper("1.021", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.021", new byte[] { 1 }, OpenClosedType.OPEN);
// DPT 1.022 is mapped to decimal, Calimero does not follow the recommendation
// from KNX spec to add offset 1
helper("1.022", new byte[] { 0 }, DecimalType.valueOf("0"));
helper("1.022", new byte[] { 1 }, DecimalType.valueOf("1"));
helper("1.023", new byte[] { 0 }, OnOffType.OFF);
helper("1.023", new byte[] { 1 }, OnOffType.ON);
helper("1.023", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.023", new byte[] { 1 }, OpenClosedType.OPEN);
helper("1.024", new byte[] { 0 }, OnOffType.OFF);
helper("1.024", new byte[] { 1 }, OnOffType.ON);
helper("1.024", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.024", new byte[] { 1 }, OpenClosedType.OPEN);

helper("1.100", new byte[] { 0 }, OnOffType.OFF);
helper("1.100", new byte[] { 1 }, OnOffType.ON);
helper("1.100", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.100", new byte[] { 1 }, OpenClosedType.OPEN);

helper("1.1200", new byte[] { 0 }, OnOffType.OFF);
helper("1.1200", new byte[] { 1 }, OnOffType.ON);
helper("1.1200", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.1200", new byte[] { 1 }, OpenClosedType.OPEN);
helper("1.1201", new byte[] { 0 }, OnOffType.OFF);
helper("1.1201", new byte[] { 1 }, OnOffType.ON);
helper("1.1201", new byte[] { 0 }, OpenClosedType.CLOSED);
helper("1.1201", new byte[] { 1 }, OpenClosedType.OPEN);
}

@Test
Expand Down

0 comments on commit 721368a

Please sign in to comment.