From 294f41f838d8c526d0759dd8bf81aefa29276d2c Mon Sep 17 00:00:00 2001 From: Siwat Sirichai Date: Sat, 23 Mar 2024 14:32:14 +0700 Subject: [PATCH] MVP2 - Missing Socket control - Missing AQI Report - Missing Temp Report --- src/config.hpp | 2 + src/display.cpp | 127 ++++++++++++++++++++++++++++++++++++++++++++++-- src/display.hpp | 3 ++ 3 files changed, 128 insertions(+), 4 deletions(-) diff --git a/src/config.hpp b/src/config.hpp index a8e66de..6b24579 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -44,6 +44,8 @@ #define DISPLAY_RX 17 #define DISPLAY_COMMUNICATION_BAUDRATE 115200 #define DISPLAY_OTA_BAUDRATE 921600 +#define DEFAULT_TEMP_LOWER_BOUND 18 +#define DEFAULT_TEMP_UPPER_BOUND 30 /*********************************************** * Persistent Storage Configuration * diff --git a/src/display.cpp b/src/display.cpp index 8098ec5..8b9b9b0 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -96,6 +96,7 @@ void CUDDisplay::begin(cud_display_cards_t cards) // AC Lock this->ac_lock.begin(10); this->ac_lock.bindFRAM(this->cards.fram, AC_LOCK_FRAM_ADDR); + this->ac_lock.setValueAutoSave(true); ac_lock_topic = (char *)malloc(base_topic_length + strlen(AC_LOCK_RELATIVE_TOPIC) + 3); sprintf(ac_lock_topic, "%s%s", base_topic, AC_LOCK_RELATIVE_TOPIC); this->ac_lock.enableIoT(this->cards.iot, ac_lock_topic); @@ -110,6 +111,7 @@ void CUDDisplay::begin(cud_display_cards_t cards) // AC Temp Lower Bound this->ac_temp_lower_bound.begin(6); this->ac_temp_lower_bound.bindFRAM(this->cards.fram, AC_DISPLAY_TEMP_LOWER_BOUND_ADDR); + this->ac_temp_lower_bound.setValueAutoSave(true); ac_temp_lower_bound_topic = (char *)malloc(base_topic_length + strlen(AC_TEMP_LOWER_BOUND_RELATIVE_TOPIC) + 3); sprintf(ac_temp_lower_bound_topic, "%s%s", base_topic, AC_TEMP_LOWER_BOUND_RELATIVE_TOPIC); this->ac_temp_lower_bound.enableIoT(this->cards.iot, ac_temp_lower_bound_topic); @@ -119,9 +121,12 @@ void CUDDisplay::begin(cud_display_cards_t cards) ac_temp_lower_bound_request_topic = (char *)malloc(base_topic_length + strlen(AC_TEMP_LOWER_BOUND_RELATIVE_TOPIC) + sizeof("/request") + 3); sprintf(ac_temp_lower_bound_request_topic, "%s%s/request", base_topic, AC_TEMP_LOWER_BOUND_RELATIVE_TOPIC); this->ac_temp_lower_bound.enableValueRequest(ac_temp_lower_bound_request_topic); + auto binded_ac_temp_lower_bound_callback = std::bind(&CUDDisplay::handle_bound_change, this, std::placeholders::_1); + this->ac_temp_lower_bound.registerCallback(binded_ac_temp_lower_bound_callback); // AC Temp Upper Bound this->ac_temp_upper_bound.begin(6); this->ac_temp_upper_bound.bindFRAM(this->cards.fram, AC_DISPLAY_TEMP_UPPER_BOUND_ADDR); + this->ac_temp_upper_bound.setValueAutoSave(true); ac_temp_upper_bound_topic = (char *)malloc(base_topic_length + strlen(AC_TEMP_UPPER_BOUND_RELATIVE_TOPIC) + 3); sprintf(ac_temp_upper_bound_topic, "%s%s", base_topic, AC_TEMP_UPPER_BOUND_RELATIVE_TOPIC); this->ac_temp_upper_bound.enableIoT(this->cards.iot, ac_temp_upper_bound_topic); @@ -131,6 +136,19 @@ void CUDDisplay::begin(cud_display_cards_t cards) ac_temp_upper_bound_request_topic = (char *)malloc(base_topic_length + strlen(AC_TEMP_UPPER_BOUND_RELATIVE_TOPIC) + sizeof("/request") + 3); sprintf(ac_temp_upper_bound_request_topic, "%s%s/request", base_topic, AC_TEMP_UPPER_BOUND_RELATIVE_TOPIC); this->ac_temp_upper_bound.enableValueRequest(ac_temp_upper_bound_request_topic); + auto binded_ac_temp_upper_bound_callback = std::bind(&CUDDisplay::handle_bound_change, this, std::placeholders::_1); + this->ac_temp_upper_bound.registerCallback(binded_ac_temp_upper_bound_callback); + + // Check Bound Validity + // Lower Bound must be less than Upper Bound + // Lower Bound can't be less than AC_MIN_TEMP + // Upper Bound can't be more than AC_MAX_TEMP + // If any of the bound is invalid, set all to default + if (this->ac_temp_lower_bound.getIntValue() < AC_MIN_TEMP || this->ac_temp_upper_bound.getIntValue() > AC_MAX_TEMP || this->ac_temp_lower_bound.getIntValue() >= this->ac_temp_upper_bound.getIntValue()) + { + this->ac_temp_lower_bound.setIntValue(DEFAULT_TEMP_LOWER_BOUND); + this->ac_temp_upper_bound.setIntValue(DEFAULT_TEMP_UPPER_BOUND); + } // Initialize the display ESP_LOGV("CUD Display", "Initializing display"); @@ -188,6 +206,7 @@ void CUDDisplay::handle_output_change(uint8_t pin, bool state) if (pin == this->conf->air_purifier_pin) { this->set_display_air_purifier_state(state); + this->refresh_display_allsystem(); return; } @@ -195,6 +214,7 @@ void CUDDisplay::handle_output_change(uint8_t pin, bool state) if (pin == this->conf->mosquito_zapper_pin) { this->set_display_mosquito_zapper_state(state); + this->refresh_display_allsystem(); return; } @@ -205,6 +225,7 @@ void CUDDisplay::handle_output_change(uint8_t pin, bool state) { this->set_display_light_state(i, state); this->set_display_light_all_state(); + this->refresh_display_allsystem(); return; } } @@ -215,6 +236,7 @@ void CUDDisplay::handle_output_change(uint8_t pin, bool state) { this->set_display_fan_state(i, state); this->set_display_fan_all_state(); + this->refresh_display_allsystem(); return; } } @@ -365,8 +387,16 @@ void CUDDisplay::handle_touch(uint8_t page_id, uint8_t element_id, uint8_t touch // Is the control locked? If it is, we can ignore the touch if (this->get_ac_lock()) return; + uint8_t newTemp = this->cards.ac->getTemperature() + 1; + // Does the temperature exceed the upper bound?, if it does, bound it + ESP_LOGD("CUD Display", "Requested Temp: %d, Lower Bound: %d", newTemp, this->ac_temp_lower_bound.getIntValue()); + if (newTemp > this->ac_temp_upper_bound.getIntValue()) + { + newTemp = this->ac_temp_upper_bound.getIntValue(); + } + ESP_LOGD("CUD Display", "New Temp: %d", newTemp); // Increase the AC temperature - this->cards.ac->setTemperature(this->cards.ac->getTemperature() + 1); + this->cards.ac->setTemperature(newTemp); return; } // Check if element_id is the AC temperature down button @@ -375,8 +405,21 @@ void CUDDisplay::handle_touch(uint8_t page_id, uint8_t element_id, uint8_t touch // Is the control locked? If it is, we can ignore the touch if (this->get_ac_lock()) return; + uint8_t newTemp = this->cards.ac->getTemperature() - 1; + // Does the temperature exceed the lower bound?, if it does, bound it + ESP_LOGD("CUD Display", "Requested Temp: %d, Lower Bound: %d", newTemp, this->ac_temp_lower_bound.getIntValue()); + if (newTemp < this->ac_temp_lower_bound.getIntValue()) + { + newTemp = this->ac_temp_lower_bound.getIntValue(); + } + ESP_LOGD("CUD Display", "New Temp: %d", newTemp); // Decrease the AC temperature - this->cards.ac->setTemperature(this->cards.ac->getTemperature() - 1); + this->cards.ac->setTemperature(newTemp); + return; + } + if (element_id == LCD_DASHBOARD_ELEMENT_ALL_SYSTEM_TOGGLE) + { + this->system_toggle(); return; } // The element_id is not the one that our display is handling, so we can ignore it @@ -384,7 +427,31 @@ void CUDDisplay::handle_touch(uint8_t page_id, uint8_t element_id, uint8_t touch void CUDDisplay::handle_lock_change(char *value) { - set_ac_lock((bool)ac_lock.getIntValue()); + this->refresh_display_ac(); +} + +void CUDDisplay::handle_bound_change(char *value) +{ + // Bound is changed, check if the bounds are valid + // Lower Bound must be less than Upper Bound + // Lower Bound can't be less than AC_MIN_TEMP + // Upper Bound can't be more than AC_MAX_TEMP + // If any of the bound is invalid, set all to default + if (this->ac_temp_lower_bound.getIntValue() < AC_MIN_TEMP || this->ac_temp_upper_bound.getIntValue() > AC_MAX_TEMP || this->ac_temp_lower_bound.getIntValue() >= this->ac_temp_upper_bound.getIntValue()) + { + this->ac_temp_lower_bound.setIntValue(DEFAULT_TEMP_LOWER_BOUND); + this->ac_temp_upper_bound.setIntValue(DEFAULT_TEMP_UPPER_BOUND); + } + // Does the current temperature exceed the new upper bound?, if it does, bound it + if (this->cards.ac->getTemperature() > this->ac_temp_upper_bound.getIntValue()) + { + this->cards.ac->setTemperature(this->ac_temp_upper_bound.getIntValue()); + } + // Does the current temperature exceed the new lower bound?, if it does, bound it + if (this->cards.ac->getTemperature() < this->ac_temp_lower_bound.getIntValue()) + { + this->cards.ac->setTemperature(this->ac_temp_lower_bound.getIntValue()); + } } void CUDDisplay::handle_aqi_change(char *value) @@ -453,6 +520,7 @@ void CUDDisplay::handle_ac_change(uint8_t mode, uint8_t fan_speed, uint8_t tempe previous_mode = mode; } this->refresh_display_ac(); + this->refresh_display_allsystem(); } void CUDDisplay::handle_ac_sensor(float temperature, float humidity) @@ -544,6 +612,7 @@ void CUDDisplay::refresh_display() this->set_display_fan_state(i, this->cards.outputCard->getState(this->conf->fan_pins[i])); } refresh_display_ac(); + refresh_display_allsystem(); } void CUDDisplay::refresh_display_ac() @@ -626,9 +695,59 @@ void CUDDisplay::refresh_display_ac() this->giveSerialMutex(); } +void CUDDisplay::refresh_display_allsystem() +{ + this->takeSerialMutex(); + this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_ALL_SYSTEM_TOGGLE, this->get_system_state() ? LCD_DASHBOARD_PIC_ALL_SYSTEM_TOGGLE_ON : LCD_DASHBOARD_PIC_ALL_SYSTEM_TOGGLE_OFF); + this->sendStopBytes(); + this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_ALL_SYSTEM_TOGGLE, this->get_system_state() ? LCD_DASHBOARD_PIC_ALL_SYSTEM_TOGGLE_ON_PRESSED : LCD_DASHBOARD_PIC_ALL_SYSTEM_TOGGLE_OFF_PRESSED); + this->sendStopBytes(); + this->giveSerialMutex(); +} + +bool CUDDisplay::get_system_state() +{ + // The system state is defined to be on when any of the lights, fans, air purifier, mosquito zapper or AC is on + return this->get_lights_state() || this->get_fans_state() || this->cards.outputCard->getState(this->conf->air_purifier_pin) || this->cards.outputCard->getState(this->conf->mosquito_zapper_pin) || this->cards.ac->getMode() != 0; +} + void CUDDisplay::system_toggle() { - // TODO: Implement this + // If the system is on, turn everything off if it is on + if (this->get_system_state()) + { + for (int i = 0; i < 4; i++) + { + if (this->cards.outputCard->getState(this->conf->light_pins[i])) + this->cards.outputCard->setState(this->conf->light_pins[i], false); + } + for (int i = 0; i < 3; i++) + { + if (this->cards.outputCard->getState(this->conf->fan_pins[i])) + this->cards.outputCard->setState(this->conf->fan_pins[i], false); + } + if (this->cards.outputCard->getState(this->conf->air_purifier_pin)) + this->cards.outputCard->setState(this->conf->air_purifier_pin, false); + if (this->cards.outputCard->getState(this->conf->mosquito_zapper_pin)) + this->cards.outputCard->setState(this->conf->mosquito_zapper_pin, false); + if (!ac_lock.getIntValue() && this->cards.ac->getMode() != 0) + this->cards.ac->setMode(0); + } + // If the system is off, turn lights, mosquito zapper, air purifier and AC on if they are off + else + { + for (int i = 0; i < 4; i++) + { + if (!this->cards.outputCard->getState(this->conf->light_pins[i])) + this->cards.outputCard->setState(this->conf->light_pins[i], true); + } + if (!this->cards.outputCard->getState(this->conf->mosquito_zapper_pin)) + this->cards.outputCard->setState(this->conf->mosquito_zapper_pin, true); + if (!this->cards.outputCard->getState(this->conf->air_purifier_pin)) + this->cards.outputCard->setState(this->conf->air_purifier_pin, true); + if (!ac_lock.getIntValue()) + this->cards.ac->setMode(previous_mode); + } } void CUDDisplay::set_ac_lock(bool state) diff --git a/src/display.hpp b/src/display.hpp index 35f8a45..0879080 100644 --- a/src/display.hpp +++ b/src/display.hpp @@ -86,6 +86,7 @@ private: void handle_ac_sensor(float temperature, float humidity); void handle_touch(uint8_t page_id, uint8_t element_id, uint8_t touch_type); void handle_lock_change(char* value); + void handle_bound_change(char* value); // Change Display Elements void set_display_light_state(uint8_t row, bool state); void set_display_light_all_state(); @@ -95,7 +96,9 @@ private: void set_display_air_purifier_state(bool state); void refresh_display(); void refresh_display_ac(); + void refresh_display_allsystem(); // Helper Functions + bool get_system_state(); void system_toggle(); // AC Functions and Variables uint8_t previous_mode; // Used to store mode prior to turning off