[mqtt.homeassistant] bring AlarmControlPanel in line with current documentation (#17607)
* [mqtt.homeassistant] bring AlarmControlPanel in line with current documentation Signed-off-by: Cody Cutrer <cody@cutrer.us>pull/17647/head
parent
a1f448eb23
commit
df36e79925
|
@ -12,6 +12,9 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.mqtt.homeassistant.internal.component;
|
package org.openhab.binding.mqtt.homeassistant.internal.component;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.mqtt.generic.values.TextValue;
|
import org.openhab.binding.mqtt.generic.values.TextValue;
|
||||||
|
@ -31,10 +34,29 @@ import com.google.gson.annotations.SerializedName;
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class AlarmControlPanel extends AbstractComponent<AlarmControlPanel.ChannelConfiguration> {
|
public class AlarmControlPanel extends AbstractComponent<AlarmControlPanel.ChannelConfiguration> {
|
||||||
public static final String STATE_CHANNEL_ID = "alarm"; // Randomly chosen channel "ID"
|
public static final String STATE_CHANNEL_ID = "state";
|
||||||
public static final String SWITCH_DISARM_CHANNEL_ID = "disarm"; // Randomly chosen channel "ID"
|
public static final String STATE_CHANNEL_ID_DEPRECATED = "alarm";
|
||||||
public static final String SWITCH_ARM_HOME_CHANNEL_ID = "armhome"; // Randomly chosen channel "ID"
|
public static final String SWITCH_DISARM_CHANNEL_ID = "disarm";
|
||||||
public static final String SWITCH_ARM_AWAY_CHANNEL_ID = "armaway"; // Randomly chosen channel "ID"
|
public static final String SWITCH_ARM_HOME_CHANNEL_ID = "armhome";
|
||||||
|
public static final String SWITCH_ARM_AWAY_CHANNEL_ID = "armaway";
|
||||||
|
|
||||||
|
public static final String FEATURE_ARM_HOME = "arm_home";
|
||||||
|
public static final String FEATURE_ARM_AWAY = "arm_away";
|
||||||
|
public static final String FEATURE_ARM_NIGHT = "arm_night";
|
||||||
|
public static final String FEATURE_ARM_VACATION = "arm_vacation";
|
||||||
|
public static final String FEATURE_ARM_CUSTOM_BYPASS = "arm_custom_bypass";
|
||||||
|
public static final String FEATURE_TRIGGER = "trigger";
|
||||||
|
|
||||||
|
public static final String STATE_ARMED_AWAY = "armed_away";
|
||||||
|
public static final String STATE_ARMED_CUSTOM_BYPASS = "armed_custom_bypass";
|
||||||
|
public static final String STATE_ARMED_HOME = "armed_home";
|
||||||
|
public static final String STATE_ARMED_NIGHT = "armed_night";
|
||||||
|
public static final String STATE_ARMED_VACATION = "armed_vacation";
|
||||||
|
public static final String STATE_ARMING = "arming";
|
||||||
|
public static final String STATE_DISARMED = "disarmed";
|
||||||
|
public static final String STATE_DISARMING = "disarming";
|
||||||
|
public static final String STATE_PENDING = "pending";
|
||||||
|
public static final String STATE_TRIGGERED = "triggered";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration class for MQTT component
|
* Configuration class for MQTT component
|
||||||
|
@ -48,40 +70,73 @@ public class AlarmControlPanel extends AbstractComponent<AlarmControlPanel.Chann
|
||||||
|
|
||||||
@SerializedName("state_topic")
|
@SerializedName("state_topic")
|
||||||
protected String stateTopic = "";
|
protected String stateTopic = "";
|
||||||
@SerializedName("state_disarmed")
|
|
||||||
protected String stateDisarmed = "disarmed";
|
|
||||||
@SerializedName("state_armed_home")
|
|
||||||
protected String stateArmedHome = "armed_home";
|
|
||||||
@SerializedName("state_armed_away")
|
|
||||||
protected String stateArmedAway = "armed_away";
|
|
||||||
@SerializedName("state_pending")
|
|
||||||
protected String statePending = "pending";
|
|
||||||
@SerializedName("state_triggered")
|
|
||||||
protected String stateTriggered = "triggered";
|
|
||||||
|
|
||||||
@SerializedName("command_topic")
|
@SerializedName("command_topic")
|
||||||
protected @Nullable String commandTopic;
|
protected @Nullable String commandTopic;
|
||||||
@SerializedName("payload_disarm")
|
|
||||||
protected String payloadDisarm = "DISARM";
|
|
||||||
@SerializedName("payload_arm_home")
|
|
||||||
protected String payloadArmHome = "ARM_HOME";
|
|
||||||
@SerializedName("payload_arm_away")
|
@SerializedName("payload_arm_away")
|
||||||
protected String payloadArmAway = "ARM_AWAY";
|
protected String payloadArmAway = "ARM_AWAY";
|
||||||
|
@SerializedName("payload_arm_home")
|
||||||
|
protected String payloadArmHome = "ARM_HOME";
|
||||||
|
@SerializedName("payload_arm_night")
|
||||||
|
protected String payloadArmNight = "ARM_NIGHT";
|
||||||
|
@SerializedName("payload_arm_vacation")
|
||||||
|
protected String payloadArmVacation = "ARM_VACATION";
|
||||||
|
@SerializedName("payload_arm_custom_bypass")
|
||||||
|
protected String payloadArmCustomBypass = "ARM_CUSTOM_BYPASS";
|
||||||
|
@SerializedName("payload_disarm")
|
||||||
|
protected String payloadDisarm = "DISARM";
|
||||||
|
@SerializedName("payload_trigger")
|
||||||
|
protected String payloadTrigger = "TRIGGER";
|
||||||
|
|
||||||
|
@SerializedName("supported_features")
|
||||||
|
protected List<String> supportedFeatures = List.of(FEATURE_ARM_HOME, FEATURE_ARM_AWAY, FEATURE_ARM_NIGHT,
|
||||||
|
FEATURE_ARM_VACATION, FEATURE_ARM_CUSTOM_BYPASS, FEATURE_TRIGGER);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AlarmControlPanel(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) {
|
public AlarmControlPanel(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) {
|
||||||
super(componentConfiguration, ChannelConfiguration.class, newStyleChannels);
|
super(componentConfiguration, ChannelConfiguration.class, newStyleChannels);
|
||||||
|
|
||||||
final String[] stateEnum = { channelConfiguration.stateDisarmed, channelConfiguration.stateArmedHome,
|
List<String> stateEnum = new ArrayList(List.of(STATE_DISARMED, STATE_TRIGGERED, STATE_ARMING, STATE_DISARMING,
|
||||||
channelConfiguration.stateArmedAway, channelConfiguration.statePending,
|
STATE_PENDING, STATE_TRIGGERED));
|
||||||
channelConfiguration.stateTriggered };
|
List<String> commandEnum = new ArrayList(List.of(channelConfiguration.payloadDisarm));
|
||||||
buildChannel(STATE_CHANNEL_ID, ComponentChannelType.STRING, new TextValue(stateEnum), getName(),
|
if (channelConfiguration.supportedFeatures.contains(FEATURE_ARM_HOME)) {
|
||||||
componentConfiguration.getUpdateListener())
|
stateEnum.add(STATE_ARMED_HOME);
|
||||||
.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())//
|
commandEnum.add(channelConfiguration.payloadArmHome);
|
||||||
.build();
|
}
|
||||||
|
if (channelConfiguration.supportedFeatures.contains(FEATURE_ARM_AWAY)) {
|
||||||
|
stateEnum.add(STATE_ARMED_AWAY);
|
||||||
|
commandEnum.add(channelConfiguration.payloadArmAway);
|
||||||
|
}
|
||||||
|
if (channelConfiguration.supportedFeatures.contains(FEATURE_ARM_NIGHT)) {
|
||||||
|
stateEnum.add(STATE_ARMED_NIGHT);
|
||||||
|
commandEnum.add(channelConfiguration.payloadArmNight);
|
||||||
|
}
|
||||||
|
if (channelConfiguration.supportedFeatures.contains(FEATURE_ARM_VACATION)) {
|
||||||
|
stateEnum.add(STATE_ARMED_VACATION);
|
||||||
|
commandEnum.add(channelConfiguration.payloadArmVacation);
|
||||||
|
}
|
||||||
|
if (channelConfiguration.supportedFeatures.contains(FEATURE_ARM_CUSTOM_BYPASS)) {
|
||||||
|
stateEnum.add(STATE_ARMED_CUSTOM_BYPASS);
|
||||||
|
commandEnum.add(channelConfiguration.payloadArmCustomBypass);
|
||||||
|
}
|
||||||
|
if (channelConfiguration.supportedFeatures.contains(FEATURE_TRIGGER)) {
|
||||||
|
commandEnum.add(channelConfiguration.payloadTrigger);
|
||||||
|
}
|
||||||
|
|
||||||
String commandTopic = channelConfiguration.commandTopic;
|
String commandTopic = channelConfiguration.commandTopic;
|
||||||
if (commandTopic != null) {
|
TextValue value = (newStyleChannels && commandTopic != null)
|
||||||
|
? new TextValue(stateEnum.toArray(new String[0]), commandEnum.toArray(new String[0]))
|
||||||
|
: new TextValue(stateEnum.toArray(new String[0]));
|
||||||
|
var builder = buildChannel(newStyleChannels ? STATE_CHANNEL_ID : STATE_CHANNEL_ID_DEPRECATED,
|
||||||
|
ComponentChannelType.STRING, value, getName(), componentConfiguration.getUpdateListener())
|
||||||
|
.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate());
|
||||||
|
|
||||||
|
if (newStyleChannels && commandTopic != null) {
|
||||||
|
builder.commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos());
|
||||||
|
}
|
||||||
|
builder.build();
|
||||||
|
|
||||||
|
if (!newStyleChannels && commandTopic != null) {
|
||||||
buildChannel(SWITCH_DISARM_CHANNEL_ID, ComponentChannelType.STRING,
|
buildChannel(SWITCH_DISARM_CHANNEL_ID, ComponentChannelType.STRING,
|
||||||
new TextValue(new String[] { channelConfiguration.payloadDisarm }), getName(),
|
new TextValue(new String[] { channelConfiguration.payloadDisarm }), getName(),
|
||||||
componentConfiguration.getUpdateListener())
|
componentConfiguration.getUpdateListener())
|
||||||
|
@ -97,6 +152,7 @@ public class AlarmControlPanel extends AbstractComponent<AlarmControlPanel.Chann
|
||||||
componentConfiguration.getUpdateListener())
|
componentConfiguration.getUpdateListener())
|
||||||
.commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()).build();
|
.commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
finalizeChannels();
|
finalizeChannels();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2024 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.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.openhab.binding.mqtt.generic.values.TextValue;
|
||||||
|
import org.openhab.core.library.types.StringType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link AlarmControlPanel}
|
||||||
|
*
|
||||||
|
* @author Anton Kharuzhy - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class AlarmControlPanelDeprecatedTests extends AbstractComponentTests {
|
||||||
|
public static final String CONFIG_TOPIC = "alarm_control_panel/0x0000000000000000_alarm_control_panel_zigbee2mqtt";
|
||||||
|
|
||||||
|
@SuppressWarnings("null")
|
||||||
|
@Test
|
||||||
|
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" \
|
||||||
|
} \
|
||||||
|
""");
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
|
assertThat(component.channels.size(), is(4));
|
||||||
|
assertThat(component.getName(), is("alarm"));
|
||||||
|
|
||||||
|
assertChannel(component, AlarmControlPanel.STATE_CHANNEL_ID_DEPRECATED, "zigbee2mqtt/alarm/state", "", "alarm",
|
||||||
|
TextValue.class);
|
||||||
|
assertChannel(component, AlarmControlPanel.SWITCH_DISARM_CHANNEL_ID, "", "zigbee2mqtt/alarm/set/state", "alarm",
|
||||||
|
TextValue.class);
|
||||||
|
assertChannel(component, AlarmControlPanel.SWITCH_ARM_AWAY_CHANNEL_ID, "", "zigbee2mqtt/alarm/set/state",
|
||||||
|
"alarm", TextValue.class);
|
||||||
|
assertChannel(component, AlarmControlPanel.SWITCH_ARM_HOME_CHANNEL_ID, "", "zigbee2mqtt/alarm/set/state",
|
||||||
|
"alarm", TextValue.class);
|
||||||
|
|
||||||
|
publishMessage("zigbee2mqtt/alarm/state", "armed_home");
|
||||||
|
assertState(component, AlarmControlPanel.STATE_CHANNEL_ID_DEPRECATED, new StringType("armed_home"));
|
||||||
|
publishMessage("zigbee2mqtt/alarm/state", "armed_away");
|
||||||
|
assertState(component, AlarmControlPanel.STATE_CHANNEL_ID_DEPRECATED, new StringType("armed_away"));
|
||||||
|
|
||||||
|
component.getChannel(AlarmControlPanel.SWITCH_DISARM_CHANNEL_ID).getState()
|
||||||
|
.publishValue(new StringType("DISARM_"));
|
||||||
|
assertPublished("zigbee2mqtt/alarm/set/state", "DISARM_");
|
||||||
|
component.getChannel(AlarmControlPanel.SWITCH_ARM_AWAY_CHANNEL_ID).getState()
|
||||||
|
.publishValue(new StringType("ARM_AWAY_"));
|
||||||
|
assertPublished("zigbee2mqtt/alarm/set/state", "ARM_AWAY_");
|
||||||
|
component.getChannel(AlarmControlPanel.SWITCH_ARM_HOME_CHANNEL_ID).getState()
|
||||||
|
.publishValue(new StringType("ARM_HOME_"));
|
||||||
|
assertPublished("zigbee2mqtt/alarm/set/state", "ARM_HOME_");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Set<String> getConfigTopics() {
|
||||||
|
return Set.of(CONFIG_TOPIC);
|
||||||
|
}
|
||||||
|
}
|
|
@ -65,31 +65,22 @@ public class AlarmControlPanelTests extends AbstractComponentTests {
|
||||||
""");
|
""");
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
assertThat(component.channels.size(), is(4));
|
assertThat(component.channels.size(), is(1));
|
||||||
assertThat(component.getName(), is("alarm"));
|
assertThat(component.getName(), is("alarm"));
|
||||||
|
|
||||||
assertChannel(component, AlarmControlPanel.STATE_CHANNEL_ID, "zigbee2mqtt/alarm/state", "", "alarm",
|
assertChannel(component, AlarmControlPanel.STATE_CHANNEL_ID, "zigbee2mqtt/alarm/state",
|
||||||
TextValue.class);
|
"zigbee2mqtt/alarm/set/state", "alarm", TextValue.class);
|
||||||
assertChannel(component, AlarmControlPanel.SWITCH_DISARM_CHANNEL_ID, "", "zigbee2mqtt/alarm/set/state", "alarm",
|
|
||||||
TextValue.class);
|
|
||||||
assertChannel(component, AlarmControlPanel.SWITCH_ARM_AWAY_CHANNEL_ID, "", "zigbee2mqtt/alarm/set/state",
|
|
||||||
"alarm", TextValue.class);
|
|
||||||
assertChannel(component, AlarmControlPanel.SWITCH_ARM_HOME_CHANNEL_ID, "", "zigbee2mqtt/alarm/set/state",
|
|
||||||
"alarm", TextValue.class);
|
|
||||||
|
|
||||||
publishMessage("zigbee2mqtt/alarm/state", "armed_home");
|
publishMessage("zigbee2mqtt/alarm/state", "armed_home");
|
||||||
assertState(component, AlarmControlPanel.STATE_CHANNEL_ID, new StringType("armed_home"));
|
assertState(component, AlarmControlPanel.STATE_CHANNEL_ID, new StringType("armed_home"));
|
||||||
publishMessage("zigbee2mqtt/alarm/state", "armed_away");
|
publishMessage("zigbee2mqtt/alarm/state", "armed_away");
|
||||||
assertState(component, AlarmControlPanel.STATE_CHANNEL_ID, new StringType("armed_away"));
|
assertState(component, AlarmControlPanel.STATE_CHANNEL_ID, new StringType("armed_away"));
|
||||||
|
|
||||||
component.getChannel(AlarmControlPanel.SWITCH_DISARM_CHANNEL_ID).getState()
|
component.getChannel(AlarmControlPanel.STATE_CHANNEL_ID).getState().publishValue(new StringType("DISARM_"));
|
||||||
.publishValue(new StringType("DISARM_"));
|
|
||||||
assertPublished("zigbee2mqtt/alarm/set/state", "DISARM_");
|
assertPublished("zigbee2mqtt/alarm/set/state", "DISARM_");
|
||||||
component.getChannel(AlarmControlPanel.SWITCH_ARM_AWAY_CHANNEL_ID).getState()
|
component.getChannel(AlarmControlPanel.STATE_CHANNEL_ID).getState().publishValue(new StringType("ARM_AWAY_"));
|
||||||
.publishValue(new StringType("ARM_AWAY_"));
|
|
||||||
assertPublished("zigbee2mqtt/alarm/set/state", "ARM_AWAY_");
|
assertPublished("zigbee2mqtt/alarm/set/state", "ARM_AWAY_");
|
||||||
component.getChannel(AlarmControlPanel.SWITCH_ARM_HOME_CHANNEL_ID).getState()
|
component.getChannel(AlarmControlPanel.STATE_CHANNEL_ID).getState().publishValue(new StringType("ARM_HOME_"));
|
||||||
.publishValue(new StringType("ARM_HOME_"));
|
|
||||||
assertPublished("zigbee2mqtt/alarm/set/state", "ARM_HOME_");
|
assertPublished("zigbee2mqtt/alarm/set/state", "ARM_HOME_");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,4 +88,9 @@ public class AlarmControlPanelTests extends AbstractComponentTests {
|
||||||
protected Set<String> getConfigTopics() {
|
protected Set<String> getConfigTopics() {
|
||||||
return Set.of(CONFIG_TOPIC);
|
return Set.of(CONFIG_TOPIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean useNewStyleChannels() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue