IoT Edge Services Developer Guide
SAP Dynamic Edge Processing
IoT Edge Services – Developer Guide
Version 2.0 FP02
[Type here]
IOT EDGE SERVICES – DEVELOPER GUIDE
Public
TABLE OF CONTENTS
PLUGIN DEVELOPMENT ............................................................................................................................ 3
Introduction to Plugins for IoT Edge Services ......................................................................................... 3
Protocol Plugins ............................................................................................................................................ 3
Enterprise Plugins ......................................................................................................................................... 3
Engine Plugins .............................................................................................................................................. 3
Writing a Custom Plugin (Java) ................................................................................................................. 3
IProtocolPlugin Interface ............................................................................................................................... 4
IProtocolAdapter Interface ............................................................................................................................ 5
IEnterprisePlugin Interface ............................................................................................................................ 7
IEnginePlugin Interface ............................................................................................................................... 10
Supporting Whitelisting with a Custom Enterprise Plugin ................................................................... 12
WhitelistClient Interface .............................................................................................................................. 12
Whitelist Constructor Properties Object Configuration ............................................................................... 14
Configuring a Custom Plugin .................................................................................................................. 16
Location of Custom Plugin JAR .................................................................................................................. 16
Registering and Configuring a Custom Protocol Plugin .............................................................................. 16
Registering and Configuring a Custom Enterprise Plugin .......................................................................... 16
Registering and Configuring a Custom Engine Plugin ................................................................................ 16
EXTERNAL CUSTOM RULE - CUSTOM CCL PROJECT DEVELOPMENT ........................................... 17
Input Schema ............................................................................................................................................. 17
Output Schema .......................................................................................................................................... 17
Input Schema Details ................................................................................................................................ 18
Debugging.................................................................................................................................................. 18
Compiling the CCL into a CCX File ......................................................................................................... 18
Start the Custom Project – Linux Only ................................................................................................... 18
Starting the Custom Project with User Authentication – Linux Only .................................................. 18
Start the Custom Project – Windows Only ............................................................................................. 18
APPENDIX .................................................................................................................................................. 20
Custom CCL Sample Template ................................................................................................................ 20
2
IOT EDGE SERVICES – DEVELOPER GUIDE
Public
PLUGIN DEVELOPMENT
Introduction to Plugins for IoT Edge Services
IoT edge services has been designed to be extensible. Plugins can be written in the form of Java classes
conforming to a particular interface. This allows support for a multitude of IoT devices and enterprise
destinations. There are three types of plugins that can be written by developers: protocol plugins,
enterprise plugins, and engine plugins.
Protocol Plugins
Protocol plugins are the entry point for data ingestion into IoT edge services. They are used to
listen for and receive messages from other aggregation systems (for example, SAP Plant
Connectivity) or from messages sent from smart devices. Protocol plugins format the received
data into an Object representing the sensor’s value or state, and send it to the IoT edge
services IIoTAdapter. As such, custom protocol plugins can be written to support any type of
desired protocol in order to get data into IoT edge services.
Protocol plugins must also support receiving messages from the IoT edge services
IIoTAdapter. However, the plugin does not necessarily need to do anything with the message.
For example, message output is not supported via the REST portion of the provided
HttpProtocolPlugin. Messages are sent from the IIoTAdapter to the plugin if a field message is
generated as an action in response to an event. The plugin can make use of the received data as
it sees fit.
Security Notes
A custom protocol plugin is responsible for implementation of authentication and authorization of
the inbound messages. This implementation will be dependent on the protocol support and also
the level of desired security in the solution.
Enterprise Plugins
Enterprise plugins are output end points for IoT edge services. If a rule is configured to send to an
enterprise plugin, then every time an event or fidelity reading is generated by the rule, it is
forwarded to the configured enterprise plugin(s). Enterprise plugins are a flexible way of using IoT
edge services because the received information can be used in any way the developer wishes.
Engine Plugins
Custom engine plugins are used to add custom processing logic that is outside the scope of the
existing IoT edge services streaming rules engine. IoT edge services ships with a single engine
plugin (Streaming Lite Plugin) that processes the incoming messages from the protocol plugins
and runs the rules configured by an administrator in the Edge Console.
Writing a Custom Plugin (Java)
To implement a plugin, a number of interfaces must be satisfied. The IPlugin interface outlines
methods common to all types of plugins. The IProtocolPlugin interface outlines methods for protocol
plugins, while the IEnterprisePlugin interface outlines methods for enterprise plugins. Both of these
interfaces extend the IPlugin interface, so both protocol plugins and enterprise plugins must implement
these methods. Protocol plugins must implement the IProtocolPlugin interface and all of its methods
and enterprise plugins must implement the IEnterprisePlugin interface and all of its methods.
These interfaces as well as all other com.sap.dep.* classes referenced in this guide are located in the
DEPPluginClient JAR file located in <dep_install_directory>/java_lib. In addition, this JAR
contains the com.sap.dep.logging.LogManager class through which you can get access to a
com.sap.dep.logging.ILogger logger instance for your plugin via the
getLogger(Class component) method. If a logger is retrieved by a plugin, the logger will write to a
file in <dep_install_directory>/log/ named <YourPluginClassName>.log. If any other class
retrieves a logger, the logger will write to <dep_install_directory>/log/IoTAdapter.log.
3
IOT EDGE SERVICES – DEVELOPER GUIDE
Public
IPlugin Interface
/**
* Signals to the plug-in that it should clean up resources and
* shutdown
*/
public void stopPlugin();
/**
* Allows the IIoTAdapter to periodically verify that the plug-in has
* the active connections it requires.
* If false is returned, reconnectRequest will be
* called.
*/
boolean isConnected();
/**
* Called by the IIoTAdapter after isConnected returns {@code
* false}.
*/
void reconnectRequest();
/**
* Allows the IIoTAdapter to notify the plug-in of a change to the
* plug-ins log level.
*/
void changeLogLevel(ILogger.Level level);
The stopPlugin method, defined as part of the IPlugin interface, is called by the
IIoTAdapter before IoT edge services is shut down. This method has no parameters. An
implementation of this method should close any closeable objects the plugin is using and do any
necessary cleanup.
The isConnected method is defined in order for the plugin to report its connection status in the
form of a boolean to the IIoTAdapter. This method has no parameters. An implementation of
this method should return false if the plugin requires a reconnection attempt. Otherwise, true
should be returned. If false is returned, reconnectRequest is called.
The counterpart to isConnected is reconnectRequest which is called when isConnected
returns false. This method has no parameters. The implementation of this method should
ensure that the plugin is in a valid state for interactions with smart devices and/or the
IIoTAdapter.
Lastly, a changeLogLevel method is defined. An implementation of this method should switch
the logging level to the given ILogger.Level enum argument. Following is an example of
where logger is an ILogger object that handles logging for the plugin and level is the passed
ILogger.Level.
logger.setLevel(level);
IProtocolPlugin Interface
/**
* Starts the plug-in
*
4
IOT EDGE SERVICES – DEVELOPER GUIDE
Public
* @param adapter an IProtocolAdapter which can be used to
*
input messages destined for IEnginePlugins
* @param pluginConfig a Properties instance that holds the
*
mapped configuration for the plug-in
*
* @throws StartupFailureException if the plugin fails to startup
*
properly and cannot recover
*/
void startPlugin(IProtocolAdapter adapter, Properties pluginConfig)
throws StartupFailureException;
/**
* Handles a message being output from one of the IEnginePlugin
* plug-ins to this plug-in
*
* @param message The message being given for the plug-in to handle.
*
Class type is specific to the IEnginePlugin sending the
*
message
*/
void handleEngineMessage(Message message);
The IProtocolPlugin interface defines a startPlugin method with two parameters: an
IProtocolAdapter object used to route messages to the IIoTAdapter, and a Properties
object containing all configuration information stored in the database (see Registering and
Configuring a Custom Protocol Plugin). This method is called from the main thread of the
IIoTAdapter so that any blocking calls should be made on a separate thread. If at any point the
plugin startup fails, a StartupFailureException should be thrown by the method.
Implementation of the startPlugin method should prepare the plugin for use, which may
require making use of the Properties object. The method should also continuously listen for
messages over the desired protocol.
The IProtocolPlugin interface also defines a handleEngineMessage method that takes a
com.sap.dep.client.Message object to be handled by the plugin. The actual subclass for
the message differs for each source IEnginePlugin. For instance, the Streaming Lite Engine
Plugin will send instances of com.sap.dep.client.FieldMessage. The .toString()
method of FieldMessage returns a JSON formatted version of the message.
The handleEngineMessage method will only be called if the plugin is configured with ISFIELD-PLUGIN set to 1 and Field Messages are created that use the plugin. Refer to the
“Configuring a Protocol Plugin” section in the SAP Dynamic Edge Processing IoT edge services Configuration Guide.
IProtocolAdapter Interface
/**
* Passes the provided input message to the configured Engine
* plug-in(s). The input message must first be authenticated and
* authorized custom protocol plugin before calling
* sendMessageToEnginPlugins().
*
* @param message the message to forward on.
*
The plug-in you are attempting to input a message into likely
*
has a format or object it is expecting to receive. Ensure you
5
IOT EDGE SERVICES – DEVELOPER GUIDE
Public
*
are conforming to these expectations.
*
* @param sourcePlugin the IProtocolPlugin object that is sending to
*
its registered destination IEnginePlugin(s)
*
This is done using the canonical name of the Protocol plug-in
*
class sending the message.
*
Example:
*
com.example.plugins.MyExampleProtocolPlugin
* @throws UnsupportedSensorException
* @throws UnsupportedMessageTypeException
*/
void sendMessageToEnginePlugins(Message message, IProtocolPlugin
sourcePlugin) throws UnsupportedMessageTypeException,
UnsupportedSensorException;
The IProtocolAdapter interface defines one method, sendMessageToEnginePlugins
method, which sends the given message com.sap.dep.client.Message to all registered
engine plugins (see Plugin Development) using the sourcePlugin argument to identify the
sending plugin. To input sensor readings to the Streaming Lite Engine Plugin, the message
should be an instance of com.sap.dep.client.InboundMessage populated with the reading
data via the InboundMessage.fromJSON(jsonMessage) method. The required JSON format
can be found in the “Sending Data to a Protocol Plugin” section
of the SAP Dynamic Edge Processing IoT edge services - Configuration Guide.
Security Notes
A custom protocol plugin is responsible for implementation of authentication and authorization of
the inbound messages. This implementation will be dependent on the protocol support and also
the level of desired security in the solution. The custom protocol plugin must perform this
authentication and authorization before calling the sendMessageToEnginePlugins
method.
Whitelist support
If global deviceId whitelisting is enabled (configured by the setting
whitelist.enableInboundWhitelisting), then the deviceId whitelist filtering will be
automatically applied by the IoT edge services after the sendMessageToEnginePlugins
method is called. No further work is required by the custom protocol plugin to leverage the device
id global whitelist filtering.
Following is an example using this method, where protocolAdapter is an
IProtocolAdapter object, message is a com.sap.dep.client.InboundMessage, and
this implements IProtocolPlugin.
protocolAdapter.sendMessageToEnginePlugins(message, this);
In order for Protocol Plugins to be loaded by IoT edge services, the JAR file containing the plugin
classes must have the appropriate service provider interface file in the META-INF directory, as
outlined below. This only applies to protocol plugins.
File Path & Name
File Contents
METAINF/services/com.sap.dep.interfaces.IProtocolPlugin
Canonical Name for the class implementing IProtocolPlugin
6
IOT EDGE SERVICES – DEVELOPER GUIDE
Public
Example:
com.example.protocolplugin.MyPluginClass
IEnterprisePlugin Interface
/**
* Starts the plug-in
*
* @param config A Properties instance that holds mapping of
*
configuration for the plugin
* @param pluginInstanceId The configured Id for this instance of the
*
IEnterprisePlugin
* @throws Exception
*/
void startPlugin(Properties config, String pluginInstanceId)
throws Exception;
/**
*
* @param event
* @throws Exception The plugin must throw an exception if it fails to
*
handle an event and wants it to be put in a retry queue
*/
void handleEnterpriseEvent(EnterpriseEvent event) throws Exception;
/**
*
* @param event
* @throws Exception The plugin must throw an exception if it fails to
*
handle an event and wants it to be put in a retry queue
*/
void handleFidelityEvent(SensorFidelityEvent event) throws Exception;
/**
* @return the pluginInstanceId given to the instance when startPlugin
*
is called
*/
String getPluginInstanceId();
/**
* Gets the WhitelistType that the plugin uses or
* supports. See the values of WhitelistType for
* details of what each type indicates.
*
* The default implementation returns WhitelistType.NONE.
* This means no calls will be made to get the plugin's
* whitelist
*
* @return the WhitelistType that the plugin uses
*
or supports
*/
default WhitelistType getPluginWhitelistType() {
return WhitelistType.NONE;
}
/**
7
IOT EDGE SERVICES – DEVELOPER GUIDE
Public
* Gets the full set of whitelisted devices that the plugin trusts. Any
* existing trusted devices for the plugin will be wiped away.
*
* Only called if getPluginWhitelistType() returns WhitelistType.FULL
*
* The default implementation returns an empty set.
*
* @return a Set of Strings of all of the whitelisted device Ids for
*
the plugin
* @throws WhitelistFetchException thrown if any errors are encountered
*
while attempting to fetch the whitelist
*/
default Set<String> getAllWhitelistDevices() throws
WhitelistFetchException {
return Collections.<String>emptySet();
}
/**
* Gets the set of newly whitelist devices added since
* lastRetrievalTimestamp
*
* Only called if getPluginWhitelistType() returns WhitelistType.DELTA
*
* The default implementation returns an empty srt.
*
* @return a Set of Strings of the newly whitelisted device Ids for
*
the plugin
* @throws WhitelistFetchException thrown if any errors are encountered
*
while attempting to fetch the whitelist.
*
The last retrieval timestamp will not be updated if this is
*
thrown.
*/
default Set<String> getNewWhitelistDevices(Date lastRetrievalTimestamp)
throws WhitelistFetchException {
return Collections.<String>emptySet();
}
/**
* Gets the set of whitelist devices which have been removed since
* lastRetrievalTimestamp
*
* Only called if getPluginWhitelistType()returns WhitelistType.DELTA
*
* The default implementation returns an empty set.
*
* @return a Set of Strings of the de-whitelisted device Ids for the
*
plugin
* @throws WhitelistFetchException thrown if any errors are encountered
*
while attempting to fetch the whitelist.
*
The last retrieval timestamp will not be updated if this is
*
thrown.
*/
default Set<String> getRemovedWhitelistDevices(Date
lastRetrievalTimestamp) throws WhitelistFetchException {
return Collections.<String>emptySet();
}
8
IOT EDGE SERVICES – DEVELOPER GUIDE
Public
Enterprise plugins can be configured to allow multiple simultaneous instances of the plugin with
different configuration properties. An enterprise plugin is meant to route data to a non-IoT edge
services endpoints. For example, a REST endpoint in the cloud or a WebSocket endpoint running
on a local machine. In addition, enterprise endpoints act as the source for device whitelisting
information.
The IEnterprisePlugin interface defines a startPlugin method with a Properties
object as the first parameter that contains all configuration information stored in the database
(see Registering and Configuring a Custom Protocol Plugin). The second parameter,
pluginInstanceId, is a String that is the configured Id for the instance being started. This Id
can also be used to differentiate instances for logging purposes. If at any point the plugin startup
fails, a StartupFailureException should be thrown by the implemented method.
Implementation of this method should prepare the plugin for use, which may require making use
of the Properties object.
Next, the interface defines a handleEnterpriseEvent method which takes a
com.sap.dep.client.EnterpriseEvent object as an argument. This method is called
every time an event is generated by a rule that has this plugin associated to it. Implementation of
this method should make use of the EnterpriseEvent object and perform any follow-up
actions necessary to handle the particular event. An exception can be thrown by this method in
order for the EnterpriseEvent to be put into a re-attempt queue. The get methods listed
below allow access to the event’s data.
/*
* List of EnterpriseEvent object get methods
*/
String getDeviceId();
String getDeviceTag();
String getSensorProfileId();
String getSensorProfileName();
String getSensorId();
String getSensorTag();
String getSourceRuleType();
String getSourceRuleId();
String getSourceRuleName();
String getSensorInformation();
Date getDateCreated();
The final outbound method of the interface is the handleFidelityEvent method that takes a
com.sap.dep.client.SensorFidelityEvent object as an argument. This method is called
every time a sensor fidelity reading is sent to the enterprise plugin, as determined by the sensor’s
fidelity rule settings. An exception can be thrown by this method in order for the
SensorFidelityEvent to be put into a re-attempt queue. The get methods listed below allow
access to the event’s data.
/*
* List of SensorFidelityEvent object get methods
*/
String getDeviceId();
String getDeviceTag();
String getSensorProfileId();
String getSensorProfileName();
String getSensorId();
String getSensorTag();
String getSensorReadingValue();
9
IOT EDGE SERVICES – DEVELOPER GUIDE
Public
String getSourceRuleId();
String getContext();
Date getDateCreated();
The getPluginInstanceId method is used for various purposes, including to check the
whitelist for a specific IEnterprisePlugin instance before sending that instance an event. It
should return the pluginInstanceId value given to the startPlugin method.
For the whitelisting portion of the interface, IEnterprisePlugin defines four methods. The first
method is getPluginWhitelistType, and it is used to determine the whitelist type supported
by the plugin. The IEnterprisePlugin.WhitelistType enumeration defines three values:
NONE, FULL, and DELTA.
The NONE value indicates that the plugin does not support retrieving a whitelist. If this is the case,
none of the three remaining methods will be called.
The FULL value indicates the plugin supports retrieving the full list of currently whitelisted devices.
If this is the case, the getAllWhitelistDevices method will be called when polling for
whitelist data.
Finally, the DELTA value indicates that the plugin supports timestamp-based delta retrieval of both
newly added devices and newly removed devices. If this is the case, first the
getNewWhitelistDevices method will be called with a Date timestamp of the last time an
update was requested and then getRemovedWhitelistDevices will be called with the same
timestamp.
All three of the whitelist retrieval methods (getAllWhitelistDevices,
getNewWhitelistDevices, and getRemovedWhitelistDevices) return Set<String>
containing the corresponding device Ids.
IEnginePlugin Interface
Custom engine plugins can be used to either replace the Streaming Lite engine, the default IoT edge
services rules processing engine, or augment the Streaming Lite engine functionality. If configured to
replace the Streaming Lite engine, the messages are sent to the custom engine plugin instead of the
Streaming Lite engine. If configured to augment the Streaming Lite engine, the messages are sent to the
custom engine plugin, which can perform the custom logic and send additional messages to the
Streaming Lite engine. The custom engine plugin can also optionally trigger events that are processed by
enterprise plugins.
/**
* Starts the plug-in
*
* @param adapter
*
an {@link IEngineAdapter} which can be used to output messages
*
to {@link IProtocolPlugin}s or {@link IEnterprisePlugin}s.
* @param pluginConfig
*
A {@link Properties} instance that holds the mapped
*
configuration for the plug-in
*
* @throws StartupFailureException
*
if the plugin fails to startup properly and cannot recover
*/
void startPlugin(IEngineAdapter adapter, Properties pluginConfig) throws
StartupFailureException;
10
IOT EDGE SERVICES – DEVELOPER GUIDE
Public
/**
* Handles a message being inputted from one of the IProtocolPlugin plug-ins
* to this plug-in
*
* @param message
*
The message being given for the plug-in to handle as it sees
*
fit
* @throws UnsupportedSensorException
* @throws UnsupportedMessageTypeException
*/
void handleInputMessage(Object message) throws
UnsupportedMessageTypeException, UnsupportedSensorException;
The IEnginePlugin interface defines a startPlugin method with two parameters: an
IEngineAdapter object used to route messages to protocol, enterprise, or other engine plugins, and a
Properties object containing all configuration information stored in the database (see Registering and
Configuring a Custom Engine Plugin). This method is called from the main thread of the IIoTAdapter
so that any blocking calls should be made on a separate thread. If at any point the plugin startup fails, a
StartupFailureException should be thrown by the method.
The IEnginePlugin interface also defines a handleInputMessage method which takes a generic
Java Object as an argument. This allows it to receive any type of message from the protocol plugins
however in the current version only com.sap.dep.client.InboundMessage objects will be passed
in. This method is called every time a protocol plugin generates a message destined for this engine
plugin. See Registering and Configuring a Custom Engine Plugin to configure routing protocol plugin
messages to the engine plugin. Implementation of this method should make use of the message object
and perform any custom logic to process the message.
The handleInputMessage can use the IEngineAdapter object passed in the startPlugin method
to:
 Send a message to specific protocol plugin or to all protocol plugins.
 Send an enterprise event to an enterprise plugin.
 Send a sensor fidelity event to an enterprise event.
 Send a message to specific engine plugin or to all engine plugins
