]> git.basschouten.com Git - openhab-addons.git/blob
7cb7add9f2c3dd5e711cbe6b453123a14b53abd6
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.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;
29
30 /**
31  * Tests for {@link Vacuum}
32  *
33  * @author Anton Kharuzhy - Initial contribution
34  */
35 @NonNullByDefault
36 public class VacuumTests extends AbstractComponentTests {
37     public static final String CONFIG_TOPIC = "vacuum/rockrobo_vacuum";
38
39     @SuppressWarnings("null")
40     @Test
41     public void testRoborockValetudo() {
42         // @formatter:off
43         var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC), """
44                 {\
45                 "name":"Rockrobo",\
46                 "unique_id":"rockrobo_vacuum",\
47                 "schema":"state",\
48                 "device":{\
49                    "manufacturer":"Roborock",\
50                    "model":"v1",\
51                    "name":"rockrobo",\
52                    "identifiers":["rockrobo"],\
53                    "sw_version":"0.9.9"\
54                 },\
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"\
63                 }\
64                 """);
65         // @formatter:on
66
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",
74                 TextValue.class);
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",
78                 TextValue.class);
79
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);
84
85         // @formatter:off
86         String jsonValue;
87         publishMessage("valetudo/rockrobo/attributes", jsonValue = """
88                 {\
89                 "mainBrush":"245.1",\
90                 "sideBrush":"145.1",\
91                 "filter":"95.1",\
92                 "sensor":"0.0",\
93                 "currentCleanTime":"52.0",\
94                 "currentCleanArea":"46.7",\
95                 "cleanTime":"54.9",\
96                 "cleanArea":"3280.9",\
97                 "cleanCount":84,\
98                 "last_run_stats":{\
99                    "startTime":1633257319000,\
100                    "endTime":1633260439000,\
101                    "duration":3120,\
102                    "area":"46.7",\
103                    "errorCode":0,\
104                    "errorDescription":"No error",\
105                    "finishedFlag":true\
106                 },\
107                 "last_bin_out":2147483647000,\
108                 "state":"docked",\
109                 "valetudo_state":{\
110                    "id":8,\
111                    "name":"Charging"\
112                 },\
113                 "last_bin_full":0\
114                 }\
115                 """);
116         // @formatter:on
117
118         // @formatter:off
119         publishMessage("valetudo/rockrobo/state", """
120                 {\
121                 "state":"docked",\
122                 "battery_level":100,\
123                 "fan_speed":"max"\
124                 }\
125                 """);
126         // @formatter:on
127
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));
132
133         component.getChannel(Vacuum.COMMAND_CH_ID).getState().publishValue(new StringType("start"));
134         assertPublished("valetudo/rockrobo/command", "start");
135
136         // @formatter:off
137         publishMessage("valetudo/rockrobo/state", """
138                 {\
139                 "state":"cleaning",\
140                 "battery_level":99,\
141                 "fan_speed":"max"\
142                 }\
143                 """);
144         // @formatter:on
145
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));
150
151         component.getChannel(Vacuum.FAN_SPEED_CH_ID).getState().publishValue(new StringType("medium"));
152         assertPublished("valetudo/rockrobo/set_fan_speed", "medium");
153
154         // @formatter:off
155         publishMessage("valetudo/rockrobo/state", """
156                 {\
157                 "state":"returning",\
158                 "battery_level":80,\
159                 "fan_speed":"medium"\
160                 }\
161                 """);
162         // @formatter:on
163
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));
168     }
169
170     @SuppressWarnings("null")
171     @Test
172     public void testLegacySchema() {
173         // @formatter:off
174         var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC), """
175                 {\
176                 "name":"Rockrobo",\
177                 "unique_id":"rockrobo_vacuum",\
178                 "device":{\
179                    "manufacturer":"Roborock",\
180                    "model":"v1",\
181                    "name":"rockrobo",\
182                    "identifiers":["rockrobo"],\
183                    "sw_version":"0.9.9"\
184                 },\
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"\
203                 }\
204                 """);
205         // @formatter:on
206
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",
217                 TextValue.class);
218         assertChannel(component, Vacuum.CUSTOM_COMMAND_CH_ID, "", "vacuum/send_command", "Rockrobo", TextValue.class);
219
220         // @formatter:off
221         publishMessage("vacuum/state", """
222                 {\
223                 "battery_level": 61,\
224                 "docked": true,\
225                 "cleaning": false,\
226                 "charging": true,\
227                 "fan_speed": "off",\
228                 "error": "Error message"\
229                 }\
230                 """);
231         // @formatter:on
232
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"));
239
240         component.getChannel(Vacuum.COMMAND_CH_ID).getState().publishValue(new StringType("turn_on"));
241         assertPublished("vacuum/command", "turn_on");
242
243         // @formatter:off
244         publishMessage("vacuum/state", """
245                 {\
246                 "battery_level": 55,\
247                 "docked": false,\
248                 "cleaning": true,\
249                 "charging": false,\
250                 "fan_speed": "medium",\
251                 "error": ""\
252                 }\
253                 """);
254         // @formatter:on
255
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(""));
262
263         component.getChannel(Vacuum.FAN_SPEED_CH_ID).getState().publishValue(new StringType("high"));
264         assertPublished("vacuum/set_fan_speed", "high");
265
266         component.getChannel(Vacuum.CUSTOM_COMMAND_CH_ID).getState().publishValue(new StringType("custom_command"));
267         assertPublished("vacuum/send_command", "custom_command");
268     }
269
270     @Override
271     protected Set<String> getConfigTopics() {
272         return Set.of(CONFIG_TOPIC);
273     }
274 }