From e8804864b84ea6a74401a1ea53abbf047b1b4f19 Mon Sep 17 00:00:00 2001 From: Siwat Sirichai Date: Sun, 31 Dec 2023 13:41:48 +0700 Subject: [PATCH] card rebinding support --- .../lib/ESPMegaPRO/AnalogCard.cpp | 2 +- .../lib/ESPMegaPRO/AnalogCard.hpp | 2 +- .../lib/ESPMegaPRO/AnalogIoT.cpp | 2 +- .../lib/ESPMegaPRO/AnalogIoT.hpp | 2 +- .../lib/ESPMegaPRO/DigitalOutputCard.cpp | 2 +- .../lib/ESPMegaPRO/DigitalOutputCard.hpp | 4 +- .../lib/ESPMegaPRO/DigitalOutputIoT.cpp | 2 +- .../lib/ESPMegaPRO/DigitalOutputIoT.hpp | 2 +- .../lib/ESPMegaPRO/ESPMegaDisplay.cpp | 8 +- .../lib/ESPMegaPRO/ESPMegaDisplay.hpp | 4 +- .../lib/ESPMegaPRO/ESPMegaIoT.cpp | 2 +- .../lib/ESPMegaPRO/ESPMegaIoT.hpp | 2 +- .../lib/ESPMegaPRO/InternalDisplay.cpp | 405 +++++++++++------- .../lib/ESPMegaPRO/InternalDisplay.hpp | 7 + 14 files changed, 270 insertions(+), 176 deletions(-) diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogCard.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogCard.cpp index 690de19..a2007b4 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogCard.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogCard.cpp @@ -132,7 +132,7 @@ uint8_t AnalogCard::registerDACChangeCallback(std::functionhandler_count++; } -void AnalogCard::deregisterDACChangeCallback(uint8_t handler) +void AnalogCard::unregisterDACChangeCallback(uint8_t handler) { this->dac_change_callbacks.erase(handler); } \ No newline at end of file diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogCard.hpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogCard.hpp index c6332de..c70c3eb 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogCard.hpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogCard.hpp @@ -27,7 +27,7 @@ class AnalogCard : public ExpansionCard { void setDACState(uint8_t pin, bool state); void setDACValue(uint8_t pin, uint16_t value); uint8_t registerDACChangeCallback(std::function callback); - void deregisterDACChangeCallback(uint8_t handler); + void unregisterDACChangeCallback(uint8_t handler); uint8_t getType(); private: uint8_t handler_count; diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogIoT.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogIoT.cpp index a66293c..2f014e0 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogIoT.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogIoT.cpp @@ -69,7 +69,7 @@ uint8_t AnalogIoT::registerADCConversionCallback(std::functionadc_conversion_callbacks[this->adc_conversion_callback_index] = callback; return this->adc_conversion_callback_index++; } -void AnalogIoT::deregisterADCConversionCallback(uint8_t handler) { +void AnalogIoT::unregisterADCConversionCallback(uint8_t handler) { this->adc_conversion_callbacks.erase(handler); } void AnalogIoT::setADCConversionInterval(uint8_t pin, uint16_t interval) { diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogIoT.hpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogIoT.hpp index 8633826..9c0c753 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogIoT.hpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogIoT.hpp @@ -26,7 +26,7 @@ class AnalogIoT : public IoTComponent { void setADCsPublishInterval(uint32_t interval); void setADCsPublishEnabled(bool enabled); uint8_t registerADCConversionCallback(std::function callback); - void deregisterADCConversionCallback(uint8_t handler); + void unregisterADCConversionCallback(uint8_t handler); void setADCConversionInterval(uint8_t pin, uint16_t interval); void setADCConversionEnabled(uint8_t pin, bool enabled); bool processADCSetConversionIntervalMessage(char *topic, char *payload, uint8_t topic_length); diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputCard.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputCard.cpp index 68daa41..fb3a5c2 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputCard.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputCard.cpp @@ -107,7 +107,7 @@ uint8_t DigitalOutputCard::registerChangeCallback(std::functioncallbacks_handler_index++; } -void DigitalOutputCard::deregisterChangeCallback(uint8_t handler) { +void DigitalOutputCard::unregisterChangeCallback(uint8_t handler) { this->change_callbacks.erase(handler); } diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputCard.hpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputCard.hpp index 072560f..f5ee591 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputCard.hpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputCard.hpp @@ -49,8 +49,8 @@ public: uint16_t getValue(uint8_t pin); // Register a callback function that will be called when the state of a pin changes uint8_t registerChangeCallback(std::function callback); - // Deregister the callback function - void deregisterChangeCallback(uint8_t handler); + // Unregister the callback function + void unregisterChangeCallback(uint8_t handler); // Load a new pin map void loadPinMap(uint8_t pinMap[16]); // Bind the fram object to the card diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputIoT.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputIoT.cpp index 452f32d..e7d9079 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputIoT.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputIoT.cpp @@ -166,7 +166,7 @@ void DigitalOutputIoT::registerChangeCallback(std::function callback); - void deregisterChangeCallback(); + void unregisterChangeCallback(); void publishReport(); void subscribe(); void loop(); diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaDisplay.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaDisplay.cpp index 97023f5..7c74428 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaDisplay.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaDisplay.cpp @@ -409,10 +409,10 @@ uint16_t ESPMegaDisplay::registerTouchCallback(std::function } /** - * @brief Deregisters a callback function for page change events. + * @brief Unregisters a callback function for page change events. * @param handle The handle of the callback function. */ -void ESPMegaDisplay::deregisterPageChangeCallback(uint16_t handle) +void ESPMegaDisplay::unregisterPageChangeCallback(uint16_t handle) { page_change_callbacks.erase(handle); } diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaDisplay.hpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaDisplay.hpp index 9735c60..0cff6d1 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaDisplay.hpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaDisplay.hpp @@ -21,9 +21,9 @@ class ESPMegaDisplay bool getStringToBuffer(const char* component, char* buffer, uint8_t buffer_size); uint32_t getNumber(const char* component); uint16_t registerTouchCallback(std::function callback); - void deregisterTouchCallback(uint16_t handle); + void unregisterTouchCallback(uint16_t handle); uint16_t registerPageChangeCallback(std::function callback); - void deregisterPageChangeCallback(uint16_t handle); + void unregisterPageChangeCallback(uint16_t handle); protected: uint8_t currentPage; diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaIoT.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaIoT.cpp index 21107d8..0655287 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaIoT.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaIoT.cpp @@ -127,7 +127,7 @@ void ESPMegaIoT::registerCard(uint8_t card_id) return; } } -void ESPMegaIoT::deregisterCard(uint8_t card_id) +void ESPMegaIoT::unregisterCard(uint8_t card_id) { // Check if the card is registered if (components[card_id] == NULL) diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaIoT.hpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaIoT.hpp index 294e8c1..b624057 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaIoT.hpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaIoT.hpp @@ -53,7 +53,7 @@ public: void intr_begin(ExpansionCard *cards[]); void loop(); void registerCard(uint8_t card_id); - void deregisterCard(uint8_t card_id); + void unregisterCard(uint8_t card_id); void publishCard(uint8_t card_id); // Publish topic appended with base topic void publishRelative(char *topic, char *payload); diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/InternalDisplay.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/InternalDisplay.cpp index faf3e11..50df5c5 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/InternalDisplay.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/InternalDisplay.cpp @@ -1,7 +1,7 @@ #include - -void InternalDisplay::begin(ESPMegaIoT *iot, std::function getRtcTime) { +void InternalDisplay::begin(ESPMegaIoT *iot, std::function getRtcTime) +{ this->iot = iot; this->getRtcTime = getRtcTime; this->mqttConfig = this->iot->getMqttConfig(); @@ -11,10 +11,6 @@ void InternalDisplay::begin(ESPMegaIoT *iot, std::function getRtcTi this->registerPageChangeCallback(bindedPageChangeCallback); auto bindedTouchCallback = std::bind(&InternalDisplay::handleTouch, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); this->registerTouchCallback(bindedTouchCallback); - auto bindedInputStateChangeCallback = std::bind(&InternalDisplay::handleInputStateChange, this, std::placeholders::_1, std::placeholders::_2); - auto bindedPwmStateChangeCallback = std::bind(&InternalDisplay::handlePwmStateChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); - this->inputCard->registerCallback(bindedInputStateChangeCallback); - this->outputCard->registerChangeCallback(bindedPwmStateChangeCallback); // Initialize the display this->displayAdapter->begin(115200); this->displayAdapter->setTimeout(100); @@ -24,110 +20,124 @@ void InternalDisplay::begin(ESPMegaIoT *iot, std::function getRtcTi this->jumpToPage(1); } - -void InternalDisplay::loop() { +void InternalDisplay::loop() +{ // Keep reading the Serial Adapter this->recieveSerialCommand(); // Refresh the top bar every 5 seconds static uint32_t lastTopBarRefresh; - if (millis() - lastTopBarRefresh > INTERNAL_DISPLAY_TOP_BAR_REFRESH_INTERVAL) { + if (millis() - lastTopBarRefresh > INTERNAL_DISPLAY_TOP_BAR_REFRESH_INTERVAL) + { this->updateStatusIcons(this->iot->networkConnected(), this->iot->mqttConnected()); lastTopBarRefresh = millis(); } // Refresh the clock every 10 seconds static uint32_t lastClockRefresh; - if (millis() - lastClockRefresh > INTERNAL_DISPLAY_CLOCK_REFRESH_INTERVAL) { + if (millis() - lastClockRefresh > INTERNAL_DISPLAY_CLOCK_REFRESH_INTERVAL) + { this->updateClock(); lastClockRefresh = millis(); } } - - -void InternalDisplay::handleInputStateChange(uint8_t pin, bool state) { +void InternalDisplay::handleInputStateChange(uint8_t pin, bool state) +{ // If the input card is binded to the display and the current page is the input page // then update the respective input component - if (this->inputCard!=nullptr || this->currentPage != INTERNAL_DISPLAY_INPUT_PAGE) return; + if (this->inputCard != nullptr || this->currentPage != INTERNAL_DISPLAY_INPUT_PAGE) + return; // Update the input state this->setInputMarker(pin, state); } -void InternalDisplay::handlePwmStateChange(uint8_t pin, bool state, uint16_t value) { +void InternalDisplay::handlePwmStateChange(uint8_t pin, bool state, uint16_t value) +{ // If the output card is binded to the display and the current page is the output page // then update the respective output component - if (this->outputCard!=nullptr || this->currentPage != INTERNAL_DISPLAY_OUTPUT_PAGE) return; + if (this->outputCard != nullptr || this->currentPage != INTERNAL_DISPLAY_OUTPUT_PAGE) + return; // Update the output state this->setOutputBar(pin, value); this->setOutputStateColor(pin, state); // Refresh the PWM Adjustment page if the current page is the PWM Adjustment page and the pin is the same - if (this->currentPage == INTERNAL_DISPLAY_PWM_ADJUSTMENT_PAGE && this->pmwAdjustmentPin == pin) { + if (this->currentPage == INTERNAL_DISPLAY_PWM_ADJUSTMENT_PAGE && this->pmwAdjustmentPin == pin) + { this->refreshPWMAdjustment(); } } -void InternalDisplay::handlePageChange(uint8_t page) { +void InternalDisplay::handlePageChange(uint8_t page) +{ // Refresh the page this->refreshPage(page); } -void InternalDisplay::saveNetworkConfig() { +void InternalDisplay::saveNetworkConfig() +{ // TODO: implementation } -void InternalDisplay::saveMQTTConfig() { +void InternalDisplay::saveMQTTConfig() +{ // TODO: implementation } -void InternalDisplay::updateStatusIcons(bool networkStatus, bool mqttStatus) { +void InternalDisplay::updateStatusIcons(bool networkStatus, bool mqttStatus) +{ this->setNumber("server.pic", mqttStatus ? PIC_MQTT_CONNECTED : PIC_MQTT_DISCONNECTED); this->setNumber("lan.pic", networkStatus ? PIC_LAN_CONNECTED : PIC_LAN_DISCONNECTED); } -void InternalDisplay::updateClock() { +void InternalDisplay::updateClock() +{ rtctime_t time = this->getRtcTime(); - this->displayAdapter->printf("time.txt=\"%02d:%02d %s\"", time.hours%12, time.minutes, time.hours/12 ? "PM" : "AM"); + this->displayAdapter->printf("time.txt=\"%02d:%02d %s\"", time.hours % 12, time.minutes, time.hours / 12 ? "PM" : "AM"); this->sendStopBytes(); - } -void InternalDisplay::refreshPage() { +void InternalDisplay::refreshPage() +{ this->refreshPage(this->currentPage); } -void InternalDisplay::refreshPage(uint8_t page) { - switch (page) { - case INTERNAL_DISPLAY_DASHBOARD_PAGE: - this->refreshDashboard(); - break; - case INTERNAL_DISPLAY_INPUT_PAGE: - this->refreshInput(); - break; - case INTERNAL_DISPLAY_OUTPUT_PAGE: - this->refreshOutput(); - break; - case INTERNAL_DISPLAY_AC_PAGE: - if (this->climateCard == nullptr) { - this->jumpToPage(INTERNAL_DISPLAY_CLIMATE_NULL_PTR_PAGE); - break; - } - this->refreshAC(); - break; - case INTERNAL_DISPLAY_PWM_ADJUSTMENT_PAGE: - this->refreshPWMAdjustment(); - break; - case INTERNAL_DISPLAY_NETWORK_CONFIG_PAGE: - this->refreshNetworkConfig(); - break; - case INTERNAL_DISPLAY_MQTT_CONFIG_PAGE: - this->refreshMQTTConfig(); - break; - default: +void InternalDisplay::refreshPage(uint8_t page) +{ + switch (page) + { + case INTERNAL_DISPLAY_DASHBOARD_PAGE: + this->refreshDashboard(); + break; + case INTERNAL_DISPLAY_INPUT_PAGE: + this->refreshInput(); + break; + case INTERNAL_DISPLAY_OUTPUT_PAGE: + this->refreshOutput(); + break; + case INTERNAL_DISPLAY_AC_PAGE: + if (this->climateCard == nullptr) + { + this->jumpToPage(INTERNAL_DISPLAY_CLIMATE_NULL_PTR_PAGE); break; + } + this->refreshAC(); + break; + case INTERNAL_DISPLAY_PWM_ADJUSTMENT_PAGE: + this->refreshPWMAdjustment(); + break; + case INTERNAL_DISPLAY_NETWORK_CONFIG_PAGE: + this->refreshNetworkConfig(); + break; + case INTERNAL_DISPLAY_MQTT_CONFIG_PAGE: + this->refreshMQTTConfig(); + break; + default: + break; } } -void InternalDisplay::refreshDashboard() { +void InternalDisplay::refreshDashboard() +{ // The dashboard have the following components: // 1. Hostname // 2. IP Address @@ -147,20 +157,25 @@ void InternalDisplay::refreshDashboard() { this->setString("status_txt.txt", this->iot->mqttConnected() ? MSG_MQTT_CONNECTED : MSG_MQTT_DISCONNECTED); } -void InternalDisplay::refreshInput() { - for (uint8_t i=0; i<16; i++) { +void InternalDisplay::refreshInput() +{ + for (uint8_t i = 0; i < 16; i++) + { this->setInputMarker(i, this->inputCard->digitalRead(i, false)); } } -void InternalDisplay::refreshOutput() { - for (uint8_t i=0; i<16; i++) { +void InternalDisplay::refreshOutput() +{ + for (uint8_t i = 0; i < 16; i++) + { this->setOutputBar(i, this->outputCard->getValue(i)); this->setOutputStateColor(i, this->outputCard->getState(i)); } } -void InternalDisplay::refreshAC() { +void InternalDisplay::refreshAC() +{ this->displayAdapter->print("temp.txt=\""); this->displayAdapter->print(this->climateCard->getTemperature()); this->displayAdapter->print("C\""); @@ -186,7 +201,8 @@ void InternalDisplay::refreshAC() { this->displayAdapter->print("mode_cool.pic="); this->displayAdapter->print(this->climateCard->getMode() == AC_MODE_COOL ? PIC_AC_MODE_COOL_ACTIVE : PIC_AC_MODE_COOL_INACTIVE); this->sendStopBytes(); - if (this->climateCard->getSensorType() == AC_SENSOR_TYPE_DHT22) { + if (this->climateCard->getSensorType() == AC_SENSOR_TYPE_DHT22) + { this->displayAdapter->print("roomtemp.txt=\""); this->displayAdapter->print(this->climateCard->getRoomTemperature()); this->displayAdapter->print("C\""); @@ -196,46 +212,51 @@ void InternalDisplay::refreshAC() { this->displayAdapter->print("%\""); this->sendStopBytes(); } - else if(this->climateCard->getSensorType() == AC_SENSOR_TYPE_DS18B20) { + else if (this->climateCard->getSensorType() == AC_SENSOR_TYPE_DS18B20) + { this->displayAdapter->print("roomtemp.txt=\""); this->displayAdapter->print(this->climateCard->getRoomTemperature()); this->displayAdapter->print("C\""); this->sendStopBytes(); this->setString("roomhumid.txt", "N/A"); } - else { + else + { this->setString("roomtemp.txt", "N/A"); this->setString("roomhumid.txt", "N/A"); } } -void InternalDisplay::setOutputBar(uint8_t pin, uint16_t value) { +void InternalDisplay::setOutputBar(uint8_t pin, uint16_t value) +{ // Write the value to the output bar this->displayAdapter->print("j"); this->displayAdapter->print(pin); this->displayAdapter->print(".val="); - this->displayAdapter->print((int)(value*100/4095)); + this->displayAdapter->print((int)(value * 100 / 4095)); this->sendStopBytes(); } -void InternalDisplay::setOutputStateColor(uint8_t pin, bool state) { +void InternalDisplay::setOutputStateColor(uint8_t pin, bool state) +{ this->displayAdapter->print("j"); this->displayAdapter->print(pin); this->displayAdapter->print(".ppic="); this->displayAdapter->print(state ? PIC_PWM_BAR_ON : PIC_PWM_BAR_OFF); this->sendStopBytes(); - } -void InternalDisplay::setInputMarker(uint8_t pin, bool state) { +void InternalDisplay::setInputMarker(uint8_t pin, bool state) +{ this->displayAdapter->print("I"); this->displayAdapter->print(pin); this->displayAdapter->print(".val="); - this->displayAdapter->print(state ? 0:1); + this->displayAdapter->print(state ? 0 : 1); this->sendStopBytes(); } -InternalDisplay::InternalDisplay(HardwareSerial *displayAdapter) : ESPMegaDisplay(displayAdapter) { +InternalDisplay::InternalDisplay(HardwareSerial *displayAdapter) : ESPMegaDisplay(displayAdapter) +{ this->currentPage = INTERNAL_DISPLAY_DASHBOARD_PAGE; this->iot = nullptr; this->inputCard = nullptr; @@ -244,24 +265,73 @@ InternalDisplay::InternalDisplay(HardwareSerial *displayAdapter) : ESPMegaDispla this->pmwAdjustmentPin = 0; } -void InternalDisplay::bindInputCard(DigitalInputCard *inputCard) { +void InternalDisplay::bindInputCard(DigitalInputCard *inputCard) +{ + // Check if the input card is already binded + // If it is, then unbind it first + if (this->inputCard != nullptr) + this->unbindInputCard(); this->inputCard = inputCard; + auto bindedInputStateChangeCallback = + std::bind(&InternalDisplay::handleInputStateChange, this, + std::placeholders::_1, std::placeholders::_2); + this->bindedInputCardCallbackHandler = + this->inputCard->registerCallback(bindedInputStateChangeCallback); } -void InternalDisplay::bindOutputCard(DigitalOutputCard *outputCard) { +void InternalDisplay::unbindInputCard() +{ + if (this->inputCard == nullptr) + return; + this->inputCard->unregisterCallback(this->bindedInputCardCallbackHandler); + this->inputCard = nullptr; +} + +void InternalDisplay::bindOutputCard(DigitalOutputCard *outputCard) +{ + // Check if the output card is already binded + // If it is, then unbind it first + if (this->outputCard != nullptr) + this->unbindOutputCard(); this->outputCard = outputCard; + auto bindedPwmStateChangeCallback = std::bind(&InternalDisplay::handlePwmStateChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); + this->bindedOutputCardCallbackHandler = + this->outputCard->registerChangeCallback(bindedPwmStateChangeCallback); +} + +void InternalDisplay::unbindOutputCard() +{ + if (this->outputCard == nullptr) + return; + this->outputCard->unregisterChangeCallback(this->bindedOutputCardCallbackHandler); + this->outputCard = nullptr; } // This assume that your ClimeateCard has the mode and fan speed names in the following order: // mode: [off, fan_only, cool] // fan_speed: [auto, low, medium, high] -void InternalDisplay::bindClimateCard(ClimateCard *climateCard) { +void InternalDisplay::bindClimateCard(ClimateCard *climateCard) +{ + // Check if the climate card is already binded + // If it is, then unbind it first + if (this->climateCard != nullptr) + this->unbindClimateCard(); this->climateCard = climateCard; auto bindedACStateChangeCallback = std::bind(&InternalDisplay::handleACStateChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); - this->climateCard->registerChangeCallback(bindedACStateChangeCallback); + this->bindedClimateCardCallbackHandler = + this->climateCard->registerChangeCallback(bindedACStateChangeCallback); } -void InternalDisplay::refreshPWMAdjustment() { +void InternalDisplay::unbindClimateCard() +{ + if (this->climateCard == nullptr) + return; + this->climateCard->unregisterChangeCallback(this->bindedClimateCardCallbackHandler); + this->climateCard = nullptr; +} + +void InternalDisplay::refreshPWMAdjustment() +{ // The PWM Adjustment page have the following components: // pwm_value -> a slider to adjust the PWM value // pwm_state -> a button to toggle the PWM state @@ -275,7 +345,8 @@ void InternalDisplay::refreshPWMAdjustment() { this->refreshPWMAdjustmentState(); } -void InternalDisplay::refreshPWMAdjustmentId() { +void InternalDisplay::refreshPWMAdjustmentId() +{ // Send the PWM pin this->displayAdapter->print("pwm_id.txt=\"P"); this->displayAdapter->print(pmwAdjustmentPin); @@ -283,14 +354,16 @@ void InternalDisplay::refreshPWMAdjustmentId() { this->sendStopBytes(); } -void InternalDisplay::refreshPWMAdjustmentSlider() { +void InternalDisplay::refreshPWMAdjustmentSlider() +{ // Send the PWM value this->displayAdapter->print("pwm_value.val="); this->displayAdapter->print(this->outputCard->getValue(this->pmwAdjustmentPin)); this->sendStopBytes(); } -void InternalDisplay::refreshPWMAdjustmentState() { +void InternalDisplay::refreshPWMAdjustmentState() +{ // Send the PWM state this->displayAdapter->print("pwm_state.txt=\""); this->displayAdapter->print(this->outputCard->getState(this->pmwAdjustmentPin) ? MSG_PWM_ADJUSTMENT_STATE_ON : MSG_PWM_ADJUSTMENT_STATE_OFF); @@ -298,21 +371,24 @@ void InternalDisplay::refreshPWMAdjustmentState() { this->sendStopBytes(); } -void InternalDisplay::handleTouch(uint8_t page, uint8_t component, uint8_t type) { +void InternalDisplay::handleTouch(uint8_t page, uint8_t component, uint8_t type) +{ // Switch based on the page - switch (page) { - case INTERNAL_DISPLAY_AC_PAGE: - this->handleACTouch(type, component); - break; - case INTERNAL_DISPLAY_PWM_ADJUSTMENT_PAGE: - this->handlePWMAdjustmentTouch(type, component); - break; - default: - break; + switch (page) + { + case INTERNAL_DISPLAY_AC_PAGE: + this->handleACTouch(type, component); + break; + case INTERNAL_DISPLAY_PWM_ADJUSTMENT_PAGE: + this->handlePWMAdjustmentTouch(type, component); + break; + default: + break; } } -void InternalDisplay::handleACTouch(uint8_t type, uint8_t component) { +void InternalDisplay::handleACTouch(uint8_t type, uint8_t component) +{ // b1 [component 18] -> inclement AC temperature by 1 // b0 [component 17] -> declement AC temperature by 1 // fan_auto [component 4] -> set the fan speed to auto @@ -325,88 +401,95 @@ void InternalDisplay::handleACTouch(uint8_t type, uint8_t component) { // For b0 and b1, if the type is not release then return // For other components, if the type is not press then return - if ((component == 17 || component == 18) && type != TOUCH_TYPE_RELEASE) return; - if ((component != 17 && component != 18) && type != TOUCH_TYPE_PRESS) return; + if ((component == 17 || component == 18) && type != TOUCH_TYPE_RELEASE) + return; + if ((component != 17 && component != 18) && type != TOUCH_TYPE_PRESS) + return; // Switch based on the component - switch (component) { - case 17: - // Decrement the temperature - this->climateCard->setTemperature(this->climateCard->getTemperature() - 1); - break; - case 18: - // Increment the temperature - this->climateCard->setTemperature(this->climateCard->getTemperature() + 1); - break; - case 4: - // Set the fan speed to auto - this->climateCard->setFanSpeed(AC_FAN_SPEED_AUTO); - break; - case 5: - // Set the fan speed to low - this->climateCard->setFanSpeed(AC_FAN_SPEED_LOW); - break; - case 6: - // Set the fan speed to medium - this->climateCard->setFanSpeed(AC_FAN_SPEED_MEDIUM); - break; - case 7: - // Set the fan speed to high - this->climateCard->setFanSpeed(AC_FAN_SPEED_HIGH); - break; - case 10: - // Set the mode to off - this->climateCard->setMode(AC_MODE_OFF); - break; - case 9: - // Set the mode to fan only - this->climateCard->setMode(AC_MODE_FAN_ONLY); - break; - case 8: - // Set the mode to cool - this->climateCard->setMode(AC_MODE_COOL); - break; - default: - break; + switch (component) + { + case 17: + // Decrement the temperature + this->climateCard->setTemperature(this->climateCard->getTemperature() - 1); + break; + case 18: + // Increment the temperature + this->climateCard->setTemperature(this->climateCard->getTemperature() + 1); + break; + case 4: + // Set the fan speed to auto + this->climateCard->setFanSpeed(AC_FAN_SPEED_AUTO); + break; + case 5: + // Set the fan speed to low + this->climateCard->setFanSpeed(AC_FAN_SPEED_LOW); + break; + case 6: + // Set the fan speed to medium + this->climateCard->setFanSpeed(AC_FAN_SPEED_MEDIUM); + break; + case 7: + // Set the fan speed to high + this->climateCard->setFanSpeed(AC_FAN_SPEED_HIGH); + break; + case 10: + // Set the mode to off + this->climateCard->setMode(AC_MODE_OFF); + break; + case 9: + // Set the mode to fan only + this->climateCard->setMode(AC_MODE_FAN_ONLY); + break; + case 8: + // Set the mode to cool + this->climateCard->setMode(AC_MODE_COOL); + break; + default: + break; } } -void InternalDisplay::handlePWMAdjustmentTouch(uint8_t type, uint8_t component) { +void InternalDisplay::handlePWMAdjustmentTouch(uint8_t type, uint8_t component) +{ // b0 [component 5] -> decrement the PWM id if its greater than 0, else set it to 15 // b1 [component 6] -> increment the PWM id if its less than 15, else set it to 0 // pwm_state [component 4] -> toggle the PWM state // pwm_value [component 1] -> set the PWM value based on the slider value // If the type is not release then return - if (type != TOUCH_TYPE_RELEASE) return; + if (type != TOUCH_TYPE_RELEASE) + return; uint16_t val = 0; // switch based on the component - switch (component) { - case 5: - // Decrement the PWM id - this->pmwAdjustmentPin = this->pmwAdjustmentPin > 0 ? this->pmwAdjustmentPin - 1 : 15; - this->refreshPWMAdjustment(); - break; - case 6: - // Increment the PWM id - this->pmwAdjustmentPin = this->pmwAdjustmentPin < 15 ? this->pmwAdjustmentPin + 1 : 0; - this->refreshPWMAdjustment(); - break; - case 4: - // Toggle the PWM state - this->outputCard->setState(this->pmwAdjustmentPin, !this->outputCard->getState(this->pmwAdjustmentPin)); - this->refreshPWMAdjustmentState(); - break; - case 1: - // Set the PWM value - val = (uint16_t)this -> getNumber("pwm_value.val"); - this->outputCard->setValue(this->pmwAdjustmentPin, val); - break; - default: - break; + switch (component) + { + case 5: + // Decrement the PWM id + this->pmwAdjustmentPin = this->pmwAdjustmentPin > 0 ? this->pmwAdjustmentPin - 1 : 15; + this->refreshPWMAdjustment(); + break; + case 6: + // Increment the PWM id + this->pmwAdjustmentPin = this->pmwAdjustmentPin < 15 ? this->pmwAdjustmentPin + 1 : 0; + this->refreshPWMAdjustment(); + break; + case 4: + // Toggle the PWM state + this->outputCard->setState(this->pmwAdjustmentPin, !this->outputCard->getState(this->pmwAdjustmentPin)); + this->refreshPWMAdjustmentState(); + break; + case 1: + // Set the PWM value + val = (uint16_t)this->getNumber("pwm_value.val"); + this->outputCard->setValue(this->pmwAdjustmentPin, val); + break; + default: + break; } } -void InternalDisplay::refreshNetworkConfig() { +void InternalDisplay::refreshNetworkConfig() +{ // The network config page have the following components: // ip_set -> a text input to set the ip address // netmask_set -> a text input to set the netmask @@ -441,7 +524,8 @@ void InternalDisplay::refreshNetworkConfig() { this->sendStopBytes(); } -void InternalDisplay::refreshMQTTConfig() { +void InternalDisplay::refreshMQTTConfig() +{ // The MQTT config page have the following components: // mqttsv_set -> a text input to set the mqtt server // port_set -> a text input to set the mqtt port @@ -480,7 +564,8 @@ void InternalDisplay::refreshMQTTConfig() { this->sendStopBytes(); } -void InternalDisplay::sendIpToDisplay(IPAddress ip) { +void InternalDisplay::sendIpToDisplay(IPAddress ip) +{ // Send the ip address this->displayAdapter->print(ip[0]); this->displayAdapter->print("."); @@ -491,11 +576,13 @@ void InternalDisplay::sendIpToDisplay(IPAddress ip) { this->displayAdapter->print(ip[3]); } -void InternalDisplay::handleACStateChange(uint8_t mode, uint8_t fan_speed, uint8_t temperature) { +void InternalDisplay::handleACStateChange(uint8_t mode, uint8_t fan_speed, uint8_t temperature) +{ // If the climate card is binded to the display and the current page is the AC page // then update the respective AC component Serial.println("AC state changed"); - if (this->climateCard==nullptr || this->currentPage != INTERNAL_DISPLAY_AC_PAGE) return; + if (this->climateCard == nullptr || this->currentPage != INTERNAL_DISPLAY_AC_PAGE) + return; this->sendStopBytes(); // Update the AC state this->refreshAC(); diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/InternalDisplay.hpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/InternalDisplay.hpp index 8b3b09d..aa65910 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/InternalDisplay.hpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/InternalDisplay.hpp @@ -73,8 +73,15 @@ class InternalDisplay : public ESPMegaDisplay { void bindInputCard(DigitalInputCard *inputCard); void bindOutputCard(DigitalOutputCard *outputCard); void bindClimateCard(ClimateCard *climateCard); + void unbindInputCard(); + void unbindOutputCard(); + void unbindClimateCard(); private: + uint8_t bindedInputCardCallbackHandler; + uint8_t bindedOutputCardCallbackHandler; + uint8_t bindedClimateCardCallbackHandler; + uint8_t bindedClimateCardSensorCallbackHandler; DigitalInputCard *inputCard; DigitalOutputCard *outputCard; ClimateCard *climateCard;