cud-iot-v3/src/display.cpp

981 lines
45 KiB
C++

#include "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}};
}
CUDDisplay::~CUDDisplay()
{
if (ac_lock_topic != nullptr)
{
free(ac_lock_topic);
}
if (ac_lock_set_topic != nullptr)
{
free(ac_lock_set_topic);
}
if (ac_lock_request_topic != nullptr)
{
free(ac_lock_request_topic);
}
if (ac_temp_upper_bound_topic != nullptr)
{
free(ac_temp_upper_bound_topic);
}
if (ac_temp_upper_bound_set_topic != nullptr)
{
free(ac_temp_upper_bound_set_topic);
}
if (ac_temp_upper_bound_request_topic != nullptr)
{
free(ac_temp_upper_bound_request_topic);
}
if (ac_temp_lower_bound_topic != nullptr)
{
free(ac_temp_lower_bound_topic);
}
if (ac_temp_lower_bound_set_topic != nullptr)
{
free(ac_temp_lower_bound_set_topic);
}
if (ac_temp_lower_bound_request_topic != nullptr)
{
free(ac_temp_lower_bound_request_topic);
}
}
void CUDDisplay::begin(cud_display_cards_t cards)
{
// Save Cards
this->cards = cards;
// Register callbacks
ESP_LOGV("CUD Display", "Registering 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);
auto binded_ac_callback = std::bind(&CUDDisplay::handle_ac_change, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
auto binded_ac_sensor_callback = std::bind(&CUDDisplay::handle_ac_sensor, this, std::placeholders::_1, std::placeholders::_2);
auto binded_handle_mqtt_connected = std::bind(&CUDDisplay::handle_mqtt_connected, this);
ESP_LOGV("CUD Display", "Registering Input Card Callbacks");
this->cards.inputCard->registerCallback(binded_input_callback);
ESP_LOGV("CUD Display", "Registering Output Card Callbacks");
this->cards.outputCard->registerChangeCallback(binded_output_callback);
ESP_LOGV("CUD Display", "Registering AQI Callbacks");
this->conf->aqi->registerCallback(binded_aqi_callback);
ESP_LOGV("CUD Display", "Registering MQTT Connected Callbacks");
this->cards.iot->registerSubscribeCallback(binded_handle_mqtt_connected);
ESP_LOGV("CUD Display", "Registering Display Payload Callbacks");
this->registerPayloadCallback(binded_payload_callback);
ESP_LOGV("CUD Display", "Registering Display Touch Callbacks");
this->registerTouchCallback(binded_touch_callback);
ESP_LOGV("CUD Display", "Registering AC Callbacks");
this->cards.ac->registerChangeCallback(binded_ac_callback);
ESP_LOGV("CUD Display", "Registering AC Sensor Callbacks");
this->cards.ac->registerSensorCallback(binded_ac_sensor_callback);
// Initialize Smart Variables
ESP_LOGV("CUD Display", "Initializing Smart Variables");
// Get Base Topic
char *base_topic = this->cards.iot->getMqttConfig()->base_topic;
uint8_t base_topic_length = strlen(base_topic);
// Smart Variables
// 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);
ac_lock_set_topic = (char *)malloc(base_topic_length + strlen(AC_LOCK_RELATIVE_TOPIC) + sizeof("/set") + 3);
sprintf(ac_lock_set_topic, "%s%s/set", base_topic, AC_LOCK_RELATIVE_TOPIC);
this->ac_lock.enableSetValue(ac_lock_set_topic);
ac_lock_request_topic = (char *)malloc(base_topic_length + strlen(AC_LOCK_RELATIVE_TOPIC) + sizeof("/request") + 3);
sprintf(ac_lock_request_topic, "%s%s/request", base_topic, AC_LOCK_RELATIVE_TOPIC);
this->ac_lock.enableValueRequest(ac_lock_request_topic);
auto binded_ac_lock_callback = std::bind(&CUDDisplay::handle_lock_change, this, std::placeholders::_1);
this->ac_lock.registerCallback(binded_ac_lock_callback);
// 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);
ac_temp_lower_bound_set_topic = (char *)malloc(base_topic_length + strlen(AC_TEMP_LOWER_BOUND_RELATIVE_TOPIC) + sizeof("/set") + 3);
sprintf(ac_temp_lower_bound_set_topic, "%s%s/set", base_topic, AC_TEMP_LOWER_BOUND_RELATIVE_TOPIC);
this->ac_temp_lower_bound.enableSetValue(ac_temp_lower_bound_set_topic);
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);
ac_temp_upper_bound_set_topic = (char *)malloc(base_topic_length + strlen(AC_TEMP_UPPER_BOUND_RELATIVE_TOPIC) + sizeof("/set") + 3);
sprintf(ac_temp_upper_bound_set_topic, "%s%s/set", base_topic, AC_TEMP_UPPER_BOUND_RELATIVE_TOPIC);
this->ac_temp_upper_bound.enableSetValue(ac_temp_upper_bound_set_topic);
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())
{
ESP_LOGW("CUD Display", "Temperature Bounds are invalid, setting to default");
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");
this->display_init();
}
void CUDDisplay::loop()
{
ESPMegaDisplay::loop();
// Check if the AC button press is pending
if (this->ac_button_press_pending)
{
// Check if the delay has passed
if (millis() - this->last_ac_button_press > AC_TEMP_PRESS_DELAY)
{
ESP_LOGV("CUD Display", "Sending pending temperature");
// Send the pending temperature
this->cards.ac->setTemperature(this->pending_temperature);
// Reset the pending flag
this->ac_button_press_pending = false;
}
}
// Check if MQTT is connected
static uint32_t last_mqtt_connected_check = 0;
if (last_mqtt_connected_check == 0)
{
last_mqtt_connected_check = millis() + 15000; // Wait 15 seconds before checking
}
static bool first_disconnect = true;
if (millis() - last_mqtt_connected_check > 3000)
{
ESP_LOGD("CUD Display", "Checking MQTT Connection, Connection is %s", this->cards.iot->mqttConnected() ? "true" : "false");
if (!this->cards.iot->mqttConnected())
{
this->standalone = true;
if (first_disconnect)
{
// When MQTT is disconnected, enter standalone mode
// In standalone mode, socket contactor is turned on
// A/C lock is lifted
// A/C temperature range limits are lifted
this->refresh_display_ac();
this->cards.outputCard->setState(this->conf->socket_contactor_pin, true);
first_disconnect = false;
}
}
else
{
standalone = false;
if (first_disconnect == false)
{
// When MQTT is connected, exit standalone mode
// In standalone mode, socket contactor is turned off
// A/C lock is set
// A/C temperature range limits are set
first_disconnect = true;
// Rebound the temperature
if (this->cards.ac->getTemperature() < this->get_ac_temp_lower_bound())
{
this->cards.ac->setTemperature(this->get_ac_temp_lower_bound());
}
else if (this->cards.ac->getTemperature() > this->get_ac_temp_upper_bound())
{
this->cards.ac->setTemperature(this->get_ac_temp_upper_bound());
}
this->refresh_display_ac();
}
}
last_mqtt_connected_check = millis();
}
}
void CUDDisplay::display_init()
{
// Perform a reset on the display
ESP_LOGV("CUD Display", "Resetting display");
this->reset();
vTaskDelay(1000 / portTICK_PERIOD_MS);
// Set the display to the main screen
ESP_LOGV("CUD Display", "Setting display to main screen");
this->jumpToPage(LCD_PAGE_ID_DASHBOARD);
// Send the initial states to the display
ESP_LOGV("CUD Display", "Sending initial states to display");
this->refresh_display();
}
bool CUDDisplay::get_lights_state()
{
for (int i = 0; i < 4; i++)
{
if (this->cards.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->cards.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);
this->refresh_display_allsystem();
return;
}
// Check if it's the mosquito zapper
if (pin == this->conf->mosquito_zapper_pin)
{
this->set_display_mosquito_zapper_state(state);
this->refresh_display_allsystem();
return;
}
// Check if it's the socket contactor
if (pin == this->conf->socket_contactor_pin)
{
this->refresh_display_socket();
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();
this->refresh_display_allsystem();
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();
this->refresh_display_allsystem();
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->cards.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->cards.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->cards.outputCard->setState(this->conf->air_purifier_pin, !this->cards.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->cards.outputCard->setState(this->conf->mosquito_zapper_pin, !this->cards.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->cards.outputCard->setState(this->conf->light_pins[i], !this->cards.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->cards.outputCard->setState(this->conf->fan_pins[i], !this->cards.outputCard->getState(this->conf->fan_pins[i]));
return;
}
}
// Check if element_id is the AC state button
if (element_id == LCD_DASHBOARD_ELEMENT_AC_STATE)
{
// Is the control locked? If it is, we can ignore the touch
if (this->get_ac_lock())
return;
// Toggle the AC
// Is the AC on?
if (this->cards.ac->getMode() != 0)
{
// If it is, turn it off
this->cards.ac->setMode(0);
}
else
{
// If it is not, turn it on
this->cards.ac->setMode(previous_mode);
}
return;
}
// Check if element_id is the AC mode fan button
if (element_id == LCD_DASHBOARD_ELEMENT_AC_MODE_FAN)
{
// Is the control locked? If it is, we can ignore the touch
if (this->get_ac_lock())
return;
// Set the AC mode to fan
this->cards.ac->setMode(1);
return;
}
// Check if element_id is the AC mode cool button
if (element_id == LCD_DASHBOARD_ELEMENT_AC_MODE_COOL)
{
// Is the control locked? If it is, we can ignore the touch
if (this->get_ac_lock())
return;
// Set the AC mode to cool
this->cards.ac->setMode(2);
return;
}
// Check if element_id is the AC fan speed auto button
if (element_id == LCD_DASHBOARD_ELEMENT_AC_FAN_SPEED_AUTO)
{
// Is the control locked? If it is, we can ignore the touch
if (this->get_ac_lock())
return;
// Set the AC fan speed to auto
this->cards.ac->setFanSpeed(0);
return;
}
// Check if element_id is the AC fan speed low button
if (element_id == LCD_DASHBOARD_ELEMENT_AC_FAN_SPEED_LOW)
{
// Is the control locked? If it is, we can ignore the touch
if (this->get_ac_lock())
return;
// Set the AC fan speed to low
this->cards.ac->setFanSpeed(1);
return;
}
// Check if element_id is the AC fan speed medium button
if (element_id == LCD_DASHBOARD_ELEMENT_AC_FAN_SPEED_MEDIUM)
{
// Is the control locked? If it is, we can ignore the touch
if (this->get_ac_lock())
return;
// Set the AC fan speed to medium
this->cards.ac->setFanSpeed(2);
return;
}
// Check if element_id is the AC fan speed high button
if (element_id == LCD_DASHBOARD_ELEMENT_AC_FAN_SPEED_HIGH)
{
// Is the control locked? If it is, we can ignore the touch
if (this->get_ac_lock())
return;
// Set the AC fan speed to high
this->cards.ac->setFanSpeed(3);
return;
}
// Check if element_id is the AC temperature up button
if (element_id == LCD_DASHBOARD_ELEMENT_AC_TEMP_UP_BUTTON)
{
// 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();
if (this->ac_button_press_pending)
{
// If the button press is pending, use the pending temperature as base
newTemp = this->pending_temperature;
}
newTemp++;
// Does the temperature exceed the upper bound?, if it does, bound it
if (newTemp > this->get_ac_temp_upper_bound())
{
newTemp = this->get_ac_temp_upper_bound();
}
ESP_LOGD("CUD Display", "New Temp: %d", newTemp);
// Increase the AC temperature
pending_temperature = newTemp;
ac_button_press_pending = true;
last_ac_button_press = millis();
// Send the new temperature to the Display
this->takeSerialMutex();
this->displayAdapter->printf("%s.txt=\"%d\"", LCD_DASHBOARD_ELEMENT_NAME_AC_TEMPERATURE, newTemp);
this->sendStopBytes();
this->giveSerialMutex();
return;
}
// Check if element_id is the AC temperature down button
if (element_id == LCD_DASHBOARD_ELEMENT_AC_TEMP_DOWN_BUTTON)
{
// 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();
if (this->ac_button_press_pending)
{
// If the button press is pending, use the pending temperature as base
newTemp = this->pending_temperature;
}
newTemp--;
// Does the temperature exceed the lower bound?, if it does, bound it
ESP_LOGD("CUD Display", "Requested Temp: %d, Lower Bound: %d", newTemp, this->get_ac_temp_lower_bound());
if (newTemp < this->get_ac_temp_lower_bound())
{
newTemp = this->get_ac_temp_lower_bound();
}
ESP_LOGD("CUD Display", "New Temp: %d", newTemp);
// Decrease the AC temperature
pending_temperature = newTemp;
ac_button_press_pending = true;
last_ac_button_press = millis();
// Send the new temperature to the Display
this->takeSerialMutex();
this->displayAdapter->printf("%s.txt=\"%d\"", LCD_DASHBOARD_ELEMENT_NAME_AC_TEMPERATURE, newTemp);
this->sendStopBytes();
this->giveSerialMutex();
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
}
void CUDDisplay::handle_lock_change(char *value)
{
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_lower_bound.getIntValue() >= this->ac_temp_upper_bound.getIntValue())
{
ESP_LOGV("CUD Display", "Invalid Lower Bound, Setting to Default");
this->ac_temp_lower_bound.setIntValue(DEFAULT_TEMP_LOWER_BOUND);
}
if (this->ac_temp_upper_bound.getIntValue() > AC_MAX_TEMP || this->ac_temp_lower_bound.getIntValue() >= this->ac_temp_upper_bound.getIntValue())
{
ESP_LOGV("CUD Display", "Invalid Upper Bound, Setting to Default");
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)
{
ESP_LOGV("CUD Display", "AQI Changed: %s", value);
// Update the AQI value on the display
uint16_t aqi = atoi(value);
this->takeSerialMutex();
this->displayAdapter->printf("%s.txt=\"%03d\"", 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_PICTURE, LCD_DASHBOARD_PIC_AQI_GOOD);
this->sendStopBytes();
this->displayAdapter->printf("%s.pco=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_COLOR_AQI_TEXT_GOOD);
this->sendStopBytes();
}
else if (aqi <= 100)
{
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_PICTURE, LCD_DASHBOARD_PIC_AQI_MODERATE);
this->sendStopBytes();
this->displayAdapter->printf("%s.pco=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_COLOR_AQI_TEXT_MODERATE);
this->sendStopBytes();
}
else if (aqi <= 150)
{
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_PICTURE, LCD_DASHBOARD_PIC_AQI_UNHEALTHY_FOR_SENSITIVE_GROUPS);
this->sendStopBytes();
this->displayAdapter->printf("%s.pco=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_COLOR_AQI_TEXT_UNHEALTHY_FOR_SENSITIVE_GROUPS);
this->sendStopBytes();
}
else if (aqi <= 200)
{
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_PICTURE, LCD_DASHBOARD_PIC_AQI_UNHEALTHY);
this->sendStopBytes();
this->displayAdapter->printf("%s.pco=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_COLOR_AQI_TEXT_UNHEALTHY);
this->sendStopBytes();
}
else if (aqi <= 300)
{
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_PICTURE, LCD_DASHBOARD_PIC_AQI_VERY_UNHEALTHY);
this->sendStopBytes();
this->displayAdapter->printf("%s.pco=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_COLOR_AQI_TEXT_VERY_UNHEALTHY);
this->sendStopBytes();
}
else
{
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_PICTURE, LCD_DASHBOARD_PIC_AQI_HAZARDOUS);
this->sendStopBytes();
this->displayAdapter->printf("%s.pco=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_COLOR_AQI_TEXT_HAZARDOUS);
this->sendStopBytes();
}
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::handle_ac_change(uint8_t mode, uint8_t fan_speed, uint8_t temperature)
{
// Set the previous mode to the current mode if the current mode is not 0
if (mode != 0)
{
previous_mode = mode;
}
this->refresh_display_ac();
this->refresh_display_allsystem();
}
void CUDDisplay::handle_ac_sensor(float temperature, float humidity)
{
// Is the temperature valid?
// A temperature of -999.0 means the sensor is not connected
ESP_LOGV("CUD Display", "AC Sensor Temperature: %f", temperature);
if (temperature == -999.0)
{
// If the temperature is not valid, Send NA to the display
this->takeSerialMutex();
this->displayAdapter->printf("%s.txt=\"NA\"", LCD_DASHBOARD_ELEMENT_NAME_ROOM_TEMPERATURE);
this->sendStopBytes();
this->giveSerialMutex();
return;
}
// Temperature is valid, send it to the display
this->takeSerialMutex();
this->displayAdapter->printf("%s.txt=\"%d\"", LCD_DASHBOARD_ELEMENT_NAME_ROOM_TEMPERATURE, (int)temperature);
this->sendStopBytes();
this->giveSerialMutex();
}
void CUDDisplay::handle_mqtt_connected()
{
// Refresh the display
this->refresh_display_ac();
}
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->sendStopBytes();
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->sendStopBytes();
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->sendStopBytes();
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->sendStopBytes();
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();
this->giveSerialMutex();
}
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->sendStopBytes();
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();
this->giveSerialMutex();
}
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->sendStopBytes();
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();
this->giveSerialMutex();
}
void CUDDisplay::refresh_display()
{
// Send every states to the display
ESP_LOGV("CUD Display", "Refreshing all light button states");
this->set_display_light_all_state();
ESP_LOGV("CUD Display", "Refreshing all fan button states");
this->set_display_fan_all_state();
ESP_LOGV("CUD Display", "Refreshing air purifier state");
this->set_display_air_purifier_state(this->cards.outputCard->getState(this->conf->air_purifier_pin));
ESP_LOGV("CUD Display", "Refreshing mosquito zapper state");
this->set_display_mosquito_zapper_state(this->cards.outputCard->getState(this->conf->mosquito_zapper_pin));
ESP_LOGV("CUD Display", "Refreshing light states");
for (int i = 0; i < 4; i++)
{
this->set_display_light_state(i, this->cards.outputCard->getState(this->conf->light_pins[i]));
}
ESP_LOGV("CUD Display", "Refreshing Fan state");
for (int i = 0; i < 3; i++)
{
this->set_display_fan_state(i, this->cards.outputCard->getState(this->conf->fan_pins[i]));
}
refresh_display_ac();
refresh_display_allsystem();
refresh_display_socket();
}
void CUDDisplay::refresh_display_ac()
{
// Fetch data from the AC
uint8_t mode = this->cards.ac->getMode();
bool state = mode != 0;
previous_mode = previous_mode == 0 ? 2 : previous_mode;
uint8_t drawn_mode = mode == 0 ? previous_mode : mode;
uint8_t fan_speed = this->cards.ac->getFanSpeed();
uint8_t temperature = this->cards.ac->getTemperature();
ESP_LOGV("CUD Display", "Mode: %d, Fan Speed: %d, Temperature: %d", mode, fan_speed, temperature);
ESP_LOGV("CUD Display", "Previous Mode: %d, Drawn Mode: %d", previous_mode, drawn_mode);
// Is the AC locked?
if (this->get_ac_lock())
{
// Draw the state picture set
// When the display is locked
// the state picture set we use is the locked state picture set
this->takeSerialMutex();
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_STATE, state ? LCD_DASHBOARD_PIC_AC_STATE_ON_LOCKED : LCD_DASHBOARD_PIC_AC_STATE_OFF_LOCKED);
this->sendStopBytes();
// Since the display is locked, when pressed, the state picture set should not change
this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_STATE, state ? LCD_DASHBOARD_PIC_AC_STATE_ON_LOCKED : LCD_DASHBOARD_PIC_AC_STATE_OFF_LOCKED);
this->sendStopBytes();
// Set Alpha of Locked Icon to 127
this->displayAdapter->printf("%s.aph=%d", LCD_DASHBOARD_ELEMENT_NAME_ICO_LOCK, 127);
this->sendStopBytes();
// Overlay the ac container
this->displayAdapter->printf("vis %s,1", LCD_DASHBOARD_ELEMENT_NAME_AC_PANEL_OVERLAY);
this->sendStopBytes();
// Hide the temperature adjustment buttons
this->displayAdapter->printf("vis %s,0", LCD_DASHBOARD_ELEMENT_NAME_AC_TEMP_UP_BUTTON);
this->sendStopBytes();
this->displayAdapter->printf("vis %s,0", LCD_DASHBOARD_ELEMENT_NAME_AC_TEMP_DOWN_BUTTON);
this->sendStopBytes();
// Draw the mode picture set
// If it is not locked
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_MODE_COOL, drawn_mode == 2 ? (LCD_DASHBOARD_PIC_AC_MODE_COOL_ACTIVE_LOCKED) : LCD_DASHBOARD_PIC_AC_MODE_COOL_INACTIVE);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_MODE_COOL, drawn_mode == 2 ? LCD_DASHBOARD_PIC_AC_MODE_COOL_ACTIVE_LOCKED : LCD_DASHBOARD_PIC_AC_MODE_COOL_INACTIVE);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_MODE_FAN, drawn_mode == 1 ? LCD_DASHBOARD_PIC_AC_MODE_FAN_ACTIVE_LOCKED : LCD_DASHBOARD_PIC_AC_MODE_FAN_INACTIVE);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_MODE_FAN, drawn_mode == 1 ? LCD_DASHBOARD_PIC_AC_MODE_FAN_ACTIVE_LOCKED : LCD_DASHBOARD_PIC_AC_MODE_FAN_INACTIVE);
this->sendStopBytes();
// Draw fan speed auto picture set
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_AUTO, fan_speed == 0 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_AUTO_ACTIVE_LOCKED : LCD_DASHBOARD_PIC_AC_FAN_SPEED_AUTO_INACTIVE);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_AUTO, fan_speed == 0 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_AUTO_ACTIVE_LOCKED : LCD_DASHBOARD_PIC_AC_FAN_SPEED_AUTO_INACTIVE);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_LOW, fan_speed == 1 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_LOW_ACTIVE_LOCKED : LCD_DASHBOARD_PIC_AC_FAN_SPEED_LOW_INACTIVE);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_LOW, fan_speed == 1 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_LOW_ACTIVE_LOCKED : LCD_DASHBOARD_PIC_AC_FAN_SPEED_LOW_INACTIVE);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_MEDIUM, fan_speed == 2 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_MEDIUM_ACTIVE_LOCKED : LCD_DASHBOARD_PIC_AC_FAN_SPEED_MEDIUM_INACTIVE);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_MEDIUM, fan_speed == 2 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_MEDIUM_ACTIVE_LOCKED : LCD_DASHBOARD_PIC_AC_FAN_SPEED_MEDIUM_INACTIVE);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_HIGH, fan_speed == 3 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_HIGH_ACTIVE_LOCKED : LCD_DASHBOARD_PIC_AC_FAN_SPEED_HIGH_INACTIVE);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_HIGH, fan_speed == 3 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_HIGH_ACTIVE_LOCKED : LCD_DASHBOARD_PIC_AC_FAN_SPEED_HIGH_INACTIVE);
this->sendStopBytes();
this->giveSerialMutex();
}
else
{
// When the display is not locked
// the state picture set we use is the unlocked state picture set
this->takeSerialMutex();
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_STATE, state ? LCD_DASHBOARD_PIC_AC_STATE_ON : LCD_DASHBOARD_PIC_AC_STATE_OFF);
this->sendStopBytes();
// When pressed, the state picture set should change
this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_STATE, state ? LCD_DASHBOARD_PIC_AC_STATE_ON_PRESSED : LCD_DASHBOARD_PIC_AC_STATE_OFF_PRESSED);
this->sendStopBytes();
// Set Alpha of Locked Icon to 0
this->displayAdapter->printf("%s.aph=%d", LCD_DASHBOARD_ELEMENT_NAME_ICO_LOCK, 0);
this->sendStopBytes();
// Hide the ac container overlay
this->displayAdapter->printf("vis %s,0", LCD_DASHBOARD_ELEMENT_NAME_AC_PANEL_OVERLAY);
this->sendStopBytes();
// Show the temperature adjustment buttons
this->displayAdapter->printf("vis %s,1", LCD_DASHBOARD_ELEMENT_NAME_AC_TEMP_UP_BUTTON);
this->sendStopBytes();
this->displayAdapter->printf("vis %s,1", LCD_DASHBOARD_ELEMENT_NAME_AC_TEMP_DOWN_BUTTON);
this->sendStopBytes();
// Draw the mode picture set
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_MODE_COOL, drawn_mode == 2 ? (LCD_DASHBOARD_PIC_AC_MODE_COOL_ACTIVE) : LCD_DASHBOARD_PIC_AC_MODE_COOL_INACTIVE);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_MODE_COOL, drawn_mode == 2 ? LCD_DASHBOARD_PIC_AC_MODE_COOL_ACTIVE_PRESS : LCD_DASHBOARD_PIC_AC_MODE_COOL_INACTIVE_PRESS);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_MODE_FAN, drawn_mode == 1 ? LCD_DASHBOARD_PIC_AC_MODE_FAN_ACTIVE : LCD_DASHBOARD_PIC_AC_MODE_FAN_INACTIVE);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_MODE_FAN, drawn_mode == 1 ? LCD_DASHBOARD_PIC_AC_MODE_FAN_ACTIVE_PRESS : LCD_DASHBOARD_PIC_AC_MODE_FAN_INACTIVE_PRESS);
this->sendStopBytes();
this->giveSerialMutex();
// Draw fan speed picture set
this->takeSerialMutex();
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_AUTO, fan_speed == 0 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_AUTO_ACTIVE : LCD_DASHBOARD_PIC_AC_FAN_SPEED_AUTO_INACTIVE);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_AUTO, fan_speed == 0 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_AUTO_ACTIVE_PRESS : LCD_DASHBOARD_PIC_AC_FAN_SPEED_AUTO_INACTIVE_PRESS);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_LOW, fan_speed == 1 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_LOW_ACTIVE : LCD_DASHBOARD_PIC_AC_FAN_SPEED_LOW_INACTIVE);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_LOW, fan_speed == 1 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_LOW_ACTIVE_PRESS : LCD_DASHBOARD_PIC_AC_FAN_SPEED_LOW_INACTIVE_PRESS);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_MEDIUM, fan_speed == 2 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_MEDIUM_ACTIVE : LCD_DASHBOARD_PIC_AC_FAN_SPEED_MEDIUM_INACTIVE);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_MEDIUM, fan_speed == 2 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_MEDIUM_ACTIVE_PRESS : LCD_DASHBOARD_PIC_AC_FAN_SPEED_MEDIUM_INACTIVE_PRESS);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_HIGH, fan_speed == 3 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_HIGH_ACTIVE : LCD_DASHBOARD_PIC_AC_FAN_SPEED_HIGH_INACTIVE);
this->sendStopBytes();
this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_HIGH, fan_speed == 3 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_HIGH_ACTIVE_PRESS : LCD_DASHBOARD_PIC_AC_FAN_SPEED_HIGH_INACTIVE_PRESS);
this->sendStopBytes();
this->giveSerialMutex();
}
// Draw the fan speed picture set
// Draw the temperature
this->takeSerialMutex();
this->displayAdapter->printf("%s.txt=\"%d\"", LCD_DASHBOARD_ELEMENT_NAME_AC_TEMPERATURE, temperature);
this->sendStopBytes();
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();
}
void CUDDisplay::refresh_display_socket()
{
this->takeSerialMutex();
this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_SOCKET_POWER, this->cards.outputCard->getState(this->conf->socket_contactor_pin) ? LCD_DASHBOARD_PIC_SOCKET_POWER_ON : LCD_DASHBOARD_PIC_SOCKET_POWER_OFF);
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()
{
// 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 (!get_ac_lock() && 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 (!get_ac_lock())
this->cards.ac->setMode(previous_mode);
}
}
void CUDDisplay::set_ac_lock(bool state)
{
ac_lock.setIntValue((bool)state);
this->refresh_display_ac();
}
bool CUDDisplay::get_ac_lock()
{
if (standalone)
{
return false;
}
return (bool)ac_lock.getIntValue();
}
uint8_t CUDDisplay::get_ac_temp_lower_bound()
{
if (standalone)
{
return AC_MIN_TEMP;
}
return ac_temp_lower_bound.getIntValue();
}
uint8_t CUDDisplay::get_ac_temp_upper_bound()
{
if (standalone)
{
return AC_MAX_TEMP;
}
return ac_temp_upper_bound.getIntValue();
}