diff --git a/.doc_gen/metadata/iam_metadata.yaml b/.doc_gen/metadata/iam_metadata.yaml
index 0bda611f2a6..d93258f88e9 100644
--- a/.doc_gen/metadata/iam_metadata.yaml
+++ b/.doc_gen/metadata/iam_metadata.yaml
@@ -1487,6 +1487,14 @@ iam_GetPolicyVersion:
- description:
snippet_tags:
- python.example_code.iam.GetPolicyVersion
+ SAP ABAP:
+ versions:
+ - sdk_version: 1
+ github: sap-abap/services/iam
+ excerpts:
+ - description:
+ snippet_tags:
+ - iam.abapv1.get_policy_version
services:
iam: {GetPolicyVersion}
iam_Scenario_RollbackPolicyVersion:
diff --git a/.doc_gen/metadata/iot-data_metadata.yaml b/.doc_gen/metadata/iot-data_metadata.yaml
index f48bdfcfd29..98a1eda3da1 100644
--- a/.doc_gen/metadata/iot-data_metadata.yaml
+++ b/.doc_gen/metadata/iot-data_metadata.yaml
@@ -43,6 +43,14 @@ iot-data-plane_GetThingShadow:
- description:
snippet_tags:
- cpp.example_code.iot.GetThingShadow
+ SAP ABAP:
+ versions:
+ - sdk_version: 1
+ github: sap-abap/services/iop
+ excerpts:
+ - description:
+ snippet_tags:
+ - iop.abapv1.get_thing_shadow
services:
iot-data-plane: {GetThingShadow}
iot-data-plane_UpdateThingShadow:
@@ -89,5 +97,13 @@ iot-data-plane_UpdateThingShadow:
- description:
snippet_tags:
- cpp.example_code.iot.UpdateThingShadow
+ SAP ABAP:
+ versions:
+ - sdk_version: 1
+ github: sap-abap/services/iop
+ excerpts:
+ - description:
+ snippet_tags:
+ - iop.abapv1.update_thing_shadow
services:
iot-data-plane: {UpdateThingShadow}
diff --git a/.tools/readmes/config.py b/.tools/readmes/config.py
index 0d8733eddb4..0dd797bf232 100644
--- a/.tools/readmes/config.py
+++ b/.tools/readmes/config.py
@@ -211,6 +211,7 @@
"firehose": "sap-abap/services/frh",
"glue": "sap-abap/services/glu",
"healthlake": "sap-abap/services/hll",
+ "iot-data-plane": "sap-abap/services/iop",
"iotsitewise": "sap-abap/services/ios",
"keyspaces": "sap-abap/services/kys",
"kinesis": "sap-abap/services/kns",
diff --git a/sap-abap/services/iam/#awsex#cl_iam_actions.clas.abap b/sap-abap/services/iam/#awsex#cl_iam_actions.clas.abap
index 18a00a39c34..3a34d67c9f2 100644
--- a/sap-abap/services/iam/#awsex#cl_iam_actions.clas.abap
+++ b/sap-abap/services/iam/#awsex#cl_iam_actions.clas.abap
@@ -280,6 +280,15 @@ CLASS /awsex/cl_iam_actions DEFINITION
RAISING
/aws1/cx_rt_generic.
+ METHODS get_policy_version
+ IMPORTING
+ !iv_policy_arn TYPE /aws1/iamarntype
+ !iv_version_id TYPE /aws1/iampolicyversionidtype
+ EXPORTING
+ !oo_result TYPE REF TO /aws1/cl_iamgetpolicyvrsrsp
+ RAISING
+ /aws1/cx_rt_generic.
+
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
@@ -1027,4 +1036,25 @@ CLASS /AWSEX/CL_IAM_ACTIONS IMPLEMENTATION.
ENDTRY.
" snippet-end:[iam.abapv1.delete_policy_version]
ENDMETHOD.
+
+
+ METHOD get_policy_version.
+ CONSTANTS cv_pfl TYPE /aws1/rt_profile_id VALUE 'ZCODE_DEMO'.
+
+ DATA(lo_session) = /aws1/cl_rt_session_aws=>create( cv_pfl ).
+ DATA(lo_iam) = /aws1/cl_iam_factory=>create( lo_session ).
+
+ " snippet-start:[iam.abapv1.get_policy_version]
+ TRY.
+ oo_result = lo_iam->getpolicyversion(
+ iv_policyarn = iv_policy_arn
+ iv_versionid = iv_version_id ).
+ MESSAGE 'Retrieved policy version information.' TYPE 'I'.
+ CATCH /aws1/cx_iamnosuchentityex.
+ MESSAGE 'Policy or version does not exist.' TYPE 'E'.
+ CATCH /aws1/cx_iaminvalidinputex.
+ MESSAGE 'Invalid input provided.' TYPE 'E'.
+ ENDTRY.
+ " snippet-end:[iam.abapv1.get_policy_version]
+ ENDMETHOD.
ENDCLASS.
diff --git a/sap-abap/services/iam/#awsex#cl_iam_actions.clas.testclasses.abap b/sap-abap/services/iam/#awsex#cl_iam_actions.clas.testclasses.abap
index 7b616c0c083..43d1f5c43f5 100644
--- a/sap-abap/services/iam/#awsex#cl_iam_actions.clas.testclasses.abap
+++ b/sap-abap/services/iam/#awsex#cl_iam_actions.clas.testclasses.abap
@@ -67,6 +67,7 @@ CLASS ltc_awsex_cl_iam_actions DEFINITION FOR TESTING DURATION LONG RISK LEVEL D
list_saml_providers FOR TESTING RAISING /aws1/cx_rt_generic,
create_service_linked_role FOR TESTING RAISING /aws1/cx_rt_generic,
list_policy_versions FOR TESTING RAISING /aws1/cx_rt_generic,
+ get_policy_version FOR TESTING RAISING /aws1/cx_rt_generic,
set_default_policy_version FOR TESTING RAISING /aws1/cx_rt_generic,
delete_policy_version FOR TESTING RAISING /aws1/cx_rt_generic.
@@ -1507,6 +1508,56 @@ CLASS ltc_awsex_cl_iam_actions IMPLEMENTATION.
msg = |Policy should have a default version| ).
ENDMETHOD.
+
+ METHOD get_policy_version.
+ DATA lo_result TYPE REF TO /aws1/cl_iamgetpolicyvrsrsp.
+ DATA lv_version_id TYPE /aws1/iampolicyversionidtype.
+
+ " Use test policy created in class_setup
+ " First get the list of versions to find the default version ID
+ DATA(lo_list_result) = ao_iam->listpolicyversions( iv_policyarn = av_test_policy_arn ).
+ DATA(lt_versions) = lo_list_result->get_versions( ).
+
+ " Find the default version
+ LOOP AT lt_versions INTO DATA(lo_version).
+ IF lo_version->get_isdefaultversion( ) = abap_true.
+ lv_version_id = lo_version->get_versionid( ).
+ EXIT.
+ ENDIF.
+ ENDLOOP.
+
+ cl_abap_unit_assert=>assert_not_initial(
+ act = lv_version_id
+ msg = |Default policy version ID should be found| ).
+
+ " Now get the policy version details
+ ao_iam_actions->get_policy_version(
+ EXPORTING
+ iv_policy_arn = av_test_policy_arn
+ iv_version_id = lv_version_id
+ IMPORTING
+ oo_result = lo_result ).
+
+ cl_abap_unit_assert=>assert_bound(
+ act = lo_result
+ msg = |Get policy version result should not be initial| ).
+
+ DATA(lo_policy_version) = lo_result->get_policyversion( ).
+ cl_abap_unit_assert=>assert_bound(
+ act = lo_policy_version
+ msg = |Policy version should not be initial| ).
+
+ cl_abap_unit_assert=>assert_equals(
+ exp = lv_version_id
+ act = lo_policy_version->get_versionid( )
+ msg = |Version ID should match| ).
+
+ cl_abap_unit_assert=>assert_not_initial(
+ act = lo_policy_version->get_document( )
+ msg = |Policy document should not be initial| ).
+ ENDMETHOD.
+
+
METHOD set_default_policy_version.
DATA lv_new_policy_doc TYPE string.
DATA lv_version_id TYPE /aws1/iampolicyversionidtype.
diff --git a/sap-abap/services/iam/README.md b/sap-abap/services/iam/README.md
index a5ce4acae6b..7f6b58ed71a 100644
--- a/sap-abap/services/iam/README.md
+++ b/sap-abap/services/iam/README.md
@@ -33,44 +33,45 @@ For prerequisites, see the [README](../../README.md#Prerequisites) in the `sap-a
Code excerpts that show you how to call individual service functions.
-- [AttachRolePolicy](%23awsex%23cl_iam_actions.clas.abap#L689)
-- [AttachUserPolicy](%23awsex%23cl_iam_actions.clas.abap#L573)
-- [CreateAccessKey](%23awsex%23cl_iam_actions.clas.abap#L377)
-- [CreateAccountAlias](%23awsex%23cl_iam_actions.clas.abap#L782)
-- [CreatePolicy](%23awsex%23cl_iam_actions.clas.abap#L472)
-- [CreatePolicyVersion](%23awsex%23cl_iam_actions.clas.abap#L549)
-- [CreateRole](%23awsex%23cl_iam_actions.clas.abap#L613)
-- [CreateServiceLinkedRole](%23awsex%23cl_iam_actions.clas.abap#L972)
-- [CreateUser](%23awsex%23cl_iam_actions.clas.abap#L298)
-- [DeleteAccessKey](%23awsex%23cl_iam_actions.clas.abap#L397)
-- [DeleteAccountAlias](%23awsex%23cl_iam_actions.clas.abap#L802)
-- [DeletePolicy](%23awsex%23cl_iam_actions.clas.abap#L496)
-- [DeletePolicyVersion](%23awsex%23cl_iam_actions.clas.abap#L1015)
-- [DeleteRole](%23awsex%23cl_iam_actions.clas.abap#L636)
-- [DeleteUser](%23awsex%23cl_iam_actions.clas.abap#L320)
-- [DetachRolePolicy](%23awsex%23cl_iam_actions.clas.abap#L710)
-- [DetachUserPolicy](%23awsex%23cl_iam_actions.clas.abap#L594)
-- [GenerateCredentialReport](%23awsex%23cl_iam_actions.clas.abap#L871)
-- [GetAccessKeyLastUsed](%23awsex%23cl_iam_actions.clas.abap#L454)
-- [GetAccountAuthorizationDetails](%23awsex%23cl_iam_actions.clas.abap#L837)
-- [GetAccountPasswordPolicy](%23awsex%23cl_iam_actions.clas.abap#L913)
-- [GetAccountSummary](%23awsex%23cl_iam_actions.clas.abap#L854)
-- [GetCredentialReport](%23awsex%23cl_iam_actions.clas.abap#L890)
-- [GetPolicy](%23awsex%23cl_iam_actions.clas.abap#L532)
-- [GetRole](%23awsex%23cl_iam_actions.clas.abap#L655)
-- [ListAccessKeys](%23awsex%23cl_iam_actions.clas.abap#L416)
-- [ListAccountAliases](%23awsex%23cl_iam_actions.clas.abap#L820)
-- [ListAttachedRolePolicies](%23awsex%23cl_iam_actions.clas.abap#L729)
-- [ListGroups](%23awsex%23cl_iam_actions.clas.abap#L765)
-- [ListPolicies](%23awsex%23cl_iam_actions.clas.abap#L515)
-- [ListPolicyVersions](%23awsex%23cl_iam_actions.clas.abap#L972)
-- [ListRolePolicies](%23awsex%23cl_iam_actions.clas.abap#L747)
-- [ListRoles](%23awsex%23cl_iam_actions.clas.abap#L672)
-- [ListSAMLProviders](%23awsex%23cl_iam_actions.clas.abap#L932)
-- [ListUsers](%23awsex%23cl_iam_actions.clas.abap#L339)
-- [SetDefaultPolicyVersion](%23awsex%23cl_iam_actions.clas.abap#L992)
-- [UpdateAccessKey](%23awsex%23cl_iam_actions.clas.abap#L434)
-- [UpdateUser](%23awsex%23cl_iam_actions.clas.abap#L356)
+- [AttachRolePolicy](%23awsex%23cl_iam_actions.clas.abap#L698)
+- [AttachUserPolicy](%23awsex%23cl_iam_actions.clas.abap#L582)
+- [CreateAccessKey](%23awsex%23cl_iam_actions.clas.abap#L386)
+- [CreateAccountAlias](%23awsex%23cl_iam_actions.clas.abap#L791)
+- [CreatePolicy](%23awsex%23cl_iam_actions.clas.abap#L481)
+- [CreatePolicyVersion](%23awsex%23cl_iam_actions.clas.abap#L558)
+- [CreateRole](%23awsex%23cl_iam_actions.clas.abap#L622)
+- [CreateServiceLinkedRole](%23awsex%23cl_iam_actions.clas.abap#L981)
+- [CreateUser](%23awsex%23cl_iam_actions.clas.abap#L307)
+- [DeleteAccessKey](%23awsex%23cl_iam_actions.clas.abap#L406)
+- [DeleteAccountAlias](%23awsex%23cl_iam_actions.clas.abap#L811)
+- [DeletePolicy](%23awsex%23cl_iam_actions.clas.abap#L505)
+- [DeletePolicyVersion](%23awsex%23cl_iam_actions.clas.abap#L1024)
+- [DeleteRole](%23awsex%23cl_iam_actions.clas.abap#L645)
+- [DeleteUser](%23awsex%23cl_iam_actions.clas.abap#L329)
+- [DetachRolePolicy](%23awsex%23cl_iam_actions.clas.abap#L719)
+- [DetachUserPolicy](%23awsex%23cl_iam_actions.clas.abap#L603)
+- [GenerateCredentialReport](%23awsex%23cl_iam_actions.clas.abap#L880)
+- [GetAccessKeyLastUsed](%23awsex%23cl_iam_actions.clas.abap#L463)
+- [GetAccountAuthorizationDetails](%23awsex%23cl_iam_actions.clas.abap#L846)
+- [GetAccountPasswordPolicy](%23awsex%23cl_iam_actions.clas.abap#L922)
+- [GetAccountSummary](%23awsex%23cl_iam_actions.clas.abap#L863)
+- [GetCredentialReport](%23awsex%23cl_iam_actions.clas.abap#L899)
+- [GetPolicy](%23awsex%23cl_iam_actions.clas.abap#L541)
+- [GetPolicyVersion](%23awsex%23cl_iam_actions.clas.abap#L1047)
+- [GetRole](%23awsex%23cl_iam_actions.clas.abap#L664)
+- [ListAccessKeys](%23awsex%23cl_iam_actions.clas.abap#L425)
+- [ListAccountAliases](%23awsex%23cl_iam_actions.clas.abap#L829)
+- [ListAttachedRolePolicies](%23awsex%23cl_iam_actions.clas.abap#L738)
+- [ListGroups](%23awsex%23cl_iam_actions.clas.abap#L774)
+- [ListPolicies](%23awsex%23cl_iam_actions.clas.abap#L524)
+- [ListPolicyVersions](%23awsex%23cl_iam_actions.clas.abap#L981)
+- [ListRolePolicies](%23awsex%23cl_iam_actions.clas.abap#L756)
+- [ListRoles](%23awsex%23cl_iam_actions.clas.abap#L681)
+- [ListSAMLProviders](%23awsex%23cl_iam_actions.clas.abap#L941)
+- [ListUsers](%23awsex%23cl_iam_actions.clas.abap#L348)
+- [SetDefaultPolicyVersion](%23awsex%23cl_iam_actions.clas.abap#L1001)
+- [UpdateAccessKey](%23awsex%23cl_iam_actions.clas.abap#L443)
+- [UpdateUser](%23awsex%23cl_iam_actions.clas.abap#L365)
diff --git a/sap-abap/services/iop/#awsex#cl_iop_actions.clas.abap b/sap-abap/services/iop/#awsex#cl_iop_actions.clas.abap
new file mode 100644
index 00000000000..a06058bcba0
--- /dev/null
+++ b/sap-abap/services/iop/#awsex#cl_iop_actions.clas.abap
@@ -0,0 +1,87 @@
+" Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+" SPDX-License-Identifier: Apache-2.0
+CLASS /awsex/cl_iop_actions DEFINITION
+ PUBLIC
+ FINAL
+ CREATE PUBLIC .
+
+ PUBLIC SECTION.
+ " Updates the shadow for an AWS IoT thing
+ " @parameter iv_thing_name | The name of the thing (e.g., 'MyIoTDevice')
+ " @parameter iv_shadow_state | The shadow state as JSON string
+ " @raising /aws1/cx_rt_generic | Thrown when operation fails
+ METHODS update_thing_shadow
+ IMPORTING
+ !iv_thing_name TYPE /aws1/iopthingname
+ !iv_shadow_state TYPE string
+ RAISING
+ /aws1/cx_rt_generic.
+
+ " Gets the shadow for an AWS IoT thing
+ " @parameter iv_thing_name | The name of the thing (e.g., 'MyIoTDevice')
+ " @parameter ov_shadow | The shadow state as JSON string
+ " @raising /aws1/cx_rt_generic | Thrown when operation fails
+ METHODS get_thing_shadow
+ IMPORTING
+ !iv_thing_name TYPE /aws1/iopthingname
+ RETURNING
+ VALUE(ov_shadow) TYPE string
+ RAISING
+ /aws1/cx_rt_generic.
+
+ PROTECTED SECTION.
+ PRIVATE SECTION.
+ENDCLASS.
+
+
+
+CLASS /awsex/cl_iop_actions IMPLEMENTATION.
+
+ METHOD update_thing_shadow.
+ CONSTANTS cv_pfl TYPE /aws1/rt_profile_id VALUE 'ZCODE_DEMO'.
+
+ DATA(lo_session) = /aws1/cl_rt_session_aws=>create( cv_pfl ).
+ DATA(lo_iop) = /aws1/cl_iop_factory=>create( lo_session ).
+
+ " snippet-start:[iop.abapv1.update_thing_shadow]
+ TRY.
+ " Convert JSON string to xstring for payload
+ DATA(lv_payload) = /aws1/cl_rt_util=>string_to_xstring( iv_shadow_state ).
+
+ lo_iop->updatethingshadow(
+ iv_thingname = iv_thing_name
+ iv_payload = lv_payload ).
+ MESSAGE 'Thing shadow updated successfully.' TYPE 'I'.
+ CATCH /aws1/cx_iopresourcenotfoundex.
+ MESSAGE 'Thing not found.' TYPE 'E'.
+ CATCH /aws1/cx_rt_generic INTO DATA(lo_exception).
+ DATA(lv_error) = |{ lo_exception->get_text( ) }|.
+ MESSAGE lv_error TYPE 'E'.
+ ENDTRY.
+ " snippet-end:[iop.abapv1.update_thing_shadow]
+ ENDMETHOD.
+
+ METHOD get_thing_shadow.
+ CONSTANTS cv_pfl TYPE /aws1/rt_profile_id VALUE 'ZCODE_DEMO'.
+
+ DATA(lo_session) = /aws1/cl_rt_session_aws=>create( cv_pfl ).
+ DATA(lo_iop) = /aws1/cl_iop_factory=>create( lo_session ).
+
+ " snippet-start:[iop.abapv1.get_thing_shadow]
+ TRY.
+ DATA(lo_result) = lo_iop->getthingshadow( iv_thingname = iv_thing_name ).
+
+ " Convert xstring payload to JSON string
+ DATA(lv_payload) = lo_result->get_payload( ).
+ ov_shadow = /aws1/cl_rt_util=>xstring_to_string( lv_payload ).
+ MESSAGE 'Thing shadow retrieved successfully.' TYPE 'I'.
+ CATCH /aws1/cx_iopresourcenotfoundex.
+ MESSAGE 'Thing shadow not found.' TYPE 'E'.
+ CATCH /aws1/cx_rt_generic INTO DATA(lo_exception).
+ DATA(lv_error) = |{ lo_exception->get_text( ) }|.
+ MESSAGE lv_error TYPE 'E'.
+ ENDTRY.
+ " snippet-end:[iop.abapv1.get_thing_shadow]
+ ENDMETHOD.
+
+ENDCLASS.
diff --git a/sap-abap/services/iop/#awsex#cl_iop_actions.clas.testclasses.abap b/sap-abap/services/iop/#awsex#cl_iop_actions.clas.testclasses.abap
new file mode 100644
index 00000000000..afa22941dd5
--- /dev/null
+++ b/sap-abap/services/iop/#awsex#cl_iop_actions.clas.testclasses.abap
@@ -0,0 +1,289 @@
+" Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+" SPDX-License-Identifier: Apache-2.0
+CLASS ltc_awsex_cl_iop_actions DEFINITION DEFERRED.
+CLASS /awsex/cl_iop_actions DEFINITION LOCAL FRIENDS ltc_awsex_cl_iop_actions.
+
+CLASS ltc_awsex_cl_iop_actions DEFINITION FOR TESTING DURATION LONG RISK LEVEL DANGEROUS.
+
+ PRIVATE SECTION.
+ CONSTANTS cv_pfl TYPE /aws1/rt_profile_id VALUE 'ZCODE_DEMO'.
+
+ CLASS-DATA ao_iot TYPE REF TO /aws1/if_iot.
+ CLASS-DATA ao_iop TYPE REF TO /aws1/if_iop.
+ CLASS-DATA ao_session TYPE REF TO /aws1/cl_rt_session_base.
+ CLASS-DATA ao_iop_actions TYPE REF TO /awsex/cl_iop_actions.
+
+ CLASS-DATA av_thing_name TYPE /aws1/iopthingname.
+
+ METHODS: update_thing_shadow FOR TESTING RAISING /aws1/cx_rt_generic,
+ get_thing_shadow FOR TESTING RAISING /aws1/cx_rt_generic.
+
+ CLASS-METHODS class_setup RAISING /aws1/cx_rt_generic.
+ CLASS-METHODS class_teardown RAISING /aws1/cx_rt_generic.
+
+ CLASS-METHODS wait_for_thing_ready
+ IMPORTING
+ iv_thing_name TYPE /aws1/iotthingname
+ iv_max_wait TYPE i DEFAULT 30
+ RAISING
+ /aws1/cx_rt_generic.
+
+ENDCLASS.
+
+CLASS ltc_awsex_cl_iop_actions IMPLEMENTATION.
+
+ METHOD class_setup.
+ ao_session = /aws1/cl_rt_session_aws=>create( cv_pfl ).
+ ao_iot = /aws1/cl_iot_factory=>create( ao_session ).
+ ao_iop = /aws1/cl_iop_factory=>create( ao_session ).
+ ao_iop_actions = NEW /awsex/cl_iop_actions( ).
+
+ " Create a test thing for shadow operations - MUST succeed
+ DATA(lv_uuid) = /awsex/cl_utils=>get_random_string( ).
+ av_thing_name = |sap-abap-iot-shadow-{ lv_uuid }|.
+
+ TRY.
+ DATA(lo_thing_result) = ao_iot->creatething( iv_thingname = av_thing_name ).
+
+ IF lo_thing_result IS NOT BOUND.
+ MESSAGE 'Failed to create IoT thing for shadow tests' TYPE 'E'.
+ ENDIF.
+
+ " Verify thing was created
+ cl_abap_unit_assert=>assert_not_initial(
+ act = lo_thing_result->get_thingname( )
+ msg = |Thing name is initial after creation| ).
+
+ CATCH /aws1/cx_iotresrcalrdyexistsex.
+ " Thing already exists - verify it's accessible
+ TRY.
+ ao_iot->describething( iv_thingname = av_thing_name ).
+ CATCH /aws1/cx_rt_generic INTO DATA(lo_desc_ex).
+ MESSAGE |Thing exists but cannot be accessed: { lo_desc_ex->get_text( ) }| TYPE 'E'.
+ ENDTRY.
+ CATCH /aws1/cx_rt_generic INTO DATA(lo_create_ex).
+ MESSAGE |Failed to create thing: { lo_create_ex->get_text( ) }| TYPE 'E'.
+ ENDTRY.
+
+ " Wait for thing to be fully ready
+ wait_for_thing_ready( iv_thing_name = av_thing_name ).
+
+ ENDMETHOD.
+
+ METHOD class_teardown.
+ " Clean up test thing
+ IF av_thing_name IS NOT INITIAL.
+ TRY.
+ " Delete the thing shadow first if it exists
+ TRY.
+ ao_iop->deletethingshadow( iv_thingname = av_thing_name ).
+ " Wait for shadow deletion to propagate
+ WAIT UP TO 2 SECONDS.
+ CATCH /aws1/cx_rt_generic.
+ " Shadow may not exist
+ ENDTRY.
+
+ " Delete the thing
+ ao_iot->deletething( iv_thingname = av_thing_name ).
+ CATCH /aws1/cx_rt_generic.
+ " Thing may not exist or may have dependencies
+ ENDTRY.
+ ENDIF.
+
+ ENDMETHOD.
+
+ METHOD wait_for_thing_ready.
+ " Wait for thing to be ready with status-based polling
+ DATA lv_elapsed TYPE i VALUE 0.
+ DATA lv_ready TYPE abap_bool VALUE abap_false.
+ DATA lv_start_time TYPE timestampl.
+ DATA lv_current_time TYPE timestampl.
+
+ GET TIME STAMP FIELD lv_start_time.
+
+ WHILE lv_elapsed < iv_max_wait AND lv_ready = abap_false.
+ TRY.
+ " Try to describe the thing
+ DATA(lo_thing_desc) = ao_iot->describething( iv_thingname = iv_thing_name ).
+ IF lo_thing_desc IS BOUND.
+ lv_ready = abap_true.
+ ELSE.
+ WAIT UP TO 2 SECONDS.
+ GET TIME STAMP FIELD lv_current_time.
+ lv_elapsed = lv_current_time - lv_start_time.
+ ENDIF.
+
+ CATCH /aws1/cx_rt_generic.
+ " Thing not ready yet
+ WAIT UP TO 2 SECONDS.
+ GET TIME STAMP FIELD lv_current_time.
+ lv_elapsed = lv_current_time - lv_start_time.
+ ENDTRY.
+ ENDWHILE.
+
+ IF lv_ready = abap_false.
+ MESSAGE 'Thing did not become ready in time' TYPE 'E'.
+ ENDIF.
+
+ ENDMETHOD.
+
+ METHOD update_thing_shadow.
+ " Verify thing exists
+ TRY.
+ ao_iot->describething( iv_thingname = av_thing_name ).
+ CATCH /aws1/cx_rt_generic INTO DATA(lo_verify_ex).
+ MESSAGE |Thing does not exist: { lo_verify_ex->get_text( ) }| TYPE 'E'.
+ ENDTRY.
+
+ " Create a shadow state JSON
+ DATA lv_shadow_state TYPE string.
+ lv_shadow_state =
+ '{"state":{"desired":{"temperature":25,"humidity":60},"reported":{"temperature":24,"humidity":58}}}'.
+
+ " Update thing shadow - this MUST succeed
+ ao_iop_actions->update_thing_shadow(
+ iv_thing_name = av_thing_name
+ iv_shadow_state = lv_shadow_state ).
+
+ " Wait for shadow to be updated
+ WAIT UP TO 3 SECONDS.
+
+ " Verify shadow was updated by getting it - MUST be retrievable
+ DATA(lo_shadow_result) = ao_iop->getthingshadow( iv_thingname = av_thing_name ).
+
+ cl_abap_unit_assert=>assert_bound(
+ act = lo_shadow_result
+ msg = |Shadow result is not bound| ).
+
+ DATA(lv_payload) = lo_shadow_result->get_payload( ).
+
+ cl_abap_unit_assert=>assert_not_initial(
+ act = lv_payload
+ msg = |Shadow payload is empty| ).
+
+ " Convert payload to string and verify it contains expected data
+ DATA(lv_shadow_json) = /aws1/cl_rt_util=>xstring_to_string( lv_payload ).
+
+ cl_abap_unit_assert=>assert_not_initial(
+ act = lv_shadow_json
+ msg = |Shadow JSON is empty| ).
+
+ " Verify shadow structure - MUST contain expected fields
+ cl_abap_unit_assert=>assert_differs(
+ act = find( val = lv_shadow_json sub = 'state' )
+ exp = -1
+ msg = |Shadow does not contain state field| ).
+
+ cl_abap_unit_assert=>assert_differs(
+ act = find( val = lv_shadow_json sub = 'desired' )
+ exp = -1
+ msg = |Shadow does not contain desired state| ).
+
+ cl_abap_unit_assert=>assert_differs(
+ act = find( val = lv_shadow_json sub = 'reported' )
+ exp = -1
+ msg = |Shadow does not contain reported state| ).
+
+ " Verify our test values are present
+ cl_abap_unit_assert=>assert_differs(
+ act = find( val = lv_shadow_json sub = 'temperature' )
+ exp = -1
+ msg = |Shadow does not contain temperature field| ).
+
+ cl_abap_unit_assert=>assert_differs(
+ act = find( val = lv_shadow_json sub = 'humidity' )
+ exp = -1
+ msg = |Shadow does not contain humidity field| ).
+
+ ENDMETHOD.
+
+ METHOD get_thing_shadow.
+ " Verify thing exists
+ TRY.
+ ao_iot->describething( iv_thingname = av_thing_name ).
+ CATCH /aws1/cx_rt_generic INTO DATA(lo_verify_ex).
+ MESSAGE |Thing does not exist: { lo_verify_ex->get_text( ) }| TYPE 'E'.
+ ENDTRY.
+
+ " First ensure shadow exists by updating it
+ DATA lv_shadow_state TYPE string.
+ lv_shadow_state =
+ '{"state":{"desired":{"power":"on","level":75},"reported":{"power":"on","level":70}}}'.
+
+ TRY.
+ ao_iop->updatethingshadow(
+ iv_thingname = av_thing_name
+ iv_payload = /aws1/cl_rt_util=>string_to_xstring( lv_shadow_state ) ).
+ CATCH /aws1/cx_rt_generic INTO DATA(lo_update_ex).
+ MESSAGE |Failed to create shadow for test: { lo_update_ex->get_text( ) }| TYPE 'E'.
+ ENDTRY.
+
+ " Wait for shadow to be updated with status-based polling
+ DATA lv_shadow_ready TYPE abap_bool VALUE abap_false.
+ DATA lv_retry_count TYPE i VALUE 0.
+
+ WHILE lv_retry_count < 10 AND lv_shadow_ready = abap_false.
+ TRY.
+ DATA(lo_check_shadow) = ao_iop->getthingshadow( iv_thingname = av_thing_name ).
+ IF lo_check_shadow IS BOUND AND lo_check_shadow->get_payload( ) IS NOT INITIAL.
+ lv_shadow_ready = abap_true.
+ ELSE.
+ lv_retry_count = lv_retry_count + 1.
+ WAIT UP TO 2 SECONDS.
+ ENDIF.
+ CATCH /aws1/cx_rt_generic.
+ lv_retry_count = lv_retry_count + 1.
+ IF lv_retry_count < 10.
+ WAIT UP TO 2 SECONDS.
+ ELSE.
+ MESSAGE 'Shadow did not become ready in time' TYPE 'E'.
+ ENDIF.
+ ENDTRY.
+ ENDWHILE.
+
+ IF lv_shadow_ready = abap_false.
+ MESSAGE 'Shadow was not created successfully' TYPE 'E'.
+ ENDIF.
+
+ " Now get the shadow using our action method - this MUST succeed
+ DATA(lv_shadow) = ao_iop_actions->get_thing_shadow( iv_thing_name = av_thing_name ).
+
+ cl_abap_unit_assert=>assert_not_initial(
+ act = lv_shadow
+ msg = |Shadow is empty| ).
+
+ " Verify shadow contains expected structure - MUST contain these fields
+ cl_abap_unit_assert=>assert_differs(
+ act = find( val = lv_shadow sub = 'state' )
+ exp = -1
+ msg = |Shadow does not contain state| ).
+
+ cl_abap_unit_assert=>assert_differs(
+ act = find( val = lv_shadow sub = 'desired' )
+ exp = -1
+ msg = |Shadow does not contain desired state| ).
+
+ cl_abap_unit_assert=>assert_differs(
+ act = find( val = lv_shadow sub = 'reported' )
+ exp = -1
+ msg = |Shadow does not contain reported state| ).
+
+ " Verify it contains our test values - MUST contain these fields
+ cl_abap_unit_assert=>assert_differs(
+ act = find( val = lv_shadow sub = 'power' )
+ exp = -1
+ msg = |Shadow does not contain power field| ).
+
+ cl_abap_unit_assert=>assert_differs(
+ act = find( val = lv_shadow sub = 'level' )
+ exp = -1
+ msg = |Shadow does not contain level field| ).
+
+ " Verify the actual values are correct
+ cl_abap_unit_assert=>assert_true(
+ act = xsdbool( find( val = lv_shadow sub = '75' ) >= 0 OR find( val = lv_shadow sub = '"level":75' ) >= 0 )
+ msg = |Shadow does not contain expected level value 75| ).
+
+ ENDMETHOD.
+
+ENDCLASS.
diff --git a/sap-abap/services/iop/#awsex#cl_iop_actions.clas.xml b/sap-abap/services/iop/#awsex#cl_iop_actions.clas.xml
new file mode 100644
index 00000000000..e19f0a776f3
--- /dev/null
+++ b/sap-abap/services/iop/#awsex#cl_iop_actions.clas.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+ /AWSEX/CL_IOP_ACTIONS
+ E
+ Iot-data-plane Code Example
+ 1
+ X
+ X
+ X
+ X
+
+
+
+
\ No newline at end of file
diff --git a/sap-abap/services/iop/README.md b/sap-abap/services/iop/README.md
new file mode 100644
index 00000000000..832a014be88
--- /dev/null
+++ b/sap-abap/services/iop/README.md
@@ -0,0 +1,79 @@
+# AWS IoT data code examples for the SDK for SAP ABAP
+
+## Overview
+
+Shows how to use the AWS SDK for SAP ABAP to work with AWS IoT data.
+
+
+
+
+_AWS IoT data _
+
+## ⚠ Important
+
+* Running this code might result in charges to your AWS account. For more details, see [AWS Pricing](https://aws.amazon.com/pricing/) and [Free Tier](https://aws.amazon.com/free/).
+* Running the tests might result in charges to your AWS account.
+* We recommend that you grant your code least privilege. At most, grant only the minimum permissions required to perform the task. For more information, see [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege).
+* This code is not tested in every AWS Region. For more information, see [AWS Regional Services](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services).
+
+
+
+
+## Code examples
+
+### Prerequisites
+
+For prerequisites, see the [README](../../README.md#Prerequisites) in the `sap-abap` folder.
+
+
+
+
+
+### Single actions
+
+Code excerpts that show you how to call individual service functions.
+
+- [GetThingShadow](%23awsex%23cl_iop_actions.clas.abap#L70)
+- [UpdateThingShadow](%23awsex%23cl_iop_actions.clas.abap#L46)
+
+
+
+
+
+## Run the examples
+
+### Instructions
+
+
+
+
+
+
+
+### Tests
+
+⚠ Running tests might result in charges to your AWS account.
+
+
+To find instructions for running these tests, see the [README](../../README.md#Tests)
+in the `sap-abap` folder.
+
+
+
+
+
+
+## Additional resources
+
+- [AWS IoT data Developer Guide](https://docs.aws.amazon.com/iot/latest/developerguide/what-is-aws-iot.html)
+- [AWS IoT data API Reference](https://docs.aws.amazon.com/iot/latest/apireference/Welcome.html)
+- [SDK for SAP ABAP AWS IoT data reference](https://docs.aws.amazon.com/sdk-for-sap-abap/v1/api/latest/iot-data-plane/index.html)
+
+
+
+
+---
+
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+SPDX-License-Identifier: Apache-2.0
diff --git a/sap-abap/services/iop/package.devc.xml b/sap-abap/services/iop/package.devc.xml
new file mode 100644
index 00000000000..2b097a9ba19
--- /dev/null
+++ b/sap-abap/services/iop/package.devc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+ Package for Iot data plane
+
+
+
+
\ No newline at end of file