Initial check in accordance with Parallel IP

This commit is contained in:
Kai Zimmermann
2016-01-21 13:18:55 +01:00
parent c5e4f1139f
commit 7497ab61ed
763 changed files with 114508 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
/bin/
/target/

View File

@@ -0,0 +1,18 @@
# hawkBit Device Simulator
The device simulator handles software update commands from the update server.
## Run
```
java -jar examples/hawkbit-device-simulator/target/hawkbit-device-simulator-*-SNAPSHOT.jar
```
Or:
```
run org.eclipse.hawkbit.simulator.DeviceSimulator
```
## Usage
The device simulator exposes an REST-API which can be used to trigger device creation.
```
http://localhost:8083/start?amount=10
```

View File

@@ -0,0 +1,61 @@
<?xml version="1.0"?>
<!--
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
-->
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipse.hawkbit</groupId>
<version>0.1.0-SNAPSHOT</version>
<artifactId>hawkbit-examples-parent</artifactId>
</parent>
<artifactId>hawkbit-device-simulator</artifactId>
<name>hawkBit :: Device Simulator</name>
<description>Device Management Federation API based simulator</description>
<dependencies>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-dmf-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,32 @@
/**
* 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 org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* The main-method to start the Spring-Boot application.
*
*
*
*/
@SpringBootApplication
public class DeviceSimulator {
/**
* Start the Spring Boot Application.
*
* @param args
* the args
*/
public static void main(final String[] args) {
SpringApplication.run(DeviceSimulator.class, args);
}
}

View File

@@ -0,0 +1,51 @@
/**
* 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 org.eclipse.hawkbit.simulator.amqp.SpSenderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* REST endpoint for controlling the device simulator.
*
*
*
*/
@RestController
public class SimulationController {
@Autowired
private SpSenderService spSenderService;
/**
* The start resource to start a device creation.
*
* @param name
* the name prefix of the generated device naming
* @param amount
* the amount of devices to be created
* @param tenant
* the tenant to create the device to
* @return a response string that devices has been created
*/
@RequestMapping("/start")
String start(@RequestParam(value = "name", defaultValue = "dmfSimulated") final String name,
@RequestParam(value = "amount", defaultValue = "20") final int amount,
@RequestParam(value = "tenant", defaultValue = "DEFAULT") final String tenant) {
for (int i = 0; i < amount; i++) {
spSenderService.createOrUpdateThing(tenant, name + i);
}
return "Updated " + amount + " DMF connected targets!";
}
}

View File

@@ -0,0 +1,144 @@
/**
* 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.amqp;
import java.util.HashMap;
import java.util.Map;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* The spring AMQP configuration to use a AMQP for communication with SP update
* server.
*
*
*
*/
@Configuration
@EnableConfigurationProperties(AmqpProperties.class)
public class AmqpConfiguration {
@Autowired
protected AmqpProperties amqpProperties;
@Autowired
private ConnectionFactory connectionFactory;
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* Create jackson message converter bean.
*
* @return the jackson message converter
*/
@Bean
public MessageConverter jsonMessageConverter() {
final Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
rabbitTemplate.setMessageConverter(jackson2JsonMessageConverter);
return jackson2JsonMessageConverter;
}
/**
* Create the receiver queue from sp. Receive messages from sp.
*
* @return the queue
*/
@Bean
public Queue receiverConnectorQueueFromSp() {
return new Queue(amqpProperties.getReceiverConnectorQueueFromSp(), true, false, false,
getDeadLetterExchangeArgs());
}
/**
* Create the recevier exchange. Sp send messages to this exchange.
*
* @return the exchange
*/
@Bean
public FanoutExchange exchangeQueueToConnector() {
return new FanoutExchange(amqpProperties.getSenderForSpExchange());
}
/**
* Create the Binding
* {@link AmqpConfiguration#receiverConnectorQueueFromSp()} to
* {@link AmqpConfiguration#exchangeQueueToConnector()}.
*
* @return the binding and create the queue and exchange
*/
@Bean
public Binding bindReceiverQueueToSpExchange() {
return BindingBuilder.bind(receiverConnectorQueueFromSp()).to(exchangeQueueToConnector());
}
/**
* Create dead letter queue.
*
* @return the queue
*/
@Bean
public Queue deadLetterQueue() {
return new Queue(amqpProperties.getDeadLetterQueue(), true, false, true);
}
/**
* Create the dead letter fanout exchange.
*
* @return the fanout exchange
*/
@Bean
public FanoutExchange exchangeDeadLetter() {
return new FanoutExchange(amqpProperties.getDeadLetterExchange());
}
/**
* Create the Binding deadLetterQueue to exchangeDeadLetter.
*
* @return the binding
*/
@Bean
public Binding bindDeadLetterQueueToLwm2mExchange() {
return BindingBuilder.bind(deadLetterQueue()).to(exchangeDeadLetter());
}
/**
* Returns the Listener factory.
*
* @return the {@link SimpleMessageListenerContainer} that gets used receive
* AMQP messages
*/
@Bean(name = { "listenerContainerFactory" })
public SimpleRabbitListenerContainerFactory listenerContainerFactory() {
final SimpleRabbitListenerContainerFactory containerFactory = new SimpleRabbitListenerContainerFactory();
containerFactory.setDefaultRequeueRejected(false);
containerFactory.setConnectionFactory(connectionFactory);
return containerFactory;
}
private Map<String, Object> getDeadLetterExchangeArgs() {
final Map<String, Object> args = new HashMap<String, Object>();
args.put("x-dead-letter-exchange", amqpProperties.getDeadLetterExchange());
return args;
}
}

