Search in sources :

Example 16 with Command

use of org.eclipse.hono.client.command.Command in project hono by eclipse.

the class LoraProtocolAdapter method handleTenantTimeout.

private void handleTenantTimeout(final Message<String> msg) {
    final String tenantId = msg.body();
    log.debug("check command subscriptions on timeout of tenant [{}]", tenantId);
    final Span span = TracingHelper.buildSpan(tracer, null, "check command subscriptions on tenant timeout", getClass().getSimpleName()).withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT).start();
    TracingHelper.setDeviceTags(span, tenantId, null);
    // check if tenant still exists
    getTenantConfiguration(tenantId, span.context()).recover(thr -> {
        if (thr instanceof TenantDisabledOrNotRegisteredException) {
            log.debug("tenant [{}] disabled or removed, removing corresponding command consumers", tenantId);
            span.log("tenant disabled or removed, corresponding command consumers will be closed");
            @SuppressWarnings("rawtypes") final List<Future> consumerCloseFutures = new LinkedList<>();
            for (final var iter = commandSubscriptions.entrySet().iterator(); iter.hasNext(); ) {
                final var entry = iter.next();
                if (entry.getKey().getTenant().equals(tenantId)) {
                    final CommandConsumer commandConsumer = entry.getValue().one();
                    consumerCloseFutures.add(commandConsumer.close(span.context()));
                    iter.remove();
                }
            }
            return CompositeFuture.join(consumerCloseFutures).mapEmpty();
        } else {
            return Future.failedFuture(thr);
        }
    }).onFailure(thr -> TracingHelper.logError(span, thr)).onComplete(ar -> span.finish());
}
Also used : HttpURLConnection(java.net.HttpURLConnection) LoraProviderMalformedPayloadException(org.eclipse.hono.adapter.lora.providers.LoraProviderMalformedPayloadException) LoggerFactory(org.slf4j.LoggerFactory) Router(io.vertx.ext.web.Router) Tag(io.opentracing.tag.Tag) RoutingContext(io.vertx.ext.web.RoutingContext) Tags(io.opentracing.tag.Tags) Map(java.util.Map) Pair(org.eclipse.hono.util.Pair) Fields(io.opentracing.log.Fields) JsonObject(io.vertx.core.json.JsonObject) TracingHelper(org.eclipse.hono.tracing.TracingHelper) TenantServiceBasedX509Authentication(org.eclipse.hono.adapter.auth.device.TenantServiceBasedX509Authentication) ChainAuthHandler(io.vertx.ext.web.handler.ChainAuthHandler) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) CommandContext(org.eclipse.hono.client.command.CommandContext) MetricsTags(org.eclipse.hono.service.metric.MetricsTags) Message(io.vertx.core.eventbus.Message) EventConstants(org.eclipse.hono.util.EventConstants) StringTag(io.opentracing.tag.StringTag) Future(io.vertx.core.Future) HonoBasicAuthHandler(org.eclipse.hono.adapter.http.HonoBasicAuthHandler) Device(org.eclipse.hono.auth.Device) Objects(java.util.Objects) List(java.util.List) Buffer(io.vertx.core.buffer.Buffer) X509AuthHandler(org.eclipse.hono.adapter.http.X509AuthHandler) CommandConsumer(org.eclipse.hono.client.command.CommandConsumer) Optional(java.util.Optional) Span(io.opentracing.Span) UsernamePasswordCredentials(org.eclipse.hono.adapter.auth.device.UsernamePasswordCredentials) CommandEndpoint(org.eclipse.hono.util.CommandEndpoint) HttpContext(org.eclipse.hono.service.http.HttpContext) Json(io.vertx.core.json.Json) LoraProvider(org.eclipse.hono.adapter.lora.providers.LoraProvider) WebClient(io.vertx.ext.web.client.WebClient) Command(org.eclipse.hono.client.command.Command) ClientErrorException(org.eclipse.hono.client.ClientErrorException) TenantDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.TenantDisabledOrNotRegisteredException) Constants(org.eclipse.hono.util.Constants) ArrayList(java.util.ArrayList) TracingHandler(org.eclipse.hono.service.http.TracingHandler) CompositeFuture(io.vertx.core.CompositeFuture) StatusCodeMapper(org.eclipse.hono.client.StatusCodeMapper) HttpUtils(org.eclipse.hono.service.http.HttpUtils) LinkedList(java.util.LinkedList) UsernamePasswordAuthProvider(org.eclipse.hono.adapter.auth.device.UsernamePasswordAuthProvider) Logger(org.slf4j.Logger) Direction(org.eclipse.hono.service.metric.MetricsTags.Direction) AbstractVertxBasedHttpProtocolAdapter(org.eclipse.hono.adapter.http.AbstractVertxBasedHttpProtocolAdapter) Promise(io.vertx.core.Promise) ServerErrorException(org.eclipse.hono.client.ServerErrorException) Sample(io.micrometer.core.instrument.Timer.Sample) TenantObject(org.eclipse.hono.util.TenantObject) SpanContext(io.opentracing.SpanContext) HttpRequest(io.vertx.ext.web.client.HttpRequest) DeviceCredentialsAuthProvider(org.eclipse.hono.adapter.auth.device.DeviceCredentialsAuthProvider) X509AuthProvider(org.eclipse.hono.adapter.auth.device.X509AuthProvider) HttpMethod(io.vertx.core.http.HttpMethod) HttpProtocolAdapterProperties(org.eclipse.hono.adapter.http.HttpProtocolAdapterProperties) SubjectDnCredentials(org.eclipse.hono.adapter.auth.device.SubjectDnCredentials) CommandConsumer(org.eclipse.hono.client.command.CommandConsumer) Future(io.vertx.core.Future) CompositeFuture(io.vertx.core.CompositeFuture) TenantDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.TenantDisabledOrNotRegisteredException) Span(io.opentracing.Span) LinkedList(java.util.LinkedList)

