Skip navigation links
Java SE Device Virtualization API Reference for Oracle Internet of Things Cloud Service Client Software Library. Release 19.1.1.0.0-13 E64443-24

Java SE Device Virtualization API Reference for Oracle Internet of Things Cloud Service Client Software Library

The device and enterprise client libraries simplify working with the Oracle IoT Cloud Service.

See: Description

Packages 
Package Description
oracle.iot.client
Client API for the Oracle IoT Cloud Service.
oracle.iot.client.device
API for directly–connected devices and gateway devices as clients of the Oracle IoT Cloud Service.
oracle.iot.client.enterprise
APIs for an enterprise client of the Oracle IoT Cloud Service.
The device and enterprise client libraries simplify working with the Oracle IoT Cloud Service. These client libraries are a higher–level abstraction over top of messages and REST APIs. Device clients are designed to make it easy to expose device functionality to the Oracle IoT Cloud Service, while enterprise clients are designed to make it easy to inspect and control a device. The true state of a device is within the device itself (whether the light is on or off). A "virtual" device object is contained within the cloud and enterprise clients that represent the last–known state of that device, and allow enterprise clients to send commands and set attributes of the device model (e.g., "turn the light off").

Configuration

The client must have a runtime configuration in order to communicate with the cloud service. This runtime configuration includes the IoT Cloud Service host, the identifier of the device or enterprise integration the client represents, and the shared secret of the device or enterprise integration.

The configuration is created by running the "bin/provisioner.sh" or "bin/provisioner.bat" tool which is part of the client library binary distribution. This tool creates an encrypted file that is used when running the client application. Running provisioner.sh or provisioner.bat with a -h option will provide usage.

Device Models

A device model is a predefined specification of the attributes, actions, formats and resources of a device that can be accessed by the client library. The attributes of a device model represent the basic variables that the device supports, such as temperature, humidity, flow rate, valve position, and so forth. Actions are similar to attributes, but are invocable state rather than readable state. For example, "reset". An action can can have zero or one arguments. The formats of a device model define the structure of a message payload. A format describes the message attributes by specifying the attribute names, types, optionality, and default values. The resources of a device model define additional, ad-hoc REST resources which provide richer REST support than what is possible with attributes and formats.

The client library has explicit API for obtaining a device model. See oracle.iot.client.Client#getDeviceModel(java.lang.String).

By default the API above always uses the network to retrieve a given device model. This behavior can be changed to cache device models to a local file store by setting the property oracle.iot.client.device_model_store to an existing, local file directory. Each model will be stored in its own file using a pattern of "dm-{URL encoded device model URN}.json", for example "dm-urn%3Acom%3Aoracle%3Aiot%3Adevice%3Ahumidity_sensor.json". Statically provisioning a local file directory with device models avoids network traffic; however, the local model must be identical to the model on the server. Dynamic provisioning, in which the client library retrieves the model from the server, ensures correctness of the model, but at the expense of network traffic. Dynamic provisioning is recommended.

Beware that when using a local store of device models, a local model will not get updated if the model on the server is changed.

Device Policies

A policy is a set of rules and constraints that can be associated with a device client (see below) to control its basic data transformation and transfer behavior. Device policies are automatically loaded, if they have been configured for the device, and there is no direct API in the library for manipulating the policies. The policies are applied when a value is offered to a VirtualDevice.

Device and Enterprise Clients

Both enterprise and device clients share common API for getting and setting values through a user-interface (in the case of an enterprise client application) and for getting and setting values on a physical device (in the case of a device client application). A device client application will create an oracle.iot.client.DirectlyConnectedDevice or an oracle.iot.client.GatewayDevice. An enterprise client application will create an oracle.iot.client.EnterpriseClient. From there, the application can use the Oracle IoT Client API to create instances of a "virtual device" which provides access to get and set values. Further detail is available in the oracle.iot.client.Client javadoc.

Prerequisites

Directly Connected Device Client Quick Start

The following steps must be performed by a device client application to allow a device to be monitored and controlled.

1. Initialize device client, ensure that the configurationFilePath is not pointing to a read only file as this might be modified during activation


     oracle.iot.client.DirectlyConnectedDevice dcd =
         new oracle.iot.client.DirectlyConnectedDevice(configurationFilePath, password);
 
