]> git.basschouten.com Git - openhab-addons.git/blob
9ff969e3e2b7d5b1febc1651ed35becaef9ce91d
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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.junit.jupiter.api.Test;
21 import org.openhab.binding.mqtt.generic.values.OnOffValue;
22 import org.openhab.binding.mqtt.generic.values.PercentageValue;
23 import org.openhab.binding.mqtt.generic.values.TextValue;
24 import org.openhab.core.library.types.OnOffType;
25 import org.openhab.core.library.types.PercentType;
26 import org.openhab.core.library.types.StringType;
27 import org.openhab.core.types.UnDefType;
28
29 /**
30  * Tests for {@link Vacuum}
31  *
32  * @author Anton Kharuzhy - Initial contribution
33  */
34 @SuppressWarnings("ConstantConditions")
35 public class VacuumTests extends AbstractComponentTests {
36     public static final String CONFIG_TOPIC = "vacuum/rockrobo_vacuum";
37
38     @Test
39     public void testRoborockValetudo() {
40         // @formatter:off
41         var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC), "{" +
42                 "\"name\":\"Rockrobo\"," +
43                 "\"unique_id\":\"rockrobo_vacuum\"," +
44                 "\"schema\":\"state\"," +
45                 "\"device\":{" +
46                 "   \"manufacturer\":\"Roborock\"," +
47                 "   \"model\":\"v1\"," +
48                 "   \"name\":\"rockrobo\"," +
49                 "   \"identifiers\":[\"rockrobo\"]," +
50                 "   \"sw_version\":\"0.9.9\"" +
51                 "}," +
52                 "\"supported_features\":[\"start\",\"pause\",\"stop\",\"return_home\",\"battery\",\"status\"," +
53                 "   \"locate\",\"clean_spot\",\"fan_speed\",\"send_command\"]," +
54                 "\"command_topic\":\"valetudo/rockrobo/command\"," +
55                 "\"state_topic\":\"valetudo/rockrobo/state\"," +
56                 "\"set_fan_speed_topic\":\"valetudo/rockrobo/set_fan_speed\"," +
57                 "\"fan_speed_list\":[\"min\",\"medium\",\"high\",\"max\",\"mop\"]," +
58                 "\"send_command_topic\":\"valetudo/rockrobo/custom_command\"," +
59                 "\"json_attributes_topic\":\"valetudo/rockrobo/attributes\"" +
60                 "}");
61         // @formatter:on
62
63         assertThat(component.channels.size(), is(6)); // command, state, fan speed, send command, battery, json attrs
64         assertThat(component.getName(), is("Rockrobo"));
65         assertChannel(component, Vacuum.COMMAND_CH_ID, "", "valetudo/rockrobo/command", "Rockrobo", TextValue.class);
66         assertChannel(component, Vacuum.STATE_CH_ID, "valetudo/rockrobo/state", "", "Rockrobo", TextValue.class);
67         assertChannel(component, Vacuum.FAN_SPEED_CH_ID, "valetudo/rockrobo/state", "valetudo/rockrobo/set_fan_speed",
68                 "Rockrobo", TextValue.class);
69         assertChannel(component, Vacuum.CUSTOM_COMMAND_CH_ID, "", "valetudo/rockrobo/custom_command", "Rockrobo",
70                 TextValue.class);
71         assertChannel(component, Vacuum.BATTERY_LEVEL_CH_ID, "valetudo/rockrobo/state", "", "Rockrobo",
72                 PercentageValue.class);
73         assertChannel(component, Vacuum.JSON_ATTRIBUTES_CH_ID, "valetudo/rockrobo/attributes", "", "Rockrobo",
74                 TextValue.class);
75
76         assertState(component, Vacuum.STATE_CH_ID, UnDefType.UNDEF);
77         assertState(component, Vacuum.FAN_SPEED_CH_ID, UnDefType.UNDEF);
78         assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, UnDefType.UNDEF);
79         assertState(component, Vacuum.JSON_ATTRIBUTES_CH_ID, UnDefType.UNDEF);
80
81         // @formatter:off
82         String jsonValue;
83         publishMessage("valetudo/rockrobo/attributes", jsonValue = "{" +
84                 "\"mainBrush\":\"245.1\"," +
85                 "\"sideBrush\":\"145.1\"," +
86                 "\"filter\":\"95.1\"," +
87                 "\"sensor\":\"0.0\"," +
88                 "\"currentCleanTime\":\"52.0\"," +
89                 "\"currentCleanArea\":\"46.7\"," +
90                 "\"cleanTime\":\"54.9\"," +
91                 "\"cleanArea\":\"3280.9\"," +
92                 "\"cleanCount\":84," +
93                 "\"last_run_stats\":{" +
94                 "   \"startTime\":1633257319000," +
95                 "   \"endTime\":1633260439000," +
96                 "   \"duration\":3120," +
97                 "   \"area\":\"46.7\"," +
98                 "   \"errorCode\":0," +
99                 "   \"errorDescription\":\"No error\"," +
100                 "   \"finishedFlag\":true" +
101                 "}," +
102                 "\"last_bin_out\":2147483647000," +
103                 "\"state\":\"docked\"," +
104                 "\"valetudo_state\":{" +
105                 "   \"id\":8," +
106                 "   \"name\":\"Charging\"" +
107                 "}," +
108                 "\"last_bin_full\":0" +
109                 "}");
110         // @formatter:on
111
112         // @formatter:off
113         publishMessage("valetudo/rockrobo/state", "{" +
114                 "\"state\":\"docked\"," +
115                 "\"battery_level\":100," +
116                 "\"fan_speed\":\"max\"" +
117                 "}");
118         // @formatter:on
119
120         assertState(component, Vacuum.STATE_CH_ID, new StringType(Vacuum.STATE_DOCKED));
121         assertState(component, Vacuum.FAN_SPEED_CH_ID, new StringType("max"));
122         assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, new PercentType(100));
123         assertState(component, Vacuum.JSON_ATTRIBUTES_CH_ID, new StringType(jsonValue));
124
125         component.getChannel(Vacuum.COMMAND_CH_ID).getState().publishValue(new StringType("start"));
126         assertPublished("valetudo/rockrobo/command", "start");
127
128         // @formatter:off
129         publishMessage("valetudo/rockrobo/state", "{" +
130                 "\"state\":\"cleaning\"," +
131                 "\"battery_level\":99," +
132                 "\"fan_speed\":\"max\"" +
133                 "}");
134         // @formatter:on
135
136         assertState(component, Vacuum.STATE_CH_ID, new StringType(Vacuum.STATE_CLEANING));
137         assertState(component, Vacuum.FAN_SPEED_CH_ID, new StringType("max"));
138         assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, new PercentType(99));
139         assertState(component, Vacuum.JSON_ATTRIBUTES_CH_ID, new StringType(jsonValue));
140
141         component.getChannel(Vacuum.FAN_SPEED_CH_ID).getState().publishValue(new StringType("medium"));
142         assertPublished("valetudo/rockrobo/set_fan_speed", "medium");
143
144         // @formatter:off
145         publishMessage("valetudo/rockrobo/state", "{" +
146                 "\"state\":\"returning\"," +
147                 "\"battery_level\":80," +
148                 "\"fan_speed\":\"medium\"" +
149                 "}");
150         // @formatter:on
151
152         assertState(component, Vacuum.STATE_CH_ID, new StringType(Vacuum.STATE_RETURNING));
153         assertState(component, Vacuum.FAN_SPEED_CH_ID, new StringType("medium"));
154         assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, new PercentType(80));
155         assertState(component, Vacuum.JSON_ATTRIBUTES_CH_ID, new StringType(jsonValue));
156     }
157
158     @Test
159     public void testLegacySchema() {
160         // @formatter:off
161         var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC), "{" +
162                 "\"name\":\"Rockrobo\"," +
163                 "\"unique_id\":\"rockrobo_vacuum\"," +
164                 "\"device\":{" +
165                 "   \"manufacturer\":\"Roborock\"," +
166                 "   \"model\":\"v1\"," +
167                 "   \"name\":\"rockrobo\"," +
168                 "   \"identifiers\":[\"rockrobo\"]," +
169                 "   \"sw_version\":\"0.9.9\"" +
170                 "}," +
171                 "\"supported_features\":[\"turn_on\", \"turn_off\",\"pause\",\"stop\",\"return_home\",\"battery\",\"status\"," +
172                 "   \"locate\",\"clean_spot\",\"fan_speed\",\"send_command\"]," +
173                 "\"command_topic\":\"vacuum/command\"," +
174                 "\"battery_level_topic\":\"vacuum/state\"," +
175                 "\"battery_level_template\":\"{{ value_json.battery_level }}\"," +
176                 "\"charging_topic\":\"vacuum/state\"," +
177                 "\"charging_template\":\"{{ value_json.charging }}\"," +
178                 "\"cleaning_topic\":\"vacuum/state\"," +
179                 "\"cleaning_template\":\"{{ value_json.cleaning }}\"," +
180                 "\"docked_topic\":\"vacuum/state\"," +
181                 "\"docked_template\":\"{{ value_json.docked }}\"," +
182                 "\"error_topic\":\"vacuum/state\"," +
183                 "\"error_template\":\"{{ value_json.error }}\"," +
184                 "\"fan_speed_topic\":\"vacuum/state\"," +
185                 "\"set_fan_speed_topic\":\"vacuum/set_fan_speed\"," +
186                 "\"fan_speed_template\":\"{{ value_json.fan_speed }}\"," +
187                 "\"fan_speed_list\":[\"min\",\"medium\",\"high\",\"max\"]," +
188                 "\"send_command_topic\":\"vacuum/send_command\"" +
189                 "}");
190         // @formatter:on
191
192         assertThat(component.channels.size(), is(8)); // command, battery, charging, cleaning, docked, error,
193         // fan speed, send command
194         assertThat(component.getName(), is("Rockrobo"));
195         assertChannel(component, Vacuum.COMMAND_CH_ID, "", "vacuum/command", "Rockrobo", TextValue.class);
196         assertChannel(component, Vacuum.BATTERY_LEVEL_CH_ID, "vacuum/state", "", "Rockrobo", PercentageValue.class);
197         assertChannel(component, Vacuum.CHARGING_CH_ID, "vacuum/state", "", "Rockrobo", OnOffValue.class);
198         assertChannel(component, Vacuum.CLEANING_CH_ID, "vacuum/state", "", "Rockrobo", OnOffValue.class);
199         assertChannel(component, Vacuum.DOCKED_CH_ID, "vacuum/state", "", "Rockrobo", OnOffValue.class);
200         assertChannel(component, Vacuum.ERROR_CH_ID, "vacuum/state", "", "Rockrobo", TextValue.class);
201         assertChannel(component, Vacuum.FAN_SPEED_CH_ID, "vacuum/state", "vacuum/set_fan_speed", "Rockrobo",
202                 TextValue.class);
203         assertChannel(component, Vacuum.CUSTOM_COMMAND_CH_ID, "", "vacuum/send_command", "Rockrobo", TextValue.class);
204
205         // @formatter:off
206         publishMessage("vacuum/state", "{" +
207                 "\"battery_level\": 61," +
208                 "\"docked\": true," +
209                 "\"cleaning\": false," +
210                 "\"charging\": true," +
211                 "\"fan_speed\": \"off\"," +
212                 "\"error\": \"Error message\"" +
213                 "}");
214         // @formatter:on
215
216         assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, new PercentType(61));
217         assertState(component, Vacuum.DOCKED_CH_ID, OnOffType.ON);
218         assertState(component, Vacuum.CLEANING_CH_ID, OnOffType.OFF);
219         assertState(component, Vacuum.CHARGING_CH_ID, OnOffType.ON);
220         assertState(component, Vacuum.FAN_SPEED_CH_ID, new StringType("off"));
221         assertState(component, Vacuum.ERROR_CH_ID, new StringType("Error message"));
222
223         component.getChannel(Vacuum.COMMAND_CH_ID).getState().publishValue(new StringType("turn_on"));
224         assertPublished("vacuum/command", "turn_on");
225
226         // @formatter:off
227         publishMessage("vacuum/state", "{" +
228                 "\"battery_level\": 55," +
229                 "\"docked\": false," +
230                 "\"cleaning\": true," +
231                 "\"charging\": false," +
232                 "\"fan_speed\": \"medium\"," +
233                 "\"error\": \"\"" +
234                 "}");
235         // @formatter:on
236
237         assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, new PercentType(55));
238         assertState(component, Vacuum.DOCKED_CH_ID, OnOffType.OFF);
239         assertState(component, Vacuum.CLEANING_CH_ID, OnOffType.ON);
240         assertState(component, Vacuum.CHARGING_CH_ID, OnOffType.OFF);
241         assertState(component, Vacuum.FAN_SPEED_CH_ID, new StringType("medium"));
242         assertState(component, Vacuum.ERROR_CH_ID, new StringType(""));
243
244         component.getChannel(Vacuum.FAN_SPEED_CH_ID).getState().publishValue(new StringType("high"));
245         assertPublished("vacuum/set_fan_speed", "high");
246
247         component.getChannel(Vacuum.CUSTOM_COMMAND_CH_ID).getState().publishValue(new StringType("custom_command"));
248         assertPublished("vacuum/send_command", "custom_command");
249     }
250
251     protected Set<String> getConfigTopics() {
252         return Set.of(CONFIG_TOPIC);
253     }
254 }