View File

@@ -0,0 +1,60 @@
/**
* 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.amqp;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Bean which holds the necessary properties for configuring the AMQP
* connection.
*
*
*
*/
@ConfigurationProperties("hawkbit.device.simulator.amqp")
public class AmqpProperties {
private String receiverConnectorQueueFromSp;
private String senderForSpExchange;
private String deadLetterQueue;
private String deadLetterExchange;
public String getReceiverConnectorQueueFromSp() {
return receiverConnectorQueueFromSp;
}
public void setReceiverConnectorQueueFromSp(final String receiverConnectorQueueFromSp) {
this.receiverConnectorQueueFromSp = receiverConnectorQueueFromSp;
}
public String getDeadLetterExchange() {
return deadLetterExchange;
}
public void setDeadLetterExchange(final String deadLetterExchange) {
this.deadLetterExchange = deadLetterExchange;
}
public String getDeadLetterQueue() {
return deadLetterQueue;
}
public void setDeadLetterQueue(final String deadLetterQueue) {
this.deadLetterQueue = deadLetterQueue;
}
public String getSenderForSpExchange() {
return senderForSpExchange;
}
public void setSenderForSpExchange(final String senderForSpExchange) {
this.senderForSpExchange = senderForSpExchange;
}
}

View File

@@ -0,0 +1,27 @@
/**
* 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.amqp;
/**
* The constants for the caching.
*
*
*
*/
public final class MessageHandlerCacheConstant {
/**
* The name of the cache.
*/
public static final String CACHE_NAME = "hawkbit.device.simulator.states";
private MessageHandlerCacheConstant() {
}
}

View File

@@ -0,0 +1,102 @@
/**
* 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.amqp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.AbstractJavaTypeMapper;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Abstract class for sender and receiver service.
*
*
*
*/
public class MessageService {
private static final Logger LOGGER = LoggerFactory.getLogger(MessageService.class);
protected RabbitTemplate rabbitTemplate;
protected AmqpProperties amqpProperties;
/**
* Constructor.
*
* @param rabbitTemplate
* the rabbit template
* @param amqpProperties
* the amqp properties
* @param messageConverter
* the message converter
*/
@Autowired
public MessageService(final RabbitTemplate rabbitTemplate, final AmqpProperties amqpProperties) {
this.rabbitTemplate = rabbitTemplate;
this.amqpProperties = amqpProperties;
}
public void setAmqpProperties(final AmqpProperties amqpProperties) {
this.amqpProperties = amqpProperties;
}
public void setRabbitTemplate(final RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}
/**
* Method to call when error emerges.
*
* @param message
* the message that triggered the error
* @param error
* the error
*/
public void logAndThrowMessageError(final Message message, final String error) {
LOGGER.error("Error \"{}\" reported by message {}", error, message.getMessageProperties().getMessageId());
throw new IllegalArgumentException(error);
}
/**
* Convert a message body to a given class and set the message header
* AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME for Jackson converter.
*
* @param message
* which body will converted
* @param clazz
* the body class
* @return the converted body
*/
@SuppressWarnings("unchecked")
public <T> T convertMessage(final Message message, final Class<T> clazz) {
message.getMessageProperties().getHeaders().put(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME,
clazz.getTypeName());
return (T) rabbitTemplate.getMessageConverter().fromMessage(message);
}
/**
* Method to verify if lwm2m header is set.
*
* @param message
* the message with the header
* @param header
* the header to verify
*/
public void checkIfLwm2mHeaderEmpty(final Message message, final String header) {
final Object headerObject = message.getMessageProperties().getHeaders().get(header);
if (null == headerObject) {
logAndThrowMessageError(message, "Header of " + header + "empty.");
}
}
}