2. Activate the device

     if (!dcd.isActivated()) {
         dcd.activate(deviceModelUrn);
     }
 
3. Obtain the device model

     DeviceModel deviceModel = dcd.getDeviceModel(deviceModelUrn):
4. Create a virtual device implementing the device model

    oracle.iot.client.device.VirtualDevice virtualDevice =
        dcd.createVirtualDevice(dcd.getEndpointId(), deviceModel);
5. Listen for control operations from an enterprise client

     // set a callback for any changes from the server to this virtual object
     virtualDevice.setOnChange(new oracle.iot.client.device.VirtualDevice.ChangeCallback<oracle.iot.client.device.VirtualDevice>() {
         public void onChange(oracle.iot.client.device.VirtualDevice.ChangeEvent<oracle.iot.client.device.VirtualDevice> event) {
             oracle.iot.client.device.VirtualDevice virtualDevice = event.getVirtualDevice();
             oracle.iot.client.device.VirtualDevice.NamedValue<?> namedValue = event.getNamedValue();
             while (namedValue != null) {
                 String attribute = namedValue.getName();
                 Object value = namedValue.getValue();
                 // update the device with the new value
                 namedValue = namedValue.next();
             }
         }
     });
    
     // Set a handler for a callable action. For example, the device model 
     // might have a 'reset' action. In this example, the action does not
     // require any input data.
     virtualDevice.setCallable("reset", new oracle.iot.client.device.VirtualDevice.Callable<Void>() {
         public void call(oracle.iot.client.device.VirtualDevice virtualDevice, Void not_used) {
             // reset the device
         }
     });

     // Set a handler for a callable action. For example, the device model 
     // might have a 'calibrate' action. In this example, the action
     // requires numeric input data.
     virtualDevice.setCallable("calibrate", new oracle.iot.client.device.VirtualDevice.Callable<Number>() {
         public void call(oracle.iot.client.device.VirtualDevice virtualDevice, Number zeroOffset) {
             // calibrate the device to zeroOffset
         }
     });
        
     // set a callback to receive errors from sending data to the server
     virtualDevice.setOnError(new oracle.iot.client.device.VirtualDevice.ErrorCallback<oracle.iot.client.device.VirtualDevice>() {
         public void onError(oracle.iot.client.device.VirtualDevice.ErrorEvent<oracle.iot.client.device.VirtualDevice> event) {
             oracle.iot.client.device.VirtualDevice device =  event.getVirtualDevice();
             String message = event.getMessage();
             oracle.iot.client.device.VirtualDevice.NamedValue<?> namedValue = event.getNamedValue();
             // get the attributes that are affected by the error   
             while (namedValue != null) {
                 String attribute = namedValue.getName();
                 Object value = namedValue.getValue();
                 // log or otherwise handle the error
                 namedValue = namedValue.next();
             }
         }
     });
6. Update the virtual device when the data on the physical device changes

     // set a value for a particular attribute in this virtual device
     oracle.iot.client.device.VirtualDevice.set("attribute", newValue);

     // or set multiple attributes in a batch operation
     virtualDevice.update()
         .set("attribute1", value1)
         .set("attribute2", value2)
         .finish();
7. Dispose of the device client

     dcd.close();

Gateway Device Client Quick Start

The following steps must be performed by a gateway device client application to allow devices to be monitored and controlled.

1. Initialize gateway device client, ensure that the configurationFilePath is not pointing to a read only file as this might be modified during activation


    oracle.iot.client.GatewayDevice gw =
        new oracle.iot.client.GatewayDevice(configurationFilePath, password);
 
2. Activate the gateway device

     if (!gw.isActivated()) {
         gw.activate();
     }
 
3. Obtain the device model

     DeviceModel deviceModel = gw.getDeviceModel(deviceModelUrn):
