Compare commits

...

27 Commits

Author SHA1 Message Date
Paul Wieland 644c294194
Merge f58247e029 into 2b46c587fc 2024-12-04 16:38:34 +00:00
Paul Wieland f58247e029 Merge branch 'ratgdo32' of https://github.com/ratgdo/esphome-ratgdo into ratgdo32 2024-12-04 11:38:29 -05:00
Paul Wieland 1bfea01043 Update index.html 2024-12-04 11:38:27 -05:00
pre-commit-ci[bot] 690a2b6659 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2024-12-04 16:32:34 +00:00
Paul Wieland 336252b20c Update index.html 2024-12-04 11:32:25 -05:00
Paul Wieland 9479f794f3 Create ratgdo32.jpg 2024-12-04 11:22:39 -05:00
Paul Wieland af632d139f Update README.md 2024-12-04 11:17:21 -05:00
Paul Wieland eb90d3fd55 add v32 2024-11-15 10:56:17 -05:00
Paul Wieland c11a748608 display diagram 2024-11-13 04:57:31 -05:00
Paul Wieland 8dd09d2c29 display diagram 2024-11-13 04:43:00 -05:00
Paul Wieland 12af6603fb Update index.html 2024-11-12 13:58:16 -05:00
Paul Wieland fbcc2ae75d Update index.html 2024-11-12 13:40:35 -05:00
Paul Wieland 4ee1ddf0bc diagrams 2024-11-12 13:26:46 -05:00
Paul Wieland e919ff53da Create ratgdo32_disco.jpg 2024-11-12 13:06:36 -05:00
Paul Wieland f0cf81b5dd Update build.yml 2024-11-12 12:52:59 -05:00
Paul Wieland 53a2589ba3 ratgdo32 branch 2024-11-12 12:35:05 -05:00
Paul Wieland 1f9b4a4682 temp switch gh pages to ratgdo32 branch 2024-11-12 12:18:40 -05:00
Paul Wieland ee0f0bcabd LED GPIO 2024-11-10 13:53:47 -05:00
Paul Wieland ae8d1a3c2a add branch
roll back after merge
2024-11-10 13:47:47 -05:00
Paul Wieland 52bc8cc1d3 Merge branch 'ratgdo32' of https://github.com/ratgdo/esphome-ratgdo into ratgdo32 2024-11-10 13:21:41 -05:00
Paul Wieland be6ec93b3e add branch
to be removed after merge
2024-11-10 13:21:39 -05:00
pre-commit-ci[bot] eee6f5e4d5 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2024-11-10 18:05:29 +00:00
Paul Wieland fd43050842 closing delay max
reduce to increase slider resolution
2024-11-10 11:41:55 -05:00
Paul Wieland 1e15dae5a7 Add disco to build/webtools 2024-11-10 10:25:43 -05:00
Paul Wieland 8068dbed46 ignore bugs 2024-11-07 11:36:35 -05:00
Paul Wieland 516eb29d96 correct yaml 2024-11-07 09:43:47 -05:00
Paul Wieland f68d126fb8 ratgdo32 2024-10-28 13:56:16 -04:00
44 changed files with 1205 additions and 47 deletions

View File

@ -4,7 +4,7 @@ on:
workflow_dispatch: workflow_dispatch:
push: push:
branches: branches:
- main - ratgdo32
pull_request: pull_request:
schedule: schedule:
- cron: '0 4 * * 1' - cron: '0 4 * * 1'
@ -55,6 +55,24 @@ jobs:
- file: v25iboard_drycontact.yaml - file: v25iboard_drycontact.yaml
name: V2.5i Board Dry Contact name: V2.5i Board Dry Contact
manifest_filename: v25iboard_drycontact-manifest.json manifest_filename: v25iboard_drycontact-manifest.json
- file: v32board.yaml
name: V32 Board Security+ 2.0
manifest_filename: v32board-manifest.json
- file: v32board_secplusv1.yaml
name: V32 Board Security+ 1.0
manifest_filename: v32board_secplusv1-manifest.json
- file: v32board_drycontact.yaml
name: V32 Board Board Dry Contact
manifest_filename: v32board_drycontact-manifest.json
- file: v32disco.yaml
name: V32 Disco Board Security+ 2.0
manifest_filename: v32disco-manifest.json
- file: v32disco_secplusv1.yaml
name: V32 Disco Board Security+ 1.0
manifest_filename: v32disco_secplusv1-manifest.json
- file: v32disco_drycontact.yaml
name: V32 Disco Board Dry Contact
manifest_filename: v32disco_drycontact-manifest.json
fail-fast: false fail-fast: false
steps: steps:
- name: Checkout source code - name: Checkout source code
@ -79,7 +97,7 @@ jobs:
consolidate: consolidate:
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' if: github.event_name != 'pull_request' && github.ref == 'refs/heads/ratgdo32'
name: Consolidate firmwares name: Consolidate firmwares
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
@ -101,7 +119,7 @@ jobs:
path: output path: output
deploy: deploy:
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' if: github.event_name != 'pull_request' && github.ref == 'refs/heads/ratgdo32'
name: Deploy to GitHub Pages name: Deploy to GitHub Pages
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: consolidate needs: consolidate

View File

@ -1,16 +1,12 @@
# ratgdo for ESPHome # ratgdo for ESPHome
This is a port of the ratgdo software for the v2.0/v2.5 board to ESPHome. [Visit the ratcloud.llc to purchase boards](https://ratcloud.llc)
[Visit the github.io page to purchase boards](https://paulwieland.github.io/ratgdo/#order)
## Installation ## Installation
- Flash the ESPHome based firmware using the [Web Installer](https://ratgdo.github.io/esphome-ratgdo/) - Flash the ESPHome based firmware using the [Web Installer](https://ratgdo.github.io/esphome-ratgdo/)
It is no longer necessary to save the rolling code counter when switching between firmware.
## First use after adding to Home Assistant ## First use after adding to Home Assistant
The ESPHome firmware will allow you to open the door to any position after calibration. To calibrate the door, open and close it once without stopping. The ESPHome firmware will allow you to open the door to any position after calibration. To calibrate the door, open and close it once without stopping.

View File

@ -1,10 +1,13 @@
--- ---
external_components: external_components:
- source: - source:
type: git type: git
url: https://github.com/ratgdo/esphome-ratgdo url: https://github.com/ratgdo/esphome-ratgdo
ref: ratgdo32
refresh: 1s refresh: 1s
# - source:
# type: local
# path: components
safe_mode: safe_mode:

View File

@ -2,11 +2,13 @@
external_components: external_components:
- source: - source:
# type: local
# path: components
type: git type: git
url: https://github.com/ratgdo/esphome-ratgdo url: https://github.com/ratgdo/esphome-ratgdo
ref: ratgdo32
refresh: 1s refresh: 1s
# - source:
# type: local
# path: components
safe_mode: safe_mode:
@ -20,6 +22,7 @@ text_sensor:
ratgdo: ratgdo:
id: ${id_prefix} id: ${id_prefix}
output_gdo_pin: ${uart_tx_pin} output_gdo_pin: ${uart_tx_pin}
input_gdo_pin: ${uart_rx_pin}
input_obst_pin: ${input_obst_pin} input_obst_pin: ${input_obst_pin}
dry_contact_open_sensor: ${id_prefix}_dry_contact_open dry_contact_open_sensor: ${id_prefix}_dry_contact_open
dry_contact_close_sensor: ${id_prefix}_dry_contact_close dry_contact_close_sensor: ${id_prefix}_dry_contact_close

View File

@ -4,7 +4,11 @@ external_components:
- source: - source:
type: git type: git
url: https://github.com/ratgdo/esphome-ratgdo url: https://github.com/ratgdo/esphome-ratgdo
ref: ratgdo32
refresh: 1s refresh: 1s
# - source:
# type: local
# path: components
safe_mode: safe_mode:

View File

@ -18,6 +18,9 @@ TYPES = {
"obstruction": SensorType.RATGDO_SENSOR_OBSTRUCTION, "obstruction": SensorType.RATGDO_SENSOR_OBSTRUCTION,
"motor": SensorType.RATGDO_SENSOR_MOTOR, "motor": SensorType.RATGDO_SENSOR_MOTOR,
"button": SensorType.RATGDO_SENSOR_BUTTON, "button": SensorType.RATGDO_SENSOR_BUTTON,
"vehicle_detected": SensorType.RATGDO_SENSOR_VEHICLE_DETECTED,
"vehicle_arriving": SensorType.RATGDO_SENSOR_VEHICLE_ARRIVING,
"vehicle_leaving": SensorType.RATGDO_SENSOR_VEHICLE_LEAVING,
} }

View File

@ -28,6 +28,22 @@ namespace ratgdo {
this->parent_->subscribe_button_state([=](ButtonState state) { this->parent_->subscribe_button_state([=](ButtonState state) {
this->publish_state(state == ButtonState::PRESSED); this->publish_state(state == ButtonState::PRESSED);
}); });
} else if (this->binary_sensor_type_ == SensorType::RATGDO_SENSOR_VEHICLE_DETECTED) {
this->publish_initial_state(false);
this->parent_->subscribe_vehicle_detected_state([=](VehicleDetectedState state) {
this->publish_state(state == VehicleDetectedState::YES);
this->parent_->presence_change(state == VehicleDetectedState::YES);
});
} else if (this->binary_sensor_type_ == SensorType::RATGDO_SENSOR_VEHICLE_ARRIVING) {
this->publish_initial_state(false);
this->parent_->subscribe_vehicle_arriving_state([=](VehicleArrivingState state) {
this->publish_state(state == VehicleArrivingState::YES);
});
} else if (this->binary_sensor_type_ == SensorType::RATGDO_SENSOR_VEHICLE_LEAVING) {
this->publish_initial_state(false);
this->parent_->subscribe_vehicle_leaving_state([=](VehicleLeavingState state) {
this->publish_state(state == VehicleLeavingState::YES);
});
} }
} }
@ -42,6 +58,12 @@ namespace ratgdo {
ESP_LOGCONFIG(TAG, " Type: Motor"); ESP_LOGCONFIG(TAG, " Type: Motor");
} else if (this->binary_sensor_type_ == SensorType::RATGDO_SENSOR_BUTTON) { } else if (this->binary_sensor_type_ == SensorType::RATGDO_SENSOR_BUTTON) {
ESP_LOGCONFIG(TAG, " Type: Button"); ESP_LOGCONFIG(TAG, " Type: Button");
} else if (this->binary_sensor_type_ == SensorType::RATGDO_SENSOR_VEHICLE_DETECTED) {
ESP_LOGCONFIG(TAG, " Type: VehicleDetected");
} else if (this->binary_sensor_type_ == SensorType::RATGDO_SENSOR_VEHICLE_ARRIVING) {
ESP_LOGCONFIG(TAG, " Type: VehicleArriving");
} else if (this->binary_sensor_type_ == SensorType::RATGDO_SENSOR_VEHICLE_LEAVING) {
ESP_LOGCONFIG(TAG, " Type: VehicleLeaving");
} }
} }

