2024-01-08 21:04:17 +00:00
|
|
|
#pragma once
|
|
|
|
|
2024-01-13 06:11:39 +00:00
|
|
|
#include <queue>
|
|
|
|
|
2024-01-08 21:04:17 +00:00
|
|
|
#include "SoftwareSerial.h" // Using espsoftwareserial https://github.com/plerup/espsoftwareserial
|
|
|
|
#include "esphome/core/optional.h"
|
|
|
|
|
|
|
|
#include "ratgdo_state.h"
|
|
|
|
#include "protocol.h"
|
|
|
|
#include "callbacks.h"
|
|
|
|
#include "observable.h"
|
|
|
|
|
|
|
|
namespace esphome {
|
|
|
|
|
|
|
|
class Scheduler;
|
|
|
|
class InternalGPIOPin;
|
|
|
|
|
|
|
|
namespace ratgdo {
|
|
|
|
namespace secplus1 {
|
|
|
|
|
2024-01-09 16:42:11 +00:00
|
|
|
using namespace esphome::ratgdo::protocol;
|
|
|
|
|
2024-01-08 21:04:17 +00:00
|
|
|
static const uint8_t RX_LENGTH = 2;
|
|
|
|
typedef uint8_t RxPacket[RX_LENGTH];
|
|
|
|
|
2024-01-11 04:09:36 +00:00
|
|
|
static const uint8_t TX_LENGTH = 2;
|
2024-01-08 21:04:17 +00:00
|
|
|
typedef uint8_t TxPacket[TX_LENGTH];
|
|
|
|
|
2024-01-11 04:09:36 +00:00
|
|
|
static const TxPacket toggle_door = {0x30, 0x31};
|
|
|
|
static const TxPacket toggle_light = {0x32, 0x33};
|
|
|
|
static const TxPacket toggle_lock = {0x34, 0x35};
|
2024-01-08 21:04:17 +00:00
|
|
|
|
|
|
|
static const uint8_t secplus1_states[] = {0x35,0x35,0x35,0x35,0x33,0x33,0x53,0x53,0x38,0x3A,0x3A,0x3A,0x39,0x38,0x3A, 0x38,0x3A,0x39,0x3A};
|
|
|
|
|
|
|
|
ENUM(CommandType, uint16_t,
|
2024-01-13 01:13:09 +00:00
|
|
|
(TOGGLE_DOOR_PRESS, 0x30),
|
|
|
|
(TOGGLE_DOOR_RELEASE, 0x31),
|
|
|
|
(TOGGLE_LIGHT_PRESS, 0x32),
|
|
|
|
(TOGGLE_LIGHT_RELEASE, 0x33),
|
|
|
|
(TOGGLE_LOCK_PRESS, 0x34),
|
|
|
|
(TOGGLE_LOCK_RELEASE, 0x35),
|
2024-01-14 08:00:21 +00:00
|
|
|
(QUERY_DOOR_STATUS_0x37, 0x37),
|
|
|
|
(QUERY_DOOR_STATUS, 0x38),
|
2024-01-12 16:51:56 +00:00
|
|
|
(OBSTRUCTION, 0x39),
|
2024-01-14 08:00:21 +00:00
|
|
|
(QUERY_OTHER_STATUS, 0x3A),
|
2024-01-08 21:04:17 +00:00
|
|
|
(UNKNOWN, 0xFF),
|
|
|
|
)
|
|
|
|
|
2024-01-13 06:11:39 +00:00
|
|
|
struct RxCommand {
|
|
|
|
CommandType req;
|
|
|
|
uint8_t resp;
|
|
|
|
|
|
|
|
RxCommand(): req(CommandType::UNKNOWN), resp(0) {}
|
|
|
|
RxCommand(CommandType req_): req(req_), resp(0) {}
|
|
|
|
RxCommand(CommandType req_, uint8_t resp_ = 0) : req(req_), resp(resp_) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct TxCommand {
|
|
|
|
CommandType request;
|
|
|
|
uint32_t time;
|
|
|
|
};
|
2024-01-08 21:04:17 +00:00
|
|
|
|
2024-01-13 06:11:39 +00:00
|
|
|
struct FirstToSend {
|
|
|
|
bool operator()(const TxCommand l, const TxCommand r) const { return l.time > r.time; }
|
2024-01-08 21:04:17 +00:00
|
|
|
};
|
|
|
|
|
2024-01-09 08:35:29 +00:00
|
|
|
enum class WallPanelEmulationState {
|
|
|
|
WAITING,
|
|
|
|
RUNNING,
|
|
|
|
};
|
2024-01-08 21:04:17 +00:00
|
|
|
|
|
|
|
class Secplus1 : public Protocol {
|
|
|
|
public:
|
|
|
|
void setup(RATGDOComponent* ratgdo, Scheduler* scheduler, InternalGPIOPin* rx_pin, InternalGPIOPin* tx_pin);
|
|
|
|
void loop();
|
|
|
|
void dump_config();
|
|
|
|
|
2024-01-09 08:35:29 +00:00
|
|
|
void sync();
|
|
|
|
|
2024-01-08 21:04:17 +00:00
|
|
|
void light_action(LightAction action);
|
|
|
|
void lock_action(LockAction action);
|
|
|
|
void door_action(DoorAction action);
|
|
|
|
|
2024-01-09 16:42:11 +00:00
|
|
|
Result call(Args args);
|
2024-01-08 21:04:17 +00:00
|
|
|
|
2024-01-19 03:08:40 +00:00
|
|
|
const Traits& traits() const { return this->traits_; }
|
2024-01-18 18:23:04 +00:00
|
|
|
|
2024-01-08 21:04:17 +00:00
|
|
|
protected:
|
2024-01-11 04:09:36 +00:00
|
|
|
void wall_panel_emulation(size_t index = 0);
|
2024-01-08 21:04:17 +00:00
|
|
|
|
2024-01-13 06:11:39 +00:00
|
|
|
optional<RxCommand> read_command();
|
|
|
|
void handle_command(const RxCommand& cmd);
|
2024-01-08 21:04:17 +00:00
|
|
|
|
|
|
|
void print_rx_packet(const RxPacket& packet) const;
|
|
|
|
void print_tx_packet(const TxPacket& packet) const;
|
2024-01-13 06:11:39 +00:00
|
|
|
optional<RxCommand> decode_packet(const RxPacket& packet) const;
|
|
|
|
|
|
|
|
void enqueue_transmit(CommandType cmd, uint32_t time = 0);
|
|
|
|
optional<CommandType> pending_tx();
|
2024-01-14 08:00:21 +00:00
|
|
|
optional<CommandType> pop_pending_tx();
|
2024-01-13 06:11:39 +00:00
|
|
|
bool do_transmit_if_pending();
|
|
|
|
void enqueue_command_pair(CommandType cmd);
|
2024-01-18 18:39:29 +00:00
|
|
|
void transmit_byte(uint32_t value);
|
2024-01-08 21:04:17 +00:00
|
|
|
|
2024-01-13 06:11:39 +00:00
|
|
|
void toggle_light();
|
|
|
|
void toggle_lock();
|
|
|
|
void toggle_door();
|
|
|
|
void query_status();
|
2024-01-08 21:04:17 +00:00
|
|
|
|
|
|
|
LightState light_state { LightState::UNKNOWN };
|
|
|
|
LockState lock_state { LockState::UNKNOWN };
|
|
|
|
DoorState door_state { DoorState::UNKNOWN };
|
|
|
|
|
2024-01-13 21:34:13 +00:00
|
|
|
LightState maybe_light_state { LightState::UNKNOWN };
|
|
|
|
LockState maybe_lock_state { LockState::UNKNOWN };
|
|
|
|
DoorState maybe_door_state { DoorState::UNKNOWN };
|
|
|
|
|
2024-01-18 18:23:45 +00:00
|
|
|
OnceCallbacks<void(DoorState)> on_door_state_;
|
|
|
|
|
2024-01-14 08:00:21 +00:00
|
|
|
bool door_moving_ { false };
|
|
|
|
|
2024-01-09 08:35:29 +00:00
|
|
|
bool wall_panel_starting_ { false };
|
|
|
|
uint32_t wall_panel_emulation_start_ { 0 };
|
|
|
|
WallPanelEmulationState wall_panel_emulation_state_ { WallPanelEmulationState::WAITING };
|
|
|
|
|
2024-01-12 22:10:35 +00:00
|
|
|
bool is_0x37_panel_ { false };
|
2024-01-13 06:11:39 +00:00
|
|
|
std::priority_queue<TxCommand, std::vector<TxCommand>, FirstToSend> pending_tx_;
|
2024-01-08 21:04:17 +00:00
|
|
|
uint32_t last_rx_ { 0 };
|
2024-01-14 08:00:21 +00:00
|
|
|
uint32_t last_tx_ { 0 };
|
2024-01-13 07:28:13 +00:00
|
|
|
uint32_t last_status_query_ { 0 };
|
2024-01-08 21:04:17 +00:00
|
|
|
|
2024-01-19 03:08:40 +00:00
|
|
|
Traits traits_;
|
2024-01-18 18:23:04 +00:00
|
|
|
|
2024-01-08 21:04:17 +00:00
|
|
|
SoftwareSerial sw_serial_;
|
|
|
|
|
|
|
|
InternalGPIOPin* tx_pin_;
|
|
|
|
InternalGPIOPin* rx_pin_;
|
|
|
|
|
|
|
|
RATGDOComponent* ratgdo_;
|
|
|
|
Scheduler* scheduler_;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace secplus1
|
|
|
|
} // namespace ratgdo
|
|
|
|
} // namespace esphome
|