View File

@@ -0,0 +1,61 @@
/**
* 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.amqp;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Abstract class for all receiver objects.
*
*
*
*/
public abstract class ReceiverService extends MessageService {
/**
* Constructor.
*
* @param rabbitTemplate
* RabbitTemplate
* @param amqpProperties
* AmqpProperties
* @param messageConverter
* MessageConverter
*/
@Autowired
public ReceiverService(final RabbitTemplate rabbitTemplate, final AmqpProperties amqpProperties) {
super(rabbitTemplate, amqpProperties);
}
/**
* Method to validate if content type is set in the message properties.
*
* @param message
* the message to get validated
*/
protected void checkContentTypeJson(final Message message) {
if (message.getBody().length == 0) {
return;
}
final MessageProperties messageProperties = message.getMessageProperties();
final String headerContentType = (String) messageProperties.getHeaders().get("content-type");
if (null != headerContentType) {
messageProperties.setContentType(headerContentType);
}
final String contentType = messageProperties.getContentType();
if (contentType != null && contentType.contains("json")) {
return;
}
throw new IllegalArgumentException("Content-Type is not JSON compatible");
}
}

View File

@@ -0,0 +1,68 @@
/**
* 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.amqp;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Abstract calls for sender service objects.
*
*
*
*/
public abstract class SenderService extends MessageService {
/**
* Constructor for sender service.
*
* @param rabbitTemplate
* the rabbit template
* @param amqpProperties
* the amqp properties
* @param cacheManager
* the cache manager
*/
@Autowired
public SenderService(final RabbitTemplate rabbitTemplate, final AmqpProperties amqpProperties) {
super(rabbitTemplate, amqpProperties);
}
/**
* Send a message if the message is not null.
*
* @param adress
* the exchange name
* @param message
* the amqp message which will be send if its not null
*/
public void sendMessage(final String adress, final Message message) {
if (message == null) {
return;
}
rabbitTemplate.setExchange(adress);
rabbitTemplate.send(message);
}
/**
* Convert object and message properties to message.
*
* @param object
* to get converted
* @param messageProperties
* to get converted
* @return converted message
*/
public Message convertMessage(final Object object, final MessageProperties messageProperties) {
return rabbitTemplate.getMessageConverter().toMessage(object, messageProperties);
}
}

View File

@@ -0,0 +1,68 @@
/**
* 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.amqp;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* Object for holding attributes for a simulated update for the device
* simulator.
*
*
*
*/
public class SimulatedUpdate implements Serializable {
private static final long serialVersionUID = 1L;
protected final String tenant;
protected final String thingId;
protected final Long actionId;
protected LocalDateTime startCacheTime;
/**
* Constructor of the class.
*
* @param tenant
* the tenant name.
* @param thingId
* the thing id.
* @param actionId
* the action id
* @param softwareModuleId
* software modul id
* @param urls
* the artifact download urls.
*/
public SimulatedUpdate(final String tenant, final String thingId, final Long actionId) {
this.tenant = tenant;
this.thingId = thingId;
this.actionId = actionId;
this.startCacheTime = LocalDateTime.now();
}
public String getTenant() {
return tenant;
}
public String getThingId() {
return thingId;
}
public Long getActionId() {
return actionId;
}
public LocalDateTime getStartCacheTime() {
return startCacheTime;
}
}

View File

