Changes to Twin ID and iotics-host-lib - effective 1 November 2022

  1. Twin ID will be standardised across the IOTICS API
  2. iotics-host-lib will be deprecated and no longer supported

This will introduce a breaking change and will likely require you to update your code.

This page covers:

  1. Standardisation of ID across the IOTICS API
  2. Deprecation of iotics-host-lib

1. Standardisation of Twin ID across the IOTICS API

Overview

From 1 November 2022, the use of the TwinID object will be standardised across the IOTICS API to support further development of Linked Data.

Where we have used a single value, e.g. TwinID {"value": "did:iotics:iot12345128492"}, the ID will be made up of two values, e.g. TwinID {"id": "did:iotics:iot12345128492", "hostId": "did:iotics:iotabcdefghi"}. The new TwinID will correspond to the existing "value" object (now renamed to "id") and the hostId refers to the corresponding IOTICSpace's Host Twin DID.

Before the changes: TwinID { "value": "did:iotics:iot12345128492"}

After the changes: TwinID {"id": "did:iotics:iot12345128492", "hostId": "did:iotics:iotabcdefghi"}
   * where id corresponds to the current "value";
   * where hostId corresponds to the Host Twin DID of the IOTICSpace ("Host") where that Digital Twin lives

General data changes

  • GetHostId - will now return hostTwinDID instead of peerID.
  • DEPRECATING "internal" /healthendpoint

IOTICS API (gRPC)

Before:

  • the response payload includes only the TwinId’s value;
  • operations with local or remote Twins (like “describe Twin”, “send Input message”, “follow Feed”, etc.) have different fields for TwinID and remoteHostID.

After:

  • the response payload will include the id (previous: value) along with the hostId;
  • operations with local or remote Twins will have a single object with 2 fields: id and hostId where the latter can also be empty.

IOTICS API (REST) and STOMP Client

Before:

  • all REST operations with local or remote Twins (like “describe Twin”, “send Input message”, “follow Feed”, etc.) have different endpoints depending on whether the operation is local or remote (like “describe Twin” and “Describe remote Twin”, or “Follow Feed” and “Follow remote Feed”)

After:

  • all REST operations with remote Twins/Feeds/Inputs will be renamed exactly like the current local operations (like “describe remote Twin” to “describe Twin” or “Follow remote Feed” to “Follow Feed”) and accept a new parameter called hostId that must be non-empty if the user wants to perform a remote operation.
  • all REST operations with local Twins/Feeds/Inputs will be renamed by adding the word “local” to their endpoint (like “describe Twin” to “describe local Twin”), and marked as deprecated (non-maintained but still usable)
  • Please note: if a remote hostId is passed to a “local only” REST endpoint, an error will be returned.

List of all affected API functions

Twin API: click to see all affected functions

CreateTwin

  • Request - Payload now contains a String id
  • Response - Payload now contains compositeTwinID twinId

DeleteTwin

  • Request - Arguments now contains composite TwinID twinId
  • Response - Payload now contains compositeTwinID twinId

DescribeTwin

  • Request:
    • Arguments now contains composite TwinID twinId
    • HostID remoteHostId will be removed in favour of composite key as above
  • Response:
    • Existing TwinID twinId object will now reference the composite key in Payload
    • Deprecated Visibility will be moved to Payload.MetaResult alongside other meta (location/feeds/inputs/props)

UpdateTwin

  • Request: Arguments now contains composite TwinID twinId
  • Response: Payload now contains composite TwinID twinId

UpsertTwin

  • Request: Payload now contains composite TwinID twinId instead of string twinId
  • Response: Payload now contains composite TwinID twinId instead of string twinId
Feed API: click to see all affected functions

CreateFeed

  • Request: Arguments now contains a String id
  • Response: Payload.feed now contains composite TwinID twinId

DeleteFeed

  • Request: Arguments.feed now contains compositeTwinID twinId
  • Response: Payload.feed now contains compositeTwinID twinId

DescribeFeed

  • Request:
    • Arguments.feed now contains composite TwinID twinId
    • HostID remoteHostId will be removed from Arguments in favour of hostId inside Arguments.feed.twinId as above
  • Response:
    • Payload.feed now contains composite TwinID twinId
    • HostID remoteHostId will be removed from Payload in favour of hostId inside Payload.feed.twinId as above

