From 01a4a41809a9cb3194dc9d14d65c4aff29803ef2 Mon Sep 17 00:00:00 2001
From: Paul Wieland
Date: Thu, 11 Jul 2024 16:36:21 -0400
Subject: [PATCH] Add an emulation switch toggle to the web UI
---
base_secplusv1.yaml | 6 ++++++
components/ratgdo/ratgdo.cpp | 4 ++++
components/ratgdo/ratgdo.h | 2 ++
components/ratgdo/ratgdo_state.h | 4 ++++
components/ratgdo/switch/__init__.py | 1 +
components/ratgdo/switch/ratgdo_switch.cpp | 19 +++++++++++++++++++
components/ratgdo/switch/ratgdo_switch.h | 4 +++-
7 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/base_secplusv1.yaml b/base_secplusv1.yaml
index aafdaa8..5f1a95e 100644
--- a/base_secplusv1.yaml
+++ b/base_secplusv1.yaml
@@ -59,6 +59,12 @@ switch:
output: true
name: "Status obstruction"
entity_category: diagnostic
+ - platform: ratgdo
+ type: emulation
+ id: "${id_prefix}_emulation_enabled"
+ ratgdo_id: ${id_prefix}
+ name: "Emulation Mode"
+ entity_category: config
binary_sensor:
- platform: ratgdo
diff --git a/components/ratgdo/ratgdo.cpp b/components/ratgdo/ratgdo.cpp
index 0327658..8b4f86e 100644
--- a/components/ratgdo/ratgdo.cpp
+++ b/components/ratgdo/ratgdo.cpp
@@ -679,6 +679,10 @@ namespace ratgdo {
{
this->learn_state.subscribe([=](LearnState state) { defer("learn_state", [=] { f(state); }); });
}
+ void RATGDOComponent::subscribe_emulation_state(std::function&& f)
+ {
+ this->emulation_state.subscribe([=](EmulationState state) { defer("emulation_state", [=] { f(state); }); });
+ }
// dry contact methods
void RATGDOComponent::set_dry_contact_open_sensor(esphome::gpio::GPIOBinarySensor* dry_contact_open_sensor)
diff --git a/components/ratgdo/ratgdo.h b/components/ratgdo/ratgdo.h
index 4f9611d..ccb5b20 100644
--- a/components/ratgdo/ratgdo.h
+++ b/components/ratgdo/ratgdo.h
@@ -83,6 +83,7 @@ namespace ratgdo {
observable button_state { ButtonState::UNKNOWN };
observable motion_state { MotionState::UNKNOWN };
observable learn_state { LearnState::UNKNOWN };
+ observable emulation_state { EmulationState::INACTIVE };
OnceCallbacks on_door_state_;
@@ -172,6 +173,7 @@ namespace ratgdo {
void subscribe_motion_state(std::function&& f);
void subscribe_sync_failed(std::function&& f);
void subscribe_learn_state(std::function&& f);
+ void subscribe_emulation_state(std::function&& f);
protected:
RATGDOStore isr_store_ {};
diff --git a/components/ratgdo/ratgdo_state.h b/components/ratgdo/ratgdo_state.h
index f71440a..2547ca9 100644
--- a/components/ratgdo/ratgdo_state.h
+++ b/components/ratgdo/ratgdo_state.h
@@ -76,6 +76,10 @@ namespace ratgdo {
(UNKNOWN, 2))
LearnState learn_state_toggle(LearnState state);
+ ENUM(EmulationState, uint8_t,
+ (INACTIVE, 0),
+ (ACTIVE, 1))
+
ENUM(PairedDevice, uint8_t,
(ALL, 0),
(REMOTE, 1),
diff --git a/components/ratgdo/switch/__init__.py b/components/ratgdo/switch/__init__.py
index 9028cca..b7ecb68 100644
--- a/components/ratgdo/switch/__init__.py
+++ b/components/ratgdo/switch/__init__.py
@@ -13,6 +13,7 @@ SwitchType = ratgdo_ns.enum("SwitchType")
CONF_TYPE = "type"
TYPES = {
"learn": SwitchType.RATGDO_LEARN,
+ "emulation": SwitchType.RATGDO_EMULATION
}
diff --git a/components/ratgdo/switch/ratgdo_switch.cpp b/components/ratgdo/switch/ratgdo_switch.cpp
index b0f911c..a89468c 100644
--- a/components/ratgdo/switch/ratgdo_switch.cpp
+++ b/components/ratgdo/switch/ratgdo_switch.cpp
@@ -4,6 +4,7 @@
namespace esphome {
namespace ratgdo {
+ using protocol::SetEnableEmulationMode;
static const char* const TAG = "ratgdo.switch";
@@ -21,6 +22,18 @@ namespace ratgdo {
this->parent_->subscribe_learn_state([=](LearnState state) {
this->publish_state(state == LearnState::ACTIVE);
});
+ } else if (this->switch_type_ == SwitchType::RATGDO_EMULATION) {
+ bool value = false;
+ this->pref_ = global_preferences->make_preference(this->get_object_id_hash());
+ this->pref_.load(&value);
+ this->state = value;
+ this->parent_->emulation_state = value ? EmulationState::ACTIVE : EmulationState::INACTIVE;
+
+ this->parent_->subscribe_emulation_state([=](EmulationState state) {
+ this->publish_state(state == EmulationState::ACTIVE);
+ });
+
+ this->parent_->call_protocol(SetEnableEmulationMode { static_cast(this->state) });
}
}
@@ -32,6 +45,12 @@ namespace ratgdo {
} else {
this->parent_->inactivate_learn();
}
+ } else if (this->switch_type_ == SwitchType::RATGDO_EMULATION) {
+ this->state = state;
+ this->parent_->emulation_state = state ? EmulationState::ACTIVE : EmulationState::INACTIVE;
+ this->parent_->call_protocol(SetEnableEmulationMode { static_cast(state) });
+
+ this->pref_.save(&state);
}
}
diff --git a/components/ratgdo/switch/ratgdo_switch.h b/components/ratgdo/switch/ratgdo_switch.h
index 3640bec..499e80c 100644
--- a/components/ratgdo/switch/ratgdo_switch.h
+++ b/components/ratgdo/switch/ratgdo_switch.h
@@ -9,7 +9,8 @@ namespace esphome {
namespace ratgdo {
enum SwitchType {
- RATGDO_LEARN
+ RATGDO_LEARN,
+ RATGDO_EMULATION
};
class RATGDOSwitch : public switch_::Switch, public RATGDOClient, public Component {
@@ -22,6 +23,7 @@ namespace ratgdo {
protected:
SwitchType switch_type_;
+ ESPPreferenceObject pref_;
};
} // namespace ratgdo