View File

@ -12,7 +12,10 @@ namespace ratgdo {
RATGDO_SENSOR_MOTION, RATGDO_SENSOR_MOTION,
RATGDO_SENSOR_OBSTRUCTION, RATGDO_SENSOR_OBSTRUCTION,
RATGDO_SENSOR_MOTOR, RATGDO_SENSOR_MOTOR,
RATGDO_SENSOR_BUTTON RATGDO_SENSOR_BUTTON,
RATGDO_SENSOR_VEHICLE_DETECTED,
RATGDO_SENSOR_VEHICLE_ARRIVING,
RATGDO_SENSOR_VEHICLE_LEAVING,
}; };
class RATGDOBinarySensor : public binary_sensor::BinarySensor, public RATGDOClient, public Component { class RATGDOBinarySensor : public binary_sensor::BinarySensor, public RATGDOClient, public Component {

View File

@ -16,6 +16,8 @@ TYPES = {
"rolling_code_counter": NumberType.RATGDO_ROLLING_CODE_COUNTER, "rolling_code_counter": NumberType.RATGDO_ROLLING_CODE_COUNTER,
"opening_duration": NumberType.RATGDO_OPENING_DURATION, "opening_duration": NumberType.RATGDO_OPENING_DURATION,
"closing_duration": NumberType.RATGDO_CLOSING_DURATION, "closing_duration": NumberType.RATGDO_CLOSING_DURATION,
"closing_delay": NumberType.RATGDO_CLOSING_DELAY,
"target_distance_measurement": NumberType.RATGDO_TARGET_DISTANCE_MEASUREMENT,
} }

View File

@ -30,6 +30,10 @@ namespace ratgdo {
ESP_LOGCONFIG(TAG, " Type: Opening Duration"); ESP_LOGCONFIG(TAG, " Type: Opening Duration");
} else if (this->number_type_ == RATGDO_CLOSING_DURATION) { } else if (this->number_type_ == RATGDO_CLOSING_DURATION) {
ESP_LOGCONFIG(TAG, " Type: Closing Duration"); ESP_LOGCONFIG(TAG, " Type: Closing Duration");
} else if (this->number_type_ == RATGDO_CLOSING_DELAY) {
ESP_LOGCONFIG(TAG, " Type: Closing Delay");
} else if (this->number_type_ == RATGDO_TARGET_DISTANCE_MEASUREMENT) {
ESP_LOGCONFIG(TAG, " Type: Target Distance Measurement");
} }
} }
@ -66,6 +70,14 @@ namespace ratgdo {
this->parent_->subscribe_closing_duration([=](float value) { this->parent_->subscribe_closing_duration([=](float value) {
this->update_state(value); this->update_state(value);
}); });
} else if (this->number_type_ == RATGDO_CLOSING_DELAY) {
this->parent_->subscribe_closing_delay([=](uint32_t value) {
this->update_state(value);
});
} else if (this->number_type_ == RATGDO_TARGET_DISTANCE_MEASUREMENT) {
// this->parent_->subscribe_target_distance_measurement([=](float value) {
// this->update_state(value);
// });
} }
} }
@ -76,12 +88,20 @@ namespace ratgdo {
this->traits.set_step(0.1); this->traits.set_step(0.1);
this->traits.set_min_value(0.0); this->traits.set_min_value(0.0);
this->traits.set_max_value(180.0); this->traits.set_max_value(180.0);
} else if (this->number_type_ == RATGDO_CLOSING_DELAY) {
this->traits.set_step(1);
this->traits.set_min_value(0.0);
this->traits.set_max_value(60.0);
} else if (this->number_type_ == RATGDO_ROLLING_CODE_COUNTER) { } else if (this->number_type_ == RATGDO_ROLLING_CODE_COUNTER) {
this->traits.set_max_value(0xfffffff); this->traits.set_max_value(0xfffffff);
} else if (this->number_type_ == RATGDO_CLIENT_ID) { } else if (this->number_type_ == RATGDO_CLIENT_ID) {
this->traits.set_step(0x1000); this->traits.set_step(0x1000);
this->traits.set_min_value(0x539); this->traits.set_min_value(0x539);
this->traits.set_max_value(0x7ff539); this->traits.set_max_value(0x7ff539);
} else if (this->number_type_ == RATGDO_TARGET_DISTANCE_MEASUREMENT) {
this->traits.set_step(1);
this->traits.set_min_value(5);
this->traits.set_max_value(3500);
} }
} }
@ -102,9 +122,13 @@ namespace ratgdo {
this->parent_->set_opening_duration(value); this->parent_->set_opening_duration(value);
} else if (this->number_type_ == RATGDO_CLOSING_DURATION) { } else if (this->number_type_ == RATGDO_CLOSING_DURATION) {
this->parent_->set_closing_duration(value); this->parent_->set_closing_duration(value);
} else if (this->number_type_ == RATGDO_CLOSING_DELAY) {
this->parent_->set_closing_delay(value);
} else if (this->number_type_ == RATGDO_CLIENT_ID) { } else if (this->number_type_ == RATGDO_CLIENT_ID) {
value = normalize_client_id(value); value = normalize_client_id(value);
this->parent_->call_protocol(SetClientID { static_cast<uint32_t>(value) }); this->parent_->call_protocol(SetClientID { static_cast<uint32_t>(value) });
} else if (this->number_type_ == RATGDO_TARGET_DISTANCE_MEASUREMENT) {
this->parent_->set_target_distance_measurement(value);
} }
this->update_state(value); this->update_state(value);
} }

View File

