t-wolfeadam / AnyLogic-JSONifier

A simple library for enabling JSON serialization and deserialization for various AnyLogic types
MIT License
0 stars 0 forks source link

Add DTDL to JSONifier #7

Open GMGassner opened 2 weeks ago

GMGassner commented 2 weeks ago

Dear Tyler, I am currently using AL in my research and have recently explored the possibility of utilizing Digital Twins Definition Language v3 for the instantiation of some agents in AL 8.9. In addition to my research, I have observed that several major companies, such as Microsoft and Siemens, are increasingly adopting DTDL for digital twins.

Given that DTDL is JSON-LD based, I believe there is potential to advance support in this direction. Perhaps a separate "DTDLifier" could be developed to facilitate this integration.

I am very interested in contributing to this development if you decide to support DTDL. Please let me know if there is any chance to advance support for DTDL in AL 8.9.

Thank you in advance for considering this request. I look forward to your response.

t-wolfeadam commented 2 weeks ago

Hi! Thanks for the suggestion! From my (admittedly superficial) knowledge of Azure Digital Twins and DTDL, the scope of what you're proposing can vary dramatically depending on the specifics.

From what I understand about ADT, you're describing the entire model through the DTDL (i.e., the environment, rules and relationships, actions, etc). From a high-level perspective, this is similar to what you're doing when defining a model through AL and the "languages" it provides (i.e., flowcharts, statecharts, Java code, etc.).

If your proposal is to have complete support for converting DTDL to an AL model, this is definitely out of the scope of this project. That would require not only parsing the DTDL but figuring out the AL equivalents and how you can 'map' from one to the other. For example, how to link defined Commands to some code in the user's model.

The other route I can think of is just to use DTDL for the structure of how it defines its objects. Essentially you'd use it as a schema specification for agent types you've already defined in AL, with a customized serializer for converting that structure to the agent type defined in the schema. Customized serializers is already something that's in the works, namely for a way to use JSON with a different structure than what JSONifier expects.

Let me know if I missed anything or what your thoughts are!

GMGassner commented 2 weeks ago

Hi, thank you so much for the quick reply! You are right regarding the varying scope of my post so I want to narrow it down and explain my experience. I was looking into Manufacturing Ontologies, which ties together DTDL, W3C WoT and ISA95, as an ontology for my research project. We are trying to build Green Digital Twins for sustainable manufacturing of beverages and later food.

My approach was to look at the unit level of manufacturing equipment and have a description, which is relatively flexible. Using the newest version (v3) of DTDL enables that through components and modularity. This concept would be to have one DTDL per unit and use the key concepts in DTDL for a comprehensive description.

  1. Interface: An interface defines the structure and capabilities of a digital twin. It specifies the properties, telemetry, commands, and relationships that a digital twin can have.

  2. Property: Properties are attributes or state variables of a digital twin. They can be read-only or writable and have a specific data type, such as string, integer, or boolean.

  3. Telemetry: Telemetry represents data emitted by a digital twin, typically time-series data from sensors or measurements. It can include data points like temperature, pressure, or status updates.

  4. Command: Commands are actions that can be invoked on a digital twin. They allow you to trigger specific behaviors or operations on the digital twin, such as starting a process or updating a setting.

  5. Relationship: Relationships define how digital twins are connected to each other. They represent the associations or dependencies between different digital twins, such as a device being part of a larger system.

  6. Schema: Schemas define the data types used in properties, telemetry, and commands. DTDL supports primitive types (e.g., string, integer) as well as complex types like enums, objects, and arrays.

  7. Component: Components allow you to modularize and reuse common definitions across multiple interfaces. They enable you to create reusable building blocks for your digital twin models.

Here's an example of a DTDL v3 model that represents a manufacturing machine:

