/*******************************************************************************
* Copyright (c) 2011, 2016 Eurotech and/or its affiliates
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eurotech
*******************************************************************************/
package org.eclipse.kura.cloud;
import java.util.List;
import org.eclipse.kura.KuraException;
import org.eclipse.kura.data.DataService;
import org.eclipse.kura.message.KuraPayload;
/**
* The CloudClient is designed to be used by single application bundles.
* CloudClient instances are acquired from the CloudService and they
* are released when the work is completed. Generally, a CloudClient
* is acquired during the activation phase of a bundle and it is released
* during the deactivation phase.
* <br>
* CloudClient leverages the {@link org.eclipse.kura.data.DataService}
* for all interactions with the transport layer and the communication
* with the remote server. CloudClient establishes a set of default
* subscriptions that allow remote servers or other devices to direct messages
* to the application instance.
* <br>
* If the bundle using the CloudClient relies on custom subscriptions
* beyond the default ones, it is responsibility of the application to implement
* the {@link CloudClientListener#onConnectionEstablished()} callback method in the
* CloudCallbackHandler to restore the subscriptions it needs.
* <br>
* The <b>CloudClient.release method will unsubscribe</b> all subscriptions
* incurred by this client and it will unregister this CloudClient
* instance from the list of CloudCallbackHandlers registered.
* <br>
* There can be more than one instance of CloudClient in the system,
* ideally one per ApplicationId but this is not enforced.
* The class accepts more than one callback handler; all registered handlers are invoked
* when a message is received. It is up to the received to analyze the topic
* of the message received and handle it appropriately.
* <br>
* The CloudClient publishes and receives messages using a topic namespace
* following a structure as: [CRTL_PREFIX/]accountName/deviceId/appId/appTopic.<br>
* <ul>
* <li>CRTL_PREFIX: is an optional prefix to denote topic used for control messages
* as opposed to data messages. The framework makes use of control topics to
* separate management messages like replies from those used for application data.
* <li>accountName: an unique identifier that represents a group of devices and users
* <li>deviceId: an unique identifier within an account that represents a single gateway device.
* By default, the MAC address of its primary network interface is generally used as the deviceId of the gateway.
* In the case of an MQTT transport, for example, deviceId maps to the Client Identifier (Client ID).
* <li>appId: an identifier to denote an application running on the gateway device.
* We suggest to version the application identifier in order to allow multiple versions of the application
* to coexist, e.g. CONF-V1, CONF-V2, etc.
* <li>appTopic topic defined and managed by the application.
* </ul>
* accountName, deviceId, and applicationId are derived based on the configuration parameters
* of the system where this instance is deployed while the applicationTopic is controlled
* by the application. The following is an example of topic used for publishing where the prefix
* used for the control Topics is $EDC.
* <ul>
* <li>publish: accountName/deviceId/applicationId/appTopic
* <li>controlPublish: $EDC/accountName/assetId/applicationId/appTopic
* <li>subscribe: accountName/deviceId/applicationId/appTopic
* <li>controlSubscribe: $EDC/accountName/deviceId/applicationId/appTopic
* <li>default subscriptions: $EDC/accountName/deviceId/applicationId/#
* </ul>
* Note that the default subscription of a CloudClient allows remote servers
* or applications running on other devices to publish messages addressed
* to specific applications running on specific devices.
*/
public interface CloudClient {
/**
* Returns the applicationId of this CloudClient
*
* @return applicationId
*/
public String getApplicationId();
/**
* Releases this CloudClient handle. This instance should no longer be used.
* Note: CloudClient does not unsubscribes all subscriptions incurred by this client,
* this responsibility is left to the application developer
*/
public void release();
/**
* Returns an indication of whether the connection to the remote server is established.
* If your application needs to manage the connection directly, it can use the
* {@link DataService#connect} and {@link DataService#disconnect} methods.
*
* @return boolean, whether connection to broker is established.
*/
public boolean isConnected();
/**
* Publishes a message to the remote server using the default priority 5.
* Before passing the message the to {@link org.eclipse.kura.data.DataService},
* the CloudClient will manipulate the provided topic by appending the necessary parts
* to achieve topic partitioning and device identification. It is also responsible to
* encode the {@link KuraPayload} payload into binary format.
* <br>
* The KuraStoreCapacityReachedException is thrown if the database buffer
* has reached its capacity for messages that are not yet published or
* they are still in transit.
*
* @param appTopic
* A String specifying the application portion of the topic the message is published on.
* @param payload
* An KuraPayload representing the message to be published
* @param qos
* An integer specifying the quality of service the message was published on.
* @param retain
* Whether or not the broker should retain the message
* @return The published message's ID.
*/
public int publish(String appTopic, KuraPayload payload, int qos, boolean retain) throws KuraException;
/**
* Publishes a message to the remote server.
* Before passing the message the to {@link org.eclipse.kura.data.DataService},
* the CloudClient will manipulate the provided topic by appending the necessary parts
* to achieve topic partitioning and device identification. It is also responsible to
* encode the {@link KuraPayload} payload into binary format.
* <br>
* The priority argument can be used to control the relative ordering of this
* message with other messages that may be currently queued for publishing.
* Priority level 0 (highest) should be used sparingly and reserved for
* messages that should be sent with the minimum latency. Life-cycle messages
* (e.g. device start and stop) are an example of messages that are
* published by the framework with priority 0.
* Priority 1 messages are used by the framework to publish response messages
* in request/response conversations to prevent a timeout at the requester.
* Application should consider using priority 5 or higher.
* <br>
* The KuraStoreCapacityReachedException is thrown if the database buffer
* has reached its capacity for messages that are not yet published or
* they are still in transit. The limit does not apply to internal messages with the priority less than 2.
* These priority levels are reserved to the framework which uses it for life-cycle messages
* - birth and death certificates - and replies to request/response flows.
*
* @param appTopic
* A String specifying the application portion of the topic the message is published on.
* @param payload
* An KuraPayload representing the message to be published
* @param qos
* An integer specifying the quality of service the message was published on.
* @param retain
* Whether or not the broker should retain the message
* @param priority
* Relative ordering of this message with other messages that may be currently queued for publishing.
* @return The published message's ID.
*/
public int publish(String appTopic, KuraPayload payload, int qos, boolean retain, int priority)
throws KuraException;
/**
* Publishes a message to the remote server with a raw byte array payload.
* This is the lowest level publish API exposed by the CloudClient.
* Before passing the message the to {@link org.eclipse.kura.data.DataService},
* the CloudClient will manipulate the provided topic by appending the necessary parts
* to achieve topic partitioning and device identification.
* <br>
* The priority argument can be used to control the relative ordering of this
* message with other messages that may be currently queued for publishing.
* Priority level 0 (highest) should be used sparingly and reserved for
* messages that should be sent with the minimum latency. Life-cycle messages
* (e.g. device start and stop) are an example of messages that are
* published by the framework with priority 0.
* Priority 1 messages are used by the framework to publish response messages
* in request/response conversations to prevent a timeout at the requester.
* Application should consider using priority 5 or higher.
* <br>
* The KuraStoreCapacityReachedException is thrown if the database buffer
* has reached its capacity for messages that are not yet published or
* they are still in transit. The limit does not apply to internal messages with the priority less than 2.
* These priority levels are reserved to the framework which uses it for life-cycle messages
* - birth and death certificates - and replies to request/response flows.
*
* @param appTopic
* A String specifying the application portion of the topic the message is published on.
* @param payload
* Binary payload representing the message to be published
* @param qos
* An integer specifying the quality of service the message was published on.
* @param retain
* Whether or not the broker should retain the message
* @param priority
* Relative ordering of this message with other messages that may be currently queued for publishing.
* @return The published message's ID.
*/
public int publish(String appTopic, byte[] payload, int qos, boolean retain, int priority) throws KuraException;
/**
* Publishes a control message to the remote server. Control messages are qualified with an
* additional prefix appended at the beginning of the target topic. The
* prefix is configured as a property of the {@link CloudService} and it appended
* automatically by this controlPublish method. Just as {@link #publish}, the
* controlPublish method will manipulate the provided topic by appending the necessary parts
* to achieve topic partitioning including device identification and encode
* the {@link KuraPayload} payload into binary format.
* <br>
* The priority argument can be used to control the relative ordering of this
* message with other messages that may be currently queued for publishing.
* Priority level 0 (highest) should be used sparingly and reserved for
* messages that should be sent with the minimum latency. Life-cycle messages
* (e.g. device start and stop) are an example of messages that are
* published by the framework with priority 0.
* Priority 1 messages are used by the framework to publish response messages
* in request/response conversations to prevent a timeout at the requester.
* Application should consider using priority 5 or higher.
* <br>
* The KuraStoreCapacityReachedException is thrown if the database buffer
* has reached its capacity for messages that are not yet published or
* they are still in transit. The limit does not apply to internal messages with the priority less than 2.
* These priority levels are reserved to the framework which uses it for life-cycle messages
* - birth and death certificates - and replies to request/response flows.
*
* @param appTopic
* A String specifying the application topic the message is published on.
* @param payload
* An KuraPayload representing the message to be published
* @param qos
* An integer specifying the quality of service the message was published on.
* @param retain
* Whether or not the broker should retain the message
* @param priority
* Relative ordering of this message with other messages that may be currently queued for publishing.
* @return The published message's ID.
*/
public int controlPublish(String appTopic, KuraPayload payload, int qos, boolean retain, int priority)
throws KuraException;
/**
* Publishes a control message to the remote server addressing it to another device.
* Control messages are qualified with an additional prefix appended at the beginning of the target topic.
* The prefix is configured as a property of the {@link CloudService} and it appended
* automatically by this controlPublish method. Just as {@link #publish}, the
* controlPublish method will manipulate the provided topic by appending the necessary parts
* to achieve topic partitioning including device identification and encode
* the {@link KuraPayload} payload into binary format.
* <br>
* The priority argument can be used to control the relative ordering of this
* message with other messages that may be currently queued for publishing.
* Priority level 0 (highest) should be used sparingly and reserved for
* messages that should be sent with the minimum latency. Life-cycle messages
* (e.g. device start and stop) are an example of messages that are
* published by the framework with priority 0.
* Priority 1 messages are used by the framework to publish response messages
* in request/response conversations to prevent a timeout at the requester.
* Application should consider using priority 5 or higher.
* <br>
* The KuraStoreCapacityReachedException is thrown if the database buffer
* has reached its capacity for messages that are not yet published or
* they are still in transit. The limit does not apply to internal messages with the priority less than 2.
* These priority levels are reserved to the framework which uses it for life-cycle messages
* - birth and death certificates - and replies to request/response flows.
*
* @param deviceId
* A String specifying the asset ID.
* @param appTopic
* A String specifying the application topic the message is published on.
* @param payload
* An KuraPayload representing the message to be published
* @param qos
* An integer specifying the quality of service the message was published on.
* @param retain
* Whether or not the broker should retain the message
* @param priority
* Relative ordering of this message with other messages that may be currently queued for publishing.
* @return The published message's ID.
*/
public int controlPublish(String deviceId, String appTopic, KuraPayload payload, int qos, boolean retain,
int priority) throws KuraException;
/**
* Publishes a control message to the remote server addressing it to another device
* with a raw byte array payload.
* Control messages are qualified with an additional prefix appended at the beginning of the target topic.
* The prefix is configured as a property of the {@link CloudService} and it appended
* automatically by this controlPublish method. Just as {@link #publish}, the
* controlPublish method will manipulate the provided topic by appending the necessary parts
* to achieve topic partitioning including device identification.
* <br>
* The priority argument can be used to control the relative ordering of this
* message with other messages that may be currently queued for publishing.
* Priority level 0 (highest) should be used sparingly and reserved for
* messages that should be sent with the minimum latency. Life-cycle messages
* (e.g. device start and stop) are an example of messages that are
* published by the framework with priority 0.
* Priority 1 messages are used by the framework to publish response messages
* in request/response conversations to prevent a timeout at the requester.
* Application should consider using priority 5 or higher.
* <br>
* The KuraStoreCapacityReachedException is thrown if the database buffer
* has reached its capacity for messages that are not yet published or
* they are still in transit. The limit does not apply to internal messages with the priority less than 2.
* These priority levels are reserved to the framework which uses it for life-cycle messages
* - birth and death certificates - and replies to request/response flows.
*
* @param deviceId
* A String specifying the asset ID.
* @param appTopic
* A String specifying the application topic the message is published on.
* @param payload
* Binary payload representing the message to be published
* @param qos
* An integer specifying the quality of service the message was published on.
* @param retain
* Whether or not the broker should retain the message
* @param priority
* Relative ordering of this message with other messages that may be currently queued for publishing.
* @return The published message's ID.
*/
public int controlPublish(String deviceId, String appTopic, byte[] payload, int qos, boolean retain, int priority)
throws KuraException;
/**
* Subscribes to a topic with the remote server. The topic is specified as a String
* object and the QoS is specified as an integer. The CloudClient will manipulate the
* provided topic by appending the necessary parts to achieve topic partitioning and
* device identification.<br>
* This is a synchronous call. If the subscribe fails, an exception will be thrown
* that will contain information about the cause of the failure.
*
* @param appTopic
* A String object containing the application topic.
* @param qos
* An int containing the Quality of Service.
*/
public void subscribe(String appTopic, int qos) throws KuraException;
/**
* Subscribes to a control topic with the remote server. The topic is specified as a String
* object and the QoS is specified as an integer. The CloudClient will manipulate the
* provided topic by appending the necessary parts to achieve topic partitioning and
* including control prefix and device identification.<br>
* This is a synchronous call. If the subscribe fails, an exception will be thrown
* that will contain information about the cause of the failure.
*
* @param appTopic
* A String object containing the application topic.
* @param qos
* An int containing the Quality of Service.
*/
public void controlSubscribe(String appTopic, int qos) throws KuraException;
/**
* Unubscribes to a topic with the remote server. The topic is specified as a String
* object and the QoS is specified as an integer. The CloudClient will manipulate the
* provided topic by appending the necessary parts to achieve topic partitioning and
* device identification.<br>
* This is a synchronous call. If the unsubscribe fails, an exception will be thrown
* that will contain information about the cause of the failure.
*
* @param appTopic
* A String object containing the application topic.
*/
public void unsubscribe(String appTopic) throws KuraException;
/**
* Unsubscribes to a control topic with the remote server. The topic is specified as a String
* object and the QoS is specified as an integer. The CloudClient will manipulate the
* provided topic by appending the necessary parts to achieve topic partitioning and
* including control prefix and device identification.<br>
* This is a synchronous call. If the unsubscribe fails, an exception will be thrown
* that will contain information about the cause of the failure.
*
* @param appTopic
* A String object containing the application topic.
*/
public void controlUnsubscribe(String appTopic) throws KuraException;
/**
* Adds a CloudCallbackHandler with this CloudClient. This handler
* will receive events when a client publication has arrived, and
* when a publish has been fully acknowledged by the remote server.
*
* @param cloudClientListener
* An implementation of the CloudCallbackHandler interface.
*/
public void addCloudClientListener(CloudClientListener cloudClientListener);
/**
* Removes a CloudCallbackHandler from this CloudClient.
* The provided CloudCallbackHandler will no longer receive the events
* when a published message is received.
*/
public void removeCloudClientListener(CloudClientListener cloudClientListener);
/**
* Gets the list of identifiers of messages that have not been published yet.
*
* @return
* @throws KuraException
*/
List<Integer> getUnpublishedMessageIds() throws KuraException;
/**
* Finds the list of identifiers of messages that are still in-flight
* (messages published but not confirmed yet).
* This only applies to messages published with QoS > 0.
*
* @return
* @throws KuraException
*/
List<Integer> getInFlightMessageIds() throws KuraException;
/**
* Finds the list of identifiers of in-flight messages that have been dropped.
* This only applies to messages published with QoS > 0.
* On the establishment of a new connection, the service can be configured
* either to republish or drop in-flight messages.
* The former option can be used if service users tolerate publishing message
* duplicates.
* The latter option can be used it service users tolerate losing messages.
*
* @return
* @throws KuraException
*/
List<Integer> getDroppedInFlightMessageIds() throws KuraException;
}