From 3c48f63b1f6217dd3baef8178ef4866b98c0fcf3 Mon Sep 17 00:00:00 2001 From: piconem Date: Fri, 15 Mar 2024 09:46:57 +0000 Subject: [PATCH] deploy: 0b8dd6668ea9f8aad23d43190db7bf91f157a66c --- about/index.html | 2 +- blog/index.html | 4 ++-- blog/index.xml | 2 +- .../index.html | 4 ++-- blog/sitemap.xml | 2 +- docs/adapters/http-digital-adapter/index.html | 2 +- docs/adapters/mqtt-digital-adapter/index.html | 2 +- docs/adapters/mqtt-physical-adapter/index.html | 2 +- docs/adapters/sitemap.xml | 2 +- docs/change-logs/change-log-0.3.0/index.html | 2 +- docs/change-logs/sitemap.xml | 2 +- docs/guides/configurable-adapters/index.html | 2 +- docs/guides/digital-actions/index.html | 2 +- docs/guides/digital-adapter/index.html | 2 +- docs/guides/dt-engine-dt-instance/index.html | 2 +- docs/guides/physical-adapter/index.html | 2 +- docs/guides/shadowing-function/index.html | 2 +- docs/guides/sitemap.xml | 2 +- docs/introduction/dt-life-cycle/index.html | 2 +- docs/introduction/dt-model/index.html | 2 +- docs/introduction/library-structure-basic-concepts/index.html | 2 +- docs/introduction/sitemap.xml | 2 +- docs/sitemap.xml | 2 +- en/sitemap.xml | 2 +- index.xml | 2 +- privacy/index.html | 2 +- search-index.json | 2 +- sitemap.xml | 2 +- 28 files changed, 30 insertions(+), 30 deletions(-) rename blog/{wldt-library-version-0.3.0 => ls-wldt-library-version-0.3.0}/index.html (68%) diff --git a/about/index.html b/about/index.html index 0e621b4..adedad4 100644 --- a/about/index.html +++ b/about/index.html @@ -3,7 +3,7 @@
WLDT

About WLDT Library

Welcome to White Label Digital Twins (WLDT), an open-source project dedicated to supporting the design, development, and deployment of Digital Twins within the Internet of Things (IoT) ecosystems.

The WLDT library has been designed to align with the latest DT definitions from both Industrial and Scientific domains. It identifies DTs as active, flexible, and scalable software components. Our library aims to provide developers with the tools and resources necessary to create robust Digital Twins that effectively simulate and monitor physical assets within IoT environments.

Whether you’re working on IoT, Industrial IoT (IIoT) applications, Smart Cities projects, or any other IoT-related endeavor, the WLDT library offers a versatile solution for implementing Digital Twins that accurately represent real-world objects and support informed decision-making processes.

💻 Team & Mantainers

  • [Founders & Main Contributors]
    • Marco Picone - University of Modena & Reggio Emilia, Italy - (Link)
  • [Key Contributors]
    • Samuele Burattini - University of Bologna, Italy - (Link)

📜 Scientitic Citation & References

If you use the WLDT Library in a Scientific Paper please use this reference:

@article{PICONE2021100661,
+

About WLDT Library

Welcome to White Label Digital Twins (WLDT), an open-source project dedicated to supporting the design, development, and deployment of Digital Twins within the Internet of Things (IoT) ecosystems.

The WLDT library has been designed to align with the latest DT definitions from both Industrial and Scientific domains. It identifies DTs as active, flexible, and scalable software components. Our library aims to provide developers with the tools and resources necessary to create robust Digital Twins that effectively simulate and monitor physical assets within IoT environments.

Whether you’re working on IoT, Industrial IoT (IIoT) applications, Smart Cities projects, or any other IoT-related endeavor, the WLDT library offers a versatile solution for implementing Digital Twins that accurately represent real-world objects and support informed decision-making processes.

💻 Team & Mantainers

  • [Founders & Main Contributors]
    • Marco Picone - University of Modena & Reggio Emilia, Italy - (Link)
  • [Key Contributors]
    • Samuele Burattini - University of Bologna, Italy - (Link)
  • [Additional Contributors]
    • Marta Spadoni - University of Bologna, Italy - Master Thesis 2022

📜 Scientitic Citation & References

If you use the WLDT Library in a Scientific Paper please use this reference:

@article{PICONE2021100661,
     title = {WLDT: A general purpose library to build IoT digital twins},
     journal = {SoftwareX},
     volume = {13},
diff --git a/blog/index.html b/blog/index.html
index e977246..c383680 100644
--- a/blog/index.html
+++ b/blog/index.html
@@ -1,7 +1,7 @@
 
-Blog | WLDT

Blog

\ No newline at end of file diff --git a/blog/index.xml b/blog/index.xml index b044b4e..9b8595b 100644 --- a/blog/index.xml +++ b/blog/index.xml @@ -1 +1 @@ -Blog on WLDThttps://wldt.github.io/blog/Recent content in Blog on WLDTHugo -- gohugo.ioenCopyright (c) 2023 HyasThu, 07 Sep 2023 16:21:44 +0200WLDT Library Version 0.3.0https://wldt.github.io/blog/wldt-library-version-0.3.0/Wed, 13 Mar 2024 16:27:22 +0200https://wldt.github.io/blog/wldt-library-version-0.3.0/📣 We’re thrilled to announce the release of version 0.3.0 of the White Label Digital Twins (WLDT) library! This release brings significant enhancements, improvements, and new features to further empower developers in designing, developing, and deploying Digital Twins within Internet of Things (IoT) ecosystems. \ No newline at end of file +Blog on WLDThttps://wldt.github.io/blog/Recent content in Blog on WLDTHugo -- gohugo.ioenCopyright (c) 2023 HyasThu, 07 Sep 2023 16:21:44 +0200ls WLDT Library Version 0.3.0https://wldt.github.io/blog/ls-wldt-library-version-0.3.0/Wed, 13 Mar 2024 16:27:22 +0200https://wldt.github.io/blog/ls-wldt-library-version-0.3.0/📣 We’re thrilled to announce the release of version 0.3.0 of the White Label Digital Twins (WLDT) library! This release brings significant enhancements, improvements, and new features to further empower developers in designing, developing, and deploying Digital Twins within Internet of Things (IoT) ecosystems. \ No newline at end of file diff --git a/blog/wldt-library-version-0.3.0/index.html b/blog/ls-wldt-library-version-0.3.0/index.html similarity index 68% rename from blog/wldt-library-version-0.3.0/index.html rename to blog/ls-wldt-library-version-0.3.0/index.html index aab1380..125cbca 100644 --- a/blog/wldt-library-version-0.3.0/index.html +++ b/blog/ls-wldt-library-version-0.3.0/index.html @@ -1,9 +1,9 @@ -WLDT Library Version 0.3.0 | WLDT

ls WLDT Library Version 0.3.0

March 13, 2024 ‐ 3 min read

📣 We’re thrilled to announce the release of version 0.3.0 of the White Label Digital Twins (WLDT) library! This release brings significant enhancements, improvements, and new features to further empower developers in designing, developing, and deploying Digital Twins within Internet of Things (IoT) ecosystems.

For detailed information about these changes and their impact, please refer to the information provided:

Let’s dive into the key changes and updates included in this release:

Migration Digital Adapters

In version 0.3.0, we’ve made several enhancements and adjustments to the Digital Adapter class to improve its functionality and usability. Notable changes include:

  • Discontinued Methods: Several methods have been discontinued and removed from the DigitalAdapter class to streamline its interface and improve clarity. Method Signature Changes: The signatures of certain methods have been updated for consistency and clarity, ensuring a more intuitive developer experience.
  • New Methods: We’ve introduced new methods to provide additional functionality and flexibility for handling state updates and event notifications.

Migration Shadowing Function

We’ve made significant improvements to the ShadowingModelFunction, which is now renamed to ShadowingFunction. Additionally, we’ve introduced changes to how the DigitalTwinState is managed within the Shadowing Function, providing developers with more control and flexibility.

Migrating WLDT Engine & DT Creation

In version 0.3.0, the WldtEngine class has been renamed to DigitalTwin, offering improved clarity and consistency. We’ve also made adjustments to the lifecycle management of Digital Twins, streamlining the process and enhancing usability.

Digital Twin & Digital Twin Engine

We’ve introduced enhancements to the Digital Twin and Digital Twin Engine classes, providing developers with improved functionality and ease of use. Notable updates include:

  • Simplified Digital Twin Creation: Creating and managing Digital Twins is now more intuitive and streamlined.
  • Lifecycle Management: We’ve enhanced the lifecycle management of Digital Twins, making it easier to start, stop, and manage multiple instances.

Digital Twin State Manager

The DigitalTwinStateManager class has been improved to provide better support for managing the state of Digital Twins. With features such as transaction support and event notification, developers can more effectively manage changes to Digital Twin states and respond to events.

To learn more about the capabilities of the DigitalTwinStateManager, please refer to the Digital Twin State Manager section.

Digital Adapter

We’ve extended and improved the Digital Adapter base class to provide enhanced support for handling Digital Twin state updates and event notifications. With the introduction of the onStateUpdate and onEventNotificationReceived methods, developers can more effectively respond to changes in Digital Twin states and events.

Get Started with WLDT 0.3.0

To get started with version 0.3.0 of the WLDT library, simply update your dependencies to include the latest release. Detailed documentation and usage examples are available in the project repository, providing comprehensive guidance on leveraging the new features and enhancements.

We’re excited about the improvements and new capabilities introduced in WLDT 0.3.0, and we can’t wait to see how developers utilize them to create innovative IoT solutions powered by Digital Twins. As always, we welcome your feedback and contributions to help us further improve the library and empower the community.

Happy coding with WLDT 0.3.0! 🚀

\ No newline at end of file diff --git a/blog/sitemap.xml b/blog/sitemap.xml index 20da511..fc8204e 100644 --- a/blog/sitemap.xml +++ b/blog/sitemap.xml @@ -1 +1 @@ -https://wldt.github.io/blog/wldt-library-version-0.3.0/2024-03-14T17:11:51+01:00monthly0.5 \ No newline at end of file +https://wldt.github.io/blog/ls-wldt-library-version-0.3.0/2024-03-15T10:45:36+01:00monthly0.5 \ No newline at end of file diff --git a/docs/adapters/http-digital-adapter/index.html b/docs/adapters/http-digital-adapter/index.html index 2a2537e..8371e25 100644 --- a/docs/adapters/http-digital-adapter/index.html +++ b/docs/adapters/http-digital-adapter/index.html @@ -67,5 +67,5 @@

HTTP RESTful API

This section of the documentation provides detailed information about the RESTful API exposed by the WLDT - HTTP Digital Adapter. The API allows you to interact with the Digital Twin (DT) instance, retrieve its state, read properties, actions, event and relationships description, and trigger actions.

Available endpoints with the associated methods are:

Note: Replace {propertyKey}, {actionKey}, and {relationshipName} with the actual values you want to retrieve or trigger. -Make sure to use the appropriate HTTP method (GET, POST) and include any required parameters or payload as described in each endpoint’s description. For more detailed information, refer to the Postman Collection for this API available in the folder api: http_adapter_api_postman.json

+Make sure to use the appropriate HTTP method (GET, POST) and include any required parameters or payload as described in each endpoint’s description. For more detailed information, refer to the Postman Collection for this API available in the folder api: http_adapter_api_postman.json

\ No newline at end of file diff --git a/docs/adapters/mqtt-digital-adapter/index.html b/docs/adapters/mqtt-digital-adapter/index.html index b097690..0d754ff 100644 --- a/docs/adapters/mqtt-digital-adapter/index.html +++ b/docs/adapters/mqtt-digital-adapter/index.html @@ -55,5 +55,5 @@ digitalTwinEngine.addDigitalTwin(digitalTwin); digitalTwinEngine.startAll(); -
+
\ No newline at end of file diff --git a/docs/adapters/mqtt-physical-adapter/index.html b/docs/adapters/mqtt-physical-adapter/index.html index 7b0cedb..a17b834 100644 --- a/docs/adapters/mqtt-physical-adapter/index.html +++ b/docs/adapters/mqtt-physical-adapter/index.html @@ -78,5 +78,5 @@ return properties; }

This information are used by the adapter to build the PAD describe the capabilities and the characteristics of our object allowing -the Shadowing Function to decide how to digitalize its physical counterpart.

+the Shadowing Function to decide how to digitalize its physical counterpart.

\ No newline at end of file diff --git a/docs/adapters/sitemap.xml b/docs/adapters/sitemap.xml index 85877f4..3f568e1 100644 --- a/docs/adapters/sitemap.xml +++ b/docs/adapters/sitemap.xml @@ -1 +1 @@ -https://wldt.github.io/docs/adapters/mqtt-physical-adapter/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/adapters/mqtt-digital-adapter/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/adapters/http-digital-adapter/2024-03-14T17:11:51+01:00monthly0.5 \ No newline at end of file +https://wldt.github.io/docs/adapters/mqtt-physical-adapter/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/adapters/mqtt-digital-adapter/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/adapters/http-digital-adapter/2024-03-15T10:45:36+01:00monthly0.5 \ No newline at end of file diff --git a/docs/change-logs/change-log-0.3.0/index.html b/docs/change-logs/change-log-0.3.0/index.html index b3a649f..c93cd8b 100644 --- a/docs/change-logs/change-log-0.3.0/index.html +++ b/docs/change-logs/change-log-0.3.0/index.html @@ -235,5 +235,5 @@ System.out.println("No state changes detected."); } } -

In this example, the method iterates over the list of state changes, extracts information about each change, and performs custom actions based on the changes. Developers can adapt this method to suit the specific requirements of their Digital Twin application.

+

In this example, the method iterates over the list of state changes, extracts information about each change, and performs custom actions based on the changes. Developers can adapt this method to suit the specific requirements of their Digital Twin application.

\ No newline at end of file diff --git a/docs/change-logs/sitemap.xml b/docs/change-logs/sitemap.xml index 8d4e5fa..6c255d0 100644 --- a/docs/change-logs/sitemap.xml +++ b/docs/change-logs/sitemap.xml @@ -1 +1 @@ -https://wldt.github.io/docs/change-logs/change-log-0.3.0/2024-03-14T17:11:51+01:00monthly0.5 \ No newline at end of file +https://wldt.github.io/docs/change-logs/change-log-0.3.0/2024-03-15T10:45:36+01:00monthly0.5 \ No newline at end of file diff --git a/docs/guides/configurable-adapters/index.html b/docs/guides/configurable-adapters/index.html index 74eba7e..80278bb 100644 --- a/docs/guides/configurable-adapters/index.html +++ b/docs/guides/configurable-adapters/index.html @@ -233,5 +233,5 @@ } } } - +
\ No newline at end of file diff --git a/docs/guides/digital-actions/index.html b/docs/guides/digital-actions/index.html index eda8279..55c968c 100644 --- a/docs/guides/digital-actions/index.html +++ b/docs/guides/digital-actions/index.html @@ -71,5 +71,5 @@ e.printStackTrace(); } } - +
\ No newline at end of file diff --git a/docs/guides/digital-adapter/index.html b/docs/guides/digital-adapter/index.html index 6c0d26f..98fdd65 100644 --- a/docs/guides/digital-adapter/index.html +++ b/docs/guides/digital-adapter/index.html @@ -190,5 +190,5 @@ }

In this example, the method iterates over the list of state changes, extracts information about each change, and performs custom actions based on the changes. Developers can adapt this method to suit the specific requirements of their Digital Twin application.

Both Physical Adapters and Digital Adapters can be defined natively with a custom configuration provided by the developer -as illustrated in the dedicated Section: Configurable Physical & Digital Adapters.

+as illustrated in the dedicated Section: Configurable Physical & Digital Adapters.

\ No newline at end of file diff --git a/docs/guides/dt-engine-dt-instance/index.html b/docs/guides/dt-engine-dt-instance/index.html index 76463db..4280321 100644 --- a/docs/guides/dt-engine-dt-instance/index.html +++ b/docs/guides/dt-engine-dt-instance/index.html @@ -87,5 +87,5 @@ } } } - +
\ No newline at end of file diff --git a/docs/guides/physical-adapter/index.html b/docs/guides/physical-adapter/index.html index 6bf069b..4882626 100644 --- a/docs/guides/physical-adapter/index.html +++ b/docs/guides/physical-adapter/index.html @@ -257,5 +257,5 @@ } }

Both Physical Adapters and Digital Adapters can be defined natively with a custom configuration provided by the developer -as illustrated in the dedicated Section: Configurable Physical & Digital Adapters.

+as illustrated in the dedicated Section: Configurable Physical & Digital Adapters.

\ No newline at end of file diff --git a/docs/guides/shadowing-function/index.html b/docs/guides/shadowing-function/index.html index 0a01e9a..2ed487f 100644 --- a/docs/guides/shadowing-function/index.html +++ b/docs/guides/shadowing-function/index.html @@ -273,5 +273,5 @@ to the Physical Adapter with the method of the Shadowing Function denoted as this.publishPhysicalAssetActionWldtEvent and passing directly the action key and the target Body. No additional processing or validation have been introduced here, but they might be required in advanced scenario in order to properly adapt incoming digital action request to what is effectively expected on the -physical counterpart.

+physical counterpart.

\ No newline at end of file diff --git a/docs/guides/sitemap.xml b/docs/guides/sitemap.xml index c135c99..864bad4 100644 --- a/docs/guides/sitemap.xml +++ b/docs/guides/sitemap.xml @@ -1 +1 @@ -https://wldt.github.io/docs/guides/physical-adapter/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/shadowing-function/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/digital-adapter/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/dt-engine-dt-instance/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/digital-actions/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/configurable-adapters/2024-03-14T17:11:51+01:00monthly0.5 \ No newline at end of file +https://wldt.github.io/docs/guides/physical-adapter/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/shadowing-function/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/digital-adapter/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/dt-engine-dt-instance/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/digital-actions/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/configurable-adapters/2024-03-15T10:45:36+01:00monthly0.5 \ No newline at end of file diff --git a/docs/introduction/dt-life-cycle/index.html b/docs/introduction/dt-life-cycle/index.html index bbdb13d..4729379 100644 --- a/docs/introduction/dt-life-cycle/index.html +++ b/docs/introduction/dt-life-cycle/index.html @@ -42,5 +42,5 @@ expose the DT’s State, its properties and capabilities to the external digital world. At the same time, eDT can be used by Digital Adapters to trigger action on the DT and consequently to propagate (if acceptable and/or needed) the incoming request to the physical assets bound with the target DT. Supported events are illustrated in the following -schema.

DT Life Cycle

+schema.

DT Life Cycle

\ No newline at end of file diff --git a/docs/introduction/dt-model/index.html b/docs/introduction/dt-model/index.html index e4bdc87..39758a4 100644 --- a/docs/introduction/dt-model/index.html +++ b/docs/introduction/dt-model/index.html @@ -43,5 +43,5 @@ propagates the request through its physical interface. An important aspect to emphasize is that the request for a digital_action does not directly change the state of the DT since any changes can only occur as a result of the -shadowing function from the PA to the DT, as described earlier.

+shadowing function from the PA to the DT, as described earlier.

\ No newline at end of file diff --git a/docs/introduction/library-structure-basic-concepts/index.html b/docs/introduction/library-structure-basic-concepts/index.html index 916339d..d6e4e2c 100644 --- a/docs/introduction/library-structure-basic-concepts/index.html +++ b/docs/introduction/library-structure-basic-concepts/index.html @@ -78,5 +78,5 @@ entity and allow the DT to be used by external applications. Once the 3 components are defined, it is possible to instantiate the WLDT Engine and, subsequently, start the lifecycle of the DT. In the following sections we will go through the fundamental steps to start working with the library and creating all -the basic modules to design, develop and execute our first Java Digital Twin.

+the basic modules to design, develop and execute our first Java Digital Twin.

\ No newline at end of file diff --git a/docs/introduction/sitemap.xml b/docs/introduction/sitemap.xml index f9cd46c..c6c3f46 100644 --- a/docs/introduction/sitemap.xml +++ b/docs/introduction/sitemap.xml @@ -1 +1 @@ -https://wldt.github.io/docs/introduction/library-structure-basic-concepts/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/introduction/dt-model/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/introduction/dt-life-cycle/2024-03-14T17:11:51+01:00monthly0.5 \ No newline at end of file +https://wldt.github.io/docs/introduction/library-structure-basic-concepts/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/introduction/dt-model/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/introduction/dt-life-cycle/2024-03-15T10:45:36+01:00monthly0.5 \ No newline at end of file diff --git a/docs/sitemap.xml b/docs/sitemap.xml index 2645612..a93d56f 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -1 +1 @@ -https://wldt.github.io/docs/introduction/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/adapters/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/change-logs/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/introduction/library-structure-basic-concepts/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/introduction/dt-model/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/introduction/dt-life-cycle/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/physical-adapter/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/shadowing-function/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/digital-adapter/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/dt-engine-dt-instance/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/digital-actions/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/configurable-adapters/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/adapters/mqtt-physical-adapter/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/adapters/mqtt-digital-adapter/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/adapters/http-digital-adapter/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/change-logs/change-log-0.3.0/2024-03-14T17:11:51+01:00monthly0.5 \ No newline at end of file +https://wldt.github.io/docs/introduction/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/adapters/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/change-logs/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/introduction/library-structure-basic-concepts/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/introduction/dt-model/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/introduction/dt-life-cycle/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/physical-adapter/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/shadowing-function/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/digital-adapter/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/dt-engine-dt-instance/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/digital-actions/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/configurable-adapters/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/adapters/mqtt-physical-adapter/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/adapters/mqtt-digital-adapter/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/adapters/http-digital-adapter/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/change-logs/change-log-0.3.0/2024-03-15T10:45:36+01:00monthly0.5 \ No newline at end of file diff --git a/en/sitemap.xml b/en/sitemap.xml index 382b082..54eaf8a 100644 --- a/en/sitemap.xml +++ b/en/sitemap.xml @@ -1 +1 @@ -https://wldt.github.io/blog/wldt-library-version-0.3.0/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/blog/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/introduction/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/physical-adapter/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/shadowing-function/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/digital-adapter/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/dt-engine-dt-instance/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/digital-actions/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/guides/configurable-adapters/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/adapters/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/adapters/mqtt-physical-adapter/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/change-logs/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/adapters/mqtt-digital-adapter/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/change-logs/change-log-0.3.0/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/adapters/http-digital-adapter/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/introduction/library-structure-basic-concepts/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/introduction/dt-model/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/introduction/dt-life-cycle/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/docs/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/about/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/privacy/2024-03-14T17:11:51+01:00monthly0.5https://wldt.github.io/categories/monthly0.5https://wldt.github.io/contributors/monthly0.5https://wldt.github.io/tags/monthly0.5 \ No newline at end of file +https://wldt.github.io/blog/ls-wldt-library-version-0.3.0/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/blog/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/introduction/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/physical-adapter/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/shadowing-function/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/digital-adapter/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/dt-engine-dt-instance/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/digital-actions/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/guides/configurable-adapters/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/adapters/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/adapters/mqtt-physical-adapter/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/change-logs/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/adapters/mqtt-digital-adapter/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/change-logs/change-log-0.3.0/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/adapters/http-digital-adapter/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/introduction/library-structure-basic-concepts/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/introduction/dt-model/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/introduction/dt-life-cycle/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/docs/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/about/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/privacy/2024-03-15T10:45:36+01:00monthly0.5https://wldt.github.io/categories/monthly0.5https://wldt.github.io/contributors/monthly0.5https://wldt.github.io/tags/monthly0.5 \ No newline at end of file diff --git a/index.xml b/index.xml index 5b712b0..be998b3 100644 --- a/index.xml +++ b/index.xml @@ -1,2 +1,2 @@ -White Label Digital Twins on WLDThttps://wldt.github.io/Recent content in White Label Digital Twins on WLDTHugo -- gohugo.ioenCopyright (c) 2023 HyasFri, 06 Oct 2023 08:47:36 +0000WLDT Library Version 0.3.0https://wldt.github.io/blog/wldt-library-version-0.3.0/Wed, 13 Mar 2024 16:27:22 +0200https://wldt.github.io/blog/wldt-library-version-0.3.0/📣 We’re thrilled to announce the release of version 0.3.0 of the White Label Digital Twins (WLDT) library! This release brings significant enhancements, improvements, and new features to further empower developers in designing, developing, and deploying Digital Twins within Internet of Things (IoT) ecosystems.Physical Adapterhttps://wldt.github.io/docs/guides/physical-adapter/Fri, 09 Feb 2024 12:09:02 +0100https://wldt.github.io/docs/guides/physical-adapter/The developer can use an existing Physical Adapter or create a new one to handle the communication with a specific physical twin.Shadowing Functionhttps://wldt.github.io/docs/guides/shadowing-function/Fri, 09 Feb 2024 12:15:33 +0100https://wldt.github.io/docs/guides/shadowing-function/After the definition of the Physical Adapter it is time to start implementing the core of our DT through the definition of its shadowing function in charge of:Digital Adapterhttps://wldt.github.io/docs/guides/digital-adapter/Fri, 09 Feb 2024 12:16:06 +0100https://wldt.github.io/docs/guides/digital-adapter/The las component that we have to implement to complete our first simple Digital Twin definition through the WLDT library is a Digital Adapter in charge of:DT Engine & DT Instancehttps://wldt.github.io/docs/guides/dt-engine-dt-instance/Fri, 09 Feb 2024 12:16:36 +0100https://wldt.github.io/docs/guides/dt-engine-dt-instance/Now that we have created the main fundamental element of a DT (Physical Adapter, Shadowing Function and Digital Adapter) we can create Class file with a main to create the WLDT Engine with the created components and start the DT.Digital Actionshttps://wldt.github.io/docs/guides/digital-actions/Fri, 09 Feb 2024 12:18:13 +0100https://wldt.github.io/docs/guides/digital-actions/In this demo implementation, we are going to emulate an incoming Digital Action on the Digital Adapter in order to show how it can be handled by the adapter and properly forwarded to the Shadowing Function for validation and the consequent interaction with the Physical Adapter and then with the physical twin.Configurable Adaptershttps://wldt.github.io/docs/guides/configurable-adapters/Fri, 09 Feb 2024 12:19:37 +0100https://wldt.github.io/docs/guides/configurable-adapters/The WLDT library provides a native method to define Configurable Physical ad Digital Adapters specifying a custom configuration class passed as parameter in the constructor.MQTT Physical Adapterhttps://wldt.github.io/docs/adapters/mqtt-physical-adapter/Fri, 09 Feb 2024 12:55:52 +0100https://wldt.github.io/docs/adapters/mqtt-physical-adapter/The MqttPhysicalAdapter library provides a streamlined solution for efficiently managing physical assets through the MQTT protocol. It offers a range of features, including a versatile builder for effortless configuration of MQTT connections, dedicated classes for handling both incoming and outgoing topics, and a specialized adapter designed for seamless integration with diverse physical assets.MQTT Digital Adapterhttps://wldt.github.io/docs/adapters/mqtt-digital-adapter/Fri, 09 Feb 2024 12:58:14 +0100https://wldt.github.io/docs/adapters/mqtt-digital-adapter/The MqttDigitalAdapter, +White Label Digital Twins on WLDThttps://wldt.github.io/Recent content in White Label Digital Twins on WLDTHugo -- gohugo.ioenCopyright (c) 2023 HyasFri, 06 Oct 2023 08:47:36 +0000ls WLDT Library Version 0.3.0https://wldt.github.io/blog/ls-wldt-library-version-0.3.0/Wed, 13 Mar 2024 16:27:22 +0200https://wldt.github.io/blog/ls-wldt-library-version-0.3.0/📣 We’re thrilled to announce the release of version 0.3.0 of the White Label Digital Twins (WLDT) library! This release brings significant enhancements, improvements, and new features to further empower developers in designing, developing, and deploying Digital Twins within Internet of Things (IoT) ecosystems.Physical Adapterhttps://wldt.github.io/docs/guides/physical-adapter/Fri, 09 Feb 2024 12:09:02 +0100https://wldt.github.io/docs/guides/physical-adapter/The developer can use an existing Physical Adapter or create a new one to handle the communication with a specific physical twin.Shadowing Functionhttps://wldt.github.io/docs/guides/shadowing-function/Fri, 09 Feb 2024 12:15:33 +0100https://wldt.github.io/docs/guides/shadowing-function/After the definition of the Physical Adapter it is time to start implementing the core of our DT through the definition of its shadowing function in charge of:Digital Adapterhttps://wldt.github.io/docs/guides/digital-adapter/Fri, 09 Feb 2024 12:16:06 +0100https://wldt.github.io/docs/guides/digital-adapter/The las component that we have to implement to complete our first simple Digital Twin definition through the WLDT library is a Digital Adapter in charge of:DT Engine & DT Instancehttps://wldt.github.io/docs/guides/dt-engine-dt-instance/Fri, 09 Feb 2024 12:16:36 +0100https://wldt.github.io/docs/guides/dt-engine-dt-instance/Now that we have created the main fundamental element of a DT (Physical Adapter, Shadowing Function and Digital Adapter) we can create Class file with a main to create the WLDT Engine with the created components and start the DT.Digital Actionshttps://wldt.github.io/docs/guides/digital-actions/Fri, 09 Feb 2024 12:18:13 +0100https://wldt.github.io/docs/guides/digital-actions/In this demo implementation, we are going to emulate an incoming Digital Action on the Digital Adapter in order to show how it can be handled by the adapter and properly forwarded to the Shadowing Function for validation and the consequent interaction with the Physical Adapter and then with the physical twin.Configurable Adaptershttps://wldt.github.io/docs/guides/configurable-adapters/Fri, 09 Feb 2024 12:19:37 +0100https://wldt.github.io/docs/guides/configurable-adapters/The WLDT library provides a native method to define Configurable Physical ad Digital Adapters specifying a custom configuration class passed as parameter in the constructor.MQTT Physical Adapterhttps://wldt.github.io/docs/adapters/mqtt-physical-adapter/Fri, 09 Feb 2024 12:55:52 +0100https://wldt.github.io/docs/adapters/mqtt-physical-adapter/The MqttPhysicalAdapter library provides a streamlined solution for efficiently managing physical assets through the MQTT protocol. It offers a range of features, including a versatile builder for effortless configuration of MQTT connections, dedicated classes for handling both incoming and outgoing topics, and a specialized adapter designed for seamless integration with diverse physical assets.MQTT Digital Adapterhttps://wldt.github.io/docs/adapters/mqtt-digital-adapter/Fri, 09 Feb 2024 12:58:14 +0100https://wldt.github.io/docs/adapters/mqtt-digital-adapter/The MqttDigitalAdapter, MqttDigitalAdapterConfiguration, and MqttDigitalAdapterConfigurationBuilder classes and guides you through using these classes to set up an MQTT Digital Adapter within WLDT.Change Log 0.3.0https://wldt.github.io/docs/change-logs/change-log-0.3.0/Fri, 09 Feb 2024 12:23:33 +0100https://wldt.github.io/docs/change-logs/change-log-0.3.0/Digital Adapters The following methods have been discontinued and removed from the DigitalAdapter class: onStateChangePropertyCreated onStateChangePropertyUpdated onStateChangePropertyDeleted onStatePropertyUpdated onStatePropertyDeleted onStateChangeActionEnabled onStateChangeActionUpdated onStateChangeActionDisabled onStateChangeEventRegistered onStateChangeEventRegistrationUpdated onStateChangeEventUnregistered onStateChangeRelationshipInstanceDeleted onStateChangeRelationshipDeleted onStateChangeRelationshipInstanceCreated onStateChangeRelationshipCreated onDigitalTwinStateEventNotificationReceived The Signature of the following methods have been changed: onDigitalTwinSync(IDigitalTwinState currentDigitalTwinState) -> onDigitalTwinSync(DigitalTwinState currentDigitalTwinState) onDigitalTwinUnSync(IDigitalTwinState currentDigitalTwinState) -> onDigitalTwinUnSync(DigitalTwinState currentDigitalTwinState) New methods that have been added are: onStateUpdate(DigitalTwinState newDigitalTwinState, DigitalTwinState previousDigitalTwinState, ArrayList<DigitalTwinStateChange> digitalTwinStateChangeList) onEventNotificationReceived(DigitalTwinStateEventNotification<? \ No newline at end of file diff --git a/privacy/index.html b/privacy/index.html index 1614022..e76f49c 100644 --- a/privacy/index.html +++ b/privacy/index.html @@ -3,5 +3,5 @@

Privacy Policy

Last updated on March 14, 2024

+

Privacy Policy

Last updated on March 15, 2024

