ESPHome 2026.2.3
Loading...
Searching...
No Matches
mqtt_alarm_control_panel.cpp
Go to the documentation of this file.
2#include "esphome/core/log.h"
4
5#include "mqtt_const.h"
6
7#ifdef USE_MQTT
8#ifdef USE_ALARM_CONTROL_PANEL
9
10namespace esphome::mqtt {
11
12static const char *const TAG = "mqtt.alarm_control_panel";
13
14using namespace esphome::alarm_control_panel;
15
16// Alarm state MQTT strings indexed by AlarmControlPanelState enum (0-9)
17PROGMEM_STRING_TABLE(AlarmMqttStateStrings, "disarmed", "armed_home", "armed_away", "armed_night", "armed_vacation",
18 "armed_custom_bypass", "pending", "arming", "disarming", "triggered", "unknown");
19
20static ProgmemStr alarm_state_to_mqtt_str(AlarmControlPanelState state) {
21 return AlarmMqttStateStrings::get_progmem_str(static_cast<uint8_t>(state), AlarmMqttStateStrings::LAST_INDEX);
22}
23
25 : alarm_control_panel_(alarm_control_panel) {}
27 this->alarm_control_panel_->add_on_state_callback([this]() { this->publish_state(); });
28 this->subscribe(this->get_command_topic_(), [this](const std::string &topic, const std::string &payload) {
29 auto call = this->alarm_control_panel_->make_call();
30 if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("ARM_AWAY")) == 0) {
31 call.arm_away();
32 } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("ARM_HOME")) == 0) {
33 call.arm_home();
34 } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("ARM_NIGHT")) == 0) {
35 call.arm_night();
36 } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("ARM_VACATION")) == 0) {
37 call.arm_vacation();
38 } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("ARM_CUSTOM_BYPASS")) == 0) {
39 call.arm_custom_bypass();
40 } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("DISARM")) == 0) {
41 call.disarm();
42 } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("PENDING")) == 0) {
43 call.pending();
44 } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("TRIGGERED")) == 0) {
45 call.triggered();
46 } else {
47 ESP_LOGW(TAG, "'%s': Received unknown command payload %s", this->friendly_name_().c_str(), payload.c_str());
48 }
49 call.perform();
50 });
51}
52
54 ESP_LOGCONFIG(TAG, "MQTT alarm_control_panel '%s':", this->alarm_control_panel_->get_name().c_str());
55 LOG_MQTT_COMPONENT(true, true);
56 ESP_LOGCONFIG(TAG,
57 " Supported Features: %" PRIu32 "\n"
58 " Requires Code to Disarm: %s\n"
59 " Requires Code To Arm: %s",
63}
64
66 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
67 JsonArray supported_features = root[MQTT_SUPPORTED_FEATURES].to<JsonArray>();
68 const uint32_t acp_supported_features = this->alarm_control_panel_->get_supported_features();
69 if (acp_supported_features & ACP_FEAT_ARM_AWAY) {
70 supported_features.add(ESPHOME_F("arm_away"));
71 }
72 if (acp_supported_features & ACP_FEAT_ARM_HOME) {
73 supported_features.add(ESPHOME_F("arm_home"));
74 }
75 if (acp_supported_features & ACP_FEAT_ARM_NIGHT) {
76 supported_features.add(ESPHOME_F("arm_night"));
77 }
78 if (acp_supported_features & ACP_FEAT_ARM_VACATION) {
79 supported_features.add(ESPHOME_F("arm_vacation"));
80 }
81 if (acp_supported_features & ACP_FEAT_ARM_CUSTOM_BYPASS) {
82 supported_features.add(ESPHOME_F("arm_custom_bypass"));
83 }
84 if (acp_supported_features & ACP_FEAT_TRIGGER) {
85 supported_features.add(ESPHOME_F("trigger"));
86 }
87 root[MQTT_CODE_DISARM_REQUIRED] = this->alarm_control_panel_->get_requires_code();
88 root[MQTT_CODE_ARM_REQUIRED] = this->alarm_control_panel_->get_requires_code_to_arm();
89}
90
92const EntityBase *MQTTAlarmControlPanelComponent::get_entity() const { return this->alarm_control_panel_; }
93
96 char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN];
97 return this->publish(this->get_state_topic_to_(topic_buf),
98 alarm_state_to_mqtt_str(this->alarm_control_panel_->get_state()));
99}
100
101} // namespace esphome::mqtt
102
103#endif
104#endif // USE_MQTT
const StringRef & get_name() const
constexpr const char * c_str() const
Definition string_ref.h:73
void add_on_state_callback(std::function< void()> &&callback)
Add a callback for when the state of the alarm_control_panel changes.
virtual uint32_t get_supported_features() const =0
A numeric representation of the supported features as per HomeAssistant.
AlarmControlPanelState get_state() const
Get the state.
virtual bool get_requires_code_to_arm() const =0
Returns if the alarm_control_panel requires a code to arm.
virtual bool get_requires_code() const =0
Returns if the alarm_control_panel has a code.
AlarmControlPanelCall make_call()
Make a AlarmControlPanelCall.
MQTTAlarmControlPanelComponent(alarm_control_panel::AlarmControlPanel *alarm_control_panel)
void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override
alarm_control_panel::AlarmControlPanel * alarm_control_panel_
bool publish(const std::string &topic, const std::string &payload)
Send a MQTT message.
StringRef get_state_topic_to_(std::span< char, MQTT_DEFAULT_TOPIC_MAX_LEN > buf) const
Get the MQTT state topic into a buffer (no heap allocation for non-lambda custom topics).
const StringRef & friendly_name_() const
Get the friendly name of this MQTT component.
std::string get_command_topic_() const
Get the MQTT topic for listening to commands (allocates std::string).
void subscribe(const std::string &topic, mqtt_callback_t callback, uint8_t qos=0)
Subscribe to a MQTT topic.
bool state
Definition fan.h:2
PROGMEM_STRING_TABLE(AlarmControlPanelStateStrings, "DISARMED", "ARMED_HOME", "ARMED_AWAY", "ARMED_NIGHT", "ARMED_VACATION", "ARMED_CUSTOM_BYPASS", "PENDING", "ARMING", "DISARMING", "TRIGGERED", "UNKNOWN")
MQTT_COMPONENT_TYPE(MQTTAlarmControlPanelComponent, "alarm_control_panel") const EntityBase *MQTTAlarmControlPanelComponent
const __FlashStringHelper * ProgmemStr
Definition progmem.h:26
Simple Helper struct used for Home Assistant MQTT send_discovery().