feat: add learn and clear capability (#149)
Co-authored-by: Marius Muja <mariusmuja@gmail.com> Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
f0dda92908
commit
4c2ed4e7c0
32
base.yaml
32
base.yaml
|
@ -22,6 +22,24 @@ ratgdo:
|
||||||
title: "${friendly_name} sync failed"
|
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)"
|
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"
|
notification_id: "esphome_ratgdo_${id_prefix}_sync_failed"
|
||||||
|
api:
|
||||||
|
services:
|
||||||
|
- service: wipe_devices_from_gdo_memory
|
||||||
|
variables:
|
||||||
|
devices_to_wipe: string
|
||||||
|
then:
|
||||||
|
- lambda: !lambda |-
|
||||||
|
if(devices_to_wipe.compare("all") == 0) {
|
||||||
|
id($id_prefix).clear_paired_devices(ratgdo::PairedDevice::ALL);
|
||||||
|
} else if (devices_to_wipe.compare("remote") == 0) {
|
||||||
|
id($id_prefix).clear_paired_devices(ratgdo::PairedDevice::REMOTE);
|
||||||
|
} else if (devices_to_wipe.compare("keypad") == 0) {
|
||||||
|
id($id_prefix).clear_paired_devices(ratgdo::PairedDevice::KEYPAD);
|
||||||
|
} else if (devices_to_wipe.compare("wall") == 0) {
|
||||||
|
id($id_prefix).clear_paired_devices(ratgdo::PairedDevice::WALL_CONTROL);
|
||||||
|
} else if (devices_to_wipe.compare("accessory") == 0) {
|
||||||
|
id($id_prefix).clear_paired_devices(ratgdo::PairedDevice::ACCESSORY);
|
||||||
|
}
|
||||||
|
|
||||||
sensor:
|
sensor:
|
||||||
- platform: ratgdo
|
- platform: ratgdo
|
||||||
|
@ -32,6 +50,13 @@ sensor:
|
||||||
name: "Openings"
|
name: "Openings"
|
||||||
unit_of_measurement: "openings"
|
unit_of_measurement: "openings"
|
||||||
icon: mdi:open-in-app
|
icon: mdi:open-in-app
|
||||||
|
- platform: ratgdo
|
||||||
|
id: ${id_prefix}_paired_devices_total
|
||||||
|
type: paired_devices_total
|
||||||
|
entity_category: diagnostic
|
||||||
|
ratgdo_id: ${id_prefix}
|
||||||
|
name: "Paired Devices"
|
||||||
|
icon: mdi:remote
|
||||||
|
|
||||||
lock:
|
lock:
|
||||||
- platform: ratgdo
|
- platform: ratgdo
|
||||||
|
@ -58,6 +83,13 @@ switch:
|
||||||
output: true
|
output: true
|
||||||
name: "Status obstruction"
|
name: "Status obstruction"
|
||||||
entity_category: diagnostic
|
entity_category: diagnostic
|
||||||
|
- platform: ratgdo
|
||||||
|
id: "${id_prefix}_learn"
|
||||||
|
type: learn
|
||||||
|
ratgdo_id: ${id_prefix}
|
||||||
|
name: "Learn"
|
||||||
|
icon: mdi:plus-box
|
||||||
|
entity_category: config
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: ratgdo
|
- platform: ratgdo
|
||||||
|
|
|
@ -194,6 +194,14 @@ namespace ratgdo {
|
||||||
this->motion_state = MotionState::CLEAR; // when the status message is read, reset motion state to 0|clear
|
this->motion_state = MotionState::CLEAR; // when the status message is read, reset motion state to 0|clear
|
||||||
this->motor_state = MotorState::OFF; // when the status message is read, reset motor state to 0|off
|
this->motor_state = MotorState::OFF; // when the status message is read, reset motor state to 0|off
|
||||||
|
|
||||||
|
auto learn_state = static_cast<LearnState>((byte2 >> 5) & 1);
|
||||||
|
if (*this->learn_state != learn_state) {
|
||||||
|
if (learn_state == LearnState::INACTIVE) {
|
||||||
|
this->query_paired_devices();
|
||||||
|
}
|
||||||
|
this->learn_state = learn_state;
|
||||||
|
}
|
||||||
|
|
||||||
if (this->obstruction_from_status_) {
|
if (this->obstruction_from_status_) {
|
||||||
// ESP_LOGD(TAG, "Obstruction: reading from byte2, bit2, status=%d", ((byte2 >> 2) & 1) == 1);
|
// ESP_LOGD(TAG, "Obstruction: reading from byte2, bit2, status=%d", ((byte2 >> 2) & 1) == 1);
|
||||||
this->obstruction_state = static_cast<ObstructionState>((byte1 >> 6) & 1);
|
this->obstruction_state = static_cast<ObstructionState>((byte1 >> 6) & 1);
|
||||||
|
@ -207,10 +215,12 @@ namespace ratgdo {
|
||||||
this->send_command(Command::GET_OPENINGS);
|
this->send_command(Command::GET_OPENINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGD(TAG, "Status: door=%s light=%s lock=%s",
|
ESP_LOGD(TAG, "Status: door=%s light=%s lock=%s learn=%s",
|
||||||
DoorState_to_string(*this->door_state),
|
DoorState_to_string(*this->door_state),
|
||||||
LightState_to_string(*this->light_state),
|
LightState_to_string(*this->light_state),
|
||||||
LockState_to_string(*this->lock_state));
|
LockState_to_string(*this->lock_state),
|
||||||
|
LearnState_to_string(*this->learn_state));
|
||||||
|
|
||||||
} else if (cmd == Command::LIGHT) {
|
} else if (cmd == Command::LIGHT) {
|
||||||
if (nibble == 0) {
|
if (nibble == 0) {
|
||||||
this->light_state = LightState::OFF;
|
this->light_state = LightState::OFF;
|
||||||
|
@ -250,6 +260,18 @@ namespace ratgdo {
|
||||||
} else if (cmd == Command::SET_TTC) {
|
} else if (cmd == Command::SET_TTC) {
|
||||||
auto seconds = (byte1 << 8) | byte2;
|
auto seconds = (byte1 << 8) | byte2;
|
||||||
ESP_LOGD(TAG, "Time to close (TTC): %ds", seconds);
|
ESP_LOGD(TAG, "Time to close (TTC): %ds", seconds);
|
||||||
|
} else if (cmd == Command::PAIRED_DEVICES) {
|
||||||
|
if (nibble == static_cast<uint8_t>(PairedDevice::ALL)) {
|
||||||
|
this->paired_total = byte2;
|
||||||
|
} else if (nibble == static_cast<uint8_t>(PairedDevice::REMOTE)) {
|
||||||
|
this->paired_remotes = byte2;
|
||||||
|
} else if (nibble == static_cast<uint8_t>(PairedDevice::KEYPAD)) {
|
||||||
|
this->paired_keypads = byte2;
|
||||||
|
} else if (nibble == static_cast<uint8_t>(PairedDevice::WALL_CONTROL)) {
|
||||||
|
this->paired_wall_controls = byte2;
|
||||||
|
} else if (nibble == static_cast<uint8_t>(PairedDevice::ACCESSORY)) {
|
||||||
|
this->paired_accessories = byte2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmd;
|
return cmd;
|
||||||
|
@ -454,6 +476,49 @@ namespace ratgdo {
|
||||||
send_command(Command::GET_OPENINGS);
|
send_command(Command::GET_OPENINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RATGDOComponent::query_paired_devices()
|
||||||
|
{
|
||||||
|
const auto kinds = {
|
||||||
|
PairedDevice::ALL,
|
||||||
|
PairedDevice::REMOTE,
|
||||||
|
PairedDevice::KEYPAD,
|
||||||
|
PairedDevice::WALL_CONTROL,
|
||||||
|
PairedDevice::ACCESSORY
|
||||||
|
};
|
||||||
|
uint32_t timeout = 0;
|
||||||
|
for (auto kind : kinds) {
|
||||||
|
timeout += 200;
|
||||||
|
set_timeout(timeout, [=] { this->query_paired_devices(kind); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RATGDOComponent::query_paired_devices(PairedDevice kind)
|
||||||
|
{
|
||||||
|
ESP_LOGD(TAG, "Query paired devices of type: %s", PairedDevice_to_string(kind));
|
||||||
|
this->send_command(Command::GET_PAIRED_DEVICES, static_cast<uint8_t>(kind));
|
||||||
|
}
|
||||||
|
|
||||||
|
// wipe devices from memory based on get paired devices nibble values
|
||||||
|
void RATGDOComponent::clear_paired_devices(PairedDevice kind)
|
||||||
|
{
|
||||||
|
if (kind == PairedDevice::UNKNOWN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ESP_LOGW(TAG, "Clear paired devices of type: %s", PairedDevice_to_string(kind));
|
||||||
|
if (kind == PairedDevice::ALL) {
|
||||||
|
set_timeout(200, [=] { this->send_command(Command::CLEAR_PAIRED_DEVICES, static_cast<uint8_t>(PairedDevice::REMOTE)-1); }); // wireless
|
||||||
|
set_timeout(400, [=] { this->send_command(Command::CLEAR_PAIRED_DEVICES, static_cast<uint8_t>(PairedDevice::KEYPAD)-1); }); // keypads
|
||||||
|
set_timeout(600, [=] { this->send_command(Command::CLEAR_PAIRED_DEVICES, static_cast<uint8_t>(PairedDevice::WALL_CONTROL)-1); }); // wall controls
|
||||||
|
set_timeout(800, [=] { this->send_command(Command::CLEAR_PAIRED_DEVICES, static_cast<uint8_t>(PairedDevice::ACCESSORY)-1); }); // accessories
|
||||||
|
set_timeout(1000, [=] { this->query_status(); });
|
||||||
|
set_timeout(1200, [=] { this->query_paired_devices(); });
|
||||||
|
} else {
|
||||||
|
this->send_command(Command::CLEAR_PAIRED_DEVICES, static_cast<uint8_t>(kind) - 1); // just requested device
|
||||||
|
set_timeout(200, [=] { this->query_status(); });
|
||||||
|
set_timeout(400, [=] { this->query_paired_devices(kind); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RATGDOComponent::send_command(Command command, uint32_t data, bool increment)
|
void RATGDOComponent::send_command(Command command, uint32_t data, bool increment)
|
||||||
{
|
{
|
||||||
ESP_LOG1(TAG, "Send command: %s, data: %08" PRIx32, Command_to_string(command), data);
|
ESP_LOG1(TAG, "Send command: %s, data: %08" PRIx32, Command_to_string(command), data);
|
||||||
|
@ -528,6 +593,26 @@ namespace ratgdo {
|
||||||
this->send_command(Command::GET_OPENINGS);
|
this->send_command(Command::GET_OPENINGS);
|
||||||
return RetryResult::RETRY;
|
return RetryResult::RETRY;
|
||||||
}
|
}
|
||||||
|
if (*this->paired_total == PAIRED_DEVICES_UNKNOWN) {
|
||||||
|
this->query_paired_devices(PairedDevice::ALL);
|
||||||
|
return RetryResult::RETRY;
|
||||||
|
}
|
||||||
|
if (*this->paired_remotes == PAIRED_DEVICES_UNKNOWN) {
|
||||||
|
this->query_paired_devices(PairedDevice::REMOTE);
|
||||||
|
return RetryResult::RETRY;
|
||||||
|
}
|
||||||
|
if (*this->paired_keypads == PAIRED_DEVICES_UNKNOWN) {
|
||||||
|
this->query_paired_devices(PairedDevice::KEYPAD);
|
||||||
|
return RetryResult::RETRY;
|
||||||
|
}
|
||||||
|
if (*this->paired_wall_controls == PAIRED_DEVICES_UNKNOWN) {
|
||||||
|
this->query_paired_devices(PairedDevice::WALL_CONTROL);
|
||||||
|
return RetryResult::RETRY;
|
||||||
|
}
|
||||||
|
if (*this->paired_accessories == PAIRED_DEVICES_UNKNOWN) {
|
||||||
|
this->query_paired_devices(PairedDevice::ACCESSORY);
|
||||||
|
return RetryResult::RETRY;
|
||||||
|
}
|
||||||
return RetryResult::DONE;
|
return RetryResult::DONE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -724,6 +809,23 @@ namespace ratgdo {
|
||||||
return *this->light_state;
|
return *this->light_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Learn functions
|
||||||
|
void RATGDOComponent::activate_learn()
|
||||||
|
{
|
||||||
|
// Send LEARN with nibble = 0 then nibble = 1 to mimic wall control learn button
|
||||||
|
this->send_command(Command::LEARN, 0);
|
||||||
|
set_timeout(150, [=] { this->send_command(Command::LEARN, 1); });
|
||||||
|
set_timeout(500, [=] { this->send_command(Command::GET_STATUS); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void RATGDOComponent::inactivate_learn()
|
||||||
|
{
|
||||||
|
// Send LEARN twice with nibble = 0 to inactivate learn and get status to update switch state
|
||||||
|
this->send_command(Command::LEARN, 0);
|
||||||
|
set_timeout(150, [=] { this->send_command(Command::LEARN, 0); });
|
||||||
|
set_timeout(500, [=] { this->send_command(Command::GET_STATUS); });
|
||||||
|
}
|
||||||
|
|
||||||
void RATGDOComponent::subscribe_rolling_code_counter(std::function<void(uint32_t)>&& f)
|
void RATGDOComponent::subscribe_rolling_code_counter(std::function<void(uint32_t)>&& f)
|
||||||
{
|
{
|
||||||
// change update to children is defered until after component loop
|
// change update to children is defered until after component loop
|
||||||
|
@ -742,6 +844,26 @@ namespace ratgdo {
|
||||||
{
|
{
|
||||||
this->openings.subscribe([=](uint16_t state) { defer("openings", [=] { f(state); }); });
|
this->openings.subscribe([=](uint16_t state) { defer("openings", [=] { f(state); }); });
|
||||||
}
|
}
|
||||||
|
void RATGDOComponent::subscribe_paired_devices_total(std::function<void(uint16_t)>&& f)
|
||||||
|
{
|
||||||
|
this->paired_total.subscribe([=](uint16_t state) { defer("paired_total", [=] { f(state); }); });
|
||||||
|
}
|
||||||
|
void RATGDOComponent::subscribe_paired_remotes(std::function<void(uint16_t)>&& f)
|
||||||
|
{
|
||||||
|
this->paired_remotes.subscribe([=](uint16_t state) { defer("paired_remotes", [=] { f(state); }); });
|
||||||
|
}
|
||||||
|
void RATGDOComponent::subscribe_paired_keypads(std::function<void(uint16_t)>&& f)
|
||||||
|
{
|
||||||
|
this->paired_keypads.subscribe([=](uint16_t state) { defer("paired_keypads", [=] { f(state); }); });
|
||||||
|
}
|
||||||
|
void RATGDOComponent::subscribe_paired_wall_controls(std::function<void(uint16_t)>&& f)
|
||||||
|
{
|
||||||
|
this->paired_wall_controls.subscribe([=](uint16_t state) { defer("paired_wall_controls", [=] { f(state); }); });
|
||||||
|
}
|
||||||
|
void RATGDOComponent::subscribe_paired_accessories(std::function<void(uint16_t)>&& f)
|
||||||
|
{
|
||||||
|
this->paired_accessories.subscribe([=](uint16_t state) { defer("paired_accessories", [=] { f(state); }); });
|
||||||
|
}
|
||||||
void RATGDOComponent::subscribe_door_state(std::function<void(DoorState, float)>&& f)
|
void RATGDOComponent::subscribe_door_state(std::function<void(DoorState, float)>&& f)
|
||||||
{
|
{
|
||||||
this->door_state.subscribe([=](DoorState state) {
|
this->door_state.subscribe([=](DoorState state) {
|
||||||
|
@ -779,6 +901,10 @@ namespace ratgdo {
|
||||||
{
|
{
|
||||||
this->sync_failed.subscribe(std::move(f));
|
this->sync_failed.subscribe(std::move(f));
|
||||||
}
|
}
|
||||||
|
void RATGDOComponent::subscribe_learn_state(std::function<void(LearnState)>&& f)
|
||||||
|
{
|
||||||
|
this->learn_state.subscribe([=](LearnState state) { defer("learn_state", [=] { f(state); }); });
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ratgdo
|
} // namespace ratgdo
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
|
@ -38,6 +38,7 @@ namespace ratgdo {
|
||||||
|
|
||||||
const float DOOR_POSITION_UNKNOWN = -1.0;
|
const float DOOR_POSITION_UNKNOWN = -1.0;
|
||||||
const float DOOR_DELTA_UNKNOWN = -2.0;
|
const float DOOR_DELTA_UNKNOWN = -2.0;
|
||||||
|
const uint16_t PAIRED_DEVICES_UNKNOWN = 0xFF;
|
||||||
|
|
||||||
namespace data {
|
namespace data {
|
||||||
const uint32_t LIGHT_OFF = 0;
|
const uint32_t LIGHT_OFF = 0;
|
||||||
|
@ -64,13 +65,17 @@ namespace ratgdo {
|
||||||
(PAIR_3, 0x0a0),
|
(PAIR_3, 0x0a0),
|
||||||
(PAIR_3_RESP, 0x0a1),
|
(PAIR_3_RESP, 0x0a1),
|
||||||
|
|
||||||
(LEARN_2, 0x181),
|
(LEARN, 0x181),
|
||||||
(LOCK, 0x18c),
|
(LOCK, 0x18c),
|
||||||
(DOOR_ACTION, 0x280),
|
(DOOR_ACTION, 0x280),
|
||||||
(LIGHT, 0x281),
|
(LIGHT, 0x281),
|
||||||
(MOTOR_ON, 0x284),
|
(MOTOR_ON, 0x284),
|
||||||
(MOTION, 0x285),
|
(MOTION, 0x285),
|
||||||
|
|
||||||
|
(GET_PAIRED_DEVICES, 0x307), // nibble 0 for total, 1 wireless, 2 keypads, 3 wall, 4 accessories.
|
||||||
|
(PAIRED_DEVICES, 0x308), // byte2 holds number of paired devices
|
||||||
|
(CLEAR_PAIRED_DEVICES, 0x30D), // nibble 0 to clear remotes, 1 keypads, 2 wall, 3 accessories (offset from above)
|
||||||
|
|
||||||
(LEARN_1, 0x391),
|
(LEARN_1, 0x391),
|
||||||
(PING, 0x392),
|
(PING, 0x392),
|
||||||
(PING_RESP, 0x393),
|
(PING_RESP, 0x393),
|
||||||
|
@ -110,6 +115,11 @@ namespace ratgdo {
|
||||||
observable<float> closing_duration { 0 };
|
observable<float> closing_duration { 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_remotes { PAIRED_DEVICES_UNKNOWN };
|
||||||
|
observable<uint16_t> paired_keypads { PAIRED_DEVICES_UNKNOWN };
|
||||||
|
observable<uint16_t> paired_wall_controls { PAIRED_DEVICES_UNKNOWN };
|
||||||
|
observable<uint16_t> paired_accessories { PAIRED_DEVICES_UNKNOWN };
|
||||||
|
|
||||||
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 };
|
||||||
|
@ -124,6 +134,7 @@ namespace ratgdo {
|
||||||
observable<MotorState> motor_state { MotorState::UNKNOWN };
|
observable<MotorState> motor_state { MotorState::UNKNOWN };
|
||||||
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 };
|
||||||
|
|
||||||
OnceCallbacks<void(DoorState)> door_state_received;
|
OnceCallbacks<void(DoorState)> door_state_received;
|
||||||
OnceCallbacks<void()> command_sent;
|
OnceCallbacks<void()> command_sent;
|
||||||
|
@ -173,6 +184,13 @@ namespace ratgdo {
|
||||||
void lock();
|
void lock();
|
||||||
void unlock();
|
void unlock();
|
||||||
|
|
||||||
|
// Learn & Paired
|
||||||
|
void activate_learn();
|
||||||
|
void inactivate_learn();
|
||||||
|
void query_paired_devices();
|
||||||
|
void query_paired_devices(PairedDevice kind);
|
||||||
|
void clear_paired_devices(PairedDevice kind);
|
||||||
|
|
||||||
// button functionality
|
// button functionality
|
||||||
void query_status();
|
void query_status();
|
||||||
void query_openings();
|
void query_openings();
|
||||||
|
@ -183,6 +201,11 @@ namespace ratgdo {
|
||||||
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_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_remotes(std::function<void(uint16_t)>&& f);
|
||||||
|
void subscribe_paired_keypads(std::function<void(uint16_t)>&& f);
|
||||||
|
void subscribe_paired_wall_controls(std::function<void(uint16_t)>&& f);
|
||||||
|
void subscribe_paired_accessories(std::function<void(uint16_t)>&& f);
|
||||||
void subscribe_door_state(std::function<void(DoorState, float)>&& f);
|
void subscribe_door_state(std::function<void(DoorState, float)>&& f);
|
||||||
void subscribe_light_state(std::function<void(LightState)>&& f);
|
void subscribe_light_state(std::function<void(LightState)>&& f);
|
||||||
void subscribe_lock_state(std::function<void(LockState)>&& f);
|
void subscribe_lock_state(std::function<void(LockState)>&& f);
|
||||||
|
@ -191,6 +214,7 @@ namespace ratgdo {
|
||||||
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);
|
void subscribe_sync_failed(std::function<void(bool)>&& f);
|
||||||
|
void subscribe_learn_state(std::function<void(LearnState)>&& f);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// tx data
|
// tx data
|
||||||
|
|
|
@ -31,5 +31,19 @@ namespace ratgdo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LearnState learn_state_toggle(LearnState state)
|
||||||
|
{
|
||||||
|
switch (state) {
|
||||||
|
case LearnState::ACTIVE:
|
||||||
|
return LearnState::INACTIVE;
|
||||||
|
case LearnState::INACTIVE:
|
||||||
|
return LearnState::ACTIVE;
|
||||||
|
// 2 and 3 appears sometimes
|
||||||
|
case LearnState::UNKNOWN:
|
||||||
|
default:
|
||||||
|
return LearnState::UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ratgdo
|
} // namespace ratgdo
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
|
@ -64,5 +64,20 @@ namespace ratgdo {
|
||||||
(RELEASED, 1),
|
(RELEASED, 1),
|
||||||
(UNKNOWN, 2))
|
(UNKNOWN, 2))
|
||||||
|
|
||||||
|
/// Enum for learn states.
|
||||||
|
ENUM(LearnState, uint8_t,
|
||||||
|
(INACTIVE, 0),
|
||||||
|
(ACTIVE, 1),
|
||||||
|
(UNKNOWN, 2))
|
||||||
|
LearnState learn_state_toggle(LearnState state);
|
||||||
|
|
||||||
|
ENUM(PairedDevice, uint8_t,
|
||||||
|
(ALL, 0),
|
||||||
|
(REMOTE, 1),
|
||||||
|
(KEYPAD, 2),
|
||||||
|
(WALL_CONTROL, 3),
|
||||||
|
(ACCESSORY, 4),
|
||||||
|
(UNKNOWN, 0xff))
|
||||||
|
|
||||||
} // namespace ratgdo
|
} // namespace ratgdo
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
|
@ -13,6 +13,11 @@ RATGDOSensorType = ratgdo_ns.enum("RATGDOSensorType")
|
||||||
CONF_TYPE = "type"
|
CONF_TYPE = "type"
|
||||||
TYPES = {
|
TYPES = {
|
||||||
"openings": RATGDOSensorType.RATGDO_OPENINGS,
|
"openings": RATGDOSensorType.RATGDO_OPENINGS,
|
||||||
|
"paired_devices_total": RATGDOSensorType.RATGDO_PAIRED_DEVICES_TOTAL,
|
||||||
|
"paired_devices_remotes": RATGDOSensorType.RATGDO_PAIRED_REMOTES,
|
||||||
|
"paired_devices_keypads": RATGDOSensorType.RATGDO_PAIRED_KEYPADS,
|
||||||
|
"paired_devices_wall_controls": RATGDOSensorType.RATGDO_PAIRED_WALL_CONTROLS,
|
||||||
|
"paired_devices_accessories": RATGDOSensorType.RATGDO_PAIRED_ACCESSORIES,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,3 +38,4 @@ 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)
|
||||||
|
|
||||||
|
|
|
@ -7,17 +7,51 @@ namespace ratgdo {
|
||||||
|
|
||||||
static const char* const TAG = "ratgdo.sensor";
|
static const char* const TAG = "ratgdo.sensor";
|
||||||
|
|
||||||
void RATGDOSensor::dump_config()
|
|
||||||
{
|
|
||||||
LOG_SENSOR("", "RATGDO Sensor", this);
|
|
||||||
ESP_LOGCONFIG(TAG, " Type: Openings");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RATGDOSensor::setup()
|
void RATGDOSensor::setup()
|
||||||
{
|
{
|
||||||
|
if (this->ratgdo_sensor_type_ == RATGDOSensorType::RATGDO_OPENINGS) {
|
||||||
this->parent_->subscribe_openings([=](uint16_t value) {
|
this->parent_->subscribe_openings([=](uint16_t value) {
|
||||||
this->publish_state(value);
|
this->publish_state(value);
|
||||||
});
|
});
|
||||||
|
} else if (this->ratgdo_sensor_type_ == RATGDOSensorType::RATGDO_PAIRED_DEVICES_TOTAL) {
|
||||||
|
this->parent_->subscribe_paired_devices_total([=](uint16_t value) {
|
||||||
|
this->publish_state(value);
|
||||||
|
});
|
||||||
|
} else if (this->ratgdo_sensor_type_ == RATGDOSensorType::RATGDO_PAIRED_REMOTES) {
|
||||||
|
this->parent_->subscribe_paired_remotes([=](uint16_t value) {
|
||||||
|
this->publish_state(value);
|
||||||
|
});
|
||||||
|
} else if (this->ratgdo_sensor_type_ == RATGDOSensorType::RATGDO_PAIRED_KEYPADS) {
|
||||||
|
this->parent_->subscribe_paired_keypads([=](uint16_t value) {
|
||||||
|
this->publish_state(value);
|
||||||
|
});
|
||||||
|
} else if (this->ratgdo_sensor_type_ == RATGDOSensorType::RATGDO_PAIRED_WALL_CONTROLS) {
|
||||||
|
this->parent_->subscribe_paired_wall_controls([=](uint16_t value) {
|
||||||
|
this->publish_state(value);
|
||||||
|
});
|
||||||
|
} else if (this->ratgdo_sensor_type_ == RATGDOSensorType::RATGDO_PAIRED_ACCESSORIES) {
|
||||||
|
this->parent_->subscribe_paired_accessories([=](uint16_t value) {
|
||||||
|
this->publish_state(value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RATGDOSensor::dump_config()
|
||||||
|
{
|
||||||
|
LOG_SENSOR("", "RATGDO Sensor", this);
|
||||||
|
if (this->ratgdo_sensor_type_ == RATGDOSensorType::RATGDO_OPENINGS) {
|
||||||
|
ESP_LOGCONFIG(TAG, " Type: Openings");
|
||||||
|
} else if (this->ratgdo_sensor_type_ == RATGDOSensorType::RATGDO_PAIRED_DEVICES_TOTAL) {
|
||||||
|
ESP_LOGCONFIG(TAG, " Type: Paired Devices");
|
||||||
|
} else if (this->ratgdo_sensor_type_ == RATGDOSensorType::RATGDO_PAIRED_REMOTES) {
|
||||||
|
ESP_LOGCONFIG(TAG, " Type: Paired Remotes");
|
||||||
|
} else if (this->ratgdo_sensor_type_ == RATGDOSensorType::RATGDO_PAIRED_KEYPADS) {
|
||||||
|
ESP_LOGCONFIG(TAG, " Type: Paired Keypads");
|
||||||
|
} else if (this->ratgdo_sensor_type_ == RATGDOSensorType::RATGDO_PAIRED_WALL_CONTROLS) {
|
||||||
|
ESP_LOGCONFIG(TAG, " Type: Paired Wall Controls");
|
||||||
|
} else if (this->ratgdo_sensor_type_ == RATGDOSensorType::RATGDO_PAIRED_ACCESSORIES) {
|
||||||
|
ESP_LOGCONFIG(TAG, " Type: Paired Accessories");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ratgdo
|
} // namespace ratgdo
|
||||||
|
|
|
@ -9,7 +9,12 @@ namespace esphome {
|
||||||
namespace ratgdo {
|
namespace ratgdo {
|
||||||
|
|
||||||
enum RATGDOSensorType {
|
enum RATGDOSensorType {
|
||||||
RATGDO_OPENINGS
|
RATGDO_OPENINGS,
|
||||||
|
RATGDO_PAIRED_DEVICES_TOTAL,
|
||||||
|
RATGDO_PAIRED_REMOTES,
|
||||||
|
RATGDO_PAIRED_KEYPADS,
|
||||||
|
RATGDO_PAIRED_WALL_CONTROLS,
|
||||||
|
RATGDO_PAIRED_ACCESSORIES
|
||||||
};
|
};
|
||||||
|
|
||||||
class RATGDOSensor : public sensor::Sensor, public RATGDOClient, public Component {
|
class RATGDOSensor : public sensor::Sensor, public RATGDOClient, public Component {
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import switch
|
||||||
|
from esphome.const import CONF_ID
|
||||||
|
|
||||||
|
from .. import RATGDO_CLIENT_SCHMEA, ratgdo_ns, register_ratgdo_child
|
||||||
|
|
||||||
|
DEPENDENCIES = ["ratgdo"]
|
||||||
|
|
||||||
|
RATGDOSwitch = ratgdo_ns.class_("RATGDOSwitch", switch.Switch, cg.Component)
|
||||||
|
SwitchType = ratgdo_ns.enum("SwitchType")
|
||||||
|
|
||||||
|
CONF_TYPE = "type"
|
||||||
|
TYPES = {
|
||||||
|
"learn": SwitchType.RATGDO_LEARN,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = (
|
||||||
|
switch.switch_schema(RATGDOSwitch)
|
||||||
|
.extend(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_TYPE): cv.enum(TYPES, lower=True),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(RATGDO_CLIENT_SCHMEA)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
await switch.register_switch(var, config)
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
cg.add(var.set_switch_type(config[CONF_TYPE]))
|
||||||
|
await register_ratgdo_child(var, config)
|
|
@ -0,0 +1,39 @@
|
||||||
|
#include "ratgdo_switch.h"
|
||||||
|
#include "../ratgdo_state.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ratgdo {
|
||||||
|
|
||||||
|
static const char* const TAG = "ratgdo.switch";
|
||||||
|
|
||||||
|
void RATGDOSwitch::dump_config()
|
||||||
|
{
|
||||||
|
LOG_SWITCH("", "RATGDO Switch", this);
|
||||||
|
if (this->switch_type_ == SwitchType::RATGDO_LEARN) {
|
||||||
|
ESP_LOGCONFIG(TAG, " Type: Learn");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RATGDOSwitch::setup()
|
||||||
|
{
|
||||||
|
if (this->switch_type_ == SwitchType::RATGDO_LEARN) {
|
||||||
|
this->parent_->subscribe_learn_state([=](LearnState state) {
|
||||||
|
this->publish_state(state==LearnState::ACTIVE);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RATGDOSwitch::write_state(bool state)
|
||||||
|
{
|
||||||
|
if (this->switch_type_ == SwitchType::RATGDO_LEARN) {
|
||||||
|
if (state) {
|
||||||
|
this->parent_->activate_learn();
|
||||||
|
} else {
|
||||||
|
this->parent_->inactivate_learn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ratgdo
|
||||||
|
} // namespace esphome
|
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../ratgdo.h"
|
||||||
|
#include "../ratgdo_state.h"
|
||||||
|
#include "esphome/components/switch/switch.h"
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ratgdo {
|
||||||
|
|
||||||
|
enum SwitchType {
|
||||||
|
RATGDO_LEARN
|
||||||
|
};
|
||||||
|
|
||||||
|
class RATGDOSwitch : public switch_::Switch, public RATGDOClient, public Component {
|
||||||
|
public:
|
||||||
|
void dump_config() override;
|
||||||
|
void setup() override;
|
||||||
|
void set_switch_type(SwitchType switch_type_) { this->switch_type_ = switch_type_; }
|
||||||
|
|
||||||
|
void write_state(bool state) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SwitchType switch_type_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ratgdo
|
||||||
|
} // namespace esphome
|
Loading…
Reference in New Issue