Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
* 2) Exploring and managing resources and resource values on said devices
*
* 3) Setup resource subscriptions and webhooks for resource monitoring
*/
public class Connect extends AbstractModule {
private static final String BUFFER = "BUFFER";
private static final String TAG_VALUE_TYPE = "valueType";
private static final String TAG_PRESUBSCRIPTION = "presubscription";
private static final String TAG_ON_NOTIFICATION_CALLBACK = "on notification callback";
private static final String TAG_WEBHOOK = "webhook";
private static final Filter CONNECTED_DEVICES_FILTER = new Filter("state", FilterOperator.EQUAL,
DeviceState.getIsConnectedState().getString());
private static final String TAG_RESOURCE = "resource";
private static final String FALSE = "false";
private static final String TAG_RESOURCE_PATH = "resource path";
private static final String TAG_METRIC_OPTIONS = "Metric options";
private static final String TAG_DEVICE_ID = "Device Id";
private static final String TAG_DEVICE = "Device";
private final EndPoints endpoint;
private final DeviceDirectory deviceDirectory;
protected final NotificationHandlersStore handlersStore;
protected final AtomicReference deliveryMethod;
private final Object presubscriptionLock = new Object();
private final Object webhookLock = new Object();
@Internal
protected Connect() {
this(new ConnectionOptions());
}
/**
* Connect module constructor.
*
* This module spawns threads for retrieving notifications when daemon is started @see
* {@link #startNotifications()}.
*
* By default, the executor services in charge are defined and managed internally. It is however possible to specify
* your own executors @see #Connect(ConnectionOptions, ExecutorService, ExecutorService).
*
* @param options
* connection options @see {@link ConnectionOptions}.
*/
public Connect(@NonNull ConnectionOptions options) {
this(options, null, null);
}
/**
* Constructor.
*
* @param context
* SDK context
*/
public Connect(SdkContext context) {
this(context == null ? null : context.getConnectionOption());
}
/**
* Connect module constructor.
*
* As opposed to {@link #Connect(ConnectionOptions)} which uses default thread pools for retrieving notifications,
* this constructor lets you the possibility to specify the executor services to use.
*
* @param options
* connection options @see {@link ConnectionOptions}.
*
* @param notificationHandlingThreadPool
* Threads in charge of retrieving notifications for a specific resource. If null, a default thread pool
* will be created internally.
* @param notificationPullingThreadPool
* Threads in charge of listening to notifications. The pool can either be a scheduled thread pool or a
* fixed thread pool depending on what best suits your system. If null, an internal timer will be created
* internally.
*/
public Connect(@NonNull ConnectionOptions options, @Nullable ExecutorService notificationHandlingThreadPool,
@Nullable ExecutorService notificationPullingThreadPool) {
super(options);
deliveryMethod = new AtomicReference(DeliveryMethod.UNDEFINED);
endpoint = new EndPoints(this.serviceRegistry);
deviceDirectory = new DeviceDirectory(options);
deviceDirectory.shareNetworkLayer(this);
this.handlersStore = new NotificationHandlersStore(this,
(notificationPullingThreadPool == null) ? createDefaultDaemonThreadPool()
: notificationPullingThreadPool,
notificationHandlingThreadPool, endpoint);
}
@SuppressWarnings("resource")
@Override
public Connect clone() {
return new Connect(this).setDeliveryMethod(deliveryMethod.get());
}
/**
* Creates a default thread pool in case none was specified.
*
* @return thread pool
*/
private static ScheduledExecutorService createDefaultDaemonThreadPool() {
return Executors.newScheduledThreadPool(1, new ThreadFactory() {
@Override
public Thread newThread(Runnable runable) {
final Thread thread = new Thread(runable);
thread.setDaemon(true);
return thread;
}
});
}
/**
* Starts notification pull.
*
* If an external callback is not set up (using `update_webhook`) then calling this function is mandatory to get or
* set resources. Unless {@link ConnectionOptions#setAutostartDaemon(boolean)} has been set to true or left as
* default.
*
* @throws MbedCloudException
* if a problem occurred during the process.
*/
@API
@Daemon(task = "Listen to notification", start = true)
public void startNotifications() throws MbedCloudException {
logger.logInfo(getModuleName() + ": startNotifications()");
if (handlersStore.isPullingActive()) {
logger.logInfo("Notification listening daemon thread is already started");
return;
}
setDeliveryMethod(true);
checkConfiguration(getConnectionOption());
if (deliveryMethod.get() == DeliveryMethod.SERVER_INITIATED) {
logger.throwSdkException("The SDK has been set up to use a server initiated delivery method. No daemon thread listening to notifications can be started in this mode.");
}
if (isForceClear()) {
logger.logWarn("Clearing any existing notification channel");
clearAllNotificationChannels();
}
// TODO use delivery method check instead when available
Webhook webhook = null;
try {
webhook = getWebhook();
} catch (@SuppressWarnings("unused") MbedCloudException exception) {
// Nothing to do
}
if (webhook != null) {
logger.throwSdkException("A webhook is currently set up [" + webhook
+ "]. Client-initiated delivery method cannot be used at the same time. Please remove the webhook if you want to use this mechanism instead.");
}
handlersStore.startNotificationListener();
}
protected void autostartDaemonIfNeeded() throws MbedCloudException {
setDeliveryMethod(true);
checkConfiguration(getConnectionOption());
if (deliveryMethod.get() != DeliveryMethod.CLIENT_INITIATED) {
return;
}
if (!handlersStore.isPullingActive() && isAutostartDaemon()) {
startNotifications();
}
}
/**
* Stops notification pull for notifications.
*
*
* @throws MbedCloudException
* if a problem occurred during the process.
*/
@API
@Daemon(task = "Notification pull", stop = true)
public void stopNotifications() throws MbedCloudException {
logger.logInfo(getModuleName() + ": stopNotifications()");
if (deliveryMethod.get() == DeliveryMethod.CLIENT_INITIATED) {
logger.logInfo("Delivery method was set to [" + deliveryMethod.get()
+ "]. Stopping daemon notification listening threads.");
handlersStore.stopNotificationListener();
}
if (isSkipCleanup()) {
logger.logWarn("Notification channel and subscriptions are not cleaned up as skipCleanup mode was requested.");
} else {
clearAllNotificationChannels();
}
}
private void deleteLongPollingChannel() throws MbedCloudException {
CloudCaller.call(this, "clearLongPollingNotificationChannel()", null, new CloudCall() {
@Override
public Call call() {
return endpoint.getNotifications().deleteLongPollChannel();
}
});
}
/**
* Shuts down all daemon services.
*/
@API
@Daemon(task = "Notification pull", shutdown = true)
public void shutdownConnectService() {
logger.logInfo(getModuleName() + ": shutdownConnectService()");
handlersStore.shutdown();
}
@Override
@API
public void close() {
super.close();
try {
stopNotifications();
} catch (@SuppressWarnings("unused") MbedCloudException exception) {
// Nothing to do
}
shutdownConnectService();
}
/**
* Lists connected devices (One page).
*
*
* @deprecated Use {@link DeviceListDao} instead
* @param options
* filter options
* @return the list of connected devices (One page).
* @throws MbedCloudException
* if a problem occurred during request processing.
*/
@API
@Deprecated
public @Nullable ListResponse
listConnectedDevices(DeviceListOptions options) throws MbedCloudException {
return deviceDirectory.listDevicesWithExtraFilters("listConnectedDevices()", options, CONNECTED_DEVICES_FILTER);
}
/**
* Gets an iterator over all connected devices according to filter options.
*
*
* @deprecated Use {@link DeviceListDao} instead
* @param options
* filter options.
* @return paginator @see {@link Paginator} for the list of devices corresponding to filter options.
* @throws MbedCloudException
* if a problem occurred during request processing.
*/
@API
@Deprecated
public @Nullable Paginator
listAllConnectedDevices(@Nullable DeviceListOptions options) throws MbedCloudException {
return new Paginator<>((options == null) ? new DeviceListOptions() : options,
new PageRequester() {
@Override
public ListResponse
requestNewPage(ListOptions opt) throws MbedCloudException {
return listConnectedDevices((DeviceListOptions) opt);
}
});
}
/**
* Lists device's resources.
*
*
* @deprecated use {@link #listResources(Device)} instead.
* @param device
* Device.
* @return list of resources present on a device.
* @throws MbedCloudException
* if a problem occurred during request processing.
*/
@API
@Deprecated
public @Nullable List
listResources(@NonNull com.arm.mbed.cloud.sdk.devicedirectory.model.Device device) throws MbedCloudException {
return listResources(DeviceAdapter.mapToFoundation(device));
}
/**
* Lists device's resources.
*
*
* @param device
* Device.
* @return list of resources present on a device.
* @throws MbedCloudException
* if a problem occurred during request processing.
*/
@API
public @Nullable List listResources(@NonNull Device device) throws MbedCloudException {
checkNotNull(device, TAG_DEVICE);
checkNotNull(device.getId(), TAG_DEVICE_ID);
final String finalDeviceId = device.getId();
return CloudCaller.call(this, "listResources()", ResourceAdapter.getListMapper(finalDeviceId),
new CloudCall>() {
@Override
public Call>
call() {
return endpoint.getEndpoints().getEndpointResources(finalDeviceId);
}
});
}
/**
* Lists device's observable resources.
*
* @deprecated use {@link #listObservableResources(Device)} instead
* @see Resource#isObservable()
*
*
* @param device
* Device.
* @return list of observable resources present on a device.
* @throws MbedCloudException
* if a problem occurred during request processing.
*/
@API
@Deprecated
public @Nullable List
listObservableResources(@NonNull com.arm.mbed.cloud.sdk.devicedirectory.model.Device device) throws MbedCloudException {
return listObservableResources(DeviceAdapter.mapToFoundation(device));
}
/**
* Lists device's observable resources.
*
* @see Resource#isObservable()
*
*
* @param device
* Device.
* @return list of observable resources present on a device.
* @throws MbedCloudException
* if a problem occurred during request processing.
*/
@API
public @Nullable List listObservableResources(@NonNull Device device) throws MbedCloudException {
final List resources = listResources(device);
if (resources == null || resources.isEmpty()) {
return null;
}
final List observableResources = new LinkedList<>();
for (final Resource resource : resources) {
if (resource.isObservable()) {
observableResources.add(resource);
}
}
return observableResources.isEmpty() ? null : observableResources;
}
/**
* Gets device's resource.
*
*
* @deprecated use {@link #getResource(Device, String)} instead.
*
* @param device
* Device.
* @param resourcePath
* Path of the resource to get
* @return resource present on the device.
* @throws MbedCloudException
* if a problem occurred during request processing.
*/
@API
@Deprecated
public @Nullable Resource getResource(@NonNull com.arm.mbed.cloud.sdk.devicedirectory.model.Device device,
@NonNull String resourcePath) throws MbedCloudException {
return getResource(DeviceAdapter.mapToFoundation(device), resourcePath);
}
/**
* Gets device's resource.
*
*
* @param device
* Device.
* @param resourcePath
* Path of the resource to get
* @return resource present on the device.
* @throws MbedCloudException
* if a problem occurred during request processing.
*/
@API
public @Nullable Resource getResource(@NonNull Device device,
@NonNull String resourcePath) throws MbedCloudException {
checkNotNull(device, TAG_DEVICE);
checkNotNull(device.getId(), TAG_DEVICE_ID);
checkNotNull(resourcePath, TAG_RESOURCE_PATH);
final List resources = listResources(device);
if (resources == null || resources.isEmpty()) {
return null;
}
for (final Resource resource : resources) {
if (ApiUtils.comparePaths(resourcePath, resource.getPath())) {
return resource;
}
}
return null;
}
/**
* Lists a device's subscriptions.
*
*
* @deprecated use {@link #listDeviceSubscriptions(Device)} instead.
* @param device
* Device.
* @return list of subscriptions
* @throws MbedCloudException
* if a problem occurred during request processing.
*/
@API
@Deprecated
public @Nullable List
listDeviceSubscriptions(@NonNull com.arm.mbed.cloud.sdk.devicedirectory.model.Device device) throws MbedCloudException {
return listDeviceSubscriptions(DeviceAdapter.mapToFoundation(device));
}
/**
* Lists a device's subscriptions.
*
*
* @param device
* Device.
* @return list of subscriptions
* @throws MbedCloudException
* if a problem occurred during request processing.
*/
@API
public @Nullable List listDeviceSubscriptions(@NonNull Device device) throws MbedCloudException {
checkNotNull(device, TAG_DEVICE);
checkNotNull(device.getId(), TAG_DEVICE_ID);
final String finalDeviceId = device.getId();
return CloudCaller.call(this, "listDeviceSubscriptions()", PresubscriptionAdapter.getResourcePathListMapper(),
new CloudCall() {
@Override
public Call call() {
return endpoint.getSubscriptions().getEndpointSubscriptions(finalDeviceId);
}
});
}
/**
* Gets the subscribe module.
*
* @return subscribe module.
* @throws MbedCloudException
* if a problem occurred during request processing.
*/
@API
public CloudSubscriptionManager subscribe() throws MbedCloudException {
autostartDaemonIfNeeded();
return this.handlersStore.getSubscriptionManager();
}
/**
* Lists metrics.
*
*
* @param options
* metrics options.
* @param
* Type of metrics list options
* @return list of metrics for the corresponding options.
* @throws MbedCloudException
* if a problem occurred during request processing.
*/
@API
public @Nullable ListResponse
listMetrics(@NonNull T options) throws MbedCloudException {
checkNotNull(options, TAG_METRIC_OPTIONS);
final T finalOptions = options;
final Date finalStart = options instanceof MetricsStartEndListOptions ? ((MetricsStartEndListOptions) options).getStart()
: null;
final Date finalEnd = options instanceof MetricsStartEndListOptions ? ((MetricsStartEndListOptions) options).getEnd()
: null;
final String finalPeriod = options instanceof MetricsPeriodListOptions ? ((MetricsPeriodListOptions) options).getPeriod()
.toString()
: null;
return CloudCaller.call(this, "listMetrics()", MetricAdapter.getListMapper(),
new CloudCall() {
@Override
public Call call() {
return endpoint.getStatistic()
.getMetrics(MetricAdapter.mapIncludes(finalOptions.getInclude()),
finalOptions.getInterval().toString(),
TranslationUtils.toLocalDate(finalStart),
TranslationUtils.toLocalDate(finalEnd), finalPeriod,
finalOptions.getPageSize(), finalOptions.getAfter(),
finalOptions.getOrder().toString());
}
});
}
/**
* Gets an iterator over all metrics according to filter options.
*
*
* @param options
* filter options.
* @param
* Type of metrics list options
* @return paginator @see {@link Paginator} for the list of metrics corresponding to filter options.
* @throws MbedCloudException
* if a problem occurred during request processing.
*/
@API
public @Nullable Paginator
listAllMetrics(@NonNull T options) throws MbedCloudException {
checkNotNull(options, TAG_METRIC_OPTIONS);
return new Paginator<>(options, new PageRequester() {
@SuppressWarnings("unchecked")
@Override
public ListResponse requestNewPage(ListOptions opt) throws MbedCloudException {
return listMetrics((T) opt);
}
});
}
/**
* Creates a observer to obtain resource current value.
*
* See {@link Observer}
*
* @param resource
* resource of interest.
* @param strategy
* backpressure strategy.
* @return corresponding observer.
* @throws MbedCloudException
* if a problem occurred during request processing.
*/
public @Nullable AsynchronousResponseObserver
createCurrentResourceValueObserver(@NonNull Resource resource,
@Nullable @DefaultValue(BUFFER) BackpressureStrategy strategy) throws MbedCloudException {
return createResourceActionObserver(createResourceAction("getResourceValueAsync()",
ResourceActionAdapter.getGetResourceValueMapper()),
resource, strategy, null, null, true);
}
/**
* Creates a observer to set a resource value.
*
* See {@link Observer}
*
* @param resource
* resource of interest.
* @param strategy
* backpressure strategy.
* @param value
* value to set.
* @param valueType
* type of the value to set.
* @return corresponding observer.
* @throws MbedCloudException
* if a problem occurred during request processing.
*/
public @Nullable AsynchronousResponseObserver
createSetResourceValueObserver(@NonNull Resource resource,
@Nullable @DefaultValue(BUFFER) BackpressureStrategy strategy,
@Nullable Object value,
@NonNull ResourceValueType valueType) throws MbedCloudException {
return createResourceActionObserver(createResourceAction("setResourceValueAsync()",
ResourceActionAdapter.getSetResourceValueMapper()),
resource, strategy, value, valueType, true);
}
/**
* Creates a observer to execute a resource.
*
* See {@link Observer}
*
* @param resource
* resource of interest.
* @param strategy
* backpressure strategy.
* @param value
* value to set.
* @param valueType
* type of the value to set.
* @return corresponding observer.
* @throws MbedCloudException
* if a problem occurred during request processing.
*/
public @Nullable AsynchronousResponseObserver
createExecuteResourceValueObserver(@NonNull Resource resource,
@Nullable @DefaultValue(BUFFER) BackpressureStrategy strategy,
@Nullable Object value,
@NonNull ResourceValueType valueType) throws MbedCloudException {
return createResourceActionObserver(createResourceAction("executeResourceAsync()",
ResourceActionAdapter.getExecuteResourceValueMapper()),
resource, strategy, value, valueType, false);
}
@SuppressWarnings("resource")
protected ResourceAction createResourceAction(String functionName,
Mapper requestMapper) {
final AbstractModule module = this;
final String function = functionName;
final Mapper finalMapper = requestMapper;
return new ResourceAction() {
@Override
public void execute(ResourceActionParameters arg) throws MbedCloudException {
final ResourceActionParameters finalArgs = arg;
CloudCaller.call(module, function, null, new CloudCall() {
@Override
public Call call() {
return endpoint.getAsync().createAsyncRequest(finalArgs.getResource().getDeviceId(),
finalArgs.getAsyncId(),
finalMapper.map(finalArgs));
}
});
}
};
}
protected AsynchronousResponseObserver
createResourceActionObserver(ResourceAction action, Resource resource, BackpressureStrategy strategy,
Object value, ResourceValueType type,
boolean notifyOtherObservers) throws MbedCloudException {
checkNotNull(resource, TAG_RESOURCE);
checkModelValidity(resource, TAG_RESOURCE);
autostartDaemonIfNeeded();
final ResourceActionParameters parameters = new ResourceActionParameters(UuidGenerator.generate(), resource,
value, type);
final BackpressureStrategy finalStrategy = (strategy == null) ? BackpressureStrategy.BUFFER : strategy;
final AsynchronousResponseObserver observer = handlersStore.createAsyncResponseObserver(parameters.getResource(),
parameters.getAsyncId(),
finalStrategy,
notifyOtherObservers);
try {
action.execute(parameters);
} catch (MbedCloudException exception) {
observer.unsubscribe();
throw exception;
}
return observer;
}
protected Future