Archive - Tutorial 3 - Searching

❗️

Opps

This page has been deprecated, if you have found your way here please head back to the Welcome page!

Now that we know how to create twins and share and subscribe to feeds, we need to know how to find Twins. By the end of this tutorial you will know how to search for twins.

Before you begin

Make sure you create a file with the content in Tutorial 2 You can then run that file in the REPL with:

exec(open("./iotics_tutorial.py").read())

❗️

Warning - Known Issue

If the STOMP client socket disconnects you must invoke stomp_client.disconnect() manually before attempting a reconnect.

You can invoke the disconnectfunction in the on_disconnect() callback of the implemented listener.

Search request concepts

Search is an async operation performed over STOMP because of the decentralised nature of the system. A search request is dispatched to the network of interconnected hosts and the results streamed to the client.

A client must send a search request over the host /qapi/searches/requests specifying a unique Iotics-ClientRef header value; each search response matching the request, for each host in the network, will be returned with the specified input ClientRef.

A search request has the following attributes:

Request filters: A search request consists of one or more filters that are expressed:

  • Location filter: specifies a filter matching twins having a location matching an area centered in the filter “location” lat/lon and a radius specified in the filter.
  • Text: text search on the basic twin metadata such as comments, labels, tags.
  • Properties: properties will be discussed in the next tutorial

Scope: A request parameter used to apply a scope to a given request:

  • GLOBAL - go over the network/target the public Twin
  • LOCAL - restrain the request to the local host

Request timeout: Client request timeout used to stop the request processing once the timeout is reached. A client is stating that it’s prepared to wait until this timeout. Any search response after this timeout will be discarded or ignored. HOSTs in the network will reserve the right to ignore the request if the timeout has expired or if the result can’t be provided within the requested timeout.

Response type: The response type determines whether the response contains or not details about the found entities.

  • FULL: verbose response for each entity
  • MINIMAL: essential parts of each entity
  • LOCATED:

Limit: Limit is a request parameter to limit the number of results. The use of "Limit" is:

  • if limit is not supplied or supplied with no limit value, assume default=500
  • if limit is supplied assume max number of entries is whatever specified. The limit value is capped to 1000.

Offset: Offset is a request parameter applicable in conjunction with the "Limit" request parameter to start returning results from the given offset.

Preparing the STOMP client

It’s assumed the iotics_tutorial.py has successfully run and the STOMP client is correctly created in stomp_client:

stomp_client.set_listener("log_listener", PrintingListener())

token = agent2_identity.document_manager.new_token(principal_did=user_key.id, duration=3600, audience=host.address)
stomp_client.connect(wait=True, passcode=token)

Subscribing to search responses

Search responses are delivered to a shared topic:

stomp_client.subscribe(destination="/qapi/searches/results", id=1, headers=iotics_stomp_headers(agent2_identity))

🚧

Note

To receive search responses you need subscribe: /qapi/searches/results

Sending search requests and parsing the results

search_payload={
  "filter": {
    "location": {
      "radiusKm": 20,
      "location": {
        "lat": 6.027456183070403,
        "lon": 1.4658129805029452
      }
    },
    "text": "some text",
  },
  "expiryTimeout": "2040-01-23T04:56:07+00:00"
}
stomp_client.send('/qapi/searches/dispatches', headers=iotics_stomp_headers(agent2_identity), body=json.dumps(search_payload))

The printing listener should display the search result (likely to be empty unless there’s a real match for search text within 20Km from the specified location.

The request will be discarded if the server attempting to match it, won’t be able to respond, or receives the request after the expiryTimeout.

🚧

Note

To dispatch search requests you must sent to the topic: /qapi/searches/dispatches

The search response will be returned with Iotic-ClientRef matching the one set in the request.

Parsing search responses

Each response from the server is a STOMP frame with

{'content-length': '958', 
  'Iotics-ClientRef': 'd-poc-4rnRhk5o', 
  'Iotics-ClientAppId': 'did:iotics:iotJmRTuP5yJmM3zqVKaqXbujLkb9isDHGQw', 
  'Iotics-TransactionRef': 'usOBrL0sRr6MmSEUGXG66A', 
  'ack': 'auto', 
  'destination': '/qapi/searches/results', 
  'message-id': '6dcb0e63-6449-4ce5-835f-87983e3a44bc', 
  'content-type': 'application/json', 
  'id': '1', 
  'subscription': '1'
}

and a body of the form:

{
    "responseType": "FULL",
    "twins": [{
        "id": { "value": "did:iotics:iotZZZZ"}
        ...
      },
      {
      ...
      },
    ...
    ]
}

For example:

{
            "id": {
                "value": "did:iotics:iotTzCmwcpndoeJUggEcoHw5mhgfZpbejYze"
            },
            "location": {
                "lat": 51.26391852277632,
                "lon": -1.1035326924247784
            },
            "label": "EV Station - The GeniePoint Network ( Engie EV Solutions ) @ Mor",
            "tags": [
                "cat_transport",
                "tutorial",
                "charger",
                "vehicle",
                "station",
                "electric"
            ],
            "properties": [
                {
                    "key": "http://data.iotics.com/ns/category",
                    "uriValue": {
                        "value": "http://data.iotics.com/category/Transport"
                    }
                },
                {
                    "key": "http://demo.iotics.com/ont/ev/type",
                    "stringLiteralValue": {
                        "value": "charger"
                    }
                }
            ],
            "feeds": [
                {
                    "feed": {
                        "id": {
                            "value": "status"
                        },
                        "twinId": {
                            "value": "did:iotics:iotTzCmwcpndoeJUggEcoHw5mhgfZpbejYze"
                        }
                    },
                    "label": "status",
                    "storeLast": true
                },
                {
                    "feed": {
                        "id": {
                            "value": "forecast"
                        },
                        "twinId": {
                            "value": "did:iotics:iotTzCmwcpndoeJUggEcoHw5mhgfZpbejYze"
                        }
                    },
                    "label": "busy forecast in 1 and 2 hours",
                    "storeLast": true
                }
            ]
        },