]> git.basschouten.com Git - openhab-addons.git/blob
0472f6225e470f40e318c6322b36899084d61797
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.webthing.internal.link;
14
15 import static org.junit.jupiter.api.Assertions.assertEquals;
16 import static org.mockito.Mockito.*;
17
18 import java.net.URI;
19 import java.nio.file.Files;
20 import java.nio.file.Paths;
21 import java.util.Map;
22 import java.util.Objects;
23 import java.util.concurrent.ConcurrentHashMap;
24
25 import org.eclipse.jdt.annotation.NonNullByDefault;
26 import org.junit.jupiter.api.Test;
27 import org.openhab.binding.webthing.internal.ChannelHandler;
28 import org.openhab.binding.webthing.internal.channel.Channels;
29 import org.openhab.binding.webthing.internal.client.Mocks;
30 import org.openhab.binding.webthing.internal.client.WebthingTest;
31 import org.openhab.binding.webthing.internal.client.dto.PropertyStatusMessage;
32 import org.openhab.core.library.types.DecimalType;
33 import org.openhab.core.library.types.HSBType;
34 import org.openhab.core.library.types.OnOffType;
35 import org.openhab.core.library.types.OpenClosedType;
36 import org.openhab.core.library.types.PercentType;
37 import org.openhab.core.library.types.StringType;
38 import org.openhab.core.thing.ChannelUID;
39 import org.openhab.core.thing.ThingUID;
40 import org.openhab.core.types.Command;
41 import org.openhab.core.types.State;
42
43 import com.google.gson.Gson;
44
45 /**
46  * Mapping test.
47  *
48  * Please consider that changes of 'ItemType<->PropertyType mapping' validated by this test
49  * will break the compatibility to former releases.
50  *
51  * @author Gregor Roth - Initial contribution
52  */
53 @NonNullByDefault
54 public class WebthingChannelLinkTest {
55     private final Gson gson = new Gson();
56
57     @Test
58     public void testChannelToProperty() throws Exception {
59         var httpClient = mock(org.eclipse.jetty.client.HttpClient.class);
60         var request = Mocks.mockRequest(null, load("/awning_response.json"));
61         when(httpClient.newRequest(URI.create("http://example.org:8090/0"))).thenReturn(request);
62
63         var request2 = Mocks.mockRequest("{\"target_position\":10}", load("/awning_property.json"));
64         when(httpClient.newRequest(URI.create("http://example.org:8090/0/properties/target_position")))
65                 .thenReturn(request2);
66
67         var thingUID = new ThingUID("webthing", "anwing");
68         var channelUID = Channels.createChannelUID(thingUID, "target_position");
69
70         var webthing = WebthingTest.createTestWebthing("http://example.org:8090/0", httpClient);
71         var channel = Channels.createChannel(thingUID, "target_position",
72                 Objects.requireNonNull(webthing.getPropertyDescription("target_position")));
73
74         var testWebthingThingHandler = new TestWebthingThingHandler();
75         ChannelToPropertyLink.establish(testWebthingThingHandler, channel, webthing, "target_position");
76
77         testWebthingThingHandler.listeners.get(channelUID).onItemStateChanged(channelUID, new DecimalType(10));
78     }
79
80     @Test
81     public void testChannelToPropertyServerError() throws Exception {
82         var httpClient = mock(org.eclipse.jetty.client.HttpClient.class);
83         var request = Mocks.mockRequest(null, load("/awning_response.json"));
84         when(httpClient.newRequest(URI.create("http://example.org:8090/0"))).thenReturn(request);
85
86         var request2 = Mocks.mockRequest("{\"target_position\":130}", load("/awning_property.json"), 200, 500);
87         when(httpClient.newRequest(URI.create("http://example.org:8090/0/properties/target_position")))
88                 .thenReturn(request2);
89
90         var thingUID = new ThingUID("webthing", "anwing");
91         var channelUID = Channels.createChannelUID(thingUID, "target_position");
92
93         var webthing = WebthingTest.createTestWebthing("http://example.org:8090/0", httpClient);
94         var channel = Channels.createChannel(thingUID, "target_position",
95                 Objects.requireNonNull(webthing.getPropertyDescription("target_position")));
96
97         var testWebthingThingHandler = new TestWebthingThingHandler();
98         ChannelToPropertyLink.establish(testWebthingThingHandler, channel, webthing, "target_position");
99
100         testWebthingThingHandler.listeners.get(channelUID).onItemStateChanged(channelUID, new DecimalType(130));
101     }
102
103     @Test
104     public void testPropertyToChannel() throws Exception {
105         var httpClient = mock(org.eclipse.jetty.client.HttpClient.class);
106         var request = Mocks.mockRequest(null, load("/awning_response.json"));
107         when(httpClient.newRequest(URI.create("http://example.org:8090/0"))).thenReturn(request);
108
109         var request2 = Mocks.mockRequest("{\"target_position\":10}", load("/awning_property.json"));
110         when(httpClient.newRequest(URI.create("http://example.org:8090/0/properties/target_position")))
111                 .thenReturn(request2);
112
113         var thingUID = new ThingUID("webthing", "anwing");
114         var channelUID = Channels.createChannelUID(thingUID, "target_position");
115
116         var errorHandler = new WebthingTest.ErrorHandler();
117         var websocketConnectionFactory = new WebthingTest.TestWebsocketConnectionFactory();
118         var webthing = WebthingTest.createTestWebthing("http://example.org:8090/0", httpClient, errorHandler,
119                 websocketConnectionFactory);
120         var channel = Channels.createChannel(thingUID, "target_position",
121                 Objects.requireNonNull(webthing.getPropertyDescription("target_position")));
122
123         var testWebthingThingHandler = new TestWebthingThingHandler();
124         PropertyToChannelLink.establish(webthing, "target_position", testWebthingThingHandler, channel);
125
126         var message = new PropertyStatusMessage();
127         message.messageType = "propertyStatus";
128         message.data = Map.of("target_position", 77);
129         websocketConnectionFactory.webSocketRef.get().sendToClient(message);
130
131         assertEquals(new DecimalType(77), testWebthingThingHandler.itemState.get(channelUID));
132     }
133
134     @Test
135     public void testDataTypeMapping() throws Exception {
136         performDataTypeMappingTest("level_prop", 56.5, new DecimalType(56.5), 3.5, new DecimalType(3.5));
137         performDataTypeMappingTest("level_unit_prop", 10, new PercentType(10), 90, new PercentType(90));
138         performDataTypeMappingTest("thermo_prop", "off", new StringType("off"), "auto", new StringType("auto"));
139         performDataTypeMappingTest("temp_prop", 18.6, new DecimalType(18.6), 23.2, new DecimalType(23.2));
140         performDataTypeMappingTest("targettemp_prop", 18.6, new DecimalType(18.6), 23.2, new DecimalType(23.2));
141         performDataTypeMappingTest("open_prop", true, OpenClosedType.OPEN, false, OpenClosedType.CLOSED);
142         performDataTypeMappingTest("colortemp_prop", 10, new PercentType(10), 60, new PercentType(60));
143         performDataTypeMappingTest("color_prop", "#f2fe00", new HSBType("62,100,99"), "#ff0000",
144                 new HSBType("0.0,100.0,100.0"));
145         performDataTypeMappingTest("colormode_prop", "color", new StringType("color"), "temperature",
146                 new StringType("temperature"));
147         performDataTypeMappingTest("brightness_prop", 33, new PercentType(33), 65, new PercentType(65));
148         performDataTypeMappingTest("voltage_prop", 4.5, new DecimalType(4.5), 30.2, new DecimalType(30.2));
149         performDataTypeMappingTest("heating_prop", "off", new StringType("off"), "cooling", new StringType("cooling"));
150         performDataTypeMappingTest("onoff_prop", true, OnOffType.ON, false, OnOffType.OFF);
151         performDataTypeMappingTest("string_prop", "initial", new StringType("initial"), "updated",
152                 new StringType("updated"));
153         performDataTypeMappingTest("number_prop", 80.5, new DecimalType(80.5), 60.9, new DecimalType(60.9));
154         performDataTypeMappingTest("integer_prop", 11, new DecimalType(11), 77, new DecimalType(77));
155         performDataTypeMappingTest("boolean_prop", true, OnOffType.ON, false, OnOffType.OFF);
156     }
157
158     private void performDataTypeMappingTest(String propertyName, Object initialValue, State initialState,
159             Object updatedValue, State updatedState) throws Exception {
160         var httpClient = mock(org.eclipse.jetty.client.HttpClient.class);
161         var request = Mocks.mockRequest(null, load("/datatypes_test_response.json"));
162         when(httpClient.newRequest(URI.create("http://example.org:8090/"))).thenReturn(request);
163
164         var request2 = Mocks.mockRequest(gson.toJson(Map.of(propertyName, updatedValue)),
165                 gson.toJson(Map.of(propertyName, initialValue)));
166         when(httpClient.newRequest(URI.create("http://example.org:8090/properties/" + propertyName)))
167                 .thenReturn(request2);
168
169         var thingUID = new ThingUID("webthing", "test");
170         var channelUID = Channels.createChannelUID(thingUID, propertyName);
171
172         var errorHandler = new WebthingTest.ErrorHandler();
173         var websocketConnectionFactory = new WebthingTest.TestWebsocketConnectionFactory();
174         var webthing = WebthingTest.createTestWebthing("http://example.org:8090/", httpClient, errorHandler,
175                 websocketConnectionFactory);
176         var channel = Channels.createChannel(thingUID, propertyName,
177                 Objects.requireNonNull(webthing.getPropertyDescription(propertyName)));
178
179         var testWebthingThingHandler = new TestWebthingThingHandler();
180
181         PropertyToChannelLink.establish(webthing, propertyName, testWebthingThingHandler, channel);
182
183         var message = new PropertyStatusMessage();
184         message.messageType = "propertyStatus";
185         message.data = Map.of(propertyName, initialValue);
186         websocketConnectionFactory.webSocketRef.get().sendToClient(message);
187
188         assertEquals(initialState, testWebthingThingHandler.itemState.get(channelUID));
189
190         ChannelToPropertyLink.establish(testWebthingThingHandler, channel, webthing, propertyName);
191         testWebthingThingHandler.listeners.get(channelUID).onItemStateChanged(channelUID, updatedState);
192     }
193
194     public static String load(String name) throws Exception {
195         return new String(Files.readAllBytes(Paths.get(WebthingTest.class.getResource(name).toURI())));
196     }
197
198     private static class TestWebthingThingHandler implements ChannelHandler {
199         public final Map<ChannelUID, ItemChangedListener> listeners = new ConcurrentHashMap<>();
200         public final Map<ChannelUID, Command> itemState = new ConcurrentHashMap<>();
201
202         @Override
203         public void observeChannel(ChannelUID channelUID, ItemChangedListener listener) {
204             listeners.put(channelUID, listener);
205         }
206
207         @Override
208         public void updateItemState(ChannelUID channelUID, Command command) {
209             itemState.put(channelUID, command);
210         }
211     }
212 }