Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The batch removal device attribute failed #238

Closed
chenzheng1988 opened this issue May 16, 2018 · 11 comments
Closed

The batch removal device attribute failed #238

chenzheng1988 opened this issue May 16, 2018 · 11 comments
Assignees
Labels
bug fix checked in Fix checked into main or preview, but not yet released.

Comments

@chenzheng1988
Copy link

The device attribute failed to be removed in batch, the device property was set to null, the batch update was performed, and the final device attribute was still present and was not removed.

    // new set of desired properties
    Set<Pair> desiredProperties = new HashSet<Pair>();
    //desiredProperties.add(new Pair("temp", new Random().nextInt(TEMPERATURE_RANGE)));
    desiredProperties.add(new Pair("Name", "wo"));
    device.setDesiredProperties(desiredProperties);

    // date when the update shall be executed
    Date updateDateInFuture = new Date(new Date().getTime() + ADD_10_SECONDS_IN_MILLISECONDS); // 10 seconds in the future.

    // query condition that defines the list of device to be updated
    String queryCondition = "DeviceId IN " + deviceIds + "";

    System.out.println("Schedule updating Device twin (new temp, hum) in 10 seconds");
    Job job = twinClient.scheduleUpdateTwin(queryCondition, device, updateDateInFuture, MAX_EXECUTION_TIME_IN_SECONDS);

    System.out.println("Wait for job completed..."+job.getJobId());
    JobResult jobResult = job.get();
    while (jobResult.getJobStatus() != JobStatus.completed)
    {
        Thread.sleep(GIVE_100_MILLISECONDS_TO_IOTHUB);
        jobResult = job.get();
    }
    System.out.println("job completed");

    System.out.println("Getting the updated Device twin");
    twinClient.getTwin(device);
    System.out.println(device);

pom.xml:

com.microsoft.azure.sdk.iot
iot-service-client
1.13.2

@chenzheng1988
Copy link
Author

Set the name property to null, and the name attribute still exists after executing the code, without removing it.

 desiredProperties.add(new Pair("Name", null));

