# OGC STAplus (SensorThings) API Python Client
This STAplus Python Client implements the [STAplus](https://docs.ogc.org/is/22-022r1/22-022r1.html) API. The aim is to simplify development of STAplus and SensorThings enabled client applications.
**_NOTE:_** This implementation is an extension to the [FROST API Python Client](https://github.com/FraunhoferIOSB/FROST-Python-Client). To have better control over bug fixing and improvements, this implementation is actually based on a fork of the FROST API Python Client, hosted on a Secure Dimensions Github repository: [STA Python Client](https://github.com/securedimensions/STA-Python-Client).
## Python Version
This library requires Python 3.11 or better to support parsing ISO datetime values (`datetime.datetime.fromisoformat`). See [here](https://docs.python.org/3/library/datetime.html#datetime.datetime.fromisoformat) for more information.
## Features
* Support for all STAplus and SensorThings entity types
* CRUD operations
* Queries on entity lists
* Query on single entity
* MultiDatastreams
* Cloning Entities
* Fetching entities relative to an entity (using many-association)
* Fetching one single entity relative to an entity (using one-association)
## Installation via PyPi
Installation via pip: `pip install staplus-client`
## Limitations
This implementation has the following limitations for the Entity `Location` and `FeatureOfInterest`:
* `Location/location` must be a GeoJSON Geometry object (this is an Any in the SensorThings datamodel)
* `FeatureOfInterest/feature` must be a GeoJSON Object (this is an Any in the SensorThings datamodel)
For both entities, the `encodingType` attribute is not tested by the implementation. For interoperability with other applications, the value should be `application/geo+json`.
## API
The `STAplusService` class is central to the library. An instance of it represents a STAplus service and is identified by a URI.
### Creating Entities via the STAplus Client
The source code below demonstrates how to initialize the client for a STAplus endpoint on `url`.
```python
import staplus_client as staplus
url = "<your domain>/staplus/v1.1"
service = staplus.STAplusService(url)
```
#### Configuring an Authentication Handler
When interacting with a STAplus service that has enabled authentication, the use of an `AuthHandler` is required.
```python
import staplus_client as staplus
url = "<your domain>/staplus/v1.1"
auth_handler.AuthHandler(...)
service = staPlus.STAplusService(url, auth_handler=auth)
```
#### Creating a Party Entity
The `Party` entity represents a user or an institution. When interacting with a STAplus service that has enabled authentication, the `Party` entity represents the acting user and access control controls Create, Update and Delete.
```python
import staplus_client as staplus
url = "<your domain>/staplus/v1.1"
auth_handler.AuthHandler(...)
service = staPlus.STAplusService(url, auth_handler=auth)
ljs = staPlus.Party(description='I am Long John Silver the opportunistic pirate created by Robert Louis Stevenson',
display_name='LJS',
role='individual')
service.create(ljs)
```
#### Creating a STAplus enriched Datastream
The STAplus `Datastream` is capable to have a `Party` and a `License` associated. Also, the `Thing` is associated to a `Party` entity.
```python
import staplus_client as staplus
url = "<your domain>/staplus/v1.1"
auth_handler.AuthHandler(...)
service = staplus.STAplusService(url, auth_handler=auth)
ljs = staplus.Party(description='I am Long John Silver the opportunistic pirate created by Robert Louis Stevenson',
display_name='LJS',
role='individual')
service.create(ljs)
# find the CC-BY license
cc_by = service.licenses().find('CC_BY')
# Create a thing associated to LJS
thing = staplus.Thing('Raspberry Pi', 'Raspberry Pi 4', )
thing.party = ljs
# Create a sensor
sensor = staplus.Sensor('air temperature sensor', 'SmartCitizen air temperature sensor', 'test/html', None,
'https://www.seeedstudio.com/Smart-Citizen-Starter-Kit-p-2865.html')
# Create a datastream associated to LJS with CC-BY license
datastream = staplus.Datastream('air temperature', 'air temperature measured with the SmartCitizen Kit',
'http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement',
staplus.UnitOfMeasurement('Celsius', 'C', 'https://qudt.org/vocab/unit/DEG_C'))
datastream.observed_property = staplus.ObservedProperty('temperature', 'http://vocabs.lter-europe.net/EnvThes/22035',
'air temperature')
datastream.party = ljs
datastream.thing = thing
datastream.sensor = sensor
datastream.license = cc_by
service.create(datastream)
```
#### Creating a few Observation entities
```python
import staplus_client as staplus
url = "<your domain>/staplus/v1.1"
auth_handler.AuthHandler(...)
service = staplus.STAplusService(url, auth_handler=auth)
ljs = staplus.Party(description='I am Long John Silver the opportunistic pirate created by Robert Louis Stevenson',
display_name='LJS',
role='individual')
service.create(ljs)
# The feature of interest
marienplatz = {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [11.571831046,48.135666124]
}
}
foi = staplus.FeatureOfInterest('Marienplatz', 'famous place in Munich', 'application/vnd.geo+json', marienplatz)
# The temperature
observation = staplus.Observation("2023-07-02T15:34:00Z", 20, "2023-07-02T15:34:00Z")
observation.feature_of_interest = foi
observation.datastream = service.datastreams().find(<the datastream id created previously>)
service.create(observation)
observation = staplus.Observation("2023-07-02T15:34:10Z", 21, "2023-07-02T15:34:10Z")
observation.feature_of_interest = foi
observation.datastream = service.datastreams().find(<the datastream id created previously>)
service.create(observation)
```
#### Creating an ObservationGroup Entity
A `ObservationGroup` entity can be used as a container of observations that belong together.
```python
import staplus_client as staplus
url = "<your domain>/staplus/v1.1"
service = staPlus.STAplusService(url, auth_handler=auth)
ljs = staPlus.Party(description='I am Long John Silver the opportunistic pirate created by Robert Louis Stevenson',
display_name='LJS',
role='individual')
service.create(ljs)
group = staPlus.ObservationGroup("Marienplatz", "observations on Marienplatz", "none", "")
group.creation_time = parse_datetime("2023-07-02T15:35:00Z")
# Add all the observations that are associated to the FoI named 'Marienplatz'
group.observations = service.observations().query().filter("FeatureOfInterest/name eq 'Marienplatz'").list()
group.license = service.licenses().find('CC_BY')
group.party = ljs
service.create(group)
```
#### Creating SensorThings Entities
How to use this implementation on SensorThings Entity Types, please see the [FROST-Python-Client](https://github.com/securedimensions/STAplus-Python-Client) documentation.
### Fetching Entities via the STAplus Client
This implementation supports the fetching of `EntityList` and `Entity`.
#### Fetching an EntityList
An `EntityList` is the result from fetching entities that have a multiplicity `0..*` or `1..*`. To fetch the list of entities, you need to use the `.list()` function. The following example fetches all datastreams:
```python
import staplus_client as staplus
url = "<your domain>/staplus/v1.1"
service = staplus.STAplusService(url)
datastreams = service.datastreams().query().list()
```
In order to get all entities of a given entity, you can use the function `get_<entity_plural>()`. For example, to fetch all datastreams of a given `Thing` please use the following code:
```python
import staplus_client as staplus
url = "<your domain>/staplus/v1.1"
service = staplus.STAplusService(url)
thing = service.things().find(1)
thing_datastreams = thing.get_datastreams().query().list()
```
#### Fetching an Entity
An `Entity` is the result from fetching an entity that has multiplicity `0..1` or `1`. To fetch one single entity you need to use the `.item()` function. The following example fetches the thing associated to a datastream:
```python
import staplus_client as staplus
url = "<your domain>/staplus/v1.1"
service = staplus.STAplusService(url)
datastream = service.datastreams().find(1).item()
datastream_thing = datastream.get_thing().query().item()
```
### Cloning an Entity
When creating an Entity, mandatory entities can be provided either inline or by reference. To support the referencing of existing entities, the `clone()` function can be used. `clone()` returns a copy of the entity but only containing the `@iot.id`. This is important when preparing MQTT messages to publish observations.
#### Example ObservationGroup with inline entities
```JSON
{
"Observations": [
{
"Datastream": {
"@iot.id": 1,
"description": "desc",
"name": "new name",
"observationType": "OM_Observation",
"observedArea": {
"coordinates": [11.509234, 48.110728],
"type": "Point"
},
"phenomenonTime": "2023-07-24T06:30:18+00:00/2023-09-14T05:40:25.292000+00:00",
"resultTime": "2023-07-24T06:30:18+00:00/2023-07-24T06:31:42+00:00",
"unitOfMeasurement": { "definition": "...", "name": "n", "symbol": "n" }
},
"FeatureOfInterest": {
"@iot.id": 77,
"description": "A rainy place",
"encodingType": "application/geo+json",
"feature": { "coordinates": [-6.22299, 53.306816], "type": "Point" },
"name": "Dublin",
"properties": {
"datastreams": [1, 2, 76, 2, 78, 77],
"multi_datastreams": [11]
}
},
"phenomenonTime": "2024-04-13T19:57:08+00:00",
"result": 19.111,
"resultTime": "2024-05-02T19:36:06+00:00"
},
{
"Datastream": {
"@iot.id": 2,
"description": "air relative humidity measured with the SmartCitizen Kit",
"name": "Relative Humidity",
"observationType": "http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement",
"observedArea": {
"coordinates": [11.509234, 48.110728],
"type": "Point"
},
"phenomenonTime": "2023-07-24T06:30:18+00:00/2023-07-24T06:31:42+00:00",
"resultTime": "2023-07-24T06:30:18+00:00/2023-07-24T06:31:42+00:00",
"unitOfMeasurement": {
"definition": "https://qudt.org/vocab/unit/PERCENT",
"name": "Percentage",
"symbol": "%"
}
},
"FeatureOfInterest": {
"@iot.id": 77,
"description": "A rainy place",
"encodingType": "application/geo+json",
"feature": { "coordinates": [-6.22299, 53.306816], "type": "Point" },
"name": "Dublin",
"properties": {
"datastreams": [1, 2, 76, 2, 78, 77],
"multi_datastreams": [11]
}
},
"phenomenonTime": "2024-04-13T19:57:08+00:00",
"result": 43.0,
"resultTime": "2024-05-02T19:36:06+00:00"
},
{
"Datastream": {
"@iot.id": 76,
"description": "Precipitation measured with the FT-0310 Weather Station",
"name": "Rain",
"observationType": "http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement",
"unitOfMeasurement": {
"definition": "https://qudt.org/vocab/unit/MilliM",
"name": "millimiter",
"symbol": "mm"
}
},
"FeatureOfInterest": {
"@iot.id": 77,
"description": "A rainy place",
"encodingType": "application/geo+json",
"feature": { "coordinates": [-6.22299, 53.306816], "type": "Point" },
"name": "Dublin",
"properties": {
"datastreams": [1, 2, 76, 2, 78, 77],
"multi_datastreams": [11]
}
},
"phenomenonTime": "2024-04-13T19:57:08+00:00",
"result": 87.0,
"resultTime": "2024-05-02T19:36:06+00:00"
},
{
"Datastream": {
"@iot.id": 77,
"description": "Wind direction measured with the FT-0310 Weather Station",
"name": "Wind direction",
"observationType": "http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement",
"unitOfMeasurement": {
"definition": "https://qudt.org/vocab/unit/DEG",
"name": "degree",
"symbol": "deg"
}
},
"FeatureOfInterest": {
"@iot.id": 77,
"description": "A rainy place",
"encodingType": "application/geo+json",
"feature": { "coordinates": [-6.22299, 53.306816], "type": "Point" },
"name": "Dublin",
"properties": {
"datastreams": [1, 2, 76, 2, 78, 77],
"multi_datastreams": [11]
}
},
"phenomenonTime": "2024-04-13T19:57:08+00:00",
"result": 241.0,
"resultTime": "2024-05-02T19:36:06+00:00"
},
{
"FeatureOfInterest": {
"@iot.id": 77,
"description": "A rainy place",
"encodingType": "application/geo+json",
"feature": { "coordinates": [-6.22299, 53.306816], "type": "Point" },
"name": "Dublin",
"properties": {
"datastreams": [1, 2, 76, 2, 78, 77],
"multi_datastreams": [11]
}
},
"MultiDatastream": {
"@iot.id": 11,
"ObservedProperties": [
{
"@iot.id": 105,
"definition": "http://vocab.nerc.ac.uk/standard_name/wind_speed/",
"description": "Wind speed",
"name": "wspeed"
},
{
"@iot.id": 106,
"definition": "http://vocab.nerc.ac.uk/standard_name/wind_gust_from_direction/",
"description": "Wind gust",
"name": "wgust"
}
],
"description": "Wind speed average and gust measured with the FT-0310 Weather Station",
"multiObservationDataTypes": [
"http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement",
"http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement"
],
"name": "Wind speed avg and gust",
"observationType": "http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_ComplexObservation",
"unitOfMeasurements": [
{
"definition": "https://qudt.org/vocab/unit/M-PER-SEC",
"name": "Meters per second",
"symbol": "m/s"
},
{
"definition": "https://qudt.org/vocab/unit/M-PER-SEC",
"name": "Meters per second",
"symbol": "m/s"
}
]
},
"phenomenonTime": "2024-04-13T19:57:08+00:00",
"result": [0.0, 0.0],
"resultTime": "2024-05-02T19:36:06+00:00"
}
],
"Party": {
"@iot.id": "36fd7ca4-08bb-11ef-b156-a337e8ef4d15",
"displayName": "LJS",
"role": "individual"
},
"creationTime": "2024-05-02T19:36:06+00:00",
"description": " ",
"endTime": "2024-05-02T19:36:06+00:00",
"name": "OG 2024-05-02T19:36:06+00:00"
}
```
This example with inline `Datastream` and `FeatureOfInterest` entities has the size of 6245 Bytes.
#### Example ObservationGroup with referencing entities
```JSON
{
"Observations": [
{
"Datastream": { "@iot.id": 1 },
"FeatureOfInterest": { "@iot.id": 77 },
"phenomenonTime": "2024-04-13T19:57:08+00:00",
"result": 19.111,
"resultTime": "2024-05-03T09:48:33+00:00"
},
{
"Datastream": { "@iot.id": 2 },
"FeatureOfInterest": { "@iot.id": 77 },
"phenomenonTime": "2024-04-13T19:57:08+00:00",
"result": 43.0,
"resultTime": "2024-05-03T09:48:33+00:00"
},
{
"Datastream": { "@iot.id": 76 },
"FeatureOfInterest": { "@iot.id": 77 },
"phenomenonTime": "2024-04-13T19:57:08+00:00",
"result": 87.0,
"resultTime": "2024-05-03T09:48:33+00:00"
},
{
"Datastream": { "@iot.id": 77 },
"FeatureOfInterest": { "@iot.id": 77 },
"phenomenonTime": "2024-04-13T19:57:08+00:00",
"result": 241.0,
"resultTime": "2024-05-03T09:48:33+00:00"
},
{
"FeatureOfInterest": { "@iot.id": 77 },
"MultiDatastream": { "@iot.id": 11 },
"phenomenonTime": "2024-04-13T19:57:08+00:00",
"result": [0.0, 0.0],
"resultTime": "2024-05-03T09:48:33+00:00"
}
],
"Party": {
"@iot.id": "4cd42a10-0932-11ef-919f-57f24e9b90e3",
"displayName": "LJS",
"role": "individual"
},
"creationTime": "2024-05-03T09:48:33+00:00",
"description": " ",
"endTime": "2024-05-03T09:48:33+00:00",
"name": "OG 2024-05-03T09:48:33+00:00"
}
```
This example with referenced `Datastream` and `FeatureOfInterest` entities has the size of 1420 Bytes.
Raw data
{
"_id": null,
"home_page": "https://github.com/securedimensions/STAplus-Python-Client",
"name": "staplus-client",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "ogc, staplus, sensorthingsapi, IoT",
"author": "Andreas Matheus",
"author_email": "andreas.matheus@secure-dimensions.de",
"download_url": "https://files.pythonhosted.org/packages/89/c1/dfd362fea4ad82106f830b4cd7d7d026a6045280e6c29f819af518c9a945/staplus_client-0.3.3.tar.gz",
"platform": null,
"description": "# OGC STAplus (SensorThings) API Python Client\n\nThis STAplus Python Client implements the [STAplus](https://docs.ogc.org/is/22-022r1/22-022r1.html) API. The aim is to simplify development of STAplus and SensorThings enabled client applications.\n\n**_NOTE:_** This implementation is an extension to the [FROST API Python Client](https://github.com/FraunhoferIOSB/FROST-Python-Client). To have better control over bug fixing and improvements, this implementation is actually based on a fork of the FROST API Python Client, hosted on a Secure Dimensions Github repository: [STA Python Client](https://github.com/securedimensions/STA-Python-Client).\n\n## Python Version\nThis library requires Python 3.11 or better to support parsing ISO datetime values (`datetime.datetime.fromisoformat`). See [here](https://docs.python.org/3/library/datetime.html#datetime.datetime.fromisoformat) for more information.\n\n## Features\n* Support for all STAplus and SensorThings entity types\n* CRUD operations\n* Queries on entity lists\n* Query on single entity\n* MultiDatastreams\n* Cloning Entities\n* Fetching entities relative to an entity (using many-association)\n* Fetching one single entity relative to an entity (using one-association)\n\n## Installation via PyPi\nInstallation via pip: `pip install staplus-client`\n\n## Limitations\nThis implementation has the following limitations for the Entity `Location` and `FeatureOfInterest`:\n\n* `Location/location` must be a GeoJSON Geometry object (this is an Any in the SensorThings datamodel)\n* `FeatureOfInterest/feature` must be a GeoJSON Object (this is an Any in the SensorThings datamodel)\n\nFor both entities, the `encodingType` attribute is not tested by the implementation. For interoperability with other applications, the value should be `application/geo+json`.\n\n## API\n\nThe `STAplusService` class is central to the library. An instance of it represents a STAplus service and is identified by a URI.\n\n\n### Creating Entities via the STAplus Client\nThe source code below demonstrates how to initialize the client for a STAplus endpoint on `url`. \n\n```python\nimport staplus_client as staplus\n\nurl = \"<your domain>/staplus/v1.1\"\nservice = staplus.STAplusService(url)\n```\n\n#### Configuring an Authentication Handler\nWhen interacting with a STAplus service that has enabled authentication, the use of an `AuthHandler` is required.\n\n```python\nimport staplus_client as staplus\n\nurl = \"<your domain>/staplus/v1.1\"\nauth_handler.AuthHandler(...)\nservice = staPlus.STAplusService(url, auth_handler=auth)\n```\n\n#### Creating a Party Entity\nThe `Party` entity represents a user or an institution. When interacting with a STAplus service that has enabled authentication, the `Party` entity represents the acting user and access control controls Create, Update and Delete.\n```python\nimport staplus_client as staplus\n\nurl = \"<your domain>/staplus/v1.1\"\nauth_handler.AuthHandler(...)\nservice = staPlus.STAplusService(url, auth_handler=auth)\nljs = staPlus.Party(description='I am Long John Silver the opportunistic pirate created by Robert Louis Stevenson',\n display_name='LJS',\n role='individual')\nservice.create(ljs)\n```\n\n#### Creating a STAplus enriched Datastream\nThe STAplus `Datastream` is capable to have a `Party` and a `License` associated. Also, the `Thing` is associated to a `Party` entity.\n```python\nimport staplus_client as staplus\n\nurl = \"<your domain>/staplus/v1.1\"\nauth_handler.AuthHandler(...)\nservice = staplus.STAplusService(url, auth_handler=auth)\nljs = staplus.Party(description='I am Long John Silver the opportunistic pirate created by Robert Louis Stevenson',\n display_name='LJS',\n role='individual')\nservice.create(ljs)\n\n# find the CC-BY license\ncc_by = service.licenses().find('CC_BY')\n\n# Create a thing associated to LJS\nthing = staplus.Thing('Raspberry Pi', 'Raspberry Pi 4', )\nthing.party = ljs\n\n# Create a sensor\nsensor = staplus.Sensor('air temperature sensor', 'SmartCitizen air temperature sensor', 'test/html', None,\n 'https://www.seeedstudio.com/Smart-Citizen-Starter-Kit-p-2865.html')\n\n# Create a datastream associated to LJS with CC-BY license\ndatastream = staplus.Datastream('air temperature', 'air temperature measured with the SmartCitizen Kit',\n 'http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement', \n staplus.UnitOfMeasurement('Celsius', 'C', 'https://qudt.org/vocab/unit/DEG_C'))\ndatastream.observed_property = staplus.ObservedProperty('temperature', 'http://vocabs.lter-europe.net/EnvThes/22035',\n 'air temperature')\ndatastream.party = ljs\ndatastream.thing = thing\ndatastream.sensor = sensor\ndatastream.license = cc_by\n\nservice.create(datastream)\n```\n\n#### Creating a few Observation entities\n```python\nimport staplus_client as staplus\n\nurl = \"<your domain>/staplus/v1.1\"\nauth_handler.AuthHandler(...)\nservice = staplus.STAplusService(url, auth_handler=auth)\nljs = staplus.Party(description='I am Long John Silver the opportunistic pirate created by Robert Louis Stevenson',\n display_name='LJS',\n role='individual')\nservice.create(ljs)\n\n# The feature of interest\nmarienplatz = {\n \"type\": \"Feature\",\n \"geometry\": {\n \"type\": \"Point\",\n \"coordinates\": [11.571831046,48.135666124]\n }\n}\nfoi = staplus.FeatureOfInterest('Marienplatz', 'famous place in Munich', 'application/vnd.geo+json', marienplatz)\n\n# The temperature\nobservation = staplus.Observation(\"2023-07-02T15:34:00Z\", 20, \"2023-07-02T15:34:00Z\")\nobservation.feature_of_interest = foi\nobservation.datastream = service.datastreams().find(<the datastream id created previously>)\n\nservice.create(observation)\n\nobservation = staplus.Observation(\"2023-07-02T15:34:10Z\", 21, \"2023-07-02T15:34:10Z\")\nobservation.feature_of_interest = foi\nobservation.datastream = service.datastreams().find(<the datastream id created previously>)\n\nservice.create(observation)\n```\n\n#### Creating an ObservationGroup Entity\nA `ObservationGroup` entity can be used as a container of observations that belong together.\n\n```python\nimport staplus_client as staplus\n\nurl = \"<your domain>/staplus/v1.1\"\nservice = staPlus.STAplusService(url, auth_handler=auth)\nljs = staPlus.Party(description='I am Long John Silver the opportunistic pirate created by Robert Louis Stevenson',\n display_name='LJS',\n role='individual')\nservice.create(ljs)\ngroup = staPlus.ObservationGroup(\"Marienplatz\", \"observations on Marienplatz\", \"none\", \"\")\ngroup.creation_time = parse_datetime(\"2023-07-02T15:35:00Z\")\n# Add all the observations that are associated to the FoI named 'Marienplatz'\ngroup.observations = service.observations().query().filter(\"FeatureOfInterest/name eq 'Marienplatz'\").list()\ngroup.license = service.licenses().find('CC_BY')\ngroup.party = ljs\n\nservice.create(group)\n```\n\n#### Creating SensorThings Entities\nHow to use this implementation on SensorThings Entity Types, please see the [FROST-Python-Client](https://github.com/securedimensions/STAplus-Python-Client) documentation.\n\n### Fetching Entities via the STAplus Client\nThis implementation supports the fetching of `EntityList` and `Entity`.\n\n#### Fetching an EntityList\nAn `EntityList` is the result from fetching entities that have a multiplicity `0..*` or `1..*`. To fetch the list of entities, you need to use the `.list()` function. The following example fetches all datastreams:\n\n```python\nimport staplus_client as staplus\n\nurl = \"<your domain>/staplus/v1.1\"\nservice = staplus.STAplusService(url)\ndatastreams = service.datastreams().query().list()\n```\n\nIn order to get all entities of a given entity, you can use the function `get_<entity_plural>()`. For example, to fetch all datastreams of a given `Thing` please use the following code: \n\n```python\nimport staplus_client as staplus\n\nurl = \"<your domain>/staplus/v1.1\"\nservice = staplus.STAplusService(url)\nthing = service.things().find(1)\nthing_datastreams = thing.get_datastreams().query().list()\n```\n\n#### Fetching an Entity\nAn `Entity` is the result from fetching an entity that has multiplicity `0..1` or `1`. To fetch one single entity you need to use the `.item()` function. The following example fetches the thing associated to a datastream:\n\n```python\nimport staplus_client as staplus\n\nurl = \"<your domain>/staplus/v1.1\"\nservice = staplus.STAplusService(url)\ndatastream = service.datastreams().find(1).item()\ndatastream_thing = datastream.get_thing().query().item()\n```\n\n### Cloning an Entity\nWhen creating an Entity, mandatory entities can be provided either inline or by reference. To support the referencing of existing entities, the `clone()` function can be used. `clone()` returns a copy of the entity but only containing the `@iot.id`. This is important when preparing MQTT messages to publish observations.\n\n#### Example ObservationGroup with inline entities\n```JSON\n{\n \"Observations\": [\n {\n \"Datastream\": {\n \"@iot.id\": 1,\n \"description\": \"desc\",\n \"name\": \"new name\",\n \"observationType\": \"OM_Observation\",\n \"observedArea\": {\n \"coordinates\": [11.509234, 48.110728],\n \"type\": \"Point\"\n },\n \"phenomenonTime\": \"2023-07-24T06:30:18+00:00/2023-09-14T05:40:25.292000+00:00\",\n \"resultTime\": \"2023-07-24T06:30:18+00:00/2023-07-24T06:31:42+00:00\",\n \"unitOfMeasurement\": { \"definition\": \"...\", \"name\": \"n\", \"symbol\": \"n\" }\n },\n \"FeatureOfInterest\": {\n \"@iot.id\": 77,\n \"description\": \"A rainy place\",\n \"encodingType\": \"application/geo+json\",\n \"feature\": { \"coordinates\": [-6.22299, 53.306816], \"type\": \"Point\" },\n \"name\": \"Dublin\",\n \"properties\": {\n \"datastreams\": [1, 2, 76, 2, 78, 77],\n \"multi_datastreams\": [11]\n }\n },\n \"phenomenonTime\": \"2024-04-13T19:57:08+00:00\",\n \"result\": 19.111,\n \"resultTime\": \"2024-05-02T19:36:06+00:00\"\n },\n {\n \"Datastream\": {\n \"@iot.id\": 2,\n \"description\": \"air relative humidity measured with the SmartCitizen Kit\",\n \"name\": \"Relative Humidity\",\n \"observationType\": \"http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement\",\n \"observedArea\": {\n \"coordinates\": [11.509234, 48.110728],\n \"type\": \"Point\"\n },\n \"phenomenonTime\": \"2023-07-24T06:30:18+00:00/2023-07-24T06:31:42+00:00\",\n \"resultTime\": \"2023-07-24T06:30:18+00:00/2023-07-24T06:31:42+00:00\",\n \"unitOfMeasurement\": {\n \"definition\": \"https://qudt.org/vocab/unit/PERCENT\",\n \"name\": \"Percentage\",\n \"symbol\": \"%\"\n }\n },\n \"FeatureOfInterest\": {\n \"@iot.id\": 77,\n \"description\": \"A rainy place\",\n \"encodingType\": \"application/geo+json\",\n \"feature\": { \"coordinates\": [-6.22299, 53.306816], \"type\": \"Point\" },\n \"name\": \"Dublin\",\n \"properties\": {\n \"datastreams\": [1, 2, 76, 2, 78, 77],\n \"multi_datastreams\": [11]\n }\n },\n \"phenomenonTime\": \"2024-04-13T19:57:08+00:00\",\n \"result\": 43.0,\n \"resultTime\": \"2024-05-02T19:36:06+00:00\"\n },\n {\n \"Datastream\": {\n \"@iot.id\": 76,\n \"description\": \"Precipitation measured with the FT-0310 Weather Station\",\n \"name\": \"Rain\",\n \"observationType\": \"http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement\",\n \"unitOfMeasurement\": {\n \"definition\": \"https://qudt.org/vocab/unit/MilliM\",\n \"name\": \"millimiter\",\n \"symbol\": \"mm\"\n }\n },\n \"FeatureOfInterest\": {\n \"@iot.id\": 77,\n \"description\": \"A rainy place\",\n \"encodingType\": \"application/geo+json\",\n \"feature\": { \"coordinates\": [-6.22299, 53.306816], \"type\": \"Point\" },\n \"name\": \"Dublin\",\n \"properties\": {\n \"datastreams\": [1, 2, 76, 2, 78, 77],\n \"multi_datastreams\": [11]\n }\n },\n \"phenomenonTime\": \"2024-04-13T19:57:08+00:00\",\n \"result\": 87.0,\n \"resultTime\": \"2024-05-02T19:36:06+00:00\"\n },\n {\n \"Datastream\": {\n \"@iot.id\": 77,\n \"description\": \"Wind direction measured with the FT-0310 Weather Station\",\n \"name\": \"Wind direction\",\n \"observationType\": \"http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement\",\n \"unitOfMeasurement\": {\n \"definition\": \"https://qudt.org/vocab/unit/DEG\",\n \"name\": \"degree\",\n \"symbol\": \"deg\"\n }\n },\n \"FeatureOfInterest\": {\n \"@iot.id\": 77,\n \"description\": \"A rainy place\",\n \"encodingType\": \"application/geo+json\",\n \"feature\": { \"coordinates\": [-6.22299, 53.306816], \"type\": \"Point\" },\n \"name\": \"Dublin\",\n \"properties\": {\n \"datastreams\": [1, 2, 76, 2, 78, 77],\n \"multi_datastreams\": [11]\n }\n },\n \"phenomenonTime\": \"2024-04-13T19:57:08+00:00\",\n \"result\": 241.0,\n \"resultTime\": \"2024-05-02T19:36:06+00:00\"\n },\n {\n \"FeatureOfInterest\": {\n \"@iot.id\": 77,\n \"description\": \"A rainy place\",\n \"encodingType\": \"application/geo+json\",\n \"feature\": { \"coordinates\": [-6.22299, 53.306816], \"type\": \"Point\" },\n \"name\": \"Dublin\",\n \"properties\": {\n \"datastreams\": [1, 2, 76, 2, 78, 77],\n \"multi_datastreams\": [11]\n }\n },\n \"MultiDatastream\": {\n \"@iot.id\": 11,\n \"ObservedProperties\": [\n {\n \"@iot.id\": 105,\n \"definition\": \"http://vocab.nerc.ac.uk/standard_name/wind_speed/\",\n \"description\": \"Wind speed\",\n \"name\": \"wspeed\"\n },\n {\n \"@iot.id\": 106,\n \"definition\": \"http://vocab.nerc.ac.uk/standard_name/wind_gust_from_direction/\",\n \"description\": \"Wind gust\",\n \"name\": \"wgust\"\n }\n ],\n \"description\": \"Wind speed average and gust measured with the FT-0310 Weather Station\",\n \"multiObservationDataTypes\": [\n \"http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement\",\n \"http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement\"\n ],\n \"name\": \"Wind speed avg and gust\",\n \"observationType\": \"http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_ComplexObservation\",\n \"unitOfMeasurements\": [\n {\n \"definition\": \"https://qudt.org/vocab/unit/M-PER-SEC\",\n \"name\": \"Meters per second\",\n \"symbol\": \"m/s\"\n },\n {\n \"definition\": \"https://qudt.org/vocab/unit/M-PER-SEC\",\n \"name\": \"Meters per second\",\n \"symbol\": \"m/s\"\n }\n ]\n },\n \"phenomenonTime\": \"2024-04-13T19:57:08+00:00\",\n \"result\": [0.0, 0.0],\n \"resultTime\": \"2024-05-02T19:36:06+00:00\"\n }\n ],\n \"Party\": {\n \"@iot.id\": \"36fd7ca4-08bb-11ef-b156-a337e8ef4d15\",\n \"displayName\": \"LJS\",\n \"role\": \"individual\"\n },\n \"creationTime\": \"2024-05-02T19:36:06+00:00\",\n \"description\": \" \",\n \"endTime\": \"2024-05-02T19:36:06+00:00\",\n \"name\": \"OG 2024-05-02T19:36:06+00:00\"\n}\n```\n\nThis example with inline `Datastream` and `FeatureOfInterest` entities has the size of 6245 Bytes.\n\n#### Example ObservationGroup with referencing entities\n```JSON\n{\n \"Observations\": [\n {\n \"Datastream\": { \"@iot.id\": 1 },\n \"FeatureOfInterest\": { \"@iot.id\": 77 },\n \"phenomenonTime\": \"2024-04-13T19:57:08+00:00\",\n \"result\": 19.111,\n \"resultTime\": \"2024-05-03T09:48:33+00:00\"\n },\n {\n \"Datastream\": { \"@iot.id\": 2 },\n \"FeatureOfInterest\": { \"@iot.id\": 77 },\n \"phenomenonTime\": \"2024-04-13T19:57:08+00:00\",\n \"result\": 43.0,\n \"resultTime\": \"2024-05-03T09:48:33+00:00\"\n },\n {\n \"Datastream\": { \"@iot.id\": 76 },\n \"FeatureOfInterest\": { \"@iot.id\": 77 },\n \"phenomenonTime\": \"2024-04-13T19:57:08+00:00\",\n \"result\": 87.0,\n \"resultTime\": \"2024-05-03T09:48:33+00:00\"\n },\n {\n \"Datastream\": { \"@iot.id\": 77 },\n \"FeatureOfInterest\": { \"@iot.id\": 77 },\n \"phenomenonTime\": \"2024-04-13T19:57:08+00:00\",\n \"result\": 241.0,\n \"resultTime\": \"2024-05-03T09:48:33+00:00\"\n },\n {\n \"FeatureOfInterest\": { \"@iot.id\": 77 },\n \"MultiDatastream\": { \"@iot.id\": 11 },\n \"phenomenonTime\": \"2024-04-13T19:57:08+00:00\",\n \"result\": [0.0, 0.0],\n \"resultTime\": \"2024-05-03T09:48:33+00:00\"\n }\n ],\n \"Party\": {\n \"@iot.id\": \"4cd42a10-0932-11ef-919f-57f24e9b90e3\",\n \"displayName\": \"LJS\",\n \"role\": \"individual\"\n },\n \"creationTime\": \"2024-05-03T09:48:33+00:00\",\n \"description\": \" \",\n \"endTime\": \"2024-05-03T09:48:33+00:00\",\n \"name\": \"OG 2024-05-03T09:48:33+00:00\"\n}\n```\n\nThis example with referenced `Datastream` and `FeatureOfInterest` entities has the size of 1420 Bytes.\n",
"bugtrack_url": null,
"license": "LGPL3",
"summary": "A client library to facilitate interaction with a STAplus Server",
"version": "0.3.3",
"project_urls": {
"Homepage": "https://github.com/securedimensions/STAplus-Python-Client"
},
"split_keywords": [
"ogc",
" staplus",
" sensorthingsapi",
" iot"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "eddcaa556107e63147914f8c95ed575501fdad24cd8b9eac7e946e5b55c5dc1d",
"md5": "b59f8319f71c147f79753818d353f9dc",
"sha256": "e8dbba738103f237a948cde564adcfaed74f1a03a93941b103d7f0782b67bb42"
},
"downloads": -1,
"filename": "staplus_client-0.3.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "b59f8319f71c147f79753818d353f9dc",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 59993,
"upload_time": "2024-05-24T09:26:05",
"upload_time_iso_8601": "2024-05-24T09:26:05.534920Z",
"url": "https://files.pythonhosted.org/packages/ed/dc/aa556107e63147914f8c95ed575501fdad24cd8b9eac7e946e5b55c5dc1d/staplus_client-0.3.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "89c1dfd362fea4ad82106f830b4cd7d7d026a6045280e6c29f819af518c9a945",
"md5": "b93ed837a242dc1af237a501748be72f",
"sha256": "acc261751d6fff6fc0f7fac6ea083ffd89a36e147c23a9929f3bd1b3fb245d84"
},
"downloads": -1,
"filename": "staplus_client-0.3.3.tar.gz",
"has_sig": false,
"md5_digest": "b93ed837a242dc1af237a501748be72f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 32096,
"upload_time": "2024-05-24T09:26:06",
"upload_time_iso_8601": "2024-05-24T09:26:06.619085Z",
"url": "https://files.pythonhosted.org/packages/89/c1/dfd362fea4ad82106f830b4cd7d7d026a6045280e6c29f819af518c9a945/staplus_client-0.3.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-05-24 09:26:06",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "securedimensions",
"github_project": "STAplus-Python-Client",
"github_not_found": true,
"lcname": "staplus-client"
}