In order for Engine Plugins to be loaded by IoT edge services, the JAR file containing the plugin classes
must have the appropriate service provider interface file in the META-INF directory, as outlined below.
File Path & Name
File Contents
METAINF/services/com.sap.dep.interfaces.IEnginePlugin
Canonical Name for the class implementing IEnginePlugin
Example:
com.example.engineplugin.MyPluginClass
A sample implementation of an engine plugin is provided in the samples/plugin/engine/CpkEnginePlugin
directory. Refer to the documentation in the README.md in the CpkEnginePlugin directory for full
description of the plugin.
11
IOT EDGE SERVICES – DEVELOPER GUIDE
Public
Supporting Whitelisting with a Custom Enterprise Plugin
If it is desirable to support whitelisting when creating a custom enterprise plugin, the class
com.sap.dep.whitelist.WhitelistClient provides an implementation that is utilized by
RESTPlugin and WebSocketPlugin for their whitelist support. This class supports making HTTP GET calls
which return JSON in one of the following formats:
1. Arrays
[ "Device1", "Device2", "Device3" ]
2. JSON member with an array value
{ "devices": [ "Device1", "Device2", "Device3" ] }
3. OData JSON
{
"d": {
"results": [
{ "deviceId": "Device1" },
{ "deviceId": "Device2" },
{ "deviceId": "Device3" }
]
}
}
If using formats 2 or 3, the Properties object passed to the constructor should have a value for the key
WHITELIST_JSON_MEMBER_NAME that aligns with the member name in 2 or the object member name in
3. In the provided samples, the values would be "devices" for format 2 and "deviceId" for format 3.
Any extra members in formats 2 or 3 will be ignored.
The public interface for WhitelistClient is outlined below. It is followed by the Whitelist Constructor
Properties Object Configuration table that outlines the configuration values for the Properties object
given to the constructor.
WhitelistClient Interface
/**
* Instantiates an instance of WhitelistClient using the specified
* configuration and logging via the passed logger.
*
* @param config A Properties object containing the configuration for
*
the instance
* @param logger the ILogger which will be used for logging
* @throws AssertionError Only thrown if run on a platform which
*
doesn't support UTF-8 encoding
* @throws IllegalArgumentException thrown if the config object
*
contains invalid configuration data
* @throws StartupFailureException thrown if any exception occurs when
*
starting the HTTP client
*/
public WhitelistClient(final Properties config, ILogger logger)
throws AssertionError, IllegalArgumentException,
StartupFailureException
/**
* Gets the WhitelistType this instance is configured for
* @return the WhitelistType the instance is configured for
*/
12
IOT EDGE SERVICES – DEVELOPER GUIDE
Public
public WhitelistType getWhitelistType()
/**
* Closes the client. Calling {@code close} after the first call
* doesn't do anything.
* Once this has been called, no further calls to
* WhitelistClient.getAllWhitelistDevices(),
* WhitelistClient.getNewWhitelistDevices(Date), or
* WhitelistClient.getRemovedWhitelistDevices(Date) should be made.
* @throws Exception thrown if any exception occurs while closing the
*
client.
*/
public void close() throws Exception
/**
* Implementation for
* IEnterprisePlugin.getAllWhitelistDevices() which will make a GET
* request to the configured endpoint to retrieve the full list of
* whitelist devices
*
* @return A set containing all of the parsed device ids
* @throws WhitelistFetchException thrown if the configured
*
WhitelistType isn't WhitelistType.FULL or any exception occurs
*
while making or processing the request.
*/
public Set<String> getAllWhitelistDevices()
throws WhitelistFetchException
/**
* Implementation for
* IEnterprisePlugin.getNewWhitelistDevices(Date) which will make a GET
* request to the configured endpoint to retrieve the list of whitelist
* devices added since lastRetrievalTimestamp
*
* @return A set containing all of the parsed device ids
* @throws WhitelistFetchException thrown if the configured
* WhitelistType isn't WhitelistType.DELTA or any exception occurs
*
while making or processing the request.
*/
public Set<String> getNewWhitelistDevices(Date lastRetrievalTimestamp)
throws WhitelistFetchException
/**
* Implementation for
* IEnterprisePlugin.getRemovedWhitelistDevices(Date) which will make a
* GET request to the configured endpoint to retrieve the list of
* whitelist devices removed since lastRetrievalTimestamp
*
* @return A set containing all of the parsed device ids
* @throws WhitelistFetchException thrown if the configured
*
WhitelistType isn't WhitelistType.DELTA or any exception occurs
*
while making or processing the request.
*/
public Set<String> getRemovedWhitelistDevices(
Date lastRetrievalTimestamp)
throws WhitelistFetchException
13
IOT EDGE SERVICES – DEVELOPER GUIDE
Whitelist Constructor Properties Object Configuration
Setting Name
Description
<CONFIG_NAME>
WHITELIST_TYPE
Whether the configured endpoint
returns a full list or a delta list. None is
an option, but it doesn’t make sense
to do all the configuration
WHITELIST_URI_ALL_DEVI
Complete URI for obtaining the full list
CES
of whitelisted devices – only called
(required only for WHITELIST when WHITELIST_TYPE = FULL
_TYPE = FULL)
WHITELIST_URI_ADDED_D Complete URI for obtaining the list of
EVICES
newly whitelisted devices – only
(required only for WHITELIST called when WHITELIST_TYPE =
_TYPE = DELTA)
DELTA.
The value should contain the
placeholder
${lastUpdatedTimestamp} which
will be replaced with the last run
timestamp using the format
configured by
WHITELIST_LAST_UPDATED_TIME
STAMP_FORMAT.
WHITELIST_URI_REMOVED Complete URI for obtaining the list of
_DEVICES
devices removed from the whitelist –
(required only for WHITELIST only called when WHITELIST_TYPE
_TYPE = DELTA)
= DELTA.
The value should contain the
placeholder
${lastUpdatedTimestamp} which
will be replaced with the last run
timestamp using the format
configured by
WHITELIST_LAST_UPDATED_TIME
STAMP_FORMAT.
WHITELIST_PROXY_HOST
The host portion of the proxy to use
(optional)
when retrieving the whitelist. A proxy
port must also be provided.
WHITELIST_PROXY_PORT
The port portion of the proxy to use
(optional)
when retrieving the whitelist. A proxy
host must also be provided.
WHITELIST_AUTH_TYPE
The type of authorization to use for
(optional)
requests.
- Basic –
WHITELIST _USERNAME,
WHITELIST _
AUTHENTICATION, and
WHITELIST
_BASIC_AUTH_REALM are
required.
- oAuth –
WHITELIST_OAUTH_TOKE
N is required.
Public
Sample Value
<CONFIG_VALUE>
FULL
DELTA
NONE
https://hana.ondemand.
com/whitelist
https://hana.ondemand.
com/whitelist/added?sin
ce=${lastUpdatedTimes
tamp}
https://hana.ondemand.
com/whitelist/removed?
since=${lastUpdatedTim
estamp}
hana.ondemand.com
80
basic
14
IOT EDGE SERVICES – DEVELOPER GUIDE
WHITELIST_BASIC_AUTH_
REALM
(optional)
WHITELIST_USERNAME
(optional)
WHITELIST_AUTHENTICATI
ON
(optional)
WHITELIST_OAUTH_TOKE
N
(optional)
WHITELIST_KEY_STORE_I
N_SECURE_CONFIG_DIRE
CTORY
(optional)
WHITELIST_KEY_STORE_P
ATH
(optional)
WHITELIST_KEY_STORE_A
UTHENTICATION
(optional)
WHITELIST_TRUST_STORE
_PATH
(optional)
WHITELIST_TRUST_STORE
_AUTHENTICATION
(optional)
WHITELIST_CERT_AUTHEN
TICATION
(optional)
If this setting isn’t configured, no
authentication mechanism is
configured.
The realm to use for BASIC
authentication challenges.
Public
example_realm
The user name to use for BASIC
authentication challenges.
The password to use for BASIC
authentication challenges.
sap_IoT
The bearer token to set as the value
for the authentication header.
Automatically prefixed with “Bearer “.
- True - the plugin prepends the
path of the secure configuration
directory to the configured
KEY_STORE_PATH.
- False - the plugin uses the raw
value of the KEY_STORE_PATH
setting for the path.
The path for the Java keystore. Value
can be the file name or the path,
depending on the value of
WHITELIST_KEY_STORE_IN_SECU
RE_CONFIG_DIRECTORY.
Defaults to SQL Anywhere 17’s
cacerts on x86 Windows and Linux
and the running JRE’s cacerts on
ARM.
The password for the configured
keystore. May optionally be
obfuscated using Jetty.
The path for the Java keystore to use
as the truststore. Value must be the
full path to the file. If not provided, the
configured keystore
(WHITELIST_KEY_STORE_PATH) is
also used as the truststore.
The password for the configured
truststore. May optionally be
obfuscated using Jetty.
The password for the configured
WHITELIST_CERT_ALIAS or best
matching certificate and key in the
keystore. This is the password set
using the -keypass flag when
imported using keytool. If not set,
WHITELIST_KEY_STORE_
AUTHENTICATION is used. As a
result, the keypass must either be the
same or no keypass must be set.
May optionally be obfuscated using
Jetty.
a73b15c7d42f272e6212
c7010b438317ae198b4
a
true
password
RESTEnterprisePlug
in.jks or
<dep_iot_edge>/sto
re/CustomKeyStore.
jks
OBF:1umm1y851z0f1s
w61sox1vno1z0f1vne1s
ot1svs1z0f1y7t1uvk
<dep_iot_edge>/sto
re/CustomTrustStor
e.jks
OBF:1umm1y851z0f1s
w61sox1vno1z0f1vne1s
ot1svs1z0f1y7t1uvk
OBF:1umm1y851z0f1s
w61sox1vno1z0f1vne1s
ot1svs1z0f1y7t1uvk
15
IOT EDGE SERVICES – DEVELOPER GUIDE
WHITELIST_CERT_ALIAS
(optional)
WHITELIST_JSON_MEMBE
R_NAME
(required only if the return
result is format 2 or 3 of the
examples above)
WHITELIST_LAST_UPDATE
D_TIMESTAMP_FORMAT
(required only if TYPE =
DELTA)
Public
Key for selecting which certificate to
use from the keystore. If not provided,
an attempt is made to find the best
matching certificate in the keystore.
Keystores use lowercase aliases;
therefore, this value must also be
lowercase.
The name of the member on the
returned JSON data to pull device Ids
from. See the examples above
whitelistalias
This is the format for the value which
will replace the
${lastUpdatedTimestamp}
placeholder in Delta URIs.
The format string supports the same
functionality as the date format string
for Enterprise Events and Fidelity
Readings sent via RESTPlugin and
WebSocketPlugin. Refer to the SAP
Dynamic Edge Processing IoT edge
services - Configuration Guide for the
supported.
Defaults to ISO8601 format if left
unconfigured.
Y-M-d
deviceId
Configuring a Custom Plugin
Once the java file(s) has/have been written for the custom plugin and a JAR file has been created, it must
be placed in the designated installation subdirectory. Next, the custom plugin must be configured via the
database.
Location of Custom Plugin JAR
The custom JAR file needs to be placed in the <dep_install_directory>/java_lib
directory. This is the directory where IoT edge services will look for plugins to start.
Registering and Configuring a Custom Protocol Plugin
The protocol plugin must be configured for integration with IoT edge services. Refer to the SAP
Dynamic Edge Processing IoT edge services - Configuration Guide.
Registering and Configuring a Custom Enterprise Plugin
The enterprise plugin must be configured for integration with IoT edge services.
Refer to the SAP Dynamic Edge Processing IoT edge services - Configuration Guide.
Registering and Configuring a Custom Engine Plugin
The engine plugin must be configured for integration with IoT edge services.
Refer to the SAP Dynamic Edge Processing IoT edge services - Configuration Guide.
16
IOT EDGE SERVICES – DEVELOPER GUIDE
Public
EXTERNAL CUSTOM RULE - CUSTOM CCL PROJECT DEVELOPMENT
NOTE: This document assumes you are familiar with CCL development. If this is not the case, please
refer to the Smart Data Streaming developer information found at http://help.sap.com/hana_options_sds/
for further information. Streaming Lite does not support the full functionality offered by Smart Data
Streaming.
NOTE: The CCL supported by a Custom CCL project running in IoT edge services is limited to the CCL
support that is standard across Streaming Lite and SAP Event Stream Processor (ESP). In most cases,
the lowest common denominator is the CCL supported by Streaming Lite, but this is not guaranteed. The
only tested and supported adapter is the “ODBC Database” or in CCL “type db_out”. All other ESP
adapters are not supported.
The external custom rule provides the ability define custom processing logic to be used as a rule. The
custom CCL project must satisfy these two requirements to integrate into IoT edge services.
1. The custom CCL project has an Input Stream named isCustomSL with a schema matching the
Input Schema outlined below.
2. The custom CCL project has an Output Stream named osCustomSL with a schema matching the
Output Schema outlined below.
 The RuleId being output needs to match either the Rule ID or Rule Name of the
