]> git.basschouten.com Git - openhab-addons.git/blob
0ffc01d6a3b63831ef37fb61c8bc574f88d5a0e8
[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.loxone.internal.controls;
14
15 import static org.hamcrest.CoreMatchers.*;
16 import static org.hamcrest.MatcherAssert.assertThat;
17 import static org.junit.jupiter.api.Assertions.*;
18
19 import java.io.BufferedReader;
20 import java.io.InputStream;
21 import java.io.InputStreamReader;
22 import java.math.BigDecimal;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.stream.Collectors;
27
28 import org.junit.jupiter.api.BeforeEach;
29 import org.junit.jupiter.api.Test;
30 import org.openhab.binding.loxone.internal.types.LxUuid;
31 import org.openhab.core.library.types.DecimalType;
32 import org.openhab.core.library.types.OnOffType;
33 import org.openhab.core.library.types.UpDownType;
34 import org.openhab.core.types.StateOption;
35 import org.openhab.core.types.UnDefType;
36
37 /**
38  * Test class for (@link LxControlSwitch}
39  *
40  * @author Pawel Pieczul - initial contribution
41  *
42  */
43 public class LxControlLightControllerV2Test extends LxControlTest {
44     @BeforeEach
45     public void setup() {
46         setupControl("1076668f-0101-7076-ffff403fb0c34b9e", "0b734138-03ac-03f0-ffff403fb0c34b9e",
47                 "0b734138-033e-02d4-ffff403fb0c34b9e", "Lighting controller");
48     }
49
50     @Test
51     public void testControlCreation() {
52         testControlCreation(LxControlLightControllerV2.class, 1, 5, 1, 6, 4);
53         testSubControl(LxControlSwitch.class, "Overall Switch");
54         testSubControl(LxControlSwitch.class, "Hall Study Lights");
55         testSubControl(LxControlSwitch.class, "Roof Lights");
56         testSubControl(LxControlSwitch.class, "Hall Left Lights");
57         testSubControl(LxControlSwitch.class, "Hall Right Lights");
58     }
59
60     @Test
61     public void testChannels() {
62         testChannel("Number", Collections.singleton("Scene"));
63     }
64
65     @Test
66     public void testCommands() {
67         for (int i = 0; i < 20; i++) {
68             executeCommand(UpDownType.UP);
69             testAction("plus");
70             executeCommand(UpDownType.DOWN);
71             testAction("minus");
72         }
73         executeCommand(new DecimalType(1));
74         testAction(null);
75
76         loadMoodList1();
77
78         executeCommand(new DecimalType(0));
79         testAction(null);
80         executeCommand(new DecimalType(1));
81         testAction(null);
82         executeCommand(new DecimalType(2));
83         testAction("changeTo/2");
84         executeCommand(new DecimalType(3));
85         testAction("changeTo/3");
86         executeCommand(new DecimalType(4));
87         testAction("changeTo/4");
88         executeCommand(new DecimalType(5));
89         testAction("changeTo/5");
90         executeCommand(new DecimalType(6));
91         testAction(null);
92         executeCommand(new DecimalType(777));
93         testAction("changeTo/777");
94         executeCommand(new DecimalType(778));
95         testAction("changeTo/778");
96         executeCommand(new DecimalType(779));
97         testAction(null);
98         clearMoodList();
99     }
100
101     @Test
102     public void testMoodListChanges() {
103         for (int i = 0; i < 20; i++) {
104             loadMoodList1();
105             loadMoodList2();
106         }
107         clearMoodList();
108     }
109
110     @Test
111     public void testActiveMoodChanges() {
112         loadMoodList2();
113         for (int i = 0; i < 10; i++) {
114             changeLoxoneState("activemoods", "[4]");
115             testActiveMoods(779, 4);
116             changeLoxoneState("activemoods", "[4,6]");
117             testActiveMoods(779, 4, 6);
118             changeLoxoneState("activemoods", "[4,6,7,8,5]");
119             testActiveMoods(779, 4, 6, 7, 8, 5);
120             changeLoxoneState("activemoods", "[4,6,7,8,5,777,778]");
121             testActiveMoods(779, 4, 6, 7, 8, 5, 777, 778);
122             changeLoxoneState("activemoods", "[6,8,777]");
123             testActiveMoods(779, 6, 8, 777);
124             changeLoxoneState("activemoods", "[779]");
125             testActiveMoods(779, 779);
126             changeLoxoneState("activemoods", "[1,2,3,500,900]");
127             testActiveMoods(779);
128             changeLoxoneState("activemoods", "[1,2,3,6,500,900]");
129             testActiveMoods(779, 6);
130             changeLoxoneState("activemoods", "[5]");
131             testActiveMoods(779, 5);
132             changeLoxoneState("activemoods", "[778]");
133             testActiveMoods(779, 778);
134         }
135         clearMoodList();
136     }
137
138     @Test
139     public void testMoodAddRemove() {
140         loadMoodList1();
141         for (int i = 0; i < 10; i++) {
142             handler.extraControls.values().forEach(c -> {
143                 LxControlMood m = (LxControlMood) c;
144                 if (!m.getId().equals(778)) {
145                     executeCommand(m, OnOffType.ON);
146                     testAction("addMood/" + m.getId());
147                     executeCommand(m, OnOffType.OFF);
148                     testAction("removeMood/" + m.getId());
149                 }
150             });
151         }
152         clearMoodList();
153     }
154
155     private void testActiveMoods(Integer offId, Integer... moods) {
156         List<Integer> ids = new ArrayList<>();
157         for (Integer id : moods) {
158             if (!offId.equals(id)) {
159                 LxControlMood m = getMood(id);
160                 testChannelState(m, OnOffType.ON);
161             }
162             ids.add(id);
163         }
164         handler.extraControls.values().stream()
165                 .filter(c -> !ids.contains(((LxControlMood) c).getId()) && !((LxControlMood) c).getId().equals(offId))
166                 .forEach(c -> testChannelState(c, OnOffType.OFF));
167
168         if (ids.size() == 1) {
169             testChannelState(new DecimalType(ids.get(0)));
170         } else {
171             testChannelState(UnDefType.UNDEF);
172         }
173     }
174
175     private void loadMoodList1() {
176         String list = loadMoodList("MoodList1.json");
177         changeLoxoneState("moodlist", list);
178         List<StateOption> options = new ArrayList<>();
179         options.add(new StateOption("2", "Side Lights"));
180         options.add(new StateOption("3", "Play Lights"));
181         options.add(new StateOption("4", "Study Only"));
182         options.add(new StateOption("5", "Low Lights"));
183         options.add(new StateOption("777", "Bright"));
184         options.add(new StateOption("778", "Off"));
185         testMoodList(options, 778);
186     }
187
188     private void loadMoodList2() {
189         String list = loadMoodList("MoodList2.json");
190         changeLoxoneState("moodlist", list);
191         List<StateOption> options = new ArrayList<>();
192         options.add(new StateOption("4", "Study Only Changed Name")); // changed name
193         options.add(new StateOption("5", "Low Lights")); // same as in list 1
194         options.add(new StateOption("6", "Play Lights")); // changed id
195         options.add(new StateOption("7", "New Mood 1"));
196         options.add(new StateOption("8", "New Mood 2"));
197         options.add(new StateOption("777", "Bright"));
198         options.add(new StateOption("778", "Off"));
199         options.add(new StateOption("779", "New Off"));
200         testMoodList(options, 779);
201     }
202
203     private LxControlMood getMood(Integer id) {
204         LxControl ctrl = handler.extraControls.get(new LxUuid("1076668f-0101-7076-ffff403fb0c34b9e-M" + id));
205         assertNotNull(ctrl);
206         assertThat(ctrl, is(instanceOf(LxControlMood.class)));
207         return (LxControlMood) ctrl;
208     }
209
210     private void clearMoodList() {
211         changeLoxoneState("moodlist", "[]");
212         List<StateOption> options = new ArrayList<>();
213         testMoodList(options, 0);
214     }
215
216     private void testMoodList(List<StateOption> options, Integer offId) {
217         assertEquals(options.size(), handler.extraControls.size());
218         if (options.isEmpty()) {
219             return;
220         }
221         Integer min = null;
222         Integer max = null;
223         for (StateOption o : options) {
224             testMood(o.getLabel(), o.getValue(), o.getValue().equals(offId.toString()));
225             Integer id = Integer.parseInt(o.getValue());
226             assertNotNull(id);
227             if (min == null || id < min) {
228                 min = id;
229             }
230             if (max == null || id > max) {
231                 max = id;
232             }
233         }
234         assertNotNull(min);
235         assertNotNull(max);
236         testChannel("Number", null, new BigDecimal(min), new BigDecimal(max), BigDecimal.ONE, null, false, options,
237                 Collections.singleton("Scene"));
238     }
239
240     private void testMood(String name, String id, boolean isStatic) {
241         LxControlMood mood = getMood(Integer.parseInt(id));
242         assertEquals(new LxUuid("0b734138-03ac-03f0-ffff403fb0c34b9e"), mood.getRoom().getUuid());
243         assertEquals(new LxUuid("0b734138-033e-02d4-ffff403fb0c34b9e"), mood.getCategory().getUuid());
244         assertEquals(name, mood.getName());
245         assertEquals(id, mood.getId().toString());
246         if (isStatic) {
247             assertEquals(0, mood.getChannels().size());
248         } else {
249             assertEquals(1, mood.getChannels().size());
250             testChannel(mood, "Switch", Collections.singleton("Lighting"));
251         }
252     }
253
254     private String loadMoodList(String name) {
255         InputStream stream = LxControlLightControllerV2Test.class.getResourceAsStream(name);
256         assertNotNull(stream);
257         BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
258         assertNotNull(reader);
259         String msg = reader.lines().collect(Collectors.joining(System.lineSeparator()));
260         assertNotNull(msg);
261         // mood list comes as a single line JSON from Loxone Miniserver
262         msg = msg.replaceAll("[\\t+\\n+]", "");
263         return msg;
264     }
265 }