Example 17 with Command

use of org.eclipse.hono.client.command.Command in project hono by eclipse.

the class LoraProtocolAdapterTest method handleCommandForLNS.

/**
 * Verifies that an uplink message triggers a command subscription.
 */
@SuppressWarnings("unchecked")
@Test
public void handleCommandForLNS() {
    givenATelemetrySenderForAnyTenant();
    final LoraProvider providerMock = getLoraProviderMock();
    final HttpServerRequest request = mock(HttpServerRequest.class);
    final HttpContext httpContext = newHttpContext();
    when(httpContext.request()).thenReturn(request);
    final CommandEndpoint commandEndpoint = new CommandEndpoint();
    commandEndpoint.setHeaders(Map.of("my-header", "my-header-value"));
    commandEndpoint.setUri("https://my-server.com/commands/{{deviceId}}/send");
    setGatewayDeviceCommandEndpoint(commandEndpoint);
    final CommandConsumer commandConsumer = mock(CommandConsumer.class);
    when(commandConsumer.close(any())).thenReturn(Future.succeededFuture());
    when(commandConsumerFactory.createCommandConsumer(any(), any(), any(), any(), any())).thenReturn(Future.succeededFuture(commandConsumer));
    adapter.handleProviderRoute(httpContext, providerMock);
    final ArgumentCaptor<Handler<CommandContext>> handlerArgumentCaptor = VertxMockSupport.argumentCaptorHandler();
    verify(commandConsumerFactory).createCommandConsumer(eq(TEST_TENANT_ID), eq(TEST_GATEWAY_ID), handlerArgumentCaptor.capture(), isNull(), any());
    final Handler<CommandContext> commandHandler = handlerArgumentCaptor.getValue();
    final Command command = mock(Command.class);
    when(command.getTenant()).thenReturn(TEST_TENANT_ID);
    when(command.getDeviceId()).thenReturn(TEST_DEVICE_ID);
    when(command.getGatewayId()).thenReturn(TEST_GATEWAY_ID);
    when(command.getPayload()).thenReturn(Buffer.buffer("bumlux"));
    when(command.isValid()).thenReturn(true);
    final CommandContext commandContext = mock(CommandContext.class);
    when(commandContext.getCommand()).thenReturn(command);
    when(commandContext.getTracingSpan()).thenReturn(processMessageSpan);
    final JsonObject json = new JsonObject().put("my-payload", "bumlux");
    final LoraCommand loraCommand = new LoraCommand(json, "https://my-server.com/commands/deviceId/send");
    when(providerMock.getCommand(any(), any(), any(), any())).thenReturn(loraCommand);
    when(providerMock.getDefaultHeaders()).thenReturn(Map.of("my-provider-header", "my-provider-header-value"));
    final HttpRequest<Buffer> httpClientRequest = mock(HttpRequest.class, withSettings().defaultAnswer(RETURNS_SELF));
    final HttpResponse<Buffer> httpResponse = mock(HttpResponse.class);
    when(httpResponse.statusCode()).thenReturn(HttpURLConnection.HTTP_NO_CONTENT);
    when(httpClientRequest.sendJson(any(JsonObject.class))).thenReturn(Future.succeededFuture(httpResponse));
    when(webClient.postAbs(anyString())).thenReturn(httpClientRequest);
    commandHandler.handle(commandContext);
    verify(webClient, times(1)).postAbs("https://my-server.com/commands/deviceId/send");
    verify(httpClientRequest, times(1)).putHeader("my-header", "my-header-value");
    verify(httpClientRequest, times(1)).putHeader("my-provider-header", "my-provider-header-value");
    verify(httpClientRequest, times(1)).sendJson(json);
}
Also used : Buffer(io.vertx.core.buffer.Buffer) LoraProvider(org.eclipse.hono.adapter.lora.providers.LoraProvider) CommandContext(org.eclipse.hono.client.command.CommandContext) HttpServerRequest(io.vertx.core.http.HttpServerRequest) HttpContext(org.eclipse.hono.service.http.HttpContext) TracingHandler(org.eclipse.hono.service.http.TracingHandler) Handler(io.vertx.core.Handler) JsonObject(io.vertx.core.json.JsonObject) Command(org.eclipse.hono.client.command.Command) CommandEndpoint(org.eclipse.hono.util.CommandEndpoint) CommandConsumer(org.eclipse.hono.client.command.CommandConsumer) Test(org.junit.jupiter.api.Test)

