Search in sources :

Example 1 with ShadowState

use of software.amazon.awssdk.iot.iotshadow.model.ShadowState in project aws-greengrass-nucleus by aws-greengrass.

the class ShadowDeploymentE2ETest method GIVEN_device_deployment_WHEN_shadow_update_messages_gets_delivered_out_of_order_THEN_shadow_updated_with_latest_deployment_status.

@Test
void GIVEN_device_deployment_WHEN_shadow_update_messages_gets_delivered_out_of_order_THEN_shadow_updated_with_latest_deployment_status() throws Exception {
    CreateDeploymentRequest createDeploymentRequest = CreateDeploymentRequest.builder().targetArn(thingInfo.getThingArn()).components(Utils.immutableMap("CustomerApp", ComponentDeploymentSpecification.builder().componentVersion("1.0.0").build(), "SomeService", ComponentDeploymentSpecification.builder().componentVersion("1.0.0").build())).build();
    draftAndCreateDeployment(createDeploymentRequest);
    assertThat(kernel.getMain()::getState, eventuallyEval(is(State.FINISHED)));
    IotShadowClient shadowClient = new IotShadowClient(new WrapperMqttClientConnection(kernel.getContext().get(MqttClient.class)));
    UpdateNamedShadowSubscriptionRequest req = new UpdateNamedShadowSubscriptionRequest();
    req.shadowName = DEPLOYMENT_SHADOW_NAME;
    req.thingName = thingInfo.getThingName();
    CountDownLatch reportSucceededCdl = new CountDownLatch(1);
    CountDownLatch deviceSyncedStateToSucceededCdl = new CountDownLatch(1);
    AtomicReference<HashMap<String, Object>> reportedSection = new AtomicReference<>();
    AtomicReference<Integer> shadowVersionWhenDeviceFirstReportedSuccess = new AtomicReference<>();
    AtomicReference<Integer> shadowVersionWhenDeviceReportedInProgress = new AtomicReference<>();
    shadowClient.SubscribeToUpdateNamedShadowAccepted(req, QualityOfService.AT_LEAST_ONCE, (response) -> {
        try {
            logger.info("Got shadow update: {}", new ObjectMapper().writeValueAsString(response));
        } catch (JsonProcessingException e) {
        // ignore
        }
        if (response.state.reported == null) {
            return;
        }
        String reportedStatus = (String) response.state.reported.get(STATUS_KEY);
        if (JobStatus.IN_PROGRESS.toString().equals(reportedStatus)) {
            reportedSection.set(response.state.reported);
            shadowVersionWhenDeviceReportedInProgress.set(response.version);
        } else if (JobStatus.SUCCEEDED.toString().equals(reportedStatus)) {
            // state to SUCCESS second time the shadow version
            if (reportSucceededCdl.getCount() == 0 && response.version > shadowVersionWhenDeviceFirstReportedSuccess.get()) {
                deviceSyncedStateToSucceededCdl.countDown();
            }
            shadowVersionWhenDeviceFirstReportedSuccess.set(response.version);
            reportSucceededCdl.countDown();
        }
    });
    // waiting for the device to report success
    assertTrue(reportSucceededCdl.await(60, TimeUnit.SECONDS));
    // Updating the shadow with deployment status IN_PROGRESS to simulate out-of-order update of shadow
    ShadowState shadowState = new ShadowState();
    shadowState.reported = reportedSection.get();
    UpdateNamedShadowRequest updateNamedShadowRequest = new UpdateNamedShadowRequest();
    updateNamedShadowRequest.shadowName = DEPLOYMENT_SHADOW_NAME;
    updateNamedShadowRequest.thingName = thingInfo.getThingName();
    updateNamedShadowRequest.state = shadowState;
    shadowClient.PublishUpdateNamedShadow(updateNamedShadowRequest, QualityOfService.AT_LEAST_ONCE).get(30, TimeUnit.SECONDS);
    // verify that the device updates shadow state to SUCCEEDED
    assertTrue(deviceSyncedStateToSucceededCdl.await(60, TimeUnit.SECONDS));
    // Updating the shadow with a lower version number to trigger a message to /update/rejected event
    shadowState = new ShadowState();
    shadowState.reported = reportedSection.get();
    updateNamedShadowRequest = new UpdateNamedShadowRequest();
    updateNamedShadowRequest.shadowName = DEPLOYMENT_SHADOW_NAME;
    updateNamedShadowRequest.thingName = thingInfo.getThingName();
    updateNamedShadowRequest.state = shadowState;
    updateNamedShadowRequest.version = shadowVersionWhenDeviceReportedInProgress.get();
    shadowClient.PublishUpdateNamedShadow(updateNamedShadowRequest, QualityOfService.AT_LEAST_ONCE).get(30, TimeUnit.SECONDS);
    CountDownLatch deviceRetrievedShadowCdl = new CountDownLatch(1);
    GetNamedShadowSubscriptionRequest getNamedShadowSubscriptionRequest = new GetNamedShadowSubscriptionRequest();
    getNamedShadowSubscriptionRequest.shadowName = DEPLOYMENT_SHADOW_NAME;
    getNamedShadowSubscriptionRequest.thingName = thingInfo.getThingName();
    shadowClient.SubscribeToGetNamedShadowAccepted(getNamedShadowSubscriptionRequest, QualityOfService.AT_MOST_ONCE, getShadowResponse -> {
        deviceRetrievedShadowCdl.countDown();
    }).get(30, TimeUnit.SECONDS);
    // verify that the device retrieved the shadow when an update operation was rejected.
    assertTrue(deviceRetrievedShadowCdl.await(60, TimeUnit.SECONDS));
}
Also used : BeforeEach(org.junit.jupiter.api.BeforeEach) ComponentDeploymentSpecification(software.amazon.awssdk.services.greengrassv2.model.ComponentDeploymentSpecification) HashMap(java.util.HashMap) Coerce(com.aws.greengrass.util.Coerce) StringUtils(org.apache.commons.lang3.StringUtils) AtomicReference(java.util.concurrent.atomic.AtomicReference) STATUS_KEY(com.aws.greengrass.status.DeploymentInformation.STATUS_KEY) BaseE2ETestCase(com.aws.greengrass.integrationtests.e2e.BaseE2ETestCase) ShadowState(software.amazon.awssdk.iot.iotshadow.model.ShadowState) UpdateNamedShadowRequest(software.amazon.awssdk.iot.iotshadow.model.UpdateNamedShadowRequest) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) QualityOfService(software.amazon.awssdk.crt.mqtt.QualityOfService) State(com.aws.greengrass.dependency.State) IotShadowClient(software.amazon.awssdk.iot.iotshadow.IotShadowClient) GGExtension(com.aws.greengrass.testcommons.testutilities.GGExtension) Tag(org.junit.jupiter.api.Tag) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) JobStatus(software.amazon.awssdk.iot.iotjobs.model.JobStatus) DEPLOYMENT_SHADOW_NAME(com.aws.greengrass.deployment.ShadowDeploymentListener.DEPLOYMENT_SHADOW_NAME) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) ComponentConfigurationUpdate(software.amazon.awssdk.services.greengrassv2.model.ComponentConfigurationUpdate) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) TestUtils(com.aws.greengrass.testcommons.testutilities.TestUtils) EventuallyLambdaMatcher.eventuallyEval(com.github.grantwest.eventually.EventuallyLambdaMatcher.eventuallyEval) Test(org.junit.jupiter.api.Test) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) Topics(com.aws.greengrass.config.Topics) Slf4jLogAdapter(com.aws.greengrass.logging.impl.Slf4jLogAdapter) WrapperMqttClientConnection(com.aws.greengrass.mqttclient.WrapperMqttClientConnection) CountDownLatch(java.util.concurrent.CountDownLatch) AfterEach(org.junit.jupiter.api.AfterEach) Utils(com.aws.greengrass.util.Utils) UpdateNamedShadowSubscriptionRequest(software.amazon.awssdk.iot.iotshadow.model.UpdateNamedShadowSubscriptionRequest) CreateDeploymentRequest(software.amazon.awssdk.services.greengrassv2.model.CreateDeploymentRequest) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) MqttClient(com.aws.greengrass.mqttclient.MqttClient) Matchers.is(org.hamcrest.Matchers.is) GreengrassLogMessage(com.aws.greengrass.logging.impl.GreengrassLogMessage) GetNamedShadowSubscriptionRequest(software.amazon.awssdk.iot.iotshadow.model.GetNamedShadowSubscriptionRequest) HashMap(java.util.HashMap) CreateDeploymentRequest(software.amazon.awssdk.services.greengrassv2.model.CreateDeploymentRequest) AtomicReference(java.util.concurrent.atomic.AtomicReference) WrapperMqttClientConnection(com.aws.greengrass.mqttclient.WrapperMqttClientConnection) UpdateNamedShadowRequest(software.amazon.awssdk.iot.iotshadow.model.UpdateNamedShadowRequest) CountDownLatch(java.util.concurrent.CountDownLatch) UpdateNamedShadowSubscriptionRequest(software.amazon.awssdk.iot.iotshadow.model.UpdateNamedShadowSubscriptionRequest) IotShadowClient(software.amazon.awssdk.iot.iotshadow.IotShadowClient) GetNamedShadowSubscriptionRequest(software.amazon.awssdk.iot.iotshadow.model.GetNamedShadowSubscriptionRequest) ShadowState(software.amazon.awssdk.iot.iotshadow.model.ShadowState) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) Test(org.junit.jupiter.api.Test)