@@ -0,0 +1,142 @@
/**
* 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.amqp;
import java.util.Map;
import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
import org.eclipse.hawkbit.dmf.json.model.ActionStatus;
import org.eclipse.hawkbit.dmf.json.model.DownloadAndUpdateRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
/**
* Handle all incoming Messages from SP.
*
*
*
*/
@Component
public class SpReceiverService extends ReceiverService {
private static final Logger LOGGER = LoggerFactory.getLogger(ReceiverService.class);
public static final String SOFTWARE_MODULE_FIRMWARE = "firmware";
private final SpSenderService spSenderService;
/**
* Constructor.
*
* @param rabbitTemplate
* the rabbit template
* @param amqpProperties
* the amqp properties
* @param lwm2mSenderService
* the lwm2mSenderService
* @param spSenderService
* the spSenderService
*/
@Autowired
public SpReceiverService(final RabbitTemplate rabbitTemplate, final AmqpProperties amqpProperties,
final SpSenderService spSenderService) {
super(rabbitTemplate, amqpProperties);
this.spSenderService = spSenderService;
}
/**
* Handle the incoming Message from Queue with the property
* (com.bosch.sp.lwm2m.connector.amqp.receiverConnectorQueueFromSp).
*
* @param message
* the incoming message
* @param type
* the action type
* @param contentType
* the content type in message header
* @param thingId
* the thing id in message header
*/
@RabbitListener(queues = "${hawkbit.device.simulator.amqp.receiverConnectorQueueFromSp}", containerFactory = "listenerContainerFactory")
public void recieveMessageSp(final Message message, @Header(MessageHeaderKey.TYPE) final String type,
@Header(MessageHeaderKey.THING_ID) final String thingId) {
checkContentTypeJson(message);
delegateMessage(message, type, thingId);
}
private void delegateMessage(final Message message, final String type, final String thingId) {
final MessageType messageType = MessageType.valueOf(type);
switch (messageType) {
case EVENT:
handleEventMessage(message, thingId);
break;
default:
LOGGER.info("No valid message type property.");
break;
}
}
private void handleEventMessage(final Message message, final String thingId) {
final Object eventHeader = message.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC);
if (eventHeader == null) {
logAndThrowMessageError(message, "Event Topic is not set");
}
final EventTopic eventTopic = EventTopic.valueOf(eventHeader.toString());
switch (eventTopic) {
case DOWNLOAD_AND_INSTALL:
handleUpdateProcess(message, thingId);
break;
case CANCEL_DOWNLOAD:
handleCancelDownloadAction(message, thingId);
break;
default:
LOGGER.info("No valid event property.");
break;
}
}
private void handleCancelDownloadAction(final Message message, final String thingId) {
final MessageProperties messageProperties = message.getMessageProperties();
final Map<String, Object> headers = messageProperties.getHeaders();
final String tenant = (String) headers.get(MessageHeaderKey.TENANT);
final Long actionId = convertMessage(message, Long.class);
final SimulatedUpdate update = new SimulatedUpdate(tenant, thingId, actionId);
spSenderService.finishUpdateProcess(update, "Simulation canceled");
}
private void handleUpdateProcess(final Message message, final String thingId) {
final MessageProperties messageProperties = message.getMessageProperties();
final Map<String, Object> headers = messageProperties.getHeaders();
final String tenant = (String) headers.get(MessageHeaderKey.TENANT);
final DownloadAndUpdateRequest downloadAndUpdateRequest = convertMessage(message,
DownloadAndUpdateRequest.class);
final Long actionId = downloadAndUpdateRequest.getActionId();
spSenderService.sendActionStatusMessage(tenant, ActionStatus.RUNNING,
"device Simulator retrieved update request. proceeding with simulation.", actionId);
final SimulatedUpdate update = new SimulatedUpdate(tenant, thingId, actionId);
spSenderService.finishUpdateProcess(update, "Simulation complete!");
}
}

View File

