1

Rewrite button presses in loop to prevent blocking

This commit is contained in:
2025-07-02 17:16:13 -04:00
parent d8ed5913e6
commit 9a978cd646
2 changed files with 79 additions and 47 deletions
+70 -45
View File
@@ -5,7 +5,6 @@ namespace esphome {
namespace hauslane {
static const char *TAG = "hauslane";
static const int DELAY=250; // how long to press/release buttons in ms
void Hauslane::setup() {
// initialize the input pins
@@ -65,6 +64,52 @@ void Hauslane::loop() {
pos = 0;
}
}
// execute new button press every DELAY ms if needed to adjust state
if (millis() - this->last_press > DELAY) {
if (this->last_button) {
// button already pressed, so de-activate button
button_press(this->last_button, false);
} else if (this->meet_target) {
// adjustment of speed/light requested, so press buttons until
// reaching speed_target and light_target
if (this->speed != this->speed_target) {
// adjust speed as necessary
if (this->speed_target==0 && !this->light_cur) {
// request fan turn off and light is off, so simply hit power button
button_press(pin_power, true);
} else if (this->speed == 0 && !this->light_cur) {
if (this->power) {
// power already on, so activate fan by pressing down button
button_press(pin_down, true);
} else {
// first activate by pressing power button
button_press(pin_power, true);
}
} else if (this->speed < this->speed_target) {
// increase speed
button_press(pin_up, true)
} else if (this->speed > this->speed_target) {
// decrease speed
button_press(pin_down, true)
}
} else if (this->light_cur != this->light_target) {
if (this->power) {
// press light button
button_press(pin_light, true)
} else {
// power on hood first
button_press(pin_power, true);
}
} else {
// target already met, so rest flag
this->meet_target=false;
}
} else if (this->speed==0 && !this->light_cur) {
// reset power flag
this->power=false;
}
}
}
}
@@ -78,44 +123,17 @@ void Hauslane::dump_config() {
// turns the light on/off
void Hauslane::set_light(bool binary) {
if (this->light_cur != binary) {
if (speed==0) {
// fan is not on, so need to power system on before pressing light button
button_press(pin_power);
if (binary) {
button_press(pin_light);
}
} else {
// fan is on, so only need to press light button
button_press(pin_light);
}
if (this->light_target != binary) {
this->light_target = binary;
this->meet_target = true;
}
}
// set the speed of the fan 0=off, 6=full
void Hauslane::set_speed(int new_speed) {
if (new_speed==0 && !this->light_cur) {
// request fan turn off and light is off, so simply hit the power button
button_press(pin_power);
} else if (this->speed == 0) {
// requesting speed from 1-6
if (!this->light_cur) {
// light is off, so activate hood with power button first
button_press(pin_power);
}
// turn on the fan to previously used speed by pressing down button
button_press(pin_down);
} else {
// adjust speed pressing up/down appropriate number of times
while (this->speed != new_speed) {
if (this->speed < new_speed) {
this->speed++;
button_press(pin_up);
} else if (this->speed > new_speed) {
this->speed--;
button_press(pin_down);
}
}
if (this->speed_target != new_speed) {
this->speed_target = new_speed;
this->meet_target = true;
}
}
@@ -211,7 +229,7 @@ void Hauslane::set_state(bool set_light, uint8_t set_speed) {
}
if (speed != set_speed) {
// save current state of fan in memory
ESP_LOGD(TAG, "Received fan peed: %d", set_speed);
ESP_LOGD(TAG, "Received fan speed: %d", set_speed);
this->speed = set_speed;
// send fan state to API if it is active
if (this->send_fan_speed) {
@@ -225,27 +243,34 @@ void Hauslane::set_state(bool set_light, uint8_t set_speed) {
// simulates a button press for the specified button on front panel via GPIO
void Hauslane::command(std::string command) {
if (command == "timer" && pin_timer) {
button_press(pin_timer);
button_press(pin_timer, true);
} else if (command == "up" && pin_up) {
button_press(pin_up);
button_press(pin_up, true);
} else if (command =="down" && pin_down) {
button_press(pin_down);
button_press(pin_down, true);
} else if (command == "light" && pin_light) {
button_press(pin_light);
button_press(pin_light, true);
} else if (command == "power" && pin_power) {
button_press(pin_power);
button_press(pin_power, true);
} else {
ESP_LOGD(TAG, "Invalid button name: %s", command.c_str());
}
}
// simulate a button press by activating the GPIO then releasing
void Hauslane::button_press(GPIOPin *pin) {
void Hauslane::button_press(GPIOPin *pin, val) {
if (val) {
ESP_LOGD(TAG, "Press button: %d", pin);
pin->digital_write(true);
delay(DELAY);
pin->digital_write(false);
delay(DELAY);
this->last_button=pin;
} else {
ESP_LOGD(TAG, "Release button: %d", pin);
if (this->last_button=this->power_pin) {
this->power= !this->power;
}
this->last_button=NULL;
}
pin->digital_write(val);
last_press=millis();
}
// ESPHome light component
+8 -1
View File
@@ -17,6 +17,7 @@ static const unsigned char MSG_START[] = {0x08, 0x08, 0x08, 0xfe, 0xc0};
static const unsigned char MSG_END[] = {0xc0, 0xce, 0xce, 0xce};
static const uint8_t START_LEN=5;
static const uint8_t END_LEN=4;
static const int DELAY=250; // how long to press/release buttons in ms
class Hauslane : public Component, public uart::UARTDevice, public api::CustomAPIDevice {
public:
@@ -40,14 +41,20 @@ class Hauslane : public Component, public uart::UARTDevice, public api::CustomAP
void parse_state();
void set_state(bool set_light, uint8_t set_speed);
bool light_cur=false;
bool light_target=false;
uint8_t speed=0;
uint8_t speed_target=0;
bool meet_target=false;
bool power=false;
unsigned long last_press=0;
GPIOPin *pin_timer;
GPIOPin *pin_up;
GPIOPin *pin_down;
GPIOPin *pin_light;
GPIOPin *pin_power;
GPIOPin *last_button;
void command(std::string command);
void button_press(GPIOPin *pin);
void button_press(GPIOPin *pin, bool val);
std::function<void(bool)> send_light_state;
std::function<void(int)> send_fan_speed;
};