Using the Time Series Client Library

Using the Time Series Client Library

The Time Series service provides a REST-based API that you can access programatically using Java.

About This Task

In addition to a RESTful API that can be accessed using any language, the Time Series service provides a Java-based client library interface to the service. Use this library to help save time with configuring the WebSocket and HTTP connections, for example.

To use the Time Series client library, you should have a basic understanding of how to develop Java applications. You can use the Time Series client library to make calls to the Time Series API.

Note: This is a beta version of the Time Series client library. If you have questions or comments about the Time Series client library, post them on the Predix Forum at http://www.predix.io/community/forum.
This version of the Time Series client library supports filtering, as well as the following aggregators:
  • Average
  • Interpolation
  • Scale

To use the client library, complete the tasks in tss-setup-configure.html#reference_7ed111be-2b84-42c8-b8de-5d2a4f9bb799, then complete the following steps:

Procedure

  1. Include the Time Series client in your application project. See tss-using-client-lib.html#task_41133ec4-df51-4aed-98c6-6f054ac536cd.
  2. Download the Time Series library from https://artifactory.predix.io/artifactory/PREDIX-EXT/.
    Note: You must have a Predix account to access the download site.
  3. Configure the Time Series library. See tss-using-client-lib.html#task_0e6b07ab-888f-4672-be7b-b6b29119833f.
  4. Build the ingestion request. See tss-using-client-lib.html#task_2eced21d-df87-447e-b7ae-9f9cecf8979e.
  5. Build the query request. See tss-using-client-lib.html#task_0e4b86b0-5181-4d84-b566-462a6130821b.

Including the Time Series Client in Your Project

The Time Series client must be included in your project.

Procedure

  1. Update your Maven settings to use the Predix platform Artifactory by copying the following into the <servers> block of your settings.xml file, located in your ~/.m2 folder:
    <server>
        <id>artifactory.external</id>
        <username><predix-user-name></username>
        <password><predix-password></password>
    </server>
    where <predix-user-name> and <predix-password> are your Predix.io user name and password.
    Optionally, you can encrypt your password instead of using plain text. See Password Encryption.
  2. Add the repository to the POM file located in your project's root directory:
    <repositories>
          <repository>
             <id>artifactory.external</id>
             <name>GE external repository</name>
             <url>https://artifactory.predix.io/artifactory/PREDIX-EXT</url>
          </repository>
    </repositories>
  3. Add the Time Series client as a dependency in your POM file:
    <dependency>
        <groupId>com.ge.predix.timeseries</groupId>
        <artifactId>timeseries-client</artifactId>
        <version>0.0.2-SNAPSHOT</version>
    </dependency>
    

Configuring the Time Series Client Library

About This Task

The application bound to your Time Series service contains environmental variables needed to configure the application with the Time Series client library using the predix-timeseries.properties file.