Example 18 with Command

use of org.eclipse.hono.client.command.Command in project hono by eclipse.

the class CommandSubscriptionTest method testSubscriptionSucceedsForAuthenticatedDevice.

/**
 * Verifies that an authenticated device can successfully subscribe for commands
 * targeted at itself using all variants of topic names.
 *
 * @param endpointName The endpoint name used in the topic.
 * @param reqPartName The request part name used in the topic.
 * @param qos The requested QoS.
 */
@ParameterizedTest
@MethodSource("endpointAndReqNamesWithQoS")
public void testSubscriptionSucceedsForAuthenticatedDevice(final String endpointName, final String reqPartName, final MqttQoS qos) {
    final Command command = mock(Command.class);
    when(command.isTargetedAtGateway()).thenReturn(false);
    when(command.getTenant()).thenReturn(device.getTenantId());
    when(command.getGatewayOrDeviceId()).thenReturn(device.getDeviceId());
    when(command.getRequestId()).thenReturn("requestId");
    when(command.getName()).thenReturn("doSomething");
    // WHEN subscribing to commands using explicit topic
    MqttTopicSubscription mqttTopicSubscription = new MqttTopicSubscriptionImpl(String.format("%s/tenant/device/%s/#", endpointName, reqPartName), qos);
    CommandSubscription subscription = CommandSubscription.fromTopic(mqttTopicSubscription, device);
    assertThat(subscription).isNotNull();
    assertThat(subscription.getTenant()).isEqualTo("tenant");
    assertThat(subscription.getDeviceId()).isEqualTo("device");
    assertThat(subscription.getEndpoint()).isEqualTo(endpointName);
    assertThat(subscription.getRequestPart()).isEqualTo(reqPartName);
    assertThat(subscription.getQos()).isEqualTo(qos);
    // THEN the command topic does include both the tenant and device ID
    assertThat(subscription.getCommandPublishTopic(command)).isEqualTo(String.format("%s/%s/%s/%s/requestId/doSomething", endpointName, device.getTenantId(), device.getDeviceId(), reqPartName));
    // WHEN subscribing to commands including tenant only
    mqttTopicSubscription = new MqttTopicSubscriptionImpl(String.format("%s/tenant//%s/#", endpointName, reqPartName), qos);
    subscription = CommandSubscription.fromTopic(mqttTopicSubscription, device);
    assertThat(subscription).isNotNull();
    assertThat(subscription.getTenant()).isEqualTo("tenant");
    assertThat(subscription.getDeviceId()).isEqualTo("device");
    assertThat(subscription.getEndpoint()).isEqualTo(endpointName);
    assertThat(subscription.getRequestPart()).isEqualTo(reqPartName);
    assertThat(subscription.getQos()).isEqualTo(qos);
    // THEN the command topic does include the tenant as well
    assertThat(subscription.getCommandPublishTopic(command)).isEqualTo(String.format("%s/%s//%s/requestId/doSomething", endpointName, device.getTenantId(), reqPartName));
    // WHEN subscribing to commands including device ID only
    mqttTopicSubscription = new MqttTopicSubscriptionImpl(String.format("%s//device/%s/#", endpointName, reqPartName), qos);
    subscription = CommandSubscription.fromTopic(mqttTopicSubscription, device);
    assertThat(subscription).isNotNull();
    assertThat(subscription.getTenant()).isEqualTo("tenant");
    assertThat(subscription.getDeviceId()).isEqualTo("device");
    assertThat(subscription.getEndpoint()).isEqualTo(endpointName);
    assertThat(subscription.getRequestPart()).isEqualTo(reqPartName);
    assertThat(subscription.getQos()).isEqualTo(qos);
    // THEN the command topic does include the device ID as well
    assertThat(subscription.getCommandPublishTopic(command)).isEqualTo(String.format("%s//%s/%s/requestId/doSomething", endpointName, device.getDeviceId(), reqPartName));
    // WHEN subscribing to commands using implicit topic
    mqttTopicSubscription = new MqttTopicSubscriptionImpl(String.format("%s///%s/#", endpointName, reqPartName), qos);
    subscription = CommandSubscription.fromTopic(mqttTopicSubscription, device);
    assertThat(subscription).isNotNull();
    assertThat(subscription.getTenant()).isEqualTo("tenant");
    assertThat(subscription.getDeviceId()).isEqualTo("device");
    assertThat(subscription.getEndpoint()).isEqualTo(endpointName);
    assertThat(subscription.getRequestPart()).isEqualTo(reqPartName);
    assertThat(subscription.getQos()).isEqualTo(qos);
    // THEN the command topic does not include tenant nor device ID
    assertThat(subscription.getCommandPublishTopic(command)).isEqualTo(String.format("%s///%s/requestId/doSomething", endpointName, reqPartName));
    // using a tenant other than the tenant that the device belongs to should fail
    mqttTopicSubscription = new MqttTopicSubscriptionImpl(String.format("%s/otherTenant/device/%s/#", endpointName, reqPartName), qos);
    assertThat(CommandSubscription.fromTopic(mqttTopicSubscription, device)).isNull();
}
Also used : MqttTopicSubscriptionImpl(io.vertx.mqtt.impl.MqttTopicSubscriptionImpl) Command(org.eclipse.hono.client.command.Command) MqttTopicSubscription(io.vertx.mqtt.MqttTopicSubscription) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 19 with Command

