From b15063763a26dced8746172abc1a15b44e8f05a6 Mon Sep 17 00:00:00 2001
From: "J. Nick Koston" <nick@koston.org>
Date: Mon, 5 Jun 2023 19:57:06 -0500
Subject: [PATCH] fix

---
 components/ratgdo/__init__.py |   7 +-
 components/ratgdo/ratgdo.cpp  | 784 +++++++++++++++++-----------------
 2 files changed, 397 insertions(+), 394 deletions(-)

diff --git a/components/ratgdo/__init__.py b/components/ratgdo/__init__.py
index efeebcc..56c0303 100644
--- a/components/ratgdo/__init__.py
+++ b/components/ratgdo/__init__.py
@@ -2,12 +2,13 @@ import esphome.codegen as cg
 import esphome.config_validation as cv
 from esphome.const import CONF_ID
 from esphome import pins, automation
+from esphome.components import uart
 
-DEPENDENCIES = ["preferences"]
+DEPENDENCIES = ["preferences", "uart"]
 
 
 ratgdo_ns = cg.esphome_ns.namespace("ratgdo")
-RATGDO = ratgdo_ns.class_("RATGDOComponent", cg.Component)
+RATGDO = ratgdo_ns.class_("RATGDOComponent", cg.Component, uart.UARTDevice)
 
 
 CONF_OUTPUT_GDO = "output_gdo_pin"
@@ -46,7 +47,7 @@ CONFIG_SCHEMA = cv.Schema(
         cv.Optional(CONF_STATUS_DOOR, default=DEFAULT_STATUS_DOOR): pins.internal_gpio_input_pin_schema,
         cv.Optional(CONF_STATUS_OBST, default=DEFAULT_STATUS_OBST): pins.internal_gpio_input_pin_schema,
     }
-).extend(cv.COMPONENT_SCHEMA)
+).extend(cv.COMPONENT_SCHEMA).extend(uart.UART_DEVICE_SCHEMA)
 
 
 async def to_code(config):
diff --git a/components/ratgdo/ratgdo.cpp b/components/ratgdo/ratgdo.cpp
index 5e5be27..8a49a3d 100644
--- a/components/ratgdo/ratgdo.cpp
+++ b/components/ratgdo/ratgdo.cpp
@@ -88,443 +88,445 @@ namespace ratgdo {
         }
     }
 
