2023-12-30 07:32:40 +00:00
|
|
|
#include <ClimateIoT.hpp>
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
|
2023-12-30 07:32:40 +00:00
|
|
|
ClimateIoT::ClimateIoT() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @brief Destructor for the ClimateIoT class.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
ClimateIoT::~ClimateIoT() {
|
|
|
|
// Destructor implementation
|
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
bool ClimateIoT::begin(uint8_t card_id, ExpansionCard *card, PubSubClient *mqtt, char *base_topic) {
|
2023-12-31 16:29:40 +00:00
|
|
|
this->mqtt = mqtt;
|
|
|
|
this->base_topic = base_topic;
|
|
|
|
this->card_id = card_id;
|
2023-12-30 07:32:40 +00:00
|
|
|
this->card = (ClimateCard *)card;
|
|
|
|
// Reister Callbacks
|
|
|
|
auto bindedSensorCallback = std::bind(&ClimateIoT::handleSensorUpdate, this, std::placeholders::_1, std::placeholders::_2);
|
|
|
|
this->card->registerSensorCallback(bindedSensorCallback);
|
|
|
|
auto bindedAirConditionerCallback = std::bind(&ClimateIoT::handleAirConditionerUpdate, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
|
|
|
this->card->registerChangeCallback(bindedAirConditionerCallback);
|
2023-12-31 16:29:40 +00:00
|
|
|
ESP_LOGD("ClimateIoT", "Climate IoT Component initialized");
|
2023-12-30 07:42:52 +00:00
|
|
|
return true;
|
2023-12-30 07:32:40 +00:00
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
void ClimateIoT::handleMqttMessage(char *topic, char *payload) {
|
|
|
|
uint8_t topic_length = strlen(topic);
|
|
|
|
if (this->processSetTemperatureMessage(topic, payload, topic_length))
|
|
|
|
return;
|
|
|
|
if (this->processSetModeMessage(topic, payload, topic_length))
|
|
|
|
return;
|
|
|
|
if (this->processSetFanSpeedMessage(topic, payload, topic_length))
|
|
|
|
return;
|
|
|
|
if (this->processRequestStateMessage(topic, payload, topic_length))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @brief Publishes the temperature of the air conditioner to the MQTT broker.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
void ClimateIoT::publishClimateTemperature() {
|
|
|
|
char payload[5];
|
|
|
|
itoa(this->card->getTemperature(), payload, 10);
|
|
|
|
this->publishRelative(AC_TEMPERATURE_REPORT_TOPIC, payload);
|
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @brief Publishes the mode of the air conditioner to the MQTT broker.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
void ClimateIoT::publishClimateMode() {
|
2023-12-31 17:07:11 +00:00
|
|
|
this->publishRelative(AC_MODE_REPORT_TOPIC, this->card->getModeName());
|
2023-12-30 07:32:40 +00:00
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @brief Publishes the fan speed of the air conditioner to the MQTT broker.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
void ClimateIoT::publishClimateFanSpeed() {
|
2023-12-31 17:07:11 +00:00
|
|
|
this->publishRelative(AC_FAN_SPEED_REPORT_TOPIC, this->card->getFanSpeedName());
|
2023-12-30 07:32:40 +00:00
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @brief Publishes the temperature and humidity of the room to the MQTT broker.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
void ClimateIoT::publishSensor() {
|
|
|
|
this->publishRoomTemperature();
|
|
|
|
this->publishHumidity();
|
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @brief Publishes the climate data (temperature, mode, fan speed) to the MQTT broker.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
void ClimateIoT::publishClimate() {
|
|
|
|
this->publishClimateTemperature();
|
|
|
|
this->publishClimateMode();
|
|
|
|
this->publishClimateFanSpeed();
|
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @brief Publishes the room temperature to the MQTT broker.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
void ClimateIoT::publishRoomTemperature() {
|
2023-12-31 17:31:28 +00:00
|
|
|
if (this->card->getSensorType() == AC_SENSOR_TYPE_NONE ) {
|
|
|
|
return;
|
|
|
|
}
|
2023-12-30 07:32:40 +00:00
|
|
|
char payload[5];
|
|
|
|
itoa(this->card->getRoomTemperature(), payload, 10);
|
|
|
|
this->publishRelative(AC_ROOM_TEMPERATURE_REPORT_TOPIC, payload);
|
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @brief Publishes the humidity of the room to the MQTT broker.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
void ClimateIoT::publishHumidity() {
|
|
|
|
if (this->card->getSensorType() == AC_SENSOR_TYPE_DHT22) {
|
|
|
|
char payload[5];
|
|
|
|
itoa(this->card->getHumidity(), payload, 10);
|
|
|
|
this->publishRelative(AC_HUMIDITY_REPORT_TOPIC, payload);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @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
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
void ClimateIoT::handleStateChange(uint8_t temperature, uint8_t mode, uint8_t fan_speed) {
|
|
|
|
this->publishClimate();
|
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @brief Publishes the climate and sensor data to the MQTT broker.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
void ClimateIoT::publishReport() {
|
|
|
|
this->publishClimate();
|
|
|
|
this->publishSensor();
|
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @brief Subscribes to MQTT topics.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
void ClimateIoT::subscribe() {
|
2023-12-31 16:29:40 +00:00
|
|
|
ESP_LOGD("ClimateIoT", " topics");
|
2023-12-30 07:32:40 +00:00
|
|
|
this->subscribeRelative(AC_TEMPERATURE_SET_TOPIC);
|
|
|
|
this->subscribeRelative(AC_MODE_SET_TOPIC);
|
|
|
|
this->subscribeRelative(AC_FAN_SPEED_SET_TOPIC);
|
2024-05-17 14:29:50 +00:00
|
|
|
this->subscribeRelative(AC_REQUEST_STATE_TOPIC);
|
2023-12-31 16:29:40 +00:00
|
|
|
ESP_LOGD("ClimateIoT", "Subscribed to topics");
|
2023-12-30 07:32:40 +00:00
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @brief The loop function for the ClimateIoT component.
|
|
|
|
*
|
|
|
|
* @note This function does nothing.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
void ClimateIoT::loop() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @brief Returns the type of the expansion card.
|
|
|
|
*
|
|
|
|
* @return The type of the expansion card.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
uint8_t ClimateIoT::getType() {
|
|
|
|
return CARD_TYPE_CLIMATE;
|
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
bool ClimateIoT::processSetTemperatureMessage(char *topic, char *payload, uint8_t topic_length) {
|
|
|
|
if (!strcmp(topic, AC_TEMPERATURE_SET_TOPIC)) {
|
|
|
|
uint8_t temperature = atoi(payload);
|
|
|
|
this->card->setTemperature(temperature);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
bool ClimateIoT::processSetModeMessage(char *topic, char *payload, uint8_t topic_length) {
|
|
|
|
if (!strcmp(topic, AC_MODE_SET_TOPIC)) {
|
2023-12-31 17:07:11 +00:00
|
|
|
this->card->setModeByName(payload);
|
2023-12-30 07:32:40 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
bool ClimateIoT::processSetFanSpeedMessage(char *topic, char *payload, uint8_t topic_length) {
|
|
|
|
if (!strcmp(topic, AC_FAN_SPEED_SET_TOPIC)) {
|
2023-12-31 17:07:11 +00:00
|
|
|
this->card->setFanSpeedByName(payload);
|
2023-12-30 07:32:40 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2023-12-30 07:32:40 +00:00
|
|
|
bool ClimateIoT::processRequestStateMessage(char *topic, char *payload, uint8_t topic_length) {
|
|
|
|
if (!strcmp(topic, AC_REQUEST_STATE_TOPIC)) {
|
|
|
|
this->publishReport();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2023-12-30 08:39:16 +00:00
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2023-12-30 08:39:16 +00:00
|
|
|
void ClimateIoT::handleSensorUpdate(float temperature, float humidity) {
|
|
|
|
this->publishSensor();
|
|
|
|
}
|
|
|
|
|
2023-12-31 18:38:25 +00:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2023-12-30 08:39:16 +00:00
|
|
|
void ClimateIoT::handleAirConditionerUpdate(uint8_t mode, uint8_t fan_speed, uint8_t temperature) {
|
|
|
|
this->publishClimate();
|
2023-12-30 07:32:40 +00:00
|
|
|
}
|