\ No newline at end of file diff --git a/search-index.json b/search-index.json index 821a295..40acbb5 100644 --- a/search-index.json +++ b/search-index.json @@ -1 +1 @@ -[{"content":"📣 We\u0026rsquo;re thrilled to announce the release of version 0.3.0 of the White Label Digital Twins (WLDT) library! This release brings significant enhancements, improvements, and new features to further empower developers in designing, developing, and deploying Digital Twins within Internet of Things (IoT) ecosystems.\nFor detailed information about these changes and their impact, please refer to the information provided:\nOfficial Changelog Official Documentation Let\u0026rsquo;s dive into the key changes and updates included in this release:\nMigration Digital Adapters In version 0.3.0, we\u0026rsquo;ve made several enhancements and adjustments to the Digital Adapter class to improve its functionality and usability. Notable changes include:\nDiscontinued Methods: Several methods have been discontinued and removed from the DigitalAdapter class to streamline its interface and improve clarity. Method Signature Changes: The signatures of certain methods have been updated for consistency and clarity, ensuring a more intuitive developer experience. New Methods: We\u0026rsquo;ve introduced new methods to provide additional functionality and flexibility for handling state updates and event notifications. Migration Shadowing Function We\u0026rsquo;ve made significant improvements to the ShadowingModelFunction, which is now renamed to ShadowingFunction. Additionally, we\u0026rsquo;ve introduced changes to how the DigitalTwinState is managed within the Shadowing Function, providing developers with more control and flexibility.\nMigrating WLDT Engine \u0026amp; DT Creation In version 0.3.0, the WldtEngine class has been renamed to DigitalTwin, offering improved clarity and consistency. We\u0026rsquo;ve also made adjustments to the lifecycle management of Digital Twins, streamlining the process and enhancing usability.\nDigital Twin \u0026amp; Digital Twin Engine We\u0026rsquo;ve introduced enhancements to the Digital Twin and Digital Twin Engine classes, providing developers with improved functionality and ease of use. Notable updates include:\nSimplified Digital Twin Creation: Creating and managing Digital Twins is now more intuitive and streamlined. Lifecycle Management: We\u0026rsquo;ve enhanced the lifecycle management of Digital Twins, making it easier to start, stop, and manage multiple instances. Digital Twin State Manager The DigitalTwinStateManager class has been improved to provide better support for managing the state of Digital Twins. With features such as transaction support and event notification, developers can more effectively manage changes to Digital Twin states and respond to events.\nTo learn more about the capabilities of the DigitalTwinStateManager, please refer to the Digital Twin State Manager section.\nDigital Adapter We\u0026rsquo;ve extended and improved the Digital Adapter base class to provide enhanced support for handling Digital Twin state updates and event notifications. With the introduction of the onStateUpdate and onEventNotificationReceived methods, developers can more effectively respond to changes in Digital Twin states and events.\nGet Started with WLDT 0.3.0 To get started with version 0.3.0 of the WLDT library, simply update your dependencies to include the latest release. Detailed documentation and usage examples are available in the project repository, providing comprehensive guidance on leveraging the new features and enhancements.\nWe\u0026rsquo;re excited about the improvements and new capabilities introduced in WLDT 0.3.0, and we can\u0026rsquo;t wait to see how developers utilize them to create innovative IoT solutions powered by Digital Twins. As always, we welcome your feedback and contributions to help us further improve the library and empower the community.\nHappy coding with WLDT 0.3.0! 🚀\n","date":"March 13, 2024","id":0,"permalink":"/blog/wldt-library-version-0.3.0/","summary":"📣 We\u0026rsquo;re thrilled to announce the release of version 0.3.0 of the White Label Digital Twins (WLDT) library! This release brings significant enhancements, improvements, and new features to further empower developers in designing, developing, and deploying Digital Twins within Internet of Things (IoT) ecosystems.","tags":"","title":"WLDT Library Version 0.3.0"},{"content":"","date":"September 7, 2023","id":1,"permalink":"/blog/","summary":"","tags":"","title":"Blog"},{"content":"","date":"September 7, 2023","id":2,"permalink":"/docs/introduction/","summary":"","tags":"","title":"Introduction"},{"content":"","date":"February 9, 2024","id":3,"permalink":"/docs/guides/","summary":"","tags":"","title":"Getting Started"},{"content":"The developer can use an existing Physical Adapter or create a new one to handle the communication with a specific physical twin. In this documentation we focus on the creation of a new Physical Adapter in order to explain library core functionalities. However, existing Physical Adapters can be found on the official repository and linked in the core documentation and webpage (WLDT-GitHub).\nIn general WLDT Physical Adapter extends the class PhysicalAdapter and it is responsible to talk with the physical world and handling the following main tasks:\nGenerate a PAD describing the properties, events, actions and relationships available on the physical twin using the class PhysicalAssetDescription Generate Physical Event using the class PhysicalAssetEventWldtEvent associated to the variation of any aspect of the physical state (properties, events, and relationships) Handle action request coming from the Digital World through the DT Shadowing Function by implementing the method onIncomingPhysicalAction and processing events modeled through the class PhysicalAssetActionWldtEvent Create a new class called DemoPhysicalAdapter extending the library class PhysicalAdapter and implement the following methods:\nonAdapterStart: A callback method used to notify when the adapter has been effectively started withing the DT\u0026rsquo;s life cycle onAdapterStop: A call method invoked when the adapter has been stopped and will be dismissed by the core onIncomingPhysicalAction: The callback method called when a new PhysicalAssetActionWldtEvent is sent by the Shadowing Function upon the receiving of a valid Digital Action through a Digital Adapter Then you have to create a constructor for your Physical Adapter with a single String parameter representing the id of the adapter. This id will be used internally by the library to handle and coordinate multiple adapters, adapts logs and execute functions upon the arrival of a new event. The resulting empty class will the following:\npublic class DemoPhysicalAdapter extends PhysicalAdapter { public DemoPhysicalAdapter(String id) { super(id); } @Override public void onIncomingPhysicalAction(PhysicalAssetActionWldtEvent\u0026lt;?\u0026gt; physicalAssetActionWldtEvent) { } @Override public void onAdapterStart() { } @Override public void onAdapterStop() { } } In our test Physical Adapter example we are going to emulate the communication with an Internet of Things device with the following sensing and actuation characteristics:\nA Temperature Sensor generating data about new measurements The possibility to generate OVER-HEATING events An action to set the target desired temperature value The first step will be to generate and publish the PhysicalAssetDescription (PAD) to describe the capabilities and the characteristics of our object allowing the Shadowing Function to decide how to digitalize its physical counterpart. Of course in our case the PAD is generated manually but according to the nature of the connected physical twin it can be automatically generated starting from a discovery or a configuration passed to the adapter.\nThe generation of the PAD for each active Physical Adapter is the fundamental DT process to handle the binding procedure and to allow the Shadowing Function and consequently the core of the twin to be aware of what is available in the physical world and consequently decide what to observe and digitalize.\nIn order to publish the PAD we can update the onAdapterStart method with the following lines of code:\nprivate final static String TEMPERATURE_PROPERTY_KEY = \u0026#34;temperature-property-key\u0026#34;; private final static String OVERHEATING_EVENT_KEY = \u0026#34;overheating-event-key\u0026#34;; private final static String SET_TEMPERATURE_ACTION_KEY = \u0026#34;set-temperatura-action-key\u0026#34;; @Override public void onAdapterStart() { try { //Create an empty PAD PhysicalAssetDescription pad = new PhysicalAssetDescription(); //Add a new Property associated to the target PAD with a key and a default value PhysicalAssetProperty\u0026lt;Double\u0026gt; temperatureProperty = new PhysicalAssetProperty\u0026lt;Double\u0026gt;(TEMPERATURE_PROPERTY_KEY, 0.0); pad.getProperties().add(temperatureProperty); //Add the declaration of a new type of generated event associated to a event key // and the content type of the generated payload PhysicalAssetEvent overheatingEvent = new PhysicalAssetEvent(OVERHEATING_EVENT_KEY, \u0026#34;text/plain\u0026#34;); pad.getEvents().add(overheatingEvent); //Declare the availability of a target action characterized by a Key, an action type // and the expected content type and the request body PhysicalAssetAction setTemperatureAction = new PhysicalAssetAction(SET_TEMPERATURE_ACTION_KEY, \u0026#34;temperature.actuation\u0026#34;, \u0026#34;text/plain\u0026#34;); pad.getActions().add(setTemperatureAction); //Notify the new PAD to the DT\u0026#39;s Shadowing Function this.notifyPhysicalAdapterBound(pad); //TODO add here the Device Emulation method } catch (PhysicalAdapterException | EventBusException e) { e.printStackTrace(); } } Now we need a simple code to emulate the generation of new temperature measurements and over-heating events. In a real Physical Adapter implementation we have to implement the real communication with the physical twin in order to read its state variation over time according to the supported protocols. In our simplified Physical Adapter we can the following function:\nprivate final static int MESSAGE_UPDATE_TIME = 1000; private final static int MESSAGE_UPDATE_NUMBER = 10; private final static double TEMPERATURE_MIN_VALUE = 20; private final static double TEMPERATURE_MAX_VALUE = 30; private Runnable deviceEmulation(){ return () -\u0026gt; { try { //Sleep 5 seconds to emulate device startup Thread.sleep(5000); //Create a new random object to emulate temperature variations Random r = new Random(); //Publish an initial Event for a normal condition publishPhysicalAssetEventWldtEvent(new PhysicalAssetEventWldtEvent\u0026lt;\u0026gt;(OVERHEATING_EVENT_KEY, \u0026#34;normal\u0026#34;)); //Emulate the generation on \u0026#39;n\u0026#39; temperature measurements for(int i = 0; i \u0026lt; MESSAGE_UPDATE_NUMBER; i++){ //Sleep to emulate sensor measurement Thread.sleep(MESSAGE_UPDATE_TIME); //Update the double randomTemperature = TEMPERATURE_MIN_VALUE + (TEMPERATURE_MAX_VALUE - TEMPERATURE_MIN_VALUE) * r.nextDouble(); //Create a new event to notify the variation of a Physical Property PhysicalAssetPropertyWldtEvent\u0026lt;Double\u0026gt; newPhysicalPropertyEvent = new PhysicalAssetPropertyWldtEvent\u0026lt;\u0026gt;(TEMPERATURE_PROPERTY_KEY, randomTemperature); //Publish the WLDTEvent associated to the Physical Property Variation publishPhysicalAssetPropertyWldtEvent(newPhysicalPropertyEvent); } //Publish a demo Physical Event associated to a \u0026#39;critical\u0026#39; overheating condition publishPhysicalAssetEventWldtEvent(new PhysicalAssetEventWldtEvent\u0026lt;\u0026gt;(OVERHEATING_EVENT_KEY, \u0026#34;critical\u0026#34;)); } catch (EventBusException | InterruptedException e) { e.printStackTrace(); } }; } Now we have to call the deviceEmulationFunction() inside the onAdapterStart() triggering its execution and emulating the physical counterpart of our DT. To do that add the following line at the end of the onAdapterStart() method after the this.notifyPhysicalAdapterBound(pad);.\nThe last step will be to handle an incoming action trying to set a new temperature on the device by implementing the method onIncomingPhysicalAction(). This method will receive a PhysicalAssetActionWldtEvent\u0026lt;?\u0026gt; physicalAssetActionWldtEvent associated to the action request generated by the shadowing function. Since a Physical Adapter can handle multiple action we have to check both action-key and body type in order to properly process the action (in our case just logging the request). The new update method will result like this:\n@Override public void onIncomingPhysicalAction(PhysicalAssetActionWldtEvent\u0026lt;?\u0026gt; physicalAssetActionWldtEvent) { try{ if(physicalAssetActionWldtEvent != null \u0026amp;\u0026amp; physicalAssetActionWldtEvent.getActionKey().equals(SET_TEMPERATURE_ACTION_KEY) \u0026amp;\u0026amp; physicalAssetActionWldtEvent.getBody() instanceof String) { System.out.println(\u0026#34;Received Action Request: \u0026#34; + physicalAssetActionWldtEvent.getActionKey() + \u0026#34; with Body: \u0026#34; + physicalAssetActionWldtEvent.getBody()); } else System.err.println(\u0026#34;Wrong Action Received !\u0026#34;); }catch (Exception e){ e.printStackTrace(); } } The overall class will result as following:\nimport it.wldt.adapter.physical.*; import it.wldt.adapter.physical.event.PhysicalAssetActionWldtEvent; import it.wldt.adapter.physical.event.PhysicalAssetEventWldtEvent; import it.wldt.adapter.physical.event.PhysicalAssetPropertyWldtEvent; import it.wldt.exception.EventBusException; import it.wldt.exception.PhysicalAdapterException; import java.util.Random; public class DemoPhysicalAdapter extends PhysicalAdapter { private final static String TEMPERATURE_PROPERTY_KEY = \u0026#34;temperature-property-key\u0026#34;; private final static String OVERHEATING_EVENT_KEY = \u0026#34;overheating-event-key\u0026#34;; private final static String SET_TEMPERATURE_ACTION_KEY = \u0026#34;set-temperature-action-key\u0026#34;; private final static int MESSAGE_UPDATE_TIME = 1000; private final static int MESSAGE_UPDATE_NUMBER = 10; private final static double TEMPERATURE_MIN_VALUE = 20; private final static double TEMPERATURE_MAX_VALUE = 30; public DemoPhysicalAdapter(String id) { super(id); } @Override public void onIncomingPhysicalAction(PhysicalAssetActionWldtEvent\u0026lt;?\u0026gt; physicalAssetActionWldtEvent) { try{ if(physicalAssetActionWldtEvent != null \u0026amp;\u0026amp; physicalAssetActionWldtEvent.getActionKey().equals(SET_TEMPERATURE_ACTION_KEY) \u0026amp;\u0026amp; physicalAssetActionWldtEvent.getBody() instanceof Double) { System.out.println(\u0026#34;Received Action Request: \u0026#34; + physicalAssetActionWldtEvent.getActionKey() + \u0026#34; with Body: \u0026#34; + physicalAssetActionWldtEvent.getBody()); } else System.err.println(\u0026#34;Wrong Action Received !\u0026#34;); }catch (Exception e){ e.printStackTrace(); } } @Override public void onAdapterStart() { try { //Create an empty PAD PhysicalAssetDescription pad = new PhysicalAssetDescription(); //Add a new Property associated to the target PAD with a key and a default value PhysicalAssetProperty\u0026lt;Double\u0026gt; temperatureProperty = new PhysicalAssetProperty\u0026lt;Double\u0026gt;(GlobalKeywords.TEMPERATURE_PROPERTY_KEY, 0.0); pad.getProperties().add(temperatureProperty); //Add the declaration of a new type of generated event associated to a event key // and the content type of the generated payload PhysicalAssetEvent overheatingEvent = new PhysicalAssetEvent(GlobalKeywords.OVERHEATING_EVENT_KEY, \u0026#34;text/plain\u0026#34;); pad.getEvents().add(overheatingEvent); //Declare the availability of a target action characterized by a Key, an action type // and the expected content type and the request body PhysicalAssetAction setTemperatureAction = new PhysicalAssetAction(GlobalKeywords.SET_TEMPERATURE_ACTION_KEY, \u0026#34;temperature.actuation\u0026#34;, \u0026#34;text/plain\u0026#34;); pad.getActions().add(setTemperatureAction); //Notify the new PAD to the DT\u0026#39;s Shadowing Function this.notifyPhysicalAdapterBound(pad); //Start Device Emulation new Thread(deviceEmulation()).start(); } catch (PhysicalAdapterException | EventBusException e) { e.printStackTrace(); } } @Override public void onAdapterStop() { } private Runnable deviceEmulation(){ return () -\u0026gt; { try { //Sleep 5 seconds to emulate device startup Thread.sleep(5000); //Create a new random object to emulate temperature variations Random r = new Random(); //Publish an initial Event for a normal condition publishPhysicalAssetEventWldtEvent(new PhysicalAssetEventWldtEvent\u0026lt;\u0026gt;(GlobalKeywords.OVERHEATING_EVENT_KEY, \u0026#34;normal\u0026#34;)); //Emulate the generation on \u0026#39;n\u0026#39; temperature measurements for(int i = 0; i \u0026lt; GlobalKeywords.MESSAGE_UPDATE_NUMBER; i++){ //Sleep to emulate sensor measurement Thread.sleep(GlobalKeywords.MESSAGE_UPDATE_TIME); //Update the double randomTemperature = GlobalKeywords.TEMPERATURE_MIN_VALUE + (GlobalKeywords.TEMPERATURE_MAX_VALUE - GlobalKeywords.TEMPERATURE_MIN_VALUE) * r.nextDouble(); //Create a new event to notify the variation of a Physical Property PhysicalAssetPropertyWldtEvent\u0026lt;Double\u0026gt; newPhysicalPropertyEvent = new PhysicalAssetPropertyWldtEvent\u0026lt;\u0026gt;(GlobalKeywords.TEMPERATURE_PROPERTY_KEY, randomTemperature); //Publish the WLDTEvent associated to the Physical Property Variation publishPhysicalAssetPropertyWldtEvent(newPhysicalPropertyEvent); } //Publish a demo Physical Event associated to a \u0026#39;critical\u0026#39; overheating condition publishPhysicalAssetEventWldtEvent(new PhysicalAssetEventWldtEvent\u0026lt;\u0026gt;(GlobalKeywords.OVERHEATING_EVENT_KEY, \u0026#34;critical\u0026#34;)); } catch (EventBusException | InterruptedException e) { e.printStackTrace(); } }; } } Both Physical Adapters and Digital Adapters can be defined natively with a custom configuration provided by the developer as illustrated in the dedicated Section: Configurable Physical \u0026amp; Digital Adapters.\n","date":"February 9, 2024","id":4,"permalink":"/docs/guides/physical-adapter/","summary":"The developer can use an existing Physical Adapter or create a new one to handle the communication with a specific physical twin.","tags":"","title":"Physical Adapter"},{"content":"After the definition of the Physical Adapter it is time to start implementing the core of our DT through the definition of its shadowing function in charge of:\nHandle received PAD from Physical Adapters in order to device which properties, events, relationships or actions available on connected physical twins should be mapped and managed into the DT State Manage incoming notifications/callbacks associated to the variation of physical properties (e.g, temperature variation) or the generation of physical event (e.g., overheating) Process action requests from the digital world that should be validated and forward to the correct Physical Adapter in order to trigger the associated actions on the physical world The Shadowing Function has the responsibility to build and maintain the updated state of the Digital Twin The internal variable of any WLDT Shadowing Function (available through the base class ShadowingFunction) used to do that is DigitalTwinStateManager accessible through the variable: this.digitalTwinStateManager\nWhen the Shadowing Function has to compute the new DT State it can now work with the following method to handle DT State Transition:\nStart the DT State Transaction: startStateTransaction() DT State variation methods such as: createProperty() updateProperty() updatePropertyValue() deleteProperty() enableAction() updateAction() disableAction() registerEvent() updateRegisteredEvent() unRegisterEvent() createRelationship() addRelationshipInstance() deleteRelationship() deleteRelationshipInstance() At the end the transaction can be committed using the method: commitStateTransaction() To access the current DT State the Shadowing Function implementation can use the method this.digitalTwinStateManager.getDigitalTwinState() The information available on the DT State are:\nproperties: List of Properties with their values (if available) actions: List of Actions that can be called on the DT events: List of Events that can be generated by the DT relationships: List of Relationships and their instances (if available) evaluationInstant: The timestamp representing the evaluation instant of the DT state Available main methods on that class instance are:\nProperties: getProperty(String propertyKey): Retrieves if present the target DigitalTwinStateProperty by Key containsProperty(String propertyKey): Checks if a target Property Key is already available in the current Digital Twin\u0026rsquo;s State getPropertyList(): Loads the list of available Properties (described by the class DigitalTwinStateProperty) available on the Digital Twin\u0026rsquo;s State createProperty(DigitalTwinStateProperty\u0026lt;?\u0026gt; dtStateProperty): Allows the creation of a new Property on the Digital Twin\u0026rsquo;s State through the class DigitalTwinStateProperty readProperty(String propertyKey): Retrieves if present the target DigitalTwinStateProperty by Key updateProperty(DigitalTwinStateProperty\u0026lt;?\u0026gt; dtStateProperty): Updates the target property using the DigitalTwinStateProperty and the associated Property Key field deleteProperty(String propertyKey): Deletes the target property identified by the specified key Actions: containsAction(String actionKey): Checks if a Digital Twin State Action with the specified key is correctly registered getAction(String actionKey): Loads the target DigitalTwinStateAction by key getActionList(): Gets the list of available Actions registered on the Digital Twin\u0026rsquo;s State enableAction(DigitalTwinStateAction digitalTwinStateAction): Enables and registers the target Action described through an instance of the DigitalTwinStateAction class updateAction(DigitalTwinStateAction digitalTwinStateAction): Update the already registered target Action described through an instance of the DigitalTwinStateAction class disableAction(String actionKey): Disables and unregisters the target Action described through an instance of the DigitalTwinStateAction class Events: containsEvent(String eventKey): Check if a Digital Twin State Event with the specified key is correctly registered getEvent(String eventKey): Return the description of a registered Digital Twin State Event according to its Key getEventList(): Return the list of existing and registered Digital Twin State Events registerEvent(DigitalTwinStateEvent digitalTwinStateEvent): Register a new Digital Twin State Event updateRegisteredEvent(DigitalTwinStateEvent digitalTwinStateEvent): Update the registration and signature of an existing Digital Twin State Event unRegisterEvent(String eventKey): Un-register a Digital Twin State Event notifyDigitalTwinStateEvent(DigitalTwinStateEventNotification\u0026lt;?\u0026gt; digitalTwinStateEventNotification): Method to notify the occurrence of the target Digital Twin State Event Relationships: containsRelationship(String relationshipName): Checks if a Relationship Name is already available in the current Digital Twin\u0026rsquo;s State createRelationship(DigitalTwinStateRelationship\u0026lt;?\u0026gt; relationship): Creates a new Relationships (described by the class DigitalTwinStateRelationship) in the Digital Twin\u0026rsquo;s State addRelationshipInstance(String name, DigitalTwinStateRelationshipInstance\u0026lt;?\u0026gt; instance): Adds a new Relationship instance described through the class DigitalTwinStateRelationshipInstance and identified through its name getRelationshipList(): Loads the list of existing relationships on the Digital Twin\u0026rsquo;s State through a list of DigitalTwinStateRelationship getRelationship(String name): Gets a target Relationship identified through its name and described through the class DigitalTwinStateRelationship deleteRelationship(String name): Deletes a target Relationship identified through its name deleteRelationshipInstance(String relationshipName, String instanceKey): Deletes the target Relationship Instance using relationship name and instance Key The basic library class that we are going to extend is called ShadowingFunction and creating a new class named DemoShadowingFunction the resulting code is the same after implementing required methods the basic constructor with the id String parameter.\nimport it.wldt.adapter.digital.event.DigitalActionWldtEvent; import it.wldt.adapter.physical.PhysicalAssetDescription; import it.wldt.adapter.physical.event.PhysicalAssetEventWldtEvent; import it.wldt.adapter.physical.event.PhysicalAssetPropertyWldtEvent; import it.wldt.adapter.physical.event.PhysicalAssetRelationshipInstanceCreatedWldtEvent; import it.wldt.adapter.physical.event.PhysicalAssetRelationshipInstanceDeletedWldtEvent; import it.wldt.core.model.ShadowingModelFunction; import java.util.Map; public class DemoShadowingFunction extends ShadowingModelFunction { public DemoShadowingFunction(String id) { super(id); } //// Shadowing Function Management Callbacks //// @Override protected void onCreate() { } @Override protected void onStart() { } @Override protected void onStop() { } //// Bound LifeCycle State Management Callbacks //// @Override protected void onDigitalTwinBound(Map\u0026lt;String, PhysicalAssetDescription\u0026gt; adaptersPhysicalAssetDescriptionMap) { } @Override protected void onDigitalTwinUnBound(Map\u0026lt;String, PhysicalAssetDescription\u0026gt; map, String s) { } @Override protected void onPhysicalAdapterBidingUpdate(String s, PhysicalAssetDescription physicalAssetDescription) { } //// Physical Property Variation Callback //// @Override protected void onPhysicalAssetPropertyVariation(PhysicalAssetPropertyWldtEvent\u0026lt;?\u0026gt; physicalAssetPropertyWldtEvent) { } //// Physical Event Notification Callback //// @Override protected void onPhysicalAssetEventNotification(PhysicalAssetEventWldtEvent\u0026lt;?\u0026gt; physicalAssetEventWldtEvent) { } //// Physical Relationships Notification Callbacks //// @Override protected void onPhysicalAssetRelationshipEstablished(PhysicalAssetRelationshipInstanceCreatedWldtEvent\u0026lt;?\u0026gt; physicalAssetRelationshipInstanceCreatedWldtEvent) { } @Override protected void onPhysicalAssetRelationshipDeleted(PhysicalAssetRelationshipInstanceDeletedWldtEvent\u0026lt;?\u0026gt; physicalAssetRelationshipInstanceDeletedWldtEvent) { } //// Digital Action Received Callbacks //// @Override protected void onDigitalActionEvent(DigitalActionWldtEvent\u0026lt;?\u0026gt; digitalActionWldtEvent) { } } The methods onCreate(), onStart() and onStop() are used to receive callbacks from the DT\u0026rsquo;s core when the Shadowing Function has been effectively created within the twin, is started or stopped according to the evolution of its life cycle. In our initial implementation we are not implementing any of them but they can be useful to trigger specific behaviours according to the different phases.\nThe first method that we have to implement in order to analyze received PAD and build the Digital Twin State in terms of properties, events, relationships and available actions is the onDigitalTwinBound(Map\u0026lt;String, PhysicalAssetDescription\u0026gt; map) method. In our initial implementation we just pass through all the received characteristics recevied from each connected Physical Adapter mapping every physical entity into the DT\u0026rsquo;s state without any change or adaptation (Of course complex behaviour can be implemented to customized the digitalization process).\nThrough the following method we implement the following behaviour:\nAnalyze each received PAD from each connected and active Physical Adapter (in our case we will have just 1 Physical Adapter) Iterate over all the received Properties for each PAD and create the same Property on the Digital Twin State Start observing target Physical Properties in order to receive notification callback about physical variation through the method observePhysicalAssetProperty(property); Analyze received PAD\u0026rsquo;s Events declaration and recreates them also on the DT\u0026rsquo;s State Start observing target Physical Event in order to receive notification callback about physical event generation through the method observePhysicalAssetEvent(event); Check available Physical Action and enable them on the DT\u0026rsquo;s State. Enabled Digital Action are automatically observed by the Shadowing Function in order to receive action requests from active Digital Adapters The possibility to manually observe Physical Properties and Event has been introduced to allow the Shadowing Function to decide what to do according to the nature of the property or of the target event. For example in some cases with static properties it will not be necessary to observe any variation, and it will be enough to read the initial value to build the digital replica of that specific property.\nSince the DT State is managed through the DigitalTwinStateManager class all the changes and variation should be applied on the DT ShadowingFunction using the previously presented transaction management and the correct call of methods startStateTransaction() and commitStateTransaction().\n@Override protected void onDigitalTwinBound(Map\u0026lt;String, PhysicalAssetDescription\u0026gt; adaptersPhysicalAssetDescriptionMap) { try{ // NEW from 0.3.0 -\u0026gt; Start DT State Change Transaction this.digitalTwinStateManager.startStateTransaction(); //Iterate over all the received PAD from connected Physical Adapters adaptersPhysicalAssetDescriptionMap.values().forEach(pad -\u0026gt; { //Iterate over all the received PAD from connected Physical Adapters adaptersPhysicalAssetDescriptionMap.values().forEach(pad -\u0026gt; { pad.getProperties().forEach(property -\u0026gt; { try { //Create and write the property on the DT\u0026#39;s State this.digitalTwinState.createProperty(new DigitalTwinStateProperty\u0026lt;\u0026gt;(property.getKey(),(Double) property.getInitialValue())); //Start observing the variation of the physical property in order to receive notifications //Without this call the Shadowing Function will not receive any notifications or callback about //incoming physical property of the target type and with the target key this.observePhysicalAssetProperty(property); } catch (Exception e) { e.printStackTrace(); } }); //Iterate over available declared Physical Events for the target Physical Adapter\u0026#39;s PAD pad.getEvents().forEach(event -\u0026gt; { try { //Instantiate a new DT State Event with the same key and type DigitalTwinStateEvent dtStateEvent = new DigitalTwinStateEvent(event.getKey(), event.getType()); //Create and write the event on the DT\u0026#39;s State this.digitalTwinState.registerEvent(dtStateEvent); //Start observing the variation of the physical event in order to receive notifications //Without this call the Shadowing Function will not receive any notifications or callback about //incoming physical events of the target type and with the target key this.observePhysicalAssetEvent(event); } catch (Exception e) { e.printStackTrace(); } }); //Iterate over available declared Physical Actions for the target Physical Adapter\u0026#39;s PAD pad.getActions().forEach(action -\u0026gt; { try { //Instantiate a new DT State Action with the same key and type DigitalTwinStateAction dtStateAction = new DigitalTwinStateAction(action.getKey(), action.getType(), action.getContentType()); //Enable the action on the DT\u0026#39;s State this.digitalTwinState.enableAction(dtStateAction); } catch (Exception e) { e.printStackTrace(); } }); }); // NEW from 0.3.0 -\u0026gt; Commit DT State Change Transaction to apply the changes on the DT State and notify about the change this.digitalTwinStateManager.commitStateTransaction(); //Start observation to receive all incoming Digital Action through active Digital Adapter //Without this call the Shadowing Function will not receive any notifications or callback about //incoming request to execute an exposed DT\u0026#39;s Action observeDigitalActionEvents(); //Notify the DT Core that the Bounding phase has been correctly completed and the DT has evaluated its //internal status according to what is available and declared through the Physical Adapters notifyShadowingSync(); }catch (Exception e){ e.printStackTrace(); } } In particular the method observeDigitalActionEvents() should be called start the observation of digital actions and to receive all incoming Digital Action through active Digital Adapters. Without this call the Shadowing Function will not receive any notifications or callback about incoming request to execute an exposed DT\u0026rsquo;s Action. Of course, we have to call this method if we are mapping any digital action in our DT.\nAnother fundamental method is notifyShadowingSync() used to notify the DT Core that the Bounding phase has been correctly completed and the DT has evaluated its internal status according to what is available and declared through the Physical Adapters.\nAs mentioned, in the previous example the Shadowing Function does not apply any control or check on the nature of declared physical property. Of course in order to have a more granular control, it will be possible to use property Key or any other field or even the type of the instance through an instanceof check to implement different controls and behaviours.\nA variation (only for the property management code) to the previous method can be the following:\n//Iterate over available declared Physical Property for the target Physical Adapter\u0026#39;s PAD pad.getProperties().forEach(property -\u0026gt; { try { //Check property Key and Instance of to validate that is a Double if(property.getKey().equals(\u0026#34;temperature-property-key\u0026#34;) \u0026amp;\u0026amp; property.getInitialValue() != null \u0026amp;\u0026amp; property.getInitialValue() instanceof Double) { //Instantiate a new DT State Property of the right type, the same key and initial value DigitalTwinStateProperty\u0026lt;Double\u0026gt; dtStateProperty = new DigitalTwinStateProperty\u0026lt;Double\u0026gt;(property.getKey(),(Double) property.getInitialValue()); //Create and write the property on the DT\u0026#39;s State this.digitalTwinState.createProperty(dtStateProperty); //Start observing the variation of the physical property in order to receive notifications //Without this call the Shadowing Function will not receive any notifications or callback about //incoming physical property of the target type and with the target key this.observePhysicalAssetProperty(property); } } catch (Exception e) { e.printStackTrace(); } }); The next method that we have to implement in order to properly define and implement the behaviour of our DT through its ShadowingModelFunction are:\nonPhysicalAssetPropertyVariation: Method called when a new variation for a specific Physical Property has been detected by the associated Physical Adapter. The method receive as parameter a specific WLDT Event called PhysicalAssetPropertyWldtEvent\u0026lt;?\u0026gt; physicalPropertyEventMessage containing all the information generated by the Physical Adapter upon the variation of the monitored physical counterpart. onPhysicalAssetEventNotification: Callback method used to be notified by a PhysicalAdapter about the generation of a Physical Event. As for the previous method, also this function receive a WLDT Event parameter of type onPhysicalAssetEventNotification(PhysicalAssetEventWldtEvent\u0026lt;?\u0026gt; physicalAssetEventWldtEvent)) containing all the field of the generated physical event. onDigitalActionEvent: On the opposite this method is triggered from one of the active Digital Adapter when an Action request has been received on the Digital Interface. The method receive as parameter an instance of the WLDT Event class DigitalActionWldtEvent\u0026lt;?\u0026gt; digitalActionWldtEvent describing the target digital action request and the associated body. For the onPhysicalAssetPropertyVariation a simple implementation in charge ONLY of mapping the new Physical Property value into the corresponding DT\u0026rsquo;State property can be implemented as follows:\nThe DT State transaction management should be applied in the point of the code where the Shadowing Function receive a variation from the Physical world through a target adapter and the callback method onPhysicalAssetPropertyVariation(...)\n@Override protected void onPhysicalAssetPropertyVariation(PhysicalAssetPropertyWldtEvent\u0026lt;?\u0026gt; physicalPropertyEventMessage) { try { //Update Digital Twin State //NEW from 0.3.0 -\u0026gt; Start State Transaction this.digitalTwinStateManager.startStateTransaction(); this.digitalTwinState.updateProperty(new DigitalTwinStateProperty\u0026lt;\u0026gt;(physicalPropertyEventMessage.getPhysicalPropertyId(), physicalPropertyEventMessage.getBody())); //NEW from 0.3.0 -\u0026gt; Commit State Transaction this.digitalTwinStateManager.commitStateTransaction(); } catch (WldtDigitalTwinStatePropertyException | WldtDigitalTwinStatePropertyBadRequestException | WldtDigitalTwinStatePropertyNotFoundException | WldtDigitalTwinStateException e) { e.printStackTrace(); } } In this case as reported in the code, we call the method this.digitalTwinState.updateProperty on the Shadowing Function in order to update an existing DT\u0026rsquo;State property (previously created in the onDigitalTwinBound method). To update the value we directly use the received data on the PhysicalAssetPropertyWldtEvent without any additional check or change that might be instead needed in advanced examples.\nFollowing the same principle, a simplified digital mapping between physical and digital state upon the receving of a physical event variation can be the following:\n@Override protected void onPhysicalAssetEventNotification(PhysicalAssetEventWldtEvent\u0026lt;?\u0026gt; physicalAssetEventWldtEvent) { try { this.digitalTwinStateManager.notifyDigitalTwinStateEvent(new DigitalTwinStateEventNotification\u0026lt;\u0026gt;(physicalAssetEventWldtEvent.getPhysicalEventKey(), physicalAssetEventWldtEvent.getBody(), physicalAssetEventWldtEvent.getCreationTimestamp())); } catch (WldtDigitalTwinStateEventNotificationException | EventBusException e) { e.printStackTrace(); } } With respect to events management, we use the Shadowint Function method this.digitalTwinState.notifyDigitalTwinStateEvent to notify the other DT Components (e.g., Digital Adapters) the incoming Physical Event by creating a new instance of a DigitalTwinStateEventNotification class containing all the information associated to the event. Of course, additional controls and checks can be introduced in this method validating and processing the incoming physical message to define complex behaviours.\nThe last method that we are going to implement is the onDigitalActionEvent one where we have to handle an incoming Digital Action request associated to an Action declared on the DT\u0026rsquo;s State in the onDigitalTwinBound method. In that case the Digital Action should be forwarded to the Physical Interface in order to be sent to the physical counterpart for the effective execution.\n@Override protected void onDigitalActionEvent(DigitalActionWldtEvent\u0026lt;?\u0026gt; digitalActionWldtEvent) { try { this.publishPhysicalAssetActionWldtEvent(digitalActionWldtEvent.getActionKey(), digitalActionWldtEvent.getBody()); } catch (EventBusException e) { e.printStackTrace(); } } Also in that case we are forwarding the incoming Digital Action request described through the class DigitalActionWldtEvent to the Physical Adapter with the method of the Shadowing Function denoted as this.publishPhysicalAssetActionWldtEvent and passing directly the action key and the target Body. No additional processing or validation have been introduced here, but they might be required in advanced scenario in order to properly adapt incoming digital action request to what is effectively expected on the physical counterpart.\n","date":"February 9, 2024","id":5,"permalink":"/docs/guides/shadowing-function/","summary":"After the definition of the Physical Adapter it is time to start implementing the core of our DT through the definition of its shadowing function in charge of:","tags":"","title":"Shadowing Function"},{"content":"The las component that we have to implement to complete our first simple Digital Twin definition through the WLDT library is a Digital Adapter in charge of:\nReceiving event from the DT\u0026rsquo;s Core related to the variation of properties, events, available actions and relationships Expose received information to the external world according to its implementation and the supported protocol Handle incoming digital action and forward them to the Core in order to be validated and processed by the Shadowing Function The basic library class that we are going to extend is called DigitalAdapter and creating a new class named DemoDigitalAdapter. The DigitalTwinAdapter class can take as Generic Type the type of Configuration used to configure its behaviours. In this simplified example we are defining a DigitalAdapter without any Configuration.\nA Digital Adapter has direct access to the current DT\u0026rsquo;s State through callbacks or directly in a synchronous way using the internal variable called: digitalTwinState. Through it is possibile to navigate all the fields currently composing the state of our Digital Twin.\nThe Digital Adapter class has e long list of callback and notification method to allow the adapter to be updated about all the variation and changes on the twin. Available callbacks can be summarized as follows:\nDigital Adapter Start/Stop: onAdapterStart(): Feedback when the Digital Adapter correctly starts onAdapterStop(): Feedback when the Digital Adapter has been stopped Digital Twin Life Cycle Notifications: onDigitalTwinCreate(): The DT has been created onDigitalTwinStart(): The DT started onDigitalTwinSync(IDigitalTwinState digitalTwinState): The DT is Synchronized with its physical counterpart. The current DigitalTwinState is passed as parameter to allow the Digital Adapter to know the current state and consequently implement its behaviour onDigitalTwinUnSync(IDigitalTwinState digitalTwinState): The DT is not synchronized anymore with its physical counterpart. The last current DigitalTwinState is passed as parameter to allow the Digital Adapter to know the last state and consequently implement its behaviour onDigitalTwinStop(): The DT is stopped onDigitalTwinDestroy(): The DT has been destroyed and the application stopped The Digital Adapter DT State variations and DT events are received by the Adapter from the DT core belongs to the following categories:\nDigital Twin State Update through the method onStateUpdate(...) providing information about the new state of the Digital Twin, the previous state, and a list of changes that occurred between these two states. In the previous version each variation of a property, relationships, actions or events were notified. In the new version only a committed DT\u0026rsquo;State variation is notified to listeners. Event Notifications through the method onEventNotificationReceived(...) whenever there is a notification about an event related to the Digital Twin\u0026rsquo;s state coming from the physical world, generated by the twin and processed by the Shadowing Function. For example in the DT State we can have the declaration of the over-heating-alert structured and received in the DT State while the effective occurrence of the event and the associated notification is notified through this dedicated callback The onStateUpdate method is an abstract method that must be implemented by any class extending the DigitalAdapter class. This method is called whenever there is an update to the Digital Twin\u0026rsquo;s state. It provides information about the new state of the Digital Twin, the previous state, and a list of changes that occurred between these two states.\nThe explanation of the parameters is the following:\nnewDigitalTwinState: This parameter represents the updated state of the Digital Twin. It is an instance of the DigitalTwinState class, which encapsulates the current state information. previousDigitalTwinState: This parameter represents the state of the Digital Twin before the update. It is also an instance of the DigitalTwinState class. digitalTwinStateChangeList: This parameter is an ArrayList containing DigitalTwinStateChange objects. Each DigitalTwinStateChange object encapsulates information about a specific change that occurred between the previous and new states. It includes details such as the property or aspect of the state that changed, the previous value, and the new value. Another core method where a Digital Adapter receive the description of the DT\u0026rsquo;State is onDigitalTwinSync(IDigitalTwinState digitalTwinState). The Adapter using the parameter digitalTwinState can analyze available properties, actions, events and relationships and decide how to implement its internal behaviour with the methods presented in ShadowingFunction. The DT State is automatically monitored by each Digital Adapter while for the Events potentially generated by the DT can be observed by each adapter using:\nobserveAllDigitalTwinEventsNotifications: Enable the observation of available Digital Twin State Events Notifications. unObserveAllDigitalTwinEventsNotifications: Cancel the observation of Digital Twin State Events Notifications observeDigitalTwinEventsNotifications: Enable the observation of the notification associated to a specific list of Digital Twin State events. With respect to event a notification contains the new associated value unObserveDigitalTwinEventsNotifications: Cancel the observation of a target list of properties observeDigitalTwinEventNotification: Enable the observation of the notification associated to a single Digital Twin State event. With respect to event a notification contains the new associated value unObserveDigitalTwinEventNotification: Cancel the observation of a single target event The resulting code will be the following after adding the required methods (still empty) and the basic constructor with the id String parameter is the following:\nimport it.wldt.adapter.digital.DigitalAdapter; import it.wldt.core.state.*; public class DemoDigitalAdapter extends DigitalAdapter\u0026lt;Void\u0026gt; { public DemoDigitalAdapter(String id) { super(id); } /** * Callback to notify the adapter on its correct startup */ @Override public void onAdapterStart() {} /** * Callback to notify the adapter that has been stopped */ @Override public void onAdapterStop() {} /** * DT Life Cycle notification that the DT is correctly on Sync * @param digitalTwinState */ @Override public void onDigitalTwinSync(DigitalTwinState digitalTwinState) {} /** * DT Life Cycle notification that the DT is currently Not Sync * @param digitalTwinState */ @Override public void onDigitalTwinUnSync(DigitalTwinState digitalTwinState) {} /** * DT Life Cycle notification that the DT has been created */ @Override public void onDigitalTwinCreate() {} /** * DT Life Cycle Notification that the DT has correctly Started */ @Override public void onDigitalTwinStart() {} /** * DT Life Cycle Notification that the DT has been stopped */ @Override public void onDigitalTwinStop() {} /** * DT Life Cycle Notification that the DT has destroyed */ @Override public void onDigitalTwinDestroy() {} /** * Callback method allowing the Digital Adapter to receive the updated Digital Twin State together with * the previous state and the list of applied changes * * @param newDigitalTwinState The new Digital Twin State computed by the Shadowing Function * @param previousDigitalTwinState The previous Digital Twin State * @param digitalTwinStateChangeList The list of applied changes to compute the new Digital Twin State */ @Override protected void onStateUpdate(DigitalTwinState newDigitalTwinState, DigitalTwinState previousDigitalTwinState, ArrayList\u0026lt;DigitalTwinStateChange\u0026gt; digitalTwinStateChangeList) {} /** * Callback method to receive a new computed Event Notification (associated to event declared in the DT State) * * @param digitalTwinStateEventNotification The generated Notification associated to a DT Event */ @Override protected void onEventNotificationReceived(DigitalTwinStateEventNotification\u0026lt;?\u0026gt; digitalTwinStateEventNotification) {} } By default, a Digital Adapter observes all the variation on the DT\u0026rsquo;s State in terms of Properties, Relationships, Actions and Events. As previously mentioned the observation of DT\u0026rsquo;s State Properties allows to receive also properties variation on the method since a property is natively composed by its description (e.g., type) and its current value. On the opposite the observation on DT\u0026rsquo;s State Action, Relationships and Events allow ONLY to receive callbacks when a new entity is added or an update is occurred without receiving updates on values variation.\nThe only thing that we should add in the onDigitalTwinSync(IDigitalTwinState currentDigitalTwinState) callback is the direct observation for Events. Following this approach we can change our Digital Adapter in the following methods:\nIn onDigitalTwinSync we observe in this first simple implementation only the incoming values for declared Events in the DT\u0026rsquo;State. As previously mentioned the observation of any variation of the State structure together with Properties Values are by default observed by any Digital Adapter. In this method we use the internal variable digitalTwinState to access the DT\u0026rsquo;s state and find available Events declaration that we would like to observe.\npublic void onDigitalTwinSync(IDigitalTwinState currentDigitalTwinState) { try { //Retrieve the list of available events and observe all variations digitalTwinState.getEventList() .map(eventList -\u0026gt; eventList.stream() .map(DigitalTwinStateEvent::getKey) .collect(Collectors.toList())) .ifPresent(eventKeys -\u0026gt; { try { observeDigitalTwinEventsNotifications(eventKeys); } catch (EventBusException e) { e.printStackTrace(); } }); } catch (Exception e) { e.printStackTrace(); } } Developers extending the DigitalAdapter class should implement the onStateUpdate method to define custom logic that needs to be executed whenever the state of the Digital Twin is updated. This could include tasks such as processing state changes, updating internal variables, triggering specific actions, or notifying other components about the state update.\nHere\u0026rsquo;s an example of how the method might be implemented in a concrete subclass of DigitalAdapter:\n@Override protected void onStateUpdate(DigitalTwinState newDigitalTwinState, DigitalTwinState previousDigitalTwinState, ArrayList\u0026lt;DigitalTwinStateChange\u0026gt; digitalTwinStateChangeList) { // In newDigitalTwinState we have the new DT State System.out.println(\u0026#34;New DT State is: \u0026#34; + newDigitalTwinState); // The previous DT State is available through the variable previousDigitalTwinState System.out.println(\u0026#34;Previous DT State is: \u0026#34; + previousDigitalTwinState); // We can also check each DT\u0026#39;s state change potentially differentiating the behaviour for each change if (digitalTwinStateChangeList != null \u0026amp;\u0026amp; !digitalTwinStateChangeList.isEmpty()) { // Iterate through each state change in the list for (DigitalTwinStateChange stateChange : digitalTwinStateChangeList) { // Get information from the state change DigitalTwinStateChange.Operation operation = stateChange.getOperation(); DigitalTwinStateChange.ResourceType resourceType = stateChange.getResourceType(); DigitalTwinStateResource resource = stateChange.getResource(); // Perform different actions based on the type of operation switch (operation) { case OPERATION_UPDATE: // Handle an update operation System.out.println(\u0026#34;Update operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; case OPERATION_UPDATE_VALUE: // Handle an update value operation System.out.println(\u0026#34;Update value operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; case OPERATION_ADD: // Handle an add operation System.out.println(\u0026#34;Add operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; case OPERATION_REMOVE: // Handle a remove operation System.out.println(\u0026#34;Remove operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; default: // Handle unknown operation (optional) System.out.println(\u0026#34;Unknown operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; } } } else { // No state changes System.out.println(\u0026#34;No state changes detected.\u0026#34;); } } In this example, the method iterates over the list of state changes, extracts information about each change, and performs custom actions based on the changes. Developers can adapt this method to suit the specific requirements of their Digital Twin application.\nBoth Physical Adapters and Digital Adapters can be defined natively with a custom configuration provided by the developer as illustrated in the dedicated Section: Configurable Physical \u0026amp; Digital Adapters.\n","date":"February 9, 2024","id":6,"permalink":"/docs/guides/digital-adapter/","summary":"The las component that we have to implement to complete our first simple Digital Twin definition through the WLDT library is a Digital Adapter in charge of:","tags":"","title":"Digital Adapter"},{"content":"Now that we have created the main fundamental element of a DT (Physical Adapter, Shadowing Function and Digital Adapter) we can create Class file with a main to create the WLDT Engine with the created components and start the DT.\nCreate a new Java file called DemoDigitalTwin adding the following code:\nWith the following code we now create a new Digital Twin Instance\n// Create the new Digital Twin with its Shadowing Function DigitalTwin digitalTwin = new DigitalTwin(digitalTwinId, new DemoShadowingFunction()); // Physical Adapter with Configuration digitalTwin.addPhysicalAdapter( new DemoPhysicalAdapter( String.format(\u0026#34;%s-%s\u0026#34;, digitalTwinId, \u0026#34;test-physical-adapter\u0026#34;), new DemoPhysicalAdapterConfiguration(), true)); // Digital Adapter with Configuration digitalTwin.addDigitalAdapter( new DemoDigitalAdapter( String.format(\u0026#34;%s-%s\u0026#34;, digitalTwinId, \u0026#34;test-digital-adapter\u0026#34;), new DemoDigitalAdapterConfiguration()) ); DTs cannot be directly run but it should be added to the DigitalTwinEngine in order to be executed through the WLDT Library\n// Create the Digital Twin Engine DigitalTwinEngine digitalTwinEngine = new DigitalTwinEngine(); // Add the Digital Twin to the Engine digitalTwinEngine.addDigitalTwin(digitalTwin); In order to start a DT from the Engine you can:\n// Directly start when you add it passing a second boolean value = true digitalTwinEngine.addDigitalTwin(digitalTwin. true); // Starting the single DT on the engine through its id digitalTwinEngine.startDigitalTwin(DIGITAL_TWIN_ID); // Start all the DTs registered on the engine digitalTwinEngine.startAll(); To stop a single twin or all the twin registered on the engine:\n// Stop a single DT on the engine through its id digitalTwinEngine.stopDigitalTwin(DIGITAL_TWIN_ID); // Stop all the DTs registered on the engine digitalTwinEngine.stopAll(); It is also possible to remove a DT from the Engine with a consequent stop if it is active and the deletion of its reference from the engine:\n// Remove a single DT on the engine through its id digitalTwinEngine.removeDigitalTwin(DIGITAL_TWIN_ID); // Remove all the DTs registered on the engine digitalTwinEngine.removeAll(); The resulting code in our case is:\npublic class DemoDigitalTwin { public static void main(String[] args) { try{ // Create the new Digital Twin DigitalTwin digitalTwin = new DigitalTwin( \u0026#34;test-dt-id\u0026#34;, new DemoShadowingFunction(\u0026#34;test-shadowing-function\u0026#34;) ); //Default Physical and Digital Adapter //digitalTwin.addPhysicalAdapter(new DemoPhysicalAdapter(\u0026#34;test-physical-adapter\u0026#34;)); //digitalTwin.addDigitalAdapter(new DemoDigitalAdapter(\u0026#34;test-digital-adapter\u0026#34;)); //Physical and Digital Adapters with Configuration digitalTwin.addPhysicalAdapter(new DemoConfPhysicalAdapter(\u0026#34;test-physical-adapter\u0026#34;, new DemoPhysicalAdapterConfiguration())); digitalTwin.addDigitalAdapter(new DemoConfDigitalAdapter(\u0026#34;test-digital-adapter\u0026#34;, new DemoDigitalAdapterConfiguration())); // Create the Digital Twin Engine DigitalTwinEngine digitalTwinEngine = new DigitalTwinEngine(); // Add the Digital Twin to the Engine digitalTwinEngine.addDigitalTwin(digitalTwin); // Set a new Event-Logger to a Custom One that we created with the class \u0026#39;DemoEventLogger\u0026#39; WldtEventBus.getInstance().setEventLogger(new DemoEventLogger()); // Start all the DTs registered on the engine digitalTwinEngine.startAll(); }catch (Exception e){ e.printStackTrace(); } } } ","date":"February 9, 2024","id":7,"permalink":"/docs/guides/dt-engine-dt-instance/","summary":"Now that we have created the main fundamental element of a DT (Physical Adapter, Shadowing Function and Digital Adapter) we can create Class file with a main to create the WLDT Engine with the created components and start the DT.","tags":"","title":"DT Engine \u0026 DT Instance"},{"content":"In this demo implementation, we are going to emulate an incoming Digital Action on the Digital Adapter in order to show how it can be handled by the adapter and properly forwarded to the Shadowing Function for validation and the consequent interaction with the Physical Adapter and then with the physical twin.\nIn order to add a demo Digital Action trigger on the Digital Adapter we add the following method to the DemoDigitalAdapter class:\nprivate Runnable emulateIncomingDigitalAction(){ return () -\u0026gt; { try { System.out.println(\u0026#34;Sleeping before Emulating Incoming Digital Action ...\u0026#34;); Thread.sleep(5000); Random random = new Random(); //Emulate the generation on \u0026#39;n\u0026#39; temperature measurements for(int i = 0; i \u0026lt; 10; i++){ //Sleep to emulate sensor measurement Thread.sleep(1000); double randomTemperature = 25.0 + (30.0 - 25.0) * random.nextDouble(); publishDigitalActionWldtEvent(\u0026#34;set-temperature-action-key\u0026#34;, randomTemperature); } } catch (Exception e) { e.printStackTrace(); } }; } This method uses the Digital Adapter internal function denoted as publishDigitalActionWldtEvent(String actionKey, T body) allowing the adapter to send a notification to the DT\u0026rsquo;s Core (and consequently the Shadowing Function) about the arrival of a Digital Action with a specific key and body. In our case the key is set-temperature-action-key as declared in the Physical Adapter and in the PAD and the value is a simple Double with the new temperature value.\nThen we call this method in the following way at the end ot the onDigitalTwinSync(IDigitalTwinState currentDigitalTwinState) method.\n//Start Digital Action Emulation new Thread(emulateIncomingDigitalAction()).start(); Now the Shadowing Function should be updated in order to handle the incoming Action request from the Digital Adapter. In our case the shadowing function does not apply any validation or check and just forward to action to the Physical Adapter in order to be then forwarded to the physical twin. Of course advanced implementation can be introduced for example to validate action, adapt payload and data-formats or to augment functionalities (e.g., trigger multiple physical actions from a single digital request).\nIn our simple demo implementation the updated Shadowing Function method onDigitalActionEvent(DigitalActionWldtEvent\u0026lt;?\u0026gt; digitalActionWldtEvent) results as follows:\n@Override protected void onDigitalActionEvent(DigitalActionWldtEvent\u0026lt;?\u0026gt; digitalActionWldtEvent) { try { this.publishPhysicalAssetActionWldtEvent(digitalActionWldtEvent.getActionKey(), digitalActionWldtEvent.getBody()); } catch (Exception e) { e.printStackTrace(); } } This forwarding of the action triggers the corresponding Physical Adapter method onIncomingPhysicalAction(PhysicalAssetActionWldtEvent\u0026lt;?\u0026gt; physicalAssetActionWldtEvent) that in our case is emulated just with a Log on the console. Also in that case advanced Physical Adapter implementation can be introduced for example to adapt the request from a high-level (and potentially standard) DT action description to the custom requirements of the specific physical twin managed by the adapter.\n@Override public void onIncomingPhysicalAction(PhysicalAssetActionWldtEvent\u0026lt;?\u0026gt; physicalAssetActionWldtEvent) { try{ if(physicalAssetActionWldtEvent != null \u0026amp;\u0026amp; physicalAssetActionWldtEvent.getActionKey().equals(SET_TEMPERATURE_ACTION_KEY) \u0026amp;\u0026amp; physicalAssetActionWldtEvent.getBody() instanceof Double) { System.out.println(\u0026#34;Received Action Request: \u0026#34; + physicalAssetActionWldtEvent.getActionKey() + \u0026#34; with Body: \u0026#34; + physicalAssetActionWldtEvent.getBody()); } else System.err.println(\u0026#34;Wrong Action Received !\u0026#34;); }catch (Exception e){ e.printStackTrace(); } } ","date":"February 9, 2024","id":8,"permalink":"/docs/guides/digital-actions/","summary":"In this demo implementation, we are going to emulate an incoming Digital Action on the Digital Adapter in order to show how it can be handled by the adapter and properly forwarded to the Shadowing Function for validation and the consequent interaction with the Physical Adapter and then with the physical twin.","tags":"","title":"Digital Actions"},{"content":"The WLDT library provides a native method to define Configurable Physical ad Digital Adapters specifying a custom configuration class passed as parameter in the constructor.\nStarting with the Physical Adapter created in the previous example DemoPhysicalAdapter instead of extending the base class PhysicalAdapter we can extend now ConfigurablePhysicalAdapter\u0026lt;C\u0026gt; where C is the name of the that we would like to use as configuration.\nIn our example we can create a simple configuration class called DemoPhysicalAdapterConfiguration where we move the constant variable used to implement the behaviour of our demo physical adapter. The resulting class will be the following:\npublic class DemoPhysicalAdapterConfiguration { private int messageUpdateTime = GlobalKeywords.MESSAGE_UPDATE_TIME; private int messageUpdateNumber = GlobalKeywords.MESSAGE_UPDATE_NUMBER; private double temperatureMinValue = GlobalKeywords.TEMPERATURE_MIN_VALUE; private double temperatureMaxValue = GlobalKeywords.TEMPERATURE_MAX_VALUE; public DemoPhysicalAdapterConfiguration() { } public DemoPhysicalAdapterConfiguration(int messageUpdateTime, int messageUpdateNumber, double temperatureMinValue, double temperatureMaxValue) { this.messageUpdateTime = messageUpdateTime; this.messageUpdateNumber = messageUpdateNumber; this.temperatureMinValue = temperatureMinValue; this.temperatureMaxValue = temperatureMaxValue; } public int getMessageUpdateTime() { return messageUpdateTime; } public void setMessageUpdateTime(int messageUpdateTime) { this.messageUpdateTime = messageUpdateTime; } public int getMessageUpdateNumber() { return messageUpdateNumber; } public void setMessageUpdateNumber(int messageUpdateNumber) { this.messageUpdateNumber = messageUpdateNumber; } public double getTemperatureMinValue() { return temperatureMinValue; } public void setTemperatureMinValue(double temperatureMinValue) { this.temperatureMinValue = temperatureMinValue; } public double getTemperatureMaxValue() { return temperatureMaxValue; } public void setTemperatureMaxValue(double temperatureMaxValue) { this.temperatureMaxValue = temperatureMaxValue; } } Now we can create or update our Physical Adapter extending ConfigurablePhysicalAdapter\u0026lt;DemoPhysicalAdapterConfiguration\u0026gt; as illustrated in the following snippet:\npublic class DemoPhysicalAdapter extends ConfigurablePhysicalAdapter\u0026lt;DemoPhysicalAdapterConfiguration\u0026gt; { [...] } Extending this class also the constructor should be updated getting as a parameter the expected configuration instance. Our constructor will be the following:\npublic DemoConfPhysicalAdapter(String id, DemoPhysicalAdapterConfiguration configuration) { super(id, configuration); } After that change since we removed and moved the used constant values into the new Configuration class we have also to update the deviceEmulation() method having access to the configuration through the method getConfiguration() or this.getConfiguration() directly on the adapter.\nprivate Runnable deviceEmulation(){ return () -\u0026gt; { try { System.out.println(\u0026#34;[DemoPhysicalAdapter] -\u0026gt; Sleeping before Starting Physical Device Emulation ...\u0026#34;); //Sleep 5 seconds to emulate device startup Thread.sleep(10000); System.out.println(\u0026#34;[DemoPhysicalAdapter] -\u0026gt; Starting Physical Device Emulation ...\u0026#34;); //Create a new random object to emulate temperature variations Random r = new Random(); //Publish an initial Event for a normal condition publishPhysicalAssetEventWldtEvent(new PhysicalAssetEventWldtEvent\u0026lt;\u0026gt;(GlobalKeywords.OVERHEATING_EVENT_KEY, \u0026#34;normal\u0026#34;)); //Emulate the generation on \u0026#39;n\u0026#39; temperature measurements for(int i = 0; i \u0026lt; getConfiguration().getMessageUpdateNumber(); i++){ //Sleep to emulate sensor measurement Thread.sleep(getConfiguration().getMessageUpdateTime()); //Update the double randomTemperature = getConfiguration().getTemperatureMinValue() + (getConfiguration().getTemperatureMaxValue() - getConfiguration().getTemperatureMinValue()) * r.nextDouble(); //Create a new event to notify the variation of a Physical Property PhysicalAssetPropertyWldtEvent\u0026lt;Double\u0026gt; newPhysicalPropertyEvent = new PhysicalAssetPropertyWldtEvent\u0026lt;\u0026gt;(GlobalKeywords.TEMPERATURE_PROPERTY_KEY, randomTemperature); //Publish the WLDTEvent associated to the Physical Property Variation publishPhysicalAssetPropertyWldtEvent(newPhysicalPropertyEvent); } //Publish a demo Physical Event associated to a \u0026#39;critical\u0026#39; overheating condition publishPhysicalAssetEventWldtEvent(new PhysicalAssetEventWldtEvent\u0026lt;\u0026gt;(GlobalKeywords.OVERHEATING_EVENT_KEY, \u0026#34;critical\u0026#34;)); } catch (EventBusException | InterruptedException e) { e.printStackTrace(); } }; } A similar approach can be adopted also for the Digital Adapter with the small difference that the base class DigitalAdapter already allow the possibility to specify a configuration. For this reason in the previous example we extended DigitalAdapter\u0026lt;Void\u0026gt; avoiding to specifying a configuration.\nIn this updated version we can create a new DemoDigitalAdapterConfiguration class containing the parameter association to the emulation of the action and then update our adapter to support the new configuration. Our new configuration class will be:\npublic class DemoDigitalAdapterConfiguration { private int sleepTimeMs = GlobalKeywords.ACTION_SLEEP_TIME_MS; private int emulatedActionCount = GlobalKeywords.EMULATED_ACTION_COUNT; private double temperatureMinValue = GlobalKeywords.TEMPERATURE_MIN_VALUE; private double temperatureMaxValue = GlobalKeywords.TEMPERATURE_MAX_VALUE; public DemoDigitalAdapterConfiguration() { } public DemoDigitalAdapterConfiguration(int sleepTimeMs, int emulatedActionCount, double temperatureMinValue, double temperatureMaxValue) { this.sleepTimeMs = sleepTimeMs; this.emulatedActionCount = emulatedActionCount; this.temperatureMinValue = temperatureMinValue; this.temperatureMaxValue = temperatureMaxValue; } public int getSleepTimeMs() { return sleepTimeMs; } public void setSleepTimeMs(int sleepTimeMs) { this.sleepTimeMs = sleepTimeMs; } public int getEmulatedActionCount() { return emulatedActionCount; } public void setEmulatedActionCount(int emulatedActionCount) { this.emulatedActionCount = emulatedActionCount; } public double getTemperatureMinValue() { return temperatureMinValue; } public void setTemperatureMinValue(double temperatureMinValue) { this.temperatureMinValue = temperatureMinValue; } public double getTemperatureMaxValue() { return temperatureMaxValue; } public void setTemperatureMaxValue(double temperatureMaxValue) { this.temperatureMaxValue = temperatureMaxValue; } } After that we can update the declaration of our Digital Adapter and modify its constructor to accept the configuration. The resulting class will be:\npublic class DemoDigitalAdapter extends DigitalAdapter\u0026lt;DemoDigitalAdapterConfiguration\u0026gt; { public DemoDigitalAdapter(String id, DemoDigitalAdapterConfiguration configuration) { super(id, configuration); } [...] } Of course the possibility to have this configuration will allow us to improve the emulateIncomingDigitalAction method in the following way having access to the configuration through the method getConfiguration() or this.getConfiguration() directly on the adapter:\nprivate Runnable emulateIncomingDigitalAction(){ return () -\u0026gt; { try { System.out.println(\u0026#34;[DemoDigitalAdapter] -\u0026gt; Sleeping before Emulating Incoming Digital Action ...\u0026#34;); Thread.sleep(5000); Random random = new Random(); //Emulate the generation on \u0026#39;n\u0026#39; temperature measurements for(int i = 0; i \u0026lt; getConfiguration().getEmulatedActionCount(); i++){ //Sleep to emulate sensor measurement Thread.sleep(getConfiguration().getSleepTimeMs()); double randomTemperature = getConfiguration().getTemperatureMinValue() + (getConfiguration().getTemperatureMaxValue() - getConfiguration().getTemperatureMinValue()) * random.nextDouble(); publishDigitalActionWldtEvent(\u0026#34;set-temperature-action-key\u0026#34;, randomTemperature); } } catch (Exception e) { e.printStackTrace(); } }; } When we have updated both adapters making them configurable we can update our main function in the process that we have previouly device using the updated adapters and passing the configurations:\npublic class DemoDigitalTwin { public static void main(String[] args) { try{ WldtEngine digitalTwinEngine = new WldtEngine(new DemoShadowingFunction(\u0026#34;test-shadowing-function\u0026#34;), \u0026#34;test-digital-twin\u0026#34;); //Default Physical and Digital Adapter //digitalTwinEngine.addPhysicalAdapter(new DemoPhysicalAdapter(\u0026#34;test-physical-adapter\u0026#34;)); //digitalTwinEngine.addDigitalAdapter(new DemoDigitalAdapter(\u0026#34;test-digital-adapter\u0026#34;)); //Physical and Digital Adapters with Configuration digitalTwinEngine.addPhysicalAdapter(new DemoConfPhysicalAdapter(\u0026#34;test-physical-adapter\u0026#34;, new DemoPhysicalAdapterConfiguration())); digitalTwinEngine.addDigitalAdapter(new DemoConfDigitalAdapter(\u0026#34;test-digital-adapter\u0026#34;, new DemoDigitalAdapterConfiguration())); digitalTwinEngine.startLifeCycle(); }catch (Exception e){ e.printStackTrace(); } } } ","date":"February 9, 2024","id":9,"permalink":"/docs/guides/configurable-adapters/","summary":"The WLDT library provides a native method to define Configurable Physical ad Digital Adapters specifying a custom configuration class passed as parameter in the constructor.","tags":"","title":"Configurable Adapters"},{"content":"","date":"February 9, 2024","id":10,"permalink":"/docs/adapters/","summary":"","tags":"","title":"Adapters"},{"content":"The MqttPhysicalAdapter library provides a streamlined solution for efficiently managing physical assets through the MQTT protocol. It offers a range of features, including a versatile builder for effortless configuration of MQTT connections, dedicated classes for handling both incoming and outgoing topics, and a specialized adapter designed for seamless integration with diverse physical assets.\nKey Features:\nBuilder for MQTT Configuration: The library incorporates a flexible builder pattern, enabling users to effortlessly configure the essential parameters of the MQTT connection. This includes specifying the MQTT broker\u0026rsquo;s address, port, and other relevant details to establish a reliable and customizable communication link. Incoming and Outgoing Topic Handling: MqttPhysicalAdapter facilitates the handling of incoming and outgoing topics, crucial for communication between the physical assets and the MQTT broker. The library includes dedicated classes for defining and managing topics, allowing users to efficiently subscribe to incoming data and publish outgoing messages. Adapter for Physical Asset Integration: At the core of the library is a robust adapter designed specifically for integrating with various physical assets. This adapter streamlines the process of connecting and interacting with physical devices, ensuring a smooth and standardized approach to managing asset-related data. In the WLDT library, Physical Adapters has the responsibility to generate and publish the PhysicalAssetDescription (PAD) to describe the capabilities and the characteristics of our object allowing the Shadowing Function to decide how to digitalize its physical counterpart.\nIn the MqttPhysicalAdapter the generation of the PAD (Physical Asset Description) is automatically and internally executed by the adapter itself accordingly to the adapter configuration in terms of MQTT topics and their mapping with DT\u0026rsquo;s properties, events and actions.\nPrerequisites:\nExternal MQTT Broker: The MqttPhysicalAdapter library requires an external MQTT broker for optimal functionality. Users must have access to a reliable MQTT broker to which the adapter can subscribe. This external broker serves as the central communication hub, facilitating the exchange of messages between the adapter and the physical assets. A complete example is provided in the test folder with a complete DT Creation in the TestMain class together with MQTT IoT demo device and a test MQTT consumer.\nWLDT-Core Version Compatibility The correct mapping and compatibility between versions is reported in the following table\nmqtt-physical-adapter wldt-core 0.2.1 wldt-core 0.3.0 0.1.0 ✅ ❌ 0.1.1 ❌ ✅ Installation To use MqttPhysicalAdapter in your Java project, you can include it as a dependency using Maven or Gradle.\nMaven \u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;io.github.wldt\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;mqtt-physical-adapter\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;0.1.1\u0026lt;/version\u0026gt; \u0026lt;/dependency\u0026gt; Gradle implementation \u0026#39;io.github.wldt:mqtt-physical-adapter:0.1.1\u0026#39; Class Structure \u0026amp; Functionalities MqttPhysicalAdapterConfigurationBuilder \u0026amp; Main Methods The MqttPhysicalAdapterConfigurationBuilder is the class used to build the configuration used by the PhysicalAdater and described and implemented through the class MqttPhysicalAdapterConfiguration.\nIn order to create a configuration builder we can use the static method builder() on the MqttPhysicalAdapterConfiguration class:\nMqttPhysicalAdapterConfiguration.builder(); On the builder the available methods that can be used are:\naddPhysicalAssetPropertyAndTopic public \u0026lt;T\u0026gt; MqttPhysicalAdapterConfigurationBuilder addPhysicalAssetPropertyAndTopic(String propertyKey, T initialValue, String topic, Function\u0026lt;String, T\u0026gt; topicFunction) throws MqttPhysicalAdapterConfigurationException Adds a physical asset property and its corresponding MQTT topic to the configuration.\nType Parameter T: The type of the property. propertyKey: The key of the property. initialValue: The initial value of the property. topic: The MQTT topic associated with the property. topicFunction: A function to parse the MQTT topic payload into the property type. Returns: The updated MqttPhysicalAdapterConfigurationBuilder.\nThrows: MqttPhysicalAdapterConfigurationException - If there is a configuration error.\naddPhysicalAssetActionAndTopic public \u0026lt;T\u0026gt; MqttPhysicalAdapterConfigurationBuilder addPhysicalAssetActionAndTopic(String actionKey, String type, String contentType, String topic, Function\u0026lt;T, String\u0026gt; topicFunction) throws MqttPhysicalAdapterConfigurationException Adds a physical asset action and its corresponding MQTT topic to the configuration.\nType Parameter T: The type of the action payload. actionKey: The key of the action. type: The type of the action. contentType: The content type of the action. topic: The MQTT topic associated with the action. topicFunction: A function to convert the action payload into the MQTT topic payload. Returns: The updated MqttPhysicalAdapterConfigurationBuilder.\nThrows: MqttPhysicalAdapterConfigurationException - If there is a configuration error.\naddPhysicalAssetEventAndTopic public \u0026lt;T\u0026gt; MqttPhysicalAdapterConfigurationBuilder addPhysicalAssetEventAndTopic(String eventKey, String type, String topic, Function\u0026lt;String, T\u0026gt; topicFunction) throws MqttPhysicalAdapterConfigurationException Adds a physical asset event and its corresponding MQTT topic to the configuration.\nType Parameter T: The type of the event payload. eventKey: The key of the event. type: The type of the event. topic: The MQTT topic associated with the event. topicFunction: A function to parse the MQTT topic payload into the event payload type. Returns: The updated MqttPhysicalAdapterConfigurationBuilder.\nThrows: MqttPhysicalAdapterConfigurationException - If there is a configuration error.\naddIncomingTopic public MqttPhysicalAdapterConfigurationBuilder addIncomingTopic(DigitalTwinIncomingTopic topic, List\u0026lt;PhysicalAssetProperty\u0026lt;?\u0026gt;\u0026gt; properties, List\u0026lt;PhysicalAssetEvent\u0026gt; events) throws MqttPhysicalAdapterConfigurationException This method is used when multiple properties or events can be associated to a single MQTT topic on the physical device. It adds a DigitalTwinIncomingTopic describing the topic where the DT will receive the data along with its related lists of properties and events associated to that topic.\ntopic: The DigitalTwinIncomingTopic to be added. properties: The list of related physical asset properties. events: The list of related physical asset events. Returns: The updated MqttPhysicalAdapterConfigurationBuilder.\nThrows: MqttPhysicalAdapterConfigurationException - If there is a configuration error.\naddOutgoingTopic public MqttPhysicalAdapterConfigurationBuilder addOutgoingTopic(String actionKey, String type, String contentType, DigitalTwinOutgoingTopic topic) throws MqttPhysicalAdapterConfigurationException Adds a DigitalTwinOutgoingTopic to the configuration.\nactionKey: The key of the associated action. type: The type of the associated action. contentType: The content type of the associated action. topic: The DigitalTwinOutgoingTopic to be added. Returns: The updated MqttPhysicalAdapterConfigurationBuilder.\nThrows: MqttPhysicalAdapterConfigurationException - If there is a configuration error.\nAdditional Methods setConnectionTimeout(Integer connectionTimeout): Sets the connection timeout for the MQTT client. Returns the builder for method chaining. Throws MqttPhysicalAdapterConfigurationException if the provided timeout is invalid. setCleanSessionFlag(boolean cleanSession): Sets the clean session flag for the MQTT client. Returns the builder for method chaining. setAutomaticReconnectFlag(boolean automaticReconnect): Sets the automatic reconnect flag for the MQTT client. Returns the builder for method chaining. setMqttClientPersistence(MqttClientPersistence persistence): Sets the persistence for the MQTT client. Returns the builder for method chaining. Throws MqttPhysicalAdapterConfigurationException if the provided persistence is null. build(): Builds and returns the finalized MqttPhysicalAdapterConfiguration object. Throws MqttPhysicalAdapterConfigurationException if the configuration is incomplete or invalid. MqttPhysicalAdapter The MqttPhysicalAdapter class is the core component for interacting with physical assets. Instantiate it with a unique ID and the configuration. It extends the default WLDT Library PhysicalAdapter implementing all the functionalities to automatically interact with an MQTT physical device following the specifications and details provided in the MqttPhysicalAdapterConfiguration and built using MqttPhysicalAdapterConfigurationBuilder.\nAn example of its creation is:\nMqttPhysicalAdapter mqttPhysicalAdapter = new MqttPhysicalAdapter(\u0026#34;uniqueId\u0026#34;, configuration); Integrated Example This example demonstrates the integration of a MqttPhysicalAdapter within a Digital Twin setup, where multiple adapters (including a console adapter) are added to a Digital Twin, and the overall system is managed by a DigitalTwinEngine.\n// Create a Digital Twin with a default shadowing function DigitalTwin digitalTwin = new DigitalTwin(\u0026#34;mqtt-digital-twin\u0026#34;, new DefaultShadowingFunction()); // Create an instance of ConsoleDigitalAdapter ConsoleDigitalAdapter consoleDigitalAdapter = new ConsoleDigitalAdapter(); // Create an instance of MqttPhysicalAdapterConfiguration MqttPhysicalAdapterConfiguration config = MqttPhysicalAdapterConfiguration.builder(\u0026#34;127.0.0.1\u0026#34;, 1883) .addPhysicalAssetPropertyAndTopic(\u0026#34;intensity\u0026#34;, 0, \u0026#34;sensor/intensity\u0026#34;, Integer::parseInt) .addIncomingTopic(new DigitalTwinIncomingTopic(\u0026#34;sensor/state\u0026#34;, getSensorStateFunction()), createIncomingTopicRelatedPropertyList(), new ArrayList\u0026lt;\u0026gt;()) .addPhysicalAssetEventAndTopic(\u0026#34;overheating\u0026#34;, \u0026#34;text/plain\u0026#34;, \u0026#34;sensor/overheating\u0026#34;, Function.identity()) .addPhysicalAssetActionAndTopic(\u0026#34;switch-off\u0026#34;, \u0026#34;sensor.actuation\u0026#34;, \u0026#34;text/plain\u0026#34;, \u0026#34;sensor/actions/switch\u0026#34;, actionBody -\u0026gt; \u0026#34;switch\u0026#34; + actionBody) .build(); // Create an instance of the MQTT Physical Adapter using the defined configuration MqttPhysicalAdapter mqttPhysicalAdapter = new MqttPhysicalAdapter(\u0026#34;test-mqtt-pa\u0026#34;, config); // Add both Digital and Physical Adapters to the Digital Twin digitalTwin.addDigitalAdapter(consoleDigitalAdapter); digitalTwin.addPhysicalAdapter(mqttPhysicalAdapter); // Create the Digital Twin Engine DigitalTwinEngine digitalTwinEngine = new DigitalTwinEngine(); // Add the Digital Twin to the Engine digitalTwinEngine.addDigitalTwin(digitalTwin); // Start all the Digital Twins registered on the engine digitalTwinEngine.startAll(); In this example the createIncomingTopicRelatedPropertyList() used to map properties and events associated to a single topic is the following:\nprivate static List\u0026lt;PhysicalAssetProperty\u0026lt;?\u0026gt;\u0026gt; createIncomingTopicRelatedPropertyList(){ List\u0026lt;PhysicalAssetProperty\u0026lt;?\u0026gt;\u0026gt; properties = new ArrayList\u0026lt;\u0026gt;(); properties.add(new PhysicalAssetProperty\u0026lt;\u0026gt;(\u0026#34;temperature\u0026#34;, 0)); properties.add(new PhysicalAssetProperty\u0026lt;\u0026gt;(\u0026#34;humidity\u0026#34;, 0)); return properties; } This information are used by the adapter to build the PAD describe the capabilities and the characteristics of our object allowing the Shadowing Function to decide how to digitalize its physical counterpart.\n","date":"February 9, 2024","id":11,"permalink":"/docs/adapters/mqtt-physical-adapter/","summary":"The MqttPhysicalAdapter library provides a streamlined solution for efficiently managing physical assets through the MQTT protocol. It offers a range of features, including a versatile builder for effortless configuration of MQTT connections, dedicated classes for handling both incoming and outgoing topics, and a specialized adapter designed for seamless integration with diverse physical assets.","tags":"","title":"MQTT Physical Adapter"},{"content":"","date":"February 9, 2024","id":12,"permalink":"/docs/change-logs/","summary":"","tags":"","title":"Change Logs"},{"content":"The MqttDigitalAdapter,\nMqttDigitalAdapterConfiguration, and MqttDigitalAdapterConfigurationBuilder classes and guides you through using these classes to set up an MQTT Digital Adapter within WLDT.\nRequires an external MQTT broker to send messages.\nMain functionalities are:\nManages the interaction between the Digital Twin and external systems. Handles state updates, events, and property changes. Dynamic configuration of the MqttDigitalAdapter with broker details, topics, and other settings. Allows customization of data and payload management associated to MQTT topics for properties, events, and actions. Prerequisites:\nExternal MQTT Broker: The MqttDigitalAdapter library requires an external MQTT broker for optimal functionality and communication. Users must have access to a reliable MQTT broker to which the adapter can subscribe and publish. This external broker serves as the central communication hub, facilitating the exchange of messages between the adapter and digital applications A complete example is provided in the test folder with a complete DT Creation in the TestMain class together with MQTT IoT demo device and a test MQTT consumer.\nWLDT-Core Version Compatibility The correct mapping and compatibility between versions is reported in the following table\nmqtt-digital-adapter wldt-core 0.2.1 wldt-core 0.3.0 0.1.0 ✅ ❌ 0.1.1 ❌ ✅ Installation To use MqttDigitalAdapter in your Java project, you can include it as a dependency using Maven or Gradle.\nMaven \u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;io.github.wldt\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;mqtt-digital-adapter\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;0.1.1\u0026lt;/version\u0026gt; \u0026lt;/dependency\u0026gt; Gradle implementation \u0026#39;io.github.wldt:mqtt-digital-adapter:0.1.1\u0026#39; Class Structure \u0026amp; Functionalities MqttDigitalAdapterConfiguration MqttDigitalAdapterConfiguration is a crucial class in the Digital Twin library, allowing developers to configure the behavior of the MQTT Digital Adapter. It provides a flexible and customizable way to set up MQTT communication parameters, topics for properties, events, and actions.\nKey functionalities and exposed capabilities:\nBroker Configuration brokerAddress and brokerPort: Set the MQTT broker\u0026rsquo;s address and port. username and password: Set optional credentials for connecting to the broker. Client Configuration clientId: Unique identifier for the MQTT client. cleanSessionFlag: Flag indicating whether the client starts with a clean session. connectionTimeout: Maximum time to wait for the connection to the MQTT broker. MQTT Client Persistence persistence: Configurable persistence for the MQTT client\u0026rsquo;s data. Reconnect Configuration: automaticReconnectFlag: Flag enabling or disabling automatic reconnection. Topic Configuration: propertyUpdateTopics: Map of property update topics. eventNotificationTopics: Map of event notification topics. actionIncomingTopics: Map of incoming action topics. Builder Methods: builder: Static method to start building a new configuration. addPropertyTopic: Add a property topic with specified parameters. addEventNotificationTopic: Add an event notification topic. addActionTopic: Add an action topic. setConnectionTimeout: Set the connection timeout. setCleanSessionFlag: Set the clean session flag. setAutomaticReconnectFlag: Set the automatic reconnect flag. setMqttClientPersistence: Set the MQTT client persistence. build: Finalize the configuration and build the instance. MqttDigitalAdapterConfigurationBuilder The MqttDigitalAdapterConfigurationBuilder is a powerful tool designed to simplify the process of constructing configurations for the MQTT Digital Adapter in the Digital Twin library. It offers a fluent and intuitive interface, allowing developers to define various aspects of MQTT communication seamlessly.\nBuilder Instantiation The builder is instantiated by providing essential parameters like brokerAddress and brokerPort or including an optional clientId\nMqttDigitalAdapterConfigurationBuilder builder = MqttDigitalAdapterConfiguration.builder(\u0026#34;127.0.0.1\u0026#34;, 1883); Adding Property Topics Developers can add property topics with specific configurations, such as the key, topic, QoS level, and a function to convert property values to payload.\nbuilder.addPropertyTopic(\u0026#34;energy\u0026#34;, \u0026#34;dummy/properties/energy\u0026#34;, MqttQosLevel.MQTT_QOS_0, value -\u0026gt; String.valueOf(((Double)value).intValue())); Adding Event Notification Topics Event notification topics are easily added, including event keys, topics, QoS levels, and payload conversion functions.\nbuilder.addEventNotificationTopic(\u0026#34;overheating\u0026#34;, \u0026#34;dummy/events/overheating/notifications\u0026#34;, MqttQosLevel.MQTT_QOS_0, Object::toString); Adding Action Topics Developers can include action topics with key, topic, and a function to convert the payload to the desired action.\nbuilder.addActionTopic(\u0026#34;switch_off\u0026#34;, \u0026#34;app/actions/switch-off\u0026#34;, msg -\u0026gt; \u0026#34;OFF\u0026#34;); Connection Options Developers can set the connection timeout for the MQTT client.\nbuilder.setConnectionTimeout(30); The clean session flag can be configured based on the desired behavior.\nbuilder.setCleanSessionFlag(true); Developers can specify whether the MQTT client should automatically reconnect in case of a connection failure.\nbuilder.setAutomaticReconnectFlag(true); The builder allows setting a custom MQTT client persistence, such as an in-memory persistence or a file-based one.\nbuilder.setMqttClientPersistence(new MemoryPersistence()); Building Configuration The final configuration is built using the build method.\nMqttDigitalAdapterConfiguration configuration = builder.build(); MqttDigitalAdapter MqttDigitalAdapter extends DigitalAdapter and specializes in MQTT communication for Digital Twin instances. It handles the publication of state updates, events, and property changes over MQTT. This class facilitates seamless integration with MQTT-enabled systems.\nIt uses the information defined and provided in the `` to handle the communication both with the DT Core and external application interested to interact with the DT through the MQTT protocol.\nHere\u0026rsquo;s a basic example illustrating how to use MqttDigitalAdapter:\n// Create a Digital Twin instance DigitalTwin digitalTwin = new DigitalTwin(\u0026#34;my-digital-twin\u0026#34;, new DefaultShadowingFunction()); // Add a Physical Adapter to the DT [...] // Build the MQTT Digital Adapter Configuration MqttDigitalAdapterConfiguration configuration = MqttDigitalAdapterConfiguration.builder(\u0026#34;127.0.0.1\u0026#34;, 1883) .addPropertyTopic(\u0026#34;energy\u0026#34;, \u0026#34;dummy/properties/energy\u0026#34;, MqttQosLevel.MQTT_QOS_0, value -\u0026gt; String.valueOf(((Double)value).intValue())) .addActionTopic(\u0026#34;switch_off\u0026#34;, \u0026#34;app/actions/switch-off\u0026#34;, msg -\u0026gt; \u0026#34;OFF\u0026#34;) .build(); // Add the MQTT Digital Adapter to the Digital Twin digitalTwin.addDigitalAdapter(new MqttDigitalAdapter(\u0026#34;mqtt-da\u0026#34;, configuration)); // Create the Digital Twin Engine and start the simulation DigitalTwinEngine digitalTwinEngine = new DigitalTwinEngine(); digitalTwinEngine.addDigitalTwin(digitalTwin); digitalTwinEngine.startAll(); ","date":"February 9, 2024","id":13,"permalink":"/docs/adapters/mqtt-digital-adapter/","summary":"The MqttDigitalAdapter,\nMqttDigitalAdapterConfiguration, and MqttDigitalAdapterConfigurationBuilder classes and guides you through using these classes to set up an MQTT Digital Adapter within WLDT.","tags":"","title":"MQTT Digital Adapter"},{"content":"Digital Adapters The following methods have been discontinued and removed from the DigitalAdapter class: onStateChangePropertyCreated onStateChangePropertyUpdated onStateChangePropertyDeleted onStatePropertyUpdated onStatePropertyDeleted onStateChangeActionEnabled onStateChangeActionUpdated onStateChangeActionDisabled onStateChangeEventRegistered onStateChangeEventRegistrationUpdated onStateChangeEventUnregistered onStateChangeRelationshipInstanceDeleted onStateChangeRelationshipDeleted onStateChangeRelationshipInstanceCreated onStateChangeRelationshipCreated onDigitalTwinStateEventNotificationReceived The Signature of the following methods have been changed: onDigitalTwinSync(IDigitalTwinState currentDigitalTwinState) -\u0026gt; onDigitalTwinSync(DigitalTwinState currentDigitalTwinState) onDigitalTwinUnSync(IDigitalTwinState currentDigitalTwinState) -\u0026gt; onDigitalTwinUnSync(DigitalTwinState currentDigitalTwinState) New methods that have been added are: onStateUpdate(DigitalTwinState newDigitalTwinState, DigitalTwinState previousDigitalTwinState, ArrayList\u0026lt;DigitalTwinStateChange\u0026gt; digitalTwinStateChangeList) onEventNotificationReceived(DigitalTwinStateEventNotification\u0026lt;?\u0026gt; digitalTwinStateEventNotification) For additional details about Digital Adapters check Sub Section [[Change Log - v.0.3.0#Digital Adapter| Digital Adapters]] Shadowing Function ShadowingModelFunction is now ShadowingFunction this.digitalTwinState is not directly accessible anymore and it is wrapped through the DigitalTwinStateManager using the variable digitalTwinStateManager (see next descriptions and changes) The method addRelationshipInstance now take only one parameter that is the DigitalTwinStateRelationshipInstance The same change for example should be applied in the point of the code where the Shadowing Function receive a variation from the Physical world through a target adapter and the callback method onPhysicalAssetPropertyVariation(...) When the Shadowing Function has to compute the new DT State it can now work with the following method to handle DT State Transition: this.digitalTwinStateManager.startStateTransaction() DT State variation methods such as: digitalTwinStateManager.createProperty() digitalTwinStateManager.updateProperty() digitalTwinStateManager.updatePropertyValue() digitalTwinStateManager.deleteProperty() digitalTwinStateManager.enableAction() digitalTwinStateManager.updateAction() digitalTwinStateManager.disableAction() digitalTwinStateManager.registerEvent() digitalTwinStateManager.updateRegisteredEvent() digitalTwinStateManager.unRegisterEvent() digitalTwinStateManager.createRelationship() digitalTwinStateManager.addRelationshipInstance() digitalTwinStateManager.deleteRelationship() digitalTwinStateManager.deleteRelationshipInstance() At the end the transaction can be committed using the method: digitalTwinStateManager.commitStateTransaction() The method notifyDigitalTwinStateEvent is now available through the digitalTwinStateManager Additional Details associated to Shadowing Function Migration can be found in the dedicated section [[Change Log - v.0.3.0#Shadowing Function Changes | Shadowing Function Changes]] WLDT Engine \u0026amp; DT Creation WldtEngine is now DigitalTwin and model and structure a single Digital Twin and takes the following parameters: String digitalTwinId ShadowingFunction shadowingFunction The startLifeCycle has been removed from the DigitalTwin (previously WLDT Engine) and now DigitalTwinEngine should be used to start twins Once a new Digital Twin has been create it has to be added to the DigitalTwinEngine DigitalTwinEngine has dedicated method to start and stop twins such as: startAll() startDigitalTwin(\u0026lt;DIGITAL_TWIN_ID\u0026gt;); stopAll() digitalTwinEngine.stopDigitalTwin(\u0026lt;DIGITAL_TWIN_ID\u0026gt;); Digital Twin \u0026amp; Digital Twin Engine With the following code we now create a new Digital Twin Instance\n// Create the new Digital Twin with its Shadowing Function DigitalTwin digitalTwin = new DigitalTwin(digitalTwinId, new DemoShadowingFunction()); // Physical Adapter with Configuration digitalTwin.addPhysicalAdapter( new DemoPhysicalAdapter( String.format(\u0026#34;%s-%s\u0026#34;, digitalTwinId, \u0026#34;test-physical-adapter\u0026#34;), new DemoPhysicalAdapterConfiguration(), true)); // Digital Adapter with Configuration digitalTwin.addDigitalAdapter( new DemoDigitalAdapter( String.format(\u0026#34;%s-%s\u0026#34;, digitalTwinId, \u0026#34;test-digital-adapter\u0026#34;), new DemoDigitalAdapterConfiguration()) ); In the new version the DT cannot be directly run but it should be added to the DigitalTwinEngine in order to be executed through the WLDT Library\n// Create the Digital Twin Engine DigitalTwinEngine digitalTwinEngine = new DigitalTwinEngine(); // Add the Digital Twin to the Engine digitalTwinEngine.addDigitalTwin(digitalTwin); In order to start a DT from the Engine you can:\n// Directly start when you add it passing a second boolean value = true digitalTwinEngine.addDigitalTwin(digitalTwin. true); // Starting the single DT on the engine through its id digitalTwinEngine.startDigitalTwin(DIGITAL_TWIN_ID); // Start all the DTs registered on the engine digitalTwinEngine.startAll(); To stop a single twin or all the twin registered on the engine:\n// Stop a single DT on the engine through its id digitalTwinEngine.stopDigitalTwin(DIGITAL_TWIN_ID); // Stop all the DTs registered on the engine digitalTwinEngine.stopAll(); It is also possible to remove a DT from the Engine with a consequent stop if it is active and the deletion of its reference from the engine:\n// Remove a single DT on the engine through its id digitalTwinEngine.removeDigitalTwin(DIGITAL_TWIN_ID); // Remove all the DTs registered on the engine digitalTwinEngine.removeAll(); Digital Twin State DT State now has the reference timestamp representing the evaluation instant of the digital twin state, this timestamp is computed through the DigitalTwinStateManager and cannot manually set by the developer The information available on the DT State are: properties: List of Properties with their values (if available) actions: List of Actions that can be called on the DT events: List of Events that can be generated by the DT relationships: List of Relationships and their instances (if available) evaluationInstant: The timestamp representing the evaluation instant of the DT state Available main methods on that class instance are: Properties:\n- getProperty(String propertyKey): Retrieves if present the target DigitalTwinStateProperty by Key\n- containsProperty(String propertyKey): Checks if a target Property Key is already available in the current Digital Twin\u0026rsquo;s State\n- getPropertyList(): Loads the list of available Properties (described by the class DigitalTwinStateProperty) available on the Digital Twin\u0026rsquo;s State\n- createProperty(DigitalTwinStateProperty\u0026lt;?\u0026gt; dtStateProperty): Allows the creation of a new Property on the Digital Twin\u0026rsquo;s State through the class DigitalTwinStateProperty\n- readProperty(String propertyKey): Retrieves if present the target DigitalTwinStateProperty by Key\n- updateProperty(DigitalTwinStateProperty\u0026lt;?\u0026gt; dtStateProperty): Updates the target property using the DigitalTwinStateProperty and the associated Property Key field\n- deleteProperty(String propertyKey): Deletes the target property identified by the specified key Actions:\n- containsAction(String actionKey): Checks if a Digital Twin State Action with the specified key is correctly registered\n- getAction(String actionKey): Loads the target DigitalTwinStateAction by key\n- getActionList(): Gets the list of available Actions registered on the Digital Twin\u0026rsquo;s State\n- enableAction(DigitalTwinStateAction digitalTwinStateAction): Enables and registers the target Action described through an instance of the DigitalTwinStateAction class\n- updateAction(DigitalTwinStateAction digitalTwinStateAction): Update the already registered target Action described through an instance of the DigitalTwinStateAction class\n- disableAction(String actionKey): Disables and unregisters the target Action described through an instance of the DigitalTwinStateAction class Events:\n- containsEvent(String eventKey): Check if a Digital Twin State Event with the specified key is correctly registered\n- getEvent(String eventKey): Return the description of a registered Digital Twin State Event according to its Key\n- getEventList(): Return the list of existing and registered Digital Twin State Events\n- registerEvent(DigitalTwinStateEvent digitalTwinStateEvent): Register a new Digital Twin State Event\n- updateRegisteredEvent(DigitalTwinStateEvent digitalTwinStateEvent): Update the registration and signature of an existing Digital Twin State Event\n- unRegisterEvent(String eventKey): Un-register a Digital Twin State Event\n- notifyDigitalTwinStateEvent(DigitalTwinStateEventNotification\u0026lt;?\u0026gt; digitalTwinStateEventNotification): Method to notify the occurrence of the target Digital Twin State Event Relationships:\n- containsRelationship(String relationshipName): Checks if a Relationship Name is already available in the current Digital Twin\u0026rsquo;s State\n- createRelationship(DigitalTwinStateRelationship\u0026lt;?\u0026gt; relationship): Creates a new Relationships (described by the class DigitalTwinStateRelationship) in the Digital Twin\u0026rsquo;s State\n- addRelationshipInstance(String name, DigitalTwinStateRelationshipInstance\u0026lt;?\u0026gt; instance): Adds a new Relationship instance described through the class DigitalTwinStateRelationshipInstance and identified through its name\n- getRelationshipList(): Loads the list of existing relationships on the Digital Twin\u0026rsquo;s State through a list of DigitalTwinStateRelationship\n- getRelationship(String name): Gets a target Relationship identified through its name and described through the class DigitalTwinStateRelationship\n- deleteRelationship(String name): Deletes a target Relationship identified through its name\n- deleteRelationshipInstance(String relationshipName, String instanceKey): Deletes the target Relationship Instance using relationship name and instance Key Digital Twin State Manager The DigitalTwinStateManager is a Java class that serves as the default implementation of the IDigitalTwinStateManager interface within the White Label Digital Twin Java Framework (whitelabel-digitaltwin). This class allows developers to manage the state of a digital twin, including properties, actions, events, and relationships.\nFeatures State Management: Handles the creation, update, and deletion of properties, actions, events, and relationships associated with the digital twin state. Transaction Support: Allows developers to start, commit, or rollback transactions to manage changes to the digital twin state. Event Notification: Notifies listeners about updates to the digital twin state through the WLDT event bus. When the Shadowing Function has to compute the new DT State it can now work with the following method to handle DT State Transition: - Start the DT State Transaction: startStateTransaction() - DT State variation methods such as: - createProperty() - updateProperty()\n- updatePropertyValue() - deleteProperty() - enableAction() - updateAction() - disableAction() - registerEvent() - updateRegisteredEvent() - unRegisterEvent() - createRelationship() - addRelationshipInstance() - deleteRelationship() - deleteRelationshipInstance()\nAt the end the transaction can be committed using the method: commitStateTransaction()\nUsage To use the DigitalTwinStateManager within your digital twin implementation:\nInitialization: Create an instance of the DigitalTwinStateManager. DigitalTwinStateManager digitalTwinStateManager = new DigitalTwinStateManager(); State Transaction:\nStart a new transaction using startStateTransaction() to manage changes. Make changes to the digital twin state. Commit the transaction using commitStateTransaction() to apply the changes. digitalTwinStateManager.startStateTransaction(); // Make changes to properties, actions, events, or relationships // [...] digitalTwinStateManager.commitStateTransaction(); Event Notification:\nDT State Updates after a commit action are automatically notified to Digital Adapter by the Manager Once an event incoming from the physical or generated by the DT itself is handled by the Shadowing Function, the developer can use notifyDigitalTwinStateUpdate to notify Digital Adapter listening about events variations. // Notify a specific event notification digitalTwinStateManager.notifyDigitalTwinStateEvent(digitalTwinStateEventNotification); Property, Action, Event, Relationship Management:\nCreate, update, or delete properties, actions, events, or relationships as needed. // Begin Digital Twin State Transaction digitalTwinStateManager.startStateTransaction(); // Create a new property digitalTwinStateManager.createProperty(dtStateProperty); // Update an existing property digitalTwinStateManager.updateProperty(dtStateProperty); // Delete a property digitalTwinStateManager.deleteProperty(propertyKey);` // Commit DT State Update to apply all the changes and notify the Digital Adapters and other listeners about the variation digitalTwinStateManager.commitStateTransaction(); Exception Handling The class throws WldtDigitalTwinStateException to indicate errors related to digital twin state management. Proper exception handling is advised to manage potential errors during state transactions. Shadowing Function Changes Now that the DT State is managed through the DigitalTwinStateManager class all the changes and variation should be applied on the DT ShadowingFunction using the previously presented transaction management and the correct call of methods startStateTransaction() and commitStateTransaction().\nHere there is an example of the change with a simple and demo shadowing function on callback onDigitalTwinBound:\n@Override protected void onDigitalTwinBound(Map\u0026lt;String, PhysicalAssetDescription\u0026gt; adaptersPhysicalAssetDescriptionMap) { try{ // NEW -\u0026gt; Start DT State Change Transaction this.digitalTwinStateManager.startStateTransaction(); for(Map.Entry\u0026lt;String, PhysicalAssetDescription\u0026gt; entry : adaptersPhysicalAssetDescriptionMap.entrySet()){ String adapterId = entry.getKey(); PhysicalAssetDescription physicalAssetDescription = entry.getValue(); //In that simple case the Digital Twin shadow all the properties and actions available in the physical asset for(PhysicalAssetProperty\u0026lt;?\u0026gt; p : physicalAssetDescription.getProperties()) this.digitalTwinStateManager.createProperty(new DigitalTwinStateProperty\u0026lt;\u0026gt;(p.getKey(), p.getInitialValue())); for(PhysicalAssetAction a : physicalAssetDescription.getActions()) this.digitalTwinStateManager.enableAction(new DigitalTwinStateAction(a.getKey(), a.getType(), a.getContentType())); for(PhysicalAssetEvent e: physicalAssetDescription.getEvents()) this.digitalTwinStateManager.registerEvent(new DigitalTwinStateEvent(e.getKey(), physicalAssetEvent.getType())); } // NEW -\u0026gt; Commit DT State Change Transaction to apply the changes on the DT State and notify about the change this.digitalTwinStateManager.commitStateTransaction(); //Observer Target Physical Properties for(Map.Entry\u0026lt;String, PhysicalAssetDescription\u0026gt; entry : adaptersPhysicalAssetDescriptionMap.entrySet()){ [...] } //Observe all the target available Physical Asset Events for each Adapter for(Map.Entry\u0026lt;String, PhysicalAssetDescription\u0026gt; entry : adaptersPhysicalAssetDescriptionMap.entrySet()){ [...] } // Observer for Incoming Digital Actions observeDigitalActionEvents(); //Notify Shadowing Completed notifyShadowingSync(); }catch (Exception e){ e.printStackTrace(); } } The same change for example should be applied in the point of the code where the Shadowing Function receive a variation from the Physical world through a target adapter and the callback method onPhysicalAssetPropertyVariation(...)\n@Override protected void onPhysicalAssetPropertyVariation(PhysicalAssetPropertyWldtEvent\u0026lt;?\u0026gt; physicalPropertyEventMessage) { try { if(physicalPropertyEventMessage != null \u0026amp;\u0026amp; getPhysicalEventsFilter().contains(physicalPropertyEventMessage.getType())){ if(physicalPropertyEventMessage.getPhysicalPropertyId().equals(TestPhysicalAdapter.SWITCH_PROPERTY_KEY) \u0026amp;\u0026amp; physicalPropertyEventMessage.getBody() instanceof String){ [...] } else{ //Update Digital Twin State //NEW -\u0026gt; Start State Transaction this.digitalTwinStateManager.startStateTransaction(); // Update State Property Value this.digitalTwinStateManager.updateProperty( new DigitalTwinStateProperty\u0026lt;\u0026gt;( physicalPropertyEventMessage.getPhysicalPropertyId(), physicalPropertyEventMessage.getBody())); //NEW -\u0026gt; Commit State Transaction this.digitalTwinStateManager.commitStateTransaction(); } } else logger.error(\u0026#34;WRONG Physical Event Message Received !\u0026#34;); }catch (Exception e){ e.printStackTrace(); } } Digital Adapter The Digital Adapter base class has been significantly extended and improved with respect to the previous version. In this new Version notifications that are received by the Adapter from the the DT core belongs to the following categories:\nDigital Twin State Update through the method onStateUpdate(...) providing information about the new state of the Digital Twin, the previous state, and a list of changes that occurred between these two states. In the previous version each variation of a property, relationships, actions or events were notified. In the new version only a committed DT\u0026rsquo;State variation is notified to listeners. Event Notifications through the method onEventNotificationReceived(...) whenever there is a notification about an event related to the Digital Twin\u0026rsquo;s state coming from the physical world, generated by the twin and processed by the Shadowing Function. For example in the DT State we can have the declaration of the over-heating-alert structured and received in the DT State while the effective occurrence of the event and the associated notification is notified through this dedicated callback The onStateUpdate method is an abstract method that must be implemented by any class extending the DigitalAdapter class. This method is called whenever there is an update to the Digital Twin\u0026rsquo;s state. It provides information about the new state of the Digital Twin, the previous state, and a list of changes that occurred between these two states.\nHere is an explanation of the parameters:\nnewDigitalTwinState: This parameter represents the updated state of the Digital Twin. It is an instance of the DigitalTwinState class, which encapsulates the current state information.\npreviousDigitalTwinState: This parameter represents the state of the Digital Twin before the update. It is also an instance of the DigitalTwinState class.\ndigitalTwinStateChangeList: This parameter is an ArrayList containing DigitalTwinStateChange objects. Each DigitalTwinStateChange object encapsulates information about a specific change that occurred between the previous and new states. It includes details such as the property or aspect of the state that changed, the previous value, and the new value.\nThe DT State is automatically monitored by each Digital Adapter while for the Events potentially generated by the DT can be observed by each adapter using:\nobserveAllDigitalTwinEventsNotifications: Enable the observation of available Digital Twin State Events Notifications. unObserveAllDigitalTwinEventsNotifications: Cancel the observation of Digital Twin State Events Notifications observeDigitalTwinEventsNotifications: Enable the observation of the notification associated to a specific list of Digital Twin State events. With respect to event a notification contains the new associated value unObserveDigitalTwinEventsNotifications: Cancel the observation of a target list of properties observeDigitalTwinEventNotification: Enable the observation of the notification associated to a single Digital Twin State event. With respect to event a notification contains the new associated value unObserveDigitalTwinEventNotification: Cancel the observation of a single target event DigitalTwinStateChange Class DigitalTwinStateChange Class\nThe DigitalTwinStateChange class is a representation of a change that occurred in the state of a Digital Twin. It encapsulates information about the type of operation, the resource type, and the affected resource within the Digital Twin.\nEnums:\nOperation: Enumerates different types of operations that can be performed on a Digital Twin state. The possible operations are: OPERATION_UPDATE: Represents an update operation on a resource. OPERATION_UPDATE_VALUE: Represents an update operation specifically on the value of a resource. OPERATION_ADD: Represents an addition operation of a new resource. OPERATION_REMOVE: Represents a removal operation of an existing resource. ResourceType: Enumerates different types of resources within a Digital Twin. The possible resource types are: PROPERTY: Represents a property of the Digital Twin. PROPERTY_VALUE: Represents the value of a property within the Digital Twin. EVENT: Represents an event associated with the Digital Twin. ACTION: Represents an action that can be performed on the Digital Twin. RELATIONSHIP: Represents a relationship between different components of the Digital Twin. RELATIONSHIP_INSTANCE: Represents an instance of a relationship. Fields:\noperation: Indicates the type of operation performed on the Digital Twin state (e.g., update, add, remove). resourceType: Represents the type of resource affected by the change (e.g., property, event, relationship). resource: The specific resource that has undergone the change, represented by an instance of the DigitalTwinStateResource class. Available type of DigitalTwinStateResource are:\nDigitalTwinStateProperty\u0026lt;T\u0026gt;: This class define a generic property associated to the Digital Twin State. Each property is associated to a Key and a Value. Furthermore, it can also be associated to a type to identify its nature and data structure. By default, it is associated to the type of the Class (e.g., java.lang.String) but it can be directly changed by the developer to associate it to a specific ontology or data type. DigitalTwinStateEvent: This class define a generic event associated to the Digital Twin State. Events enable a mechanism for asynchronous messages to be sent by the digital twin (e.g., an overheating) . They are different from Properties that can change values according to the type of Digital Twin and may be associated also to telemetry patterns. Each event is associated to a Key and a Type used to identify its nature and data structure. By default, it is associated to the type of the Class (e.g., java.lang.String) but it can be directly changed by the developer to associate it to a specific ontology or data type. DigitalTwinStateAction: This class define a generic action associated to the Digital Twin State. Each action is by a key, an action type and a content type used to identify the expected input required by the action. The type of the can be directly changed by the developer to associate it to a specific ontology or data type. DigitalTwinStateRelationship\u0026lt;T\u0026gt;: Structures and describes a Relationship in the Digital Twins\u0026rsquo;s State. This is just the description of the relationships while the effective values/instances are described through the other class DigitalTwinStateRelationshipInstance DigitalTwinStateRelationshipInstance\u0026lt;T\u0026gt;: Structures and describes a Relationship Instance in the Digital Twins\u0026rsquo;s State. This is effective description of a relationship while its generic declaration is described through the class DigitalTwinStateRelationship. When there is a change in the DT State it is possibile to cast the received resource variation to the correct one. For example in the following code we detect and manage the variation on a Property Value:\n// Get information from the state change DigitalTwinStateChange.Operation operation = stateChange.getOperation(); DigitalTwinStateChange.ResourceType resourceType = stateChange.getResourceType(); DigitalTwinStateResource resource = stateChange.getResource(); // Search for property value variation if(resourceType.equals(DigitalTwinStateChange.ResourceType.PROPERTY_VALUE) \u0026amp;\u0026amp; operation.equals(DigitalTwinStateChange.Operation.OPERATION_UPDATE) \u0026amp;\u0026amp; resource instanceof DigitalTwinStateProperty){ DigitalTwinStateProperty\u0026lt;?\u0026gt; digitalTwinStateProperty = (DigitalTwinStateProperty\u0026lt;?\u0026gt;) resource; if(getConfiguration().getPropertyUpdateTopics().containsKey(digitalTwinStateProperty.getKey())){ //Handle property value variation } } Constructors:\nDigitalTwinStateChange(): An empty constructor that allows creating an instance of the class. DigitalTwinStateChange(Operation operation, ResourceType resourceType, DigitalTwinStateResource resource): Constructs a DigitalTwinStateChange object with specified operation, resource type, and resource. Throws a WldtDigitalTwinStateException if any of the parameters is missing or null. Methods:\nAccessor methods (getOperation(), getResourceType(), getResource()) to retrieve the values of the fields. Mutator methods (setOperation(), setResourceType(), setResource()) to update the values of the fields. Usage Examples Developers extending the DigitalAdapter class should implement the onStateUpdate method to define custom logic that needs to be executed whenever the state of the Digital Twin is updated. This could include tasks such as processing state changes, updating internal variables, triggering specific actions, or notifying other components about the state update.\nHere\u0026rsquo;s an example of how the method might be implemented in a concrete subclass of DigitalAdapter:\n@Override protected void onStateUpdate(DigitalTwinState newDigitalTwinState, DigitalTwinState previousDigitalTwinState, ArrayList\u0026lt;DigitalTwinStateChange\u0026gt; digitalTwinStateChangeList) { // In newDigitalTwinState we have the new DT State System.out.println(\u0026#34;New DT State is: \u0026#34; + newDigitalTwinState); // The previous DT State is available through the variable previousDigitalTwinState System.out.println(\u0026#34;Previous DT State is: \u0026#34; + previousDigitalTwinState); // We can also check each DT\u0026#39;s state change potentially differentiating the behaviour for each change if (digitalTwinStateChangeList != null \u0026amp;\u0026amp; !digitalTwinStateChangeList.isEmpty()) { // Iterate through each state change in the list for (DigitalTwinStateChange stateChange : digitalTwinStateChangeList) { // Get information from the state change DigitalTwinStateChange.Operation operation = stateChange.getOperation(); DigitalTwinStateChange.ResourceType resourceType = stateChange.getResourceType(); DigitalTwinStateResource resource = stateChange.getResource(); // Perform different actions based on the type of operation switch (operation) { case OPERATION_UPDATE: // Handle an update operation System.out.println(\u0026#34;Update operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; case OPERATION_UPDATE_VALUE: // Handle an update value operation System.out.println(\u0026#34;Update value operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; case OPERATION_ADD: // Handle an add operation System.out.println(\u0026#34;Add operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; case OPERATION_REMOVE: // Handle a remove operation System.out.println(\u0026#34;Remove operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; default: // Handle unknown operation (optional) System.out.println(\u0026#34;Unknown operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; } } } else { // No state changes System.out.println(\u0026#34;No state changes detected.\u0026#34;); } } In this example, the method iterates over the list of state changes, extracts information about each change, and performs custom actions based on the changes. Developers can adapt this method to suit the specific requirements of their Digital Twin application.\n","date":"February 9, 2024","id":14,"permalink":"/docs/change-logs/change-log-0.3.0/","summary":"Digital Adapters The following methods have been discontinued and removed from the DigitalAdapter class: onStateChangePropertyCreated onStateChangePropertyUpdated onStateChangePropertyDeleted onStatePropertyUpdated onStatePropertyDeleted onStateChangeActionEnabled onStateChangeActionUpdated onStateChangeActionDisabled onStateChangeEventRegistered onStateChangeEventRegistrationUpdated onStateChangeEventUnregistered onStateChangeRelationshipInstanceDeleted onStateChangeRelationshipDeleted onStateChangeRelationshipInstanceCreated onStateChangeRelationshipCreated onDigitalTwinStateEventNotificationReceived The Signature of the following methods have been changed: onDigitalTwinSync(IDigitalTwinState currentDigitalTwinState) -\u0026gt; onDigitalTwinSync(DigitalTwinState currentDigitalTwinState) onDigitalTwinUnSync(IDigitalTwinState currentDigitalTwinState) -\u0026gt; onDigitalTwinUnSync(DigitalTwinState currentDigitalTwinState) New methods that have been added are: onStateUpdate(DigitalTwinState newDigitalTwinState, DigitalTwinState previousDigitalTwinState, ArrayList\u0026lt;DigitalTwinStateChange\u0026gt; digitalTwinStateChangeList) onEventNotificationReceived(DigitalTwinStateEventNotification\u0026lt;?","tags":"","title":"Change Log 0.3.0"},{"content":"The HttpDigitalAdapter is a powerful component designed to facilitate the integration of Digital Twins into HTTP-based systems. It serves as a bridge between a Digital Twin and HTTP-based applications, allowing developers to easily expose and interact with Digital Twin data and functionalities over HTTP.\nKey Features:\nHTTP Integration: Seamlessly integrates Digital Twins into HTTP environments, enabling communication with web applications and services. Dynamic Configuration: Offers a flexible configuration mechanism through the HttpDigitalAdapterConfiguration, allowing developers to customize the adapter\u0026rsquo;s behavior based on specific requirements. State Monitoring: Monitors changes in the Digital Twin state and provides HTTP endpoints to query the state of the Digital Twin (properties, events, actions and relationships). Event Notifications: Allows developers to retrieve event notifications triggered by changes in the Digital Twin state. A complete example is provided in the test folder with a complete DT Creation in the TestMain class together with a demo DT with and emulated Physical Adapter and the HTTP Digital Adapter.\nWLDT-Core Version Compatibility The correct mapping and compatibility between versions is reported in the following table\nhttp-digital-adapter wldt-core 0.2.1 wldt-core 0.3.0 0.1.1 ❌ ✅ Installation To use HttpDigitalAdapter in your Java project, you can include it as a dependency using Maven or Gradle.\nMaven \u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;io.github.wldt\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;http-digital-adapter\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;0.1.1\u0026lt;/version\u0026gt; \u0026lt;/dependency\u0026gt; Gradle implementation \u0026#39;io.github.wldt:http-digital-adapter:0.1.1\u0026#39; Class Structure \u0026amp; Functionalities HttpDigitalAdapterConfiguration The HttpDigitalAdapterConfiguration is a crucial part of the HttpDigitalAdapter, providing the necessary settings to tailor the adapter\u0026rsquo;s behavior to meet specific needs.\nRepresents the configuration for an HTTP Digital Adapter, specifying the host, port, and filters for properties, actions, events, and relationships.\nThe filters are used to selectively include or exclude specific properties, actions, events, and relationships when interacting with the HTTP Digital Adapter. Filters are meant to be white list filters, if they are empty, it means that ALL fields are considered\nThis class provides methods to add filters for each type and getters to retrieve the configured values.\nKey functionalities and exposed capabilities:\nBasic Configuration Adapter ID: A unique identifier for the HttpDigitalAdapter instance. Host: The hostname or IP address on which the adapter will listen for incoming HTTP requests. Port: The port number on which the adapter will listen for incoming HTTP requests. Filters (Optional) addPropertyFilter(String propertyKey): Adds a single property key to the property filter. addPropertiesFilter(Collection\u0026lt;String\u0026gt; propertiesKey): Adds a collection of property keys to the property filter. addActionFilter(String actionKey): Adds a single action key to the action filter. addActionsFilter(Collection\u0026lt;String\u0026gt; actionsKey): Adds a collection of action keys to the action filter. addEventFilter(String eventKey): Adds a single event key to the event filter. addEventsFilter(Collection\u0026lt;String\u0026gt; eventsKey): Adds a collection of event keys to the event filter. addRelationshipFilter(String relationshipName): Adds a single relationship name to the relationship filter. addRelationshipsFilter(Collection\u0026lt;String\u0026gt; relationshipNames): Adds a collection of relationship names to the relationship filter. Configured Filter can be accessed using: getPropertyFilter() getActionFilter() getEventFilter() getRelationshipFilter() A basic example without any filter that accesses and uses the entire DT State is:\nHttpDigitalAdapterConfiguration config = new HttpDigitalAdapterConfiguration(\u0026#34;my-http-adapter\u0026#34;, \u0026#34;localhost\u0026#34;, 8080); An example of using filter to select specific field of interest can be structured ad follows:\nHttpDigitalAdapterConfiguration config = new HttpDigitalAdapterConfiguration(\u0026#34;my-http-adapter\u0026#34;, \u0026#34;localhost\u0026#34;, 8080); // Add property filter config.addPropertyFilter(\u0026#34;temperature\u0026#34;); config.addPropertiesFilter(Arrays.asList(\u0026#34;humidity\u0026#34;, \u0026#34;pressure\u0026#34;)); // Add action filter config.addActionFilter(\u0026#34;start\u0026#34;); config.addActionsFilter(Arrays.asList(\u0026#34;stop\u0026#34;, \u0026#34;reset\u0026#34;)); // Add event filter config.addEventFilter(\u0026#34;temperatureChange\u0026#34;); config.addEventsFilter(Collections.singletonList(\u0026#34;pressureChange\u0026#34;)); // Add relationship filter config.addRelationshipFilter(\u0026#34;connectedTo\u0026#34;); config.addRelationshipsFilter(Arrays.asList(\u0026#34;parentOf\u0026#34;, \u0026#34;siblingOf\u0026#34;)); // Retrieve and display filters List\u0026lt;String\u0026gt; propertyFilter = config.getPropertyFilter(); List\u0026lt;String\u0026gt; actionFilter = config.getActionFilter(); List\u0026lt;String\u0026gt; eventFilter = config.getEventFilter(); List\u0026lt;String\u0026gt; relationshipFilter = config.getRelationshipFilter(); System.out.println(\u0026#34;Property Filter: \u0026#34; + propertyFilter); System.out.println(\u0026#34;Action Filter: \u0026#34; + actionFilter); System.out.println(\u0026#34;Event Filter: \u0026#34; + eventFilter); System.out.println(\u0026#34;Relationship Filter: \u0026#34; + relationshipFilter); HttpDigitalAdapter The HttpDigitalAdapter itself is the core component responsible for handling HTTP requests and interacting with the underlying Digital Twin. It extends the capabilities of the base DigitalAdapter to specifically cater to HTTP-based scenarios.\nKey Functionalities:\nRESTful Endpoints: Provides RESTful endpoints for reading properties, invoking actions, querying events, and managing relationships. State Updates: Automatically reflects changes in the Digital Twin state to the HTTP endpoints, ensuring real-time information. Event Handling: Listens for Digital Twin events and provides events notifications to HTTP clients. Here\u0026rsquo;s a basic example illustrating how to use MqttDigitalAdapter:\nGetting Started: Create HttpDigitalAdapterConfiguration:\nHttpDigitalAdapterConfiguration config = new HttpDigitalAdapterConfiguration(\u0026#34;my-http-adapter\u0026#34;, \u0026#34;localhost\u0026#34;, 8080); Instantiate HttpDigitalAdapter:\nDigitalTwin digitalTwin = new DigitalTwin(\u0026#34;my-digital-twin\u0026#34;, new DefaultShadowingFunction()); HttpDigitalAdapter httpDigitalAdapter = new HttpDigitalAdapter(config, digitalTwin); // Add a Physical Adapter to the DT [...] Add HttpDigitalAdapter to DigitalTwin:\ndigitalTwin.addDigitalAdapter(httpDigitalAdapter); Start the Digital Twin Engine:\nDigitalTwinEngine digitalTwinEngine = new DigitalTwinEngine(); digitalTwinEngine.addDigitalTwin(digitalTwin); digitalTwinEngine.startAll(); HTTP RESTful API This section of the documentation provides detailed information about the RESTful API exposed by the WLDT - HTTP Digital Adapter. The API allows you to interact with the Digital Twin (DT) instance, retrieve its state, read properties, actions, event and relationships description, and trigger actions.\nAvailable endpoints with the associated methods are:\nGET /instance: Retrieves information about the Digital Twin instance. GET /state: Retrieves the current state of the Digital Twin. GET /state/changes: Retrieves the list of state changes in the Digital Twin. GET /state/previous: Retrieves the previous state of the Digital Twin. GET /state/properties: Retrieves the list of properties in the Digital Twin state. GET /properties/{propertyKey}: Retrieves the value of a specific property (e.g., /properties/color) from the Digital Twin state. GET /state/events: Retrieves the list of events in the Digital Twin state. GET /state/actions: Retrieves the list of actions in the Digital Twin state. POST /state/actions/{actionKey}: Triggers the specified action (e.g., /state/actions/switch_on) in the Digital Twin state. The raw body contains the action request payload. GET /state/relationships: Retrieves the list of relationships in the Digital Twin state. GET /state/relationships/{relationshipName}/instances: Retrieves the instances of the specified relationship (e.g., /state/relationships/insideIn/instances) in the Digital Twin state. Note: Replace {propertyKey}, {actionKey}, and {relationshipName} with the actual values you want to retrieve or trigger. Make sure to use the appropriate HTTP method (GET, POST) and include any required parameters or payload as described in each endpoint\u0026rsquo;s description. For more detailed information, refer to the Postman Collection for this API available in the folder api: http_adapter_api_postman.json\n","date":"February 9, 2024","id":15,"permalink":"/docs/adapters/http-digital-adapter/","summary":"The HttpDigitalAdapter is a powerful component designed to facilitate the integration of Digital Twins into HTTP-based systems. It serves as a bridge between a Digital Twin and HTTP-based applications, allowing developers to easily expose and interact with Digital Twin data and functionalities over HTTP.","tags":"","title":"HTTP Digital Adapter"},{"content":"The WLDT framework intends to maximize modularity, re-usability and flexibility in order to effectively mirror physical smart objects in their digital counterparts. The proposed library focuses on the simplification of twins design and development aiming to provide a set of core features and functionalities for the widespread adoption of Internet of Things DTs applications.\nA WLDT instance is a general purpose software entity implementing all the features and functionalities of a Digital Twin running in cloud or on the edge. It has the peculiar characteristic to be generic and ``attachable\u0026rsquo;\u0026rsquo; to any physical thing in order to impersonate and maintain its digital replica and extend the provided functionalities for example through the support of additional protocols or a specific translation or normalization for data and formats.\nHereafter, the requirements that led the design and development of the WLDT framework are:\ni) Simplicity - with WLDT developers must have the possibility to easily create a new instance by using existing modules or customizing the behavior according the need of their application scenario; ii) Extensibility - while WLDT must be as simple and light as possible, the API should be also easily extendible in order to let programmers to personalize the configuration and/or to add new features loading and executing multiple modules at the same times; iii) Portability \u0026amp; Micorservice Readiness - a digital twin implemented through WLDT must be able to run on any platform without changes and customization. Our goal is to have a simple and light core engine with a strategic set of IoT-oriented features allowing the developer to easily create DT applications modeled as independent software agents and packed as microservices. In the following Figure, the main components that make up the architecture of WLDT are represented, and thus through which the individual Digital Twin is implemented. Specifically, from the image it is possible to identify the three levels on which the architecture is developed: the one related to the core of the library, the one that models the DT, and finally, that of the adapters.\nEach of this core components has the following main characteristics:\nMetrics Manager: Provides the functionalities for managing and tracking various metrics within DT instances combining both internal and custom metrics through a flexible and extensible approach. Logger: Is designed to facilitate efficient and customizable logging within implemented and deployed DTs with configurable log levels and versatile output options. Utils \u0026amp; Commons: Hold a collection of utility classes and common functionalities that can be readily employed across DT implementations ranging from handling common data structures to providing helpful tools for string manipulation. Event Communication Bus: Represents the internal Event Bus, designed to support communication between the different components of the DT\u0026rsquo;s instance. It allows defining customized events to model both physical and digital input and outputs. Each WLDT\u0026rsquo;s component can publish on the shared Event Bus and define an Event Filter to specify which types of events it is interested in managing, associating a specific callback to each one to process the different messages. Digital Twin Engine: Defines the multi-thread engine of the library allowing the execution and monitoring of multiple DTs (and their core components) simultaneously. Therefore, it is also responsible for orchestrating the different internal modules of the architecture while keeping track of each one, and it can be considered the core of the platform itself allowing the execution and control of the deployed DTs. Currently, it supports the execution of twins on the same Java process, however the same engine abstraction might be used to extend the framework to support distributed execution for example through different processes or microservices. Digital Twin: Models a modular DT structure built through the combination of core functionalities together with physical and digital adapter capabilities. This Layer includes the Digital Twin State responsible to structure the state of the DT by defining the list of properties, events, and actions. The different instances included in the lists can correspond directly to elements of the physical asset or can derive from their combination, in any case, it is the Shadowing Function (SF) that defines the mapping, following the model defined by the designer. This component also exposes a set of methods to allow SF manipulation. Every time the Digital Twin State is modified, the latter generates the corresponding DT\u0026rsquo;s event to notify all the components about the variation. Shadowing Function: It is the library component responsible for defining the behavior of the Digital Twin by interacting with the Digital Twin State. Specifically, it implements the shadowing process that allows keeping the DT synchronized with its physical entity. This component is based on a specific implementation of a WLDT Worker called Model Engine, in order to be executed by the WLDT Engine. The Shadowing Model Function is the fundamental component that must be extended by the DT designer to concretize its model. The shadowing function observes the life cycle of the Digital Twin to be notified of the different state changes. For example, it is informed when the DT enters the Bound state, i.e. when its Physical Adapters have completed the binding procedure with the physical asset. This component also allows the designer to define the behavior of the DT in case a property is modified, an event is triggered, or an action is invoked. Physical Adapter: It defines the essential functionalities that the individual extensions, related to specific protocols, must implement. As provided by the DT definition, a DT can be equipped with multiple Physical Adapters in order to manage communication with the corresponding physical entity. Each will produce a Physical Asset Description (PAD), i.e., a description of the properties, events, actions, and relationships that the physical asset exposes through the specific protocol. The DT transitions from the Unbound to the Bound state when all its Physical Adapters have produced their respective PADs. The Shadowing Function, following the DT model, selects the components of the various PADs that it is interested in managing. Digital Adapter: It provides the set of callbacks that each specific implementation can use to be notified of changes in the DT state. Symmetrically to what happens with Physical Adapters, a Digital Twin can define multiple Digital Adapters to expose its state and functionality through different protocols. Therefore, to create a Digital Twin using WLDT, it is necessary to define and instantiate a DT with its Shadowing Function and at least one Physical Adapter and one Digital Adapter, in order to enable connection with the physical entity and allow the DT to be used by external applications. Once the 3 components are defined, it is possible to instantiate the WLDT Engine and, subsequently, start the lifecycle of the DT. In the following sections we will go through the fundamental steps to start working with the library and creating all the basic modules to design, develop and execute our first Java Digital Twin.\n","date":"February 9, 2024","id":16,"permalink":"/docs/introduction/library-structure-basic-concepts/","summary":"The WLDT framework intends to maximize modularity, re-usability and flexibility in order to effectively mirror physical smart objects in their digital counterparts.","tags":"","title":"Library Structure \u0026 Basic Concepts"},{"content":" With respect to the element present in the real world, it is defined as a Physical Asset (PA) with the intention of referring to any entity that has a manifestation or relevance in the physical world and a well-defined lifespan.\nThe previous Figure schematically illustrates the main component of an abstract Digital Twin and clarifies its responsibility to be a bridge between the cyber and the physical world. The blueprint components (then mapped into the WLDT Library) are:\nPhysical Interface The entity in charge of both the initial digitalization o shadowing process and the perpetual responsibility to keep the DT and PA in synch during its life cycle. It can execute multiple Physical Asset Adapters to interact with the PA and detect and digitalize the physical event coming from the physical entity according to its nature and the supported protocols and data formats (e.g., through HTTP and JSON). Digital Interface The component complementary to the Physical Interface and in charge of handling DT\u0026rsquo;s internal variations and events towards external digital entities and consumers. It executes multiple and reusable Digital Adapters in charge of handling digital interactions and events and responsible for making the DT interoperable with external applications. DT\u0026rsquo;s Model The module defining the DT\u0026rsquo;s behaviour and its augmented functionalities. It supports the execution of different configurable and reusable modules and functionalities handling both physical and digial events according to the implemented behaviour. Furthermore, the Model is the component responsible to handle and keep updated the Digital Twin State as described in the following sections. The Digital Twin Model(M) allows capturing and representing the PA at an appropriate level of abstraction, i.e., avoiding irrelevant aspects for its purpose and modeling only domain-level information rather than technological ones. Finally, the link between the physical and digital copy is defined as shadowing. Specifically, the term defines the process that enables continuous and (almost) real-time updating of the internal state of the DT in relation to changes that occur in the PA.\nEach DT is thus equipped with an internal model, which defines how the PA is represented in the digital level. The DT\u0026rsquo;s representation denoted as Digital Twin State supported and defined through M is defined in terms of:\nProperties: represent the observable attributes of the corresponding PA as labeled data whose values can dynamically change over time, in accordance with the evolution of the PA\u0026rsquo;s state. Events: represent the domain-level events that can be observed in the PA. Relationships: represent the links that exist between the modeled PA and other physical assets of the organizations through links to their corresponding Digital Twins. Like properties, relationships can be observed, dynamically created, and change over time, but unlike properties, they are not properly part of the PA\u0026rsquo;s state but of its operational context (e.g., a DT of a robot within a production line). Actions: represent the actions that can be invoked on the PA through interaction with the DT or directly on the DT if they are not directly available on the PA (the DT is augmenting the physical capabilities). Once the model M is defined, the dynamic state of the DT (SDT) can be defined by through the combination of its properties, events, relationships and actions associated to the DT timestamp that represents the current time of synchronization between the physical and digital counterparts.\nThe Shadowing Process The shadowing process (also known as replication of digitalization) allows to keep the Digital Twin State synchronized with that of the corresponding physical resource according to what is defined by the model M. Specifically, each relevant update of the PA state (SPA) is translated into a sequence of 3 main steps:\neach relevant change in physical asset state is modeled by a physical_event (e_pa); the event is propagated to the DT; given the new physical_event, the DT\u0026rsquo;s is updated through the application of a shadowing function, which depends on the model M The shadowing process allows also the DT to reflect and invoke possible actions of the PA. The DT receives an action request (denoted as digital_action) on its digital interface, applies the shadowing function to validate it and then propagates the request through its physical interface. An important aspect to emphasize is that the request for a digital_action does not directly change the state of the DT since any changes can only occur as a result of the shadowing function from the PA to the DT, as described earlier.\n","date":"February 9, 2024","id":17,"permalink":"/docs/introduction/dt-model/","summary":"With respect to the element present in the real world, it is defined as a Physical Asset (PA) with the intention of referring to any entity that has a manifestation or relevance in the physical world and a well-defined lifespan.","tags":"","title":"DT Model"},{"content":"\rThe modeling of the concept of DT includes also the definition and characterization of its life cycle. Based on the scientific literature, we model (and then map into the library) a life cycle with 5 states through which the DT goes from when it is executed to when it is stopped. The previous Figure shows a graphical representation of the life cycle with the following steps:\nOperating \u0026amp; Not Bound: this is the state in which the DT is located following the initialization phase, indicating that all internal modules of the DT are active but there is no association yet with the corresponding PA. Bound: this is the state in which the DT transitions following the correct execution of the binding procedure. The binding procedure allows to connect the two parts and enables bidirectional flow of events. Shadowed: this is the state reached by the DT when the shadowing process begins and its state is correctly synchronized with that of the PA. Out of Sync: this is the state that determines the presence of errors in the shadowing process. When in this state, the DT is not able to handle either state alignment events or those generated by the application layer. Done: this is the state that the DT reaches when the shadowing process is stopped, but the DT continues to be active to handle requests coming from external applications. From Unbound to Bound Taking into account the target reference Life Cycle the first point to address is how we can move from an UnBound state to a Bound condition with respect to the relationship with the Physical Layer.\nThe previous Figure illustrates a simple scenario where a Physical Asset uses two protocols (P1 and P2) to communicate and it is connected to the Digital Twin through a DT\u0026rsquo;s Physical Interface enabled with two dedicated Adapters for protocol P1 and P2. In order to move from the Unbound to Bound state the DT should be aware of the description of the target asset with respect to the two protocols. For example through P1 the asset exposes telemetry data (e.g., light bulb status and energy consumption) while on P2 allows incoming action requests (e.g., turn on/off the light). The Digital Twin can start the shadowing process only when it is bound and has a description of the properties and capabilities of the associated physical counterpart. The schematic procedure is illustrated in the following Figure:\nInvolved steps are:\nThe Adapter P1 communicates with the PA through Protocol 1 and provides a Physical Asset Description from its perspective The Adapter P2 communicates with the PA through Protocol 2 and provides a Physical Asset Description from its perspective Only when all Physical Adapters have been correctly bound (it may require time) to the Physical Asset and the associated Physical Asset Descriptions have been generated, the DT can move from UnBound to Bound Main core aspects associated to the concept of Physical Asset Description (PAD) are the following:\nIt is used to describe the list of properties, actions and relationships of a Physical Asset Each Physical Adapter generates a dedicated PAD associated to its perspective on the Physical Assets and its capabilities to read data and execute actions It is a responsibility of the DT to handle multiple descriptions in order to build the digital replica It will be used by the DT to handle the shadowing process and keep the digital replica synchronized with the physical counterpart From Bound to Shadowed Following the same approach described in the previous step we need to define a procedure to allow the DT to move from a Bound state to a Shadowed condition where the twin identified the interesting capabilities of the Physical Asset that has to be digitalized and according to the received Physical Asset Descriptions start the shadowing procedure to be synchronized with the physical world.\nAs schematically illustrated in the previous Figure, involved steps are:\nThe Model defines which properties should be monitored on the Physical Asset and start observing them through the target adapters Involved Physical Adapters communicate with the Physical Asset, receive data and generate Events (ePA) to notify about physical property changes Received ePA will be used by the Digital Twin Model in order to run the Shadowing function and compute the new DT State The DT can move from the Bound to Shadowed phase until it is able to maintain a proper synchronization with the physical asset over time through its shadowing process and the generation and maintenance of the DT\u0026rsquo;s State The Digital Twin State is structured and characterized by the following elements:\nA list of properties A list of actions A list of relationships Listed elements can be directly associated to the corresponding element of the Physical Asset or generated by DT Model combining multiple physical properties, actions or relationships at the same time. The Digital Twin State can be managed through the Shadowing Function and exposes a set of methods for its manipulated. When there is a change in the DT State an event (eDT) will be generated\nThe manipulation of DT\u0026rsquo;s State generates a set of DT\u0026rsquo;s events (eDT) associated to each specific variation and evolution of the twin during its life cyle. These events are used by the Digital Interface and in particular by its Digital Adapters to expose the DT\u0026rsquo;s State, its properties and capabilities to the external digital world. At the same time, eDT can be used by Digital Adapters to trigger action on the DT and consequently to propagate (if acceptable and/or needed) the incoming request to the physical assets bound with the target DT. Supported events are illustrated in the following schema.\n","date":"February 9, 2024","id":18,"permalink":"/docs/introduction/dt-life-cycle/","summary":"The modeling of the concept of DT includes also the definition and characterization of its life cycle. Based on the scientific literature, we model (and then map into the library) a life cycle with 5 states through which the DT goes from when it is executed to when it is stopped.","tags":"","title":"DT Life Cycle"},{"content":"","date":"September 7, 2023","id":19,"permalink":"/docs/","summary":"","tags":"","title":"Docs"},{"content":"Welcome to White Label Digital Twins (WLDT), an open-source project dedicated to supporting the design, development, and deployment of Digital Twins within the Internet of Things (IoT) ecosystems.\nThe WLDT library has been designed to align with the latest DT definitions from both Industrial and Scientific domains. It identifies DTs as active, flexible, and scalable software components. Our library aims to provide developers with the tools and resources necessary to create robust Digital Twins that effectively simulate and monitor physical assets within IoT environments.\nWhether you\u0026rsquo;re working on IoT, Industrial IoT (IIoT) applications, Smart Cities projects, or any other IoT-related endeavor, the WLDT library offers a versatile solution for implementing Digital Twins that accurately represent real-world objects and support informed decision-making processes.\n💻 Team \u0026amp; Mantainers [Founders \u0026amp; Main Contributors] Marco Picone - University of Modena \u0026amp; Reggio Emilia, Italy - (Link) [Key Contributors] Samuele Burattini - University of Bologna, Italy - (Link) 📜 Scientitic Citation \u0026amp; References If you use the WLDT Library in a Scientific Paper please use this reference:\n@article{PICONE2021100661, title = {WLDT: A general purpose library to build IoT digital twins}, journal = {SoftwareX}, volume = {13}, pages = {100661}, year = {2021}, issn = {2352-7110}, doi = {https://doi.org/10.1016/j.softx.2021.100661}, url = {https://www.sciencedirect.com/science/article/pii/S2352711021000066}, author = {Marco Picone and Marco Mamei and Franco Zambonelli}, keywords = {Internet of Things, Digital twin, Library, Software agent} } 📨 Community Join our community and contribute to the advancement of Digital Twin technology with White Label Digital Twins!\nWLDT questions, feedback and discussions are tracked using slack channels in the WLDT Slack Workspace.\nThe workspace is available here: WLDT Slack Workspace\nNew users first need to join the MEC Sandbox slack workspace by creating a new account using the invitation link provided here: Join the WLDT Slack Workspace\n🐛 Reporting Issues WLDT issues should be reported on Slack, where they can be discussed with the core team that maintains the WLDT Library.\n","date":"March 13, 2024","id":20,"permalink":"/about/","summary":"Welcome to White Label Digital Twins (WLDT), an open-source project dedicated to supporting the design, development, and deployment of Digital Twins within the Internet of Things (IoT) ecosystems.","tags":"","title":"About WLDT Library"},{"content":" What is a digital Twin? A Digital Twin (DT) is a comprehensive software representation of any individual Physical Asset (PA) in the real world.\nIt includes the properties, conditions, relationships, and behavior(s) of the real-life object through models and data.\nA Digital Twin is a set of realistic models that can digitalize an object’s behavior in the deployed environment and has the responsibility to represent and reflect its physical counterpart over time maintaining its digital replica across the object’s entire lifecycle.\nWhat can WLDT do for me? The White Label Digital Twin (WLDT) library aims to support the design, development, and deployment of Digital Twins within the Internet of Things (IoT) ecosystems.\nThe library has been designed following the latest DT definitions coming from both Industrial and Scientific domains and identifying DTs as active, flexible and scalable software components.\nScientitic Citation \u0026amp; Reference If you use the WLDT Library in a Scientific Paper refer to the About Page for additional information and scientific references. Thanks :)\n","date":"October 6, 2023","id":21,"permalink":"/","summary":"What is a digital Twin? A Digital Twin (DT) is a comprehensive software representation of any individual Physical Asset (PA) in the real world.","tags":"","title":"White Label Digital Twins"},{"content":"","date":"September 7, 2023","id":22,"permalink":"/privacy/","summary":"","tags":"","title":"Privacy Policy"},{"content":"","date":"January 1, 0001","id":23,"permalink":"/categories/","summary":"","tags":"","title":"Categories"},{"content":"","date":"January 1, 0001","id":24,"permalink":"/contributors/","summary":"","tags":"","title":"Contributors"},{"content":"","date":"January 1, 0001","id":25,"permalink":"/tags/","summary":"","tags":"","title":"Tags"}] \ No newline at end of file +[{"content":"📣 We\u0026rsquo;re thrilled to announce the release of version 0.3.0 of the White Label Digital Twins (WLDT) library! This release brings significant enhancements, improvements, and new features to further empower developers in designing, developing, and deploying Digital Twins within Internet of Things (IoT) ecosystems.\nFor detailed information about these changes and their impact, please refer to the information provided:\nOfficial Changelog Official Documentation Let\u0026rsquo;s dive into the key changes and updates included in this release:\nMigration Digital Adapters In version 0.3.0, we\u0026rsquo;ve made several enhancements and adjustments to the Digital Adapter class to improve its functionality and usability. Notable changes include:\nDiscontinued Methods: Several methods have been discontinued and removed from the DigitalAdapter class to streamline its interface and improve clarity. Method Signature Changes: The signatures of certain methods have been updated for consistency and clarity, ensuring a more intuitive developer experience. New Methods: We\u0026rsquo;ve introduced new methods to provide additional functionality and flexibility for handling state updates and event notifications. Migration Shadowing Function We\u0026rsquo;ve made significant improvements to the ShadowingModelFunction, which is now renamed to ShadowingFunction. Additionally, we\u0026rsquo;ve introduced changes to how the DigitalTwinState is managed within the Shadowing Function, providing developers with more control and flexibility.\nMigrating WLDT Engine \u0026amp; DT Creation In version 0.3.0, the WldtEngine class has been renamed to DigitalTwin, offering improved clarity and consistency. We\u0026rsquo;ve also made adjustments to the lifecycle management of Digital Twins, streamlining the process and enhancing usability.\nDigital Twin \u0026amp; Digital Twin Engine We\u0026rsquo;ve introduced enhancements to the Digital Twin and Digital Twin Engine classes, providing developers with improved functionality and ease of use. Notable updates include:\nSimplified Digital Twin Creation: Creating and managing Digital Twins is now more intuitive and streamlined. Lifecycle Management: We\u0026rsquo;ve enhanced the lifecycle management of Digital Twins, making it easier to start, stop, and manage multiple instances. Digital Twin State Manager The DigitalTwinStateManager class has been improved to provide better support for managing the state of Digital Twins. With features such as transaction support and event notification, developers can more effectively manage changes to Digital Twin states and respond to events.\nTo learn more about the capabilities of the DigitalTwinStateManager, please refer to the Digital Twin State Manager section.\nDigital Adapter We\u0026rsquo;ve extended and improved the Digital Adapter base class to provide enhanced support for handling Digital Twin state updates and event notifications. With the introduction of the onStateUpdate and onEventNotificationReceived methods, developers can more effectively respond to changes in Digital Twin states and events.\nGet Started with WLDT 0.3.0 To get started with version 0.3.0 of the WLDT library, simply update your dependencies to include the latest release. Detailed documentation and usage examples are available in the project repository, providing comprehensive guidance on leveraging the new features and enhancements.\nWe\u0026rsquo;re excited about the improvements and new capabilities introduced in WLDT 0.3.0, and we can\u0026rsquo;t wait to see how developers utilize them to create innovative IoT solutions powered by Digital Twins. As always, we welcome your feedback and contributions to help us further improve the library and empower the community.\nHappy coding with WLDT 0.3.0! 🚀\n","date":"March 13, 2024","id":0,"permalink":"/blog/ls-wldt-library-version-0.3.0/","summary":"📣 We\u0026rsquo;re thrilled to announce the release of version 0.3.0 of the White Label Digital Twins (WLDT) library! This release brings significant enhancements, improvements, and new features to further empower developers in designing, developing, and deploying Digital Twins within Internet of Things (IoT) ecosystems.","tags":"","title":"ls WLDT Library Version 0.3.0"},{"content":"","date":"September 7, 2023","id":1,"permalink":"/blog/","summary":"","tags":"","title":"Blog"},{"content":"","date":"September 7, 2023","id":2,"permalink":"/docs/introduction/","summary":"","tags":"","title":"Introduction"},{"content":"","date":"February 9, 2024","id":3,"permalink":"/docs/guides/","summary":"","tags":"","title":"Getting Started"},{"content":"The developer can use an existing Physical Adapter or create a new one to handle the communication with a specific physical twin. In this documentation we focus on the creation of a new Physical Adapter in order to explain library core functionalities. However, existing Physical Adapters can be found on the official repository and linked in the core documentation and webpage (WLDT-GitHub).\nIn general WLDT Physical Adapter extends the class PhysicalAdapter and it is responsible to talk with the physical world and handling the following main tasks:\nGenerate a PAD describing the properties, events, actions and relationships available on the physical twin using the class PhysicalAssetDescription Generate Physical Event using the class PhysicalAssetEventWldtEvent associated to the variation of any aspect of the physical state (properties, events, and relationships) Handle action request coming from the Digital World through the DT Shadowing Function by implementing the method onIncomingPhysicalAction and processing events modeled through the class PhysicalAssetActionWldtEvent Create a new class called DemoPhysicalAdapter extending the library class PhysicalAdapter and implement the following methods:\nonAdapterStart: A callback method used to notify when the adapter has been effectively started withing the DT\u0026rsquo;s life cycle onAdapterStop: A call method invoked when the adapter has been stopped and will be dismissed by the core onIncomingPhysicalAction: The callback method called when a new PhysicalAssetActionWldtEvent is sent by the Shadowing Function upon the receiving of a valid Digital Action through a Digital Adapter Then you have to create a constructor for your Physical Adapter with a single String parameter representing the id of the adapter. This id will be used internally by the library to handle and coordinate multiple adapters, adapts logs and execute functions upon the arrival of a new event. The resulting empty class will the following:\npublic class DemoPhysicalAdapter extends PhysicalAdapter { public DemoPhysicalAdapter(String id) { super(id); } @Override public void onIncomingPhysicalAction(PhysicalAssetActionWldtEvent\u0026lt;?\u0026gt; physicalAssetActionWldtEvent) { } @Override public void onAdapterStart() { } @Override public void onAdapterStop() { } } In our test Physical Adapter example we are going to emulate the communication with an Internet of Things device with the following sensing and actuation characteristics:\nA Temperature Sensor generating data about new measurements The possibility to generate OVER-HEATING events An action to set the target desired temperature value The first step will be to generate and publish the PhysicalAssetDescription (PAD) to describe the capabilities and the characteristics of our object allowing the Shadowing Function to decide how to digitalize its physical counterpart. Of course in our case the PAD is generated manually but according to the nature of the connected physical twin it can be automatically generated starting from a discovery or a configuration passed to the adapter.\nThe generation of the PAD for each active Physical Adapter is the fundamental DT process to handle the binding procedure and to allow the Shadowing Function and consequently the core of the twin to be aware of what is available in the physical world and consequently decide what to observe and digitalize.\nIn order to publish the PAD we can update the onAdapterStart method with the following lines of code:\nprivate final static String TEMPERATURE_PROPERTY_KEY = \u0026#34;temperature-property-key\u0026#34;; private final static String OVERHEATING_EVENT_KEY = \u0026#34;overheating-event-key\u0026#34;; private final static String SET_TEMPERATURE_ACTION_KEY = \u0026#34;set-temperatura-action-key\u0026#34;; @Override public void onAdapterStart() { try { //Create an empty PAD PhysicalAssetDescription pad = new PhysicalAssetDescription(); //Add a new Property associated to the target PAD with a key and a default value PhysicalAssetProperty\u0026lt;Double\u0026gt; temperatureProperty = new PhysicalAssetProperty\u0026lt;Double\u0026gt;(TEMPERATURE_PROPERTY_KEY, 0.0); pad.getProperties().add(temperatureProperty); //Add the declaration of a new type of generated event associated to a event key // and the content type of the generated payload PhysicalAssetEvent overheatingEvent = new PhysicalAssetEvent(OVERHEATING_EVENT_KEY, \u0026#34;text/plain\u0026#34;); pad.getEvents().add(overheatingEvent); //Declare the availability of a target action characterized by a Key, an action type // and the expected content type and the request body PhysicalAssetAction setTemperatureAction = new PhysicalAssetAction(SET_TEMPERATURE_ACTION_KEY, \u0026#34;temperature.actuation\u0026#34;, \u0026#34;text/plain\u0026#34;); pad.getActions().add(setTemperatureAction); //Notify the new PAD to the DT\u0026#39;s Shadowing Function this.notifyPhysicalAdapterBound(pad); //TODO add here the Device Emulation method } catch (PhysicalAdapterException | EventBusException e) { e.printStackTrace(); } } Now we need a simple code to emulate the generation of new temperature measurements and over-heating events. In a real Physical Adapter implementation we have to implement the real communication with the physical twin in order to read its state variation over time according to the supported protocols. In our simplified Physical Adapter we can the following function:\nprivate final static int MESSAGE_UPDATE_TIME = 1000; private final static int MESSAGE_UPDATE_NUMBER = 10; private final static double TEMPERATURE_MIN_VALUE = 20; private final static double TEMPERATURE_MAX_VALUE = 30; private Runnable deviceEmulation(){ return () -\u0026gt; { try { //Sleep 5 seconds to emulate device startup Thread.sleep(5000); //Create a new random object to emulate temperature variations Random r = new Random(); //Publish an initial Event for a normal condition publishPhysicalAssetEventWldtEvent(new PhysicalAssetEventWldtEvent\u0026lt;\u0026gt;(OVERHEATING_EVENT_KEY, \u0026#34;normal\u0026#34;)); //Emulate the generation on \u0026#39;n\u0026#39; temperature measurements for(int i = 0; i \u0026lt; MESSAGE_UPDATE_NUMBER; i++){ //Sleep to emulate sensor measurement Thread.sleep(MESSAGE_UPDATE_TIME); //Update the double randomTemperature = TEMPERATURE_MIN_VALUE + (TEMPERATURE_MAX_VALUE - TEMPERATURE_MIN_VALUE) * r.nextDouble(); //Create a new event to notify the variation of a Physical Property PhysicalAssetPropertyWldtEvent\u0026lt;Double\u0026gt; newPhysicalPropertyEvent = new PhysicalAssetPropertyWldtEvent\u0026lt;\u0026gt;(TEMPERATURE_PROPERTY_KEY, randomTemperature); //Publish the WLDTEvent associated to the Physical Property Variation publishPhysicalAssetPropertyWldtEvent(newPhysicalPropertyEvent); } //Publish a demo Physical Event associated to a \u0026#39;critical\u0026#39; overheating condition publishPhysicalAssetEventWldtEvent(new PhysicalAssetEventWldtEvent\u0026lt;\u0026gt;(OVERHEATING_EVENT_KEY, \u0026#34;critical\u0026#34;)); } catch (EventBusException | InterruptedException e) { e.printStackTrace(); } }; } Now we have to call the deviceEmulationFunction() inside the onAdapterStart() triggering its execution and emulating the physical counterpart of our DT. To do that add the following line at the end of the onAdapterStart() method after the this.notifyPhysicalAdapterBound(pad);.\nThe last step will be to handle an incoming action trying to set a new temperature on the device by implementing the method onIncomingPhysicalAction(). This method will receive a PhysicalAssetActionWldtEvent\u0026lt;?\u0026gt; physicalAssetActionWldtEvent associated to the action request generated by the shadowing function. Since a Physical Adapter can handle multiple action we have to check both action-key and body type in order to properly process the action (in our case just logging the request). The new update method will result like this:\n@Override public void onIncomingPhysicalAction(PhysicalAssetActionWldtEvent\u0026lt;?\u0026gt; physicalAssetActionWldtEvent) { try{ if(physicalAssetActionWldtEvent != null \u0026amp;\u0026amp; physicalAssetActionWldtEvent.getActionKey().equals(SET_TEMPERATURE_ACTION_KEY) \u0026amp;\u0026amp; physicalAssetActionWldtEvent.getBody() instanceof String) { System.out.println(\u0026#34;Received Action Request: \u0026#34; + physicalAssetActionWldtEvent.getActionKey() + \u0026#34; with Body: \u0026#34; + physicalAssetActionWldtEvent.getBody()); } else System.err.println(\u0026#34;Wrong Action Received !\u0026#34;); }catch (Exception e){ e.printStackTrace(); } } The overall class will result as following:\nimport it.wldt.adapter.physical.*; import it.wldt.adapter.physical.event.PhysicalAssetActionWldtEvent; import it.wldt.adapter.physical.event.PhysicalAssetEventWldtEvent; import it.wldt.adapter.physical.event.PhysicalAssetPropertyWldtEvent; import it.wldt.exception.EventBusException; import it.wldt.exception.PhysicalAdapterException; import java.util.Random; public class DemoPhysicalAdapter extends PhysicalAdapter { private final static String TEMPERATURE_PROPERTY_KEY = \u0026#34;temperature-property-key\u0026#34;; private final static String OVERHEATING_EVENT_KEY = \u0026#34;overheating-event-key\u0026#34;; private final static String SET_TEMPERATURE_ACTION_KEY = \u0026#34;set-temperature-action-key\u0026#34;; private final static int MESSAGE_UPDATE_TIME = 1000; private final static int MESSAGE_UPDATE_NUMBER = 10; private final static double TEMPERATURE_MIN_VALUE = 20; private final static double TEMPERATURE_MAX_VALUE = 30; public DemoPhysicalAdapter(String id) { super(id); } @Override public void onIncomingPhysicalAction(PhysicalAssetActionWldtEvent\u0026lt;?\u0026gt; physicalAssetActionWldtEvent) { try{ if(physicalAssetActionWldtEvent != null \u0026amp;\u0026amp; physicalAssetActionWldtEvent.getActionKey().equals(SET_TEMPERATURE_ACTION_KEY) \u0026amp;\u0026amp; physicalAssetActionWldtEvent.getBody() instanceof Double) { System.out.println(\u0026#34;Received Action Request: \u0026#34; + physicalAssetActionWldtEvent.getActionKey() + \u0026#34; with Body: \u0026#34; + physicalAssetActionWldtEvent.getBody()); } else System.err.println(\u0026#34;Wrong Action Received !\u0026#34;); }catch (Exception e){ e.printStackTrace(); } } @Override public void onAdapterStart() { try { //Create an empty PAD PhysicalAssetDescription pad = new PhysicalAssetDescription(); //Add a new Property associated to the target PAD with a key and a default value PhysicalAssetProperty\u0026lt;Double\u0026gt; temperatureProperty = new PhysicalAssetProperty\u0026lt;Double\u0026gt;(GlobalKeywords.TEMPERATURE_PROPERTY_KEY, 0.0); pad.getProperties().add(temperatureProperty); //Add the declaration of a new type of generated event associated to a event key // and the content type of the generated payload PhysicalAssetEvent overheatingEvent = new PhysicalAssetEvent(GlobalKeywords.OVERHEATING_EVENT_KEY, \u0026#34;text/plain\u0026#34;); pad.getEvents().add(overheatingEvent); //Declare the availability of a target action characterized by a Key, an action type // and the expected content type and the request body PhysicalAssetAction setTemperatureAction = new PhysicalAssetAction(GlobalKeywords.SET_TEMPERATURE_ACTION_KEY, \u0026#34;temperature.actuation\u0026#34;, \u0026#34;text/plain\u0026#34;); pad.getActions().add(setTemperatureAction); //Notify the new PAD to the DT\u0026#39;s Shadowing Function this.notifyPhysicalAdapterBound(pad); //Start Device Emulation new Thread(deviceEmulation()).start(); } catch (PhysicalAdapterException | EventBusException e) { e.printStackTrace(); } } @Override public void onAdapterStop() { } private Runnable deviceEmulation(){ return () -\u0026gt; { try { //Sleep 5 seconds to emulate device startup Thread.sleep(5000); //Create a new random object to emulate temperature variations Random r = new Random(); //Publish an initial Event for a normal condition publishPhysicalAssetEventWldtEvent(new PhysicalAssetEventWldtEvent\u0026lt;\u0026gt;(GlobalKeywords.OVERHEATING_EVENT_KEY, \u0026#34;normal\u0026#34;)); //Emulate the generation on \u0026#39;n\u0026#39; temperature measurements for(int i = 0; i \u0026lt; GlobalKeywords.MESSAGE_UPDATE_NUMBER; i++){ //Sleep to emulate sensor measurement Thread.sleep(GlobalKeywords.MESSAGE_UPDATE_TIME); //Update the double randomTemperature = GlobalKeywords.TEMPERATURE_MIN_VALUE + (GlobalKeywords.TEMPERATURE_MAX_VALUE - GlobalKeywords.TEMPERATURE_MIN_VALUE) * r.nextDouble(); //Create a new event to notify the variation of a Physical Property PhysicalAssetPropertyWldtEvent\u0026lt;Double\u0026gt; newPhysicalPropertyEvent = new PhysicalAssetPropertyWldtEvent\u0026lt;\u0026gt;(GlobalKeywords.TEMPERATURE_PROPERTY_KEY, randomTemperature); //Publish the WLDTEvent associated to the Physical Property Variation publishPhysicalAssetPropertyWldtEvent(newPhysicalPropertyEvent); } //Publish a demo Physical Event associated to a \u0026#39;critical\u0026#39; overheating condition publishPhysicalAssetEventWldtEvent(new PhysicalAssetEventWldtEvent\u0026lt;\u0026gt;(GlobalKeywords.OVERHEATING_EVENT_KEY, \u0026#34;critical\u0026#34;)); } catch (EventBusException | InterruptedException e) { e.printStackTrace(); } }; } } Both Physical Adapters and Digital Adapters can be defined natively with a custom configuration provided by the developer as illustrated in the dedicated Section: Configurable Physical \u0026amp; Digital Adapters.\n","date":"February 9, 2024","id":4,"permalink":"/docs/guides/physical-adapter/","summary":"The developer can use an existing Physical Adapter or create a new one to handle the communication with a specific physical twin.","tags":"","title":"Physical Adapter"},{"content":"After the definition of the Physical Adapter it is time to start implementing the core of our DT through the definition of its shadowing function in charge of:\nHandle received PAD from Physical Adapters in order to device which properties, events, relationships or actions available on connected physical twins should be mapped and managed into the DT State Manage incoming notifications/callbacks associated to the variation of physical properties (e.g, temperature variation) or the generation of physical event (e.g., overheating) Process action requests from the digital world that should be validated and forward to the correct Physical Adapter in order to trigger the associated actions on the physical world The Shadowing Function has the responsibility to build and maintain the updated state of the Digital Twin The internal variable of any WLDT Shadowing Function (available through the base class ShadowingFunction) used to do that is DigitalTwinStateManager accessible through the variable: this.digitalTwinStateManager\nWhen the Shadowing Function has to compute the new DT State it can now work with the following method to handle DT State Transition:\nStart the DT State Transaction: startStateTransaction() DT State variation methods such as: createProperty() updateProperty() updatePropertyValue() deleteProperty() enableAction() updateAction() disableAction() registerEvent() updateRegisteredEvent() unRegisterEvent() createRelationship() addRelationshipInstance() deleteRelationship() deleteRelationshipInstance() At the end the transaction can be committed using the method: commitStateTransaction() To access the current DT State the Shadowing Function implementation can use the method this.digitalTwinStateManager.getDigitalTwinState() The information available on the DT State are:\nproperties: List of Properties with their values (if available) actions: List of Actions that can be called on the DT events: List of Events that can be generated by the DT relationships: List of Relationships and their instances (if available) evaluationInstant: The timestamp representing the evaluation instant of the DT state Available main methods on that class instance are:\nProperties: getProperty(String propertyKey): Retrieves if present the target DigitalTwinStateProperty by Key containsProperty(String propertyKey): Checks if a target Property Key is already available in the current Digital Twin\u0026rsquo;s State getPropertyList(): Loads the list of available Properties (described by the class DigitalTwinStateProperty) available on the Digital Twin\u0026rsquo;s State createProperty(DigitalTwinStateProperty\u0026lt;?\u0026gt; dtStateProperty): Allows the creation of a new Property on the Digital Twin\u0026rsquo;s State through the class DigitalTwinStateProperty readProperty(String propertyKey): Retrieves if present the target DigitalTwinStateProperty by Key updateProperty(DigitalTwinStateProperty\u0026lt;?\u0026gt; dtStateProperty): Updates the target property using the DigitalTwinStateProperty and the associated Property Key field deleteProperty(String propertyKey): Deletes the target property identified by the specified key Actions: containsAction(String actionKey): Checks if a Digital Twin State Action with the specified key is correctly registered getAction(String actionKey): Loads the target DigitalTwinStateAction by key getActionList(): Gets the list of available Actions registered on the Digital Twin\u0026rsquo;s State enableAction(DigitalTwinStateAction digitalTwinStateAction): Enables and registers the target Action described through an instance of the DigitalTwinStateAction class updateAction(DigitalTwinStateAction digitalTwinStateAction): Update the already registered target Action described through an instance of the DigitalTwinStateAction class disableAction(String actionKey): Disables and unregisters the target Action described through an instance of the DigitalTwinStateAction class Events: containsEvent(String eventKey): Check if a Digital Twin State Event with the specified key is correctly registered getEvent(String eventKey): Return the description of a registered Digital Twin State Event according to its Key getEventList(): Return the list of existing and registered Digital Twin State Events registerEvent(DigitalTwinStateEvent digitalTwinStateEvent): Register a new Digital Twin State Event updateRegisteredEvent(DigitalTwinStateEvent digitalTwinStateEvent): Update the registration and signature of an existing Digital Twin State Event unRegisterEvent(String eventKey): Un-register a Digital Twin State Event notifyDigitalTwinStateEvent(DigitalTwinStateEventNotification\u0026lt;?\u0026gt; digitalTwinStateEventNotification): Method to notify the occurrence of the target Digital Twin State Event Relationships: containsRelationship(String relationshipName): Checks if a Relationship Name is already available in the current Digital Twin\u0026rsquo;s State createRelationship(DigitalTwinStateRelationship\u0026lt;?\u0026gt; relationship): Creates a new Relationships (described by the class DigitalTwinStateRelationship) in the Digital Twin\u0026rsquo;s State addRelationshipInstance(String name, DigitalTwinStateRelationshipInstance\u0026lt;?\u0026gt; instance): Adds a new Relationship instance described through the class DigitalTwinStateRelationshipInstance and identified through its name getRelationshipList(): Loads the list of existing relationships on the Digital Twin\u0026rsquo;s State through a list of DigitalTwinStateRelationship getRelationship(String name): Gets a target Relationship identified through its name and described through the class DigitalTwinStateRelationship deleteRelationship(String name): Deletes a target Relationship identified through its name deleteRelationshipInstance(String relationshipName, String instanceKey): Deletes the target Relationship Instance using relationship name and instance Key The basic library class that we are going to extend is called ShadowingFunction and creating a new class named DemoShadowingFunction the resulting code is the same after implementing required methods the basic constructor with the id String parameter.\nimport it.wldt.adapter.digital.event.DigitalActionWldtEvent; import it.wldt.adapter.physical.PhysicalAssetDescription; import it.wldt.adapter.physical.event.PhysicalAssetEventWldtEvent; import it.wldt.adapter.physical.event.PhysicalAssetPropertyWldtEvent; import it.wldt.adapter.physical.event.PhysicalAssetRelationshipInstanceCreatedWldtEvent; import it.wldt.adapter.physical.event.PhysicalAssetRelationshipInstanceDeletedWldtEvent; import it.wldt.core.model.ShadowingModelFunction; import java.util.Map; public class DemoShadowingFunction extends ShadowingModelFunction { public DemoShadowingFunction(String id) { super(id); } //// Shadowing Function Management Callbacks //// @Override protected void onCreate() { } @Override protected void onStart() { } @Override protected void onStop() { } //// Bound LifeCycle State Management Callbacks //// @Override protected void onDigitalTwinBound(Map\u0026lt;String, PhysicalAssetDescription\u0026gt; adaptersPhysicalAssetDescriptionMap) { } @Override protected void onDigitalTwinUnBound(Map\u0026lt;String, PhysicalAssetDescription\u0026gt; map, String s) { } @Override protected void onPhysicalAdapterBidingUpdate(String s, PhysicalAssetDescription physicalAssetDescription) { } //// Physical Property Variation Callback //// @Override protected void onPhysicalAssetPropertyVariation(PhysicalAssetPropertyWldtEvent\u0026lt;?\u0026gt; physicalAssetPropertyWldtEvent) { } //// Physical Event Notification Callback //// @Override protected void onPhysicalAssetEventNotification(PhysicalAssetEventWldtEvent\u0026lt;?\u0026gt; physicalAssetEventWldtEvent) { } //// Physical Relationships Notification Callbacks //// @Override protected void onPhysicalAssetRelationshipEstablished(PhysicalAssetRelationshipInstanceCreatedWldtEvent\u0026lt;?\u0026gt; physicalAssetRelationshipInstanceCreatedWldtEvent) { } @Override protected void onPhysicalAssetRelationshipDeleted(PhysicalAssetRelationshipInstanceDeletedWldtEvent\u0026lt;?\u0026gt; physicalAssetRelationshipInstanceDeletedWldtEvent) { } //// Digital Action Received Callbacks //// @Override protected void onDigitalActionEvent(DigitalActionWldtEvent\u0026lt;?\u0026gt; digitalActionWldtEvent) { } } The methods onCreate(), onStart() and onStop() are used to receive callbacks from the DT\u0026rsquo;s core when the Shadowing Function has been effectively created within the twin, is started or stopped according to the evolution of its life cycle. In our initial implementation we are not implementing any of them but they can be useful to trigger specific behaviours according to the different phases.\nThe first method that we have to implement in order to analyze received PAD and build the Digital Twin State in terms of properties, events, relationships and available actions is the onDigitalTwinBound(Map\u0026lt;String, PhysicalAssetDescription\u0026gt; map) method. In our initial implementation we just pass through all the received characteristics recevied from each connected Physical Adapter mapping every physical entity into the DT\u0026rsquo;s state without any change or adaptation (Of course complex behaviour can be implemented to customized the digitalization process).\nThrough the following method we implement the following behaviour:\nAnalyze each received PAD from each connected and active Physical Adapter (in our case we will have just 1 Physical Adapter) Iterate over all the received Properties for each PAD and create the same Property on the Digital Twin State Start observing target Physical Properties in order to receive notification callback about physical variation through the method observePhysicalAssetProperty(property); Analyze received PAD\u0026rsquo;s Events declaration and recreates them also on the DT\u0026rsquo;s State Start observing target Physical Event in order to receive notification callback about physical event generation through the method observePhysicalAssetEvent(event); Check available Physical Action and enable them on the DT\u0026rsquo;s State. Enabled Digital Action are automatically observed by the Shadowing Function in order to receive action requests from active Digital Adapters The possibility to manually observe Physical Properties and Event has been introduced to allow the Shadowing Function to decide what to do according to the nature of the property or of the target event. For example in some cases with static properties it will not be necessary to observe any variation, and it will be enough to read the initial value to build the digital replica of that specific property.\nSince the DT State is managed through the DigitalTwinStateManager class all the changes and variation should be applied on the DT ShadowingFunction using the previously presented transaction management and the correct call of methods startStateTransaction() and commitStateTransaction().\n@Override protected void onDigitalTwinBound(Map\u0026lt;String, PhysicalAssetDescription\u0026gt; adaptersPhysicalAssetDescriptionMap) { try{ // NEW from 0.3.0 -\u0026gt; Start DT State Change Transaction this.digitalTwinStateManager.startStateTransaction(); //Iterate over all the received PAD from connected Physical Adapters adaptersPhysicalAssetDescriptionMap.values().forEach(pad -\u0026gt; { //Iterate over all the received PAD from connected Physical Adapters adaptersPhysicalAssetDescriptionMap.values().forEach(pad -\u0026gt; { pad.getProperties().forEach(property -\u0026gt; { try { //Create and write the property on the DT\u0026#39;s State this.digitalTwinState.createProperty(new DigitalTwinStateProperty\u0026lt;\u0026gt;(property.getKey(),(Double) property.getInitialValue())); //Start observing the variation of the physical property in order to receive notifications //Without this call the Shadowing Function will not receive any notifications or callback about //incoming physical property of the target type and with the target key this.observePhysicalAssetProperty(property); } catch (Exception e) { e.printStackTrace(); } }); //Iterate over available declared Physical Events for the target Physical Adapter\u0026#39;s PAD pad.getEvents().forEach(event -\u0026gt; { try { //Instantiate a new DT State Event with the same key and type DigitalTwinStateEvent dtStateEvent = new DigitalTwinStateEvent(event.getKey(), event.getType()); //Create and write the event on the DT\u0026#39;s State this.digitalTwinState.registerEvent(dtStateEvent); //Start observing the variation of the physical event in order to receive notifications //Without this call the Shadowing Function will not receive any notifications or callback about //incoming physical events of the target type and with the target key this.observePhysicalAssetEvent(event); } catch (Exception e) { e.printStackTrace(); } }); //Iterate over available declared Physical Actions for the target Physical Adapter\u0026#39;s PAD pad.getActions().forEach(action -\u0026gt; { try { //Instantiate a new DT State Action with the same key and type DigitalTwinStateAction dtStateAction = new DigitalTwinStateAction(action.getKey(), action.getType(), action.getContentType()); //Enable the action on the DT\u0026#39;s State this.digitalTwinState.enableAction(dtStateAction); } catch (Exception e) { e.printStackTrace(); } }); }); // NEW from 0.3.0 -\u0026gt; Commit DT State Change Transaction to apply the changes on the DT State and notify about the change this.digitalTwinStateManager.commitStateTransaction(); //Start observation to receive all incoming Digital Action through active Digital Adapter //Without this call the Shadowing Function will not receive any notifications or callback about //incoming request to execute an exposed DT\u0026#39;s Action observeDigitalActionEvents(); //Notify the DT Core that the Bounding phase has been correctly completed and the DT has evaluated its //internal status according to what is available and declared through the Physical Adapters notifyShadowingSync(); }catch (Exception e){ e.printStackTrace(); } } In particular the method observeDigitalActionEvents() should be called start the observation of digital actions and to receive all incoming Digital Action through active Digital Adapters. Without this call the Shadowing Function will not receive any notifications or callback about incoming request to execute an exposed DT\u0026rsquo;s Action. Of course, we have to call this method if we are mapping any digital action in our DT.\nAnother fundamental method is notifyShadowingSync() used to notify the DT Core that the Bounding phase has been correctly completed and the DT has evaluated its internal status according to what is available and declared through the Physical Adapters.\nAs mentioned, in the previous example the Shadowing Function does not apply any control or check on the nature of declared physical property. Of course in order to have a more granular control, it will be possible to use property Key or any other field or even the type of the instance through an instanceof check to implement different controls and behaviours.\nA variation (only for the property management code) to the previous method can be the following:\n//Iterate over available declared Physical Property for the target Physical Adapter\u0026#39;s PAD pad.getProperties().forEach(property -\u0026gt; { try { //Check property Key and Instance of to validate that is a Double if(property.getKey().equals(\u0026#34;temperature-property-key\u0026#34;) \u0026amp;\u0026amp; property.getInitialValue() != null \u0026amp;\u0026amp; property.getInitialValue() instanceof Double) { //Instantiate a new DT State Property of the right type, the same key and initial value DigitalTwinStateProperty\u0026lt;Double\u0026gt; dtStateProperty = new DigitalTwinStateProperty\u0026lt;Double\u0026gt;(property.getKey(),(Double) property.getInitialValue()); //Create and write the property on the DT\u0026#39;s State this.digitalTwinState.createProperty(dtStateProperty); //Start observing the variation of the physical property in order to receive notifications //Without this call the Shadowing Function will not receive any notifications or callback about //incoming physical property of the target type and with the target key this.observePhysicalAssetProperty(property); } } catch (Exception e) { e.printStackTrace(); } }); The next method that we have to implement in order to properly define and implement the behaviour of our DT through its ShadowingModelFunction are:\nonPhysicalAssetPropertyVariation: Method called when a new variation for a specific Physical Property has been detected by the associated Physical Adapter. The method receive as parameter a specific WLDT Event called PhysicalAssetPropertyWldtEvent\u0026lt;?\u0026gt; physicalPropertyEventMessage containing all the information generated by the Physical Adapter upon the variation of the monitored physical counterpart. onPhysicalAssetEventNotification: Callback method used to be notified by a PhysicalAdapter about the generation of a Physical Event. As for the previous method, also this function receive a WLDT Event parameter of type onPhysicalAssetEventNotification(PhysicalAssetEventWldtEvent\u0026lt;?\u0026gt; physicalAssetEventWldtEvent)) containing all the field of the generated physical event. onDigitalActionEvent: On the opposite this method is triggered from one of the active Digital Adapter when an Action request has been received on the Digital Interface. The method receive as parameter an instance of the WLDT Event class DigitalActionWldtEvent\u0026lt;?\u0026gt; digitalActionWldtEvent describing the target digital action request and the associated body. For the onPhysicalAssetPropertyVariation a simple implementation in charge ONLY of mapping the new Physical Property value into the corresponding DT\u0026rsquo;State property can be implemented as follows:\nThe DT State transaction management should be applied in the point of the code where the Shadowing Function receive a variation from the Physical world through a target adapter and the callback method onPhysicalAssetPropertyVariation(...)\n@Override protected void onPhysicalAssetPropertyVariation(PhysicalAssetPropertyWldtEvent\u0026lt;?\u0026gt; physicalPropertyEventMessage) { try { //Update Digital Twin State //NEW from 0.3.0 -\u0026gt; Start State Transaction this.digitalTwinStateManager.startStateTransaction(); this.digitalTwinState.updateProperty(new DigitalTwinStateProperty\u0026lt;\u0026gt;(physicalPropertyEventMessage.getPhysicalPropertyId(), physicalPropertyEventMessage.getBody())); //NEW from 0.3.0 -\u0026gt; Commit State Transaction this.digitalTwinStateManager.commitStateTransaction(); } catch (WldtDigitalTwinStatePropertyException | WldtDigitalTwinStatePropertyBadRequestException | WldtDigitalTwinStatePropertyNotFoundException | WldtDigitalTwinStateException e) { e.printStackTrace(); } } In this case as reported in the code, we call the method this.digitalTwinState.updateProperty on the Shadowing Function in order to update an existing DT\u0026rsquo;State property (previously created in the onDigitalTwinBound method). To update the value we directly use the received data on the PhysicalAssetPropertyWldtEvent without any additional check or change that might be instead needed in advanced examples.\nFollowing the same principle, a simplified digital mapping between physical and digital state upon the receving of a physical event variation can be the following:\n@Override protected void onPhysicalAssetEventNotification(PhysicalAssetEventWldtEvent\u0026lt;?\u0026gt; physicalAssetEventWldtEvent) { try { this.digitalTwinStateManager.notifyDigitalTwinStateEvent(new DigitalTwinStateEventNotification\u0026lt;\u0026gt;(physicalAssetEventWldtEvent.getPhysicalEventKey(), physicalAssetEventWldtEvent.getBody(), physicalAssetEventWldtEvent.getCreationTimestamp())); } catch (WldtDigitalTwinStateEventNotificationException | EventBusException e) { e.printStackTrace(); } } With respect to events management, we use the Shadowint Function method this.digitalTwinState.notifyDigitalTwinStateEvent to notify the other DT Components (e.g., Digital Adapters) the incoming Physical Event by creating a new instance of a DigitalTwinStateEventNotification class containing all the information associated to the event. Of course, additional controls and checks can be introduced in this method validating and processing the incoming physical message to define complex behaviours.\nThe last method that we are going to implement is the onDigitalActionEvent one where we have to handle an incoming Digital Action request associated to an Action declared on the DT\u0026rsquo;s State in the onDigitalTwinBound method. In that case the Digital Action should be forwarded to the Physical Interface in order to be sent to the physical counterpart for the effective execution.\n@Override protected void onDigitalActionEvent(DigitalActionWldtEvent\u0026lt;?\u0026gt; digitalActionWldtEvent) { try { this.publishPhysicalAssetActionWldtEvent(digitalActionWldtEvent.getActionKey(), digitalActionWldtEvent.getBody()); } catch (EventBusException e) { e.printStackTrace(); } } Also in that case we are forwarding the incoming Digital Action request described through the class DigitalActionWldtEvent to the Physical Adapter with the method of the Shadowing Function denoted as this.publishPhysicalAssetActionWldtEvent and passing directly the action key and the target Body. No additional processing or validation have been introduced here, but they might be required in advanced scenario in order to properly adapt incoming digital action request to what is effectively expected on the physical counterpart.\n","date":"February 9, 2024","id":5,"permalink":"/docs/guides/shadowing-function/","summary":"After the definition of the Physical Adapter it is time to start implementing the core of our DT through the definition of its shadowing function in charge of:","tags":"","title":"Shadowing Function"},{"content":"The las component that we have to implement to complete our first simple Digital Twin definition through the WLDT library is a Digital Adapter in charge of:\nReceiving event from the DT\u0026rsquo;s Core related to the variation of properties, events, available actions and relationships Expose received information to the external world according to its implementation and the supported protocol Handle incoming digital action and forward them to the Core in order to be validated and processed by the Shadowing Function The basic library class that we are going to extend is called DigitalAdapter and creating a new class named DemoDigitalAdapter. The DigitalTwinAdapter class can take as Generic Type the type of Configuration used to configure its behaviours. In this simplified example we are defining a DigitalAdapter without any Configuration.\nA Digital Adapter has direct access to the current DT\u0026rsquo;s State through callbacks or directly in a synchronous way using the internal variable called: digitalTwinState. Through it is possibile to navigate all the fields currently composing the state of our Digital Twin.\nThe Digital Adapter class has e long list of callback and notification method to allow the adapter to be updated about all the variation and changes on the twin. Available callbacks can be summarized as follows:\nDigital Adapter Start/Stop: onAdapterStart(): Feedback when the Digital Adapter correctly starts onAdapterStop(): Feedback when the Digital Adapter has been stopped Digital Twin Life Cycle Notifications: onDigitalTwinCreate(): The DT has been created onDigitalTwinStart(): The DT started onDigitalTwinSync(IDigitalTwinState digitalTwinState): The DT is Synchronized with its physical counterpart. The current DigitalTwinState is passed as parameter to allow the Digital Adapter to know the current state and consequently implement its behaviour onDigitalTwinUnSync(IDigitalTwinState digitalTwinState): The DT is not synchronized anymore with its physical counterpart. The last current DigitalTwinState is passed as parameter to allow the Digital Adapter to know the last state and consequently implement its behaviour onDigitalTwinStop(): The DT is stopped onDigitalTwinDestroy(): The DT has been destroyed and the application stopped The Digital Adapter DT State variations and DT events are received by the Adapter from the DT core belongs to the following categories:\nDigital Twin State Update through the method onStateUpdate(...) providing information about the new state of the Digital Twin, the previous state, and a list of changes that occurred between these two states. In the previous version each variation of a property, relationships, actions or events were notified. In the new version only a committed DT\u0026rsquo;State variation is notified to listeners. Event Notifications through the method onEventNotificationReceived(...) whenever there is a notification about an event related to the Digital Twin\u0026rsquo;s state coming from the physical world, generated by the twin and processed by the Shadowing Function. For example in the DT State we can have the declaration of the over-heating-alert structured and received in the DT State while the effective occurrence of the event and the associated notification is notified through this dedicated callback The onStateUpdate method is an abstract method that must be implemented by any class extending the DigitalAdapter class. This method is called whenever there is an update to the Digital Twin\u0026rsquo;s state. It provides information about the new state of the Digital Twin, the previous state, and a list of changes that occurred between these two states.\nThe explanation of the parameters is the following:\nnewDigitalTwinState: This parameter represents the updated state of the Digital Twin. It is an instance of the DigitalTwinState class, which encapsulates the current state information. previousDigitalTwinState: This parameter represents the state of the Digital Twin before the update. It is also an instance of the DigitalTwinState class. digitalTwinStateChangeList: This parameter is an ArrayList containing DigitalTwinStateChange objects. Each DigitalTwinStateChange object encapsulates information about a specific change that occurred between the previous and new states. It includes details such as the property or aspect of the state that changed, the previous value, and the new value. Another core method where a Digital Adapter receive the description of the DT\u0026rsquo;State is onDigitalTwinSync(IDigitalTwinState digitalTwinState). The Adapter using the parameter digitalTwinState can analyze available properties, actions, events and relationships and decide how to implement its internal behaviour with the methods presented in ShadowingFunction. The DT State is automatically monitored by each Digital Adapter while for the Events potentially generated by the DT can be observed by each adapter using:\nobserveAllDigitalTwinEventsNotifications: Enable the observation of available Digital Twin State Events Notifications. unObserveAllDigitalTwinEventsNotifications: Cancel the observation of Digital Twin State Events Notifications observeDigitalTwinEventsNotifications: Enable the observation of the notification associated to a specific list of Digital Twin State events. With respect to event a notification contains the new associated value unObserveDigitalTwinEventsNotifications: Cancel the observation of a target list of properties observeDigitalTwinEventNotification: Enable the observation of the notification associated to a single Digital Twin State event. With respect to event a notification contains the new associated value unObserveDigitalTwinEventNotification: Cancel the observation of a single target event The resulting code will be the following after adding the required methods (still empty) and the basic constructor with the id String parameter is the following:\nimport it.wldt.adapter.digital.DigitalAdapter; import it.wldt.core.state.*; public class DemoDigitalAdapter extends DigitalAdapter\u0026lt;Void\u0026gt; { public DemoDigitalAdapter(String id) { super(id); } /** * Callback to notify the adapter on its correct startup */ @Override public void onAdapterStart() {} /** * Callback to notify the adapter that has been stopped */ @Override public void onAdapterStop() {} /** * DT Life Cycle notification that the DT is correctly on Sync * @param digitalTwinState */ @Override public void onDigitalTwinSync(DigitalTwinState digitalTwinState) {} /** * DT Life Cycle notification that the DT is currently Not Sync * @param digitalTwinState */ @Override public void onDigitalTwinUnSync(DigitalTwinState digitalTwinState) {} /** * DT Life Cycle notification that the DT has been created */ @Override public void onDigitalTwinCreate() {} /** * DT Life Cycle Notification that the DT has correctly Started */ @Override public void onDigitalTwinStart() {} /** * DT Life Cycle Notification that the DT has been stopped */ @Override public void onDigitalTwinStop() {} /** * DT Life Cycle Notification that the DT has destroyed */ @Override public void onDigitalTwinDestroy() {} /** * Callback method allowing the Digital Adapter to receive the updated Digital Twin State together with * the previous state and the list of applied changes * * @param newDigitalTwinState The new Digital Twin State computed by the Shadowing Function * @param previousDigitalTwinState The previous Digital Twin State * @param digitalTwinStateChangeList The list of applied changes to compute the new Digital Twin State */ @Override protected void onStateUpdate(DigitalTwinState newDigitalTwinState, DigitalTwinState previousDigitalTwinState, ArrayList\u0026lt;DigitalTwinStateChange\u0026gt; digitalTwinStateChangeList) {} /** * Callback method to receive a new computed Event Notification (associated to event declared in the DT State) * * @param digitalTwinStateEventNotification The generated Notification associated to a DT Event */ @Override protected void onEventNotificationReceived(DigitalTwinStateEventNotification\u0026lt;?\u0026gt; digitalTwinStateEventNotification) {} } By default, a Digital Adapter observes all the variation on the DT\u0026rsquo;s State in terms of Properties, Relationships, Actions and Events. As previously mentioned the observation of DT\u0026rsquo;s State Properties allows to receive also properties variation on the method since a property is natively composed by its description (e.g., type) and its current value. On the opposite the observation on DT\u0026rsquo;s State Action, Relationships and Events allow ONLY to receive callbacks when a new entity is added or an update is occurred without receiving updates on values variation.\nThe only thing that we should add in the onDigitalTwinSync(IDigitalTwinState currentDigitalTwinState) callback is the direct observation for Events. Following this approach we can change our Digital Adapter in the following methods:\nIn onDigitalTwinSync we observe in this first simple implementation only the incoming values for declared Events in the DT\u0026rsquo;State. As previously mentioned the observation of any variation of the State structure together with Properties Values are by default observed by any Digital Adapter. In this method we use the internal variable digitalTwinState to access the DT\u0026rsquo;s state and find available Events declaration that we would like to observe.\npublic void onDigitalTwinSync(IDigitalTwinState currentDigitalTwinState) { try { //Retrieve the list of available events and observe all variations digitalTwinState.getEventList() .map(eventList -\u0026gt; eventList.stream() .map(DigitalTwinStateEvent::getKey) .collect(Collectors.toList())) .ifPresent(eventKeys -\u0026gt; { try { observeDigitalTwinEventsNotifications(eventKeys); } catch (EventBusException e) { e.printStackTrace(); } }); } catch (Exception e) { e.printStackTrace(); } } Developers extending the DigitalAdapter class should implement the onStateUpdate method to define custom logic that needs to be executed whenever the state of the Digital Twin is updated. This could include tasks such as processing state changes, updating internal variables, triggering specific actions, or notifying other components about the state update.\nHere\u0026rsquo;s an example of how the method might be implemented in a concrete subclass of DigitalAdapter:\n@Override protected void onStateUpdate(DigitalTwinState newDigitalTwinState, DigitalTwinState previousDigitalTwinState, ArrayList\u0026lt;DigitalTwinStateChange\u0026gt; digitalTwinStateChangeList) { // In newDigitalTwinState we have the new DT State System.out.println(\u0026#34;New DT State is: \u0026#34; + newDigitalTwinState); // The previous DT State is available through the variable previousDigitalTwinState System.out.println(\u0026#34;Previous DT State is: \u0026#34; + previousDigitalTwinState); // We can also check each DT\u0026#39;s state change potentially differentiating the behaviour for each change if (digitalTwinStateChangeList != null \u0026amp;\u0026amp; !digitalTwinStateChangeList.isEmpty()) { // Iterate through each state change in the list for (DigitalTwinStateChange stateChange : digitalTwinStateChangeList) { // Get information from the state change DigitalTwinStateChange.Operation operation = stateChange.getOperation(); DigitalTwinStateChange.ResourceType resourceType = stateChange.getResourceType(); DigitalTwinStateResource resource = stateChange.getResource(); // Perform different actions based on the type of operation switch (operation) { case OPERATION_UPDATE: // Handle an update operation System.out.println(\u0026#34;Update operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; case OPERATION_UPDATE_VALUE: // Handle an update value operation System.out.println(\u0026#34;Update value operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; case OPERATION_ADD: // Handle an add operation System.out.println(\u0026#34;Add operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; case OPERATION_REMOVE: // Handle a remove operation System.out.println(\u0026#34;Remove operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; default: // Handle unknown operation (optional) System.out.println(\u0026#34;Unknown operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; } } } else { // No state changes System.out.println(\u0026#34;No state changes detected.\u0026#34;); } } In this example, the method iterates over the list of state changes, extracts information about each change, and performs custom actions based on the changes. Developers can adapt this method to suit the specific requirements of their Digital Twin application.\nBoth Physical Adapters and Digital Adapters can be defined natively with a custom configuration provided by the developer as illustrated in the dedicated Section: Configurable Physical \u0026amp; Digital Adapters.\n","date":"February 9, 2024","id":6,"permalink":"/docs/guides/digital-adapter/","summary":"The las component that we have to implement to complete our first simple Digital Twin definition through the WLDT library is a Digital Adapter in charge of:","tags":"","title":"Digital Adapter"},{"content":"Now that we have created the main fundamental element of a DT (Physical Adapter, Shadowing Function and Digital Adapter) we can create Class file with a main to create the WLDT Engine with the created components and start the DT.\nCreate a new Java file called DemoDigitalTwin adding the following code:\nWith the following code we now create a new Digital Twin Instance\n// Create the new Digital Twin with its Shadowing Function DigitalTwin digitalTwin = new DigitalTwin(digitalTwinId, new DemoShadowingFunction()); // Physical Adapter with Configuration digitalTwin.addPhysicalAdapter( new DemoPhysicalAdapter( String.format(\u0026#34;%s-%s\u0026#34;, digitalTwinId, \u0026#34;test-physical-adapter\u0026#34;), new DemoPhysicalAdapterConfiguration(), true)); // Digital Adapter with Configuration digitalTwin.addDigitalAdapter( new DemoDigitalAdapter( String.format(\u0026#34;%s-%s\u0026#34;, digitalTwinId, \u0026#34;test-digital-adapter\u0026#34;), new DemoDigitalAdapterConfiguration()) ); DTs cannot be directly run but it should be added to the DigitalTwinEngine in order to be executed through the WLDT Library\n// Create the Digital Twin Engine DigitalTwinEngine digitalTwinEngine = new DigitalTwinEngine(); // Add the Digital Twin to the Engine digitalTwinEngine.addDigitalTwin(digitalTwin); In order to start a DT from the Engine you can:\n// Directly start when you add it passing a second boolean value = true digitalTwinEngine.addDigitalTwin(digitalTwin. true); // Starting the single DT on the engine through its id digitalTwinEngine.startDigitalTwin(DIGITAL_TWIN_ID); // Start all the DTs registered on the engine digitalTwinEngine.startAll(); To stop a single twin or all the twin registered on the engine:\n// Stop a single DT on the engine through its id digitalTwinEngine.stopDigitalTwin(DIGITAL_TWIN_ID); // Stop all the DTs registered on the engine digitalTwinEngine.stopAll(); It is also possible to remove a DT from the Engine with a consequent stop if it is active and the deletion of its reference from the engine:\n// Remove a single DT on the engine through its id digitalTwinEngine.removeDigitalTwin(DIGITAL_TWIN_ID); // Remove all the DTs registered on the engine digitalTwinEngine.removeAll(); The resulting code in our case is:\npublic class DemoDigitalTwin { public static void main(String[] args) { try{ // Create the new Digital Twin DigitalTwin digitalTwin = new DigitalTwin( \u0026#34;test-dt-id\u0026#34;, new DemoShadowingFunction(\u0026#34;test-shadowing-function\u0026#34;) ); //Default Physical and Digital Adapter //digitalTwin.addPhysicalAdapter(new DemoPhysicalAdapter(\u0026#34;test-physical-adapter\u0026#34;)); //digitalTwin.addDigitalAdapter(new DemoDigitalAdapter(\u0026#34;test-digital-adapter\u0026#34;)); //Physical and Digital Adapters with Configuration digitalTwin.addPhysicalAdapter(new DemoConfPhysicalAdapter(\u0026#34;test-physical-adapter\u0026#34;, new DemoPhysicalAdapterConfiguration())); digitalTwin.addDigitalAdapter(new DemoConfDigitalAdapter(\u0026#34;test-digital-adapter\u0026#34;, new DemoDigitalAdapterConfiguration())); // Create the Digital Twin Engine DigitalTwinEngine digitalTwinEngine = new DigitalTwinEngine(); // Add the Digital Twin to the Engine digitalTwinEngine.addDigitalTwin(digitalTwin); // Set a new Event-Logger to a Custom One that we created with the class \u0026#39;DemoEventLogger\u0026#39; WldtEventBus.getInstance().setEventLogger(new DemoEventLogger()); // Start all the DTs registered on the engine digitalTwinEngine.startAll(); }catch (Exception e){ e.printStackTrace(); } } } ","date":"February 9, 2024","id":7,"permalink":"/docs/guides/dt-engine-dt-instance/","summary":"Now that we have created the main fundamental element of a DT (Physical Adapter, Shadowing Function and Digital Adapter) we can create Class file with a main to create the WLDT Engine with the created components and start the DT.","tags":"","title":"DT Engine \u0026 DT Instance"},{"content":"In this demo implementation, we are going to emulate an incoming Digital Action on the Digital Adapter in order to show how it can be handled by the adapter and properly forwarded to the Shadowing Function for validation and the consequent interaction with the Physical Adapter and then with the physical twin.\nIn order to add a demo Digital Action trigger on the Digital Adapter we add the following method to the DemoDigitalAdapter class:\nprivate Runnable emulateIncomingDigitalAction(){ return () -\u0026gt; { try { System.out.println(\u0026#34;Sleeping before Emulating Incoming Digital Action ...\u0026#34;); Thread.sleep(5000); Random random = new Random(); //Emulate the generation on \u0026#39;n\u0026#39; temperature measurements for(int i = 0; i \u0026lt; 10; i++){ //Sleep to emulate sensor measurement Thread.sleep(1000); double randomTemperature = 25.0 + (30.0 - 25.0) * random.nextDouble(); publishDigitalActionWldtEvent(\u0026#34;set-temperature-action-key\u0026#34;, randomTemperature); } } catch (Exception e) { e.printStackTrace(); } }; } This method uses the Digital Adapter internal function denoted as publishDigitalActionWldtEvent(String actionKey, T body) allowing the adapter to send a notification to the DT\u0026rsquo;s Core (and consequently the Shadowing Function) about the arrival of a Digital Action with a specific key and body. In our case the key is set-temperature-action-key as declared in the Physical Adapter and in the PAD and the value is a simple Double with the new temperature value.\nThen we call this method in the following way at the end ot the onDigitalTwinSync(IDigitalTwinState currentDigitalTwinState) method.\n//Start Digital Action Emulation new Thread(emulateIncomingDigitalAction()).start(); Now the Shadowing Function should be updated in order to handle the incoming Action request from the Digital Adapter. In our case the shadowing function does not apply any validation or check and just forward to action to the Physical Adapter in order to be then forwarded to the physical twin. Of course advanced implementation can be introduced for example to validate action, adapt payload and data-formats or to augment functionalities (e.g., trigger multiple physical actions from a single digital request).\nIn our simple demo implementation the updated Shadowing Function method onDigitalActionEvent(DigitalActionWldtEvent\u0026lt;?\u0026gt; digitalActionWldtEvent) results as follows:\n@Override protected void onDigitalActionEvent(DigitalActionWldtEvent\u0026lt;?\u0026gt; digitalActionWldtEvent) { try { this.publishPhysicalAssetActionWldtEvent(digitalActionWldtEvent.getActionKey(), digitalActionWldtEvent.getBody()); } catch (Exception e) { e.printStackTrace(); } } This forwarding of the action triggers the corresponding Physical Adapter method onIncomingPhysicalAction(PhysicalAssetActionWldtEvent\u0026lt;?\u0026gt; physicalAssetActionWldtEvent) that in our case is emulated just with a Log on the console. Also in that case advanced Physical Adapter implementation can be introduced for example to adapt the request from a high-level (and potentially standard) DT action description to the custom requirements of the specific physical twin managed by the adapter.\n@Override public void onIncomingPhysicalAction(PhysicalAssetActionWldtEvent\u0026lt;?\u0026gt; physicalAssetActionWldtEvent) { try{ if(physicalAssetActionWldtEvent != null \u0026amp;\u0026amp; physicalAssetActionWldtEvent.getActionKey().equals(SET_TEMPERATURE_ACTION_KEY) \u0026amp;\u0026amp; physicalAssetActionWldtEvent.getBody() instanceof Double) { System.out.println(\u0026#34;Received Action Request: \u0026#34; + physicalAssetActionWldtEvent.getActionKey() + \u0026#34; with Body: \u0026#34; + physicalAssetActionWldtEvent.getBody()); } else System.err.println(\u0026#34;Wrong Action Received !\u0026#34;); }catch (Exception e){ e.printStackTrace(); } } ","date":"February 9, 2024","id":8,"permalink":"/docs/guides/digital-actions/","summary":"In this demo implementation, we are going to emulate an incoming Digital Action on the Digital Adapter in order to show how it can be handled by the adapter and properly forwarded to the Shadowing Function for validation and the consequent interaction with the Physical Adapter and then with the physical twin.","tags":"","title":"Digital Actions"},{"content":"The WLDT library provides a native method to define Configurable Physical ad Digital Adapters specifying a custom configuration class passed as parameter in the constructor.\nStarting with the Physical Adapter created in the previous example DemoPhysicalAdapter instead of extending the base class PhysicalAdapter we can extend now ConfigurablePhysicalAdapter\u0026lt;C\u0026gt; where C is the name of the that we would like to use as configuration.\nIn our example we can create a simple configuration class called DemoPhysicalAdapterConfiguration where we move the constant variable used to implement the behaviour of our demo physical adapter. The resulting class will be the following:\npublic class DemoPhysicalAdapterConfiguration { private int messageUpdateTime = GlobalKeywords.MESSAGE_UPDATE_TIME; private int messageUpdateNumber = GlobalKeywords.MESSAGE_UPDATE_NUMBER; private double temperatureMinValue = GlobalKeywords.TEMPERATURE_MIN_VALUE; private double temperatureMaxValue = GlobalKeywords.TEMPERATURE_MAX_VALUE; public DemoPhysicalAdapterConfiguration() { } public DemoPhysicalAdapterConfiguration(int messageUpdateTime, int messageUpdateNumber, double temperatureMinValue, double temperatureMaxValue) { this.messageUpdateTime = messageUpdateTime; this.messageUpdateNumber = messageUpdateNumber; this.temperatureMinValue = temperatureMinValue; this.temperatureMaxValue = temperatureMaxValue; } public int getMessageUpdateTime() { return messageUpdateTime; } public void setMessageUpdateTime(int messageUpdateTime) { this.messageUpdateTime = messageUpdateTime; } public int getMessageUpdateNumber() { return messageUpdateNumber; } public void setMessageUpdateNumber(int messageUpdateNumber) { this.messageUpdateNumber = messageUpdateNumber; } public double getTemperatureMinValue() { return temperatureMinValue; } public void setTemperatureMinValue(double temperatureMinValue) { this.temperatureMinValue = temperatureMinValue; } public double getTemperatureMaxValue() { return temperatureMaxValue; } public void setTemperatureMaxValue(double temperatureMaxValue) { this.temperatureMaxValue = temperatureMaxValue; } } Now we can create or update our Physical Adapter extending ConfigurablePhysicalAdapter\u0026lt;DemoPhysicalAdapterConfiguration\u0026gt; as illustrated in the following snippet:\npublic class DemoPhysicalAdapter extends ConfigurablePhysicalAdapter\u0026lt;DemoPhysicalAdapterConfiguration\u0026gt; { [...] } Extending this class also the constructor should be updated getting as a parameter the expected configuration instance. Our constructor will be the following:\npublic DemoConfPhysicalAdapter(String id, DemoPhysicalAdapterConfiguration configuration) { super(id, configuration); } After that change since we removed and moved the used constant values into the new Configuration class we have also to update the deviceEmulation() method having access to the configuration through the method getConfiguration() or this.getConfiguration() directly on the adapter.\nprivate Runnable deviceEmulation(){ return () -\u0026gt; { try { System.out.println(\u0026#34;[DemoPhysicalAdapter] -\u0026gt; Sleeping before Starting Physical Device Emulation ...\u0026#34;); //Sleep 5 seconds to emulate device startup Thread.sleep(10000); System.out.println(\u0026#34;[DemoPhysicalAdapter] -\u0026gt; Starting Physical Device Emulation ...\u0026#34;); //Create a new random object to emulate temperature variations Random r = new Random(); //Publish an initial Event for a normal condition publishPhysicalAssetEventWldtEvent(new PhysicalAssetEventWldtEvent\u0026lt;\u0026gt;(GlobalKeywords.OVERHEATING_EVENT_KEY, \u0026#34;normal\u0026#34;)); //Emulate the generation on \u0026#39;n\u0026#39; temperature measurements for(int i = 0; i \u0026lt; getConfiguration().getMessageUpdateNumber(); i++){ //Sleep to emulate sensor measurement Thread.sleep(getConfiguration().getMessageUpdateTime()); //Update the double randomTemperature = getConfiguration().getTemperatureMinValue() + (getConfiguration().getTemperatureMaxValue() - getConfiguration().getTemperatureMinValue()) * r.nextDouble(); //Create a new event to notify the variation of a Physical Property PhysicalAssetPropertyWldtEvent\u0026lt;Double\u0026gt; newPhysicalPropertyEvent = new PhysicalAssetPropertyWldtEvent\u0026lt;\u0026gt;(GlobalKeywords.TEMPERATURE_PROPERTY_KEY, randomTemperature); //Publish the WLDTEvent associated to the Physical Property Variation publishPhysicalAssetPropertyWldtEvent(newPhysicalPropertyEvent); } //Publish a demo Physical Event associated to a \u0026#39;critical\u0026#39; overheating condition publishPhysicalAssetEventWldtEvent(new PhysicalAssetEventWldtEvent\u0026lt;\u0026gt;(GlobalKeywords.OVERHEATING_EVENT_KEY, \u0026#34;critical\u0026#34;)); } catch (EventBusException | InterruptedException e) { e.printStackTrace(); } }; } A similar approach can be adopted also for the Digital Adapter with the small difference that the base class DigitalAdapter already allow the possibility to specify a configuration. For this reason in the previous example we extended DigitalAdapter\u0026lt;Void\u0026gt; avoiding to specifying a configuration.\nIn this updated version we can create a new DemoDigitalAdapterConfiguration class containing the parameter association to the emulation of the action and then update our adapter to support the new configuration. Our new configuration class will be:\npublic class DemoDigitalAdapterConfiguration { private int sleepTimeMs = GlobalKeywords.ACTION_SLEEP_TIME_MS; private int emulatedActionCount = GlobalKeywords.EMULATED_ACTION_COUNT; private double temperatureMinValue = GlobalKeywords.TEMPERATURE_MIN_VALUE; private double temperatureMaxValue = GlobalKeywords.TEMPERATURE_MAX_VALUE; public DemoDigitalAdapterConfiguration() { } public DemoDigitalAdapterConfiguration(int sleepTimeMs, int emulatedActionCount, double temperatureMinValue, double temperatureMaxValue) { this.sleepTimeMs = sleepTimeMs; this.emulatedActionCount = emulatedActionCount; this.temperatureMinValue = temperatureMinValue; this.temperatureMaxValue = temperatureMaxValue; } public int getSleepTimeMs() { return sleepTimeMs; } public void setSleepTimeMs(int sleepTimeMs) { this.sleepTimeMs = sleepTimeMs; } public int getEmulatedActionCount() { return emulatedActionCount; } public void setEmulatedActionCount(int emulatedActionCount) { this.emulatedActionCount = emulatedActionCount; } public double getTemperatureMinValue() { return temperatureMinValue; } public void setTemperatureMinValue(double temperatureMinValue) { this.temperatureMinValue = temperatureMinValue; } public double getTemperatureMaxValue() { return temperatureMaxValue; } public void setTemperatureMaxValue(double temperatureMaxValue) { this.temperatureMaxValue = temperatureMaxValue; } } After that we can update the declaration of our Digital Adapter and modify its constructor to accept the configuration. The resulting class will be:\npublic class DemoDigitalAdapter extends DigitalAdapter\u0026lt;DemoDigitalAdapterConfiguration\u0026gt; { public DemoDigitalAdapter(String id, DemoDigitalAdapterConfiguration configuration) { super(id, configuration); } [...] } Of course the possibility to have this configuration will allow us to improve the emulateIncomingDigitalAction method in the following way having access to the configuration through the method getConfiguration() or this.getConfiguration() directly on the adapter:\nprivate Runnable emulateIncomingDigitalAction(){ return () -\u0026gt; { try { System.out.println(\u0026#34;[DemoDigitalAdapter] -\u0026gt; Sleeping before Emulating Incoming Digital Action ...\u0026#34;); Thread.sleep(5000); Random random = new Random(); //Emulate the generation on \u0026#39;n\u0026#39; temperature measurements for(int i = 0; i \u0026lt; getConfiguration().getEmulatedActionCount(); i++){ //Sleep to emulate sensor measurement Thread.sleep(getConfiguration().getSleepTimeMs()); double randomTemperature = getConfiguration().getTemperatureMinValue() + (getConfiguration().getTemperatureMaxValue() - getConfiguration().getTemperatureMinValue()) * random.nextDouble(); publishDigitalActionWldtEvent(\u0026#34;set-temperature-action-key\u0026#34;, randomTemperature); } } catch (Exception e) { e.printStackTrace(); } }; } When we have updated both adapters making them configurable we can update our main function in the process that we have previouly device using the updated adapters and passing the configurations:\npublic class DemoDigitalTwin { public static void main(String[] args) { try{ WldtEngine digitalTwinEngine = new WldtEngine(new DemoShadowingFunction(\u0026#34;test-shadowing-function\u0026#34;), \u0026#34;test-digital-twin\u0026#34;); //Default Physical and Digital Adapter //digitalTwinEngine.addPhysicalAdapter(new DemoPhysicalAdapter(\u0026#34;test-physical-adapter\u0026#34;)); //digitalTwinEngine.addDigitalAdapter(new DemoDigitalAdapter(\u0026#34;test-digital-adapter\u0026#34;)); //Physical and Digital Adapters with Configuration digitalTwinEngine.addPhysicalAdapter(new DemoConfPhysicalAdapter(\u0026#34;test-physical-adapter\u0026#34;, new DemoPhysicalAdapterConfiguration())); digitalTwinEngine.addDigitalAdapter(new DemoConfDigitalAdapter(\u0026#34;test-digital-adapter\u0026#34;, new DemoDigitalAdapterConfiguration())); digitalTwinEngine.startLifeCycle(); }catch (Exception e){ e.printStackTrace(); } } } ","date":"February 9, 2024","id":9,"permalink":"/docs/guides/configurable-adapters/","summary":"The WLDT library provides a native method to define Configurable Physical ad Digital Adapters specifying a custom configuration class passed as parameter in the constructor.","tags":"","title":"Configurable Adapters"},{"content":"","date":"February 9, 2024","id":10,"permalink":"/docs/adapters/","summary":"","tags":"","title":"Adapters"},{"content":"The MqttPhysicalAdapter library provides a streamlined solution for efficiently managing physical assets through the MQTT protocol. It offers a range of features, including a versatile builder for effortless configuration of MQTT connections, dedicated classes for handling both incoming and outgoing topics, and a specialized adapter designed for seamless integration with diverse physical assets.\nKey Features:\nBuilder for MQTT Configuration: The library incorporates a flexible builder pattern, enabling users to effortlessly configure the essential parameters of the MQTT connection. This includes specifying the MQTT broker\u0026rsquo;s address, port, and other relevant details to establish a reliable and customizable communication link. Incoming and Outgoing Topic Handling: MqttPhysicalAdapter facilitates the handling of incoming and outgoing topics, crucial for communication between the physical assets and the MQTT broker. The library includes dedicated classes for defining and managing topics, allowing users to efficiently subscribe to incoming data and publish outgoing messages. Adapter for Physical Asset Integration: At the core of the library is a robust adapter designed specifically for integrating with various physical assets. This adapter streamlines the process of connecting and interacting with physical devices, ensuring a smooth and standardized approach to managing asset-related data. In the WLDT library, Physical Adapters has the responsibility to generate and publish the PhysicalAssetDescription (PAD) to describe the capabilities and the characteristics of our object allowing the Shadowing Function to decide how to digitalize its physical counterpart.\nIn the MqttPhysicalAdapter the generation of the PAD (Physical Asset Description) is automatically and internally executed by the adapter itself accordingly to the adapter configuration in terms of MQTT topics and their mapping with DT\u0026rsquo;s properties, events and actions.\nPrerequisites:\nExternal MQTT Broker: The MqttPhysicalAdapter library requires an external MQTT broker for optimal functionality. Users must have access to a reliable MQTT broker to which the adapter can subscribe. This external broker serves as the central communication hub, facilitating the exchange of messages between the adapter and the physical assets. A complete example is provided in the test folder with a complete DT Creation in the TestMain class together with MQTT IoT demo device and a test MQTT consumer.\nWLDT-Core Version Compatibility The correct mapping and compatibility between versions is reported in the following table\nmqtt-physical-adapter wldt-core 0.2.1 wldt-core 0.3.0 0.1.0 ✅ ❌ 0.1.1 ❌ ✅ Installation To use MqttPhysicalAdapter in your Java project, you can include it as a dependency using Maven or Gradle.\nMaven \u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;io.github.wldt\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;mqtt-physical-adapter\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;0.1.1\u0026lt;/version\u0026gt; \u0026lt;/dependency\u0026gt; Gradle implementation \u0026#39;io.github.wldt:mqtt-physical-adapter:0.1.1\u0026#39; Class Structure \u0026amp; Functionalities MqttPhysicalAdapterConfigurationBuilder \u0026amp; Main Methods The MqttPhysicalAdapterConfigurationBuilder is the class used to build the configuration used by the PhysicalAdater and described and implemented through the class MqttPhysicalAdapterConfiguration.\nIn order to create a configuration builder we can use the static method builder() on the MqttPhysicalAdapterConfiguration class:\nMqttPhysicalAdapterConfiguration.builder(); On the builder the available methods that can be used are:\naddPhysicalAssetPropertyAndTopic public \u0026lt;T\u0026gt; MqttPhysicalAdapterConfigurationBuilder addPhysicalAssetPropertyAndTopic(String propertyKey, T initialValue, String topic, Function\u0026lt;String, T\u0026gt; topicFunction) throws MqttPhysicalAdapterConfigurationException Adds a physical asset property and its corresponding MQTT topic to the configuration.\nType Parameter T: The type of the property. propertyKey: The key of the property. initialValue: The initial value of the property. topic: The MQTT topic associated with the property. topicFunction: A function to parse the MQTT topic payload into the property type. Returns: The updated MqttPhysicalAdapterConfigurationBuilder.\nThrows: MqttPhysicalAdapterConfigurationException - If there is a configuration error.\naddPhysicalAssetActionAndTopic public \u0026lt;T\u0026gt; MqttPhysicalAdapterConfigurationBuilder addPhysicalAssetActionAndTopic(String actionKey, String type, String contentType, String topic, Function\u0026lt;T, String\u0026gt; topicFunction) throws MqttPhysicalAdapterConfigurationException Adds a physical asset action and its corresponding MQTT topic to the configuration.\nType Parameter T: The type of the action payload. actionKey: The key of the action. type: The type of the action. contentType: The content type of the action. topic: The MQTT topic associated with the action. topicFunction: A function to convert the action payload into the MQTT topic payload. Returns: The updated MqttPhysicalAdapterConfigurationBuilder.\nThrows: MqttPhysicalAdapterConfigurationException - If there is a configuration error.\naddPhysicalAssetEventAndTopic public \u0026lt;T\u0026gt; MqttPhysicalAdapterConfigurationBuilder addPhysicalAssetEventAndTopic(String eventKey, String type, String topic, Function\u0026lt;String, T\u0026gt; topicFunction) throws MqttPhysicalAdapterConfigurationException Adds a physical asset event and its corresponding MQTT topic to the configuration.\nType Parameter T: The type of the event payload. eventKey: The key of the event. type: The type of the event. topic: The MQTT topic associated with the event. topicFunction: A function to parse the MQTT topic payload into the event payload type. Returns: The updated MqttPhysicalAdapterConfigurationBuilder.\nThrows: MqttPhysicalAdapterConfigurationException - If there is a configuration error.\naddIncomingTopic public MqttPhysicalAdapterConfigurationBuilder addIncomingTopic(DigitalTwinIncomingTopic topic, List\u0026lt;PhysicalAssetProperty\u0026lt;?\u0026gt;\u0026gt; properties, List\u0026lt;PhysicalAssetEvent\u0026gt; events) throws MqttPhysicalAdapterConfigurationException This method is used when multiple properties or events can be associated to a single MQTT topic on the physical device. It adds a DigitalTwinIncomingTopic describing the topic where the DT will receive the data along with its related lists of properties and events associated to that topic.\ntopic: The DigitalTwinIncomingTopic to be added. properties: The list of related physical asset properties. events: The list of related physical asset events. Returns: The updated MqttPhysicalAdapterConfigurationBuilder.\nThrows: MqttPhysicalAdapterConfigurationException - If there is a configuration error.\naddOutgoingTopic public MqttPhysicalAdapterConfigurationBuilder addOutgoingTopic(String actionKey, String type, String contentType, DigitalTwinOutgoingTopic topic) throws MqttPhysicalAdapterConfigurationException Adds a DigitalTwinOutgoingTopic to the configuration.\nactionKey: The key of the associated action. type: The type of the associated action. contentType: The content type of the associated action. topic: The DigitalTwinOutgoingTopic to be added. Returns: The updated MqttPhysicalAdapterConfigurationBuilder.\nThrows: MqttPhysicalAdapterConfigurationException - If there is a configuration error.\nAdditional Methods setConnectionTimeout(Integer connectionTimeout): Sets the connection timeout for the MQTT client. Returns the builder for method chaining. Throws MqttPhysicalAdapterConfigurationException if the provided timeout is invalid. setCleanSessionFlag(boolean cleanSession): Sets the clean session flag for the MQTT client. Returns the builder for method chaining. setAutomaticReconnectFlag(boolean automaticReconnect): Sets the automatic reconnect flag for the MQTT client. Returns the builder for method chaining. setMqttClientPersistence(MqttClientPersistence persistence): Sets the persistence for the MQTT client. Returns the builder for method chaining. Throws MqttPhysicalAdapterConfigurationException if the provided persistence is null. build(): Builds and returns the finalized MqttPhysicalAdapterConfiguration object. Throws MqttPhysicalAdapterConfigurationException if the configuration is incomplete or invalid. MqttPhysicalAdapter The MqttPhysicalAdapter class is the core component for interacting with physical assets. Instantiate it with a unique ID and the configuration. It extends the default WLDT Library PhysicalAdapter implementing all the functionalities to automatically interact with an MQTT physical device following the specifications and details provided in the MqttPhysicalAdapterConfiguration and built using MqttPhysicalAdapterConfigurationBuilder.\nAn example of its creation is:\nMqttPhysicalAdapter mqttPhysicalAdapter = new MqttPhysicalAdapter(\u0026#34;uniqueId\u0026#34;, configuration); Integrated Example This example demonstrates the integration of a MqttPhysicalAdapter within a Digital Twin setup, where multiple adapters (including a console adapter) are added to a Digital Twin, and the overall system is managed by a DigitalTwinEngine.\n// Create a Digital Twin with a default shadowing function DigitalTwin digitalTwin = new DigitalTwin(\u0026#34;mqtt-digital-twin\u0026#34;, new DefaultShadowingFunction()); // Create an instance of ConsoleDigitalAdapter ConsoleDigitalAdapter consoleDigitalAdapter = new ConsoleDigitalAdapter(); // Create an instance of MqttPhysicalAdapterConfiguration MqttPhysicalAdapterConfiguration config = MqttPhysicalAdapterConfiguration.builder(\u0026#34;127.0.0.1\u0026#34;, 1883) .addPhysicalAssetPropertyAndTopic(\u0026#34;intensity\u0026#34;, 0, \u0026#34;sensor/intensity\u0026#34;, Integer::parseInt) .addIncomingTopic(new DigitalTwinIncomingTopic(\u0026#34;sensor/state\u0026#34;, getSensorStateFunction()), createIncomingTopicRelatedPropertyList(), new ArrayList\u0026lt;\u0026gt;()) .addPhysicalAssetEventAndTopic(\u0026#34;overheating\u0026#34;, \u0026#34;text/plain\u0026#34;, \u0026#34;sensor/overheating\u0026#34;, Function.identity()) .addPhysicalAssetActionAndTopic(\u0026#34;switch-off\u0026#34;, \u0026#34;sensor.actuation\u0026#34;, \u0026#34;text/plain\u0026#34;, \u0026#34;sensor/actions/switch\u0026#34;, actionBody -\u0026gt; \u0026#34;switch\u0026#34; + actionBody) .build(); // Create an instance of the MQTT Physical Adapter using the defined configuration MqttPhysicalAdapter mqttPhysicalAdapter = new MqttPhysicalAdapter(\u0026#34;test-mqtt-pa\u0026#34;, config); // Add both Digital and Physical Adapters to the Digital Twin digitalTwin.addDigitalAdapter(consoleDigitalAdapter); digitalTwin.addPhysicalAdapter(mqttPhysicalAdapter); // Create the Digital Twin Engine DigitalTwinEngine digitalTwinEngine = new DigitalTwinEngine(); // Add the Digital Twin to the Engine digitalTwinEngine.addDigitalTwin(digitalTwin); // Start all the Digital Twins registered on the engine digitalTwinEngine.startAll(); In this example the createIncomingTopicRelatedPropertyList() used to map properties and events associated to a single topic is the following:\nprivate static List\u0026lt;PhysicalAssetProperty\u0026lt;?\u0026gt;\u0026gt; createIncomingTopicRelatedPropertyList(){ List\u0026lt;PhysicalAssetProperty\u0026lt;?\u0026gt;\u0026gt; properties = new ArrayList\u0026lt;\u0026gt;(); properties.add(new PhysicalAssetProperty\u0026lt;\u0026gt;(\u0026#34;temperature\u0026#34;, 0)); properties.add(new PhysicalAssetProperty\u0026lt;\u0026gt;(\u0026#34;humidity\u0026#34;, 0)); return properties; } This information are used by the adapter to build the PAD describe the capabilities and the characteristics of our object allowing the Shadowing Function to decide how to digitalize its physical counterpart.\n","date":"February 9, 2024","id":11,"permalink":"/docs/adapters/mqtt-physical-adapter/","summary":"The MqttPhysicalAdapter library provides a streamlined solution for efficiently managing physical assets through the MQTT protocol. It offers a range of features, including a versatile builder for effortless configuration of MQTT connections, dedicated classes for handling both incoming and outgoing topics, and a specialized adapter designed for seamless integration with diverse physical assets.","tags":"","title":"MQTT Physical Adapter"},{"content":"","date":"February 9, 2024","id":12,"permalink":"/docs/change-logs/","summary":"","tags":"","title":"Change Logs"},{"content":"The MqttDigitalAdapter,\nMqttDigitalAdapterConfiguration, and MqttDigitalAdapterConfigurationBuilder classes and guides you through using these classes to set up an MQTT Digital Adapter within WLDT.\nRequires an external MQTT broker to send messages.\nMain functionalities are:\nManages the interaction between the Digital Twin and external systems. Handles state updates, events, and property changes. Dynamic configuration of the MqttDigitalAdapter with broker details, topics, and other settings. Allows customization of data and payload management associated to MQTT topics for properties, events, and actions. Prerequisites:\nExternal MQTT Broker: The MqttDigitalAdapter library requires an external MQTT broker for optimal functionality and communication. Users must have access to a reliable MQTT broker to which the adapter can subscribe and publish. This external broker serves as the central communication hub, facilitating the exchange of messages between the adapter and digital applications A complete example is provided in the test folder with a complete DT Creation in the TestMain class together with MQTT IoT demo device and a test MQTT consumer.\nWLDT-Core Version Compatibility The correct mapping and compatibility between versions is reported in the following table\nmqtt-digital-adapter wldt-core 0.2.1 wldt-core 0.3.0 0.1.0 ✅ ❌ 0.1.1 ❌ ✅ Installation To use MqttDigitalAdapter in your Java project, you can include it as a dependency using Maven or Gradle.\nMaven \u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;io.github.wldt\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;mqtt-digital-adapter\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;0.1.1\u0026lt;/version\u0026gt; \u0026lt;/dependency\u0026gt; Gradle implementation \u0026#39;io.github.wldt:mqtt-digital-adapter:0.1.1\u0026#39; Class Structure \u0026amp; Functionalities MqttDigitalAdapterConfiguration MqttDigitalAdapterConfiguration is a crucial class in the Digital Twin library, allowing developers to configure the behavior of the MQTT Digital Adapter. It provides a flexible and customizable way to set up MQTT communication parameters, topics for properties, events, and actions.\nKey functionalities and exposed capabilities:\nBroker Configuration brokerAddress and brokerPort: Set the MQTT broker\u0026rsquo;s address and port. username and password: Set optional credentials for connecting to the broker. Client Configuration clientId: Unique identifier for the MQTT client. cleanSessionFlag: Flag indicating whether the client starts with a clean session. connectionTimeout: Maximum time to wait for the connection to the MQTT broker. MQTT Client Persistence persistence: Configurable persistence for the MQTT client\u0026rsquo;s data. Reconnect Configuration: automaticReconnectFlag: Flag enabling or disabling automatic reconnection. Topic Configuration: propertyUpdateTopics: Map of property update topics. eventNotificationTopics: Map of event notification topics. actionIncomingTopics: Map of incoming action topics. Builder Methods: builder: Static method to start building a new configuration. addPropertyTopic: Add a property topic with specified parameters. addEventNotificationTopic: Add an event notification topic. addActionTopic: Add an action topic. setConnectionTimeout: Set the connection timeout. setCleanSessionFlag: Set the clean session flag. setAutomaticReconnectFlag: Set the automatic reconnect flag. setMqttClientPersistence: Set the MQTT client persistence. build: Finalize the configuration and build the instance. MqttDigitalAdapterConfigurationBuilder The MqttDigitalAdapterConfigurationBuilder is a powerful tool designed to simplify the process of constructing configurations for the MQTT Digital Adapter in the Digital Twin library. It offers a fluent and intuitive interface, allowing developers to define various aspects of MQTT communication seamlessly.\nBuilder Instantiation The builder is instantiated by providing essential parameters like brokerAddress and brokerPort or including an optional clientId\nMqttDigitalAdapterConfigurationBuilder builder = MqttDigitalAdapterConfiguration.builder(\u0026#34;127.0.0.1\u0026#34;, 1883); Adding Property Topics Developers can add property topics with specific configurations, such as the key, topic, QoS level, and a function to convert property values to payload.\nbuilder.addPropertyTopic(\u0026#34;energy\u0026#34;, \u0026#34;dummy/properties/energy\u0026#34;, MqttQosLevel.MQTT_QOS_0, value -\u0026gt; String.valueOf(((Double)value).intValue())); Adding Event Notification Topics Event notification topics are easily added, including event keys, topics, QoS levels, and payload conversion functions.\nbuilder.addEventNotificationTopic(\u0026#34;overheating\u0026#34;, \u0026#34;dummy/events/overheating/notifications\u0026#34;, MqttQosLevel.MQTT_QOS_0, Object::toString); Adding Action Topics Developers can include action topics with key, topic, and a function to convert the payload to the desired action.\nbuilder.addActionTopic(\u0026#34;switch_off\u0026#34;, \u0026#34;app/actions/switch-off\u0026#34;, msg -\u0026gt; \u0026#34;OFF\u0026#34;); Connection Options Developers can set the connection timeout for the MQTT client.\nbuilder.setConnectionTimeout(30); The clean session flag can be configured based on the desired behavior.\nbuilder.setCleanSessionFlag(true); Developers can specify whether the MQTT client should automatically reconnect in case of a connection failure.\nbuilder.setAutomaticReconnectFlag(true); The builder allows setting a custom MQTT client persistence, such as an in-memory persistence or a file-based one.\nbuilder.setMqttClientPersistence(new MemoryPersistence()); Building Configuration The final configuration is built using the build method.\nMqttDigitalAdapterConfiguration configuration = builder.build(); MqttDigitalAdapter MqttDigitalAdapter extends DigitalAdapter and specializes in MQTT communication for Digital Twin instances. It handles the publication of state updates, events, and property changes over MQTT. This class facilitates seamless integration with MQTT-enabled systems.\nIt uses the information defined and provided in the `` to handle the communication both with the DT Core and external application interested to interact with the DT through the MQTT protocol.\nHere\u0026rsquo;s a basic example illustrating how to use MqttDigitalAdapter:\n// Create a Digital Twin instance DigitalTwin digitalTwin = new DigitalTwin(\u0026#34;my-digital-twin\u0026#34;, new DefaultShadowingFunction()); // Add a Physical Adapter to the DT [...] // Build the MQTT Digital Adapter Configuration MqttDigitalAdapterConfiguration configuration = MqttDigitalAdapterConfiguration.builder(\u0026#34;127.0.0.1\u0026#34;, 1883) .addPropertyTopic(\u0026#34;energy\u0026#34;, \u0026#34;dummy/properties/energy\u0026#34;, MqttQosLevel.MQTT_QOS_0, value -\u0026gt; String.valueOf(((Double)value).intValue())) .addActionTopic(\u0026#34;switch_off\u0026#34;, \u0026#34;app/actions/switch-off\u0026#34;, msg -\u0026gt; \u0026#34;OFF\u0026#34;) .build(); // Add the MQTT Digital Adapter to the Digital Twin digitalTwin.addDigitalAdapter(new MqttDigitalAdapter(\u0026#34;mqtt-da\u0026#34;, configuration)); // Create the Digital Twin Engine and start the simulation DigitalTwinEngine digitalTwinEngine = new DigitalTwinEngine(); digitalTwinEngine.addDigitalTwin(digitalTwin); digitalTwinEngine.startAll(); ","date":"February 9, 2024","id":13,"permalink":"/docs/adapters/mqtt-digital-adapter/","summary":"The MqttDigitalAdapter,\nMqttDigitalAdapterConfiguration, and MqttDigitalAdapterConfigurationBuilder classes and guides you through using these classes to set up an MQTT Digital Adapter within WLDT.","tags":"","title":"MQTT Digital Adapter"},{"content":"Digital Adapters The following methods have been discontinued and removed from the DigitalAdapter class: onStateChangePropertyCreated onStateChangePropertyUpdated onStateChangePropertyDeleted onStatePropertyUpdated onStatePropertyDeleted onStateChangeActionEnabled onStateChangeActionUpdated onStateChangeActionDisabled onStateChangeEventRegistered onStateChangeEventRegistrationUpdated onStateChangeEventUnregistered onStateChangeRelationshipInstanceDeleted onStateChangeRelationshipDeleted onStateChangeRelationshipInstanceCreated onStateChangeRelationshipCreated onDigitalTwinStateEventNotificationReceived The Signature of the following methods have been changed: onDigitalTwinSync(IDigitalTwinState currentDigitalTwinState) -\u0026gt; onDigitalTwinSync(DigitalTwinState currentDigitalTwinState) onDigitalTwinUnSync(IDigitalTwinState currentDigitalTwinState) -\u0026gt; onDigitalTwinUnSync(DigitalTwinState currentDigitalTwinState) New methods that have been added are: onStateUpdate(DigitalTwinState newDigitalTwinState, DigitalTwinState previousDigitalTwinState, ArrayList\u0026lt;DigitalTwinStateChange\u0026gt; digitalTwinStateChangeList) onEventNotificationReceived(DigitalTwinStateEventNotification\u0026lt;?\u0026gt; digitalTwinStateEventNotification) For additional details about Digital Adapters check Sub Section [[Change Log - v.0.3.0#Digital Adapter| Digital Adapters]] Shadowing Function ShadowingModelFunction is now ShadowingFunction this.digitalTwinState is not directly accessible anymore and it is wrapped through the DigitalTwinStateManager using the variable digitalTwinStateManager (see next descriptions and changes) The method addRelationshipInstance now take only one parameter that is the DigitalTwinStateRelationshipInstance The same change for example should be applied in the point of the code where the Shadowing Function receive a variation from the Physical world through a target adapter and the callback method onPhysicalAssetPropertyVariation(...) When the Shadowing Function has to compute the new DT State it can now work with the following method to handle DT State Transition: this.digitalTwinStateManager.startStateTransaction() DT State variation methods such as: digitalTwinStateManager.createProperty() digitalTwinStateManager.updateProperty() digitalTwinStateManager.updatePropertyValue() digitalTwinStateManager.deleteProperty() digitalTwinStateManager.enableAction() digitalTwinStateManager.updateAction() digitalTwinStateManager.disableAction() digitalTwinStateManager.registerEvent() digitalTwinStateManager.updateRegisteredEvent() digitalTwinStateManager.unRegisterEvent() digitalTwinStateManager.createRelationship() digitalTwinStateManager.addRelationshipInstance() digitalTwinStateManager.deleteRelationship() digitalTwinStateManager.deleteRelationshipInstance() At the end the transaction can be committed using the method: digitalTwinStateManager.commitStateTransaction() The method notifyDigitalTwinStateEvent is now available through the digitalTwinStateManager Additional Details associated to Shadowing Function Migration can be found in the dedicated section [[Change Log - v.0.3.0#Shadowing Function Changes | Shadowing Function Changes]] WLDT Engine \u0026amp; DT Creation WldtEngine is now DigitalTwin and model and structure a single Digital Twin and takes the following parameters: String digitalTwinId ShadowingFunction shadowingFunction The startLifeCycle has been removed from the DigitalTwin (previously WLDT Engine) and now DigitalTwinEngine should be used to start twins Once a new Digital Twin has been create it has to be added to the DigitalTwinEngine DigitalTwinEngine has dedicated method to start and stop twins such as: startAll() startDigitalTwin(\u0026lt;DIGITAL_TWIN_ID\u0026gt;); stopAll() digitalTwinEngine.stopDigitalTwin(\u0026lt;DIGITAL_TWIN_ID\u0026gt;); Digital Twin \u0026amp; Digital Twin Engine With the following code we now create a new Digital Twin Instance\n// Create the new Digital Twin with its Shadowing Function DigitalTwin digitalTwin = new DigitalTwin(digitalTwinId, new DemoShadowingFunction()); // Physical Adapter with Configuration digitalTwin.addPhysicalAdapter( new DemoPhysicalAdapter( String.format(\u0026#34;%s-%s\u0026#34;, digitalTwinId, \u0026#34;test-physical-adapter\u0026#34;), new DemoPhysicalAdapterConfiguration(), true)); // Digital Adapter with Configuration digitalTwin.addDigitalAdapter( new DemoDigitalAdapter( String.format(\u0026#34;%s-%s\u0026#34;, digitalTwinId, \u0026#34;test-digital-adapter\u0026#34;), new DemoDigitalAdapterConfiguration()) ); In the new version the DT cannot be directly run but it should be added to the DigitalTwinEngine in order to be executed through the WLDT Library\n// Create the Digital Twin Engine DigitalTwinEngine digitalTwinEngine = new DigitalTwinEngine(); // Add the Digital Twin to the Engine digitalTwinEngine.addDigitalTwin(digitalTwin); In order to start a DT from the Engine you can:\n// Directly start when you add it passing a second boolean value = true digitalTwinEngine.addDigitalTwin(digitalTwin. true); // Starting the single DT on the engine through its id digitalTwinEngine.startDigitalTwin(DIGITAL_TWIN_ID); // Start all the DTs registered on the engine digitalTwinEngine.startAll(); To stop a single twin or all the twin registered on the engine:\n// Stop a single DT on the engine through its id digitalTwinEngine.stopDigitalTwin(DIGITAL_TWIN_ID); // Stop all the DTs registered on the engine digitalTwinEngine.stopAll(); It is also possible to remove a DT from the Engine with a consequent stop if it is active and the deletion of its reference from the engine:\n// Remove a single DT on the engine through its id digitalTwinEngine.removeDigitalTwin(DIGITAL_TWIN_ID); // Remove all the DTs registered on the engine digitalTwinEngine.removeAll(); Digital Twin State DT State now has the reference timestamp representing the evaluation instant of the digital twin state, this timestamp is computed through the DigitalTwinStateManager and cannot manually set by the developer The information available on the DT State are: properties: List of Properties with their values (if available) actions: List of Actions that can be called on the DT events: List of Events that can be generated by the DT relationships: List of Relationships and their instances (if available) evaluationInstant: The timestamp representing the evaluation instant of the DT state Available main methods on that class instance are: Properties:\n- getProperty(String propertyKey): Retrieves if present the target DigitalTwinStateProperty by Key\n- containsProperty(String propertyKey): Checks if a target Property Key is already available in the current Digital Twin\u0026rsquo;s State\n- getPropertyList(): Loads the list of available Properties (described by the class DigitalTwinStateProperty) available on the Digital Twin\u0026rsquo;s State\n- createProperty(DigitalTwinStateProperty\u0026lt;?\u0026gt; dtStateProperty): Allows the creation of a new Property on the Digital Twin\u0026rsquo;s State through the class DigitalTwinStateProperty\n- readProperty(String propertyKey): Retrieves if present the target DigitalTwinStateProperty by Key\n- updateProperty(DigitalTwinStateProperty\u0026lt;?\u0026gt; dtStateProperty): Updates the target property using the DigitalTwinStateProperty and the associated Property Key field\n- deleteProperty(String propertyKey): Deletes the target property identified by the specified key Actions:\n- containsAction(String actionKey): Checks if a Digital Twin State Action with the specified key is correctly registered\n- getAction(String actionKey): Loads the target DigitalTwinStateAction by key\n- getActionList(): Gets the list of available Actions registered on the Digital Twin\u0026rsquo;s State\n- enableAction(DigitalTwinStateAction digitalTwinStateAction): Enables and registers the target Action described through an instance of the DigitalTwinStateAction class\n- updateAction(DigitalTwinStateAction digitalTwinStateAction): Update the already registered target Action described through an instance of the DigitalTwinStateAction class\n- disableAction(String actionKey): Disables and unregisters the target Action described through an instance of the DigitalTwinStateAction class Events:\n- containsEvent(String eventKey): Check if a Digital Twin State Event with the specified key is correctly registered\n- getEvent(String eventKey): Return the description of a registered Digital Twin State Event according to its Key\n- getEventList(): Return the list of existing and registered Digital Twin State Events\n- registerEvent(DigitalTwinStateEvent digitalTwinStateEvent): Register a new Digital Twin State Event\n- updateRegisteredEvent(DigitalTwinStateEvent digitalTwinStateEvent): Update the registration and signature of an existing Digital Twin State Event\n- unRegisterEvent(String eventKey): Un-register a Digital Twin State Event\n- notifyDigitalTwinStateEvent(DigitalTwinStateEventNotification\u0026lt;?\u0026gt; digitalTwinStateEventNotification): Method to notify the occurrence of the target Digital Twin State Event Relationships:\n- containsRelationship(String relationshipName): Checks if a Relationship Name is already available in the current Digital Twin\u0026rsquo;s State\n- createRelationship(DigitalTwinStateRelationship\u0026lt;?\u0026gt; relationship): Creates a new Relationships (described by the class DigitalTwinStateRelationship) in the Digital Twin\u0026rsquo;s State\n- addRelationshipInstance(String name, DigitalTwinStateRelationshipInstance\u0026lt;?\u0026gt; instance): Adds a new Relationship instance described through the class DigitalTwinStateRelationshipInstance and identified through its name\n- getRelationshipList(): Loads the list of existing relationships on the Digital Twin\u0026rsquo;s State through a list of DigitalTwinStateRelationship\n- getRelationship(String name): Gets a target Relationship identified through its name and described through the class DigitalTwinStateRelationship\n- deleteRelationship(String name): Deletes a target Relationship identified through its name\n- deleteRelationshipInstance(String relationshipName, String instanceKey): Deletes the target Relationship Instance using relationship name and instance Key Digital Twin State Manager The DigitalTwinStateManager is a Java class that serves as the default implementation of the IDigitalTwinStateManager interface within the White Label Digital Twin Java Framework (whitelabel-digitaltwin). This class allows developers to manage the state of a digital twin, including properties, actions, events, and relationships.\nFeatures State Management: Handles the creation, update, and deletion of properties, actions, events, and relationships associated with the digital twin state. Transaction Support: Allows developers to start, commit, or rollback transactions to manage changes to the digital twin state. Event Notification: Notifies listeners about updates to the digital twin state through the WLDT event bus. When the Shadowing Function has to compute the new DT State it can now work with the following method to handle DT State Transition: - Start the DT State Transaction: startStateTransaction() - DT State variation methods such as: - createProperty() - updateProperty()\n- updatePropertyValue() - deleteProperty() - enableAction() - updateAction() - disableAction() - registerEvent() - updateRegisteredEvent() - unRegisterEvent() - createRelationship() - addRelationshipInstance() - deleteRelationship() - deleteRelationshipInstance()\nAt the end the transaction can be committed using the method: commitStateTransaction()\nUsage To use the DigitalTwinStateManager within your digital twin implementation:\nInitialization: Create an instance of the DigitalTwinStateManager. DigitalTwinStateManager digitalTwinStateManager = new DigitalTwinStateManager(); State Transaction:\nStart a new transaction using startStateTransaction() to manage changes. Make changes to the digital twin state. Commit the transaction using commitStateTransaction() to apply the changes. digitalTwinStateManager.startStateTransaction(); // Make changes to properties, actions, events, or relationships // [...] digitalTwinStateManager.commitStateTransaction(); Event Notification:\nDT State Updates after a commit action are automatically notified to Digital Adapter by the Manager Once an event incoming from the physical or generated by the DT itself is handled by the Shadowing Function, the developer can use notifyDigitalTwinStateUpdate to notify Digital Adapter listening about events variations. // Notify a specific event notification digitalTwinStateManager.notifyDigitalTwinStateEvent(digitalTwinStateEventNotification); Property, Action, Event, Relationship Management:\nCreate, update, or delete properties, actions, events, or relationships as needed. // Begin Digital Twin State Transaction digitalTwinStateManager.startStateTransaction(); // Create a new property digitalTwinStateManager.createProperty(dtStateProperty); // Update an existing property digitalTwinStateManager.updateProperty(dtStateProperty); // Delete a property digitalTwinStateManager.deleteProperty(propertyKey);` // Commit DT State Update to apply all the changes and notify the Digital Adapters and other listeners about the variation digitalTwinStateManager.commitStateTransaction(); Exception Handling The class throws WldtDigitalTwinStateException to indicate errors related to digital twin state management. Proper exception handling is advised to manage potential errors during state transactions. Shadowing Function Changes Now that the DT State is managed through the DigitalTwinStateManager class all the changes and variation should be applied on the DT ShadowingFunction using the previously presented transaction management and the correct call of methods startStateTransaction() and commitStateTransaction().\nHere there is an example of the change with a simple and demo shadowing function on callback onDigitalTwinBound:\n@Override protected void onDigitalTwinBound(Map\u0026lt;String, PhysicalAssetDescription\u0026gt; adaptersPhysicalAssetDescriptionMap) { try{ // NEW -\u0026gt; Start DT State Change Transaction this.digitalTwinStateManager.startStateTransaction(); for(Map.Entry\u0026lt;String, PhysicalAssetDescription\u0026gt; entry : adaptersPhysicalAssetDescriptionMap.entrySet()){ String adapterId = entry.getKey(); PhysicalAssetDescription physicalAssetDescription = entry.getValue(); //In that simple case the Digital Twin shadow all the properties and actions available in the physical asset for(PhysicalAssetProperty\u0026lt;?\u0026gt; p : physicalAssetDescription.getProperties()) this.digitalTwinStateManager.createProperty(new DigitalTwinStateProperty\u0026lt;\u0026gt;(p.getKey(), p.getInitialValue())); for(PhysicalAssetAction a : physicalAssetDescription.getActions()) this.digitalTwinStateManager.enableAction(new DigitalTwinStateAction(a.getKey(), a.getType(), a.getContentType())); for(PhysicalAssetEvent e: physicalAssetDescription.getEvents()) this.digitalTwinStateManager.registerEvent(new DigitalTwinStateEvent(e.getKey(), physicalAssetEvent.getType())); } // NEW -\u0026gt; Commit DT State Change Transaction to apply the changes on the DT State and notify about the change this.digitalTwinStateManager.commitStateTransaction(); //Observer Target Physical Properties for(Map.Entry\u0026lt;String, PhysicalAssetDescription\u0026gt; entry : adaptersPhysicalAssetDescriptionMap.entrySet()){ [...] } //Observe all the target available Physical Asset Events for each Adapter for(Map.Entry\u0026lt;String, PhysicalAssetDescription\u0026gt; entry : adaptersPhysicalAssetDescriptionMap.entrySet()){ [...] } // Observer for Incoming Digital Actions observeDigitalActionEvents(); //Notify Shadowing Completed notifyShadowingSync(); }catch (Exception e){ e.printStackTrace(); } } The same change for example should be applied in the point of the code where the Shadowing Function receive a variation from the Physical world through a target adapter and the callback method onPhysicalAssetPropertyVariation(...)\n@Override protected void onPhysicalAssetPropertyVariation(PhysicalAssetPropertyWldtEvent\u0026lt;?\u0026gt; physicalPropertyEventMessage) { try { if(physicalPropertyEventMessage != null \u0026amp;\u0026amp; getPhysicalEventsFilter().contains(physicalPropertyEventMessage.getType())){ if(physicalPropertyEventMessage.getPhysicalPropertyId().equals(TestPhysicalAdapter.SWITCH_PROPERTY_KEY) \u0026amp;\u0026amp; physicalPropertyEventMessage.getBody() instanceof String){ [...] } else{ //Update Digital Twin State //NEW -\u0026gt; Start State Transaction this.digitalTwinStateManager.startStateTransaction(); // Update State Property Value this.digitalTwinStateManager.updateProperty( new DigitalTwinStateProperty\u0026lt;\u0026gt;( physicalPropertyEventMessage.getPhysicalPropertyId(), physicalPropertyEventMessage.getBody())); //NEW -\u0026gt; Commit State Transaction this.digitalTwinStateManager.commitStateTransaction(); } } else logger.error(\u0026#34;WRONG Physical Event Message Received !\u0026#34;); }catch (Exception e){ e.printStackTrace(); } } Digital Adapter The Digital Adapter base class has been significantly extended and improved with respect to the previous version. In this new Version notifications that are received by the Adapter from the the DT core belongs to the following categories:\nDigital Twin State Update through the method onStateUpdate(...) providing information about the new state of the Digital Twin, the previous state, and a list of changes that occurred between these two states. In the previous version each variation of a property, relationships, actions or events were notified. In the new version only a committed DT\u0026rsquo;State variation is notified to listeners. Event Notifications through the method onEventNotificationReceived(...) whenever there is a notification about an event related to the Digital Twin\u0026rsquo;s state coming from the physical world, generated by the twin and processed by the Shadowing Function. For example in the DT State we can have the declaration of the over-heating-alert structured and received in the DT State while the effective occurrence of the event and the associated notification is notified through this dedicated callback The onStateUpdate method is an abstract method that must be implemented by any class extending the DigitalAdapter class. This method is called whenever there is an update to the Digital Twin\u0026rsquo;s state. It provides information about the new state of the Digital Twin, the previous state, and a list of changes that occurred between these two states.\nHere is an explanation of the parameters:\nnewDigitalTwinState: This parameter represents the updated state of the Digital Twin. It is an instance of the DigitalTwinState class, which encapsulates the current state information.\npreviousDigitalTwinState: This parameter represents the state of the Digital Twin before the update. It is also an instance of the DigitalTwinState class.\ndigitalTwinStateChangeList: This parameter is an ArrayList containing DigitalTwinStateChange objects. Each DigitalTwinStateChange object encapsulates information about a specific change that occurred between the previous and new states. It includes details such as the property or aspect of the state that changed, the previous value, and the new value.\nThe DT State is automatically monitored by each Digital Adapter while for the Events potentially generated by the DT can be observed by each adapter using:\nobserveAllDigitalTwinEventsNotifications: Enable the observation of available Digital Twin State Events Notifications. unObserveAllDigitalTwinEventsNotifications: Cancel the observation of Digital Twin State Events Notifications observeDigitalTwinEventsNotifications: Enable the observation of the notification associated to a specific list of Digital Twin State events. With respect to event a notification contains the new associated value unObserveDigitalTwinEventsNotifications: Cancel the observation of a target list of properties observeDigitalTwinEventNotification: Enable the observation of the notification associated to a single Digital Twin State event. With respect to event a notification contains the new associated value unObserveDigitalTwinEventNotification: Cancel the observation of a single target event DigitalTwinStateChange Class DigitalTwinStateChange Class\nThe DigitalTwinStateChange class is a representation of a change that occurred in the state of a Digital Twin. It encapsulates information about the type of operation, the resource type, and the affected resource within the Digital Twin.\nEnums:\nOperation: Enumerates different types of operations that can be performed on a Digital Twin state. The possible operations are: OPERATION_UPDATE: Represents an update operation on a resource. OPERATION_UPDATE_VALUE: Represents an update operation specifically on the value of a resource. OPERATION_ADD: Represents an addition operation of a new resource. OPERATION_REMOVE: Represents a removal operation of an existing resource. ResourceType: Enumerates different types of resources within a Digital Twin. The possible resource types are: PROPERTY: Represents a property of the Digital Twin. PROPERTY_VALUE: Represents the value of a property within the Digital Twin. EVENT: Represents an event associated with the Digital Twin. ACTION: Represents an action that can be performed on the Digital Twin. RELATIONSHIP: Represents a relationship between different components of the Digital Twin. RELATIONSHIP_INSTANCE: Represents an instance of a relationship. Fields:\noperation: Indicates the type of operation performed on the Digital Twin state (e.g., update, add, remove). resourceType: Represents the type of resource affected by the change (e.g., property, event, relationship). resource: The specific resource that has undergone the change, represented by an instance of the DigitalTwinStateResource class. Available type of DigitalTwinStateResource are:\nDigitalTwinStateProperty\u0026lt;T\u0026gt;: This class define a generic property associated to the Digital Twin State. Each property is associated to a Key and a Value. Furthermore, it can also be associated to a type to identify its nature and data structure. By default, it is associated to the type of the Class (e.g., java.lang.String) but it can be directly changed by the developer to associate it to a specific ontology or data type. DigitalTwinStateEvent: This class define a generic event associated to the Digital Twin State. Events enable a mechanism for asynchronous messages to be sent by the digital twin (e.g., an overheating) . They are different from Properties that can change values according to the type of Digital Twin and may be associated also to telemetry patterns. Each event is associated to a Key and a Type used to identify its nature and data structure. By default, it is associated to the type of the Class (e.g., java.lang.String) but it can be directly changed by the developer to associate it to a specific ontology or data type. DigitalTwinStateAction: This class define a generic action associated to the Digital Twin State. Each action is by a key, an action type and a content type used to identify the expected input required by the action. The type of the can be directly changed by the developer to associate it to a specific ontology or data type. DigitalTwinStateRelationship\u0026lt;T\u0026gt;: Structures and describes a Relationship in the Digital Twins\u0026rsquo;s State. This is just the description of the relationships while the effective values/instances are described through the other class DigitalTwinStateRelationshipInstance DigitalTwinStateRelationshipInstance\u0026lt;T\u0026gt;: Structures and describes a Relationship Instance in the Digital Twins\u0026rsquo;s State. This is effective description of a relationship while its generic declaration is described through the class DigitalTwinStateRelationship. When there is a change in the DT State it is possibile to cast the received resource variation to the correct one. For example in the following code we detect and manage the variation on a Property Value:\n// Get information from the state change DigitalTwinStateChange.Operation operation = stateChange.getOperation(); DigitalTwinStateChange.ResourceType resourceType = stateChange.getResourceType(); DigitalTwinStateResource resource = stateChange.getResource(); // Search for property value variation if(resourceType.equals(DigitalTwinStateChange.ResourceType.PROPERTY_VALUE) \u0026amp;\u0026amp; operation.equals(DigitalTwinStateChange.Operation.OPERATION_UPDATE) \u0026amp;\u0026amp; resource instanceof DigitalTwinStateProperty){ DigitalTwinStateProperty\u0026lt;?\u0026gt; digitalTwinStateProperty = (DigitalTwinStateProperty\u0026lt;?\u0026gt;) resource; if(getConfiguration().getPropertyUpdateTopics().containsKey(digitalTwinStateProperty.getKey())){ //Handle property value variation } } Constructors:\nDigitalTwinStateChange(): An empty constructor that allows creating an instance of the class. DigitalTwinStateChange(Operation operation, ResourceType resourceType, DigitalTwinStateResource resource): Constructs a DigitalTwinStateChange object with specified operation, resource type, and resource. Throws a WldtDigitalTwinStateException if any of the parameters is missing or null. Methods:\nAccessor methods (getOperation(), getResourceType(), getResource()) to retrieve the values of the fields. Mutator methods (setOperation(), setResourceType(), setResource()) to update the values of the fields. Usage Examples Developers extending the DigitalAdapter class should implement the onStateUpdate method to define custom logic that needs to be executed whenever the state of the Digital Twin is updated. This could include tasks such as processing state changes, updating internal variables, triggering specific actions, or notifying other components about the state update.\nHere\u0026rsquo;s an example of how the method might be implemented in a concrete subclass of DigitalAdapter:\n@Override protected void onStateUpdate(DigitalTwinState newDigitalTwinState, DigitalTwinState previousDigitalTwinState, ArrayList\u0026lt;DigitalTwinStateChange\u0026gt; digitalTwinStateChangeList) { // In newDigitalTwinState we have the new DT State System.out.println(\u0026#34;New DT State is: \u0026#34; + newDigitalTwinState); // The previous DT State is available through the variable previousDigitalTwinState System.out.println(\u0026#34;Previous DT State is: \u0026#34; + previousDigitalTwinState); // We can also check each DT\u0026#39;s state change potentially differentiating the behaviour for each change if (digitalTwinStateChangeList != null \u0026amp;\u0026amp; !digitalTwinStateChangeList.isEmpty()) { // Iterate through each state change in the list for (DigitalTwinStateChange stateChange : digitalTwinStateChangeList) { // Get information from the state change DigitalTwinStateChange.Operation operation = stateChange.getOperation(); DigitalTwinStateChange.ResourceType resourceType = stateChange.getResourceType(); DigitalTwinStateResource resource = stateChange.getResource(); // Perform different actions based on the type of operation switch (operation) { case OPERATION_UPDATE: // Handle an update operation System.out.println(\u0026#34;Update operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; case OPERATION_UPDATE_VALUE: // Handle an update value operation System.out.println(\u0026#34;Update value operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; case OPERATION_ADD: // Handle an add operation System.out.println(\u0026#34;Add operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; case OPERATION_REMOVE: // Handle a remove operation System.out.println(\u0026#34;Remove operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; default: // Handle unknown operation (optional) System.out.println(\u0026#34;Unknown operation on \u0026#34; + resourceType + \u0026#34;: \u0026#34; + resource); break; } } } else { // No state changes System.out.println(\u0026#34;No state changes detected.\u0026#34;); } } In this example, the method iterates over the list of state changes, extracts information about each change, and performs custom actions based on the changes. Developers can adapt this method to suit the specific requirements of their Digital Twin application.\n","date":"February 9, 2024","id":14,"permalink":"/docs/change-logs/change-log-0.3.0/","summary":"Digital Adapters The following methods have been discontinued and removed from the DigitalAdapter class: onStateChangePropertyCreated onStateChangePropertyUpdated onStateChangePropertyDeleted onStatePropertyUpdated onStatePropertyDeleted onStateChangeActionEnabled onStateChangeActionUpdated onStateChangeActionDisabled onStateChangeEventRegistered onStateChangeEventRegistrationUpdated onStateChangeEventUnregistered onStateChangeRelationshipInstanceDeleted onStateChangeRelationshipDeleted onStateChangeRelationshipInstanceCreated onStateChangeRelationshipCreated onDigitalTwinStateEventNotificationReceived The Signature of the following methods have been changed: onDigitalTwinSync(IDigitalTwinState currentDigitalTwinState) -\u0026gt; onDigitalTwinSync(DigitalTwinState currentDigitalTwinState) onDigitalTwinUnSync(IDigitalTwinState currentDigitalTwinState) -\u0026gt; onDigitalTwinUnSync(DigitalTwinState currentDigitalTwinState) New methods that have been added are: onStateUpdate(DigitalTwinState newDigitalTwinState, DigitalTwinState previousDigitalTwinState, ArrayList\u0026lt;DigitalTwinStateChange\u0026gt; digitalTwinStateChangeList) onEventNotificationReceived(DigitalTwinStateEventNotification\u0026lt;?","tags":"","title":"Change Log 0.3.0"},{"content":"The HttpDigitalAdapter is a powerful component designed to facilitate the integration of Digital Twins into HTTP-based systems. It serves as a bridge between a Digital Twin and HTTP-based applications, allowing developers to easily expose and interact with Digital Twin data and functionalities over HTTP.\nKey Features:\nHTTP Integration: Seamlessly integrates Digital Twins into HTTP environments, enabling communication with web applications and services. Dynamic Configuration: Offers a flexible configuration mechanism through the HttpDigitalAdapterConfiguration, allowing developers to customize the adapter\u0026rsquo;s behavior based on specific requirements. State Monitoring: Monitors changes in the Digital Twin state and provides HTTP endpoints to query the state of the Digital Twin (properties, events, actions and relationships). Event Notifications: Allows developers to retrieve event notifications triggered by changes in the Digital Twin state. A complete example is provided in the test folder with a complete DT Creation in the TestMain class together with a demo DT with and emulated Physical Adapter and the HTTP Digital Adapter.\nWLDT-Core Version Compatibility The correct mapping and compatibility between versions is reported in the following table\nhttp-digital-adapter wldt-core 0.2.1 wldt-core 0.3.0 0.1.1 ❌ ✅ Installation To use HttpDigitalAdapter in your Java project, you can include it as a dependency using Maven or Gradle.\nMaven \u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;io.github.wldt\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;http-digital-adapter\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;0.1.1\u0026lt;/version\u0026gt; \u0026lt;/dependency\u0026gt; Gradle implementation \u0026#39;io.github.wldt:http-digital-adapter:0.1.1\u0026#39; Class Structure \u0026amp; Functionalities HttpDigitalAdapterConfiguration The HttpDigitalAdapterConfiguration is a crucial part of the HttpDigitalAdapter, providing the necessary settings to tailor the adapter\u0026rsquo;s behavior to meet specific needs.\nRepresents the configuration for an HTTP Digital Adapter, specifying the host, port, and filters for properties, actions, events, and relationships.\nThe filters are used to selectively include or exclude specific properties, actions, events, and relationships when interacting with the HTTP Digital Adapter. Filters are meant to be white list filters, if they are empty, it means that ALL fields are considered\nThis class provides methods to add filters for each type and getters to retrieve the configured values.\nKey functionalities and exposed capabilities:\nBasic Configuration Adapter ID: A unique identifier for the HttpDigitalAdapter instance. Host: The hostname or IP address on which the adapter will listen for incoming HTTP requests. Port: The port number on which the adapter will listen for incoming HTTP requests. Filters (Optional) addPropertyFilter(String propertyKey): Adds a single property key to the property filter. addPropertiesFilter(Collection\u0026lt;String\u0026gt; propertiesKey): Adds a collection of property keys to the property filter. addActionFilter(String actionKey): Adds a single action key to the action filter. addActionsFilter(Collection\u0026lt;String\u0026gt; actionsKey): Adds a collection of action keys to the action filter. addEventFilter(String eventKey): Adds a single event key to the event filter. addEventsFilter(Collection\u0026lt;String\u0026gt; eventsKey): Adds a collection of event keys to the event filter. addRelationshipFilter(String relationshipName): Adds a single relationship name to the relationship filter. addRelationshipsFilter(Collection\u0026lt;String\u0026gt; relationshipNames): Adds a collection of relationship names to the relationship filter. Configured Filter can be accessed using: getPropertyFilter() getActionFilter() getEventFilter() getRelationshipFilter() A basic example without any filter that accesses and uses the entire DT State is:\nHttpDigitalAdapterConfiguration config = new HttpDigitalAdapterConfiguration(\u0026#34;my-http-adapter\u0026#34;, \u0026#34;localhost\u0026#34;, 8080); An example of using filter to select specific field of interest can be structured ad follows:\nHttpDigitalAdapterConfiguration config = new HttpDigitalAdapterConfiguration(\u0026#34;my-http-adapter\u0026#34;, \u0026#34;localhost\u0026#34;, 8080); // Add property filter config.addPropertyFilter(\u0026#34;temperature\u0026#34;); config.addPropertiesFilter(Arrays.asList(\u0026#34;humidity\u0026#34;, \u0026#34;pressure\u0026#34;)); // Add action filter config.addActionFilter(\u0026#34;start\u0026#34;); config.addActionsFilter(Arrays.asList(\u0026#34;stop\u0026#34;, \u0026#34;reset\u0026#34;)); // Add event filter config.addEventFilter(\u0026#34;temperatureChange\u0026#34;); config.addEventsFilter(Collections.singletonList(\u0026#34;pressureChange\u0026#34;)); // Add relationship filter config.addRelationshipFilter(\u0026#34;connectedTo\u0026#34;); config.addRelationshipsFilter(Arrays.asList(\u0026#34;parentOf\u0026#34;, \u0026#34;siblingOf\u0026#34;)); // Retrieve and display filters List\u0026lt;String\u0026gt; propertyFilter = config.getPropertyFilter(); List\u0026lt;String\u0026gt; actionFilter = config.getActionFilter(); List\u0026lt;String\u0026gt; eventFilter = config.getEventFilter(); List\u0026lt;String\u0026gt; relationshipFilter = config.getRelationshipFilter(); System.out.println(\u0026#34;Property Filter: \u0026#34; + propertyFilter); System.out.println(\u0026#34;Action Filter: \u0026#34; + actionFilter); System.out.println(\u0026#34;Event Filter: \u0026#34; + eventFilter); System.out.println(\u0026#34;Relationship Filter: \u0026#34; + relationshipFilter); HttpDigitalAdapter The HttpDigitalAdapter itself is the core component responsible for handling HTTP requests and interacting with the underlying Digital Twin. It extends the capabilities of the base DigitalAdapter to specifically cater to HTTP-based scenarios.\nKey Functionalities:\nRESTful Endpoints: Provides RESTful endpoints for reading properties, invoking actions, querying events, and managing relationships. State Updates: Automatically reflects changes in the Digital Twin state to the HTTP endpoints, ensuring real-time information. Event Handling: Listens for Digital Twin events and provides events notifications to HTTP clients. Here\u0026rsquo;s a basic example illustrating how to use MqttDigitalAdapter:\nGetting Started: Create HttpDigitalAdapterConfiguration:\nHttpDigitalAdapterConfiguration config = new HttpDigitalAdapterConfiguration(\u0026#34;my-http-adapter\u0026#34;, \u0026#34;localhost\u0026#34;, 8080); Instantiate HttpDigitalAdapter:\nDigitalTwin digitalTwin = new DigitalTwin(\u0026#34;my-digital-twin\u0026#34;, new DefaultShadowingFunction()); HttpDigitalAdapter httpDigitalAdapter = new HttpDigitalAdapter(config, digitalTwin); // Add a Physical Adapter to the DT [...] Add HttpDigitalAdapter to DigitalTwin:\ndigitalTwin.addDigitalAdapter(httpDigitalAdapter); Start the Digital Twin Engine:\nDigitalTwinEngine digitalTwinEngine = new DigitalTwinEngine(); digitalTwinEngine.addDigitalTwin(digitalTwin); digitalTwinEngine.startAll(); HTTP RESTful API This section of the documentation provides detailed information about the RESTful API exposed by the WLDT - HTTP Digital Adapter. The API allows you to interact with the Digital Twin (DT) instance, retrieve its state, read properties, actions, event and relationships description, and trigger actions.\nAvailable endpoints with the associated methods are:\nGET /instance: Retrieves information about the Digital Twin instance. GET /state: Retrieves the current state of the Digital Twin. GET /state/changes: Retrieves the list of state changes in the Digital Twin. GET /state/previous: Retrieves the previous state of the Digital Twin. GET /state/properties: Retrieves the list of properties in the Digital Twin state. GET /properties/{propertyKey}: Retrieves the value of a specific property (e.g., /properties/color) from the Digital Twin state. GET /state/events: Retrieves the list of events in the Digital Twin state. GET /state/actions: Retrieves the list of actions in the Digital Twin state. POST /state/actions/{actionKey}: Triggers the specified action (e.g., /state/actions/switch_on) in the Digital Twin state. The raw body contains the action request payload. GET /state/relationships: Retrieves the list of relationships in the Digital Twin state. GET /state/relationships/{relationshipName}/instances: Retrieves the instances of the specified relationship (e.g., /state/relationships/insideIn/instances) in the Digital Twin state. Note: Replace {propertyKey}, {actionKey}, and {relationshipName} with the actual values you want to retrieve or trigger. Make sure to use the appropriate HTTP method (GET, POST) and include any required parameters or payload as described in each endpoint\u0026rsquo;s description. For more detailed information, refer to the Postman Collection for this API available in the folder api: http_adapter_api_postman.json\n","date":"February 9, 2024","id":15,"permalink":"/docs/adapters/http-digital-adapter/","summary":"The HttpDigitalAdapter is a powerful component designed to facilitate the integration of Digital Twins into HTTP-based systems. It serves as a bridge between a Digital Twin and HTTP-based applications, allowing developers to easily expose and interact with Digital Twin data and functionalities over HTTP.","tags":"","title":"HTTP Digital Adapter"},{"content":"The WLDT framework intends to maximize modularity, re-usability and flexibility in order to effectively mirror physical smart objects in their digital counterparts. The proposed library focuses on the simplification of twins design and development aiming to provide a set of core features and functionalities for the widespread adoption of Internet of Things DTs applications.\nA WLDT instance is a general purpose software entity implementing all the features and functionalities of a Digital Twin running in cloud or on the edge. It has the peculiar characteristic to be generic and ``attachable\u0026rsquo;\u0026rsquo; to any physical thing in order to impersonate and maintain its digital replica and extend the provided functionalities for example through the support of additional protocols or a specific translation or normalization for data and formats.\nHereafter, the requirements that led the design and development of the WLDT framework are:\ni) Simplicity - with WLDT developers must have the possibility to easily create a new instance by using existing modules or customizing the behavior according the need of their application scenario; ii) Extensibility - while WLDT must be as simple and light as possible, the API should be also easily extendible in order to let programmers to personalize the configuration and/or to add new features loading and executing multiple modules at the same times; iii) Portability \u0026amp; Micorservice Readiness - a digital twin implemented through WLDT must be able to run on any platform without changes and customization. Our goal is to have a simple and light core engine with a strategic set of IoT-oriented features allowing the developer to easily create DT applications modeled as independent software agents and packed as microservices. In the following Figure, the main components that make up the architecture of WLDT are represented, and thus through which the individual Digital Twin is implemented. Specifically, from the image it is possible to identify the three levels on which the architecture is developed: the one related to the core of the library, the one that models the DT, and finally, that of the adapters.\nEach of this core components has the following main characteristics:\nMetrics Manager: Provides the functionalities for managing and tracking various metrics within DT instances combining both internal and custom metrics through a flexible and extensible approach. Logger: Is designed to facilitate efficient and customizable logging within implemented and deployed DTs with configurable log levels and versatile output options. Utils \u0026amp; Commons: Hold a collection of utility classes and common functionalities that can be readily employed across DT implementations ranging from handling common data structures to providing helpful tools for string manipulation. Event Communication Bus: Represents the internal Event Bus, designed to support communication between the different components of the DT\u0026rsquo;s instance. It allows defining customized events to model both physical and digital input and outputs. Each WLDT\u0026rsquo;s component can publish on the shared Event Bus and define an Event Filter to specify which types of events it is interested in managing, associating a specific callback to each one to process the different messages. Digital Twin Engine: Defines the multi-thread engine of the library allowing the execution and monitoring of multiple DTs (and their core components) simultaneously. Therefore, it is also responsible for orchestrating the different internal modules of the architecture while keeping track of each one, and it can be considered the core of the platform itself allowing the execution and control of the deployed DTs. Currently, it supports the execution of twins on the same Java process, however the same engine abstraction might be used to extend the framework to support distributed execution for example through different processes or microservices. Digital Twin: Models a modular DT structure built through the combination of core functionalities together with physical and digital adapter capabilities. This Layer includes the Digital Twin State responsible to structure the state of the DT by defining the list of properties, events, and actions. The different instances included in the lists can correspond directly to elements of the physical asset or can derive from their combination, in any case, it is the Shadowing Function (SF) that defines the mapping, following the model defined by the designer. This component also exposes a set of methods to allow SF manipulation. Every time the Digital Twin State is modified, the latter generates the corresponding DT\u0026rsquo;s event to notify all the components about the variation. Shadowing Function: It is the library component responsible for defining the behavior of the Digital Twin by interacting with the Digital Twin State. Specifically, it implements the shadowing process that allows keeping the DT synchronized with its physical entity. This component is based on a specific implementation of a WLDT Worker called Model Engine, in order to be executed by the WLDT Engine. The Shadowing Model Function is the fundamental component that must be extended by the DT designer to concretize its model. The shadowing function observes the life cycle of the Digital Twin to be notified of the different state changes. For example, it is informed when the DT enters the Bound state, i.e. when its Physical Adapters have completed the binding procedure with the physical asset. This component also allows the designer to define the behavior of the DT in case a property is modified, an event is triggered, or an action is invoked. Physical Adapter: It defines the essential functionalities that the individual extensions, related to specific protocols, must implement. As provided by the DT definition, a DT can be equipped with multiple Physical Adapters in order to manage communication with the corresponding physical entity. Each will produce a Physical Asset Description (PAD), i.e., a description of the properties, events, actions, and relationships that the physical asset exposes through the specific protocol. The DT transitions from the Unbound to the Bound state when all its Physical Adapters have produced their respective PADs. The Shadowing Function, following the DT model, selects the components of the various PADs that it is interested in managing. Digital Adapter: It provides the set of callbacks that each specific implementation can use to be notified of changes in the DT state. Symmetrically to what happens with Physical Adapters, a Digital Twin can define multiple Digital Adapters to expose its state and functionality through different protocols. Therefore, to create a Digital Twin using WLDT, it is necessary to define and instantiate a DT with its Shadowing Function and at least one Physical Adapter and one Digital Adapter, in order to enable connection with the physical entity and allow the DT to be used by external applications. Once the 3 components are defined, it is possible to instantiate the WLDT Engine and, subsequently, start the lifecycle of the DT. In the following sections we will go through the fundamental steps to start working with the library and creating all the basic modules to design, develop and execute our first Java Digital Twin.\n","date":"February 9, 2024","id":16,"permalink":"/docs/introduction/library-structure-basic-concepts/","summary":"The WLDT framework intends to maximize modularity, re-usability and flexibility in order to effectively mirror physical smart objects in their digital counterparts.","tags":"","title":"Library Structure \u0026 Basic Concepts"},{"content":" With respect to the element present in the real world, it is defined as a Physical Asset (PA) with the intention of referring to any entity that has a manifestation or relevance in the physical world and a well-defined lifespan.\nThe previous Figure schematically illustrates the main component of an abstract Digital Twin and clarifies its responsibility to be a bridge between the cyber and the physical world. The blueprint components (then mapped into the WLDT Library) are:\nPhysical Interface The entity in charge of both the initial digitalization o shadowing process and the perpetual responsibility to keep the DT and PA in synch during its life cycle. It can execute multiple Physical Asset Adapters to interact with the PA and detect and digitalize the physical event coming from the physical entity according to its nature and the supported protocols and data formats (e.g., through HTTP and JSON). Digital Interface The component complementary to the Physical Interface and in charge of handling DT\u0026rsquo;s internal variations and events towards external digital entities and consumers. It executes multiple and reusable Digital Adapters in charge of handling digital interactions and events and responsible for making the DT interoperable with external applications. DT\u0026rsquo;s Model The module defining the DT\u0026rsquo;s behaviour and its augmented functionalities. It supports the execution of different configurable and reusable modules and functionalities handling both physical and digial events according to the implemented behaviour. Furthermore, the Model is the component responsible to handle and keep updated the Digital Twin State as described in the following sections. The Digital Twin Model(M) allows capturing and representing the PA at an appropriate level of abstraction, i.e., avoiding irrelevant aspects for its purpose and modeling only domain-level information rather than technological ones. Finally, the link between the physical and digital copy is defined as shadowing. Specifically, the term defines the process that enables continuous and (almost) real-time updating of the internal state of the DT in relation to changes that occur in the PA.\nEach DT is thus equipped with an internal model, which defines how the PA is represented in the digital level. The DT\u0026rsquo;s representation denoted as Digital Twin State supported and defined through M is defined in terms of:\nProperties: represent the observable attributes of the corresponding PA as labeled data whose values can dynamically change over time, in accordance with the evolution of the PA\u0026rsquo;s state. Events: represent the domain-level events that can be observed in the PA. Relationships: represent the links that exist between the modeled PA and other physical assets of the organizations through links to their corresponding Digital Twins. Like properties, relationships can be observed, dynamically created, and change over time, but unlike properties, they are not properly part of the PA\u0026rsquo;s state but of its operational context (e.g., a DT of a robot within a production line). Actions: represent the actions that can be invoked on the PA through interaction with the DT or directly on the DT if they are not directly available on the PA (the DT is augmenting the physical capabilities). Once the model M is defined, the dynamic state of the DT (SDT) can be defined by through the combination of its properties, events, relationships and actions associated to the DT timestamp that represents the current time of synchronization between the physical and digital counterparts.\nThe Shadowing Process The shadowing process (also known as replication of digitalization) allows to keep the Digital Twin State synchronized with that of the corresponding physical resource according to what is defined by the model M. Specifically, each relevant update of the PA state (SPA) is translated into a sequence of 3 main steps:\neach relevant change in physical asset state is modeled by a physical_event (e_pa); the event is propagated to the DT; given the new physical_event, the DT\u0026rsquo;s is updated through the application of a shadowing function, which depends on the model M The shadowing process allows also the DT to reflect and invoke possible actions of the PA. The DT receives an action request (denoted as digital_action) on its digital interface, applies the shadowing function to validate it and then propagates the request through its physical interface. An important aspect to emphasize is that the request for a digital_action does not directly change the state of the DT since any changes can only occur as a result of the shadowing function from the PA to the DT, as described earlier.\n","date":"February 9, 2024","id":17,"permalink":"/docs/introduction/dt-model/","summary":"With respect to the element present in the real world, it is defined as a Physical Asset (PA) with the intention of referring to any entity that has a manifestation or relevance in the physical world and a well-defined lifespan.","tags":"","title":"DT Model"},{"content":"\rThe modeling of the concept of DT includes also the definition and characterization of its life cycle. Based on the scientific literature, we model (and then map into the library) a life cycle with 5 states through which the DT goes from when it is executed to when it is stopped. The previous Figure shows a graphical representation of the life cycle with the following steps:\nOperating \u0026amp; Not Bound: this is the state in which the DT is located following the initialization phase, indicating that all internal modules of the DT are active but there is no association yet with the corresponding PA. Bound: this is the state in which the DT transitions following the correct execution of the binding procedure. The binding procedure allows to connect the two parts and enables bidirectional flow of events. Shadowed: this is the state reached by the DT when the shadowing process begins and its state is correctly synchronized with that of the PA. Out of Sync: this is the state that determines the presence of errors in the shadowing process. When in this state, the DT is not able to handle either state alignment events or those generated by the application layer. Done: this is the state that the DT reaches when the shadowing process is stopped, but the DT continues to be active to handle requests coming from external applications. From Unbound to Bound Taking into account the target reference Life Cycle the first point to address is how we can move from an UnBound state to a Bound condition with respect to the relationship with the Physical Layer.\nThe previous Figure illustrates a simple scenario where a Physical Asset uses two protocols (P1 and P2) to communicate and it is connected to the Digital Twin through a DT\u0026rsquo;s Physical Interface enabled with two dedicated Adapters for protocol P1 and P2. In order to move from the Unbound to Bound state the DT should be aware of the description of the target asset with respect to the two protocols. For example through P1 the asset exposes telemetry data (e.g., light bulb status and energy consumption) while on P2 allows incoming action requests (e.g., turn on/off the light). The Digital Twin can start the shadowing process only when it is bound and has a description of the properties and capabilities of the associated physical counterpart. The schematic procedure is illustrated in the following Figure:\nInvolved steps are:\nThe Adapter P1 communicates with the PA through Protocol 1 and provides a Physical Asset Description from its perspective The Adapter P2 communicates with the PA through Protocol 2 and provides a Physical Asset Description from its perspective Only when all Physical Adapters have been correctly bound (it may require time) to the Physical Asset and the associated Physical Asset Descriptions have been generated, the DT can move from UnBound to Bound Main core aspects associated to the concept of Physical Asset Description (PAD) are the following:\nIt is used to describe the list of properties, actions and relationships of a Physical Asset Each Physical Adapter generates a dedicated PAD associated to its perspective on the Physical Assets and its capabilities to read data and execute actions It is a responsibility of the DT to handle multiple descriptions in order to build the digital replica It will be used by the DT to handle the shadowing process and keep the digital replica synchronized with the physical counterpart From Bound to Shadowed Following the same approach described in the previous step we need to define a procedure to allow the DT to move from a Bound state to a Shadowed condition where the twin identified the interesting capabilities of the Physical Asset that has to be digitalized and according to the received Physical Asset Descriptions start the shadowing procedure to be synchronized with the physical world.\nAs schematically illustrated in the previous Figure, involved steps are:\nThe Model defines which properties should be monitored on the Physical Asset and start observing them through the target adapters Involved Physical Adapters communicate with the Physical Asset, receive data and generate Events (ePA) to notify about physical property changes Received ePA will be used by the Digital Twin Model in order to run the Shadowing function and compute the new DT State The DT can move from the Bound to Shadowed phase until it is able to maintain a proper synchronization with the physical asset over time through its shadowing process and the generation and maintenance of the DT\u0026rsquo;s State The Digital Twin State is structured and characterized by the following elements:\nA list of properties A list of actions A list of relationships Listed elements can be directly associated to the corresponding element of the Physical Asset or generated by DT Model combining multiple physical properties, actions or relationships at the same time. The Digital Twin State can be managed through the Shadowing Function and exposes a set of methods for its manipulated. When there is a change in the DT State an event (eDT) will be generated\nThe manipulation of DT\u0026rsquo;s State generates a set of DT\u0026rsquo;s events (eDT) associated to each specific variation and evolution of the twin during its life cyle. These events are used by the Digital Interface and in particular by its Digital Adapters to expose the DT\u0026rsquo;s State, its properties and capabilities to the external digital world. At the same time, eDT can be used by Digital Adapters to trigger action on the DT and consequently to propagate (if acceptable and/or needed) the incoming request to the physical assets bound with the target DT. Supported events are illustrated in the following schema.\n","date":"February 9, 2024","id":18,"permalink":"/docs/introduction/dt-life-cycle/","summary":"The modeling of the concept of DT includes also the definition and characterization of its life cycle. Based on the scientific literature, we model (and then map into the library) a life cycle with 5 states through which the DT goes from when it is executed to when it is stopped.","tags":"","title":"DT Life Cycle"},{"content":"","date":"September 7, 2023","id":19,"permalink":"/docs/","summary":"","tags":"","title":"Docs"},{"content":"Welcome to White Label Digital Twins (WLDT), an open-source project dedicated to supporting the design, development, and deployment of Digital Twins within the Internet of Things (IoT) ecosystems.\nThe WLDT library has been designed to align with the latest DT definitions from both Industrial and Scientific domains. It identifies DTs as active, flexible, and scalable software components. Our library aims to provide developers with the tools and resources necessary to create robust Digital Twins that effectively simulate and monitor physical assets within IoT environments.\nWhether you\u0026rsquo;re working on IoT, Industrial IoT (IIoT) applications, Smart Cities projects, or any other IoT-related endeavor, the WLDT library offers a versatile solution for implementing Digital Twins that accurately represent real-world objects and support informed decision-making processes.\n💻 Team \u0026amp; Mantainers [Founders \u0026amp; Main Contributors] Marco Picone - University of Modena \u0026amp; Reggio Emilia, Italy - (Link) [Key Contributors] Samuele Burattini - University of Bologna, Italy - (Link) [Additional Contributors] Marta Spadoni - University of Bologna, Italy - Master Thesis 2022 📜 Scientitic Citation \u0026amp; References If you use the WLDT Library in a Scientific Paper please use this reference:\n@article{PICONE2021100661, title = {WLDT: A general purpose library to build IoT digital twins}, journal = {SoftwareX}, volume = {13}, pages = {100661}, year = {2021}, issn = {2352-7110}, doi = {https://doi.org/10.1016/j.softx.2021.100661}, url = {https://www.sciencedirect.com/science/article/pii/S2352711021000066}, author = {Marco Picone and Marco Mamei and Franco Zambonelli}, keywords = {Internet of Things, Digital twin, Library, Software agent} } 📨 Community Join our community and contribute to the advancement of Digital Twin technology with White Label Digital Twins!\nWLDT questions, feedback and discussions are tracked using slack channels in the WLDT Slack Workspace.\nThe workspace is available here: WLDT Slack Workspace\nNew users first need to join the MEC Sandbox slack workspace by creating a new account using the invitation link provided here: Join the WLDT Slack Workspace\n🐛 Reporting Issues WLDT issues should be reported on Slack, where they can be discussed with the core team that maintains the WLDT Library.\n","date":"March 13, 2024","id":20,"permalink":"/about/","summary":"Welcome to White Label Digital Twins (WLDT), an open-source project dedicated to supporting the design, development, and deployment of Digital Twins within the Internet of Things (IoT) ecosystems.","tags":"","title":"About WLDT Library"},{"content":" What is a digital Twin? A Digital Twin (DT) is a comprehensive software representation of any individual Physical Asset (PA) in the real world.\nIt includes the properties, conditions, relationships, and behavior(s) of the real-life object through models and data.\nA Digital Twin is a set of realistic models that can digitalize an object’s behavior in the deployed environment and has the responsibility to represent and reflect its physical counterpart over time maintaining its digital replica across the object’s entire lifecycle.\nWhat can WLDT do for me? The White Label Digital Twin (WLDT) library aims to support the design, development, and deployment of Digital Twins within the Internet of Things (IoT) ecosystems.\nThe library has been designed following the latest DT definitions coming from both Industrial and Scientific domains and identifying DTs as active, flexible and scalable software components.\nScientitic Citation \u0026amp; Reference If you use the WLDT Library in a Scientific Paper refer to the About Page for additional information and scientific references. Thanks :)\n","date":"October 6, 2023","id":21,"permalink":"/","summary":"What is a digital Twin? A Digital Twin (DT) is a comprehensive software representation of any individual Physical Asset (PA) in the real world.","tags":"","title":"White Label Digital Twins"},{"content":"","date":"September 7, 2023","id":22,"permalink":"/privacy/","summary":"","tags":"","title":"Privacy Policy"},{"content":"","date":"January 1, 0001","id":23,"permalink":"/categories/","summary":"","tags":"","title":"Categories"},{"content":"","date":"January 1, 0001","id":24,"permalink":"/contributors/","summary":"","tags":"","title":"Contributors"},{"content":"","date":"January 1, 0001","id":25,"permalink":"/tags/","summary":"","tags":"","title":"Tags"}] \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index 1d5e277..b8f2299 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1 +1 @@ -https://wldt.github.io/en/sitemap.xml2024-03-14T17:11:51+01:00 \ No newline at end of file +https://wldt.github.io/en/sitemap.xml2024-03-15T10:45:36+01:00 \ No newline at end of file