Skip to content
This repository has been archived by the owner on Oct 9, 2024. It is now read-only.

Commit

Permalink
Added POM, First Implementation of Command & Control
Browse files Browse the repository at this point in the history
  • Loading branch information
switschel committed Dec 16, 2019
1 parent 807a6ad commit a00a85c
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 6 deletions.
101 changes: 101 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.softwareag</groupId>
<artifactId>hono-agent</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<c8y.version>1005.6.1</c8y.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<main.class>honoagent.App</main.class>
<spring-boot-dependencies.version>1.5.7.RELEASE</spring-boot-dependencies.version>
</properties>
<repositories>
<repository>
<id>cumulocity</id>
<layout>default</layout>
<url>http://download.cumulocity.com/maven/repository</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>cumulocity</id>
<layout>default</layout>
<url>http://download.cumulocity.com/maven/repository</url>
</pluginRepository>
</pluginRepositories>

<dependencies>
<dependency>
<groupId>com.nsn.cumulocity.clients-java</groupId>
<artifactId>microservice-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>com.nsn.cumulocity.model</groupId>
<artifactId>device-capability-model</artifactId>
<version>${c8y.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.hono</groupId>
<artifactId>hono-client</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>

<dependencyManagement>
<dependencies>
<!-- microservice api -->
<dependency>
<groupId>com.nsn.cumulocity.clients-java</groupId>
<artifactId>microservice-dependencies</artifactId>
<version>${c8y.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot-dependencies.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.nsn.cumulocity.clients-java</groupId>
<artifactId>microservice-package-maven-plugin</artifactId>
<version>${c8y.version}</version>
<executions>
<execution>
<id>package</id>
<phase>package</phase>
<goals>
<goal>package</goal>
</goals>
<configuration>
<name>${project.artifactId}</name>
<image>${project.artifactId}</image>
<encoding>UTF-8</encoding>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>


</project>
129 changes: 129 additions & 0 deletions src/main/java/honoagent/services/CumulocityClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,25 @@
import com.cumulocity.microservice.subscription.service.MicroserviceSubscriptionsService;
import com.cumulocity.model.DateTimeConverter;
import com.cumulocity.model.ID;
import com.cumulocity.model.idtype.GId;
import com.cumulocity.model.operation.OperationStatus;
import com.cumulocity.rest.representation.event.EventRepresentation;
import com.cumulocity.rest.representation.identity.ExternalIDRepresentation;
import com.cumulocity.rest.representation.inventory.ManagedObjectReferenceRepresentation;
import com.cumulocity.rest.representation.inventory.ManagedObjectRepresentation;
import com.cumulocity.rest.representation.measurement.MeasurementRepresentation;
import com.cumulocity.rest.representation.operation.OperationRepresentation;
import com.cumulocity.rest.representation.tenant.OptionRepresentation;
import com.cumulocity.sdk.client.SDKException;
import com.cumulocity.sdk.client.devicecontrol.DeviceControlApi;
import com.cumulocity.sdk.client.devicecontrol.OperationFilter;
import com.cumulocity.sdk.client.event.EventApi;
import com.cumulocity.sdk.client.identity.IdentityApi;
import com.cumulocity.sdk.client.inventory.InventoryApi;
import com.cumulocity.sdk.client.measurement.MeasurementApi;
import com.cumulocity.sdk.client.notification.Subscriber;
import com.cumulocity.sdk.client.notification.Subscription;
import com.cumulocity.sdk.client.notification.SubscriptionListener;
import com.cumulocity.sdk.client.option.TenantOptionApi;
import com.cumulocity.sdk.client.option.TenantOptionCollection;
import com.fasterxml.jackson.databind.ObjectMapper;
Expand All @@ -25,6 +34,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.swing.text.html.Option;
Expand All @@ -51,6 +61,9 @@ public class CumulocityClient {
@Autowired
MeasurementApi measurementApi;

@Autowired
DeviceControlApi deviceControlApi;

@Autowired
MicroserviceSubscriptionsService subscriptionsService;

Expand All @@ -59,6 +72,14 @@ public class CumulocityClient {
private final String LOGGING_ID = "HONO_LOGGING";
private final String SERIAL_TYPE = "c8y_Serial";

@Value("${C8Y.agentName}")
public String agentName;

@Value("${C8Y.agentId}")
public String agentId;

private ManagedObjectRepresentation agentMor;

final Logger logger = LoggerFactory.getLogger(CumulocityClient.class);

public ExternalIDRepresentation findExternalId(String externalId, String type) {
Expand Down Expand Up @@ -154,6 +175,16 @@ public void createSignalStrengthMeasurement(ManagedObjectRepresentation mor, lon
}
}

public List<ManagedObjectReferenceRepresentation> getParentDevicesByDeviceId(ManagedObjectRepresentation mor) {
try {
List<ManagedObjectReferenceRepresentation> referenceRepresentations = inventoryApi.get(mor.getId()).getDeviceParents().getReferences();
return referenceRepresentations;
} catch (SDKException e) {
logger.error("Error receiving References for Device {}", mor.getId());
return null;
}
}

public List<OptionRepresentation> getTenantOptions(String category) {
List<OptionRepresentation> optionList = new ArrayList<>();
try {
Expand Down Expand Up @@ -194,4 +225,102 @@ public EventRepresentation createEvent(ManagedObjectRepresentation mor, String e
}
}

public ManagedObjectRepresentation findAgentMor() {
ExternalIDRepresentation extId = null;
if (extId == null)
extId = findExternalId(agentId, "c8y_Serial");

if (extId == null) {
logger.info("Creating Agent Object...");
extId = createAgent(agentName, agentId);
logger.info("Agent Object has been created with id {}", extId.getManagedObject().getId().getLong());
}
agentMor = extId.getManagedObject();
return extId.getManagedObject();
}

private ExternalIDRepresentation createAgent(String name, String id) {
logger.info("Creating new Agent with name {} and id {}", name, id);
ManagedObjectRepresentation mor = new ManagedObjectRepresentation();
mor.setType(id);
mor.setName(name);
mor.set(new com.cumulocity.model.Agent());
mor = inventoryApi.create(mor);
ExternalIDRepresentation externalIDRepresentation = new ExternalIDRepresentation();
externalIDRepresentation.setType("c8y_Serial");
externalIDRepresentation.setExternalId(id);
externalIDRepresentation.setManagedObject(mor);
externalIDRepresentation = identityApi.create(externalIDRepresentation);
return externalIDRepresentation;
}

public void processFirstPendingOperation(ManagedObjectRepresentation agentMor) {
OperationFilter filter = new OperationFilter();
filter = filter.byAgent(agentMor.getId().toString());
filter = filter.byStatus(OperationStatus.PENDING);
Iterator<OperationRepresentation> opIt = deviceControlApi.getOperationsByFilter(filter).get().allPages().iterator();
while (opIt.hasNext()) {
OperationRepresentation op = opIt.next();
op.setStatus(OperationStatus.EXECUTING.toString());
deviceControlApi.update(op);
//TODO Call Command & Control
}
}

public void checkAgentAssignment(ManagedObjectRepresentation mor) {
boolean agentAssigned = false;
try {
List<ManagedObjectReferenceRepresentation> referencesList = getParentDevicesByDeviceId(mor);
for (ManagedObjectReferenceRepresentation reference : referencesList) {
ManagedObjectRepresentation parentMor = reference.getManagedObject();
if (agentName.equals(parentMor.getName())) {
agentAssigned = true;
continue;
}
}
} catch (Exception e) {
logger.error("Error on finding MORs", e);
}

// Assign Agent
if (!agentAssigned) {
ManagedObjectRepresentation agentMor = findAgentMor();
assignDeviceToAgent(mor, agentMor);
}
}

public void assignDeviceToAgent(ManagedObjectRepresentation deviceMor, ManagedObjectRepresentation agentMor) {
ManagedObjectReferenceRepresentation child2Ref = new ManagedObjectReferenceRepresentation();
child2Ref.setManagedObject(deviceMor);
inventoryApi.getManagedObjectApi(agentMor.getId()).addChildDevice(child2Ref);
}

public void registerForOperations(GId agentId) {
Subscriber<GId, OperationRepresentation> subscriber = deviceControlApi.getNotificationsSubscriber();
OperationListener<GId, OperationRepresentation> operationListener = new OperationListener<>();
subscriber.subscribe(agentId, operationListener);
}

public class OperationListener<GId, OperationRepresentation>
implements SubscriptionListener<GId, OperationRepresentation> {

@Override
public void onNotification(Subscription<GId> sub, OperationRepresentation operation) {
subscriptionsService.runForEachTenant(() -> {
com.cumulocity.rest.representation.operation.OperationRepresentation op = (com.cumulocity.rest.representation.operation.OperationRepresentation) operation;
logger.info("Operation received {}", op.toString());
op.setStatus(OperationStatus.EXECUTING.toString());
deviceControlApi.update(op);
//TODO Create Hono Command & Control
});

}

@Override
public void onError(Subscription<GId> sub, Throwable throwable) {
logger.info("Error on Operation Listener: {}", throwable.getLocalizedMessage() );

}
}

}
11 changes: 10 additions & 1 deletion src/main/java/honoagent/services/HonoAgent.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.cumulocity.microservice.subscription.model.MicroserviceSubscriptionAddedEvent;
import com.cumulocity.microservice.subscription.service.MicroserviceSubscriptionsService;
import com.cumulocity.rest.representation.inventory.ManagedObjectReferenceRepresentation;
import com.cumulocity.rest.representation.inventory.ManagedObjectRepresentation;
import com.cumulocity.rest.representation.tenant.OptionRepresentation;
import honoagent.config.HonoConfiguration;
Expand Down Expand Up @@ -94,9 +95,13 @@ private void onAdded(MicroserviceSubscriptionAddedEvent event) {
//props.setTrustStorePath("target/config/hono-demo-certs-jar/trusted-certs.pem");
props.setHostnameVerificationRequired(false);
clientFactory = ApplicationClientFactory.create(HonoConnection.newConnection(vertx, props));
ManagedObjectRepresentation agentMor = cumulocityClient.findAgentMor();
cumulocityClient.registerForOperations(agentMor.getId());
connectWithRetry();
cumulocityClient.processFirstPendingOperation(agentMor);
} catch (Exception e) {
logger.error("Error on Initializatzion {}", e.getStackTrace());
logger.error("Error on Initializatzion {}", e.getMessage() );
e.printStackTrace();
}
}

Expand Down Expand Up @@ -191,6 +196,8 @@ private void onDetach(Void event) {
connectWithRetry();
}



/**
* /**
* Handler method for a Message from Hono that was received as telemetry data.
Expand All @@ -206,6 +213,7 @@ private void handleTelemetryMessage(final Message msg) {
JsonObject contentJson = MessageHelper.getJsonPayload(msg);
logger.info("Telemetry received for Device {} with Payload {}", deviceId, content);
ManagedObjectRepresentation mor = cumulocityClient.upsertHonoDevice(deviceId, deviceId, content, DateTime.now());
cumulocityClient.checkAgentAssignment(mor);
cumulocityClient.createEvent(mor, "hono_Telemetry", "Hono Telemetry Message", content, contentJson, DateTime.now());
});
}
Expand All @@ -225,6 +233,7 @@ private void handleEventMessage(final Message msg) {

logger.info("Event received for Device {} with Payload {}", deviceId, content);
ManagedObjectRepresentation mor = cumulocityClient.upsertHonoDevice(deviceId, deviceId, content, DateTime.now());
cumulocityClient.checkAgentAssignment(mor);
cumulocityClient.createEvent(mor, "hono_Event", "Hono Event Message", content, jsonContent, DateTime.now());
});
}
Expand Down
12 changes: 7 additions & 5 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ application.name=hono-agent

logging.file=logs/debug.log

C8Y.baseURL=https://switschel.cumulocity.com
C8Y.bootstrap.register=true
C8Y.bootstrap.tenant=t86833178
C8Y.bootstrap.user=servicebootstrap_hono-agent
C8Y.bootstrap.password=qL5Ft6lV0IH0Ym7Asv8kjVnS4z6Ns3gX
C8Y.baseURL=<UrlToCumulocity>
#C8Y.bootstrap.register=true
#C8Y.bootstrap.tenant=
#C8Y.bootstrap.user=
#C8Y.bootstrap.password=
C8Y.agentId=hono_Agent
C8Y.agentName=hono_Agent

hono.host=hono.eclipse.org
hono.port=15672
Expand Down

0 comments on commit a00a85c

Please sign in to comment.