#include "cud_display.hpp" CUDDisplay::CUDDisplay(cud_display_conf_t *conf) : ESPMegaDisplay(conf->uart, conf->communication_baudrate, conf->ota_baudrate, conf->tx, conf->rx) { this->conf = conf; // Initialize Light Group and Fan Group this->light_group = { .element_id = {LCD_DASHBOARD_ELEMENT_LIGHT_1, LCD_DASHBOARD_ELEMENT_LIGHT_2, LCD_DASHBOARD_ELEMENT_LIGHT_3, LCD_DASHBOARD_ELEMENT_LIGHT_4}, .element_name = {LCD_DASHBOARD_ELEMENT_NAME_LIGHT_1, LCD_DASHBOARD_ELEMENT_NAME_LIGHT_2, LCD_DASHBOARD_ELEMENT_NAME_LIGHT_3, LCD_DASHBOARD_ELEMENT_NAME_LIGHT_4}, .picture_on = {LCD_DASHBOARD_PIC_LIGHT_1_ON, LCD_DASHBOARD_PIC_LIGHT_2_ON, LCD_DASHBOARD_PIC_LIGHT_3_ON, LCD_DASHBOARD_PIC_LIGHT_4_ON}, .picture_on_pressed = {LCD_DASHBOARD_PIC_LIGHT_1_ON_PRESSED, LCD_DASHBOARD_PIC_LIGHT_2_ON_PRESSED, LCD_DASHBOARD_PIC_LIGHT_3_ON_PRESSED, LCD_DASHBOARD_PIC_LIGHT_4_ON_PRESSED}, .picture_off = {LCD_DASHBOARD_PIC_LIGHT_1_OFF, LCD_DASHBOARD_PIC_LIGHT_2_OFF, LCD_DASHBOARD_PIC_LIGHT_3_OFF, LCD_DASHBOARD_PIC_LIGHT_4_OFF}, .picture_off_pressed = {LCD_DASHBOARD_PIC_LIGHT_1_OFF_PRESSED, LCD_DASHBOARD_PIC_LIGHT_2_OFF_PRESSED, LCD_DASHBOARD_PIC_LIGHT_3_OFF_PRESSED, LCD_DASHBOARD_PIC_LIGHT_4_OFF_PRESSED} }; this->fan_group = { .element_id = {LCD_DASHBOARD_ELEMENT_FAN_1, LCD_DASHBOARD_ELEMENT_FAN_2, LCD_DASHBOARD_ELEMENT_FAN_3}, .element_name = {LCD_DASHBOARD_ELEMENT_NAME_FAN_1, LCD_DASHBOARD_ELEMENT_NAME_FAN_2, LCD_DASHBOARD_ELEMENT_NAME_FAN_3}, .picture_on = {LCD_DASHBOARD_PIC_FAN_1_ON, LCD_DASHBOARD_PIC_FAN_2_ON, LCD_DASHBOARD_PIC_FAN_3_ON}, .picture_on_pressed = {LCD_DASHBOARD_PIC_FAN_1_ON_PRESSED, LCD_DASHBOARD_PIC_FAN_2_ON_PRESSED, LCD_DASHBOARD_PIC_FAN_3_ON_PRESSED}, .picture_off = {LCD_DASHBOARD_PIC_FAN_1_OFF, LCD_DASHBOARD_PIC_FAN_2_OFF, LCD_DASHBOARD_PIC_FAN_3_OFF}, .picture_off_pressed = {LCD_DASHBOARD_PIC_FAN_1_OFF_PRESSED, LCD_DASHBOARD_PIC_FAN_2_OFF_PRESSED, LCD_DASHBOARD_PIC_FAN_3_OFF_PRESSED} }; } void CUDDisplay::begin() { // Register callbacks auto binded_input_callback = std::bind(&CUDDisplay::handle_input_change, this, std::placeholders::_1, std::placeholders::_2); auto binded_output_callback = std::bind(&CUDDisplay::handle_output_change, this, std::placeholders::_1, std::placeholders::_2); auto binded_aqi_callback = std::bind(&CUDDisplay::handle_aqi_change, this, std::placeholders::_1); auto binded_payload_callback = std::bind(&CUDDisplay::handle_payload, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); auto binded_touch_callback = std::bind(&CUDDisplay::handle_touch, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); this->conf->inputCard->registerCallback(binded_input_callback); this->conf->outputCard->registerChangeCallback(binded_output_callback); this->conf->aqi->registerCallback(binded_aqi_callback); this->registerPayloadCallback(binded_payload_callback); this->registerTouchCallback(binded_touch_callback); // Initialize the display this->display_init(); } void CUDDisplay::display_init() { // Perform a reset on the display this->reset(); // Set the display to the main screen this->jumpToPage(LCD_PAGE_ID_DASHBOARD); // Send the initial states to the display this->refresh_display(); } bool CUDDisplay::get_lights_state() { for (int i = 0; i < 4; i++) { if (this->conf->outputCard->getState(this->conf->light_pins[i])) return true; } return false; } bool CUDDisplay::get_fans_state() { for (int i = 0; i < 3; i++) { if (this->conf->outputCard->getState(this->conf->fan_pins[i])) return true; } return false; } void CUDDisplay::handle_input_change(uint8_t pin, bool state) { // This is not needed for now. We are only handling outputs // Putting this here in case we need to handle inputs in the future } void CUDDisplay::handle_output_change(uint8_t pin, bool state) { // Check if it is a light or fan // If it's a light, call set_display_light_state // If it's a fan, call set_display_fan_state // If it's the air purifier, call set_display_air_purifier_state // If it's the mosquito zapper, call set_display_mosquito_zapper_state // Check if it's the air purifier if (pin == this->conf->air_purifier_pin) { this->set_display_air_purifier_state(state); return; } // Check if it's the mosquito zapper if (pin == this->conf->mosquito_zapper_pin) { this->set_display_mosquito_zapper_state(state); return; } // Loop through each to check if the pin is a light for (int i = 0; i < 4; i++) { if (pin == this->conf->light_pins[i]) { this->set_display_light_state(i, state); this->set_display_light_all_state(); return; } } // Loop through each to check if the pin is a fan for (int i = 0; i < 3; i++) { if (pin == this->conf->fan_pins[i]) { this->set_display_fan_state(i, state); this->set_display_fan_all_state(); return; } } // The pin is not the one that our display is handling, so we can ignore it } void CUDDisplay::handle_touch(uint8_t page_id, uint8_t element_id, uint8_t touch_type) { // Check if element_id is the light all button if (element_id == LCD_DASHBOARD_ELEMENT_LIGHT_ALL) { // If it is, toggle all the lights bool light_on = this->get_lights_state(); for (int i = 0; i < 4; i++) { this->conf->outputCard->setState(this->conf->light_pins[i], !light_on); } return; } // Check if element_id is the fan all button else if (element_id == LCD_DASHBOARD_ELEMENT_FAN_ALL) { // If it is, toggle all the fans bool fan_on = this->get_fans_state(); for (int i = 0; i < 3; i++) { this->conf->outputCard->setState(this->conf->fan_pins[i], !fan_on); } return; } // Check if element_id is the air purifier button else if (element_id == LCD_DASHBOARD_ELEMENT_AIR_PURIFIER) { // If it is, toggle the air purifier this->conf->outputCard->setState(this->conf->air_purifier_pin, !this->conf->outputCard->getState(this->conf->air_purifier_pin)); return; } // Check if element_id is the mosquito zapper button else if (element_id == LCD_DASHBOARD_ELEMENT_MOSQUITO_ZAPPER) { // If it is, toggle the mosquito zapper this->conf->outputCard->setState(this->conf->mosquito_zapper_pin, !this->conf->outputCard->getState(this->conf->mosquito_zapper_pin)); return; } // Check if element_id is a light button for (int i = 0; i < 4; i++) { if (element_id == this->light_group.element_id[i]) { // If it is, toggle the light this->conf->outputCard->setState(this->conf->light_pins[i], !this->conf->outputCard->getState(this->conf->light_pins[i])); return; } } // Check if element_id is a fan button for (int i = 0; i < 3; i++) { if (element_id == this->fan_group.element_id[i]) { // If it is, toggle the fan this->conf->outputCard->setState(this->conf->fan_pins[i], !this->conf->outputCard->getState(this->conf->fan_pins[i])); return; } } // The element_id is not the one that our display is handling, so we can ignore it } void CUDDisplay::handle_aqi_change(char *value) { // Update the AQI value on the display float aqi = atof(value); this->takeSerialMutex(); this->displayAdapter->printf("%s.txt=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, (int)aqi); this->sendStopBytes(); // Update the AQI picture on the display if (aqi <= 50) { this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_PIC_AQI_GOOD); } else if (aqi <= 100) { this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_PIC_AQI_MODERATE); } else if (aqi <= 150) { this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_PIC_AQI_UNHEALTHY_FOR_SENSITIVE_GROUPS); } else if (aqi <= 200) { this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_PIC_AQI_UNHEALTHY); } else if (aqi <= 300) { this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_PIC_AQI_VERY_UNHEALTHY); } else { this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_PIC_AQI_HAZARDOUS); } this->giveSerialMutex(); } /** * @brief Handle the payload from the display that is not handled by the parent class * * @param type Payload type * @param payload The payload itself * @param length The length of the payload excluding the type */ void CUDDisplay::handle_payload(uint8_t type, uint8_t *payload, uint8_t length) { // If payload of type 0x92 is received // Reset the display and reinitialize it if (type == 0x92) { this->display_init(); } } void CUDDisplay::set_display_light_state(uint8_t row, bool state) { this->takeSerialMutex(); this->displayAdapter->printf("%s.pic=%d", this->light_group.element_name[row], state ? this->light_group.picture_on[row] : this->light_group.picture_off[row]); this->displayAdapter->printf("%s.pic2=%d", this->light_group.element_name[row], state ? this->light_group.picture_on_pressed[row] : this->light_group.picture_off_pressed[row]); this->sendStopBytes(); this->giveSerialMutex(); } void CUDDisplay::set_display_light_all_state() { bool light_on = this->get_lights_state(); this->takeSerialMutex(); this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_LIGHT_ALL, light_on ? LCD_DASHBOARD_PIC_LIGHT_ALL_ON : LCD_DASHBOARD_PIC_LIGHT_ALL_OFF); this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_LIGHT_ALL, light_on ? LCD_DASHBOARD_PIC_LIGHT_ALL_ON_PRESSED : LCD_DASHBOARD_PIC_LIGHT_ALL_OFF_PRESSED); this->sendStopBytes(); this->giveSerialMutex(); } void CUDDisplay::set_display_fan_state(uint8_t row, bool state) { this->takeSerialMutex(); this->displayAdapter->printf("%s.pic=%d", this->fan_group.element_name[row], state ? this->fan_group.picture_on[row] : this->fan_group.picture_off[row]); this->displayAdapter->printf("%s.pic2=%d", this->fan_group.element_name[row], state ? this->fan_group.picture_on_pressed[row] : this->fan_group.picture_off_pressed[row]); this->sendStopBytes(); this->giveSerialMutex(); } void CUDDisplay::set_display_fan_all_state() { bool fan_on = this->get_fans_state(); this->takeSerialMutex(); this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_FAN_ALL, fan_on ? LCD_DASHBOARD_PIC_FAN_ALL_ON : LCD_DASHBOARD_PIC_FAN_ALL_OFF); this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_FAN_ALL, fan_on ? LCD_DASHBOARD_PIC_FAN_ALL_ON_PRESSED : LCD_DASHBOARD_PIC_FAN_ALL_OFF_PRESSED); this->sendStopBytes(); } void CUDDisplay::set_display_mosquito_zapper_state(bool state) { this->takeSerialMutex(); this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_MOSQUITO_ZAPPER, state ? LCD_DASHBOARD_PIC_MOSQUITO_ZAPPER_ON : LCD_DASHBOARD_PIC_MOSQUITO_ZAPPER_OFF); this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_MOSQUITO_ZAPPER, state ? LCD_DASHBOARD_PIC_MOSQUITO_ZAPPER_ON_PRESSED : LCD_DASHBOARD_PIC_MOSQUITO_ZAPPER_OFF_PRESSED); this->sendStopBytes(); } void CUDDisplay::set_display_air_purifier_state(bool state) { this->takeSerialMutex(); this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AIR_PURIFIER, state ? LCD_DASHBOARD_PIC_AIR_PURIFIER_ON : LCD_DASHBOARD_PIC_AIR_PURIFIER_OFF); this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AIR_PURIFIER, state ? LCD_DASHBOARD_PIC_AIR_PURIFIER_ON_PRESSED : LCD_DASHBOARD_PIC_AIR_PURIFIER_OFF_PRESSED); this->sendStopBytes(); } void CUDDisplay::refresh_display() { // Send every states to the display this->set_display_light_all_state(); this->set_display_fan_all_state(); this->set_display_air_purifier_state(this->conf->outputCard->getState(this->conf->air_purifier_pin)); this->set_display_mosquito_zapper_state(this->conf->outputCard->getState(this->conf->mosquito_zapper_pin)); for (int i = 0; i < 4; i++) { this->set_display_light_state(i, this->conf->outputCard->getState(this->conf->light_pins[i])); } for (int i = 0; i < 3; i++) { this->set_display_fan_state(i, this->conf->outputCard->getState(this->conf->fan_pins[i])); } }