diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputCard.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputCard.cpp index fb3a5c2..2a7b616 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputCard.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputCard.cpp @@ -1,5 +1,12 @@ #include +/** + * @brief Create a new Digital Output Card object with the specified address + * + * @note If you are using the ESPMegaI/O board, you should use the dip switch constructor + * + * @param address The ESPMegaI/O address of the card + */ DigitalOutputCard::DigitalOutputCard(uint8_t address) : change_callbacks(){ this->address = address; // load default pin map @@ -10,14 +17,34 @@ DigitalOutputCard::DigitalOutputCard(uint8_t address) : change_callbacks(){ this->framBinded = false; this->callbacks_handler_index = 0; } -// Instantiate the card with the specified position on the dip switch + +/** + * @brief Create a new Digital Output Card object with the specified position on the dip switch + * + * @note The bit 0 are at the left of the dip switch + * + * @warning There are 5 switches on the dip switch, they should be unique accross all the cards + * + * @param bit0 The position of the first switch on the dip switch + * @param bit1 The position of the second switch on the dip switch + * @param bit2 The position of the third switch on the dip switch + * @param bit3 The position of the fourth switch on the dip switch + * @param bit4 The position of the fifth switch on the dip switch + */ DigitalOutputCard::DigitalOutputCard(bool bit0, bool bit1, bool bit2, bool bit3, bool bit4) : DigitalOutputCard(0x20+bit0+bit1*2+bit2*4+bit3*8+bit4*16) { } -// Initialize the card + +/** + * @brief Initialize the Digital Output Card + * + * @note Although this function can be called inside the main program, it is recommended to use ESPMegaPRO::installCard() instead + * + * @return True if the initialization is successful, false otherwise + */ bool DigitalOutputCard::begin() { this->pwm = Adafruit_PWMServoDriver(this->address); this->pwm.begin(); @@ -26,7 +53,15 @@ bool DigitalOutputCard::begin() { // so we just return true return true; } -// Set the output to the specified state + +/** + * @brief Write a digtal LOW or HIGH to the specified pin + * + * @note This function set both the state and the pwm value of the pin + * + * @param pin The pin to set the state + * @param state The logic level to set the pin to + */ void DigitalOutputCard::digitalWrite(uint8_t pin, bool state) { this->pwm.setPin(virtualPinMap[pin], state ? 4095 : 0); this->state_buffer[pin] = state; @@ -40,7 +75,15 @@ void DigitalOutputCard::digitalWrite(uint8_t pin, bool state) { callback.second(pin, state, state ? 4095 : 0); } } -// Set the output to the specified pwm value + +/** + * @brief Write a pwm value to the specified pin + * + * @note This function set both the state and the pwm value of the pin + * + * @param pin The pin to set the pwm value + * @param value The pwm value to set + */ void DigitalOutputCard::analogWrite(uint8_t pin, uint16_t value) { // If value is greater than 4095, set it to 4095 if (value > 4095) value = 4095; @@ -58,25 +101,49 @@ void DigitalOutputCard::analogWrite(uint8_t pin, uint16_t value) { } } -// Dummy loop function +/** + * @brief The main loop for the Digital Output Card object. + * + * @note This function is not used, it is only here to implement the ExpansionCard interface + */ void DigitalOutputCard::loop() { } -// Get the state of the specified pin +/** + * @brief Get the state of the specified pin + * + * @param pin The pin to get the state + * @return The state of the pin + */ bool DigitalOutputCard::getState(uint8_t pin) { return this->state_buffer[pin]; } -// Get the pwm value of the specified pin +/** + * @brief Get the pwm value of the specified pin + * + * @param pin The pin to get the pwm value + * @return The pwm value of the pin + */ uint16_t DigitalOutputCard::getValue(uint8_t pin) { return this->value_buffer[pin]; } -// Get type of card +/** + * @brief Get the type of the card + * + * @return The type of the card + */ uint8_t DigitalOutputCard::getType() { return CARD_TYPE_DIGITAL_OUTPUT; } +/** + * @brief Set the state of the specified pin + * + * @param pin The pin to set the state + * @param state The state of the pin + */ void DigitalOutputCard::setState(uint8_t pin, bool state) { this-> state_buffer[pin] = state; this->pwm.setPin(pin, state*value_buffer[pin]); @@ -88,6 +155,12 @@ void DigitalOutputCard::setState(uint8_t pin, bool state) { } } +/** + * @brief Set the pwm value of the specified pin + * + * @param pin The pin to set the pwm value + * @param value The pwm value to set + */ void DigitalOutputCard::setValue(uint8_t pin, uint16_t value) { // If value is greater than 4095, set it to 4095 if (value > 4095) value = 4095; @@ -102,15 +175,36 @@ void DigitalOutputCard::setValue(uint8_t pin, uint16_t value) { } } +/** + * @brief Register a callback function for the specified pin + * + * @param callback The callback function to be called, the first parameter is the pin, the second parameter is the state, the third parameter is the pwm value + * @return The handler of the callback function + */ uint8_t DigitalOutputCard::registerChangeCallback(std::function callback) { this->change_callbacks[this->callbacks_handler_index] = callback; return this->callbacks_handler_index++; } +/** + * @brief Unregister a callback function + * + * @param handler The handler of the callback function to be unregistered + */ void DigitalOutputCard::unregisterChangeCallback(uint8_t handler) { this->change_callbacks.erase(handler); } +/** + * @brief Load a pin map + * + * A pin map is an array of 16 elements that maps the physical pins to virtual pins + * The virtual pins are the pins that are used in the callback functions and are used for all the functions in this class + * The physical pins are the pins on the Output IC, This can be found on the schematic of the ESPMegaI/O board + * This function is useful if you want to change the number identification of the pins to match your project needs + * + * @param pinMap The pin map to load + */ void DigitalOutputCard::loadPinMap(uint8_t pinMap[16]) { for(int i = 0; i < 16; i++) { this->pinMap[i] = pinMap[i]; @@ -118,12 +212,27 @@ void DigitalOutputCard::loadPinMap(uint8_t pinMap[16]) { } } +/** + * @brief Bind a FRAM to the card + * + * @note The Output Card use 34 bytes of FRAM + * + * @warning If the fram range overlap with another card, undefined behavior will occur + * + * @param fram The FRAM to bind + * @param address The address of the card in the FRAM + */ void DigitalOutputCard::bindFRAM(FRAM *fram, uint16_t address) { this->fram = fram; this->framBinded = true; this->framAddress = address; } +/** + * @brief Pack the states of all the pins into a 16 bit integer + * + * @return The packed states + */ uint16_t DigitalOutputCard::packStates() { uint16_t packed = 0; for(int i = 0; i < 16; i++) { @@ -132,12 +241,20 @@ uint16_t DigitalOutputCard::packStates() { return packed; } +/** + * @brief Unpack the states of all the pins from a 16 bit integer + * + * @param states The packed states + */ void DigitalOutputCard::unpackStates(uint16_t states) { for(int i = 0; i < 16; i++) { this->setState(i, (states >> i) & 1); } } +/** + * @brief Save the states and values of all the pins to the FRAM + */ void DigitalOutputCard::saveToFRAM() { if(!framBinded) return; // Save the state @@ -147,6 +264,9 @@ void DigitalOutputCard::saveToFRAM() { this->fram->write(framAddress+2, (uint8_t*)value_buffer, 32); } +/** + * @brief Load the states and values of all the pins from the FRAM + */ void DigitalOutputCard::loadFromFRAM() { if(!framBinded) return; // Load the state @@ -160,15 +280,28 @@ void DigitalOutputCard::loadFromFRAM() { } } +/** + * @brief Set the auto save to FRAM + * + * @param autoSave True to enable auto save, false to disable auto save + */ void DigitalOutputCard::setAutoSaveToFRAM(bool autoSave) { this->framAutoSave = autoSave; } +/** + * @brief Save a single pin value to FRAM + * + * @param pin The pin to save + */ void DigitalOutputCard::savePinValueToFRAM(uint8_t pin) { if(!framBinded) return; this->fram->write(framAddress+2+pin*2, (uint8_t*)&value_buffer[pin], 2); } +/** + * @brief Save the states of all the pins to FRAM + */ void DigitalOutputCard::saveStateToFRAM() { if(!framBinded) return; uint16_t packed = packStates(); diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputCard.hpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputCard.hpp index f5ee591..a3ed97c 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputCard.hpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputCard.hpp @@ -13,6 +13,7 @@ // Publish all topic: requeststate payload: N/A // Enable/disable publish topic: publish_enable payload: 0/1 +// MQTT Topics #define SET_STATE_TOPIC "/set/state" #define SET_VALUE_TOPIC "/set/value" #define STATE_TOPIC "/state" @@ -20,8 +21,20 @@ #define REQUEST_STATE_TOPIC "requeststate" #define PUBLISH_ENABLE_TOPIC "publish_enable" +// Card type #define CARD_TYPE_DIGITAL_OUTPUT 0x00 +/** + * @brief The DigitalOutputCard class is a class for controlling the Digital Output Card. + * + * This Digital Output Card has 16 digital outputs. + * All outputs are PWM capable. + * ALl outputs are 12V Push-Pull outputs. + * Outputs is grouped in 4 groups of 4 outputs.(0-3, 4-7, 8-11, 12-15) + * Each pin is capable of 0.6A, however each group's total current is limited to 1.2A. + * + * @warning You should not instantiate this class directly, instead use ESPMegaIO's registerCard function. + */ class DigitalOutputCard : public ExpansionCard { public: diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputIoT.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputIoT.cpp index e7d9079..cd78212 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputIoT.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputIoT.cpp @@ -1,22 +1,42 @@ #include -DigitalOutputIoT::DigitalOutputIoT() { +/** + * @brief Create a new DigitalOutputIoT object + */ +DigitalOutputIoT::DigitalOutputIoT() +{ this->state_report_topic = new char[10]; this->value_report_topic = new char[10]; this->digital_outputs_publish_enabled = true; } -DigitalOutputIoT::~DigitalOutputIoT() { +/** + * @brief Destroy the DigitalOutputIoT object + */ +DigitalOutputIoT::~DigitalOutputIoT() +{ delete[] this->state_report_topic; delete[] this->value_report_topic; } -bool DigitalOutputIoT::begin(uint8_t card_id, ExpansionCard *card, PubSubClient *mqtt, char *base_topic) { +/** + * @brief Initialize the DigitalOutputIoT object + * + * @note ALthough this function can be called inside the main program, it is recommended to use ESPMegaPRO::installCard() instead + * + * @param card_id The id of the card + * @param card The card object + * @param mqtt The PubSubClient object + * @param base_topic The base topic of the card + * @return True if the initialization is successful, false otherwise + */ +bool DigitalOutputIoT::begin(uint8_t card_id, ExpansionCard *card, PubSubClient *mqtt, char *base_topic) +{ ESP_LOGD("DigitalOutputIoT", "Beginning DigitalOutputIoT"); this->mqtt = mqtt; this->base_topic = base_topic; - this->card = (DigitalOutputCard *) card; - this-> card_id = card_id; + this->card = (DigitalOutputCard *)card; + this->card_id = card_id; this->set_state_length = strlen(SET_STATE_TOPIC); this->set_value_length = strlen(SET_VALUE_TOPIC); this->state_length = strlen(STATE_TOPIC); @@ -27,51 +47,78 @@ bool DigitalOutputIoT::begin(uint8_t card_id, ExpansionCard *card, PubSubClient strcpy(this->value_report_topic, "00/value"); ESP_LOGV("DigitalOutputIoT", "Registering callbacks inside DigitalOutputIoT::begin"); // Register callbacks - auto bindedCallback = std::bind(&DigitalOutputIoT::handleValueChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); + auto bindedCallback = std::bind(&DigitalOutputIoT::handleValueChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); this->card->registerChangeCallback(bindedCallback); ESP_LOGV("DigitalOutputIoT", "DigitalOutputIoT::begin complete"); return true; } -// Protocol for digital output card -// Note that pin is always 2 characters long and padded with 0 if necessary -// Set pin state topic: /set/state payload: 0/1 -// Set pin pwm topic: /set/value payload: 0-4095 -// Publish pin state topic: /state payload: 0/1 -// Publish pin pwm topic: /value payload: 0-4095 -// Publish all topic: requeststate payload: N/A -// Enable/disable publish topic: publish_enable payload: 0/1 -void DigitalOutputIoT::handleMqttMessage(char *topic, char *payload) { +/** + * @brief Handle the MQTT messages for the DigitalOutputIoT card + * + * @param topic The topic of the message + * @param payload The payload of the message + */ +void DigitalOutputIoT::handleMqttMessage(char *topic, char *payload) +{ + // Protocol for digital output card + // Note that pin is always 2 characters long and padded with 0 if necessary + // Set pin state topic: /set/state payload: 0/1 + // Set pin pwm topic: /set/value payload: 0-4095 + // Publish pin state topic: /state payload: 0/1 + // Publish pin pwm topic: /value payload: 0-4095 + // Publish all topic: requeststate payload: N/A + // Enable/disable publish topic: publish_enable payload: 0/1 uint8_t topic_length = strlen(topic); - if(this-> processSetStateMessage(topic, payload, topic_length)) return; - if(this-> processSetValueMessage(topic, payload, topic_length)) return; - if(this-> processRequestStateMessage(topic, payload, topic_length)) return; + if (this->processSetStateMessage(topic, payload, topic_length)) + return; + if (this->processSetValueMessage(topic, payload, topic_length)) + return; + if (this->processRequestStateMessage(topic, payload, topic_length)) + return; } -bool DigitalOutputIoT::processSetStateMessage(char *topic, char *payload, uint8_t topic_length) { +/** + * @brief Process a set state message + * + * @param topic The null terminated topic + * @param payload The null terminated payload + * @param topic_length The length of the topic + * @return True if the message is a set state message, false otherwise + */ +bool DigitalOutputIoT::processSetStateMessage(char *topic, char *payload, uint8_t topic_length) +{ // Check if the topic is a set state topic // The correct format is /set/state // This mean that the topic must end with /set/state // Check if the 3rd character is / - if(topic[2] != '/') { + if (topic[2] != '/') + { return false; } // The topic must be set_state_length + 2 characters long - if(topic_length != set_state_length + 2) { + if (topic_length != set_state_length + 2) + { return false; } // Check if the topic ends with /set/state - if (!strncmp(topic+2, SET_STATE_TOPIC, set_state_length)) { + if (!strncmp(topic + 2, SET_STATE_TOPIC, set_state_length)) + { // Get the pin number - uint8_t pin = (topic[0] - '0')*10 + (topic[1] - '0'); + uint8_t pin = (topic[0] - '0') * 10 + (topic[1] - '0'); // Get the state bool state = false; char state_char = payload[0]; - if (state_char == '0') { + if (state_char == '0') + { state = false; - } else if (state_char == '1') { + } + else if (state_char == '1') + { state = true; - } else { + } + else + { return false; } // Set the state @@ -81,22 +128,34 @@ bool DigitalOutputIoT::processSetStateMessage(char *topic, char *payload, uint8_ return false; } -bool DigitalOutputIoT::processSetValueMessage(char *topic, char *payload, uint8_t topic_length) { +/** + * @brief Process a set value message + * + * @param topic The null terminated topic + * @param payload The null terminated payload + * @param topic_length The length of the topic + * @return True if the message is a set value message, false otherwise + */ +bool DigitalOutputIoT::processSetValueMessage(char *topic, char *payload, uint8_t topic_length) +{ // Check if the topic is a set value topic // The correct format is /set/value // This mean that the topic must end with /set/value // Check if the 3rd character is / - if(topic[2] != '/') { + if (topic[2] != '/') + { return false; } // The topic must be set_value_length + 2 characters long - if(topic_length != set_value_length + 2) { + if (topic_length != set_value_length + 2) + { return false; } // Check if the topic ends with /set/value - if (!strncmp(topic+2, SET_VALUE_TOPIC, set_value_length)) { + if (!strncmp(topic + 2, SET_VALUE_TOPIC, set_value_length)) + { // Get the pin number - uint8_t pin = (topic[0] - '0')*10 + (topic[1] - '0'); + uint8_t pin = (topic[0] - '0') * 10 + (topic[1] - '0'); // Get the value uint16_t value = atoi(payload); // Set the value @@ -106,16 +165,27 @@ bool DigitalOutputIoT::processSetValueMessage(char *topic, char *payload, uint8_ return false; } -bool DigitalOutputIoT::processRequestStateMessage(char *topic, char *payload, uint8_t topic_length) { +/** + * @brief Process a request state message + * + * @param topic The null terminated topic + * @param payload The null terminated payload + * @param topic_length The length of the topic + * @return True if the message is a request state message, false otherwise + */ +bool DigitalOutputIoT::processRequestStateMessage(char *topic, char *payload, uint8_t topic_length) +{ // Check if the topic is a request state topic // The correct format is requeststate // This mean that the topic must be request_state_length characters long // The topic must be request_state_length characters long - if(topic_length != request_state_length) { + if (topic_length != request_state_length) + { return false; } // Check if the topic is requeststate - if (!strncmp(topic, REQUEST_STATE_TOPIC, request_state_length)) { + if (!strncmp(topic, REQUEST_STATE_TOPIC, request_state_length)) + { // Publish the state of all pins publishDigitalOutputs(); return true; @@ -123,27 +193,53 @@ bool DigitalOutputIoT::processRequestStateMessage(char *topic, char *payload, ui return false; } -void DigitalOutputIoT::publishDigitalOutputs() { - if(!digital_outputs_publish_enabled) return; - for(int i = 0; i < 16; i++) { +/** + * @brief Publish the state of all digital outputs + */ +void DigitalOutputIoT::publishDigitalOutputs() +{ + if (!digital_outputs_publish_enabled) + return; + for (int i = 0; i < 16; i++) + { publishDigitalOutput(i); } } -void DigitalOutputIoT::publishDigitalOutput(uint8_t pin) { +/** + * @brief Publish the state and value of the specified digital output + * + * @param pin The pin to publish + */ +void DigitalOutputIoT::publishDigitalOutput(uint8_t pin) +{ publishDigitalOutputState(pin); publishDigitalOutputValue(pin); } -void DigitalOutputIoT::publishDigitalOutputState(uint8_t pin) { - if(!digital_outputs_publish_enabled) return; +/** + * @brief Publish the state of the specified digital output + * + * @param pin The pin to publish + */ +void DigitalOutputIoT::publishDigitalOutputState(uint8_t pin) +{ + if (!digital_outputs_publish_enabled) + return; state_report_topic[0] = pin / 10 + '0'; state_report_topic[1] = pin % 10 + '0'; publishRelative(state_report_topic, card->getState(pin) ? "1" : "0"); -} +} -void DigitalOutputIoT::publishDigitalOutputValue(uint8_t pin) { - if(!digital_outputs_publish_enabled) return; +/** + * @brief Publish the value of the specified digital output + * + * @param pin The pin to publish + */ +void DigitalOutputIoT::publishDigitalOutputValue(uint8_t pin) +{ + if (!digital_outputs_publish_enabled) + return; value_report_topic[0] = pin / 10 + '0'; value_report_topic[1] = pin % 10 + '0'; char payload[5]; @@ -151,42 +247,65 @@ void DigitalOutputIoT::publishDigitalOutputValue(uint8_t pin) { publishRelative(value_report_topic, payload); } -void DigitalOutputIoT::setDigitalOutputsPublishEnabled(bool enabled) { +/** + * @brief Enable/disable publishing of digital outputs + * + * @param enabled True to enable publishing, false to disable publishing + */ +void DigitalOutputIoT::setDigitalOutputsPublishEnabled(bool enabled) +{ digital_outputs_publish_enabled = enabled; } -void DigitalOutputIoT::handleValueChange(uint8_t pin, bool state, uint16_t value) { +/** + * @brief Handle the value change of a pin + * + * @note This function is registered as a callback function with the DigitalOutputCard object + * + * @param pin The pin that changed + * @param state The new state of the pin + * @param value The new value of the pin + */ +void DigitalOutputIoT::handleValueChange(uint8_t pin, bool state, uint16_t value) +{ publishDigitalOutput(pin); - if(value_change_callback != NULL) { - value_change_callback(pin, state, value); - } } -void DigitalOutputIoT::registerChangeCallback(std::function callback) { - value_change_callback = callback; -} - -void DigitalOutputIoT::unregisterChangeCallback() { - value_change_callback = NULL; -} - -void DigitalOutputIoT::publishReport() { +/** + * @brief Publish all digital outputs + * + * @note This function is called by the ESPMegaIoT object + */ +void DigitalOutputIoT::publishReport() +{ publishDigitalOutputs(); } -uint8_t DigitalOutputIoT::getType() { +/** + * @brief Get the type of the IoT component + * + * @return The type of the IoT component + */ +uint8_t DigitalOutputIoT::getType() +{ return CARD_TYPE_DIGITAL_OUTPUT; } -void DigitalOutputIoT::subscribe() { +/** + * @brief Subscribe to the MQTT topics used by the DigitalOutputIoT object + */ +void DigitalOutputIoT::subscribe() +{ char topic[20]; // Subscribe to all set state topics - for(int i = 0; i < 16; i++) { + for (int i = 0; i < 16; i++) + { sprintf(topic, "%02d/set/state", i); subscribeRelative(topic); } // Subscribe to all set value topics - for(int i = 0; i < 16; i++) { + for (int i = 0; i < 16; i++) + { sprintf(topic, "%02d/set/value", i); subscribeRelative(topic); } @@ -196,5 +315,11 @@ void DigitalOutputIoT::subscribe() { subscribeRelative(PUBLISH_ENABLE_TOPIC); } -void DigitalOutputIoT::loop() { +/** + * @brief The main loop for the DigitalOutputIoT object + * + * @note This function is not used, it is only here to implement the IoTComponent interface + */ +void DigitalOutputIoT::loop() +{ } \ No newline at end of file diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputIoT.hpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputIoT.hpp index 90a2504..116f206 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputIoT.hpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalOutputIoT.hpp @@ -3,6 +3,11 @@ #include #include +/** + * @brief The DigitalOutputIoT class is a class interfacing with the Digital Output Card through MQTT. + * + * @warning You should not instantiate this class directly, instead use ESPMegaIO's registerCard function. + */ class DigitalOutputIoT : public IoTComponent { public: DigitalOutputIoT(); @@ -15,8 +20,6 @@ class DigitalOutputIoT : public IoTComponent { void publishDigitalOutputValue(uint8_t pin); void setDigitalOutputsPublishEnabled(bool enabled); void handleValueChange(uint8_t pin, bool state, uint16_t value); - void registerChangeCallback(std::function callback); - void unregisterChangeCallback(); void publishReport(); void subscribe(); void loop(); @@ -26,7 +29,6 @@ class DigitalOutputIoT : public IoTComponent { bool processSetStateMessage(char *topic, char *payload, uint8_t topic_length); bool processSetValueMessage(char *topic, char *payload, uint8_t topic_length); bool processRequestStateMessage(char *topic, char *payload, uint8_t topic_length); - std::function value_change_callback; DigitalOutputCard *card; char *state_report_topic; char *value_report_topic; diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaDisplay.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaDisplay.cpp index 09a00bc..f4d0563 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaDisplay.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaDisplay.cpp @@ -36,6 +36,7 @@ bool ESPMegaDisplay::recieveSerialCommand() /** * @brief Processes the received serial command. + * @note This function interacts directly with the rx_buffer. */ void ESPMegaDisplay::processSerialCommand() { @@ -62,6 +63,7 @@ void ESPMegaDisplay::processSerialCommand() /** * @brief Processes the touch event payload. + * @note This function interacts directly with the rx_buffer. */ void ESPMegaDisplay::processTouchPayload() { @@ -83,6 +85,7 @@ void ESPMegaDisplay::processTouchPayload() /** * @brief Processes the page report event payload. + * @note This function interacts directly with the rx_buffer. */ void ESPMegaDisplay::processPageReportPayload() { @@ -161,6 +164,8 @@ void ESPMegaDisplay::setString(const char *component, const char *value) /** * @brief Gets the value of a number component from the display. + * @warning This function is blocking. + * @warning If the display does not respond or is not connected, this function will block for up to DISPLAY_FETCH_RETRY_COUNT * DISPLAY_FETCH_TIMEOUT milliseconds. * @param component The component name. * @return The value of the number component. */ @@ -219,6 +224,8 @@ uint32_t ESPMegaDisplay::getNumber(const char *component) /** * @brief Gets the value of a string component from the display. + * @warning This function is blocking. + * @warning If the display does not respond or is not connected, this function will block for up to DISPLAY_FETCH_RETRY_COUNT * DISPLAY_FETCH_TIMEOUT milliseconds. * @param component The component name. * @return The value of the string component. * @note The returned char array must be freed after use. @@ -275,6 +282,15 @@ const char *ESPMegaDisplay::getString(const char *component) return value; } +/** + * @brief Gets the value of a number component from the display and stores it in a buffer. + * @warning This function is blocking. + * @warning If the display does not respond or is not connected, this function will block for up to DISPLAY_FETCH_RETRY_COUNT * DISPLAY_FETCH_TIMEOUT milliseconds. + * @param component The component name. + * @param buffer The buffer to store the value. + * @param buffer_size The size of the buffer. + * @return True if the value is successfully stored in the buffer, false otherwise. + */ bool ESPMegaDisplay::getStringToBuffer(const char *component, char *buffer, uint8_t buffer_size) { // We might be in the middle of a serial command diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaDisplay.hpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaDisplay.hpp index 0cff6d1..5fd009b 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaDisplay.hpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaDisplay.hpp @@ -5,6 +5,12 @@ #define DISPLAY_FETCH_TIMEOUT 100 // ms #define DISPLAY_FETCH_RETRY_COUNT 5 +/** + * @brief The ESPMegaDisplay class is a class for controlling the ESPMegaDisplay. + * + * @note The ESPMegaDisplay is a UART controlled display. + * @note Connect the Display's TX pin to the ESPMega's RX pin and the Display's RX pin to the ESPMega's TX pin. + */ class ESPMegaDisplay { public: diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ExpansionCard.hpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ExpansionCard.hpp index 50ee940..b656240 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ExpansionCard.hpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ExpansionCard.hpp @@ -1,6 +1,17 @@ #pragma once #include +/** + * @brief The base class for all expansion cards + * + * In order to create a new expansion card, you should create a new class that inherits from this class. + * Your class should implement the following functions: + * - begin() : Initialize the card + * - loop() : A function that is called in the main loop + * - getType() : Get the type of the card, The type should be a unique number between 0 and 255 + * + * @warning This class is abstract and should not be instantiated directly. + */ class ExpansionCard { public: // Instantiate the card with the specified address diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/IoTComponent.hpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/IoTComponent.hpp index c075cdc..c323103 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/IoTComponent.hpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/IoTComponent.hpp @@ -2,6 +2,25 @@ #include #include #include + +/** + * @brief The IoTComponent class is a base class that is used to interface with an expansion card through MQTT. + * + * In order to create a new IoTComponent, you should create a new class that inherits from this class. + * Your class should implement the following functions: + * - begin() : Initialize the component, record the card id, ExpansionCard object, the PubSubClient object and the base topic + * - handleMqttMessage() : Handle the MQTT messages for the component + * - publishReport() : Publish all the reports for the component + * - getType() : Get the type of the component, This should return the underlying ExpansionCard type + * - subscribe() : Subscribe to the MQTT topics used by the component + * - loop() : A function that is called in the main loop + * + * Additionally, the inherited class will have access to these helper functions: + * - publishRelative() : Publish a message to a topic relative to the base topic and the card id + * - subscribeRelative() : Subscribe to a topic relative to the base topic and the card id + * + * @warning This class is abstract and should not be instantiated directly. + */ class IoTComponent { public: virtual bool begin(uint8_t card_id, ExpansionCard *card, PubSubClient *mqtt, char *base_topic); @@ -10,7 +29,6 @@ class IoTComponent { virtual void publishReport(); virtual uint8_t getType(); virtual void subscribe(); - void loop(); protected: char *base_topic;