-    void RATGDOComponent::setup()
-    {
-        this->pref_ = global_preferences->make_preference<int>(734874333U);
-        if (!this->pref_.load(&this->rollingCodeCounter)) {
-            this->rollingCodeCounter = 0;
+    class RATGDOComponent : public Component, public UARTDevice {
+         public:
+          RATGDOComponent(UARTComponent *parent) : UARTDevice(parent) {}
+
+        void setup()
+        {
+            this->pref_ = global_preferences->make_preference<int>(734874333U);
+            if (!this->pref_.load(&this->rollingCodeCounter)) {
+                this->rollingCodeCounter = 0;
+            }
+
+            this->output_gdo_pin_->setup();
+            this->input_gdo_pin_->setup();
+            this->input_obst_pin_->setup();
+
+            this->trigger_open_pin_->setup();
+            this->trigger_close_pin_->setup();
+            this->trigger_light_pin_->setup();
+
+            this->status_door_pin_->setup();
+            this->status_obst_pin_->setup();
+
+            this->store_.input_obst = this->input_obst_pin_->to_isr();
+
+            this->store_.trigger_open = this->trigger_open_pin_->to_isr();
+            this->store_.trigger_close = this->trigger_close_pin_->to_isr();
+            this->store_.trigger_light = this->trigger_light_pin_->to_isr();
+
+            this->trigger_open_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
+            this->trigger_close_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
+            this->trigger_light_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
+
+            this->status_door_pin_->pin_mode(gpio::FLAG_OUTPUT);
+            this->status_obst_pin_->pin_mode(gpio::FLAG_OUTPUT);
+
+            //this->output_gdo_pin_->pin_mode(gpio::FLAG_OUTPUT);
+            //this->input_gdo_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);        
+            this->input_obst_pin_->pin_mode(gpio::FLAG_INPUT);
+
+            this->swSerial.begin(9600, SWSERIAL_8N1, this->input_gdo_pin_->get_pin(), this->output_gdo_pin_->get_pin(), true);
+
+            this->trigger_open_pin_->attach_interrupt(RATGDOStore::isrDoorOpen, &this->store_, gpio::INTERRUPT_ANY_EDGE);
+            this->trigger_close_pin_->attach_interrupt(RATGDOStore::isrDoorClose, &this->store_, gpio::INTERRUPT_ANY_EDGE);
+            this->trigger_light_pin_->attach_interrupt(RATGDOStore::isrLight, &this->store_, gpio::INTERRUPT_ANY_EDGE);
+            this->input_obst_pin_->attach_interrupt(RATGDOStore::isrObstruction, &this->store_, gpio::INTERRUPT_ANY_EDGE);
+
+            ESP_LOGD(TAG, "Syncing rolling code counter after reboot...");
+            sync(); // if rolling codes are being used (rolling code counter > 0), send
+                    // reboot/sync to the opener on startup
+
         }
 
-		this->output_gdo_pin_->setup();
-		this->input_gdo_pin_->setup();
-		this->input_obst_pin_->setup();
-
-		this->trigger_open_pin_->setup();
-		this->trigger_close_pin_->setup();
-		this->trigger_light_pin_->setup();
-
-		this->status_door_pin_->setup();
-		this->status_obst_pin_->setup();
-
-		this->store_.input_obst = this->input_obst_pin_->to_isr();
-
-		this->store_.trigger_open = this->trigger_open_pin_->to_isr();
-		this->store_.trigger_close = this->trigger_close_pin_->to_isr();
-		this->store_.trigger_light = this->trigger_light_pin_->to_isr();
-
-		this->trigger_open_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
-		this->trigger_close_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
-		this->trigger_light_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
-
-		this->status_door_pin_->pin_mode(gpio::FLAG_OUTPUT);
-		this->status_obst_pin_->pin_mode(gpio::FLAG_OUTPUT);
-
-        //this->output_gdo_pin_->pin_mode(gpio::FLAG_OUTPUT);
-        //this->input_gdo_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);        
-		this->input_obst_pin_->pin_mode(gpio::FLAG_INPUT);
-
-        this->swSerial.begin(9600, SWSERIAL_8N1, this->input_gdo_pin_->get_pin(), this->output_gdo_pin_->get_pin(), true);
-
-		this->trigger_open_pin_->attach_interrupt(RATGDOStore::isrDoorOpen, &this->store_, gpio::INTERRUPT_ANY_EDGE);
-		this->trigger_close_pin_->attach_interrupt(RATGDOStore::isrDoorClose, &this->store_, gpio::INTERRUPT_ANY_EDGE);
-		this->trigger_light_pin_->attach_interrupt(RATGDOStore::isrLight, &this->store_, gpio::INTERRUPT_ANY_EDGE);
-		this->input_obst_pin_->attach_interrupt(RATGDOStore::isrObstruction, &this->store_, gpio::INTERRUPT_ANY_EDGE);
-
-        ESP_LOGD(TAG, "Syncing rolling code counter after reboot...");
-        sync(); // if rolling codes are being used (rolling code counter > 0), send
-                // reboot/sync to the opener on startup
-
-    }
-
-    void RATGDOComponent::loop()
-    {
-        ESP_LOGD(TAG, "loop rollingCodeCounter: %d", this->rollingCodeCounter);
-        obstructionLoop();
-        gdoStateLoop();
-        dryContactLoop();
-        statusUpdateLoop();
-		//ESP_LOGD(TAG, "Door State: %s", this->doorState.c_str());
-    }
-
-    void RATGDOComponent::readRollingCode(uint8_t &door, uint8_t &light, uint8_t &lock, uint8_t &motion, uint8_t &obstruction){
-        uint32_t rolling = 0;
-        uint64_t fixed = 0;
-        uint32_t data = 0;
-
-        uint16_t cmd = 0;
-        uint8_t nibble = 0;
-        uint8_t byte1 = 0;
-        uint8_t byte2 = 0;
-
-        decode_wireline(this->rxRollingCode, &rolling, &fixed, &data);
-
-        cmd = ((fixed >> 24) & 0xf00) | (data & 0xff);
-
-        nibble = (data >> 8) & 0xf;
-        byte1 = (data >> 16) & 0xff;
-        byte2 = (data >> 24) & 0xff;
-
-        if(cmd == 0x81){
-            door = nibble;
-            light = (byte2 >> 1) & 1;
-            lock = byte2 & 1;
-            motion = 0; // when the status message is read, reset motion state to 0|clear
-            // obstruction = (byte1 >> 6) & 1; // unreliable due to the time it takes to register an obstruction
-
-        }else if(cmd == 0x281){
-            light ^= 1; // toggle bit
-        }else if(cmd == 0x84){
-        }else if(cmd == 0x285){
-            motion = 1; // toggle bit
+        void loop()
+        {
+            ESP_LOGD(TAG, "loop rollingCodeCounter: %d", this->rollingCodeCounter);
+            obstructionLoop();
+            gdoStateLoop();
+            dryContactLoop();
+            statusUpdateLoop();
+            //ESP_LOGD(TAG, "Door State: %s", this->doorState.c_str());
         }
-    }
 
-    void RATGDOComponent::getRollingCode(const char* command)
-    {
+        void readRollingCode(uint8_t &door, uint8_t &light, uint8_t &lock, uint8_t &motion, uint8_t &obstruction){
+            uint32_t rolling = 0;
+            uint64_t fixed = 0;
+            uint32_t data = 0;
 
-        uint64_t id = 0x539;
-        uint64_t fixed = 0;
-        uint32_t data = 0;
+            uint16_t cmd = 0;
+            uint8_t nibble = 0;
+            uint8_t byte1 = 0;
+            uint8_t byte2 = 0;
 
-        if(strcmp(command,"reboot1") == 0){
-            fixed = 0x400000000;
-            data = 0x0000618b;
-        }else if(strcmp(command,"reboot2") == 0){
-            fixed = 0;
-            data = 0x01009080;
-        }else if(strcmp(command,"reboot3") == 0){
-            fixed = 0;
-            data = 0x0000b1a0;
-        }else if(strcmp(command,"reboot4") == 0){
-            fixed = 0;
-            data = 0x01009080;
-        }else if(strcmp(command,"reboot5") == 0){
-            fixed = 0x300000000;
-            data = 0x00008092;
-        }else if(strcmp(command,"reboot6") == 0){
-            fixed = 0x300000000;
-            data = 0x00008092;
-        }else if(strcmp(command,"door1") == 0){
-            fixed = 0x200000000;
-            data = 0x01018280;
-        }else if(strcmp(command,"door2") == 0){
-            fixed = 0x200000000;
-            data = 0x01009280;
-        }else if(strcmp(command,"light") == 0){
-            fixed = 0x200000000;
-            data = 0x00009281;
-        }else if(strcmp(command,"lock") == 0){
-            fixed = 0x0100000000;
-            data = 0x0000728c;
-        } else {
-            ESP_LOGD(TAG, "ERROR: Invalid command");
+            decode_wireline(this->rxRollingCode, &rolling, &fixed, &data);
+
+            cmd = ((fixed >> 24) & 0xf00) | (data & 0xff);
+
+            nibble = (data >> 8) & 0xf;
+            byte1 = (data >> 16) & 0xff;
+            byte2 = (data >> 24) & 0xff;
+
+            if(cmd == 0x81){
+                door = nibble;
+                light = (byte2 >> 1) & 1;
+                lock = byte2 & 1;
+                motion = 0; // when the status message is read, reset motion state to 0|clear
+                // obstruction = (byte1 >> 6) & 1; // unreliable due to the time it takes to register an obstruction
+
+            }else if(cmd == 0x281){
+                light ^= 1; // toggle bit
+            }else if(cmd == 0x84){
+            }else if(cmd == 0x285){
+                motion = 1; // toggle bit
+            }
+        }
+
+        void getRollingCode(const char* command)
+        {
+
+            uint64_t id = 0x539;
+            uint64_t fixed = 0;
+            uint32_t data = 0;
+
+            if(strcmp(command,"reboot1") == 0){
+                fixed = 0x400000000;
+                data = 0x0000618b;
+            }else if(strcmp(command,"reboot2") == 0){
+                fixed = 0;
+                data = 0x01009080;
+            }else if(strcmp(command,"reboot3") == 0){
+                fixed = 0;
+                data = 0x0000b1a0;
+            }else if(strcmp(command,"reboot4") == 0){
+                fixed = 0;
+                data = 0x01009080;
+            }else if(strcmp(command,"reboot5") == 0){
+                fixed = 0x300000000;
+                data = 0x00008092;
+            }else if(strcmp(command,"reboot6") == 0){
+                fixed = 0x300000000;
+                data = 0x00008092;
+            }else if(strcmp(command,"door1") == 0){
+                fixed = 0x200000000;
+                data = 0x01018280;
+            }else if(strcmp(command,"door2") == 0){
+                fixed = 0x200000000;
+                data = 0x01009280;
+            }else if(strcmp(command,"light") == 0){
+                fixed = 0x200000000;
+                data = 0x00009281;
+            }else if(strcmp(command,"lock") == 0){
+                fixed = 0x0100000000;
+                data = 0x0000728c;
+            } else {
+                ESP_LOGD(TAG, "ERROR: Invalid command");
+                return;
+            }
+
+            fixed = fixed | id;
+
+            encode_wireline(this->rollingCodeCounter, fixed, data, this->txRollingCode);
+
+            printRollingCode();
+
+            if (strcmp(command, "door1") != 0) { // door2 is created with same counter and should always be called after door1
+                this->rollingCodeCounter = (this->rollingCodeCounter + 1) & 0xfffffff;
+            }
             return;
         }
 
-        fixed = fixed | id;
-
-        encode_wireline(this->rollingCodeCounter, fixed, data, this->txRollingCode);
-
-        printRollingCode();
-
-        if (strcmp(command, "door1") != 0) { // door2 is created with same counter and should always be called after door1
-            this->rollingCodeCounter = (this->rollingCodeCounter + 1) & 0xfffffff;
-        }
-        return;
-    }
-
-    void RATGDOComponent::printRollingCode()
-    {
-        for (int i = 0; i < CODE_LENGTH; i++) {
-            if (this->txRollingCode[i] <= 0x0f)
-                ESP_LOGD(TAG, "0");
-            ESP_LOGD(TAG, "%x", this->txRollingCode[i]);
-        }
-    }
-
-    // handle changes to the dry contact state
-    void RATGDOComponent::dryContactLoop()
-    {
-        if (this->store_.dryContactDoorOpen) {
-            ESP_LOGD(TAG, "Dry Contact: open the door");
-            this->store_.dryContactDoorOpen = false;
-            openDoor();
+        void printRollingCode()
+        {
+            for (int i = 0; i < CODE_LENGTH; i++) {
+                if (this->txRollingCode[i] <= 0x0f)
+                    ESP_LOGD(TAG, "0");
+                ESP_LOGD(TAG, "%x", this->txRollingCode[i]);
+            }
         }
 
-        if (this->store_.dryContactDoorClose) {
-            ESP_LOGD(TAG, "Dry Contact: close the door");
-            this->store_.dryContactDoorClose = false;
-            closeDoor();
+        // handle changes to the dry contact state
+        void dryContactLoop()
+        {
+            if (this->store_.dryContactDoorOpen) {
+                ESP_LOGD(TAG, "Dry Contact: open the door");
+                this->store_.dryContactDoorOpen = false;
+                openDoor();
+            }
+
+            if (this->store_.dryContactDoorClose) {
+                ESP_LOGD(TAG, "Dry Contact: close the door");
+                this->store_.dryContactDoorClose = false;
+                closeDoor();
+            }
+
+            if (this->store_.dryContactToggleLight) {
+                ESP_LOGD(TAG, "Dry Contact: toggle the light");
+                this->store_.dryContactToggleLight = false;
+                toggleLight();
+            }
         }
 
-        if (this->store_.dryContactToggleLight) {
-            ESP_LOGD(TAG, "Dry Contact: toggle the light");
-            this->store_.dryContactToggleLight = false;
-            toggleLight();
+        /*************************** OBSTRUCTION DETECTION ***************************/
+        void obstructionLoop()
+        {
+            long currentMillis = millis();
+            static unsigned long lastMillis = 0;
+
+            // the obstruction sensor has 3 states: clear (HIGH with LOW pulse every 7ms), obstructed (HIGH), asleep (LOW)
+            // the transitions between awake and asleep are tricky because the voltage drops slowly when falling asleep
+            // and is high without pulses when waking up
+
+            // If at least 3 low pulses are counted within 50ms, the door is awake, not obstructed and we don't have to check anything else
+
+            // Every 50ms
+            if(currentMillis - lastMillis > 50){
+                // check to see if we got between 3 and 8 low pulses on the line
+                if(this->store_.obstructionLowCount >= 3 && this->store_.obstructionLowCount <= 8){
+                    // obstructionCleared();
+                    this->store_.obstructionState = 1;
+
+                // if there have been no pulses the line is steady high or low			
+                }else if(this->store_.obstructionLowCount == 0){
+                    // if the line is high and the last high pulse was more than 70ms ago, then there is an obstruction present
+                    if(this->input_obst_pin_->digital_read() && currentMillis - this->store_.lastObstructionHigh > 70){
+                        this->store_.obstructionState = 0;
+                        // obstructionDetected();
+                    }else{
+                        // asleep
+                    }
+                }
+
+                lastMillis = currentMillis;
+                this->store_.obstructionLowCount = 0;
+            }
         }
-    }
 
-    /*************************** OBSTRUCTION DETECTION ***************************/
+        void gdoStateLoop(){
+            if(!this->swSerial.available()) {
+                //ESP_LOGD(TAG, "No data available input:%d output:%d", this->input_gdo_pin_->get_pin(), this->output_gdo_pin_->get_pin());
+                return;
+            }
+            uint8_t serData = this->swSerial.read();
 
+            static uint32_t msgStart;
+            static bool reading = false;
+            static uint16_t byteCount = 0;
 
-    void RATGDOComponent::obstructionLoop()
-    {
-        long currentMillis = millis();
-        static unsigned long lastMillis = 0;
+            if(!reading){
+                // shift serial byte onto msg start
+                msgStart <<= 8;
+                msgStart |= serData;
 
-        // the obstruction sensor has 3 states: clear (HIGH with LOW pulse every 7ms), obstructed (HIGH), asleep (LOW)
-        // the transitions between awake and asleep are tricky because the voltage drops slowly when falling asleep
-        // and is high without pulses when waking up
+                // truncate to 3 bytes
+                msgStart &= 0x00FFFFFF;
 
-        // If at least 3 low pulses are counted within 50ms, the door is awake, not obstructed and we don't have to check anything else
+                // if we are at the start of a message, capture the next 16 bytes
+                if(msgStart == 0x550100){
+                    byteCount = 3;
+                    rxRollingCode[0] = 0x55;
+                    rxRollingCode[1] = 0x01;
+                    rxRollingCode[2] = 0x00;
 
-        // Every 50ms
-        if(currentMillis - lastMillis > 50){
-            // check to see if we got between 3 and 8 low pulses on the line
-            if(this->store_.obstructionLowCount >= 3 && this->store_.obstructionLowCount <= 8){
-                // obstructionCleared();
-                this->store_.obstructionState = 1;
-
-            // if there have been no pulses the line is steady high or low			
-            }else if(this->store_.obstructionLowCount == 0){
-                // if the line is high and the last high pulse was more than 70ms ago, then there is an obstruction present
-                if(this->input_obst_pin_->digital_read() && currentMillis - this->store_.lastObstructionHigh > 70){
-                    this->store_.obstructionState = 0;
-                    // obstructionDetected();
-                }else{
-                    // asleep
+                    reading = true;
+                    return;
                 }
             }
 
-            lastMillis = currentMillis;
-            this->store_.obstructionLowCount = 0;
+            if(reading){
+                this->rxRollingCode[byteCount] = serData;
+                byteCount++;
+
+                if(byteCount == 19){
+                    reading = false;
+                    msgStart = 0;
+                    byteCount = 0;
+
+                    readRollingCode(this->store_.doorState, this->store_.lightState, this->store_.lockState, this->store_.motionState, this->store_.obstructionState);
+                }
+            }
         }
-    }
 
-    void RATGDOComponent::gdoStateLoop(){
-        if(!this->swSerial.available()) {
-            //ESP_LOGD(TAG, "No data available input:%d output:%d", this->input_gdo_pin_->get_pin(), this->output_gdo_pin_->get_pin());
-            return;
+
+        void statusUpdateLoop(){
+            // initialize to unknown
+            static uint8_t previousDoorState = 0;
+            static uint8_t previousLightState = 2;
+            static uint8_t previousLockState = 2;
+            static uint8_t previousObstructionState = 2;
+
+            if(this->store_.doorState != previousDoorState) sendDoorStatus();
+            if(this->store_.lightState != previousLightState) sendLightStatus();
+            if(this->store_.lockState != previousLockState) sendLockStatus();
+            if(this->store_.obstructionState != previousObstructionState) sendObstructionStatus();
+
+            if(this->store_.motionState == 1){
+                sendMotionStatus();
+                this->store_.motionState = 0;
+            }
+
+            previousDoorState = this->store_.doorState;
+            previousLightState = this->store_.lightState;
+            previousLockState = this->store_.lockState;
+            previousObstructionState = this->store_.obstructionState;
         }
-        uint8_t serData = this->swSerial.read();
 
-        static uint32_t msgStart;
-        static bool reading = false;
-        static uint16_t byteCount = 0;
+        void sendDoorStatus(){
+            ESP_LOGD(TAG, "Door state %d", this->store_.doorState);
+            this->status_door_pin_->digital_write(this->store_.doorState == 1);       
+        }
 
-        if(!reading){
-            // shift serial byte onto msg start
-            msgStart <<= 8;
-            msgStart |= serData;
+        void sendLightStatus(){
+            ESP_LOGD(TAG, "Light state %d", this->store_.lightState);
+        }
 
-            // truncate to 3 bytes
-            msgStart &= 0x00FFFFFF;
+        void sendLockStatus(){
+            ESP_LOGD(TAG, "Lock state %d", this->store_.lockState);
+        }
 
-            // if we are at the start of a message, capture the next 16 bytes
-            if(msgStart == 0x550100){
-                byteCount = 3;
-                rxRollingCode[0] = 0x55;
-                rxRollingCode[1] = 0x01;
-                rxRollingCode[2] = 0x00;
+        void sendMotionStatus(){
+            ESP_LOGD(TAG, "Motion state %d", this->store_.motionState);
+            this->store_.motionState = 0; // reset motion state
+        }
 
-                reading = true;
+        void sendObstructionStatus(){
+            ESP_LOGD(TAG, "Obstruction state %d", this->store_.obstructionState);
+            this->status_obst_pin_->digital_write(this->store_.obstructionState == 0);       
+        }
+
+        /************************* DOOR COMMUNICATION *************************/
+        /*
+        * Transmit a message to the door opener over uart1
+        * The TX1 pin is controlling a transistor, so the logic is inverted
+        * A HIGH state on TX1 will pull the 12v line LOW
+        *
+        * The opener requires a specific duration low/high pulse before it will accept
+        * a message
+        */
+        void transmit(const unsigned char * payload)
+        {
+            this->output_gdo_pin_->digital_write(true); // pull the line high for 1305 micros so the
+                                            // door opener responds to the message
+            delayMicroseconds(1305);
+            this->output_gdo_pin_->digital_write(false); // bring the line low
+
+            delayMicroseconds(1260); // "LOW" pulse duration before the message start
+            this->swSerial.write(payload, CODE_LENGTH);
+        }
+
+        void sync()
+        {
+            getRollingCode("reboot1");
+            transmit(this->txRollingCode);
+            delay(65);
+
+            getRollingCode("reboot2");
+            transmit(this->txRollingCode);
+            delay(65);
+
+            getRollingCode("reboot3");
+            transmit(this->txRollingCode);
+            delay(65);
+
+            getRollingCode("reboot4");
+            transmit(this->txRollingCode);
+            delay(65);
+
+            getRollingCode("reboot5");
+            transmit(this->txRollingCode);
+            delay(65);
+
+            getRollingCode("reboot6");
+            transmit(this->txRollingCode);
+            delay(65);
+
+            this->pref_.save(&this->rollingCodeCounter);
+        }
+
+        void openDoor()
+        {
+            if(this->doorStates[this->store_.doorState] == "open" || doorStates[this->store_.doorState] == "opening"){
+                ESP_LOGD(TAG, "The door is already %s", this->doorStates[this->store_.doorState]);
                 return;
             }
+            toggleDoor();
         }
 
-        if(reading){
-            this->rxRollingCode[byteCount] = serData;
-            byteCount++;
+        void closeDoor()
+        {
+            if(this->doorStates[this->store_.doorState] == "closed" || doorStates[this->store_.doorState] == "closing"){
+                ESP_LOGD(TAG, "The door is already %s", this->doorStates[this->store_.doorState]);
+                return;
+            }
+            toggleDoor();
+        }
 
-            if(byteCount == 19){
-                reading = false;
-                msgStart = 0;
-                byteCount = 0;
-
-                readRollingCode(this->store_.doorState, this->store_.lightState, this->store_.lockState, this->store_.motionState, this->store_.obstructionState);
+        void stopDoor(){
+            if(this->doorStates[this->store_.doorState] == "opening" || doorStates[this->store_.doorState] == "closing"){
+                toggleDoor();
+            }else{
+                Serial.print("The door is not moving.");
             }
         }
-    }
 
-
-    void RATGDOComponent::statusUpdateLoop(){
-        // initialize to unknown
-        static uint8_t previousDoorState = 0;
-        static uint8_t previousLightState = 2;
-        static uint8_t previousLockState = 2;
-        static uint8_t previousObstructionState = 2;
-
-        if(this->store_.doorState != previousDoorState) sendDoorStatus();
-        if(this->store_.lightState != previousLightState) sendLightStatus();
-        if(this->store_.lockState != previousLockState) sendLockStatus();
-        if(this->store_.obstructionState != previousObstructionState) sendObstructionStatus();
-
-        if(this->store_.motionState == 1){
-            sendMotionStatus();
-            this->store_.motionState = 0;
+        void toggleDoor()
+        {
+            getRollingCode("door1");
+            transmit(this->txRollingCode);
+            delay(40);
+            getRollingCode("door2");
+            transmit(this->txRollingCode);
+            this->pref_.save(&this->rollingCodeCounter);
+        
         }
 
-        previousDoorState = this->store_.doorState;
-        previousLightState = this->store_.lightState;
-        previousLockState = this->store_.lockState;
-        previousObstructionState = this->store_.obstructionState;
-    }
-
-    void RATGDOComponent::sendDoorStatus(){
-        ESP_LOGD(TAG, "Door state %d", this->store_.doorState);
-        this->status_door_pin_->digital_write(this->store_.doorState == 1);       
-    }
-
-    void RATGDOComponent::sendLightStatus(){
-        ESP_LOGD(TAG, "Light state %d", this->store_.lightState);
-    }
-
-    void RATGDOComponent::sendLockStatus(){
-        ESP_LOGD(TAG, "Lock state %d", this->store_.lockState);
-    }
-
-    void RATGDOComponent::sendMotionStatus(){
-        ESP_LOGD(TAG, "Motion state %d", this->store_.motionState);
-        this->store_.motionState = 0; // reset motion state
-    }
-
-    void RATGDOComponent::sendObstructionStatus(){
-        ESP_LOGD(TAG, "Obstruction state %d", this->store_.obstructionState);
-        this->status_obst_pin_->digital_write(this->store_.obstructionState == 0);       
-    }
-
-    /************************* DOOR COMMUNICATION *************************/
-    /*
-     * Transmit a message to the door opener over uart1
-     * The TX1 pin is controlling a transistor, so the logic is inverted
-     * A HIGH state on TX1 will pull the 12v line LOW
-     *
-     * The opener requires a specific duration low/high pulse before it will accept
-     * a message
-     */
-    void RATGDOComponent::transmit(const unsigned char * payload)
-    {
-		this->output_gdo_pin_->digital_write(true); // pull the line high for 1305 micros so the
-                                        // door opener responds to the message
-        delayMicroseconds(1305);
-		this->output_gdo_pin_->digital_write(false); // bring the line low
-
-        delayMicroseconds(1260); // "LOW" pulse duration before the message start
-        this->swSerial.write(payload, CODE_LENGTH);
-    }
-
-    void RATGDOComponent::sync()
-    {
-        getRollingCode("reboot1");
-        transmit(this->txRollingCode);
-        delay(65);
-
-        getRollingCode("reboot2");
-        transmit(this->txRollingCode);
-        delay(65);
-
-        getRollingCode("reboot3");
-        transmit(this->txRollingCode);
-        delay(65);
-
-        getRollingCode("reboot4");
-        transmit(this->txRollingCode);
-        delay(65);
-
-        getRollingCode("reboot5");
-        transmit(this->txRollingCode);
-        delay(65);
-
-        getRollingCode("reboot6");
-        transmit(this->txRollingCode);
-        delay(65);
-
-        this->pref_.save(&this->rollingCodeCounter);
-    }
-
-    void RATGDOComponent::openDoor()
-    {
-	    if(this->doorStates[this->store_.doorState] == "open" || doorStates[this->store_.doorState] == "opening"){
-            ESP_LOGD(TAG, "The door is already %s", this->doorStates[this->store_.doorState]);
-            return;
+        void lightOn(){
+            if(this->lightStates[this->store_.lightState] == "on"){
+                ESP_LOGD(TAG, "already on");
+            }else{
+                toggleLight();
+            }
         }
-        toggleDoor();
-    }
 
-    void RATGDOComponent::closeDoor()
-    {
-	    if(this->doorStates[this->store_.doorState] == "closed" || doorStates[this->store_.doorState] == "closing"){
-            ESP_LOGD(TAG, "The door is already %s", this->doorStates[this->store_.doorState]);
-            return;
+        void lightOff(){
+            if(this->lightStates[this->store_.lightState] == "off"){
+                ESP_LOGD(TAG, "already off");
+            }else{
+                toggleLight();
+            }
         }
-        toggleDoor();
-    }
 
-    void RATGDOComponent::stopDoor(){
-	    if(this->doorStates[this->store_.doorState] == "opening" || doorStates[this->store_.doorState] == "closing"){
-            toggleDoor();
-        }else{
-            Serial.print("The door is not moving.");
+        void toggleLight(){
+            sendCommand("light");
+        }
+
+        // Lock functions
+        void lock(){
+            if(this->lockStates[this->store_.lockState] == "locked"){
+                ESP_LOGD(TAG, "already locked");
+            }else{
+                toggleLock();
+            }
+        }
+
+        void unlock(){
+            if(this->lockStates[this->store_.lockState] == "unlocked"){
+                ESP_LOGD(TAG, "already unlocked");
+            }else{
+                toggleLock();
+            }
+        }
+
+        void toggleLock(){
+            sendCommand("lock");
+        }
+
+        void sendCommand(const char* command){
+            getRollingCode(command);
+            transmit(this->txRollingCode);
+            this->pref_.save(&this->rollingCodeCounter);
         }
     }
-
-    void RATGDOComponent::toggleDoor()
-    {
-        getRollingCode("door1");
-        transmit(this->txRollingCode);
-        delay(40);
-        getRollingCode("door2");
-        transmit(this->txRollingCode);
-        this->pref_.save(&this->rollingCodeCounter);
-     
-    }
-
-    void RATGDOComponent::lightOn(){
-        if(this->lightStates[this->store_.lightState] == "on"){
-            ESP_LOGD(TAG, "already on");
-        }else{
-            toggleLight();
-        }
-    }
-
-    void RATGDOComponent::lightOff(){
-        if(this->lightStates[this->store_.lightState] == "off"){
-            ESP_LOGD(TAG, "already off");
-        }else{
-            toggleLight();
-        }
-    }
-
-    void RATGDOComponent::toggleLight(){
-        sendCommand("light");
-    }
-
-    // Lock functions
-    void RATGDOComponent::lock(){
-        if(this->lockStates[this->store_.lockState] == "locked"){
-            ESP_LOGD(TAG, "already locked");
-        }else{
-            toggleLock();
-        }
-    }
-
-    void RATGDOComponent::unlock(){
-        if(this->lockStates[this->store_.lockState] == "unlocked"){
-            ESP_LOGD(TAG, "already unlocked");
-        }else{
-            toggleLock();
-        }
-    }
-
-    void RATGDOComponent::toggleLock(){
-        sendCommand("lock");
-    }
-
-    void RATGDOComponent::sendCommand(const char* command){
-        getRollingCode(command);
-        transmit(this->txRollingCode);
-        this->pref_.save(&this->rollingCodeCounter);
-    }
-
 } // namespace ratgdo
 } // namespace esphome