Built-in actions

Overview

With Apama EPL, it is possible to utilize functions, called “actions”. Every monitor will have at least one action - the onload action. This section covers the already built-in actions ready to use.

See also the API Reference for EPL (ApamaDoc) for actions on the built-in types.

Querying Cumulocity IoT data

To interact with your historical data, you can use one of the following request-response event pairs to look up resources.

Example: To look up alarms, you can send a FindAlarm request event with appropriate query parameters to the FindAlarm.SEND_CHANNEL channel. In response, you can expect 0 or more FindAlarmResponse events (depending on the number of resources that match the lookup request) and a FindAlarmResponseAck event on the FindAlarmResponse.SUBSCRIBE_CHANNEL channel. Similar functionality is also provided for looking up managed objects, events, measurements and operations.

To look up Request-Response Events Example
ManagedObject FindManagedObject
FindManagedObjectResponse
FindManagedObjectResponseAck
Example
Alarm FindAlarm
FindAlarmResponse
FindAlarmResponseAck
Example
Event FindEvent
FindEventResponse
FindEventResponseAck
Example
Measurement FindMeasurement
FindMeasurementResponse
FindMeasurementResponseAck
Example
Operation FindOperation
FindOperationResponse
FindOperationResponseAck
Example
CurrentUser CurrentUser
GetCurrentUser
GetCurrentUserResponse
Example
TenantOption TenantOption
FindTenantOptions
FindTenantOptionsResponse
Documentation

Invoking other parts of the Cumulocity IoT REST API

The Cumulocity IoT REST API covers some extra functionality which is not covered with the individual event types. To invoke any other part of the REST API, a generic request-response API is provided which you can use to invoke any part of the Cumulocity IoT API.

You can use the following request-response events:

Info: The Apama-ctrl microservice, and thus all EPL apps code within it, runs with a number of permissions which permit the EPL to access all objects in the inventory and also read user details.
This includes personal identifiable information, such as username, email address, and so on.

For more information, see REST implementation and Invoking other parts of the Cumulocity IoT REST API in the Apama documentation.

Invoking HTTP services

To interact with HTTP services using REST and JSON, create an HttpTransport instance using one of the factory methods:

On the HttpTransport object, call one of the create methods, passing a path and payload as needed, to produce a Request object.

On the Request object, you may set cookies, headers or query parameters as needed, and can then invoke the request with the execute(action<Response> callback). Supply the name of an action in your monitor for the callback, and it will be invoked with the Response when the request has completed (or timed out).

In the callback, the Response object is supplied with statusCode and payload. Fields on the payload are accessible via the AnyExtractor object it is supplied in - see the information on access fragments below.

Refer to the API Reference for EPL (ApamaDoc) for further details.

Utility functions

Access fragments

You can access fragments via the params dictionary of most events. The AnyExtractor object can be constructed to help you extract data from any objects containing multiple subfragments and access:

You can use a JSON path to navigate in the object structure. For example:

string s := AnyExtractor(measurement.params["fragment"]).getString("sub.fragment.object");

Example “fragment”: “c8y_TemperatureMeasurement”.
Example “sub.fragment.object”: “c8y_TemperatureMeasurement.T.Unit”.

Casting “any” values

Alternatively, use a cast to convert an any to a particular type:

string s := <string> measurement.params["strfragment"];

Note that a cast operation will throw if the object is of a different type.

currentTime and the TimeFormatter

The read-only variable currentTime can be used to obtain the current server time. Apama deals with time using seconds since the Unix Epoch (1 Jan 1970 UTC). You can easily transform it to a human-readable form using the TimeFormat object. The TimeFormat object can be used for formatting dates and times, and also for parsing them.

Example:

using com.apama.correlator.timeformat.TimeFormat;

monitor Example {
    action onload {
        log TimeFormat.format(currentTime, "yyyy.MM.dd 'at' HH:mm:ss") at INFO;
    }
}

For more information on TimeFormat and its functions, see Using the TimeFormat Event Library in the Apama documentation and the API Reference for EPL (ApamaDoc).

inMaintenanceMode

The Util.inMaintenanceMode() function is a fast way to check if the device is currently in maintenance mode. It takes a managed object as a parameter and returns a boolean which is true if the device is in maintenance mode.

Example:

using com.apama.cumulocity.Measurement;
using com.apama.cumulocity.Event;
using com.apama.cumulocity.FindManagedObject;
using com.apama.cumulocity.FindManagedObjectResponse;
using com.apama.cumulocity.FindManagedObjectResponseAck;

using com.apama.cumulocity.Util;

monitor ExampleMonitor {
  action onload() {
    // Subscribe to Measurement.SUBSCRIBE_CHANNEL to receive all measurements
    monitor.subscribe(Measurement.SUBSCRIBE_CHANNEL);
    monitor.subscribe(FindManagedObjectResponse.SUBSCRIBE_CHANNEL);
    on all Measurement() as m {
      integer reqId := integer.getUnique();
      send FindManagedObject(reqId, m.source, new dictionary<string,string>) to FindManagedObject.SEND_CHANNEL;
      on FindManagedObjectResponse(reqId = reqId, id = m.source) as d and not FindManagedObjectResponseAck(reqId = reqId) {
        if not Util.inMaintenanceMode(d.managedObject) {
          send Event("", "c8y_Event", m.source, currentTime, "Received measurement from active device", new dictionary<string,any>) to Event.SEND_CHANNEL;
        }
      }
    }
  }
}

replacePlaceholders

To build strings, you can use concatenation as follows:

string s:= "An event with the text " + evt.text + " has been created.";

If the texts get longer and have more values that are dynamically set from the data, you can use the Util.replacePlaceholders() function. In your text string, you mark the placeholders with the field name from the event and surround it by #{}. The second parameter to replacePlaceholders can be any event type.

myMailText := Util.replacePlaceholders("The device #{source} with the serial number #{c8y_Hardware.serialNumber} created an event with the text #{text} at #{time}. The device is located at #{c8y_Address.street} in #{c8y_Address.city}.", evt);