From 63c1909d5a288b436a74f1361ed1ba11a4569b1c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 15:59:42 +0200 Subject: [PATCH 1/7] chore(python-docs): update python doc assets to recent development state (#117) --- .../dev/scripts/gen_ref_pages/index.html | 12 +-- docs-python/dev/sitemap.xml | 96 +++++++++--------- docs-python/dev/sitemap.xml.gz | Bin 704 -> 704 bytes 3 files changed, 54 insertions(+), 54 deletions(-) diff --git a/docs-python/dev/scripts/gen_ref_pages/index.html b/docs-python/dev/scripts/gen_ref_pages/index.html index 5cac5c70f..02184c9d6 100644 --- a/docs-python/dev/scripts/gen_ref_pages/index.html +++ b/docs-python/dev/scripts/gen_ref_pages/index.html @@ -3168,7 +3168,7 @@
Dependency issue with StreamPipes Python 0.92.0
In StreamPipes Python 0.92.0
there is a problem with the required dependencies. Pydantic has recently released the new version 2.0
with many exciting improvements, but also some breaking changes. Unfortunately, we didn't limit our requirements strictly enough, so yydantic 2.0
is installed together with streampipes, which is not (yet) compatible. To fix this bug, simply run the following command after installing streampipes, or adjust your dependencies accordingly:
pip install \"pydantic<2.0\" \"pydantic_core<2.0\"\n
Apache StreamPipes for Python \ud83d\udc0d Apache StreamPipes meets Python! We are working highly motivated on a Python library to interact with StreamPipes. In this way, we would like to unite the power of StreamPipes to easily connect to and read from different data sources, especially in the IoT domain, and the amazing universe of data analytics libraries in Python.
StreamPipes Python is in beta
The current version of this Python library is still a beta version. This means that it is still heavily under development, which may result in frequent and extensive API changes, unstable behavior, etc.
"},{"location":"#quickstart","title":"\u26a1\ufe0f Quickstart","text":"As a quick example, we demonstrate how to set up and configure a StreamPipes client. In addition, we will get the available data lake measures out of StreamPipes.
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nconfig = StreamPipesClientConfig(\n credential_provider = StreamPipesApiKeyCredentials(\n username = \"test@streampipes.apache.org\",\n api_key = \"DEMO-KEY\",\n ),\n host_address = \"localhost\",\n https_disabled = True,\n port = 80\n)\n\nclient = StreamPipesClient(client_config=config)\n\n# get all available datat lake measures\nmeasures = client.dataLakeMeasureApi.all()\n\n# get amount of retrieved measures\nlen(measures)\n
Output: 1\n
# inspect the data lake measures as pandas dataframe\nmeasures.to_pandas()\n
Output:
measure_name timestamp_field ... pipeline_is_running num_event_properties\n0 test s0::timestamp ... False 2\n[1 rows x 6 columns]\n
Alternatively, you can provide your credentials via environment variables. Simply define your credential provider as follows: from streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nStreamPipesApiKeyCredentials()\n
This requires to set the following environment variables: SP_API_KEY
and SP_USERNAME
username
is always the username that is used to log in into StreamPipes.
The api_key
can be generated within the UI as demonstrated below:
This document describes how to easily set up your local dev environment to work on StreamPipes Python \ud83d\udc0d.
"},{"location":"getting-started/developing/#first-steps","title":"\ud83d\ude80 First Steps","text":"1) Set up your Python environment
Create a virtual Python environment using a tool of your choice. To manage dependencies, we use Poetry, so please install poetry in your local environment, e.g. via
pip install poetry\n
Once poetry is installed you can simply finalize your Python environment by running:
poetry install --with dev,stubs # install everything that is required for the development\npoetry install --with docs # install everything to work with the documentation\npoetry install --with dev,stubs,docs # install all optional dependencies related to development\n
2) Install pre-commit hook
The pre-commit hook is run before every commit and takes care about code style, linting, type hints, import sorting, etc. It will stop your commit in case the changes do not apply the expected format. Always check to have the recent version of the pre-commit hook installed otherwise the CI build might fail. If you are interested, you can have a deeper look on the underlying library: pre-commit.
pre-commit install\n
The definition of the pre-commit hook can be found in .pre-commit-config.yaml. "},{"location":"getting-started/developing/#conventions","title":"\ud83d\udc4f Conventions","text":"Below we list some conventions that we have agreed on for creating StreamPipes Python. Please comply to them when you plan to contribute to this project. If you have any other suggestions or would like to discuss them, we would be happy to hear from you on our mailing list dev@streampipes.apache.org or in our discussions on GitHub.
1) Use numpy
style for Python docstrings \ud83d\udcc4 Please stick to the numpy
style when writing docstrings, as we require this for generating our documentation.
2) Provide tests \u2705 We are aiming for broad test coverage for the Python package and have therefore set a requirement of at least 90% unit test coverage. Therefore, please remember to write (unit) tests already during development. If you have problems with writing tests, don't hesitate to ask us for help directly in the PR or even before that via our mailing list (see above).
3) Build a similar API as the Java client provides \ud83d\udd04 Whenever possible, please try to develop the API of the Python library the same as the Java client or Java SDK. By doing so, we would like to provide a consistent developer experience and the basis for automated testing in the future.
"},{"location":"getting-started/developing/#dependency-management","title":"\ud83d\udce6 Dependency Management","text":"In case you want to add a new dependency to StreamPipes you can use the following command:
poetry add <dep-name>\n
If the dependency is only required for development purpose or the documentation, please stick to one the following:
poetry add <dep-name> --group dev\npoetry add <dep-name> --group stubs\npoetry add <dep-name> --group docs\n
In case you want to regenerate the poetry lock file, e.g., in case you manually updated the pyproject.toml
, the following command should be used:
poetry lock --no-update\n
After that, you should install the current version of the poetry lock file to keep your local environment consistent (see command above.)
"},{"location":"getting-started/developing/#documentation","title":"\ud83d\udcdaDocumentation","text":"To build our documentation, we use Materials for MkDocs. All files can be found within the docs
directory. To pre-view your local version of the documentation, you can use the following command:
make livedoc\n
"},{"location":"getting-started/developing/#roadmap","title":"\ud83d\ude80 Roadmap","text":"Broadly speaking, we plan to expand or add new aspects/functionality to the library where we are focusing on the following:
In case you want to have a more detailed look on what we are currently planning, have a look at our open issues(more short-term driven).
Of course, contributions are always highly appreciated \ud83d\udd2e
Stay tuned!
"},{"location":"getting-started/developing/#contributing","title":"\ud83d\udc68\u200d\ud83d\udcbb Contributing","text":"Before opening a pull request, review the Get Involved page. It lists information that is required for contributing to StreamPipes.
When you contribute code, you affirm that the contribution is your original work and that you license the work to the project under the project's open source license. Whether or not you state this explicitly, by submitting any copyrighted material via pull request, email, or other means you agree to license the material under the project's open source license and warrant that you have the legal authority to do so.
"},{"location":"getting-started/first-steps/","title":"First Steps","text":""},{"location":"getting-started/first-steps/#installation","title":"\ud83d\udcda Installation","text":"The StreamPipes Python library is meant to work with Python 3.8 and above. Installation can be done via pip
: You can install the latest development version from GitHub, as so:
pip install streampipes\n\n# if you want to have the current development state you can also execute\npip install git+https://github.com/apache/streampipes.git#subdirectory=streampipes-client-python\n# the corresponding documentation can be found here: https://streampipes.apache.org/docs/docs/python/dev/\n
"},{"location":"getting-started/first-steps/#setting-up-streampipes","title":"\u2b06\ufe0f Setting up StreamPipes","text":"When working with the StreamPipes Python library it is inevitable to have a running StreamPipes instance to connect and interact with. In case you don't have a running instance at hand, you can easily set up one on your local machine. Hereby you need to consider that StreamPipes supports different message broker (e.g., Kafka, NATS). We will demonstrate below how you can easily set up StreamPipes for both supported message brokers.
"},{"location":"getting-started/first-steps/#start-streampipes-via-docker-compose","title":"\ud83d\udc33 Start StreamPipes via Docker Compose","text":"The easiest and therefore recommend way to get StreamPipes started is by using docker compose. Therefore, you need Docker running. You can check if Docker is ready on your machine by executing.
docker ps\n
If this results in an output similar to the following, Docker is ready to continue. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES\n... ... ... ... ... ... ...\n
Otherwise, you need to start docker first. Please read the full guide on how to start StreamPipes with docker compose
here."},{"location":"getting-started/first-steps/#setup-streampipes-with-nats-as-message-broker","title":"Setup StreamPipes with NATS as message broker","text":"The following shows how you can set up a StreamPipes instance that uses NATS as messaging layer. So in this scenario, we will go with docker-compose.nats.yml
. Thereby, when running locally, we need to add the following port mapping entry to services.nats.ports
:
- 4222:4222\n
After this modification is applied, StreamPipes can simply be started with this command:
docker-compose -f docker-compose.nats.yml up -d\n
Once all services are started, you can access StreamPipes via http://localhost
.
Alternatively, you can use docker-compose.yml
to start StreamPipes with Kafka as messaging layer. When running locally we have to modify services.kafka.environment
and add the ports to services.kafka.ports
:
environment:\nKAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,OUTSIDE:PLAINTEXT\nKAFKA_ADVERTISED_LISTENERS: PLAINTEXT://:9092,OUTSIDE://localhost:9094\nKAFKA_LISTENERS: PLAINTEXT://:9092,OUTSIDE://:9094\n...\nports:\n- 9094:9094\n
Then, you need to execute the following command: docker-compose -f docker-compose.yml up -d\n
Once all services are started, you can access StreamPipes via http://localhost
.
In case you want to have more control over your StreamPipes setup, you might take a look at our deployment CLI.
Have fun discovering StreamPipes and our Python library \ud83d\ude80
"},{"location":"getting-started/quickstart/","title":"Quickstart","text":""},{"location":"getting-started/quickstart/#quickstart","title":"\u26a1\ufe0f Quickstart","text":"As a quick example, we demonstrate how to set up and configure a StreamPipes client. In addition, we will get the available data lake measures out of StreamPipes.
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nconfig = StreamPipesClientConfig(\n credential_provider = StreamPipesApiKeyCredentials(\n username = \"test@streampipes.apache.org\",\n api_key = \"DEMO-KEY\",\n ),\n host_address = \"localhost\",\n https_disabled = True,\n port = 80\n)\n\nclient = StreamPipesClient(client_config=config)\n\n# get all available datat lake measures\nmeasures = client.dataLakeMeasureApi.all()\n\n# get amount of retrieved measures\nlen(measures)\n
Output: 1\n
# inspect the data lake measures as pandas dataframe\nmeasures.to_pandas()\n
Output:
measure_name timestamp_field ... pipeline_is_running num_event_properties\n0 test s0::timestamp ... False 2\n[1 rows x 6 columns]\n
Alternatively, you can provide your credentials via environment variables. Simply define your credential provider as follows: from streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nStreamPipesApiKeyCredentials()\n
This requires to set the following environment variables: SP_API_KEY
and SP_USERNAME
username
is always the username that is used to log in into StreamPipes. The api_key
can be generated within the UI as demonstrated below:
Implementation of the StreamPipes client. The client is designed as the central point of interaction with the StreamPipes API and provides all functionalities to communicate with the API.
"},{"location":"reference/client/client/#streampipes.client.client.StreamPipesClient","title":"StreamPipesClient(client_config, logging_level=logging.INFO)
","text":"The client to connect to StreamPipes.
This is the central point of contact with StreamPipes and provides all the functionalities to interact with it.
The client provides so-called \"endpoints\" each of which refers to an endpoint of the StreamPipes API, e.g. .dataLakeMeasureApi
. An endpoint provides the actual methods to interact with StreamPipes API.
client_config
Configures the client to connect properly to the StreamPipes instance.
TYPE: StreamPipesClientConfig
logging_level
Influences the log messages emitted by the StreamPipesClient
TYPE: Optional[int]
DEFAULT: logging.INFO
dataLakeMeasureApi
Instance of the data lake measure endpoint
TYPE: DataLakeMeasureEndpoint
dataStreamApi
Instance of the data stream endpoint
TYPE: DataStreamEndpoint
Examples:
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
client_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(\n username=\"test-user\",\n api_key=\"api-key\"\n ),\n host_address=\"localhost\",\n https_disabled=True\n)\n
The following way of instantiating a client instance is intended to be consistent with the StreamPipes Java client.
client = StreamPipesClient.create(client_config=client_config)\n
If you prefer a more pythonic way, you can simply write:
client = StreamPipesClient(client_config=client_config)\n
To interact with an endpoint:
data_lake_measures = client.dataLakeMeasureApi.all()\n
To inspect returned data as a pandas dataframe:
data_lake_measures.to_pandas()\n#\n# measure_name timestamp_field ... pipeline_is_running num_event_properties\n# 0 test s0::timestamp ... False 2\n# [1 rows x 6 columns]\n
"},{"location":"reference/client/client/#streampipes.client.client.StreamPipesClient.base_api_path","title":"base_api_path: str
property
","text":"Constructs the basic API URL from the given client_config
.
base_api_path
basic API path of the connected StreamPipes instance
TYPE: str
http_headers: Dict[str, str]
property
","text":"Returns the HTTP headers used for all requests.
The HTTP headers are composed of the authentication headers supplied by the credential provider and additional required headers (currently this is only the application header).
RETURNS DESCRIPTIONhttp_headers
header information for HTTP requests as string key-value pairs.
TYPE: Dict[str, str]
create(client_config, logging_level=logging.INFO)
classmethod
","text":"Returns an instance of the StreamPipesPythonClient
.
Provides consistency to the StreamPipes Java client.
PARAMETER DESCRIPTIONclient_config
Configures the client to connect properly to the StreamPipes instance.
TYPE: StreamPipesClientConfig
logging_level
Influences the log messages emitted by the StreamPipesClient
.
TYPE: int
DEFAULT: logging.INFO
StreamPipesClient
"},{"location":"reference/client/client/#streampipes.client.client.StreamPipesClient.describe","title":"describe()
","text":"Prints a short description of the connected StreamPipes instance and the available resources to the console.
RETURNS DESCRIPTION None
Examples:
client.describe()\n
Output: Hi there!\nYou are connected to a StreamPipes instance running at http://localhost:80.\nThe following StreamPipes resources are available with this client:\n6x DataStreams\n1x DataLakeMeasures\n
"},{"location":"reference/client/config/","title":"Config","text":"Configuration class for the StreamPipes client.
"},{"location":"reference/client/config/#streampipes.client.config.StreamPipesClientConfig","title":"StreamPipesClientConfig
dataclass
","text":"Configure the StreamPipes client in accordance to the actual StreamPipes instance to connect to.
An instance is provided to the StreamPipesClient
to configure it properly.
credential_provider
Provides the credentials to authenticate with the StreamPipes API.
TYPE: CredentialProvider
host_address
Host address of the StreamPipes instance to connect to. Should be provided without the protocol/scheme, e.g. as localhost
or streampipes.xyz
.
TYPE: str
https_disabled
Determines whether https is used to connect to StreamPipes.
TYPE: Optional[bool]
DEFAULT: False
port
Specifies the port under which the StreamPipes API is available, e.g., 80
(with http) or 443
(with https)
TYPE: Optional[int]
DEFAULT: 80
Examples:
see StreamPipesClient
"},{"location":"reference/client/credential_provider/","title":"Credential provider","text":"Implementation of credential providers. A credential provider supplies the specified sort of credentials in the appropriate HTTP header format. The headers are then used by the client to connect to StreamPipes.
"},{"location":"reference/client/credential_provider/#streampipes.client.credential_provider.CredentialProvider","title":"CredentialProvider
","text":" Bases: ABC
Abstract implementation of a credential provider. Must be inherited by all credential providers.
"},{"location":"reference/client/credential_provider/#streampipes.client.credential_provider.CredentialProvider.make_headers","title":"make_headers(http_headers=None)
","text":"Creates the HTTP headers for the specific credential provider.
Concrete authentication headers must be defined in the implementation of a credential provider.
PARAMETER DESCRIPTIONhttp_headers
Additional HTTP headers the generated headers are extended by.
TYPE: Optional[Dict[str, str]]
DEFAULT: None
https_headers
Dictionary with header information as string key-value pairs. Contains all pairs given as parameter plus the header pairs for authentication determined by the credential provider.
TYPE: Dict[str, str]
StreamPipesApiKeyCredentials(username=None, api_key=None)
","text":" Bases: CredentialProvider
A credential provider that allows authentication via a StreamPipes API Token.
The required token can be generated via the StreamPipes UI (see the description on our start-page.
Both parameters can either be passed as arguments or remain unset. If they are not passed, they are retrieved from environment variables:
SP_USERNAME
is expected to contain the usernameSP_API_KEY
is expected to contain the API keyusername
The username to which the API token is granted, e.g., demo-user@streampipes.apche.org
. If not passed, the username is retrieved from environment variable SP_USERNAME
.
TYPE: Optional[str]
DEFAULT: None
api_key
The StreamPipes API key as it is displayed in the UI. If not passed, the api key is retrieved from environment variable SP_API_KEY
TYPE: Optional[str]
DEFAULT: None
Examples:
see StreamPipesClient
"},{"location":"reference/client/credential_provider/#streampipes.client.credential_provider.StreamPipesApiKeyCredentials.from_env","title":"from_env(username_env, api_key_env)
classmethod
","text":"DEPRECATED - use the class constructor instead
Returns an api key provider parameterized via environment variables.
PARAMETER DESCRIPTIONusername_env
Name of the environment variable that contains the username
TYPE: str
api_key_env
Name of the environment variable that contains the API key
TYPE: str
StreamPipesApiKeyCredentials
RAISES DESCRIPTION KeyError
If one of the environment variables is not defined
"},{"location":"reference/endpoint/endpoint/","title":"Endpoint","text":"General implementation for an endpoint. Provided classes and assets are aimed to be used for developing endpoints. An endpoint provides all options to communicate with ad dedicated part of StreamPipes in a handy way.
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.APIEndpoint","title":"APIEndpoint
","text":" Bases: Endpoint
Abstract implementation of an API endpoint.
Serves as template for all endpoints of the StreamPipes API. By design, endpoints are only instantiated within the __init__
method of the StreamPipesClient.
all()
","text":"Get all resources of this endpoint provided by the StreamPipes API.
Results are provided as an instance of a ResourceContainer
that allows to handle the returned resources in a comfortable and pythonic way.
container
container element that bundles the returned resources
TYPE: ResourceContainer
build_url()
","text":"Builds the endpoint's URL of the API path.
RETURNS DESCRIPTIONurl
The URL of the endpoint
TYPE: str
get(identifier, **kwargs)
","text":"Queries the specified resource from the API endpoint.
PARAMETER DESCRIPTIONidentifier
The identifier of the resource to be queried.
TYPE: str
resource
The specified resource as an instance of the corresponding model class.
TYPE: Resource
post(resource)
","text":"Allows to post a resource to the StreamPipes API.
PARAMETER DESCRIPTIONresource
The resource to be posted.
TYPE: Resource
None
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.Endpoint","title":"Endpoint(parent_client)
","text":" Bases: ABC
Abstract implementation of a StreamPipes endpoint.
Serves as template for all endpoints used for interaction with a StreamPipes instance. By design, endpoints are only instantiated within the __init__
method of the StreamPipesClient.
parent_client
This parameter expects the instance of StreamPipesClient
the endpoint is attached to.
TYPE: StreamPipesClient
MessagingEndpoint(parent_client)
","text":" Bases: Endpoint
Abstract implementation of a StreamPipes messaging endpoint.
Serves as template for all endpoints used for interacting with the StreamPipes messaging layer directly. Therefore, they need to provide the functionality to talk with the broker system running in StreamPipes. By design, endpoints are only instantiated within the __init__
method of the StreamPipesClient.
broker: Broker
property
writable
","text":"Defines the broker instance that is used to connect to StreamPipes' messaging layer.
This instance enables the client to authenticate to the broker used in the target StreamPipes instance, to consume messages from and to write messages to the broker.
RAISES DESCRIPTIONMessagingEndpointNotConfiguredError
If the endpoint is used before the broker instance is set via configure()
broker
The broker instance to be used to communicate with StreamPipes' messaging layer.
TYPE: Broker
configure(broker)
","text":"Configures the message endpoint by setting the broker instance to be used.
This configuration step is required before the endpoint can be actually used. The based broker
instance is passed to an internal property
broker
Broker instance that should be used for this endpoint
TYPE: Broker
None
"},{"location":"reference/endpoint/exceptions/","title":"Exceptions","text":"Custom exceptions dedicated for the endpoints module
"},{"location":"reference/endpoint/exceptions/#streampipes.endpoint.exceptions.MessagingEndpointNotConfiguredError","title":"MessagingEndpointNotConfiguredError(endpoint_name)
","text":" Bases: Exception
Exception that indicates that an instance of a messaging endpoint has not been configured.
This error occurs when an instance of a messaging endpoint is used before the broker instance to be used is configured by passing it to the configure()
method.
endpoint_name
The name of the endpoint that caused the error
TYPE: str
Specific implementation of the StreamPipes API's data lake measure endpoints. This endpoint allows to consume data stored in StreamPipes' data lake.
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.DataLakeMeasureEndpoint","title":"DataLakeMeasureEndpoint
","text":" Bases: APIEndpoint
Implementation of the DataLakeMeasure endpoint.
This endpoint provides an interface to all data stored in the StreamPipes data lake.
Consequently, it allows querying metadata about available data sets (see all()
method). The metadata is returned as an instance of DataLakeMeasures
.
In addition, the endpoint provides direct access to the data stored in the data laka by querying a specific data lake measure using the get()
method.
Examples:
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
client_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(username=\"test-user\", api_key=\"api-key\"),\n host_address=\"localhost\",\n port=8082,\n https_disabled=True\n)\nclient = StreamPipesClient.create(client_config=client_config)\n
# get all existing data lake measures from StreamPipes\ndata_lake_measures = client.dataLakeMeasureApi.all()\n\n# let's take a look how many we got\nlen(data_lake_measures)\n
5\n
# Retrieve a specific data lake measure as a pandas DataFrame\nflow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\").to_pandas()\nflow_rate_pd\n
time density mass_flow sensorId sensor_fault_flags temperature volume_flow\n0 2023-02-24T16:19:41.472Z 50.872730 3.309556 flowrate02 False 44.448483 5.793138\n1 2023-02-24T16:19:41.482Z 47.186588 5.608580 flowrate02 False 40.322033 0.058015\n2 2023-02-24T16:19:41.493Z 46.735321 7.692881 flowrate02 False 49.239639 10.283526\n3 2023-02-24T16:19:41.503Z 40.169796 3.632898 flowrate02 False 49.933754 6.893441\n4 2023-02-24T16:19:41.513Z 49.635124 0.711260 flowrate02 False 50.106617 2.999871\n.. ... ... ... ... ... ... ...\n995 2023-02-24T16:19:52.927Z 50.057495 1.740114 flowrate02 False 46.558231 1.818237\n996 2023-02-24T16:19:52.94Z 41.038895 7.211723 flowrate02 False 48.048622 2.127493\n997 2023-02-24T16:19:52.952Z 45.837013 7.770180 flowrate02 False 48.188026 7.892062\n998 2023-02-24T16:19:52.965Z 43.389065 4.458602 flowrate02 False 48.280899 5.733892\n999 2023-02-24T16:19:52.977Z 44.056030 2.592060 flowrate02 False 47.505951 4.260697\n
As you can see, the returned amount of rows per default is 1000
. We can modify this behavior by passing the limit
paramter.
flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", limit=10).to_pandas()\nlen(flow_rate_pd)\n
10\n
If we are only interested in the values for density
, columns
allows us to select the columns to be returned:
flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", columns='density', limit=3).to_pandas()\nflow_rate_pd\n
time density\n0 2023-02-24T16:19:41.472Z 50.872730\n1 2023-02-24T16:19:41.482Z 47.186588\n2 2023-02-24T16:19:41.493Z 46.735321\n
This is only a subset of the available query parameters, find them at MeasurementGetQueryConfig.
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.DataLakeMeasureEndpoint.get","title":"get(identifier, **kwargs)
","text":"Queries the specified data lake measure from the API.
By default, the maximum number of returned records is 1000. This behaviour can be influenced by passing the parameter limit
with a different value (see MeasurementGetQueryConfig).
identifier
The identifier of the data lake measure to be queried.
TYPE: str
**kwargs
keyword arguments can be used to provide additional query parameters. The available query parameters are defined by the MeasurementGetQueryConfig.
TYPE: Optional[Dict[str, Any]]
DEFAULT: {}
measurement
the specified data lake measure
TYPE: DataLakeMeasures
Examples:
see directly at DataLakeMeasureEndpoint.
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.MeasurementGetQueryConfig","title":"MeasurementGetQueryConfig
","text":" Bases: BaseModel
Config class describing the parameters of the get()
method for measurements.
This config class is used to validate the provided query parameters for the GET endpoint of measurements. Additionally, it takes care of the conversion to a proper HTTP query string. Thereby, parameter names are adapted to the naming of the StreamPipes API, for which Pydantic aliases are used.
ATTRIBUTE DESCRIPTIONcolumns
A comma separated list of column names (e.g., time,value
) If provided, the returned data only consists of the given columns. Please be aware that the column time
as an index is always included.
TYPE: Optional[List[str]]
end_date
Restricts queried data to be younger than the specified time.
TYPE: Optional[datetime]
limit
Amount of records returned at maximum (default: 1000
) This needs to be at least 1
TYPE: Optional[int]
offset
Offset to be applied to returned data This needs to be at least 0
TYPE: Optional[int]
order
Ordering of query results Allowed values: ASC
and DESC
(default: ASC
)
TYPE: Optional[str]
page_no
Page number used for paging operation This needs to be at least 1
TYPE: Optional[int]
start_date
Restricts queried data to be older than the specified time
TYPE: Optional[datetime]
Config
","text":"Pydantic Config class
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.MeasurementGetQueryConfig.build_query_string","title":"build_query_string()
","text":"Builds a HTTP query string for the config.
This method returns an HTTP query string for the invoking config. It follows the following structure ?param1=value1¶m2=value2...
. This query string is not an entire URL, instead it needs to appended to an API path.
query_param_string
HTTP query params string (?param1=value1¶m2=value2...
)
TYPE: str
StreamPipesQueryValidationError
","text":" Bases: Exception
A custom exception to be raised when the validation of query parameter causes an error.
"},{"location":"reference/endpoint/api/data_stream/","title":"Data stream","text":"Specific implementation of the StreamPipes API's data stream endpoints.
"},{"location":"reference/endpoint/api/data_stream/#streampipes.endpoint.api.data_stream.DataStreamEndpoint","title":"DataStreamEndpoint
","text":" Bases: APIEndpoint
Implementation of the DataStream endpoint.
Consequently, it allows querying metadata about available data streams (see all()
method). The metadata is returned as an instance of DataStreams
.
Examples:
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nclient_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(username=\"test-user\", api_key=\"api-key\"),\n host_address=\"localhost\",\n port=8082,\n https_disabled=True\n)\nclient = StreamPipesClient.create(client_config=client_config)\n
# let's get all existing data streams in StreamPipes\ndata_streams = client.dataStreamApi.all()\nlen(data_streams)\n
2\n
"},{"location":"reference/endpoint/api/version/","title":"Version","text":"Specific implementation of the StreamPipes API's version endpoint.
"},{"location":"reference/endpoint/api/version/#streampipes.endpoint.api.version.VersionEndpoint","title":"VersionEndpoint
","text":" Bases: APIEndpoint
Implementation of the Versions endpoint.
This endpoint provides metadata about the StreamPipes version of the connected instance. It only allows to apply the get()
method with an empty string as identifier.
parent_client
The instance of StreamPipesClient the endpoint is attached to.
Examples:
>>> from streampipes.client import StreamPipesClient\n>>> from streampipes.client.config import StreamPipesClientConfig\n>>> from streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
>>> client_config = StreamPipesClientConfig(\n... credential_provider=StreamPipesApiKeyCredentials(username=\"test-user\", api_key=\"api-key\"),\n... host_address=\"localhost\",\n... port=8082,\n... https_disabled=True\n... )\n
>>> client = StreamPipesClient.create(client_config=client_config)\n
>>> client.versionApi.get(identifier=\"\").to_dict(use_source_names=False)\n{'backend_version': '0.92.0-SNAPSHOT'}\n
"},{"location":"reference/endpoint/api/version/#streampipes.endpoint.api.version.VersionEndpoint.all","title":"all()
","text":"Usually, this method returns information about all resources provided by this endpoint. However, this endpoint does not support this kind of operation.
RAISES DESCRIPTIONNotImplementedError
this endpoint does not return multiple entries, therefore this method is not available
"},{"location":"reference/endpoint/api/version/#streampipes.endpoint.api.version.VersionEndpoint.get","title":"get(identifier, **kwargs)
","text":"Queries the resource from the API endpoint.
For this endpoint only one resource is available.
PARAMETER DESCRIPTIONidentifier
Not supported by this endpoint, is set to an empty string.
TYPE: str
versions
The specified resource as an instance of the corresponding model class(Version). # noqa: 501
TYPE: Version
post(resource)
","text":"Usually, this method allows to create via this endpoint. Since the data represented by this endpoint is immutable, it does not support this kind of operation.
RAISES DESCRIPTIONNotImplementedError
this endpoint does not allow for POST requests, therefore this method is not available
"},{"location":"reference/function_zoo/river_function/","title":"River function","text":""},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.OnlineML","title":"OnlineML(client, stream_ids, model, prediction_type=RuntimeType.STRING.value, supervised=False, target_label=None, on_start=lambda self, context: None, on_event=lambda self, event, streamId: None, on_stop=lambda self: None)
","text":"Wrapper class to enable an easy usage for Online Machine Learning models of the River library.
It creates a StreamPipesFunction to train a model with the incoming events of a data stream and creates an output data stream that publishes the prediction to StreamPipes.
PARAMETER DESCRIPTIONclient
The client for the StreamPipes API.
TYPE: StreamPipesClient
stream_ids
The ids of the data stream to train the model.
TYPE: List[str]
model
The model to train. It meant to be a River model/pipeline, but can be every model with a 'learn_one' and 'predict_one' methode.
TYPE: Any
prediction_type
The data type of the prediction. Is only needed when you continue to work with the prediction in StreamPipes.
TYPE: str
DEFAULT: RuntimeType.STRING.value
supervised
Define if the model is supervised or unsupervised.
TYPE: bool
DEFAULT: False
target_label
Define the name of the target attribute if the model is supervised.
TYPE: Optional[str]
DEFAULT: None
on_start
A function to be called when this StreamPipesFunction gets started.
TYPE: Callable[[Any, FunctionContext], None]
DEFAULT: lambda self, context: None
on_event
A function to be called when this StreamPipesFunction receives an event.
TYPE: Callable[[Any, Dict[str, Any], str], None]
DEFAULT: lambda self, event, streamId: None
on_stop
A function to be called when this StreamPipesFunction gets stopped.
TYPE: Callable[[Any], None]
DEFAULT: lambda self: None
set_learning(learning)
","text":"Start or stop the training of the model.
PARAMETER DESCRIPTIONlearning
Defines if the training should be continued
TYPE: bool
start()
","text":"Registers the function and starts the training.
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.OnlineML.stop","title":"stop()
","text":"Stops the function and ends the training forever.
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.RiverFunction","title":"RiverFunction(function_definition, model, supervised, target_label, on_start, on_event, on_stop)
","text":" Bases: StreamPipesFunction
Implementation of a StreamPipesFunction to enable an easy usage for Online Machine Learning models of the River library.
The function trains the model with the incoming events and publishes the prediction to an output data stream.
PARAMETER DESCRIPTIONfunction_definition
The function definition which contains the output stream.
TYPE: FunctionDefinition
model
The model to train. It meant to be a River model/pipeline, but can be every model with a 'learn_one' and 'predict_one' method.
TYPE: Any
supervised
Define if the model is supervised or unsupervised.
TYPE: bool
target_label
Define the name of the target attribute if the model is supervised.
TYPE: Optional[str]
on_start
A function to be called when this StreamPipesFunction gets started.
TYPE: Callable[[Any, FunctionContext], None]
on_event
A function to be called when this StreamPipesFunction receives an event.
TYPE: Callable[[Any, Dict[str, Any], str], None]
on_stop
A function to be called when this StreamPipesFunction gets stopped.
TYPE: Callable[[Any], None]
onEvent(event, streamId)
","text":"Trains the model with the incoming events and sends the prediction back to StreamPipes.
PARAMETER DESCRIPTIONevent
The incoming event that serves as input for the function
TYPE: Dict[str, Any]
streamId
Identifier of the corresponding data stream
TYPE: str
None
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.RiverFunction.onServiceStarted","title":"onServiceStarted(context)
","text":"Executes the on_start
method of the function.
context
The functions' context
TYPE: FunctionContext
None
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.RiverFunction.onServiceStopped","title":"onServiceStopped()
","text":"Executes the on_stop
function.
FunctionHandler(registration, client)
","text":"The function handler manages the StreamPipes Functions.
It controls the connection to the brokers, starts the functions, manages the broadcast of the live data and is able to stop the connection to the brokers and functions.
PARAMETER DESCRIPTIONregistration
The registration, that contains the StreamPipesFunctions.
TYPE: Registration
client
The client to interact with the API.
TYPE: StreamPipesClient
stream_contexts
Map of all data stream contexts
TYPE: Dict[str, DataStreamContext]
brokers
List of all registered brokers
TYPE: List[Broker]
disconnect()
","text":"Disconnects from the brokers and stops all functions.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/function_handler/#streampipes.functions.function_handler.FunctionHandler.force_stop_functions","title":"force_stop_functions()
","text":"Stops the StreamPipesFunctions when the event loop was stopped without stopping the functions.
RETURNS DESCRIPTIONNone
WARNS DESCRIPTION UserWarning
If there is a running event loop and the functions should be stopped by disconnecting from the broker.
"},{"location":"reference/functions/function_handler/#streampipes.functions.function_handler.FunctionHandler.initializeFunctions","title":"initializeFunctions()
","text":"Creates the context for every data stream and starts the event loop to manage the StreamPipes Functions.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/registration/","title":"Registration","text":""},{"location":"reference/functions/registration/#streampipes.functions.registration.Registration","title":"Registration()
","text":"Manages the existing StreamPipesFunctions and registers them.
ATTRIBUTE DESCRIPTIONfunctions
List of all registered StreamPipesFunction
TYPE: List[StreamPipesFunction]
getFunctions()
","text":"Get all registered functions.
This method exists to be consistent with the Java client.
RETURNS DESCRIPTIONfunctions
List of all registered functions.
TYPE: List[StreamPipesFunction]
register(streampipes_function)
","text":"Registers a new function.
PARAMETER DESCRIPTIONstreampipes_function
The function to register.
TYPE: StreamPipesFunction
self
The updated Registration instance
TYPE: Registration
StreamPipesFunction(function_definition=None)
","text":" Bases: ABC
Abstract implementation of a StreamPipesFunction.
A StreamPipesFunction allows users to get the data of a StreamPipes data streams easily. It makes it possible to work with the live data in python and enables to use the powerful data analytics libraries there.
PARAMETER DESCRIPTIONfunction_definition
the definition of the function that contains metadata about the connected function
TYPE: Optional[FunctionDefinition]
DEFAULT: None
output_collectors
List of all output collectors which are created based on the provided function definitions.
TYPE: Dict[str, OutputCollector]
add_output(stream_id, event)
","text":"Send an event via an output data stream to StreamPipes
PARAMETER DESCRIPTIONstream_id
The id of the output data stream
TYPE: str
event
The event which should be sent
TYPE: Dict[str, Any]
None
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.getFunctionId","title":"getFunctionId()
","text":"Returns the id of the function.
RETURNS DESCRIPTIONfunction_id
Identification object of the StreamPipes function
TYPE: FunctionId
onEvent(event, streamId)
abstractmethod
","text":"Is called for every event of a data stream.
PARAMETER DESCRIPTIONevent
The received event from the data stream.
TYPE: Dict[str, Any]
streamId
The id of the data stream which the event belongs to.
TYPE: str
None
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.onServiceStarted","title":"onServiceStarted(context)
abstractmethod
","text":"Is called when the function gets started.
PARAMETER DESCRIPTIONcontext
The context in which the function gets started.
TYPE: FunctionContext
None
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.onServiceStopped","title":"onServiceStopped()
abstractmethod
","text":"Is called when the function gets stopped.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.requiredStreamIds","title":"requiredStreamIds()
","text":"Get the ids of the streams needed by the function.
RETURNS DESCRIPTIONstream_ids
List of the stream ids
TYPE: List[str]
stop()
","text":"Stops the function and disconnects from the output streams
"},{"location":"reference/functions/broker/broker/","title":"Broker","text":""},{"location":"reference/functions/broker/broker/#streampipes.functions.broker.broker.Broker","title":"Broker
","text":" Bases: ABC
Abstract implementation of a broker for consumer and publisher.
It contains the basic logic to connect to a data stream.
"},{"location":"reference/functions/broker/broker/#streampipes.functions.broker.broker.Broker.connect","title":"connect(data_stream)
async
","text":"Connects to the broker running in StreamPipes.
PARAMETER DESCRIPTIONdata_stream
Contains the meta information (resources) for a data stream.
TYPE: DataStream
None
"},{"location":"reference/functions/broker/broker/#streampipes.functions.broker.broker.Broker.disconnect","title":"disconnect()
abstractmethod
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/broker/broker_handler/","title":"Broker handler","text":""},{"location":"reference/functions/broker/broker_handler/#streampipes.functions.broker.broker_handler.SupportedBroker","title":"SupportedBroker
","text":" Bases: Enum
Enum for the supported brokers.
"},{"location":"reference/functions/broker/broker_handler/#streampipes.functions.broker.broker_handler.UnsupportedBrokerError","title":"UnsupportedBrokerError(broker_name)
","text":" Bases: Exception
Exception if a broker isn't implemented yet.
"},{"location":"reference/functions/broker/broker_handler/#streampipes.functions.broker.broker_handler.get_broker","title":"get_broker(data_stream, is_publisher=False)
","text":"Derive the broker for the given data stream.
PARAMETER DESCRIPTIONdata_stream
Data stream instance from which the broker is inferred
TYPE: DataStream
broker
The corresponding broker instance derived from data stream.
TYPE: Broker
UnsupportedBrokerError
Is raised when the given data stream belongs to a broker that is currently not supported by StreamPipes Python.
"},{"location":"reference/functions/broker/broker_handler/#streampipes.functions.broker.broker_handler.get_broker_description","title":"get_broker_description(data_stream)
","text":"Derive the decription of the broker for the given data stream.
PARAMETER DESCRIPTIONdata_stream
Data stream instance from which the broker is inferred
TYPE: DataStream
broker
The corresponding broker description derived from data stream.
TYPE: SupportedBroker
UnsupportedBrokerError
Is raised when the given data stream belongs to a broker that is currently not supported by StreamPipes Python.
"},{"location":"reference/functions/broker/consumer/","title":"Consumer","text":""},{"location":"reference/functions/broker/consumer/#streampipes.functions.broker.consumer.Consumer","title":"Consumer
","text":" Bases: Broker
Abstract implementation a consumer for a broker.
A consumer allows to subscribe to a data stream.
"},{"location":"reference/functions/broker/consumer/#streampipes.functions.broker.consumer.Consumer.connect","title":"connect(data_stream)
async
","text":"Connects to the broker running in StreamPipes and creates a subscription.
PARAMETER DESCRIPTIONdata_stream
Contains the meta information (resources) for a data stream.
TYPE: DataStream
None
"},{"location":"reference/functions/broker/consumer/#streampipes.functions.broker.consumer.Consumer.get_message","title":"get_message()
abstractmethod
","text":"Get the published messages of the subscription.
RETURNS DESCRIPTIONiterator
An async iterator for the messages.
TYPE: AsyncIterator
OutputCollector(data_stream)
","text":"Collector for output events. The events are published to an output data stream. Therefore, the output collector establishes a connection to the broker.
PARAMETER DESCRIPTIONdata_stream
The output data stream that will receive the events.
TYPE: DataStream
publisher
The publisher instance that sends the data to StreamPipes
TYPE: Publisher
collect(event)
","text":"Publishes an event to the output stream.
PARAMETER DESCRIPTIONevent
The event to be published.
TYPE: Dict[str, Any]
None
"},{"location":"reference/functions/broker/output_collector/#streampipes.functions.broker.output_collector.OutputCollector.disconnect","title":"disconnect()
","text":"Disconnects the broker of the output collector.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/broker/publisher/","title":"Publisher","text":""},{"location":"reference/functions/broker/publisher/#streampipes.functions.broker.publisher.Publisher","title":"Publisher
","text":" Bases: Broker
Abstract implementation of a publisher for a broker.
A publisher allows to publish events to a data stream.
"},{"location":"reference/functions/broker/publisher/#streampipes.functions.broker.publisher.Publisher.publish_event","title":"publish_event(event)
abstractmethod
async
","text":"Publish an event to a connected data stream.
PARAMETER DESCRIPTIONevent
The event to be published.
TYPE: Dict[str, Any]
None
"},{"location":"reference/functions/broker/kafka/kafka_consumer/","title":"Kafka consumer","text":""},{"location":"reference/functions/broker/kafka/kafka_consumer/#streampipes.functions.broker.kafka.kafka_consumer.KafkaConsumer","title":"KafkaConsumer
","text":" Bases: Consumer
Implementation of a consumer for Kafka
"},{"location":"reference/functions/broker/kafka/kafka_consumer/#streampipes.functions.broker.kafka.kafka_consumer.KafkaConsumer.disconnect","title":"disconnect()
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/broker/kafka/kafka_consumer/#streampipes.functions.broker.kafka.kafka_consumer.KafkaConsumer.get_message","title":"get_message()
","text":"Get the published messages of the subscription.
RETURNS DESCRIPTIONiterator
An async iterator for the messages.
TYPE: AsyncIterator
KafkaMessage(data)
","text":"An internal representation of a Kafka message
PARAMETER DESCRIPTIONdata
The received Kafka message as byte array
"},{"location":"reference/functions/broker/kafka/kafka_message_fetcher/#streampipes.functions.broker.kafka.kafka_message_fetcher.KafkaMessageFetcher","title":"
KafkaMessageFetcher(consumer)
","text":"Fetches the next message from Kafka
PARAMETER DESCRIPTIONconsumer
The Kafka consumer
TYPE: Consumer
KafkaPublisher
","text":" Bases: Publisher
Implementation of a publisher for Kafka
"},{"location":"reference/functions/broker/kafka/kafka_publisher/#streampipes.functions.broker.kafka.kafka_publisher.KafkaPublisher.disconnect","title":"disconnect()
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/broker/kafka/kafka_publisher/#streampipes.functions.broker.kafka.kafka_publisher.KafkaPublisher.publish_event","title":"publish_event(event)
async
","text":"Publish an event to a connected data stream.
PARAMETER DESCRIPTIONevent
The event to be published.
TYPE: Dict[str, Any]
None
"},{"location":"reference/functions/broker/nats/nats_consumer/","title":"Nats consumer","text":""},{"location":"reference/functions/broker/nats/nats_consumer/#streampipes.functions.broker.nats.nats_consumer.NatsConsumer","title":"NatsConsumer
","text":" Bases: Consumer
Implementation of a consumer for NATS
"},{"location":"reference/functions/broker/nats/nats_consumer/#streampipes.functions.broker.nats.nats_consumer.NatsConsumer.disconnect","title":"disconnect()
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/broker/nats/nats_consumer/#streampipes.functions.broker.nats.nats_consumer.NatsConsumer.get_message","title":"get_message()
","text":"Get the published messages of the subscription.
RETURNS DESCRIPTIONmessage_iterator
An async iterator for the messages.
TYPE: AsyncIterator
NatsPublisher
","text":" Bases: Publisher
Implementation of a publisher for NATS
"},{"location":"reference/functions/broker/nats/nats_publisher/#streampipes.functions.broker.nats.nats_publisher.NatsPublisher.disconnect","title":"disconnect()
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/broker/nats/nats_publisher/#streampipes.functions.broker.nats.nats_publisher.NatsPublisher.publish_event","title":"publish_event(event)
async
","text":"Publish an event to a connected data stream.
PARAMETER DESCRIPTIONevent
The event to be published.
TYPE: Dict[str, Any]
None
"},{"location":"reference/functions/utils/async_iter_handler/","title":"Async iter handler","text":""},{"location":"reference/functions/utils/async_iter_handler/#streampipes.functions.utils.async_iter_handler.AsyncIterHandler","title":"AsyncIterHandler
","text":"Handles asynchronous iterators to get every message after another in parallel.
"},{"location":"reference/functions/utils/async_iter_handler/#streampipes.functions.utils.async_iter_handler.AsyncIterHandler.anext","title":"anext(stream_id, message)
async
staticmethod
","text":"Gets the next message from an AsyncIterator.
PARAMETER DESCRIPTIONstream_id
The id of the data stream which the message belongs to.
TYPE: str
message
An asynchronous iterator that contains the messages.
TYPE: AsyncIterator
result
Tuple of the stream id und next message or (\"stop\", None)
if no message is left.
TYPE: Tuple[str, Optional[Any]]
combine_async_messages(messages)
async
staticmethod
","text":"Continuously gets the next published message from multiple AsyncIterators in parallel.
PARAMETER DESCRIPTIONmessages
A dictionary with an asynchronous iterator for every stream id.
TYPE: Dict[str, AsyncIterator]
message
Description of the anonymous integer return value.
TYPE:: Tuple[str, Any]
DataStreamContext(functions, schema, broker)
","text":"Container for the context of a data stream.
PARAMETER DESCRIPTIONfunctions
StreamPipes Functions which require the data of this data stream.
TYPE: List[StreamPipesFunction]
schema
The schema of this data stream.
TYPE: DataStream
broker
The consumer to connect to this data stream.
TYPE: Consumer
add_function(function)
","text":"Adds a new StreamPipes Function.
PARAMETER DESCRIPTIONfunction
StreamPipesFunction which requires this data stream.
TYPE: StreamPipesFunction
None
"},{"location":"reference/functions/utils/data_stream_generator/","title":"Data stream generator","text":""},{"location":"reference/functions/utils/data_stream_generator/#streampipes.functions.utils.data_stream_generator.RuntimeType","title":"RuntimeType
","text":" Bases: Enum
Runtime type names for the attributes of a data stream.
ATTRIBUTE DESCRIPTIONSTRING
BOOLEAN
DOUBLE
FLOAT
INTEGER
LONG
"},{"location":"reference/functions/utils/data_stream_generator/#streampipes.functions.utils.data_stream_generator.create_data_stream","title":"
create_data_stream(name, attributes, stream_id=None, broker=SupportedBroker.NATS)
","text":"Creates a data stream
PARAMETER DESCRIPTIONname
Name of the data stream to be shown at the UI.
TYPE: str
attributes
Name and types of the attributes.
TYPE: Dict[str, str]
stream_id
The id of this data stream.
TYPE: Optional[str]
DEFAULT: None
data_stream
The created data stream
TYPE: DataStream
FunctionContext(function_id, schema, client, streams)
","text":"Container for the context of a StreamPipesFunction.
PARAMETER DESCRIPTIONfunction_id
The id of this function.
TYPE: str
schema
A dictionary which contains the schema of a data stream for each stream id.
TYPE: Dict[str, DataStream]
client
The client to interact with the API.
TYPE: StreamPipesClient
streams
The ids of the streams needed by this function.
TYPE: List[str]
add_data_stream_schema(stream_id, data_stream)
","text":"Adds a new data stream for a new stream id.
PARAMETER DESCRIPTIONstream_id
The id of the data stream.
TYPE: str
data_stream
The schema of the data stream.
TYPE: DataStream
None
"},{"location":"reference/model/common/","title":"Common","text":"Classes of the StreamPipes data model that are commonly shared.
"},{"location":"reference/model/common/#streampipes.model.common.ApplicationLink","title":"ApplicationLink
","text":" Bases: BasicModel
Data model of an ApplicationLink
in compliance to the StreamPipes Backend.
BaseElement
","text":" Bases: BasicModel
Structure of a basic element in the StreamPipes backend
"},{"location":"reference/model/common/#streampipes.model.common.BasicModel","title":"BasicModel
","text":" Bases: BaseModel
Basic model class used for the whole Python StreamPipes data model.
"},{"location":"reference/model/common/#streampipes.model.common.BasicModel.Config","title":"Config
","text":"Configuration class for Pydantic. Defines alias generator to convert field names from camelCase (API) to snake_case (Python codebase).
"},{"location":"reference/model/common/#streampipes.model.common.EventGrounding","title":"EventGrounding
","text":" Bases: BasicModel
Data model of an EventGrounding
in compliance to the StreamPipes Backend.
EventProperty
","text":" Bases: BasicModel
Data model of an EventProperty
in compliance to the StreamPipes Backend.
EventSchema
","text":" Bases: BasicModel
Data model of an EventSchema
in compliance to the StreamPipes Backend.
MeasurementCapability
","text":" Bases: BasicModel
Data model of a MeasurementCapability
in compliance to the StreamPipes Backend.
MeasurementObject
","text":" Bases: BasicModel
Data model of a MeasurementObject
in compliance to the StreamPipes Backend.
TopicDefinition
","text":" Bases: BasicModel
Data model of a TopicDefinition
in compliance to the StreamPipes Backend.
TransportFormat
","text":" Bases: BasicModel
Data model of a TransportFormat
in compliance to the StreamPipes Backend.
TransportProtocol
","text":" Bases: BasicModel
Data model of a TransportProtocol
in compliance to the StreamPipes Backend.
ValueSpecification
","text":" Bases: BasicModel
Data model of an ValueSpecification
in compliance to the StreamPipes Backend.
random_letters(n)
","text":"Generates a string consisting of random letters.
PARAMETER DESCRIPTIONn
number of letters
TYPE: int
rand_str
String consisting of n
random letters
TYPE: str
Implementation of a resource container for the data lake measures endpoint.
"},{"location":"reference/model/container/data_lake_measures/#streampipes.model.container.data_lake_measures.DataLakeMeasures","title":"DataLakeMeasures
","text":" Bases: ResourceContainer
Implementation of the resource container for the data lake measures endpoint.
This resource container is a collection of data lake measures returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried DataLakeMeasure
. Furthermore, the resource container makes them accessible in a pythonic manner.
Implementation of a resource container for the data streams endpoint.
"},{"location":"reference/model/container/data_streams/#streampipes.model.container.data_streams.DataStreams","title":"DataStreams
","text":" Bases: ResourceContainer
Implementation of the resource container for the data stream endpoint.
This resource container is a collection of data streams returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried DataStream
. Furthermore, the resource container makes them accessible in a pythonic manner.
General and abstract implementation for a resource container.
A resource container is a collection of resources returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried resources. Furthermore, the resource container makes them accessible in a pythonic manner.
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.ResourceContainer","title":"ResourceContainer(resources)
","text":" Bases: ABC
General and abstract implementation for a resource container.
A resource container is a collection of resources returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried resources. Furthermore, the resource container makes them accessible in a pythonic manner.
PARAMETER DESCRIPTIONresources
A list of resources to be contained in the ResourceContainer
.
TYPE: List[Resource]
from_json(json_string)
classmethod
","text":"Creates a ResourceContainer
from the given JSON string.
json_string
The JSON string returned from the StreamPipes API.
TYPE: str
container
instance of the container derived from the JSON definition
TYPE: ResourceContainer
StreamPipesDataModelError
If a resource cannot be mapped to the corresponding Python data model.
StreamPipesResourceContainerJSONError
If JSON response cannot be parsed to a ResourceContainer
.
to_dicts(use_source_names=False)
","text":"Returns the contained resources as list of dictionaries.
PARAMETER DESCRIPTIONuse_source_names
Determines whether the field names are named in Python style (=False
) or as originally named by StreamPipes (=True
).
TYPE: bool
DEFAULT: False
dictionary_list
List of resources in dictionary representation. If use_source_names
equals True
the keys are named as in the StreamPipes backend.
TYPE: List[Dict[str, Any]]
to_json()
","text":"Returns the resource container in the StreamPipes JSON representation.
RETURNS DESCRIPTION json_string: str
JSON representation of the resource container where key names are equal to keys used in the StreamPipes backend
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.ResourceContainer.to_pandas","title":"to_pandas()
","text":"Returns the resource container in representation of a Pandas Dataframe.
RETURNS DESCRIPTIONresource_container_df
Representation of the resource container as pandas DataFrame
TYPE: pd.DataFrame
StreamPipesDataModelError(validation_error)
","text":" Bases: Exception
A custom exception to be raised when a validation error occurs during the parsing of StreamPipes API responses.
PARAMETER DESCRIPTIONvalidation_error
The validation error thrown by Pydantic during parsing.
TYPE: ValidationError
StreamPipesResourceContainerJSONError(container_name, json_string)
","text":" Bases: Exception
A custom exception to be raised when the returned JSON string does not suit to the structure of resource container.
PARAMETER DESCRIPTIONcontainer_name
The class name of the resource container where the invalid data structure was detected.
TYPE: str
json_string
The JSON string that has been tried to parse.
TYPE: str
Implementation of a resource container for the versions endpoint.
"},{"location":"reference/model/container/versions/#streampipes.model.container.versions.Versions","title":"Versions
","text":" Bases: ResourceContainer
Implementation of the resource container for the versions endpoint.
This resource container is a collection of versions returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried Version
. Furthermore, the resource container makes them accessible in a pythonic manner.
resources
A list of resources (Version) to be contained in the ResourceContainer
.
"},{"location":"reference/model/resource/data_lake_measure/","title":"Data lake measure","text":""},{"location":"reference/model/resource/data_lake_measure/#streampipes.model.resource.data_lake_measure.DataLakeMeasure","title":"
DataLakeMeasure
","text":" Bases: Resource
Implementation of a resource for data lake measures.
This resource defines the data model used by resource container (model.container.DataLakeMeasures
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response, and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
convert_to_pandas_representation()
","text":"Returns the dictionary representation of a data lake measure to be used when creating a pandas Dataframe.
It excludes the following fields: element_id
, event_schema
, schema_version
. Instead of the whole event schema the number of event properties contained is returned with the column name num_event_properties
.
pandas_repr
Pandas representation of the resource as a dictionary, which is then used by the respource container to create a data frame from a collection of resources.
TYPE: Dict[str, Any]
DataSeries
","text":" Bases: Resource
Implementation of a resource for data series. This resource defines the data model used by its resource container(model.container.DataLakeMeasures
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
This class will only exist temporarily in it its current appearance since\nthere are some inconsistencies in the StreamPipes API.\n
"},{"location":"reference/model/resource/data_series/#streampipes.model.resource.data_series.DataSeries.convert_to_pandas_representation","title":"convert_to_pandas_representation()
","text":"Returns the dictionary representation of a data lake series to be used when creating a pandas Dataframe.
It contains only the \"header rows\" (the column names) and \"rows\" that contain the actual data.
RETURNS DESCRIPTIONpandas_repr
Dictionary with the keys headers
and rows
TYPE: dict[str, Any]
from_json(json_string)
classmethod
","text":"Creates an instance of DataSeries
from a given JSON string.
This method is used by the resource container to parse the JSON response of the StreamPipes API. Currently, it only supports data lake series that consist of exactly one series of data.
PARAMETER DESCRIPTIONjson_string
The JSON string the data lake series should be created on.
TYPE: str
DataSeries
Instance of DataSeries
that is created based on the given JSON string.
StreamPipesUnsupportedDataLakeSeries
If the data lake series returned by the StreamPipes API cannot be parsed with the current version of the Python client.
"},{"location":"reference/model/resource/data_series/#streampipes.model.resource.data_series.DataSeries.to_pandas","title":"to_pandas()
","text":"Returns the data lake series in representation of a Pandas Dataframe.
RETURNS DESCRIPTIONpd
The data lake series in form of a pandas dataframe
TYPE: pd.DataFrame
DataStream(**kwargs)
","text":" Bases: Resource
Implementation of a resource for data streams.
This resource defines the data model used by resource container (model.container.DataStreams
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
convert_to_pandas_representation()
","text":"Returns the dictionary representation of a data stream to be used when creating a pandas Dataframe.
RETURNS DESCRIPTIONpandas_repr
Pandas representation of the resource as a dictionary, which is then used by the respource container to create a data frame from a collection of resources.
TYPE: Dict[str, Any]
to_dict(use_source_names=True)
","text":"Returns the resource in dictionary representation.
PARAMETER DESCRIPTIONuse_source_names
Indicates if the dictionary keys are in python representation or equally named to the StreamPipes backend
DEFAULT: True
resource
The resource as dictionary representation
TYPE: Dict[str, Any]
StreamPipesUnsupportedDataSeries(reason=None)
","text":" Bases: Exception
Exception to be raised when the returned data lake series cannot be parsed with the current implementation of the resource.
"},{"location":"reference/model/resource/function_definition/","title":"Function definition","text":""},{"location":"reference/model/resource/function_definition/#streampipes.model.resource.function_definition.FunctionDefinition","title":"FunctionDefinition
","text":" Bases: Resource
Configuration for a StreamPipes Function.
This class maps to the FunctionDefinition
class in the StreamPipes model. It contains all metadata that are required to register a function at the StreamPipes backend.
consumed_streams
List of data streams the function is consuming from
function_id
identifier object of a StreamPipes function
ATTRIBUTE DESCRIPTION
output_data_streams
Map off all output data streams added to the function definition
TYPE: Dict[str, DataStream]
add_output_data_stream(data_stream)
","text":"Adds an output data stream to the function which makes it possible to write data back to StreamPipes.
PARAMETER DESCRIPTIONdata_stream
The schema of the output data stream.
TYPE: DataStream
self
Instance of the function definition that is extended by the provided DataStream
TYPE: FunctionDefinition
convert_to_pandas_representation()
","text":"Returns the dictionary representation of a function definition to be used when creating a pandas Dataframe.
RETURNS DESCRIPTIONpandas_repr
Pandas representation of the resource as a dictionary, which is then used by the respource container to create a data frame from a collection of resources.
TYPE: Dict[str, Any]
get_output_data_streams()
","text":"Get the output data streams of the function.
RETURNS DESCRIPTIONoutput_streams
Dictionary with every known stream id and the related output stream.
TYPE: Dict[str, DataStream]
get_output_stream_ids()
","text":"Get the stream ids of the output data streams.
RETURNS DESCRIPTIONoutput_stream_ids
List of all stream ids
TYPE: List[str]
FunctionId
","text":" Bases: BasicModel
Identification object for a StreamPipes function.
Maps to the FunctionId
class defined in the StreamPipes model.
id
unique identifier of the function instance
version
version of the corresponding function
"},{"location":"reference/model/resource/query_result/","title":"Query result","text":""},{"location":"reference/model/resource/query_result/#streampipes.model.resource.query_result.QueryResult","title":"
QueryResult
","text":" Bases: Resource
Implementation of a resource for query result. This resource defines the data model used by its resource container(model.container.DataLakeMeasures
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
convert_to_pandas_representation()
","text":"Returns the dictionary representation of a data lake series to be used when creating a pandas Dataframe.
It contains only the \"header rows\" (the column names) and \"rows\" that contain the actual data.
RETURNS DESCRIPTIONdict
Dictionary with the keys headers
and rows
StreamPipesUnsupportedDataLakeSeries
If the query result returned by the StreamPipes API cannot be converted to the pandas representation
"},{"location":"reference/model/resource/query_result/#streampipes.model.resource.query_result.QueryResult.to_pandas","title":"to_pandas()
","text":"Returns the data lake series in representation of a Pandas Dataframe.
RETURNS DESCRIPTIONdf
Pandas df containing the query result
TYPE: pd.DataFrame
General and abstract implementation for a resource.
A resource defines the data model that is used by a resource container (model.container.resourceContainer
).
Resource
","text":" Bases: ABC
, BasicModel
General and abstract implementation for a resource.
A resource defines the data model used by a resource container (model.container.resourceContainer
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
convert_to_pandas_representation()
abstractmethod
","text":"Returns a dictionary representation to be used when creating a pandas Dataframe.
RETURNS DESCRIPTIONpandas_repr
Pandas representation of the resource as a dictionary, which is then used by the respource container to create a data frame from a collection of resources.
TYPE: Dict[str, Any]
to_dict(use_source_names=True)
","text":"Returns the resource in dictionary representation.
PARAMETER DESCRIPTIONuse_source_names
Indicates if the dictionary keys are in python representation or equally named to the StreamPipes backend
DEFAULT: True
resource
The resource as dictionary representation
TYPE: Dict[str, Any]
Version
","text":" Bases: Resource
Metadata about the version of the connected StreamPipes server.
ATTRIBUTE DESCRIPTIONbackend_version
version of the StreamPipes backend the client is connected to
TYPE: str
convert_to_pandas_representation()
","text":"Returns the dictionary representation of the version metadata to be used when creating a pandas Dataframe.
"},{"location":"scripts/gen_ref_pages/","title":"Gen ref pages","text":"Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
In\u00a0[\u00a0]: Copied!from pathlib import Path\nfrom pathlib import Path In\u00a0[\u00a0]: Copied!
import mkdocs_gen_files\nimport mkdocs_gen_files In\u00a0[\u00a0]: Copied!
nav = mkdocs_gen_files.Nav()\nnav = mkdocs_gen_files.Nav() In\u00a0[\u00a0]: Copied!
for path in sorted(Path(\"streampipes\").rglob(\"*.py\")):\n module_path = path.relative_to(\"streampipes\").with_suffix(\"\")\n doc_path = path.relative_to(\"streampipes\").with_suffix(\".md\")\n full_doc_path = Path(\"reference\", doc_path)\n\n parts = list(module_path.parts)\n\n if parts[-1] == \"__init__\":\n # parts = parts[:-1]\n continue\n elif parts[-1] == \"__version__\":\n continue\n elif parts[-1] == \"__main__\":\n continue\n elif parts[-1] == \" \":\n continue\n\n nav[parts] = doc_path.as_posix()\n\n with mkdocs_gen_files.open(full_doc_path, \"w+\") as fd:\n identifier = \".\".join(parts)\n print(f\"::: streampipes.{identifier}\", file=fd)\n\n mkdocs_gen_files.set_edit_path(full_doc_path, path)\nfor path in sorted(Path(\"streampipes\").rglob(\"*.py\")): module_path = path.relative_to(\"streampipes\").with_suffix(\"\") doc_path = path.relative_to(\"streampipes\").with_suffix(\".md\") full_doc_path = Path(\"reference\", doc_path) parts = list(module_path.parts) if parts[-1] == \"__init__\": # parts = parts[:-1] continue elif parts[-1] == \"__version__\": continue elif parts[-1] == \"__main__\": continue elif parts[-1] == \" \": continue nav[parts] = doc_path.as_posix() with mkdocs_gen_files.open(full_doc_path, \"w+\") as fd: identifier = \".\".join(parts) print(f\"::: streampipes.{identifier}\", file=fd) mkdocs_gen_files.set_edit_path(full_doc_path, path)
with mkdocs_gen_files.open(\"reference/SUMMARY.md\", \"w+\") as nav_file: nav_file.writelines(nav.build_literate_nav())
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/","title":"Introduction to StreamPipes Python","text":"In\u00a0[\u00a0]: Copied!%pip install streampipes\n%pip install streampipes
If you want to have the current development state you can also execute:
In\u00a0[\u00a0]: Copied!%pip install git+https://github.com/apache/streampipes.git#subdirectory=streampipes-client-python\n%pip install git+https://github.com/apache/streampipes.git#subdirectory=streampipes-client-python
The corresponding documentation can be found here.
In\u00a0[\u00a0]: Copied!from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\nfrom streampipes.client import StreamPipesClient from streampipes.client.config import StreamPipesClientConfig from streampipes.client.credential_provider import StreamPipesApiKeyCredentials In\u00a0[\u00a0]: Copied!
config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(\n username=\"test@streampipes.apache.org\",\n api_key=\"API-KEY\",\n ),\n host_address=\"localhost\",\n https_disabled=True,\n port=80\n)\nconfig = StreamPipesClientConfig( credential_provider=StreamPipesApiKeyCredentials( username=\"test@streampipes.apache.org\", api_key=\"API-KEY\", ), host_address=\"localhost\", https_disabled=True, port=80 )
Please be aware that connecting to StreamPipes via a https
connection is currently not supported by the Python client.
Providing secrets like the api_key
as plaintext in the source code is an anti-pattern. This is why the StreamPipes client also supports passing the required secrets as environment variables. To do so, you must initialize the credential provider like the following:
StreamPipesApiKeyCredentials()\nStreamPipesApiKeyCredentials()
To ensure that the above code works, you must set the environment variables as expected. This can be done like following:
In\u00a0[\u00a0]: Copied!%export SP_USERNAME=\"<USERNAME>\"\n%export SP_API_KEY=\"<API-KEY>\"\n%export SP_USERNAME=\"\" %export SP_API_KEY=\"\"
Having the config
ready, we can now initialize the actual client.
client = StreamPipesClient(client_config=config)\nclient = StreamPipesClient(client_config=config)
That's already it. You can check if everything works out by using the following command:
In\u00a0[6]: Copied!client.describe()\nclient.describe()
2023-02-24 17:05:49,398 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n2023-02-24 17:05:49,457 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n\nHi there!\nYou are connected to a StreamPipes instance running at http://localhost:80.\nThe following StreamPipes resources are available with this client:\n1x DataLakeMeasures\n1x DataStreams\n
This prints you a short textual description of the connected StreamPipes instance to the console.
The created client
instance serves as the central point of interaction with StreamPipes. You can invoke a variety of commands directly on this object.
Are you curious now how you actually can get data out of StreamPipes and make use of it with Python? Then check out the next tutorial on extracting Data from the StreamPipes data lake.
Thanks for reading this introductory tutorial. We hope you like it and would love to receive some feedback from you. Just go to our GitHub discussion page and let us know your impression. We'll read and react to them all, we promise!
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/#Introduction-to-StreamPipes-Python","title":"Introduction to StreamPipes Python\u00b6","text":""},{"location":"tutorials/1-introduction-to-streampipes-python-client/#Why-there-is-an-extra-Python-library-for-StreamPipes?","title":"Why there is an extra Python library for StreamPipes?\u00b6","text":"Apache StreamPipes aims to enable non-technical users to connect and analyze IoT data streams. To this end, it provides an easy-to-use and convenient user interface that allows one to connect to an IoT data source and create some visual graphs within a few minutes. Although this is the main use case of Apache StreamPipes, it can also provide great value for people who are eager to work on data analysis or data science with IoT data, but don't we do get in touch with all the hassle associated with extracting data from devices in a suitable format. In this scenario, StreamPipes helps you connect to your data source and extract the data for you. You then can make the data available outside StreamPipes by writing it into an external source, such as a database, Kafka, etc. While this requires another component, you can also extract your data directly from StreamPipes programmatically using the StreamPipes API. For convenience, we also provide you with a StreamPipes client both available for Java and Python. Specifically with StreamPipes Python, we want to address the amazing data analytics and data science community in Python and benefit from the great universe of Python libraries out there.
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/#How-to-install-StreamPipes-Python?","title":"How to install StreamPipes Python?\u00b6","text":"Simply use the following pip
command:
In case you want to reproduce the first two tutorials exactly on your end, you need to create a simple pipeline in StreamPipes like demonstrated below.
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/#How-to-configure-the-Python-client","title":"How to configure the Python client\u00b6","text":"In order to access the resources available in StreamPipes, one must be able to authenticate against the backend. For this purpose, the client sofar only supports the authentication via an API token that can be generated via the StreamPipes UI, as you see below.
Having generated the API token, one can directly start initializing a client instance as follows:
"},{"location":"tutorials/2-extracting-data-from-the-streampipes-data-lake/","title":"Extracting Data from the StreamPipes data lake","text":"In\u00a0[1]: Copied!from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\nfrom streampipes.client import StreamPipesClient from streampipes.client.config import StreamPipesClientConfig from streampipes.client.credential_provider import StreamPipesApiKeyCredentials In\u00a0[\u00a0]: Copied!
# if you want all necessary dependencies required for this tutorial to be installed,\n# you can simply execute the following command\n%pip install matplotlib streampipes\n# if you want all necessary dependencies required for this tutorial to be installed, # you can simply execute the following command %pip install matplotlib streampipes In\u00a0[2]: Copied!
import os\nos.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\"\nos.environ[\"SP_API_KEY\"] = \"XXX\"\nimport os os.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\" os.environ[\"SP_API_KEY\"] = \"XXX\" In\u00a0[3]: Copied!
config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(),\n host_address=\"localhost\",\n https_disabled=True,\n port=80\n)\nconfig = StreamPipesClientConfig( credential_provider=StreamPipesApiKeyCredentials(), host_address=\"localhost\", https_disabled=True, port=80 ) In\u00a0[4]: Copied!
client = StreamPipesClient(client_config=config)\nclient = StreamPipesClient(client_config=config)
2023-02-24 17:34:25,860 - streampipes.client.client - [INFO] - [client.py:128] [_set_up_logging] - Logging successfully initialized with logging level INFO.\n
As a first step, we want to get an overview about all data available in the data lake. The data is stored as so-called measures
, which refer to a data stream stored in the data lake. For his purpose we use the all()
method of the dataLakeMeasure
endpoint.
data_lake_measures = client.dataLakeMeasureApi.all()\ndata_lake_measures = client.dataLakeMeasureApi.all()
2023-02-24 17:34:25,929 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n
So let's see how many measures are available
In\u00a0[6]: Copied!len(data_lake_measures)\nlen(data_lake_measures) Out[6]:
2
All resources of the StreamPipes Python client support the standard Python expressions. If not, please let us know.
In\u00a0[7]: Copied!data_lake_measures[-1]\ndata_lake_measures[-1] Out[7]:
DataLakeMeasure(element_id='3cb6b5e6f107452483d1fd2ccf4bf9f9', measure_name='test', timestamp_field='s0::timestamp', event_schema=EventSchema(event_properties=[EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:EiFnkL', label='Density', description='Denotes the current density of the fluid', runtime_name='density', required=False, domain_properties=['http://schema.org/Number'], property_scope='MEASUREMENT_PROPERTY', index=5, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#float', measurement_unit=None, value_specification=None), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:ghSkQI', label='Mass Flow', description='Denotes the current mass flow in the sensor', runtime_name='mass_flow', required=False, domain_properties=['http://schema.org/Number'], property_scope='MEASUREMENT_PROPERTY', index=2, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#float', measurement_unit=None, value_specification=None), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:cQAUry', label='Sensor ID', description='The ID of the sensor', runtime_name='sensorId', required=False, domain_properties=['https://streampipes.org/vocabulary/examples/watertank/v1/hasSensorId'], property_scope='DIMENSION_PROPERTY', index=1, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#string', measurement_unit=None, value_specification=None), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:pbPMyL', label='Sensor Fault Flags', description='Any fault flags of the sensors', runtime_name='sensor_fault_flags', required=False, domain_properties=['http://schema.org/Boolean'], property_scope='MEASUREMENT_PROPERTY', index=6, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#boolean', measurement_unit=None, value_specification=None), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:Qmayhw', label='Temperature', description='Denotes the current temperature in degrees celsius', runtime_name='temperature', required=False, domain_properties=['http://schema.org/Number'], property_scope='MEASUREMENT_PROPERTY', index=4, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#float', measurement_unit='http://qudt.org/vocab/unit#DegreeCelsius', value_specification=ValueSpecification(class_name='org.apache.streampipes.model.schema.QuantitativeValue', element_id=None, min_value=0, max_value=100, step=0.1)), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:YQYhjd', label='Volume Flow', description='Denotes the current volume flow', runtime_name='volume_flow', required=False, domain_properties=['http://schema.org/Number'], property_scope='MEASUREMENT_PROPERTY', index=3, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#float', measurement_unit=None, value_specification=None)]), pipeline_id=None, pipeline_name=None, pipeline_is_running=False, schema_version='1.1')
To get a more comprehensive overview, you can take a look at the pandas
representation
display(data_lake_measures.to_pandas())\ndisplay(data_lake_measures.to_pandas()) measure_name timestamp_field pipeline_id pipeline_name pipeline_is_running num_event_properties 0 flow-rate s0::timestamp None None False 6 1 test s0::timestamp None None False 6
So far, we have only retrieved metadata about the available data lake measure. In the following, we will access the actual data of the measure flow-rate
.
For this purpose, we will use the get()
method of the dataLakeMeasure
endpoint.
flow_rate_measure = client.dataLakeMeasureApi.get(identifier=\"flow-rate\")\nflow_rate_measure = client.dataLakeMeasureApi.get(identifier=\"flow-rate\")
2023-02-24 17:34:26,020 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n
For further processing, the easiest way is to turn the data measure into a pandas DataFrame
.
flow_rate_pd = flow_rate_measure.to_pandas()\nflow_rate_pd = flow_rate_measure.to_pandas()
Let's see how many data points we got...
In\u00a0[11]: Copied!len(flow_rate_pd)\nlen(flow_rate_pd) Out[11]:
1000
... and get a first overview
In\u00a0[12]: Copied!flow_rate_pd.describe()\nflow_rate_pd.describe() Out[12]: density mass_flow temperature volume_flow count 1000.000000 1000.000000 1000.000000 1000.000000 mean 45.560337 5.457014 45.480231 5.659558 std 3.201544 3.184959 3.132878 3.122437 min 40.007698 0.004867 40.000992 0.039422 25% 42.819497 2.654101 42.754623 3.021625 50% 45.679264 5.382355 45.435944 5.572553 75% 48.206881 8.183144 48.248473 8.338209 max 50.998310 10.986015 50.964909 10.998676
As a final step, we want to create a plot of both attributes
In\u00a0[13]: Copied!import matplotlib.pyplot as plt\nflow_rate_pd.plot(y=[\"mass_flow\", \"temperature\"])\nplt.show()\nimport matplotlib.pyplot as plt flow_rate_pd.plot(y=[\"mass_flow\", \"temperature\"]) plt.show()
For data lake measurements, the get()
method is even more powerful than simply returning all the data for a given data lake measurement. We will look at a selection of these below. The full list of supported parameters can be found in the docs. Let's start by referring to the graph we created above, where we use only two columns of our data lake measurement. If we already know this, we can directly restrict the queried data to a subset of columns by using the columns
parameter. columns
takes a list of column names as a comma-separated string:
flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", columns=\"mass_flow,temperature\").to_pandas()\nflow_rate_pd\nflow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", columns=\"mass_flow,temperature\").to_pandas() flow_rate_pd
2023-02-24 17:34:26,492 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\nOut[14]: timestamp mass_flow temperature 0 2023-02-24T16:19:41.472Z 3.309556 44.448483 1 2023-02-24T16:19:41.482Z 5.608580 40.322033 2 2023-02-24T16:19:41.493Z 7.692881 49.239639 3 2023-02-24T16:19:41.503Z 3.632898 49.933754 4 2023-02-24T16:19:41.513Z 0.711260 50.106617 ... ... ... ... 995 2023-02-24T16:19:52.927Z 1.740114 46.558231 996 2023-02-24T16:19:52.94Z 7.211723 48.048622 997 2023-02-24T16:19:52.952Z 7.770180 48.188026 998 2023-02-24T16:19:52.965Z 4.458602 48.280899 999 2023-02-24T16:19:52.977Z 2.592060 47.505951
1000 rows \u00d7 3 columns
By default, the client returns only the first one thousand records of a Data Lake measurement. This can be changed by passing a concrete value for the limit
parameter:
flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", limit=10000).to_pandas()\nlen(flow_rate_pd)\nflow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", limit=10000).to_pandas() len(flow_rate_pd)
2023-02-24 17:34:26,736 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\nOut[15]:
9528
If you want your data to be selected by time of occurrence rather than quantity, you can specify your time window by passing the start_date
and end_date
parameters:
from datetime import datetime\nflow_rate_pd = client.dataLakeMeasureApi.get(\n identifier=\"flow-rate\",\n start_date=datetime(year=2023, month=2, day=24, hour=17, minute=21, second=0),\n end_date=datetime(year=2023, month=2, day=24, hour=17, minute=21, second=1),\n ).to_pandas()\nflow_rate_pd.plot(y=[\"mass_flow\", \"temperature\"])\nplt.show()\nfrom datetime import datetime flow_rate_pd = client.dataLakeMeasureApi.get( identifier=\"flow-rate\", start_date=datetime(year=2023, month=2, day=24, hour=17, minute=21, second=0), end_date=datetime(year=2023, month=2, day=24, hour=17, minute=21, second=1), ).to_pandas() flow_rate_pd.plot(y=[\"mass_flow\", \"temperature\"]) plt.show()
2023-02-24 17:34:26,899 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n
... from this point on we leave all future processing of the data up to your creativity. Keep in mind: the general syntax used in this tutorial (all()
, to_pandas()
, get()
) applies to all endpoints and associated resources of the StreamPipes Python client.
If you get further and create exiting stuff with data extracted from StreamPipes please let us know. We are thrilled to see what you as a community will build with the provided client. Furthermore, don't hesitate to discuss feature requests to extend the current functionality with us.
For now, that's all about the StreamPipes client. Read the next tutorial (Getting live data from the StreamPipes data stream) if you are interested in making use of the powerful StreamPipes functions to interact with StreamPipes event-based.
How do you like this tutorial? We hope you like it and would love to receive some feedback from you. Just go to our GitHub discussion page and let us know your impression. We'll read and react to them all, we promise!
"},{"location":"tutorials/2-extracting-data-from-the-streampipes-data-lake/#Extracting-Data-from-the-StreamPipes-data-lake","title":"Extracting Data from the StreamPipes data lake\u00b6","text":"In the first tutorial (Introduction to the StreamPipes Python client) we took the first steps with the StreamPipes Python client and learned how to set everything up. Now we are ready to get started and want to retrieve some data out of StreamPipes. In this tutorial, we'll focus on the StreamPipes Data Lake, the component where StreamPipes stores data internally. To get started, we'll use the client
instance created in the first tutorial.
Note As of now we mainly developed the support for StreamPipes functions using NATS as messaging protocol. Consequently, this setup is tested most and should work flawlessly. Visit our first-steps page to see how to start StreamPipes accordingly. Anyhow, you can also use the other brokers that are currently supported in StreamPipes Python. In case you observe any problems, please reach out to us and file us an issue on GitHub.
In\u00a0[1]: Copied!from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\nfrom streampipes.client import StreamPipesClient from streampipes.client.config import StreamPipesClientConfig from streampipes.client.credential_provider import StreamPipesApiKeyCredentials In\u00a0[\u00a0]: Copied!
# You can install all required libraries for this tutorial with the following command\n%pip install matplotlib ipython streampipes\n# You can install all required libraries for this tutorial with the following command %pip install matplotlib ipython streampipes In\u00a0[2]: Copied!
import os\n\nos.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\"\nos.environ[\"SP_API_KEY\"] = \"XXX\"\n\n# Use this if you work locally:\nos.environ[\"BROKER-HOST\"] = \"localhost\" \nos.environ[\"KAFKA-PORT\"] = \"9094\" # When using Kafka as message broker\nimport os os.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\" os.environ[\"SP_API_KEY\"] = \"XXX\" # Use this if you work locally: os.environ[\"BROKER-HOST\"] = \"localhost\" os.environ[\"KAFKA-PORT\"] = \"9094\" # When using Kafka as message broker In\u00a0[3]: Copied!
client_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(),\n host_address=\"localhost\",\n port=80,\n https_disabled=True,\n)\nclient = StreamPipesClient(client_config=client_config)\nclient_config = StreamPipesClientConfig( credential_provider=StreamPipesApiKeyCredentials(), host_address=\"localhost\", port=80, https_disabled=True, ) client = StreamPipesClient(client_config=client_config)
2022-12-14 10:43:37,664 - streampipes.client.client - [INFO] - [client.py:127] [_set_up_logging] - Logging successfully initialized with logging level INFO.\n
Now we can have a look at the available data streams. We can choose one or more stream to receive the data from and copy their element_id
.
client.dataStreamApi.all().to_pandas()\nclient.dataStreamApi.all().to_pandas()
2022-12-14 10:43:39,944 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:153] [_make_request] - Successfully retrieved all resources.\nOut[4]: element_id name description icon_url app_id includes_assets includes_locales internally_managed measurement_object index ... uri dom num_transport_protocols num_measurement_capability num_application_links num_included_assets num_connected_to num_category num_event_properties num_included_locales 0 urn:streampipes.apache.org:eventstream:HHoidJ Test2 None None False False True None 0 ... urn:streampipes.apache.org:eventstream:HHoidJ None 1 0 0 0 0 0 7 0 1 urn:streampipes.apache.org:eventstream:uPDKLI Test None None False False True None 0 ... urn:streampipes.apache.org:eventstream:uPDKLI None 1 0 0 0 0 0 7 0
2 rows \u00d7 21 columns
Next we can create a StreamPipesFunction. For this we need to implement the 3 following methods:
onServiceStarted
is called when the function gets started. There you can use the given meta information of the FunctionContext
to initialize the function.onEvent
is called when ever a new event arrives. The event
contains the live data and you can use the streamId
to identify a stream if the function is connected to multiple data streams.onServiceStopped
is called when the function gets stopped.For this tutorial we just create a function that saves every new event in a pandas DataFrame
and plots the first column of the DataFrame
when the function gets stopped.
(If you want to use the same structure as in Java you can overwrite the getFunctionId
and requiredStreamIds
methods instead of using the FunctionDefinition
)
from typing import Dict, Any\nimport pandas as pd\nfrom datetime import datetime\nimport matplotlib.pyplot as plt\nfrom streampipes.functions.function_handler import FunctionHandler\nfrom streampipes.functions.registration import Registration\nfrom streampipes.functions.streampipes_function import StreamPipesFunction\nfrom streampipes.functions.utils.function_context import FunctionContext\nfrom streampipes.model.resource.function_definition import FunctionDefinition, FunctionId\n\nclass ExampleFunction(StreamPipesFunction):\n def __init__(self, function_definition: FunctionDefinition) -> None:\n super().__init__(function_definition)\n # Create the Dataframe to save the live data\n self.df = pd.DataFrame()\n\n def onServiceStarted(self, context: FunctionContext):\n # Get the name of the timestamp field\n for event_property in context.schema[context.streams[0]].event_schema.event_properties:\n if event_property.property_scope == \"HEADER_PROPERTY\":\n self.timestamp = event_property.runtime_name\n\n def onEvent(self, event: Dict[str, Any], streamId: str):\n # Convert the unix timestamp to datetime\n event[self.timestamp] = datetime.fromtimestamp(event[self.timestamp] / 1000)\n # Add every value of the event to the DataFrame\n self.df = pd.concat(\n [self.df, pd.DataFrame({key: [event[key]] for key in event.keys()}).set_index(self.timestamp)]\n )\n\n def onServiceStopped(self):\n # Plot the first column of the Dataframe\n plt.figure(figsize=(10, 5))\n plt.xlabel(self.timestamp)\n plt.ylabel(self.df.columns[0])\n plt.plot(self.df.iloc[:, 0])\n plt.show()\nfrom typing import Dict, Any import pandas as pd from datetime import datetime import matplotlib.pyplot as plt from streampipes.functions.function_handler import FunctionHandler from streampipes.functions.registration import Registration from streampipes.functions.streampipes_function import StreamPipesFunction from streampipes.functions.utils.function_context import FunctionContext from streampipes.model.resource.function_definition import FunctionDefinition, FunctionId class ExampleFunction(StreamPipesFunction): def __init__(self, function_definition: FunctionDefinition) -> None: super().__init__(function_definition) # Create the Dataframe to save the live data self.df = pd.DataFrame() def onServiceStarted(self, context: FunctionContext): # Get the name of the timestamp field for event_property in context.schema[context.streams[0]].event_schema.event_properties: if event_property.property_scope == \"HEADER_PROPERTY\": self.timestamp = event_property.runtime_name def onEvent(self, event: Dict[str, Any], streamId: str): # Convert the unix timestamp to datetime event[self.timestamp] = datetime.fromtimestamp(event[self.timestamp] / 1000) # Add every value of the event to the DataFrame self.df = pd.concat( [self.df, pd.DataFrame({key: [event[key]] for key in event.keys()}).set_index(self.timestamp)] ) def onServiceStopped(self): # Plot the first column of the Dataframe plt.figure(figsize=(10, 5)) plt.xlabel(self.timestamp) plt.ylabel(self.df.columns[0]) plt.plot(self.df.iloc[:, 0]) plt.show()
Now we can start the function. First we create an instance of the ExampleFunction
and insert the element_id
of the stream which data we want to consume. Then we have to register this function and we can start all functions by initializing the FunctionHandler
. (it's also possible to register multiple functions with .register(...).register(...)
)
example_function = ExampleFunction(\n FunctionDefinition(\n function_id=FunctionId(id=\"example-function\"),\n consumed_streams=[\"urn:streampipes.apache.org:eventstream:uPDKLI\"]\n )\n)\n\nregistration = Registration()\nregistration.register(example_function)\n\nfunction_handler = FunctionHandler(registration, client)\nfunction_handler.initializeFunctions()\nexample_function = ExampleFunction( FunctionDefinition( function_id=FunctionId(id=\"example-function\"), consumed_streams=[\"urn:streampipes.apache.org:eventstream:uPDKLI\"] ) ) registration = Registration() registration.register(example_function) function_handler = FunctionHandler(registration, client) function_handler.initializeFunctions()
2022-12-14 10:43:42,810 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:153] [_make_request] - Successfully retrieved all resources.\n2022-12-14 10:43:42,812 - streampipes.functions.function_handler - [INFO] - [function_handler.py:82] [initializeFunctions] - Using NatsBroker for <__main__.ExampleFunction object at 0x000001F2EF298D90>\n
The DataFrame
of the ExampleFunction
gets updated whenever a new event arrives. Let's test this by executing the cell below.
import asyncio\nfrom asyncio.exceptions import CancelledError\nfrom IPython.display import clear_output\n\nwhile True:\n clear_output(wait=True)\n display(example_function.df)\n try:\n await asyncio.sleep(1)\n except CancelledError:\n break\nimport asyncio from asyncio.exceptions import CancelledError from IPython.display import clear_output while True: clear_output(wait=True) display(example_function.df) try: await asyncio.sleep(1) except CancelledError: break mass_flow density volume_flow sensor_fault_flags temperature sensorId timestamp 2022-12-14 10:43:43.357 10.955496 47.546290 1.001985 False 44.993413 flowrate02 2022-12-14 10:43:44.371 6.499040 44.392069 2.034402 False 41.232352 flowrate02 2022-12-14 10:43:45.382 10.168300 41.192146 9.724287 False 46.812779 flowrate02 2022-12-14 10:43:46.395 10.849059 50.086308 5.832691 False 45.860412 flowrate02 2022-12-14 10:43:47.410 3.081855 47.254246 8.860531 False 50.505801 flowrate02 ... ... ... ... ... ... ... 2022-12-14 10:44:43.920 1.803572 41.978894 10.294002 False 47.820239 flowrate02 2022-12-14 10:44:44.932 1.967062 42.212883 3.237440 False 49.047258 flowrate02 2022-12-14 10:44:45.934 4.457819 47.561256 0.315024 False 40.223413 flowrate02 2022-12-14 10:44:46.949 8.745343 46.346891 7.439090 False 41.982529 flowrate02 2022-12-14 10:44:47.950 5.828744 47.679720 6.307405 False 42.100354 flowrate02
65 rows \u00d7 6 columns
The while
loop just displays the the DataFrame
every second until the cell is stopped. We could achieve the same result manually by executing example_function.df
repeatedly.
You can stop the functions whenever you want by executing the command below.
In\u00a0[\u00a0]: Copied!function_handler.disconnect()\nfunction_handler.disconnect()
2022-12-14 10:44:53,309 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:67] [disconnect] - Stopped connection to stream: urn:streampipes.apache.org:eventstream:uPDKLI\n
That's enough for this tutorial. Now you can try to write your own StreamPipesFunction
. All you need to do is creating a new class, implementing the 4 required methods and registering the function.
Want to see more exciting use cases you can achieve with StreamPipes functions in Python? Then don't hesitate and jump to our next tutorial on applying online machine learning algorithms to StreamPipes data streams with River.
How do you like this tutorial? We hope you like it and would love to receive some feedback from you. Just go to our GitHub discussion page and let us know your impression. We'll read and react to them all, we promise!
"},{"location":"tutorials/3-getting-live-data-from-the-streampipes-data-stream/#Getting-live-data-from-the-StreamPipes-data-stream","title":"Getting live data from the StreamPipes data stream\u00b6","text":"In the last tutorial (Extracting Data from the StreamPipes data lake) we learned how to extract the stored data from a StreamPipes data lake. This tutorial is about the StreamPipes data stream and shows how to get the live data from StreamPipes into Python. Therefore, we first create the client
instance as before.
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\nfrom streampipes.client import StreamPipesClient from streampipes.client.config import StreamPipesClientConfig from streampipes.client.credential_provider import StreamPipesApiKeyCredentials In\u00a0[\u00a0]: Copied!
# you can install all required dependecies for this tutorial by executing the following command\n%pip install river streampipes\n# you can install all required dependecies for this tutorial by executing the following command %pip install river streampipes In\u00a0[2]: Copied!
import os\n\nos.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\"\nos.environ[\"SP_API_KEY\"] = \"XXX\"\n\n# Use this if you work locally:\nos.environ[\"BROKER-HOST\"] = \"localhost\" \nos.environ[\"KAFKA-PORT\"] = \"9094\" # When using Kafka as message broker\nimport os os.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\" os.environ[\"SP_API_KEY\"] = \"XXX\" # Use this if you work locally: os.environ[\"BROKER-HOST\"] = \"localhost\" os.environ[\"KAFKA-PORT\"] = \"9094\" # When using Kafka as message broker In\u00a0[3]: Copied!
client_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(),\n host_address=\"localhost\",\n port=80,\n https_disabled=True,\n)\nclient = StreamPipesClient(client_config=client_config)\nclient_config = StreamPipesClientConfig( credential_provider=StreamPipesApiKeyCredentials(), host_address=\"localhost\", port=80, https_disabled=True, ) client = StreamPipesClient(client_config=client_config)
2023-01-27 16:04:24,784 - streampipes.client.client - [INFO] - [client.py:128] [_set_up_logging] - Logging successfully initialized with logging level INFO.\nIn\u00a0[4]: Copied!
client.dataStreamApi.all().to_pandas()\nclient.dataStreamApi.all().to_pandas()
2023-01-27 16:04:28,212 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:163] [_make_request] - Successfully retrieved all resources.\nOut[4]: element_id name description icon_url app_id includes_assets includes_locales internally_managed measurement_object index ... dom rev num_transport_protocols num_measurement_capability num_application_links num_included_assets num_connected_to num_category num_event_properties num_included_locales 0 sp:spdatastream:xboBFK Test None None False False True None 0 ... None 5-558c861debc745e1ebae29a266a8bdb9 1 0 0 0 0 0 7 0 1 urn:streampipes.apache.org:eventstream:Wgyrse Test File None None False False True None 0 ... None 4-66548b6b84287011b7cec0876ef82baf 1 0 0 0 0 0 2 0
2 rows \u00d7 22 columns
In\u00a0[5]: Copied!from river import cluster, compose, preprocessing\nfrom streampipes.function_zoo.river_function import OnlineML\nfrom streampipes.functions.utils.data_stream_generator import RuntimeType\n\nk_means = compose.Pipeline(\n (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")),\n (\"scale\", preprocessing.StandardScaler()),\n (\"k_means\", cluster.KMeans(n_clusters=2)),\n)\n\nclustering = OnlineML(\n client=client, stream_ids=[\"sp:spdatastream:xboBFK\"], model=k_means, prediction_type=RuntimeType.INTEGER.value\n)\nclustering.start()\nfrom river import cluster, compose, preprocessing from streampipes.function_zoo.river_function import OnlineML from streampipes.functions.utils.data_stream_generator import RuntimeType k_means = compose.Pipeline( (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")), (\"scale\", preprocessing.StandardScaler()), (\"k_means\", cluster.KMeans(n_clusters=2)), ) clustering = OnlineML( client=client, stream_ids=[\"sp:spdatastream:xboBFK\"], model=k_means, prediction_type=RuntimeType.INTEGER.value ) clustering.start()
2023-01-27 16:04:35,599 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:163] [_make_request] - Successfully retrieved all resources.\n2023-01-27 16:04:35,599 - streampipes.functions.function_handler - [INFO] - [function_handler.py:64] [initializeFunctions] - Create output data stream \"sp:spdatastream:cwKPoo\" for the function \"65cf8b86-bcdf-433e-a1c7-3e920eab55d0\"\n2023-01-27 16:04:37,766 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:163] [_make_request] - Successfully retrieved all resources.\n2023-01-27 16:04:37,767 - streampipes.functions.function_handler - [INFO] - [function_handler.py:78] [initializeFunctions] - Using NatsBroker for RiverFunction\n2023-01-27 16:04:37,791 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:48] [_makeConnection] - Connected to NATS at localhost:4222\n2023-01-27 16:04:37,791 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:48] [_makeConnection] - Connected to NATS at localhost:4222\n2023-01-27 16:04:37,792 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:58] [createSubscription] - Subscribed to stream: sp:spdatastream:xboBFK\nIn\u00a0[6]: Copied!
clustering.set_learning(False)\nclustering.set_learning(False) In\u00a0[\u00a0]: Copied!
clustering.stop()\nclustering.stop()
2023-01-27 16:04:57,303 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:82] [disconnect] - Stopped connection to stream: sp:spdatastream:xboBFK\n2023-01-27 16:04:57,304 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:82] [disconnect] - Stopped connection to stream: sp:spdatastream:cwKPoo\nIn\u00a0[\u00a0]: Copied!
import pickle\nfrom river import compose, tree\nfrom streampipes.function_zoo.river_function import OnlineML\nfrom streampipes.functions.utils.data_stream_generator import RuntimeType\n\nhoeffding_tree = compose.Pipeline(\n (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")),\n (\"hoeffding_tree\", tree.HoeffdingTreeRegressor(grace_period=5)),\n)\n\n\ndef draw_tree(self, event, streamId):\n\"\"\"Draw the tree and save the image.\"\"\"\n if self.learning:\n if self.model[1].n_nodes != None:\n self.model[1].draw().render(\"hoeffding_tree\", format=\"png\", cleanup=True)\n\n\ndef save_model(self):\n\"\"\"Save the trained model.\"\"\"\n with open(\"hoeffding_tree.pkl\", \"wb\") as f:\n pickle.dump(self.model, f)\n\n\nregressor = OnlineML(\n client=client,\n stream_ids=[\"sp:spdatastream:xboBFK\"],\n model=hoeffding_tree,\n prediction_type=RuntimeType.FLOAT.value,\n supervised=True,\n target_label=\"temperature\",\n on_event=draw_tree,\n on_stop=save_model,\n)\nregressor.start()\nimport pickle from river import compose, tree from streampipes.function_zoo.river_function import OnlineML from streampipes.functions.utils.data_stream_generator import RuntimeType hoeffding_tree = compose.Pipeline( (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")), (\"hoeffding_tree\", tree.HoeffdingTreeRegressor(grace_period=5)), ) def draw_tree(self, event, streamId): \"\"\"Draw the tree and save the image.\"\"\" if self.learning: if self.model[1].n_nodes != None: self.model[1].draw().render(\"hoeffding_tree\", format=\"png\", cleanup=True) def save_model(self): \"\"\"Save the trained model.\"\"\" with open(\"hoeffding_tree.pkl\", \"wb\") as f: pickle.dump(self.model, f) regressor = OnlineML( client=client, stream_ids=[\"sp:spdatastream:xboBFK\"], model=hoeffding_tree, prediction_type=RuntimeType.FLOAT.value, supervised=True, target_label=\"temperature\", on_event=draw_tree, on_stop=save_model, ) regressor.start() In\u00a0[9]: Copied!
regressor.set_learning(False)\nregressor.set_learning(False) In\u00a0[\u00a0]: Copied!
regressor.stop()\nregressor.stop() In\u00a0[\u00a0]: Copied!
import pickle\nfrom river import compose, tree\nfrom streampipes.function_zoo.river_function import OnlineML\nfrom streampipes.functions.utils.data_stream_generator import RuntimeType\n\ndecision_tree = compose.Pipeline(\n (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")),\n (\"decision_tree\", tree.ExtremelyFastDecisionTreeClassifier(grace_period=5)),\n)\n\n\ndef draw_tree(self, event, streamId):\n\"\"\"Draw the tree and save the image.\"\"\"\n if self.learning:\n if self.model[1].n_nodes != None:\n self.model[1].draw().render(\"decicion_tree\", format=\"png\", cleanup=True)\n\n\ndef save_model(self):\n\"\"\"Save the trained model.\"\"\"\n with open(\"decision_tree.pkl\", \"wb\") as f:\n pickle.dump(self.model, f)\n\n\nclassifier = OnlineML(\n client=client,\n stream_ids=[\"sp:spdatastream:xboBFK\"],\n model=decision_tree,\n prediction_type=RuntimeType.BOOLEAN.value,\n supervised=True,\n target_label=\"sensor_fault_flags\",\n on_event=draw_tree,\n on_stop=save_model,\n)\nclassifier.start()\nimport pickle from river import compose, tree from streampipes.function_zoo.river_function import OnlineML from streampipes.functions.utils.data_stream_generator import RuntimeType decision_tree = compose.Pipeline( (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")), (\"decision_tree\", tree.ExtremelyFastDecisionTreeClassifier(grace_period=5)), ) def draw_tree(self, event, streamId): \"\"\"Draw the tree and save the image.\"\"\" if self.learning: if self.model[1].n_nodes != None: self.model[1].draw().render(\"decicion_tree\", format=\"png\", cleanup=True) def save_model(self): \"\"\"Save the trained model.\"\"\" with open(\"decision_tree.pkl\", \"wb\") as f: pickle.dump(self.model, f) classifier = OnlineML( client=client, stream_ids=[\"sp:spdatastream:xboBFK\"], model=decision_tree, prediction_type=RuntimeType.BOOLEAN.value, supervised=True, target_label=\"sensor_fault_flags\", on_event=draw_tree, on_stop=save_model, ) classifier.start() In\u00a0[12]: Copied!
classifier.set_learning(False)\nclassifier.set_learning(False) In\u00a0[\u00a0]: Copied!
classifier.stop()\nclassifier.stop()
How do you like this tutorial? We hope you like it and would love to receive some feedback from you. Just go to our GitHub discussion page and let us know your impression. We'll read and react to them all, we promise!
"},{"location":"tutorials/4-using-online-machine-learning-on-a-streampipes-data-stream/#Using-Online-Machine-Learning-on-a-StreamPipes-data-stream","title":"Using Online Machine Learning on a StreamPipes data stream\u00b6","text":"The last tutorial (Getting live data from the StreamPipes data stream) showed how we can connect to a data stream, and it would be possible to use Online Machine Learning with this approach and train a model with the incoming events at the onEvent
method. However, the StreamPipes client also provides an easier way to do this with the use of the River library for Online Machine Learning. We will have a look at this now.
After we configured the client as usual, we can start with the new part. The approach is straight forward and you can start with the ML part in just 3 steps:
OnlineML
wrapper to fit to your model and insert the client and required data stream ids.A StreamPipesFunction is then started, which trains the model for each new event. It also creates an output data stream which will send the prediction of the model back to StreamPipes. This output stream can be seen when creating a new pipeline and can be used like every other data source. So you can use it in a pipeline and save the predictions in a Data Lake. You can also stop and start the training with the method set_learning
. To stop the whole function use the stop
methode and if you want to delete the output stream entirely, you can go to the Pipeline Element Installer
in StreamPipes and uninstall it.
Now let's take a look at some examples. If you want to execute the examples below you have to create an adapter for the Machine Data Simulator
, select the flowrate
sensor and insert the stream id of this stream.
Dependency issue with StreamPipes Python 0.92.0
In StreamPipes Python 0.92.0
there is a problem with the required dependencies. Pydantic has recently released the new version 2.0
with many exciting improvements, but also some breaking changes. Unfortunately, we didn't limit our requirements strictly enough, so yydantic 2.0
is installed together with streampipes, which is not (yet) compatible. To fix this bug, simply run the following command after installing streampipes, or adjust your dependencies accordingly:
pip install \"pydantic<2.0\" \"pydantic_core<2.0\"\n
Apache StreamPipes for Python \ud83d\udc0d Apache StreamPipes meets Python! We are working highly motivated on a Python library to interact with StreamPipes. In this way, we would like to unite the power of StreamPipes to easily connect to and read from different data sources, especially in the IoT domain, and the amazing universe of data analytics libraries in Python.
StreamPipes Python is in beta
The current version of this Python library is still a beta version. This means that it is still heavily under development, which may result in frequent and extensive API changes, unstable behavior, etc.
"},{"location":"#quickstart","title":"\u26a1\ufe0f Quickstart","text":"As a quick example, we demonstrate how to set up and configure a StreamPipes client. In addition, we will get the available data lake measures out of StreamPipes.
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nconfig = StreamPipesClientConfig(\n credential_provider = StreamPipesApiKeyCredentials(\n username = \"test@streampipes.apache.org\",\n api_key = \"DEMO-KEY\",\n ),\n host_address = \"localhost\",\n https_disabled = True,\n port = 80\n)\n\nclient = StreamPipesClient(client_config=config)\n\n# get all available datat lake measures\nmeasures = client.dataLakeMeasureApi.all()\n\n# get amount of retrieved measures\nlen(measures)\n
Output: 1\n
# inspect the data lake measures as pandas dataframe\nmeasures.to_pandas()\n
Output:
measure_name timestamp_field ... pipeline_is_running num_event_properties\n0 test s0::timestamp ... False 2\n[1 rows x 6 columns]\n
Alternatively, you can provide your credentials via environment variables. Simply define your credential provider as follows: from streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nStreamPipesApiKeyCredentials()\n
This requires to set the following environment variables: SP_API_KEY
and SP_USERNAME
username
is always the username that is used to log in into StreamPipes.
The api_key
can be generated within the UI as demonstrated below:
This document describes how to easily set up your local dev environment to work on StreamPipes Python \ud83d\udc0d.
"},{"location":"getting-started/developing/#first-steps","title":"\ud83d\ude80 First Steps","text":"1) Set up your Python environment
Create a virtual Python environment using a tool of your choice. To manage dependencies, we use Poetry, so please install poetry in your local environment, e.g. via
pip install poetry\n
Once poetry is installed you can simply finalize your Python environment by running:
poetry install --with dev,stubs # install everything that is required for the development\npoetry install --with docs # install everything to work with the documentation\npoetry install --with dev,stubs,docs # install all optional dependencies related to development\n
2) Install pre-commit hook
The pre-commit hook is run before every commit and takes care about code style, linting, type hints, import sorting, etc. It will stop your commit in case the changes do not apply the expected format. Always check to have the recent version of the pre-commit hook installed otherwise the CI build might fail. If you are interested, you can have a deeper look on the underlying library: pre-commit.
pre-commit install\n
The definition of the pre-commit hook can be found in .pre-commit-config.yaml. "},{"location":"getting-started/developing/#conventions","title":"\ud83d\udc4f Conventions","text":"Below we list some conventions that we have agreed on for creating StreamPipes Python. Please comply to them when you plan to contribute to this project. If you have any other suggestions or would like to discuss them, we would be happy to hear from you on our mailing list dev@streampipes.apache.org or in our discussions on GitHub.
1) Use numpy
style for Python docstrings \ud83d\udcc4 Please stick to the numpy
style when writing docstrings, as we require this for generating our documentation.
2) Provide tests \u2705 We are aiming for broad test coverage for the Python package and have therefore set a requirement of at least 90% unit test coverage. Therefore, please remember to write (unit) tests already during development. If you have problems with writing tests, don't hesitate to ask us for help directly in the PR or even before that via our mailing list (see above).
3) Build a similar API as the Java client provides \ud83d\udd04 Whenever possible, please try to develop the API of the Python library the same as the Java client or Java SDK. By doing so, we would like to provide a consistent developer experience and the basis for automated testing in the future.
"},{"location":"getting-started/developing/#dependency-management","title":"\ud83d\udce6 Dependency Management","text":"In case you want to add a new dependency to StreamPipes you can use the following command:
poetry add <dep-name>\n
If the dependency is only required for development purpose or the documentation, please stick to one the following:
poetry add <dep-name> --group dev\npoetry add <dep-name> --group stubs\npoetry add <dep-name> --group docs\n
In case you want to regenerate the poetry lock file, e.g., in case you manually updated the pyproject.toml
, the following command should be used:
poetry lock --no-update\n
After that, you should install the current version of the poetry lock file to keep your local environment consistent (see command above.)
"},{"location":"getting-started/developing/#documentation","title":"\ud83d\udcdaDocumentation","text":"To build our documentation, we use Materials for MkDocs. All files can be found within the docs
directory. To pre-view your local version of the documentation, you can use the following command:
make livedoc\n
"},{"location":"getting-started/developing/#roadmap","title":"\ud83d\ude80 Roadmap","text":"Broadly speaking, we plan to expand or add new aspects/functionality to the library where we are focusing on the following:
In case you want to have a more detailed look on what we are currently planning, have a look at our open issues(more short-term driven).
Of course, contributions are always highly appreciated \ud83d\udd2e
Stay tuned!
"},{"location":"getting-started/developing/#contributing","title":"\ud83d\udc68\u200d\ud83d\udcbb Contributing","text":"Before opening a pull request, review the Get Involved page. It lists information that is required for contributing to StreamPipes.
When you contribute code, you affirm that the contribution is your original work and that you license the work to the project under the project's open source license. Whether or not you state this explicitly, by submitting any copyrighted material via pull request, email, or other means you agree to license the material under the project's open source license and warrant that you have the legal authority to do so.
"},{"location":"getting-started/first-steps/","title":"First Steps","text":""},{"location":"getting-started/first-steps/#installation","title":"\ud83d\udcda Installation","text":"The StreamPipes Python library is meant to work with Python 3.8 and above. Installation can be done via pip
: You can install the latest development version from GitHub, as so:
pip install streampipes\n\n# if you want to have the current development state you can also execute\npip install git+https://github.com/apache/streampipes.git#subdirectory=streampipes-client-python\n# the corresponding documentation can be found here: https://streampipes.apache.org/docs/docs/python/dev/\n
"},{"location":"getting-started/first-steps/#setting-up-streampipes","title":"\u2b06\ufe0f Setting up StreamPipes","text":"When working with the StreamPipes Python library it is inevitable to have a running StreamPipes instance to connect and interact with. In case you don't have a running instance at hand, you can easily set up one on your local machine. Hereby you need to consider that StreamPipes supports different message broker (e.g., Kafka, NATS). We will demonstrate below how you can easily set up StreamPipes for both supported message brokers.
"},{"location":"getting-started/first-steps/#start-streampipes-via-docker-compose","title":"\ud83d\udc33 Start StreamPipes via Docker Compose","text":"The easiest and therefore recommend way to get StreamPipes started is by using docker compose. Therefore, you need Docker running. You can check if Docker is ready on your machine by executing.
docker ps\n
If this results in an output similar to the following, Docker is ready to continue. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES\n... ... ... ... ... ... ...\n
Otherwise, you need to start docker first. Please read the full guide on how to start StreamPipes with docker compose
here."},{"location":"getting-started/first-steps/#setup-streampipes-with-nats-as-message-broker","title":"Setup StreamPipes with NATS as message broker","text":"The following shows how you can set up a StreamPipes instance that uses NATS as messaging layer. So in this scenario, we will go with docker-compose.nats.yml
. Thereby, when running locally, we need to add the following port mapping entry to services.nats.ports
:
- 4222:4222\n
After this modification is applied, StreamPipes can simply be started with this command:
docker-compose -f docker-compose.nats.yml up -d\n
Once all services are started, you can access StreamPipes via http://localhost
.
Alternatively, you can use docker-compose.yml
to start StreamPipes with Kafka as messaging layer. When running locally we have to modify services.kafka.environment
and add the ports to services.kafka.ports
:
environment:\nKAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,OUTSIDE:PLAINTEXT\nKAFKA_ADVERTISED_LISTENERS: PLAINTEXT://:9092,OUTSIDE://localhost:9094\nKAFKA_LISTENERS: PLAINTEXT://:9092,OUTSIDE://:9094\n...\nports:\n- 9094:9094\n
Then, you need to execute the following command: docker-compose -f docker-compose.yml up -d\n
Once all services are started, you can access StreamPipes via http://localhost
.
In case you want to have more control over your StreamPipes setup, you might take a look at our deployment CLI.
Have fun discovering StreamPipes and our Python library \ud83d\ude80
"},{"location":"getting-started/quickstart/","title":"Quickstart","text":""},{"location":"getting-started/quickstart/#quickstart","title":"\u26a1\ufe0f Quickstart","text":"As a quick example, we demonstrate how to set up and configure a StreamPipes client. In addition, we will get the available data lake measures out of StreamPipes.
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nconfig = StreamPipesClientConfig(\n credential_provider = StreamPipesApiKeyCredentials(\n username = \"test@streampipes.apache.org\",\n api_key = \"DEMO-KEY\",\n ),\n host_address = \"localhost\",\n https_disabled = True,\n port = 80\n)\n\nclient = StreamPipesClient(client_config=config)\n\n# get all available datat lake measures\nmeasures = client.dataLakeMeasureApi.all()\n\n# get amount of retrieved measures\nlen(measures)\n
Output: 1\n
# inspect the data lake measures as pandas dataframe\nmeasures.to_pandas()\n
Output:
measure_name timestamp_field ... pipeline_is_running num_event_properties\n0 test s0::timestamp ... False 2\n[1 rows x 6 columns]\n
Alternatively, you can provide your credentials via environment variables. Simply define your credential provider as follows: from streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nStreamPipesApiKeyCredentials()\n
This requires to set the following environment variables: SP_API_KEY
and SP_USERNAME
username
is always the username that is used to log in into StreamPipes. The api_key
can be generated within the UI as demonstrated below:
Implementation of the StreamPipes client. The client is designed as the central point of interaction with the StreamPipes API and provides all functionalities to communicate with the API.
"},{"location":"reference/client/client/#streampipes.client.client.StreamPipesClient","title":"StreamPipesClient(client_config, logging_level=logging.INFO)
","text":"The client to connect to StreamPipes.
This is the central point of contact with StreamPipes and provides all the functionalities to interact with it.
The client provides so-called \"endpoints\" each of which refers to an endpoint of the StreamPipes API, e.g. .dataLakeMeasureApi
. An endpoint provides the actual methods to interact with StreamPipes API.
client_config
Configures the client to connect properly to the StreamPipes instance.
TYPE: StreamPipesClientConfig
logging_level
Influences the log messages emitted by the StreamPipesClient
TYPE: Optional[int]
DEFAULT: logging.INFO
dataLakeMeasureApi
Instance of the data lake measure endpoint
TYPE: DataLakeMeasureEndpoint
dataStreamApi
Instance of the data stream endpoint
TYPE: DataStreamEndpoint
Examples:
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
client_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(\n username=\"test-user\",\n api_key=\"api-key\"\n ),\n host_address=\"localhost\",\n https_disabled=True\n)\n
The following way of instantiating a client instance is intended to be consistent with the StreamPipes Java client.
client = StreamPipesClient.create(client_config=client_config)\n
If you prefer a more pythonic way, you can simply write:
client = StreamPipesClient(client_config=client_config)\n
To interact with an endpoint:
data_lake_measures = client.dataLakeMeasureApi.all()\n
To inspect returned data as a pandas dataframe:
data_lake_measures.to_pandas()\n#\n# measure_name timestamp_field ... pipeline_is_running num_event_properties\n# 0 test s0::timestamp ... False 2\n# [1 rows x 6 columns]\n
"},{"location":"reference/client/client/#streampipes.client.client.StreamPipesClient.base_api_path","title":"base_api_path: str
property
","text":"Constructs the basic API URL from the given client_config
.
base_api_path
basic API path of the connected StreamPipes instance
TYPE: str
http_headers: Dict[str, str]
property
","text":"Returns the HTTP headers used for all requests.
The HTTP headers are composed of the authentication headers supplied by the credential provider and additional required headers (currently this is only the application header).
RETURNS DESCRIPTIONhttp_headers
header information for HTTP requests as string key-value pairs.
TYPE: Dict[str, str]
create(client_config, logging_level=logging.INFO)
classmethod
","text":"Returns an instance of the StreamPipesPythonClient
.
Provides consistency to the StreamPipes Java client.
PARAMETER DESCRIPTIONclient_config
Configures the client to connect properly to the StreamPipes instance.
TYPE: StreamPipesClientConfig
logging_level
Influences the log messages emitted by the StreamPipesClient
.
TYPE: int
DEFAULT: logging.INFO
StreamPipesClient
"},{"location":"reference/client/client/#streampipes.client.client.StreamPipesClient.describe","title":"describe()
","text":"Prints a short description of the connected StreamPipes instance and the available resources to the console.
RETURNS DESCRIPTION None
Examples:
client.describe()\n
Output: Hi there!\nYou are connected to a StreamPipes instance running at http://localhost:80.\nThe following StreamPipes resources are available with this client:\n6x DataStreams\n1x DataLakeMeasures\n
"},{"location":"reference/client/config/","title":"Config","text":"Configuration class for the StreamPipes client.
"},{"location":"reference/client/config/#streampipes.client.config.StreamPipesClientConfig","title":"StreamPipesClientConfig
dataclass
","text":"Configure the StreamPipes client in accordance to the actual StreamPipes instance to connect to.
An instance is provided to the StreamPipesClient
to configure it properly.
credential_provider
Provides the credentials to authenticate with the StreamPipes API.
TYPE: CredentialProvider
host_address
Host address of the StreamPipes instance to connect to. Should be provided without the protocol/scheme, e.g. as localhost
or streampipes.xyz
.
TYPE: str
https_disabled
Determines whether https is used to connect to StreamPipes.
TYPE: Optional[bool]
DEFAULT: False
port
Specifies the port under which the StreamPipes API is available, e.g., 80
(with http) or 443
(with https)
TYPE: Optional[int]
DEFAULT: 80
Examples:
see StreamPipesClient
"},{"location":"reference/client/credential_provider/","title":"Credential provider","text":"Implementation of credential providers. A credential provider supplies the specified sort of credentials in the appropriate HTTP header format. The headers are then used by the client to connect to StreamPipes.
"},{"location":"reference/client/credential_provider/#streampipes.client.credential_provider.CredentialProvider","title":"CredentialProvider
","text":" Bases: ABC
Abstract implementation of a credential provider. Must be inherited by all credential providers.
"},{"location":"reference/client/credential_provider/#streampipes.client.credential_provider.CredentialProvider.make_headers","title":"make_headers(http_headers=None)
","text":"Creates the HTTP headers for the specific credential provider.
Concrete authentication headers must be defined in the implementation of a credential provider.
PARAMETER DESCRIPTIONhttp_headers
Additional HTTP headers the generated headers are extended by.
TYPE: Optional[Dict[str, str]]
DEFAULT: None
https_headers
Dictionary with header information as string key-value pairs. Contains all pairs given as parameter plus the header pairs for authentication determined by the credential provider.
TYPE: Dict[str, str]
StreamPipesApiKeyCredentials(username=None, api_key=None)
","text":" Bases: CredentialProvider
A credential provider that allows authentication via a StreamPipes API Token.
The required token can be generated via the StreamPipes UI (see the description on our start-page.
Both parameters can either be passed as arguments or remain unset. If they are not passed, they are retrieved from environment variables:
SP_USERNAME
is expected to contain the usernameSP_API_KEY
is expected to contain the API keyusername
The username to which the API token is granted, e.g., demo-user@streampipes.apche.org
. If not passed, the username is retrieved from environment variable SP_USERNAME
.
TYPE: Optional[str]
DEFAULT: None
api_key
The StreamPipes API key as it is displayed in the UI. If not passed, the api key is retrieved from environment variable SP_API_KEY
TYPE: Optional[str]
DEFAULT: None
Examples:
see StreamPipesClient
"},{"location":"reference/client/credential_provider/#streampipes.client.credential_provider.StreamPipesApiKeyCredentials.from_env","title":"from_env(username_env, api_key_env)
classmethod
","text":"DEPRECATED - use the class constructor instead
Returns an api key provider parameterized via environment variables.
PARAMETER DESCRIPTIONusername_env
Name of the environment variable that contains the username
TYPE: str
api_key_env
Name of the environment variable that contains the API key
TYPE: str
StreamPipesApiKeyCredentials
RAISES DESCRIPTION KeyError
If one of the environment variables is not defined
"},{"location":"reference/endpoint/endpoint/","title":"Endpoint","text":"General implementation for an endpoint. Provided classes and assets are aimed to be used for developing endpoints. An endpoint provides all options to communicate with ad dedicated part of StreamPipes in a handy way.
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.APIEndpoint","title":"APIEndpoint
","text":" Bases: Endpoint
Abstract implementation of an API endpoint.
Serves as template for all endpoints of the StreamPipes API. By design, endpoints are only instantiated within the __init__
method of the StreamPipesClient.
all()
","text":"Get all resources of this endpoint provided by the StreamPipes API.
Results are provided as an instance of a ResourceContainer
that allows to handle the returned resources in a comfortable and pythonic way.
container
container element that bundles the returned resources
TYPE: ResourceContainer
build_url()
","text":"Builds the endpoint's URL of the API path.
RETURNS DESCRIPTIONurl
The URL of the endpoint
TYPE: str
get(identifier, **kwargs)
","text":"Queries the specified resource from the API endpoint.
PARAMETER DESCRIPTIONidentifier
The identifier of the resource to be queried.
TYPE: str
resource
The specified resource as an instance of the corresponding model class.
TYPE: Resource
post(resource)
","text":"Allows to post a resource to the StreamPipes API.
PARAMETER DESCRIPTIONresource
The resource to be posted.
TYPE: Resource
None
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.Endpoint","title":"Endpoint(parent_client)
","text":" Bases: ABC
Abstract implementation of a StreamPipes endpoint.
Serves as template for all endpoints used for interaction with a StreamPipes instance. By design, endpoints are only instantiated within the __init__
method of the StreamPipesClient.
parent_client
This parameter expects the instance of StreamPipesClient
the endpoint is attached to.
TYPE: StreamPipesClient
MessagingEndpoint(parent_client)
","text":" Bases: Endpoint
Abstract implementation of a StreamPipes messaging endpoint.
Serves as template for all endpoints used for interacting with the StreamPipes messaging layer directly. Therefore, they need to provide the functionality to talk with the broker system running in StreamPipes. By design, endpoints are only instantiated within the __init__
method of the StreamPipesClient.
broker: Broker
property
writable
","text":"Defines the broker instance that is used to connect to StreamPipes' messaging layer.
This instance enables the client to authenticate to the broker used in the target StreamPipes instance, to consume messages from and to write messages to the broker.
RAISES DESCRIPTIONMessagingEndpointNotConfiguredError
If the endpoint is used before the broker instance is set via configure()
broker
The broker instance to be used to communicate with StreamPipes' messaging layer.
TYPE: Broker
configure(broker)
","text":"Configures the message endpoint by setting the broker instance to be used.
This configuration step is required before the endpoint can be actually used. The based broker
instance is passed to an internal property
broker
Broker instance that should be used for this endpoint
TYPE: Broker
None
"},{"location":"reference/endpoint/exceptions/","title":"Exceptions","text":"Custom exceptions dedicated for the endpoints module
"},{"location":"reference/endpoint/exceptions/#streampipes.endpoint.exceptions.MessagingEndpointNotConfiguredError","title":"MessagingEndpointNotConfiguredError(endpoint_name)
","text":" Bases: Exception
Exception that indicates that an instance of a messaging endpoint has not been configured.
This error occurs when an instance of a messaging endpoint is used before the broker instance to be used is configured by passing it to the configure()
method.
endpoint_name
The name of the endpoint that caused the error
TYPE: str
Specific implementation of the StreamPipes API's data lake measure endpoints. This endpoint allows to consume data stored in StreamPipes' data lake.
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.DataLakeMeasureEndpoint","title":"DataLakeMeasureEndpoint
","text":" Bases: APIEndpoint
Implementation of the DataLakeMeasure endpoint.
This endpoint provides an interface to all data stored in the StreamPipes data lake.
Consequently, it allows querying metadata about available data sets (see all()
method). The metadata is returned as an instance of DataLakeMeasures
.
In addition, the endpoint provides direct access to the data stored in the data laka by querying a specific data lake measure using the get()
method.
Examples:
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
client_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(username=\"test-user\", api_key=\"api-key\"),\n host_address=\"localhost\",\n port=8082,\n https_disabled=True\n)\nclient = StreamPipesClient.create(client_config=client_config)\n
# get all existing data lake measures from StreamPipes\ndata_lake_measures = client.dataLakeMeasureApi.all()\n\n# let's take a look how many we got\nlen(data_lake_measures)\n
5\n
# Retrieve a specific data lake measure as a pandas DataFrame\nflow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\").to_pandas()\nflow_rate_pd\n
time density mass_flow sensorId sensor_fault_flags temperature volume_flow\n0 2023-02-24T16:19:41.472Z 50.872730 3.309556 flowrate02 False 44.448483 5.793138\n1 2023-02-24T16:19:41.482Z 47.186588 5.608580 flowrate02 False 40.322033 0.058015\n2 2023-02-24T16:19:41.493Z 46.735321 7.692881 flowrate02 False 49.239639 10.283526\n3 2023-02-24T16:19:41.503Z 40.169796 3.632898 flowrate02 False 49.933754 6.893441\n4 2023-02-24T16:19:41.513Z 49.635124 0.711260 flowrate02 False 50.106617 2.999871\n.. ... ... ... ... ... ... ...\n995 2023-02-24T16:19:52.927Z 50.057495 1.740114 flowrate02 False 46.558231 1.818237\n996 2023-02-24T16:19:52.94Z 41.038895 7.211723 flowrate02 False 48.048622 2.127493\n997 2023-02-24T16:19:52.952Z 45.837013 7.770180 flowrate02 False 48.188026 7.892062\n998 2023-02-24T16:19:52.965Z 43.389065 4.458602 flowrate02 False 48.280899 5.733892\n999 2023-02-24T16:19:52.977Z 44.056030 2.592060 flowrate02 False 47.505951 4.260697\n
As you can see, the returned amount of rows per default is 1000
. We can modify this behavior by passing the limit
paramter.
flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", limit=10).to_pandas()\nlen(flow_rate_pd)\n
10\n
If we are only interested in the values for density
, columns
allows us to select the columns to be returned:
flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", columns='density', limit=3).to_pandas()\nflow_rate_pd\n
time density\n0 2023-02-24T16:19:41.472Z 50.872730\n1 2023-02-24T16:19:41.482Z 47.186588\n2 2023-02-24T16:19:41.493Z 46.735321\n
This is only a subset of the available query parameters, find them at MeasurementGetQueryConfig.
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.DataLakeMeasureEndpoint.get","title":"get(identifier, **kwargs)
","text":"Queries the specified data lake measure from the API.
By default, the maximum number of returned records is 1000. This behaviour can be influenced by passing the parameter limit
with a different value (see MeasurementGetQueryConfig).
identifier
The identifier of the data lake measure to be queried.
TYPE: str
**kwargs
keyword arguments can be used to provide additional query parameters. The available query parameters are defined by the MeasurementGetQueryConfig.
TYPE: Optional[Dict[str, Any]]
DEFAULT: {}
measurement
the specified data lake measure
TYPE: DataLakeMeasures
Examples:
see directly at DataLakeMeasureEndpoint.
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.MeasurementGetQueryConfig","title":"MeasurementGetQueryConfig
","text":" Bases: BaseModel
Config class describing the parameters of the get()
method for measurements.
This config class is used to validate the provided query parameters for the GET endpoint of measurements. Additionally, it takes care of the conversion to a proper HTTP query string. Thereby, parameter names are adapted to the naming of the StreamPipes API, for which Pydantic aliases are used.
ATTRIBUTE DESCRIPTIONcolumns
A comma separated list of column names (e.g., time,value
) If provided, the returned data only consists of the given columns. Please be aware that the column time
as an index is always included.
TYPE: Optional[List[str]]
end_date
Restricts queried data to be younger than the specified time.
TYPE: Optional[datetime]
limit
Amount of records returned at maximum (default: 1000
) This needs to be at least 1
TYPE: Optional[int]
offset
Offset to be applied to returned data This needs to be at least 0
TYPE: Optional[int]
order
Ordering of query results Allowed values: ASC
and DESC
(default: ASC
)
TYPE: Optional[str]
page_no
Page number used for paging operation This needs to be at least 1
TYPE: Optional[int]
start_date
Restricts queried data to be older than the specified time
TYPE: Optional[datetime]
Config
","text":"Pydantic Config class
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.MeasurementGetQueryConfig.build_query_string","title":"build_query_string()
","text":"Builds a HTTP query string for the config.
This method returns an HTTP query string for the invoking config. It follows the following structure ?param1=value1¶m2=value2...
. This query string is not an entire URL, instead it needs to appended to an API path.
query_param_string
HTTP query params string (?param1=value1¶m2=value2...
)
TYPE: str
StreamPipesQueryValidationError
","text":" Bases: Exception
A custom exception to be raised when the validation of query parameter causes an error.
"},{"location":"reference/endpoint/api/data_stream/","title":"Data stream","text":"Specific implementation of the StreamPipes API's data stream endpoints.
"},{"location":"reference/endpoint/api/data_stream/#streampipes.endpoint.api.data_stream.DataStreamEndpoint","title":"DataStreamEndpoint
","text":" Bases: APIEndpoint
Implementation of the DataStream endpoint.
Consequently, it allows querying metadata about available data streams (see all()
method). The metadata is returned as an instance of DataStreams
.
Examples:
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nclient_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(username=\"test-user\", api_key=\"api-key\"),\n host_address=\"localhost\",\n port=8082,\n https_disabled=True\n)\nclient = StreamPipesClient.create(client_config=client_config)\n
# let's get all existing data streams in StreamPipes\ndata_streams = client.dataStreamApi.all()\nlen(data_streams)\n
2\n
"},{"location":"reference/endpoint/api/version/","title":"Version","text":"Specific implementation of the StreamPipes API's version endpoint.
"},{"location":"reference/endpoint/api/version/#streampipes.endpoint.api.version.VersionEndpoint","title":"VersionEndpoint
","text":" Bases: APIEndpoint
Implementation of the Versions endpoint.
This endpoint provides metadata about the StreamPipes version of the connected instance. It only allows to apply the get()
method with an empty string as identifier.
parent_client
The instance of StreamPipesClient the endpoint is attached to.
Examples:
>>> from streampipes.client import StreamPipesClient\n>>> from streampipes.client.config import StreamPipesClientConfig\n>>> from streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
>>> client_config = StreamPipesClientConfig(\n... credential_provider=StreamPipesApiKeyCredentials(username=\"test-user\", api_key=\"api-key\"),\n... host_address=\"localhost\",\n... port=8082,\n... https_disabled=True\n... )\n
>>> client = StreamPipesClient.create(client_config=client_config)\n
>>> client.versionApi.get(identifier=\"\").to_dict(use_source_names=False)\n{'backend_version': '0.92.0-SNAPSHOT'}\n
"},{"location":"reference/endpoint/api/version/#streampipes.endpoint.api.version.VersionEndpoint.all","title":"all()
","text":"Usually, this method returns information about all resources provided by this endpoint. However, this endpoint does not support this kind of operation.
RAISES DESCRIPTIONNotImplementedError
this endpoint does not return multiple entries, therefore this method is not available
"},{"location":"reference/endpoint/api/version/#streampipes.endpoint.api.version.VersionEndpoint.get","title":"get(identifier, **kwargs)
","text":"Queries the resource from the API endpoint.
For this endpoint only one resource is available.
PARAMETER DESCRIPTIONidentifier
Not supported by this endpoint, is set to an empty string.
TYPE: str
versions
The specified resource as an instance of the corresponding model class(Version). # noqa: 501
TYPE: Version
post(resource)
","text":"Usually, this method allows to create via this endpoint. Since the data represented by this endpoint is immutable, it does not support this kind of operation.
RAISES DESCRIPTIONNotImplementedError
this endpoint does not allow for POST requests, therefore this method is not available
"},{"location":"reference/function_zoo/river_function/","title":"River function","text":""},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.OnlineML","title":"OnlineML(client, stream_ids, model, prediction_type=RuntimeType.STRING.value, supervised=False, target_label=None, on_start=lambda self, context: None, on_event=lambda self, event, streamId: None, on_stop=lambda self: None)
","text":"Wrapper class to enable an easy usage for Online Machine Learning models of the River library.
It creates a StreamPipesFunction to train a model with the incoming events of a data stream and creates an output data stream that publishes the prediction to StreamPipes.
PARAMETER DESCRIPTIONclient
The client for the StreamPipes API.
TYPE: StreamPipesClient
stream_ids
The ids of the data stream to train the model.
TYPE: List[str]
model
The model to train. It meant to be a River model/pipeline, but can be every model with a 'learn_one' and 'predict_one' methode.
TYPE: Any
prediction_type
The data type of the prediction. Is only needed when you continue to work with the prediction in StreamPipes.
TYPE: str
DEFAULT: RuntimeType.STRING.value
supervised
Define if the model is supervised or unsupervised.
TYPE: bool
DEFAULT: False
target_label
Define the name of the target attribute if the model is supervised.
TYPE: Optional[str]
DEFAULT: None
on_start
A function to be called when this StreamPipesFunction gets started.
TYPE: Callable[[Any, FunctionContext], None]
DEFAULT: lambda self, context: None
on_event
A function to be called when this StreamPipesFunction receives an event.
TYPE: Callable[[Any, Dict[str, Any], str], None]
DEFAULT: lambda self, event, streamId: None
on_stop
A function to be called when this StreamPipesFunction gets stopped.
TYPE: Callable[[Any], None]
DEFAULT: lambda self: None
set_learning(learning)
","text":"Start or stop the training of the model.
PARAMETER DESCRIPTIONlearning
Defines if the training should be continued
TYPE: bool
start()
","text":"Registers the function and starts the training.
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.OnlineML.stop","title":"stop()
","text":"Stops the function and ends the training forever.
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.RiverFunction","title":"RiverFunction(function_definition, model, supervised, target_label, on_start, on_event, on_stop)
","text":" Bases: StreamPipesFunction
Implementation of a StreamPipesFunction to enable an easy usage for Online Machine Learning models of the River library.
The function trains the model with the incoming events and publishes the prediction to an output data stream.
PARAMETER DESCRIPTIONfunction_definition
The function definition which contains the output stream.
TYPE: FunctionDefinition
model
The model to train. It meant to be a River model/pipeline, but can be every model with a 'learn_one' and 'predict_one' method.
TYPE: Any
supervised
Define if the model is supervised or unsupervised.
TYPE: bool
target_label
Define the name of the target attribute if the model is supervised.
TYPE: Optional[str]
on_start
A function to be called when this StreamPipesFunction gets started.
TYPE: Callable[[Any, FunctionContext], None]
on_event
A function to be called when this StreamPipesFunction receives an event.
TYPE: Callable[[Any, Dict[str, Any], str], None]
on_stop
A function to be called when this StreamPipesFunction gets stopped.
TYPE: Callable[[Any], None]
onEvent(event, streamId)
","text":"Trains the model with the incoming events and sends the prediction back to StreamPipes.
PARAMETER DESCRIPTIONevent
The incoming event that serves as input for the function
TYPE: Dict[str, Any]
streamId
Identifier of the corresponding data stream
TYPE: str
None
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.RiverFunction.onServiceStarted","title":"onServiceStarted(context)
","text":"Executes the on_start
method of the function.
context
The functions' context
TYPE: FunctionContext
None
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.RiverFunction.onServiceStopped","title":"onServiceStopped()
","text":"Executes the on_stop
function.
FunctionHandler(registration, client)
","text":"The function handler manages the StreamPipes Functions.
It controls the connection to the brokers, starts the functions, manages the broadcast of the live data and is able to stop the connection to the brokers and functions.
PARAMETER DESCRIPTIONregistration
The registration, that contains the StreamPipesFunctions.
TYPE: Registration
client
The client to interact with the API.
TYPE: StreamPipesClient
stream_contexts
Map of all data stream contexts
TYPE: Dict[str, DataStreamContext]
brokers
List of all registered brokers
TYPE: List[Broker]
disconnect()
","text":"Disconnects from the brokers and stops all functions.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/function_handler/#streampipes.functions.function_handler.FunctionHandler.force_stop_functions","title":"force_stop_functions()
","text":"Stops the StreamPipesFunctions when the event loop was stopped without stopping the functions.
RETURNS DESCRIPTIONNone
WARNS DESCRIPTION UserWarning
If there is a running event loop and the functions should be stopped by disconnecting from the broker.
"},{"location":"reference/functions/function_handler/#streampipes.functions.function_handler.FunctionHandler.initializeFunctions","title":"initializeFunctions()
","text":"Creates the context for every data stream and starts the event loop to manage the StreamPipes Functions.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/registration/","title":"Registration","text":""},{"location":"reference/functions/registration/#streampipes.functions.registration.Registration","title":"Registration()
","text":"Manages the existing StreamPipesFunctions and registers them.
ATTRIBUTE DESCRIPTIONfunctions
List of all registered StreamPipesFunction
TYPE: List[StreamPipesFunction]
getFunctions()
","text":"Get all registered functions.
This method exists to be consistent with the Java client.
RETURNS DESCRIPTIONfunctions
List of all registered functions.
TYPE: List[StreamPipesFunction]
register(streampipes_function)
","text":"Registers a new function.
PARAMETER DESCRIPTIONstreampipes_function
The function to register.
TYPE: StreamPipesFunction
self
The updated Registration instance
TYPE: Registration
StreamPipesFunction(function_definition=None)
","text":" Bases: ABC
Abstract implementation of a StreamPipesFunction.
A StreamPipesFunction allows users to get the data of a StreamPipes data streams easily. It makes it possible to work with the live data in python and enables to use the powerful data analytics libraries there.
PARAMETER DESCRIPTIONfunction_definition
the definition of the function that contains metadata about the connected function
TYPE: Optional[FunctionDefinition]
DEFAULT: None
output_collectors
List of all output collectors which are created based on the provided function definitions.
TYPE: Dict[str, OutputCollector]
add_output(stream_id, event)
","text":"Send an event via an output data stream to StreamPipes
PARAMETER DESCRIPTIONstream_id
The id of the output data stream
TYPE: str
event
The event which should be sent
TYPE: Dict[str, Any]
None
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.getFunctionId","title":"getFunctionId()
","text":"Returns the id of the function.
RETURNS DESCRIPTIONfunction_id
Identification object of the StreamPipes function
TYPE: FunctionId
onEvent(event, streamId)
abstractmethod
","text":"Is called for every event of a data stream.
PARAMETER DESCRIPTIONevent
The received event from the data stream.
TYPE: Dict[str, Any]
streamId
The id of the data stream which the event belongs to.
TYPE: str
None
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.onServiceStarted","title":"onServiceStarted(context)
abstractmethod
","text":"Is called when the function gets started.
PARAMETER DESCRIPTIONcontext
The context in which the function gets started.
TYPE: FunctionContext
None
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.onServiceStopped","title":"onServiceStopped()
abstractmethod
","text":"Is called when the function gets stopped.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.requiredStreamIds","title":"requiredStreamIds()
","text":"Get the ids of the streams needed by the function.
RETURNS DESCRIPTIONstream_ids
List of the stream ids
TYPE: List[str]
stop()
","text":"Stops the function and disconnects from the output streams
"},{"location":"reference/functions/broker/broker/","title":"Broker","text":""},{"location":"reference/functions/broker/broker/#streampipes.functions.broker.broker.Broker","title":"Broker
","text":" Bases: ABC
Abstract implementation of a broker for consumer and publisher.
It contains the basic logic to connect to a data stream.
"},{"location":"reference/functions/broker/broker/#streampipes.functions.broker.broker.Broker.connect","title":"connect(data_stream)
async
","text":"Connects to the broker running in StreamPipes.
PARAMETER DESCRIPTIONdata_stream
Contains the meta information (resources) for a data stream.
TYPE: DataStream
None
"},{"location":"reference/functions/broker/broker/#streampipes.functions.broker.broker.Broker.disconnect","title":"disconnect()
abstractmethod
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/broker/broker_handler/","title":"Broker handler","text":""},{"location":"reference/functions/broker/broker_handler/#streampipes.functions.broker.broker_handler.SupportedBroker","title":"SupportedBroker
","text":" Bases: Enum
Enum for the supported brokers.
"},{"location":"reference/functions/broker/broker_handler/#streampipes.functions.broker.broker_handler.UnsupportedBrokerError","title":"UnsupportedBrokerError(broker_name)
","text":" Bases: Exception
Exception if a broker isn't implemented yet.
"},{"location":"reference/functions/broker/broker_handler/#streampipes.functions.broker.broker_handler.get_broker","title":"get_broker(data_stream, is_publisher=False)
","text":"Derive the broker for the given data stream.
PARAMETER DESCRIPTIONdata_stream
Data stream instance from which the broker is inferred
TYPE: DataStream
broker
The corresponding broker instance derived from data stream.
TYPE: Broker
UnsupportedBrokerError
Is raised when the given data stream belongs to a broker that is currently not supported by StreamPipes Python.
"},{"location":"reference/functions/broker/broker_handler/#streampipes.functions.broker.broker_handler.get_broker_description","title":"get_broker_description(data_stream)
","text":"Derive the decription of the broker for the given data stream.
PARAMETER DESCRIPTIONdata_stream
Data stream instance from which the broker is inferred
TYPE: DataStream
broker
The corresponding broker description derived from data stream.
TYPE: SupportedBroker
UnsupportedBrokerError
Is raised when the given data stream belongs to a broker that is currently not supported by StreamPipes Python.
"},{"location":"reference/functions/broker/consumer/","title":"Consumer","text":""},{"location":"reference/functions/broker/consumer/#streampipes.functions.broker.consumer.Consumer","title":"Consumer
","text":" Bases: Broker
Abstract implementation a consumer for a broker.
A consumer allows to subscribe to a data stream.
"},{"location":"reference/functions/broker/consumer/#streampipes.functions.broker.consumer.Consumer.connect","title":"connect(data_stream)
async
","text":"Connects to the broker running in StreamPipes and creates a subscription.
PARAMETER DESCRIPTIONdata_stream
Contains the meta information (resources) for a data stream.
TYPE: DataStream
None
"},{"location":"reference/functions/broker/consumer/#streampipes.functions.broker.consumer.Consumer.get_message","title":"get_message()
abstractmethod
","text":"Get the published messages of the subscription.
RETURNS DESCRIPTIONiterator
An async iterator for the messages.
TYPE: AsyncIterator
OutputCollector(data_stream)
","text":"Collector for output events. The events are published to an output data stream. Therefore, the output collector establishes a connection to the broker.
PARAMETER DESCRIPTIONdata_stream
The output data stream that will receive the events.
TYPE: DataStream
publisher
The publisher instance that sends the data to StreamPipes
TYPE: Publisher
collect(event)
","text":"Publishes an event to the output stream.
PARAMETER DESCRIPTIONevent
The event to be published.
TYPE: Dict[str, Any]
None
"},{"location":"reference/functions/broker/output_collector/#streampipes.functions.broker.output_collector.OutputCollector.disconnect","title":"disconnect()
","text":"Disconnects the broker of the output collector.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/broker/publisher/","title":"Publisher","text":""},{"location":"reference/functions/broker/publisher/#streampipes.functions.broker.publisher.Publisher","title":"Publisher
","text":" Bases: Broker
Abstract implementation of a publisher for a broker.
A publisher allows to publish events to a data stream.
"},{"location":"reference/functions/broker/publisher/#streampipes.functions.broker.publisher.Publisher.publish_event","title":"publish_event(event)
abstractmethod
async
","text":"Publish an event to a connected data stream.
PARAMETER DESCRIPTIONevent
The event to be published.
TYPE: Dict[str, Any]
None
"},{"location":"reference/functions/broker/kafka/kafka_consumer/","title":"Kafka consumer","text":""},{"location":"reference/functions/broker/kafka/kafka_consumer/#streampipes.functions.broker.kafka.kafka_consumer.KafkaConsumer","title":"KafkaConsumer
","text":" Bases: Consumer
Implementation of a consumer for Kafka
"},{"location":"reference/functions/broker/kafka/kafka_consumer/#streampipes.functions.broker.kafka.kafka_consumer.KafkaConsumer.disconnect","title":"disconnect()
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/broker/kafka/kafka_consumer/#streampipes.functions.broker.kafka.kafka_consumer.KafkaConsumer.get_message","title":"get_message()
","text":"Get the published messages of the subscription.
RETURNS DESCRIPTIONiterator
An async iterator for the messages.
TYPE: AsyncIterator
KafkaMessage(data)
","text":"An internal representation of a Kafka message
PARAMETER DESCRIPTIONdata
The received Kafka message as byte array
"},{"location":"reference/functions/broker/kafka/kafka_message_fetcher/#streampipes.functions.broker.kafka.kafka_message_fetcher.KafkaMessageFetcher","title":"
KafkaMessageFetcher(consumer)
","text":"Fetches the next message from Kafka
PARAMETER DESCRIPTIONconsumer
The Kafka consumer
TYPE: Consumer
KafkaPublisher
","text":" Bases: Publisher
Implementation of a publisher for Kafka
"},{"location":"reference/functions/broker/kafka/kafka_publisher/#streampipes.functions.broker.kafka.kafka_publisher.KafkaPublisher.disconnect","title":"disconnect()
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/broker/kafka/kafka_publisher/#streampipes.functions.broker.kafka.kafka_publisher.KafkaPublisher.publish_event","title":"publish_event(event)
async
","text":"Publish an event to a connected data stream.
PARAMETER DESCRIPTIONevent
The event to be published.
TYPE: Dict[str, Any]
None
"},{"location":"reference/functions/broker/nats/nats_consumer/","title":"Nats consumer","text":""},{"location":"reference/functions/broker/nats/nats_consumer/#streampipes.functions.broker.nats.nats_consumer.NatsConsumer","title":"NatsConsumer
","text":" Bases: Consumer
Implementation of a consumer for NATS
"},{"location":"reference/functions/broker/nats/nats_consumer/#streampipes.functions.broker.nats.nats_consumer.NatsConsumer.disconnect","title":"disconnect()
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/broker/nats/nats_consumer/#streampipes.functions.broker.nats.nats_consumer.NatsConsumer.get_message","title":"get_message()
","text":"Get the published messages of the subscription.
RETURNS DESCRIPTIONmessage_iterator
An async iterator for the messages.
TYPE: AsyncIterator
NatsPublisher
","text":" Bases: Publisher
Implementation of a publisher for NATS
"},{"location":"reference/functions/broker/nats/nats_publisher/#streampipes.functions.broker.nats.nats_publisher.NatsPublisher.disconnect","title":"disconnect()
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTIONNone
"},{"location":"reference/functions/broker/nats/nats_publisher/#streampipes.functions.broker.nats.nats_publisher.NatsPublisher.publish_event","title":"publish_event(event)
async
","text":"Publish an event to a connected data stream.
PARAMETER DESCRIPTIONevent
The event to be published.
TYPE: Dict[str, Any]
None
"},{"location":"reference/functions/utils/async_iter_handler/","title":"Async iter handler","text":""},{"location":"reference/functions/utils/async_iter_handler/#streampipes.functions.utils.async_iter_handler.AsyncIterHandler","title":"AsyncIterHandler
","text":"Handles asynchronous iterators to get every message after another in parallel.
"},{"location":"reference/functions/utils/async_iter_handler/#streampipes.functions.utils.async_iter_handler.AsyncIterHandler.anext","title":"anext(stream_id, message)
async
staticmethod
","text":"Gets the next message from an AsyncIterator.
PARAMETER DESCRIPTIONstream_id
The id of the data stream which the message belongs to.
TYPE: str
message
An asynchronous iterator that contains the messages.
TYPE: AsyncIterator
result
Tuple of the stream id und next message or (\"stop\", None)
if no message is left.
TYPE: Tuple[str, Optional[Any]]
combine_async_messages(messages)
async
staticmethod
","text":"Continuously gets the next published message from multiple AsyncIterators in parallel.
PARAMETER DESCRIPTIONmessages
A dictionary with an asynchronous iterator for every stream id.
TYPE: Dict[str, AsyncIterator]
message
Description of the anonymous integer return value.
TYPE:: Tuple[str, Any]
DataStreamContext(functions, schema, broker)
","text":"Container for the context of a data stream.
PARAMETER DESCRIPTIONfunctions
StreamPipes Functions which require the data of this data stream.
TYPE: List[StreamPipesFunction]
schema
The schema of this data stream.
TYPE: DataStream
broker
The consumer to connect to this data stream.
TYPE: Consumer
add_function(function)
","text":"Adds a new StreamPipes Function.
PARAMETER DESCRIPTIONfunction
StreamPipesFunction which requires this data stream.
TYPE: StreamPipesFunction
None
"},{"location":"reference/functions/utils/data_stream_generator/","title":"Data stream generator","text":""},{"location":"reference/functions/utils/data_stream_generator/#streampipes.functions.utils.data_stream_generator.RuntimeType","title":"RuntimeType
","text":" Bases: Enum
Runtime type names for the attributes of a data stream.
ATTRIBUTE DESCRIPTIONSTRING
BOOLEAN
DOUBLE
FLOAT
INTEGER
LONG
"},{"location":"reference/functions/utils/data_stream_generator/#streampipes.functions.utils.data_stream_generator.create_data_stream","title":"
create_data_stream(name, attributes, stream_id=None, broker=SupportedBroker.NATS)
","text":"Creates a data stream
PARAMETER DESCRIPTIONname
Name of the data stream to be shown at the UI.
TYPE: str
attributes
Name and types of the attributes.
TYPE: Dict[str, str]
stream_id
The id of this data stream.
TYPE: Optional[str]
DEFAULT: None
data_stream
The created data stream
TYPE: DataStream
FunctionContext(function_id, schema, client, streams)
","text":"Container for the context of a StreamPipesFunction.
PARAMETER DESCRIPTIONfunction_id
The id of this function.
TYPE: str
schema
A dictionary which contains the schema of a data stream for each stream id.
TYPE: Dict[str, DataStream]
client
The client to interact with the API.
TYPE: StreamPipesClient
streams
The ids of the streams needed by this function.
TYPE: List[str]
add_data_stream_schema(stream_id, data_stream)
","text":"Adds a new data stream for a new stream id.
PARAMETER DESCRIPTIONstream_id
The id of the data stream.
TYPE: str
data_stream
The schema of the data stream.
TYPE: DataStream
None
"},{"location":"reference/model/common/","title":"Common","text":"Classes of the StreamPipes data model that are commonly shared.
"},{"location":"reference/model/common/#streampipes.model.common.ApplicationLink","title":"ApplicationLink
","text":" Bases: BasicModel
Data model of an ApplicationLink
in compliance to the StreamPipes Backend.
BaseElement
","text":" Bases: BasicModel
Structure of a basic element in the StreamPipes backend
"},{"location":"reference/model/common/#streampipes.model.common.BasicModel","title":"BasicModel
","text":" Bases: BaseModel
Basic model class used for the whole Python StreamPipes data model.
"},{"location":"reference/model/common/#streampipes.model.common.BasicModel.Config","title":"Config
","text":"Configuration class for Pydantic. Defines alias generator to convert field names from camelCase (API) to snake_case (Python codebase).
"},{"location":"reference/model/common/#streampipes.model.common.EventGrounding","title":"EventGrounding
","text":" Bases: BasicModel
Data model of an EventGrounding
in compliance to the StreamPipes Backend.
EventProperty
","text":" Bases: BasicModel
Data model of an EventProperty
in compliance to the StreamPipes Backend.
EventSchema
","text":" Bases: BasicModel
Data model of an EventSchema
in compliance to the StreamPipes Backend.
MeasurementCapability
","text":" Bases: BasicModel
Data model of a MeasurementCapability
in compliance to the StreamPipes Backend.
MeasurementObject
","text":" Bases: BasicModel
Data model of a MeasurementObject
in compliance to the StreamPipes Backend.
TopicDefinition
","text":" Bases: BasicModel
Data model of a TopicDefinition
in compliance to the StreamPipes Backend.
TransportFormat
","text":" Bases: BasicModel
Data model of a TransportFormat
in compliance to the StreamPipes Backend.
TransportProtocol
","text":" Bases: BasicModel
Data model of a TransportProtocol
in compliance to the StreamPipes Backend.
ValueSpecification
","text":" Bases: BasicModel
Data model of an ValueSpecification
in compliance to the StreamPipes Backend.
random_letters(n)
","text":"Generates a string consisting of random letters.
PARAMETER DESCRIPTIONn
number of letters
TYPE: int
rand_str
String consisting of n
random letters
TYPE: str
Implementation of a resource container for the data lake measures endpoint.
"},{"location":"reference/model/container/data_lake_measures/#streampipes.model.container.data_lake_measures.DataLakeMeasures","title":"DataLakeMeasures
","text":" Bases: ResourceContainer
Implementation of the resource container for the data lake measures endpoint.
This resource container is a collection of data lake measures returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried DataLakeMeasure
. Furthermore, the resource container makes them accessible in a pythonic manner.
Implementation of a resource container for the data streams endpoint.
"},{"location":"reference/model/container/data_streams/#streampipes.model.container.data_streams.DataStreams","title":"DataStreams
","text":" Bases: ResourceContainer
Implementation of the resource container for the data stream endpoint.
This resource container is a collection of data streams returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried DataStream
. Furthermore, the resource container makes them accessible in a pythonic manner.
General and abstract implementation for a resource container.
A resource container is a collection of resources returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried resources. Furthermore, the resource container makes them accessible in a pythonic manner.
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.ResourceContainer","title":"ResourceContainer(resources)
","text":" Bases: ABC
General and abstract implementation for a resource container.
A resource container is a collection of resources returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried resources. Furthermore, the resource container makes them accessible in a pythonic manner.
PARAMETER DESCRIPTIONresources
A list of resources to be contained in the ResourceContainer
.
TYPE: List[Resource]
from_json(json_string)
classmethod
","text":"Creates a ResourceContainer
from the given JSON string.
json_string
The JSON string returned from the StreamPipes API.
TYPE: str
container
instance of the container derived from the JSON definition
TYPE: ResourceContainer
StreamPipesDataModelError
If a resource cannot be mapped to the corresponding Python data model.
StreamPipesResourceContainerJSONError
If JSON response cannot be parsed to a ResourceContainer
.
to_dicts(use_source_names=False)
","text":"Returns the contained resources as list of dictionaries.
PARAMETER DESCRIPTIONuse_source_names
Determines whether the field names are named in Python style (=False
) or as originally named by StreamPipes (=True
).
TYPE: bool
DEFAULT: False
dictionary_list
List of resources in dictionary representation. If use_source_names
equals True
the keys are named as in the StreamPipes backend.
TYPE: List[Dict[str, Any]]
to_json()
","text":"Returns the resource container in the StreamPipes JSON representation.
RETURNS DESCRIPTION json_string: str
JSON representation of the resource container where key names are equal to keys used in the StreamPipes backend
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.ResourceContainer.to_pandas","title":"to_pandas()
","text":"Returns the resource container in representation of a Pandas Dataframe.
RETURNS DESCRIPTIONresource_container_df
Representation of the resource container as pandas DataFrame
TYPE: pd.DataFrame
StreamPipesDataModelError(validation_error)
","text":" Bases: Exception
A custom exception to be raised when a validation error occurs during the parsing of StreamPipes API responses.
PARAMETER DESCRIPTIONvalidation_error
The validation error thrown by Pydantic during parsing.
TYPE: ValidationError
StreamPipesResourceContainerJSONError(container_name, json_string)
","text":" Bases: Exception
A custom exception to be raised when the returned JSON string does not suit to the structure of resource container.
PARAMETER DESCRIPTIONcontainer_name
The class name of the resource container where the invalid data structure was detected.
TYPE: str
json_string
The JSON string that has been tried to parse.
TYPE: str
Implementation of a resource container for the versions endpoint.
"},{"location":"reference/model/container/versions/#streampipes.model.container.versions.Versions","title":"Versions
","text":" Bases: ResourceContainer
Implementation of the resource container for the versions endpoint.
This resource container is a collection of versions returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried Version
. Furthermore, the resource container makes them accessible in a pythonic manner.
resources
A list of resources (Version) to be contained in the ResourceContainer
.
"},{"location":"reference/model/resource/data_lake_measure/","title":"Data lake measure","text":""},{"location":"reference/model/resource/data_lake_measure/#streampipes.model.resource.data_lake_measure.DataLakeMeasure","title":"
DataLakeMeasure
","text":" Bases: Resource
Implementation of a resource for data lake measures.
This resource defines the data model used by resource container (model.container.DataLakeMeasures
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response, and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
convert_to_pandas_representation()
","text":"Returns the dictionary representation of a data lake measure to be used when creating a pandas Dataframe.
It excludes the following fields: element_id
, event_schema
, schema_version
. Instead of the whole event schema the number of event properties contained is returned with the column name num_event_properties
.
pandas_repr
Pandas representation of the resource as a dictionary, which is then used by the respource container to create a data frame from a collection of resources.
TYPE: Dict[str, Any]
DataSeries
","text":" Bases: Resource
Implementation of a resource for data series. This resource defines the data model used by its resource container(model.container.DataLakeMeasures
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
This class will only exist temporarily in it its current appearance since\nthere are some inconsistencies in the StreamPipes API.\n
"},{"location":"reference/model/resource/data_series/#streampipes.model.resource.data_series.DataSeries.convert_to_pandas_representation","title":"convert_to_pandas_representation()
","text":"Returns the dictionary representation of a data lake series to be used when creating a pandas Dataframe.
It contains only the \"header rows\" (the column names) and \"rows\" that contain the actual data.
RETURNS DESCRIPTIONpandas_repr
Dictionary with the keys headers
and rows
TYPE: dict[str, Any]
from_json(json_string)
classmethod
","text":"Creates an instance of DataSeries
from a given JSON string.
This method is used by the resource container to parse the JSON response of the StreamPipes API. Currently, it only supports data lake series that consist of exactly one series of data.
PARAMETER DESCRIPTIONjson_string
The JSON string the data lake series should be created on.
TYPE: str
DataSeries
Instance of DataSeries
that is created based on the given JSON string.
StreamPipesUnsupportedDataLakeSeries
If the data lake series returned by the StreamPipes API cannot be parsed with the current version of the Python client.
"},{"location":"reference/model/resource/data_series/#streampipes.model.resource.data_series.DataSeries.to_pandas","title":"to_pandas()
","text":"Returns the data lake series in representation of a Pandas Dataframe.
RETURNS DESCRIPTIONpd
The data lake series in form of a pandas dataframe
TYPE: pd.DataFrame
DataStream(**kwargs)
","text":" Bases: Resource
Implementation of a resource for data streams.
This resource defines the data model used by resource container (model.container.DataStreams
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
convert_to_pandas_representation()
","text":"Returns the dictionary representation of a data stream to be used when creating a pandas Dataframe.
RETURNS DESCRIPTIONpandas_repr
Pandas representation of the resource as a dictionary, which is then used by the respource container to create a data frame from a collection of resources.
TYPE: Dict[str, Any]
to_dict(use_source_names=True)
","text":"Returns the resource in dictionary representation.
PARAMETER DESCRIPTIONuse_source_names
Indicates if the dictionary keys are in python representation or equally named to the StreamPipes backend
DEFAULT: True
resource
The resource as dictionary representation
TYPE: Dict[str, Any]
StreamPipesUnsupportedDataSeries(reason=None)
","text":" Bases: Exception
Exception to be raised when the returned data lake series cannot be parsed with the current implementation of the resource.
"},{"location":"reference/model/resource/function_definition/","title":"Function definition","text":""},{"location":"reference/model/resource/function_definition/#streampipes.model.resource.function_definition.FunctionDefinition","title":"FunctionDefinition
","text":" Bases: Resource
Configuration for a StreamPipes Function.
This class maps to the FunctionDefinition
class in the StreamPipes model. It contains all metadata that are required to register a function at the StreamPipes backend.
consumed_streams
List of data streams the function is consuming from
function_id
identifier object of a StreamPipes function
ATTRIBUTE DESCRIPTION
output_data_streams
Map off all output data streams added to the function definition
TYPE: Dict[str, DataStream]
add_output_data_stream(data_stream)
","text":"Adds an output data stream to the function which makes it possible to write data back to StreamPipes.
PARAMETER DESCRIPTIONdata_stream
The schema of the output data stream.
TYPE: DataStream
self
Instance of the function definition that is extended by the provided DataStream
TYPE: FunctionDefinition
convert_to_pandas_representation()
","text":"Returns the dictionary representation of a function definition to be used when creating a pandas Dataframe.
RETURNS DESCRIPTIONpandas_repr
Pandas representation of the resource as a dictionary, which is then used by the respource container to create a data frame from a collection of resources.
TYPE: Dict[str, Any]
get_output_data_streams()
","text":"Get the output data streams of the function.
RETURNS DESCRIPTIONoutput_streams
Dictionary with every known stream id and the related output stream.
TYPE: Dict[str, DataStream]
get_output_stream_ids()
","text":"Get the stream ids of the output data streams.
RETURNS DESCRIPTIONoutput_stream_ids
List of all stream ids
TYPE: List[str]
FunctionId
","text":" Bases: BasicModel
Identification object for a StreamPipes function.
Maps to the FunctionId
class defined in the StreamPipes model.
id
unique identifier of the function instance
version
version of the corresponding function
"},{"location":"reference/model/resource/query_result/","title":"Query result","text":""},{"location":"reference/model/resource/query_result/#streampipes.model.resource.query_result.QueryResult","title":"
QueryResult
","text":" Bases: Resource
Implementation of a resource for query result. This resource defines the data model used by its resource container(model.container.DataLakeMeasures
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
convert_to_pandas_representation()
","text":"Returns the dictionary representation of a data lake series to be used when creating a pandas Dataframe.
It contains only the \"header rows\" (the column names) and \"rows\" that contain the actual data.
RETURNS DESCRIPTIONdict
Dictionary with the keys headers
and rows
StreamPipesUnsupportedDataLakeSeries
If the query result returned by the StreamPipes API cannot be converted to the pandas representation
"},{"location":"reference/model/resource/query_result/#streampipes.model.resource.query_result.QueryResult.to_pandas","title":"to_pandas()
","text":"Returns the data lake series in representation of a Pandas Dataframe.
RETURNS DESCRIPTIONdf
Pandas df containing the query result
TYPE: pd.DataFrame
General and abstract implementation for a resource.
A resource defines the data model that is used by a resource container (model.container.resourceContainer
).
Resource
","text":" Bases: ABC
, BasicModel
General and abstract implementation for a resource.
A resource defines the data model used by a resource container (model.container.resourceContainer
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
convert_to_pandas_representation()
abstractmethod
","text":"Returns a dictionary representation to be used when creating a pandas Dataframe.
RETURNS DESCRIPTIONpandas_repr
Pandas representation of the resource as a dictionary, which is then used by the respource container to create a data frame from a collection of resources.
TYPE: Dict[str, Any]
to_dict(use_source_names=True)
","text":"Returns the resource in dictionary representation.
PARAMETER DESCRIPTIONuse_source_names
Indicates if the dictionary keys are in python representation or equally named to the StreamPipes backend
DEFAULT: True
resource
The resource as dictionary representation
TYPE: Dict[str, Any]
Version
","text":" Bases: Resource
Metadata about the version of the connected StreamPipes server.
ATTRIBUTE DESCRIPTIONbackend_version
version of the StreamPipes backend the client is connected to
TYPE: str
convert_to_pandas_representation()
","text":"Returns the dictionary representation of the version metadata to be used when creating a pandas Dataframe.
"},{"location":"scripts/gen_ref_pages/","title":"Gen ref pages","text":"Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
In\u00a0[\u00a0]: Copied!from pathlib import Path\nfrom pathlib import Path In\u00a0[\u00a0]: Copied!
import mkdocs_gen_files\nimport mkdocs_gen_files In\u00a0[\u00a0]: Copied!
nav = mkdocs_gen_files.Nav()\nnav = mkdocs_gen_files.Nav() In\u00a0[\u00a0]: Copied!
for path in sorted(Path(\"streampipes\").rglob(\"*.py\")):\n module_path = path.relative_to(\"streampipes\").with_suffix(\"\")\n doc_path = path.relative_to(\"streampipes\").with_suffix(\".md\")\n full_doc_path = Path(\"reference\", doc_path)\n\n parts = list(module_path.parts)\n\n if parts[-1] == \"__init__\":\n # parts = parts[:-1]\n continue\n elif parts[-1] == \"__version__\":\n continue\n elif parts[-1] == \"__main__\":\n continue\n elif parts[-1] == \" \":\n continue\n\n nav[parts] = doc_path.as_posix()\n\n with mkdocs_gen_files.open(full_doc_path, \"w+\") as fd:\n identifier = \".\".join(parts)\n print(f\"::: streampipes.{identifier}\", file=fd)\n\n mkdocs_gen_files.set_edit_path(full_doc_path, path)\nfor path in sorted(Path(\"streampipes\").rglob(\"*.py\")): module_path = path.relative_to(\"streampipes\").with_suffix(\"\") doc_path = path.relative_to(\"streampipes\").with_suffix(\".md\") full_doc_path = Path(\"reference\", doc_path) parts = list(module_path.parts) if parts[-1] == \"__init__\": # parts = parts[:-1] continue elif parts[-1] == \"__version__\": continue elif parts[-1] == \"__main__\": continue elif parts[-1] == \" \": continue nav[parts] = doc_path.as_posix() with mkdocs_gen_files.open(full_doc_path, \"w+\") as fd: identifier = \".\".join(parts) print(f\"::: streampipes.{identifier}\", file=fd) mkdocs_gen_files.set_edit_path(full_doc_path, path)
with mkdocs_gen_files.open(\"reference/SUMMARY.md\", \"w+\") as nav_file: nav_file.writelines(nav.build_literate_nav())
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/","title":"Introduction to StreamPipes Python","text":"In\u00a0[\u00a0]: Copied!%pip install streampipes\n%pip install streampipes
If you want to have the current development state you can also execute:
In\u00a0[\u00a0]: Copied!%pip install git+https://github.com/apache/streampipes.git#subdirectory=streampipes-client-python\n%pip install git+https://github.com/apache/streampipes.git#subdirectory=streampipes-client-python
The corresponding documentation can be found here.
In\u00a0[\u00a0]: Copied!from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\nfrom streampipes.client import StreamPipesClient from streampipes.client.config import StreamPipesClientConfig from streampipes.client.credential_provider import StreamPipesApiKeyCredentials In\u00a0[\u00a0]: Copied!
config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(\n username=\"test@streampipes.apache.org\",\n api_key=\"API-KEY\",\n ),\n host_address=\"localhost\",\n https_disabled=True,\n port=80\n)\nconfig = StreamPipesClientConfig( credential_provider=StreamPipesApiKeyCredentials( username=\"test@streampipes.apache.org\", api_key=\"API-KEY\", ), host_address=\"localhost\", https_disabled=True, port=80 )
Please be aware that connecting to StreamPipes via a https
connection is currently not supported by the Python client.
Providing secrets like the api_key
as plaintext in the source code is an anti-pattern. This is why the StreamPipes client also supports passing the required secrets as environment variables. To do so, you must initialize the credential provider like the following:
StreamPipesApiKeyCredentials()\nStreamPipesApiKeyCredentials()
To ensure that the above code works, you must set the environment variables as expected. This can be done like following:
In\u00a0[\u00a0]: Copied!%export SP_USERNAME=\"<USERNAME>\"\n%export SP_API_KEY=\"<API-KEY>\"\n%export SP_USERNAME=\"\" %export SP_API_KEY=\"\"
Having the config
ready, we can now initialize the actual client.
client = StreamPipesClient(client_config=config)\nclient = StreamPipesClient(client_config=config)
That's already it. You can check if everything works out by using the following command:
In\u00a0[6]: Copied!client.describe()\nclient.describe()
2023-02-24 17:05:49,398 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n2023-02-24 17:05:49,457 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n\nHi there!\nYou are connected to a StreamPipes instance running at http://localhost:80.\nThe following StreamPipes resources are available with this client:\n1x DataLakeMeasures\n1x DataStreams\n
This prints you a short textual description of the connected StreamPipes instance to the console.
The created client
instance serves as the central point of interaction with StreamPipes. You can invoke a variety of commands directly on this object.
Are you curious now how you actually can get data out of StreamPipes and make use of it with Python? Then check out the next tutorial on extracting Data from the StreamPipes data lake.
Thanks for reading this introductory tutorial. We hope you like it and would love to receive some feedback from you. Just go to our GitHub discussion page and let us know your impression. We'll read and react to them all, we promise!
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/#Introduction-to-StreamPipes-Python","title":"Introduction to StreamPipes Python\u00b6","text":""},{"location":"tutorials/1-introduction-to-streampipes-python-client/#Why-there-is-an-extra-Python-library-for-StreamPipes?","title":"Why there is an extra Python library for StreamPipes?\u00b6","text":"Apache StreamPipes aims to enable non-technical users to connect and analyze IoT data streams. To this end, it provides an easy-to-use and convenient user interface that allows one to connect to an IoT data source and create some visual graphs within a few minutes. Although this is the main use case of Apache StreamPipes, it can also provide great value for people who are eager to work on data analysis or data science with IoT data, but don't we do get in touch with all the hassle associated with extracting data from devices in a suitable format. In this scenario, StreamPipes helps you connect to your data source and extract the data for you. You then can make the data available outside StreamPipes by writing it into an external source, such as a database, Kafka, etc. While this requires another component, you can also extract your data directly from StreamPipes programmatically using the StreamPipes API. For convenience, we also provide you with a StreamPipes client both available for Java and Python. Specifically with StreamPipes Python, we want to address the amazing data analytics and data science community in Python and benefit from the great universe of Python libraries out there.
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/#How-to-install-StreamPipes-Python?","title":"How to install StreamPipes Python?\u00b6","text":"Simply use the following pip
command:
In case you want to reproduce the first two tutorials exactly on your end, you need to create a simple pipeline in StreamPipes like demonstrated below.
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/#How-to-configure-the-Python-client","title":"How to configure the Python client\u00b6","text":"In order to access the resources available in StreamPipes, one must be able to authenticate against the backend. For this purpose, the client sofar only supports the authentication via an API token that can be generated via the StreamPipes UI, as you see below.
Having generated the API token, one can directly start initializing a client instance as follows:
"},{"location":"tutorials/2-extracting-data-from-the-streampipes-data-lake/","title":"Extracting Data from the StreamPipes data lake","text":"In\u00a0[1]: Copied!from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\nfrom streampipes.client import StreamPipesClient from streampipes.client.config import StreamPipesClientConfig from streampipes.client.credential_provider import StreamPipesApiKeyCredentials In\u00a0[\u00a0]: Copied!
# if you want all necessary dependencies required for this tutorial to be installed,\n# you can simply execute the following command\n%pip install matplotlib streampipes\n# if you want all necessary dependencies required for this tutorial to be installed, # you can simply execute the following command %pip install matplotlib streampipes In\u00a0[2]: Copied!
import os\nos.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\"\nos.environ[\"SP_API_KEY\"] = \"XXX\"\nimport os os.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\" os.environ[\"SP_API_KEY\"] = \"XXX\" In\u00a0[3]: Copied!
config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(),\n host_address=\"localhost\",\n https_disabled=True,\n port=80\n)\nconfig = StreamPipesClientConfig( credential_provider=StreamPipesApiKeyCredentials(), host_address=\"localhost\", https_disabled=True, port=80 ) In\u00a0[4]: Copied!
client = StreamPipesClient(client_config=config)\nclient = StreamPipesClient(client_config=config)
2023-02-24 17:34:25,860 - streampipes.client.client - [INFO] - [client.py:128] [_set_up_logging] - Logging successfully initialized with logging level INFO.\n
As a first step, we want to get an overview about all data available in the data lake. The data is stored as so-called measures
, which refer to a data stream stored in the data lake. For his purpose we use the all()
method of the dataLakeMeasure
endpoint.
data_lake_measures = client.dataLakeMeasureApi.all()\ndata_lake_measures = client.dataLakeMeasureApi.all()
2023-02-24 17:34:25,929 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n
So let's see how many measures are available
In\u00a0[6]: Copied!len(data_lake_measures)\nlen(data_lake_measures) Out[6]:
2
All resources of the StreamPipes Python client support the standard Python expressions. If not, please let us know.
In\u00a0[7]: Copied!data_lake_measures[-1]\ndata_lake_measures[-1] Out[7]:
DataLakeMeasure(element_id='3cb6b5e6f107452483d1fd2ccf4bf9f9', measure_name='test', timestamp_field='s0::timestamp', event_schema=EventSchema(event_properties=[EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:EiFnkL', label='Density', description='Denotes the current density of the fluid', runtime_name='density', required=False, domain_properties=['http://schema.org/Number'], property_scope='MEASUREMENT_PROPERTY', index=5, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#float', measurement_unit=None, value_specification=None), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:ghSkQI', label='Mass Flow', description='Denotes the current mass flow in the sensor', runtime_name='mass_flow', required=False, domain_properties=['http://schema.org/Number'], property_scope='MEASUREMENT_PROPERTY', index=2, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#float', measurement_unit=None, value_specification=None), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:cQAUry', label='Sensor ID', description='The ID of the sensor', runtime_name='sensorId', required=False, domain_properties=['https://streampipes.org/vocabulary/examples/watertank/v1/hasSensorId'], property_scope='DIMENSION_PROPERTY', index=1, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#string', measurement_unit=None, value_specification=None), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:pbPMyL', label='Sensor Fault Flags', description='Any fault flags of the sensors', runtime_name='sensor_fault_flags', required=False, domain_properties=['http://schema.org/Boolean'], property_scope='MEASUREMENT_PROPERTY', index=6, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#boolean', measurement_unit=None, value_specification=None), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:Qmayhw', label='Temperature', description='Denotes the current temperature in degrees celsius', runtime_name='temperature', required=False, domain_properties=['http://schema.org/Number'], property_scope='MEASUREMENT_PROPERTY', index=4, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#float', measurement_unit='http://qudt.org/vocab/unit#DegreeCelsius', value_specification=ValueSpecification(class_name='org.apache.streampipes.model.schema.QuantitativeValue', element_id=None, min_value=0, max_value=100, step=0.1)), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:YQYhjd', label='Volume Flow', description='Denotes the current volume flow', runtime_name='volume_flow', required=False, domain_properties=['http://schema.org/Number'], property_scope='MEASUREMENT_PROPERTY', index=3, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#float', measurement_unit=None, value_specification=None)]), pipeline_id=None, pipeline_name=None, pipeline_is_running=False, schema_version='1.1')
To get a more comprehensive overview, you can take a look at the pandas
representation
display(data_lake_measures.to_pandas())\ndisplay(data_lake_measures.to_pandas()) measure_name timestamp_field pipeline_id pipeline_name pipeline_is_running num_event_properties 0 flow-rate s0::timestamp None None False 6 1 test s0::timestamp None None False 6
So far, we have only retrieved metadata about the available data lake measure. In the following, we will access the actual data of the measure flow-rate
.
For this purpose, we will use the get()
method of the dataLakeMeasure
endpoint.
flow_rate_measure = client.dataLakeMeasureApi.get(identifier=\"flow-rate\")\nflow_rate_measure = client.dataLakeMeasureApi.get(identifier=\"flow-rate\")
2023-02-24 17:34:26,020 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n
For further processing, the easiest way is to turn the data measure into a pandas DataFrame
.
flow_rate_pd = flow_rate_measure.to_pandas()\nflow_rate_pd = flow_rate_measure.to_pandas()
Let's see how many data points we got...
In\u00a0[11]: Copied!len(flow_rate_pd)\nlen(flow_rate_pd) Out[11]:
1000
... and get a first overview
In\u00a0[12]: Copied!flow_rate_pd.describe()\nflow_rate_pd.describe() Out[12]: density mass_flow temperature volume_flow count 1000.000000 1000.000000 1000.000000 1000.000000 mean 45.560337 5.457014 45.480231 5.659558 std 3.201544 3.184959 3.132878 3.122437 min 40.007698 0.004867 40.000992 0.039422 25% 42.819497 2.654101 42.754623 3.021625 50% 45.679264 5.382355 45.435944 5.572553 75% 48.206881 8.183144 48.248473 8.338209 max 50.998310 10.986015 50.964909 10.998676
As a final step, we want to create a plot of both attributes
In\u00a0[13]: Copied!import matplotlib.pyplot as plt\nflow_rate_pd.plot(y=[\"mass_flow\", \"temperature\"])\nplt.show()\nimport matplotlib.pyplot as plt flow_rate_pd.plot(y=[\"mass_flow\", \"temperature\"]) plt.show()
For data lake measurements, the get()
method is even more powerful than simply returning all the data for a given data lake measurement. We will look at a selection of these below. The full list of supported parameters can be found in the docs. Let's start by referring to the graph we created above, where we use only two columns of our data lake measurement. If we already know this, we can directly restrict the queried data to a subset of columns by using the columns
parameter. columns
takes a list of column names as a comma-separated string:
flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", columns=\"mass_flow,temperature\").to_pandas()\nflow_rate_pd\nflow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", columns=\"mass_flow,temperature\").to_pandas() flow_rate_pd
2023-02-24 17:34:26,492 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\nOut[14]: timestamp mass_flow temperature 0 2023-02-24T16:19:41.472Z 3.309556 44.448483 1 2023-02-24T16:19:41.482Z 5.608580 40.322033 2 2023-02-24T16:19:41.493Z 7.692881 49.239639 3 2023-02-24T16:19:41.503Z 3.632898 49.933754 4 2023-02-24T16:19:41.513Z 0.711260 50.106617 ... ... ... ... 995 2023-02-24T16:19:52.927Z 1.740114 46.558231 996 2023-02-24T16:19:52.94Z 7.211723 48.048622 997 2023-02-24T16:19:52.952Z 7.770180 48.188026 998 2023-02-24T16:19:52.965Z 4.458602 48.280899 999 2023-02-24T16:19:52.977Z 2.592060 47.505951
1000 rows \u00d7 3 columns
By default, the client returns only the first one thousand records of a Data Lake measurement. This can be changed by passing a concrete value for the limit
parameter:
flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", limit=10000).to_pandas()\nlen(flow_rate_pd)\nflow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", limit=10000).to_pandas() len(flow_rate_pd)
2023-02-24 17:34:26,736 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\nOut[15]:
9528
If you want your data to be selected by time of occurrence rather than quantity, you can specify your time window by passing the start_date
and end_date
parameters:
from datetime import datetime\nflow_rate_pd = client.dataLakeMeasureApi.get(\n identifier=\"flow-rate\",\n start_date=datetime(year=2023, month=2, day=24, hour=17, minute=21, second=0),\n end_date=datetime(year=2023, month=2, day=24, hour=17, minute=21, second=1),\n ).to_pandas()\nflow_rate_pd.plot(y=[\"mass_flow\", \"temperature\"])\nplt.show()\nfrom datetime import datetime flow_rate_pd = client.dataLakeMeasureApi.get( identifier=\"flow-rate\", start_date=datetime(year=2023, month=2, day=24, hour=17, minute=21, second=0), end_date=datetime(year=2023, month=2, day=24, hour=17, minute=21, second=1), ).to_pandas() flow_rate_pd.plot(y=[\"mass_flow\", \"temperature\"]) plt.show()
2023-02-24 17:34:26,899 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n
... from this point on we leave all future processing of the data up to your creativity. Keep in mind: the general syntax used in this tutorial (all()
, to_pandas()
, get()
) applies to all endpoints and associated resources of the StreamPipes Python client.
If you get further and create exiting stuff with data extracted from StreamPipes please let us know. We are thrilled to see what you as a community will build with the provided client. Furthermore, don't hesitate to discuss feature requests to extend the current functionality with us.
For now, that's all about the StreamPipes client. Read the next tutorial (Getting live data from the StreamPipes data stream) if you are interested in making use of the powerful StreamPipes functions to interact with StreamPipes event-based.
How do you like this tutorial? We hope you like it and would love to receive some feedback from you. Just go to our GitHub discussion page and let us know your impression. We'll read and react to them all, we promise!
"},{"location":"tutorials/2-extracting-data-from-the-streampipes-data-lake/#Extracting-Data-from-the-StreamPipes-data-lake","title":"Extracting Data from the StreamPipes data lake\u00b6","text":"In the first tutorial (Introduction to the StreamPipes Python client) we took the first steps with the StreamPipes Python client and learned how to set everything up. Now we are ready to get started and want to retrieve some data out of StreamPipes. In this tutorial, we'll focus on the StreamPipes Data Lake, the component where StreamPipes stores data internally. To get started, we'll use the client
instance created in the first tutorial.
Note As of now we mainly developed the support for StreamPipes functions using NATS as messaging protocol. Consequently, this setup is tested most and should work flawlessly. Visit our first-steps page to see how to start StreamPipes accordingly. Anyhow, you can also use the other brokers that are currently supported in StreamPipes Python. In case you observe any problems, please reach out to us and file us an issue on GitHub.
In\u00a0[1]: Copied!from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\nfrom streampipes.client import StreamPipesClient from streampipes.client.config import StreamPipesClientConfig from streampipes.client.credential_provider import StreamPipesApiKeyCredentials In\u00a0[\u00a0]: Copied!
# You can install all required libraries for this tutorial with the following command\n%pip install matplotlib ipython streampipes\n# You can install all required libraries for this tutorial with the following command %pip install matplotlib ipython streampipes In\u00a0[2]: Copied!
import os\n\nos.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\"\nos.environ[\"SP_API_KEY\"] = \"XXX\"\n\n# Use this if you work locally:\nos.environ[\"BROKER-HOST\"] = \"localhost\" \nos.environ[\"KAFKA-PORT\"] = \"9094\" # When using Kafka as message broker. If Kafka is not running on localhost, KAFKA_ADVERTISED_LISTENERS should be adjusted to the external address\nimport os os.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\" os.environ[\"SP_API_KEY\"] = \"XXX\" # Use this if you work locally: os.environ[\"BROKER-HOST\"] = \"localhost\" os.environ[\"KAFKA-PORT\"] = \"9094\" # When using Kafka as message broker. If Kafka is not running on localhost, KAFKA_ADVERTISED_LISTENERS should be adjusted to the external address In\u00a0[3]: Copied!
client_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(),\n host_address=\"localhost\",\n port=80,\n https_disabled=True,\n)\nclient = StreamPipesClient(client_config=client_config)\nclient_config = StreamPipesClientConfig( credential_provider=StreamPipesApiKeyCredentials(), host_address=\"localhost\", port=80, https_disabled=True, ) client = StreamPipesClient(client_config=client_config)
2022-12-14 10:43:37,664 - streampipes.client.client - [INFO] - [client.py:127] [_set_up_logging] - Logging successfully initialized with logging level INFO.\n
Now we can have a look at the available data streams. We can choose one or more stream to receive the data from and copy their element_id
.
client.dataStreamApi.all().to_pandas()\nclient.dataStreamApi.all().to_pandas()
2022-12-14 10:43:39,944 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:153] [_make_request] - Successfully retrieved all resources.\nOut[4]: element_id name description icon_url app_id includes_assets includes_locales internally_managed measurement_object index ... uri dom num_transport_protocols num_measurement_capability num_application_links num_included_assets num_connected_to num_category num_event_properties num_included_locales 0 urn:streampipes.apache.org:eventstream:HHoidJ Test2 None None False False True None 0 ... urn:streampipes.apache.org:eventstream:HHoidJ None 1 0 0 0 0 0 7 0 1 urn:streampipes.apache.org:eventstream:uPDKLI Test None None False False True None 0 ... urn:streampipes.apache.org:eventstream:uPDKLI None 1 0 0 0 0 0 7 0
2 rows \u00d7 21 columns
Next we can create a StreamPipesFunction. For this we need to implement the 3 following methods:
onServiceStarted
is called when the function gets started. There you can use the given meta information of the FunctionContext
to initialize the function.onEvent
is called when ever a new event arrives. The event
contains the live data and you can use the streamId
to identify a stream if the function is connected to multiple data streams.onServiceStopped
is called when the function gets stopped.For this tutorial we just create a function that saves every new event in a pandas DataFrame
and plots the first column of the DataFrame
when the function gets stopped.
(If you want to use the same structure as in Java you can overwrite the getFunctionId
and requiredStreamIds
methods instead of using the FunctionDefinition
)
from typing import Dict, Any\nimport pandas as pd\nfrom datetime import datetime\nimport matplotlib.pyplot as plt\nfrom streampipes.functions.function_handler import FunctionHandler\nfrom streampipes.functions.registration import Registration\nfrom streampipes.functions.streampipes_function import StreamPipesFunction\nfrom streampipes.functions.utils.function_context import FunctionContext\nfrom streampipes.model.resource.function_definition import FunctionDefinition, FunctionId\n\nclass ExampleFunction(StreamPipesFunction):\n def __init__(self, function_definition: FunctionDefinition) -> None:\n super().__init__(function_definition)\n # Create the Dataframe to save the live data\n self.df = pd.DataFrame()\n\n def onServiceStarted(self, context: FunctionContext):\n # Get the name of the timestamp field\n for event_property in context.schema[context.streams[0]].event_schema.event_properties:\n if event_property.property_scope == \"HEADER_PROPERTY\":\n self.timestamp = event_property.runtime_name\n\n def onEvent(self, event: Dict[str, Any], streamId: str):\n # Convert the unix timestamp to datetime\n event[self.timestamp] = datetime.fromtimestamp(event[self.timestamp] / 1000)\n # Add every value of the event to the DataFrame\n self.df = pd.concat(\n [self.df, pd.DataFrame({key: [event[key]] for key in event.keys()}).set_index(self.timestamp)]\n )\n\n def onServiceStopped(self):\n # Plot the first column of the Dataframe\n plt.figure(figsize=(10, 5))\n plt.xlabel(self.timestamp)\n plt.ylabel(self.df.columns[0])\n plt.plot(self.df.iloc[:, 0])\n plt.show()\nfrom typing import Dict, Any import pandas as pd from datetime import datetime import matplotlib.pyplot as plt from streampipes.functions.function_handler import FunctionHandler from streampipes.functions.registration import Registration from streampipes.functions.streampipes_function import StreamPipesFunction from streampipes.functions.utils.function_context import FunctionContext from streampipes.model.resource.function_definition import FunctionDefinition, FunctionId class ExampleFunction(StreamPipesFunction): def __init__(self, function_definition: FunctionDefinition) -> None: super().__init__(function_definition) # Create the Dataframe to save the live data self.df = pd.DataFrame() def onServiceStarted(self, context: FunctionContext): # Get the name of the timestamp field for event_property in context.schema[context.streams[0]].event_schema.event_properties: if event_property.property_scope == \"HEADER_PROPERTY\": self.timestamp = event_property.runtime_name def onEvent(self, event: Dict[str, Any], streamId: str): # Convert the unix timestamp to datetime event[self.timestamp] = datetime.fromtimestamp(event[self.timestamp] / 1000) # Add every value of the event to the DataFrame self.df = pd.concat( [self.df, pd.DataFrame({key: [event[key]] for key in event.keys()}).set_index(self.timestamp)] ) def onServiceStopped(self): # Plot the first column of the Dataframe plt.figure(figsize=(10, 5)) plt.xlabel(self.timestamp) plt.ylabel(self.df.columns[0]) plt.plot(self.df.iloc[:, 0]) plt.show()
Now we can start the function. First we create an instance of the ExampleFunction
and insert the element_id
of the stream which data we want to consume. Then we have to register this function and we can start all functions by initializing the FunctionHandler
. (it's also possible to register multiple functions with .register(...).register(...)
)
example_function = ExampleFunction(\n FunctionDefinition(\n function_id=FunctionId(id=\"example-function\"),\n consumed_streams=[\"urn:streampipes.apache.org:eventstream:uPDKLI\"]\n )\n)\n\nregistration = Registration()\nregistration.register(example_function)\n\nfunction_handler = FunctionHandler(registration, client)\nfunction_handler.initializeFunctions()\nexample_function = ExampleFunction( FunctionDefinition( function_id=FunctionId(id=\"example-function\"), consumed_streams=[\"urn:streampipes.apache.org:eventstream:uPDKLI\"] ) ) registration = Registration() registration.register(example_function) function_handler = FunctionHandler(registration, client) function_handler.initializeFunctions()
2022-12-14 10:43:42,810 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:153] [_make_request] - Successfully retrieved all resources.\n2022-12-14 10:43:42,812 - streampipes.functions.function_handler - [INFO] - [function_handler.py:82] [initializeFunctions] - Using NatsBroker for <__main__.ExampleFunction object at 0x000001F2EF298D90>\n
The DataFrame
of the ExampleFunction
gets updated whenever a new event arrives. Let's test this by executing the cell below.
import asyncio\nfrom asyncio.exceptions import CancelledError\nfrom IPython.display import clear_output\n\nwhile True:\n clear_output(wait=True)\n display(example_function.df)\n try:\n await asyncio.sleep(1)\n except CancelledError:\n break\nimport asyncio from asyncio.exceptions import CancelledError from IPython.display import clear_output while True: clear_output(wait=True) display(example_function.df) try: await asyncio.sleep(1) except CancelledError: break mass_flow density volume_flow sensor_fault_flags temperature sensorId timestamp 2022-12-14 10:43:43.357 10.955496 47.546290 1.001985 False 44.993413 flowrate02 2022-12-14 10:43:44.371 6.499040 44.392069 2.034402 False 41.232352 flowrate02 2022-12-14 10:43:45.382 10.168300 41.192146 9.724287 False 46.812779 flowrate02 2022-12-14 10:43:46.395 10.849059 50.086308 5.832691 False 45.860412 flowrate02 2022-12-14 10:43:47.410 3.081855 47.254246 8.860531 False 50.505801 flowrate02 ... ... ... ... ... ... ... 2022-12-14 10:44:43.920 1.803572 41.978894 10.294002 False 47.820239 flowrate02 2022-12-14 10:44:44.932 1.967062 42.212883 3.237440 False 49.047258 flowrate02 2022-12-14 10:44:45.934 4.457819 47.561256 0.315024 False 40.223413 flowrate02 2022-12-14 10:44:46.949 8.745343 46.346891 7.439090 False 41.982529 flowrate02 2022-12-14 10:44:47.950 5.828744 47.679720 6.307405 False 42.100354 flowrate02
65 rows \u00d7 6 columns
The while
loop just displays the the DataFrame
every second until the cell is stopped. We could achieve the same result manually by executing example_function.df
repeatedly.
You can stop the functions whenever you want by executing the command below.
In\u00a0[\u00a0]: Copied!function_handler.disconnect()\nfunction_handler.disconnect()
2022-12-14 10:44:53,309 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:67] [disconnect] - Stopped connection to stream: urn:streampipes.apache.org:eventstream:uPDKLI\n
That's enough for this tutorial. Now you can try to write your own StreamPipesFunction
. All you need to do is creating a new class, implementing the 4 required methods and registering the function.
Want to see more exciting use cases you can achieve with StreamPipes functions in Python? Then don't hesitate and jump to our next tutorial on applying online machine learning algorithms to StreamPipes data streams with River.
How do you like this tutorial? We hope you like it and would love to receive some feedback from you. Just go to our GitHub discussion page and let us know your impression. We'll read and react to them all, we promise!
"},{"location":"tutorials/3-getting-live-data-from-the-streampipes-data-stream/#Getting-live-data-from-the-StreamPipes-data-stream","title":"Getting live data from the StreamPipes data stream\u00b6","text":"In the last tutorial (Extracting Data from the StreamPipes data lake) we learned how to extract the stored data from a StreamPipes data lake. This tutorial is about the StreamPipes data stream and shows how to get the live data from StreamPipes into Python. Therefore, we first create the client
instance as before.
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\nfrom streampipes.client import StreamPipesClient from streampipes.client.config import StreamPipesClientConfig from streampipes.client.credential_provider import StreamPipesApiKeyCredentials In\u00a0[\u00a0]: Copied!
# you can install all required dependecies for this tutorial by executing the following command\n%pip install river streampipes\n# you can install all required dependecies for this tutorial by executing the following command %pip install river streampipes In\u00a0[2]: Copied!
import os\n\nos.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\"\nos.environ[\"SP_API_KEY\"] = \"XXX\"\n\n# Use this if you work locally:\nos.environ[\"BROKER-HOST\"] = \"localhost\" \nos.environ[\"KAFKA-PORT\"] = \"9094\" # When using Kafka as message broker\nimport os os.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\" os.environ[\"SP_API_KEY\"] = \"XXX\" # Use this if you work locally: os.environ[\"BROKER-HOST\"] = \"localhost\" os.environ[\"KAFKA-PORT\"] = \"9094\" # When using Kafka as message broker In\u00a0[3]: Copied!
client_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(),\n host_address=\"localhost\",\n port=80,\n https_disabled=True,\n)\nclient = StreamPipesClient(client_config=client_config)\nclient_config = StreamPipesClientConfig( credential_provider=StreamPipesApiKeyCredentials(), host_address=\"localhost\", port=80, https_disabled=True, ) client = StreamPipesClient(client_config=client_config)
2023-01-27 16:04:24,784 - streampipes.client.client - [INFO] - [client.py:128] [_set_up_logging] - Logging successfully initialized with logging level INFO.\nIn\u00a0[4]: Copied!
client.dataStreamApi.all().to_pandas()\nclient.dataStreamApi.all().to_pandas()
2023-01-27 16:04:28,212 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:163] [_make_request] - Successfully retrieved all resources.\nOut[4]: element_id name description icon_url app_id includes_assets includes_locales internally_managed measurement_object index ... dom rev num_transport_protocols num_measurement_capability num_application_links num_included_assets num_connected_to num_category num_event_properties num_included_locales 0 sp:spdatastream:xboBFK Test None None False False True None 0 ... None 5-558c861debc745e1ebae29a266a8bdb9 1 0 0 0 0 0 7 0 1 urn:streampipes.apache.org:eventstream:Wgyrse Test File None None False False True None 0 ... None 4-66548b6b84287011b7cec0876ef82baf 1 0 0 0 0 0 2 0
2 rows \u00d7 22 columns
In\u00a0[5]: Copied!from river import cluster, compose, preprocessing\nfrom streampipes.function_zoo.river_function import OnlineML\nfrom streampipes.functions.utils.data_stream_generator import RuntimeType\n\nk_means = compose.Pipeline(\n (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")),\n (\"scale\", preprocessing.StandardScaler()),\n (\"k_means\", cluster.KMeans(n_clusters=2)),\n)\n\nclustering = OnlineML(\n client=client, stream_ids=[\"sp:spdatastream:xboBFK\"], model=k_means, prediction_type=RuntimeType.INTEGER.value\n)\nclustering.start()\nfrom river import cluster, compose, preprocessing from streampipes.function_zoo.river_function import OnlineML from streampipes.functions.utils.data_stream_generator import RuntimeType k_means = compose.Pipeline( (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")), (\"scale\", preprocessing.StandardScaler()), (\"k_means\", cluster.KMeans(n_clusters=2)), ) clustering = OnlineML( client=client, stream_ids=[\"sp:spdatastream:xboBFK\"], model=k_means, prediction_type=RuntimeType.INTEGER.value ) clustering.start()
2023-01-27 16:04:35,599 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:163] [_make_request] - Successfully retrieved all resources.\n2023-01-27 16:04:35,599 - streampipes.functions.function_handler - [INFO] - [function_handler.py:64] [initializeFunctions] - Create output data stream \"sp:spdatastream:cwKPoo\" for the function \"65cf8b86-bcdf-433e-a1c7-3e920eab55d0\"\n2023-01-27 16:04:37,766 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:163] [_make_request] - Successfully retrieved all resources.\n2023-01-27 16:04:37,767 - streampipes.functions.function_handler - [INFO] - [function_handler.py:78] [initializeFunctions] - Using NatsBroker for RiverFunction\n2023-01-27 16:04:37,791 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:48] [_makeConnection] - Connected to NATS at localhost:4222\n2023-01-27 16:04:37,791 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:48] [_makeConnection] - Connected to NATS at localhost:4222\n2023-01-27 16:04:37,792 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:58] [createSubscription] - Subscribed to stream: sp:spdatastream:xboBFK\nIn\u00a0[6]: Copied!
clustering.set_learning(False)\nclustering.set_learning(False) In\u00a0[\u00a0]: Copied!
clustering.stop()\nclustering.stop()
2023-01-27 16:04:57,303 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:82] [disconnect] - Stopped connection to stream: sp:spdatastream:xboBFK\n2023-01-27 16:04:57,304 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:82] [disconnect] - Stopped connection to stream: sp:spdatastream:cwKPoo\nIn\u00a0[\u00a0]: Copied!
import pickle\nfrom river import compose, tree\nfrom streampipes.function_zoo.river_function import OnlineML\nfrom streampipes.functions.utils.data_stream_generator import RuntimeType\n\nhoeffding_tree = compose.Pipeline(\n (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")),\n (\"hoeffding_tree\", tree.HoeffdingTreeRegressor(grace_period=5)),\n)\n\n\ndef draw_tree(self, event, streamId):\n\"\"\"Draw the tree and save the image.\"\"\"\n if self.learning:\n if self.model[1].n_nodes != None:\n self.model[1].draw().render(\"hoeffding_tree\", format=\"png\", cleanup=True)\n\n\ndef save_model(self):\n\"\"\"Save the trained model.\"\"\"\n with open(\"hoeffding_tree.pkl\", \"wb\") as f:\n pickle.dump(self.model, f)\n\n\nregressor = OnlineML(\n client=client,\n stream_ids=[\"sp:spdatastream:xboBFK\"],\n model=hoeffding_tree,\n prediction_type=RuntimeType.FLOAT.value,\n supervised=True,\n target_label=\"temperature\",\n on_event=draw_tree,\n on_stop=save_model,\n)\nregressor.start()\nimport pickle from river import compose, tree from streampipes.function_zoo.river_function import OnlineML from streampipes.functions.utils.data_stream_generator import RuntimeType hoeffding_tree = compose.Pipeline( (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")), (\"hoeffding_tree\", tree.HoeffdingTreeRegressor(grace_period=5)), ) def draw_tree(self, event, streamId): \"\"\"Draw the tree and save the image.\"\"\" if self.learning: if self.model[1].n_nodes != None: self.model[1].draw().render(\"hoeffding_tree\", format=\"png\", cleanup=True) def save_model(self): \"\"\"Save the trained model.\"\"\" with open(\"hoeffding_tree.pkl\", \"wb\") as f: pickle.dump(self.model, f) regressor = OnlineML( client=client, stream_ids=[\"sp:spdatastream:xboBFK\"], model=hoeffding_tree, prediction_type=RuntimeType.FLOAT.value, supervised=True, target_label=\"temperature\", on_event=draw_tree, on_stop=save_model, ) regressor.start() In\u00a0[9]: Copied!
regressor.set_learning(False)\nregressor.set_learning(False) In\u00a0[\u00a0]: Copied!
regressor.stop()\nregressor.stop() In\u00a0[\u00a0]: Copied!
import pickle\nfrom river import compose, tree\nfrom streampipes.function_zoo.river_function import OnlineML\nfrom streampipes.functions.utils.data_stream_generator import RuntimeType\n\ndecision_tree = compose.Pipeline(\n (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")),\n (\"decision_tree\", tree.ExtremelyFastDecisionTreeClassifier(grace_period=5)),\n)\n\n\ndef draw_tree(self, event, streamId):\n\"\"\"Draw the tree and save the image.\"\"\"\n if self.learning:\n if self.model[1].n_nodes != None:\n self.model[1].draw().render(\"decicion_tree\", format=\"png\", cleanup=True)\n\n\ndef save_model(self):\n\"\"\"Save the trained model.\"\"\"\n with open(\"decision_tree.pkl\", \"wb\") as f:\n pickle.dump(self.model, f)\n\n\nclassifier = OnlineML(\n client=client,\n stream_ids=[\"sp:spdatastream:xboBFK\"],\n model=decision_tree,\n prediction_type=RuntimeType.BOOLEAN.value,\n supervised=True,\n target_label=\"sensor_fault_flags\",\n on_event=draw_tree,\n on_stop=save_model,\n)\nclassifier.start()\nimport pickle from river import compose, tree from streampipes.function_zoo.river_function import OnlineML from streampipes.functions.utils.data_stream_generator import RuntimeType decision_tree = compose.Pipeline( (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")), (\"decision_tree\", tree.ExtremelyFastDecisionTreeClassifier(grace_period=5)), ) def draw_tree(self, event, streamId): \"\"\"Draw the tree and save the image.\"\"\" if self.learning: if self.model[1].n_nodes != None: self.model[1].draw().render(\"decicion_tree\", format=\"png\", cleanup=True) def save_model(self): \"\"\"Save the trained model.\"\"\" with open(\"decision_tree.pkl\", \"wb\") as f: pickle.dump(self.model, f) classifier = OnlineML( client=client, stream_ids=[\"sp:spdatastream:xboBFK\"], model=decision_tree, prediction_type=RuntimeType.BOOLEAN.value, supervised=True, target_label=\"sensor_fault_flags\", on_event=draw_tree, on_stop=save_model, ) classifier.start() In\u00a0[12]: Copied!
classifier.set_learning(False)\nclassifier.set_learning(False) In\u00a0[\u00a0]: Copied!
classifier.stop()\nclassifier.stop()
How do you like this tutorial? We hope you like it and would love to receive some feedback from you. Just go to our GitHub discussion page and let us know your impression. We'll read and react to them all, we promise!
"},{"location":"tutorials/4-using-online-machine-learning-on-a-streampipes-data-stream/#Using-Online-Machine-Learning-on-a-StreamPipes-data-stream","title":"Using Online Machine Learning on a StreamPipes data stream\u00b6","text":"The last tutorial (Getting live data from the StreamPipes data stream) showed how we can connect to a data stream, and it would be possible to use Online Machine Learning with this approach and train a model with the incoming events at the onEvent
method. However, the StreamPipes client also provides an easier way to do this with the use of the River library for Online Machine Learning. We will have a look at this now.
After we configured the client as usual, we can start with the new part. The approach is straight forward and you can start with the ML part in just 3 steps:
OnlineML
wrapper to fit to your model and insert the client and required data stream ids.A StreamPipesFunction is then started, which trains the model for each new event. It also creates an output data stream which will send the prediction of the model back to StreamPipes. This output stream can be seen when creating a new pipeline and can be used like every other data source. So you can use it in a pipeline and save the predictions in a Data Lake. You can also stop and start the training with the method set_learning
. To stop the whole function use the stop
methode and if you want to delete the output stream entirely, you can go to the Pipeline Element Installer
in StreamPipes and uninstall it.
Now let's take a look at some examples. If you want to execute the examples below you have to create an adapter for the Machine Data Simulator
, select the flowrate
sensor and insert the stream id of this stream.
RAISES | +DESCRIPTION | +
---|---|
+
+ AttributeError:
+
+ |
+
+
+
+ In case an invalid configuration of the |
+
Examples:
from streampipes.client import StreamPipesClient
from streampipes.client.config import StreamPipesClientConfig
diff --git a/docs-python/dev/scripts/gen_ref_pages/index.html b/docs-python/dev/scripts/gen_ref_pages/index.html
index 93d2c8d04..fcc084c5e 100644
--- a/docs-python/dev/scripts/gen_ref_pages/index.html
+++ b/docs-python/dev/scripts/gen_ref_pages/index.html
@@ -3168,7 +3168,7 @@ Gen ref pages
init_mathjax();
-
+
@@ -3190,7 +3190,7 @@ Gen ref pages
-
+
@@ -3217,7 +3217,7 @@ Gen ref pages
-
+
@@ -3244,7 +3244,7 @@ Gen ref pages
-
+
@@ -3271,7 +3271,7 @@ Gen ref pages
-
+
@@ -3344,7 +3344,7 @@ Gen ref pages
-
+
diff --git a/docs-python/dev/search/search_index.json b/docs-python/dev/search/search_index.json
index 277e9165f..b80f14eb0 100644
--- a/docs-python/dev/search/search_index.json
+++ b/docs-python/dev/search/search_index.json
@@ -1 +1 @@
-{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"\ud83c\udfe1 Home","text":"StreamPipes is a self-service (Industrial) IoT toolbox to enable non-technical users to connect, analyze and explore IoT data streams. Dependency issue with StreamPipes Python 0.92.0
In StreamPipes Python 0.92.0
there is a problem with the required dependencies. Pydantic has recently released the new version 2.0
with many exciting improvements, but also some breaking changes. Unfortunately, we didn't limit our requirements strictly enough, so yydantic 2.0
is installed together with streampipes, which is not (yet) compatible. To fix this bug, simply run the following command after installing streampipes, or adjust your dependencies accordingly:
pip install \"pydantic<2.0\" \"pydantic_core<2.0\"\n
Apache StreamPipes for Python \ud83d\udc0d Apache StreamPipes meets Python! We are working highly motivated on a Python library to interact with StreamPipes. In this way, we would like to unite the power of StreamPipes to easily connect to and read from different data sources, especially in the IoT domain, and the amazing universe of data analytics libraries in Python.
StreamPipes Python is in beta
The current version of this Python library is still a beta version. This means that it is still heavily under development, which may result in frequent and extensive API changes, unstable behavior, etc.
"},{"location":"#quickstart","title":"\u26a1\ufe0f Quickstart","text":"As a quick example, we demonstrate how to set up and configure a StreamPipes client. In addition, we will get the available data lake measures out of StreamPipes.
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nconfig = StreamPipesClientConfig(\n credential_provider = StreamPipesApiKeyCredentials(\n username = \"test@streampipes.apache.org\",\n api_key = \"DEMO-KEY\",\n ),\n host_address = \"localhost\",\n https_disabled = True,\n port = 80\n)\n\nclient = StreamPipesClient(client_config=config)\n\n# get all available datat lake measures\nmeasures = client.dataLakeMeasureApi.all()\n\n# get amount of retrieved measures\nlen(measures)\n
Output: 1\n
# inspect the data lake measures as pandas dataframe\nmeasures.to_pandas()\n
Output:
measure_name timestamp_field ... pipeline_is_running num_event_properties\n0 test s0::timestamp ... False 2\n[1 rows x 6 columns]\n
Alternatively, you can provide your credentials via environment variables. Simply define your credential provider as follows: from streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nStreamPipesApiKeyCredentials()\n
This requires to set the following environment variables: SP_API_KEY
and SP_USERNAME
username
is always the username that is used to log in into StreamPipes.
How to get your StreamPipes API key The api_key
can be generated within the UI as demonstrated below:
"},{"location":"getting-started/developing/","title":"Developing & Contributing","text":""},{"location":"getting-started/developing/#development-guide","title":"\ud83d\udcd6 Development Guide","text":"This document describes how to easily set up your local dev environment to work on StreamPipes Python \ud83d\udc0d.
"},{"location":"getting-started/developing/#first-steps","title":"\ud83d\ude80 First Steps","text":"1) Set up your Python environment
Create a virtual Python environment using a tool of your choice. To manage dependencies, we use Poetry, so please install poetry in your local environment, e.g. via
pip install poetry\n
Once poetry is installed you can simply finalize your Python environment by running:
poetry install --with dev,stubs # install everything that is required for the development\npoetry install --with docs # install everything to work with the documentation\npoetry install --with dev,stubs,docs # install all optional dependencies related to development\n
2) Install pre-commit hook
The pre-commit hook is run before every commit and takes care about code style, linting, type hints, import sorting, etc. It will stop your commit in case the changes do not apply the expected format. Always check to have the recent version of the pre-commit hook installed otherwise the CI build might fail. If you are interested, you can have a deeper look on the underlying library: pre-commit.
pre-commit install\n
The definition of the pre-commit hook can be found in .pre-commit-config.yaml. "},{"location":"getting-started/developing/#conventions","title":"\ud83d\udc4f Conventions","text":"Below we list some conventions that we have agreed on for creating StreamPipes Python. Please comply to them when you plan to contribute to this project. If you have any other suggestions or would like to discuss them, we would be happy to hear from you on our mailing list dev@streampipes.apache.org or in our discussions on GitHub.
1) Use numpy
style for Python docstrings \ud83d\udcc4 Please stick to the numpy
style when writing docstrings, as we require this for generating our documentation.
2) Provide tests \u2705 We are aiming for broad test coverage for the Python package and have therefore set a requirement of at least 90% unit test coverage. Therefore, please remember to write (unit) tests already during development. If you have problems with writing tests, don't hesitate to ask us for help directly in the PR or even before that via our mailing list (see above).
3) Build a similar API as the Java client provides \ud83d\udd04 Whenever possible, please try to develop the API of the Python library the same as the Java client or Java SDK. By doing so, we would like to provide a consistent developer experience and the basis for automated testing in the future.
"},{"location":"getting-started/developing/#dependency-management","title":"\ud83d\udce6 Dependency Management","text":"In case you want to add a new dependency to StreamPipes you can use the following command:
poetry add <dep-name>\n
If the dependency is only required for development purpose or the documentation, please stick to one the following:
poetry add <dep-name> --group dev\npoetry add <dep-name> --group stubs\npoetry add <dep-name> --group docs\n
In case you want to regenerate the poetry lock file, e.g., in case you manually updated the pyproject.toml
, the following command should be used:
poetry lock --no-update\n
After that, you should install the current version of the poetry lock file to keep your local environment consistent (see command above.)
"},{"location":"getting-started/developing/#documentation","title":"\ud83d\udcdaDocumentation","text":"To build our documentation, we use Materials for MkDocs. All files can be found within the docs
directory. To pre-view your local version of the documentation, you can use the following command:
make livedoc\n
"},{"location":"getting-started/developing/#roadmap","title":"\ud83d\ude80 Roadmap","text":"Broadly speaking, we plan to expand or add new aspects/functionality to the library where we are focusing on the following:
- increase coverage of StreamPipes API \ud83d\udd17
- build a comprehensive function zoo \ud83d\udc18
- support more messaging broker \ud83d\udcec
- possibility to build pipeline elements \ud83d\udd27
In case you want to have a more detailed look on what we are currently planning, have a look at our open issues(more short-term driven).
Of course, contributions are always highly appreciated \ud83d\udd2e
Stay tuned!
"},{"location":"getting-started/developing/#contributing","title":"\ud83d\udc68\u200d\ud83d\udcbb Contributing","text":"Before opening a pull request, review the Get Involved page. It lists information that is required for contributing to StreamPipes.
When you contribute code, you affirm that the contribution is your original work and that you license the work to the project under the project's open source license. Whether or not you state this explicitly, by submitting any copyrighted material via pull request, email, or other means you agree to license the material under the project's open source license and warrant that you have the legal authority to do so.
"},{"location":"getting-started/first-steps/","title":"First Steps","text":""},{"location":"getting-started/first-steps/#installation","title":"\ud83d\udcda Installation","text":"The StreamPipes Python library is meant to work with Python 3.8 and above. Installation can be done via pip
: You can install the latest development version from GitHub, as so:
pip install streampipes\n\n# if you want to have the current development state you can also execute\npip install git+https://github.com/apache/streampipes.git#subdirectory=streampipes-client-python\n# the corresponding documentation can be found here: https://streampipes.apache.org/docs/docs/python/dev/\n
"},{"location":"getting-started/first-steps/#setting-up-streampipes","title":"\u2b06\ufe0f Setting up StreamPipes","text":"When working with the StreamPipes Python library it is inevitable to have a running StreamPipes instance to connect and interact with. In case you don't have a running instance at hand, you can easily set up one on your local machine. Hereby you need to consider that StreamPipes supports different message broker (e.g., Kafka, NATS). We will demonstrate below how you can easily set up StreamPipes for both supported message brokers.
"},{"location":"getting-started/first-steps/#start-streampipes-via-docker-compose","title":"\ud83d\udc33 Start StreamPipes via Docker Compose","text":"The easiest and therefore recommend way to get StreamPipes started is by using docker compose. Therefore, you need Docker running. You can check if Docker is ready on your machine by executing.
docker ps\n
If this results in an output similar to the following, Docker is ready to continue. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES\n... ... ... ... ... ... ...\n
Otherwise, you need to start docker first. Please read the full guide on how to start StreamPipes with docker compose
here."},{"location":"getting-started/first-steps/#setup-streampipes-with-nats-as-message-broker","title":"Setup StreamPipes with NATS as message broker","text":"The following shows how you can set up a StreamPipes instance that uses NATS as messaging layer. So in this scenario, we will go with docker-compose.nats.yml
. Thereby, when running locally, we need to add the following port mapping entry to services.nats.ports
:
- 4222:4222\n
After this modification is applied, StreamPipes can simply be started with this command:
docker-compose -f docker-compose.nats.yml up -d\n
Once all services are started, you can access StreamPipes via http://localhost
.
"},{"location":"getting-started/first-steps/#setup-streampipes-with-kafka-as-message-broker","title":"Setup StreamPipes with Kafka as message broker","text":"Alternatively, you can use docker-compose.yml
to start StreamPipes with Kafka as messaging layer. When running locally we have to modify services.kafka.environment
and add the ports to services.kafka.ports
:
environment:\nKAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,OUTSIDE:PLAINTEXT\nKAFKA_ADVERTISED_LISTENERS: PLAINTEXT://:9092,OUTSIDE://localhost:9094\nKAFKA_LISTENERS: PLAINTEXT://:9092,OUTSIDE://:9094\n...\nports:\n- 9094:9094\n
Then, you need to execute the following command: docker-compose -f docker-compose.yml up -d\n
Once all services are started, you can access StreamPipes via http://localhost
.
In case you want to have more control over your StreamPipes setup, you might take a look at our deployment CLI.
Have fun discovering StreamPipes and our Python library \ud83d\ude80
"},{"location":"getting-started/quickstart/","title":"Quickstart","text":""},{"location":"getting-started/quickstart/#quickstart","title":"\u26a1\ufe0f Quickstart","text":"As a quick example, we demonstrate how to set up and configure a StreamPipes client. In addition, we will get the available data lake measures out of StreamPipes.
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nconfig = StreamPipesClientConfig(\n credential_provider = StreamPipesApiKeyCredentials(\n username = \"test@streampipes.apache.org\",\n api_key = \"DEMO-KEY\",\n ),\n host_address = \"localhost\",\n https_disabled = True,\n port = 80\n)\n\nclient = StreamPipesClient(client_config=config)\n\n# get all available datat lake measures\nmeasures = client.dataLakeMeasureApi.all()\n\n# get amount of retrieved measures\nlen(measures)\n
Output: 1\n
# inspect the data lake measures as pandas dataframe\nmeasures.to_pandas()\n
Output:
measure_name timestamp_field ... pipeline_is_running num_event_properties\n0 test s0::timestamp ... False 2\n[1 rows x 6 columns]\n
Alternatively, you can provide your credentials via environment variables. Simply define your credential provider as follows: from streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nStreamPipesApiKeyCredentials()\n
This requires to set the following environment variables: SP_API_KEY
and SP_USERNAME
username
is always the username that is used to log in into StreamPipes. The api_key
can be generated within the UI as demonstrated below:
"},{"location":"reference/client/client/","title":"Client","text":"Implementation of the StreamPipes client. The client is designed as the central point of interaction with the StreamPipes API and provides all functionalities to communicate with the API.
"},{"location":"reference/client/client/#streampipes.client.client.StreamPipesClient","title":"StreamPipesClient(client_config, logging_level=logging.INFO)
","text":"The client to connect to StreamPipes.
This is the central point of contact with StreamPipes and provides all the functionalities to interact with it.
The client provides so-called \"endpoints\" each of which refers to an endpoint of the StreamPipes API, e.g. .dataLakeMeasureApi
. An endpoint provides the actual methods to interact with StreamPipes API.
PARAMETER DESCRIPTION client_config
Configures the client to connect properly to the StreamPipes instance.
TYPE: StreamPipesClientConfig
logging_level
Influences the log messages emitted by the StreamPipesClient
TYPE: Optional[int]
DEFAULT: logging.INFO
ATTRIBUTE DESCRIPTION dataLakeMeasureApi
Instance of the data lake measure endpoint
TYPE: DataLakeMeasureEndpoint
dataStreamApi
Instance of the data stream endpoint
TYPE: DataStreamEndpoint
Examples:
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
client_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(\n username=\"test-user\",\n api_key=\"api-key\"\n ),\n host_address=\"localhost\",\n https_disabled=True\n)\n
The following way of instantiating a client instance is intended to be consistent with the StreamPipes Java client.
client = StreamPipesClient.create(client_config=client_config)\n
If you prefer a more pythonic way, you can simply write:
client = StreamPipesClient(client_config=client_config)\n
To interact with an endpoint:
data_lake_measures = client.dataLakeMeasureApi.all()\n
To inspect returned data as a pandas dataframe:
data_lake_measures.to_pandas()\n#\n# measure_name timestamp_field ... pipeline_is_running num_event_properties\n# 0 test s0::timestamp ... False 2\n# [1 rows x 6 columns]\n
"},{"location":"reference/client/client/#streampipes.client.client.StreamPipesClient.base_api_path","title":"base_api_path: str
property
","text":"Constructs the basic API URL from the given client_config
.
RETURNS DESCRIPTION base_api_path
basic API path of the connected StreamPipes instance
TYPE: str
"},{"location":"reference/client/client/#streampipes.client.client.StreamPipesClient.http_headers","title":"http_headers: Dict[str, str]
property
","text":"Returns the HTTP headers used for all requests.
The HTTP headers are composed of the authentication headers supplied by the credential provider and additional required headers (currently this is only the application header).
RETURNS DESCRIPTION http_headers
header information for HTTP requests as string key-value pairs.
TYPE: Dict[str, str]
"},{"location":"reference/client/client/#streampipes.client.client.StreamPipesClient.create","title":"create(client_config, logging_level=logging.INFO)
classmethod
","text":"Returns an instance of the StreamPipesPythonClient
.
Provides consistency to the StreamPipes Java client.
PARAMETER DESCRIPTION client_config
Configures the client to connect properly to the StreamPipes instance.
TYPE: StreamPipesClientConfig
logging_level
Influences the log messages emitted by the StreamPipesClient
.
TYPE: int
DEFAULT: logging.INFO
RETURNS DESCRIPTION StreamPipesClient
"},{"location":"reference/client/client/#streampipes.client.client.StreamPipesClient.describe","title":"describe()
","text":"Prints a short description of the connected StreamPipes instance and the available resources to the console.
RETURNS DESCRIPTION None
Examples:
client.describe()\n
Output: Hi there!\nYou are connected to a StreamPipes instance running at http://localhost:80.\nThe following StreamPipes resources are available with this client:\n6x DataStreams\n1x DataLakeMeasures\n
"},{"location":"reference/client/config/","title":"Config","text":"Configuration class for the StreamPipes client.
"},{"location":"reference/client/config/#streampipes.client.config.StreamPipesClientConfig","title":"StreamPipesClientConfig
dataclass
","text":"Configure the StreamPipes client in accordance to the actual StreamPipes instance to connect to.
An instance is provided to the StreamPipesClient
to configure it properly.
PARAMETER DESCRIPTION credential_provider
Provides the credentials to authenticate with the StreamPipes API.
TYPE: CredentialProvider
host_address
Host address of the StreamPipes instance to connect to. Should be provided without the protocol/scheme, e.g. as localhost
or streampipes.xyz
.
TYPE: str
https_disabled
Determines whether https is used to connect to StreamPipes.
TYPE: Optional[bool]
DEFAULT: False
port
Specifies the port under which the StreamPipes API is available, e.g., 80
(with http) or 443
(with https)
TYPE: Optional[int]
DEFAULT: 80
Examples:
see StreamPipesClient
"},{"location":"reference/client/credential_provider/","title":"Credential provider","text":"Implementation of credential providers. A credential provider supplies the specified sort of credentials in the appropriate HTTP header format. The headers are then used by the client to connect to StreamPipes.
"},{"location":"reference/client/credential_provider/#streampipes.client.credential_provider.CredentialProvider","title":"CredentialProvider
","text":" Bases: ABC
Abstract implementation of a credential provider. Must be inherited by all credential providers.
"},{"location":"reference/client/credential_provider/#streampipes.client.credential_provider.CredentialProvider.make_headers","title":"make_headers(http_headers=None)
","text":"Creates the HTTP headers for the specific credential provider.
Concrete authentication headers must be defined in the implementation of a credential provider.
PARAMETER DESCRIPTION http_headers
Additional HTTP headers the generated headers are extended by.
TYPE: Optional[Dict[str, str]]
DEFAULT: None
RETURNS DESCRIPTION https_headers
Dictionary with header information as string key-value pairs. Contains all pairs given as parameter plus the header pairs for authentication determined by the credential provider.
TYPE: Dict[str, str]
"},{"location":"reference/client/credential_provider/#streampipes.client.credential_provider.StreamPipesApiKeyCredentials","title":"StreamPipesApiKeyCredentials(username=None, api_key=None)
","text":" Bases: CredentialProvider
A credential provider that allows authentication via a StreamPipes API Token.
The required token can be generated via the StreamPipes UI (see the description on our start-page.
Both parameters can either be passed as arguments or remain unset. If they are not passed, they are retrieved from environment variables:
SP_USERNAME
is expected to contain the username SP_API_KEY
is expected to contain the API key
PARAMETER DESCRIPTION username
The username to which the API token is granted, e.g., demo-user@streampipes.apche.org
. If not passed, the username is retrieved from environment variable SP_USERNAME
.
TYPE: Optional[str]
DEFAULT: None
api_key
The StreamPipes API key as it is displayed in the UI. If not passed, the api key is retrieved from environment variable SP_API_KEY
TYPE: Optional[str]
DEFAULT: None
Examples:
see StreamPipesClient
"},{"location":"reference/client/credential_provider/#streampipes.client.credential_provider.StreamPipesApiKeyCredentials.from_env","title":"from_env(username_env, api_key_env)
classmethod
","text":"DEPRECATED - use the class constructor instead
Returns an api key provider parameterized via environment variables.
PARAMETER DESCRIPTION username_env
Name of the environment variable that contains the username
TYPE: str
api_key_env
Name of the environment variable that contains the API key
TYPE: str
RETURNS DESCRIPTION StreamPipesApiKeyCredentials
RAISES DESCRIPTION KeyError
If one of the environment variables is not defined
"},{"location":"reference/endpoint/endpoint/","title":"Endpoint","text":"General implementation for an endpoint. Provided classes and assets are aimed to be used for developing endpoints. An endpoint provides all options to communicate with ad dedicated part of StreamPipes in a handy way.
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.APIEndpoint","title":"APIEndpoint
","text":" Bases: Endpoint
Abstract implementation of an API endpoint.
Serves as template for all endpoints of the StreamPipes API. By design, endpoints are only instantiated within the __init__
method of the StreamPipesClient.
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.APIEndpoint.all","title":"all()
","text":"Get all resources of this endpoint provided by the StreamPipes API.
Results are provided as an instance of a ResourceContainer
that allows to handle the returned resources in a comfortable and pythonic way.
RETURNS DESCRIPTION container
container element that bundles the returned resources
TYPE: ResourceContainer
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.APIEndpoint.build_url","title":"build_url()
","text":"Builds the endpoint's URL of the API path.
RETURNS DESCRIPTION url
The URL of the endpoint
TYPE: str
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.APIEndpoint.get","title":"get(identifier, **kwargs)
","text":"Queries the specified resource from the API endpoint.
PARAMETER DESCRIPTION identifier
The identifier of the resource to be queried.
TYPE: str
RETURNS DESCRIPTION resource
The specified resource as an instance of the corresponding model class.
TYPE: Resource
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.APIEndpoint.post","title":"post(resource)
","text":"Allows to post a resource to the StreamPipes API.
PARAMETER DESCRIPTION resource
The resource to be posted.
TYPE: Resource
RETURNS DESCRIPTION None
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.Endpoint","title":"Endpoint(parent_client)
","text":" Bases: ABC
Abstract implementation of a StreamPipes endpoint.
Serves as template for all endpoints used for interaction with a StreamPipes instance. By design, endpoints are only instantiated within the __init__
method of the StreamPipesClient.
PARAMETER DESCRIPTION parent_client
This parameter expects the instance of StreamPipesClient
the endpoint is attached to.
TYPE: StreamPipesClient
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.MessagingEndpoint","title":"MessagingEndpoint(parent_client)
","text":" Bases: Endpoint
Abstract implementation of a StreamPipes messaging endpoint.
Serves as template for all endpoints used for interacting with the StreamPipes messaging layer directly. Therefore, they need to provide the functionality to talk with the broker system running in StreamPipes. By design, endpoints are only instantiated within the __init__
method of the StreamPipesClient.
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.MessagingEndpoint.broker","title":"broker: Broker
property
writable
","text":"Defines the broker instance that is used to connect to StreamPipes' messaging layer.
This instance enables the client to authenticate to the broker used in the target StreamPipes instance, to consume messages from and to write messages to the broker.
RAISES DESCRIPTION MessagingEndpointNotConfiguredError
If the endpoint is used before the broker instance is set via configure()
RETURNS DESCRIPTION broker
The broker instance to be used to communicate with StreamPipes' messaging layer.
TYPE: Broker
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.MessagingEndpoint.configure","title":"configure(broker)
","text":"Configures the message endpoint by setting the broker instance to be used.
This configuration step is required before the endpoint can be actually used. The based broker
instance is passed to an internal property
PARAMETER DESCRIPTION broker
Broker instance that should be used for this endpoint
TYPE: Broker
RETURNS DESCRIPTION None
"},{"location":"reference/endpoint/exceptions/","title":"Exceptions","text":"Custom exceptions dedicated for the endpoints module
"},{"location":"reference/endpoint/exceptions/#streampipes.endpoint.exceptions.MessagingEndpointNotConfiguredError","title":"MessagingEndpointNotConfiguredError(endpoint_name)
","text":" Bases: Exception
Exception that indicates that an instance of a messaging endpoint has not been configured.
This error occurs when an instance of a messaging endpoint is used before the broker instance to be used is configured by passing it to the configure()
method.
PARAMETER DESCRIPTION endpoint_name
The name of the endpoint that caused the error
TYPE: str
"},{"location":"reference/endpoint/api/data_lake_measure/","title":"Data lake measure","text":"Specific implementation of the StreamPipes API's data lake measure endpoints. This endpoint allows to consume data stored in StreamPipes' data lake.
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.DataLakeMeasureEndpoint","title":"DataLakeMeasureEndpoint
","text":" Bases: APIEndpoint
Implementation of the DataLakeMeasure endpoint.
This endpoint provides an interface to all data stored in the StreamPipes data lake.
Consequently, it allows querying metadata about available data sets (see all()
method). The metadata is returned as an instance of DataLakeMeasures
.
In addition, the endpoint provides direct access to the data stored in the data laka by querying a specific data lake measure using the get()
method.
Examples:
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
client_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(username=\"test-user\", api_key=\"api-key\"),\n host_address=\"localhost\",\n port=8082,\n https_disabled=True\n)\nclient = StreamPipesClient.create(client_config=client_config)\n
# get all existing data lake measures from StreamPipes\ndata_lake_measures = client.dataLakeMeasureApi.all()\n\n# let's take a look how many we got\nlen(data_lake_measures)\n
5\n
# Retrieve a specific data lake measure as a pandas DataFrame\nflow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\").to_pandas()\nflow_rate_pd\n
time density mass_flow sensorId sensor_fault_flags temperature volume_flow\n0 2023-02-24T16:19:41.472Z 50.872730 3.309556 flowrate02 False 44.448483 5.793138\n1 2023-02-24T16:19:41.482Z 47.186588 5.608580 flowrate02 False 40.322033 0.058015\n2 2023-02-24T16:19:41.493Z 46.735321 7.692881 flowrate02 False 49.239639 10.283526\n3 2023-02-24T16:19:41.503Z 40.169796 3.632898 flowrate02 False 49.933754 6.893441\n4 2023-02-24T16:19:41.513Z 49.635124 0.711260 flowrate02 False 50.106617 2.999871\n.. ... ... ... ... ... ... ...\n995 2023-02-24T16:19:52.927Z 50.057495 1.740114 flowrate02 False 46.558231 1.818237\n996 2023-02-24T16:19:52.94Z 41.038895 7.211723 flowrate02 False 48.048622 2.127493\n997 2023-02-24T16:19:52.952Z 45.837013 7.770180 flowrate02 False 48.188026 7.892062\n998 2023-02-24T16:19:52.965Z 43.389065 4.458602 flowrate02 False 48.280899 5.733892\n999 2023-02-24T16:19:52.977Z 44.056030 2.592060 flowrate02 False 47.505951 4.260697\n
As you can see, the returned amount of rows per default is 1000
. We can modify this behavior by passing the limit
paramter.
flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", limit=10).to_pandas()\nlen(flow_rate_pd)\n
10\n
If we are only interested in the values for density
, columns
allows us to select the columns to be returned:
flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", columns='density', limit=3).to_pandas()\nflow_rate_pd\n
time density\n0 2023-02-24T16:19:41.472Z 50.872730\n1 2023-02-24T16:19:41.482Z 47.186588\n2 2023-02-24T16:19:41.493Z 46.735321\n
This is only a subset of the available query parameters, find them at MeasurementGetQueryConfig.
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.DataLakeMeasureEndpoint.get","title":"get(identifier, **kwargs)
","text":"Queries the specified data lake measure from the API.
By default, the maximum number of returned records is 1000. This behaviour can be influenced by passing the parameter limit
with a different value (see MeasurementGetQueryConfig).
PARAMETER DESCRIPTION identifier
The identifier of the data lake measure to be queried.
TYPE: str
**kwargs
keyword arguments can be used to provide additional query parameters. The available query parameters are defined by the MeasurementGetQueryConfig.
TYPE: Optional[Dict[str, Any]]
DEFAULT: {}
RETURNS DESCRIPTION measurement
the specified data lake measure
TYPE: DataLakeMeasures
Examples:
see directly at DataLakeMeasureEndpoint.
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.MeasurementGetQueryConfig","title":"MeasurementGetQueryConfig
","text":" Bases: BaseModel
Config class describing the parameters of the get()
method for measurements.
This config class is used to validate the provided query parameters for the GET endpoint of measurements. Additionally, it takes care of the conversion to a proper HTTP query string. Thereby, parameter names are adapted to the naming of the StreamPipes API, for which Pydantic aliases are used.
ATTRIBUTE DESCRIPTION columns
A comma separated list of column names (e.g., time,value
) If provided, the returned data only consists of the given columns. Please be aware that the column time
as an index is always included.
TYPE: Optional[List[str]]
end_date
Restricts queried data to be younger than the specified time.
TYPE: Optional[datetime]
limit
Amount of records returned at maximum (default: 1000
) This needs to be at least 1
TYPE: Optional[int]
offset
Offset to be applied to returned data This needs to be at least 0
TYPE: Optional[int]
order
Ordering of query results Allowed values: ASC
and DESC
(default: ASC
)
TYPE: Optional[str]
page_no
Page number used for paging operation This needs to be at least 1
TYPE: Optional[int]
start_date
Restricts queried data to be older than the specified time
TYPE: Optional[datetime]
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.MeasurementGetQueryConfig.Config","title":"Config
","text":"Pydantic Config class
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.MeasurementGetQueryConfig.build_query_string","title":"build_query_string()
","text":"Builds a HTTP query string for the config.
This method returns an HTTP query string for the invoking config. It follows the following structure ?param1=value1¶m2=value2...
. This query string is not an entire URL, instead it needs to appended to an API path.
RETURNS DESCRIPTION query_param_string
HTTP query params string (?param1=value1¶m2=value2...
)
TYPE: str
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.StreamPipesQueryValidationError","title":"StreamPipesQueryValidationError
","text":" Bases: Exception
A custom exception to be raised when the validation of query parameter causes an error.
"},{"location":"reference/endpoint/api/data_stream/","title":"Data stream","text":"Specific implementation of the StreamPipes API's data stream endpoints.
"},{"location":"reference/endpoint/api/data_stream/#streampipes.endpoint.api.data_stream.DataStreamEndpoint","title":"DataStreamEndpoint
","text":" Bases: APIEndpoint
Implementation of the DataStream endpoint.
Consequently, it allows querying metadata about available data streams (see all()
method). The metadata is returned as an instance of DataStreams
.
Examples:
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nclient_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(username=\"test-user\", api_key=\"api-key\"),\n host_address=\"localhost\",\n port=8082,\n https_disabled=True\n)\nclient = StreamPipesClient.create(client_config=client_config)\n
# let's get all existing data streams in StreamPipes\ndata_streams = client.dataStreamApi.all()\nlen(data_streams)\n
2\n
"},{"location":"reference/endpoint/api/version/","title":"Version","text":"Specific implementation of the StreamPipes API's version endpoint.
"},{"location":"reference/endpoint/api/version/#streampipes.endpoint.api.version.VersionEndpoint","title":"VersionEndpoint
","text":" Bases: APIEndpoint
Implementation of the Versions endpoint.
This endpoint provides metadata about the StreamPipes version of the connected instance. It only allows to apply the get()
method with an empty string as identifier.
PARAMETER DESCRIPTION parent_client
The instance of StreamPipesClient the endpoint is attached to.
Examples:
>>> from streampipes.client import StreamPipesClient\n>>> from streampipes.client.config import StreamPipesClientConfig\n>>> from streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
>>> client_config = StreamPipesClientConfig(\n... credential_provider=StreamPipesApiKeyCredentials(username=\"test-user\", api_key=\"api-key\"),\n... host_address=\"localhost\",\n... port=8082,\n... https_disabled=True\n... )\n
>>> client = StreamPipesClient.create(client_config=client_config)\n
>>> client.versionApi.get(identifier=\"\").to_dict(use_source_names=False)\n{'backend_version': '0.92.0-SNAPSHOT'}\n
"},{"location":"reference/endpoint/api/version/#streampipes.endpoint.api.version.VersionEndpoint.all","title":"all()
","text":"Usually, this method returns information about all resources provided by this endpoint. However, this endpoint does not support this kind of operation.
RAISES DESCRIPTION NotImplementedError
this endpoint does not return multiple entries, therefore this method is not available
"},{"location":"reference/endpoint/api/version/#streampipes.endpoint.api.version.VersionEndpoint.get","title":"get(identifier, **kwargs)
","text":"Queries the resource from the API endpoint.
For this endpoint only one resource is available.
PARAMETER DESCRIPTION identifier
Not supported by this endpoint, is set to an empty string.
TYPE: str
RETURNS DESCRIPTION versions
The specified resource as an instance of the corresponding model class(Version). # noqa: 501
TYPE: Version
"},{"location":"reference/endpoint/api/version/#streampipes.endpoint.api.version.VersionEndpoint.post","title":"post(resource)
","text":"Usually, this method allows to create via this endpoint. Since the data represented by this endpoint is immutable, it does not support this kind of operation.
RAISES DESCRIPTION NotImplementedError
this endpoint does not allow for POST requests, therefore this method is not available
"},{"location":"reference/function_zoo/river_function/","title":"River function","text":""},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.OnlineML","title":"OnlineML(client, stream_ids, model, prediction_type=RuntimeType.STRING.value, supervised=False, target_label=None, on_start=lambda self, context: None, on_event=lambda self, event, streamId: None, on_stop=lambda self: None)
","text":"Wrapper class to enable an easy usage for Online Machine Learning models of the River library.
It creates a StreamPipesFunction to train a model with the incoming events of a data stream and creates an output data stream that publishes the prediction to StreamPipes.
PARAMETER DESCRIPTION client
The client for the StreamPipes API.
TYPE: StreamPipesClient
stream_ids
The ids of the data stream to train the model.
TYPE: List[str]
model
The model to train. It meant to be a River model/pipeline, but can be every model with a 'learn_one' and 'predict_one' methode.
TYPE: Any
prediction_type
The data type of the prediction. Is only needed when you continue to work with the prediction in StreamPipes.
TYPE: str
DEFAULT: RuntimeType.STRING.value
supervised
Define if the model is supervised or unsupervised.
TYPE: bool
DEFAULT: False
target_label
Define the name of the target attribute if the model is supervised.
TYPE: Optional[str]
DEFAULT: None
on_start
A function to be called when this StreamPipesFunction gets started.
TYPE: Callable[[Any, FunctionContext], None]
DEFAULT: lambda self, context: None
on_event
A function to be called when this StreamPipesFunction receives an event.
TYPE: Callable[[Any, Dict[str, Any], str], None]
DEFAULT: lambda self, event, streamId: None
on_stop
A function to be called when this StreamPipesFunction gets stopped.
TYPE: Callable[[Any], None]
DEFAULT: lambda self: None
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.OnlineML.set_learning","title":"set_learning(learning)
","text":"Start or stop the training of the model.
PARAMETER DESCRIPTION learning
Defines if the training should be continued
TYPE: bool
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.OnlineML.start","title":"start()
","text":"Registers the function and starts the training.
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.OnlineML.stop","title":"stop()
","text":"Stops the function and ends the training forever.
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.RiverFunction","title":"RiverFunction(function_definition, model, supervised, target_label, on_start, on_event, on_stop)
","text":" Bases: StreamPipesFunction
Implementation of a StreamPipesFunction to enable an easy usage for Online Machine Learning models of the River library.
The function trains the model with the incoming events and publishes the prediction to an output data stream.
PARAMETER DESCRIPTION function_definition
The function definition which contains the output stream.
TYPE: FunctionDefinition
model
The model to train. It meant to be a River model/pipeline, but can be every model with a 'learn_one' and 'predict_one' method.
TYPE: Any
supervised
Define if the model is supervised or unsupervised.
TYPE: bool
target_label
Define the name of the target attribute if the model is supervised.
TYPE: Optional[str]
on_start
A function to be called when this StreamPipesFunction gets started.
TYPE: Callable[[Any, FunctionContext], None]
on_event
A function to be called when this StreamPipesFunction receives an event.
TYPE: Callable[[Any, Dict[str, Any], str], None]
on_stop
A function to be called when this StreamPipesFunction gets stopped.
TYPE: Callable[[Any], None]
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.RiverFunction.onEvent","title":"onEvent(event, streamId)
","text":"Trains the model with the incoming events and sends the prediction back to StreamPipes.
PARAMETER DESCRIPTION event
The incoming event that serves as input for the function
TYPE: Dict[str, Any]
streamId
Identifier of the corresponding data stream
TYPE: str
RETURNS DESCRIPTION None
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.RiverFunction.onServiceStarted","title":"onServiceStarted(context)
","text":"Executes the on_start
method of the function.
PARAMETER DESCRIPTION context
The functions' context
TYPE: FunctionContext
RETURNS DESCRIPTION None
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.RiverFunction.onServiceStopped","title":"onServiceStopped()
","text":"Executes the on_stop
function.
"},{"location":"reference/functions/function_handler/","title":"Function handler","text":""},{"location":"reference/functions/function_handler/#streampipes.functions.function_handler.FunctionHandler","title":"FunctionHandler(registration, client)
","text":"The function handler manages the StreamPipes Functions.
It controls the connection to the brokers, starts the functions, manages the broadcast of the live data and is able to stop the connection to the brokers and functions.
PARAMETER DESCRIPTION registration
The registration, that contains the StreamPipesFunctions.
TYPE: Registration
client
The client to interact with the API.
TYPE: StreamPipesClient
ATTRIBUTE DESCRIPTION stream_contexts
Map of all data stream contexts
TYPE: Dict[str, DataStreamContext]
brokers
List of all registered brokers
TYPE: List[Broker]
"},{"location":"reference/functions/function_handler/#streampipes.functions.function_handler.FunctionHandler.disconnect","title":"disconnect()
","text":"Disconnects from the brokers and stops all functions.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/function_handler/#streampipes.functions.function_handler.FunctionHandler.force_stop_functions","title":"force_stop_functions()
","text":"Stops the StreamPipesFunctions when the event loop was stopped without stopping the functions.
RETURNS DESCRIPTION None
WARNS DESCRIPTION UserWarning
If there is a running event loop and the functions should be stopped by disconnecting from the broker.
"},{"location":"reference/functions/function_handler/#streampipes.functions.function_handler.FunctionHandler.initializeFunctions","title":"initializeFunctions()
","text":"Creates the context for every data stream and starts the event loop to manage the StreamPipes Functions.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/registration/","title":"Registration","text":""},{"location":"reference/functions/registration/#streampipes.functions.registration.Registration","title":"Registration()
","text":"Manages the existing StreamPipesFunctions and registers them.
ATTRIBUTE DESCRIPTION functions
List of all registered StreamPipesFunction
TYPE: List[StreamPipesFunction]
"},{"location":"reference/functions/registration/#streampipes.functions.registration.Registration.getFunctions","title":"getFunctions()
","text":"Get all registered functions.
This method exists to be consistent with the Java client.
RETURNS DESCRIPTION functions
List of all registered functions.
TYPE: List[StreamPipesFunction]
"},{"location":"reference/functions/registration/#streampipes.functions.registration.Registration.register","title":"register(streampipes_function)
","text":"Registers a new function.
PARAMETER DESCRIPTION streampipes_function
The function to register.
TYPE: StreamPipesFunction
RETURNS DESCRIPTION self
The updated Registration instance
TYPE: Registration
"},{"location":"reference/functions/streampipes_function/","title":"Streampipes function","text":""},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction","title":"StreamPipesFunction(function_definition=None)
","text":" Bases: ABC
Abstract implementation of a StreamPipesFunction.
A StreamPipesFunction allows users to get the data of a StreamPipes data streams easily. It makes it possible to work with the live data in python and enables to use the powerful data analytics libraries there.
PARAMETER DESCRIPTION function_definition
the definition of the function that contains metadata about the connected function
TYPE: Optional[FunctionDefinition]
DEFAULT: None
ATTRIBUTE DESCRIPTION output_collectors
List of all output collectors which are created based on the provided function definitions.
TYPE: Dict[str, OutputCollector]
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.add_output","title":"add_output(stream_id, event)
","text":"Send an event via an output data stream to StreamPipes
PARAMETER DESCRIPTION stream_id
The id of the output data stream
TYPE: str
event
The event which should be sent
TYPE: Dict[str, Any]
RETURNS DESCRIPTION None
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.getFunctionId","title":"getFunctionId()
","text":"Returns the id of the function.
RETURNS DESCRIPTION function_id
Identification object of the StreamPipes function
TYPE: FunctionId
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.onEvent","title":"onEvent(event, streamId)
abstractmethod
","text":"Is called for every event of a data stream.
PARAMETER DESCRIPTION event
The received event from the data stream.
TYPE: Dict[str, Any]
streamId
The id of the data stream which the event belongs to.
TYPE: str
RETURNS DESCRIPTION None
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.onServiceStarted","title":"onServiceStarted(context)
abstractmethod
","text":"Is called when the function gets started.
PARAMETER DESCRIPTION context
The context in which the function gets started.
TYPE: FunctionContext
RETURNS DESCRIPTION None
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.onServiceStopped","title":"onServiceStopped()
abstractmethod
","text":"Is called when the function gets stopped.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.requiredStreamIds","title":"requiredStreamIds()
","text":"Get the ids of the streams needed by the function.
RETURNS DESCRIPTION stream_ids
List of the stream ids
TYPE: List[str]
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.stop","title":"stop()
","text":"Stops the function and disconnects from the output streams
"},{"location":"reference/functions/broker/broker/","title":"Broker","text":""},{"location":"reference/functions/broker/broker/#streampipes.functions.broker.broker.Broker","title":"Broker
","text":" Bases: ABC
Abstract implementation of a broker for consumer and publisher.
It contains the basic logic to connect to a data stream.
"},{"location":"reference/functions/broker/broker/#streampipes.functions.broker.broker.Broker.connect","title":"connect(data_stream)
async
","text":"Connects to the broker running in StreamPipes.
PARAMETER DESCRIPTION data_stream
Contains the meta information (resources) for a data stream.
TYPE: DataStream
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/broker/#streampipes.functions.broker.broker.Broker.disconnect","title":"disconnect()
abstractmethod
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/broker_handler/","title":"Broker handler","text":""},{"location":"reference/functions/broker/broker_handler/#streampipes.functions.broker.broker_handler.SupportedBroker","title":"SupportedBroker
","text":" Bases: Enum
Enum for the supported brokers.
"},{"location":"reference/functions/broker/broker_handler/#streampipes.functions.broker.broker_handler.UnsupportedBrokerError","title":"UnsupportedBrokerError(broker_name)
","text":" Bases: Exception
Exception if a broker isn't implemented yet.
"},{"location":"reference/functions/broker/broker_handler/#streampipes.functions.broker.broker_handler.get_broker","title":"get_broker(data_stream, is_publisher=False)
","text":"Derive the broker for the given data stream.
PARAMETER DESCRIPTION data_stream
Data stream instance from which the broker is inferred
TYPE: DataStream
RETURNS DESCRIPTION broker
The corresponding broker instance derived from data stream.
TYPE: Broker
RAISES DESCRIPTION UnsupportedBrokerError
Is raised when the given data stream belongs to a broker that is currently not supported by StreamPipes Python.
"},{"location":"reference/functions/broker/broker_handler/#streampipes.functions.broker.broker_handler.get_broker_description","title":"get_broker_description(data_stream)
","text":"Derive the decription of the broker for the given data stream.
PARAMETER DESCRIPTION data_stream
Data stream instance from which the broker is inferred
TYPE: DataStream
RETURNS DESCRIPTION broker
The corresponding broker description derived from data stream.
TYPE: SupportedBroker
RAISES DESCRIPTION UnsupportedBrokerError
Is raised when the given data stream belongs to a broker that is currently not supported by StreamPipes Python.
"},{"location":"reference/functions/broker/consumer/","title":"Consumer","text":""},{"location":"reference/functions/broker/consumer/#streampipes.functions.broker.consumer.Consumer","title":"Consumer
","text":" Bases: Broker
Abstract implementation a consumer for a broker.
A consumer allows to subscribe to a data stream.
"},{"location":"reference/functions/broker/consumer/#streampipes.functions.broker.consumer.Consumer.connect","title":"connect(data_stream)
async
","text":"Connects to the broker running in StreamPipes and creates a subscription.
PARAMETER DESCRIPTION data_stream
Contains the meta information (resources) for a data stream.
TYPE: DataStream
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/consumer/#streampipes.functions.broker.consumer.Consumer.get_message","title":"get_message()
abstractmethod
","text":"Get the published messages of the subscription.
RETURNS DESCRIPTION iterator
An async iterator for the messages.
TYPE: AsyncIterator
"},{"location":"reference/functions/broker/output_collector/","title":"Output collector","text":""},{"location":"reference/functions/broker/output_collector/#streampipes.functions.broker.output_collector.OutputCollector","title":"OutputCollector(data_stream)
","text":"Collector for output events. The events are published to an output data stream. Therefore, the output collector establishes a connection to the broker.
PARAMETER DESCRIPTION data_stream
The output data stream that will receive the events.
TYPE: DataStream
ATTRIBUTE DESCRIPTION publisher
The publisher instance that sends the data to StreamPipes
TYPE: Publisher
"},{"location":"reference/functions/broker/output_collector/#streampipes.functions.broker.output_collector.OutputCollector.collect","title":"collect(event)
","text":"Publishes an event to the output stream.
PARAMETER DESCRIPTION event
The event to be published.
TYPE: Dict[str, Any]
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/output_collector/#streampipes.functions.broker.output_collector.OutputCollector.disconnect","title":"disconnect()
","text":"Disconnects the broker of the output collector.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/publisher/","title":"Publisher","text":""},{"location":"reference/functions/broker/publisher/#streampipes.functions.broker.publisher.Publisher","title":"Publisher
","text":" Bases: Broker
Abstract implementation of a publisher for a broker.
A publisher allows to publish events to a data stream.
"},{"location":"reference/functions/broker/publisher/#streampipes.functions.broker.publisher.Publisher.publish_event","title":"publish_event(event)
abstractmethod
async
","text":"Publish an event to a connected data stream.
PARAMETER DESCRIPTION event
The event to be published.
TYPE: Dict[str, Any]
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/kafka/kafka_consumer/","title":"Kafka consumer","text":""},{"location":"reference/functions/broker/kafka/kafka_consumer/#streampipes.functions.broker.kafka.kafka_consumer.KafkaConsumer","title":"KafkaConsumer
","text":" Bases: Consumer
Implementation of a consumer for Kafka
"},{"location":"reference/functions/broker/kafka/kafka_consumer/#streampipes.functions.broker.kafka.kafka_consumer.KafkaConsumer.disconnect","title":"disconnect()
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/kafka/kafka_consumer/#streampipes.functions.broker.kafka.kafka_consumer.KafkaConsumer.get_message","title":"get_message()
","text":"Get the published messages of the subscription.
RETURNS DESCRIPTION iterator
An async iterator for the messages.
TYPE: AsyncIterator
"},{"location":"reference/functions/broker/kafka/kafka_message_fetcher/","title":"Kafka message fetcher","text":""},{"location":"reference/functions/broker/kafka/kafka_message_fetcher/#streampipes.functions.broker.kafka.kafka_message_fetcher.KafkaMessage","title":"KafkaMessage(data)
","text":"An internal representation of a Kafka message
PARAMETER DESCRIPTION data
The received Kafka message as byte array
"},{"location":"reference/functions/broker/kafka/kafka_message_fetcher/#streampipes.functions.broker.kafka.kafka_message_fetcher.KafkaMessageFetcher","title":"KafkaMessageFetcher(consumer)
","text":"Fetches the next message from Kafka
PARAMETER DESCRIPTION consumer
The Kafka consumer
TYPE: Consumer
"},{"location":"reference/functions/broker/kafka/kafka_publisher/","title":"Kafka publisher","text":""},{"location":"reference/functions/broker/kafka/kafka_publisher/#streampipes.functions.broker.kafka.kafka_publisher.KafkaPublisher","title":"KafkaPublisher
","text":" Bases: Publisher
Implementation of a publisher for Kafka
"},{"location":"reference/functions/broker/kafka/kafka_publisher/#streampipes.functions.broker.kafka.kafka_publisher.KafkaPublisher.disconnect","title":"disconnect()
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/kafka/kafka_publisher/#streampipes.functions.broker.kafka.kafka_publisher.KafkaPublisher.publish_event","title":"publish_event(event)
async
","text":"Publish an event to a connected data stream.
PARAMETER DESCRIPTION event
The event to be published.
TYPE: Dict[str, Any]
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/nats/nats_consumer/","title":"Nats consumer","text":""},{"location":"reference/functions/broker/nats/nats_consumer/#streampipes.functions.broker.nats.nats_consumer.NatsConsumer","title":"NatsConsumer
","text":" Bases: Consumer
Implementation of a consumer for NATS
"},{"location":"reference/functions/broker/nats/nats_consumer/#streampipes.functions.broker.nats.nats_consumer.NatsConsumer.disconnect","title":"disconnect()
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/nats/nats_consumer/#streampipes.functions.broker.nats.nats_consumer.NatsConsumer.get_message","title":"get_message()
","text":"Get the published messages of the subscription.
RETURNS DESCRIPTION message_iterator
An async iterator for the messages.
TYPE: AsyncIterator
"},{"location":"reference/functions/broker/nats/nats_publisher/","title":"Nats publisher","text":""},{"location":"reference/functions/broker/nats/nats_publisher/#streampipes.functions.broker.nats.nats_publisher.NatsPublisher","title":"NatsPublisher
","text":" Bases: Publisher
Implementation of a publisher for NATS
"},{"location":"reference/functions/broker/nats/nats_publisher/#streampipes.functions.broker.nats.nats_publisher.NatsPublisher.disconnect","title":"disconnect()
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/nats/nats_publisher/#streampipes.functions.broker.nats.nats_publisher.NatsPublisher.publish_event","title":"publish_event(event)
async
","text":"Publish an event to a connected data stream.
PARAMETER DESCRIPTION event
The event to be published.
TYPE: Dict[str, Any]
RETURNS DESCRIPTION None
"},{"location":"reference/functions/utils/async_iter_handler/","title":"Async iter handler","text":""},{"location":"reference/functions/utils/async_iter_handler/#streampipes.functions.utils.async_iter_handler.AsyncIterHandler","title":"AsyncIterHandler
","text":"Handles asynchronous iterators to get every message after another in parallel.
"},{"location":"reference/functions/utils/async_iter_handler/#streampipes.functions.utils.async_iter_handler.AsyncIterHandler.anext","title":"anext(stream_id, message)
async
staticmethod
","text":"Gets the next message from an AsyncIterator.
PARAMETER DESCRIPTION stream_id
The id of the data stream which the message belongs to.
TYPE: str
message
An asynchronous iterator that contains the messages.
TYPE: AsyncIterator
RETURNS DESCRIPTION result
Tuple of the stream id und next message or (\"stop\", None)
if no message is left.
TYPE: Tuple[str, Optional[Any]]
"},{"location":"reference/functions/utils/async_iter_handler/#streampipes.functions.utils.async_iter_handler.AsyncIterHandler.combine_async_messages","title":"combine_async_messages(messages)
async
staticmethod
","text":"Continuously gets the next published message from multiple AsyncIterators in parallel.
PARAMETER DESCRIPTION messages
A dictionary with an asynchronous iterator for every stream id.
TYPE: Dict[str, AsyncIterator]
YIELDS DESCRIPTION message
Description of the anonymous integer return value.
TYPE:: Tuple[str, Any]
"},{"location":"reference/functions/utils/data_stream_context/","title":"Data stream context","text":""},{"location":"reference/functions/utils/data_stream_context/#streampipes.functions.utils.data_stream_context.DataStreamContext","title":"DataStreamContext(functions, schema, broker)
","text":"Container for the context of a data stream.
PARAMETER DESCRIPTION functions
StreamPipes Functions which require the data of this data stream.
TYPE: List[StreamPipesFunction]
schema
The schema of this data stream.
TYPE: DataStream
broker
The consumer to connect to this data stream.
TYPE: Consumer
"},{"location":"reference/functions/utils/data_stream_context/#streampipes.functions.utils.data_stream_context.DataStreamContext.add_function","title":"add_function(function)
","text":"Adds a new StreamPipes Function.
PARAMETER DESCRIPTION function
StreamPipesFunction which requires this data stream.
TYPE: StreamPipesFunction
RETURNS DESCRIPTION None
"},{"location":"reference/functions/utils/data_stream_generator/","title":"Data stream generator","text":""},{"location":"reference/functions/utils/data_stream_generator/#streampipes.functions.utils.data_stream_generator.RuntimeType","title":"RuntimeType
","text":" Bases: Enum
Runtime type names for the attributes of a data stream.
ATTRIBUTE DESCRIPTION STRING
BOOLEAN
DOUBLE
FLOAT
INTEGER
LONG
"},{"location":"reference/functions/utils/data_stream_generator/#streampipes.functions.utils.data_stream_generator.create_data_stream","title":"create_data_stream(name, attributes, stream_id=None, broker=SupportedBroker.NATS)
","text":"Creates a data stream
PARAMETER DESCRIPTION name
Name of the data stream to be shown at the UI.
TYPE: str
attributes
Name and types of the attributes.
TYPE: Dict[str, str]
stream_id
The id of this data stream.
TYPE: Optional[str]
DEFAULT: None
RETURNS DESCRIPTION data_stream
The created data stream
TYPE: DataStream
"},{"location":"reference/functions/utils/function_context/","title":"Function context","text":""},{"location":"reference/functions/utils/function_context/#streampipes.functions.utils.function_context.FunctionContext","title":"FunctionContext(function_id, schema, client, streams)
","text":"Container for the context of a StreamPipesFunction.
PARAMETER DESCRIPTION function_id
The id of this function.
TYPE: str
schema
A dictionary which contains the schema of a data stream for each stream id.
TYPE: Dict[str, DataStream]
client
The client to interact with the API.
TYPE: StreamPipesClient
streams
The ids of the streams needed by this function.
TYPE: List[str]
"},{"location":"reference/functions/utils/function_context/#streampipes.functions.utils.function_context.FunctionContext.add_data_stream_schema","title":"add_data_stream_schema(stream_id, data_stream)
","text":"Adds a new data stream for a new stream id.
PARAMETER DESCRIPTION stream_id
The id of the data stream.
TYPE: str
data_stream
The schema of the data stream.
TYPE: DataStream
RETURNS DESCRIPTION None
"},{"location":"reference/model/common/","title":"Common","text":"Classes of the StreamPipes data model that are commonly shared.
"},{"location":"reference/model/common/#streampipes.model.common.ApplicationLink","title":"ApplicationLink
","text":" Bases: BasicModel
Data model of an ApplicationLink
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.BaseElement","title":"BaseElement
","text":" Bases: BasicModel
Structure of a basic element in the StreamPipes backend
"},{"location":"reference/model/common/#streampipes.model.common.BasicModel","title":"BasicModel
","text":" Bases: BaseModel
Basic model class used for the whole Python StreamPipes data model.
"},{"location":"reference/model/common/#streampipes.model.common.BasicModel.Config","title":"Config
","text":"Configuration class for Pydantic. Defines alias generator to convert field names from camelCase (API) to snake_case (Python codebase).
"},{"location":"reference/model/common/#streampipes.model.common.EventGrounding","title":"EventGrounding
","text":" Bases: BasicModel
Data model of an EventGrounding
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.EventProperty","title":"EventProperty
","text":" Bases: BasicModel
Data model of an EventProperty
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.EventSchema","title":"EventSchema
","text":" Bases: BasicModel
Data model of an EventSchema
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.MeasurementCapability","title":"MeasurementCapability
","text":" Bases: BasicModel
Data model of a MeasurementCapability
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.MeasurementObject","title":"MeasurementObject
","text":" Bases: BasicModel
Data model of a MeasurementObject
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.TopicDefinition","title":"TopicDefinition
","text":" Bases: BasicModel
Data model of a TopicDefinition
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.TransportFormat","title":"TransportFormat
","text":" Bases: BasicModel
Data model of a TransportFormat
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.TransportProtocol","title":"TransportProtocol
","text":" Bases: BasicModel
Data model of a TransportProtocol
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.ValueSpecification","title":"ValueSpecification
","text":" Bases: BasicModel
Data model of an ValueSpecification
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.random_letters","title":"random_letters(n)
","text":"Generates a string consisting of random letters.
PARAMETER DESCRIPTION n
number of letters
TYPE: int
RETURNS DESCRIPTION rand_str
String consisting of n
random letters
TYPE: str
"},{"location":"reference/model/container/data_lake_measures/","title":"Data lake measures","text":"Implementation of a resource container for the data lake measures endpoint.
"},{"location":"reference/model/container/data_lake_measures/#streampipes.model.container.data_lake_measures.DataLakeMeasures","title":"DataLakeMeasures
","text":" Bases: ResourceContainer
Implementation of the resource container for the data lake measures endpoint.
This resource container is a collection of data lake measures returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried DataLakeMeasure
. Furthermore, the resource container makes them accessible in a pythonic manner.
"},{"location":"reference/model/container/data_streams/","title":"Data streams","text":"Implementation of a resource container for the data streams endpoint.
"},{"location":"reference/model/container/data_streams/#streampipes.model.container.data_streams.DataStreams","title":"DataStreams
","text":" Bases: ResourceContainer
Implementation of the resource container for the data stream endpoint.
This resource container is a collection of data streams returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried DataStream
. Furthermore, the resource container makes them accessible in a pythonic manner.
"},{"location":"reference/model/container/resource_container/","title":"Resource container","text":"General and abstract implementation for a resource container.
A resource container is a collection of resources returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried resources. Furthermore, the resource container makes them accessible in a pythonic manner.
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.ResourceContainer","title":"ResourceContainer(resources)
","text":" Bases: ABC
General and abstract implementation for a resource container.
A resource container is a collection of resources returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried resources. Furthermore, the resource container makes them accessible in a pythonic manner.
PARAMETER DESCRIPTION resources
A list of resources to be contained in the ResourceContainer
.
TYPE: List[Resource]
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.ResourceContainer.from_json","title":"from_json(json_string)
classmethod
","text":"Creates a ResourceContainer
from the given JSON string.
PARAMETER DESCRIPTION json_string
The JSON string returned from the StreamPipes API.
TYPE: str
RETURNS DESCRIPTION container
instance of the container derived from the JSON definition
TYPE: ResourceContainer
RAISES DESCRIPTION StreamPipesDataModelError
If a resource cannot be mapped to the corresponding Python data model.
StreamPipesResourceContainerJSONError
If JSON response cannot be parsed to a ResourceContainer
.
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.ResourceContainer.to_dicts","title":"to_dicts(use_source_names=False)
","text":"Returns the contained resources as list of dictionaries.
PARAMETER DESCRIPTION use_source_names
Determines whether the field names are named in Python style (=False
) or as originally named by StreamPipes (=True
).
TYPE: bool
DEFAULT: False
RETURNS DESCRIPTION dictionary_list
List of resources in dictionary representation. If use_source_names
equals True
the keys are named as in the StreamPipes backend.
TYPE: List[Dict[str, Any]]
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.ResourceContainer.to_json","title":"to_json()
","text":"Returns the resource container in the StreamPipes JSON representation.
RETURNS DESCRIPTION json_string: str
JSON representation of the resource container where key names are equal to keys used in the StreamPipes backend
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.ResourceContainer.to_pandas","title":"to_pandas()
","text":"Returns the resource container in representation of a Pandas Dataframe.
RETURNS DESCRIPTION resource_container_df
Representation of the resource container as pandas DataFrame
TYPE: pd.DataFrame
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.StreamPipesDataModelError","title":"StreamPipesDataModelError(validation_error)
","text":" Bases: Exception
A custom exception to be raised when a validation error occurs during the parsing of StreamPipes API responses.
PARAMETER DESCRIPTION validation_error
The validation error thrown by Pydantic during parsing.
TYPE: ValidationError
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.StreamPipesResourceContainerJSONError","title":"StreamPipesResourceContainerJSONError(container_name, json_string)
","text":" Bases: Exception
A custom exception to be raised when the returned JSON string does not suit to the structure of resource container.
PARAMETER DESCRIPTION container_name
The class name of the resource container where the invalid data structure was detected.
TYPE: str
json_string
The JSON string that has been tried to parse.
TYPE: str
"},{"location":"reference/model/container/versions/","title":"Versions","text":"Implementation of a resource container for the versions endpoint.
"},{"location":"reference/model/container/versions/#streampipes.model.container.versions.Versions","title":"Versions
","text":" Bases: ResourceContainer
Implementation of the resource container for the versions endpoint.
This resource container is a collection of versions returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried Version
. Furthermore, the resource container makes them accessible in a pythonic manner.
PARAMETER DESCRIPTION resources
A list of resources (Version) to be contained in the ResourceContainer
.
"},{"location":"reference/model/resource/data_lake_measure/","title":"Data lake measure","text":""},{"location":"reference/model/resource/data_lake_measure/#streampipes.model.resource.data_lake_measure.DataLakeMeasure","title":"DataLakeMeasure
","text":" Bases: Resource
Implementation of a resource for data lake measures.
This resource defines the data model used by resource container (model.container.DataLakeMeasures
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response, and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
"},{"location":"reference/model/resource/data_lake_measure/#streampipes.model.resource.data_lake_measure.DataLakeMeasure.convert_to_pandas_representation","title":"convert_to_pandas_representation()
","text":"Returns the dictionary representation of a data lake measure to be used when creating a pandas Dataframe.
It excludes the following fields: element_id
, event_schema
, schema_version
. Instead of the whole event schema the number of event properties contained is returned with the column name num_event_properties
.
RETURNS DESCRIPTION pandas_repr
Pandas representation of the resource as a dictionary, which is then used by the respource container to create a data frame from a collection of resources.
TYPE: Dict[str, Any]
"},{"location":"reference/model/resource/data_series/","title":"Data series","text":""},{"location":"reference/model/resource/data_series/#streampipes.model.resource.data_series.DataSeries","title":"DataSeries
","text":" Bases: Resource
Implementation of a resource for data series. This resource defines the data model used by its resource container(model.container.DataLakeMeasures
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
"},{"location":"reference/model/resource/data_series/#streampipes.model.resource.data_series.DataSeries--notes","title":"Notes","text":"This class will only exist temporarily in it its current appearance since\nthere are some inconsistencies in the StreamPipes API.\n
"},{"location":"reference/model/resource/data_series/#streampipes.model.resource.data_series.DataSeries.convert_to_pandas_representation","title":"convert_to_pandas_representation()
","text":"Returns the dictionary representation of a data lake series to be used when creating a pandas Dataframe.
It contains only the \"header rows\" (the column names) and \"rows\" that contain the actual data.
RETURNS DESCRIPTION pandas_repr
Dictionary with the keys headers
and rows
TYPE: dict[str, Any]
"},{"location":"reference/model/resource/data_series/#streampipes.model.resource.data_series.DataSeries.from_json","title":"from_json(json_string)
classmethod
","text":"Creates an instance of DataSeries
from a given JSON string.
This method is used by the resource container to parse the JSON response of the StreamPipes API. Currently, it only supports data lake series that consist of exactly one series of data.
PARAMETER DESCRIPTION json_string
The JSON string the data lake series should be created on.
TYPE: str
RETURNS DESCRIPTION DataSeries
Instance of DataSeries
that is created based on the given JSON string.
RAISES DESCRIPTION StreamPipesUnsupportedDataLakeSeries
If the data lake series returned by the StreamPipes API cannot be parsed with the current version of the Python client.
"},{"location":"reference/model/resource/data_series/#streampipes.model.resource.data_series.DataSeries.to_pandas","title":"to_pandas()
","text":"Returns the data lake series in representation of a Pandas Dataframe.
RETURNS DESCRIPTION pd
The data lake series in form of a pandas dataframe
TYPE: pd.DataFrame
"},{"location":"reference/model/resource/data_stream/","title":"Data stream","text":""},{"location":"reference/model/resource/data_stream/#streampipes.model.resource.data_stream.DataStream","title":"DataStream(**kwargs)
","text":" Bases: Resource
Implementation of a resource for data streams.
This resource defines the data model used by resource container (model.container.DataStreams
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
"},{"location":"reference/model/resource/data_stream/#streampipes.model.resource.data_stream.DataStream.convert_to_pandas_representation","title":"convert_to_pandas_representation()
","text":"Returns the dictionary representation of a data stream to be used when creating a pandas Dataframe.
RETURNS DESCRIPTION pandas_repr
Pandas representation of the resource as a dictionary, which is then used by the respource container to create a data frame from a collection of resources.
TYPE: Dict[str, Any]
"},{"location":"reference/model/resource/data_stream/#streampipes.model.resource.data_stream.DataStream.to_dict","title":"to_dict(use_source_names=True)
","text":"Returns the resource in dictionary representation.
PARAMETER DESCRIPTION use_source_names
Indicates if the dictionary keys are in python representation or equally named to the StreamPipes backend
DEFAULT: True
RETURNS DESCRIPTION resource
The resource as dictionary representation
TYPE: Dict[str, Any]
"},{"location":"reference/model/resource/exceptions/","title":"Exceptions","text":""},{"location":"reference/model/resource/exceptions/#streampipes.model.resource.exceptions.StreamPipesUnsupportedDataSeries","title":"StreamPipesUnsupportedDataSeries(reason=None)
","text":" Bases: Exception
Exception to be raised when the returned data lake series cannot be parsed with the current implementation of the resource.
"},{"location":"reference/model/resource/function_definition/","title":"Function definition","text":""},{"location":"reference/model/resource/function_definition/#streampipes.model.resource.function_definition.FunctionDefinition","title":"FunctionDefinition
","text":" Bases: Resource
Configuration for a StreamPipes Function.
This class maps to the FunctionDefinition
class in the StreamPipes model. It contains all metadata that are required to register a function at the StreamPipes backend.
PARAMETER DESCRIPTION consumed_streams
List of data streams the function is consuming from
function_id
identifier object of a StreamPipes function
ATTRIBUTE DESCRIPTION output_data_streams
Map off all output data streams added to the function definition
TYPE: Dict[str, DataStream]
"},{"location":"reference/model/resource/function_definition/#streampipes.model.resource.function_definition.FunctionDefinition.add_output_data_stream","title":"add_output_data_stream(data_stream)
","text":"Adds an output data stream to the function which makes it possible to write data back to StreamPipes.
PARAMETER DESCRIPTION data_stream
The schema of the output data stream.
TYPE: DataStream
RETURNS DESCRIPTION self
Instance of the function definition that is extended by the provided DataStream
TYPE: FunctionDefinition
"},{"location":"reference/model/resource/function_definition/#streampipes.model.resource.function_definition.FunctionDefinition.convert_to_pandas_representation","title":"convert_to_pandas_representation()
","text":"Returns the dictionary representation of a function definition to be used when creating a pandas Dataframe.
RETURNS DESCRIPTION pandas_repr
Pandas representation of the resource as a dictionary, which is then used by the respource container to create a data frame from a collection of resources.
TYPE: Dict[str, Any]
"},{"location":"reference/model/resource/function_definition/#streampipes.model.resource.function_definition.FunctionDefinition.get_output_data_streams","title":"get_output_data_streams()
","text":"Get the output data streams of the function.
RETURNS DESCRIPTION output_streams
Dictionary with every known stream id and the related output stream.
TYPE: Dict[str, DataStream]
"},{"location":"reference/model/resource/function_definition/#streampipes.model.resource.function_definition.FunctionDefinition.get_output_stream_ids","title":"get_output_stream_ids()
","text":"Get the stream ids of the output data streams.
RETURNS DESCRIPTION output_stream_ids
List of all stream ids
TYPE: List[str]
"},{"location":"reference/model/resource/function_definition/#streampipes.model.resource.function_definition.FunctionId","title":"FunctionId
","text":" Bases: BasicModel
Identification object for a StreamPipes function.
Maps to the FunctionId
class defined in the StreamPipes model.
PARAMETER DESCRIPTION id
unique identifier of the function instance
version
version of the corresponding function
"},{"location":"reference/model/resource/query_result/","title":"Query result","text":""},{"location":"reference/model/resource/query_result/#streampipes.model.resource.query_result.QueryResult","title":"QueryResult
","text":" Bases: Resource
Implementation of a resource for query result. This resource defines the data model used by its resource container(model.container.DataLakeMeasures
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
"},{"location":"reference/model/resource/query_result/#streampipes.model.resource.query_result.QueryResult.convert_to_pandas_representation","title":"convert_to_pandas_representation()
","text":"Returns the dictionary representation of a data lake series to be used when creating a pandas Dataframe.
It contains only the \"header rows\" (the column names) and \"rows\" that contain the actual data.
RETURNS DESCRIPTION dict
Dictionary with the keys headers
and rows
RAISES DESCRIPTION StreamPipesUnsupportedDataLakeSeries
If the query result returned by the StreamPipes API cannot be converted to the pandas representation
"},{"location":"reference/model/resource/query_result/#streampipes.model.resource.query_result.QueryResult.to_pandas","title":"to_pandas()
","text":"Returns the data lake series in representation of a Pandas Dataframe.
RETURNS DESCRIPTION df
Pandas df containing the query result
TYPE: pd.DataFrame
"},{"location":"reference/model/resource/resource/","title":"Resource","text":"General and abstract implementation for a resource.
A resource defines the data model that is used by a resource container (model.container.resourceContainer
).
"},{"location":"reference/model/resource/resource/#streampipes.model.resource.resource.Resource","title":"Resource
","text":" Bases: ABC
, BasicModel
General and abstract implementation for a resource.
A resource defines the data model used by a resource container (model.container.resourceContainer
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
"},{"location":"reference/model/resource/resource/#streampipes.model.resource.resource.Resource.convert_to_pandas_representation","title":"convert_to_pandas_representation()
abstractmethod
","text":"Returns a dictionary representation to be used when creating a pandas Dataframe.
RETURNS DESCRIPTION pandas_repr
Pandas representation of the resource as a dictionary, which is then used by the respource container to create a data frame from a collection of resources.
TYPE: Dict[str, Any]
"},{"location":"reference/model/resource/resource/#streampipes.model.resource.resource.Resource.to_dict","title":"to_dict(use_source_names=True)
","text":"Returns the resource in dictionary representation.
PARAMETER DESCRIPTION use_source_names
Indicates if the dictionary keys are in python representation or equally named to the StreamPipes backend
DEFAULT: True
RETURNS DESCRIPTION resource
The resource as dictionary representation
TYPE: Dict[str, Any]
"},{"location":"reference/model/resource/version/","title":"Version","text":""},{"location":"reference/model/resource/version/#streampipes.model.resource.version.Version","title":"Version
","text":" Bases: Resource
Metadata about the version of the connected StreamPipes server.
ATTRIBUTE DESCRIPTION backend_version
version of the StreamPipes backend the client is connected to
TYPE: str
"},{"location":"reference/model/resource/version/#streampipes.model.resource.version.Version.convert_to_pandas_representation","title":"convert_to_pandas_representation()
","text":"Returns the dictionary representation of the version metadata to be used when creating a pandas Dataframe.
"},{"location":"scripts/gen_ref_pages/","title":"Gen ref pages","text":"Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
In\u00a0[\u00a0]: Copied! from pathlib import Path\n
from pathlib import Path In\u00a0[\u00a0]: Copied! import mkdocs_gen_files\n
import mkdocs_gen_files In\u00a0[\u00a0]: Copied! nav = mkdocs_gen_files.Nav()\n
nav = mkdocs_gen_files.Nav() In\u00a0[\u00a0]: Copied! for path in sorted(Path(\"streampipes\").rglob(\"*.py\")):\n module_path = path.relative_to(\"streampipes\").with_suffix(\"\")\n doc_path = path.relative_to(\"streampipes\").with_suffix(\".md\")\n full_doc_path = Path(\"reference\", doc_path)\n\n parts = list(module_path.parts)\n\n if parts[-1] == \"__init__\":\n # parts = parts[:-1]\n continue\n elif parts[-1] == \"__version__\":\n continue\n elif parts[-1] == \"__main__\":\n continue\n elif parts[-1] == \" \":\n continue\n\n nav[parts] = doc_path.as_posix()\n\n with mkdocs_gen_files.open(full_doc_path, \"w+\") as fd:\n identifier = \".\".join(parts)\n print(f\"::: streampipes.{identifier}\", file=fd)\n\n mkdocs_gen_files.set_edit_path(full_doc_path, path)\n
for path in sorted(Path(\"streampipes\").rglob(\"*.py\")): module_path = path.relative_to(\"streampipes\").with_suffix(\"\") doc_path = path.relative_to(\"streampipes\").with_suffix(\".md\") full_doc_path = Path(\"reference\", doc_path) parts = list(module_path.parts) if parts[-1] == \"__init__\": # parts = parts[:-1] continue elif parts[-1] == \"__version__\": continue elif parts[-1] == \"__main__\": continue elif parts[-1] == \" \": continue nav[parts] = doc_path.as_posix() with mkdocs_gen_files.open(full_doc_path, \"w+\") as fd: identifier = \".\".join(parts) print(f\"::: streampipes.{identifier}\", file=fd) mkdocs_gen_files.set_edit_path(full_doc_path, path) with mkdocs_gen_files.open(\"reference/SUMMARY.md\", \"w+\") as nav_file: nav_file.writelines(nav.build_literate_nav())
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/","title":"Introduction to StreamPipes Python","text":"In\u00a0[\u00a0]: Copied! %pip install streampipes\n
%pip install streampipes If you want to have the current development state you can also execute:
In\u00a0[\u00a0]: Copied! %pip install git+https://github.com/apache/streampipes.git#subdirectory=streampipes-client-python\n
%pip install git+https://github.com/apache/streampipes.git#subdirectory=streampipes-client-python The corresponding documentation can be found here.
In\u00a0[\u00a0]: Copied! from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
from streampipes.client import StreamPipesClient from streampipes.client.config import StreamPipesClientConfig from streampipes.client.credential_provider import StreamPipesApiKeyCredentials In\u00a0[\u00a0]: Copied! config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(\n username=\"test@streampipes.apache.org\",\n api_key=\"API-KEY\",\n ),\n host_address=\"localhost\",\n https_disabled=True,\n port=80\n)\n
config = StreamPipesClientConfig( credential_provider=StreamPipesApiKeyCredentials( username=\"test@streampipes.apache.org\", api_key=\"API-KEY\", ), host_address=\"localhost\", https_disabled=True, port=80 ) Please be aware that connecting to StreamPipes via a https
connection is currently not supported by the Python client.
Providing secrets like the api_key
as plaintext in the source code is an anti-pattern. This is why the StreamPipes client also supports passing the required secrets as environment variables. To do so, you must initialize the credential provider like the following:
In\u00a0[\u00a0]: Copied! StreamPipesApiKeyCredentials()\n
StreamPipesApiKeyCredentials() To ensure that the above code works, you must set the environment variables as expected. This can be done like following:
In\u00a0[\u00a0]: Copied! %export SP_USERNAME=\"<USERNAME>\"\n%export SP_API_KEY=\"<API-KEY>\"\n
%export SP_USERNAME=\"\" %export SP_API_KEY=\"\" Having the config
ready, we can now initialize the actual client.
In\u00a0[\u00a0]: Copied! client = StreamPipesClient(client_config=config)\n
client = StreamPipesClient(client_config=config) That's already it. You can check if everything works out by using the following command:
In\u00a0[6]: Copied! client.describe()\n
client.describe() 2023-02-24 17:05:49,398 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n2023-02-24 17:05:49,457 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n\nHi there!\nYou are connected to a StreamPipes instance running at http://localhost:80.\nThe following StreamPipes resources are available with this client:\n1x DataLakeMeasures\n1x DataStreams\n
This prints you a short textual description of the connected StreamPipes instance to the console.
The created client
instance serves as the central point of interaction with StreamPipes. You can invoke a variety of commands directly on this object.
Are you curious now how you actually can get data out of StreamPipes and make use of it with Python? Then check out the next tutorial on extracting Data from the StreamPipes data lake.
Thanks for reading this introductory tutorial. We hope you like it and would love to receive some feedback from you. Just go to our GitHub discussion page and let us know your impression. We'll read and react to them all, we promise!
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/#Introduction-to-StreamPipes-Python","title":"Introduction to StreamPipes Python\u00b6","text":""},{"location":"tutorials/1-introduction-to-streampipes-python-client/#Why-there-is-an-extra-Python-library-for-StreamPipes?","title":"Why there is an extra Python library for StreamPipes?\u00b6","text":"Apache StreamPipes aims to enable non-technical users to connect and analyze IoT data streams. To this end, it provides an easy-to-use and convenient user interface that allows one to connect to an IoT data source and create some visual graphs within a few minutes. Although this is the main use case of Apache StreamPipes, it can also provide great value for people who are eager to work on data analysis or data science with IoT data, but don't we do get in touch with all the hassle associated with extracting data from devices in a suitable format. In this scenario, StreamPipes helps you connect to your data source and extract the data for you. You then can make the data available outside StreamPipes by writing it into an external source, such as a database, Kafka, etc. While this requires another component, you can also extract your data directly from StreamPipes programmatically using the StreamPipes API. For convenience, we also provide you with a StreamPipes client both available for Java and Python. Specifically with StreamPipes Python, we want to address the amazing data analytics and data science community in Python and benefit from the great universe of Python libraries out there.
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/#How-to-install-StreamPipes-Python?","title":"How to install StreamPipes Python?\u00b6","text":"Simply use the following pip
command:
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/#How-to-prepare-the-tutorials","title":"How to prepare the tutorials\u00b6","text":"In case you want to reproduce the first two tutorials exactly on your end, you need to create a simple pipeline in StreamPipes like demonstrated below.
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/#How-to-configure-the-Python-client","title":"How to configure the Python client\u00b6","text":"In order to access the resources available in StreamPipes, one must be able to authenticate against the backend. For this purpose, the client sofar only supports the authentication via an API token that can be generated via the StreamPipes UI, as you see below.
Having generated the API token, one can directly start initializing a client instance as follows:
"},{"location":"tutorials/2-extracting-data-from-the-streampipes-data-lake/","title":"Extracting Data from the StreamPipes data lake","text":"In\u00a0[1]: Copied! from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
from streampipes.client import StreamPipesClient from streampipes.client.config import StreamPipesClientConfig from streampipes.client.credential_provider import StreamPipesApiKeyCredentials In\u00a0[\u00a0]: Copied! # if you want all necessary dependencies required for this tutorial to be installed,\n# you can simply execute the following command\n%pip install matplotlib streampipes\n
# if you want all necessary dependencies required for this tutorial to be installed, # you can simply execute the following command %pip install matplotlib streampipes In\u00a0[2]: Copied! import os\nos.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\"\nos.environ[\"SP_API_KEY\"] = \"XXX\"\n
import os os.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\" os.environ[\"SP_API_KEY\"] = \"XXX\" In\u00a0[3]: Copied! config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(),\n host_address=\"localhost\",\n https_disabled=True,\n port=80\n)\n
config = StreamPipesClientConfig( credential_provider=StreamPipesApiKeyCredentials(), host_address=\"localhost\", https_disabled=True, port=80 ) In\u00a0[4]: Copied! client = StreamPipesClient(client_config=config)\n
client = StreamPipesClient(client_config=config) 2023-02-24 17:34:25,860 - streampipes.client.client - [INFO] - [client.py:128] [_set_up_logging] - Logging successfully initialized with logging level INFO.\n
As a first step, we want to get an overview about all data available in the data lake. The data is stored as so-called measures
, which refer to a data stream stored in the data lake. For his purpose we use the all()
method of the dataLakeMeasure
endpoint.
In\u00a0[5]: Copied! data_lake_measures = client.dataLakeMeasureApi.all()\n
data_lake_measures = client.dataLakeMeasureApi.all() 2023-02-24 17:34:25,929 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n
So let's see how many measures are available
In\u00a0[6]: Copied! len(data_lake_measures)\n
len(data_lake_measures) Out[6]: 2
All resources of the StreamPipes Python client support the standard Python expressions. If not, please let us know.
In\u00a0[7]: Copied! data_lake_measures[-1]\n
data_lake_measures[-1] Out[7]: DataLakeMeasure(element_id='3cb6b5e6f107452483d1fd2ccf4bf9f9', measure_name='test', timestamp_field='s0::timestamp', event_schema=EventSchema(event_properties=[EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:EiFnkL', label='Density', description='Denotes the current density of the fluid', runtime_name='density', required=False, domain_properties=['http://schema.org/Number'], property_scope='MEASUREMENT_PROPERTY', index=5, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#float', measurement_unit=None, value_specification=None), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:ghSkQI', label='Mass Flow', description='Denotes the current mass flow in the sensor', runtime_name='mass_flow', required=False, domain_properties=['http://schema.org/Number'], property_scope='MEASUREMENT_PROPERTY', index=2, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#float', measurement_unit=None, value_specification=None), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:cQAUry', label='Sensor ID', description='The ID of the sensor', runtime_name='sensorId', required=False, domain_properties=['https://streampipes.org/vocabulary/examples/watertank/v1/hasSensorId'], property_scope='DIMENSION_PROPERTY', index=1, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#string', measurement_unit=None, value_specification=None), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:pbPMyL', label='Sensor Fault Flags', description='Any fault flags of the sensors', runtime_name='sensor_fault_flags', required=False, domain_properties=['http://schema.org/Boolean'], property_scope='MEASUREMENT_PROPERTY', index=6, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#boolean', measurement_unit=None, value_specification=None), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:Qmayhw', label='Temperature', description='Denotes the current temperature in degrees celsius', runtime_name='temperature', required=False, domain_properties=['http://schema.org/Number'], property_scope='MEASUREMENT_PROPERTY', index=4, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#float', measurement_unit='http://qudt.org/vocab/unit#DegreeCelsius', value_specification=ValueSpecification(class_name='org.apache.streampipes.model.schema.QuantitativeValue', element_id=None, min_value=0, max_value=100, step=0.1)), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:YQYhjd', label='Volume Flow', description='Denotes the current volume flow', runtime_name='volume_flow', required=False, domain_properties=['http://schema.org/Number'], property_scope='MEASUREMENT_PROPERTY', index=3, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#float', measurement_unit=None, value_specification=None)]), pipeline_id=None, pipeline_name=None, pipeline_is_running=False, schema_version='1.1')
To get a more comprehensive overview, you can take a look at the pandas
representation
In\u00a0[8]: Copied! display(data_lake_measures.to_pandas())\n
display(data_lake_measures.to_pandas()) measure_name timestamp_field pipeline_id pipeline_name pipeline_is_running num_event_properties 0 flow-rate s0::timestamp None None False 6 1 test s0::timestamp None None False 6 So far, we have only retrieved metadata about the available data lake measure. In the following, we will access the actual data of the measure flow-rate
.
For this purpose, we will use the get()
method of the dataLakeMeasure
endpoint.
In\u00a0[9]: Copied! flow_rate_measure = client.dataLakeMeasureApi.get(identifier=\"flow-rate\")\n
flow_rate_measure = client.dataLakeMeasureApi.get(identifier=\"flow-rate\") 2023-02-24 17:34:26,020 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n
For further processing, the easiest way is to turn the data measure into a pandas DataFrame
.
In\u00a0[10]: Copied! flow_rate_pd = flow_rate_measure.to_pandas()\n
flow_rate_pd = flow_rate_measure.to_pandas() Let's see how many data points we got...
In\u00a0[11]: Copied! len(flow_rate_pd)\n
len(flow_rate_pd) Out[11]: 1000
... and get a first overview
In\u00a0[12]: Copied! flow_rate_pd.describe()\n
flow_rate_pd.describe() Out[12]: density mass_flow temperature volume_flow count 1000.000000 1000.000000 1000.000000 1000.000000 mean 45.560337 5.457014 45.480231 5.659558 std 3.201544 3.184959 3.132878 3.122437 min 40.007698 0.004867 40.000992 0.039422 25% 42.819497 2.654101 42.754623 3.021625 50% 45.679264 5.382355 45.435944 5.572553 75% 48.206881 8.183144 48.248473 8.338209 max 50.998310 10.986015 50.964909 10.998676 As a final step, we want to create a plot of both attributes
In\u00a0[13]: Copied! import matplotlib.pyplot as plt\nflow_rate_pd.plot(y=[\"mass_flow\", \"temperature\"])\nplt.show()\n
import matplotlib.pyplot as plt flow_rate_pd.plot(y=[\"mass_flow\", \"temperature\"]) plt.show() For data lake measurements, the get()
method is even more powerful than simply returning all the data for a given data lake measurement. We will look at a selection of these below. The full list of supported parameters can be found in the docs. Let's start by referring to the graph we created above, where we use only two columns of our data lake measurement. If we already know this, we can directly restrict the queried data to a subset of columns by using the columns
parameter. columns
takes a list of column names as a comma-separated string:
In\u00a0[14]: Copied! flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", columns=\"mass_flow,temperature\").to_pandas()\nflow_rate_pd\n
flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", columns=\"mass_flow,temperature\").to_pandas() flow_rate_pd 2023-02-24 17:34:26,492 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n
Out[14]: timestamp mass_flow temperature 0 2023-02-24T16:19:41.472Z 3.309556 44.448483 1 2023-02-24T16:19:41.482Z 5.608580 40.322033 2 2023-02-24T16:19:41.493Z 7.692881 49.239639 3 2023-02-24T16:19:41.503Z 3.632898 49.933754 4 2023-02-24T16:19:41.513Z 0.711260 50.106617 ... ... ... ... 995 2023-02-24T16:19:52.927Z 1.740114 46.558231 996 2023-02-24T16:19:52.94Z 7.211723 48.048622 997 2023-02-24T16:19:52.952Z 7.770180 48.188026 998 2023-02-24T16:19:52.965Z 4.458602 48.280899 999 2023-02-24T16:19:52.977Z 2.592060 47.505951 1000 rows \u00d7 3 columns
By default, the client returns only the first one thousand records of a Data Lake measurement. This can be changed by passing a concrete value for the limit
parameter:
In\u00a0[15]: Copied! flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", limit=10000).to_pandas()\nlen(flow_rate_pd)\n
flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", limit=10000).to_pandas() len(flow_rate_pd) 2023-02-24 17:34:26,736 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n
Out[15]: 9528
If you want your data to be selected by time of occurrence rather than quantity, you can specify your time window by passing the start_date
and end_date
parameters:
In\u00a0[16]: Copied! from datetime import datetime\nflow_rate_pd = client.dataLakeMeasureApi.get(\n identifier=\"flow-rate\",\n start_date=datetime(year=2023, month=2, day=24, hour=17, minute=21, second=0),\n end_date=datetime(year=2023, month=2, day=24, hour=17, minute=21, second=1),\n ).to_pandas()\nflow_rate_pd.plot(y=[\"mass_flow\", \"temperature\"])\nplt.show()\n
from datetime import datetime flow_rate_pd = client.dataLakeMeasureApi.get( identifier=\"flow-rate\", start_date=datetime(year=2023, month=2, day=24, hour=17, minute=21, second=0), end_date=datetime(year=2023, month=2, day=24, hour=17, minute=21, second=1), ).to_pandas() flow_rate_pd.plot(y=[\"mass_flow\", \"temperature\"]) plt.show() 2023-02-24 17:34:26,899 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n
... from this point on we leave all future processing of the data up to your creativity. Keep in mind: the general syntax used in this tutorial (all()
, to_pandas()
, get()
) applies to all endpoints and associated resources of the StreamPipes Python client.
If you get further and create exiting stuff with data extracted from StreamPipes please let us know. We are thrilled to see what you as a community will build with the provided client. Furthermore, don't hesitate to discuss feature requests to extend the current functionality with us.
For now, that's all about the StreamPipes client. Read the next tutorial (Getting live data from the StreamPipes data stream) if you are interested in making use of the powerful StreamPipes functions to interact with StreamPipes event-based.
How do you like this tutorial? We hope you like it and would love to receive some feedback from you. Just go to our GitHub discussion page and let us know your impression. We'll read and react to them all, we promise!
"},{"location":"tutorials/2-extracting-data-from-the-streampipes-data-lake/#Extracting-Data-from-the-StreamPipes-data-lake","title":"Extracting Data from the StreamPipes data lake\u00b6","text":"In the first tutorial (Introduction to the StreamPipes Python client) we took the first steps with the StreamPipes Python client and learned how to set everything up. Now we are ready to get started and want to retrieve some data out of StreamPipes. In this tutorial, we'll focus on the StreamPipes Data Lake, the component where StreamPipes stores data internally. To get started, we'll use the client
instance created in the first tutorial.
"},{"location":"tutorials/3-getting-live-data-from-the-streampipes-data-stream/","title":"Getting live data from the StreamPipes data stream","text":"Note As of now we mainly developed the support for StreamPipes functions using NATS as messaging protocol. Consequently, this setup is tested most and should work flawlessly. Visit our first-steps page to see how to start StreamPipes accordingly. Anyhow, you can also use the other brokers that are currently supported in StreamPipes Python. In case you observe any problems, please reach out to us and file us an issue on GitHub.
In\u00a0[1]: Copied! from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
from streampipes.client import StreamPipesClient from streampipes.client.config import StreamPipesClientConfig from streampipes.client.credential_provider import StreamPipesApiKeyCredentials In\u00a0[\u00a0]: Copied! # You can install all required libraries for this tutorial with the following command\n%pip install matplotlib ipython streampipes\n
# You can install all required libraries for this tutorial with the following command %pip install matplotlib ipython streampipes In\u00a0[2]: Copied! import os\n\nos.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\"\nos.environ[\"SP_API_KEY\"] = \"XXX\"\n\n# Use this if you work locally:\nos.environ[\"BROKER-HOST\"] = \"localhost\" \nos.environ[\"KAFKA-PORT\"] = \"9094\" # When using Kafka as message broker. If Kafka is not running on localhost, KAFKA_ADVERTISED_LISTENERS should be adjusted to the external address\n
import os os.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\" os.environ[\"SP_API_KEY\"] = \"XXX\" # Use this if you work locally: os.environ[\"BROKER-HOST\"] = \"localhost\" os.environ[\"KAFKA-PORT\"] = \"9094\" # When using Kafka as message broker. If Kafka is not running on localhost, KAFKA_ADVERTISED_LISTENERS should be adjusted to the external address In\u00a0[3]: Copied! client_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(),\n host_address=\"localhost\",\n port=80,\n https_disabled=True,\n)\nclient = StreamPipesClient(client_config=client_config)\n
client_config = StreamPipesClientConfig( credential_provider=StreamPipesApiKeyCredentials(), host_address=\"localhost\", port=80, https_disabled=True, ) client = StreamPipesClient(client_config=client_config) 2022-12-14 10:43:37,664 - streampipes.client.client - [INFO] - [client.py:127] [_set_up_logging] - Logging successfully initialized with logging level INFO.\n
Now we can have a look at the available data streams. We can choose one or more stream to receive the data from and copy their element_id
.
In\u00a0[4]: Copied! client.dataStreamApi.all().to_pandas()\n
client.dataStreamApi.all().to_pandas() 2022-12-14 10:43:39,944 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:153] [_make_request] - Successfully retrieved all resources.\n
Out[4]: element_id name description icon_url app_id includes_assets includes_locales internally_managed measurement_object index ... uri dom num_transport_protocols num_measurement_capability num_application_links num_included_assets num_connected_to num_category num_event_properties num_included_locales 0 urn:streampipes.apache.org:eventstream:HHoidJ Test2 None None False False True None 0 ... urn:streampipes.apache.org:eventstream:HHoidJ None 1 0 0 0 0 0 7 0 1 urn:streampipes.apache.org:eventstream:uPDKLI Test None None False False True None 0 ... urn:streampipes.apache.org:eventstream:uPDKLI None 1 0 0 0 0 0 7 0 2 rows \u00d7 21 columns
Next we can create a StreamPipesFunction. For this we need to implement the 3 following methods:
onServiceStarted
is called when the function gets started. There you can use the given meta information of the FunctionContext
to initialize the function. onEvent
is called when ever a new event arrives. The event
contains the live data and you can use the streamId
to identify a stream if the function is connected to multiple data streams. onServiceStopped
is called when the function gets stopped.
For this tutorial we just create a function that saves every new event in a pandas DataFrame
and plots the first column of the DataFrame
when the function gets stopped.
(If you want to use the same structure as in Java you can overwrite the getFunctionId
and requiredStreamIds
methods instead of using the FunctionDefinition
)
In\u00a0[5]: Copied! from typing import Dict, Any\nimport pandas as pd\nfrom datetime import datetime\nimport matplotlib.pyplot as plt\nfrom streampipes.functions.function_handler import FunctionHandler\nfrom streampipes.functions.registration import Registration\nfrom streampipes.functions.streampipes_function import StreamPipesFunction\nfrom streampipes.functions.utils.function_context import FunctionContext\nfrom streampipes.model.resource.function_definition import FunctionDefinition, FunctionId\n\nclass ExampleFunction(StreamPipesFunction):\n def __init__(self, function_definition: FunctionDefinition) -> None:\n super().__init__(function_definition)\n # Create the Dataframe to save the live data\n self.df = pd.DataFrame()\n\n def onServiceStarted(self, context: FunctionContext):\n # Get the name of the timestamp field\n for event_property in context.schema[context.streams[0]].event_schema.event_properties:\n if event_property.property_scope == \"HEADER_PROPERTY\":\n self.timestamp = event_property.runtime_name\n\n def onEvent(self, event: Dict[str, Any], streamId: str):\n # Convert the unix timestamp to datetime\n event[self.timestamp] = datetime.fromtimestamp(event[self.timestamp] / 1000)\n # Add every value of the event to the DataFrame\n self.df = pd.concat(\n [self.df, pd.DataFrame({key: [event[key]] for key in event.keys()}).set_index(self.timestamp)]\n )\n\n def onServiceStopped(self):\n # Plot the first column of the Dataframe\n plt.figure(figsize=(10, 5))\n plt.xlabel(self.timestamp)\n plt.ylabel(self.df.columns[0])\n plt.plot(self.df.iloc[:, 0])\n plt.show()\n
from typing import Dict, Any import pandas as pd from datetime import datetime import matplotlib.pyplot as plt from streampipes.functions.function_handler import FunctionHandler from streampipes.functions.registration import Registration from streampipes.functions.streampipes_function import StreamPipesFunction from streampipes.functions.utils.function_context import FunctionContext from streampipes.model.resource.function_definition import FunctionDefinition, FunctionId class ExampleFunction(StreamPipesFunction): def __init__(self, function_definition: FunctionDefinition) -> None: super().__init__(function_definition) # Create the Dataframe to save the live data self.df = pd.DataFrame() def onServiceStarted(self, context: FunctionContext): # Get the name of the timestamp field for event_property in context.schema[context.streams[0]].event_schema.event_properties: if event_property.property_scope == \"HEADER_PROPERTY\": self.timestamp = event_property.runtime_name def onEvent(self, event: Dict[str, Any], streamId: str): # Convert the unix timestamp to datetime event[self.timestamp] = datetime.fromtimestamp(event[self.timestamp] / 1000) # Add every value of the event to the DataFrame self.df = pd.concat( [self.df, pd.DataFrame({key: [event[key]] for key in event.keys()}).set_index(self.timestamp)] ) def onServiceStopped(self): # Plot the first column of the Dataframe plt.figure(figsize=(10, 5)) plt.xlabel(self.timestamp) plt.ylabel(self.df.columns[0]) plt.plot(self.df.iloc[:, 0]) plt.show() Now we can start the function. First we create an instance of the ExampleFunction
and insert the element_id
of the stream which data we want to consume. Then we have to register this function and we can start all functions by initializing the FunctionHandler
. (it's also possible to register multiple functions with .register(...).register(...)
)
In\u00a0[6]: Copied! example_function = ExampleFunction(\n FunctionDefinition(\n function_id=FunctionId(id=\"example-function\"),\n consumed_streams=[\"urn:streampipes.apache.org:eventstream:uPDKLI\"]\n )\n)\n\nregistration = Registration()\nregistration.register(example_function)\n\nfunction_handler = FunctionHandler(registration, client)\nfunction_handler.initializeFunctions()\n
example_function = ExampleFunction( FunctionDefinition( function_id=FunctionId(id=\"example-function\"), consumed_streams=[\"urn:streampipes.apache.org:eventstream:uPDKLI\"] ) ) registration = Registration() registration.register(example_function) function_handler = FunctionHandler(registration, client) function_handler.initializeFunctions() 2022-12-14 10:43:42,810 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:153] [_make_request] - Successfully retrieved all resources.\n2022-12-14 10:43:42,812 - streampipes.functions.function_handler - [INFO] - [function_handler.py:82] [initializeFunctions] - Using NatsBroker for <__main__.ExampleFunction object at 0x000001F2EF298D90>\n
The DataFrame
of the ExampleFunction
gets updated whenever a new event arrives. Let's test this by executing the cell below.
In\u00a0[7]: Copied! import asyncio\nfrom asyncio.exceptions import CancelledError\nfrom IPython.display import clear_output\n\nwhile True:\n clear_output(wait=True)\n display(example_function.df)\n try:\n await asyncio.sleep(1)\n except CancelledError:\n break\n
import asyncio from asyncio.exceptions import CancelledError from IPython.display import clear_output while True: clear_output(wait=True) display(example_function.df) try: await asyncio.sleep(1) except CancelledError: break mass_flow density volume_flow sensor_fault_flags temperature sensorId timestamp 2022-12-14 10:43:43.357 10.955496 47.546290 1.001985 False 44.993413 flowrate02 2022-12-14 10:43:44.371 6.499040 44.392069 2.034402 False 41.232352 flowrate02 2022-12-14 10:43:45.382 10.168300 41.192146 9.724287 False 46.812779 flowrate02 2022-12-14 10:43:46.395 10.849059 50.086308 5.832691 False 45.860412 flowrate02 2022-12-14 10:43:47.410 3.081855 47.254246 8.860531 False 50.505801 flowrate02 ... ... ... ... ... ... ... 2022-12-14 10:44:43.920 1.803572 41.978894 10.294002 False 47.820239 flowrate02 2022-12-14 10:44:44.932 1.967062 42.212883 3.237440 False 49.047258 flowrate02 2022-12-14 10:44:45.934 4.457819 47.561256 0.315024 False 40.223413 flowrate02 2022-12-14 10:44:46.949 8.745343 46.346891 7.439090 False 41.982529 flowrate02 2022-12-14 10:44:47.950 5.828744 47.679720 6.307405 False 42.100354 flowrate02 65 rows \u00d7 6 columns
The while
loop just displays the the DataFrame
every second until the cell is stopped. We could achieve the same result manually by executing example_function.df
repeatedly.
You can stop the functions whenever you want by executing the command below.
In\u00a0[\u00a0]: Copied! function_handler.disconnect()\n
function_handler.disconnect() 2022-12-14 10:44:53,309 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:67] [disconnect] - Stopped connection to stream: urn:streampipes.apache.org:eventstream:uPDKLI\n
That's enough for this tutorial. Now you can try to write your own StreamPipesFunction
. All you need to do is creating a new class, implementing the 4 required methods and registering the function.
Want to see more exciting use cases you can achieve with StreamPipes functions in Python? Then don't hesitate and jump to our next tutorial on applying online machine learning algorithms to StreamPipes data streams with River.
How do you like this tutorial? We hope you like it and would love to receive some feedback from you. Just go to our GitHub discussion page and let us know your impression. We'll read and react to them all, we promise!
"},{"location":"tutorials/3-getting-live-data-from-the-streampipes-data-stream/#Getting-live-data-from-the-StreamPipes-data-stream","title":"Getting live data from the StreamPipes data stream\u00b6","text":"In the last tutorial (Extracting Data from the StreamPipes data lake) we learned how to extract the stored data from a StreamPipes data lake. This tutorial is about the StreamPipes data stream and shows how to get the live data from StreamPipes into Python. Therefore, we first create the client
instance as before.
"},{"location":"tutorials/4-using-online-machine-learning-on-a-streampipes-data-stream/","title":"Using Online Machine Learning on a StreamPipes data stream","text":"In\u00a0[1]: Copied! from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
from streampipes.client import StreamPipesClient from streampipes.client.config import StreamPipesClientConfig from streampipes.client.credential_provider import StreamPipesApiKeyCredentials In\u00a0[\u00a0]: Copied! # you can install all required dependecies for this tutorial by executing the following command\n%pip install river streampipes\n
# you can install all required dependecies for this tutorial by executing the following command %pip install river streampipes In\u00a0[2]: Copied! import os\n\nos.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\"\nos.environ[\"SP_API_KEY\"] = \"XXX\"\n\n# Use this if you work locally:\nos.environ[\"BROKER-HOST\"] = \"localhost\" \nos.environ[\"KAFKA-PORT\"] = \"9094\" # When using Kafka as message broker\n
import os os.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\" os.environ[\"SP_API_KEY\"] = \"XXX\" # Use this if you work locally: os.environ[\"BROKER-HOST\"] = \"localhost\" os.environ[\"KAFKA-PORT\"] = \"9094\" # When using Kafka as message broker In\u00a0[3]: Copied! client_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(),\n host_address=\"localhost\",\n port=80,\n https_disabled=True,\n)\nclient = StreamPipesClient(client_config=client_config)\n
client_config = StreamPipesClientConfig( credential_provider=StreamPipesApiKeyCredentials(), host_address=\"localhost\", port=80, https_disabled=True, ) client = StreamPipesClient(client_config=client_config) 2023-01-27 16:04:24,784 - streampipes.client.client - [INFO] - [client.py:128] [_set_up_logging] - Logging successfully initialized with logging level INFO.\n
In\u00a0[4]: Copied! client.dataStreamApi.all().to_pandas()\n
client.dataStreamApi.all().to_pandas() 2023-01-27 16:04:28,212 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:163] [_make_request] - Successfully retrieved all resources.\n
Out[4]: element_id name description icon_url app_id includes_assets includes_locales internally_managed measurement_object index ... dom rev num_transport_protocols num_measurement_capability num_application_links num_included_assets num_connected_to num_category num_event_properties num_included_locales 0 sp:spdatastream:xboBFK Test None None False False True None 0 ... None 5-558c861debc745e1ebae29a266a8bdb9 1 0 0 0 0 0 7 0 1 urn:streampipes.apache.org:eventstream:Wgyrse Test File None None False False True None 0 ... None 4-66548b6b84287011b7cec0876ef82baf 1 0 0 0 0 0 2 0 2 rows \u00d7 22 columns
In\u00a0[5]: Copied! from river import cluster, compose, preprocessing\nfrom streampipes.function_zoo.river_function import OnlineML\nfrom streampipes.functions.utils.data_stream_generator import RuntimeType\n\nk_means = compose.Pipeline(\n (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")),\n (\"scale\", preprocessing.StandardScaler()),\n (\"k_means\", cluster.KMeans(n_clusters=2)),\n)\n\nclustering = OnlineML(\n client=client, stream_ids=[\"sp:spdatastream:xboBFK\"], model=k_means, prediction_type=RuntimeType.INTEGER.value\n)\nclustering.start()\n
from river import cluster, compose, preprocessing from streampipes.function_zoo.river_function import OnlineML from streampipes.functions.utils.data_stream_generator import RuntimeType k_means = compose.Pipeline( (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")), (\"scale\", preprocessing.StandardScaler()), (\"k_means\", cluster.KMeans(n_clusters=2)), ) clustering = OnlineML( client=client, stream_ids=[\"sp:spdatastream:xboBFK\"], model=k_means, prediction_type=RuntimeType.INTEGER.value ) clustering.start() 2023-01-27 16:04:35,599 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:163] [_make_request] - Successfully retrieved all resources.\n2023-01-27 16:04:35,599 - streampipes.functions.function_handler - [INFO] - [function_handler.py:64] [initializeFunctions] - Create output data stream \"sp:spdatastream:cwKPoo\" for the function \"65cf8b86-bcdf-433e-a1c7-3e920eab55d0\"\n2023-01-27 16:04:37,766 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:163] [_make_request] - Successfully retrieved all resources.\n2023-01-27 16:04:37,767 - streampipes.functions.function_handler - [INFO] - [function_handler.py:78] [initializeFunctions] - Using NatsBroker for RiverFunction\n2023-01-27 16:04:37,791 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:48] [_makeConnection] - Connected to NATS at localhost:4222\n2023-01-27 16:04:37,791 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:48] [_makeConnection] - Connected to NATS at localhost:4222\n2023-01-27 16:04:37,792 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:58] [createSubscription] - Subscribed to stream: sp:spdatastream:xboBFK\n
In\u00a0[6]: Copied! clustering.set_learning(False)\n
clustering.set_learning(False) In\u00a0[\u00a0]: Copied! clustering.stop()\n
clustering.stop() 2023-01-27 16:04:57,303 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:82] [disconnect] - Stopped connection to stream: sp:spdatastream:xboBFK\n2023-01-27 16:04:57,304 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:82] [disconnect] - Stopped connection to stream: sp:spdatastream:cwKPoo\n
In\u00a0[\u00a0]: Copied! import pickle\nfrom river import compose, tree\nfrom streampipes.function_zoo.river_function import OnlineML\nfrom streampipes.functions.utils.data_stream_generator import RuntimeType\n\nhoeffding_tree = compose.Pipeline(\n (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")),\n (\"hoeffding_tree\", tree.HoeffdingTreeRegressor(grace_period=5)),\n)\n\n\ndef draw_tree(self, event, streamId):\n\"\"\"Draw the tree and save the image.\"\"\"\n if self.learning:\n if self.model[1].n_nodes != None:\n self.model[1].draw().render(\"hoeffding_tree\", format=\"png\", cleanup=True)\n\n\ndef save_model(self):\n\"\"\"Save the trained model.\"\"\"\n with open(\"hoeffding_tree.pkl\", \"wb\") as f:\n pickle.dump(self.model, f)\n\n\nregressor = OnlineML(\n client=client,\n stream_ids=[\"sp:spdatastream:xboBFK\"],\n model=hoeffding_tree,\n prediction_type=RuntimeType.FLOAT.value,\n supervised=True,\n target_label=\"temperature\",\n on_event=draw_tree,\n on_stop=save_model,\n)\nregressor.start()\n
import pickle from river import compose, tree from streampipes.function_zoo.river_function import OnlineML from streampipes.functions.utils.data_stream_generator import RuntimeType hoeffding_tree = compose.Pipeline( (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")), (\"hoeffding_tree\", tree.HoeffdingTreeRegressor(grace_period=5)), ) def draw_tree(self, event, streamId): \"\"\"Draw the tree and save the image.\"\"\" if self.learning: if self.model[1].n_nodes != None: self.model[1].draw().render(\"hoeffding_tree\", format=\"png\", cleanup=True) def save_model(self): \"\"\"Save the trained model.\"\"\" with open(\"hoeffding_tree.pkl\", \"wb\") as f: pickle.dump(self.model, f) regressor = OnlineML( client=client, stream_ids=[\"sp:spdatastream:xboBFK\"], model=hoeffding_tree, prediction_type=RuntimeType.FLOAT.value, supervised=True, target_label=\"temperature\", on_event=draw_tree, on_stop=save_model, ) regressor.start() In\u00a0[9]: Copied! regressor.set_learning(False)\n
regressor.set_learning(False) In\u00a0[\u00a0]: Copied! regressor.stop()\n
regressor.stop() In\u00a0[\u00a0]: Copied! import pickle\nfrom river import compose, tree\nfrom streampipes.function_zoo.river_function import OnlineML\nfrom streampipes.functions.utils.data_stream_generator import RuntimeType\n\ndecision_tree = compose.Pipeline(\n (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")),\n (\"decision_tree\", tree.ExtremelyFastDecisionTreeClassifier(grace_period=5)),\n)\n\n\ndef draw_tree(self, event, streamId):\n\"\"\"Draw the tree and save the image.\"\"\"\n if self.learning:\n if self.model[1].n_nodes != None:\n self.model[1].draw().render(\"decicion_tree\", format=\"png\", cleanup=True)\n\n\ndef save_model(self):\n\"\"\"Save the trained model.\"\"\"\n with open(\"decision_tree.pkl\", \"wb\") as f:\n pickle.dump(self.model, f)\n\n\nclassifier = OnlineML(\n client=client,\n stream_ids=[\"sp:spdatastream:xboBFK\"],\n model=decision_tree,\n prediction_type=RuntimeType.BOOLEAN.value,\n supervised=True,\n target_label=\"sensor_fault_flags\",\n on_event=draw_tree,\n on_stop=save_model,\n)\nclassifier.start()\n
import pickle from river import compose, tree from streampipes.function_zoo.river_function import OnlineML from streampipes.functions.utils.data_stream_generator import RuntimeType decision_tree = compose.Pipeline( (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")), (\"decision_tree\", tree.ExtremelyFastDecisionTreeClassifier(grace_period=5)), ) def draw_tree(self, event, streamId): \"\"\"Draw the tree and save the image.\"\"\" if self.learning: if self.model[1].n_nodes != None: self.model[1].draw().render(\"decicion_tree\", format=\"png\", cleanup=True) def save_model(self): \"\"\"Save the trained model.\"\"\" with open(\"decision_tree.pkl\", \"wb\") as f: pickle.dump(self.model, f) classifier = OnlineML( client=client, stream_ids=[\"sp:spdatastream:xboBFK\"], model=decision_tree, prediction_type=RuntimeType.BOOLEAN.value, supervised=True, target_label=\"sensor_fault_flags\", on_event=draw_tree, on_stop=save_model, ) classifier.start() In\u00a0[12]: Copied! classifier.set_learning(False)\n
classifier.set_learning(False) In\u00a0[\u00a0]: Copied! classifier.stop()\n
classifier.stop() How do you like this tutorial? We hope you like it and would love to receive some feedback from you. Just go to our GitHub discussion page and let us know your impression. We'll read and react to them all, we promise!
"},{"location":"tutorials/4-using-online-machine-learning-on-a-streampipes-data-stream/#Using-Online-Machine-Learning-on-a-StreamPipes-data-stream","title":"Using Online Machine Learning on a StreamPipes data stream\u00b6","text":"The last tutorial (Getting live data from the StreamPipes data stream) showed how we can connect to a data stream, and it would be possible to use Online Machine Learning with this approach and train a model with the incoming events at the onEvent
method. However, the StreamPipes client also provides an easier way to do this with the use of the River library for Online Machine Learning. We will have a look at this now.
"},{"location":"tutorials/4-using-online-machine-learning-on-a-streampipes-data-stream/#How-to-use-Online-Machine-Learning-with-StreamPipes","title":"How to use Online Machine Learning with StreamPipes\u00b6","text":"After we configured the client as usual, we can start with the new part. The approach is straight forward and you can start with the ML part in just 3 steps:
- Create a pipeline with River and insert the preprocessing steps and model of your choice.
- Configure the
OnlineML
wrapper to fit to your model and insert the client and required data stream ids. - Start the wrapper and let the learning begin.
A StreamPipesFunction is then started, which trains the model for each new event. It also creates an output data stream which will send the prediction of the model back to StreamPipes. This output stream can be seen when creating a new pipeline and can be used like every other data source. So you can use it in a pipeline and save the predictions in a Data Lake. You can also stop and start the training with the method set_learning
. To stop the whole function use the stop
methode and if you want to delete the output stream entirely, you can go to the Pipeline Element Installer
in StreamPipes and uninstall it.
Now let's take a look at some examples. If you want to execute the examples below you have to create an adapter for the Machine Data Simulator
, select the flowrate
sensor and insert the stream id of this stream.
"},{"location":"tutorials/4-using-online-machine-learning-on-a-streampipes-data-stream/#KMeans","title":"KMeans\u00b6","text":""},{"location":"tutorials/4-using-online-machine-learning-on-a-streampipes-data-stream/#HoeffdingTreeRegressor","title":"HoeffdingTreeRegressor\u00b6","text":""},{"location":"tutorials/4-using-online-machine-learning-on-a-streampipes-data-stream/#DecisionTreeClassifier","title":"DecisionTreeClassifier\u00b6","text":""}]}
\ No newline at end of file
+{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"\ud83c\udfe1 Home","text":"StreamPipes is a self-service (Industrial) IoT toolbox to enable non-technical users to connect, analyze and explore IoT data streams. Dependency issue with StreamPipes Python 0.92.0
In StreamPipes Python 0.92.0
there is a problem with the required dependencies. Pydantic has recently released the new version 2.0
with many exciting improvements, but also some breaking changes. Unfortunately, we didn't limit our requirements strictly enough, so yydantic 2.0
is installed together with streampipes, which is not (yet) compatible. To fix this bug, simply run the following command after installing streampipes, or adjust your dependencies accordingly:
pip install \"pydantic<2.0\" \"pydantic_core<2.0\"\n
Apache StreamPipes for Python \ud83d\udc0d Apache StreamPipes meets Python! We are working highly motivated on a Python library to interact with StreamPipes. In this way, we would like to unite the power of StreamPipes to easily connect to and read from different data sources, especially in the IoT domain, and the amazing universe of data analytics libraries in Python.
StreamPipes Python is in beta
The current version of this Python library is still a beta version. This means that it is still heavily under development, which may result in frequent and extensive API changes, unstable behavior, etc.
"},{"location":"#quickstart","title":"\u26a1\ufe0f Quickstart","text":"As a quick example, we demonstrate how to set up and configure a StreamPipes client. In addition, we will get the available data lake measures out of StreamPipes.
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nconfig = StreamPipesClientConfig(\n credential_provider = StreamPipesApiKeyCredentials(\n username = \"test@streampipes.apache.org\",\n api_key = \"DEMO-KEY\",\n ),\n host_address = \"localhost\",\n https_disabled = True,\n port = 80\n)\n\nclient = StreamPipesClient(client_config=config)\n\n# get all available datat lake measures\nmeasures = client.dataLakeMeasureApi.all()\n\n# get amount of retrieved measures\nlen(measures)\n
Output: 1\n
# inspect the data lake measures as pandas dataframe\nmeasures.to_pandas()\n
Output:
measure_name timestamp_field ... pipeline_is_running num_event_properties\n0 test s0::timestamp ... False 2\n[1 rows x 6 columns]\n
Alternatively, you can provide your credentials via environment variables. Simply define your credential provider as follows: from streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nStreamPipesApiKeyCredentials()\n
This requires to set the following environment variables: SP_API_KEY
and SP_USERNAME
username
is always the username that is used to log in into StreamPipes.
How to get your StreamPipes API key The api_key
can be generated within the UI as demonstrated below:
"},{"location":"getting-started/developing/","title":"Developing & Contributing","text":""},{"location":"getting-started/developing/#development-guide","title":"\ud83d\udcd6 Development Guide","text":"This document describes how to easily set up your local dev environment to work on StreamPipes Python \ud83d\udc0d.
"},{"location":"getting-started/developing/#first-steps","title":"\ud83d\ude80 First Steps","text":"1) Set up your Python environment
Create a virtual Python environment using a tool of your choice. To manage dependencies, we use Poetry, so please install poetry in your local environment, e.g. via
pip install poetry\n
Once poetry is installed you can simply finalize your Python environment by running:
poetry install --with dev,stubs # install everything that is required for the development\npoetry install --with docs # install everything to work with the documentation\npoetry install --with dev,stubs,docs # install all optional dependencies related to development\n
2) Install pre-commit hook
The pre-commit hook is run before every commit and takes care about code style, linting, type hints, import sorting, etc. It will stop your commit in case the changes do not apply the expected format. Always check to have the recent version of the pre-commit hook installed otherwise the CI build might fail. If you are interested, you can have a deeper look on the underlying library: pre-commit.
pre-commit install\n
The definition of the pre-commit hook can be found in .pre-commit-config.yaml. "},{"location":"getting-started/developing/#conventions","title":"\ud83d\udc4f Conventions","text":"Below we list some conventions that we have agreed on for creating StreamPipes Python. Please comply to them when you plan to contribute to this project. If you have any other suggestions or would like to discuss them, we would be happy to hear from you on our mailing list dev@streampipes.apache.org or in our discussions on GitHub.
1) Use numpy
style for Python docstrings \ud83d\udcc4 Please stick to the numpy
style when writing docstrings, as we require this for generating our documentation.
2) Provide tests \u2705 We are aiming for broad test coverage for the Python package and have therefore set a requirement of at least 90% unit test coverage. Therefore, please remember to write (unit) tests already during development. If you have problems with writing tests, don't hesitate to ask us for help directly in the PR or even before that via our mailing list (see above).
3) Build a similar API as the Java client provides \ud83d\udd04 Whenever possible, please try to develop the API of the Python library the same as the Java client or Java SDK. By doing so, we would like to provide a consistent developer experience and the basis for automated testing in the future.
"},{"location":"getting-started/developing/#dependency-management","title":"\ud83d\udce6 Dependency Management","text":"In case you want to add a new dependency to StreamPipes you can use the following command:
poetry add <dep-name>\n
If the dependency is only required for development purpose or the documentation, please stick to one the following:
poetry add <dep-name> --group dev\npoetry add <dep-name> --group stubs\npoetry add <dep-name> --group docs\n
In case you want to regenerate the poetry lock file, e.g., in case you manually updated the pyproject.toml
, the following command should be used:
poetry lock --no-update\n
After that, you should install the current version of the poetry lock file to keep your local environment consistent (see command above.)
"},{"location":"getting-started/developing/#documentation","title":"\ud83d\udcdaDocumentation","text":"To build our documentation, we use Materials for MkDocs. All files can be found within the docs
directory. To pre-view your local version of the documentation, you can use the following command:
make livedoc\n
"},{"location":"getting-started/developing/#roadmap","title":"\ud83d\ude80 Roadmap","text":"Broadly speaking, we plan to expand or add new aspects/functionality to the library where we are focusing on the following:
- increase coverage of StreamPipes API \ud83d\udd17
- build a comprehensive function zoo \ud83d\udc18
- support more messaging broker \ud83d\udcec
- possibility to build pipeline elements \ud83d\udd27
In case you want to have a more detailed look on what we are currently planning, have a look at our open issues(more short-term driven).
Of course, contributions are always highly appreciated \ud83d\udd2e
Stay tuned!
"},{"location":"getting-started/developing/#contributing","title":"\ud83d\udc68\u200d\ud83d\udcbb Contributing","text":"Before opening a pull request, review the Get Involved page. It lists information that is required for contributing to StreamPipes.
When you contribute code, you affirm that the contribution is your original work and that you license the work to the project under the project's open source license. Whether or not you state this explicitly, by submitting any copyrighted material via pull request, email, or other means you agree to license the material under the project's open source license and warrant that you have the legal authority to do so.
"},{"location":"getting-started/first-steps/","title":"First Steps","text":""},{"location":"getting-started/first-steps/#installation","title":"\ud83d\udcda Installation","text":"The StreamPipes Python library is meant to work with Python 3.8 and above. Installation can be done via pip
: You can install the latest development version from GitHub, as so:
pip install streampipes\n\n# if you want to have the current development state you can also execute\npip install git+https://github.com/apache/streampipes.git#subdirectory=streampipes-client-python\n# the corresponding documentation can be found here: https://streampipes.apache.org/docs/docs/python/dev/\n
"},{"location":"getting-started/first-steps/#setting-up-streampipes","title":"\u2b06\ufe0f Setting up StreamPipes","text":"When working with the StreamPipes Python library it is inevitable to have a running StreamPipes instance to connect and interact with. In case you don't have a running instance at hand, you can easily set up one on your local machine. Hereby you need to consider that StreamPipes supports different message broker (e.g., Kafka, NATS). We will demonstrate below how you can easily set up StreamPipes for both supported message brokers.
"},{"location":"getting-started/first-steps/#start-streampipes-via-docker-compose","title":"\ud83d\udc33 Start StreamPipes via Docker Compose","text":"The easiest and therefore recommend way to get StreamPipes started is by using docker compose. Therefore, you need Docker running. You can check if Docker is ready on your machine by executing.
docker ps\n
If this results in an output similar to the following, Docker is ready to continue. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES\n... ... ... ... ... ... ...\n
Otherwise, you need to start docker first. Please read the full guide on how to start StreamPipes with docker compose
here."},{"location":"getting-started/first-steps/#setup-streampipes-with-nats-as-message-broker","title":"Setup StreamPipes with NATS as message broker","text":"The following shows how you can set up a StreamPipes instance that uses NATS as messaging layer. So in this scenario, we will go with docker-compose.nats.yml
. Thereby, when running locally, we need to add the following port mapping entry to services.nats.ports
:
- 4222:4222\n
After this modification is applied, StreamPipes can simply be started with this command:
docker-compose -f docker-compose.nats.yml up -d\n
Once all services are started, you can access StreamPipes via http://localhost
.
"},{"location":"getting-started/first-steps/#setup-streampipes-with-kafka-as-message-broker","title":"Setup StreamPipes with Kafka as message broker","text":"Alternatively, you can use docker-compose.yml
to start StreamPipes with Kafka as messaging layer. When running locally we have to modify services.kafka.environment
and add the ports to services.kafka.ports
:
environment:\nKAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,OUTSIDE:PLAINTEXT\nKAFKA_ADVERTISED_LISTENERS: PLAINTEXT://:9092,OUTSIDE://localhost:9094\nKAFKA_LISTENERS: PLAINTEXT://:9092,OUTSIDE://:9094\n...\nports:\n- 9094:9094\n
Then, you need to execute the following command: docker-compose -f docker-compose.yml up -d\n
Once all services are started, you can access StreamPipes via http://localhost
.
In case you want to have more control over your StreamPipes setup, you might take a look at our deployment CLI.
Have fun discovering StreamPipes and our Python library \ud83d\ude80
"},{"location":"getting-started/quickstart/","title":"Quickstart","text":""},{"location":"getting-started/quickstart/#quickstart","title":"\u26a1\ufe0f Quickstart","text":"As a quick example, we demonstrate how to set up and configure a StreamPipes client. In addition, we will get the available data lake measures out of StreamPipes.
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nconfig = StreamPipesClientConfig(\n credential_provider = StreamPipesApiKeyCredentials(\n username = \"test@streampipes.apache.org\",\n api_key = \"DEMO-KEY\",\n ),\n host_address = \"localhost\",\n https_disabled = True,\n port = 80\n)\n\nclient = StreamPipesClient(client_config=config)\n\n# get all available datat lake measures\nmeasures = client.dataLakeMeasureApi.all()\n\n# get amount of retrieved measures\nlen(measures)\n
Output: 1\n
# inspect the data lake measures as pandas dataframe\nmeasures.to_pandas()\n
Output:
measure_name timestamp_field ... pipeline_is_running num_event_properties\n0 test s0::timestamp ... False 2\n[1 rows x 6 columns]\n
Alternatively, you can provide your credentials via environment variables. Simply define your credential provider as follows: from streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nStreamPipesApiKeyCredentials()\n
This requires to set the following environment variables: SP_API_KEY
and SP_USERNAME
username
is always the username that is used to log in into StreamPipes. The api_key
can be generated within the UI as demonstrated below:
"},{"location":"reference/client/client/","title":"Client","text":"Implementation of the StreamPipes client. The client is designed as the central point of interaction with the StreamPipes API and provides all functionalities to communicate with the API.
"},{"location":"reference/client/client/#streampipes.client.client.StreamPipesClient","title":"StreamPipesClient(client_config, logging_level=logging.INFO)
","text":"The client to connect to StreamPipes.
This is the central point of contact with StreamPipes and provides all the functionalities to interact with it.
The client provides so-called \"endpoints\" each of which refers to an endpoint of the StreamPipes API, e.g. .dataLakeMeasureApi
. An endpoint provides the actual methods to interact with StreamPipes API.
PARAMETER DESCRIPTION client_config
Configures the client to connect properly to the StreamPipes instance.
TYPE: StreamPipesClientConfig
logging_level
Influences the log messages emitted by the StreamPipesClient
TYPE: Optional[int]
DEFAULT: logging.INFO
ATTRIBUTE DESCRIPTION dataLakeMeasureApi
Instance of the data lake measure endpoint
TYPE: DataLakeMeasureEndpoint
dataStreamApi
Instance of the data stream endpoint
TYPE: DataStreamEndpoint
RAISES DESCRIPTION AttributeError:
In case an invalid configuration of the StreamPipesClientConfig
is passed
Examples:
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
client_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(\n username=\"test-user\",\n api_key=\"api-key\"\n ),\n host_address=\"localhost\",\n https_disabled=True\n)\n
The following way of instantiating a client instance is intended to be consistent with the StreamPipes Java client.
client = StreamPipesClient.create(client_config=client_config)\n
If you prefer a more pythonic way, you can simply write:
client = StreamPipesClient(client_config=client_config)\n
To interact with an endpoint:
data_lake_measures = client.dataLakeMeasureApi.all()\n
To inspect returned data as a pandas dataframe:
data_lake_measures.to_pandas()\n#\n# measure_name timestamp_field ... pipeline_is_running num_event_properties\n# 0 test s0::timestamp ... False 2\n# [1 rows x 6 columns]\n
"},{"location":"reference/client/client/#streampipes.client.client.StreamPipesClient.base_api_path","title":"base_api_path: str
property
","text":"Constructs the basic API URL from the given client_config
.
RETURNS DESCRIPTION base_api_path
basic API path of the connected StreamPipes instance
TYPE: str
"},{"location":"reference/client/client/#streampipes.client.client.StreamPipesClient.http_headers","title":"http_headers: Dict[str, str]
property
","text":"Returns the HTTP headers used for all requests.
The HTTP headers are composed of the authentication headers supplied by the credential provider and additional required headers (currently this is only the application header).
RETURNS DESCRIPTION http_headers
header information for HTTP requests as string key-value pairs.
TYPE: Dict[str, str]
"},{"location":"reference/client/client/#streampipes.client.client.StreamPipesClient.create","title":"create(client_config, logging_level=logging.INFO)
classmethod
","text":"Returns an instance of the StreamPipesPythonClient
.
Provides consistency to the StreamPipes Java client.
PARAMETER DESCRIPTION client_config
Configures the client to connect properly to the StreamPipes instance.
TYPE: StreamPipesClientConfig
logging_level
Influences the log messages emitted by the StreamPipesClient
.
TYPE: int
DEFAULT: logging.INFO
RETURNS DESCRIPTION StreamPipesClient
"},{"location":"reference/client/client/#streampipes.client.client.StreamPipesClient.describe","title":"describe()
","text":"Prints a short description of the connected StreamPipes instance and the available resources to the console.
RETURNS DESCRIPTION None
Examples:
client.describe()\n
Output: Hi there!\nYou are connected to a StreamPipes instance running at http://localhost:80.\nThe following StreamPipes resources are available with this client:\n6x DataStreams\n1x DataLakeMeasures\n
"},{"location":"reference/client/config/","title":"Config","text":"Configuration class for the StreamPipes client.
"},{"location":"reference/client/config/#streampipes.client.config.StreamPipesClientConfig","title":"StreamPipesClientConfig
dataclass
","text":"Configure the StreamPipes client in accordance to the actual StreamPipes instance to connect to.
An instance is provided to the StreamPipesClient
to configure it properly.
PARAMETER DESCRIPTION credential_provider
Provides the credentials to authenticate with the StreamPipes API.
TYPE: CredentialProvider
host_address
Host address of the StreamPipes instance to connect to. Should be provided without the protocol/scheme, e.g. as localhost
or streampipes.xyz
.
TYPE: str
https_disabled
Determines whether https is used to connect to StreamPipes.
TYPE: Optional[bool]
DEFAULT: False
port
Specifies the port under which the StreamPipes API is available, e.g., 80
(with http) or 443
(with https)
TYPE: Optional[int]
DEFAULT: 80
Examples:
see StreamPipesClient
"},{"location":"reference/client/credential_provider/","title":"Credential provider","text":"Implementation of credential providers. A credential provider supplies the specified sort of credentials in the appropriate HTTP header format. The headers are then used by the client to connect to StreamPipes.
"},{"location":"reference/client/credential_provider/#streampipes.client.credential_provider.CredentialProvider","title":"CredentialProvider
","text":" Bases: ABC
Abstract implementation of a credential provider. Must be inherited by all credential providers.
"},{"location":"reference/client/credential_provider/#streampipes.client.credential_provider.CredentialProvider.make_headers","title":"make_headers(http_headers=None)
","text":"Creates the HTTP headers for the specific credential provider.
Concrete authentication headers must be defined in the implementation of a credential provider.
PARAMETER DESCRIPTION http_headers
Additional HTTP headers the generated headers are extended by.
TYPE: Optional[Dict[str, str]]
DEFAULT: None
RETURNS DESCRIPTION https_headers
Dictionary with header information as string key-value pairs. Contains all pairs given as parameter plus the header pairs for authentication determined by the credential provider.
TYPE: Dict[str, str]
"},{"location":"reference/client/credential_provider/#streampipes.client.credential_provider.StreamPipesApiKeyCredentials","title":"StreamPipesApiKeyCredentials(username=None, api_key=None)
","text":" Bases: CredentialProvider
A credential provider that allows authentication via a StreamPipes API Token.
The required token can be generated via the StreamPipes UI (see the description on our start-page.
Both parameters can either be passed as arguments or remain unset. If they are not passed, they are retrieved from environment variables:
SP_USERNAME
is expected to contain the username SP_API_KEY
is expected to contain the API key
PARAMETER DESCRIPTION username
The username to which the API token is granted, e.g., demo-user@streampipes.apche.org
. If not passed, the username is retrieved from environment variable SP_USERNAME
.
TYPE: Optional[str]
DEFAULT: None
api_key
The StreamPipes API key as it is displayed in the UI. If not passed, the api key is retrieved from environment variable SP_API_KEY
TYPE: Optional[str]
DEFAULT: None
Examples:
see StreamPipesClient
"},{"location":"reference/client/credential_provider/#streampipes.client.credential_provider.StreamPipesApiKeyCredentials.from_env","title":"from_env(username_env, api_key_env)
classmethod
","text":"DEPRECATED - use the class constructor instead
Returns an api key provider parameterized via environment variables.
PARAMETER DESCRIPTION username_env
Name of the environment variable that contains the username
TYPE: str
api_key_env
Name of the environment variable that contains the API key
TYPE: str
RETURNS DESCRIPTION StreamPipesApiKeyCredentials
RAISES DESCRIPTION KeyError
If one of the environment variables is not defined
"},{"location":"reference/endpoint/endpoint/","title":"Endpoint","text":"General implementation for an endpoint. Provided classes and assets are aimed to be used for developing endpoints. An endpoint provides all options to communicate with ad dedicated part of StreamPipes in a handy way.
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.APIEndpoint","title":"APIEndpoint
","text":" Bases: Endpoint
Abstract implementation of an API endpoint.
Serves as template for all endpoints of the StreamPipes API. By design, endpoints are only instantiated within the __init__
method of the StreamPipesClient.
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.APIEndpoint.all","title":"all()
","text":"Get all resources of this endpoint provided by the StreamPipes API.
Results are provided as an instance of a ResourceContainer
that allows to handle the returned resources in a comfortable and pythonic way.
RETURNS DESCRIPTION container
container element that bundles the returned resources
TYPE: ResourceContainer
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.APIEndpoint.build_url","title":"build_url()
","text":"Builds the endpoint's URL of the API path.
RETURNS DESCRIPTION url
The URL of the endpoint
TYPE: str
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.APIEndpoint.get","title":"get(identifier, **kwargs)
","text":"Queries the specified resource from the API endpoint.
PARAMETER DESCRIPTION identifier
The identifier of the resource to be queried.
TYPE: str
RETURNS DESCRIPTION resource
The specified resource as an instance of the corresponding model class.
TYPE: Resource
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.APIEndpoint.post","title":"post(resource)
","text":"Allows to post a resource to the StreamPipes API.
PARAMETER DESCRIPTION resource
The resource to be posted.
TYPE: Resource
RETURNS DESCRIPTION None
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.Endpoint","title":"Endpoint(parent_client)
","text":" Bases: ABC
Abstract implementation of a StreamPipes endpoint.
Serves as template for all endpoints used for interaction with a StreamPipes instance. By design, endpoints are only instantiated within the __init__
method of the StreamPipesClient.
PARAMETER DESCRIPTION parent_client
This parameter expects the instance of StreamPipesClient
the endpoint is attached to.
TYPE: StreamPipesClient
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.MessagingEndpoint","title":"MessagingEndpoint(parent_client)
","text":" Bases: Endpoint
Abstract implementation of a StreamPipes messaging endpoint.
Serves as template for all endpoints used for interacting with the StreamPipes messaging layer directly. Therefore, they need to provide the functionality to talk with the broker system running in StreamPipes. By design, endpoints are only instantiated within the __init__
method of the StreamPipesClient.
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.MessagingEndpoint.broker","title":"broker: Broker
property
writable
","text":"Defines the broker instance that is used to connect to StreamPipes' messaging layer.
This instance enables the client to authenticate to the broker used in the target StreamPipes instance, to consume messages from and to write messages to the broker.
RAISES DESCRIPTION MessagingEndpointNotConfiguredError
If the endpoint is used before the broker instance is set via configure()
RETURNS DESCRIPTION broker
The broker instance to be used to communicate with StreamPipes' messaging layer.
TYPE: Broker
"},{"location":"reference/endpoint/endpoint/#streampipes.endpoint.endpoint.MessagingEndpoint.configure","title":"configure(broker)
","text":"Configures the message endpoint by setting the broker instance to be used.
This configuration step is required before the endpoint can be actually used. The based broker
instance is passed to an internal property
PARAMETER DESCRIPTION broker
Broker instance that should be used for this endpoint
TYPE: Broker
RETURNS DESCRIPTION None
"},{"location":"reference/endpoint/exceptions/","title":"Exceptions","text":"Custom exceptions dedicated for the endpoints module
"},{"location":"reference/endpoint/exceptions/#streampipes.endpoint.exceptions.MessagingEndpointNotConfiguredError","title":"MessagingEndpointNotConfiguredError(endpoint_name)
","text":" Bases: Exception
Exception that indicates that an instance of a messaging endpoint has not been configured.
This error occurs when an instance of a messaging endpoint is used before the broker instance to be used is configured by passing it to the configure()
method.
PARAMETER DESCRIPTION endpoint_name
The name of the endpoint that caused the error
TYPE: str
"},{"location":"reference/endpoint/api/data_lake_measure/","title":"Data lake measure","text":"Specific implementation of the StreamPipes API's data lake measure endpoints. This endpoint allows to consume data stored in StreamPipes' data lake.
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.DataLakeMeasureEndpoint","title":"DataLakeMeasureEndpoint
","text":" Bases: APIEndpoint
Implementation of the DataLakeMeasure endpoint.
This endpoint provides an interface to all data stored in the StreamPipes data lake.
Consequently, it allows querying metadata about available data sets (see all()
method). The metadata is returned as an instance of DataLakeMeasures
.
In addition, the endpoint provides direct access to the data stored in the data laka by querying a specific data lake measure using the get()
method.
Examples:
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
client_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(username=\"test-user\", api_key=\"api-key\"),\n host_address=\"localhost\",\n port=8082,\n https_disabled=True\n)\nclient = StreamPipesClient.create(client_config=client_config)\n
# get all existing data lake measures from StreamPipes\ndata_lake_measures = client.dataLakeMeasureApi.all()\n\n# let's take a look how many we got\nlen(data_lake_measures)\n
5\n
# Retrieve a specific data lake measure as a pandas DataFrame\nflow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\").to_pandas()\nflow_rate_pd\n
time density mass_flow sensorId sensor_fault_flags temperature volume_flow\n0 2023-02-24T16:19:41.472Z 50.872730 3.309556 flowrate02 False 44.448483 5.793138\n1 2023-02-24T16:19:41.482Z 47.186588 5.608580 flowrate02 False 40.322033 0.058015\n2 2023-02-24T16:19:41.493Z 46.735321 7.692881 flowrate02 False 49.239639 10.283526\n3 2023-02-24T16:19:41.503Z 40.169796 3.632898 flowrate02 False 49.933754 6.893441\n4 2023-02-24T16:19:41.513Z 49.635124 0.711260 flowrate02 False 50.106617 2.999871\n.. ... ... ... ... ... ... ...\n995 2023-02-24T16:19:52.927Z 50.057495 1.740114 flowrate02 False 46.558231 1.818237\n996 2023-02-24T16:19:52.94Z 41.038895 7.211723 flowrate02 False 48.048622 2.127493\n997 2023-02-24T16:19:52.952Z 45.837013 7.770180 flowrate02 False 48.188026 7.892062\n998 2023-02-24T16:19:52.965Z 43.389065 4.458602 flowrate02 False 48.280899 5.733892\n999 2023-02-24T16:19:52.977Z 44.056030 2.592060 flowrate02 False 47.505951 4.260697\n
As you can see, the returned amount of rows per default is 1000
. We can modify this behavior by passing the limit
paramter.
flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", limit=10).to_pandas()\nlen(flow_rate_pd)\n
10\n
If we are only interested in the values for density
, columns
allows us to select the columns to be returned:
flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", columns='density', limit=3).to_pandas()\nflow_rate_pd\n
time density\n0 2023-02-24T16:19:41.472Z 50.872730\n1 2023-02-24T16:19:41.482Z 47.186588\n2 2023-02-24T16:19:41.493Z 46.735321\n
This is only a subset of the available query parameters, find them at MeasurementGetQueryConfig.
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.DataLakeMeasureEndpoint.get","title":"get(identifier, **kwargs)
","text":"Queries the specified data lake measure from the API.
By default, the maximum number of returned records is 1000. This behaviour can be influenced by passing the parameter limit
with a different value (see MeasurementGetQueryConfig).
PARAMETER DESCRIPTION identifier
The identifier of the data lake measure to be queried.
TYPE: str
**kwargs
keyword arguments can be used to provide additional query parameters. The available query parameters are defined by the MeasurementGetQueryConfig.
TYPE: Optional[Dict[str, Any]]
DEFAULT: {}
RETURNS DESCRIPTION measurement
the specified data lake measure
TYPE: DataLakeMeasures
Examples:
see directly at DataLakeMeasureEndpoint.
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.MeasurementGetQueryConfig","title":"MeasurementGetQueryConfig
","text":" Bases: BaseModel
Config class describing the parameters of the get()
method for measurements.
This config class is used to validate the provided query parameters for the GET endpoint of measurements. Additionally, it takes care of the conversion to a proper HTTP query string. Thereby, parameter names are adapted to the naming of the StreamPipes API, for which Pydantic aliases are used.
ATTRIBUTE DESCRIPTION columns
A comma separated list of column names (e.g., time,value
) If provided, the returned data only consists of the given columns. Please be aware that the column time
as an index is always included.
TYPE: Optional[List[str]]
end_date
Restricts queried data to be younger than the specified time.
TYPE: Optional[datetime]
limit
Amount of records returned at maximum (default: 1000
) This needs to be at least 1
TYPE: Optional[int]
offset
Offset to be applied to returned data This needs to be at least 0
TYPE: Optional[int]
order
Ordering of query results Allowed values: ASC
and DESC
(default: ASC
)
TYPE: Optional[str]
page_no
Page number used for paging operation This needs to be at least 1
TYPE: Optional[int]
start_date
Restricts queried data to be older than the specified time
TYPE: Optional[datetime]
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.MeasurementGetQueryConfig.Config","title":"Config
","text":"Pydantic Config class
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.MeasurementGetQueryConfig.build_query_string","title":"build_query_string()
","text":"Builds a HTTP query string for the config.
This method returns an HTTP query string for the invoking config. It follows the following structure ?param1=value1¶m2=value2...
. This query string is not an entire URL, instead it needs to appended to an API path.
RETURNS DESCRIPTION query_param_string
HTTP query params string (?param1=value1¶m2=value2...
)
TYPE: str
"},{"location":"reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.StreamPipesQueryValidationError","title":"StreamPipesQueryValidationError
","text":" Bases: Exception
A custom exception to be raised when the validation of query parameter causes an error.
"},{"location":"reference/endpoint/api/data_stream/","title":"Data stream","text":"Specific implementation of the StreamPipes API's data stream endpoints.
"},{"location":"reference/endpoint/api/data_stream/#streampipes.endpoint.api.data_stream.DataStreamEndpoint","title":"DataStreamEndpoint
","text":" Bases: APIEndpoint
Implementation of the DataStream endpoint.
Consequently, it allows querying metadata about available data streams (see all()
method). The metadata is returned as an instance of DataStreams
.
Examples:
from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n\nclient_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(username=\"test-user\", api_key=\"api-key\"),\n host_address=\"localhost\",\n port=8082,\n https_disabled=True\n)\nclient = StreamPipesClient.create(client_config=client_config)\n
# let's get all existing data streams in StreamPipes\ndata_streams = client.dataStreamApi.all()\nlen(data_streams)\n
2\n
"},{"location":"reference/endpoint/api/version/","title":"Version","text":"Specific implementation of the StreamPipes API's version endpoint.
"},{"location":"reference/endpoint/api/version/#streampipes.endpoint.api.version.VersionEndpoint","title":"VersionEndpoint
","text":" Bases: APIEndpoint
Implementation of the Versions endpoint.
This endpoint provides metadata about the StreamPipes version of the connected instance. It only allows to apply the get()
method with an empty string as identifier.
PARAMETER DESCRIPTION parent_client
The instance of StreamPipesClient the endpoint is attached to.
Examples:
>>> from streampipes.client import StreamPipesClient\n>>> from streampipes.client.config import StreamPipesClientConfig\n>>> from streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
>>> client_config = StreamPipesClientConfig(\n... credential_provider=StreamPipesApiKeyCredentials(username=\"test-user\", api_key=\"api-key\"),\n... host_address=\"localhost\",\n... port=8082,\n... https_disabled=True\n... )\n
>>> client = StreamPipesClient.create(client_config=client_config)\n
>>> client.versionApi.get(identifier=\"\").to_dict(use_source_names=False)\n{'backend_version': '0.92.0-SNAPSHOT'}\n
"},{"location":"reference/endpoint/api/version/#streampipes.endpoint.api.version.VersionEndpoint.all","title":"all()
","text":"Usually, this method returns information about all resources provided by this endpoint. However, this endpoint does not support this kind of operation.
RAISES DESCRIPTION NotImplementedError
this endpoint does not return multiple entries, therefore this method is not available
"},{"location":"reference/endpoint/api/version/#streampipes.endpoint.api.version.VersionEndpoint.get","title":"get(identifier, **kwargs)
","text":"Queries the resource from the API endpoint.
For this endpoint only one resource is available.
PARAMETER DESCRIPTION identifier
Not supported by this endpoint, is set to an empty string.
TYPE: str
RETURNS DESCRIPTION versions
The specified resource as an instance of the corresponding model class(Version). # noqa: 501
TYPE: Version
"},{"location":"reference/endpoint/api/version/#streampipes.endpoint.api.version.VersionEndpoint.post","title":"post(resource)
","text":"Usually, this method allows to create via this endpoint. Since the data represented by this endpoint is immutable, it does not support this kind of operation.
RAISES DESCRIPTION NotImplementedError
this endpoint does not allow for POST requests, therefore this method is not available
"},{"location":"reference/function_zoo/river_function/","title":"River function","text":""},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.OnlineML","title":"OnlineML(client, stream_ids, model, prediction_type=RuntimeType.STRING.value, supervised=False, target_label=None, on_start=lambda self, context: None, on_event=lambda self, event, streamId: None, on_stop=lambda self: None)
","text":"Wrapper class to enable an easy usage for Online Machine Learning models of the River library.
It creates a StreamPipesFunction to train a model with the incoming events of a data stream and creates an output data stream that publishes the prediction to StreamPipes.
PARAMETER DESCRIPTION client
The client for the StreamPipes API.
TYPE: StreamPipesClient
stream_ids
The ids of the data stream to train the model.
TYPE: List[str]
model
The model to train. It meant to be a River model/pipeline, but can be every model with a 'learn_one' and 'predict_one' methode.
TYPE: Any
prediction_type
The data type of the prediction. Is only needed when you continue to work with the prediction in StreamPipes.
TYPE: str
DEFAULT: RuntimeType.STRING.value
supervised
Define if the model is supervised or unsupervised.
TYPE: bool
DEFAULT: False
target_label
Define the name of the target attribute if the model is supervised.
TYPE: Optional[str]
DEFAULT: None
on_start
A function to be called when this StreamPipesFunction gets started.
TYPE: Callable[[Any, FunctionContext], None]
DEFAULT: lambda self, context: None
on_event
A function to be called when this StreamPipesFunction receives an event.
TYPE: Callable[[Any, Dict[str, Any], str], None]
DEFAULT: lambda self, event, streamId: None
on_stop
A function to be called when this StreamPipesFunction gets stopped.
TYPE: Callable[[Any], None]
DEFAULT: lambda self: None
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.OnlineML.set_learning","title":"set_learning(learning)
","text":"Start or stop the training of the model.
PARAMETER DESCRIPTION learning
Defines if the training should be continued
TYPE: bool
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.OnlineML.start","title":"start()
","text":"Registers the function and starts the training.
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.OnlineML.stop","title":"stop()
","text":"Stops the function and ends the training forever.
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.RiverFunction","title":"RiverFunction(function_definition, model, supervised, target_label, on_start, on_event, on_stop)
","text":" Bases: StreamPipesFunction
Implementation of a StreamPipesFunction to enable an easy usage for Online Machine Learning models of the River library.
The function trains the model with the incoming events and publishes the prediction to an output data stream.
PARAMETER DESCRIPTION function_definition
The function definition which contains the output stream.
TYPE: FunctionDefinition
model
The model to train. It meant to be a River model/pipeline, but can be every model with a 'learn_one' and 'predict_one' method.
TYPE: Any
supervised
Define if the model is supervised or unsupervised.
TYPE: bool
target_label
Define the name of the target attribute if the model is supervised.
TYPE: Optional[str]
on_start
A function to be called when this StreamPipesFunction gets started.
TYPE: Callable[[Any, FunctionContext], None]
on_event
A function to be called when this StreamPipesFunction receives an event.
TYPE: Callable[[Any, Dict[str, Any], str], None]
on_stop
A function to be called when this StreamPipesFunction gets stopped.
TYPE: Callable[[Any], None]
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.RiverFunction.onEvent","title":"onEvent(event, streamId)
","text":"Trains the model with the incoming events and sends the prediction back to StreamPipes.
PARAMETER DESCRIPTION event
The incoming event that serves as input for the function
TYPE: Dict[str, Any]
streamId
Identifier of the corresponding data stream
TYPE: str
RETURNS DESCRIPTION None
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.RiverFunction.onServiceStarted","title":"onServiceStarted(context)
","text":"Executes the on_start
method of the function.
PARAMETER DESCRIPTION context
The functions' context
TYPE: FunctionContext
RETURNS DESCRIPTION None
"},{"location":"reference/function_zoo/river_function/#streampipes.function_zoo.river_function.RiverFunction.onServiceStopped","title":"onServiceStopped()
","text":"Executes the on_stop
function.
"},{"location":"reference/functions/function_handler/","title":"Function handler","text":""},{"location":"reference/functions/function_handler/#streampipes.functions.function_handler.FunctionHandler","title":"FunctionHandler(registration, client)
","text":"The function handler manages the StreamPipes Functions.
It controls the connection to the brokers, starts the functions, manages the broadcast of the live data and is able to stop the connection to the brokers and functions.
PARAMETER DESCRIPTION registration
The registration, that contains the StreamPipesFunctions.
TYPE: Registration
client
The client to interact with the API.
TYPE: StreamPipesClient
ATTRIBUTE DESCRIPTION stream_contexts
Map of all data stream contexts
TYPE: Dict[str, DataStreamContext]
brokers
List of all registered brokers
TYPE: List[Broker]
"},{"location":"reference/functions/function_handler/#streampipes.functions.function_handler.FunctionHandler.disconnect","title":"disconnect()
","text":"Disconnects from the brokers and stops all functions.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/function_handler/#streampipes.functions.function_handler.FunctionHandler.force_stop_functions","title":"force_stop_functions()
","text":"Stops the StreamPipesFunctions when the event loop was stopped without stopping the functions.
RETURNS DESCRIPTION None
WARNS DESCRIPTION UserWarning
If there is a running event loop and the functions should be stopped by disconnecting from the broker.
"},{"location":"reference/functions/function_handler/#streampipes.functions.function_handler.FunctionHandler.initializeFunctions","title":"initializeFunctions()
","text":"Creates the context for every data stream and starts the event loop to manage the StreamPipes Functions.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/registration/","title":"Registration","text":""},{"location":"reference/functions/registration/#streampipes.functions.registration.Registration","title":"Registration()
","text":"Manages the existing StreamPipesFunctions and registers them.
ATTRIBUTE DESCRIPTION functions
List of all registered StreamPipesFunction
TYPE: List[StreamPipesFunction]
"},{"location":"reference/functions/registration/#streampipes.functions.registration.Registration.getFunctions","title":"getFunctions()
","text":"Get all registered functions.
This method exists to be consistent with the Java client.
RETURNS DESCRIPTION functions
List of all registered functions.
TYPE: List[StreamPipesFunction]
"},{"location":"reference/functions/registration/#streampipes.functions.registration.Registration.register","title":"register(streampipes_function)
","text":"Registers a new function.
PARAMETER DESCRIPTION streampipes_function
The function to register.
TYPE: StreamPipesFunction
RETURNS DESCRIPTION self
The updated Registration instance
TYPE: Registration
"},{"location":"reference/functions/streampipes_function/","title":"Streampipes function","text":""},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction","title":"StreamPipesFunction(function_definition=None)
","text":" Bases: ABC
Abstract implementation of a StreamPipesFunction.
A StreamPipesFunction allows users to get the data of a StreamPipes data streams easily. It makes it possible to work with the live data in python and enables to use the powerful data analytics libraries there.
PARAMETER DESCRIPTION function_definition
the definition of the function that contains metadata about the connected function
TYPE: Optional[FunctionDefinition]
DEFAULT: None
ATTRIBUTE DESCRIPTION output_collectors
List of all output collectors which are created based on the provided function definitions.
TYPE: Dict[str, OutputCollector]
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.add_output","title":"add_output(stream_id, event)
","text":"Send an event via an output data stream to StreamPipes
PARAMETER DESCRIPTION stream_id
The id of the output data stream
TYPE: str
event
The event which should be sent
TYPE: Dict[str, Any]
RETURNS DESCRIPTION None
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.getFunctionId","title":"getFunctionId()
","text":"Returns the id of the function.
RETURNS DESCRIPTION function_id
Identification object of the StreamPipes function
TYPE: FunctionId
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.onEvent","title":"onEvent(event, streamId)
abstractmethod
","text":"Is called for every event of a data stream.
PARAMETER DESCRIPTION event
The received event from the data stream.
TYPE: Dict[str, Any]
streamId
The id of the data stream which the event belongs to.
TYPE: str
RETURNS DESCRIPTION None
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.onServiceStarted","title":"onServiceStarted(context)
abstractmethod
","text":"Is called when the function gets started.
PARAMETER DESCRIPTION context
The context in which the function gets started.
TYPE: FunctionContext
RETURNS DESCRIPTION None
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.onServiceStopped","title":"onServiceStopped()
abstractmethod
","text":"Is called when the function gets stopped.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.requiredStreamIds","title":"requiredStreamIds()
","text":"Get the ids of the streams needed by the function.
RETURNS DESCRIPTION stream_ids
List of the stream ids
TYPE: List[str]
"},{"location":"reference/functions/streampipes_function/#streampipes.functions.streampipes_function.StreamPipesFunction.stop","title":"stop()
","text":"Stops the function and disconnects from the output streams
"},{"location":"reference/functions/broker/broker/","title":"Broker","text":""},{"location":"reference/functions/broker/broker/#streampipes.functions.broker.broker.Broker","title":"Broker
","text":" Bases: ABC
Abstract implementation of a broker for consumer and publisher.
It contains the basic logic to connect to a data stream.
"},{"location":"reference/functions/broker/broker/#streampipes.functions.broker.broker.Broker.connect","title":"connect(data_stream)
async
","text":"Connects to the broker running in StreamPipes.
PARAMETER DESCRIPTION data_stream
Contains the meta information (resources) for a data stream.
TYPE: DataStream
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/broker/#streampipes.functions.broker.broker.Broker.disconnect","title":"disconnect()
abstractmethod
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/broker_handler/","title":"Broker handler","text":""},{"location":"reference/functions/broker/broker_handler/#streampipes.functions.broker.broker_handler.SupportedBroker","title":"SupportedBroker
","text":" Bases: Enum
Enum for the supported brokers.
"},{"location":"reference/functions/broker/broker_handler/#streampipes.functions.broker.broker_handler.UnsupportedBrokerError","title":"UnsupportedBrokerError(broker_name)
","text":" Bases: Exception
Exception if a broker isn't implemented yet.
"},{"location":"reference/functions/broker/broker_handler/#streampipes.functions.broker.broker_handler.get_broker","title":"get_broker(data_stream, is_publisher=False)
","text":"Derive the broker for the given data stream.
PARAMETER DESCRIPTION data_stream
Data stream instance from which the broker is inferred
TYPE: DataStream
RETURNS DESCRIPTION broker
The corresponding broker instance derived from data stream.
TYPE: Broker
RAISES DESCRIPTION UnsupportedBrokerError
Is raised when the given data stream belongs to a broker that is currently not supported by StreamPipes Python.
"},{"location":"reference/functions/broker/broker_handler/#streampipes.functions.broker.broker_handler.get_broker_description","title":"get_broker_description(data_stream)
","text":"Derive the decription of the broker for the given data stream.
PARAMETER DESCRIPTION data_stream
Data stream instance from which the broker is inferred
TYPE: DataStream
RETURNS DESCRIPTION broker
The corresponding broker description derived from data stream.
TYPE: SupportedBroker
RAISES DESCRIPTION UnsupportedBrokerError
Is raised when the given data stream belongs to a broker that is currently not supported by StreamPipes Python.
"},{"location":"reference/functions/broker/consumer/","title":"Consumer","text":""},{"location":"reference/functions/broker/consumer/#streampipes.functions.broker.consumer.Consumer","title":"Consumer
","text":" Bases: Broker
Abstract implementation a consumer for a broker.
A consumer allows to subscribe to a data stream.
"},{"location":"reference/functions/broker/consumer/#streampipes.functions.broker.consumer.Consumer.connect","title":"connect(data_stream)
async
","text":"Connects to the broker running in StreamPipes and creates a subscription.
PARAMETER DESCRIPTION data_stream
Contains the meta information (resources) for a data stream.
TYPE: DataStream
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/consumer/#streampipes.functions.broker.consumer.Consumer.get_message","title":"get_message()
abstractmethod
","text":"Get the published messages of the subscription.
RETURNS DESCRIPTION iterator
An async iterator for the messages.
TYPE: AsyncIterator
"},{"location":"reference/functions/broker/output_collector/","title":"Output collector","text":""},{"location":"reference/functions/broker/output_collector/#streampipes.functions.broker.output_collector.OutputCollector","title":"OutputCollector(data_stream)
","text":"Collector for output events. The events are published to an output data stream. Therefore, the output collector establishes a connection to the broker.
PARAMETER DESCRIPTION data_stream
The output data stream that will receive the events.
TYPE: DataStream
ATTRIBUTE DESCRIPTION publisher
The publisher instance that sends the data to StreamPipes
TYPE: Publisher
"},{"location":"reference/functions/broker/output_collector/#streampipes.functions.broker.output_collector.OutputCollector.collect","title":"collect(event)
","text":"Publishes an event to the output stream.
PARAMETER DESCRIPTION event
The event to be published.
TYPE: Dict[str, Any]
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/output_collector/#streampipes.functions.broker.output_collector.OutputCollector.disconnect","title":"disconnect()
","text":"Disconnects the broker of the output collector.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/publisher/","title":"Publisher","text":""},{"location":"reference/functions/broker/publisher/#streampipes.functions.broker.publisher.Publisher","title":"Publisher
","text":" Bases: Broker
Abstract implementation of a publisher for a broker.
A publisher allows to publish events to a data stream.
"},{"location":"reference/functions/broker/publisher/#streampipes.functions.broker.publisher.Publisher.publish_event","title":"publish_event(event)
abstractmethod
async
","text":"Publish an event to a connected data stream.
PARAMETER DESCRIPTION event
The event to be published.
TYPE: Dict[str, Any]
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/kafka/kafka_consumer/","title":"Kafka consumer","text":""},{"location":"reference/functions/broker/kafka/kafka_consumer/#streampipes.functions.broker.kafka.kafka_consumer.KafkaConsumer","title":"KafkaConsumer
","text":" Bases: Consumer
Implementation of a consumer for Kafka
"},{"location":"reference/functions/broker/kafka/kafka_consumer/#streampipes.functions.broker.kafka.kafka_consumer.KafkaConsumer.disconnect","title":"disconnect()
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/kafka/kafka_consumer/#streampipes.functions.broker.kafka.kafka_consumer.KafkaConsumer.get_message","title":"get_message()
","text":"Get the published messages of the subscription.
RETURNS DESCRIPTION iterator
An async iterator for the messages.
TYPE: AsyncIterator
"},{"location":"reference/functions/broker/kafka/kafka_message_fetcher/","title":"Kafka message fetcher","text":""},{"location":"reference/functions/broker/kafka/kafka_message_fetcher/#streampipes.functions.broker.kafka.kafka_message_fetcher.KafkaMessage","title":"KafkaMessage(data)
","text":"An internal representation of a Kafka message
PARAMETER DESCRIPTION data
The received Kafka message as byte array
"},{"location":"reference/functions/broker/kafka/kafka_message_fetcher/#streampipes.functions.broker.kafka.kafka_message_fetcher.KafkaMessageFetcher","title":"KafkaMessageFetcher(consumer)
","text":"Fetches the next message from Kafka
PARAMETER DESCRIPTION consumer
The Kafka consumer
TYPE: Consumer
"},{"location":"reference/functions/broker/kafka/kafka_publisher/","title":"Kafka publisher","text":""},{"location":"reference/functions/broker/kafka/kafka_publisher/#streampipes.functions.broker.kafka.kafka_publisher.KafkaPublisher","title":"KafkaPublisher
","text":" Bases: Publisher
Implementation of a publisher for Kafka
"},{"location":"reference/functions/broker/kafka/kafka_publisher/#streampipes.functions.broker.kafka.kafka_publisher.KafkaPublisher.disconnect","title":"disconnect()
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/kafka/kafka_publisher/#streampipes.functions.broker.kafka.kafka_publisher.KafkaPublisher.publish_event","title":"publish_event(event)
async
","text":"Publish an event to a connected data stream.
PARAMETER DESCRIPTION event
The event to be published.
TYPE: Dict[str, Any]
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/nats/nats_consumer/","title":"Nats consumer","text":""},{"location":"reference/functions/broker/nats/nats_consumer/#streampipes.functions.broker.nats.nats_consumer.NatsConsumer","title":"NatsConsumer
","text":" Bases: Consumer
Implementation of a consumer for NATS
"},{"location":"reference/functions/broker/nats/nats_consumer/#streampipes.functions.broker.nats.nats_consumer.NatsConsumer.disconnect","title":"disconnect()
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/nats/nats_consumer/#streampipes.functions.broker.nats.nats_consumer.NatsConsumer.get_message","title":"get_message()
","text":"Get the published messages of the subscription.
RETURNS DESCRIPTION message_iterator
An async iterator for the messages.
TYPE: AsyncIterator
"},{"location":"reference/functions/broker/nats/nats_publisher/","title":"Nats publisher","text":""},{"location":"reference/functions/broker/nats/nats_publisher/#streampipes.functions.broker.nats.nats_publisher.NatsPublisher","title":"NatsPublisher
","text":" Bases: Publisher
Implementation of a publisher for NATS
"},{"location":"reference/functions/broker/nats/nats_publisher/#streampipes.functions.broker.nats.nats_publisher.NatsPublisher.disconnect","title":"disconnect()
async
","text":"Closes the connection to the server.
RETURNS DESCRIPTION None
"},{"location":"reference/functions/broker/nats/nats_publisher/#streampipes.functions.broker.nats.nats_publisher.NatsPublisher.publish_event","title":"publish_event(event)
async
","text":"Publish an event to a connected data stream.
PARAMETER DESCRIPTION event
The event to be published.
TYPE: Dict[str, Any]
RETURNS DESCRIPTION None
"},{"location":"reference/functions/utils/async_iter_handler/","title":"Async iter handler","text":""},{"location":"reference/functions/utils/async_iter_handler/#streampipes.functions.utils.async_iter_handler.AsyncIterHandler","title":"AsyncIterHandler
","text":"Handles asynchronous iterators to get every message after another in parallel.
"},{"location":"reference/functions/utils/async_iter_handler/#streampipes.functions.utils.async_iter_handler.AsyncIterHandler.anext","title":"anext(stream_id, message)
async
staticmethod
","text":"Gets the next message from an AsyncIterator.
PARAMETER DESCRIPTION stream_id
The id of the data stream which the message belongs to.
TYPE: str
message
An asynchronous iterator that contains the messages.
TYPE: AsyncIterator
RETURNS DESCRIPTION result
Tuple of the stream id und next message or (\"stop\", None)
if no message is left.
TYPE: Tuple[str, Optional[Any]]
"},{"location":"reference/functions/utils/async_iter_handler/#streampipes.functions.utils.async_iter_handler.AsyncIterHandler.combine_async_messages","title":"combine_async_messages(messages)
async
staticmethod
","text":"Continuously gets the next published message from multiple AsyncIterators in parallel.
PARAMETER DESCRIPTION messages
A dictionary with an asynchronous iterator for every stream id.
TYPE: Dict[str, AsyncIterator]
YIELDS DESCRIPTION message
Description of the anonymous integer return value.
TYPE:: Tuple[str, Any]
"},{"location":"reference/functions/utils/data_stream_context/","title":"Data stream context","text":""},{"location":"reference/functions/utils/data_stream_context/#streampipes.functions.utils.data_stream_context.DataStreamContext","title":"DataStreamContext(functions, schema, broker)
","text":"Container for the context of a data stream.
PARAMETER DESCRIPTION functions
StreamPipes Functions which require the data of this data stream.
TYPE: List[StreamPipesFunction]
schema
The schema of this data stream.
TYPE: DataStream
broker
The consumer to connect to this data stream.
TYPE: Consumer
"},{"location":"reference/functions/utils/data_stream_context/#streampipes.functions.utils.data_stream_context.DataStreamContext.add_function","title":"add_function(function)
","text":"Adds a new StreamPipes Function.
PARAMETER DESCRIPTION function
StreamPipesFunction which requires this data stream.
TYPE: StreamPipesFunction
RETURNS DESCRIPTION None
"},{"location":"reference/functions/utils/data_stream_generator/","title":"Data stream generator","text":""},{"location":"reference/functions/utils/data_stream_generator/#streampipes.functions.utils.data_stream_generator.RuntimeType","title":"RuntimeType
","text":" Bases: Enum
Runtime type names for the attributes of a data stream.
ATTRIBUTE DESCRIPTION STRING
BOOLEAN
DOUBLE
FLOAT
INTEGER
LONG
"},{"location":"reference/functions/utils/data_stream_generator/#streampipes.functions.utils.data_stream_generator.create_data_stream","title":"create_data_stream(name, attributes, stream_id=None, broker=SupportedBroker.NATS)
","text":"Creates a data stream
PARAMETER DESCRIPTION name
Name of the data stream to be shown at the UI.
TYPE: str
attributes
Name and types of the attributes.
TYPE: Dict[str, str]
stream_id
The id of this data stream.
TYPE: Optional[str]
DEFAULT: None
RETURNS DESCRIPTION data_stream
The created data stream
TYPE: DataStream
"},{"location":"reference/functions/utils/function_context/","title":"Function context","text":""},{"location":"reference/functions/utils/function_context/#streampipes.functions.utils.function_context.FunctionContext","title":"FunctionContext(function_id, schema, client, streams)
","text":"Container for the context of a StreamPipesFunction.
PARAMETER DESCRIPTION function_id
The id of this function.
TYPE: str
schema
A dictionary which contains the schema of a data stream for each stream id.
TYPE: Dict[str, DataStream]
client
The client to interact with the API.
TYPE: StreamPipesClient
streams
The ids of the streams needed by this function.
TYPE: List[str]
"},{"location":"reference/functions/utils/function_context/#streampipes.functions.utils.function_context.FunctionContext.add_data_stream_schema","title":"add_data_stream_schema(stream_id, data_stream)
","text":"Adds a new data stream for a new stream id.
PARAMETER DESCRIPTION stream_id
The id of the data stream.
TYPE: str
data_stream
The schema of the data stream.
TYPE: DataStream
RETURNS DESCRIPTION None
"},{"location":"reference/model/common/","title":"Common","text":"Classes of the StreamPipes data model that are commonly shared.
"},{"location":"reference/model/common/#streampipes.model.common.ApplicationLink","title":"ApplicationLink
","text":" Bases: BasicModel
Data model of an ApplicationLink
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.BaseElement","title":"BaseElement
","text":" Bases: BasicModel
Structure of a basic element in the StreamPipes backend
"},{"location":"reference/model/common/#streampipes.model.common.BasicModel","title":"BasicModel
","text":" Bases: BaseModel
Basic model class used for the whole Python StreamPipes data model.
"},{"location":"reference/model/common/#streampipes.model.common.BasicModel.Config","title":"Config
","text":"Configuration class for Pydantic. Defines alias generator to convert field names from camelCase (API) to snake_case (Python codebase).
"},{"location":"reference/model/common/#streampipes.model.common.EventGrounding","title":"EventGrounding
","text":" Bases: BasicModel
Data model of an EventGrounding
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.EventProperty","title":"EventProperty
","text":" Bases: BasicModel
Data model of an EventProperty
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.EventSchema","title":"EventSchema
","text":" Bases: BasicModel
Data model of an EventSchema
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.MeasurementCapability","title":"MeasurementCapability
","text":" Bases: BasicModel
Data model of a MeasurementCapability
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.MeasurementObject","title":"MeasurementObject
","text":" Bases: BasicModel
Data model of a MeasurementObject
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.TopicDefinition","title":"TopicDefinition
","text":" Bases: BasicModel
Data model of a TopicDefinition
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.TransportFormat","title":"TransportFormat
","text":" Bases: BasicModel
Data model of a TransportFormat
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.TransportProtocol","title":"TransportProtocol
","text":" Bases: BasicModel
Data model of a TransportProtocol
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.ValueSpecification","title":"ValueSpecification
","text":" Bases: BasicModel
Data model of an ValueSpecification
in compliance to the StreamPipes Backend.
"},{"location":"reference/model/common/#streampipes.model.common.random_letters","title":"random_letters(n)
","text":"Generates a string consisting of random letters.
PARAMETER DESCRIPTION n
number of letters
TYPE: int
RETURNS DESCRIPTION rand_str
String consisting of n
random letters
TYPE: str
"},{"location":"reference/model/container/data_lake_measures/","title":"Data lake measures","text":"Implementation of a resource container for the data lake measures endpoint.
"},{"location":"reference/model/container/data_lake_measures/#streampipes.model.container.data_lake_measures.DataLakeMeasures","title":"DataLakeMeasures
","text":" Bases: ResourceContainer
Implementation of the resource container for the data lake measures endpoint.
This resource container is a collection of data lake measures returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried DataLakeMeasure
. Furthermore, the resource container makes them accessible in a pythonic manner.
"},{"location":"reference/model/container/data_streams/","title":"Data streams","text":"Implementation of a resource container for the data streams endpoint.
"},{"location":"reference/model/container/data_streams/#streampipes.model.container.data_streams.DataStreams","title":"DataStreams
","text":" Bases: ResourceContainer
Implementation of the resource container for the data stream endpoint.
This resource container is a collection of data streams returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried DataStream
. Furthermore, the resource container makes them accessible in a pythonic manner.
"},{"location":"reference/model/container/resource_container/","title":"Resource container","text":"General and abstract implementation for a resource container.
A resource container is a collection of resources returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried resources. Furthermore, the resource container makes them accessible in a pythonic manner.
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.ResourceContainer","title":"ResourceContainer(resources)
","text":" Bases: ABC
General and abstract implementation for a resource container.
A resource container is a collection of resources returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried resources. Furthermore, the resource container makes them accessible in a pythonic manner.
PARAMETER DESCRIPTION resources
A list of resources to be contained in the ResourceContainer
.
TYPE: List[Resource]
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.ResourceContainer.from_json","title":"from_json(json_string)
classmethod
","text":"Creates a ResourceContainer
from the given JSON string.
PARAMETER DESCRIPTION json_string
The JSON string returned from the StreamPipes API.
TYPE: str
RETURNS DESCRIPTION container
instance of the container derived from the JSON definition
TYPE: ResourceContainer
RAISES DESCRIPTION StreamPipesDataModelError
If a resource cannot be mapped to the corresponding Python data model.
StreamPipesResourceContainerJSONError
If JSON response cannot be parsed to a ResourceContainer
.
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.ResourceContainer.to_dicts","title":"to_dicts(use_source_names=False)
","text":"Returns the contained resources as list of dictionaries.
PARAMETER DESCRIPTION use_source_names
Determines whether the field names are named in Python style (=False
) or as originally named by StreamPipes (=True
).
TYPE: bool
DEFAULT: False
RETURNS DESCRIPTION dictionary_list
List of resources in dictionary representation. If use_source_names
equals True
the keys are named as in the StreamPipes backend.
TYPE: List[Dict[str, Any]]
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.ResourceContainer.to_json","title":"to_json()
","text":"Returns the resource container in the StreamPipes JSON representation.
RETURNS DESCRIPTION json_string: str
JSON representation of the resource container where key names are equal to keys used in the StreamPipes backend
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.ResourceContainer.to_pandas","title":"to_pandas()
","text":"Returns the resource container in representation of a Pandas Dataframe.
RETURNS DESCRIPTION resource_container_df
Representation of the resource container as pandas DataFrame
TYPE: pd.DataFrame
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.StreamPipesDataModelError","title":"StreamPipesDataModelError(validation_error)
","text":" Bases: Exception
A custom exception to be raised when a validation error occurs during the parsing of StreamPipes API responses.
PARAMETER DESCRIPTION validation_error
The validation error thrown by Pydantic during parsing.
TYPE: ValidationError
"},{"location":"reference/model/container/resource_container/#streampipes.model.container.resource_container.StreamPipesResourceContainerJSONError","title":"StreamPipesResourceContainerJSONError(container_name, json_string)
","text":" Bases: Exception
A custom exception to be raised when the returned JSON string does not suit to the structure of resource container.
PARAMETER DESCRIPTION container_name
The class name of the resource container where the invalid data structure was detected.
TYPE: str
json_string
The JSON string that has been tried to parse.
TYPE: str
"},{"location":"reference/model/container/versions/","title":"Versions","text":"Implementation of a resource container for the versions endpoint.
"},{"location":"reference/model/container/versions/#streampipes.model.container.versions.Versions","title":"Versions
","text":" Bases: ResourceContainer
Implementation of the resource container for the versions endpoint.
This resource container is a collection of versions returned by the StreamPipes API. It is capable of parsing the response content directly into a list of queried Version
. Furthermore, the resource container makes them accessible in a pythonic manner.
PARAMETER DESCRIPTION resources
A list of resources (Version) to be contained in the ResourceContainer
.
"},{"location":"reference/model/resource/data_lake_measure/","title":"Data lake measure","text":""},{"location":"reference/model/resource/data_lake_measure/#streampipes.model.resource.data_lake_measure.DataLakeMeasure","title":"DataLakeMeasure
","text":" Bases: Resource
Implementation of a resource for data lake measures.
This resource defines the data model used by resource container (model.container.DataLakeMeasures
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response, and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
"},{"location":"reference/model/resource/data_lake_measure/#streampipes.model.resource.data_lake_measure.DataLakeMeasure.convert_to_pandas_representation","title":"convert_to_pandas_representation()
","text":"Returns the dictionary representation of a data lake measure to be used when creating a pandas Dataframe.
It excludes the following fields: element_id
, event_schema
, schema_version
. Instead of the whole event schema the number of event properties contained is returned with the column name num_event_properties
.
RETURNS DESCRIPTION pandas_repr
Pandas representation of the resource as a dictionary, which is then used by the respource container to create a data frame from a collection of resources.
TYPE: Dict[str, Any]
"},{"location":"reference/model/resource/data_series/","title":"Data series","text":""},{"location":"reference/model/resource/data_series/#streampipes.model.resource.data_series.DataSeries","title":"DataSeries
","text":" Bases: Resource
Implementation of a resource for data series. This resource defines the data model used by its resource container(model.container.DataLakeMeasures
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
"},{"location":"reference/model/resource/data_series/#streampipes.model.resource.data_series.DataSeries--notes","title":"Notes","text":"This class will only exist temporarily in it its current appearance since\nthere are some inconsistencies in the StreamPipes API.\n
"},{"location":"reference/model/resource/data_series/#streampipes.model.resource.data_series.DataSeries.convert_to_pandas_representation","title":"convert_to_pandas_representation()
","text":"Returns the dictionary representation of a data lake series to be used when creating a pandas Dataframe.
It contains only the \"header rows\" (the column names) and \"rows\" that contain the actual data.
RETURNS DESCRIPTION pandas_repr
Dictionary with the keys headers
and rows
TYPE: dict[str, Any]
"},{"location":"reference/model/resource/data_series/#streampipes.model.resource.data_series.DataSeries.from_json","title":"from_json(json_string)
classmethod
","text":"Creates an instance of DataSeries
from a given JSON string.
This method is used by the resource container to parse the JSON response of the StreamPipes API. Currently, it only supports data lake series that consist of exactly one series of data.
PARAMETER DESCRIPTION json_string
The JSON string the data lake series should be created on.
TYPE: str
RETURNS DESCRIPTION DataSeries
Instance of DataSeries
that is created based on the given JSON string.
RAISES DESCRIPTION StreamPipesUnsupportedDataLakeSeries
If the data lake series returned by the StreamPipes API cannot be parsed with the current version of the Python client.
"},{"location":"reference/model/resource/data_series/#streampipes.model.resource.data_series.DataSeries.to_pandas","title":"to_pandas()
","text":"Returns the data lake series in representation of a Pandas Dataframe.
RETURNS DESCRIPTION pd
The data lake series in form of a pandas dataframe
TYPE: pd.DataFrame
"},{"location":"reference/model/resource/data_stream/","title":"Data stream","text":""},{"location":"reference/model/resource/data_stream/#streampipes.model.resource.data_stream.DataStream","title":"DataStream(**kwargs)
","text":" Bases: Resource
Implementation of a resource for data streams.
This resource defines the data model used by resource container (model.container.DataStreams
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
"},{"location":"reference/model/resource/data_stream/#streampipes.model.resource.data_stream.DataStream.convert_to_pandas_representation","title":"convert_to_pandas_representation()
","text":"Returns the dictionary representation of a data stream to be used when creating a pandas Dataframe.
RETURNS DESCRIPTION pandas_repr
Pandas representation of the resource as a dictionary, which is then used by the respource container to create a data frame from a collection of resources.
TYPE: Dict[str, Any]
"},{"location":"reference/model/resource/data_stream/#streampipes.model.resource.data_stream.DataStream.to_dict","title":"to_dict(use_source_names=True)
","text":"Returns the resource in dictionary representation.
PARAMETER DESCRIPTION use_source_names
Indicates if the dictionary keys are in python representation or equally named to the StreamPipes backend
DEFAULT: True
RETURNS DESCRIPTION resource
The resource as dictionary representation
TYPE: Dict[str, Any]
"},{"location":"reference/model/resource/exceptions/","title":"Exceptions","text":""},{"location":"reference/model/resource/exceptions/#streampipes.model.resource.exceptions.StreamPipesUnsupportedDataSeries","title":"StreamPipesUnsupportedDataSeries(reason=None)
","text":" Bases: Exception
Exception to be raised when the returned data lake series cannot be parsed with the current implementation of the resource.
"},{"location":"reference/model/resource/function_definition/","title":"Function definition","text":""},{"location":"reference/model/resource/function_definition/#streampipes.model.resource.function_definition.FunctionDefinition","title":"FunctionDefinition
","text":" Bases: Resource
Configuration for a StreamPipes Function.
This class maps to the FunctionDefinition
class in the StreamPipes model. It contains all metadata that are required to register a function at the StreamPipes backend.
PARAMETER DESCRIPTION consumed_streams
List of data streams the function is consuming from
function_id
identifier object of a StreamPipes function
ATTRIBUTE DESCRIPTION output_data_streams
Map off all output data streams added to the function definition
TYPE: Dict[str, DataStream]
"},{"location":"reference/model/resource/function_definition/#streampipes.model.resource.function_definition.FunctionDefinition.add_output_data_stream","title":"add_output_data_stream(data_stream)
","text":"Adds an output data stream to the function which makes it possible to write data back to StreamPipes.
PARAMETER DESCRIPTION data_stream
The schema of the output data stream.
TYPE: DataStream
RETURNS DESCRIPTION self
Instance of the function definition that is extended by the provided DataStream
TYPE: FunctionDefinition
"},{"location":"reference/model/resource/function_definition/#streampipes.model.resource.function_definition.FunctionDefinition.convert_to_pandas_representation","title":"convert_to_pandas_representation()
","text":"Returns the dictionary representation of a function definition to be used when creating a pandas Dataframe.
RETURNS DESCRIPTION pandas_repr
Pandas representation of the resource as a dictionary, which is then used by the respource container to create a data frame from a collection of resources.
TYPE: Dict[str, Any]
"},{"location":"reference/model/resource/function_definition/#streampipes.model.resource.function_definition.FunctionDefinition.get_output_data_streams","title":"get_output_data_streams()
","text":"Get the output data streams of the function.
RETURNS DESCRIPTION output_streams
Dictionary with every known stream id and the related output stream.
TYPE: Dict[str, DataStream]
"},{"location":"reference/model/resource/function_definition/#streampipes.model.resource.function_definition.FunctionDefinition.get_output_stream_ids","title":"get_output_stream_ids()
","text":"Get the stream ids of the output data streams.
RETURNS DESCRIPTION output_stream_ids
List of all stream ids
TYPE: List[str]
"},{"location":"reference/model/resource/function_definition/#streampipes.model.resource.function_definition.FunctionId","title":"FunctionId
","text":" Bases: BasicModel
Identification object for a StreamPipes function.
Maps to the FunctionId
class defined in the StreamPipes model.
PARAMETER DESCRIPTION id
unique identifier of the function instance
version
version of the corresponding function
"},{"location":"reference/model/resource/query_result/","title":"Query result","text":""},{"location":"reference/model/resource/query_result/#streampipes.model.resource.query_result.QueryResult","title":"QueryResult
","text":" Bases: Resource
Implementation of a resource for query result. This resource defines the data model used by its resource container(model.container.DataLakeMeasures
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
"},{"location":"reference/model/resource/query_result/#streampipes.model.resource.query_result.QueryResult.convert_to_pandas_representation","title":"convert_to_pandas_representation()
","text":"Returns the dictionary representation of a data lake series to be used when creating a pandas Dataframe.
It contains only the \"header rows\" (the column names) and \"rows\" that contain the actual data.
RETURNS DESCRIPTION dict
Dictionary with the keys headers
and rows
RAISES DESCRIPTION StreamPipesUnsupportedDataLakeSeries
If the query result returned by the StreamPipes API cannot be converted to the pandas representation
"},{"location":"reference/model/resource/query_result/#streampipes.model.resource.query_result.QueryResult.to_pandas","title":"to_pandas()
","text":"Returns the data lake series in representation of a Pandas Dataframe.
RETURNS DESCRIPTION df
Pandas df containing the query result
TYPE: pd.DataFrame
"},{"location":"reference/model/resource/resource/","title":"Resource","text":"General and abstract implementation for a resource.
A resource defines the data model that is used by a resource container (model.container.resourceContainer
).
"},{"location":"reference/model/resource/resource/#streampipes.model.resource.resource.Resource","title":"Resource
","text":" Bases: ABC
, BasicModel
General and abstract implementation for a resource.
A resource defines the data model used by a resource container (model.container.resourceContainer
). It inherits from Pydantic's BaseModel to get all its superpowers, which are used to parse, validate the API response and to easily switch between the Python representation (both serialized and deserialized) and Java representation (serialized only).
"},{"location":"reference/model/resource/resource/#streampipes.model.resource.resource.Resource.convert_to_pandas_representation","title":"convert_to_pandas_representation()
abstractmethod
","text":"Returns a dictionary representation to be used when creating a pandas Dataframe.
RETURNS DESCRIPTION pandas_repr
Pandas representation of the resource as a dictionary, which is then used by the respource container to create a data frame from a collection of resources.
TYPE: Dict[str, Any]
"},{"location":"reference/model/resource/resource/#streampipes.model.resource.resource.Resource.to_dict","title":"to_dict(use_source_names=True)
","text":"Returns the resource in dictionary representation.
PARAMETER DESCRIPTION use_source_names
Indicates if the dictionary keys are in python representation or equally named to the StreamPipes backend
DEFAULT: True
RETURNS DESCRIPTION resource
The resource as dictionary representation
TYPE: Dict[str, Any]
"},{"location":"reference/model/resource/version/","title":"Version","text":""},{"location":"reference/model/resource/version/#streampipes.model.resource.version.Version","title":"Version
","text":" Bases: Resource
Metadata about the version of the connected StreamPipes server.
ATTRIBUTE DESCRIPTION backend_version
version of the StreamPipes backend the client is connected to
TYPE: str
"},{"location":"reference/model/resource/version/#streampipes.model.resource.version.Version.convert_to_pandas_representation","title":"convert_to_pandas_representation()
","text":"Returns the dictionary representation of the version metadata to be used when creating a pandas Dataframe.
"},{"location":"scripts/gen_ref_pages/","title":"Gen ref pages","text":"Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
In\u00a0[\u00a0]: Copied! from pathlib import Path\n
from pathlib import Path In\u00a0[\u00a0]: Copied! import mkdocs_gen_files\n
import mkdocs_gen_files In\u00a0[\u00a0]: Copied! nav = mkdocs_gen_files.Nav()\n
nav = mkdocs_gen_files.Nav() In\u00a0[\u00a0]: Copied! for path in sorted(Path(\"streampipes\").rglob(\"*.py\")):\n module_path = path.relative_to(\"streampipes\").with_suffix(\"\")\n doc_path = path.relative_to(\"streampipes\").with_suffix(\".md\")\n full_doc_path = Path(\"reference\", doc_path)\n\n parts = list(module_path.parts)\n\n if parts[-1] == \"__init__\":\n # parts = parts[:-1]\n continue\n elif parts[-1] == \"__version__\":\n continue\n elif parts[-1] == \"__main__\":\n continue\n elif parts[-1] == \" \":\n continue\n\n nav[parts] = doc_path.as_posix()\n\n with mkdocs_gen_files.open(full_doc_path, \"w+\") as fd:\n identifier = \".\".join(parts)\n print(f\"::: streampipes.{identifier}\", file=fd)\n\n mkdocs_gen_files.set_edit_path(full_doc_path, path)\n
for path in sorted(Path(\"streampipes\").rglob(\"*.py\")): module_path = path.relative_to(\"streampipes\").with_suffix(\"\") doc_path = path.relative_to(\"streampipes\").with_suffix(\".md\") full_doc_path = Path(\"reference\", doc_path) parts = list(module_path.parts) if parts[-1] == \"__init__\": # parts = parts[:-1] continue elif parts[-1] == \"__version__\": continue elif parts[-1] == \"__main__\": continue elif parts[-1] == \" \": continue nav[parts] = doc_path.as_posix() with mkdocs_gen_files.open(full_doc_path, \"w+\") as fd: identifier = \".\".join(parts) print(f\"::: streampipes.{identifier}\", file=fd) mkdocs_gen_files.set_edit_path(full_doc_path, path) with mkdocs_gen_files.open(\"reference/SUMMARY.md\", \"w+\") as nav_file: nav_file.writelines(nav.build_literate_nav())
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/","title":"Introduction to StreamPipes Python","text":"In\u00a0[\u00a0]: Copied! %pip install streampipes\n
%pip install streampipes If you want to have the current development state you can also execute:
In\u00a0[\u00a0]: Copied! %pip install git+https://github.com/apache/streampipes.git#subdirectory=streampipes-client-python\n
%pip install git+https://github.com/apache/streampipes.git#subdirectory=streampipes-client-python The corresponding documentation can be found here.
In\u00a0[\u00a0]: Copied! from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
from streampipes.client import StreamPipesClient from streampipes.client.config import StreamPipesClientConfig from streampipes.client.credential_provider import StreamPipesApiKeyCredentials In\u00a0[\u00a0]: Copied! config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(\n username=\"test@streampipes.apache.org\",\n api_key=\"API-KEY\",\n ),\n host_address=\"localhost\",\n https_disabled=True,\n port=80\n)\n
config = StreamPipesClientConfig( credential_provider=StreamPipesApiKeyCredentials( username=\"test@streampipes.apache.org\", api_key=\"API-KEY\", ), host_address=\"localhost\", https_disabled=True, port=80 ) Please be aware that connecting to StreamPipes via a https
connection is currently not supported by the Python client.
Providing secrets like the api_key
as plaintext in the source code is an anti-pattern. This is why the StreamPipes client also supports passing the required secrets as environment variables. To do so, you must initialize the credential provider like the following:
In\u00a0[\u00a0]: Copied! StreamPipesApiKeyCredentials()\n
StreamPipesApiKeyCredentials() To ensure that the above code works, you must set the environment variables as expected. This can be done like following:
In\u00a0[\u00a0]: Copied! %export SP_USERNAME=\"<USERNAME>\"\n%export SP_API_KEY=\"<API-KEY>\"\n
%export SP_USERNAME=\"\" %export SP_API_KEY=\"\" Having the config
ready, we can now initialize the actual client.
In\u00a0[\u00a0]: Copied! client = StreamPipesClient(client_config=config)\n
client = StreamPipesClient(client_config=config) That's already it. You can check if everything works out by using the following command:
In\u00a0[6]: Copied! client.describe()\n
client.describe() 2023-02-24 17:05:49,398 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n2023-02-24 17:05:49,457 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n\nHi there!\nYou are connected to a StreamPipes instance running at http://localhost:80.\nThe following StreamPipes resources are available with this client:\n1x DataLakeMeasures\n1x DataStreams\n
This prints you a short textual description of the connected StreamPipes instance to the console.
The created client
instance serves as the central point of interaction with StreamPipes. You can invoke a variety of commands directly on this object.
Are you curious now how you actually can get data out of StreamPipes and make use of it with Python? Then check out the next tutorial on extracting Data from the StreamPipes data lake.
Thanks for reading this introductory tutorial. We hope you like it and would love to receive some feedback from you. Just go to our GitHub discussion page and let us know your impression. We'll read and react to them all, we promise!
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/#Introduction-to-StreamPipes-Python","title":"Introduction to StreamPipes Python\u00b6","text":""},{"location":"tutorials/1-introduction-to-streampipes-python-client/#Why-there-is-an-extra-Python-library-for-StreamPipes?","title":"Why there is an extra Python library for StreamPipes?\u00b6","text":"Apache StreamPipes aims to enable non-technical users to connect and analyze IoT data streams. To this end, it provides an easy-to-use and convenient user interface that allows one to connect to an IoT data source and create some visual graphs within a few minutes. Although this is the main use case of Apache StreamPipes, it can also provide great value for people who are eager to work on data analysis or data science with IoT data, but don't we do get in touch with all the hassle associated with extracting data from devices in a suitable format. In this scenario, StreamPipes helps you connect to your data source and extract the data for you. You then can make the data available outside StreamPipes by writing it into an external source, such as a database, Kafka, etc. While this requires another component, you can also extract your data directly from StreamPipes programmatically using the StreamPipes API. For convenience, we also provide you with a StreamPipes client both available for Java and Python. Specifically with StreamPipes Python, we want to address the amazing data analytics and data science community in Python and benefit from the great universe of Python libraries out there.
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/#How-to-install-StreamPipes-Python?","title":"How to install StreamPipes Python?\u00b6","text":"Simply use the following pip
command:
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/#How-to-prepare-the-tutorials","title":"How to prepare the tutorials\u00b6","text":"In case you want to reproduce the first two tutorials exactly on your end, you need to create a simple pipeline in StreamPipes like demonstrated below.
"},{"location":"tutorials/1-introduction-to-streampipes-python-client/#How-to-configure-the-Python-client","title":"How to configure the Python client\u00b6","text":"In order to access the resources available in StreamPipes, one must be able to authenticate against the backend. For this purpose, the client sofar only supports the authentication via an API token that can be generated via the StreamPipes UI, as you see below.
Having generated the API token, one can directly start initializing a client instance as follows:
"},{"location":"tutorials/2-extracting-data-from-the-streampipes-data-lake/","title":"Extracting Data from the StreamPipes data lake","text":"In\u00a0[1]: Copied! from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
from streampipes.client import StreamPipesClient from streampipes.client.config import StreamPipesClientConfig from streampipes.client.credential_provider import StreamPipesApiKeyCredentials In\u00a0[\u00a0]: Copied! # if you want all necessary dependencies required for this tutorial to be installed,\n# you can simply execute the following command\n%pip install matplotlib streampipes\n
# if you want all necessary dependencies required for this tutorial to be installed, # you can simply execute the following command %pip install matplotlib streampipes In\u00a0[2]: Copied! import os\nos.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\"\nos.environ[\"SP_API_KEY\"] = \"XXX\"\n
import os os.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\" os.environ[\"SP_API_KEY\"] = \"XXX\" In\u00a0[3]: Copied! config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(),\n host_address=\"localhost\",\n https_disabled=True,\n port=80\n)\n
config = StreamPipesClientConfig( credential_provider=StreamPipesApiKeyCredentials(), host_address=\"localhost\", https_disabled=True, port=80 ) In\u00a0[4]: Copied! client = StreamPipesClient(client_config=config)\n
client = StreamPipesClient(client_config=config) 2023-02-24 17:34:25,860 - streampipes.client.client - [INFO] - [client.py:128] [_set_up_logging] - Logging successfully initialized with logging level INFO.\n
As a first step, we want to get an overview about all data available in the data lake. The data is stored as so-called measures
, which refer to a data stream stored in the data lake. For his purpose we use the all()
method of the dataLakeMeasure
endpoint.
In\u00a0[5]: Copied! data_lake_measures = client.dataLakeMeasureApi.all()\n
data_lake_measures = client.dataLakeMeasureApi.all() 2023-02-24 17:34:25,929 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n
So let's see how many measures are available
In\u00a0[6]: Copied! len(data_lake_measures)\n
len(data_lake_measures) Out[6]: 2
All resources of the StreamPipes Python client support the standard Python expressions. If not, please let us know.
In\u00a0[7]: Copied! data_lake_measures[-1]\n
data_lake_measures[-1] Out[7]: DataLakeMeasure(element_id='3cb6b5e6f107452483d1fd2ccf4bf9f9', measure_name='test', timestamp_field='s0::timestamp', event_schema=EventSchema(event_properties=[EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:EiFnkL', label='Density', description='Denotes the current density of the fluid', runtime_name='density', required=False, domain_properties=['http://schema.org/Number'], property_scope='MEASUREMENT_PROPERTY', index=5, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#float', measurement_unit=None, value_specification=None), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:ghSkQI', label='Mass Flow', description='Denotes the current mass flow in the sensor', runtime_name='mass_flow', required=False, domain_properties=['http://schema.org/Number'], property_scope='MEASUREMENT_PROPERTY', index=2, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#float', measurement_unit=None, value_specification=None), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:cQAUry', label='Sensor ID', description='The ID of the sensor', runtime_name='sensorId', required=False, domain_properties=['https://streampipes.org/vocabulary/examples/watertank/v1/hasSensorId'], property_scope='DIMENSION_PROPERTY', index=1, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#string', measurement_unit=None, value_specification=None), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:pbPMyL', label='Sensor Fault Flags', description='Any fault flags of the sensors', runtime_name='sensor_fault_flags', required=False, domain_properties=['http://schema.org/Boolean'], property_scope='MEASUREMENT_PROPERTY', index=6, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#boolean', measurement_unit=None, value_specification=None), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:Qmayhw', label='Temperature', description='Denotes the current temperature in degrees celsius', runtime_name='temperature', required=False, domain_properties=['http://schema.org/Number'], property_scope='MEASUREMENT_PROPERTY', index=4, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#float', measurement_unit='http://qudt.org/vocab/unit#DegreeCelsius', value_specification=ValueSpecification(class_name='org.apache.streampipes.model.schema.QuantitativeValue', element_id=None, min_value=0, max_value=100, step=0.1)), EventProperty(class_name='org.apache.streampipes.model.schema.EventPropertyPrimitive', element_id='sp:eventproperty:YQYhjd', label='Volume Flow', description='Denotes the current volume flow', runtime_name='volume_flow', required=False, domain_properties=['http://schema.org/Number'], property_scope='MEASUREMENT_PROPERTY', index=3, runtime_id=None, runtime_type='http://www.w3.org/2001/XMLSchema#float', measurement_unit=None, value_specification=None)]), pipeline_id=None, pipeline_name=None, pipeline_is_running=False, schema_version='1.1')
To get a more comprehensive overview, you can take a look at the pandas
representation
In\u00a0[8]: Copied! display(data_lake_measures.to_pandas())\n
display(data_lake_measures.to_pandas()) measure_name timestamp_field pipeline_id pipeline_name pipeline_is_running num_event_properties 0 flow-rate s0::timestamp None None False 6 1 test s0::timestamp None None False 6 So far, we have only retrieved metadata about the available data lake measure. In the following, we will access the actual data of the measure flow-rate
.
For this purpose, we will use the get()
method of the dataLakeMeasure
endpoint.
In\u00a0[9]: Copied! flow_rate_measure = client.dataLakeMeasureApi.get(identifier=\"flow-rate\")\n
flow_rate_measure = client.dataLakeMeasureApi.get(identifier=\"flow-rate\") 2023-02-24 17:34:26,020 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n
For further processing, the easiest way is to turn the data measure into a pandas DataFrame
.
In\u00a0[10]: Copied! flow_rate_pd = flow_rate_measure.to_pandas()\n
flow_rate_pd = flow_rate_measure.to_pandas() Let's see how many data points we got...
In\u00a0[11]: Copied! len(flow_rate_pd)\n
len(flow_rate_pd) Out[11]: 1000
... and get a first overview
In\u00a0[12]: Copied! flow_rate_pd.describe()\n
flow_rate_pd.describe() Out[12]: density mass_flow temperature volume_flow count 1000.000000 1000.000000 1000.000000 1000.000000 mean 45.560337 5.457014 45.480231 5.659558 std 3.201544 3.184959 3.132878 3.122437 min 40.007698 0.004867 40.000992 0.039422 25% 42.819497 2.654101 42.754623 3.021625 50% 45.679264 5.382355 45.435944 5.572553 75% 48.206881 8.183144 48.248473 8.338209 max 50.998310 10.986015 50.964909 10.998676 As a final step, we want to create a plot of both attributes
In\u00a0[13]: Copied! import matplotlib.pyplot as plt\nflow_rate_pd.plot(y=[\"mass_flow\", \"temperature\"])\nplt.show()\n
import matplotlib.pyplot as plt flow_rate_pd.plot(y=[\"mass_flow\", \"temperature\"]) plt.show() For data lake measurements, the get()
method is even more powerful than simply returning all the data for a given data lake measurement. We will look at a selection of these below. The full list of supported parameters can be found in the docs. Let's start by referring to the graph we created above, where we use only two columns of our data lake measurement. If we already know this, we can directly restrict the queried data to a subset of columns by using the columns
parameter. columns
takes a list of column names as a comma-separated string:
In\u00a0[14]: Copied! flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", columns=\"mass_flow,temperature\").to_pandas()\nflow_rate_pd\n
flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", columns=\"mass_flow,temperature\").to_pandas() flow_rate_pd 2023-02-24 17:34:26,492 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n
Out[14]: timestamp mass_flow temperature 0 2023-02-24T16:19:41.472Z 3.309556 44.448483 1 2023-02-24T16:19:41.482Z 5.608580 40.322033 2 2023-02-24T16:19:41.493Z 7.692881 49.239639 3 2023-02-24T16:19:41.503Z 3.632898 49.933754 4 2023-02-24T16:19:41.513Z 0.711260 50.106617 ... ... ... ... 995 2023-02-24T16:19:52.927Z 1.740114 46.558231 996 2023-02-24T16:19:52.94Z 7.211723 48.048622 997 2023-02-24T16:19:52.952Z 7.770180 48.188026 998 2023-02-24T16:19:52.965Z 4.458602 48.280899 999 2023-02-24T16:19:52.977Z 2.592060 47.505951 1000 rows \u00d7 3 columns
By default, the client returns only the first one thousand records of a Data Lake measurement. This can be changed by passing a concrete value for the limit
parameter:
In\u00a0[15]: Copied! flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", limit=10000).to_pandas()\nlen(flow_rate_pd)\n
flow_rate_pd = client.dataLakeMeasureApi.get(identifier=\"flow-rate\", limit=10000).to_pandas() len(flow_rate_pd) 2023-02-24 17:34:26,736 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n
Out[15]: 9528
If you want your data to be selected by time of occurrence rather than quantity, you can specify your time window by passing the start_date
and end_date
parameters:
In\u00a0[16]: Copied! from datetime import datetime\nflow_rate_pd = client.dataLakeMeasureApi.get(\n identifier=\"flow-rate\",\n start_date=datetime(year=2023, month=2, day=24, hour=17, minute=21, second=0),\n end_date=datetime(year=2023, month=2, day=24, hour=17, minute=21, second=1),\n ).to_pandas()\nflow_rate_pd.plot(y=[\"mass_flow\", \"temperature\"])\nplt.show()\n
from datetime import datetime flow_rate_pd = client.dataLakeMeasureApi.get( identifier=\"flow-rate\", start_date=datetime(year=2023, month=2, day=24, hour=17, minute=21, second=0), end_date=datetime(year=2023, month=2, day=24, hour=17, minute=21, second=1), ).to_pandas() flow_rate_pd.plot(y=[\"mass_flow\", \"temperature\"]) plt.show() 2023-02-24 17:34:26,899 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:167] [_make_request] - Successfully retrieved all resources.\n
... from this point on we leave all future processing of the data up to your creativity. Keep in mind: the general syntax used in this tutorial (all()
, to_pandas()
, get()
) applies to all endpoints and associated resources of the StreamPipes Python client.
If you get further and create exiting stuff with data extracted from StreamPipes please let us know. We are thrilled to see what you as a community will build with the provided client. Furthermore, don't hesitate to discuss feature requests to extend the current functionality with us.
For now, that's all about the StreamPipes client. Read the next tutorial (Getting live data from the StreamPipes data stream) if you are interested in making use of the powerful StreamPipes functions to interact with StreamPipes event-based.
How do you like this tutorial? We hope you like it and would love to receive some feedback from you. Just go to our GitHub discussion page and let us know your impression. We'll read and react to them all, we promise!
"},{"location":"tutorials/2-extracting-data-from-the-streampipes-data-lake/#Extracting-Data-from-the-StreamPipes-data-lake","title":"Extracting Data from the StreamPipes data lake\u00b6","text":"In the first tutorial (Introduction to the StreamPipes Python client) we took the first steps with the StreamPipes Python client and learned how to set everything up. Now we are ready to get started and want to retrieve some data out of StreamPipes. In this tutorial, we'll focus on the StreamPipes Data Lake, the component where StreamPipes stores data internally. To get started, we'll use the client
instance created in the first tutorial.
"},{"location":"tutorials/3-getting-live-data-from-the-streampipes-data-stream/","title":"Getting live data from the StreamPipes data stream","text":"Note As of now we mainly developed the support for StreamPipes functions using NATS as messaging protocol. Consequently, this setup is tested most and should work flawlessly. Visit our first-steps page to see how to start StreamPipes accordingly. Anyhow, you can also use the other brokers that are currently supported in StreamPipes Python. In case you observe any problems, please reach out to us and file us an issue on GitHub.
In\u00a0[1]: Copied! from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
from streampipes.client import StreamPipesClient from streampipes.client.config import StreamPipesClientConfig from streampipes.client.credential_provider import StreamPipesApiKeyCredentials In\u00a0[\u00a0]: Copied! # You can install all required libraries for this tutorial with the following command\n%pip install matplotlib ipython streampipes\n
# You can install all required libraries for this tutorial with the following command %pip install matplotlib ipython streampipes In\u00a0[2]: Copied! import os\n\nos.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\"\nos.environ[\"SP_API_KEY\"] = \"XXX\"\n\n# Use this if you work locally:\nos.environ[\"BROKER-HOST\"] = \"localhost\" \nos.environ[\"KAFKA-PORT\"] = \"9094\" # When using Kafka as message broker. If Kafka is not running on localhost, KAFKA_ADVERTISED_LISTENERS should be adjusted to the external address\n
import os os.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\" os.environ[\"SP_API_KEY\"] = \"XXX\" # Use this if you work locally: os.environ[\"BROKER-HOST\"] = \"localhost\" os.environ[\"KAFKA-PORT\"] = \"9094\" # When using Kafka as message broker. If Kafka is not running on localhost, KAFKA_ADVERTISED_LISTENERS should be adjusted to the external address In\u00a0[3]: Copied! client_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(),\n host_address=\"localhost\",\n port=80,\n https_disabled=True,\n)\nclient = StreamPipesClient(client_config=client_config)\n
client_config = StreamPipesClientConfig( credential_provider=StreamPipesApiKeyCredentials(), host_address=\"localhost\", port=80, https_disabled=True, ) client = StreamPipesClient(client_config=client_config) 2022-12-14 10:43:37,664 - streampipes.client.client - [INFO] - [client.py:127] [_set_up_logging] - Logging successfully initialized with logging level INFO.\n
Now we can have a look at the available data streams. We can choose one or more stream to receive the data from and copy their element_id
.
In\u00a0[4]: Copied! client.dataStreamApi.all().to_pandas()\n
client.dataStreamApi.all().to_pandas() 2022-12-14 10:43:39,944 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:153] [_make_request] - Successfully retrieved all resources.\n
Out[4]: element_id name description icon_url app_id includes_assets includes_locales internally_managed measurement_object index ... uri dom num_transport_protocols num_measurement_capability num_application_links num_included_assets num_connected_to num_category num_event_properties num_included_locales 0 urn:streampipes.apache.org:eventstream:HHoidJ Test2 None None False False True None 0 ... urn:streampipes.apache.org:eventstream:HHoidJ None 1 0 0 0 0 0 7 0 1 urn:streampipes.apache.org:eventstream:uPDKLI Test None None False False True None 0 ... urn:streampipes.apache.org:eventstream:uPDKLI None 1 0 0 0 0 0 7 0 2 rows \u00d7 21 columns
Next we can create a StreamPipesFunction. For this we need to implement the 3 following methods:
onServiceStarted
is called when the function gets started. There you can use the given meta information of the FunctionContext
to initialize the function. onEvent
is called when ever a new event arrives. The event
contains the live data and you can use the streamId
to identify a stream if the function is connected to multiple data streams. onServiceStopped
is called when the function gets stopped.
For this tutorial we just create a function that saves every new event in a pandas DataFrame
and plots the first column of the DataFrame
when the function gets stopped.
(If you want to use the same structure as in Java you can overwrite the getFunctionId
and requiredStreamIds
methods instead of using the FunctionDefinition
)
In\u00a0[5]: Copied! from typing import Dict, Any\nimport pandas as pd\nfrom datetime import datetime\nimport matplotlib.pyplot as plt\nfrom streampipes.functions.function_handler import FunctionHandler\nfrom streampipes.functions.registration import Registration\nfrom streampipes.functions.streampipes_function import StreamPipesFunction\nfrom streampipes.functions.utils.function_context import FunctionContext\nfrom streampipes.model.resource.function_definition import FunctionDefinition, FunctionId\n\nclass ExampleFunction(StreamPipesFunction):\n def __init__(self, function_definition: FunctionDefinition) -> None:\n super().__init__(function_definition)\n # Create the Dataframe to save the live data\n self.df = pd.DataFrame()\n\n def onServiceStarted(self, context: FunctionContext):\n # Get the name of the timestamp field\n for event_property in context.schema[context.streams[0]].event_schema.event_properties:\n if event_property.property_scope == \"HEADER_PROPERTY\":\n self.timestamp = event_property.runtime_name\n\n def onEvent(self, event: Dict[str, Any], streamId: str):\n # Convert the unix timestamp to datetime\n event[self.timestamp] = datetime.fromtimestamp(event[self.timestamp] / 1000)\n # Add every value of the event to the DataFrame\n self.df = pd.concat(\n [self.df, pd.DataFrame({key: [event[key]] for key in event.keys()}).set_index(self.timestamp)]\n )\n\n def onServiceStopped(self):\n # Plot the first column of the Dataframe\n plt.figure(figsize=(10, 5))\n plt.xlabel(self.timestamp)\n plt.ylabel(self.df.columns[0])\n plt.plot(self.df.iloc[:, 0])\n plt.show()\n
from typing import Dict, Any import pandas as pd from datetime import datetime import matplotlib.pyplot as plt from streampipes.functions.function_handler import FunctionHandler from streampipes.functions.registration import Registration from streampipes.functions.streampipes_function import StreamPipesFunction from streampipes.functions.utils.function_context import FunctionContext from streampipes.model.resource.function_definition import FunctionDefinition, FunctionId class ExampleFunction(StreamPipesFunction): def __init__(self, function_definition: FunctionDefinition) -> None: super().__init__(function_definition) # Create the Dataframe to save the live data self.df = pd.DataFrame() def onServiceStarted(self, context: FunctionContext): # Get the name of the timestamp field for event_property in context.schema[context.streams[0]].event_schema.event_properties: if event_property.property_scope == \"HEADER_PROPERTY\": self.timestamp = event_property.runtime_name def onEvent(self, event: Dict[str, Any], streamId: str): # Convert the unix timestamp to datetime event[self.timestamp] = datetime.fromtimestamp(event[self.timestamp] / 1000) # Add every value of the event to the DataFrame self.df = pd.concat( [self.df, pd.DataFrame({key: [event[key]] for key in event.keys()}).set_index(self.timestamp)] ) def onServiceStopped(self): # Plot the first column of the Dataframe plt.figure(figsize=(10, 5)) plt.xlabel(self.timestamp) plt.ylabel(self.df.columns[0]) plt.plot(self.df.iloc[:, 0]) plt.show() Now we can start the function. First we create an instance of the ExampleFunction
and insert the element_id
of the stream which data we want to consume. Then we have to register this function and we can start all functions by initializing the FunctionHandler
. (it's also possible to register multiple functions with .register(...).register(...)
)
In\u00a0[6]: Copied! example_function = ExampleFunction(\n FunctionDefinition(\n function_id=FunctionId(id=\"example-function\"),\n consumed_streams=[\"urn:streampipes.apache.org:eventstream:uPDKLI\"]\n )\n)\n\nregistration = Registration()\nregistration.register(example_function)\n\nfunction_handler = FunctionHandler(registration, client)\nfunction_handler.initializeFunctions()\n
example_function = ExampleFunction( FunctionDefinition( function_id=FunctionId(id=\"example-function\"), consumed_streams=[\"urn:streampipes.apache.org:eventstream:uPDKLI\"] ) ) registration = Registration() registration.register(example_function) function_handler = FunctionHandler(registration, client) function_handler.initializeFunctions() 2022-12-14 10:43:42,810 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:153] [_make_request] - Successfully retrieved all resources.\n2022-12-14 10:43:42,812 - streampipes.functions.function_handler - [INFO] - [function_handler.py:82] [initializeFunctions] - Using NatsBroker for <__main__.ExampleFunction object at 0x000001F2EF298D90>\n
The DataFrame
of the ExampleFunction
gets updated whenever a new event arrives. Let's test this by executing the cell below.
In\u00a0[7]: Copied! import asyncio\nfrom asyncio.exceptions import CancelledError\nfrom IPython.display import clear_output\n\nwhile True:\n clear_output(wait=True)\n display(example_function.df)\n try:\n await asyncio.sleep(1)\n except CancelledError:\n break\n
import asyncio from asyncio.exceptions import CancelledError from IPython.display import clear_output while True: clear_output(wait=True) display(example_function.df) try: await asyncio.sleep(1) except CancelledError: break mass_flow density volume_flow sensor_fault_flags temperature sensorId timestamp 2022-12-14 10:43:43.357 10.955496 47.546290 1.001985 False 44.993413 flowrate02 2022-12-14 10:43:44.371 6.499040 44.392069 2.034402 False 41.232352 flowrate02 2022-12-14 10:43:45.382 10.168300 41.192146 9.724287 False 46.812779 flowrate02 2022-12-14 10:43:46.395 10.849059 50.086308 5.832691 False 45.860412 flowrate02 2022-12-14 10:43:47.410 3.081855 47.254246 8.860531 False 50.505801 flowrate02 ... ... ... ... ... ... ... 2022-12-14 10:44:43.920 1.803572 41.978894 10.294002 False 47.820239 flowrate02 2022-12-14 10:44:44.932 1.967062 42.212883 3.237440 False 49.047258 flowrate02 2022-12-14 10:44:45.934 4.457819 47.561256 0.315024 False 40.223413 flowrate02 2022-12-14 10:44:46.949 8.745343 46.346891 7.439090 False 41.982529 flowrate02 2022-12-14 10:44:47.950 5.828744 47.679720 6.307405 False 42.100354 flowrate02 65 rows \u00d7 6 columns
The while
loop just displays the the DataFrame
every second until the cell is stopped. We could achieve the same result manually by executing example_function.df
repeatedly.
You can stop the functions whenever you want by executing the command below.
In\u00a0[\u00a0]: Copied! function_handler.disconnect()\n
function_handler.disconnect() 2022-12-14 10:44:53,309 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:67] [disconnect] - Stopped connection to stream: urn:streampipes.apache.org:eventstream:uPDKLI\n
That's enough for this tutorial. Now you can try to write your own StreamPipesFunction
. All you need to do is creating a new class, implementing the 4 required methods and registering the function.
Want to see more exciting use cases you can achieve with StreamPipes functions in Python? Then don't hesitate and jump to our next tutorial on applying online machine learning algorithms to StreamPipes data streams with River.
How do you like this tutorial? We hope you like it and would love to receive some feedback from you. Just go to our GitHub discussion page and let us know your impression. We'll read and react to them all, we promise!
"},{"location":"tutorials/3-getting-live-data-from-the-streampipes-data-stream/#Getting-live-data-from-the-StreamPipes-data-stream","title":"Getting live data from the StreamPipes data stream\u00b6","text":"In the last tutorial (Extracting Data from the StreamPipes data lake) we learned how to extract the stored data from a StreamPipes data lake. This tutorial is about the StreamPipes data stream and shows how to get the live data from StreamPipes into Python. Therefore, we first create the client
instance as before.
"},{"location":"tutorials/4-using-online-machine-learning-on-a-streampipes-data-stream/","title":"Using Online Machine Learning on a StreamPipes data stream","text":"In\u00a0[1]: Copied! from streampipes.client import StreamPipesClient\nfrom streampipes.client.config import StreamPipesClientConfig\nfrom streampipes.client.credential_provider import StreamPipesApiKeyCredentials\n
from streampipes.client import StreamPipesClient from streampipes.client.config import StreamPipesClientConfig from streampipes.client.credential_provider import StreamPipesApiKeyCredentials In\u00a0[\u00a0]: Copied! # you can install all required dependecies for this tutorial by executing the following command\n%pip install river streampipes\n
# you can install all required dependecies for this tutorial by executing the following command %pip install river streampipes In\u00a0[2]: Copied! import os\n\nos.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\"\nos.environ[\"SP_API_KEY\"] = \"XXX\"\n\n# Use this if you work locally:\nos.environ[\"BROKER-HOST\"] = \"localhost\" \nos.environ[\"KAFKA-PORT\"] = \"9094\" # When using Kafka as message broker\n
import os os.environ[\"SP_USERNAME\"] = \"admin@streampipes.apache.org\" os.environ[\"SP_API_KEY\"] = \"XXX\" # Use this if you work locally: os.environ[\"BROKER-HOST\"] = \"localhost\" os.environ[\"KAFKA-PORT\"] = \"9094\" # When using Kafka as message broker In\u00a0[3]: Copied! client_config = StreamPipesClientConfig(\n credential_provider=StreamPipesApiKeyCredentials(),\n host_address=\"localhost\",\n port=80,\n https_disabled=True,\n)\nclient = StreamPipesClient(client_config=client_config)\n
client_config = StreamPipesClientConfig( credential_provider=StreamPipesApiKeyCredentials(), host_address=\"localhost\", port=80, https_disabled=True, ) client = StreamPipesClient(client_config=client_config) 2023-01-27 16:04:24,784 - streampipes.client.client - [INFO] - [client.py:128] [_set_up_logging] - Logging successfully initialized with logging level INFO.\n
In\u00a0[4]: Copied! client.dataStreamApi.all().to_pandas()\n
client.dataStreamApi.all().to_pandas() 2023-01-27 16:04:28,212 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:163] [_make_request] - Successfully retrieved all resources.\n
Out[4]: element_id name description icon_url app_id includes_assets includes_locales internally_managed measurement_object index ... dom rev num_transport_protocols num_measurement_capability num_application_links num_included_assets num_connected_to num_category num_event_properties num_included_locales 0 sp:spdatastream:xboBFK Test None None False False True None 0 ... None 5-558c861debc745e1ebae29a266a8bdb9 1 0 0 0 0 0 7 0 1 urn:streampipes.apache.org:eventstream:Wgyrse Test File None None False False True None 0 ... None 4-66548b6b84287011b7cec0876ef82baf 1 0 0 0 0 0 2 0 2 rows \u00d7 22 columns
In\u00a0[5]: Copied! from river import cluster, compose, preprocessing\nfrom streampipes.function_zoo.river_function import OnlineML\nfrom streampipes.functions.utils.data_stream_generator import RuntimeType\n\nk_means = compose.Pipeline(\n (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")),\n (\"scale\", preprocessing.StandardScaler()),\n (\"k_means\", cluster.KMeans(n_clusters=2)),\n)\n\nclustering = OnlineML(\n client=client, stream_ids=[\"sp:spdatastream:xboBFK\"], model=k_means, prediction_type=RuntimeType.INTEGER.value\n)\nclustering.start()\n
from river import cluster, compose, preprocessing from streampipes.function_zoo.river_function import OnlineML from streampipes.functions.utils.data_stream_generator import RuntimeType k_means = compose.Pipeline( (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")), (\"scale\", preprocessing.StandardScaler()), (\"k_means\", cluster.KMeans(n_clusters=2)), ) clustering = OnlineML( client=client, stream_ids=[\"sp:spdatastream:xboBFK\"], model=k_means, prediction_type=RuntimeType.INTEGER.value ) clustering.start() 2023-01-27 16:04:35,599 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:163] [_make_request] - Successfully retrieved all resources.\n2023-01-27 16:04:35,599 - streampipes.functions.function_handler - [INFO] - [function_handler.py:64] [initializeFunctions] - Create output data stream \"sp:spdatastream:cwKPoo\" for the function \"65cf8b86-bcdf-433e-a1c7-3e920eab55d0\"\n2023-01-27 16:04:37,766 - streampipes.endpoint.endpoint - [INFO] - [endpoint.py:163] [_make_request] - Successfully retrieved all resources.\n2023-01-27 16:04:37,767 - streampipes.functions.function_handler - [INFO] - [function_handler.py:78] [initializeFunctions] - Using NatsBroker for RiverFunction\n2023-01-27 16:04:37,791 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:48] [_makeConnection] - Connected to NATS at localhost:4222\n2023-01-27 16:04:37,791 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:48] [_makeConnection] - Connected to NATS at localhost:4222\n2023-01-27 16:04:37,792 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:58] [createSubscription] - Subscribed to stream: sp:spdatastream:xboBFK\n
In\u00a0[6]: Copied! clustering.set_learning(False)\n
clustering.set_learning(False) In\u00a0[\u00a0]: Copied! clustering.stop()\n
clustering.stop() 2023-01-27 16:04:57,303 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:82] [disconnect] - Stopped connection to stream: sp:spdatastream:xboBFK\n2023-01-27 16:04:57,304 - streampipes.functions.broker.nats_broker - [INFO] - [nats_broker.py:82] [disconnect] - Stopped connection to stream: sp:spdatastream:cwKPoo\n
In\u00a0[\u00a0]: Copied! import pickle\nfrom river import compose, tree\nfrom streampipes.function_zoo.river_function import OnlineML\nfrom streampipes.functions.utils.data_stream_generator import RuntimeType\n\nhoeffding_tree = compose.Pipeline(\n (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")),\n (\"hoeffding_tree\", tree.HoeffdingTreeRegressor(grace_period=5)),\n)\n\n\ndef draw_tree(self, event, streamId):\n\"\"\"Draw the tree and save the image.\"\"\"\n if self.learning:\n if self.model[1].n_nodes != None:\n self.model[1].draw().render(\"hoeffding_tree\", format=\"png\", cleanup=True)\n\n\ndef save_model(self):\n\"\"\"Save the trained model.\"\"\"\n with open(\"hoeffding_tree.pkl\", \"wb\") as f:\n pickle.dump(self.model, f)\n\n\nregressor = OnlineML(\n client=client,\n stream_ids=[\"sp:spdatastream:xboBFK\"],\n model=hoeffding_tree,\n prediction_type=RuntimeType.FLOAT.value,\n supervised=True,\n target_label=\"temperature\",\n on_event=draw_tree,\n on_stop=save_model,\n)\nregressor.start()\n
import pickle from river import compose, tree from streampipes.function_zoo.river_function import OnlineML from streampipes.functions.utils.data_stream_generator import RuntimeType hoeffding_tree = compose.Pipeline( (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")), (\"hoeffding_tree\", tree.HoeffdingTreeRegressor(grace_period=5)), ) def draw_tree(self, event, streamId): \"\"\"Draw the tree and save the image.\"\"\" if self.learning: if self.model[1].n_nodes != None: self.model[1].draw().render(\"hoeffding_tree\", format=\"png\", cleanup=True) def save_model(self): \"\"\"Save the trained model.\"\"\" with open(\"hoeffding_tree.pkl\", \"wb\") as f: pickle.dump(self.model, f) regressor = OnlineML( client=client, stream_ids=[\"sp:spdatastream:xboBFK\"], model=hoeffding_tree, prediction_type=RuntimeType.FLOAT.value, supervised=True, target_label=\"temperature\", on_event=draw_tree, on_stop=save_model, ) regressor.start() In\u00a0[9]: Copied! regressor.set_learning(False)\n
regressor.set_learning(False) In\u00a0[\u00a0]: Copied! regressor.stop()\n
regressor.stop() In\u00a0[\u00a0]: Copied! import pickle\nfrom river import compose, tree\nfrom streampipes.function_zoo.river_function import OnlineML\nfrom streampipes.functions.utils.data_stream_generator import RuntimeType\n\ndecision_tree = compose.Pipeline(\n (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")),\n (\"decision_tree\", tree.ExtremelyFastDecisionTreeClassifier(grace_period=5)),\n)\n\n\ndef draw_tree(self, event, streamId):\n\"\"\"Draw the tree and save the image.\"\"\"\n if self.learning:\n if self.model[1].n_nodes != None:\n self.model[1].draw().render(\"decicion_tree\", format=\"png\", cleanup=True)\n\n\ndef save_model(self):\n\"\"\"Save the trained model.\"\"\"\n with open(\"decision_tree.pkl\", \"wb\") as f:\n pickle.dump(self.model, f)\n\n\nclassifier = OnlineML(\n client=client,\n stream_ids=[\"sp:spdatastream:xboBFK\"],\n model=decision_tree,\n prediction_type=RuntimeType.BOOLEAN.value,\n supervised=True,\n target_label=\"sensor_fault_flags\",\n on_event=draw_tree,\n on_stop=save_model,\n)\nclassifier.start()\n
import pickle from river import compose, tree from streampipes.function_zoo.river_function import OnlineML from streampipes.functions.utils.data_stream_generator import RuntimeType decision_tree = compose.Pipeline( (\"drop_features\", compose.Discard(\"sensorId\", \"timestamp\")), (\"decision_tree\", tree.ExtremelyFastDecisionTreeClassifier(grace_period=5)), ) def draw_tree(self, event, streamId): \"\"\"Draw the tree and save the image.\"\"\" if self.learning: if self.model[1].n_nodes != None: self.model[1].draw().render(\"decicion_tree\", format=\"png\", cleanup=True) def save_model(self): \"\"\"Save the trained model.\"\"\" with open(\"decision_tree.pkl\", \"wb\") as f: pickle.dump(self.model, f) classifier = OnlineML( client=client, stream_ids=[\"sp:spdatastream:xboBFK\"], model=decision_tree, prediction_type=RuntimeType.BOOLEAN.value, supervised=True, target_label=\"sensor_fault_flags\", on_event=draw_tree, on_stop=save_model, ) classifier.start() In\u00a0[12]: Copied! classifier.set_learning(False)\n
classifier.set_learning(False) In\u00a0[\u00a0]: Copied! classifier.stop()\n
classifier.stop() How do you like this tutorial? We hope you like it and would love to receive some feedback from you. Just go to our GitHub discussion page and let us know your impression. We'll read and react to them all, we promise!
"},{"location":"tutorials/4-using-online-machine-learning-on-a-streampipes-data-stream/#Using-Online-Machine-Learning-on-a-StreamPipes-data-stream","title":"Using Online Machine Learning on a StreamPipes data stream\u00b6","text":"The last tutorial (Getting live data from the StreamPipes data stream) showed how we can connect to a data stream, and it would be possible to use Online Machine Learning with this approach and train a model with the incoming events at the onEvent
method. However, the StreamPipes client also provides an easier way to do this with the use of the River library for Online Machine Learning. We will have a look at this now.
"},{"location":"tutorials/4-using-online-machine-learning-on-a-streampipes-data-stream/#How-to-use-Online-Machine-Learning-with-StreamPipes","title":"How to use Online Machine Learning with StreamPipes\u00b6","text":"After we configured the client as usual, we can start with the new part. The approach is straight forward and you can start with the ML part in just 3 steps:
- Create a pipeline with River and insert the preprocessing steps and model of your choice.
- Configure the
OnlineML
wrapper to fit to your model and insert the client and required data stream ids. - Start the wrapper and let the learning begin.
A StreamPipesFunction is then started, which trains the model for each new event. It also creates an output data stream which will send the prediction of the model back to StreamPipes. This output stream can be seen when creating a new pipeline and can be used like every other data source. So you can use it in a pipeline and save the predictions in a Data Lake. You can also stop and start the training with the method set_learning
. To stop the whole function use the stop
methode and if you want to delete the output stream entirely, you can go to the Pipeline Element Installer
in StreamPipes and uninstall it.
Now let's take a look at some examples. If you want to execute the examples below you have to create an adapter for the Machine Data Simulator
, select the flowrate
sensor and insert the stream id of this stream.
"},{"location":"tutorials/4-using-online-machine-learning-on-a-streampipes-data-stream/#KMeans","title":"KMeans\u00b6","text":""},{"location":"tutorials/4-using-online-machine-learning-on-a-streampipes-data-stream/#HoeffdingTreeRegressor","title":"HoeffdingTreeRegressor\u00b6","text":""},{"location":"tutorials/4-using-online-machine-learning-on-a-streampipes-data-stream/#DecisionTreeClassifier","title":"DecisionTreeClassifier\u00b6","text":""}]}
\ No newline at end of file
diff --git a/docs-python/dev/sitemap.xml b/docs-python/dev/sitemap.xml
index cb7e5ce2a..43c3196a1 100644
--- a/docs-python/dev/sitemap.xml
+++ b/docs-python/dev/sitemap.xml
@@ -2,242 +2,242 @@
https://streampipes.apache.org/docs/docs/python/latest/latest/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/getting-started/developing/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/getting-started/first-steps/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/getting-started/quickstart/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/client/client/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/client/config/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/client/credential_provider/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/endpoint/endpoint/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/endpoint/exceptions/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/endpoint/api/data_lake_measure/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/endpoint/api/data_stream/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/endpoint/api/version/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/function_zoo/river_function/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/functions/function_handler/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/functions/registration/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/functions/streampipes_function/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/functions/broker/broker/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/functions/broker/broker_handler/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/functions/broker/consumer/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/functions/broker/output_collector/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/functions/broker/publisher/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/functions/broker/kafka/kafka_consumer/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/functions/broker/kafka/kafka_message_fetcher/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/functions/broker/kafka/kafka_publisher/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/functions/broker/nats/nats_consumer/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/functions/broker/nats/nats_publisher/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/functions/utils/async_iter_handler/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/functions/utils/data_stream_context/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/functions/utils/data_stream_generator/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/functions/utils/function_context/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/model/common/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/model/container/data_lake_measures/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/model/container/data_streams/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/model/container/resource_container/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/model/container/versions/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/model/resource/data_lake_measure/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/model/resource/data_series/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/model/resource/data_stream/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/model/resource/exceptions/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/model/resource/function_definition/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/model/resource/query_result/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/model/resource/resource/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/reference/model/resource/version/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/scripts/gen_ref_pages/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/tutorials/1-introduction-to-streampipes-python-client/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/tutorials/2-extracting-data-from-the-streampipes-data-lake/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/tutorials/3-getting-live-data-from-the-streampipes-data-stream/
- 2023-10-14
+ 2023-10-21
daily
https://streampipes.apache.org/docs/docs/python/latest/latest/tutorials/4-using-online-machine-learning-on-a-streampipes-data-stream/
- 2023-10-14
+ 2023-10-21
daily
\ No newline at end of file
diff --git a/docs-python/dev/sitemap.xml.gz b/docs-python/dev/sitemap.xml.gz
index 07d180b983bc2c317051ac9a4eee20a73c77895a..6ac121a51d8463ce1553a423440c53af473b38a2 100644
GIT binary patch
literal 704
zcmV;x0zds9iwFoSGBafY|8r?{Wo=<_E_iKh0Nt9+lAACL$M1cLOzw`8Y!7WGo4xf3
z+B4%df_P$VuO(+UefkQ>2i)bG
z>+OTutkrhIr(A54)9k^77Mct%``S2v-sy>D9IL(!_TLY?1tR`$6_UvWwXWd=J|;Fv
zA!=Mk;vOWFg7i|HJr13@5@l#0^TY;iy@Np4Mhs32jceuLWT?4y##brFldB=mpAABt
zqGP(-fgq$e3yJs{ih`g_a=JETDsPTZbzrb$kjOVG3M0EDb@QicO0fOZs(!?%vtzF6
zYLWwocT65g?Iqms?`#=b$7)8J&n8MDWAZu2BS+$;kqRbp#$5n8FUHb|M2m$|p~^<@
z!BUinn98$vco6BnqiK$2+*g95bc)#lqG_ROfUJC{N)Fy&2#1~I(7i*7bY&suQ5!r5
zTRD=M1&oZ78n=&Ef;W;4*+Kv=HljdZ-l{|~j^uHH=R~#ZB-BnJ5dOY?hC&%f
zQGs;qvRJZ(>TVLpcv&kH5b8ZCi}UZ;B)u_uhjzl+Terb?!r?_Hk?7ii9KO|wxhP>yvO?iz}s
znkcIAVm0p%R_?G{#Z_B2cKE=kf553G$4=1!exV+I=@Xav6F;cy_f+1U;BU1|K2
zoefo{9U-!$id5R{=||i7@VWuJ3>ZuwEQ_)K&@ZHHQug-wz4MDBWOOk+EjO$6ask1{
z+J*LM`Tg5h^=bLMyW5uR5op0D2Yg!YiP9IX-`?I<=m-z__S*y(>pK`WMPP2OxT4*x7?rP)wX{#reajg0}*ndCl7Kr%2RY)ci)VhWv_?Xxv
zg{W~EiF=Sx3eszF_AqqjN|d32%o7{5^$r4E8ZkIAG_I9{lcDC;8DFIwkFJJ1e>Mnp
zijL{72ZE5^EhOS+C<=ly$?4jVsk}Kr)q%m1K_cI%D2(i!)Xkr&DZ%zrtNIb6&W^dN
zi%AX~-Y|I}wU=KAR|sjLDZA4;+c-Mk<)Z8FvQcyckO-5-k==g(@4p
z2TM^RVk$4*;a;Ts4yHMnabF3J(kW&Kh^B?A0kZO)Dmi$AAslv+L-z(L(v^jrM{V#F
zY~@I17BDhSYTQ0v3EoLIWD5bf*oXpsd94z~IFiQ&o)guslTbTdXaX6>LHPUn846__
zMFrBa%VNnEs+&n1<9V%6jQ1`+lem2SCqjhmK&bbmEY5#mlk~>u1KKr5siASf$ygNq
z!1!7qpDOMaPvYRN2hzZ1{!R>Sc8QB}u5UQ>nkt!gzIS~pT%b9_HO)r3KsnZBxN9hi
zYNDvdi`Be8Sh>O8E3VqIvBL*O{R2)lId+Qn@C)_uOP{#RpZGytzNhl;2!CUq_v8LX
m{iq7|%rSUQu~o+kee1#GFxr**fAm9xK)atUdr-&$DgXd9FJSxt
From 3d6e331411b3ea11868eec6028ae0c7b006831e8 Mon Sep 17 00:00:00 2001
From: Dominik Riemer
Date: Sun, 22 Oct 2023 22:06:16 +0200
Subject: [PATCH 7/7] Add architecture section (#123)
* Add architecture section
* Add messaging section
* Remove outdated configuration section
---
docs/07_technicals-architecture.md | 122 ++++++++++++------
docs/07_technicals-configuration.md | 74 -----------
docs/07_technicals-messaging.md | 37 +++++-
website-v2/sidebars.json | 5 +-
.../static/img/07_technicals/architecture.png | Bin 0 -> 127397 bytes
.../07_technicals-architecture.md | 122 ++++++++++++------
.../07_technicals-configuration.md | 58 ---------
.../version-0.92.0/07_technicals-messaging.md | 37 +++++-
.../version-0.92.0-sidebars.json | 3 +-
9 files changed, 245 insertions(+), 213 deletions(-)
delete mode 100644 docs/07_technicals-configuration.md
create mode 100644 website-v2/static/img/07_technicals/architecture.png
delete mode 100644 website-v2/versioned_docs/version-0.92.0/07_technicals-configuration.md
diff --git a/docs/07_technicals-architecture.md b/docs/07_technicals-architecture.md
index 916adde1b..e62ba4625 100644
--- a/docs/07_technicals-architecture.md
+++ b/docs/07_technicals-architecture.md
@@ -4,59 +4,107 @@ title: Architecture
sidebar_label: Architecture
---
+## Architecture
-The following picture illustrates the high-level architecture of StreamPipes:
+
-
+Apache StreamPipes implements a microservice architecture as shown in the figure above.
-Users mainly interact (besides other UI components) with the _Pipeline Editor_ to create stream processing pipelines based on data streams, data processors and data sinks.
-These reusable pipeline elements are provided by self-contained _pipeline element containers_, each of them having a semantic description that specifies their characteristics (e.g., input, output and required user input for data processors).
-Each pipeline element container has a REST endpoint that provides these characteristics as a JSON-LD document.
+## StreamPipes Core
-Pipeline element containers are built using one of several provided _wrappers_.
-Wrappers abstract from the underlying runtime stream processing framework.
-Currently, the StreamPipes framework provides wrappers for Apache Flink, Esper and algorithms running directly on the JVM.
+The StreamPipes Core is the central component to manage all StreamPipes resources.
+It delegates the management of adapters, pipeline elements, pipelines and functions to registered extensions services (see below) and monitors the execution of extensions.
+The Core also provides internal REST interfaces to communicate with the user interface, as well as public REST interfaces that can be used by external applications and StreamPipes clients.
-The _pipeline manager_ manages the definition and execution of pipelines.
-When creating pipelines, the manager continuously matches the pipeline against its semantic description and provides user guidance in form of recommendations.
-Once a pipeline is started, the pipeline manager invokes the corresponding pipeline element containers.
-The container prepares the actual execution logic and submits the program to the underlying execution engine, e.g., the program is deployed in the Apache Flink cluster.
+Configuration and user data are stored in an Apache CouchDB database.
-Pipeline elements exchange data using one or more message brokers and protocols (e.g., Kafka or MQTT).
-StreamPipes does not rely on a specific broker or message format, but negotiates suitable brokers based on the capabilities of connected pipeline elements.
+## StreamPipes Extensions
-Thus, StreamPipes provides a higher-level abstraction of existing stream processing technology by leveraging domain experts to create streaming analytics pipelines in a self-service manner.
+An Apache StreamPipes extensions service is a microservice which contains the implementation of specific adapters, data streams, data processors, data sinks and functions.
+Multiple extension services can be part of a single StreamPipes installation.
+Each service might provide its own set of extensions. Extensions services register at the StreamPipes Core at startup. Users are able to install all or a subset of extensions of each service.
+This allows StreamPipes to be extended at runtime by starting a new service with additional extensions.
-## Semantic description
-Pipeline elements in StreamPipes are meant to be reusable:
+Extensions can be built using the SDK (see [Extending StreamPipes](06_extend-setup.md)).
+Extensions services can be provided either in Java or in Python.
-* Data processors and data sink are generic (or domain-specific) elements that express their requirements and are able to operate on any stream that satisfies these requirements.
-* Data processors and data sinks can be manually configured by offering possible configuration parameters which users can individually define when creating pipelines.
-* Data streams can be connected to any data processor or data sink that matches the capabilities of the stream.
+:::info
-When users create pipelines by connecting a data stream with a data processor (or further processors), the pipeline manager _matches_ the input stream of a data processor against its requirements.
-This matching is performed based on the _semantic description of each element.
-The semantic description (technically an RDF graph serialized as JSON-LD) can be best understood by seeing it as an envelope around a pipeline element.
-It only provides metadata information, while we don't rely on any RDF at runtime for exchanging events between pipeline elements.
-While RDF-based metadata ensures good understanding of stream capabilities, lightweight event formats at runtime (such as JSON or Thrift) ensure fast processing of events.
+As of version 0.93.0, the Python SDK supports functions only. If you would like to develop pipeline elements in Python as well, let us know in a [Github discussions](https://github.com/apache/streampipes/discussions) comment, so that we can better prioritize development.
-Let's look at an example stream that produces a continuous stream of vehicle positions as illustrated below:
+:::
-
-While the runtime layer produces plain JSON by submitting actual values of the position and the vehicle's plate number, the description layer describes various characteristics of the stream:
-For instance, it defines the event schema (including, besides the data type and the runtime name of each property also a more fine-grained meaning of the property), quality aspects (e.g., the measurement unit of a property or the frequency) and the grounding (e.g., the format used at runtime and the communication protocol used for transmitting events).
+An extensions service interacts with the core by receiving control messages to invoke or detach an extension.
+In addition, the core regularly fetches monitoring and log data from each registered extensions service.
-The same accounts for data processors and data sinks:
-
+## StreamPipes Client
+
+The Apache StreamPipes Client is a lightweight library for Java and Python which can be used to interact with StreamPipes resources programmatically.
+For instance, users use the client to influence the control flow of pipelines, to download raw data from the data lake APIs or to realize custom applications with live data.
+
+
+## Third-party systems
+
+In addition to the core components, an Apache StreamPipes version uses several third-party services, which are part of the standard installation.
+
+* Configurations and user data is stored in an [Apache CouchDB](https://couchdb.apache.org) database.
+* Time-series data is stored in an [InfluxDB](https://github.com/influxdata/influxdb) database.
+* Events are exchanged over a messaging system. Users can choose from various messaging systems that StreamPipes supports. Currently, we support [Apache Kafka](https://kafka.apache.org), [Apache Pulsar](https://pulsar.apache.org), [MQTT](https://mqtt.org/) and [NATS](https://nats.io/). The selection of the right messaging system depends on the use case. See [Messaging](07_technicals-messaging.md) for more information.
+
+:::info
+
+Versions prior to 0.93.0 included Consul for service discovery and registration. Starting from 0.93.0 onwards, we switched to an internal service discovery mechanism.
+
+:::
+
+All mentioned third-party services are part of the default installation and are auto-configured during the installation process.
+
+## Programming Languages
+
+Apache StreamPipes is mainly written in Java.
+Services are based on Spring Boot.
+The included [Python integration](https://streampipes.apache.org/docs/docs/python/latest/) is written in Python.
+
+The user interface is mainly written in TypeScript using the Angular framework.
+
+
+## Data Model
+
+Internally, Apache StreamPipes realizes a stream processing layer where events are continuously exchanged over a messaging system.
+When building a pipeline, data processors consume data from a topic assigned by the core and publish data back to another topic, which is also assigned by the core.
+
+At runtime, events have a flat and easily understandable data structure, consisting of key/value pairs. Events are serialized in JSON, although StreamPipes can be configured to use other (binary) message formats.
+
+This allows for easy integration with other systems which want to consume data from Streampipes, since an event could look as simple as this:
+
+```json
+{
+ "timestamp": 1234556,
+ "deviceId": "ABC",
+ "temperature": 37.5
+}
+```
+
+However, this wouldn't be very expressive, right? To [assist users](07_technicals-user-guidance.md), StreamPipes provides a rich description layer for events. So under the hood, for the `temperature` field shown above StreamPipes can also store the following:
+
+```json
+{
+ "label": "Temperature",
+ "description": "Measures the temperature during leakage tests",
+ "measurementUnit": "https://qudt.org/vocab/unit/DEG_C",
+ "runtimeName": "temperature",
+ "runtimeType": "xsd:float",
+ "semanticType": "https://my-company-vocabulary/leakage-test-temperature"
+}
+```
+
+By dividing the description layer from the runtime representation, we get a good trade-off between expressivity, readability for humans and lightweight runtime message formats.
+The schema is stored in an internal schema registry and available to the client APIs and user interface views to improve validation and user guidance.
+
+StreamPipes also supports arrays and nested structures, although we recommend using flat events where possible to ease integration with downstream systems (such as time-series storage).
-Data processors (and, with some differences, data sinks) are annotated by providing metadata information on their required input and output.
-For instance, we can define minimum schema requirements (such as geospatial coordinates that need to be provided by any stream that is connected to a processor), but also required (minimum or maximum) quality levels and supported transport protocols and formats.
-In addition, required configuration parameters users can define during the pipeline definition process are provided by the semantic description.
-Once new pipeline elements are imported into StreamPipes, we store all information provided by the description layer in a central repository and use this information to guide useres through the pipeline definition process.
-Don't worry - you will never be required to model RDF by yourself.
-Our SDK provides convenience methods that help creating the description automatically.
diff --git a/docs/07_technicals-configuration.md b/docs/07_technicals-configuration.md
deleted file mode 100644
index cc343831e..000000000
--- a/docs/07_technicals-configuration.md
+++ /dev/null
@@ -1,74 +0,0 @@
----
-id: technicals-configuration
-title: Configuration
-sidebar_label: Configuration
----
-
-On this page we explain how the StreamPipes configuration works.
-StreamPipes allows the individual services (pipeline element containers and third-party services) to store configuration
-parameters in a distributed key-value store.
-This has the advantage that individual services do not need to store any configurations on the local file system,
-enabling us to run containers anywhere.
-As a key-value store we use [Consul](https://www.consul.io/), which is an essential service for all our services.
-
-
-
-## Edit Configurations
-
-All services in StreamPipes can have configuration parameters.
-You can either change them in the consul user interface (which is by default running on port 8500) or directly in the
-StreamPipes Configurations Page.
-Once a new pipeline element container is started, it is registered in Consul and the parameters can be edited in the
-configuration page, as shown below.
-To store changes in Consul, the update button must be clicked.
-
-
-
-
-
-## Configuration for Developers
-
-We provide a Configurations API for the use of configuration parameters in your services.
-Each processing element project has a “config”
-package [[Example]](https://github.com/apache/streampipes-extensions/tree/dev/streampipes-sinks-internal-jvm/src/main/java/org/streampipes/sinks/internal/jvm/config).
-This package usually contains two classes.
-One containing unique keys for the configuration values and one containing the getter and setter methods to access these
-values.
-For the naming of configuration keys, we recommend to use “SP” as a prefix.
-As we explain later, it is possible to set default configurations as environment variables, this prefix makes them
-unique on your server.
-A configuration entry needs a unique config key. For this key, a value can be specified containing the configuration,
-like for example the port number of the service.
-For each configuration, a description explaining the parameter can be provided, further the data type must be specified
-and whether it is a password or not.
-Below, the schema of a configuration item is shown on the left and an example of a port configuration on the right.
-
-
-
-As a developer, you can add as many new configurations to services as you wish, but there are some that are required for
-all processing element containers.
-Those are **the host**, **the port**, and **the name** of the service.
-
-## Default Values
-
-You can provide default values for the configurations, which are used when a configuration is read for the first time.
-The first option is to register a configuration parameter in the Config class.
-This is a fallback value, which is used if nothing else is defined.
-Since this value is static, we offer a second option.
-It is possible to provide a default value by setting an environment variable.
-In this case, the convention is that the key of a configuration parameter must be used as the environment variable.
-Now, this value is used instead of the value defined in the Config class.
-During development, the configuration values often need to be changed for debugging purposes, therefore we provide an
-.env file in all processing element projects and archetypes.
-This file can be used by your IDE to set the environment variables. (
-e.g., [Intellij Plugin](https://plugins.jetbrains.com/plugin/7861-envfile))
-When you need to change the variable at runtime, you can do this in the StreamPipes configurations as explained before.
-Those changes take effect immediately without the need of a container restart.
-
-:::caution Installed pipeline elements
-
-Be cautious, when the configuration is used in the semantic description of a processing element which is already
-installed in StreamPipes, you have to reload this element in StreamPipes (my elements -> reload).
-In addition, changes might affect already running pipelines.
-
-:::
diff --git a/docs/07_technicals-messaging.md b/docs/07_technicals-messaging.md
index e944745fe..9ce44b9f4 100644
--- a/docs/07_technicals-messaging.md
+++ b/docs/07_technicals-messaging.md
@@ -4,4 +4,39 @@ title: Messaging
sidebar_label: Messaging
---
-tbd
\ No newline at end of file
+## Architecture
+
+To exchange messages at runtime between individual [Extensions Services](07_technicals-architecture.md), StreamPipes uses external messaging systems.
+This corresponds to an event-driven architecture with a central message broker and decoupled services which consume and produce events from the messaging system.
+
+There are many different open source messaging systems on the market, which each have individual strengths.
+To provide a flexible system which matches different needs, StreamPipes can be configured to use various messaging systems.
+
+## Supported messaging systems
+
+The following messaging systems are currently supported:
+
+* Apache Kafka
+* Apache Pulsar
+* MQTT
+* NATS
+
+## Configure StreamPipes to use another messaging system
+
+Configuring StreamPipes for one of these messaging system is an installation-time configuration.
+We currently do not recommend to change the configuration at runtime.
+
+The protocol can be configured with the environment variable `SP_PRIORITIZED_PROTOCOL` assigned to the core with one of the following values:
+
+```bash
+SP_PRIORITIZED_PROTOCOL=kafka # Use Kafka as protocol
+SP_PRIORITIZED_PROTOCOL=pulsar # Use Pulsar as protocol
+SP_PRIORITIZED_PROTOCOL=mqtt # Use MQTT as protocol
+SP_PRIORITIZED_PROTOCOL=nats # Use NATS as protocol
+```
+
+Note that each extension service can support an arbitrary number of protocols. For instance, you can have a lightweight extension service which only supports NATS, but have another, cloud-centered service which supports Kafka, both registered at the Core.
+To select a protocol when multiple protocols are supported by two pipeline elements, StreamPipes selects a protocol based on a priority, which can be configured in the [Configuration View](03_use-configurations.md).
+StreamPipes ensures that only pipeline elements which have a commonly supported protocol can be connected.
+
+Note that you might need to change the installation files. For the `Docker-Compose` based installation, we provide various compose file for different messaging setups. For the `Kubernetes` installation, we provide variables which can be set in the helm chart's `values.yaml` file.
diff --git a/website-v2/sidebars.json b/website-v2/sidebars.json
index 55e46f5dc..c193904b5 100644
--- a/website-v2/sidebars.json
+++ b/website-v2/sidebars.json
@@ -179,8 +179,7 @@
"technicals-architecture",
"technicals-user-guidance",
"technicals-runtime-wrappers",
- "technicals-messaging",
- "technicals-configuration"
+ "technicals-messaging"
],
"👪 Community": [
"community-get-help",
@@ -192,4 +191,4 @@
"faq-common-problems"
]
}
-}
\ No newline at end of file
+}
diff --git a/website-v2/static/img/07_technicals/architecture.png b/website-v2/static/img/07_technicals/architecture.png
new file mode 100644
index 0000000000000000000000000000000000000000..1c8cc709ad2de121147771cdd6dbb03d785cdb31
GIT binary patch
literal 127397
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