Changes to Twin ID and iotics-host-lib - effective 1 November 2022
- Twin ID will be standardised across the IOTICS API
- 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 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}}
- It was:
- Upsert Twin payload:
{"twinId": {"hostId": host_id, "id": twin_did}}
- It was:
{"twinId": twin_did}
- It was:
- Update Twin endpoint:
{HOST}/qapi/hosts/{host_id}/twins/{twin_did}
- It was:
{HOST}/qapi/twins/{twin_did}
- It was:
- Describe Twin endpoint:
{HOST}/qapi/hosts/{host_id}/twins/{twin_did}
- It was:
{HOST}/qapi/twins/{twin_did}
- It was:
- Delete Twin endpoint:
{HOST}/qapi/hosts/{host_id}/twins/{twin_did}
- It was:
{HOST}/qapi/twins/{twin_did}
- It was:
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
- It was:
- Create Feed payload:
{"id": feed_id}
- It was:
{"feedId": {"value": feed_id}}
- It was:
- Describe Feed endpoint:
{HOST}/qapi/hosts/{host_id}/twins/{twin_did}/feeds/{feed_id}
- It was:
{HOST}/qapi/twins/{twin_did}/feeds/{feed_id}
- It was:
- Update Feed endpoint:
{HOST}/qapi/hosts/{host_id}/twins/{twin_did}/feeds/{feed_id}
- It was:
{HOST}/qapi/twins/{twin_did}/feeds/{feed_id}
- It was:
- Delete Feed endpoint:
{HOST}/qapi/hosts/{host_id}/twins/{twin_did}/feeds/{feed_id}
- It was:
{HOST}/qapi/twins/{twin_did}/feeds/{feed_id}
- It was:
- List All Feeds endpoint:
{HOST}/qapi/hosts/{host_id}/twins/{twin_did}/feeds
- It was:
{HOST}/qapi/twins/{twin_did}/feeds
- It was:
- 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
- It was:
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}
- It was:
- Delete Input endpoint:
{HOST}/qapi/hosts/{host_id}/twins/{twin_did}/inputs/{input_id}
- It was:
{HOST}/qapi/twins/{twin_did}/inputs/{input_id}
- It was:
- 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
- It was:
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
- IOTICS API (REST): API Reference in Swagger / OpenAPI
- IOTICS API (gRPC): New proto files on GitHub
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:
- 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 theexamples
folder calledIdentityAuth
. It is used by any example code within the aforementioned directory. - 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.
Updated about 2 years ago