Make storing persistent state the resposibility of ratgdo_number (#30)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
3721bb5465
commit
bd36a7e6a3
|
@ -22,6 +22,10 @@ The ESPHome firmware will allow you to open the door to any position after calib
|
||||||
<img width="560" alt="position_demo" src="https://github.com/ESPHome-RATGDO/esphome-ratgdo/assets/663432/22a9873e-67bb-4b2f-bb32-70047cfe666d">
|
<img width="560" alt="position_demo" src="https://github.com/ESPHome-RATGDO/esphome-ratgdo/assets/663432/22a9873e-67bb-4b2f-bb32-70047cfe666d">
|
||||||
|
|
||||||
|
|
||||||
|
## Updating from versions older than 2023.07.07
|
||||||
|
|
||||||
|
When updating from older versions, save the rolling counter value and restore it via the number entity after flashing the new firmware. If you forget to save the code, check the Home Assistant history.
|
||||||
|
|
||||||
# ESPHome config
|
# ESPHome config
|
||||||
|
|
||||||
- [ESPHome config for v2 board with ESP8266 D1 Mini lite](https://github.com/ESPHome-RATGDO/esphome-ratgdo/blob/main/static/v2board_esp8266_d1_mini_lite.yaml)
|
- [ESPHome config for v2 board with ESP8266 D1 Mini lite](https://github.com/ESPHome-RATGDO/esphome-ratgdo/blob/main/static/v2board_esp8266_d1_mini_lite.yaml)
|
||||||
|
|
|
@ -15,6 +15,14 @@ ratgdo:
|
||||||
output_gdo_pin: ${uart_tx_pin}
|
output_gdo_pin: ${uart_tx_pin}
|
||||||
input_obst_pin: ${input_obst_pin}
|
input_obst_pin: ${input_obst_pin}
|
||||||
remote_id: 0x539
|
remote_id: 0x539
|
||||||
|
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; Check the ${friendly_name} Rolling code counter number entity history and set the entity to one number larger than the largest value in history. [ESPHome devices](/config/devices/dashboard?domain=esphome)"
|
||||||
|
notification_id: "esphome_ratgdo_${id_prefix}_sync_failed"
|
||||||
|
|
||||||
sensor:
|
sensor:
|
||||||
- platform: ratgdo
|
- platform: ratgdo
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome import pins
|
from esphome import automation, pins
|
||||||
from esphome.const import CONF_ID
|
from esphome.const import CONF_ID, CONF_TRIGGER_ID
|
||||||
|
|
||||||
DEPENDENCIES = ["preferences"]
|
DEPENDENCIES = ["preferences"]
|
||||||
MULTI_CONF = True
|
MULTI_CONF = True
|
||||||
|
@ -11,6 +11,8 @@ ratgdo_ns = cg.esphome_ns.namespace("ratgdo")
|
||||||
RATGDO = ratgdo_ns.class_("RATGDOComponent", cg.Component)
|
RATGDO = ratgdo_ns.class_("RATGDOComponent", cg.Component)
|
||||||
|
|
||||||
|
|
||||||
|
SyncFailed = ratgdo_ns.class_("SyncFailed", automation.Trigger.template())
|
||||||
|
|
||||||
CONF_OUTPUT_GDO = "output_gdo_pin"
|
CONF_OUTPUT_GDO = "output_gdo_pin"
|
||||||
DEFAULT_OUTPUT_GDO = (
|
DEFAULT_OUTPUT_GDO = (
|
||||||
"D4" # D4 red control terminal / GarageDoorOpener (UART1 TX) pin is D4 on D1 Mini
|
"D4" # D4 red control terminal / GarageDoorOpener (UART1 TX) pin is D4 on D1 Mini
|
||||||
|
@ -27,6 +29,9 @@ DEFAULT_REMOTE_ID = 0x539
|
||||||
|
|
||||||
CONF_RATGDO_ID = "ratgdo_id"
|
CONF_RATGDO_ID = "ratgdo_id"
|
||||||
|
|
||||||
|
CONF_ON_SYNC_FAILED = "on_sync_failed"
|
||||||
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.Schema(
|
CONFIG_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(RATGDO),
|
cv.GenerateID(): cv.declare_id(RATGDO),
|
||||||
|
@ -42,6 +47,11 @@ CONFIG_SCHEMA = cv.Schema(
|
||||||
cv.Optional(
|
cv.Optional(
|
||||||
CONF_REMOTE_ID, default=DEFAULT_REMOTE_ID
|
CONF_REMOTE_ID, default=DEFAULT_REMOTE_ID
|
||||||
): cv.uint64_t,
|
): cv.uint64_t,
|
||||||
|
cv.Optional(CONF_ON_SYNC_FAILED): automation.validate_automation(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SyncFailed),
|
||||||
|
}
|
||||||
|
),
|
||||||
}
|
}
|
||||||
).extend(cv.COMPONENT_SCHEMA)
|
).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
|
||||||
|
@ -67,6 +77,10 @@ async def to_code(config):
|
||||||
pin = await cg.gpio_pin_expression(config[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_input_obst_pin(pin))
|
||||||
cg.add(var.set_remote_id(config[CONF_REMOTE_ID]))
|
cg.add(var.set_remote_id(config[CONF_REMOTE_ID]))
|
||||||
|
|
||||||
|
for conf in config.get(CONF_ON_SYNC_FAILED, []):
|
||||||
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
await automation.build_automation(trigger, [], conf)
|
||||||
|
|
||||||
cg.add_library(
|
cg.add_library(
|
||||||
name="secplus",
|
name="secplus",
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/automation.h"
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "ratgdo.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ratgdo {
|
||||||
|
|
||||||
|
class SyncFailed : public Trigger<> {
|
||||||
|
public:
|
||||||
|
explicit SyncFailed(RATGDOComponent* parent)
|
||||||
|
{
|
||||||
|
parent->subscribe_sync_failed([this](bool state) {
|
||||||
|
if (state)
|
||||||
|
this->trigger();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,10 @@ namespace ratgdo {
|
||||||
|
|
||||||
void RATGDOCover::setup()
|
void RATGDOCover::setup()
|
||||||
{
|
{
|
||||||
|
auto state = this->restore_state_();
|
||||||
|
if (state.has_value()) {
|
||||||
|
this->parent_->set_door_position(state.value().position);
|
||||||
|
}
|
||||||
this->parent_->subscribe_door_state([=](DoorState state, float position) {
|
this->parent_->subscribe_door_state([=](DoorState state, float position) {
|
||||||
this->on_door_state(state, position);
|
this->on_door_state(state, position);
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace ratgdo {
|
||||||
|
|
||||||
void RATGDOLightOutput::dump_config()
|
void RATGDOLightOutput::dump_config()
|
||||||
{
|
{
|
||||||
ESP_LOGCONFIG("", "RATGDO Light");
|
ESP_LOGCONFIG(TAG, "RATGDO Light");
|
||||||
}
|
}
|
||||||
|
|
||||||
void RATGDOLightOutput::setup()
|
void RATGDOLightOutput::setup()
|
||||||
|
|
|
@ -21,17 +21,25 @@ namespace ratgdo {
|
||||||
|
|
||||||
void RATGDONumber::setup()
|
void RATGDONumber::setup()
|
||||||
{
|
{
|
||||||
|
float value;
|
||||||
|
this->pref_ = global_preferences->make_preference<float>(this->get_object_id_hash());
|
||||||
|
if (!this->pref_.load(&value)) {
|
||||||
|
value = 0;
|
||||||
|
}
|
||||||
|
this->publish_state(value);
|
||||||
|
this->control(value);
|
||||||
|
|
||||||
if (this->number_type_ == RATGDO_ROLLING_CODE_COUNTER) {
|
if (this->number_type_ == RATGDO_ROLLING_CODE_COUNTER) {
|
||||||
this->parent_->subscribe_rolling_code_counter([=](uint32_t value) {
|
this->parent_->subscribe_rolling_code_counter([=](uint32_t value) {
|
||||||
this->publish_state(value);
|
this->update_state(value);
|
||||||
});
|
});
|
||||||
} else if (this->number_type_ == RATGDO_OPENING_DURATION) {
|
} else if (this->number_type_ == RATGDO_OPENING_DURATION) {
|
||||||
this->parent_->subscribe_opening_duration([=](float value) {
|
this->parent_->subscribe_opening_duration([=](float value) {
|
||||||
this->publish_state(value);
|
this->update_state(value);
|
||||||
});
|
});
|
||||||
} else if (this->number_type_ == RATGDO_CLOSING_DURATION) {
|
} else if (this->number_type_ == RATGDO_CLOSING_DURATION) {
|
||||||
this->parent_->subscribe_closing_duration([=](float value) {
|
this->parent_->subscribe_closing_duration([=](float value) {
|
||||||
this->publish_state(value);
|
this->update_state(value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,6 +57,12 @@ namespace ratgdo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RATGDONumber::update_state(float value)
|
||||||
|
{
|
||||||
|
this->pref_.save(&value);
|
||||||
|
this->publish_state(value);
|
||||||
|
}
|
||||||
|
|
||||||
void RATGDONumber::control(float value)
|
void RATGDONumber::control(float value)
|
||||||
{
|
{
|
||||||
if (this->number_type_ == RATGDO_ROLLING_CODE_COUNTER) {
|
if (this->number_type_ == RATGDO_ROLLING_CODE_COUNTER) {
|
||||||
|
@ -58,6 +72,7 @@ namespace ratgdo {
|
||||||
} 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);
|
||||||
}
|
}
|
||||||
|
this->pref_.save(&value);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ratgdo
|
} // namespace ratgdo
|
||||||
|
|
|
@ -18,12 +18,18 @@ namespace ratgdo {
|
||||||
public:
|
public:
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void set_number_type(NumberType number_type_);
|
void set_number_type(NumberType number_type);
|
||||||
|
// other esphome components that persist state in the flash have HARDWARE priority
|
||||||
|
// ensure we get initialized before them, so that the state doesn't get invalidated
|
||||||
|
// by components that might be added in the future
|
||||||
|
float get_setup_priority() const override { return setup_priority::HARDWARE + 1; }
|
||||||
|
|
||||||
|
void update_state(float value);
|
||||||
void control(float value) override;
|
void control(float value) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NumberType number_type_;
|
NumberType number_type_;
|
||||||
|
ESPPreferenceObject pref_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ratgdo
|
} // namespace ratgdo
|
||||||
|
|
|
@ -44,25 +44,6 @@ namespace ratgdo {
|
||||||
|
|
||||||
void RATGDOComponent::setup()
|
void RATGDOComponent::setup()
|
||||||
{
|
{
|
||||||
this->rolling_code_counter_pref_ = global_preferences->make_preference<int>(734874333U);
|
|
||||||
uint32_t rolling_code_counter = 0;
|
|
||||||
this->rolling_code_counter_pref_.load(&rolling_code_counter);
|
|
||||||
this->rolling_code_counter = rolling_code_counter;
|
|
||||||
// observers are subscribed in the setup() of children defer notify until after setup()
|
|
||||||
defer([=] { this->rolling_code_counter.notify(); });
|
|
||||||
|
|
||||||
this->opening_duration_pref_ = global_preferences->make_preference<float>(734874334U);
|
|
||||||
float opening_duration = 0;
|
|
||||||
this->opening_duration_pref_.load(&opening_duration);
|
|
||||||
this->set_opening_duration(opening_duration);
|
|
||||||
defer([=] { this->opening_duration.notify(); });
|
|
||||||
|
|
||||||
this->closing_duration_pref_ = global_preferences->make_preference<float>(734874335U);
|
|
||||||
float closing_duration = 0;
|
|
||||||
this->closing_duration_pref_.load(&closing_duration);
|
|
||||||
this->set_closing_duration(closing_duration);
|
|
||||||
defer([=] { this->closing_duration.notify(); });
|
|
||||||
|
|
||||||
this->output_gdo_pin_->setup();
|
this->output_gdo_pin_->setup();
|
||||||
this->input_gdo_pin_->setup();
|
this->input_gdo_pin_->setup();
|
||||||
this->input_obst_pin_->setup();
|
this->input_obst_pin_->setup();
|
||||||
|
@ -109,7 +90,7 @@ namespace ratgdo {
|
||||||
|
|
||||||
uint16_t cmd = ((fixed >> 24) & 0xf00) | (data & 0xff);
|
uint16_t cmd = ((fixed >> 24) & 0xf00) | (data & 0xff);
|
||||||
data &= ~0xf000; // clear parity nibble
|
data &= ~0xf000; // clear parity nibble
|
||||||
|
|
||||||
Command cmd_enum = to_Command(cmd, Command::UNKNOWN);
|
Command cmd_enum = to_Command(cmd, Command::UNKNOWN);
|
||||||
|
|
||||||
if ((fixed & 0xfffffff) == this->remote_id_) { // my commands
|
if ((fixed & 0xfffffff) == this->remote_id_) { // my commands
|
||||||
|
@ -212,8 +193,14 @@ namespace ratgdo {
|
||||||
this->button_state = (byte1 & 1) == 1 ? ButtonState::PRESSED : ButtonState::RELEASED;
|
this->button_state = (byte1 & 1) == 1 ? ButtonState::PRESSED : ButtonState::RELEASED;
|
||||||
ESP_LOGD(TAG, "Open: button=%s", ButtonState_to_string(*this->button_state));
|
ESP_LOGD(TAG, "Open: button=%s", ButtonState_to_string(*this->button_state));
|
||||||
} else if (cmd == Command::OPENINGS) {
|
} else if (cmd == Command::OPENINGS) {
|
||||||
this->openings = (byte1 << 8) | byte2;
|
// nibble==0 if it's our request
|
||||||
ESP_LOGD(TAG, "Openings: %d", *this->openings);
|
// update openings only from our request or if it's not unknown state
|
||||||
|
if (nibble == 0 || *this->openings != 0) {
|
||||||
|
this->openings = (byte1 << 8) | byte2;
|
||||||
|
ESP_LOGD(TAG, "Openings: %d", *this->openings);
|
||||||
|
} else {
|
||||||
|
ESP_LOGD(TAG, "Ignoreing openings, not from our request");
|
||||||
|
}
|
||||||
} else if (cmd == Command::MOTION) {
|
} else if (cmd == Command::MOTION) {
|
||||||
this->motion_state = MotionState::DETECTED;
|
this->motion_state = MotionState::DETECTED;
|
||||||
if (*this->light_state == LightState::OFF) {
|
if (*this->light_state == LightState::OFF) {
|
||||||
|
@ -247,7 +234,6 @@ namespace ratgdo {
|
||||||
{
|
{
|
||||||
ESP_LOGD(TAG, "Set opening duration: %.1fs", duration);
|
ESP_LOGD(TAG, "Set opening duration: %.1fs", duration);
|
||||||
this->opening_duration = duration;
|
this->opening_duration = duration;
|
||||||
this->opening_duration_pref_.save(&this->opening_duration);
|
|
||||||
|
|
||||||
if (*this->closing_duration == 0 && duration != 0) {
|
if (*this->closing_duration == 0 && duration != 0) {
|
||||||
this->set_closing_duration(duration);
|
this->set_closing_duration(duration);
|
||||||
|
@ -258,7 +244,6 @@ namespace ratgdo {
|
||||||
{
|
{
|
||||||
ESP_LOGD(TAG, "Set closing duration: %.1fs", duration);
|
ESP_LOGD(TAG, "Set closing duration: %.1fs", duration);
|
||||||
this->closing_duration = duration;
|
this->closing_duration = duration;
|
||||||
this->closing_duration_pref_.save(&this->closing_duration);
|
|
||||||
|
|
||||||
if (*this->opening_duration == 0 && duration != 0) {
|
if (*this->opening_duration == 0 && duration != 0) {
|
||||||
this->set_opening_duration(duration);
|
this->set_opening_duration(duration);
|
||||||
|
@ -269,7 +254,6 @@ namespace ratgdo {
|
||||||
{
|
{
|
||||||
ESP_LOGV(TAG, "Set rolling code counter to %d", counter);
|
ESP_LOGV(TAG, "Set rolling code counter to %d", counter);
|
||||||
this->rolling_code_counter = counter;
|
this->rolling_code_counter = counter;
|
||||||
this->rolling_code_counter_pref_.save(&this->rolling_code_counter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RATGDOComponent::increment_rolling_code_counter(int delta)
|
void RATGDOComponent::increment_rolling_code_counter(int delta)
|
||||||
|
@ -280,7 +264,7 @@ namespace ratgdo {
|
||||||
void RATGDOComponent::print_packet(const WirePacket& packet) const
|
void RATGDOComponent::print_packet(const WirePacket& packet) const
|
||||||
{
|
{
|
||||||
ESP_LOGV(TAG, "Counter: %d Send code: [%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X]",
|
ESP_LOGV(TAG, "Counter: %d Send code: [%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X]",
|
||||||
*this->rollingCodeCounter,
|
*this->rolling_code_counter,
|
||||||
packet[0],
|
packet[0],
|
||||||
packet[1],
|
packet[1],
|
||||||
packet[2],
|
packet[2],
|
||||||
|
@ -413,8 +397,6 @@ namespace ratgdo {
|
||||||
|
|
||||||
delayMicroseconds(1260); // "LOW" pulse duration before the message start
|
delayMicroseconds(1260); // "LOW" pulse duration before the message start
|
||||||
this->sw_serial_.write(tx_packet, PACKET_LENGTH);
|
this->sw_serial_.write(tx_packet, PACKET_LENGTH);
|
||||||
|
|
||||||
this->save_rolling_code_counter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RATGDOComponent::sync()
|
void RATGDOComponent::sync()
|
||||||
|
@ -423,15 +405,23 @@ namespace ratgdo {
|
||||||
this->increment_rolling_code_counter(MAX_CODES_WITHOUT_FLASH_WRITE);
|
this->increment_rolling_code_counter(MAX_CODES_WITHOUT_FLASH_WRITE);
|
||||||
|
|
||||||
set_retry(
|
set_retry(
|
||||||
300, 10, [=](uint8_t r) {
|
500, 10, [=](uint8_t r) {
|
||||||
if (*this->door_state != DoorState::UNKNOWN) { // have status
|
if (*this->door_state != DoorState::UNKNOWN) { // have status
|
||||||
if (*this->openings != 0) { // have openings
|
if (*this->openings != 0) { // have openings
|
||||||
return RetryResult::DONE;
|
return RetryResult::DONE;
|
||||||
} else {
|
} else {
|
||||||
|
if (r == 0) { // failed to sync probably rolling counter is wrong, notify
|
||||||
|
ESP_LOGD(TAG, "Triggering sync failed actions.");
|
||||||
|
this->sync_failed = true;
|
||||||
|
};
|
||||||
this->transmit(Command::GET_OPENINGS);
|
this->transmit(Command::GET_OPENINGS);
|
||||||
return RetryResult::RETRY;
|
return RetryResult::RETRY;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (r == 0) { // failed to sync probably rolling counter is wrong, notify
|
||||||
|
ESP_LOGD(TAG, "Triggering sync failed actions.");
|
||||||
|
this->sync_failed = true;
|
||||||
|
};
|
||||||
this->transmit(Command::GET_STATUS);
|
this->transmit(Command::GET_STATUS);
|
||||||
return RetryResult::RETRY;
|
return RetryResult::RETRY;
|
||||||
}
|
}
|
||||||
|
@ -610,14 +600,6 @@ namespace ratgdo {
|
||||||
this->transmit(Command::LOCK, data::LOCK_TOGGLE);
|
this->transmit(Command::LOCK, data::LOCK_TOGGLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RATGDOComponent::save_rolling_code_counter()
|
|
||||||
{
|
|
||||||
this->rolling_code_counter_pref_.save(&this->rolling_code_counter);
|
|
||||||
// Forcing a sync results in a soft reset if there are too many
|
|
||||||
// writes to flash in a short period of time. To avoid this,
|
|
||||||
// we have configured preferences to write every 5s
|
|
||||||
}
|
|
||||||
|
|
||||||
LightState RATGDOComponent::get_light_state() const
|
LightState RATGDOComponent::get_light_state() const
|
||||||
{
|
{
|
||||||
return *this->light_state;
|
return *this->light_state;
|
||||||
|
@ -674,6 +656,10 @@ namespace ratgdo {
|
||||||
{
|
{
|
||||||
this->motion_state.subscribe([=](MotionState state) { defer("motion_state", [=] { f(state); }); });
|
this->motion_state.subscribe([=](MotionState state) { defer("motion_state", [=] { f(state); }); });
|
||||||
}
|
}
|
||||||
|
void RATGDOComponent::subscribe_sync_failed(std::function<void(bool)>&& f)
|
||||||
|
{
|
||||||
|
this->sync_failed.subscribe(std::move(f));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ratgdo
|
} // namespace ratgdo
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
|
@ -26,7 +26,6 @@ extern "C" {
|
||||||
|
|
||||||
#include "ratgdo_state.h"
|
#include "ratgdo_state.h"
|
||||||
|
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ratgdo {
|
namespace ratgdo {
|
||||||
|
|
||||||
|
@ -121,6 +120,8 @@ 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<bool> sync_failed { false };
|
||||||
|
|
||||||
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_input_obst_pin(InternalGPIOPin* pin) { this->input_obst_pin_ = pin; }
|
||||||
|
@ -136,7 +137,6 @@ namespace ratgdo {
|
||||||
|
|
||||||
void increment_rolling_code_counter(int delta = 1);
|
void increment_rolling_code_counter(int delta = 1);
|
||||||
void set_rolling_code_counter(uint32_t code);
|
void set_rolling_code_counter(uint32_t code);
|
||||||
void save_rolling_code_counter();
|
|
||||||
|
|
||||||
// door
|
// door
|
||||||
void door_command(uint32_t data);
|
void door_command(uint32_t data);
|
||||||
|
@ -148,6 +148,7 @@ namespace ratgdo {
|
||||||
void position_sync_while_opening(float delta, float update_period = 500);
|
void position_sync_while_opening(float delta, float update_period = 500);
|
||||||
void position_sync_while_closing(float delta, float update_period = 500);
|
void position_sync_while_closing(float delta, float update_period = 500);
|
||||||
void cancel_position_sync_callbacks();
|
void cancel_position_sync_callbacks();
|
||||||
|
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);
|
||||||
|
|
||||||
|
@ -179,11 +180,9 @@ namespace ratgdo {
|
||||||
void subscribe_motor_state(std::function<void(MotorState)>&& f);
|
void subscribe_motor_state(std::function<void(MotorState)>&& f);
|
||||||
void subscribe_button_state(std::function<void(ButtonState)>&& f);
|
void subscribe_button_state(std::function<void(ButtonState)>&& f);
|
||||||
void subscribe_motion_state(std::function<void(MotionState)>&& f);
|
void subscribe_motion_state(std::function<void(MotionState)>&& f);
|
||||||
|
void subscribe_sync_failed(std::function<void(bool)>&& f);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ESPPreferenceObject rolling_code_counter_pref_;
|
|
||||||
ESPPreferenceObject opening_duration_pref_;
|
|
||||||
ESPPreferenceObject closing_duration_pref_;
|
|
||||||
RATGDOStore isr_store_ {};
|
RATGDOStore isr_store_ {};
|
||||||
SoftwareSerial sw_serial_;
|
SoftwareSerial sw_serial_;
|
||||||
|
|
||||||
|
|
|
@ -190,6 +190,11 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h3>Updating from versions older than 2023.07.07</h3>
|
||||||
|
<p>
|
||||||
|
When updating from older versions, save the rolling counter value and restore it via the number entity after flashing the new firmware. If you forget to save the code, check the Home Assistant history.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3>Advanced Users</h3>
|
<h3>Advanced Users</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
|
|
Loading…
Reference in New Issue