JSON-LD Messaging

Internally, INTER-MW uses messages in JSON-LD format, encapsulated in a eu.interiot.message.Message Java class. Any such message is composed of 2 RDF graphs:

  • metadata graph, with identifier http://inter-iot.eu/message/metadata
  • payload graph identified by http://inter-iot.eu/message/payload

Metadata graph

The metadata graph contains information about the message itself, and is used by INTER-MW to route the message. Any INTER-MW JSON-LD message is required to have one metadata graph, containing one instance of RDF class http://inter-iot.eu/message/meta, called a "metadata instance". All metadata items are properties attached to that instance, i.e. the instance is the subject of metadata triples. The instance may be anonymous.

The types of the whole message are actually the RDF types of the metadata instance. The instance can technically have any number of types, but in INTER-MW it will have at most two types, on top of the META type (see - message types section).

All message routing within INTER-MW is done based on information, found in the metadata graph. In the case that the payload contains essential information for routing of the message, this is information must be first transferred to the metadata of the message and only then used in message processing and routing within INTER-MW.

The following properties are available for use in any INTER-MW message (all of which use the http://inter-iot.eu/message/ namespace):

  • messageID - a string identifier of a message.
  • conversationID - a string identifier of a conversation that this message is a part of. When replying to a message with another one, the conversation ID should be preserved.

INTER-MW auto-generated string identifiers are 36 random alphanumerical strings with dashes, prefixed with a fixed "type string" e.g. "msg" for message IDs, or "conv" for conversation IDs.

  • dateTimeStamp - xsd:datetimestamp of message creation.
  • status - General information about the status of the message, in case a simple response is required (e.g. STATUS = "OK").
  • SenderPlatformId - URI identifier of a platform that sent the message.
  • ReceiverPlatformId - URI identifier of a platform that is the intended receiver of the message.

URI identifiers of the platforms need to be registered with INTER-MW, and have a bridge associated with them. Even though the identifiers are for platforms, they are used to route messages between bridges. Because a single bridge can support only one platform, the identification is unique.

Depending on the message type, other properties will be set and read by INTER-MW. The message types are described in a further section of this document.

For SYS_INIT:

  • previousConversationID - a string identifier of a previous conversation that this message was a part of. This property is used when an INTER-MW component needs to reinitialize and continue some previous conversation.

For DISCOVERY_QUERY:

  • query - a query string for the INTER-MW Discovery service.

For CLIENT_REGISTER and CLIENT_UNREGISTER:

  • clientId - string identifier of an INTER-MW client application.
  • clientCallbackURL - a callback URL for the client application, encoded in a string.

For ERROR:

  • errID, errCategory, errDesc - these properties identify the error with different levels of generality - the description can be any string that describes the error in a human-understandable fashion. Error ID is a string that identifies the error with more specificity than the error category.
  • errOriginalMsg - another INTER-MW JSON-LD message is serialized here, if it is relevant to the error, e.g. if the error occured when parsing some other message.
  • errStackTrace - if the error message is sent as a result of catching a Java exception, the serialized stack trace will be put here.

Metadata example

Example metadata graph, where InterIoTMsg is the prefix for http://inter-iot.eu/message/:

{
      "@graph": [
        {
          "@id": "InterIoTMsg:meta/36d6-49a2-82ec-d909d8e6f10b",
          "@type": [
            "InterIoTMsg:meta",
            "InterIoTMsg:Device_Add"
          ],
          "InterIoTMsg:SenderPlatformId": {
            "@id": "http://om2m.org/myPlatform"
          },
          "InterIoTMsg:conversationID": "conv614d3621-7399-45b1-bf2f-505b24045ea7",
          "InterIoTMsg:dateTimeStamp": "2018-01-15T15:49:00.655+01:00",
          "InterIoTMsg:messageID": "msg7713aa0f-61df-471d-beec-80e8fb71528b"
        }
      ],
      "@id": "InterIoTMsg:metadata"
    }

Payload graph

The payload graph, in principle, can contain any RDF code. INTER-MW requires the payload to use the common ontology, and utilizes IPSM to translate to and from it. Bridges use the syntactic translation components to transform messages from platforms into RDF, and put them in the payload.

TODO: Link to GOIoTP

Example payload

Example payload graph:

{
      "@graph": [
        {
          "@id": "http://myplatform:8080/weather/station2",
          "@type": [
            "iiot:IoTDevice",
            "sosa:Sensor"
          ],
          "InterIoT:GOIoTP#hasName": "Weather Station 1",
          "InterIoT:GOIoTP#hasDescription": "Second Weather Station on the mountain, which is itself also a sensor",
          "sosa:observes": {
            "@id": "http://myplatform:8080/weather/station2/temperature"
          }
        },
        {
          "@id": "http://myplatform:8080/weather/station2/temperature",
          "@type": [
            "iiotex:Temperature",
            "sosa:ObservableProperty",
            "ssn:Property"
          ],
          "iiot:hasDescription": "air temperature on the mountain top, second weather station"
        }
      ],
      "@id": "InterIoTMsg:payload"
    }

The prefixes for the example above are defined as follows:

"@context": {
    "InterIoTMsg": "http://inter-iot.eu/message/",
    "InterIoT": "http://inter-iot.eu/",
    "sosa": "http://www.w3.org/ns/sosa/",
    "iiot": "http://inter-iot.eu/GOIoTP#"
  }

Message types

Although implementation of the Message class allows for a message to have multiple types, in practice a message has one or two types, not counting the META type. In these cases, RESPONSE is the second message type. This reflects the message flow mechanism: some message types are request, which expect responses from INTER-MW components. The table below lists all message types, their usage and typical data flow scenarios. For the tables below, the default prefix : is bound to http://inter-iot.eu/message/.

MessageType Java enum/
RDF Message type
Description Direction
META
:meta
Every metadata graph is required to have an instance of this type. It is hidden from the user in the Java libraries (never returned by getMessageTypes() method), but needs to always be present in every message. ANY
UNRECOGNIZED
N/A
This type is used for any RDF type that is not defined by INTER-MW. It appears as UNDEFINED in the Java enum. It will never be produced by INTER-MW itself, but may be produced by a bridge. If a type URI has a typo, it will also result in an UNRECOGNIZED message type. ANY
RESPONSE
:response
Indicates, that this message is a response to another one. The interpretation of a response type, is in the context of all other message types, excluding META. For instance, a message of types SUBSCRIBE and RESPONSE is a response to a subscription. Even though an OBSERVATION message can be thought of as a response to a SUBSCRIPTION, it is semantically different. In other words, an OBSERVATION message should not have the additional type of RESPONSE, if it is only sent for a subscription. The RESPONSE type is automatically added to a message in createResponse() within AbstractBridge class. In short - in INTER-MW Response is generated as a fulfillment of a request. The RESPONSE type is always combined with one of the "requesting" types. Bridge → Intermw
SYS_INIT
:Sys_init
This message type often appears alongside other types, and is a special indicator, that the INTER-MW system was reinitialized (usually as a result of restart). Any additional types indicate the actual meaning of the message. For instance, a SUBSCRIBE, SYS_INIT message means that the subscription information contained in the payload was sent to the receiver previously, and is not being sent again. The receiver needs to make the decision, as to how to renew the subscription. This mechanism is intended to support platforms and applications that do not have persistence, and would lose any information that they need for run-time configuration of any service. INTER-MW → Bridge, INTER-MW → Client App
SUBSCRIBE
:Subscribe
A request to create a subscription on a platform, to any new observations made by any of the devices listed in the payload (only device identifiers are given). INTER-MW → Bridge
UNSUBSCRIBE
:Unsubscribe
A request to remove a subscription for any devices listed in the payload. INTER-MW → Bridge
DEVICE_ADD_OR_UPDATE
:Device_Add
Adds a device to the INTER-MW device registry, or updates existing device information. Any previously existing information about the device is removed from registry, and replaced with the new one. Devices are identified only by the RDF ID. Bridge → INTER-MW
DEVICE_REMOVE
:Device_Remove
Removes a device from INTER-MW registry. Only device ID is required. Bridge → INTER-MW
DEVICE_REGISTRY_INITIALIZE
:Device_Init
Removes all device information from INTER-MW registry. If sent by a bridge, it clears all information about devices hosted on the bridge's platform. Bridge → INTER-MW
LIST_DEVICES
:Discovery_List
A request from INTER-MW for all device information that a platform and bridge are willing to share. The information should then be sent in a series of DEVICE_ADD_OR_UPDATE messages, with information about one device per message. Afterwards, the bridge should keep it updated with messages of type DEVICE_ADD_OR_UPDATE, DEVICE_REMOVE, or DEVICE_REGISTRY_INITIALIZE. INTER-MW → Bridge
DISCOVERY_QUERY
:Device_discovery_query
A message to INTER-MW device registry to query it about devices that satisfy some query string. INTER-MW will respond with a list of device identifiers in a message of double type DISCOVERY_QUERY and RESPONSE. This message is usually followed by a SUBSCRIBE message to a bridge, that contains the device IDs returned from the discovery query. Client App → INTER-MW
QUERY
:Query
A query for the current status and last observation of a particular device identified with a given ID. INTER-MW → Bridge
PLATFORM_CREATE_DEVICE
:Platform_create_Device
A request to a bridge to register a new device on a platform. INTER-MW → Bridge
PLATFORM_UPDATE_DEVICE
:Platform_update_Device
A request to a bridge to update information about a device managed by a platform. INTER-MW → Bridge
PLATFORM_DELETE_DEVICE
:Platform_delete_Device
A request for a platform to stop managing (i.e. unregister) a device. INTER-MW → Bridge
OBSERVATION
:Observation
A message with a single observation in the payload. It is sent from the bridge as a result of a QUERY, a previous subscription; or from INTER-MW to a bridge to push the observation to a platform. Observations are also the constant response to a subscription - INTER-MW will expect observations, as long as a subscription is active. INTER-MW → Bridge Bridge → INTER-MW
ACTUATION
:Actuation
A message with an action to be performed by a device. The payload contains an actuation that is the intended result of the actuation. INTER-MW → Bridge
ERROR
:Error
Any error that occurred in INTER-MW, or the bridges can be communicated with a message of type ERROR, including encapsulated Java exceptions. When sent to INTER-MW it arrives at the global error handler. ANY
PLATFORM_REGISTER
:Platform_register
A message to INTER-MW to start managing a bridge, that includes basic bridge configuration parameters. This message results in creation of a new Platform entry in INTER-MW platform registry, and creates (and sets up) a bridge instance. Client App → INTER-MW
PLATFORM_UNREGISTER
:Platform_unregister
A message for INTER-MW to stop managing a platform. Its information is removed from INTER-MW registries, and the bridge performs cleanup operations. Finally, the bridge itself is destroyed. Client App → INTER-MW
PLATFORM_UPDATE
:Platform_update
A message to INTER-MW Platform registry, with updated information about a previously registered platform. Not every platform property may be updated - some changes may require unregistering a platform, and registering it again. In particular, the platform type and ID may not be updated. Client App → INTER-MW
PLATFORM_DISCOVERY_QUERY
:Platform_discovery_query
A message with a query to INTER-MW Platform registry, to which INTER-MW will respond with a list of platform IDs. Client App → INTER-MW
LIST_SUPPORTED_PLATFORM_TYPES
:List_supported_platform_types
A message with a query to INTER-MW, to which INTER-MW will respond with a list of typed platforms. Each platform in INTER-MW may have multiple types, and each typed platform entity corresponds to a platform type supported by INTER-MW. In other words, a response to LIST_PLATFORM_TYPES informs about the types of platforms that may be registered with a given instance of INTER-MW, and directly corresponds to the bridges available in a particular INTER-MW deployment. In Java, methods from message.utils.INTERMWUtils may be used to obtain a list of supported platform types. Client App → INTER-MW
CLIENT_REGISTER
:Client_register
A message from a Client App INTER-MW informing about the client App itself, and registering it with INTER-MW. Client App → INTER-MW
CLIENT_UNREGISTER
:Client_unregister
A message from a Client App asking INTER-MW to forget about it. Cient App → INTER-MW

TODO: Describe message routing through IPSM.

MessageType Java enum/
RDF Message type
Comment Syntactic Translation IPSM
META
:meta
Not relevant to translation.
UNRECOGNIZED
N/A
Not relevant to translation.
RESPONSE
:response
Not relevant to translation.
SYS_INIT
:Sys_init
Not relevant to translation.
SUBSCRIBE
:Subscribe
Subscription message has a list of IDs in the payload, which can be retrieved using Java methods. Semantic translation could potentially change entity types from iiot:IoTDevice to another type. Because the iiot:IoTDevice type is required for the Java libraries to work correctly, the payload should not be translated semantically. Depending on the platform, syntactic translation is probably unnecessary, because subscription to a platform should be formed by the bridge directly. If a bridges syntactic translator can construct a proper subscribe message for a platform, from only a list of devices, then the translation may be applied. (YES)/NO NO
UNSUBSCRIBE
:Unsubscribe
Similar to SUBSCRIBE. (YES)/NO NO
DEVICE_ADD_OR_UPDATE
:Device_Add
YES YES
DEVICE_REMOVE
:Device_Remove
YES YES
DEVICE_REGISTRY_INITIALIZE
:Device_Init
YES YES
LIST_DEVICES
:Discovery_List
This message does not have a relevant payload. NO NO
DISCOVERY_QUERY
:Device_discovery_query
Apps should provide correct INTER-MW message format and semantics, or use a REST call to INTER-MW API. In the first case, INTER-MW should offer translation services, and the App must decide if there is a need to use them.
QUERY
:Query
PLATFORM_CREATE_DEVICE
:Platform_create_Device
PLATFORM_UPDATE_DEVICE
:Platform_update_Device
PLATFORM_DELETE_DEVICE
:Platform_delete_Device
OBSERVATION
:Observation
ACTUATION
:Actuation
ERROR
:Error
PLATFORM_REGISTER
:Platform_register
PLATFORM_UNREGISTER
:Platform_unregister
PLATFORM_UPDATE
:Platform_update
NO NO
PLATFORM_DISCOVERY_QUERY
:Platform_discovery_query
LIST_SUPPORTED_PLATFORM_TYPES
:List_supported_platform_types
NO NO
CLIENT_REGISTER
:Client_register
CLIENT_UNREGISTER
:Client_unregister

Example messages

TODO: Describe example messages, and add more

Simple device

{
  "@graph": [
    {
      "@graph": [
        {
          "@id": "InterIoTMsg:meta/36d6-49a2-82ec-d909d8e6f10b",
          "@type": [
            "InterIoTMsg:meta",
            "InterIoTMsg:Device_Add"
          ],
          "InterIoTMsg:SenderPlatformId": {
            "@id": "http://om2m.org/myPlatform"
          },
          "InterIoTMsg:conversationID": "conv614d3621-7399-45b1-bf2f-505b24045ea7",
          "InterIoTMsg:dateTimeStamp": "2018-01-15T15:49:00.655+01:00",
          "InterIoTMsg:messageID": "msg7713aa0f-61df-471d-beec-80e8fb71528b"
        }
      ],
      "@id": "InterIoTMsg:metadata"
    },
    {
      "@graph": [
        {
          "@id": "http://myplatform:8080/weather/station2",
          "@type": [
            "iiot:IoTDevice",
            "sosa:Sensor"
          ],
          "InterIoT:GOIoTP#hasName": "Weather Station 1",
          "InterIoT:GOIoTP#hasDescription": "Second Weather Station on the mountain, which is itself also a sensor",
          "sosa:observes": {
            "@id": "http://myplatform:8080/weather/station2/temperature"
          }
        },
        {
          "@id": "http://myplatform:8080/weather/station2/temperature",
          "@type": [
            "iiotex:Temperature",
            "sosa:ObservableProperty",
            "ssn:Property"
          ],
          "iiot:hasDescription": "air temperature on the mountain top, second weather station"
        }
      ],
      "@id": "InterIoTMsg:payload"
    }
  ],
  "@context": {
    "InterIoTMsg": "http://inter-iot.eu/message/",
    "InterIoT": "http://inter-iot.eu/",
    "sosa": "http://www.w3.org/ns/sosa/",
    "iiot": "http://inter-iot.eu/GOIoTP#"
  }
}

Device

{
  "@graph": [
    {
      "@graph": [
        {
          "@id": "InterIoTMsg:meta/36d6-49a2-82ec-d909d8e6f10b",
          "@type": [
            "InterIoTMsg:meta",
            "InterIoTMsg:Device_Add"
          ],
          "InterIoTMsg:SenderPlatformId": {
            "@id": "http://om2m.org/myPlatform"
          },
          "InterIoTMsg:conversationID": "conv614d3621-7399-45b1-bf2f-505b24045ea7",
          "InterIoTMsg:dateTimeStamp": "2018-01-15T15:49:00.655+01:00",
          "InterIoTMsg:messageID": "msg7713aa0f-61df-471d-beec-80e8fb71528b"
        }
      ],
      "@id": "InterIoTMsg:metadata"
    },
    {
      "@graph": [
        {
          "@id": "http://myplatform:8080/weather/station1",
          "@type": ["http://inter-iot.eu/GOIoTP#IoTDevice", "ssn:System"],
          "iiotex:hasLocalID": "WS_1",
          "iiot:hasName": "Weather Station 1",
          "iiot:hasDescription": "First Weather Station on the mountain",
          "iiot:hasLocation": {
            "@id": "_b3"
          },
          "iiot:hasCoverage": {
            "@id": "_b4"
          },
          "sosa:hosts": [
            {
              "@id": "_:b0"
            },
            {
              "@id": "_:b1"
            },
            {
              "@id": "_:b2"
            }
          ]
        },
        {
          "@id": "_b3",
          "@type": [
            "iiot:Location",
            "geosparql:Geometry"
          ],
          "geosparql:asWKT": {
            "@type": "geosparql:wktLiteral",
            "@value": "POINT(46.9726 11.7250)"
          }
        },
        {
          "@id": "_b4",
          "@type": [
            "iiot:Location",
            "geosparql:Geometry"
          ],
          "geosparql:asWKT": {
            "@type": "geosparql:wktLiteral",
            "@value": "POLYGON((46.9809 11.9221, 46.9702 11.9299, 46.8717 11.638, 46.9876 11.8250, 46.9916 11.7251))"
          }
        },
        {
          "@id": "_:b0",
          "@type": "sosa:Sensor",
          "sosa:isHostedBy": {
            "@id": "http://myplatform:8080/weather/station1"
          },
          "sosa:observes": {
            "@id": "_b5"
          }
        },
        {
          "@id": "_:b1",
          "@type": "sosa:Sensor",
          "sosa:isHostedBy": {
            "@id": "http://myplatform:8080/weather/station1"
          }
        },
        {
          "@id": "_:b2",
          "@type": "sosa:Actuator",
          "sosa:isHostedBy": {
            "@id": "http://myplatform:8080/weather/station1"
          },
          "ssn:forProperty": {
            "@id": "_b6"
          }
        },
        {
          "@id": "_b5",
          "@type": [
            "iiotex:Temperature",
            "sosa:ObservableProperty",
            "ssn:Property"
          ],
          "iiot:hasDescription": "air temperature on the mountain top",
          "sosa:isObservedBy": {
            "@id": "_b0"
          }
        },
        {
          "@id": "_b6",
          "@type": [
            "sosa:ActuatableProperty",
            "ssn:Property"
          ],
          "iiot:hasDescription": "Rain catcher open/close"
        }
      ],
      "@id": "InterIoTMsg:payload"
    }
  ],
  "@context": {
    "InterIoTMsg": "http://inter-iot.eu/message/",
    "InterIoT": "http://inter-iot.eu/",
    "ssn": "http://www.w3.org/ns/ssn/",
    "sosa": "http://www.w3.org/ns/sosa/",
    "iiot": "http://inter-iot.eu/GOIoTP#",
    "iiotex": "http://inter-iot.eu/GOIoTPex#",
    "geosparql": "http://www.opengis.net/ont/geosparql#",
    "geosparqlf": "http://www.opengis.net/def/function/geosparql/"
  }
}

Simple observation

{
  "@graph": [
    {
      "@graph": [
        {
          "@id": "InterIoTMsg:meta/36d6-49a2-82ec-d909d8e6f10b",
          "@type": [
            "InterIoTMsg:meta",
            "InterIoTMsg:Observation"
          ],
          "InterIoTMsg:SenderPlatformId": {
            "@id": "http://om2m.org/myPlatform"
          },
          "InterIoTMsg:conversationID": "conv614d3621-7399-45b1-bf2f-505b24045ea7",
          "InterIoTMsg:dateTimeStamp": "2018-01-15T15:49:00.655+01:00",
          "InterIoTMsg:messageID": "msg7713aa0f-61df-471d-beec-80e8fb71528b"
        }
      ],
      "@id": "InterIoTMsg:metadata"
    },
    {
      "@graph": [
        {
          "@id": "_:b1",
          "@type": "sosa:Observation",
          "sosa:resultTime": {
            "@type": "http://www.w3.org/2001/XMLSchema#dateTime",
            "@value": "2018-05-06T12:36:12Z"
          },
          "sosa:hasResult": {
            "@id": "_:b0"
          },
          "sosa:madeBySensor": {
            "@id": "http://localhost:8080/weather/station2"
          },
          "sosa:observedProperty": {
            "@id": "http://localhost:8080/weather/station2/temperature"
          }
        },
        {
          "@id": "_:b0",
          "@type": "sosa:Result",
          "iiot:hasResultValue": {
            "@type": "http://www.w3.org/2001/XMLSchema#long",
            "@value": "15"
          },
          "iiot:hasUnit": {
            "@id": "sweet_units:celsius"
          }
        }
      ],
      "@id": "InterIoTMsg:payload"
    }
  ],
  "@context": {
    "InterIoTMsg": "http://inter-iot.eu/message/",
    "InterIoT": "http://inter-iot.eu/",
    "sosa": "http://www.w3.org/ns/sosa/",
    "iiot": "http://inter-iot.eu/GOIoTP#"
  }
}

Observation

{
  "@graph": [
    {
      "@graph": [
        {
          "@id": "InterIoTMsg:meta/b453273f-36d6-49a2-82ec-d909d8e6f10a",
          "@type": [
            "InterIoTMsg:meta",
            "InterIoTMsg:Observation"
          ],
          "InterIoTMsg:ReceiverPlatformId": {
            "@id": "http://om2m.org/myPlatform"
          },
          "InterIoTMsg:conversationID": "conv614d3621-7399-45b1-bf2f-505b24045ea6",
          "InterIoTMsg:dateTimeStamp": "2018-01-15T21:49:00.655+01:00",
          "InterIoTMsg:messageID": "msg7713aa0f-61df-471d-beec-80e8fb71528a"
        }
      ],
      "@id": "InterIoTMsg:metadata"
    },
    {
      "@graph": [
        {
          "@id": "_:b1",
          "@type": "sosa:Observation",
          "iiot:hasName": "tempOutside",
          "sosa:resultTime": {
            "@type": "http://www.w3.org/2001/XMLSchema#dateTime",
            "@value": "2018-04-06T12:36:12Z"
          },
          "sosa:hasResult": {
            "@id": "_:b2"
          },
          "sosa:madeBySensor": {
            "@id": "_:b0"
          }
        },
        {
          "@id": "_:b2",
          "@type": "sosa:Result",
          "iiot:hasResultValue": {
            "@type": "http://www.w3.org/2001/XMLSchema#long",
            "@value": "32"
          },
          "iiot:hasUnit": {
            "@id": "sweet_units:celsius"
          }
        },
        {
          "@id": "http://localhost:8080/weather/station1",
          "@type": "http://inter-iot.eu/GOIoTP#IoTDevice",
          "InterIoT:GOIoTP#hasName": "Weather Station 1"
        },
        {
          "@id": "_:b0",
          "@type": "sosa:Sensor",
          "sosa:isHostedBy": {
            "@id": "http://localhost:8080/in-name/humidity"
          }
        }
      ],
      "@id": "InterIoTMsg:payload"
    }
  ],
  "@context": {
    "InterIoTMsg": "http://inter-iot.eu/message/",
    "InterIoT": "http://inter-iot.eu/",
    "sosa": "http://www.w3.org/ns/sosa/",
    "iiot": "http://inter-iot.eu/GOIoTP#"
  }
}

Simple Actuation

{
  "@graph": [
    {
      "@graph": [
        {
          "@id": "InterIoTMsg:meta/36d6-49a2-82ec-d909d8e6f10b",
          "@type": [
            "InterIoTMsg:meta",
            "InterIoTMsg:Actuation"
          ],
          "InterIoTMsg:SenderPlatformId": {
            "@id": "http://om2m.org/myPlatform"
          },
          "InterIoTMsg:conversationID": "conv614d3621-7399-45b1-bf2f-505b24045ea7",
          "InterIoTMsg:dateTimeStamp": "2018-01-15T15:49:00.655+01:00",
          "InterIoTMsg:messageID": "msg7713aa0f-61df-471d-beec-80e8fb71528b"
        }
      ],
      "@id": "InterIoTMsg:metadata"
    },
    {
      "@graph": [
        {
          "@id": "http://inter-iot.eu/light/L01",
          "@type": "sosa:Actuator",
          "sosa:madeActuation": {
            "@id": "_b0"
          }
        },
        {
          "@id": "_:b0",
          "@type": "sosa:Actuation",
          "sosa:resultTime": {
            "@type": "http://www.w3.org/2001/XMLSchema#dateTime",
            "@value": "2018-07-06T12:36:12Z"
          },
          "sosa:hasResult": {
            "@id": "_:b1"
          },
          "ssn:actsOnProperty": {
            "@id": "http://inter-iot.eu/syntax/WSO2Port#lights"
          }
        },
        {
          "@id": "_:b1",
          "@type": "sosa:Result",
          "iiot:hasResultValue": {
            "@value": true
          },
          "ssn:forProperty": {
            "@id": "http://inter-iot.eu/syntax/WSO2Port#lights"
          }
        },
        {
          "@id": "http://inter-iot.eu/syntax/WSO2Port#lights",
          "@type": [
            "sosa:ActuatableProperty",
            "ssn:Property"
          ],
          "iiotex:hasLocalId": "lights"
        }
      ],
      "@id": "InterIoTMsg:payload"
    }
  ],
  "@context": {
    "InterIoTMsg": "http://inter-iot.eu/message/",
    "InterIoT": "http://inter-iot.eu/",
    "ssn": "http://www.w3.org/ns/ssn/",
    "sosa": "http://www.w3.org/ns/sosa/",
    "iiot": "http://inter-iot.eu/GOIoTP#",
    "iiotex": "http://inter-iot.eu/GOIoTPex#",
    "geosparql": "http://www.opengis.net/ont/geosparql#",
    "geosparqlf": "http://www.opengis.net/def/function/geosparql/"
  }
}

Actuation

{
  "@graph": [
    {
      "@graph": [
        {
          "@id": "InterIoTMsg:meta/36d6-49a2-82ec-d909d8e6f10b",
          "@type": [
            "InterIoTMsg:meta",
            "InterIoTMsg:Actuation"
          ],
          "InterIoTMsg:SenderPlatformId": {
            "@id": "http://om2m.org/myPlatform"
          },
          "InterIoTMsg:conversationID": "conv614d3621-7399-45b1-bf2f-505b24045ea7",
          "InterIoTMsg:dateTimeStamp": "2018-01-15T15:49:00.655+01:00",
          "InterIoTMsg:messageID": "msg7713aa0f-61df-471d-beec-80e8fb71528b"
        }
      ],
      "@id": "InterIoTMsg:metadata"
    },
    {
      "@graph": [
        {
          "@id": "http://localhost:8080/weather/station1",
          "@type": "http://inter-iot.eu/GOIoTP#IoTDevice",
          "iiotex:hasLocalID": "WS_1",
          "iiot:hasName": "Weather Station 1",
          "iiot:hasDescription": "First Weather Station on the mountain",
          "sosa:hosts": [
            {
              "@id": "_:b0"
            }
          ]
        },
        {
          "@id": "_:b0",
          "@type": "sosa:Actuator",
          "sosa:isHostedBy": {
            "@id": "http://localhost:8080/weather/station1"
          },
          "ssn:forProperty": {
            "@id": "_b6"
          },
          "sosa:madeActuation": {
            "@id": "_b1"
          }
        },
        {
          "@id": "_b6",
          "@type": [
            "sosa:ActuatableProperty",
            "ssn:Property"
          ],
          "iiot:hasDescription": "Rain catcher open/close"
        },
        {
          "@id": "_:b1",
          "@type": "sosa:Actuation",
          "sosa:resultTime": {
            "@type": "http://www.w3.org/2001/XMLSchema#dateTime",
            "@value": "2018-07-06T12:36:12Z"
          },
          "sosa:hasResult": {
            "@id": "_:b2"
          },
          "sosa:actuationMadeBy": {
            "@id": "_:b0"
          },
          "ssn:forProperty": {
            "@id": "http://inter-iot.eu/syntax/WSO2Port#lights"
          }
        },
        {
          "@id": "_:b2",
          "@type": "sosa:Result",
          "iiot:hasResultValue": {
            "@type": "http://www.w3.org/2001/XMLSchema#boolean",
            "@value": true
          }
        }
      ],
      "@id": "InterIoTMsg:payload"
    }
  ],
  "@context": {
    "InterIoTMsg": "http://inter-iot.eu/message/",
    "InterIoT": "http://inter-iot.eu/",
    "ssn": "http://www.w3.org/ns/ssn/",
    "sosa": "http://www.w3.org/ns/sosa/",
    "iiot": "http://inter-iot.eu/GOIoTP#",
    "iiotex": "http://inter-iot.eu/GOIoTPex#",
    "geosparql": "http://www.opengis.net/ont/geosparql#",
    "geosparqlf": "http://www.opengis.net/def/function/geosparql/"
  }
}