4. Register indirectly-connected devices

     // create meta-data with the indirectly-connected device's
     // manufacturer, model, and serial number
     Map<String,String> metaData = new HashMap<String, String>();
     metaData.put(oracle.iot.client.GatewayDevice.MANUFACTURER, "A Manufacturer");
     metaData.put(oracle.iot.client.GatewayDevice.MODEL_NUMBER, "MN-xxxx-xxxx");
     metaData.put(oracle.iot.client.GatewayDevice.SERIAL_NUMBER, "SN-yyyyyyyy");
     // add any vendor-specific meta-data to the metaData Map
     // register it
     String deviceId = gw.registerDevice(hardwareId, metaData, deviceModelUrn);
 
5. Create a virtual device implementing the device model

     oracle.iot.client.device.VirtualDevice virtualDevice = gw.createVirtualDevice(deviceId, deviceModel);
6. Listen for control operations from enterprise client

     // set a callback for any changes from the server to this virtual object
     virtualDevice.setOnChange(new oracle.iot.client.device.VirtualDevice.ChangeCallback<oracle.iot.client.device.VirtualDevice>() {
         public void onChange(oracle.iot.client.device.VirtualDevice.ChangeEvent<oracle.iot.client.device.VirtualDevice> event) {
             oracle.iot.client.device.VirtualDevice virtualDevice = event.getVirtualDevice();
             oracle.iot.client.device.VirtualDevice.NamedValue<?> namedValue = event.getNamedValue();
             while (namedValue != null) {
                 String attribute = namedValue.getName();
                 Object value = namedValue.getValue();
                 // update the device with the new value
                 namedValue = namedValue.next();
             }
         }
     });

     // Set a handler for a callable action. For example, the device model
     // might have a 'reset' action. In this example, the action does not
     // require any input data.
     virtualDevice.setCallable("reset", new oracle.iot.client.device.VirtualDevice.Callable<Void>() {
         public void call(oracle.iot.client.device.VirtualDevice virtualDevice, Void not_used) {
             // reset the device
         }
     });

     // Set a handler for a callable action. For example, the device model
     // might have a 'calibrate' action. In this example, the action
     // requires numeric input data.
     virtualDevice.setCallable("calibrate", new oracle.iot.client.device.VirtualDevice.Callable<Number>() {
         public void call(oracle.iot.client.device.VirtualDevice virtualDevice, Number zeroOffset) {
             // calibrate the device to zeroOffset
         }
     });

     virtualDevice.setOnError(new oracle.iot.client.device.VirtualDevice.ErrorCallback<oracle.iot.client.device.VirtualDevice>() {
         public void onError(oracle.iot.client.device.VirtualDevice.ErrorEvent<oracle.iot.client.device.VirtualDevice> event) {
             oracle.iot.client.device.VirtualDevice device =  event.getVirtualDevice();
             String message = event.getMessage();
             oracle.iot.client.device.VirtualDevice.NamedValue<?> namedValue = event.getNamedValue();
             // get the attributes that are affected by the error   
             while (namedValue != null) {
                 String attribute = namedValue.getName();
                 Object value = namedValue.getValue();
                 // log or otherwise handle the error
                 namedValue = namedValue.next();
             }
         }
     });
7. Update the virtual device when the data on the physical device changes

     // set a value for a particular attribute in this virtual device
     virtualDevice.set("attribute", newValue);

     // or set multiple attributes in a batch operation
     virtualDevice.update()
         .set("attribute1", value1)
         .set("attribute2", value2)
         .finish();
8. Dispose of the virtual device

     virtualDevice.close()
9. Dispose of the gateway device client

     gw.close();

Enterprise Client Quick Start

The following steps must be performed by an enterprise client application to monitor and control a device.

1. Initialize enterprise client,ensure that the configurationFilePath is not pointing to a read only file as this might be modified during activation


    EnterpriseClient ec =
        EnterpriseClient.newClient(configurationFilePath, password);
2. If the device model of the target device is not known at application startup, it can be selected from a list


     // To enumerate device models available in this app
     Pageable<String> deviceModelUrns = ec.getDeviceModels();
     while (deviceModelUrns.hasMore()) {
         deviceModelUrns.next();
         Collection<String> urns = deviceModelNames.elements();
         ... application or user selects a model URN ...
     }
 