@@ -0,0 +1,224 @@
/**
* 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.amqp;
import java.util.Map;
import org.eclipse.hawkbit.dmf.amqp.api.AmqpSettings;
import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
import org.eclipse.hawkbit.dmf.json.model.ActionStatus;
import org.eclipse.hawkbit.dmf.json.model.ActionUpdateStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
/**
* Sender service to send message to SP.
*
*
*
*/
@Service
public class SpSenderService extends SenderService {
private static final Logger LOGGER = LoggerFactory.getLogger(SpSenderService.class);
private final String spExchange;
/**
*
* @param rabbitTemplate
* the rabbit template
* @param amqpProperties
* the amqp properties
*/
@Autowired
public SpSenderService(final RabbitTemplate rabbitTemplate, final AmqpProperties amqpProperties) {
super(rabbitTemplate, amqpProperties);
this.spExchange = AmqpSettings.DMF_EXCHANGE;
}
/**
* Finish the update process. This will send a action status to SP.
*
* @param update
* the simulated update object
* @param description
* a description according the update process
*/
public void finishUpdateProcess(final SimulatedUpdate update, final String description) {
final Message updateResultMessage = createUpdateResultMessage(update, ActionStatus.FINISHED, description);
sendMessage(spExchange, updateResultMessage);
}
/**
* Finish update process with error and send error to SP.
*
* @param update
* the simulated update object
* @param messageDescription
* a description according the update process
*/
public void finishUpdateProcessWithError(final SimulatedUpdate update, final String messageDescription) {
sendErrorgMessage(update, messageDescription);
LOGGER.debug("Update process finished with error \"{}\" reported by thing {}", messageDescription,
update.getThingId());
}
/**
* Send an error message to SP.
*
* @param tenant
* the tenant
* @param messageDescription
* the error message description to send
* @param actionId
* the ID of the action for the error message
*/
public void sendErrorMessage(final String tenant, final String messageDescription, final Long actionId) {
final Message message = createActionStatusMessage(tenant, ActionStatus.ERROR, messageDescription, actionId);
sendMessage(spExchange, message);
}
/**
* Send a warning message to SP.
*
* @param update
* the simulated update object
* @param warningMessage
* a warning description
*/
public void sendWarningMessage(final SimulatedUpdate update, final String warningMessage) {
final Message message = createActionStatusMessage(update, warningMessage, ActionStatus.WARNING);
sendMessage(spExchange, message);
}
/**
* Method to send a action status to SP.
*
* @param tenant
* the tenant
* @param actionStatus
* the action status
* @param actionMessage
* the message to get send
* @param actionId
* the cached value
*/
public void sendActionStatusMessage(final String tenant, final ActionStatus actionStatus,
final String actionMessage, final Long actionId) {
final Message message = createActionStatusMessage(tenant, actionStatus, actionMessage, actionId);
sendMessage(message);
}
/**
* Create new thing created message and send to SP.
*
* @param tenant
* the tenant to create the target
* @param targetId
* the ID of the target to create or update
*/
public void createOrUpdateThing(final String tenant, final String targetId) {
final MessageProperties messagePropertiesForSP = new MessageProperties();
messagePropertiesForSP.setHeader(MessageHeaderKey.TYPE, MessageType.THING_CREATED.name());
messagePropertiesForSP.setHeader(MessageHeaderKey.TENANT, tenant);
messagePropertiesForSP.setHeader(MessageHeaderKey.THING_ID, targetId);
messagePropertiesForSP.setHeader(MessageHeaderKey.SENDER, "simulator");
messagePropertiesForSP.setContentType(MessageProperties.CONTENT_TYPE_JSON);
messagePropertiesForSP.setReplyTo(amqpProperties.getSenderForSpExchange());
final Message convertedMessage = new Message(null, messagePropertiesForSP);
sendMessage(spExchange, convertedMessage);
LOGGER.debug("Created thing created message and send to SP for Thing \"{}\"", targetId);
}
/**
* Send a created message to SP.
*
* @param message
* the message to get send
*/
private void sendMessage(final Message message) {
sendMessage(spExchange, message);
}
/**
* Send error message to SP.
*
* @param context
* the current context
* @param messageDescription
* a description according the update process
*/
private void sendErrorgMessage(final SimulatedUpdate update, final String messageDescription) {
final Message message = createActionStatusMessage(update, messageDescription, ActionStatus.ERROR);
sendMessage(spExchange, message);
}
/**
* Create a action status message.
*
* @param actionStatus
* the ActionStatus
* @param actionMessage
* the message description
* @param actionId
* the action id
* @param cacheValue
* the cacheValue value
*/
private Message createActionStatusMessage(final String tenant, final ActionStatus actionStatus,
final String actionMessage, final Long actionId) {
final MessageProperties messageProperties = new MessageProperties();
final Map<String, Object> headers = messageProperties.getHeaders();
final ActionUpdateStatus actionUpdateStatus = new ActionUpdateStatus();
actionUpdateStatus.setActionStatus(actionStatus);
headers.put(MessageHeaderKey.TYPE, MessageType.EVENT.name());
headers.put(MessageHeaderKey.TENANT, tenant);
headers.put(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.name());
headers.put(MessageHeaderKey.CONTENT_TYPE, MessageProperties.CONTENT_TYPE_JSON);
if (!StringUtils.isEmpty(actionMessage)) {
actionUpdateStatus.getMessage().add(actionMessage);
}
actionUpdateStatus.setActionId(actionId);
return convertMessage(actionUpdateStatus, messageProperties);
}
private Message createUpdateResultMessage(final SimulatedUpdate cacheValue, final ActionStatus actionStatus,
final String updateResultMessage) {
final MessageProperties messageProperties = new MessageProperties();
final Map<String, Object> headers = messageProperties.getHeaders();
final ActionUpdateStatus actionUpdateStatus = new ActionUpdateStatus();
actionUpdateStatus.setActionStatus(actionStatus);
headers.put(MessageHeaderKey.TYPE, MessageType.EVENT.name());
headers.put(MessageHeaderKey.TENANT, cacheValue.getTenant());
headers.put(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.name());
headers.put(MessageHeaderKey.CONTENT_TYPE, MessageProperties.CONTENT_TYPE_JSON);
actionUpdateStatus.getMessage().add(updateResultMessage);
actionUpdateStatus.setActionId(cacheValue.getActionId());
return convertMessage(actionUpdateStatus, messageProperties);
}
private Message createActionStatusMessage(final SimulatedUpdate update, final String messageDescription,
final ActionStatus status) {
final Message sendMessage = createActionStatusMessage(update.getTenant(), status, messageDescription,
update.getActionId());
return sendMessage;
}
}