{
  "@id": "dtmi:com:example:ManufacturingMachine;3",
  "@type": "Interface",
  "@context": "dtmi:dtdl:context;3",
  "displayName": "Manufacturing Machine",
  "contents": [
    {
      "@type": "Property",
      "name": "machineId",
      "schema": "string",
      "writable": false
    },
    {
      "@type": "Property",
      "name": "machineType",
      "schema": "string",
      "writable": false
    },
    {
      "@type": "Property",
      "name": "status",
      "schema": {
        "@type": "Enum",
        "valueSchema": "string",
        "enumValues": [
          {
            "name": "Idle",
            "enumValue": "idle"
          },
          {
            "name": "Running",
            "enumValue": "running"
          },
          {
            "name": "Maintenance",
            "enumValue": "maintenance"
          }
        ]
      },
      "writable": true
    },
    {
      "@type": "Telemetry",
      "name": "temperature",
      "schema": "double"
    },
    {
      "@type": "Telemetry",
      "name": "vibration",
      "schema": "double"
    },
    {
      "@type": "Property",
      "name": "productionRate",
      "schema": "integer",
      "unit": "units/hour",
      "writable": false
    },
    {
      "@type": "Relationship",
      "name": "hasOutputProducts",
      "target": "dtmi:com:example:Product;1"
    },
    {
      "@type": "Command",
      "name": "startProduction",
      "request": {
        "name": "productionSettings",
        "schema": {
          "@type": "Object",
          "fields": [
            {
              "name": "productType",
              "schema": "string"
            },
            {
              "name": "quantity",
              "schema": "integer"
            }
          ]
        }
      }
    }
  ]
}

In this example: The @id property identifies the model as a manufacturing machine with version 3. The displayNameproperty provides a human-readable name for the machine. The contentsproperty defines the properties, telemetry, relationships, and commands of the machine: Property elements represent the machine's attributes, such as machineId, machineType, status (an enum property), and productionRate. Telemetry elements define the data points emitted by the machine, such as temperature and vibration. The Relationship element hasOutputProductsindicates that the machine produces products, referencing the Product model. The Command element startProductiondefines an action to start the production process, accepting productionSettingsas a request parameter with productTypeand quantity fields.

So in essence use DTDL to instantiate agents like with the JSONifer, just in a richer format that also enables other use cases. A customized serializer for converting that structure to the agent is essentially what it boils down to.

I would love to help and am happy to hear that something is in the works to enable that. How can i help?

t-wolfeadam commented 1 week ago

Thanks for the extremely detailed explanation, including the example that tied all the mentioned concepts together.

So in essence use DTDL to instantiate agents like with the JSONifer

The part I'm missing though is that the DTDL example you provided is in an interface, not an instance. What you're describing seems to be like a conversion from a DTDL model to an AnyLogic agent type definition. In other words, the library would create agent types themselves dynamically (in traditional Java terms, auto-generated classes). To do this currently would require reverse engineering the XML which makes up the source of an AnyLogic model (which has no guarantee to remain consistent) and is way more complex than what the Jsonifier does.

The only equivalent to the Jsonifier would be if you wanted to take a DTDL instance and import it to the sim to be converted to a pre-defined agent type, with parameters that would map to everything that could be provided by the DTDL instance. The property and telemetry would likely map nicely to parameters, though there's no way to make parameters read-only. You can define enums in the AnyLogic model; they'd just need to be predefined and match up with the naming from the DTDL model. Relationships are trickier because the library would need logic to figure out a way to map whatever value is in the relationship fields to what's in the AnyLogic model (again, pre-defined).

I'm curious to know which route you were thinking about going in! Knowing that will definitely help clarify the feasibility of this.

GMGassner commented 3 days ago

Thanks for taking the time and effort to my request! Sry for the delayed response, I could not find time up until now. I completely agree with you,

create agent types themselves dynamically (in traditional Java terms, auto-generated classes)

is way beyond and not part of my request.

My train of thought was rather simple. From what I gathered a DTDL Interface describes a DT with its components. If I have a DTDL file of every unit I want to have a DT for (like a machine in manufacturing) the sum of DTDL files describe my manufacturing process in a way to be able to have digital twins of every unit and of the whole process. If I wanted to have a simulation that is used for manufacturing optimization, everything that is needed for this to work should be already in the DTDL files (parameters, specification, states, etc.). So my idea was, why not use this detailed description of units and processes to instantiate agents in a simulation. So basically use DTDL not only for connecting machines to their DT, but also to instantiate agents in a simulation model that generates data needed to drive the DT. Of course this has limitation and agent types would have to be compatible in their composition to be instantiated with the files.

