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));
}
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;
});
}
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);
}
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;
}
};
}
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);
}
Aggregations