External Custom Rule configured to use the custom CCL project. It is recommended to
use the Rule Name as it isn’t system generated and can be consistent across
deployments.
Between these streams, the custom CCL can consume the data from isCustomSL and define the logic
required for the custom rule. Once the conditions for the rule have been met, an output to osCustomSL
must be made with all of the input stream data, except Context, and the Rule ID or Rule Name of the
triggered event. The output is consumed by IoT edge services, and IoT edge services performs scoping
and enforces the Max Event Frequency for the rule. If scoping is met and the event hasn’t occurred too
recently, the actions configured for the rule will fire, the event will be sent to the configured enterprise
endpoints, and the event will be saved to the edge database if the rule has been configured to do so.
A basic sample template for a custom CCL project can be found in the appendix.
Input Schema
SCHEMA (
DeviceId string,
DeviceTag string,
SensorId string,
SensorTag string,
SensorProfileId string,
SensorReadingValue string,
Context string,
DateCreated msdate
)
Output Schema
SCHEMA (
DeviceId string,
DeviceTag string,
SensorId string,
SensorTag string,
SensorProfileId string,
SensorReadingValue string,
DateCreated msdate,
RuleId string
)
17
IOT EDGE SERVICES - DEVELOPER
Input Schema Details
The only required and guaranteed non-null fields are DeviceId, SensorProfileId, SensorReadingValue,
and DateCreated. SensorReadingValue can be cast to an integer or a float using the to_integer() or
to_float() CCL functions.
Debugging
To debug using Streaming Lite, make use of the print(string) function and direct the output to a file or
watch the terminal hosting the streamingproject. If the value of the print statement is null or any of the
values being concatenated are null, an empty line will be output. An easy way to get prevent this is to use
firstnonnull(thePossibleNullValue, 'null').
Compiling the CCL into a CCX File
Note: On Windows replace references to $STREAMING_HOME with %STREAMING_HOME%. On Linux
$STREAMING_HOME is the correct format.
Use the streamingcompiler executable in $STREAMING_HOME/bin to compile the CCL file. Replace the
placeholders in the following example with your path and files.
$STREAMING_HOME/bin/streamingcompiler –i <path-to-ccl>/<ccl-file-name>.ccl –o
<output-path>/<compiled-file-name>.ccx
The -i flag is used to specify the input file and the -o flag is used to specify the output file.
Start the Custom Project – Linux Only
Start the project using the streamingproject executable in $STREAMING_HOME/bin to start the compiled
ccx as a process. Replace the placeholder paths and file with those for your CCX file.
NOTE: Port 9230 is used by the primary IoT Edge Services streaming project and should not be used for custom
projects.
$STREAMING_HOME/bin/streamingproject --ccx <path-to-ccx>/<compiled-file-name>.ccx -command-port 9231 --host localhost
The --ccx flag is used to specify the CCX file to run, the --command-port flag is used to specify the port that
the custom project listens to, and the --host flag specifies the host address the custom project listens on.
To redirect the terminal output to a file, add the following to the end of the previous command. Customize the
path and file name, as necessary.
>> ~/customProjectOutput.log 2>&1
Starting the Custom Project with User Authentication – Linux Only
Starting the project using the streamingproject executable in with the -V flag will enable user authentication.
Custom projects are authenticated using the same user credentials as the main IoT edge services streaming lite
project. See the SAP Dynamic Edge Processing: Edge Business Services - Configuration Guide for instructions
to configure the Streaming Lite authentication mechanism
Start the Custom Project – Windows Only
A script is provided to configure the custom CCL project as a Windows service. This script will both install and
uninstall a dedicated Windows service to run the custom CCL project.
18
IOT EDGE SERVICES – DEVELOPER GUIDE
Public
The script is located here: <dep_iot_edge>\bin\CustomCCLService.bat
The script will require a port and path to the compiled ccx file.
NOTE: Port 9230 is used by the primary IoT Edge Services streaming project and should not be used for custom
projects.
To install a custom CCX file as a Windows service, run the following and provide the port and ccx file when
prompted:
<dep_iot_edge>\bin\CustomCCLService.bat
To uninstall a custom CCX file as a Windows service (replace <service_name> with “CustomCCLProject_” + ccx
file name):
<dep_iot_edge>\bin\CustomCCLService.bat --delete_service <service_name>
19
IOT EDGE SERVICES – DEVELOPER GUIDE
Public
APPENDIX
Custom CCL Sample Template
/* Copyright (c) 2017 SAP SE or an affiliate company. All rights reserved. */
/** This is a sample template that may be used to create custom CCL project that
integrates with SAP Dynamic Edge Processing – IoT edge services */
/* You MUST have an input stream with this name and this schema */
CREATE INPUT STREAM isCustomSL SCHEMA (
DeviceId string,
DeviceTag string,
SensorId string,
SensorTag string,
SensorProfileId string,
SensorReadingValue string,
Context string,
DateCreated msdate
);
/* You may call this flex operator or any window operation and its output stream
whatever you wish */
CREATE FLEX ThisCanBeRenamed
IN isCustomSL
OUT OUTPUT STREAM ThisCanBeRenamed
SCHEMA (
DeviceId string,
DeviceTag string,
SensorId string,
SensorTag string,
SensorProfileId string,
SensorReadingValue string,
DateCreated msdate,
RuleId string
)
BEGIN
ON isCustomSL {
OUTPUT [
DeviceId=isCustomSL.DeviceId;
DeviceTag=isCustomSL.DeviceTag;
SensorId=isCustomSL.SensorId;
SensorTag=isCustomSL.SensorTag;
SensorProfileId=isCustomSL.SensorProfileId;
SensorReadingValue=isCustomSL.SensorReadingValue;
DateCreated=isCustomSL.DateCreated;
RuleId='This will be the Id or Name of the Rule your custom logic
triggers';
];
};
END;
/* You MUST have an output stream with this name and this schema */
CREATE OUTPUT STREAM osCustomSL
20
IOT EDGE SERVICES – DEVELOPER GUIDE
Public
AS
SELECT
ThisCanBeRenamed.DeviceId DeviceId,
ThisCanBeRenamed.DeviceTag DeviceTag,
ThisCanBeRenamed.SensorId SensorId,
ThisCanBeRenamed.SensorTag SensorTag,
ThisCanBeRenamed.SensorProfileId SensorProfileId,
ThisCanBeRenamed.SensorReadingValue SensorReadingValue,
ThisCanBeRenamed.DateCreated DateCreated,
ThisCanBeRenamed.RuleId RuleId
FROM ThisCanBeRenamed;
21
www.sap.com
© 2017 SAP SE or an SAP affiliate company. All rights reserved.
No part of this publication may be reproduced or transmitted in any form
or for any purpose without the express permission of SAP SE or an SAP
affiliate company.
SAP and other SAP products and services mentioned herein as well as their
respective logos are trademarks or registered trademarks of SAP SE (or an
SAP affiliate company) in Germany and other countries. Please see
http://www.sap.com/corporate-en/legal/copyright/index.epx#trademark for
additional trademark information and notices. Some software products
marketed by SAP SE and its distributors contain proprietary software
components of other software vendors.
National product specifications may vary.
These materials are provided by SAP SE or an SAP affiliate company for
informational purposes only, without representation or warranty of any kind,
and SAP SE or its affiliated companies shall not be liable for errors or
omissions with respect to the materials. The only warranties for SAP SE or
SAP affiliate company products and services are those that are set forth in
the express warranty statements accompanying such products and services,
if any. Nothing herein should be construed as constituting an additional
warranty.
In particular, SAP SE or its affiliated companies have no obligation to pursue
any course of business outlined in this document or any related presentation,
or to develop or release any functionality mentioned therein. This document,
or any related presentation, and SAP SE’s or its affiliated companies’
strategy and possible future developments, products, and/or platform
directions and functionality are all subject to change and may be changed by
SAP SE or its affiliated companies at any time for any reason without notice.
The information in this document is not a commitment, promise, or legal
obligation to deliver any material, code, or functionality. All forward-looking
statements are subject to various risks and uncertainties that could cause
actual results to differ materially from expectations. Readers are cautioned
not to place undue reliance on these forward-looking statements, which
speak only as of their dates, and they should not be relied upon in making
purchasing decisions.
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertisement