1#ifndef Attribute_Request_h
2#define Attribute_Request_h
20#if THINGSBOARD_ENABLE_DEBUG
21char constexpr NO_KEYS_TO_REQUEST[] =
"No keys to request were given";
22char constexpr ATT_KEY_NOT_FOUND[] =
"Attribute key in Attribute_Request_Callback is NULL";
23char constexpr ATT_KEY_IS_NULL[] =
"Requested attribute key is NULL";
25#if !THINGSBOARD_ENABLE_DYNAMIC
33#if THINGSBOARD_ENABLE_DYNAMIC
34template <
typename Logger = DefaultLogger>
41template<
size_t MaxSubscriptions = DEFAULT_SUBSCRIPTION_AMOUNT,
size_t MaxAttributes = DEFAULT_ATTRIBUTES_AMOUNT,
typename Logger = DefaultLogger>
44#if THINGSBOARD_ENABLE_DYNAMIC
85 return API_Process_Type::JSON;
94 JsonObjectConst
object = data.template as<JsonObjectConst>();
97#if THINGSBOARD_ENABLE_STL
98 auto it = std::find_if(m_attribute_request_callbacks.
begin(), m_attribute_request_callbacks.
end(), [&request_id](
Callback_Value & attribute_request) {
99 return attribute_request.Get_Request_ID() == request_id;
101 if (it != m_attribute_request_callbacks.
end()) {
102 auto & attribute_request = *it;
104 for (
auto it = m_attribute_request_callbacks.
begin(); it != m_attribute_request_callbacks.
end(); ++it) {
105 auto & attribute_request = *it;
112 if (attribute_response_key ==
nullptr) {
113#if THINGSBOARD_ENABLE_DEBUG
114 Logger::printfln(ATT_KEY_NOT_FOUND);
116 goto delete_callback;
119 if (
object.containsKey(attribute_response_key)) {
120 object =
object[attribute_response_key];
129 m_attribute_request_callbacks.
erase(it);
130#if !THINGSBOARD_ENABLE_STL
138 if (m_attribute_request_callbacks.
empty()) {
139 (void)Attributes_Request_Unsubscribe();
148 return Attributes_Request_Unsubscribe();
152 m_attribute_request_callbacks.
clear();
156#if !THINGSBOARD_USE_ESP_TIMER
158 for (
auto & attribute_request : m_attribute_request_callbacks) {
169 void Set_Client_Callbacks(
Callback<void, IAPI_Implementation &>::function subscribe_api_callback,
Callback<bool, char const * const, JsonDocument const &>::function send_json_callback,
Callback<bool, char const * const, char const * const>::function send_json_string_callback,
Callback<bool, char const * const>::function subscribe_topic_callback,
Callback<bool, char const * const>::function unsubscribe_topic_callback,
Callback<uint16_t>::function get_receive_size_callback,
Callback<uint16_t>::function get_send_size_callback,
Callback<bool, uint16_t, uint16_t>::function set_buffer_size_callback,
Callback<size_t *>::function get_request_id_callback)
override {
171 m_subscribe_topic_callback.Set_Callback(subscribe_topic_callback);
172 m_unsubscribe_topic_callback.Set_Callback(unsubscribe_topic_callback);
173 m_get_request_id_callback.
Set_Callback(get_request_id_callback);
177 bool Attributes_Request(
Callback_Value const & callback,
char const * attribute_request_key,
char const * attribute_response_key) {
178 auto const & attributes = callback.Get_Attributes();
181 if (attributes.empty()) {
182#if THINGSBOARD_ENABLE_DEBUG
183 Logger::printfln(NO_KEYS_TO_REQUEST);
187 else if (attribute_request_key ==
nullptr || attribute_response_key ==
nullptr) {
188#if THINGSBOARD_ENABLE_DEBUG
189 Logger::printfln(ATT_KEY_NOT_FOUND);
195 if (!Attributes_Request_Subscribe(callback, registered_callback)) {
198 else if (registered_callback ==
nullptr) {
205 StaticJsonDocument<JSON_OBJECT_SIZE(1)> request_buffer;
210 for (
auto const & att : attributes) {
225 char request[size] = {};
226 for (
auto const & att : attributes) {
228#if THINGSBOARD_ENABLE_DEBUG
229 Logger::printfln(ATT_KEY_IS_NULL);
234 strncat(request, att, size);
236 strncat(request,
",", size);
243 request_buffer[attribute_request_key] =
static_cast<const char*
>(request);
245 size_t * p_request_id = m_get_request_id_callback.
Call_Callback();
246 if (p_request_id ==
nullptr) {
250 auto & request_id = *p_request_id;
252 registered_callback->Set_Request_ID(++request_id);
253 registered_callback->Set_Attribute_Key(attribute_response_key);
254 auto & request_callback = registered_callback->Get_Request_Timeout();
259 return m_send_json_callback.
Call_Callback(topic, request_buffer);
267#if !THINGSBOARD_ENABLE_DYNAMIC
268 if (m_attribute_request_callbacks.
size() + 1 > m_attribute_request_callbacks.
capacity()) {
277 m_attribute_request_callbacks.
push_back(callback);
278 registered_callback = &m_attribute_request_callbacks.
back();
284 bool Attributes_Request_Unsubscribe() {
293 Callback_Container m_attribute_request_callbacks = {};
API_Process_Type
Possible processing types an API Implementation uses to handle responses from the server.
Definition: API_Process_Type.h:19
char constexpr ATTRIBUTE_RESPONSE_SUBSCRIBE_TOPIC[]
Definition: Attribute_Request.h:12
char constexpr CLIENT_SHARED_ATTRIBUTE_SUBSCRIPTIONS[]
Definition: Attribute_Request.h:26
char constexpr CLIENT_RESPONSE_KEY[]
Definition: Attribute_Request.h:16
char constexpr ATTRIBUTE_RESPONSE_TOPIC[]
Definition: Attribute_Request.h:13
char constexpr SHARED_REQUEST_KEY[]
Definition: Attribute_Request.h:18
char constexpr ATTRIBUTE_REQUEST_TOPIC[]
Definition: Attribute_Request.h:11
char constexpr CLIENT_REQUEST_KEYS[]
Definition: Attribute_Request.h:15
char constexpr MAX_SUBSCRIPTIONS_TEMPLATE_NAME[]
Definition: IAPI_Implementation.h:22
char constexpr SHARED_RESPONSE_KEY[]
Definition: IAPI_Implementation.h:31
char constexpr SUBSCRIBE_TOPIC_FAILED[]
Definition: IAPI_Implementation.h:23
char constexpr MAX_SUBSCRIPTIONS_EXCEEDED[]
Definition: IAPI_Implementation.h:20
char constexpr REQUEST_ID_NULL[]
Definition: IAPI_Implementation.h:24
Client-side or shared attributes request callback wrapper, contains the needed configuration settings...
Definition: Attribute_Request_Callback.h:25
Timeoutable_Request & Get_Request_Timeout()
Gets the request timeout callback.
Definition: Attribute_Request_Callback.h:132
size_t const & Get_Request_ID() const
Gets the unique request identifier that is connected to the original request.
Definition: Attribute_Request_Callback.h:71
char const * Get_Attribute_Key() const
Gets the response key of the json array key-value pair, that we expect the client-side or shared attr...
Definition: Attribute_Request_Callback.h:87
Handles the internal implementation of the ThingsBoard client and shared Attribute Request API....
Definition: Attribute_Request.h:43
void Initialize() override
Method that allows to construct internal objects, after the required callback member methods have bee...
Definition: Attribute_Request.h:165
~Attribute_Request() override=default
void Set_Client_Callbacks(Callback< void, IAPI_Implementation & >::function subscribe_api_callback, Callback< bool, char const *const, JsonDocument const & >::function send_json_callback, Callback< bool, char const *const, char const *const >::function send_json_string_callback, Callback< bool, char const *const >::function subscribe_topic_callback, Callback< bool, char const *const >::function unsubscribe_topic_callback, Callback< uint16_t >::function get_receive_size_callback, Callback< uint16_t >::function get_send_size_callback, Callback< bool, uint16_t, uint16_t >::function set_buffer_size_callback, Callback< size_t * >::function get_request_id_callback) override
Sets the underlying callbacks that are required for the different API Implementation to communicate w...
Definition: Attribute_Request.h:169
bool Unsubscribe() override
Unsubcribes all callbacks, to clear up any ongoing subscriptions and stop receiving information over ...
Definition: Attribute_Request.h:147
bool Resubscribe_Permanent_Subscriptions() override
Forwards the call to let the API clear up any ongoing single-event subscriptions (Provision,...
Definition: Attribute_Request.h:151
bool Client_Attributes_Request(Callback_Value const &callback)
Requests one client-side attribute, which will call the passed callback. If the key-value pair from t...
Definition: Attribute_Request.h:67
void loop() override
Internal loop method to update inernal timers for API calls that can timeout.
Definition: Attribute_Request.h:157
void Process_Json_Response(char const *topic, JsonDocument const &data) override
Process callback that will be called upon response arrival.
Definition: Attribute_Request.h:92
bool Is_Response_Topic_Matching(char const *topic) const override
Compares received response topic and the topic this api implementation handles responses on,...
Definition: Attribute_Request.h:143
void Process_Response(char const *topic, uint8_t *payload, uint32_t length) override
Process callback that will be called upon response arrival.
Definition: Attribute_Request.h:88
API_Process_Type Get_Process_Type() const override
Returns the way the server response should be processed.
Definition: Attribute_Request.h:84
Attribute_Request()=default
Constructor.
bool Shared_Attributes_Request(Callback_Value const &callback)
Requests one shared attribute, which will call the passed callback. If the key-value pair from the se...
Definition: Attribute_Request.h:80
General purpose safe callback wrapper. Expects either c-style or c++ style function pointer,...
Definition: Callback.h:30
std::function< return_type(argument_types... arguments)> function
Callback signature.
Definition: Callback.h:34
void Set_Callback(function callback)
Sets the callback method that will be called upon data arrival with the given data that was received....
Definition: Callback.h:72
return_type Call_Callback(argument_types const &... arguments) const
Calls the callback that was subscribed, when this class instance was initally created.
Definition: Callback.h:62
size_type size() const
Gets the current amount of elements in the underlying data container.
Definition: Container.h:147
reference back()
Returns a reference to the last element of the array. If the array is empty this method will assert a...
Definition: Container.h:196
iterator begin()
Returns an iterator to the first element of the underlying data container. If the array is empty,...
Definition: Container.h:165
void erase(const_iterator position)
Removes the element at the given position, has to move all element one to the left if the iterator do...
Definition: Container.h:284
size_type constexpr capacity() const
Gets the maximum amount of elements that can be stored in the underlying data container.
Definition: Container.h:157
void push_back(const_reference element)
Appends the given element at the end of the underlying data container.
Definition: Container.h:230
bool empty() const
Returns whether there are any elements in the underlying data container.
Definition: Container.h:141
void clear()
Erases all elements from the container. After this call, size() returns zero.
Definition: Container.h:330
iterator end()
Returns a iterator to one-past-the-last element of the underlying data container.
Definition: Container.h:209
static size_t Calculate_Print_Size(char const *format, Args const &... args)
Returns the total amount of bytes needed to store the formatted string with null termination,...
Definition: Helper.h:32
static bool String_IsNull_Or_Empty(char const *str)
Returns wheter the given string is either a nullptr or is an empty string, meaning it only contains a...
Definition: Helper.cpp:27
static size_t Split_Topic_Into_Request_ID(char const *received_topic, size_t const &end_position)
Splits the topic at the given position and extracts the request id parameter from the remaining strin...
Definition: Helper.cpp:31
Base functionality required by all API implementation.
Definition: IAPI_Implementation.h:37
General purpose request callback that can timeout if the response to the request is not received in t...
Definition: Timeoutable_Request.h:10
void Update_Timeout_Timer()
Updates the internal timeout timer.
Definition: Timeoutable_Request.cpp:20
void Start_Timeout_Timer()
Starts the internal timeout timer if we actually received a configured valid timeout time and a valid...
Definition: Timeoutable_Request.cpp:25
void Stop_Timeout_Timer()
Stops the internal timeout timer, is called as soon as an answer is received from the cloud....
Definition: Timeoutable_Request.cpp:32