Mbed forum

setResourceValue() and getResourceValue() APIs of Mbed Cloud JAVA SDK throw timeout exception always

mbed_cloud

(Arnab Dey) #1

Hi,

I have integrated Mbed Cloud Java SDK to my Android App and it works fine. However, the following two APIs always throw exceptions -

  1. setResourceValue()
  2. 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.

If I call setResourceValueAsync() directly, all the things work fine.
I have followed the examples provided here - https://github.com/ARMmbed/mbed-cloud-sdk-java/tree/master/examples/src/main/java/pelion_cloud_sdk

Therefore, I assume implementation of get and set device resource calls in my application are alright. Please help.

Note: I am using mbed-cloud-sdk v1.2.8 and my application runs on Android O+ devices.

Thanking you,

Regards,
Arnab Dey


(shai feldman) #2

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 ?

Tanks,

IOTSUPPORT


(Arnab Dey) #3

Hi Mr. Feldman,

Exception log - https://pastebin.com/rpCLZcnm

[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.

Please help.

Thanking you,

Regards,
Arnab Dey


(Arnab Dey) #4

Hi Mr. Feldman,

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.

Thanking you,

Regards,
Arnab Dey


(Adrien CABARBAYE) #5

Hello @arnabdey,

The latest SDK i.e. 2.2.0 indeed comprises major changes regarding these two functions. The API endpoint in use is different and the way async-responses are handled is also different and now uses solely Observers (https://github.com/ARMmbed/mbed-cloud-sdk-java/blob/master/CHANGELOG.md#220-2018-11-15). Glad this solved your issue.

Best regards,

Adrien


(Arnab Dey) #6

Hi Mr. Adrien

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?

Thanking you,

Regards,
Arnab Dey


(Adrien CABARBAYE) #7

Hello @arnabdey,

Get and set resource values are really methods to use with the long polling solution.
For your case, if your need is to use a webhook i.e. a standing server with a publicly available URL which responds to notifications from Pelion Cloud, then I would suggest to use the subscriptions/observers model https://github.com/ARMmbed/mbed-cloud-sdk-java/blob/0858ab35dcd0075d5cc5cf746f068353a26ed2d8/examples/src/main/java/pelion_cloud_sdk/SdkExamples.java#L100

Observers give you a way to only wait for one value using method like futureOne() or one() https://cloud.mbed.com/docs/current/mbed-cloud-sdk-java/com/arm/mbed/cloud/sdk/subscribe/Observer.html.

The following documentation is still in an alpha version and may contain typos but may still give you some more information about the different ways to communicate with a device: https://armmbed.github.io/mbed-cloud-sdk-documentation/#subscribing-to-events

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,

Adrien


(Arnab Dey) #8

Hi Mr. Adrien,

Thank you for the details. I will go through the links you have shared.

My use case:

  1. 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.
  2. 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.

Thanking you,

Regards,
Arnab Dey


(Adrien CABARBAYE) #9

Hello Arnab,

I am not sure I understand this bit:

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.

Best regards,

Adrien


(Arnab Dey) #10

Hi Mr. Adrien,

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?

Thanking you,

Regards,
Arnab Dey


(Adrien CABARBAYE) #11

Hello @arnabdey,

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.

Tell me if it is not clear.
Best regards,

Adrien


(Arnab Dey) #12

Hi Mr. Adrien,

I can consider it as a temporary solution because of the following reason:

  1. 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?

Thanking you,

Regards,
Arnab Dey


(Adrien CABARBAYE) #13

Hello @arnabdey,

Regarding your second question, I’ll say no. The endpoints that used to be in use in previous SDK versions are deprecated and therefore, I’'d recommend to use latest SDK. noResponse parameter moreover may not do what you think it does: https://cloud.mbed.com/docs/current/service-api-references/device-management-connect.html#resources

noResp (optional)

Query Parameter —

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();

Hope this helps,

Adrien


(Arnab Dey) #14

Hi Mr. Adrien,

Thank you very much for your help. I am trying to figure out the best possible way to achieve my target. I need some clarifications -

  1. Can you please let me know the significance of Sdk.subscribe() and Connect.subscribe()? Is the Sdk one there to provide observer implementation only?

  2. Can I use both Sdk.subscribe() and Connect.subscribe() for same/different resource in my code?

  3. Is it possible to explain the role of the separate ‘Sdk’ class in brief, or point me to any documentation on this?

Thanking you,

Regards,
Arnab Dey


(Adrien CABARBAYE) #15

Hello @arnabdey,

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,

Adrien


(Arnab Dey) #16

Hi Adrien,

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?

Thanking you,

Regards,
Arnab Dey


(Adrien CABARBAYE) #17

Hello @arnabdey,

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.

Best regards,

Adrien