Example 2 with ShadowState

use of software.amazon.awssdk.iot.iotshadow.model.ShadowState in project aws-iot-device-sdk-java-v2 by aws.

the class ShadowSample method changeShadowValue.

static CompletableFuture<Void> changeShadowValue(String value) {
    if (localValue != null) {
        if (localValue.equals(value)) {
            System.out.println("Local value is already " + value);
            CompletableFuture<Void> result = new CompletableFuture<>();
            result.complete(null);
            return result;
        }
    }
    System.out.println("Changed local value to " + value);
    localValue = value;
    System.out.println("Updating shadow value to " + value);
    // build a request to let the service know our current value and desired value, and that we only want
    // to update if the version matches the version we know about
    UpdateShadowRequest request = new UpdateShadowRequest();
    request.thingName = thingName;
    request.state = new ShadowState();
    if (value.compareToIgnoreCase("clear_shadow") == 0) {
        request.state.desiredIsNullable = true;
        request.state.reportedIsNullable = true;
        request.state.desired = null;
        request.state.reported = null;
    } else if (value.compareToIgnoreCase("null") == 0) {
        // A bit of a hack - we have to set reportedNullIsValid OR desiredNullIsValid
        // so the JSON formatter will allow null , otherwise null will always be
        // be converted to "null"
        // As long as we're passing a Hashmap that is NOT assigned to null, it will not
        // clear the data - so we pass an empty HashMap to avoid clearing data we want to keep
        request.state.desiredIsNullable = true;
        request.state.reportedIsNullable = false;
        // We will only clear desired, so we need to pass an empty HashMap for reported
        request.state.reported = new HashMap<String, Object>() {

            {
            }
        };
        request.state.desired = new HashMap<String, Object>() {

            {
                put(SHADOW_PROPERTY, null);
            }
        };
    } else {
        request.state.reported = new HashMap<String, Object>() {

            {
                put(SHADOW_PROPERTY, value);
            }
        };
        request.state.desired = new HashMap<String, Object>() {

            {
                put(SHADOW_PROPERTY, value);
            }
        };
    }
    // Publish the request
    return shadow.PublishUpdateShadow(request, QualityOfService.AT_LEAST_ONCE).thenRun(() -> {
        System.out.println("Update request published");
    }).exceptionally((ex) -> {
        System.out.println("Update request failed: " + ex.getMessage());
        System.exit(3);
        return null;
    });
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) HashMap(java.util.HashMap) UpdateShadowRequest(software.amazon.awssdk.iot.iotshadow.model.UpdateShadowRequest) ShadowState(software.amazon.awssdk.iot.iotshadow.model.ShadowState)