Procedure

  1. Provide the configuration information to use the Time Series client library.
    1. Bind your application to your Time Series service instance (tss-setup-configure.html#task_fac802b9-5075-41dd-bd90-2a5bc261f998).
    2. To retrieve the values needed to configure the Time Series client library, enter the following command at the Cloud Foundry CLI:
      cf env <application_name>
      The environment variables for your application (including the ingestion and query URLs) are returned to you. Make note of the environment variables.
    3. Create a file called predix-timeseries.properties and add the configuration information retrieved in the previous step.
      Note: The predix-timeseries.properties file is required to use the Time Series client library. However, if you are using the createTenantContextFromProvidedProperties method (shown in Step 2), the URIs, client id, and secrets properties in the "Execution properties" section are not used.
      # Predix Timeseries configuration. >>>>>
      # DO NOT MODIFY WITHOUT CONSULTING PREDIX SUPPORT
      predix.timeseries.maxTagsPerQuery=5
      predix.timeseries.maxIngestionMessageSize=512000
      # Predix Timeseries configuration. <<<<<
      
      #Purchased Plan restrictions. >>>>>
      # MODIFY TO SUIT YOUR PLAN. GOING OVER MIGHT RESULT IN ADDED CHARGES
      plan.ingestion.concurrent.connections.max=100
      plan.query.concurrent.connections.max=100
      #Purchased Plan restrictions. <<<<<
      
      #Execution properties. >>>>>
      # MODIFY AS APPROPRIATE
      
      #Execution properties. <<<<<
      
      uaa.uri=<your uaa uri. (without the /oauth/token)>
      ingestion.uri=<ingestion uri obtained from the binding to Predix time-series>
      ingestion.zone-http-header-name=Predix-Zone-Id
      ingestion.client.id=<the client id that has scope access to 'timeseries.zones.<your zone id>.ingest'>
      ingestion.client.secret.env.variable=<environment variable that contains the ingestion client secret>
      query.uri=<query uri obtained from the binding to Predix time-series>
      query.zone-http-header-name=Predix-Zone-Id
      query.client.id=<client id that has scope access to 'timeseries.zones.<your zone id>.query'>
      query.client.secret.env.variable=<environment variable that contains the query client secret>
      
      Note: The client secret is an environment variable that you set on your local machine, which contains a password that you set. Add the name of the environment variable you created as the client secret. If you have two different client IDs (one for ingestion, one for querying), create two different environment variables with two different passwords.
    4. Save the predix-timeseries.properties file and add it to your project.
    5. To provide the path to the predix-timeseries.properties file, add the following line to your code:
      TenantContext tenant=TenantContextFactory.createTenantContextFromPropertiesFile<propertiesPath>;
  2. If you already have the Time Series URLs and authorization tokens available in your code, you can directly provide the configuration information programatically.
    To use both the ingestion and query client, add the following code:
    TenantContext tenant=TenantContextFactory.createTenantContextFromProvidedProperties<queryUri, queryAccessToken, ingestionUri, ingestionAccessToken, zoneHeaderName, zoneId>
    To use the ingestion client only, add the following code:
    TenantContext tenant = TenantContextFactory.createIngestionTenantContextFromProvidedProperties(ingestionUrl, authToken, predixZoneIdHeaderName, predixZoneIdHeaderValue);
    To use the query client only, add the following code:
    TenantContext tenant = TenantContextFactory.createQueryTenantContextFromProvidedProperties(queryUrl, authToken, predixZoneIdHeaderName, predixZoneIdHeaderValue);
    

Creating an Ingestion Request Using the Time Series Client Library

Learn how to create a time series data ingestion request using the example in this topic.

About This Task

The client library offers an Ingestion Request Builder that interfaces with the Time Series service and handles the WebSocket connection. The library uses a builder, which allows flexibility in adding whatever values you would like to the Ingestion Request.

The following shows an example data ingestion request using one good, one bad, and one uncertain data point. These values are derived from an active data source, such as a sensor.

Integer sensorValueAsInt = (int) Math.random();
Double sensorValueAsDouble = Math.random();
IngestionRequestBuilder ingestionBuilder = IngestionRequestBuilder.createIngestionRequest()
        .withMessageId("<MessageID>")
        .addIngestionTag(IngestionTag.Builder.createIngestionTag()
                .withTagName("TagName")
                .addDataPoints(
                        Arrays.asList(
                                new DataPoint(new Date().getTime(), sensorValueAsInt, Quality.GOOD),
                                new DataPoint(new Date().getTime(), sensorValueAsDouble, Quality.NOT_APPLICABLE),
                                new DataPoint(new Date().getTime(), "Bad Value", Quality.BAD),
                                new DataPoint(new Date().getTime(), null, Quality.UNCERTAIN)
                        )
                )
                .addAttribute("AttributeKey", "AttributeValue")
                .addAttribute("AttributeKey2", "AttributeValue2")
                .build());

String json = ingestionBuilder.build().get(0);
IngestionResponse response = ClientFactory.ingestionClientForTenant(ingestionTenant).ingest(json);
String responseStr = response.getMessageId() + response.getStatusCode();
Note: The Time Series service now accepts compressed (GZIP) JSON payloads. The size limit for the actual JSON payload is 512 KB regardless of the ingestion request format. For compressed payloads, this means that the decompressed payload cannot exceed 512 KB.

Creating a Query Using the Time Series Client Library

The client library also offers a Query Builder that interfaces with the Time Series service and return a QueryResponse object.

About This Task

The Query Response can then be accessed either programmatically, or converted to a JSON string. The library again uses a builder, which allows flexibility in adding whatever values and filters are needed in the Query Request.

Procedure

Create a data query request.
The following shows an example data query request using numerous filters.
QueryBuilder builder = QueryBuilder.createQuery()
        .withStartAbs(1427463525000L)
        .withEndAbs(1427483525000L)
        .addTags(
                QueryTag.Builder.createQueryTag()
                        .withTagNames(Arrays.asList("ALT_SENSOR", "TEMP_SENSOR"))
                        .withLimit(1000)
                        .addAggregation(Aggregation.Builder.averageWithInterval(1, TimeUnit.HOURS))
                        .addFilters(FilterBuilder.getInstance()
                                .addAttributeFilter("host", Arrays.asList("<host>")).build())
                        .addFilters(FilterBuilder.getInstance()
                                .addAttributeFilter("type", Arrays.asList("<type>")).build())
                        .addFilters(FilterBuilder.getInstance()
                                .addMeasurementFilter(FilterBuilder.Condition.GREATER_THAN_OR_EQUALS, Arrays.asList("23.1")).build())
                        .addFilters(FilterBuilder.getInstance()
                                .withQualitiesFilter(Arrays.asList(Quality.BAD, Quality.GOOD)).build())
                        .build());
QueryResponse response = ClientFactory.queryClientForTenant(tenant).queryAll(builder.build());