Setting up dry contact protocol

This commit is contained in:
Paul Wieland 2024-03-22 13:08:51 -04:00
parent 17a74f8a29
commit e79c0823e3
4 changed files with 315 additions and 0 deletions

212
base_drycontact.yaml Normal file
View File

@ -0,0 +1,212 @@
---
external_components:
- source:
type: local
path: components
# type: git
# url: https://github.com/ratgdo/esphome-ratgdo
# refresh: 1s
preferences:
flash_write_interval: 1min
ratgdo:
id: ${id_prefix}
input_gdo_pin: ${uart_rx_pin}
output_gdo_pin: ${uart_tx_pin}
input_obst_pin: ${input_obst_pin}
protocol: drycontact
on_sync_failed:
then:
- homeassistant.service:
service: persistent_notification.create
data:
title: "${friendly_name} sync failed"
message: "Failed to communicate with garage opener on startup."
notification_id: "esphome_ratgdo_${id_prefix}_sync_failed"
lock:
- platform: ratgdo
id: ${id_prefix}_lock_remotes
ratgdo_id: ${id_prefix}
name: "Lock remotes"
switch:
- platform: gpio
id: "${id_prefix}_status_door"
internal: true
pin:
number: ${status_door_pin} # D0 output door status, HIGH for open, LOW for closed
mode:
output: true
name: "Status door"
entity_category: diagnostic
- platform: gpio
id: "${id_prefix}_status_obstruction"
internal: true
pin:
number: ${status_obstruction_pin} # D8 output for obstruction status, HIGH for obstructed, LOW for clear
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:
number: ${dry_contact_open_pin} # D5 dry contact for opening door
inverted: true
mode:
input: true
pullup: true
name: "Dry contact open"
entity_category: diagnostic
filters:
- delayed_on_off: 500ms
# on_state:
# then:
# lambda: |-
# id($id_prefix)->call_protocol(set_open_limit { static_cast<bool>(true) });
- platform: gpio
id: "${id_prefix}_dry_contact_close"
pin:
number: ${dry_contact_close_pin} # D6 dry contact for closing door
inverted: true
mode:
input: true
pullup: true
name: "Dry contact close"
entity_category: diagnostic
filters:
- delayed_on_off: 500ms
# on_press:
# - if:
# condition:
# binary_sensor.is_off: ${id_prefix}_dry_contact_open
# then:
# - cover.close: ${id_prefix}_garage_door
- platform: gpio
id: "${id_prefix}_dry_contact_light"
pin:
number: ${dry_contact_light_pin} # D3 dry contact for triggering light (no discrete light commands, so toggle only)
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
id: ${id_prefix}_rolling_code_counter
type: rolling_code_counter
entity_category: config
ratgdo_id: ${id_prefix}
name: "Rolling code counter"
mode: box
unit_of_measurement: "codes"
- platform: ratgdo
id: ${id_prefix}_opening_duration
type: opening_duration
entity_category: config
ratgdo_id: ${id_prefix}
name: "Opening duration"
unit_of_measurement: "s"
- platform: ratgdo
id: ${id_prefix}_closing_duration
type: closing_duration
entity_category: config
ratgdo_id: ${id_prefix}
name: "Closing duration"
unit_of_measurement: "s"
- platform: ratgdo
id: ${id_prefix}_client_id
type: client_id
entity_category: config
ratgdo_id: ${id_prefix}
name: "Client ID"
mode: box
cover:
- platform: ratgdo
id: ${id_prefix}_garage_door
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
light:
- platform: ratgdo
id: ${id_prefix}_light
name: "Light"
ratgdo_id: ${id_prefix}
button:
- platform: restart
id: ${id_prefix}_restart
name: "Restart"
- platform: safe_mode
id: ${id_prefix}_safe_mode
name: "Safe mode boot"
entity_category: diagnostic
- platform: template
id: ${id_prefix}_query_status
entity_category: diagnostic
name: "Query status"
on_press:
then:
lambda: !lambda |-
id($id_prefix).query_status();
- platform: template
id: ${id_prefix}_sync
name: "Sync"
entity_category: diagnostic
on_press:
then:
lambda: !lambda |-
id($id_prefix).sync();
- platform: template
id: ${id_prefix}_toggle_door
name: "Toggle door!"
on_press:
then:
lambda: !lambda |-
id($id_prefix).door_toggle();

View File

@ -18,6 +18,11 @@ namespace ratgdo {
this->scheduler_ = scheduler;
this->tx_pin_ = tx_pin;
this->rx_pin_ = rx_pin;
this->open_limit_reached_ = 0;
this->last_open_limit_ = 0;
this->close_limit_reached_ = 0;
this->last_close_limit_ = 0;
}
void DryContact::loop()
@ -33,6 +38,42 @@ namespace ratgdo {
{
}
void DryContact::set_open_limit(bool val)
{
ESP_LOGD(TAG, "Set open_limit_reached to %d", val);
this->last_open_limit_ = this->open_limit_reached_;
this->open_limit_reached_ = val;
this->send_door_state();
}
void DryContact::set_close_limit(bool val)
{
ESP_LOGD(TAG, "Set close_limit_reached to %d", val);
this->last_close_limit_ = this->close_limit_reached_;
this->close_limit_reached_ = val;
this->send_door_state();
}
void DryContact::send_door_state(){
DoorState door_state;
if(this->open_limit_reached_){
door_state = DoorState::OPEN;
}else if(this->close_limit_reached_){
door_state = DoorState::CLOSED;
}else if(!this->close_limit_reached_ && !this->open_limit_reached_){
if(this->last_close_limit_){
door_state = DoorState::OPENING;
}
if(this->last_open_limit_){
door_state = DoorState::CLOSING;
}
}
this->ratgdo_->received(door_state);
}
void DryContact::light_action(LightAction action)
{
ESP_LOG1(TAG, "Ignoring light action: %s", LightAction_to_string(action));

View File

@ -29,6 +29,9 @@ namespace ratgdo {
void light_action(LightAction action);
void lock_action(LockAction action);
void door_action(DoorAction action);
void set_open_limit(bool val);
void set_close_limit(bool val);
void send_door_state();
Result call(Args args);
@ -42,6 +45,11 @@ namespace ratgdo {
RATGDOComponent* ratgdo_;
Scheduler* scheduler_;
bool open_limit_reached_;
bool last_open_limit_;
bool close_limit_reached_;
bool last_close_limit_;
};
} // namespace secplus1

54
v25iboard_drycontact.yaml Normal file
View File

@ -0,0 +1,54 @@
---
substitutions:
id_prefix: ratgdov25i
friendly_name: "ratgdov2.5i"
uart_tx_pin: D1
uart_rx_pin: D2
input_obst_pin: D7
status_door_pin: D0
status_obstruction_pin: D8
dry_contact_open_pin: D5
dry_contact_close_pin: D6
dry_contact_light_pin: D3
web_server:
esphome:
name: ${id_prefix}
friendly_name: ${friendly_name}
name_add_mac_suffix: true
project:
name: ratgdo.esphome
version: "2.5i"
esp8266:
board: d1_mini
restore_from_flash: true
dashboard_import:
package_import_url: github://ratgdo/esphome-ratgdo/v25iboard_secplusv1.yaml@main
packages:
# remote_package:
# url: https://github.com/ratgdo/esphome-ratgdo
# files: [base_secplusv1.yaml]
# refresh: 1s
remote_package: !include
file: base_drycontact.yaml
# Sync time with Home Assistant.
time:
- platform: homeassistant
id: homeassistant_time
api:
id: api_server
ota:
improv_serial:
wifi:
ap:
logger:
level: DEBUG