Strip unused sensors and their implementation

This commit is contained in:
2026-05-12 16:26:24 +00:00
parent 19d7a1532e
commit dac704f372
11 changed files with 7 additions and 373 deletions
+2 -74
View File
@@ -84,13 +84,6 @@ CONF_INPUT_GDO = "input_gdo_pin"
DEFAULT_INPUT_GDO = ( DEFAULT_INPUT_GDO = (
"D2" # D2 red control terminal / GarageDoorOpener (UART1 RX) pin is D2 on D1 Mini "D2" # D2 red control terminal / GarageDoorOpener (UART1 RX) pin is D2 on D1 Mini
) )
CONF_INPUT_OBST = "input_obst_pin"
DEFAULT_INPUT_OBST = "D7" # D7 black obstruction sensor terminal
CONF_OBST_SLEEP_LOW = "obst_sleep_low"
CONF_DISCRETE_OPEN_PIN = "discrete_open_pin"
CONF_DISCRETE_CLOSE_PIN = "discrete_close_pin"
CONF_RATGDO_ID = "ratgdo_id" CONF_RATGDO_ID = "ratgdo_id"
@@ -98,33 +91,11 @@ CONF_ON_SYNC_FAILED = "on_sync_failed"
CONF_PROTOCOL = "protocol" CONF_PROTOCOL = "protocol"
PROTOCOL_SECPLUSV1 = "secplusv1"
PROTOCOL_SECPLUSV2 = "secplusv2" PROTOCOL_SECPLUSV2 = "secplusv2"
PROTOCOL_DRYCONTACT = "drycontact" SUPPORTED_PROTOCOLS = [PROTOCOL_SECPLUSV2]
SUPPORTED_PROTOCOLS = [PROTOCOL_SECPLUSV1, PROTOCOL_SECPLUSV2, PROTOCOL_DRYCONTACT]
CONF_DRY_CONTACT_OPEN_SENSOR = "dry_contact_open_sensor"
CONF_DRY_CONTACT_CLOSE_SENSOR = "dry_contact_close_sensor"
CONF_DRY_CONTACT_SENSOR_GROUP = "dry_contact_sensor_group"
def validate_protocol(config): def validate_protocol(config):
if config.get(CONF_PROTOCOL, None) == PROTOCOL_DRYCONTACT and (
CONF_DRY_CONTACT_CLOSE_SENSOR not in config
or CONF_DRY_CONTACT_OPEN_SENSOR not in config
):
raise cv.Invalid(
"dry_contact_close_sensor and dry_contact_open_sensor are required when using protocol drycontact"
)
if config.get(CONF_PROTOCOL, None) != PROTOCOL_DRYCONTACT and (
CONF_DRY_CONTACT_CLOSE_SENSOR in config
or CONF_DRY_CONTACT_OPEN_SENSOR in config
):
raise cv.Invalid(
"dry_contact_close_sensor and dry_contact_open_sensor are only valid when using protocol drycontact"
)
# if config.get(CONF_PROTOCOL, None) == PROTOCOL_DRYCONTACT and CONF_DRY_CONTACT_OPEN_SENSOR not in config:
# raise cv.Invalid("dry_contact_open_sensor is required when using protocol drycontact")
return config return config
@@ -138,12 +109,6 @@ CONFIG_SCHEMA = cv.All(
cv.Optional( cv.Optional(
CONF_INPUT_GDO, default=DEFAULT_INPUT_GDO CONF_INPUT_GDO, default=DEFAULT_INPUT_GDO
): pins.gpio_input_pin_schema, ): pins.gpio_input_pin_schema,
cv.Optional(CONF_INPUT_OBST, default=DEFAULT_INPUT_OBST): cv.Any(
cv.none, pins.gpio_input_pin_schema
),
cv.SplitDefault(CONF_OBST_SLEEP_LOW, esp32=False, esp8266=True): cv.boolean,
cv.Optional(CONF_DISCRETE_OPEN_PIN): pins.gpio_output_pin_schema,
cv.Optional(CONF_DISCRETE_CLOSE_PIN): pins.gpio_output_pin_schema,
cv.Optional(CONF_ON_SYNC_FAILED): automation.validate_automation( cv.Optional(CONF_ON_SYNC_FAILED): automation.validate_automation(
{ {
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SyncFailed), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SyncFailed),
@@ -152,14 +117,6 @@ CONFIG_SCHEMA = cv.All(
cv.Optional(CONF_PROTOCOL, default=PROTOCOL_SECPLUSV2): cv.All( cv.Optional(CONF_PROTOCOL, default=PROTOCOL_SECPLUSV2): cv.All(
vol.In(SUPPORTED_PROTOCOLS) vol.In(SUPPORTED_PROTOCOLS)
), ),
# cv.Inclusive(CONF_DRY_CONTACT_OPEN_SENSOR,CONF_DRY_CONTACT_SENSOR_GROUP): cv.use_id(binary_sensor.BinarySensor),
# cv.Inclusive(CONF_DRY_CONTACT_CLOSE_SENSOR,CONF_DRY_CONTACT_SENSOR_GROUP): cv.use_id(binary_sensor.BinarySensor),
cv.Optional(CONF_DRY_CONTACT_OPEN_SENSOR): cv.use_id(
binary_sensor.BinarySensor
),
cv.Optional(CONF_DRY_CONTACT_CLOSE_SENSOR): cv.use_id(
binary_sensor.BinarySensor
),
} }
).extend(cv.COMPONENT_SCHEMA), ).extend(cv.COMPONENT_SCHEMA),
validate_protocol, validate_protocol,
@@ -184,23 +141,6 @@ async def to_code(config):
cg.add(var.set_output_gdo_pin(pin)) cg.add(var.set_output_gdo_pin(pin))
pin = await cg.gpio_pin_expression(config[CONF_INPUT_GDO]) pin = await cg.gpio_pin_expression(config[CONF_INPUT_GDO])
cg.add(var.set_input_gdo_pin(pin)) cg.add(var.set_input_gdo_pin(pin))
if config.get(CONF_INPUT_OBST):
pin = await cg.gpio_pin_expression(config[CONF_INPUT_OBST])
cg.add(var.set_input_obst_pin(pin))
cg.add(var.set_obst_sleep_low(config[CONF_OBST_SLEEP_LOW]))
if config.get(CONF_DRY_CONTACT_OPEN_SENSOR):
dry_contact_open_sensor = await cg.get_variable(
config[CONF_DRY_CONTACT_OPEN_SENSOR]
)
cg.add(var.set_dry_contact_open_sensor(dry_contact_open_sensor))
if config.get(CONF_DRY_CONTACT_CLOSE_SENSOR):
dry_contact_close_sensor = await cg.get_variable(
config[CONF_DRY_CONTACT_CLOSE_SENSOR]
)
cg.add(var.set_dry_contact_close_sensor(dry_contact_close_sensor))
for conf in config.get(CONF_ON_SYNC_FAILED, []): for conf in config.get(CONF_ON_SYNC_FAILED, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
@@ -228,12 +168,7 @@ async def to_code(config):
version=None, version=None,
) )
if config[CONF_PROTOCOL] == PROTOCOL_SECPLUSV1: cg.add_define("PROTOCOL_SECPLUSV2")
cg.add_build_flag("-DPROTOCOL_SECPLUSV1")
elif config[CONF_PROTOCOL] == PROTOCOL_SECPLUSV2:
cg.add_build_flag("-DPROTOCOL_SECPLUSV2")
elif config[CONF_PROTOCOL] == PROTOCOL_DRYCONTACT:
cg.add_build_flag("-DPROTOCOL_DRYCONTACT")
cg.add(var.init_protocol()) cg.add(var.init_protocol())
# RATGDOComponent::setup() subscribes to door_state # RATGDOComponent::setup() subscribes to door_state
@@ -241,10 +176,3 @@ async def to_code(config):
# Emit observable subscriber count defines after all children register # Emit observable subscriber count defines after all children register
CORE.add_job(_emit_subscriber_defines) CORE.add_job(_emit_subscriber_defines)
if config.get(CONF_DISCRETE_OPEN_PIN):
pin = await cg.gpio_pin_expression(config[CONF_DISCRETE_OPEN_PIN])
cg.add(var.set_discrete_open_pin(pin))
if config.get(CONF_DISCRETE_CLOSE_PIN):
pin = await cg.gpio_pin_expression(config[CONF_DISCRETE_CLOSE_PIN])
cg.add(var.set_discrete_close_pin(pin))
@@ -24,7 +24,6 @@ SensorType = ratgdo_ns.enum("SensorType")
CONF_TYPE = "type" CONF_TYPE = "type"
TYPES = { TYPES = {
"button": SensorType.RATGDO_SENSOR_BUTTON,
"vehicle_detected": SensorType.RATGDO_SENSOR_VEHICLE_DETECTED, "vehicle_detected": SensorType.RATGDO_SENSOR_VEHICLE_DETECTED,
"vehicle_arriving": SensorType.RATGDO_SENSOR_VEHICLE_ARRIVING, "vehicle_arriving": SensorType.RATGDO_SENSOR_VEHICLE_ARRIVING,
"vehicle_leaving": SensorType.RATGDO_SENSOR_VEHICLE_LEAVING, "vehicle_leaving": SensorType.RATGDO_SENSOR_VEHICLE_LEAVING,
@@ -12,11 +12,6 @@ void RATGDOBinarySensor::setup()
this->publish_initial_state(false); this->publish_initial_state(false);
switch (this->binary_sensor_type_) { switch (this->binary_sensor_type_) {
case SensorType::RATGDO_SENSOR_BUTTON:
this->parent_->subscribe_button_state([this](ButtonState state) {
this->publish_state(state == ButtonState::PRESSED);
});
break;
#ifdef RATGDO_USE_VEHICLE_SENSORS #ifdef RATGDO_USE_VEHICLE_SENSORS
case SensorType::RATGDO_SENSOR_VEHICLE_DETECTED: case SensorType::RATGDO_SENSOR_VEHICLE_DETECTED:
this->parent_->subscribe_vehicle_detected_state([this](VehicleDetectedState state) { this->parent_->subscribe_vehicle_detected_state([this](VehicleDetectedState state) {
@@ -44,9 +39,6 @@ void RATGDOBinarySensor::dump_config()
{ {
LOG_BINARY_SENSOR("", "RATGDO BinarySensor", this); LOG_BINARY_SENSOR("", "RATGDO BinarySensor", this);
switch (this->binary_sensor_type_) { switch (this->binary_sensor_type_) {
case SensorType::RATGDO_SENSOR_BUTTON:
ESP_LOGCONFIG(TAG, " Type: Button");
break;
#ifdef RATGDO_USE_VEHICLE_SENSORS #ifdef RATGDO_USE_VEHICLE_SENSORS
case SensorType::RATGDO_SENSOR_VEHICLE_DETECTED: case SensorType::RATGDO_SENSOR_VEHICLE_DETECTED:
ESP_LOGCONFIG(TAG, " Type: VehicleDetected"); ESP_LOGCONFIG(TAG, " Type: VehicleDetected");
@@ -9,9 +9,8 @@
namespace esphome::ratgdo { namespace esphome::ratgdo {
enum SensorType : uint8_t { enum SensorType : uint8_t {
RATGDO_SENSOR_BUTTON = 3,
#ifdef RATGDO_USE_VEHICLE_SENSORS #ifdef RATGDO_USE_VEHICLE_SENSORS
RATGDO_SENSOR_VEHICLE_DETECTED, RATGDO_SENSOR_VEHICLE_DETECTED = 4,
RATGDO_SENSOR_VEHICLE_ARRIVING, RATGDO_SENSOR_VEHICLE_ARRIVING,
RATGDO_SENSOR_VEHICLE_LEAVING, RATGDO_SENSOR_VEHICLE_LEAVING,
#endif #endif
-6
View File
@@ -90,12 +90,6 @@ namespace protocol {
virtual void sync(); virtual void sync();
// dry contact methods
virtual void set_open_limit(bool);
virtual void set_close_limit(bool);
virtual void set_discrete_open_pin(InternalGPIOPin* pin);
virtual void set_discrete_close_pin(InternalGPIOPin* pin);
virtual const Traits& traits() const; virtual const Traits& traits() const;
virtual void light_action(LightAction action); virtual void light_action(LightAction action);
-87
View File
@@ -15,15 +15,7 @@
#include "common.h" #include "common.h"
#include "ratgdo_state.h" #include "ratgdo_state.h"
#ifdef PROTOCOL_DRYCONTACT
#include "dry_contact.h"
#endif
#ifdef PROTOCOL_SECPLUSV1
#include "secplus1.h"
#endif
#ifdef PROTOCOL_SECPLUSV2
#include "secplus2.h" #include "secplus2.h"
#endif
#include "esphome/core/application.h" #include "esphome/core/application.h"
#include "esphome/core/gpio.h" #include "esphome/core/gpio.h"
@@ -80,40 +72,13 @@ void RATGDOComponent::setup()
ESP_LOGD(TAG, "| -| | | | | | | | | | |"); ESP_LOGD(TAG, "| -| | | | | | | | | | |");
ESP_LOGD(TAG, "|__|__|__|__| |_| |_____|____/|_____|"); ESP_LOGD(TAG, "|__|__|__|__| |_| |_____|____/|_____|");
ESP_LOGD(TAG, "https://paulwieland.github.io/ratgdo/"); ESP_LOGD(TAG, "https://paulwieland.github.io/ratgdo/");
this->subscribe_door_state([this](DoorState state, float position) {
#ifdef RATGDO_USE_VEHICLE_SENSORS
if (this->last_door_state_for_presence_ != DoorState::UNKNOWN && state != DoorState::CLOSED && !this->flags_.presence_detect_window_active) {
this->flags_.presence_detect_window_active = true;
this->set_timeout(
TIMEOUT_PRESENCE_DETECT_WINDOW, PRESENCE_DETECT_WINDOW,
[this] { this->flags_.presence_detect_window_active = false; });
}
if (state == DoorState::CLOSED) {
this->set_timeout(
TIMEOUT_PRESENCE_DETECT_WINDOW, PRESENCE_DETECT_WINDOW_AFTER_CLOSE,
[this] { this->flags_.presence_detect_window_active = false; });
}
this->last_door_state_for_presence_ = state;
#endif
});
} }
// initializing protocol, this gets called before setup() because // initializing protocol, this gets called before setup() because
// its children components might require that // its children components might require that
void RATGDOComponent::init_protocol() void RATGDOComponent::init_protocol()
{ {
#ifdef PROTOCOL_SECPLUSV2
this->protocol_ = new secplus2::Secplus2(); this->protocol_ = new secplus2::Secplus2();
#endif
#ifdef PROTOCOL_SECPLUSV1
this->protocol_ = new secplus1::Secplus1();
#endif
#ifdef PROTOCOL_DRYCONTACT
this->protocol_ = new dry_contact::DryContact();
#endif
} }
void RATGDOComponent::loop() void RATGDOComponent::loop()
@@ -239,13 +204,6 @@ void RATGDOComponent::received(const LockState lock_state)
this->lock_state = lock_state; this->lock_state = lock_state;
} }
void RATGDOComponent::received(const ButtonState button_state)
{
ESP_LOGD(TAG, "Button state=%s",
LOG_STR_ARG(ButtonState_to_string(*this->button_state)));
this->button_state = button_state;
}
void RATGDOComponent::received(const LightAction light_action) void RATGDOComponent::received(const LightAction light_action)
{ {
ESP_LOGD(TAG, "Light cmd=%s state=%s", ESP_LOGD(TAG, "Light cmd=%s state=%s",
@@ -270,17 +228,6 @@ void RATGDOComponent::received(const Openings openings)
} }
} }
void RATGDOComponent::received(const TimeToClose ttc)
{
ESP_LOGD(TAG, "Time to close (TTC): %ds", ttc.seconds);
}
void RATGDOComponent::received(const BatteryState battery_state)
{
ESP_LOGD(TAG, "Battery state=%s",
LOG_STR_ARG(BatteryState_to_string(battery_state)));
}
void RATGDOComponent::schedule_door_position_sync(float update_period) void RATGDOComponent::schedule_door_position_sync(float update_period)
{ {
ESP_LOG1( ESP_LOG1(
@@ -423,14 +370,6 @@ void RATGDOComponent::query_openings()
void RATGDOComponent::sync() void RATGDOComponent::sync()
{ {
this->protocol_->sync(); this->protocol_->sync();
// dry contact protocol:
// needed to trigger the intial state of the limit switch sensors
// ideally this would be in drycontact::sync
#ifdef PROTOCOL_DRYCONTACT
this->protocol_->set_open_limit(this->dry_contact_open_sensor_->state);
this->protocol_->set_close_limit(this->dry_contact_close_sensor_->state);
#endif
} }
void RATGDOComponent::set_door_state_expiry() void RATGDOComponent::set_door_state_expiry()
@@ -488,12 +427,7 @@ void RATGDOComponent::door_close()
return; return;
} }
if (this->flags_.obstruction_sensor_detected) {
this->door_action(DoorAction::CLOSE); this->door_action(DoorAction::CLOSE);
} else if (*this->door_state == DoorState::OPEN) {
ESP_LOGD(TAG, "No obstruction sensors detected. Close using TOGGLE.");
this->door_action(DoorAction::TOGGLE);
}
if (*this->closing_duration > 0) { if (*this->closing_duration > 0) {
// query state in case we don't get a status message // query state in case we don't get a status message
@@ -628,25 +562,4 @@ void RATGDOComponent::lock_toggle()
// Subscribe implementations are now templates in ratgdo.h // Subscribe implementations are now templates in ratgdo.h
// dry contact methods
void RATGDOComponent::set_dry_contact_open_sensor(
esphome::binary_sensor::BinarySensor* dry_contact_open_sensor)
{
dry_contact_open_sensor_ = dry_contact_open_sensor;
dry_contact_open_sensor_->add_on_state_callback([this](bool sensor_value) {
this->protocol_->set_open_limit(sensor_value);
this->door_position = 1.0;
});
}
void RATGDOComponent::set_dry_contact_close_sensor(
esphome::binary_sensor::BinarySensor* dry_contact_close_sensor)
{
dry_contact_close_sensor_ = dry_contact_close_sensor;
dry_contact_close_sensor_->add_on_state_callback([this](bool sensor_value) {
this->protocol_->set_close_limit(sensor_value);
this->door_position = 0.0;
});
}
} // namespace esphome::ratgdo } // namespace esphome::ratgdo
+2 -47
View File
@@ -62,15 +62,6 @@ typedef Parented<RATGDOComponent> RATGDOClient;
const float DOOR_POSITION_UNKNOWN = -1.0; const float DOOR_POSITION_UNKNOWN = -1.0;
const float DOOR_DELTA_UNKNOWN = -2.0; const float DOOR_DELTA_UNKNOWN = -2.0;
struct RATGDOStore {
volatile uint32_t obstruction_low_count = 0; // count obstruction low pulses
static void IRAM_ATTR HOT isr_obstruction(RATGDOStore* arg)
{
arg->obstruction_low_count++;
}
};
using protocol::Args; using protocol::Args;
using protocol::Result; using protocol::Result;
@@ -114,7 +105,6 @@ public:
single_observable<LightState> light_state { LightState::UNKNOWN }; single_observable<LightState> light_state { LightState::UNKNOWN };
single_observable<LockState> lock_state { LockState::UNKNOWN }; single_observable<LockState> lock_state { LockState::UNKNOWN };
single_observable<ButtonState> button_state { ButtonState::UNKNOWN };
#ifdef RATGDO_USE_VEHICLE_SENSORS #ifdef RATGDO_USE_VEHICLE_SENSORS
observable<VehicleDetectedState, RATGDO_MAX_VEHICLE_DETECTED_SUBSCRIBERS> vehicle_detected_state { VehicleDetectedState::NO }; observable<VehicleDetectedState, RATGDO_MAX_VEHICLE_DETECTED_SUBSCRIBERS> vehicle_detected_state { VehicleDetectedState::NO };
observable<VehicleArrivingState, RATGDO_MAX_VEHICLE_ARRIVING_SUBSCRIBERS> vehicle_arriving_state { VehicleArrivingState::NO }; observable<VehicleArrivingState, RATGDO_MAX_VEHICLE_ARRIVING_SUBSCRIBERS> vehicle_arriving_state { VehicleArrivingState::NO };
@@ -127,14 +117,6 @@ public:
void set_output_gdo_pin(InternalGPIOPin* pin) { this->output_gdo_pin_ = pin; } void set_output_gdo_pin(InternalGPIOPin* pin) { this->output_gdo_pin_ = pin; }
void set_input_gdo_pin(InternalGPIOPin* pin) { this->input_gdo_pin_ = pin; } void set_input_gdo_pin(InternalGPIOPin* pin) { this->input_gdo_pin_ = pin; }
void set_input_obst_pin(InternalGPIOPin* pin) { this->input_obst_pin_ = pin; }
void set_obst_sleep_low(bool low) { this->flags_.obst_sleep_low = low; }
// dry contact methods
void set_dry_contact_open_sensor(esphome::binary_sensor::BinarySensor* dry_contact_open_sensor_);
void set_dry_contact_close_sensor(esphome::binary_sensor::BinarySensor* dry_contact_close_sensor_);
void set_discrete_open_pin(InternalGPIOPin* pin) { this->protocol_->set_discrete_open_pin(pin); }
void set_discrete_close_pin(InternalGPIOPin* pin) { this->protocol_->set_discrete_close_pin(pin); }
Result call_protocol(Args args); Result call_protocol(Args args);
@@ -142,10 +124,7 @@ public:
void received(const LightState light_state); void received(const LightState light_state);
void received(const LockState lock_state); void received(const LockState lock_state);
void received(const LightAction light_action); void received(const LightAction light_action);
void received(const ButtonState button_state);
void received(const Openings openings); void received(const Openings openings);
void received(const TimeToClose ttc);
void received(const BatteryState pdc);
// door // door
void door_toggle(); void door_toggle();
@@ -154,7 +133,6 @@ public:
void door_stop(); void door_stop();
void door_action(DoorAction action); void door_action(DoorAction action);
void ensure_door_action(DoorAction action, uint32_t delay = 1500);
void door_move_to_position(float position); void door_move_to_position(float position);
void set_door_position(float door_position) { this->door_position = door_position; } void set_door_position(float door_position) { this->door_position = door_position; }
void set_opening_duration(float duration); void set_opening_duration(float duration);
@@ -254,8 +232,6 @@ public:
template <typename F> template <typename F>
void subscribe_lock_state(F&& f); void subscribe_lock_state(F&& f);
template <typename F> template <typename F>
void subscribe_button_state(F&& f);
template <typename F>
void subscribe_sync_failed(F&& f); void subscribe_sync_failed(F&& f);
template <typename F> template <typename F>
void subscribe_door_action_delayed(F&& f); void subscribe_door_action_delayed(F&& f);
@@ -277,22 +253,14 @@ protected:
protocol::Protocol* protocol_; protocol::Protocol* protocol_;
InternalGPIOPin* output_gdo_pin_; InternalGPIOPin* output_gdo_pin_;
InternalGPIOPin* input_gdo_pin_; InternalGPIOPin* input_gdo_pin_;
InternalGPIOPin* input_obst_pin_;
esphome::binary_sensor::BinarySensor* dry_contact_open_sensor_;
esphome::binary_sensor::BinarySensor* dry_contact_close_sensor_;
// 4-byte members
RATGDOStore isr_store_ { };
// Bool members packed into bitfield // Bool members packed into bitfield
struct { struct {
uint8_t obstruction_sensor_detected : 1;
uint8_t obst_sleep_low : 1;
#ifdef RATGDO_USE_VEHICLE_SENSORS #ifdef RATGDO_USE_VEHICLE_SENSORS
uint8_t presence_detect_window_active : 1; uint8_t presence_detect_window_active : 1;
uint8_t reserved : 5; // Reserved for future use uint8_t reserved : 7; // Reserved for future use
#else #else
uint8_t reserved : 6; // Reserved for future use uint8_t reserved : 8; // Reserved for future use
#endif #endif
} flags_ { 0 }; } flags_ { 0 };
@@ -368,19 +336,14 @@ namespace scheduler_ids {
DEFER_OPENINGS, DEFER_OPENINGS,
DEFER_LIGHT_STATE, DEFER_LIGHT_STATE,
DEFER_LOCK_STATE, DEFER_LOCK_STATE,
DEFER_BUTTON_STATE,
// Named timeout IDs (replacing string-based names) // Named timeout IDs (replacing string-based names)
TIMEOUT_DOOR_QUERY_STATE, TIMEOUT_DOOR_QUERY_STATE,
TIMEOUT_DOOR_ACTION, TIMEOUT_DOOR_ACTION,
TIMEOUT_MOVE_TO_POSITION, TIMEOUT_MOVE_TO_POSITION,
// Shared by RATGDOComponent and Secplus1 — safe because only one
// protocol is compiled at a time (#ifdef PROTOCOL_SECPLUSV1) and
// both use ratgdo_ as the scheduler owner.
TIMEOUT_DOOR_STATE_EXPIRY, TIMEOUT_DOOR_STATE_EXPIRY,
TIMEOUT_PRESENCE_DETECT_WINDOW, TIMEOUT_PRESENCE_DETECT_WINDOW,
TIMEOUT_CLEAR_PRESENCE, TIMEOUT_CLEAR_PRESENCE,
TIMEOUT_WALL_PANEL_EMULATION,
TIMEOUT_SYNC, TIMEOUT_SYNC,
}; };
} // namespace scheduler_ids } // namespace scheduler_ids
@@ -466,14 +429,6 @@ void RATGDOComponent::subscribe_lock_state(F&& f)
}); });
} }
template <typename F>
void RATGDOComponent::subscribe_button_state(F&& f)
{
this->button_state.subscribe([this, f](ButtonState state) {
defer(scheduler_ids::DEFER_BUTTON_STATE, [f, state] { f(state); });
});
}
template <typename F> template <typename F>
void RATGDOComponent::subscribe_sync_failed(F&& f) void RATGDOComponent::subscribe_sync_failed(F&& f)
{ {
-15
View File
@@ -44,17 +44,6 @@ ENUM(LockState, uint8_t,
(UNKNOWN, 2)) (UNKNOWN, 2))
LockState lock_state_toggle(LockState state); LockState lock_state_toggle(LockState state);
/// Enum for all states the button can be in.
ENUM(ButtonState, uint8_t,
(PRESSED, 0),
(RELEASED, 1),
(UNKNOWN, 2))
ENUM_SPARSE(BatteryState, uint8_t,
(UNKNOWN, 0),
(CHARGING, 0x6),
(FULL, 0x8))
// actions // actions
ENUM(LightAction, uint8_t, ENUM(LightAction, uint8_t,
(OFF, 0), (OFF, 0),
@@ -94,8 +83,4 @@ struct Openings {
uint8_t flag; uint8_t flag;
}; };
struct TimeToClose {
uint16_t seconds;
};
} // namespace esphome::ratgdo } // namespace esphome::ratgdo
-11
View File
@@ -1,6 +1,4 @@
#ifdef PROTOCOL_SECPLUSV2
#include "secplus2.h" #include "secplus2.h"
#include "ratgdo.h" #include "ratgdo.h"
@@ -281,15 +279,8 @@ namespace secplus2 {
this->ratgdo_->received(to_LockState((cmd.byte2 & 1), LockState::UNKNOWN)); this->ratgdo_->received(to_LockState((cmd.byte2 & 1), LockState::UNKNOWN));
} else if (cmd.type == CommandType::LIGHT) { } else if (cmd.type == CommandType::LIGHT) {
this->ratgdo_->received(to_LightAction(cmd.nibble, LightAction::UNKNOWN)); this->ratgdo_->received(to_LightAction(cmd.nibble, LightAction::UNKNOWN));
} else if (cmd.type == CommandType::DOOR_ACTION) {
auto button_state = (cmd.byte1 & 1) == 1 ? ButtonState::PRESSED : ButtonState::RELEASED;
this->ratgdo_->received(button_state);
} else if (cmd.type == CommandType::OPENINGS) { } else if (cmd.type == CommandType::OPENINGS) {
this->ratgdo_->received(Openings { static_cast<uint16_t>((cmd.byte1 << 8) | cmd.byte2), cmd.nibble }); this->ratgdo_->received(Openings { static_cast<uint16_t>((cmd.byte1 << 8) | cmd.byte2), cmd.nibble });
} else if (cmd.type == CommandType::SET_TTC) {
this->ratgdo_->received(TimeToClose { static_cast<uint16_t>((cmd.byte1 << 8) | cmd.byte2) });
} else if (cmd.type == CommandType::BATTERY_STATUS) {
this->ratgdo_->received(to_BatteryState(cmd.byte1, BatteryState::UNKNOWN));
} }
ESP_LOG1(TAG, "Done handle command: %s", LOG_STR_ARG(CommandType_to_string(cmd.type))); ESP_LOG1(TAG, "Done handle command: %s", LOG_STR_ARG(CommandType_to_string(cmd.type)));
@@ -377,5 +368,3 @@ namespace secplus2 {
} // namespace secplus2 } // namespace secplus2
} // namespace esphome::ratgdo } // namespace esphome::ratgdo
#endif // PROTOCOL_SECPLUSV2
-31
View File
@@ -1,7 +1,5 @@
#pragma once #pragma once
#ifdef PROTOCOL_SECPLUSV2
#include "esphome/core/optional.h" #include "esphome/core/optional.h"
#include "ratgdo_uart.h" #include "ratgdo_uart.h"
@@ -32,32 +30,11 @@ namespace secplus2 {
(UNKNOWN, 0x000), (UNKNOWN, 0x000),
(GET_STATUS, 0x080), (GET_STATUS, 0x080),
(STATUS, 0x081), (STATUS, 0x081),
(OBST_1, 0x084), // sent when an obstruction happens?
(OBST_2, 0x085), // sent when an obstruction happens?
(BATTERY_STATUS, 0x09d),
(PAIR_3, 0x0a0),
(PAIR_3_RESP, 0x0a1),
(LEARN, 0x181),
(LOCK, 0x18c), (LOCK, 0x18c),
(DOOR_ACTION, 0x280), (DOOR_ACTION, 0x280),
(LIGHT, 0x281), (LIGHT, 0x281),
(MOTOR_ON, 0x284),
(MOTION, 0x285),
(GET_PAIRED_DEVICES, 0x307), // nibble 0 for total, 1 wireless, 2 keypads, 3 wall, 4 accessories.
(PAIRED_DEVICES, 0x308), // byte2 holds number of paired devices
(CLEAR_PAIRED_DEVICES, 0x30D), // nibble 0 to clear remotes, 1 keypads, 2 wall, 3 accessories (offset from above)
(LEARN_1, 0x391),
(PING, 0x392),
(PING_RESP, 0x393),
(PAIR_2, 0x400),
(PAIR_2_RESP, 0x401),
(SET_TTC, 0x402), // ttc_in_seconds = (byte1<<8)+byte2
(CANCEL_TTC, 0x408), // ?
(TTC, 0x40a), // Time to close
(GET_OPENINGS, 0x48b), (GET_OPENINGS, 0x48b),
(OPENINGS, 0x48c), // openings = (byte1<<8)+byte2 (OPENINGS, 0x48c), // openings = (byte1<<8)+byte2
) )
@@ -106,12 +83,6 @@ namespace secplus2 {
const Traits& traits() const { return this->traits_; } const Traits& traits() const { return this->traits_; }
// methods not used by secplus2
void set_open_limit(bool state) { }
void set_close_limit(bool state) { }
void set_discrete_open_pin(InternalGPIOPin* pin) { }
void set_discrete_close_pin(InternalGPIOPin* pin) { }
protected: protected:
void increment_rolling_code_counter(int delta = 1); void increment_rolling_code_counter(int delta = 1);
void set_rolling_code_counter(uint32_t counter); void set_rolling_code_counter(uint32_t counter);
@@ -185,5 +156,3 @@ namespace secplus2 {
}; };
} // namespace secplus2 } // namespace secplus2
} // namespace esphome::ratgdo } // namespace esphome::ratgdo
#endif // PROTOCOL_SECPLUSV2
+1 -90
View File
@@ -3,12 +3,7 @@ substitutions:
friendly_name: "Garage Gate" friendly_name: "Garage Gate"
uart_tx_pin: GPIO17 uart_tx_pin: GPIO17
uart_rx_pin: GPIO21 uart_rx_pin: GPIO21
input_obst_pin: GPIO4
status_door_pin: GPIO26 status_door_pin: GPIO26
status_obstruction_pin: GPIO25
dry_contact_open_pin: GPIO13
dry_contact_close_pin: GPIO14
dry_contact_light_pin: GPIO27
web_server: web_server:
include_internal: true include_internal: true
@@ -17,6 +12,7 @@ web_server:
esphome: esphome:
name: garage-gate name: garage-gate
friendly_name: ${friendly_name} friendly_name: ${friendly_name}
name_add_mac_suffix: true
min_version: 2026.2.0 min_version: 2026.2.0
project: project:
name: ratgdo.v32disco_secplus2 name: ratgdo.v32disco_secplus2
@@ -51,7 +47,6 @@ ratgdo:
id: ${id_prefix} id: ${id_prefix}
input_gdo_pin: ${uart_rx_pin} input_gdo_pin: ${uart_rx_pin}
output_gdo_pin: ${uart_tx_pin} output_gdo_pin: ${uart_tx_pin}
input_obst_pin: ${input_obst_pin}
ota: ota:
- platform: web_server - platform: web_server
@@ -80,55 +75,6 @@ logger:
sensor: NONE sensor: NONE
binary_sensor: binary_sensor:
- platform: ratgdo
type: button
id: ${id_prefix}_button
name: "Button"
entity_category: diagnostic
- platform: gpio
id: "${id_prefix}_dry_contact_open"
pin:
number: ${dry_contact_open_pin}
inverted: true
mode:
input: true
pullup: true
name: "Dry contact open"
entity_category: diagnostic
filters:
- delayed_on_off: 500ms
on_press:
then:
script.execute: "${id_prefix}_dry_contact_door_control"
- platform: gpio
id: "${id_prefix}_dry_contact_close"
pin:
number: ${dry_contact_close_pin}
inverted: true
mode:
input: true
pullup: true
name: "Dry contact close"
entity_category: diagnostic
filters:
- delayed_on_off: 500ms
on_press:
then:
script.execute: "${id_prefix}_dry_contact_door_control"
- platform: gpio
id: "${id_prefix}_dry_contact_light"
pin:
number: ${dry_contact_light_pin}
inverted: true
mode:
input: true
pullup: true
name: "Dry contact light"
entity_category: diagnostic
filters:
- delayed_on_off: 500ms
on_press:
- light.toggle: ${id_prefix}_light
- platform: ratgdo - platform: ratgdo
id: ${id_prefix}_vehicle_detected id: ${id_prefix}_vehicle_detected
type: vehicle_detected type: vehicle_detected
@@ -191,15 +137,6 @@ switch:
output: true output: true
name: "Status door" name: "Status door"
entity_category: diagnostic entity_category: diagnostic
- platform: gpio
id: "${id_prefix}_status_obstruction"
internal: true
pin:
number: ${status_obstruction_pin}
mode:
output: true
name: "Status obstruction"
entity_category: diagnostic
- platform: ratgdo - platform: ratgdo
id: ${id_prefix}_led id: ${id_prefix}_led
type: led type: led
@@ -213,32 +150,6 @@ switch:
name: "LASER" name: "LASER"
entity_category: config entity_category: config
script:
- id: "${id_prefix}_dry_contact_door_control"
then:
- delay: 0.1s
- if:
condition:
and:
- binary_sensor.is_on: ${id_prefix}_dry_contact_close
- binary_sensor.is_on: ${id_prefix}_dry_contact_open
then:
- cover.toggle: ${id_prefix}_garage_door
- if:
condition:
and:
- binary_sensor.is_off: ${id_prefix}_dry_contact_close
- binary_sensor.is_on: ${id_prefix}_dry_contact_open
then:
- cover.open: ${id_prefix}_garage_door
- if:
condition:
and:
- binary_sensor.is_on: ${id_prefix}_dry_contact_close
- binary_sensor.is_off: ${id_prefix}_dry_contact_open
then:
- cover.close: ${id_prefix}_garage_door
number: number:
- platform: ratgdo - platform: ratgdo
id: ${id_prefix}_rolling_code_counter id: ${id_prefix}_rolling_code_counter