From cea8820d4fdd1674a5ab1a494b050d6ea63cecdd Mon Sep 17 00:00:00 2001 From: Paul Wieland
Date: Tue, 16 Apr 2024 14:02:52 -0400
Subject: [PATCH] Add triple button (discrete) control for commercial openers &
gates
---
base_drycontact.yaml | 56 ++-----------------------------
components/ratgdo/__init__.py | 12 +++++++
components/ratgdo/dry_contact.cpp | 16 ++++++++-
components/ratgdo/dry_contact.h | 14 ++++++++
components/ratgdo/protocol.h | 3 ++
components/ratgdo/ratgdo.h | 9 +++--
v25iboard_drycontact.yaml | 5 ++-
7 files changed, 54 insertions(+), 61 deletions(-)
diff --git a/base_drycontact.yaml b/base_drycontact.yaml
index e82925b..cecac5a 100644
--- a/base_drycontact.yaml
+++ b/base_drycontact.yaml
@@ -17,51 +17,17 @@ ratgdo:
input_obst_pin: ${input_obst_pin}
dry_contact_open_sensor: ${id_prefix}_dry_contact_open
dry_contact_close_sensor: ${id_prefix}_dry_contact_close
+ discrete_open_pin: ${discrete_open_pin}
+ discrete_close_pin: ${discrete_close_pin}
protocol: drycontact
-switch:
- # - platform: gpio
- # id: "${id_prefix}_status_door"
- # internal: true
- # pin:
- # number: ${status_door_pin}
- # mode:
- # output: true
- # name: "Status door"
- # 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
-
binary_sensor:
- # - platform: ratgdo
- # type: motion
- # id: ${id_prefix}_motion
- # ratgdo_id: ${id_prefix}
- # name: "Motion"
- # device_class: motion
- platform: ratgdo
type: obstruction
id: ${id_prefix}_obstruction
ratgdo_id: ${id_prefix}
name: "Obstruction"
device_class: problem
- # on_press:
- # - switch.turn_on: ${id_prefix}_status_obstruction
- # on_release:
- # - switch.turn_off: ${id_prefix}_status_obstruction
- # - platform: ratgdo
- # type: button
- # id: ${id_prefix}_button
- # ratgdo_id: ${id_prefix}
- # name: "Button"
- # entity_category: diagnostic
- platform: gpio
id: "${id_prefix}_dry_contact_open"
pin:
@@ -86,20 +52,6 @@ binary_sensor:
entity_category: diagnostic
filters:
- delayed_on_off: 500ms
- # - 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
number:
- platform: ratgdo
@@ -124,10 +76,6 @@ cover:
device_class: garage
name: "Door"
ratgdo_id: ${id_prefix}
- # on_closed:
- # - switch.turn_off: ${id_prefix}_status_door
- # on_open:
- # - switch.turn_on: ${id_prefix}_status_door
button:
- platform: restart
diff --git a/components/ratgdo/__init__.py b/components/ratgdo/__init__.py
index 44a5f9a..7dbf9c3 100644
--- a/components/ratgdo/__init__.py
+++ b/components/ratgdo/__init__.py
@@ -26,6 +26,9 @@ DEFAULT_INPUT_GDO = (
CONF_INPUT_OBST = "input_obst_pin"
DEFAULT_INPUT_OBST = "D7" # D7 black obstruction sensor terminal
+CONF_DISCRETE_OPEN_PIN = "discrete_open_pin"
+CONF_DISCRETE_CLOSE_PIN = "discrete_close_pin"
+
CONF_RATGDO_ID = "ratgdo_id"
CONF_ON_SYNC_FAILED = "on_sync_failed"
@@ -64,6 +67,8 @@ CONFIG_SCHEMA = cv.All(
cv.Optional(CONF_INPUT_OBST, default=DEFAULT_INPUT_OBST): cv.Any(
cv.none, pins.gpio_input_pin_schema
),
+ 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.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SyncFailed),
@@ -134,3 +139,10 @@ async def to_code(config):
elif config[CONF_PROTOCOL] == PROTOCOL_DRYCONTACT:
cg.add_define("PROTOCOL_DRYCONTACT")
cg.add(var.init_protocol())
+
+ if CONF_DISCRETE_OPEN_PIN in config and config[CONF_DISCRETE_OPEN_PIN]:
+ pin = await cg.gpio_pin_expression(config[CONF_DISCRETE_OPEN_PIN])
+ cg.add(var.set_discrete_open_pin(pin))
+ if CONF_DISCRETE_CLOSE_PIN in config and config[CONF_DISCRETE_CLOSE_PIN]:
+ pin = await cg.gpio_pin_expression(config[CONF_DISCRETE_CLOSE_PIN])
+ cg.add(var.set_discrete_close_pin(pin))
\ No newline at end of file
diff --git a/components/ratgdo/dry_contact.cpp b/components/ratgdo/dry_contact.cpp
index 159506f..9860e16 100644
--- a/components/ratgdo/dry_contact.cpp
+++ b/components/ratgdo/dry_contact.cpp
@@ -102,7 +102,21 @@ namespace ratgdo {
ESP_LOG1(TAG, "Door action: %s", DoorAction_to_string(action));
- this->tx_pin_->digital_write(1);
+ if (action == DoorAction::OPEN){
+ this->discrete_open_pin_->digital_write(1);
+ this->scheduler_->set_timeout(this->ratgdo_, "", 500, [=] {
+ this->discrete_open_pin_->digital_write(0);
+ });
+ }
+
+ if (action == DoorAction::CLOSE){
+ this->discrete_close_pin_->digital_write(1);
+ this->scheduler_->set_timeout(this->ratgdo_, "", 500, [=] {
+ this->discrete_close_pin_->digital_write(0);
+ });
+ }
+
+ this->tx_pin_->digital_write(1); // Single button control
this->scheduler_->set_timeout(this->ratgdo_, "", 500, [=] {
this->tx_pin_->digital_write(0);
});
diff --git a/components/ratgdo/dry_contact.h b/components/ratgdo/dry_contact.h
index 162c367..09362b6 100644
--- a/components/ratgdo/dry_contact.h
+++ b/components/ratgdo/dry_contact.h
@@ -36,6 +36,18 @@ namespace ratgdo {
void set_close_limit(bool state);
void send_door_state();
+ void set_discrete_open_pin(InternalGPIOPin* pin) {
+ this->discrete_open_pin_ = pin;
+ this->discrete_open_pin_->setup();
+ this->discrete_open_pin_->pin_mode(gpio::FLAG_OUTPUT);
+ }
+
+ void set_discrete_close_pin(InternalGPIOPin* pin) {
+ this->discrete_close_pin_ = pin;
+ this->discrete_close_pin_->setup();
+ this->discrete_close_pin_->pin_mode(gpio::FLAG_OUTPUT);
+ }
+
Result call(Args args);
const Traits& traits() const { return this->traits_; }
@@ -45,6 +57,8 @@ namespace ratgdo {
InternalGPIOPin* tx_pin_;
InternalGPIOPin* rx_pin_;
+ InternalGPIOPin* discrete_open_pin_;
+ InternalGPIOPin* discrete_close_pin_;
RATGDOComponent* ratgdo_;
Scheduler* scheduler_;
diff --git a/components/ratgdo/protocol.h b/components/ratgdo/protocol.h
index f7a82e1..325c6ea 100644
--- a/components/ratgdo/protocol.h
+++ b/components/ratgdo/protocol.h
@@ -105,6 +105,9 @@ namespace ratgdo {
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 void light_action(LightAction action);
diff --git a/components/ratgdo/ratgdo.h b/components/ratgdo/ratgdo.h
index e221d4f..2c9ac61 100644
--- a/components/ratgdo/ratgdo.h
+++ b/components/ratgdo/ratgdo.h
@@ -92,6 +92,12 @@ namespace ratgdo {
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_dry_contact_open_sensor(esphome::gpio::GPIOBinarySensor* dry_contact_open_sensor_);
+ void set_dry_contact_close_sensor(esphome::gpio::GPIOBinarySensor* 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);
void received(const DoorState door_state);
@@ -169,9 +175,6 @@ namespace ratgdo {
void subscribe_sync_failed(std::function