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.

In order to add a demo Digital Action trigger on the Digital Adapter we add the following method to the DemoDigitalAdapter class:

private Runnable emulateIncomingDigitalAction(){
    return () -> {
        try {

            System.out.println("Sleeping before Emulating Incoming Digital Action ...");
            Thread.sleep(5000);
            Random random = new Random();

            //Emulate the generation on 'n' temperature measurements
            for(int i = 0; i < 10; i++){

                //Sleep to emulate sensor measurement
                Thread.sleep(1000);

                double randomTemperature = 25.0 + (30.0 - 25.0) * random.nextDouble();
                publishDigitalActionWldtEvent("set-temperature-action-key", 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’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.

Then we call this method in the following way at the end ot the onDigitalTwinSync(IDigitalTwinState currentDigitalTwinState) method.

//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).

In our simple demo implementation the updated Shadowing Function method onDigitalActionEvent(DigitalActionWldtEvent<?> digitalActionWldtEvent) results as follows:

@Override
protected void onDigitalActionEvent(DigitalActionWldtEvent<?> 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<?> 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.

@Override
public void onIncomingPhysicalAction(PhysicalAssetActionWldtEvent<?> physicalAssetActionWldtEvent) {
    try{

        if(physicalAssetActionWldtEvent != null
                && physicalAssetActionWldtEvent.getActionKey().equals(SET_TEMPERATURE_ACTION_KEY)
                && physicalAssetActionWldtEvent.getBody() instanceof Double) {
            System.out.println("Received Action Request: " + physicalAssetActionWldtEvent.getActionKey()
                    + " with Body: " + physicalAssetActionWldtEvent.getBody());
        }
        else
            System.err.println("Wrong Action Received !");

    }catch (Exception e){
        e.printStackTrace();
    }
}