2024-01-16 04:22:41 +00:00
|
|
|
#include <RemoteVariable.hpp>
|
|
|
|
|
2024-02-10 07:26:41 +00:00
|
|
|
/**
|
|
|
|
* @brief Construct a new Remote Variable object
|
|
|
|
* This constructor does not take any arguments.
|
|
|
|
* Please use the begin method to initialize the object.
|
|
|
|
*/
|
2024-01-16 04:22:41 +00:00
|
|
|
RemoteVariable::RemoteVariable() {
|
|
|
|
this->topic = nullptr;
|
|
|
|
this->value = nullptr;
|
|
|
|
}
|
2024-02-10 07:26:41 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Destroy the Remote Variable object
|
|
|
|
* This destructor does not take any arguments.
|
|
|
|
* It will free the memory allocated for the topic and value.
|
|
|
|
*/
|
2024-01-16 04:22:41 +00:00
|
|
|
RemoteVariable::~RemoteVariable() {
|
2024-02-10 07:26:41 +00:00
|
|
|
free(this->value);
|
2024-01-16 04:22:41 +00:00
|
|
|
}
|
2024-02-10 07:26:41 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Initialize the RemoteVariable object with value request
|
|
|
|
*
|
|
|
|
* This method is used to initialize the RemoteVariable object.
|
|
|
|
*
|
|
|
|
* @param size The maximum size of the variable in bytes
|
|
|
|
* @param topic The topic that the variable is published to
|
|
|
|
* @param iot The ESPMegaIoT object
|
|
|
|
* @param useValueRequest Whether to use value request
|
|
|
|
* @param valueRequestTopic The topic to request value
|
|
|
|
*
|
|
|
|
* @note Because the value is null terminated, the size should be the desired text length + 1
|
|
|
|
* @warning This use dynamic memory allocation, so it is important to call the destructor when the object is no longer needed
|
|
|
|
*/
|
2024-02-09 10:48:43 +00:00
|
|
|
void RemoteVariable::begin(size_t size, const char* topic, ESPMegaIoT* iot, bool useValueRequest, const char* valueRequestTopic) {
|
2024-01-16 04:22:41 +00:00
|
|
|
this->iot = iot;
|
|
|
|
this->size = size;
|
2024-02-09 10:48:43 +00:00
|
|
|
this->topic = topic;
|
|
|
|
this->useValueRequest = useValueRequest;
|
|
|
|
this->valueRequestTopic = valueRequestTopic;
|
2024-01-16 04:22:41 +00:00
|
|
|
value = (char*)calloc(size, sizeof(char));
|
|
|
|
auto bindedMqttCallback = std::bind(&RemoteVariable::mqtt_callback, this, std::placeholders::_1, std::placeholders::_2);
|
|
|
|
this->iot->registerMqttCallback(bindedMqttCallback);
|
|
|
|
auto bindedSubscribe = std::bind(&RemoteVariable::subscribe, this);
|
|
|
|
this->iot->registerSubscribeCallback(bindedSubscribe);
|
2024-02-09 10:48:43 +00:00
|
|
|
this->subscribe();
|
2024-01-16 04:22:41 +00:00
|
|
|
}
|
2024-01-16 05:48:06 +00:00
|
|
|
|
2024-02-10 07:26:41 +00:00
|
|
|
/**
|
|
|
|
* @brief Initialize the RemoteVariable object
|
|
|
|
*
|
|
|
|
* This method is used to initialize the RemoteVariable object.
|
|
|
|
*
|
|
|
|
* @param size The maximum size of the variable in bytes
|
|
|
|
* @param topic The topic that the variable is published to
|
|
|
|
* @param iot The ESPMegaIoT object
|
|
|
|
*
|
|
|
|
* @note Because the value is null terminated, the size should be the desired text length + 1
|
|
|
|
* @warning This use dynamic memory allocation, so it is important to call the destructor when the object is no longer needed
|
|
|
|
*/
|
2024-02-09 10:48:43 +00:00
|
|
|
void RemoteVariable::begin(size_t size, const char* topic, ESPMegaIoT* iot) {
|
2024-01-16 05:48:06 +00:00
|
|
|
this->begin(size, topic, iot, false, nullptr);
|
|
|
|
}
|
|
|
|
|
2024-02-10 07:26:41 +00:00
|
|
|
/**
|
|
|
|
* @brief Subscribe to the topic
|
|
|
|
* This method is used internally to subscribe to the topic from iot core
|
|
|
|
*/
|
2024-01-16 04:22:41 +00:00
|
|
|
void RemoteVariable::subscribe() {
|
2024-02-09 10:48:43 +00:00
|
|
|
ESP_LOGD("RemoteVariable", "Subscribing to %s", this->topic);
|
2024-01-16 04:22:41 +00:00
|
|
|
this->iot->subscribe(this->topic);
|
2024-01-16 05:48:06 +00:00
|
|
|
if(this->useValueRequest) {
|
2024-02-09 10:48:43 +00:00
|
|
|
ESP_LOGD("RemoteVariable", "Subscribing to %s", this->valueRequestTopic);
|
2024-02-05 16:47:53 +00:00
|
|
|
this->requestValue();
|
2024-01-16 05:48:06 +00:00
|
|
|
}
|
2024-01-16 04:22:41 +00:00
|
|
|
}
|
2024-02-10 07:26:41 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the value of the variable
|
|
|
|
*
|
|
|
|
* This method is used to get the value of the variable.
|
|
|
|
*
|
|
|
|
* @return char* The null terminated string of the value
|
|
|
|
*/
|
2024-01-16 04:22:41 +00:00
|
|
|
char* RemoteVariable::getValue() {
|
2024-02-09 10:48:43 +00:00
|
|
|
return this->value;
|
2024-01-16 04:22:41 +00:00
|
|
|
}
|
|
|
|
|
2024-02-10 07:26:41 +00:00
|
|
|
/**
|
|
|
|
* @brief The MQTT callback
|
|
|
|
* This method is binded to the MQTT callback in iot core
|
|
|
|
*/
|
2024-01-16 04:22:41 +00:00
|
|
|
void RemoteVariable::mqtt_callback(char* topic, char* payload) {
|
|
|
|
if (strcmp(topic, this->topic) == 0) {
|
2024-02-09 10:48:43 +00:00
|
|
|
ESP_LOGD("RemoteVariable", "Received MQTT message from %s", topic);
|
2024-01-16 04:22:41 +00:00
|
|
|
strcpy(this->value, payload);
|
2024-02-12 09:40:46 +00:00
|
|
|
for (auto& callback : this->valueChangeCallback) {
|
|
|
|
callback.second(this->value);
|
|
|
|
}
|
2024-01-16 04:22:41 +00:00
|
|
|
}
|
2024-01-16 05:48:06 +00:00
|
|
|
}
|
|
|
|
|
2024-02-10 07:26:41 +00:00
|
|
|
/**
|
|
|
|
* @brief Request the value of the variable
|
|
|
|
* This method request a value update from the device that has the variable
|
|
|
|
* @note This method is only functional if the useValueRequest is set to true
|
|
|
|
*/
|
2024-01-16 05:48:06 +00:00
|
|
|
void RemoteVariable::requestValue() {
|
|
|
|
if(!this->useValueRequest)
|
|
|
|
return;
|
2024-02-09 10:48:43 +00:00
|
|
|
ESP_LOGD("RemoteVariable", "Sending request to %s", this->valueRequestTopic);
|
2024-01-16 05:48:06 +00:00
|
|
|
this->iot->publish(this->valueRequestTopic, "request");
|
|
|
|
}
|
|
|
|
|
2024-02-10 07:26:41 +00:00
|
|
|
/**
|
|
|
|
* @brief Enable the set value feature
|
|
|
|
* This method is used to enable the set value feature
|
|
|
|
* @param setValueTopic The topic to send the value to
|
|
|
|
*/
|
2024-02-09 10:48:43 +00:00
|
|
|
void RemoteVariable::enableSetValue(const char* setValueTopic) {
|
2024-01-16 05:48:06 +00:00
|
|
|
this->useSetValue = true;
|
|
|
|
this->setValueTopic = setValueTopic;
|
|
|
|
}
|
|
|
|
|
2024-02-10 07:26:41 +00:00
|
|
|
/**
|
|
|
|
* @brief Set the value of the variable
|
|
|
|
* This method is used to set the value of the variable
|
|
|
|
* @param value The value to set
|
|
|
|
* @note This method is only functional if the enableSetValue is already called
|
|
|
|
*/
|
2024-02-09 10:48:43 +00:00
|
|
|
void RemoteVariable::setValue(const char* value) {
|
2024-01-16 05:48:06 +00:00
|
|
|
if(!this->useSetValue)
|
|
|
|
return;
|
|
|
|
this->iot->publish(this->setValueTopic, value);
|
2024-02-12 09:40:46 +00:00
|
|
|
}
|
|
|
|
|
2024-02-12 19:28:34 +00:00
|
|
|
/**
|
|
|
|
* @brief Register a callback for value change
|
|
|
|
* This method will be called when the value of the variable changes on the remote device
|
|
|
|
* @param callback The callback function
|
|
|
|
* @return uint8_t The handler for the callback
|
|
|
|
*/
|
2024-02-12 09:40:46 +00:00
|
|
|
uint8_t RemoteVariable::registerCallback(std::function<void(char*)> callback) {
|
|
|
|
this->valueChangeCallback[this->valueChangeCallbackCount] = callback;
|
|
|
|
return valueChangeCallbackCount++;
|
|
|
|
}
|
2024-02-12 19:28:34 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Unregister a callback
|
|
|
|
* This method is used to unregister a callback
|
|
|
|
* @param handler The handler of the callback
|
|
|
|
*/
|
2024-02-12 09:40:46 +00:00
|
|
|
void RemoteVariable::unregisterCallback(uint8_t handler) {
|
|
|
|
this->valueChangeCallback.erase(handler);
|
2024-02-12 19:28:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the value of the variable as an integer
|
|
|
|
* This method is used to get the value of the variable as an integer
|
|
|
|
* @return int The value of the variable as an integer
|
|
|
|
* @note If the value is not a valid integer, it will return 0
|
|
|
|
*/
|
|
|
|
int RemoteVariable::getValueAsInt() {
|
|
|
|
return atoi(this->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the value of the variable as a long
|
|
|
|
* This method is used to get the value of the variable as a long
|
|
|
|
* @return long The value of the variable as a long
|
|
|
|
* @note If the value is not a valid long, it will return 0
|
|
|
|
*/
|
|
|
|
long RemoteVariable::getValueAsLong() {
|
|
|
|
return atol(this->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the value of the variable as a double
|
|
|
|
* This method is used to get the value of the variable as a double
|
|
|
|
* @return double The value of the variable as a double
|
|
|
|
* @note If the value is not a valid double, it will return 0
|
|
|
|
*/
|
|
|
|
double RemoteVariable::getValueAsDouble() {
|
|
|
|
return atof(this->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Set the value of the variable as an integer
|
|
|
|
* This method is used to set the value of the variable as an integer
|
|
|
|
* @param value The value to set
|
|
|
|
*/
|
|
|
|
void RemoteVariable::setIntValue(int value) {
|
|
|
|
char buffer[this->size];
|
|
|
|
itoa(value, buffer, DEC);
|
|
|
|
this->setValue(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Set the value of the variable as a long
|
|
|
|
* This method is used to set the value of the variable as a long
|
|
|
|
* @param value The value to set
|
|
|
|
*/
|
|
|
|
void RemoteVariable::setLongValue(long value) {
|
|
|
|
char buffer[this->size];
|
|
|
|
ltoa(value, buffer, DEC);
|
|
|
|
this->setValue(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Set the value of the variable as a double
|
|
|
|
* This method is used to set the value of the variable as a double
|
|
|
|
* @param value The value to set
|
|
|
|
*/
|
|
|
|
void RemoteVariable::setDoubleValue(double value) {
|
|
|
|
char buffer[this->size];
|
|
|
|
snprintf(buffer, this->size, "%f", value);
|
|
|
|
this->setValue(buffer);
|
|
|
|
}
|