add_learn
This commit is contained in:
parent
587ff4c7c5
commit
3744f571d3
|
@ -58,6 +58,13 @@ switch:
|
||||||
output: true
|
output: true
|
||||||
name: "Status obstruction"
|
name: "Status obstruction"
|
||||||
entity_category: diagnostic
|
entity_category: diagnostic
|
||||||
|
- platform: ratgdo
|
||||||
|
id: "${id_prefix}_learn"
|
||||||
|
type: learn
|
||||||
|
ratgdo_id: ${id_prefix}
|
||||||
|
name: "Learn"
|
||||||
|
icon: mdi:plus-box
|
||||||
|
entity_category: diagnostic
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: ratgdo
|
- platform: ratgdo
|
||||||
|
|
|
@ -194,6 +194,16 @@ namespace ratgdo {
|
||||||
this->motion_state = MotionState::CLEAR; // when the status message is read, reset motion state to 0|clear
|
this->motion_state = MotionState::CLEAR; // when the status message is read, reset motion state to 0|clear
|
||||||
this->motor_state = MotorState::OFF; // when the status message is read, reset motor state to 0|off
|
this->motor_state = MotorState::OFF; // when the status message is read, reset motor state to 0|off
|
||||||
|
|
||||||
|
if (*this->learn_state != static_cast<LearnState>((byte2 >> 5) & 1)) {
|
||||||
|
this->learn_state = static_cast<LearnState>((byte2 >> 5) & 1);
|
||||||
|
if (*this->learn_state == LearnState::ACTIVE && this->learn_poll_status_) {
|
||||||
|
set_interval("learn_poll", 1000, [=] { this->send_command(Command::GET_STATUS); });
|
||||||
|
} else {
|
||||||
|
cancel_interval("learn_poll");
|
||||||
|
learn_poll_status_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this->obstruction_from_status_) {
|
if (this->obstruction_from_status_) {
|
||||||
// ESP_LOGD(TAG, "Obstruction: reading from byte2, bit2, status=%d", ((byte2 >> 2) & 1) == 1);
|
// ESP_LOGD(TAG, "Obstruction: reading from byte2, bit2, status=%d", ((byte2 >> 2) & 1) == 1);
|
||||||
this->obstruction_state = static_cast<ObstructionState>((byte1 >> 6) & 1);
|
this->obstruction_state = static_cast<ObstructionState>((byte1 >> 6) & 1);
|
||||||
|
@ -207,10 +217,12 @@ namespace ratgdo {
|
||||||
this->send_command(Command::GET_OPENINGS);
|
this->send_command(Command::GET_OPENINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGD(TAG, "Status: door=%s light=%s lock=%s",
|
ESP_LOGD(TAG, "Status: door=%s light=%s lock=%s learn=%s",
|
||||||
DoorState_to_string(*this->door_state),
|
DoorState_to_string(*this->door_state),
|
||||||
LightState_to_string(*this->light_state),
|
LightState_to_string(*this->light_state),
|
||||||
LockState_to_string(*this->lock_state));
|
LockState_to_string(*this->lock_state),
|
||||||
|
LearnState_to_string(*this->learn_state));
|
||||||
|
|
||||||
} else if (cmd == Command::LIGHT) {
|
} else if (cmd == Command::LIGHT) {
|
||||||
if (nibble == 0) {
|
if (nibble == 0) {
|
||||||
this->light_state = LightState::OFF;
|
this->light_state = LightState::OFF;
|
||||||
|
@ -251,6 +263,11 @@ namespace ratgdo {
|
||||||
auto seconds = (byte1 << 8) | byte2;
|
auto seconds = (byte1 << 8) | byte2;
|
||||||
ESP_LOGD(TAG, "Time to close (TTC): %ds", seconds);
|
ESP_LOGD(TAG, "Time to close (TTC): %ds", seconds);
|
||||||
}
|
}
|
||||||
|
if (cmd == Command::LEARN) {
|
||||||
|
if (nibble == 1) { // LEARN sent from wall control, it will poll status every second
|
||||||
|
learn_poll_status_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
@ -724,6 +741,30 @@ namespace ratgdo {
|
||||||
return *this->light_state;
|
return *this->light_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Learn functions
|
||||||
|
void RATGDOComponent::activate_learn()
|
||||||
|
{
|
||||||
|
// Send LEARN with nibble = 0 then nibble = 1 to mimic wall control learn button
|
||||||
|
learn_poll_status_ = true;
|
||||||
|
this->send_command(Command::LEARN, 0);
|
||||||
|
set_timeout(150, [=] { this->send_command(Command::LEARN, 1); });
|
||||||
|
set_timeout(500, [=] { this->send_command(Command::GET_STATUS); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void RATGDOComponent::inactivate_learn()
|
||||||
|
{
|
||||||
|
// Send LEARN twice with nibble = 0 to inactivate learn and get status to update switch state
|
||||||
|
this->send_command(Command::LEARN, 0);
|
||||||
|
set_timeout(150, [=] { this->send_command(Command::LEARN, 0); });
|
||||||
|
set_timeout(500, [=] { this->send_command(Command::GET_STATUS); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void RATGDOComponent::toggle_learn()
|
||||||
|
{
|
||||||
|
this->learn_state = learn_state_toggle(*this->learn_state);
|
||||||
|
// this->send_command(Command::learn, data::LOCK_TOGGLE);
|
||||||
|
}
|
||||||
|
|
||||||
void RATGDOComponent::subscribe_rolling_code_counter(std::function<void(uint32_t)>&& f)
|
void RATGDOComponent::subscribe_rolling_code_counter(std::function<void(uint32_t)>&& f)
|
||||||
{
|
{
|
||||||
// change update to children is defered until after component loop
|
// change update to children is defered until after component loop
|
||||||
|
@ -779,6 +820,10 @@ namespace ratgdo {
|
||||||
{
|
{
|
||||||
this->sync_failed.subscribe(std::move(f));
|
this->sync_failed.subscribe(std::move(f));
|
||||||
}
|
}
|
||||||
|
void RATGDOComponent::subscribe_learn_state(std::function<void(LearnState)>&& f)
|
||||||
|
{
|
||||||
|
this->learn_state.subscribe([=](LearnState state) { defer("learn_state", [=] { f(state); }); });
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ratgdo
|
} // namespace ratgdo
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
|
@ -64,7 +64,7 @@ namespace ratgdo {
|
||||||
(PAIR_3, 0x0a0),
|
(PAIR_3, 0x0a0),
|
||||||
(PAIR_3_RESP, 0x0a1),
|
(PAIR_3_RESP, 0x0a1),
|
||||||
|
|
||||||
(LEARN_2, 0x181),
|
(LEARN, 0x181),
|
||||||
(LOCK, 0x18c),
|
(LOCK, 0x18c),
|
||||||
(DOOR_ACTION, 0x280),
|
(DOOR_ACTION, 0x280),
|
||||||
(LIGHT, 0x281),
|
(LIGHT, 0x281),
|
||||||
|
@ -124,6 +124,7 @@ namespace ratgdo {
|
||||||
observable<MotorState> motor_state { MotorState::UNKNOWN };
|
observable<MotorState> motor_state { MotorState::UNKNOWN };
|
||||||
observable<ButtonState> button_state { ButtonState::UNKNOWN };
|
observable<ButtonState> button_state { ButtonState::UNKNOWN };
|
||||||
observable<MotionState> motion_state { MotionState::UNKNOWN };
|
observable<MotionState> motion_state { MotionState::UNKNOWN };
|
||||||
|
observable<LearnState> learn_state { LearnState::UNKNOWN };
|
||||||
|
|
||||||
OnceCallbacks<void(DoorState)> door_state_received;
|
OnceCallbacks<void(DoorState)> door_state_received;
|
||||||
OnceCallbacks<void()> command_sent;
|
OnceCallbacks<void()> command_sent;
|
||||||
|
@ -173,6 +174,10 @@ namespace ratgdo {
|
||||||
void lock();
|
void lock();
|
||||||
void unlock();
|
void unlock();
|
||||||
|
|
||||||
|
void toggle_learn();
|
||||||
|
void activate_learn();
|
||||||
|
void inactivate_learn();
|
||||||
|
|
||||||
// button functionality
|
// button functionality
|
||||||
void query_status();
|
void query_status();
|
||||||
void query_openings();
|
void query_openings();
|
||||||
|
@ -191,6 +196,7 @@ namespace ratgdo {
|
||||||
void subscribe_button_state(std::function<void(ButtonState)>&& f);
|
void subscribe_button_state(std::function<void(ButtonState)>&& f);
|
||||||
void subscribe_motion_state(std::function<void(MotionState)>&& f);
|
void subscribe_motion_state(std::function<void(MotionState)>&& f);
|
||||||
void subscribe_sync_failed(std::function<void(bool)>&& f);
|
void subscribe_sync_failed(std::function<void(bool)>&& f);
|
||||||
|
void subscribe_learn_state(std::function<void(LearnState)>&& f);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// tx data
|
// tx data
|
||||||
|
@ -203,6 +209,8 @@ namespace ratgdo {
|
||||||
|
|
||||||
bool obstruction_from_status_ { false };
|
bool obstruction_from_status_ { false };
|
||||||
|
|
||||||
|
bool learn_poll_status_ { true };
|
||||||
|
|
||||||
InternalGPIOPin* output_gdo_pin_;
|
InternalGPIOPin* output_gdo_pin_;
|
||||||
InternalGPIOPin* input_gdo_pin_;
|
InternalGPIOPin* input_gdo_pin_;
|
||||||
InternalGPIOPin* input_obst_pin_;
|
InternalGPIOPin* input_obst_pin_;
|
||||||
|
|
|
@ -31,5 +31,19 @@ namespace ratgdo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LearnState learn_state_toggle(LearnState state)
|
||||||
|
{
|
||||||
|
switch (state) {
|
||||||
|
case LearnState::ACTIVE:
|
||||||
|
return LearnState::INACTIVE;
|
||||||
|
case LearnState::INACTIVE:
|
||||||
|
return LearnState::ACTIVE;
|
||||||
|
// 2 and 3 appears sometimes
|
||||||
|
case LearnState::UNKNOWN:
|
||||||
|
default:
|
||||||
|
return LearnState::UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ratgdo
|
} // namespace ratgdo
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
|
@ -64,5 +64,12 @@ namespace ratgdo {
|
||||||
(RELEASED, 1),
|
(RELEASED, 1),
|
||||||
(UNKNOWN, 2))
|
(UNKNOWN, 2))
|
||||||
|
|
||||||
|
/// Enum for learn states.
|
||||||
|
ENUM(LearnState, uint8_t,
|
||||||
|
(INACTIVE, 0),
|
||||||
|
(ACTIVE, 1),
|
||||||
|
(UNKNOWN, 2))
|
||||||
|
LearnState learn_state_toggle(LearnState state);
|
||||||
|
|
||||||
} // namespace ratgdo
|
} // namespace ratgdo
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import switch
|
||||||
|
from esphome.const import CONF_ID
|
||||||
|
|
||||||
|
from .. import RATGDO_CLIENT_SCHMEA, ratgdo_ns, register_ratgdo_child
|
||||||
|
|
||||||
|
DEPENDENCIES = ["ratgdo"]
|
||||||
|
|
||||||
|
RATGDOSwitch = ratgdo_ns.class_("RATGDOSwitch", switch.Switch, cg.Component)
|
||||||
|
SwitchType = ratgdo_ns.enum("SwitchType")
|
||||||
|
|
||||||
|
CONF_TYPE = "type"
|
||||||
|
TYPES = {
|
||||||
|
"learn": SwitchType.RATGDO_LEARN,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = (
|
||||||
|
switch.switch_schema(RATGDOSwitch)
|
||||||
|
.extend(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_TYPE): cv.enum(TYPES, lower=True),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(RATGDO_CLIENT_SCHMEA)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
await switch.register_switch(var, config)
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
cg.add(var.set_switch_type(config[CONF_TYPE]))
|
||||||
|
await register_ratgdo_child(var, config)
|
|
@ -0,0 +1,46 @@
|
||||||
|
#include "ratgdo_switch.h"
|
||||||
|
#include "../ratgdo_state.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ratgdo {
|
||||||
|
|
||||||
|
static const char* const TAG = "ratgdo.switch";
|
||||||
|
|
||||||
|
void RATGDOSwitch::dump_config()
|
||||||
|
{
|
||||||
|
LOG_SWITCH("", "RATGDO Switch", this);
|
||||||
|
if (this->switch_type_ == SwitchType::RATGDO_LEARN) {
|
||||||
|
ESP_LOGCONFIG(TAG, " Type: Learn");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RATGDOSwitch::setup()
|
||||||
|
{
|
||||||
|
if (this->switch_type_ == SwitchType::RATGDO_LEARN) {
|
||||||
|
this->parent_->subscribe_learn_state([=](LearnState state) {
|
||||||
|
this->on_learn_state(state);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RATGDOSwitch::on_learn_state(LearnState state)
|
||||||
|
{
|
||||||
|
bool value = state == LearnState::ACTIVE;
|
||||||
|
this->state = value;
|
||||||
|
this->publish_state(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RATGDOSwitch::write_state(bool state)
|
||||||
|
{
|
||||||
|
if (this->switch_type_ == SwitchType::RATGDO_LEARN) {
|
||||||
|
if (state) {
|
||||||
|
this->parent_->activate_learn();
|
||||||
|
} else {
|
||||||
|
this->parent_->inactivate_learn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ratgdo
|
||||||
|
} // namespace esphome
|
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../ratgdo.h"
|
||||||
|
#include "../ratgdo_state.h"
|
||||||
|
#include "esphome/components/switch/switch.h"
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ratgdo {
|
||||||
|
|
||||||
|
enum SwitchType {
|
||||||
|
RATGDO_LEARN
|
||||||
|
};
|
||||||
|
|
||||||
|
class RATGDOSwitch : public switch_::Switch, public RATGDOClient, public Component {
|
||||||
|
public:
|
||||||
|
void dump_config() override;
|
||||||
|
void setup() override;
|
||||||
|
void set_switch_type(SwitchType switch_type_) { this->switch_type_ = switch_type_; }
|
||||||
|
|
||||||
|
void on_learn_state(LearnState state);
|
||||||
|
void write_state(bool state) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SwitchType switch_type_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ratgdo
|
||||||
|
} // namespace esphome
|
Loading…
Reference in New Issue