Example 3 with ShadowState

use of software.amazon.awssdk.iot.iotshadow.model.ShadowState in project aws-iot-device-sdk-java-v2 by aws.

the class ShadowStateTest method TestNullSendThroughJson.

@Test
public void TestNullSendThroughJson() {
    ShadowState state = new ShadowState();
    state.desired = new HashMap<String, Object>() {

        {
            put("ThingOne", 10.0);
            put("ThingTwo", "Bob");
        }
    };
    state.reported = null;
    state.reportedIsNullable = true;
    String state_json = shadowGson.toJson(state);
    String expected_json = "{\"desired\":{\"ThingTwo\":\"Bob\",\"ThingOne\":10.0},\"reported\":null}";
    assertEquals(state_json, expected_json);
}
Also used : ShadowState(software.amazon.awssdk.iot.iotshadow.model.ShadowState) Test(org.junit.jupiter.api.Test)

Example 4 with ShadowState

use of software.amazon.awssdk.iot.iotshadow.model.ShadowState in project aws-iot-device-sdk-java-v2 by aws.

the class ShadowStateFactory method create.

public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
    Class<T> rawType = (Class<T>) type.getRawType();
    if (rawType != ShadowState.class) {
        return null;
    }
    final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
    return new TypeAdapter<T>() {

        public void write(JsonWriter out, T shadowValue) throws IOException {
            // Are null values present? If so, we need to process this differently
            ShadowState shadow = (ShadowState) shadowValue;
            if (shadow.desiredIsNullable == true || shadow.reportedIsNullable == true) {
                out.setSerializeNulls(true);
                // If a property is null but null is not valid for it, then just send an empty HashMap
                if (shadow.desired == null && shadow.desiredIsNullable == false) {
                    shadow.desired = new HashMap<String, Object>();
                }
                if (shadow.reported == null && shadow.reportedIsNullable == false) {
                    shadow.reported = new HashMap<String, Object>();
                }
                delegate.write(out, shadowValue);
                out.setSerializeNulls(false);
            } else {
                delegate.write(out, shadowValue);
            }
        }

        public T read(JsonReader in) throws IOException {
            T returnType = delegate.read(in);
            return returnType;
        }
    };
}
Also used : TypeAdapter(com.google.gson.TypeAdapter) JsonReader(com.google.gson.stream.JsonReader) ShadowState(software.amazon.awssdk.iot.iotshadow.model.ShadowState) JsonWriter(com.google.gson.stream.JsonWriter)

