diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogCard.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogCard.cpp index a2007b4..b74f748 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogCard.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogCard.cpp @@ -1,6 +1,14 @@ +/** + * @file AnalogCard.cpp + * @brief Implementation of the AnalogCard class. + */ + #include #include "esp_log.h" +/** + * @brief Default constructor for the AnalogCard class. + */ AnalogCard::AnalogCard() : dac0(DAC0_ADDRESS), dac1(DAC1_ADDRESS), dac2(DAC2_ADDRESS), @@ -12,6 +20,11 @@ AnalogCard::AnalogCard() : dac0(DAC0_ADDRESS), this->handler_count = 0; } +/** + * @brief Writes a value to the specified DAC pin. + * @param pin The DAC pin to write to. + * @param value The value to write. + */ void AnalogCard::dacWrite(uint8_t pin, uint16_t value) { ESP_LOGV("AnalogCard", "DAC Write: %d, %d", pin, value); @@ -19,6 +32,11 @@ void AnalogCard::dacWrite(uint8_t pin, uint16_t value) this->setDACValue(pin, value); } +/** + * @brief Sets the state of the specified DAC pin. + * @param pin The DAC pin to set the state of. + * @param state The state to set (true = on, false = off). + */ void AnalogCard::setDACState(uint8_t pin, bool state) { ESP_LOGD("AnalogCard", "Setting DAC state: %d, %d", pin, state); @@ -30,6 +48,11 @@ void AnalogCard::setDACState(uint8_t pin, bool state) } } +/** + * @brief Sets the value of the specified DAC pin. + * @param pin The DAC pin to set the value of. + * @param value The value to set. + */ void AnalogCard::setDACValue(uint8_t pin, uint16_t value) { ESP_LOGD("AnalogCard", "Setting DAC value: %d, %d", pin, value); @@ -40,18 +63,33 @@ void AnalogCard::setDACValue(uint8_t pin, uint16_t value) callback.second(pin, this->dac_state[pin], value); } } - +/** + * @brief Gets the value of the specified DAC pin. + * @param pin The DAC pin to get the value of. + * @return The value of the DAC pin. + */ uint16_t AnalogCard::getDACValue(uint8_t pin) { return this->dac_value[pin]; } +/** + * @brief Gets the state of the specified DAC pin. + * @param pin The DAC pin to get the state of. + * @return The state of the DAC pin (true = on, false = off). + */ bool AnalogCard::getDACState(uint8_t pin) { return this->dac_state[pin]; } +/** + * @brief Sends data to the specified DAC pin. + * @param pin The DAC pin to send data to. + * @param value The data to send. + * @note This function does not call the DAC change callbacks. + */ void AnalogCard::sendDataToDAC(uint8_t pin, uint16_t value) { switch (pin) @@ -70,6 +108,12 @@ void AnalogCard::sendDataToDAC(uint8_t pin, uint16_t value) break; } } + +/** + * @brief Reads the value from the specified analog pin. + * @param pin The analog pin to read from. + * @return The value read from the analog pin. + */ uint16_t AnalogCard::analogRead(uint8_t pin) { if (pin >= 0 && pin <= 3) @@ -82,6 +126,11 @@ uint16_t AnalogCard::analogRead(uint8_t pin) } return 65535; } + +/** + * @brief Initializes the AnalogCard. + * @return True if initialization is successful, false otherwise. + */ bool AnalogCard::begin() { if (!this->dac0.begin()) @@ -117,21 +166,38 @@ bool AnalogCard::begin() return true; } +/** + * @brief The main loop of the AnalogCard. + * @note This function does nothing. + */ void AnalogCard::loop() { } +/** + * @brief Gets the type of the AnalogCard. + * @return The type of the AnalogCard. + */ uint8_t AnalogCard::getType() { return CARD_TYPE_ANALOG; } +/** + * @brief Registers a callback function to be called when the state or value of a DAC pin changes. + * @param callback The callback function to register. + * @return The handler ID of the registered callback. + */ uint8_t AnalogCard::registerDACChangeCallback(std::function callback) { this->dac_change_callbacks[this->handler_count] = callback; return this->handler_count++; } +/** + * @brief Unregisters a previously registered DAC change callback. + * @param handler The handler ID of the callback to unregister. + */ void AnalogCard::unregisterDACChangeCallback(uint8_t handler) { this->dac_change_callbacks.erase(handler); diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogCard.hpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogCard.hpp index c70c3eb..86134c2 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogCard.hpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogCard.hpp @@ -5,8 +5,10 @@ #include #include +// Analog Card #define CARD_TYPE_ANALOG 0x02 +// Analog Card FRAM Address #define ANALOG_INPUT_BANK_A_ADDRESS 0x48 #define ANALOG_INPUT_BANK_B_ADDRESS 0x49 #define DAC0_ADDRESS 0x60 @@ -31,6 +33,7 @@ class AnalogCard : public ExpansionCard { uint8_t getType(); private: uint8_t handler_count; + // Map of handler IDs to callback functions std::map> dac_change_callbacks; bool dac_state[4]; uint16_t dac_value[4]; diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogIoT.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogIoT.cpp index 2f014e0..4479153 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogIoT.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogIoT.cpp @@ -1,5 +1,19 @@ +/** + * @file AnalogIoT.cpp + * @brief Implementation of the AnalogIoT class. + * + * This file contains the implementation of the AnalogIoT class, which provides functionality for handling analog input and output operations in an IoT system. + * The class allows for setting the state and value of digital-to-analog converters (DACs), as well as reading the value of analog-to-digital converters (ADCs). + * It also supports publishing the state and value of DACs and ADCs over MQTT. + */ #include + +/** + * @brief Default constructor for the AnalogIoT class. + * + * This constructor initializes the AnalogIoT object and sets up the ADC conversion callbacks. + */ AnalogIoT::AnalogIoT() : adc_conversion_callbacks() { for (uint8_t i = 0; i < 8; i++) { adc_publish_enabled[i] = false; @@ -8,8 +22,23 @@ AnalogIoT::AnalogIoT() : adc_conversion_callbacks() { this->adc_conversion_callback_index = 0; } +/** + * @brief Default destructor for the AnalogIoT class. + */ AnalogIoT::~AnalogIoT() { + this->adc_conversion_callbacks.clear(); } + +/** + * @brief Initializes the AnalogIoT object. + * @param card_id The ID of the card. + * @param card A pointer to the card object. + * @param mqtt A pointer to the MQTT client object. + * @param base_topic The base MQTT topic. + * @return True if the initialization was successful, false otherwise. + * @note This function can be called from the main program but it is recommended to use ESPMegaIoT to initialize the IoT Components. + * This function initializes the AnalogIoT object and registers the callbacks for handling DAC changes. + */ bool AnalogIoT::begin(uint8_t card_id, ExpansionCard *card, PubSubClient *mqtt, char *base_topic) { this->mqtt = mqtt; this->base_topic = base_topic; @@ -26,6 +55,11 @@ bool AnalogIoT::begin(uint8_t card_id, ExpansionCard *card, PubSubClient *mqtt, this->card->registerDACChangeCallback(bindedCallback); return true; } + +/** + * @brief Publishes the state of all DACs. + * @note This function is called when a request state message is received. + */ void AnalogIoT::handleMqttMessage(char *topic, char *payload){ uint8_t topic_length = strlen(topic); if(this-> processDACSetStateMessage(topic, payload, topic_length)) return; @@ -34,11 +68,20 @@ void AnalogIoT::handleMqttMessage(char *topic, char *payload){ if(this-> processADCSetConversionIntervalMessage(topic, payload, topic_length)) return; if(this-> processADCSetConversionEnabledMessage(topic, payload, topic_length)) return; } + +/** + * @brief Publishes the state of all DACs. + */ void AnalogIoT::publishADCs() { for (uint8_t i = 0; i < 8; i++) { this->publishADC(i); } } + +/** + * @brief Publishes the state of a DAC. + * @param pin The pin of the DAC. + */ void AnalogIoT::publishADC(uint8_t pin) { if (this->adc_publish_enabled[pin]) { uint16_t value = this->card->analogRead(pin); @@ -55,29 +98,71 @@ void AnalogIoT::publishADC(uint8_t pin) { } } } + +/** + * @brief Sets the interval at which the state of all DACs is published. + * @param interval The interval in milliseconds. + */ void AnalogIoT::setADCsPublishInterval(uint32_t interval) { for (uint8_t i = 0; i < 8; i++) { adc_conversion_interval[i] = interval; } } + +/** + * @brief Sets whether the state of all DACs is published. + * @param enabled True if the state of all DACs should be published, false otherwise. + */ void AnalogIoT::setADCsPublishEnabled(bool enabled) { for (uint8_t i = 0; i < 8; i++) { adc_publish_enabled[i] = enabled; } } + +/** + * @brief Registers a callback for handling ADC conversions. + * @param callback The callback function. + * @return The handler of the callback. + */ uint8_t AnalogIoT::registerADCConversionCallback(std::function callback) { this->adc_conversion_callbacks[this->adc_conversion_callback_index] = callback; return this->adc_conversion_callback_index++; } + +/** + * @brief Unregisters a callback for handling ADC conversions. + * @param handler The handler of the callback. + */ void AnalogIoT::unregisterADCConversionCallback(uint8_t handler) { this->adc_conversion_callbacks.erase(handler); } + +/** + * @brief Sets the interval at which the value of an ADC channel is read. + * @param pin The pin of the ADC channel. + * @param interval The interval in milliseconds. + */ void AnalogIoT::setADCConversionInterval(uint8_t pin, uint16_t interval) { adc_conversion_interval[pin] = interval; } + +/** + * @brief Enables or disables the periodic reading of the value of an ADC channel. + * @param pin The pin of the ADC channel. + * @param enabled True if the value of the ADC channel should be read, false otherwise. + */ void AnalogIoT::setADCConversionEnabled(uint8_t pin, bool enabled) { adc_publish_enabled[pin] = enabled; } + +/** + * @brief Processes a message received on the MQTT topic for setting the state of a DAC. + * @param topic The topic of the message. + * @param payload The payload of the message. + * @param topic_length The length of the topic. + * @note This function is not meant to be called from user code. + * @return True if the message was processed, false otherwise. + */ bool AnalogIoT::processADCSetConversionIntervalMessage(char *topic, char *payload, uint8_t topic_length) { // TODO: Process payload matching the criteria // Topic: adc/<%02d>/set/conversion_interval @@ -102,6 +187,15 @@ bool AnalogIoT::processADCSetConversionIntervalMessage(char *topic, char *payloa this->setADCConversionInterval(pin, interval); return true; } + +/** + * @brief Processes a message received on the MQTT topic for setting the value of a DAC. + * @param topic The topic of the message. + * @param payload The payload of the message. + * @param topic_length The length of the topic. + * @note This function is not meant to be called from user code. + * @return True if the message was processed, false otherwise. + */ bool AnalogIoT::processADCSetConversionEnabledMessage(char *topic, char *payload, uint8_t topic_length) { // Topic: adc/<%02d>/set/conversion_enabled // The first 4 characters are "adc/" @@ -125,6 +219,15 @@ bool AnalogIoT::processADCSetConversionEnabledMessage(char *topic, char *payload this->setADCConversionEnabled(pin, enabled); return true; } + +/** + * @brief Processes a message received on the MQTT topic for setting the state of a DAC. + * @param topic The topic of the message. + * @param payload The payload of the message. + * @param topic_length The length of the topic. + * @note This function is not meant to be called from user code. + * @return True if the message was processed, false otherwise. + */ bool AnalogIoT::processDACSetStateMessage(char *topic, char *payload, uint8_t topic_length) { // Topic: dac/<%02d>/set/state // The first 4 characters are "dac/" @@ -148,6 +251,15 @@ bool AnalogIoT::processDACSetStateMessage(char *topic, char *payload, uint8_t to this->card->setDACState(pin, state); return true; } + +/** + * @brief Processes a message received on the MQTT topic for setting the value of a DAC. + * @param topic The topic of the message. + * @param payload The payload of the message. + * @param topic_length The length of the topic. + * @note This function is not meant to be called from user code. + * @return True if the message was processed, false otherwise. + */ bool AnalogIoT::processDACSetValueMessage(char *topic, char *payload, uint8_t topic_length) { // Topic: dac/<%02d>/set/value // The first 4 characters are "dac/" @@ -171,6 +283,15 @@ bool AnalogIoT::processDACSetValueMessage(char *topic, char *payload, uint8_t to this->card->setDACValue(pin, value); return true; } + +/** + * @brief Processes a message received on the MQTT topic for requesting the state of all DACs. + * @param topic The topic of the message. + * @param payload The payload of the message. + * @param topic_length The length of the topic. + * @note This function is not meant to be called from user code. + * @return True if the message was processed, false otherwise. + */ bool AnalogIoT::processRequestStateMessage(char *topic, char *payload, uint8_t topic_length) { // Topic: requeststate // The length of the topic must be 12 characters @@ -187,6 +308,11 @@ bool AnalogIoT::processRequestStateMessage(char *topic, char *payload, uint8_t t this->publishADCs(); return false; } + +/** + * @brief Subscribes to all MQTT topics used by the AnalogIoT object. + * @note This function is called when the MQTT client connects. + */ void AnalogIoT::subscribe() { // There are 4 DACs and 8 ADCs // DACs: dac/<%02d>/set/state, dac/<%02d>/set/value, dac/publish_enable @@ -226,23 +352,45 @@ void AnalogIoT::loop() { } } } + +/** + * @brief Publishes the state of all DACs. + */ void AnalogIoT::publishReport() { publishADCs(); publishDACs(); } +/** + * @brief Gets the type of the card. + * @return The type of the card. + */ uint8_t AnalogIoT::getType() { return CARD_TYPE_ANALOG; } + +/** + * @brief Publishes the state of all DACs. + */ void AnalogIoT::publishDACs() { for (uint8_t i = 0; i < 4; i++) { this->publishDAC(i); } } + +/** + * @brief Publishes the state of a DAC. + * @param pin The pin of the DAC. + */ void AnalogIoT::publishDAC(uint8_t pin) { this->publishDACState(pin); this->publishDACValue(pin); } + +/** + * @brief Publishes the state of a DAC. + * @param pin The pin of the DAC. + */ void AnalogIoT::publishDACState(uint8_t pin) { char *topic = new char[15]; sprintf(topic, "dac/%02d/state", pin); @@ -252,6 +400,11 @@ void AnalogIoT::publishDACState(uint8_t pin) { delete[] topic; delete[] payload; } + +/** + * @brief Publishes the value of a DAC. + * @param pin The pin of the DAC. + */ void AnalogIoT::publishDACValue(uint8_t pin) { char *topic = new char[15]; sprintf(topic, "dac/%02d/value", pin); @@ -262,6 +415,10 @@ void AnalogIoT::publishDACValue(uint8_t pin) { delete[] payload; } +/** + * @brief Publishes the state of a DAC. + * @param pin The pin of the DAC. + */ void AnalogIoT::handleDACChange(uint8_t pin, uint16_t value) { this->publishDAC(pin); } \ No newline at end of file diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogIoT.hpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogIoT.hpp index 9c0c753..b806b84 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogIoT.hpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/AnalogIoT.hpp @@ -3,6 +3,7 @@ #include #include +// MQTT Topics #define DAC_SET_STATE_TOPIC "/set/state" #define DAC_SET_VALUE_TOPIC "/set/value" #define DAC_STATE_TOPIC "/dac/00/state" @@ -39,7 +40,9 @@ class AnalogIoT : public IoTComponent { void loop(); uint8_t getType(); private: + // The index of the next callback to be registered uint8_t adc_conversion_callback_index = 0; + // We keep track of the length of the topics so we don't have to calculate it every time uint8_t dac_set_state_length; uint8_t dac_set_value_length; uint8_t dac_state_length; diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ClimateCard.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ClimateCard.cpp index 25484fe..adae7b9 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ClimateCard.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ClimateCard.cpp @@ -1,5 +1,21 @@ +/** + * @file ClimateCard.cpp + * @brief Implementation file for the ClimateCard class. + * + * This file contains the implementation of the ClimateCard class, which represents a climate control card. + * The ClimateCard class provides methods for controlling an air conditioner, reading temperature and humidity + * from sensors, and saving and loading the state to/from FRAM memory. + */ #include +/** + * @brief Construct a new ClimateCard object. + * + * @param ir_pin The GPIO pin number of the IR transmitter. + * @param ac The AirConditioner object that represents the air conditioner. + * @param sensor_type The type of the sensor connected to the card. + * @param sensor_pin The GPIO pin number of the sensor. + */ ClimateCard::ClimateCard(uint8_t ir_pin, AirConditioner ac, uint8_t sensor_type, uint8_t sensor_pin) { this->ir_pin = ir_pin; @@ -24,11 +40,21 @@ ClimateCard::ClimateCard(uint8_t ir_pin, AirConditioner ac, uint8_t sensor_type, this->state.ac_fan_speed = 0; } +/** + * @brief Construct a new ClimateCard object. + * + * @param ir_pin The GPIO pin number of the IR transmitter. + * @param ac The AirConditioner object that represents the air conditioner. + * + * @note This constructor can be used when no sensor is connected to the card. + */ ClimateCard::ClimateCard(uint8_t ir_pin, AirConditioner ac) : ClimateCard(ir_pin, ac, AC_SENSOR_TYPE_NONE, 0) { - } +/** + * @brief The destructor of the ClimateCard class. + */ ClimateCard::~ClimateCard() { delete dht; @@ -36,6 +62,12 @@ ClimateCard::~ClimateCard() rmt_driver_uninstall(RMT_TX_CHANNEL); } +/** + * @brief Initialize the ClimateCard object. + * + * @return true if initialization was successful. + * @return false if initialization failed. + */ bool ClimateCard::begin() { switch (sensor_type) @@ -49,6 +81,7 @@ bool ClimateCard::begin() break; } updateAirConditioner(); + // We are returning here because sending IR signals is not working yet return true; if (sensor_pin != 0) { @@ -61,6 +94,11 @@ bool ClimateCard::begin() } } +/** + * @brief Loop function of the ClimateCard class. + * + * @note When this card is installed in an ESPMega, this function is called automatically by the ESPMega class. + */ void ClimateCard::loop() { static uint32_t last_sensor_update = 0; @@ -71,26 +109,54 @@ void ClimateCard::loop() } } +/** + * @brief bind FRAM memory to the ClimateCard object at the specified address. + * + * @note This function must be called before calling loadStateFromFRAM() or saveStateToFRAM(). + * @note This card takes up 3 bytes of FRAM memory. + * + * @param fram The FRAM object. + * @param fram_address The starting address of the card in FRAM memory. + */ void ClimateCard::bindFRAM(FRAM *fram, uint16_t fram_address) { this->fram = fram; this->fram_address = fram_address; } +/** + * @brief Set whether the state should be automatically saved to FRAM memory. + * + * @note This function has no effect if bindFRAM() has not been called. + * @param autoSave Whether the state should be automatically saved to FRAM memory. + */ void ClimateCard::setFRAMAutoSave(bool autoSave) { this->fram_auto_save = autoSave; } +/** + * @brief Save the state to FRAM memory. + * @note This function has no effect if bindFRAM() has not been called. + */ void ClimateCard::saveStateToFRAM() { + if (fram == nullptr) + return; fram->write8(fram_address, state.ac_temperature); fram->write8(fram_address + 1, state.ac_mode); fram->write8(fram_address + 2, state.ac_fan_speed); } +/** + * @brief Load the state from FRAM memory. + * + * @note This function has no effect if bindFRAM() has not been called. + */ void ClimateCard::loadStateFromFRAM() { + if (fram == nullptr) + return; if (state.ac_temperature > ac.max_temperature) state.ac_temperature = ac.max_temperature; else if (state.ac_temperature < ac.min_temperature) @@ -102,12 +168,18 @@ void ClimateCard::loadStateFromFRAM() if (state.ac_fan_speed > ac.fan_speeds) state.ac_fan_speed = 0; updateAirConditioner(); - for (const auto& callback : callbacks) + for (const auto &callback : callbacks) { callback.second(this->state.ac_mode, this->state.ac_fan_speed, this->state.ac_temperature); } } +/** + * @brief Set the temperature of the air conditioner. + * + * @param temperature The temperature to set. + * @note If the temperature is out of range, it will be set to its respective maximum or minimum. + */ void ClimateCard::setTemperature(uint8_t temperature) { // If temperature is out of range, set to its respective maximum or minimum @@ -121,33 +193,64 @@ void ClimateCard::setTemperature(uint8_t temperature) saveStateToFRAM(); } +/** + * @brief Set the mode of the air conditioner. + * + * @note If the mode is out of range, it will be set to 0. + * @param mode The mode to set. + */ void ClimateCard::setMode(uint8_t mode) { + if (mode > ac.modes) + mode = 0; this->state.ac_mode = mode; updateAirConditioner(); if (fram_auto_save) saveStateToFRAM(); } -char* ClimateCard::getModeName() +/** + * @brief Get the name of the current mode. + * @return The name of the current mode. + */ +char *ClimateCard::getModeName() { - return (char*)ac.mode_names[state.ac_mode]; + return (char *)ac.mode_names[state.ac_mode]; } -char* ClimateCard::getFanSpeedName() +/** + * @brief Get the name of the current fan speed. + * + * @return The name of the current fan speed. + */ +char *ClimateCard::getFanSpeedName() { - return (char*)ac.fan_speed_names[state.ac_fan_speed]; + return (char *)ac.fan_speed_names[state.ac_fan_speed]; } +/** + * @brief Set the fan speed of the air conditioner. + * + * @note If the fan speed is out of range, it will be set to 0. + * @param fan_speed The fan speed to set. + */ void ClimateCard::setFanSpeed(uint8_t fan_speed) { + if (fan_speed > ac.fan_speeds) + fan_speed = 0; this->state.ac_fan_speed = fan_speed; updateAirConditioner(); if (fram_auto_save) saveStateToFRAM(); } -void ClimateCard::setFanSpeedByName(const char* fan_speed_name) +/** + * @brief Set fan speed by name. + * + * @param fan_speed_name The name of the fan speed to set. + * @note If the fan speed is not found, the function will not do anything. + */ +void ClimateCard::setFanSpeedByName(const char *fan_speed_name) { for (uint8_t i = 0; i < ac.fan_speeds; i++) { @@ -159,7 +262,13 @@ void ClimateCard::setFanSpeedByName(const char* fan_speed_name) } } -void ClimateCard::setModeByName(const char* mode_name) +/** + * @brief Set mode by name. + * + * @param mode_name The name of the mode to set. + * @note If the mode is not found, the function will not do anything. + */ +void ClimateCard::setModeByName(const char *mode_name) { for (uint8_t i = 0; i < ac.modes; i++) { @@ -171,17 +280,36 @@ void ClimateCard::setModeByName(const char* mode_name) } } +/** + * @brief Register a callback function that will be called when the state of the air conditioner changes. + * + * @param callback The callback function to register. + * + * @return uint8_t The handler of the callback function. + */ uint8_t ClimateCard::registerChangeCallback(std::function callback) { callbacks[callbacks_handler_count] = callback; return callbacks_handler_count++; } +/** + * @brief Get the type of the card. + * + * @return The handler of the callback function. + */ uint8_t ClimateCard::getType() { return CARD_TYPE_CLIMATE; } +/** + * @brief update environmental sensor data. + * + * @note This function is called automatically by the loop() function. + * @note This function has no effect if no sensor is connected to the card. + * @note This function also calls the sensor callbacks. + */ void ClimateCard::updateSensor() { if (sensor_type == AC_SENSOR_TYPE_NONE) @@ -209,17 +337,23 @@ void ClimateCard::updateSensor() room_temperature = ds18b20->getTempC(); break; } - for (const auto& callback : sensor_callbacks) + for (const auto &callback : sensor_callbacks) { callback.second(room_temperature, humidity); } } +/** + * @brief Update the air conditioner state to match the state of the card. + * + * @warning This function is not working yet. + */ void ClimateCard::updateAirConditioner() { + // // The IR Transmissions are not working yet so we just return // const uint16_t* ir_code_ptr = nullptr; // size_t itemCount = (*(this->ac.getInfraredCode))(this->state.ac_mode, this->state.ac_fan_speed, this->state.ac_temperature, &ir_code_ptr); - + // if (ir_code_ptr == nullptr) // return; @@ -236,53 +370,100 @@ void ClimateCard::updateAirConditioner() // rmt_write_items(RMT_TX_CHANNEL, items, itemCount, true); // rmt_wait_tx_done(RMT_TX_CHANNEL, portMAX_DELAY); // // Publish state - for (const auto& callback : callbacks) + for (const auto &callback : callbacks) { callback.second(this->state.ac_mode, this->state.ac_fan_speed, this->state.ac_temperature); } } +/** + * @brief Get the type of the sensor connected to the card. + * + * @return The type of the sensor connected to the card. + */ uint8_t ClimateCard::getSensorType() { return sensor_type; } +/** + * @brief Get the room temperature in degrees Celsius. + * + * @return The room temperature. + */ float ClimateCard::getRoomTemperature() { return room_temperature; } +/** + * @brief Get the humidity in percent. + * + * @return The humidity. + */ float ClimateCard::getHumidity() { return humidity; } +/** + * @brief Get the temperature of the air conditioner. + * + * @return The temperature of the air conditioner. + */ uint8_t ClimateCard::getTemperature() { return state.ac_temperature; } +/** + * @brief Get the mode of the air conditioner. + * + * @return The mode of the air conditioner. + */ uint8_t ClimateCard::getMode() { return state.ac_mode; } +/** + * @brief Get the fan speed of the air conditioner. + * + * @return The fan speed of the air conditioner. + */ uint8_t ClimateCard::getFanSpeed() { return state.ac_fan_speed; } +/** + * @brief Register a callback function that will be called when the sensor data changes. + * + * @param callback The callback function to register. + * + * @return The handler of the callback function + */ uint8_t ClimateCard::registerSensorCallback(std::function callback) { sensor_callbacks[sensor_callbacks_handler_count] = callback; return sensor_callbacks_handler_count++; } +/** + * @brief Unregister a callback function. + * + * @param handler The handler of the callback function to unregister. + */ void ClimateCard::unregisterChangeCallback(uint8_t handler) { callbacks.erase(handler); } +/** + * @brief Unregister a sensor callback function. + * + * @param handler The handler of the callback function to unregister. + */ void ClimateCard::unregisterSensorCallback(uint8_t handler) { sensor_callbacks.erase(handler); diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ClimateCard.hpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ClimateCard.hpp index f17ad50..a194bd0 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ClimateCard.hpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ClimateCard.hpp @@ -18,22 +18,38 @@ #define AC_SENSOR_READ_INTERVAL 5000 #define AC_SENSOR_READ_TIMEOUT 250 +/** + * @brief The struct is used to store the state of the air conditioner + * + * @note This struct is stored in FRAM if it is used + * @note This struct is 3 bytes long + */ struct ClimateCardData { - uint8_t ac_temperature; - uint8_t ac_mode; - uint8_t ac_fan_speed; + uint8_t ac_temperature; ///< Temperature of the air conditioner + uint8_t ac_mode; ///< Mode of the air conditioner + uint8_t ac_fan_speed;///< Fan speed of the air conditioner }; +/** + * @brief This struct is used to store information about an air conditioner + */ struct AirConditioner { - uint8_t max_temperature; - uint8_t min_temperature; - uint8_t modes; - const char **mode_names; - uint8_t fan_speeds; - const char **fan_speed_names; - // function to get IR code - // takes 3 arguments: mode, fan speed, temperature, all uint8_t - // return size of IR code array + uint8_t max_temperature; ///< Maximum temperature + uint8_t min_temperature; ///< Minimum temperature + uint8_t modes; ///< Number of modes + const char **mode_names; ///< Names of modes in the form of an array of strings + uint8_t fan_speeds; ///< Number of fan speeds + const char **fan_speed_names; ///< Names of fan speeds in the form of an array of strings + /** + * @brief Function to get IR code + * + * @param mode Mode of the air conditioner + * @param fan_speed Fan speed of the air conditioner + * @param temperature Temperature of the air conditioner + * @param code Pointer to the IR code array + * + * @return Size of the IR code array + */ size_t (*getInfraredCode)(uint8_t, uint8_t, uint8_t, const uint16_t**); }; // This requires 3 bytes of FRAM diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ClimateIoT.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ClimateIoT.cpp index d2f8813..e6e179c 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ClimateIoT.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ClimateIoT.cpp @@ -1,13 +1,29 @@ #include + ClimateIoT::ClimateIoT() { } +/** + * @brief Destructor for the ClimateIoT class. + */ ClimateIoT::~ClimateIoT() { // Destructor implementation } +/** + * @brief Initializes the ClimateIoT component. + * + * This function sets the MQTT client, base topic, card ID, and card pointer. + * It also registers the sensor and air conditioner update callbacks. + * + * @param card_id The ID of the expansion card. + * @param card A pointer to the ExpansionCard object. + * @param mqtt A pointer to the PubSubClient object. + * @param base_topic The base topic for MQTT communication. + * @return True if the initialization is successful, false otherwise. + */ bool ClimateIoT::begin(uint8_t card_id, ExpansionCard *card, PubSubClient *mqtt, char *base_topic) { this->mqtt = mqtt; this->base_topic = base_topic; @@ -22,6 +38,12 @@ bool ClimateIoT::begin(uint8_t card_id, ExpansionCard *card, PubSubClient *mqtt, return true; } +/** + * @brief Handles MQTT messages for the ClimateIoT component. + * + * @param topic The trimmed topic of the MQTT message. + * @param payload The null-terminated payload of the MQTT message. + */ void ClimateIoT::handleMqttMessage(char *topic, char *payload) { uint8_t topic_length = strlen(topic); if (this->processSetTemperatureMessage(topic, payload, topic_length)) @@ -34,31 +56,49 @@ void ClimateIoT::handleMqttMessage(char *topic, char *payload) { return; } +/** + * @brief Publishes the temperature of the air conditioner to the MQTT broker. + */ void ClimateIoT::publishClimateTemperature() { char payload[5]; itoa(this->card->getTemperature(), payload, 10); this->publishRelative(AC_TEMPERATURE_REPORT_TOPIC, payload); } +/** + * @brief Publishes the mode of the air conditioner to the MQTT broker. + */ void ClimateIoT::publishClimateMode() { this->publishRelative(AC_MODE_REPORT_TOPIC, this->card->getModeName()); } +/** + * @brief Publishes the fan speed of the air conditioner to the MQTT broker. + */ void ClimateIoT::publishClimateFanSpeed() { this->publishRelative(AC_FAN_SPEED_REPORT_TOPIC, this->card->getFanSpeedName()); } +/** + * @brief Publishes the temperature and humidity of the room to the MQTT broker. + */ void ClimateIoT::publishSensor() { this->publishRoomTemperature(); this->publishHumidity(); } +/** + * @brief Publishes the climate data (temperature, mode, fan speed) to the MQTT broker. + */ void ClimateIoT::publishClimate() { this->publishClimateTemperature(); this->publishClimateMode(); this->publishClimateFanSpeed(); } +/** + * @brief Publishes the room temperature to the MQTT broker. + */ void ClimateIoT::publishRoomTemperature() { if (this->card->getSensorType() == AC_SENSOR_TYPE_NONE ) { return; @@ -68,6 +108,9 @@ void ClimateIoT::publishRoomTemperature() { this->publishRelative(AC_ROOM_TEMPERATURE_REPORT_TOPIC, payload); } +/** + * @brief Publishes the humidity of the room to the MQTT broker. + */ void ClimateIoT::publishHumidity() { if (this->card->getSensorType() == AC_SENSOR_TYPE_DHT22) { char payload[5]; @@ -76,15 +119,30 @@ void ClimateIoT::publishHumidity() { } } +/** + * @brief Handle Air Conditioner state change. + * + * @note This function is called by the underlying ClimateCard object and is not meant to be called manually. + * + * @param temperature Temperature of the air conditioner + * @param mode Mode of the air conditioner + * @param fan_speed Fan speed of the air conditioner + */ void ClimateIoT::handleStateChange(uint8_t temperature, uint8_t mode, uint8_t fan_speed) { this->publishClimate(); } +/** + * @brief Publishes the climate and sensor data to the MQTT broker. + */ void ClimateIoT::publishReport() { this->publishClimate(); this->publishSensor(); } +/** + * @brief Subscribes to MQTT topics. + */ void ClimateIoT::subscribe() { ESP_LOGD("ClimateIoT", " topics"); this->subscribeRelative(AC_TEMPERATURE_SET_TOPIC); @@ -93,14 +151,32 @@ void ClimateIoT::subscribe() { ESP_LOGD("ClimateIoT", "Subscribed to topics"); } +/** + * @brief The loop function for the ClimateIoT component. + * + * @note This function does nothing. + */ void ClimateIoT::loop() { } +/** + * @brief Returns the type of the expansion card. + * + * @return The type of the expansion card. + */ uint8_t ClimateIoT::getType() { return CARD_TYPE_CLIMATE; } +/** + * @brief Processes the set temperature MQTT message. + * + * @param topic The trimmed topic of the MQTT message. + * @param payload The null-terminated payload of the MQTT message. + * @param topic_length The length of the topic. + * @return True if the message is processed, false otherwise. + */ bool ClimateIoT::processSetTemperatureMessage(char *topic, char *payload, uint8_t topic_length) { if (!strcmp(topic, AC_TEMPERATURE_SET_TOPIC)) { uint8_t temperature = atoi(payload); @@ -110,6 +186,14 @@ bool ClimateIoT::processSetTemperatureMessage(char *topic, char *payload, uint8_ return false; } +/** + * @brief Processes the set mode MQTT message. + * + * @param topic The trimmed topic of the MQTT message. + * @param payload The null-terminated payload of the MQTT message. + * @param topic_length The length of the topic. + * @return True if the message is processed, false otherwise. + */ bool ClimateIoT::processSetModeMessage(char *topic, char *payload, uint8_t topic_length) { if (!strcmp(topic, AC_MODE_SET_TOPIC)) { this->card->setModeByName(payload); @@ -118,6 +202,14 @@ bool ClimateIoT::processSetModeMessage(char *topic, char *payload, uint8_t topic return false; } +/** + * @brief Processes the set fan speed MQTT message. + * + * @param topic The trimmed topic of the MQTT message. + * @param payload The null-terminated payload of the MQTT message. + * @param topic_length The length of the topic. + * @return True if the message is processed, false otherwise. + */ bool ClimateIoT::processSetFanSpeedMessage(char *topic, char *payload, uint8_t topic_length) { if (!strcmp(topic, AC_FAN_SPEED_SET_TOPIC)) { this->card->setFanSpeedByName(payload); @@ -125,6 +217,14 @@ bool ClimateIoT::processSetFanSpeedMessage(char *topic, char *payload, uint8_t t return false; } +/** + * @brief Processes the request state MQTT message. + * + * @param topic The trimmed topic of the MQTT message. + * @param payload The null-terminated payload of the MQTT message. + * @param topic_length The length of the topic. + * @return True if the message is processed, false otherwise. + */ bool ClimateIoT::processRequestStateMessage(char *topic, char *payload, uint8_t topic_length) { if (!strcmp(topic, AC_REQUEST_STATE_TOPIC)) { this->publishReport(); @@ -133,10 +233,25 @@ bool ClimateIoT::processRequestStateMessage(char *topic, char *payload, uint8_t return false; } +/** + * @brief This function is a callback function registered with the Climate card to be called when the sensor data is updated. + * + * @param temperature The room temperature. + * @param humidity The room humidity. + * + * @note The temperature and humidity are not used in this function but are required by the ClimateCard class to match the signature of the callback function. + */ void ClimateIoT::handleSensorUpdate(float temperature, float humidity) { this->publishSensor(); } +/** + * @brief This function is a callback function registered with the Climate card to be called when the air conditioner state is updated. + * + * @param mode The mode of the air conditioner. + * @param fan_speed The fan speed of the air conditioner. + * @param temperature The temperature of the air conditioner. + */ void ClimateIoT::handleAirConditionerUpdate(uint8_t mode, uint8_t fan_speed, uint8_t temperature) { this->publishClimate(); } \ No newline at end of file diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ClimateIoT.hpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ClimateIoT.hpp index 18e6d80..072b3de 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ClimateIoT.hpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ClimateIoT.hpp @@ -3,6 +3,7 @@ #include #include +// MQTT Topics #define AC_MODE_REPORT_TOPIC "mode" #define AC_MODE_SET_TOPIC "set/mode" #define AC_TEMPERATURE_REPORT_TOPIC "temperature" diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalInputCard.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalInputCard.cpp index 3bb7493..86ad5a1 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalInputCard.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalInputCard.cpp @@ -1,15 +1,33 @@ #include -// Instantiate the card with the specified address +/** + * @brief Create a new Digital Input Card object with the specified address + * @note If you are using the ESPMegaI/O board, you should use the dip switch constructor + * + * @param address_a The ESPMegaI/O address of bank A + * @param address_b The ESPMegaI/O address of bank B + */ DigitalInputCard::DigitalInputCard(uint8_t address_a, uint8_t address_b) : callbacks() { this->address_a = address_a; this->address_b = address_b; this->callbacks_handler_index = 0; } -// Instantiate the card with the specified position on the dip switch -// Bit 0,1,2 are for bank A -// Bit 3,4,5 are for bank B + +/** + * @brief Create a new Digital Input 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 6 switches on the dip switch, 3 for bank A and 3 for bank B, They should be unique for each bank 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 + * @param bit5 The position of the sixth switch on the dip switch + */ DigitalInputCard::DigitalInputCard(bool bit0, bool bit1, bool bit2, bool bit3, bool bit4, bool bit5) { this->address_a = 0x20; @@ -29,7 +47,12 @@ DigitalInputCard::DigitalInputCard(bool bit0, bool bit1, bool bit2, bool bit3, b if (bit5) this->address_b += 4; } -// Initialize the card + +/** + * @brief Initialize the Digital Input Card + * + * @return True if the initialization is successful, false otherwise + */ bool DigitalInputCard::begin() { this->inputBankA = PCF8574(this->address_a); @@ -56,12 +79,25 @@ bool DigitalInputCard::begin() } return true; } -// Refresh and Read the input from the specified pin, always refresh the input buffers + +/** + * @brief Read the input from the specified pin, always refresh the input buffers + * + * @param pin The pin to read from + * @return True if the pin is HIGH, false if the pin is LOW + */ bool DigitalInputCard::digitalRead(uint8_t pin) { return this->digitalRead(pin, true); } -// Read the input from the specified pin, also refresh the input buffers if refresh is true + +/** + * @brief Read the input from the specified pin, also refresh the input buffers if refresh is true + * + * @param pin The pin to read from + * @param refresh If true, the input buffers will be refreshed before reading the pin + * @return True if the pin is HIGH, false if the pin is LOW + */ bool DigitalInputCard::digitalRead(uint8_t pin, bool refresh) { pin = pinMap[pin]; @@ -85,6 +121,15 @@ bool DigitalInputCard::digitalRead(uint8_t pin, bool refresh) return 255; } +/** + * @brief Check if the specified pin changed since the last call to this function + * + * @note This function compares the current input buffer with the previous input buffer to detect changes + * + * @param pin The pin to check + * @param currentBuffer The current input buffer + * @param previousBuffer The previous input buffer + */ void DigitalInputCard::handlePinChange(int pin, uint8_t ¤tBuffer, uint8_t &previousBuffer) { // Get the index of the pin in the pin map @@ -113,7 +158,11 @@ void DigitalInputCard::handlePinChange(int pin, uint8_t ¤tBuffer, uint8_t } } - +/** + * @brief A loop to refresh the input buffers and check for pin changes + * + * @note Although this function can be called in the main loop, it is recommended install the card in ESPMega to automatically manage the loop + */ // Preform a loop to refresh the input buffers void DigitalInputCard::loop() { @@ -134,7 +183,12 @@ void DigitalInputCard::loop() } } } -// Get the input buffer for bank A + +/** + * @brief Get the input buffer for bank A (the first 8 pins) + * + * @return The input buffer for bank A where the first bit is the first pin and the last bit is the last pin + */ uint8_t DigitalInputCard::getInputBufferA() { // Rearrange the bits to match the pin map @@ -145,7 +199,12 @@ uint8_t DigitalInputCard::getInputBufferA() } return inputBufferA_rearranged; } -// Get the input buffer for bank B + +/** + * @brief Get the input buffer for bank B (the last 8 pins) + * + * @return The input buffer for bank B where the first bit is the first pin and the last bit is the last pin + */ uint8_t DigitalInputCard::getInputBufferB() { // Rearrange the bits to match the pin map @@ -156,35 +215,71 @@ uint8_t DigitalInputCard::getInputBufferB() } return inputBufferB_rearranged; } -// Register a callback function to be called when a pin changes + +/** + * @brief Register a callback function to be called when a pin changes + * + * @param callback The callback function to be called + * @return The handler of the callback function + */ uint8_t DigitalInputCard::registerCallback(std::function callback) { callbacks[this->callbacks_handler_index] = callback; return this->callbacks_handler_index++; } -// Refresh the input buffer for bank A +/** + * @brief Read the input state from the input ic and store it in the input buffer for bank A + */ void DigitalInputCard::refreshInputBankA() { inputBufferA = inputBankA.read8(); } -// Refresh the input buffer for bank B + +/** + * @brief Read the input state from the input ic and store it in the input buffer for bank B + */ void DigitalInputCard::refreshInputBankB() { inputBufferB = inputBankB.read8(); } +/** + * @brief Set the debounce time for the specified pin + * + * Debounce is the time in milliseconds that the pin should be stable before the callback function is called + * This is useful to prevent false triggers when the input is noisy + * An example of this is when the input is connected to a mechanical switch + * + * @param pin The pin to set the debounce time for + * @param debounceTime The debounce time in milliseconds + */ void DigitalInputCard::setDebounceTime(uint8_t pin, uint32_t debounceTime) { pin = pinMap[pin]; this->debounceTime[pin] = debounceTime; } +/** + * @brief Unregister a callback function + * + * @param handler The handler of the callback function to unregister + */ void DigitalInputCard::unregisterCallback(uint8_t handler) { callbacks.erase(handler); } +/** + * @brief Load the pin map for the card + * + * 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 Input 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 DigitalInputCard::loadPinMap(uint8_t pinMap[16]) { for (int i = 0; i < 16; i++) @@ -196,6 +291,11 @@ void DigitalInputCard::loadPinMap(uint8_t pinMap[16]) } } +/** + * @brief Get the type of the card + * + * @return The type of the card + */ uint8_t DigitalInputCard::getType() { return CARD_TYPE_DIGITAL_INPUT; diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalInputCard.hpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalInputCard.hpp index d428d30..0464347 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalInputCard.hpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalInputCard.hpp @@ -3,6 +3,7 @@ #include #include +// Card Type #define CARD_TYPE_DIGITAL_INPUT 0x01 class DigitalInputCard : public ExpansionCard { diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalInputIoT.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalInputIoT.cpp index 2f7529e..7b7a6b0 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalInputIoT.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalInputIoT.cpp @@ -1,6 +1,20 @@ #include +/** + * @brief Initializes the DigitalInputIoT object. + * + * This function sets the necessary parameters for the DigitalInputIoT object, such as the card ID, expansion card, MQTT client, and base topic. + * It also enables the publishing of digital input values and registers a callback function for handling value changes. + * + * @note Although this function can be called in the main program, it is recommended to use ESPMegaIoT::registerCard() to automatically manage the instantiation and initialization of this component. + * + * @param card_id The ID of the card. + * @param card Pointer to the DigitalInputCard object. + * @param mqtt Pointer to the PubSubClient object. + * @param base_topic The base topic for MQTT communication. + * @return True if the initialization is successful, false otherwise. + */ bool DigitalInputIoT::begin(uint8_t card_id, ExpansionCard *card, PubSubClient *mqtt, char *base_topic) { this->card = (DigitalInputCard *)card; this->card_id = card_id; @@ -12,10 +26,19 @@ bool DigitalInputIoT::begin(uint8_t card_id, ExpansionCard *card, PubSubClient * } +/** + * @brief Subscribes to the MQTT topics for the DigitalInputIoT component. + */ void DigitalInputIoT::subscribe() { this->subscribeRelative(PUBLISH_ENABLE_TOPIC); } +/** + * @brief Handles MQTT messages for the DigitalInputIoT component. + * + * @param topic The trimmed topic of the MQTT message. + * @param payload The null-terminated payload of the MQTT message. + */ void DigitalInputIoT::handleMqttMessage(char *topic, char *payload) { // payload is char '0' or '1' if (!strcmp(topic, PUBLISH_ENABLE_TOPIC)) { @@ -26,6 +49,10 @@ void DigitalInputIoT::handleMqttMessage(char *topic, char *payload) { } } } + +/** + * @brief Publish all digital inputs to the MQTT broker. + */ void DigitalInputIoT::publishDigitalInputs() { if (!this->digital_inputs_publish_enabled) { return; @@ -34,18 +61,41 @@ void DigitalInputIoT::publishDigitalInputs() { this->publishDigitalInput(i); } } + +/** + * @brief Set if the digital inputs should be published to the MQTT broker. + * + * @param enabled True if the digital inputs should be published, false otherwise. + */ void DigitalInputIoT::setDigitalInputsPublishEnabled(bool enabled) { this->digital_inputs_publish_enabled = enabled; if (enabled) { this->publishDigitalInputs(); } } + +/** + * @brief Handles a value change for a digital input. + * + * @note This function is registered as a callback function for the DigitalInputCard object. + * + * @param pin The pin that changed. + * @param value The new value of the pin. + */ void DigitalInputIoT::handleValueChange(uint8_t pin, uint8_t value) { if (this->digital_inputs_publish_enabled) { this->publishDigitalInput(pin); } } + +/** + * @brief Publish all inputs to the MQTT Broker + * + * @note This function is overriden from the IoTComponent class and is called by ESPMegaIoT. + * + * @param pin The pin to publish. + */ void DigitalInputIoT::publishReport() { this->publishDigitalInputs(); } @@ -53,7 +103,11 @@ uint8_t DigitalInputIoT::getType() { return CARD_TYPE_DIGITAL_INPUT; } - +/** + * @brief Publish a digital input to the MQTT broker. + * + * @param pin The pin to publish. + */ void DigitalInputIoT::publishDigitalInput(uint8_t pin) { char topic[20] = {0}; char payload[20] = {0}; diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalInputIoT.hpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalInputIoT.hpp index 7eeb100..7b1a636 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalInputIoT.hpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalInputIoT.hpp @@ -4,6 +4,7 @@ #include #include +// MQTT Topics #define PUBLISH_ENABLE_TOPIC "publish_enable" class DigitalInputIoT : public IoTComponent {