I’m trying to develop a gateway that has to read and write shadows of different devices using a single client.
Checking out ShadowClient_t I see that there’s an array of shadowconfigMAX_THINGS_WITH_CALLBACKS CallbackCatalogEntry_t items which makes me think that this action is feasible but then looking deep in the code I see that some bits save the status of supscriptions for the update/get/delete topics (i.e. xUpdateSubscribed) in order to avoid subscribing multiple times. But while all the things I have will try to publish to different topics these bits have no connection to a particular thing and seem to be related to the shadow client itself.
What I guess is happening is that when I try to update the shadow of thing “2”, prvGetSubscribedFlag returns true even if the subscription was made previously on the topics related to thing “1”. New subscriptions are therefore not issued and the publish can only fail.
What am I missing here? Do I need to have one client for each thing if I want to keep subscriptions to the Delta document of each of the things?
Thanks for bringing this issue to our attention. We have a few questions that will help us understand some more details about the issue that you are facing.
Can you please let us know the below details.
Is there a specific version of Amazon FreeRTOS that you are using for this application?
How are you managing the authentication while trying to update 2 different shadows? Do these ‘Things’ have a common client certificate and private key? If not you may not be able to share the same MQTT connection.
thanks for your reply. I’m using a pretty old Amazon FreeRTOS V1.2.0 and Amazon FreeRTOS Shadow V1.0.3 provided with the SDK 2.4.2 for NXP LPC54018. I compared the aws_shadow.c file with one from a release of one month ago (but for a different mcu) and haven’t seen major differences (besides names of variables that have changed). The management of subscriptions for the shadow seems not to have changed.
As for certificates the gateway has its own certificate and private key different from those owned by the things connected to it but we managed authorizations on server side where the gateway is allowed to publish for different children. I haven’t done in person this part but I can ask for details. This parts work properly as I managed to update all the shadows, the only thing is that I have to disconnect and reconnect all the time for every single thing in order to force new subscriptions to the topics that the shadow needs to operate.
Thanks for your patience. In Amazon FreeRTOS V1.2.0, accepted and rejected MQTT subscriptions for Shadow operations are kept active, when the flag ucKeepSubscriptions ( https://docs.aws.amazon.com/freertos/latest/lib-ref/html1/struct_shadow_operation_params.html#a50265915f3783b3936905db007039bc6 ) is enabled. Please find an example of using this flag in Shadow demo in https://github.com/aws/amazon-freertos/blob/v1.2.0/demos/common/shadow/aws_shadow_lightbulb_on_off.c#L301. These subscriptions are kept only for a thing in each Shadow client.
If you want to update multiple Shadows in Amazon FreeRTOS V1.2.0, using a Shadow client, the flag ucKeepSubscriptions should be disabled. When you disable this flag, every operation on Shadow will subscribe to the accepted and rejected MQTT topics and unsubscribe once the operation is completed. Please let us know if this information helps with your problem. Please also let us know if there are any more questions.
I will try the solution you suggested as soon as I get back to the office (in january).
For delta subscription, in my understanding these bits aren’t involved so the relevant mqtt subscriptions should remain in place for each thing (in pxCallbackCatalog), we should be ok on this side. Correct me if I’m wrong.
Isn’t it quite heavy to perform new subscriptions every time we have to update the shadow, especially in a device that will be publishing very often (as it publishes in the name of many other things)?
Is it possible to totally avoid subscriptions to accepted/rejected topics and exploit the updated callback (which is saved separately for each device)? Although I guess that would probably mean using a simple mqtt agent instead of the shadow code infrastructure on the client side.
Yes, you are right that callbacks registered for a thing are stored in catalog and the corresponding subscriptions will remain in place.
The previous suggestion of keeping ucKeepSubscriptions 0 is for when you are doing the update. The shadow client does subscribe to accepted/rejected topics in order to know whether or not the operation succeeded. As you mentioned correctly, you can use MQTT agent to just update the shadow without subscribing to accepted/rejected topics.
I believe @Gaurav-Aggarwal-AWS has answered most of your questions. I would like to add more details about your question regarding if it is going to be heavy to have a subscription every time you are doing an update.
Keeping ucKeepSubscriptions as 1 will keep the subscriptions for accepted/rejected MQTT topics for future operations for a single thing. However it will not help with the subscription needed for the update of a different thing. Hope this answered your question. Please let us know if you have any more questions.
I finally managed to test the system with ucKeepSubscriptions = 0 and the whole process now works properly. I would like to thank you guys for the support.
I still think that this should be better dealt with or explained in the code on future releases as, for now, if ucKeepSubscriptions == 1 a single shadow client cannot be used to publish for multiple things. This is due to the bits that keep track of subscription status. These bits are unique for each client and not for each managed thing causing the required subscriptions for updates of subsequent things not to happen (only the first thing updated triggers a subscription to its own accepted/rejected topics on the client).
By using ucKeepSubscriptions = 0 the issue is not faced and a single client can properly update multiple things. So, for now, this is the solution.