3. If the endpoint ID of the target device is not known at application start up, it can be selected from a list of active devices implementing a given device model

     // To enumerate devices implementing this device model
     Pageable<Device> devices = ec.getActiveDevices(deviceModelUrn);
     while(devices.hasMore()) {
         Collection<Device> names = devices.elements();
         ... application or user selects a device ...
     }
4. Create a virtual device for the target device and model

     DeviceModel deviceModel = ec.getDeviceModel(deviceModelUrn);
     oracle.iot.client.enterprise.VirtualDevice virtualDevice =
         ec.createVirtualDevice(device.getId(), deviceModel);
5. Monitor the device

     // set a callback for any changes to this virtual object
     virtualDevice.setOnChange(new oracle.iot.client.enterprise.VirtualDevice.ChangeCallback<oracle.iot.client.enterprise.VirtualDevice>() {
         public void onChange(oracle.iot.client.enterprise.VirtualDevice.ChangeEvent<oracle.iot.client.enterprise.VirtualDevice> event) {
             oracle.iot.client.enterprise.VirtualDevice virtualDevice = event.getVirtualDevice();
             oracle.iot.client.enterprise.VirtualDevice.NamedValue<?> namedValue = event.getNamedValue();
             while (namedValue != null) {
                 String attribute = namedValue.getName();
                 Object value = namedValue.getValue();
                 // Perform application behaviors based on attribute changes
                 namedValue = namedValue.next();
             }
         }
     });

     virtualDevice.setOnError(new oracle.iot.client.enterprise.VirtualDevice.ErrorCallback<oracle.iot.client.enterprise.VirtualDevice>() {
         public void onError(oracle.iot.client.enterprise.VirtualDevice.ErrorEvent<oracle.iot.client.enterprise.VirtualDevice> event) {
             oracle.iot.client.enterprise.VirtualDevice device =  event.getVirtualDevice();
             String message = event.getMessage();
             oracle.iot.client.enterprise.VirtualDevice.NamedValue<?> namedValue = event.getNamedValue();
             // get the attributes that are affected by the error
             while (namedValue != null) {
                 String attribute = namedValue.getName();
                 Object value = namedValue.getValue();
                 // Perform error handling on device errors.
                 namedValue = namedValue.next();
             }
         }
     });
6. Control the device

     // set a value for a particular attribute in this virtualDevice
     virtualDevice.set("attribute ", newValue);

     // or set multiple attributes in a batch operation
     virtualDevice.update()
         .set("attribute1", value1)
         .set("attribute2", value2)
         .finish();

     // execute an action with data, for example 'calibrate', on the virtualDevice
     virtualDevice.call("calibrate", value);

     // execute an action without data, for example 'reset', on the virtualDevice
     virtualDevice.call("reset");
7. Dispose of the enterprise client

     ec.close();

Storage Cloud Quick Start

This shows how to use a virtual device attribute to upload content to, or download content from, the Oracle Storage Cloud Service. To upload or download content from a virtual device, there must be an attribute, field, or action in the device model with type URI. For the Oracle Storage Cloud Service, the URI type corresponds to the class oracle.iot.client.StorageObject. When the attribute, field, or action of type URI is set to a StorageObject instance, the content is automatically synchronized with the Storage Cloud Service.

Uploading content

An instance of oracle.iot.client.StorageObject is first needed to upload a file from a device client or from an enterprise client. The StorageObject is created using the createStorageObject API in oracle.iot.client.Client, which is the base class for oracle.iot.client.enterprise.EnterpriseClient, oracle.iot.client.device.DirectlyConnectedDevice, and oracle.iot.client.device.GatewayDevice. The StorageObject names the object in storage, and provides the mime-type of the content. To set the input file, the oracle.iot.client.StorageObject API setInputPath(String) is used.

This example shows the typical use case from a DirectlyConnectedDevice. But the code for a GatewayDevice or EnterpriseClient is the same.


    StorageObject storageObject = directlyConnectedDevice.createStorageObject("mediaSnapshot.jpg", "image/jpg");
    storageObject.setInputPath("../images/mediaSnapshot.jpg");
    virtualDevice.set("snapshot", storageObject);
A StorageObject may also be set on an Alert field, or as an Action parameter, provided the type in the device model is URI.

