Skip to content
This repository was archived by the owner on Oct 27, 2025. It is now read-only.

Conversation

@twendtland
Copy link

@twendtland twendtland commented Nov 14, 2024

I made the params string optional, just because I like being able to omit arguments that are not necessary. If someone's not cool with that, I'm happy to make it a normal parameter

@twendtland twendtland force-pushed the feature/rpc branch 7 times, most recently from 9106616 to 89919b9 Compare November 14, 2024 15:47
@twendtland twendtland marked this pull request as ready for review November 14, 2024 16:13
{
int err;
va_list param;
char params[64];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We of course don't know how long the parameters list will be but 64 characters seems very short to me. Maybe increase it a bit to 256 or something like that?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, you're right, this was the first thing I used for testing, it might well be too short. I will increase it

K_SEM_DEFINE(time_sem, 0, 1);

static attr_write_callback_t attribute_cb;
static rpc_callback_t rpc_cb;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callback will be overwritten by another one if the user calls thingsboad_rpc multiple times without waiting for the response. When the response arrives the wrong callback would be called.
Avoiding multiple RPCs in flight with a semaphore approach that you mentioned yesterday would probably solve this. Or just reset rpc_cb to NULL after it was called and return with an error from thingsboad_rpc() if rpc_cb is not NULL?

A nicer solution would be to allow simultaneous RPC calls by using a memory slab to store multiple callbacks (the same way coap_client.c manages multiple requests).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, the limitation is obvious. I will think about a solution, being able to do multiple RPC calls simultaneously seems like something that's not often used, but could come in handy.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be fine with having this limitations as it is probably okay for most use cases. We should just document this and somehow enforce the "only one rpc at a time" rule to avoid weird behaviour (like wrong callback called) for the user.

* Parameters are an optional string in JSON format as the variadic arguments
* See https://thingsboard.io/docs/reference/coap-api/#client-side-rpc for details.
*/
void thingsboard_rpc(const char *method, rpc_callback_t cb, ...);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have the time it would be great if you can add a sample for this in samples/, too.

@twendtland twendtland force-pushed the feature/rpc branch 4 times, most recently from 9c084a4 to 6b2062a Compare November 15, 2024 11:13
@twendtland
Copy link
Author

I added a sample and changed the RPC function to return an error code.

@twendtland twendtland force-pushed the feature/rpc branch 2 times, most recently from 4043849 to 7dd968c Compare November 15, 2024 11:46
Copy link
Contributor

@gumulka gumulka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, if we should also change our RPC code to already use your code to remove code duplicates and have a seconds example on how to use the RPC callbacks.

Comment on lines 253 to 228
if (k_sem_take(&rpc_sem, K_MSEC(5000)) > 0) {
// in case no response was ever received, reset the semaphore and continue
k_sem_reset(&rpc_sem);
err = k_sem_take(&rpc_sem, K_MSEC(50));
if (err > 0) {
LOG_ERR("failed to take RPC semaphore");
return err;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if the way you inplemented it in the send routine is the right way to do it.

What I assume you want to do is: If there is no response within 5 seconds of sending, then just assume, that there was never a response and send the next message.

What you achieve: When trying to send a message, wait for 5 seconds before actually sending it, so that the old message is gone.

and if two threads try to send at nearly the same time, then the second thread will overwrite the callback for the first thread.

Copy link
Author

@twendtland twendtland Nov 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure I can follow. assuming there is no ongoing request: why would the code wait for 5 seconds? 'take' would return immediately, as the semaphore is free. the second param to 'take' is a timeout, after all, isn't it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the comparison should be fixed for that, ofc :D

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I was hinting at was assume the following sequence of Events:
time in minute:seconds

0:00: call to thingsboard_rpc (1)
10:00: call to thingsboard_rpc (2)
10:04: call to thingsboard_rpc (3)

If we assume for 1 to not return, then 2 will wait 5 seconds for the semaphore, and at 10:05 it will reset the semaphore and take it.
Now it will create the request, overwrite the callback and return, making place for other threads to run.
3 will be scheduled to run, because the semaphore it was trying to take was reset, which in turn is an error on taking a semaphore, it will immediately reset the semaphore and take it, then send its own request overwriting the callback.

If we assume the response from 2 at 10:06, it is already to late, as the callback function has been overwritten by 3.

If you instead keep track on when you send out the request at the beginning, then you could reset the semaphore at 10:00, send your request, receive the answer at 10:01 and have no problems or conflicts with 3.

@twendtland twendtland force-pushed the feature/rpc branch 3 times, most recently from 72f0946 to 84e562f Compare November 18, 2024 14:04
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants