private void setResponsePayload(final HttpServerResponse response, final CommandContext commandContext, final Span currentSpan) { if (commandContext == null) { response.setStatusCode(HttpURLConnection.HTTP_ACCEPTED); } else { final Command command = commandContext.getCommand(); response.putHeader(Constants.HEADER_COMMAND, command.getName()); currentSpan.setTag(Constants.HEADER_COMMAND, command.getName()); LOG.trace("adding command [name: {}, request-id: {}] to response for device [tenant-id: {}, device-id: {}]", command.getName(), command.getRequestId(), command.getTenant(), command.getDeviceId()); if (!command.isOneWay()) { response.putHeader(Constants.HEADER_COMMAND_REQUEST_ID, command.getRequestId()); currentSpan.setTag(Constants.HEADER_COMMAND_REQUEST_ID, command.getRequestId()); } response.setStatusCode(HttpURLConnection.HTTP_OK); HttpUtils.setResponseBody(response, command.getPayload(), command.getContentType()); } }
/** * Gets the request identifier of this command. * * @return The identifier. * @throws IllegalStateException if this command is invalid. */ public String getRequestId() { if (isValid()) { return requestId; } else { throw new IllegalStateException("command is invalid"); } }
@Override public String toString() { if (valid) { return String.format("Command [name: %s, tenant-id: %s, device-id %s, request-id: %s]", getName(), getTenant(), getDeviceId(), getRequestId()); } else { return "Invalid Command"; } } }
final String commandRequestId = (command.isOneWay() ? "" : command.getRequestId()); final String topic = String.format("%s/%s/%s/%s/%s/%s", subscription.getEndpoint(), tenantId, deviceId, subscription.getRequestPart(), commandRequestId, command.getName()); endpoint.publish(topic, command.getPayload(), qos, false, false); metrics.incrementCommandDeliveredToDevice(subscription.getTenant()); LOG.trace("command published to device [tenant-id: {}, device-id: {}, MQTT client-id: {}]",
(delivery, msg) -> { final Command command = Command.from(msg, tenantId, deviceId); if (command.isValid()) { TracingHelper.TAG_CORRELATION_ID.set(currentSpan, command.getCorrelationId()); items.put("reply-to", command.getCommandMessage().getReplyTo()); items.put("name", command.getName()); items.put("content-type", command.getContentType());
final Message msg = command.getCommandMessage(); if (msg.getCorrelationId() == null) { if (delivery.remotelySettled()) { if (Accepted.class.isInstance(remoteState)) { LOG.trace("device accepted command message [command: {}]", command.getName()); logItems.put(Fields.EVENT, "device accepted command"); commandContext.getCurrentSpan().log(logItems); } else if (Rejected.class.isInstance(remoteState)) { final ErrorCondition error = ((Rejected) remoteState).getError(); LOG.debug("device rejected command message [command: {}, error: {}]", command.getName(), error); logItems.put(Fields.EVENT, "device rejected command"); commandContext.getCurrentSpan().log(logItems); commandContext.reject(error, 1); } else if (Released.class.isInstance(remoteState)) { LOG.debug("device released command message [command: {}]", command.getName()); logItems.put(Fields.EVENT, "device released command"); commandContext.getCurrentSpan().log(logItems); LOG.debug("device did not settle command message [command: {}, remote state: {}]", command.getName(), remoteState.getClass().getSimpleName()); logItems.put(Fields.EVENT, "device did not settle command");
private Command( final boolean valid, final Message message, final String tenantId, final String deviceId, final String correlationId, final String replyToId) { this.valid = valid; this.message = message; this.tenantId = tenantId; this.deviceId = deviceId; this.correlationId = correlationId; this.replyToId = replyToId; this.requestId = getRequestId(correlationId, replyToId, deviceId); }
final String commandRequestId = (command.isOneWay() ? "" : command.getRequestId()); final String topic = String.format("%s/%s/%s/%s/%s/%s", subscription.getEndpoint(), tenantId, deviceId, subscription.getRequestPart(), commandRequestId, command.getName()); LOG.debug("Publishing command to device [tenant-id: {}, device-id: {}, MQTT client-id: {}, QoS: {}]", subscription.getTenant(), subscription.getDeviceId(), subscription.getClientId(), commandContext.getCurrentSpan().log(items); endpoint.publish(topic, command.getPayload(), subscription.getQos(), false, false, sentHandler -> { if (sentHandler.succeeded()) { if (MqttQoS.AT_LEAST_ONCE.equals(subscription.getQos())) {
private void setResponsePayload(final HttpServerResponse response, final CommandContext commandContext, final Span currentSpan) { if (commandContext == null) { response.setStatusCode(HttpURLConnection.HTTP_ACCEPTED); } else { final Command command = commandContext.getCommand(); response.putHeader(Constants.HEADER_COMMAND, command.getName()); currentSpan.setTag(Constants.HEADER_COMMAND, command.getName()); LOG.trace("adding command [name: {}, request-id: {}] to response for device [tenant-id: {}, device-id: {}]", command.getName(), command.getRequestId(), command.getTenant(), command.getDeviceId()); if (!command.isOneWay()) { response.putHeader(Constants.HEADER_COMMAND_REQUEST_ID, command.getRequestId()); currentSpan.setTag(Constants.HEADER_COMMAND_REQUEST_ID, command.getRequestId()); } response.setStatusCode(HttpURLConnection.HTTP_OK); HttpUtils.setResponseBody(response, command.getPayload(), command.getContentType()); } }
/** * Gets this command's reply-to-id. * * @return The identifier. * @throws IllegalStateException if this command is invalid. */ public String getReplyToId() { if (isValid()) { return replyToId; } else { throw new IllegalStateException("command is invalid"); } }
/** * Gets the ID to use for correlating a response to this command. * * @return The identifier. * @throws IllegalStateException if this command is invalid. */ public String getCorrelationId() { if (isValid()) { return correlationId; } else { throw new IllegalStateException("command is invalid"); } }
/** * Gets the tenant that the device belongs to. * * @return The tenant identifier. * @throws IllegalStateException if this command is invalid. */ public String getTenant() { if (isValid()) { return tenantId; } else { throw new IllegalStateException("command is invalid"); } }
/** * Gets the device's identifier. * * @return The identifier. * @throws IllegalStateException if this command is invalid. */ public String getDeviceId() { if (isValid()) { return deviceId; } else { throw new IllegalStateException("command is invalid"); } }
/** * Gets the payload of this command. * * @return The message payload or {@code null} if the command message contains no payload. * @throws IllegalStateException if this command is invalid. */ public Buffer getPayload() { if (isValid()) { return MessageHelper.getPayload(message); } else { throw new IllegalStateException("command is invalid"); } }
/** * Gets the name of this command. * * @return The name. * @throws IllegalStateException if this command is invalid. */ public String getName() { if (isValid()) { return message.getSubject(); } else { throw new IllegalStateException("command is invalid"); } }
/** * Gets the type of this command's payload. * * @return The content type or {@code null} if not set. * @throws IllegalStateException if this command is invalid. */ public String getContentType() { if (isValid()) { return message.getContentType(); } else { throw new IllegalStateException("command is invalid"); } }
/** * Gets the application properties of a message if any. * * @return The application properties. * @throws IllegalStateException if this command is invalid. */ public Map<String, Object> getApplicationProperties() { if (isValid()) { if (message.getApplicationProperties() == null) { return null; } return message.getApplicationProperties().getValue(); } else { throw new IllegalStateException("command is invalid"); } } /**
if (command.isValid()) { if (responseReady.isComplete()) {
if (command.isValid()) { if (responseReady.isComplete()) {
private Future<MessageConsumer> createCommandConsumer(final MqttEndpoint mqttEndpoint, final CommandSubscription sub, final CommandHandler<T> cmdHandler) { // if a device does not specify a keep alive in its CONNECT packet then // the default value of the CommandConnection will be used final long livenessCheckInterval = mqttEndpoint.keepAliveTimeSeconds() * 1000 / 2; return getCommandConnection().createCommandConsumer( sub.getTenant(), sub.getDeviceId(), commandContext -> { Tags.COMPONENT.set(commandContext.getCurrentSpan(), getTypeName()); final Command command = commandContext.getCommand(); if (command.isValid()) { onCommandReceived(mqttEndpoint, sub, commandContext, cmdHandler); } else { // issue credit so that application(s) can send the next command commandContext.reject(new ErrorCondition(Constants.AMQP_BAD_REQUEST, "malformed command message"), 1); } }, remoteClose -> {}, livenessCheckInterval); }