mirror of
https://github.com/esphome/esphome.git
synced 2024-11-10 01:07:45 +01:00
Adds MQTT component to Alarm Control panel component (#7188)
This commit is contained in:
parent
3ba9caa118
commit
7074fa06ae
5 changed files with 260 additions and 75 deletions
|
@ -1,16 +1,17 @@
|
||||||
import esphome.codegen as cg
|
|
||||||
import esphome.config_validation as cv
|
|
||||||
from esphome.components import web_server
|
|
||||||
from esphome import automation
|
from esphome import automation
|
||||||
from esphome.automation import maybe_simple_id
|
from esphome.automation import maybe_simple_id
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
import esphome.codegen as cg
|
||||||
|
from esphome.components import mqtt, web_server
|
||||||
|
import esphome.config_validation as cv
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
|
CONF_CODE,
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
|
CONF_MQTT_ID,
|
||||||
CONF_ON_STATE,
|
CONF_ON_STATE,
|
||||||
CONF_TRIGGER_ID,
|
CONF_TRIGGER_ID,
|
||||||
CONF_CODE,
|
|
||||||
CONF_WEB_SERVER_ID,
|
CONF_WEB_SERVER_ID,
|
||||||
)
|
)
|
||||||
|
from esphome.core import CORE, coroutine_with_priority
|
||||||
from esphome.cpp_helpers import setup_entity
|
from esphome.cpp_helpers import setup_entity
|
||||||
|
|
||||||
CODEOWNERS = ["@grahambrown11", "@hwstar"]
|
CODEOWNERS = ["@grahambrown11", "@hwstar"]
|
||||||
|
@ -77,67 +78,72 @@ AlarmControlPanelCondition = alarm_control_panel_ns.class_(
|
||||||
"AlarmControlPanelCondition", automation.Condition
|
"AlarmControlPanelCondition", automation.Condition
|
||||||
)
|
)
|
||||||
|
|
||||||
ALARM_CONTROL_PANEL_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
|
ALARM_CONTROL_PANEL_SCHEMA = (
|
||||||
web_server.WEBSERVER_SORTING_SCHEMA
|
cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA)
|
||||||
).extend(
|
.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA)
|
||||||
{
|
.extend(
|
||||||
cv.GenerateID(): cv.declare_id(AlarmControlPanel),
|
{
|
||||||
cv.Optional(CONF_ON_STATE): automation.validate_automation(
|
cv.GenerateID(): cv.declare_id(AlarmControlPanel),
|
||||||
{
|
cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger),
|
mqtt.MQTTAlarmControlPanelComponent
|
||||||
}
|
),
|
||||||
),
|
cv.Optional(CONF_ON_STATE): automation.validate_automation(
|
||||||
cv.Optional(CONF_ON_TRIGGERED): automation.validate_automation(
|
{
|
||||||
{
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger),
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TriggeredTrigger),
|
}
|
||||||
}
|
),
|
||||||
),
|
cv.Optional(CONF_ON_TRIGGERED): automation.validate_automation(
|
||||||
cv.Optional(CONF_ON_ARMING): automation.validate_automation(
|
{
|
||||||
{
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TriggeredTrigger),
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmingTrigger),
|
}
|
||||||
}
|
),
|
||||||
),
|
cv.Optional(CONF_ON_ARMING): automation.validate_automation(
|
||||||
cv.Optional(CONF_ON_PENDING): automation.validate_automation(
|
{
|
||||||
{
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmingTrigger),
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PendingTrigger),
|
}
|
||||||
}
|
),
|
||||||
),
|
cv.Optional(CONF_ON_PENDING): automation.validate_automation(
|
||||||
cv.Optional(CONF_ON_ARMED_HOME): automation.validate_automation(
|
{
|
||||||
{
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PendingTrigger),
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedHomeTrigger),
|
}
|
||||||
}
|
),
|
||||||
),
|
cv.Optional(CONF_ON_ARMED_HOME): automation.validate_automation(
|
||||||
cv.Optional(CONF_ON_ARMED_NIGHT): automation.validate_automation(
|
{
|
||||||
{
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedHomeTrigger),
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedNightTrigger),
|
}
|
||||||
}
|
),
|
||||||
),
|
cv.Optional(CONF_ON_ARMED_NIGHT): automation.validate_automation(
|
||||||
cv.Optional(CONF_ON_ARMED_AWAY): automation.validate_automation(
|
{
|
||||||
{
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedNightTrigger),
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedAwayTrigger),
|
}
|
||||||
}
|
),
|
||||||
),
|
cv.Optional(CONF_ON_ARMED_AWAY): automation.validate_automation(
|
||||||
cv.Optional(CONF_ON_DISARMED): automation.validate_automation(
|
{
|
||||||
{
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedAwayTrigger),
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DisarmedTrigger),
|
}
|
||||||
}
|
),
|
||||||
),
|
cv.Optional(CONF_ON_DISARMED): automation.validate_automation(
|
||||||
cv.Optional(CONF_ON_CLEARED): automation.validate_automation(
|
{
|
||||||
{
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DisarmedTrigger),
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ClearedTrigger),
|
}
|
||||||
}
|
),
|
||||||
),
|
cv.Optional(CONF_ON_CLEARED): automation.validate_automation(
|
||||||
cv.Optional(CONF_ON_CHIME): automation.validate_automation(
|
{
|
||||||
{
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ClearedTrigger),
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ChimeTrigger),
|
}
|
||||||
}
|
),
|
||||||
),
|
cv.Optional(CONF_ON_CHIME): automation.validate_automation(
|
||||||
cv.Optional(CONF_ON_READY): automation.validate_automation(
|
{
|
||||||
{
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ChimeTrigger),
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ReadyTrigger),
|
}
|
||||||
}
|
),
|
||||||
),
|
cv.Optional(CONF_ON_READY): automation.validate_automation(
|
||||||
}
|
{
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ReadyTrigger),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
ALARM_CONTROL_PANEL_ACTION_SCHEMA = maybe_simple_id(
|
ALARM_CONTROL_PANEL_ACTION_SCHEMA = maybe_simple_id(
|
||||||
|
@ -192,6 +198,9 @@ async def setup_alarm_control_panel_core_(var, config):
|
||||||
if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None:
|
if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None:
|
||||||
web_server_ = await cg.get_variable(webserver_id)
|
web_server_ = await cg.get_variable(webserver_id)
|
||||||
web_server.add_entity_to_sorting_list(web_server_, var, config)
|
web_server.add_entity_to_sorting_list(web_server_, var, config)
|
||||||
|
if mqtt_id := config.get(CONF_MQTT_ID):
|
||||||
|
mqtt_ = cg.new_Pvariable(mqtt_id, var)
|
||||||
|
await mqtt.register_mqtt_component(mqtt_, config)
|
||||||
|
|
||||||
|
|
||||||
async def register_alarm_control_panel(var, config):
|
async def register_alarm_control_panel(var, config):
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import esphome.codegen as cg
|
|
||||||
import esphome.config_validation as cv
|
|
||||||
from esphome import automation
|
from esphome import automation
|
||||||
from esphome.automation import Condition
|
from esphome.automation import Condition
|
||||||
|
import esphome.codegen as cg
|
||||||
from esphome.components import logger
|
from esphome.components import logger
|
||||||
|
from esphome.components.esp32 import add_idf_sdkconfig_option
|
||||||
|
import esphome.config_validation as cv
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
CONF_AVAILABILITY,
|
CONF_AVAILABILITY,
|
||||||
CONF_BIRTH_MESSAGE,
|
CONF_BIRTH_MESSAGE,
|
||||||
|
@ -13,21 +14,21 @@ from esphome.const import (
|
||||||
CONF_CLIENT_CERTIFICATE,
|
CONF_CLIENT_CERTIFICATE,
|
||||||
CONF_CLIENT_CERTIFICATE_KEY,
|
CONF_CLIENT_CERTIFICATE_KEY,
|
||||||
CONF_CLIENT_ID,
|
CONF_CLIENT_ID,
|
||||||
CONF_COMMAND_TOPIC,
|
|
||||||
CONF_COMMAND_RETAIN,
|
CONF_COMMAND_RETAIN,
|
||||||
|
CONF_COMMAND_TOPIC,
|
||||||
CONF_DISCOVERY,
|
CONF_DISCOVERY,
|
||||||
|
CONF_DISCOVERY_OBJECT_ID_GENERATOR,
|
||||||
CONF_DISCOVERY_PREFIX,
|
CONF_DISCOVERY_PREFIX,
|
||||||
CONF_DISCOVERY_RETAIN,
|
CONF_DISCOVERY_RETAIN,
|
||||||
CONF_DISCOVERY_UNIQUE_ID_GENERATOR,
|
CONF_DISCOVERY_UNIQUE_ID_GENERATOR,
|
||||||
CONF_DISCOVERY_OBJECT_ID_GENERATOR,
|
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
CONF_KEEPALIVE,
|
CONF_KEEPALIVE,
|
||||||
CONF_LEVEL,
|
CONF_LEVEL,
|
||||||
CONF_LOG_TOPIC,
|
CONF_LOG_TOPIC,
|
||||||
CONF_ON_JSON_MESSAGE,
|
|
||||||
CONF_ON_MESSAGE,
|
|
||||||
CONF_ON_CONNECT,
|
CONF_ON_CONNECT,
|
||||||
CONF_ON_DISCONNECT,
|
CONF_ON_DISCONNECT,
|
||||||
|
CONF_ON_JSON_MESSAGE,
|
||||||
|
CONF_ON_MESSAGE,
|
||||||
CONF_PASSWORD,
|
CONF_PASSWORD,
|
||||||
CONF_PAYLOAD,
|
CONF_PAYLOAD,
|
||||||
CONF_PAYLOAD_AVAILABLE,
|
CONF_PAYLOAD_AVAILABLE,
|
||||||
|
@ -45,12 +46,11 @@ from esphome.const import (
|
||||||
CONF_USE_ABBREVIATIONS,
|
CONF_USE_ABBREVIATIONS,
|
||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
CONF_WILL_MESSAGE,
|
CONF_WILL_MESSAGE,
|
||||||
|
PLATFORM_BK72XX,
|
||||||
PLATFORM_ESP32,
|
PLATFORM_ESP32,
|
||||||
PLATFORM_ESP8266,
|
PLATFORM_ESP8266,
|
||||||
PLATFORM_BK72XX,
|
|
||||||
)
|
)
|
||||||
from esphome.core import coroutine_with_priority, CORE
|
from esphome.core import CORE, coroutine_with_priority
|
||||||
from esphome.components.esp32 import add_idf_sdkconfig_option
|
|
||||||
|
|
||||||
DEPENDENCIES = ["network"]
|
DEPENDENCIES = ["network"]
|
||||||
|
|
||||||
|
@ -110,6 +110,9 @@ MQTTDisconnectTrigger = mqtt_ns.class_(
|
||||||
MQTTComponent = mqtt_ns.class_("MQTTComponent", cg.Component)
|
MQTTComponent = mqtt_ns.class_("MQTTComponent", cg.Component)
|
||||||
MQTTConnectedCondition = mqtt_ns.class_("MQTTConnectedCondition", Condition)
|
MQTTConnectedCondition = mqtt_ns.class_("MQTTConnectedCondition", Condition)
|
||||||
|
|
||||||
|
MQTTAlarmControlPanelComponent = mqtt_ns.class_(
|
||||||
|
"MQTTAlarmControlPanelComponent", MQTTComponent
|
||||||
|
)
|
||||||
MQTTBinarySensorComponent = mqtt_ns.class_("MQTTBinarySensorComponent", MQTTComponent)
|
MQTTBinarySensorComponent = mqtt_ns.class_("MQTTBinarySensorComponent", MQTTComponent)
|
||||||
MQTTClimateComponent = mqtt_ns.class_("MQTTClimateComponent", MQTTComponent)
|
MQTTClimateComponent = mqtt_ns.class_("MQTTClimateComponent", MQTTComponent)
|
||||||
MQTTCoverComponent = mqtt_ns.class_("MQTTCoverComponent", MQTTComponent)
|
MQTTCoverComponent = mqtt_ns.class_("MQTTCoverComponent", MQTTComponent)
|
||||||
|
|
128
esphome/components/mqtt/mqtt_alarm_control_panel.cpp
Normal file
128
esphome/components/mqtt/mqtt_alarm_control_panel.cpp
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
#include "mqtt_alarm_control_panel.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
#include "mqtt_const.h"
|
||||||
|
|
||||||
|
#ifdef USE_MQTT
|
||||||
|
#ifdef USE_ALARM_CONTROL_PANEL
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace mqtt {
|
||||||
|
|
||||||
|
static const char *const TAG = "mqtt.alarm_control_panel";
|
||||||
|
|
||||||
|
using namespace esphome::alarm_control_panel;
|
||||||
|
|
||||||
|
MQTTAlarmControlPanelComponent::MQTTAlarmControlPanelComponent(AlarmControlPanel *alarm_control_panel)
|
||||||
|
: alarm_control_panel_(alarm_control_panel) {}
|
||||||
|
void MQTTAlarmControlPanelComponent::setup() {
|
||||||
|
this->alarm_control_panel_->add_on_state_callback([this]() { this->publish_state(); });
|
||||||
|
this->subscribe(this->get_command_topic_(), [this](const std::string &topic, const std::string &payload) {
|
||||||
|
auto call = this->alarm_control_panel_->make_call();
|
||||||
|
if (strcasecmp(payload.c_str(), "ARM_AWAY") == 0) {
|
||||||
|
call.arm_away();
|
||||||
|
} else if (strcasecmp(payload.c_str(), "ARM_HOME") == 0) {
|
||||||
|
call.arm_home();
|
||||||
|
} else if (strcasecmp(payload.c_str(), "ARM_NIGHT") == 0) {
|
||||||
|
call.arm_night();
|
||||||
|
} else if (strcasecmp(payload.c_str(), "ARM_VACATION") == 0) {
|
||||||
|
call.arm_vacation();
|
||||||
|
} else if (strcasecmp(payload.c_str(), "ARM_CUSTOM_BYPASS") == 0) {
|
||||||
|
call.arm_custom_bypass();
|
||||||
|
} else if (strcasecmp(payload.c_str(), "DISARM") == 0) {
|
||||||
|
call.disarm();
|
||||||
|
} else if (strcasecmp(payload.c_str(), "PENDING") == 0) {
|
||||||
|
call.pending();
|
||||||
|
} else if (strcasecmp(payload.c_str(), "TRIGGERED") == 0) {
|
||||||
|
call.triggered();
|
||||||
|
} else {
|
||||||
|
ESP_LOGW(TAG, "'%s': Received unknown command payload %s", this->friendly_name().c_str(), payload.c_str());
|
||||||
|
}
|
||||||
|
call.perform();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MQTTAlarmControlPanelComponent::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG, "MQTT alarm_control_panel '%s':", this->alarm_control_panel_->get_name().c_str());
|
||||||
|
LOG_MQTT_COMPONENT(true, true)
|
||||||
|
ESP_LOGCONFIG(TAG, " Supported Features: %" PRIu32, this->alarm_control_panel_->get_supported_features());
|
||||||
|
ESP_LOGCONFIG(TAG, " Requires Code to Disarm: %s", YESNO(this->alarm_control_panel_->get_requires_code()));
|
||||||
|
ESP_LOGCONFIG(TAG, " Requires Code To Arm: %s", YESNO(this->alarm_control_panel_->get_requires_code_to_arm()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MQTTAlarmControlPanelComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||||
|
JsonArray supported_features = root.createNestedArray(MQTT_SUPPORTED_FEATURES);
|
||||||
|
const uint32_t acp_supported_features = this->alarm_control_panel_->get_supported_features();
|
||||||
|
if (acp_supported_features & ACP_FEAT_ARM_AWAY) {
|
||||||
|
supported_features.add("arm_away");
|
||||||
|
}
|
||||||
|
if (acp_supported_features & ACP_FEAT_ARM_HOME) {
|
||||||
|
supported_features.add("arm_home");
|
||||||
|
}
|
||||||
|
if (acp_supported_features & ACP_FEAT_ARM_NIGHT) {
|
||||||
|
supported_features.add("arm_night");
|
||||||
|
}
|
||||||
|
if (acp_supported_features & ACP_FEAT_ARM_VACATION) {
|
||||||
|
supported_features.add("arm_vacation");
|
||||||
|
}
|
||||||
|
if (acp_supported_features & ACP_FEAT_ARM_CUSTOM_BYPASS) {
|
||||||
|
supported_features.add("arm_custom_bypass");
|
||||||
|
}
|
||||||
|
if (acp_supported_features & ACP_FEAT_TRIGGER) {
|
||||||
|
supported_features.add("trigger");
|
||||||
|
}
|
||||||
|
root[MQTT_CODE_DISARM_REQUIRED] = this->alarm_control_panel_->get_requires_code();
|
||||||
|
root[MQTT_CODE_ARM_REQUIRED] = this->alarm_control_panel_->get_requires_code_to_arm();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MQTTAlarmControlPanelComponent::component_type() const { return "alarm_control_panel"; }
|
||||||
|
const EntityBase *MQTTAlarmControlPanelComponent::get_entity() const { return this->alarm_control_panel_; }
|
||||||
|
|
||||||
|
bool MQTTAlarmControlPanelComponent::send_initial_state() { return this->publish_state(); }
|
||||||
|
bool MQTTAlarmControlPanelComponent::publish_state() {
|
||||||
|
bool success = true;
|
||||||
|
const char *state_s = "";
|
||||||
|
switch (this->alarm_control_panel_->get_state()) {
|
||||||
|
case ACP_STATE_DISARMED:
|
||||||
|
state_s = "disarmed";
|
||||||
|
break;
|
||||||
|
case ACP_STATE_ARMED_HOME:
|
||||||
|
state_s = "armed_home";
|
||||||
|
break;
|
||||||
|
case ACP_STATE_ARMED_AWAY:
|
||||||
|
state_s = "armed_away";
|
||||||
|
break;
|
||||||
|
case ACP_STATE_ARMED_NIGHT:
|
||||||
|
state_s = "armed_night";
|
||||||
|
break;
|
||||||
|
case ACP_STATE_ARMED_VACATION:
|
||||||
|
state_s = "armed_vacation";
|
||||||
|
break;
|
||||||
|
case ACP_STATE_ARMED_CUSTOM_BYPASS:
|
||||||
|
state_s = "armed_custom_bypass";
|
||||||
|
break;
|
||||||
|
case ACP_STATE_PENDING:
|
||||||
|
state_s = "pending";
|
||||||
|
break;
|
||||||
|
case ACP_STATE_ARMING:
|
||||||
|
state_s = "arming";
|
||||||
|
break;
|
||||||
|
case ACP_STATE_DISARMING:
|
||||||
|
state_s = "disarming";
|
||||||
|
break;
|
||||||
|
case ACP_STATE_TRIGGERED:
|
||||||
|
state_s = "triggered";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
state_s = "unknown";
|
||||||
|
}
|
||||||
|
if (!this->publish(this->get_state_topic_(), state_s))
|
||||||
|
success = false;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mqtt
|
||||||
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif // USE_MQTT
|
39
esphome/components/mqtt/mqtt_alarm_control_panel.h
Normal file
39
esphome/components/mqtt/mqtt_alarm_control_panel.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/defines.h"
|
||||||
|
|
||||||
|
#ifdef USE_MQTT
|
||||||
|
#ifdef USE_ALARM_CONTROL_PANEL
|
||||||
|
|
||||||
|
#include "mqtt_component.h"
|
||||||
|
#include "esphome/components/alarm_control_panel/alarm_control_panel.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace mqtt {
|
||||||
|
|
||||||
|
class MQTTAlarmControlPanelComponent : public mqtt::MQTTComponent {
|
||||||
|
public:
|
||||||
|
explicit MQTTAlarmControlPanelComponent(alarm_control_panel::AlarmControlPanel *alarm_control_panel);
|
||||||
|
|
||||||
|
void setup() override;
|
||||||
|
|
||||||
|
void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override;
|
||||||
|
|
||||||
|
bool send_initial_state() override;
|
||||||
|
|
||||||
|
bool publish_state();
|
||||||
|
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string component_type() const override;
|
||||||
|
const EntityBase *get_entity() const override;
|
||||||
|
|
||||||
|
alarm_control_panel::AlarmControlPanel *alarm_control_panel_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mqtt
|
||||||
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif // USE_MQTT
|
|
@ -426,3 +426,9 @@ valve:
|
||||||
} else {
|
} else {
|
||||||
return VALVE_CLOSED;
|
return VALVE_CLOSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alarm_control_panel:
|
||||||
|
- platform: template
|
||||||
|
name: Alarm Control Panel
|
||||||
|
binary_sensors:
|
||||||
|
- input: some_binary_sensor
|
||||||
|
|
Loading…
Reference in a new issue