如何检测端点(KAA SDK)是否从应用程序连接到 KAA 服务器
How to detect weather the endpoint (KAA SDK) is connected to KAA server or not from application
是否有任何机制或方法或步骤来检测端点(KAA SDK)从应用程序到 KAA 服务器的连接。
如果不是,那我们如何远程识别故障设备??或者我们如何识别在现场部署设备后无法与 KAA 服务器通信的设备?
如何才能达到这一要求,释放物联网的力量??
我自己是 Kaa 的新手,不确定是否有一种方法可以直接在 SDK 中确定它,但是一个解决方法是您可以有一个额外的端点,您可以从中定期向所有其他端点并期待回复。当端点没有回复时,您就知道有问题了。
如果您的端点在连接到 Kaa 服务器时遇到一些问题,将会发生 "failover"。
因此您必须定义自己的故障转移策略并为您的 Kaa 客户端设置它。每次发生故障转移时都会调用策略的 onFialover()
方法。
下面您可以看到 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);
}
}
}
}
更新 (2016/10/28)
从服务器端您可以检查端点凭据状态,如以下代码中的方法checkCredentialsStatus()
所示。状态 IN_USE
表明端点至少有一次成功的连接尝试。
不幸的是,在当前的 Kaa 版本中,没有办法直接检查端点是否连接到服务器。我在代码示例之后描述它们。
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;
}
}
您可以在 class KaaAdminManager in Credentials Demo Application from Kaa sample-apps project GitHub 中查看更多使用 AdminClient
的示例。
了解解决方法
- 使用 Kaa Notifications in conjunction with Kaa Data Collection 功能。服务器向端点发送特定的单播通知(使用端点 ID),然后端点回复发送具有数据收集功能的数据。服务器稍等一下,然后检查端点的最后一个附加程序记录(通常在数据库中)的时间戳(通过端点 ID)。所有消息都是异步发送的,因此您必须 select 根据您的真实环境响应等待时间。
- 仅使用 Kaa Data Collection 功能。这种方法比较简单,但有一定的性能缺陷。如果您的端点必须根据其性质(测量传感器等)将数据发送到 Kaa 服务器,则可以使用它。端点只是定期向服务器发送数据。当服务器需要检查端点是否为 "on-line" 时,它会查询保存的数据日志(通常是数据库)以通过端点 ID(密钥哈希)获取最后一条记录并分析时间戳字段。
* 为了有效使用 Kaa Data Collection 功能,您必须在 selected Log appender 的设置中添加此类元数据(在 Kaa Admin UI): "Endpoint key hash" (等同于 "Endpoint ID"), "Timestamp"。这将自动向从端点接收的每条日志记录添加所需的字段。
是否有任何机制或方法或步骤来检测端点(KAA SDK)从应用程序到 KAA 服务器的连接。
如果不是,那我们如何远程识别故障设备??或者我们如何识别在现场部署设备后无法与 KAA 服务器通信的设备?
如何才能达到这一要求,释放物联网的力量??
我自己是 Kaa 的新手,不确定是否有一种方法可以直接在 SDK 中确定它,但是一个解决方法是您可以有一个额外的端点,您可以从中定期向所有其他端点并期待回复。当端点没有回复时,您就知道有问题了。
如果您的端点在连接到 Kaa 服务器时遇到一些问题,将会发生 "failover"。
因此您必须定义自己的故障转移策略并为您的 Kaa 客户端设置它。每次发生故障转移时都会调用策略的 onFialover()
方法。
下面您可以看到 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);
}
}
}
}
更新 (2016/10/28)
从服务器端您可以检查端点凭据状态,如以下代码中的方法checkCredentialsStatus()
所示。状态 IN_USE
表明端点至少有一次成功的连接尝试。
不幸的是,在当前的 Kaa 版本中,没有办法直接检查端点是否连接到服务器。我在代码示例之后描述它们。
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;
}
}
您可以在 class KaaAdminManager in Credentials Demo Application from Kaa sample-apps project GitHub 中查看更多使用 AdminClient
的示例。
了解解决方法
- 使用 Kaa Notifications in conjunction with Kaa Data Collection 功能。服务器向端点发送特定的单播通知(使用端点 ID),然后端点回复发送具有数据收集功能的数据。服务器稍等一下,然后检查端点的最后一个附加程序记录(通常在数据库中)的时间戳(通过端点 ID)。所有消息都是异步发送的,因此您必须 select 根据您的真实环境响应等待时间。
- 仅使用 Kaa Data Collection 功能。这种方法比较简单,但有一定的性能缺陷。如果您的端点必须根据其性质(测量传感器等)将数据发送到 Kaa 服务器,则可以使用它。端点只是定期向服务器发送数据。当服务器需要检查端点是否为 "on-line" 时,它会查询保存的数据日志(通常是数据库)以通过端点 ID(密钥哈希)获取最后一条记录并分析时间戳字段。
* 为了有效使用 Kaa Data Collection 功能,您必须在 selected Log appender 的设置中添加此类元数据(在 Kaa Admin UI): "Endpoint key hash" (等同于 "Endpoint ID"), "Timestamp"。这将自动向从端点接收的每条日志记录添加所需的字段。