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.mqtt.homeassistant.internal.component;
15 import static org.hamcrest.CoreMatchers.is;
16 import static org.hamcrest.MatcherAssert.assertThat;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.junit.jupiter.api.Test;
22 import org.openhab.binding.mqtt.generic.values.OnOffValue;
23 import org.openhab.binding.mqtt.generic.values.PercentageValue;
24 import org.openhab.binding.mqtt.generic.values.TextValue;
25 import org.openhab.core.library.types.OnOffType;
26 import org.openhab.core.library.types.PercentType;
27 import org.openhab.core.library.types.StringType;
28 import org.openhab.core.types.UnDefType;
31 * Tests for {@link Vacuum}
33 * @author Anton Kharuzhy - Initial contribution
36 public class VacuumTests extends AbstractComponentTests {
37 public static final String CONFIG_TOPIC = "vacuum/rockrobo_vacuum";
39 @SuppressWarnings("null")
41 public void testRoborockValetudo() {
43 var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC), """
46 "unique_id":"rockrobo_vacuum",\
49 "manufacturer":"Roborock",\
52 "identifiers":["rockrobo"],\
55 "supported_features":["start","pause","stop","return_home","battery","status",\
56 "locate","clean_spot","fan_speed","send_command"],\
57 "command_topic":"valetudo/rockrobo/command",\
58 "state_topic":"valetudo/rockrobo/state",\
59 "set_fan_speed_topic":"valetudo/rockrobo/set_fan_speed",\
60 "fan_speed_list":["min","medium","high","max","mop"],\
61 "send_command_topic":"valetudo/rockrobo/custom_command",\
62 "json_attributes_topic":"valetudo/rockrobo/attributes"\
67 assertThat(component.channels.size(), is(6)); // command, state, fan speed, send command, battery, json attrs
68 assertThat(component.getName(), is("Rockrobo"));
69 assertChannel(component, Vacuum.COMMAND_CH_ID, "", "valetudo/rockrobo/command", "Rockrobo", TextValue.class);
70 assertChannel(component, Vacuum.STATE_CH_ID, "valetudo/rockrobo/state", "", "Rockrobo", TextValue.class);
71 assertChannel(component, Vacuum.FAN_SPEED_CH_ID, "valetudo/rockrobo/state", "valetudo/rockrobo/set_fan_speed",
72 "Rockrobo", TextValue.class);
73 assertChannel(component, Vacuum.CUSTOM_COMMAND_CH_ID, "", "valetudo/rockrobo/custom_command", "Rockrobo",
75 assertChannel(component, Vacuum.BATTERY_LEVEL_CH_ID, "valetudo/rockrobo/state", "", "Rockrobo",
76 PercentageValue.class);
77 assertChannel(component, Vacuum.JSON_ATTRIBUTES_CH_ID, "valetudo/rockrobo/attributes", "", "Rockrobo",
80 assertState(component, Vacuum.STATE_CH_ID, UnDefType.UNDEF);
81 assertState(component, Vacuum.FAN_SPEED_CH_ID, UnDefType.UNDEF);
82 assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, UnDefType.UNDEF);
83 assertState(component, Vacuum.JSON_ATTRIBUTES_CH_ID, UnDefType.UNDEF);
87 publishMessage("valetudo/rockrobo/attributes", jsonValue = """
93 "currentCleanTime":"52.0",\
94 "currentCleanArea":"46.7",\
96 "cleanArea":"3280.9",\
99 "startTime":1633257319000,\
100 "endTime":1633260439000,\
104 "errorDescription":"No error",\
107 "last_bin_out":2147483647000,\
119 publishMessage("valetudo/rockrobo/state", """
122 "battery_level":100,\
128 assertState(component, Vacuum.STATE_CH_ID, new StringType(Vacuum.STATE_DOCKED));
129 assertState(component, Vacuum.FAN_SPEED_CH_ID, new StringType("max"));
130 assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, new PercentType(100));
131 assertState(component, Vacuum.JSON_ATTRIBUTES_CH_ID, new StringType(jsonValue));
133 component.getChannel(Vacuum.COMMAND_CH_ID).getState().publishValue(new StringType("start"));
134 assertPublished("valetudo/rockrobo/command", "start");
137 publishMessage("valetudo/rockrobo/state", """
146 assertState(component, Vacuum.STATE_CH_ID, new StringType(Vacuum.STATE_CLEANING));
147 assertState(component, Vacuum.FAN_SPEED_CH_ID, new StringType("max"));
148 assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, new PercentType(99));
149 assertState(component, Vacuum.JSON_ATTRIBUTES_CH_ID, new StringType(jsonValue));
151 component.getChannel(Vacuum.FAN_SPEED_CH_ID).getState().publishValue(new StringType("medium"));
152 assertPublished("valetudo/rockrobo/set_fan_speed", "medium");
155 publishMessage("valetudo/rockrobo/state", """
157 "state":"returning",\
159 "fan_speed":"medium"\
164 assertState(component, Vacuum.STATE_CH_ID, new StringType(Vacuum.STATE_RETURNING));
165 assertState(component, Vacuum.FAN_SPEED_CH_ID, new StringType("medium"));
166 assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, new PercentType(80));
167 assertState(component, Vacuum.JSON_ATTRIBUTES_CH_ID, new StringType(jsonValue));
170 @SuppressWarnings("null")
172 public void testLegacySchema() {
174 var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC), """
177 "unique_id":"rockrobo_vacuum",\
179 "manufacturer":"Roborock",\
182 "identifiers":["rockrobo"],\
183 "sw_version":"0.9.9"\
185 "supported_features":["turn_on", "turn_off","pause","stop","return_home","battery","status",\
186 "locate","clean_spot","fan_speed","send_command"],\
187 "command_topic":"vacuum/command",\
188 "battery_level_topic":"vacuum/state",\
189 "battery_level_template":"{{ value_json.battery_level }}",\
190 "charging_topic":"vacuum/state",\
191 "charging_template":"{{ value_json.charging }}",\
192 "cleaning_topic":"vacuum/state",\
193 "cleaning_template":"{{ value_json.cleaning }}",\
194 "docked_topic":"vacuum/state",\
195 "docked_template":"{{ value_json.docked }}",\
196 "error_topic":"vacuum/state",\
197 "error_template":"{{ value_json.error }}",\
198 "fan_speed_topic":"vacuum/state",\
199 "set_fan_speed_topic":"vacuum/set_fan_speed",\
200 "fan_speed_template":"{{ value_json.fan_speed }}",\
201 "fan_speed_list":["min","medium","high","max"],\
202 "send_command_topic":"vacuum/send_command"\
207 assertThat(component.channels.size(), is(8)); // command, battery, charging, cleaning, docked, error,
208 // fan speed, send command
209 assertThat(component.getName(), is("Rockrobo"));
210 assertChannel(component, Vacuum.COMMAND_CH_ID, "", "vacuum/command", "Rockrobo", TextValue.class);
211 assertChannel(component, Vacuum.BATTERY_LEVEL_CH_ID, "vacuum/state", "", "Rockrobo", PercentageValue.class);
212 assertChannel(component, Vacuum.CHARGING_CH_ID, "vacuum/state", "", "Rockrobo", OnOffValue.class);
213 assertChannel(component, Vacuum.CLEANING_CH_ID, "vacuum/state", "", "Rockrobo", OnOffValue.class);
214 assertChannel(component, Vacuum.DOCKED_CH_ID, "vacuum/state", "", "Rockrobo", OnOffValue.class);
215 assertChannel(component, Vacuum.ERROR_CH_ID, "vacuum/state", "", "Rockrobo", TextValue.class);
216 assertChannel(component, Vacuum.FAN_SPEED_CH_ID, "vacuum/state", "vacuum/set_fan_speed", "Rockrobo",
218 assertChannel(component, Vacuum.CUSTOM_COMMAND_CH_ID, "", "vacuum/send_command", "Rockrobo", TextValue.class);
221 publishMessage("vacuum/state", """
223 "battery_level": 61,\
228 "error": "Error message"\
233 assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, new PercentType(61));
234 assertState(component, Vacuum.DOCKED_CH_ID, OnOffType.ON);
235 assertState(component, Vacuum.CLEANING_CH_ID, OnOffType.OFF);
236 assertState(component, Vacuum.CHARGING_CH_ID, OnOffType.ON);
237 assertState(component, Vacuum.FAN_SPEED_CH_ID, new StringType("off"));
238 assertState(component, Vacuum.ERROR_CH_ID, new StringType("Error message"));
240 component.getChannel(Vacuum.COMMAND_CH_ID).getState().publishValue(new StringType("turn_on"));
241 assertPublished("vacuum/command", "turn_on");
244 publishMessage("vacuum/state", """
246 "battery_level": 55,\
250 "fan_speed": "medium",\
256 assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, new PercentType(55));
257 assertState(component, Vacuum.DOCKED_CH_ID, OnOffType.OFF);
258 assertState(component, Vacuum.CLEANING_CH_ID, OnOffType.ON);
259 assertState(component, Vacuum.CHARGING_CH_ID, OnOffType.OFF);
260 assertState(component, Vacuum.FAN_SPEED_CH_ID, new StringType("medium"));
261 assertState(component, Vacuum.ERROR_CH_ID, new StringType(""));
263 component.getChannel(Vacuum.FAN_SPEED_CH_ID).getState().publishValue(new StringType("high"));
264 assertPublished("vacuum/set_fan_speed", "high");
266 component.getChannel(Vacuum.CUSTOM_COMMAND_CH_ID).getState().publishValue(new StringType("custom_command"));
267 assertPublished("vacuum/send_command", "custom_command");
271 protected Set<String> getConfigTopics() {
272 return Set.of(CONFIG_TOPIC);