UpdateFeed

  • Request: Arguments.feed now contains composite TwinID twinId
  • Response: Payload.feed now contains composite TwinID twinId

ListAllFeeds

  • Request: Payload now contains composite TwinID twinId
  • Response: Payload.feedIds list now contains composite TwinID twinId inside each feedID object

ShareFeedData

  • Request: Arguments.feedId now contains compositeTwinID twinId
  • Response: N/A
Input API: click to see all affected functions

DeleteInput

  • Request: Arguments.input now contains composite TwinID twinId
  • Response: Payload.input now contains composite TwinID twinId

DescribeInput

  • Request:
    • Arguments.input now contains composite TwinID twinId
    • HostID remoteHostId will be removed from Arguments in favour of hostId inside Arguments.input.twinId as above
  • Response:
    • Payload.input now contains composite TwinID twinId
    • HostID remoteHostId will be removed from Payload in favour of hostId inside Payload.input.twin as above

ReceiveInputMessages

  • Request: Arguments.input now contains composite TwinID twinId
  • Response: Payload.input now contains composite TwinID twinId
Search API: click to see all affected functions

DispatchSearchRequest

  • no change

SynchronousSearch/ReceiveAllSearchResponses

  • no change

SearchRequest

  • no change

SearchResponse

  • Each twin object in Payload.twins list now contains composite TwinID twinId
  • HostID remoteHostId will be removed from Payload in favour of hostId inside each twin object in Payload.twins as above
  • Each twin object in Payload.twins will now contain composite TwinID twinId inside each feed and input
Interest API: click to see all affected functions

Most requests below reference a nested Interest object. Changes here will be reflected across the Interest API.

For example

message Interest {
  // FollowedFeed fully identify the (local or remote) feed to follow.
  message FollowedFeed {
    // Followed feed identifier
    Feed feed = 1;
    // Feed remote host identifier (If not specified, the Interest is taken to be in scope of the host from which a request is made.)
    HostID hostId = 2;
  }

  // Follower twin unique identifier.
  TwinID followerTwinId = 2;

  // a reference to the interested feed
  FollowedFeed followedFeed = 3;
}
message Interest {
  // Follower twin unique identifier.
  TwinID followerTwinId = 1; <---contains hostId

  // a reference to the interested feed
  FeedID followedFeedId = 2; <---contains hostId
}

CreateInterest

  • Request: Arguments will now contain composite TwinID twinId (see change in Interest object above)
  • Response: Se change in Interest object above

DeleteInterest

  • Request: See change in Interest object above
  • Response: See change in Interest object above

ListAllInterests

  • Request: Arguments will now contain composite TwinID twinId
  • Response: Each interest object in Payload.interests: See change in Interest object above

FetchInterests

  • Request: See change in Interest object above
  • Response: See change in Interest object above

FetchLastStored

  • Request: See change in Interest object above
  • Response: See change in Interest object above

SendInputMessage

  • Request:
    • Arguments.interest.senderTwinId will now reference the composite TwinID
    • Arguments.interest.destInput.inputId now contains composite TwinID twinId
    • HostID hostId will be removed from Arguments.interest.destInput in favour in favour of hostId inside Arguments.interest.destInput.inputId as above
  • Response: N/A
Meta API: click to see all affected functions

SparqlQuery

  • Request: N/A
  • Response: HostID remoteHostId will be updated to string hostId

SparqlUpdate

  • no change

ExplorerRequest

  • no change

How to update your code

Some REST operations require their endpoint and/or payload format to be changed. In particular the host_id needs to be included within the endpoint.

Twin Operations: click to see the changes

  • Create Twin payload: {"id": twin_did}
    • It was: {"twinId": {"value": twin_did}}
  • Upsert Twin payload: {"twinId": {"hostId": host_id, "id": twin_did}}
    • It was: {"twinId": twin_did}
  • Update Twin endpoint: {HOST}/qapi/hosts/{host_id}/twins/{twin_did}
    • It was: {HOST}/qapi/twins/{twin_did}
  • Describe Twin endpoint: {HOST}/qapi/hosts/{host_id}/twins/{twin_did}
    • It was: {HOST}/qapi/twins/{twin_did}
  • Delete Twin endpoint: {HOST}/qapi/hosts/{host_id}/twins/{twin_did}
    • It was: {HOST}/qapi/twins/{twin_did}
