I have integrated Mbed Cloud Java SDK to my Android App and it works fine. However, the following two APIs always throw exceptions -
setResourceValue()
getResourceValue()
though they complete the intended tasks(i.e. setting a resource value/getting a resource value) successfully with the help of setResourceValueAsync()/getResourceValueAsync() which are called inside the above mentioned APIs. E.g. When setting a resource value, I can see that the value changes on my pelion portal, but the API throws exception in android device.
Hi ,
Can you please write the content of the exceptions you got on your android device ?
Did you try with a different android device and got the same results ? , if not , can you please test it and update on results ?
[Note: In the log, MbedCloudConfigHelper.java and AsyncTaskRunner are specific to my app, in which I am calling Mbed Cloud SDK APIs]
I have tried with Pixel 2(Android 8.0.0) and Nexus 6P (Android 8.1.0). Both gave me same result. I could get the value of the resource from ‘async-responses’, however the API threw exception.
I observed similar behavior for setResourceValue() API also.
I just upgraded Mbed Cloud SDK version to v2.2.0 from v1.2.8 and I did not observe the issue. It seems there is some problem with the older SDK version. My issue is solved and this case can be closed.
Thank you very much for the fixes in SDK v2.2.0. However, I have a question regarding these APIs :
I could see that these two APIs, by default, remove the webhook (v2/notification/callback) and set up pull channel (v2/notification/pull) to receive the async-response. Moreover, async APIs and overloading functions with noResponse argument are deprecated. But as far as I understood, it is not required to remove callback to use set or get APIs if we explicitly handle the responses in our application.
For my work, it will be great if I can get the ‘async-response’ also through /v2/notification/callback. If I call ‘updateWebhook()’ immediately after calling getResourceValue()/setResourceValue(), I am afraid that it might cause some race condition. Please let me know what is the best way to use get/set APIs without removing callback to receive async-response via webhook?
To be able to give you more guidance or help, I would have to better understand your use case. Is it possible that you give me more details about what you are trying to do?
Best regards,
Thank you for the details. I will go through the links you have shared.
My use case:
What I want:
1.a. User will have option to select either pull or webhook notification from UI. Accordingly, my app will communicate to MBed Cloud.
1.b. If user selects webhook, options will be given to select device/resources to subscribe and user should provide webhook URL, and any user-specific headers to include.
1.c. User clicks on ‘Setup Callback’ button and my app will take care of the rest.
1.d. Whenever any resource value changes, my app should get notification utilizing webhook (I have done it already and it is working fine)
1.e. Whenever user wants to refresh the resource states shown on UI, user will click on ‘Refresh’ and my app should use ‘getResourceValue()’ for resources subscribed/shown on UI.
1.f. At, this point, as per SDK v2.2.0, webhook will be removed unless I explicitly gather the info user created in 1.b and my app will again execute 1.c automatically.
1.g. User can change the value of any resource from UI. My app will use setResourceValue(). Again webhook will be deleted and app should execute 1.b and 1.c automatically.
What my problem is:
2.a. I do not want to go through the cycle (set or get->webhook delete->set or get done → webhook init) mentioned in 1.e. - 1.g.
2.b. Webhook initialization takes time, therefore, what happens if after refresh, my webhook is still getting set up and some resource value changes on the device? How will the user come to know about that?
Is not it really nice to have one unified callback structure(whatever user will choose at 1.a.) and get all type of notifications via it without going through create-delete-create cycle? Please let me know your thoughts on this.
Because you subscribe to any value changes, the webhook will receive notifications from resources for which the values have changed. For the others, the values are the same as they were before. So your UI should already show the latest resource states and I don’t see what new information the ‘Refresh’ button is supposed to bring.
It is possible that for some resources, user does not want to subscribe to value changes but wants to get the value as per wish. Or, consider this example - I have a master switch which controls 2 light bulbs(individual resources). I have subscribed to switch only. On my UI, along with switch, bulbs states are also shown. Therefore, when the switch is turned off, I want to make sure that along with the switch, all the bulbs are switched off and then populate my UI. In this case, upon receiving the switch notification via webhook, I want to call getResourceValue() for those two bulbs.
EDIT: Please let me know how I can get or set resource value without removing /v2/notification/callback channel i.e. webhook?
What you can do is to use 2 API Keys: one for setting the webhook and one for the app/client (in a sense, use two SDK instances). the client uses normal polling and can then set/get values of any resources it wants. The webhook listens to a different notification channel (the API key setting it being different) and for any notification received, it feeds back the client using the notify method.
I can consider it as a temporary solution because of the following reason:
In the final product, the API keys will be provided by the users. Users will install my App, provide the API key linked to their accounts and it should start working like Plug-and-Play. It is really inconvenient to ask users to provide two API keys.
Moreover, what about a race condition? While getResource() is going on, if a resource value changes, app might get different values from the two different channels. One unified callback will solve this.
Rather, I would like to request MBed team to provide some mechanism to have one unified callback structure. Please let me know your thoughts.
EDIT: Can you please let me know if the ‘noResponse’ argument in the get/set APIs can solve my problem? Though this argument is deprecated in SDK v2.2.0. I could see that in earlier SDK versions, I had to remove callback explicitly but in latest SDK, it is done internally. Therefore, in this context, would the older style implementation of get/set with noResponse=true solve my problem?
If a request is made with noResp=true , Device Management Connect makes a CoAP non-confirmable request to the device. Such requests are not guaranteed to arrive in the device, and you do not get back an async-response-id.
If calls with this parameter enabled succeed, they return with the status code 204 No Content . If the underlying protocol does not support non-confirmable requests, or if the endpoint is registered in queue mode, the response is status code 409 Conflict .
If you are using 1 API key, you can only use either polling or webhook but not both at once. This is a limitation of the service itself and cannot really be overcome by the SDK. This may change in the future but there is not currently any plan for this, as far as I am aware.
To avoid having the webhook deleted automatically, you can do as in the example referenced above by telling the SDK not to start the polling daemon. Then, use the Async method of choice to make the query to Pelion cloud. The async-response will be fed back to the corresponding observers by the webhook using the notify(...) method.
ConnectionOptions config = ConnectionOptions.newConfiguration(...);
config.autostartDaemon(false); // This will ensure polling thread is not started
Connect api = new Connect(config);
try {
Device device = api2.getDevice("01....");
api.executeResourceAsync(new Resource(device, "/3/..."), null);
} catch (MbedCloudException exception) {
// TODO Auto-generated catch block
exception.printStackTrace();
Sdk class represents the single point of entry for the SDK. As you can see, it is marked as @Experimental and therefore, may change in the future. Currently, it only lets you subscribe to resources but later it will be the place to access anything, in a more intuitive way i.e. perform device management, etc… This class will evolve quite a lot in the near future and you will see quite a lot of changes in SDK 3.0.0, as the structure of the SDK will change.
Under the hood, the subscribe method in Sdk uses the functionality defined currently in the Connect module. Therefore, you can use methods in Sdk in the same way as in Connect. They are separate instances though so the store of observers is not shared between a Connect instance and a Sdk instance if I understand correctly your question 2).
Hope I answered your questions.
Best regards,
Thank you for your clarification. Does it mean that in near future, ‘Connect’ and other classes might get deprecated when ‘Sdk’ will be in matured state?
It’ll probably happen but definitely not in the near future. When it happens, if it happens, there will be a deprecation period, which may be quite long, following a deprecation notice and some migration guidance. So do not worry if you are using the Connect Module, changes will not happen overnight. It is moreover recommended to use the SDK as is and not to use the Sdk module just yet.