cud-iot-v3/src/cud_display.cpp

304 lines
13 KiB
C++

#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]));
}
}