Feed Operations: click to see the changes

  • Create Feed endpoint: {HOST}/qapi/hosts/{host_id}/twins/{twin_did}/feeds
    • It was: {HOST}/qapi/twins/{twin_did}/feeds
  • Create Feed payload: {"id": feed_id}
    • It was: {"feedId": {"value": feed_id}}
  • Describe Feed endpoint: {HOST}/qapi/hosts/{host_id}/twins/{twin_did}/feeds/{feed_id}
    • It was: {HOST}/qapi/twins/{twin_did}/feeds/{feed_id}
  • Update Feed endpoint: {HOST}/qapi/hosts/{host_id}/twins/{twin_did}/feeds/{feed_id}
    • It was: {HOST}/qapi/twins/{twin_did}/feeds/{feed_id}
  • Delete Feed endpoint: {HOST}/qapi/hosts/{host_id}/twins/{twin_did}/feeds/{feed_id}
    • It was: {HOST}/qapi/twins/{twin_did}/feeds/{feed_id}
  • List All Feeds endpoint: {HOST}/qapi/hosts/{host_id}/twins/{twin_did}/feeds
    • It was: {HOST}/qapi/twins/{twin_did}/feeds
  • Share Data Sample via Feed endpoint: {HOST}/qapi/hosts/{host_id}/twins/{twin_did}/feeds/{feed_id}/shares
    • {HOST}/qapi/twins/{twin_did}/feeds/{feed_id}/shares
  • Get Last Shared Value endpoint: {HOST}/qapi/hosts/{follower_host_id}/twins/{follower_twin_did}/interests/hosts/{followed_host_id}/twins/{followed_twin_did}/feeds/{feed_id}/samples/last
    • It was: {HOST}/qapi/twins/{twin_follower_did}/interests/twins/{twin_publisher_did}/feeds/{feed_id}/samples/last
Input Operations: click to see the changes

  • Describe Input endpoint: {HOST}/qapi/hosts/{host_id}/twins/{twin_did}/inputs/{input_id}
    • It was: {HOST}/qapi/twins/{twin_did}/inputs/{input_id}
  • Delete Input endpoint: {HOST}/qapi/hosts/{host_id}/twins/{twin_did}/inputs/{input_id}
    • It was: {HOST}/qapi/twins/{twin_did}/inputs/{input_id}
  • Send Input Message endpoint: {HOST}/qapi/hosts/{sender_host_id}/twins/{sender_twin_did}/interests/hosts/{receiver_host_id}/twins/{receiver_twin_did}/inputs/{input_id}/messages
    • It was: {HOST}/qapi/twins/{sender_twin_did}/interests/twins/{receiver_twin_did}/inputs/{input_id}/messages

The host_id in the endpoint corresponds to the Host Twin's DID. The latter will be returned in the response payload of any operation against Twins/Feeds/Inputs or can be obtained through the following REST call:

  • Method: GET
  • Endpoint: {HOST}/qapi/host/id

Useful links


2. Deprecation of iotics-host-lib

Overview of the changes

From 1 November 2022, iotics-host-lib will be deprecated and can no longer be used. We recommend that users switch to the Python Client Library instead.

The new Python Client Library is built on top of the IOTICS API (gRPC) for improved performance. An introduction to gRPC and an overview of the supported client libraries can be found here.

How to update your code

The iotics-host-lib and the Python Client Library have exactly the same methods to manage your Twins (i.e.: create_twin, share_feed_data, describe_twin, etc.), so your code will not change much. However, there are two major differences in the use of the Python Client Library compared to the iotics-host-lib:

  1. iotics-host-lib includes a pre-made Class to manage the Identities (Users, Agents and Twins) called AgentAuthBuilder that all the Connectors built with this library make use of. The Python Client Library does not provide this functionality out-of-the-box, but it does provide an example on how a similar same-purpose Class can be built. You can find it within the examples folder called IdentityAuth. It is used by any example code within the aforementioned directory.
  2. iotics-host-lib allows the authentication token to be automatically regenerated, so that, as soon as it expires (by default with the iotics-host-lib every 10 minutes), a new token will be created and used. The Python Client Library does not regenerate the token. An example on how to do this will be included within the examples repository shortly.