Downloading content

In the virtualization API, the client is notified through an onChange event, onAlert event, or a call callback for an action. The value in the event is a StorageObject. To download the content, the output path is set on the StorageObject, and the content is synchronized by calling the StorageObject sync() API.

This example shows the typical use case from an onChange event. The code for an onAlert or for an action callback is much the same.


        virtualDevice.setOnChange("snapshot", new VirtualDevice.ChangeCallback<VirtualDevice>() {
            public void onChange(AbstractVirtualDevice.ChangeEvent<VirtualDevice> event) {
                VirtualDevice.NamedValue namedValue = event.getNamedValue();
                StorageObject storageObject = (StorageObject) namedValue.getValue();
                // only download if image is less than 4M
                if (storageObject.getLength() < 4 * 1024L * 1024L) {
                    try {
                        storageObject.setOutputPath("../downloads/"+storageObject.getName());
                        storageObject.sync();
                    } catch (FileNotFoundException e) {
                        System.err.println("cannot create file for download");
                    }
                }
            }
        });

Checking synchronization status

A StorageObject is a reference to some content in the Storage Cloud. The content can be in sync with the storage cloud, not in sync with the storage cloud, or in process of being sync'd with the storage cloud. The synchronization happens on a separate thread, but can be monitored by setting a SyncCallback with setOnSync.

For the upload case, set the SyncCallback on the storage object before setting the virtual device attribute. For the download case, set the SyncCallback on the storage object from within the onChange callback.


    storageObject.setOnSync(new StorageObject.SyncCallback<VirtualDevice>() {
        public void onSync(StorageObject.SyncEvent<VirtualDevice> event) {
            StorageObject storageObject = event.getStorageObject();
            if (storageObject.getSyncStatus() == StorageObject.SyncStatus.IN_SYNC) {
                 // image was uploaded and can be deleted
            } else if (storageObject.getSyncStatus() == StorageObject.SyncStatus.SYNC_FAILED) {
                 // image was not uploaded, take action!
            }
        }
     });

Device and Enterprise Client System Properties

Key Meaning
oracle.iot.client.device.dispatcher_polling_interval Default: 3 seconds
The polling interval, in seconds, for message dispatching. If a message is not sent to the server within this timeout, an empty message will be sent in order to solicit request messages that may be queued in the server.

oracle.iot.client.device.message_dispatcher_base_number_of_retries Default: 3
Controls the number of times a message is retried if the message cannot be sent. A message with a reliability of no-guarantee is retried this number of times. A message with a reliability of best-effort is retried twice this number of times. A message with a reliability of guaranteed-delivery is retried an unlimited number of times. The value must be greater than zero.
oracle.iot.client.device.message_dispatcher_backoff Default: 1000 milliseconds
Amount of time in milliseconds to backoff if the client receives an HTTP 503 response from the server. This is the initial value used for the amount of time to backoff. The backoff time increases exponentially if the server continues to return an HTTP 503 response.
oracle.iot.client.device.dispatcher_max_queue_size Default: 10000
Total messages to queue. Attempts to send messages when the queue is full will result in an error.

oracle.iot.client.device.dispatcher_max_messages_per_connection Default: 100
Maximum number of outgoing messages to send in one payload per HTTPS connection to the server.
oracle.iot.client.device.request_buffer_size Default: 4192 bytes
The size, in bytes, of the buffer for holding incoming messages received from the server pending dispatch to handlers in the application.
com.oracle.iot.client.disable_long_polling Default: false
Long polling is used by default, set this to true to disable it.

com.oracle.iot.client.long_polling_timeout_offset Default: 100 milliseconds
The time, in milliseconds, added to the receive timeout given by the application and then used for the client transport timeout.
oracle.iot.client.device.send_receive_timeout Default: 100 milliseconds
Only used when long polling is disabled. The minimum time, in milliseconds, since the last send before polling the server for incoming messages if the receive buffer is empty. A larger value may cause a delay in the receipt of incoming messages, but will cause less network overhead. A value of zero will cause the library to skip the poll for incoming messages when calling receive if the receive buffer is empty.
oracle.iot.client.enterprise.monitor_max_formats Default: 10
The number of alerts each request the enterprise client performs for virtual device updates can have.

