2 * Copyright (c) 2010-2024 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.knx.internal.channel;
15 import static org.hamcrest.MatcherAssert.assertThat;
16 import static org.hamcrest.Matchers.*;
17 import static org.junit.jupiter.api.Assertions.*;
18 import static org.mockito.Mockito.mock;
19 import static org.mockito.Mockito.when;
21 import java.util.List;
23 import java.util.Objects;
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.junit.jupiter.api.Test;
28 import org.openhab.binding.knx.internal.KNXBindingConstants;
29 import org.openhab.binding.knx.internal.client.OutboundSpec;
30 import org.openhab.binding.knx.internal.dpt.ValueEncoder;
31 import org.openhab.core.config.core.Configuration;
32 import org.openhab.core.library.items.ColorItem;
33 import org.openhab.core.library.types.HSBType;
34 import org.openhab.core.library.types.PercentType;
35 import org.openhab.core.thing.Channel;
36 import org.openhab.core.thing.type.ChannelTypeUID;
37 import org.openhab.core.types.Command;
38 import org.openhab.core.types.UnDefType;
40 import tuwien.auto.calimero.GroupAddress;
41 import tuwien.auto.calimero.KNXFormatException;
45 * @author Simon Kaufmann - Initial contribution
49 class KNXChannelTest {
52 public void invalidFails() {
53 GroupAddressConfiguration res = GroupAddressConfiguration.parse("5.001:<1/3/22+0/3/22+<0/8/15");
58 void testParseWithDptMultipleWithRead() throws KNXFormatException {
59 GroupAddressConfiguration res = GroupAddressConfiguration.parse("5.001:<1/3/22+0/3/22+<0/7/15");
66 assertEquals("5.001", res.getDPT());
67 assertEquals(new GroupAddress("1/3/22"), res.getMainGA());
68 assertTrue(res.getReadGAs().contains(res.getMainGA()));
69 assertEquals(3, res.getListenGAs().size());
70 assertEquals(2, res.getReadGAs().size());
74 void testParseWithDptMultipleWithoutRead() throws KNXFormatException {
75 GroupAddressConfiguration res = GroupAddressConfiguration.parse("5.001:1/3/22+0/3/22+0/7/15");
82 assertEquals("5.001", res.getDPT());
83 assertEquals(new GroupAddress("1/3/22"), res.getMainGA());
84 assertFalse(res.getReadGAs().contains(res.getMainGA()));
85 assertEquals(3, res.getListenGAs().size());
86 assertEquals(0, res.getReadGAs().size());
90 void testParseWithoutDptSingleWithoutRead() throws KNXFormatException {
91 GroupAddressConfiguration res = GroupAddressConfiguration.parse("1/3/22");
98 assertNull(res.getDPT());
99 assertEquals(new GroupAddress("1/3/22"), res.getMainGA());
100 assertFalse(res.getReadGAs().contains(res.getMainGA()));
101 assertEquals(1, res.getListenGAs().size());
102 assertEquals(0, res.getReadGAs().size());
106 void testParseWithoutDptSingleWithRead() throws KNXFormatException {
107 GroupAddressConfiguration res = GroupAddressConfiguration.parse("<1/3/22");
114 assertNull(res.getDPT());
115 assertEquals(new GroupAddress("1/3/22"), res.getMainGA());
116 assertTrue(res.getReadGAs().contains(res.getMainGA()));
117 assertEquals(1, res.getListenGAs().size());
118 assertEquals(1, res.getReadGAs().size());
122 void testParseTwoLevel() throws KNXFormatException {
123 GroupAddressConfiguration res = GroupAddressConfiguration.parse("5.001:<3/1024+<4/1025");
130 assertEquals(new GroupAddress("3/1024"), res.getMainGA());
131 assertTrue(res.getReadGAs().contains(res.getMainGA()));
132 assertEquals(2, res.getListenGAs().size());
133 assertEquals(2, res.getReadGAs().size());
137 void testParseFreeLevel() throws KNXFormatException {
138 GroupAddressConfiguration res = GroupAddressConfiguration.parse("5.001:<4610+<4611");
145 assertEquals(new GroupAddress("4610"), res.getMainGA());
146 assertEquals(2, res.getListenGAs().size());
147 assertEquals(2, res.getReadGAs().size());
151 public void testChannelGaParsing() throws KNXFormatException {
152 Channel channel = Objects.requireNonNull(mock(Channel.class));
153 Configuration configuration = new Configuration(
154 Map.of("key1", "5.001:<1/2/3+4/5/6+1/5/6", "key2", "1.001:7/1/9+1/1/2"));
155 when(channel.getChannelTypeUID()).thenReturn(new ChannelTypeUID("a:b:c"));
156 when(channel.getConfiguration()).thenReturn(configuration);
157 when(channel.getAcceptedItemType()).thenReturn("none");
159 MyKNXChannel knxChannel = new MyKNXChannel(channel);
161 Set<GroupAddress> listenAddresses = knxChannel.getAllGroupAddresses();
162 assertEquals(5, listenAddresses.size());
163 // we don't check the content since parsing has been checked before and the quantity is correct
164 Set<GroupAddress> writeAddresses = knxChannel.getWriteAddresses();
165 assertEquals(2, writeAddresses.size());
166 assertTrue(writeAddresses.contains(new GroupAddress("1/2/3")));
167 assertTrue(writeAddresses.contains(new GroupAddress("7/1/9")));
171 void testSubTypeMapping() throws KNXFormatException {
172 Channel channel = Objects.requireNonNull(mock(Channel.class));
173 Configuration configuration = new Configuration(Map.of("key1", "1.001:1/2/3"));
174 when(channel.getChannelTypeUID()).thenReturn(new ChannelTypeUID("a:b:c"));
175 when(channel.getConfiguration()).thenReturn(configuration);
176 when(channel.getAcceptedItemType()).thenReturn(ColorItem.class.getName());
177 MyKNXChannel knxChannel = new MyKNXChannel(channel);
178 assertNotNull(knxChannel.getCommandSpec(new HSBType("0,100,100")));
179 assertEquals(knxChannel.getCommandSpec(new HSBType("0,100,100")).getDPT(), "1.001");
183 void test5001PercentType() throws KNXFormatException {
184 Configuration configuration = new Configuration(Map.of("switch", "1.001:1/2/1", "position", "5.001:1/2/2"));
185 Channel channel = Objects.requireNonNull(mock(Channel.class));
186 when(channel.getChannelTypeUID())
187 .thenReturn(new ChannelTypeUID(KNXBindingConstants.BINDING_ID, KNXBindingConstants.CHANNEL_DIMMER));
188 when(channel.getConfiguration()).thenReturn(configuration);
190 KNXChannel knxChannel = KNXChannelFactory.createKnxChannel(channel);
191 assertThat(knxChannel, instanceOf(TypeDimmer.class));
193 Command command = new PercentType("100");
194 OutboundSpec outboundSpec = knxChannel.getCommandSpec(command);
195 assertThat(outboundSpec, is(notNullValue()));
197 String mappedValue = ValueEncoder.encode(outboundSpec.getValue(), outboundSpec.getDPT());
198 assertThat(mappedValue, is("100"));
199 assertThat(outboundSpec.getValue(), is(instanceOf(PercentType.class)));
202 private static class MyKNXChannel extends KNXChannel {
203 public MyKNXChannel(Channel channel) {
204 super(Set.of("key1", "key2"), List.of(UnDefType.class), channel);
208 protected String getDefaultDPT(String gaConfigKey) {