Result:

 Desired Properties: {"hum":"asf","temp":64.0,"Address":"China","testproper":"","ID":1.0,"Name":"wo","$version":15,

@timtay-microsoft
Copy link
Member

It looks like the problem here is that you are able to add a pair to the desired properties with the same key as an existing pair. When the set of desired properties has two pairs with the same key, the SDK will randomly choose one of those pairs as the "true" pair to be included in the communication to the service.

If you simply remove the old pair from your desiredProperties before adding the new pair with the null value, your codeflow should work. See below for a sample

    // new set of desired properties
    Set<Pair> desiredProperties = new HashSet<Pair>();
    desiredProperties.add(new Pair("Name", "wo"));
    device.setDesiredProperties(desiredProperties);

    // date when the update shall be executed
    Date updateDateInFuture = new Date(new Date().getTime() + ADD_10_SECONDS_IN_MILLISECONDS); // 10 seconds in the future.

    // query condition that defines the list of device to be updated
    String queryCondition = "DeviceId IN " + deviceIds + "";

    System.out.println("Schedule updating Device twin (new temp, hum) in 10 seconds");
    Job job = twinClient.scheduleUpdateTwin(queryCondition, device, updateDateInFuture, MAX_EXECUTION_TIME_IN_SECONDS);

    System.out.println("Wait for job completed..."+job.getJobId());
    JobResult jobResult = job.get();
    while (jobResult.getJobStatus() != JobStatus.completed)
    {
        Thread.sleep(GIVE_100_MILLISECONDS_TO_IOTHUB);
        jobResult = job.get();
    }
    System.out.println("job completed");

    System.out.println("Getting the updated Device twin");
    twinClient.getTwin(device);
    System.out.println(device);

    ....

    //deleting desired property "Name"
    desiredProperties.clear();
    desiredProperties.add(new Pair("Name", null));
    device.setDesiredProperties(desiredProperties);
    twinClient.updateTwin(device);
    twinClient.getTwin(device);
    System.out.println(device);

This should unblock you for now, but I'll add a safeguard to prevent this from happening in the future.

@chenzheng1988
Copy link
Author

So I can only delete the property of one device. What do I do if I want to delete the attributes of multiple devices in batches?

@chenzheng1988
Copy link
Author

Do not support batch update twin attributes?Tested, is to support batch updates twin attributes in a iothub ah, now you can't just batch remove twin attributes, that is to say, when twin attribute value is set to null, the results of this property has not been removed.

@timtay-microsoft
Copy link
Member

I'm having trouble understanding your previous comment. Are you saying that setting a property to null still does not result in the property being removed in the sample code I gave you?

@chenzheng1988
Copy link
Author

I want to delete the device attributes in bulk. The example you gave earlier can only delete the attributes of a single device and not delete multiple devices.

@chenzheng1988
Copy link
Author

Here is the code I used:

   public static final String deviceId = "mydevice1";
   public static final String deviceIds="['mydevice0','mydevice1','mydevice2']";
    public static void main(String[] args) throws Exception
{

    System.out.println("Starting sample...");
    DeviceTwin twinClient = DeviceTwin.createFromConnectionString(SampleUtils.iotHubConnectionString);
    DeviceTwinDevice device = new DeviceTwinDevice(deviceId);
    try
    {           
        // ============================ schedule update desired property ==========================
        scheduleUpdateDesiredProperties(twinClient, device);
    }
}
 private static void scheduleUpdateDesiredProperties(DeviceTwin twinClient, DeviceTwinDevice device) throws IOException, IotHubException, InterruptedException
{
    // new set of desired properties
    Set<Pair> desiredProperties = new HashSet<Pair>();
    desiredProperties.add(new Pair("hum", null));

    device.setDesiredProperties(desiredProperties);
    // date when the update shall be executed
    Date updateDateInFuture = new Date(new Date().getTime() + ADD_10_SECONDS_IN_MILLISECONDS); // 10 seconds in the future.
    // query condition that defines the list of device to be updated
    String queryCondition = "DeviceId IN " + deviceIds + "";
    System.out.println("Schedule updating Device twin (new temp, hum) in 10 seconds");
    Job job = twinClient.scheduleUpdateTwin(queryCondition, device, updateDateInFuture, MAX_EXECUTION_TIME_IN_SECONDS);   
    System.out.println("Wait for job completed..."+job.getJobId());   
    String start=Instant.now().toString();
    System.out.println("Wait for job completed...starttime "+start);
    
    JobResult jobResult = job.get();
    while (jobResult.getJobStatus() != JobStatus.completed)
    {
        Thread.sleep(GIVE_100_MILLISECONDS_TO_IOTHUB);
        jobResult = job.get();
    }
    String start1=Instant.now().toString();
    System.out.println("Wait for job completed...endtime "+start1); 
    System.out.println("job completed");

    System.out.println("Getting the updated Device twin");
    twinClient.getTwin(device);
    System.out.println(device);
    
    desiredProperties.clear();
    desiredProperties.add(new Pair("Name", null));
    device.setDesiredProperties(desiredProperties);
    twinClient.updateTwin(device);
    twinClient.getTwin(device);
    System.out.println(device);
}

the result is: the hum attribute of the mydevice1 device has been deleted, but the hum properties of the two devices of mydevice0 and mydevice2 still exist.
So I want to delete the hum property of all three devices.What should I do?

@timtay-microsoft
Copy link
Member

Okay, I understand your problem now, then. You currently cannot do batch removal of an attribute on devices, but only due to a bug with our Service Client. I'll try to get the fix for that in before our release on 5/25. When I release the fix for this bug, I will update this thread with a sample code for doing what you want.

timtay-microsoft added a commit that referenced this issue May 21, 2018
timtay-microsoft added a commit that referenced this issue May 21, 2018
@timtay-microsoft timtay-microsoft self-assigned this May 21, 2018
timtay-microsoft added a commit that referenced this issue May 24, 2018
timtay-microsoft added a commit that referenced this issue May 24, 2018
timtay-microsoft added a commit that referenced this issue May 24, 2018
@timtay-microsoft timtay-microsoft added the fix checked in Fix checked into main or preview, but not yet released. label May 24, 2018
@timtay-microsoft
Copy link
Member

The fix for this issue has been checked in. Feel free to build from source to check that the bug is resolved for you. Our next package release will be tomorrow.

For doing batch updates that remove an attribute from multiple devices, you will use the same API that you are using to add those properties in your sample code. You just need to set the desired property to null to delete it.

@timtay-microsoft
Copy link
Member

The fix for this bug has been released in Service Client 1.13.3.

Since the fix has been released, I'm closing this issue. Feel free to re-open if you still see this issue.

@chenzheng1988 thank you for your contribution to our open-sourced project! Please help us improve by filling out this 2-minute customer satisfaction survey.

@chenzheng1988
Copy link
Author

This problem has been solved. Thank you very much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug fix checked in Fix checked into main or preview, but not yet released.
Projects
None yet
Development

No branches or pull requests

2 participants