use of org.eclipse.hono.client.command.Command in project hono by eclipse.

the class CommandSubscriptionTest method testSubscriptionSucceedsForAuthenticatedGateway.

/**
 * Verifies that an authenticated gateway can successfully subscribe for commands
 * targeted at one of devices that it is authorized to act on behalf of.
 *
 * @param endpointName The endpoint name used in the topic.
 * @param reqPartName The request part name used in the topic.
 * @param qos The requested QoS.
 */
@ParameterizedTest
@MethodSource("endpointAndReqNamesWithQoS")
public void testSubscriptionSucceedsForAuthenticatedGateway(final String endpointName, final String reqPartName, final MqttQoS qos) {
    final String gatewayManagedDeviceId = "gatewayManagedDevice";
    final Command command = mock(Command.class);
    when(command.isTargetedAtGateway()).thenReturn(true);
    when(command.getTenant()).thenReturn(gw.getTenantId());
    when(command.getGatewayId()).thenReturn(gw.getDeviceId());
    when(command.getGatewayOrDeviceId()).thenReturn(gw.getDeviceId());
    when(command.getDeviceId()).thenReturn(gatewayManagedDeviceId);
    when(command.getRequestId()).thenReturn("requestId");
    when(command.getName()).thenReturn("doSomething");
    // WHEN subscribing to commands for a specific device omitting tenant
    MqttTopicSubscription mqttTopicSubscription = new MqttTopicSubscriptionImpl(String.format("%s//%s/%s/#", endpointName, gatewayManagedDeviceId, reqPartName), qos);
    CommandSubscription subscription = CommandSubscription.fromTopic(mqttTopicSubscription, gw);
    assertThat(subscription).isNotNull();
    assertThat(subscription.getTenant()).isEqualTo(gw.getTenantId());
    assertThat(subscription.getDeviceId()).isEqualTo(gatewayManagedDeviceId);
    assertThat(subscription.getAuthenticatedDeviceId()).isEqualTo(gw.getDeviceId());
    assertThat(subscription.getQos()).isEqualTo(qos);
    assertThat(subscription.isGatewaySubscriptionForSpecificDevice()).isEqualTo(true);
    // THEN the command topic does not include the tenant either
    assertThat(subscription.getCommandPublishTopic(command)).isEqualTo(String.format("%s//%s/%s/requestId/doSomething", endpointName, gatewayManagedDeviceId, reqPartName));
    // WHEN subscribing to commands for a specific device including the tenant
    mqttTopicSubscription = new MqttTopicSubscriptionImpl(String.format("%s/%s/%s/%s/#", endpointName, device.getTenantId(), gatewayManagedDeviceId, reqPartName), qos);
    subscription = CommandSubscription.fromTopic(mqttTopicSubscription, gw);
    assertThat(subscription).isNotNull();
    assertThat(subscription.getTenant()).isEqualTo(gw.getTenantId());
    assertThat(subscription.getDeviceId()).isEqualTo(gatewayManagedDeviceId);
    assertThat(subscription.getAuthenticatedDeviceId()).isEqualTo(gw.getDeviceId());
    assertThat(subscription.getQos()).isEqualTo(qos);
    assertThat(subscription.isGatewaySubscriptionForSpecificDevice()).isEqualTo(true);
    // THEN the command topic does include the tenant as well
    assertThat(subscription.getCommandPublishTopic(command)).isEqualTo(String.format("%s/%s/%s/%s/requestId/doSomething", endpointName, gw.getTenantId(), gatewayManagedDeviceId, reqPartName));
    // WHEN subscribing to commands for all devices omitting tenant
    mqttTopicSubscription = new MqttTopicSubscriptionImpl(String.format("%s//+/%s/#", endpointName, reqPartName), qos);
    subscription = CommandSubscription.fromTopic(mqttTopicSubscription, gw);
    assertThat(subscription).isNotNull();
    assertThat(subscription.getTenant()).isEqualTo(gw.getTenantId());
    assertThat(subscription.getDeviceId()).isEqualTo(gw.getDeviceId());
    assertThat(subscription.getAuthenticatedDeviceId()).isEqualTo(gw.getDeviceId());
    assertThat(subscription.getQos()).isEqualTo(qos);
    assertThat(subscription.isGatewaySubscriptionForSpecificDevice()).isEqualTo(false);
    // THEN the command topic does not include the tenant either
    assertThat(subscription.getCommandPublishTopic(command)).isEqualTo(String.format("%s//%s/%s/requestId/doSomething", endpointName, gatewayManagedDeviceId, reqPartName));
    // WHEN subscribing to commands for all devices including the tenant
    mqttTopicSubscription = new MqttTopicSubscriptionImpl(String.format("%s/%s/+/%s/#", endpointName, device.getTenantId(), reqPartName), qos);
    subscription = CommandSubscription.fromTopic(mqttTopicSubscription, gw);
    assertThat(subscription).isNotNull();
    assertThat(subscription.getTenant()).isEqualTo(gw.getTenantId());
    assertThat(subscription.getDeviceId()).isEqualTo(gw.getDeviceId());
    assertThat(subscription.getAuthenticatedDeviceId()).isEqualTo(gw.getDeviceId());
    assertThat(subscription.getQos()).isEqualTo(qos);
    assertThat(subscription.isGatewaySubscriptionForSpecificDevice()).isEqualTo(false);
    // THEN the command topic does include the tenant as well
    assertThat(subscription.getCommandPublishTopic(command)).isEqualTo(String.format("%s/%s/%s/%s/requestId/doSomething", endpointName, gw.getTenantId(), gatewayManagedDeviceId, reqPartName));
    // using a tenant other than the tenant that the gateway belongs to should fail
    mqttTopicSubscription = new MqttTopicSubscriptionImpl(String.format("%s/otherTenant/+/%s/#", endpointName, reqPartName), qos);
    assertThat(CommandSubscription.fromTopic(mqttTopicSubscription, gw)).isNull();
}
Also used : MqttTopicSubscriptionImpl(io.vertx.mqtt.impl.MqttTopicSubscriptionImpl) Command(org.eclipse.hono.client.command.Command) MqttTopicSubscription(io.vertx.mqtt.MqttTopicSubscription) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 20 with Command