In a more structured way: DTDL Interface. "Interface describes the contents (Commands, Components, Properties, Relationships, and Telemetries) of any digital twin. Interfaces are reusable and can be reused as the schema for Components in another Interface."

  1. DTDL Interface:

    • Describes the structure and capabilities of a digital twin of a unit
    • Defines properties, telemetry, relationships, and components
    • Acts as a template or schema for instances
  2. AnyLogic Agent:

    • Represents a unit in a simulation model
    • Has properties, behaviors, and can interact with other agents
    • Can be instantiated from a predefined type

The similarity lies in how both DTDL interfaces and AnyLogic agent types serve as templates for creating instances.

  1. Properties: DTDL properties could map to AnyLogic agent parameters or variables.
  2. Telemetry: Could be represented as variables or outputs in agents.
  3. Relationships: Might be translated to the sequence of units and how agents flow from unit to unit. Alternatively connections
  4. Components: Could map to populations of agents
  5. Command: State charts, Events, etc.

An inspiration was this paper on how DTDL and OPC UA could map to each other Proposal of Mapping Digital Twins Definition Language to Open Platform Communications Unified Architecture

Maybe I'm barking up the wrong tree, but I thought I'll share this with you to see whether it has some merit to it.

t-wolfeadam commented 3 days ago

Again, thank you for such a thorough explanation! I'm starting to see where my previous disconnect was, which I'll speak to first.

The Jsonifier implementation takes advantage of the API shared across all agents, notably the parameter functions (getParameter(name), setParameter(name, value), etc.) which are the main source of initialization targets; most other sources are assumed to be assigned as part of the dynamic logic.

What it seems like you're proposing is an extension of this, also initializing variable values, nested agents/populations, other attributes (e.g., position, speed), connections, schedule events, etc. This is feasible through a much more robust specification (the Jsonifier's intention is to be as simple/inutive as possible).

The more complicated aspect is that the way people define these in their model can vary. For example, sometimes a relationship is defined via a 'Link to agents' and other times with typed variables. This could be theoretically resolved through documentation though.

Where I'm still lost though is the practical, actual nuts and bolts of the implementation and workflow.

If I wanted to have a simulation that is used for manufacturing optimization, everything that is needed for this to work should be already in the DTDL files (parameters, specification, states, etc.).

But this is backwards, is it not? The simulation is essentially a replacement for the real-world equivalent + IoT devices.

To clarify with an example, say I'm wanting to monitor/control my house's temperature/its thermostat. My (limited) understanding is that the Azure DT workflow looks like this:

  1. Define my house (e.g., room relationships/references, thermostat-command-schema) as a model in DTDL and upload that to Azure
  2. Install IoT devices to send out temperature and be able to receive commands
  3. Connect my IoT devices to the Azure DT
  4. Now I can monitor the live temperature and change the thermostat (live) from here

In diagram form:

DTDL ----(uploaded to)----v
                         AZURE
Thermostat <--> IOT <--> DIGITAL TWIN <--> Me (remotely)
^________House_________^

With a simulation model, I'm not just defining the house but also recreating the physics of temperature propagation (or recreating the effects of it) and all the dynamics of the real world system (e.g., simulating how I respond and the points in which I override the set temperature). It also serves as where experimentation/data gathering happens via running experiments. In this way, it's like a replacement for the thermostat + IoT + Azure Digital Twin platform. You could actually create a DTDL model from a simulation model; whereas, the the other way around - uploading a DTDL model to a sim - is like trying to pass it to the IoT devices.

The other (maybe obvious) thing to note is that, unlike Azure DT, syncing to the real, live system only happens at once on startup. After this point, it's assumed it has all the rules and relationships of the system baked into it so that it can accurately play out one possible future trajectory of the environment.

I imagine the true intention is to rather take whatever is outputted by the IoT device, specifically in whatever data format the Azure DT expects as input (maybe this is still referred to as being in DTDL? I couldn't find many resources on actual integration with real systems) and have some library that can parse that and apply it to the sim(?)

t-wolfeadam commented 3 days ago

Also, I did read through the paper you sent (I wasn't previously aware of OPC UA, so thank you!).

From what I gather, in terms of their relationship to a simulation model, the real-time data from both OPC UA-enabled devices or digital twins defined using DTDL could be used to feed into the sim as input on its startup; this would be in whatever data format/structure is outputted by each (or by the underlying IoT device, if you wanted to go that route too).