Teached simulator to download artifacts including SHA1 hash check and
targetToken usage. Signed-off-by: Kai Zimmermann <kai.zimmermann@bosch-si.com>
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
@@ -9,7 +8,8 @@
|
|||||||
http://www.eclipse.org/legal/epl-v10.html
|
http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
|
||||||
-->
|
-->
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
<project
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
<parent>
|
||||||
@@ -133,6 +133,15 @@
|
|||||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.scala-lang</groupId>
|
||||||
|
<artifactId>scala-library</artifactId>
|
||||||
|
<version>2.10.4</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.simulator;
|
package org.eclipse.hawkbit.simulator;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The bean of a simulated device which can be stored in the
|
* The bean of a simulated device which can be stored in the
|
||||||
* {@link DeviceSimulatorRepository} or shown in the UI.
|
* {@link DeviceSimulatorRepository} or shown in the UI.
|
||||||
@@ -22,16 +24,15 @@ public abstract class AbstractSimulatedDevice {
|
|||||||
private Status status;
|
private Status status;
|
||||||
private double progress;
|
private double progress;
|
||||||
private String swversion = "unknown";
|
private String swversion = "unknown";
|
||||||
private ResponseStatus responseStatus = ResponseStatus.SUCCESSFUL;
|
private UpdateStatus updateStatus = new UpdateStatus(ResponseStatus.SUCCESSFUL, "Simulation complete!");
|
||||||
private Protocol protocol = Protocol.DMF_AMQP;
|
private Protocol protocol = Protocol.DMF_AMQP;
|
||||||
|
private String targetSecurityToken;
|
||||||
|
|
||||||
private int nextPollCounterSec;
|
private int nextPollCounterSec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enum definition of the protocol to be used for the simulated device.
|
* Enum definition of the protocol to be used for the simulated device.
|
||||||
*
|
*
|
||||||
* @author Michael Hirsch
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public enum Protocol {
|
public enum Protocol {
|
||||||
/**
|
/**
|
||||||
@@ -69,24 +70,6 @@ public abstract class AbstractSimulatedDevice {
|
|||||||
ERROR;
|
ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The status to response to the hawkbit update server if an simulated
|
|
||||||
* update process should be respond with successful or failure update.
|
|
||||||
*
|
|
||||||
* @author Michael Hirsch
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public enum ResponseStatus {
|
|
||||||
/**
|
|
||||||
* updated has been successful and response the successful update.
|
|
||||||
*/
|
|
||||||
SUCCESSFUL,
|
|
||||||
/**
|
|
||||||
* updated has been not successful and response the error update.
|
|
||||||
*/
|
|
||||||
ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* empty constructor.
|
* empty constructor.
|
||||||
*/
|
*/
|
||||||
@@ -158,12 +141,12 @@ public abstract class AbstractSimulatedDevice {
|
|||||||
this.swversion = swversion;
|
this.swversion = swversion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResponseStatus getResponseStatus() {
|
public UpdateStatus getUpdateStatus() {
|
||||||
return responseStatus;
|
return updateStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setResponseStatus(final ResponseStatus responseStatus) {
|
public void setUpdateStatus(final UpdateStatus updateStatus) {
|
||||||
this.responseStatus = responseStatus;
|
this.updateStatus = updateStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Protocol getProtocol() {
|
public Protocol getProtocol() {
|
||||||
@@ -177,4 +160,13 @@ public abstract class AbstractSimulatedDevice {
|
|||||||
public void setNextPollCounterSec(final int nextPollDelayInSec) {
|
public void setNextPollCounterSec(final int nextPollDelayInSec) {
|
||||||
this.nextPollCounterSec = nextPollDelayInSec;
|
this.nextPollCounterSec = nextPollDelayInSec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTargetSecurityToken() {
|
||||||
|
return targetSecurityToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTargetSecurityToken(final String targetSecurityToken) {
|
||||||
|
this.targetSecurityToken = targetSecurityToken;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.simulator;
|
package org.eclipse.hawkbit.simulator;
|
||||||
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
|
|
||||||
import org.eclipse.hawkbit.simulator.http.ControllerResource;
|
import org.eclipse.hawkbit.simulator.http.ControllerResource;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -18,7 +16,7 @@ import com.jayway.jsonpath.JsonPath;
|
|||||||
import com.jayway.jsonpath.PathNotFoundException;
|
import com.jayway.jsonpath.PathNotFoundException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Michael Hirsch
|
* A simulated device using the DDI API of the hawkBit update server.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DDISimulatedDevice extends AbstractSimulatedDevice {
|
public class DDISimulatedDevice extends AbstractSimulatedDevice {
|
||||||
@@ -26,12 +24,12 @@ public class DDISimulatedDevice extends AbstractSimulatedDevice {
|
|||||||
private static final Logger LOGGER = LoggerFactory.getLogger(DDISimulatedDevice.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(DDISimulatedDevice.class);
|
||||||
|
|
||||||
private final int pollDelaySec;
|
private final int pollDelaySec;
|
||||||
private final ScheduledExecutorService pollthreadpool;
|
|
||||||
private final ControllerResource controllerResource;
|
private final ControllerResource controllerResource;
|
||||||
|
|
||||||
|
private final DeviceSimulatorUpdater deviceUpdater;
|
||||||
|
|
||||||
private volatile boolean removed;
|
private volatile boolean removed;
|
||||||
private volatile Long currentActionId;
|
private volatile Long currentActionId;
|
||||||
private final DeviceSimulatorUpdater deviceUpdater;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param id
|
* @param id
|
||||||
@@ -42,18 +40,14 @@ public class DDISimulatedDevice extends AbstractSimulatedDevice {
|
|||||||
* the delay of the poll interval in sec
|
* the delay of the poll interval in sec
|
||||||
* @param controllerResource
|
* @param controllerResource
|
||||||
* the http controller resource
|
* the http controller resource
|
||||||
* @param pollthreadpool
|
|
||||||
* the threadpool for polling endpoint
|
|
||||||
* @param deviceUpdater
|
* @param deviceUpdater
|
||||||
* the service to update devices
|
* the service to update devices
|
||||||
*/
|
*/
|
||||||
public DDISimulatedDevice(final String id, final String tenant, final int pollDelaySec,
|
public DDISimulatedDevice(final String id, final String tenant, final int pollDelaySec,
|
||||||
final ControllerResource controllerResource, final ScheduledExecutorService pollthreadpool,
|
final ControllerResource controllerResource, final DeviceSimulatorUpdater deviceUpdater) {
|
||||||
final DeviceSimulatorUpdater deviceUpdater) {
|
|
||||||
super(id, tenant, Protocol.DDI_HTTP);
|
super(id, tenant, Protocol.DDI_HTTP);
|
||||||
this.pollDelaySec = pollDelaySec;
|
this.pollDelaySec = pollDelaySec;
|
||||||
this.controllerResource = controllerResource;
|
this.controllerResource = controllerResource;
|
||||||
this.pollthreadpool = pollthreadpool;
|
|
||||||
this.deviceUpdater = deviceUpdater;
|
this.deviceUpdater = deviceUpdater;
|
||||||
setNextPollCounterSec(pollDelaySec);
|
setNextPollCounterSec(pollDelaySec);
|
||||||
}
|
}
|
||||||
@@ -76,27 +70,12 @@ public class DDISimulatedDevice extends AbstractSimulatedDevice {
|
|||||||
final String basePollJson = controllerResource.get(getTenant(), getId());
|
final String basePollJson = controllerResource.get(getTenant(), getId());
|
||||||
try {
|
try {
|
||||||
final String href = JsonPath.parse(basePollJson).read("_links.deploymentBase.href");
|
final String href = JsonPath.parse(basePollJson).read("_links.deploymentBase.href");
|
||||||
final long actionId = Long.parseLong(href.substring(href.lastIndexOf("/") + 1, href.indexOf("?")));
|
final long actionId = Long.parseLong(href.substring(href.lastIndexOf('/') + 1, href.indexOf('?')));
|
||||||
if (currentActionId == null) {
|
if (currentActionId == null) {
|
||||||
final String deploymentJson = controllerResource.getDeployment(getTenant(), getId(), actionId);
|
final String deploymentJson = controllerResource.getDeployment(getTenant(), getId(), actionId);
|
||||||
final String swVersion = JsonPath.parse(deploymentJson).read("deployment.chunks[0].version");
|
final String swVersion = JsonPath.parse(deploymentJson).read("deployment.chunks[0].version");
|
||||||
currentActionId = actionId;
|
currentActionId = actionId;
|
||||||
deviceUpdater.startUpdate(getTenant(), getId(), actionId, swVersion, (device, actionId1) -> {
|
startDdiUpdate(actionId, swVersion);
|
||||||
switch (device.getResponseStatus()) {
|
|
||||||
case SUCCESSFUL:
|
|
||||||
controllerResource.postSuccessFeedback(getTenant(), getId(),
|
|
||||||
actionId1);
|
|
||||||
break;
|
|
||||||
case ERROR:
|
|
||||||
controllerResource.postErrorFeedback(getTenant(), getId(),
|
|
||||||
actionId1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"simulated device has an unknown response status + " + device.getResponseStatus());
|
|
||||||
}
|
|
||||||
currentActionId = null;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} catch (final PathNotFoundException e) {
|
} catch (final PathNotFoundException e) {
|
||||||
// href might not be in the json response, so ignore
|
// href might not be in the json response, so ignore
|
||||||
@@ -106,4 +85,21 @@ public class DDISimulatedDevice extends AbstractSimulatedDevice {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startDdiUpdate(final long actionId, final String swVersion) {
|
||||||
|
deviceUpdater.startUpdate(getTenant(), getId(), actionId, swVersion, null, null, (device, actionId1) -> {
|
||||||
|
switch (device.getUpdateStatus().getResponseStatus()) {
|
||||||
|
case SUCCESSFUL:
|
||||||
|
controllerResource.postSuccessFeedback(getTenant(), getId(), actionId1);
|
||||||
|
break;
|
||||||
|
case ERROR:
|
||||||
|
controllerResource.postErrorFeedback(getTenant(), getId(), actionId1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException("simulated device has an unknown response status + "
|
||||||
|
+ device.getUpdateStatus().getResponseStatus());
|
||||||
|
}
|
||||||
|
currentActionId = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,7 @@
|
|||||||
package org.eclipse.hawkbit.simulator;
|
package org.eclipse.hawkbit.simulator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An simulated device using the DMF API of the hawkbit update server.
|
* A simulated device using the DMF API of the hawkBit update server.
|
||||||
*
|
|
||||||
* @author Michael Hirsch
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class DMFSimulatedDevice extends AbstractSimulatedDevice {
|
public class DMFSimulatedDevice extends AbstractSimulatedDevice {
|
||||||
|
|
||||||
|
|||||||
@@ -8,27 +8,52 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.simulator;
|
package org.eclipse.hawkbit.simulator;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.DigestOutputStream;
|
||||||
|
import java.security.KeyManagementException;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
|
import org.apache.http.conn.ssl.SSLContextBuilder;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
import org.eclipse.hawkbit.dmf.json.model.Artifact;
|
||||||
|
import org.eclipse.hawkbit.dmf.json.model.SoftwareModule;
|
||||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
||||||
|
import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus;
|
||||||
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
||||||
import org.eclipse.hawkbit.simulator.event.InitUpdate;
|
import org.eclipse.hawkbit.simulator.event.InitUpdate;
|
||||||
import org.eclipse.hawkbit.simulator.event.ProgressUpdate;
|
import org.eclipse.hawkbit.simulator.event.ProgressUpdate;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
|
import com.google.common.io.BaseEncoding;
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Michael Hirsch
|
* Update simulation handler.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class DeviceSimulatorUpdater {
|
public class DeviceSimulatorUpdater {
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(DeviceSimulatorUpdater.class);
|
||||||
|
|
||||||
private static final ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(4);
|
private static final ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(4);
|
||||||
|
|
||||||
@@ -54,14 +79,18 @@ public class DeviceSimulatorUpdater {
|
|||||||
* @param actionId
|
* @param actionId
|
||||||
* the actionId from the hawkbit update server to start the
|
* the actionId from the hawkbit update server to start the
|
||||||
* update.
|
* update.
|
||||||
* @param swVersion
|
* @param modules
|
||||||
* the software module version from the hawkbit update server
|
* the software module version from the hawkbit update server
|
||||||
|
* @param swVersion
|
||||||
|
* the software version as static value in case modules is null
|
||||||
|
* @param targetSecurityToken
|
||||||
|
* the target security token for download authentication
|
||||||
* @param callback
|
* @param callback
|
||||||
* the callback which gets called when the simulated update
|
* the callback which gets called when the simulated update
|
||||||
* process has been finished
|
* process has been finished
|
||||||
*/
|
*/
|
||||||
public void startUpdate(final String tenant, final String id, final long actionId, final String swVersion,
|
public void startUpdate(final String tenant, final String id, final long actionId, final String swVersion,
|
||||||
final UpdaterCallback callback) {
|
final List<SoftwareModule> modules, final String targetSecurityToken, final UpdaterCallback callback) {
|
||||||
AbstractSimulatedDevice device = repository.get(tenant, id);
|
AbstractSimulatedDevice device = repository.get(tenant, id);
|
||||||
|
|
||||||
// plug and play - non existing device will be auto created
|
// plug and play - non existing device will be auto created
|
||||||
@@ -70,11 +99,18 @@ public class DeviceSimulatorUpdater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
device.setProgress(0.0);
|
device.setProgress(0.0);
|
||||||
|
|
||||||
|
if (modules == null) {
|
||||||
device.setSwversion(swVersion);
|
device.setSwversion(swVersion);
|
||||||
|
} else {
|
||||||
|
device.setSwversion(modules.stream().map(sm -> sm.getModuleVersion()).collect(Collectors.joining(", ")));
|
||||||
|
}
|
||||||
|
device.setTargetSecurityToken(targetSecurityToken);
|
||||||
eventbus.post(new InitUpdate(device));
|
eventbus.post(new InitUpdate(device));
|
||||||
|
|
||||||
threadPool.schedule(new DeviceSimulatorUpdateThread(device, spSenderService, actionId, eventbus, callback),
|
threadPool.schedule(
|
||||||
2_000, TimeUnit.MILLISECONDS);
|
new DeviceSimulatorUpdateThread(device, spSenderService, actionId, eventbus, callback, modules), 2_000,
|
||||||
|
TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class DeviceSimulatorUpdateThread implements Runnable {
|
private static final class DeviceSimulatorUpdateThread implements Runnable {
|
||||||
@@ -85,38 +121,130 @@ public class DeviceSimulatorUpdater {
|
|||||||
private final long actionId;
|
private final long actionId;
|
||||||
private final EventBus eventbus;
|
private final EventBus eventbus;
|
||||||
private final UpdaterCallback callback;
|
private final UpdaterCallback callback;
|
||||||
|
private final List<SoftwareModule> modules;
|
||||||
|
|
||||||
private DeviceSimulatorUpdateThread(final AbstractSimulatedDevice device, final SpSenderService spSenderService,
|
private DeviceSimulatorUpdateThread(final AbstractSimulatedDevice device, final SpSenderService spSenderService,
|
||||||
final long actionId, final EventBus eventbus, final UpdaterCallback callback) {
|
final long actionId, final EventBus eventbus, final UpdaterCallback callback,
|
||||||
|
final List<SoftwareModule> modules) {
|
||||||
this.device = device;
|
this.device = device;
|
||||||
this.spSenderService = spSenderService;
|
this.spSenderService = spSenderService;
|
||||||
this.actionId = actionId;
|
this.actionId = actionId;
|
||||||
this.eventbus = eventbus;
|
this.eventbus = eventbus;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
|
this.modules = modules;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
if (device.getProgress() <= 0 && modules != null) {
|
||||||
|
device.setUpdateStatus(simulateDownloads(device.getTargetSecurityToken()));
|
||||||
|
if (device.getUpdateStatus().getResponseStatus().equals(ResponseStatus.ERROR)) {
|
||||||
|
callback.updateFinished(device, actionId);
|
||||||
|
eventbus.post(new ProgressUpdate(device));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final double newProgress = device.getProgress() + 0.2;
|
final double newProgress = device.getProgress() + 0.2;
|
||||||
device.setProgress(newProgress);
|
device.setProgress(newProgress);
|
||||||
if (newProgress < 1.0) {
|
if (newProgress < 1.0) {
|
||||||
threadPool.schedule(
|
threadPool.schedule(
|
||||||
new DeviceSimulatorUpdateThread(device, spSenderService, actionId, eventbus, callback),
|
new DeviceSimulatorUpdateThread(device, spSenderService, actionId, eventbus, callback, modules),
|
||||||
rndSleep.nextInt(5_000), TimeUnit.MILLISECONDS);
|
rndSleep.nextInt(5_000), TimeUnit.MILLISECONDS);
|
||||||
} else {
|
} else {
|
||||||
callback.updateFinished(device, actionId);
|
callback.updateFinished(device, actionId);
|
||||||
}
|
}
|
||||||
eventbus.post(new ProgressUpdate(device));
|
eventbus.post(new ProgressUpdate(device));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private UpdateStatus simulateDownloads(final String targetToken) {
|
||||||
|
final List<UpdateStatus> status = new ArrayList<>();
|
||||||
|
|
||||||
|
LOGGER.info("Simulate downloads for {}", device.getId());
|
||||||
|
|
||||||
|
modules.forEach(module -> module.getArtifacts()
|
||||||
|
.forEach(artifact -> handleArtifacts(targetToken, status, artifact)));
|
||||||
|
|
||||||
|
final UpdateStatus result = new UpdateStatus(ResponseStatus.SUCCESSFUL);
|
||||||
|
result.getStatusMessages().add("Simulation complete!");
|
||||||
|
status.forEach(download -> {
|
||||||
|
result.getStatusMessages().addAll(download.getStatusMessages());
|
||||||
|
if (download.getResponseStatus().equals(ResponseStatus.ERROR)) {
|
||||||
|
result.setResponseStatus(ResponseStatus.ERROR);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
LOGGER.info("Download simulations complete for {}", device.getId());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void handleArtifacts(final String targetToken, final List<UpdateStatus> status,
|
||||||
|
final Artifact artifact) {
|
||||||
|
artifact.getUrls().entrySet().forEach(entry -> {
|
||||||
|
switch (entry.getKey()) {
|
||||||
|
case HTTPS:
|
||||||
|
status.add(downloadUrl(entry.getValue(), targetToken, artifact.getHashes().getSha1()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// not supported yet
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static UpdateStatus downloadUrl(final String url, final String targetToken, final String sha1Hash) {
|
||||||
|
LOGGER.debug("Downloading " + url);
|
||||||
|
|
||||||
|
long overallread = 0;
|
||||||
|
try {
|
||||||
|
final CloseableHttpClient httpclient = createHttpClientThatAcceptsAllServerCerts();
|
||||||
|
final HttpGet request = new HttpGet(url);
|
||||||
|
request.addHeader("TargetToken", targetToken);
|
||||||
|
|
||||||
|
final String sha1HashResult;
|
||||||
|
try (final CloseableHttpResponse response = httpclient.execute(request)) {
|
||||||
|
final File tempFile = File.createTempFile("uploadFile", null);
|
||||||
|
final MessageDigest md = MessageDigest.getInstance("SHA-1");
|
||||||
|
|
||||||
|
try (final DigestOutputStream dos = new DigestOutputStream(new FileOutputStream(tempFile), md)) {
|
||||||
|
overallread = ByteStreams.copy(response.getEntity().getContent(), dos);
|
||||||
|
sha1HashResult = BaseEncoding.base16().lowerCase().encode(md.digest());
|
||||||
|
} finally {
|
||||||
|
tempFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sha1Hash.equals(sha1HashResult)) {
|
||||||
|
final String message = "Download " + url + " failed with SHA1 hash missmatch (Expected: " + sha1Hash
|
||||||
|
+ " but got: " + sha1HashResult + ")";
|
||||||
|
LOGGER.debug(message);
|
||||||
|
return new UpdateStatus(ResponseStatus.ERROR, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException | KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
|
||||||
|
LOGGER.error("Failed to download {}", url, e);
|
||||||
|
return new UpdateStatus(ResponseStatus.ERROR, "Failed to download " + url + ": " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
final String message = "Downloaded " + url + " (" + overallread + " bytes)";
|
||||||
|
LOGGER.debug(message);
|
||||||
|
return new UpdateStatus(ResponseStatus.SUCCESSFUL, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CloseableHttpClient createHttpClientThatAcceptsAllServerCerts()
|
||||||
|
throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
|
||||||
|
final SSLContextBuilder builder = new SSLContextBuilder();
|
||||||
|
builder.loadTrustMaterial(null, (chain, authType) -> true);
|
||||||
|
final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
|
||||||
|
return HttpClients.custom().setSSLSocketFactory(sslsf).build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback interface which is called when the simulated update process has
|
* Callback interface which is called when the simulated update process has
|
||||||
* been finished and the caller of starting the simulated update process can
|
* been finished and the caller of starting the simulated update process can
|
||||||
* send the result to the hawkbit update server back.
|
* send the result to the hawkBit update server back. *
|
||||||
*
|
|
||||||
* @author Michael Hirsch
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface UpdaterCallback {
|
public interface UpdaterCallback {
|
||||||
|
|||||||
@@ -26,9 +26,6 @@ import com.google.common.eventbus.EventBus;
|
|||||||
/**
|
/**
|
||||||
* Poll time trigger which executes the {@link DDISimulatedDevice#poll()} every
|
* Poll time trigger which executes the {@link DDISimulatedDevice#poll()} every
|
||||||
* second.
|
* second.
|
||||||
*
|
|
||||||
* @author Michael Hirsch
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class NextPollTimeController {
|
public class NextPollTimeController {
|
||||||
@@ -59,8 +56,7 @@ public class NextPollTimeController {
|
|||||||
|
|
||||||
devices.forEach(device -> {
|
devices.forEach(device -> {
|
||||||
int nextCounter = device.getNextPollCounterSec() - 1;
|
int nextCounter = device.getNextPollCounterSec() - 1;
|
||||||
if (nextCounter < 0) {
|
if (nextCounter < 0 && device instanceof DDISimulatedDevice) {
|
||||||
if (device instanceof DDISimulatedDevice) {
|
|
||||||
try {
|
try {
|
||||||
pollService.submit(() -> ((DDISimulatedDevice) device).poll());
|
pollService.submit(() -> ((DDISimulatedDevice) device).poll());
|
||||||
} catch (final IllegalStateException e) {
|
} catch (final IllegalStateException e) {
|
||||||
@@ -68,7 +64,7 @@ public class NextPollTimeController {
|
|||||||
}
|
}
|
||||||
nextCounter = ((DDISimulatedDevice) device).getPollDelaySec();
|
nextCounter = ((DDISimulatedDevice) device).getPollDelaySec();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
device.setNextPollCounterSec(nextCounter);
|
device.setNextPollCounterSec(nextCounter);
|
||||||
});
|
});
|
||||||
eventBus.post(new NextPollCounterUpdate(devices));
|
eventBus.post(new NextPollCounterUpdate(devices));
|
||||||
|
|||||||
@@ -9,8 +9,6 @@
|
|||||||
package org.eclipse.hawkbit.simulator;
|
package org.eclipse.hawkbit.simulator;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
|
|
||||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
||||||
import org.eclipse.hawkbit.simulator.http.ControllerResource;
|
import org.eclipse.hawkbit.simulator.http.ControllerResource;
|
||||||
@@ -24,15 +22,9 @@ import feign.Logger;
|
|||||||
/**
|
/**
|
||||||
* The simulated device factory to create either {@link DMFSimulatedDevice} or
|
* The simulated device factory to create either {@link DMFSimulatedDevice} or
|
||||||
* {@link DDISimulatedDevice#}.
|
* {@link DDISimulatedDevice#}.
|
||||||
*
|
|
||||||
* @author Michael Hirsch
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class SimulatedDeviceFactory {
|
public class SimulatedDeviceFactory {
|
||||||
|
|
||||||
private static final ScheduledExecutorService pollThreadPool = Executors.newScheduledThreadPool(4);
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeviceSimulatorUpdater deviceUpdater;
|
private DeviceSimulatorUpdater deviceUpdater;
|
||||||
|
|
||||||
@@ -47,7 +39,8 @@ public class SimulatedDeviceFactory {
|
|||||||
* the protocol of the device
|
* the protocol of the device
|
||||||
* @return the created simulated device
|
* @return the created simulated device
|
||||||
*/
|
*/
|
||||||
public AbstractSimulatedDevice createSimulatedDevice(final String id, final String tenant, final Protocol protocol) {
|
public AbstractSimulatedDevice createSimulatedDevice(final String id, final String tenant,
|
||||||
|
final Protocol protocol) {
|
||||||
return createSimulatedDevice(id, tenant, protocol, 30, null, null);
|
return createSimulatedDevice(id, tenant, protocol, 30, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +73,7 @@ public class SimulatedDeviceFactory {
|
|||||||
final ControllerResource controllerResource = Feign.builder().logger(new Logger.ErrorLogger())
|
final ControllerResource controllerResource = Feign.builder().logger(new Logger.ErrorLogger())
|
||||||
.requestInterceptor(new GatewayTokenInterceptor(gatewayToken)).logLevel(Logger.Level.BASIC)
|
.requestInterceptor(new GatewayTokenInterceptor(gatewayToken)).logLevel(Logger.Level.BASIC)
|
||||||
.target(ControllerResource.class, baseEndpoint.toString());
|
.target(ControllerResource.class, baseEndpoint.toString());
|
||||||
return new DDISimulatedDevice(id, tenant, pollDelaySec, controllerResource, pollThreadPool, deviceUpdater);
|
return new DDISimulatedDevice(id, tenant, pollDelaySec, controllerResource, deviceUpdater);
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Protocol " + protocol + " unknown");
|
throw new IllegalArgumentException("Protocol " + protocol + " unknown");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.simulator;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update status of the simulated update.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class UpdateStatus {
|
||||||
|
private ResponseStatus responseStatus = ResponseStatus.SUCCESSFUL;
|
||||||
|
private final List<String> statusMessages = new ArrayList<>();
|
||||||
|
|
||||||
|
public UpdateStatus(final ResponseStatus responseStatus) {
|
||||||
|
this.responseStatus = responseStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UpdateStatus(final ResponseStatus responseStatus, final String message) {
|
||||||
|
this(responseStatus);
|
||||||
|
statusMessages.add(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResponseStatus getResponseStatus() {
|
||||||
|
return responseStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResponseStatus(final ResponseStatus responseStatus) {
|
||||||
|
this.responseStatus = responseStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getStatusMessages() {
|
||||||
|
return statusMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The status to response to the hawkBit update server if an simulated
|
||||||
|
* update process should be respond with successful or failure update.
|
||||||
|
*/
|
||||||
|
public enum ResponseStatus {
|
||||||
|
/**
|
||||||
|
* updated has been successful and response the successful update.
|
||||||
|
*/
|
||||||
|
SUCCESSFUL,
|
||||||
|
/**
|
||||||
|
* updated has been not successful and response the error update.
|
||||||
|
*/
|
||||||
|
ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -25,6 +25,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.messaging.handler.annotation.Header;
|
import org.springframework.messaging.handler.annotation.Header;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle all incoming Messages from hawkBit update server.
|
* Handle all incoming Messages from hawkBit update server.
|
||||||
*
|
*
|
||||||
@@ -109,7 +111,7 @@ public class SpReceiverService extends ReceiverService {
|
|||||||
final Long actionId = convertMessage(message, Long.class);
|
final Long actionId = convertMessage(message, Long.class);
|
||||||
|
|
||||||
final SimulatedUpdate update = new SimulatedUpdate(tenant, thingId, actionId);
|
final SimulatedUpdate update = new SimulatedUpdate(tenant, thingId, actionId);
|
||||||
spSenderService.finishUpdateProcess(update, "Simulation canceled");
|
spSenderService.finishUpdateProcess(update, Lists.newArrayList("Simulation canceled"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleUpdateProcess(final Message message, final String thingId) {
|
private void handleUpdateProcess(final Message message, final String thingId) {
|
||||||
@@ -120,19 +122,20 @@ public class SpReceiverService extends ReceiverService {
|
|||||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = convertMessage(message,
|
final DownloadAndUpdateRequest downloadAndUpdateRequest = convertMessage(message,
|
||||||
DownloadAndUpdateRequest.class);
|
DownloadAndUpdateRequest.class);
|
||||||
final Long actionId = downloadAndUpdateRequest.getActionId();
|
final Long actionId = downloadAndUpdateRequest.getActionId();
|
||||||
|
final String targetSecurityToken = downloadAndUpdateRequest.getTargetSecurityToken();
|
||||||
|
|
||||||
deviceUpdater.startUpdate(tenant, thingId, actionId,
|
deviceUpdater.startUpdate(tenant, thingId, actionId, null, downloadAndUpdateRequest.getSoftwareModules(),
|
||||||
downloadAndUpdateRequest.getSoftwareModules().get(0).getModuleVersion(), (device, actionId1) -> {
|
targetSecurityToken, (device, actionId1) -> {
|
||||||
switch (device.getResponseStatus()) {
|
switch (device.getUpdateStatus().getResponseStatus()) {
|
||||||
case SUCCESSFUL:
|
case SUCCESSFUL:
|
||||||
spSenderService.finishUpdateProcess(
|
spSenderService.finishUpdateProcess(
|
||||||
new SimulatedUpdate(device.getTenant(), device.getId(), actionId1),
|
new SimulatedUpdate(device.getTenant(), device.getId(), actionId1),
|
||||||
"Simulation complete!");
|
device.getUpdateStatus().getStatusMessages());
|
||||||
break;
|
break;
|
||||||
case ERROR:
|
case ERROR:
|
||||||
spSenderService.finishUpdateProcessWithError(
|
spSenderService.finishUpdateProcessWithError(
|
||||||
new SimulatedUpdate(device.getTenant(), device.getId(), actionId1),
|
new SimulatedUpdate(device.getTenant(), device.getId(), actionId1),
|
||||||
"Simulation complete with error!");
|
device.getUpdateStatus().getStatusMessages());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.simulator.amqp;
|
package org.eclipse.hawkbit.simulator.amqp;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.dmf.amqp.api.AmqpSettings;
|
import org.eclipse.hawkbit.dmf.amqp.api.AmqpSettings;
|
||||||
@@ -23,13 +24,9 @@ import org.springframework.amqp.core.MessageProperties;
|
|||||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sender service to send message to SP.
|
* Sender service to send messages to update server.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class SpSenderService extends SenderService {
|
public class SpSenderService extends SenderService {
|
||||||
@@ -59,8 +56,9 @@ public class SpSenderService extends SenderService {
|
|||||||
* @param description
|
* @param description
|
||||||
* a description according the update process
|
* a description according the update process
|
||||||
*/
|
*/
|
||||||
public void finishUpdateProcess(final SimulatedUpdate update, final String description) {
|
public void finishUpdateProcess(final SimulatedUpdate update, final List<String> updateResultMessages) {
|
||||||
final Message updateResultMessage = createUpdateResultMessage(update, ActionStatus.FINISHED, description);
|
final Message updateResultMessage = createUpdateResultMessage(update, ActionStatus.FINISHED,
|
||||||
|
updateResultMessages);
|
||||||
sendMessage(spExchange, updateResultMessage);
|
sendMessage(spExchange, updateResultMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,9 +70,9 @@ public class SpSenderService extends SenderService {
|
|||||||
* @param messageDescription
|
* @param messageDescription
|
||||||
* a description according the update process
|
* a description according the update process
|
||||||
*/
|
*/
|
||||||
public void finishUpdateProcessWithError(final SimulatedUpdate update, final String messageDescription) {
|
public void finishUpdateProcessWithError(final SimulatedUpdate update, final List<String> updateResultMessages) {
|
||||||
sendErrorgMessage(update, messageDescription);
|
sendErrorgMessage(update, updateResultMessages);
|
||||||
LOGGER.debug("Update process finished with error \"{}\" reported by thing {}", messageDescription,
|
LOGGER.debug("Update process finished with error \"{}\" reported by thing {}", updateResultMessages,
|
||||||
update.getThingId());
|
update.getThingId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,8 +86,8 @@ public class SpSenderService extends SenderService {
|
|||||||
* @param actionId
|
* @param actionId
|
||||||
* the ID of the action for the error message
|
* the ID of the action for the error message
|
||||||
*/
|
*/
|
||||||
public void sendErrorMessage(final String tenant, final String messageDescription, final Long actionId) {
|
public void sendErrorMessage(final String tenant, final List<String> updateResultMessages, final Long actionId) {
|
||||||
final Message message = createActionStatusMessage(tenant, ActionStatus.ERROR, messageDescription, actionId);
|
final Message message = createActionStatusMessage(tenant, ActionStatus.ERROR, updateResultMessages, actionId);
|
||||||
sendMessage(spExchange, message);
|
sendMessage(spExchange, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,8 +99,8 @@ public class SpSenderService extends SenderService {
|
|||||||
* @param warningMessage
|
* @param warningMessage
|
||||||
* a warning description
|
* a warning description
|
||||||
*/
|
*/
|
||||||
public void sendWarningMessage(final SimulatedUpdate update, final String warningMessage) {
|
public void sendWarningMessage(final SimulatedUpdate update, final List<String> updateResultMessages) {
|
||||||
final Message message = createActionStatusMessage(update, warningMessage, ActionStatus.WARNING);
|
final Message message = createActionStatusMessage(update, updateResultMessages, ActionStatus.WARNING);
|
||||||
sendMessage(spExchange, message);
|
sendMessage(spExchange, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,8 +117,8 @@ public class SpSenderService extends SenderService {
|
|||||||
* the cached value
|
* the cached value
|
||||||
*/
|
*/
|
||||||
public void sendActionStatusMessage(final String tenant, final ActionStatus actionStatus,
|
public void sendActionStatusMessage(final String tenant, final ActionStatus actionStatus,
|
||||||
final String actionMessage, final Long actionId) {
|
final List<String> updateResultMessages, final Long actionId) {
|
||||||
final Message message = createActionStatusMessage(tenant, actionStatus, actionMessage, actionId);
|
final Message message = createActionStatusMessage(tenant, actionStatus, updateResultMessages, actionId);
|
||||||
sendMessage(message);
|
sendMessage(message);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -162,11 +160,11 @@ public class SpSenderService extends SenderService {
|
|||||||
*
|
*
|
||||||
* @param context
|
* @param context
|
||||||
* the current context
|
* the current context
|
||||||
* @param messageDescription
|
* @param updateResultMessages
|
||||||
* a description according the update process
|
* a list of descriptions according the update process
|
||||||
*/
|
*/
|
||||||
private void sendErrorgMessage(final SimulatedUpdate update, final String messageDescription) {
|
private void sendErrorgMessage(final SimulatedUpdate update, final List<String> updateResultMessages) {
|
||||||
final Message message = createActionStatusMessage(update, messageDescription, ActionStatus.ERROR);
|
final Message message = createActionStatusMessage(update, updateResultMessages, ActionStatus.ERROR);
|
||||||
sendMessage(spExchange, message);
|
sendMessage(spExchange, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +181,7 @@ public class SpSenderService extends SenderService {
|
|||||||
* the cacheValue value
|
* the cacheValue value
|
||||||
*/
|
*/
|
||||||
private Message createActionStatusMessage(final String tenant, final ActionStatus actionStatus,
|
private Message createActionStatusMessage(final String tenant, final ActionStatus actionStatus,
|
||||||
final String actionMessage, final Long actionId) {
|
final List<String> updateResultMessages, final Long actionId) {
|
||||||
final MessageProperties messageProperties = new MessageProperties();
|
final MessageProperties messageProperties = new MessageProperties();
|
||||||
final Map<String, Object> headers = messageProperties.getHeaders();
|
final Map<String, Object> headers = messageProperties.getHeaders();
|
||||||
final ActionUpdateStatus actionUpdateStatus = new ActionUpdateStatus();
|
final ActionUpdateStatus actionUpdateStatus = new ActionUpdateStatus();
|
||||||
@@ -192,15 +190,14 @@ public class SpSenderService extends SenderService {
|
|||||||
headers.put(MessageHeaderKey.TENANT, tenant);
|
headers.put(MessageHeaderKey.TENANT, tenant);
|
||||||
headers.put(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.name());
|
headers.put(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.name());
|
||||||
headers.put(MessageHeaderKey.CONTENT_TYPE, MessageProperties.CONTENT_TYPE_JSON);
|
headers.put(MessageHeaderKey.CONTENT_TYPE, MessageProperties.CONTENT_TYPE_JSON);
|
||||||
if (!StringUtils.isEmpty(actionMessage)) {
|
actionUpdateStatus.getMessage().addAll(updateResultMessages);
|
||||||
actionUpdateStatus.getMessage().add(actionMessage);
|
|
||||||
}
|
|
||||||
actionUpdateStatus.setActionId(actionId);
|
actionUpdateStatus.setActionId(actionId);
|
||||||
return convertMessage(actionUpdateStatus, messageProperties);
|
return convertMessage(actionUpdateStatus, messageProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Message createUpdateResultMessage(final SimulatedUpdate cacheValue, final ActionStatus actionStatus,
|
private Message createUpdateResultMessage(final SimulatedUpdate cacheValue, final ActionStatus actionStatus,
|
||||||
final String updateResultMessage) {
|
final List<String> updateResultMessages) {
|
||||||
final MessageProperties messageProperties = new MessageProperties();
|
final MessageProperties messageProperties = new MessageProperties();
|
||||||
final Map<String, Object> headers = messageProperties.getHeaders();
|
final Map<String, Object> headers = messageProperties.getHeaders();
|
||||||
final ActionUpdateStatus actionUpdateStatus = new ActionUpdateStatus();
|
final ActionUpdateStatus actionUpdateStatus = new ActionUpdateStatus();
|
||||||
@@ -209,14 +206,14 @@ public class SpSenderService extends SenderService {
|
|||||||
headers.put(MessageHeaderKey.TENANT, cacheValue.getTenant());
|
headers.put(MessageHeaderKey.TENANT, cacheValue.getTenant());
|
||||||
headers.put(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.name());
|
headers.put(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.name());
|
||||||
headers.put(MessageHeaderKey.CONTENT_TYPE, MessageProperties.CONTENT_TYPE_JSON);
|
headers.put(MessageHeaderKey.CONTENT_TYPE, MessageProperties.CONTENT_TYPE_JSON);
|
||||||
actionUpdateStatus.getMessage().add(updateResultMessage);
|
actionUpdateStatus.getMessage().addAll(updateResultMessages);
|
||||||
actionUpdateStatus.setActionId(cacheValue.getActionId());
|
actionUpdateStatus.setActionId(cacheValue.getActionId());
|
||||||
return convertMessage(actionUpdateStatus, messageProperties);
|
return convertMessage(actionUpdateStatus, messageProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Message createActionStatusMessage(final SimulatedUpdate update, final String messageDescription,
|
private Message createActionStatusMessage(final SimulatedUpdate update, final List<String> updateResultMessages,
|
||||||
final ActionStatus status) {
|
final ActionStatus status) {
|
||||||
return createActionStatusMessage(update.getTenant(), status, messageDescription, update.getActionId());
|
return createActionStatusMessage(update.getTenant(), status, updateResultMessages, update.getActionId());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice;
|
|||||||
* Event definition object which is published if the simulated device updated
|
* Event definition object which is published if the simulated device updated
|
||||||
* its update progress.
|
* its update progress.
|
||||||
*
|
*
|
||||||
* @author Michael Hirsch
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class ProgressUpdate {
|
public class ProgressUpdate {
|
||||||
|
|
||||||
|
|||||||
@@ -8,21 +8,19 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.simulator.ui;
|
package org.eclipse.hawkbit.simulator.ui;
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice;
|
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice;
|
||||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
||||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.ResponseStatus;
|
|
||||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Status;
|
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Status;
|
||||||
import org.eclipse.hawkbit.simulator.DeviceSimulatorRepository;
|
import org.eclipse.hawkbit.simulator.DeviceSimulatorRepository;
|
||||||
import org.eclipse.hawkbit.simulator.SimulatedDeviceFactory;
|
import org.eclipse.hawkbit.simulator.SimulatedDeviceFactory;
|
||||||
|
import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus;
|
||||||
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
||||||
import org.eclipse.hawkbit.simulator.event.InitUpdate;
|
import org.eclipse.hawkbit.simulator.event.InitUpdate;
|
||||||
import org.eclipse.hawkbit.simulator.event.NextPollCounterUpdate;
|
import org.eclipse.hawkbit.simulator.event.NextPollCounterUpdate;
|
||||||
import org.eclipse.hawkbit.simulator.event.ProgressUpdate;
|
import org.eclipse.hawkbit.simulator.event.ProgressUpdate;
|
||||||
import org.eclipse.hawkbit.simulator.ui.GenerateDialog.GenerateDialogCallback;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
@@ -53,8 +51,6 @@ import com.vaadin.ui.renderers.ProgressBarRenderer;
|
|||||||
* current simulated devices in a grid with their current status and update
|
* current simulated devices in a grid with their current status and update
|
||||||
* progress.
|
* progress.
|
||||||
*
|
*
|
||||||
* @author Michael Hirsch
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@SpringView(name = "")
|
@SpringView(name = "")
|
||||||
public class SimulatorView extends VerticalLayout implements View {
|
public class SimulatorView extends VerticalLayout implements View {
|
||||||
@@ -153,18 +149,12 @@ public class SimulatorView extends VerticalLayout implements View {
|
|||||||
@Subscribe
|
@Subscribe
|
||||||
public void pollCounterUpdate(final NextPollCounterUpdate update) {
|
public void pollCounterUpdate(final NextPollCounterUpdate update) {
|
||||||
final List<AbstractSimulatedDevice> devices = update.getDevices();
|
final List<AbstractSimulatedDevice> devices = update.getDevices();
|
||||||
this.getUI().access(new Runnable() {
|
this.getUI().access(() -> devices.forEach(device -> {
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
devices.forEach(device -> {
|
|
||||||
final BeanItem<AbstractSimulatedDevice> item = beanContainer.getItem(device.getId());
|
final BeanItem<AbstractSimulatedDevice> item = beanContainer.getItem(device.getId());
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
item.getItemProperty("nextPollCounterSec").setValue(device.getNextPollCounterSec());
|
item.getItemProperty("nextPollCounterSec").setValue(device.getNextPollCounterSec());
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -176,10 +166,7 @@ public class SimulatorView extends VerticalLayout implements View {
|
|||||||
@Subscribe
|
@Subscribe
|
||||||
public void initUpdate(final InitUpdate update) {
|
public void initUpdate(final InitUpdate update) {
|
||||||
final AbstractSimulatedDevice device = update.getDevice();
|
final AbstractSimulatedDevice device = update.getDevice();
|
||||||
this.getUI().access(new Runnable() {
|
this.getUI().access(() -> {
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
final BeanItem<AbstractSimulatedDevice> item = beanContainer.getItem(device.getId());
|
final BeanItem<AbstractSimulatedDevice> item = beanContainer.getItem(device.getId());
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
item.getItemProperty("progress").setValue(device.getProgress());
|
item.getItemProperty("progress").setValue(device.getProgress());
|
||||||
@@ -187,7 +174,6 @@ public class SimulatorView extends VerticalLayout implements View {
|
|||||||
item.getItemProperty("swversion").setValue(device.getSwversion());
|
item.getItemProperty("swversion").setValue(device.getSwversion());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,14 +186,12 @@ public class SimulatorView extends VerticalLayout implements View {
|
|||||||
@Subscribe
|
@Subscribe
|
||||||
public void progessUpdate(final ProgressUpdate update) {
|
public void progessUpdate(final ProgressUpdate update) {
|
||||||
final AbstractSimulatedDevice device = update.getDevice();
|
final AbstractSimulatedDevice device = update.getDevice();
|
||||||
this.getUI().access(new Runnable() {
|
this.getUI().access(() -> {
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
final BeanItem<AbstractSimulatedDevice> item = beanContainer.getItem(device.getId());
|
final BeanItem<AbstractSimulatedDevice> item = beanContainer.getItem(device.getId());
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
item.getItemProperty("progress").setValue(device.getProgress());
|
item.getItemProperty("progress").setValue(device.getProgress());
|
||||||
if (device.getProgress() >= 1) {
|
if (device.getProgress() >= 1) {
|
||||||
switch (device.getResponseStatus()) {
|
switch (device.getUpdateStatus().getResponseStatus()) {
|
||||||
case SUCCESSFUL:
|
case SUCCESSFUL:
|
||||||
item.getItemProperty("status").setValue(Status.FINISH);
|
item.getItemProperty("status").setValue(Status.FINISH);
|
||||||
break;
|
break;
|
||||||
@@ -222,7 +206,6 @@ public class SimulatorView extends VerticalLayout implements View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,17 +229,14 @@ public class SimulatorView extends VerticalLayout implements View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void openGenerateDialog() {
|
private void openGenerateDialog() {
|
||||||
UI.getCurrent().addWindow(new GenerateDialog(new GenerateDialogCallback() {
|
UI.getCurrent().addWindow(
|
||||||
@Override
|
new GenerateDialog((namePrefix, tenant, amount, pollDelay, basePollUrl, gatewayToken, protocol) -> {
|
||||||
public void okButton(final String namePrefix, final String tenant, final int amount, final int pollDelay,
|
|
||||||
final URL basePollUrl, final String gatewayToken, final Protocol protocol) {
|
|
||||||
for (int index = 0; index < amount; index++) {
|
for (int index = 0; index < amount; index++) {
|
||||||
final String deviceId = namePrefix + index;
|
final String deviceId = namePrefix + index;
|
||||||
beanContainer.addBean(repository.add(deviceFactory.createSimulatedDevice(deviceId,
|
beanContainer.addBean(repository.add(deviceFactory.createSimulatedDevice(deviceId,
|
||||||
tenant.toLowerCase(), protocol, pollDelay, basePollUrl, gatewayToken)));
|
tenant.toLowerCase(), protocol, pollDelay, basePollUrl, gatewayToken)));
|
||||||
spSenderService.createOrUpdateThing(tenant, deviceId);
|
spSenderService.createOrUpdateThing(tenant, deviceId);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user