use of org.eclipse.hono.client.command.Command in project hono by eclipse.

the class AbstractMappingAndDelegatingCommandHandler method mapAndDelegateIncomingCommand.

/**
 * Delegates an incoming command to the protocol adapter instance that the target
 * device is connected to.
 * <p>
 * Determines the target gateway (if applicable) and protocol adapter instance for an incoming command
 * and delegates the command to the resulting protocol adapter instance.
 *
 * @param commandContext The context of the command to send.
 * @param timer The timer indicating the amount of time used for processing the command message.
 * @return A future indicating the outcome of the operation.
 * @throws NullPointerException if any of the parameters are {@code null}.
 */
protected final Future<Void> mapAndDelegateIncomingCommand(final CommandContext commandContext, final Timer.Sample timer) {
    Objects.requireNonNull(commandContext);
    Objects.requireNonNull(timer);
    final Command command = commandContext.getCommand();
    // determine last used gateway device id
    if (log.isTraceEnabled()) {
        log.trace("determine command target gateway/adapter for [{}]", command);
    }
    final Future<TenantObject> tenantObjectFuture = tenantClient.get(command.getTenant(), commandContext.getTracingContext());
    return tenantObjectFuture.compose(tenantObject -> {
        TenantTraceSamplingHelper.applyTraceSamplingPriority(tenantObject, null, commandContext.getTracingSpan());
        commandContext.put(CommandContext.KEY_TENANT_CONFIG, tenantObject);
        // check whether the handler messaging type is equal to the messaging type of the tenant (if set)
        final MessagingType tenantMessagingType = Optional.ofNullable(tenantObject.getProperty(TenantConstants.FIELD_EXT, JsonObject.class)).map(ext -> ext.getString(TenantConstants.FIELD_EXT_MESSAGING_TYPE)).map(MessagingType::valueOf).orElse(null);
        if (tenantMessagingType != null && getMessagingType() != tenantMessagingType) {
            log.info("command received via {} but tenant is configured to use {} [{}]", getMessagingType(), tenantMessagingType, commandContext.getCommand());
            commandContext.getTracingSpan().log(String.format("command received via %s but tenant is configured to use %s", getMessagingType(), tenantMessagingType));
        }
        return commandTargetMapper.getTargetGatewayAndAdapterInstance(command.getTenant(), command.getDeviceId(), commandContext.getTracingContext());
    }).recover(cause -> {
        final Throwable error;
        if (tenantObjectFuture.failed() && ServiceInvocationException.extractStatusCode(cause) == HttpURLConnection.HTTP_NOT_FOUND) {
            error = new TenantDisabledOrNotRegisteredException(command.getTenant(), HttpURLConnection.HTTP_NOT_FOUND);
        } else if (cause instanceof DeviceDisabledOrNotRegisteredException) {
            error = cause;
        } else if (ServiceInvocationException.extractStatusCode(cause) == HttpURLConnection.HTTP_NOT_FOUND) {
            log.debug("no target adapter instance found for command with device id " + command.getDeviceId(), cause);
            error = new NoConsumerException("no target adapter instance found");
        } else {
            log.debug("error getting target gateway and adapter instance for command with device id " + command.getDeviceId(), cause);
            error = new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "error getting target gateway and adapter instance", cause);
        }
        if (error instanceof ClientErrorException) {
            commandContext.reject(error);
        } else {
            commandContext.release(error);
        }
        reportCommandProcessingError(command, tenantObjectFuture.result(), error, timer);
        return Future.failedFuture(cause);
    }).compose(result -> {
        final String targetAdapterInstanceId = result.getString(DeviceConnectionConstants.FIELD_ADAPTER_INSTANCE_ID);
        final String targetDeviceId = result.getString(DeviceConnectionConstants.FIELD_PAYLOAD_DEVICE_ID);
        final String targetGatewayId = targetDeviceId.equals(command.getDeviceId()) ? null : targetDeviceId;
        if (Objects.isNull(targetGatewayId)) {
            log.trace("determined target adapter instance [{}] for [{}] (command not mapped to gateway)", targetAdapterInstanceId, command);
        } else {
            command.setGatewayId(targetGatewayId);
            log.trace("determined target gateway [{}] and adapter instance [{}] for [{}]", targetGatewayId, targetAdapterInstanceId, command);
            commandContext.getTracingSpan().log("determined target gateway [" + targetGatewayId + "]");
        }
        return sendCommand(commandContext, targetAdapterInstanceId, tenantObjectFuture.result(), timer);
    });
}
Also used : HttpURLConnection(java.net.HttpURLConnection) InternalCommandSender(org.eclipse.hono.client.command.InternalCommandSender) Command(org.eclipse.hono.client.command.Command) TenantConstants(org.eclipse.hono.util.TenantConstants) Lifecycle(org.eclipse.hono.util.Lifecycle) LoggerFactory(org.slf4j.LoggerFactory) ClientErrorException(org.eclipse.hono.client.ClientErrorException) TenantDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.TenantDisabledOrNotRegisteredException) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) Tags(io.opentracing.tag.Tags) NoConsumerException(org.eclipse.hono.client.NoConsumerException) DeviceDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.DeviceDisabledOrNotRegisteredException) MessagingType(org.eclipse.hono.util.MessagingType) Timer(io.micrometer.core.instrument.Timer) JsonObject(io.vertx.core.json.JsonObject) TracingHelper(org.eclipse.hono.tracing.TracingHelper) Logger(org.slf4j.Logger) Tracer(io.opentracing.Tracer) DeviceConnectionConstants(org.eclipse.hono.util.DeviceConnectionConstants) CommandContext(org.eclipse.hono.client.command.CommandContext) MetricsTags(org.eclipse.hono.service.metric.MetricsTags) ServerErrorException(org.eclipse.hono.client.ServerErrorException) CommandTargetMapper(org.eclipse.hono.commandrouter.CommandTargetMapper) TenantClient(org.eclipse.hono.client.registry.TenantClient) Future(io.vertx.core.Future) TenantObject(org.eclipse.hono.util.TenantObject) SpanContext(io.opentracing.SpanContext) Objects(java.util.Objects) CommandRouterMetrics(org.eclipse.hono.commandrouter.CommandRouterMetrics) TenantTraceSamplingHelper(org.eclipse.hono.tracing.TenantTraceSamplingHelper) Optional(java.util.Optional) Span(io.opentracing.Span) TenantObject(org.eclipse.hono.util.TenantObject) DeviceDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.DeviceDisabledOrNotRegisteredException) Command(org.eclipse.hono.client.command.Command) NoConsumerException(org.eclipse.hono.client.NoConsumerException) MessagingType(org.eclipse.hono.util.MessagingType) ClientErrorException(org.eclipse.hono.client.ClientErrorException) TenantDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.TenantDisabledOrNotRegisteredException) ServerErrorException(org.eclipse.hono.client.ServerErrorException)

Aggregations

Command (org.eclipse.hono.client.command.Command)34 Span (io.opentracing.Span)23 Future (io.vertx.core.Future)23 HttpURLConnection (java.net.HttpURLConnection)22 ServerErrorException (org.eclipse.hono.client.ServerErrorException)22 CommandContext (org.eclipse.hono.client.command.CommandContext)22 Map (java.util.Map)19 Objects (java.util.Objects)19 Optional (java.util.Optional)19 Device (org.eclipse.hono.auth.Device)19 Constants (org.eclipse.hono.util.Constants)19 Buffer (io.vertx.core.buffer.Buffer)18 TracingHelper (org.eclipse.hono.tracing.TracingHelper)18 SpanContext (io.opentracing.SpanContext)17 Tags (io.opentracing.tag.Tags)17 Handler (io.vertx.core.Handler)17 ClientErrorException (org.eclipse.hono.client.ClientErrorException)17 MessageHelper (org.eclipse.hono.util.MessageHelper)17 TenantObject (org.eclipse.hono.util.TenantObject)17 List (java.util.List)16