[MQTT.Homeassistant] make the mqtt.vacuum implementation compilant with the specification (#11562)

Signed-off-by: Anton Kharuzhy <publicantroids@gmail.com>
This commit is contained in:
antroids
2021-11-20 12:44:09 +01:00
committed by GitHub
parent ec863117ea
commit 4a3a9d5873
2 changed files with 499 additions and 198 deletions

View File

@@ -0,0 +1,254 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.mqtt.homeassistant.internal.component;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import java.util.Set;
import org.junit.jupiter.api.Test;
import org.openhab.binding.mqtt.generic.values.OnOffValue;
import org.openhab.binding.mqtt.generic.values.PercentageValue;
import org.openhab.binding.mqtt.generic.values.TextValue;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.types.UnDefType;
/**
* Tests for {@link Vacuum}
*
* @author Anton Kharuzhy - Initial contribution
*/
@SuppressWarnings("ConstantConditions")
public class VacuumTests extends AbstractComponentTests {
public static final String CONFIG_TOPIC = "vacuum/rockrobo_vacuum";
@Test
public void testRoborockValetudo() {
// @formatter:off
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC), "{" +
"\"name\":\"Rockrobo\"," +
"\"unique_id\":\"rockrobo_vacuum\"," +
"\"schema\":\"state\"," +
"\"device\":{" +
" \"manufacturer\":\"Roborock\"," +
" \"model\":\"v1\"," +
" \"name\":\"rockrobo\"," +
" \"identifiers\":[\"rockrobo\"]," +
" \"sw_version\":\"0.9.9\"" +
"}," +
"\"supported_features\":[\"start\",\"pause\",\"stop\",\"return_home\",\"battery\",\"status\"," +
" \"locate\",\"clean_spot\",\"fan_speed\",\"send_command\"]," +
"\"command_topic\":\"valetudo/rockrobo/command\"," +
"\"state_topic\":\"valetudo/rockrobo/state\"," +
"\"set_fan_speed_topic\":\"valetudo/rockrobo/set_fan_speed\"," +
"\"fan_speed_list\":[\"min\",\"medium\",\"high\",\"max\",\"mop\"]," +
"\"send_command_topic\":\"valetudo/rockrobo/custom_command\"," +
"\"json_attributes_topic\":\"valetudo/rockrobo/attributes\"" +
"}");
// @formatter:on
assertThat(component.channels.size(), is(6)); // command, state, fan speed, send command, battery, json attrs
assertThat(component.getName(), is("Rockrobo"));
assertChannel(component, Vacuum.COMMAND_CH_ID, "", "valetudo/rockrobo/command", "Rockrobo", TextValue.class);
assertChannel(component, Vacuum.STATE_CH_ID, "valetudo/rockrobo/state", "", "Rockrobo", TextValue.class);
assertChannel(component, Vacuum.FAN_SPEED_CH_ID, "valetudo/rockrobo/state", "valetudo/rockrobo/set_fan_speed",
"Rockrobo", TextValue.class);
assertChannel(component, Vacuum.CUSTOM_COMMAND_CH_ID, "", "valetudo/rockrobo/custom_command", "Rockrobo",
TextValue.class);
assertChannel(component, Vacuum.BATTERY_LEVEL_CH_ID, "valetudo/rockrobo/state", "", "Rockrobo",
PercentageValue.class);
assertChannel(component, Vacuum.JSON_ATTRIBUTES_CH_ID, "valetudo/rockrobo/attributes", "", "Rockrobo",
TextValue.class);
assertState(component, Vacuum.STATE_CH_ID, UnDefType.UNDEF);
assertState(component, Vacuum.FAN_SPEED_CH_ID, UnDefType.UNDEF);
assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, UnDefType.UNDEF);
assertState(component, Vacuum.JSON_ATTRIBUTES_CH_ID, UnDefType.UNDEF);
// @formatter:off
String jsonValue;
publishMessage("valetudo/rockrobo/attributes", jsonValue = "{" +
"\"mainBrush\":\"245.1\"," +
"\"sideBrush\":\"145.1\"," +
"\"filter\":\"95.1\"," +
"\"sensor\":\"0.0\"," +
"\"currentCleanTime\":\"52.0\"," +
"\"currentCleanArea\":\"46.7\"," +
"\"cleanTime\":\"54.9\"," +
"\"cleanArea\":\"3280.9\"," +
"\"cleanCount\":84," +
"\"last_run_stats\":{" +
" \"startTime\":1633257319000," +
" \"endTime\":1633260439000," +
" \"duration\":3120," +
" \"area\":\"46.7\"," +
" \"errorCode\":0," +
" \"errorDescription\":\"No error\"," +
" \"finishedFlag\":true" +
"}," +
"\"last_bin_out\":2147483647000," +
"\"state\":\"docked\"," +
"\"valetudo_state\":{" +
" \"id\":8," +
" \"name\":\"Charging\"" +
"}," +
"\"last_bin_full\":0" +
"}");
// @formatter:on
// @formatter:off
publishMessage("valetudo/rockrobo/state", "{" +
"\"state\":\"docked\"," +
"\"battery_level\":100," +
"\"fan_speed\":\"max\"" +
"}");
// @formatter:on
assertState(component, Vacuum.STATE_CH_ID, new StringType(Vacuum.STATE_DOCKED));
assertState(component, Vacuum.FAN_SPEED_CH_ID, new StringType("max"));
assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, new PercentType(100));
assertState(component, Vacuum.JSON_ATTRIBUTES_CH_ID, new StringType(jsonValue));
component.getChannel(Vacuum.COMMAND_CH_ID).getState().publishValue(new StringType("start"));
assertPublished("valetudo/rockrobo/command", "start");
// @formatter:off
publishMessage("valetudo/rockrobo/state", "{" +
"\"state\":\"cleaning\"," +
"\"battery_level\":99," +
"\"fan_speed\":\"max\"" +
"}");
// @formatter:on
assertState(component, Vacuum.STATE_CH_ID, new StringType(Vacuum.STATE_CLEANING));
assertState(component, Vacuum.FAN_SPEED_CH_ID, new StringType("max"));
assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, new PercentType(99));
assertState(component, Vacuum.JSON_ATTRIBUTES_CH_ID, new StringType(jsonValue));
component.getChannel(Vacuum.FAN_SPEED_CH_ID).getState().publishValue(new StringType("medium"));
assertPublished("valetudo/rockrobo/set_fan_speed", "medium");
// @formatter:off
publishMessage("valetudo/rockrobo/state", "{" +
"\"state\":\"returning\"," +
"\"battery_level\":80," +
"\"fan_speed\":\"medium\"" +
"}");
// @formatter:on
assertState(component, Vacuum.STATE_CH_ID, new StringType(Vacuum.STATE_RETURNING));
assertState(component, Vacuum.FAN_SPEED_CH_ID, new StringType("medium"));
assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, new PercentType(80));
assertState(component, Vacuum.JSON_ATTRIBUTES_CH_ID, new StringType(jsonValue));
}
@Test
public void testLegacySchema() {
// @formatter:off
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC), "{" +
"\"name\":\"Rockrobo\"," +
"\"unique_id\":\"rockrobo_vacuum\"," +
"\"device\":{" +
" \"manufacturer\":\"Roborock\"," +
" \"model\":\"v1\"," +
" \"name\":\"rockrobo\"," +
" \"identifiers\":[\"rockrobo\"]," +
" \"sw_version\":\"0.9.9\"" +
"}," +
"\"supported_features\":[\"turn_on\", \"turn_off\",\"pause\",\"stop\",\"return_home\",\"battery\",\"status\"," +
" \"locate\",\"clean_spot\",\"fan_speed\",\"send_command\"]," +
"\"command_topic\":\"vacuum/command\"," +
"\"battery_level_topic\":\"vacuum/state\"," +
"\"battery_level_template\":\"{{ value_json.battery_level }}\"," +
"\"charging_topic\":\"vacuum/state\"," +
"\"charging_template\":\"{{ value_json.charging }}\"," +
"\"cleaning_topic\":\"vacuum/state\"," +
"\"cleaning_template\":\"{{ value_json.cleaning }}\"," +
"\"docked_topic\":\"vacuum/state\"," +
"\"docked_template\":\"{{ value_json.docked }}\"," +
"\"error_topic\":\"vacuum/state\"," +
"\"error_template\":\"{{ value_json.error }}\"," +
"\"fan_speed_topic\":\"vacuum/state\"," +
"\"set_fan_speed_topic\":\"vacuum/set_fan_speed\"," +
"\"fan_speed_template\":\"{{ value_json.fan_speed }}\"," +
"\"fan_speed_list\":[\"min\",\"medium\",\"high\",\"max\"]," +
"\"send_command_topic\":\"vacuum/send_command\"" +
"}");
// @formatter:on
assertThat(component.channels.size(), is(8)); // command, battery, charging, cleaning, docked, error,
// fan speed, send command
assertThat(component.getName(), is("Rockrobo"));
assertChannel(component, Vacuum.COMMAND_CH_ID, "", "vacuum/command", "Rockrobo", TextValue.class);
assertChannel(component, Vacuum.BATTERY_LEVEL_CH_ID, "vacuum/state", "", "Rockrobo", PercentageValue.class);
assertChannel(component, Vacuum.CHARGING_CH_ID, "vacuum/state", "", "Rockrobo", OnOffValue.class);
assertChannel(component, Vacuum.CLEANING_CH_ID, "vacuum/state", "", "Rockrobo", OnOffValue.class);
assertChannel(component, Vacuum.DOCKED_CH_ID, "vacuum/state", "", "Rockrobo", OnOffValue.class);
assertChannel(component, Vacuum.ERROR_CH_ID, "vacuum/state", "", "Rockrobo", TextValue.class);
assertChannel(component, Vacuum.FAN_SPEED_CH_ID, "vacuum/state", "vacuum/set_fan_speed", "Rockrobo",
TextValue.class);
assertChannel(component, Vacuum.CUSTOM_COMMAND_CH_ID, "", "vacuum/send_command", "Rockrobo", TextValue.class);
// @formatter:off
publishMessage("vacuum/state", "{" +
"\"battery_level\": 61," +
"\"docked\": true," +
"\"cleaning\": false," +
"\"charging\": true," +
"\"fan_speed\": \"off\"," +
"\"error\": \"Error message\"" +
"}");
// @formatter:on
assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, new PercentType(61));
assertState(component, Vacuum.DOCKED_CH_ID, OnOffType.ON);
assertState(component, Vacuum.CLEANING_CH_ID, OnOffType.OFF);
assertState(component, Vacuum.CHARGING_CH_ID, OnOffType.ON);
assertState(component, Vacuum.FAN_SPEED_CH_ID, new StringType("off"));
assertState(component, Vacuum.ERROR_CH_ID, new StringType("Error message"));
component.getChannel(Vacuum.COMMAND_CH_ID).getState().publishValue(new StringType("turn_on"));
assertPublished("vacuum/command", "turn_on");
// @formatter:off
publishMessage("vacuum/state", "{" +
"\"battery_level\": 55," +
"\"docked\": false," +
"\"cleaning\": true," +
"\"charging\": false," +
"\"fan_speed\": \"medium\"," +
"\"error\": \"\"" +
"}");
// @formatter:on
assertState(component, Vacuum.BATTERY_LEVEL_CH_ID, new PercentType(55));
assertState(component, Vacuum.DOCKED_CH_ID, OnOffType.OFF);
assertState(component, Vacuum.CLEANING_CH_ID, OnOffType.ON);
assertState(component, Vacuum.CHARGING_CH_ID, OnOffType.OFF);
assertState(component, Vacuum.FAN_SPEED_CH_ID, new StringType("medium"));
assertState(component, Vacuum.ERROR_CH_ID, new StringType(""));
component.getChannel(Vacuum.FAN_SPEED_CH_ID).getState().publishValue(new StringType("high"));
assertPublished("vacuum/set_fan_speed", "high");
component.getChannel(Vacuum.CUSTOM_COMMAND_CH_ID).getState().publishValue(new StringType("custom_command"));
assertPublished("vacuum/send_command", "custom_command");
}
protected Set<String> getConfigTopics() {
return Set.of(CONFIG_TOPIC);
}
}