oracle.iot.client.enterprise.message_enumerator_limit Default: 10
The number of messages to return in the Pageable<Message> from the MessageEnumerator getMessages API. The value will be clamped between 10 and 200, inclusive.
com.oracle.iot.client.enterprise.message_polling_interval Default: 3000 milliseconds
The amount of delay, in milliseconds, between polls for messages by the MessagePoller. This setting affects how often a MessageEnumerator.MessageListener instance may be called.
com.oracle.iot.client.enterprise.message_polling_limit Default: 10
The maximum number of messages to return on a single poll by the MessagePoller. The value will be clamped between 10 and 200, inclusive.
oracle.iot.client.http_response_timeout Default: 15000 milliseconds
Only used when long polling is disabled. The amount of time, in milliseconds, to wait for the server to respond to an HTTPS request.
oracle.iot.client.device.mqtt_connection_timeout Default: 30 seconds

The maximum time in seconds the client will wait for the connection to the MQTT server to be established. The default timeout is 30 seconds. A value of 0 means the client will wait until the network connection is made successfully or fails.

oracle.iot.client.device.mqtt_keep_alive_interval Default: 60 seconds

The maximum time in seconds before the client will disconnect if no messages are sent or received. between messages sent or received. The default value is 60 seconds. A value of zero means the client will not disconnect due to inactivity.

oracle.iot.client.device.mqtt_time_to_wait Default: 1000

The maximum time in milliseconds to wait after sending an MQTT packet to the broker for a response. If the timeout is exceeded, the application will receive an IOException. A value of zero means ‘no timeout’.

oracle.iot.client.tam Default: null
The fully qualified name of a class implementing com.oracle.iot.client.trust.TrustedAssetsManager. The specified class must have a public constructor accepting an Object parameter. See Trusted Assets for more information.
oracle.iot.client.device_model_store Default: null
If the property is not set, device models will not be stored locally. An existing, local file directory where statically provisioned device models are stored. See Device Models for more information.
com.oracle.iot.client.device.allow_draft_device_models Default: false
The server will create a draft device model for device models that have not been provisioned on the server. When set to false, this flag overrides that behavior. The consequence of setting the flag to false is that API that takes a device model URN may throw an exception if the device model has not been provisioned. If the flag is set to true, however, a coding error might go unnoticed.
This flag also controls whether or not the client will accept a draft device model from the server.
oracle.iot.client.pretty_print_messages Default: true
Controls whether or not logged messages should be pretty printed. Pretty printing the messages makes the JSON easier to read. By default, pretty printing is enabled. Set this property to false to disable pretty printing for a more compact view of the logged messages.
oracle.iot.client.network_cost Default: ETHERNET
Used by the "batchByCost" device function, set this property to the type of connected network. The property may be set from the application code; for example, when the type of connected network changes.
oracle.iot.client.configuration_path Default: current directory
The directory where the simple trusted assets manager will store activation parameters.
oracle.iot.client.disable_storage_object_prefix Default: false
Disable the prefixing the storage object's name with the device's client ID and a directory separator.
oracle.iot.client.device.request_dispatcher_thread_pool_size Default: 1
Number of threads created for dispatching request messages so that request handlers can be executed in parallel. This number should be specified as greater than one, else it will be ignored and the default value of one will be used for request handler thread pool size.
com.oracle.iot.client.device.persistence_directory Default: System property user.dir
The directory that is used for local persistence.
com.oracle.iot.client.device.persistence_db_name Default: persistence_store
The name of the database used for persisting data.
com.oracle.iot.client.device.persistence_enabled Default: true
If true, the client library will persist data.
com.oracle.iot.client.device.isolation_level Default: java.sql.Connection.TRANSACTION_READ_UNCOMMITTED
Get the transaction isolation level for SQL database persistence.
Skip navigation links
Java SE Device Virtualization API Reference for Oracle Internet of Things Cloud Service Client Software Library. Release 19.1.1.0.0-13 E64443-24

Copyright © 2015, 2017, Oracle. All rights reserved.