4
votes

Is there any mechanism or method or steps to detect the endpoint(KAA SDK) connectivity to the KAA server from the application.

If no, then how can we identifies failure devices through remotely?? or How can we identifies devices that are not able to communicate with the KAA Server after deploying devices in the field??

How one can achieve this requirement to unlock the power of IOT??

2

2 Answers

5
votes

If your endpoint will meet some problems connecting to Kaa server a "failover" will happen.

So you must define your own failover strategy and set it for your Kaa client. Every time failover happens strategy's onFialover() method will be called.

Below you can see the code example for the Java SDK.

  import org.kaaproject.kaa.client.DesktopKaaPlatformContext;
  import org.kaaproject.kaa.client.Kaa;
  import org.kaaproject.kaa.client.KaaClient;
  import org.kaaproject.kaa.client.SimpleKaaClientStateListener;
  import org.kaaproject.kaa.client.channel.failover.FailoverDecision;
  import org.kaaproject.kaa.client.channel.failover.FailoverStatus;
  import org.kaaproject.kaa.client.channel.failover.strategies.DefaultFailoverStrategy;
  import org.kaaproject.kaa.client.exceptions.KaaRuntimeException;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;

  import java.io.IOException;
  import java.util.concurrent.TimeUnit;

  /**
  * A demo application that shows how to use the Kaa credentials API.
  */
  public class CredentialsDemo {
  private static final Logger LOG = LoggerFactory.getLogger(CredentialsDemo.class);
  private static KaaClient kaaClient;

  public static void main(String[] args) throws InterruptedException, IOException {

  LOG.info("Demo application started");

  try {

  // Create a Kaa client and add a startup listener
  kaaClient = Kaa.newClient(new DesktopKaaPlatformContext(), new SimpleKaaClientStateListener() {
  @Override
  public void onStarted() {
  super.onStarted();
  LOG.info("Kaa client started");
  }
  }, true);

  kaaClient.setFailoverStrategy(new CustomFailoverStrategy());
  kaaClient.start();

  // ... Do some work ...

  LOG.info("Stopping application.");
  kaaClient.stop();

  } catch (KaaRuntimeException e) {
  LOG.info("Cannot connect to server - no credentials found.");
  LOG.info("Stopping application.");
  }

  }

  // Give a possibility to manage device behavior when it loses connection
  // or has other problems dealing with Kaa server.
  private static class CustomFailoverStrategy extends DefaultFailoverStrategy {

  @Override
  public FailoverDecision onFailover(FailoverStatus failoverStatus) {
  LOG.info("Failover happen. Failover type: " + failoverStatus);

  // See enum DefaultFailoverStrategy from package org.kaaproject.kaa.client.channel.failover
  // to list all possible values
  switch (failoverStatus) {
  case CURRENT_BOOTSTRAP_SERVER_NA:
  LOG.info("Current Bootstrap server is not available. Trying connect to another one.");

  // ... Do some recovery, send notification messages, etc. ...

  // Trying to connect to another bootstrap node one-by-one every 5 seconds
  return new FailoverDecision(FailoverDecision.FailoverAction.USE_NEXT_BOOTSTRAP, 5L, TimeUnit.SECONDS);
  default:
  return super.onFailover(failoverStatus);
  }
  }
  }
  }

UPDATED (2016/10/28)

From the server side you can check endpoint credentials status as shown in method checkCredentialsStatus() in code below. The status IN_USE shows that endpoint has at least one successful connection attempt.