Example 5 with ShadowState

use of software.amazon.awssdk.iot.iotshadow.model.ShadowState in project aws-iot-device-sdk-java-v2 by aws.

the class ShadowUpdate method changeShadowValue.

static CompletableFuture<Integer> changeShadowValue() {
    // build a request to let the service know our current value and desired value, and that we only want
    // to update if the version matches the version we know about
    UpdateShadowRequest request = new UpdateShadowRequest();
    request.thingName = DATestUtils.thing_name;
    request.state = new ShadowState();
    request.state.reported = new HashMap<String, Object>() {

        {
            put(DATestUtils.shadowProperty, DATestUtils.shadowValue);
        }
    };
    request.state.desired = new HashMap<String, Object>() {

        {
            put(DATestUtils.shadowProperty, DATestUtils.shadowValue);
        }
    };
    // Publish the request
    return shadow.PublishUpdateShadow(request, QualityOfService.AT_MOST_ONCE);
}
Also used : UpdateShadowRequest(software.amazon.awssdk.iot.iotshadow.model.UpdateShadowRequest) ShadowState(software.amazon.awssdk.iot.iotshadow.model.ShadowState)

Aggregations

ShadowState (software.amazon.awssdk.iot.iotshadow.model.ShadowState)8 Test (org.junit.jupiter.api.Test)4 HashMap (java.util.HashMap)2 Topics (com.aws.greengrass.config.Topics)1 State (com.aws.greengrass.dependency.State)1 DEPLOYMENT_SHADOW_NAME (com.aws.greengrass.deployment.ShadowDeploymentListener.DEPLOYMENT_SHADOW_NAME)1 BaseE2ETestCase (com.aws.greengrass.integrationtests.e2e.BaseE2ETestCase)1 GreengrassLogMessage (com.aws.greengrass.logging.impl.GreengrassLogMessage)1 Slf4jLogAdapter (com.aws.greengrass.logging.impl.Slf4jLogAdapter)1 MqttClient (com.aws.greengrass.mqttclient.MqttClient)1 WrapperMqttClientConnection (com.aws.greengrass.mqttclient.WrapperMqttClientConnection)1 STATUS_KEY (com.aws.greengrass.status.DeploymentInformation.STATUS_KEY)1 GGExtension (com.aws.greengrass.testcommons.testutilities.GGExtension)1 TestUtils (com.aws.greengrass.testcommons.testutilities.TestUtils)1 Coerce (com.aws.greengrass.util.Coerce)1 Utils (com.aws.greengrass.util.Utils)1 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)1 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)1 EventuallyLambdaMatcher.eventuallyEval (com.github.grantwest.eventually.EventuallyLambdaMatcher.eventuallyEval)1 TypeAdapter (com.google.gson.TypeAdapter)1