]> git.basschouten.com Git - openhab-addons.git/blob
ff8bde13ec2f612a414c3fc305b5f4f5180bd064
[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.mqtt.homeassistant.internal.component;
14
15 import static org.hamcrest.CoreMatchers.is;
16 import static org.hamcrest.MatcherAssert.assertThat;
17
18 import java.util.Set;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.junit.jupiter.api.Test;
22 import org.openhab.binding.mqtt.generic.values.RollershutterValue;
23 import org.openhab.binding.mqtt.generic.values.TextValue;
24 import org.openhab.core.library.types.PercentType;
25 import org.openhab.core.library.types.StopMoveType;
26 import org.openhab.core.library.types.StringType;
27 import org.openhab.core.library.types.UpDownType;
28
29 /**
30  * Tests for {@link Cover}
31  *
32  * @author Anton Kharuzhy - Initial contribution
33  */
34 @NonNullByDefault
35 public class CoverTests extends AbstractComponentTests {
36     public static final String CONFIG_TOPIC = "cover/0x0000000000000000_cover_zigbee2mqtt";
37
38     @SuppressWarnings("null")
39     @Test
40     public void testStateOnly() throws InterruptedException {
41         // @formatter:off
42         var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
43                 """
44                 { \
45                   "availability": [ \
46                     { \
47                       "topic": "zigbee2mqtt/bridge/state" \
48                     } \
49                   ], \
50                   "device": { \
51                     "identifiers": [ \
52                       "zigbee2mqtt_0x0000000000000000" \
53                     ], \
54                     "manufacturer": "Covers inc", \
55                     "model": "cover v1", \
56                     "name": "Cover", \
57                     "sw_version": "Zigbee2MQTT 1.18.2" \
58                   }, \
59                   "name": "cover", \
60                   "payload_open": "OPEN_", \
61                   "payload_close": "CLOSE_", \
62                   "payload_stop": "STOP_", \
63                   "state_topic": "zigbee2mqtt/cover/state", \
64                   "command_topic": "zigbee2mqtt/cover/set/state" \
65                 }\
66                 """);
67         // @formatter:on
68
69         assertThat(component.channels.size(), is(2));
70         assertThat(component.getName(), is("cover"));
71
72         assertChannel(component, Cover.STATE_CHANNEL_ID, "zigbee2mqtt/cover/state", "", "State", TextValue.class);
73         assertChannel(component, Cover.COVER_CHANNEL_ID, "zigbee2mqtt/cover/state", "zigbee2mqtt/cover/set/state",
74                 "Cover", RollershutterValue.class);
75
76         publishMessage("zigbee2mqtt/cover/state", "closed");
77         assertState(component, Cover.COVER_CHANNEL_ID, UpDownType.DOWN);
78         assertState(component, Cover.STATE_CHANNEL_ID, new StringType("closed"));
79         publishMessage("zigbee2mqtt/cover/state", "open");
80         assertState(component, Cover.STATE_CHANNEL_ID, new StringType("open"));
81         assertState(component, Cover.COVER_CHANNEL_ID, UpDownType.UP);
82
83         component.getChannel(Cover.COVER_CHANNEL_ID).getState().publishValue(UpDownType.UP);
84         assertPublished("zigbee2mqtt/cover/set/state", "OPEN_");
85         component.getChannel(Cover.COVER_CHANNEL_ID).getState().publishValue(UpDownType.DOWN);
86         assertPublished("zigbee2mqtt/cover/set/state", "CLOSE_");
87         component.getChannel(Cover.COVER_CHANNEL_ID).getState().publishValue(StopMoveType.STOP);
88         assertPublished("zigbee2mqtt/cover/set/state", "STOP_");
89     }
90
91     @SuppressWarnings("null")
92     @Test
93     public void testPositionAndState() throws InterruptedException {
94         // @formatter:off
95         var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
96                 """
97                 {
98                   "dev_cla":"garage",
99                   "pos_t":"esphome/single-car-gdo/cover/door/position/state",
100                   "set_pos_t":"esphome/single-car-gdo/cover/door/position/command",
101                   "name":"Door",
102                   "stat_t":"esphome/single-car-gdo/cover/door/state",
103                   "cmd_t":"esphome/single-car-gdo/cover/door/command",
104                   "avty_t":"esphome/single-car-gdo/status",
105                   "uniq_id":"78e36d645710-cover-d27845ad",
106                   "dev":{
107                     "ids":"78e36d645710",
108                     "name":"Single Car Garage Door Opener",
109                     "sw":"esphome v2023.10.4 Nov  7 2023, 16:19:39",
110                     "mdl":"esp32dev",
111                     "mf":"espressif"}
112                 }
113                 """);
114         // @formatter:on
115
116         assertThat(component.channels.size(), is(2));
117         assertThat(component.getName(), is("Door"));
118
119         assertChannel(component, Cover.STATE_CHANNEL_ID, "esphome/single-car-gdo/cover/door/state", "", "State",
120                 TextValue.class);
121         assertChannel(component, Cover.COVER_CHANNEL_ID, "esphome/single-car-gdo/cover/door/position/state",
122                 "esphome/single-car-gdo/cover/door/position/command", "Cover", RollershutterValue.class);
123
124         publishMessage("esphome/single-car-gdo/cover/door/state", "closed");
125         assertState(component, Cover.STATE_CHANNEL_ID, new StringType("closed"));
126         publishMessage("esphome/single-car-gdo/cover/door/state", "open");
127         assertState(component, Cover.STATE_CHANNEL_ID, new StringType("open"));
128         publishMessage("esphome/single-car-gdo/cover/door/state", "opening");
129         assertState(component, Cover.STATE_CHANNEL_ID, new StringType("opening"));
130
131         publishMessage("esphome/single-car-gdo/cover/door/position/state", "100");
132         assertState(component, Cover.COVER_CHANNEL_ID, PercentType.ZERO);
133         publishMessage("esphome/single-car-gdo/cover/door/position/state", "40");
134         assertState(component, Cover.COVER_CHANNEL_ID, new PercentType(60));
135         publishMessage("esphome/single-car-gdo/cover/door/position/state", "0");
136         assertState(component, Cover.COVER_CHANNEL_ID, PercentType.HUNDRED);
137
138         component.getChannel(Cover.COVER_CHANNEL_ID).getState().publishValue(PercentType.ZERO);
139         assertPublished("esphome/single-car-gdo/cover/door/position/command", "100");
140         component.getChannel(Cover.COVER_CHANNEL_ID).getState().publishValue(PercentType.HUNDRED);
141         assertPublished("esphome/single-car-gdo/cover/door/position/command", "0");
142         component.getChannel(Cover.COVER_CHANNEL_ID).getState().publishValue(StopMoveType.STOP);
143         assertPublished("esphome/single-car-gdo/cover/door/command", "STOP");
144         component.getChannel(Cover.COVER_CHANNEL_ID).getState().publishValue(UpDownType.UP);
145         assertPublished("esphome/single-car-gdo/cover/door/command", "OPEN");
146         component.getChannel(Cover.COVER_CHANNEL_ID).getState().publishValue(UpDownType.DOWN);
147         assertPublished("esphome/single-car-gdo/cover/door/command", "CLOSE");
148         component.getChannel(Cover.COVER_CHANNEL_ID).getState().publishValue(new PercentType(40));
149         assertPublished("esphome/single-car-gdo/cover/door/position/command", "60");
150     }
151
152     @SuppressWarnings("null")
153     @Test
154     public void testPositionOnly() throws InterruptedException {
155         // @formatter:off
156         var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
157                 """
158                 {
159                   "dev_cla":"garage",
160                   "pos_t":"esphome/single-car-gdo/cover/door/position/state",
161                   "set_pos_t":"esphome/single-car-gdo/cover/door/position/command",
162                   "name":"Door",
163                   "avty_t":"esphome/single-car-gdo/status",
164                   "uniq_id":"78e36d645710-cover-d27845ad",
165                   "dev":{
166                     "ids":"78e36d645710",
167                     "name":"Single Car Garage Door Opener",
168                     "sw":"esphome v2023.10.4 Nov  7 2023, 16:19:39",
169                     "mdl":"esp32dev",
170                     "mf":"espressif"}
171                 }
172                 """);
173         // @formatter:on
174
175         assertThat(component.channels.size(), is(1));
176         assertThat(component.getName(), is("Door"));
177
178         assertChannel(component, Cover.COVER_CHANNEL_ID, "esphome/single-car-gdo/cover/door/position/state",
179                 "esphome/single-car-gdo/cover/door/position/command", "Cover", RollershutterValue.class);
180
181         publishMessage("esphome/single-car-gdo/cover/door/position/state", "100");
182         assertState(component, Cover.COVER_CHANNEL_ID, PercentType.ZERO);
183         publishMessage("esphome/single-car-gdo/cover/door/position/state", "40");
184         assertState(component, Cover.COVER_CHANNEL_ID, new PercentType(60));
185         publishMessage("esphome/single-car-gdo/cover/door/position/state", "0");
186         assertState(component, Cover.COVER_CHANNEL_ID, PercentType.HUNDRED);
187
188         component.getChannel(Cover.COVER_CHANNEL_ID).getState().publishValue(PercentType.ZERO);
189         assertPublished("esphome/single-car-gdo/cover/door/position/command", "100");
190         component.getChannel(Cover.COVER_CHANNEL_ID).getState().publishValue(PercentType.HUNDRED);
191         assertPublished("esphome/single-car-gdo/cover/door/position/command", "0");
192         component.getChannel(Cover.COVER_CHANNEL_ID).getState().publishValue(UpDownType.UP);
193         assertPublished("esphome/single-car-gdo/cover/door/position/command", "100", 2);
194         component.getChannel(Cover.COVER_CHANNEL_ID).getState().publishValue(UpDownType.DOWN);
195         assertPublished("esphome/single-car-gdo/cover/door/position/command", "0", 2);
196         component.getChannel(Cover.COVER_CHANNEL_ID).getState().publishValue(new PercentType(40));
197         assertPublished("esphome/single-car-gdo/cover/door/position/command", "60");
198     }
199
200     @Override
201     protected Set<String> getConfigTopics() {
202         return Set.of(CONFIG_TOPIC);
203     }
204 }