Java 17 features (H-M) (#15520)

- add missing @override
- Java style array syntax
- remove redundant modifiers
- always move String constants to left side in comparisons
- simplify lambda expressions and return statements
- use replace instead of replaceAll w/o regex
- instanceof matching and multiline strings
- remove null check before instanceof

Signed-off-by: Holger Friedrich <mail@holger-friedrich.de>
This commit is contained in:
Holger Friedrich
2023-09-08 14:36:59 +02:00
committed by GitHub
parent 3751fd0646
commit edaf17b345
519 changed files with 2703 additions and 2660 deletions

View File

@@ -53,10 +53,10 @@ abstract class AbstractRawSchemaLight extends Light {
if (newState.getBrightness().equals(PercentType.ZERO)) {
newState = new HSBType(newState.getHue(), newState.getSaturation(), PercentType.HUNDRED);
}
} else if (command instanceof HSBType) {
newState = (HSBType) command;
} else if (command instanceof PercentType) {
newState = new HSBType(newState.getHue(), newState.getSaturation(), (PercentType) command);
} else if (command instanceof HSBType hsb) {
newState = hsb;
} else if (command instanceof PercentType brightness) {
newState = new HSBType(newState.getHue(), newState.getSaturation(), brightness);
} else {
return false;
}

View File

@@ -58,7 +58,7 @@ public class Climate extends AbstractComponent<Climate.ChannelConfiguration> {
public static final String TEMPERATURE_LOW_CH_ID = "temperatureLow";
public static final String POWER_CH_ID = "power";
public static enum TemperatureUnit {
public enum TemperatureUnit {
@SerializedName("C")
CELSIUS(SIUnits.CELSIUS, new BigDecimal("0.1")),
@SerializedName("F")

View File

@@ -224,8 +224,7 @@ public class DefaultSchemaLight extends Light {
private boolean handleColorCommand(Command command) {
if (!handleOnOffCommand(command)) {
return false;
} else if (command instanceof HSBType) {
HSBType color = (HSBType) command;
} else if (command instanceof HSBType color) {
if (channelConfiguration.hsCommandTopic != null) {
// If we don't have a brightness channel, something is probably busted
// but don't choke
@@ -250,7 +249,7 @@ public class DefaultSchemaLight extends Light {
String xyString = String.format("%f,%f", xy[0].doubleValue(), xy[1].doubleValue());
xyChannel.getState().publishValue(new StringType(xyString));
}
} else if (command instanceof PercentType) {
} else if (command instanceof PercentType brightness) {
if (channelConfiguration.brightnessCommandTopic != null) {
brightnessChannel.getState().publishValue(command);
} else {
@@ -261,8 +260,7 @@ public class DefaultSchemaLight extends Light {
color = HSBType.WHITE;
}
HSBType existingColor = (HSBType) color;
HSBType newCommand = new HSBType(existingColor.getHue(), existingColor.getSaturation(),
(PercentType) command);
HSBType newCommand = new HSBType(existingColor.getHue(), existingColor.getSaturation(), brightness);
// re-process
handleColorCommand(newCommand);
}

View File

@@ -47,7 +47,7 @@ public class DeviceTrigger extends AbstractComponent<DeviceTrigger.ChannelConfig
public DeviceTrigger(ComponentFactory.ComponentConfiguration componentConfiguration) {
super(componentConfiguration, ChannelConfiguration.class);
if (!channelConfiguration.automationType.equals("trigger")) {
if (!"trigger".equals(channelConfiguration.automationType)) {
throw new ConfigurationException("Component:DeviceTrigger must have automation_type 'trigger'");
}
if (channelConfiguration.type.isBlank()) {

View File

@@ -137,6 +137,7 @@ public class JSONSchemaLight extends AbstractRawSchemaLight {
rawChannel.getState().publishValue(new StringType(command));
}
@Override
protected boolean handleCommand(Command command) {
JSONState json = new JSONState();
if (command.getClass().equals(OnOffType.class)) {

View File

@@ -103,8 +103,7 @@ public class ChannelConfigurationTypeAdapterFactory implements TypeAdapterFactor
@Override
public @Nullable T read(JsonReader in) throws IOException {
/* read the object using the default adapter, but translate the names in the reader */
T result = delegate.read(MappingJsonReader.getDeviceMapper(in));
return result;
return delegate.read(MappingJsonReader.getDeviceMapper(in));
}
@Override

View File

@@ -43,9 +43,11 @@ public class ConnectionDeserializer implements JsonDeserializer<Connection> {
try {
list = json.getAsJsonArray();
} catch (IllegalStateException e) {
throw new JsonParseException("Cannot parse JSON array. Each connection must be defined as array with two "
+ "elements: connection_type, connection identifier. For example: \"connections\": [[\"mac\", "
+ "\"02:5b:26:a8:dc:12\"]]", e);
throw new JsonParseException("""
Cannot parse JSON array. Each connection must be defined as array with two \
elements: connection_type, connection identifier. For example: "connections": [["mac", \
"02:5b:26:a8:dc:12"]]\
""", e);
}
if (list.size() != 2) {
throw new JsonParseException("Connection information must be a tuple, but has " + list.size()

View File

@@ -14,7 +14,6 @@ package org.openhab.binding.mqtt.homeassistant.internal.config;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -63,7 +62,7 @@ public class ListOrStringDeserializer extends TypeAdapter<List<String>> {
in.nextNull();
return null;
case STRING:
return Collections.singletonList(in.nextString());
return List.of(in.nextString());
case BEGIN_ARRAY:
return readList(in);
default:

View File

@@ -17,7 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsIterableContaining.hasItem;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test;
@@ -45,8 +45,7 @@ public class HaIDTests {
assertThat(restore, is(subject));
HandlerConfiguration haConfig = new HandlerConfiguration(subject.baseTopic,
Collections.singletonList(subject.toShortTopic()));
HandlerConfiguration haConfig = new HandlerConfiguration(subject.baseTopic, List.of(subject.toShortTopic()));
Collection<HaID> restoreList = HaID.fromConfig(haConfig);
assertThat(restoreList, hasItem(new HaID("homeassistant/switch/name/config")));
@@ -68,8 +67,7 @@ public class HaIDTests {
assertThat(restore, is(subject));
HandlerConfiguration haConfig = new HandlerConfiguration(subject.baseTopic,
Collections.singletonList(subject.toShortTopic()));
HandlerConfiguration haConfig = new HandlerConfiguration(subject.baseTopic, List.of(subject.toShortTopic()));
Collection<HaID> restoreList = HaID.fromConfig(haConfig);
assertThat(restoreList, hasItem(new HaID("homeassistant/switch/node/name/config")));

View File

@@ -36,31 +36,33 @@ public class AlarmControlPanelTests extends AbstractComponentTests {
public void testAlarmControlPanel() {
// @formatter:off
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"availability\": [ " +
" { " +
" \"topic\": \"zigbee2mqtt/bridge/state\" " +
" } " +
" ], " +
" \"code\": \"12345\", " +
" \"command_topic\": \"zigbee2mqtt/alarm/set/state\", " +
" \"device\": { " +
" \"identifiers\": [ " +
" \"zigbee2mqtt_0x0000000000000000\" " +
" ], " +
" \"manufacturer\": \"BestAlarmEver\", " +
" \"model\": \"Heavy duty super duper alarm\", " +
" \"name\": \"Alarm\", " +
" \"sw_version\": \"Zigbee2MQTT 1.18.2\" " +
" }, " +
" \"name\": \"alarm\", " +
" \"payload_arm_away\": \"ARM_AWAY_\", " +
" \"payload_arm_home\": \"ARM_HOME_\", " +
" \"payload_arm_night\": \"ARM_NIGHT_\", " +
" \"payload_arm_custom_bypass\": \"ARM_CUSTOM_BYPASS_\", " +
" \"payload_disarm\": \"DISARM_\", " +
" \"state_topic\": \"zigbee2mqtt/alarm/state\" " +
"} ");
"""
{ \
"availability": [ \
{ \
"topic": "zigbee2mqtt/bridge/state" \
} \
], \
"code": "12345", \
"command_topic": "zigbee2mqtt/alarm/set/state", \
"device": { \
"identifiers": [ \
"zigbee2mqtt_0x0000000000000000" \
], \
"manufacturer": "BestAlarmEver", \
"model": "Heavy duty super duper alarm", \
"name": "Alarm", \
"sw_version": "Zigbee2MQTT 1.18.2" \
}, \
"name": "alarm", \
"payload_arm_away": "ARM_AWAY_", \
"payload_arm_home": "ARM_HOME_", \
"payload_arm_night": "ARM_NIGHT_", \
"payload_arm_custom_bypass": "ARM_CUSTOM_BYPASS_", \
"payload_disarm": "DISARM_", \
"state_topic": "zigbee2mqtt/alarm/state" \
} \
""");
// @formatter:on
assertThat(component.channels.size(), is(4));

View File

@@ -36,29 +36,31 @@ public class BinarySensorTests extends AbstractComponentTests {
public void test() throws InterruptedException {
// @formatter:off
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"availability\": [ " +
" { " +
" \"topic\": \"zigbee2mqtt/bridge/state\" " +
" } " +
" ], " +
" \"device\": { " +
" \"identifiers\": [ " +
" \"zigbee2mqtt_0x0000000000000000\" " +
" ], " +
" \"manufacturer\": \"Sensors inc\", " +
" \"model\": \"On Off Sensor\", " +
" \"name\": \"OnOffSensor\", " +
" \"sw_version\": \"Zigbee2MQTT 1.18.2\" " +
" }, " +
" \"name\": \"onoffsensor\", " +
" \"force_update\": \"true\", " +
" \"payload_off\": \"OFF_\", " +
" \"payload_on\": \"ON_\", " +
" \"state_topic\": \"zigbee2mqtt/sensor/state\", " +
" \"unique_id\": \"sn1\", " +
" \"value_template\": \"{{ value_json.state }}\" " +
"}");
"""
{ \
"availability": [ \
{ \
"topic": "zigbee2mqtt/bridge/state" \
} \
], \
"device": { \
"identifiers": [ \
"zigbee2mqtt_0x0000000000000000" \
], \
"manufacturer": "Sensors inc", \
"model": "On Off Sensor", \
"name": "OnOffSensor", \
"sw_version": "Zigbee2MQTT 1.18.2" \
}, \
"name": "onoffsensor", \
"force_update": "true", \
"payload_off": "OFF_", \
"payload_on": "ON_", \
"state_topic": "zigbee2mqtt/sensor/state", \
"unique_id": "sn1", \
"value_template": "{{ value_json.state }}" \
}\
""");
// @formatter:on
assertThat(component.channels.size(), is(1));
@@ -82,30 +84,32 @@ public class BinarySensorTests extends AbstractComponentTests {
public void offDelayTest() {
// @formatter:off
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"availability\": [ " +
" { " +
" \"topic\": \"zigbee2mqtt/bridge/state\" " +
" } " +
" ], " +
" \"device\": { " +
" \"identifiers\": [ " +
" \"zigbee2mqtt_0x0000000000000000\" " +
" ], " +
" \"manufacturer\": \"Sensors inc\", " +
" \"model\": \"On Off Sensor\", " +
" \"name\": \"OnOffSensor\", " +
" \"sw_version\": \"Zigbee2MQTT 1.18.2\" " +
" }, " +
" \"name\": \"onoffsensor\", " +
" \"force_update\": \"true\", " +
" \"off_delay\": \"1\", " +
" \"payload_off\": \"OFF_\", " +
" \"payload_on\": \"ON_\", " +
" \"state_topic\": \"zigbee2mqtt/sensor/state\", " +
" \"unique_id\": \"sn1\", " +
" \"value_template\": \"{{ value_json.state }}\" " +
"}");
"""
{ \
"availability": [ \
{ \
"topic": "zigbee2mqtt/bridge/state" \
} \
], \
"device": { \
"identifiers": [ \
"zigbee2mqtt_0x0000000000000000" \
], \
"manufacturer": "Sensors inc", \
"model": "On Off Sensor", \
"name": "OnOffSensor", \
"sw_version": "Zigbee2MQTT 1.18.2" \
}, \
"name": "onoffsensor", \
"force_update": "true", \
"off_delay": "1", \
"payload_off": "OFF_", \
"payload_on": "ON_", \
"state_topic": "zigbee2mqtt/sensor/state", \
"unique_id": "sn1", \
"value_template": "{{ value_json.state }}" \
}\
""");
// @formatter:on
publishMessage("zigbee2mqtt/sensor/state", "{ \"state\": \"ON_\" }");
@@ -118,30 +122,32 @@ public class BinarySensorTests extends AbstractComponentTests {
public void expireAfterTest() {
// @formatter:off
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"availability\": [ " +
" { " +
" \"topic\": \"zigbee2mqtt/bridge/state\" " +
" } " +
" ], " +
" \"device\": { " +
" \"identifiers\": [ " +
" \"zigbee2mqtt_0x0000000000000000\" " +
" ], " +
" \"manufacturer\": \"Sensors inc\", " +
" \"model\": \"On Off Sensor\", " +
" \"name\": \"OnOffSensor\", " +
" \"sw_version\": \"Zigbee2MQTT 1.18.2\" " +
" }, " +
" \"name\": \"onoffsensor\", " +
" \"expire_after\": \"1\", " +
" \"force_update\": \"true\", " +
" \"payload_off\": \"OFF_\", " +
" \"payload_on\": \"ON_\", " +
" \"state_topic\": \"zigbee2mqtt/sensor/state\", " +
" \"unique_id\": \"sn1\", " +
" \"value_template\": \"{{ value_json.state }}\" " +
"}");
"""
{ \
"availability": [ \
{ \
"topic": "zigbee2mqtt/bridge/state" \
} \
], \
"device": { \
"identifiers": [ \
"zigbee2mqtt_0x0000000000000000" \
], \
"manufacturer": "Sensors inc", \
"model": "On Off Sensor", \
"name": "OnOffSensor", \
"sw_version": "Zigbee2MQTT 1.18.2" \
}, \
"name": "onoffsensor", \
"expire_after": "1", \
"force_update": "true", \
"payload_off": "OFF_", \
"payload_on": "ON_", \
"state_topic": "zigbee2mqtt/sensor/state", \
"unique_id": "sn1", \
"value_template": "{{ value_json.state }}" \
}\
""");
// @formatter:on
publishMessage("zigbee2mqtt/sensor/state", "{ \"state\": \"OFF_\" }");

View File

@@ -35,24 +35,26 @@ public class CameraTests extends AbstractComponentTests {
public void test() throws InterruptedException {
// @formatter:off
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"availability\": [ " +
" { " +
" \"topic\": \"zigbee2mqtt/bridge/state\" " +
" } " +
" ], " +
" \"device\": { " +
" \"identifiers\": [ " +
" \"zigbee2mqtt_0x0000000000000000\" " +
" ], " +
" \"manufacturer\": \"Cameras inc\", " +
" \"model\": \"Camera\", " +
" \"name\": \"camera\", " +
" \"sw_version\": \"Zigbee2MQTT 1.18.2\" " +
" }, " +
" \"name\": \"cam1\", " +
" \"topic\": \"zigbee2mqtt/cam1/state\"" +
"}");
"""
{ \
"availability": [ \
{ \
"topic": "zigbee2mqtt/bridge/state" \
} \
], \
"device": { \
"identifiers": [ \
"zigbee2mqtt_0x0000000000000000" \
], \
"manufacturer": "Cameras inc", \
"model": "Camera", \
"name": "camera", \
"sw_version": "Zigbee2MQTT 1.18.2" \
}, \
"name": "cam1", \
"topic": "zigbee2mqtt/cam1/state"\
}\
""");
// @formatter:on
assertThat(component.channels.size(), is(1));

View File

@@ -41,31 +41,34 @@ public class ClimateTests extends AbstractComponentTests {
@SuppressWarnings("null")
@Test
public void testTS0601Climate() {
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC), "{"
+ " \"action_template\": \"{% set values = {'idle':'off','heat':'heating','cool':'cooling','fan only':'fan'} %}{{ values[value_json.running_state] }}\","
+ " \"action_topic\": \"zigbee2mqtt/th1\", \"availability\": [ {"
+ " \"topic\": \"zigbee2mqtt/bridge/state\" } ],"
+ " \"away_mode_command_topic\": \"zigbee2mqtt/th1/set/away_mode\","
+ " \"away_mode_state_template\": \"{{ value_json.away_mode }}\","
+ " \"away_mode_state_topic\": \"zigbee2mqtt/th1\","
+ " \"current_temperature_template\": \"{{ value_json.local_temperature }}\","
+ " \"current_temperature_topic\": \"zigbee2mqtt/th1\", \"device\": {"
+ " \"identifiers\": [ \"zigbee2mqtt_0x847127fffe11dd6a\" ], \"manufacturer\": \"TuYa\","
+ " \"model\": \"Radiator valve with thermostat (TS0601_thermostat)\","
+ " \"name\": \"th1\", \"sw_version\": \"Zigbee2MQTT 1.18.2\" },"
+ " \"hold_command_topic\": \"zigbee2mqtt/th1/set/preset\", \"hold_modes\": ["
+ " \"schedule\", \"manual\", \"boost\", \"complex\", \"comfort\", \"eco\" ],"
+ " \"hold_state_template\": \"{{ value_json.preset }}\","
+ " \"hold_state_topic\": \"zigbee2mqtt/th1\","
+ " \"json_attributes_topic\": \"zigbee2mqtt/th1\", \"max_temp\": \"35\","
+ " \"min_temp\": \"5\", \"mode_command_topic\": \"zigbee2mqtt/th1/set/system_mode\","
+ " \"mode_state_template\": \"{{ value_json.system_mode }}\","
+ " \"mode_state_topic\": \"zigbee2mqtt/th1\", \"modes\": [ \"heat\","
+ " \"auto\", \"off\" ], \"name\": \"th1\", \"temp_step\": 0.5,"
+ " \"temperature_command_topic\": \"zigbee2mqtt/th1/set/current_heating_setpoint\","
+ " \"temperature_state_template\": \"{{ value_json.current_heating_setpoint }}\","
+ " \"temperature_state_topic\": \"zigbee2mqtt/th1\", \"temperature_unit\": \"C\","
+ " \"unique_id\": \"0x847127fffe11dd6a_climate_zigbee2mqtt\"}");
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"""
{\
"action_template": "{% set values = {'idle':'off','heat':'heating','cool':'cooling','fan only':'fan'} %}{{ values[value_json.running_state] }}",\
"action_topic": "zigbee2mqtt/th1", "availability": [ {\
"topic": "zigbee2mqtt/bridge/state" } ],\
"away_mode_command_topic": "zigbee2mqtt/th1/set/away_mode",\
"away_mode_state_template": "{{ value_json.away_mode }}",\
"away_mode_state_topic": "zigbee2mqtt/th1",\
"current_temperature_template": "{{ value_json.local_temperature }}",\
"current_temperature_topic": "zigbee2mqtt/th1", "device": {\
"identifiers": [ "zigbee2mqtt_0x847127fffe11dd6a" ], "manufacturer": "TuYa",\
"model": "Radiator valve with thermostat (TS0601_thermostat)",\
"name": "th1", "sw_version": "Zigbee2MQTT 1.18.2" },\
"hold_command_topic": "zigbee2mqtt/th1/set/preset", "hold_modes": [\
"schedule", "manual", "boost", "complex", "comfort", "eco" ],\
"hold_state_template": "{{ value_json.preset }}",\
"hold_state_topic": "zigbee2mqtt/th1",\
"json_attributes_topic": "zigbee2mqtt/th1", "max_temp": "35",\
"min_temp": "5", "mode_command_topic": "zigbee2mqtt/th1/set/system_mode",\
"mode_state_template": "{{ value_json.system_mode }}",\
"mode_state_topic": "zigbee2mqtt/th1", "modes": [ "heat",\
"auto", "off" ], "name": "th1", "temp_step": 0.5,\
"temperature_command_topic": "zigbee2mqtt/th1/set/current_heating_setpoint",\
"temperature_state_template": "{{ value_json.current_heating_setpoint }}",\
"temperature_state_topic": "zigbee2mqtt/th1", "temperature_unit": "C",\
"unique_id": "0x847127fffe11dd6a_climate_zigbee2mqtt"}\
""");
assertThat(component.channels.size(), is(6));
assertThat(component.getName(), is("th1"));
@@ -81,10 +84,11 @@ public class ClimateTests extends AbstractComponentTests {
assertChannel(component, Climate.TEMPERATURE_CH_ID, "zigbee2mqtt/th1",
"zigbee2mqtt/th1/set/current_heating_setpoint", "th1", NumberValue.class);
publishMessage("zigbee2mqtt/th1",
"{\"running_state\": \"idle\", \"away_mode\": \"ON\", "
+ "\"local_temperature\": \"22.2\", \"preset\": \"schedule\", \"system_mode\": \"heat\", "
+ "\"current_heating_setpoint\": \"24\"}");
publishMessage("zigbee2mqtt/th1", """
{"running_state": "idle", "away_mode": "ON", \
"local_temperature": "22.2", "preset": "schedule", "system_mode": "heat", \
"current_heating_setpoint": "24"}\
""");
assertState(component, Climate.ACTION_CH_ID, new StringType("off"));
assertState(component, Climate.AWAY_MODE_CH_ID, OnOffType.ON);
assertState(component, Climate.CURRENT_TEMPERATURE_CH_ID, new QuantityType<>(22.2, SIUnits.CELSIUS));
@@ -105,32 +109,35 @@ public class ClimateTests extends AbstractComponentTests {
@SuppressWarnings("null")
@Test
public void testTS0601ClimateNotSendIfOff() {
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC), "{"
+ " \"action_template\": \"{% set values = {'idle':'off','heat':'heating','cool':'cooling','fan only':'fan'} %}{{ values[value_json.running_state] }}\","
+ " \"action_topic\": \"zigbee2mqtt/th1\", \"availability\": [ {"
+ " \"topic\": \"zigbee2mqtt/bridge/state\" } ],"
+ " \"away_mode_command_topic\": \"zigbee2mqtt/th1/set/away_mode\","
+ " \"away_mode_state_template\": \"{{ value_json.away_mode }}\","
+ " \"away_mode_state_topic\": \"zigbee2mqtt/th1\","
+ " \"current_temperature_template\": \"{{ value_json.local_temperature }}\","
+ " \"current_temperature_topic\": \"zigbee2mqtt/th1\", \"device\": {"
+ " \"identifiers\": [ \"zigbee2mqtt_0x847127fffe11dd6a\" ], \"manufacturer\": \"TuYa\","
+ " \"model\": \"Radiator valve with thermostat (TS0601_thermostat)\","
+ " \"name\": \"th1\", \"sw_version\": \"Zigbee2MQTT 1.18.2\" },"
+ " \"hold_command_topic\": \"zigbee2mqtt/th1/set/preset\", \"hold_modes\": ["
+ " \"schedule\", \"manual\", \"boost\", \"complex\", \"comfort\", \"eco\" ],"
+ " \"hold_state_template\": \"{{ value_json.preset }}\","
+ " \"hold_state_topic\": \"zigbee2mqtt/th1\","
+ " \"json_attributes_topic\": \"zigbee2mqtt/th1\", \"max_temp\": \"35\","
+ " \"min_temp\": \"5\", \"mode_command_topic\": \"zigbee2mqtt/th1/set/system_mode\","
+ " \"mode_state_template\": \"{{ value_json.system_mode }}\","
+ " \"mode_state_topic\": \"zigbee2mqtt/th1\", \"modes\": [ \"heat\","
+ " \"auto\", \"off\" ], \"name\": \"th1\", \"temp_step\": 0.5,"
+ " \"temperature_command_topic\": \"zigbee2mqtt/th1/set/current_heating_setpoint\","
+ " \"temperature_state_template\": \"{{ value_json.current_heating_setpoint }}\","
+ " \"temperature_state_topic\": \"zigbee2mqtt/th1\", \"temperature_unit\": \"C\","
+ " \"power_command_topic\": \"zigbee2mqtt/th1/power\","
+ " \"unique_id\": \"0x847127fffe11dd6a_climate_zigbee2mqtt\", \"send_if_off\": \"false\"}");
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"""
{\
"action_template": "{% set values = {'idle':'off','heat':'heating','cool':'cooling','fan only':'fan'} %}{{ values[value_json.running_state] }}",\
"action_topic": "zigbee2mqtt/th1", "availability": [ {\
"topic": "zigbee2mqtt/bridge/state" } ],\
"away_mode_command_topic": "zigbee2mqtt/th1/set/away_mode",\
"away_mode_state_template": "{{ value_json.away_mode }}",\
"away_mode_state_topic": "zigbee2mqtt/th1",\
"current_temperature_template": "{{ value_json.local_temperature }}",\
"current_temperature_topic": "zigbee2mqtt/th1", "device": {\
"identifiers": [ "zigbee2mqtt_0x847127fffe11dd6a" ], "manufacturer": "TuYa",\
"model": "Radiator valve with thermostat (TS0601_thermostat)",\
"name": "th1", "sw_version": "Zigbee2MQTT 1.18.2" },\
"hold_command_topic": "zigbee2mqtt/th1/set/preset", "hold_modes": [\
"schedule", "manual", "boost", "complex", "comfort", "eco" ],\
"hold_state_template": "{{ value_json.preset }}",\
"hold_state_topic": "zigbee2mqtt/th1",\
"json_attributes_topic": "zigbee2mqtt/th1", "max_temp": "35",\
"min_temp": "5", "mode_command_topic": "zigbee2mqtt/th1/set/system_mode",\
"mode_state_template": "{{ value_json.system_mode }}",\
"mode_state_topic": "zigbee2mqtt/th1", "modes": [ "heat",\
"auto", "off" ], "name": "th1", "temp_step": 0.5,\
"temperature_command_topic": "zigbee2mqtt/th1/set/current_heating_setpoint",\
"temperature_state_template": "{{ value_json.current_heating_setpoint }}",\
"temperature_state_topic": "zigbee2mqtt/th1", "temperature_unit": "C",\
"power_command_topic": "zigbee2mqtt/th1/power",\
"unique_id": "0x847127fffe11dd6a_climate_zigbee2mqtt", "send_if_off": "false"}\
""");
assertThat(component.channels.size(), is(7));
assertThat(component.getName(), is("th1"));
@@ -146,10 +153,11 @@ public class ClimateTests extends AbstractComponentTests {
assertChannel(component, Climate.TEMPERATURE_CH_ID, "zigbee2mqtt/th1",
"zigbee2mqtt/th1/set/current_heating_setpoint", "th1", NumberValue.class);
publishMessage("zigbee2mqtt/th1",
"{\"running_state\": \"idle\", \"away_mode\": \"ON\", "
+ "\"local_temperature\": \"22.2\", \"preset\": \"schedule\", \"system_mode\": \"heat\", "
+ "\"current_heating_setpoint\": \"24\"}");
publishMessage("zigbee2mqtt/th1", """
{"running_state": "idle", "away_mode": "ON", \
"local_temperature": "22.2", "preset": "schedule", "system_mode": "heat", \
"current_heating_setpoint": "24"}\
""");
assertState(component, Climate.ACTION_CH_ID, new StringType("off"));
assertState(component, Climate.AWAY_MODE_CH_ID, OnOffType.ON);
assertState(component, Climate.CURRENT_TEMPERATURE_CH_ID, new QuantityType<>(22.2, SIUnits.CELSIUS));
@@ -170,10 +178,11 @@ public class ClimateTests extends AbstractComponentTests {
assertPublished("zigbee2mqtt/th1/power", "ON");
// Enabled
publishMessage("zigbee2mqtt/th1",
"{\"running_state\": \"heat\", \"away_mode\": \"ON\", "
+ "\"local_temperature\": \"22.2\", \"preset\": \"schedule\", \"system_mode\": \"heat\", "
+ "\"current_heating_setpoint\": \"24\"}");
publishMessage("zigbee2mqtt/th1", """
{"running_state": "heat", "away_mode": "ON", \
"local_temperature": "22.2", "preset": "schedule", "system_mode": "heat", \
"current_heating_setpoint": "24"}\
""");
// Climate is in ON state
component.getChannel(Climate.AWAY_MODE_CH_ID).getState().publishValue(OnOffType.OFF);
@@ -189,48 +198,49 @@ public class ClimateTests extends AbstractComponentTests {
@SuppressWarnings("null")
@Test
public void testClimate() {
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{\"action_template\": \"{{ value_json.action }}\", \"action_topic\": \"zigbee2mqtt/th1\","
+ " \"aux_command_topic\": \"zigbee2mqtt/th1/aux\","
+ " \"aux_state_template\": \"{{ value_json.aux }}\", \"aux_state_topic\": \"zigbee2mqtt/th1\","
+ " \"away_mode_command_topic\": \"zigbee2mqtt/th1/away_mode\","
+ " \"away_mode_state_template\": \"{{ value_json.away_mode }}\","
+ " \"away_mode_state_topic\": \"zigbee2mqtt/th1\","
+ " \"current_temperature_template\": \"{{ value_json.current_temperature }}\","
+ " \"current_temperature_topic\": \"zigbee2mqtt/th1\","
+ " \"fan_mode_command_template\": \"fan_mode={{ value }}\","
+ " \"fan_mode_command_topic\": \"zigbee2mqtt/th1/fan_mode\","
+ " \"fan_mode_state_template\": \"{{ value_json.fan_mode }}\","
+ " \"fan_mode_state_topic\": \"zigbee2mqtt/th1\", \"fan_modes\": [ \"p1\","
+ " \"p2\" ], \"hold_command_template\": \"hold={{ value }}\","
+ " \"hold_command_topic\": \"zigbee2mqtt/th1/hold\","
+ " \"hold_state_template\": \"{{ value_json.hold }}\","
+ " \"hold_state_topic\": \"zigbee2mqtt/th1\", \"hold_modes\": [ \"u1\", \"u2\","
+ " \"u3\" ], \"json_attributes_template\": \"{{ value_json.attrs }}\","
+ " \"json_attributes_topic\": \"zigbee2mqtt/th1\","
+ " \"mode_command_template\": \"mode={{ value }}\","
+ " \"mode_command_topic\": \"zigbee2mqtt/th1/mode\","
+ " \"mode_state_template\": \"{{ value_json.mode }}\","
+ " \"mode_state_topic\": \"zigbee2mqtt/th1\", \"modes\": [ \"B1\", \"B2\""
+ " ], \"swing_command_template\": \"swing={{ value }}\","
+ " \"swing_command_topic\": \"zigbee2mqtt/th1/swing\","
+ " \"swing_state_template\": \"{{ value_json.swing }}\","
+ " \"swing_state_topic\": \"zigbee2mqtt/th1\", \"swing_modes\": [ \"G1\","
+ " \"G2\" ], \"temperature_command_template\": \"temperature={{ value }}\","
+ " \"temperature_command_topic\": \"zigbee2mqtt/th1/temperature\","
+ " \"temperature_state_template\": \"{{ value_json.temperature }}\","
+ " \"temperature_state_topic\": \"zigbee2mqtt/th1\","
+ " \"temperature_high_command_template\": \"temperature_high={{ value }}\","
+ " \"temperature_high_command_topic\": \"zigbee2mqtt/th1/temperature_high\","
+ " \"temperature_high_state_template\": \"{{ value_json.temperature_high }}\","
+ " \"temperature_high_state_topic\": \"zigbee2mqtt/th1\","
+ " \"temperature_low_command_template\": \"temperature_low={{ value }}\","
+ " \"temperature_low_command_topic\": \"zigbee2mqtt/th1/temperature_low\","
+ " \"temperature_low_state_template\": \"{{ value_json.temperature_low }}\","
+ " \"temperature_low_state_topic\": \"zigbee2mqtt/th1\","
+ " \"power_command_topic\": \"zigbee2mqtt/th1/power\", \"initial\": \"10\","
+ " \"max_temp\": \"40\", \"min_temp\": \"0\", \"temperature_unit\": \"F\","
+ " \"temp_step\": \"1\", \"precision\": \"0.5\", \"send_if_off\": \"false\" }");
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC), """
{"action_template": "{{ value_json.action }}", "action_topic": "zigbee2mqtt/th1",\
"aux_command_topic": "zigbee2mqtt/th1/aux",\
"aux_state_template": "{{ value_json.aux }}", "aux_state_topic": "zigbee2mqtt/th1",\
"away_mode_command_topic": "zigbee2mqtt/th1/away_mode",\
"away_mode_state_template": "{{ value_json.away_mode }}",\
"away_mode_state_topic": "zigbee2mqtt/th1",\
"current_temperature_template": "{{ value_json.current_temperature }}",\
"current_temperature_topic": "zigbee2mqtt/th1",\
"fan_mode_command_template": "fan_mode={{ value }}",\
"fan_mode_command_topic": "zigbee2mqtt/th1/fan_mode",\
"fan_mode_state_template": "{{ value_json.fan_mode }}",\
"fan_mode_state_topic": "zigbee2mqtt/th1", "fan_modes": [ "p1",\
"p2" ], "hold_command_template": "hold={{ value }}",\
"hold_command_topic": "zigbee2mqtt/th1/hold",\
"hold_state_template": "{{ value_json.hold }}",\
"hold_state_topic": "zigbee2mqtt/th1", "hold_modes": [ "u1", "u2",\
"u3" ], "json_attributes_template": "{{ value_json.attrs }}",\
"json_attributes_topic": "zigbee2mqtt/th1",\
"mode_command_template": "mode={{ value }}",\
"mode_command_topic": "zigbee2mqtt/th1/mode",\
"mode_state_template": "{{ value_json.mode }}",\
"mode_state_topic": "zigbee2mqtt/th1", "modes": [ "B1", "B2"\
], "swing_command_template": "swing={{ value }}",\
"swing_command_topic": "zigbee2mqtt/th1/swing",\
"swing_state_template": "{{ value_json.swing }}",\
"swing_state_topic": "zigbee2mqtt/th1", "swing_modes": [ "G1",\
"G2" ], "temperature_command_template": "temperature={{ value }}",\
"temperature_command_topic": "zigbee2mqtt/th1/temperature",\
"temperature_state_template": "{{ value_json.temperature }}",\
"temperature_state_topic": "zigbee2mqtt/th1",\
"temperature_high_command_template": "temperature_high={{ value }}",\
"temperature_high_command_topic": "zigbee2mqtt/th1/temperature_high",\
"temperature_high_state_template": "{{ value_json.temperature_high }}",\
"temperature_high_state_topic": "zigbee2mqtt/th1",\
"temperature_low_command_template": "temperature_low={{ value }}",\
"temperature_low_command_topic": "zigbee2mqtt/th1/temperature_low",\
"temperature_low_state_template": "{{ value_json.temperature_low }}",\
"temperature_low_state_topic": "zigbee2mqtt/th1",\
"power_command_topic": "zigbee2mqtt/th1/power", "initial": "10",\
"max_temp": "40", "min_temp": "0", "temperature_unit": "F",\
"temp_step": "1", "precision": "0.5", "send_if_off": "false" }\
""");
assertThat(component.channels.size(), is(12));
assertThat(component.getName(), is("MQTT HVAC"));
@@ -258,11 +268,12 @@ public class ClimateTests extends AbstractComponentTests {
"MQTT HVAC", NumberValue.class);
assertChannel(component, Climate.POWER_CH_ID, "", "zigbee2mqtt/th1/power", "MQTT HVAC", OnOffValue.class);
publishMessage("zigbee2mqtt/th1",
"{ \"action\": \"fan\", \"aux\": \"ON\", \"away_mode\": \"OFF\", "
+ "\"current_temperature\": \"35.5\", \"fan_mode\": \"p2\", \"hold\": \"u2\", "
+ "\"mode\": \"B1\", \"swing\": \"G1\", \"temperature\": \"30\", "
+ "\"temperature_high\": \"37\", \"temperature_low\": \"20\" }");
publishMessage("zigbee2mqtt/th1", """
{ "action": "fan", "aux": "ON", "away_mode": "OFF", \
"current_temperature": "35.5", "fan_mode": "p2", "hold": "u2", \
"mode": "B1", "swing": "G1", "temperature": "30", \
"temperature_high": "37", "temperature_low": "20" }\
""");
assertState(component, Climate.ACTION_CH_ID, new StringType("fan"));
assertState(component, Climate.AUX_CH_ID, OnOffType.ON);

View File

@@ -37,28 +37,30 @@ public class CoverTests extends AbstractComponentTests {
public void test() throws InterruptedException {
// @formatter:off
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"availability\": [ " +
" { " +
" \"topic\": \"zigbee2mqtt/bridge/state\" " +
" } " +
" ], " +
" \"device\": { " +
" \"identifiers\": [ " +
" \"zigbee2mqtt_0x0000000000000000\" " +
" ], " +
" \"manufacturer\": \"Covers inc\", " +
" \"model\": \"cover v1\", " +
" \"name\": \"Cover\", " +
" \"sw_version\": \"Zigbee2MQTT 1.18.2\" " +
" }, " +
" \"name\": \"cover\", " +
" \"payload_open\": \"OPEN_\", " +
" \"payload_close\": \"CLOSE_\", " +
" \"payload_stop\": \"STOP_\", " +
" \"state_topic\": \"zigbee2mqtt/cover/state\", " +
" \"command_topic\": \"zigbee2mqtt/cover/set/state\" " +
"}");
"""
{ \
"availability": [ \
{ \
"topic": "zigbee2mqtt/bridge/state" \
} \
], \
"device": { \
"identifiers": [ \
"zigbee2mqtt_0x0000000000000000" \
], \
"manufacturer": "Covers inc", \
"model": "cover v1", \
"name": "Cover", \
"sw_version": "Zigbee2MQTT 1.18.2" \
}, \
"name": "cover", \
"payload_open": "OPEN_", \
"payload_close": "CLOSE_", \
"payload_stop": "STOP_", \
"state_topic": "zigbee2mqtt/cover/state", \
"command_topic": "zigbee2mqtt/cover/set/state" \
}\
""");
// @formatter:on
assertThat(component.channels.size(), is(1));

View File

@@ -46,34 +46,36 @@ public class DefaultSchemaLightTests extends AbstractComponentTests {
public void testRgb() throws InterruptedException {
// @formatter:off
var component = (Light) discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"availability\": [ " +
" { " +
" \"topic\": \"zigbee2mqtt/bridge/state\" " +
" } " +
" ], " +
" \"device\": { " +
" \"identifiers\": [ " +
" \"zigbee2mqtt_0x0000000000000000\" " +
" ], " +
" \"manufacturer\": \"Lights inc\", " +
" \"model\": \"light v1\", " +
" \"name\": \"Light\", " +
" \"sw_version\": \"Zigbee2MQTT 1.18.2\" " +
" }, " +
" \"name\": \"light\", " +
" \"state_topic\": \"zigbee2mqtt/light/state\", " +
" \"command_topic\": \"zigbee2mqtt/light/set/state\", " +
" \"state_value_template\": \"{{ value_json.power }}\", " +
" \"payload_on\": \"ON_\", " +
" \"payload_off\": \"OFF_\", " +
" \"rgb_state_topic\": \"zigbee2mqtt/light/rgb\", " +
" \"rgb_command_topic\": \"zigbee2mqtt/light/set/rgb\", " +
" \"rgb_value_template\": \"{{ value_json.rgb }}\", " +
" \"brightness_state_topic\": \"zigbee2mqtt/light/brightness\", " +
" \"brightness_command_topic\": \"zigbee2mqtt/light/set/brightness\", " +
" \"brightness_value_template\": \"{{ value_json.br }}\" " +
"}");
"""
{ \
"availability": [ \
{ \
"topic": "zigbee2mqtt/bridge/state" \
} \
], \
"device": { \
"identifiers": [ \
"zigbee2mqtt_0x0000000000000000" \
], \
"manufacturer": "Lights inc", \
"model": "light v1", \
"name": "Light", \
"sw_version": "Zigbee2MQTT 1.18.2" \
}, \
"name": "light", \
"state_topic": "zigbee2mqtt/light/state", \
"command_topic": "zigbee2mqtt/light/set/state", \
"state_value_template": "{{ value_json.power }}", \
"payload_on": "ON_", \
"payload_off": "OFF_", \
"rgb_state_topic": "zigbee2mqtt/light/rgb", \
"rgb_command_topic": "zigbee2mqtt/light/set/rgb", \
"rgb_value_template": "{{ value_json.rgb }}", \
"brightness_state_topic": "zigbee2mqtt/light/brightness", \
"brightness_command_topic": "zigbee2mqtt/light/set/brightness", \
"brightness_value_template": "{{ value_json.br }}" \
}\
""");
// @formatter:on
assertThat(component.channels.size(), is(1));
@@ -119,17 +121,19 @@ public class DefaultSchemaLightTests extends AbstractComponentTests {
public void testRgbWithoutBrightness() throws InterruptedException {
// @formatter:off
var component = (Light) discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"name\": \"light\", " +
" \"state_topic\": \"zigbee2mqtt/light/state\", " +
" \"command_topic\": \"zigbee2mqtt/light/set/state\", " +
" \"state_value_template\": \"{{ value_json.power }}\", " +
" \"payload_on\": \"ON_\", " +
" \"payload_off\": \"OFF_\", " +
" \"rgb_state_topic\": \"zigbee2mqtt/light/rgb\", " +
" \"rgb_command_topic\": \"zigbee2mqtt/light/set/rgb\", " +
" \"rgb_value_template\": \"{{ value_json.rgb }}\"" +
"}");
"""
{ \
"name": "light", \
"state_topic": "zigbee2mqtt/light/state", \
"command_topic": "zigbee2mqtt/light/set/state", \
"state_value_template": "{{ value_json.power }}", \
"payload_on": "ON_", \
"payload_off": "OFF_", \
"rgb_state_topic": "zigbee2mqtt/light/rgb", \
"rgb_command_topic": "zigbee2mqtt/light/set/rgb", \
"rgb_value_template": "{{ value_json.rgb }}"\
}\
""");
// @formatter:on
publishMessage("zigbee2mqtt/light/rgb", "{\"rgb\": \"255,255,255\"}");
@@ -148,20 +152,22 @@ public class DefaultSchemaLightTests extends AbstractComponentTests {
public void testHsb() throws InterruptedException {
// @formatter:off
var component = (Light) discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"name\": \"light\", " +
" \"state_topic\": \"zigbee2mqtt/light/state\", " +
" \"command_topic\": \"zigbee2mqtt/light/set/state\", " +
" \"state_value_template\": \"{{ value_json.power }}\", " +
" \"payload_on\": \"ON_\", " +
" \"payload_off\": \"OFF_\", " +
" \"hs_state_topic\": \"zigbee2mqtt/light/hs\", " +
" \"hs_command_topic\": \"zigbee2mqtt/light/set/hs\", " +
" \"hs_value_template\": \"{{ value_json.hs }}\", " +
" \"brightness_state_topic\": \"zigbee2mqtt/light/brightness\", " +
" \"brightness_command_topic\": \"zigbee2mqtt/light/set/brightness\", " +
" \"brightness_value_template\": \"{{ value_json.br }}\" " +
"}");
"""
{ \
"name": "light", \
"state_topic": "zigbee2mqtt/light/state", \
"command_topic": "zigbee2mqtt/light/set/state", \
"state_value_template": "{{ value_json.power }}", \
"payload_on": "ON_", \
"payload_off": "OFF_", \
"hs_state_topic": "zigbee2mqtt/light/hs", \
"hs_command_topic": "zigbee2mqtt/light/set/hs", \
"hs_value_template": "{{ value_json.hs }}", \
"brightness_state_topic": "zigbee2mqtt/light/brightness", \
"brightness_command_topic": "zigbee2mqtt/light/set/brightness", \
"brightness_value_template": "{{ value_json.br }}" \
}\
""");
// @formatter:on
assertThat(component.channels.size(), is(1));
@@ -206,16 +212,18 @@ public class DefaultSchemaLightTests extends AbstractComponentTests {
public void testBrightnessAndOnOff() throws InterruptedException {
// @formatter:off
var component = (Light) discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"name\": \"light\", " +
" \"state_topic\": \"zigbee2mqtt/light/state\", " +
" \"command_topic\": \"zigbee2mqtt/light/set/state\", " +
" \"state_value_template\": \"{{ value_json.power }}\", " +
" \"brightness_state_topic\": \"zigbee2mqtt/light/brightness\", " +
" \"brightness_command_topic\": \"zigbee2mqtt/light/set/brightness\", " +
" \"payload_on\": \"ON_\", " +
" \"payload_off\": \"OFF_\" " +
"}");
"""
{ \
"name": "light", \
"state_topic": "zigbee2mqtt/light/state", \
"command_topic": "zigbee2mqtt/light/set/state", \
"state_value_template": "{{ value_json.power }}", \
"brightness_state_topic": "zigbee2mqtt/light/brightness", \
"brightness_command_topic": "zigbee2mqtt/light/set/brightness", \
"payload_on": "ON_", \
"payload_off": "OFF_" \
}\
""");
// @formatter:on
assertThat(component.channels.size(), is(1));
@@ -249,14 +257,16 @@ public class DefaultSchemaLightTests extends AbstractComponentTests {
public void testOnOffOnly() throws InterruptedException {
// @formatter:off
var component = (Light) discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"name\": \"light\", " +
" \"state_topic\": \"zigbee2mqtt/light/state\", " +
" \"command_topic\": \"zigbee2mqtt/light/set/state\", " +
" \"state_value_template\": \"{{ value_json.power }}\", " +
" \"payload_on\": \"ON_\", " +
" \"payload_off\": \"OFF_\" " +
"}");
"""
{ \
"name": "light", \
"state_topic": "zigbee2mqtt/light/state", \
"command_topic": "zigbee2mqtt/light/set/state", \
"state_value_template": "{{ value_json.power }}", \
"payload_on": "ON_", \
"payload_off": "OFF_" \
}\
""");
// @formatter:on
assertThat(component.channels.size(), is(1));

View File

@@ -36,27 +36,29 @@ public class FanTests extends AbstractComponentTests {
public void test() throws InterruptedException {
// @formatter:off
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"availability\": [ " +
" { " +
" \"topic\": \"zigbee2mqtt/bridge/state\" " +
" } " +
" ], " +
" \"device\": { " +
" \"identifiers\": [ " +
" \"zigbee2mqtt_0x0000000000000000\" " +
" ], " +
" \"manufacturer\": \"Fans inc\", " +
" \"model\": \"Fan\", " +
" \"name\": \"FanBlower\", " +
" \"sw_version\": \"Zigbee2MQTT 1.18.2\" " +
" }, " +
" \"name\": \"fan\", " +
" \"payload_off\": \"OFF_\", " +
" \"payload_on\": \"ON_\", " +
" \"state_topic\": \"zigbee2mqtt/fan/state\", " +
" \"command_topic\": \"zigbee2mqtt/fan/set/state\" " +
"}");
"""
{ \
"availability": [ \
{ \
"topic": "zigbee2mqtt/bridge/state" \
} \
], \
"device": { \
"identifiers": [ \
"zigbee2mqtt_0x0000000000000000" \
], \
"manufacturer": "Fans inc", \
"model": "Fan", \
"name": "FanBlower", \
"sw_version": "Zigbee2MQTT 1.18.2" \
}, \
"name": "fan", \
"payload_off": "OFF_", \
"payload_on": "ON_", \
"state_topic": "zigbee2mqtt/fan/state", \
"command_topic": "zigbee2mqtt/fan/set/state" \
}\
""");
// @formatter:on
assertThat(component.channels.size(), is(1));

View File

@@ -41,29 +41,31 @@ public class JSONSchemaLightTests extends AbstractComponentTests {
public void testRgb() throws InterruptedException {
// @formatter:off
var component = (Light) discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"availability\": [ " +
" { " +
" \"topic\": \"zigbee2mqtt/bridge/state\" " +
" } " +
" ], " +
" \"device\": { " +
" \"identifiers\": [ " +
" \"zigbee2mqtt_0x0000000000000000\" " +
" ], " +
" \"manufacturer\": \"Lights inc\", " +
" \"model\": \"light v1\", " +
" \"name\": \"Light\", " +
" \"sw_version\": \"Zigbee2MQTT 1.18.2\" " +
" }, " +
" \"name\": \"light\", " +
" \"schema\": \"json\", " +
" \"state_topic\": \"zigbee2mqtt/light/state\", " +
" \"command_topic\": \"zigbee2mqtt/light/set/state\", " +
" \"brightness\": true, " +
" \"color_mode\": true, " +
" \"supported_color_modes\": [\"onoff\", \"brightness\", \"rgb\"]" +
"}");
"""
{ \
"availability": [ \
{ \
"topic": "zigbee2mqtt/bridge/state" \
} \
], \
"device": { \
"identifiers": [ \
"zigbee2mqtt_0x0000000000000000" \
], \
"manufacturer": "Lights inc", \
"model": "light v1", \
"name": "Light", \
"sw_version": "Zigbee2MQTT 1.18.2" \
}, \
"name": "light", \
"schema": "json", \
"state_topic": "zigbee2mqtt/light/state", \
"command_topic": "zigbee2mqtt/light/set/state", \
"brightness": true, \
"color_mode": true, \
"supported_color_modes": ["onoff", "brightness", "rgb"]\
}\
""");
// @formatter:on
assertThat(component.channels.size(), is(1));
@@ -97,13 +99,15 @@ public class JSONSchemaLightTests extends AbstractComponentTests {
public void testBrightnessAndOnOff() throws InterruptedException {
// @formatter:off
var component = (Light) discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"name\": \"light\", " +
" \"schema\": \"json\", " +
" \"state_topic\": \"zigbee2mqtt/light/state\", " +
" \"command_topic\": \"zigbee2mqtt/light/set/state\", " +
" \"brightness\": true" +
"}");
"""
{ \
"name": "light", \
"schema": "json", \
"state_topic": "zigbee2mqtt/light/state", \
"command_topic": "zigbee2mqtt/light/set/state", \
"brightness": true\
}\
""");
// @formatter:on
assertThat(component.channels.size(), is(1));
@@ -126,12 +130,14 @@ public class JSONSchemaLightTests extends AbstractComponentTests {
public void testOnOffOnly() throws InterruptedException {
// @formatter:off
var component = (Light) discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"name\": \"light\", " +
" \"schema\": \"json\", " +
" \"state_topic\": \"zigbee2mqtt/light/state\", " +
" \"command_topic\": \"zigbee2mqtt/light/set/state\"" +
"}");
"""
{ \
"name": "light", \
"schema": "json", \
"state_topic": "zigbee2mqtt/light/state", \
"command_topic": "zigbee2mqtt/light/set/state"\
}\
""");
// @formatter:on
assertThat(component.channels.size(), is(1));

View File

@@ -36,27 +36,29 @@ public class LockTests extends AbstractComponentTests {
public void test() throws InterruptedException {
// @formatter:off
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"availability\": [ " +
" { " +
" \"topic\": \"zigbee2mqtt/bridge/state\" " +
" } " +
" ], " +
" \"device\": { " +
" \"identifiers\": [ " +
" \"zigbee2mqtt_0x0000000000000000\" " +
" ], " +
" \"manufacturer\": \"Locks inc\", " +
" \"model\": \"Lock\", " +
" \"name\": \"LockBlower\", " +
" \"sw_version\": \"Zigbee2MQTT 1.18.2\" " +
" }, " +
" \"name\": \"lock\", " +
" \"payload_unlock\": \"UNLOCK_\", " +
" \"payload_lock\": \"LOCK_\", " +
" \"state_topic\": \"zigbee2mqtt/lock/state\", " +
" \"command_topic\": \"zigbee2mqtt/lock/set/state\" " +
"}");
"""
{ \
"availability": [ \
{ \
"topic": "zigbee2mqtt/bridge/state" \
} \
], \
"device": { \
"identifiers": [ \
"zigbee2mqtt_0x0000000000000000" \
], \
"manufacturer": "Locks inc", \
"model": "Lock", \
"name": "LockBlower", \
"sw_version": "Zigbee2MQTT 1.18.2" \
}, \
"name": "lock", \
"payload_unlock": "UNLOCK_", \
"payload_lock": "LOCK_", \
"state_topic": "zigbee2mqtt/lock/state", \
"command_topic": "zigbee2mqtt/lock/set/state" \
}\
""");
// @formatter:on
assertThat(component.channels.size(), is(1));
@@ -84,28 +86,30 @@ public class LockTests extends AbstractComponentTests {
public void forceOptimisticIsNotSupported() {
// @formatter:off
publishMessage(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"availability\": [ " +
" { " +
" \"topic\": \"zigbee2mqtt/bridge/state\" " +
" } " +
" ], " +
" \"device\": { " +
" \"identifiers\": [ " +
" \"zigbee2mqtt_0x0000000000000000\" " +
" ], " +
" \"manufacturer\": \"Locks inc\", " +
" \"model\": \"Lock\", " +
" \"name\": \"LockBlower\", " +
" \"sw_version\": \"Zigbee2MQTT 1.18.2\" " +
" }, " +
" \"name\": \"lock\", " +
" \"payload_unlock\": \"UNLOCK_\", " +
" \"payload_lock\": \"LOCK_\", " +
" \"optimistic\": \"true\", " +
" \"state_topic\": \"zigbee2mqtt/lock/state\", " +
" \"command_topic\": \"zigbee2mqtt/lock/set/state\" " +
"}");
"""
{ \
"availability": [ \
{ \
"topic": "zigbee2mqtt/bridge/state" \
} \
], \
"device": { \
"identifiers": [ \
"zigbee2mqtt_0x0000000000000000" \
], \
"manufacturer": "Locks inc", \
"model": "Lock", \
"name": "LockBlower", \
"sw_version": "Zigbee2MQTT 1.18.2" \
}, \
"name": "lock", \
"payload_unlock": "UNLOCK_", \
"payload_lock": "LOCK_", \
"optimistic": "true", \
"state_topic": "zigbee2mqtt/lock/state", \
"command_topic": "zigbee2mqtt/lock/set/state" \
}\
""");
// @formatter:on
}

View File

@@ -40,25 +40,27 @@ public class SensorTests extends AbstractComponentTests {
public void test() throws InterruptedException {
// @formatter:off
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"availability_topic\": \"zigbee2mqtt/bridge/state\", " +
" \"availability_template\": \"{{value_json.state}}\", " +
" \"device\": { " +
" \"identifiers\": [ " +
" \"zigbee2mqtt_0x0000000000000000\" " +
" ], " +
" \"manufacturer\": \"Sensors inc\", " +
" \"model\": \"Sensor\", " +
" \"name\": \"Sensor\", " +
" \"sw_version\": \"Zigbee2MQTT 1.18.2\" " +
" }, " +
" \"name\": \"sensor1\", " +
" \"expire_after\": \"1\", " +
" \"force_update\": \"true\", " +
" \"unit_of_measurement\": \"W\", " +
" \"state_topic\": \"zigbee2mqtt/sensor/state\", " +
" \"unique_id\": \"sn1\" " +
"}");
"""
{ \
"availability_topic": "zigbee2mqtt/bridge/state", \
"availability_template": "{{value_json.state}}", \
"device": { \
"identifiers": [ \
"zigbee2mqtt_0x0000000000000000" \
], \
"manufacturer": "Sensors inc", \
"model": "Sensor", \
"name": "Sensor", \
"sw_version": "Zigbee2MQTT 1.18.2" \
}, \
"name": "sensor1", \
"expire_after": "1", \
"force_update": "true", \
"unit_of_measurement": "W", \
"state_topic": "zigbee2mqtt/sensor/state", \
"unique_id": "sn1" \
}\
""");
// @formatter:on
assertThat(component.channels.size(), is(1));
@@ -87,23 +89,25 @@ public class SensorTests extends AbstractComponentTests {
public void testMeasurementStateClass() throws InterruptedException {
// @formatter:off
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"device\": { " +
" \"identifiers\": [ " +
" \"zigbee2mqtt_0x0000000000000000\" " +
" ], " +
" \"manufacturer\": \"Sensors inc\", " +
" \"model\": \"Sensor\", " +
" \"name\": \"Sensor\", " +
" \"sw_version\": \"Zigbee2MQTT 1.18.2\" " +
" }, " +
" \"name\": \"sensor1\", " +
" \"expire_after\": \"1\", " +
" \"force_update\": \"true\", " +
" \"state_class\": \"measurement\", " +
" \"state_topic\": \"zigbee2mqtt/sensor/state\", " +
" \"unique_id\": \"sn1\" " +
"}");
"""
{ \
"device": { \
"identifiers": [ \
"zigbee2mqtt_0x0000000000000000" \
], \
"manufacturer": "Sensors inc", \
"model": "Sensor", \
"name": "Sensor", \
"sw_version": "Zigbee2MQTT 1.18.2" \
}, \
"name": "sensor1", \
"expire_after": "1", \
"force_update": "true", \
"state_class": "measurement", \
"state_topic": "zigbee2mqtt/sensor/state", \
"unique_id": "sn1" \
}\
""");
// @formatter:on
assertChannel(component, Sensor.SENSOR_CHANNEL_ID, "zigbee2mqtt/sensor/state", "", "sensor1",
@@ -114,22 +118,24 @@ public class SensorTests extends AbstractComponentTests {
public void testNonNumericSensor() throws InterruptedException {
// @formatter:off
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"{ " +
" \"device\": { " +
" \"identifiers\": [ " +
" \"zigbee2mqtt_0x0000000000000000\" " +
" ], " +
" \"manufacturer\": \"Sensors inc\", " +
" \"model\": \"Sensor\", " +
" \"name\": \"Sensor\", " +
" \"sw_version\": \"Zigbee2MQTT 1.18.2\" " +
" }, " +
" \"name\": \"sensor1\", " +
" \"expire_after\": \"1\", " +
" \"force_update\": \"true\", " +
" \"state_topic\": \"zigbee2mqtt/sensor/state\", " +
" \"unique_id\": \"sn1\" " +
"}");
"""
{ \
"device": { \
"identifiers": [ \
"zigbee2mqtt_0x0000000000000000" \
], \
"manufacturer": "Sensors inc", \
"model": "Sensor", \
"name": "Sensor", \
"sw_version": "Zigbee2MQTT 1.18.2" \
}, \
"name": "sensor1", \
"expire_after": "1", \
"force_update": "true", \
"state_topic": "zigbee2mqtt/sensor/state", \
"unique_id": "sn1" \
}\
""");
// @formatter:on
assertChannel(component, Sensor.SENSOR_CHANNEL_ID, "zigbee2mqtt/sensor/state", "", "sensor1", TextValue.class);

View File

@@ -34,20 +34,34 @@ public class SwitchTests extends AbstractComponentTests {
@SuppressWarnings("null")
@Test
public void testSwitchWithStateAndCommand() {
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"" + "{\n" + " \"availability\": [\n" + " {\n" + " \"topic\": \"zigbee2mqtt/bridge/state\"\n"
+ " }\n" + " ],\n" + " \"command_topic\": \"zigbee2mqtt/th1/set/auto_lock\",\n"
+ " \"device\": {\n" + " \"identifiers\": [\n"
+ " \"zigbee2mqtt_0x847127fffe11dd6a\"\n" + " ],\n"
+ " \"manufacturer\": \"TuYa\",\n"
+ " \"model\": \"Radiator valve with thermostat (TS0601_thermostat)\",\n"
+ " \"name\": \"th1\",\n" + " \"sw_version\": \"Zigbee2MQTT 1.18.2\"\n" + " },\n"
+ " \"json_attributes_topic\": \"zigbee2mqtt/th1\",\n" + " \"name\": \"th1 auto lock\",\n"
+ " \"payload_off\": \"MANUAL\",\n" + " \"payload_on\": \"AUTO\",\n"
+ " \"state_off\": \"MANUAL\",\n" + " \"state_on\": \"AUTO\",\n"
+ " \"state_topic\": \"zigbee2mqtt/th1\",\n"
+ " \"unique_id\": \"0x847127fffe11dd6a_auto_lock_zigbee2mqtt\",\n"
+ " \"value_template\": \"{{ value_json.auto_lock }}\"\n" + "}");
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC), """
{
"availability": [
{
"topic": "zigbee2mqtt/bridge/state"
}
],
"command_topic": "zigbee2mqtt/th1/set/auto_lock",
"device": {
"identifiers": [
"zigbee2mqtt_0x847127fffe11dd6a"
],
"manufacturer": "TuYa",
"model": "Radiator valve with thermostat (TS0601_thermostat)",
"name": "th1",
"sw_version": "Zigbee2MQTT 1.18.2"
},
"json_attributes_topic": "zigbee2mqtt/th1",
"name": "th1 auto lock",
"payload_off": "MANUAL",
"payload_on": "AUTO",
"state_off": "MANUAL",
"state_on": "AUTO",
"state_topic": "zigbee2mqtt/th1",
"unique_id": "0x847127fffe11dd6a_auto_lock_zigbee2mqtt",
"value_template": "{{ value_json.auto_lock }}"
}\
""");
assertThat(component.channels.size(), is(1));
assertThat(component.getName(), is("th1 auto lock"));
@@ -68,18 +82,31 @@ public class SwitchTests extends AbstractComponentTests {
@Test
public void testSwitchWithState() {
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"" + "{\n" + " \"availability\": [\n" + " {\n" + " \"topic\": \"zigbee2mqtt/bridge/state\"\n"
+ " }\n" + " ],\n" + " \"device\": {\n" + " \"identifiers\": [\n"
+ " \"zigbee2mqtt_0x847127fffe11dd6a\"\n" + " ],\n"
+ " \"manufacturer\": \"TuYa\",\n"
+ " \"model\": \"Radiator valve with thermostat (TS0601_thermostat)\",\n"
+ " \"name\": \"th1\",\n" + " \"sw_version\": \"Zigbee2MQTT 1.18.2\"\n" + " },\n"
+ " \"json_attributes_topic\": \"zigbee2mqtt/th1\",\n" + " \"name\": \"th1 auto lock\",\n"
+ " \"state_off\": \"MANUAL\",\n" + " \"state_on\": \"AUTO\",\n"
+ " \"state_topic\": \"zigbee2mqtt/th1\",\n"
+ " \"unique_id\": \"0x847127fffe11dd6a_auto_lock_zigbee2mqtt\",\n"
+ " \"value_template\": \"{{ value_json.auto_lock }}\"\n" + "}");
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC), """
{
"availability": [
{
"topic": "zigbee2mqtt/bridge/state"
}
],
"device": {
"identifiers": [
"zigbee2mqtt_0x847127fffe11dd6a"
],
"manufacturer": "TuYa",
"model": "Radiator valve with thermostat (TS0601_thermostat)",
"name": "th1",
"sw_version": "Zigbee2MQTT 1.18.2"
},
"json_attributes_topic": "zigbee2mqtt/th1",
"name": "th1 auto lock",
"state_off": "MANUAL",
"state_on": "AUTO",
"state_topic": "zigbee2mqtt/th1",
"unique_id": "0x847127fffe11dd6a_auto_lock_zigbee2mqtt",
"value_template": "{{ value_json.auto_lock }}"
}\
""");
assertThat(component.channels.size(), is(1));
assertThat(component.getName(), is("th1 auto lock"));
@@ -95,18 +122,31 @@ public class SwitchTests extends AbstractComponentTests {
@SuppressWarnings("null")
@Test
public void testSwitchWithCommand() {
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"" + "{\n" + " \"availability\": [\n" + " {\n" + " \"topic\": \"zigbee2mqtt/bridge/state\"\n"
+ " }\n" + " ],\n" + " \"command_topic\": \"zigbee2mqtt/th1/set/auto_lock\",\n"
+ " \"device\": {\n" + " \"identifiers\": [\n"
+ " \"zigbee2mqtt_0x847127fffe11dd6a\"\n" + " ],\n"
+ " \"manufacturer\": \"TuYa\",\n"
+ " \"model\": \"Radiator valve with thermostat (TS0601_thermostat)\",\n"
+ " \"name\": \"th1\",\n" + " \"sw_version\": \"Zigbee2MQTT 1.18.2\"\n" + " },\n"
+ " \"json_attributes_topic\": \"zigbee2mqtt/th1\",\n" + " \"name\": \"th1 auto lock\",\n"
+ " \"payload_off\": \"MANUAL\",\n" + " \"payload_on\": \"AUTO\",\n"
+ " \"unique_id\": \"0x847127fffe11dd6a_auto_lock_zigbee2mqtt\",\n"
+ " \"value_template\": \"{{ value_json.auto_lock }}\"\n" + "}");
var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC), """
{
"availability": [
{
"topic": "zigbee2mqtt/bridge/state"
}
],
"command_topic": "zigbee2mqtt/th1/set/auto_lock",
"device": {
"identifiers": [
"zigbee2mqtt_0x847127fffe11dd6a"
],
"manufacturer": "TuYa",
"model": "Radiator valve with thermostat (TS0601_thermostat)",
"name": "th1",
"sw_version": "Zigbee2MQTT 1.18.2"
},
"json_attributes_topic": "zigbee2mqtt/th1",
"name": "th1 auto lock",
"payload_off": "MANUAL",
"payload_on": "AUTO",
"unique_id": "0x847127fffe11dd6a_auto_lock_zigbee2mqtt",
"value_template": "{{ value_json.auto_lock }}"
}\
""");
assertThat(component.channels.size(), is(1));
assertThat(component.getName(), is("th1 auto lock"));

View File

@@ -40,26 +40,28 @@ public class VacuumTests extends AbstractComponentTests {
@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\"" +
"}");
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
@@ -82,41 +84,45 @@ public class VacuumTests extends AbstractComponentTests {
// @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" +
"}");
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\"" +
"}");
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));
@@ -128,11 +134,13 @@ public class VacuumTests extends AbstractComponentTests {
assertPublished("valetudo/rockrobo/command", "start");
// @formatter:off
publishMessage("valetudo/rockrobo/state", "{" +
"\"state\":\"cleaning\"," +
"\"battery_level\":99," +
"\"fan_speed\":\"max\"" +
"}");
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));
@@ -144,11 +152,13 @@ public class VacuumTests extends AbstractComponentTests {
assertPublished("valetudo/rockrobo/set_fan_speed", "medium");
// @formatter:off
publishMessage("valetudo/rockrobo/state", "{" +
"\"state\":\"returning\"," +
"\"battery_level\":80," +
"\"fan_speed\":\"medium\"" +
"}");
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));
@@ -161,35 +171,37 @@ public class VacuumTests extends AbstractComponentTests {
@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\"" +
"}");
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,
@@ -206,14 +218,16 @@ public class VacuumTests extends AbstractComponentTests {
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\"" +
"}");
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));
@@ -227,14 +241,16 @@ public class VacuumTests extends AbstractComponentTests {
assertPublished("vacuum/command", "turn_on");
// @formatter:off
publishMessage("vacuum/state", "{" +
"\"battery_level\": 55," +
"\"docked\": false," +
"\"cleaning\": true," +
"\"charging\": false," +
"\"fan_speed\": \"medium\"," +
"\"error\": \"\"" +
"}");
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));