mirror of
https://github.com/esphome/esphome.git
synced 2024-12-25 15:04:54 +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.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 (
|
||||
CONF_CODE,
|
||||
CONF_ID,
|
||||
CONF_MQTT_ID,
|
||||
CONF_ON_STATE,
|
||||
CONF_TRIGGER_ID,
|
||||
CONF_CODE,
|
||||
CONF_WEB_SERVER_ID,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
|
||||
CODEOWNERS = ["@grahambrown11", "@hwstar"]
|
||||
|
@ -77,67 +78,72 @@ AlarmControlPanelCondition = alarm_control_panel_ns.class_(
|
|||
"AlarmControlPanelCondition", automation.Condition
|
||||
)
|
||||
|
||||
ALARM_CONTROL_PANEL_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
|
||||
web_server.WEBSERVER_SORTING_SCHEMA
|
||||
).extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(AlarmControlPanel),
|
||||
cv.Optional(CONF_ON_STATE): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_TRIGGERED): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TriggeredTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_ARMING): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmingTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_PENDING): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PendingTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_ARMED_HOME): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedHomeTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_ARMED_NIGHT): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedNightTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_ARMED_AWAY): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedAwayTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_DISARMED): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DisarmedTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_CLEARED): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ClearedTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_CHIME): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ChimeTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_READY): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ReadyTrigger),
|
||||
}
|
||||
),
|
||||
}
|
||||
ALARM_CONTROL_PANEL_SCHEMA = (
|
||||
cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA)
|
||||
.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA)
|
||||
.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(AlarmControlPanel),
|
||||
cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(
|
||||
mqtt.MQTTAlarmControlPanelComponent
|
||||
),
|
||||
cv.Optional(CONF_ON_STATE): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_TRIGGERED): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TriggeredTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_ARMING): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmingTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_PENDING): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PendingTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_ARMED_HOME): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedHomeTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_ARMED_NIGHT): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedNightTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_ARMED_AWAY): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedAwayTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_DISARMED): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DisarmedTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_CLEARED): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ClearedTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_CHIME): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ChimeTrigger),
|
||||
}
|
||||
),
|
||||
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(
|
||||
|
@ -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:
|
||||
web_server_ = await cg.get_variable(webserver_id)
|
||||
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):
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import re
|
||||
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import automation
|
||||
from esphome.automation import Condition
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import logger
|
||||
from esphome.components.esp32 import add_idf_sdkconfig_option
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_AVAILABILITY,
|
||||
CONF_BIRTH_MESSAGE,
|
||||
|
@ -13,21 +14,21 @@ from esphome.const import (
|
|||
CONF_CLIENT_CERTIFICATE,
|
||||
CONF_CLIENT_CERTIFICATE_KEY,
|
||||
CONF_CLIENT_ID,
|
||||
CONF_COMMAND_TOPIC,
|
||||
CONF_COMMAND_RETAIN,
|
||||
CONF_COMMAND_TOPIC,
|
||||
CONF_DISCOVERY,
|
||||
CONF_DISCOVERY_OBJECT_ID_GENERATOR,
|
||||
CONF_DISCOVERY_PREFIX,
|
||||
CONF_DISCOVERY_RETAIN,
|
||||
CONF_DISCOVERY_UNIQUE_ID_GENERATOR,
|
||||
CONF_DISCOVERY_OBJECT_ID_GENERATOR,
|
||||
CONF_ID,
|
||||
CONF_KEEPALIVE,
|
||||
CONF_LEVEL,
|
||||
CONF_LOG_TOPIC,
|
||||
CONF_ON_JSON_MESSAGE,
|
||||
CONF_ON_MESSAGE,
|
||||
CONF_ON_CONNECT,
|
||||
CONF_ON_DISCONNECT,
|
||||
CONF_ON_JSON_MESSAGE,
|
||||
CONF_ON_MESSAGE,
|
||||
CONF_PASSWORD,
|
||||
CONF_PAYLOAD,
|
||||
CONF_PAYLOAD_AVAILABLE,
|
||||
|
@ -45,12 +46,11 @@ from esphome.const import (
|
|||
CONF_USE_ABBREVIATIONS,
|
||||
CONF_USERNAME,
|
||||
CONF_WILL_MESSAGE,
|
||||
PLATFORM_BK72XX,
|
||||
PLATFORM_ESP32,
|
||||
PLATFORM_ESP8266,
|
||||
PLATFORM_BK72XX,
|
||||
)
|
||||
from esphome.core import coroutine_with_priority, CORE
|
||||
from esphome.components.esp32 import add_idf_sdkconfig_option
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
|
||||
DEPENDENCIES = ["network"]
|
||||
|
||||
|
@ -110,6 +110,9 @@ MQTTDisconnectTrigger = mqtt_ns.class_(
|
|||
MQTTComponent = mqtt_ns.class_("MQTTComponent", cg.Component)
|
||||
MQTTConnectedCondition = mqtt_ns.class_("MQTTConnectedCondition", Condition)
|
||||
|
||||
MQTTAlarmControlPanelComponent = mqtt_ns.class_(
|
||||
"MQTTAlarmControlPanelComponent", MQTTComponent
|
||||
)
|
||||
MQTTBinarySensorComponent = mqtt_ns.class_("MQTTBinarySensorComponent", MQTTComponent)
|
||||
MQTTClimateComponent = mqtt_ns.class_("MQTTClimateComponent", 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 {
|
||||
return VALVE_CLOSED;
|
||||
}
|
||||
|
||||
alarm_control_panel:
|
||||
- platform: template
|
||||
name: Alarm Control Panel
|
||||
binary_sensors:
|
||||
- input: some_binary_sensor
|
||||
|
|
Loading…
Reference in a new issue