Skip to content

Commit

Permalink
Feature/28681: Improve Error Messages (#675)
Browse files Browse the repository at this point in the history
* improve error log when tag was not found

* fix WritingSchema error case when tag is not present

* fix after rebase
  • Loading branch information
DC2-DanielKrueger authored Dec 12, 2024
1 parent d52e472 commit eb5dc42
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 140 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,16 @@ public class OpcUaClientWrapper {

private final String adapterId;
public final @NotNull OpcUaClient client;
public final @NotNull Optional<JsonToOpcUAConverter> jsonToOpcUAConverter;
public final @NotNull Optional<JsonSchemaGenerator> jsonSchemaGenerator;
public final @NotNull JsonToOpcUAConverter jsonToOpcUAConverter;
public final @NotNull JsonSchemaGenerator jsonSchemaGenerator;
public final @NotNull OpcUaSubscriptionLifecycle opcUaSubscriptionLifecycle;

public OpcUaClientWrapper(
final @NotNull String adapterId,
final @NotNull OpcUaClient client,
final @NotNull OpcUaSubscriptionLifecycle opcUaSubscriptionLifecycle,
final @NotNull Optional<JsonToOpcUAConverter> jsonToOpcUAConverter,
final @NotNull Optional<JsonSchemaGenerator> jsonSchemaGenerator) {
final @NotNull JsonToOpcUAConverter jsonToOpcUAConverter,
final @NotNull JsonSchemaGenerator jsonSchemaGenerator) {
this.adapterId = adapterId;
this.client = client;
this.jsonToOpcUAConverter = jsonToOpcUAConverter;
Expand All @@ -88,14 +88,7 @@ public void createMqttPayloadJsonSchema(
final @NotNull OpcuaTag tag, final @NotNull TagSchemaCreationOutput output) {

final String nodeId = tag.getDefinition().getNode();
jsonSchemaGenerator.ifPresentOrElse(gen -> gen.createJsonSchema(NodeId.parse(nodeId))
.whenComplete((jsonNode, throwable) -> {
if (throwable != null) {
output.fail(throwable, null);
} else {
output.finish(jsonNode);
}
}), () -> output.fail(new IllegalArgumentException("Missing JSON Schema generator"), null));
jsonSchemaGenerator.createJsonSchema(NodeId.parse(nodeId), output);
}

public void discoverValues(
Expand Down Expand Up @@ -145,23 +138,19 @@ public void write(
final NodeId nodeId = NodeId.parse(opcuaTag.getDefinition().getNode());

try {
jsonToOpcUAConverter.map(conv -> conv.convertToOpcUAValue(opcUAWritePayload.getValue(), nodeId))
.ifPresentOrElse(opcUaObject -> {
final Variant variant = new Variant(opcUaObject);
final DataValue dataValue = new DataValue(variant, null, null);
final CompletableFuture<StatusCode> writeFuture = client.writeValue(nodeId, dataValue);
writeFuture.whenComplete((statusCode, throwable) -> {
if (throwable != null) {
log.error("Exception while writing to opcua node '{}'",
writeContext.getTagName(),
throwable);
writingOutput.fail(throwable, null);
} else {
log.info("Wrote '{}' to nodeId={}", variant, nodeId);
writingOutput.finish();
}
});
}, () -> writingOutput.fail("JsonToOpcUaConverter not available"));
final Object opcuaObject = jsonToOpcUAConverter.convertToOpcUAValue(opcUAWritePayload.getValue(), nodeId);
final Variant variant = new Variant(opcuaObject);
final DataValue dataValue = new DataValue(variant, null, null);
final CompletableFuture<StatusCode> writeFuture = client.writeValue(nodeId, dataValue);
writeFuture.whenComplete((statusCode, throwable) -> {
if (throwable != null) {
log.error("Exception while writing to opcua node '{}'", writeContext.getTagName(), throwable);
writingOutput.fail(throwable, null);
} else {
log.info("Wrote '{}' to nodeId={}", variant, nodeId);
writingOutput.finish();
}
});
} catch (final Exception e) {
writingOutput.fail(e, null);
}
Expand Down Expand Up @@ -281,8 +270,7 @@ public void onSessionActive(final @NotNull UaSession session) {
});

return opcUaClient.connect().thenCompose(uaClient -> {
final OpcUaSubscriptionLifecycle opcUaSubscriptionLifecycle = new OpcUaSubscriptionLifecycle(
opcUaClient,
final OpcUaSubscriptionLifecycle opcUaSubscriptionLifecycle = new OpcUaSubscriptionLifecycle(opcUaClient,
adapterId,
protocolId,
protocolAdapterMetricsService,
Expand All @@ -294,17 +282,16 @@ public void onSessionActive(final @NotNull UaSession session) {
opcUaClient.getSubscriptionManager().addSubscriptionListener(opcUaSubscriptionLifecycle);

try {
final Optional<JsonToOpcUAConverter> jsonToOpcUAConverterOpt =
Optional.of(new JsonToOpcUAConverter(opcUaClient));
final Optional<JsonSchemaGenerator> jsonSchemaGeneratorOpt =
Optional.of(new JsonSchemaGenerator(opcUaClient, new ObjectMapper()));
final JsonToOpcUAConverter jsonToOpcUAConverter = new JsonToOpcUAConverter(opcUaClient);
final JsonSchemaGenerator jsonSchemaGenerator =
new JsonSchemaGenerator(opcUaClient, new ObjectMapper());
if (adapterConfig.getOpcuaToMqttConfig() != null) {
return opcUaSubscriptionLifecycle.subscribeAll(northboundsMappings)
.thenApply(ignored -> new OpcUaClientWrapper(adapterId,
opcUaClient,
opcUaSubscriptionLifecycle,
jsonToOpcUAConverterOpt,
jsonSchemaGeneratorOpt));
jsonToOpcUAConverter,
jsonSchemaGenerator));
} else {
return CompletableFuture.completedFuture(null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,17 +88,16 @@ public void start(
synchronized (this) {
if (opcUaClientWrapper == null) {
try {
OpcUaClientWrapper.createAndConnect(
adapterId,
OpcUaClientWrapper.createAndConnect(adapterId,
adapterConfig,
tags, northboundMappings,
tags,
northboundMappings,
protocolAdapterState,
moduleServices.eventService(),
moduleServices.adapterPublishService(),
adapterInformation.getProtocolId(),
protocolAdapterMetricsService,
output)
.thenApply(wrapper -> {
output).thenApply(wrapper -> {
protocolAdapterState.setConnectionStatus(CONNECTED);
output.startedSuccessfully();
opcUaClientWrapper = wrapper;
Expand Down Expand Up @@ -188,8 +187,14 @@ public void createTagSchema(
.findFirst()
.ifPresentOrElse(def -> opcUaClientWrapperTemp.createMqttPayloadJsonSchema((OpcuaTag) def, output),
() -> {
//FIXME needs logging
output.adapterNotStarted();
log.warn(
"The tag '{}' was not found during creation of schema for tags on remote plc. Available tags: {}",
input.getTagName(),
tags);
output.tagNotFound(String.format(
"The tag '%s' was not found during creation of schema for tags on remote plc. Available tags: '%s'",
input.getTagName(),
tags));
});
} else {
output.adapterNotStarted();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public class OpcUaSpecificAdapterConfig implements ProtocolSpecificAdapterConfig
@JsonProperty(value = "opcuaToMqtt")
@ModuleConfigField(title = "OPC UA To MQTT Config",
description = "The configuration for a data stream from OPC UA to MQTT")
private final @Nullable OpcUaToMqttConfig opcuaToMqttConfig;
private final @NotNull OpcUaToMqttConfig opcuaToMqttConfig;

@JsonCreator
public OpcUaSpecificAdapterConfig(
Expand All @@ -85,7 +85,6 @@ public OpcUaSpecificAdapterConfig(
this.tls = requireNonNullElse(tls, new Tls(false, null, null));
this.opcuaToMqttConfig =
Objects.requireNonNullElseGet(opcuaToMqttConfig, () -> new OpcUaToMqttConfig(null, null));

this.security = requireNonNullElse(security, new Security(SecPolicy.DEFAULT));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,9 @@ public boolean equals(final @Nullable Object o) {
public int hashCode() {
return node.hashCode();
}

@Override
public @NotNull String toString() {
return "OpcuaTagDefinition{" + "node='" + node + '\'' + '}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import com.hivemq.adapter.sdk.api.schema.TagSchemaCreationOutput;
import org.eclipse.milo.opcua.binaryschema.AbstractCodec;
import org.eclipse.milo.opcua.sdk.client.DataTypeTreeBuilder;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
Expand Down Expand Up @@ -56,26 +57,31 @@ public JsonSchemaGenerator(final @NotNull OpcUaClient client, final @NotNull Obj
this.builtinJsonSchema = new BuiltinJsonSchema();
}

public @NotNull CompletableFuture<@NotNull JsonNode> createJsonSchema(final @NotNull NodeId destinationNodeId) {
public void createJsonSchema(
final @NotNull NodeId destinationNodeId, final @NotNull TagSchemaCreationOutput output) {
final CompletableFuture<UaVariableNode> variableNodeFuture =
client.getAddressSpace().getVariableNodeAsync(destinationNodeId);
return variableNodeFuture.thenApply(uaVariableNode -> {
variableNodeFuture.whenComplete((uaVariableNode, throwable) -> {
if (throwable != null) {
// no node was found for the given nodeId
output.tagNotFound("No node was found for the given node id '" + destinationNodeId + "'");
return;
}
final NodeId dataTypeNodeId = uaVariableNode.getDataType();
final DataTypeTree.DataType dataType = tree.getDataType(dataTypeNodeId);
if (dataType == null) {
throw new RuntimeException("No data type was found in the DataTypeTree for node id '" +
dataTypeNodeId +
"'");
output.fail("Unable to find the data type for the given node id '" + destinationNodeId + "'.");
return;
}
final BuiltinDataType builtinType = tree.getBuiltinType(dataType.getNodeId());
if (builtinType != BuiltinDataType.ExtensionObject) {
return builtinJsonSchema.getJsonSchema(builtinType);
output.finish(builtinJsonSchema.getJsonSchema(builtinType));
} else {
final NodeId binaryEncodingId = dataType.getBinaryEncodingId();
if (binaryEncodingId == null) {
throw new RuntimeException("No encoding was present for data type: '" + dataType + "'");
output.fail("No encoding was present for the complex data type: '" + dataType + "'.");
}
return jsonSchemaFromNodeId(binaryEncodingId);
output.finish(jsonSchemaFromNodeId(binaryEncodingId));
}
});
}
Expand Down

0 comments on commit eb5dc42

Please sign in to comment.