View File

@@ -0,0 +1,101 @@
#
# 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
#
#########################################################################################
# PUBLIC configuration, i.e. can be changed by users at runtime (defaults provided here)
#########################################################################################
## Configuration for RabbitMQ communication
hawkbit.device.simulator.amqp.receiverConnectorQueueFromSp=sp_connector_receiver
hawkbit.device.simulator.amqp.deadLetterQueue=simulator_deadletter
hawkbit.device.simulator.amqp.deadLetterExchange=simulator.deadletter
hawkbit.device.simulator.amqp.senderForSpExchange=simulator.replyTo
## Configuration for RabbitMQ integration
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtualHost=/
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.dynamic=true
#disable expose jmx beans
spring.jmx.enabled=false
# the context path of the monitor spring actuator which offers following endpoints
# /autoconfig, /beans, /configprops, /dump, /env, /health, /info, /metrics, /mappings, /trace
management.context-path=/system
management.security.enabled=true
management.security.sessions=stateless
# ENDPOINTS
endpoints.autoconfig.id=autoconfig
endpoints.autoconfig.sensitive=true
endpoints.autoconfig.enabled=false
endpoints.beans.id=beans
endpoints.beans.sensitive=true
endpoints.beans.enabled=false
endpoints.configprops.id=configprops
endpoints.configprops.sensitive=true
endpoints.configprops.enabled=true
#endpoints.configprops.keys-to-sanitize=password,secret,key # suffix or regex
endpoints.dump.id=dump
endpoints.dump.sensitive=true
endpoints.dump.enabled=false
endpoints.env.id=env
endpoints.env.sensitive=true
endpoints.env.enabled=true
#endpoints.env.keys-to-sanitize=password,secret,key # suffix or regex
endpoints.health.id=health
endpoints.health.sensitive=true
endpoints.health.enabled=true
endpoints.info.id=info
endpoints.info.sensitive=true
endpoints.info.enabled=true
endpoints.metrics.id=metrics
endpoints.metrics.sensitive=true
endpoints.metrics.enabled=true
endpoints.shutdown.id=shutdown
endpoints.shutdown.sensitive=true
endpoints.shutdown.enabled=false
endpoints.trace.id=trace
endpoints.trace.sensitive=true
endpoints.trace.enabled=true
# HEALTH INDICATORS (previously health.*)
management.health.db.enabled=true
management.health.diskspace.enabled=true
management.health.mongo.enabled=true
management.health.rabbit.enabled=true
management.health.redis.enabled=false
management.health.solr.enabled=false
management.health.diskspace.path=.
management.health.diskspace.threshold=10485760
management.health.status.order=DOWN, OUT_OF_SERVICE, UNKNOWN, UP
# SECURITY (SecurityProperties)
security.user.name=${BASIC_USERNAME:admin}
security.user.password=${BASIC_PASSWORD:admin}
security.user.role=USER
security.require-ssl=false
security.enable-csrf=false
security.basic.enabled=true
security.basic.realm=DeviceSimulator
security.basic.path= /system/**
security.basic.authorize-mode=ROLE
security.filter-order=0
security.headers.xss=false
security.headers.cache=false
security.headers.frame=false
security.headers.content-type=false
security.headers.hsts=all
security.sessions=stateless
security.ignored=
server.port=8083