@ -13,6 +13,8 @@ namespace ratgdo {
RATGDO_ROLLING_CODE_COUNTER, RATGDO_ROLLING_CODE_COUNTER,
RATGDO_OPENING_DURATION, RATGDO_OPENING_DURATION,
RATGDO_CLOSING_DURATION, RATGDO_CLOSING_DURATION,
RATGDO_CLOSING_DELAY,
RATGDO_TARGET_DISTANCE_MEASUREMENT,
}; };
class RATGDONumber : public number::Number, public RATGDOClient, public Component { class RATGDONumber : public number::Number, public RATGDOClient, public Component {

View File

@ -0,0 +1,36 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import rtttl
from esphome.const import CONF_ID
CONF_RTTTL = "rtttl"
CONF_SONG = "song"
from .. import RATGDO_CLIENT_SCHMEA, ratgdo_ns, register_ratgdo_child
DEPENDENCIES = ["esp32","ratgdo","rtttl"]
RATGDOOutput = ratgdo_ns.class_("RATGDOOutput", cg.Component)
OutputType = ratgdo_ns.enum("OutputType")
CONF_TYPE = "type"
TYPES = {
"beeper": OutputType.RATGDO_BEEPER
}
CONFIG_SCHEMA = cv.Schema(
{
cv.Required(CONF_ID): cv.declare_id(RATGDOOutput),
cv.Required(CONF_TYPE): cv.enum(TYPES, lower=True),
cv.Required(CONF_RTTTL): cv.use_id(rtttl),
cv.Required(CONF_SONG): cv.string
}
).extend(RATGDO_CLIENT_SCHMEA)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
rtttl = await cg.get_variable(config[CONF_RTTTL])
cg.add(var.set_rtttl(rtttl))
cg.add(var.set_song(config[CONF_SONG]))
await register_ratgdo_child(var, config)

View File

@ -0,0 +1,58 @@
#include "ratgdo_output.h"
#include "../ratgdo_state.h"
#include "esphome/core/log.h"
namespace esphome {
namespace ratgdo {
static const char* TAG = "ratgdo.output";
void RATGDOOutput::setup()
{
ESP_LOGD(TAG, "Output was setup");
if (this->output_type_ == OutputType::RATGDO_BEEPER) {
this->beeper_->add_on_finished_playback_callback([=] { this->finished_playback(); });
this->parent_->subscribe_vehicle_arriving_state([=](VehicleArrivingState state) {
if (state == VehicleArrivingState::YES) {
this->play();
}
});
this->parent_->subscribe_door_action_delayed([=](DoorActionDelayed state) {
if (state == DoorActionDelayed::YES) {
this->play();
this->repeat_ = true;
} else if (state == DoorActionDelayed::NO) {
this->repeat_ = false;
}
});
}
}
void RATGDOOutput::play()
{
this->beeper_->play(this->rtttlSong_);
}
void RATGDOOutput::finished_playback()
{
if (this->repeat_)
this->play();
}
void RATGDOOutput::dump_config()
{
if (this->output_type_ == OutputType::RATGDO_BEEPER) {
ESP_LOGCONFIG(TAG, " Type: Beeper");
}
}
void RATGDOOutput::set_output_type(OutputType output_type_)
{
this->output_type_ = output_type_;
}
} // namespace ratgdo
} // namespace esphome

View File

@ -0,0 +1,32 @@
#pragma once
#include "../ratgdo.h"
#include "esphome/components/rtttl/rtttl.h"
#include "esphome/core/component.h"
namespace esphome {
namespace ratgdo {
enum OutputType {
RATGDO_BEEPER
};
class RATGDOOutput : public RATGDOClient, public Component {
public:
void setup() override;
void play();
void finished_playback();
void dump_config() override;
void set_output_type(OutputType output_type);
void set_song(std::string rtttlSong) { this->rtttlSong_ = rtttlSong; }
void set_rtttl(rtttl::Rtttl* output) { this->beeper_ = output; }
protected:
OutputType output_type_;
rtttl::Rtttl* beeper_;
std::string rtttlSong_;
bool repeat_;
};
} // namespace ratgdo
} // namespace esphome

View File

@ -30,6 +30,10 @@ namespace ratgdo {
static const char* const TAG = "ratgdo"; static const char* const TAG = "ratgdo";
static const int SYNC_DELAY = 1000; static const int SYNC_DELAY = 1000;
static const int CLEAR_PRESENCE = 60000; // how long to keep arriving/leaving active
static const int PRESENCE_DETECT_WINDOW = 300000; // how long to calculate presence after door state change
static const int MIN_DISTANCE = 20; // ignore bugs crawling on the distance sensor
void RATGDOComponent::setup() void RATGDOComponent::setup()
{ {
this->output_gdo_pin_->setup(); this->output_gdo_pin_->setup();
@ -39,7 +43,11 @@ namespace ratgdo {
this->input_gdo_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); this->input_gdo_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
this->input_obst_pin_->setup(); this->input_obst_pin_->setup();
#ifdef USE_ESP32
this->input_obst_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
#else
this->input_obst_pin_->pin_mode(gpio::FLAG_INPUT); this->input_obst_pin_->pin_mode(gpio::FLAG_INPUT);
#endif
this->input_obst_pin_->attach_interrupt(RATGDOStore::isr_obstruction, &this->isr_store_, gpio::INTERRUPT_FALLING_EDGE); this->input_obst_pin_->attach_interrupt(RATGDOStore::isr_obstruction, &this->isr_store_, gpio::INTERRUPT_FALLING_EDGE);
this->protocol_->setup(this, &App.scheduler, this->input_gdo_pin_, this->output_gdo_pin_); this->protocol_->setup(this, &App.scheduler, this->input_gdo_pin_, this->output_gdo_pin_);
@ -51,6 +59,24 @@ namespace ratgdo {
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([=](DoorState state, float position) {
static DoorState lastState = DoorState::UNKNOWN;
if (lastState != DoorState::UNKNOWN && state != DoorState::CLOSED && !this->presence_detect_window_active_) {
this->presence_detect_window_active_ = true;
set_timeout("presence_detect_window", PRESENCE_DETECT_WINDOW, [=] {
this->presence_detect_window_active_ = false;
});
}
if (state == DoorState::CLOSED) {
this->presence_detect_window_active_ = false;
cancel_timeout("presence_detect_window");
}
lastState = state;
});
} }
// initializing protocol, this gets called before setup() because // initializing protocol, this gets called before setup() because
@ -335,6 +361,70 @@ namespace ratgdo {
this->closing_duration = duration; this->closing_duration = duration;
} }
void RATGDOComponent::set_target_distance_measurement(int16_t distance)
{
this->target_distance_measurement = distance;
}
void RATGDOComponent::set_distance_measurement(int16_t distance)
{
if (distance > 0 && distance < MIN_DISTANCE)
return;
this->last_distance_measurement = distance;
// current value = [0], last value = [1]
this->distance_measurement.insert(this->distance_measurement.begin(), distance);
this->distance_measurement.pop_back();
this->calculate_presence();
}
void RATGDOComponent::calculate_presence()
{
bool all_in_range = true;
bool all_out_of_range = true;
// int16_t min = *this->target_distance_measurement - PRESENCE_DETECT_TOLERANCE;
// int16_t max = *this->target_distance_measurement + PRESENCE_DETECT_TOLERANCE;
for (int16_t value : this->distance_measurement) {
// if (value < min || value > max || value == -1) {
if (value >= *this->target_distance_measurement || value == -1) {
all_in_range = false;
}
if (value < *this->target_distance_measurement && value != -1) {
all_out_of_range = false;
}
}
if (all_in_range)
this->vehicle_detected_state = VehicleDetectedState::YES;
if (all_out_of_range)
this->vehicle_detected_state = VehicleDetectedState::NO;
// auto k = this->distance_measurement;
// ESP_LOGD(TAG,"measure: %i,%i,%i,%i,%i,%i,%i,%i,%i,%i; target: %i; all_in: %s; all_out: %s;", k[0],k[1],k[2],k[3],k[4],k[5],k[6],k[7],k[8],k[9], *this->target_distance_measurement, all_in_range ? "y" : "n", all_out_of_range ? "y" : "n");
}
void RATGDOComponent::presence_change(bool sensor_value)
{
if (this->presence_detect_window_active_) {
if (sensor_value) {
this->vehicle_arriving_state = VehicleArrivingState::YES;
this->vehicle_leaving_state = VehicleLeavingState::NO;
set_timeout(CLEAR_PRESENCE, [=] {
this->vehicle_arriving_state = VehicleArrivingState::NO;
});
} else {
this->vehicle_arriving_state = VehicleArrivingState::NO;
this->vehicle_leaving_state = VehicleLeavingState::YES;
set_timeout(CLEAR_PRESENCE, [=] {
this->vehicle_leaving_state = VehicleLeavingState::NO;
});
}
}
}
Result RATGDOComponent::call_protocol(Args args) Result RATGDOComponent::call_protocol(Args args)
{ {
return this->protocol_->call(args); return this->protocol_->call(args);
@ -359,7 +449,7 @@ namespace ratgdo {
if (current_millis - last_millis > CHECK_PERIOD) { if (current_millis - last_millis > CHECK_PERIOD) {
// ESP_LOGD(TAG, "%ld: Obstruction count: %d, expected: %d, since asleep: %ld", // ESP_LOGD(TAG, "%ld: Obstruction count: %d, expected: %d, since asleep: %ld",
// current_millis, this->isr_store_.obstruction_low_count, PULSES_EXPECTED, // current_millis, this->isr_store_.obstruction_low_count, PULSES_LOWER_LIMIT,
// current_millis - last_asleep // current_millis - last_asleep
// ); // );
@ -369,7 +459,11 @@ namespace ratgdo {
this->obstruction_sensor_detected_ = true; this->obstruction_sensor_detected_ = true;
} else if (this->isr_store_.obstruction_low_count == 0) { } else if (this->isr_store_.obstruction_low_count == 0) {
// if there have been no pulses the line is steady high or low // if there have been no pulses the line is steady high or low
#ifdef USE_ESP32
if (this->input_obst_pin_->digital_read()) {
#else
if (!this->input_obst_pin_->digital_read()) { if (!this->input_obst_pin_->digital_read()) {
#endif
// asleep // asleep
last_asleep = current_millis; last_asleep = current_millis;
} else { } else {
@ -494,7 +588,15 @@ namespace ratgdo {
void RATGDOComponent::door_action(DoorAction action) void RATGDOComponent::door_action(DoorAction action)
{ {
this->protocol_->door_action(action); if (*this->closing_delay > 0 && action == DoorAction::CLOSE) {
this->door_action_delayed = DoorActionDelayed::YES;
set_timeout("door_action", *this->closing_delay * 1000, [=] {
this->door_action_delayed = DoorActionDelayed::NO;
this->protocol_->door_action(DoorAction::CLOSE);
});
} else {
this->protocol_->door_action(action);
}
} }
void RATGDOComponent::door_move_to_position(float position) void RATGDOComponent::door_move_to_position(float position)
@ -614,6 +716,10 @@ namespace ratgdo {
{ {
this->closing_duration.subscribe([=](float state) { defer("closing_duration", [=] { f(state); }); }); this->closing_duration.subscribe([=](float state) { defer("closing_duration", [=] { f(state); }); });
} }
void RATGDOComponent::subscribe_closing_delay(std::function<void(uint32_t)>&& f)
{
this->closing_delay.subscribe([=](uint32_t state) { defer("closing_delay", [=] { f(state); }); });
}
void RATGDOComponent::subscribe_openings(std::function<void(uint16_t)>&& f) void RATGDOComponent::subscribe_openings(std::function<void(uint16_t)>&& f)
{ {
this->openings.subscribe([=](uint16_t state) { defer("openings", [=] { f(state); }); }); this->openings.subscribe([=](uint16_t state) { defer("openings", [=] { f(state); }); });
@ -640,11 +746,14 @@ namespace ratgdo {
} }
void RATGDOComponent::subscribe_door_state(std::function<void(DoorState, float)>&& f) void RATGDOComponent::subscribe_door_state(std::function<void(DoorState, float)>&& f)
{ {
static int num = 0;
auto name = "door_state" + std::to_string(num++);
this->door_state.subscribe([=](DoorState state) { this->door_state.subscribe([=](DoorState state) {
defer("door_state", [=] { f(state, *this->door_position); }); defer(name, [=] { f(state, *this->door_position); });
}); });
this->door_position.subscribe([=](float position) { this->door_position.subscribe([=](float position) {
defer("door_state", [=] { f(*this->door_state, position); }); defer(name, [=] { f(*this->door_state, position); });
}); });
} }
void RATGDOComponent::subscribe_light_state(std::function<void(LightState)>&& f) void RATGDOComponent::subscribe_light_state(std::function<void(LightState)>&& f)
@ -679,6 +788,37 @@ namespace ratgdo {
{ {
this->learn_state.subscribe([=](LearnState state) { defer("learn_state", [=] { f(state); }); }); this->learn_state.subscribe([=](LearnState state) { defer("learn_state", [=] { f(state); }); });
} }
void RATGDOComponent::subscribe_door_action_delayed(std::function<void(DoorActionDelayed)>&& f)
{
static int num = 0;
auto name = "door_action_delayed" + std::to_string(num++);
this->door_action_delayed.subscribe([=](DoorActionDelayed state) { defer(name, [=] { f(state); }); });
}
void RATGDOComponent::subscribe_distance_measurement(std::function<void(int16_t)>&& f)
{
static int num = 0;
auto name = "last_distance_measurement" + std::to_string(num++);
this->last_distance_measurement.subscribe([=](int16_t state) { defer(name, [=] { f(state); }); });
}
void RATGDOComponent::subscribe_vehicle_detected_state(std::function<void(VehicleDetectedState)>&& f)
{
static int num = 0;
auto name = "vehicle_detected_state" + std::to_string(num++);
this->vehicle_detected_state.subscribe([=](VehicleDetectedState state) { defer(name, [=] { f(state); }); });
}
void RATGDOComponent::subscribe_vehicle_arriving_state(std::function<void(VehicleArrivingState)>&& f)
{
static int num = 0;
auto name = "vehicle_arriving_state" + std::to_string(num++);
this->vehicle_arriving_state.subscribe([=](VehicleArrivingState state) { defer(name, [=] { f(state); }); });
}
void RATGDOComponent::subscribe_vehicle_leaving_state(std::function<void(VehicleLeavingState)>&& f)
{
static int num = 0;
auto name = "vehicle_leaving_state" + std::to_string(num++);
this->vehicle_leaving_state.subscribe([=](VehicleLeavingState state) { defer(name, [=] { f(state); }); });
}
// dry contact methods // dry contact methods
void RATGDOComponent::set_dry_contact_open_sensor(esphome::binary_sensor::BinarySensor* dry_contact_open_sensor) void RATGDOComponent::set_dry_contact_open_sensor(esphome::binary_sensor::BinarySensor* dry_contact_open_sensor)

View File

@ -62,6 +62,11 @@ namespace ratgdo {
observable<float> opening_duration { 0 }; observable<float> opening_duration { 0 };
float start_closing { -1 }; float start_closing { -1 };
observable<float> closing_duration { 0 }; observable<float> closing_duration { 0 };
observable<uint32_t> closing_delay { 0 };
observable<int16_t> target_distance_measurement { -1 };
std::vector<int16_t> distance_measurement { std::vector<int16_t>(10, -1) }; // the length of this vector determines how many in-range readings are required for presence detection to change states
observable<int16_t> last_distance_measurement { 0 };
observable<uint16_t> openings { 0 }; // number of times the door has been opened observable<uint16_t> openings { 0 }; // number of times the door has been opened
observable<uint16_t> paired_total { PAIRED_DEVICES_UNKNOWN }; observable<uint16_t> paired_total { PAIRED_DEVICES_UNKNOWN };
@ -72,6 +77,7 @@ namespace ratgdo {
observable<DoorState> door_state { DoorState::UNKNOWN }; observable<DoorState> door_state { DoorState::UNKNOWN };
observable<float> door_position { DOOR_POSITION_UNKNOWN }; observable<float> door_position { DOOR_POSITION_UNKNOWN };
observable<DoorActionDelayed> door_action_delayed { DoorActionDelayed::NO };
unsigned long door_start_moving { 0 }; unsigned long door_start_moving { 0 };
float door_start_position { DOOR_POSITION_UNKNOWN }; float door_start_position { DOOR_POSITION_UNKNOWN };
@ -84,6 +90,9 @@ namespace ratgdo {
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 }; observable<LearnState> learn_state { LearnState::UNKNOWN };
observable<VehicleDetectedState> vehicle_detected_state { VehicleDetectedState::NO };
observable<VehicleArrivingState> vehicle_arriving_state { VehicleArrivingState::NO };
observable<VehicleLeavingState> vehicle_leaving_state { VehicleLeavingState::NO };
OnceCallbacks<void(DoorState)> on_door_state_; OnceCallbacks<void(DoorState)> on_door_state_;
@ -127,9 +136,14 @@ namespace ratgdo {
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);
void set_closing_duration(float duration); void set_closing_duration(float duration);
void set_closing_delay(uint32_t delay) { this->closing_delay = delay; }
void schedule_door_position_sync(float update_period = 500); void schedule_door_position_sync(float update_period = 500);
void door_position_update(); void door_position_update();
void cancel_position_sync_callbacks(); void cancel_position_sync_callbacks();
void set_target_distance_measurement(int16_t distance);
void set_distance_measurement(int16_t distance);
void calculate_presence();
void presence_change(bool sensor_value);
// light // light
void light_toggle(); void light_toggle();
@ -158,6 +172,7 @@ namespace ratgdo {
void subscribe_rolling_code_counter(std::function<void(uint32_t)>&& f); void subscribe_rolling_code_counter(std::function<void(uint32_t)>&& f);
void subscribe_opening_duration(std::function<void(float)>&& f); void subscribe_opening_duration(std::function<void(float)>&& f);
void subscribe_closing_duration(std::function<void(float)>&& f); void subscribe_closing_duration(std::function<void(float)>&& f);
void subscribe_closing_delay(std::function<void(uint32_t)>&& f);
void subscribe_openings(std::function<void(uint16_t)>&& f); void subscribe_openings(std::function<void(uint16_t)>&& f);
void subscribe_paired_devices_total(std::function<void(uint16_t)>&& f); void subscribe_paired_devices_total(std::function<void(uint16_t)>&& f);
void subscribe_paired_remotes(std::function<void(uint16_t)>&& f); void subscribe_paired_remotes(std::function<void(uint16_t)>&& f);
@ -173,11 +188,17 @@ namespace ratgdo {
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); void subscribe_learn_state(std::function<void(LearnState)>&& f);
void subscribe_door_action_delayed(std::function<void(DoorActionDelayed)>&& f);
void subscribe_distance_measurement(std::function<void(int16_t)>&& f);
void subscribe_vehicle_detected_state(std::function<void(VehicleDetectedState)>&& f);
void subscribe_vehicle_arriving_state(std::function<void(VehicleArrivingState)>&& f);
void subscribe_vehicle_leaving_state(std::function<void(VehicleLeavingState)>&& f);
protected: protected:
RATGDOStore isr_store_ {}; RATGDOStore isr_store_ {};
protocol::Protocol* protocol_; protocol::Protocol* protocol_;
bool obstruction_sensor_detected_ { false }; bool obstruction_sensor_detected_ { false };
bool presence_detect_window_active_ { false };
InternalGPIOPin* output_gdo_pin_; InternalGPIOPin* output_gdo_pin_;
InternalGPIOPin* input_gdo_pin_; InternalGPIOPin* input_gdo_pin_;

View File

@ -26,6 +26,10 @@ namespace ratgdo {
(OPENING, 4), (OPENING, 4),
(CLOSING, 5)) (CLOSING, 5))
ENUM(DoorActionDelayed, uint8_t,
(NO, 0),
(YES, 1))
/// Enum for all states a the light can be in. /// Enum for all states a the light can be in.
ENUM(LightState, uint8_t, ENUM(LightState, uint8_t,
(OFF, 0), (OFF, 0),
@ -104,6 +108,18 @@ namespace ratgdo {
(STOP, 3), (STOP, 3),
(UNKNOWN, 4)) (UNKNOWN, 4))
ENUM(VehicleDetectedState, uint8_t,
(NO, 0),
(YES, 1))
ENUM(VehicleArrivingState, uint8_t,
(NO, 0),
(YES, 1))
ENUM(VehicleLeavingState, uint8_t,
(NO, 0),
(YES, 1))
struct Openings { struct Openings {
uint16_t count; uint16_t count;
uint8_t flag; uint8_t flag;

View File

@ -2,6 +2,7 @@ import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import sensor from esphome.components import sensor
from esphome.const import CONF_ID from esphome.const import CONF_ID
CONF_DISTANCE = "distance"
from .. import RATGDO_CLIENT_SCHMEA, ratgdo_ns, register_ratgdo_child from .. import RATGDO_CLIENT_SCHMEA, ratgdo_ns, register_ratgdo_child
@ -18,6 +19,7 @@ TYPES = {
"paired_devices_keypads": RATGDOSensorType.RATGDO_PAIRED_KEYPADS, "paired_devices_keypads": RATGDOSensorType.RATGDO_PAIRED_KEYPADS,
"paired_devices_wall_controls": RATGDOSensorType.RATGDO_PAIRED_WALL_CONTROLS, "paired_devices_wall_controls": RATGDOSensorType.RATGDO_PAIRED_WALL_CONTROLS,
"paired_devices_accessories": RATGDOSensorType.RATGDO_PAIRED_ACCESSORIES, "paired_devices_accessories": RATGDOSensorType.RATGDO_PAIRED_ACCESSORIES,
"distance": RATGDOSensorType.RATGDO_DISTANCE
} }
@ -38,3 +40,15 @@ async def to_code(config):
await cg.register_component(var, config) await cg.register_component(var, config)
cg.add(var.set_ratgdo_sensor_type(config[CONF_TYPE])) cg.add(var.set_ratgdo_sensor_type(config[CONF_TYPE]))
await register_ratgdo_child(var, config) await register_ratgdo_child(var, config)
if config['type'] == 'distance':
cg.add_library(
name="Wire",
version=None
)
cg.add_library(
name="vl53l4cx",
repository="https://github.com/stm32duino/VL53L4CX",
version=None,
)
cg.add_define("USE_DISTANCE")

View File

@ -33,6 +33,22 @@ namespace ratgdo {
this->parent_->subscribe_paired_accessories([=](uint16_t value) { this->parent_->subscribe_paired_accessories([=](uint16_t value) {
this->publish_state(value); this->publish_state(value);
}); });
} else if (this->ratgdo_sensor_type_ == RATGDOSensorType::RATGDO_DISTANCE) {
#ifdef USE_DISTANCE
this->distance_sensor_.setI2cDevice(&I2C);
this->distance_sensor_.setXShutPin(32);
// I2C.begin(17,16);
I2C.begin(19, 18);
this->distance_sensor_.begin();
this->distance_sensor_.VL53L4CX_Off();
this->distance_sensor_.InitSensor(0x59);
this->distance_sensor_.VL53L4CX_SetDistanceMode(VL53L4CX_DISTANCEMODE_LONG);
this->distance_sensor_.VL53L4CX_StartMeasurement();
this->parent_->subscribe_distance_measurement([=](int16_t value) {
this->publish_state(value);
});
#endif
} }
} }
@ -51,8 +67,46 @@ namespace ratgdo {
ESP_LOGCONFIG(TAG, " Type: Paired Wall Controls"); ESP_LOGCONFIG(TAG, " Type: Paired Wall Controls");
} else if (this->ratgdo_sensor_type_ == RATGDOSensorType::RATGDO_PAIRED_ACCESSORIES) { } else if (this->ratgdo_sensor_type_ == RATGDOSensorType::RATGDO_PAIRED_ACCESSORIES) {
ESP_LOGCONFIG(TAG, " Type: Paired Accessories"); ESP_LOGCONFIG(TAG, " Type: Paired Accessories");
} else if (this->ratgdo_sensor_type_ == RATGDOSensorType::RATGDO_DISTANCE) {
ESP_LOGCONFIG(TAG, " Type: Distance");
} }
} }
void RATGDOSensor::loop()
{
#ifdef USE_DISTANCE
if (this->ratgdo_sensor_type_ == RATGDOSensorType::RATGDO_DISTANCE) {
VL53L4CX_MultiRangingData_t distanceData;
VL53L4CX_MultiRangingData_t* pDistanceData = &distanceData;
uint8_t dataReady = 0;
int objCount = 0;
int16_t maxDistance = 0;
int status;
if (this->distance_sensor_.VL53L4CX_GetMeasurementDataReady(&dataReady) == 0 && dataReady) {
status = this->distance_sensor_.VL53L4CX_GetMultiRangingData(pDistanceData);
objCount = pDistanceData->NumberOfObjectsFound;
maxDistance = objCount == 0 ? -1 : pDistanceData->RangeData[objCount - 1].RangeMilliMeter;
/* if(maxDistance < 0) maxDistance = -1;
* if the sensor is pointed at glass, there are many error readings which will fill the
* vector with out of range data. The sensor should be sensitive enough to detect the floor
* in most situations, unless its mounted really far away.
* If this doesn't work, then the vector size will have to increase substantially
*/
if (maxDistance > 0) {
this->parent_->set_distance_measurement(maxDistance);
}
// ESP_LOGD(TAG,"# obj found %d; distance %d",objCount, maxDistance);
if (status == 0) {
status = this->distance_sensor_.VL53L4CX_ClearInterruptAndStartMeasurement();
}
}
}
#endif
}
} // namespace ratgdo } // namespace ratgdo
} // namespace esphome } // namespace esphome

View File

@ -5,6 +5,12 @@
#include "esphome/components/sensor/sensor.h" #include "esphome/components/sensor/sensor.h"
#include "esphome/core/component.h" #include "esphome/core/component.h"
#ifdef USE_DISTANCE
#include "Wire.h"
#include "vl53l4cx_class.h"
#define I2C Wire
#endif
namespace esphome { namespace esphome {
namespace ratgdo { namespace ratgdo {
@ -14,17 +20,23 @@ namespace ratgdo {
RATGDO_PAIRED_REMOTES, RATGDO_PAIRED_REMOTES,
RATGDO_PAIRED_KEYPADS, RATGDO_PAIRED_KEYPADS,
RATGDO_PAIRED_WALL_CONTROLS, RATGDO_PAIRED_WALL_CONTROLS,
RATGDO_PAIRED_ACCESSORIES RATGDO_PAIRED_ACCESSORIES,
RATGDO_DISTANCE
}; };
class RATGDOSensor : public sensor::Sensor, public RATGDOClient, public Component { class RATGDOSensor : public sensor::Sensor, public RATGDOClient, public Component {
public: public:
void dump_config() override; void dump_config() override;
void setup() override; void setup() override;
void loop() override;
void set_ratgdo_sensor_type(RATGDOSensorType ratgdo_sensor_type_) { this->ratgdo_sensor_type_ = ratgdo_sensor_type_; } void set_ratgdo_sensor_type(RATGDOSensorType ratgdo_sensor_type_) { this->ratgdo_sensor_type_ = ratgdo_sensor_type_; }
protected: protected:
RATGDOSensorType ratgdo_sensor_type_; RATGDOSensorType ratgdo_sensor_type_;
#ifdef USE_DISTANCE
VL53L4CX distance_sensor_;
#endif
}; };
} // namespace ratgdo } // namespace ratgdo

View File

@ -1,7 +1,8 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import switch from esphome.components import switch
from esphome.const import CONF_ID from esphome import pins
from esphome.const import CONF_ID, CONF_PIN
from .. import RATGDO_CLIENT_SCHMEA, ratgdo_ns, register_ratgdo_child from .. import RATGDO_CLIENT_SCHMEA, ratgdo_ns, register_ratgdo_child
@ -13,6 +14,7 @@ SwitchType = ratgdo_ns.enum("SwitchType")
CONF_TYPE = "type" CONF_TYPE = "type"
TYPES = { TYPES = {
"learn": SwitchType.RATGDO_LEARN, "learn": SwitchType.RATGDO_LEARN,
"led": SwitchType.RATGDO_LED
} }
@ -21,6 +23,7 @@ CONFIG_SCHEMA = (
.extend( .extend(
{ {
cv.Required(CONF_TYPE): cv.enum(TYPES, lower=True), cv.Required(CONF_TYPE): cv.enum(TYPES, lower=True),
cv.Optional(CONF_PIN): pins.gpio_output_pin_schema,
} }
) )
.extend(RATGDO_CLIENT_SCHMEA) .extend(RATGDO_CLIENT_SCHMEA)
@ -33,3 +36,6 @@ async def to_code(config):
await cg.register_component(var, config) await cg.register_component(var, config)
cg.add(var.set_switch_type(config[CONF_TYPE])) cg.add(var.set_switch_type(config[CONF_TYPE]))
await register_ratgdo_child(var, config) await register_ratgdo_child(var, config)
if CONF_PIN in config:
pin = await cg.gpio_pin_expression(config[CONF_PIN])
cg.add(var.set_pin(pin))

View File

@ -21,6 +21,11 @@ namespace ratgdo {
this->parent_->subscribe_learn_state([=](LearnState state) { this->parent_->subscribe_learn_state([=](LearnState state) {
this->publish_state(state == LearnState::ACTIVE); this->publish_state(state == LearnState::ACTIVE);
}); });
} else if (this->switch_type_ == SwitchType::RATGDO_LED) {
this->pin_->setup();
this->parent_->subscribe_vehicle_arriving_state([=](VehicleArrivingState state) {
this->write_state(state == VehicleArrivingState::YES);
});
} }
} }
@ -32,6 +37,9 @@ namespace ratgdo {
} else { } else {
this->parent_->inactivate_learn(); this->parent_->inactivate_learn();
} }
} else if (this->switch_type_ == SwitchType::RATGDO_LED) {
this->pin_->digital_write(state);
this->publish_state(state);
} }
} }

View File

@ -9,7 +9,8 @@ namespace esphome {
namespace ratgdo { namespace ratgdo {
enum SwitchType { enum SwitchType {
RATGDO_LEARN RATGDO_LEARN,
RATGDO_LED
}; };
class RATGDOSwitch : public switch_::Switch, public RATGDOClient, public Component { class RATGDOSwitch : public switch_::Switch, public RATGDOClient, public Component {
@ -19,9 +20,11 @@ namespace ratgdo {
void set_switch_type(SwitchType switch_type_) { this->switch_type_ = switch_type_; } void set_switch_type(SwitchType switch_type_) { this->switch_type_ = switch_type_; }
void write_state(bool state) override; void write_state(bool state) override;
void set_pin(GPIOPin* pin) { pin_ = pin; }
protected: protected:
SwitchType switch_type_; SwitchType switch_type_;
GPIOPin* pin_;
}; };
} // namespace ratgdo } // namespace ratgdo

View File

@ -177,7 +177,7 @@
/> />
<h1>ESPHome ratgdo</h1> <h1>ESPHome ratgdo</h1>
<p> <p>
In order to install the firmware, first pick your door opener control protocol, then pick your <a href="https://paulwieland.github.io/ratgdo/">ratgdo control board</a> version. In order to install the firmware, first pick your door opener control protocol, then pick your <a href="https://ratcloud.llc/">ratgdo control board</a> version.
No programming or other software required. No programming or other software required.
</p> </p>
@ -209,33 +209,49 @@
<h2>Choose your ratgdo control board:</h2> <h2>Choose your ratgdo control board:</h2>
<div class="hardware radios"> <div class="hardware radios">
<label>
<img src="./ratgdo32_disco.jpg" alt="v32 disco" />
<input type="radio" name="hardware" value="v32disco" checked />
ratgdo32 disco
</label>
<label>
<img src="./ratgdo32.jpg" alt="v32 board" />
<input type="radio" name="hardware" value="v32board" checked />
ratgdo32
</label>
<label> <label>
<img src="./ratgdo_v2.5xi.jpg" alt="v2.5i, v2.52i, v2.53i" /> <img src="./ratgdo_v2.5xi.jpg" alt="v2.5i, v2.52i, v2.53i" />
<input type="radio" name="hardware" value="v25iboard" checked /> <input type="radio" name="hardware" value="v25iboard" checked />
ratgdo v2.5x<br/> ratgdo v2.5x<br/>
v2.5, v2.5i, v2.52i, v2.53i (black PCB) v2.5, v2.5i, v2.52i, v2.53i (black PCB)
</label> </label>
</div>
<label> <a id="show_legacy_hardware" style="text-decoration: underline;" onclick="toggleLegacy()">Show Legacy Hardware &raquo;</a>
<img src="./ratgdo_v2.0.jpg" alt="v2.0" />
<input type="radio" name="hardware" value="v2board_esp8266_d1_mini" />
ratgdo v2.0<br/>
ESP8266 / D1 Mini (white PCB)
</label>
<label> <div class="hardware radios" id="legacy_hardware" style="display: none">
<img src="./v25board_esp32_d1_mini.png" alt="v2.5 esp32" /> <label>
<input type="radio" name="hardware" value="v25board_esp32_d1_mini" /> <img src="./ratgdo_v2.0.jpg" alt="v2.0" />
ratgdo v2.5<br/> <input type="radio" name="hardware" value="v2board_esp8266_d1_mini" />
ESP32 (black PCB) ratgdo v2.0<br/>
</label> ESP8266 / D1 Mini (white PCB)
</label>
<label> <label>
<img src="./v2board_esp32_d1_mini.png" alt="v2.0 esp32" /> <img src="./v25board_esp32_d1_mini.png" alt="v2.5 esp32" />
<input type="radio" name="hardware" value="v2board_esp32_d1_mini" /> <input type="radio" name="hardware" value="v25board_esp32_d1_mini" />
ratgdo v2.0<br/> ratgdo v2.5<br/>
ESP32 (white PCB) ESP32 (black PCB)
</label> </label>
<label>
<img src="./v2board_esp32_d1_mini.png" alt="v2.0 esp32" />
<input type="radio" name="hardware" value="v2board_esp32_d1_mini" />
ratgdo v2.0<br/>
ESP32 (white PCB)
</label>
</div> </div>
<p> <p>
@ -244,7 +260,7 @@
<h2>Wiring Diagram</h2> <h2>Wiring Diagram</h2>
<img id="wiring_diagram" src="wiring_diagrams/secplus_diagram.png" alt="Security + 1 and 2 wiring diagram" /> <img id="wiring_diagram" src="wiring_diagrams/v25iboard_secplus.png" alt="Security + 1 and 2 wiring diagram" />
<h3>Documentation</h3> <h3>Documentation</h3>
<ul> <ul>
@ -255,12 +271,10 @@
<h3>Drivers</h3> <h3>Drivers</h3>
<p>If you can't connect to your ratgdo board make sure you have the right driver installed for the type of board you have.</p> <p>If you can't connect to your ratgdo board make sure you have the right driver installed for the type of board you have.</p>
<ul> <ul>
<li>ratgdo32 disco uses a CH9102 USB to Serial chipset. [<a href="https://www.wch-ic.com/downloads/CH343SER_EXE.html" target="_blank">driver download</a>]</li>
<li>ratgdo v2.5i uses a CH340 USB to Serial chipset. [<a href="https://www.wch-ic.com/downloads/CH341SER_EXE.html" target="_blank">driver download</a>]</li> <li>ratgdo v2.5i uses a CH340 USB to Serial chipset. [<a href="https://www.wch-ic.com/downloads/CH341SER_EXE.html" target="_blank">driver download</a>]</li>
<li>Most D1 Minis use an FTDI USB to Serial chipset. [<a href="https://ftdichip.com/drivers/vcp-drivers/" target="_blank">driver download</a>]</li>
</ul> </ul>
<p>Watch the driver and firmware installation [<a href="https://www.youtube.com/watch?v=9WecAUTC9iI">video on YouTube</a>].</p> <p>Watch the v2.5i driver and firmware installation [<a href="https://www.youtube.com/watch?v=9WecAUTC9iI">video on YouTube</a>].</p>
<!-- <iframe width="640" height="360" src="https://youtube.com/embed/9WecAUTC9iI"></iframe> -->
<h3>Advanced Users</h3> <h3>Advanced Users</h3>
<ul> <ul>
@ -284,17 +298,31 @@
</div> </div>
</div> </div>
<script> <script>
function toggleLegacy() {
var x = document.querySelector("#legacy_hardware");
var y = document.querySelector("#show_legacy_hardware");
if (x.style.display === "none") {
x.style.display = "flex";
y.innerHTML = "hide legacy hardware &raquo;";
} else {
x.style.display = "none";
y.innerHTML = "show legacy hardware &raquo;";
}
}
document.querySelectorAll('div.radios input').forEach((radio) => document.querySelectorAll('div.radios input').forEach((radio) =>
radio.addEventListener("change", () => { radio.addEventListener("change", () => {
const button = document.querySelector("esp-web-install-button"); const button = document.querySelector("esp-web-install-button");
var protocol = document.querySelector('input[name="protocol"]:checked').value; var protocol = document.querySelector('input[name="protocol"]:checked').value;
var hardware = document.querySelector('input[name="hardware"]:checked').value; var hardware = document.querySelector('input[name="hardware"]:checked').value;
if(protocol === "drycontact"){ var diagram_protocol = protocol.replace("v1","").replace("v2","");
document.querySelector("#wiring_diagram").src = "wiring_diagrams/dry_contact_diagram.png"; var img = document.querySelector("#wiring_diagram");
}else{ img.onerror = function() {
document.querySelector("#wiring_diagram").src = "wiring_diagrams/secplus_diagram.png"; console.log(`img not found: ${this.src}`);
this.src = "wiring_diagrams/v25iboard_secplus.png";
} }
img.src = `wiring_diagrams/${hardware}_${diagram_protocol}.png`;
if(protocol !== "secplusv2" && (hardware === "v2board_esp8266_d1_mini" || hardware === "v2board_esp32_d1_mini")){ if(protocol !== "secplusv2" && (hardware === "v2board_esp8266_d1_mini" || hardware === "v2board_esp32_d1_mini")){
alert("ratgdo version 2.0 only works with Security + 2.0"); alert("ratgdo version 2.0 only works with Security + 2.0");

BIN
static/ratgdo32.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

BIN
static/ratgdo32_disco.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

View File

@ -33,6 +33,8 @@ packages:
url: https://github.com/ratgdo/esphome-ratgdo url: https://github.com/ratgdo/esphome-ratgdo
files: [base.yaml] files: [base.yaml]
refresh: 1s refresh: 1s
# remote_package: !include
# file: base.yaml
# Sync time with Home Assistant. # Sync time with Home Assistant.
time: time:

View File

@ -34,6 +34,7 @@ packages:
refresh: 1s refresh: 1s
# remote_package: !include # remote_package: !include
# file: base_drycontact.yaml # file: base_drycontact.yaml
# Sync time with Home Assistant. # Sync time with Home Assistant.
time: time:
- platform: homeassistant - platform: homeassistant

66
static/v32board.yaml Normal file
View File

@ -0,0 +1,66 @@
---
substitutions:
id_prefix: ratgdov32
friendly_name: "ratgdov32"
uart_tx_pin: GPIO17
uart_rx_pin: GPIO21
input_obst_pin: GPIO4
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:
esphome:
name: ${id_prefix}
friendly_name: ${friendly_name}
name_add_mac_suffix: true
project:
name: ratgdo.esphome
version: "32.0"
esp32:
board: esp32dev
dashboard_import:
package_import_url: github://ratgdo/esphome-ratgdo/v32board.yaml@main
packages:
remote_package:
url: https://github.com/ratgdo/esphome-ratgdo
ref: ratgdo32
files: [base.yaml]
refresh: 1s
# remote_package: !include
# file: base.yaml
switch:
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_led
type: led
pin: GPIO2
name: "LED"
entity_category: config
sensor:
- platform: wifi_signal
name: "WiFi Signal"
update_interval: 120s
# Sync time with Home Assistant.
time:
- platform: homeassistant
id: homeassistant_time
api:
id: api_server
improv_serial:
wifi:
ap:
logger:

View File

@ -0,0 +1,65 @@
---
substitutions:
id_prefix: ratgdo32disco
friendly_name: "ratgdo32disco"
uart_tx_pin: GPIO17
uart_rx_pin: GPIO21
input_obst_pin: GPIO4
dry_contact_open_pin: GPIO13
dry_contact_close_pin: GPIO14
discrete_open_pin: GPIO26
discrete_close_pin: GPIO25
web_server:
esphome:
name: ${id_prefix}
friendly_name: ${friendly_name}
name_add_mac_suffix: true
project:
name: ratgdo.esphome
version: "32.0"
esp32:
board: esp32dev
dashboard_import:
package_import_url: github://ratgdo/esphome-ratgdo/v32board_drycontact.yaml@main
packages:
remote_package:
url: https://github.com/ratgdo/esphome-ratgdo
ref: ratgdo32
files: [base_drycontact.yaml]
refresh: 1s
# remote_package: !include
# file: base_drycontact.yaml
switch:
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_led
type: led
pin: GPIO2
name: "LED"
entity_category: config
sensor:
- platform: wifi_signal
name: "WiFi Signal"
update_interval: 120s
# Sync time with Home Assistant.
time:
- platform: homeassistant
id: homeassistant_time
api:
id: api_server
improv_serial:
wifi:
ap:
logger:

View File

@ -0,0 +1,66 @@
---
substitutions:
id_prefix: ratgdov32
friendly_name: "ratgdov32"
uart_tx_pin: GPIO17
uart_rx_pin: GPIO21
input_obst_pin: GPIO4
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:
esphome:
name: ${id_prefix}
friendly_name: ${friendly_name}
name_add_mac_suffix: true
project:
name: ratgdo.esphome
version: "32.0"
esp32:
board: esp32dev
dashboard_import:
package_import_url: github://ratgdo/esphome-ratgdo/v32board_secplusv1.yaml@main
packages:
remote_package:
url: https://github.com/ratgdo/esphome-ratgdo
ref: ratgdo32
files: [base_secplusv1.yaml]
refresh: 1s
# remote_package: !include
# file: base_secplusv1.yaml
switch:
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_led
type: led
pin: GPIO2
name: "LED"
entity_category: config
sensor:
- platform: wifi_signal
name: "WiFi Signal"
update_interval: 120s
# Sync time with Home Assistant.
time:
- platform: homeassistant
id: homeassistant_time
api:
id: api_server
improv_serial:
wifi:
ap:
logger:

153
static/v32disco.yaml Normal file
View File

@ -0,0 +1,153 @@
---
substitutions:
id_prefix: ratgdo32disco
friendly_name: "ratgdo32disco"
uart_tx_pin: GPIO17
uart_rx_pin: GPIO21
input_obst_pin: GPIO4
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:
esphome:
name: ${id_prefix}
friendly_name: ${friendly_name}
name_add_mac_suffix: true
project:
name: ratgdo.esphome
version: "32disco"
esp32:
board: esp32dev
dashboard_import:
package_import_url: github://ratgdo/esphome-ratgdo/v32disco.yaml@main
packages:
remote_package:
url: https://github.com/ratgdo/esphome-ratgdo
ref: ratgdo32
files: [base.yaml]
refresh: 1s
# remote_package: !include
# file: base.yaml
# Sync time with Home Assistant.
time:
- platform: homeassistant
id: homeassistant_time
api:
id: api_server
improv_serial:
wifi:
ap:
logger:
ota:
binary_sensor:
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_vehicle_detected
type: vehicle_detected
name: "Vehicle detected"
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_vehicle_arriving
type: vehicle_arriving
name: "Vehicle arriving"
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_vehicle_leaving
type: vehicle_leaving
name: "Vehicle leaving"
number:
- platform: ratgdo
id: ${id_prefix}_target_distance_measurement
type: target_distance_measurement
entity_category: config
ratgdo_id: ${id_prefix}
name: "Vehicle distance target"
mode: box
unit_of_measurement: "mm"
- platform: ratgdo
id: ${id_prefix}_closing_delay
type: closing_delay
entity_category: config
ratgdo_id: ${id_prefix}
name: "Closing Delay"
unit_of_measurement: "s"
output:
- platform: ledc
pin: GPIO33
id: ${id_prefix}_ledc
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_beeper
type: beeper
rtttl: ${id_prefix}_rtttl
song: "alert:d=8,o=5,b=120:a,p,a,p,a,p,4b,p"
rtttl:
- id: ${id_prefix}_rtttl
output: ${id_prefix}_ledc
switch:
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_led
type: led
pin: GPIO2
name: "LED"
entity_category: config
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_laser
type: led
pin: GPIO23
name: "LASER"
entity_category: config
sensor:
- platform: wifi_signal
name: "WiFi Signal"
update_interval: 120s
- platform: ratgdo
id: ${id_prefix}_vehicle_distance_actual
type: distance
name: "Vehicle distance actual"
ratgdo_id: ${id_prefix}
unit_of_measurement: "mm"
filters:
- throttle: 1s
- filter_out: -1
- median:
window_size: 20
send_every: 5
send_first_at: 5
- platform: adc
pin: GPIO34
name: "Voltage"
attenuation: auto
update_interval: 60s
filters:
- calibrate_linear:
- 1.16 -> 5
- 2.783 -> 12
# uncomment to convert voltage scale to a % for lead acid batteries
# - 2.43 -> 0 # 10.5v = 0%
# - 2.98 -> 100 # 12.85 = 100%
# - clamp:
# min_value: 0
# max_value: 100
# unit_of_measurement: "%"

View File

@ -0,0 +1,145 @@
---
substitutions:
id_prefix: ratgdo32disco
friendly_name: "ratgdo32disco"
uart_tx_pin: GPIO17
uart_rx_pin: GPIO21
input_obst_pin: GPIO4
dry_contact_open_pin: GPIO13
dry_contact_close_pin: GPIO14
discrete_open_pin: GPIO26
discrete_close_pin: GPIO25
web_server:
esphome:
name: ${id_prefix}
friendly_name: ${friendly_name}
name_add_mac_suffix: true
project:
name: ratgdo.esphome
version: "32disco"
esp32:
board: esp32dev
dashboard_import:
package_import_url: github://ratgdo/esphome-ratgdo/v32disco_drycontact.yaml@main
packages:
remote_package:
url: https://github.com/ratgdo/esphome-ratgdo
ref: ratgdo32
files: [base_drycontact.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
improv_serial:
wifi:
ap:
logger:
ota:
binary_sensor:
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_vehicle_detected
type: vehicle_detected
name: "Vehicle detected"
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_vehicle_arriving
type: vehicle_arriving
name: "Vehicle arriving"
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_vehicle_leaving
type: vehicle_leaving
name: "Vehicle leaving"
number:
- platform: ratgdo
id: ${id_prefix}_target_distance_measurement
type: target_distance_measurement
entity_category: config
ratgdo_id: ${id_prefix}
name: "Vehicle distance target"
mode: box
unit_of_measurement: "mm"
- platform: ratgdo
id: ${id_prefix}_closing_delay
type: closing_delay
entity_category: config
ratgdo_id: ${id_prefix}
name: "Closing Delay"
unit_of_measurement: "s"
output:
- platform: ledc
pin: GPIO33
id: ${id_prefix}_ledc
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_beeper
type: beeper
rtttl: ${id_prefix}_rtttl
song: "alert:d=8,o=5,b=120:a,p,a,p,a,p,4b,p"
rtttl:
- id: ${id_prefix}_rtttl
output: ${id_prefix}_ledc
switch:
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_led
type: led
pin: GPIO2
name: "LED"
entity_category: config
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_laser
type: led
pin: GPIO23
name: "LASER"
entity_category: config
sensor:
- platform: wifi_signal
name: "WiFi Signal"
update_interval: 120s
- platform: ratgdo
id: ${id_prefix}_vehicle_distance_actual
type: distance
name: "Vehicle distance actual"
ratgdo_id: ${id_prefix}
unit_of_measurement: "mm"
filters:
- throttle: 10s
- filter_out: -1
- median:
window_size: 20
send_every: 5
send_first_at: 5
- platform: adc
pin: GPIO34
name: "Voltage"
attenuation: auto
update_interval: 60s
filters:
- calibrate_linear:
- 1.16 -> 5
- 2.783 -> 12

View File

@ -0,0 +1,146 @@
---
substitutions:
id_prefix: ratgdo32disco
friendly_name: "ratgdo32disco"
uart_tx_pin: GPIO17
uart_rx_pin: GPIO21
input_obst_pin: GPIO4
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:
esphome:
name: ${id_prefix}
friendly_name: ${friendly_name}
name_add_mac_suffix: true
project:
name: ratgdo.esphome
version: "32disco"
esp32:
board: esp32dev
dashboard_import:
package_import_url: github://ratgdo/esphome-ratgdo/v32disco_secplusv1.yaml@main
packages:
remote_package:
url: https://github.com/ratgdo/esphome-ratgdo
ref: ratgdo32
files: [base_secplusv1.yaml]
refresh: 1s
# remote_package: !include
# file: base_secplusv1.yaml
# Sync time with Home Assistant.
time:
- platform: homeassistant
id: homeassistant_time
api:
id: api_server
improv_serial:
wifi:
ap:
logger:
ota:
binary_sensor:
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_vehicle_detected
type: vehicle_detected
name: "Vehicle detected"
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_vehicle_arriving
type: vehicle_arriving
name: "Vehicle arriving"
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_vehicle_leaving
type: vehicle_leaving
name: "Vehicle leaving"
number:
- platform: ratgdo
id: ${id_prefix}_target_distance_measurement
type: target_distance_measurement
entity_category: config
ratgdo_id: ${id_prefix}
name: "Vehicle distance target"
mode: box
unit_of_measurement: "mm"
- platform: ratgdo
id: ${id_prefix}_closing_delay
type: closing_delay
entity_category: config
ratgdo_id: ${id_prefix}
name: "Closing Delay"
unit_of_measurement: "s"
output:
- platform: ledc
pin: GPIO33
id: ${id_prefix}_ledc
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_beeper
type: beeper
rtttl: ${id_prefix}_rtttl
song: "alert:d=8,o=5,b=120:a,p,a,p,a,p,4b,p"
rtttl:
- id: ${id_prefix}_rtttl
output: ${id_prefix}_ledc
switch:
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_led
type: led
pin: GPIO2
name: "LED"
entity_category: config
- platform: ratgdo
ratgdo_id: ${id_prefix}
id: ${id_prefix}_laser
type: led
pin: GPIO23
name: "LASER"
entity_category: config
sensor:
- platform: wifi_signal
name: "WiFi Signal"
update_interval: 120s
- platform: ratgdo
id: ${id_prefix}_vehicle_distance_actual
type: distance
name: "Vehicle distance actual"
ratgdo_id: ${id_prefix}
unit_of_measurement: "mm"
filters:
- throttle: 10s
- filter_out: -1
- median:
window_size: 20
send_every: 5
send_first_at: 5
- platform: adc
pin: GPIO34
name: "Voltage"
attenuation: auto
update_interval: 60s
filters:
- calibrate_linear:
- 1.16 -> 5
- 2.783 -> 12

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 554 KiB

After

Width:  |  Height:  |  Size: 554 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

1
v32board.yaml Symbolic link
View File

@ -0,0 +1 @@
static/v32board.yaml

1
v32board_drycontact.yaml Symbolic link
View File

@ -0,0 +1 @@
static/v32board_drycontact.yaml

1
v32board_secplusv1.yaml Symbolic link
View File

@ -0,0 +1 @@
static/v32board_secplusv1.yaml

1
v32disco.yaml Symbolic link
View File

@ -0,0 +1 @@
static/v32disco.yaml

1
v32disco_drycontact.yaml Symbolic link
View File

@ -0,0 +1 @@
static/v32disco_drycontact.yaml

1
v32disco_secplusv1.yaml Symbolic link
View File

@ -0,0 +1 @@
static/v32disco_secplusv1.yaml