diff --git a/Template Project/lib/ESPMegaPRO/ESPMegaDisplay.cpp b/Template Project/lib/ESPMegaPRO/ESPMegaDisplay.cpp index 2fdf2a1..d7f4f0f 100644 --- a/Template Project/lib/ESPMegaPRO/ESPMegaDisplay.cpp +++ b/Template Project/lib/ESPMegaPRO/ESPMegaDisplay.cpp @@ -1,5 +1,10 @@ #include +/** + * @brief Receives and processes serial commands from the display adapter. + * @param process Flag indicating whether to process the received commands. + * @return True if data is received, false otherwise. + */ bool ESPMegaDisplay::recieveSerialCommand(bool process){ bool dataRecieved = false; // Read the serial buffer if available @@ -16,10 +21,17 @@ bool ESPMegaDisplay::recieveSerialCommand(bool process){ return dataRecieved; } +/** + * @brief Receives and processes serial commands from the display adapter. + * @return True if data is received, false otherwise. + */ bool ESPMegaDisplay::recieveSerialCommand(){ return recieveSerialCommand(true); } +/** + * @brief Processes the received serial command. + */ void ESPMegaDisplay::processSerialCommand(){ // Check if the rx buffer ended with stop bytes (0xFF 0xFF 0xFF) if(!payloadIsValid()) return; @@ -38,6 +50,9 @@ void ESPMegaDisplay::processSerialCommand(){ } } +/** + * @brief Processes the touch event payload. + */ void ESPMegaDisplay::processTouchPayload() { if (rx_buffer_index != 4) return; // The second byte of the payload is the page number @@ -49,6 +64,9 @@ void ESPMegaDisplay::processTouchPayload() { // 0x01 is press, 0x00 is release } +/** + * @brief Processes the page report event payload. + */ void ESPMegaDisplay::processPageReportPayload() { // The second byte of the payload is the page number this->currentPage = rx_buffer[1]; @@ -58,32 +76,39 @@ void ESPMegaDisplay::processPageReportPayload() { rx_buffer_index = 0; } +/** + * @brief Sends stop bytes to the display adapter. + */ void ESPMegaDisplay::sendStopBytes() { displayAdapter->write(0xFF); displayAdapter->write(0xFF); displayAdapter->write(0xFF); } +/** + * @brief Sends a command to the display adapter. + * @param command The command to send. + */ void ESPMegaDisplay::sendCommand(char* command) { displayAdapter->print(command); sendStopBytes(); } -void ESPMegaDisplay::refreshPage() { - if(this->currentPage==0){ - refreshInputPage(); - } - else if(this->currentPage==1){ - refreshOutputPage(); - } -} - +/** + * @brief Jumps to the specified page on the display. + * @param page The page number to jump to. + */ void ESPMegaDisplay::jumpToPage(int page) { this->displayAdapter->print("page "); this->displayAdapter->print(page); sendStopBytes(); } +/** + * @brief Sets the value of a number component on the display. + * @param component The component name. + * @param value The value to set. + */ void ESPMegaDisplay::setNumber(char* component, int value) { this->displayAdapter->print(component); this->displayAdapter->print("="); @@ -91,6 +116,11 @@ void ESPMegaDisplay::setNumber(char* component, int value) { sendStopBytes(); } +/** + * @brief Sets the value of a string component on the display. + * @param component The component name. + * @param value The value to set. + */ void ESPMegaDisplay::setString(char* component, char* value) { this->displayAdapter->print(component); this->displayAdapter->print("=\""); @@ -99,18 +129,91 @@ void ESPMegaDisplay::setString(char* component, char* value) { sendStopBytes(); } -int ESPMegaDisplay::getNumber(char* component) { +/** + * @brief Gets the value of a number component from the display. + * @param component The component name. + * @return The value of the number component. + */ +uint32_t ESPMegaDisplay::getNumber(char* component) { uint32_t start = millis(); // Send the get command this->displayAdapter->print("get "); this->displayAdapter->print(component); sendStopBytes(); // Wait for the response - if(!waitForValidPayload(FETCH_TIMEOUT)) return 0; + if(!waitForValidPayload(DISPLAY_FETCH_TIMEOUT)) return 0; // The rx buffer is valid - + // The expected payload is type 0x71 + if(rx_buffer[0]!=0x71) return 0; + // The 2nd to 5th byte of the payload is the value + // It's a 4 byte 32-bit value in little endian order. + // Convert the 4 bytes to a 32-bit value + uint32_t value = 0; + value |= rx_buffer[1]; + value |= rx_buffer[2]<<8; + value |= rx_buffer[3]<<16; + value |= rx_buffer[4]<<24; + return value; } +/** + * @brief Gets the value of a string component from the display. + * @param component The component name. + * @return The value of the string component. + * @note The returned char array must be freed after use. + */ +char* ESPMegaDisplay::getString(char* component) { + uint32_t start = millis(); + // Send the get command + this->displayAdapter->print("get "); + this->displayAdapter->print(component); + sendStopBytes(); + // Wait for the response + if(!waitForValidPayload(DISPLAY_FETCH_TIMEOUT)) return ""; + // The rx buffer is valid + // The expected payload is type 0x70 + if(rx_buffer[0]!=0x70) return ""; + // The 2nd bytes onwards before the stop bytes is the string + // The length of the string is the length of the payload minus 4 + uint8_t length = rx_buffer_index-4; + // First we malloc a char array with the length of the string + char* value = (char*)malloc(length+1); + // Copy the string from the rx buffer to the char array + memcpy(value, rx_buffer+1, length); + // Add the null terminator + value[length] = '\0'; + // Return the char array + return value; +} + +bool ESPMegaDisplay::getStringToBuffer(char* component, char* buffer, uint8_t buffer_size) { + uint32_t start = millis(); + // Send the get command + this->displayAdapter->print("get "); + this->displayAdapter->print(component); + sendStopBytes(); + // Wait for the response + if(!waitForValidPayload(DISPLAY_FETCH_TIMEOUT)) return false; + // The rx buffer is valid + // The expected payload is type 0x70 + if(rx_buffer[0]!=0x70) return false; + // The 2nd bytes onwards before the stop bytes is the string + // The length of the string is the length of the payload minus 4 + uint8_t length = rx_buffer_index-4; + // Check if the buffer is large enough to hold the string + if(length>buffer_size) return false; + // Copy the string from the rx buffer to the char array + memcpy(buffer, rx_buffer+1, length); + // Add the null terminator + buffer[length] = '\0'; + return true; +} + +/** + * @brief Waits for a valid payload from the display adapter. + * @param timeout The timeout value in milliseconds. + * @return True if a valid payload is received, false otherwise. + */ bool ESPMegaDisplay::waitForValidPayload(uint32_t timeout) { uint32_t start = millis(); // If the payload is not valid, keep reading the serial buffer until timeout @@ -123,6 +226,10 @@ bool ESPMegaDisplay::waitForValidPayload(uint32_t timeout) { return true; } +/** + * @brief Checks if the received payload is valid. + * @return True if the payload is valid, false otherwise. + */ bool ESPMegaDisplay::payloadIsValid() { // Check if the rx buffer ended with stop bytes (0xFF 0xFF 0xFF) if(rx_buffer_index<3) return false; @@ -130,4 +237,112 @@ bool ESPMegaDisplay::payloadIsValid() { if(rx_buffer[rx_buffer_index-2]!=0xFF) return false; if(rx_buffer[rx_buffer_index-3]!=0xFF) return false; return true; +} + +/** + * @brief Sets the brightness of the display. + * @param value The brightness value. + */ +void ESPMegaDisplay::setBrightness(int value) { + this->displayAdapter->print("dim="); + this->displayAdapter->print(value); + sendStopBytes(); +} + +/** + * @brief Sets the volume of the display. + * @param value The volume value. + */ +void ESPMegaDisplay::setVolume(int value) { + this->displayAdapter->print("vol="); + this->displayAdapter->print(value); + sendStopBytes(); +} + +/** + * @brief Restarts the display. + */ +void ESPMegaDisplay::reset() { + // First we send a stop bytes to clear the serial buffer + // This ensures that the display is ready to receive the reset command + sendStopBytes(); + this->displayAdapter->print("rest"); + sendStopBytes(); +} + +/** + * @brief Registers a callback function that will be called when a push event is received. + * @param callback The callback function. + */ +void ESPMegaDisplay::registerPushCallback(std::function callback) { + this->pushCallback = callback; +} + +/** + * @brief Registers a callback function that will be called when a pop event is received. + * @param callback The callback function. + */ +void ESPMegaDisplay::registerPopCallback(std::function callback) { + this->popCallback = callback; +} + +/** + * @brief Registers a callback function that will be called when a page change event is received. + * @param callback The callback function. + */ +void ESPMegaDisplay::registerPageChangeCallback(std::function callback) { + this->pageChangeCallback = callback; +} + +/** + * @brief Unregisters the push callback function. + */ +void ESPMegaDisplay::unregisterPushCallback() { + this->pushCallback = NULL; +} + +/** + * @brief Unregisters the pop callback function. + */ +void ESPMegaDisplay::unregisterPopCallback() { + this->popCallback = NULL; +} + +/** + * @brief Unregisters the page change callback function. + */ +void ESPMegaDisplay::unregisterPageChangeCallback() { + this->pageChangeCallback = NULL; +} + +/** + * @brief Constructor for the ESPMegaDisplay class. + * @param displayAdapter The serial adapter connected to the display. + */ +ESPMegaDisplay::ESPMegaDisplay(HardwareSerial *displayAdapter) { + this->displayAdapter = displayAdapter; + this->currentPage = 0; + this->rx_buffer_index = 0; + this->pushCallback = NULL; + this->popCallback = NULL; + this->pageChangeCallback = NULL; +} + +/** + * @brief Initializes the display. + */ +void ESPMegaDisplay::begin() { + this->displayAdapter->begin(115200); + this->displayAdapter->setTimeout(100); + this->displayAdapter->flush(); + this->reset(); +} + +/** + * @brief The main loop function of the display. + */ +void ESPMegaDisplay::loop() { + // Check if there is data in the serial buffer + // If there is data, process the data + recieveSerialCommand(); } \ No newline at end of file diff --git a/Template Project/lib/ESPMegaPRO/ESPMegaDisplay.hpp b/Template Project/lib/ESPMegaPRO/ESPMegaDisplay.hpp index 13e7e8f..49bd331 100644 --- a/Template Project/lib/ESPMegaPRO/ESPMegaDisplay.hpp +++ b/Template Project/lib/ESPMegaPRO/ESPMegaDisplay.hpp @@ -1,23 +1,23 @@ #include #include -#define FETCH_TIMEOUT 100 +#define DISPLAY_FETCH_TIMEOUT 100 // ms class ESPMegaDisplay { public: - ESPMegaDisplay(HardwareSerial *displayAdapter, ESPMegaPRO *espmega); + ESPMegaDisplay(HardwareSerial *displayAdapter); void begin(); void loop(); void reset(); void setBrightness(int value); + void setVolume(int value); void jumpToPage(int page); void setString(char* component, char* value); void setNumber(char* component, int value); char* getString(char* component); - int getNumber(char* component); - void bindInputPage(uint8_t card_id); - void bindOutputPage(uint8_t card_id); + bool getStringToBuffer(char* component, char* buffer, uint8_t buffer_size); + uint32_t getNumber(char* component); void handlePwmStateChange(uint8_t pin, uint16_t value); void handleInputStateChange(uint8_t pin, bool state); void registerPushCallback(std::function callback); @@ -26,9 +26,7 @@ class ESPMegaDisplay void unregisterPushCallback(); void unregisterPopCallback(); void unregisterPageChangeCallback(); - private: - uint8_t inputCardId; - uint8_t outputCardId; + protected: uint8_t currentPage; uint8_t rx_buffer_index; char rx_buffer[256]; @@ -40,13 +38,9 @@ class ESPMegaDisplay void processPageReportPayload(); void sendStopBytes(); void sendCommand(char* command); - void refreshPage(); - void refreshInputPage(); - void refreshOutputPage(); bool payloadIsValid(); bool waitForValidPayload(uint32_t timeout); HardwareSerial *displayAdapter; - ESPMegaPRO *espmega; std::function pushCallback; std::function popCallback; std::function pageChangeCallback; diff --git a/Template Project/lib/ESPMegaPRO/ESPMegaIoT.cpp b/Template Project/lib/ESPMegaPRO/ESPMegaIoT.cpp index 6fa7507..7b8be66 100644 --- a/Template Project/lib/ESPMegaPRO/ESPMegaIoT.cpp +++ b/Template Project/lib/ESPMegaPRO/ESPMegaIoT.cpp @@ -19,6 +19,8 @@ ESPMegaIoT::~ESPMegaIoT() { // Delete the mqtt server delete[] mqtt_server; + delete[] mqtt_user; + delete[] mqtt_password; } void ESPMegaIoT::mqttCallback(char *topic, byte *payload, unsigned int length) diff --git a/Template Project/lib/ESPMegaPRO/ESPMegaPRO_OOP.hpp b/Template Project/lib/ESPMegaPRO/ESPMegaPRO_OOP.hpp index fb65de2..ee2dbad 100644 --- a/Template Project/lib/ESPMegaPRO/ESPMegaPRO_OOP.hpp +++ b/Template Project/lib/ESPMegaPRO/ESPMegaPRO_OOP.hpp @@ -10,6 +10,7 @@ #include #include + struct rtctime_t { uint8_t hours; uint8_t minutes; diff --git a/Template Project/lib/ESPMegaPRO/InternalDisplay.cpp b/Template Project/lib/ESPMegaPRO/InternalDisplay.cpp new file mode 100644 index 0000000..96894d7 --- /dev/null +++ b/Template Project/lib/ESPMegaPRO/InternalDisplay.cpp @@ -0,0 +1,101 @@ +#include + + +void InternalDisplay::begin(ESPMegaPRO *espmega) { + this->espmega = espmega; +} + +void InternalDisplay::loop() { + // TODO: implementation +} + +void InternalDisplay::bindInputCard(uint8_t card_id) { + this->bindedInputCard = card_id; + if(currentPage == INTERNAL_DISPLAY_INPUT_PAGE) { + refreshInput(); + } +} + +void InternalDisplay::bindOutputCard(uint8_t card_id) { + this->bindedOutputCard = card_id; + if(currentPage == INTERNAL_DISPLAY_OUTPUT_PAGE) { + refreshOutput(); + } +} + +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 + // TODO: implementation +} + +void InternalDisplay::handlePwmStateChange(uint8_t pin, 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 + // TODO: implementation +} + +void InternalDisplay::handlePageChange(uint8_t page) { + // TODO: implementation +} + +void InternalDisplay::saveNetworkConfig() { + // TODO: implementation +} + +void InternalDisplay::saveMQTTConfig() { + // TODO: implementation +} + +void InternalDisplay::updateStatusIcons() { + // TODO: implementation +} + +void InternalDisplay::updateClock() { + // TODO: implementation +} + +void InternalDisplay::refreshPage() { + // TODO: implementation +} + +void InternalDisplay::refreshPage(uint8_t page) { + // TODO: implementation +} + +void InternalDisplay::refreshDashboard() { + // TODO: implementation +} + +void InternalDisplay::refreshInput() { + // TODO: implementation +} + +void InternalDisplay::refreshOutput() { + // TODO: implementation +} + +void InternalDisplay::refreshAC() { + // TODO: implementation +} + +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(value); + this->sendStopBytes(); +} + +void InternalDisplay::setPWMAdjustmentSlider(uint16_t value) { + // TODO: implementation +} + +void InternalDisplay::setPWMAdjustmentPin(uint8_t pin) { + // TODO: implementation +} + +void InternalDisplay::setPWMAdjustmentButton(bool state) { + // TODO: implementation +} diff --git a/Template Project/lib/ESPMegaPRO/InternalDisplay.hpp b/Template Project/lib/ESPMegaPRO/InternalDisplay.hpp new file mode 100644 index 0000000..1793648 --- /dev/null +++ b/Template Project/lib/ESPMegaPRO/InternalDisplay.hpp @@ -0,0 +1,38 @@ +#include +#include + +#define INTERNAL_DISPLAY_DASHBOARD_PAGE 0 +#define INTERNAL_DISPLAY_INPUT_PAGE 1 +#define INTERNAL_DISPLAY_OUTPUT_PAGE 2 +#define INTERNAL_DISPLAY_AC_PAGE 3 + +class InternalDisplay : public ESPMegaDisplay { + public: + void begin(ESPMegaPRO *espmega); + void loop(); + void bindInputCard(uint8_t card_id); + void bindOutputCard(uint8_t card_id); + private: + uint8_t bindedInputCard; + uint8_t bindedOutputCard; + ESPMegaPRO *espmega; + void handleInputStateChange(uint8_t pin, bool state); + void handlePwmStateChange(uint8_t pin, uint16_t value); + void handlePageChange(uint8_t page); + void setOutputBar(uint8_t pin, uint16_t value); + void setOutputStateColor(uint8_t pin, bool state); + void setInputMarker(uint8_t pin, bool state); + void setPWMAdjustmentSlider(uint16_t value); + void setPWMAdjustmentPin(uint8_t pin); + void setPWMAdjustmentButton(bool state); + void saveNetworkConfig(); + void saveMQTTConfig(); + void updateStatusIcons(); + void updateClock(); + void refreshPage(); + void refreshPage(uint8_t page); + void refreshDashboard(); + void refreshInput(); + void refreshOutput(); + void refreshAC(); +}; \ No newline at end of file