Unfortunately in current Kaa version there are no ways to directly check if endpoint is connected to server or not. I describe them after code example.

  package org.kaaproject.kaa.examples.credentials.kaa;

  import org.kaaproject.kaa.common.dto.ApplicationDto;
  import org.kaaproject.kaa.common.dto.admin.AuthResultDto;
  import org.kaaproject.kaa.common.dto.credentials.CredentialsStatus;
  import org.kaaproject.kaa.examples.credentials.utils.IOUtils;
  import org.kaaproject.kaa.server.common.admin.AdminClient;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;

  import java.util.List;

  public class KaaAdminManager {

  private static final Logger LOG = LoggerFactory.getLogger(KaaAdminManager.class);

  private static final int DEFAULT_KAA_PORT = 8080;
  private static final String APPLICATION_NAME = "Credentials demo";

  public String tenantAdminUsername = "admin";
  public String tenantAdminPassword = "admin123";

  private AdminClient adminClient;

  public KaaAdminManager(String sandboxIp) {
  this.adminClient = new AdminClient(sandboxIp, DEFAULT_KAA_PORT);
  }

  // ...

  /**
  * Check credentials status for getting information
  * @return credential status
  */
  public void checkCredentialsStatus() {
  LOG.info("Enter endpoint ID:");

  // Reads endpoint ID (aka "endpoint key hash") from user input
  String endpointId = IOUtils.getUserInput().trim();

  LOG.info("Getting credentials status...");
  try {
  ApplicationDto app = getApplicationByName(APPLICATION_NAME);
  String appToken = app.getApplicationToken();

  // CredentialsStatus can be: AVAILABLE, IN_USE, REVOKED
  // if endpoint is not found on Kaa server, exception will be thrown
  CredentialsStatus status = adminClient.getCredentialsStatus(appToken, endpointId);
  LOG.info("Credentials for endpoint ID = {} are now in status: {}", endpointId, status.toString());
  } catch (Exception e) {
  LOG.error("Get credentials status for endpoint ID = {} failed. Error: {}", endpointId, e.getMessage());
  }
  }

  /**
  * Get application object by specified application name
  */
  private ApplicationDto getApplicationByName(String applicationName) {
  checkAuthorizationAndLogin();

  try {
  List<ApplicationDto> applications = adminClient.getApplications();
  for (ApplicationDto application : applications) {
  if (application.getName().trim().equals(applicationName)) {
  return application;
  }
  }
  } catch (Exception e) {
  LOG.error("Exception has occurred: " + e.getMessage());
  }
  return null;
  }

  /**
  * Checks authorization and log in
  */
  private void checkAuthorizationAndLogin() {
  if (!checkAuth()) {
  adminClient.login(tenantAdminUsername, tenantAdminPassword);
  }
  }

  /**
  * Do authorization check
  * @return true if user is authorized, false otherwise
  */
  private boolean checkAuth() {
  AuthResultDto.Result authResult = null;
  try {
  authResult = adminClient.checkAuth().getAuthResult();
  } catch (Exception e) {
  LOG.error("Exception has occurred: " + e.getMessage());
  }
  return authResult == AuthResultDto.Result.OK;
  }

  }

You can see an more examples of using AdminClient in class KaaAdminManager in Credentials Demo Application from Kaa sample-apps project on GitHub.

Knowing workarounds

  1. Using Kaa Notifications in conjunction with Kaa Data Collection feature. Server sends specific unicast notification to endpoint (using endpoint ID), then endpoint replies sending data with Data Collection feature. Server wait a bit and checks timestamp of the last appender record (typically in database) for your endpoint (by endpoint ID). All messages go asynchronously, so you must select response-wait time according to your real environment.
  2. Using Kaa Data Collection feature only. This method is simpler but has certain performance drawbacks. You can use it if your endpoints must send data to Kaa server by theirs nature (measuring sensors, etc.). Endpoint just sends data to server at regular intervals. When server needs to check if endpoint is "on-line", it query saved data logs (typically database) to get last record by endpoint ID (key hash) and analyze the timestamp field.

* To make effective use of Kaa Data Collection feature, you must add such metadata in settings of selected Log appender (in Kaa Admin UI): "Endpoint key hash" (the same as "Endpoint ID"), "Timestamp". This will automatically add needed fields to every log record received from endpoints.

0
votes

I'm new to Kaa myself and unsure whether there is a method to determine that directly in the SDK, but a work-around is that you could have an extra endpoint from which you periodically send an event to all the other endpoints and expect a reply. When an endpoint does not reply, you know there's a problem.